OLD | NEW |
| (Empty) |
1 /* | |
2 * Copyright 2011 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 #include "GrStencilSettings.h" | |
10 | |
11 #include "GrProcessor.h" | |
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 | |
220 //////////////////////////////////////////////////////////////////////////////// | |
221 // Stencil Rules for Merging user stencil space into clip | |
222 // | |
223 | |
224 /////// | |
225 // Replace | |
226 static constexpr GrUserStencilSettings gUserToClipReplace( | |
227 GrUserStencilSettings::StaticInit< | |
228 0x0000, | |
229 GrUserStencilTest::kNotEqual, | |
230 0xffff, | |
231 GrUserStencilOp::kSetClipAndReplaceUserBits, | |
232 GrUserStencilOp::kZeroClipAndUserBits, | |
233 0xffff>() | |
234 ); | |
235 | |
236 static constexpr GrUserStencilSettings gInvUserToClipReplace( | |
237 GrUserStencilSettings::StaticInit< | |
238 0x0000, | |
239 GrUserStencilTest::kEqual, | |
240 0xffff, | |
241 GrUserStencilOp::kSetClipAndReplaceUserBits, | |
242 GrUserStencilOp::kZeroClipAndUserBits, | |
243 0xffff>() | |
244 ); | |
245 | |
246 /////// | |
247 // Intersect | |
248 static constexpr GrUserStencilSettings gUserToClipIsect( | |
249 GrUserStencilSettings::StaticInit< | |
250 0x0000, | |
251 GrUserStencilTest::kLessIfInClip, // "0 < userBits" is equivalent to "0
!= userBits". | |
252 0xffff, | |
253 GrUserStencilOp::kSetClipAndReplaceUserBits, | |
254 GrUserStencilOp::kZeroClipAndUserBits, | |
255 0xffff>() | |
256 ); | |
257 | |
258 /////// | |
259 // Difference | |
260 static constexpr GrUserStencilSettings gUserToClipDiff( | |
261 GrUserStencilSettings::StaticInit< | |
262 0x0000, | |
263 GrUserStencilTest::kEqualIfInClip, | |
264 0xffff, | |
265 GrUserStencilOp::kSetClipAndReplaceUserBits, | |
266 GrUserStencilOp::kZeroClipAndUserBits, | |
267 0xffff>() | |
268 ); | |
269 | |
270 /////// | |
271 // Union | |
272 static constexpr GrUserStencilSettings gUserToClipUnion( | |
273 GrUserStencilSettings::StaticInit< | |
274 0x0000, | |
275 GrUserStencilTest::kNotEqual, | |
276 0xffff, | |
277 GrUserStencilOp::kSetClipAndReplaceUserBits, | |
278 GrUserStencilOp::kKeep, | |
279 0xffff>() | |
280 ); | |
281 | |
282 static constexpr GrUserStencilSettings gInvUserToClipUnionPass0( // Does not zer
o user bits. | |
283 GrUserStencilSettings::StaticInit< | |
284 0x0000, | |
285 GrUserStencilTest::kEqual, | |
286 0xffff, | |
287 GrUserStencilOp::kSetClipBit, | |
288 GrUserStencilOp::kKeep, | |
289 0x0000>() | |
290 ); | |
291 | |
292 /////// | |
293 // Xor | |
294 static constexpr GrUserStencilSettings gUserToClipXorPass0( // Does not zero use
r bits. | |
295 GrUserStencilSettings::StaticInit< | |
296 0x0000, | |
297 GrUserStencilTest::kNotEqual, | |
298 0xffff, | |
299 GrUserStencilOp::kInvertClipBit, | |
300 GrUserStencilOp::kKeep, | |
301 0x0000>() | |
302 ); | |
303 | |
304 static constexpr GrUserStencilSettings gInvUserToClipXorPass0( // Does not zero
user bits. | |
305 GrUserStencilSettings::StaticInit< | |
306 0x0000, | |
307 GrUserStencilTest::kEqual, | |
308 0xffff, | |
309 GrUserStencilOp::kInvertClipBit, | |
310 GrUserStencilOp::kKeep, | |
311 0x0000>() | |
312 ); | |
313 | |
314 /////// | |
315 // Reverse Diff | |
316 static constexpr GrUserStencilSettings gUserToClipRDiffPass0( // Does not zero u
ser bits. | |
317 GrUserStencilSettings::StaticInit< | |
318 0x0000, | |
319 GrUserStencilTest::kNotEqual, | |
320 0xffff, | |
321 GrUserStencilOp::kInvertClipBit, | |
322 GrUserStencilOp::kZeroClipBit, | |
323 0x0000>() | |
324 ); | |
325 | |
326 static constexpr GrUserStencilSettings gInvUserToClipRDiffPass0( // Does not zer
o user bits. | |
327 GrUserStencilSettings::StaticInit< | |
328 0x0000, | |
329 GrUserStencilTest::kEqual, | |
330 0xffff, | |
331 GrUserStencilOp::kInvertClipBit, | |
332 GrUserStencilOp::kZeroClipBit, | |
333 0x0000>() | |
334 ); | |
335 | |
336 /////// | |
337 // Second pass to clear user bits (only needed sometimes) | |
338 static constexpr GrUserStencilSettings gZeroUserBits( | |
339 GrUserStencilSettings::StaticInit< | |
340 0x0000, | |
341 GrUserStencilTest::kNotEqual, | |
342 0xffff, | |
343 GrUserStencilOp::kZero, | |
344 GrUserStencilOp::kKeep, | |
345 0xffff>() | |
346 ); | |
347 | |
348 static constexpr const GrUserStencilSettings* gUserToClipTable[2][1 + SkRegion::
kLastOp][3] = { | |
349 { /* Normal fill. */ | |
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); | |
373 | |
374 /////// | |
375 // Direct to Stencil | |
376 | |
377 // We can render a clip element directly without first writing to the client | |
378 // portion of the clip when the fill is not inverse and the set operation will | |
379 // only modify the in/out status of samples covered by the clip element. | |
380 | |
381 // this one only works if used right after stencil clip was cleared. | |
382 // Our clip mask creation code doesn't allow midstream replace ops. | |
383 static constexpr GrUserStencilSettings gReplaceClip( | |
384 GrUserStencilSettings::StaticInit< | |
385 0x0000, | |
386 GrUserStencilTest::kAlways, | |
387 0xffff, | |
388 GrUserStencilOp::kSetClipBit, | |
389 GrUserStencilOp::kSetClipBit, | |
390 0x0000>() | |
391 ); | |
392 | |
393 static constexpr GrUserStencilSettings gUnionClip( | |
394 GrUserStencilSettings::StaticInit< | |
395 0x0000, | |
396 GrUserStencilTest::kAlwaysIfInClip, | |
397 0xffff, | |
398 GrUserStencilOp::kKeep, | |
399 GrUserStencilOp::kSetClipBit, | |
400 0x0000>() | |
401 ); | |
402 | |
403 static constexpr GrUserStencilSettings gXorClip( | |
404 GrUserStencilSettings::StaticInit< | |
405 0x0000, | |
406 GrUserStencilTest::kAlways, | |
407 0xffff, | |
408 GrUserStencilOp::kInvertClipBit, | |
409 GrUserStencilOp::kInvertClipBit, | |
410 0x0000>() | |
411 ); | |
412 | |
413 static constexpr GrUserStencilSettings gDiffClip( | |
414 GrUserStencilSettings::StaticInit< | |
415 0x0000, | |
416 GrUserStencilTest::kAlwaysIfInClip, | |
417 0xffff, | |
418 GrUserStencilOp::kZeroClipBit, | |
419 GrUserStencilOp::kKeep, | |
420 0x0000>() | |
421 ); | |
422 | |
423 static constexpr const GrUserStencilSettings* gDirectDrawTable[1 + SkRegion::kLa
stOp][2] = { | |
424 {&gDiffClip, nullptr}, // kDifference_Op. | |
425 {nullptr, nullptr}, // kIntersect_Op. | |
426 {&gUnionClip, nullptr}, // kUnion_Op. | |
427 {&gXorClip, nullptr}, // kXOR_Op. | |
428 {nullptr, nullptr}, // kReverseDifference_Op. | |
429 {&gReplaceClip, nullptr} // kReplace_Op. | |
430 }; | |
431 | |
432 GR_STATIC_ASSERT(0 == SkRegion::kDifference_Op); | |
433 GR_STATIC_ASSERT(1 == SkRegion::kIntersect_Op); | |
434 GR_STATIC_ASSERT(2 == SkRegion::kUnion_Op); | |
435 GR_STATIC_ASSERT(3 == SkRegion::kXOR_Op); | |
436 GR_STATIC_ASSERT(4 == SkRegion::kReverseDifference_Op); | |
437 GR_STATIC_ASSERT(5 == SkRegion::kReplace_Op); | |
438 | |
439 GrUserStencilSettings const* const* GrStencilSettings::GetClipPasses(SkRegion::O
p op, | |
440 bool canBeD
irect, | |
441 bool invert
edFill, | |
442 bool* drawD
irectToClip) { | |
443 SkASSERT((unsigned)op <= SkRegion::kLastOp); | |
444 if (canBeDirect && !invertedFill) { // TODO: inverse fill + intersect op can
be direct. | |
445 GrUserStencilSettings const* const* directPass = gDirectDrawTable[op]; | |
446 if (directPass[0]) { | |
447 *drawDirectToClip = true; | |
448 return directPass; | |
449 } | |
450 } | |
451 *drawDirectToClip = false; | |
452 return gUserToClipTable[invertedFill][op]; | |
453 } | |
454 | |
455 void GrStencilSettings::genKey(GrProcessorKeyBuilder* b) const { | |
456 b->add32(fFlags); | |
457 if (this->isDisabled()) { | |
458 return; | |
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)); | |
489 } | |
OLD | NEW |