xref: /aosp_15_r20/external/skia/src/text/gpu/StrikeCache.h (revision c8dee2aa9b3f27cf6c858bd81872bdeb2c07ed17)
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