home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / mesa5.zip / mesa5src.zip / swrast / s_stencil.cpp < prev    next >
C/C++ Source or Header  |  2002-10-24  |  37KB  |  1,328 lines

  1. /* $Id: s_stencil.c,v 1.28 2002/10/24 23:57:24 brianp Exp $ */
  2.  
  3. /*
  4.  * Mesa 3-D graphics library
  5.  * Version:  4.1
  6.  *
  7.  * Copyright (C) 1999-2002  Brian Paul   All Rights Reserved.
  8.  *
  9.  * Permission is hereby granted, free of charge, to any person obtaining a
  10.  * copy of this software and associated documentation files (the "Software"),
  11.  * to deal in the Software without restriction, including without limitation
  12.  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
  13.  * and/or sell copies of the Software, and to permit persons to whom the
  14.  * Software is furnished to do so, subject to the following conditions:
  15.  *
  16.  * The above copyright notice and this permission notice shall be included
  17.  * in all copies or substantial portions of the Software.
  18.  *
  19.  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
  20.  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  21.  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
  22.  * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
  23.  * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
  24.  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  25.  */
  26.  
  27.  
  28. #include "glheader.h"
  29. #include "context.h"
  30. #include "macros.h"
  31. #include "imports.h"
  32.  
  33. #include "s_context.h"
  34. #include "s_depth.h"
  35. #include "s_stencil.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.  * Return the address of a stencil buffer value given the window coords:
  57.  */
  58. #define STENCIL_ADDRESS(X,Y)  \
  59.        (ctx->DrawBuffer->Stencil + ctx->DrawBuffer->Width * (Y) + (X))
  60.  
  61.  
  62.  
  63. /**
  64.  * Apply the given stencil operator to the array of stencil values.
  65.  * Don't touch stencil[i] if mask[i] is zero.
  66.  * Input:  n - size of stencil array
  67.  *         oper - the stencil buffer operator
  68.  *         face - 0 or 1 for front or back face operation
  69.  *         stencil - array of stencil values
  70.  *         mask - array [n] of flag:  1=apply operator, 0=don't apply operator
  71.  * Output:  stencil - modified values
  72.  */
  73. static void
  74. apply_stencil_op( const GLcontext *ctx, GLenum oper, GLuint face,
  75.                   GLuint n, GLstencil stencil[], const GLubyte mask[] )
  76. {
  77.    const GLstencil ref = ctx->Stencil.Ref[face];
  78.    const GLstencil wrtmask = ctx->Stencil.WriteMask[face];
  79.    const GLstencil invmask = (GLstencil) (~wrtmask);
  80.    GLuint i;
  81.  
  82.    switch (oper) {
  83.       case GL_KEEP:
  84.          /* do nothing */
  85.          break;
  86.       case GL_ZERO:
  87.      if (invmask==0) {
  88.         for (i=0;i<n;i++) {
  89.            if (mask[i]) {
  90.           stencil[i] = 0;
  91.            }
  92.         }
  93.      }
  94.      else {
  95.         for (i=0;i<n;i++) {
  96.            if (mask[i]) {
  97.           stencil[i] = (GLstencil) (stencil[i] & invmask);
  98.            }
  99.         }
  100.      }
  101.      break;
  102.       case GL_REPLACE:
  103.      if (invmask==0) {
  104.         for (i=0;i<n;i++) {
  105.            if (mask[i]) {
  106.                   stencil[i] = ref;
  107.            }
  108.         }
  109.      }
  110.      else {
  111.         for (i=0;i<n;i++) {
  112.            if (mask[i]) {
  113.           GLstencil s = stencil[i];
  114.           stencil[i] = (GLstencil) ((invmask & s ) | (wrtmask & ref));
  115.            }
  116.         }
  117.      }
  118.      break;
  119.       case GL_INCR:
  120.      if (invmask==0) {
  121.         for (i=0;i<n;i++) {
  122.            if (mask[i]) {
  123.           GLstencil s = stencil[i];
  124.           if (s < STENCIL_MAX) {
  125.              stencil[i] = (GLstencil) (s+1);
  126.           }
  127.            }
  128.         }
  129.      }
  130.      else {
  131.         for (i=0;i<n;i++) {
  132.            if (mask[i]) {
  133.           /* VERIFY logic of adding 1 to a write-masked value */
  134.           GLstencil s = stencil[i];
  135.           if (s < STENCIL_MAX) {
  136.              stencil[i] = (GLstencil) ((invmask & s) | (wrtmask & (s+1)));
  137.           }
  138.            }
  139.         }
  140.      }
  141.      break;
  142.       case GL_DECR:
  143.      if (invmask==0) {
  144.         for (i=0;i<n;i++) {
  145.            if (mask[i]) {
  146.           GLstencil s = stencil[i];
  147.           if (s>0) {
  148.              stencil[i] = (GLstencil) (s-1);
  149.           }
  150.            }
  151.         }
  152.      }
  153.      else {
  154.         for (i=0;i<n;i++) {
  155.            if (mask[i]) {
  156.           /* VERIFY logic of subtracting 1 to a write-masked value */
  157.           GLstencil s = stencil[i];
  158.           if (s>0) {
  159.              stencil[i] = (GLstencil) ((invmask & s) | (wrtmask & (s-1)));
  160.           }
  161.            }
  162.         }
  163.      }
  164.      break;
  165.       case GL_INCR_WRAP_EXT:
  166.      if (invmask==0) {
  167.         for (i=0;i<n;i++) {
  168.            if (mask[i]) {
  169.                   stencil[i]++;
  170.            }
  171.         }
  172.      }
  173.      else {
  174.         for (i=0;i<n;i++) {
  175.            if (mask[i]) {
  176.                   GLstencil s = stencil[i];
  177.                   stencil[i] = (GLstencil) ((invmask & s) | (wrtmask & (s+1)));
  178.            }
  179.         }
  180.      }
  181.      break;
  182.       case GL_DECR_WRAP_EXT:
  183.      if (invmask==0) {
  184.         for (i=0;i<n;i++) {
  185.            if (mask[i]) {
  186.           stencil[i]--;
  187.            }
  188.         }
  189.      }
  190.      else {
  191.         for (i=0;i<n;i++) {
  192.            if (mask[i]) {
  193.                   GLstencil s = stencil[i];
  194.                   stencil[i] = (GLstencil) ((invmask & s) | (wrtmask & (s-1)));
  195.            }
  196.         }
  197.      }
  198.      break;
  199.       case GL_INVERT:
  200.      if (invmask==0) {
  201.         for (i=0;i<n;i++) {
  202.            if (mask[i]) {
  203.           GLstencil s = stencil[i];
  204.           stencil[i] = (GLstencil) ~s;
  205.            }
  206.         }
  207.      }
  208.      else {
  209.         for (i=0;i<n;i++) {
  210.            if (mask[i]) {
  211.           GLstencil s = stencil[i];
  212.           stencil[i] = (GLstencil) ((invmask & s) | (wrtmask & ~s));
  213.            }
  214.         }
  215.      }
  216.      break;
  217.       default:
  218.          _mesa_problem(ctx, "Bad stencil op in apply_stencil_op");
  219.    }
  220. }
  221.  
  222.  
  223.  
  224.  
  225. /**
  226.  * Apply stencil test to an array of stencil values (before depth buffering).
  227.  * Input:  face - 0 or 1 for front or back-face polygons
  228.  *         n - number of pixels in the array
  229.  *         stencil - array of [n] stencil values
  230.  *         mask - array [n] of flag:  0=skip the pixel, 1=stencil the pixel
  231.  * Output:  mask - pixels which fail the stencil test will have their
  232.  *                 mask flag set to 0.
  233.  *          stencil - updated stencil values (where the test passed)
  234.  * Return:  GL_FALSE = all pixels failed, GL_TRUE = zero or more pixels passed.
  235.  */
  236. static GLboolean
  237. do_stencil_test( GLcontext *ctx, GLuint face, GLuint n, GLstencil stencil[],
  238.                  GLubyte mask[] )
  239. {
  240.    GLubyte fail[MAX_WIDTH];
  241.    GLboolean allfail = GL_FALSE;
  242.    GLuint i;
  243.    GLstencil r, s;
  244.    const GLuint valueMask = ctx->Stencil.ValueMask[face];
  245.  
  246.    ASSERT(n <= MAX_WIDTH);
  247.  
  248.    /*
  249.     * Perform stencil test.  The results of this operation are stored
  250.     * in the fail[] array:
  251.     *   IF fail[i] is non-zero THEN
  252.     *       the stencil fail operator is to be applied
  253.     *   ELSE
  254.     *       the stencil fail operator is not to be applied
  255.     *   ENDIF
  256.     */
  257.    switch (ctx->Stencil.Function[face]) {
  258.       case GL_NEVER:
  259.          /* never pass; always fail */
  260.          for (i=0;i<n;i++) {
  261.         if (mask[i]) {
  262.            mask[i] = 0;
  263.            fail[i] = 1;
  264.         }
  265.         else {
  266.            fail[i] = 0;
  267.         }
  268.      }
  269.      allfail = GL_TRUE;
  270.      break;
  271.       case GL_LESS:
  272.      r = (GLstencil) (ctx->Stencil.Ref[face] & valueMask);
  273.      for (i=0;i<n;i++) {
  274.         if (mask[i]) {
  275.            s = (GLstencil) (stencil[i] & valueMask);
  276.            if (r < s) {
  277.           /* passed */
  278.           fail[i] = 0;
  279.            }
  280.            else {
  281.           fail[i] = 1;
  282.           mask[i] = 0;
  283.            }
  284.         }
  285.         else {
  286.            fail[i] = 0;
  287.         }
  288.      }
  289.      break;
  290.       case GL_LEQUAL:
  291.      r = (GLstencil) (ctx->Stencil.Ref[face] & valueMask);
  292.      for (i=0;i<n;i++) {
  293.         if (mask[i]) {
  294.            s = (GLstencil) (stencil[i] & valueMask);
  295.            if (r <= s) {
  296.           /* pass */
  297.           fail[i] = 0;
  298.            }
  299.            else {
  300.           fail[i] = 1;
  301.           mask[i] = 0;
  302.            }
  303.         }
  304.         else {
  305.            fail[i] = 0;
  306.         }
  307.      }
  308.      break;
  309.       case GL_GREATER:
  310.      r = (GLstencil) (ctx->Stencil.Ref[face] & valueMask);
  311.      for (i=0;i<n;i++) {
  312.         if (mask[i]) {
  313.            s = (GLstencil) (stencil[i] & valueMask);
  314.            if (r > s) {
  315.           /* passed */
  316.           fail[i] = 0;
  317.            }
  318.            else {
  319.           fail[i] = 1;
  320.           mask[i] = 0;
  321.            }
  322.         }
  323.         else {
  324.            fail[i] = 0;
  325.         }
  326.      }
  327.      break;
  328.       case GL_GEQUAL:
  329.      r = (GLstencil) (ctx->Stencil.Ref[face] & valueMask);
  330.      for (i=0;i<n;i++) {
  331.         if (mask[i]) {
  332.            s = (GLstencil) (stencil[i] & valueMask);
  333.            if (r >= s) {
  334.           /* passed */
  335.           fail[i] = 0;
  336.            }
  337.            else {
  338.           fail[i] = 1;
  339.           mask[i] = 0;
  340.            }
  341.         }
  342.         else {
  343.            fail[i] = 0;
  344.         }
  345.      }
  346.      break;
  347.       case GL_EQUAL:
  348.      r = (GLstencil) (ctx->Stencil.Ref[face] & valueMask);
  349.      for (i=0;i<n;i++) {
  350.         if (mask[i]) {
  351.            s = (GLstencil) (stencil[i] & valueMask);
  352.            if (r == s) {
  353.           /* passed */
  354.           fail[i] = 0;
  355.            }
  356.            else {
  357.           fail[i] = 1;
  358.           mask[i] = 0;
  359.            }
  360.         }
  361.         else {
  362.            fail[i] = 0;
  363.         }
  364.      }
  365.      break;
  366.       case GL_NOTEQUAL:
  367.      r = (GLstencil) (ctx->Stencil.Ref[face] & valueMask);
  368.      for (i=0;i<n;i++) {
  369.         if (mask[i]) {
  370.            s = (GLstencil) (stencil[i] & valueMask);
  371.            if (r != s) {
  372.           /* passed */
  373.           fail[i] = 0;
  374.            }
  375.            else {
  376.           fail[i] = 1;
  377.           mask[i] = 0;
  378.            }
  379.         }
  380.         else {
  381.            fail[i] = 0;
  382.         }
  383.      }
  384.      break;
  385.       case GL_ALWAYS:
  386.      /* always pass */
  387.      for (i=0;i<n;i++) {
  388.         fail[i] = 0;
  389.      }
  390.      break;
  391.       default:
  392.          _mesa_problem(ctx, "Bad stencil func in gl_stencil_span");
  393.          return 0;
  394.    }
  395.  
  396.    if (ctx->Stencil.FailFunc[face] != GL_KEEP) {
  397.       apply_stencil_op( ctx, ctx->Stencil.FailFunc[face], face, n, stencil, fail );
  398.    }
  399.  
  400.    return !allfail;
  401. }
  402.  
  403.  
  404.  
  405. /**
  406.  * Apply stencil and depth testing to the span of pixels.
  407.  * Both software and hardware stencil buffers are acceptable.
  408.  * Input:  n - number of pixels in the span
  409.  *         x, y - location of leftmost pixel in span
  410.  *         z - array [n] of z values
  411.  *         mask - array [n] of flags  (1=test this pixel, 0=skip the pixel)
  412.  * Output:  mask - array [n] of flags (1=stencil and depth test passed)
  413.  * Return: GL_FALSE - all fragments failed the testing
  414.  *         GL_TRUE - one or more fragments passed the testing
  415.  *
  416.  */
  417. static GLboolean
  418. stencil_and_ztest_span(GLcontext *ctx, struct sw_span *span, GLuint face)
  419. {
  420.    SWcontext *swrast = SWRAST_CONTEXT(ctx);
  421.    GLstencil stencilRow[MAX_WIDTH];
  422.    GLstencil *stencil;
  423.    const GLuint n = span->end;
  424.    const GLint x = span->x;
  425.    const GLint y = span->y;
  426.    GLubyte *mask = span->array->mask;
  427.  
  428.    ASSERT((span->arrayMask & SPAN_XY) == 0);
  429.    ASSERT(ctx->Stencil.Enabled);
  430.    ASSERT(n <= MAX_WIDTH);
  431. #ifdef DEBUG
  432.    if (ctx->Depth.Test) {
  433.       ASSERT(span->arrayMask & SPAN_Z);
  434.    }
  435. #endif
  436.    
  437.    /* Get initial stencil values */
  438.    if (swrast->Driver.WriteStencilSpan) {
  439.       /* Get stencil values from the hardware stencil buffer */
  440.       ASSERT(swrast->Driver.ReadStencilSpan);
  441.       (*swrast->Driver.ReadStencilSpan)(ctx, n, x, y, stencilRow);
  442.       stencil = stencilRow;
  443.    }
  444.    else {
  445.       /* Get pointer into software stencil buffer */
  446.       stencil = STENCIL_ADDRESS(x, y);
  447.    }
  448.    
  449.    /*
  450.     * Apply the stencil test to the fragments.
  451.     * failMask[i] is 1 if the stencil test failed.
  452.     */
  453.    if (do_stencil_test( ctx, face, n, stencil, mask ) == GL_FALSE) {
  454.       /* all fragments failed the stencil test, we're done. */
  455.       span->writeAll = GL_FALSE;
  456.       return GL_FALSE;
  457.    }
  458.  
  459.    /*
  460.     * Some fragments passed the stencil test, apply depth test to them
  461.     * and apply Zpass and Zfail stencil ops.
  462.     */
  463.    if (ctx->Depth.Test == GL_FALSE) {
  464.       /*
  465.        * No depth buffer, just apply zpass stencil function to active pixels.
  466.        */
  467.       apply_stencil_op( ctx, ctx->Stencil.ZPassFunc[face], face, n, stencil, mask );
  468.    }
  469.    else {
  470.       /*
  471.        * Perform depth buffering, then apply zpass or zfail stencil function.
  472.        */
  473.       GLubyte passmask[MAX_WIDTH], failmask[MAX_WIDTH], oldmask[MAX_WIDTH];
  474.       GLuint i;
  475.  
  476.       /* save the current mask bits */
  477.       MEMCPY(oldmask, mask, n * sizeof(GLubyte));
  478.  
  479.       /* apply the depth test */
  480.       _mesa_depth_test_span(ctx, span);
  481.  
  482.       /* Set the stencil pass/fail flags according to result of depth testing.
  483.        * if oldmask[i] == 0 then
  484.        *    Don't touch the stencil value
  485.        * else if oldmask[i] and newmask[i] then
  486.        *    Depth test passed
  487.        * else
  488.        *    assert(oldmask[i] && !newmask[i])
  489.        *    Depth test failed
  490.        * endif
  491.        */
  492.       for (i=0;i<n;i++) {
  493.          ASSERT(mask[i] == 0 || mask[i] == 1);
  494.          passmask[i] = oldmask[i] & mask[i];
  495.          failmask[i] = oldmask[i] & (mask[i] ^ 1);
  496.       }
  497.  
  498.       /* apply the pass and fail operations */
  499.       if (ctx->Stencil.ZFailFunc[face] != GL_KEEP) {
  500.          apply_stencil_op( ctx, ctx->Stencil.ZFailFunc[face], face,
  501.                            n, stencil, failmask );
  502.       }
  503.       if (ctx->Stencil.ZPassFunc[face] != GL_KEEP) {
  504.          apply_stencil_op( ctx, ctx->Stencil.ZPassFunc[face], face,
  505.                            n, stencil, passmask );
  506.       }
  507.    }
  508.  
  509.    /*
  510.     * Write updated stencil values back into hardware stencil buffer.
  511.     */
  512.    if (swrast->Driver.WriteStencilSpan) {
  513.       ASSERT(stencil == stencilRow);
  514.       (swrast->Driver.WriteStencilSpan)(ctx, n, x, y, stencil, mask );
  515.    }
  516.    
  517.    span->writeAll = GL_FALSE;
  518.    
  519.    return GL_TRUE;  /* one or more fragments passed both tests */
  520. }
  521.  
  522.  
  523.  
  524.  
  525. /**
  526.  * Apply the given stencil operator for each pixel in the array whose
  527.  * mask flag is set.
  528.  * \note  This is for software stencil buffers only.
  529.  * Input:  n - number of pixels in the span
  530.  *         x, y - array of [n] pixels
  531.  *         operator - the stencil buffer operator
  532.  *         mask - array [n] of flag:  1=apply operator, 0=don't apply operator
  533.  */
  534. static void
  535. apply_stencil_op_to_pixels( const GLcontext *ctx,
  536.                             GLuint n, const GLint x[], const GLint y[],
  537.                             GLenum oper, GLuint face, const GLubyte mask[] )
  538. {
  539.    const GLstencil ref = ctx->Stencil.Ref[face];
  540.    const GLstencil wrtmask = ctx->Stencil.WriteMask[face];
  541.    const GLstencil invmask = (GLstencil) (~wrtmask);
  542.    GLuint i;
  543.  
  544.    ASSERT(!SWRAST_CONTEXT(ctx)->Driver.WriteStencilSpan);  /* software stencil buffer only! */
  545.  
  546.    switch (oper) {
  547.       case GL_KEEP:
  548.          /* do nothing */
  549.          break;
  550.       case GL_ZERO:
  551.      if (invmask==0) {
  552.         for (i=0;i<n;i++) {
  553.            if (mask[i]) {
  554.                   GLstencil *sptr = STENCIL_ADDRESS( x[i], y[i] );
  555.                   *sptr = 0;
  556.            }
  557.         }
  558.      }
  559.      else {
  560.         for (i=0;i<n;i++) {
  561.            if (mask[i]) {
  562.                   GLstencil *sptr = STENCIL_ADDRESS( x[i], y[i] );
  563.           *sptr = (GLstencil) (invmask & *sptr);
  564.            }
  565.         }
  566.      }
  567.      break;
  568.       case GL_REPLACE:
  569.      if (invmask==0) {
  570.         for (i=0;i<n;i++) {
  571.            if (mask[i]) {
  572.                   GLstencil *sptr = STENCIL_ADDRESS( x[i], y[i] );
  573.                   *sptr = ref;
  574.            }
  575.         }
  576.      }
  577.      else {
  578.         for (i=0;i<n;i++) {
  579.            if (mask[i]) {
  580.                   GLstencil *sptr = STENCIL_ADDRESS( x[i], y[i] );
  581.           *sptr = (GLstencil) ((invmask & *sptr ) | (wrtmask & ref));
  582.            }
  583.         }
  584.      }
  585.      break;
  586.       case GL_INCR:
  587.      if (invmask==0) {
  588.         for (i=0;i<n;i++) {
  589.            if (mask[i]) {
  590.                   GLstencil *sptr = STENCIL_ADDRESS( x[i], y[i] );
  591.           if (*sptr < STENCIL_MAX) {
  592.              *sptr = (GLstencil) (*sptr + 1);
  593.           }
  594.            }
  595.         }
  596.      }
  597.      else {
  598.         for (i=0;i<n;i++) {
  599.            if (mask[i]) {
  600.                   GLstencil *sptr = STENCIL_ADDRESS( x[i], y[i] );
  601.           if (*sptr < STENCIL_MAX) {
  602.              *sptr = (GLstencil) ((invmask & *sptr) | (wrtmask & (*sptr+1)));
  603.           }
  604.            }
  605.         }
  606.      }
  607.      break;
  608.       case GL_DECR:
  609.      if (invmask==0) {
  610.         for (i=0;i<n;i++) {
  611.            if (mask[i]) {
  612.                   GLstencil *sptr = STENCIL_ADDRESS( x[i], y[i] );
  613.           if (*sptr>0) {
  614.              *sptr = (GLstencil) (*sptr - 1);
  615.           }
  616.            }
  617.         }
  618.      }
  619.      else {
  620.         for (i=0;i<n;i++) {
  621.            if (mask[i]) {
  622.                   GLstencil *sptr = STENCIL_ADDRESS( x[i], y[i] );
  623.           if (*sptr>0) {
  624.              *sptr = (GLstencil) ((invmask & *sptr) | (wrtmask & (*sptr-1)));
  625.           }
  626.            }
  627.         }
  628.      }
  629.      break;
  630.       case GL_INCR_WRAP_EXT:
  631.      if (invmask==0) {
  632.         for (i=0;i<n;i++) {
  633.            if (mask[i]) {
  634.                   GLstencil *sptr = STENCIL_ADDRESS( x[i], y[i] );
  635.                   *sptr = (GLstencil) (*sptr + 1);
  636.            }
  637.         }
  638.      }
  639.      else {
  640.         for (i=0;i<n;i++) {
  641.            if (mask[i]) {
  642.                   GLstencil *sptr = STENCIL_ADDRESS( x[i], y[i] );
  643.                   *sptr = (GLstencil) ((invmask & *sptr) | (wrtmask & (*sptr+1)));
  644.            }
  645.         }
  646.      }
  647.      break;
  648.       case GL_DECR_WRAP_EXT:
  649.      if (invmask==0) {
  650.         for (i=0;i<n;i++) {
  651.            if (mask[i]) {
  652.                   GLstencil *sptr = STENCIL_ADDRESS( x[i], y[i] );
  653.                   *sptr = (GLstencil) (*sptr - 1);
  654.            }
  655.         }
  656.      }
  657.      else {
  658.         for (i=0;i<n;i++) {
  659.            if (mask[i]) {
  660.                   GLstencil *sptr = STENCIL_ADDRESS( x[i], y[i] );
  661.                   *sptr = (GLstencil) ((invmask & *sptr) | (wrtmask & (*sptr-1)));
  662.            }
  663.         }
  664.      }
  665.      break;
  666.       case GL_INVERT:
  667.      if (invmask==0) {
  668.         for (i=0;i<n;i++) {
  669.            if (mask[i]) {
  670.                   GLstencil *sptr = STENCIL_ADDRESS( x[i], y[i] );
  671.                   *sptr = (GLstencil) (~*sptr);
  672.            }
  673.         }
  674.      }
  675.      else {
  676.         for (i=0;i<n;i++) {
  677.            if (mask[i]) {
  678.                   GLstencil *sptr = STENCIL_ADDRESS( x[i], y[i] );
  679.                   *sptr = (GLstencil) ((invmask & *sptr) | (wrtmask & ~*sptr));
  680.            }
  681.         }
  682.      }
  683.      break;
  684.       default:
  685.          _mesa_problem(ctx, "Bad stencilop in apply_stencil_op_to_pixels");
  686.    }
  687. }
  688.  
  689.  
  690.  
  691. /**
  692.  * Apply stencil test to an array of pixels before depth buffering.
  693.  *
  694.  * \note Used for software stencil buffer only.
  695.  * Input:  n - number of pixels in the span
  696.  *         x, y - array of [n] pixels to stencil
  697.  *         mask - array [n] of flag:  0=skip the pixel, 1=stencil the pixel
  698.  * Output:  mask - pixels which fail the stencil test will have their
  699.  *                 mask flag set to 0.
  700.  * \return  GL_FALSE = all pixels failed, GL_TRUE = zero or more pixels passed.
  701.  */
  702. static GLboolean
  703. stencil_test_pixels( GLcontext *ctx, GLuint face, GLuint n,
  704.                      const GLint x[], const GLint y[], GLubyte mask[] )
  705. {
  706.    GLubyte fail[MAX_WIDTH];
  707.    GLstencil r, s;
  708.    GLuint i;
  709.    GLboolean allfail = GL_FALSE;
  710.    const GLuint valueMask = ctx->Stencil.ValueMask[face];
  711.  
  712.   /* software stencil buffer only! */
  713.    ASSERT(ctx->DrawBuffer->UseSoftwareStencilBuffer);
  714.    ASSERT(!SWRAST_CONTEXT(ctx)->Driver.ReadStencilSpan);
  715.    ASSERT(!SWRAST_CONTEXT(ctx)->Driver.WriteStencilSpan);
  716.  
  717.    /*
  718.     * Perform stencil test.  The results of this operation are stored
  719.     * in the fail[] array:
  720.     *   IF fail[i] is non-zero THEN
  721.     *       the stencil fail operator is to be applied
  722.     *   ELSE
  723.     *       the stencil fail operator is not to be applied
  724.     *   ENDIF
  725.     */
  726.  
  727.    switch (ctx->Stencil.Function[face]) {
  728.       case GL_NEVER:
  729.          /* always fail */
  730.          for (i=0;i<n;i++) {
  731.         if (mask[i]) {
  732.            mask[i] = 0;
  733.            fail[i] = 1;
  734.         }
  735.         else {
  736.            fail[i] = 0;
  737.         }
  738.      }
  739.      allfail = GL_TRUE;
  740.      break;
  741.       case GL_LESS:
  742.      r = (GLstencil) (ctx->Stencil.Ref[face] & valueMask);
  743.      for (i=0;i<n;i++) {
  744.         if (mask[i]) {
  745.                GLstencil *sptr = STENCIL_ADDRESS(x[i],y[i]);
  746.            s = (GLstencil) (*sptr & valueMask);
  747.            if (r < s) {
  748.           /* passed */
  749.           fail[i] = 0;
  750.            }
  751.            else {
  752.           fail[i] = 1;
  753.           mask[i] = 0;
  754.            }
  755.         }
  756.         else {
  757.            fail[i] = 0;
  758.         }
  759.      }
  760.      break;
  761.       case GL_LEQUAL:
  762.      r = (GLstencil) (ctx->Stencil.Ref[face] & valueMask);
  763.      for (i=0;i<n;i++) {
  764.         if (mask[i]) {
  765.                GLstencil *sptr = STENCIL_ADDRESS(x[i],y[i]);
  766.            s = (GLstencil) (*sptr & valueMask);
  767.            if (r <= s) {
  768.           /* pass */
  769.           fail[i] = 0;
  770.            }
  771.            else {
  772.           fail[i] = 1;
  773.           mask[i] = 0;
  774.            }
  775.         }
  776.         else {
  777.            fail[i] = 0;
  778.         }
  779.      }
  780.      break;
  781.       case GL_GREATER:
  782.      r = (GLstencil) (ctx->Stencil.Ref[face] & valueMask);
  783.      for (i=0;i<n;i++) {
  784.         if (mask[i]) {
  785.                GLstencil *sptr = STENCIL_ADDRESS(x[i],y[i]);
  786.            s = (GLstencil) (*sptr & valueMask);
  787.            if (r > s) {
  788.           /* passed */
  789.           fail[i] = 0;
  790.            }
  791.            else {
  792.           fail[i] = 1;
  793.           mask[i] = 0;
  794.            }
  795.         }
  796.         else {
  797.            fail[i] = 0;
  798.         }
  799.      }
  800.      break;
  801.       case GL_GEQUAL:
  802.      r = (GLstencil) (ctx->Stencil.Ref[face] & valueMask);
  803.      for (i=0;i<n;i++) {
  804.         if (mask[i]) {
  805.                GLstencil *sptr = STENCIL_ADDRESS(x[i],y[i]);
  806.            s = (GLstencil) (*sptr & valueMask);
  807.            if (r >= s) {
  808.           /* passed */
  809.           fail[i] = 0;
  810.            }
  811.            else {
  812.           fail[i] = 1;
  813.           mask[i] = 0;
  814.            }
  815.         }
  816.         else {
  817.            fail[i] = 0;
  818.         }
  819.      }
  820.      break;
  821.       case GL_EQUAL:
  822.      r = (GLstencil) (ctx->Stencil.Ref[face] & valueMask);
  823.      for (i=0;i<n;i++) {
  824.         if (mask[i]) {
  825.                GLstencil *sptr = STENCIL_ADDRESS(x[i],y[i]);
  826.            s = (GLstencil) (*sptr & valueMask);
  827.            if (r == s) {
  828.           /* passed */
  829.           fail[i] = 0;
  830.            }
  831.            else {
  832.           fail[i] = 1;
  833.           mask[i] = 0;
  834.            }
  835.         }
  836.         else {
  837.            fail[i] = 0;
  838.         }
  839.      }
  840.      break;
  841.       case GL_NOTEQUAL:
  842.      r = (GLstencil) (ctx->Stencil.Ref[face] & valueMask);
  843.      for (i=0;i<n;i++) {
  844.         if (mask[i]) {
  845.                GLstencil *sptr = STENCIL_ADDRESS(x[i],y[i]);
  846.            s = (GLstencil) (*sptr & valueMask);
  847.            if (r != s) {
  848.           /* passed */
  849.           fail[i] = 0;
  850.            }
  851.            else {
  852.           fail[i] = 1;
  853.           mask[i] = 0;
  854.            }
  855.         }
  856.         else {
  857.            fail[i] = 0;
  858.         }
  859.      }
  860.      break;
  861.       case GL_ALWAYS:
  862.      /* always pass */
  863.      for (i=0;i<n;i++) {
  864.         fail[i] = 0;
  865.      }
  866.      break;
  867.       default:
  868.          _mesa_problem(ctx, "Bad stencil func in gl_stencil_pixels");
  869.          return 0;
  870.    }
  871.  
  872.    if (ctx->Stencil.FailFunc[face] != GL_KEEP) {
  873.       apply_stencil_op_to_pixels( ctx, n, x, y, ctx->Stencil.FailFunc[face],
  874.                                   face, fail );
  875.    }
  876.  
  877.    return !allfail;
  878. }
  879.  
  880.  
  881.  
  882.  
  883. /**
  884.  * Apply stencil and depth testing to an array of pixels.
  885.  * This is used both for software and hardware stencil buffers.
  886.  *
  887.  * The comments in this function are a bit sparse but the code is
  888.  * almost identical to stencil_and_ztest_span(), which is well
  889.  * commented.
  890.  *
  891.  * Input:  n - number of pixels in the array
  892.  *         x, y - array of [n] pixel positions
  893.  *         z - array [n] of z values
  894.  *         mask - array [n] of flags  (1=test this pixel, 0=skip the pixel)
  895.  * Output: mask - array [n] of flags (1=stencil and depth test passed)
  896.  * Return: GL_FALSE - all fragments failed the testing
  897.  *         GL_TRUE - one or more fragments passed the testing
  898.  */
  899. static GLboolean
  900. stencil_and_ztest_pixels( GLcontext *ctx, struct sw_span *span, GLuint face )
  901. {
  902.    const GLuint n = span->end;
  903.    const GLint *x = span->array->x;
  904.    const GLint *y = span->array->y;
  905.    GLubyte *mask = span->array->mask;
  906.    SWcontext *swrast = SWRAST_CONTEXT(ctx);
  907.  
  908.    ASSERT(span->arrayMask & SPAN_XY);
  909.    ASSERT(ctx->Stencil.Enabled);
  910.    ASSERT(n <= MAX_WIDTH);
  911.  
  912.    if (swrast->Driver.WriteStencilPixels) {
  913.       /*** Hardware stencil buffer ***/
  914.       GLstencil stencil[MAX_WIDTH];
  915.       GLubyte origMask[MAX_WIDTH];
  916.  
  917.       ASSERT(!ctx->DrawBuffer->UseSoftwareStencilBuffer);
  918.       ASSERT(swrast->Driver.ReadStencilPixels);
  919.       (*swrast->Driver.ReadStencilPixels)(ctx, n, x, y, stencil);
  920.  
  921.       MEMCPY(origMask, mask, n * sizeof(GLubyte));
  922.  
  923.       (void) do_stencil_test(ctx, face, n, stencil, mask);
  924.  
  925.       if (ctx->Depth.Test == GL_FALSE) {
  926.          apply_stencil_op(ctx, ctx->Stencil.ZPassFunc[face], face,
  927.                           n, stencil, mask);
  928.       }
  929.       else {
  930.          _mesa_depth_test_span(ctx, span);
  931.  
  932.          if (ctx->Stencil.ZFailFunc[face] != GL_KEEP) {
  933.             GLubyte failmask[MAX_WIDTH];
  934.             GLuint i;
  935.             for (i = 0; i < n; i++) {
  936.                ASSERT(mask[i] == 0 || mask[i] == 1);
  937.                failmask[i] = origMask[i] & (mask[i] ^ 1);
  938.             }
  939.             apply_stencil_op(ctx, ctx->Stencil.ZFailFunc[face], face,
  940.                              n, stencil, failmask);
  941.          }
  942.          if (ctx->Stencil.ZPassFunc[face] != GL_KEEP) {
  943.             GLubyte passmask[MAX_WIDTH];
  944.             GLuint i;
  945.             for (i = 0; i < n; i++) {
  946.                ASSERT(mask[i] == 0 || mask[i] == 1);
  947.                passmask[i] = origMask[i] & mask[i];
  948.             }
  949.             apply_stencil_op(ctx, ctx->Stencil.ZPassFunc[face], face,
  950.                              n, stencil, passmask);
  951.          }
  952.       }
  953.  
  954.       /* Write updated stencil values into hardware stencil buffer */
  955.       (swrast->Driver.WriteStencilPixels)(ctx, n, x, y, stencil, origMask);
  956.  
  957.       return GL_TRUE;
  958.    }
  959.    else {
  960.       /*** Software stencil buffer ***/
  961.  
  962.       ASSERT(ctx->DrawBuffer->UseSoftwareStencilBuffer);
  963.  
  964.       if (stencil_test_pixels(ctx, face, n, x, y, mask) == GL_FALSE) {
  965.          /* all fragments failed the stencil test, we're done. */
  966.          return GL_FALSE;
  967.       }
  968.  
  969.       if (ctx->Depth.Test==GL_FALSE) {
  970.          apply_stencil_op_to_pixels(ctx, n, x, y,
  971.                                     ctx->Stencil.ZPassFunc[face], face, mask);
  972.       }
  973.       else {
  974.          GLubyte passmask[MAX_WIDTH], failmask[MAX_WIDTH], oldmask[MAX_WIDTH];
  975.          GLuint i;
  976.  
  977.          MEMCPY(oldmask, mask, n * sizeof(GLubyte));
  978.  
  979.          _mesa_depth_test_span(ctx, span);
  980.  
  981.          for (i=0;i<n;i++) {
  982.             ASSERT(mask[i] == 0 || mask[i] == 1);
  983.             passmask[i] = oldmask[i] & mask[i];
  984.             failmask[i] = oldmask[i] & (mask[i] ^ 1);
  985.          }
  986.  
  987.          if (ctx->Stencil.ZFailFunc[face] != GL_KEEP) {
  988.             apply_stencil_op_to_pixels(ctx, n, x, y,
  989.                                        ctx->Stencil.ZFailFunc[face],
  990.                                        face, failmask);
  991.          }
  992.          if (ctx->Stencil.ZPassFunc[face] != GL_KEEP) {
  993.             apply_stencil_op_to_pixels(ctx, n, x, y,
  994.                                        ctx->Stencil.ZPassFunc[face],
  995.                                        face, passmask);
  996.          }
  997.       }
  998.  
  999.       return GL_TRUE;  /* one or more fragments passed both tests */
  1000.    }
  1001. }
  1002.  
  1003.  
  1004. /**
  1005.  * /return GL_TRUE = one or more fragments passed,
  1006.  * GL_FALSE = all fragments failed.
  1007.  */
  1008. GLboolean
  1009. _mesa_stencil_and_ztest_span(GLcontext *ctx, struct sw_span *span)
  1010. {
  1011.    /* span->facing can only be non-zero if using two-sided stencil */
  1012.    ASSERT(ctx->Stencil.TestTwoSide || span->facing == 0);
  1013.    if (span->arrayMask & SPAN_XY)
  1014.       return stencil_and_ztest_pixels(ctx, span, span->facing);
  1015.    else
  1016.       return stencil_and_ztest_span(ctx, span, span->facing);
  1017. }
  1018.  
  1019.  
  1020. /**
  1021.  * Return a span of stencil values from the stencil buffer.
  1022.  * Used for glRead/CopyPixels
  1023.  * Input:  n - how many pixels
  1024.  *         x,y - location of first pixel
  1025.  * Output:  stencil - the array of stencil values
  1026.  */
  1027. void
  1028. _mesa_read_stencil_span( GLcontext *ctx,
  1029.                          GLint n, GLint x, GLint y, GLstencil stencil[] )
  1030. {
  1031.    SWcontext *swrast = SWRAST_CONTEXT(ctx);
  1032.    const GLint bufWidth = (GLint) ctx->DrawBuffer->Width;
  1033.    const GLint bufHeight = (GLint) ctx->DrawBuffer->Height;
  1034.  
  1035.    if (y < 0 || y >= bufHeight || x + n <= 0 || x >= bufWidth) {
  1036.       /* span is completely outside framebuffer */
  1037.       return; /* undefined values OK */
  1038.    }
  1039.  
  1040.    if (x < 0) {
  1041.       GLint dx = -x;
  1042.       x = 0;
  1043.       n -= dx;
  1044.       stencil += dx;
  1045.    }
  1046.    if (x + n > bufWidth) {
  1047.       GLint dx = x + n - bufWidth;
  1048.       n -= dx;
  1049.    }
  1050.    if (n <= 0) {
  1051.       return;
  1052.    }
  1053.  
  1054.  
  1055.    ASSERT(n >= 0);
  1056.    if (swrast->Driver.ReadStencilSpan) {
  1057.       (*swrast->Driver.ReadStencilSpan)( ctx, (GLuint) n, x, y, stencil );
  1058.    }
  1059.    else if (ctx->DrawBuffer->Stencil) {
  1060.       const GLstencil *s = STENCIL_ADDRESS( x, y );
  1061. #if STENCIL_BITS == 8
  1062.       MEMCPY( stencil, s, n * sizeof(GLstencil) );
  1063. #else
  1064.       GLuint i;
  1065.       for (i=0;i<n;i++)
  1066.          stencil[i] = s[i];
  1067. #endif
  1068.    }
  1069. }
  1070.  
  1071.  
  1072.  
  1073. /**
  1074.  * Write a span of stencil values to the stencil buffer.
  1075.  * Used for glDraw/CopyPixels
  1076.  * Input:  n - how many pixels
  1077.  *         x, y - location of first pixel
  1078.  *         stencil - the array of stencil values
  1079.  */
  1080. void
  1081. _mesa_write_stencil_span( GLcontext *ctx, GLint n, GLint x, GLint y,
  1082.                           const GLstencil stencil[] )
  1083. {
  1084.    SWcontext *swrast = SWRAST_CONTEXT(ctx);
  1085.    const GLstencil *ssrc = stencil;
  1086.    const GLint bufWidth = (GLint) ctx->DrawBuffer->Width;
  1087.    const GLint bufHeight = (GLint) ctx->DrawBuffer->Height;
  1088.  
  1089.    if (y < 0 || y >= bufHeight || x + n <= 0 || x >= bufWidth) {
  1090.       /* span is completely outside framebuffer */
  1091.       return; /* undefined values OK */
  1092.    }
  1093.  
  1094.    if (x < 0) {
  1095.       GLint dx = -x;
  1096.       x = 0;
  1097.       n -= dx;
  1098.       ssrc += dx;
  1099.    }
  1100.    if (x + n > bufWidth) {
  1101.       GLint dx = x + n - bufWidth;
  1102.       n -= dx;
  1103.    }
  1104.    if (n <= 0) {
  1105.       return;
  1106.    }
  1107.  
  1108.    if (swrast->Driver.WriteStencilSpan) {
  1109.       (*swrast->Driver.WriteStencilSpan)( ctx, n, x, y, ssrc, NULL );
  1110.    }
  1111.    else if (ctx->DrawBuffer->Stencil) {
  1112.       GLstencil *s = STENCIL_ADDRESS( x, y );
  1113. #if STENCIL_BITS == 8
  1114.       MEMCPY( s, ssrc, n * sizeof(GLstencil) );
  1115. #else
  1116.       GLuint i;
  1117.       for (i=0;i<n;i++)
  1118.          s[i] = ssrc[i];
  1119. #endif
  1120.    }
  1121. }
  1122.  
  1123.  
  1124.  
  1125. /**
  1126.  * Allocate a new stencil buffer.  If there's an old one it will be
  1127.  * deallocated first.  The new stencil buffer will be uninitialized.
  1128.  */
  1129. void
  1130. _mesa_alloc_stencil_buffer( GLframebuffer *buffer )
  1131. {
  1132.    /* deallocate current stencil buffer if present */
  1133.    if (buffer->Stencil) {
  1134.       MESA_PBUFFER_FREE(buffer->Stencil);
  1135.       buffer->Stencil = NULL;
  1136.    }
  1137.  
  1138.    /* allocate new stencil buffer */
  1139.    buffer->Stencil = (GLstencil *)
  1140.       MESA_PBUFFER_ALLOC(buffer->Width * buffer->Height * sizeof(GLstencil));
  1141.    if (!buffer->Stencil) {
  1142.       /* out of memory */
  1143.       _mesa_error( NULL, GL_OUT_OF_MEMORY, "_mesa_alloc_stencil_buffer" );
  1144.    }
  1145. }
  1146.  
  1147.  
  1148.  
  1149. /**
  1150.  * Clear the software (malloc'd) stencil buffer.
  1151.  */
  1152. static void
  1153. clear_software_stencil_buffer( GLcontext *ctx )
  1154. {
  1155.    if (ctx->Visual.stencilBits==0 || !ctx->DrawBuffer->Stencil) {
  1156.       /* no stencil buffer */
  1157.       return;
  1158.    }
  1159.  
  1160.    if (ctx->Scissor.Enabled) {
  1161.       /* clear scissor region only */
  1162.       const GLint width = ctx->DrawBuffer->_Xmax - ctx->DrawBuffer->_Xmin;
  1163.       if (ctx->Stencil.WriteMask[0] != STENCIL_MAX) {
  1164.          /* must apply mask to the clear */
  1165.          GLint y;
  1166.          for (y = ctx->DrawBuffer->_Ymin; y < ctx->DrawBuffer->_Ymax; y++) {
  1167.             const GLstencil mask = ctx->Stencil.WriteMask[0];
  1168.             const GLstencil invMask = ~mask;
  1169.             const GLstencil clearVal = (ctx->Stencil.Clear & mask);
  1170.             GLstencil *stencil = STENCIL_ADDRESS( ctx->DrawBuffer->_Xmin, y );
  1171.             GLint i;
  1172.             for (i = 0; i < width; i++) {
  1173.                stencil[i] = (stencil[i] & invMask) | clearVal;
  1174.             }
  1175.          }
  1176.       }
  1177.       else {
  1178.          /* no masking */
  1179.          GLint y;
  1180.          for (y = ctx->DrawBuffer->_Ymin; y < ctx->DrawBuffer->_Ymax; y++) {
  1181.             GLstencil *stencil = STENCIL_ADDRESS( ctx->DrawBuffer->_Xmin, y );
  1182. #if STENCIL_BITS==8
  1183.             MEMSET( stencil, ctx->Stencil.Clear, width * sizeof(GLstencil) );
  1184. #else
  1185.             GLint i;
  1186.             for (i = 0; i < width; i++)
  1187.                stencil[x] = ctx->Stencil.Clear;
  1188. #endif
  1189.          }
  1190.       }
  1191.    }
  1192.    else {
  1193.       /* clear whole stencil buffer */
  1194.       if (ctx->Stencil.WriteMask[0] != STENCIL_MAX) {
  1195.          /* must apply mask to the clear */
  1196.          const GLuint n = ctx->DrawBuffer->Width * ctx->DrawBuffer->Height;
  1197.          GLstencil *stencil = ctx->DrawBuffer->Stencil;
  1198.          const GLstencil mask = ctx->Stencil.WriteMask[0];
  1199.          const GLstencil invMask = ~mask;
  1200.          const GLstencil clearVal = (ctx->Stencil.Clear & mask);
  1201.          GLuint i;
  1202.          for (i = 0; i < n; i++) {
  1203.             stencil[i] = (stencil[i] & invMask) | clearVal;
  1204.          }
  1205.       }
  1206.       else {
  1207.          /* clear whole buffer without masking */
  1208.          const GLuint n = ctx->DrawBuffer->Width * ctx->DrawBuffer->Height;
  1209.          GLstencil *stencil = ctx->DrawBuffer->Stencil;
  1210.  
  1211. #if STENCIL_BITS==8
  1212.          MEMSET(stencil, ctx->Stencil.Clear, n * sizeof(GLstencil) );
  1213. #else
  1214.          GLuint i;
  1215.          for (i = 0; i < n; i++) {
  1216.             stencil[i] = ctx->Stencil.Clear;
  1217.          }
  1218. #endif
  1219.       }
  1220.    }
  1221. }
  1222.  
  1223.  
  1224.  
  1225. /**
  1226.  * Clear the hardware (in graphics card) stencil buffer.
  1227.  * This is done with the Driver.WriteStencilSpan() and Driver.ReadStencilSpan()
  1228.  * functions.
  1229.  * Actually, if there is a hardware stencil buffer it really should have
  1230.  * been cleared in Driver.Clear()!  However, if the hardware does not
  1231.  * support scissored clears or masked clears (i.e. glStencilMask) then
  1232.  * we have to use the span-based functions.
  1233.  */
  1234. static void
  1235. clear_hardware_stencil_buffer( GLcontext *ctx )
  1236. {
  1237.    SWcontext *swrast = SWRAST_CONTEXT(ctx);
  1238.    ASSERT(swrast->Driver.WriteStencilSpan);
  1239.    ASSERT(swrast->Driver.ReadStencilSpan);
  1240.  
  1241.    if (ctx->Scissor.Enabled) {
  1242.       /* clear scissor region only */
  1243.       const GLint x = ctx->DrawBuffer->_Xmin;
  1244.       const GLint width = ctx->DrawBuffer->_Xmax - ctx->DrawBuffer->_Xmin;
  1245.       if (ctx->Stencil.WriteMask[0] != STENCIL_MAX) {
  1246.          /* must apply mask to the clear */
  1247.          GLint y;
  1248.          for (y = ctx->DrawBuffer->_Ymin; y < ctx->DrawBuffer->_Ymax; y++) {
  1249.             const GLstencil mask = ctx->Stencil.WriteMask[0];
  1250.             const GLstencil invMask = ~mask;
  1251.             const GLstencil clearVal = (ctx->Stencil.Clear & mask);
  1252.             GLstencil stencil[MAX_WIDTH];
  1253.             GLint i;
  1254.             (*swrast->Driver.ReadStencilSpan)(ctx, width, x, y, stencil);
  1255.             for (i = 0; i < width; i++) {
  1256.                stencil[i] = (stencil[i] & invMask) | clearVal;
  1257.             }
  1258.             (*swrast->Driver.WriteStencilSpan)(ctx, width, x, y, stencil, NULL);
  1259.          }
  1260.       }
  1261.       else {
  1262.          /* no masking */
  1263.          GLstencil stencil[MAX_WIDTH];
  1264.          GLint y, i;
  1265.          for (i = 0; i < width; i++) {
  1266.             stencil[i] = ctx->Stencil.Clear;
  1267.          }
  1268.          for (y = ctx->DrawBuffer->_Ymin; y < ctx->DrawBuffer->_Ymax; y++) {
  1269.             (*swrast->Driver.WriteStencilSpan)(ctx, width, x, y, stencil, NULL);
  1270.          }
  1271.       }
  1272.    }
  1273.    else {
  1274.       /* clear whole stencil buffer */
  1275.       if (ctx->Stencil.WriteMask[0] != STENCIL_MAX) {
  1276.          /* must apply mask to the clear */
  1277.          const GLstencil mask = ctx->Stencil.WriteMask[0];
  1278.          const GLstencil invMask = ~mask;
  1279.          const GLstencil clearVal = (ctx->Stencil.Clear & mask);
  1280.          const GLint width = ctx->DrawBuffer->Width;
  1281.          const GLint height = ctx->DrawBuffer->Height;
  1282.          const GLint x = ctx->DrawBuffer->_Xmin;
  1283.          GLint y;
  1284.          for (y = 0; y < height; y++) {
  1285.             GLstencil stencil[MAX_WIDTH];
  1286.             GLint i;
  1287.             (*swrast->Driver.ReadStencilSpan)(ctx, width, x, y, stencil);
  1288.             for (i = 0; i < width; i++) {
  1289.                stencil[i] = (stencil[i] & invMask) | clearVal;
  1290.             }
  1291.             (*swrast->Driver.WriteStencilSpan)(ctx, width, x, y, stencil, NULL);
  1292.          }
  1293.       }
  1294.       else {
  1295.          /* clear whole buffer without masking */
  1296.          const GLint width = ctx->DrawBuffer->Width;
  1297.          const GLint height = ctx->DrawBuffer->Height;
  1298.          const GLint x = ctx->DrawBuffer->_Xmin;
  1299.          GLstencil stencil[MAX_WIDTH];
  1300.          GLint y, i;
  1301.          for (i = 0; i < width; i++) {
  1302.             stencil[i] = ctx->Stencil.Clear;
  1303.          }
  1304.          for (y = 0; y < height; y++) {
  1305.             (*swrast->Driver.WriteStencilSpan)(ctx, width, x, y, stencil, NULL);
  1306.          }
  1307.       }
  1308.    }
  1309. }
  1310.  
  1311.  
  1312.  
  1313. /**
  1314.  * Clear the stencil buffer (hardware or software).
  1315.  */
  1316. void
  1317. _mesa_clear_stencil_buffer( GLcontext *ctx )
  1318. {
  1319.    SWcontext *swrast = SWRAST_CONTEXT(ctx);
  1320.    if (swrast->Driver.WriteStencilSpan) {
  1321.       ASSERT(swrast->Driver.ReadStencilSpan);
  1322.       clear_hardware_stencil_buffer(ctx);
  1323.    }
  1324.    else {
  1325.       clear_software_stencil_buffer(ctx);
  1326.    }
  1327. }
  1328.