• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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
24 GR_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 
32 GR_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
42 GR_STATIC_CONST_SAME_STENCIL(gUserToClipIsect,
43     kReplace_StencilOp,
44     kZero_StencilOp,
45     kLess_StencilFunc,
46     0xffff,
47     0x0000,           // set clip bit
48     0xffff);
49 
50 GR_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
60 GR_STATIC_CONST_SAME_STENCIL(gUserToClipDiff,
61     kReplace_StencilOp,
62     kZero_StencilOp,
63     kEqual_StencilFunc,
64     0xffff,
65     0x0000,           // set clip bit
66     0xffff);
67 
68 GR_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.
80 GR_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
89 GR_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
99 GR_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
109 GR_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
120 GR_STATIC_CONST_SAME_STENCIL(gUserToClipXorPass0,
121     kInvert_StencilOp,
122     kKeep_StencilOp,
123     kEqual_StencilFunc,
124     0xffff,           // unset clip bit
125     0x0000,
126     0xffff);
127 
128 GR_STATIC_CONST_SAME_STENCIL(gUserToClipXorPass1,
129     kReplace_StencilOp,
130     kZero_StencilOp,
131     kGreater_StencilFunc,
132     0xffff,
133     0x0000,          // set clip bit
134     0xffff);
135 
136 GR_STATIC_CONST_SAME_STENCIL(gInvUserToClipXorPass0,
137     kInvert_StencilOp,
138     kKeep_StencilOp,
139     kEqual_StencilFunc,
140     0xffff,           // unset clip bit
141     0x0000,
142     0xffff);
143 
144 GR_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
154 GR_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 
162 GR_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.
172 GR_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 
181 GR_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.
199 GR_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 
208 GR_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 
217 GR_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 
226 GR_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 
GetClipPasses(SkRegion::Op op,bool canBeDirect,unsigned int stencilClipMask,bool invertedFill,int * numPasses,GrStencilSettings settings[kMaxStencilClipPasses])235 bool 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