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