aboutsummaryrefslogtreecommitdiffhomepage
path: root/src
diff options
context:
space:
mode:
authorGravatar robertphillips@google.com <robertphillips@google.com@2bbb7eff-a529-9590-31e7-b0007b416f81>2012-10-31 12:25:21 +0000
committerGravatar robertphillips@google.com <robertphillips@google.com@2bbb7eff-a529-9590-31e7-b0007b416f81>2012-10-31 12:25:21 +0000
commit209a1143a1a26935578d45c7f86dc6f9aa2eb1a6 (patch)
tree18a8acaf8ae8e318e0447ed1849b094f705a8e2d /src
parente862d16162fd46ad9b2832c8844b00c81bedbac0 (diff)
Ganesh resource cache changes
Diffstat (limited to 'src')
-rw-r--r--src/gpu/GrContext.cpp17
-rw-r--r--src/gpu/GrResourceCache.cpp68
-rw-r--r--src/gpu/GrResourceCache.h38
3 files changed, 92 insertions, 31 deletions
diff --git a/src/gpu/GrContext.cpp b/src/gpu/GrContext.cpp
index 900af8acbd..f7f6b0c0b7 100644
--- a/src/gpu/GrContext.cpp
+++ b/src/gpu/GrContext.cpp
@@ -236,7 +236,7 @@ void GrContext::addStencilBuffer(GrStencilBuffer* sb) {
GrResourceKey resourceKey = GrStencilBuffer::ComputeKey(sb->width(),
sb->height(),
sb->numSamples());
- fTextureCache->create(resourceKey, sb);
+ fTextureCache->addResource(resourceKey, sb);
}
GrStencilBuffer* GrContext::findStencilBuffer(int width, int height,
@@ -378,7 +378,7 @@ GrTexture* GrContext::createTexture(
}
if (NULL != texture) {
- fTextureCache->create(resourceKey, texture);
+ fTextureCache->addResource(resourceKey, texture);
}
return texture;
@@ -407,7 +407,8 @@ GrTexture* GrContext::lockScratchTexture(const GrTextureDesc& inDesc,
do {
GrResourceKey key = GrTexture::ComputeKey(fGpu, NULL, desc, cacheData, true);
- resource = fTextureCache->find(key);
+ // Ensure we have exclusive access to the texture so future 'find' calls don't return it
+ resource = fTextureCache->find(key, GrResourceCache::kHide_OwnershipFlag);
// if we miss, relax the fit of the flags...
// then try doubling width... then height.
if (NULL != resource || kExact_ScratchTexMatch == match) {
@@ -443,18 +444,12 @@ GrTexture* GrContext::lockScratchTexture(const GrTextureDesc& inDesc,
texture->desc(),
cacheData,
true);
- fTextureCache->create(key, texture);
+ // Make the resource exclusive so future 'find' calls don't return it
+ fTextureCache->addResource(key, texture, GrResourceCache::kHide_OwnershipFlag);
resource = texture;
}
}
- // If the caller gives us the same desc twice we don't want to return the
- // same texture the second time (unless it was previously released). So
- // make it exclusive to hide it from future searches.
- if (NULL != resource) {
- fTextureCache->makeExclusive(resource->getCacheEntry());
- }
-
return static_cast<GrTexture*>(resource);
}
diff --git a/src/gpu/GrResourceCache.cpp b/src/gpu/GrResourceCache.cpp
index 89fce55f70..825b122bfa 100644
--- a/src/gpu/GrResourceCache.cpp
+++ b/src/gpu/GrResourceCache.cpp
@@ -94,7 +94,7 @@ GrResourceCache::~GrResourceCache() {
fCache.remove(entry->fKey, entry);
// remove from our llist
- this->internalDetach(entry, false);
+ this->internalDetach(entry);
delete entry;
}
@@ -121,11 +121,11 @@ void GrResourceCache::setLimits(int maxResources, size_t maxResourceBytes) {
}
void GrResourceCache::internalDetach(GrResourceEntry* entry,
- bool clientDetach) {
+ BudgetBehaviors behavior) {
fList.remove(entry);
// update our stats
- if (clientDetach) {
+ if (kIgnore_BudgetBehavior == behavior) {
fClientDetachedCount += 1;
fClientDetachedBytes += entry->resource()->sizeInBytes();
@@ -139,20 +139,24 @@ void GrResourceCache::internalDetach(GrResourceEntry* entry,
#endif
} else {
+ GrAssert(kAccountFor_BudgetBehavior == behavior);
+
fEntryCount -= 1;
fEntryBytes -= entry->resource()->sizeInBytes();
}
}
void GrResourceCache::attachToHead(GrResourceEntry* entry,
- bool clientReattach) {
+ BudgetBehaviors behavior) {
fList.addToHead(entry);
// update our stats
- if (clientReattach) {
+ if (kIgnore_BudgetBehavior == behavior) {
fClientDetachedCount -= 1;
fClientDetachedBytes -= entry->resource()->sizeInBytes();
} else {
+ GrAssert(kAccountFor_BudgetBehavior == behavior);
+
fEntryCount += 1;
fEntryBytes += entry->resource()->sizeInBytes();
@@ -167,16 +171,40 @@ void GrResourceCache::attachToHead(GrResourceEntry* entry,
}
}
-GrResource* GrResourceCache::find(const GrResourceKey& key) {
+// This functor just searches for an entry with only a single ref (from
+// the texture cache itself). Presumably in this situation no one else
+// is relying on the texture.
+class GrTFindUnreffedFunctor {
+public:
+ bool operator()(const GrResourceEntry* entry) const {
+ return 1 == entry->resource()->getRefCnt();
+ }
+};
+
+GrResource* GrResourceCache::find(const GrResourceKey& key, uint32_t ownershipFlags) {
GrAutoResourceCacheValidate atcv(this);
- GrResourceEntry* entry = fCache.find(key);
+ GrResourceEntry* entry = NULL;
+
+ if (ownershipFlags & kNoOtherOwners_OwnershipFlag) {
+ GrTFindUnreffedFunctor functor;
+
+ entry = fCache.find<GrTFindUnreffedFunctor>(key, functor);
+ } else {
+ entry = fCache.find(key);
+ }
+
if (NULL == entry) {
return NULL;
}
- this->internalDetach(entry, false);
- this->attachToHead(entry, false);
+ if (ownershipFlags & kHide_OwnershipFlag) {
+ this->makeExclusive(entry);
+ } else {
+ // Make this resource MRU
+ this->internalDetach(entry);
+ this->attachToHead(entry);
+ }
return entry->fResource;
}
@@ -185,7 +213,9 @@ bool GrResourceCache::hasKey(const GrResourceKey& key) const {
return NULL != fCache.find(key);
}
-void GrResourceCache::create(const GrResourceKey& key, GrResource* resource) {
+void GrResourceCache::addResource(const GrResourceKey& key,
+ GrResource* resource,
+ uint32_t ownershipFlags) {
GrAssert(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.
@@ -197,19 +227,26 @@ void GrResourceCache::create(const GrResourceKey& key, GrResource* resource) {
GrResourceEntry* entry = SkNEW_ARGS(GrResourceEntry, (key, resource));
resource->setCacheEntry(entry);
- this->attachToHead(entry, false);
+ this->attachToHead(entry);
fCache.insert(key, entry);
#if GR_DUMP_TEXTURE_UPLOAD
GrPrintf("--- add resource to cache %p, count=%d bytes= %d %d\n",
entry, fEntryCount, resource->sizeInBytes(), fEntryBytes);
#endif
+
+ if (ownershipFlags & kHide_OwnershipFlag) {
+ this->makeExclusive(entry);
+ }
+
}
void GrResourceCache::makeExclusive(GrResourceEntry* entry) {
GrAutoResourceCacheValidate atcv(this);
- this->internalDetach(entry, 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);
#if GR_DEBUG
@@ -238,7 +275,10 @@ void GrResourceCache::makeNonExclusive(GrResourceEntry* entry) {
#endif
if (entry->resource()->isValid()) {
- attachToHead(entry, true);
+ // 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);
} else {
this->removeInvalidResource(entry);
@@ -290,7 +330,7 @@ void GrResourceCache::purgeAsNeeded() {
fCache.remove(entry->key(), entry);
// remove from our llist
- this->internalDetach(entry, false);
+ this->internalDetach(entry);
#if GR_DUMP_TEXTURE_UPLOAD
GrPrintf("--- ~resource from cache %p [%d %d]\n",
diff --git a/src/gpu/GrResourceCache.h b/src/gpu/GrResourceCache.h
index 7897b7ae47..4ee7015d11 100644
--- a/src/gpu/GrResourceCache.h
+++ b/src/gpu/GrResourceCache.h
@@ -220,20 +220,41 @@ public:
*/
size_t getCachedResourceBytes() const { return fEntryBytes; }
+ // For a found or added resource to be completely exclusive to the caller
+ // both the kNoOtherOwners and kHide flags need to be specified
+ enum OwnershipFlags {
+ kNoOtherOwners_OwnershipFlag = 0x1, // found/added resource has no other owners
+ kHide_OwnershipFlag = 0x2 // found/added resource is hidden from future 'find's
+ };
+
/**
* Search for an entry with the same Key. If found, return it.
* If not found, return null.
+ * If ownershipFlags includes kNoOtherOwners and a resource is returned
+ * then that resource has no other refs to it.
+ * If ownershipFlags includes kHide and a resource is returned then that
+ * resource will not be returned from future 'find' calls until it is
+ * 'freed' (and recycled) or makeNonExclusive is called.
+ * For a resource to be completely exclusive to a caller both kNoOtherOwners
+ * and kHide must be specified.
*/
- GrResource* find(const GrResourceKey& key);
+ GrResource* find(const GrResourceKey& key,
+ uint32_t ownershipFlags = 0);
/**
- * Create a new cache entry, based on the provided key and resource, and
- * return it.
+ * Add the new resource to the cache (by creating a new cache entry based
+ * on the provided key and resource).
*
* Ownership of the resource is transferred to the resource cache,
* which will unref() it when it is purged or deleted.
+ *
+ * If ownershipFlags includes kHide, subsequent calls to 'find' will not
+ * return 'resource' until it is 'freed' (and recycled) or makeNonExclusive
+ * is called.
*/
- void create(const GrResourceKey&, GrResource*);
+ void addResource(const GrResourceKey& key,
+ GrResource* resource,
+ uint32_t ownershipFlags = 0);
/**
* Determines if the cache contains an entry matching a key. If a matching
@@ -278,8 +299,13 @@ public:
#endif
private:
- void internalDetach(GrResourceEntry*, bool);
- void attachToHead(GrResourceEntry*, bool);
+ enum BudgetBehaviors {
+ kAccountFor_BudgetBehavior,
+ kIgnore_BudgetBehavior
+ };
+
+ void internalDetach(GrResourceEntry*, BudgetBehaviors behavior = kAccountFor_BudgetBehavior);
+ void attachToHead(GrResourceEntry*, BudgetBehaviors behavior = kAccountFor_BudgetBehavior);
void removeInvalidResource(GrResourceEntry* entry);