ccpr: Recycle cache entries when possible to avoid malloc
Bug: skia:
Change-Id: Id06098f66ad6399c11707f8380597e7eeb392eec
Reviewed-on: https://skia-review.googlesource.com/138441
Commit-Queue: Chris Dalton <csmartdalton@google.com>
Reviewed-by: Robert Phillips <robertphillips@google.com>
diff --git a/src/gpu/ccpr/GrCCPathCache.cpp b/src/gpu/ccpr/GrCCPathCache.cpp
index b6eb82a..b22b1dd 100644
--- a/src/gpu/ccpr/GrCCPathCache.cpp
+++ b/src/gpu/ccpr/GrCCPathCache.cpp
@@ -78,19 +78,6 @@
SkASSERT(fEntry->fCacheWeakPtr);
fEntry->fCacheWeakPtr->fLRU.remove(fEntry);
fEntry->fCacheWeakPtr = nullptr;
-
- if (GrCCAtlas::CachedAtlasInfo* info = fEntry->fCachedAtlasInfo.get()) {
- // Mark our own pixels invalid in the cached atlas texture now that we have been evicted.
- info->fNumInvalidatedPathPixels += fEntry->height() * fEntry->width();
- if (!info->fIsPurgedFromResourceCache &&
- info->fNumInvalidatedPathPixels >= info->fNumPathPixels / 2) {
- // Too many invalidated pixels: purge the atlas texture from the resource cache.
- SkMessageBus<GrUniqueKeyInvalidatedMessage>::Post(
- GrUniqueKeyInvalidatedMessage(fEntry->fAtlasKey));
- info->fIsPurgedFromResourceCache = true;
- }
- }
-
fEntry->unref();
}
@@ -115,9 +102,15 @@
entry = node->entry();
SkASSERT(this == entry->fCacheWeakPtr);
if (fuzzy_equals(m, entry->fMaskTransform)) {
- ++entry->fHitCount;
+ ++entry->fHitCount; // The path was reused with a compatible matrix.
+ } else if (CreateIfAbsent::kYes == createIfAbsent && entry->unique()) {
+ // This entry is unique: we can recycle it instead of deleting and malloc-ing a new one.
+ entry->fMaskTransform = m;
+ entry->fHitCount = 1;
+ entry->invalidateAtlas();
+ SkASSERT(!entry->fCurrFlushAtlas); // Should be null because 'entry' is unique.
} else {
- this->evict(entry); // The path was reused with an incompatible matrix.
+ this->evict(entry);
entry = nullptr;
}
}
@@ -148,6 +141,14 @@
fHashTable.remove(HashNode::GetKey(entry)); // ~HashNode() handles the rest.
}
+
+GrCCPathCacheEntry::~GrCCPathCacheEntry() {
+ SkASSERT(!fCacheWeakPtr); // HashNode should have cleared our cache pointer.
+ SkASSERT(!fCurrFlushAtlas); // Client is required to reset fCurrFlushAtlas back to null.
+
+ this->invalidateAtlas();
+}
+
void GrCCPathCacheEntry::initAsStashedAtlas(const GrUniqueKey& atlasKey,
const SkIVector& atlasOffset, const SkRect& devBounds,
const SkRect& devBounds45, const SkIRect& devIBounds,
@@ -179,6 +180,23 @@
fCachedAtlasInfo->fNumPathPixels += this->height() * this->width();
}
+void GrCCPathCacheEntry::invalidateAtlas() {
+ if (fCachedAtlasInfo) {
+ // Mark our own pixels invalid in the cached atlas texture.
+ fCachedAtlasInfo->fNumInvalidatedPathPixels += this->height() * this->width();
+ if (!fCachedAtlasInfo->fIsPurgedFromResourceCache &&
+ fCachedAtlasInfo->fNumInvalidatedPathPixels >= fCachedAtlasInfo->fNumPathPixels / 2) {
+ // Too many invalidated pixels: purge the atlas texture from the resource cache.
+ SkMessageBus<GrUniqueKeyInvalidatedMessage>::Post(
+ GrUniqueKeyInvalidatedMessage(fAtlasKey));
+ fCachedAtlasInfo->fIsPurgedFromResourceCache = true;
+ }
+ }
+
+ fAtlasKey.reset();
+ fCachedAtlasInfo = nullptr;
+}
+
void GrCCPathCacheEntry::onChange() {
// Our corresponding path was modified or deleted. Evict ourselves.
if (fCacheWeakPtr) {