Remove on static initializer in GrGpu.cpp
This is another go for the patch that was initially submitted at http://codereview.appspot.com/5504073/ but crashed the 'gm' unit test. A problem with the previous implementation is that the GrStencilSettings ::isDisabled() and ::doesWrite() methods can modify the object's fFlags member if it is 0, and this will crash at runtime when doing this for a static constant object/structure. I'm not sure why this wasn't triggered previously. We solve the issue by modifying the implementation of GR_STATIC_CONST_STENCIL and GR_STATIC_CONST_STENCIL macros to compute the correct default values for fFlags (which prevents any member modifications in the above methods). This requires moving the definition of the disabled/write flags out of the GrStencilSettings class definition's private section. Note that the flags are renamed to avoid any confusion and conflicts, i.e.: SkIsDisabled_Flag -> SkIsDisabled_StencilFlag SkNotDisabled_Flag -> SkNotDisabled_StencilFlag ... Review URL: https://codereview.appspot.com/5616051 git-svn-id: http://skia.googlecode.com/svn/trunk@3214 2bbb7eff-a529-9590-31e7-b0007b416f81
This commit is contained in:
parent
128cd221b1
commit
9b482c4d33
@ -343,15 +343,17 @@ const GrVertexBuffer* GrGpu::getUnitSquareVertexBuffer() const {
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
const GrStencilSettings* GrGpu::GetClipStencilSettings(void) {
|
||||
// stencil settings to use when clip is in stencil
|
||||
GR_STATIC_CONST_SAME_STENCIL(gClipStencilSettings,
|
||||
GR_STATIC_CONST_SAME_STENCIL_STRUCT(sClipStencilSettings,
|
||||
kKeep_StencilOp,
|
||||
kKeep_StencilOp,
|
||||
kAlwaysIfInClip_StencilFunc,
|
||||
0x0000,
|
||||
0x0000,
|
||||
0x0000);
|
||||
const GrStencilSettings& GrGpu::gClipStencilSettings = ::gClipStencilSettings;
|
||||
return GR_CONST_STENCIL_SETTINGS_PTR_FROM_STRUCT_PTR(&sClipStencilSettings);
|
||||
}
|
||||
|
||||
// mapping of clip-respecting stencil funcs to normal stencil funcs
|
||||
// mapping depends on whether stencil-clipping is in effect.
|
||||
|
@ -355,7 +355,7 @@ protected:
|
||||
|
||||
// stencil settings to clip drawing when stencil clipping is in effect
|
||||
// and the client isn't using the stencil test.
|
||||
static const GrStencilSettings& gClipStencilSettings;
|
||||
static const GrStencilSettings* GetClipStencilSettings();
|
||||
|
||||
GrGpuStats fStats;
|
||||
|
||||
|
@ -84,6 +84,13 @@ enum GrStencilOp {
|
||||
kStencilOpCount
|
||||
};
|
||||
|
||||
enum GrStencilFlags {
|
||||
kIsDisabled_StencilFlag = 0x1,
|
||||
kNotDisabled_StencilFlag = 0x2,
|
||||
kDoesWrite_StencilFlag = 0x4,
|
||||
kDoesNotWrite_StencilFlag = 0x8,
|
||||
};
|
||||
|
||||
/**
|
||||
* GrStencilState needs to be a class with accessors and setters so that it
|
||||
* can maintain flags related to its current state. However, we also want to
|
||||
@ -121,6 +128,45 @@ GR_STATIC_ASSERT(sizeof(GrStencilSettingsStruct) ==
|
||||
2*sizeof(unsigned short) + // write masks
|
||||
sizeof(uint32_t)); // flags
|
||||
|
||||
// This macro is used to compute the GrStencilSettingsStructs flags
|
||||
// associated to disabling. It is used both to define constant structure
|
||||
// initializers and inside GrStencilSettings::isDisabled()
|
||||
//
|
||||
#define GR_STENCIL_SETTINGS_IS_DISABLED( \
|
||||
FRONT_PASS_OP, BACK_PASS_OP, \
|
||||
FRONT_FAIL_OP, BACK_FAIL_OP, \
|
||||
FRONT_FUNC, BACK_FUNC) \
|
||||
((FRONT_PASS_OP) == kKeep_StencilOp && \
|
||||
(BACK_PASS_OP) == kKeep_StencilOp && \
|
||||
(FRONT_FAIL_OP) == kKeep_StencilOp && \
|
||||
(BACK_FAIL_OP) == kKeep_StencilOp && \
|
||||
(FRONT_FUNC) == kAlways_StencilFunc && \
|
||||
(BACK_FUNC) == kAlways_StencilFunc)
|
||||
|
||||
#define GR_STENCIL_SETTINGS_DOES_WRITE( \
|
||||
FRONT_PASS_OP, BACK_PASS_OP, \
|
||||
FRONT_FAIL_OP, BACK_FAIL_OP, \
|
||||
FRONT_FUNC, BACK_FUNC) \
|
||||
(!(((FRONT_FUNC) == kNever_StencilFunc || \
|
||||
(FRONT_PASS_OP) == kKeep_StencilOp) && \
|
||||
((BACK_FUNC) == kNever_StencilFunc || \
|
||||
(BACK_PASS_OP) == kKeep_StencilOp) && \
|
||||
((FRONT_FUNC) == kAlways_StencilFunc || \
|
||||
(FRONT_FAIL_OP) == kKeep_StencilOp) && \
|
||||
((BACK_FUNC) == kAlways_StencilFunc || \
|
||||
(BACK_FAIL_OP) == kKeep_StencilOp)))
|
||||
|
||||
#define GR_STENCIL_SETTINGS_DEFAULT_FLAGS( \
|
||||
FRONT_PASS_OP, BACK_PASS_OP, \
|
||||
FRONT_FAIL_OP, BACK_FAIL_OP, \
|
||||
FRONT_FUNC, BACK_FUNC) \
|
||||
((GR_STENCIL_SETTINGS_IS_DISABLED(FRONT_PASS_OP,BACK_PASS_OP, \
|
||||
FRONT_FAIL_OP,BACK_FAIL_OP,FRONT_FUNC,BACK_FUNC) ? \
|
||||
kIsDisabled_StencilFlag : kNotDisabled_StencilFlag) | \
|
||||
(GR_STENCIL_SETTINGS_DOES_WRITE(FRONT_PASS_OP,BACK_PASS_OP, \
|
||||
FRONT_FAIL_OP,BACK_FAIL_OP,FRONT_FUNC,BACK_FUNC) ? \
|
||||
kDoesWrite_StencilFlag : kDoesNotWrite_StencilFlag))
|
||||
|
||||
/**
|
||||
* Class representing stencil state.
|
||||
*/
|
||||
@ -183,42 +229,36 @@ public:
|
||||
memset(this, 0, sizeof(*this));
|
||||
GR_STATIC_ASSERT(0 == kKeep_StencilOp);
|
||||
GR_STATIC_ASSERT(0 == kAlways_StencilFunc);
|
||||
fFlags = kIsDisabled_Flag | kDoesNotWrite_Flag;
|
||||
fFlags = kIsDisabled_StencilFlag | kDoesNotWrite_StencilFlag;
|
||||
}
|
||||
|
||||
bool isDisabled() const {
|
||||
if (fFlags & kIsDisabled_Flag) {
|
||||
if (fFlags & kIsDisabled_StencilFlag) {
|
||||
return true;
|
||||
}
|
||||
if (fFlags & kNotDisabled_Flag) {
|
||||
if (fFlags & kNotDisabled_StencilFlag) {
|
||||
return false;
|
||||
}
|
||||
bool disabled = kKeep_StencilOp == fFrontPassOp &&
|
||||
kKeep_StencilOp == fBackPassOp &&
|
||||
kKeep_StencilOp == fFrontFailOp &&
|
||||
kKeep_StencilOp == fBackFailOp &&
|
||||
kAlways_StencilFunc == fFrontFunc &&
|
||||
kAlways_StencilFunc == fBackFunc;
|
||||
fFlags |= disabled ? kIsDisabled_Flag : kNotDisabled_Flag;
|
||||
bool disabled = GR_STENCIL_SETTINGS_IS_DISABLED(
|
||||
fFrontPassOp, fBackPassOp,
|
||||
fFrontFailOp, fBackFailOp,
|
||||
fFrontFunc ,fBackFunc);
|
||||
fFlags |= disabled ? kIsDisabled_StencilFlag : kNotDisabled_StencilFlag;
|
||||
return disabled;
|
||||
}
|
||||
|
||||
bool doesWrite() const {
|
||||
if (fFlags & kDoesWrite_Flag) {
|
||||
if (fFlags & kDoesWrite_StencilFlag) {
|
||||
return true;
|
||||
}
|
||||
if (fFlags & kDoesNotWrite_Flag) {
|
||||
if (fFlags & kDoesNotWrite_StencilFlag) {
|
||||
return false;
|
||||
}
|
||||
bool writes = !((kNever_StencilFunc == fFrontFunc ||
|
||||
kKeep_StencilOp == fFrontPassOp) &&
|
||||
(kNever_StencilFunc == fBackFunc ||
|
||||
kKeep_StencilOp == fBackPassOp) &&
|
||||
(kAlways_StencilFunc == fFrontFunc ||
|
||||
kKeep_StencilOp == fFrontFailOp) &&
|
||||
(kAlways_StencilFunc == fBackFunc ||
|
||||
kKeep_StencilOp == fBackFailOp));
|
||||
fFlags |= writes ? kDoesWrite_Flag : kDoesNotWrite_Flag;
|
||||
bool writes = GR_STENCIL_SETTINGS_DOES_WRITE(
|
||||
fFrontPassOp, fBackPassOp,
|
||||
fFrontFailOp, fBackFailOp,
|
||||
fFrontFunc, fBackFunc);
|
||||
fFlags |= writes ? kDoesWrite_StencilFlag : kDoesNotWrite_StencilFlag;
|
||||
return writes;
|
||||
}
|
||||
|
||||
@ -250,13 +290,6 @@ public:
|
||||
|
||||
private:
|
||||
friend class GrGpu;
|
||||
enum {
|
||||
kIsDisabled_Flag = 0x1,
|
||||
kNotDisabled_Flag = 0x2,
|
||||
kDoesWrite_Flag = 0x4,
|
||||
kDoesNotWrite_Flag = 0x8,
|
||||
};
|
||||
|
||||
enum {
|
||||
kMaxStencilClipPasses = 2 // maximum number of passes to add a clip
|
||||
// element to the stencil buffer.
|
||||
@ -295,14 +328,14 @@ private:
|
||||
|
||||
GR_STATIC_ASSERT(sizeof(GrStencilSettingsStruct) == sizeof(GrStencilSettings));
|
||||
|
||||
#define GR_STATIC_CONST_STENCIL(NAME, \
|
||||
#define GR_STATIC_CONST_STENCIL_STRUCT(STRUCT_NAME, \
|
||||
FRONT_PASS_OP, BACK_PASS_OP, \
|
||||
FRONT_FAIL_OP, BACK_FAIL_OP, \
|
||||
FRONT_FUNC, BACK_FUNC, \
|
||||
FRONT_MASK, BACK_MASK, \
|
||||
FRONT_REF, BACK_REF, \
|
||||
FRONT_WRITE_MASK, BACK_WRITE_MASK) \
|
||||
static const GrStencilSettingsStruct NAME ## _STRUCT = { \
|
||||
static const GrStencilSettingsStruct STRUCT_NAME = { \
|
||||
(FRONT_PASS_OP), (BACK_PASS_OP), \
|
||||
(FRONT_FAIL_OP), (BACK_FAIL_OP), \
|
||||
(FRONT_FUNC), (BACK_FUNC), \
|
||||
@ -310,14 +343,39 @@ GR_STATIC_ASSERT(sizeof(GrStencilSettingsStruct) == sizeof(GrStencilSettings));
|
||||
(FRONT_MASK), (BACK_MASK), \
|
||||
(FRONT_REF), (BACK_REF), \
|
||||
(FRONT_WRITE_MASK), (BACK_WRITE_MASK), \
|
||||
0 \
|
||||
}; \
|
||||
GR_STENCIL_SETTINGS_DEFAULT_FLAGS( \
|
||||
FRONT_PASS_OP, BACK_PASS_OP, FRONT_FAIL_OP, BACK_FAIL_OP, \
|
||||
FRONT_FUNC, BACK_FUNC) \
|
||||
};
|
||||
|
||||
#define GR_CONST_STENCIL_SETTINGS_PTR_FROM_STRUCT_PTR(STRUCT_PTR) \
|
||||
reinterpret_cast<const GrStencilSettings*>(STRUCT_PTR)
|
||||
|
||||
#define GR_STATIC_CONST_SAME_STENCIL_STRUCT(STRUCT_NAME, \
|
||||
PASS_OP, FAIL_OP, FUNC, MASK, REF, WRITE_MASK) \
|
||||
GR_STATIC_CONST_STENCIL_STRUCT(STRUCT_NAME, (PASS_OP), (PASS_OP), \
|
||||
(FAIL_OP),(FAIL_OP), (FUNC), (FUNC), (MASK), (MASK), (REF), (REF), \
|
||||
(WRITE_MASK),(WRITE_MASK))
|
||||
|
||||
#define GR_STATIC_CONST_STENCIL(NAME, \
|
||||
FRONT_PASS_OP, BACK_PASS_OP, \
|
||||
FRONT_FAIL_OP, BACK_FAIL_OP, \
|
||||
FRONT_FUNC, BACK_FUNC, \
|
||||
FRONT_MASK, BACK_MASK, \
|
||||
FRONT_REF, BACK_REF, \
|
||||
FRONT_WRITE_MASK, BACK_WRITE_MASK) \
|
||||
GR_STATIC_CONST_STENCIL_STRUCT(NAME ## _STRUCT, \
|
||||
(FRONT_PASS_OP),(BACK_PASS_OP),(FRONT_FAIL_OP),(BACK_FAIL_OP), \
|
||||
(FRONT_FUNC),(BACK_FUNC),(FRONT_MASK),(BACK_MASK), \
|
||||
(FRONT_REF),(BACK_REF),(FRONT_WRITE_MASK),(BACK_WRITE_MASK)) \
|
||||
static const GrStencilSettings& NAME = \
|
||||
*reinterpret_cast<const GrStencilSettings*>(&(NAME ## _STRUCT))
|
||||
#endif
|
||||
*GR_CONST_STENCIL_SETTINGS_PTR_FROM_STRUCT_PTR(&(NAME ## _STRUCT));
|
||||
|
||||
|
||||
#define GR_STATIC_CONST_SAME_STENCIL(NAME, \
|
||||
PASS_OP, FAIL_OP, FUNC, MASK, REF, WRITE_MASK) \
|
||||
GR_STATIC_CONST_STENCIL(NAME, (PASS_OP), (PASS_OP), (FAIL_OP), \
|
||||
(FAIL_OP), (FUNC), (FUNC), (MASK), (MASK), (REF), (REF), (WRITE_MASK), \
|
||||
(WRITE_MASK))
|
||||
|
||||
#endif
|
||||
|
@ -1642,7 +1642,7 @@ void GrGpuGL::flushStencil() {
|
||||
|
||||
if (settings->isDisabled()) {
|
||||
if (stencilClip) {
|
||||
settings = &gClipStencilSettings;
|
||||
settings = GetClipStencilSettings();
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user