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