blob: f37aa317ec37b20f9ff0f731278ab27dedc8bf66 [file] [log] [blame]
epoger@google.comec3ed6a2011-07-28 14:26:00 +00001
bsalomon@google.comd302f142011-03-03 13:54:13 +00002/*
epoger@google.comec3ed6a2011-07-28 14:26:00 +00003 * 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.
bsalomon@google.comd302f142011-03-03 13:54:13 +00007 */
8
epoger@google.comec3ed6a2011-07-28 14:26:00 +00009
bsalomon@google.comd302f142011-03-03 13:54:13 +000010#include "GrStencil.h"
11
bsalomon@google.comd302f142011-03-03 13:54:13 +000012////////////////////////////////////////////////////////////////////////////////
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
bsalomon@google.com6b2445e2011-12-15 19:47:46 +000024GR_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
32GR_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);
bsalomon@google.comd302f142011-03-03 13:54:13 +000039
40///////
41// Intersect
bsalomon@google.com6b2445e2011-12-15 19:47:46 +000042GR_STATIC_CONST_SAME_STENCIL(gUserToClipIsect,
43 kReplace_StencilOp,
44 kZero_StencilOp,
45 kLess_StencilFunc,
46 0xffff,
47 0x0000, // set clip bit
48 0xffff);
49
50GR_STATIC_CONST_SAME_STENCIL(gInvUserToClipIsect,
51 kReplace_StencilOp,
52 kZero_StencilOp,
53 kEqual_StencilFunc,
54 0xffff,
55 0x0000, // set clip bit
56 0xffff);
bsalomon@google.comd302f142011-03-03 13:54:13 +000057
58///////
59// Difference
bsalomon@google.com6b2445e2011-12-15 19:47:46 +000060GR_STATIC_CONST_SAME_STENCIL(gUserToClipDiff,
61 kReplace_StencilOp,
62 kZero_StencilOp,
63 kEqual_StencilFunc,
64 0xffff,
65 0x0000, // set clip bit
66 0xffff);
67
68GR_STATIC_CONST_SAME_STENCIL(gInvUserToClipDiff,
69 kReplace_StencilOp,
70 kZero_StencilOp,
71 kLess_StencilFunc,
72 0xffff,
73 0x0000, // set clip bit
74 0xffff);
bsalomon@google.comd302f142011-03-03 13:54:13 +000075
76///////
77// Union
78
79// first pass makes all the passing cases >= just clip bit set.
bsalomon@google.com6b2445e2011-12-15 19:47:46 +000080GR_STATIC_CONST_SAME_STENCIL(gUserToClipUnionPass0,
81 kReplace_StencilOp,
82 kKeep_StencilOp,
83 kLEqual_StencilFunc,
84 0xffff,
85 0x0001, // set clip bit
86 0xffff);
bsalomon@google.comd302f142011-03-03 13:54:13 +000087
88// second pass allows anything greater than just clip bit set to pass
bsalomon@google.com6b2445e2011-12-15 19:47:46 +000089GR_STATIC_CONST_SAME_STENCIL(gUserToClipUnionPass1,
90 kReplace_StencilOp,
91 kZero_StencilOp,
92 kLEqual_StencilFunc,
93 0xffff,
94 0x0000, // set clip bit
95 0xffff);
bsalomon@google.comd302f142011-03-03 13:54:13 +000096
bsalomon@google.com6b20c2d2011-12-09 21:23:46 +000097// first pass finds zeros in the user bits and if found sets
98// the clip bit to 1
bsalomon@google.com6b2445e2011-12-15 19:47:46 +000099GR_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);
bsalomon@google.com6b20c2d2011-12-09 21:23:46 +0000107
108// second pass zeros the user bits
bsalomon@google.com6b2445e2011-12-15 19:47:46 +0000109GR_STATIC_CONST_SAME_STENCIL(gInvUserToClipUnionPass1,
110 kZero_StencilOp,
111 kZero_StencilOp,
112 kLess_StencilFunc,
113 0xffff,
114 0x0000,
115 0xffff // unset clip bit
116);
bsalomon@google.comd302f142011-03-03 13:54:13 +0000117
118///////
119// Xor
bsalomon@google.com6b2445e2011-12-15 19:47:46 +0000120GR_STATIC_CONST_SAME_STENCIL(gUserToClipXorPass0,
121 kInvert_StencilOp,
122 kKeep_StencilOp,
123 kEqual_StencilFunc,
124 0xffff, // unset clip bit
125 0x0000,
126 0xffff);
bsalomon@google.comd302f142011-03-03 13:54:13 +0000127
bsalomon@google.com6b2445e2011-12-15 19:47:46 +0000128GR_STATIC_CONST_SAME_STENCIL(gUserToClipXorPass1,
129 kReplace_StencilOp,
130 kZero_StencilOp,
131 kGreater_StencilFunc,
132 0xffff,
133 0x0000, // set clip bit
134 0xffff);
bsalomon@google.comd302f142011-03-03 13:54:13 +0000135
bsalomon@google.com6b2445e2011-12-15 19:47:46 +0000136GR_STATIC_CONST_SAME_STENCIL(gInvUserToClipXorPass0,
137 kInvert_StencilOp,
138 kKeep_StencilOp,
139 kEqual_StencilFunc,
140 0xffff, // unset clip bit
141 0x0000,
142 0xffff);
bsalomon@google.comd302f142011-03-03 13:54:13 +0000143
bsalomon@google.com6b2445e2011-12-15 19:47:46 +0000144GR_STATIC_CONST_SAME_STENCIL(gInvUserToClipXorPass1,
145 kReplace_StencilOp,
146 kZero_StencilOp,
147 kLess_StencilFunc,
148 0xffff,
149 0x0000, // set clip bit
150 0xffff);
bsalomon@google.comd302f142011-03-03 13:54:13 +0000151
152///////
153// Reverse Diff
bsalomon@google.com6b2445e2011-12-15 19:47:46 +0000154GR_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);
bsalomon@google.comd302f142011-03-03 13:54:13 +0000161
bsalomon@google.com6b2445e2011-12-15 19:47:46 +0000162GR_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);
bsalomon@google.comd302f142011-03-03 13:54:13 +0000169
bsalomon@google.com70fc1522012-06-25 18:03:46 +0000170// 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.
172GR_STATIC_CONST_SAME_STENCIL(gInvUserToClipRDiffPass0,
bsalomon@google.com6b2445e2011-12-15 19:47:46 +0000173 kInvert_StencilOp,
174 kZero_StencilOp,
175 kEqual_StencilFunc,
176 0xffff,
177 0x0000,
178 0x0000 // set clip bit
179);
bsalomon@google.com70fc1522012-06-25 18:03:46 +0000180
181GR_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
bsalomon@google.comd302f142011-03-03 13:54:13 +0000190///////
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.
robertphillips@google.coma2d71482012-08-01 20:08:47 +0000198// Our clip mask creation code doesn't allow midstream replace ops.
bsalomon@google.com6b2445e2011-12-15 19:47:46 +0000199GR_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);
bsalomon@google.comd302f142011-03-03 13:54:13 +0000207
bsalomon@google.com6b2445e2011-12-15 19:47:46 +0000208GR_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);
bsalomon@google.comd302f142011-03-03 13:54:13 +0000216
bsalomon@google.com6b2445e2011-12-15 19:47:46 +0000217GR_STATIC_CONST_SAME_STENCIL(gXorClip,
218 kInvert_StencilOp,
219 kInvert_StencilOp,
220 kAlways_StencilFunc,
221 0xffff,
222 0x0000,
223 0x0000 // set clip bit
224);
bsalomon@google.comd302f142011-03-03 13:54:13 +0000225
bsalomon@google.com6b2445e2011-12-15 19:47:46 +0000226GR_STATIC_CONST_SAME_STENCIL(gDiffClip,
227 kZero_StencilOp,
228 kZero_StencilOp,
229 kAlways_StencilFunc,
230 0xffff,
231 0x0000,
232 0x0000 // set clip bit
233);
bsalomon@google.comd302f142011-03-03 13:54:13 +0000234
bsalomon@google.coma3201942012-06-21 19:58:20 +0000235bool GrStencilSettings::GetClipPasses(
rmistry@google.comfbfcd562012-08-23 18:09:54 +0000236 SkRegion::Op op,
bsalomon@google.coma3201942012-06-21 19:58:20 +0000237 bool canBeDirect,
238 unsigned int stencilClipMask,
239 bool invertedFill,
240 int* numPasses,
241 GrStencilSettings settings[kMaxStencilClipPasses]) {
bsalomon@google.com7f5875d2011-03-24 16:55:45 +0000242 if (canBeDirect && !invertedFill) {
bsalomon@google.com5aaa69e2011-03-04 20:29:08 +0000243 *numPasses = 0;
244 switch (op) {
robertphillips@google.com0f191f32012-04-25 15:23:36 +0000245 case SkRegion::kReplace_Op:
bsalomon@google.com5aaa69e2011-03-04 20:29:08 +0000246 *numPasses = 1;
247 settings[0] = gReplaceClip;
248 break;
robertphillips@google.com0f191f32012-04-25 15:23:36 +0000249 case SkRegion::kUnion_Op:
bsalomon@google.com5aaa69e2011-03-04 20:29:08 +0000250 *numPasses = 1;
251 settings[0] = gUnionClip;
252 break;
robertphillips@google.com0f191f32012-04-25 15:23:36 +0000253 case SkRegion::kXOR_Op:
bsalomon@google.com5aaa69e2011-03-04 20:29:08 +0000254 *numPasses = 1;
255 settings[0] = gXorClip;
256 break;
robertphillips@google.com0f191f32012-04-25 15:23:36 +0000257 case SkRegion::kDifference_Op:
bsalomon@google.com5aaa69e2011-03-04 20:29:08 +0000258 *numPasses = 1;
259 settings[0] = gDiffClip;
260 break;
261 default: // suppress warning
262 break;
263 }
264 if (1 == *numPasses) {
bsalomon@google.coma3201942012-06-21 19:58:20 +0000265 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];
bsalomon@google.com5aaa69e2011-03-04 20:29:08 +0000271 return true;
bsalomon@google.comd302f142011-03-03 13:54:13 +0000272 }
273 }
274 switch (op) {
bsalomon@google.com5aaa69e2011-03-04 20:29:08 +0000275 // 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.
robertphillips@google.com0f191f32012-04-25 15:23:36 +0000278 case SkRegion::kReplace_Op:
bsalomon@google.comd302f142011-03-03 13:54:13 +0000279 *numPasses= 1;
bsalomon@google.coma3201942012-06-21 19:58:20 +0000280 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];
bsalomon@google.com5aaa69e2011-03-04 20:29:08 +0000288 break;
robertphillips@google.com0f191f32012-04-25 15:23:36 +0000289 case SkRegion::kIntersect_Op:
bsalomon@google.comd302f142011-03-03 13:54:13 +0000290 *numPasses = 1;
bsalomon@google.com5aaa69e2011-03-04 20:29:08 +0000291 settings[0] = invertedFill ? gInvUserToClipIsect : gUserToClipIsect;
bsalomon@google.coma3201942012-06-21 19:58:20 +0000292 settings[0].fFuncRefs[kFront_Face] = stencilClipMask;
293 settings[0].fFuncRefs[kBack_Face] =
294 settings[0].fFuncRefs[kFront_Face];
bsalomon@google.comd302f142011-03-03 13:54:13 +0000295 break;
robertphillips@google.com0f191f32012-04-25 15:23:36 +0000296 case SkRegion::kUnion_Op:
bsalomon@google.comd302f142011-03-03 13:54:13 +0000297 *numPasses = 2;
bsalomon@google.com5aaa69e2011-03-04 20:29:08 +0000298 if (invertedFill) {
bsalomon@google.comd302f142011-03-03 13:54:13 +0000299 settings[0] = gInvUserToClipUnionPass0;
bsalomon@google.coma3201942012-06-21 19:58:20 +0000300 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];
bsalomon@google.comd302f142011-03-03 13:54:13 +0000309
310 settings[1] = gInvUserToClipUnionPass1;
bsalomon@google.coma3201942012-06-21 19:58:20 +0000311 settings[1].fWriteMasks[kFront_Face] &= ~stencilClipMask;
312 settings[1].fWriteMasks[kBack_Face] &=
313 settings[1].fWriteMasks[kFront_Face];
bsalomon@google.comd302f142011-03-03 13:54:13 +0000314
315 } else {
316 settings[0] = gUserToClipUnionPass0;
bsalomon@google.coma3201942012-06-21 19:58:20 +0000317 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];
bsalomon@google.comd302f142011-03-03 13:54:13 +0000323
324 settings[1] = gUserToClipUnionPass1;
bsalomon@google.coma3201942012-06-21 19:58:20 +0000325 settings[1].fFuncRefs[kFront_Face] |= stencilClipMask;
326 settings[1].fFuncRefs[kBack_Face] =
327 settings[1].fFuncRefs[kFront_Face];
bsalomon@google.comd302f142011-03-03 13:54:13 +0000328 }
329 break;
robertphillips@google.com0f191f32012-04-25 15:23:36 +0000330 case SkRegion::kXOR_Op:
bsalomon@google.comd302f142011-03-03 13:54:13 +0000331 *numPasses = 2;
bsalomon@google.com5aaa69e2011-03-04 20:29:08 +0000332 if (invertedFill) {
bsalomon@google.comd302f142011-03-03 13:54:13 +0000333 settings[0] = gInvUserToClipXorPass0;
bsalomon@google.coma3201942012-06-21 19:58:20 +0000334 settings[0].fFuncMasks[kFront_Face] &= ~stencilClipMask;
335 settings[0].fFuncMasks[kBack_Face] =
336 settings[0].fFuncMasks[kFront_Face];
bsalomon@google.comd302f142011-03-03 13:54:13 +0000337
338 settings[1] = gInvUserToClipXorPass1;
bsalomon@google.coma3201942012-06-21 19:58:20 +0000339 settings[1].fFuncRefs[kFront_Face] |= stencilClipMask;
340 settings[1].fFuncRefs[kBack_Face] =
341 settings[1].fFuncRefs[kFront_Face];
bsalomon@google.comd302f142011-03-03 13:54:13 +0000342 } else {
343 settings[0] = gUserToClipXorPass0;
bsalomon@google.coma3201942012-06-21 19:58:20 +0000344 settings[0].fFuncMasks[kFront_Face] &= ~stencilClipMask;
345 settings[0].fFuncMasks[kBack_Face] =
346 settings[0].fFuncMasks[kFront_Face];
bsalomon@google.comd302f142011-03-03 13:54:13 +0000347
348 settings[1] = gUserToClipXorPass1;
bsalomon@google.coma3201942012-06-21 19:58:20 +0000349 settings[1].fFuncRefs[kFront_Face] |= stencilClipMask;
350 settings[1].fFuncRefs[kBack_Face] =
351 settings[1].fFuncRefs[kFront_Face];
bsalomon@google.comd302f142011-03-03 13:54:13 +0000352 }
353 break;
robertphillips@google.com0f191f32012-04-25 15:23:36 +0000354 case SkRegion::kDifference_Op:
bsalomon@google.comd302f142011-03-03 13:54:13 +0000355 *numPasses = 1;
bsalomon@google.com5aaa69e2011-03-04 20:29:08 +0000356 settings[0] = invertedFill ? gInvUserToClipDiff : gUserToClipDiff;
bsalomon@google.coma3201942012-06-21 19:58:20 +0000357 settings[0].fFuncRefs[kFront_Face] |= stencilClipMask;
358 settings[0].fFuncRefs[kBack_Face] =
359 settings[0].fFuncRefs[kFront_Face];
bsalomon@google.comd302f142011-03-03 13:54:13 +0000360 break;
robertphillips@google.com0f191f32012-04-25 15:23:36 +0000361 case SkRegion::kReverseDifference_Op:
bsalomon@google.com5aaa69e2011-03-04 20:29:08 +0000362 if (invertedFill) {
bsalomon@google.com70fc1522012-06-25 18:03:46 +0000363 *numPasses = 2;
364 settings[0] = gInvUserToClipRDiffPass0;
bsalomon@google.coma3201942012-06-21 19:58:20 +0000365 settings[0].fWriteMasks[kFront_Face] |= stencilClipMask;
366 settings[0].fWriteMasks[kBack_Face] =
367 settings[0].fWriteMasks[kFront_Face];
bsalomon@google.com70fc1522012-06-25 18:03:46 +0000368 settings[1] = gInvUserToClipRDiffPass1;
369 settings[1].fWriteMasks[kFront_Face] &= ~stencilClipMask;
370 settings[1].fWriteMasks[kBack_Face] =
371 settings[1].fWriteMasks[kFront_Face];
bsalomon@google.comd302f142011-03-03 13:54:13 +0000372 } else {
373 *numPasses = 2;
374 settings[0] = gUserToClipRDiffPass0;
bsalomon@google.coma3201942012-06-21 19:58:20 +0000375 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];
bsalomon@google.comd302f142011-03-03 13:54:13 +0000381
382 settings[1] = gUserToClipRDiffPass1;
bsalomon@google.coma3201942012-06-21 19:58:20 +0000383 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];
bsalomon@google.comd302f142011-03-03 13:54:13 +0000389 }
390 break;
391 default:
commit-bot@chromium.org88cb22b2014-04-30 14:17:00 +0000392 SkFAIL("Unknown set op");
bsalomon@google.comd302f142011-03-03 13:54:13 +0000393 }
bsalomon@google.comd302f142011-03-03 13:54:13 +0000394 return false;
ctguil@chromium.orgd5683e22011-04-18 18:12:50 +0000395}