blob: 66249429d293bc0a1261a5cf4a828ffbd810f6df [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.comd302f142011-03-03 13:54:13 +0000223bool GrStencilSettings::GetClipPasses(GrSetOp op,
224 bool canBeDirect,
225 unsigned int stencilClipMask,
bsalomon@google.com5aaa69e2011-03-04 20:29:08 +0000226 bool invertedFill,
bsalomon@google.comd302f142011-03-03 13:54:13 +0000227 int* numPasses,
228 GrStencilSettings settings[kMaxStencilClipPasses]) {
bsalomon@google.com7f5875d2011-03-24 16:55:45 +0000229 if (canBeDirect && !invertedFill) {
bsalomon@google.com5aaa69e2011-03-04 20:29:08 +0000230 *numPasses = 0;
231 switch (op) {
232 case kReplace_SetOp:
233 *numPasses = 1;
234 settings[0] = gReplaceClip;
235 break;
236 case kUnion_SetOp:
237 *numPasses = 1;
238 settings[0] = gUnionClip;
239 break;
240 case kXor_SetOp:
241 *numPasses = 1;
242 settings[0] = gXorClip;
243 break;
244 case kDifference_SetOp:
245 *numPasses = 1;
246 settings[0] = gDiffClip;
247 break;
248 default: // suppress warning
249 break;
250 }
251 if (1 == *numPasses) {
252 settings[0].fFrontFuncRef |= stencilClipMask;
253 settings[0].fFrontWriteMask |= stencilClipMask;
254 settings[0].fBackFuncRef = settings[0].fFrontFuncRef;
255 settings[0].fBackWriteMask = settings[0].fFrontWriteMask;
256 return true;
bsalomon@google.comd302f142011-03-03 13:54:13 +0000257 }
258 }
259 switch (op) {
bsalomon@google.com5aaa69e2011-03-04 20:29:08 +0000260 // if we make the path renderer go to stencil we always give it a
261 // non-inverted fill and we use the stencil rules on the client->clipbit
262 // pass to select either the zeros or nonzeros.
bsalomon@google.comd302f142011-03-03 13:54:13 +0000263 case kReplace_SetOp:
264 *numPasses= 1;
bsalomon@google.com5aaa69e2011-03-04 20:29:08 +0000265 settings[0] = invertedFill ? gInvUserToClipReplace : gUserToClipReplace;
bsalomon@google.comd302f142011-03-03 13:54:13 +0000266 settings[0].fFrontFuncMask &= ~stencilClipMask;
267 settings[0].fFrontFuncRef |= stencilClipMask;
268 settings[0].fBackFuncMask = settings[0].fFrontFuncMask;
269 settings[0].fBackFuncRef = settings[0].fFrontFuncRef;
bsalomon@google.com5aaa69e2011-03-04 20:29:08 +0000270 break;
bsalomon@google.comd302f142011-03-03 13:54:13 +0000271 case kIntersect_SetOp:
272 *numPasses = 1;
bsalomon@google.com5aaa69e2011-03-04 20:29:08 +0000273 settings[0] = invertedFill ? gInvUserToClipIsect : gUserToClipIsect;
bsalomon@google.comd302f142011-03-03 13:54:13 +0000274 settings[0].fFrontFuncRef = stencilClipMask;
275 settings[0].fBackFuncRef = settings[0].fFrontFuncRef;
276 break;
277 case kUnion_SetOp:
278 *numPasses = 2;
bsalomon@google.com5aaa69e2011-03-04 20:29:08 +0000279 if (invertedFill) {
bsalomon@google.comd302f142011-03-03 13:54:13 +0000280 settings[0] = gInvUserToClipUnionPass0;
bsalomon@google.com6b20c2d2011-12-09 21:23:46 +0000281 settings[0].fFrontFuncMask &= ~stencilClipMask;
282 settings[0].fBackFuncMask = settings[0].fFrontFuncMask;
bsalomon@google.comd302f142011-03-03 13:54:13 +0000283 settings[0].fFrontFuncRef |= stencilClipMask;
bsalomon@google.com6b20c2d2011-12-09 21:23:46 +0000284 settings[0].fBackFuncRef = settings[0].fFrontFuncRef;
285 settings[0].fFrontWriteMask |= stencilClipMask;
286 settings[0].fBackWriteMask = settings[0].fFrontWriteMask;
bsalomon@google.comd302f142011-03-03 13:54:13 +0000287
288 settings[1] = gInvUserToClipUnionPass1;
bsalomon@google.com6b20c2d2011-12-09 21:23:46 +0000289 settings[1].fFrontWriteMask &= ~stencilClipMask;
290 settings[1].fBackWriteMask &= settings[1].fFrontWriteMask;
bsalomon@google.comd302f142011-03-03 13:54:13 +0000291
292 } else {
293 settings[0] = gUserToClipUnionPass0;
294 settings[0].fFrontFuncMask &= ~stencilClipMask;
295 settings[0].fFrontFuncRef |= stencilClipMask;
296 settings[0].fBackFuncMask = settings[0].fFrontFuncMask;
297 settings[0].fBackFuncRef = settings[0].fFrontFuncRef;
298
299 settings[1] = gUserToClipUnionPass1;
300 settings[1].fFrontFuncRef |= stencilClipMask;
301 settings[1].fBackFuncRef = settings[1].fFrontFuncRef;
302 }
303 break;
304 case kXor_SetOp:
305 *numPasses = 2;
bsalomon@google.com5aaa69e2011-03-04 20:29:08 +0000306 if (invertedFill) {
bsalomon@google.comd302f142011-03-03 13:54:13 +0000307 settings[0] = gInvUserToClipXorPass0;
308 settings[0].fFrontFuncMask &= ~stencilClipMask;
309 settings[0].fBackFuncMask = settings[0].fFrontFuncMask;
310
311 settings[1] = gInvUserToClipXorPass1;
312 settings[1].fFrontFuncRef |= stencilClipMask;
313 settings[1].fBackFuncRef = settings[1].fFrontFuncRef;
314 } else {
315 settings[0] = gUserToClipXorPass0;
316 settings[0].fFrontFuncMask &= ~stencilClipMask;
317 settings[0].fBackFuncMask = settings[0].fFrontFuncMask;
318
319 settings[1] = gUserToClipXorPass1;
320 settings[1].fFrontFuncRef |= stencilClipMask;
321 settings[1].fBackFuncRef = settings[1].fFrontFuncRef;
322 }
323 break;
324 case kDifference_SetOp:
325 *numPasses = 1;
bsalomon@google.com5aaa69e2011-03-04 20:29:08 +0000326 settings[0] = invertedFill ? gInvUserToClipDiff : gUserToClipDiff;
bsalomon@google.comd302f142011-03-03 13:54:13 +0000327 settings[0].fFrontFuncRef |= stencilClipMask;
328 settings[0].fBackFuncRef = settings[0].fFrontFuncRef;
329 break;
330 case kReverseDifference_SetOp:
bsalomon@google.com5aaa69e2011-03-04 20:29:08 +0000331 if (invertedFill) {
bsalomon@google.comd302f142011-03-03 13:54:13 +0000332 *numPasses = 1;
333 settings[0] = gInvUserToClipRDiff;
334 settings[0].fFrontWriteMask |= stencilClipMask;
335 settings[0].fBackWriteMask = settings[0].fFrontWriteMask;
336 } else {
337 *numPasses = 2;
338 settings[0] = gUserToClipRDiffPass0;
339 settings[0].fFrontFuncMask &= ~stencilClipMask;
340 settings[0].fBackFuncMask = settings[0].fFrontFuncMask;
341 settings[0].fFrontFuncRef |= stencilClipMask;
342 settings[0].fBackFuncRef = settings[0].fFrontFuncRef;
343
344 settings[1] = gUserToClipRDiffPass1;
345 settings[1].fFrontFuncMask |= stencilClipMask;
346 settings[1].fFrontFuncRef |= stencilClipMask;
347 settings[1].fBackFuncMask = settings[1].fFrontFuncMask;
348 settings[1].fBackFuncRef = settings[1].fFrontFuncRef;
349 }
350 break;
351 default:
352 GrCrash("Unknown set op");
353 }
bsalomon@google.comd302f142011-03-03 13:54:13 +0000354 return false;
ctguil@chromium.orgd5683e22011-04-18 18:12:50 +0000355}