1 /* 2 * Copyright 2015 Google Inc. 3 * 4 * Use of this source code is governed by a BSD-style license that can be 5 * found in the LICENSE file. 6 */ 7 8 #ifndef GrBatchAtlas_DEFINED 9 #define GrBatchAtlas_DEFINED 10 11 #include "GrTexture.h" 12 #include "SkPoint.h" 13 #include "SkTDArray.h" 14 #include "SkTInternalLList.h" 15 16 class BatchPlot; 17 class GrBatchTarget; 18 class GrRectanizer; 19 20 typedef SkTInternalLList<BatchPlot> GrBatchPlotList; 21 22 class GrBatchAtlas { 23 public: 24 typedef uint64_t BatchToken; 25 // An AtlasID is an opaque handle which callers can use to determine if the atlas contains 26 // a specific piece of data 27 typedef uint32_t AtlasID; 28 static const uint32_t kInvalidAtlasID = 0; 29 static const uint64_t kInvalidAtlasGeneration = 0; 30 31 // A function pointer for use as a callback during eviction. Whenever GrBatchAtlas evicts a 32 // specific AtlasID, it will call all of the registered listeners so they can optionally process 33 // the eviction 34 typedef void (*EvictionFunc)(GrBatchAtlas::AtlasID, void*); 35 36 GrBatchAtlas(GrTexture*, int numPlotsX, int numPlotsY); 37 ~GrBatchAtlas(); 38 39 // Adds a width x height subimage to the atlas. Upon success it returns 40 // the containing GrPlot and absolute location in the backing texture. 41 // NULL is returned if the subimage cannot fit in the atlas. 42 // If provided, the image data will be written to the CPU-side backing bitmap. 43 // NOTE: If the client intends to refer to the atlas, they should immediately call 'setUseToken' 44 // with the currentToken from the batch target, otherwise the next call to addToAtlas might 45 // cause an eviction 46 bool addToAtlas(AtlasID*, GrBatchTarget*, int width, int height, const void* image, 47 SkIPoint16* loc); 48 getTexture()49 GrTexture* getTexture() const { return fTexture; } 50 atlasGeneration()51 uint64_t atlasGeneration() const { return fAtlasGeneration; } 52 bool hasID(AtlasID id); 53 54 // To ensure the atlas does not evict a given entry, the client must set the last use token 55 void setLastUseToken(AtlasID id, BatchToken batchToken); registerEvictionCallback(EvictionFunc func,void * userData)56 void registerEvictionCallback(EvictionFunc func, void* userData) { 57 EvictionData* data = fEvictionCallbacks.append(); 58 data->fFunc = func; 59 data->fData = userData; 60 } 61 62 /* 63 * A class which can be handed back to GrBatchAtlas for updating in bulk last use tokens. The 64 * current max number of plots the GrBatchAtlas can handle is 32, if in the future this is 65 * insufficient then we can move to a 64 bit int 66 */ 67 class BulkUseTokenUpdater { 68 public: BulkUseTokenUpdater()69 BulkUseTokenUpdater() : fPlotAlreadyUpdated(0) {} add(AtlasID id)70 void add(AtlasID id) { 71 int index = GrBatchAtlas::GetIndexFromID(id); 72 if (!this->find(index)) { 73 this->set(index); 74 } 75 } 76 reset()77 void reset() { 78 fPlotsToUpdate.reset(); 79 fPlotAlreadyUpdated = 0; 80 } 81 82 private: find(int index)83 bool find(int index) const { 84 SkASSERT(index < kMaxPlots); 85 return (fPlotAlreadyUpdated >> index) & 1; 86 } 87 set(int index)88 void set(int index) { 89 SkASSERT(!this->find(index)); 90 fPlotAlreadyUpdated = fPlotAlreadyUpdated | (1 << index); 91 fPlotsToUpdate.push_back(index); 92 } 93 94 static const int kMinItems = 4; 95 static const int kMaxPlots = 32; 96 SkSTArray<kMinItems, int, true> fPlotsToUpdate; 97 uint32_t fPlotAlreadyUpdated; 98 99 friend class GrBatchAtlas; 100 }; 101 102 void setLastUseTokenBulk(const BulkUseTokenUpdater& reffer, BatchToken); 103 104 static const int kGlyphMaxDim = 256; GlyphTooLargeForAtlas(int width,int height)105 static bool GlyphTooLargeForAtlas(int width, int height) { 106 return width > kGlyphMaxDim || height > kGlyphMaxDim; 107 } 108 109 private: GetIndexFromID(AtlasID id)110 static int GetIndexFromID(AtlasID id) { 111 return id & 0xffff; 112 } 113 GetGenerationFromID(AtlasID id)114 static int GetGenerationFromID(AtlasID id) { 115 return (id >> 16) & 0xffff; 116 } 117 118 inline void updatePlot(GrBatchTarget*, AtlasID*, BatchPlot*); 119 120 inline void makeMRU(BatchPlot* plot); 121 122 inline void processEviction(AtlasID); 123 124 GrTexture* fTexture; 125 int fNumPlotsX; 126 int fNumPlotsY; 127 int fPlotWidth; 128 int fPlotHeight; 129 size_t fBPP; 130 uint64_t fAtlasGeneration; 131 132 struct EvictionData { 133 EvictionFunc fFunc; 134 void* fData; 135 }; 136 137 SkTDArray<EvictionData> fEvictionCallbacks; 138 // allocated array of GrBatchPlots 139 SkAutoTUnref<BatchPlot>* fPlotArray; 140 // LRU list of GrPlots (MRU at head - LRU at tail) 141 GrBatchPlotList fPlotList; 142 }; 143 144 #endif 145