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 GrTextBlobCache_DEFINED |
9 | #define GrTextBlobCache_DEFINED |
10 | |
11 | #include "include/core/SkRefCnt.h" |
12 | #include "include/private/SkMutex.h" |
13 | #include "include/private/SkTArray.h" |
14 | #include "include/private/SkTHash.h" |
15 | #include "src/core/SkMessageBus.h" |
16 | #include "src/core/SkTextBlobPriv.h" |
17 | #include "src/gpu/text/GrTextBlob.h" |
18 | |
19 | #include <functional> |
20 | |
21 | class GrTextBlobCache { |
22 | public: |
23 | GrTextBlobCache(uint32_t messageBusID); |
24 | |
25 | sk_sp<GrTextBlob> makeCachedBlob(const SkGlyphRunList& glyphRunList, |
26 | const GrTextBlob::Key& key, |
27 | const SkMaskFilterBase::BlurRec& blurRec, |
28 | const SkMatrix& viewMatrix) SK_EXCLUDES(fSpinLock); |
29 | |
30 | sk_sp<GrTextBlob> find(const GrTextBlob::Key& key) SK_EXCLUDES(fSpinLock); |
31 | |
32 | void remove(GrTextBlob* blob) SK_EXCLUDES(fSpinLock); |
33 | |
34 | void freeAll() SK_EXCLUDES(fSpinLock); |
35 | |
36 | struct PurgeBlobMessage { |
37 | PurgeBlobMessage(uint32_t blobID, uint32_t contextUniqueID) |
38 | : fBlobID(blobID), fContextID(contextUniqueID) {} |
39 | |
40 | uint32_t fBlobID; |
41 | uint32_t fContextID; |
42 | }; |
43 | |
44 | static void PostPurgeBlobMessage(uint32_t blobID, uint32_t cacheID); |
45 | |
46 | void purgeStaleBlobs() SK_EXCLUDES(fSpinLock); |
47 | |
48 | size_t usedBytes() const SK_EXCLUDES(fSpinLock); |
49 | |
50 | bool isOverBudget() const SK_EXCLUDES(fSpinLock); |
51 | |
52 | private: |
53 | friend class GrTextBlobTestingPeer; |
54 | using TextBlobList = SkTInternalLList<GrTextBlob>; |
55 | |
56 | struct BlobIDCacheEntry { |
57 | BlobIDCacheEntry(); |
58 | explicit BlobIDCacheEntry(uint32_t id); |
59 | |
60 | static uint32_t GetKey(const BlobIDCacheEntry& entry); |
61 | |
62 | void addBlob(sk_sp<GrTextBlob> blob); |
63 | |
64 | void removeBlob(GrTextBlob* blob); |
65 | |
66 | sk_sp<GrTextBlob> find(const GrTextBlob::Key& key) const; |
67 | |
68 | int findBlobIndex(const GrTextBlob::Key& key) const; |
69 | |
70 | uint32_t fID; |
71 | // Current clients don't generate multiple GrAtlasTextBlobs per SkTextBlob, so an array w/ |
72 | // linear search is acceptable. If usage changes, we should re-evaluate this structure. |
73 | SkSTArray<1, sk_sp<GrTextBlob>> fBlobs; |
74 | }; |
75 | |
76 | void internalPurgeStaleBlobs() SK_REQUIRES(fSpinLock); |
77 | |
78 | void internalAdd(sk_sp<GrTextBlob> blob) SK_REQUIRES(fSpinLock); |
79 | void internalRemove(GrTextBlob* blob) SK_REQUIRES(fSpinLock); |
80 | |
81 | void internalCheckPurge(GrTextBlob* blob = nullptr) SK_REQUIRES(fSpinLock); |
82 | |
83 | static const int kDefaultBudget = 1 << 22; |
84 | |
85 | mutable SkSpinlock fSpinLock; |
86 | TextBlobList fBlobList SK_GUARDED_BY(fSpinLock); |
87 | SkTHashMap<uint32_t, BlobIDCacheEntry> fBlobIDCache SK_GUARDED_BY(fSpinLock); |
88 | size_t fSizeBudget SK_GUARDED_BY(fSpinLock); |
89 | size_t fCurrentSize SK_GUARDED_BY(fSpinLock) {0}; |
90 | |
91 | // In practice 'messageBusID' is always the unique ID of the owning GrContext |
92 | const uint32_t fMessageBusID; |
93 | SkMessageBus<PurgeBlobMessage>::Inbox fPurgeBlobInbox SK_GUARDED_BY(fSpinLock); |
94 | }; |
95 | |
96 | #endif |
97 | |