• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 "include/gpu/GrTypes.h"
13 
14 /**
15  * Gr uses the stencil buffer to implement complex clipping inside the
16  * OpsTask class. The OpsTask 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. OpsTask will ignore ref, mask, and writemask bits
19  * provided by clients that fall outside the user range.
20  *
21  * When code outside the OpsTask 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 #ifdef SK_ENABLE_STENCIL_CULLING_OHOS
35  // Stencil Culling use
36 static const int kStencilLayersMax = 6;
37 #endif
38 enum GrStencilFlags : int {
39     kDisabled_StencilFlag         = (1 << 0),
40     kTestAlwaysPasses_StencilFlag = (1 << 1),
41     kNoModifyStencil_StencilFlag  = (1 << 2),
42     kNoWrapOps_StencilFlag        = (1 << 3),
43     kSingleSided_StencilFlag      = (1 << 4),
44 
45     kLast_StencilFlag = kSingleSided_StencilFlag,
46     kAll_StencilFlags = kLast_StencilFlag | (kLast_StencilFlag - 1)
47 };
48 
49 template<typename TTest, typename TOp> struct GrTStencilFaceSettings {
50     uint16_t   fRef;        // Reference value for stencil test and ops.
51     TTest      fTest;       // Stencil test function, where fRef is on the left side.
52     uint16_t   fTestMask;   // Bitwise "and" to perform on fRef and stencil values before testing.
53                             // (e.g. (fRef & fTestMask) < (stencil & fTestMask))
54     TOp        fPassOp;     // Op to perform when the test passes.
55     TOp        fFailOp;     // Op to perform when the test fails.
56     uint16_t   fWriteMask;  // Indicates which bits in the stencil buffer should be updated.
57                             // (e.g. stencil = (newValue & fWriteMask) | (stencil & ~fWriteMask))
58 };
59 
60 enum class GrUserStencilTest : uint16_t {
61     // Tests that respect the clip bit. If a stencil clip is not in effect, the "IfInClip" is
62     // ignored and these only act on user bits.
63     kAlwaysIfInClip,
64     kEqualIfInClip,
65     kLessIfInClip,
66     kLEqualIfInClip,
67 
68     // Tests that ignore the clip bit. The client is responsible to ensure no color write occurs
69     // outside the clip if it is in use.
70     kAlways,
71     kNever,
72     kGreater,
73     kGEqual,
74     kLess,
75     kLEqual,
76     kEqual,
77     kNotEqual
78 };
79 constexpr static GrUserStencilTest kLastClippedStencilTest = GrUserStencilTest::kLEqualIfInClip;
80 constexpr static int kGrUserStencilTestCount = 1 + (int)GrUserStencilTest::kNotEqual;
81 
82 enum class GrUserStencilOp : uint8_t {
83     kKeep,
84 
85     // Ops that only modify user bits. These must not be paired with ops that modify the clip bit.
86     kZero,
87     kReplace, // Replace stencil value with fRef (only the bits enabled in fWriteMask).
88     kInvert,
89     kIncWrap,
90     kDecWrap,
91     // These two should only be used if wrap ops are not supported, or if the math is guaranteed
92     // to not overflow. The user bits may or may not clamp, depending on the state of non-user bits.
93     kIncMaybeClamp,
94     kDecMaybeClamp,
95 
96     // Ops that only modify the clip bit. These must not be paired with ops that modify user bits.
97     kZeroClipBit,
98     kSetClipBit,
99     kInvertClipBit,
100 
101     // Ops that modify both clip and user bits. These can only be paired with kKeep or each other.
102     kSetClipAndReplaceUserBits,
103     kZeroClipAndUserBits
104 };
105 constexpr static GrUserStencilOp kLastUserOnlyStencilOp = GrUserStencilOp::kDecMaybeClamp;
106 constexpr static GrUserStencilOp kLastClipOnlyStencilOp = GrUserStencilOp::kInvertClipBit;
107 constexpr static int kGrUserStencilOpCount = 1 + (int)GrUserStencilOp::kZeroClipAndUserBits;
108 
109 /**
110  * This struct is a compile-time constant representation of user stencil settings. It describes in
111  * abstract terms how a draw will use the stencil buffer. It gets ODR-used at runtime to define a
112  * draw's stencil settings, and is later translated into concrete settings when the pipeline is
113  * finalized.
114  */
115 struct GrUserStencilSettings {
116     typedef GrTStencilFaceSettings<GrUserStencilTest, GrUserStencilOp> Face;
117 
118     template<GrUserStencilTest, GrUserStencilOp PassOp, GrUserStencilOp FailOp> struct Attrs;
119 
120     // Unfortunately, this is the only way to pass template arguments to a constructor.
121     template<uint16_t Ref, GrUserStencilTest Test, uint16_t TestMask,
122              GrUserStencilOp PassOp, GrUserStencilOp FailOp, uint16_t WriteMask> struct Init {};
123 
124     template<uint16_t CWRef,            uint16_t CCWRef,
125              GrUserStencilTest CWTest,  GrUserStencilTest CCWTest,
126              uint16_t CWTestMask,       uint16_t CCWTestMask,
127              GrUserStencilOp CWPassOp,  GrUserStencilOp CCWPassOp,
128              GrUserStencilOp CWFailOp,  GrUserStencilOp CCWFailOp,
129              uint16_t CWWriteMask,      uint16_t CCWWriteMask> struct InitSeparate {};
130 
131     template<uint16_t Ref, GrUserStencilTest Test, uint16_t TestMask,
132              GrUserStencilOp PassOp, GrUserStencilOp FailOp, uint16_t WriteMask>
StaticInitGrUserStencilSettings133     constexpr static Init<Ref, Test, TestMask, PassOp, FailOp, WriteMask> StaticInit() {
134         return Init<Ref, Test, TestMask, PassOp, FailOp, WriteMask>();
135     }
136 
137     template<uint16_t CWRef,            uint16_t CCWRef,
138              GrUserStencilTest CWTest,  GrUserStencilTest CCWTest,
139              uint16_t CWTestMask,       uint16_t CCWTestMask,
140              GrUserStencilOp CWPassOp,  GrUserStencilOp CCWPassOp,
141              GrUserStencilOp CWFailOp,  GrUserStencilOp CCWFailOp,
142              uint16_t CWWriteMask,      uint16_t CCWWriteMask>
143     constexpr static InitSeparate<CWRef, CCWRef, CWTest, CCWTest, CWTestMask, CCWTestMask,
144                                   CWPassOp, CCWPassOp, CWFailOp, CCWFailOp, CWWriteMask,
StaticInitSeparateGrUserStencilSettings145                                   CCWWriteMask> StaticInitSeparate() {
146         return InitSeparate<CWRef, CCWRef, CWTest, CCWTest, CWTestMask, CCWTestMask,
147                             CWPassOp, CCWPassOp, CWFailOp, CCWFailOp, CWWriteMask, CCWWriteMask>();
148     }
149 
150     // We construct with template arguments in order to enforce that the struct be compile-time
151     // constant and to make use of static asserts.
152     template<uint16_t Ref, GrUserStencilTest Test, uint16_t TestMask,
153              GrUserStencilOp PassOp, GrUserStencilOp FailOp, uint16_t WriteMask,
154              typename Attrs = Attrs<Test, PassOp, FailOp> >
GrUserStencilSettingsGrUserStencilSettings155     constexpr explicit GrUserStencilSettings(
156             const Init<Ref, Test, TestMask, PassOp, FailOp, WriteMask>&)
157         : fCWFlags{(uint16_t)(Attrs::Flags(false) | kSingleSided_StencilFlag),
158                       (uint16_t)(Attrs::Flags(true) | kSingleSided_StencilFlag)}
159         , fCWFace{Ref, Test, Attrs::EffectiveTestMask(TestMask), PassOp, FailOp,
160                  Attrs::EffectiveWriteMask(WriteMask)}
161         , fCCWFlags{(uint16_t)(Attrs::Flags(false) | kSingleSided_StencilFlag),
162                      (uint16_t)(Attrs::Flags(true) | kSingleSided_StencilFlag)}
163         , fCCWFace{Ref, Test, Attrs::EffectiveTestMask(TestMask), PassOp, FailOp,
164                 Attrs::EffectiveWriteMask(WriteMask)} {
165     }
166 
167     template<uint16_t CWRef,            uint16_t CCWRef,
168              GrUserStencilTest CWTest,  GrUserStencilTest CCWTest,
169              uint16_t CWTestMask,       uint16_t CCWTestMask,
170              GrUserStencilOp CWPassOp,  GrUserStencilOp CCWPassOp,
171              GrUserStencilOp CWFailOp,  GrUserStencilOp CCWFailOp,
172              uint16_t CWWriteMask,      uint16_t CCWWriteMask,
173              typename CWAttrs = Attrs<CWTest, CWPassOp, CWFailOp>,
174              typename CCWAttrs = Attrs<CCWTest, CCWPassOp, CCWFailOp> >
GrUserStencilSettingsGrUserStencilSettings175     constexpr explicit GrUserStencilSettings(
176             const InitSeparate<CWRef, CCWRef, CWTest, CCWTest, CWTestMask, CCWTestMask,
177                                CWPassOp, CCWPassOp, CWFailOp, CCWFailOp, CWWriteMask,
178                                CCWWriteMask>&)
179         : fCWFlags{CWAttrs::Flags(false), CWAttrs::Flags(true)}
180         , fCWFace{CWRef, CWTest, CWAttrs::EffectiveTestMask(CWTestMask), CWPassOp, CWFailOp,
181                  CWAttrs::EffectiveWriteMask(CWWriteMask)}
182         , fCCWFlags{CCWAttrs::Flags(false), CCWAttrs::Flags(true)}
183         , fCCWFace{CCWRef, CCWTest, CCWAttrs::EffectiveTestMask(CCWTestMask), CCWPassOp, CCWFailOp,
184                 CCWAttrs::EffectiveWriteMask(CCWWriteMask)} {}
185 
186     // This struct can only be constructed with static initializers.
187     GrUserStencilSettings() = delete;
188     GrUserStencilSettings(const GrUserStencilSettings&) = delete;
189 
flagsGrUserStencilSettings190     uint16_t flags(bool hasStencilClip) const {
191         return fCWFlags[hasStencilClip] & fCCWFlags[hasStencilClip];
192     }
isDisabledGrUserStencilSettings193     bool isDisabled(bool hasStencilClip) const {
194         return this->flags(hasStencilClip) & kDisabled_StencilFlag;
195     }
testAlwaysPassesGrUserStencilSettings196     bool testAlwaysPasses(bool hasStencilClip) const {
197         return this->flags(hasStencilClip) & kTestAlwaysPasses_StencilFlag;
198     }
isTwoSidedGrUserStencilSettings199     bool isTwoSided(bool hasStencilClip) const {
200         return !(this->flags(hasStencilClip) & kSingleSided_StencilFlag);
201     }
usesWrapOpGrUserStencilSettings202     bool usesWrapOp(bool hasStencilClip) const {
203         return !(this->flags(hasStencilClip) & kNoWrapOps_StencilFlag);
204     }
205 
206     const uint16_t   fCWFlags[2]; // cwFlagsForDraw = fCWFlags[hasStencilClip].
207     const Face       fCWFace;
208     const uint16_t   fCCWFlags[2]; // ccwFlagsForDraw = fCCWFlags[hasStencilClip].
209     const Face       fCCWFace;
210 
211     static const GrUserStencilSettings& kUnused;
212 #ifdef SK_ENABLE_STENCIL_CULLING_OHOS
213     static const GrUserStencilSettings *kGE[kStencilLayersMax];
214 #endif
215 
isUnusedGrUserStencilSettings216     bool isUnused() const { return this == &kUnused; }
217 };
218 
219 template<GrUserStencilTest Test, GrUserStencilOp PassOp, GrUserStencilOp FailOp>
220 struct GrUserStencilSettings::Attrs {
221     // Ensure an op that only modifies user bits isn't paired with one that modifies clip bits.
222     static_assert(GrUserStencilOp::kKeep == PassOp || GrUserStencilOp::kKeep == FailOp ||
223                   (PassOp <= kLastUserOnlyStencilOp) == (FailOp <= kLastUserOnlyStencilOp));
224     // Ensure an op that only modifies clip bits isn't paired with one that modifies clip and user.
225     static_assert(GrUserStencilOp::kKeep == PassOp || GrUserStencilOp::kKeep == FailOp ||
226                   (PassOp <= kLastClipOnlyStencilOp) == (FailOp <= kLastClipOnlyStencilOp));
227 
TestAlwaysPassesAttrs228     constexpr static bool TestAlwaysPasses(bool hasStencilClip) {
229         return (!hasStencilClip && GrUserStencilTest::kAlwaysIfInClip == Test) ||
230                 GrUserStencilTest::kAlways == Test;
231     }
DoesNotModifyStencilAttrs232     constexpr static bool DoesNotModifyStencil(bool hasStencilClip) {
233         return (GrUserStencilTest::kNever == Test || GrUserStencilOp::kKeep == PassOp) &&
234                 (TestAlwaysPasses(hasStencilClip) || GrUserStencilOp::kKeep == FailOp);
235     }
IsDisabledAttrs236     constexpr static bool IsDisabled(bool hasStencilClip) {
237         return TestAlwaysPasses(hasStencilClip) && DoesNotModifyStencil(hasStencilClip);
238     }
UsesWrapOpsAttrs239     constexpr static bool UsesWrapOps() {
240         return GrUserStencilOp::kIncWrap == PassOp || GrUserStencilOp::kDecWrap == PassOp ||
241                GrUserStencilOp::kIncWrap == FailOp || GrUserStencilOp::kDecWrap == FailOp;
242     }
TestIgnoresRefAttrs243     constexpr static bool TestIgnoresRef() {
244         return (GrUserStencilTest::kAlwaysIfInClip == Test || GrUserStencilTest::kAlways == Test ||
245                 GrUserStencilTest::kNever == Test);
246     }
FlagsAttrs247     constexpr static uint16_t Flags(bool hasStencilClip) {
248         return (IsDisabled(hasStencilClip) ? kDisabled_StencilFlag : 0) |
249                (TestAlwaysPasses(hasStencilClip) ? kTestAlwaysPasses_StencilFlag : 0) |
250                (DoesNotModifyStencil(hasStencilClip) ? kNoModifyStencil_StencilFlag : 0) |
251                (UsesWrapOps() ? 0 : kNoWrapOps_StencilFlag);
252     }
EffectiveTestMaskAttrs253     constexpr static uint16_t EffectiveTestMask(uint16_t testMask) {
254         return TestIgnoresRef() ? 0 : testMask;
255     }
EffectiveWriteMaskAttrs256     constexpr static uint16_t EffectiveWriteMask(uint16_t writeMask) {
257         // We don't modify the mask differently when hasStencilClip=false because either the entire
258         // face gets disabled in that case (e.g. Test=kAlwaysIfInClip, PassOp=kKeep), or else the
259         // effective mask stays the same either way.
260         return DoesNotModifyStencil(true) ? 0 : writeMask;
261     }
262 };
263 
264 #endif
265