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