First batch of OpenGL SI related changes:
[mesa.git] / src / mesa / main / stencil.c
1 /* $Id: stencil.c,v 1.19 2000/09/26 20:53:53 brianp Exp $ */
2
3 /*
4 * Mesa 3-D graphics library
5 * Version: 3.5
6 *
7 * Copyright (C) 1999-2000 Brian Paul All Rights Reserved.
8 *
9 * Permission is hereby granted, free of charge, to any person obtaining a
10 * copy of this software and associated documentation files (the "Software"),
11 * to deal in the Software without restriction, including without limitation
12 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
13 * and/or sell copies of the Software, and to permit persons to whom the
14 * Software is furnished to do so, subject to the following conditions:
15 *
16 * The above copyright notice and this permission notice shall be included
17 * in all copies or substantial portions of the Software.
18 *
19 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
20 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
22 * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
23 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
24 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
25 */
26
27
28 #ifdef PC_HEADER
29 #include "all.h"
30 #else
31 #include "glheader.h"
32 #include "context.h"
33 #include "depth.h"
34 #include "mem.h"
35 #include "pb.h"
36 #include "stencil.h"
37 #include "types.h"
38 #include "enable.h"
39 #endif
40
41
42
43
44 void
45 _mesa_ClearStencil( GLint s )
46 {
47 GET_CURRENT_CONTEXT(ctx);
48 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glClearStencil");
49 ctx->Stencil.Clear = (GLstencil) s;
50
51 if (ctx->Driver.ClearStencil) {
52 (*ctx->Driver.ClearStencil)( ctx, s );
53 }
54 }
55
56
57
58 void
59 _mesa_StencilFunc( GLenum func, GLint ref, GLuint mask )
60 {
61 GET_CURRENT_CONTEXT(ctx);
62 GLint maxref;
63
64 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glStencilFunc");
65
66 switch (func) {
67 case GL_NEVER:
68 case GL_LESS:
69 case GL_LEQUAL:
70 case GL_GREATER:
71 case GL_GEQUAL:
72 case GL_EQUAL:
73 case GL_NOTEQUAL:
74 case GL_ALWAYS:
75 ctx->Stencil.Function = func;
76 break;
77 default:
78 gl_error( ctx, GL_INVALID_ENUM, "glStencilFunc" );
79 return;
80 }
81
82 maxref = (1 << STENCIL_BITS) - 1;
83 ctx->Stencil.Ref = (GLstencil) CLAMP( ref, 0, maxref );
84 ctx->Stencil.ValueMask = (GLstencil) mask;
85
86 if (ctx->Driver.StencilFunc) {
87 (*ctx->Driver.StencilFunc)( ctx, func, ctx->Stencil.Ref, mask );
88 }
89 }
90
91
92
93 void
94 _mesa_StencilMask( GLuint mask )
95 {
96 GET_CURRENT_CONTEXT(ctx);
97 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glStencilMask");
98 ctx->Stencil.WriteMask = (GLstencil) mask;
99
100 if (ctx->Driver.StencilMask) {
101 (*ctx->Driver.StencilMask)( ctx, mask );
102 }
103 }
104
105
106
107 void
108 _mesa_StencilOp(GLenum fail, GLenum zfail, GLenum zpass)
109 {
110 GET_CURRENT_CONTEXT(ctx);
111 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glStencilOp");
112 switch (fail) {
113 case GL_KEEP:
114 case GL_ZERO:
115 case GL_REPLACE:
116 case GL_INCR:
117 case GL_DECR:
118 case GL_INVERT:
119 ctx->Stencil.FailFunc = fail;
120 break;
121 case GL_INCR_WRAP_EXT:
122 case GL_DECR_WRAP_EXT:
123 if (ctx->Extensions.HaveStencilWrap) {
124 ctx->Stencil.FailFunc = fail;
125 break;
126 }
127 /* FALL-THROUGH */
128 default:
129 gl_error(ctx, GL_INVALID_ENUM, "glStencilOp");
130 return;
131 }
132 switch (zfail) {
133 case GL_KEEP:
134 case GL_ZERO:
135 case GL_REPLACE:
136 case GL_INCR:
137 case GL_DECR:
138 case GL_INVERT:
139 ctx->Stencil.ZFailFunc = zfail;
140 break;
141 case GL_INCR_WRAP_EXT:
142 case GL_DECR_WRAP_EXT:
143 if (ctx->Extensions.HaveStencilWrap) {
144 ctx->Stencil.ZFailFunc = zfail;
145 break;
146 }
147 /* FALL-THROUGH */
148 default:
149 gl_error(ctx, GL_INVALID_ENUM, "glStencilOp");
150 return;
151 }
152 switch (zpass) {
153 case GL_KEEP:
154 case GL_ZERO:
155 case GL_REPLACE:
156 case GL_INCR:
157 case GL_DECR:
158 case GL_INVERT:
159 ctx->Stencil.ZPassFunc = zpass;
160 break;
161 case GL_INCR_WRAP_EXT:
162 case GL_DECR_WRAP_EXT:
163 if (ctx->Extensions.HaveStencilWrap) {
164 ctx->Stencil.ZPassFunc = zpass;
165 break;
166 }
167 /* FALL-THROUGH */
168 default:
169 gl_error(ctx, GL_INVALID_ENUM, "glStencilOp");
170 return;
171 }
172
173 if (ctx->Driver.StencilOp) {
174 (*ctx->Driver.StencilOp)(ctx, fail, zfail, zpass);
175 }
176 }
177
178
179
180 /* Stencil Logic:
181
182 IF stencil test fails THEN
183 Apply fail-op to stencil value
184 Don't write the pixel (RGBA,Z)
185 ELSE
186 IF doing depth test && depth test fails THEN
187 Apply zfail-op to stencil value
188 Write RGBA and Z to appropriate buffers
189 ELSE
190 Apply zpass-op to stencil value
191 ENDIF
192
193 */
194
195
196
197
198 /*
199 * Return the address of a stencil buffer value given the window coords:
200 */
201 #define STENCIL_ADDRESS(X,Y) \
202 (ctx->DrawBuffer->Stencil + ctx->DrawBuffer->Width * (Y) + (X))
203
204
205
206 /*
207 * Apply the given stencil operator to the array of stencil values.
208 * Don't touch stencil[i] if mask[i] is zero.
209 * Input: n - size of stencil array
210 * oper - the stencil buffer operator
211 * stencil - array of stencil values
212 * mask - array [n] of flag: 1=apply operator, 0=don't apply operator
213 * Output: stencil - modified values
214 */
215 static void apply_stencil_op( const GLcontext *ctx, GLenum oper,
216 GLuint n, GLstencil stencil[],
217 const GLubyte mask[] )
218 {
219 const GLstencil ref = ctx->Stencil.Ref;
220 const GLstencil wrtmask = ctx->Stencil.WriteMask;
221 const GLstencil invmask = (GLstencil) (~ctx->Stencil.WriteMask);
222 GLuint i;
223
224 switch (oper) {
225 case GL_KEEP:
226 /* do nothing */
227 break;
228 case GL_ZERO:
229 if (invmask==0) {
230 for (i=0;i<n;i++) {
231 if (mask[i]) {
232 stencil[i] = 0;
233 }
234 }
235 }
236 else {
237 for (i=0;i<n;i++) {
238 if (mask[i]) {
239 stencil[i] = (GLstencil) (stencil[i] & invmask);
240 }
241 }
242 }
243 break;
244 case GL_REPLACE:
245 if (invmask==0) {
246 for (i=0;i<n;i++) {
247 if (mask[i]) {
248 stencil[i] = ref;
249 }
250 }
251 }
252 else {
253 for (i=0;i<n;i++) {
254 if (mask[i]) {
255 GLstencil s = stencil[i];
256 stencil[i] = (GLstencil) ((invmask & s ) | (wrtmask & ref));
257 }
258 }
259 }
260 break;
261 case GL_INCR:
262 if (invmask==0) {
263 for (i=0;i<n;i++) {
264 if (mask[i]) {
265 GLstencil s = stencil[i];
266 if (s < STENCIL_MAX) {
267 stencil[i] = (GLstencil) (s+1);
268 }
269 }
270 }
271 }
272 else {
273 for (i=0;i<n;i++) {
274 if (mask[i]) {
275 /* VERIFY logic of adding 1 to a write-masked value */
276 GLstencil s = stencil[i];
277 if (s < STENCIL_MAX) {
278 stencil[i] = (GLstencil) ((invmask & s) | (wrtmask & (s+1)));
279 }
280 }
281 }
282 }
283 break;
284 case GL_DECR:
285 if (invmask==0) {
286 for (i=0;i<n;i++) {
287 if (mask[i]) {
288 GLstencil s = stencil[i];
289 if (s>0) {
290 stencil[i] = (GLstencil) (s-1);
291 }
292 }
293 }
294 }
295 else {
296 for (i=0;i<n;i++) {
297 if (mask[i]) {
298 /* VERIFY logic of subtracting 1 to a write-masked value */
299 GLstencil s = stencil[i];
300 if (s>0) {
301 stencil[i] = (GLstencil) ((invmask & s) | (wrtmask & (s-1)));
302 }
303 }
304 }
305 }
306 break;
307 case GL_INCR_WRAP_EXT:
308 if (invmask==0) {
309 for (i=0;i<n;i++) {
310 if (mask[i]) {
311 stencil[i]++;
312 }
313 }
314 }
315 else {
316 for (i=0;i<n;i++) {
317 if (mask[i]) {
318 GLstencil s = stencil[i];
319 stencil[i] = (GLstencil) ((invmask & s) | (wrtmask & (s+1)));
320 }
321 }
322 }
323 break;
324 case GL_DECR_WRAP_EXT:
325 if (invmask==0) {
326 for (i=0;i<n;i++) {
327 if (mask[i]) {
328 stencil[i]--;
329 }
330 }
331 }
332 else {
333 for (i=0;i<n;i++) {
334 if (mask[i]) {
335 GLstencil s = stencil[i];
336 stencil[i] = (GLstencil) ((invmask & s) | (wrtmask & (s-1)));
337 }
338 }
339 }
340 break;
341 case GL_INVERT:
342 if (invmask==0) {
343 for (i=0;i<n;i++) {
344 if (mask[i]) {
345 GLstencil s = stencil[i];
346 stencil[i] = (GLstencil) ~s;
347 }
348 }
349 }
350 else {
351 for (i=0;i<n;i++) {
352 if (mask[i]) {
353 GLstencil s = stencil[i];
354 stencil[i] = (GLstencil) ((invmask & s) | (wrtmask & ~s));
355 }
356 }
357 }
358 break;
359 default:
360 gl_problem(ctx, "Bad stencil op in apply_stencil_op");
361 }
362 }
363
364
365
366
367 /*
368 * Apply stencil test to an array of stencil values (before depth buffering).
369 * Input: n - number of pixels in the array
370 * stencil - array of [n] stencil values
371 * mask - array [n] of flag: 0=skip the pixel, 1=stencil the pixel
372 * Output: mask - pixels which fail the stencil test will have their
373 * mask flag set to 0.
374 * stencil - updated stencil values (where the test passed)
375 * Return: GL_FALSE = all pixels failed, GL_TRUE = zero or more pixels passed.
376 */
377 static GLboolean
378 do_stencil_test( GLcontext *ctx, GLuint n, GLstencil stencil[],
379 GLubyte mask[] )
380 {
381 GLubyte fail[PB_SIZE];
382 GLboolean allfail = GL_FALSE;
383 GLuint i;
384 GLstencil r, s;
385
386 ASSERT(n <= PB_SIZE);
387
388 /*
389 * Perform stencil test. The results of this operation are stored
390 * in the fail[] array:
391 * IF fail[i] is non-zero THEN
392 * the stencil fail operator is to be applied
393 * ELSE
394 * the stencil fail operator is not to be applied
395 * ENDIF
396 */
397 switch (ctx->Stencil.Function) {
398 case GL_NEVER:
399 /* always fail */
400 for (i=0;i<n;i++) {
401 if (mask[i]) {
402 mask[i] = 0;
403 fail[i] = 1;
404 }
405 else {
406 fail[i] = 0;
407 }
408 }
409 allfail = GL_TRUE;
410 break;
411 case GL_LESS:
412 r = (GLstencil) (ctx->Stencil.Ref & ctx->Stencil.ValueMask);
413 for (i=0;i<n;i++) {
414 if (mask[i]) {
415 s = (GLstencil) (stencil[i] & ctx->Stencil.ValueMask);
416 if (r < s) {
417 /* passed */
418 fail[i] = 0;
419 }
420 else {
421 fail[i] = 1;
422 mask[i] = 0;
423 }
424 }
425 else {
426 fail[i] = 0;
427 }
428 }
429 break;
430 case GL_LEQUAL:
431 r = (GLstencil) (ctx->Stencil.Ref & ctx->Stencil.ValueMask);
432 for (i=0;i<n;i++) {
433 if (mask[i]) {
434 s = (GLstencil) (stencil[i] & ctx->Stencil.ValueMask);
435 if (r <= s) {
436 /* pass */
437 fail[i] = 0;
438 }
439 else {
440 fail[i] = 1;
441 mask[i] = 0;
442 }
443 }
444 else {
445 fail[i] = 0;
446 }
447 }
448 break;
449 case GL_GREATER:
450 r = (GLstencil) (ctx->Stencil.Ref & ctx->Stencil.ValueMask);
451 for (i=0;i<n;i++) {
452 if (mask[i]) {
453 s = (GLstencil) (stencil[i] & ctx->Stencil.ValueMask);
454 if (r > s) {
455 /* passed */
456 fail[i] = 0;
457 }
458 else {
459 fail[i] = 1;
460 mask[i] = 0;
461 }
462 }
463 else {
464 fail[i] = 0;
465 }
466 }
467 break;
468 case GL_GEQUAL:
469 r = (GLstencil) (ctx->Stencil.Ref & ctx->Stencil.ValueMask);
470 for (i=0;i<n;i++) {
471 if (mask[i]) {
472 s = (GLstencil) (stencil[i] & ctx->Stencil.ValueMask);
473 if (r >= s) {
474 /* passed */
475 fail[i] = 0;
476 }
477 else {
478 fail[i] = 1;
479 mask[i] = 0;
480 }
481 }
482 else {
483 fail[i] = 0;
484 }
485 }
486 break;
487 case GL_EQUAL:
488 r = (GLstencil) (ctx->Stencil.Ref & ctx->Stencil.ValueMask);
489 for (i=0;i<n;i++) {
490 if (mask[i]) {
491 s = (GLstencil) (stencil[i] & ctx->Stencil.ValueMask);
492 if (r == s) {
493 /* passed */
494 fail[i] = 0;
495 }
496 else {
497 fail[i] = 1;
498 mask[i] = 0;
499 }
500 }
501 else {
502 fail[i] = 0;
503 }
504 }
505 break;
506 case GL_NOTEQUAL:
507 r = (GLstencil) (ctx->Stencil.Ref & ctx->Stencil.ValueMask);
508 for (i=0;i<n;i++) {
509 if (mask[i]) {
510 s = (GLstencil) (stencil[i] & ctx->Stencil.ValueMask);
511 if (r != s) {
512 /* passed */
513 fail[i] = 0;
514 }
515 else {
516 fail[i] = 1;
517 mask[i] = 0;
518 }
519 }
520 else {
521 fail[i] = 0;
522 }
523 }
524 break;
525 case GL_ALWAYS:
526 /* always pass */
527 for (i=0;i<n;i++) {
528 fail[i] = 0;
529 }
530 break;
531 default:
532 gl_problem(ctx, "Bad stencil func in gl_stencil_span");
533 return 0;
534 }
535
536 if (ctx->Stencil.FailFunc != GL_KEEP) {
537 apply_stencil_op( ctx, ctx->Stencil.FailFunc, n, stencil, fail );
538 }
539
540 return !allfail;
541 }
542
543
544
545
546 /*
547 * Apply stencil and depth testing to an array of pixels.
548 * Hardware or software stencil buffer acceptable.
549 * Input: n - number of pixels in the span
550 * z - array [n] of z values
551 * stencil - array [n] of stencil values
552 * mask - array [n] of flags (1=test this pixel, 0=skip the pixel)
553 * Output: stencil - modified stencil values
554 * mask - array [n] of flags (1=stencil and depth test passed)
555 * Return: GL_TRUE - all fragments failed the testing
556 * GL_FALSE - one or more fragments passed the testing
557 *
558 */
559 static GLboolean
560 stencil_and_ztest_span( GLcontext *ctx, GLuint n, GLint x, GLint y,
561 const GLdepth z[], GLstencil stencil[],
562 GLubyte mask[] )
563 {
564 ASSERT(ctx->Stencil.Enabled);
565 ASSERT(n <= PB_SIZE);
566
567 /*
568 * Apply the stencil test to the fragments.
569 * failMask[i] is 1 if the stencil test failed.
570 */
571 if (do_stencil_test( ctx, n, stencil, mask ) == GL_FALSE) {
572 /* all fragments failed the stencil test, we're done. */
573 return GL_FALSE;
574 }
575
576
577 /*
578 * Some fragments passed the stencil test, apply depth test to them
579 * and apply Zpass and Zfail stencil ops.
580 */
581 if (ctx->Depth.Test==GL_FALSE) {
582 /*
583 * No depth buffer, just apply zpass stencil function to active pixels.
584 */
585 apply_stencil_op( ctx, ctx->Stencil.ZPassFunc, n, stencil, mask );
586 }
587 else {
588 /*
589 * Perform depth buffering, then apply zpass or zfail stencil function.
590 */
591 GLubyte passmask[MAX_WIDTH], failmask[MAX_WIDTH], oldmask[MAX_WIDTH];
592 GLuint i;
593
594 /* save the current mask bits */
595 MEMCPY(oldmask, mask, n * sizeof(GLubyte));
596
597 /* apply the depth test */
598 _mesa_depth_test_span(ctx, n, x, y, z, mask);
599
600 /* Set the stencil pass/fail flags according to result of depth testing.
601 * if oldmask[i] == 0 then
602 * Don't touch the stencil value
603 * else if oldmask[i] and newmask[i] then
604 * Depth test passed
605 * else
606 * assert(oldmask[i] && !newmask[i])
607 * Depth test failed
608 * endif
609 */
610 for (i=0;i<n;i++) {
611 ASSERT(mask[i] == 0 || mask[i] == 1);
612 passmask[i] = oldmask[i] & mask[i];
613 failmask[i] = oldmask[i] & (mask[i] ^ 1);
614 }
615
616 /* apply the pass and fail operations */
617 if (ctx->Stencil.ZFailFunc != GL_KEEP) {
618 apply_stencil_op( ctx, ctx->Stencil.ZFailFunc, n, stencil, failmask );
619 }
620 if (ctx->Stencil.ZPassFunc != GL_KEEP) {
621 apply_stencil_op( ctx, ctx->Stencil.ZPassFunc, n, stencil, passmask );
622 }
623 }
624
625 return GL_TRUE; /* one or more fragments passed both tests */
626 }
627
628
629
630 /*
631 * Apply stencil and depth testing to the span of pixels.
632 * Both software and hardware stencil buffers are acceptable.
633 * Input: n - number of pixels in the span
634 * x, y - location of leftmost pixel in span
635 * z - array [n] of z values
636 * mask - array [n] of flags (1=test this pixel, 0=skip the pixel)
637 * Output: mask - array [n] of flags (1=stencil and depth test passed)
638 * Return: GL_TRUE - all fragments failed the testing
639 * GL_FALSE - one or more fragments passed the testing
640 *
641 */
642 GLboolean
643 _mesa_stencil_and_ztest_span( GLcontext *ctx, GLuint n, GLint x, GLint y,
644 const GLdepth z[], GLubyte mask[] )
645 {
646 GLstencil stencilRow[MAX_WIDTH];
647 GLstencil *stencil;
648 GLboolean result;
649
650 ASSERT(ctx->Stencil.Enabled);
651 ASSERT(n <= MAX_WIDTH);
652
653 /* Get initial stencil values */
654 if (ctx->Driver.WriteStencilSpan) {
655 ASSERT(ctx->Driver.ReadStencilSpan);
656 /* Get stencil values from the hardware stencil buffer */
657 (*ctx->Driver.ReadStencilSpan)(ctx, n, x, y, stencilRow);
658 stencil = stencilRow;
659 }
660 else {
661 /* software stencil buffer */
662 stencil = STENCIL_ADDRESS(x, y);
663 }
664
665 /* do all the stencil/depth testing/updating */
666 result = stencil_and_ztest_span( ctx, n, x, y, z, stencil, mask );
667
668 if (ctx->Driver.WriteStencilSpan) {
669 /* Write updated stencil values into hardware stencil buffer */
670 (ctx->Driver.WriteStencilSpan)(ctx, n, x, y, stencil, mask );
671 }
672
673 return result;
674 }
675
676
677
678
679 /*
680 * Apply the given stencil operator for each pixel in the array whose
681 * mask flag is set. This is for software stencil buffers only.
682 * Input: n - number of pixels in the span
683 * x, y - array of [n] pixels
684 * operator - the stencil buffer operator
685 * mask - array [n] of flag: 1=apply operator, 0=don't apply operator
686 */
687 static void
688 apply_stencil_op_to_pixels( const GLcontext *ctx,
689 GLuint n, const GLint x[], const GLint y[],
690 GLenum oper, const GLubyte mask[] )
691 {
692 const GLstencil ref = ctx->Stencil.Ref;
693 const GLstencil wrtmask = ctx->Stencil.WriteMask;
694 const GLstencil invmask = (GLstencil) (~ctx->Stencil.WriteMask);
695 GLuint i;
696
697 ASSERT(!ctx->Driver.WriteStencilSpan); /* software stencil buffer only! */
698
699 switch (oper) {
700 case GL_KEEP:
701 /* do nothing */
702 break;
703 case GL_ZERO:
704 if (invmask==0) {
705 for (i=0;i<n;i++) {
706 if (mask[i]) {
707 GLstencil *sptr = STENCIL_ADDRESS( x[i], y[i] );
708 *sptr = 0;
709 }
710 }
711 }
712 else {
713 for (i=0;i<n;i++) {
714 if (mask[i]) {
715 GLstencil *sptr = STENCIL_ADDRESS( x[i], y[i] );
716 *sptr = (GLstencil) (invmask & *sptr);
717 }
718 }
719 }
720 break;
721 case GL_REPLACE:
722 if (invmask==0) {
723 for (i=0;i<n;i++) {
724 if (mask[i]) {
725 GLstencil *sptr = STENCIL_ADDRESS( x[i], y[i] );
726 *sptr = ref;
727 }
728 }
729 }
730 else {
731 for (i=0;i<n;i++) {
732 if (mask[i]) {
733 GLstencil *sptr = STENCIL_ADDRESS( x[i], y[i] );
734 *sptr = (GLstencil) ((invmask & *sptr ) | (wrtmask & ref));
735 }
736 }
737 }
738 break;
739 case GL_INCR:
740 if (invmask==0) {
741 for (i=0;i<n;i++) {
742 if (mask[i]) {
743 GLstencil *sptr = STENCIL_ADDRESS( x[i], y[i] );
744 if (*sptr < STENCIL_MAX) {
745 *sptr = (GLstencil) (*sptr + 1);
746 }
747 }
748 }
749 }
750 else {
751 for (i=0;i<n;i++) {
752 if (mask[i]) {
753 GLstencil *sptr = STENCIL_ADDRESS( x[i], y[i] );
754 if (*sptr < STENCIL_MAX) {
755 *sptr = (GLstencil) ((invmask & *sptr) | (wrtmask & (*sptr+1)));
756 }
757 }
758 }
759 }
760 break;
761 case GL_DECR:
762 if (invmask==0) {
763 for (i=0;i<n;i++) {
764 if (mask[i]) {
765 GLstencil *sptr = STENCIL_ADDRESS( x[i], y[i] );
766 if (*sptr>0) {
767 *sptr = (GLstencil) (*sptr - 1);
768 }
769 }
770 }
771 }
772 else {
773 for (i=0;i<n;i++) {
774 if (mask[i]) {
775 GLstencil *sptr = STENCIL_ADDRESS( x[i], y[i] );
776 if (*sptr>0) {
777 *sptr = (GLstencil) ((invmask & *sptr) | (wrtmask & (*sptr-1)));
778 }
779 }
780 }
781 }
782 break;
783 case GL_INCR_WRAP_EXT:
784 if (invmask==0) {
785 for (i=0;i<n;i++) {
786 if (mask[i]) {
787 GLstencil *sptr = STENCIL_ADDRESS( x[i], y[i] );
788 *sptr = (GLstencil) (*sptr + 1);
789 }
790 }
791 }
792 else {
793 for (i=0;i<n;i++) {
794 if (mask[i]) {
795 GLstencil *sptr = STENCIL_ADDRESS( x[i], y[i] );
796 *sptr = (GLstencil) ((invmask & *sptr) | (wrtmask & (*sptr+1)));
797 }
798 }
799 }
800 break;
801 case GL_DECR_WRAP_EXT:
802 if (invmask==0) {
803 for (i=0;i<n;i++) {
804 if (mask[i]) {
805 GLstencil *sptr = STENCIL_ADDRESS( x[i], y[i] );
806 *sptr = (GLstencil) (*sptr - 1);
807 }
808 }
809 }
810 else {
811 for (i=0;i<n;i++) {
812 if (mask[i]) {
813 GLstencil *sptr = STENCIL_ADDRESS( x[i], y[i] );
814 *sptr = (GLstencil) ((invmask & *sptr) | (wrtmask & (*sptr-1)));
815 }
816 }
817 }
818 break;
819 case GL_INVERT:
820 if (invmask==0) {
821 for (i=0;i<n;i++) {
822 if (mask[i]) {
823 GLstencil *sptr = STENCIL_ADDRESS( x[i], y[i] );
824 *sptr = (GLstencil) (~*sptr);
825 }
826 }
827 }
828 else {
829 for (i=0;i<n;i++) {
830 if (mask[i]) {
831 GLstencil *sptr = STENCIL_ADDRESS( x[i], y[i] );
832 *sptr = (GLstencil) ((invmask & *sptr) | (wrtmask & ~*sptr));
833 }
834 }
835 }
836 break;
837 default:
838 gl_problem(ctx, "Bad stencilop in apply_stencil_op_to_pixels");
839 }
840 }
841
842
843
844 /*
845 * Apply stencil test to an array of pixels before depth buffering.
846 * Used for software stencil buffer only.
847 * Input: n - number of pixels in the span
848 * x, y - array of [n] pixels to stencil
849 * mask - array [n] of flag: 0=skip the pixel, 1=stencil the pixel
850 * Output: mask - pixels which fail the stencil test will have their
851 * mask flag set to 0.
852 * Return: 0 = all pixels failed, 1 = zero or more pixels passed.
853 */
854 static GLboolean
855 stencil_test_pixels( GLcontext *ctx, GLuint n,
856 const GLint x[], const GLint y[], GLubyte mask[] )
857 {
858 GLubyte fail[PB_SIZE];
859 GLstencil r, s;
860 GLuint i;
861 GLboolean allfail = GL_FALSE;
862
863 ASSERT(!ctx->Driver.WriteStencilSpan); /* software stencil buffer only! */
864
865 /*
866 * Perform stencil test. The results of this operation are stored
867 * in the fail[] array:
868 * IF fail[i] is non-zero THEN
869 * the stencil fail operator is to be applied
870 * ELSE
871 * the stencil fail operator is not to be applied
872 * ENDIF
873 */
874
875 switch (ctx->Stencil.Function) {
876 case GL_NEVER:
877 /* always fail */
878 for (i=0;i<n;i++) {
879 if (mask[i]) {
880 mask[i] = 0;
881 fail[i] = 1;
882 }
883 else {
884 fail[i] = 0;
885 }
886 }
887 allfail = GL_TRUE;
888 break;
889 case GL_LESS:
890 r = (GLstencil) (ctx->Stencil.Ref & ctx->Stencil.ValueMask);
891 for (i=0;i<n;i++) {
892 if (mask[i]) {
893 GLstencil *sptr = STENCIL_ADDRESS(x[i],y[i]);
894 s = (GLstencil) (*sptr & ctx->Stencil.ValueMask);
895 if (r < s) {
896 /* passed */
897 fail[i] = 0;
898 }
899 else {
900 fail[i] = 1;
901 mask[i] = 0;
902 }
903 }
904 else {
905 fail[i] = 0;
906 }
907 }
908 break;
909 case GL_LEQUAL:
910 r = (GLstencil) (ctx->Stencil.Ref & ctx->Stencil.ValueMask);
911 for (i=0;i<n;i++) {
912 if (mask[i]) {
913 GLstencil *sptr = STENCIL_ADDRESS(x[i],y[i]);
914 s = (GLstencil) (*sptr & ctx->Stencil.ValueMask);
915 if (r <= s) {
916 /* pass */
917 fail[i] = 0;
918 }
919 else {
920 fail[i] = 1;
921 mask[i] = 0;
922 }
923 }
924 else {
925 fail[i] = 0;
926 }
927 }
928 break;
929 case GL_GREATER:
930 r = (GLstencil) (ctx->Stencil.Ref & ctx->Stencil.ValueMask);
931 for (i=0;i<n;i++) {
932 if (mask[i]) {
933 GLstencil *sptr = STENCIL_ADDRESS(x[i],y[i]);
934 s = (GLstencil) (*sptr & ctx->Stencil.ValueMask);
935 if (r > s) {
936 /* passed */
937 fail[i] = 0;
938 }
939 else {
940 fail[i] = 1;
941 mask[i] = 0;
942 }
943 }
944 else {
945 fail[i] = 0;
946 }
947 }
948 break;
949 case GL_GEQUAL:
950 r = (GLstencil) (ctx->Stencil.Ref & ctx->Stencil.ValueMask);
951 for (i=0;i<n;i++) {
952 if (mask[i]) {
953 GLstencil *sptr = STENCIL_ADDRESS(x[i],y[i]);
954 s = (GLstencil) (*sptr & ctx->Stencil.ValueMask);
955 if (r >= s) {
956 /* passed */
957 fail[i] = 0;
958 }
959 else {
960 fail[i] = 1;
961 mask[i] = 0;
962 }
963 }
964 else {
965 fail[i] = 0;
966 }
967 }
968 break;
969 case GL_EQUAL:
970 r = (GLstencil) (ctx->Stencil.Ref & ctx->Stencil.ValueMask);
971 for (i=0;i<n;i++) {
972 if (mask[i]) {
973 GLstencil *sptr = STENCIL_ADDRESS(x[i],y[i]);
974 s = (GLstencil) (*sptr & ctx->Stencil.ValueMask);
975 if (r == s) {
976 /* passed */
977 fail[i] = 0;
978 }
979 else {
980 fail[i] = 1;
981 mask[i] = 0;
982 }
983 }
984 else {
985 fail[i] = 0;
986 }
987 }
988 break;
989 case GL_NOTEQUAL:
990 r = (GLstencil) (ctx->Stencil.Ref & ctx->Stencil.ValueMask);
991 for (i=0;i<n;i++) {
992 if (mask[i]) {
993 GLstencil *sptr = STENCIL_ADDRESS(x[i],y[i]);
994 s = (GLstencil) (*sptr & ctx->Stencil.ValueMask);
995 if (r != s) {
996 /* passed */
997 fail[i] = 0;
998 }
999 else {
1000 fail[i] = 1;
1001 mask[i] = 0;
1002 }
1003 }
1004 else {
1005 fail[i] = 0;
1006 }
1007 }
1008 break;
1009 case GL_ALWAYS:
1010 /* always pass */
1011 for (i=0;i<n;i++) {
1012 fail[i] = 0;
1013 }
1014 break;
1015 default:
1016 gl_problem(ctx, "Bad stencil func in gl_stencil_pixels");
1017 return 0;
1018 }
1019
1020 if (ctx->Stencil.FailFunc != GL_KEEP) {
1021 apply_stencil_op_to_pixels( ctx, n, x, y, ctx->Stencil.FailFunc, fail );
1022 }
1023
1024 return !allfail;
1025 }
1026
1027
1028
1029
1030 /*
1031 * Apply stencil and depth testing to an array of pixels.
1032 * This is used both for software and hardware stencil buffers.
1033 *
1034 * The comments in this function are a bit sparse but the code is
1035 * almost identical to stencil_and_ztest_span(), which is well
1036 * commented.
1037 *
1038 * Input: n - number of pixels in the array
1039 * x, y - array of [n] pixel positions
1040 * z - array [n] of z values
1041 * mask - array [n] of flags (1=test this pixel, 0=skip the pixel)
1042 * Output: mask - array [n] of flags (1=stencil and depth test passed)
1043 * Return: GL_TRUE - all fragments failed the testing
1044 * GL_FALSE - one or more fragments passed the testing
1045 */
1046 GLboolean
1047 _mesa_stencil_and_ztest_pixels( GLcontext *ctx,
1048 GLuint n, const GLint x[], const GLint y[],
1049 const GLdepth z[], GLubyte mask[] )
1050 {
1051 ASSERT(ctx->Stencil.Enabled);
1052 ASSERT(n <= PB_SIZE);
1053
1054 if (ctx->Driver.WriteStencilPixels) {
1055 /*** Hardware stencil buffer ***/
1056 GLstencil stencil[PB_SIZE];
1057 GLubyte mask[PB_SIZE];
1058
1059 ASSERT(ctx->Driver.ReadStencilPixels);
1060 (*ctx->Driver.ReadStencilPixels)(ctx, n, x, y, stencil);
1061
1062
1063 if (do_stencil_test( ctx, n, stencil, mask ) == GL_FALSE) {
1064 /* all fragments failed the stencil test, we're done. */
1065 return GL_FALSE;
1066 }
1067
1068 if (ctx->Depth.Test == GL_FALSE) {
1069 apply_stencil_op( ctx, ctx->Stencil.ZPassFunc, n, stencil, mask );
1070 }
1071 else {
1072 GLubyte passmask[PB_SIZE], failmask[PB_SIZE], oldmask[PB_SIZE];
1073 GLuint i;
1074
1075 MEMCPY(oldmask, mask, n * sizeof(GLubyte));
1076
1077 _mesa_depth_test_pixels(ctx, n, x, y, z, mask);
1078
1079 for (i=0;i<n;i++) {
1080 ASSERT(mask[i] == 0 || mask[i] == 1);
1081 passmask[i] = oldmask[i] & mask[i];
1082 failmask[i] = oldmask[i] & (mask[i] ^ 1);
1083 }
1084
1085 if (ctx->Stencil.ZFailFunc != GL_KEEP) {
1086 apply_stencil_op( ctx, ctx->Stencil.ZFailFunc, n, stencil, failmask );
1087 }
1088 if (ctx->Stencil.ZPassFunc != GL_KEEP) {
1089 apply_stencil_op( ctx, ctx->Stencil.ZPassFunc, n, stencil, passmask );
1090 }
1091 }
1092
1093 /* Write updated stencil values into hardware stencil buffer */
1094 (ctx->Driver.WriteStencilPixels)(ctx, n, x, y, stencil, mask );
1095
1096 return GL_TRUE;
1097
1098 }
1099 else {
1100 /*** Software stencil buffer ***/
1101
1102 if (stencil_test_pixels(ctx, n, x, y, mask) == GL_FALSE) {
1103 /* all fragments failed the stencil test, we're done. */
1104 return GL_FALSE;
1105 }
1106
1107
1108 if (ctx->Depth.Test==GL_FALSE) {
1109 apply_stencil_op_to_pixels( ctx, n, x, y, ctx->Stencil.ZPassFunc, mask );
1110 }
1111 else {
1112 GLubyte passmask[PB_SIZE], failmask[PB_SIZE], oldmask[PB_SIZE];
1113 GLuint i;
1114
1115 MEMCPY(oldmask, mask, n * sizeof(GLubyte));
1116
1117 _mesa_depth_test_pixels(ctx, n, x, y, z, mask);
1118
1119 for (i=0;i<n;i++) {
1120 ASSERT(mask[i] == 0 || mask[i] == 1);
1121 passmask[i] = oldmask[i] & mask[i];
1122 failmask[i] = oldmask[i] & (mask[i] ^ 1);
1123 }
1124
1125 if (ctx->Stencil.ZFailFunc != GL_KEEP) {
1126 apply_stencil_op_to_pixels( ctx, n, x, y,
1127 ctx->Stencil.ZFailFunc, failmask );
1128 }
1129 if (ctx->Stencil.ZPassFunc != GL_KEEP) {
1130 apply_stencil_op_to_pixels( ctx, n, x, y,
1131 ctx->Stencil.ZPassFunc, passmask );
1132 }
1133 }
1134
1135 return GL_TRUE; /* one or more fragments passed both tests */
1136 }
1137 }
1138
1139
1140
1141 /*
1142 * Return a span of stencil values from the stencil buffer.
1143 * Used for glRead/CopyPixels
1144 * Input: n - how many pixels
1145 * x,y - location of first pixel
1146 * Output: stencil - the array of stencil values
1147 */
1148 void
1149 _mesa_read_stencil_span( GLcontext *ctx,
1150 GLint n, GLint x, GLint y, GLstencil stencil[] )
1151 {
1152 if (y < 0 || y >= ctx->DrawBuffer->Height ||
1153 x + n <= 0 || x >= ctx->DrawBuffer->Width) {
1154 /* span is completely outside framebuffer */
1155 return; /* undefined values OK */
1156 }
1157
1158 if (x < 0) {
1159 GLint dx = -x;
1160 x = 0;
1161 n -= dx;
1162 stencil += dx;
1163 }
1164 if (x + n > ctx->DrawBuffer->Width) {
1165 GLint dx = x + n - ctx->DrawBuffer->Width;
1166 n -= dx;
1167 }
1168 if (n <= 0) {
1169 return;
1170 }
1171
1172
1173 ASSERT(n >= 0);
1174 if (ctx->Driver.ReadStencilSpan) {
1175 (*ctx->Driver.ReadStencilSpan)( ctx, (GLuint) n, x, y, stencil );
1176 }
1177 else if (ctx->DrawBuffer->Stencil) {
1178 const GLstencil *s = STENCIL_ADDRESS( x, y );
1179 #if STENCIL_BITS == 8
1180 MEMCPY( stencil, s, n * sizeof(GLstencil) );
1181 #else
1182 GLuint i;
1183 for (i=0;i<n;i++)
1184 stencil[i] = s[i];
1185 #endif
1186 }
1187 }
1188
1189
1190
1191 /*
1192 * Write a span of stencil values to the stencil buffer.
1193 * Used for glDraw/CopyPixels
1194 * Input: n - how many pixels
1195 * x, y - location of first pixel
1196 * stencil - the array of stencil values
1197 */
1198 void
1199 _mesa_write_stencil_span( GLcontext *ctx, GLint n, GLint x, GLint y,
1200 const GLstencil stencil[] )
1201 {
1202 if (y < 0 || y >= ctx->DrawBuffer->Height ||
1203 x + n <= 0 || x >= ctx->DrawBuffer->Width) {
1204 /* span is completely outside framebuffer */
1205 return; /* undefined values OK */
1206 }
1207
1208 if (x < 0) {
1209 GLint dx = -x;
1210 x = 0;
1211 n -= dx;
1212 stencil += dx;
1213 }
1214 if (x + n > ctx->DrawBuffer->Width) {
1215 GLint dx = x + n - ctx->DrawBuffer->Width;
1216 n -= dx;
1217 }
1218 if (n <= 0) {
1219 return;
1220 }
1221
1222 if (ctx->Driver.WriteStencilSpan) {
1223 (*ctx->Driver.WriteStencilSpan)( ctx, n, x, y, stencil, NULL );
1224 }
1225 else if (ctx->DrawBuffer->Stencil) {
1226 GLstencil *s = STENCIL_ADDRESS( x, y );
1227 #if STENCIL_BITS == 8
1228 MEMCPY( s, stencil, n * sizeof(GLstencil) );
1229 #else
1230 GLuint i;
1231 for (i=0;i<n;i++)
1232 s[i] = stencil[i];
1233 #endif
1234 }
1235 }
1236
1237
1238
1239 /*
1240 * Allocate a new stencil buffer. If there's an old one it will be
1241 * deallocated first. The new stencil buffer will be uninitialized.
1242 */
1243 void
1244 _mesa_alloc_stencil_buffer( GLcontext *ctx )
1245 {
1246 GLuint buffersize = ctx->DrawBuffer->Width * ctx->DrawBuffer->Height;
1247
1248 /* deallocate current stencil buffer if present */
1249 if (ctx->DrawBuffer->Stencil) {
1250 FREE(ctx->DrawBuffer->Stencil);
1251 ctx->DrawBuffer->Stencil = NULL;
1252 }
1253
1254 /* allocate new stencil buffer */
1255 ctx->DrawBuffer->Stencil = (GLstencil *) MALLOC(buffersize * sizeof(GLstencil));
1256 if (!ctx->DrawBuffer->Stencil) {
1257 /* out of memory */
1258 _mesa_set_enable( ctx, GL_STENCIL_TEST, GL_FALSE );
1259 gl_error( ctx, GL_OUT_OF_MEMORY, "_mesa_alloc_stencil_buffer" );
1260 }
1261 }
1262
1263
1264
1265 /*
1266 * Clear the software (malloc'd) stencil buffer.
1267 */
1268 static void
1269 clear_software_stencil_buffer( GLcontext *ctx )
1270 {
1271 if (ctx->Visual.StencilBits==0 || !ctx->DrawBuffer->Stencil) {
1272 /* no stencil buffer */
1273 return;
1274 }
1275
1276 if (ctx->Scissor.Enabled) {
1277 /* clear scissor region only */
1278 const GLint width = ctx->DrawBuffer->Xmax - ctx->DrawBuffer->Xmin;
1279 if (ctx->Stencil.WriteMask != STENCIL_MAX) {
1280 /* must apply mask to the clear */
1281 GLint y;
1282 for (y = ctx->DrawBuffer->Ymin; y < ctx->DrawBuffer->Ymax; y++) {
1283 const GLstencil mask = ctx->Stencil.WriteMask;
1284 const GLstencil invMask = ~mask;
1285 const GLstencil clearVal = (ctx->Stencil.Clear & mask);
1286 GLstencil *stencil = STENCIL_ADDRESS( ctx->DrawBuffer->Xmin, y );
1287 GLint i;
1288 for (i = 0; i < width; i++) {
1289 stencil[i] = (stencil[i] & invMask) | clearVal;
1290 }
1291 }
1292 }
1293 else {
1294 /* no masking */
1295 GLint y;
1296 for (y = ctx->DrawBuffer->Ymin; y < ctx->DrawBuffer->Ymax; y++) {
1297 GLstencil *stencil = STENCIL_ADDRESS( ctx->DrawBuffer->Xmin, y );
1298 #if STENCIL_BITS==8
1299 MEMSET( stencil, ctx->Stencil.Clear, width * sizeof(GLstencil) );
1300 #else
1301 GLint i;
1302 for (i = 0; i < width; i++)
1303 stencil[x] = ctx->Stencil.Clear;
1304 #endif
1305 }
1306 }
1307 }
1308 else {
1309 /* clear whole stencil buffer */
1310 if (ctx->Stencil.WriteMask != STENCIL_MAX) {
1311 /* must apply mask to the clear */
1312 const GLuint n = ctx->DrawBuffer->Width * ctx->DrawBuffer->Height;
1313 GLstencil *stencil = ctx->DrawBuffer->Stencil;
1314 const GLstencil mask = ctx->Stencil.WriteMask;
1315 const GLstencil invMask = ~mask;
1316 const GLstencil clearVal = (ctx->Stencil.Clear & mask);
1317 GLuint i;
1318 for (i = 0; i < n; i++) {
1319 stencil[i] = (stencil[i] & invMask) | clearVal;
1320 }
1321 }
1322 else {
1323 /* clear whole buffer without masking */
1324 const GLuint n = ctx->DrawBuffer->Width * ctx->DrawBuffer->Height;
1325 GLstencil *stencil = ctx->DrawBuffer->Stencil;
1326
1327 #if STENCIL_BITS==8
1328 MEMSET(stencil, ctx->Stencil.Clear, n * sizeof(GLstencil) );
1329 #else
1330 GLuint i;
1331 for (i = 0; i < n; i++) {
1332 stencil[i] = ctx->Stencil.Clear;
1333 }
1334 #endif
1335 }
1336 }
1337 }
1338
1339
1340
1341 /*
1342 * Clear the hardware (in graphics card) stencil buffer.
1343 * This is done with the Driver.WriteStencilSpan() and Driver.ReadStencilSpan()
1344 * functions.
1345 * Actually, if there is a hardware stencil buffer it really should have
1346 * been cleared in Driver.Clear()! However, if the hardware does not
1347 * support scissored clears or masked clears (i.e. glStencilMask) then
1348 * we have to use the span-based functions.
1349 */
1350 static void
1351 clear_hardware_stencil_buffer( GLcontext *ctx )
1352 {
1353 ASSERT(ctx->Driver.WriteStencilSpan);
1354 ASSERT(ctx->Driver.ReadStencilSpan);
1355
1356 if (ctx->Scissor.Enabled) {
1357 /* clear scissor region only */
1358 const GLint x = ctx->DrawBuffer->Xmin;
1359 const GLint width = ctx->DrawBuffer->Xmax - ctx->DrawBuffer->Xmin;
1360 if (ctx->Stencil.WriteMask != STENCIL_MAX) {
1361 /* must apply mask to the clear */
1362 GLint y;
1363 for (y = ctx->DrawBuffer->Ymin; y < ctx->DrawBuffer->Ymax; y++) {
1364 const GLstencil mask = ctx->Stencil.WriteMask;
1365 const GLstencil invMask = ~mask;
1366 const GLstencil clearVal = (ctx->Stencil.Clear & mask);
1367 GLstencil stencil[MAX_WIDTH];
1368 GLint i;
1369 (*ctx->Driver.ReadStencilSpan)(ctx, x, y, width, stencil);
1370 for (i = 0; i < width; i++) {
1371 stencil[i] = (stencil[i] & invMask) | clearVal;
1372 }
1373 (*ctx->Driver.WriteStencilSpan)(ctx, x, y, width, stencil, NULL);
1374 }
1375 }
1376 else {
1377 /* no masking */
1378 GLstencil stencil[MAX_WIDTH];
1379 GLint y, i;
1380 for (i = 0; i < width; i++) {
1381 stencil[i] = ctx->Stencil.Clear;
1382 }
1383 for (y = ctx->DrawBuffer->Ymin; y < ctx->DrawBuffer->Ymax; y++) {
1384 (*ctx->Driver.WriteStencilSpan)(ctx, x, y, width, stencil, NULL);
1385 }
1386 }
1387 }
1388 else {
1389 /* clear whole stencil buffer */
1390 if (ctx->Stencil.WriteMask != STENCIL_MAX) {
1391 /* must apply mask to the clear */
1392 const GLstencil mask = ctx->Stencil.WriteMask;
1393 const GLstencil invMask = ~mask;
1394 const GLstencil clearVal = (ctx->Stencil.Clear & mask);
1395 const GLint width = ctx->DrawBuffer->Width;
1396 const GLint height = ctx->DrawBuffer->Height;
1397 const GLint x = ctx->DrawBuffer->Xmin;
1398 GLint y;
1399 for (y = 0; y < height; y++) {
1400 GLstencil stencil[MAX_WIDTH];
1401 GLuint i;
1402 (*ctx->Driver.ReadStencilSpan)(ctx, x, y, width, stencil);
1403 for (i = 0; i < width; i++) {
1404 stencil[i] = (stencil[i] & invMask) | clearVal;
1405 }
1406 (*ctx->Driver.WriteStencilSpan)(ctx, x, y, width, stencil, NULL);
1407 }
1408 }
1409 else {
1410 /* clear whole buffer without masking */
1411 const GLint width = ctx->DrawBuffer->Width;
1412 const GLint height = ctx->DrawBuffer->Width;
1413 const GLint x = ctx->DrawBuffer->Xmin;
1414 GLstencil stencil[MAX_WIDTH];
1415 GLint y, i;
1416 for (i = 0; i < width; i++) {
1417 stencil[i] = ctx->Stencil.Clear;
1418 }
1419 for (y = 0; y < height; y++) {
1420 (*ctx->Driver.WriteStencilSpan)(ctx, x, y, width, stencil, NULL);
1421 }
1422 }
1423 }
1424 }
1425
1426
1427
1428 /*
1429 * Clear the stencil buffer.
1430 */
1431 void
1432 _mesa_clear_stencil_buffer( GLcontext *ctx )
1433 {
1434 if (ctx->Driver.WriteStencilSpan) {
1435 ASSERT(ctx->Driver.ReadStencilSpan);
1436 clear_hardware_stencil_buffer(ctx);
1437 }
1438 else {
1439 clear_software_stencil_buffer(ctx);
1440 }
1441 }
1442