blob: 88cbaeb2c7695ad7f989e5746af0593630ba94b8 [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() {
Robert Phillips303cd582018-02-14 18:54:01 -050013 this->freeAll();
14 delete fPool;
joshualittb7133be2015-04-08 09:08:31 -070015}
16
joshualitt26ffc002015-04-16 11:24:04 -070017void GrTextBlobCache::freeAll() {
Florin Malita33fdb8d2017-03-07 16:51:57 -050018 fBlobIDCache.foreach([this](uint32_t, BlobIDCacheEntry* entry) {
Florin Malitac337c9e2017-03-10 18:02:29 +000019 for (const auto& blob : entry->fBlobs) {
20 fBlobList.remove(blob.get());
Florin Malita33fdb8d2017-03-07 16:51:57 -050021 }
22 });
23
24 fBlobIDCache.reset();
joshualitt20ccd402016-01-05 08:56:56 -080025
26 // There should be no allocations in the memory pool at this point
Robert Phillips303cd582018-02-14 18:54:01 -050027 SkASSERT(!fPool || fPool->isEmpty());
Florin Malita33fdb8d2017-03-07 16:51:57 -050028 SkASSERT(fBlobList.isEmpty());
joshualitt26ffc002015-04-16 11:24:04 -070029}
Florin Malita4a01ac92017-03-13 16:45:28 -040030
Jim Van Verth474d6872017-12-14 13:00:05 -050031void GrTextBlobCache::PostPurgeBlobMessage(uint32_t blobID, uint32_t cacheID) {
32 SkASSERT(blobID != SK_InvalidGenID);
33 SkMessageBus<PurgeBlobMessage>::Post(PurgeBlobMessage({blobID}), cacheID);
Florin Malita4a01ac92017-03-13 16:45:28 -040034}
Jim Van Verth76d917c2017-12-13 09:26:37 -050035
36void GrTextBlobCache::purgeStaleBlobs() {
37 SkTArray<PurgeBlobMessage> msgs;
38 fPurgeBlobInbox.poll(&msgs);
39
40 for (const auto& msg : msgs) {
41 auto* idEntry = fBlobIDCache.find(msg.fID);
42 if (!idEntry) {
43 // no cache entries for id
44 continue;
45 }
46
47 // remove all blob entries from the LRU list
48 for (const auto& blob : idEntry->fBlobs) {
49 fBlobList.remove(blob.get());
50 }
51
52 // drop the idEntry itself (unrefs all blobs)
53 fBlobIDCache.remove(msg.fID);
54 }
55}
56
Robert Phillips303cd582018-02-14 18:54:01 -050057bool GrTextBlobCache::overBudget() const {
58 if (fPool) {
59 return fPool->size() > fBudget;
60 }
61
62 // When DDLs are being recorded no GrAtlasTextBlob will be deleted so the cache budget is
63 // somewhat meaningless.
64 return false;
65}
66
Jim Van Verth76d917c2017-12-13 09:26:37 -050067void GrTextBlobCache::checkPurge(GrAtlasTextBlob* blob) {
68 // First, purge all stale blob IDs.
69 this->purgeStaleBlobs();
70
71 // If we are still over budget, then unref until we are below budget again
Robert Phillips303cd582018-02-14 18:54:01 -050072 if (this->overBudget()) {
Jim Van Verth76d917c2017-12-13 09:26:37 -050073 BitmapBlobList::Iter iter;
74 iter.init(fBlobList, BitmapBlobList::Iter::kTail_IterStart);
75 GrAtlasTextBlob* lruBlob = nullptr;
Robert Phillips303cd582018-02-14 18:54:01 -050076 while (this->overBudget() && (lruBlob = iter.get()) && lruBlob != blob) {
Jim Van Verth76d917c2017-12-13 09:26:37 -050077 // Backup the iterator before removing and unrefing the blob
78 iter.prev();
79
80 this->remove(lruBlob);
81 }
82
83 // If we break out of the loop with lruBlob == blob, then we haven't purged enough
84 // use the call back and try to free some more. If we are still overbudget after this,
85 // then this single textblob is over our budget
86 if (blob && lruBlob == blob) {
87 (*fCallback)(fData);
88 }
89
90#ifdef SPEW_BUDGET_MESSAGE
Robert Phillips303cd582018-02-14 18:54:01 -050091 if (this->overBudget()) {
Jim Van Verth76d917c2017-12-13 09:26:37 -050092 SkDebugf("Single textblob is larger than our whole budget");
93 }
94#endif
95 }
96}
97
98
99