1cb93a386Sopenharmony_ci/* 2cb93a386Sopenharmony_ci * Copyright 2018 Google Inc. 3cb93a386Sopenharmony_ci * 4cb93a386Sopenharmony_ci * Use of this source code is governed by a BSD-style license that can be 5cb93a386Sopenharmony_ci * found in the LICENSE file. 6cb93a386Sopenharmony_ci */ 7cb93a386Sopenharmony_ci 8cb93a386Sopenharmony_ci#include "src/core/SkStrikeCache.h" 9cb93a386Sopenharmony_ci 10cb93a386Sopenharmony_ci#include <cctype> 11cb93a386Sopenharmony_ci 12cb93a386Sopenharmony_ci#include "include/core/SkGraphics.h" 13cb93a386Sopenharmony_ci#include "include/core/SkRefCnt.h" 14cb93a386Sopenharmony_ci#include "include/core/SkTraceMemoryDump.h" 15cb93a386Sopenharmony_ci#include "include/core/SkTypeface.h" 16cb93a386Sopenharmony_ci#include "include/private/SkMutex.h" 17cb93a386Sopenharmony_ci#include "include/private/SkTemplates.h" 18cb93a386Sopenharmony_ci#include "src/core/SkGlyphRunPainter.h" 19cb93a386Sopenharmony_ci#include "src/core/SkScalerCache.h" 20cb93a386Sopenharmony_ci 21cb93a386Sopenharmony_ci#if SK_SUPPORT_GPU 22cb93a386Sopenharmony_ci#include "src/gpu/text/GrStrikeCache.h" 23cb93a386Sopenharmony_ci#endif 24cb93a386Sopenharmony_ci 25cb93a386Sopenharmony_cibool gSkUseThreadLocalStrikeCaches_IAcknowledgeThisIsIncrediblyExperimental = false; 26cb93a386Sopenharmony_ci 27cb93a386Sopenharmony_ciSkStrikeCache* SkStrikeCache::GlobalStrikeCache() { 28cb93a386Sopenharmony_ci if (gSkUseThreadLocalStrikeCaches_IAcknowledgeThisIsIncrediblyExperimental) { 29cb93a386Sopenharmony_ci static thread_local auto* cache = new SkStrikeCache; 30cb93a386Sopenharmony_ci return cache; 31cb93a386Sopenharmony_ci } 32cb93a386Sopenharmony_ci static auto* cache = new SkStrikeCache; 33cb93a386Sopenharmony_ci return cache; 34cb93a386Sopenharmony_ci} 35cb93a386Sopenharmony_ci 36cb93a386Sopenharmony_ciauto SkStrikeCache::findOrCreateStrike(const SkStrikeSpec& strikeSpec) -> sk_sp<SkStrike> { 37cb93a386Sopenharmony_ci SkAutoMutexExclusive ac(fLock); 38cb93a386Sopenharmony_ci sk_sp<SkStrike> strike = this->internalFindStrikeOrNull(strikeSpec.descriptor()); 39cb93a386Sopenharmony_ci if (strike == nullptr) { 40cb93a386Sopenharmony_ci strike = this->internalCreateStrike(strikeSpec); 41cb93a386Sopenharmony_ci } 42cb93a386Sopenharmony_ci this->internalPurge(); 43cb93a386Sopenharmony_ci return strike; 44cb93a386Sopenharmony_ci} 45cb93a386Sopenharmony_ci 46cb93a386Sopenharmony_ciSkScopedStrikeForGPU SkStrikeCache::findOrCreateScopedStrike(const SkStrikeSpec& strikeSpec) { 47cb93a386Sopenharmony_ci return SkScopedStrikeForGPU{this->findOrCreateStrike(strikeSpec).release()}; 48cb93a386Sopenharmony_ci} 49cb93a386Sopenharmony_ci 50cb93a386Sopenharmony_civoid SkStrikeCache::PurgeAll() { 51cb93a386Sopenharmony_ci GlobalStrikeCache()->purgeAll(); 52cb93a386Sopenharmony_ci} 53cb93a386Sopenharmony_ci 54cb93a386Sopenharmony_civoid SkStrikeCache::Dump() { 55cb93a386Sopenharmony_ci SkDebugf("GlyphCache [ used budget ]\n"); 56cb93a386Sopenharmony_ci SkDebugf(" bytes [ %8zu %8zu ]\n", 57cb93a386Sopenharmony_ci SkGraphics::GetFontCacheUsed(), SkGraphics::GetFontCacheLimit()); 58cb93a386Sopenharmony_ci SkDebugf(" count [ %8d %8d ]\n", 59cb93a386Sopenharmony_ci SkGraphics::GetFontCacheCountUsed(), SkGraphics::GetFontCacheCountLimit()); 60cb93a386Sopenharmony_ci 61cb93a386Sopenharmony_ci int counter = 0; 62cb93a386Sopenharmony_ci 63cb93a386Sopenharmony_ci auto visitor = [&counter](const SkStrike& strike) { 64cb93a386Sopenharmony_ci const SkScalerContextRec& rec = strike.fScalerCache.getScalerContext()->getRec(); 65cb93a386Sopenharmony_ci 66cb93a386Sopenharmony_ci SkDebugf("index %d\n", counter); 67cb93a386Sopenharmony_ci SkDebugf("%s", rec.dump().c_str()); 68cb93a386Sopenharmony_ci counter += 1; 69cb93a386Sopenharmony_ci }; 70cb93a386Sopenharmony_ci 71cb93a386Sopenharmony_ci GlobalStrikeCache()->forEachStrike(visitor); 72cb93a386Sopenharmony_ci} 73cb93a386Sopenharmony_ci 74cb93a386Sopenharmony_cinamespace { 75cb93a386Sopenharmony_ci const char gGlyphCacheDumpName[] = "skia/sk_glyph_cache"; 76cb93a386Sopenharmony_ci} // namespace 77cb93a386Sopenharmony_ci 78cb93a386Sopenharmony_civoid SkStrikeCache::DumpMemoryStatistics(SkTraceMemoryDump* dump) { 79cb93a386Sopenharmony_ci dump->dumpNumericValue(gGlyphCacheDumpName, "size", "bytes", SkGraphics::GetFontCacheUsed()); 80cb93a386Sopenharmony_ci dump->dumpNumericValue(gGlyphCacheDumpName, "budget_size", "bytes", 81cb93a386Sopenharmony_ci SkGraphics::GetFontCacheLimit()); 82cb93a386Sopenharmony_ci dump->dumpNumericValue(gGlyphCacheDumpName, "glyph_count", "objects", 83cb93a386Sopenharmony_ci SkGraphics::GetFontCacheCountUsed()); 84cb93a386Sopenharmony_ci dump->dumpNumericValue(gGlyphCacheDumpName, "budget_glyph_count", "objects", 85cb93a386Sopenharmony_ci SkGraphics::GetFontCacheCountLimit()); 86cb93a386Sopenharmony_ci 87cb93a386Sopenharmony_ci if (dump->getRequestedDetails() == SkTraceMemoryDump::kLight_LevelOfDetail) { 88cb93a386Sopenharmony_ci dump->setMemoryBacking(gGlyphCacheDumpName, "malloc", nullptr); 89cb93a386Sopenharmony_ci return; 90cb93a386Sopenharmony_ci } 91cb93a386Sopenharmony_ci 92cb93a386Sopenharmony_ci auto visitor = [&dump](const SkStrike& strike) { 93cb93a386Sopenharmony_ci const SkTypeface* face = strike.fScalerCache.getScalerContext()->getTypeface(); 94cb93a386Sopenharmony_ci const SkScalerContextRec& rec = strike.fScalerCache.getScalerContext()->getRec(); 95cb93a386Sopenharmony_ci 96cb93a386Sopenharmony_ci SkString fontName; 97cb93a386Sopenharmony_ci face->getFamilyName(&fontName); 98cb93a386Sopenharmony_ci // Replace all special characters with '_'. 99cb93a386Sopenharmony_ci for (size_t index = 0; index < fontName.size(); ++index) { 100cb93a386Sopenharmony_ci if (!std::isalnum(fontName[index])) { 101cb93a386Sopenharmony_ci fontName[index] = '_'; 102cb93a386Sopenharmony_ci } 103cb93a386Sopenharmony_ci } 104cb93a386Sopenharmony_ci 105cb93a386Sopenharmony_ci SkString dumpName = SkStringPrintf( 106cb93a386Sopenharmony_ci "%s/%s_%d/%p", gGlyphCacheDumpName, fontName.c_str(), rec.fFontID, &strike); 107cb93a386Sopenharmony_ci 108cb93a386Sopenharmony_ci dump->dumpNumericValue(dumpName.c_str(), 109cb93a386Sopenharmony_ci "size", "bytes", strike.fMemoryUsed); 110cb93a386Sopenharmony_ci dump->dumpNumericValue(dumpName.c_str(), 111cb93a386Sopenharmony_ci "glyph_count", "objects", 112cb93a386Sopenharmony_ci strike.fScalerCache.countCachedGlyphs()); 113cb93a386Sopenharmony_ci dump->setMemoryBacking(dumpName.c_str(), "malloc", nullptr); 114cb93a386Sopenharmony_ci }; 115cb93a386Sopenharmony_ci 116cb93a386Sopenharmony_ci GlobalStrikeCache()->forEachStrike(visitor); 117cb93a386Sopenharmony_ci} 118cb93a386Sopenharmony_ci 119cb93a386Sopenharmony_cisk_sp<SkStrike> SkStrikeCache::findStrike(const SkDescriptor& desc) { 120cb93a386Sopenharmony_ci SkAutoMutexExclusive ac(fLock); 121cb93a386Sopenharmony_ci sk_sp<SkStrike> result = this->internalFindStrikeOrNull(desc); 122cb93a386Sopenharmony_ci this->internalPurge(); 123cb93a386Sopenharmony_ci return result; 124cb93a386Sopenharmony_ci} 125cb93a386Sopenharmony_ci 126cb93a386Sopenharmony_ciauto SkStrikeCache::internalFindStrikeOrNull(const SkDescriptor& desc) -> sk_sp<SkStrike> { 127cb93a386Sopenharmony_ci 128cb93a386Sopenharmony_ci // Check head because it is likely the strike we are looking for. 129cb93a386Sopenharmony_ci if (fHead != nullptr && fHead->getDescriptor() == desc) { return sk_ref_sp(fHead); } 130cb93a386Sopenharmony_ci 131cb93a386Sopenharmony_ci // Do the heavy search looking for the strike. 132cb93a386Sopenharmony_ci sk_sp<SkStrike>* strikeHandle = fStrikeLookup.find(desc); 133cb93a386Sopenharmony_ci if (strikeHandle == nullptr) { return nullptr; } 134cb93a386Sopenharmony_ci SkStrike* strikePtr = strikeHandle->get(); 135cb93a386Sopenharmony_ci SkASSERT(strikePtr != nullptr); 136cb93a386Sopenharmony_ci if (fHead != strikePtr) { 137cb93a386Sopenharmony_ci // Make most recently used 138cb93a386Sopenharmony_ci strikePtr->fPrev->fNext = strikePtr->fNext; 139cb93a386Sopenharmony_ci if (strikePtr->fNext != nullptr) { 140cb93a386Sopenharmony_ci strikePtr->fNext->fPrev = strikePtr->fPrev; 141cb93a386Sopenharmony_ci } else { 142cb93a386Sopenharmony_ci fTail = strikePtr->fPrev; 143cb93a386Sopenharmony_ci } 144cb93a386Sopenharmony_ci fHead->fPrev = strikePtr; 145cb93a386Sopenharmony_ci strikePtr->fNext = fHead; 146cb93a386Sopenharmony_ci strikePtr->fPrev = nullptr; 147cb93a386Sopenharmony_ci fHead = strikePtr; 148cb93a386Sopenharmony_ci } 149cb93a386Sopenharmony_ci return sk_ref_sp(strikePtr); 150cb93a386Sopenharmony_ci} 151cb93a386Sopenharmony_ci 152cb93a386Sopenharmony_cisk_sp<SkStrike> SkStrikeCache::createStrike( 153cb93a386Sopenharmony_ci const SkStrikeSpec& strikeSpec, 154cb93a386Sopenharmony_ci SkFontMetrics* maybeMetrics, 155cb93a386Sopenharmony_ci std::unique_ptr<SkStrikePinner> pinner) { 156cb93a386Sopenharmony_ci SkAutoMutexExclusive ac(fLock); 157cb93a386Sopenharmony_ci return this->internalCreateStrike(strikeSpec, maybeMetrics, std::move(pinner)); 158cb93a386Sopenharmony_ci} 159cb93a386Sopenharmony_ci 160cb93a386Sopenharmony_ciauto SkStrikeCache::internalCreateStrike( 161cb93a386Sopenharmony_ci const SkStrikeSpec& strikeSpec, 162cb93a386Sopenharmony_ci SkFontMetrics* maybeMetrics, 163cb93a386Sopenharmony_ci std::unique_ptr<SkStrikePinner> pinner) -> sk_sp<SkStrike> { 164cb93a386Sopenharmony_ci std::unique_ptr<SkScalerContext> scaler = strikeSpec.createScalerContext(); 165cb93a386Sopenharmony_ci auto strike = 166cb93a386Sopenharmony_ci sk_make_sp<SkStrike>(this, strikeSpec, std::move(scaler), maybeMetrics, std::move(pinner)); 167cb93a386Sopenharmony_ci this->internalAttachToHead(strike); 168cb93a386Sopenharmony_ci return strike; 169cb93a386Sopenharmony_ci} 170cb93a386Sopenharmony_ci 171cb93a386Sopenharmony_civoid SkStrikeCache::purgeAll() { 172cb93a386Sopenharmony_ci SkAutoMutexExclusive ac(fLock); 173cb93a386Sopenharmony_ci this->internalPurge(fTotalMemoryUsed); 174cb93a386Sopenharmony_ci} 175cb93a386Sopenharmony_ci 176cb93a386Sopenharmony_cisize_t SkStrikeCache::getTotalMemoryUsed() const { 177cb93a386Sopenharmony_ci SkAutoMutexExclusive ac(fLock); 178cb93a386Sopenharmony_ci return fTotalMemoryUsed; 179cb93a386Sopenharmony_ci} 180cb93a386Sopenharmony_ci 181cb93a386Sopenharmony_ciint SkStrikeCache::getCacheCountUsed() const { 182cb93a386Sopenharmony_ci SkAutoMutexExclusive ac(fLock); 183cb93a386Sopenharmony_ci return fCacheCount; 184cb93a386Sopenharmony_ci} 185cb93a386Sopenharmony_ci 186cb93a386Sopenharmony_ciint SkStrikeCache::getCacheCountLimit() const { 187cb93a386Sopenharmony_ci SkAutoMutexExclusive ac(fLock); 188cb93a386Sopenharmony_ci return fCacheCountLimit; 189cb93a386Sopenharmony_ci} 190cb93a386Sopenharmony_ci 191cb93a386Sopenharmony_cisize_t SkStrikeCache::setCacheSizeLimit(size_t newLimit) { 192cb93a386Sopenharmony_ci SkAutoMutexExclusive ac(fLock); 193cb93a386Sopenharmony_ci 194cb93a386Sopenharmony_ci size_t prevLimit = fCacheSizeLimit; 195cb93a386Sopenharmony_ci fCacheSizeLimit = newLimit; 196cb93a386Sopenharmony_ci this->internalPurge(); 197cb93a386Sopenharmony_ci return prevLimit; 198cb93a386Sopenharmony_ci} 199cb93a386Sopenharmony_ci 200cb93a386Sopenharmony_cisize_t SkStrikeCache::getCacheSizeLimit() const { 201cb93a386Sopenharmony_ci SkAutoMutexExclusive ac(fLock); 202cb93a386Sopenharmony_ci return fCacheSizeLimit; 203cb93a386Sopenharmony_ci} 204cb93a386Sopenharmony_ci 205cb93a386Sopenharmony_ciint SkStrikeCache::setCacheCountLimit(int newCount) { 206cb93a386Sopenharmony_ci if (newCount < 0) { 207cb93a386Sopenharmony_ci newCount = 0; 208cb93a386Sopenharmony_ci } 209cb93a386Sopenharmony_ci 210cb93a386Sopenharmony_ci SkAutoMutexExclusive ac(fLock); 211cb93a386Sopenharmony_ci 212cb93a386Sopenharmony_ci int prevCount = fCacheCountLimit; 213cb93a386Sopenharmony_ci fCacheCountLimit = newCount; 214cb93a386Sopenharmony_ci this->internalPurge(); 215cb93a386Sopenharmony_ci return prevCount; 216cb93a386Sopenharmony_ci} 217cb93a386Sopenharmony_ci 218cb93a386Sopenharmony_civoid SkStrikeCache::forEachStrike(std::function<void(const SkStrike&)> visitor) const { 219cb93a386Sopenharmony_ci SkAutoMutexExclusive ac(fLock); 220cb93a386Sopenharmony_ci 221cb93a386Sopenharmony_ci this->validate(); 222cb93a386Sopenharmony_ci 223cb93a386Sopenharmony_ci for (SkStrike* strike = fHead; strike != nullptr; strike = strike->fNext) { 224cb93a386Sopenharmony_ci visitor(*strike); 225cb93a386Sopenharmony_ci } 226cb93a386Sopenharmony_ci} 227cb93a386Sopenharmony_ci 228cb93a386Sopenharmony_cisize_t SkStrikeCache::internalPurge(size_t minBytesNeeded) { 229cb93a386Sopenharmony_ci size_t bytesNeeded = 0; 230cb93a386Sopenharmony_ci if (fTotalMemoryUsed > fCacheSizeLimit) { 231cb93a386Sopenharmony_ci bytesNeeded = fTotalMemoryUsed - fCacheSizeLimit; 232cb93a386Sopenharmony_ci } 233cb93a386Sopenharmony_ci bytesNeeded = std::max(bytesNeeded, minBytesNeeded); 234cb93a386Sopenharmony_ci if (bytesNeeded) { 235cb93a386Sopenharmony_ci // no small purges! 236cb93a386Sopenharmony_ci bytesNeeded = std::max(bytesNeeded, fTotalMemoryUsed >> 2); 237cb93a386Sopenharmony_ci } 238cb93a386Sopenharmony_ci 239cb93a386Sopenharmony_ci int countNeeded = 0; 240cb93a386Sopenharmony_ci if (fCacheCount > fCacheCountLimit) { 241cb93a386Sopenharmony_ci countNeeded = fCacheCount - fCacheCountLimit; 242cb93a386Sopenharmony_ci // no small purges! 243cb93a386Sopenharmony_ci countNeeded = std::max(countNeeded, fCacheCount >> 2); 244cb93a386Sopenharmony_ci } 245cb93a386Sopenharmony_ci 246cb93a386Sopenharmony_ci // early exit 247cb93a386Sopenharmony_ci if (!countNeeded && !bytesNeeded) { 248cb93a386Sopenharmony_ci return 0; 249cb93a386Sopenharmony_ci } 250cb93a386Sopenharmony_ci 251cb93a386Sopenharmony_ci size_t bytesFreed = 0; 252cb93a386Sopenharmony_ci int countFreed = 0; 253cb93a386Sopenharmony_ci 254cb93a386Sopenharmony_ci // Start at the tail and proceed backwards deleting; the list is in LRU 255cb93a386Sopenharmony_ci // order, with unimportant entries at the tail. 256cb93a386Sopenharmony_ci SkStrike* strike = fTail; 257cb93a386Sopenharmony_ci while (strike != nullptr && (bytesFreed < bytesNeeded || countFreed < countNeeded)) { 258cb93a386Sopenharmony_ci SkStrike* prev = strike->fPrev; 259cb93a386Sopenharmony_ci 260cb93a386Sopenharmony_ci // Only delete if the strike is not pinned. 261cb93a386Sopenharmony_ci if (strike->fPinner == nullptr || strike->fPinner->canDelete()) { 262cb93a386Sopenharmony_ci bytesFreed += strike->fMemoryUsed; 263cb93a386Sopenharmony_ci countFreed += 1; 264cb93a386Sopenharmony_ci this->internalRemoveStrike(strike); 265cb93a386Sopenharmony_ci } 266cb93a386Sopenharmony_ci strike = prev; 267cb93a386Sopenharmony_ci } 268cb93a386Sopenharmony_ci 269cb93a386Sopenharmony_ci this->validate(); 270cb93a386Sopenharmony_ci 271cb93a386Sopenharmony_ci#ifdef SPEW_PURGE_STATUS 272cb93a386Sopenharmony_ci if (countFreed) { 273cb93a386Sopenharmony_ci SkDebugf("purging %dK from font cache [%d entries]\n", 274cb93a386Sopenharmony_ci (int)(bytesFreed >> 10), countFreed); 275cb93a386Sopenharmony_ci } 276cb93a386Sopenharmony_ci#endif 277cb93a386Sopenharmony_ci 278cb93a386Sopenharmony_ci return bytesFreed; 279cb93a386Sopenharmony_ci} 280cb93a386Sopenharmony_ci 281cb93a386Sopenharmony_civoid SkStrikeCache::internalAttachToHead(sk_sp<SkStrike> strike) { 282cb93a386Sopenharmony_ci SkASSERT(fStrikeLookup.find(strike->getDescriptor()) == nullptr); 283cb93a386Sopenharmony_ci SkStrike* strikePtr = strike.get(); 284cb93a386Sopenharmony_ci fStrikeLookup.set(std::move(strike)); 285cb93a386Sopenharmony_ci SkASSERT(nullptr == strikePtr->fPrev && nullptr == strikePtr->fNext); 286cb93a386Sopenharmony_ci 287cb93a386Sopenharmony_ci fCacheCount += 1; 288cb93a386Sopenharmony_ci fTotalMemoryUsed += strikePtr->fMemoryUsed; 289cb93a386Sopenharmony_ci 290cb93a386Sopenharmony_ci if (fHead != nullptr) { 291cb93a386Sopenharmony_ci fHead->fPrev = strikePtr; 292cb93a386Sopenharmony_ci strikePtr->fNext = fHead; 293cb93a386Sopenharmony_ci } 294cb93a386Sopenharmony_ci 295cb93a386Sopenharmony_ci if (fTail == nullptr) { 296cb93a386Sopenharmony_ci fTail = strikePtr; 297cb93a386Sopenharmony_ci } 298cb93a386Sopenharmony_ci 299cb93a386Sopenharmony_ci fHead = strikePtr; // Transfer ownership of strike to the cache list. 300cb93a386Sopenharmony_ci} 301cb93a386Sopenharmony_ci 302cb93a386Sopenharmony_civoid SkStrikeCache::internalRemoveStrike(SkStrike* strike) { 303cb93a386Sopenharmony_ci SkASSERT(fCacheCount > 0); 304cb93a386Sopenharmony_ci fCacheCount -= 1; 305cb93a386Sopenharmony_ci fTotalMemoryUsed -= strike->fMemoryUsed; 306cb93a386Sopenharmony_ci 307cb93a386Sopenharmony_ci if (strike->fPrev) { 308cb93a386Sopenharmony_ci strike->fPrev->fNext = strike->fNext; 309cb93a386Sopenharmony_ci } else { 310cb93a386Sopenharmony_ci fHead = strike->fNext; 311cb93a386Sopenharmony_ci } 312cb93a386Sopenharmony_ci if (strike->fNext) { 313cb93a386Sopenharmony_ci strike->fNext->fPrev = strike->fPrev; 314cb93a386Sopenharmony_ci } else { 315cb93a386Sopenharmony_ci fTail = strike->fPrev; 316cb93a386Sopenharmony_ci } 317cb93a386Sopenharmony_ci 318cb93a386Sopenharmony_ci strike->fPrev = strike->fNext = nullptr; 319cb93a386Sopenharmony_ci strike->fRemoved = true; 320cb93a386Sopenharmony_ci fStrikeLookup.remove(strike->getDescriptor()); 321cb93a386Sopenharmony_ci} 322cb93a386Sopenharmony_ci 323cb93a386Sopenharmony_civoid SkStrikeCache::validate() const { 324cb93a386Sopenharmony_ci#ifdef SK_DEBUG 325cb93a386Sopenharmony_ci size_t computedBytes = 0; 326cb93a386Sopenharmony_ci int computedCount = 0; 327cb93a386Sopenharmony_ci 328cb93a386Sopenharmony_ci const SkStrike* strike = fHead; 329cb93a386Sopenharmony_ci while (strike != nullptr) { 330cb93a386Sopenharmony_ci computedBytes += strike->fMemoryUsed; 331cb93a386Sopenharmony_ci computedCount += 1; 332cb93a386Sopenharmony_ci SkASSERT(fStrikeLookup.findOrNull(strike->getDescriptor()) != nullptr); 333cb93a386Sopenharmony_ci strike = strike->fNext; 334cb93a386Sopenharmony_ci } 335cb93a386Sopenharmony_ci 336cb93a386Sopenharmony_ci if (fCacheCount != computedCount) { 337cb93a386Sopenharmony_ci SkDebugf("fCacheCount: %d, computedCount: %d", fCacheCount, computedCount); 338cb93a386Sopenharmony_ci SK_ABORT("fCacheCount != computedCount"); 339cb93a386Sopenharmony_ci } 340cb93a386Sopenharmony_ci if (fTotalMemoryUsed != computedBytes) { 341cb93a386Sopenharmony_ci SkDebugf("fTotalMemoryUsed: %zu, computedBytes: %zu", fTotalMemoryUsed, computedBytes); 342cb93a386Sopenharmony_ci SK_ABORT("fTotalMemoryUsed == computedBytes"); 343cb93a386Sopenharmony_ci } 344cb93a386Sopenharmony_ci#endif 345cb93a386Sopenharmony_ci} 346cb93a386Sopenharmony_ci 347cb93a386Sopenharmony_ci#if SK_SUPPORT_GPU 348cb93a386Sopenharmony_ci sk_sp<GrTextStrike> SkStrike::findOrCreateGrStrike(GrStrikeCache* grStrikeCache) const { 349cb93a386Sopenharmony_ci return grStrikeCache->findOrCreateStrike(fStrikeSpec); 350cb93a386Sopenharmony_ci } 351cb93a386Sopenharmony_ci#endif 352cb93a386Sopenharmony_ci 353cb93a386Sopenharmony_civoid SkStrike::updateDelta(size_t increase) { 354cb93a386Sopenharmony_ci if (increase != 0) { 355cb93a386Sopenharmony_ci SkAutoMutexExclusive lock{fStrikeCache->fLock}; 356cb93a386Sopenharmony_ci fMemoryUsed += increase; 357cb93a386Sopenharmony_ci if (!fRemoved) { 358cb93a386Sopenharmony_ci fStrikeCache->fTotalMemoryUsed += increase; 359cb93a386Sopenharmony_ci } 360cb93a386Sopenharmony_ci } 361cb93a386Sopenharmony_ci} 362cb93a386Sopenharmony_ci 363