blob: 23c65b2e5064a7394fa145eaf6426fff8209bdb1 [file] [log] [blame]
Robert Phillips26f3aeb2020-09-16 10:57:32 -04001/*
2 * Copyright 2020 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
Robert Phillipsd464feb2020-10-08 11:00:02 -04008#include "src/gpu/GrThreadSafeCache.h"
Robert Phillips26f3aeb2020-09-16 10:57:32 -04009
Robert Phillipsb1807122020-10-06 16:44:18 -040010#include "include/gpu/GrDirectContext.h"
Adlai Hollera0693042020-10-14 11:23:11 -040011#include "src/gpu/GrDirectContextPriv.h"
Robert Phillipsb1807122020-10-06 16:44:18 -040012#include "src/gpu/GrProxyProvider.h"
13#include "src/gpu/GrRenderTargetContext.h"
Robert Phillips187b04b2020-09-22 12:18:16 -040014#include "src/gpu/GrResourceCache.h"
15
Robert Phillips42a741a2020-10-23 12:27:47 -040016GrThreadSafeCache::VertexData::~VertexData () {
17 this->reset();
18}
19
Robert Phillipsd464feb2020-10-08 11:00:02 -040020GrThreadSafeCache::GrThreadSafeCache()
Robert Phillips45593682020-09-18 16:16:33 -040021 : fFreeEntryList(nullptr) {
22}
Robert Phillips26f3aeb2020-09-16 10:57:32 -040023
Robert Phillipsd464feb2020-10-08 11:00:02 -040024GrThreadSafeCache::~GrThreadSafeCache() {
Robert Phillips45593682020-09-18 16:16:33 -040025 this->dropAllRefs();
Robert Phillips26f3aeb2020-09-16 10:57:32 -040026}
27
28#if GR_TEST_UTILS
Robert Phillipsd464feb2020-10-08 11:00:02 -040029int GrThreadSafeCache::numEntries() const {
Robert Phillips26f3aeb2020-09-16 10:57:32 -040030 SkAutoSpinlock lock{fSpinLock};
31
Robert Phillips74ad27d2020-10-20 10:16:55 -040032 return fUniquelyKeyedEntryMap.count();
Robert Phillips26f3aeb2020-09-16 10:57:32 -040033}
34
Robert Phillipsd464feb2020-10-08 11:00:02 -040035size_t GrThreadSafeCache::approxBytesUsedForHash() const {
Robert Phillips26f3aeb2020-09-16 10:57:32 -040036 SkAutoSpinlock lock{fSpinLock};
37
Robert Phillips74ad27d2020-10-20 10:16:55 -040038 return fUniquelyKeyedEntryMap.approxBytesUsed();
Robert Phillips26f3aeb2020-09-16 10:57:32 -040039}
40#endif
41
Robert Phillipsd464feb2020-10-08 11:00:02 -040042void GrThreadSafeCache::dropAllRefs() {
Robert Phillips26f3aeb2020-09-16 10:57:32 -040043 SkAutoSpinlock lock{fSpinLock};
44
Robert Phillips74ad27d2020-10-20 10:16:55 -040045 fUniquelyKeyedEntryMap.reset();
46 while (auto tmp = fUniquelyKeyedEntryList.head()) {
47 fUniquelyKeyedEntryList.remove(tmp);
Robert Phillips45593682020-09-18 16:16:33 -040048 this->recycleEntry(tmp);
49 }
50 // TODO: should we empty out the fFreeEntryList and reset fEntryAllocator?
Robert Phillips26f3aeb2020-09-16 10:57:32 -040051}
52
Robert Phillips3380be92020-09-25 12:47:10 -040053// TODO: If iterating becomes too expensive switch to using something like GrIORef for the
54// GrSurfaceProxy
Robert Phillipsd464feb2020-10-08 11:00:02 -040055void GrThreadSafeCache::dropUniqueRefs(GrResourceCache* resourceCache) {
Robert Phillips12d06a32020-09-16 12:31:34 -040056 SkAutoSpinlock lock{fSpinLock};
57
Robert Phillips187b04b2020-09-22 12:18:16 -040058 // Iterate from LRU to MRU
Robert Phillips74ad27d2020-10-20 10:16:55 -040059 Entry* cur = fUniquelyKeyedEntryList.tail();
Robert Phillips187b04b2020-09-22 12:18:16 -040060 Entry* prev = cur ? cur->fPrev : nullptr;
Robert Phillips45593682020-09-18 16:16:33 -040061
62 while (cur) {
Robert Phillips187b04b2020-09-22 12:18:16 -040063 if (resourceCache && !resourceCache->overBudget()) {
64 return;
65 }
66
Robert Phillips01771c12020-10-20 15:46:07 -040067 if (cur->uniquelyHeld()) {
68 fUniquelyKeyedEntryMap.remove(cur->key());
Robert Phillips74ad27d2020-10-20 10:16:55 -040069 fUniquelyKeyedEntryList.remove(cur);
Robert Phillips45593682020-09-18 16:16:33 -040070 this->recycleEntry(cur);
71 }
72
Robert Phillips187b04b2020-09-22 12:18:16 -040073 cur = prev;
74 prev = cur ? cur->fPrev : nullptr;
Robert Phillips45593682020-09-18 16:16:33 -040075 }
Robert Phillips12d06a32020-09-16 12:31:34 -040076}
77
Robert Phillipsd464feb2020-10-08 11:00:02 -040078void GrThreadSafeCache::dropUniqueRefsOlderThan(GrStdSteadyClock::time_point purgeTime) {
Robert Phillipsc2fe1642020-09-22 17:34:51 -040079 SkAutoSpinlock lock{fSpinLock};
80
81 // Iterate from LRU to MRU
Robert Phillips74ad27d2020-10-20 10:16:55 -040082 Entry* cur = fUniquelyKeyedEntryList.tail();
Robert Phillipsc2fe1642020-09-22 17:34:51 -040083 Entry* prev = cur ? cur->fPrev : nullptr;
84
85 while (cur) {
86 if (cur->fLastAccess >= purgeTime) {
87 // This entry and all the remaining ones in the list will be newer than 'purgeTime'
88 return;
89 }
90
Robert Phillips01771c12020-10-20 15:46:07 -040091 if (cur->uniquelyHeld()) {
92 fUniquelyKeyedEntryMap.remove(cur->key());
Robert Phillips74ad27d2020-10-20 10:16:55 -040093 fUniquelyKeyedEntryList.remove(cur);
Robert Phillipsc2fe1642020-09-22 17:34:51 -040094 this->recycleEntry(cur);
95 }
96
97 cur = prev;
98 prev = cur ? cur->fPrev : nullptr;
99 }
100}
101
Robert Phillips42a741a2020-10-23 12:27:47 -0400102void GrThreadSafeCache::makeExistingEntryMRU(Entry* entry) {
103 SkASSERT(fUniquelyKeyedEntryList.isInList(entry));
104
105 entry->fLastAccess = GrStdSteadyClock::now();
106 fUniquelyKeyedEntryList.remove(entry);
107 fUniquelyKeyedEntryList.addToHead(entry);
108}
109
Robert Phillipsd464feb2020-10-08 11:00:02 -0400110std::tuple<GrSurfaceProxyView, sk_sp<SkData>> GrThreadSafeCache::internalFind(
Robert Phillips6e17ffe2020-10-06 14:52:11 -0400111 const GrUniqueKey& key) {
Robert Phillips74ad27d2020-10-20 10:16:55 -0400112 Entry* tmp = fUniquelyKeyedEntryMap.find(key);
Robert Phillips26f3aeb2020-09-16 10:57:32 -0400113 if (tmp) {
Robert Phillips42a741a2020-10-23 12:27:47 -0400114 this->makeExistingEntryMRU(tmp);
Robert Phillips01771c12020-10-20 15:46:07 -0400115 return { tmp->view(), tmp->refCustomData() };
Robert Phillips26f3aeb2020-09-16 10:57:32 -0400116 }
117
118 return {};
119}
120
Robert Phillipsd464feb2020-10-08 11:00:02 -0400121GrSurfaceProxyView GrThreadSafeCache::find(const GrUniqueKey& key) {
Robert Phillips6e17ffe2020-10-06 14:52:11 -0400122 SkAutoSpinlock lock{fSpinLock};
123
124 GrSurfaceProxyView view;
125 std::tie(view, std::ignore) = this->internalFind(key);
126 return view;
127}
128
Robert Phillipsd464feb2020-10-08 11:00:02 -0400129std::tuple<GrSurfaceProxyView, sk_sp<SkData>> GrThreadSafeCache::findWithData(
Robert Phillips6e17ffe2020-10-06 14:52:11 -0400130 const GrUniqueKey& key) {
131 SkAutoSpinlock lock{fSpinLock};
132
133 return this->internalFind(key);
134}
135
Robert Phillipsd464feb2020-10-08 11:00:02 -0400136GrThreadSafeCache::Entry* GrThreadSafeCache::getEntry(const GrUniqueKey& key,
137 const GrSurfaceProxyView& view) {
Robert Phillips45593682020-09-18 16:16:33 -0400138 Entry* entry;
139
140 if (fFreeEntryList) {
141 entry = fFreeEntryList;
142 fFreeEntryList = entry->fNext;
143 entry->fNext = nullptr;
144
Robert Phillips01771c12020-10-20 15:46:07 -0400145 entry->set(key, view);
Robert Phillips45593682020-09-18 16:16:33 -0400146 } else {
147 entry = fEntryAllocator.make<Entry>(key, view);
148 }
149
Robert Phillips42a741a2020-10-23 12:27:47 -0400150 return this->makeNewEntryMRU(entry);
151}
152
153GrThreadSafeCache::Entry* GrThreadSafeCache::makeNewEntryMRU(Entry* entry) {
Robert Phillipsc2fe1642020-09-22 17:34:51 -0400154 entry->fLastAccess = GrStdSteadyClock::now();
Robert Phillips74ad27d2020-10-20 10:16:55 -0400155 fUniquelyKeyedEntryList.addToHead(entry);
156 fUniquelyKeyedEntryMap.add(entry);
Robert Phillips45593682020-09-18 16:16:33 -0400157 return entry;
158}
159
Robert Phillips42a741a2020-10-23 12:27:47 -0400160GrThreadSafeCache::Entry* GrThreadSafeCache::getEntry(const GrUniqueKey& key,
161 sk_sp<VertexData> vertData) {
162 Entry* entry;
163
164 if (fFreeEntryList) {
165 entry = fFreeEntryList;
166 fFreeEntryList = entry->fNext;
167 entry->fNext = nullptr;
168
169 entry->set(key, std::move(vertData));
170 } else {
171 entry = fEntryAllocator.make<Entry>(key, std::move(vertData));
172 }
173
174 return this->makeNewEntryMRU(entry);
175}
176
Robert Phillipsd464feb2020-10-08 11:00:02 -0400177void GrThreadSafeCache::recycleEntry(Entry* dead) {
Robert Phillips45593682020-09-18 16:16:33 -0400178 SkASSERT(!dead->fPrev && !dead->fNext && !dead->fList);
179
Robert Phillips01771c12020-10-20 15:46:07 -0400180 dead->makeEmpty();
Robert Phillips45593682020-09-18 16:16:33 -0400181
182 dead->fNext = fFreeEntryList;
183 fFreeEntryList = dead;
184}
185
Robert Phillipsd464feb2020-10-08 11:00:02 -0400186std::tuple<GrSurfaceProxyView, sk_sp<SkData>> GrThreadSafeCache::internalAdd(
Robert Phillips26f3aeb2020-09-16 10:57:32 -0400187 const GrUniqueKey& key,
188 const GrSurfaceProxyView& view) {
Robert Phillips74ad27d2020-10-20 10:16:55 -0400189 Entry* tmp = fUniquelyKeyedEntryMap.find(key);
Robert Phillips26f3aeb2020-09-16 10:57:32 -0400190 if (!tmp) {
Robert Phillipsf3e2b3c2020-09-18 14:07:43 -0400191 tmp = this->getEntry(key, view);
Robert Phillips45593682020-09-18 16:16:33 -0400192
Robert Phillips74ad27d2020-10-20 10:16:55 -0400193 SkASSERT(fUniquelyKeyedEntryMap.find(key));
Robert Phillips26f3aeb2020-09-16 10:57:32 -0400194 }
195
Robert Phillips01771c12020-10-20 15:46:07 -0400196 return { tmp->view(), tmp->refCustomData() };
Robert Phillips26f3aeb2020-09-16 10:57:32 -0400197}
198
Robert Phillipsd464feb2020-10-08 11:00:02 -0400199GrSurfaceProxyView GrThreadSafeCache::add(const GrUniqueKey& key, const GrSurfaceProxyView& view) {
Robert Phillips26f3aeb2020-09-16 10:57:32 -0400200 SkAutoSpinlock lock{fSpinLock};
201
Robert Phillips6e17ffe2020-10-06 14:52:11 -0400202 GrSurfaceProxyView newView;
203 std::tie(newView, std::ignore) = this->internalAdd(key, view);
204 return newView;
205}
206
Robert Phillipsd464feb2020-10-08 11:00:02 -0400207std::tuple<GrSurfaceProxyView, sk_sp<SkData>> GrThreadSafeCache::addWithData(
Robert Phillips6e17ffe2020-10-06 14:52:11 -0400208 const GrUniqueKey& key,
209 const GrSurfaceProxyView& view) {
210 SkAutoSpinlock lock{fSpinLock};
211
Robert Phillips26f3aeb2020-09-16 10:57:32 -0400212 return this->internalAdd(key, view);
213}
Robert Phillips3380be92020-09-25 12:47:10 -0400214
Robert Phillipsd464feb2020-10-08 11:00:02 -0400215GrSurfaceProxyView GrThreadSafeCache::findOrAdd(const GrUniqueKey& key,
216 const GrSurfaceProxyView& v) {
Robert Phillips3380be92020-09-25 12:47:10 -0400217 SkAutoSpinlock lock{fSpinLock};
218
Robert Phillips6e17ffe2020-10-06 14:52:11 -0400219 GrSurfaceProxyView view;
220 std::tie(view, std::ignore) = this->internalFind(key);
221 if (view) {
222 return view;
223 }
224
225 std::tie(view, std::ignore) = this->internalAdd(key, v);
226 return view;
227}
228
Robert Phillipsd464feb2020-10-08 11:00:02 -0400229std::tuple<GrSurfaceProxyView, sk_sp<SkData>> GrThreadSafeCache::findOrAddWithData(
Robert Phillips6e17ffe2020-10-06 14:52:11 -0400230 const GrUniqueKey& key,
231 const GrSurfaceProxyView& v) {
232 SkAutoSpinlock lock{fSpinLock};
233
234 auto [view, data] = this->internalFind(key);
235 if (view) {
236 return { std::move(view), std::move(data) };
Robert Phillips3380be92020-09-25 12:47:10 -0400237 }
238
239 return this->internalAdd(key, v);
240}
241
Robert Phillips42a741a2020-10-23 12:27:47 -0400242sk_sp<GrThreadSafeCache::VertexData> GrThreadSafeCache::MakeVertexData(const void* vertices,
243 int vertexCount,
244 size_t vertexSize) {
245 return sk_sp<VertexData>(new VertexData(vertices, vertexCount, vertexSize));
246}
247
248std::tuple<sk_sp<GrThreadSafeCache::VertexData>, sk_sp<SkData>> GrThreadSafeCache::internalFindVerts(
249 const GrUniqueKey& key) {
250 Entry* tmp = fUniquelyKeyedEntryMap.find(key);
251 if (tmp) {
252 this->makeExistingEntryMRU(tmp);
253 return { tmp->vertexData(), tmp->refCustomData() };
254 }
255
256 return {};
257}
258
259std::tuple<sk_sp<GrThreadSafeCache::VertexData>, sk_sp<SkData>> GrThreadSafeCache::findVertsWithData(
260 const GrUniqueKey& key) {
261 SkAutoSpinlock lock{fSpinLock};
262
263 return this->internalFindVerts(key);
264}
265
266std::tuple<sk_sp<GrThreadSafeCache::VertexData>, sk_sp<SkData>> GrThreadSafeCache::internalAddVerts(
267 const GrUniqueKey& key,
268 sk_sp<VertexData> vertData) {
269 Entry* tmp = fUniquelyKeyedEntryMap.find(key);
270 if (!tmp) {
271 tmp = this->getEntry(key, std::move(vertData));
272
273 SkASSERT(fUniquelyKeyedEntryMap.find(key));
274 }
275
276 return { tmp->vertexData(), tmp->refCustomData() };
277}
278
279std::tuple<sk_sp<GrThreadSafeCache::VertexData>, sk_sp<SkData>> GrThreadSafeCache::addVertsWithData(
280 const GrUniqueKey& key,
281 sk_sp<VertexData> vertData) {
282 SkAutoSpinlock lock{fSpinLock};
283
284 return this->internalAddVerts(key, std::move(vertData));
285}
286
Robert Phillipsd464feb2020-10-08 11:00:02 -0400287void GrThreadSafeCache::remove(const GrUniqueKey& key) {
Robert Phillips3380be92020-09-25 12:47:10 -0400288 SkAutoSpinlock lock{fSpinLock};
289
Robert Phillips74ad27d2020-10-20 10:16:55 -0400290 Entry* tmp = fUniquelyKeyedEntryMap.find(key);
Robert Phillips3380be92020-09-25 12:47:10 -0400291 if (tmp) {
Robert Phillips74ad27d2020-10-20 10:16:55 -0400292 fUniquelyKeyedEntryMap.remove(key);
293 fUniquelyKeyedEntryList.remove(tmp);
Robert Phillips3380be92020-09-25 12:47:10 -0400294 this->recycleEntry(tmp);
295 }
296}
Robert Phillipsb1807122020-10-06 16:44:18 -0400297
Robert Phillipsd464feb2020-10-08 11:00:02 -0400298std::tuple<GrSurfaceProxyView, sk_sp<GrThreadSafeCache::Trampoline>>
299GrThreadSafeCache::CreateLazyView(GrDirectContext* dContext,
300 GrColorType origCT,
301 SkISize dimensions,
302 GrSurfaceOrigin origin,
303 SkBackingFit fit) {
Robert Phillipsb1807122020-10-06 16:44:18 -0400304 GrProxyProvider* proxyProvider = dContext->priv().proxyProvider();
305
306 constexpr int kSampleCnt = 1;
307 auto [newCT, format] = GrRenderTargetContext::GetFallbackColorTypeAndFormat(
308 dContext, origCT, kSampleCnt);
309
310 if (newCT == GrColorType::kUnknown) {
311 return {GrSurfaceProxyView(nullptr), nullptr};
312 }
313
314 sk_sp<Trampoline> trampoline(new Trampoline);
315
316 GrProxyProvider::TextureInfo texInfo{ GrMipMapped::kNo, GrTextureType::k2D };
317
318 sk_sp<GrRenderTargetProxy> proxy = proxyProvider->createLazyRenderTargetProxy(
319 [trampoline](
320 GrResourceProvider* resourceProvider,
321 const GrSurfaceProxy::LazySurfaceDesc&) -> GrSurfaceProxy::LazyCallbackResult {
322 if (!resourceProvider || !trampoline->fProxy ||
323 !trampoline->fProxy->isInstantiated()) {
324 return GrSurfaceProxy::LazyCallbackResult(nullptr, true);
325 }
326
327 SkASSERT(!trampoline->fProxy->peekTexture()->getUniqueKey().isValid());
328 return GrSurfaceProxy::LazyCallbackResult(
329 sk_ref_sp(trampoline->fProxy->peekTexture()));
330 },
331 format,
332 dimensions,
333 kSampleCnt,
334 GrInternalSurfaceFlags::kNone,
335 &texInfo,
336 GrMipmapStatus::kNotAllocated,
Robert Phillipsfde67e42020-10-07 15:33:43 -0400337 fit,
Robert Phillipsb1807122020-10-06 16:44:18 -0400338 SkBudgeted::kYes,
339 GrProtected::kNo,
340 /* wrapsVkSecondaryCB */ false,
341 GrSurfaceProxy::UseAllocator::kYes);
342
343 // TODO: It seems like this 'newCT' usage should be 'origCT' but this is
344 // what GrRenderTargetContext::MakeWithFallback does
345 GrSwizzle swizzle = dContext->priv().caps()->getReadSwizzle(format, newCT);
346
347 return {{std::move(proxy), origin, swizzle}, std::move(trampoline)};
348}