Mesa (master): Track two sets of back-face stencil state

Ian Romanick idr at kemper.freedesktop.org
Fri Jan 23 17:49:51 UTC 2009


Module: Mesa
Branch: master
Commit: dde7cb962860e72e1bf3175069767358cc5b3f3c
URL:    http://cgit.freedesktop.org/mesa/mesa/commit/?id=dde7cb962860e72e1bf3175069767358cc5b3f3c

Author: Ian Romanick <idr at freedesktop.org>
Date:   Fri Jan  9 15:43:17 2009 -0800

Track two sets of back-face stencil state

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      |   15 +++--
 src/mesa/drivers/dri/i965/brw_wm.c      |    3 +-
 src/mesa/drivers/dri/r300/r300_render.c |   16 +++--
 src/mesa/drivers/dri/r300/r300_state.c  |   40 ++++--------
 src/mesa/main/enable.c                  |    7 ++-
 src/mesa/main/getstring.c               |   11 +++-
 src/mesa/main/mtypes.h                  |   30 +++++++---
 src/mesa/main/stencil.c                 |  104 +++++++++++++++++--------------
 src/mesa/swrast/s_stencil.c             |    6 +-
 9 files changed, 128 insertions(+), 104 deletions(-)

diff --git a/src/mesa/drivers/dri/i965/brw_cc.c b/src/mesa/drivers/dri/i965/brw_cc.c
index fa8121e..abae4b3 100644
--- a/src/mesa/drivers/dri/i965/brw_cc.c
+++ b/src/mesa/drivers/dri/i965/brw_cc.c
@@ -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)
diff --git a/src/mesa/drivers/dri/i965/brw_wm.c b/src/mesa/drivers/dri/i965/brw_wm.c
index c50b0d2..24149cf 100644
--- a/src/mesa/drivers/dri/i965/brw_wm.c
+++ b/src/mesa/drivers/dri/i965/brw_wm.c
@@ -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;
    }
 
diff --git a/src/mesa/drivers/dri/r300/r300_render.c b/src/mesa/drivers/dri/r300/r300_render.c
index f9266e4..16ce4a1 100644
--- a/src/mesa/drivers/dri/r300/r300_render.c
+++ b/src/mesa/drivers/dri/r300/r300_render.c
@@ -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);
diff --git a/src/mesa/drivers/dri/r300/r300_state.c b/src/mesa/drivers/dri/r300/r300_state.c
index a63dbac..d02034f 100644
--- a/src/mesa/drivers/dri/r300/r300_state.c
+++ b/src/mesa/drivers/dri/r300/r300_state.c
@@ -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);
 }
 
 /* =============================================================
diff --git a/src/mesa/main/enable.c b/src/mesa/main/enable.c
index dae576a..1c02617 100644
--- a/src/mesa/main/enable.c
+++ b/src/mesa/main/enable.c
@@ -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
diff --git a/src/mesa/main/getstring.c b/src/mesa/main/getstring.c
index 94bf5de..a9e22d3 100644
--- a/src/mesa/main/getstring.c
+++ b/src/mesa/main/getstring.c
@@ -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 &&
diff --git a/src/mesa/main/mtypes.h b/src/mesa/main/mtypes.h
index f1da638..088d45b 100644
--- a/src/mesa/main/mtypes.h
+++ b/src/mesa/main/mtypes.h
@@ -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 */
 };
 
diff --git a/src/mesa/main/stencil.c b/src/mesa/main/stencil.c
index 2a4c38b..b4ea997 100644
--- a/src/mesa/main/stencil.c
+++ b/src/mesa/main/stencil.c
@@ -27,21 +27,6 @@
  * \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;
 }
diff --git a/src/mesa/swrast/s_stencil.c b/src/mesa/swrast/s_stencil.c
index c925922..2e84dde 100644
--- a/src/mesa/swrast/s_stencil.c
+++ b/src/mesa/swrast/s_stencil.c
@@ -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);
 }
 
 




More information about the mesa-commit mailing list