| /* | |
| * Copyright 2015 Google Inc. | |
| * | |
| * Use of this source code is governed by a BSD-style license that can be | |
| * found in the LICENSE file. | |
| */ | |
| #ifndef sktext_gpu_StrikeCache_DEFINED | |
| #define sktext_gpu_StrikeCache_DEFINED | |
| #include "include/core/SkRefCnt.h" | |
| #include "src/core/SkArenaAlloc.h" | |
| #include "src/core/SkDescriptor.h" | |
| #include "src/core/SkStrikeSpec.h" | |
| #include "src/core/SkTHash.h" | |
| #include <cstddef> | |
| #include <cstdint> | |
| struct SkPackedGlyphID; | |
| // SK_DEFAULT_GPU_FONT_CACHE_COUNT_LIMIT and SK_DEFAULT_GPU_FONT_CACHE_LIMIT can be set using -D | |
| // on your ompiler commandline, or by using the defines in SkUserConfig.h | |
| #ifndef SK_DEFAULT_GPU_FONT_CACHE_COUNT_LIMIT | |
| #define SK_DEFAULT_GPU_FONT_CACHE_COUNT_LIMIT 2048 | |
| #endif | |
| #ifndef SK_DEFAULT_GPU_FONT_CACHE_LIMIT | |
| #define SK_DEFAULT_GPU_FONT_CACHE_LIMIT (2 * 1024 * 1024) | |
| #endif | |
| namespace sktext::gpu { | |
| class StrikeCache; | |
| /** | |
| * Abstract base class for backend-specific text strike caches. This allows a | |
| * shared StrikeCache implementation. | |
| */ | |
| class TextStrikeBase : public SkRefCnt { | |
| public: | |
| ~TextStrikeBase() override = default; | |
| const SkStrikeSpec& strikeSpec() const { return fStrikeSpec; } | |
| const SkDescriptor& getDescriptor() const { return fStrikeSpec.descriptor(); } | |
| size_t memoryUsed() const { return fMemoryUsed; } | |
| protected: | |
| TextStrikeBase(StrikeCache* strikeCache, const SkStrikeSpec& strikeSpec) | |
| : fStrikeCache(strikeCache), fStrikeSpec(strikeSpec) {} | |
| static sk_sp<TextStrikeBase> Find(const StrikeCache*, const SkDescriptor&); | |
| static void Add(StrikeCache*, sk_sp<TextStrikeBase>); | |
| // Called by derived classes when allocating glyphs to update cache accounting | |
| void addMemoryUsed(size_t bytes); | |
| StrikeCache* const fStrikeCache; | |
| const SkStrikeSpec fStrikeSpec; | |
| // Store for the glyph information (backend-specific glyphs allocated here) | |
| SkArenaAlloc fAlloc{512}; | |
| // Linked list for LRU cache management | |
| TextStrikeBase* fNext{nullptr}; | |
| TextStrikeBase* fPrev{nullptr}; | |
| size_t fMemoryUsed{sizeof(TextStrikeBase)}; | |
| bool fRemoved{false}; | |
| friend class StrikeCache; | |
| }; | |
| // StrikeCache manages strikes which are indexed by a SkStrike. These strikes can then be | |
| // used to generate individual Glyph Masks. | |
| class StrikeCache { | |
| public: | |
| ~StrikeCache(); | |
| void freeAll(); | |
| private: | |
| friend class TextStrikeBase; | |
| void internalRemoveStrike(TextStrikeBase* strike); | |
| void internalAttachToHead(sk_sp<TextStrikeBase> strike); | |
| // Checkout budgets, modulated by the specified min-bytes-needed-to-purge, | |
| // and attempt to purge caches to match. | |
| // Returns number of bytes freed. | |
| size_t internalPurge(size_t minBytesNeeded = 0); | |
| // A simple accounting of what each glyph cache reports and the strike cache total. | |
| void validate() const; | |
| TextStrikeBase* fHead{nullptr}; | |
| TextStrikeBase* fTail{nullptr}; | |
| struct HashTraits { | |
| static const SkDescriptor& GetKey(const sk_sp<TextStrikeBase>& strike); | |
| static uint32_t Hash(const SkDescriptor& strikeSpec); | |
| }; | |
| using StrikeHash = | |
| skia_private::THashTable<sk_sp<TextStrikeBase>, const SkDescriptor&, HashTraits>; | |
| StrikeHash fCache; | |
| size_t fCacheSizeLimit{SK_DEFAULT_GPU_FONT_CACHE_LIMIT}; | |
| size_t fTotalMemoryUsed{0}; | |
| int32_t fCacheCountLimit{SK_DEFAULT_GPU_FONT_CACHE_COUNT_LIMIT}; | |
| int32_t fCacheCount{0}; | |
| }; | |
| inline sk_sp<TextStrikeBase> TextStrikeBase::Find(const StrikeCache* cache, | |
| const SkDescriptor& desc) { | |
| auto entry = cache->fCache.find(desc); | |
| return entry ? *entry : nullptr; | |
| } | |
| inline void TextStrikeBase::Add(StrikeCache* cache, sk_sp<TextStrikeBase> strike) { | |
| SkASSERT(!Find(cache, strike->getDescriptor())); | |
| cache->internalAttachToHead(std::move(strike)); | |
| cache->internalPurge(); | |
| } | |
| } // namespace sktext::gpu | |
| #endif // sktext_gpu_StrikeCache_DEFINED |