* \file stencil.c
* Stencil operations.
*
+ * Note: There's some conflict 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.
+ *
+ * Also, note that GL_ATI_separate_stencil is different as well:
+ * glStencilFuncSeparateATI(GLenum frontfunc, GLenum backfunc, ...) vs.
+ * glStencilFuncSeparate(GLenum face, GLenum func, ...).
+ *
+ * This problem is solved by keeping three sets of stencil state:
+ * state[0] = GL_FRONT state.
+ * state[1] = OpenGL 2.0 / GL_ATI_separate_stencil GL_BACK state.
+ * state[2] = GL_EXT_stencil_two_side GL_BACK state.
*/
{
const GLint face = ctx->Stencil._BackFace;
- ctx->Stencil._TestTwoSide =
+ ctx->Stencil._Enabled = (ctx->Stencil.Enabled &&
+ ctx->DrawBuffer->Visual.stencilBits > 0);
+
+ ctx->Stencil._TestTwoSide =
+ ctx->Stencil._Enabled &&
(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.Enabled = GL_FALSE;
ctx->Stencil.TestTwoSide = GL_FALSE;
- ctx->Stencil.ActiveFace = 0; /* 0 = GL_FRONT, 1 = GL_BACK */
+ ctx->Stencil.ActiveFace = 0; /* 0 = GL_FRONT, 2 = GL_BACK */
ctx->Stencil.Function[0] = GL_ALWAYS;
ctx->Stencil.Function[1] = GL_ALWAYS;
ctx->Stencil.Function[2] = GL_ALWAYS;
ctx->Stencil.WriteMask[1] = ~0U;
ctx->Stencil.WriteMask[2] = ~0U;
ctx->Stencil.Clear = 0;
+ ctx->Stencil._BackFace = 1;
}