home *** CD-ROM | disk | FTP | other *** search
/ AmigActive 6 / AACD06.ISO / AACD / System / Mesa-3.1 / src / stencil.c < prev    next >
C/C++ Source or Header  |  2000-01-07  |  28KB  |  1,139 lines

  1. /* $Id: stencil.c,v 1.8.2.1 1999/12/04 21:15:31 brianp Exp $ */
  2.  
  3. /*
  4.  * Mesa 3-D graphics library
  5.  * Version:  3.1
  6.  * 
  7.  * Copyright (C) 1999  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. /* $XFree86: xc/lib/GL/mesa/src/stencil.c,v 1.3 1999/04/04 00:20:32 dawes Exp $ */
  29.  
  30. #ifdef PC_HEADER
  31. #include "all.h"
  32. #else
  33. #ifndef XFree86Server
  34. #include <stdlib.h>
  35. #include <string.h>
  36. #else
  37. #include "GL/xf86glx.h"
  38. #endif
  39. #include "context.h"
  40. #include "macros.h"
  41. #include "pb.h"
  42. #include "stencil.h"
  43. #include "types.h"
  44. #include "enable.h"
  45. #endif
  46.  
  47.  
  48.  
  49. /*
  50.  * Return the address of a stencil buffer value given the window coords:
  51.  */
  52. #define STENCIL_ADDRESS(X,Y)  (ctx->Buffer->Stencil + ctx->Buffer->Width * (Y) + (X))
  53.  
  54.  
  55. void gl_ClearStencil( GLcontext *ctx, GLint s )
  56. {
  57.    ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glClearStencil");
  58.    ctx->Stencil.Clear = (GLstencil) s;
  59.  
  60.    if (ctx->Driver.ClearStencil) {
  61.       (*ctx->Driver.ClearStencil)( ctx, s );
  62.    }
  63. }
  64.  
  65.  
  66.  
  67. void gl_StencilFunc( GLcontext *ctx, GLenum func, GLint ref, GLuint mask )
  68. {
  69.    GLint maxref;
  70.  
  71.    ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glStencilFunc");
  72.  
  73.    switch (func) {
  74.       case GL_NEVER:
  75.       case GL_LESS:
  76.       case GL_LEQUAL:
  77.       case GL_GREATER:
  78.       case GL_GEQUAL:
  79.       case GL_EQUAL:
  80.       case GL_NOTEQUAL:
  81.       case GL_ALWAYS:
  82.          ctx->Stencil.Function = func;
  83.          break;
  84.       default:
  85.          gl_error( ctx, GL_INVALID_ENUM, "glStencilFunc" );
  86.          return;
  87.    }
  88.  
  89.    maxref = (1 << STENCIL_BITS) - 1;
  90.    ctx->Stencil.Ref = (GLstencil) CLAMP( ref, 0, maxref );
  91.    ctx->Stencil.ValueMask = (GLstencil) mask;
  92.  
  93.    if (ctx->Driver.StencilFunc) {
  94.       (*ctx->Driver.StencilFunc)( ctx, func, ctx->Stencil.Ref, mask );
  95.    }
  96. }
  97.  
  98.  
  99.  
  100. void gl_StencilMask( GLcontext *ctx, GLuint mask )
  101. {
  102.    ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glStencilMask");
  103.    ctx->Stencil.WriteMask = (GLstencil) mask;
  104.  
  105.    if (ctx->Driver.StencilMask) {
  106.       (*ctx->Driver.StencilMask)( ctx, mask );
  107.    }
  108. }
  109.  
  110.  
  111.  
  112. void gl_StencilOp( GLcontext *ctx, GLenum fail, GLenum zfail, GLenum zpass )
  113. {
  114.    ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glStencilOp");
  115.    switch (fail) {
  116.       case GL_KEEP:
  117.       case GL_ZERO:
  118.       case GL_REPLACE:
  119.       case GL_INCR:
  120.       case GL_DECR:
  121.       case GL_INVERT:
  122.       case GL_INCR_WRAP_EXT:
  123.       case GL_DECR_WRAP_EXT:
  124.          ctx->Stencil.FailFunc = fail;
  125.          break;
  126.       default:
  127.          gl_error( ctx, GL_INVALID_ENUM, "glStencilOp" );
  128.          return;
  129.    }
  130.    switch (zfail) {
  131.       case GL_KEEP:
  132.       case GL_ZERO:
  133.       case GL_REPLACE:
  134.       case GL_INCR:
  135.       case GL_DECR:
  136.       case GL_INVERT:
  137.       case GL_INCR_WRAP_EXT:
  138.       case GL_DECR_WRAP_EXT:
  139.          ctx->Stencil.ZFailFunc = zfail;
  140.          break;
  141.       default:
  142.          gl_error( ctx, GL_INVALID_ENUM, "glStencilOp" );
  143.          return;
  144.    }
  145.    switch (zpass) {
  146.       case GL_KEEP:
  147.       case GL_ZERO:
  148.       case GL_REPLACE:
  149.       case GL_INCR:
  150.       case GL_DECR:
  151.       case GL_INVERT:
  152.       case GL_INCR_WRAP_EXT:
  153.       case GL_DECR_WRAP_EXT:
  154.          ctx->Stencil.ZPassFunc = zpass;
  155.          break;
  156.       default:
  157.          gl_error( ctx, GL_INVALID_ENUM, "glStencilOp" );
  158.          return;
  159.    }
  160.  
  161.    if (ctx->Driver.StencilOp) {
  162.       (*ctx->Driver.StencilOp)( ctx, fail, zfail, zpass );
  163.    }
  164. }
  165.  
  166.  
  167.  
  168. /* Stencil Logic:
  169.  
  170. IF stencil test fails THEN
  171.    Apply fail-op to stencil value   
  172.    Don't write the pixel (RGBA,Z)
  173. ELSE
  174.    IF doing depth test && depth test fails THEN
  175.       Apply zfail-op to stencil value   
  176.       Write RGBA and Z to appropriate buffers
  177.    ELSE
  178.       Apply zpass-op to stencil value
  179. ENDIF
  180.  
  181. */
  182.  
  183.  
  184.  
  185.  
  186. /*
  187.  * Apply the given stencil operator to the array of stencil values.
  188.  * Don't touch stencil[i] if mask[i] is zero.
  189.  * Input:  n - number of pixels in the span
  190.  *         oper - the stencil buffer operator
  191.  *         stencil - array of stencil values
  192.  *         mask - array [n] of flag:  1=apply operator, 0=don't apply operator
  193.  */
  194. static void apply_stencil_op( GLcontext *ctx, GLenum oper,
  195.                               GLuint n, GLstencil stencil[], GLubyte mask[] )
  196. {
  197.    const GLstencil ref = ctx->Stencil.Ref;
  198.    const GLstencil wrtmask = ctx->Stencil.WriteMask;
  199.    const GLstencil invmask = (GLstencil) (~ctx->Stencil.WriteMask);
  200.    GLuint i;
  201.  
  202.    switch (oper) {
  203.       case GL_KEEP:
  204.          /* do nothing */
  205.          break;
  206.       case GL_ZERO:
  207.      if (invmask==0) {
  208.         for (i=0;i<n;i++) {
  209.            if (mask[i]) {
  210.           stencil[i] = 0;
  211.            }
  212.         }
  213.      }
  214.      else {
  215.         for (i=0;i<n;i++) {
  216.            if (mask[i]) {
  217.           stencil[i] = (GLstencil) (stencil[i] & invmask);
  218.            }
  219.         }
  220.      }
  221.      break;
  222.       case GL_REPLACE:
  223.      if (invmask==0) {
  224.         for (i=0;i<n;i++) {
  225.            if (mask[i]) {
  226.                   stencil[i] = ref;
  227.            }
  228.         }
  229.      }
  230.      else {
  231.         for (i=0;i<n;i++) {
  232.            if (mask[i]) {
  233.           GLstencil s = stencil[i];
  234.           stencil[i] = (GLstencil) ((invmask & s ) | (wrtmask & ref));
  235.            }
  236.         }
  237.      }
  238.      break;
  239.       case GL_INCR:
  240.      if (invmask==0) {
  241.         for (i=0;i<n;i++) {
  242.            if (mask[i]) {
  243.           GLstencil s = stencil[i];
  244.           if (s < STENCIL_MAX) {
  245.              stencil[i] = (GLstencil) (s+1);
  246.           }
  247.            }
  248.         }
  249.      }
  250.      else {
  251.         for (i=0;i<n;i++) {
  252.            if (mask[i]) {
  253.           /* VERIFY logic of adding 1 to a write-masked value */
  254.           GLstencil s = stencil[i];
  255.           if (s < STENCIL_MAX) {
  256.              stencil[i] = (GLstencil) ((invmask & s) | (wrtmask & (s+1)));
  257.           }
  258.            }
  259.         }
  260.      }
  261.      break;
  262.       case GL_DECR:
  263.      if (invmask==0) {
  264.         for (i=0;i<n;i++) {
  265.            if (mask[i]) {
  266.           GLstencil s = stencil[i];
  267.           if (s>0) {
  268.              stencil[i] = (GLstencil) (s-1);
  269.           }
  270.            }
  271.         }
  272.      }
  273.      else {
  274.         for (i=0;i<n;i++) {
  275.            if (mask[i]) {
  276.           /* VERIFY logic of subtracting 1 to a write-masked value */
  277.           GLstencil s = stencil[i];
  278.           if (s>0) {
  279.              stencil[i] = (GLstencil) ((invmask & s) | (wrtmask & (s-1)));
  280.           }
  281.            }
  282.         }
  283.      }
  284.      break;
  285.       case GL_INCR_WRAP_EXT:
  286.      if (invmask==0) {
  287.         for (i=0;i<n;i++) {
  288.            if (mask[i]) {
  289.                   stencil[i]++;
  290.            }
  291.         }
  292.      }
  293.      else {
  294.         for (i=0;i<n;i++) {
  295.            if (mask[i]) {
  296.                   GLstencil s = stencil[i];
  297.                   stencil[i] = (GLstencil) ((invmask & s) | (wrtmask & (stencil[i]+1)));
  298.            }
  299.         }
  300.      }
  301.      break;
  302.       case GL_DECR_WRAP_EXT:
  303.      if (invmask==0) {
  304.         for (i=0;i<n;i++) {
  305.            if (mask[i]) {
  306.           stencil[i]--;
  307.            }
  308.         }
  309.      }
  310.      else {
  311.         for (i=0;i<n;i++) {
  312.            if (mask[i]) {
  313.                   GLstencil s = stencil[i];
  314.                   stencil[i] = (GLstencil) ((invmask & s) | (wrtmask & (stencil[i]-1)));
  315.            }
  316.         }
  317.      }
  318.      break;
  319.       case GL_INVERT:
  320.      if (invmask==0) {
  321.         for (i=0;i<n;i++) {
  322.            if (mask[i]) {
  323.           GLstencil s = stencil[i];
  324.           stencil[i] = (GLstencil) ~s;
  325.            }
  326.         }
  327.      }
  328.      else {
  329.         for (i=0;i<n;i++) {
  330.            if (mask[i]) {
  331.           GLstencil s = stencil[i];
  332.           stencil[i] = (GLstencil) ((invmask & s) | (wrtmask & ~s));
  333.            }
  334.         }
  335.      }
  336.      break;
  337.       default:
  338.          gl_problem(ctx, "Bad stencil op in apply_stencil_op");
  339.    }
  340. }
  341.  
  342.  
  343.  
  344.  
  345. /*
  346.  * Apply stencil test to a span of pixels before depth buffering.
  347.  * Input:  n - number of pixels in the span
  348.  *         x, y - coordinate of left-most pixel in the span
  349.  *         mask - array [n] of flag:  0=skip the pixel, 1=stencil the pixel
  350.  * Output:  mask - pixels which fail the stencil test will have their
  351.  *                 mask flag set to 0.
  352.  * Return:  0 = all pixels failed, 1 = zero or more pixels passed.
  353.  */
  354. GLint gl_stencil_span( GLcontext *ctx,
  355.                        GLuint n, GLint x, GLint y, GLubyte mask[] )
  356. {
  357.    GLubyte fail[MAX_WIDTH];
  358.    GLint allfail = 0;
  359.    GLuint i;
  360.    GLstencil r, s;
  361.    GLstencil *stencil;
  362.  
  363.    stencil = STENCIL_ADDRESS( x, y );
  364.  
  365.    /*
  366.     * Perform stencil test.  The results of this operation are stored
  367.     * in the fail[] array:
  368.     *   IF fail[i] is non-zero THEN
  369.     *       the stencil fail operator is to be applied
  370.     *   ELSE
  371.     *       the stencil fail operator is not to be applied
  372.     *   ENDIF
  373.     */
  374.    switch (ctx->Stencil.Function) {
  375.       case GL_NEVER:
  376.          /* always fail */
  377.          for (i=0;i<n;i++) {
  378.         if (mask[i]) {
  379.            mask[i] = 0;
  380.            fail[i] = 1;
  381.         }
  382.         else {
  383.            fail[i] = 0;
  384.         }
  385.      }
  386.      allfail = 1;
  387.      break;
  388.       case GL_LESS:
  389.      r = (GLstencil) (ctx->Stencil.Ref & ctx->Stencil.ValueMask);
  390.      for (i=0;i<n;i++) {
  391.         if (mask[i]) {
  392.            s = (GLstencil) (stencil[i] & ctx->Stencil.ValueMask);
  393.            if (r < s) {
  394.           /* passed */
  395.           fail[i] = 0;
  396.            }
  397.            else {
  398.           fail[i] = 1;
  399.           mask[i] = 0;
  400.            }
  401.         }
  402.         else {
  403.            fail[i] = 0;
  404.         }
  405.      }
  406.      break;
  407.       case GL_LEQUAL:
  408.      r = (GLstencil) (ctx->Stencil.Ref & ctx->Stencil.ValueMask);
  409.      for (i=0;i<n;i++) {
  410.         if (mask[i]) {
  411.            s = (GLstencil) (stencil[i] & ctx->Stencil.ValueMask);
  412.            if (r <= s) {
  413.           /* pass */
  414.           fail[i] = 0;
  415.            }
  416.            else {
  417.           fail[i] = 1;
  418.           mask[i] = 0;
  419.            }
  420.         }
  421.         else {
  422.            fail[i] = 0;
  423.         }
  424.      }
  425.      break;
  426.       case GL_GREATER:
  427.      r = (GLstencil) (ctx->Stencil.Ref & ctx->Stencil.ValueMask);
  428.      for (i=0;i<n;i++) {
  429.         if (mask[i]) {
  430.            s = (GLstencil) (stencil[i] & ctx->Stencil.ValueMask);
  431.            if (r > s) {
  432.           /* passed */
  433.           fail[i] = 0;
  434.            }
  435.            else {
  436.           fail[i] = 1;
  437.           mask[i] = 0;
  438.            }
  439.         }
  440.         else {
  441.            fail[i] = 0;
  442.         }
  443.      }
  444.      break;
  445.       case GL_GEQUAL:
  446.      r = (GLstencil) (ctx->Stencil.Ref & ctx->Stencil.ValueMask);
  447.      for (i=0;i<n;i++) {
  448.         if (mask[i]) {
  449.            s = (GLstencil) (stencil[i] & ctx->Stencil.ValueMask);
  450.            if (r >= s) {
  451.           /* passed */
  452.           fail[i] = 0;
  453.            }
  454.            else {
  455.           fail[i] = 1;
  456.           mask[i] = 0;
  457.            }
  458.         }
  459.         else {
  460.            fail[i] = 0;
  461.         }
  462.      }
  463.      break;
  464.       case GL_EQUAL:
  465.      r = (GLstencil) (ctx->Stencil.Ref & ctx->Stencil.ValueMask);
  466.      for (i=0;i<n;i++) {
  467.         if (mask[i]) {
  468.            s = (GLstencil) (stencil[i] & ctx->Stencil.ValueMask);
  469.            if (r == s) {
  470.           /* passed */
  471.           fail[i] = 0;
  472.            }
  473.            else {
  474.           fail[i] = 1;
  475.           mask[i] = 0;
  476.            }
  477.         }
  478.         else {
  479.            fail[i] = 0;
  480.         }
  481.      }
  482.      break;
  483.       case GL_NOTEQUAL:
  484.      r = (GLstencil) (ctx->Stencil.Ref & ctx->Stencil.ValueMask);
  485.      for (i=0;i<n;i++) {
  486.         if (mask[i]) {
  487.            s = (GLstencil) (stencil[i] & ctx->Stencil.ValueMask);
  488.            if (r != s) {
  489.           /* passed */
  490.           fail[i] = 0;
  491.            }
  492.            else {
  493.           fail[i] = 1;
  494.           mask[i] = 0;
  495.            }
  496.         }
  497.         else {
  498.            fail[i] = 0;
  499.         }
  500.      }
  501.      break;
  502.       case GL_ALWAYS:
  503.      /* always pass */
  504.      for (i=0;i<n;i++) {
  505.         fail[i] = 0;
  506.      }
  507.      break;
  508.       default:
  509.          gl_problem(ctx, "Bad stencil func in gl_stencil_span");
  510.          return 0;
  511.    }
  512.  
  513.    if (ctx->Stencil.FailFunc != GL_KEEP) {
  514.       apply_stencil_op( ctx, ctx->Stencil.FailFunc, n, stencil, fail );
  515.    }
  516.  
  517.    return (allfail) ? 0 : 1;
  518. }
  519.  
  520.  
  521.  
  522.  
  523. /*
  524.  * Apply the combination depth-buffer/stencil operator to a span of pixels.
  525.  * Input:  n - number of pixels in the span
  526.  *         x, y - location of leftmost pixel in span
  527.  *         z - array [n] of z values
  528.  * Input:  mask - array [n] of flags  (1=test this pixel, 0=skip the pixel)
  529.  * Output:  mask - array [n] of flags (1=depth test passed, 0=failed) 
  530.  */
  531. void gl_depth_stencil_span( GLcontext *ctx,
  532.                             GLuint n, GLint x, GLint y, const GLdepth z[],
  533.                 GLubyte mask[] )
  534. {
  535.    GLstencil *stencil = STENCIL_ADDRESS(x, y);
  536.  
  537.    if (ctx->Depth.Test==GL_FALSE) {
  538.       /*
  539.        * No depth buffer, just apply zpass stencil function to active pixels.
  540.        */
  541.       apply_stencil_op( ctx, ctx->Stencil.ZPassFunc, n, stencil, mask );
  542.    }
  543.    else {
  544.       /*
  545.        * Perform depth buffering, then apply zpass or zfail stencil function.
  546.        */
  547.       GLubyte passmask[MAX_WIDTH], failmask[MAX_WIDTH], oldmask[MAX_WIDTH];
  548.       GLuint i;
  549.  
  550.       /* save the current mask bits */
  551.       MEMCPY(oldmask, mask, n * sizeof(GLubyte));
  552.  
  553.       /* apply the depth test */
  554.       if (ctx->Driver.DepthTestSpan)
  555.          (*ctx->Driver.DepthTestSpan)( ctx, n, x, y, z, mask );
  556.  
  557.       /* Set the stencil pass/fail flags according to result of depth testing.
  558.        * if oldmask[i] == 0 then
  559.        *    Don't touch the stencil value
  560.        * else if oldmask[i] and newmask[i] then
  561.        *    Depth test passed
  562.        * else
  563.        *    assert(oldmask[i] && !newmask[i])
  564.        *    Depth test failed
  565.        * endif
  566.        */
  567.       for (i=0;i<n;i++) {
  568.          ASSERT(mask[i] == 0 || mask[i] == 1);
  569.          passmask[i] = oldmask[i] & mask[i];
  570.          failmask[i] = oldmask[i] & (mask[i] ^ 1);
  571.       }
  572.  
  573.       /* apply the pass and fail operations */
  574.       if (ctx->Stencil.ZFailFunc != GL_KEEP) {
  575.          apply_stencil_op( ctx, ctx->Stencil.ZFailFunc, n, stencil, failmask );
  576.       }
  577.       if (ctx->Stencil.ZPassFunc != GL_KEEP) {
  578.          apply_stencil_op( ctx, ctx->Stencil.ZPassFunc, n, stencil, passmask );
  579.       }
  580.    }
  581. }
  582.  
  583.  
  584.  
  585.  
  586. /*
  587.  * Apply the given stencil operator for each pixel in the array whose
  588.  * mask flag is set.
  589.  * Input:  n - number of pixels in the span
  590.  *         x, y - array of [n] pixels
  591.  *         operator - the stencil buffer operator
  592.  *         mask - array [n] of flag:  1=apply operator, 0=don't apply operator
  593.  */
  594. static void apply_stencil_op_to_pixels( GLcontext *ctx,
  595.                                         GLuint n, const GLint x[],
  596.                         const GLint y[],
  597.                         GLenum oper, GLubyte mask[] )
  598. {
  599.    GLuint i;
  600.    GLstencil ref;
  601.    GLstencil wrtmask, invmask;
  602.  
  603.    wrtmask = ctx->Stencil.WriteMask;
  604.    invmask = (GLstencil) (~ctx->Stencil.WriteMask);
  605.  
  606.    ref = ctx->Stencil.Ref;
  607.  
  608.    switch (oper) {
  609.       case GL_KEEP:
  610.          /* do nothing */
  611.          break;
  612.       case GL_ZERO:
  613.      if (invmask==0) {
  614.         for (i=0;i<n;i++) {
  615.            if (mask[i]) {
  616.                   GLstencil *sptr = STENCIL_ADDRESS( x[i], y[i] );
  617.                   *sptr = 0;
  618.            }
  619.         }
  620.      }
  621.      else {
  622.         for (i=0;i<n;i++) {
  623.            if (mask[i]) {
  624.                   GLstencil *sptr = STENCIL_ADDRESS( x[i], y[i] );
  625.           *sptr = (GLstencil) (invmask & *sptr);
  626.            }
  627.         }
  628.      }
  629.      break;
  630.       case GL_REPLACE:
  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 = ref;
  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 & ref));
  644.            }
  645.         }
  646.      }
  647.      break;
  648.       case GL_INCR:
  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.           if (*sptr < STENCIL_MAX) {
  654.              *sptr = (GLstencil) (*sptr + 1);
  655.           }
  656.            }
  657.         }
  658.      }
  659.      else {
  660.         for (i=0;i<n;i++) {
  661.            if (mask[i]) {
  662.                   GLstencil *sptr = STENCIL_ADDRESS( x[i], y[i] );
  663.           if (*sptr < STENCIL_MAX) {
  664.              *sptr = (GLstencil) ((invmask & *sptr) | (wrtmask & (*sptr+1)));
  665.           }
  666.            }
  667.         }
  668.      }
  669.      break;
  670.       case GL_DECR:
  671.      if (invmask==0) {
  672.         for (i=0;i<n;i++) {
  673.            if (mask[i]) {
  674.                   GLstencil *sptr = STENCIL_ADDRESS( x[i], y[i] );
  675.           if (*sptr>0) {
  676.              *sptr = (GLstencil) (*sptr - 1);
  677.           }
  678.            }
  679.         }
  680.      }
  681.      else {
  682.         for (i=0;i<n;i++) {
  683.            if (mask[i]) {
  684.                   GLstencil *sptr = STENCIL_ADDRESS( x[i], y[i] );
  685.           if (*sptr>0) {
  686.              *sptr = (GLstencil) ((invmask & *sptr) | (wrtmask & (*sptr-1)));
  687.           }
  688.            }
  689.         }
  690.      }
  691.      break;
  692.       case GL_INCR_WRAP_EXT:
  693.      if (invmask==0) {
  694.         for (i=0;i<n;i++) {
  695.            if (mask[i]) {
  696.                   GLstencil *sptr = STENCIL_ADDRESS( x[i], y[i] );
  697.                   *sptr = (GLstencil) (*sptr + 1);
  698.            }
  699.         }
  700.      }
  701.      else {
  702.         for (i=0;i<n;i++) {
  703.            if (mask[i]) {
  704.                   GLstencil *sptr = STENCIL_ADDRESS( x[i], y[i] );
  705.                   *sptr = (GLstencil) ((invmask & *sptr) | (wrtmask & (*sptr+1)));
  706.            }
  707.         }
  708.      }
  709.      break;
  710.       case GL_DECR_WRAP_EXT:
  711.      if (invmask==0) {
  712.         for (i=0;i<n;i++) {
  713.            if (mask[i]) {
  714.                   GLstencil *sptr = STENCIL_ADDRESS( x[i], y[i] );
  715.                   *sptr = (GLstencil) (*sptr - 1);
  716.            }
  717.         }
  718.      }
  719.      else {
  720.         for (i=0;i<n;i++) {
  721.            if (mask[i]) {
  722.                   GLstencil *sptr = STENCIL_ADDRESS( x[i], y[i] );
  723.                   *sptr = (GLstencil) ((invmask & *sptr) | (wrtmask & (*sptr-1)));
  724.            }
  725.         }
  726.      }
  727.      break;
  728.       case GL_INVERT:
  729.      if (invmask==0) {
  730.         for (i=0;i<n;i++) {
  731.            if (mask[i]) {
  732.                   GLstencil *sptr = STENCIL_ADDRESS( x[i], y[i] );
  733.                   *sptr = (GLstencil) (~*sptr);
  734.            }
  735.         }
  736.      }
  737.      else {
  738.         for (i=0;i<n;i++) {
  739.            if (mask[i]) {
  740.                   GLstencil *sptr = STENCIL_ADDRESS( x[i], y[i] );
  741.                   *sptr = (GLstencil) ((invmask & *sptr) | (wrtmask & ~*sptr));
  742.            }
  743.         }
  744.      }
  745.      break;
  746.       default:
  747.          gl_problem(ctx, "Bad stencilop in apply_stencil_op_to_pixels");
  748.    }
  749. }
  750.  
  751.  
  752.  
  753. /*
  754.  * Apply stencil test to an array of pixels before depth buffering.
  755.  * Input:  n - number of pixels in the span
  756.  *         x, y - array of [n] pixels to stencil
  757.  *         mask - array [n] of flag:  0=skip the pixel, 1=stencil the pixel
  758.  * Output:  mask - pixels which fail the stencil test will have their
  759.  *                 mask flag set to 0.
  760.  * Return:  0 = all pixels failed, 1 = zero or more pixels passed.
  761.  */
  762. GLint gl_stencil_pixels( GLcontext *ctx,
  763.                          GLuint n, const GLint x[], const GLint y[],
  764.              GLubyte mask[] )
  765. {
  766.    GLubyte fail[PB_SIZE];
  767.    GLstencil r, s;
  768.    GLuint i;
  769.    GLint allfail = 0;
  770.  
  771.    /*
  772.     * Perform stencil test.  The results of this operation are stored
  773.     * in the fail[] array:
  774.     *   IF fail[i] is non-zero THEN
  775.     *       the stencil fail operator is to be applied
  776.     *   ELSE
  777.     *       the stencil fail operator is not to be applied
  778.     *   ENDIF
  779.     */
  780.  
  781.    switch (ctx->Stencil.Function) {
  782.       case GL_NEVER:
  783.          /* always fail */
  784.          for (i=0;i<n;i++) {
  785.         if (mask[i]) {
  786.            mask[i] = 0;
  787.            fail[i] = 1;
  788.         }
  789.         else {
  790.            fail[i] = 0;
  791.         }
  792.      }
  793.      allfail = 1;
  794.      break;
  795.       case GL_LESS:
  796.      r = (GLstencil) (ctx->Stencil.Ref & ctx->Stencil.ValueMask);
  797.      for (i=0;i<n;i++) {
  798.         if (mask[i]) {
  799.                GLstencil *sptr = STENCIL_ADDRESS(x[i],y[i]);
  800.            s = (GLstencil) (*sptr & ctx->Stencil.ValueMask);
  801.            if (r < s) {
  802.           /* passed */
  803.           fail[i] = 0;
  804.            }
  805.            else {
  806.           fail[i] = 1;
  807.           mask[i] = 0;
  808.            }
  809.         }
  810.         else {
  811.            fail[i] = 0;
  812.         }
  813.      }
  814.      break;
  815.       case GL_LEQUAL:
  816.      r = (GLstencil) (ctx->Stencil.Ref & ctx->Stencil.ValueMask);
  817.      for (i=0;i<n;i++) {
  818.         if (mask[i]) {
  819.                GLstencil *sptr = STENCIL_ADDRESS(x[i],y[i]);
  820.            s = (GLstencil) (*sptr & ctx->Stencil.ValueMask);
  821.            if (r <= s) {
  822.           /* pass */
  823.           fail[i] = 0;
  824.            }
  825.            else {
  826.           fail[i] = 1;
  827.           mask[i] = 0;
  828.            }
  829.         }
  830.         else {
  831.            fail[i] = 0;
  832.         }
  833.      }
  834.      break;
  835.       case GL_GREATER:
  836.      r = (GLstencil) (ctx->Stencil.Ref & ctx->Stencil.ValueMask);
  837.      for (i=0;i<n;i++) {
  838.         if (mask[i]) {
  839.                GLstencil *sptr = STENCIL_ADDRESS(x[i],y[i]);
  840.            s = (GLstencil) (*sptr & ctx->Stencil.ValueMask);
  841.            if (r > s) {
  842.           /* passed */
  843.           fail[i] = 0;
  844.            }
  845.            else {
  846.           fail[i] = 1;
  847.           mask[i] = 0;
  848.            }
  849.         }
  850.         else {
  851.            fail[i] = 0;
  852.         }
  853.      }
  854.      break;
  855.       case GL_GEQUAL:
  856.      r = (GLstencil) (ctx->Stencil.Ref & ctx->Stencil.ValueMask);
  857.      for (i=0;i<n;i++) {
  858.         if (mask[i]) {
  859.                GLstencil *sptr = STENCIL_ADDRESS(x[i],y[i]);
  860.            s = (GLstencil) (*sptr & ctx->Stencil.ValueMask);
  861.            if (r >= s) {
  862.           /* passed */
  863.           fail[i] = 0;
  864.            }
  865.            else {
  866.           fail[i] = 1;
  867.           mask[i] = 0;
  868.            }
  869.         }
  870.         else {
  871.            fail[i] = 0;
  872.         }
  873.      }
  874.      break;
  875.       case GL_EQUAL:
  876.      r = (GLstencil) (ctx->Stencil.Ref & ctx->Stencil.ValueMask);
  877.      for (i=0;i<n;i++) {
  878.         if (mask[i]) {
  879.                GLstencil *sptr = STENCIL_ADDRESS(x[i],y[i]);
  880.            s = (GLstencil) (*sptr & ctx->Stencil.ValueMask);
  881.            if (r == s) {
  882.           /* passed */
  883.           fail[i] = 0;
  884.            }
  885.            else {
  886.           fail[i] = 1;
  887.           mask[i] = 0;
  888.            }
  889.         }
  890.         else {
  891.            fail[i] = 0;
  892.         }
  893.      }
  894.      break;
  895.       case GL_NOTEQUAL:
  896.      r = (GLstencil) (ctx->Stencil.Ref & ctx->Stencil.ValueMask);
  897.      for (i=0;i<n;i++) {
  898.         if (mask[i]) {
  899.                GLstencil *sptr = STENCIL_ADDRESS(x[i],y[i]);
  900.            s = (GLstencil) (*sptr & ctx->Stencil.ValueMask);
  901.            if (r != s) {
  902.           /* passed */
  903.           fail[i] = 0;
  904.            }
  905.            else {
  906.           fail[i] = 1;
  907.           mask[i] = 0;
  908.            }
  909.         }
  910.         else {
  911.            fail[i] = 0;
  912.         }
  913.      }
  914.      break;
  915.       case GL_ALWAYS:
  916.      /* always pass */
  917.      for (i=0;i<n;i++) {
  918.         fail[i] = 0;
  919.      }
  920.      break;
  921.       default:
  922.          gl_problem(ctx, "Bad stencil func in gl_stencil_pixels");
  923.          return 0;
  924.    }
  925.  
  926.    apply_stencil_op_to_pixels( ctx, n, x, y, ctx->Stencil.FailFunc, fail );
  927.  
  928.    return (allfail) ? 0 : 1;
  929. }
  930.  
  931.  
  932.  
  933.  
  934. /*
  935.  * Apply the combination depth-buffer/stencil operator to a span of pixels.
  936.  * Input:  n - number of pixels in the span
  937.  *         x, y - array of [n] pixels to stencil
  938.  *         z - array [n] of z values
  939.  * Input:  mask - array [n] of flags  (1=test this pixel, 0=skip the pixel)
  940.  * Output:  mask - array [n] of flags (1=depth test passed, 0=failed) 
  941.  */
  942. void gl_depth_stencil_pixels( GLcontext *ctx,
  943.                               GLuint n, const GLint x[], const GLint y[],
  944.                   const GLdepth z[], GLubyte mask[] )
  945. {
  946.    if (ctx->Depth.Test==GL_FALSE) {
  947.       /*
  948.        * No depth buffer, just apply zpass stencil function to active pixels.
  949.        */
  950.       apply_stencil_op_to_pixels( ctx, n, x, y, ctx->Stencil.ZPassFunc, mask );
  951.    }
  952.    else {
  953.       /*
  954.        * Perform depth buffering, then apply zpass or zfail stencil function.
  955.        */
  956.       GLubyte passmask[PB_SIZE], failmask[PB_SIZE], oldmask[PB_SIZE];
  957.       GLuint i;
  958.  
  959.       /* save the current mask bits */
  960.       MEMCPY(oldmask, mask, n * sizeof(GLubyte));
  961.  
  962.       /* apply the depth test */
  963.       if (ctx->Driver.DepthTestPixels)
  964.          (*ctx->Driver.DepthTestPixels)( ctx, n, x, y, z, mask );
  965.  
  966.       /* Set the stencil pass/fail flags according to result of depth testing.
  967.        * if oldmask[i] == 0 then
  968.        *    Don't touch the stencil value
  969.        * else if oldmask[i] and newmask[i] then
  970.        *    Depth test passed
  971.        * else
  972.        *    assert(oldmask[i] && !newmask[i])
  973.        *    Depth test failed
  974.        * endif
  975.        */
  976.       for (i=0;i<n;i++) {
  977.          ASSERT(mask[i] == 0 || mask[i] == 1);
  978.          passmask[i] = oldmask[i] & mask[i];
  979.          failmask[i] = oldmask[i] & (mask[i] ^ 1);
  980.       }
  981.  
  982.       /* apply the pass and fail operations */
  983.       apply_stencil_op_to_pixels( ctx, n, x, y,
  984.                                   ctx->Stencil.ZFailFunc, failmask );
  985.       apply_stencil_op_to_pixels( ctx, n, x, y,
  986.                                   ctx->Stencil.ZPassFunc, passmask );
  987.    }
  988.  
  989. }
  990.  
  991.  
  992.  
  993. /*
  994.  * Return a span of stencil values from the stencil buffer.
  995.  * Input:  n - how many pixels
  996.  *         x,y - location of first pixel
  997.  * Output:  stencil - the array of stencil values
  998.  */
  999. void gl_read_stencil_span( GLcontext *ctx,
  1000.                            GLuint n, GLint x, GLint y, GLstencil stencil[] )
  1001. {
  1002.    if (ctx->Buffer->Stencil) {
  1003.       const GLstencil *s = STENCIL_ADDRESS( x, y );
  1004. #if STENCIL_BITS == 8
  1005.       MEMCPY( stencil, s, n * sizeof(GLstencil) );
  1006. #else
  1007.       GLuint i;
  1008.       for (i=0;i<n;i++)
  1009.          stencil[i] = s[i];
  1010. #endif
  1011.    }
  1012. }
  1013.  
  1014.  
  1015.  
  1016. /*
  1017.  * Write a span of stencil values to the stencil buffer.
  1018.  * Input:  n - how many pixels
  1019.  *         x,y - location of first pixel
  1020.  *         stencil - the array of stencil values
  1021.  */
  1022. void gl_write_stencil_span( GLcontext *ctx,
  1023.                             GLuint n, GLint x, GLint y,
  1024.                 const GLstencil stencil[] )
  1025. {
  1026.    if (ctx->Buffer->Stencil) {
  1027.       GLstencil *s = STENCIL_ADDRESS( x, y );
  1028. #if STENCIL_BITS == 8
  1029.       MEMCPY( s, stencil, n * sizeof(GLstencil) );
  1030. #else
  1031.       GLuint i;
  1032.       for (i=0;i<n;i++)
  1033.          s[i] = stencil[i];
  1034. #endif
  1035.    }
  1036. }
  1037.  
  1038.  
  1039.  
  1040. /*
  1041.  * Allocate a new stencil buffer.  If there's an old one it will be
  1042.  * deallocated first.  The new stencil buffer will be uninitialized.
  1043.  */
  1044. void gl_alloc_stencil_buffer( GLcontext *ctx )
  1045. {
  1046.    GLuint buffersize = ctx->Buffer->Width * ctx->Buffer->Height;
  1047.  
  1048.    /* deallocate current stencil buffer if present */
  1049.    if (ctx->Buffer->Stencil) {
  1050.       FREE(ctx->Buffer->Stencil);
  1051.       ctx->Buffer->Stencil = NULL;
  1052.    }
  1053.  
  1054.    /* allocate new stencil buffer */
  1055.    ctx->Buffer->Stencil = (GLstencil *) MALLOC(buffersize * sizeof(GLstencil));
  1056.    if (!ctx->Buffer->Stencil) {
  1057.       /* out of memory */
  1058.       gl_set_enable( ctx, GL_STENCIL_TEST, GL_FALSE );
  1059.       gl_error( ctx, GL_OUT_OF_MEMORY, "gl_alloc_stencil_buffer" );
  1060.    }
  1061. }
  1062.  
  1063.  
  1064.  
  1065.  
  1066. /*
  1067.  * Clear the stencil buffer.  If the stencil buffer doesn't exist yet we'll
  1068.  * allocate it now.
  1069.  */
  1070. void gl_clear_stencil_buffer( GLcontext *ctx )
  1071. {
  1072.    if (ctx->Visual->StencilBits==0 || !ctx->Buffer->Stencil) {
  1073.       /* no stencil buffer */
  1074.       return;
  1075.    }
  1076.  
  1077.    if (ctx->Scissor.Enabled) {
  1078.       /* clear scissor region only */
  1079.       const GLint width = ctx->Buffer->Xmax - ctx->Buffer->Xmin + 1;
  1080.       if (ctx->Stencil.WriteMask != STENCIL_MAX) {
  1081.          /* must apply mask to the clear */
  1082.          GLint y;
  1083.          for (y=ctx->Buffer->Ymin; y<=ctx->Buffer->Ymax; y++) {
  1084.             GLstencil *ptr = STENCIL_ADDRESS( ctx->Buffer->Xmin, y );
  1085.             GLint x;
  1086.             const GLstencil mask = ctx->Stencil.WriteMask;
  1087.             const GLstencil invMask = ~mask;
  1088.             const GLstencil clearVal = (ctx->Stencil.Clear & mask);
  1089.             for (x = 0; x < width; x++) {
  1090.                ptr[x] = (ptr[x] & invMask) | clearVal;
  1091.             }
  1092.          }
  1093.       }
  1094.       else {
  1095.          /* no masking */
  1096.          GLint y;
  1097.          for (y=ctx->Buffer->Ymin; y<=ctx->Buffer->Ymax; y++) {
  1098.             GLstencil *ptr = STENCIL_ADDRESS( ctx->Buffer->Xmin, y );
  1099. #if STENCIL_BITS==8
  1100.             MEMSET( ptr, ctx->Stencil.Clear, width * sizeof(GLstencil) );
  1101. #else
  1102.             GLint x;
  1103.             for (x = 0; x < width; x++)
  1104.                ptr[x] = ctx->Stencil.Clear;
  1105. #endif
  1106.          }
  1107.       }
  1108.    }
  1109.    else {
  1110.       /* clear whole stencil buffer */
  1111.       if (ctx->Stencil.WriteMask != STENCIL_MAX) {
  1112.          /* must apply mask to the clear */
  1113.          const GLuint n = ctx->Buffer->Width * ctx->Buffer->Height;
  1114.          GLstencil *buffer = ctx->Buffer->Stencil;
  1115.          const GLstencil mask = ctx->Stencil.WriteMask;
  1116.          const GLstencil invMask = ~mask;
  1117.          const GLstencil clearVal = (ctx->Stencil.Clear & mask);
  1118.          GLuint i;
  1119.          for (i = 0; i < n; i++) {
  1120.             buffer[i] = (buffer[i] & invMask) | clearVal;
  1121.          }
  1122.       }
  1123.       else {
  1124.          /* clear whole buffer without masking */
  1125.          const GLuint n = ctx->Buffer->Width * ctx->Buffer->Height;
  1126.          GLstencil *buffer = ctx->Buffer->Stencil;
  1127.  
  1128. #if STENCIL_BITS==8
  1129.          MEMSET(buffer, ctx->Stencil.Clear, n * sizeof(GLstencil) );
  1130. #else
  1131.          GLuint i;
  1132.          for (i = 0; i < n; i++) {
  1133.             buffer[i] = ctx->Stencil.Clear;
  1134.          }
  1135. #endif
  1136.       }
  1137.    }
  1138. }
  1139.