Remove all knowledge of resource keys from the legacy cache.

BUG=skia:2889

Review URL: https://codereview.chromium.org/705413002
This commit is contained in:
bsalomon 2014-11-11 07:27:16 -08:00 committed by Commit bot
parent a99f9eeed6
commit 6d4488c5e0
7 changed files with 68 additions and 91 deletions

View 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.

View 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);
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());
fCacheEntry = cacheEntry;
if (this->wasDestroyed() || NULL == cacheEntry) {
return true;
}
if (!cacheEntry->key().isScratch()) {
if (!get_resource_cache2(fGpu)->didAddContentKey(this)) {
fCacheEntry = NULL;
if (fContentKeySet) {
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;
}

View 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,12 +161,14 @@ 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() &&
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());
}
}
}
bool GrResourceCache::addResource(const GrResourceKey& key, GrGpuResource* resource) {
@ -191,6 +176,14 @@ bool GrResourceCache::addResource(const GrResourceKey& key, GrGpuResource* resou
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.
// each resource destroyed creates and locks 2 resources and
@ -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);

View 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;
};
///////////////////////////////////////////////////////////////////////////////

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

View 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();

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