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