| 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 (*fOverbudgetCB)(fOverbudgetData); |
| 293 this->internalPurge(); |
| 294 } |
| 289 | 295 |
| 290 // Note: the following code relies on the fact that the | 296 fPurging = false; |
| 291 // doubly linked list doesn't invalidate its data/pointers | 297 } |
| 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 | 298 |
| 296 while (NULL != entry) { | 299 void GrResourceCache::internalPurge() { |
| 297 GrAutoResourceCacheValidate atcv(this); | 300 SkASSERT(fPurging); |
| 298 | 301 |
| 299 if (fEntryCount <= fMaxCount && fEntryBytes <= fMaxBytes) { | 302 bool withinBudget = false; |
| 300 withinBudget = true; | 303 bool changed = false; |
| 301 break; | |
| 302 } | |
| 303 | 304 |
| 304 GrResourceEntry* prev = iter.prev(); | 305 // The purging process is repeated several times since one pass |
| 305 if (1 == entry->fResource->getRefCnt()) { | 306 // may free up other resources |
| 306 changed = true; | 307 do { |
| 308 EntryList::Iter iter; |
| 307 | 309 |
| 308 // remove from our cache | 310 changed = false; |
| 309 fCache.remove(entry->key(), entry); | |
| 310 | 311 |
| 311 // remove from our llist | 312 // Note: the following code relies on the fact that the |
| 312 this->internalDetach(entry); | 313 // doubly linked list doesn't invalidate its data/pointers |
| 313 delete entry; | 314 // outside of the specific area where a deletion occurs (e.g., |
| 314 } | 315 // in internalDetach) |
| 315 entry = prev; | 316 GrResourceEntry* entry = iter.init(fList, EntryList::Iter::kTail_IterSta
rt); |
| 317 |
| 318 while (NULL != entry) { |
| 319 GrAutoResourceCacheValidate atcv(this); |
| 320 |
| 321 if (fEntryCount <= fMaxCount && fEntryBytes <= fMaxBytes) { |
| 322 withinBudget = true; |
| 323 break; |
| 316 } | 324 } |
| 317 } while (!withinBudget && changed); | 325 |
| 318 fPurging = false; | 326 GrResourceEntry* prev = iter.prev(); |
| 319 } | 327 if (1 == entry->fResource->getRefCnt()) { |
| 328 changed = true; |
| 329 |
| 330 // remove from our cache |
| 331 fCache.remove(entry->key(), entry); |
| 332 |
| 333 // remove from our llist |
| 334 this->internalDetach(entry); |
| 335 delete entry; |
| 336 } |
| 337 entry = prev; |
| 338 } |
| 339 } while (!withinBudget && changed); |
| 320 } | 340 } |
| 321 | 341 |
| 322 void GrResourceCache::purgeAllUnlocked() { | 342 void GrResourceCache::purgeAllUnlocked() { |
| 323 GrAutoResourceCacheValidate atcv(this); | 343 GrAutoResourceCacheValidate atcv(this); |
| 324 | 344 |
| 325 // we can have one GrResource holding a lock on another | 345 // we can have one GrResource holding a lock on another |
| 326 // so we don't want to just do a simple loop kicking each | 346 // so we don't want to just do a simple loop kicking each |
| 327 // entry out. Instead change the budget and purge. | 347 // entry out. Instead change the budget and purge. |
| 328 | 348 |
| 329 int savedMaxBytes = fMaxBytes; | 349 int savedMaxBytes = fMaxBytes; |
| (...skipping 107 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 437 fEntryBytes, fHighWaterEntryBytes); | 457 fEntryBytes, fHighWaterEntryBytes); |
| 438 SkDebugf("\t\tDetached Entry Count: current %d high %d\n", | 458 SkDebugf("\t\tDetached Entry Count: current %d high %d\n", |
| 439 fClientDetachedCount, fHighWaterClientDetachedCount); | 459 fClientDetachedCount, fHighWaterClientDetachedCount); |
| 440 SkDebugf("\t\tDetached Bytes: current %d high %d\n", | 460 SkDebugf("\t\tDetached Bytes: current %d high %d\n", |
| 441 fClientDetachedBytes, fHighWaterClientDetachedBytes); | 461 fClientDetachedBytes, fHighWaterClientDetachedBytes); |
| 442 } | 462 } |
| 443 | 463 |
| 444 #endif | 464 #endif |
| 445 | 465 |
| 446 /////////////////////////////////////////////////////////////////////////////// | 466 /////////////////////////////////////////////////////////////////////////////// |
| OLD | NEW |