s_stencil.c revision 7117f1b4
1/*
2 * Mesa 3-D graphics library
3 * Version:  6.5
4 *
5 * Copyright (C) 1999-2005  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 "glheader.h"
27#include "context.h"
28#include "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   GLstencil r, s;
235   const GLuint valueMask = ctx->Stencil.ValueMask[face];
236
237   ASSERT(n <= MAX_WIDTH);
238
239   /*
240    * Perform stencil test.  The results of this operation are stored
241    * in the fail[] array:
242    *   IF fail[i] is non-zero THEN
243    *       the stencil fail operator is to be applied
244    *   ELSE
245    *       the stencil fail operator is not to be applied
246    *   ENDIF
247    */
248   switch (ctx->Stencil.Function[face]) {
249      case GL_NEVER:
250         /* never pass; always fail */
251         for (i=0;i<n;i++) {
252	    if (mask[i]) {
253	       mask[i] = 0;
254	       fail[i] = 1;
255	    }
256	    else {
257	       fail[i] = 0;
258	    }
259	 }
260	 allfail = GL_TRUE;
261	 break;
262      case GL_LESS:
263	 r = (GLstencil) (ctx->Stencil.Ref[face] & valueMask);
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	 r = (GLstencil) (ctx->Stencil.Ref[face] & valueMask);
283	 for (i=0;i<n;i++) {
284	    if (mask[i]) {
285	       s = (GLstencil) (stencil[i] & valueMask);
286	       if (r <= s) {
287		  /* pass */
288		  fail[i] = 0;
289	       }
290	       else {
291		  fail[i] = 1;
292		  mask[i] = 0;
293	       }
294	    }
295	    else {
296	       fail[i] = 0;
297	    }
298	 }
299	 break;
300      case GL_GREATER:
301	 r = (GLstencil) (ctx->Stencil.Ref[face] & valueMask);
302	 for (i=0;i<n;i++) {
303	    if (mask[i]) {
304	       s = (GLstencil) (stencil[i] & valueMask);
305	       if (r > s) {
306		  /* passed */
307		  fail[i] = 0;
308	       }
309	       else {
310		  fail[i] = 1;
311		  mask[i] = 0;
312	       }
313	    }
314	    else {
315	       fail[i] = 0;
316	    }
317	 }
318	 break;
319      case GL_GEQUAL:
320	 r = (GLstencil) (ctx->Stencil.Ref[face] & valueMask);
321	 for (i=0;i<n;i++) {
322	    if (mask[i]) {
323	       s = (GLstencil) (stencil[i] & valueMask);
324	       if (r >= s) {
325		  /* passed */
326		  fail[i] = 0;
327	       }
328	       else {
329		  fail[i] = 1;
330		  mask[i] = 0;
331	       }
332	    }
333	    else {
334	       fail[i] = 0;
335	    }
336	 }
337	 break;
338      case GL_EQUAL:
339	 r = (GLstencil) (ctx->Stencil.Ref[face] & valueMask);
340	 for (i=0;i<n;i++) {
341	    if (mask[i]) {
342	       s = (GLstencil) (stencil[i] & valueMask);
343	       if (r == s) {
344		  /* passed */
345		  fail[i] = 0;
346	       }
347	       else {
348		  fail[i] = 1;
349		  mask[i] = 0;
350	       }
351	    }
352	    else {
353	       fail[i] = 0;
354	    }
355	 }
356	 break;
357      case GL_NOTEQUAL:
358	 r = (GLstencil) (ctx->Stencil.Ref[face] & valueMask);
359	 for (i=0;i<n;i++) {
360	    if (mask[i]) {
361	       s = (GLstencil) (stencil[i] & valueMask);
362	       if (r != s) {
363		  /* passed */
364		  fail[i] = 0;
365	       }
366	       else {
367		  fail[i] = 1;
368		  mask[i] = 0;
369	       }
370	    }
371	    else {
372	       fail[i] = 0;
373	    }
374	 }
375	 break;
376      case GL_ALWAYS:
377	 /* always pass */
378	 for (i=0;i<n;i++) {
379	    fail[i] = 0;
380	 }
381	 break;
382      default:
383         _mesa_problem(ctx, "Bad stencil func in gl_stencil_span");
384         return 0;
385   }
386
387   if (ctx->Stencil.FailFunc[face] != GL_KEEP) {
388      apply_stencil_op( ctx, ctx->Stencil.FailFunc[face], face, n, stencil, fail );
389   }
390
391   return !allfail;
392}
393
394
395
396/**
397 * Apply stencil and depth testing to the span of pixels.
398 * Both software and hardware stencil buffers are acceptable.
399 * Input:  n - number of pixels in the span
400 *         x, y - location of leftmost pixel in span
401 *         z - array [n] of z values
402 *         mask - array [n] of flags  (1=test this pixel, 0=skip the pixel)
403 * Output:  mask - array [n] of flags (1=stencil and depth test passed)
404 * Return: GL_FALSE - all fragments failed the testing
405 *         GL_TRUE - one or more fragments passed the testing
406 *
407 */
408static GLboolean
409stencil_and_ztest_span(GLcontext *ctx, SWspan *span, GLuint face)
410{
411   struct gl_framebuffer *fb = ctx->DrawBuffer;
412   struct gl_renderbuffer *rb = fb->_StencilBuffer;
413   GLstencil stencilRow[MAX_WIDTH];
414   GLstencil *stencil;
415   const GLuint n = span->end;
416   const GLint x = span->x;
417   const GLint y = span->y;
418   GLubyte *mask = span->array->mask;
419
420   ASSERT((span->arrayMask & SPAN_XY) == 0);
421   ASSERT(ctx->Stencil.Enabled);
422   ASSERT(n <= MAX_WIDTH);
423#ifdef DEBUG
424   if (ctx->Depth.Test) {
425      ASSERT(span->arrayMask & SPAN_Z);
426   }
427#endif
428
429   stencil = (GLstencil *) rb->GetPointer(ctx, rb, x, y);
430   if (!stencil) {
431      rb->GetRow(ctx, rb, n, x, y, stencilRow);
432      stencil = stencilRow;
433   }
434
435   /*
436    * Apply the stencil test to the fragments.
437    * failMask[i] is 1 if the stencil test failed.
438    */
439   if (do_stencil_test( ctx, face, n, stencil, mask ) == GL_FALSE) {
440      /* all fragments failed the stencil test, we're done. */
441      span->writeAll = GL_FALSE;
442      if (!rb->GetPointer(ctx, rb, 0, 0)) {
443         /* put updated stencil values into buffer */
444         rb->PutRow(ctx, rb, n, x, y, stencil, NULL);
445      }
446      return GL_FALSE;
447   }
448
449   /*
450    * Some fragments passed the stencil test, apply depth test to them
451    * and apply Zpass and Zfail stencil ops.
452    */
453   if (ctx->Depth.Test == GL_FALSE) {
454      /*
455       * No depth buffer, just apply zpass stencil function to active pixels.
456       */
457      apply_stencil_op( ctx, ctx->Stencil.ZPassFunc[face], face, n, stencil, mask );
458   }
459   else {
460      /*
461       * Perform depth buffering, then apply zpass or zfail stencil function.
462       */
463      GLubyte passmask[MAX_WIDTH], failmask[MAX_WIDTH], oldmask[MAX_WIDTH];
464      GLuint i;
465
466      /* save the current mask bits */
467      _mesa_memcpy(oldmask, mask, n * sizeof(GLubyte));
468
469      /* apply the depth test */
470      _swrast_depth_test_span(ctx, span);
471
472      /* Set the stencil pass/fail flags according to result of depth testing.
473       * if oldmask[i] == 0 then
474       *    Don't touch the stencil value
475       * else if oldmask[i] and newmask[i] then
476       *    Depth test passed
477       * else
478       *    assert(oldmask[i] && !newmask[i])
479       *    Depth test failed
480       * endif
481       */
482      for (i=0;i<n;i++) {
483         ASSERT(mask[i] == 0 || mask[i] == 1);
484         passmask[i] = oldmask[i] & mask[i];
485         failmask[i] = oldmask[i] & (mask[i] ^ 1);
486      }
487
488      /* apply the pass and fail operations */
489      if (ctx->Stencil.ZFailFunc[face] != GL_KEEP) {
490         apply_stencil_op( ctx, ctx->Stencil.ZFailFunc[face], face,
491                           n, stencil, failmask );
492      }
493      if (ctx->Stencil.ZPassFunc[face] != GL_KEEP) {
494         apply_stencil_op( ctx, ctx->Stencil.ZPassFunc[face], face,
495                           n, stencil, passmask );
496      }
497   }
498
499   /*
500    * Write updated stencil values back into hardware stencil buffer.
501    */
502   if (!rb->GetPointer(ctx, rb, 0, 0)) {
503      rb->PutRow(ctx, rb, n, x, y, stencil, NULL);
504   }
505
506   span->writeAll = GL_FALSE;
507
508   return GL_TRUE;  /* one or more fragments passed both tests */
509}
510
511
512
513/*
514 * Return the address of a stencil buffer value given the window coords:
515 */
516#define STENCIL_ADDRESS(X, Y)  (stencilStart + (Y) * stride + (X))
517
518
519
520/**
521 * Apply the given stencil operator for each pixel in the array whose
522 * mask flag is set.
523 * \note  This is for software stencil buffers only.
524 * Input:  n - number of pixels in the span
525 *         x, y - array of [n] pixels
526 *         operator - the stencil buffer operator
527 *         mask - array [n] of flag:  1=apply operator, 0=don't apply operator
528 */
529static void
530apply_stencil_op_to_pixels( GLcontext *ctx,
531                            GLuint n, const GLint x[], const GLint y[],
532                            GLenum oper, GLuint face, const GLubyte mask[] )
533{
534   struct gl_framebuffer *fb = ctx->DrawBuffer;
535   struct gl_renderbuffer *rb = fb->_StencilBuffer;
536   const GLstencil stencilMax = (1 << fb->Visual.stencilBits) - 1;
537   const GLstencil ref = ctx->Stencil.Ref[face];
538   const GLstencil wrtmask = ctx->Stencil.WriteMask[face];
539   const GLstencil invmask = (GLstencil) (~wrtmask);
540   GLuint i;
541   GLstencil *stencilStart = (GLubyte *) rb->Data;
542   const GLuint stride = rb->Width;
543
544   ASSERT(rb->GetPointer(ctx, rb, 0, 0));
545   ASSERT(sizeof(GLstencil) == 1);
546
547   switch (oper) {
548      case GL_KEEP:
549         /* do nothing */
550         break;
551      case GL_ZERO:
552	 if (invmask==0) {
553	    for (i=0;i<n;i++) {
554	       if (mask[i]) {
555                  GLstencil *sptr = STENCIL_ADDRESS( x[i], y[i] );
556                  *sptr = 0;
557	       }
558	    }
559	 }
560	 else {
561	    for (i=0;i<n;i++) {
562	       if (mask[i]) {
563                  GLstencil *sptr = STENCIL_ADDRESS( x[i], y[i] );
564		  *sptr = (GLstencil) (invmask & *sptr);
565	       }
566	    }
567	 }
568	 break;
569      case GL_REPLACE:
570	 if (invmask==0) {
571	    for (i=0;i<n;i++) {
572	       if (mask[i]) {
573                  GLstencil *sptr = STENCIL_ADDRESS( x[i], y[i] );
574                  *sptr = ref;
575	       }
576	    }
577	 }
578	 else {
579	    for (i=0;i<n;i++) {
580	       if (mask[i]) {
581                  GLstencil *sptr = STENCIL_ADDRESS( x[i], y[i] );
582		  *sptr = (GLstencil) ((invmask & *sptr ) | (wrtmask & ref));
583	       }
584	    }
585	 }
586	 break;
587      case GL_INCR:
588	 if (invmask==0) {
589	    for (i=0;i<n;i++) {
590	       if (mask[i]) {
591                  GLstencil *sptr = STENCIL_ADDRESS( x[i], y[i] );
592		  if (*sptr < stencilMax) {
593		     *sptr = (GLstencil) (*sptr + 1);
594		  }
595	       }
596	    }
597	 }
598	 else {
599	    for (i=0;i<n;i++) {
600	       if (mask[i]) {
601                  GLstencil *sptr = STENCIL_ADDRESS( x[i], y[i] );
602		  if (*sptr < stencilMax) {
603		     *sptr = (GLstencil) ((invmask & *sptr) | (wrtmask & (*sptr+1)));
604		  }
605	       }
606	    }
607	 }
608	 break;
609      case GL_DECR:
610	 if (invmask==0) {
611	    for (i=0;i<n;i++) {
612	       if (mask[i]) {
613                  GLstencil *sptr = STENCIL_ADDRESS( x[i], y[i] );
614		  if (*sptr>0) {
615		     *sptr = (GLstencil) (*sptr - 1);
616		  }
617	       }
618	    }
619	 }
620	 else {
621	    for (i=0;i<n;i++) {
622	       if (mask[i]) {
623                  GLstencil *sptr = STENCIL_ADDRESS( x[i], y[i] );
624		  if (*sptr>0) {
625		     *sptr = (GLstencil) ((invmask & *sptr) | (wrtmask & (*sptr-1)));
626		  }
627	       }
628	    }
629	 }
630	 break;
631      case GL_INCR_WRAP_EXT:
632	 if (invmask==0) {
633	    for (i=0;i<n;i++) {
634	       if (mask[i]) {
635                  GLstencil *sptr = STENCIL_ADDRESS( x[i], y[i] );
636                  *sptr = (GLstencil) (*sptr + 1);
637	       }
638	    }
639	 }
640	 else {
641	    for (i=0;i<n;i++) {
642	       if (mask[i]) {
643                  GLstencil *sptr = STENCIL_ADDRESS( x[i], y[i] );
644                  *sptr = (GLstencil) ((invmask & *sptr) | (wrtmask & (*sptr+1)));
645	       }
646	    }
647	 }
648	 break;
649      case GL_DECR_WRAP_EXT:
650	 if (invmask==0) {
651	    for (i=0;i<n;i++) {
652	       if (mask[i]) {
653                  GLstencil *sptr = STENCIL_ADDRESS( x[i], y[i] );
654                  *sptr = (GLstencil) (*sptr - 1);
655	       }
656	    }
657	 }
658	 else {
659	    for (i=0;i<n;i++) {
660	       if (mask[i]) {
661                  GLstencil *sptr = STENCIL_ADDRESS( x[i], y[i] );
662                  *sptr = (GLstencil) ((invmask & *sptr) | (wrtmask & (*sptr-1)));
663	       }
664	    }
665	 }
666	 break;
667      case GL_INVERT:
668	 if (invmask==0) {
669	    for (i=0;i<n;i++) {
670	       if (mask[i]) {
671                  GLstencil *sptr = STENCIL_ADDRESS( x[i], y[i] );
672                  *sptr = (GLstencil) (~*sptr);
673	       }
674	    }
675	 }
676	 else {
677	    for (i=0;i<n;i++) {
678	       if (mask[i]) {
679                  GLstencil *sptr = STENCIL_ADDRESS( x[i], y[i] );
680                  *sptr = (GLstencil) ((invmask & *sptr) | (wrtmask & ~*sptr));
681	       }
682	    }
683	 }
684	 break;
685      default:
686         _mesa_problem(ctx, "Bad stencilop in apply_stencil_op_to_pixels");
687   }
688}
689
690
691
692/**
693 * Apply stencil test to an array of pixels before depth buffering.
694 *
695 * \note Used for software stencil buffer only.
696 * Input:  n - number of pixels in the span
697 *         x, y - array of [n] pixels to stencil
698 *         mask - array [n] of flag:  0=skip the pixel, 1=stencil the pixel
699 * Output:  mask - pixels which fail the stencil test will have their
700 *                 mask flag set to 0.
701 * \return  GL_FALSE = all pixels failed, GL_TRUE = zero or more pixels passed.
702 */
703static GLboolean
704stencil_test_pixels( GLcontext *ctx, GLuint face, GLuint n,
705                     const GLint x[], const GLint y[], GLubyte mask[] )
706{
707   const struct gl_framebuffer *fb = ctx->DrawBuffer;
708   struct gl_renderbuffer *rb = fb->_StencilBuffer;
709   GLubyte fail[MAX_WIDTH];
710   GLstencil r, s;
711   GLuint i;
712   GLboolean allfail = GL_FALSE;
713   const GLuint valueMask = ctx->Stencil.ValueMask[face];
714   const GLstencil *stencilStart = (GLstencil *) rb->Data;
715   const GLuint stride = rb->Width;
716
717   ASSERT(rb->GetPointer(ctx, rb, 0, 0));
718   ASSERT(sizeof(GLstencil) == 1);
719
720   /*
721    * Perform stencil test.  The results of this operation are stored
722    * in the fail[] array:
723    *   IF fail[i] is non-zero THEN
724    *       the stencil fail operator is to be applied
725    *   ELSE
726    *       the stencil fail operator is not to be applied
727    *   ENDIF
728    */
729
730   switch (ctx->Stencil.Function[face]) {
731      case GL_NEVER:
732         /* always fail */
733         for (i=0;i<n;i++) {
734	    if (mask[i]) {
735	       mask[i] = 0;
736	       fail[i] = 1;
737	    }
738	    else {
739	       fail[i] = 0;
740	    }
741	 }
742	 allfail = GL_TRUE;
743	 break;
744      case GL_LESS:
745	 r = (GLstencil) (ctx->Stencil.Ref[face] & valueMask);
746	 for (i=0;i<n;i++) {
747	    if (mask[i]) {
748               const GLstencil *sptr = STENCIL_ADDRESS(x[i],y[i]);
749	       s = (GLstencil) (*sptr & valueMask);
750	       if (r < s) {
751		  /* passed */
752		  fail[i] = 0;
753	       }
754	       else {
755		  fail[i] = 1;
756		  mask[i] = 0;
757	       }
758	    }
759	    else {
760	       fail[i] = 0;
761	    }
762	 }
763	 break;
764      case GL_LEQUAL:
765	 r = (GLstencil) (ctx->Stencil.Ref[face] & valueMask);
766	 for (i=0;i<n;i++) {
767	    if (mask[i]) {
768               const GLstencil *sptr = STENCIL_ADDRESS(x[i],y[i]);
769	       s = (GLstencil) (*sptr & valueMask);
770	       if (r <= s) {
771		  /* pass */
772		  fail[i] = 0;
773	       }
774	       else {
775		  fail[i] = 1;
776		  mask[i] = 0;
777	       }
778	    }
779	    else {
780	       fail[i] = 0;
781	    }
782	 }
783	 break;
784      case GL_GREATER:
785	 r = (GLstencil) (ctx->Stencil.Ref[face] & valueMask);
786	 for (i=0;i<n;i++) {
787	    if (mask[i]) {
788               const GLstencil *sptr = STENCIL_ADDRESS(x[i],y[i]);
789	       s = (GLstencil) (*sptr & valueMask);
790	       if (r > s) {
791		  /* passed */
792		  fail[i] = 0;
793	       }
794	       else {
795		  fail[i] = 1;
796		  mask[i] = 0;
797	       }
798	    }
799	    else {
800	       fail[i] = 0;
801	    }
802	 }
803	 break;
804      case GL_GEQUAL:
805	 r = (GLstencil) (ctx->Stencil.Ref[face] & valueMask);
806	 for (i=0;i<n;i++) {
807	    if (mask[i]) {
808               const GLstencil *sptr = STENCIL_ADDRESS(x[i],y[i]);
809	       s = (GLstencil) (*sptr & valueMask);
810	       if (r >= s) {
811		  /* passed */
812		  fail[i] = 0;
813	       }
814	       else {
815		  fail[i] = 1;
816		  mask[i] = 0;
817	       }
818	    }
819	    else {
820	       fail[i] = 0;
821	    }
822	 }
823	 break;
824      case GL_EQUAL:
825	 r = (GLstencil) (ctx->Stencil.Ref[face] & valueMask);
826	 for (i=0;i<n;i++) {
827	    if (mask[i]) {
828               const GLstencil *sptr = STENCIL_ADDRESS(x[i],y[i]);
829	       s = (GLstencil) (*sptr & valueMask);
830	       if (r == s) {
831		  /* passed */
832		  fail[i] = 0;
833	       }
834	       else {
835		  fail[i] = 1;
836		  mask[i] = 0;
837	       }
838	    }
839	    else {
840	       fail[i] = 0;
841	    }
842	 }
843	 break;
844      case GL_NOTEQUAL:
845	 r = (GLstencil) (ctx->Stencil.Ref[face] & valueMask);
846	 for (i=0;i<n;i++) {
847	    if (mask[i]) {
848               const GLstencil *sptr = STENCIL_ADDRESS(x[i],y[i]);
849	       s = (GLstencil) (*sptr & valueMask);
850	       if (r != s) {
851		  /* passed */
852		  fail[i] = 0;
853	       }
854	       else {
855		  fail[i] = 1;
856		  mask[i] = 0;
857	       }
858	    }
859	    else {
860	       fail[i] = 0;
861	    }
862	 }
863	 break;
864      case GL_ALWAYS:
865	 /* always pass */
866	 for (i=0;i<n;i++) {
867	    fail[i] = 0;
868	 }
869	 break;
870      default:
871         _mesa_problem(ctx, "Bad stencil func in gl_stencil_pixels");
872         return 0;
873   }
874
875   if (ctx->Stencil.FailFunc[face] != GL_KEEP) {
876      apply_stencil_op_to_pixels( ctx, n, x, y, ctx->Stencil.FailFunc[face],
877                                  face, fail );
878   }
879
880   return !allfail;
881}
882
883
884
885
886/**
887 * Apply stencil and depth testing to an array of pixels.
888 * This is used both for software and hardware stencil buffers.
889 *
890 * The comments in this function are a bit sparse but the code is
891 * almost identical to stencil_and_ztest_span(), which is well
892 * commented.
893 *
894 * Input:  n - number of pixels in the array
895 *         x, y - array of [n] pixel positions
896 *         z - array [n] of z values
897 *         mask - array [n] of flags  (1=test this pixel, 0=skip the pixel)
898 * Output: mask - array [n] of flags (1=stencil and depth test passed)
899 * Return: GL_FALSE - all fragments failed the testing
900 *         GL_TRUE - one or more fragments passed the testing
901 */
902static GLboolean
903stencil_and_ztest_pixels( GLcontext *ctx, SWspan *span, GLuint face )
904{
905   struct gl_framebuffer *fb = ctx->DrawBuffer;
906   struct gl_renderbuffer *rb = fb->_StencilBuffer;
907   const GLuint n = span->end;
908   const GLint *x = span->array->x;
909   const GLint *y = span->array->y;
910   GLubyte *mask = span->array->mask;
911
912   ASSERT(span->arrayMask & SPAN_XY);
913   ASSERT(ctx->Stencil.Enabled);
914   ASSERT(n <= MAX_WIDTH);
915
916   if (!rb->GetPointer(ctx, rb, 0, 0)) {
917      /* No direct access */
918      GLstencil stencil[MAX_WIDTH];
919      GLubyte origMask[MAX_WIDTH];
920
921      ASSERT(rb->DataType == GL_UNSIGNED_BYTE);
922      _swrast_get_values(ctx, rb, n, x, y, stencil, sizeof(GLubyte));
923
924      _mesa_memcpy(origMask, mask, n * sizeof(GLubyte));
925
926      (void) do_stencil_test(ctx, face, n, stencil, mask);
927
928      if (ctx->Depth.Test == GL_FALSE) {
929         apply_stencil_op(ctx, ctx->Stencil.ZPassFunc[face], face,
930                          n, stencil, mask);
931      }
932      else {
933         _swrast_depth_test_span(ctx, span);
934
935         if (ctx->Stencil.ZFailFunc[face] != GL_KEEP) {
936            GLubyte failmask[MAX_WIDTH];
937            GLuint i;
938            for (i = 0; i < n; i++) {
939               ASSERT(mask[i] == 0 || mask[i] == 1);
940               failmask[i] = origMask[i] & (mask[i] ^ 1);
941            }
942            apply_stencil_op(ctx, ctx->Stencil.ZFailFunc[face], face,
943                             n, stencil, failmask);
944         }
945         if (ctx->Stencil.ZPassFunc[face] != GL_KEEP) {
946            GLubyte passmask[MAX_WIDTH];
947            GLuint i;
948            for (i = 0; i < n; i++) {
949               ASSERT(mask[i] == 0 || mask[i] == 1);
950               passmask[i] = origMask[i] & mask[i];
951            }
952            apply_stencil_op(ctx, ctx->Stencil.ZPassFunc[face], face,
953                             n, stencil, passmask);
954         }
955      }
956
957      /* Write updated stencil values into hardware stencil buffer */
958      rb->PutValues(ctx, rb, n, x, y, stencil, origMask);
959
960      return GL_TRUE;
961   }
962   else {
963      /* Direct access to stencil buffer */
964
965      if (stencil_test_pixels(ctx, face, n, x, y, mask) == GL_FALSE) {
966         /* all fragments failed the stencil test, we're done. */
967         return GL_FALSE;
968      }
969
970      if (ctx->Depth.Test==GL_FALSE) {
971         apply_stencil_op_to_pixels(ctx, n, x, y,
972                                    ctx->Stencil.ZPassFunc[face], face, mask);
973      }
974      else {
975         GLubyte passmask[MAX_WIDTH], failmask[MAX_WIDTH], oldmask[MAX_WIDTH];
976         GLuint i;
977
978         _mesa_memcpy(oldmask, mask, n * sizeof(GLubyte));
979
980         _swrast_depth_test_span(ctx, span);
981
982         for (i=0;i<n;i++) {
983            ASSERT(mask[i] == 0 || mask[i] == 1);
984            passmask[i] = oldmask[i] & mask[i];
985            failmask[i] = oldmask[i] & (mask[i] ^ 1);
986         }
987
988         if (ctx->Stencil.ZFailFunc[face] != GL_KEEP) {
989            apply_stencil_op_to_pixels(ctx, n, x, y,
990                                       ctx->Stencil.ZFailFunc[face],
991                                       face, failmask);
992         }
993         if (ctx->Stencil.ZPassFunc[face] != GL_KEEP) {
994            apply_stencil_op_to_pixels(ctx, n, x, y,
995                                       ctx->Stencil.ZPassFunc[face],
996                                       face, passmask);
997         }
998      }
999
1000      return GL_TRUE;  /* one or more fragments passed both tests */
1001   }
1002}
1003
1004
1005/**
1006 * /return GL_TRUE = one or more fragments passed,
1007 * GL_FALSE = all fragments failed.
1008 */
1009GLboolean
1010_swrast_stencil_and_ztest_span(GLcontext *ctx, SWspan *span)
1011{
1012   if (span->arrayMask & SPAN_XY)
1013      return stencil_and_ztest_pixels(ctx, span, span->facing);
1014   else
1015      return stencil_and_ztest_span(ctx, span, span->facing);
1016}
1017
1018
1019#if 0
1020GLuint
1021clip_span(GLuint bufferWidth, GLuint bufferHeight,
1022          GLint x, GLint y, GLuint *count)
1023{
1024   GLuint n = *count;
1025   GLuint skipPixels = 0;
1026
1027   if (y < 0 || y >= bufferHeight || x + n <= 0 || x >= bufferWidth) {
1028      /* totally out of bounds */
1029      n = 0;
1030   }
1031   else {
1032      /* left clip */
1033      if (x < 0) {
1034         skipPixels = -x;
1035         x = 0;
1036         n -= skipPixels;
1037      }
1038      /* right clip */
1039      if (x + n > bufferWidth) {
1040         GLint dx = x + n - bufferWidth;
1041         n -= dx;
1042      }
1043   }
1044
1045   *count = n;
1046
1047   return skipPixels;
1048}
1049#endif
1050
1051
1052/**
1053 * Return a span of stencil values from the stencil buffer.
1054 * Used for glRead/CopyPixels
1055 * Input:  n - how many pixels
1056 *         x,y - location of first pixel
1057 * Output:  stencil - the array of stencil values
1058 */
1059void
1060_swrast_read_stencil_span(GLcontext *ctx, struct gl_renderbuffer *rb,
1061                          GLint n, GLint x, GLint y, GLstencil stencil[])
1062{
1063   if (y < 0 || y >= (GLint) rb->Height ||
1064       x + n <= 0 || x >= (GLint) rb->Width) {
1065      /* span is completely outside framebuffer */
1066      return; /* undefined values OK */
1067   }
1068
1069   if (x < 0) {
1070      GLint dx = -x;
1071      x = 0;
1072      n -= dx;
1073      stencil += dx;
1074   }
1075   if (x + n > (GLint) rb->Width) {
1076      GLint dx = x + n - rb->Width;
1077      n -= dx;
1078   }
1079   if (n <= 0) {
1080      return;
1081   }
1082
1083   rb->GetRow(ctx, rb, n, x, y, stencil);
1084}
1085
1086
1087
1088/**
1089 * Write a span of stencil values to the stencil buffer.  This function
1090 * applies the stencil write mask when needed.
1091 * Used for glDraw/CopyPixels
1092 * Input:  n - how many pixels
1093 *         x, y - location of first pixel
1094 *         stencil - the array of stencil values
1095 */
1096void
1097_swrast_write_stencil_span(GLcontext *ctx, GLint n, GLint x, GLint y,
1098                           const GLstencil stencil[] )
1099{
1100   struct gl_framebuffer *fb = ctx->DrawBuffer;
1101   struct gl_renderbuffer *rb = fb->_StencilBuffer;
1102   const GLuint stencilMax = (1 << fb->Visual.stencilBits) - 1;
1103   const GLuint stencilMask = ctx->Stencil.WriteMask[0];
1104
1105   if (y < 0 || y >= (GLint) rb->Height ||
1106       x + n <= 0 || x >= (GLint) rb->Width) {
1107      /* span is completely outside framebuffer */
1108      return; /* undefined values OK */
1109   }
1110   if (x < 0) {
1111      GLint dx = -x;
1112      x = 0;
1113      n -= dx;
1114      stencil += dx;
1115   }
1116   if (x + n > (GLint) rb->Width) {
1117      GLint dx = x + n - rb->Width;
1118      n -= dx;
1119   }
1120   if (n <= 0) {
1121      return;
1122   }
1123
1124   if ((stencilMask & stencilMax) != stencilMax) {
1125      /* need to apply writemask */
1126      GLstencil destVals[MAX_WIDTH], newVals[MAX_WIDTH];
1127      GLint i;
1128      rb->GetRow(ctx, rb, n, x, y, destVals);
1129      for (i = 0; i < n; i++) {
1130         newVals[i]
1131            = (stencil[i] & stencilMask) | (destVals[i] & ~stencilMask);
1132      }
1133      rb->PutRow(ctx, rb, n, x, y, newVals, NULL);
1134   }
1135   else {
1136      rb->PutRow(ctx, rb, n, x, y, stencil, NULL);
1137   }
1138}
1139
1140
1141
1142/**
1143 * Clear the stencil buffer.
1144 */
1145void
1146_swrast_clear_stencil_buffer( GLcontext *ctx, struct gl_renderbuffer *rb )
1147{
1148   const GLubyte stencilBits = ctx->DrawBuffer->Visual.stencilBits;
1149   const GLuint mask = ctx->Stencil.WriteMask[0];
1150   const GLuint invMask = ~mask;
1151   const GLuint clearVal = (ctx->Stencil.Clear & mask);
1152   const GLuint stencilMax = (1 << stencilBits) - 1;
1153   GLint x, y, width, height;
1154
1155   if (!rb || mask == 0)
1156      return;
1157
1158   ASSERT(rb->DataType == GL_UNSIGNED_BYTE ||
1159          rb->DataType == GL_UNSIGNED_SHORT);
1160
1161   ASSERT(rb->_BaseFormat == GL_STENCIL_INDEX);
1162
1163   /* compute region to clear */
1164   x = ctx->DrawBuffer->_Xmin;
1165   y = ctx->DrawBuffer->_Ymin;
1166   width  = ctx->DrawBuffer->_Xmax - ctx->DrawBuffer->_Xmin;
1167   height = ctx->DrawBuffer->_Ymax - ctx->DrawBuffer->_Ymin;
1168
1169   if (rb->GetPointer(ctx, rb, 0, 0)) {
1170      /* Direct buffer access */
1171      if ((mask & stencilMax) != stencilMax) {
1172         /* need to mask the clear */
1173         if (rb->DataType == GL_UNSIGNED_BYTE) {
1174            GLint i, j;
1175            for (i = 0; i < height; i++) {
1176               GLubyte *stencil = (GLubyte*) rb->GetPointer(ctx, rb, x, y + i);
1177               for (j = 0; j < width; j++) {
1178                  stencil[j] = (stencil[j] & invMask) | clearVal;
1179               }
1180            }
1181         }
1182         else {
1183            GLint i, j;
1184            for (i = 0; i < height; i++) {
1185               GLushort *stencil = (GLushort*) rb->GetPointer(ctx, rb, x, y + i);
1186               for (j = 0; j < width; j++) {
1187                  stencil[j] = (stencil[j] & invMask) | clearVal;
1188               }
1189            }
1190         }
1191      }
1192      else {
1193         /* no bit masking */
1194         if (width == (GLint) rb->Width && rb->DataType == GL_UNSIGNED_BYTE) {
1195            /* optimized case */
1196            /* Note: bottom-to-top raster assumed! */
1197            GLubyte *stencil = (GLubyte *) rb->GetPointer(ctx, rb, x, y);
1198            GLuint len = width * height * sizeof(GLubyte);
1199            _mesa_memset(stencil, clearVal, len);
1200         }
1201         else {
1202            /* general case */
1203            GLint i;
1204            for (i = 0; i < height; i++) {
1205               GLvoid *stencil = rb->GetPointer(ctx, rb, x, y + i);
1206               if (rb->DataType == GL_UNSIGNED_BYTE) {
1207                  _mesa_memset(stencil, clearVal, width);
1208               }
1209               else {
1210                  _mesa_memset16((short unsigned int*) stencil, clearVal, width);
1211               }
1212            }
1213         }
1214      }
1215   }
1216   else {
1217      /* no direct access */
1218      if ((mask & stencilMax) != stencilMax) {
1219         /* need to mask the clear */
1220         if (rb->DataType == GL_UNSIGNED_BYTE) {
1221            GLint i, j;
1222            for (i = 0; i < height; i++) {
1223               GLubyte stencil[MAX_WIDTH];
1224               rb->GetRow(ctx, rb, width, x, y + i, stencil);
1225               for (j = 0; j < width; j++) {
1226                  stencil[j] = (stencil[j] & invMask) | clearVal;
1227               }
1228               rb->PutRow(ctx, rb, width, x, y + i, stencil, NULL);
1229            }
1230         }
1231         else {
1232            GLint i, j;
1233            for (i = 0; i < height; i++) {
1234               GLushort stencil[MAX_WIDTH];
1235               rb->GetRow(ctx, rb, width, x, y + i, stencil);
1236               for (j = 0; j < width; j++) {
1237                  stencil[j] = (stencil[j] & invMask) | clearVal;
1238               }
1239               rb->PutRow(ctx, rb, width, x, y + i, stencil, NULL);
1240            }
1241         }
1242      }
1243      else {
1244         /* no bit masking */
1245         const GLubyte clear8 = (GLubyte) clearVal;
1246         const GLushort clear16 = (GLushort) clearVal;
1247         const void *clear;
1248         GLint i;
1249         if (rb->DataType == GL_UNSIGNED_BYTE) {
1250            clear = &clear8;
1251         }
1252         else {
1253            clear = &clear16;
1254         }
1255         for (i = 0; i < height; i++) {
1256            rb->PutMonoRow(ctx, rb, width, x, y + i, clear, NULL);
1257         }
1258      }
1259   }
1260}
1261