aboutsummaryrefslogtreecommitdiffhomepage
path: root/src
diff options
context:
space:
mode:
authorGravatar bsalomon <bsalomon@google.com>2014-08-19 08:21:25 -0700
committerGravatar Commit bot <commit-bot@chromium.org>2014-08-19 08:21:25 -0700
commit94ce9ac8624dbb45656b8f5c992fad9c9ff3ee5f (patch)
treeb72401c17facf9399d4e8f05f69523a1d7ed0658 /src
parent38dd9f2e41748953f46e5daaf341971a851b247d (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.h8
-rw-r--r--src/gpu/GrClipMaskManager.cpp4
-rw-r--r--src/gpu/GrClipMaskManager.h6
-rwxr-xr-xsrc/gpu/GrContext.cpp21
-rw-r--r--src/gpu/GrGpu.cpp60
-rw-r--r--src/gpu/GrGpu.h36
-rw-r--r--src/gpu/GrGpuResource.cpp18
-rw-r--r--src/gpu/GrLayerCache.cpp2
-rw-r--r--src/gpu/GrResourceCache.cpp2
-rw-r--r--src/gpu/GrResourceCache2.cpp47
-rw-r--r--src/gpu/GrResourceCache2.h40
-rw-r--r--src/gpu/gl/GrGLPathRendering.cpp1
-rw-r--r--src/gpu/gl/GrGpuGL.cpp12
-rw-r--r--src/gpu/gl/GrGpuGL.h4
-rw-r--r--src/gpu/gl/GrGpuGL_program.cpp11
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) {