diff options
author | bsalomon <bsalomon@google.com> | 2014-08-19 08:21:25 -0700 |
---|---|---|
committer | Commit bot <commit-bot@chromium.org> | 2014-08-19 08:21:25 -0700 |
commit | 94ce9ac8624dbb45656b8f5c992fad9c9ff3ee5f (patch) | |
tree | b72401c17facf9399d4e8f05f69523a1d7ed0658 /src | |
parent | 38dd9f2e41748953f46e5daaf341971a851b247d (diff) |
Add GrResourceCache2.
Currently it just replaces GrGpu as the owner of the linked list of resources.
R=robertphillips@google.com, mtklein@google.com
Author: bsalomon@google.com
Review URL: https://codereview.chromium.org/481443002
Diffstat (limited to 'src')
-rw-r--r-- | src/gpu/GrClipMaskCache.h | 8 | ||||
-rw-r--r-- | src/gpu/GrClipMaskManager.cpp | 4 | ||||
-rw-r--r-- | src/gpu/GrClipMaskManager.h | 6 | ||||
-rwxr-xr-x | src/gpu/GrContext.cpp | 21 | ||||
-rw-r--r-- | src/gpu/GrGpu.cpp | 60 | ||||
-rw-r--r-- | src/gpu/GrGpu.h | 36 | ||||
-rw-r--r-- | src/gpu/GrGpuResource.cpp | 18 | ||||
-rw-r--r-- | src/gpu/GrLayerCache.cpp | 2 | ||||
-rw-r--r-- | src/gpu/GrResourceCache.cpp | 2 | ||||
-rw-r--r-- | src/gpu/GrResourceCache2.cpp | 47 | ||||
-rw-r--r-- | src/gpu/GrResourceCache2.h | 40 | ||||
-rw-r--r-- | src/gpu/gl/GrGLPathRendering.cpp | 1 | ||||
-rw-r--r-- | src/gpu/gl/GrGpuGL.cpp | 12 | ||||
-rw-r--r-- | src/gpu/gl/GrGpuGL.h | 4 | ||||
-rw-r--r-- | src/gpu/gl/GrGpuGL_program.cpp | 11 |
15 files changed, 151 insertions, 121 deletions
diff --git a/src/gpu/GrClipMaskCache.h b/src/gpu/GrClipMaskCache.h index b332c7be9b..6b484e8af8 100644 --- a/src/gpu/GrClipMaskCache.h +++ b/src/gpu/GrClipMaskCache.h @@ -41,6 +41,7 @@ public: // We could reuse the mask if bounds is a subset of last bounds. We'd have to communicate // an offset to the caller. if (back->fLastMask.texture() && + !back->fLastMask.texture()->wasDestroyed() && back->fLastBound == bounds && back->fLastClipGenID == clipGenID) { return true; @@ -179,8 +180,8 @@ public: return fContext; } - void releaseResources() { - + // TODO: Remove this when we hold cache keys instead of refs to textures. + void purgeResources() { SkDeque::F2BIter iter(fStack); for (GrClipStackFrame* frame = (GrClipStackFrame*) iter.next(); frame != NULL; @@ -219,7 +220,8 @@ private: int32_t fLastClipGenID; // The mask's width & height values are used by GrClipMaskManager to correctly scale the - // texture coords for the geometry drawn with this mask. + // texture coords for the geometry drawn with this mask. TODO: This should be a cache key + // and not a hard ref to a texture. GrAutoScratchTexture fLastMask; // fLastBound stores the bounding box of the clip mask in clip-stack space. This rect is // used by GrClipMaskManager to position a rect and compute texture coords for the mask. diff --git a/src/gpu/GrClipMaskManager.cpp b/src/gpu/GrClipMaskManager.cpp index 7cafdf7d56..d4ab0b74f9 100644 --- a/src/gpu/GrClipMaskManager.cpp +++ b/src/gpu/GrClipMaskManager.cpp @@ -1112,8 +1112,8 @@ GrTexture* GrClipMaskManager::createSoftwareClipMask(int32_t elementsGenID, } //////////////////////////////////////////////////////////////////////////////// -void GrClipMaskManager::releaseResources() { - fAACache.releaseResources(); +void GrClipMaskManager::purgeResources() { + fAACache.purgeResources(); } void GrClipMaskManager::setGpu(GrGpu* gpu) { diff --git a/src/gpu/GrClipMaskManager.h b/src/gpu/GrClipMaskManager.h index c3a21fd8a2..ea16fc842b 100644 --- a/src/gpu/GrClipMaskManager.h +++ b/src/gpu/GrClipMaskManager.h @@ -53,7 +53,11 @@ public: bool setupClipping(const GrClipData* clipDataIn, GrDrawState::AutoRestoreEffects*, const SkRect* devBounds); - void releaseResources(); + /** + * Purge resources to free up memory. TODO: This class shouldn't hold any long lived refs + * which will allow ResourceCache2 to automatically purge anything this class has created. + */ + void purgeResources(); bool isClipInStencil() const { return kStencil_ClipMaskType == fCurrClipMaskType; diff --git a/src/gpu/GrContext.cpp b/src/gpu/GrContext.cpp index 091c4a899e..df26be6a46 100755 --- a/src/gpu/GrContext.cpp +++ b/src/gpu/GrContext.cpp @@ -25,6 +25,7 @@ #include "GrPathRenderer.h" #include "GrPathUtils.h" #include "GrResourceCache.h" +#include "GrResourceCache2.h" #include "GrSoftwarePathRenderer.h" #include "GrStencilBuffer.h" #include "GrStencilAndCoverTextContext.h" @@ -108,6 +109,7 @@ GrContext::GrContext(const Options& opts) : fOptions(opts) { fPathRendererChain = NULL; fSoftwarePathRenderer = NULL; fResourceCache = NULL; + fResourceCache2 = NULL; fFontCache = NULL; fDrawBuffer = NULL; fDrawBufferVBAllocPool = NULL; @@ -133,6 +135,7 @@ bool GrContext::init(GrBackend backend, GrBackendContext backendContext) { fResourceCache = SkNEW_ARGS(GrResourceCache, (MAX_RESOURCE_CACHE_COUNT, MAX_RESOURCE_CACHE_BYTES)); fResourceCache->setOverbudgetCallback(OverbudgetCB, this); + fResourceCache2 = SkNEW(GrResourceCache2); fFontCache = SkNEW_ARGS(GrFontCache, (fGpu)); @@ -161,10 +164,8 @@ GrContext::~GrContext() { (*fCleanUpData[i].fFunc)(this, fCleanUpData[i].fInfo); } - // Since the gpu can hold scratch textures, give it a chance to let go - // of them before freeing the texture cache - fGpu->purgeResources(); - + delete fResourceCache2; + fResourceCache2 = NULL; delete fResourceCache; fResourceCache = NULL; delete fFontCache; @@ -184,7 +185,9 @@ GrContext::~GrContext() { void GrContext::abandonContext() { // abandon first to so destructors // don't try to free the resources in the API. - fGpu->abandonResources(); + fResourceCache2->abandonAll(); + + fGpu->contextAbandonded(); // a path renderer may be holding onto resources that // are now unusable @@ -207,7 +210,6 @@ void GrContext::abandonContext() { fFontCache->freeAll(); fLayerCache->freeAll(); - fGpu->markContextDirty(); } void GrContext::resetContext(uint32_t state) { @@ -218,6 +220,9 @@ void GrContext::freeGpuResources() { this->flush(); fGpu->purgeResources(); + if (NULL != fDrawBuffer) { + fDrawBuffer->purgeResources(); + } fAARectRenderer->reset(); fOvalRenderer->reset(); @@ -540,6 +545,10 @@ void GrContext::addExistingTextureToCache(GrTexture* texture) { } void GrContext::unlockScratchTexture(GrTexture* texture) { + if (texture->wasDestroyed()) { + return; + } + ASSERT_OWNED_RESOURCE(texture); SkASSERT(NULL != texture->getCacheEntry()); diff --git a/src/gpu/GrGpu.cpp b/src/gpu/GrGpu.cpp index 0b49e7445a..bdf67727c3 100644 --- a/src/gpu/GrGpu.cpp +++ b/src/gpu/GrGpu.cpp @@ -49,62 +49,9 @@ GrGpu::GrGpu(GrContext* context) #endif } -GrGpu::~GrGpu() { - this->releaseResources(); -} - -void GrGpu::abandonResources() { - - fClipMaskManager.releaseResources(); - - while (NULL != fObjectList.head()) { - fObjectList.head()->abandon(); - } - - SkASSERT(NULL == fQuadIndexBuffer || fQuadIndexBuffer->wasDestroyed()); - SkSafeSetNull(fQuadIndexBuffer); - delete fVertexPool; - fVertexPool = NULL; - delete fIndexPool; - fIndexPool = NULL; -} - -void GrGpu::releaseResources() { - - fClipMaskManager.releaseResources(); +GrGpu::~GrGpu() {} - while (NULL != fObjectList.head()) { - fObjectList.head()->release(); - } - - SkASSERT(NULL == fQuadIndexBuffer || fQuadIndexBuffer->wasDestroyed()); - SkSafeSetNull(fQuadIndexBuffer); - delete fVertexPool; - fVertexPool = NULL; - delete fIndexPool; - fIndexPool = NULL; -} - -void GrGpu::insertObject(GrGpuResource* object) { - SkASSERT(NULL != object); - SkASSERT(this == object->getGpu()); - - fObjectList.addToHead(object); -} - -void GrGpu::removeObject(GrGpuResource* object) { - SkASSERT(NULL != object); - SkASSERT(this == object->getGpu()); - - fObjectList.remove(object); -} - - -void GrGpu::unimpl(const char msg[]) { -#ifdef SK_DEBUG - GrPrintf("--- GrGpu unimplemented(\"%s\")\n", msg); -#endif -} +void GrGpu::contextAbandonded() {} //////////////////////////////////////////////////////////////////////////////// @@ -319,7 +266,8 @@ static inline void fill_indices(uint16_t* indices, int quadCount) { } const GrIndexBuffer* GrGpu::getQuadIndexBuffer() const { - if (NULL == fQuadIndexBuffer) { + if (NULL == fQuadIndexBuffer || fQuadIndexBuffer->wasDestroyed()) { + SkSafeUnref(fQuadIndexBuffer); static const int SIZE = sizeof(uint16_t) * 6 * MAX_QUADS; GrGpu* me = const_cast<GrGpu*>(this); fQuadIndexBuffer = me->createIndexBuffer(SIZE, false); diff --git a/src/gpu/GrGpu.h b/src/gpu/GrGpu.h index b752f7c09c..360e889a1d 100644 --- a/src/gpu/GrGpu.h +++ b/src/gpu/GrGpu.h @@ -54,6 +54,12 @@ public: GrContext* getContext() { return this->INHERITED::getContext(); } const GrContext* getContext() const { return this->INHERITED::getContext(); } + // Called by GrContext when the underlying backend context has been destroyed. + // GrGpu should use this to ensure that no backend API calls will be made from + // here onward, including in its destructor. Subclasses should call + // INHERITED::contextAbandonded() if they override this. + virtual void contextAbandonded(); + /** * The GrGpu object normally assumes that no outsider is setting state * within the underlying 3D API's context/device/whatever. This call informs @@ -248,30 +254,6 @@ public: GrPixelConfig config, const void* buffer, size_t rowBytes); - /** - * Called to tell GrGpu that all GrGpuResources have been lost and should - * be abandoned. Overrides must call INHERITED::abandonResources(). - */ - virtual void abandonResources(); - - /** - * Called to tell GrGpu to release all GrGpuResources. Overrides must call - * INHERITED::releaseResources(). - */ - void releaseResources(); - - /** - * Add object to list of objects. Should only be called by GrGpuResource. - * @param resource the resource to add. - */ - void insertObject(GrGpuResource* object); - - /** - * Remove object from list of objects. Should only be called by GrGpuResource. - * @param resource the resource to remove. - */ - void removeObject(GrGpuResource* object); - // GrDrawTarget overrides virtual void clear(const SkIRect* rect, GrColor color, @@ -281,7 +263,7 @@ public: virtual void purgeResources() SK_OVERRIDE { // The clip mask manager can rebuild all its clip masks so just // get rid of them all. - fClipMaskManager.releaseResources(); + fClipMaskManager.purgeResources(); } // After the client interacts directly with the 3D context state the GrGpu @@ -526,7 +508,6 @@ private: enum { kPreallocGeomPoolStateStackCnt = 4, }; - typedef SkTInternalLList<GrGpuResource> ObjectList; SkSTArray<kPreallocGeomPoolStateStackCnt, GeometryPoolState, true> fGeomPoolStateStack; ResetTimestamp fResetTimestamp; uint32_t fResetBits; @@ -537,9 +518,6 @@ private: int fIndexPoolUseCnt; // these are mutable so they can be created on-demand mutable GrIndexBuffer* fQuadIndexBuffer; - // Used to abandon/release all resources created by this GrGpu. TODO: Move this - // functionality to GrResourceCache. - ObjectList fObjectList; typedef GrDrawTarget INHERITED; }; diff --git a/src/gpu/GrGpuResource.cpp b/src/gpu/GrGpuResource.cpp index 8c2dc45080..7a19c25e46 100644 --- a/src/gpu/GrGpuResource.cpp +++ b/src/gpu/GrGpuResource.cpp @@ -8,19 +8,27 @@ #include "GrGpuResource.h" +#include "GrResourceCache2.h" #include "GrGpu.h" +static inline GrResourceCache2* get_resource_cache2(GrGpu* gpu) { + SkASSERT(NULL != gpu); + SkASSERT(NULL != gpu->getContext()); + SkASSERT(NULL != gpu->getContext()->getResourceCache2()); + return gpu->getContext()->getResourceCache2(); +} + GrGpuResource::GrGpuResource(GrGpu* gpu, bool isWrapped) - : fRefCnt(1) + : fGpu(gpu) + , fRefCnt(1) , fCacheEntry(NULL) , fUniqueID(CreateUniqueID()) { - fGpu = gpu; if (isWrapped) { fFlags = kWrapped_FlagBit; } else { fFlags = 0; } - fGpu->insertObject(this); + get_resource_cache2(fGpu)->insertResource(this); } GrGpuResource::~GrGpuResource() { @@ -32,7 +40,7 @@ GrGpuResource::~GrGpuResource() { void GrGpuResource::release() { if (NULL != fGpu) { this->onRelease(); - fGpu->removeObject(this); + get_resource_cache2(fGpu)->removeResource(this); fGpu = NULL; } } @@ -40,7 +48,7 @@ void GrGpuResource::release() { void GrGpuResource::abandon() { if (NULL != fGpu) { this->onAbandon(); - fGpu->removeObject(this); + get_resource_cache2(fGpu)->removeResource(this); fGpu = NULL; } } diff --git a/src/gpu/GrLayerCache.cpp b/src/gpu/GrLayerCache.cpp index c0510c0365..9325497997 100644 --- a/src/gpu/GrLayerCache.cpp +++ b/src/gpu/GrLayerCache.cpp @@ -112,7 +112,7 @@ void GrLayerCache::freeAll() { fAtlas.free(); // GrLayerCache always assumes an atlas exists so recreate it. The atlas // lazily allocates a replacement texture so reallocating a new - // atlas here won't disrupt a GrContext::contextDestroyed or freeGpuResources. + // atlas here won't disrupt a GrContext::abandonContext or freeGpuResources. // TODO: Make GrLayerCache lazily allocate the atlas manager? this->initAtlas(); } diff --git a/src/gpu/GrResourceCache.cpp b/src/gpu/GrResourceCache.cpp index e3a17f05c5..8a21002e1c 100644 --- a/src/gpu/GrResourceCache.cpp +++ b/src/gpu/GrResourceCache.cpp @@ -267,7 +267,7 @@ void GrResourceCache::makeExclusive(GrResourceCacheEntry* entry) { 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::contextDestroyed() to notify Gr, + // 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. diff --git a/src/gpu/GrResourceCache2.cpp b/src/gpu/GrResourceCache2.cpp new file mode 100644 index 0000000000..0b6944ee85 --- /dev/null +++ b/src/gpu/GrResourceCache2.cpp @@ -0,0 +1,47 @@ + +/* + * Copyright 2014 Google Inc. + * + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + + +#include "GrResourceCache2.h" +#include "GrGpuResource.h" + +GrResourceCache2::~GrResourceCache2() { + this->releaseAll(); +} + +void GrResourceCache2::insertResource(GrGpuResource* resource) { + SkASSERT(NULL != resource); + SkASSERT(!resource->wasDestroyed()); + fResources.addToHead(resource); + ++fCount; +} + +void GrResourceCache2::removeResource(GrGpuResource* resource) { + fResources.remove(resource); + --fCount; +} + +void GrResourceCache2::abandonAll() { + while (GrGpuResource* head = fResources.head()) { + SkASSERT(!head->wasDestroyed()); + head->abandon(); + // abandon should have already removed this from the list. + SkASSERT(head != fResources.head()); + } + SkASSERT(!fCount); +} + +void GrResourceCache2::releaseAll() { + while (GrGpuResource* head = fResources.head()) { + SkASSERT(!head->wasDestroyed()); + head->release(); + // release should have already removed this from the list. + SkASSERT(head != fResources.head()); + } + SkASSERT(!fCount); +} diff --git a/src/gpu/GrResourceCache2.h b/src/gpu/GrResourceCache2.h new file mode 100644 index 0000000000..1262c805ac --- /dev/null +++ b/src/gpu/GrResourceCache2.h @@ -0,0 +1,40 @@ + +/* + * Copyright 2014 Google Inc. + * + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#ifndef GrResourceCache2_DEFINED +#define GrResourceCache2_DEFINED + +#include "GrTypes.h" +#include "SkTInternalLList.h" + +class GrGpuResource; + +/** + * Eventual replacement for GrResourceCache. Currently it simply holds a list + * of all GrGpuResource objects for a GrContext. It is used to invalidate all + * the resources when necessary. + */ +class GrResourceCache2 { +public: + GrResourceCache2() : fCount(0) {}; + ~GrResourceCache2(); + + void insertResource(GrGpuResource* resource); + + void removeResource(GrGpuResource* resource); + + void abandonAll(); + + void releaseAll(); + +private: + int fCount; + SkTInternalLList<GrGpuResource> fResources; +}; + +#endif diff --git a/src/gpu/gl/GrGLPathRendering.cpp b/src/gpu/gl/GrGLPathRendering.cpp index 249d98139a..6204deb094 100644 --- a/src/gpu/gl/GrGLPathRendering.cpp +++ b/src/gpu/gl/GrGLPathRendering.cpp @@ -73,7 +73,6 @@ void GrGLPathRendering::abandonGpuResources() { fPathNameAllocator.reset(NULL); } - // NV_path_rendering GrGLuint GrGLPathRendering::genPaths(GrGLsizei range) { if (range > 1) { diff --git a/src/gpu/gl/GrGpuGL.cpp b/src/gpu/gl/GrGpuGL.cpp index 7131cfa1eb..b975fd1871 100644 --- a/src/gpu/gl/GrGpuGL.cpp +++ b/src/gpu/gl/GrGpuGL.cpp @@ -182,9 +182,15 @@ GrGpuGL::~GrGpuGL() { // This must be called by before the GrDrawTarget destructor this->releaseGeometry(); - // This subclass must do this before the base class destructor runs - // since we will unref the GrGLInterface. - this->releaseResources(); +} + +void GrGpuGL::contextAbandonded() { + INHERITED::contextAbandonded(); + fProgramCache->abandon(); + fHWProgramID = 0; + if (this->glCaps().pathRenderingSupport()) { + fPathRendering->abandonGpuResources(); + } } /////////////////////////////////////////////////////////////////////////////// diff --git a/src/gpu/gl/GrGpuGL.h b/src/gpu/gl/GrGpuGL.h index b39aedb824..92702193c5 100644 --- a/src/gpu/gl/GrGpuGL.h +++ b/src/gpu/gl/GrGpuGL.h @@ -31,6 +31,8 @@ public: GrGpuGL(const GrGLContext& ctx, GrContext* context); virtual ~GrGpuGL(); + virtual void contextAbandonded() SK_OVERRIDE; + const GrGLContext& glContext() const { return fGLContext; } const GrGLInterface* glInterface() const { return fGLContext.interface(); } @@ -83,8 +85,6 @@ public: virtual void initCopySurfaceDstDesc(const GrSurface* src, GrTextureDesc* desc) SK_OVERRIDE; - virtual void abandonResources() SK_OVERRIDE; - // These functions should be used to bind GL objects. They track the GL state and skip redundant // bindings. Making the equivalent glBind calls directly will confuse the state tracking. void bindVertexArray(GrGLuint id) { diff --git a/src/gpu/gl/GrGpuGL_program.cpp b/src/gpu/gl/GrGpuGL_program.cpp index beaaa903b2..b4fd464662 100644 --- a/src/gpu/gl/GrGpuGL_program.cpp +++ b/src/gpu/gl/GrGpuGL_program.cpp @@ -199,17 +199,6 @@ GrGLProgram* GrGpuGL::ProgramCache::getProgram(const GrGLProgramDesc& desc, //////////////////////////////////////////////////////////////////////////////// -void GrGpuGL::abandonResources(){ - INHERITED::abandonResources(); - fProgramCache->abandon(); - fHWProgramID = 0; - if (this->glCaps().pathRenderingSupport()) { - fPathRendering->abandonGpuResources(); - } -} - -//////////////////////////////////////////////////////////////////////////////// - #define GL_CALL(X) GR_GL_CALL(this->glInterface(), X) bool GrGpuGL::flushGraphicsState(DrawType type, const GrDeviceCoordTexture* dstCopy) { |