Light cleanup of GrTextBlob cache

* Remove unused methods
* GrTextBlobCache::makeBlob -> GrTextBlob::Make
* Fix up comments
* Move impl to .cpp

Change-Id: Ife4de04e709d3a6d212486f631bc67561957cdd6
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/291198
Commit-Queue: Herb Derby <herb@google.com>
Reviewed-by: Robert Phillips <robertphillips@google.com>
diff --git a/src/gpu/text/GrTextBlobCache.cpp b/src/gpu/text/GrTextBlobCache.cpp
index c3a6860..37489c6 100644
--- a/src/gpu/text/GrTextBlobCache.cpp
+++ b/src/gpu/text/GrTextBlobCache.cpp
@@ -9,15 +9,63 @@
 
 DECLARE_SKMESSAGEBUS_MESSAGE(GrTextBlobCache::PurgeBlobMessage)
 
+// This function is captured by the above macro using implementations from SkMessageBus.h
 static inline bool SkShouldPostMessageToBus(
         const GrTextBlobCache::PurgeBlobMessage& msg, uint32_t msgBusUniqueID) {
     return msg.fContextID == msgBusUniqueID;
 }
 
+GrTextBlobCache::GrTextBlobCache(GrTextBlobCache::PFOverBudgetCB cb, void* data, uint32_t uniqueID)
+        : fCallback(cb)
+        , fData(data)
+        , fSizeBudget(kDefaultBudget)
+        , fUniqueID(uniqueID)
+        , fPurgeBlobInbox(uniqueID) {
+    SkASSERT(cb != nullptr && data != nullptr);
+}
+
 GrTextBlobCache::~GrTextBlobCache() {
     this->freeAll();
 }
 
