diff options
author | 2012-05-03 17:58:27 +0000 | |
---|---|---|
committer | 2012-05-03 17:58:27 +0000 | |
commit | 1942c05e9c51b462355626155c1bdc3fc43161cf (patch) | |
tree | b0a24c9ff844387fe546bb1c50b58164fcf5ead0 | |
parent | 58b381841cb8d234d09c85af43720cbff00e6212 (diff) |
Fixed texture ref/unref bug in GrInOrderDrawBuffer/GrDrawState
http://codereview.appspot.com/6186043/
git-svn-id: http://skia.googlecode.com/svn/trunk@3832 2bbb7eff-a529-9590-31e7-b0007b416f81
-rw-r--r-- | src/gpu/GrDrawState.h | 16 | ||||
-rw-r--r-- | src/gpu/GrInOrderDrawBuffer.cpp | 8 | ||||
-rw-r--r-- | src/gpu/gl/GrGpuGL.cpp | 4 |
3 files changed, 27 insertions, 1 deletions
diff --git a/src/gpu/GrDrawState.h b/src/gpu/GrDrawState.h index fee22bfaf4..63134088af 100644 --- a/src/gpu/GrDrawState.h +++ b/src/gpu/GrDrawState.h @@ -169,6 +169,18 @@ public: */ void setTexture(int stage, GrTexture* texture) { GrAssert((unsigned)stage < kNumStages); + + if (isStateFlagEnabled(kTexturesNeedRef_StateBit)) { + // 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); + } + fTextures[stage] = texture; } @@ -657,6 +669,10 @@ public: * ignored. */ kColorMatrix_StateBit = 0x20, + /** + * Calls to setTexture will ref/unref the texture + */ + kTexturesNeedRef_StateBit = 0x40, // Users of the class may add additional bits to the vector kDummyStateBit, diff --git a/src/gpu/GrInOrderDrawBuffer.cpp b/src/gpu/GrInOrderDrawBuffer.cpp index e6b3ca8c43..de49e8c8bf 100644 --- a/src/gpu/GrInOrderDrawBuffer.cpp +++ b/src/gpu/GrInOrderDrawBuffer.cpp @@ -466,6 +466,10 @@ void GrInOrderDrawBuffer::reset() { GrSafeUnref(fStates[i].getTexture(s)); } GrSafeUnref(fStates[i].getRenderTarget()); + + // GrInOrderDrawBuffer is no longer managing the refs/unrefs + // for the stored GrDrawStates + fStates[i].disableState(GrDrawState::kTexturesNeedRef_StateBit); } int numDraws = fDraws.count(); for (int d = 0; d < numDraws; ++d) { @@ -782,6 +786,10 @@ void GrInOrderDrawBuffer::pushState() { } 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().enableState(GrDrawState::kTexturesNeedRef_StateBit); } bool GrInOrderDrawBuffer::needsNewClip() const { diff --git a/src/gpu/gl/GrGpuGL.cpp b/src/gpu/gl/GrGpuGL.cpp index 3b5fffe7ef..a06b0084aa 100644 --- a/src/gpu/gl/GrGpuGL.cpp +++ b/src/gpu/gl/GrGpuGL.cpp @@ -2102,7 +2102,7 @@ bool GrGpuGL::flushGLStateCommon(GrPrimitiveType type) { // true for now, but maybe not with GrEffect. GrAssert(NULL != nextTexture); // if we created a rt/tex and rendered to it without using a - // texture and now we're texuring from the rt it will still be + // texture and now we're texturing from the rt it will still be // the last bound texture, but it needs resolving. So keep this // out of the "last != next" check. GrGLRenderTarget* texRT = @@ -2239,6 +2239,8 @@ bool GrGpuGL::flushGLStateCommon(GrPrimitiveType type) { // relies on detecting when the kModifyStencilClip_StateBit state has // changed since the last draw. fHWDrawState.copyStateFlags(*drawState); + // only GrInOrderDrawBuffer ever needs to ref/unref the textures + fHWDrawState.disableState(GrDrawState::kTexturesNeedRef_StateBit); return true; } |