Subversion Repositories Kolibri OS

Rev

Blame | Last modification | View Log | RSS feed

  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(gl_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_S8) {
  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_S8:
  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_S8_Z24:
  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_Z24_S8:
  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.