Index: src/gpu/GrResourceCache.cpp |
diff --git a/src/gpu/GrResourceCache.cpp b/src/gpu/GrResourceCache.cpp |
deleted file mode 100644 |
index a73d11703db0ddd1686916fd8634b340e12661cf..0000000000000000000000000000000000000000 |
--- a/src/gpu/GrResourceCache.cpp |
+++ /dev/null |
@@ -1,393 +0,0 @@ |
- |
-/* |
- * Copyright 2010 Google Inc. |
- * |
- * Use of this source code is governed by a BSD-style license that can be |
- * found in the LICENSE file. |
- */ |
- |
-#include "GrResourceCache.h" |
-#include "GrGpuResource.h" |
-#include "GrGpuResourceCacheAccess.h" |
-#include "GrTexturePriv.h" |
- |
-DECLARE_SKMESSAGEBUS_MESSAGE(GrResourceInvalidatedMessage); |
- |
-/////////////////////////////////////////////////////////////////////////////// |
- |
-void GrGpuResource::didChangeGpuMemorySize() const { |
- fGpuMemorySize = kInvalidGpuMemorySize; |
- if (this->cacheAccess().isInCache()) { |
- fCacheEntry->didChangeResourceSize(); |
- } |
-} |
- |
-/////////////////////////////////////////////////////////////////////////////// |
- |
-GrResourceKey::ResourceType GrResourceKey::GenerateResourceType() { |
- static int32_t gNextType = 0; |
- |
- int32_t type = sk_atomic_inc(&gNextType); |
- if (type >= (1 << 8 * sizeof(ResourceType))) { |
- SkFAIL("Too many Resource Types"); |
- } |
- |
- return static_cast<ResourceType>(type); |
-} |
- |
-/////////////////////////////////////////////////////////////////////////////// |
- |
-GrResourceCacheEntry::GrResourceCacheEntry(GrResourceCache* resourceCache, GrGpuResource* resource) |
- : fResourceCache(resourceCache), |
- fResource(resource), |
- fCachedSize(resource->gpuMemorySize()) { |
- // we assume ownership of the resource, and will unref it when we die |
- SkASSERT(resource); |
- resource->ref(); |
-} |
- |
-GrResourceCacheEntry::~GrResourceCacheEntry() { |
- // We're relying on having the cache entry to remove this from GrResourceCache2's content hash. |
- // fResource->setCacheEntry(NULL); |
- fResource->unref(); |
-} |
- |
-#ifdef SK_DEBUG |
-void GrResourceCacheEntry::validate() const { |
- SkASSERT(fResourceCache); |
- SkASSERT(fResource); |
- SkASSERT(fResource->cacheAccess().getCacheEntry() == this); |
- SkASSERT(fResource->gpuMemorySize() == fCachedSize); |
- fResource->validate(); |
-} |
-#endif |
- |
-void GrResourceCacheEntry::didChangeResourceSize() { |
- size_t oldSize = fCachedSize; |
- fCachedSize = fResource->gpuMemorySize(); |
- if (fCachedSize > oldSize) { |
- fResourceCache->didIncreaseResourceSize(this, fCachedSize - oldSize); |
- } else if (fCachedSize < oldSize) { |
- fResourceCache->didDecreaseResourceSize(this, oldSize - fCachedSize); |
- } |
-} |
- |
-/////////////////////////////////////////////////////////////////////////////// |
- |
-GrResourceCache::GrResourceCache(const GrDrawTargetCaps* caps, int maxCount, size_t maxBytes) |
- : fMaxCount(maxCount) |
- , fMaxBytes(maxBytes) |
- , fCaps(SkRef(caps)) { |
-#if GR_CACHE_STATS |
- fHighWaterEntryCount = 0; |
- fHighWaterEntryBytes = 0; |
-#endif |
- |
- fEntryCount = 0; |
- fEntryBytes = 0; |
- |
- fPurging = false; |
- |
- fOverbudgetCB = NULL; |
- fOverbudgetData = NULL; |
-} |
- |
-GrResourceCache::~GrResourceCache() { |
- GrAutoResourceCacheValidate atcv(this); |
- |
- EntryList::Iter iter; |
- |
- // Unlike the removeAll, here we really remove everything, including locked resources. |
- while (GrResourceCacheEntry* entry = fList.head()) { |
- GrAutoResourceCacheValidate atcv(this); |
- |
- // remove from our llist |
- this->internalDetach(entry); |
- |
- delete entry; |
- } |
-} |
- |
-void GrResourceCache::getLimits(int* maxResources, size_t* maxResourceBytes) const{ |
- if (maxResources) { |
- *maxResources = fMaxCount; |
- } |
- if (maxResourceBytes) { |
- *maxResourceBytes = fMaxBytes; |
- } |
-} |
- |
-void GrResourceCache::setLimits(int maxResources, size_t maxResourceBytes) { |
- bool smaller = (maxResources < fMaxCount) || (maxResourceBytes < fMaxBytes); |
- |
- fMaxCount = maxResources; |
- fMaxBytes = maxResourceBytes; |
- |
- if (smaller) { |
- this->purgeAsNeeded(); |
- } |
-} |
- |
-void GrResourceCache::internalDetach(GrResourceCacheEntry* entry) { |
- fList.remove(entry); |
- fEntryCount -= 1; |
- fEntryBytes -= entry->fCachedSize; |
-} |
- |
-void GrResourceCache::attachToHead(GrResourceCacheEntry* entry) { |
- fList.addToHead(entry); |
- |
- fEntryCount += 1; |
- fEntryBytes += entry->fCachedSize; |
- |
-#if GR_CACHE_STATS |
- if (fHighWaterEntryCount < fEntryCount) { |
- fHighWaterEntryCount = fEntryCount; |
- } |
- if (fHighWaterEntryBytes < fEntryBytes) { |
- fHighWaterEntryBytes = fEntryBytes; |
- } |
-#endif |
-} |
- |
- |
-void GrResourceCache::makeResourceMRU(GrGpuResource* resource) { |
- GrResourceCacheEntry* entry = resource->cacheAccess().getCacheEntry(); |
- if (entry) { |
- this->internalDetach(entry); |
- this->attachToHead(entry); |
- } |
-} |
- |
-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->cacheAccess().getCacheEntry()); |
- if (resource->cacheAccess().isScratch()) { |
- const GrResourceKey& key = resource->cacheAccess().getScratchKey(); |
- if (key.getResourceType() == GrTexturePriv::ResourceType() && |
- !fCaps->reuseScratchTextures() && |
- !(static_cast<const GrSurface*>(resource)->desc().fFlags & kRenderTarget_GrSurfaceFlag)) { |
- this->deleteResource(resource->cacheAccess().getCacheEntry()); |
- } |
- } |
-} |
- |
-bool GrResourceCache::addResource(const GrResourceKey& key, GrGpuResource* resource) { |
- if (NULL != resource->cacheAccess().getCacheEntry()) { |
- return false; |
- } |
- |
- if (key.isScratch()) { |
- SkASSERT(resource->cacheAccess().isScratch()); |
- SkASSERT(key == resource->cacheAccess().getScratchKey()); |
- } else { |
- if (!resource->cacheAccess().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 |
- // unlocks 1 thereby causing a new purge). |
- SkASSERT(!fPurging); |
- GrAutoResourceCacheValidate atcv(this); |
- |
- GrResourceCacheEntry* entry = SkNEW_ARGS(GrResourceCacheEntry, (this, resource)); |
- resource->cacheAccess().setCacheEntry(entry); |
- |
- this->attachToHead(entry); |
- this->purgeAsNeeded(); |
- return true; |
-} |
- |
-void GrResourceCache::didIncreaseResourceSize(const GrResourceCacheEntry* entry, size_t amountInc) { |
- fEntryBytes += amountInc; |
- this->purgeAsNeeded(); |
-} |
- |
-void GrResourceCache::didDecreaseResourceSize(const GrResourceCacheEntry* entry, size_t amountDec) { |
- fEntryBytes -= amountDec; |
-#ifdef SK_DEBUG |
- this->validate(); |
-#endif |
-} |
- |
-/** |
- * Destroying a resource may potentially trigger the unlock of additional |
- * resources which in turn will trigger a nested purge. We block the nested |
- * purge using the fPurging variable. However, the initial purge will keep |
- * looping until either all resources in the cache are unlocked or we've met |
- * the budget. There is an assertion in createAndLock to check against a |
- * resource's destructor inserting new resources into the cache. If these |
- * new resources were unlocked before purgeAsNeeded completed it could |
- * potentially make purgeAsNeeded loop infinitely. |
- * |
- * extraCount and extraBytes are added to the current resource totals to account |
- * for incoming resources (e.g., GrContext is about to add 10MB split between |
- * 10 textures). |
- */ |
-void GrResourceCache::purgeAsNeeded(int extraCount, size_t extraBytes) { |
- if (fPurging) { |
- return; |
- } |
- |
- fPurging = true; |
- |
- this->internalPurge(extraCount, extraBytes); |
- if (((fEntryCount+extraCount) > fMaxCount || |
- (fEntryBytes+extraBytes) > fMaxBytes) && |
- fOverbudgetCB) { |
- // Despite the purge we're still over budget. See if Ganesh can |
- // release some resources and purge again. |
- if ((*fOverbudgetCB)(fOverbudgetData)) { |
- this->internalPurge(extraCount, extraBytes); |
- } |
- } |
- |
- fPurging = false; |
-} |
- |
-void GrResourceCache::purgeInvalidated() { |
- // TODO: Implement this in GrResourceCache2. |
-} |
- |
-void GrResourceCache::deleteResource(GrResourceCacheEntry* entry) { |
- SkASSERT(entry->fResource->isPurgable()); |
- // remove from our llist |
- this->internalDetach(entry); |
- delete entry; |
-} |
- |
-void GrResourceCache::internalPurge(int extraCount, size_t extraBytes) { |
- 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) |
- GrResourceCacheEntry* entry = iter.init(fList, EntryList::Iter::kTail_IterStart); |
- |
- while (entry) { |
- GrAutoResourceCacheValidate atcv(this); |
- |
- if ((fEntryCount+extraCount) <= fMaxCount && |
- (fEntryBytes+extraBytes) <= fMaxBytes) { |
- withinBudget = true; |
- break; |
- } |
- |
- GrResourceCacheEntry* prev = iter.prev(); |
- if (entry->fResource->isPurgable()) { |
- changed = true; |
- this->deleteResource(entry); |
- } |
- entry = prev; |
- } |
- } while (!withinBudget && changed); |
-} |
- |
-void GrResourceCache::purgeAllUnlocked() { |
- GrAutoResourceCacheValidate atcv(this); |
- |
- // we can have one GrCacheable holding a lock on another |
- // so we don't want to just do a simple loop kicking each |
- // entry out. Instead change the budget and purge. |
- |
- size_t savedMaxBytes = fMaxBytes; |
- int savedMaxCount = fMaxCount; |
- fMaxBytes = (size_t) -1; |
- fMaxCount = 0; |
- this->purgeAsNeeded(); |
- |
- fMaxBytes = savedMaxBytes; |
- fMaxCount = savedMaxCount; |
-} |
- |
-/////////////////////////////////////////////////////////////////////////////// |
- |
-#ifdef SK_DEBUG |
-size_t GrResourceCache::countBytes(const EntryList& list) { |
- size_t bytes = 0; |
- |
- EntryList::Iter iter; |
- |
- const GrResourceCacheEntry* entry = iter.init(const_cast<EntryList&>(list), |
- EntryList::Iter::kTail_IterStart); |
- |
- for ( ; entry; entry = iter.prev()) { |
- bytes += entry->resource()->gpuMemorySize(); |
- } |
- return bytes; |
-} |
- |
-static bool both_zero_or_nonzero(int count, size_t bytes) { |
- return (count == 0 && bytes == 0) || (count > 0 && bytes > 0); |
-} |
- |
-void GrResourceCache::validate() const { |
- fList.validate(); |
- SkASSERT(both_zero_or_nonzero(fEntryCount, fEntryBytes)); |
- |
- EntryList::Iter iter; |
- |
- // check that the shareable entries are okay |
- const GrResourceCacheEntry* entry = iter.init(const_cast<EntryList&>(fList), |
- EntryList::Iter::kHead_IterStart); |
- |
- int count = 0; |
- for ( ; entry; entry = iter.next()) { |
- entry->validate(); |
- count += 1; |
- } |
- SkASSERT(count == fEntryCount); |
- |
- size_t bytes = this->countBytes(fList); |
- SkASSERT(bytes == fEntryBytes); |
- SkASSERT(fList.countEntries() == fEntryCount); |
-} |
-#endif // SK_DEBUG |
- |
-#if GR_CACHE_STATS |
- |
-void GrResourceCache::printStats() { |
- int locked = 0; |
- int scratch = 0; |
- |
- EntryList::Iter iter; |
- |
- GrResourceCacheEntry* entry = iter.init(fList, EntryList::Iter::kTail_IterStart); |
- |
- for ( ; entry; entry = iter.prev()) { |
- if (!entry->fResource->isPurgable()) { |
- ++locked; |
- } |
- if (entry->fResource->cacheAccess().isScratch()) { |
- ++scratch; |
- } |
- } |
- |
- float countUtilization = (100.f * fEntryCount) / fMaxCount; |
- float byteUtilization = (100.f * fEntryBytes) / fMaxBytes; |
- |
- SkDebugf("Budget: %d items %d bytes\n", fMaxCount, fMaxBytes); |
- SkDebugf("\t\tEntry Count: current %d (%d locked, %d scratch %.2g%% full), high %d\n", |
- fEntryCount, locked, scratch, countUtilization, fHighWaterEntryCount); |
- SkDebugf("\t\tEntry Bytes: current %d (%.2g%% full) high %d\n", |
- fEntryBytes, byteUtilization, fHighWaterEntryBytes); |
-} |
- |
-#endif |
- |
-/////////////////////////////////////////////////////////////////////////////// |