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