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