1 /* 2 * Copyright 2015 Google Inc. 3 * 4 * Use of this source code is governed by a BSD-style license that can be 5 * found in the LICENSE file. 6 */ 7 8 #ifndef sktext_gpu_StrikeCache_DEFINED 9 #define sktext_gpu_StrikeCache_DEFINED 10 11 #include "include/core/SkRefCnt.h" 12 #include "src/base/SkArenaAlloc.h" 13 #include "src/core/SkDescriptor.h" 14 #include "src/core/SkStrikeSpec.h" 15 #include "src/core/SkTHash.h" 16 17 #include <cstddef> 18 #include <cstdint> 19 20 struct SkPackedGlyphID; 21 22 // SK_DEFAULT_GPU_FONT_CACHE_COUNT_LIMIT and SK_DEFAULT_GPU_FONT_CACHE_LIMIT can be set using -D 23 // on your ompiler commandline, or by using the defines in SkUserConfig.h 24 #ifndef SK_DEFAULT_GPU_FONT_CACHE_COUNT_LIMIT 25 #define SK_DEFAULT_GPU_FONT_CACHE_COUNT_LIMIT 2048 26 #endif 27 28 #ifndef SK_DEFAULT_GPU_FONT_CACHE_LIMIT 29 #define SK_DEFAULT_GPU_FONT_CACHE_LIMIT (2 * 1024 * 1024) 30 #endif 31 32 namespace sktext::gpu { 33 34 class Glyph; 35 class StrikeCache; 36 37 // The TextStrike manages an SkArenaAlloc for Glyphs. The SkStrike is what actually creates 38 // the mask. The TextStrike may outlive the generating SkStrike. However, it retains a copy 39 // of it's SkDescriptor as a key to access (or regenerate) the SkStrike. TextStrikes are 40 // created by and owned by a StrikeCache. 41 class TextStrike : public SkNVRefCnt<TextStrike> { 42 public: 43 TextStrike(StrikeCache* strikeCache, 44 const SkStrikeSpec& strikeSpec); 45 46 Glyph* getGlyph(SkPackedGlyphID); strikeSpec()47 const SkStrikeSpec& strikeSpec() const { return fStrikeSpec; } getDescriptor()48 const SkDescriptor& getDescriptor() const { return fStrikeSpec.descriptor(); } 49 50 private: 51 StrikeCache* const fStrikeCache; 52 53 // Key for retrieving the SkStrike for creating new atlas data. 54 const SkStrikeSpec fStrikeSpec; 55 56 struct HashTraits { 57 static const SkPackedGlyphID& GetKey(const Glyph* glyph); 58 static uint32_t Hash(SkPackedGlyphID key); 59 }; 60 // Map SkPackedGlyphID -> Glyph*. 61 skia_private::THashTable<Glyph*, SkPackedGlyphID, HashTraits> fCache; 62 63 // Store for the glyph information. 64 SkArenaAlloc fAlloc{512}; 65 66 TextStrike* fNext{nullptr}; 67 TextStrike* fPrev{nullptr}; 68 size_t fMemoryUsed{sizeof(TextStrike)}; 69 bool fRemoved{false}; 70 71 friend class StrikeCache; 72 }; 73 74 // StrikeCache manages strikes which are indexed by a SkStrike. These strikes can then be 75 // used to generate individual Glyph Masks. 76 class StrikeCache { 77 public: 78 ~StrikeCache(); 79 80 // The user of the cache may hold a long-lived ref to the returned strike. 81 sk_sp<TextStrike> findOrCreateStrike(const SkStrikeSpec& strikeSpec); 82 83 void freeAll(); 84 85 private: 86 friend class TextStrike; // for TextStrike::getGlyph 87 sk_sp<TextStrike> internalFindStrikeOrNull(const SkDescriptor& desc); 88 sk_sp<TextStrike> generateStrike(const SkStrikeSpec& strikeSpec); 89 90 void internalRemoveStrike(TextStrike* strike); 91 void internalAttachToHead(sk_sp<TextStrike> strike); 92 93 // Checkout budgets, modulated by the specified min-bytes-needed-to-purge, 94 // and attempt to purge caches to match. 95 // Returns number of bytes freed. 96 size_t internalPurge(size_t minBytesNeeded = 0); 97 98 // A simple accounting of what each glyph cache reports and the strike cache total. 99 void validate() const; 100 101 TextStrike* fHead{nullptr}; 102 TextStrike* fTail{nullptr}; 103 104 struct HashTraits { 105 static const SkDescriptor& GetKey(const sk_sp<TextStrike>& strike); 106 static uint32_t Hash(const SkDescriptor& strikeSpec); 107 }; 108 using StrikeHash = skia_private::THashTable<sk_sp<TextStrike>, const SkDescriptor&, HashTraits>; 109 110 StrikeHash fCache; 111 112 size_t fCacheSizeLimit{SK_DEFAULT_GPU_FONT_CACHE_LIMIT}; 113 size_t fTotalMemoryUsed{0}; 114 int32_t fCacheCountLimit{SK_DEFAULT_GPU_FONT_CACHE_COUNT_LIMIT}; 115 int32_t fCacheCount{0}; 116 }; 117 118 } // namespace sktext::gpu 119 120 #endif // sktext_gpu_StrikeCache_DEFINED 121