Adding bulk plot reffer to cached textblobs
This change will prevent the atlas from evicting glyphs the TextBlob
needs.
BUG=skia:
Committed: https://skia.googlesource.com/skia/+/7281c61e7bc689d484dcbda49be3cef4ce4f11c2
Review URL: https://codereview.chromium.org/1050113004
diff --git a/src/gpu/GrBatchAtlas.h b/src/gpu/GrBatchAtlas.h
index cd8123f..889d260 100644
--- a/src/gpu/GrBatchAtlas.h
+++ b/src/gpu/GrBatchAtlas.h
@@ -40,6 +40,9 @@
// 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 @@
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;
}