• 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 GR_STATIC_CONST_SAME_STENCIL(gInvUserToClipRDiff,
171     kInvert_StencilOp,
172     kZero_StencilOp,
173     kEqual_StencilFunc,
174     0xffff,
175     0x0000,
176     0x0000           // set clip bit
177 );
178 ///////
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.
187 GR_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 );
195 
196 GR_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 );
204 
205 GR_STATIC_CONST_SAME_STENCIL(gXorClip,
206     kInvert_StencilOp,
207     kInvert_StencilOp,
208     kAlways_StencilFunc,
209     0xffff,
210     0x0000,
211     0x0000            // set clip bit
212 );
213 
214 GR_STATIC_CONST_SAME_STENCIL(gDiffClip,
215     kZero_StencilOp,
216     kZero_StencilOp,
217     kAlways_StencilFunc,
218     0xffff,
219     0x0000,
220     0x0000            // set clip bit
221 );
222 
GetClipPasses(GrSetOp op,bool canBeDirect,unsigned int stencilClipMask,bool invertedFill,int * numPasses,GrStencilSettings settings[kMaxStencilClipPasses])223 bool GrStencilSettings::GetClipPasses(GrSetOp op,
224                                       bool canBeDirect,
225                                       unsigned int stencilClipMask,
226                                       bool invertedFill,
227                                       int* numPasses,
228                                       GrStencilSettings settings[kMaxStencilClipPasses]) {
229     if (canBeDirect && !invertedFill) {
230         *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;
257         }
258     }
259     switch (op) {
260         // 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.
263         case kReplace_SetOp:
264             *numPasses= 1;
265             settings[0] = invertedFill ? gInvUserToClipReplace : gUserToClipReplace;
266             settings[0].fFrontFuncMask &= ~stencilClipMask;
267             settings[0].fFrontFuncRef |= stencilClipMask;
268             settings[0].fBackFuncMask = settings[0].fFrontFuncMask;
269             settings[0].fBackFuncRef = settings[0].fFrontFuncRef;
270             break;
271         case kIntersect_SetOp:
272             *numPasses = 1;
273             settings[0] = invertedFill ? gInvUserToClipIsect : gUserToClipIsect;
274             settings[0].fFrontFuncRef = stencilClipMask;
275             settings[0].fBackFuncRef = settings[0].fFrontFuncRef;
276             break;
277         case kUnion_SetOp:
278             *numPasses = 2;
279             if (invertedFill) {
280                 settings[0] = gInvUserToClipUnionPass0;
281                 settings[0].fFrontFuncMask &= ~stencilClipMask;
282                 settings[0].fBackFuncMask = settings[0].fFrontFuncMask;
283                 settings[0].fFrontFuncRef |= stencilClipMask;
284                 settings[0].fBackFuncRef = settings[0].fFrontFuncRef;
285                 settings[0].fFrontWriteMask |= stencilClipMask;
286                 settings[0].fBackWriteMask = settings[0].fFrontWriteMask;
287 
288                 settings[1] = gInvUserToClipUnionPass1;
289                 settings[1].fFrontWriteMask &= ~stencilClipMask;
290                 settings[1].fBackWriteMask &= settings[1].fFrontWriteMask;
291 
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;
306             if (invertedFill) {
307                 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;
326             settings[0] = invertedFill ? gInvUserToClipDiff : gUserToClipDiff;
327             settings[0].fFrontFuncRef |= stencilClipMask;
328             settings[0].fBackFuncRef = settings[0].fFrontFuncRef;
329             break;
330         case kReverseDifference_SetOp:
331             if (invertedFill) {
332                 *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     }
354     return false;
355 }
356