blob: 312e2ba95d3f334b2850845ee6c949cb4db875a0 [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
8#include "src/gpu/GrThreadSafeUniquelyKeyedProxyViewCache.h"
9
Robert Phillipsb1807122020-10-06 16:44:18 -040010#include "include/gpu/GrDirectContext.h"
11#include "src/gpu/GrContextPriv.h"
12#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 Phillips45593682020-09-18 16:16:33 -040016GrThreadSafeUniquelyKeyedProxyViewCache::GrThreadSafeUniquelyKeyedProxyViewCache()
17 : fFreeEntryList(nullptr) {
18}
Robert Phillips26f3aeb2020-09-16 10:57:32 -040019
20GrThreadSafeUniquelyKeyedProxyViewCache::~GrThreadSafeUniquelyKeyedProxyViewCache() {
Robert Phillips45593682020-09-18 16:16:33 -040021 this->dropAllRefs();
Robert Phillips26f3aeb2020-09-16 10:57:32 -040022}
23
24#if GR_TEST_UTILS
25int GrThreadSafeUniquelyKeyedProxyViewCache::numEntries() const {
26 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 Phillipsc61c8952020-09-22 14:24:43 -040031size_t GrThreadSafeUniquelyKeyedProxyViewCache::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
38void GrThreadSafeUniquelyKeyedProxyViewCache::dropAllRefs() {
39 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 Phillips331699c2020-09-22 15:20:01 -040051void GrThreadSafeUniquelyKeyedProxyViewCache::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 Phillipsc2fe1642020-09-22 17:34:51 -040074void GrThreadSafeUniquelyKeyedProxyViewCache::dropUniqueRefsOlderThan(
75 GrStdSteadyClock::time_point purgeTime) {
76 SkAutoSpinlock lock{fSpinLock};
77
78 // Iterate from LRU to MRU
79 Entry* cur = fUniquelyKeyedProxyViewList.tail();
80 Entry* prev = cur ? cur->fPrev : nullptr;
81
82 while (cur) {
83 if (cur->fLastAccess >= purgeTime) {
84 // This entry and all the remaining ones in the list will be newer than 'purgeTime'
85 return;
86 }
87
88 if (cur->fView.proxy()->unique()) {
89 fUniquelyKeyedProxyViewMap.remove(cur->fKey);
90 fUniquelyKeyedProxyViewList.remove(cur);
91 this->recycleEntry(cur);
92 }
93
94 cur = prev;
95 prev = cur ? cur->fPrev : nullptr;
96 }
97}
98
Robert Phillips6e17ffe2020-10-06 14:52:11 -040099std::tuple<GrSurfaceProxyView, sk_sp<SkData>> GrThreadSafeUniquelyKeyedProxyViewCache::internalFind(
100 const GrUniqueKey& key) {
Robert Phillips45593682020-09-18 16:16:33 -0400101 Entry* tmp = fUniquelyKeyedProxyViewMap.find(key);
Robert Phillips26f3aeb2020-09-16 10:57:32 -0400102 if (tmp) {
Robert Phillips45593682020-09-18 16:16:33 -0400103 SkASSERT(fUniquelyKeyedProxyViewList.isInList(tmp));
104 // make the sought out entry the MRU
Robert Phillipsc2fe1642020-09-22 17:34:51 -0400105 tmp->fLastAccess = GrStdSteadyClock::now();
Robert Phillips45593682020-09-18 16:16:33 -0400106 fUniquelyKeyedProxyViewList.remove(tmp);
107 fUniquelyKeyedProxyViewList.addToHead(tmp);
Robert Phillips6e17ffe2020-10-06 14:52:11 -0400108 return { tmp->fView, tmp->fKey.refCustomData() };
Robert Phillips26f3aeb2020-09-16 10:57:32 -0400109 }
110
111 return {};
112}
113
Robert Phillips6e17ffe2020-10-06 14:52:11 -0400114GrSurfaceProxyView GrThreadSafeUniquelyKeyedProxyViewCache::find(const GrUniqueKey& key) {
115 SkAutoSpinlock lock{fSpinLock};
116
117 GrSurfaceProxyView view;
118 std::tie(view, std::ignore) = this->internalFind(key);
119 return view;
120}
121
122std::tuple<GrSurfaceProxyView, sk_sp<SkData>> GrThreadSafeUniquelyKeyedProxyViewCache::findWithData(
123 const GrUniqueKey& key) {
124 SkAutoSpinlock lock{fSpinLock};
125
126 return this->internalFind(key);
127}
128
Robert Phillips45593682020-09-18 16:16:33 -0400129GrThreadSafeUniquelyKeyedProxyViewCache::Entry*
130GrThreadSafeUniquelyKeyedProxyViewCache::getEntry(const GrUniqueKey& key,
131 const GrSurfaceProxyView& view) {
132 Entry* entry;
133
134 if (fFreeEntryList) {
135 entry = fFreeEntryList;
136 fFreeEntryList = entry->fNext;
137 entry->fNext = nullptr;
138
139 entry->fKey = key;
140 entry->fView = view;
141 } else {
142 entry = fEntryAllocator.make<Entry>(key, view);
143 }
144
Robert Phillipsc2fe1642020-09-22 17:34:51 -0400145 // make 'entry' the MRU
146 entry->fLastAccess = GrStdSteadyClock::now();
147 fUniquelyKeyedProxyViewList.addToHead(entry);
Robert Phillips45593682020-09-18 16:16:33 -0400148 fUniquelyKeyedProxyViewMap.add(entry);
149 return entry;
150}
151
152void GrThreadSafeUniquelyKeyedProxyViewCache::recycleEntry(Entry* dead) {
153 SkASSERT(!dead->fPrev && !dead->fNext && !dead->fList);
154
155 dead->fKey.reset();
156 dead->fView.reset();
157
158 dead->fNext = fFreeEntryList;
159 fFreeEntryList = dead;
160}
161
Robert Phillips6e17ffe2020-10-06 14:52:11 -0400162std::tuple<GrSurfaceProxyView, sk_sp<SkData>> GrThreadSafeUniquelyKeyedProxyViewCache::internalAdd(
Robert Phillips26f3aeb2020-09-16 10:57:32 -0400163 const GrUniqueKey& key,
164 const GrSurfaceProxyView& view) {
Robert Phillips45593682020-09-18 16:16:33 -0400165 Entry* tmp = fUniquelyKeyedProxyViewMap.find(key);
Robert Phillips26f3aeb2020-09-16 10:57:32 -0400166 if (!tmp) {
Robert Phillipsf3e2b3c2020-09-18 14:07:43 -0400167 tmp = this->getEntry(key, view);
Robert Phillips45593682020-09-18 16:16:33 -0400168
169 SkASSERT(fUniquelyKeyedProxyViewMap.find(key));
Robert Phillips26f3aeb2020-09-16 10:57:32 -0400170 }
171
Robert Phillips6e17ffe2020-10-06 14:52:11 -0400172 return { tmp->fView, tmp->fKey.refCustomData() };
Robert Phillips26f3aeb2020-09-16 10:57:32 -0400173}
174
175GrSurfaceProxyView GrThreadSafeUniquelyKeyedProxyViewCache::add(const GrUniqueKey& key,
176 const GrSurfaceProxyView& view) {
177 SkAutoSpinlock lock{fSpinLock};
178
Robert Phillips6e17ffe2020-10-06 14:52:11 -0400179 GrSurfaceProxyView newView;
180 std::tie(newView, std::ignore) = this->internalAdd(key, view);
181 return newView;
182}
183
184std::tuple<GrSurfaceProxyView, sk_sp<SkData>> GrThreadSafeUniquelyKeyedProxyViewCache::addWithData(
185 const GrUniqueKey& key,
186 const GrSurfaceProxyView& view) {
187 SkAutoSpinlock lock{fSpinLock};
188
Robert Phillips26f3aeb2020-09-16 10:57:32 -0400189 return this->internalAdd(key, view);
190}
Robert Phillips3380be92020-09-25 12:47:10 -0400191
192GrSurfaceProxyView GrThreadSafeUniquelyKeyedProxyViewCache::findOrAdd(const GrUniqueKey& key,
193 const GrSurfaceProxyView& v) {
194 SkAutoSpinlock lock{fSpinLock};
195
Robert Phillips6e17ffe2020-10-06 14:52:11 -0400196 GrSurfaceProxyView view;
197 std::tie(view, std::ignore) = this->internalFind(key);
198 if (view) {
199 return view;
200 }
201
202 std::tie(view, std::ignore) = this->internalAdd(key, v);
203 return view;
204}
205
206std::tuple<GrSurfaceProxyView, sk_sp<SkData>> GrThreadSafeUniquelyKeyedProxyViewCache::findOrAddWithData(
207 const GrUniqueKey& key,
208 const GrSurfaceProxyView& v) {
209 SkAutoSpinlock lock{fSpinLock};
210
211 auto [view, data] = this->internalFind(key);
212 if (view) {
213 return { std::move(view), std::move(data) };
Robert Phillips3380be92020-09-25 12:47:10 -0400214 }
215
216 return this->internalAdd(key, v);
217}
218
219void GrThreadSafeUniquelyKeyedProxyViewCache::remove(const GrUniqueKey& key) {
220 SkAutoSpinlock lock{fSpinLock};
221
222 Entry* tmp = fUniquelyKeyedProxyViewMap.find(key);
223 if (tmp) {
224 fUniquelyKeyedProxyViewMap.remove(key);
225 fUniquelyKeyedProxyViewList.remove(tmp);
226 this->recycleEntry(tmp);
227 }
228}
Robert Phillipsb1807122020-10-06 16:44:18 -0400229
230std::tuple<GrSurfaceProxyView, sk_sp<GrThreadSafeUniquelyKeyedProxyViewCache::Trampoline>>
231GrThreadSafeUniquelyKeyedProxyViewCache::CreateLazyView(GrDirectContext* dContext,
Robert Phillipsb1807122020-10-06 16:44:18 -0400232 GrColorType origCT,
Robert Phillipsfde67e42020-10-07 15:33:43 -0400233 SkISize dimensions,
234 GrSurfaceOrigin origin,
235 SkBackingFit fit) {
Robert Phillipsb1807122020-10-06 16:44:18 -0400236 GrProxyProvider* proxyProvider = dContext->priv().proxyProvider();
237
238 constexpr int kSampleCnt = 1;
239 auto [newCT, format] = GrRenderTargetContext::GetFallbackColorTypeAndFormat(
240 dContext, origCT, kSampleCnt);
241
242 if (newCT == GrColorType::kUnknown) {
243 return {GrSurfaceProxyView(nullptr), nullptr};
244 }
245
246 sk_sp<Trampoline> trampoline(new Trampoline);
247
248 GrProxyProvider::TextureInfo texInfo{ GrMipMapped::kNo, GrTextureType::k2D };
249
250 sk_sp<GrRenderTargetProxy> proxy = proxyProvider->createLazyRenderTargetProxy(
251 [trampoline](
252 GrResourceProvider* resourceProvider,
253 const GrSurfaceProxy::LazySurfaceDesc&) -> GrSurfaceProxy::LazyCallbackResult {
254 if (!resourceProvider || !trampoline->fProxy ||
255 !trampoline->fProxy->isInstantiated()) {
256 return GrSurfaceProxy::LazyCallbackResult(nullptr, true);
257 }
258
259 SkASSERT(!trampoline->fProxy->peekTexture()->getUniqueKey().isValid());
260 return GrSurfaceProxy::LazyCallbackResult(
261 sk_ref_sp(trampoline->fProxy->peekTexture()));
262 },
263 format,
264 dimensions,
265 kSampleCnt,
266 GrInternalSurfaceFlags::kNone,
267 &texInfo,
268 GrMipmapStatus::kNotAllocated,
Robert Phillipsfde67e42020-10-07 15:33:43 -0400269 fit,
Robert Phillipsb1807122020-10-06 16:44:18 -0400270 SkBudgeted::kYes,
271 GrProtected::kNo,
272 /* wrapsVkSecondaryCB */ false,
273 GrSurfaceProxy::UseAllocator::kYes);
274
275 // TODO: It seems like this 'newCT' usage should be 'origCT' but this is
276 // what GrRenderTargetContext::MakeWithFallback does
277 GrSwizzle swizzle = dContext->priv().caps()->getReadSwizzle(format, newCT);
278
279 return {{std::move(proxy), origin, swizzle}, std::move(trampoline)};
280}