| 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() {
|
|
|