stencil.c revision b1394fa92aaaf859ce9efc8b5fc194397921320c
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
44void
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
58void
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
93void
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
107void
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
182IF stencil test fails THEN
183   Apply fail-op to stencil value
184   Don't write the pixel (RGBA,Z)
185ELSE
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
191ENDIF
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 */
215static 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 */
377static GLboolean
378do_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 */
559static GLboolean
560stencil_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 */
642GLboolean
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 */
687static void
688apply_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 */
854static GLboolean
855stencil_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 */
1046GLboolean
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 */
1148void
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 */
1198void
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 */
1243void
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 */
1268static void
1269clear_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 */
1350static void
1351clear_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 */
1431void
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
1443