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

Side by Side Diff: src/gpu/GrStencil.cpp

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 #include "GrStencil.h" 9 #include "GrStencil.h"
10 10
11 #include "GrProcessor.h" 11 #include "GrProcessor.h"
12 12
13 constexpr const GrUserStencilSettings gUnused(
14 GrUserStencilSettings::StaticInit<
15 0x0000,
16 GrUserStencilTest::kAlwaysIfInClip,
17 0xffff,
18 GrUserStencilOp::kKeep,
19 GrUserStencilOp::kKeep,
20 0x0000>()
21 );
22
23 GR_STATIC_ASSERT(kAll_StencilFlags == (gUnused.fFrontFlags[0] & gUnused.fBackFla gs[0]));
24
25 const GrUserStencilSettings& GrUserStencilSettings::kUnused = gUnused;
26
27 void GrStencilSettings::reset(const GrUserStencilSettings& user, bool hasStencil Clip,
28 int numStencilBits) {
29 uint16_t frontFlags = user.fFrontFlags[hasStencilClip];
30 if (frontFlags & kSingleSided_StencilFlag) {
31 fFlags = frontFlags;
32 if (!this->isDisabled()) {
33 fFront.reset(user.fFront, hasStencilClip, numStencilBits);
34 }
35 return;
36 }
37
38 uint16_t backFlags = user.fBackFlags[hasStencilClip];
39 fFlags = frontFlags & backFlags;
40 if (this->isDisabled()) {
41 return;
42 }
43 if (!(frontFlags & kDisabled_StencilFlag)) {
44 fFront.reset(user.fFront, hasStencilClip, numStencilBits);
45 } else {
46 fFront.setDisabled();
47 }
48 if (!(backFlags & kDisabled_StencilFlag)) {
49 fBack.reset(user.fBack, hasStencilClip, numStencilBits);
50 } else {
51 fBack.setDisabled();
52 }
53 }
54
55 void GrStencilSettings::reset(const GrStencilSettings& that) {
56 fFlags = that.fFlags;
57 if ((kInvalid_PrivateFlag | kDisabled_StencilFlag) & fFlags) {
58 return;
59 }
60 if (!this->isTwoSided()) {
61 memcpy(&fFront, &that.fFront, sizeof(Face));
62 } else {
63 memcpy(&fFront, &that.fFront, 2 * sizeof(Face));
64 GR_STATIC_ASSERT(sizeof(Face) ==
65 offsetof(GrStencilSettings, fBack) - offsetof(GrStencil Settings, fFront));
66 }
67 }
68
69 bool GrStencilSettings::operator==(const GrStencilSettings& that) const {
70 if ((kInvalid_PrivateFlag | kDisabled_StencilFlag) & (fFlags | that.fFlags)) {
71 // At least one is invalid and/or disabled.
72 if (kInvalid_PrivateFlag & (fFlags | that.fFlags)) {
73 return false; // We never allow invalid stencils to be equal.
74 }
75 // They're only equal if both are disabled.
76 return kDisabled_StencilFlag & (fFlags & that.fFlags);
77 }
78 if (kSingleSided_StencilFlag & (fFlags & that.fFlags)) {
79 return 0 == memcmp(&fFront, &that.fFront, sizeof(Face)); // Both are sin gle sided.
80 } else {
81 return 0 == memcmp(&fFront, &that.fFront, 2 * sizeof(Face));
82 GR_STATIC_ASSERT(sizeof(Face) ==
83 offsetof(GrStencilSettings, fBack) - offsetof(GrStencil Settings, fFront));
84 }
85 // memcmp relies on GrStencilSettings::Face being tightly packed.
86 GR_STATIC_ASSERT(0 == offsetof(Face, fRef));
87 GR_STATIC_ASSERT(2 == sizeof(Face::fRef));
88 GR_STATIC_ASSERT(2 == offsetof(Face, fTest));
89 GR_STATIC_ASSERT(2 == sizeof(Face::fTest));
90 GR_STATIC_ASSERT(4 == offsetof(Face, fTestMask));
91 GR_STATIC_ASSERT(2 == sizeof(Face::fTestMask));
92 GR_STATIC_ASSERT(6 == offsetof(Face, fPassOp));
93 GR_STATIC_ASSERT(1 == sizeof(Face::fPassOp));
94 GR_STATIC_ASSERT(7 == offsetof(Face, fFailOp));
95 GR_STATIC_ASSERT(1 == sizeof(Face::fFailOp));
96 GR_STATIC_ASSERT(8 == offsetof(Face, fWriteMask));
97 GR_STATIC_ASSERT(2 == sizeof(Face::fWriteMask));
98 GR_STATIC_ASSERT(10 == sizeof(Face));
99 }
100
101 static constexpr GrStencilTest gUserStencilTestToRaw[kGrUserStencilTestCount] = {
102 // Tests that respect the clip.
103 GrStencilTest::kAlways, // kAlwaysIfInClip (This is only for when there is not a stencil clip).
104 GrStencilTest::kEqual, // kEqualIfInClip.
105 GrStencilTest::kLess, // kLessIfInClip.
106 GrStencilTest::kLEqual, // kLEqualIfInClip.
107
108 // Tests that ignore the clip.
109 GrStencilTest::kAlways,
110 GrStencilTest::kNever,
111 GrStencilTest::kGreater,
112 GrStencilTest::kGEqual,
113 GrStencilTest::kLess,
114 GrStencilTest::kLEqual,
115 GrStencilTest::kEqual,
116 GrStencilTest::kNotEqual
117 };
118
119 GR_STATIC_ASSERT(0 == (int)GrUserStencilTest::kAlwaysIfInClip);
120 GR_STATIC_ASSERT(1 == (int)GrUserStencilTest::kEqualIfInClip);
121 GR_STATIC_ASSERT(2 == (int)GrUserStencilTest::kLessIfInClip);
122 GR_STATIC_ASSERT(3 == (int)GrUserStencilTest::kLEqualIfInClip);
123 GR_STATIC_ASSERT(4 == (int)GrUserStencilTest::kAlways);
124 GR_STATIC_ASSERT(5 == (int)GrUserStencilTest::kNever);
125 GR_STATIC_ASSERT(6 == (int)GrUserStencilTest::kGreater);
126 GR_STATIC_ASSERT(7 == (int)GrUserStencilTest::kGEqual);
127 GR_STATIC_ASSERT(8 == (int)GrUserStencilTest::kLess);
128 GR_STATIC_ASSERT(9 == (int)GrUserStencilTest::kLEqual);
129 GR_STATIC_ASSERT(10 == (int)GrUserStencilTest::kEqual);
130 GR_STATIC_ASSERT(11 == (int)GrUserStencilTest::kNotEqual);
131
132 static constexpr GrStencilOp gUserStencilOpToRaw[kGrUserStencilOpCount] = {
133 GrStencilOp::kKeep,
134
135 // Ops that only modify user bits.
136 GrStencilOp::kZero,
137 GrStencilOp::kReplace,
138 GrStencilOp::kInvert,
139 GrStencilOp::kIncWrap,
140 GrStencilOp::kDecWrap,
141 GrStencilOp::kIncClamp, // kIncMaybeClamp.
142 GrStencilOp::kDecClamp, // kDecMaybeClamp.
143
144 // Ops that only modify the clip bit.
145 GrStencilOp::kZero, // kZeroClipBit.
146 GrStencilOp::kReplace, // kSetClipBit.
147 GrStencilOp::kInvert, // kInvertClipBit.
148
149 // Ops that modify clip and user bits.
150 GrStencilOp::kReplace, // kSetClipAndReplaceUserBits.
151 GrStencilOp::kZero // kZeroClipAndUserBits.
152 };
153
154 GR_STATIC_ASSERT(0 == (int)GrUserStencilOp::kKeep);
155 GR_STATIC_ASSERT(1 == (int)GrUserStencilOp::kZero);
156 GR_STATIC_ASSERT(2 == (int)GrUserStencilOp::kReplace);
157 GR_STATIC_ASSERT(3 == (int)GrUserStencilOp::kInvert);
158 GR_STATIC_ASSERT(4 == (int)GrUserStencilOp::kIncWrap);
159 GR_STATIC_ASSERT(5 == (int)GrUserStencilOp::kDecWrap);
160 GR_STATIC_ASSERT(6 == (int)GrUserStencilOp::kIncMaybeClamp);
161 GR_STATIC_ASSERT(7 == (int)GrUserStencilOp::kDecMaybeClamp);
162 GR_STATIC_ASSERT(8 == (int)GrUserStencilOp::kZeroClipBit);
163 GR_STATIC_ASSERT(9 == (int)GrUserStencilOp::kSetClipBit);
164 GR_STATIC_ASSERT(10 == (int)GrUserStencilOp::kInvertClipBit);
165 GR_STATIC_ASSERT(11 == (int)GrUserStencilOp::kSetClipAndReplaceUserBits);
166 GR_STATIC_ASSERT(12 == (int)GrUserStencilOp::kZeroClipAndUserBits);
167
168 void GrStencilSettings::Face::reset(const GrUserStencilSettings::Face& user, boo l hasStencilClip,
169 int numStencilBits) {
170 SkASSERT(user.fTest < (GrUserStencilTest)kGrUserStencilTestCount);
171 SkASSERT(user.fPassOp < (GrUserStencilOp)kGrUserStencilOpCount);
172 SkASSERT(user.fFailOp < (GrUserStencilOp)kGrUserStencilOpCount);
173 SkASSERT(numStencilBits <= 16);
174 int clipBit = 1 << (numStencilBits - 1);
175 int userMask = clipBit - 1;
176
177 GrUserStencilOp maxOp = SkTMax(user.fPassOp, user.fFailOp);
178 SkDEBUGCODE(GrUserStencilOp otherOp = SkTMin(user.fPassOp, user.fFailOp);)
179 if (maxOp <= kLastUserOnlyStencilOp) {
180 // Ops that only modify user bits.
181 fWriteMask = user.fWriteMask & userMask;
182 SkASSERT(otherOp <= kLastUserOnlyStencilOp);
183 } else if (maxOp <= kLastClipOnlyStencilOp) {
184 // Ops that only modify the clip bit.
185 fWriteMask = clipBit;
186 SkASSERT(GrUserStencilOp::kKeep == otherOp ||
187 (otherOp > kLastUserOnlyStencilOp && otherOp <= kLastClipOnlySt encilOp));
188 } else {
189 // Ops that modify both clip and user bits.
190 fWriteMask = clipBit | (user.fWriteMask & userMask);
191 SkASSERT(GrUserStencilOp::kKeep == otherOp || otherOp > kLastClipOnlySte ncilOp);
192 }
193
194 fFailOp = gUserStencilOpToRaw[(int)user.fFailOp];
195 fPassOp = gUserStencilOpToRaw[(int)user.fPassOp];
196
197 if (!hasStencilClip || user.fTest > kLastClippedStencilTest) {
198 // Ignore the clip.
199 fTestMask = user.fTestMask & userMask;
200 fTest = gUserStencilTestToRaw[(int)user.fTest];
201 } else if (GrUserStencilTest::kAlwaysIfInClip != user.fTest) {
202 // Respect the clip.
203 fTestMask = clipBit | (user.fTestMask & userMask);
204 fTest = gUserStencilTestToRaw[(int)user.fTest];
205 } else {
206 // Test only for clip.
207 fTestMask = clipBit;
208 fTest = GrStencilTest::kEqual;
209 }
210
211 fRef = (clipBit | user.fRef) & (fTestMask | fWriteMask);
212 }
213
214 void GrStencilSettings::Face::setDisabled() {
215 memset(this, 0, sizeof(*this));
216 GR_STATIC_ASSERT(0 == (int)GrStencilTest::kAlways);
217 GR_STATIC_ASSERT(0 == (int)GrStencilOp::kKeep);
218 }
219
13 //////////////////////////////////////////////////////////////////////////////// 220 ////////////////////////////////////////////////////////////////////////////////
14 // Stencil Rules for Merging user stencil space into clip 221 // Stencil Rules for Merging user stencil space into clip
15 222 //
16 // We can't include the clip bit in the ref or mask values because the division
17 // between user and clip bits in the stencil depends on the number of stencil
18 // bits in the runtime. Comments below indicate what the code should do to
19 // incorporate the clip bit into these settings.
20 223
21 /////// 224 ///////
22 // Replace 225 // Replace
23 226 static constexpr GrUserStencilSettings gUserToClipReplace(
24 // set the ref to be the clip bit, but mask it out for the test 227 GrUserStencilSettings::StaticInit<
25 static constexpr GrStencilSettings gUserToClipReplace( 228 0x0000,
26 kReplace_StencilOp, 229 GrUserStencilTest::kNotEqual,
27 kZero_StencilOp, 230 0xffff,
28 kLess_StencilFunc, 231 GrUserStencilOp::kSetClipAndReplaceUserBits,
29 0xffff, // unset clip bit 232 GrUserStencilOp::kZeroClipAndUserBits,
30 0x0000, // set clip bit 233 0xffff>()
31 0xffff); 234 );
32 235
33 static constexpr GrStencilSettings gInvUserToClipReplace( 236 static constexpr GrUserStencilSettings gInvUserToClipReplace(
34 kReplace_StencilOp, 237 GrUserStencilSettings::StaticInit<
35 kZero_StencilOp, 238 0x0000,
36 kEqual_StencilFunc, 239 GrUserStencilTest::kEqual,
37 0xffff, // unset clip bit 240 0xffff,
38 0x0000, // set clip bit 241 GrUserStencilOp::kSetClipAndReplaceUserBits,
39 0xffff); 242 GrUserStencilOp::kZeroClipAndUserBits,
243 0xffff>()
244 );
40 245
41 /////// 246 ///////
42 // Intersect 247 // Intersect
43 static constexpr GrStencilSettings gUserToClipIsect( 248 static constexpr GrUserStencilSettings gUserToClipIsect(
44 kReplace_StencilOp, 249 GrUserStencilSettings::StaticInit<
45 kZero_StencilOp, 250 0x0000,
46 kLess_StencilFunc, 251 GrUserStencilTest::kLessIfInClip, // "0 < userBits" is equivalent to "0 != userBits".
47 0xffff, 252 0xffff,
48 0x0000, // set clip bit 253 GrUserStencilOp::kSetClipAndReplaceUserBits,
49 0xffff); 254 GrUserStencilOp::kZeroClipAndUserBits,
50 255 0xffff>()
51 static constexpr GrStencilSettings gInvUserToClipIsect( 256 );
52 kReplace_StencilOp,
53 kZero_StencilOp,
54 kEqual_StencilFunc,
55 0xffff,
56 0x0000, // set clip bit
57 0xffff);
58 257
59 /////// 258 ///////
60 // Difference 259 // Difference
61 static constexpr GrStencilSettings gUserToClipDiff( 260 static constexpr GrUserStencilSettings gUserToClipDiff(
62 kReplace_StencilOp, 261 GrUserStencilSettings::StaticInit<
63 kZero_StencilOp, 262 0x0000,
64 kEqual_StencilFunc, 263 GrUserStencilTest::kEqualIfInClip,
65 0xffff, 264 0xffff,
66 0x0000, // set clip bit 265 GrUserStencilOp::kSetClipAndReplaceUserBits,
67 0xffff); 266 GrUserStencilOp::kZeroClipAndUserBits,
68 267 0xffff>()
69 static constexpr GrStencilSettings gInvUserToClipDiff( 268 );
70 kReplace_StencilOp,
71 kZero_StencilOp,
72 kLess_StencilFunc,
73 0xffff,
74 0x0000, // set clip bit
75 0xffff);
76 269
77 /////// 270 ///////
78 // Union 271 // Union
79 272 static constexpr GrUserStencilSettings gUserToClipUnion(
80 // first pass makes all the passing cases >= just clip bit set. 273 GrUserStencilSettings::StaticInit<
81 static constexpr GrStencilSettings gUserToClipUnionPass0( 274 0x0000,
82 kReplace_StencilOp, 275 GrUserStencilTest::kNotEqual,
83 kKeep_StencilOp, 276 0xffff,
84 kLEqual_StencilFunc, 277 GrUserStencilOp::kSetClipAndReplaceUserBits,
85 0xffff, 278 GrUserStencilOp::kKeep,
86 0x0001, // set clip bit 279 0xffff>()
87 0xffff); 280 );
88 281
89 // second pass allows anything greater than just clip bit set to pass 282 static constexpr GrUserStencilSettings gInvUserToClipUnionPass0( // Does not zer o user bits.
90 static constexpr GrStencilSettings gUserToClipUnionPass1( 283 GrUserStencilSettings::StaticInit<
91 kReplace_StencilOp, 284 0x0000,
92 kZero_StencilOp, 285 GrUserStencilTest::kEqual,
93 kLEqual_StencilFunc, 286 0xffff,
94 0xffff, 287 GrUserStencilOp::kSetClipBit,
95 0x0000, // set clip bit 288 GrUserStencilOp::kKeep,
96 0xffff); 289 0x0000>()
97
98 // first pass finds zeros in the user bits and if found sets
99 // the clip bit to 1
100 static constexpr GrStencilSettings gInvUserToClipUnionPass0(
101 kReplace_StencilOp,
102 kKeep_StencilOp,
103 kEqual_StencilFunc,
104 0xffff,
105 0x0000, // set clip bit
106 0x0000 // set clip bit
107 );
108
109 // second pass zeros the user bits
110 static constexpr GrStencilSettings gInvUserToClipUnionPass1(
111 kZero_StencilOp,
112 kZero_StencilOp,
113 kLess_StencilFunc,
114 0xffff,
115 0x0000,
116 0xffff // unset clip bit
117 ); 290 );
118 291
119 /////// 292 ///////
120 // Xor 293 // Xor
121 static constexpr GrStencilSettings gUserToClipXorPass0( 294 static constexpr GrUserStencilSettings gUserToClipXorPass0( // Does not zero use r bits.
122 kInvert_StencilOp, 295 GrUserStencilSettings::StaticInit<
123 kKeep_StencilOp, 296 0x0000,
124 kEqual_StencilFunc, 297 GrUserStencilTest::kNotEqual,
125 0xffff, // unset clip bit 298 0xffff,
126 0x0000, 299 GrUserStencilOp::kInvertClipBit,
127 0xffff); 300 GrUserStencilOp::kKeep,
128 301 0x0000>()
129 static constexpr GrStencilSettings gUserToClipXorPass1( 302 );
130 kReplace_StencilOp, 303
131 kZero_StencilOp, 304 static constexpr GrUserStencilSettings gInvUserToClipXorPass0( // Does not zero user bits.
132 kGreater_StencilFunc, 305 GrUserStencilSettings::StaticInit<
133 0xffff, 306 0x0000,
134 0x0000, // set clip bit 307 GrUserStencilTest::kEqual,
135 0xffff); 308 0xffff,
136 309 GrUserStencilOp::kInvertClipBit,
137 static constexpr GrStencilSettings gInvUserToClipXorPass0( 310 GrUserStencilOp::kKeep,
138 kInvert_StencilOp, 311 0x0000>()
139 kKeep_StencilOp, 312 );
140 kEqual_StencilFunc,
141 0xffff, // unset clip bit
142 0x0000,
143 0xffff);
144
145 static constexpr GrStencilSettings gInvUserToClipXorPass1(
146 kReplace_StencilOp,
147 kZero_StencilOp,
148 kLess_StencilFunc,
149 0xffff,
150 0x0000, // set clip bit
151 0xffff);
152 313
153 /////// 314 ///////
154 // Reverse Diff 315 // Reverse Diff
155 static constexpr GrStencilSettings gUserToClipRDiffPass0( 316 static constexpr GrUserStencilSettings gUserToClipRDiffPass0( // Does not zero u ser bits.
156 kInvert_StencilOp, 317 GrUserStencilSettings::StaticInit<
157 kZero_StencilOp, 318 0x0000,
158 kLess_StencilFunc, 319 GrUserStencilTest::kNotEqual,
159 0xffff, // unset clip bit 320 0xffff,
160 0x0000, // set clip bit 321 GrUserStencilOp::kInvertClipBit,
161 0xffff); 322 GrUserStencilOp::kZeroClipBit,
162 323 0x0000>()
163 static constexpr GrStencilSettings gUserToClipRDiffPass1( 324 );
164 kReplace_StencilOp, 325
165 kZero_StencilOp, 326 static constexpr GrUserStencilSettings gInvUserToClipRDiffPass0( // Does not zer o user bits.
166 kEqual_StencilFunc, 327 GrUserStencilSettings::StaticInit<
167 0x0000, // set clip bit 328 0x0000,
168 0x0000, // set clip bit 329 GrUserStencilTest::kEqual,
169 0xffff); 330 0xffff,
170 331 GrUserStencilOp::kInvertClipBit,
171 // We are looking for stencil values that are all zero. The first pass sets the 332 GrUserStencilOp::kZeroClipBit,
172 // clip bit if the stencil is all zeros. The second pass clears the user bits. 333 0x0000>()
173 static constexpr GrStencilSettings gInvUserToClipRDiffPass0( 334 );
174 kInvert_StencilOp, 335
175 kZero_StencilOp, 336 ///////
176 kEqual_StencilFunc, 337 // Second pass to clear user bits (only needed sometimes)
177 0xffff, 338 static constexpr GrUserStencilSettings gZeroUserBits(
178 0x0000, 339 GrUserStencilSettings::StaticInit<
179 0x0000 // set clip bit 340 0x0000,
180 ); 341 GrUserStencilTest::kNotEqual,
181 342 0xffff,
182 static constexpr GrStencilSettings gInvUserToClipRDiffPass1( 343 GrUserStencilOp::kZero,
183 kZero_StencilOp, 344 GrUserStencilOp::kKeep,
184 kZero_StencilOp, 345 0xffff>()
185 kAlways_StencilFunc, 346 );
186 0xffff, 347
187 0x0000, 348 static constexpr const GrUserStencilSettings* gUserToClipTable[2][1 + SkRegion:: kLastOp][3] = {
188 0xffff // unset clip bit 349 { /* Normal fill. */
189 ); 350 {&gUserToClipDiff, nullptr, nullptr}, // kDifference_ Op.
351 {&gUserToClipIsect, nullptr, nullptr}, // kIntersect_O p.
352 {&gUserToClipUnion, nullptr, nullptr}, // kUnion_Op.
353 {&gUserToClipXorPass0, &gZeroUserBits, nullptr}, // kXOR_Op.
354 {&gUserToClipRDiffPass0, &gZeroUserBits, nullptr}, // kReverseDiff erence_Op.
355 {&gUserToClipReplace, nullptr, nullptr} // kReplace_Op.
356
357 }, /* Inverse fill. */ {
358 {&gUserToClipIsect, nullptr, nullptr}, // ~diff (aka i sect).
359 {&gUserToClipDiff, nullptr, nullptr}, // ~isect (aka diff).
360 {&gInvUserToClipUnionPass0, &gZeroUserBits, nullptr}, // ~union.
361 {&gInvUserToClipXorPass0, &gZeroUserBits, nullptr}, // ~xor.
362 {&gInvUserToClipRDiffPass0, &gZeroUserBits, nullptr}, // ~reverse dif f.
363 {&gInvUserToClipReplace, nullptr, nullptr} // ~replace.
364 }
365 };
366
367 GR_STATIC_ASSERT(0 == SkRegion::kDifference_Op);
368 GR_STATIC_ASSERT(1 == SkRegion::kIntersect_Op);
369 GR_STATIC_ASSERT(2 == SkRegion::kUnion_Op);
370 GR_STATIC_ASSERT(3 == SkRegion::kXOR_Op);
371 GR_STATIC_ASSERT(4 == SkRegion::kReverseDifference_Op);
372 GR_STATIC_ASSERT(5 == SkRegion::kReplace_Op);
190 373
191 /////// 374 ///////
192 // Direct to Stencil 375 // Direct to Stencil
193 376
194 // We can render a clip element directly without first writing to the client 377 // We can render a clip element directly without first writing to the client
195 // portion of the clip when the fill is not inverse and the set operation will 378 // portion of the clip when the fill is not inverse and the set operation will
196 // only modify the in/out status of samples covered by the clip element. 379 // only modify the in/out status of samples covered by the clip element.
197 380
198 // this one only works if used right after stencil clip was cleared. 381 // this one only works if used right after stencil clip was cleared.
199 // Our clip mask creation code doesn't allow midstream replace ops. 382 // Our clip mask creation code doesn't allow midstream replace ops.
200 static constexpr GrStencilSettings gReplaceClip( 383 static constexpr GrUserStencilSettings gReplaceClip(
201 kReplace_StencilOp, 384 GrUserStencilSettings::StaticInit<
202 kReplace_StencilOp, 385 0x0000,
203 kAlways_StencilFunc, 386 GrUserStencilTest::kAlways,
204 0xffff, 387 0xffff,
205 0x0000, // set clip bit 388 GrUserStencilOp::kSetClipBit,
206 0x0000 // set clipBit 389 GrUserStencilOp::kSetClipBit,
390 0x0000>()
207 ); 391 );
208 392
209 static constexpr GrStencilSettings gUnionClip( 393 static constexpr GrUserStencilSettings gUnionClip(
210 kReplace_StencilOp, 394 GrUserStencilSettings::StaticInit<
211 kReplace_StencilOp, 395 0x0000,
212 kAlways_StencilFunc, 396 GrUserStencilTest::kAlwaysIfInClip,
213 0xffff, 397 0xffff,
214 0x0000, // set clip bit 398 GrUserStencilOp::kKeep,
215 0x0000 // set clip bit 399 GrUserStencilOp::kSetClipBit,
400 0x0000>()
216 ); 401 );
217 402
218 static constexpr GrStencilSettings gXorClip( 403 static constexpr GrUserStencilSettings gXorClip(
219 kInvert_StencilOp, 404 GrUserStencilSettings::StaticInit<
220 kInvert_StencilOp, 405 0x0000,
221 kAlways_StencilFunc, 406 GrUserStencilTest::kAlways,
222 0xffff, 407 0xffff,
223 0x0000, 408 GrUserStencilOp::kInvertClipBit,
224 0x0000 // set clip bit 409 GrUserStencilOp::kInvertClipBit,
410 0x0000>()
225 ); 411 );
226 412
227 static constexpr GrStencilSettings gDiffClip( 413 static constexpr GrUserStencilSettings gDiffClip(
228 kZero_StencilOp, 414 GrUserStencilSettings::StaticInit<
229 kZero_StencilOp, 415 0x0000,
230 kAlways_StencilFunc, 416 GrUserStencilTest::kAlwaysIfInClip,
231 0xffff, 417 0xffff,
232 0x0000, 418 GrUserStencilOp::kZeroClipBit,
233 0x0000 // set clip bit 419 GrUserStencilOp::kKeep,
420 0x0000>()
234 ); 421 );
235 422
236 bool GrStencilSettings::GetClipPasses( 423 static constexpr const GrUserStencilSettings* gDirectDrawTable[1 + SkRegion::kLa stOp][2] = {
237 SkRegion::Op op, 424 {&gDiffClip, nullptr}, // kDifference_Op.
238 bool canBeDirect, 425 {nullptr, nullptr}, // kIntersect_Op.
239 unsigned int stencilClipMask, 426 {&gUnionClip, nullptr}, // kUnion_Op.
240 bool invertedFill, 427 {&gXorClip, nullptr}, // kXOR_Op.
241 int* numPasses, 428 {nullptr, nullptr}, // kReverseDifference_Op.
242 GrStencilSettings settings[kMaxStencilClipPasses]) { 429 {&gReplaceClip, nullptr} // kReplace_Op.
243 if (canBeDirect && !invertedFill) { 430 };
244 *numPasses = 0; 431
245 switch (op) { 432 GR_STATIC_ASSERT(0 == SkRegion::kDifference_Op);
246 case SkRegion::kReplace_Op: 433 GR_STATIC_ASSERT(1 == SkRegion::kIntersect_Op);
247 *numPasses = 1; 434 GR_STATIC_ASSERT(2 == SkRegion::kUnion_Op);
248 settings[0] = gReplaceClip; 435 GR_STATIC_ASSERT(3 == SkRegion::kXOR_Op);
249 break; 436 GR_STATIC_ASSERT(4 == SkRegion::kReverseDifference_Op);
250 case SkRegion::kUnion_Op: 437 GR_STATIC_ASSERT(5 == SkRegion::kReplace_Op);
251 *numPasses = 1; 438
252 settings[0] = gUnionClip; 439 GrUserStencilSettings const* const* GrStencilSettings::GetClipPasses(SkRegion::O p op,
253 break; 440 bool canBeD irect,
254 case SkRegion::kXOR_Op: 441 bool invert edFill,
255 *numPasses = 1; 442 bool* drawD irectToClip) {
256 settings[0] = gXorClip; 443 SkASSERT((unsigned)op <= SkRegion::kLastOp);
257 break; 444 if (canBeDirect && !invertedFill) { // TODO: inverse fill + intersect op can be direct.
258 case SkRegion::kDifference_Op: 445 GrUserStencilSettings const* const* directPass = gDirectDrawTable[op];
259 *numPasses = 1; 446 if (directPass[0]) {
260 settings[0] = gDiffClip; 447 *drawDirectToClip = true;
261 break; 448 return directPass;
262 default: // suppress warning
263 break;
264 }
265 if (1 == *numPasses) {
266 settings[0].fFuncRefs[kFront_Face] |= stencilClipMask;
267 settings[0].fWriteMasks[kFront_Face] |= stencilClipMask;
268 settings[0].fFuncRefs[kBack_Face] =
269 settings[0].fFuncRefs[kFront_Face];
270 settings[0].fWriteMasks[kBack_Face] =
271 settings[0].fWriteMasks[kFront_Face];
272 return true;
273 } 449 }
274 } 450 }
275 switch (op) { 451 *drawDirectToClip = false;
276 // if we make the path renderer go to stencil we always give it a 452 return gUserToClipTable[invertedFill][op];
277 // non-inverted fill and we use the stencil rules on the client->clipbit
278 // pass to select either the zeros or nonzeros.
279 case SkRegion::kReplace_Op:
280 *numPasses= 1;
281 settings[0] = invertedFill ? gInvUserToClipReplace :
282 gUserToClipReplace;
283 settings[0].fFuncMasks[kFront_Face] &= ~stencilClipMask;
284 settings[0].fFuncRefs[kFront_Face] |= stencilClipMask;
285 settings[0].fFuncMasks[kBack_Face] =
286 settings[0].fFuncMasks[kFront_Face];
287 settings[0].fFuncRefs[kBack_Face] =
288 settings[0].fFuncRefs[kFront_Face];
289 break;
290 case SkRegion::kIntersect_Op:
291 *numPasses = 1;
292 settings[0] = invertedFill ? gInvUserToClipIsect : gUserToClipIsect;
293 settings[0].fFuncRefs[kFront_Face] = stencilClipMask;
294 settings[0].fFuncRefs[kBack_Face] =
295 settings[0].fFuncRefs[kFront_Face];
296 break;
297 case SkRegion::kUnion_Op:
298 *numPasses = 2;
299 if (invertedFill) {
300 settings[0] = gInvUserToClipUnionPass0;
301 settings[0].fFuncMasks[kFront_Face] &= ~stencilClipMask;
302 settings[0].fFuncMasks[kBack_Face] =
303 settings[0].fFuncMasks[kFront_Face];
304 settings[0].fFuncRefs[kFront_Face] |= stencilClipMask;
305 settings[0].fFuncRefs[kBack_Face] =
306 settings[0].fFuncRefs[kFront_Face];
307 settings[0].fWriteMasks[kFront_Face] |= stencilClipMask;
308 settings[0].fWriteMasks[kBack_Face] =
309 settings[0].fWriteMasks[kFront_Face];
310
311 settings[1] = gInvUserToClipUnionPass1;
312 settings[1].fWriteMasks[kFront_Face] &= ~stencilClipMask;
313 settings[1].fWriteMasks[kBack_Face] &=
314 settings[1].fWriteMasks[kFront_Face];
315
316 } else {
317 settings[0] = gUserToClipUnionPass0;
318 settings[0].fFuncMasks[kFront_Face] &= ~stencilClipMask;
319 settings[0].fFuncRefs[kFront_Face] |= stencilClipMask;
320 settings[0].fFuncMasks[kBack_Face] =
321 settings[0].fFuncMasks[kFront_Face];
322 settings[0].fFuncRefs[kBack_Face] =
323 settings[0].fFuncRefs[kFront_Face];
324
325 settings[1] = gUserToClipUnionPass1;
326 settings[1].fFuncRefs[kFront_Face] |= stencilClipMask;
327 settings[1].fFuncRefs[kBack_Face] =
328 settings[1].fFuncRefs[kFront_Face];
329 }
330 break;
331 case SkRegion::kXOR_Op:
332 *numPasses = 2;
333 if (invertedFill) {
334 settings[0] = gInvUserToClipXorPass0;
335 settings[0].fFuncMasks[kFront_Face] &= ~stencilClipMask;
336 settings[0].fFuncMasks[kBack_Face] =
337 settings[0].fFuncMasks[kFront_Face];
338
339 settings[1] = gInvUserToClipXorPass1;
340 settings[1].fFuncRefs[kFront_Face] |= stencilClipMask;
341 settings[1].fFuncRefs[kBack_Face] =
342 settings[1].fFuncRefs[kFront_Face];
343 } else {
344 settings[0] = gUserToClipXorPass0;
345 settings[0].fFuncMasks[kFront_Face] &= ~stencilClipMask;
346 settings[0].fFuncMasks[kBack_Face] =
347 settings[0].fFuncMasks[kFront_Face];
348
349 settings[1] = gUserToClipXorPass1;
350 settings[1].fFuncRefs[kFront_Face] |= stencilClipMask;
351 settings[1].fFuncRefs[kBack_Face] =
352 settings[1].fFuncRefs[kFront_Face];
353 }
354 break;
355 case SkRegion::kDifference_Op:
356 *numPasses = 1;
357 settings[0] = invertedFill ? gInvUserToClipDiff : gUserToClipDiff;
358 settings[0].fFuncRefs[kFront_Face] |= stencilClipMask;
359 settings[0].fFuncRefs[kBack_Face] =
360 settings[0].fFuncRefs[kFront_Face];
361 break;
362 case SkRegion::kReverseDifference_Op:
363 if (invertedFill) {
364 *numPasses = 2;
365 settings[0] = gInvUserToClipRDiffPass0;
366 settings[0].fWriteMasks[kFront_Face] |= stencilClipMask;
367 settings[0].fWriteMasks[kBack_Face] =
368 settings[0].fWriteMasks[kFront_Face];
369 settings[1] = gInvUserToClipRDiffPass1;
370 settings[1].fWriteMasks[kFront_Face] &= ~stencilClipMask;
371 settings[1].fWriteMasks[kBack_Face] =
372 settings[1].fWriteMasks[kFront_Face];
373 } else {
374 *numPasses = 2;
375 settings[0] = gUserToClipRDiffPass0;
376 settings[0].fFuncMasks[kFront_Face] &= ~stencilClipMask;
377 settings[0].fFuncMasks[kBack_Face] =
378 settings[0].fFuncMasks[kFront_Face];
379 settings[0].fFuncRefs[kFront_Face] |= stencilClipMask;
380 settings[0].fFuncRefs[kBack_Face] =
381 settings[0].fFuncRefs[kFront_Face];
382
383 settings[1] = gUserToClipRDiffPass1;
384 settings[1].fFuncMasks[kFront_Face] |= stencilClipMask;
385 settings[1].fFuncRefs[kFront_Face] |= stencilClipMask;
386 settings[1].fFuncMasks[kBack_Face] =
387 settings[1].fFuncMasks[kFront_Face];
388 settings[1].fFuncRefs[kBack_Face] =
389 settings[1].fFuncRefs[kFront_Face];
390 }
391 break;
392 default:
393 SkFAIL("Unknown set op");
394 }
395 return false;
396 } 453 }
397 454
398 void GrStencilSettings::genKey(GrProcessorKeyBuilder* b) const { 455 void GrStencilSettings::genKey(GrProcessorKeyBuilder* b) const {
399 static const int kCount = sizeof(GrStencilSettings) / sizeof(uint32_t); 456 b->add32(fFlags);
400 GR_STATIC_ASSERT(0 == sizeof(GrStencilSettings) % sizeof(uint32_t)); 457 if (this->isDisabled()) {
401 uint32_t* key = b->add32n(kCount); 458 return;
402 memcpy(key, this, sizeof(GrStencilSettings)); 459 }
460 if (!this->isTwoSided()) {
461 constexpr int kCount16 = sizeof(Face) / sizeof(uint16_t);
462 GR_STATIC_ASSERT(0 == sizeof(Face) % sizeof(uint16_t));
463 uint16_t* key = reinterpret_cast<uint16_t*>(b->add32n((kCount16 + 1) / 2 ));
464 memcpy(key, &fFront, sizeof(Face));
465 key[kCount16] = 0;
466 GR_STATIC_ASSERT(1 == kCount16 % 2);
467 } else {
468 constexpr int kCount32 = (2 * sizeof(Face)) / sizeof(uint32_t);
469 GR_STATIC_ASSERT(0 == (2 * sizeof(Face)) % sizeof(uint32_t));
470 uint32_t* key = b->add32n(kCount32);
471 memcpy(key, &fFront, 2 * sizeof(Face));
472 GR_STATIC_ASSERT(sizeof(Face) ==
473 offsetof(GrStencilSettings, fBack) - offsetof(GrStencil Settings, fFront));
474 }
475 // We rely on GrStencilSettings::Face being tightly packed for the key to be reliable.
476 GR_STATIC_ASSERT(0 == offsetof(Face, fRef));
477 GR_STATIC_ASSERT(2 == sizeof(Face::fRef));
478 GR_STATIC_ASSERT(2 == offsetof(Face, fTest));
479 GR_STATIC_ASSERT(2 == sizeof(Face::fTest));
480 GR_STATIC_ASSERT(4 == offsetof(Face, fTestMask));
481 GR_STATIC_ASSERT(2 == sizeof(Face::fTestMask));
482 GR_STATIC_ASSERT(6 == offsetof(Face, fPassOp));
483 GR_STATIC_ASSERT(1 == sizeof(Face::fPassOp));
484 GR_STATIC_ASSERT(7 == offsetof(Face, fFailOp));
485 GR_STATIC_ASSERT(1 == sizeof(Face::fFailOp));
486 GR_STATIC_ASSERT(8 == offsetof(Face, fWriteMask));
487 GR_STATIC_ASSERT(2 == sizeof(Face::fWriteMask));
488 GR_STATIC_ASSERT(10 == sizeof(Face));
403 } 489 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698