blob: c81933909d374eac9480e054d870e4a73f7c0eb2 [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 Phillips26f3aeb2020-09-16 10:57:32 -040095GrSurfaceProxyView GrThreadSafeUniquelyKeyedProxyViewCache::find(const GrUniqueKey& key) {
96 SkAutoSpinlock lock{fSpinLock};
97
Robert Phillips45593682020-09-18 16:16:33 -040098 Entry* tmp = fUniquelyKeyedProxyViewMap.find(key);
Robert Phillips26f3aeb2020-09-16 10:57:32 -040099 if (tmp) {
Robert Phillips45593682020-09-18 16:16:33 -0400100 SkASSERT(fUniquelyKeyedProxyViewList.isInList(tmp));
101 // make the sought out entry the MRU
Robert Phillipsc2fe1642020-09-22 17:34:51 -0400102 tmp->fLastAccess = GrStdSteadyClock::now();
Robert Phillips45593682020-09-18 16:16:33 -0400103 fUniquelyKeyedProxyViewList.remove(tmp);
104 fUniquelyKeyedProxyViewList.addToHead(tmp);
Robert Phillips752f7e12020-09-18 12:28:59 -0400105 return tmp->fView;
Robert Phillips26f3aeb2020-09-16 10:57:32 -0400106 }
107
108 return {};
109}
110
Robert Phillips45593682020-09-18 16:16:33 -0400111GrThreadSafeUniquelyKeyedProxyViewCache::Entry*
112GrThreadSafeUniquelyKeyedProxyViewCache::getEntry(const GrUniqueKey& key,
113 const GrSurfaceProxyView& view) {
114 Entry* entry;
115
116 if (fFreeEntryList) {
117 entry = fFreeEntryList;
118 fFreeEntryList = entry->fNext;
119 entry->fNext = nullptr;
120
121 entry->fKey = key;
122 entry->fView = view;
123 } else {
124 entry = fEntryAllocator.make<Entry>(key, view);
125 }
126
Robert Phillipsc2fe1642020-09-22 17:34:51 -0400127 // make 'entry' the MRU
128 entry->fLastAccess = GrStdSteadyClock::now();
129 fUniquelyKeyedProxyViewList.addToHead(entry);
Robert Phillips45593682020-09-18 16:16:33 -0400130 fUniquelyKeyedProxyViewMap.add(entry);
131 return entry;
132}
133
134void GrThreadSafeUniquelyKeyedProxyViewCache::recycleEntry(Entry* dead) {
135 SkASSERT(!dead->fPrev && !dead->fNext && !dead->fList);
136
137 dead->fKey.reset();
138 dead->fView.reset();
139
140 dead->fNext = fFreeEntryList;
141 fFreeEntryList = dead;
142}
143
Robert Phillips26f3aeb2020-09-16 10:57:32 -0400144GrSurfaceProxyView GrThreadSafeUniquelyKeyedProxyViewCache::internalAdd(
145 const GrUniqueKey& key,
146 const GrSurfaceProxyView& view) {
Robert Phillips45593682020-09-18 16:16:33 -0400147 Entry* tmp = fUniquelyKeyedProxyViewMap.find(key);
Robert Phillips26f3aeb2020-09-16 10:57:32 -0400148 if (!tmp) {
Robert Phillipsf3e2b3c2020-09-18 14:07:43 -0400149 tmp = this->getEntry(key, view);
Robert Phillips45593682020-09-18 16:16:33 -0400150
151 SkASSERT(fUniquelyKeyedProxyViewMap.find(key));
Robert Phillips26f3aeb2020-09-16 10:57:32 -0400152 }
153
Robert Phillips752f7e12020-09-18 12:28:59 -0400154 return tmp->fView;
Robert Phillips26f3aeb2020-09-16 10:57:32 -0400155}
156
157GrSurfaceProxyView GrThreadSafeUniquelyKeyedProxyViewCache::add(const GrUniqueKey& key,
158 const GrSurfaceProxyView& view) {
159 SkAutoSpinlock lock{fSpinLock};
160
161 return this->internalAdd(key, view);
162}
Robert Phillips3380be92020-09-25 12:47:10 -0400163
164GrSurfaceProxyView GrThreadSafeUniquelyKeyedProxyViewCache::findOrAdd(const GrUniqueKey& key,
165 const GrSurfaceProxyView& v) {
166 SkAutoSpinlock lock{fSpinLock};
167
168 Entry* tmp = fUniquelyKeyedProxyViewMap.find(key);
169 if (tmp) {
170 SkASSERT(fUniquelyKeyedProxyViewList.isInList(tmp));
171 // make the sought out entry the MRU
172 tmp->fLastAccess = GrStdSteadyClock::now();
173 fUniquelyKeyedProxyViewList.remove(tmp);
174 fUniquelyKeyedProxyViewList.addToHead(tmp);
175 return tmp->fView;
176 }
177
178 return this->internalAdd(key, v);
179}
180
181void GrThreadSafeUniquelyKeyedProxyViewCache::remove(const GrUniqueKey& key) {
182 SkAutoSpinlock lock{fSpinLock};
183
184 Entry* tmp = fUniquelyKeyedProxyViewMap.find(key);
185 if (tmp) {
186 fUniquelyKeyedProxyViewMap.remove(key);
187 fUniquelyKeyedProxyViewList.remove(tmp);
188 this->recycleEntry(tmp);
189 }
190}