Make GrStencilState a class to enable future optimizations

Review URL: http://codereview.appspot.com/5492047/


git-svn-id: http://skia.googlecode.com/svn/trunk@2881 2bbb7eff-a529-9590-31e7-b0007b416f81
This commit is contained in:
bsalomon@google.com 2011-12-15 19:47:46 +00:00
parent 8c0aab1443
commit 6b2445eb15
6 changed files with 357 additions and 325 deletions

View File

@ -41,34 +41,31 @@ bool GrDefaultPathRenderer::canDrawPath(const GrDrawTarget::Caps& targetCaps,
////// Even/Odd
static const GrStencilSettings gEOStencilPass = {
kInvert_StencilOp, kInvert_StencilOp,
kKeep_StencilOp, kKeep_StencilOp,
kAlwaysIfInClip_StencilFunc, kAlwaysIfInClip_StencilFunc,
0xffff, 0xffff,
0xffff, 0xffff,
0xffff, 0xffff
};
GR_STATIC_CONST_SAME_STENCIL(gEOStencilPass,
kInvert_StencilOp,
kKeep_StencilOp,
kAlwaysIfInClip_StencilFunc,
0xffff,
0xffff,
0xffff);
// ok not to check clip b/c stencil pass only wrote inside clip
static const GrStencilSettings gEOColorPass = {
kZero_StencilOp, kZero_StencilOp,
kZero_StencilOp, kZero_StencilOp,
kNotEqual_StencilFunc, kNotEqual_StencilFunc,
0xffff, 0xffff,
0x0000, 0x0000,
0xffff, 0xffff
};
GR_STATIC_CONST_SAME_STENCIL(gEOColorPass,
kZero_StencilOp,
kZero_StencilOp,
kNotEqual_StencilFunc,
0xffff,
0x0000,
0xffff);
// have to check clip b/c outside clip will always be zero.
static const GrStencilSettings gInvEOColorPass = {
kZero_StencilOp, kZero_StencilOp,
kZero_StencilOp, kZero_StencilOp,
kEqualIfInClip_StencilFunc, kEqualIfInClip_StencilFunc,
0xffff, 0xffff,
0x0000, 0x0000,
0xffff, 0xffff
};
GR_STATIC_CONST_SAME_STENCIL(gInvEOColorPass,
kZero_StencilOp,
kZero_StencilOp,
kEqualIfInClip_StencilFunc,
0xffff,
0x0000,
0xffff);
////// Winding
@ -76,95 +73,91 @@ static const GrStencilSettings gInvEOColorPass = {
// when we don't have wrap incr and decr we use the stencil test to simulate
// them.
static const GrStencilSettings gWindStencilSeparateWithWrap = {
GR_STATIC_CONST_STENCIL(gWindStencilSeparateWithWrap,
kIncWrap_StencilOp, kDecWrap_StencilOp,
kKeep_StencilOp, kKeep_StencilOp,
kAlwaysIfInClip_StencilFunc, kAlwaysIfInClip_StencilFunc,
0xffff, 0xffff,
0xffff, 0xffff,
0xffff, 0xffff
};
0xffff, 0xffff);
// if inc'ing the max value, invert to make 0
// if dec'ing zero invert to make all ones.
// we can't avoid touching the stencil on both passing and
// failing, so we can't resctrict ourselves to the clip.
static const GrStencilSettings gWindStencilSeparateNoWrap = {
GR_STATIC_CONST_STENCIL(gWindStencilSeparateNoWrap,
kInvert_StencilOp, kInvert_StencilOp,
kIncClamp_StencilOp, kDecClamp_StencilOp,
kEqual_StencilFunc, kEqual_StencilFunc,
0xffff, 0xffff,
0xffff, 0x0000,
0xffff, 0xffff
};
0xffff, 0xffff);
// When there are no separate faces we do two passes to setup the winding rule
// stencil. First we draw the front faces and inc, then we draw the back faces
// and dec. These are same as the above two split into the incrementing and
// decrementing passes.
static const GrStencilSettings gWindSingleStencilWithWrapInc = {
kIncWrap_StencilOp, kIncWrap_StencilOp,
kKeep_StencilOp, kKeep_StencilOp,
kAlwaysIfInClip_StencilFunc, kAlwaysIfInClip_StencilFunc,
0xffff, 0xffff,
0xffff, 0xffff,
0xffff, 0xffff
};
static const GrStencilSettings gWindSingleStencilWithWrapDec = {
kDecWrap_StencilOp, kDecWrap_StencilOp,
kKeep_StencilOp, kKeep_StencilOp,
kAlwaysIfInClip_StencilFunc, kAlwaysIfInClip_StencilFunc,
0xffff, 0xffff,
0xffff, 0xffff,
0xffff, 0xffff
};
static const GrStencilSettings gWindSingleStencilNoWrapInc = {
kInvert_StencilOp, kInvert_StencilOp,
kIncClamp_StencilOp, kIncClamp_StencilOp,
kEqual_StencilFunc, kEqual_StencilFunc,
0xffff, 0xffff,
0xffff, 0xffff,
0xffff, 0xffff
};
static const GrStencilSettings gWindSingleStencilNoWrapDec = {
kInvert_StencilOp, kInvert_StencilOp,
kDecClamp_StencilOp, kDecClamp_StencilOp,
kEqual_StencilFunc, kEqual_StencilFunc,
0xffff, 0xffff,
0x0000, 0x0000,
0xffff, 0xffff
};
GR_STATIC_CONST_SAME_STENCIL(gWindSingleStencilWithWrapInc,
kIncWrap_StencilOp,
kKeep_StencilOp,
kAlwaysIfInClip_StencilFunc,
0xffff,
0xffff,
0xffff);
static const GrStencilSettings gWindColorPass = {
kZero_StencilOp, kZero_StencilOp,
kZero_StencilOp, kZero_StencilOp,
kNonZeroIfInClip_StencilFunc, kNonZeroIfInClip_StencilFunc,
0xffff, 0xffff,
0x0000, 0x0000,
0xffff, 0xffff
};
GR_STATIC_CONST_SAME_STENCIL(gWindSingleStencilWithWrapDec,
kDecWrap_StencilOp,
kKeep_StencilOp,
kAlwaysIfInClip_StencilFunc,
0xffff,
0xffff,
0xffff);
static const GrStencilSettings gInvWindColorPass = {
kZero_StencilOp, kZero_StencilOp,
kZero_StencilOp, kZero_StencilOp,
kEqualIfInClip_StencilFunc, kEqualIfInClip_StencilFunc,
0xffff, 0xffff,
0x0000, 0x0000,
0xffff, 0xffff
};
GR_STATIC_CONST_SAME_STENCIL(gWindSingleStencilNoWrapInc,
kInvert_StencilOp,
kIncClamp_StencilOp,
kEqual_StencilFunc,
0xffff,
0xffff,
0xffff);
GR_STATIC_CONST_SAME_STENCIL(gWindSingleStencilNoWrapDec,
kInvert_StencilOp,
kDecClamp_StencilOp,
kEqual_StencilFunc,
0xffff,
0x0000,
0xffff);
// Color passes are the same whether we use the two-sided stencil or two passes
GR_STATIC_CONST_SAME_STENCIL(gWindColorPass,
kZero_StencilOp,
kZero_StencilOp,
kNonZeroIfInClip_StencilFunc,
0xffff,
0x0000,
0xffff);
GR_STATIC_CONST_SAME_STENCIL(gInvWindColorPass,
kZero_StencilOp,
kZero_StencilOp,
kEqualIfInClip_StencilFunc,
0xffff,
0x0000,
0xffff);
////// Normal render to stencil
// Sometimes the default path renderer can draw a path directly to the stencil
// buffer without having to first resolve the interior / exterior.
static const GrStencilSettings gDirectToStencil = {
kZero_StencilOp, kZero_StencilOp,
kIncClamp_StencilOp, kIncClamp_StencilOp,
kAlwaysIfInClip_StencilFunc, kAlwaysIfInClip_StencilFunc,
0xffff, 0xffff,
0x0000, 0x0000,
0xffff, 0xffff
};
GR_STATIC_CONST_SAME_STENCIL(gDirectToStencil,
kZero_StencilOp,
kIncClamp_StencilOp,
kAlwaysIfInClip_StencilFunc,
0xffff,
0x0000,
0xffff);
////////////////////////////////////////////////////////////////////////////////
// Helpers for drawPath

View File

@ -339,14 +339,14 @@ const GrVertexBuffer* GrGpu::getUnitSquareVertexBuffer() const {
////////////////////////////////////////////////////////////////////////////////
// stencil settings to use when clip is in stencil
const GrStencilSettings GrGpu::gClipStencilSettings = {
kKeep_StencilOp, kKeep_StencilOp,
kKeep_StencilOp, kKeep_StencilOp,
kAlwaysIfInClip_StencilFunc, kAlwaysIfInClip_StencilFunc,
0x0000, 0x0000,
0x0000, 0x0000,
0x0000, 0x0000
};
GR_STATIC_CONST_SAME_STENCIL(gClipStencilSettings,
kKeep_StencilOp,
kKeep_StencilOp,
kAlwaysIfInClip_StencilFunc,
0x0000,
0x0000,
0x0000);
const GrStencilSettings& GrGpu::gClipStencilSettings = ::gClipStencilSettings;
// mapping of clip-respecting stencil funcs to normal stencil funcs
// mapping depends on whether stencil-clipping is in effect.
@ -669,14 +669,13 @@ bool GrGpu::setupClipAndFlushState(GrPrimitiveType type) {
// draw the element to the client stencil bits if necessary
if (!canDrawDirectToClip) {
static const GrStencilSettings gDrawToStencil = {
kIncClamp_StencilOp, kIncClamp_StencilOp,
kIncClamp_StencilOp, kIncClamp_StencilOp,
kAlways_StencilFunc, kAlways_StencilFunc,
0xffff, 0xffff,
0x0000, 0x0000,
0xffff, 0xffff,
};
GR_STATIC_CONST_SAME_STENCIL(gDrawToStencil,
kIncClamp_StencilOp,
kIncClamp_StencilOp,
kAlways_StencilFunc,
0xffff,
0x0000,
0xffff);
SET_RANDOM_COLOR
if (kRect_ClipType == clip.getElementType(c)) {
*drawState->stencil() = gDrawToStencil;

View File

@ -355,8 +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& gClipStencilSettings;
GrGpuStats fStats;

View File

@ -1826,14 +1826,14 @@ void GrGpuGL::flushStencil() {
GL_CALL(Enable(GR_GL_STENCIL_TEST));
#if GR_DEBUG
if (!this->getCaps().fStencilWrapOpsSupport) {
GrAssert(settings->fFrontPassOp != kIncWrap_StencilOp);
GrAssert(settings->fFrontPassOp != kDecWrap_StencilOp);
GrAssert(settings->fFrontFailOp != kIncWrap_StencilOp);
GrAssert(settings->fBackFailOp != kDecWrap_StencilOp);
GrAssert(settings->fBackPassOp != kIncWrap_StencilOp);
GrAssert(settings->fBackPassOp != kDecWrap_StencilOp);
GrAssert(settings->fBackFailOp != kIncWrap_StencilOp);
GrAssert(settings->fFrontFailOp != kDecWrap_StencilOp);
GrAssert(settings->frontPassOp() != kIncWrap_StencilOp);
GrAssert(settings->frontPassOp() != kDecWrap_StencilOp);
GrAssert(settings->frontFailOp() != kIncWrap_StencilOp);
GrAssert(settings->backFailOp() != kDecWrap_StencilOp);
GrAssert(settings->backPassOp() != kIncWrap_StencilOp);
GrAssert(settings->backPassOp() != kDecWrap_StencilOp);
GrAssert(settings->backFailOp() != kIncWrap_StencilOp);
GrAssert(settings->frontFailOp() != kDecWrap_StencilOp);
}
#endif
int stencilBits = 0;
@ -1843,8 +1843,7 @@ void GrGpuGL::flushStencil() {
stencilBits = stencilBuffer->bits();
}
// TODO: dynamically attach a stencil buffer
GrAssert(stencilBits ||
(GrStencilSettings::gDisabled == *settings));
GrAssert(stencilBits || settings->isDisabled());
GrGLuint clipStencilMask = 0;
GrGLuint userStencilMask = ~0;
@ -1853,19 +1852,19 @@ void GrGpuGL::flushStencil() {
userStencilMask = clipStencilMask - 1;
}
unsigned int frontRef = settings->fFrontFuncRef;
unsigned int frontMask = settings->fFrontFuncMask;
unsigned int frontWriteMask = settings->fFrontWriteMask;
unsigned int frontRef = settings->frontFuncRef();
unsigned int frontMask = settings->frontFuncMask();
unsigned int frontWriteMask = settings->frontWriteMask();
GrGLenum frontFunc;
if (drawClipToStencil) {
GrAssert(settings->fFrontFunc < kBasicStencilFuncCount);
frontFunc = grToGLStencilFunc[settings->fFrontFunc];
GrAssert(settings->frontFunc() < kBasicStencilFuncCount);
frontFunc = grToGLStencilFunc[settings->frontFunc()];
} else {
frontFunc = grToGLStencilFunc[ConvertStencilFunc(
stencilClip, settings->fFrontFunc)];
stencilClip, settings->frontFunc())];
ConvertStencilFuncAndMask(settings->fFrontFunc,
ConvertStencilFuncAndMask(settings->frontFunc(),
stencilClip,
clipStencilMask,
userStencilMask,
@ -1874,28 +1873,28 @@ void GrGpuGL::flushStencil() {
frontWriteMask &= userStencilMask;
}
GrAssert((size_t)
settings->fFrontFailOp < GR_ARRAY_COUNT(grToGLStencilOp));
settings->frontFailOp() < GR_ARRAY_COUNT(grToGLStencilOp));
GrAssert((size_t)
settings->fFrontPassOp < GR_ARRAY_COUNT(grToGLStencilOp));
settings->frontPassOp() < GR_ARRAY_COUNT(grToGLStencilOp));
GrAssert((size_t)
settings->fBackFailOp < GR_ARRAY_COUNT(grToGLStencilOp));
settings->backFailOp() < GR_ARRAY_COUNT(grToGLStencilOp));
GrAssert((size_t)
settings->fBackPassOp < GR_ARRAY_COUNT(grToGLStencilOp));
settings->backPassOp() < GR_ARRAY_COUNT(grToGLStencilOp));
if (this->getCaps().fTwoSidedStencilSupport) {
GrGLenum backFunc;
unsigned int backRef = settings->fBackFuncRef;
unsigned int backMask = settings->fBackFuncMask;
unsigned int backWriteMask = settings->fBackWriteMask;
unsigned int backRef = settings->backFuncRef();
unsigned int backMask = settings->backFuncMask();
unsigned int backWriteMask = settings->backWriteMask();
if (drawClipToStencil) {
GrAssert(settings->fBackFunc < kBasicStencilFuncCount);
backFunc = grToGLStencilFunc[settings->fBackFunc];
GrAssert(settings->backFunc() < kBasicStencilFuncCount);
backFunc = grToGLStencilFunc[settings->backFunc()];
} else {
backFunc = grToGLStencilFunc[ConvertStencilFunc(
stencilClip, settings->fBackFunc)];
ConvertStencilFuncAndMask(settings->fBackFunc,
stencilClip, settings->backFunc())];
ConvertStencilFuncAndMask(settings->backFunc(),
stencilClip,
clipStencilMask,
userStencilMask,
@ -1911,20 +1910,20 @@ void GrGpuGL::flushStencil() {
backRef, backMask));
GL_CALL(StencilMaskSeparate(GR_GL_BACK, backWriteMask));
GL_CALL(StencilOpSeparate(GR_GL_FRONT,
grToGLStencilOp[settings->fFrontFailOp],
grToGLStencilOp[settings->fFrontPassOp],
grToGLStencilOp[settings->fFrontPassOp]));
grToGLStencilOp[settings->frontFailOp()],
grToGLStencilOp[settings->frontPassOp()],
grToGLStencilOp[settings->frontPassOp()]));
GL_CALL(StencilOpSeparate(GR_GL_BACK,
grToGLStencilOp[settings->fBackFailOp],
grToGLStencilOp[settings->fBackPassOp],
grToGLStencilOp[settings->fBackPassOp]));
grToGLStencilOp[settings->backFailOp()],
grToGLStencilOp[settings->backPassOp()],
grToGLStencilOp[settings->backPassOp()]));
} else {
GL_CALL(StencilFunc(frontFunc, frontRef, frontMask));
GL_CALL(StencilMask(frontWriteMask));
GL_CALL(StencilOp(grToGLStencilOp[settings->fFrontFailOp],
grToGLStencilOp[settings->fFrontPassOp],
grToGLStencilOp[settings->fFrontPassOp]));
GL_CALL(StencilOp(grToGLStencilOp[settings->frontFailOp()],
grToGLStencilOp[settings->frontPassOp()],
grToGLStencilOp[settings->frontPassOp()]));
}
}
*fHWDrawState.stencil() = *settings;

