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