diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/gpu/GrResourceCache.cpp | 73 | ||||
-rw-r--r-- | src/gpu/GrResourceCache.h | 21 | ||||
-rw-r--r-- | src/gpu/GrTexture.cpp | 27 |
3 files changed, 110 insertions, 11 deletions
diff --git a/src/gpu/GrResourceCache.cpp b/src/gpu/GrResourceCache.cpp index 26f7592548..529c3a5d1d 100644 --- a/src/gpu/GrResourceCache.cpp +++ b/src/gpu/GrResourceCache.cpp @@ -13,6 +13,16 @@ DECLARE_SKMESSAGEBUS_MESSAGE(GrResourceInvalidatedMessage); +/////////////////////////////////////////////////////////////////////////////// + +void GrCacheable::didChangeGpuMemorySize() const { + if (this->isInCache()) { + fCacheEntry->didChangeResourceSize(); + } +} + +/////////////////////////////////////////////////////////////////////////////// + GrResourceKey::ResourceType GrResourceKey::GenerateResourceType() { static int32_t gNextType = 0; @@ -26,8 +36,14 @@ GrResourceKey::ResourceType GrResourceKey::GenerateResourceType() { /////////////////////////////////////////////////////////////////////////////// -GrResourceCacheEntry::GrResourceCacheEntry(const GrResourceKey& key, GrCacheable* resource) - : fKey(key), fResource(resource) { +GrResourceCacheEntry::GrResourceCacheEntry(GrResourceCache* resourceCache, + const GrResourceKey& key, + GrCacheable* resource) + : fResourceCache(resourceCache), + fKey(key), + fResource(resource), + fCachedSize(resource->gpuMemorySize()), + fIsExclusive(false) { // we assume ownership of the resource, and will unref it when we die SkASSERT(resource); resource->ref(); @@ -40,12 +56,24 @@ GrResourceCacheEntry::~GrResourceCacheEntry() { #ifdef SK_DEBUG void GrResourceCacheEntry::validate() const { + SkASSERT(fResourceCache); SkASSERT(fResource); SkASSERT(fResource->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(int maxCount, size_t maxBytes) : @@ -115,7 +143,7 @@ void GrResourceCache::internalDetach(GrResourceCacheEntry* entry, // update our stats if (kIgnore_BudgetBehavior == behavior) { fClientDetachedCount += 1; - fClientDetachedBytes += entry->resource()->gpuMemorySize(); + fClientDetachedBytes += entry->fCachedSize; #if GR_CACHE_STATS if (fHighWaterClientDetachedCount < fClientDetachedCount) { @@ -130,7 +158,7 @@ void GrResourceCache::internalDetach(GrResourceCacheEntry* entry, SkASSERT(kAccountFor_BudgetBehavior == behavior); fEntryCount -= 1; - fEntryBytes -= entry->resource()->gpuMemorySize(); + fEntryBytes -= entry->fCachedSize; } } @@ -141,12 +169,12 @@ void GrResourceCache::attachToHead(GrResourceCacheEntry* entry, // update our stats if (kIgnore_BudgetBehavior == behavior) { fClientDetachedCount -= 1; - fClientDetachedBytes -= entry->resource()->gpuMemorySize(); + fClientDetachedBytes -= entry->fCachedSize; } else { SkASSERT(kAccountFor_BudgetBehavior == behavior); fEntryCount += 1; - fEntryBytes += entry->resource()->gpuMemorySize(); + fEntryBytes += entry->fCachedSize; #if GR_CACHE_STATS if (fHighWaterEntryCount < fEntryCount) { @@ -208,7 +236,7 @@ void GrResourceCache::addResource(const GrResourceKey& key, SkASSERT(!fPurging); GrAutoResourceCacheValidate atcv(this); - GrResourceCacheEntry* entry = SkNEW_ARGS(GrResourceCacheEntry, (key, resource)); + GrResourceCacheEntry* entry = SkNEW_ARGS(GrResourceCacheEntry, (this, key, resource)); resource->setCacheEntry(entry); this->attachToHead(entry); @@ -223,6 +251,9 @@ void GrResourceCache::addResource(const GrResourceKey& key, void GrResourceCache::makeExclusive(GrResourceCacheEntry* entry) { GrAutoResourceCacheValidate atcv(this); + SkASSERT(!entry->fIsExclusive); + entry->fIsExclusive = true; + // When scratch textures are detached (to hide them from future finds) they // still count against the resource budget this->internalDetach(entry, kIgnore_BudgetBehavior); @@ -239,11 +270,12 @@ void GrResourceCache::removeInvalidResource(GrResourceCacheEntry* entry) { // the client called GrContext::contextDestroyed() to notify Gr, // and then later an SkGpuDevice's destructor releases its backing // texture (which was invalidated at contextDestroyed time). + // TODO: Safely delete the GrResourceCacheEntry as well. fClientDetachedCount -= 1; fEntryCount -= 1; - size_t size = entry->resource()->gpuMemorySize(); - fClientDetachedBytes -= size; - fEntryBytes -= size; + fClientDetachedBytes -= entry->fCachedSize; + fEntryBytes -= entry->fCachedSize; + entry->fCachedSize = 0; } void GrResourceCache::makeNonExclusive(GrResourceCacheEntry* entry) { @@ -259,11 +291,32 @@ void GrResourceCache::makeNonExclusive(GrResourceCacheEntry* entry) { // alter the budget information. attachToHead(entry, kIgnore_BudgetBehavior); fCache.insert(entry->key(), entry); + + SkASSERT(entry->fIsExclusive); + entry->fIsExclusive = false; } else { this->removeInvalidResource(entry); } } +void GrResourceCache::didIncreaseResourceSize(const GrResourceCacheEntry* entry, size_t amountInc) { + fEntryBytes += amountInc; + if (entry->fIsExclusive) { + fClientDetachedBytes += amountInc; + } + this->purgeAsNeeded(); +} + +void GrResourceCache::didDecreaseResourceSize(const GrResourceCacheEntry* entry, size_t amountDec) { + fEntryBytes -= amountDec; + if (entry->fIsExclusive) { + fClientDetachedBytes -= 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 diff --git a/src/gpu/GrResourceCache.h b/src/gpu/GrResourceCache.h index b2f91cdbdb..1a81fe61d1 100644 --- a/src/gpu/GrResourceCache.h +++ b/src/gpu/GrResourceCache.h @@ -19,6 +19,7 @@ #include "SkTInternalLList.h" class GrCacheable; +class GrResourceCache; class GrResourceCacheEntry; class GrResourceKey { @@ -128,12 +129,24 @@ public: void validate() const {} #endif + /** + * Update the cached size for this entry and inform the resource cache that + * it has changed. Usually invoked from GrCacheable::didChangeGpuMemorySize, + * not directly from here. + */ + void didChangeResourceSize(); + private: - GrResourceCacheEntry(const GrResourceKey& key, GrCacheable* resource); + GrResourceCacheEntry(GrResourceCache* resourceCache, + const GrResourceKey& key, + GrCacheable* resource); ~GrResourceCacheEntry(); + GrResourceCache* fResourceCache; GrResourceKey fKey; GrCacheable* fResource; + size_t fCachedSize; + bool fIsExclusive; // Linked list for the LRU ordering. SK_DECLARE_INTERNAL_LLIST_INTERFACE(GrResourceCacheEntry); @@ -272,6 +285,12 @@ public: void makeNonExclusive(GrResourceCacheEntry* entry); /** + * Notify the cache that the size of a resource has changed. + */ + void didIncreaseResourceSize(const GrResourceCacheEntry*, size_t amountInc); + void didDecreaseResourceSize(const GrResourceCacheEntry*, size_t amountDec); + + /** * Remove a resource from the cache and delete it! */ void deleteResource(GrResourceCacheEntry* entry); diff --git a/src/gpu/GrTexture.cpp b/src/gpu/GrTexture.cpp index f851515371..3186d89d77 100644 --- a/src/gpu/GrTexture.cpp +++ b/src/gpu/GrTexture.cpp @@ -44,6 +44,33 @@ void GrTexture::internal_dispose() const { this->INHERITED::internal_dispose(); } +void GrTexture::dirtyMipMaps(bool mipMapsDirty) { + if (mipMapsDirty) { + if (kValid_MipMapsStatus == fMipMapsStatus) { + fMipMapsStatus = kAllocated_MipMapsStatus; + } + } else { + const bool sizeChanged = kNotAllocated_MipMapsStatus == fMipMapsStatus; + fMipMapsStatus = kValid_MipMapsStatus; + if (sizeChanged) { + // This must not be called until after changing fMipMapsStatus. + this->didChangeGpuMemorySize(); + } + } +} + +size_t GrTexture::gpuMemorySize() const { + size_t textureSize = (size_t) fDesc.fWidth * + fDesc.fHeight * + GrBytesPerPixel(fDesc.fConfig); + if (kNotAllocated_MipMapsStatus != fMipMapsStatus) { + // We don't have to worry about the mipmaps being a different size than + // we'd expect because we never change fDesc.fWidth/fHeight. + textureSize *= 2; + } + return textureSize; +} + bool GrTexture::readPixels(int left, int top, int width, int height, GrPixelConfig config, void* buffer, size_t rowBytes, uint32_t pixelOpsFlags) { |