blob: a275075a8c13b449eaeb8717cceff399992a6739 [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 Phillips74ad27d2020-10-20 10:16:55 -040028 return fUniquelyKeyedEntryMap.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 Phillips74ad27d2020-10-20 10:16:55 -040034 return fUniquelyKeyedEntryMap.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 Phillips74ad27d2020-10-20 10:16:55 -040041 fUniquelyKeyedEntryMap.reset();
42 while (auto tmp = fUniquelyKeyedEntryList.head()) {
43 fUniquelyKeyedEntryList.remove(tmp);
Robert Phillips45593682020-09-18 16:16:33 -040044 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
Robert Phillips74ad27d2020-10-20 10:16:55 -040055 Entry* cur = fUniquelyKeyedEntryList.tail();
Robert Phillips187b04b2020-09-22 12:18:16 -040056 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 Phillips01771c12020-10-20 15:46:07 -040063 if (cur->uniquelyHeld()) {
64 fUniquelyKeyedEntryMap.remove(cur->key());
Robert Phillips74ad27d2020-10-20 10:16:55 -040065 fUniquelyKeyedEntryList.remove(cur);
Robert Phillips45593682020-09-18 16:16:33 -040066 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
Robert Phillips74ad27d2020-10-20 10:16:55 -040078 Entry* cur = fUniquelyKeyedEntryList.tail();
Robert Phillipsc2fe1642020-09-22 17:34:51 -040079 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
Robert Phillips01771c12020-10-20 15:46:07 -040087 if (cur->uniquelyHeld()) {
88 fUniquelyKeyedEntryMap.remove(cur->key());
Robert Phillips74ad27d2020-10-20 10:16:55 -040089 fUniquelyKeyedEntryList.remove(cur);
Robert Phillipsc2fe1642020-09-22 17:34:51 -040090 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 Phillips74ad27d2020-10-20 10:16:55 -0400100 Entry* tmp = fUniquelyKeyedEntryMap.find(key);
Robert Phillips26f3aeb2020-09-16 10:57:32 -0400101 if (tmp) {
Robert Phillips74ad27d2020-10-20 10:16:55 -0400102 SkASSERT(fUniquelyKeyedEntryList.isInList(tmp));
Robert Phillips45593682020-09-18 16:16:33 -0400103 // make the sought out entry the MRU
Robert Phillipsc2fe1642020-09-22 17:34:51 -0400104 tmp->fLastAccess = GrStdSteadyClock::now();
Robert Phillips74ad27d2020-10-20 10:16:55 -0400105 fUniquelyKeyedEntryList.remove(tmp);
106 fUniquelyKeyedEntryList.addToHead(tmp);
Robert Phillips01771c12020-10-20 15:46:07 -0400107 return { tmp->view(), tmp->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
Robert Phillips01771c12020-10-20 15:46:07 -0400137 entry->set(key, view);
Robert Phillips45593682020-09-18 16:16:33 -0400138 } else {
139 entry = fEntryAllocator.make<Entry>(key, view);
140 }
141
Robert Phillipsc2fe1642020-09-22 17:34:51 -0400142 // make 'entry' the MRU
143 entry->fLastAccess = GrStdSteadyClock::now();
Robert Phillips74ad27d2020-10-20 10:16:55 -0400144 fUniquelyKeyedEntryList.addToHead(entry);
145 fUniquelyKeyedEntryMap.add(entry);
Robert Phillips45593682020-09-18 16:16:33 -0400146 return entry;
147}
148
Robert Phillipsd464feb2020-10-08 11:00:02 -0400149void GrThreadSafeCache::recycleEntry(Entry* dead) {
Robert Phillips45593682020-09-18 16:16:33 -0400150 SkASSERT(!dead->fPrev && !dead->fNext && !dead->fList);
151
Robert Phillips01771c12020-10-20 15:46:07 -0400152 dead->makeEmpty();
Robert Phillips45593682020-09-18 16:16:33 -0400153
154 dead->fNext = fFreeEntryList;
155 fFreeEntryList = dead;
156}
157
Robert Phillipsd464feb2020-10-08 11:00:02 -0400158std::tuple<GrSurfaceProxyView, sk_sp<SkData>> GrThreadSafeCache::internalAdd(
Robert Phillips26f3aeb2020-09-16 10:57:32 -0400159 const GrUniqueKey& key,
160 const GrSurfaceProxyView& view) {
Robert Phillips74ad27d2020-10-20 10:16:55 -0400161 Entry* tmp = fUniquelyKeyedEntryMap.find(key);
Robert Phillips26f3aeb2020-09-16 10:57:32 -0400162 if (!tmp) {
Robert Phillipsf3e2b3c2020-09-18 14:07:43 -0400163 tmp = this->getEntry(key, view);
Robert Phillips45593682020-09-18 16:16:33 -0400164
Robert Phillips74ad27d2020-10-20 10:16:55 -0400165 SkASSERT(fUniquelyKeyedEntryMap.find(key));
Robert Phillips26f3aeb2020-09-16 10:57:32 -0400166 }
167
Robert Phillips01771c12020-10-20 15:46:07 -0400168 return { tmp->view(), tmp->refCustomData() };
Robert Phillips26f3aeb2020-09-16 10:57:32 -0400169}
170
Robert Phillipsd464feb2020-10-08 11:00:02 -0400171GrSurfaceProxyView GrThreadSafeCache::add(const GrUniqueKey& key, const GrSurfaceProxyView& view) {
Robert Phillips26f3aeb2020-09-16 10:57:32 -0400172 SkAutoSpinlock lock{fSpinLock};
173
Robert Phillips6e17ffe2020-10-06 14:52:11 -0400174 GrSurfaceProxyView newView;
175 std::tie(newView, std::ignore) = this->internalAdd(key, view);
176 return newView;
177}
178
Robert Phillipsd464feb2020-10-08 11:00:02 -0400179std::tuple<GrSurfaceProxyView, sk_sp<SkData>> GrThreadSafeCache::addWithData(
Robert Phillips6e17ffe2020-10-06 14:52:11 -0400180 const GrUniqueKey& key,
181 const GrSurfaceProxyView& view) {
182 SkAutoSpinlock lock{fSpinLock};
183
Robert Phillips26f3aeb2020-09-16 10:57:32 -0400184 return this->internalAdd(key, view);
185}
Robert Phillips3380be92020-09-25 12:47:10 -0400186
Robert Phillipsd464feb2020-10-08 11:00:02 -0400187GrSurfaceProxyView GrThreadSafeCache::findOrAdd(const GrUniqueKey& key,
188 const GrSurfaceProxyView& v) {
Robert Phillips3380be92020-09-25 12:47:10 -0400189 SkAutoSpinlock lock{fSpinLock};
190
Robert Phillips6e17ffe2020-10-06 14:52:11 -0400191 GrSurfaceProxyView view;
192 std::tie(view, std::ignore) = this->internalFind(key);
193 if (view) {
194 return view;
195 }
196
197 std::tie(view, std::ignore) = this->internalAdd(key, v);
198 return view;
199}
200
Robert Phillipsd464feb2020-10-08 11:00:02 -0400201std::tuple<GrSurfaceProxyView, sk_sp<SkData>> GrThreadSafeCache::findOrAddWithData(
Robert Phillips6e17ffe2020-10-06 14:52:11 -0400202 const GrUniqueKey& key,
203 const GrSurfaceProxyView& v) {
204 SkAutoSpinlock lock{fSpinLock};
205
206 auto [view, data] = this->internalFind(key);
207 if (view) {
208 return { std::move(view), std::move(data) };
Robert Phillips3380be92020-09-25 12:47:10 -0400209 }
210
211 return this->internalAdd(key, v);
212}
213
Robert Phillipsd464feb2020-10-08 11:00:02 -0400214void GrThreadSafeCache::remove(const GrUniqueKey& key) {
Robert Phillips3380be92020-09-25 12:47:10 -0400215 SkAutoSpinlock lock{fSpinLock};
216
Robert Phillips74ad27d2020-10-20 10:16:55 -0400217 Entry* tmp = fUniquelyKeyedEntryMap.find(key);
Robert Phillips3380be92020-09-25 12:47:10 -0400218 if (tmp) {
Robert Phillips74ad27d2020-10-20 10:16:55 -0400219 fUniquelyKeyedEntryMap.remove(key);
220 fUniquelyKeyedEntryList.remove(tmp);
Robert Phillips3380be92020-09-25 12:47:10 -0400221 this->recycleEntry(tmp);
222 }
223}
Robert Phillipsb1807122020-10-06 16:44:18 -0400224
Robert Phillipsd464feb2020-10-08 11:00:02 -0400225std::tuple<GrSurfaceProxyView, sk_sp<GrThreadSafeCache::Trampoline>>
226GrThreadSafeCache::CreateLazyView(GrDirectContext* dContext,
227 GrColorType origCT,
228 SkISize dimensions,
229 GrSurfaceOrigin origin,
230 SkBackingFit fit) {
Robert Phillipsb1807122020-10-06 16:44:18 -0400231 GrProxyProvider* proxyProvider = dContext->priv().proxyProvider();
232
233 constexpr int kSampleCnt = 1;
234 auto [newCT, format] = GrRenderTargetContext::GetFallbackColorTypeAndFormat(
235 dContext, origCT, kSampleCnt);
236
237 if (newCT == GrColorType::kUnknown) {
238 return {GrSurfaceProxyView(nullptr), nullptr};
239 }
240
241 sk_sp<Trampoline> trampoline(new Trampoline);
242
243 GrProxyProvider::TextureInfo texInfo{ GrMipMapped::kNo, GrTextureType::k2D };
244
245 sk_sp<GrRenderTargetProxy> proxy = proxyProvider->createLazyRenderTargetProxy(
246 [trampoline](
247 GrResourceProvider* resourceProvider,
248 const GrSurfaceProxy::LazySurfaceDesc&) -> GrSurfaceProxy::LazyCallbackResult {
249 if (!resourceProvider || !trampoline->fProxy ||
250 !trampoline->fProxy->isInstantiated()) {
251 return GrSurfaceProxy::LazyCallbackResult(nullptr, true);
252 }
253
254 SkASSERT(!trampoline->fProxy->peekTexture()->getUniqueKey().isValid());
255 return GrSurfaceProxy::LazyCallbackResult(
256 sk_ref_sp(trampoline->fProxy->peekTexture()));
257 },
258 format,
259 dimensions,
260 kSampleCnt,
261 GrInternalSurfaceFlags::kNone,
262 &texInfo,
263 GrMipmapStatus::kNotAllocated,
Robert Phillipsfde67e42020-10-07 15:33:43 -0400264 fit,
Robert Phillipsb1807122020-10-06 16:44:18 -0400265 SkBudgeted::kYes,
266 GrProtected::kNo,
267 /* wrapsVkSecondaryCB */ false,
268 GrSurfaceProxy::UseAllocator::kYes);
269
270 // TODO: It seems like this 'newCT' usage should be 'origCT' but this is
271 // what GrRenderTargetContext::MakeWithFallback does
272 GrSwizzle swizzle = dContext->priv().caps()->getReadSwizzle(format, newCT);
273
274 return {{std::move(proxy), origin, swizzle}, std::move(trampoline)};
275}