Index: src/gpu/GrResourceCache.cpp |
=================================================================== |
--- src/gpu/GrResourceCache.cpp (revision 9928) |
+++ src/gpu/GrResourceCache.cpp (working copy) |
@@ -62,7 +62,10 @@ |
fClientDetachedCount = 0; |
fClientDetachedBytes = 0; |
- fPurging = false; |
+ fPurging = false; |
+ |
+ fOverbudgetCB = NULL; |
+ fOverbudgetData = NULL; |
} |
GrResourceCache::~GrResourceCache() { |
@@ -275,48 +278,66 @@ |
* potentially make purgeAsNeeded loop infinitely. |
*/ |
void GrResourceCache::purgeAsNeeded() { |
- if (!fPurging) { |
- fPurging = true; |
- bool withinBudget = false; |
- bool changed = false; |
+ if (fPurging) { |
+ return; |
+ } |
- // The purging process is repeated several times since one pass |
- // may free up other resources |
- do { |
- EntryList::Iter iter; |
+ fPurging = true; |
- changed = false; |
+ this->internalPurge(); |
+ if ((fEntryCount > fMaxCount || fEntryBytes > fMaxBytes) && |
+ NULL != fOverbudgetCB) { |
+ // Despite the purge we're still over budget. See if Ganesh can |
+ // release some resources and purge again. |
+ if ((*fOverbudgetCB)(fOverbudgetData)) { |
+ this->internalPurge(); |
+ } |
+ } |
- // Note: the following code relies on the fact that the |
- // doubly linked list doesn't invalidate its data/pointers |
- // outside of the specific area where a deletion occurs (e.g., |
- // in internalDetach) |
- GrResourceEntry* entry = iter.init(fList, EntryList::Iter::kTail_IterStart); |
+ fPurging = false; |
+} |
- while (NULL != entry) { |
- GrAutoResourceCacheValidate atcv(this); |
+void GrResourceCache::internalPurge() { |
+ SkASSERT(fPurging); |
- if (fEntryCount <= fMaxCount && fEntryBytes <= fMaxBytes) { |
- withinBudget = true; |
- break; |
- } |
+ bool withinBudget = false; |
+ bool changed = false; |
- GrResourceEntry* prev = iter.prev(); |
- if (1 == entry->fResource->getRefCnt()) { |
- changed = true; |
+ // The purging process is repeated several times since one pass |
+ // may free up other resources |
+ do { |
+ EntryList::Iter iter; |
- // remove from our cache |
- fCache.remove(entry->key(), entry); |
+ changed = false; |
- // remove from our llist |
- this->internalDetach(entry); |
- delete entry; |
- } |
- entry = prev; |
+ // Note: the following code relies on the fact that the |
+ // doubly linked list doesn't invalidate its data/pointers |
+ // outside of the specific area where a deletion occurs (e.g., |
+ // in internalDetach) |
+ GrResourceEntry* entry = iter.init(fList, EntryList::Iter::kTail_IterStart); |
+ |
+ while (NULL != entry) { |
+ GrAutoResourceCacheValidate atcv(this); |
+ |
+ if (fEntryCount <= fMaxCount && fEntryBytes <= fMaxBytes) { |
+ withinBudget = true; |
+ break; |
} |
- } while (!withinBudget && changed); |
- fPurging = false; |
- } |
+ |
+ GrResourceEntry* prev = iter.prev(); |
+ if (1 == entry->fResource->getRefCnt()) { |
+ changed = true; |
+ |
+ // remove from our cache |
+ fCache.remove(entry->key(), entry); |
+ |
+ // remove from our llist |
+ this->internalDetach(entry); |
+ delete entry; |
+ } |
+ entry = prev; |
+ } |
+ } while (!withinBudget && changed); |
} |
void GrResourceCache::purgeAllUnlocked() { |