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
diff --git a/src/gpu/GrDrawState.h b/src/gpu/GrDrawState.h
index 79d6d48..a568ca7 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 @@
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 @@
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 @@
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 @@
*
* @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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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