Coverage Report

Created: 2021-08-22 09:07

/src/skia/src/core/SkStrikeCache.h
Line
Count
Source (jump to first uncovered line)
1
/*
2
 * Copyright 2010 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 SkStrikeCache_DEFINED
9
#define SkStrikeCache_DEFINED
10
11
#include <unordered_map>
12
#include <unordered_set>
13
14
#include "include/private/SkSpinlock.h"
15
#include "include/private/SkTemplates.h"
16
#include "src/core/SkDescriptor.h"
17
#include "src/core/SkScalerCache.h"
18
19
class SkTraceMemoryDump;
20
21
#ifndef SK_DEFAULT_FONT_CACHE_COUNT_LIMIT
22
    #define SK_DEFAULT_FONT_CACHE_COUNT_LIMIT   2048
23
#endif
24
25
#ifndef SK_DEFAULT_FONT_CACHE_LIMIT
26
    #define SK_DEFAULT_FONT_CACHE_LIMIT     (2 * 1024 * 1024)
27
#endif
28
29
///////////////////////////////////////////////////////////////////////////////
30
31
class SkStrikePinner {
32
public:
33
0
    virtual ~SkStrikePinner() = default;
34
    virtual bool canDelete() = 0;
35
};
36
37
class SkStrikeCache final : public SkStrikeForGPUCacheInterface {
38
public:
39
18
    SkStrikeCache() = default;
40
41
    class Strike final : public SkRefCnt, public SkStrikeForGPU {
42
    public:
43
        Strike(SkStrikeCache* strikeCache,
44
               const SkDescriptor& desc,
45
               std::unique_ptr<SkScalerContext> scaler,
46
               const SkFontMetrics* metrics,
47
               std::unique_ptr<SkStrikePinner> pinner)
48
                : fStrikeCache{strikeCache}
49
                , fScalerCache{desc, std::move(scaler), metrics}
50
16.0k
                , fPinner{std::move(pinner)} {}
51
52
0
        SkGlyph* mergeGlyphAndImage(SkPackedGlyphID toID, const SkGlyph& from) {
53
0
            auto [glyph, increase] = fScalerCache.mergeGlyphAndImage(toID, from);
54
0
            this->updateDelta(increase);
55
0
            return glyph;
56
0
        }
57
58
0
        const SkPath* mergePath(SkGlyph* glyph, const SkPath* path) {
59
0
            auto [glyphPath, increase] = fScalerCache.mergePath(glyph, path);
60
0
            this->updateDelta(increase);
61
0
            return glyphPath;
62
0
        }
63
64
0
        SkScalerContext* getScalerContext() const {
65
0
            return fScalerCache.getScalerContext();
66
0
        }
67
68
        void findIntercepts(const SkScalar bounds[2], SkScalar scale, SkScalar xPos,
69
0
                            SkGlyph* glyph, SkScalar* array, int* count) {
70
0
            fScalerCache.findIntercepts(bounds, scale, xPos, glyph, array, count);
71
0
        }
72
73
4.02k
        const SkFontMetrics& getFontMetrics() const {
74
4.02k
            return fScalerCache.getFontMetrics();
75
4.02k
        }
76
77
        SkSpan<const SkGlyph*> metrics(SkSpan<const SkGlyphID> glyphIDs,
78
9.62M
                                       const SkGlyph* results[]) {
79
9.62M
            auto [glyphs, increase] = fScalerCache.metrics(glyphIDs, results);
80
9.62M
            this->updateDelta(increase);
81
9.62M
            return glyphs;
82
9.62M
        }
83
84
        SkSpan<const SkGlyph*> preparePaths(SkSpan<const SkGlyphID> glyphIDs,
85
53.6k
                                            const SkGlyph* results[]) {
86
53.6k
            auto [glyphs, increase] = fScalerCache.preparePaths(glyphIDs, results);
87
53.6k
            this->updateDelta(increase);
88
53.6k
            return glyphs;
89
53.6k
        }
90
91
        SkSpan<const SkGlyph*> prepareImages(SkSpan<const SkPackedGlyphID> glyphIDs,
92
715
                                             const SkGlyph* results[]) {
93
715
            auto [glyphs, increase] = fScalerCache.prepareImages(glyphIDs, results);
94
715
            this->updateDelta(increase);
95
715
            return glyphs;
96
715
        }
97
98
155k
        void prepareForDrawingMasksCPU(SkDrawableGlyphBuffer* drawables) {
99
155k
            size_t increase = fScalerCache.prepareForDrawingMasksCPU(drawables);
100
155k
            this->updateDelta(increase);
101
155k
        }
102
103
157k
        const SkGlyphPositionRoundingSpec& roundingSpec() const override {
104
157k
            return fScalerCache.roundingSpec();
105
157k
        }
106
107
10.3M
        const SkDescriptor& getDescriptor() const override {
108
10.3M
            return fScalerCache.getDescriptor();
109
10.3M
        }
110
111
        void prepareForMaskDrawing(
112
1.26k
                SkDrawableGlyphBuffer* drawbles, SkSourceGlyphBuffer* rejects) override {
113
1.26k
            size_t increase = fScalerCache.prepareForMaskDrawing(drawbles, rejects);
114
1.26k
            this->updateDelta(increase);
115
1.26k
        }
116
117
        void prepareForSDFTDrawing(
118
132
                SkDrawableGlyphBuffer* drawbles, SkSourceGlyphBuffer* rejects) override {
119
132
            size_t increase = fScalerCache.prepareForSDFTDrawing(drawbles, rejects);
120
132
            this->updateDelta(increase);
121
132
        }
122
123
        void prepareForPathDrawing(
124
56.7k
                SkDrawableGlyphBuffer* drawbles, SkSourceGlyphBuffer* rejects) override {
125
56.7k
            size_t increase = fScalerCache.prepareForPathDrawing(drawbles, rejects);
126
56.7k
            this->updateDelta(increase);
127
56.7k
        }
128
129
5.31k
        void onAboutToExitScope() override {
130
5.31k
            this->unref();
131
5.31k
        }
132
133
        void updateDelta(size_t increase);
134
135
        SkStrikeCache* const            fStrikeCache;
136
        Strike*                         fNext{nullptr};
137
        Strike*                         fPrev{nullptr};
138
        SkScalerCache                   fScalerCache;
139
        std::unique_ptr<SkStrikePinner> fPinner;
140
        size_t                          fMemoryUsed{sizeof(SkScalerCache)};
141
        bool                            fRemoved{false};
142
    };  // Strike
143
144
    static SkStrikeCache* GlobalStrikeCache();
145
146
    sk_sp<Strike> findStrike(const SkDescriptor& desc) SK_EXCLUDES(fLock);
147
148
    sk_sp<Strike> createStrike(
149
            const SkDescriptor& desc,
150
            std::unique_ptr<SkScalerContext> scaler,
151
            SkFontMetrics* maybeMetrics = nullptr,
152
            std::unique_ptr<SkStrikePinner> = nullptr) SK_EXCLUDES(fLock);
153
154
    sk_sp<Strike> findOrCreateStrike(
155
            const SkDescriptor& desc,
156
            const SkScalerContextEffects& effects,
157
            const SkTypeface& typeface) SK_EXCLUDES(fLock);
158
159
    SkScopedStrikeForGPU findOrCreateScopedStrike(
160
            const SkDescriptor& desc,
161
            const SkScalerContextEffects& effects,
162
            const SkTypeface& typeface) override SK_EXCLUDES(fLock);
163
164
    static void PurgeAll();
165
    static void Dump();
166
167
    // Dump memory usage statistics of all the attaches caches in the process using the
168
    // SkTraceMemoryDump interface.
169
    static void DumpMemoryStatistics(SkTraceMemoryDump* dump);
170
171
    void purgeAll() SK_EXCLUDES(fLock); // does not change budget
172
173
    int getCacheCountLimit() const SK_EXCLUDES(fLock);
174
    int setCacheCountLimit(int limit) SK_EXCLUDES(fLock);
175
    int getCacheCountUsed() const SK_EXCLUDES(fLock);
176
177
    size_t getCacheSizeLimit() const SK_EXCLUDES(fLock);
178
    size_t setCacheSizeLimit(size_t limit) SK_EXCLUDES(fLock);
179
    size_t getTotalMemoryUsed() const SK_EXCLUDES(fLock);
180
181
private:
182
    sk_sp<Strike> internalFindStrikeOrNull(const SkDescriptor& desc) SK_REQUIRES(fLock);
183
    sk_sp<Strike> internalCreateStrike(
184
            const SkDescriptor& desc,
185
            std::unique_ptr<SkScalerContext> scaler,
186
            SkFontMetrics* maybeMetrics = nullptr,
187
            std::unique_ptr<SkStrikePinner> = nullptr) SK_REQUIRES(fLock);
188
189
    // The following methods can only be called when mutex is already held.
190
    void internalRemoveStrike(Strike* strike) SK_REQUIRES(fLock);
191
    void internalAttachToHead(sk_sp<Strike> strike) SK_REQUIRES(fLock);
192
193
    // Checkout budgets, modulated by the specified min-bytes-needed-to-purge,
194
    // and attempt to purge caches to match.
195
    // Returns number of bytes freed.
196
    size_t internalPurge(size_t minBytesNeeded = 0) SK_REQUIRES(fLock);
197
198
    // A simple accounting of what each glyph cache reports and the strike cache total.
199
    void validate() const SK_REQUIRES(fLock);
200
201
    void forEachStrike(std::function<void(const Strike&)> visitor) const SK_EXCLUDES(fLock);
202
203
    mutable SkMutex fLock;
204
    Strike* fHead SK_GUARDED_BY(fLock) {nullptr};
205
    Strike* fTail SK_GUARDED_BY(fLock) {nullptr};
206
    struct StrikeTraits {
207
402k
        static const SkDescriptor& GetKey(const sk_sp<Strike>& strike) {
208
402k
            return strike->getDescriptor();
209
402k
        }
210
418k
        static uint32_t Hash(const SkDescriptor& descriptor) {
211
418k
            return descriptor.getChecksum();
212
418k
        }
213
    };
214
    SkTHashTable<sk_sp<Strike>, SkDescriptor, StrikeTraits> fStrikeLookup SK_GUARDED_BY(fLock);
215
216
    size_t  fCacheSizeLimit{SK_DEFAULT_FONT_CACHE_LIMIT};
217
    size_t  fTotalMemoryUsed SK_GUARDED_BY(fLock) {0};
218
    int32_t fCacheCountLimit{SK_DEFAULT_FONT_CACHE_COUNT_LIMIT};
219
    int32_t fCacheCount SK_GUARDED_BY(fLock) {0};
220
};
221
222
using SkStrike = SkStrikeCache::Strike;
223
224
#endif  // SkStrikeCache_DEFINED