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
24GR_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);
39
40///////
41// Intersect
42GR_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);
57
58///////
59// Difference
60GR_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);
75
76///////
77// Union
78
79// first pass makes all the passing cases >= just clip bit set.
80GR_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
89GR_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
99GR_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
109GR_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
120GR_STATIC_CONST_SAME_STENCIL(gUserToClipXorPass0,
121    kInvert_StencilOp,
122    kKeep_StencilOp,
123    kEqual_StencilFunc,
124    0xffff,           // unset clip bit
125    0x0000,
126    0xffff);
127
128GR_STATIC_CONST_SAME_STENCIL(gUserToClipXorPass1,
129    kReplace_StencilOp,
130    kZero_StencilOp,
131    kGreater_StencilFunc,
132    0xffff,
133    0x0000,          // set clip bit
134    0xffff);
135
136GR_STATIC_CONST_SAME_STENCIL(gInvUserToClipXorPass0,
137    kInvert_StencilOp,
138    kKeep_StencilOp,
139    kEqual_StencilFunc,
140    0xffff,           // unset clip bit
141    0x0000,
142    0xffff);
143
144GR_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
154GR_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
162GR_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.
172GR_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
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
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.
199GR_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
208GR_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
217GR_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
226GR_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
235bool 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            SkFAIL("Unknown set op");
393    }
394    return false;
395}
396