blob: e84667b5ea02cec6b8ca4e2cb9b75c84a896da24 [file] [log] [blame]
robertphillipse51fa4a2015-11-03 07:04:47 -08001
2/*
3 * Copyright 2010 Google Inc.
4 *
5 * Use of this source code is governed by a BSD-style license that can be
6 * found in the LICENSE file.
7 */
8
9#ifndef GrLayerAtlas_DEFINED
10#define GrLayerAtlas_DEFINED
11
robertphillips60029a52015-11-09 13:51:06 -080012#include "GrTexture.h"
robertphillipse51fa4a2015-11-03 07:04:47 -080013
14#include "SkPoint.h"
robertphillipse51fa4a2015-11-03 07:04:47 -080015#include "SkTDArray.h"
16#include "SkTInternalLList.h"
17
18class GrLayerAtlas;
robertphillipse51fa4a2015-11-03 07:04:47 -080019class GrTextureProvider;
20class GrRectanizer;
21
22// The backing GrTexture for a GrLayerAtlas is broken into a spatial grid of Plots. When
23// the atlas needs space on the texture (i.e., in response to an addToAtlas call), it
24// iterates through the plots in use by the requesting client looking for space and,
25// if no space is found, opens up a new Plot for that client. The Plots keep track of
26// subimage placement via their GrRectanizer.
27//
28// If all Plots are full, the replacement strategy is up to the client. The Plot::reset
29// call will remove a Plot's knowledge of any allocated rects - freeing its space for reuse.
30
31class GrLayerAtlas {
32public:
33 class Plot {
34 SK_DECLARE_INTERNAL_LLIST_INTERFACE(Plot); // In an MRU llist
35
36 public:
37 // This returns a plot ID unique to each plot in the atlas. They are
38 // consecutive and start at 0.
39 int id() const { return fID; }
40
41 void reset();
42
43 private:
44 friend class GrLayerAtlas;
45
46 Plot();
47 ~Plot(); // does not try to delete the fNext field
48
49 void init(int id, int offX, int offY, int width, int height);
50
51 bool allocateRect(int width, int height, SkIPoint16*);
52
53 int fID;
54 GrRectanizer* fRects;
55 SkIPoint16 fOffset; // the offset of the plot in the backing texture
56 };
57
58 // This class allows each client to independently track the Plots in
59 // which its data is stored.
60 // For example, multiple pictures may simultaneously store their layers in the
61 // layer atlas. When a picture goes away it can use the ClientPlotUsage to remove itself
62 // from those plots.
63 class ClientPlotUsage {
64 public:
65 ClientPlotUsage(int maxPlots)
66 SkDEBUGCODE(: fMaxPlots(maxPlots)) {
67 fPlots.setReserve(maxPlots);
68 }
69
70 bool isEmpty() const { return 0 == fPlots.count(); }
71
72 int numPlots() const { return fPlots.count(); }
73 Plot* plot(int index) { return fPlots[index]; }
74
75 void appendPlot(Plot* plot) {
76 SkASSERT(fPlots.count() <= fMaxPlots);
77 SkASSERT(!fPlots.contains(plot));
78 *fPlots.append() = plot;
79 }
80
81 // remove reference to 'plot'
82 void removePlot(const Plot* plot) {
83 int index = fPlots.find(const_cast<Plot*>(plot));
84 if (index >= 0) {
85 fPlots.remove(index);
86 }
87 }
88
89#ifdef SK_DEBUG
90 bool contains(const Plot* plot) const {
91 return fPlots.contains(const_cast<Plot*>(plot));
92 }
93#endif
94
95 private:
96 SkTDArray<Plot*> fPlots;
97 SkDEBUGCODE(int fMaxPlots;)
98 };
99
100 GrLayerAtlas(GrTextureProvider*, GrPixelConfig, GrSurfaceFlags flags,
101 const SkISize& backingTextureSize,
102 int numPlotsX, int numPlotsY);
103 ~GrLayerAtlas();
104
105 // Requests a width x height block in the atlas. Upon success it returns
106 // the containing Plot and absolute location in the backing texture.
107 // nullptr is returned if there is no more space in the atlas.
108 Plot* addToAtlas(ClientPlotUsage*, int width, int height, SkIPoint16* loc);
109
robertphillips60029a52015-11-09 13:51:06 -0800110 GrTexture* getTextureOrNull() const {
robertphillips42597bc2015-11-06 04:14:55 -0800111 return fTexture;
112 }
113
robertphillips60029a52015-11-09 13:51:06 -0800114 GrTexture* getTexture() const {
115 SkASSERT(fTexture);
116 return fTexture;
117 }
118
119 bool reattachBackingTexture();
120
121 void detachBackingTexture() {
122 fTexture.reset(nullptr);
123 }
124
125 void resetPlots();
126
robertphillipse51fa4a2015-11-03 07:04:47 -0800127 enum IterOrder {
128 kLRUFirst_IterOrder,
129 kMRUFirst_IterOrder
130 };
131
132 typedef SkTInternalLList<Plot> PlotList;
133 typedef PlotList::Iter PlotIter;
134 Plot* iterInit(PlotIter* iter, IterOrder order) {
135 return iter->init(fPlotList, kLRUFirst_IterOrder == order
136 ? PlotList::Iter::kTail_IterStart
137 : PlotList::Iter::kHead_IterStart);
138 }
139
140private:
robertphillips60029a52015-11-09 13:51:06 -0800141 void createBackingTexture();
142
robertphillipse51fa4a2015-11-03 07:04:47 -0800143 void makeMRU(Plot* plot);
144
145 GrTextureProvider* fTexProvider;
146 GrPixelConfig fPixelConfig;
147 GrSurfaceFlags fFlags;
robertphillips60029a52015-11-09 13:51:06 -0800148 SkAutoTUnref<GrTexture> fTexture;
robertphillipse51fa4a2015-11-03 07:04:47 -0800149
150 SkISize fBackingTextureSize;
151
152 // allocated array of Plots
153 Plot* fPlotArray;
154 // LRU list of Plots (MRU at head - LRU at tail)
155 PlotList fPlotList;
156};
157
158#endif