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

Side by Side Diff: src/gpu/GrStencil.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
OLDNEW
1 /* 1 /*
2 * Copyright 2011 Google Inc. 2 * Copyright 2011 Google Inc.
3 * 3 *
4 * Use of this source code is governed by a BSD-style license that can be 4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file. 5 * found in the LICENSE file.
6 */ 6 */
7 7
8 8
9 #ifndef GrStencil_DEFINED 9 #ifndef GrStencil_DEFINED
10 #define GrStencil_DEFINED 10 #define GrStencil_DEFINED
11 11
12 #include "GrTypes.h" 12 #include "GrTypes.h"
13 #include "SkRegion.h" 13 #include "SkRegion.h"
14 14
15 class GrProcessorKeyBuilder; 15 class GrProcessorKeyBuilder;
16 16
17 /** 17 /**
18 * Gr uses the stencil buffer to implement complex clipping inside the 18 * Gr uses the stencil buffer to implement complex clipping inside the
19 * GrDrawTarget class. The GrDrawTarget makes a subset of the stencil buffer 19 * GrDrawTarget class. The GrDrawTarget makes a subset of the stencil buffer
20 * bits available for other uses by external code (clients). Client code can 20 * bits available for other uses by external code (user bits). Client code can
21 * modify these bits. GrDrawTarget will ignore ref, mask, and writemask bits 21 * modify these bits. GrDrawTarget will ignore ref, mask, and writemask bits
22 * provided by clients that overlap the bits used to implement clipping. 22 * provided by clients that fall outside the user range.
23 * 23 *
24 * When code outside the GrDrawTarget class uses the stencil buffer the contract 24 * When code outside the GrDrawTarget class uses the stencil buffer the contract
25 * is as follows: 25 * is as follows:
26 * 26 *
27 * > Normal stencil funcs allow the client to pass / fail regardless of the 27 * > Normal stencil funcs allow the client to pass / fail regardless of the
28 * reserved clip bits. 28 * reserved clip bits.
29 * > Additional functions allow a test against the clip along with a limited 29 * > Additional functions allow a test against the clip along with a limited
30 * set of tests against the client bits. 30 * set of tests against the user bits.
31 * > Client can assume all client bits are zero initially. 31 * > Client can assume all user bits are zero initially.
32 * > Client must ensure that after all its passes are finished it has only 32 * > Client must ensure that after all its passes are finished it has only
33 * written to the color buffer in the region inside the clip. Furthermore, it 33 * written to the color buffer in the region inside the clip. Furthermore, it
34 * must zero all client bits that were modifed (both inside and outside the 34 * must zero all user bits that were modifed (both inside and outside the
35 * clip). 35 * clip).
36 */ 36 */
37 37
38 enum GrStencilFlags {
39 kDisabled_StencilFlag = 0x1,
40 kNoModifyStencil_StencilFlag = 0x2,
41 kNoWrapOps_StencilFlag = 0x4,
42 kSingleSided_StencilFlag = 0x8,
43
44 kLast_StencilFlag = kSingleSided_StencilFlag,
45 kAll_StencilFlags = kLast_StencilFlag | (kLast_StencilFlag - 1)
46 };
47
48 template<typename TTest, typename TOp> struct GrTStencilFaceSettings {
49 uint16_t fRef; // Reference value for stencil test and ops.
50 TTest fTest; // Stencil test function, where fRef is on the left side.
51 uint16_t fTestMask; // Bitwise "and" to perform on fRef and stencil valu es before testing.
52 // (e.g. (fRef & fTestMask) < (stencil & fTestMask))
53 TOp fPassOp; // Op to perform when the test passes.
54 TOp fFailOp; // Op to perform when the test fails.
55 uint16_t fWriteMask; // Indicates which bits in the stencil buffer should be updated.
56 // (e.g. stencil = (newValue & fWriteMask) | (stenci l & ~fWriteMask))
57 };
58
59 //////////////////////////////////////////////////////////////////////////////// ////////////////////
60
61 enum class GrUserStencilTest : uint16_t {
62 // Tests that respect the clip bit (if in use).
bsalomon 2016/05/10 14:06:21 Maybe say that these tests "always fail when the c
Chris Dalton 2016/05/10 16:39:30 How's the reworded comment?
bsalomon 2016/05/10 20:10:58 better, thanks.
63 kAlwaysIfInClip,
64 kEqualIfInClip,
65 kLessIfInClip,
66 kLEqualIfInClip,
67
68 // Tests that ignore the clip bit. The client is responsible to ensure no co lor writes occur
69 // outside the clip when it is in use.
70 kAlways,
71 kNever,
72 kGreater,
73 kGEqual,
74 kLess,
75 kLEqual,
76 kEqual,
77 kNotEqual
78 };
79 static constexpr GrUserStencilTest kLastClippedStencilTest = GrUserStencilTest:: kLEqualIfInClip;
80 static constexpr int kGrUserStencilTestCount = 1 + (int)GrUserStencilTest::kNotE qual;
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 mo dify the clip bit.
86 kZero,
87 kReplace, // Replace stencil value with fRef (only the bits enabled in fWrit eMask).
88 kInvert,
89 kIncWrap,
90 kDecWrap,
91 // These two should only be used if wrap ops are not supported, or if the ma th is guaranteed
92 // to not overflow. The user bits may or may not clamp, depending on the sta te 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 kK eep or each other.
102 kSetClipAndReplaceUserBits,
103 kZeroClipAndUserBits
104 };
105 static constexpr GrUserStencilOp kLastUserOnlyStencilOp = GrUserStencilOp::kDecM aybeClamp;
106 static constexpr GrUserStencilOp kLastClipOnlyStencilOp = GrUserStencilOp::kInve rtClipBit;
107 static constexpr int kGrUserStencilOpCount = 1 + (int)GrUserStencilOp::kZeroClip AndUserBits;
108
38 /** 109 /**
39 * Determines which pixels pass / fail the stencil test. 110 * This struct is a compile-time constant representation of user stencil setting s. It describes in
40 * Stencil test passes if (ref & mask) FUNC (stencil & mask) is true 111 * abstract terms how a draw will use the stencil buffer. It gets ODR-used at ru ntime to define a
112 * draw's stencil settings, and is later translated into concrete settings when the pipeline is
113 * finalized.
41 */ 114 */
42 enum GrStencilFunc { 115 struct GrUserStencilSettings {
43 kAlways_StencilFunc = 0, 116 typedef GrTStencilFaceSettings<GrUserStencilTest, GrUserStencilOp> Face;
44 kNever_StencilFunc, 117
45 kGreater_StencilFunc, 118 template<GrUserStencilTest, GrUserStencilOp PassOp, GrUserStencilOp FailOp> struct Attrs;
46 kGEqual_StencilFunc, 119
47 kLess_StencilFunc, 120 // Unfortunately, this is the only way to pass template arguments to a const ructor.
48 kLEqual_StencilFunc, 121 template<uint16_t Ref, GrUserStencilTest Test, uint16_t TestMask,
49 kEqual_StencilFunc, 122 GrUserStencilOp PassOp, GrUserStencilOp FailOp, uint16_t WriteMask> struct Init {};
50 kNotEqual_StencilFunc, 123
51 124 template<uint16_t FtRef, uint16_t BkRef,
52 // Gr stores the current clip in the 125 GrUserStencilTest FtTest, GrUserStencilTest BkTest,
53 // stencil buffer in the high bits that 126 uint16_t FtTestMask, uint16_t BkTestMask,
54 // are not directly accessible modifiable 127 GrUserStencilOp FtPassOp, GrUserStencilOp BkPassOp,
55 // via the GrDrawTarget interface. The below 128 GrUserStencilOp FtFailOp, GrUserStencilOp BkFailOp,
56 // stencil funcs test against the current 129 uint16_t FtWriteMask, uint16_t BkWriteMask> struct InitSeparat e {};
57 // clip in addition to the GrDrawTarget 130
58 // client's stencil bits. 131 template<uint16_t Ref, GrUserStencilTest Test, uint16_t TestMask,
59 132 GrUserStencilOp PassOp, GrUserStencilOp FailOp, uint16_t WriteMask>
60 // pass if inside the clip 133 constexpr static Init<Ref, Test, TestMask, PassOp, FailOp, WriteMask> Static Init() {
61 kAlwaysIfInClip_StencilFunc, 134 return Init<Ref, Test, TestMask, PassOp, FailOp, WriteMask>();
62 kEqualIfInClip_StencilFunc, 135 }
63 kLessIfInClip_StencilFunc, 136
64 kLEqualIfInClip_StencilFunc, 137 template<uint16_t FtRef, uint16_t BkRef,
65 kNonZeroIfInClip_StencilFunc, // this one forces the ref to be 0 138 GrUserStencilTest FtTest, GrUserStencilTest BkTest,
66 139 uint16_t FtTestMask, uint16_t BkTestMask,
67 kLast_StencilFunc = kNonZeroIfInClip_StencilFunc 140 GrUserStencilOp FtPassOp, GrUserStencilOp BkPassOp,
68 }; 141 GrUserStencilOp FtFailOp, GrUserStencilOp BkFailOp,
69 142 uint16_t FtWriteMask, uint16_t BkWriteMask>
70 static const int kStencilFuncCnt = kLast_StencilFunc + 1; 143 constexpr static InitSeparate<FtRef, BkRef, FtTest, BkTest, FtTestMask, BkTe stMask,
71 static const int kClipStencilFuncCnt = 144 FtPassOp, BkPassOp, FtFailOp, BkFailOp, FtWrit eMask,
72 kNonZeroIfInClip_StencilFunc - kAlwaysIfInClip_StencilFunc + 1; 145 BkWriteMask> StaticInitSeparate() {
73 static const int kBasicStencilFuncCnt = kStencilFuncCnt - kClipStencilFuncCnt; 146 return InitSeparate<FtRef, BkRef, FtTest, BkTest, FtTestMask, BkTestMask ,
147 FtPassOp, BkPassOp, FtFailOp, BkFailOp, FtWriteMask, BkWriteMask>();
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> >
155 constexpr explicit GrUserStencilSettings(
156 const Init<Ref, Test, TestMask, PassOp, FailOp, WriteMask>&)
157 : fFrontFlags{Attrs::Flags(false) | kSingleSided_StencilFlag,
158 Attrs::Flags(true) | kSingleSided_StencilFlag}
159 , fFront{Ref, Test, Attrs::EffectiveTestMask(TestMask), PassOp, FailOp,
160 Attrs::EffectiveWriteMask(WriteMask)}
161 , fBackFlags{Attrs::Flags(false) | kSingleSided_StencilFlag,
162 Attrs::Flags(true) | kSingleSided_StencilFlag}
163 , fBack{Ref, Test, Attrs::EffectiveTestMask(TestMask), PassOp, FailOp,
164 Attrs::EffectiveWriteMask(WriteMask)} {
165 }
166
167 template<uint16_t FtRef, uint16_t BkRef,
168 GrUserStencilTest FtTest, GrUserStencilTest BkTest,
169 uint16_t FtTestMask, uint16_t BkTestMask,
170 GrUserStencilOp FtPassOp, GrUserStencilOp BkPassOp,
171 GrUserStencilOp FtFailOp, GrUserStencilOp BkFailOp,
172 uint16_t FtWriteMask, uint16_t BkWriteMask,
173 typename FtAttrs = Attrs<FtTest, FtPassOp, FtFailOp>,
174 typename BkAttrs = Attrs<BkTest, BkPassOp, BkFailOp> >
175 constexpr explicit GrUserStencilSettings(
176 const InitSeparate<FtRef, BkRef, FtTest, BkTest, FtTestMask, BkTestM ask,
177 FtPassOp, BkPassOp, FtFailOp, BkFailOp, FtWriteMa sk, BkWriteMask>&)
178 : fFrontFlags{FtAttrs::Flags(false), FtAttrs::Flags(true)}
179 , fFront{FtRef, FtTest, FtAttrs::EffectiveTestMask(FtTestMask), FtPassOp , FtFailOp,
180 FtAttrs::EffectiveWriteMask(FtWriteMask)}
181 , fBackFlags{BkAttrs::Flags(false), BkAttrs::Flags(true)}
182 , fBack{BkRef, BkTest, BkAttrs::EffectiveTestMask(BkTestMask), BkPassOp, BkFailOp,
183 BkAttrs::EffectiveWriteMask(BkWriteMask)} {}
184
185 // This struct can only be constructed with static initializers.
186 GrUserStencilSettings() = delete;
187 GrUserStencilSettings(const GrUserStencilSettings&) = delete;
188
189 const uint16_t fFrontFlags[2]; // frontFlagsForDraw = fFrontFlags[hasStenc ilClip].
190 const Face fFront;
191 const uint16_t fBackFlags[2]; // backFlagsForDraw = fBackFlags[hasStencilC lip].
192 const Face fBack;
193
194 static const GrUserStencilSettings& kUnused;
195 };
196
197 template<GrUserStencilTest Test, GrUserStencilOp PassOp, GrUserStencilOp FailOp>
198 struct GrUserStencilSettings::Attrs {
199 // Ensure an op that only modifies user bits isn't paired with one that modi fies clip bits.
200 GR_STATIC_ASSERT(GrUserStencilOp::kKeep == PassOp || GrUserStencilOp::kKeep == FailOp ||
201 (PassOp <= kLastUserOnlyStencilOp) == (FailOp <= kLastUserO nlyStencilOp));
202 // Ensure an op that only modifies clip bits isn't paired with one that modi fies clip and user.
203 GR_STATIC_ASSERT(GrUserStencilOp::kKeep == PassOp || GrUserStencilOp::kKeep == FailOp ||
204 (PassOp <= kLastClipOnlyStencilOp) == (FailOp <= kLastClipO nlyStencilOp));
205
206 static constexpr bool TestAlwaysPasses(bool hasStencilClip) {
207 return (!hasStencilClip && GrUserStencilTest::kAlwaysIfInClip == Test) | |
208 GrUserStencilTest::kAlways == Test;
209 }
210 static constexpr bool DoesNotModifyStencil(bool hasStencilClip) {
211 return (GrUserStencilTest::kNever == Test || GrUserStencilOp::kKeep == P assOp) &&
212 (TestAlwaysPasses(hasStencilClip) || GrUserStencilOp::kKeep == F ailOp);
213 }
214 static constexpr bool IsDisabled(bool hasStencilClip) {
215 return TestAlwaysPasses(hasStencilClip) && DoesNotModifyStencil(hasStenc ilClip);
216 }
217 static constexpr bool UsesWrapOps() {
218 return GrUserStencilOp::kIncWrap == PassOp || GrUserStencilOp::kDecWrap == PassOp ||
219 GrUserStencilOp::kIncWrap == FailOp || GrUserStencilOp::kDecWrap == FailOp;
220 }
221 static constexpr bool TestIgnoresRef() {
222 return (GrUserStencilTest::kAlwaysIfInClip == Test || GrUserStencilTest: :kAlways == Test ||
223 GrUserStencilTest::kNever == Test);
224 }
225 static constexpr uint16_t Flags(bool hasStencilClip) {
226 return (IsDisabled(hasStencilClip) ? kDisabled_StencilFlag : 0) |
227 (DoesNotModifyStencil(hasStencilClip) ? kNoModifyStencil_StencilF lag : 0) |
228 (UsesWrapOps() ? 0 : kNoWrapOps_StencilFlag);
229 }
230 static constexpr uint16_t EffectiveTestMask(uint16_t testMask) {
231 return TestIgnoresRef() ? 0 : testMask;
232 }
233 static constexpr uint16_t EffectiveWriteMask(uint16_t writeMask) {
234 // We don't modify the mask differently when hasStencilClip=false becaus e either the entire
235 // face gets disabled in that case (e.g. Test=kAlwaysIfInClip, PassOp=kK eep), or the
236 // effective mask stays the same either way.
237 return DoesNotModifyStencil(true) ? 0 : writeMask;
238 }
239 };
240
241 //////////////////////////////////////////////////////////////////////////////// ////////////////////
242
243 enum class GrStencilTest : uint16_t {
bsalomon 2016/05/10 14:06:21 I'm wondering if this could be in another file tha
Chris Dalton 2016/05/10 16:39:30 Done. Good idea.
244 kAlways,
245 kNever,
246 kGreater,
247 kGEqual,
248 kLess,
249 kLEqual,
250 kEqual,
251 kNotEqual
252 };
253 static constexpr int kGrStencilTestCount = 1 + (int)GrStencilTest::kNotEqual;
254
255 enum class GrStencilOp : uint8_t {
256 kKeep,
257 kZero,
258 kReplace, // Replace stencil value with fRef (only the bits enabled in fWrit eMask).
259 kInvert,
260 kIncWrap,
261 kDecWrap,
262 // NOTE: clamping occurs before the write mask. So if the MSB is zero and ma sked out, stencil
263 // values will still wrap when using clamping ops.
264 kIncClamp,
265 kDecClamp
266 };
267 static constexpr int kGrStencilOpCount = 1 + (int)GrStencilOp::kDecClamp;
74 268
75 /** 269 /**
76 * Operations to perform based on whether stencil test passed failed. 270 * This class defines concrete stencil settings that map directly to the underly ing hardware. It
77 */ 271 * is deduced from user stencil settings, stencil clip status, and the number of bits in the
78 enum GrStencilOp { 272 * target stencil buffer.
79 kKeep_StencilOp = 0, // preserve existing stencil value
80 kReplace_StencilOp, // replace with reference value from stencl test
81 kIncWrap_StencilOp, // increment and wrap at max
82 kIncClamp_StencilOp, // increment and clamp at max
83 kDecWrap_StencilOp, // decrement and wrap at 0
84 kDecClamp_StencilOp, // decrement and clamp at 0
85 kZero_StencilOp, // zero stencil bits
86 kInvert_StencilOp, // invert stencil bits
87 kLast_StencilOp = kInvert_StencilOp
88 };
89 static const int kStencilOpCnt = kLast_StencilOp + 1;
90
91 /**
92 * Class representing stencil state.
93 */ 273 */
94 class GrStencilSettings { 274 class GrStencilSettings {
95 public: 275 public:
96 enum Face { 276 GrStencilSettings() { this->setDisabled(); }
97 kFront_Face = 0, 277 GrStencilSettings(const GrUserStencilSettings& user, bool hasStencilClip, in t numStencilBits) {
98 kBack_Face = 1, 278 this->reset(user, hasStencilClip, numStencilBits);
279 }
280 GrStencilSettings(const GrStencilSettings& that) { this->reset(that); }
281 GrStencilSettings& operator=(const GrStencilSettings& that) { this->reset(th at); return *this; }
282
283 void invalidate() { fFlags |= kInvalid_PrivateFlag; }
284 void setDisabled() { fFlags = kAll_StencilFlags; }
285 void reset(const GrUserStencilSettings&, bool hasStencilClip, int numStencil Bits);
286 void reset(const GrStencilSettings&);
287
288 bool isValid() const { return !(fFlags & kInvalid_PrivateFlag); }
289 bool isDisabled() const { SkASSERT(this->isValid()); return fFlags & kDisabl ed_StencilFlag; }
290 bool doesWrite() const { SkASSERT(this->isValid());
291 return !(fFlags & kNoModifyStencil_StencilFlag); }
292 bool isTwoSided() const { SkASSERT(this->isValid());
293 return !(fFlags & kSingleSided_StencilFlag); }
294 bool usesWrapOp() const { SkASSERT(this->isValid());
295 return !(fFlags & kNoWrapOps_StencilFlag); }
296
297 void genKey(GrProcessorKeyBuilder* b) const;
298
299 bool operator!=(const GrStencilSettings& that) const { return !(*this == tha t); }
300 bool operator==(const GrStencilSettings&) const;
301
302 struct Face : public GrTStencilFaceSettings<GrStencilTest, GrStencilOp> {
303 void reset(const GrUserStencilSettings::Face&, bool useStencilClip, int numStencilBits);
304 void setDisabled();
99 }; 305 };
100 306
101 constexpr GrStencilSettings(GrStencilOp passOp, 307 const Face& front() const { SkASSERT(!this->isDisabled()); return fFront; }
102 GrStencilOp failOp, 308 const Face& back() const { SkASSERT(this->isTwoSided()); return fBack; }
103 GrStencilFunc func,
104 unsigned short funcMask,
105 unsigned short funcRef,
106 unsigned short writeMask)
107 : fPassOps{(uint8_t)passOp, (uint8_t)passOp}
108 , fFailOps{(uint8_t)failOp, (uint8_t)failOp}
109 , fFuncs{(uint8_t)func, (uint8_t)func}
110 , fPad0(0)
111 , fPad1(0)
112 , fFuncMasks{funcMask, funcMask}
113 , fFuncRefs{funcRef, funcRef}
114 , fWriteMasks{writeMask, writeMask}
115 , fFlags(ComputeFlags(passOp, passOp,
116 failOp, failOp,
117 func, func,
118 writeMask, writeMask)) {
119 }
120
121 constexpr GrStencilSettings(GrStencilOp frontPassOp, GrStencilOp backPassOp ,
122 GrStencilOp frontFailOp, GrStencilOp backFailOp ,
123 GrStencilFunc frontFunc, GrStencilFunc backFunc ,
124 uint16_t frontFuncMask, uint16_t backFuncMask,
125 uint16_t frontFuncRef, uint16_t backFuncRef,
126 uint16_t frontWriteMask, uint16_t backWriteMask )
127 : fPassOps{(uint8_t)frontPassOp, (uint8_t)backPassOp}
128 , fFailOps{(uint8_t)frontFailOp, (uint8_t)backFailOp}
129 , fFuncs{(uint8_t)frontFunc, (uint8_t)backFunc}
130 , fPad0(0)
131 , fPad1(0)
132 , fFuncMasks{frontFuncMask, backFuncMask}
133 , fFuncRefs{frontFuncRef, backFuncRef}
134 , fWriteMasks{frontWriteMask, backWriteMask}
135 , fFlags(ComputeFlags(frontPassOp, backPassOp,
136 frontFailOp, backFailOp,
137 frontFunc, backFunc,
138 frontWriteMask, backWriteMask)) {
139 }
140
141 GrStencilSettings() {
142 fPad0 = fPad1 = 0;
143 this->setDisabled();
144 }
145
146 GrStencilOp passOp(Face f) const { return static_cast<GrStencilOp>(fPassOps[ f]); }
147 GrStencilOp failOp(Face f) const { return static_cast<GrStencilOp>(fFailOps[ f]); }
148 GrStencilFunc func(Face f) const { return static_cast<GrStencilFunc>(fFuncs[ f]); }
149 uint16_t funcMask(Face f) const { return fFuncMasks[f]; }
150 uint16_t funcRef(Face f) const { return fFuncRefs[f]; }
151 uint16_t writeMask(Face f) const { return fWriteMasks[f]; }
152
153 void setPassOp(Face f, GrStencilOp op) { fPassOps[f] = op; fFlags = 0;}
154 void setFailOp(Face f, GrStencilOp op) { fFailOps[f] = op; fFlags = 0;}
155 void setFunc(Face f, GrStencilFunc func) { fFuncs[f] = func; fFlags = 0;}
156 void setFuncMask(Face f, unsigned short mask) { fFuncMasks[f] = mask; }
157 void setFuncRef(Face f, unsigned short ref) { fFuncRefs[f] = ref; }
158 void setWriteMask(Face f, unsigned short writeMask) { fWriteMasks[f] = write Mask; }
159
160 void copyFrontSettingsToBack() {
161 fPassOps[kBack_Face] = fPassOps[kFront_Face];
162 fFailOps[kBack_Face] = fFailOps[kFront_Face];
163 fFuncs[kBack_Face] = fFuncs[kFront_Face];
164 fFuncMasks[kBack_Face] = fFuncMasks[kFront_Face];
165 fFuncRefs[kBack_Face] = fFuncRefs[kFront_Face];
166 fWriteMasks[kBack_Face] = fWriteMasks[kFront_Face];
167 fFlags = 0;
168 }
169
170 void setDisabled() {
171 memset(this, 0, sizeof(*this));
172 GR_STATIC_ASSERT(0 == kKeep_StencilOp);
173 GR_STATIC_ASSERT(0 == kAlways_StencilFunc);
174 fFlags = kIsDisabled_StencilFlag | kDoesNotWrite_StencilFlag;
175 }
176
177 bool isTwoSided() const {
178 return fPassOps[kFront_Face] != fPassOps[kBack_Face] ||
179 fFailOps[kFront_Face] != fFailOps[kBack_Face] ||
180 fFuncs[kFront_Face] != fFuncs[kBack_Face] ||
181 fFuncMasks[kFront_Face] != fFuncMasks[kBack_Face] ||
182 fFuncRefs[kFront_Face] != fFuncRefs[kBack_Face] ||
183 fWriteMasks[kFront_Face] != fWriteMasks[kBack_Face];
184 }
185
186 bool usesWrapOp() const {
187 return kIncWrap_StencilOp == fPassOps[kFront_Face] ||
188 kDecWrap_StencilOp == fPassOps[kFront_Face] ||
189 kIncWrap_StencilOp == fPassOps[kBack_Face] ||
190 kDecWrap_StencilOp == fPassOps[kBack_Face] ||
191 kIncWrap_StencilOp == fFailOps[kFront_Face] ||
192 kDecWrap_StencilOp == fFailOps[kFront_Face] ||
193 kIncWrap_StencilOp == fFailOps[kBack_Face] ||
194 kDecWrap_StencilOp == fFailOps[kBack_Face];
195 }
196
197 bool isDisabled() const {
198 if (fFlags & kIsDisabled_StencilFlag) {
199 return true;
200 }
201 if (fFlags & kNotDisabled_StencilFlag) {
202 return false;
203 }
204 bool disabled = this->computeIsDisabled();
205 fFlags |= disabled ? kIsDisabled_StencilFlag : kNotDisabled_StencilFlag;
206 return disabled;
207 }
208
209 bool doesWrite() const {
210 if (fFlags & kDoesWrite_StencilFlag) {
211 return true;
212 }
213 if (fFlags & kDoesNotWrite_StencilFlag) {
214 return false;
215 }
216 bool writes = this->computeDoesWrite();
217 fFlags |= writes ? kDoesWrite_StencilFlag : kDoesNotWrite_StencilFlag;
218 return writes;
219 }
220
221 void invalidate() {
222 // write an illegal value to the first member
223 fPassOps[0] = kStencilOpCnt;
224 fFlags = 0;
225 }
226
227 bool isValid() const { return fPassOps[0] < kStencilOpCnt; }
228
229 void genKey(GrProcessorKeyBuilder* b) const;
230
231 bool operator==(const GrStencilSettings& s) const {
232 static const size_t gCompareSize = sizeof(GrStencilSettings) -
233 sizeof(fFlags);
234 SkASSERT((const char*)&fFlags + sizeof(fFlags) ==
235 (const char*)this + sizeof(GrStencilSettings));
236 if (this->isDisabled() & s.isDisabled()) { // using & not &&
237 return true;
238 }
239 return 0 == memcmp(this, &s, gCompareSize);
240 }
241
242 bool operator!=(const GrStencilSettings& s) const {
243 return !(*this == s);
244 }
245
246 GrStencilSettings& operator=(const GrStencilSettings& s) {
247 memcpy(this, &s, sizeof(GrStencilSettings));
248 return *this;
249 }
250
251 private:
252 friend class GrClipMaskManager;
253
254 enum {
255 kMaxStencilClipPasses = 2 // maximum number of passes to add a clip
256 // element to the stencil buffer.
257 };
258 309
259 /** 310 /**
260 * Given a thing to draw into the stencil clip, a fill type, and a set op 311 * Given a thing to draw into the stencil clip, a fill type, and a set op
261 * this function determines: 312 * this function determines:
262 * 1. Whether the thing can be draw directly to the stencil clip or 313 * 1. Whether the thing can be draw directly to the stencil clip or
263 * needs to be drawn to the client portion of the stencil first. 314 * needs to be drawn to the client portion of the stencil first.
264 * 2. How many passes are needed. 315 * 2. How many passes are needed.
265 * 3. What those passes are. 316 * 3. What those passes are.
266 * 4. The fill rule that should actually be used to render (will
267 * always be non-inverted).
268 * 317 *
269 * @param op the set op to combine this element with the 318 * @param op the set op to combine this element with the exis ting clip
270 * existing clip 319 * @param canBeDirect can the caller draw this element directly (witho ut using stencil)?
271 * @param stencilClipMask mask with just the stencil bit used for clipping
272 * enabled.
273 * @param invertedFill is this path inverted 320 * @param invertedFill is this path inverted
274 * @param numPasses out: the number of passes needed to add the 321 * @param drawDirectToClip out: true if caller should draw the element dire ctly, false if it
275 * element to the clip. 322 * should draw it into the user stencil bits first.
276 * @param settings out: the stencil settings to use for each pass
277 * 323 *
278 * @return true if the clip element's geometry can be drawn directly to the 324 * @return a null-terminated array of settings for stencil passes.
279 * stencil clip bit. Will only be true if canBeDirect is true. 325 *
280 * numPasses will be 1 if return value is true. 326 * If drawDirectToClip is false, the caller must first draw the elem ent into the user
327 * stencil bits, and then cover the clip area with multiple passes u sing the returned
328 * stencil settings.
329 *
330 * If drawDirectToClip is true, the returned array will only have on e pass and the
331 * caller should use those stencil settings while drawing the elemen t directly.
281 */ 332 */
282 static bool GetClipPasses(SkRegion::Op op, 333 static GrUserStencilSettings const* const* GetClipPasses(SkRegion::Op op,
283 bool canBeDirect, 334 bool canBeDirect,
284 unsigned int stencilClipMask, 335 bool invertedFill,
285 bool invertedFill, 336 bool* drawDirectToC lip);
286 int* numPasses,
287 GrStencilSettings settings[kMaxStencilClipPasses]) ;
288 337
289 constexpr static bool IsDisabled(GrStencilOp frontPassOp, GrStencilOp backP assOp, 338 private:
290 GrStencilOp frontFailOp, GrStencilOp backF ailOp, 339 // Internal flag for backends to optionally mark their tracked stencil state as invalid.
291 GrStencilFunc frontFunc, GrStencilFunc bac kFunc) { 340 enum { kInvalid_PrivateFlag = (kLast_StencilFlag << 1) };
292 return (((frontPassOp == kKeep_StencilOp && frontFailOp == kKeep_Stencil Op)) &&
293 ((backPassOp == kKeep_StencilOp && backFailOp == kKeep_Stencil Op)) &&
294 frontFunc == kAlways_StencilFunc &&
295 backFunc == kAlways_StencilFunc);
296 }
297 341
298 constexpr static bool DoesWrite(GrStencilOp frontPassOp, GrStencilOp backPa ssOp, 342 uint32_t fFlags;
299 GrStencilOp frontFailOp, GrStencilOp backFa ilOp, 343 Face fFront;
300 GrStencilFunc frontFunc, GrStencilFunc back Func, 344 Face fBack;
301 uint16_t frontWriteMask, uint16_t backWrite Mask) {
302 return (0 != (frontWriteMask | backWriteMask)) &&
303 // Can we write due to a front face passing the stencil test?
304 ((frontFunc != kNever_StencilFunc && frontPassOp != kKeep_Stenci lOp) ||
305 // Can we write due to a back face passing the stencil test?
306 (backFunc != kNever_StencilFunc && backPassOp != kKeep_Stenci lOp) ||
307 // Can we write due to a front face failing the stencil test?
308 (frontFunc != kAlways_StencilFunc && frontFailOp != kKeep_Stenci lOp) ||
309 // Can we write due to a back face failing the stencil test?
310 (backFunc != kAlways_StencilFunc && backFailOp != kKeep_Stenci lOp));
311 }
312
313 constexpr static uint32_t ComputeFlags(GrStencilOp frontPassOp, GrStencilOp backPassOp,
314 GrStencilOp frontFailOp, GrStencilOp backFailOp,
315 GrStencilFunc frontFunc, GrStencilFu nc backFunc,
316 uint16_t frontWriteMask, uint16_t ba ckWriteMask) {
317 return (IsDisabled(frontPassOp, backPassOp, frontFailOp, backFailOp,
318 frontFunc, backFunc)
319 ? kIsDisabled_StencilFlag
320 : kNotDisabled_StencilFlag) |
321 (DoesWrite(frontPassOp, backPassOp, frontFailOp, backFailOp,
322 frontFunc, backFunc, frontWriteMask, backWriteMask)
323 ? kDoesWrite_StencilFlag
324 : kDoesNotWrite_StencilFlag);
325 }
326
327 bool computeIsDisabled() const {
328 return IsDisabled((GrStencilOp) fPassOps[kFront_Face], (GrStencilOp) fPa ssOps[kBack_Face],
329 (GrStencilOp) fFailOps[kFront_Face], (GrStencilOp) fFa ilOps[kBack_Face],
330 (GrStencilFunc) fFuncs[kFront_Face], (GrStencilFunc) f Funcs[kBack_Face]);
331 }
332 bool computeDoesWrite() const {
333 return DoesWrite((GrStencilOp)fPassOps[kFront_Face], (GrStencilOp)fPassO ps[kBack_Face],
334 (GrStencilOp)fFailOps[kFront_Face], (GrStencilOp)fFailO ps[kBack_Face],
335 (GrStencilFunc)fFuncs[kFront_Face], (GrStencilFunc)fFun cs[kBack_Face],
336 fWriteMasks[kFront_Face], fWriteMasks[kBack_F ace]);
337 }
338
339 enum GrStencilFlags {
340 kIsDisabled_StencilFlag = 0x1,
341 kNotDisabled_StencilFlag = 0x2,
342 kDoesWrite_StencilFlag = 0x4,
343 kDoesNotWrite_StencilFlag = 0x8,
344 };
345
346 uint8_t fPassOps[2]; // op to perform when faces pass (GrStencilOp)
347 uint8_t fFailOps[2]; // op to perform when faces fail (GrStencilOp)
348 uint8_t fFuncs[2]; // test function for faces (GrStencilFunc)
349 uint8_t fPad0;
350 uint8_t fPad1;
351 uint16_t fFuncMasks[2]; // mask for face tests
352 uint16_t fFuncRefs[2]; // reference values for face tests
353 uint16_t fWriteMasks[2]; // stencil write masks
354 mutable uint32_t fFlags;
355
356 }; 345 };
357 346
358 // We rely on this being packed and aligned (memcmp'ed and memcpy'ed)
359 GR_STATIC_ASSERT(sizeof(GrStencilSettings) % 4 == 0);
360 GR_STATIC_ASSERT(sizeof(GrStencilSettings) ==
361 4*sizeof(uint8_t) + // ops
362 2*sizeof(uint8_t) + // funcs
363 2*sizeof(uint8_t) + // pads
364 2*sizeof(uint16_t) + // func masks
365 2*sizeof(uint16_t) + // ref values
366 2*sizeof(uint16_t) + // write masks
367 sizeof(uint32_t)); // flags
368
369 #endif 347 #endif
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698