| Index: src/gpu/GrBatchAtlas.h
|
| diff --git a/src/gpu/GrBatchAtlas.h b/src/gpu/GrBatchAtlas.h
|
| index 0f36951922f47558ea10a2282fa1d8ba38b77645..bd6504030bb8f54fbda7dd21d9111069fcd4ad53 100644
|
| --- a/src/gpu/GrBatchAtlas.h
|
| +++ b/src/gpu/GrBatchAtlas.h
|
| @@ -14,7 +14,6 @@
|
| #include "SkTDArray.h"
|
| #include "SkTInternalLList.h"
|
|
|
| -class BatchPlot;
|
| class GrRectanizer;
|
|
|
| struct GrBatchAtlasConfig {
|
| @@ -55,11 +54,23 @@ public:
|
| GrTexture* getTexture() const { return fTexture; }
|
|
|
| uint64_t atlasGeneration() const { return fAtlasGeneration; }
|
| - bool hasID(AtlasID id);
|
| +
|
| + inline bool hasID(AtlasID id) {
|
| + uint32_t index = GetIndexFromID(id);
|
| + SkASSERT(index < fNumPlots);
|
| + return fPlotArray[index]->genID() == GetGenerationFromID(id);
|
| + }
|
|
|
| // To ensure the atlas does not evict a given entry, the client must set the last use token
|
| - void setLastUseToken(AtlasID id, GrBatchToken batchToken);
|
| - void registerEvictionCallback(EvictionFunc func, void* userData) {
|
| + inline void setLastUseToken(AtlasID id, GrBatchToken batchToken) {
|
| + SkASSERT(this->hasID(id));
|
| + uint32_t index = GetIndexFromID(id);
|
| + SkASSERT(index < fNumPlots);
|
| + this->makeMRU(fPlotArray[index]);
|
| + fPlotArray[index]->setLastUseToken(batchToken);
|
| + }
|
| +
|
| + inline void registerEvictionCallback(EvictionFunc func, void* userData) {
|
| EvictionData* data = fEvictionCallbacks.append();
|
| data->fFunc = func;
|
| data->fData = userData;
|
| @@ -110,7 +121,14 @@ public:
|
| friend class GrBatchAtlas;
|
| };
|
|
|
| - void setLastUseTokenBulk(const BulkUseTokenUpdater& reffer, GrBatchToken);
|
| + void setLastUseTokenBulk(const BulkUseTokenUpdater& updater, GrBatchToken batchToken) {
|
| + int count = updater.fPlotsToUpdate.count();
|
| + for (int i = 0; i < count; i++) {
|
| + BatchPlot* plot = fPlotArray[updater.fPlotsToUpdate[i]];
|
| + this->makeMRU(plot);
|
| + plot->setLastUseToken(batchToken);
|
| + }
|
| + }
|
|
|
| static const int kGlyphMaxDim = 256;
|
| static bool GlyphTooLargeForAtlas(int width, int height) {
|
| @@ -118,6 +136,89 @@ public:
|
| }
|
|
|
| private:
|
| + // The backing GrTexture for a GrBatchAtlas is broken into a spatial grid of BatchPlots.
|
| + // The BatchPlots keep track of subimage placement via their GrRectanizer. A BatchPlot
|
| + // manages the lifetime of its data using two tokens, a last use token and a last upload token.
|
| + // Once a BatchPlot is "full" (i.e. there is no room for the new subimage according to the
|
| + // GrRectanizer), it can no longer be used unless the last use of the GrPlot has already been
|
| + // flushed through to the gpu.
|
| + class BatchPlot : public SkRefCnt {
|
| + SK_DECLARE_INTERNAL_LLIST_INTERFACE(BatchPlot);
|
| +
|
| + public:
|
| + // index() is a unique id for the plot relative to the owning GrAtlas. genID() is a
|
| + // monotonically incremented number which is bumped every time this plot is
|
| + // evicted from the cache (i.e., there is continuity in genID() across atlas spills).
|
| + uint32_t index() const { return fIndex; }
|
| + uint64_t genID() const { return fGenID; }
|
| + GrBatchAtlas::AtlasID id() const {
|
| + SkASSERT(GrBatchAtlas::kInvalidAtlasID != fID);
|
| + return fID;
|
| + }
|
| + SkDEBUGCODE(size_t bpp() const { return fBytesPerPixel; })
|
| +
|
| + bool addSubImage(int width, int height, const void* image, SkIPoint16* loc);
|
| +
|
| + // To manage the lifetime of a plot, we use two tokens. We use the last upload token to
|
| + // know when we can 'piggy back' uploads, ie if the last upload hasn't been flushed to gpu,
|
| + // we don't need to issue a new upload even if we update the cpu backing store. We use
|
| + // lastUse to determine when we can evict a plot from the cache, ie if the last use has
|
| + // already flushed through the gpu then we can reuse the plot.
|
| + GrBatchToken lastUploadToken() const { return fLastUpload; }
|
| + GrBatchToken lastUseToken() const { return fLastUse; }
|
| + void setLastUploadToken(GrBatchToken batchToken) {
|
| + SkASSERT(batchToken >= fLastUpload);
|
| + fLastUpload = batchToken;
|
| + }
|
| + void setLastUseToken(GrBatchToken batchToken) {
|
| + SkASSERT(batchToken >= fLastUse);
|
| + fLastUse = batchToken;
|
| + }
|
| +
|
| + void uploadToTexture(GrBatchUploader::TextureUploader* uploader, GrTexture* texture);
|
| + void resetRects();
|
| +
|
| + private:
|
| + BatchPlot(int index, uint64_t genID, int offX, int offY, int width, int height,
|
| + GrPixelConfig config);
|
| +
|
| + ~BatchPlot() override;
|
| +
|
| + // Create a clone of this plot. The cloned plot will take the place of the
|
| + // current plot in the atlas.
|
| + BatchPlot* clone() const {
|
| + return new BatchPlot(fIndex, fGenID+1, fX, fY, fWidth, fHeight, fConfig);
|
| + }
|
| +
|
| + static GrBatchAtlas::AtlasID CreateId(uint32_t index, uint64_t generation) {
|
| + SkASSERT(index < (1 << 16));
|
| + SkASSERT(generation < ((uint64_t)1 << 48));
|
| + return generation << 16 | index;
|
| + }
|
| +
|
| + GrBatchToken fLastUpload;
|
| + GrBatchToken fLastUse;
|
| +
|
| + const uint32_t fIndex;
|
| + uint64_t fGenID;
|
| + GrBatchAtlas::AtlasID fID;
|
| + unsigned char* fData;
|
| + const int fWidth;
|
| + const int fHeight;
|
| + const int fX;
|
| + const int fY;
|
| + GrRectanizer* fRects;
|
| + const SkIPoint16 fOffset; // the offset of the plot in the backing texture
|
| + const GrPixelConfig fConfig;
|
| + const size_t fBytesPerPixel;
|
| + SkIRect fDirtyRect;
|
| + SkDEBUGCODE(bool fDirty;)
|
| +
|
| + friend class GrBatchAtlas;
|
| +
|
| + typedef SkRefCnt INHERITED;
|
| + };
|
| +
|
| typedef SkTInternalLList<BatchPlot> GrBatchPlotList;
|
|
|
| static uint32_t GetIndexFromID(AtlasID id) {
|
| @@ -131,10 +232,19 @@ private:
|
|
|
| inline void updatePlot(GrDrawBatch::Target*, AtlasID*, BatchPlot*);
|
|
|
| - inline void makeMRU(BatchPlot* plot);
|
| + inline void makeMRU(BatchPlot* plot) {
|
| + if (fPlotList.head() == plot) {
|
| + return;
|
| + }
|
| +
|
| + fPlotList.remove(plot);
|
| + fPlotList.addToHead(plot);
|
| + }
|
|
|
| inline void processEviction(AtlasID);
|
|
|
| + friend class GrPlotUploader; // to access GrBatchPlot
|
| +
|
| GrTexture* fTexture;
|
| SkDEBUGCODE(uint32_t fNumPlots;)
|
|
|
|
|