diff options
author | robertphillips@google.com <robertphillips@google.com@2bbb7eff-a529-9590-31e7-b0007b416f81> | 2013-07-19 16:51:46 +0000 |
---|---|---|
committer | robertphillips@google.com <robertphillips@google.com@2bbb7eff-a529-9590-31e7-b0007b416f81> | 2013-07-19 16:51:46 +0000 |
commit | e4eaea2d126d58d8ce4034a1ce921404e83fe3f4 (patch) | |
tree | b198ea1e63b9244e288e42e8cc88c53da1a5193b /src | |
parent | 727b33faef255a455c067501f27460704e56e380 (diff) |
Alter resource cache and GrContext to (optionally) never reuse a scratch texture
https://codereview.chromium.org/19482004/
git-svn-id: http://skia.googlecode.com/svn/trunk@10193 2bbb7eff-a529-9590-31e7-b0007b416f81
Diffstat (limited to 'src')
-rw-r--r-- | src/gpu/GrContext.cpp | 59 | ||||
-rw-r--r-- | src/gpu/GrResourceCache.cpp | 27 | ||||
-rw-r--r-- | src/gpu/GrResourceCache.h | 43 | ||||
-rw-r--r-- | src/gpu/gl/GrGLCaps.cpp | 8 |
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) { |