make adding a text blob to GrTextBlobCache thread safe
Change-Id: I18d3b05e4913114e44905a6020baca90bf437320
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/375056
Commit-Queue: Herb Derby <herb@google.com>
Reviewed-by: Robert Phillips <robertphillips@google.com>
diff --git a/src/gpu/GrSurfaceDrawContext.cpp b/src/gpu/GrSurfaceDrawContext.cpp
index 3803946..51ee7eb 100644
--- a/src/gpu/GrSurfaceDrawContext.cpp
+++ b/src/gpu/GrSurfaceDrawContext.cpp
@@ -426,7 +426,9 @@
blob = GrTextBlob::Make(glyphRunList, drawMatrix);
if (canCache) {
blob->addKey(key);
- textBlobCache->add(glyphRunList, blob);
+ // The blob may already have been created on a different thread. Use the first one
+ // that was there.
+ blob = textBlobCache->addOrReturnExisting(glyphRunList, blob);
}
bool supportsSDFT = fContext->priv().caps()->shaderCaps()->supportsDistanceFieldText();
diff --git a/src/gpu/text/GrTextBlobCache.cpp b/src/gpu/text/GrTextBlobCache.cpp
index 815a775..baee93ee2 100644
--- a/src/gpu/text/GrTextBlobCache.cpp
+++ b/src/gpu/text/GrTextBlobCache.cpp
@@ -20,10 +20,12 @@
, fMessageBusID(messageBusID)
, fPurgeBlobInbox(messageBusID) { }
-void GrTextBlobCache::add(const SkGlyphRunList& glyphRunList, sk_sp<GrTextBlob> blob) {
+sk_sp<GrTextBlob> GrTextBlobCache::addOrReturnExisting(
+ const SkGlyphRunList& glyphRunList, sk_sp<GrTextBlob> blob) {
SkAutoSpinlock lock{fSpinLock};
- this->internalAdd(std::move(blob));
+ blob = this->internalAdd(std::move(blob));
glyphRunList.temporaryShuntBlobNotifyAddedToCache(fMessageBusID);
+ return blob;
}
sk_sp<GrTextBlob> GrTextBlobCache::find(const GrTextBlob::Key& key) {
@@ -133,20 +135,23 @@
}
}
-void GrTextBlobCache::internalAdd(sk_sp<GrTextBlob> blob) {
+sk_sp<GrTextBlob> GrTextBlobCache::internalAdd(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));
+ if (sk_sp<GrTextBlob> alreadyIn = idEntry->find(GrTextBlob::GetKey(*blob)); alreadyIn) {
+ blob = std::move(alreadyIn);
+ } else {
+ fBlobList.addToHead(blob.get());
+ fCurrentSize += blob->size();
+ idEntry->addBlob(blob);
+ }
- this->internalCheckPurge(rawBlobPtr);
+ this->internalCheckPurge(blob.get());
+ return blob;
}
GrTextBlobCache::BlobIDCacheEntry::BlobIDCacheEntry() : fID(SK_InvalidGenID) {}
diff --git a/src/gpu/text/GrTextBlobCache.h b/src/gpu/text/GrTextBlobCache.h
index c973384..8e86092d 100644
--- a/src/gpu/text/GrTextBlobCache.h
+++ b/src/gpu/text/GrTextBlobCache.h
@@ -22,8 +22,9 @@
public:
GrTextBlobCache(uint32_t messageBusID);
- void add(const SkGlyphRunList& glyphRunList,
- sk_sp<GrTextBlob> blob) SK_EXCLUDES(fSpinLock);
+ // If not already in the cache, then add it else, return the text blob from the cache.
+ sk_sp<GrTextBlob> addOrReturnExisting(
+ const SkGlyphRunList& glyphRunList, sk_sp<GrTextBlob> blob) SK_EXCLUDES(fSpinLock);
sk_sp<GrTextBlob> find(const GrTextBlob::Key& key) SK_EXCLUDES(fSpinLock);
@@ -73,7 +74,7 @@
void internalPurgeStaleBlobs() SK_REQUIRES(fSpinLock);
- void internalAdd(sk_sp<GrTextBlob> blob) SK_REQUIRES(fSpinLock);
+ sk_sp<GrTextBlob> internalAdd(sk_sp<GrTextBlob> blob) SK_REQUIRES(fSpinLock);
void internalRemove(GrTextBlob* blob) SK_REQUIRES(fSpinLock);
void internalCheckPurge(GrTextBlob* blob = nullptr) SK_REQUIRES(fSpinLock);