aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorGravatar robertphillips@google.com <robertphillips@google.com@2bbb7eff-a529-9590-31e7-b0007b416f81>2012-05-03 17:58:27 +0000
committerGravatar robertphillips@google.com <robertphillips@google.com@2bbb7eff-a529-9590-31e7-b0007b416f81>2012-05-03 17:58:27 +0000
commit1942c05e9c51b462355626155c1bdc3fc43161cf (patch)
treeb0a24c9ff844387fe546bb1c50b58164fcf5ead0
parent58b381841cb8d234d09c85af43720cbff00e6212 (diff)
Fixed texture ref/unref bug in GrInOrderDrawBuffer/GrDrawState
-rw-r--r--src/gpu/GrDrawState.h16
-rw-r--r--src/gpu/GrInOrderDrawBuffer.cpp8
-rw-r--r--src/gpu/gl/GrGpuGL.cpp4
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;
}