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:
parent
a99f9eeed6
commit
6d4488c5e0
@ -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.
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
};
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -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) {
|
||||
|
@ -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();
|
||||
|
||||
|
@ -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) {
|
||||
|
Loading…
Reference in New Issue
Block a user