• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 GrTextBlobRedrawCoordinator_DEFINED
9 #define GrTextBlobRedrawCoordinator_DEFINED
10 
11 #include "include/core/SkRefCnt.h"
12 #include "include/private/SkSpinlock.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 // GrTextBlobRedrawCoordinator reuses data from previous drawing operations using multiple criteria
22 // to pick the best data for the draw. In addition, it provides a central service for managing
23 // resource usage through a messageBus.
24 // The draw data is stored in a three-tiered system. The first tier is keyed by the SkTextBlob's
25 // uniqueID. The second tier uses the GrTextBlob's key to get a general match for the draw. The
26 // last tier queries each sub run using canReuse to determine if each sub run can handle the
27 // drawing parameters.
28 class GrTextBlobRedrawCoordinator {
29 public:
30     GrTextBlobRedrawCoordinator(uint32_t messageBusID);
31 
32     void drawGlyphRunList(SkCanvas* canvas,
33                           const GrClip* clip,
34                           const SkMatrixProvider& viewMatrix,
35                           const SkGlyphRunList& glyphRunList,
36                           const SkPaint& paint,
37                           skgpu::v1::SurfaceDrawContext* sdc);
38 
39     void freeAll() SK_EXCLUDES(fSpinLock);
40 
41     struct PurgeBlobMessage {
PurgeBlobMessagePurgeBlobMessage42         PurgeBlobMessage(uint32_t blobID, uint32_t contextUniqueID)
43                 : fBlobID(blobID), fContextID(contextUniqueID) {}
44 
45         uint32_t fBlobID;
46         uint32_t fContextID;
47     };
48 
49     static void PostPurgeBlobMessage(uint32_t blobID, uint32_t cacheID);
50 
51     void purgeStaleBlobs() SK_EXCLUDES(fSpinLock);
52 
53     size_t usedBytes() const SK_EXCLUDES(fSpinLock);
54 
55     bool isOverBudget() const SK_EXCLUDES(fSpinLock);
56 
57 private:
58     friend class GrTextBlobTestingPeer;
59     using TextBlobList = SkTInternalLList<GrTextBlob>;
60 
61     struct BlobIDCacheEntry {
62         BlobIDCacheEntry();
63         explicit BlobIDCacheEntry(uint32_t id);
64 
65         static uint32_t GetKey(const BlobIDCacheEntry& entry);
66 
67         void addBlob(sk_sp<GrTextBlob> blob);
68 
69         void removeBlob(GrTextBlob* blob);
70 
71         sk_sp<GrTextBlob> find(const GrTextBlob::Key& key) const;
72 
73         int findBlobIndex(const GrTextBlob::Key& key) const;
74 
75         uint32_t fID;
76         // Current clients don't generate multiple GrAtlasTextBlobs per SkTextBlob, so an array w/
77         // linear search is acceptable.  If usage changes, we should re-evaluate this structure.
78         SkSTArray<1, sk_sp<GrTextBlob>> fBlobs;
79     };
80 
81     // If not already in the cache, then add it else, return the text blob from the cache.
82     sk_sp<GrTextBlob> addOrReturnExisting(
83             const SkGlyphRunList& glyphRunList, sk_sp<GrTextBlob> blob) SK_EXCLUDES(fSpinLock);
84 
85     sk_sp<GrTextBlob> find(const GrTextBlob::Key& key) SK_EXCLUDES(fSpinLock);
86 
87     void remove(GrTextBlob* blob) SK_EXCLUDES(fSpinLock);
88 
89     void internalPurgeStaleBlobs() SK_REQUIRES(fSpinLock);
90 
91     sk_sp<GrTextBlob> internalAdd(sk_sp<GrTextBlob> blob) SK_REQUIRES(fSpinLock);
92     void internalRemove(GrTextBlob* blob) SK_REQUIRES(fSpinLock);
93 
94     void internalCheckPurge(GrTextBlob* blob = nullptr) SK_REQUIRES(fSpinLock);
95 
96     static const int kDefaultBudget = 1 << 22;
97 
98     mutable SkSpinlock fSpinLock;
99     TextBlobList fBlobList SK_GUARDED_BY(fSpinLock);
100     SkTHashMap<uint32_t, BlobIDCacheEntry> fBlobIDCache SK_GUARDED_BY(fSpinLock);
101     size_t fSizeBudget SK_GUARDED_BY(fSpinLock);
SK_GUARDED_BY(fSpinLock)102     size_t fCurrentSize SK_GUARDED_BY(fSpinLock) {0};
103 
104     // In practice 'messageBusID' is always the unique ID of the owning GrContext
105     const uint32_t fMessageBusID;
106     SkMessageBus<PurgeBlobMessage, uint32_t>::Inbox fPurgeBlobInbox SK_GUARDED_BY(fSpinLock);
107 };
108 #endif  // GrTextBlobRedrawCoordinator_DEFINED
109