Index: src/gpu/GrResourceCache.cpp |
diff --git a/src/gpu/GrResourceCache.cpp b/src/gpu/GrResourceCache.cpp |
index e9be509569a09efef5d22d9ad9ffb5b84a722a73..a9d30805ce1d5dfcf6676eba346f94d3cb0c1510 100644 |
--- a/src/gpu/GrResourceCache.cpp |
+++ b/src/gpu/GrResourceCache.cpp |
@@ -10,6 +10,8 @@ |
#include "GrResourceCache.h" |
#include "GrGpuResource.h" |
+#include "GrTexturePriv.h" |
+ |
DECLARE_SKMESSAGEBUS_MESSAGE(GrResourceInvalidatedMessage); |
@@ -76,20 +78,17 @@ void GrResourceCacheEntry::didChangeResourceSize() { |
/////////////////////////////////////////////////////////////////////////////// |
-GrResourceCache::GrResourceCache(int maxCount, size_t maxBytes) : |
- fMaxCount(maxCount), |
- fMaxBytes(maxBytes) { |
+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; |
- fHighWaterClientDetachedCount = 0; |
- fHighWaterClientDetachedBytes = 0; |
#endif |
fEntryCount = 0; |
fEntryBytes = 0; |
- fClientDetachedCount = 0; |
- fClientDetachedBytes = 0; |
fPurging = false; |
@@ -136,55 +135,26 @@ void GrResourceCache::setLimits(int maxResources, size_t maxResourceBytes) { |
} |
} |
-void GrResourceCache::internalDetach(GrResourceCacheEntry* entry, |
- BudgetBehaviors behavior) { |
+void GrResourceCache::internalDetach(GrResourceCacheEntry* entry) { |
fList.remove(entry); |
- |
- // update our stats |
- if (kIgnore_BudgetBehavior == behavior) { |
- fClientDetachedCount += 1; |
- fClientDetachedBytes += entry->fCachedSize; |
- |
-#if GR_CACHE_STATS |
- if (fHighWaterClientDetachedCount < fClientDetachedCount) { |
- fHighWaterClientDetachedCount = fClientDetachedCount; |
- } |
- if (fHighWaterClientDetachedBytes < fClientDetachedBytes) { |
- fHighWaterClientDetachedBytes = fClientDetachedBytes; |
- } |
-#endif |
- |
- } else { |
- SkASSERT(kAccountFor_BudgetBehavior == behavior); |
- |
- fEntryCount -= 1; |
- fEntryBytes -= entry->fCachedSize; |
- } |
+ fEntryCount -= 1; |
+ fEntryBytes -= entry->fCachedSize; |
} |
-void GrResourceCache::attachToHead(GrResourceCacheEntry* entry, |
- BudgetBehaviors behavior) { |
+void GrResourceCache::attachToHead(GrResourceCacheEntry* entry) { |
fList.addToHead(entry); |
- // update our stats |
- if (kIgnore_BudgetBehavior == behavior) { |
- fClientDetachedCount -= 1; |
- fClientDetachedBytes -= entry->fCachedSize; |
- } else { |
- SkASSERT(kAccountFor_BudgetBehavior == behavior); |
- |
- fEntryCount += 1; |
- fEntryBytes += entry->fCachedSize; |
+ fEntryCount += 1; |
+ fEntryBytes += entry->fCachedSize; |
#if GR_CACHE_STATS |
- if (fHighWaterEntryCount < fEntryCount) { |
- fHighWaterEntryCount = fEntryCount; |
- } |
- if (fHighWaterEntryBytes < fEntryBytes) { |
- fHighWaterEntryBytes = fEntryBytes; |
- } |
-#endif |
+ if (fHighWaterEntryCount < fEntryCount) { |
+ fHighWaterEntryCount = fEntryCount; |
} |
+ if (fHighWaterEntryBytes < fEntryBytes) { |
+ fHighWaterEntryBytes = fEntryBytes; |
+ } |
+#endif |
} |
// This functor just searches for an entry with only a single ref (from |
@@ -193,41 +163,53 @@ void GrResourceCache::attachToHead(GrResourceCacheEntry* entry, |
class GrTFindUnreffedFunctor { |
public: |
bool operator()(const GrResourceCacheEntry* entry) const { |
- return entry->resource()->unique(); |
+ return entry->resource()->isPurgable(); |
} |
}; |
-GrGpuResource* GrResourceCache::find(const GrResourceKey& key, uint32_t ownershipFlags) { |
+ |
+void GrResourceCache::makeResourceMRU(GrGpuResource* resource) { |
+ GrResourceCacheEntry* entry = resource->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->getCacheEntry()); |
+ if (resource->getCacheEntry()->key().getResourceType() == GrTexturePriv::ResourceType() && |
+ resource->fIsScratch && |
+ !fCaps->reuseScratchTextures() && |
+ !(static_cast<const GrTexture*>(resource)->desc().fFlags & |
+ kRenderTarget_GrTextureFlagBit)) { |
+ this->deleteResource(resource->getCacheEntry()); |
+ } |
+} |
+ |
+GrGpuResource* GrResourceCache::find(const GrResourceKey& key) { |
GrAutoResourceCacheValidate atcv(this); |
GrResourceCacheEntry* entry = NULL; |
- if (ownershipFlags & kNoOtherOwners_OwnershipFlag) { |
- GrTFindUnreffedFunctor functor; |
- |
- entry = fCache.find<GrTFindUnreffedFunctor>(key, functor); |
- } else { |
- entry = fCache.find(key); |
- } |
+ entry = fCache.find(key); |
if (NULL == entry) { |
return NULL; |
} |
- if (ownershipFlags & kHide_OwnershipFlag) { |
- this->makeExclusive(entry); |
- } else { |
- // Make this resource MRU |
- this->internalDetach(entry); |
- this->attachToHead(entry); |
- } |
+ // Make this resource MRU |
+ this->internalDetach(entry); |
+ this->attachToHead(entry); |
+ // GrResourceCache2 is responsible for scratch resources. |
+ SkASSERT(GrGpuResource::kNo_IsScratch == entry->resource()->fIsScratch); |
return entry->fResource; |
} |
-void GrResourceCache::addResource(const GrResourceKey& key, |
- GrGpuResource* resource, |
- uint32_t ownershipFlags) { |
+void GrResourceCache::addResource(const GrResourceKey& key, GrGpuResource* resource) { |
SkASSERT(NULL == resource->getCacheEntry()); |
// we don't expect to create new resources during a purge. In theory |
// this could cause purgeAsNeeded() into an infinite loop (e.g. |
@@ -242,76 +224,16 @@ void GrResourceCache::addResource(const GrResourceKey& key, |
this->attachToHead(entry); |
fCache.insert(key, entry); |
- if (ownershipFlags & kHide_OwnershipFlag) { |
- this->makeExclusive(entry); |
- } |
- |
-} |
- |
-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); |
- fCache.remove(entry->key(), entry); |
- |
-#ifdef SK_DEBUG |
- fExclusiveList.addToHead(entry); |
-#endif |
-} |
- |
-void GrResourceCache::removeInvalidResource(GrResourceCacheEntry* entry) { |
- // If the resource went invalid while it was detached then purge it |
- // This can happen when a 3D context was lost, |
- // the client called GrContext::abandonContext() 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; |
- fClientDetachedBytes -= entry->fCachedSize; |
- fEntryBytes -= entry->fCachedSize; |
- entry->fCachedSize = 0; |
-} |
- |
-void GrResourceCache::makeNonExclusive(GrResourceCacheEntry* entry) { |
- GrAutoResourceCacheValidate atcv(this); |
- |
-#ifdef SK_DEBUG |
- fExclusiveList.remove(entry); |
-#endif |
- |
- if (!entry->resource()->wasDestroyed()) { |
- // Since scratch textures still count against the cache budget even |
- // when they have been removed from the cache, re-adding them doesn't |
- // alter the budget information. |
- attachToHead(entry, kIgnore_BudgetBehavior); |
- fCache.insert(entry->key(), entry); |
- |
- SkASSERT(entry->fIsExclusive); |
- entry->fIsExclusive = false; |
- } else { |
- this->removeInvalidResource(entry); |
- } |
+ this->purgeAsNeeded(); |
} |
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 |
@@ -359,13 +281,6 @@ void GrResourceCache::purgeInvalidated() { |
fInvalidationInbox.poll(&invalidated); |
for (int i = 0; i < invalidated.count(); i++) { |
- // We're somewhat missing an opportunity here. We could use the |
- // default find functor that gives us back resources whether we own |
- // them exclusively or not, and when they're not exclusively owned mark |
- // them for purging later when they do become exclusively owned. |
- // |
- // This is complicated and confusing. May try this in the future. For |
- // now, these resources are just LRU'd as if we never got the message. |
while (GrResourceCacheEntry* entry = fCache.find(invalidated[i].key, GrTFindUnreffedFunctor())) { |
this->deleteResource(entry); |
} |
@@ -373,7 +288,7 @@ void GrResourceCache::purgeInvalidated() { |
} |
void GrResourceCache::deleteResource(GrResourceCacheEntry* entry) { |
- SkASSERT(entry->fResource->unique()); |
+ SkASSERT(entry->fResource->isPurgable()); |
// remove from our cache |
fCache.remove(entry->key(), entry); |
@@ -412,7 +327,7 @@ void GrResourceCache::internalPurge(int extraCount, size_t extraBytes) { |
} |
GrResourceCacheEntry* prev = iter.prev(); |
- if (entry->fResource->unique()) { |
+ if (entry->fResource->isPurgable()) { |
changed = true; |
this->deleteResource(entry); |
} |
@@ -435,14 +350,7 @@ void GrResourceCache::purgeAllUnlocked() { |
this->purgeAsNeeded(); |
#ifdef SK_DEBUG |
- SkASSERT(fExclusiveList.countEntries() == fClientDetachedCount); |
- SkASSERT(countBytes(fExclusiveList) == fClientDetachedBytes); |
if (!fCache.count()) { |
- // Items may have been detached from the cache (such as the backing |
- // texture for an SkGpuDevice). The above purge would not have removed |
- // them. |
- SkASSERT(fEntryCount == fClientDetachedCount); |
- SkASSERT(fEntryBytes == fClientDetachedBytes); |
SkASSERT(fList.isEmpty()); |
} |
#endif |
@@ -474,25 +382,14 @@ static bool both_zero_or_nonzero(int count, size_t bytes) { |
void GrResourceCache::validate() const { |
fList.validate(); |
- fExclusiveList.validate(); |
SkASSERT(both_zero_or_nonzero(fEntryCount, fEntryBytes)); |
- SkASSERT(both_zero_or_nonzero(fClientDetachedCount, fClientDetachedBytes)); |
- SkASSERT(fClientDetachedBytes <= fEntryBytes); |
- SkASSERT(fClientDetachedCount <= fEntryCount); |
- SkASSERT((fEntryCount - fClientDetachedCount) == fCache.count()); |
+ SkASSERT(fEntryCount == fCache.count()); |
EntryList::Iter iter; |
- // check that the exclusively held entries are okay |
- const GrResourceCacheEntry* entry = iter.init(const_cast<EntryList&>(fExclusiveList), |
- EntryList::Iter::kHead_IterStart); |
- |
- for ( ; entry; entry = iter.next()) { |
- entry->validate(); |
- } |
- |
// check that the shareable entries are okay |
- entry = iter.init(const_cast<EntryList&>(fList), EntryList::Iter::kHead_IterStart); |
+ const GrResourceCacheEntry* entry = iter.init(const_cast<EntryList&>(fList), |
+ EntryList::Iter::kHead_IterStart); |
int count = 0; |
for ( ; entry; entry = iter.next()) { |
@@ -500,17 +397,11 @@ void GrResourceCache::validate() const { |
SkASSERT(fCache.find(entry->key())); |
count += 1; |
} |
- SkASSERT(count == fEntryCount - fClientDetachedCount); |
- |
- size_t bytes = countBytes(fList); |
- SkASSERT(bytes == fEntryBytes - fClientDetachedBytes); |
- |
- bytes = countBytes(fExclusiveList); |
- SkASSERT(bytes == fClientDetachedBytes); |
- |
- SkASSERT(fList.countEntries() == fEntryCount - fClientDetachedCount); |
+ SkASSERT(count == fEntryCount); |
- SkASSERT(fExclusiveList.countEntries() == fClientDetachedCount); |
+ size_t bytes = this->countBytes(fList); |
+ SkASSERT(bytes == fEntryBytes); |
+ SkASSERT(fList.countEntries() == fEntryCount); |
} |
#endif // SK_DEBUG |
@@ -534,10 +425,6 @@ void GrResourceCache::printStats() { |
fEntryCount, locked, fHighWaterEntryCount); |
SkDebugf("\t\tEntry Bytes: current %d high %d\n", |
fEntryBytes, fHighWaterEntryBytes); |
- SkDebugf("\t\tDetached Entry Count: current %d high %d\n", |
- fClientDetachedCount, fHighWaterClientDetachedCount); |
- SkDebugf("\t\tDetached Bytes: current %d high %d\n", |
- fClientDetachedBytes, fHighWaterClientDetachedBytes); |
} |
#endif |