| Index: src/gpu/GrResourceCache2.cpp
|
| diff --git a/src/gpu/GrResourceCache2.cpp b/src/gpu/GrResourceCache2.cpp
|
| index 109e815dacc9150d55af160cf46254c9ec517b46..83143d78185898c8ed0ed83420228019de1f9d42 100644
|
| --- a/src/gpu/GrResourceCache2.cpp
|
| +++ b/src/gpu/GrResourceCache2.cpp
|
| @@ -9,13 +9,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} } };
|
| @@ -34,85 +27,26 @@
|
| 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 @@
|
| 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::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 @@
|
|
|
| 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 @@
|
| // 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 @@
|
| }
|
|
|
| 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
|
|
|