blob: 8d7534aa4cfd54919aa5a54b253cbf0a21a83c7f [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.com6b2445e2011-12-15 19:47:46 +0000170GR_STATIC_CONST_SAME_STENCIL(gInvUserToClipRDiff,
171 kInvert_StencilOp,
172 kZero_StencilOp,
173 kEqual_StencilFunc,
174 0xffff,
175 0x0000,
176 0x0000 // set clip bit
177);
bsalomon@google.comd302f142011-03-03 13:54:13 +0000178///////
179// Direct to Stencil
180
181// We can render a clip element directly without first writing to the client
182// portion of the clip when the fill is not inverse and the set operation will
183// only modify the in/out status of samples covered by the clip element.
184
185// this one only works if used right after stencil clip was cleared.
186// Our GrClip doesn't allow midstream replace ops.
bsalomon@google.com6b2445e2011-12-15 19:47:46 +0000187GR_STATIC_CONST_SAME_STENCIL(gReplaceClip,
188 kReplace_StencilOp,
189 kReplace_StencilOp,
190 kAlways_StencilFunc,
191 0xffff,
192 0x0000, // set clip bit
193 0x0000 // set clipBit
194);
bsalomon@google.comd302f142011-03-03 13:54:13 +0000195
bsalomon@google.com6b2445e2011-12-15 19:47:46 +0000196GR_STATIC_CONST_SAME_STENCIL(gUnionClip,
197 kReplace_StencilOp,
198 kReplace_StencilOp,
199 kAlways_StencilFunc,
200 0xffff,
201 0x0000, // set clip bit
202 0x0000 // set clip bit
203);
bsalomon@google.comd302f142011-03-03 13:54:13 +0000204
bsalomon@google.com6b2445e2011-12-15 19:47:46 +0000205GR_STATIC_CONST_SAME_STENCIL(gXorClip,
206 kInvert_StencilOp,
207 kInvert_StencilOp,
208 kAlways_StencilFunc,
209 0xffff,
210 0x0000,
211 0x0000 // set clip bit
212);
bsalomon@google.comd302f142011-03-03 13:54:13 +0000213
bsalomon@google.com6b2445e2011-12-15 19:47:46 +0000214GR_STATIC_CONST_SAME_STENCIL(gDiffClip,
215 kZero_StencilOp,
216 kZero_StencilOp,
217 kAlways_StencilFunc,
218 0xffff,
219 0x0000,
220 0x0000 // set clip bit
221);
bsalomon@google.comd302f142011-03-03 13:54:13 +0000222
bsalomon@google.coma3201942012-06-21 19:58:20 +0000223bool GrStencilSettings::GetClipPasses(
224 SkRegion::Op op,
225 bool canBeDirect,
226 unsigned int stencilClipMask,
227 bool invertedFill,
228 int* numPasses,
229 GrStencilSettings settings[kMaxStencilClipPasses]) {
bsalomon@google.com7f5875d2011-03-24 16:55:45 +0000230 if (canBeDirect && !invertedFill) {
bsalomon@google.com5aaa69e2011-03-04 20:29:08 +0000231 *numPasses = 0;
232 switch (op) {
robertphillips@google.com0f191f32012-04-25 15:23:36 +0000233 case SkRegion::kReplace_Op:
bsalomon@google.com5aaa69e2011-03-04 20:29:08 +0000234 *numPasses = 1;
235 settings[0] = gReplaceClip;
236 break;
robertphillips@google.com0f191f32012-04-25 15:23:36 +0000237 case SkRegion::kUnion_Op:
bsalomon@google.com5aaa69e2011-03-04 20:29:08 +0000238 *numPasses = 1;
239 settings[0] = gUnionClip;
240 break;
robertphillips@google.com0f191f32012-04-25 15:23:36 +0000241 case SkRegion::kXOR_Op:
bsalomon@google.com5aaa69e2011-03-04 20:29:08 +0000242 *numPasses = 1;
243 settings[0] = gXorClip;
244 break;
robertphillips@google.com0f191f32012-04-25 15:23:36 +0000245 case SkRegion::kDifference_Op:
bsalomon@google.com5aaa69e2011-03-04 20:29:08 +0000246 *numPasses = 1;
247 settings[0] = gDiffClip;
248 break;
249 default: // suppress warning
250 break;
251 }
252 if (1 == *numPasses) {
bsalomon@google.coma3201942012-06-21 19:58:20 +0000253 settings[0].fFuncRefs[kFront_Face] |= stencilClipMask;
254 settings[0].fWriteMasks[kFront_Face] |= stencilClipMask;
255 settings[0].fFuncRefs[kBack_Face] =
256 settings[0].fFuncRefs[kFront_Face];
257 settings[0].fWriteMasks[kBack_Face] =
258 settings[0].fWriteMasks[kFront_Face];
bsalomon@google.com5aaa69e2011-03-04 20:29:08 +0000259 return true;
bsalomon@google.comd302f142011-03-03 13:54:13 +0000260 }
261 }
262 switch (op) {
bsalomon@google.com5aaa69e2011-03-04 20:29:08 +0000263 // if we make the path renderer go to stencil we always give it a
264 // non-inverted fill and we use the stencil rules on the client->clipbit
265 // pass to select either the zeros or nonzeros.
robertphillips@google.com0f191f32012-04-25 15:23:36 +0000266 case SkRegion::kReplace_Op:
bsalomon@google.comd302f142011-03-03 13:54:13 +0000267 *numPasses= 1;
bsalomon@google.coma3201942012-06-21 19:58:20 +0000268 settings[0] = invertedFill ? gInvUserToClipReplace :
269 gUserToClipReplace;
270 settings[0].fFuncMasks[kFront_Face] &= ~stencilClipMask;
271 settings[0].fFuncRefs[kFront_Face] |= stencilClipMask;
272 settings[0].fFuncMasks[kBack_Face] =
273 settings[0].fFuncMasks[kFront_Face];
274 settings[0].fFuncRefs[kBack_Face] =
275 settings[0].fFuncRefs[kFront_Face];
bsalomon@google.com5aaa69e2011-03-04 20:29:08 +0000276 break;
robertphillips@google.com0f191f32012-04-25 15:23:36 +0000277 case SkRegion::kIntersect_Op:
bsalomon@google.comd302f142011-03-03 13:54:13 +0000278 *numPasses = 1;
bsalomon@google.com5aaa69e2011-03-04 20:29:08 +0000279 settings[0] = invertedFill ? gInvUserToClipIsect : gUserToClipIsect;
bsalomon@google.coma3201942012-06-21 19:58:20 +0000280 settings[0].fFuncRefs[kFront_Face] = stencilClipMask;
281 settings[0].fFuncRefs[kBack_Face] =
282 settings[0].fFuncRefs[kFront_Face];
bsalomon@google.comd302f142011-03-03 13:54:13 +0000283 break;
robertphillips@google.com0f191f32012-04-25 15:23:36 +0000284 case SkRegion::kUnion_Op:
bsalomon@google.comd302f142011-03-03 13:54:13 +0000285 *numPasses = 2;
bsalomon@google.com5aaa69e2011-03-04 20:29:08 +0000286 if (invertedFill) {
bsalomon@google.comd302f142011-03-03 13:54:13 +0000287 settings[0] = gInvUserToClipUnionPass0;
bsalomon@google.coma3201942012-06-21 19:58:20 +0000288 settings[0].fFuncMasks[kFront_Face] &= ~stencilClipMask;
289 settings[0].fFuncMasks[kBack_Face] =
290 settings[0].fFuncMasks[kFront_Face];
291 settings[0].fFuncRefs[kFront_Face] |= stencilClipMask;
292 settings[0].fFuncRefs[kBack_Face] =
293 settings[0].fFuncRefs[kFront_Face];
294 settings[0].fWriteMasks[kFront_Face] |= stencilClipMask;
295 settings[0].fWriteMasks[kBack_Face] =
296 settings[0].fWriteMasks[kFront_Face];
bsalomon@google.comd302f142011-03-03 13:54:13 +0000297
298 settings[1] = gInvUserToClipUnionPass1;
bsalomon@google.coma3201942012-06-21 19:58:20 +0000299 settings[1].fWriteMasks[kFront_Face] &= ~stencilClipMask;
300 settings[1].fWriteMasks[kBack_Face] &=
301 settings[1].fWriteMasks[kFront_Face];
bsalomon@google.comd302f142011-03-03 13:54:13 +0000302
303 } else {
304 settings[0] = gUserToClipUnionPass0;
bsalomon@google.coma3201942012-06-21 19:58:20 +0000305 settings[0].fFuncMasks[kFront_Face] &= ~stencilClipMask;
306 settings[0].fFuncRefs[kFront_Face] |= stencilClipMask;
307 settings[0].fFuncMasks[kBack_Face] =
308 settings[0].fFuncMasks[kFront_Face];
309 settings[0].fFuncRefs[kBack_Face] =
310 settings[0].fFuncRefs[kFront_Face];
bsalomon@google.comd302f142011-03-03 13:54:13 +0000311
312 settings[1] = gUserToClipUnionPass1;
bsalomon@google.coma3201942012-06-21 19:58:20 +0000313 settings[1].fFuncRefs[kFront_Face] |= stencilClipMask;
314 settings[1].fFuncRefs[kBack_Face] =
315 settings[1].fFuncRefs[kFront_Face];
bsalomon@google.comd302f142011-03-03 13:54:13 +0000316 }
317 break;
robertphillips@google.com0f191f32012-04-25 15:23:36 +0000318 case SkRegion::kXOR_Op:
bsalomon@google.comd302f142011-03-03 13:54:13 +0000319 *numPasses = 2;
bsalomon@google.com5aaa69e2011-03-04 20:29:08 +0000320 if (invertedFill) {
bsalomon@google.comd302f142011-03-03 13:54:13 +0000321 settings[0] = gInvUserToClipXorPass0;
bsalomon@google.coma3201942012-06-21 19:58:20 +0000322 settings[0].fFuncMasks[kFront_Face] &= ~stencilClipMask;
323 settings[0].fFuncMasks[kBack_Face] =
324 settings[0].fFuncMasks[kFront_Face];
bsalomon@google.comd302f142011-03-03 13:54:13 +0000325
326 settings[1] = gInvUserToClipXorPass1;
bsalomon@google.coma3201942012-06-21 19:58:20 +0000327 settings[1].fFuncRefs[kFront_Face] |= stencilClipMask;
328 settings[1].fFuncRefs[kBack_Face] =
329 settings[1].fFuncRefs[kFront_Face];
bsalomon@google.comd302f142011-03-03 13:54:13 +0000330 } else {
331 settings[0] = gUserToClipXorPass0;
bsalomon@google.coma3201942012-06-21 19:58:20 +0000332 settings[0].fFuncMasks[kFront_Face] &= ~stencilClipMask;
333 settings[0].fFuncMasks[kBack_Face] =
334 settings[0].fFuncMasks[kFront_Face];
bsalomon@google.comd302f142011-03-03 13:54:13 +0000335
336 settings[1] = gUserToClipXorPass1;
bsalomon@google.coma3201942012-06-21 19:58:20 +0000337 settings[1].fFuncRefs[kFront_Face] |= stencilClipMask;
338 settings[1].fFuncRefs[kBack_Face] =
339 settings[1].fFuncRefs[kFront_Face];
bsalomon@google.comd302f142011-03-03 13:54:13 +0000340 }
341 break;
robertphillips@google.com0f191f32012-04-25 15:23:36 +0000342 case SkRegion::kDifference_Op:
bsalomon@google.comd302f142011-03-03 13:54:13 +0000343 *numPasses = 1;
bsalomon@google.com5aaa69e2011-03-04 20:29:08 +0000344 settings[0] = invertedFill ? gInvUserToClipDiff : gUserToClipDiff;
bsalomon@google.coma3201942012-06-21 19:58:20 +0000345 settings[0].fFuncRefs[kFront_Face] |= stencilClipMask;
346 settings[0].fFuncRefs[kBack_Face] =
347 settings[0].fFuncRefs[kFront_Face];
bsalomon@google.comd302f142011-03-03 13:54:13 +0000348 break;
robertphillips@google.com0f191f32012-04-25 15:23:36 +0000349 case SkRegion::kReverseDifference_Op:
bsalomon@google.com5aaa69e2011-03-04 20:29:08 +0000350 if (invertedFill) {
bsalomon@google.comd302f142011-03-03 13:54:13 +0000351 *numPasses = 1;
352 settings[0] = gInvUserToClipRDiff;
bsalomon@google.coma3201942012-06-21 19:58:20 +0000353 settings[0].fWriteMasks[kFront_Face] |= stencilClipMask;
354 settings[0].fWriteMasks[kBack_Face] =
355 settings[0].fWriteMasks[kFront_Face];
bsalomon@google.comd302f142011-03-03 13:54:13 +0000356 } else {
357 *numPasses = 2;
358 settings[0] = gUserToClipRDiffPass0;
bsalomon@google.coma3201942012-06-21 19:58:20 +0000359 settings[0].fFuncMasks[kFront_Face] &= ~stencilClipMask;
360 settings[0].fFuncMasks[kBack_Face] =
361 settings[0].fFuncMasks[kFront_Face];
362 settings[0].fFuncRefs[kFront_Face] |= stencilClipMask;
363 settings[0].fFuncRefs[kBack_Face] =
364 settings[0].fFuncRefs[kFront_Face];
bsalomon@google.comd302f142011-03-03 13:54:13 +0000365
366 settings[1] = gUserToClipRDiffPass1;
bsalomon@google.coma3201942012-06-21 19:58:20 +0000367 settings[1].fFuncMasks[kFront_Face] |= stencilClipMask;
368 settings[1].fFuncRefs[kFront_Face] |= stencilClipMask;
369 settings[1].fFuncMasks[kBack_Face] =
370 settings[1].fFuncMasks[kFront_Face];
371 settings[1].fFuncRefs[kBack_Face] =
372 settings[1].fFuncRefs[kFront_Face];
bsalomon@google.comd302f142011-03-03 13:54:13 +0000373 }
374 break;
375 default:
376 GrCrash("Unknown set op");
377 }
bsalomon@google.comd302f142011-03-03 13:54:13 +0000378 return false;
ctguil@chromium.orgd5683e22011-04-18 18:12:50 +0000379}