1
2 /*
3 * Copyright 2011 Google Inc.
4 *
5 * Use of this source code is governed by a BSD-style license that can be
6 * found in the LICENSE file.
7 */
8
9
10 #include "GrStencil.h"
11
12 ////////////////////////////////////////////////////////////////////////////////
13 // Stencil Rules for Merging user stencil space into clip
14
15 // We can't include the clip bit in the ref or mask values because the division
16 // between user and clip bits in the stencil depends on the number of stencil
17 // bits in the runtime. Comments below indicate what the code should do to
18 // incorporate the clip bit into these settings.
19
20 ///////
21 // Replace
22
23 // set the ref to be the clip bit, but mask it out for the test
24 GR_STATIC_CONST_SAME_STENCIL(gUserToClipReplace,
25 kReplace_StencilOp,
26 kZero_StencilOp,
27 kLess_StencilFunc,
28 0xffff, // unset clip bit
29 0x0000, // set clip bit
30 0xffff);
31
32 GR_STATIC_CONST_SAME_STENCIL(gInvUserToClipReplace,
33 kReplace_StencilOp,
34 kZero_StencilOp,
35 kEqual_StencilFunc,
36 0xffff, // unset clip bit
37 0x0000, // set clip bit
38 0xffff);
39
40 ///////
41 // Intersect
42 GR_STATIC_CONST_SAME_STENCIL(gUserToClipIsect,
43 kReplace_StencilOp,
44 kZero_StencilOp,
45 kLess_StencilFunc,
46 0xffff,
47 0x0000, // set clip bit
48 0xffff);
49
50 GR_STATIC_CONST_SAME_STENCIL(gInvUserToClipIsect,
51 kReplace_StencilOp,
52 kZero_StencilOp,
53 kEqual_StencilFunc,
54 0xffff,
55 0x0000, // set clip bit
56 0xffff);
57
58 ///////
59 // Difference
60 GR_STATIC_CONST_SAME_STENCIL(gUserToClipDiff,
61 kReplace_StencilOp,
62 kZero_StencilOp,
63 kEqual_StencilFunc,
64 0xffff,
65 0x0000, // set clip bit
66 0xffff);
67
68 GR_STATIC_CONST_SAME_STENCIL(gInvUserToClipDiff,
69 kReplace_StencilOp,
70 kZero_StencilOp,
71 kLess_StencilFunc,
72 0xffff,
73 0x0000, // set clip bit
74 0xffff);
75
76 ///////
77 // Union
78
79 // first pass makes all the passing cases >= just clip bit set.
80 GR_STATIC_CONST_SAME_STENCIL(gUserToClipUnionPass0,
81 kReplace_StencilOp,
82 kKeep_StencilOp,
83 kLEqual_StencilFunc,
84 0xffff,
85 0x0001, // set clip bit
86 0xffff);
87
88 // second pass allows anything greater than just clip bit set to pass
89 GR_STATIC_CONST_SAME_STENCIL(gUserToClipUnionPass1,
90 kReplace_StencilOp,
91 kZero_StencilOp,
92 kLEqual_StencilFunc,
93 0xffff,
94 0x0000, // set clip bit
95 0xffff);
96
97 // first pass finds zeros in the user bits and if found sets
98 // the clip bit to 1
99 GR_STATIC_CONST_SAME_STENCIL(gInvUserToClipUnionPass0,
100 kReplace_StencilOp,
101 kKeep_StencilOp,
102 kEqual_StencilFunc,
103 0xffff,
104 0x0000, // set clip bit
105 0x0000 // set clip bit
106 );
107
108 // second pass zeros the user bits
109 GR_STATIC_CONST_SAME_STENCIL(gInvUserToClipUnionPass1,
110 kZero_StencilOp,
111 kZero_StencilOp,
112 kLess_StencilFunc,
113 0xffff,
114 0x0000,
115 0xffff // unset clip bit
116 );
117
118 ///////
119 // Xor
120 GR_STATIC_CONST_SAME_STENCIL(gUserToClipXorPass0,
121 kInvert_StencilOp,
122 kKeep_StencilOp,
123 kEqual_StencilFunc,
124 0xffff, // unset clip bit
125 0x0000,
126 0xffff);
127
128 GR_STATIC_CONST_SAME_STENCIL(gUserToClipXorPass1,
129 kReplace_StencilOp,
130 kZero_StencilOp,
131 kGreater_StencilFunc,
132 0xffff,
133 0x0000, // set clip bit
134 0xffff);
135
136 GR_STATIC_CONST_SAME_STENCIL(gInvUserToClipXorPass0,
137 kInvert_StencilOp,
138 kKeep_StencilOp,
139 kEqual_StencilFunc,
140 0xffff, // unset clip bit
141 0x0000,
142 0xffff);
143
144 GR_STATIC_CONST_SAME_STENCIL(gInvUserToClipXorPass1,
145 kReplace_StencilOp,
146 kZero_StencilOp,
147 kLess_StencilFunc,
148 0xffff,
149 0x0000, // set clip bit
150 0xffff);
151
152 ///////
153 // Reverse Diff
154 GR_STATIC_CONST_SAME_STENCIL(gUserToClipRDiffPass0,
155 kInvert_StencilOp,
156 kZero_StencilOp,
157 kLess_StencilFunc,
158 0xffff, // unset clip bit
159 0x0000, // set clip bit
160 0xffff);
161
162 GR_STATIC_CONST_SAME_STENCIL(gUserToClipRDiffPass1,
163 kReplace_StencilOp,
164 kZero_StencilOp,
165 kEqual_StencilFunc,
166 0x0000, // set clip bit
167 0x0000, // set clip bit
168 0xffff);
169
170 // We are looking for stencil values that are all zero. The first pass sets the
171 // clip bit if the stencil is all zeros. The second pass clears the user bits.
172 GR_STATIC_CONST_SAME_STENCIL(gInvUserToClipRDiffPass0,
173 kInvert_StencilOp,
174 kZero_StencilOp,
175 kEqual_StencilFunc,
176 0xffff,
177 0x0000,
178 0x0000 // set clip bit
179 );
180
181 GR_STATIC_CONST_SAME_STENCIL(gInvUserToClipRDiffPass1,
182 kZero_StencilOp,
183 kZero_StencilOp,
184 kAlways_StencilFunc,
185 0xffff,
186 0x0000,
187 0xffff // unset clip bit
188 );
189
190 ///////
191 // Direct to Stencil
192
193 // We can render a clip element directly without first writing to the client
194 // portion of the clip when the fill is not inverse and the set operation will
195 // only modify the in/out status of samples covered by the clip element.
196
197 // this one only works if used right after stencil clip was cleared.
198 // Our clip mask creation code doesn't allow midstream replace ops.
199 GR_STATIC_CONST_SAME_STENCIL(gReplaceClip,
200 kReplace_StencilOp,
201 kReplace_StencilOp,
202 kAlways_StencilFunc,
203 0xffff,
204 0x0000, // set clip bit
205 0x0000 // set clipBit
206 );
207
208 GR_STATIC_CONST_SAME_STENCIL(gUnionClip,
209 kReplace_StencilOp,
210 kReplace_StencilOp,
211 kAlways_StencilFunc,
212 0xffff,
213 0x0000, // set clip bit
214 0x0000 // set clip bit
215 );
216
217 GR_STATIC_CONST_SAME_STENCIL(gXorClip,
218 kInvert_StencilOp,
219 kInvert_StencilOp,
220 kAlways_StencilFunc,
221 0xffff,
222 0x0000,
223 0x0000 // set clip bit
224 );
225
226 GR_STATIC_CONST_SAME_STENCIL(gDiffClip,
227 kZero_StencilOp,
228 kZero_StencilOp,
229 kAlways_StencilFunc,
230 0xffff,
231 0x0000,
232 0x0000 // set clip bit
233 );
234
GetClipPasses(SkRegion::Op op,bool canBeDirect,unsigned int stencilClipMask,bool invertedFill,int * numPasses,GrStencilSettings settings[kMaxStencilClipPasses])235 bool GrStencilSettings::GetClipPasses(
236 SkRegion::Op op,
237 bool canBeDirect,
238 unsigned int stencilClipMask,
239 bool invertedFill,
240 int* numPasses,
241 GrStencilSettings settings[kMaxStencilClipPasses]) {
242 if (canBeDirect && !invertedFill) {
243 *numPasses = 0;
244 switch (op) {
245 case SkRegion::kReplace_Op:
246 *numPasses = 1;
247 settings[0] = gReplaceClip;
248 break;
249 case SkRegion::kUnion_Op:
250 *numPasses = 1;
251 settings[0] = gUnionClip;
252 break;
253 case SkRegion::kXOR_Op:
254 *numPasses = 1;
255 settings[0] = gXorClip;
256 break;
257 case SkRegion::kDifference_Op:
258 *numPasses = 1;
259 settings[0] = gDiffClip;
260 break;
261 default: // suppress warning
262 break;
263 }
264 if (1 == *numPasses) {
265 settings[0].fFuncRefs[kFront_Face] |= stencilClipMask;
266 settings[0].fWriteMasks[kFront_Face] |= stencilClipMask;
267 settings[0].fFuncRefs[kBack_Face] =
268 settings[0].fFuncRefs[kFront_Face];
269 settings[0].fWriteMasks[kBack_Face] =
270 settings[0].fWriteMasks[kFront_Face];
271 return true;
272 }
273 }
274 switch (op) {
275 // if we make the path renderer go to stencil we always give it a
276 // non-inverted fill and we use the stencil rules on the client->clipbit
277 // pass to select either the zeros or nonzeros.
278 case SkRegion::kReplace_Op:
279 *numPasses= 1;
280 settings[0] = invertedFill ? gInvUserToClipReplace :
281 gUserToClipReplace;
282 settings[0].fFuncMasks[kFront_Face] &= ~stencilClipMask;
283 settings[0].fFuncRefs[kFront_Face] |= stencilClipMask;
284 settings[0].fFuncMasks[kBack_Face] =
285 settings[0].fFuncMasks[kFront_Face];
286 settings[0].fFuncRefs[kBack_Face] =
287 settings[0].fFuncRefs[kFront_Face];
288 break;
289 case SkRegion::kIntersect_Op:
290 *numPasses = 1;
291 settings[0] = invertedFill ? gInvUserToClipIsect : gUserToClipIsect;
292 settings[0].fFuncRefs[kFront_Face] = stencilClipMask;
293 settings[0].fFuncRefs[kBack_Face] =
294 settings[0].fFuncRefs[kFront_Face];
295 break;
296 case SkRegion::kUnion_Op:
297 *numPasses = 2;
298 if (invertedFill) {
299 settings[0] = gInvUserToClipUnionPass0;
300 settings[0].fFuncMasks[kFront_Face] &= ~stencilClipMask;
301 settings[0].fFuncMasks[kBack_Face] =
302 settings[0].fFuncMasks[kFront_Face];
303 settings[0].fFuncRefs[kFront_Face] |= stencilClipMask;
304 settings[0].fFuncRefs[kBack_Face] =
305 settings[0].fFuncRefs[kFront_Face];
306 settings[0].fWriteMasks[kFront_Face] |= stencilClipMask;
307 settings[0].fWriteMasks[kBack_Face] =
308 settings[0].fWriteMasks[kFront_Face];
309
310 settings[1] = gInvUserToClipUnionPass1;
311 settings[1].fWriteMasks[kFront_Face] &= ~stencilClipMask;
312 settings[1].fWriteMasks[kBack_Face] &=
313 settings[1].fWriteMasks[kFront_Face];
314
315 } else {
316 settings[0] = gUserToClipUnionPass0;
317 settings[0].fFuncMasks[kFront_Face] &= ~stencilClipMask;
318 settings[0].fFuncRefs[kFront_Face] |= stencilClipMask;
319 settings[0].fFuncMasks[kBack_Face] =
320 settings[0].fFuncMasks[kFront_Face];
321 settings[0].fFuncRefs[kBack_Face] =
322 settings[0].fFuncRefs[kFront_Face];
323
324 settings[1] = gUserToClipUnionPass1;
325 settings[1].fFuncRefs[kFront_Face] |= stencilClipMask;
326 settings[1].fFuncRefs[kBack_Face] =
327 settings[1].fFuncRefs[kFront_Face];
328 }
329 break;
330 case SkRegion::kXOR_Op:
331 *numPasses = 2;
332 if (invertedFill) {
333 settings[0] = gInvUserToClipXorPass0;
334 settings[0].fFuncMasks[kFront_Face] &= ~stencilClipMask;
335 settings[0].fFuncMasks[kBack_Face] =
336 settings[0].fFuncMasks[kFront_Face];
337
338 settings[1] = gInvUserToClipXorPass1;
339 settings[1].fFuncRefs[kFront_Face] |= stencilClipMask;
340 settings[1].fFuncRefs[kBack_Face] =
341 settings[1].fFuncRefs[kFront_Face];
342 } else {
343 settings[0] = gUserToClipXorPass0;
344 settings[0].fFuncMasks[kFront_Face] &= ~stencilClipMask;
345 settings[0].fFuncMasks[kBack_Face] =
346 settings[0].fFuncMasks[kFront_Face];
347
348 settings[1] = gUserToClipXorPass1;
349 settings[1].fFuncRefs[kFront_Face] |= stencilClipMask;
350 settings[1].fFuncRefs[kBack_Face] =
351 settings[1].fFuncRefs[kFront_Face];
352 }
353 break;
354 case SkRegion::kDifference_Op:
355 *numPasses = 1;
356 settings[0] = invertedFill ? gInvUserToClipDiff : gUserToClipDiff;
357 settings[0].fFuncRefs[kFront_Face] |= stencilClipMask;
358 settings[0].fFuncRefs[kBack_Face] =
359 settings[0].fFuncRefs[kFront_Face];
360 break;
361 case SkRegion::kReverseDifference_Op:
362 if (invertedFill) {
363 *numPasses = 2;
364 settings[0] = gInvUserToClipRDiffPass0;
365 settings[0].fWriteMasks[kFront_Face] |= stencilClipMask;
366 settings[0].fWriteMasks[kBack_Face] =
367 settings[0].fWriteMasks[kFront_Face];
368 settings[1] = gInvUserToClipRDiffPass1;
369 settings[1].fWriteMasks[kFront_Face] &= ~stencilClipMask;
370 settings[1].fWriteMasks[kBack_Face] =
371 settings[1].fWriteMasks[kFront_Face];
372 } else {
373 *numPasses = 2;
374 settings[0] = gUserToClipRDiffPass0;
375 settings[0].fFuncMasks[kFront_Face] &= ~stencilClipMask;
376 settings[0].fFuncMasks[kBack_Face] =
377 settings[0].fFuncMasks[kFront_Face];
378 settings[0].fFuncRefs[kFront_Face] |= stencilClipMask;
379 settings[0].fFuncRefs[kBack_Face] =
380 settings[0].fFuncRefs[kFront_Face];
381
382 settings[1] = gUserToClipRDiffPass1;
383 settings[1].fFuncMasks[kFront_Face] |= stencilClipMask;
384 settings[1].fFuncRefs[kFront_Face] |= stencilClipMask;
385 settings[1].fFuncMasks[kBack_Face] =
386 settings[1].fFuncMasks[kFront_Face];
387 settings[1].fFuncRefs[kBack_Face] =
388 settings[1].fFuncRefs[kFront_Face];
389 }
390 break;
391 default:
392 SkFAIL("Unknown set op");
393 }
394 return false;
395 }
396