1*c8dee2aaSAndroid Build Coastguard Worker /* 2*c8dee2aaSAndroid Build Coastguard Worker * Copyright 2016 Google Inc. 3*c8dee2aaSAndroid Build Coastguard Worker * 4*c8dee2aaSAndroid Build Coastguard Worker * Use of this source code is governed by a BSD-style license that can be 5*c8dee2aaSAndroid Build Coastguard Worker * found in the LICENSE file. 6*c8dee2aaSAndroid Build Coastguard Worker */ 7*c8dee2aaSAndroid Build Coastguard Worker 8*c8dee2aaSAndroid Build Coastguard Worker 9*c8dee2aaSAndroid Build Coastguard Worker #ifndef GrUserStencilSettings_DEFINED 10*c8dee2aaSAndroid Build Coastguard Worker #define GrUserStencilSettings_DEFINED 11*c8dee2aaSAndroid Build Coastguard Worker 12*c8dee2aaSAndroid Build Coastguard Worker #include "include/gpu/ganesh/GrTypes.h" // IWYU pragma: keep 13*c8dee2aaSAndroid Build Coastguard Worker 14*c8dee2aaSAndroid Build Coastguard Worker #include <cstdint> 15*c8dee2aaSAndroid Build Coastguard Worker 16*c8dee2aaSAndroid Build Coastguard Worker /** 17*c8dee2aaSAndroid Build Coastguard Worker * Gr uses the stencil buffer to implement complex clipping inside the 18*c8dee2aaSAndroid Build Coastguard Worker * OpsTask class. The OpsTask makes a subset of the stencil buffer 19*c8dee2aaSAndroid Build Coastguard Worker * bits available for other uses by external code (user bits). Client code can 20*c8dee2aaSAndroid Build Coastguard Worker * modify these bits. OpsTask will ignore ref, mask, and writemask bits 21*c8dee2aaSAndroid Build Coastguard Worker * provided by clients that fall outside the user range. 22*c8dee2aaSAndroid Build Coastguard Worker * 23*c8dee2aaSAndroid Build Coastguard Worker * When code outside the OpsTask class uses the stencil buffer the contract 24*c8dee2aaSAndroid Build Coastguard Worker * is as follows: 25*c8dee2aaSAndroid Build Coastguard Worker * 26*c8dee2aaSAndroid Build Coastguard Worker * > Normal stencil funcs allow the client to pass / fail regardless of the 27*c8dee2aaSAndroid Build Coastguard Worker * reserved clip bits. 28*c8dee2aaSAndroid Build Coastguard Worker * > Additional functions allow a test against the clip along with a limited 29*c8dee2aaSAndroid Build Coastguard Worker * set of tests against the user bits. 30*c8dee2aaSAndroid Build Coastguard Worker * > Client can assume all user bits are zero initially. 31*c8dee2aaSAndroid Build Coastguard Worker * > Client must ensure that after all its passes are finished it has only 32*c8dee2aaSAndroid Build Coastguard Worker * written to the color buffer in the region inside the clip. Furthermore, it 33*c8dee2aaSAndroid Build Coastguard Worker * must zero all user bits that were modifed (both inside and outside the 34*c8dee2aaSAndroid Build Coastguard Worker * clip). 35*c8dee2aaSAndroid Build Coastguard Worker */ 36*c8dee2aaSAndroid Build Coastguard Worker 37*c8dee2aaSAndroid Build Coastguard Worker enum GrStencilFlags : int { 38*c8dee2aaSAndroid Build Coastguard Worker kDisabled_StencilFlag = (1 << 0), 39*c8dee2aaSAndroid Build Coastguard Worker kTestAlwaysPasses_StencilFlag = (1 << 1), 40*c8dee2aaSAndroid Build Coastguard Worker kNoModifyStencil_StencilFlag = (1 << 2), 41*c8dee2aaSAndroid Build Coastguard Worker kNoWrapOps_StencilFlag = (1 << 3), 42*c8dee2aaSAndroid Build Coastguard Worker kSingleSided_StencilFlag = (1 << 4), 43*c8dee2aaSAndroid Build Coastguard Worker 44*c8dee2aaSAndroid Build Coastguard Worker kLast_StencilFlag = kSingleSided_StencilFlag, 45*c8dee2aaSAndroid Build Coastguard Worker kAll_StencilFlags = kLast_StencilFlag | (kLast_StencilFlag - 1) 46*c8dee2aaSAndroid Build Coastguard Worker }; 47*c8dee2aaSAndroid Build Coastguard Worker 48*c8dee2aaSAndroid Build Coastguard Worker template<typename TTest, typename TOp> struct GrTStencilFaceSettings { 49*c8dee2aaSAndroid Build Coastguard Worker uint16_t fRef; // Reference value for stencil test and ops. 50*c8dee2aaSAndroid Build Coastguard Worker TTest fTest; // Stencil test function, where fRef is on the left side. 51*c8dee2aaSAndroid Build Coastguard Worker uint16_t fTestMask; // Bitwise "and" to perform on fRef and stencil values before testing. 52*c8dee2aaSAndroid Build Coastguard Worker // (e.g. (fRef & fTestMask) < (stencil & fTestMask)) 53*c8dee2aaSAndroid Build Coastguard Worker TOp fPassOp; // Op to perform when the test passes. 54*c8dee2aaSAndroid Build Coastguard Worker TOp fFailOp; // Op to perform when the test fails. 55*c8dee2aaSAndroid Build Coastguard Worker uint16_t fWriteMask; // Indicates which bits in the stencil buffer should be updated. 56*c8dee2aaSAndroid Build Coastguard Worker // (e.g. stencil = (newValue & fWriteMask) | (stencil & ~fWriteMask)) 57*c8dee2aaSAndroid Build Coastguard Worker }; 58*c8dee2aaSAndroid Build Coastguard Worker 59*c8dee2aaSAndroid Build Coastguard Worker enum class GrUserStencilTest : uint16_t { 60*c8dee2aaSAndroid Build Coastguard Worker // Tests that respect the clip bit. If a stencil clip is not in effect, the "IfInClip" is 61*c8dee2aaSAndroid Build Coastguard Worker // ignored and these only act on user bits. 62*c8dee2aaSAndroid Build Coastguard Worker kAlwaysIfInClip, 63*c8dee2aaSAndroid Build Coastguard Worker kEqualIfInClip, 64*c8dee2aaSAndroid Build Coastguard Worker kLessIfInClip, 65*c8dee2aaSAndroid Build Coastguard Worker kLEqualIfInClip, 66*c8dee2aaSAndroid Build Coastguard Worker 67*c8dee2aaSAndroid Build Coastguard Worker // Tests that ignore the clip bit. The client is responsible to ensure no color write occurs 68*c8dee2aaSAndroid Build Coastguard Worker // outside the clip if it is in use. 69*c8dee2aaSAndroid Build Coastguard Worker kAlways, 70*c8dee2aaSAndroid Build Coastguard Worker kNever, 71*c8dee2aaSAndroid Build Coastguard Worker kGreater, 72*c8dee2aaSAndroid Build Coastguard Worker kGEqual, 73*c8dee2aaSAndroid Build Coastguard Worker kLess, 74*c8dee2aaSAndroid Build Coastguard Worker kLEqual, 75*c8dee2aaSAndroid Build Coastguard Worker kEqual, 76*c8dee2aaSAndroid Build Coastguard Worker kNotEqual 77*c8dee2aaSAndroid Build Coastguard Worker }; 78*c8dee2aaSAndroid Build Coastguard Worker constexpr static GrUserStencilTest kLastClippedStencilTest = GrUserStencilTest::kLEqualIfInClip; 79*c8dee2aaSAndroid Build Coastguard Worker constexpr static int kGrUserStencilTestCount = 1 + (int)GrUserStencilTest::kNotEqual; 80*c8dee2aaSAndroid Build Coastguard Worker 81*c8dee2aaSAndroid Build Coastguard Worker enum class GrUserStencilOp : uint8_t { 82*c8dee2aaSAndroid Build Coastguard Worker kKeep, 83*c8dee2aaSAndroid Build Coastguard Worker 84*c8dee2aaSAndroid Build Coastguard Worker // Ops that only modify user bits. These must not be paired with ops that modify the clip bit. 85*c8dee2aaSAndroid Build Coastguard Worker kZero, 86*c8dee2aaSAndroid Build Coastguard Worker kReplace, // Replace stencil value with fRef (only the bits enabled in fWriteMask). 87*c8dee2aaSAndroid Build Coastguard Worker kInvert, 88*c8dee2aaSAndroid Build Coastguard Worker kIncWrap, 89*c8dee2aaSAndroid Build Coastguard Worker kDecWrap, 90*c8dee2aaSAndroid Build Coastguard Worker // These two should only be used if wrap ops are not supported, or if the math is guaranteed 91*c8dee2aaSAndroid Build Coastguard Worker // to not overflow. The user bits may or may not clamp, depending on the state of non-user bits. 92*c8dee2aaSAndroid Build Coastguard Worker kIncMaybeClamp, 93*c8dee2aaSAndroid Build Coastguard Worker kDecMaybeClamp, 94*c8dee2aaSAndroid Build Coastguard Worker 95*c8dee2aaSAndroid Build Coastguard Worker // Ops that only modify the clip bit. These must not be paired with ops that modify user bits. 96*c8dee2aaSAndroid Build Coastguard Worker kZeroClipBit, 97*c8dee2aaSAndroid Build Coastguard Worker kSetClipBit, 98*c8dee2aaSAndroid Build Coastguard Worker kInvertClipBit, 99*c8dee2aaSAndroid Build Coastguard Worker 100*c8dee2aaSAndroid Build Coastguard Worker // Ops that modify both clip and user bits. These can only be paired with kKeep or each other. 101*c8dee2aaSAndroid Build Coastguard Worker kSetClipAndReplaceUserBits, 102*c8dee2aaSAndroid Build Coastguard Worker kZeroClipAndUserBits 103*c8dee2aaSAndroid Build Coastguard Worker }; 104*c8dee2aaSAndroid Build Coastguard Worker constexpr static GrUserStencilOp kLastUserOnlyStencilOp = GrUserStencilOp::kDecMaybeClamp; 105*c8dee2aaSAndroid Build Coastguard Worker constexpr static GrUserStencilOp kLastClipOnlyStencilOp = GrUserStencilOp::kInvertClipBit; 106*c8dee2aaSAndroid Build Coastguard Worker constexpr static int kGrUserStencilOpCount = 1 + (int)GrUserStencilOp::kZeroClipAndUserBits; 107*c8dee2aaSAndroid Build Coastguard Worker 108*c8dee2aaSAndroid Build Coastguard Worker /** 109*c8dee2aaSAndroid Build Coastguard Worker * This struct is a compile-time constant representation of user stencil settings. It describes in 110*c8dee2aaSAndroid Build Coastguard Worker * abstract terms how a draw will use the stencil buffer. It gets ODR-used at runtime to define a 111*c8dee2aaSAndroid Build Coastguard Worker * draw's stencil settings, and is later translated into concrete settings when the pipeline is 112*c8dee2aaSAndroid Build Coastguard Worker * finalized. 113*c8dee2aaSAndroid Build Coastguard Worker */ 114*c8dee2aaSAndroid Build Coastguard Worker struct GrUserStencilSettings { 115*c8dee2aaSAndroid Build Coastguard Worker typedef GrTStencilFaceSettings<GrUserStencilTest, GrUserStencilOp> Face; 116*c8dee2aaSAndroid Build Coastguard Worker 117*c8dee2aaSAndroid Build Coastguard Worker template<GrUserStencilTest, GrUserStencilOp PassOp, GrUserStencilOp FailOp> struct Attrs; 118*c8dee2aaSAndroid Build Coastguard Worker 119*c8dee2aaSAndroid Build Coastguard Worker // Unfortunately, this is the only way to pass template arguments to a constructor. 120*c8dee2aaSAndroid Build Coastguard Worker template<uint16_t Ref, GrUserStencilTest Test, uint16_t TestMask, 121*c8dee2aaSAndroid Build Coastguard Worker GrUserStencilOp PassOp, GrUserStencilOp FailOp, uint16_t WriteMask> struct Init {}; 122*c8dee2aaSAndroid Build Coastguard Worker 123*c8dee2aaSAndroid Build Coastguard Worker template<uint16_t CWRef, uint16_t CCWRef, 124*c8dee2aaSAndroid Build Coastguard Worker GrUserStencilTest CWTest, GrUserStencilTest CCWTest, 125*c8dee2aaSAndroid Build Coastguard Worker uint16_t CWTestMask, uint16_t CCWTestMask, 126*c8dee2aaSAndroid Build Coastguard Worker GrUserStencilOp CWPassOp, GrUserStencilOp CCWPassOp, 127*c8dee2aaSAndroid Build Coastguard Worker GrUserStencilOp CWFailOp, GrUserStencilOp CCWFailOp, 128*c8dee2aaSAndroid Build Coastguard Worker uint16_t CWWriteMask, uint16_t CCWWriteMask> struct InitSeparate {}; 129*c8dee2aaSAndroid Build Coastguard Worker 130*c8dee2aaSAndroid Build Coastguard Worker template<uint16_t Ref, GrUserStencilTest Test, uint16_t TestMask, 131*c8dee2aaSAndroid Build Coastguard Worker GrUserStencilOp PassOp, GrUserStencilOp FailOp, uint16_t WriteMask> StaticInitGrUserStencilSettings132*c8dee2aaSAndroid Build Coastguard Worker constexpr static Init<Ref, Test, TestMask, PassOp, FailOp, WriteMask> StaticInit() { 133*c8dee2aaSAndroid Build Coastguard Worker return Init<Ref, Test, TestMask, PassOp, FailOp, WriteMask>(); 134*c8dee2aaSAndroid Build Coastguard Worker } 135*c8dee2aaSAndroid Build Coastguard Worker 136*c8dee2aaSAndroid Build Coastguard Worker template<uint16_t CWRef, uint16_t CCWRef, 137*c8dee2aaSAndroid Build Coastguard Worker GrUserStencilTest CWTest, GrUserStencilTest CCWTest, 138*c8dee2aaSAndroid Build Coastguard Worker uint16_t CWTestMask, uint16_t CCWTestMask, 139*c8dee2aaSAndroid Build Coastguard Worker GrUserStencilOp CWPassOp, GrUserStencilOp CCWPassOp, 140*c8dee2aaSAndroid Build Coastguard Worker GrUserStencilOp CWFailOp, GrUserStencilOp CCWFailOp, 141*c8dee2aaSAndroid Build Coastguard Worker uint16_t CWWriteMask, uint16_t CCWWriteMask> 142*c8dee2aaSAndroid Build Coastguard Worker constexpr static InitSeparate<CWRef, CCWRef, CWTest, CCWTest, CWTestMask, CCWTestMask, 143*c8dee2aaSAndroid Build Coastguard Worker CWPassOp, CCWPassOp, CWFailOp, CCWFailOp, CWWriteMask, StaticInitSeparateGrUserStencilSettings144*c8dee2aaSAndroid Build Coastguard Worker CCWWriteMask> StaticInitSeparate() { 145*c8dee2aaSAndroid Build Coastguard Worker return InitSeparate<CWRef, CCWRef, CWTest, CCWTest, CWTestMask, CCWTestMask, 146*c8dee2aaSAndroid Build Coastguard Worker CWPassOp, CCWPassOp, CWFailOp, CCWFailOp, CWWriteMask, CCWWriteMask>(); 147*c8dee2aaSAndroid Build Coastguard Worker } 148*c8dee2aaSAndroid Build Coastguard Worker 149*c8dee2aaSAndroid Build Coastguard Worker // We construct with template arguments in order to enforce that the struct be compile-time 150*c8dee2aaSAndroid Build Coastguard Worker // constant and to make use of static asserts. 151*c8dee2aaSAndroid Build Coastguard Worker template<uint16_t Ref, GrUserStencilTest Test, uint16_t TestMask, 152*c8dee2aaSAndroid Build Coastguard Worker GrUserStencilOp PassOp, GrUserStencilOp FailOp, uint16_t WriteMask, 153*c8dee2aaSAndroid Build Coastguard Worker typename Attrs = Attrs<Test, PassOp, FailOp> > GrUserStencilSettingsGrUserStencilSettings154*c8dee2aaSAndroid Build Coastguard Worker constexpr explicit GrUserStencilSettings( 155*c8dee2aaSAndroid Build Coastguard Worker const Init<Ref, Test, TestMask, PassOp, FailOp, WriteMask>&) 156*c8dee2aaSAndroid Build Coastguard Worker : fCWFlags{(uint16_t)(Attrs::Flags(false) | kSingleSided_StencilFlag), 157*c8dee2aaSAndroid Build Coastguard Worker (uint16_t)(Attrs::Flags(true) | kSingleSided_StencilFlag)} 158*c8dee2aaSAndroid Build Coastguard Worker , fCWFace{Ref, Test, Attrs::EffectiveTestMask(TestMask), PassOp, FailOp, 159*c8dee2aaSAndroid Build Coastguard Worker Attrs::EffectiveWriteMask(WriteMask)} 160*c8dee2aaSAndroid Build Coastguard Worker , fCCWFlags{(uint16_t)(Attrs::Flags(false) | kSingleSided_StencilFlag), 161*c8dee2aaSAndroid Build Coastguard Worker (uint16_t)(Attrs::Flags(true) | kSingleSided_StencilFlag)} 162*c8dee2aaSAndroid Build Coastguard Worker , fCCWFace{Ref, Test, Attrs::EffectiveTestMask(TestMask), PassOp, FailOp, 163*c8dee2aaSAndroid Build Coastguard Worker Attrs::EffectiveWriteMask(WriteMask)} { 164*c8dee2aaSAndroid Build Coastguard Worker } 165*c8dee2aaSAndroid Build Coastguard Worker 166*c8dee2aaSAndroid Build Coastguard Worker template<uint16_t CWRef, uint16_t CCWRef, 167*c8dee2aaSAndroid Build Coastguard Worker GrUserStencilTest CWTest, GrUserStencilTest CCWTest, 168*c8dee2aaSAndroid Build Coastguard Worker uint16_t CWTestMask, uint16_t CCWTestMask, 169*c8dee2aaSAndroid Build Coastguard Worker GrUserStencilOp CWPassOp, GrUserStencilOp CCWPassOp, 170*c8dee2aaSAndroid Build Coastguard Worker GrUserStencilOp CWFailOp, GrUserStencilOp CCWFailOp, 171*c8dee2aaSAndroid Build Coastguard Worker uint16_t CWWriteMask, uint16_t CCWWriteMask, 172*c8dee2aaSAndroid Build Coastguard Worker typename CWAttrs = Attrs<CWTest, CWPassOp, CWFailOp>, 173*c8dee2aaSAndroid Build Coastguard Worker typename CCWAttrs = Attrs<CCWTest, CCWPassOp, CCWFailOp> > GrUserStencilSettingsGrUserStencilSettings174*c8dee2aaSAndroid Build Coastguard Worker constexpr explicit GrUserStencilSettings( 175*c8dee2aaSAndroid Build Coastguard Worker const InitSeparate<CWRef, CCWRef, CWTest, CCWTest, CWTestMask, CCWTestMask, 176*c8dee2aaSAndroid Build Coastguard Worker CWPassOp, CCWPassOp, CWFailOp, CCWFailOp, CWWriteMask, 177*c8dee2aaSAndroid Build Coastguard Worker CCWWriteMask>&) 178*c8dee2aaSAndroid Build Coastguard Worker : fCWFlags{CWAttrs::Flags(false), CWAttrs::Flags(true)} 179*c8dee2aaSAndroid Build Coastguard Worker , fCWFace{CWRef, CWTest, CWAttrs::EffectiveTestMask(CWTestMask), CWPassOp, CWFailOp, 180*c8dee2aaSAndroid Build Coastguard Worker CWAttrs::EffectiveWriteMask(CWWriteMask)} 181*c8dee2aaSAndroid Build Coastguard Worker , fCCWFlags{CCWAttrs::Flags(false), CCWAttrs::Flags(true)} 182*c8dee2aaSAndroid Build Coastguard Worker , fCCWFace{CCWRef, CCWTest, CCWAttrs::EffectiveTestMask(CCWTestMask), CCWPassOp, CCWFailOp, 183*c8dee2aaSAndroid Build Coastguard Worker CCWAttrs::EffectiveWriteMask(CCWWriteMask)} {} 184*c8dee2aaSAndroid Build Coastguard Worker 185*c8dee2aaSAndroid Build Coastguard Worker // This struct can only be constructed with static initializers. 186*c8dee2aaSAndroid Build Coastguard Worker GrUserStencilSettings() = delete; 187*c8dee2aaSAndroid Build Coastguard Worker GrUserStencilSettings(const GrUserStencilSettings&) = delete; 188*c8dee2aaSAndroid Build Coastguard Worker flagsGrUserStencilSettings189*c8dee2aaSAndroid Build Coastguard Worker uint16_t flags(bool hasStencilClip) const { 190*c8dee2aaSAndroid Build Coastguard Worker return fCWFlags[hasStencilClip] & fCCWFlags[hasStencilClip]; 191*c8dee2aaSAndroid Build Coastguard Worker } isDisabledGrUserStencilSettings192*c8dee2aaSAndroid Build Coastguard Worker bool isDisabled(bool hasStencilClip) const { 193*c8dee2aaSAndroid Build Coastguard Worker return this->flags(hasStencilClip) & kDisabled_StencilFlag; 194*c8dee2aaSAndroid Build Coastguard Worker } testAlwaysPassesGrUserStencilSettings195*c8dee2aaSAndroid Build Coastguard Worker bool testAlwaysPasses(bool hasStencilClip) const { 196*c8dee2aaSAndroid Build Coastguard Worker return this->flags(hasStencilClip) & kTestAlwaysPasses_StencilFlag; 197*c8dee2aaSAndroid Build Coastguard Worker } isTwoSidedGrUserStencilSettings198*c8dee2aaSAndroid Build Coastguard Worker bool isTwoSided(bool hasStencilClip) const { 199*c8dee2aaSAndroid Build Coastguard Worker return !(this->flags(hasStencilClip) & kSingleSided_StencilFlag); 200*c8dee2aaSAndroid Build Coastguard Worker } usesWrapOpGrUserStencilSettings201*c8dee2aaSAndroid Build Coastguard Worker bool usesWrapOp(bool hasStencilClip) const { 202*c8dee2aaSAndroid Build Coastguard Worker return !(this->flags(hasStencilClip) & kNoWrapOps_StencilFlag); 203*c8dee2aaSAndroid Build Coastguard Worker } 204*c8dee2aaSAndroid Build Coastguard Worker 205*c8dee2aaSAndroid Build Coastguard Worker const uint16_t fCWFlags[2]; // cwFlagsForDraw = fCWFlags[hasStencilClip]. 206*c8dee2aaSAndroid Build Coastguard Worker const Face fCWFace; 207*c8dee2aaSAndroid Build Coastguard Worker const uint16_t fCCWFlags[2]; // ccwFlagsForDraw = fCCWFlags[hasStencilClip]. 208*c8dee2aaSAndroid Build Coastguard Worker const Face fCCWFace; 209*c8dee2aaSAndroid Build Coastguard Worker 210*c8dee2aaSAndroid Build Coastguard Worker static const GrUserStencilSettings& kUnused; 211*c8dee2aaSAndroid Build Coastguard Worker isUnusedGrUserStencilSettings212*c8dee2aaSAndroid Build Coastguard Worker bool isUnused() const { return this == &kUnused; } 213*c8dee2aaSAndroid Build Coastguard Worker }; 214*c8dee2aaSAndroid Build Coastguard Worker 215*c8dee2aaSAndroid Build Coastguard Worker template<GrUserStencilTest Test, GrUserStencilOp PassOp, GrUserStencilOp FailOp> 216*c8dee2aaSAndroid Build Coastguard Worker struct GrUserStencilSettings::Attrs { 217*c8dee2aaSAndroid Build Coastguard Worker // Ensure an op that only modifies user bits isn't paired with one that modifies clip bits. 218*c8dee2aaSAndroid Build Coastguard Worker static_assert(GrUserStencilOp::kKeep == PassOp || GrUserStencilOp::kKeep == FailOp || 219*c8dee2aaSAndroid Build Coastguard Worker (PassOp <= kLastUserOnlyStencilOp) == (FailOp <= kLastUserOnlyStencilOp)); 220*c8dee2aaSAndroid Build Coastguard Worker // Ensure an op that only modifies clip bits isn't paired with one that modifies clip and user. 221*c8dee2aaSAndroid Build Coastguard Worker static_assert(GrUserStencilOp::kKeep == PassOp || GrUserStencilOp::kKeep == FailOp || 222*c8dee2aaSAndroid Build Coastguard Worker (PassOp <= kLastClipOnlyStencilOp) == (FailOp <= kLastClipOnlyStencilOp)); 223*c8dee2aaSAndroid Build Coastguard Worker TestAlwaysPassesAttrs224*c8dee2aaSAndroid Build Coastguard Worker constexpr static bool TestAlwaysPasses(bool hasStencilClip) { 225*c8dee2aaSAndroid Build Coastguard Worker return (!hasStencilClip && GrUserStencilTest::kAlwaysIfInClip == Test) || 226*c8dee2aaSAndroid Build Coastguard Worker GrUserStencilTest::kAlways == Test; 227*c8dee2aaSAndroid Build Coastguard Worker } DoesNotModifyStencilAttrs228*c8dee2aaSAndroid Build Coastguard Worker constexpr static bool DoesNotModifyStencil(bool hasStencilClip) { 229*c8dee2aaSAndroid Build Coastguard Worker return (GrUserStencilTest::kNever == Test || GrUserStencilOp::kKeep == PassOp) && 230*c8dee2aaSAndroid Build Coastguard Worker (TestAlwaysPasses(hasStencilClip) || GrUserStencilOp::kKeep == FailOp); 231*c8dee2aaSAndroid Build Coastguard Worker } IsDisabledAttrs232*c8dee2aaSAndroid Build Coastguard Worker constexpr static bool IsDisabled(bool hasStencilClip) { 233*c8dee2aaSAndroid Build Coastguard Worker return TestAlwaysPasses(hasStencilClip) && DoesNotModifyStencil(hasStencilClip); 234*c8dee2aaSAndroid Build Coastguard Worker } UsesWrapOpsAttrs235*c8dee2aaSAndroid Build Coastguard Worker constexpr static bool UsesWrapOps() { 236*c8dee2aaSAndroid Build Coastguard Worker return GrUserStencilOp::kIncWrap == PassOp || GrUserStencilOp::kDecWrap == PassOp || 237*c8dee2aaSAndroid Build Coastguard Worker GrUserStencilOp::kIncWrap == FailOp || GrUserStencilOp::kDecWrap == FailOp; 238*c8dee2aaSAndroid Build Coastguard Worker } TestIgnoresRefAttrs239*c8dee2aaSAndroid Build Coastguard Worker constexpr static bool TestIgnoresRef() { 240*c8dee2aaSAndroid Build Coastguard Worker return (GrUserStencilTest::kAlwaysIfInClip == Test || GrUserStencilTest::kAlways == Test || 241*c8dee2aaSAndroid Build Coastguard Worker GrUserStencilTest::kNever == Test); 242*c8dee2aaSAndroid Build Coastguard Worker } FlagsAttrs243*c8dee2aaSAndroid Build Coastguard Worker constexpr static uint16_t Flags(bool hasStencilClip) { 244*c8dee2aaSAndroid Build Coastguard Worker return (IsDisabled(hasStencilClip) ? kDisabled_StencilFlag : 0) | 245*c8dee2aaSAndroid Build Coastguard Worker (TestAlwaysPasses(hasStencilClip) ? kTestAlwaysPasses_StencilFlag : 0) | 246*c8dee2aaSAndroid Build Coastguard Worker (DoesNotModifyStencil(hasStencilClip) ? kNoModifyStencil_StencilFlag : 0) | 247*c8dee2aaSAndroid Build Coastguard Worker (UsesWrapOps() ? 0 : kNoWrapOps_StencilFlag); 248*c8dee2aaSAndroid Build Coastguard Worker } EffectiveTestMaskAttrs249*c8dee2aaSAndroid Build Coastguard Worker constexpr static uint16_t EffectiveTestMask(uint16_t testMask) { 250*c8dee2aaSAndroid Build Coastguard Worker return TestIgnoresRef() ? 0 : testMask; 251*c8dee2aaSAndroid Build Coastguard Worker } EffectiveWriteMaskAttrs252*c8dee2aaSAndroid Build Coastguard Worker constexpr static uint16_t EffectiveWriteMask(uint16_t writeMask) { 253*c8dee2aaSAndroid Build Coastguard Worker // We don't modify the mask differently when hasStencilClip=false because either the entire 254*c8dee2aaSAndroid Build Coastguard Worker // face gets disabled in that case (e.g. Test=kAlwaysIfInClip, PassOp=kKeep), or else the 255*c8dee2aaSAndroid Build Coastguard Worker // effective mask stays the same either way. 256*c8dee2aaSAndroid Build Coastguard Worker return DoesNotModifyStencil(true) ? 0 : writeMask; 257*c8dee2aaSAndroid Build Coastguard Worker } 258*c8dee2aaSAndroid Build Coastguard Worker }; 259*c8dee2aaSAndroid Build Coastguard Worker 260*c8dee2aaSAndroid Build Coastguard Worker #endif 261