Track two sets of back-face stencil state
authorIan Romanick <idr@freedesktop.org>
Fri, 9 Jan 2009 23:43:17 +0000 (15:43 -0800)
committerIan Romanick <ian.d.romanick@intel.com>
Fri, 23 Jan 2009 17:49:29 +0000 (09:49 -0800)
Track separate back-face stencil state for OpenGL 2.0 /
GL_ATI_separate_stencil and GL_EXT_stencil_two_side.  This allows all
three to be enabled in a driver.  One set of state is set via the 2.0
or ATI functions and is used when STENCIL_TEST_TWO_SIDE_EXT is
disabled.  The other is set by StencilFunc and StencilOp when the
active stencil face is set to BACK.  The GL_EXT_stencil_two_side spec has
more details.

http://opengl.org/registry/specs/EXT/stencil_two_side.txt

src/mesa/drivers/dri/i965/brw_cc.c
src/mesa/drivers/dri/i965/brw_wm.c
src/mesa/drivers/dri/r300/r300_render.c
src/mesa/drivers/dri/r300/r300_state.c
src/mesa/main/enable.c
src/mesa/main/getstring.c
src/mesa/main/mtypes.h
src/mesa/main/stencil.c
src/mesa/swrast/s_stencil.c

index fa8121e02d3c44de83cf0d86f0f30e50abdaa2fb..abae4b321525256bf27a85eba16103cb02324fef 100644 (file)
@@ -84,6 +84,7 @@ static void
 cc_unit_populate_key(struct brw_context *brw, struct brw_cc_unit_key *key)
 {
    struct gl_stencil_attrib *stencil = brw->attribs.Stencil;
+   const unsigned back = stencil->_BackFace;
 
    memset(key, 0, sizeof(*key));
 
@@ -100,13 +101,13 @@ cc_unit_populate_key(struct brw_context *brw, struct brw_cc_unit_key *key)
       key->stencil_test_mask[0] = stencil->ValueMask[0];
    }
    if (key->stencil_two_side) {
-      key->stencil_func[1] = stencil->Function[1];
-      key->stencil_fail_op[1] = stencil->FailFunc[1];
-      key->stencil_pass_depth_fail_op[1] = stencil->ZFailFunc[1];
-      key->stencil_pass_depth_pass_op[1] = stencil->ZPassFunc[1];
-      key->stencil_ref[1] = stencil->Ref[1];
-      key->stencil_write_mask[1] = stencil->WriteMask[1];
-      key->stencil_test_mask[1] = stencil->ValueMask[1];
+      key->stencil_func[1] = stencil->Function[back];
+      key->stencil_fail_op[1] = stencil->FailFunc[back];
+      key->stencil_pass_depth_fail_op[1] = stencil->ZFailFunc[back];
+      key->stencil_pass_depth_pass_op[1] = stencil->ZPassFunc[back];
+      key->stencil_ref[1] = stencil->Ref[back];
+      key->stencil_write_mask[1] = stencil->WriteMask[back];
+      key->stencil_test_mask[1] = stencil->ValueMask[back];
    }
 
    if (brw->attribs.Color->_LogicOpEnabled)
index c50b0d2dd9535ff1169810d7ada67086afc84ddf..24149cf8a17d184eb8fc980521115f7b20137b36 100644 (file)
@@ -189,8 +189,7 @@ static void brw_wm_populate_key( struct brw_context *brw,
       lookup |= IZ_STENCIL_TEST_ENABLE_BIT;
 
       if (brw->attribs.Stencil->WriteMask[0] ||
-         (brw->attribs.Stencil->_TestTwoSide &&
-          brw->attribs.Stencil->WriteMask[1]))
+         brw->attribs.Stencil->WriteMask[brw->attribs.Stencil->_BackFace])
         lookup |= IZ_STENCIL_WRITE_ENABLE_BIT;
    }
 
