1cb93a386Sopenharmony_ci/* 2cb93a386Sopenharmony_ci * Copyright 2015 Google Inc. 3cb93a386Sopenharmony_ci * 4cb93a386Sopenharmony_ci * Use of this source code is governed by a BSD-style license that can be 5cb93a386Sopenharmony_ci * found in the LICENSE file. 6cb93a386Sopenharmony_ci */ 7cb93a386Sopenharmony_ci 8cb93a386Sopenharmony_ci#include "src/gpu/text/GrTextBlobCache.h" 9cb93a386Sopenharmony_ci 10cb93a386Sopenharmony_ciDECLARE_SKMESSAGEBUS_MESSAGE(GrTextBlobCache::PurgeBlobMessage, uint32_t, true) 11cb93a386Sopenharmony_ci 12cb93a386Sopenharmony_ci// This function is captured by the above macro using implementations from SkMessageBus.h 13cb93a386Sopenharmony_cistatic inline bool SkShouldPostMessageToBus( 14cb93a386Sopenharmony_ci const GrTextBlobCache::PurgeBlobMessage& msg, uint32_t msgBusUniqueID) { 15cb93a386Sopenharmony_ci return msg.fContextID == msgBusUniqueID; 16cb93a386Sopenharmony_ci} 17cb93a386Sopenharmony_ci 18cb93a386Sopenharmony_ciGrTextBlobCache::GrTextBlobCache(uint32_t messageBusID) 19cb93a386Sopenharmony_ci : fSizeBudget(kDefaultBudget) 20cb93a386Sopenharmony_ci , fMessageBusID(messageBusID) 21cb93a386Sopenharmony_ci , fPurgeBlobInbox(messageBusID) { } 22cb93a386Sopenharmony_ci 23cb93a386Sopenharmony_cisk_sp<GrTextBlob> GrTextBlobCache::addOrReturnExisting( 24cb93a386Sopenharmony_ci const SkGlyphRunList& glyphRunList, sk_sp<GrTextBlob> blob) { 25cb93a386Sopenharmony_ci SkAutoSpinlock lock{fSpinLock}; 26cb93a386Sopenharmony_ci blob = this->internalAdd(std::move(blob)); 27cb93a386Sopenharmony_ci glyphRunList.temporaryShuntBlobNotifyAddedToCache(fMessageBusID); 28cb93a386Sopenharmony_ci return blob; 29cb93a386Sopenharmony_ci} 30cb93a386Sopenharmony_ci 31cb93a386Sopenharmony_cisk_sp<GrTextBlob> GrTextBlobCache::find(const GrTextBlob::Key& key) { 32cb93a386Sopenharmony_ci SkAutoSpinlock lock{fSpinLock}; 33cb93a386Sopenharmony_ci const BlobIDCacheEntry* idEntry = fBlobIDCache.find(key.fUniqueID); 34cb93a386Sopenharmony_ci if (idEntry == nullptr) { 35cb93a386Sopenharmony_ci return nullptr; 36cb93a386Sopenharmony_ci } 37cb93a386Sopenharmony_ci 38cb93a386Sopenharmony_ci sk_sp<GrTextBlob> blob = idEntry->find(key); 39cb93a386Sopenharmony_ci GrTextBlob* blobPtr = blob.get(); 40cb93a386Sopenharmony_ci if (blobPtr != nullptr && blobPtr != fBlobList.head()) { 41cb93a386Sopenharmony_ci fBlobList.remove(blobPtr); 42cb93a386Sopenharmony_ci fBlobList.addToHead(blobPtr); 43cb93a386Sopenharmony_ci } 44cb93a386Sopenharmony_ci return blob; 45cb93a386Sopenharmony_ci} 46cb93a386Sopenharmony_ci 47cb93a386Sopenharmony_civoid GrTextBlobCache::remove(GrTextBlob* blob) { 48cb93a386Sopenharmony_ci SkAutoSpinlock lock{fSpinLock}; 49cb93a386Sopenharmony_ci this->internalRemove(blob); 50cb93a386Sopenharmony_ci} 51cb93a386Sopenharmony_ci 52cb93a386Sopenharmony_civoid GrTextBlobCache::internalRemove(GrTextBlob* blob) { 53cb93a386Sopenharmony_ci auto id = blob->key().fUniqueID; 54cb93a386Sopenharmony_ci auto* idEntry = fBlobIDCache.find(id); 55cb93a386Sopenharmony_ci 56cb93a386Sopenharmony_ci if (idEntry != nullptr) { 57cb93a386Sopenharmony_ci sk_sp<GrTextBlob> stillExists = idEntry->find(blob->key()); 58cb93a386Sopenharmony_ci if (blob == stillExists.get()) { 59cb93a386Sopenharmony_ci fCurrentSize -= blob->size(); 60cb93a386Sopenharmony_ci fBlobList.remove(blob); 61cb93a386Sopenharmony_ci idEntry->removeBlob(blob); 62cb93a386Sopenharmony_ci if (idEntry->fBlobs.empty()) { 63cb93a386Sopenharmony_ci fBlobIDCache.remove(id); 64cb93a386Sopenharmony_ci } 65cb93a386Sopenharmony_ci } 66cb93a386Sopenharmony_ci } 67cb93a386Sopenharmony_ci} 68cb93a386Sopenharmony_ci 69cb93a386Sopenharmony_civoid GrTextBlobCache::freeAll() { 70cb93a386Sopenharmony_ci SkAutoSpinlock lock{fSpinLock}; 71cb93a386Sopenharmony_ci fBlobIDCache.reset(); 72cb93a386Sopenharmony_ci fBlobList.reset(); 73cb93a386Sopenharmony_ci fCurrentSize = 0; 74cb93a386Sopenharmony_ci} 75cb93a386Sopenharmony_ci 76cb93a386Sopenharmony_civoid GrTextBlobCache::PostPurgeBlobMessage(uint32_t blobID, uint32_t cacheID) { 77cb93a386Sopenharmony_ci SkASSERT(blobID != SK_InvalidGenID); 78cb93a386Sopenharmony_ci SkMessageBus<PurgeBlobMessage, uint32_t>::Post(PurgeBlobMessage(blobID, cacheID)); 79cb93a386Sopenharmony_ci} 80cb93a386Sopenharmony_ci 81cb93a386Sopenharmony_civoid GrTextBlobCache::purgeStaleBlobs() { 82cb93a386Sopenharmony_ci SkAutoSpinlock lock{fSpinLock}; 83cb93a386Sopenharmony_ci this->internalPurgeStaleBlobs(); 84cb93a386Sopenharmony_ci} 85cb93a386Sopenharmony_ci 86cb93a386Sopenharmony_civoid GrTextBlobCache::internalPurgeStaleBlobs() { 87cb93a386Sopenharmony_ci SkTArray<PurgeBlobMessage> msgs; 88cb93a386Sopenharmony_ci fPurgeBlobInbox.poll(&msgs); 89cb93a386Sopenharmony_ci 90cb93a386Sopenharmony_ci for (const auto& msg : msgs) { 91cb93a386Sopenharmony_ci auto* idEntry = fBlobIDCache.find(msg.fBlobID); 92cb93a386Sopenharmony_ci if (!idEntry) { 93cb93a386Sopenharmony_ci // no cache entries for id 94cb93a386Sopenharmony_ci continue; 95cb93a386Sopenharmony_ci } 96cb93a386Sopenharmony_ci 97cb93a386Sopenharmony_ci // remove all blob entries from the LRU list 98cb93a386Sopenharmony_ci for (const auto& blob : idEntry->fBlobs) { 99cb93a386Sopenharmony_ci fCurrentSize -= blob->size(); 100cb93a386Sopenharmony_ci fBlobList.remove(blob.get()); 101cb93a386Sopenharmony_ci } 102cb93a386Sopenharmony_ci 103cb93a386Sopenharmony_ci // drop the idEntry itself (unrefs all blobs) 104cb93a386Sopenharmony_ci fBlobIDCache.remove(msg.fBlobID); 105cb93a386Sopenharmony_ci } 106cb93a386Sopenharmony_ci} 107cb93a386Sopenharmony_ci 108cb93a386Sopenharmony_cisize_t GrTextBlobCache::usedBytes() const { 109cb93a386Sopenharmony_ci SkAutoSpinlock lock{fSpinLock}; 110cb93a386Sopenharmony_ci return fCurrentSize; 111cb93a386Sopenharmony_ci} 112cb93a386Sopenharmony_ci 113cb93a386Sopenharmony_cibool GrTextBlobCache::isOverBudget() const { 114cb93a386Sopenharmony_ci SkAutoSpinlock lock{fSpinLock}; 115cb93a386Sopenharmony_ci return fCurrentSize > fSizeBudget; 116cb93a386Sopenharmony_ci} 117cb93a386Sopenharmony_ci 118cb93a386Sopenharmony_civoid GrTextBlobCache::internalCheckPurge(GrTextBlob* blob) { 119cb93a386Sopenharmony_ci // First, purge all stale blob IDs. 120cb93a386Sopenharmony_ci this->internalPurgeStaleBlobs(); 121cb93a386Sopenharmony_ci 122cb93a386Sopenharmony_ci // If we are still over budget, then unref until we are below budget again 123cb93a386Sopenharmony_ci if (fCurrentSize > fSizeBudget) { 124cb93a386Sopenharmony_ci TextBlobList::Iter iter; 125cb93a386Sopenharmony_ci iter.init(fBlobList, TextBlobList::Iter::kTail_IterStart); 126cb93a386Sopenharmony_ci GrTextBlob* lruBlob = nullptr; 127cb93a386Sopenharmony_ci while (fCurrentSize > fSizeBudget && (lruBlob = iter.get()) && lruBlob != blob) { 128cb93a386Sopenharmony_ci // Backup the iterator before removing and unrefing the blob 129cb93a386Sopenharmony_ci iter.prev(); 130cb93a386Sopenharmony_ci 131cb93a386Sopenharmony_ci this->internalRemove(lruBlob); 132cb93a386Sopenharmony_ci } 133cb93a386Sopenharmony_ci 134cb93a386Sopenharmony_ci #ifdef SPEW_BUDGET_MESSAGE 135cb93a386Sopenharmony_ci if (fCurrentSize > fSizeBudget) { 136cb93a386Sopenharmony_ci SkDebugf("Single textblob is larger than our whole budget"); 137cb93a386Sopenharmony_ci } 138cb93a386Sopenharmony_ci #endif 139cb93a386Sopenharmony_ci } 140cb93a386Sopenharmony_ci} 141cb93a386Sopenharmony_ci 142cb93a386Sopenharmony_cisk_sp<GrTextBlob> GrTextBlobCache::internalAdd(sk_sp<GrTextBlob> blob) { 143cb93a386Sopenharmony_ci auto id = blob->key().fUniqueID; 144cb93a386Sopenharmony_ci auto* idEntry = fBlobIDCache.find(id); 145cb93a386Sopenharmony_ci if (!idEntry) { 146cb93a386Sopenharmony_ci idEntry = fBlobIDCache.set(id, BlobIDCacheEntry(id)); 147cb93a386Sopenharmony_ci } 148cb93a386Sopenharmony_ci 149cb93a386Sopenharmony_ci if (sk_sp<GrTextBlob> alreadyIn = idEntry->find(blob->key()); alreadyIn) { 150cb93a386Sopenharmony_ci blob = std::move(alreadyIn); 151cb93a386Sopenharmony_ci } else { 152cb93a386Sopenharmony_ci fBlobList.addToHead(blob.get()); 153cb93a386Sopenharmony_ci fCurrentSize += blob->size(); 154cb93a386Sopenharmony_ci idEntry->addBlob(blob); 155cb93a386Sopenharmony_ci } 156cb93a386Sopenharmony_ci 157cb93a386Sopenharmony_ci this->internalCheckPurge(blob.get()); 158cb93a386Sopenharmony_ci return blob; 159cb93a386Sopenharmony_ci} 160cb93a386Sopenharmony_ci 161cb93a386Sopenharmony_ciGrTextBlobCache::BlobIDCacheEntry::BlobIDCacheEntry() : fID(SK_InvalidGenID) {} 162cb93a386Sopenharmony_ci 163cb93a386Sopenharmony_ciGrTextBlobCache::BlobIDCacheEntry::BlobIDCacheEntry(uint32_t id) : fID(id) {} 164cb93a386Sopenharmony_ci 165cb93a386Sopenharmony_ciuint32_t GrTextBlobCache::BlobIDCacheEntry::GetKey(const GrTextBlobCache::BlobIDCacheEntry& entry) { 166cb93a386Sopenharmony_ci return entry.fID; 167cb93a386Sopenharmony_ci} 168cb93a386Sopenharmony_ci 169cb93a386Sopenharmony_civoid GrTextBlobCache::BlobIDCacheEntry::addBlob(sk_sp<GrTextBlob> blob) { 170cb93a386Sopenharmony_ci SkASSERT(blob); 171cb93a386Sopenharmony_ci SkASSERT(blob->key().fUniqueID == fID); 172cb93a386Sopenharmony_ci SkASSERT(!this->find(blob->key())); 173cb93a386Sopenharmony_ci 174cb93a386Sopenharmony_ci fBlobs.emplace_back(std::move(blob)); 175cb93a386Sopenharmony_ci} 176cb93a386Sopenharmony_ci 177cb93a386Sopenharmony_civoid GrTextBlobCache::BlobIDCacheEntry::removeBlob(GrTextBlob* blob) { 178cb93a386Sopenharmony_ci SkASSERT(blob); 179cb93a386Sopenharmony_ci SkASSERT(blob->key().fUniqueID == fID); 180cb93a386Sopenharmony_ci 181cb93a386Sopenharmony_ci auto index = this->findBlobIndex(blob->key()); 182cb93a386Sopenharmony_ci SkASSERT(index >= 0); 183cb93a386Sopenharmony_ci 184cb93a386Sopenharmony_ci fBlobs.removeShuffle(index); 185cb93a386Sopenharmony_ci} 186cb93a386Sopenharmony_ci 187cb93a386Sopenharmony_cisk_sp<GrTextBlob> GrTextBlobCache::BlobIDCacheEntry::find(const GrTextBlob::Key& key) const { 188cb93a386Sopenharmony_ci auto index = this->findBlobIndex(key); 189cb93a386Sopenharmony_ci return index < 0 ? nullptr : fBlobs[index]; 190cb93a386Sopenharmony_ci} 191cb93a386Sopenharmony_ci 192cb93a386Sopenharmony_ciint GrTextBlobCache::BlobIDCacheEntry::findBlobIndex(const GrTextBlob::Key& key) const { 193cb93a386Sopenharmony_ci for (int i = 0; i < fBlobs.count(); ++i) { 194cb93a386Sopenharmony_ci if (fBlobs[i]->key() == key) { 195cb93a386Sopenharmony_ci return i; 196cb93a386Sopenharmony_ci } 197cb93a386Sopenharmony_ci } 198cb93a386Sopenharmony_ci return -1; 199cb93a386Sopenharmony_ci} 200