blob: d467d2b3f75beeb3bc920d6c7adec01feea4389d [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 Phillips187b04b2020-09-22 12:18:16 -040010#include "src/gpu/GrResourceCache.h"
11
Robert Phillips45593682020-09-18 16:16:33 -040012GrThreadSafeUniquelyKeyedProxyViewCache::GrThreadSafeUniquelyKeyedProxyViewCache()
13 : fFreeEntryList(nullptr) {
14}
Robert Phillips26f3aeb2020-09-16 10:57:32 -040015
16GrThreadSafeUniquelyKeyedProxyViewCache::~GrThreadSafeUniquelyKeyedProxyViewCache() {
Robert Phillips45593682020-09-18 16:16:33 -040017 this->dropAllRefs();
Robert Phillips26f3aeb2020-09-16 10:57:32 -040018}
19
20#if GR_TEST_UTILS
21int GrThreadSafeUniquelyKeyedProxyViewCache::numEntries() const {
22 SkAutoSpinlock lock{fSpinLock};
23
Robert Phillips45593682020-09-18 16:16:33 -040024 return fUniquelyKeyedProxyViewMap.count();
Robert Phillips26f3aeb2020-09-16 10:57:32 -040025}
26
Robert Phillipsc61c8952020-09-22 14:24:43 -040027size_t GrThreadSafeUniquelyKeyedProxyViewCache::approxBytesUsedForHash() const {
Robert Phillips26f3aeb2020-09-16 10:57:32 -040028 SkAutoSpinlock lock{fSpinLock};
29
Robert Phillipsc61c8952020-09-22 14:24:43 -040030 return fUniquelyKeyedProxyViewMap.approxBytesUsed();
Robert Phillips26f3aeb2020-09-16 10:57:32 -040031}
32#endif
33
34void GrThreadSafeUniquelyKeyedProxyViewCache::dropAllRefs() {
35 SkAutoSpinlock lock{fSpinLock};
36
Robert Phillips45593682020-09-18 16:16:33 -040037 fUniquelyKeyedProxyViewMap.reset();
38 while (auto tmp = fUniquelyKeyedProxyViewList.head()) {
39 fUniquelyKeyedProxyViewList.remove(tmp);
40 this->recycleEntry(tmp);
41 }
42 // TODO: should we empty out the fFreeEntryList and reset fEntryAllocator?
Robert Phillips26f3aeb2020-09-16 10:57:32 -040043}
44
Robert Phillips3380be92020-09-25 12:47:10 -040045// TODO: If iterating becomes too expensive switch to using something like GrIORef for the
46// GrSurfaceProxy
Robert Phillips331699c2020-09-22 15:20:01 -040047void GrThreadSafeUniquelyKeyedProxyViewCache::dropUniqueRefs(GrResourceCache* resourceCache) {
Robert Phillips12d06a32020-09-16 12:31:34 -040048 SkAutoSpinlock lock{fSpinLock};
49
Robert Phillips187b04b2020-09-22 12:18:16 -040050 // Iterate from LRU to MRU
51 Entry* cur = fUniquelyKeyedProxyViewList.tail();
52 Entry* prev = cur ? cur->fPrev : nullptr;
Robert Phillips45593682020-09-18 16:16:33 -040053
54 while (cur) {
Robert Phillips187b04b2020-09-22 12:18:16 -040055 if (resourceCache && !resourceCache->overBudget()) {
56 return;
57 }
58
Robert Phillips45593682020-09-18 16:16:33 -040059 if (cur->fView.proxy()->unique()) {
60 fUniquelyKeyedProxyViewMap.remove(cur->fKey);
61 fUniquelyKeyedProxyViewList.remove(cur);
62 this->recycleEntry(cur);
63 }
64
Robert Phillips187b04b2020-09-22 12:18:16 -040065 cur = prev;
66 prev = cur ? cur->fPrev : nullptr;
Robert Phillips45593682020-09-18 16:16:33 -040067 }
Robert Phillips12d06a32020-09-16 12:31:34 -040068}
69
Robert Phillipsc2fe1642020-09-22 17:34:51 -040070void GrThreadSafeUniquelyKeyedProxyViewCache::dropUniqueRefsOlderThan(
71 GrStdSteadyClock::time_point purgeTime) {
72 SkAutoSpinlock lock{fSpinLock};
73
74 // Iterate from LRU to MRU
75 Entry* cur = fUniquelyKeyedProxyViewList.tail();
76 Entry* prev = cur ? cur->fPrev : nullptr;
77
78 while (cur) {
79 if (cur->fLastAccess >= purgeTime) {
80 // This entry and all the remaining ones in the list will be newer than 'purgeTime'
81 return;
82 }
83
84 if (cur->fView.proxy()->unique()) {
85 fUniquelyKeyedProxyViewMap.remove(cur->fKey);
86 fUniquelyKeyedProxyViewList.remove(cur);
87 this->recycleEntry(cur);
88 }
89
90 cur = prev;
91 prev = cur ? cur->fPrev : nullptr;
92 }
93}
94
Robert Phillips6e17ffe2020-10-06 14:52:11 -040095std::tuple<GrSurfaceProxyView, sk_sp<SkData>> GrThreadSafeUniquelyKeyedProxyViewCache::internalFind(
96 const GrUniqueKey& key) {
Robert Phillips45593682020-09-18 16:16:33 -040097 Entry* tmp = fUniquelyKeyedProxyViewMap.find(key);
Robert Phillips26f3aeb2020-09-16 10:57:32 -040098 if (tmp) {
Robert Phillips45593682020-09-18 16:16:33 -040099 SkASSERT(fUniquelyKeyedProxyViewList.isInList(tmp));
100 // make the sought out entry the MRU
Robert Phillipsc2fe1642020-09-22 17:34:51 -0400101 tmp->fLastAccess = GrStdSteadyClock::now();
Robert Phillips45593682020-09-18 16:16:33 -0400102 fUniquelyKeyedProxyViewList.remove(tmp);
103 fUniquelyKeyedProxyViewList.addToHead(tmp);
Robert Phillips6e17ffe2020-10-06 14:52:11 -0400104 return { tmp->fView, tmp->fKey.refCustomData() };
Robert Phillips26f3aeb2020-09-16 10:57:32 -0400105 }
106
107 return {};
108}
109
Robert Phillips6e17ffe2020-10-06 14:52:11 -0400110GrSurfaceProxyView GrThreadSafeUniquelyKeyedProxyViewCache::find(const GrUniqueKey& key) {
111 SkAutoSpinlock lock{fSpinLock};
112
113 GrSurfaceProxyView view;
114 std::tie(view, std::ignore) = this->internalFind(key);
115 return view;
116}
117
118std::tuple<GrSurfaceProxyView, sk_sp<SkData>> GrThreadSafeUniquelyKeyedProxyViewCache::findWithData(
119 const GrUniqueKey& key) {
120 SkAutoSpinlock lock{fSpinLock};
121
122 return this->internalFind(key);
123}
124
Robert Phillips45593682020-09-18 16:16:33 -0400125GrThreadSafeUniquelyKeyedProxyViewCache::Entry*
126GrThreadSafeUniquelyKeyedProxyViewCache::getEntry(const GrUniqueKey& key,
127 const GrSurfaceProxyView& view) {
128 Entry* entry;
129
130 if (fFreeEntryList) {
131 entry = fFreeEntryList;
132 fFreeEntryList = entry->fNext;
133 entry->fNext = nullptr;
134
135 entry->fKey = key;
136 entry->fView = view;
137 } else {
138 entry = fEntryAllocator.make<Entry>(key, view);
139 }
140
Robert Phillipsc2fe1642020-09-22 17:34:51 -0400141 // make 'entry' the MRU
142 entry->fLastAccess = GrStdSteadyClock::now();
143 fUniquelyKeyedProxyViewList.addToHead(entry);
Robert Phillips45593682020-09-18 16:16:33 -0400144 fUniquelyKeyedProxyViewMap.add(entry);
145 return entry;
146}
147
148void GrThreadSafeUniquelyKeyedProxyViewCache::recycleEntry(Entry* dead) {
149 SkASSERT(!dead->fPrev && !dead->fNext && !dead->fList);
150
151 dead->fKey.reset();
152 dead->fView.reset();
153
154 dead->fNext = fFreeEntryList;
155 fFreeEntryList = dead;
156}
157
Robert Phillips6e17ffe2020-10-06 14:52:11 -0400158std::tuple<GrSurfaceProxyView, sk_sp<SkData>> GrThreadSafeUniquelyKeyedProxyViewCache::internalAdd(
Robert Phillips26f3aeb2020-09-16 10:57:32 -0400159 const GrUniqueKey& key,
160 const GrSurfaceProxyView& view) {
Robert Phillips45593682020-09-18 16:16:33 -0400161 Entry* tmp = fUniquelyKeyedProxyViewMap.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
165 SkASSERT(fUniquelyKeyedProxyViewMap.find(key));
Robert Phillips26f3aeb2020-09-16 10:57:32 -0400166 }
167
Robert Phillips6e17ffe2020-10-06 14:52:11 -0400168 return { tmp->fView, tmp->fKey.refCustomData() };
Robert Phillips26f3aeb2020-09-16 10:57:32 -0400169}
170
171GrSurfaceProxyView GrThreadSafeUniquelyKeyedProxyViewCache::add(const GrUniqueKey& key,
172 const GrSurfaceProxyView& view) {
173 SkAutoSpinlock lock{fSpinLock};
174
Robert Phillips6e17ffe2020-10-06 14:52:11 -0400175 GrSurfaceProxyView newView;
176 std::tie(newView, std::ignore) = this->internalAdd(key, view);
177 return newView;
178}
179
180std::tuple<GrSurfaceProxyView, sk_sp<SkData>> GrThreadSafeUniquelyKeyedProxyViewCache::addWithData(
181 const GrUniqueKey& key,
182 const GrSurfaceProxyView& view) {
183 SkAutoSpinlock lock{fSpinLock};
184
Robert Phillips26f3aeb2020-09-16 10:57:32 -0400185 return this->internalAdd(key, view);
186}
Robert Phillips3380be92020-09-25 12:47:10 -0400187
188GrSurfaceProxyView GrThreadSafeUniquelyKeyedProxyViewCache::findOrAdd(const GrUniqueKey& key,
189 const GrSurfaceProxyView& v) {
190 SkAutoSpinlock lock{fSpinLock};
191
Robert Phillips6e17ffe2020-10-06 14:52:11 -0400192 GrSurfaceProxyView view;
193 std::tie(view, std::ignore) = this->internalFind(key);
194 if (view) {
195 return view;
196 }
197
198 std::tie(view, std::ignore) = this->internalAdd(key, v);
199 return view;
200}
201
202std::tuple<GrSurfaceProxyView, sk_sp<SkData>> GrThreadSafeUniquelyKeyedProxyViewCache::findOrAddWithData(
203 const GrUniqueKey& key,
204 const GrSurfaceProxyView& v) {
205 SkAutoSpinlock lock{fSpinLock};
206
207 auto [view, data] = this->internalFind(key);
208 if (view) {
209 return { std::move(view), std::move(data) };
Robert Phillips3380be92020-09-25 12:47:10 -0400210 }
211
212 return this->internalAdd(key, v);
213}
214
215void GrThreadSafeUniquelyKeyedProxyViewCache::remove(const GrUniqueKey& key) {
216 SkAutoSpinlock lock{fSpinLock};
217
218 Entry* tmp = fUniquelyKeyedProxyViewMap.find(key);
219 if (tmp) {
220 fUniquelyKeyedProxyViewMap.remove(key);
221 fUniquelyKeyedProxyViewList.remove(tmp);
222 this->recycleEntry(tmp);
223 }
224}