s_stencil.c revision 4a49301e
1/*
2 * Mesa 3-D graphics library
3 * Version:  7.1
4 *
5 * Copyright (C) 1999-2007  Brian Paul   All Rights Reserved.
6 *
7 * Permission is hereby granted, free of charge, to any person obtaining a
8 * copy of this software and associated documentation files (the "Software"),
9 * to deal in the Software without restriction, including without limitation
10 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
11 * and/or sell copies of the Software, and to permit persons to whom the
12 * Software is furnished to do so, subject to the following conditions:
13 *
14 * The above copyright notice and this permission notice shall be included
15 * in all copies or substantial portions of the Software.
16 *
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
18 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
20 * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
21 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
22 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23 */
24
25
26#include "main/glheader.h"
27#include "main/context.h"
28#include "main/imports.h"
29
30#include "s_context.h"
31#include "s_depth.h"
32#include "s_stencil.h"
33#include "s_span.h"
34
35
36
37/* Stencil Logic:
38
39IF stencil test fails THEN
40   Apply fail-op to stencil value
41   Don't write the pixel (RGBA,Z)
42ELSE
43   IF doing depth test && depth test fails THEN
44      Apply zfail-op to stencil value
45      Write RGBA and Z to appropriate buffers
46   ELSE
47      Apply zpass-op to stencil value
48ENDIF
49
50*/
51
52
53/**
54 * Apply the given stencil operator to the array of stencil values.
55 * Don't touch stencil[i] if mask[i] is zero.
56 * Input:  n - size of stencil array
57 *         oper - the stencil buffer operator
58 *         face - 0 or 1 for front or back face operation
59 *         stencil - array of stencil values
60 *         mask - array [n] of flag:  1=apply operator, 0=don't apply operator
61 * Output:  stencil - modified values
62 */
63static void
64apply_stencil_op( const GLcontext *ctx, GLenum oper, GLuint face,
65                  GLuint n, GLstencil stencil[], const GLubyte mask[] )
66{
67   const GLstencil ref = ctx->Stencil.Ref[face];
68   const GLstencil wrtmask = ctx->Stencil.WriteMask[face];
69   const GLstencil invmask = (GLstencil) (~wrtmask);
70   const GLstencil stencilMax = (1 << ctx->DrawBuffer->Visual.stencilBits) - 1;
71   GLuint i;
72
73   switch (oper) {
74      case GL_KEEP:
75         /* do nothing */
76         break;
77      case GL_ZERO:
78	 if (invmask==0) {
79	    for (i=0;i<n;i++) {
80	       if (mask[i]) {
81		  stencil[i] = 0;
82	       }
83	    }
84	 }
85	 else {
86	    for (i=0;i<n;i++) {
87	       if (mask[i]) {
88		  stencil[i] = (GLstencil) (stencil[i] & invmask);
89	       }
90	    }
91	 }
92	 break;
93      case GL_REPLACE:
94	 if (invmask==0) {
95	    for (i=0;i<n;i++) {
96	       if (mask[i]) {
97                  stencil[i] = ref;
98	       }
99	    }
100	 }
101	 else {
102	    for (i=0;i<n;i++) {
103	       if (mask[i]) {
104		  GLstencil s = stencil[i];
105		  stencil[i] = (GLstencil) ((invmask & s ) | (wrtmask & ref));
106	       }
107	    }
108	 }
109	 break;
110      case GL_INCR:
111	 if (invmask==0) {
112	    for (i=0;i<n;i++) {
113	       if (mask[i]) {
114		  GLstencil s = stencil[i];
115		  if (s < stencilMax) {
116		     stencil[i] = (GLstencil) (s+1);
117		  }
118	       }
119	    }
120	 }
121	 else {
122	    for (i=0;i<n;i++) {
123	       if (mask[i]) {
124		  /* VERIFY logic of adding 1 to a write-masked value */
125		  GLstencil s = stencil[i];
126		  if (s < stencilMax) {
127		     stencil[i] = (GLstencil) ((invmask & s) | (wrtmask & (s+1)));
128		  }
129	       }
130	    }
131	 }
132	 break;
133      case GL_DECR:
134	 if (invmask==0) {
135	    for (i=0;i<n;i++) {
136	       if (mask[i]) {
137		  GLstencil s = stencil[i];
138		  if (s>0) {
139		     stencil[i] = (GLstencil) (s-1);
140		  }
141	       }
142	    }
143	 }
144	 else {
145	    for (i=0;i<n;i++) {
146	       if (mask[i]) {
147		  /* VERIFY logic of subtracting 1 to a write-masked value */
148		  GLstencil s = stencil[i];
149		  if (s>0) {
150		     stencil[i] = (GLstencil) ((invmask & s) | (wrtmask & (s-1)));
151		  }
152	       }
153	    }
154	 }
155	 break;
156      case GL_INCR_WRAP_EXT:
157	 if (invmask==0) {
158	    for (i=0;i<n;i++) {
159	       if (mask[i]) {
160                  stencil[i]++;
161	       }
162	    }
163	 }
164	 else {
165	    for (i=0;i<n;i++) {
166	       if (mask[i]) {
167                  GLstencil s = stencil[i];
168                  stencil[i] = (GLstencil) ((invmask & s) | (wrtmask & (s+1)));
169	       }
170	    }
171	 }
172	 break;
173      case GL_DECR_WRAP_EXT:
174	 if (invmask==0) {
175	    for (i=0;i<n;i++) {
176	       if (mask[i]) {
177		  stencil[i]--;
178	       }
179	    }
180	 }
181	 else {
182	    for (i=0;i<n;i++) {
183	       if (mask[i]) {
184                  GLstencil s = stencil[i];
185                  stencil[i] = (GLstencil) ((invmask & s) | (wrtmask & (s-1)));
186	       }
187	    }
188	 }
189	 break;
190      case GL_INVERT:
191	 if (invmask==0) {
192	    for (i=0;i<n;i++) {
193	       if (mask[i]) {
194		  GLstencil s = stencil[i];
195		  stencil[i] = (GLstencil) ~s;
196	       }
197	    }
198	 }
199	 else {
200	    for (i=0;i<n;i++) {
201	       if (mask[i]) {
202		  GLstencil s = stencil[i];
203		  stencil[i] = (GLstencil) ((invmask & s) | (wrtmask & ~s));
204	       }
205	    }
206	 }
207	 break;
208      default:
209         _mesa_problem(ctx, "Bad stencil op in apply_stencil_op");
210   }
211}
212
213
214
215
216/**
217 * Apply stencil test to an array of stencil values (before depth buffering).
218 * Input:  face - 0 or 1 for front or back-face polygons
219 *         n - number of pixels in the array
220 *         stencil - array of [n] stencil values
221 *         mask - array [n] of flag:  0=skip the pixel, 1=stencil the pixel
222 * Output:  mask - pixels which fail the stencil test will have their
223 *                 mask flag set to 0.
224 *          stencil - updated stencil values (where the test passed)
225 * Return:  GL_FALSE = all pixels failed, GL_TRUE = zero or more pixels passed.
226 */
227static GLboolean
228do_stencil_test( GLcontext *ctx, GLuint face, GLuint n, GLstencil stencil[],
229                 GLubyte mask[] )
230{
231   GLubyte fail[MAX_WIDTH];
232   GLboolean allfail = GL_FALSE;
233   GLuint i;
234   const GLuint valueMask = ctx->Stencil.ValueMask[face];
235   const GLstencil r = (GLstencil) (ctx->Stencil.Ref[face] & valueMask);
236   GLstencil s;
237
238   ASSERT(n <= MAX_WIDTH);
239
240   /*
241    * Perform stencil test.  The results of this operation are stored
242    * in the fail[] array:
243    *   IF fail[i] is non-zero THEN
244    *       the stencil fail operator is to be applied
245    *   ELSE
246    *       the stencil fail operator is not to be applied
247    *   ENDIF
248    */
249   switch (ctx->Stencil.Function[face]) {
250      case GL_NEVER:
251         /* never pass; always fail */
252         for (i=0;i<n;i++) {
253	    if (mask[i]) {
254	       mask[i] = 0;
255	       fail[i] = 1;
256	    }
257	    else {
258	       fail[i] = 0;
259	    }
260	 }
261	 allfail = GL_TRUE;
262	 break;
263      case GL_LESS:
264	 for (i=0;i<n;i++) {
265	    if (mask[i]) {
266	       s = (GLstencil) (stencil[i] & valueMask);
267	       if (r < s) {
268		  /* passed */
269		  fail[i] = 0;
270	       }
271	       else {
272		  fail[i] = 1;
273		  mask[i] = 0;
274	       }
275	    }
276	    else {
277	       fail[i] = 0;
278	    }
279	 }
280	 break;
281      case GL_LEQUAL:
282	 for (i=0;i<n;i++) {
283	    if (mask[i]) {
284	       s = (GLstencil) (stencil[i] & valueMask);
285	       if (r <= s) {
286		  /* pass */
287		  fail[i] = 0;
288	       }
289	       else {
290		  fail[i] = 1;
291		  mask[i] = 0;
292	       }
293	    }
294	    else {
295	       fail[i] = 0;
296	    }
297	 }
298	 break;
299      case GL_GREATER:
300	 for (i=0;i<n;i++) {
301	    if (mask[i]) {
302	       s = (GLstencil) (stencil[i] & valueMask);
303	       if (r > s) {
304		  /* passed */
305		  fail[i] = 0;
306	       }
307	       else {
308		  fail[i] = 1;
309		  mask[i] = 0;
310	       }
311	    }
312	    else {
313	       fail[i] = 0;
314	    }
315	 }
316	 break;
317      case GL_GEQUAL:
318	 for (i=0;i<n;i++) {
319	    if (mask[i]) {
320	       s = (GLstencil) (stencil[i] & valueMask);
321	       if (r >= s) {
322		  /* passed */
323		  fail[i] = 0;
324	       }
325	       else {
326		  fail[i] = 1;
327		  mask[i] = 0;
328	       }
329	    }
330	    else {
331	       fail[i] = 0;
332	    }
333	 }
334	 break;
335      case GL_EQUAL:
336	 for (i=0;i<n;i++) {
337	    if (mask[i]) {
338	       s = (GLstencil) (stencil[i] & valueMask);
339	       if (r == s) {
340		  /* passed */
341		  fail[i] = 0;
342	       }
343	       else {
344		  fail[i] = 1;
345		  mask[i] = 0;
346	       }
347	    }
348	    else {
349	       fail[i] = 0;
350	    }
351	 }
352	 break;
353      case GL_NOTEQUAL:
354	 for (i=0;i<n;i++) {
355	    if (mask[i]) {
356	       s = (GLstencil) (stencil[i] & valueMask);
357	       if (r != s) {
358		  /* passed */
359		  fail[i] = 0;
360	       }
361	       else {
362		  fail[i] = 1;
363		  mask[i] = 0;
364	       }
365	    }
366	    else {
367	       fail[i] = 0;
368	    }
369	 }
370	 break;
371      case GL_ALWAYS:
372	 /* always pass */
373	 for (i=0;i<n;i++) {
374	    fail[i] = 0;
375	 }
376	 break;
377      default:
378         _mesa_problem(ctx, "Bad stencil func in gl_stencil_span");
379         return 0;
380   }
381
382   if (ctx->Stencil.FailFunc[face] != GL_KEEP) {
383      apply_stencil_op( ctx, ctx->Stencil.FailFunc[face], face, n, stencil, fail );
384   }
385
386   return !allfail;
387}
388
389
390/**
391 * Compute the zpass/zfail masks by comparing the pre- and post-depth test
392 * masks.
393 */
394static INLINE void
395compute_pass_fail_masks(GLuint n, const GLubyte origMask[],
396                        const GLubyte newMask[],
397                        GLubyte passMask[], GLubyte failMask[])
398{
399   GLuint i;
400   for (i = 0; i < n; i++) {
401      ASSERT(newMask[i] == 0 || newMask[i] == 1);
402      passMask[i] = origMask[i] & newMask[i];
403      failMask[i] = origMask[i] & (newMask[i] ^ 1);
404   }
405}
406
407
408/**
409 * Apply stencil and depth testing to the span of pixels.
410 * Both software and hardware stencil buffers are acceptable.
411 * Input:  n - number of pixels in the span
412 *         x, y - location of leftmost pixel in span
413 *         z - array [n] of z values
414 *         mask - array [n] of flags  (1=test this pixel, 0=skip the pixel)
415 * Output:  mask - array [n] of flags (1=stencil and depth test passed)
416 * Return: GL_FALSE - all fragments failed the testing
417 *         GL_TRUE - one or more fragments passed the testing
418 *
419 */
420static GLboolean
421stencil_and_ztest_span(GLcontext *ctx, SWspan *span, GLuint face)
422{
423   struct gl_framebuffer *fb = ctx->DrawBuffer;
424   struct gl_renderbuffer *rb = fb->_StencilBuffer;
425   GLstencil stencilRow[MAX_WIDTH];
426   GLstencil *stencil;
427   const GLuint n = span->end;
428   const GLint x = span->x;
429   const GLint y = span->y;
430   GLubyte *mask = span->array->mask;
431
432   ASSERT((span->arrayMask & SPAN_XY) == 0);
433   ASSERT(ctx->Stencil.Enabled);
434   ASSERT(n <= MAX_WIDTH);
435#ifdef DEBUG
436   if (ctx->Depth.Test) {
437      ASSERT(span->arrayMask & SPAN_Z);
438   }
439#endif
440
441   stencil = (GLstencil *) rb->GetPointer(ctx, rb, x, y);
442   if (!stencil) {
443      rb->GetRow(ctx, rb, n, x, y, stencilRow);
444      stencil = stencilRow;
445   }
446
447   /*
448    * Apply the stencil test to the fragments.
449    * failMask[i] is 1 if the stencil test failed.
450    */
451   if (do_stencil_test( ctx, face, n, stencil, mask ) == GL_FALSE) {
452      /* all fragments failed the stencil test, we're done. */
453      span->writeAll = GL_FALSE;
454      if (!rb->GetPointer(ctx, rb, 0, 0)) {
455         /* put updated stencil values into buffer */
456         rb->PutRow(ctx, rb, n, x, y, stencil, NULL);
457      }
458      return GL_FALSE;
459   }
460
461   /*
462    * Some fragments passed the stencil test, apply depth test to them
463    * and apply Zpass and Zfail stencil ops.
464    */
465   if (ctx->Depth.Test == GL_FALSE) {
466      /*
467       * No depth buffer, just apply zpass stencil function to active pixels.
468       */
469      apply_stencil_op( ctx, ctx->Stencil.ZPassFunc[face], face, n, stencil, mask );
470   }
471   else {
472      /*
473       * Perform depth buffering, then apply zpass or zfail stencil function.
474       */
475      GLubyte passMask[MAX_WIDTH], failMask[MAX_WIDTH], origMask[MAX_WIDTH];
476
477      /* save the current mask bits */
478      _mesa_memcpy(origMask, mask, n * sizeof(GLubyte));
479
480      /* apply the depth test */
481      _swrast_depth_test_span(ctx, span);
482
483      compute_pass_fail_masks(n, origMask, mask, passMask, failMask);
484
485      /* apply the pass and fail operations */
486      if (ctx->Stencil.ZFailFunc[face] != GL_KEEP) {
487         apply_stencil_op( ctx, ctx->Stencil.ZFailFunc[face], face,
488                           n, stencil, failMask );
489      }
490      if (ctx->Stencil.ZPassFunc[face] != GL_KEEP) {
491         apply_stencil_op( ctx, ctx->Stencil.ZPassFunc[face], face,
492                           n, stencil, passMask );
493      }
494   }
495
496   /*
497    * Write updated stencil values back into hardware stencil buffer.
498    */
499   if (!rb->GetPointer(ctx, rb, 0, 0)) {
500      rb->PutRow(ctx, rb, n, x, y, stencil, NULL);
501   }
502
503   span->writeAll = GL_FALSE;
504
505   return GL_TRUE;  /* one or more fragments passed both tests */
506}
507
508
509
510/*
511 * Return the address of a stencil buffer value given the window coords:
512 */
513#define STENCIL_ADDRESS(X, Y)  (stencilStart + (Y) * stride + (X))
514
515
516
517/**
518 * Apply the given stencil operator for each pixel in the array whose
519 * mask flag is set.
520 * \note  This is for software stencil buffers only.
521 * Input:  n - number of pixels in the span
522 *         x, y - array of [n] pixels
523 *         operator - the stencil buffer operator
524 *         mask - array [n] of flag:  1=apply operator, 0=don't apply operator
525 */
526static void
527apply_stencil_op_to_pixels( GLcontext *ctx,
528                            GLuint n, const GLint x[], const GLint y[],
529                            GLenum oper, GLuint face, const GLubyte mask[] )
530{
531   struct gl_framebuffer *fb = ctx->DrawBuffer;
532   struct gl_renderbuffer *rb = fb->_StencilBuffer;
533   const GLstencil stencilMax = (1 << fb->Visual.stencilBits) - 1;
534   const GLstencil ref = ctx->Stencil.Ref[face];
535   const GLstencil wrtmask = ctx->Stencil.WriteMask[face];
536   const GLstencil invmask = (GLstencil) (~wrtmask);
537   GLuint i;
538   GLstencil *stencilStart = (GLubyte *) rb->Data;
539   const GLuint stride = rb->Width;
540
541   ASSERT(rb->GetPointer(ctx, rb, 0, 0));
542   ASSERT(sizeof(GLstencil) == 1);
543
544   switch (oper) {
545      case GL_KEEP:
546         /* do nothing */
547         break;
548      case GL_ZERO:
549	 if (invmask==0) {
550	    for (i=0;i<n;i++) {
551	       if (mask[i]) {
552                  GLstencil *sptr = STENCIL_ADDRESS( x[i], y[i] );
553                  *sptr = 0;
554	       }
555	    }
556	 }
557	 else {
558	    for (i=0;i<n;i++) {
559	       if (mask[i]) {
560                  GLstencil *sptr = STENCIL_ADDRESS( x[i], y[i] );
561		  *sptr = (GLstencil) (invmask & *sptr);
562	       }
563	    }
564	 }
565	 break;
566      case GL_REPLACE:
567	 if (invmask==0) {
568	    for (i=0;i<n;i++) {
569	       if (mask[i]) {
570                  GLstencil *sptr = STENCIL_ADDRESS( x[i], y[i] );
571                  *sptr = ref;
572	       }
573	    }
574	 }
575	 else {
576	    for (i=0;i<n;i++) {
577	       if (mask[i]) {
578                  GLstencil *sptr = STENCIL_ADDRESS( x[i], y[i] );
579		  *sptr = (GLstencil) ((invmask & *sptr ) | (wrtmask & ref));
580	       }
581	    }
582	 }
583	 break;
584      case GL_INCR:
585	 if (invmask==0) {
586	    for (i=0;i<n;i++) {
587	       if (mask[i]) {
588                  GLstencil *sptr = STENCIL_ADDRESS( x[i], y[i] );
589		  if (*sptr < stencilMax) {
590		     *sptr = (GLstencil) (*sptr + 1);
591		  }
592	       }
593	    }
594	 }
595	 else {
596	    for (i=0;i<n;i++) {
597	       if (mask[i]) {
598                  GLstencil *sptr = STENCIL_ADDRESS( x[i], y[i] );
599		  if (*sptr < stencilMax) {
600		     *sptr = (GLstencil) ((invmask & *sptr) | (wrtmask & (*sptr+1)));
601		  }
602	       }
603	    }
604	 }
605	 break;
606      case GL_DECR:
607	 if (invmask==0) {
608	    for (i=0;i<n;i++) {
609	       if (mask[i]) {
610                  GLstencil *sptr = STENCIL_ADDRESS( x[i], y[i] );
611		  if (*sptr>0) {
612		     *sptr = (GLstencil) (*sptr - 1);
613		  }
614	       }
615	    }
616	 }
617	 else {
618	    for (i=0;i<n;i++) {
619	       if (mask[i]) {
620                  GLstencil *sptr = STENCIL_ADDRESS( x[i], y[i] );
621		  if (*sptr>0) {
622		     *sptr = (GLstencil) ((invmask & *sptr) | (wrtmask & (*sptr-1)));
623		  }
624	       }
625	    }
626	 }
627	 break;
628      case GL_INCR_WRAP_EXT:
629	 if (invmask==0) {
630	    for (i=0;i<n;i++) {
631	       if (mask[i]) {
632                  GLstencil *sptr = STENCIL_ADDRESS( x[i], y[i] );
633                  *sptr = (GLstencil) (*sptr + 1);
634	       }
635	    }
636	 }
637	 else {
638	    for (i=0;i<n;i++) {
639	       if (mask[i]) {
640                  GLstencil *sptr = STENCIL_ADDRESS( x[i], y[i] );
641                  *sptr = (GLstencil) ((invmask & *sptr) | (wrtmask & (*sptr+1)));
642	       }
643	    }
644	 }
645	 break;
646      case GL_DECR_WRAP_EXT:
647	 if (invmask==0) {
648	    for (i=0;i<n;i++) {
649	       if (mask[i]) {
650                  GLstencil *sptr = STENCIL_ADDRESS( x[i], y[i] );
651                  *sptr = (GLstencil) (*sptr - 1);
652	       }
653	    }
654	 }
655	 else {
656	    for (i=0;i<n;i++) {
657	       if (mask[i]) {
658                  GLstencil *sptr = STENCIL_ADDRESS( x[i], y[i] );
659                  *sptr = (GLstencil) ((invmask & *sptr) | (wrtmask & (*sptr-1)));
660	       }
661	    }
662	 }
663	 break;
664      case GL_INVERT:
665	 if (invmask==0) {
666	    for (i=0;i<n;i++) {
667	       if (mask[i]) {
668                  GLstencil *sptr = STENCIL_ADDRESS( x[i], y[i] );
669                  *sptr = (GLstencil) (~*sptr);
670	       }
671	    }
672	 }
673	 else {
674	    for (i=0;i<n;i++) {
675	       if (mask[i]) {
676                  GLstencil *sptr = STENCIL_ADDRESS( x[i], y[i] );
677                  *sptr = (GLstencil) ((invmask & *sptr) | (wrtmask & ~*sptr));
678	       }
679	    }
680	 }
681	 break;
682      default:
683         _mesa_problem(ctx, "Bad stencilop in apply_stencil_op_to_pixels");
684   }
685}
686
687
688
689/**
690 * Apply stencil test to an array of pixels before depth buffering.
691 *
692 * \note Used for software stencil buffer only.
693 * Input:  n - number of pixels in the span
694 *         x, y - array of [n] pixels to stencil
695 *         mask - array [n] of flag:  0=skip the pixel, 1=stencil the pixel
696 * Output:  mask - pixels which fail the stencil test will have their
697 *                 mask flag set to 0.
698 * \return  GL_FALSE = all pixels failed, GL_TRUE = zero or more pixels passed.
699 */
700static GLboolean
701stencil_test_pixels( GLcontext *ctx, GLuint face, GLuint n,
702                     const GLint x[], const GLint y[], GLubyte mask[] )
703{
704   const struct gl_framebuffer *fb = ctx->DrawBuffer;
705   struct gl_renderbuffer *rb = fb->_StencilBuffer;
706   GLubyte fail[MAX_WIDTH];
707   GLstencil r, s;
708   GLuint i;
709   GLboolean allfail = GL_FALSE;
710   const GLuint valueMask = ctx->Stencil.ValueMask[face];
711   const GLstencil *stencilStart = (GLstencil *) rb->Data;
712   const GLuint stride = rb->Width;
713
714   ASSERT(rb->GetPointer(ctx, rb, 0, 0));
715   ASSERT(sizeof(GLstencil) == 1);
716
717   /*
718    * Perform stencil test.  The results of this operation are stored
719    * in the fail[] array:
720    *   IF fail[i] is non-zero THEN
721    *       the stencil fail operator is to be applied
722    *   ELSE
723    *       the stencil fail operator is not to be applied
724    *   ENDIF
725    */
726
727   switch (ctx->Stencil.Function[face]) {
728      case GL_NEVER:
729         /* always fail */
730         for (i=0;i<n;i++) {
731	    if (mask[i]) {
732	       mask[i] = 0;
733	       fail[i] = 1;
734	    }
735	    else {
736	       fail[i] = 0;
737	    }
738	 }
739	 allfail = GL_TRUE;
740	 break;
741      case GL_LESS:
742	 r = (GLstencil) (ctx->Stencil.Ref[face] & valueMask);
743	 for (i=0;i<n;i++) {
744	    if (mask[i]) {
745               const GLstencil *sptr = STENCIL_ADDRESS(x[i],y[i]);
746	       s = (GLstencil) (*sptr & valueMask);
747	       if (r < s) {
748		  /* passed */
749		  fail[i] = 0;
750	       }
751	       else {
752		  fail[i] = 1;
753		  mask[i] = 0;
754	       }
755	    }
756	    else {
757	       fail[i] = 0;
758	    }
759	 }
760	 break;
761      case GL_LEQUAL:
762	 r = (GLstencil) (ctx->Stencil.Ref[face] & valueMask);
763	 for (i=0;i<n;i++) {
764	    if (mask[i]) {
765               const GLstencil *sptr = STENCIL_ADDRESS(x[i],y[i]);
766	       s = (GLstencil) (*sptr & valueMask);
767	       if (r <= s) {
768		  /* pass */
769		  fail[i] = 0;
770	       }
771	       else {
772		  fail[i] = 1;
773		  mask[i] = 0;
774	       }
775	    }
776	    else {
777	       fail[i] = 0;
778	    }
779	 }
780	 break;
781      case GL_GREATER:
782	 r = (GLstencil) (ctx->Stencil.Ref[face] & valueMask);
783	 for (i=0;i<n;i++) {
784	    if (mask[i]) {
785               const GLstencil *sptr = STENCIL_ADDRESS(x[i],y[i]);
786	       s = (GLstencil) (*sptr & valueMask);
787	       if (r > s) {
788		  /* passed */
789		  fail[i] = 0;
790	       }
791	       else {
792		  fail[i] = 1;
793		  mask[i] = 0;
794	       }
795	    }
796	    else {
797	       fail[i] = 0;
798	    }
799	 }
800	 break;
801      case GL_GEQUAL:
802	 r = (GLstencil) (ctx->Stencil.Ref[face] & valueMask);
803	 for (i=0;i<n;i++) {
804	    if (mask[i]) {
805               const GLstencil *sptr = STENCIL_ADDRESS(x[i],y[i]);
806	       s = (GLstencil) (*sptr & valueMask);
807	       if (r >= s) {
808		  /* passed */
809		  fail[i] = 0;
810	       }
811	       else {
812		  fail[i] = 1;
813		  mask[i] = 0;
814	       }
815	    }
816	    else {
817	       fail[i] = 0;
818	    }
819	 }
820	 break;
821      case GL_EQUAL:
822	 r = (GLstencil) (ctx->Stencil.Ref[face] & valueMask);
823	 for (i=0;i<n;i++) {
824	    if (mask[i]) {
825               const GLstencil *sptr = STENCIL_ADDRESS(x[i],y[i]);
826	       s = (GLstencil) (*sptr & valueMask);
827	       if (r == s) {
828		  /* passed */
829		  fail[i] = 0;
830	       }
831	       else {
832		  fail[i] = 1;
833		  mask[i] = 0;
834	       }
835	    }
836	    else {
837	       fail[i] = 0;
838	    }
839	 }
840	 break;
841      case GL_NOTEQUAL:
842	 r = (GLstencil) (ctx->Stencil.Ref[face] & valueMask);
843	 for (i=0;i<n;i++) {
844	    if (mask[i]) {
845               const GLstencil *sptr = STENCIL_ADDRESS(x[i],y[i]);
846	       s = (GLstencil) (*sptr & valueMask);
847	       if (r != s) {
848		  /* passed */
849		  fail[i] = 0;
850	       }
851	       else {
852		  fail[i] = 1;
853		  mask[i] = 0;
854	       }
855	    }
856	    else {
857	       fail[i] = 0;
858	    }
859	 }
860	 break;
861      case GL_ALWAYS:
862	 /* always pass */
863	 for (i=0;i<n;i++) {
864	    fail[i] = 0;
865	 }
866	 break;
867      default:
868         _mesa_problem(ctx, "Bad stencil func in gl_stencil_pixels");
869         return 0;
870   }
871
872   if (ctx->Stencil.FailFunc[face] != GL_KEEP) {
873      apply_stencil_op_to_pixels( ctx, n, x, y, ctx->Stencil.FailFunc[face],
874                                  face, fail );
875   }
876
877   return !allfail;
878}
879
880
881
882
883/**
884 * Apply stencil and depth testing to an array of pixels.
885 * This is used both for software and hardware stencil buffers.
886 *
887 * The comments in this function are a bit sparse but the code is
888 * almost identical to stencil_and_ztest_span(), which is well
889 * commented.
890 *
891 * Input:  n - number of pixels in the array
892 *         x, y - array of [n] pixel positions
893 *         z - array [n] of z values
894 *         mask - array [n] of flags  (1=test this pixel, 0=skip the pixel)
895 * Output: mask - array [n] of flags (1=stencil and depth test passed)
896 * Return: GL_FALSE - all fragments failed the testing
897 *         GL_TRUE - one or more fragments passed the testing
898 */
899static GLboolean
900stencil_and_ztest_pixels( GLcontext *ctx, SWspan *span, GLuint face )
901{
902   GLubyte passMask[MAX_WIDTH], failMask[MAX_WIDTH], origMask[MAX_WIDTH];
903   struct gl_framebuffer *fb = ctx->DrawBuffer;
904   struct gl_renderbuffer *rb = fb->_StencilBuffer;
905   const GLuint n = span->end;
906   const GLint *x = span->array->x;
907   const GLint *y = span->array->y;
908   GLubyte *mask = span->array->mask;
909
910   ASSERT(span->arrayMask & SPAN_XY);
911   ASSERT(ctx->Stencil.Enabled);
912   ASSERT(n <= MAX_WIDTH);
913
914   if (!rb->GetPointer(ctx, rb, 0, 0)) {
915      /* No direct access */
916      GLstencil stencil[MAX_WIDTH];
917
918      ASSERT(rb->DataType == GL_UNSIGNED_BYTE);
919      _swrast_get_values(ctx, rb, n, x, y, stencil, sizeof(GLubyte));
920
921      _mesa_memcpy(origMask, mask, n * sizeof(GLubyte));
922
923      (void) do_stencil_test(ctx, face, n, stencil, mask);
924
925      if (ctx->Depth.Test == GL_FALSE) {
926         apply_stencil_op(ctx, ctx->Stencil.ZPassFunc[face], face,
927                          n, stencil, mask);
928      }
929      else {
930         GLubyte tmpMask[MAX_WIDTH];
931         _mesa_memcpy(tmpMask, mask, n * sizeof(GLubyte));
932
933         _swrast_depth_test_span(ctx, span);
934
935         compute_pass_fail_masks(n, tmpMask, mask, passMask, failMask);
936
937         if (ctx->Stencil.ZFailFunc[face] != GL_KEEP) {
938            apply_stencil_op(ctx, ctx->Stencil.ZFailFunc[face], face,
939                             n, stencil, failMask);
940         }
941         if (ctx->Stencil.ZPassFunc[face] != GL_KEEP) {
942            apply_stencil_op(ctx, ctx->Stencil.ZPassFunc[face], face,
943                             n, stencil, passMask);
944         }
945      }
946
947      /* Write updated stencil values into hardware stencil buffer */
948      rb->PutValues(ctx, rb, n, x, y, stencil, origMask);
949
950      return GL_TRUE;
951   }
952   else {
953      /* Direct access to stencil buffer */
954
955      if (stencil_test_pixels(ctx, face, n, x, y, mask) == GL_FALSE) {
956         /* all fragments failed the stencil test, we're done. */
957         return GL_FALSE;
958      }
959
960      if (ctx->Depth.Test==GL_FALSE) {
961         apply_stencil_op_to_pixels(ctx, n, x, y,
962                                    ctx->Stencil.ZPassFunc[face], face, mask);
963      }
964      else {
965         _mesa_memcpy(origMask, mask, n * sizeof(GLubyte));
966
967         _swrast_depth_test_span(ctx, span);
968
969         compute_pass_fail_masks(n, origMask, mask, passMask, failMask);
970
971         if (ctx->Stencil.ZFailFunc[face] != GL_KEEP) {
972            apply_stencil_op_to_pixels(ctx, n, x, y,
973                                       ctx->Stencil.ZFailFunc[face],
974                                       face, failMask);
975         }
976         if (ctx->Stencil.ZPassFunc[face] != GL_KEEP) {
977            apply_stencil_op_to_pixels(ctx, n, x, y,
978                                       ctx->Stencil.ZPassFunc[face],
979                                       face, passMask);
980         }
981      }
982
983      return GL_TRUE;  /* one or more fragments passed both tests */
984   }
985}
986
987
988/**
989 * /return GL_TRUE = one or more fragments passed,
990 * GL_FALSE = all fragments failed.
991 */
992GLboolean
993_swrast_stencil_and_ztest_span(GLcontext *ctx, SWspan *span)
994{
995   const GLuint face = (span->facing == 0) ? 0 : ctx->Stencil._BackFace;
996
997   if (span->arrayMask & SPAN_XY)
998      return stencil_and_ztest_pixels(ctx, span, face);
999   else
1000      return stencil_and_ztest_span(ctx, span, face);
1001}
1002
1003
1004#if 0
1005GLuint
1006clip_span(GLuint bufferWidth, GLuint bufferHeight,
1007          GLint x, GLint y, GLuint *count)
1008{
1009   GLuint n = *count;
1010   GLuint skipPixels = 0;
1011
1012   if (y < 0 || y >= bufferHeight || x + n <= 0 || x >= bufferWidth) {
1013      /* totally out of bounds */
1014      n = 0;
1015   }
1016   else {
1017      /* left clip */
1018      if (x < 0) {
1019         skipPixels = -x;
1020         x = 0;
1021         n -= skipPixels;
1022      }
1023      /* right clip */
1024      if (x + n > bufferWidth) {
1025         GLint dx = x + n - bufferWidth;
1026         n -= dx;
1027      }
1028   }
1029
1030   *count = n;
1031
1032   return skipPixels;
1033}
1034#endif
1035
1036
1037/**
1038 * Return a span of stencil values from the stencil buffer.
1039 * Used for glRead/CopyPixels
1040 * Input:  n - how many pixels
1041 *         x,y - location of first pixel
1042 * Output:  stencil - the array of stencil values
1043 */
1044void
1045_swrast_read_stencil_span(GLcontext *ctx, struct gl_renderbuffer *rb,
1046                          GLint n, GLint x, GLint y, GLstencil stencil[])
1047{
1048   if (y < 0 || y >= (GLint) rb->Height ||
1049       x + n <= 0 || x >= (GLint) rb->Width) {
1050      /* span is completely outside framebuffer */
1051      return; /* undefined values OK */
1052   }
1053
1054   if (x < 0) {
1055      GLint dx = -x;
1056      x = 0;
1057      n -= dx;
1058      stencil += dx;
1059   }
1060   if (x + n > (GLint) rb->Width) {
1061      GLint dx = x + n - rb->Width;
1062      n -= dx;
1063   }
1064   if (n <= 0) {
1065      return;
1066   }
1067
1068   rb->GetRow(ctx, rb, n, x, y, stencil);
1069}
1070
1071
1072
1073/**
1074 * Write a span of stencil values to the stencil buffer.  This function
1075 * applies the stencil write mask when needed.
1076 * Used for glDraw/CopyPixels
1077 * Input:  n - how many pixels
1078 *         x, y - location of first pixel
1079 *         stencil - the array of stencil values
1080 */
1081void
1082_swrast_write_stencil_span(GLcontext *ctx, GLint n, GLint x, GLint y,
1083                           const GLstencil stencil[] )
1084{
1085   struct gl_framebuffer *fb = ctx->DrawBuffer;
1086   struct gl_renderbuffer *rb = fb->_StencilBuffer;
1087   const GLuint stencilMax = (1 << fb->Visual.stencilBits) - 1;
1088   const GLuint stencilMask = ctx->Stencil.WriteMask[0];
1089
1090   if (y < 0 || y >= (GLint) rb->Height ||
1091       x + n <= 0 || x >= (GLint) rb->Width) {
1092      /* span is completely outside framebuffer */
1093      return; /* undefined values OK */
1094   }
1095   if (x < 0) {
1096      GLint dx = -x;
1097      x = 0;
1098      n -= dx;
1099      stencil += dx;
1100   }
1101   if (x + n > (GLint) rb->Width) {
1102      GLint dx = x + n - rb->Width;
1103      n -= dx;
1104   }
1105   if (n <= 0) {
1106      return;
1107   }
1108
1109   if ((stencilMask & stencilMax) != stencilMax) {
1110      /* need to apply writemask */
1111      GLstencil destVals[MAX_WIDTH], newVals[MAX_WIDTH];
1112      GLint i;
1113      rb->GetRow(ctx, rb, n, x, y, destVals);
1114      for (i = 0; i < n; i++) {
1115         newVals[i]
1116            = (stencil[i] & stencilMask) | (destVals[i] & ~stencilMask);
1117      }
1118      rb->PutRow(ctx, rb, n, x, y, newVals, NULL);
1119   }
1120   else {
1121      rb->PutRow(ctx, rb, n, x, y, stencil, NULL);
1122   }
1123}
1124
1125
1126
1127/**
1128 * Clear the stencil buffer.
1129 */
1130void
1131_swrast_clear_stencil_buffer( GLcontext *ctx, struct gl_renderbuffer *rb )
1132{
1133   const GLubyte stencilBits = ctx->DrawBuffer->Visual.stencilBits;
1134   const GLuint mask = ctx->Stencil.WriteMask[0];
1135   const GLuint invMask = ~mask;
1136   const GLuint clearVal = (ctx->Stencil.Clear & mask);
1137   const GLuint stencilMax = (1 << stencilBits) - 1;
1138   GLint x, y, width, height;
1139
1140   if (!rb || mask == 0)
1141      return;
1142
1143   ASSERT(rb->DataType == GL_UNSIGNED_BYTE ||
1144          rb->DataType == GL_UNSIGNED_SHORT);
1145
1146   ASSERT(rb->_BaseFormat == GL_STENCIL_INDEX);
1147
1148   /* compute region to clear */
1149   x = ctx->DrawBuffer->_Xmin;
1150   y = ctx->DrawBuffer->_Ymin;
1151   width  = ctx->DrawBuffer->_Xmax - ctx->DrawBuffer->_Xmin;
1152   height = ctx->DrawBuffer->_Ymax - ctx->DrawBuffer->_Ymin;
1153
1154   if (rb->GetPointer(ctx, rb, 0, 0)) {
1155      /* Direct buffer access */
1156      if ((mask & stencilMax) != stencilMax) {
1157         /* need to mask the clear */
1158         if (rb->DataType == GL_UNSIGNED_BYTE) {
1159            GLint i, j;
1160            for (i = 0; i < height; i++) {
1161               GLubyte *stencil = (GLubyte*) rb->GetPointer(ctx, rb, x, y + i);
1162               for (j = 0; j < width; j++) {
1163                  stencil[j] = (stencil[j] & invMask) | clearVal;
1164               }
1165            }
1166         }
1167         else {
1168            GLint i, j;
1169            for (i = 0; i < height; i++) {
1170               GLushort *stencil = (GLushort*) rb->GetPointer(ctx, rb, x, y + i);
1171               for (j = 0; j < width; j++) {
1172                  stencil[j] = (stencil[j] & invMask) | clearVal;
1173               }
1174            }
1175         }
1176      }
1177      else {
1178         /* no bit masking */
1179         if (width == (GLint) rb->Width && rb->DataType == GL_UNSIGNED_BYTE) {
1180            /* optimized case */
1181            /* Note: bottom-to-top raster assumed! */
1182            GLubyte *stencil = (GLubyte *) rb->GetPointer(ctx, rb, x, y);
1183            GLuint len = width * height * sizeof(GLubyte);
1184            _mesa_memset(stencil, clearVal, len);
1185         }
1186         else {
1187            /* general case */
1188            GLint i;
1189            for (i = 0; i < height; i++) {
1190               GLvoid *stencil = rb->GetPointer(ctx, rb, x, y + i);
1191               if (rb->DataType == GL_UNSIGNED_BYTE) {
1192                  _mesa_memset(stencil, clearVal, width);
1193               }
1194               else {
1195                  _mesa_memset16((short unsigned int*) stencil, clearVal, width);
1196               }
1197            }
1198         }
1199      }
1200   }
1201   else {
1202      /* no direct access */
1203      if ((mask & stencilMax) != stencilMax) {
1204         /* need to mask the clear */
1205         if (rb->DataType == GL_UNSIGNED_BYTE) {
1206            GLint i, j;
1207            for (i = 0; i < height; i++) {
1208               GLubyte stencil[MAX_WIDTH];
1209               rb->GetRow(ctx, rb, width, x, y + i, stencil);
1210               for (j = 0; j < width; j++) {
1211                  stencil[j] = (stencil[j] & invMask) | clearVal;
1212               }
1213               rb->PutRow(ctx, rb, width, x, y + i, stencil, NULL);
1214            }
1215         }
1216         else {
1217            GLint i, j;
1218            for (i = 0; i < height; i++) {
1219               GLushort stencil[MAX_WIDTH];
1220               rb->GetRow(ctx, rb, width, x, y + i, stencil);
1221               for (j = 0; j < width; j++) {
1222                  stencil[j] = (stencil[j] & invMask) | clearVal;
1223               }
1224               rb->PutRow(ctx, rb, width, x, y + i, stencil, NULL);
1225            }
1226         }
1227      }
1228      else {
1229         /* no bit masking */
1230         const GLubyte clear8 = (GLubyte) clearVal;
1231         const GLushort clear16 = (GLushort) clearVal;
1232         const void *clear;
1233         GLint i;
1234         if (rb->DataType == GL_UNSIGNED_BYTE) {
1235            clear = &clear8;
1236         }
1237         else {
1238            clear = &clear16;
1239         }
1240         for (i = 0; i < height; i++) {
1241            rb->PutMonoRow(ctx, rb, width, x, y + i, clear, NULL);
1242         }
1243      }
1244   }
1245}
1246