зеркало из https://github.com/mozilla/moz-skia.git
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
This commit is contained in:
Родитель
2e0a061c09
Коммит
ab303ef6e8
|
@ -857,8 +857,13 @@ public:
|
|||
}
|
||||
|
||||
~GrAutoScratchTexture() {
|
||||
this->reset();
|
||||
}
|
||||
|
||||
void reset() {
|
||||
if (NULL != fContext) {
|
||||
fContext->unlockTexture(fEntry);
|
||||
fEntry.reset();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -866,10 +871,8 @@ public:
|
|||
const GrTextureDesc& desc,
|
||||
GrContext::ScratchTexMatch match =
|
||||
GrContext::kApprox_ScratchTexMatch) {
|
||||
if (NULL != fContext) {
|
||||
fContext->unlockTexture(fEntry);
|
||||
fEntry.reset();
|
||||
}
|
||||
this->reset();
|
||||
|
||||
fContext = context;
|
||||
if (NULL != fContext) {
|
||||
fEntry = fContext->lockScratchTexture(desc, match);
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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()) {
|
||||
|
|
Загрузка…
Ссылка в новой задаче