From e68c4fbf601e38fdab1e0ab4093647d5538fff11 Mon Sep 17 00:00:00 2001 From: Herb Derby Date: Thu, 19 Apr 2018 13:12:07 -0400 Subject: [PATCH] Adding pinning to the strike cache Here is a simple API for the object that pins, and how it flows through the cache. BUG=skia:7515 Change-Id: I1b8304dc6f9d8652282300fc1e52d52debb5b6f4 Reviewed-on: https://skia-review.googlesource.com/122500 Reviewed-by: Mike Klein Commit-Queue: Herb Derby --- src/core/SkStrikeCache.cpp | 169 +++++++++++++++++++------------------ src/core/SkStrikeCache.h | 10 ++- 2 files changed, 97 insertions(+), 82 deletions(-) diff --git a/src/core/SkStrikeCache.cpp b/src/core/SkStrikeCache.cpp index 0c6cb83447..0fb36aaf14 100644 --- a/src/core/SkStrikeCache.cpp +++ b/src/core/SkStrikeCache.cpp @@ -30,12 +30,16 @@ static SkStrikeCache& get_globals() { struct SkStrikeCache::Node { Node(const SkDescriptor& desc, - std::unique_ptr scaler, - const SkPaint::FontMetrics& metrics) - : fCache{desc, std::move(scaler), metrics} {} - Node* fNext{nullptr}; - Node* fPrev{nullptr}; - SkGlyphCache fCache; + std::unique_ptr scaler, + const SkPaint::FontMetrics& metrics, + std::unique_ptr pinner) + : fCache{desc, std::move(scaler), metrics} + , fPinner{std::move(pinner)} {} + + Node* fNext{nullptr}; + Node* fPrev{nullptr}; + SkGlyphCache fCache; + std::unique_ptr fPinner; }; SkStrikeCache::ExclusiveStrikePtr::ExclusiveStrikePtr(SkStrikeCache::Node* node) : fNode{node} {} @@ -114,6 +118,39 @@ std::unique_ptr SkStrikeCache::CreateScalerContext( return scaler; } +SkExclusiveStrikePtr SkStrikeCache::FindOrCreateStrikeExclusive( + const SkDescriptor& desc, const SkScalerContextEffects& effects, const SkTypeface& typeface) +{ + auto cache = FindStrikeExclusive(desc); + if (cache == nullptr) { + auto scaler = CreateScalerContext(desc, effects, typeface); + cache = CreateStrikeExclusive(desc, std::move(scaler)); + } + return cache; +} + +SkExclusiveStrikePtr SkStrikeCache::FindOrCreateStrikeExclusive( + const SkPaint& paint, + const SkSurfaceProps* surfaceProps, + SkScalerContextFlags scalerContextFlags, + const SkMatrix* deviceMatrix) +{ + SkAutoDescriptor ad; + SkScalerContextEffects effects; + + auto desc = SkScalerContext::CreateDescriptorAndEffectsUsingPaint( + paint, surfaceProps, scalerContextFlags, deviceMatrix, &ad, &effects); + + auto tf = SkPaintPriv::GetTypefaceOrDefault(paint); + + return FindOrCreateStrikeExclusive(*desc, effects, *tf); +} + +SkExclusiveStrikePtr SkStrikeCache::FindOrCreateStrikeExclusive(const SkPaint& paint) { + return FindOrCreateStrikeExclusive( + paint, nullptr, kFakeGammaAndBoostContrast, nullptr); +} + void SkStrikeCache::PurgeAll() { get_globals().purgeAll(); } @@ -210,6 +247,22 @@ SkExclusiveStrikePtr SkStrikeCache::findStrikeExclusive(const SkDescriptor& desc return SkExclusiveStrikePtr(nullptr); } +SkExclusiveStrikePtr SkStrikeCache::CreateStrikeExclusive( + const SkDescriptor& desc, + std::unique_ptr scaler, + SkPaint::FontMetrics* maybeMetrics, + std::unique_ptr pinner) +{ + SkPaint::FontMetrics fontMetrics; + if (maybeMetrics != nullptr) { + fontMetrics = *maybeMetrics; + } else { + scaler->getFontMetrics(&fontMetrics); + } + + return SkExclusiveStrikePtr(new Node(desc, std::move(scaler), fontMetrics, std::move(pinner))); +} + void SkStrikeCache::purgeAll() { SkAutoExclusive ac(fLock); this->internalPurge(fTotalMemoryUsed); @@ -327,17 +380,19 @@ size_t SkStrikeCache::internalPurge(size_t minBytesNeeded) { size_t bytesFreed = 0; int countFreed = 0; - // we start at the tail and proceed backwards, as the linklist is in LRU + // Start at the tail and proceed backwards deleting; the list is in LRU // order, with unimportant entries at the tail. Node* node = this->internalGetTail(); - while (node != nullptr && - (bytesFreed < bytesNeeded || countFreed < countNeeded)) { + while (node != nullptr && (bytesFreed < bytesNeeded || countFreed < countNeeded)) { Node* prev = node->fPrev; - bytesFreed += node->fCache.getMemoryUsed(); - countFreed += 1; - this->internalDetachCache(node); - delete node; + // Only delete if the strike is not pinned. + if (node->fPinner == nullptr || node->fPinner->canDelete()) { + bytesFreed += node->fCache.getMemoryUsed(); + countFreed += 1; + this->internalDetachCache(node); + delete node; + } node = prev; } @@ -381,6 +436,27 @@ void SkStrikeCache::internalDetachCache(Node* node) { node->fPrev = node->fNext = nullptr; } +#ifdef SK_DEBUG +void SkStrikeCache::validate() const { + size_t computedBytes = 0; + int computedCount = 0; + + const Node* node = fHead; + while (node != nullptr) { + computedBytes += node->fCache.getMemoryUsed(); + computedCount += 1; + node = node->fNext; + } + + SkASSERTF(fCacheCount == computedCount, "fCacheCount: %d, computedCount: %d", fCacheCount, + computedCount); + SkASSERTF(fTotalMemoryUsed == computedBytes, "fTotalMemoryUsed: %d, computedBytes: %d", + fTotalMemoryUsed, computedBytes); +} +#endif + +//////////////////////////////////////////////////////////////////////////////////////////////////// + size_t SkGraphics::GetFontCacheLimit() { return get_globals().getCacheSizeLimit(); } @@ -417,70 +493,3 @@ void SkGraphics::PurgeFontCache() { get_globals().purgeAll(); SkTypefaceCache::PurgeAll(); } - -SkExclusiveStrikePtr SkStrikeCache::CreateStrikeExclusive( - const SkDescriptor& desc, - std::unique_ptr scaler, - SkPaint::FontMetrics* maybeMetrics) -{ - SkPaint::FontMetrics fontMetrics; - if (maybeMetrics != nullptr) { - fontMetrics = *maybeMetrics; - } else { - scaler->getFontMetrics(&fontMetrics); - } - - return SkExclusiveStrikePtr(new Node(desc, move(scaler), fontMetrics)); -} - -SkExclusiveStrikePtr SkStrikeCache::FindOrCreateStrikeExclusive( - const SkDescriptor& desc, const SkScalerContextEffects& effects, const SkTypeface& typeface) -{ - auto cache = FindStrikeExclusive(desc); - if (cache == nullptr) { - auto scaler = CreateScalerContext(desc, effects, typeface); - cache = CreateStrikeExclusive(desc, move(scaler)); - } - return cache; -} - -SkExclusiveStrikePtr SkStrikeCache::FindOrCreateStrikeExclusive( - const SkPaint& paint, - const SkSurfaceProps* surfaceProps, - SkScalerContextFlags scalerContextFlags, - const SkMatrix* deviceMatrix) -{ - SkAutoDescriptor ad; - SkScalerContextEffects effects; - - auto desc = SkScalerContext::CreateDescriptorAndEffectsUsingPaint( - paint, surfaceProps, scalerContextFlags, deviceMatrix, &ad, &effects); - - auto tf = SkPaintPriv::GetTypefaceOrDefault(paint); - - return FindOrCreateStrikeExclusive(*desc, effects, *tf); -} - -SkExclusiveStrikePtr SkStrikeCache::FindOrCreateStrikeExclusive(const SkPaint& paint) { - return FindOrCreateStrikeExclusive( - paint, nullptr, kFakeGammaAndBoostContrast, nullptr); -} - -#ifdef SK_DEBUG -void SkStrikeCache::validate() const { - size_t computedBytes = 0; - int computedCount = 0; - - const Node* node = fHead; - while (node != nullptr) { - computedBytes += node->fCache.getMemoryUsed(); - computedCount += 1; - node = node->fNext; - } - - SkASSERTF(fCacheCount == computedCount, "fCacheCount: %d, computedCount: %d", fCacheCount, - computedCount); - SkASSERTF(fTotalMemoryUsed == computedBytes, "fTotalMemoryUsed: %d, computedBytes: %d", - fTotalMemoryUsed, computedBytes); -} -#endif \ No newline at end of file diff --git a/src/core/SkStrikeCache.h b/src/core/SkStrikeCache.h index a98b508c15..cdaffb5688 100644 --- a/src/core/SkStrikeCache.h +++ b/src/core/SkStrikeCache.h @@ -29,6 +29,12 @@ class SkTraceMemoryDump; /////////////////////////////////////////////////////////////////////////////// +class SkStrikePinner { +public: + virtual ~SkStrikePinner() = default; + virtual bool canDelete() = 0; +}; + class SkStrikeCache { struct Node; @@ -36,7 +42,6 @@ public: SkStrikeCache() = default; ~SkStrikeCache(); - class ExclusiveStrikePtr { public: explicit ExclusiveStrikePtr(Node*); @@ -64,7 +69,8 @@ public: static ExclusiveStrikePtr CreateStrikeExclusive( const SkDescriptor& desc, std::unique_ptr scaler, - SkPaint::FontMetrics* maybeMetrics = nullptr); + SkPaint::FontMetrics* maybeMetrics = nullptr, + std::unique_ptr = nullptr); static ExclusiveStrikePtr FindOrCreateStrikeExclusive( const SkDescriptor& desc,