summaryrefslogtreecommitdiff
path: root/src/mesa
diff options
context:
space:
mode:
Diffstat (limited to 'src/mesa')
-rw-r--r--src/mesa/drivers/dri/i965/brw_cc.c15
-rw-r--r--src/mesa/drivers/dri/i965/brw_wm.c3
-rw-r--r--src/mesa/drivers/dri/intel/intel_context.c2
-rw-r--r--src/mesa/drivers/dri/r300/r300_context.c21
-rw-r--r--src/mesa/drivers/dri/r300/r300_render.c16
-rw-r--r--src/mesa/drivers/dri/r300/r300_state.c40
-rw-r--r--src/mesa/drivers/dri/radeon/radeon_screen.c5
-rw-r--r--src/mesa/drivers/dri/swrast/swrast.c2
-rw-r--r--src/mesa/main/enable.c7
-rw-r--r--src/mesa/main/extensions.c4
-rw-r--r--src/mesa/main/getstring.c11
-rw-r--r--src/mesa/main/mtypes.h30
-rw-r--r--src/mesa/main/stencil.c104
-rw-r--r--src/mesa/swrast/s_stencil.c6
14 files changed, 156 insertions, 110 deletions
diff --git a/src/mesa/drivers/dri/i965/brw_cc.c b/src/mesa/drivers/dri/i965/brw_cc.c
index fa8121e02d..abae4b3215 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 c50b0d2dd9..24149cf8a1 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/intel/intel_context.c b/src/mesa/drivers/dri/intel/intel_context.c
index a43e6be0d9..a68e217647 100644
--- a/src/mesa/drivers/dri/intel/intel_context.c
+++ b/src/mesa/drivers/dri/intel/intel_context.c
@@ -89,6 +89,7 @@ int INTEL_DEBUG = (0);
#define need_GL_EXT_multi_draw_arrays
#define need_GL_EXT_point_parameters
#define need_GL_EXT_secondary_color
+#define need_GL_EXT_stencil_two_side
#define need_GL_ATI_separate_stencil
#define need_GL_NV_point_sprite
#define need_GL_NV_vertex_program
@@ -413,6 +414,7 @@ static const struct dri_extension brw_extensions[] = {
{ "GL_ARB_texture_non_power_of_two", NULL },
{ "GL_ARB_vertex_shader", GL_ARB_vertex_shader_functions },
{ "GL_EXT_shadow_funcs", NULL },
+ { "GL_EXT_stencil_two_side", GL_EXT_stencil_two_side_functions },
{ "GL_EXT_texture_sRGB", NULL },
{ "GL_EXT_vertex_array_bgra", NULL },
{ "GL_ATI_separate_stencil", GL_ATI_separate_stencil_functions },
diff --git a/src/mesa/drivers/dri/r300/r300_context.c b/src/mesa/drivers/dri/r300/r300_context.c
index 37436275e3..dc4cd5731d 100644
--- a/src/mesa/drivers/dri/r300/r300_context.c
+++ b/src/mesa/drivers/dri/r300/r300_context.c
@@ -77,19 +77,21 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
int future_hw_tcl_on = 1;
int hw_tcl_on = 1;
-#define need_GL_EXT_stencil_two_side
+#define need_GL_VERSION_2_0
#define need_GL_ARB_multisample
#define need_GL_ARB_point_parameters
#define need_GL_ARB_texture_compression
#define need_GL_ARB_vertex_buffer_object
#define need_GL_ARB_vertex_program
+#define need_GL_EXT_blend_equation_separate
+#define need_GL_EXT_blend_func_separate
#define need_GL_EXT_blend_minmax
//#define need_GL_EXT_fog_coord
+#define need_GL_EXT_gpu_program_parameters
#define need_GL_EXT_multi_draw_arrays
#define need_GL_EXT_secondary_color
-#define need_GL_EXT_blend_equation_separate
-#define need_GL_EXT_blend_func_separate
-#define need_GL_EXT_gpu_program_parameters
+#define need_GL_EXT_stencil_two_side
+#define need_GL_ATI_separate_stencil
#define need_GL_NV_vertex_program
#include "extension_helper.h"
@@ -130,6 +132,7 @@ const struct dri_extension card_extensions[] = {
{"GL_EXT_texture_lod_bias", NULL},
{"GL_EXT_texture_mirror_clamp", NULL},
{"GL_EXT_texture_rectangle", NULL},
+ {"GL_ATI_separate_stencil", GL_ATI_separate_stencil_functions},
{"GL_ATI_texture_env_combine3", NULL},
{"GL_ATI_texture_mirror_once", NULL},
{"GL_MESA_pack_invert", NULL},
@@ -142,6 +145,16 @@ const struct dri_extension card_extensions[] = {
/* *INDENT-ON* */
};
+
+/**
+ * The GL 2.0 functions are needed to make display lists work with
+ * functions added by GL_ATI_separate_stencil.
+ */
+const struct dri_extension gl_20_extension[] = {
+ {"GL_VERSION_2_0", GL_VERSION_2_0_functions },
+};
+
+
extern struct tnl_pipeline_stage _r300_render_stage;
extern const struct tnl_pipeline_stage _r300_tcl_stage;
diff --git a/src/mesa/drivers/dri/r300/r300_render.c b/src/mesa/drivers/dri/r300/r300_render.c
index f9266e44c1..16ce4a1199 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 a63dbac343..d02034f039 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/drivers/dri/radeon/radeon_screen.c b/src/mesa/drivers/dri/radeon/radeon_screen.c
index 5f32dd575e..f5665c4af1 100644
--- a/src/mesa/drivers/dri/radeon/radeon_screen.c
+++ b/src/mesa/drivers/dri/radeon/radeon_screen.c
@@ -206,6 +206,8 @@ DRI_CONF_BEGIN
DRI_CONF_END;
static const GLuint __driNConfigOptions = 17;
+extern const struct dri_extension gl_20_extension[];
+
#ifndef RADEON_DEBUG
int RADEON_DEBUG = 0;
@@ -1140,6 +1142,7 @@ static void radeonDestroyContext(__DRIcontextPrivate * driContextPriv)
#endif
+
/**
* This is the driver specific part of the createNewScreen entry point.
*
@@ -1192,6 +1195,8 @@ radeonInitScreen(__DRIscreenPrivate *psp)
driInitSingleExtension( NULL, NV_vp_extension );
driInitSingleExtension( NULL, ATI_fs_extension );
driInitExtensions( NULL, point_extensions, GL_FALSE );
+#elif defined(RADEON_COMMON_FOR_R300)
+ driInitSingleExtension( NULL, gl_20_extension );
#endif
if (!radeonInitDriver(psp))
diff --git a/src/mesa/drivers/dri/swrast/swrast.c b/src/mesa/drivers/dri/swrast/swrast.c
index 15b57244dc..4197603871 100644
--- a/src/mesa/drivers/dri/swrast/swrast.c
+++ b/src/mesa/drivers/dri/swrast/swrast.c
@@ -72,6 +72,7 @@
#define need_GL_EXT_framebuffer_blit
#define need_GL_EXT_gpu_program_parameters
#define need_GL_EXT_paletted_texture
+#define need_GL_EXT_stencil_two_side
#define need_GL_IBM_multimode_draw_arrays
#define need_GL_MESA_resize_buffers
#define need_GL_NV_vertex_program
@@ -103,6 +104,7 @@ const struct dri_extension card_extensions[] =
{ "GL_EXT_framebuffer_blit", GL_EXT_framebuffer_blit_functions },
{ "GL_EXT_gpu_program_parameters", GL_EXT_gpu_program_parameters_functions },
{ "GL_EXT_paletted_texture", GL_EXT_paletted_texture_functions },
+ { "GL_EXT_stencil_two_side", GL_EXT_stencil_two_side_functions },
{ "GL_IBM_multimode_draw_arrays", GL_IBM_multimode_draw_arrays_functions },
{ "GL_MESA_resize_buffers", GL_MESA_resize_buffers_functions },
{ "GL_NV_vertex_program", GL_NV_vertex_program_functions },
diff --git a/src/mesa/main/enable.c b/src/mesa/main/enable.c
index dae576ae5a..1c026174b8 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/extensions.c b/src/mesa/main/extensions.c
index 8010823cf5..43c9d4a788 100644
--- a/src/mesa/main/extensions.c
+++ b/src/mesa/main/extensions.c
@@ -263,7 +263,7 @@ _mesa_enable_sw_extensions(GLcontext *ctx)
ctx->Extensions.EXT_secondary_color = GL_TRUE;
ctx->Extensions.EXT_shared_texture_palette = GL_TRUE;
ctx->Extensions.EXT_stencil_wrap = GL_TRUE;
- ctx->Extensions.EXT_stencil_two_side = GL_FALSE; /* obsolete */
+ ctx->Extensions.EXT_stencil_two_side = GL_TRUE;
ctx->Extensions.EXT_texture_env_add = GL_TRUE;
ctx->Extensions.EXT_texture_env_combine = GL_TRUE;
ctx->Extensions.EXT_texture_env_dot3 = GL_TRUE;
@@ -412,7 +412,7 @@ _mesa_enable_2_0_extensions(GLcontext *ctx)
#if FEATURE_ARB_shading_language_100
ctx->Extensions.ARB_shading_language_100 = GL_TRUE;
#endif
- ctx->Extensions.EXT_stencil_two_side = GL_FALSE; /* obsolete */
+ ctx->Extensions.EXT_stencil_two_side = GL_TRUE;
#if FEATURE_ARB_vertex_shader
ctx->Extensions.ARB_vertex_shader = GL_TRUE;
#endif
diff --git a/src/mesa/main/getstring.c b/src/mesa/main/getstring.c
index 94bf5de1e8..a9e22d340a 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 5c31f66ed1..39c988f3c8 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 2a4c38b1f2..b4ea9978d8 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 c925922463..2e84ddec71 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);
}