wined3d: fix stencil related renderstates.

Jan Zerebecki jan.wine at zerebecki.de
Fri Jun 9 10:32:18 CDT 2006


If this patch is rejected from inclusion, please tell me why, as i would have to
ask anyway.

From: Jan Zerebecki <jan.wine at zerebecki.de>
Changelog:
wined3d: fix stencil related renderstates.
---

 dlls/wined3d/device.c          |  402 +++++++++++++++-------------------------
 dlls/wined3d/utils.c           |   18 ++
 dlls/wined3d/wined3d_private.h |    2 
 3 files changed, 170 insertions(+), 252 deletions(-)

diff --git a/dlls/wined3d/device.c b/dlls/wined3d/device.c
index 13d497c..305fc10 100644
--- a/dlls/wined3d/device.c
+++ b/dlls/wined3d/device.c
@@ -2969,6 +2969,146 @@ HRESULT WINAPI IWineD3DDeviceImpl_GetVie
     return WINED3D_OK;
 }
 
+void renderstate_stencil_twosided(
+        IWineD3DDeviceImpl *This,
+        GLint face,
+        GLint func,
+        GLint ref,
+        GLuint mask,
+        GLint stencilFail,
+        GLint depthFail,
+        GLint stencilPass ) {
+#if 0 /* Don't use OpenGL 2.0 calls for now */
+            if(GL_EXTCALL(glStencilFuncSeparate) && GL_EXTCALL(glStencilOpSeparate)) {
+                GL_EXTCALL(glStencilFuncSeparate(face, func, ref, mask));
+                checkGLcall("glStencilFuncSeparate(...)");
+                GL_EXTCALL(glStencilOpSeparate(face, stencilFail, depthFail, stencilPass));
+                checkGLcall("glStencilOpSeparate(...)");
+            }
+            else
+#endif
+            if(GL_SUPPORT(EXT_STENCIL_TWO_SIDE)) {
+                glEnable(GL_STENCIL_TEST_TWO_SIDE_EXT);
+                checkGLcall("glEnable(GL_STENCIL_TEST_TWO_SIDE_EXT)");
+                GL_EXTCALL(glActiveStencilFaceEXT(face));
+                checkGLcall("glActiveStencilFaceEXT(...)");
+                glStencilFunc(func, ref, mask);
+                checkGLcall("glStencilFunc(...)");
+                glStencilOp(stencilFail, depthFail, stencilPass);
+                checkGLcall("glStencilOp(...)");
+            } else if(GL_SUPPORT(ATI_SEPARATE_STENCIL)) {
+                GL_EXTCALL(glStencilFuncSeparateATI(face, func, ref, mask));
+                checkGLcall("glStencilFuncSeparateATI(...)");
+                GL_EXTCALL(glStencilOpSeparateATI(face, stencilFail, depthFail, stencilPass));
+                checkGLcall("glStencilOpSeparateATI(...)");
+            } else {
+                ERR("Separate (two sided) stencil not supported on this version of opengl. Caps weren't honored?\n");
+            }
+}
+
+void renderstate_stencil(IWineD3DDeviceImpl *This, D3DRENDERSTATETYPE State, DWORD Value) {
+    DWORD onesided_enable = FALSE;
+    if( This->stateBlock->set.renderState[WINED3DRS_STENCILENABLE] )
+        onesided_enable = This->stateBlock->renderState[WINED3DRS_STENCILENABLE];
+    DWORD twosided_enable = FALSE;
+    if( This->stateBlock->set.renderState[WINED3DRS_TWOSIDEDSTENCILMODE] )
+        twosided_enable = This->stateBlock->renderState[WINED3DRS_TWOSIDEDSTENCILMODE];
+    GLint func = GL_ALWAYS;
+    if( This->stateBlock->set.renderState[WINED3DRS_STENCILFUNC] )
+        func = StencilFunc(This->stateBlock->renderState[WINED3DRS_STENCILFUNC]);
+    GLint func_ccw = GL_ALWAYS;
+    if( This->stateBlock->set.renderState[WINED3DRS_CCW_STENCILFUNC] )
+        func_ccw = StencilFunc(This->stateBlock->renderState[WINED3DRS_CCW_STENCILFUNC]);
+    GLint ref = 0;
+    if( This->stateBlock->set.renderState[WINED3DRS_STENCILREF] )
+        ref = This->stateBlock->renderState[WINED3DRS_STENCILREF];
+    GLuint mask = 0;
+    if( This->stateBlock->set.renderState[WINED3DRS_STENCILMASK] )
+        mask = This->stateBlock->renderState[WINED3DRS_STENCILMASK];
+    GLint stencilFail = GL_KEEP;
+    if( This->stateBlock->set.renderState[WINED3DRS_STENCILFAIL] )
+        stencilFail = StencilOp(This->stateBlock->renderState[WINED3DRS_STENCILFAIL]);
+    GLint depthFail = GL_KEEP;
+    if( This->stateBlock->set.renderState[WINED3DRS_STENCILZFAIL] )
+        depthFail = StencilOp(This->stateBlock->renderState[WINED3DRS_STENCILZFAIL]);
+    GLint stencilPass = GL_KEEP;
+    if( This->stateBlock->set.renderState[WINED3DRS_STENCILPASS] )
+        stencilPass = StencilOp(This->stateBlock->renderState[WINED3DRS_STENCILPASS]);
+    GLint stencilFail_ccw = GL_KEEP;
+    if( This->stateBlock->set.renderState[WINED3DRS_CCW_STENCILFAIL] )
+        stencilFail_ccw = StencilOp(This->stateBlock->renderState[WINED3DRS_CCW_STENCILFAIL]);
+    GLint depthFail_ccw = GL_KEEP;
+    if( This->stateBlock->set.renderState[WINED3DRS_CCW_STENCILZFAIL] )
+        depthFail_ccw = StencilOp(This->stateBlock->renderState[WINED3DRS_CCW_STENCILZFAIL]);
+    GLint stencilPass_ccw = GL_KEEP;
+    if( This->stateBlock->set.renderState[WINED3DRS_CCW_STENCILPASS] )
+        stencilPass_ccw = StencilOp(This->stateBlock->renderState[WINED3DRS_CCW_STENCILPASS]);
+    switch(State) {
+        case WINED3DRS_STENCILENABLE :
+            onesided_enable = Value;
+            break;
+        case WINED3DRS_TWOSIDEDSTENCILMODE :
+            twosided_enable = Value;
+            break;
+        case WINED3DRS_STENCILFUNC :
+            func = StencilFunc(Value);
+            break;
+        case WINED3DRS_CCW_STENCILFUNC :
+            func_ccw = StencilFunc(Value);
+            break;
+        case WINED3DRS_STENCILREF :
+            ref = Value;
+            break;
+        case WINED3DRS_STENCILMASK :
+            mask = Value;
+            break;
+        case WINED3DRS_STENCILFAIL :
+            stencilFail = StencilOp(Value);
+            break;
+        case WINED3DRS_STENCILZFAIL :
+            depthFail = StencilOp(Value);
+            break;
+        case WINED3DRS_STENCILPASS :
+            stencilPass = StencilOp(Value);
+            break;
+        case WINED3DRS_CCW_STENCILFAIL :
+            stencilFail_ccw = StencilOp(Value);
+            break;
+        case WINED3DRS_CCW_STENCILZFAIL :
+            depthFail_ccw = StencilOp(Value);
+            break;
+        case WINED3DRS_CCW_STENCILPASS :
+            stencilPass_ccw = StencilOp(Value);
+            break;
+        default :
+            ERR("This should not happen!");
+    }
+
+    TRACE("(onesided %ld, twosided %ld, ref %x, mask %x,  \
+        GL_FRONT: func: %x, fail %x, zfail %x, zpass %x  \
+        GL_BACK: func: %x, fail %x, zfail %x, zpass %x )\n",
+            onesided_enable, twosided_enable, ref, mask,
+            func, stencilFail, depthFail, stencilPass,
+            func_ccw, stencilFail_ccw, depthFail_ccw, stencilPass_ccw);
+
+    if (twosided_enable) {
+        renderstate_stencil_twosided(This, GL_FRONT, func, ref, mask, stencilFail, depthFail, stencilPass);
+        renderstate_stencil_twosided(This, GL_BACK, func_ccw, ref, mask, stencilFail_ccw, depthFail_ccw, stencilPass_ccw);
+    } else {
+        if (onesided_enable) {
+            glEnable(GL_STENCIL_TEST);
+            checkGLcall("glEnable GL_STENCIL_TEST");
+            glStencilFunc(func, ref, mask);
+            checkGLcall("glStencilFunc(...)");
+            glStencilOp(stencilFail, depthFail, stencilPass);
+            checkGLcall("glStencilOp(...)");
+        } else {
+            glDisable(GL_STENCIL_TEST);
+            checkGLcall("glDisable GL_STENCIL_TEST");
+        }
+    }
+}
+
 /*****
  * Get / Set Render States
  * TODO: Verify against dx9 definitions
@@ -3397,145 +3537,20 @@ HRESULT WINAPI IWineD3DDeviceImpl_SetRen
         }
         break;
 
-    case WINED3DRS_STENCILENABLE             :
-        if (Value) {
-            glEnable(GL_STENCIL_TEST);
-            checkGLcall("glEnable GL_STENCIL_TEST");
-        } else {
-            glDisable(GL_STENCIL_TEST);
-            checkGLcall("glDisable GL_STENCIL_TEST");
-        }
-        break;
-
+    case WINED3DRS_STENCILENABLE :
+    case WINED3DRS_TWOSIDEDSTENCILMODE :
     case WINED3DRS_STENCILFUNC :
-    {
-        GLint func;
-        GLint ref = This->stateBlock->renderState[WINED3DRS_STENCILREF];
-        GLuint mask = This->stateBlock->renderState[WINED3DRS_STENCILMASK];
-
-        func = GL_ALWAYS;
-        switch ((D3DCMPFUNC)Value) {
-            case D3DCMP_NEVER: func = GL_NEVER; break;
-            case D3DCMP_LESS: func = GL_LESS; break;
-            case D3DCMP_EQUAL: func = GL_EQUAL; break;
-            case D3DCMP_LESSEQUAL: func = GL_LEQUAL; break;
-            case D3DCMP_GREATER: func = GL_GREATER; break;
-            case D3DCMP_NOTEQUAL: func = GL_NOTEQUAL; break;
-            case D3DCMP_GREATEREQUAL: func = GL_GEQUAL; break;
-            case D3DCMP_ALWAYS: func = GL_ALWAYS; break;
-            default:
-                FIXME("Unrecognized/Unhandled D3DCMPFUNC value %ld\n", Value);
-        }
-        This->stencilfunc = func;
-        if(!This->stateBlock->renderState[WINED3DRS_TWOSIDEDSTENCILMODE]) {
-#if 0 /* Don't use OpenGL 2.0 calls for now */
-            if(GL_EXTCALL(glStencilFuncSeparate)) {
-                GL_EXTCALL(glStencilFuncSeparate(GL_FRONT, func, ref, mask));
-                checkGLcall("glStencilFuncSeparate(GL_FRONT,...)");
-            }
-            else
-#endif
-	    if(GL_SUPPORT(EXT_STENCIL_TWO_SIDE)) {
-                glEnable(GL_STENCIL_TEST_TWO_SIDE_EXT);
-                checkGLcall("glEnable(GL_STENCIL_TEST_TWO_SIDE_EXT)");
-                GL_EXTCALL(glActiveStencilFaceEXT(GL_FRONT));
-                checkGLcall("glActiveStencilFaceEXT(GL_FRONT)");
-                glStencilFunc(func, ref, mask);
-                checkGLcall("glStencilFunc(...)");
-            }
-            else if(GL_SUPPORT(ATI_SEPARATE_STENCIL)) {
-                GL_EXTCALL(glStencilFuncSeparateATI(GL_FRONT, func, ref, mask));
-                checkGLcall("glStencilFuncSeparateATI(GL_FRONT,...)");
-            } else {
-                TRACE("Separate stencil function not supported on this version of opengl");
-                glStencilFunc(func, ref, mask);
-                checkGLcall("glStencilFunc(...)");
-            }
-        } else {
-            glStencilFunc(func, ref, mask);
-            checkGLcall("glStencilFunc(...)");
-        }
-        break;
-    }
-    case WINED3DRS_STENCILREF                :
-        {
-           int glParm = This->stencilfunc;
-           int ref = 0;
-           GLuint mask = This->stateBlock->renderState[WINED3DRS_STENCILMASK];
-
-           ref = Value;
-           TRACE("glStencilFunc with Parm=%x, ref=%d, mask=%x\n", glParm, ref, mask);
-           glStencilFunc(glParm, ref, mask);
-           checkGLcall("glStencilFunc");
-        }
-        break;
-
-    case WINED3DRS_STENCILMASK               :
-        {
-           int glParm = This->stencilfunc;
-           int ref = This->stateBlock->renderState[WINED3DRS_STENCILREF];
-           GLuint mask = Value;
-
-           TRACE("glStencilFunc with Parm=%x, ref=%d, mask=%x\n", glParm, ref, mask);
-           glStencilFunc(glParm, ref, mask);
-           checkGLcall("glStencilFunc");
-        }
-        break;
-
-    case WINED3DRS_STENCILFAIL               :
-    case WINED3DRS_STENCILZFAIL              :
-    case WINED3DRS_STENCILPASS               :
-    {
-        GLint stencilFail;
-        GLint depthFail;
-        GLint stencilPass;
-
-        GLint action = StencilOp(Value);
-
-        glGetIntegerv(GL_STENCIL_FAIL, &stencilFail);
-        glGetIntegerv(GL_STENCIL_PASS_DEPTH_FAIL, &depthFail);
-        glGetIntegerv(GL_STENCIL_PASS_DEPTH_PASS, &stencilPass);
-
-        if(WINED3DRS_STENCILFAIL == State) {
-            stencilFail = action;
-        }
-        else if(WINED3DRS_STENCILZFAIL == State) {
-            depthFail = action;
-        }
-        else if(WINED3DRS_STENCILPASS == State) {
-            stencilPass = action;
-        }
-
-        if(!This->stateBlock->renderState[WINED3DRS_TWOSIDEDSTENCILMODE]) {
-#if 0 /* Don't use OpenGL 2.0 calls for now */
-            if(GL_EXTCALL(glStencilOpSeparate)) {
-                GL_EXTCALL(glStencilOpSeparate(GL_FRONT, stencilFail, depthFail, stencilPass));
-                checkGLcall("glStencilOpSeparate(GL_FRONT,...)");
-            }
-            else
-#endif
-	    if(GL_SUPPORT(EXT_STENCIL_TWO_SIDE)) {
-                glEnable(GL_STENCIL_TEST_TWO_SIDE_EXT);
-                checkGLcall("glEnable(GL_STENCIL_TEST_TWO_SIDE_EXT)");
-                GL_EXTCALL(glActiveStencilFaceEXT(GL_FRONT));
-                checkGLcall("glActiveStencilFaceEXT(GL_FRONT)");
-                glStencilOp(stencilFail, depthFail, stencilPass);
-                checkGLcall("glStencilOp(...)");
-            }
-            else if(GL_SUPPORT(ATI_SEPARATE_STENCIL)) {
-                GL_EXTCALL(glStencilOpSeparateATI(GL_FRONT, stencilFail, depthFail, stencilPass));
-                checkGLcall("glStencilOpSeparateATI(GL_FRONT,...)");
-            } else {
-                TRACE("Separate stencil operation not supported on this version of opengl");
-                glStencilOp(stencilFail, depthFail, stencilPass);
-                checkGLcall("glStencilOp(...)");
-            }
-        } else {
-            glStencilOp(stencilFail, depthFail, stencilPass);
-            checkGLcall("glStencilOp(...)");
-        }
+    case WINED3DRS_CCW_STENCILFUNC :
+    case WINED3DRS_STENCILREF :
+    case WINED3DRS_STENCILMASK :
+    case WINED3DRS_STENCILFAIL :
+    case WINED3DRS_STENCILZFAIL :
+    case WINED3DRS_STENCILPASS :
+    case WINED3DRS_CCW_STENCILFAIL :
+    case WINED3DRS_CCW_STENCILZFAIL :
+    case WINED3DRS_CCW_STENCILPASS :
+        renderstate_stencil(This, State, Value);
         break;
-    }
     case WINED3DRS_STENCILWRITEMASK          :
         {
             glStencilMask(Value);
@@ -4023,119 +4038,6 @@ HRESULT WINAPI IWineD3DDeviceImpl_SetRen
         }
         break;
     }
