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 <mtklein@chromium.org>
Commit-Queue: Herb Derby <herb@google.com>
This commit is contained in:
Herb Derby 2018-04-19 13:12:07 -04:00 committed by Skia Commit-Bot
parent 33c442206a
commit e68c4fbf60
2 changed files with 97 additions and 82 deletions

View File

@ -30,12 +30,16 @@ static SkStrikeCache& get_globals() {
struct SkStrikeCache::Node {
Node(const SkDescriptor& desc,
std::unique_ptr<SkScalerContext> scaler,
const SkPaint::FontMetrics& metrics)
: fCache{desc, std::move(scaler), metrics} {}
Node* fNext{nullptr};
Node* fPrev{nullptr};
SkGlyphCache fCache;
std::unique_ptr<SkScalerContext> scaler,
const SkPaint::FontMetrics& metrics,
std::unique_ptr<SkStrikePinner> pinner)
: fCache{desc, std::move(scaler), metrics}
, fPinner{std::move(pinner)} {}
Node* fNext{nullptr};
Node* fPrev{nullptr};
SkGlyphCache fCache;
std::unique_ptr<SkStrikePinner> fPinner;
};
SkStrikeCache::ExclusiveStrikePtr::ExclusiveStrikePtr(SkStrikeCache::Node* node) : fNode{node} {}
@ -114,6 +118,39 @@ std::unique_ptr<SkScalerContext> 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<SkScalerContext> scaler,
SkPaint::FontMetrics* maybeMetrics,
std::unique_ptr<SkStrikePinner> 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<SkScalerContext> 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

View File

@ -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<SkScalerContext> scaler,
SkPaint::FontMetrics* maybeMetrics = nullptr);
SkPaint::FontMetrics* maybeMetrics = nullptr,
std::unique_ptr<SkStrikePinner> = nullptr);
static ExclusiveStrikePtr FindOrCreateStrikeExclusive(
const SkDescriptor& desc,