blob: 61749a5e9dee5352cc5ba7ade0d71ca9d84865c7 [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"
Robert Phillips187b04b2020-09-22 12:18:16 -040013#include "src/gpu/GrResourceCache.h"
Brian Salomoneebe7352020-12-09 16:37:04 -050014#include "src/gpu/GrSurfaceDrawContext.h"
Robert Phillips187b04b2020-09-22 12:18:16 -040015
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 Phillips83c38a82020-10-28 14:57:53 -0400121#ifdef SK_DEBUG
122bool GrThreadSafeCache::has(const GrUniqueKey& key) {
123 SkAutoSpinlock lock{fSpinLock};
124
125 Entry* tmp = fUniquelyKeyedEntryMap.find(key);
126 return SkToBool(tmp);
127}
128#endif
129
Robert Phillipsd464feb2020-10-08 11:00:02 -0400130GrSurfaceProxyView GrThreadSafeCache::find(const GrUniqueKey& key) {
Robert Phillips6e17ffe2020-10-06 14:52:11 -0400131 SkAutoSpinlock lock{fSpinLock};
132
133 GrSurfaceProxyView view;
134 std::tie(view, std::ignore) = this->internalFind(key);
135 return view;
136}
137
Robert Phillipsd464feb2020-10-08 11:00:02 -0400138std::tuple<GrSurfaceProxyView, sk_sp<SkData>> GrThreadSafeCache::findWithData(
Robert Phillips6e17ffe2020-10-06 14:52:11 -0400139 const GrUniqueKey& key) {
140 SkAutoSpinlock lock{fSpinLock};
141
142 return this->internalFind(key);
143}
144
Robert Phillipsd464feb2020-10-08 11:00:02 -0400145GrThreadSafeCache::Entry* GrThreadSafeCache::getEntry(const GrUniqueKey& key,
146 const GrSurfaceProxyView& view) {
Robert Phillips45593682020-09-18 16:16:33 -0400147 Entry* entry;
148
149 if (fFreeEntryList) {
150 entry = fFreeEntryList;
151 fFreeEntryList = entry->fNext;
152 entry->fNext = nullptr;
153
Robert Phillips01771c12020-10-20 15:46:07 -0400154 entry->set(key, view);
Robert Phillips45593682020-09-18 16:16:33 -0400155 } else {
156 entry = fEntryAllocator.make<Entry>(key, view);
157 }
158
Robert Phillips42a741a2020-10-23 12:27:47 -0400159 return this->makeNewEntryMRU(entry);
160}
161
162GrThreadSafeCache::Entry* GrThreadSafeCache::makeNewEntryMRU(Entry* entry) {
Robert Phillipsc2fe1642020-09-22 17:34:51 -0400163 entry->fLastAccess = GrStdSteadyClock::now();
Robert Phillips74ad27d2020-10-20 10:16:55 -0400164 fUniquelyKeyedEntryList.addToHead(entry);
165 fUniquelyKeyedEntryMap.add(entry);
Robert Phillips45593682020-09-18 16:16:33 -0400166 return entry;
167}
168
Robert Phillips42a741a2020-10-23 12:27:47 -0400169GrThreadSafeCache::Entry* GrThreadSafeCache::getEntry(const GrUniqueKey& key,
170 sk_sp<VertexData> vertData) {
171 Entry* entry;
172
173 if (fFreeEntryList) {
174 entry = fFreeEntryList;
175 fFreeEntryList = entry->fNext;
176 entry->fNext = nullptr;
177
178 entry->set(key, std::move(vertData));
179 } else {
180 entry = fEntryAllocator.make<Entry>(key, std::move(vertData));
181 }
182
183 return this->makeNewEntryMRU(entry);
184}
185
Robert Phillipsd464feb2020-10-08 11:00:02 -0400186void GrThreadSafeCache::recycleEntry(Entry* dead) {
Robert Phillips45593682020-09-18 16:16:33 -0400187 SkASSERT(!dead->fPrev && !dead->fNext && !dead->fList);
188
Robert Phillips01771c12020-10-20 15:46:07 -0400189 dead->makeEmpty();
Robert Phillips45593682020-09-18 16:16:33 -0400190
191 dead->fNext = fFreeEntryList;
192 fFreeEntryList = dead;
193}
194
Robert Phillipsd464feb2020-10-08 11:00:02 -0400195std::tuple<GrSurfaceProxyView, sk_sp<SkData>> GrThreadSafeCache::internalAdd(
Robert Phillips26f3aeb2020-09-16 10:57:32 -0400196 const GrUniqueKey& key,
197 const GrSurfaceProxyView& view) {
Robert Phillips74ad27d2020-10-20 10:16:55 -0400198 Entry* tmp = fUniquelyKeyedEntryMap.find(key);
Robert Phillips26f3aeb2020-09-16 10:57:32 -0400199 if (!tmp) {
Robert Phillipsf3e2b3c2020-09-18 14:07:43 -0400200 tmp = this->getEntry(key, view);
Robert Phillips45593682020-09-18 16:16:33 -0400201
Robert Phillips74ad27d2020-10-20 10:16:55 -0400202 SkASSERT(fUniquelyKeyedEntryMap.find(key));
Robert Phillips26f3aeb2020-09-16 10:57:32 -0400203 }
204
Robert Phillips01771c12020-10-20 15:46:07 -0400205 return { tmp->view(), tmp->refCustomData() };
Robert Phillips26f3aeb2020-09-16 10:57:32 -0400206}
207
Robert Phillipsd464feb2020-10-08 11:00:02 -0400208GrSurfaceProxyView GrThreadSafeCache::add(const GrUniqueKey& key, const GrSurfaceProxyView& view) {
Robert Phillips26f3aeb2020-09-16 10:57:32 -0400209 SkAutoSpinlock lock{fSpinLock};
210
Robert Phillips6e17ffe2020-10-06 14:52:11 -0400211 GrSurfaceProxyView newView;
212 std::tie(newView, std::ignore) = this->internalAdd(key, view);
213 return newView;
214}
215
Robert Phillipsd464feb2020-10-08 11:00:02 -0400216std::tuple<GrSurfaceProxyView, sk_sp<SkData>> GrThreadSafeCache::addWithData(
Robert Phillips6e17ffe2020-10-06 14:52:11 -0400217 const GrUniqueKey& key,
218 const GrSurfaceProxyView& view) {
219 SkAutoSpinlock lock{fSpinLock};
220
Robert Phillips26f3aeb2020-09-16 10:57:32 -0400221 return this->internalAdd(key, view);
222}
Robert Phillips3380be92020-09-25 12:47:10 -0400223
Robert Phillipsd464feb2020-10-08 11:00:02 -0400224GrSurfaceProxyView GrThreadSafeCache::findOrAdd(const GrUniqueKey& key,
225 const GrSurfaceProxyView& v) {
Robert Phillips3380be92020-09-25 12:47:10 -0400226 SkAutoSpinlock lock{fSpinLock};
227
Robert Phillips6e17ffe2020-10-06 14:52:11 -0400228 GrSurfaceProxyView view;
229 std::tie(view, std::ignore) = this->internalFind(key);
230 if (view) {
231 return view;
232 }
233
234 std::tie(view, std::ignore) = this->internalAdd(key, v);
235 return view;
236}
237
Robert Phillipsd464feb2020-10-08 11:00:02 -0400238std::tuple<GrSurfaceProxyView, sk_sp<SkData>> GrThreadSafeCache::findOrAddWithData(
Robert Phillips6e17ffe2020-10-06 14:52:11 -0400239 const GrUniqueKey& key,
240 const GrSurfaceProxyView& v) {
241 SkAutoSpinlock lock{fSpinLock};
242
243 auto [view, data] = this->internalFind(key);
244 if (view) {
245 return { std::move(view), std::move(data) };
Robert Phillips3380be92020-09-25 12:47:10 -0400246 }
247
248 return this->internalAdd(key, v);
249}
250
Robert Phillips42a741a2020-10-23 12:27:47 -0400251sk_sp<GrThreadSafeCache::VertexData> GrThreadSafeCache::MakeVertexData(const void* vertices,
252 int vertexCount,
253 size_t vertexSize) {
254 return sk_sp<VertexData>(new VertexData(vertices, vertexCount, vertexSize));
255}
256
Robert Phillips83c38a82020-10-28 14:57:53 -0400257sk_sp<GrThreadSafeCache::VertexData> GrThreadSafeCache::MakeVertexData(sk_sp<GrGpuBuffer> buffer,
258 int vertexCount,
259 size_t vertexSize) {
260 return sk_sp<VertexData>(new VertexData(std::move(buffer), vertexCount, vertexSize));
261}
262
Robert Phillips42a741a2020-10-23 12:27:47 -0400263std::tuple<sk_sp<GrThreadSafeCache::VertexData>, sk_sp<SkData>> GrThreadSafeCache::internalFindVerts(
264 const GrUniqueKey& key) {
265 Entry* tmp = fUniquelyKeyedEntryMap.find(key);
266 if (tmp) {
267 this->makeExistingEntryMRU(tmp);
268 return { tmp->vertexData(), tmp->refCustomData() };
269 }
270
271 return {};
272}
273
274std::tuple<sk_sp<GrThreadSafeCache::VertexData>, sk_sp<SkData>> GrThreadSafeCache::findVertsWithData(
275 const GrUniqueKey& key) {
276 SkAutoSpinlock lock{fSpinLock};
277
278 return this->internalFindVerts(key);
279}
280
281std::tuple<sk_sp<GrThreadSafeCache::VertexData>, sk_sp<SkData>> GrThreadSafeCache::internalAddVerts(
282 const GrUniqueKey& key,
Robert Phillips67e58cb2020-11-02 08:57:39 -0500283 sk_sp<VertexData> vertData,
284 IsNewerBetter isNewerBetter) {
Robert Phillips42a741a2020-10-23 12:27:47 -0400285 Entry* tmp = fUniquelyKeyedEntryMap.find(key);
286 if (!tmp) {
287 tmp = this->getEntry(key, std::move(vertData));
288
289 SkASSERT(fUniquelyKeyedEntryMap.find(key));
Robert Phillips67e58cb2020-11-02 08:57:39 -0500290 } else if (isNewerBetter(tmp->getCustomData(), key.getCustomData())) {
291 // This orphans any existing uses of the prior vertex data but ensures the best
292 // version is in the cache.
293 tmp->set(key, std::move(vertData));
Robert Phillips42a741a2020-10-23 12:27:47 -0400294 }
295
296 return { tmp->vertexData(), tmp->refCustomData() };
297}
298
299std::tuple<sk_sp<GrThreadSafeCache::VertexData>, sk_sp<SkData>> GrThreadSafeCache::addVertsWithData(
300 const GrUniqueKey& key,
Robert Phillips67e58cb2020-11-02 08:57:39 -0500301 sk_sp<VertexData> vertData,
302 IsNewerBetter isNewerBetter) {
Robert Phillips42a741a2020-10-23 12:27:47 -0400303 SkAutoSpinlock lock{fSpinLock};
304
Robert Phillips67e58cb2020-11-02 08:57:39 -0500305 return this->internalAddVerts(key, std::move(vertData), isNewerBetter);
Robert Phillips42a741a2020-10-23 12:27:47 -0400306}
307
Robert Phillipsd464feb2020-10-08 11:00:02 -0400308void GrThreadSafeCache::remove(const GrUniqueKey& key) {
Robert Phillips3380be92020-09-25 12:47:10 -0400309 SkAutoSpinlock lock{fSpinLock};
310
Robert Phillips74ad27d2020-10-20 10:16:55 -0400311 Entry* tmp = fUniquelyKeyedEntryMap.find(key);
Robert Phillips3380be92020-09-25 12:47:10 -0400312 if (tmp) {
Robert Phillips74ad27d2020-10-20 10:16:55 -0400313 fUniquelyKeyedEntryMap.remove(key);
314 fUniquelyKeyedEntryList.remove(tmp);
Robert Phillips3380be92020-09-25 12:47:10 -0400315 this->recycleEntry(tmp);
316 }
317}
Robert Phillipsb1807122020-10-06 16:44:18 -0400318
Robert Phillipsd464feb2020-10-08 11:00:02 -0400319std::tuple<GrSurfaceProxyView, sk_sp<GrThreadSafeCache::Trampoline>>
320GrThreadSafeCache::CreateLazyView(GrDirectContext* dContext,
321 GrColorType origCT,
322 SkISize dimensions,
323 GrSurfaceOrigin origin,
324 SkBackingFit fit) {
Robert Phillipsb1807122020-10-06 16:44:18 -0400325 GrProxyProvider* proxyProvider = dContext->priv().proxyProvider();
326
327 constexpr int kSampleCnt = 1;
Brian Salomoneebe7352020-12-09 16:37:04 -0500328 auto [newCT, format] =
329 GrSurfaceDrawContext::GetFallbackColorTypeAndFormat(
Robert Phillipsb1807122020-10-06 16:44:18 -0400330 dContext, origCT, kSampleCnt);
331
332 if (newCT == GrColorType::kUnknown) {
333 return {GrSurfaceProxyView(nullptr), nullptr};
334 }
335
336 sk_sp<Trampoline> trampoline(new Trampoline);
337
338 GrProxyProvider::TextureInfo texInfo{ GrMipMapped::kNo, GrTextureType::k2D };
339
340 sk_sp<GrRenderTargetProxy> proxy = proxyProvider->createLazyRenderTargetProxy(
341 [trampoline](
342 GrResourceProvider* resourceProvider,
343 const GrSurfaceProxy::LazySurfaceDesc&) -> GrSurfaceProxy::LazyCallbackResult {
344 if (!resourceProvider || !trampoline->fProxy ||
345 !trampoline->fProxy->isInstantiated()) {
346 return GrSurfaceProxy::LazyCallbackResult(nullptr, true);
347 }
348
349 SkASSERT(!trampoline->fProxy->peekTexture()->getUniqueKey().isValid());
350 return GrSurfaceProxy::LazyCallbackResult(
351 sk_ref_sp(trampoline->fProxy->peekTexture()));
352 },
353 format,
354 dimensions,
355 kSampleCnt,
356 GrInternalSurfaceFlags::kNone,
357 &texInfo,
358 GrMipmapStatus::kNotAllocated,
Robert Phillipsfde67e42020-10-07 15:33:43 -0400359 fit,
Robert Phillipsb1807122020-10-06 16:44:18 -0400360 SkBudgeted::kYes,
361 GrProtected::kNo,
362 /* wrapsVkSecondaryCB */ false,
363 GrSurfaceProxy::UseAllocator::kYes);
364
365 // TODO: It seems like this 'newCT' usage should be 'origCT' but this is
Brian Salomoneebe7352020-12-09 16:37:04 -0500366 // what GrSurfaceDrawContext::MakeWithFallback does
Robert Phillipsb1807122020-10-06 16:44:18 -0400367 GrSwizzle swizzle = dContext->priv().caps()->getReadSwizzle(format, newCT);
368
369 return {{std::move(proxy), origin, swizzle}, std::move(trampoline)};
370}