-    case WINED3DRS_TWOSIDEDSTENCILMODE :
-    {
-        if(Value) {
-            TRACE("Two-sided stencil mode enabled\n");
-        } else {
-            TRACE("Two-sided stencil mode disabled\n");
-        }
-        break;
-    }
-    case WINED3DRS_CCW_STENCILFAIL :
-    case WINED3DRS_CCW_STENCILZFAIL :
-    case WINED3DRS_CCW_STENCILPASS :
-    {
-        GLint stencilFail;
-        GLint depthFail;
-        GLint stencilPass;
-
-        GLint action = StencilOp(Value);
-
-        glGetIntegerv(GL_STENCIL_BACK_FAIL, &stencilFail);
-        glGetIntegerv(GL_STENCIL_BACK_PASS_DEPTH_FAIL, &depthFail);
-        glGetIntegerv(GL_STENCIL_BACK_PASS_DEPTH_PASS, &stencilPass);
-
-        if(WINED3DRS_CCW_STENCILFAIL == State) {
-            stencilFail = action;
-        }
-        else if(WINED3DRS_CCW_STENCILZFAIL == State) {
-            depthFail = action;
-        }
-        else if(WINED3DRS_CCW_STENCILPASS == State) {
-            stencilPass = action;
-        }
-
-        if(!This->stateBlock->renderState[WINED3DRS_TWOSIDEDSTENCILMODE]) {
-#if 0 /* Don't use OpenGL 2.0 calls for now */
-            if(GL_EXTCALL(glStencilOpSeparate)) {
-                GL_EXTCALL(glStencilOpSeparate(GL_BACK, stencilFail, depthFail, stencilPass));
-                checkGLcall("glStencilOpSeparate(GL_BACK,...)");
-            }
-            else
-#endif
-	    if(GL_SUPPORT(EXT_STENCIL_TWO_SIDE)) {
-                glEnable(GL_STENCIL_TEST_TWO_SIDE_EXT);
-                checkGLcall("glEnable(GL_STENCIL_TEST_TWO_SIDE_EXT)");
-                GL_EXTCALL(glActiveStencilFaceEXT(GL_BACK));
-                checkGLcall("glActiveStencilFaceEXT(GL_BACK)");
-                glStencilOp(stencilFail, depthFail, stencilPass);
-                checkGLcall("glStencilOp(...)");
-            }
-            else if(GL_SUPPORT(ATI_SEPARATE_STENCIL)) {
-                GL_EXTCALL(glStencilOpSeparateATI(GL_BACK, stencilFail, depthFail, stencilPass));
-                checkGLcall("glStencilOpSeparateATI(GL_BACK,...)");
-            } else {
-                TRACE("Separate stencil operation not supported on this version of opengl");
-                glStencilOp(stencilFail, depthFail, stencilPass);
-                checkGLcall("glStencilOp(...)");
-            }
-        } else {
-            glStencilOp(stencilFail, depthFail, stencilPass);
-            checkGLcall("glStencilOp(...)");
-        }
-        break;
-    }
-    case WINED3DRS_CCW_STENCILFUNC :
-    {
-        GLint func;
-        GLint ref = This->stateBlock->renderState[WINED3DRS_STENCILREF];
-        GLuint mask = This->stateBlock->renderState[WINED3DRS_STENCILMASK];
-
-        func = GL_ALWAYS;
-        switch ((D3DCMPFUNC)Value) {
-            case D3DCMP_NEVER: func = GL_NEVER; break;
-            case D3DCMP_LESS: func = GL_LESS; break;
-            case D3DCMP_EQUAL: func = GL_EQUAL; break;
-            case D3DCMP_LESSEQUAL: func = GL_LEQUAL; break;
-            case D3DCMP_GREATER: func = GL_GREATER; break;
-            case D3DCMP_NOTEQUAL: func = GL_NOTEQUAL; break;
-            case D3DCMP_GREATEREQUAL: func = GL_GEQUAL; break;
-            case D3DCMP_ALWAYS: func = GL_ALWAYS; break;
-            default:
-                FIXME("Unrecognized/Unhandled D3DCMPFUNC value %ld\n", Value);
-        }
-        This->stencilfunc = func;
-        if(!This->stateBlock->renderState[WINED3DRS_TWOSIDEDSTENCILMODE]) {
-#if 0 /* Don't use OpenGL 2.0 calls for now */
-            if(GL_EXTCALL(glStencilFuncSeparate)) {
-                GL_EXTCALL(glStencilFuncSeparate(GL_BACK, func, ref, mask));
-                checkGLcall("glStencilFuncSeparate(GL_BACK,...)");
-            }
-            else
-#endif
-	    if(GL_SUPPORT(EXT_STENCIL_TWO_SIDE)) {
-                glEnable(GL_STENCIL_TEST_TWO_SIDE_EXT);
-                checkGLcall("glEnable(GL_STENCIL_TEST_TWO_SIDE_EXT)");
-                GL_EXTCALL(glActiveStencilFaceEXT(GL_BACK));
-                checkGLcall("glActiveStencilFaceEXT(GL_BACK)");
-                glStencilFunc(func, ref, mask);
-                checkGLcall("glStencilFunc(...)");
-            }
-            else if(GL_SUPPORT(ATI_SEPARATE_STENCIL)) {
-                GL_EXTCALL(glStencilFuncSeparateATI(GL_BACK, func, ref, mask));
-                checkGLcall("glStencilFuncSeparateATI(GL_BACK,...)");
-            } else {
-                TRACE("Separate stencil function not supported on this version of opengl");
-                glStencilFunc(func, ref, mask);
-                checkGLcall("glStencilFunc(...)");
-            }
-        } else {
-            glStencilFunc(func, ref, mask);
-            checkGLcall("glStencilFunc(...)");
-        }
-        break;
-    }
     case WINED3DRS_DEPTHBIAS :
     {
         if(Value) {
diff --git a/dlls/wined3d/utils.c b/dlls/wined3d/utils.c
index 555ad23..0d7f99b 100644
--- a/dlls/wined3d/utils.c
+++ b/dlls/wined3d/utils.c
@@ -405,7 +405,23 @@ GLenum StencilOp(DWORD op) {
     case D3DSTENCILOP_INCR    : return GL_INCR_WRAP_EXT;
     case D3DSTENCILOP_DECR    : return GL_DECR_WRAP_EXT;
     default:
-        FIXME("Invalid stencil op %ld\n", op);
+        FIXME("Unrecognized stencil op %ld\n", op);
+        return GL_KEEP;
+    }
+}
+
+GLenum StencilFunc(DWORD func) {
+    switch ((D3DCMPFUNC)func) {
+    case D3DCMP_NEVER        : return GL_NEVER;
+    case D3DCMP_LESS         : return GL_LESS;
+    case D3DCMP_EQUAL        : return GL_EQUAL;
+    case D3DCMP_LESSEQUAL    : return GL_LEQUAL;
+    case D3DCMP_GREATER      : return GL_GREATER;
+    case D3DCMP_NOTEQUAL     : return GL_NOTEQUAL;
+    case D3DCMP_GREATEREQUAL : return GL_GEQUAL;
+    case D3DCMP_ALWAYS       : return GL_ALWAYS;
+    default:
+        FIXME("Unrecognized D3DCMPFUNC value %ld\n", func);
         return GL_ALWAYS;
     }
 }
diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h
index 3a42228..96c3e79 100644
--- a/dlls/wined3d/wined3d_private.h
+++ b/dlls/wined3d/wined3d_private.h
@@ -482,7 +482,6 @@ typedef struct IWineD3DDeviceImpl
     UINT                    srcBlend;
     UINT                    dstBlend;
     UINT                    alphafunc;
-    UINT                    stencilfunc;
     BOOL                    texture_shader_active;  /* TODO: Confirm use is correct */
     BOOL                    last_was_notclipped;
 
@@ -1159,6 +1158,7 @@ const char* debug_d3dpool(WINED3DPOOL po
 
 /* Routines for GL <-> D3D values */
 GLenum StencilOp(DWORD op);
+GLenum StencilFunc(DWORD func);
 void   set_tex_op(IWineD3DDevice *iface, BOOL isAlpha, int Stage, D3DTEXTUREOP op, DWORD arg1, DWORD arg2, DWORD arg3);
 void   set_texture_matrix(const float *smat, DWORD flags, BOOL calculatedCoords);
 void   GetSrcAndOpFromValue(DWORD iValue, BOOL isAlphaArg, GLenum* source, GLenum* operand);



More information about the wine-patches mailing list