diff options
author | robertphillips@google.com <robertphillips@google.com@2bbb7eff-a529-9590-31e7-b0007b416f81> | 2012-05-28 13:37:25 +0000 |
---|---|---|
committer | robertphillips@google.com <robertphillips@google.com@2bbb7eff-a529-9590-31e7-b0007b416f81> | 2012-05-28 13:37:25 +0000 |
commit | ab303ef6e86089ae28f30a52149f1dae177e1468 (patch) | |
tree | bd2c0c733461afa351e704124a22d9f88feaa56c /src | |
parent | 2e0a061c091ae1f840267f8cb2e37c7817c8911f (diff) |
Speculative fix for Android Debug only crash in r4049
http://codereview.appspot.com/6251049/
git-svn-id: http://skia.googlecode.com/svn/trunk@4053 2bbb7eff-a529-9590-31e7-b0007b416f81
Diffstat (limited to 'src')
-rw-r--r-- | src/gpu/GrContext.cpp | 6 | ||||
-rw-r--r-- | src/gpu/GrDrawState.h | 139 | ||||
-rw-r--r-- | src/gpu/GrInOrderDrawBuffer.cpp | 19 | ||||
-rw-r--r-- | src/gpu/SkGpuDevice.cpp | 4 |
4 files changed, 91 insertions, 77 deletions
diff --git a/src/gpu/GrContext.cpp b/src/gpu/GrContext.cpp index 80dd25ebee..e0307f5e19 100644 --- a/src/gpu/GrContext.cpp +++ b/src/gpu/GrContext.cpp @@ -69,6 +69,12 @@ GrContext* GrContext::Create(GrEngine engine, GrContext::~GrContext() { this->flush(); + // the context's drawstate can be holding onto texture/render target refs. + // Relinquish them before the texture cache is freed lest a cached + // texture/RT not be freed in the right order + fDrawState->reset(); + // The gpu refs textures in its drawstate. + fGpu->setDrawState(NULL); // Since the gpu can hold scratch textures, give it a chance to let go // of them before freeing the texture cache fGpu->purgeResources(); diff --git a/src/gpu/GrDrawState.h b/src/gpu/GrDrawState.h index 79d6d483f1..a568ca776b 100644 --- a/src/gpu/GrDrawState.h +++ b/src/gpu/GrDrawState.h @@ -14,11 +14,10 @@ #include "GrRefCnt.h" #include "GrSamplerState.h" #include "GrStencil.h" +#include "GrRenderTarget.h" #include "SkXfermode.h" -class GrRenderTarget; -class GrTexture; class GrDrawState : public GrRefCnt { @@ -53,18 +52,52 @@ public: typedef uint32_t StageMask; GR_STATIC_ASSERT(sizeof(StageMask)*8 >= GrDrawState::kNumStages); - GrDrawState() { + GrDrawState() + : fRenderTarget(NULL) { + + for (int i = 0; i < kNumStages; ++i) { + fTextures[i] = NULL; + } + this->reset(); } - GrDrawState(const GrDrawState& state) { + GrDrawState(const GrDrawState& state) + : fRenderTarget(NULL) { + + for (int i = 0; i < kNumStages; ++i) { + fTextures[i] = NULL; + } + *this = state; } + virtual ~GrDrawState() { + for (int i = 0; i < kNumStages; ++i) { + GrSafeSetNull(fTextures[i]); + } + GrSafeSetNull(fRenderTarget); + } + /** * Resets to the default state. Sampler states will not be modified. */ void reset() { + + for (int i = 0; i < kNumStages; ++i) { + // just as in setTexture we have to detach the texture before + // unreffing it because, if a texture is actually freed here, + // GrGLTexture's onRelease method will try to remove it from all + // possible owner's (including this one) via setTexture(NULL) + GrTexture* temp = fTextures[i]; + fTextures[i] = NULL; + GrSafeUnref(temp); + } + + GrRenderTarget* temp = fRenderTarget; + fRenderTarget = NULL; + GrSafeUnref(temp); + // make sure any pad is zero for memcmp // all GrDrawState members should default to something valid by the // the memset except those initialized individually below. There should @@ -85,14 +118,13 @@ public: fSrcBlend = kOne_BlendCoeff; fDstBlend = kZero_BlendCoeff; fViewMatrix.reset(); - fBehaviorBits = 0; // ensure values that will be memcmp'ed in == but not memset in reset() // are tightly packed GrAssert(this->memsetSize() + sizeof(fColor) + sizeof(fCoverage) + sizeof(fFirstCoverageStage) + sizeof(fColorFilterMode) + - sizeof(fSrcBlend) + sizeof(fDstBlend) == - this->podSize()); + sizeof(fSrcBlend) + sizeof(fDstBlend) + sizeof(fTextures) + + sizeof(fRenderTarget) == this->podSize()); } /////////////////////////////////////////////////////////////////////////// @@ -174,16 +206,14 @@ public: void setTexture(int stage, GrTexture* texture) { GrAssert((unsigned)stage < kNumStages); - if (isBehaviorEnabled(kTexturesNeedRef_BehaviorBit)) { - // If we don't clear out the current texture before unreffing - // it we can get into an infinite loop as the GrGLTexture's - // onRelease method recursively calls setTexture - GrTexture* temp = fTextures[stage]; - fTextures[stage] = NULL; + // If we don't clear out the current texture before unreffing + // it we can get into an infinite loop as the GrGLTexture's + // onRelease method recursively calls setTexture + GrTexture* temp = fTextures[stage]; + fTextures[stage] = NULL; - SkSafeRef(texture); - SkSafeUnref(temp); - } + SkSafeRef(texture); + SkSafeUnref(temp); fTextures[stage] = texture; } @@ -461,7 +491,18 @@ public: * * @param target The render target to set. */ - void setRenderTarget(GrRenderTarget* target) { fRenderTarget = target; } + void setRenderTarget(GrRenderTarget* target) { + + // If we don't clear out the current render target before unreffing + // it we can get into an infinite loop as the GrGLRenderTarget's + // onRelease method recursively calls setTexture + GrRenderTarget* temp = fRenderTarget; + fRenderTarget = NULL; + + SkSafeRef(target); + SkSafeUnref(temp); + fRenderTarget = target; + } /** * Retrieves the currently set rendertarget. @@ -479,16 +520,26 @@ public: fSavedTarget = NULL; this->set(ds, newTarget); } - ~AutoRenderTargetRestore() { this->set(NULL, NULL); } - void set(GrDrawState* ds, GrRenderTarget* newTarget) { + ~AutoRenderTargetRestore() { this->restore(); } + + void restore() { if (NULL != fDrawState) { fDrawState->setRenderTarget(fSavedTarget); + fDrawState = NULL; } + GrSafeSetNull(fSavedTarget); + } + + void set(GrDrawState* ds, GrRenderTarget* newTarget) { + this->restore(); + if (NULL != ds) { + GrAssert(NULL == fSavedTarget); fSavedTarget = ds->getRenderTarget(); + SkSafeRef(fSavedTarget); ds->setRenderTarget(newTarget); + fDrawState = ds; } - fDrawState = ds; } private: GrDrawState* fDrawState; @@ -681,28 +732,6 @@ public: fFlagBits = ds.fFlagBits; } - /** - * Flags that do not affect rendering. - */ - enum GrBehaviorBits { - /** - * Calls to setTexture will ref/unref the texture - */ - kTexturesNeedRef_BehaviorBit = 0x01, - }; - - void enableBehavior(uint32_t behaviorBits) { - fBehaviorBits |= behaviorBits; - } - - void disableBehavior(uint32_t behaviorBits) { - fBehaviorBits &= ~(behaviorBits); - } - - bool isBehaviorEnabled(uint32_t behaviorBits) const { - return 0 != (behaviorBits & fBehaviorBits); - } - /// @} /////////////////////////////////////////////////////////////////////////// @@ -748,14 +777,6 @@ public: return false; } - // kTexturesNeedRef is an internal flag for altering the draw state's - // behavior rather than a property that will impact drawing - ignore it - // here - if ((fBehaviorBits & ~kTexturesNeedRef_BehaviorBit) != - (s.fBehaviorBits & ~kTexturesNeedRef_BehaviorBit)) { - return false; - } - for (int i = 0; i < kNumStages; i++) { if (fTextures[i] && this->fSamplerStates[i] != s.fSamplerStates[i]) { @@ -780,13 +801,16 @@ public: memcpy(this->podStart(), s.podStart(), this->podSize()); fViewMatrix = s.fViewMatrix; - fBehaviorBits = s.fBehaviorBits; for (int i = 0; i < kNumStages; i++) { + SkSafeRef(fTextures[i]); // already copied by memcpy if (s.fTextures[i]) { this->fSamplerStates[i] = s.fSamplerStates[i]; } } + + SkSafeRef(fRenderTarget); // already copied by memcpy + if (kColorMatrix_StateBit & s.fFlagBits) { memcpy(this->fColorMatrix, s.fColorMatrix, sizeof(fColorMatrix)); } @@ -820,15 +844,13 @@ private: GrColor fBlendConstant; GrColor fPodStartMarker; }; - GrTexture* fTextures[kNumStages]; GrColor fColorFilterColor; uint32_t fFlagBits; DrawFace fDrawFace; - VertexEdgeType fVertexEdgeType; GrStencilSettings fStencilSettings; union { - GrRenderTarget* fRenderTarget; - GrRenderTarget* fMemsetEndMarker; + VertexEdgeType fVertexEdgeType; + VertexEdgeType fMemsetEndMarker; }; // @} @@ -839,13 +861,14 @@ private: int fFirstCoverageStage; SkXfermode::Mode fColorFilterMode; GrBlendCoeff fSrcBlend; + GrBlendCoeff fDstBlend; + GrTexture* fTextures[kNumStages]; union { - GrBlendCoeff fDstBlend; - GrBlendCoeff fPodEndMarker; + GrRenderTarget* fRenderTarget; + GrRenderTarget* fPodEndMarker; }; // @} - uint32_t fBehaviorBits; GrMatrix fViewMatrix; // This field must be last; it will not be copied or compared diff --git a/src/gpu/GrInOrderDrawBuffer.cpp b/src/gpu/GrInOrderDrawBuffer.cpp index 7b3b04f75b..c608013678 100644 --- a/src/gpu/GrInOrderDrawBuffer.cpp +++ b/src/gpu/GrInOrderDrawBuffer.cpp @@ -460,17 +460,7 @@ void GrInOrderDrawBuffer::reset() { GrAssert(1 == fGeoPoolStateStack.count()); this->resetVertexSource(); this->resetIndexSource(); - uint32_t numStates = fStates.count(); - for (uint32_t i = 0; i < numStates; ++i) { - for (int s = 0; s < GrDrawState::kNumStages; ++s) { - GrSafeUnref(fStates[i].getTexture(s)); - } - GrSafeUnref(fStates[i].getRenderTarget()); - // GrInOrderDrawBuffer is no longer managing the refs/unrefs - // for the stored GrDrawStates - fStates[i].disableBehavior(GrDrawState::kTexturesNeedRef_BehaviorBit); - } int numDraws = fDraws.count(); for (int d = 0; d < numDraws; ++d) { // we always have a VB, but not always an IB @@ -780,16 +770,7 @@ bool GrInOrderDrawBuffer::needsNewState() const { } void GrInOrderDrawBuffer::pushState() { - const GrDrawState& drawState = this->getDrawState(); - for (int s = 0; s < GrDrawState::kNumStages; ++s) { - GrSafeRef(drawState.getTexture(s)); - } - GrSafeRef(drawState.getRenderTarget()); fStates.push_back(this->getDrawState()); - - // Any textures that are added to the stored state need to be - // reffed so the unref in reset doesn't inappropriately free them - fStates.back().enableBehavior(GrDrawState::kTexturesNeedRef_BehaviorBit); } bool GrInOrderDrawBuffer::needsNewClip() const { diff --git a/src/gpu/SkGpuDevice.cpp b/src/gpu/SkGpuDevice.cpp index 411b2c5b8f..d6dc010e81 100644 --- a/src/gpu/SkGpuDevice.cpp +++ b/src/gpu/SkGpuDevice.cpp @@ -258,6 +258,10 @@ SkGpuDevice::~SkGpuDevice() { delete fDrawProcs; } + // The SkGpuDevice gives the context the render target (e.g., in gainFocus) + // This call gives the context a chance to relinquish it + fContext->setRenderTarget(NULL); + SkSafeUnref(fTexture); SkSafeUnref(fRenderTarget); if (fCache.texture()) { |