Tizen 2.0 Release
[profile/ivi/osmesa.git] / src / mesa / swrast / s_stencil.c
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
39 IF stencil test fails THEN
40    Apply fail-op to stencil value
41    Don't write the pixel (RGBA,Z)
42 ELSE
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
48 ENDIF
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  */
63 static void
64 apply_stencil_op( const struct gl_context *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  */
227 static GLboolean
228 do_stencil_test( struct gl_context *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  */
394 static INLINE void
395 compute_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  */
420 static GLboolean
421 stencil_and_ztest_span(struct gl_context *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        ctx->DrawBuffer->_DepthBuffer == NULL) {
467       /*
468        * No depth buffer, just apply zpass stencil function to active pixels.
469        */
470       apply_stencil_op( ctx, ctx->Stencil.ZPassFunc[face], face, n, stencil, mask );
471    }
472    else {
473       /*
474        * Perform depth buffering, then apply zpass or zfail stencil function.
475        */
476       GLubyte passMask[MAX_WIDTH], failMask[MAX_WIDTH], origMask[MAX_WIDTH];
477
478       /* save the current mask bits */
479       memcpy(origMask, mask, n * sizeof(GLubyte));
480
481       /* apply the depth test */
482       _swrast_depth_test_span(ctx, span);
483
484       compute_pass_fail_masks(n, origMask, mask, passMask, failMask);
485
486       /* apply the pass and fail operations */
487       if (ctx->Stencil.ZFailFunc[face] != GL_KEEP) {
488          apply_stencil_op( ctx, ctx->Stencil.ZFailFunc[face], face,
489                            n, stencil, failMask );
490       }
491       if (ctx->Stencil.ZPassFunc[face] != GL_KEEP) {
492          apply_stencil_op( ctx, ctx->Stencil.ZPassFunc[face], face,
493                            n, stencil, passMask );
494       }
495    }
496
497    /*
498     * Write updated stencil values back into hardware stencil buffer.
499     */
500    if (!rb->GetPointer(ctx, rb, 0, 0)) {
501       rb->PutRow(ctx, rb, n, x, y, stencil, NULL);
502    }
503    
504    span->writeAll = GL_FALSE;
505    
506    return GL_TRUE;  /* one or more fragments passed both tests */
507 }
508
509
510
511 /*
512  * Return the address of a stencil buffer value given the window coords:
513  */
514 #define STENCIL_ADDRESS(X, Y)  (stencilStart + (Y) * stride + (X))
515
516
517
518 /**
519  * Apply the given stencil operator for each pixel in the array whose
520  * mask flag is set.
521  * \note  This is for software stencil buffers only.
522  * Input:  n - number of pixels in the span
523  *         x, y - array of [n] pixels
524  *         operator - the stencil buffer operator
525  *         mask - array [n] of flag:  1=apply operator, 0=don't apply operator
526  */
527 static void
528 apply_stencil_op_to_pixels( struct gl_context *ctx,
529                             GLuint n, const GLint x[], const GLint y[],
530                             GLenum oper, GLuint face, const GLubyte mask[] )
531 {
532    struct gl_framebuffer *fb = ctx->DrawBuffer;
533    struct gl_renderbuffer *rb = fb->_StencilBuffer;
534    const GLstencil stencilMax = (1 << fb->Visual.stencilBits) - 1;
535    const GLstencil ref = ctx->Stencil.Ref[face];
536    const GLstencil wrtmask = ctx->Stencil.WriteMask[face];
537    const GLstencil invmask = (GLstencil) (~wrtmask);
538    GLuint i;
539    GLstencil *stencilStart = (GLubyte *) rb->Data;
540    const GLuint stride = rb->Width;
541
542    ASSERT(rb->GetPointer(ctx, rb, 0, 0));
543    ASSERT(sizeof(GLstencil) == 1);
544
545    switch (oper) {
546       case GL_KEEP:
547          /* do nothing */
548          break;
549       case GL_ZERO:
550          if (invmask==0) {
551             for (i=0;i<n;i++) {
552                if (mask[i]) {
553                   GLstencil *sptr = STENCIL_ADDRESS( x[i], y[i] );
554                   *sptr = 0;
555                }
556             }
557          }
558          else {
559             for (i=0;i<n;i++) {
560                if (mask[i]) {
561                   GLstencil *sptr = STENCIL_ADDRESS( x[i], y[i] );
562                   *sptr = (GLstencil) (invmask & *sptr);
563                }
564             }
565          }
566          break;
567       case GL_REPLACE:
568          if (invmask==0) {
569             for (i=0;i<n;i++) {
570                if (mask[i]) {
571                   GLstencil *sptr = STENCIL_ADDRESS( x[i], y[i] );
572                   *sptr = ref;
573                }
574             }
575          }
576          else {
577             for (i=0;i<n;i++) {
578                if (mask[i]) {
579                   GLstencil *sptr = STENCIL_ADDRESS( x[i], y[i] );
580                   *sptr = (GLstencil) ((invmask & *sptr ) | (wrtmask & ref));
581                }
582             }
583          }
584          break;
585       case GL_INCR:
586          if (invmask==0) {
587             for (i=0;i<n;i++) {
588                if (mask[i]) {
589                   GLstencil *sptr = STENCIL_ADDRESS( x[i], y[i] );
590                   if (*sptr < stencilMax) {
591                      *sptr = (GLstencil) (*sptr + 1);
592                   }
593                }
594             }
595          }
596          else {
597             for (i=0;i<n;i++) {
598                if (mask[i]) {
599                   GLstencil *sptr = STENCIL_ADDRESS( x[i], y[i] );
600                   if (*sptr < stencilMax) {
601                      *sptr = (GLstencil) ((invmask & *sptr) | (wrtmask & (*sptr+1)));
602                   }
603                }
604             }
605          }
606          break;
607       case GL_DECR:
608          if (invmask==0) {
609             for (i=0;i<n;i++) {
610                if (mask[i]) {
611                   GLstencil *sptr = STENCIL_ADDRESS( x[i], y[i] );
612                   if (*sptr>0) {
613                      *sptr = (GLstencil) (*sptr - 1);
614                   }
615                }
616             }
617          }
618          else {
619             for (i=0;i<n;i++) {
620                if (mask[i]) {
621                   GLstencil *sptr = STENCIL_ADDRESS( x[i], y[i] );
622                   if (*sptr>0) {
623                      *sptr = (GLstencil) ((invmask & *sptr) | (wrtmask & (*sptr-1)));
624                   }
625                }
626             }
627          }
628          break;
629       case GL_INCR_WRAP_EXT:
630          if (invmask==0) {
631             for (i=0;i<n;i++) {
632                if (mask[i]) {
633                   GLstencil *sptr = STENCIL_ADDRESS( x[i], y[i] );
634                   *sptr = (GLstencil) (*sptr + 1);
635                }
636             }
637          }
638          else {
639             for (i=0;i<n;i++) {
640                if (mask[i]) {
641                   GLstencil *sptr = STENCIL_ADDRESS( x[i], y[i] );
642                   *sptr = (GLstencil) ((invmask & *sptr) | (wrtmask & (*sptr+1)));
643                }
644             }
645          }
646          break;
647       case GL_DECR_WRAP_EXT:
648          if (invmask==0) {
649             for (i=0;i<n;i++) {
650                if (mask[i]) {
651                   GLstencil *sptr = STENCIL_ADDRESS( x[i], y[i] );
652                   *sptr = (GLstencil) (*sptr - 1);
653                }
654             }
655          }
656          else {
657             for (i=0;i<n;i++) {
658                if (mask[i]) {
659                   GLstencil *sptr = STENCIL_ADDRESS( x[i], y[i] );
660                   *sptr = (GLstencil) ((invmask & *sptr) | (wrtmask & (*sptr-1)));
661                }
662             }
663          }
664          break;
665       case GL_INVERT:
666          if (invmask==0) {
667             for (i=0;i<n;i++) {
668                if (mask[i]) {
669                   GLstencil *sptr = STENCIL_ADDRESS( x[i], y[i] );
670                   *sptr = (GLstencil) (~*sptr);
671                }
672             }
673          }
674          else {
675             for (i=0;i<n;i++) {
676                if (mask[i]) {
677                   GLstencil *sptr = STENCIL_ADDRESS( x[i], y[i] );
678                   *sptr = (GLstencil) ((invmask & *sptr) | (wrtmask & ~*sptr));
679                }
680             }
681          }
682          break;
683       default:
684          _mesa_problem(ctx, "Bad stencilop in apply_stencil_op_to_pixels");
685    }
686 }
687
688
689
690 /**
691  * Apply stencil test to an array of pixels before depth buffering.
692  *
693  * \note Used for software stencil buffer only.
694  * Input:  n - number of pixels in the span
695  *         x, y - array of [n] pixels to stencil
696  *         mask - array [n] of flag:  0=skip the pixel, 1=stencil the pixel
697  * Output:  mask - pixels which fail the stencil test will have their
698  *                 mask flag set to 0.
699  * \return  GL_FALSE = all pixels failed, GL_TRUE = zero or more pixels passed.
700  */
701 static GLboolean
702 stencil_test_pixels( struct gl_context *ctx, GLuint face, GLuint n,
703                      const GLint x[], const GLint y[], GLubyte mask[] )
704 {
705    const struct gl_framebuffer *fb = ctx->DrawBuffer;
706    struct gl_renderbuffer *rb = fb->_StencilBuffer;
707    GLubyte fail[MAX_WIDTH];
708    GLstencil r, s;
709    GLuint i;
710    GLboolean allfail = GL_FALSE;
711    const GLuint valueMask = ctx->Stencil.ValueMask[face];
712    const GLstencil *stencilStart = (GLstencil *) rb->Data;
713    const GLuint stride = rb->Width;
714
715    ASSERT(rb->GetPointer(ctx, rb, 0, 0));
716    ASSERT(sizeof(GLstencil) == 1);
717
718    /*
719     * Perform stencil test.  The results of this operation are stored
720     * in the fail[] array:
721     *   IF fail[i] is non-zero THEN
722     *       the stencil fail operator is to be applied
723     *   ELSE
724     *       the stencil fail operator is not to be applied
725     *   ENDIF
726     */
727
728    switch (ctx->Stencil.Function[face]) {
729       case GL_NEVER:
730          /* always fail */
731          for (i=0;i<n;i++) {
732             if (mask[i]) {
733                mask[i] = 0;
734                fail[i] = 1;
735             }
736             else {
737                fail[i] = 0;
738             }
739          }
740          allfail = GL_TRUE;
741          break;
742       case GL_LESS:
743          r = (GLstencil) (ctx->Stencil.Ref[face] & valueMask);
744          for (i=0;i<n;i++) {
745             if (mask[i]) {
746                const GLstencil *sptr = STENCIL_ADDRESS(x[i],y[i]);
747                s = (GLstencil) (*sptr & valueMask);
748                if (r < s) {
749                   /* passed */
750                   fail[i] = 0;
751                }
752                else {
753                   fail[i] = 1;
754                   mask[i] = 0;
755                }
756             }
757             else {
758                fail[i] = 0;
759             }
760          }
761          break;
762       case GL_LEQUAL:
763          r = (GLstencil) (ctx->Stencil.Ref[face] & valueMask);
764          for (i=0;i<n;i++) {
765             if (mask[i]) {
766                const GLstencil *sptr = STENCIL_ADDRESS(x[i],y[i]);
767                s = (GLstencil) (*sptr & valueMask);
768                if (r <= s) {
769                   /* pass */
770                   fail[i] = 0;
771                }
772                else {
773                   fail[i] = 1;
774                   mask[i] = 0;
775                }
776             }
777             else {
778                fail[i] = 0;
779             }
780          }
781          break;
782       case GL_GREATER:
783          r = (GLstencil) (ctx->Stencil.Ref[face] & valueMask);
784          for (i=0;i<n;i++) {
785             if (mask[i]) {
786                const GLstencil *sptr = STENCIL_ADDRESS(x[i],y[i]);
787                s = (GLstencil) (*sptr & valueMask);
788                if (r > s) {
789                   /* passed */
790                   fail[i] = 0;
791                }
792                else {
793                   fail[i] = 1;
794                   mask[i] = 0;
795                }
796             }
797             else {
798                fail[i] = 0;
799             }
800          }
801          break;
802       case GL_GEQUAL:
803          r = (GLstencil) (ctx->Stencil.Ref[face] & valueMask);
804          for (i=0;i<n;i++) {
805             if (mask[i]) {
806                const GLstencil *sptr = STENCIL_ADDRESS(x[i],y[i]);
807                s = (GLstencil) (*sptr & valueMask);
808                if (r >= s) {
809                   /* passed */
810                   fail[i] = 0;
811                }
812                else {
813                   fail[i] = 1;
814                   mask[i] = 0;
815                }
816             }
817             else {
818                fail[i] = 0;
819             }
820          }
821          break;
822       case GL_EQUAL:
823          r = (GLstencil) (ctx->Stencil.Ref[face] & valueMask);
824          for (i=0;i<n;i++) {
825             if (mask[i]) {
826                const GLstencil *sptr = STENCIL_ADDRESS(x[i],y[i]);
827                s = (GLstencil) (*sptr & valueMask);
828                if (r == s) {
829                   /* passed */
830                   fail[i] = 0;
831                }
832                else {
833                   fail[i] = 1;
834                   mask[i] = 0;
835                }
836             }
837             else {
838                fail[i] = 0;
839             }
840          }
841          break;
842       case GL_NOTEQUAL:
843          r = (GLstencil) (ctx->Stencil.Ref[face] & valueMask);
844          for (i=0;i<n;i++) {
845             if (mask[i]) {
846                const GLstencil *sptr = STENCIL_ADDRESS(x[i],y[i]);
847                s = (GLstencil) (*sptr & valueMask);
848                if (r != s) {
849                   /* passed */
850                   fail[i] = 0;
851                }
852                else {
853                   fail[i] = 1;
854                   mask[i] = 0;
855                }
856             }
857             else {
858                fail[i] = 0;
859             }
860          }
861          break;
862       case GL_ALWAYS:
863          /* always pass */
864          for (i=0;i<n;i++) {
865             fail[i] = 0;
866          }
867          break;
868       default:
869          _mesa_problem(ctx, "Bad stencil func in gl_stencil_pixels");
870          return 0;
871    }
872
873    if (ctx->Stencil.FailFunc[face] != GL_KEEP) {
874       apply_stencil_op_to_pixels( ctx, n, x, y, ctx->Stencil.FailFunc[face],
875                                   face, fail );
876    }
877
878    return !allfail;
879 }
880
881
882
883
884 /**
885  * Apply stencil and depth testing to an array of pixels.
886  * This is used both for software and hardware stencil buffers.
887  *
888  * The comments in this function are a bit sparse but the code is
889  * almost identical to stencil_and_ztest_span(), which is well
890  * commented.
891  *
892  * Input:  n - number of pixels in the array
893  *         x, y - array of [n] pixel positions
894  *         z - array [n] of z values
895  *         mask - array [n] of flags  (1=test this pixel, 0=skip the pixel)
896  * Output: mask - array [n] of flags (1=stencil and depth test passed)
897  * Return: GL_FALSE - all fragments failed the testing
898  *         GL_TRUE - one or more fragments passed the testing
899  */
900 static GLboolean
901 stencil_and_ztest_pixels( struct gl_context *ctx, SWspan *span, GLuint face )
902 {
903    GLubyte passMask[MAX_WIDTH], failMask[MAX_WIDTH], origMask[MAX_WIDTH];
904    struct gl_framebuffer *fb = ctx->DrawBuffer;
905    struct gl_renderbuffer *rb = fb->_StencilBuffer;
906    const GLuint n = span->end;
907    const GLint *x = span->array->x;
908    const GLint *y = span->array->y;
909    GLubyte *mask = span->array->mask;
910
911    ASSERT(span->arrayMask & SPAN_XY);
912    ASSERT(ctx->Stencil.Enabled);
913    ASSERT(n <= MAX_WIDTH);
914
915    if (!rb->GetPointer(ctx, rb, 0, 0)) {
916       /* No direct access */
917       GLstencil stencil[MAX_WIDTH];
918
919       ASSERT(rb->DataType == GL_UNSIGNED_BYTE);
920       _swrast_get_values(ctx, rb, n, x, y, stencil, sizeof(GLubyte));
921
922       memcpy(origMask, mask, n * sizeof(GLubyte));          
923
924       (void) do_stencil_test(ctx, face, n, stencil, mask);
925
926       if (ctx->Depth.Test == GL_FALSE) {
927          apply_stencil_op(ctx, ctx->Stencil.ZPassFunc[face], face,
928                           n, stencil, mask);
929       }
930       else {
931          GLubyte tmpMask[MAX_WIDTH]; 
932          memcpy(tmpMask, mask, n * sizeof(GLubyte));
933
934          _swrast_depth_test_span(ctx, span);
935
936          compute_pass_fail_masks(n, tmpMask, mask, passMask, failMask);
937
938          if (ctx->Stencil.ZFailFunc[face] != GL_KEEP) {
939             apply_stencil_op(ctx, ctx->Stencil.ZFailFunc[face], face,
940                              n, stencil, failMask);
941          }
942          if (ctx->Stencil.ZPassFunc[face] != GL_KEEP) {
943             apply_stencil_op(ctx, ctx->Stencil.ZPassFunc[face], face,
944                              n, stencil, passMask);
945          }
946       }
947
948       /* Write updated stencil values into hardware stencil buffer */
949       rb->PutValues(ctx, rb, n, x, y, stencil, origMask);
950
951       return GL_TRUE;
952    }
953    else {
954       /* Direct access to stencil buffer */
955
956       if (stencil_test_pixels(ctx, face, n, x, y, mask) == GL_FALSE) {
957          /* all fragments failed the stencil test, we're done. */
958          return GL_FALSE;
959       }
960
961       if (ctx->Depth.Test==GL_FALSE) {
962          apply_stencil_op_to_pixels(ctx, n, x, y,
963                                     ctx->Stencil.ZPassFunc[face], face, mask);
964       }
965       else {
966          memcpy(origMask, mask, n * sizeof(GLubyte));
967
968          _swrast_depth_test_span(ctx, span);
969
970          compute_pass_fail_masks(n, origMask, mask, passMask, failMask);
971
972          if (ctx->Stencil.ZFailFunc[face] != GL_KEEP) {
973             apply_stencil_op_to_pixels(ctx, n, x, y,
974                                        ctx->Stencil.ZFailFunc[face],
975                                        face, failMask);
976          }
977          if (ctx->Stencil.ZPassFunc[face] != GL_KEEP) {
978             apply_stencil_op_to_pixels(ctx, n, x, y,
979                                        ctx->Stencil.ZPassFunc[face],
980                                        face, passMask);
981          }
982       }
983
984       return GL_TRUE;  /* one or more fragments passed both tests */
985    }
986 }
987
988
989 /**
990  * /return GL_TRUE = one or more fragments passed,
991  * GL_FALSE = all fragments failed.
992  */
993 GLboolean
994 _swrast_stencil_and_ztest_span(struct gl_context *ctx, SWspan *span)
995 {
996    const GLuint face = (span->facing == 0) ? 0 : ctx->Stencil._BackFace;
997
998    if (span->arrayMask & SPAN_XY)
999       return stencil_and_ztest_pixels(ctx, span, face);
1000    else
1001       return stencil_and_ztest_span(ctx, span, face);
1002 }
1003
1004
1005 #if 0
1006 GLuint
1007 clip_span(GLuint bufferWidth, GLuint bufferHeight,
1008           GLint x, GLint y, GLuint *count)
1009 {
1010    GLuint n = *count;
1011    GLuint skipPixels = 0;
1012
1013    if (y < 0 || y >= bufferHeight || x + n <= 0 || x >= bufferWidth) {
1014       /* totally out of bounds */
1015       n = 0;
1016    }
1017    else {
1018       /* left clip */
1019       if (x < 0) {
1020          skipPixels = -x;
1021          x = 0;
1022          n -= skipPixels;
1023       }
1024       /* right clip */
1025       if (x + n > bufferWidth) {
1026          GLint dx = x + n - bufferWidth;
1027          n -= dx;
1028       }
1029    }
1030
1031    *count = n;
1032
1033    return skipPixels;
1034 }
1035 #endif
1036
1037
1038 /**
1039  * Return a span of stencil values from the stencil buffer.
1040  * Used for glRead/CopyPixels
1041  * Input:  n - how many pixels
1042  *         x,y - location of first pixel
1043  * Output:  stencil - the array of stencil values
1044  */
1045 void
1046 _swrast_read_stencil_span(struct gl_context *ctx, struct gl_renderbuffer *rb,
1047                           GLint n, GLint x, GLint y, GLstencil stencil[])
1048 {
1049    if (y < 0 || y >= (GLint) rb->Height ||
1050        x + n <= 0 || x >= (GLint) rb->Width) {
1051       /* span is completely outside framebuffer */
1052       return; /* undefined values OK */
1053    }
1054
1055    if (x < 0) {
1056       GLint dx = -x;
1057       x = 0;
1058       n -= dx;
1059       stencil += dx;
1060    }
1061    if (x + n > (GLint) rb->Width) {
1062       GLint dx = x + n - rb->Width;
1063       n -= dx;
1064    }
1065    if (n <= 0) {
1066       return;
1067    }
1068
1069    rb->GetRow(ctx, rb, n, x, y, stencil);
1070 }
1071
1072
1073
1074 /**
1075  * Write a span of stencil values to the stencil buffer.  This function
1076  * applies the stencil write mask when needed.
1077  * Used for glDraw/CopyPixels
1078  * Input:  n - how many pixels
1079  *         x, y - location of first pixel
1080  *         stencil - the array of stencil values
1081  */
1082 void
1083 _swrast_write_stencil_span(struct gl_context *ctx, GLint n, GLint x, GLint y,
1084                            const GLstencil stencil[] )
1085 {
1086    struct gl_framebuffer *fb = ctx->DrawBuffer;
1087    struct gl_renderbuffer *rb = fb->_StencilBuffer;
1088    const GLuint stencilMax = (1 << fb->Visual.stencilBits) - 1;
1089    const GLuint stencilMask = ctx->Stencil.WriteMask[0];
1090
1091    if (y < 0 || y >= (GLint) rb->Height ||
1092        x + n <= 0 || x >= (GLint) rb->Width) {
1093       /* span is completely outside framebuffer */
1094       return; /* undefined values OK */
1095    }
1096    if (x < 0) {
1097       GLint dx = -x;
1098       x = 0;
1099       n -= dx;
1100       stencil += dx;
1101    }
1102    if (x + n > (GLint) rb->Width) {
1103       GLint dx = x + n - rb->Width;
1104       n -= dx;
1105    }
1106    if (n <= 0) {
1107       return;
1108    }
1109
1110    if ((stencilMask & stencilMax) != stencilMax) {
1111       /* need to apply writemask */
1112       GLstencil destVals[MAX_WIDTH], newVals[MAX_WIDTH];
1113       GLint i;
1114       rb->GetRow(ctx, rb, n, x, y, destVals);
1115       for (i = 0; i < n; i++) {
1116          newVals[i]
1117             = (stencil[i] & stencilMask) | (destVals[i] & ~stencilMask);
1118       }
1119       rb->PutRow(ctx, rb, n, x, y, newVals, NULL);
1120    }
1121    else {
1122       rb->PutRow(ctx, rb, n, x, y, stencil, NULL);
1123    }
1124 }
1125
1126
1127
1128 /**
1129  * Clear the stencil buffer.
1130  */
1131 void
1132 _swrast_clear_stencil_buffer( struct gl_context *ctx, struct gl_renderbuffer *rb )
1133 {
1134    const GLubyte stencilBits = ctx->DrawBuffer->Visual.stencilBits;
1135    const GLuint mask = ctx->Stencil.WriteMask[0];
1136    const GLuint invMask = ~mask;
1137    const GLuint clearVal = (ctx->Stencil.Clear & mask);
1138    const GLuint stencilMax = (1 << stencilBits) - 1;
1139    GLint x, y, width, height;
1140
1141    if (!rb || mask == 0)
1142       return;
1143
1144    ASSERT(rb->DataType == GL_UNSIGNED_BYTE ||
1145           rb->DataType == GL_UNSIGNED_SHORT);
1146
1147    ASSERT(rb->_BaseFormat == GL_STENCIL_INDEX);
1148
1149    /* compute region to clear */
1150    x = ctx->DrawBuffer->_Xmin;
1151    y = ctx->DrawBuffer->_Ymin;
1152    width  = ctx->DrawBuffer->_Xmax - ctx->DrawBuffer->_Xmin;
1153    height = ctx->DrawBuffer->_Ymax - ctx->DrawBuffer->_Ymin;
1154
1155    if (rb->GetPointer(ctx, rb, 0, 0)) {
1156       /* Direct buffer access */
1157       if ((mask & stencilMax) != stencilMax) {
1158          /* need to mask the clear */
1159          if (rb->DataType == GL_UNSIGNED_BYTE) {
1160             GLint i, j;
1161             for (i = 0; i < height; i++) {
1162                GLubyte *stencil = (GLubyte*) rb->GetPointer(ctx, rb, x, y + i);
1163                for (j = 0; j < width; j++) {
1164                   stencil[j] = (stencil[j] & invMask) | clearVal;
1165                }
1166             }
1167          }
1168          else {
1169             GLint i, j;
1170             for (i = 0; i < height; i++) {
1171                GLushort *stencil = (GLushort*) rb->GetPointer(ctx, rb, x, y + i);
1172                for (j = 0; j < width; j++) {
1173                   stencil[j] = (stencil[j] & invMask) | clearVal;
1174                }
1175             }
1176          }
1177       }
1178       else {
1179          /* no bit masking */
1180          if (width == (GLint) rb->Width && rb->DataType == GL_UNSIGNED_BYTE) {
1181             /* optimized case */
1182             /* Note: bottom-to-top raster assumed! */
1183             GLubyte *stencil = (GLubyte *) rb->GetPointer(ctx, rb, x, y);
1184             GLuint len = width * height * sizeof(GLubyte);
1185             memset(stencil, clearVal, len);
1186          }
1187          else {
1188             /* general case */
1189             GLint i;
1190             for (i = 0; i < height; i++) {
1191                GLvoid *stencil = rb->GetPointer(ctx, rb, x, y + i);
1192                if (rb->DataType == GL_UNSIGNED_BYTE) {
1193                   memset(stencil, clearVal, width);
1194                }
1195                else {
1196                   _mesa_memset16((short unsigned int*) stencil, clearVal, width);
1197                }
1198             }
1199          }
1200       }
1201    }
1202    else {
1203       /* no direct access */
1204       if ((mask & stencilMax) != stencilMax) {
1205          /* need to mask the clear */
1206          if (rb->DataType == GL_UNSIGNED_BYTE) {
1207             GLint i, j;
1208             for (i = 0; i < height; i++) {
1209                GLubyte stencil[MAX_WIDTH];
1210                rb->GetRow(ctx, rb, width, x, y + i, stencil);
1211                for (j = 0; j < width; j++) {
1212                   stencil[j] = (stencil[j] & invMask) | clearVal;
1213                }
1214                rb->PutRow(ctx, rb, width, x, y + i, stencil, NULL);
1215             }
1216          }
1217          else {
1218             GLint i, j;
1219             for (i = 0; i < height; i++) {
1220                GLushort stencil[MAX_WIDTH];
1221                rb->GetRow(ctx, rb, width, x, y + i, stencil);
1222                for (j = 0; j < width; j++) {
1223                   stencil[j] = (stencil[j] & invMask) | clearVal;
1224                }
1225                rb->PutRow(ctx, rb, width, x, y + i, stencil, NULL);
1226             }
1227          }
1228       }
1229       else {
1230          /* no bit masking */
1231          const GLubyte clear8 = (GLubyte) clearVal;
1232          const GLushort clear16 = (GLushort) clearVal;
1233          const void *clear;
1234          GLint i;
1235          if (rb->DataType == GL_UNSIGNED_BYTE) {
1236             clear = &clear8;
1237          }
1238          else {
1239             clear = &clear16;
1240          }
1241          for (i = 0; i < height; i++) {
1242             rb->PutMonoRow(ctx, rb, width, x, y + i, clear, NULL);
1243          }
1244       }
1245    }
1246 }