| 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 |