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