blob: 3c253d1cc0bcfdbcb0d382e1cab6fd0fba9a0c0c [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 Phillips331699c2020-09-22 15:20:01 -040045// TODO: add an atomic flag so we know when it is worthwhile to iterate
46void GrThreadSafeUniquelyKeyedProxyViewCache::dropUniqueRefs(GrResourceCache* resourceCache) {
Robert Phillips12d06a32020-09-16 12:31:34 -040047 SkAutoSpinlock lock{fSpinLock};
48
Robert Phillips187b04b2020-09-22 12:18:16 -040049 // Iterate from LRU to MRU
50 Entry* cur = fUniquelyKeyedProxyViewList.tail();
51 Entry* prev = cur ? cur->fPrev : nullptr;
Robert Phillips45593682020-09-18 16:16:33 -040052
53 while (cur) {
Robert Phillips187b04b2020-09-22 12:18:16 -040054 if (resourceCache && !resourceCache->overBudget()) {
55 return;
56 }
57
Robert Phillips45593682020-09-18 16:16:33 -040058 if (cur->fView.proxy()->unique()) {
59 fUniquelyKeyedProxyViewMap.remove(cur->fKey);
60 fUniquelyKeyedProxyViewList.remove(cur);
61 this->recycleEntry(cur);
62 }
63
Robert Phillips187b04b2020-09-22 12:18:16 -040064 cur = prev;
65 prev = cur ? cur->fPrev : nullptr;
Robert Phillips45593682020-09-18 16:16:33 -040066 }
Robert Phillips12d06a32020-09-16 12:31:34 -040067}
68
Robert Phillips26f3aeb2020-09-16 10:57:32 -040069GrSurfaceProxyView GrThreadSafeUniquelyKeyedProxyViewCache::find(const GrUniqueKey& key) {
70 SkAutoSpinlock lock{fSpinLock};
71
Robert Phillips45593682020-09-18 16:16:33 -040072 Entry* tmp = fUniquelyKeyedProxyViewMap.find(key);
Robert Phillips26f3aeb2020-09-16 10:57:32 -040073 if (tmp) {
Robert Phillips45593682020-09-18 16:16:33 -040074 SkASSERT(fUniquelyKeyedProxyViewList.isInList(tmp));
75 // make the sought out entry the MRU
76 fUniquelyKeyedProxyViewList.remove(tmp);
77 fUniquelyKeyedProxyViewList.addToHead(tmp);
Robert Phillips752f7e12020-09-18 12:28:59 -040078 return tmp->fView;
Robert Phillips26f3aeb2020-09-16 10:57:32 -040079 }
80
81 return {};
82}
83
Robert Phillips45593682020-09-18 16:16:33 -040084GrThreadSafeUniquelyKeyedProxyViewCache::Entry*
85GrThreadSafeUniquelyKeyedProxyViewCache::getEntry(const GrUniqueKey& key,
86 const GrSurfaceProxyView& view) {
87 Entry* entry;
88
89 if (fFreeEntryList) {
90 entry = fFreeEntryList;
91 fFreeEntryList = entry->fNext;
92 entry->fNext = nullptr;
93
94 entry->fKey = key;
95 entry->fView = view;
96 } else {
97 entry = fEntryAllocator.make<Entry>(key, view);
98 }
99
100 fUniquelyKeyedProxyViewList.addToHead(entry); // make 'entry' the MRU
101 fUniquelyKeyedProxyViewMap.add(entry);
102 return entry;
103}
104
105void GrThreadSafeUniquelyKeyedProxyViewCache::recycleEntry(Entry* dead) {
106 SkASSERT(!dead->fPrev && !dead->fNext && !dead->fList);
107
108 dead->fKey.reset();
109 dead->fView.reset();
110
111 dead->fNext = fFreeEntryList;
112 fFreeEntryList = dead;
113}
114
Robert Phillips26f3aeb2020-09-16 10:57:32 -0400115GrSurfaceProxyView GrThreadSafeUniquelyKeyedProxyViewCache::internalAdd(
116 const GrUniqueKey& key,
117 const GrSurfaceProxyView& view) {
Robert Phillips45593682020-09-18 16:16:33 -0400118 Entry* tmp = fUniquelyKeyedProxyViewMap.find(key);
Robert Phillips26f3aeb2020-09-16 10:57:32 -0400119 if (!tmp) {
Robert Phillipsf3e2b3c2020-09-18 14:07:43 -0400120 tmp = this->getEntry(key, view);
Robert Phillips45593682020-09-18 16:16:33 -0400121
122 SkASSERT(fUniquelyKeyedProxyViewMap.find(key));
Robert Phillips26f3aeb2020-09-16 10:57:32 -0400123 }
124
Robert Phillips752f7e12020-09-18 12:28:59 -0400125 return tmp->fView;
Robert Phillips26f3aeb2020-09-16 10:57:32 -0400126}
127
128GrSurfaceProxyView GrThreadSafeUniquelyKeyedProxyViewCache::add(const GrUniqueKey& key,
129 const GrSurfaceProxyView& view) {
130 SkAutoSpinlock lock{fSpinLock};
131
132 return this->internalAdd(key, view);
133}