Home | History | Annotate | Download | only in swrast
      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
     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
     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
    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
    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
    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
    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
    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
    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
    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
    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
    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