diff options
Diffstat (limited to 'src/gpu/GrResourceCache2.cpp')
-rw-r--r-- | src/gpu/GrResourceCache2.cpp | 300 |
1 files changed, 3 insertions, 297 deletions
diff --git a/src/gpu/GrResourceCache2.cpp b/src/gpu/GrResourceCache2.cpp index 109e815dac..83143d7818 100644 --- a/src/gpu/GrResourceCache2.cpp +++ b/src/gpu/GrResourceCache2.cpp @@ -10,13 +10,6 @@ #include "GrResourceCache2.h" #include "GrGpuResource.h" -#include "SkGr.h" -#include "SkMessageBus.h" - -DECLARE_SKMESSAGEBUS_MESSAGE(GrResourceInvalidatedMessage); - -////////////////////////////////////////////////////////////////////////////// - GrResourceKey& GrResourceKey::NullScratchKey() { static const GrCacheID::Key kBogusKey = { { {0} } }; static GrCacheID kBogusID(ScratchDomain(), kBogusKey); @@ -34,85 +27,26 @@ GrCacheID::Domain GrResourceKey::ScratchDomain() { return gDomain; } -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); -} - ////////////////////////////////////////////////////////////////////////////// -class GrResourceCache2::AutoValidate : ::SkNoncopyable { -public: - AutoValidate(GrResourceCache2* cache) : fCache(cache) { cache->validate(); } - ~AutoValidate() { fCache->validate(); } -private: - GrResourceCache2* fCache; -}; - - ////////////////////////////////////////////////////////////////////////////// - -static const int kDefaultMaxCount = 2 * (1 << 10); -static const size_t kDefaultMaxSize = 96 * (1 << 20); - -GrResourceCache2::GrResourceCache2() - : fMaxCount(kDefaultMaxCount) - , fMaxBytes(kDefaultMaxSize) -#if GR_CACHE_STATS - , fHighWaterCount(0) - , fHighWaterBytes(0) -#endif - , fCount(0) - , fBytes(0) - , fPurging(false) - , fNewlyPurgableResourceWhilePurging(false) - , fOverBudgetCB(NULL) - , fOverBudgetData(NULL) { -} - GrResourceCache2::~GrResourceCache2() { this->releaseAll(); } -void GrResourceCache2::setLimits(int count, size_t bytes) { - fMaxCount = count; - fMaxBytes = bytes; - this->purgeAsNeeded(); -} - void GrResourceCache2::insertResource(GrGpuResource* resource) { - AutoValidate av(this); - SkASSERT(resource); SkASSERT(!resource->wasDestroyed()); SkASSERT(!this->isInCache(resource)); - SkASSERT(!fPurging); fResources.addToHead(resource); - resource->ref(); - ++fCount; - SkDEBUGCODE(fHighWaterCount = SkTMax(fCount, fHighWaterCount)); - fBytes += resource->gpuMemorySize(); - SkDEBUGCODE(fHighWaterBytes = SkTMax(fBytes, fHighWaterBytes)); if (!resource->cacheAccess().getScratchKey().isNullScratch()) { // TODO(bsalomon): Make this assertion possible. // SkASSERT(!resource->isWrapped()); fScratchMap.insert(resource->cacheAccess().getScratchKey(), resource); } - - this->purgeAsNeeded(); } void GrResourceCache2::removeResource(GrGpuResource* resource) { - AutoValidate av(this); - - --fCount; - fBytes -= resource->gpuMemorySize(); SkASSERT(this->isInCache(resource)); fResources.remove(resource); if (!resource->cacheAccess().getScratchKey().isNullScratch()) { @@ -121,16 +55,13 @@ void GrResourceCache2::removeResource(GrGpuResource* resource) { if (const GrResourceKey* contentKey = resource->cacheAccess().getContentKey()) { fContentHash.remove(*contentKey); } + --fCount; } void GrResourceCache2::abandonAll() { - AutoValidate av(this); - - SkASSERT(!fPurging); while (GrGpuResource* head = fResources.head()) { SkASSERT(!head->wasDestroyed()); head->abandon(); - head->unref(); // abandon should have already removed this from the list. SkASSERT(head != fResources.head()); } @@ -140,13 +71,9 @@ void GrResourceCache2::abandonAll() { } void GrResourceCache2::releaseAll() { - AutoValidate av(this); - - SkASSERT(!fPurging); while (GrGpuResource* head = fResources.head()) { SkASSERT(!head->wasDestroyed()); head->release(); - head->unref(); // release should have already removed this from the list. SkASSERT(head != fResources.head()); } @@ -172,16 +99,11 @@ private: GrGpuResource* GrResourceCache2::findAndRefScratchResource(const GrResourceKey& scratchKey, uint32_t flags) { - AutoValidate av(this); - - SkASSERT(!fPurging); SkASSERT(scratchKey.isScratch()); - GrGpuResource* resource; if (flags & (kPreferNoPendingIO_ScratchFlag | kRequireNoPendingIO_ScratchFlag)) { - resource = fScratchMap.find(scratchKey, AvailableForScratchUse(true)); + GrGpuResource* resource = fScratchMap.find(scratchKey, AvailableForScratchUse(true)); if (resource) { - this->makeResourceMRU(resource); return SkRef(resource); } else if (flags & kRequireNoPendingIO_ScratchFlag) { return NULL; @@ -189,18 +111,11 @@ GrGpuResource* GrResourceCache2::findAndRefScratchResource(const GrResourceKey& // TODO: fail here when kPrefer is specified, we didn't find a resource without pending io, // but there is still space in our budget for the resource. } - resource = fScratchMap.find(scratchKey, AvailableForScratchUse(false)); - if (resource) { - resource->ref(); - this->makeResourceMRU(resource); - } - return resource; + return SkSafeRef(fScratchMap.find(scratchKey, AvailableForScratchUse(false))); } bool GrResourceCache2::didSetContentKey(GrGpuResource* resource) { - SkASSERT(!fPurging); SkASSERT(resource); - SkASSERT(this->isInCache(resource)); SkASSERT(resource->cacheAccess().getContentKey()); SkASSERT(!resource->cacheAccess().getContentKey()->isScratch()); @@ -210,214 +125,5 @@ bool GrResourceCache2::didSetContentKey(GrGpuResource* resource) { } fContentHash.add(resource); - this->validate(); return true; } - -void GrResourceCache2::makeResourceMRU(GrGpuResource* resource) { - AutoValidate av(this); - - SkASSERT(!fPurging); - SkASSERT(resource); - SkASSERT(this->isInCache(resource)); - fResources.remove(resource); - fResources.addToHead(resource); -} - -void GrResourceCache2::notifyPurgable(const GrGpuResource* resource) { - SkASSERT(resource); - SkASSERT(this->isInCache(resource)); - SkASSERT(resource->isPurgable()); - - // We can't purge if in the middle of purging because purge is iterating. Instead record - // that additional resources became purgable. - if (fPurging) { - fNewlyPurgableResourceWhilePurging = true; - return; - } - - // Purge the resource if we're over budget - bool overBudget = fCount > fMaxCount || fBytes > fMaxBytes; - - // We should not be over budget here unless all resources are unpuragble. -#ifdef SK_DEBUG - if (overBudget) { - ResourceList::Iter iter; - GrGpuResource* r = iter.init(fResources, ResourceList::Iter::kHead_IterStart); - for ( ; r; r = iter.next()) { - SkASSERT(r == resource || !r->isPurgable()); - } - } -#endif - - // Also purge if the resource has neither a valid scratch key nor a content key. - bool noKey = !resource->cacheAccess().isScratch() && - (NULL == resource->cacheAccess().getContentKey()); - - if (overBudget || noKey) { - SkDEBUGCODE(int beforeCount = fCount;) - resource->unref(); - SkASSERT(fCount == beforeCount - 1); - } - - this->validate(); -} - -void GrResourceCache2::didChangeGpuMemorySize(const GrGpuResource* resource, size_t oldSize) { - // SkASSERT(!fPurging); GrPathRange increases size during flush. :( - SkASSERT(resource); - SkASSERT(this->isInCache(resource)); - - fBytes += resource->gpuMemorySize() - oldSize; - SkDEBUGCODE(fHighWaterBytes = SkTMax(fBytes, fHighWaterBytes)); - - this->purgeAsNeeded(); - this->validate(); -} - -void GrResourceCache2::internalPurgeAsNeeded() { - SkASSERT(!fPurging); - SkASSERT(!fNewlyPurgableResourceWhilePurging); - SkASSERT(fCount > fMaxCount || fBytes > fMaxBytes); - - fPurging = true; - - AutoValidate av(this); // Put this after setting fPurging so we're allowed to be over budget. - - bool overBudget = true; - do { - fNewlyPurgableResourceWhilePurging = false; - ResourceList::Iter resourceIter; - GrGpuResource* resource = resourceIter.init(fResources, - ResourceList::Iter::kTail_IterStart); - - while (resource) { - GrGpuResource* prev = resourceIter.prev(); - if (resource->isPurgable()) { - resource->unref(); - } - resource = prev; - if (fCount <= fMaxCount && fBytes <= fMaxBytes) { - overBudget = false; - resource = NULL; - } - } - - if (!fNewlyPurgableResourceWhilePurging && overBudget && fOverBudgetCB) { - // Despite the purge we're still over budget. Call our over budget callback. - (*fOverBudgetCB)(fOverBudgetData); - } - } while (overBudget && fNewlyPurgableResourceWhilePurging); - - fNewlyPurgableResourceWhilePurging = false; - fPurging = false; -} - -void GrResourceCache2::purgeAllUnlocked() { - SkASSERT(!fPurging); - SkASSERT(!fNewlyPurgableResourceWhilePurging); - - fPurging = true; - - AutoValidate av(this); // Put this after setting fPurging so we're allowed to be over budget. - - do { - fNewlyPurgableResourceWhilePurging = false; - ResourceList::Iter resourceIter; - GrGpuResource* resource = - resourceIter.init(fResources, ResourceList::Iter::kTail_IterStart); - - while (resource) { - GrGpuResource* prev = resourceIter.prev(); - if (resource->isPurgable()) { - resource->unref(); - } - resource = prev; - } - - if (!fNewlyPurgableResourceWhilePurging && fCount && fOverBudgetCB) { - (*fOverBudgetCB)(fOverBudgetData); - } - } while (fNewlyPurgableResourceWhilePurging); - fPurging = false; -} - -#ifdef SK_DEBUG -void GrResourceCache2::validate() const { - size_t bytes = 0; - int count = 0; - int locked = 0; - int scratch = 0; - int couldBeScratch = 0; - int content = 0; - - ResourceList::Iter iter; - GrGpuResource* resource = iter.init(fResources, ResourceList::Iter::kHead_IterStart); - for ( ; resource; resource = iter.next()) { - bytes += resource->gpuMemorySize(); - ++count; - - if (!resource->isPurgable()) { - ++locked; - } - - if (resource->cacheAccess().isScratch()) { - SkASSERT(NULL == resource->cacheAccess().getContentKey()); - ++scratch; - SkASSERT(fScratchMap.countForKey(resource->cacheAccess().getScratchKey())); - } else if (!resource->cacheAccess().getScratchKey().isNullScratch()) { - SkASSERT(NULL != resource->cacheAccess().getContentKey()); - ++couldBeScratch; - SkASSERT(fScratchMap.countForKey(resource->cacheAccess().getScratchKey())); - } - - if (const GrResourceKey* contentKey = resource->cacheAccess().getContentKey()) { - ++content; - SkASSERT(fContentHash.find(*contentKey) == resource); - } - } - - SkASSERT(bytes == fBytes); - SkASSERT(count == fCount); -#if GR_CACHE_STATS - SkASSERT(bytes <= fHighWaterBytes); - SkASSERT(count <= fHighWaterCount); -#endif - SkASSERT(content == fContentHash.count()); - SkASSERT(scratch + couldBeScratch == fScratchMap.count()); - - bool overBudget = bytes > fMaxBytes || count > fMaxCount; - SkASSERT(!overBudget || locked == count || fPurging); -} -#endif - -#if GR_CACHE_STATS -void GrResourceCache2::printStats() const { - this->validate(); - - int locked = 0; - int scratch = 0; - - ResourceList::Iter iter; - GrGpuResource* resource = iter.init(fResources, ResourceList::Iter::kHead_IterStart); - - for ( ; resource; resource = iter.next()) { - if (!resource->isPurgable()) { - ++locked; - } - if (resource->cacheAccess().isScratch()) { - ++scratch; - } - } - - float countUtilization = (100.f * fCount) / fMaxCount; - float byteUtilization = (100.f * fBytes) / 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", - fCount, locked, scratch, countUtilization, fHighWaterCount); - SkDebugf("\t\tEntry Bytes: current %d (%.2g%% full) high %d\n", - fBytes, byteUtilization, fHighWaterBytes); -} - -#endif |