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