| Index: src/gpu/GrBatchAtlas.h
|
| diff --git a/src/gpu/GrBatchAtlas.h b/src/gpu/GrBatchAtlas.h
|
| index cd8123f140980fdb581ceb9789948098c85d7452..889d260a1809c52e8a4526b1954389ab93dcdf04 100644
|
| --- a/src/gpu/GrBatchAtlas.h
|
| +++ b/src/gpu/GrBatchAtlas.h
|
| @@ -40,6 +40,9 @@ public:
|
| // the containing GrPlot and absolute location in the backing texture.
|
| // NULL is returned if the subimage cannot fit in the atlas.
|
| // If provided, the image data will be written to the CPU-side backing bitmap.
|
| + // NOTE: If the client intends to refer to the atlas, they should immediately call 'setUseToken'
|
| + // with the currentToken from the batch target, otherwise the next call to addToAtlas might
|
| + // cause an eviction
|
| bool addToAtlas(AtlasID*, GrBatchTarget*, int width, int height, const void* image,
|
| SkIPoint16* loc);
|
|
|
| @@ -47,19 +50,74 @@ public:
|
|
|
| uint64_t atlasGeneration() const { return fAtlasGeneration; }
|
| bool hasID(AtlasID id);
|
| - void setLastRefToken(AtlasID id, BatchToken batchToken);
|
| +
|
| + // To ensure the atlas does not evict a given entry, the client must set the last use token
|
| + void setLastUseToken(AtlasID id, BatchToken batchToken);
|
| void registerEvictionCallback(EvictionFunc func, void* userData) {
|
| EvictionData* data = fEvictionCallbacks.append();
|
| data->fFunc = func;
|
| data->fData = userData;
|
| }
|
|
|
| + /*
|
| + * A class which can be handed back to GrBatchAtlas for updating in bulk last use tokens. The
|
| + * current max number of plots the GrBatchAtlas can handle is 32, if in the future this is
|
| + * insufficient then we can move to a 64 bit int
|
| + */
|
| + class BulkUseTokenUpdater {
|
| + public:
|
| + BulkUseTokenUpdater() : fPlotAlreadyUpdated(0), fCount(0), fAllocated(kMinItems) {}
|
| + void add(AtlasID id) {
|
| + int index = GrBatchAtlas::GetIndexFromID(id);
|
| + if (!this->find(index)) {
|
| + this->set(index);
|
| + }
|
| + }
|
| +
|
| + void reset() {
|
| + fPlotsToUpdate.reset(kMinItems);
|
| + fAllocated = kMinItems;
|
| + fCount = 0;
|
| + fPlotAlreadyUpdated = 0;
|
| + }
|
| +
|
| + private:
|
| + bool find(int index) const {
|
| + SkASSERT(index < kMaxPlots);
|
| + return (fPlotAlreadyUpdated >> index) & 1;
|
| + }
|
| +
|
| + void set(int index) {
|
| + SkASSERT(!this->find(index));
|
| + fPlotAlreadyUpdated = fPlotAlreadyUpdated | (1 << index);
|
| + if (fCount < fAllocated) {
|
| + fPlotsToUpdate[fCount++] = index;
|
| + } else {
|
| + // This case will almost never happen
|
| + fAllocated = fCount << 1;
|
| + fPlotsToUpdate.realloc(fAllocated);
|
| + fPlotsToUpdate[fCount++] = index;
|
| + }
|
| + }
|
| +
|
| + static const int kMinItems = 4;
|
| + static const int kMaxPlots = 32;
|
| + uint32_t fPlotAlreadyUpdated;
|
| + SkAutoSTMalloc<kMinItems, int> fPlotsToUpdate;
|
| + int fCount;
|
| + int fAllocated;
|
| +
|
| + friend class GrBatchAtlas;
|
| + };
|
| +
|
| + void setLastUseTokenBulk(const BulkUseTokenUpdater& reffer, BatchToken);
|
| +
|
| private:
|
| - int getIndexFromID(AtlasID id) {
|
| + static int GetIndexFromID(AtlasID id) {
|
| return id & 0xffff;
|
| }
|
|
|
| - int getGenerationFromID(AtlasID id) {
|
| + static int GetGenerationFromID(AtlasID id) {
|
| return (id >> 16) & 0xffff;
|
| }
|
|
|
|
|