aboutsummaryrefslogtreecommitdiffhomepage
path: root/src
diff options
context:
space:
mode:
authorGravatar robertphillips@google.com <robertphillips@google.com@2bbb7eff-a529-9590-31e7-b0007b416f81>2013-07-19 16:51:46 +0000
committerGravatar robertphillips@google.com <robertphillips@google.com@2bbb7eff-a529-9590-31e7-b0007b416f81>2013-07-19 16:51:46 +0000
commite4eaea2d126d58d8ce4034a1ce921404e83fe3f4 (patch)
treeb198ea1e63b9244e288e42e8cc88c53da1a5193b /src
parent727b33faef255a455c067501f27460704e56e380 (diff)
Alter resource cache and GrContext to (optionally) never reuse a scratch texture
Diffstat (limited to 'src')
-rw-r--r--src/gpu/GrContext.cpp59
-rw-r--r--src/gpu/GrResourceCache.cpp27
-rw-r--r--src/gpu/GrResourceCache.h43
-rw-r--r--src/gpu/gl/GrGLCaps.cpp8
4 files changed, 85 insertions, 52 deletions
diff --git a/src/gpu/GrContext.cpp b/src/gpu/GrContext.cpp
index 72cb2b365b..64dbadf354 100644
--- a/src/gpu/GrContext.cpp
+++ b/src/gpu/GrContext.cpp
@@ -115,7 +115,6 @@ bool GrContext::init(GrBackend backend, GrBackendContext backendContext) {
fDrawState = SkNEW(GrDrawState);
fGpu->setDrawState(fDrawState);
-
fTextureCache = SkNEW_ARGS(GrResourceCache,
(MAX_TEXTURE_CACHE_COUNT,
MAX_TEXTURE_CACHE_BYTES));
@@ -399,11 +398,38 @@ GrTexture* GrContext::createTexture(const GrTextureParams* params,
return texture;
}
+static GrTexture* create_scratch_texture(GrGpu* gpu,
+ GrResourceCache* textureCache,
+ const GrTextureDesc& desc) {
+ GrTexture* texture = gpu->createTexture(desc, NULL, 0);
+ if (NULL != texture) {
+ GrResourceKey key = GrTexture::ComputeScratchKey(texture->desc());
+ // Adding a resource could put us overbudget. Try to free up the
+ // necessary space before adding it.
+ textureCache->purgeAsNeeded(1, texture->sizeInBytes());
+ // Make the resource exclusive so future 'find' calls don't return it
+ textureCache->addResource(key, texture, GrResourceCache::kHide_OwnershipFlag);
+ }
+ return texture;
+}
+
GrTexture* GrContext::lockAndRefScratchTexture(const GrTextureDesc& inDesc, ScratchTexMatch match) {
- GrTextureDesc desc = inDesc;
- GrAssert((desc.fFlags & kRenderTarget_GrTextureFlagBit) ||
- !(desc.fFlags & kNoStencil_GrTextureFlagBit));
+ GrAssert((inDesc.fFlags & kRenderTarget_GrTextureFlagBit) ||
+ !(inDesc.fFlags & kNoStencil_GrTextureFlagBit));
+
+ // Renderable A8 targets are not universally supported (e.g., not on ANGLE)
+ GrAssert(this->isConfigRenderable(kAlpha_8_GrPixelConfig) ||
+ !(inDesc.fFlags & kRenderTarget_GrTextureFlagBit) ||
+ (inDesc.fConfig != kAlpha_8_GrPixelConfig));
+
+ if (!fGpu->caps()->reuseScratchTextures()) {
+ // If we're never recycling scratch textures we can
+ // always make them the right size
+ return create_scratch_texture(fGpu, fTextureCache, inDesc);
+ }
+
+ GrTextureDesc desc = inDesc;
if (kApprox_ScratchTexMatch == match) {
// bin by pow2 with a reasonable min
@@ -412,11 +438,6 @@ GrTexture* GrContext::lockAndRefScratchTexture(const GrTextureDesc& inDesc, Scra
desc.fHeight = GrMax(MIN_SIZE, GrNextPow2(desc.fHeight));
}
- // Renderable A8 targets are not universally supported (e.g., not on ANGLE)
- GrAssert(this->isConfigRenderable(kAlpha_8_GrPixelConfig) ||
- !(desc.fFlags & kRenderTarget_GrTextureFlagBit) ||
- (desc.fConfig != kAlpha_8_GrPixelConfig));
-
GrResource* resource = NULL;
int origWidth = desc.fWidth;
int origHeight = desc.fHeight;
@@ -449,16 +470,7 @@ GrTexture* GrContext::lockAndRefScratchTexture(const GrTextureDesc& inDesc, Scra
desc.fFlags = inDesc.fFlags;
desc.fWidth = origWidth;
desc.fHeight = origHeight;
- GrTexture* texture = fGpu->createTexture(desc, NULL, 0);
- if (NULL != texture) {
- GrResourceKey key = GrTexture::ComputeScratchKey(texture->desc());
- // Adding a resource could put us overbudget. Try to free up the
- // necessary space before adding it.
- fTextureCache->purgeAsNeeded(1, texture->sizeInBytes());
- // Make the resource exclusive so future 'find' calls don't return it
- fTextureCache->addResource(key, texture, GrResourceCache::kHide_OwnershipFlag);
- resource = texture;
- }
+ resource = create_scratch_texture(fGpu, fTextureCache, desc);
}
return static_cast<GrTexture*>(resource);
@@ -482,7 +494,13 @@ void GrContext::addExistingTextureToCache(GrTexture* texture) {
// still be in the exclusive pile
fTextureCache->makeNonExclusive(texture->getCacheEntry());
- this->purgeCache();
+ if (fGpu->caps()->reuseScratchTextures()) {
+ this->purgeCache();
+ } else {
+ // When we aren't reusing textures we know this scratch texture
+ // will never be reused and would be just wasting time in the cache
+ fTextureCache->deleteResource(texture->getCacheEntry());
+ }
}
@@ -497,7 +515,6 @@ void GrContext::unlockScratchTexture(GrTexture* texture) {
fTextureCache->makeNonExclusive(texture->getCacheEntry());
this->purgeCache();
}
-
}
void GrContext::purgeCache() {
diff --git a/src/gpu/GrResourceCache.cpp b/src/gpu/GrResourceCache.cpp
index 00b2d514c1..03a4e899db 100644
--- a/src/gpu/GrResourceCache.cpp
+++ b/src/gpu/GrResourceCache.cpp
@@ -88,10 +88,10 @@ GrResourceCache::~GrResourceCache() {
}
void GrResourceCache::getLimits(int* maxResources, size_t* maxResourceBytes) const{
- if (maxResources) {
+ if (NULL != maxResources) {
*maxResources = fMaxCount;
}
- if (maxResourceBytes) {
+ if (NULL != maxResourceBytes) {
*maxResourceBytes = fMaxBytes;
}
}
@@ -196,10 +196,6 @@ GrResource* GrResourceCache::find(const GrResourceKey& key, uint32_t ownershipFl
return entry->fResource;
}
-bool GrResourceCache::hasKey(const GrResourceKey& key) const {
- return NULL != fCache.find(key);
-}
-
void GrResourceCache::addResource(const GrResourceKey& key,
GrResource* resource,
uint32_t ownershipFlags) {
@@ -302,6 +298,17 @@ void GrResourceCache::purgeAsNeeded(int extraCount, size_t extraBytes) {
fPurging = false;
}
+void GrResourceCache::deleteResource(GrResourceEntry* entry) {
+ GrAssert(1 == entry->fResource->getRefCnt());
+
+ // remove from our cache
+ fCache.remove(entry->key(), entry);
+
+ // remove from our llist
+ this->internalDetach(entry);
+ delete entry;
+}
+
void GrResourceCache::internalPurge(int extraCount, size_t extraBytes) {
SkASSERT(fPurging);
@@ -333,13 +340,7 @@ void GrResourceCache::internalPurge(int extraCount, size_t extraBytes) {
GrResourceEntry* prev = iter.prev();
if (1 == entry->fResource->getRefCnt()) {
changed = true;
-
- // remove from our cache
- fCache.remove(entry->key(), entry);
-
- // remove from our llist
- this->internalDetach(entry);
- delete entry;
+ this->deleteResource(entry);
}
entry = prev;
}
diff --git a/src/gpu/GrResourceCache.h b/src/gpu/GrResourceCache.h
index b27219eafc..679780aa48 100644
--- a/src/gpu/GrResourceCache.h
+++ b/src/gpu/GrResourceCache.h
@@ -222,7 +222,7 @@ public:
* @param maxResource If non-null, returns maximum number of resources
* that can be held in the cache.
* @param maxBytes If non-null, returns maximum number of bytes of
- * gpu memory that can be held in the cache.
+ * gpu memory that can be held in the cache.
*/
void getLimits(int* maxResources, size_t* maxBytes) const;
@@ -235,7 +235,7 @@ public:
* @param maxBytes The maximum number of bytes of resource memory that
* can be held in the cache.
*/
- void setLimits(int maxResource, size_t maxResourceBytes);
+ void setLimits(int maxResources, size_t maxResourceBytes);
/**
* The callback function used by the cache when it is still over budget
@@ -248,8 +248,8 @@ public:
/**
* Set the callback the cache should use when it is still over budget
* after a purge. The 'data' provided here will be passed back to the
- * callback. The cache will attempt to purge any resources newly freed
- * by the callback.
+ * callback. Note that the cache will attempt to purge any resources newly
+ * freed by the callback.
*/
void setOverbudgetCallback(PFOverbudgetCB overbudgetCB, void* data) {
fOverbudgetCB = overbudgetCB;
@@ -301,7 +301,7 @@ public:
* Determines if the cache contains an entry matching a key. If a matching
* entry exists but was detached then it will not be found.
*/
- bool hasKey(const GrResourceKey& key) const;
+ bool hasKey(const GrResourceKey& key) const { return NULL != fCache.find(key); }
/**
* Hide 'entry' so that future searches will not find it. Such
@@ -318,6 +318,11 @@ public:
void makeNonExclusive(GrResourceEntry* entry);
/**
+ * Remove a resource from the cache and delete it!
+ */
+ void deleteResource(GrResourceEntry* entry);
+
+ /**
* Removes every resource in the cache that isn't locked.
*/
void purgeAllUnlocked();
@@ -325,7 +330,9 @@ public:
/**
* Allow cache to purge unused resources to obey resource limitations
* Note: this entry point will be hidden (again) once totally ref-driven
- * cache maintenance is implemented
+ * cache maintenance is implemented. Note that the overbudget callback
+ * will be called if the initial purge doesn't get the cache under
+ * its budget.
*
* extraCount and extraBytes are added to the current resource allocation
* to make sure enough room is available for future additions (e.g,
@@ -358,29 +365,29 @@ private:
// We're an internal doubly linked list
typedef SkTInternalLList<GrResourceEntry> EntryList;
- EntryList fList;
+ EntryList fList;
#if GR_DEBUG
// These objects cannot be returned by a search
- EntryList fExclusiveList;
+ EntryList fExclusiveList;
#endif
// our budget, used in purgeAsNeeded()
- int fMaxCount;
- size_t fMaxBytes;
+ int fMaxCount;
+ size_t fMaxBytes;
// our current stats, related to our budget
#if GR_CACHE_STATS
- int fHighWaterEntryCount;
- size_t fHighWaterEntryBytes;
- int fHighWaterClientDetachedCount;
- size_t fHighWaterClientDetachedBytes;
+ int fHighWaterEntryCount;
+ size_t fHighWaterEntryBytes;
+ int fHighWaterClientDetachedCount;
+ size_t fHighWaterClientDetachedBytes;
#endif
- int fEntryCount;
- size_t fEntryBytes;
- int fClientDetachedCount;
- size_t fClientDetachedBytes;
+ int fEntryCount;
+ size_t fEntryBytes;
+ int fClientDetachedCount;
+ size_t fClientDetachedBytes;
// prevents recursive purging
bool fPurging;
diff --git a/src/gpu/gl/GrGLCaps.cpp b/src/gpu/gl/GrGLCaps.cpp
index d7b9992cab..ec5b82155f 100644
--- a/src/gpu/gl/GrGLCaps.cpp
+++ b/src/gpu/gl/GrGLCaps.cpp
@@ -289,7 +289,15 @@ void GrGLCaps::init(const GrGLContextInfo& ctxInfo, const GrGLInterface* gli) {
fDstReadInShaderSupport = kNone_FBFetchType != fFBFetchType;
+#if 0
+ // This has to be temporarily disabled. On Android it causes the texture
+ // usage to become front loaded and the OS kills the process. It can
+ // be re-enabled once the more dynamic (ref-driven) cache clearing
+ // system is in place.
fReuseScratchTextures = kARM_GrGLVendor != ctxInfo.vendor();
+#else
+ fReuseScratchTextures = true;
+#endif
// Enable supported shader-related caps
if (kDesktop_GrGLBinding == binding) {