Allow the resource cache to (indirectly) flush the InOrderDrawBuffer
R=bsalomon@google.com
Author: robertphillips@google.com
Review URL: https://chromiumcodereview.appspot.com/18466005
git-svn-id: http://skia.googlecode.com/svn/trunk@9949 2bbb7eff-a529-9590-31e7-b0007b416f81
diff --git a/src/gpu/GrResourceCache.cpp b/src/gpu/GrResourceCache.cpp
index fa4edad..baae6bd 100644
--- a/src/gpu/GrResourceCache.cpp
+++ b/src/gpu/GrResourceCache.cpp
@@ -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;
-
- // The purging process is repeated several times since one pass
- // may free up other resources
- do {
- EntryList::Iter iter;
-
- changed = false;
-
- // 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;
- }
-
- 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);
- fPurging = false;
+ if (fPurging) {
+ return;
}
+
+ fPurging = true;
+
+ 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();
+ }
+ }
+
+ fPurging = false;
+}
+
+void GrResourceCache::internalPurge() {
+ SkASSERT(fPurging);
+
+ bool withinBudget = false;
+ bool changed = false;
+
+ // The purging process is repeated several times since one pass
+ // may free up other resources
+ do {
+ EntryList::Iter iter;
+
+ changed = false;
+
+ // 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;
+ }
+
+ 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() {