xref: /aosp_15_r20/external/skia/src/gpu/ganesh/GrThreadSafeCache.cpp (revision c8dee2aa9b3f27cf6c858bd81872bdeb2c07ed17)
1*c8dee2aaSAndroid Build Coastguard Worker /*
2*c8dee2aaSAndroid Build Coastguard Worker  * Copyright 2020 Google Inc.
3*c8dee2aaSAndroid Build Coastguard Worker  *
4*c8dee2aaSAndroid Build Coastguard Worker  * Use of this source code is governed by a BSD-style license that can be
5*c8dee2aaSAndroid Build Coastguard Worker  * found in the LICENSE file.
6*c8dee2aaSAndroid Build Coastguard Worker  */
7*c8dee2aaSAndroid Build Coastguard Worker 
8*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/ganesh/GrThreadSafeCache.h"
9*c8dee2aaSAndroid Build Coastguard Worker 
10*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkSize.h"
11*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkTypes.h"
12*c8dee2aaSAndroid Build Coastguard Worker #include "include/gpu/GpuTypes.h"
13*c8dee2aaSAndroid Build Coastguard Worker #include "include/gpu/ganesh/GrDirectContext.h"
14*c8dee2aaSAndroid Build Coastguard Worker #include "include/gpu/ganesh/GrTypes.h"
15*c8dee2aaSAndroid Build Coastguard Worker #include "include/private/base/SkTo.h"
16*c8dee2aaSAndroid Build Coastguard Worker #include "include/private/gpu/ganesh/GrTypesPriv.h"
17*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/GpuTypesPriv.h"
18*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/Swizzle.h"
19*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/ganesh/GrCaps.h"
20*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/ganesh/GrDirectContextPriv.h"
21*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/ganesh/GrGpuBuffer.h"
22*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/ganesh/GrProxyProvider.h"
23*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/ganesh/GrRenderTargetProxy.h"  // IWYU pragma: keep
24*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/ganesh/GrResourceCache.h"
25*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/ganesh/GrSurface.h"
26*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/ganesh/GrTexture.h"
27*c8dee2aaSAndroid Build Coastguard Worker 
28*c8dee2aaSAndroid Build Coastguard Worker #include <chrono>
29*c8dee2aaSAndroid Build Coastguard Worker #include <functional>
30*c8dee2aaSAndroid Build Coastguard Worker 
31*c8dee2aaSAndroid Build Coastguard Worker class GrResourceProvider;
32*c8dee2aaSAndroid Build Coastguard Worker class SkData;
33*c8dee2aaSAndroid Build Coastguard Worker enum class SkBackingFit;
34*c8dee2aaSAndroid Build Coastguard Worker 
~VertexData()35*c8dee2aaSAndroid Build Coastguard Worker GrThreadSafeCache::VertexData::~VertexData () {
36*c8dee2aaSAndroid Build Coastguard Worker     this->reset();
37*c8dee2aaSAndroid Build Coastguard Worker }
38*c8dee2aaSAndroid Build Coastguard Worker 
GrThreadSafeCache()39*c8dee2aaSAndroid Build Coastguard Worker GrThreadSafeCache::GrThreadSafeCache()
40*c8dee2aaSAndroid Build Coastguard Worker     : fFreeEntryList(nullptr) {
41*c8dee2aaSAndroid Build Coastguard Worker }
42*c8dee2aaSAndroid Build Coastguard Worker 
~GrThreadSafeCache()43*c8dee2aaSAndroid Build Coastguard Worker GrThreadSafeCache::~GrThreadSafeCache() {
44*c8dee2aaSAndroid Build Coastguard Worker     this->dropAllRefs();
45*c8dee2aaSAndroid Build Coastguard Worker }
46*c8dee2aaSAndroid Build Coastguard Worker 
47*c8dee2aaSAndroid Build Coastguard Worker #if defined(GPU_TEST_UTILS)
numEntries() const48*c8dee2aaSAndroid Build Coastguard Worker int GrThreadSafeCache::numEntries() const {
49*c8dee2aaSAndroid Build Coastguard Worker     SkAutoSpinlock lock{fSpinLock};
50*c8dee2aaSAndroid Build Coastguard Worker 
51*c8dee2aaSAndroid Build Coastguard Worker     return fUniquelyKeyedEntryMap.count();
52*c8dee2aaSAndroid Build Coastguard Worker }
53*c8dee2aaSAndroid Build Coastguard Worker 
approxBytesUsedForHash() const54*c8dee2aaSAndroid Build Coastguard Worker size_t GrThreadSafeCache::approxBytesUsedForHash() const {
55*c8dee2aaSAndroid Build Coastguard Worker     SkAutoSpinlock lock{fSpinLock};
56*c8dee2aaSAndroid Build Coastguard Worker 
57*c8dee2aaSAndroid Build Coastguard Worker     return fUniquelyKeyedEntryMap.approxBytesUsed();
58*c8dee2aaSAndroid Build Coastguard Worker }
59*c8dee2aaSAndroid Build Coastguard Worker #endif
60*c8dee2aaSAndroid Build Coastguard Worker 
dropAllRefs()61*c8dee2aaSAndroid Build Coastguard Worker void GrThreadSafeCache::dropAllRefs() {
62*c8dee2aaSAndroid Build Coastguard Worker     SkAutoSpinlock lock{fSpinLock};
63*c8dee2aaSAndroid Build Coastguard Worker 
64*c8dee2aaSAndroid Build Coastguard Worker     fUniquelyKeyedEntryMap.reset();
65*c8dee2aaSAndroid Build Coastguard Worker     while (auto tmp = fUniquelyKeyedEntryList.head()) {
66*c8dee2aaSAndroid Build Coastguard Worker         fUniquelyKeyedEntryList.remove(tmp);
67*c8dee2aaSAndroid Build Coastguard Worker         this->recycleEntry(tmp);
68*c8dee2aaSAndroid Build Coastguard Worker     }
69*c8dee2aaSAndroid Build Coastguard Worker     // TODO: should we empty out the fFreeEntryList and reset fEntryAllocator?
70*c8dee2aaSAndroid Build Coastguard Worker }
71*c8dee2aaSAndroid Build Coastguard Worker 
72*c8dee2aaSAndroid Build Coastguard Worker // TODO: If iterating becomes too expensive switch to using something like GrIORef for the
73*c8dee2aaSAndroid Build Coastguard Worker // GrSurfaceProxy
dropUniqueRefs(GrResourceCache * resourceCache)74*c8dee2aaSAndroid Build Coastguard Worker void GrThreadSafeCache::dropUniqueRefs(GrResourceCache* resourceCache) {
75*c8dee2aaSAndroid Build Coastguard Worker     SkAutoSpinlock lock{fSpinLock};
76*c8dee2aaSAndroid Build Coastguard Worker 
77*c8dee2aaSAndroid Build Coastguard Worker     // Iterate from LRU to MRU
78*c8dee2aaSAndroid Build Coastguard Worker     Entry* cur = fUniquelyKeyedEntryList.tail();
79*c8dee2aaSAndroid Build Coastguard Worker     Entry* prev = cur ? cur->fPrev : nullptr;
80*c8dee2aaSAndroid Build Coastguard Worker 
81*c8dee2aaSAndroid Build Coastguard Worker     while (cur) {
82*c8dee2aaSAndroid Build Coastguard Worker         if (resourceCache && !resourceCache->overBudget()) {
83*c8dee2aaSAndroid Build Coastguard Worker             return;
84*c8dee2aaSAndroid Build Coastguard Worker         }
85*c8dee2aaSAndroid Build Coastguard Worker 
86*c8dee2aaSAndroid Build Coastguard Worker         if (cur->uniquelyHeld()) {
87*c8dee2aaSAndroid Build Coastguard Worker             fUniquelyKeyedEntryMap.remove(cur->key());
88*c8dee2aaSAndroid Build Coastguard Worker             fUniquelyKeyedEntryList.remove(cur);
89*c8dee2aaSAndroid Build Coastguard Worker             this->recycleEntry(cur);
90*c8dee2aaSAndroid Build Coastguard Worker         }
91*c8dee2aaSAndroid Build Coastguard Worker 
92*c8dee2aaSAndroid Build Coastguard Worker         cur = prev;
93*c8dee2aaSAndroid Build Coastguard Worker         prev = cur ? cur->fPrev : nullptr;
94*c8dee2aaSAndroid Build Coastguard Worker     }
95*c8dee2aaSAndroid Build Coastguard Worker }
96*c8dee2aaSAndroid Build Coastguard Worker 
dropUniqueRefsOlderThan(skgpu::StdSteadyClock::time_point purgeTime)97*c8dee2aaSAndroid Build Coastguard Worker void GrThreadSafeCache::dropUniqueRefsOlderThan(skgpu::StdSteadyClock::time_point purgeTime) {
98*c8dee2aaSAndroid Build Coastguard Worker     SkAutoSpinlock lock{fSpinLock};
99*c8dee2aaSAndroid Build Coastguard Worker 
100*c8dee2aaSAndroid Build Coastguard Worker     // Iterate from LRU to MRU
101*c8dee2aaSAndroid Build Coastguard Worker     Entry* cur = fUniquelyKeyedEntryList.tail();
102*c8dee2aaSAndroid Build Coastguard Worker     Entry* prev = cur ? cur->fPrev : nullptr;
103*c8dee2aaSAndroid Build Coastguard Worker 
104*c8dee2aaSAndroid Build Coastguard Worker     while (cur) {
105*c8dee2aaSAndroid Build Coastguard Worker         if (cur->fLastAccess >= purgeTime) {
106*c8dee2aaSAndroid Build Coastguard Worker             // This entry and all the remaining ones in the list will be newer than 'purgeTime'
107*c8dee2aaSAndroid Build Coastguard Worker             return;
108*c8dee2aaSAndroid Build Coastguard Worker         }
109*c8dee2aaSAndroid Build Coastguard Worker 
110*c8dee2aaSAndroid Build Coastguard Worker         if (cur->uniquelyHeld()) {
111*c8dee2aaSAndroid Build Coastguard Worker             fUniquelyKeyedEntryMap.remove(cur->key());
112*c8dee2aaSAndroid Build Coastguard Worker             fUniquelyKeyedEntryList.remove(cur);
113*c8dee2aaSAndroid Build Coastguard Worker             this->recycleEntry(cur);
114*c8dee2aaSAndroid Build Coastguard Worker         }
115*c8dee2aaSAndroid Build Coastguard Worker 
116*c8dee2aaSAndroid Build Coastguard Worker         cur = prev;
117*c8dee2aaSAndroid Build Coastguard Worker         prev = cur ? cur->fPrev : nullptr;
118*c8dee2aaSAndroid Build Coastguard Worker     }
119*c8dee2aaSAndroid Build Coastguard Worker }
120*c8dee2aaSAndroid Build Coastguard Worker 
makeExistingEntryMRU(Entry * entry)121*c8dee2aaSAndroid Build Coastguard Worker void GrThreadSafeCache::makeExistingEntryMRU(Entry* entry) {
122*c8dee2aaSAndroid Build Coastguard Worker     SkASSERT(fUniquelyKeyedEntryList.isInList(entry));
123*c8dee2aaSAndroid Build Coastguard Worker 
124*c8dee2aaSAndroid Build Coastguard Worker     entry->fLastAccess = skgpu::StdSteadyClock::now();
125*c8dee2aaSAndroid Build Coastguard Worker     fUniquelyKeyedEntryList.remove(entry);
126*c8dee2aaSAndroid Build Coastguard Worker     fUniquelyKeyedEntryList.addToHead(entry);
127*c8dee2aaSAndroid Build Coastguard Worker }
128*c8dee2aaSAndroid Build Coastguard Worker 
internalFind(const skgpu::UniqueKey & key)129*c8dee2aaSAndroid Build Coastguard Worker std::tuple<GrSurfaceProxyView, sk_sp<SkData>> GrThreadSafeCache::internalFind(
130*c8dee2aaSAndroid Build Coastguard Worker                                                        const skgpu::UniqueKey& key) {
131*c8dee2aaSAndroid Build Coastguard Worker     Entry* tmp = fUniquelyKeyedEntryMap.find(key);
132*c8dee2aaSAndroid Build Coastguard Worker     if (tmp) {
133*c8dee2aaSAndroid Build Coastguard Worker         this->makeExistingEntryMRU(tmp);
134*c8dee2aaSAndroid Build Coastguard Worker         return { tmp->view(), tmp->refCustomData() };
135*c8dee2aaSAndroid Build Coastguard Worker     }
136*c8dee2aaSAndroid Build Coastguard Worker 
137*c8dee2aaSAndroid Build Coastguard Worker     return {};
138*c8dee2aaSAndroid Build Coastguard Worker }
139*c8dee2aaSAndroid Build Coastguard Worker 
140*c8dee2aaSAndroid Build Coastguard Worker #ifdef SK_DEBUG
has(const skgpu::UniqueKey & key)141*c8dee2aaSAndroid Build Coastguard Worker bool GrThreadSafeCache::has(const skgpu::UniqueKey& key) {
142*c8dee2aaSAndroid Build Coastguard Worker     SkAutoSpinlock lock{fSpinLock};
143*c8dee2aaSAndroid Build Coastguard Worker 
144*c8dee2aaSAndroid Build Coastguard Worker     Entry* tmp = fUniquelyKeyedEntryMap.find(key);
145*c8dee2aaSAndroid Build Coastguard Worker     return SkToBool(tmp);
146*c8dee2aaSAndroid Build Coastguard Worker }
147*c8dee2aaSAndroid Build Coastguard Worker #endif
148*c8dee2aaSAndroid Build Coastguard Worker 
find(const skgpu::UniqueKey & key)149*c8dee2aaSAndroid Build Coastguard Worker GrSurfaceProxyView GrThreadSafeCache::find(const skgpu::UniqueKey& key) {
150*c8dee2aaSAndroid Build Coastguard Worker     SkAutoSpinlock lock{fSpinLock};
151*c8dee2aaSAndroid Build Coastguard Worker 
152*c8dee2aaSAndroid Build Coastguard Worker     GrSurfaceProxyView view;
153*c8dee2aaSAndroid Build Coastguard Worker     std::tie(view, std::ignore) = this->internalFind(key);
154*c8dee2aaSAndroid Build Coastguard Worker     return view;
155*c8dee2aaSAndroid Build Coastguard Worker }
156*c8dee2aaSAndroid Build Coastguard Worker 
findWithData(const skgpu::UniqueKey & key)157*c8dee2aaSAndroid Build Coastguard Worker std::tuple<GrSurfaceProxyView, sk_sp<SkData>> GrThreadSafeCache::findWithData(
158*c8dee2aaSAndroid Build Coastguard Worker         const skgpu::UniqueKey& key) {
159*c8dee2aaSAndroid Build Coastguard Worker     SkAutoSpinlock lock{fSpinLock};
160*c8dee2aaSAndroid Build Coastguard Worker 
161*c8dee2aaSAndroid Build Coastguard Worker     return this->internalFind(key);
162*c8dee2aaSAndroid Build Coastguard Worker }
163*c8dee2aaSAndroid Build Coastguard Worker 
getEntry(const skgpu::UniqueKey & key,const GrSurfaceProxyView & view)164*c8dee2aaSAndroid Build Coastguard Worker GrThreadSafeCache::Entry* GrThreadSafeCache::getEntry(const skgpu::UniqueKey& key,
165*c8dee2aaSAndroid Build Coastguard Worker                                                       const GrSurfaceProxyView& view) {
166*c8dee2aaSAndroid Build Coastguard Worker     Entry* entry;
167*c8dee2aaSAndroid Build Coastguard Worker 
168*c8dee2aaSAndroid Build Coastguard Worker     if (fFreeEntryList) {
169*c8dee2aaSAndroid Build Coastguard Worker         entry = fFreeEntryList;
170*c8dee2aaSAndroid Build Coastguard Worker         fFreeEntryList = entry->fNext;
171*c8dee2aaSAndroid Build Coastguard Worker         entry->fNext = nullptr;
172*c8dee2aaSAndroid Build Coastguard Worker 
173*c8dee2aaSAndroid Build Coastguard Worker         entry->set(key, view);
174*c8dee2aaSAndroid Build Coastguard Worker     } else {
175*c8dee2aaSAndroid Build Coastguard Worker         entry = fEntryAllocator.make<Entry>(key, view);
176*c8dee2aaSAndroid Build Coastguard Worker     }
177*c8dee2aaSAndroid Build Coastguard Worker 
178*c8dee2aaSAndroid Build Coastguard Worker     return this->makeNewEntryMRU(entry);
179*c8dee2aaSAndroid Build Coastguard Worker }
180*c8dee2aaSAndroid Build Coastguard Worker 
makeNewEntryMRU(Entry * entry)181*c8dee2aaSAndroid Build Coastguard Worker GrThreadSafeCache::Entry* GrThreadSafeCache::makeNewEntryMRU(Entry* entry) {
182*c8dee2aaSAndroid Build Coastguard Worker     entry->fLastAccess = skgpu::StdSteadyClock::now();
183*c8dee2aaSAndroid Build Coastguard Worker     fUniquelyKeyedEntryList.addToHead(entry);
184*c8dee2aaSAndroid Build Coastguard Worker     fUniquelyKeyedEntryMap.add(entry);
185*c8dee2aaSAndroid Build Coastguard Worker     return entry;
186*c8dee2aaSAndroid Build Coastguard Worker }
187*c8dee2aaSAndroid Build Coastguard Worker 
getEntry(const skgpu::UniqueKey & key,sk_sp<VertexData> vertData)188*c8dee2aaSAndroid Build Coastguard Worker GrThreadSafeCache::Entry* GrThreadSafeCache::getEntry(const skgpu::UniqueKey& key,
189*c8dee2aaSAndroid Build Coastguard Worker                                                       sk_sp<VertexData> vertData) {
190*c8dee2aaSAndroid Build Coastguard Worker     Entry* entry;
191*c8dee2aaSAndroid Build Coastguard Worker 
192*c8dee2aaSAndroid Build Coastguard Worker     if (fFreeEntryList) {
193*c8dee2aaSAndroid Build Coastguard Worker         entry = fFreeEntryList;
194*c8dee2aaSAndroid Build Coastguard Worker         fFreeEntryList = entry->fNext;
195*c8dee2aaSAndroid Build Coastguard Worker         entry->fNext = nullptr;
196*c8dee2aaSAndroid Build Coastguard Worker 
197*c8dee2aaSAndroid Build Coastguard Worker         entry->set(key, std::move(vertData));
198*c8dee2aaSAndroid Build Coastguard Worker     } else {
199*c8dee2aaSAndroid Build Coastguard Worker         entry = fEntryAllocator.make<Entry>(key, std::move(vertData));
200*c8dee2aaSAndroid Build Coastguard Worker     }
201*c8dee2aaSAndroid Build Coastguard Worker 
202*c8dee2aaSAndroid Build Coastguard Worker     return this->makeNewEntryMRU(entry);
203*c8dee2aaSAndroid Build Coastguard Worker }
204*c8dee2aaSAndroid Build Coastguard Worker 
recycleEntry(Entry * dead)205*c8dee2aaSAndroid Build Coastguard Worker void GrThreadSafeCache::recycleEntry(Entry* dead) {
206*c8dee2aaSAndroid Build Coastguard Worker     SkASSERT(!dead->fPrev && !dead->fNext && !dead->fList);
207*c8dee2aaSAndroid Build Coastguard Worker 
208*c8dee2aaSAndroid Build Coastguard Worker     dead->makeEmpty();
209*c8dee2aaSAndroid Build Coastguard Worker 
210*c8dee2aaSAndroid Build Coastguard Worker     dead->fNext = fFreeEntryList;
211*c8dee2aaSAndroid Build Coastguard Worker     fFreeEntryList = dead;
212*c8dee2aaSAndroid Build Coastguard Worker }
213*c8dee2aaSAndroid Build Coastguard Worker 
internalAdd(const skgpu::UniqueKey & key,const GrSurfaceProxyView & view)214*c8dee2aaSAndroid Build Coastguard Worker std::tuple<GrSurfaceProxyView, sk_sp<SkData>> GrThreadSafeCache::internalAdd(
215*c8dee2aaSAndroid Build Coastguard Worker                                                                 const skgpu::UniqueKey& key,
216*c8dee2aaSAndroid Build Coastguard Worker                                                                 const GrSurfaceProxyView& view) {
217*c8dee2aaSAndroid Build Coastguard Worker     Entry* tmp = fUniquelyKeyedEntryMap.find(key);
218*c8dee2aaSAndroid Build Coastguard Worker     if (!tmp) {
219*c8dee2aaSAndroid Build Coastguard Worker         tmp = this->getEntry(key, view);
220*c8dee2aaSAndroid Build Coastguard Worker 
221*c8dee2aaSAndroid Build Coastguard Worker         SkASSERT(fUniquelyKeyedEntryMap.find(key));
222*c8dee2aaSAndroid Build Coastguard Worker     }
223*c8dee2aaSAndroid Build Coastguard Worker 
224*c8dee2aaSAndroid Build Coastguard Worker     return { tmp->view(), tmp->refCustomData() };
225*c8dee2aaSAndroid Build Coastguard Worker }
226*c8dee2aaSAndroid Build Coastguard Worker 
add(const skgpu::UniqueKey & key,const GrSurfaceProxyView & view)227*c8dee2aaSAndroid Build Coastguard Worker GrSurfaceProxyView GrThreadSafeCache::add(const skgpu::UniqueKey& key,
228*c8dee2aaSAndroid Build Coastguard Worker                                           const GrSurfaceProxyView& view) {
229*c8dee2aaSAndroid Build Coastguard Worker     SkAutoSpinlock lock{fSpinLock};
230*c8dee2aaSAndroid Build Coastguard Worker 
231*c8dee2aaSAndroid Build Coastguard Worker     GrSurfaceProxyView newView;
232*c8dee2aaSAndroid Build Coastguard Worker     std::tie(newView, std::ignore) = this->internalAdd(key, view);
233*c8dee2aaSAndroid Build Coastguard Worker     return newView;
234*c8dee2aaSAndroid Build Coastguard Worker }
235*c8dee2aaSAndroid Build Coastguard Worker 
addWithData(const skgpu::UniqueKey & key,const GrSurfaceProxyView & view)236*c8dee2aaSAndroid Build Coastguard Worker std::tuple<GrSurfaceProxyView, sk_sp<SkData>> GrThreadSafeCache::addWithData(
237*c8dee2aaSAndroid Build Coastguard Worker                                                                 const skgpu::UniqueKey& key,
238*c8dee2aaSAndroid Build Coastguard Worker                                                                 const GrSurfaceProxyView& view) {
239*c8dee2aaSAndroid Build Coastguard Worker     SkAutoSpinlock lock{fSpinLock};
240*c8dee2aaSAndroid Build Coastguard Worker 
241*c8dee2aaSAndroid Build Coastguard Worker     return this->internalAdd(key, view);
242*c8dee2aaSAndroid Build Coastguard Worker }
243*c8dee2aaSAndroid Build Coastguard Worker 
findOrAdd(const skgpu::UniqueKey & key,const GrSurfaceProxyView & v)244*c8dee2aaSAndroid Build Coastguard Worker GrSurfaceProxyView GrThreadSafeCache::findOrAdd(const skgpu::UniqueKey& key,
245*c8dee2aaSAndroid Build Coastguard Worker                                                 const GrSurfaceProxyView& v) {
246*c8dee2aaSAndroid Build Coastguard Worker     SkAutoSpinlock lock{fSpinLock};
247*c8dee2aaSAndroid Build Coastguard Worker 
248*c8dee2aaSAndroid Build Coastguard Worker     GrSurfaceProxyView view;
249*c8dee2aaSAndroid Build Coastguard Worker     std::tie(view, std::ignore) = this->internalFind(key);
250*c8dee2aaSAndroid Build Coastguard Worker     if (view) {
251*c8dee2aaSAndroid Build Coastguard Worker         return view;
252*c8dee2aaSAndroid Build Coastguard Worker     }
253*c8dee2aaSAndroid Build Coastguard Worker 
254*c8dee2aaSAndroid Build Coastguard Worker     std::tie(view, std::ignore) = this->internalAdd(key, v);
255*c8dee2aaSAndroid Build Coastguard Worker     return view;
256*c8dee2aaSAndroid Build Coastguard Worker }
257*c8dee2aaSAndroid Build Coastguard Worker 
findOrAddWithData(const skgpu::UniqueKey & key,const GrSurfaceProxyView & v)258*c8dee2aaSAndroid Build Coastguard Worker std::tuple<GrSurfaceProxyView, sk_sp<SkData>> GrThreadSafeCache::findOrAddWithData(
259*c8dee2aaSAndroid Build Coastguard Worker                                                                       const skgpu::UniqueKey& key,
260*c8dee2aaSAndroid Build Coastguard Worker                                                                       const GrSurfaceProxyView& v) {
261*c8dee2aaSAndroid Build Coastguard Worker     SkAutoSpinlock lock{fSpinLock};
262*c8dee2aaSAndroid Build Coastguard Worker 
263*c8dee2aaSAndroid Build Coastguard Worker     auto [view, data] = this->internalFind(key);
264*c8dee2aaSAndroid Build Coastguard Worker     if (view) {
265*c8dee2aaSAndroid Build Coastguard Worker         return { std::move(view), std::move(data) };
266*c8dee2aaSAndroid Build Coastguard Worker     }
267*c8dee2aaSAndroid Build Coastguard Worker 
268*c8dee2aaSAndroid Build Coastguard Worker     return this->internalAdd(key, v);
269*c8dee2aaSAndroid Build Coastguard Worker }
270*c8dee2aaSAndroid Build Coastguard Worker 
MakeVertexData(const void * vertices,int vertexCount,size_t vertexSize)271*c8dee2aaSAndroid Build Coastguard Worker sk_sp<GrThreadSafeCache::VertexData> GrThreadSafeCache::MakeVertexData(const void* vertices,
272*c8dee2aaSAndroid Build Coastguard Worker                                                                        int vertexCount,
273*c8dee2aaSAndroid Build Coastguard Worker                                                                        size_t vertexSize) {
274*c8dee2aaSAndroid Build Coastguard Worker     return sk_sp<VertexData>(new VertexData(vertices, vertexCount, vertexSize));
275*c8dee2aaSAndroid Build Coastguard Worker }
276*c8dee2aaSAndroid Build Coastguard Worker 
MakeVertexData(sk_sp<GrGpuBuffer> buffer,int vertexCount,size_t vertexSize)277*c8dee2aaSAndroid Build Coastguard Worker sk_sp<GrThreadSafeCache::VertexData> GrThreadSafeCache::MakeVertexData(sk_sp<GrGpuBuffer> buffer,
278*c8dee2aaSAndroid Build Coastguard Worker                                                                        int vertexCount,
279*c8dee2aaSAndroid Build Coastguard Worker                                                                        size_t vertexSize) {
280*c8dee2aaSAndroid Build Coastguard Worker     return sk_sp<VertexData>(new VertexData(std::move(buffer), vertexCount, vertexSize));
281*c8dee2aaSAndroid Build Coastguard Worker }
282*c8dee2aaSAndroid Build Coastguard Worker 
283*c8dee2aaSAndroid Build Coastguard Worker std::tuple<sk_sp<GrThreadSafeCache::VertexData>, sk_sp<SkData>>
internalFindVerts(const skgpu::UniqueKey & key)284*c8dee2aaSAndroid Build Coastguard Worker         GrThreadSafeCache::internalFindVerts(const skgpu::UniqueKey& key) {
285*c8dee2aaSAndroid Build Coastguard Worker     Entry* tmp = fUniquelyKeyedEntryMap.find(key);
286*c8dee2aaSAndroid Build Coastguard Worker     if (tmp) {
287*c8dee2aaSAndroid Build Coastguard Worker         this->makeExistingEntryMRU(tmp);
288*c8dee2aaSAndroid Build Coastguard Worker         return { tmp->vertexData(), tmp->refCustomData() };
289*c8dee2aaSAndroid Build Coastguard Worker     }
290*c8dee2aaSAndroid Build Coastguard Worker 
291*c8dee2aaSAndroid Build Coastguard Worker     return {};
292*c8dee2aaSAndroid Build Coastguard Worker }
293*c8dee2aaSAndroid Build Coastguard Worker 
294*c8dee2aaSAndroid Build Coastguard Worker std::tuple<sk_sp<GrThreadSafeCache::VertexData>, sk_sp<SkData>>
findVertsWithData(const skgpu::UniqueKey & key)295*c8dee2aaSAndroid Build Coastguard Worker         GrThreadSafeCache::findVertsWithData(const skgpu::UniqueKey& key) {
296*c8dee2aaSAndroid Build Coastguard Worker     SkAutoSpinlock lock{fSpinLock};
297*c8dee2aaSAndroid Build Coastguard Worker 
298*c8dee2aaSAndroid Build Coastguard Worker     return this->internalFindVerts(key);
299*c8dee2aaSAndroid Build Coastguard Worker }
300*c8dee2aaSAndroid Build Coastguard Worker 
internalAddVerts(const skgpu::UniqueKey & key,sk_sp<VertexData> vertData,IsNewerBetter isNewerBetter)301*c8dee2aaSAndroid Build Coastguard Worker std::tuple<sk_sp<GrThreadSafeCache::VertexData>, sk_sp<SkData>> GrThreadSafeCache::internalAddVerts(
302*c8dee2aaSAndroid Build Coastguard Worker                                                                     const skgpu::UniqueKey& key,
303*c8dee2aaSAndroid Build Coastguard Worker                                                                     sk_sp<VertexData> vertData,
304*c8dee2aaSAndroid Build Coastguard Worker                                                                     IsNewerBetter isNewerBetter) {
305*c8dee2aaSAndroid Build Coastguard Worker     Entry* tmp = fUniquelyKeyedEntryMap.find(key);
306*c8dee2aaSAndroid Build Coastguard Worker     if (!tmp) {
307*c8dee2aaSAndroid Build Coastguard Worker         tmp = this->getEntry(key, std::move(vertData));
308*c8dee2aaSAndroid Build Coastguard Worker 
309*c8dee2aaSAndroid Build Coastguard Worker         SkASSERT(fUniquelyKeyedEntryMap.find(key));
310*c8dee2aaSAndroid Build Coastguard Worker     } else if (isNewerBetter(tmp->getCustomData(), key.getCustomData())) {
311*c8dee2aaSAndroid Build Coastguard Worker         // This orphans any existing uses of the prior vertex data but ensures the best
312*c8dee2aaSAndroid Build Coastguard Worker         // version is in the cache.
313*c8dee2aaSAndroid Build Coastguard Worker         tmp->set(key, std::move(vertData));
314*c8dee2aaSAndroid Build Coastguard Worker     }
315*c8dee2aaSAndroid Build Coastguard Worker 
316*c8dee2aaSAndroid Build Coastguard Worker     return { tmp->vertexData(), tmp->refCustomData() };
317*c8dee2aaSAndroid Build Coastguard Worker }
318*c8dee2aaSAndroid Build Coastguard Worker 
addVertsWithData(const skgpu::UniqueKey & key,sk_sp<VertexData> vertData,IsNewerBetter isNewerBetter)319*c8dee2aaSAndroid Build Coastguard Worker std::tuple<sk_sp<GrThreadSafeCache::VertexData>, sk_sp<SkData>> GrThreadSafeCache::addVertsWithData(
320*c8dee2aaSAndroid Build Coastguard Worker                                                                     const skgpu::UniqueKey& key,
321*c8dee2aaSAndroid Build Coastguard Worker                                                                     sk_sp<VertexData> vertData,
322*c8dee2aaSAndroid Build Coastguard Worker                                                                     IsNewerBetter isNewerBetter) {
323*c8dee2aaSAndroid Build Coastguard Worker     SkAutoSpinlock lock{fSpinLock};
324*c8dee2aaSAndroid Build Coastguard Worker 
325*c8dee2aaSAndroid Build Coastguard Worker     return this->internalAddVerts(key, std::move(vertData), isNewerBetter);
326*c8dee2aaSAndroid Build Coastguard Worker }
327*c8dee2aaSAndroid Build Coastguard Worker 
remove(const skgpu::UniqueKey & key)328*c8dee2aaSAndroid Build Coastguard Worker void GrThreadSafeCache::remove(const skgpu::UniqueKey& key) {
329*c8dee2aaSAndroid Build Coastguard Worker     SkAutoSpinlock lock{fSpinLock};
330*c8dee2aaSAndroid Build Coastguard Worker 
331*c8dee2aaSAndroid Build Coastguard Worker     Entry* tmp = fUniquelyKeyedEntryMap.find(key);
332*c8dee2aaSAndroid Build Coastguard Worker     if (tmp) {
333*c8dee2aaSAndroid Build Coastguard Worker         fUniquelyKeyedEntryMap.remove(key);
334*c8dee2aaSAndroid Build Coastguard Worker         fUniquelyKeyedEntryList.remove(tmp);
335*c8dee2aaSAndroid Build Coastguard Worker         this->recycleEntry(tmp);
336*c8dee2aaSAndroid Build Coastguard Worker     }
337*c8dee2aaSAndroid Build Coastguard Worker }
338*c8dee2aaSAndroid Build Coastguard Worker 
339*c8dee2aaSAndroid Build Coastguard Worker std::tuple<GrSurfaceProxyView, sk_sp<GrThreadSafeCache::Trampoline>>
CreateLazyView(GrDirectContext * dContext,GrColorType origCT,SkISize dimensions,GrSurfaceOrigin origin,SkBackingFit fit)340*c8dee2aaSAndroid Build Coastguard Worker GrThreadSafeCache::CreateLazyView(GrDirectContext* dContext,
341*c8dee2aaSAndroid Build Coastguard Worker                                   GrColorType origCT,
342*c8dee2aaSAndroid Build Coastguard Worker                                   SkISize dimensions,
343*c8dee2aaSAndroid Build Coastguard Worker                                   GrSurfaceOrigin origin,
344*c8dee2aaSAndroid Build Coastguard Worker                                   SkBackingFit fit) {
345*c8dee2aaSAndroid Build Coastguard Worker     GrProxyProvider* proxyProvider = dContext->priv().proxyProvider();
346*c8dee2aaSAndroid Build Coastguard Worker     const GrCaps* caps = dContext->priv().caps();
347*c8dee2aaSAndroid Build Coastguard Worker 
348*c8dee2aaSAndroid Build Coastguard Worker     constexpr int kSampleCnt = 1;
349*c8dee2aaSAndroid Build Coastguard Worker     auto [newCT, format] = caps->getFallbackColorTypeAndFormat(origCT, kSampleCnt);
350*c8dee2aaSAndroid Build Coastguard Worker 
351*c8dee2aaSAndroid Build Coastguard Worker     if (newCT == GrColorType::kUnknown) {
352*c8dee2aaSAndroid Build Coastguard Worker         return {GrSurfaceProxyView(nullptr), nullptr};
353*c8dee2aaSAndroid Build Coastguard Worker     }
354*c8dee2aaSAndroid Build Coastguard Worker 
355*c8dee2aaSAndroid Build Coastguard Worker     sk_sp<Trampoline> trampoline(new Trampoline);
356*c8dee2aaSAndroid Build Coastguard Worker 
357*c8dee2aaSAndroid Build Coastguard Worker     GrProxyProvider::TextureInfo texInfo{skgpu::Mipmapped::kNo, GrTextureType::k2D};
358*c8dee2aaSAndroid Build Coastguard Worker 
359*c8dee2aaSAndroid Build Coastguard Worker     sk_sp<GrRenderTargetProxy> proxy = proxyProvider->createLazyRenderTargetProxy(
360*c8dee2aaSAndroid Build Coastguard Worker             [trampoline](
361*c8dee2aaSAndroid Build Coastguard Worker                     GrResourceProvider* resourceProvider,
362*c8dee2aaSAndroid Build Coastguard Worker                     const GrSurfaceProxy::LazySurfaceDesc&) -> GrSurfaceProxy::LazyCallbackResult {
363*c8dee2aaSAndroid Build Coastguard Worker                 if (!resourceProvider || !trampoline->fProxy ||
364*c8dee2aaSAndroid Build Coastguard Worker                     !trampoline->fProxy->isInstantiated()) {
365*c8dee2aaSAndroid Build Coastguard Worker                     return GrSurfaceProxy::LazyCallbackResult(nullptr, true);
366*c8dee2aaSAndroid Build Coastguard Worker                 }
367*c8dee2aaSAndroid Build Coastguard Worker 
368*c8dee2aaSAndroid Build Coastguard Worker                 SkASSERT(!trampoline->fProxy->peekTexture()->getUniqueKey().isValid());
369*c8dee2aaSAndroid Build Coastguard Worker                 return GrSurfaceProxy::LazyCallbackResult(
370*c8dee2aaSAndroid Build Coastguard Worker                         sk_ref_sp(trampoline->fProxy->peekTexture()));
371*c8dee2aaSAndroid Build Coastguard Worker             },
372*c8dee2aaSAndroid Build Coastguard Worker             format,
373*c8dee2aaSAndroid Build Coastguard Worker             dimensions,
374*c8dee2aaSAndroid Build Coastguard Worker             kSampleCnt,
375*c8dee2aaSAndroid Build Coastguard Worker             GrInternalSurfaceFlags::kNone,
376*c8dee2aaSAndroid Build Coastguard Worker             &texInfo,
377*c8dee2aaSAndroid Build Coastguard Worker             GrMipmapStatus::kNotAllocated,
378*c8dee2aaSAndroid Build Coastguard Worker             fit,
379*c8dee2aaSAndroid Build Coastguard Worker             skgpu::Budgeted::kYes,
380*c8dee2aaSAndroid Build Coastguard Worker             GrProtected::kNo,
381*c8dee2aaSAndroid Build Coastguard Worker             /* wrapsVkSecondaryCB */ false,
382*c8dee2aaSAndroid Build Coastguard Worker             GrSurfaceProxy::UseAllocator::kYes);
383*c8dee2aaSAndroid Build Coastguard Worker 
384*c8dee2aaSAndroid Build Coastguard Worker     // TODO: It seems like this 'newCT' usage should be 'origCT' but this is
385*c8dee2aaSAndroid Build Coastguard Worker     // what skgpu::ganesh::SurfaceDrawContext::MakeWithFallback does
386*c8dee2aaSAndroid Build Coastguard Worker     skgpu::Swizzle swizzle = dContext->priv().caps()->getReadSwizzle(format, newCT);
387*c8dee2aaSAndroid Build Coastguard Worker 
388*c8dee2aaSAndroid Build Coastguard Worker     return {{std::move(proxy), origin, swizzle}, std::move(trampoline)};
389*c8dee2aaSAndroid Build Coastguard Worker }
390