index f9266e44c13f7e4fedb6d511a9430c300d0664e0..16ce4a11999b30201628b7b28f41700e20ac9367 100644 (file)
@@ -347,6 +347,8 @@ static GLboolean r300RunRender(GLcontext * ctx,
 static int r300Fallback(GLcontext * ctx)
 {
        r300ContextPtr r300 = R300_CONTEXT(ctx);
+       const unsigned back = ctx->Stencil._BackFace;
+
        /* Do we need to use new-style shaders?
         * Also is there a better way to do this? */
        if (r300->radeon.radeonScreen->chip_family >= CHIP_FAMILY_RV515) {
@@ -371,12 +373,14 @@ static int r300Fallback(GLcontext * ctx)
 
        FALLBACK_IF(ctx->RenderMode != GL_RENDER);
 
-       FALLBACK_IF(ctx->Stencil._TestTwoSide
-                   && (ctx->Stencil.Ref[0] != ctx->Stencil.Ref[1]
-                       || ctx->Stencil.ValueMask[0] !=
-                       ctx->Stencil.ValueMask[1]
-                       || ctx->Stencil.WriteMask[0] !=
-                       ctx->Stencil.WriteMask[1]));
+       /* If GL_EXT_stencil_two_side is disabled, this fallback check can
+        * be removed.
+        */
+       FALLBACK_IF(ctx->Stencil.Ref[0] != ctx->Stencil.Ref[back]
+                   || ctx->Stencil.ValueMask[0] !=
+                   ctx->Stencil.ValueMask[back]
+                   || ctx->Stencil.WriteMask[0] !=
+                   ctx->Stencil.WriteMask[back]);
 
        if (ctx->Extensions.NV_point_sprite || ctx->Extensions.ARB_point_sprite)
                FALLBACK_IF(ctx->Point.PointSprite);
index a63dbac3436f4e100b3ea2b5b3c72ca8f1cc95ab..d02034f039b93882c4880882a9dfe9709dda317c 100644 (file)
@@ -974,15 +974,9 @@ static void r300StencilFuncSeparate(GLcontext * ctx, GLenum face,
 {
        r300ContextPtr rmesa = R300_CONTEXT(ctx);
        GLuint refmask =
-           (((ctx->Stencil.
-              Ref[0] & 0xff) << R300_STENCILREF_SHIFT) | ((ctx->
-                                                           Stencil.
-                                                           ValueMask
-                                                           [0] &
-                                                           0xff)
-                                                          <<
-                                                          R300_STENCILMASK_SHIFT));
-
+           ((ctx->Stencil.Ref[0] & 0xff) << R300_STENCILREF_SHIFT)
+            | ((ctx->Stencil.ValueMask[0] & 0xff) << R300_STENCILMASK_SHIFT);
+       const unsigned back = ctx->Stencil._BackFace;
        GLuint flag;
 
        R300_STATECHANGE(rmesa, zs);
@@ -1000,8 +994,7 @@ static void r300StencilFuncSeparate(GLcontext * ctx, GLenum face,
        rmesa->hw.zs.cmd[R300_ZS_CNTL_1] |=
            (flag << R300_S_FRONT_FUNC_SHIFT);
 
-       if (ctx->Stencil._TestTwoSide)
-               flag = translate_func(ctx->Stencil.Function[1]);
+       flag = translate_func(ctx->Stencil.Function[back]);
 
        rmesa->hw.zs.cmd[R300_ZS_CNTL_1] |=
            (flag << R300_S_BACK_FUNC_SHIFT);
@@ -1026,6 +1019,7 @@ static void r300StencilOpSeparate(GLcontext * ctx, GLenum face,
                                  GLenum fail, GLenum zfail, GLenum zpass)
 {
        r300ContextPtr rmesa = R300_CONTEXT(ctx);
+       const unsigned back = ctx->Stencil._BackFace;
 
        R300_STATECHANGE(rmesa, zs);
        /* It is easier to mask what's left.. */
@@ -1042,23 +1036,13 @@ static void r300StencilOpSeparate(GLcontext * ctx, GLenum face,
            | (translate_stencil_op(ctx->Stencil.ZPassFunc[0]) <<
               R300_S_FRONT_ZPASS_OP_SHIFT);
 
-       if (ctx->Stencil._TestTwoSide) {
-               rmesa->hw.zs.cmd[R300_ZS_CNTL_1] |=
-                   (translate_stencil_op(ctx->Stencil.FailFunc[1]) <<
-                    R300_S_BACK_SFAIL_OP_SHIFT)
-                   | (translate_stencil_op(ctx->Stencil.ZFailFunc[1]) <<
-                      R300_S_BACK_ZFAIL_OP_SHIFT)
-                   | (translate_stencil_op(ctx->Stencil.ZPassFunc[1]) <<
-                      R300_S_BACK_ZPASS_OP_SHIFT);
-       } else {
-               rmesa->hw.zs.cmd[R300_ZS_CNTL_1] |=
-                   (translate_stencil_op(ctx->Stencil.FailFunc[0]) <<
-                    R300_S_BACK_SFAIL_OP_SHIFT)
-                   | (translate_stencil_op(ctx->Stencil.ZFailFunc[0]) <<
-                      R300_S_BACK_ZFAIL_OP_SHIFT)
-                   | (translate_stencil_op(ctx->Stencil.ZPassFunc[0]) <<
-                      R300_S_BACK_ZPASS_OP_SHIFT);
-       }
+       rmesa->hw.zs.cmd[R300_ZS_CNTL_1] |=
+           (translate_stencil_op(ctx->Stencil.FailFunc[back]) <<
+            R300_S_BACK_SFAIL_OP_SHIFT)
+           | (translate_stencil_op(ctx->Stencil.ZFailFunc[back]) <<
+              R300_S_BACK_ZFAIL_OP_SHIFT)
+           | (translate_stencil_op(ctx->Stencil.ZPassFunc[back]) <<
+              R300_S_BACK_ZPASS_OP_SHIFT);
 }
 
 /* =============================================================
index dae576ae5ac36da2d71d4a6a6c8837909904325a..1c026174b83e18a73375283995d151ce53a37760 100644 (file)
@@ -922,10 +922,13 @@ _mesa_set_enable(GLcontext *ctx, GLenum cap, GLboolean state)
             return;
          FLUSH_VERTICES(ctx, _NEW_STENCIL);
          ctx->Stencil.TestTwoSide = state;
-         if (state)
+         if (state) {
+            ctx->Stencil._BackFace = 2;
             ctx->_TriangleCaps |= DD_TRI_TWOSTENCIL;
-         else
+         } else {
+            ctx->Stencil._BackFace = 1;
             ctx->_TriangleCaps &= ~DD_TRI_TWOSTENCIL;
+         }
          break;
 
 #if FEATURE_ARB_fragment_program
index 94bf5de1e8bf12b1423fd73db4942a69752d225f..a9e22d340a314fdae172dcc4db437a09cf507fe6 100644 (file)
@@ -82,7 +82,16 @@ compute_version(const GLcontext *ctx)
                               ctx->Extensions.ARB_vertex_shader &&
                               ctx->Extensions.ARB_fragment_shader &&
                               ctx->Extensions.ARB_texture_non_power_of_two &&
-                              ctx->Extensions.EXT_blend_equation_separate);
+                              ctx->Extensions.EXT_blend_equation_separate &&
+
+                             /* Technically, 2.0 requires the functionality
+                              * of the EXT version.  Enable 2.0 if either
+                              * extension is available, and assume that a
+                              * driver that only exposes the ATI extension
+                              * will fallback to software when necessary.
+                              */
+                             (ctx->Extensions.EXT_stencil_two_side
+                              || ctx->Extensions.ATI_separate_stencil));
    const GLboolean ver_2_1 = (ver_2_0 &&
                               /*ctx->Extensions.ARB_shading_language_120 &&*/
                               ctx->Extensions.EXT_pixel_buffer_object &&
index f1da638ae669fc99333b3caddcb7c27607661bb4..088d45b1566573b4f563cd859de85617963dfc13 100644 (file)
@@ -1108,20 +1108,34 @@ struct gl_scissor_attrib
 
 /**
  * Stencil attribute group (GL_STENCIL_BUFFER_BIT).
+ *
+ * Three sets of stencil data are tracked so that OpenGL 2.0,
+ * GL_EXT_stencil_two_side, and GL_ATI_separate_stencil can all be supported
+ * simultaneously.  In each of the stencil state arrays, element 0 corresponds
+ * to GL_FRONT.  Element 1 corresponds to the OpenGL 2.0 /
+ * GL_ATI_separate_stencil GL_BACK state.  Element 2 corresponds to the
+ * GL_EXT_stencil_two_side GL_BACK state.
+ *
+ * The derived value \c _BackFace is either 1 or 2 depending on whether or
+ * not GL_STENCIL_TEST_TWO_SIDE_EXT is enabled.
+ *
+ * The derived value \c _TestTwoSide is set when the front-face and back-face
+ * stencil state are different.
  */
 struct gl_stencil_attrib
 {
    GLboolean Enabled;          /**< Enabled flag */
    GLboolean TestTwoSide;      /**< GL_EXT_stencil_two_side */
-   GLubyte ActiveFace;         /**< GL_EXT_stencil_two_side (0 or 1) */
+   GLubyte ActiveFace;         /**< GL_EXT_stencil_two_side (0 or 2) */
    GLboolean _TestTwoSide;
-   GLenum Function[2];         /**< Stencil function */
-   GLenum FailFunc[2];         /**< Fail function */
-   GLenum ZPassFunc[2];                /**< Depth buffer pass function */
-   GLenum ZFailFunc[2];                /**< Depth buffer fail function */
-   GLint Ref[2];               /**< Reference value */
-   GLuint ValueMask[2];                /**< Value mask */
-   GLuint WriteMask[2];                /**< Write mask */
+   GLubyte _BackFace;
+   GLenum Function[3];         /**< Stencil function */
+   GLenum FailFunc[3];         /**< Fail function */
+   GLenum ZPassFunc[3];                /**< Depth buffer pass function */
+   GLenum ZFailFunc[3];                /**< Depth buffer fail function */
+   GLint Ref[3];               /**< Reference value */
+   GLuint ValueMask[3];                /**< Value mask */
+   GLuint WriteMask[3];                /**< Write mask */
    GLuint Clear;               /**< Clear value */
 };
 
index 2a4c38b1f25885dfbcf6d8d54108d36f5a34868d..b4ea9978d874bfc858083d1db81992537285c167 100644 (file)
  * \file stencil.c
  * Stencil operations.
  *
- * Note: There's an incompatibility between GL_EXT_stencil_two_side and
- * OpenGL 2.0's two-sided stencil feature.
- *
- * With GL_EXT_stencil_two_side, calling glStencilOp/Func/Mask() only the
- * front OR back face state (as set by glActiveStencilFaceEXT) is set.
- *
- * But with OpenGL 2.0, calling glStencilOp/Func/Mask() sets BOTH the
- * front AND back state.
- *
- * So either we advertise the GL_EXT_stencil_two_side extension, or OpenGL
- * 2.0, but not both.
- *
- * Also, note that GL_ATI_separate_stencil is different as well:
- * glStencilFuncSeparateATI(GLenum frontfunc, GLenum backfunc, ...)  vs.
- * glStencilFuncSeparate(GLenum face, GLenum func, ...).
  */
 
 
@@ -198,6 +183,7 @@ _mesa_StencilFunc( GLenum func, GLint ref, GLuint mask )
 {
    GET_CURRENT_CONTEXT(ctx);
    const GLint stencilMax = (1 << ctx->DrawBuffer->Visual.stencilBits) - 1;
+   const GLint face = ctx->Stencil.ActiveFace;
    ASSERT_OUTSIDE_BEGIN_END(ctx);
 
    if (!validate_stencil_func(ctx, func)) {
@@ -207,9 +193,7 @@ _mesa_StencilFunc( GLenum func, GLint ref, GLuint mask )
 
    ref = CLAMP( ref, 0, stencilMax );
 
-   if (ctx->Extensions.EXT_stencil_two_side) {
-      /* only set active face state */
-      const GLint face = ctx->Stencil.ActiveFace;
+   if (face != 0) {
       if (ctx->Stencil.Function[face] == func &&
           ctx->Stencil.ValueMask[face] == mask &&
           ctx->Stencil.Ref[face] == ref)
@@ -218,9 +202,12 @@ _mesa_StencilFunc( GLenum func, GLint ref, GLuint mask )
       ctx->Stencil.Function[face] = func;
       ctx->Stencil.Ref[face] = ref;
       ctx->Stencil.ValueMask[face] = mask;
-      if (ctx->Driver.StencilFuncSeparate) {
-         ctx->Driver.StencilFuncSeparate(ctx, face ? GL_BACK : GL_FRONT,
-                                         func, ref, mask);
+
+      /* Only propagate the change to the driver if EXT_stencil_two_side
+       * is enabled.
+       */
+      if (ctx->Driver.StencilFuncSeparate && ctx->Stencil.TestTwoSide) {
+         ctx->Driver.StencilFuncSeparate(ctx, GL_BACK, func, ref, mask);
       }
    }
    else {
@@ -237,7 +224,9 @@ _mesa_StencilFunc( GLenum func, GLint ref, GLuint mask )
       ctx->Stencil.Ref[0]       = ctx->Stencil.Ref[1]       = ref;
       ctx->Stencil.ValueMask[0] = ctx->Stencil.ValueMask[1] = mask;
       if (ctx->Driver.StencilFuncSeparate) {
-         ctx->Driver.StencilFuncSeparate(ctx, GL_FRONT_AND_BACK,
+         ctx->Driver.StencilFuncSeparate(ctx,
+                                        ((ctx->Stencil.TestTwoSide)
+                                         ? GL_FRONT : GL_FRONT_AND_BACK),
                                          func, ref, mask);
       }
    }
@@ -259,17 +248,23 @@ void GLAPIENTRY
 _mesa_StencilMask( GLuint mask )
 {
    GET_CURRENT_CONTEXT(ctx);
+   const GLint face = ctx->Stencil.ActiveFace;
+
    ASSERT_OUTSIDE_BEGIN_END(ctx);
 
-   if (ctx->Extensions.EXT_stencil_two_side) {
-      /* only set active face state */
-      const GLint face = ctx->Stencil.ActiveFace;
+   if (face != 0) {
+      /* Only modify the EXT_stencil_two_side back-face state.
+       */
       if (ctx->Stencil.WriteMask[face] == mask)
          return;
       FLUSH_VERTICES(ctx, _NEW_STENCIL);
       ctx->Stencil.WriteMask[face] = mask;
-      if (ctx->Driver.StencilMaskSeparate) {
-         ctx->Driver.StencilMaskSeparate(ctx, face ? GL_BACK : GL_FRONT, mask);
+
+      /* Only propagate the change to the driver if EXT_stencil_two_side
+       * is enabled.
+       */
+      if (ctx->Driver.StencilMaskSeparate && ctx->Stencil.TestTwoSide) {
+         ctx->Driver.StencilMaskSeparate(ctx, GL_BACK, mask);
       }
    }
    else {
@@ -280,7 +275,10 @@ _mesa_StencilMask( GLuint mask )
       FLUSH_VERTICES(ctx, _NEW_STENCIL);
       ctx->Stencil.WriteMask[0] = ctx->Stencil.WriteMask[1] = mask;
       if (ctx->Driver.StencilMaskSeparate) {
-         ctx->Driver.StencilMaskSeparate(ctx, GL_FRONT_AND_BACK, mask);
+         ctx->Driver.StencilMaskSeparate(ctx,
+                                        ((ctx->Stencil.TestTwoSide)
+                                         ? GL_FRONT : GL_FRONT_AND_BACK),
+                                         mask);
       }
    }
 }
@@ -304,6 +302,8 @@ void GLAPIENTRY
 _mesa_StencilOp(GLenum fail, GLenum zfail, GLenum zpass)
 {
    GET_CURRENT_CONTEXT(ctx);
+   const GLint face = ctx->Stencil.ActiveFace;
+
    ASSERT_OUTSIDE_BEGIN_END(ctx);
 
    if (!validate_stencil_op(ctx, fail)) {
@@ -319,9 +319,8 @@ _mesa_StencilOp(GLenum fail, GLenum zfail, GLenum zpass)
       return;
    }
 
-   if (ctx->Extensions.EXT_stencil_two_side) {
+   if (face != 0) {
       /* only set active face state */
-      const GLint face = ctx->Stencil.ActiveFace;
       if (ctx->Stencil.ZFailFunc[face] == zfail &&
           ctx->Stencil.ZPassFunc[face] == zpass &&
           ctx->Stencil.FailFunc[face] == fail)
@@ -330,9 +329,12 @@ _mesa_StencilOp(GLenum fail, GLenum zfail, GLenum zpass)
       ctx->Stencil.ZFailFunc[face] = zfail;
       ctx->Stencil.ZPassFunc[face] = zpass;
       ctx->Stencil.FailFunc[face] = fail;
-      if (ctx->Driver.StencilOpSeparate) {
-         ctx->Driver.StencilOpSeparate(ctx, face ? GL_BACK : GL_FRONT,
-                                       fail, zfail, zpass);
+
+      /* Only propagate the change to the driver if EXT_stencil_two_side
+       * is enabled.
+       */
+      if (ctx->Driver.StencilOpSeparate && ctx->Stencil.TestTwoSide) {
+         ctx->Driver.StencilOpSeparate(ctx, GL_BACK, fail, zfail, zpass);
       }
    }
    else {
@@ -349,7 +351,9 @@ _mesa_StencilOp(GLenum fail, GLenum zfail, GLenum zpass)
       ctx->Stencil.ZPassFunc[0] = ctx->Stencil.ZPassFunc[1] = zpass;
       ctx->Stencil.FailFunc[0]  = ctx->Stencil.FailFunc[1]  = fail;
       if (ctx->Driver.StencilOpSeparate) {
-         ctx->Driver.StencilOpSeparate(ctx, GL_FRONT_AND_BACK,
+         ctx->Driver.StencilOpSeparate(ctx,
+                                      ((ctx->Stencil.TestTwoSide)
+                                       ? GL_FRONT : GL_FRONT_AND_BACK),
                                        fail, zfail, zpass);
       }
    }
@@ -372,7 +376,7 @@ _mesa_ActiveStencilFaceEXT(GLenum face)
 
    if (face == GL_FRONT || face == GL_BACK) {
       FLUSH_VERTICES(ctx, _NEW_STENCIL);
-      ctx->Stencil.ActiveFace = (face == GL_FRONT) ? 0 : 1;
+      ctx->Stencil.ActiveFace = (face == GL_FRONT) ? 0 : 2;
    }
    else {
       _mesa_error(ctx, GL_INVALID_ENUM, "glActiveStencilFaceEXT(face)");
@@ -513,19 +517,16 @@ _mesa_StencilMaskSeparate(GLenum face, GLuint mask)
 void
 _mesa_update_stencil(GLcontext *ctx)
 {
-   if (ctx->Extensions.EXT_stencil_two_side) {
-      ctx->Stencil._TestTwoSide = ctx->Stencil.TestTwoSide;
-   }
-   else {
-      ctx->Stencil._TestTwoSide = 
-         (ctx->Stencil.Function[0] != ctx->Stencil.Function[1] ||
-          ctx->Stencil.FailFunc[0] != ctx->Stencil.FailFunc[1] ||
-          ctx->Stencil.ZPassFunc[0] != ctx->Stencil.ZPassFunc[1] ||
-          ctx->Stencil.ZFailFunc[0] != ctx->Stencil.ZFailFunc[1] ||
-          ctx->Stencil.Ref[0] != ctx->Stencil.Ref[1] ||
-          ctx->Stencil.ValueMask[0] != ctx->Stencil.ValueMask[1] ||
-          ctx->Stencil.WriteMask[0] != ctx->Stencil.WriteMask[1]);
-   }
+   const GLint face = ctx->Stencil._BackFace;
+
+   ctx->Stencil._TestTwoSide =
+       (ctx->Stencil.Function[0] != ctx->Stencil.Function[face] ||
+       ctx->Stencil.FailFunc[0] != ctx->Stencil.FailFunc[face] ||
+       ctx->Stencil.ZPassFunc[0] != ctx->Stencil.ZPassFunc[face] ||
+       ctx->Stencil.ZFailFunc[0] != ctx->Stencil.ZFailFunc[face] ||
+       ctx->Stencil.Ref[0] != ctx->Stencil.Ref[face] ||
+       ctx->Stencil.ValueMask[0] != ctx->Stencil.ValueMask[face] ||
+       ctx->Stencil.WriteMask[0] != ctx->Stencil.WriteMask[face]);
 }
 
 
@@ -544,17 +545,24 @@ _mesa_init_stencil(GLcontext *ctx)
    ctx->Stencil.ActiveFace = 0;  /* 0 = GL_FRONT, 1 = GL_BACK */
    ctx->Stencil.Function[0] = GL_ALWAYS;
    ctx->Stencil.Function[1] = GL_ALWAYS;
+   ctx->Stencil.Function[2] = GL_ALWAYS;
    ctx->Stencil.FailFunc[0] = GL_KEEP;
    ctx->Stencil.FailFunc[1] = GL_KEEP;
+   ctx->Stencil.FailFunc[2] = GL_KEEP;
    ctx->Stencil.ZPassFunc[0] = GL_KEEP;
    ctx->Stencil.ZPassFunc[1] = GL_KEEP;
+   ctx->Stencil.ZPassFunc[2] = GL_KEEP;
    ctx->Stencil.ZFailFunc[0] = GL_KEEP;
    ctx->Stencil.ZFailFunc[1] = GL_KEEP;
+   ctx->Stencil.ZFailFunc[2] = GL_KEEP;
    ctx->Stencil.Ref[0] = 0;
    ctx->Stencil.Ref[1] = 0;
+   ctx->Stencil.Ref[2] = 0;
    ctx->Stencil.ValueMask[0] = ~0U;
    ctx->Stencil.ValueMask[1] = ~0U;
+   ctx->Stencil.ValueMask[2] = ~0U;
    ctx->Stencil.WriteMask[0] = ~0U;
    ctx->Stencil.WriteMask[1] = ~0U;
+   ctx->Stencil.WriteMask[2] = ~0U;
    ctx->Stencil.Clear = 0;
 }
index c925922463e61a8ac0b3bf1071b998185fdeb78f..2e84ddec71fa2f874bd7ae818dfa4a0bc0acfb14 100644 (file)
@@ -997,10 +997,12 @@ stencil_and_ztest_pixels( GLcontext *ctx, SWspan *span, GLuint face )
 GLboolean
 _swrast_stencil_and_ztest_span(GLcontext *ctx, SWspan *span)
 {
+   const GLuint face = (span->facing == 0) ? 0 : ctx->Stencil._BackFace;
+
    if (span->arrayMask & SPAN_XY)
-      return stencil_and_ztest_pixels(ctx, span, span->facing);
+      return stencil_and_ztest_pixels(ctx, span, face);
    else
-      return stencil_and_ztest_span(ctx, span, span->facing);
+      return stencil_and_ztest_span(ctx, span, face);
 }