Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(2)

Side by Side Diff: src/gpu/GrUserStencilSettings.h

Issue 1962243002: Separate user and raw stencil settings (Closed) Base URL: https://skia.googlesource.com/skia.git@master
Patch Set: Created 4 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « src/gpu/GrStencilSettings.cpp ('k') | src/gpu/batches/GrDefaultPathRenderer.cpp » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
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 * GrDrawTarget class. The GrDrawTarget 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. GrDrawTarget will ignore ref, mask, and writemask bits
19 * provided by clients that fall outside the user range.
20 *
21 * When code outside the GrDrawTarget 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 valu es 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) | (stenci l & ~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 co lor 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::kNotE qual;
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 mo dify the clip bit.
82 kZero,
83 kReplace, // Replace stencil value with fRef (only the bits enabled in fWrit eMask).
84 kInvert,
85 kIncWrap,
86 kDecWrap,
87 // These two should only be used if wrap ops are not supported, or if the ma th is guaranteed
88 // to not overflow. The user bits may or may not clamp, depending on the sta te 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 kK eep or each other.
98 kSetClipAndReplaceUserBits,
99 kZeroClipAndUserBits
100 };
101 constexpr static GrUserStencilOp kLastUserOnlyStencilOp = GrUserStencilOp::kDecM aybeClamp;
102 constexpr static GrUserStencilOp kLastClipOnlyStencilOp = GrUserStencilOp::kInve rtClipBit;
103 constexpr static int kGrUserStencilOpCount = 1 + (int)GrUserStencilOp::kZeroClip AndUserBits;
104
105 /**
106 * This struct is a compile-time constant representation of user stencil setting s. It describes in
107 * abstract terms how a draw will use the stencil buffer. It gets ODR-used at ru ntime 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 const ructor.
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 InitSeparat e {};
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> Static Init() {
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, BkTe stMask,
140 FtPassOp, BkPassOp, FtFailOp, BkFailOp, FtWrit eMask,
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, BkTestM ask,
173 FtPassOp, BkPassOp, FtFailOp, BkFailOp, FtWriteMa sk, 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 const uint16_t fFrontFlags[2]; // frontFlagsForDraw = fFrontFlags[hasStenc ilClip].
186 const Face fFront;
187 const uint16_t fBackFlags[2]; // backFlagsForDraw = fBackFlags[hasStencilC lip].
188 const Face fBack;
189
190 static const GrUserStencilSettings& kUnused;
191 };
192
193 template<GrUserStencilTest Test, GrUserStencilOp PassOp, GrUserStencilOp FailOp>
194 struct GrUserStencilSettings::Attrs {
195 // Ensure an op that only modifies user bits isn't paired with one that modi fies clip bits.
196 GR_STATIC_ASSERT(GrUserStencilOp::kKeep == PassOp || GrUserStencilOp::kKeep == FailOp ||
197 (PassOp <= kLastUserOnlyStencilOp) == (FailOp <= kLastUserO nlyStencilOp));
198 // Ensure an op that only modifies clip bits isn't paired with one that modi fies clip and user.
199 GR_STATIC_ASSERT(GrUserStencilOp::kKeep == PassOp || GrUserStencilOp::kKeep == FailOp ||
200 (PassOp <= kLastClipOnlyStencilOp) == (FailOp <= kLastClipO nlyStencilOp));
201
202 constexpr static bool TestAlwaysPasses(bool hasStencilClip) {
203 return (!hasStencilClip && GrUserStencilTest::kAlwaysIfInClip == Test) | |
204 GrUserStencilTest::kAlways == Test;
205 }
206 constexpr static bool DoesNotModifyStencil(bool hasStencilClip) {
207 return (GrUserStencilTest::kNever == Test || GrUserStencilOp::kKeep == P assOp) &&
208 (TestAlwaysPasses(hasStencilClip) || GrUserStencilOp::kKeep == F ailOp);
209 }
210 constexpr static bool IsDisabled(bool hasStencilClip) {
211 return TestAlwaysPasses(hasStencilClip) && DoesNotModifyStencil(hasStenc ilClip);
212 }
213 constexpr static bool UsesWrapOps() {
214 return GrUserStencilOp::kIncWrap == PassOp || GrUserStencilOp::kDecWrap == PassOp ||
215 GrUserStencilOp::kIncWrap == FailOp || GrUserStencilOp::kDecWrap == FailOp;
216 }
217 constexpr static bool TestIgnoresRef() {
218 return (GrUserStencilTest::kAlwaysIfInClip == Test || GrUserStencilTest: :kAlways == Test ||
219 GrUserStencilTest::kNever == Test);
220 }
221 constexpr static uint16_t Flags(bool hasStencilClip) {
222 return (IsDisabled(hasStencilClip) ? kDisabled_StencilFlag : 0) |
223 (DoesNotModifyStencil(hasStencilClip) ? kNoModifyStencil_StencilF lag : 0) |
224 (UsesWrapOps() ? 0 : kNoWrapOps_StencilFlag);
225 }
226 constexpr static uint16_t EffectiveTestMask(uint16_t testMask) {
227 return TestIgnoresRef() ? 0 : testMask;
228 }
229 constexpr static uint16_t EffectiveWriteMask(uint16_t writeMask) {
230 // We don't modify the mask differently when hasStencilClip=false becaus e either the entire
231 // face gets disabled in that case (e.g. Test=kAlwaysIfInClip, PassOp=kK eep), or else the
232 // effective mask stays the same either way.
233 return DoesNotModifyStencil(true) ? 0 : writeMask;
234 }
235 };
236
237 #endif
OLDNEW
« no previous file with comments | « src/gpu/GrStencilSettings.cpp ('k') | src/gpu/batches/GrDefaultPathRenderer.cpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698