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:
parent
8c0aab1443
commit
6b2445eb15
@ -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
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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,
|
||||
|
@ -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))
|
||||
|
Loading…
Reference in New Issue
Block a user