Flutter Engine
The Flutter Engine
Loading...
Searching...
No Matches
ProxyCache.cpp
Go to the documentation of this file.
1/*
2 * Copyright 2023 Google LLC
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
9
13#include "src/core/SkMipmap.h"
14#include "src/gpu/ResourceKey.h"
19
20using namespace skia_private;
21
23 /* AllowCopyableMessage= */ true)
24
25namespace {
26
27void make_bitmap_key(skgpu::UniqueKey* key, const SkBitmap& bm, skgpu::Mipmapped mipmapped) {
29
30 SkIPoint origin = bm.pixelRefOrigin();
31 SkIRect subset = SkIRect::MakePtSize(origin, bm.dimensions());
32
33 static const skgpu::UniqueKey::Domain kProxyCacheDomain = skgpu::UniqueKey::GenerateDomain();
34 skgpu::UniqueKey::Builder builder(key, kProxyCacheDomain, 6, "ProxyCache");
35 builder[0] = bm.pixelRef()->getGenerationID();
36 builder[1] = subset.fLeft;
37 builder[2] = subset.fTop;
38 builder[3] = subset.fRight;
39 builder[4] = subset.fBottom;
40 builder[5] = SkToBool(mipmapped);
41}
42
43sk_sp<SkIDChangeListener> make_unique_key_invalidation_listener(const skgpu::UniqueKey& key,
44 uint32_t recorderID) {
45 class Listener : public SkIDChangeListener {
46 public:
47 Listener(const skgpu::UniqueKey& key, uint32_t recorderUniqueID)
48 : fMsg(key, recorderUniqueID) {}
49
50 void changed() override {
52 }
53
54 private:
56 };
57
58 return sk_make_sp<Listener>(key, recorderID);
59}
60
61} // anonymous namespace
62
63namespace skgpu::graphite {
64
65ProxyCache::ProxyCache(uint32_t recorderID) : fInvalidUniqueKeyInbox(recorderID) {
66 SkASSERT(recorderID != SK_InvalidGenID);
67}
68
70
71uint32_t ProxyCache::UniqueKeyHash::operator()(const skgpu::UniqueKey& key) const {
72 return key.hash();
73}
74
76 const SkBitmap& bitmap,
77 Mipmapped mipmapped) {
78 this->processInvalidKeyMsgs();
79
80 if (bitmap.dimensions().area() <= 1) {
81 mipmapped = skgpu::Mipmapped::kNo;
82 }
83
85
86 if (mipmapped == Mipmapped::kNo) {
87 make_bitmap_key(&key, bitmap, Mipmapped::kYes);
88
89 if (sk_sp<TextureProxy>* cached = fCache.find(key)) {
90 if (Resource* resource = (*cached)->texture(); resource) {
91 resource->updateAccessTime();
92 }
93 return *cached;
94 }
95 }
96
97 make_bitmap_key(&key, bitmap, mipmapped);
98
99 if (sk_sp<TextureProxy>* cached = fCache.find(key)) {
100 if (Resource* resource = (*cached)->texture(); resource) {
101 resource->updateAccessTime();
102 }
103 return *cached;
104 }
105
106 auto [ view, ct ] = MakeBitmapProxyView(recorder, bitmap, nullptr,
107 mipmapped, skgpu::Budgeted::kYes);
108 if (view) {
109 auto listener = make_unique_key_invalidation_listener(key, recorder->priv().uniqueID());
110 bitmap.pixelRef()->addGenIDChangeListener(std::move(listener));
111
112 fCache.set(key, view.refProxy());
113 }
114 return view.refProxy();
115}
116
118 fCache.reset();
119}
120
121void ProxyCache::processInvalidKeyMsgs() {
123 fInvalidUniqueKeyInbox.poll(&invalidKeyMsgs);
124
125 if (!invalidKeyMsgs.empty()) {
126 for (int i = 0; i < invalidKeyMsgs.size(); ++i) {
127 // TODO: this should stop crbug.com/1480570 for now but more investigation needs to be
128 // done into how we're getting into the situation where an invalid key has been
129 // purged from the cache prior to processing of the invalid key messages.
130 if (fCache.find(invalidKeyMsgs[i].key())) {
131 fCache.remove(invalidKeyMsgs[i].key());
132 }
133 }
134 }
135}
136
137void ProxyCache::freeUniquelyHeld() {
138 this->processInvalidKeyMsgs();
139
140 std::vector<skgpu::UniqueKey> toRemove;
141
142 fCache.foreach([&](const skgpu::UniqueKey& key, const sk_sp<TextureProxy>* proxy) {
143 if ((*proxy)->unique()) {
144 toRemove.push_back(key);
145 }
146 });
147
148 for (const skgpu::UniqueKey& k : toRemove) {
149 fCache.remove(k);
150 }
151}
152
153void ProxyCache::purgeProxiesNotUsedSince(const skgpu::StdSteadyClock::time_point* purgeTime) {
154 this->processInvalidKeyMsgs();
155
156 std::vector<skgpu::UniqueKey> toRemove;
157
158 fCache.foreach([&](const skgpu::UniqueKey& key, const sk_sp<TextureProxy>* proxy) {
159 if (Resource* resource = (*proxy)->texture();
160 resource &&
161 (!purgeTime || resource->lastAccessTime() < *purgeTime)) {
162 resource->setDeleteASAP();
163 toRemove.push_back(key);
164 }
165 });
166
167 for (const skgpu::UniqueKey& k : toRemove) {
168 fCache.remove(k);
169 }
170}
171
172#if defined(GRAPHITE_TEST_UTILS)
173int ProxyCache::numCached() const {
174 return fCache.count();
175}
176
177sk_sp<TextureProxy> ProxyCache::find(const SkBitmap& bitmap, Mipmapped mipmapped) {
178
180
181 make_bitmap_key(&key, bitmap, mipmapped);
182
183 if (sk_sp<TextureProxy>* cached = fCache.find(key)) {
184 return *cached;
185 }
186
187 return nullptr;
188}
189
190void ProxyCache::forceProcessInvalidKeyMsgs() {
191 this->processInvalidKeyMsgs();
192}
193
194void ProxyCache::forceFreeUniquelyHeld() {
195 this->freeUniquelyHeld();
196}
197
198void ProxyCache::forcePurgeProxiesNotUsedSince(skgpu::StdSteadyClock::time_point purgeTime) {
199 this->purgeProxiesNotUsedSince(&purgeTime);
200}
201
202#endif // defined(GRAPHITE_TEST_UTILS)
203
204} // namespace skgpu::graphite
#define SkASSERT(cond)
Definition SkAssert.h:116
#define DECLARE_SKMESSAGEBUS_MESSAGE(Message, IDType, AllowCopyableMessage)
static constexpr bool SkToBool(const T &x)
Definition SkTo.h:35
static constexpr uint32_t SK_InvalidGenID
Definition SkTypes.h:192
SkIPoint pixelRefOrigin() const
Definition SkBitmap.cpp:168
SkPixelRef * pixelRef() const
Definition SkBitmap.h:720
SkISize dimensions() const
Definition SkBitmap.h:388
virtual void changed()=0
static void Post(Message m)
uint32_t getGenerationID() const
static Domain GenerateDomain()
ProxyCache(uint32_t recorderID)
sk_sp< TextureProxy > findOrCreateCachedProxy(Recorder *, const SkBitmap &, Mipmapped)
bool empty() const
Definition SkTArray.h:194
int size() const
Definition SkTArray.h:416
void foreach(Fn &&fn)
Definition SkTHash.h:506
int count() const
Definition SkTHash.h:460
V * find(const K &key) const
Definition SkTHash.h:479
V * set(K key, V val)
Definition SkTHash.h:472
void remove(const K &key)
Definition SkTHash.h:494
std::tuple< TextureProxyView, SkColorType > MakeBitmapProxyView(Recorder *recorder, const SkBitmap &bitmap, sk_sp< SkMipmap > mipmapsIn, Mipmapped mipmapped, Budgeted budgeted)
Mipmapped
Definition GpuTypes.h:53
int32_t fBottom
larger y-axis bounds
Definition SkRect.h:36
int32_t fTop
smaller y-axis bounds
Definition SkRect.h:34
int32_t fLeft
smaller x-axis bounds
Definition SkRect.h:33
static constexpr SkIRect MakePtSize(SkIPoint pt, SkISize size)
Definition SkRect.h:78
int32_t fRight
larger x-axis bounds
Definition SkRect.h:35