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 GrAtlas_DEFINED 10 #define GrAtlas_DEFINED 11 12 13 #include "GrTexture.h" 14 #include "GrDrawTarget.h" 15 #include "SkPoint.h" 16 #include "SkTInternalLList.h" 17 18 class GrGpu; 19 class GrRectanizer; 20 class GrAtlas; 21 22 // The backing GrTexture for a set of GrAtlases is broken into a spatial grid of GrPlots. When 23 // a GrAtlas needs space on the texture, it requests a GrPlot. Each GrAtlas can claim one 24 // or more GrPlots. The GrPlots keep track of subimage placement via their GrRectanizer. Once a 25 // GrPlot is "full" (i.e. there is no room for the new subimage according to the GrRectanizer), the 26 // GrAtlas can request a new GrPlot via GrAtlas::addToAtlas(). 27 // 28 // If all GrPlots are allocated, the replacement strategy is up to the client. The drawToken is 29 // available to ensure that all draw calls are finished for that particular GrPlot. 30 // GrAtlas::removeUnusedPlots() will free up any finished plots for a given GrAtlas. 31 32 class GrPlot { 33 public: 34 SK_DECLARE_INTERNAL_LLIST_INTERFACE(GrPlot); 35 36 // This returns a plot ID unique to each plot in a given GrAtlas. They are 37 // consecutive and start at 0. id()38 int id() const { return fID; } 39 texture()40 GrTexture* texture() const { return fTexture; } 41 42 bool addSubImage(int width, int height, const void*, SkIPoint16*); 43 drawToken()44 GrDrawTarget::DrawToken drawToken() const { return fDrawToken; } setDrawToken(GrDrawTarget::DrawToken draw)45 void setDrawToken(GrDrawTarget::DrawToken draw) { fDrawToken = draw; } 46 47 void uploadToTexture(); 48 49 void resetRects(); 50 51 private: 52 GrPlot(); 53 ~GrPlot(); // does not try to delete the fNext field 54 void init(GrAtlas* atlas, int id, int offX, int offY, int width, int height, size_t bpp, 55 bool batchUploads); 56 57 // for recycling 58 GrDrawTarget::DrawToken fDrawToken; 59 60 int fID; 61 unsigned char* fPlotData; 62 GrTexture* fTexture; 63 GrRectanizer* fRects; 64 GrAtlas* fAtlas; 65 SkIPoint16 fOffset; // the offset of the plot in the backing texture 66 size_t fBytesPerPixel; 67 SkIRect fDirtyRect; 68 bool fDirty; 69 bool fBatchUploads; 70 71 friend class GrAtlas; 72 }; 73 74 typedef SkTInternalLList<GrPlot> GrPlotList; 75 76 class GrAtlas { 77 public: 78 // This class allows each client to independently track the GrPlots in 79 // which its data is stored. 80 class ClientPlotUsage { 81 public: isEmpty()82 bool isEmpty() const { return 0 == fPlots.count(); } 83 84 #ifdef SK_DEBUG contains(const GrPlot * plot)85 bool contains(const GrPlot* plot) const { 86 return fPlots.contains(const_cast<GrPlot*>(plot)); 87 } 88 #endif 89 90 private: 91 SkTDArray<GrPlot*> fPlots; 92 93 friend class GrAtlas; 94 }; 95 96 GrAtlas(GrGpu*, GrPixelConfig, GrSurfaceFlags flags, 97 const SkISize& backingTextureSize, 98 int numPlotsX, int numPlotsY, bool batchUploads); 99 ~GrAtlas(); 100 101 // Adds a width x height subimage to the atlas. Upon success it returns 102 // the containing GrPlot and absolute location in the backing texture. 103 // NULL is returned if the subimage cannot fit in the atlas. 104 // If provided, the image data will either be immediately uploaded or 105 // written to the CPU-side backing bitmap. 106 GrPlot* addToAtlas(ClientPlotUsage*, int width, int height, const void* image, SkIPoint16* loc); 107 108 // remove reference to this plot 109 static void RemovePlot(ClientPlotUsage* usage, const GrPlot* plot); 110 111 // get a plot that's not being used by the current draw 112 // this allows us to overwrite this plot without flushing 113 GrPlot* getUnusedPlot(); 114 getTexture()115 GrTexture* getTexture() const { 116 return fTexture; 117 } 118 119 void uploadPlotsToTexture(); 120 121 enum IterOrder { 122 kLRUFirst_IterOrder, 123 kMRUFirst_IterOrder 124 }; 125 126 typedef GrPlotList::Iter PlotIter; iterInit(PlotIter * iter,IterOrder order)127 GrPlot* iterInit(PlotIter* iter, IterOrder order) { 128 return iter->init(fPlotList, kLRUFirst_IterOrder == order 129 ? GrPlotList::Iter::kTail_IterStart 130 : GrPlotList::Iter::kHead_IterStart); 131 } 132 133 private: 134 void makeMRU(GrPlot* plot); 135 136 GrGpu* fGpu; 137 GrPixelConfig fPixelConfig; 138 GrSurfaceFlags fFlags; 139 GrTexture* fTexture; 140 SkISize fBackingTextureSize; 141 int fNumPlotsX; 142 int fNumPlotsY; 143 bool fBatchUploads; 144 145 // allocated array of GrPlots 146 GrPlot* fPlotArray; 147 // LRU list of GrPlots (MRU at head - LRU at tail) 148 GrPlotList fPlotList; 149 }; 150 151 #endif 152