1f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org/*
2f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * Mesa 3-D graphics library
3f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * Version:  7.1
4f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org *
5f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * Copyright (C) 1999-2007  Brian Paul   All Rights Reserved.
6f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org *
7f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * Permission is hereby granted, free of charge, to any person obtaining a
8f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * copy of this software and associated documentation files (the "Software"),
9f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * to deal in the Software without restriction, including without limitation
10f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * the rights to use, copy, modify, merge, publish, distribute, sublicense,
11f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * and/or sell copies of the Software, and to permit persons to whom the
12f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * Software is furnished to do so, subject to the following conditions:
13f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org *
14f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * The above copyright notice and this permission notice shall be included
15f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * in all copies or substantial portions of the Software.
16f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org *
17f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
18f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
20f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
21f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
22f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org */
24f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
25f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
26f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#include "main/glheader.h"
27f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#include "main/context.h"
28f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#include "main/imports.h"
29f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#include "main/format_pack.h"
30f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#include "main/format_unpack.h"
31f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
32f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#include "s_context.h"
33f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#include "s_depth.h"
34f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#include "s_stencil.h"
35f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#include "s_span.h"
36f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
37f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
38f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
39f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org/* Stencil Logic:
40f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
41f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgIF stencil test fails THEN
42f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   Apply fail-op to stencil value
43f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   Don't write the pixel (RGBA,Z)
44f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgELSE
45f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   IF doing depth test && depth test fails THEN
46f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      Apply zfail-op to stencil value
47f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      Write RGBA and Z to appropriate buffers
48f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   ELSE
49f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      Apply zpass-op to stencil value
50f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgENDIF
51f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
52f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org*/
53f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
54f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
55f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
56f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org/**
57f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * Compute/return the offset of the stencil value in a pixel.
58f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * For example, if the format is Z24+S8, the position of the stencil bits
59f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * within the 4-byte pixel will be either 0 or 3.
60f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org */
61f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgstatic GLint
62f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgget_stencil_offset(gl_format format)
63f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org{
64f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   const GLubyte one = 1;
65f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   GLubyte pixel[MAX_PIXEL_BYTES];
66f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   GLint bpp = _mesa_get_format_bytes(format);
67f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   GLint i;
68f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
69f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   assert(_mesa_get_format_bits(format, GL_STENCIL_BITS) == 8);
70f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   memset(pixel, 0, sizeof(pixel));
71f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   _mesa_pack_ubyte_stencil_row(format, 1, &one, pixel);
72f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
73f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   for (i = 0; i < bpp; i++) {
74f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      if (pixel[i])
75f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         return i;
76f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   }
77f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
78f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   _mesa_problem(NULL, "get_stencil_offset() failed\n");
79f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   return 0;
80f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org}
81f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
82f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
83f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org/** Clamp the stencil value to [0, 255] */
84f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgstatic inline GLubyte
85f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgclamp(GLint val)
86f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org{
87f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   if (val < 0)
88f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      return 0;
89f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   else if (val > 255)
90f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      return 255;
91f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   else
92f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      return val;
93f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org}
94f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
95f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
96f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#define STENCIL_OP(NEW_VAL)                                                 \
97f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   if (invmask == 0) {                                                      \
98f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      for (i = j = 0; i < n; i++, j += stride) {                            \
99f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         if (mask[i]) {                                                     \
100f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org            GLubyte s = stencil[j];                                         \
101f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org            (void) s;                                                       \
102f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org            stencil[j] = (GLubyte) (NEW_VAL);                               \
103f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         }                                                                  \
104f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      }                                                                     \
105f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   }                                                                        \
106f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   else {                                                                   \
107f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      for (i = j = 0; i < n; i++, j += stride) {                            \
108f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         if (mask[i]) {                                                     \
109f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org            GLubyte s = stencil[j];                                         \
110f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org            stencil[j] = (GLubyte) ((invmask & s) | (wrtmask & (NEW_VAL))); \
111f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         }                                                                  \
112f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      }                                                                     \
113f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   }
114f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
115f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
116f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org/**
117f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * Apply the given stencil operator to the array of stencil values.
118f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * Don't touch stencil[i] if mask[i] is zero.
119f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * @param n   number of stencil values
120f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * @param oper  the stencil buffer operator
121f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * @param face  0 or 1 for front or back face operation
122f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * @param stencil  array of stencil values (in/out)
123f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * @param mask  array [n] of flag:  1=apply operator, 0=don't apply operator
124f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * @param stride  stride between stencil values
125f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org */
126f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgstatic void
127f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgapply_stencil_op(const struct gl_context *ctx, GLenum oper, GLuint face,
128f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                 GLuint n, GLubyte stencil[], const GLubyte mask[],
129f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                 GLint stride)
130f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org{
131f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   const GLubyte ref = ctx->Stencil.Ref[face];
132f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   const GLubyte wrtmask = ctx->Stencil.WriteMask[face];
133f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   const GLubyte invmask = (GLubyte) (~wrtmask);
134f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   GLuint i, j;
135f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
136f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   switch (oper) {
137f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   case GL_KEEP:
138f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      /* do nothing */
139f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      break;
140f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   case GL_ZERO:
141f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      /* replace stencil buf values with zero */
142f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      STENCIL_OP(0);
143f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      break;
144f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   case GL_REPLACE:
145f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      /* replace stencil buf values with ref value */
146f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      STENCIL_OP(ref);
147f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      break;
148f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   case GL_INCR:
149f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      /* increment stencil buf values, with clamping */
150f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      STENCIL_OP(clamp(s + 1));
151f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      break;
152f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   case GL_DECR:
153f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      /* increment stencil buf values, with clamping */
154f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      STENCIL_OP(clamp(s - 1));
155f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      break;
156f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   case GL_INCR_WRAP_EXT:
157f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      /* increment stencil buf values, without clamping */
158f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      STENCIL_OP(s + 1);
159f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      break;
160f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   case GL_DECR_WRAP_EXT:
161f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      /* increment stencil buf values, without clamping */
162f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      STENCIL_OP(s - 1);
163f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      break;
164f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   case GL_INVERT:
165f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      /* replace stencil buf values with inverted value */
166f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      STENCIL_OP(~s);
167f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      break;
168f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   default:
169f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      _mesa_problem(ctx, "Bad stencil op in apply_stencil_op");
170f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   }
171f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org}
172f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
173f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
174f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
175f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#define STENCIL_TEST(FUNC)                        \
176f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   for (i = j = 0; i < n; i++, j += stride) {     \
177f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      if (mask[i]) {                              \
178f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         s = (GLubyte) (stencil[j] & valueMask);  \
179f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         if (FUNC) {                              \
180f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org            /* stencil pass */                    \
181f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org            fail[i] = 0;                          \
182f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         }                                        \
183f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         else {                                   \
184f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org            /* stencil fail */                    \
185f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org            fail[i] = 1;                          \
186f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org            mask[i] = 0;                          \
187f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         }                                        \
188f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      }                                           \
189f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      else {                                      \
190f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         fail[i] = 0;                             \
191f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      }                                           \
192f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   }
193f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
194f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
195f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
196f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org/**
197f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * Apply stencil test to an array of stencil values (before depth buffering).
198f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * For the values that fail, we'll apply the GL_STENCIL_FAIL operator to
199f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * the stencil values.
200f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org *
201f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * @param face  0 or 1 for front or back-face polygons
202f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * @param n  number of pixels in the array
203f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * @param stencil  array of [n] stencil values (in/out)
204f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * @param mask  array [n] of flag:  0=skip the pixel, 1=stencil the pixel,
205f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org *              values are set to zero where the stencil test fails.
206f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * @param stride  stride between stencil values
207f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * @return GL_FALSE = all pixels failed, GL_TRUE = zero or more pixels passed.
208f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org */
209f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgstatic GLboolean
210f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgdo_stencil_test(struct gl_context *ctx, GLuint face, GLuint n,
211f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                GLubyte stencil[], GLubyte mask[], GLint stride)
212f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org{
213f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   SWcontext *swrast = SWRAST_CONTEXT(ctx);
214f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   GLubyte *fail = swrast->stencil_temp.buf2;
215f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   GLboolean allfail = GL_FALSE;
216f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   GLuint i, j;
217f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   const GLuint valueMask = ctx->Stencil.ValueMask[face];
218f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   const GLubyte ref = (GLubyte) (ctx->Stencil.Ref[face] & valueMask);
219f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   GLubyte s;
220f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
221f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   /*
222f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    * Perform stencil test.  The results of this operation are stored
223f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    * in the fail[] array:
224f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    *   IF fail[i] is non-zero THEN
225f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    *       the stencil fail operator is to be applied
226f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    *   ELSE
227f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    *       the stencil fail operator is not to be applied
228f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    *   ENDIF
229f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    */
230f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   switch (ctx->Stencil.Function[face]) {
231f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   case GL_NEVER:
232f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      STENCIL_TEST(0);
233f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      allfail = GL_TRUE;
234f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      break;
235f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   case GL_LESS:
236f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      STENCIL_TEST(ref < s);
237f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      break;
238f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   case GL_LEQUAL:
239f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      STENCIL_TEST(ref <= s);
240f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      break;
241f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   case GL_GREATER:
242f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      STENCIL_TEST(ref > s);
243f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      break;
244f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   case GL_GEQUAL:
245f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      STENCIL_TEST(ref >= s);
246f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      break;
247f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   case GL_EQUAL:
248f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      STENCIL_TEST(ref == s);
249f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      break;
250f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   case GL_NOTEQUAL:
251f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      STENCIL_TEST(ref != s);
252f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      break;
253f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   case GL_ALWAYS:
254f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      STENCIL_TEST(1);
255f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      break;
256f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   default:
257f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      _mesa_problem(ctx, "Bad stencil func in gl_stencil_span");
258f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      return 0;
259f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   }
260f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
261f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   if (ctx->Stencil.FailFunc[face] != GL_KEEP) {
262f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      apply_stencil_op(ctx, ctx->Stencil.FailFunc[face], face, n, stencil,
263f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                       fail, stride);
264f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   }
265f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
266f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   return !allfail;
267f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org}
268f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
269f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
270f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org/**
271f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * Compute the zpass/zfail masks by comparing the pre- and post-depth test
272f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * masks.
273f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org */
274f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgstatic inline void
275f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgcompute_pass_fail_masks(GLuint n, const GLubyte origMask[],
276f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                        const GLubyte newMask[],
277f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                        GLubyte passMask[], GLubyte failMask[])
278f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org{
279f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   GLuint i;
280f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   for (i = 0; i < n; i++) {
281f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      ASSERT(newMask[i] == 0 || newMask[i] == 1);
282f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      passMask[i] = origMask[i] & newMask[i];
283f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      failMask[i] = origMask[i] & (newMask[i] ^ 1);
284f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   }
285f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org}
286f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
287f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
288f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org/**
289f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * Get 8-bit stencil values from random locations in the stencil buffer.
290f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org */
291f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgstatic void
292f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgget_s8_values(struct gl_context *ctx, struct gl_renderbuffer *rb,
293f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org              GLuint count, const GLint x[], const GLint y[],
294f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org              GLubyte stencil[])
295f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org{
296f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   struct swrast_renderbuffer *srb = swrast_renderbuffer(rb);
297f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   const GLint w = rb->Width, h = rb->Height;
298f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   const GLubyte *map = _swrast_pixel_address(rb, 0, 0);
299f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   GLuint i;
300f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
301f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   if (rb->Format == MESA_FORMAT_S8) {
302f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      const GLint rowStride = srb->RowStride;
303f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      for (i = 0; i < count; i++) {
304f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         if (x[i] >= 0 && y[i] >= 0 && x[i] < w && y[i] < h) {
305f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org            stencil[i] = *(map + y[i] * rowStride + x[i]);
306f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         }
307f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      }
308f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   }
309f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   else {
310f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      const GLint bpp = _mesa_get_format_bytes(rb->Format);
311f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      const GLint rowStride = srb->RowStride;
312f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      for (i = 0; i < count; i++) {
313f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         if (x[i] >= 0 && y[i] >= 0 && x[i] < w && y[i] < h) {
314f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org            const GLubyte *src = map + y[i] * rowStride + x[i] * bpp;
315f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org            _mesa_unpack_ubyte_stencil_row(rb->Format, 1, src, &stencil[i]);
316f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         }
317f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      }
318f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   }
319f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org}
320f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
321f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
322f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org/**
323f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * Put 8-bit stencil values at random locations into the stencil buffer.
324f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org */
325f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgstatic void
326f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgput_s8_values(struct gl_context *ctx, struct gl_renderbuffer *rb,
327f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org              GLuint count, const GLint x[], const GLint y[],
328f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org              const GLubyte stencil[])
329f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org{
330f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   const GLint w = rb->Width, h = rb->Height;
331f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   gl_pack_ubyte_stencil_func pack_stencil =
332f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      _mesa_get_pack_ubyte_stencil_func(rb->Format);
333f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   GLuint i;
334f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
335f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   for (i = 0; i < count; i++) {
336f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      if (x[i] >= 0 && y[i] >= 0 && x[i] < w && y[i] < h) {
337f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         GLubyte *dst = _swrast_pixel_address(rb, x[i], y[i]);
338f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         pack_stencil(&stencil[i], dst);
339f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      }
340f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   }
341f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org}
342f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
343f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
344f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org/**
345f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * /return GL_TRUE = one or more fragments passed,
346f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * GL_FALSE = all fragments failed.
347f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org */
348f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgGLboolean
349f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org_swrast_stencil_and_ztest_span(struct gl_context *ctx, SWspan *span)
350f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org{
351f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   SWcontext *swrast = SWRAST_CONTEXT(ctx);
352f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   struct gl_framebuffer *fb = ctx->DrawBuffer;
353f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   struct gl_renderbuffer *rb = fb->Attachment[BUFFER_STENCIL].Renderbuffer;
354f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   const GLint stencilOffset = get_stencil_offset(rb->Format);
355f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   const GLint stencilStride = _mesa_get_format_bytes(rb->Format);
356f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   const GLuint face = (span->facing == 0) ? 0 : ctx->Stencil._BackFace;
357f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   const GLuint count = span->end;
358f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   GLubyte *mask = span->array->mask;
359f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   GLubyte *stencilTemp = swrast->stencil_temp.buf1;
360f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   GLubyte *stencilBuf;
361f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
362f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   if (span->arrayMask & SPAN_XY) {
363f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      /* read stencil values from random locations */
364f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      get_s8_values(ctx, rb, count, span->array->x, span->array->y,
365f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                    stencilTemp);
366f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      stencilBuf = stencilTemp;
367f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   }
368f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   else {
369f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      /* Processing a horizontal run of pixels.  Since stencil is always
370f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org       * 8 bits for all MESA_FORMATs, we just need to use the right offset
371f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org       * and stride to access them.
372f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org       */
373f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      stencilBuf = _swrast_pixel_address(rb, span->x, span->y) + stencilOffset;
374f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   }
375f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
376f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   /*
377f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    * Apply the stencil test to the fragments.
378f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    * failMask[i] is 1 if the stencil test failed.
379f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    */
380f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   if (!do_stencil_test(ctx, face, count, stencilBuf, mask, stencilStride)) {
381f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      /* all fragments failed the stencil test, we're done. */
382f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      span->writeAll = GL_FALSE;
383f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      if (span->arrayMask & SPAN_XY) {
384f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         /* need to write the updated stencil values back to the buffer */
385f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         put_s8_values(ctx, rb, count, span->array->x, span->array->y,
386f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                       stencilTemp);
387f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      }
388f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      return GL_FALSE;
389f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   }
390f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
391f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   /*
392f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    * Some fragments passed the stencil test, apply depth test to them
393f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    * and apply Zpass and Zfail stencil ops.
394f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    */
395f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   if (ctx->Depth.Test == GL_FALSE ||
396f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org       ctx->DrawBuffer->Attachment[BUFFER_DEPTH].Renderbuffer == NULL) {
397f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      /*
398f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org       * No depth buffer, just apply zpass stencil function to active pixels.
399f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org       */
400f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      apply_stencil_op(ctx, ctx->Stencil.ZPassFunc[face], face, count,
401f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                       stencilBuf, mask, stencilStride);
402f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   }
403f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   else {
404f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      /*
405f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org       * Perform depth buffering, then apply zpass or zfail stencil function.
406f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org       */
407f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      SWcontext *swrast = SWRAST_CONTEXT(ctx);
408f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      GLubyte *passMask = swrast->stencil_temp.buf2;
409f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      GLubyte *failMask = swrast->stencil_temp.buf3;
410f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      GLubyte *origMask = swrast->stencil_temp.buf4;
411f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
412f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      /* save the current mask bits */
413f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      memcpy(origMask, mask, count * sizeof(GLubyte));
414f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
415f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      /* apply the depth test */
416f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      _swrast_depth_test_span(ctx, span);
417f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
418f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      compute_pass_fail_masks(count, origMask, mask, passMask, failMask);
419f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
420f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      /* apply the pass and fail operations */
421f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      if (ctx->Stencil.ZFailFunc[face] != GL_KEEP) {
422f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         apply_stencil_op(ctx, ctx->Stencil.ZFailFunc[face], face,
423f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                          count, stencilBuf, failMask, stencilStride);
424f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      }
425f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      if (ctx->Stencil.ZPassFunc[face] != GL_KEEP) {
426f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         apply_stencil_op(ctx, ctx->Stencil.ZPassFunc[face], face,
427f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                          count, stencilBuf, passMask, stencilStride);
428f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      }
429f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   }
430f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
431f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   /* Write updated stencil values back into hardware stencil buffer */
432f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   if (span->arrayMask & SPAN_XY) {
433f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      put_s8_values(ctx, rb, count, span->array->x, span->array->y,
434f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                    stencilBuf);
435f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   }
436f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
437f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   span->writeAll = GL_FALSE;
438f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
439f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   return GL_TRUE;  /* one or more fragments passed both tests */
440f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org}
441f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
442f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
443f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
444f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
445f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org/**
446f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * Return a span of stencil values from the stencil buffer.
447f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * Used for glRead/CopyPixels
448f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * Input:  n - how many pixels
449f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org *         x,y - location of first pixel
450f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * Output:  stencil - the array of stencil values
451f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org */
452f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgvoid
453f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org_swrast_read_stencil_span(struct gl_context *ctx, struct gl_renderbuffer *rb,
454f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                          GLint n, GLint x, GLint y, GLubyte stencil[])
455f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org{
456f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   GLubyte *src;
457f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
458f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   if (y < 0 || y >= (GLint) rb->Height ||
459f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org       x + n <= 0 || x >= (GLint) rb->Width) {
460f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      /* span is completely outside framebuffer */
461f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      return; /* undefined values OK */
462f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   }
463f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
464f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   if (x < 0) {
465f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      GLint dx = -x;
466f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      x = 0;
467f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      n -= dx;
468f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      stencil += dx;
469f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   }
470f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   if (x + n > (GLint) rb->Width) {
471f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      GLint dx = x + n - rb->Width;
472f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      n -= dx;
473f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   }
474f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   if (n <= 0) {
475f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      return;
476f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   }
477f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
478f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   src = _swrast_pixel_address(rb, x, y);
479f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   _mesa_unpack_ubyte_stencil_row(rb->Format, n, src, stencil);
480f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org}
481f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
482f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
483f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
484f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org/**
485f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * Write a span of stencil values to the stencil buffer.  This function
486f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * applies the stencil write mask when needed.
487f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * Used for glDraw/CopyPixels
488f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * Input:  n - how many pixels
489f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org *         x, y - location of first pixel
490f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org *         stencil - the array of stencil values
491f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org */
492f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgvoid
493f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org_swrast_write_stencil_span(struct gl_context *ctx, GLint n, GLint x, GLint y,
494f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                           const GLubyte stencil[] )
495f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org{
496f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   SWcontext *swrast = SWRAST_CONTEXT(ctx);
497f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   struct gl_framebuffer *fb = ctx->DrawBuffer;
498f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   struct gl_renderbuffer *rb = fb->Attachment[BUFFER_STENCIL].Renderbuffer;
499f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   const GLuint stencilMax = (1 << fb->Visual.stencilBits) - 1;
500f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   const GLuint stencilMask = ctx->Stencil.WriteMask[0];
501f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   GLubyte *stencilBuf;
502f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
503f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   if (y < 0 || y >= (GLint) rb->Height ||
504f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org       x + n <= 0 || x >= (GLint) rb->Width) {
505f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      /* span is completely outside framebuffer */
506f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      return; /* undefined values OK */
507f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   }
508f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   if (x < 0) {
509f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      GLint dx = -x;
510f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      x = 0;
511f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      n -= dx;
512f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      stencil += dx;
513f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   }
514f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   if (x + n > (GLint) rb->Width) {
515f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      GLint dx = x + n - rb->Width;
516f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      n -= dx;
517f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   }
518f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   if (n <= 0) {
519f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      return;
520f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   }
521f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
522f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   stencilBuf = _swrast_pixel_address(rb, x, y);
523f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
524f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   if ((stencilMask & stencilMax) != stencilMax) {
525f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      /* need to apply writemask */
526f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      GLubyte *destVals = swrast->stencil_temp.buf1;
527f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      GLubyte *newVals = swrast->stencil_temp.buf2;
528f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      GLint i;
529f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
530f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      _mesa_unpack_ubyte_stencil_row(rb->Format, n, stencilBuf, destVals);
531f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      for (i = 0; i < n; i++) {
532f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         newVals[i]
533f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org            = (stencil[i] & stencilMask) | (destVals[i] & ~stencilMask);
534f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      }
535f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      _mesa_pack_ubyte_stencil_row(rb->Format, n, newVals, stencilBuf);
536f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   }
537f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   else {
538f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      _mesa_pack_ubyte_stencil_row(rb->Format, n, stencil, stencilBuf);
539f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   }
540f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org}
541f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
542f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
543f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
544f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org/**
545f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * Clear the stencil buffer.  If the buffer is a combined
546f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * depth+stencil buffer, only the stencil bits will be touched.
547f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org */
548f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgvoid
549f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org_swrast_clear_stencil_buffer(struct gl_context *ctx)
550f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org{
551f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   struct gl_renderbuffer *rb =
552f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      ctx->DrawBuffer->Attachment[BUFFER_STENCIL].Renderbuffer;
553f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   const GLubyte stencilBits = ctx->DrawBuffer->Visual.stencilBits;
554f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   const GLuint writeMask = ctx->Stencil.WriteMask[0];
555f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   const GLuint stencilMax = (1 << stencilBits) - 1;
556f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   GLint x, y, width, height;
557f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   GLubyte *map;
558f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   GLint rowStride, i, j;
559f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   GLbitfield mapMode;
560f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
561f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   if (!rb || writeMask == 0)
562f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      return;
563f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
564f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   /* compute region to clear */
565f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   x = ctx->DrawBuffer->_Xmin;
566f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   y = ctx->DrawBuffer->_Ymin;
567f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   width  = ctx->DrawBuffer->_Xmax - ctx->DrawBuffer->_Xmin;
568f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   height = ctx->DrawBuffer->_Ymax - ctx->DrawBuffer->_Ymin;
569f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
570f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   mapMode = GL_MAP_WRITE_BIT;
571f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   if ((writeMask & stencilMax) != stencilMax) {
572f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      /* need to mask stencil values */
573f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      mapMode |= GL_MAP_READ_BIT;
574f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   }
575f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   else if (_mesa_get_format_bits(rb->Format, GL_DEPTH_BITS) > 0) {
576f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      /* combined depth+stencil, need to mask Z values */
577f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      mapMode |= GL_MAP_READ_BIT;
578f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   }
579f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
580f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   ctx->Driver.MapRenderbuffer(ctx, rb, x, y, width, height,
581f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                               mapMode, &map, &rowStride);
582f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   if (!map) {
583f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      _mesa_error(ctx, GL_OUT_OF_MEMORY, "glClear(stencil)");
584f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      return;
585f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   }
586f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
587f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   switch (rb->Format) {
588f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   case MESA_FORMAT_S8:
589f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      {
590f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         GLubyte clear = ctx->Stencil.Clear & writeMask & 0xff;
591f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         GLubyte mask = (~writeMask) & 0xff;
592f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         if (mask != 0) {
593f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org            /* masked clear */
594f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org            for (i = 0; i < height; i++) {
595f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org               GLubyte *row = map;
596f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org               for (j = 0; j < width; j++) {
597f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                  row[j] = (row[j] & mask) | clear;
598f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org               }
599f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org               map += rowStride;
600f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org            }
601f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         }
602f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         else if (rowStride == width) {
603f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org            /* clear whole buffer */
604f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org            memset(map, clear, width * height);
605f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         }
606f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         else {
607f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org            /* clear scissored */
608f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org            for (i = 0; i < height; i++) {
609f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org               memset(map, clear, width);
610f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org               map += rowStride;
611f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org            }
612f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         }
613f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      }
614f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      break;
615f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   case MESA_FORMAT_S8_Z24:
616f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      {
617f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         GLuint clear = (ctx->Stencil.Clear & writeMask & 0xff) << 24;
618f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         GLuint mask = (((~writeMask) & 0xff) << 24) | 0xffffff;
619f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         for (i = 0; i < height; i++) {
620f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org            GLuint *row = (GLuint *) map;
621f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org            for (j = 0; j < width; j++) {
622f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org               row[j] = (row[j] & mask) | clear;
623f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org            }
624f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org            map += rowStride;
625f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         }
626f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      }
627f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      break;
628f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   case MESA_FORMAT_Z24_S8:
629f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      {
630f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         GLuint clear = ctx->Stencil.Clear & writeMask & 0xff;
631f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         GLuint mask = 0xffffff00 | ((~writeMask) & 0xff);
632f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         for (i = 0; i < height; i++) {
633f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org            GLuint *row = (GLuint *) map;
634f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org            for (j = 0; j < width; j++) {
635f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org               row[j] = (row[j] & mask) | clear;
636f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org            }
637f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org            map += rowStride;
638f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         }
639f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      }
640f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      break;
641f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   default:
642f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      _mesa_problem(ctx, "Unexpected stencil buffer format %s"
643f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                    " in _swrast_clear_stencil_buffer()",
644f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                    _mesa_get_format_name(rb->Format));
645f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   }
646f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
647f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   ctx->Driver.UnmapRenderbuffer(ctx, rb);
648f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org}
649