From 6b2445eb154d71517b1ed6811f3f77eec592963a Mon Sep 17 00:00:00 2001 From: "bsalomon@google.com" Date: Thu, 15 Dec 2011 19:47:46 +0000 Subject: [PATCH] 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 --- src/gpu/GrDefaultPathRenderer.cpp | 165 +++++++-------- src/gpu/GrGpu.cpp | 31 ++- src/gpu/GrGpu.h | 3 +- src/gpu/GrGpuGL.cpp | 73 ++++--- src/gpu/GrStencil.cpp | 336 ++++++++++++++---------------- src/gpu/GrStencil.h | 74 ++++++- 6 files changed, 357 insertions(+), 325 deletions(-) diff --git a/src/gpu/GrDefaultPathRenderer.cpp b/src/gpu/GrDefaultPathRenderer.cpp index ebd0cc142d..6ea04591cd 100644 --- a/src/gpu/GrDefaultPathRenderer.cpp +++ b/src/gpu/GrDefaultPathRenderer.cpp @@ -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 diff --git a/src/gpu/GrGpu.cpp b/src/gpu/GrGpu.cpp index 4a2e5d71a9..176134528f 100644 --- a/src/gpu/GrGpu.cpp +++ b/src/gpu/GrGpu.cpp @@ -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; diff --git a/src/gpu/GrGpu.h b/src/gpu/GrGpu.h index 11f50831ca..0836ec87cc 100644 --- a/src/gpu/GrGpu.h +++ b/src/gpu/GrGpu.h @@ -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; diff --git a/src/gpu/GrGpuGL.cpp b/src/gpu/GrGpuGL.cpp index f2663689e1..339133fa8e 100644 --- a/src/gpu/GrGpuGL.cpp +++ b/src/gpu/GrGpuGL.cpp @@ -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; diff --git a/src/gpu/GrStencil.cpp b/src/gpu/GrStencil.cpp index 81b3b8d144..66249429d2 100644 --- a/src/gpu/GrStencil.cpp +++ b/src/gpu/GrStencil.cpp @@ -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, diff --git a/src/gpu/GrStencil.h b/src/gpu/GrStencil.h index 207a8316e8..78a156f9ea 100644 --- a/src/gpu/GrStencil.h +++ b/src/gpu/GrStencil.h @@ -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(&(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))