View File

@ -9,17 +9,6 @@
#include "GrStencil.h"
const GrStencilSettings GrStencilSettings::gDisabled = {
kKeep_StencilOp, kKeep_StencilOp,
kKeep_StencilOp, kKeep_StencilOp,
kAlways_StencilFunc, kAlways_StencilFunc,
0x0000, 0x0000,
0x0000, 0x0000,
0x0000, 0x0000
};
GR_STATIC_ASSERT(0 == kKeep_StencilOp);
GR_STATIC_ASSERT(0 == kAlways_StencilFunc);
////////////////////////////////////////////////////////////////////////////////
// Stencil Rules for Merging user stencil space into clip
@ -32,171 +21,160 @@ GR_STATIC_ASSERT(0 == kAlways_StencilFunc);
// Replace
// set the ref to be the clip bit, but mask it out for the test
static const GrStencilSettings gUserToClipReplace = {
kReplace_StencilOp, kReplace_StencilOp,
kZero_StencilOp, kZero_StencilOp,
kLess_StencilFunc, kLess_StencilFunc,
0xffff, 0xffff, // unset clip bit
0x0000, 0x0000, // set clip bit
0xffff, 0xffff
};
static const GrStencilSettings gInvUserToClipReplace = {
kReplace_StencilOp, kReplace_StencilOp,
kZero_StencilOp, kZero_StencilOp,
kEqual_StencilFunc, kEqual_StencilFunc,
0xffff, 0xffff, // unset clip bit
0x0000, 0x0000, // set clip bit
0xffff, 0xffff
};
GR_STATIC_CONST_SAME_STENCIL(gUserToClipReplace,
kReplace_StencilOp,
kZero_StencilOp,
kLess_StencilFunc,
0xffff, // unset clip bit
0x0000, // set clip bit
0xffff);
GR_STATIC_CONST_SAME_STENCIL(gInvUserToClipReplace,
kReplace_StencilOp,
kZero_StencilOp,
kEqual_StencilFunc,
0xffff, // unset clip bit
0x0000, // set clip bit
0xffff);
///////
// Intersect
static const GrStencilSettings gUserToClipIsect = {
kReplace_StencilOp, kReplace_StencilOp,
kZero_StencilOp, kZero_StencilOp,
kLess_StencilFunc, kLess_StencilFunc,
0xffff, 0xffff,
0x0000, 0x0000, // set clip bit
0xffff, 0xffff
};
static const GrStencilSettings gInvUserToClipIsect = {
kReplace_StencilOp, kReplace_StencilOp,
kZero_StencilOp, kZero_StencilOp,
kEqual_StencilFunc, kEqual_StencilFunc,
0xffff, 0xffff,
0x0000, 0x0000, // set clip bit
0xffff, 0xffff
};
GR_STATIC_CONST_SAME_STENCIL(gUserToClipIsect,
kReplace_StencilOp,
kZero_StencilOp,
kLess_StencilFunc,
0xffff,
0x0000, // set clip bit
0xffff);
GR_STATIC_CONST_SAME_STENCIL(gInvUserToClipIsect,
kReplace_StencilOp,
kZero_StencilOp,
kEqual_StencilFunc,
0xffff,
0x0000, // set clip bit
0xffff);
///////
// Difference
static const GrStencilSettings gUserToClipDiff = {
kReplace_StencilOp, kReplace_StencilOp,
kZero_StencilOp, kZero_StencilOp,
kEqual_StencilFunc, kEqual_StencilFunc,
0xffff, 0xffff,
0x0000, 0x0000, // set clip bit
0xffff, 0xffff
};
static const GrStencilSettings gInvUserToClipDiff = {
kReplace_StencilOp, kReplace_StencilOp,
kZero_StencilOp, kZero_StencilOp,
kLess_StencilFunc, kLess_StencilFunc,
0xffff, 0xffff,
0x0000, 0x0000, // set clip bit
0xffff, 0xffff
};
GR_STATIC_CONST_SAME_STENCIL(gUserToClipDiff,
kReplace_StencilOp,
kZero_StencilOp,
kEqual_StencilFunc,
0xffff,
0x0000, // set clip bit
0xffff);
GR_STATIC_CONST_SAME_STENCIL(gInvUserToClipDiff,
kReplace_StencilOp,
kZero_StencilOp,
kLess_StencilFunc,
0xffff,
0x0000, // set clip bit
0xffff);
///////
// Union
// first pass makes all the passing cases >= just clip bit set.
static const GrStencilSettings gUserToClipUnionPass0 = {
kReplace_StencilOp, kReplace_StencilOp,
kKeep_StencilOp, kKeep_StencilOp,
kLEqual_StencilFunc, kLEqual_StencilFunc,
0xffff, 0xffff, // unset clip bit
0x0001, 0x0001, // set clip bit
0xffff, 0xffff
};
GR_STATIC_CONST_SAME_STENCIL(gUserToClipUnionPass0,
kReplace_StencilOp,
kKeep_StencilOp,
kLEqual_StencilFunc,
0xffff,
0x0001, // set clip bit
0xffff);
// second pass allows anything greater than just clip bit set to pass
static const GrStencilSettings gUserToClipUnionPass1 = {
kReplace_StencilOp, kReplace_StencilOp,
kZero_StencilOp, kZero_StencilOp,
kLEqual_StencilFunc, kLEqual_StencilFunc,
0xffff, 0xffff,
0x0000, 0x0000, // set clip bit
0xffff, 0xffff
};
GR_STATIC_CONST_SAME_STENCIL(gUserToClipUnionPass1,
kReplace_StencilOp,
kZero_StencilOp,
kLEqual_StencilFunc,
0xffff,
0x0000, // set clip bit
0xffff);
// first pass finds zeros in the user bits and if found sets
// the clip bit to 1
static const GrStencilSettings gInvUserToClipUnionPass0 = {
kReplace_StencilOp, kReplace_StencilOp,
kKeep_StencilOp, kKeep_StencilOp,
kEqual_StencilFunc, kEqual_StencilFunc,
0xffff, 0xffff, // unset clip bit
0x0000, 0x0000, // set clip bit
0x0000, 0x0000 // set clip bit
};
GR_STATIC_CONST_SAME_STENCIL(gInvUserToClipUnionPass0,
kReplace_StencilOp,
kKeep_StencilOp,
kEqual_StencilFunc,
0xffff,
0x0000, // set clip bit
0x0000 // set clip bit
);
// second pass zeros the user bits
static const GrStencilSettings gInvUserToClipUnionPass1 = {
kZero_StencilOp, kZero_StencilOp,
kZero_StencilOp, kZero_StencilOp,
kLess_StencilFunc, kLess_StencilFunc,
0xffff, 0xffff,
0x0000, 0x0000,
0xffff, 0xffff // unset clip bit
};
GR_STATIC_CONST_SAME_STENCIL(gInvUserToClipUnionPass1,
kZero_StencilOp,
kZero_StencilOp,
kLess_StencilFunc,
0xffff,
0x0000,
0xffff // unset clip bit
);
///////
// Xor
static const GrStencilSettings gUserToClipXorPass0 = {
kInvert_StencilOp, kInvert_StencilOp,
kKeep_StencilOp, kKeep_StencilOp,
kEqual_StencilFunc, kEqual_StencilFunc,
0xffff, 0xffff, // unset clip bit
0x0000, 0x0000,
0xffff, 0xffff
};
GR_STATIC_CONST_SAME_STENCIL(gUserToClipXorPass0,
kInvert_StencilOp,
kKeep_StencilOp,
kEqual_StencilFunc,
0xffff, // unset clip bit
0x0000,
0xffff);
static const GrStencilSettings gUserToClipXorPass1 = {
kReplace_StencilOp, kReplace_StencilOp,
kZero_StencilOp, kZero_StencilOp,
kGreater_StencilFunc, kGreater_StencilFunc,
0xffff, 0xffff,
0x0000, 0x0000, // set clip bit
0xffff, 0xffff
};
GR_STATIC_CONST_SAME_STENCIL(gUserToClipXorPass1,
kReplace_StencilOp,
kZero_StencilOp,
kGreater_StencilFunc,
0xffff,
0x0000, // set clip bit
0xffff);
static const GrStencilSettings gInvUserToClipXorPass0 = {
kInvert_StencilOp, kInvert_StencilOp,
kKeep_StencilOp, kKeep_StencilOp,
kEqual_StencilFunc, kEqual_StencilFunc,
0xffff, 0xffff, // unset clip bit
0x0000, 0x0000,
0xffff, 0xffff
};
GR_STATIC_CONST_SAME_STENCIL(gInvUserToClipXorPass0,
kInvert_StencilOp,
kKeep_StencilOp,
kEqual_StencilFunc,
0xffff, // unset clip bit
0x0000,
0xffff);
static const GrStencilSettings gInvUserToClipXorPass1 = {
kReplace_StencilOp, kReplace_StencilOp,
kZero_StencilOp, kZero_StencilOp,
kLess_StencilFunc, kLess_StencilFunc,
0xffff, 0xffff,
0x0000, 0x0000, // set clip bit
0xffff, 0xffff
};
GR_STATIC_CONST_SAME_STENCIL(gInvUserToClipXorPass1,
kReplace_StencilOp,
kZero_StencilOp,
kLess_StencilFunc,
0xffff,
0x0000, // set clip bit
0xffff);
///////
// Reverse Diff
static const GrStencilSettings gUserToClipRDiffPass0 = {
kInvert_StencilOp, kInvert_StencilOp,
kZero_StencilOp, kZero_StencilOp,
kLess_StencilFunc, kLess_StencilFunc,
0xffff, 0xffff, // unset clip bit
0x0000, 0x0000, // set clip bit
0xffff, 0xffff
};
GR_STATIC_CONST_SAME_STENCIL(gUserToClipRDiffPass0,
kInvert_StencilOp,
kZero_StencilOp,
kLess_StencilFunc,
0xffff, // unset clip bit
0x0000, // set clip bit
0xffff);
static const GrStencilSettings gUserToClipRDiffPass1 = {
kReplace_StencilOp, kReplace_StencilOp,
kZero_StencilOp, kZero_StencilOp,
kEqual_StencilFunc, kEqual_StencilFunc,
0x0000, 0x0000, // set clip bit
0x0000, 0x0000, // set clip bit
0xffff, 0xffff
};
GR_STATIC_CONST_SAME_STENCIL(gUserToClipRDiffPass1,
kReplace_StencilOp,
kZero_StencilOp,
kEqual_StencilFunc,
0x0000, // set clip bit
0x0000, // set clip bit
0xffff);
static const GrStencilSettings gInvUserToClipRDiff = {
kInvert_StencilOp, kInvert_StencilOp,
kZero_StencilOp, kZero_StencilOp,
kEqual_StencilFunc, kEqual_StencilFunc,
0xffff, 0xffff,
0x0000, 0x0000,
0x0000, 0x0000 // set clip bit
};
GR_STATIC_CONST_SAME_STENCIL(gInvUserToClipRDiff,
kInvert_StencilOp,
kZero_StencilOp,
kEqual_StencilFunc,
0xffff,
0x0000,
0x0000 // set clip bit
);
///////
// Direct to Stencil
@ -206,41 +184,41 @@ static const GrStencilSettings gInvUserToClipRDiff = {
// this one only works if used right after stencil clip was cleared.
// Our GrClip doesn't allow midstream replace ops.
static const GrStencilSettings gReplaceClip = {
kReplace_StencilOp, kReplace_StencilOp,
kReplace_StencilOp, kReplace_StencilOp,
kAlways_StencilFunc, kAlways_StencilFunc,
0xffff, 0xffff,
0x0000, 0x0000, // set clip bit
0x0000, 0x0000 // set clipBit
};
GR_STATIC_CONST_SAME_STENCIL(gReplaceClip,
kReplace_StencilOp,
kReplace_StencilOp,
kAlways_StencilFunc,
0xffff,
0x0000, // set clip bit
0x0000 // set clipBit
);
static const GrStencilSettings gUnionClip = {
kReplace_StencilOp, kReplace_StencilOp,
kReplace_StencilOp, kReplace_StencilOp,
kAlways_StencilFunc, kAlways_StencilFunc,
0xffff, 0xffff,
0x0000, 0x0000, // set clip bit
0x0000, 0x0000 // set clip bit
};
GR_STATIC_CONST_SAME_STENCIL(gUnionClip,
kReplace_StencilOp,
kReplace_StencilOp,
kAlways_StencilFunc,
0xffff,
0x0000, // set clip bit
0x0000 // set clip bit
);
static const GrStencilSettings gXorClip = {
kInvert_StencilOp, kInvert_StencilOp,
kInvert_StencilOp, kInvert_StencilOp,
kAlways_StencilFunc, kAlways_StencilFunc,
0xffff, 0xffff,
0x0000, 0x0000,
0x0000, 0x0000 // set clip bit
};
GR_STATIC_CONST_SAME_STENCIL(gXorClip,
kInvert_StencilOp,
kInvert_StencilOp,
kAlways_StencilFunc,
0xffff,
0x0000,
0x0000 // set clip bit
);
static const GrStencilSettings gDiffClip = {
kZero_StencilOp, kZero_StencilOp,
kZero_StencilOp, kZero_StencilOp,
kAlways_StencilFunc, kAlways_StencilFunc,
0xffff, 0xffff,
0x0000, 0x0000,
0x0000, 0x0000 // set clip bit
};
GR_STATIC_CONST_SAME_STENCIL(gDiffClip,
kZero_StencilOp,
kZero_StencilOp,
kAlways_StencilFunc,
0xffff,
0x0000,
0x0000 // set clip bit
);
bool GrStencilSettings::GetClipPasses(GrSetOp op,
bool canBeDirect,

View File

@ -85,9 +85,15 @@ enum GrStencilOp {
};
/**
* Struct representing stencil state.
* 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
* be able to declare pre-made stencil settings at compile time (without
* inserting static initializer code). So all the data members are in this
* struct. A macro defined after the class can be used to jam an instance of
* this struct that is created from an initializer list into a
* GrStencilSettings. (We hang our heads in shame.)
*/
struct GrStencilSettings {
struct GrStencilSettingsStruct {
GrStencilOp fFrontPassOp : 8; // op to perform when front faces pass
GrStencilOp fBackPassOp : 8; // op to perform when back faces pass
GrStencilOp fFrontFailOp : 8; // op to perform when front faces fail
@ -100,7 +106,14 @@ struct GrStencilSettings {
unsigned short fBackFuncRef; // reference value for back face test
unsigned short fFrontWriteMask; // stencil write mask for front faces
unsigned short fBackWriteMask; // stencil write mask for back faces
};
/**
* Class representing stencil state.
*/
class GrStencilSettings : private GrStencilSettingsStruct {
public:
bool operator == (const GrStencilSettings& s) const {
// make sure this is tightly packed (< 4B padding).
GR_STATIC_ASSERT(sizeof(GrStencilSettings) / 4 ==
@ -119,6 +132,32 @@ struct GrStencilSettings {
return *this;
}
GrStencilOp frontPassOp() const { return fFrontPassOp; }
GrStencilOp backPassOp() const { return fBackPassOp; }
GrStencilOp frontFailOp() const { return fFrontFailOp; }
GrStencilOp backFailOp() const { return fBackFailOp; }
GrStencilFunc frontFunc() const { return fFrontFunc; }
GrStencilFunc backFunc() const { return fBackFunc; }
unsigned short frontFuncMask() const { return fFrontFuncMask; }
unsigned short backFuncMask() const { return fBackFuncMask; }
unsigned short frontFuncRef() const { return fFrontFuncRef; }
unsigned short backFuncRef() const { return fBackFuncRef; }
unsigned short frontWriteMask() const {return fFrontWriteMask; }
unsigned short backWriteMask() const { return fBackWriteMask; }
void setFrontPassOp(GrStencilOp op) { fFrontPassOp = op; }
void setBackPassOp(GrStencilOp op) { fBackPassOp = op; }
void setFrontFailOp(GrStencilOp op) {fFrontFailOp = op; }
void setBackFailOp(GrStencilOp op) { fBackFailOp = op; }
void setFrontFunc(GrStencilFunc func) { fFrontFunc = func; }
void setBackFunc(GrStencilFunc func) { fBackFunc = func; }
void setFrontFuncMask(unsigned short mask) { fFrontFuncMask = mask; }
void setBackFuncMask(unsigned short mask) { fBackFuncMask = mask; }
void setFrontFuncRef(unsigned short ref) { fFrontFuncRef = ref; }
void setBackFuncRef(unsigned short ref) { fBackFuncRef = ref; }
void setFrontWriteMask(unsigned short writeMask) { fFrontWriteMask = writeMask; }
void setBackWriteMask(unsigned short writeMask) { fBackWriteMask = writeMask; }
void setSame(GrStencilOp passOp,
GrStencilOp failOp,
GrStencilFunc func,
@ -139,10 +178,10 @@ struct GrStencilSettings {
fBackWriteMask = writeMask;
}
// canonical value for disabled stenciling
static const GrStencilSettings gDisabled;
void setDisabled() {
*this = gDisabled;
memset(this, 0, sizeof(*this));
GR_STATIC_ASSERT(0 == kKeep_StencilOp);
GR_STATIC_ASSERT(0 == kAlways_StencilFunc);
}
bool isDisabled() const {
return kKeep_StencilOp == fFrontPassOp &&
@ -206,4 +245,29 @@ private:
GrStencilSettings settings[kMaxStencilClipPasses]);
};
GR_STATIC_ASSERT(sizeof(GrStencilSettingsStruct) == sizeof(GrStencilSettings));
#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) \
static const GrStencilSettingsStruct 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 = \
*static_cast<const GrStencilSettings*>(&(NAME ## _STRUCT))
#endif
#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))