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