blob: 9e8a5cce2505ed9571fc4c8561f6744edaea8b92 [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 Phillipsd464feb2020-10-08 11:00:02 -040016GrThreadSafeCache::GrThreadSafeCache()
Robert Phillips45593682020-09-18 16:16:33 -040017 : fFreeEntryList(nullptr) {
18}
Robert Phillips26f3aeb2020-09-16 10:57:32 -040019
Robert Phillipsd464feb2020-10-08 11:00:02 -040020GrThreadSafeCache::~GrThreadSafeCache() {
Robert Phillips45593682020-09-18 16:16:33 -040021 this->dropAllRefs();
Robert Phillips26f3aeb2020-09-16 10:57:32 -040022}
23
24#if GR_TEST_UTILS
Robert Phillipsd464feb2020-10-08 11:00:02 -040025int GrThreadSafeCache::numEntries() const {
Robert Phillips26f3aeb2020-09-16 10:57:32 -040026 SkAutoSpinlock lock{fSpinLock};
27
Robert Phillips45593682020-09-18 16:16:33 -040028 return fUniquelyKeyedProxyViewMap.count();
Robert Phillips26f3aeb2020-09-16 10:57:32 -040029}
30
Robert Phillipsd464feb2020-10-08 11:00:02 -040031size_t GrThreadSafeCache::approxBytesUsedForHash() const {
Robert Phillips26f3aeb2020-09-16 10:57:32 -040032 SkAutoSpinlock lock{fSpinLock};
33
Robert Phillipsc61c8952020-09-22 14:24:43 -040034 return fUniquelyKeyedProxyViewMap.approxBytesUsed();
Robert Phillips26f3aeb2020-09-16 10:57:32 -040035}
36#endif
37
Robert Phillipsd464feb2020-10-08 11:00:02 -040038void GrThreadSafeCache::dropAllRefs() {
Robert Phillips26f3aeb2020-09-16 10:57:32 -040039 SkAutoSpinlock lock{fSpinLock};
40
Robert Phillips45593682020-09-18 16:16:33 -040041 fUniquelyKeyedProxyViewMap.reset();
42 while (auto tmp = fUniquelyKeyedProxyViewList.head()) {
43 fUniquelyKeyedProxyViewList.remove(tmp);
44 this->recycleEntry(tmp);
45 }
46 // TODO: should we empty out the fFreeEntryList and reset fEntryAllocator?
Robert Phillips26f3aeb2020-09-16 10:57:32 -040047}
48
Robert Phillips3380be92020-09-25 12:47:10 -040049// TODO: If iterating becomes too expensive switch to using something like GrIORef for the
50// GrSurfaceProxy
Robert Phillipsd464feb2020-10-08 11:00:02 -040051void GrThreadSafeCache::dropUniqueRefs(GrResourceCache* resourceCache) {
Robert Phillips12d06a32020-09-16 12:31:34 -040052 SkAutoSpinlock lock{fSpinLock};
53
Robert Phillips187b04b2020-09-22 12:18:16 -040054 // Iterate from LRU to MRU
55 Entry* cur = fUniquelyKeyedProxyViewList.tail();
56 Entry* prev = cur ? cur->fPrev : nullptr;
Robert Phillips45593682020-09-18 16:16:33 -040057
58 while (cur) {
Robert Phillips187b04b2020-09-22 12:18:16 -040059 if (resourceCache && !resourceCache->overBudget()) {
60 return;
61 }
62
Robert Phillips45593682020-09-18 16:16:33 -040063 if (cur->fView.proxy()->unique()) {
64 fUniquelyKeyedProxyViewMap.remove(cur->fKey);
65 fUniquelyKeyedProxyViewList.remove(cur);
66 this->recycleEntry(cur);
67 }
68
Robert Phillips187b04b2020-09-22 12:18:16 -040069 cur = prev;
70 prev = cur ? cur->fPrev : nullptr;
Robert Phillips45593682020-09-18 16:16:33 -040071 }
Robert Phillips12d06a32020-09-16 12:31:34 -040072}
73
Robert Phillipsd464feb2020-10-08 11:00:02 -040074void GrThreadSafeCache::dropUniqueRefsOlderThan(GrStdSteadyClock::time_point purgeTime) {
Robert Phillipsc2fe1642020-09-22 17:34:51 -040075 SkAutoSpinlock lock{fSpinLock};
76
77 // Iterate from LRU to MRU
78 Entry* cur = fUniquelyKeyedProxyViewList.tail();
79 Entry* prev = cur ? cur->fPrev : nullptr;
80
81 while (cur) {
82 if (cur->fLastAccess >= purgeTime) {
83 // This entry and all the remaining ones in the list will be newer than 'purgeTime'
84 return;
85 }
86
87 if (cur->fView.proxy()->unique()) {
88 fUniquelyKeyedProxyViewMap.remove(cur->fKey);
89 fUniquelyKeyedProxyViewList.remove(cur);
90 this->recycleEntry(cur);
91 }
92
93 cur = prev;
94 prev = cur ? cur->fPrev : nullptr;
95 }
96}
97
Robert Phillipsd464feb2020-10-08 11:00:02 -040098std::tuple<GrSurfaceProxyView, sk_sp<SkData>> GrThreadSafeCache::internalFind(
Robert Phillips6e17ffe2020-10-06 14:52:11 -040099 const GrUniqueKey& key) {
Robert Phillips45593682020-09-18 16:16:33 -0400100 Entry* tmp = fUniquelyKeyedProxyViewMap.find(key);
Robert Phillips26f3aeb2020-09-16 10:57:32 -0400101 if (tmp) {
Robert Phillips45593682020-09-18 16:16:33 -0400102 SkASSERT(fUniquelyKeyedProxyViewList.isInList(tmp));
103 // make the sought out entry the MRU
Robert Phillipsc2fe1642020-09-22 17:34:51 -0400104 tmp->fLastAccess = GrStdSteadyClock::now();
Robert Phillips45593682020-09-18 16:16:33 -0400105 fUniquelyKeyedProxyViewList.remove(tmp);
106 fUniquelyKeyedProxyViewList.addToHead(tmp);
Robert Phillips6e17ffe2020-10-06 14:52:11 -0400107 return { tmp->fView, tmp->fKey.refCustomData() };
Robert Phillips26f3aeb2020-09-16 10:57:32 -0400108 }
109
110 return {};
111}
112
Robert Phillipsd464feb2020-10-08 11:00:02 -0400113GrSurfaceProxyView GrThreadSafeCache::find(const GrUniqueKey& key) {
Robert Phillips6e17ffe2020-10-06 14:52:11 -0400114 SkAutoSpinlock lock{fSpinLock};
115
116 GrSurfaceProxyView view;
117 std::tie(view, std::ignore) = this->internalFind(key);
118 return view;
119}
120
Robert Phillipsd464feb2020-10-08 11:00:02 -0400121std::tuple<GrSurfaceProxyView, sk_sp<SkData>> GrThreadSafeCache::findWithData(
Robert Phillips6e17ffe2020-10-06 14:52:11 -0400122 const GrUniqueKey& key) {
123 SkAutoSpinlock lock{fSpinLock};
124
125 return this->internalFind(key);
126}
127
Robert Phillipsd464feb2020-10-08 11:00:02 -0400128GrThreadSafeCache::Entry* GrThreadSafeCache::getEntry(const GrUniqueKey& key,
129 const GrSurfaceProxyView& view) {
Robert Phillips45593682020-09-18 16:16:33 -0400130 Entry* entry;
131
132 if (fFreeEntryList) {
133 entry = fFreeEntryList;
134 fFreeEntryList = entry->fNext;
135 entry->fNext = nullptr;
136
137 entry->fKey = key;
138 entry->fView = view;
139 } else {
140 entry = fEntryAllocator.make<Entry>(key, view);
141 }
142
Robert Phillipsc2fe1642020-09-22 17:34:51 -0400143 // make 'entry' the MRU
144 entry->fLastAccess = GrStdSteadyClock::now();
145 fUniquelyKeyedProxyViewList.addToHead(entry);
Robert Phillips45593682020-09-18 16:16:33 -0400146 fUniquelyKeyedProxyViewMap.add(entry);
147 return entry;
148}
149
Robert Phillipsd464feb2020-10-08 11:00:02 -0400150void GrThreadSafeCache::recycleEntry(Entry* dead) {
Robert Phillips45593682020-09-18 16:16:33 -0400151 SkASSERT(!dead->fPrev && !dead->fNext && !dead->fList);
152
153 dead->fKey.reset();
154 dead->fView.reset();
155
156 dead->fNext = fFreeEntryList;
157 fFreeEntryList = dead;
158}
159
Robert Phillipsd464feb2020-10-08 11:00:02 -0400160std::tuple<GrSurfaceProxyView, sk_sp<SkData>> GrThreadSafeCache::internalAdd(
Robert Phillips26f3aeb2020-09-16 10:57:32 -0400161 const GrUniqueKey& key,
162 const GrSurfaceProxyView& view) {
Robert Phillips45593682020-09-18 16:16:33 -0400163 Entry* tmp = fUniquelyKeyedProxyViewMap.find(key);
Robert Phillips26f3aeb2020-09-16 10:57:32 -0400164 if (!tmp) {
Robert Phillipsf3e2b3c2020-09-18 14:07:43 -0400165 tmp = this->getEntry(key, view);
Robert Phillips45593682020-09-18 16:16:33 -0400166
167 SkASSERT(fUniquelyKeyedProxyViewMap.find(key));
Robert Phillips26f3aeb2020-09-16 10:57:32 -0400168 }
169
Robert Phillips6e17ffe2020-10-06 14:52:11 -0400170 return { tmp->fView, tmp->fKey.refCustomData() };
Robert Phillips26f3aeb2020-09-16 10:57:32 -0400171}
172
Robert Phillipsd464feb2020-10-08 11:00:02 -0400173GrSurfaceProxyView GrThreadSafeCache::add(const GrUniqueKey& key, const GrSurfaceProxyView& view) {
Robert Phillips26f3aeb2020-09-16 10:57:32 -0400174 SkAutoSpinlock lock{fSpinLock};
175
Robert Phillips6e17ffe2020-10-06 14:52:11 -0400176 GrSurfaceProxyView newView;
177 std::tie(newView, std::ignore) = this->internalAdd(key, view);
178 return newView;
179}
180
Robert Phillipsd464feb2020-10-08 11:00:02 -0400181std::tuple<GrSurfaceProxyView, sk_sp<SkData>> GrThreadSafeCache::addWithData(
Robert Phillips6e17ffe2020-10-06 14:52:11 -0400182 const GrUniqueKey& key,
183 const GrSurfaceProxyView& view) {
184 SkAutoSpinlock lock{fSpinLock};
185
Robert Phillips26f3aeb2020-09-16 10:57:32 -0400186 return this->internalAdd(key, view);
187}
Robert Phillips3380be92020-09-25 12:47:10 -0400188
Robert Phillipsd464feb2020-10-08 11:00:02 -0400189GrSurfaceProxyView GrThreadSafeCache::findOrAdd(const GrUniqueKey& key,
190 const GrSurfaceProxyView& v) {
Robert Phillips3380be92020-09-25 12:47:10 -0400191 SkAutoSpinlock lock{fSpinLock};
192
Robert Phillips6e17ffe2020-10-06 14:52:11 -0400193 GrSurfaceProxyView view;
194 std::tie(view, std::ignore) = this->internalFind(key);
195 if (view) {
196 return view;
197 }
198
199 std::tie(view, std::ignore) = this->internalAdd(key, v);
200 return view;
201}
202
Robert Phillipsd464feb2020-10-08 11:00:02 -0400203std::tuple<GrSurfaceProxyView, sk_sp<SkData>> GrThreadSafeCache::findOrAddWithData(
Robert Phillips6e17ffe2020-10-06 14:52:11 -0400204 const GrUniqueKey& key,
205 const GrSurfaceProxyView& v) {
206 SkAutoSpinlock lock{fSpinLock};
207
208 auto [view, data] = this->internalFind(key);
209 if (view) {
210 return { std::move(view), std::move(data) };
Robert Phillips3380be92020-09-25 12:47:10 -0400211 }
212
213 return this->internalAdd(key, v);
214}
215
Robert Phillipsd464feb2020-10-08 11:00:02 -0400216void GrThreadSafeCache::remove(const GrUniqueKey& key) {
Robert Phillips3380be92020-09-25 12:47:10 -0400217 SkAutoSpinlock lock{fSpinLock};
218
219 Entry* tmp = fUniquelyKeyedProxyViewMap.find(key);
220 if (tmp) {
221 fUniquelyKeyedProxyViewMap.remove(key);
222 fUniquelyKeyedProxyViewList.remove(tmp);
223 this->recycleEntry(tmp);
224 }
225}
Robert Phillipsb1807122020-10-06 16:44:18 -0400226
Robert Phillipsd464feb2020-10-08 11:00:02 -0400227std::tuple<GrSurfaceProxyView, sk_sp<GrThreadSafeCache::Trampoline>>
228GrThreadSafeCache::CreateLazyView(GrDirectContext* dContext,
229 GrColorType origCT,
230 SkISize dimensions,
231 GrSurfaceOrigin origin,
232 SkBackingFit fit) {
Robert Phillipsb1807122020-10-06 16:44:18 -0400233 GrProxyProvider* proxyProvider = dContext->priv().proxyProvider();
234
235 constexpr int kSampleCnt = 1;
236 auto [newCT, format] = GrRenderTargetContext::GetFallbackColorTypeAndFormat(
237 dContext, origCT, kSampleCnt);
238
239 if (newCT == GrColorType::kUnknown) {
240 return {GrSurfaceProxyView(nullptr), nullptr};
241 }
242
243 sk_sp<Trampoline> trampoline(new Trampoline);
244
245 GrProxyProvider::TextureInfo texInfo{ GrMipMapped::kNo, GrTextureType::k2D };
246
247 sk_sp<GrRenderTargetProxy> proxy = proxyProvider->createLazyRenderTargetProxy(
248 [trampoline](
249 GrResourceProvider* resourceProvider,
250 const GrSurfaceProxy::LazySurfaceDesc&) -> GrSurfaceProxy::LazyCallbackResult {
251 if (!resourceProvider || !trampoline->fProxy ||
252 !trampoline->fProxy->isInstantiated()) {
253 return GrSurfaceProxy::LazyCallbackResult(nullptr, true);
254 }
255
256 SkASSERT(!trampoline->fProxy->peekTexture()->getUniqueKey().isValid());
257 return GrSurfaceProxy::LazyCallbackResult(
258 sk_ref_sp(trampoline->fProxy->peekTexture()));
259 },
260 format,
261 dimensions,
262 kSampleCnt,
263 GrInternalSurfaceFlags::kNone,
264 &texInfo,
265 GrMipmapStatus::kNotAllocated,
Robert Phillipsfde67e42020-10-07 15:33:43 -0400266 fit,
Robert Phillipsb1807122020-10-06 16:44:18 -0400267 SkBudgeted::kYes,
268 GrProtected::kNo,
269 /* wrapsVkSecondaryCB */ false,
270 GrSurfaceProxy::UseAllocator::kYes);
271
272 // TODO: It seems like this 'newCT' usage should be 'origCT' but this is
273 // what GrRenderTargetContext::MakeWithFallback does
274 GrSwizzle swizzle = dContext->priv().caps()->getReadSwizzle(format, newCT);
275
276 return {{std::move(proxy), origin, swizzle}, std::move(trampoline)};
277}