41 sk_sp<SkStrike> strike = this->internalFindStrikeOrNull(strikeSpec.descriptor());
42 if (strike ==
nullptr) {
43 strike = this->internalCreateStrike(strikeSpec);
45 this->internalPurge();
58 SkDebugf(
"GlyphCache [ used budget ]\n");
64 auto visitor = [](
const SkStrike& strike) {
73 dump->dumpNumericValue(kGlyphCacheDumpName,
"budget_size",
"bytes",
75 dump->dumpNumericValue(kGlyphCacheDumpName,
"glyph_count",
"objects",
77 dump->dumpNumericValue(kGlyphCacheDumpName,
"budget_glyph_count",
"objects",
81 dump->setMemoryBacking(kGlyphCacheDumpName,
"malloc",
nullptr);
85 auto visitor = [&](
const SkStrike& strike) {
86 strike.dumpMemoryStatistics(
dump);
95 this->internalPurge();
102 if (fHead !=
nullptr && fHead->getDescriptor() ==
desc) {
return sk_ref_sp(fHead); }
106 if (strikeHandle ==
nullptr) {
return nullptr; }
107 SkStrike* strikePtr = strikeHandle->get();
109 if (fHead != strikePtr) {
111 strikePtr->fPrev->fNext = strikePtr->fNext;
112 if (strikePtr->fNext !=
nullptr) {
113 strikePtr->fNext->fPrev = strikePtr->fPrev;
115 fTail = strikePtr->fPrev;
117 fHead->fPrev = strikePtr;
118 strikePtr->fNext = fHead;
119 strikePtr->fPrev =
nullptr;
128 std::unique_ptr<SkStrikePinner> pinner) {
130 return this->internalCreateStrike(strikeSpec, maybeMetrics, std::move(pinner));
133auto SkStrikeCache::internalCreateStrike(
137 std::unique_ptr<SkScalerContext> scaler = strikeSpec.createScalerContext();
139 sk_make_sp<SkStrike>(
this, strikeSpec, std::move(scaler), maybeMetrics, std::move(pinner));
140 this->internalAttachToHead(strike);
146 this->internalPurge(minBytesNeeded,
true);
151 this->internalPurge(fTotalMemoryUsed,
true);
156 return fTotalMemoryUsed;
166 return fCacheCountLimit;
172 size_t prevLimit = fCacheSizeLimit;
173 fCacheSizeLimit = newLimit;
174 this->internalPurge();
180 return fCacheSizeLimit;
190 int prevCount = fCacheCountLimit;
191 fCacheCountLimit = newCount;
192 this->internalPurge();
201 for (
SkStrike* strike = fHead; strike !=
nullptr; strike = strike->fNext) {
206size_t SkStrikeCache::internalPurge(
size_t minBytesNeeded,
bool checkPinners) {
207#ifndef SK_STRIKE_CACHE_DOESNT_AUTO_CHECK_PINNERS
212 if (fPinnerCount == fCacheCount && !checkPinners)
215 size_t bytesNeeded = 0;
216 if (fTotalMemoryUsed > fCacheSizeLimit) {
217 bytesNeeded = fTotalMemoryUsed - fCacheSizeLimit;
219 bytesNeeded =
std::max(bytesNeeded, minBytesNeeded);
222 bytesNeeded =
std::max(bytesNeeded, fTotalMemoryUsed >> 2);
226 if (fCacheCount > fCacheCountLimit) {
227 countNeeded = fCacheCount - fCacheCountLimit;
229 countNeeded =
std::max(countNeeded, fCacheCount >> 2);
233 if (!countNeeded && !bytesNeeded) {
237 size_t bytesFreed = 0;
243 while (strike !=
nullptr && (bytesFreed < bytesNeeded || countFreed < countNeeded)) {
247 if (strike->fPinner ==
nullptr || (checkPinners && strike->fPinner->canDelete())) {
248 bytesFreed += strike->fMemoryUsed;
250 this->internalRemoveStrike(strike);
257#ifdef SPEW_PURGE_STATUS
259 SkDebugf(
"purging %dK from font cache [%d entries]\n",
260 (
int)(bytesFreed >> 10), countFreed);
270 fStrikeLookup.set(std::move(strike));
271 SkASSERT(
nullptr == strikePtr->fPrev &&
nullptr == strikePtr->fNext);
274 fPinnerCount += strikePtr->fPinner !=
nullptr ? 1 : 0;
275 fTotalMemoryUsed += strikePtr->fMemoryUsed;
277 if (fHead !=
nullptr) {
278 fHead->fPrev = strikePtr;
279 strikePtr->fNext = fHead;
282 if (fTail ==
nullptr) {
289void SkStrikeCache::internalRemoveStrike(
SkStrike* strike) {
292 fPinnerCount -= strike->fPinner !=
nullptr ? 1 : 0;
293 fTotalMemoryUsed -= strike->fMemoryUsed;
296 strike->fPrev->fNext = strike->fNext;
298 fHead = strike->fNext;
301 strike->fNext->fPrev = strike->fPrev;
303 fTail = strike->fPrev;
306 strike->fPrev = strike->fNext =
nullptr;
307 strike->fRemoved =
true;
311void SkStrikeCache::validate()
const {
313 size_t computedBytes = 0;
314 int computedCount = 0;
317 while (strike !=
nullptr) {
318 computedBytes += strike->fMemoryUsed;
321 strike = strike->fNext;
324 if (fCacheCount != computedCount) {
325 SkDebugf(
"fCacheCount: %d, computedCount: %d", fCacheCount, computedCount);
326 SK_ABORT(
"fCacheCount != computedCount");
328 if (fTotalMemoryUsed != computedBytes) {
329 SkDebugf(
"fTotalMemoryUsed: %zu, computedBytes: %zu", fTotalMemoryUsed, computedBytes);
330 SK_ABORT(
"fTotalMemoryUsed == computedBytes");
static float prev(float f)
#define SK_ABORT(message,...)
void SK_SPI SkDebugf(const char format[],...) SK_PRINTF_LIKE(1
sk_sp< T > sk_ref_sp(T *obj)
bool gSkUseThreadLocalStrikeCaches_IAcknowledgeThisIsIncrediblyExperimental
static void dump(const float m[20], SkYUVColorSpace cs, bool rgb2yuv)
uint32_t getChecksum() const
static int GetFontCacheCountLimit()
static size_t GetFontCacheLimit()
static int GetFontCacheCountUsed()
static size_t GetFontCacheUsed()
static void DumpMemoryStatistics(SkTraceMemoryDump *dump)
size_t getCacheSizeLimit() const SK_EXCLUDES(fLock)
size_t setCacheSizeLimit(size_t limit) SK_EXCLUDES(fLock)
int setCacheCountLimit(int limit) SK_EXCLUDES(fLock)
sk_sp< SkStrike > createStrike(const SkStrikeSpec &strikeSpec, SkFontMetrics *maybeMetrics=nullptr, std::unique_ptr< SkStrikePinner >=nullptr) SK_EXCLUDES(fLock)
sk_sp< SkStrike > findOrCreateStrike(const SkStrikeSpec &strikeSpec) SK_EXCLUDES(fLock)
sk_sp< SkStrike > findStrike(const SkDescriptor &desc) SK_EXCLUDES(fLock)
void purgePinned(size_t minBytesNeeded=0) SK_EXCLUDES(fLock)
void purgeAll() SK_EXCLUDES(fLock)
sk_sp< sktext::StrikeForGPU > findOrCreateScopedStrike(const SkStrikeSpec &strikeSpec) override SK_EXCLUDES(fLock)
int getCacheCountLimit() const SK_EXCLUDES(fLock)
size_t getTotalMemoryUsed() const SK_EXCLUDES(fLock)
int getCacheCountUsed() const SK_EXCLUDES(fLock)
static SkStrikeCache * GlobalStrikeCache()
const SkDescriptor & getDescriptor() const override
Dart_NativeFunction function
static float max(float r, float g, float b)
static uint32_t Hash(uint32_t key)
DEF_SWITCHES_START aot vmservice shared library Name of the *so containing AOT compiled Dart assets for launching the service isolate vm snapshot The VM snapshot data that will be memory mapped as read only SnapshotAssetPath must be present isolate snapshot The isolate snapshot data that will be memory mapped as read only SnapshotAssetPath must be present cache dir Path to the cache directory This is different from the persistent_cache_path in embedder which is used for Skia shader cache icu native lib Path to the library file that exports the ICU data vm service The hostname IP address on which the Dart VM Service should be served If not defaults to or::depending on whether ipv6 is specified vm service A custom Dart VM Service port The default is to pick a randomly available open port disable vm Disable the Dart VM Service The Dart VM Service is never available in release mode disable vm service Disable mDNS Dart VM Service publication Bind to the IPv6 localhost address for the Dart VM Service Ignored if vm service host is set endless trace Enable an endless trace buffer The default is a ring buffer This is useful when very old events need to viewed For during application launch Memory usage will continue to grow indefinitely however Start app with an specific route defined on the framework flutter assets Path to the Flutter assets directory enable service port Allow the VM service to fallback to automatic port selection if binding to a specified port fails trace Trace early application lifecycle Automatically switches to an endless trace buffer trace skia Filters out all Skia trace event categories except those that are specified in this comma separated list dump skp on shader Automatically dump the skp that triggers new shader compilations This is useful for writing custom ShaderWarmUp to reduce jank By this is not enabled to reduce the overhead purge persistent cache