blob: 64941efc96181f48277baf358527150ab3b98cd8 [file] [log] [blame]
joshualittb7133be2015-04-08 09:08:31 -07001/*
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#include "GrTextBlobCache.h"
9
Florin Malita4a01ac92017-03-13 16:45:28 -040010DECLARE_SKMESSAGEBUS_MESSAGE(GrTextBlobCache::PurgeBlobMessage)
11
joshualittb7133be2015-04-08 09:08:31 -070012GrTextBlobCache::~GrTextBlobCache() {
Florin Malitac337c9e2017-03-10 18:02:29 +000013 SkDEBUGCODE(this->freeAll();)
joshualittb7133be2015-04-08 09:08:31 -070014}
15
joshualitt26ffc002015-04-16 11:24:04 -070016void GrTextBlobCache::freeAll() {
Florin Malita33fdb8d2017-03-07 16:51:57 -050017 fBlobIDCache.foreach([this](uint32_t, BlobIDCacheEntry* entry) {
Florin Malitac337c9e2017-03-10 18:02:29 +000018 for (const auto& blob : entry->fBlobs) {
19 fBlobList.remove(blob.get());
Florin Malita33fdb8d2017-03-07 16:51:57 -050020 }
21 });
22
23 fBlobIDCache.reset();
joshualitt20ccd402016-01-05 08:56:56 -080024
25 // There should be no allocations in the memory pool at this point
26 SkASSERT(fPool.isEmpty());
Florin Malita33fdb8d2017-03-07 16:51:57 -050027 SkASSERT(fBlobList.isEmpty());
joshualitt26ffc002015-04-16 11:24:04 -070028}
Florin Malita4a01ac92017-03-13 16:45:28 -040029
Jim Van Verth474d6872017-12-14 13:00:05 -050030void GrTextBlobCache::PostPurgeBlobMessage(uint32_t blobID, uint32_t cacheID) {
31 SkASSERT(blobID != SK_InvalidGenID);
32 SkMessageBus<PurgeBlobMessage>::Post(PurgeBlobMessage({blobID}), cacheID);
Florin Malita4a01ac92017-03-13 16:45:28 -040033}
Jim Van Verth76d917c2017-12-13 09:26:37 -050034
35void GrTextBlobCache::purgeStaleBlobs() {
36 SkTArray<PurgeBlobMessage> msgs;
37 fPurgeBlobInbox.poll(&msgs);
38
39 for (const auto& msg : msgs) {
40 auto* idEntry = fBlobIDCache.find(msg.fID);
41 if (!idEntry) {
42 // no cache entries for id
43 continue;
44 }
45
46 // remove all blob entries from the LRU list
47 for (const auto& blob : idEntry->fBlobs) {
48 fBlobList.remove(blob.get());
49 }
50
51 // drop the idEntry itself (unrefs all blobs)
52 fBlobIDCache.remove(msg.fID);
53 }
54}
55
56void GrTextBlobCache::checkPurge(GrAtlasTextBlob* blob) {
57 // First, purge all stale blob IDs.
58 this->purgeStaleBlobs();
59
60 // If we are still over budget, then unref until we are below budget again
61 if (fPool.size() > fBudget) {
62 BitmapBlobList::Iter iter;
63 iter.init(fBlobList, BitmapBlobList::Iter::kTail_IterStart);
64 GrAtlasTextBlob* lruBlob = nullptr;
65 while (fPool.size() > fBudget && (lruBlob = iter.get()) && lruBlob != blob) {
66 // Backup the iterator before removing and unrefing the blob
67 iter.prev();
68
69 this->remove(lruBlob);
70 }
71
72 // If we break out of the loop with lruBlob == blob, then we haven't purged enough
73 // use the call back and try to free some more. If we are still overbudget after this,
74 // then this single textblob is over our budget
75 if (blob && lruBlob == blob) {
76 (*fCallback)(fData);
77 }
78
79#ifdef SPEW_BUDGET_MESSAGE
80 if (fPool.size() > fBudget) {
81 SkDebugf("Single textblob is larger than our whole budget");
82 }
83#endif
84 }
85}
86
87
88