Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1198)

Side by Side Diff: src/gpu/GrResourceCache.cpp

Issue 921323002: Make GrResourceCache use a priority queue of purgeable resources. (Closed) Base URL: https://skia.googlesource.com/skia.git@master
Patch Set: Address comments Created 5 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « src/gpu/GrResourceCache.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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 9
10 #include "GrResourceCache.h" 10 #include "GrResourceCache.h"
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after
51 private: 51 private:
52 GrResourceCache* fCache; 52 GrResourceCache* fCache;
53 }; 53 };
54 54
55 ////////////////////////////////////////////////////////////////////////////// 55 //////////////////////////////////////////////////////////////////////////////
56 56
57 static const int kDefaultMaxCount = 2 * (1 << 10); 57 static const int kDefaultMaxCount = 2 * (1 << 10);
58 static const size_t kDefaultMaxSize = 96 * (1 << 20); 58 static const size_t kDefaultMaxSize = 96 * (1 << 20);
59 59
60 GrResourceCache::GrResourceCache() 60 GrResourceCache::GrResourceCache()
61 : fMaxCount(kDefaultMaxCount) 61 : fTimestamp(0)
62 , fMaxCount(kDefaultMaxCount)
62 , fMaxBytes(kDefaultMaxSize) 63 , fMaxBytes(kDefaultMaxSize)
63 #if GR_CACHE_STATS 64 #if GR_CACHE_STATS
64 , fHighWaterCount(0) 65 , fHighWaterCount(0)
65 , fHighWaterBytes(0) 66 , fHighWaterBytes(0)
66 , fBudgetedHighWaterCount(0) 67 , fBudgetedHighWaterCount(0)
67 , fBudgetedHighWaterBytes(0) 68 , fBudgetedHighWaterBytes(0)
68 #endif 69 #endif
69 , fCount(0) 70 , fCount(0)
70 , fBytes(0) 71 , fBytes(0)
71 , fBudgetedCount(0) 72 , fBudgetedCount(0)
72 , fBudgetedBytes(0) 73 , fBudgetedBytes(0)
73 , fPurging(false)
74 , fNewlyPurgeableResourceWhilePurging(false)
75 , fOverBudgetCB(NULL) 74 , fOverBudgetCB(NULL)
76 , fOverBudgetData(NULL) { 75 , fOverBudgetData(NULL) {
77 } 76 }
78 77
79 GrResourceCache::~GrResourceCache() { 78 GrResourceCache::~GrResourceCache() {
80 this->releaseAll(); 79 this->releaseAll();
81 } 80 }
82 81
83 void GrResourceCache::setLimits(int count, size_t bytes) { 82 void GrResourceCache::setLimits(int count, size_t bytes) {
84 fMaxCount = count; 83 fMaxCount = count;
85 fMaxBytes = bytes; 84 fMaxBytes = bytes;
86 this->purgeAsNeeded(); 85 this->purgeAsNeeded();
87 } 86 }
88 87
89 void GrResourceCache::insertResource(GrGpuResource* resource) { 88 void GrResourceCache::insertResource(GrGpuResource* resource) {
90 SkASSERT(resource); 89 SkASSERT(resource);
91 SkASSERT(!resource->wasDestroyed()); 90 SkASSERT(!resource->wasDestroyed());
92 SkASSERT(!this->isInCache(resource)); 91 SkASSERT(!this->isInCache(resource));
93 SkASSERT(!fPurging);
94 fResources.addToHead(resource); 92 fResources.addToHead(resource);
95 93
96 size_t size = resource->gpuMemorySize(); 94 size_t size = resource->gpuMemorySize();
97 ++fCount; 95 ++fCount;
98 fBytes += size; 96 fBytes += size;
99 #if GR_CACHE_STATS 97 #if GR_CACHE_STATS
100 fHighWaterCount = SkTMax(fCount, fHighWaterCount); 98 fHighWaterCount = SkTMax(fCount, fHighWaterCount);
101 fHighWaterBytes = SkTMax(fBytes, fHighWaterBytes); 99 fHighWaterBytes = SkTMax(fBytes, fHighWaterBytes);
102 #endif 100 #endif
103 if (resource->resourcePriv().isBudgeted()) { 101 if (resource->resourcePriv().isBudgeted()) {
104 ++fBudgetedCount; 102 ++fBudgetedCount;
105 fBudgetedBytes += size; 103 fBudgetedBytes += size;
106 #if GR_CACHE_STATS 104 #if GR_CACHE_STATS
107 fBudgetedHighWaterCount = SkTMax(fBudgetedCount, fBudgetedHighWaterCount ); 105 fBudgetedHighWaterCount = SkTMax(fBudgetedCount, fBudgetedHighWaterCount );
108 fBudgetedHighWaterBytes = SkTMax(fBudgetedBytes, fBudgetedHighWaterBytes ); 106 fBudgetedHighWaterBytes = SkTMax(fBudgetedBytes, fBudgetedHighWaterBytes );
109 #endif 107 #endif
110 } 108 }
111 if (resource->resourcePriv().getScratchKey().isValid()) { 109 if (resource->resourcePriv().getScratchKey().isValid()) {
112 SkASSERT(!resource->cacheAccess().isWrapped()); 110 SkASSERT(!resource->cacheAccess().isWrapped());
113 fScratchMap.insert(resource->resourcePriv().getScratchKey(), resource); 111 fScratchMap.insert(resource->resourcePriv().getScratchKey(), resource);
114 } 112 }
115 113
114 resource->cacheAccess().setTimestamp(fTimestamp++);
115
116 this->purgeAsNeeded(); 116 this->purgeAsNeeded();
117 } 117 }
118 118
119 void GrResourceCache::removeResource(GrGpuResource* resource) { 119 void GrResourceCache::removeResource(GrGpuResource* resource) {
120 this->validate();
120 SkASSERT(this->isInCache(resource)); 121 SkASSERT(this->isInCache(resource));
121 122
123 if (resource->isPurgeable()) {
124 fPurgeableQueue.remove(resource);
125 }
126
122 size_t size = resource->gpuMemorySize(); 127 size_t size = resource->gpuMemorySize();
123 --fCount; 128 --fCount;
124 fBytes -= size; 129 fBytes -= size;
125 if (resource->resourcePriv().isBudgeted()) { 130 if (resource->resourcePriv().isBudgeted()) {
126 --fBudgetedCount; 131 --fBudgetedCount;
127 fBudgetedBytes -= size; 132 fBudgetedBytes -= size;
128 } 133 }
129 134
130 fResources.remove(resource); 135 fResources.remove(resource);
131 if (resource->resourcePriv().getScratchKey().isValid()) { 136 if (resource->resourcePriv().getScratchKey().isValid()) {
132 fScratchMap.remove(resource->resourcePriv().getScratchKey(), resource); 137 fScratchMap.remove(resource->resourcePriv().getScratchKey(), resource);
133 } 138 }
134 if (resource->getContentKey().isValid()) { 139 if (resource->getContentKey().isValid()) {
135 fContentHash.remove(resource->getContentKey()); 140 fContentHash.remove(resource->getContentKey());
136 } 141 }
137 this->validate(); 142 this->validate();
138 } 143 }
139 144
140 void GrResourceCache::abandonAll() { 145 void GrResourceCache::abandonAll() {
141 AutoValidate av(this); 146 AutoValidate av(this);
142 147
143 SkASSERT(!fPurging);
144 while (GrGpuResource* head = fResources.head()) { 148 while (GrGpuResource* head = fResources.head()) {
145 SkASSERT(!head->wasDestroyed()); 149 SkASSERT(!head->wasDestroyed());
146 head->cacheAccess().abandon(); 150 head->cacheAccess().abandon();
147 // abandon should have already removed this from the list. 151 // abandon should have already removed this from the list.
148 SkASSERT(head != fResources.head()); 152 SkASSERT(head != fResources.head());
149 } 153 }
150 SkASSERT(!fScratchMap.count()); 154 SkASSERT(!fScratchMap.count());
151 SkASSERT(!fContentHash.count()); 155 SkASSERT(!fContentHash.count());
152 SkASSERT(!fCount); 156 SkASSERT(!fCount);
153 SkASSERT(!fBytes); 157 SkASSERT(!fBytes);
154 SkASSERT(!fBudgetedCount); 158 SkASSERT(!fBudgetedCount);
155 SkASSERT(!fBudgetedBytes); 159 SkASSERT(!fBudgetedBytes);
156 } 160 }
157 161
158 void GrResourceCache::releaseAll() { 162 void GrResourceCache::releaseAll() {
159 AutoValidate av(this); 163 AutoValidate av(this);
160 164
161 SkASSERT(!fPurging);
162 while (GrGpuResource* head = fResources.head()) { 165 while (GrGpuResource* head = fResources.head()) {
163 SkASSERT(!head->wasDestroyed()); 166 SkASSERT(!head->wasDestroyed());
164 head->cacheAccess().release(); 167 head->cacheAccess().release();
165 // release should have already removed this from the list. 168 // release should have already removed this from the list.
166 SkASSERT(head != fResources.head()); 169 SkASSERT(head != fResources.head());
167 } 170 }
168 SkASSERT(!fScratchMap.count()); 171 SkASSERT(!fScratchMap.count());
169 SkASSERT(!fCount); 172 SkASSERT(!fCount);
170 SkASSERT(!fBytes); 173 SkASSERT(!fBytes);
171 SkASSERT(!fBudgetedCount); 174 SkASSERT(!fBudgetedCount);
172 SkASSERT(!fBudgetedBytes); 175 SkASSERT(!fBudgetedBytes);
173 } 176 }
174 177
175 class GrResourceCache::AvailableForScratchUse { 178 class GrResourceCache::AvailableForScratchUse {
176 public: 179 public:
177 AvailableForScratchUse(bool rejectPendingIO) : fRejectPendingIO(rejectPendin gIO) { } 180 AvailableForScratchUse(bool rejectPendingIO) : fRejectPendingIO(rejectPendin gIO) { }
178 181
179 bool operator()(const GrGpuResource* resource) const { 182 bool operator()(const GrGpuResource* resource) const {
180 if (resource->internalHasRef() || !resource->cacheAccess().isScratch()) { 183 if (resource->internalHasRef() || !resource->cacheAccess().isScratch()) {
181 return false; 184 return false;
182 } 185 }
183 return !fRejectPendingIO || !resource->internalHasPendingIO(); 186 return !fRejectPendingIO || !resource->internalHasPendingIO();
184 } 187 }
185 188
186 private: 189 private:
187 bool fRejectPendingIO; 190 bool fRejectPendingIO;
188 }; 191 };
189 192
190 GrGpuResource* GrResourceCache::findAndRefScratchResource(const GrScratchKey& sc ratchKey, 193 GrGpuResource* GrResourceCache::findAndRefScratchResource(const GrScratchKey& sc ratchKey,
191 uint32_t flags) { 194 uint32_t flags) {
192 SkASSERT(!fPurging);
193 SkASSERT(scratchKey.isValid()); 195 SkASSERT(scratchKey.isValid());
194 196
195 GrGpuResource* resource; 197 GrGpuResource* resource;
196 if (flags & (kPreferNoPendingIO_ScratchFlag | kRequireNoPendingIO_ScratchFla g)) { 198 if (flags & (kPreferNoPendingIO_ScratchFlag | kRequireNoPendingIO_ScratchFla g)) {
197 resource = fScratchMap.find(scratchKey, AvailableForScratchUse(true)); 199 resource = fScratchMap.find(scratchKey, AvailableForScratchUse(true));
198 if (resource) { 200 if (resource) {
199 resource->ref(); 201 this->refAndMakeResourceMRU(resource);
200 this->makeResourceMRU(resource);
201 this->validate(); 202 this->validate();
202 return resource; 203 return resource;
203 } else if (flags & kRequireNoPendingIO_ScratchFlag) { 204 } else if (flags & kRequireNoPendingIO_ScratchFlag) {
204 return NULL; 205 return NULL;
205 } 206 }
206 // TODO: fail here when kPrefer is specified, we didn't find a resource without pending io, 207 // TODO: fail here when kPrefer is specified, we didn't find a resource without pending io,
207 // but there is still space in our budget for the resource. 208 // but there is still space in our budget for the resource.
208 } 209 }
209 resource = fScratchMap.find(scratchKey, AvailableForScratchUse(false)); 210 resource = fScratchMap.find(scratchKey, AvailableForScratchUse(false));
210 if (resource) { 211 if (resource) {
211 resource->ref(); 212 this->refAndMakeResourceMRU(resource);
212 this->makeResourceMRU(resource);
213 this->validate(); 213 this->validate();
214 } 214 }
215 return resource; 215 return resource;
216 } 216 }
217 217
218 void GrResourceCache::willRemoveScratchKey(const GrGpuResource* resource) { 218 void GrResourceCache::willRemoveScratchKey(const GrGpuResource* resource) {
219 SkASSERT(resource->resourcePriv().getScratchKey().isValid()); 219 SkASSERT(resource->resourcePriv().getScratchKey().isValid());
220 fScratchMap.remove(resource->resourcePriv().getScratchKey(), resource); 220 fScratchMap.remove(resource->resourcePriv().getScratchKey(), resource);
221 } 221 }
222 222
223 void GrResourceCache::willRemoveContentKey(const GrGpuResource* resource) { 223 void GrResourceCache::willRemoveContentKey(const GrGpuResource* resource) {
224 // Someone has a ref to this resource in order to invalidate it. When the re f count reaches 224 // Someone has a ref to this resource in order to invalidate it. When the re f count reaches
225 // zero we will get a notifyPurgable() and figure out what to do with it. 225 // zero we will get a notifyPurgable() and figure out what to do with it.
226 SkASSERT(resource->getContentKey().isValid()); 226 SkASSERT(resource->getContentKey().isValid());
227 fContentHash.remove(resource->getContentKey()); 227 fContentHash.remove(resource->getContentKey());
228 } 228 }
229 229
230 bool GrResourceCache::didSetContentKey(GrGpuResource* resource) { 230 bool GrResourceCache::didSetContentKey(GrGpuResource* resource) {
231 SkASSERT(!fPurging);
232 SkASSERT(resource); 231 SkASSERT(resource);
233 SkASSERT(this->isInCache(resource)); 232 SkASSERT(this->isInCache(resource));
234 SkASSERT(resource->getContentKey().isValid()); 233 SkASSERT(resource->getContentKey().isValid());
235 234
236 GrGpuResource* res = fContentHash.find(resource->getContentKey()); 235 GrGpuResource* res = fContentHash.find(resource->getContentKey());
237 if (NULL != res) { 236 if (NULL != res) {
238 return false; 237 return false;
239 } 238 }
240 239
241 fContentHash.add(resource); 240 fContentHash.add(resource);
242 this->validate(); 241 this->validate();
243 return true; 242 return true;
244 } 243 }
245 244
246 void GrResourceCache::makeResourceMRU(GrGpuResource* resource) { 245 void GrResourceCache::refAndMakeResourceMRU(GrGpuResource* resource) {
247 SkASSERT(!fPurging);
248 SkASSERT(resource); 246 SkASSERT(resource);
249 SkASSERT(this->isInCache(resource)); 247 SkASSERT(this->isInCache(resource));
250 fResources.remove(resource); 248 if (resource->isPurgeable()) {
251 fResources.addToHead(resource); 249 // It's about to become unpurgeable.
250 fPurgeableQueue.remove(resource);
251 }
252 resource->ref();
253 resource->cacheAccess().setTimestamp(fTimestamp++);
254 SkASSERT(!resource->isPurgeable());
252 } 255 }
253 256
254 void GrResourceCache::notifyPurgeable(GrGpuResource* resource) { 257 void GrResourceCache::notifyPurgeable(GrGpuResource* resource) {
255 SkASSERT(resource); 258 SkASSERT(resource);
256 SkASSERT(this->isInCache(resource)); 259 SkASSERT(this->isInCache(resource));
257 SkASSERT(resource->isPurgeable()); 260 SkASSERT(resource->isPurgeable());
258 261
259 // We can't purge if in the middle of purging because purge is iterating. In stead record 262 SkASSERT(-1 == *resource->cacheAccess().accessCacheIndex());
260 // that additional resources became purgeable. 263 fPurgeableQueue.insert(resource);
261 if (fPurging) {
262 fNewlyPurgeableResourceWhilePurging = true;
263 return;
264 }
265 264
266 bool release = false; 265 if (!resource->resourcePriv().isBudgeted()) {
267
268 if (resource->cacheAccess().isWrapped()) {
269 release = true;
270 } else if (!resource->resourcePriv().isBudgeted()) {
271 // Check whether this resource could still be used as a scratch resource . 266 // Check whether this resource could still be used as a scratch resource .
272 if (resource->resourcePriv().getScratchKey().isValid()) { 267 if (!resource->cacheAccess().isWrapped() &&
268 resource->resourcePriv().getScratchKey().isValid()) {
273 // We won't purge an existing resource to make room for this one. 269 // We won't purge an existing resource to make room for this one.
274 bool underBudget = fBudgetedCount < fMaxCount && 270 bool underBudget = fBudgetedCount < fMaxCount &&
275 fBudgetedBytes + resource->gpuMemorySize() <= fMa xBytes; 271 fBudgetedBytes + resource->gpuMemorySize() <= fMa xBytes;
276 if (underBudget) { 272 if (underBudget) {
277 resource->resourcePriv().makeBudgeted(); 273 resource->resourcePriv().makeBudgeted();
278 } else { 274 return;
279 release = true;
280 } 275 }
281 } else {
282 release = true;
283 } 276 }
284 } else { 277 } else {
285 // Purge the resource if we're over budget 278 // Purge the resource immediately if we're over budget
286 bool overBudget = fBudgetedCount > fMaxCount || fBudgetedBytes > fMaxByt es; 279 bool overBudget = fBudgetedCount > fMaxCount || fBudgetedBytes > fMaxByt es;
287 280
288 // Also purge if the resource has neither a valid scratch key nor a cont ent key. 281 // Also purge if the resource has neither a valid scratch key nor a cont ent key.
289 bool noKey = !resource->resourcePriv().getScratchKey().isValid() && 282 bool noKey = !resource->resourcePriv().getScratchKey().isValid() &&
290 !resource->getContentKey().isValid(); 283 !resource->getContentKey().isValid();
291 if (overBudget || noKey) { 284 if (!overBudget && !noKey) {
292 release = true; 285 return;
293 } 286 }
294 } 287 }
295 288
296 if (release) { 289 SkDEBUGCODE(int beforeCount = fCount;)
297 SkDEBUGCODE(int beforeCount = fCount;) 290 resource->cacheAccess().release();
298 resource->cacheAccess().release(); 291 // We should at least free this resource, perhaps dependent resources as wel l.
299 // We should at least free this resource, perhaps dependent resources as well. 292 SkASSERT(fCount < beforeCount);
300 SkASSERT(fCount < beforeCount);
301 }
302 this->validate(); 293 this->validate();
303 } 294 }
304 295
305 void GrResourceCache::didChangeGpuMemorySize(const GrGpuResource* resource, size _t oldSize) { 296 void GrResourceCache::didChangeGpuMemorySize(const GrGpuResource* resource, size _t oldSize) {
306 // SkASSERT(!fPurging); GrPathRange increases size during flush. :( 297 // SkASSERT(!fPurging); GrPathRange increases size during flush. :(
307 SkASSERT(resource); 298 SkASSERT(resource);
308 SkASSERT(this->isInCache(resource)); 299 SkASSERT(this->isInCache(resource));
309 300
310 ptrdiff_t delta = resource->gpuMemorySize() - oldSize; 301 ptrdiff_t delta = resource->gpuMemorySize() - oldSize;
311 302
312 fBytes += delta; 303 fBytes += delta;
313 #if GR_CACHE_STATS 304 #if GR_CACHE_STATS
314 fHighWaterBytes = SkTMax(fBytes, fHighWaterBytes); 305 fHighWaterBytes = SkTMax(fBytes, fHighWaterBytes);
315 #endif 306 #endif
316 if (resource->resourcePriv().isBudgeted()) { 307 if (resource->resourcePriv().isBudgeted()) {
317 fBudgetedBytes += delta; 308 fBudgetedBytes += delta;
318 #if GR_CACHE_STATS 309 #if GR_CACHE_STATS
319 fBudgetedHighWaterBytes = SkTMax(fBudgetedBytes, fBudgetedHighWaterBytes ); 310 fBudgetedHighWaterBytes = SkTMax(fBudgetedBytes, fBudgetedHighWaterBytes );
320 #endif 311 #endif
321 } 312 }
322 313
323 this->purgeAsNeeded(); 314 this->purgeAsNeeded();
324 this->validate(); 315 this->validate();
325 } 316 }
326 317
327 void GrResourceCache::didChangeBudgetStatus(GrGpuResource* resource) { 318 void GrResourceCache::didChangeBudgetStatus(GrGpuResource* resource) {
328 SkASSERT(!fPurging);
329 SkASSERT(resource); 319 SkASSERT(resource);
330 SkASSERT(this->isInCache(resource)); 320 SkASSERT(this->isInCache(resource));
331 321
332 size_t size = resource->gpuMemorySize(); 322 size_t size = resource->gpuMemorySize();
333 323
334 if (resource->resourcePriv().isBudgeted()) { 324 if (resource->resourcePriv().isBudgeted()) {
335 ++fBudgetedCount; 325 ++fBudgetedCount;
336 fBudgetedBytes += size; 326 fBudgetedBytes += size;
337 #if GR_CACHE_STATS 327 #if GR_CACHE_STATS
338 fBudgetedHighWaterBytes = SkTMax(fBudgetedBytes, fBudgetedHighWaterBytes ); 328 fBudgetedHighWaterBytes = SkTMax(fBudgetedBytes, fBudgetedHighWaterBytes );
339 fBudgetedHighWaterCount = SkTMax(fBudgetedCount, fBudgetedHighWaterCount ); 329 fBudgetedHighWaterCount = SkTMax(fBudgetedCount, fBudgetedHighWaterCount );
340 #endif 330 #endif
341 this->purgeAsNeeded(); 331 this->purgeAsNeeded();
342 } else { 332 } else {
343 --fBudgetedCount; 333 --fBudgetedCount;
344 fBudgetedBytes -= size; 334 fBudgetedBytes -= size;
345 } 335 }
346 336
347 this->validate(); 337 this->validate();
348 } 338 }
349 339
350 void GrResourceCache::internalPurgeAsNeeded() { 340 void GrResourceCache::internalPurgeAsNeeded() {
351 SkASSERT(!fPurging);
352 SkASSERT(!fNewlyPurgeableResourceWhilePurging);
353 SkASSERT(fBudgetedCount > fMaxCount || fBudgetedBytes > fMaxBytes); 341 SkASSERT(fBudgetedCount > fMaxCount || fBudgetedBytes > fMaxBytes);
354 342
355 fPurging = true; 343 bool stillOverbudget = true;
344 while (fPurgeableQueue.count()) {
345 GrGpuResource* resource = fPurgeableQueue.peek();
346 SkASSERT(resource->isPurgeable());
347 resource->cacheAccess().release();
348 if (fBudgetedCount <= fMaxCount && fBudgetedBytes <= fMaxBytes) {
349 stillOverbudget = false;
350 break;
351 }
352 }
356 353
357 bool overBudget = true; 354 this->validate();
358 do {
359 fNewlyPurgeableResourceWhilePurging = false;
360 ResourceList::Iter resourceIter;
361 GrGpuResource* resource = resourceIter.init(fResources,
362 ResourceList::Iter::kTail_It erStart);
363 355
364 while (resource) { 356 if (stillOverbudget) {
365 GrGpuResource* prev = resourceIter.prev(); 357 // Despite the purge we're still over budget. Call our over budget callb ack. If this frees
366 if (resource->isPurgeable()) { 358 // any resources then we'll get notifyPurgeable() calls and take appropr iate action.
367 resource->cacheAccess().release(); 359 (*fOverBudgetCB)(fOverBudgetData);
368 } 360 this->validate();
369 resource = prev; 361 }
370 if (fBudgetedCount <= fMaxCount && fBudgetedBytes <= fMaxBytes) { 362 }
371 overBudget = false;
372 resource = NULL;
373 }
374 }
375 363
376 if (!fNewlyPurgeableResourceWhilePurging && overBudget && fOverBudgetCB) { 364 void GrResourceCache::purgeAllUnlocked() {
377 // Despite the purge we're still over budget. Call our over budget c allback. 365 // We could disable maintaining the heap property here, but it would add a l ot of complexity.
378 (*fOverBudgetCB)(fOverBudgetData); 366 // Moreover, this is rarely called.
379 } 367 while (fPurgeableQueue.count()) {
380 } while (overBudget && fNewlyPurgeableResourceWhilePurging); 368 GrGpuResource* resource = fPurgeableQueue.peek();
369 SkASSERT(resource->isPurgeable());
370 resource->cacheAccess().release();
371 }
381 372
382 fNewlyPurgeableResourceWhilePurging = false;
383 fPurging = false;
384 this->validate(); 373 this->validate();
385 } 374 }
386 375
387 void GrResourceCache::purgeAllUnlocked() {
388 SkASSERT(!fPurging);
389 SkASSERT(!fNewlyPurgeableResourceWhilePurging);
390
391 fPurging = true;
392
393 do {
394 fNewlyPurgeableResourceWhilePurging = false;
395 ResourceList::Iter resourceIter;
396 GrGpuResource* resource =
397 resourceIter.init(fResources, ResourceList::Iter::kTail_IterStart);
398
399 while (resource) {
400 GrGpuResource* prev = resourceIter.prev();
401 if (resource->isPurgeable()) {
402 resource->cacheAccess().release();
403 }
404 resource = prev;
405 }
406
407 if (!fNewlyPurgeableResourceWhilePurging && fCount && fOverBudgetCB) {
408 (*fOverBudgetCB)(fOverBudgetData);
409 }
410 } while (fNewlyPurgeableResourceWhilePurging);
411 fPurging = false;
412 this->validate();
413 }
414
415 void GrResourceCache::processInvalidContentKeys( 376 void GrResourceCache::processInvalidContentKeys(
416 const SkTArray<GrContentKeyInvalidatedMessage>& msgs) { 377 const SkTArray<GrContentKeyInvalidatedMessage>& msgs) {
417 for (int i = 0; i < msgs.count(); ++i) { 378 for (int i = 0; i < msgs.count(); ++i) {
418 GrGpuResource* resource = this->findAndRefContentResource(msgs[i].key()) ; 379 GrGpuResource* resource = this->findAndRefContentResource(msgs[i].key()) ;
419 if (resource) { 380 if (resource) {
420 resource->resourcePriv().removeContentKey(); 381 resource->resourcePriv().removeContentKey();
421 resource->unref(); // will call notifyPurgeable, if it is indeed now purgeable. 382 resource->unref(); // will call notifyPurgeable, if it is indeed now purgeable.
422 } 383 }
423 } 384 }
424 } 385 }
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after
468 ++content; 429 ++content;
469 SkASSERT(fContentHash.find(contentKey) == resource); 430 SkASSERT(fContentHash.find(contentKey) == resource);
470 SkASSERT(!resource->cacheAccess().isWrapped()); 431 SkASSERT(!resource->cacheAccess().isWrapped());
471 SkASSERT(resource->resourcePriv().isBudgeted()); 432 SkASSERT(resource->resourcePriv().isBudgeted());
472 } 433 }
473 434
474 if (resource->resourcePriv().isBudgeted()) { 435 if (resource->resourcePriv().isBudgeted()) {
475 ++budgetedCount; 436 ++budgetedCount;
476 budgetedBytes += resource->gpuMemorySize(); 437 budgetedBytes += resource->gpuMemorySize();
477 } 438 }
439
440 if (!resource->isPurgeable()) {
441 SkASSERT(-1 == *resource->cacheAccess().accessCacheIndex());
442 }
478 } 443 }
479 444
445 for (int i = 0; i < fPurgeableQueue.count(); ++i) {
446 SkASSERT(fPurgeableQueue.at(i)->isPurgeable());
447 }
448
449 SkASSERT(fCount - locked == fPurgeableQueue.count());
480 SkASSERT(fBudgetedCount <= fCount); 450 SkASSERT(fBudgetedCount <= fCount);
481 SkASSERT(fBudgetedBytes <= fBudgetedBytes); 451 SkASSERT(fBudgetedBytes <= fBudgetedBytes);
482 SkASSERT(bytes == fBytes); 452 SkASSERT(bytes == fBytes);
483 SkASSERT(count == fCount); 453 SkASSERT(count == fCount);
484 SkASSERT(budgetedBytes == fBudgetedBytes); 454 SkASSERT(budgetedBytes == fBudgetedBytes);
485 SkASSERT(budgetedCount == fBudgetedCount); 455 SkASSERT(budgetedCount == fBudgetedCount);
486 #if GR_CACHE_STATS 456 #if GR_CACHE_STATS
487 SkASSERT(fBudgetedHighWaterCount <= fHighWaterCount); 457 SkASSERT(fBudgetedHighWaterCount <= fHighWaterCount);
488 SkASSERT(fBudgetedHighWaterBytes <= fHighWaterBytes); 458 SkASSERT(fBudgetedHighWaterBytes <= fHighWaterBytes);
489 SkASSERT(bytes <= fHighWaterBytes); 459 SkASSERT(bytes <= fHighWaterBytes);
490 SkASSERT(count <= fHighWaterCount); 460 SkASSERT(count <= fHighWaterCount);
491 SkASSERT(budgetedBytes <= fBudgetedHighWaterBytes); 461 SkASSERT(budgetedBytes <= fBudgetedHighWaterBytes);
492 SkASSERT(budgetedCount <= fBudgetedHighWaterCount); 462 SkASSERT(budgetedCount <= fBudgetedHighWaterCount);
493 #endif 463 #endif
494 SkASSERT(content == fContentHash.count()); 464 SkASSERT(content == fContentHash.count());
495 SkASSERT(scratch + couldBeScratch == fScratchMap.count()); 465 SkASSERT(scratch + couldBeScratch == fScratchMap.count());
496 466
497 // This assertion is not currently valid because we can be in recursive noti fyIsPurgeable() 467 // This assertion is not currently valid because we can be in recursive noti fyIsPurgeable()
498 // calls. This will be fixed when subresource registration is explicit. 468 // calls. This will be fixed when subresource registration is explicit.
499 // bool overBudget = budgetedBytes > fMaxBytes || budgetedCount > fMaxCount; 469 // bool overBudget = budgetedBytes > fMaxBytes || budgetedCount > fMaxCount;
500 // SkASSERT(!overBudget || locked == count || fPurging); 470 // SkASSERT(!overBudget || locked == count || fPurging);
501 } 471 }
502 #endif 472 #endif
OLDNEW
« no previous file with comments | « src/gpu/GrResourceCache.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698