blob: 81b3b8d14404b9e900a5892835e851b94ca836ea [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
senorblanco@chromium.org64cc5792011-05-19 19:58:58 +000012const GrStencilSettings GrStencilSettings::gDisabled = {
13 kKeep_StencilOp, kKeep_StencilOp,
14 kKeep_StencilOp, kKeep_StencilOp,
15 kAlways_StencilFunc, kAlways_StencilFunc,
tomhudson@google.com62b09682011-11-09 16:39:17 +000016 0x0000, 0x0000,
17 0x0000, 0x0000,
18 0x0000, 0x0000
senorblanco@chromium.org64cc5792011-05-19 19:58:58 +000019};
bsalomon@google.comd302f142011-03-03 13:54:13 +000020GR_STATIC_ASSERT(0 == kKeep_StencilOp);
21GR_STATIC_ASSERT(0 == kAlways_StencilFunc);
22
23////////////////////////////////////////////////////////////////////////////////
24// Stencil Rules for Merging user stencil space into clip
25
26// We can't include the clip bit in the ref or mask values because the division
27// between user and clip bits in the stencil depends on the number of stencil
28// bits in the runtime. Comments below indicate what the code should do to
29// incorporate the clip bit into these settings.
30
31///////
32// Replace
33
34// set the ref to be the clip bit, but mask it out for the test
35static const GrStencilSettings gUserToClipReplace = {
36 kReplace_StencilOp, kReplace_StencilOp,
37 kZero_StencilOp, kZero_StencilOp,
38 kLess_StencilFunc, kLess_StencilFunc,
tomhudson@google.com62b09682011-11-09 16:39:17 +000039 0xffff, 0xffff, // unset clip bit
40 0x0000, 0x0000, // set clip bit
41 0xffff, 0xffff
bsalomon@google.comd302f142011-03-03 13:54:13 +000042};
43static const GrStencilSettings gInvUserToClipReplace = {
44 kReplace_StencilOp, kReplace_StencilOp,
45 kZero_StencilOp, kZero_StencilOp,
46 kEqual_StencilFunc, kEqual_StencilFunc,
tomhudson@google.com62b09682011-11-09 16:39:17 +000047 0xffff, 0xffff, // unset clip bit
48 0x0000, 0x0000, // set clip bit
49 0xffff, 0xffff
bsalomon@google.comd302f142011-03-03 13:54:13 +000050};
51
52///////
53// Intersect
54static const GrStencilSettings gUserToClipIsect = {
55 kReplace_StencilOp, kReplace_StencilOp,
56 kZero_StencilOp, kZero_StencilOp,
57 kLess_StencilFunc, kLess_StencilFunc,
tomhudson@google.com62b09682011-11-09 16:39:17 +000058 0xffff, 0xffff,
59 0x0000, 0x0000, // set clip bit
60 0xffff, 0xffff
bsalomon@google.comd302f142011-03-03 13:54:13 +000061};
62static const GrStencilSettings gInvUserToClipIsect = {
63 kReplace_StencilOp, kReplace_StencilOp,
64 kZero_StencilOp, kZero_StencilOp,
65 kEqual_StencilFunc, kEqual_StencilFunc,
tomhudson@google.com62b09682011-11-09 16:39:17 +000066 0xffff, 0xffff,
67 0x0000, 0x0000, // set clip bit
68 0xffff, 0xffff
bsalomon@google.comd302f142011-03-03 13:54:13 +000069};
70
71///////
72// Difference
73static const GrStencilSettings gUserToClipDiff = {
74 kReplace_StencilOp, kReplace_StencilOp,
75 kZero_StencilOp, kZero_StencilOp,
76 kEqual_StencilFunc, kEqual_StencilFunc,
tomhudson@google.com62b09682011-11-09 16:39:17 +000077 0xffff, 0xffff,
78 0x0000, 0x0000, // set clip bit
79 0xffff, 0xffff
bsalomon@google.comd302f142011-03-03 13:54:13 +000080};
81static const GrStencilSettings gInvUserToClipDiff = {
82 kReplace_StencilOp, kReplace_StencilOp,
83 kZero_StencilOp, kZero_StencilOp,
84 kLess_StencilFunc, kLess_StencilFunc,
tomhudson@google.com62b09682011-11-09 16:39:17 +000085 0xffff, 0xffff,
86 0x0000, 0x0000, // set clip bit
87 0xffff, 0xffff
bsalomon@google.comd302f142011-03-03 13:54:13 +000088};
89
90///////
91// Union
92
93// first pass makes all the passing cases >= just clip bit set.
94static const GrStencilSettings gUserToClipUnionPass0 = {
95 kReplace_StencilOp, kReplace_StencilOp,
96 kKeep_StencilOp, kKeep_StencilOp,
97 kLEqual_StencilFunc, kLEqual_StencilFunc,
tomhudson@google.com62b09682011-11-09 16:39:17 +000098 0xffff, 0xffff, // unset clip bit
99 0x0001, 0x0001, // set clip bit
100 0xffff, 0xffff
bsalomon@google.comd302f142011-03-03 13:54:13 +0000101};
102
103// second pass allows anything greater than just clip bit set to pass
104static const GrStencilSettings gUserToClipUnionPass1 = {
105 kReplace_StencilOp, kReplace_StencilOp,
106 kZero_StencilOp, kZero_StencilOp,
107 kLEqual_StencilFunc, kLEqual_StencilFunc,
tomhudson@google.com62b09682011-11-09 16:39:17 +0000108 0xffff, 0xffff,
109 0x0000, 0x0000, // set clip bit
110 0xffff, 0xffff
bsalomon@google.comd302f142011-03-03 13:54:13 +0000111};
112
bsalomon@google.com6b20c2d2011-12-09 21:23:46 +0000113// first pass finds zeros in the user bits and if found sets
114// the clip bit to 1
bsalomon@google.comd302f142011-03-03 13:54:13 +0000115static const GrStencilSettings gInvUserToClipUnionPass0 = {
116 kReplace_StencilOp, kReplace_StencilOp,
117 kKeep_StencilOp, kKeep_StencilOp,
bsalomon@google.com6b20c2d2011-12-09 21:23:46 +0000118 kEqual_StencilFunc, kEqual_StencilFunc,
tomhudson@google.com62b09682011-11-09 16:39:17 +0000119 0xffff, 0xffff, // unset clip bit
120 0x0000, 0x0000, // set clip bit
bsalomon@google.com6b20c2d2011-12-09 21:23:46 +0000121 0x0000, 0x0000 // set clip bit
122};
123
124// second pass zeros the user bits
125static const GrStencilSettings gInvUserToClipUnionPass1 = {
126 kZero_StencilOp, kZero_StencilOp,
127 kZero_StencilOp, kZero_StencilOp,
128 kLess_StencilFunc, kLess_StencilFunc,
129 0xffff, 0xffff,
130 0x0000, 0x0000,
131 0xffff, 0xffff // unset clip bit
bsalomon@google.comd302f142011-03-03 13:54:13 +0000132};
133
134///////
135// Xor
136static const GrStencilSettings gUserToClipXorPass0 = {
137 kInvert_StencilOp, kInvert_StencilOp,
138 kKeep_StencilOp, kKeep_StencilOp,
139 kEqual_StencilFunc, kEqual_StencilFunc,
tomhudson@google.com62b09682011-11-09 16:39:17 +0000140 0xffff, 0xffff, // unset clip bit
141 0x0000, 0x0000,
142 0xffff, 0xffff
bsalomon@google.comd302f142011-03-03 13:54:13 +0000143};
144
145static const GrStencilSettings gUserToClipXorPass1 = {
146 kReplace_StencilOp, kReplace_StencilOp,
147 kZero_StencilOp, kZero_StencilOp,
148 kGreater_StencilFunc, kGreater_StencilFunc,
tomhudson@google.com62b09682011-11-09 16:39:17 +0000149 0xffff, 0xffff,
150 0x0000, 0x0000, // set clip bit
151 0xffff, 0xffff
bsalomon@google.comd302f142011-03-03 13:54:13 +0000152};
153
154static const GrStencilSettings gInvUserToClipXorPass0 = {
155 kInvert_StencilOp, kInvert_StencilOp,
156 kKeep_StencilOp, kKeep_StencilOp,
157 kEqual_StencilFunc, kEqual_StencilFunc,
tomhudson@google.com62b09682011-11-09 16:39:17 +0000158 0xffff, 0xffff, // unset clip bit
159 0x0000, 0x0000,
160 0xffff, 0xffff
bsalomon@google.comd302f142011-03-03 13:54:13 +0000161};
162
163static const GrStencilSettings gInvUserToClipXorPass1 = {
164 kReplace_StencilOp, kReplace_StencilOp,
165 kZero_StencilOp, kZero_StencilOp,
166 kLess_StencilFunc, kLess_StencilFunc,
tomhudson@google.com62b09682011-11-09 16:39:17 +0000167 0xffff, 0xffff,
168 0x0000, 0x0000, // set clip bit
169 0xffff, 0xffff
bsalomon@google.comd302f142011-03-03 13:54:13 +0000170};
171
172///////
173// Reverse Diff
174static const GrStencilSettings gUserToClipRDiffPass0 = {
175 kInvert_StencilOp, kInvert_StencilOp,
176 kZero_StencilOp, kZero_StencilOp,
177 kLess_StencilFunc, kLess_StencilFunc,
tomhudson@google.com62b09682011-11-09 16:39:17 +0000178 0xffff, 0xffff, // unset clip bit
179 0x0000, 0x0000, // set clip bit
180 0xffff, 0xffff
bsalomon@google.comd302f142011-03-03 13:54:13 +0000181};
182
183static const GrStencilSettings gUserToClipRDiffPass1 = {
184 kReplace_StencilOp, kReplace_StencilOp,
185 kZero_StencilOp, kZero_StencilOp,
186 kEqual_StencilFunc, kEqual_StencilFunc,
tomhudson@google.com62b09682011-11-09 16:39:17 +0000187 0x0000, 0x0000, // set clip bit
188 0x0000, 0x0000, // set clip bit
189 0xffff, 0xffff
bsalomon@google.comd302f142011-03-03 13:54:13 +0000190};
191
192static const GrStencilSettings gInvUserToClipRDiff = {
193 kInvert_StencilOp, kInvert_StencilOp,
194 kZero_StencilOp, kZero_StencilOp,
195 kEqual_StencilFunc, kEqual_StencilFunc,
tomhudson@google.com62b09682011-11-09 16:39:17 +0000196 0xffff, 0xffff,
197 0x0000, 0x0000,
198 0x0000, 0x0000 // set clip bit
bsalomon@google.comd302f142011-03-03 13:54:13 +0000199};
200///////
201// Direct to Stencil
202
203// We can render a clip element directly without first writing to the client
204// portion of the clip when the fill is not inverse and the set operation will
205// only modify the in/out status of samples covered by the clip element.
206
207// this one only works if used right after stencil clip was cleared.
208// Our GrClip doesn't allow midstream replace ops.
209static const GrStencilSettings gReplaceClip = {
210 kReplace_StencilOp, kReplace_StencilOp,
211 kReplace_StencilOp, kReplace_StencilOp,
212 kAlways_StencilFunc, kAlways_StencilFunc,
tomhudson@google.com62b09682011-11-09 16:39:17 +0000213 0xffff, 0xffff,
214 0x0000, 0x0000, // set clip bit
215 0x0000, 0x0000 // set clipBit
bsalomon@google.comd302f142011-03-03 13:54:13 +0000216};
217
218static const GrStencilSettings gUnionClip = {
219 kReplace_StencilOp, kReplace_StencilOp,
220 kReplace_StencilOp, kReplace_StencilOp,
221 kAlways_StencilFunc, kAlways_StencilFunc,
tomhudson@google.com62b09682011-11-09 16:39:17 +0000222 0xffff, 0xffff,
223 0x0000, 0x0000, // set clip bit
224 0x0000, 0x0000 // set clip bit
bsalomon@google.comd302f142011-03-03 13:54:13 +0000225};
226
227static const GrStencilSettings gXorClip = {
228 kInvert_StencilOp, kInvert_StencilOp,
229 kInvert_StencilOp, kInvert_StencilOp,
230 kAlways_StencilFunc, kAlways_StencilFunc,
tomhudson@google.com62b09682011-11-09 16:39:17 +0000231 0xffff, 0xffff,
232 0x0000, 0x0000,
233 0x0000, 0x0000 // set clip bit
bsalomon@google.comd302f142011-03-03 13:54:13 +0000234};
235
236static const GrStencilSettings gDiffClip = {
237 kZero_StencilOp, kZero_StencilOp,
238 kZero_StencilOp, kZero_StencilOp,
239 kAlways_StencilFunc, kAlways_StencilFunc,
tomhudson@google.com62b09682011-11-09 16:39:17 +0000240 0xffff, 0xffff,
241 0x0000, 0x0000,
242 0x0000, 0x0000 // set clip bit
bsalomon@google.comd302f142011-03-03 13:54:13 +0000243};
244
bsalomon@google.comd302f142011-03-03 13:54:13 +0000245bool GrStencilSettings::GetClipPasses(GrSetOp op,
246 bool canBeDirect,
247 unsigned int stencilClipMask,
bsalomon@google.com5aaa69e2011-03-04 20:29:08 +0000248 bool invertedFill,
bsalomon@google.comd302f142011-03-03 13:54:13 +0000249 int* numPasses,
250 GrStencilSettings settings[kMaxStencilClipPasses]) {
bsalomon@google.com7f5875d2011-03-24 16:55:45 +0000251 if (canBeDirect && !invertedFill) {
bsalomon@google.com5aaa69e2011-03-04 20:29:08 +0000252 *numPasses = 0;
253 switch (op) {
254 case kReplace_SetOp:
255 *numPasses = 1;
256 settings[0] = gReplaceClip;
257 break;
258 case kUnion_SetOp:
259 *numPasses = 1;
260 settings[0] = gUnionClip;
261 break;
262 case kXor_SetOp:
263 *numPasses = 1;
264 settings[0] = gXorClip;
265 break;
266 case kDifference_SetOp:
267 *numPasses = 1;
268 settings[0] = gDiffClip;
269 break;
270 default: // suppress warning
271 break;
272 }
273 if (1 == *numPasses) {
274 settings[0].fFrontFuncRef |= stencilClipMask;
275 settings[0].fFrontWriteMask |= stencilClipMask;
276 settings[0].fBackFuncRef = settings[0].fFrontFuncRef;
277 settings[0].fBackWriteMask = settings[0].fFrontWriteMask;
278 return true;
bsalomon@google.comd302f142011-03-03 13:54:13 +0000279 }
280 }
281 switch (op) {
bsalomon@google.com5aaa69e2011-03-04 20:29:08 +0000282 // if we make the path renderer go to stencil we always give it a
283 // non-inverted fill and we use the stencil rules on the client->clipbit
284 // pass to select either the zeros or nonzeros.
bsalomon@google.comd302f142011-03-03 13:54:13 +0000285 case kReplace_SetOp:
286 *numPasses= 1;
bsalomon@google.com5aaa69e2011-03-04 20:29:08 +0000287 settings[0] = invertedFill ? gInvUserToClipReplace : gUserToClipReplace;
bsalomon@google.comd302f142011-03-03 13:54:13 +0000288 settings[0].fFrontFuncMask &= ~stencilClipMask;
289 settings[0].fFrontFuncRef |= stencilClipMask;
290 settings[0].fBackFuncMask = settings[0].fFrontFuncMask;
291 settings[0].fBackFuncRef = settings[0].fFrontFuncRef;
bsalomon@google.com5aaa69e2011-03-04 20:29:08 +0000292 break;
bsalomon@google.comd302f142011-03-03 13:54:13 +0000293 case kIntersect_SetOp:
294 *numPasses = 1;
bsalomon@google.com5aaa69e2011-03-04 20:29:08 +0000295 settings[0] = invertedFill ? gInvUserToClipIsect : gUserToClipIsect;
bsalomon@google.comd302f142011-03-03 13:54:13 +0000296 settings[0].fFrontFuncRef = stencilClipMask;
297 settings[0].fBackFuncRef = settings[0].fFrontFuncRef;
298 break;
299 case kUnion_SetOp:
300 *numPasses = 2;
bsalomon@google.com5aaa69e2011-03-04 20:29:08 +0000301 if (invertedFill) {
bsalomon@google.comd302f142011-03-03 13:54:13 +0000302 settings[0] = gInvUserToClipUnionPass0;
bsalomon@google.com6b20c2d2011-12-09 21:23:46 +0000303 settings[0].fFrontFuncMask &= ~stencilClipMask;
304 settings[0].fBackFuncMask = settings[0].fFrontFuncMask;
bsalomon@google.comd302f142011-03-03 13:54:13 +0000305 settings[0].fFrontFuncRef |= stencilClipMask;
bsalomon@google.com6b20c2d2011-12-09 21:23:46 +0000306 settings[0].fBackFuncRef = settings[0].fFrontFuncRef;
307 settings[0].fFrontWriteMask |= stencilClipMask;
308 settings[0].fBackWriteMask = settings[0].fFrontWriteMask;
bsalomon@google.comd302f142011-03-03 13:54:13 +0000309
310 settings[1] = gInvUserToClipUnionPass1;
bsalomon@google.com6b20c2d2011-12-09 21:23:46 +0000311 settings[1].fFrontWriteMask &= ~stencilClipMask;
312 settings[1].fBackWriteMask &= settings[1].fFrontWriteMask;
bsalomon@google.comd302f142011-03-03 13:54:13 +0000313
314 } else {
315 settings[0] = gUserToClipUnionPass0;
316 settings[0].fFrontFuncMask &= ~stencilClipMask;
317 settings[0].fFrontFuncRef |= stencilClipMask;
318 settings[0].fBackFuncMask = settings[0].fFrontFuncMask;
319 settings[0].fBackFuncRef = settings[0].fFrontFuncRef;
320
321 settings[1] = gUserToClipUnionPass1;
322 settings[1].fFrontFuncRef |= stencilClipMask;
323 settings[1].fBackFuncRef = settings[1].fFrontFuncRef;
324 }
325 break;
326 case kXor_SetOp:
327 *numPasses = 2;
bsalomon@google.com5aaa69e2011-03-04 20:29:08 +0000328 if (invertedFill) {
bsalomon@google.comd302f142011-03-03 13:54:13 +0000329 settings[0] = gInvUserToClipXorPass0;
330 settings[0].fFrontFuncMask &= ~stencilClipMask;
331 settings[0].fBackFuncMask = settings[0].fFrontFuncMask;
332
333 settings[1] = gInvUserToClipXorPass1;
334 settings[1].fFrontFuncRef |= stencilClipMask;
335 settings[1].fBackFuncRef = settings[1].fFrontFuncRef;
336 } else {
337 settings[0] = gUserToClipXorPass0;
338 settings[0].fFrontFuncMask &= ~stencilClipMask;
339 settings[0].fBackFuncMask = settings[0].fFrontFuncMask;
340
341 settings[1] = gUserToClipXorPass1;
342 settings[1].fFrontFuncRef |= stencilClipMask;
343 settings[1].fBackFuncRef = settings[1].fFrontFuncRef;
344 }
345 break;
346 case kDifference_SetOp:
347 *numPasses = 1;
bsalomon@google.com5aaa69e2011-03-04 20:29:08 +0000348 settings[0] = invertedFill ? gInvUserToClipDiff : gUserToClipDiff;
bsalomon@google.comd302f142011-03-03 13:54:13 +0000349 settings[0].fFrontFuncRef |= stencilClipMask;
350 settings[0].fBackFuncRef = settings[0].fFrontFuncRef;
351 break;
352 case kReverseDifference_SetOp:
bsalomon@google.com5aaa69e2011-03-04 20:29:08 +0000353 if (invertedFill) {
bsalomon@google.comd302f142011-03-03 13:54:13 +0000354 *numPasses = 1;
355 settings[0] = gInvUserToClipRDiff;
356 settings[0].fFrontWriteMask |= stencilClipMask;
357 settings[0].fBackWriteMask = settings[0].fFrontWriteMask;
358 } else {
359 *numPasses = 2;
360 settings[0] = gUserToClipRDiffPass0;
361 settings[0].fFrontFuncMask &= ~stencilClipMask;
362 settings[0].fBackFuncMask = settings[0].fFrontFuncMask;
363 settings[0].fFrontFuncRef |= stencilClipMask;
364 settings[0].fBackFuncRef = settings[0].fFrontFuncRef;
365
366 settings[1] = gUserToClipRDiffPass1;
367 settings[1].fFrontFuncMask |= stencilClipMask;
368 settings[1].fFrontFuncRef |= stencilClipMask;
369 settings[1].fBackFuncMask = settings[1].fFrontFuncMask;
370 settings[1].fBackFuncRef = settings[1].fFrontFuncRef;
371 }
372 break;
373 default:
374 GrCrash("Unknown set op");
375 }
bsalomon@google.comd302f142011-03-03 13:54:13 +0000376 return false;
ctguil@chromium.orgd5683e22011-04-18 18:12:50 +0000377}