Flutter Engine
The Flutter Engine
GrUserStencilSettings.h
Go to the documentation of this file.
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
35enum GrStencilFlags : int {
41
44};
45
46template<typename TTest, typename TOp> struct GrTStencilFaceSettings {
47 uint16_t fRef; // Reference value for stencil test and ops.
48 TTest fTest; // Stencil test function, where fRef is on the left side.
49 uint16_t fTestMask; // Bitwise "and" to perform on fRef and stencil values before testing.
50 // (e.g. (fRef & fTestMask) < (stencil & fTestMask))
51 TOp fPassOp; // Op to perform when the test passes.
52 TOp fFailOp; // Op to perform when the test fails.
53 uint16_t fWriteMask; // Indicates which bits in the stencil buffer should be updated.
54 // (e.g. stencil = (newValue & fWriteMask) | (stencil & ~fWriteMask))
55};
56
57enum class GrUserStencilTest : uint16_t {
58 // Tests that respect the clip bit. If a stencil clip is not in effect, the "IfInClip" is
59 // ignored and these only act on user bits.
64
65 // Tests that ignore the clip bit. The client is responsible to ensure no color write occurs
66 // outside the clip if it is in use.
67 kAlways,
68 kNever,
69 kGreater,
70 kGEqual,
71 kLess,
72 kLEqual,
73 kEqual,
74 kNotEqual
75};
78
79enum class GrUserStencilOp : uint8_t {
80 kKeep,
81
82 // Ops that only modify user bits. These must not be paired with ops that modify the clip bit.
83 kZero,
84 kReplace, // Replace stencil value with fRef (only the bits enabled in fWriteMask).
85 kInvert,
88 // These two should only be used if wrap ops are not supported, or if the math is guaranteed
89 // to not overflow. The user bits may or may not clamp, depending on the state of non-user bits.
92
93 // Ops that only modify the clip bit. These must not be paired with ops that modify user bits.
97
98 // Ops that modify both clip and user bits. These can only be paired with kKeep or each other.
101};
105
106/**
107 * This struct is a compile-time constant representation of user stencil settings. It describes in
108 * abstract terms how a draw will use the stencil buffer. It gets ODR-used at runtime to define a
109 * draw's stencil settings, and is later translated into concrete settings when the pipeline is
110 * finalized.
111 */
114
115 template<GrUserStencilTest, GrUserStencilOp PassOp, GrUserStencilOp FailOp> struct Attrs;
116
117 // Unfortunately, this is the only way to pass template arguments to a constructor.
118 template<uint16_t Ref, GrUserStencilTest Test, uint16_t TestMask,
119 GrUserStencilOp PassOp, GrUserStencilOp FailOp, uint16_t WriteMask> struct Init {};
120
121 template<uint16_t CWRef, uint16_t CCWRef,
122 GrUserStencilTest CWTest, GrUserStencilTest CCWTest,
123 uint16_t CWTestMask, uint16_t CCWTestMask,
124 GrUserStencilOp CWPassOp, GrUserStencilOp CCWPassOp,
125 GrUserStencilOp CWFailOp, GrUserStencilOp CCWFailOp,
126 uint16_t CWWriteMask, uint16_t CCWWriteMask> struct InitSeparate {};
127
128 template<uint16_t Ref, GrUserStencilTest Test, uint16_t TestMask,
129 GrUserStencilOp PassOp, GrUserStencilOp FailOp, uint16_t WriteMask>
132 }
133
134 template<uint16_t CWRef, uint16_t CCWRef,
135 GrUserStencilTest CWTest, GrUserStencilTest CCWTest,
136 uint16_t CWTestMask, uint16_t CCWTestMask,
137 GrUserStencilOp CWPassOp, GrUserStencilOp CCWPassOp,
138 GrUserStencilOp CWFailOp, GrUserStencilOp CCWFailOp,
139 uint16_t CWWriteMask, uint16_t CCWWriteMask>
140 constexpr static InitSeparate<CWRef, CCWRef, CWTest, CCWTest, CWTestMask, CCWTestMask,
141 CWPassOp, CCWPassOp, CWFailOp, CCWFailOp, CWWriteMask,
142 CCWWriteMask> StaticInitSeparate() {
143 return InitSeparate<CWRef, CCWRef, CWTest, CCWTest, CWTestMask, CCWTestMask,
144 CWPassOp, CCWPassOp, CWFailOp, CCWFailOp, CWWriteMask, CCWWriteMask>();
145 }
146
147 // We construct with template arguments in order to enforce that the struct be compile-time
148 // constant and to make use of static asserts.
149 template<uint16_t Ref, GrUserStencilTest Test, uint16_t TestMask,
150 GrUserStencilOp PassOp, GrUserStencilOp FailOp, uint16_t WriteMask,
151 typename Attrs = Attrs<Test, PassOp, FailOp> >
152 constexpr explicit GrUserStencilSettings(
156 , fCWFace{Ref, Test, Attrs::EffectiveTestMask(TestMask), PassOp, FailOp,
157 Attrs::EffectiveWriteMask(WriteMask)}
160 , fCCWFace{Ref, Test, Attrs::EffectiveTestMask(TestMask), PassOp, FailOp,
161 Attrs::EffectiveWriteMask(WriteMask)} {
162 }
163
164 template<uint16_t CWRef, uint16_t CCWRef,
165 GrUserStencilTest CWTest, GrUserStencilTest CCWTest,
166 uint16_t CWTestMask, uint16_t CCWTestMask,
167 GrUserStencilOp CWPassOp, GrUserStencilOp CCWPassOp,
168 GrUserStencilOp CWFailOp, GrUserStencilOp CCWFailOp,
169 uint16_t CWWriteMask, uint16_t CCWWriteMask,
170 typename CWAttrs = Attrs<CWTest, CWPassOp, CWFailOp>,
171 typename CCWAttrs = Attrs<CCWTest, CCWPassOp, CCWFailOp> >
172 constexpr explicit GrUserStencilSettings(
173 const InitSeparate<CWRef, CCWRef, CWTest, CCWTest, CWTestMask, CCWTestMask,
174 CWPassOp, CCWPassOp, CWFailOp, CCWFailOp, CWWriteMask,
175 CCWWriteMask>&)
176 : fCWFlags{CWAttrs::Flags(false), CWAttrs::Flags(true)}
177 , fCWFace{CWRef, CWTest, CWAttrs::EffectiveTestMask(CWTestMask), CWPassOp, CWFailOp,
178 CWAttrs::EffectiveWriteMask(CWWriteMask)}
179 , fCCWFlags{CCWAttrs::Flags(false), CCWAttrs::Flags(true)}
180 , fCCWFace{CCWRef, CCWTest, CCWAttrs::EffectiveTestMask(CCWTestMask), CCWPassOp, CCWFailOp,
181 CCWAttrs::EffectiveWriteMask(CCWWriteMask)} {}
182
183 // This struct can only be constructed with static initializers.
186
187 uint16_t flags(bool hasStencilClip) const {
188 return fCWFlags[hasStencilClip] & fCCWFlags[hasStencilClip];
189 }
190 bool isDisabled(bool hasStencilClip) const {
191 return this->flags(hasStencilClip) & kDisabled_StencilFlag;
192 }
193 bool testAlwaysPasses(bool hasStencilClip) const {
194 return this->flags(hasStencilClip) & kTestAlwaysPasses_StencilFlag;
195 }
196 bool isTwoSided(bool hasStencilClip) const {
197 return !(this->flags(hasStencilClip) & kSingleSided_StencilFlag);
198 }
199 bool usesWrapOp(bool hasStencilClip) const {
200 return !(this->flags(hasStencilClip) & kNoWrapOps_StencilFlag);
201 }
202
203 const uint16_t fCWFlags[2]; // cwFlagsForDraw = fCWFlags[hasStencilClip].
205 const uint16_t fCCWFlags[2]; // ccwFlagsForDraw = fCCWFlags[hasStencilClip].
207
209
210 bool isUnused() const { return this == &kUnused; }
211};
212
213template<GrUserStencilTest Test, GrUserStencilOp PassOp, GrUserStencilOp FailOp>
215 // Ensure an op that only modifies user bits isn't paired with one that modifies clip bits.
216 static_assert(GrUserStencilOp::kKeep == PassOp || GrUserStencilOp::kKeep == FailOp ||
217 (PassOp <= kLastUserOnlyStencilOp) == (FailOp <= kLastUserOnlyStencilOp));
218 // Ensure an op that only modifies clip bits isn't paired with one that modifies clip and user.
219 static_assert(GrUserStencilOp::kKeep == PassOp || GrUserStencilOp::kKeep == FailOp ||
220 (PassOp <= kLastClipOnlyStencilOp) == (FailOp <= kLastClipOnlyStencilOp));
221
222 constexpr static bool TestAlwaysPasses(bool hasStencilClip) {
223 return (!hasStencilClip && GrUserStencilTest::kAlwaysIfInClip == Test) ||
225 }
226 constexpr static bool DoesNotModifyStencil(bool hasStencilClip) {
227 return (GrUserStencilTest::kNever == Test || GrUserStencilOp::kKeep == PassOp) &&
228 (TestAlwaysPasses(hasStencilClip) || GrUserStencilOp::kKeep == FailOp);
229 }
230 constexpr static bool IsDisabled(bool hasStencilClip) {
231 return TestAlwaysPasses(hasStencilClip) && DoesNotModifyStencil(hasStencilClip);
232 }
233 constexpr static bool UsesWrapOps() {
234 return GrUserStencilOp::kIncWrap == PassOp || GrUserStencilOp::kDecWrap == PassOp ||
236 }
237 constexpr static bool TestIgnoresRef() {
240 }
241 constexpr static uint16_t Flags(bool hasStencilClip) {
242 return (IsDisabled(hasStencilClip) ? kDisabled_StencilFlag : 0) |
243 (TestAlwaysPasses(hasStencilClip) ? kTestAlwaysPasses_StencilFlag : 0) |
244 (DoesNotModifyStencil(hasStencilClip) ? kNoModifyStencil_StencilFlag : 0) |
246 }
247 constexpr static uint16_t EffectiveTestMask(uint16_t testMask) {
248 return TestIgnoresRef() ? 0 : testMask;
249 }
250 constexpr static uint16_t EffectiveWriteMask(uint16_t writeMask) {
251 // We don't modify the mask differently when hasStencilClip=false because either the entire
252 // face gets disabled in that case (e.g. Test=kAlwaysIfInClip, PassOp=kKeep), or else the
253 // effective mask stays the same either way.
254 return DoesNotModifyStencil(true) ? 0 : writeMask;
255 }
256};
257
258#endif
static constexpr GrUserStencilOp kLastUserOnlyStencilOp
@ kAll_StencilFlags
@ kTestAlwaysPasses_StencilFlag
@ kSingleSided_StencilFlag
@ kDisabled_StencilFlag
@ kNoWrapOps_StencilFlag
@ kNoModifyStencil_StencilFlag
@ kLast_StencilFlag
GrUserStencilTest
static constexpr GrUserStencilOp kLastClipOnlyStencilOp
static constexpr GrUserStencilTest kLastClippedStencilTest
static constexpr int kGrUserStencilOpCount
static constexpr int kGrUserStencilTestCount
constexpr auto kNever
Definition: SkSLTest.cpp:963
RefPtr< T > Ref(T *ptr)
Definition: ref_ptr.h:237
static constexpr uint16_t EffectiveWriteMask(uint16_t writeMask)
static constexpr bool TestIgnoresRef()
static constexpr uint16_t Flags(bool hasStencilClip)
static constexpr uint16_t EffectiveTestMask(uint16_t testMask)
static constexpr bool DoesNotModifyStencil(bool hasStencilClip)
static constexpr bool UsesWrapOps()
static constexpr bool TestAlwaysPasses(bool hasStencilClip)
static constexpr bool IsDisabled(bool hasStencilClip)
static constexpr Init< Ref, Test, TestMask, PassOp, FailOp, WriteMask > StaticInit()
GrTStencilFaceSettings< GrUserStencilTest, GrUserStencilOp > Face
GrUserStencilSettings(const GrUserStencilSettings &)=delete
uint16_t flags(bool hasStencilClip) const
bool isDisabled(bool hasStencilClip) const
bool isTwoSided(bool hasStencilClip) const
static constexpr InitSeparate< CWRef, CCWRef, CWTest, CCWTest, CWTestMask, CCWTestMask, CWPassOp, CCWPassOp, CWFailOp, CCWFailOp, CWWriteMask, CCWWriteMask > StaticInitSeparate()
bool usesWrapOp(bool hasStencilClip) const
GrUserStencilSettings()=delete
constexpr GrUserStencilSettings(const InitSeparate< CWRef, CCWRef, CWTest, CCWTest, CWTestMask, CCWTestMask, CWPassOp, CCWPassOp, CWFailOp, CCWFailOp, CWWriteMask, CCWWriteMask > &)
bool testAlwaysPasses(bool hasStencilClip) const
constexpr GrUserStencilSettings(const Init< Ref, Test, TestMask, PassOp, FailOp, WriteMask > &)
static const GrUserStencilSettings & kUnused