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 | #include "src/gpu/text/GrTextBlobCache.h" |
9 | |
10 | DECLARE_SKMESSAGEBUS_MESSAGE(GrTextBlobCache::PurgeBlobMessage) |
11 | |
12 | static inline bool SkShouldPostMessageToBus( |
13 | const GrTextBlobCache::PurgeBlobMessage& msg, uint32_t msgBusUniqueID) { |
14 | return msg.fContextID == msgBusUniqueID; |
15 | } |
16 | |
17 | GrTextBlobCache::~GrTextBlobCache() { |
18 | this->freeAll(); |
19 | } |
20 | |
21 | void GrTextBlobCache::freeAll() { |
22 | fBlobIDCache.foreach([this](uint32_t, BlobIDCacheEntry* entry) { |
23 | for (const auto& blob : entry->fBlobs) { |
24 | fBlobList.remove(blob.get()); |
25 | } |
26 | }); |
27 | |
28 | fBlobIDCache.reset(); |
29 | |
30 | fCurrentSize = 0; |
31 | |
32 | // There should be no allocations in the memory pool at this point |
33 | SkASSERT(fBlobList.isEmpty()); |
34 | } |
35 | |
36 | void GrTextBlobCache::PostPurgeBlobMessage(uint32_t blobID, uint32_t cacheID) { |
37 | SkASSERT(blobID != SK_InvalidGenID); |
38 | SkMessageBus<PurgeBlobMessage>::Post(PurgeBlobMessage(blobID, cacheID)); |
39 | } |
40 | |
41 | void GrTextBlobCache::purgeStaleBlobs() { |
42 | SkTArray<PurgeBlobMessage> msgs; |
43 | fPurgeBlobInbox.poll(&msgs); |
44 | |
45 | for (const auto& msg : msgs) { |
46 | auto* idEntry = fBlobIDCache.find(msg.fBlobID); |
47 | if (!idEntry) { |
48 | // no cache entries for id |
49 | continue; |
50 | } |
51 | |
52 | // remove all blob entries from the LRU list |
53 | for (const auto& blob : idEntry->fBlobs) { |
54 | fCurrentSize -= blob->size(); |
55 | fBlobList.remove(blob.get()); |
56 | } |
57 | |
58 | // drop the idEntry itself (unrefs all blobs) |
59 | fBlobIDCache.remove(msg.fBlobID); |
60 | } |
61 | } |
62 | |
63 | void GrTextBlobCache::checkPurge(GrTextBlob* blob) { |
64 | // First, purge all stale blob IDs. |
65 | this->purgeStaleBlobs(); |
66 | |
67 | // If we are still over budget, then unref until we are below budget again |
68 | if (fCurrentSize > fSizeBudget) { |
69 | BitmapBlobList::Iter iter; |
70 | iter.init(fBlobList, BitmapBlobList::Iter::kTail_IterStart); |
71 | GrTextBlob* lruBlob = nullptr; |
72 | while (fCurrentSize > fSizeBudget && (lruBlob = iter.get()) && lruBlob != blob) { |
73 | // Backup the iterator before removing and unrefing the blob |
74 | iter.prev(); |
75 | |
76 | this->remove(lruBlob); |
77 | } |
78 | |
79 | // If we break out of the loop with lruBlob == blob, then we haven't purged enough |
80 | // use the call back and try to free some more. If we are still overbudget after this, |
81 | // then this single textblob is over our budget |
82 | if (blob && lruBlob == blob) { |
83 | (*fCallback)(fData); |
84 | } |
85 | |
86 | #ifdef SPEW_BUDGET_MESSAGE |
87 | if (fCurrentSize > fSizeBudget) { |
88 | SkDebugf("Single textblob is larger than our whole budget"); |
89 | } |
90 | #endif |
91 | } |
92 | } |
93 | |
94 | |
95 | |
96 |