|
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 |
|
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 GrCrash("Unknown set op"); |
|
393 } |
|
394 return false; |
|
395 } |