• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 
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 
12 #include "GrTexture.h"
13 
14 #include "SkPoint.h"
15 #include "SkTDArray.h"
16 #include "SkTInternalLList.h"
17 
18 class GrLayerAtlas;
19 class GrTextureProvider;
20 class 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 
31 class GrLayerAtlas {
32 public:
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.
id()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:
ClientPlotUsage(int maxPlots)65         ClientPlotUsage(int maxPlots)
66             SkDEBUGCODE(: fMaxPlots(maxPlots)) {
67             fPlots.setReserve(maxPlots);
68         }
69 
isEmpty()70         bool isEmpty() const { return 0 == fPlots.count(); }
71 
numPlots()72         int numPlots() const { return fPlots.count(); }
plot(int index)73         Plot* plot(int index) { return fPlots[index]; }
74 
appendPlot(Plot * plot)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'
removePlot(const Plot * 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
contains(const Plot * plot)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 
getTextureOrNull()110     GrTexture* getTextureOrNull() const {
111         return fTexture;
112     }
113 
getTexture()114     GrTexture* getTexture() const {
115         SkASSERT(fTexture);
116         return fTexture;
117     }
118 
119     bool reattachBackingTexture();
120 
detachBackingTexture()121     void detachBackingTexture() {
122         fTexture.reset(nullptr);
123     }
124 
125     void resetPlots();
126 
127     enum IterOrder {
128         kLRUFirst_IterOrder,
129         kMRUFirst_IterOrder
130     };
131 
132     typedef SkTInternalLList<Plot> PlotList;
133     typedef PlotList::Iter PlotIter;
iterInit(PlotIter * iter,IterOrder order)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 
140 private:
141     void createBackingTexture();
142 
143     void makeMRU(Plot* plot);
144 
145     GrTextureProvider* fTexProvider;
146     GrPixelConfig      fPixelConfig;
147     GrSurfaceFlags     fFlags;
148     SkAutoTUnref<GrTexture> fTexture;
149 
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
159