Ganesh resource cache changes

https://codereview.appspot.com/6784051/



git-svn-id: http://skia.googlecode.com/svn/trunk@6211 2bbb7eff-a529-9590-31e7-b0007b416f81
diff --git a/src/gpu/GrResourceCache.cpp b/src/gpu/GrResourceCache.cpp
index 89fce55..825b122 100644
--- a/src/gpu/GrResourceCache.cpp
+++ b/src/gpu/GrResourceCache.cpp
@@ -94,7 +94,7 @@
         fCache.remove(entry->fKey, entry);
 
         // remove from our llist
-        this->internalDetach(entry, false);
+        this->internalDetach(entry);
 
         delete entry;
     }
@@ -121,11 +121,11 @@
 }
 
 void GrResourceCache::internalDetach(GrResourceEntry* entry,
-                                    bool clientDetach) {
+                                     BudgetBehaviors behavior) {
     fList.remove(entry);
 
     // update our stats
-    if (clientDetach) {
+    if (kIgnore_BudgetBehavior == behavior) {
         fClientDetachedCount += 1;
         fClientDetachedBytes += entry->resource()->sizeInBytes();
 
@@ -139,20 +139,24 @@
 #endif
 
     } else {
+        GrAssert(kAccountFor_BudgetBehavior == behavior);
+
         fEntryCount -= 1;
         fEntryBytes -= entry->resource()->sizeInBytes();
     }
 }
 
 void GrResourceCache::attachToHead(GrResourceEntry* entry,
-                                   bool clientReattach) {
+                                   BudgetBehaviors behavior) {
     fList.addToHead(entry);
 
     // update our stats
-    if (clientReattach) {
+    if (kIgnore_BudgetBehavior == behavior) {
         fClientDetachedCount -= 1;
         fClientDetachedBytes -= entry->resource()->sizeInBytes();
     } else {
+        GrAssert(kAccountFor_BudgetBehavior == behavior);
+
         fEntryCount += 1;
         fEntryBytes += entry->resource()->sizeInBytes();
 
@@ -167,16 +171,40 @@
     }
 }
 
-GrResource* GrResourceCache::find(const GrResourceKey& key) {
+// This functor just searches for an entry with only a single ref (from
+// the texture cache itself). Presumably in this situation no one else
+// is relying on the texture.
+class GrTFindUnreffedFunctor {
+public:
+    bool operator()(const GrResourceEntry* entry) const { 
+        return 1 == entry->resource()->getRefCnt();
+    }
+};
+
+GrResource* GrResourceCache::find(const GrResourceKey& key, uint32_t ownershipFlags) {
     GrAutoResourceCacheValidate atcv(this);
 
-    GrResourceEntry* entry = fCache.find(key);
+    GrResourceEntry* entry = NULL;
+
+    if (ownershipFlags & kNoOtherOwners_OwnershipFlag) {
+        GrTFindUnreffedFunctor functor;
+
+        entry = fCache.find<GrTFindUnreffedFunctor>(key, functor);
+    } else {
+        entry = fCache.find(key);
+    }
+
     if (NULL == entry) {
         return NULL;
     }
 
-    this->internalDetach(entry, false);
-    this->attachToHead(entry, false);
+    if (ownershipFlags & kHide_OwnershipFlag) {
+        this->makeExclusive(entry);
+    } else {
+        // Make this resource MRU
+        this->internalDetach(entry);
+        this->attachToHead(entry);
+    }
 
     return entry->fResource;
 }
@@ -185,7 +213,9 @@
     return NULL != fCache.find(key);
 }
 
-void GrResourceCache::create(const GrResourceKey& key, GrResource* resource) {
+void GrResourceCache::addResource(const GrResourceKey& key, 
+                                  GrResource* resource,
+                                  uint32_t ownershipFlags) {
     GrAssert(NULL == resource->getCacheEntry());
     // we don't expect to create new resources during a purge. In theory
     // this could cause purgeAsNeeded() into an infinite loop (e.g.
@@ -197,19 +227,26 @@
     GrResourceEntry* entry = SkNEW_ARGS(GrResourceEntry, (key, resource));
     resource->setCacheEntry(entry);
 
-    this->attachToHead(entry, false);
+    this->attachToHead(entry);
     fCache.insert(key, entry);
 
 #if GR_DUMP_TEXTURE_UPLOAD
     GrPrintf("--- add resource to cache %p, count=%d bytes= %d %d\n",
              entry, fEntryCount, resource->sizeInBytes(), fEntryBytes);
 #endif
+
+    if (ownershipFlags & kHide_OwnershipFlag) {
+        this->makeExclusive(entry);
+    }
+
 }
 
 void GrResourceCache::makeExclusive(GrResourceEntry* entry) {
     GrAutoResourceCacheValidate atcv(this);
 
-    this->internalDetach(entry, true);
+    // When scratch textures are detached (to hide them from future finds) they
+    // still count against the resource budget
+    this->internalDetach(entry, kIgnore_BudgetBehavior);
     fCache.remove(entry->key(), entry);
 
 #if GR_DEBUG
@@ -238,7 +275,10 @@
 #endif
 
     if (entry->resource()->isValid()) {
-        attachToHead(entry, true);
+        // Since scratch textures still count against the cache budget even 
+        // when they have been removed from the cache, re-adding them doesn't 
+        // alter the budget information.
+        attachToHead(entry, kIgnore_BudgetBehavior);
         fCache.insert(entry->key(), entry);
     } else {
         this->removeInvalidResource(entry);
@@ -290,7 +330,7 @@
                     fCache.remove(entry->key(), entry);
 
                     // remove from our llist
-                    this->internalDetach(entry, false);
+                    this->internalDetach(entry);
 
         #if GR_DUMP_TEXTURE_UPLOAD
                     GrPrintf("--- ~resource from cache %p [%d %d]\n",