aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/gpu
diff options
context:
space:
mode:
Diffstat (limited to 'src/gpu')
-rw-r--r--src/gpu/GrContext.cpp14
-rw-r--r--src/gpu/GrResourceCache.cpp105
-rw-r--r--src/gpu/GrResourceCache.h26
3 files changed, 102 insertions, 43 deletions
diff --git a/src/gpu/GrContext.cpp b/src/gpu/GrContext.cpp
index 78220c0279..39d0db33b4 100644
--- a/src/gpu/GrContext.cpp
+++ b/src/gpu/GrContext.cpp
@@ -541,6 +541,20 @@ void GrContext::purgeCache() {
}
}
+bool GrContext::OverbudgetCB(void* data) {
+ GrAssert(NULL != data);
+
+ GrContext* context = reinterpret_cast<GrContext*>(data);
+
+ // Flush the InOrderDrawBuffer to possibly free up some textures
+ context->flush();
+
+ // TODO: actually track flush's behavior rather than always just
+ // returning true.
+ return true;
+}
+
+
GrTexture* GrContext::createUncachedTexture(const GrTextureDesc& descIn,
void* srcData,
size_t rowBytes) {
diff --git a/src/gpu/GrResourceCache.cpp b/src/gpu/GrResourceCache.cpp
index fa4edadfe9..baae6bd31c 100644
--- a/src/gpu/GrResourceCache.cpp
+++ b/src/gpu/GrResourceCache.cpp
@@ -62,7 +62,10 @@ GrResourceCache::GrResourceCache(int maxCount, size_t maxBytes) :
fClientDetachedCount = 0;
fClientDetachedBytes = 0;
- fPurging = false;
+ fPurging = false;
+
+ fOverbudgetCB = NULL;
+ fOverbudgetData = NULL;
}
GrResourceCache::~GrResourceCache() {
@@ -275,48 +278,66 @@ void GrResourceCache::makeNonExclusive(GrResourceEntry* entry) {
* 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() {
diff --git a/src/gpu/GrResourceCache.h b/src/gpu/GrResourceCache.h
index c4ead34595..5ac4bf17ae 100644
--- a/src/gpu/GrResourceCache.h
+++ b/src/gpu/GrResourceCache.h
@@ -238,6 +238,25 @@ public:
void setLimits(int maxResource, size_t maxResourceBytes);
/**
+ * The callback function used by the cache when it is still over budget
+ * after a purge. The passed in 'data' is the same 'data' handed to
+ * setOverbudgetCallback. The callback returns true if some resources
+ * have been freed.
+ */
+ typedef bool (*PFOverbudgetCB)(void* data);
+
+ /**
+ * Set the callback the cache should use when it is still over budget
+ * after a purge. The 'data' provided here will be passed back to the
+ * callback. The cache will attempt to purge any resources newly freed
+ * by the callback.
+ */
+ void setOverbudgetCallback(PFOverbudgetCB overbudgetCB, void* data) {
+ fOverbudgetCB = overbudgetCB;
+ fOverbudgetData = data;
+ }
+
+ /**
* Returns the number of bytes consumed by cached resources.
*/
size_t getCachedResourceBytes() const { return fEntryBytes; }
@@ -360,7 +379,12 @@ private:
size_t fClientDetachedBytes;
// prevents recursive purging
- bool fPurging;
+ bool fPurging;
+
+ PFOverbudgetCB fOverbudgetCB;
+ void* fOverbudgetData;
+
+ void internalPurge();
#if GR_DEBUG
static size_t countBytes(const SkTInternalLList<GrResourceEntry>& list);