OLD | NEW |
1 | 1 |
2 /* | 2 /* |
3 * Copyright 2014 Google Inc. | 3 * Copyright 2014 Google Inc. |
4 * | 4 * |
5 * Use of this source code is governed by a BSD-style license that can be | 5 * Use of this source code is governed by a BSD-style license that can be |
6 * found in the LICENSE file. | 6 * found in the LICENSE file. |
7 */ | 7 */ |
8 | 8 |
9 #ifndef GrResourceCache2_DEFINED | 9 #ifndef GrResourceCache2_DEFINED |
10 #define GrResourceCache2_DEFINED | 10 #define GrResourceCache2_DEFINED |
11 | 11 |
12 #include "GrGpuResource.h" | 12 #include "GrGpuResource.h" |
13 #include "GrGpuResourceCacheAccess.h" | 13 #include "GrGpuResourceCacheAccess.h" |
14 #include "GrResourceKey.h" | 14 #include "GrResourceKey.h" |
15 #include "SkRefCnt.h" | 15 #include "SkRefCnt.h" |
16 #include "SkTInternalLList.h" | 16 #include "SkTInternalLList.h" |
17 #include "SkTMultiMap.h" | 17 #include "SkTMultiMap.h" |
18 | 18 |
19 /** | 19 /** |
20 * Manages the lifetime of all GrGpuResource instances. | 20 * Eventual replacement for GrResourceCache. Currently it simply holds a list |
21 * | 21 * of all GrGpuResource objects for a GrContext. It is used to invalidate all |
22 * Resources may have optionally have two types of keys: | 22 * the resources when necessary. |
23 * 1) A scratch key. This is for resources whose allocations are cached but
not their contents. | |
24 * Multiple resources can share the same scratch key. This is so a calle
r can have two | |
25 * resource instances with the same properties (e.g. multipass rendering
that ping pongs | |
26 * between two temporary surfaces. The scratch key is set at resource cr
eation time and | |
27 * should never change. Resources need not have a scratch key. | |
28 * 2) A content key. This key represents the contents of the resource rathe
r than just its | |
29 * allocation properties. They may not collide. The content key can be s
et after resource | |
30 * creation. Currently it may only be set once and cannot be cleared. Th
is restriction will | |
31 * be removed. | |
32 * If a resource has neither key type then it will be deleted as soon as the las
t reference to it | |
33 * is dropped. If a key has both keys the content key takes precedence. | |
34 */ | 23 */ |
35 class GrResourceCache2 { | 24 class GrResourceCache2 { |
36 public: | 25 public: |
37 GrResourceCache2(); | 26 GrResourceCache2() : fCount(0) {}; |
38 ~GrResourceCache2(); | 27 ~GrResourceCache2(); |
39 | 28 |
40 /** Used to access functionality needed by GrGpuResource for lifetime manage
ment. */ | 29 void insertResource(GrGpuResource*); |
41 class ResourceAccess; | |
42 ResourceAccess resourceAccess(); | |
43 | 30 |
44 /** | 31 void removeResource(GrGpuResource*); |
45 * Sets the cache limits in terms of number of resources and max gpu memory
byte size. | |
46 */ | |
47 void setLimits(int count, size_t bytes); | |
48 | 32 |
49 /** | 33 // This currently returns a bool and fails when an existing resource has a k
ey that collides |
50 * Returns the number of cached resources. | 34 // with the new content key. In the future it will null out the content key
for the existing |
51 */ | 35 // resource. The failure is a temporary measure taken because duties are spl
it between two |
52 int getResourceCount() const { return fCount; } | 36 // cache objects currently. |
| 37 bool didSetContentKey(GrGpuResource*); |
53 | 38 |
54 /** | |
55 * Returns the number of bytes consumed by cached resources. | |
56 */ | |
57 size_t getResourceBytes() const { return fBytes; } | |
58 | |
59 /** | |
60 * Returns the cached resources count budget. | |
61 */ | |
62 int getMaxResourceCount() const { return fMaxCount; } | |
63 | |
64 /** | |
65 * Returns the number of bytes consumed by cached resources. | |
66 */ | |
67 size_t getMaxResourceBytes() const { return fMaxBytes; } | |
68 | |
69 /** | |
70 * Abandons the backend API resources owned by all GrGpuResource objects and
removes them from | |
71 * the cache. | |
72 */ | |
73 void abandonAll(); | 39 void abandonAll(); |
74 | 40 |
75 /** | |
76 * Releases the backend API resources owned by all GrGpuResource objects and
removes them from | |
77 * the cache. | |
78 */ | |
79 void releaseAll(); | 41 void releaseAll(); |
80 | 42 |
81 enum { | 43 enum { |
82 /** Preferentially returns scratch resources with no pending IO. */ | 44 /** Preferentially returns scratch resources with no pending IO. */ |
83 kPreferNoPendingIO_ScratchFlag = 0x1, | 45 kPreferNoPendingIO_ScratchFlag = 0x1, |
84 /** Will not return any resources that match but have pending IO. */ | 46 /** Will not return any resources that match but have pending IO. */ |
85 kRequireNoPendingIO_ScratchFlag = 0x2, | 47 kRequireNoPendingIO_ScratchFlag = 0x2, |
86 }; | 48 }; |
87 | |
88 /** | |
89 * Find a resource that matches a scratch key. | |
90 */ | |
91 GrGpuResource* findAndRefScratchResource(const GrResourceKey& scratchKey, ui
nt32_t flags = 0); | 49 GrGpuResource* findAndRefScratchResource(const GrResourceKey& scratchKey, ui
nt32_t flags = 0); |
92 | 50 |
93 #ifdef SK_DEBUG | 51 #ifdef SK_DEBUG |
94 // This is not particularly fast and only used for validation, so debug only
. | 52 // This is not particularly fast and only used for validation, so debug only
. |
95 int countScratchEntriesForKey(const GrResourceKey& scratchKey) const { | 53 int countScratchEntriesForKey(const GrResourceKey& scratchKey) const { |
96 SkASSERT(scratchKey.isScratch()); | 54 SkASSERT(scratchKey.isScratch()); |
97 return fScratchMap.countForKey(scratchKey); | 55 return fScratchMap.countForKey(scratchKey); |
98 } | 56 } |
99 #endif | 57 #endif |
100 | 58 |
101 /** | |
102 * Find a resource that matches a content key. | |
103 */ | |
104 GrGpuResource* findAndRefContentResource(const GrResourceKey& contentKey) { | 59 GrGpuResource* findAndRefContentResource(const GrResourceKey& contentKey) { |
105 SkASSERT(!contentKey.isScratch()); | 60 SkASSERT(!contentKey.isScratch()); |
106 GrGpuResource* resource = fContentHash.find(contentKey); | 61 return SkSafeRef(fContentHash.find(contentKey)); |
107 if (resource) { | |
108 resource->ref(); | |
109 this->makeResourceMRU(resource); | |
110 } | |
111 return resource; | |
112 } | 62 } |
113 | 63 |
114 /** | |
115 * Query whether a content key exists in the cache. | |
116 */ | |
117 bool hasContentKey(const GrResourceKey& contentKey) const { | 64 bool hasContentKey(const GrResourceKey& contentKey) const { |
118 SkASSERT(!contentKey.isScratch()); | 65 SkASSERT(!contentKey.isScratch()); |
119 return SkToBool(fContentHash.find(contentKey)); | 66 return SkToBool(fContentHash.find(contentKey)); |
120 } | 67 } |
121 | 68 |
122 /** Purges all resources that don't have external owners. */ | |
123 void purgeAllUnlocked(); | |
124 | |
125 /** | |
126 * The callback function used by the cache when it is still over budget afte
r a purge. The | |
127 * passed in 'data' is the same 'data' handed to setOverbudgetCallback. | |
128 */ | |
129 typedef void (*PFOverBudgetCB)(void* data); | |
130 | |
131 /** | |
132 * Set the callback the cache should use when it is still over budget after
a purge. The 'data' | |
133 * provided here will be passed back to the callback. Note that the cache wi
ll attempt to purge | |
134 * any resources newly freed by the callback. | |
135 */ | |
136 void setOverBudgetCallback(PFOverBudgetCB overBudgetCB, void* data) { | |
137 fOverBudgetCB = overBudgetCB; | |
138 fOverBudgetData = data; | |
139 } | |
140 | |
141 #if GR_GPU_STATS | |
142 void printStats() const; | |
143 #endif | |
144 | |
145 private: | 69 private: |
146 /////////////////////////////////////////////////////////////////////////// | |
147 /// @name Methods accessible via ResourceAccess | |
148 //// | |
149 void insertResource(GrGpuResource*); | |
150 void removeResource(GrGpuResource*); | |
151 void notifyPurgable(const GrGpuResource*); | |
152 void didChangeGpuMemorySize(const GrGpuResource*, size_t oldSize); | |
153 bool didSetContentKey(GrGpuResource*); | |
154 void makeResourceMRU(GrGpuResource*); | |
155 /// @} | |
156 | |
157 void purgeAsNeeded() { | |
158 if (fPurging || (fCount <= fMaxCount && fBytes < fMaxBytes)) { | |
159 return; | |
160 } | |
161 this->internalPurgeAsNeeded(); | |
162 } | |
163 | |
164 void internalPurgeAsNeeded(); | |
165 | |
166 #ifdef SK_DEBUG | 70 #ifdef SK_DEBUG |
167 bool isInCache(const GrGpuResource* r) const { return fResources.isInList(r)
; } | 71 bool isInCache(const GrGpuResource* r) const { return fResources.isInList(r)
; } |
168 void validate() const; | |
169 #else | |
170 void validate() const {} | |
171 #endif | 72 #endif |
172 | 73 |
173 class AutoValidate; | |
174 | |
175 class AvailableForScratchUse; | 74 class AvailableForScratchUse; |
176 | 75 |
177 struct ScratchMapTraits { | 76 struct ScratchMapTraits { |
178 static const GrResourceKey& GetKey(const GrGpuResource& r) { | 77 static const GrResourceKey& GetKey(const GrGpuResource& r) { |
179 return r.cacheAccess().getScratchKey(); | 78 return r.cacheAccess().getScratchKey(); |
180 } | 79 } |
181 | 80 |
182 static uint32_t Hash(const GrResourceKey& key) { return key.getHash(); } | 81 static uint32_t Hash(const GrResourceKey& key) { return key.getHash(); } |
183 }; | 82 }; |
184 typedef SkTMultiMap<GrGpuResource, GrResourceKey, ScratchMapTraits> ScratchM
ap; | 83 typedef SkTMultiMap<GrGpuResource, GrResourceKey, ScratchMapTraits> ScratchM
ap; |
185 | 84 |
186 struct ContentHashTraits { | 85 struct ContentHashTraits { |
187 static const GrResourceKey& GetKey(const GrGpuResource& r) { | 86 static const GrResourceKey& GetKey(const GrGpuResource& r) { |
188 return *r.cacheAccess().getContentKey(); | 87 return *r.cacheAccess().getContentKey(); |
189 } | 88 } |
190 | 89 |
191 static uint32_t Hash(const GrResourceKey& key) { return key.getHash(); } | 90 static uint32_t Hash(const GrResourceKey& key) { return key.getHash(); } |
192 }; | 91 }; |
193 typedef SkTDynamicHash<GrGpuResource, GrResourceKey, ContentHashTraits> Cont
entHash; | 92 typedef SkTDynamicHash<GrGpuResource, GrResourceKey, ContentHashTraits> Cont
entHash; |
194 | 93 |
195 typedef SkTInternalLList<GrGpuResource> ResourceList; | 94 int fCount; |
196 | 95 SkTInternalLList<GrGpuResource> fResources; |
197 ResourceList fResources; | |
198 // This map holds all resources that can be used as scratch resources. | 96 // This map holds all resources that can be used as scratch resources. |
199 ScratchMap fScratchMap; | 97 ScratchMap fScratchMap; |
200 // This holds all resources that have content keys. | 98 // This holds all resources that have content keys. |
201 ContentHash fContentHash; | 99 ContentHash fContentHash; |
202 | |
203 // our budget, used in purgeAsNeeded() | |
204 int fMaxCount; | |
205 size_t fMaxBytes; | |
206 | |
207 #if GR_CACHE_STATS | |
208 int fHighWaterCount; | |
209 size_t fHighWaterBytes; | |
210 #endif | |
211 | |
212 // our current stats, related to our budget | |
213 int fCount; | |
214 size_t fBytes; | |
215 | |
216 // prevents recursive purging | |
217 bool fPurging; | |
218 bool fNewlyPurgableResourceWhilePurging; | |
219 | |
220 PFOverBudgetCB fOverBudgetCB; | |
221 void* fOverBudgetData; | |
222 | |
223 }; | 100 }; |
224 | 101 |
225 class GrResourceCache2::ResourceAccess { | |
226 private: | |
227 ResourceAccess(GrResourceCache2* cache) : fCache(cache) { } | |
228 ResourceAccess(const ResourceAccess& that) : fCache(that.fCache) { } | |
229 ResourceAccess& operator=(const ResourceAccess&); // unimpl | |
230 | |
231 /** | |
232 * Insert a resource into the cache. | |
233 */ | |
234 void insertResource(GrGpuResource* resource) { fCache->insertResource(resour
ce); } | |
235 | |
236 /** | |
237 * Removes a resource from the cache. | |
238 */ | |
239 void removeResource(GrGpuResource* resource) { fCache->removeResource(resour
ce); } | |
240 | |
241 /** | |
242 * Called by GrGpuResources when they detects that they are newly purgable. | |
243 */ | |
244 void notifyPurgable(const GrGpuResource* resource) { fCache->notifyPurgable(
resource); } | |
245 | |
246 /** | |
247 * Called by GrGpuResources when their sizes change. | |
248 */ | |
249 void didChangeGpuMemorySize(const GrGpuResource* resource, size_t oldSize) { | |
250 fCache->didChangeGpuMemorySize(resource, oldSize); | |
251 } | |
252 | |
253 /** | |
254 * Called by GrGpuResources when their content keys change. | |
255 * | |
256 * This currently returns a bool and fails when an existing resource has a k
ey that collides | |
257 * with the new content key. In the future it will null out the content key
for the existing | |
258 * resource. The failure is a temporary measure taken because duties are spl
it between two | |
259 * cache objects currently. | |
260 */ | |
261 bool didSetContentKey(GrGpuResource* resource) { return fCache->didSetConten
tKey(resource); } | |
262 | |
263 // No taking addresses of this type. | |
264 const ResourceAccess* operator&() const; | |
265 ResourceAccess* operator&(); | |
266 | |
267 GrResourceCache2* fCache; | |
268 | |
269 friend class GrGpuResource; // To access all the proxy inline methods. | |
270 friend class GrResourceCache2; // To create this type. | |
271 }; | |
272 | |
273 inline GrResourceCache2::ResourceAccess GrResourceCache2::resourceAccess() { | |
274 return ResourceAccess(this); | |
275 } | |
276 | |
277 #endif | 102 #endif |
OLD | NEW |