3 * Copyright 2011 Google Inc.
5 * Use of this source code is governed by a BSD-style license that can be
6 * found in the LICENSE file.
10 #include "GrStencil.h"
12 ////////////////////////////////////////////////////////////////////////////////
13 // Stencil Rules for Merging user stencil space into clip
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.
23 // set the ref to be the clip bit, but mask it out for the test
24 GR_STATIC_CONST_SAME_STENCIL(gUserToClipReplace,
28 0xffff, // unset clip bit
29 0x0000, // set clip bit
32 GR_STATIC_CONST_SAME_STENCIL(gInvUserToClipReplace,
36 0xffff, // unset clip bit
37 0x0000, // set clip bit
42 GR_STATIC_CONST_SAME_STENCIL(gUserToClipIsect,
47 0x0000, // set clip bit
50 GR_STATIC_CONST_SAME_STENCIL(gInvUserToClipIsect,
55 0x0000, // set clip bit
60 GR_STATIC_CONST_SAME_STENCIL(gUserToClipDiff,
65 0x0000, // set clip bit
68 GR_STATIC_CONST_SAME_STENCIL(gInvUserToClipDiff,
73 0x0000, // set clip bit
79 // first pass makes all the passing cases >= just clip bit set.
80 GR_STATIC_CONST_SAME_STENCIL(gUserToClipUnionPass0,
85 0x0001, // set clip bit
88 // second pass allows anything greater than just clip bit set to pass
89 GR_STATIC_CONST_SAME_STENCIL(gUserToClipUnionPass1,
94 0x0000, // set clip bit
97 // first pass finds zeros in the user bits and if found sets
99 GR_STATIC_CONST_SAME_STENCIL(gInvUserToClipUnionPass0,
104 0x0000, // set clip bit
105 0x0000 // set clip bit
108 // second pass zeros the user bits
109 GR_STATIC_CONST_SAME_STENCIL(gInvUserToClipUnionPass1,
115 0xffff // unset clip bit
120 GR_STATIC_CONST_SAME_STENCIL(gUserToClipXorPass0,
124 0xffff, // unset clip bit
128 GR_STATIC_CONST_SAME_STENCIL(gUserToClipXorPass1,
131 kGreater_StencilFunc,
133 0x0000, // set clip bit
136 GR_STATIC_CONST_SAME_STENCIL(gInvUserToClipXorPass0,
140 0xffff, // unset clip bit
144 GR_STATIC_CONST_SAME_STENCIL(gInvUserToClipXorPass1,
149 0x0000, // set clip bit
154 GR_STATIC_CONST_SAME_STENCIL(gUserToClipRDiffPass0,
158 0xffff, // unset clip bit
159 0x0000, // set clip bit
162 GR_STATIC_CONST_SAME_STENCIL(gUserToClipRDiffPass1,
166 0x0000, // set clip bit
167 0x0000, // set clip bit
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,
178 0x0000 // set clip bit
181 GR_STATIC_CONST_SAME_STENCIL(gInvUserToClipRDiffPass1,
187 0xffff // unset clip bit
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.
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,
204 0x0000, // set clip bit
205 0x0000 // set clipBit
208 GR_STATIC_CONST_SAME_STENCIL(gUnionClip,
213 0x0000, // set clip bit
214 0x0000 // set clip bit
217 GR_STATIC_CONST_SAME_STENCIL(gXorClip,
223 0x0000 // set clip bit
226 GR_STATIC_CONST_SAME_STENCIL(gDiffClip,
232 0x0000 // set clip bit
235 bool GrStencilSettings::GetClipPasses(
238 unsigned int stencilClipMask,
241 GrStencilSettings settings[kMaxStencilClipPasses]) {
242 if (canBeDirect && !invertedFill) {
245 case SkRegion::kReplace_Op:
247 settings[0] = gReplaceClip;
249 case SkRegion::kUnion_Op:
251 settings[0] = gUnionClip;
253 case SkRegion::kXOR_Op:
255 settings[0] = gXorClip;
257 case SkRegion::kDifference_Op:
259 settings[0] = gDiffClip;
261 default: // suppress warning
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];
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:
280 settings[0] = invertedFill ? gInvUserToClipReplace :
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];
289 case SkRegion::kIntersect_Op:
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];
296 case SkRegion::kUnion_Op:
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];
310 settings[1] = gInvUserToClipUnionPass1;
311 settings[1].fWriteMasks[kFront_Face] &= ~stencilClipMask;
312 settings[1].fWriteMasks[kBack_Face] &=
313 settings[1].fWriteMasks[kFront_Face];
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];
324 settings[1] = gUserToClipUnionPass1;
325 settings[1].fFuncRefs[kFront_Face] |= stencilClipMask;
326 settings[1].fFuncRefs[kBack_Face] =
327 settings[1].fFuncRefs[kFront_Face];
330 case SkRegion::kXOR_Op:
333 settings[0] = gInvUserToClipXorPass0;
334 settings[0].fFuncMasks[kFront_Face] &= ~stencilClipMask;
335 settings[0].fFuncMasks[kBack_Face] =
336 settings[0].fFuncMasks[kFront_Face];
338 settings[1] = gInvUserToClipXorPass1;
339 settings[1].fFuncRefs[kFront_Face] |= stencilClipMask;
340 settings[1].fFuncRefs[kBack_Face] =
341 settings[1].fFuncRefs[kFront_Face];
343 settings[0] = gUserToClipXorPass0;
344 settings[0].fFuncMasks[kFront_Face] &= ~stencilClipMask;
345 settings[0].fFuncMasks[kBack_Face] =
346 settings[0].fFuncMasks[kFront_Face];
348 settings[1] = gUserToClipXorPass1;
349 settings[1].fFuncRefs[kFront_Face] |= stencilClipMask;
350 settings[1].fFuncRefs[kBack_Face] =
351 settings[1].fFuncRefs[kFront_Face];
354 case SkRegion::kDifference_Op:
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];
361 case SkRegion::kReverseDifference_Op:
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];
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];
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];
392 SkFAIL("Unknown set op");