OLD | NEW |
1 | 1 |
2 /* | 2 /* |
3 * Copyright 2010 Google Inc. | 3 * Copyright 2010 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 | 10 |
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
55 fHighWaterEntryBytes = 0; | 55 fHighWaterEntryBytes = 0; |
56 fHighWaterClientDetachedCount = 0; | 56 fHighWaterClientDetachedCount = 0; |
57 fHighWaterClientDetachedBytes = 0; | 57 fHighWaterClientDetachedBytes = 0; |
58 #endif | 58 #endif |
59 | 59 |
60 fEntryCount = 0; | 60 fEntryCount = 0; |
61 fEntryBytes = 0; | 61 fEntryBytes = 0; |
62 fClientDetachedCount = 0; | 62 fClientDetachedCount = 0; |
63 fClientDetachedBytes = 0; | 63 fClientDetachedBytes = 0; |
64 | 64 |
65 fPurging = false; | 65 fPurging = false; |
| 66 |
| 67 fOverbudgetCB = NULL; |
| 68 fOverbudgetData = NULL; |
66 } | 69 } |
67 | 70 |
68 GrResourceCache::~GrResourceCache() { | 71 GrResourceCache::~GrResourceCache() { |
69 GrAutoResourceCacheValidate atcv(this); | 72 GrAutoResourceCacheValidate atcv(this); |
70 | 73 |
71 EntryList::Iter iter; | 74 EntryList::Iter iter; |
72 | 75 |
73 // Unlike the removeAll, here we really remove everything, including locked
resources. | 76 // Unlike the removeAll, here we really remove everything, including locked
resources. |
74 while (GrResourceEntry* entry = fList.head()) { | 77 while (GrResourceEntry* entry = fList.head()) { |
75 GrAutoResourceCacheValidate atcv(this); | 78 GrAutoResourceCacheValidate atcv(this); |
(...skipping 192 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
268 * Destroying a resource may potentially trigger the unlock of additional | 271 * Destroying a resource may potentially trigger the unlock of additional |
269 * resources which in turn will trigger a nested purge. We block the nested | 272 * resources which in turn will trigger a nested purge. We block the nested |
270 * purge using the fPurging variable. However, the initial purge will keep | 273 * purge using the fPurging variable. However, the initial purge will keep |
271 * looping until either all resources in the cache are unlocked or we've met | 274 * looping until either all resources in the cache are unlocked or we've met |
272 * the budget. There is an assertion in createAndLock to check against a | 275 * the budget. There is an assertion in createAndLock to check against a |
273 * resource's destructor inserting new resources into the cache. If these | 276 * resource's destructor inserting new resources into the cache. If these |
274 * new resources were unlocked before purgeAsNeeded completed it could | 277 * new resources were unlocked before purgeAsNeeded completed it could |
275 * potentially make purgeAsNeeded loop infinitely. | 278 * potentially make purgeAsNeeded loop infinitely. |
276 */ | 279 */ |
277 void GrResourceCache::purgeAsNeeded() { | 280 void GrResourceCache::purgeAsNeeded() { |
278 if (!fPurging) { | 281 if (fPurging) { |
279 fPurging = true; | 282 return; |
280 bool withinBudget = false; | 283 } |
281 bool changed = false; | |
282 | 284 |
283 // The purging process is repeated several times since one pass | 285 fPurging = true; |
284 // may free up other resources | |
285 do { | |
286 EntryList::Iter iter; | |
287 | 286 |
288 changed = false; | 287 this->internalPurge(); |
| 288 if ((fEntryCount > fMaxCount || fEntryBytes > fMaxBytes) && |
| 289 NULL != fOverbudgetCB) { |
| 290 // Despite the purge we're still over budget. See if Ganesh can |
| 291 // release some resources and purge again. |
| 292 if ((*fOverbudgetCB)(fOverbudgetData)) { |
| 293 this->internalPurge(); |
| 294 } |
| 295 } |
289 | 296 |
290 // Note: the following code relies on the fact that the | 297 fPurging = false; |
291 // doubly linked list doesn't invalidate its data/pointers | 298 } |
292 // outside of the specific area where a deletion occurs (e.g., | |
293 // in internalDetach) | |
294 GrResourceEntry* entry = iter.init(fList, EntryList::Iter::kTail_Ite
rStart); | |
295 | 299 |
296 while (NULL != entry) { | 300 void GrResourceCache::internalPurge() { |
297 GrAutoResourceCacheValidate atcv(this); | 301 SkASSERT(fPurging); |
298 | 302 |
299 if (fEntryCount <= fMaxCount && fEntryBytes <= fMaxBytes) { | 303 bool withinBudget = false; |
300 withinBudget = true; | 304 bool changed = false; |
301 break; | |
302 } | |
303 | 305 |
304 GrResourceEntry* prev = iter.prev(); | 306 // The purging process is repeated several times since one pass |
305 if (1 == entry->fResource->getRefCnt()) { | 307 // may free up other resources |
306 changed = true; | 308 do { |
| 309 EntryList::Iter iter; |
307 | 310 |
308 // remove from our cache | 311 changed = false; |
309 fCache.remove(entry->key(), entry); | |
310 | 312 |
311 // remove from our llist | 313 // Note: the following code relies on the fact that the |
312 this->internalDetach(entry); | 314 // doubly linked list doesn't invalidate its data/pointers |
313 delete entry; | 315 // outside of the specific area where a deletion occurs (e.g., |
314 } | 316 // in internalDetach) |
315 entry = prev; | 317 GrResourceEntry* entry = iter.init(fList, EntryList::Iter::kTail_IterSta
rt); |
| 318 |
| 319 while (NULL != entry) { |
| 320 GrAutoResourceCacheValidate atcv(this); |
| 321 |
| 322 if (fEntryCount <= fMaxCount && fEntryBytes <= fMaxBytes) { |
| 323 withinBudget = true; |
| 324 break; |
316 } | 325 } |
317 } while (!withinBudget && changed); | 326 |
318 fPurging = false; | 327 GrResourceEntry* prev = iter.prev(); |
319 } | 328 if (1 == entry->fResource->getRefCnt()) { |
| 329 changed = true; |
| 330 |
| 331 // remove from our cache |
| 332 fCache.remove(entry->key(), entry); |
| 333 |
| 334 // remove from our llist |
| 335 this->internalDetach(entry); |
| 336 delete entry; |
| 337 } |
| 338 entry = prev; |
| 339 } |
| 340 } while (!withinBudget && changed); |
320 } | 341 } |
321 | 342 |
322 void GrResourceCache::purgeAllUnlocked() { | 343 void GrResourceCache::purgeAllUnlocked() { |
323 GrAutoResourceCacheValidate atcv(this); | 344 GrAutoResourceCacheValidate atcv(this); |
324 | 345 |
325 // we can have one GrResource holding a lock on another | 346 // we can have one GrResource holding a lock on another |
326 // so we don't want to just do a simple loop kicking each | 347 // so we don't want to just do a simple loop kicking each |
327 // entry out. Instead change the budget and purge. | 348 // entry out. Instead change the budget and purge. |
328 | 349 |
329 int savedMaxBytes = fMaxBytes; | 350 int savedMaxBytes = fMaxBytes; |
(...skipping 107 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
437 fEntryBytes, fHighWaterEntryBytes); | 458 fEntryBytes, fHighWaterEntryBytes); |
438 SkDebugf("\t\tDetached Entry Count: current %d high %d\n", | 459 SkDebugf("\t\tDetached Entry Count: current %d high %d\n", |
439 fClientDetachedCount, fHighWaterClientDetachedCount); | 460 fClientDetachedCount, fHighWaterClientDetachedCount); |
440 SkDebugf("\t\tDetached Bytes: current %d high %d\n", | 461 SkDebugf("\t\tDetached Bytes: current %d high %d\n", |
441 fClientDetachedBytes, fHighWaterClientDetachedBytes); | 462 fClientDetachedBytes, fHighWaterClientDetachedBytes); |
442 } | 463 } |
443 | 464 |
444 #endif | 465 #endif |
445 | 466 |
446 /////////////////////////////////////////////////////////////////////////////// | 467 /////////////////////////////////////////////////////////////////////////////// |
OLD | NEW |