+sk_sp<GrTextBlob>
+GrTextBlobCache::makeCachedBlob(const SkGlyphRunList& glyphRunList, const GrTextBlob::Key& key,
+                                const SkMaskFilterBase::BlurRec& blurRec,
+                                const SkMatrix& viewMatrix, GrColor color, bool forceW) {
+    sk_sp<GrTextBlob> cacheBlob(GrTextBlob::Make(glyphRunList, viewMatrix, color, forceW));
+    cacheBlob->setupKey(key, blurRec, glyphRunList.paint());
+    this->add(cacheBlob);
+    glyphRunList.temporaryShuntBlobNotifyAddedToCache(fUniqueID);
+    return cacheBlob;
+}
+
+sk_sp<GrTextBlob> GrTextBlobCache::find(const GrTextBlob::Key& key) const {
+    const auto* idEntry = fBlobIDCache.find(key.fUniqueID);
+    return idEntry ? idEntry->find(key) : nullptr;
+}
+
+void GrTextBlobCache::remove(GrTextBlob* blob) {
+    auto  id      = GrTextBlob::GetKey(*blob).fUniqueID;
+    auto* idEntry = fBlobIDCache.find(id);
+    SkASSERT(idEntry);
+
+    fCurrentSize -= blob->size();
+    fBlobList.remove(blob);
+    idEntry->removeBlob(blob);
+    if (idEntry->fBlobs.empty()) {
+        fBlobIDCache.remove(id);
+    }
+}
+
+void GrTextBlobCache::makeMRU(GrTextBlob* blob) {
+    if (fBlobList.head() == blob) {
+        return;
+    }
+
+    fBlobList.remove(blob);
+    fBlobList.addToHead(blob);
+}
+
 void GrTextBlobCache::freeAll() {
     fBlobIDCache.foreach([this](uint32_t, BlobIDCacheEntry* entry) {
         for (const auto& blob : entry->fBlobs) {
@@ -33,6 +81,11 @@
     SkASSERT(fBlobList.isEmpty());
 }
 
+void GrTextBlobCache::setBudget(size_t budget) {
+    fSizeBudget = budget;
+    this->checkPurge();
+}
+
 void GrTextBlobCache::PostPurgeBlobMessage(uint32_t blobID, uint32_t cacheID) {
     SkASSERT(blobID != SK_InvalidGenID);
     SkMessageBus<PurgeBlobMessage>::Post(PurgeBlobMessage(blobID, cacheID));
@@ -66,8 +119,8 @@
 
     // If we are still over budget, then unref until we are below budget again
     if (fCurrentSize > fSizeBudget) {
-        BitmapBlobList::Iter iter;
-        iter.init(fBlobList, BitmapBlobList::Iter::kTail_IterStart);
+        TextBlobList::Iter iter;
+        iter.init(fBlobList, TextBlobList::Iter::kTail_IterStart);
         GrTextBlob* lruBlob = nullptr;
         while (fCurrentSize > fSizeBudget && (lruBlob = iter.get()) && lruBlob != blob) {
             // Backup the iterator before removing and unrefing the blob
@@ -83,13 +136,66 @@
             (*fCallback)(fData);
         }
 
-#ifdef SPEW_BUDGET_MESSAGE
+    #ifdef SPEW_BUDGET_MESSAGE
         if (fCurrentSize > fSizeBudget) {
             SkDebugf("Single textblob is larger than our whole budget");
         }
-#endif
+    #endif
     }
 }
 
+void GrTextBlobCache::add(sk_sp<GrTextBlob> blob) {
+    auto  id      = GrTextBlob::GetKey(*blob).fUniqueID;
+    auto* idEntry = fBlobIDCache.find(id);
+    if (!idEntry) {
+        idEntry = fBlobIDCache.set(id, BlobIDCacheEntry(id));
+    }
 
+    // Safe to retain a raw ptr temporarily here, because the cache will hold a ref.
+    GrTextBlob* rawBlobPtr = blob.get();
+    fBlobList.addToHead(rawBlobPtr);
+    fCurrentSize += blob->size();
+    idEntry->addBlob(std::move(blob));
 
+    this->checkPurge(rawBlobPtr);
+}
+
+GrTextBlobCache::BlobIDCacheEntry::BlobIDCacheEntry() : fID(SK_InvalidGenID) {}
+
+GrTextBlobCache::BlobIDCacheEntry::BlobIDCacheEntry(uint32_t id) : fID(id) {}
+
+uint32_t GrTextBlobCache::BlobIDCacheEntry::GetKey(const GrTextBlobCache::BlobIDCacheEntry& entry) {
+    return entry.fID;
+}
+
+void GrTextBlobCache::BlobIDCacheEntry::addBlob(sk_sp<GrTextBlob> blob) {
+    SkASSERT(blob);
+    SkASSERT(GrTextBlob::GetKey(*blob).fUniqueID == fID);
+    SkASSERT(!this->find(GrTextBlob::GetKey(*blob)));
+
+    fBlobs.emplace_back(std::move(blob));
+}
+
+void GrTextBlobCache::BlobIDCacheEntry::removeBlob(GrTextBlob* blob) {
+    SkASSERT(blob);
+    SkASSERT(GrTextBlob::GetKey(*blob).fUniqueID == fID);
+
+    auto index = this->findBlobIndex(GrTextBlob::GetKey(*blob));
+    SkASSERT(index >= 0);
+
+    fBlobs.removeShuffle(index);
+}
+
+sk_sp<GrTextBlob> GrTextBlobCache::BlobIDCacheEntry::find(const GrTextBlob::Key& key) const {
+    auto index = this->findBlobIndex(key);
+    return index < 0 ? nullptr : fBlobs[index];
+}
+
+int GrTextBlobCache::BlobIDCacheEntry::findBlobIndex(const GrTextBlob::Key& key) const {
+    for (int i = 0; i < fBlobs.count(); ++i) {
+        if (GrTextBlob::GetKey(*fBlobs[i]) == key) {
+            return i;
+        }
+    }
+    return -1;
+}