[3] WineD3D: Catch nop render state changes

Stefan Dösinger stefan at codeweavers.com
Fri Dec 15 12:16:36 CST 2006


SetRenderState should be used by other code in wined3d to reapply a render 
state. Redundant state changes are supposed to be cheap in d3d, but not in 
opengl, so we have to catch them ourselves.

This imposes a temporary problem for code calling SetRenderState to reapply a 
state. I have replaced the calls with dirtifying the states or applying them, 
depending on the position(before the general applying loop, or after it). 
That will be removed when the rest of the states are managed properly too, 
but its needed temporarily to prevent regressions.

Another issue is the startup: If the default render state is 0 then 
SetRenderState won't mark it dirty. Because of that all states are marked 
dirty in Init3D.
-------------- next part --------------
From 326d662b7dfed1ed0c6585e24470625a64705f7d Mon Sep 17 00:00:00 2001
From: Stefan Doesinger <stefan at codeweavers.com>
Date: Fri, 15 Dec 2006 18:54:57 +0100
Subject: [PATCH] WineD3D: Catch NOP SetRenderStates

---
 dlls/wined3d/device.c   |   47 +++++++++++++++++++++++++++++++----------------
 dlls/wined3d/drawprim.c |   16 ++--------------
 2 files changed, 33 insertions(+), 30 deletions(-)

diff --git a/dlls/wined3d/device.c b/dlls/wined3d/device.c
index e75ae6a..20b977a 100644
--- a/dlls/wined3d/device.c
+++ b/dlls/wined3d/device.c
@@ -2083,6 +2083,7 @@ static HRESULT WINAPI IWineD3DDeviceImpl
 static HRESULT WINAPI IWineD3DDeviceImpl_Init3D(IWineD3DDevice *iface, WINED3DPRESENT_PARAMETERS* pPresentationParameters, D3DCB_CREATEADDITIONALSWAPCHAIN D3DCB_CreateAdditionalSwapChain) {
     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
     IWineD3DSwapChainImpl *swapchain;
+    DWORD state;
 
     TRACE("(%p)->(%p,%p)\n", This, pPresentationParameters, D3DCB_CreateAdditionalSwapChain);
     if(This->d3d_initialized) return WINED3DERR_INVALIDCALL;
@@ -2163,6 +2164,15 @@ #endif
     /* Clear the screen */
     IWineD3DDevice_Clear((IWineD3DDevice *) This, 0, NULL, WINED3DCLEAR_STENCIL|WINED3DCLEAR_ZBUFFER|WINED3DCLEAR_TARGET, 0x00, 1.0, 0);
 
+    /* Mark all states dirty. The Setters will not mark a state dirty when the new value is equal to the old value
+     * This might create a problem in 2 situations:
+     * ->The D3D default value is 0, but the opengl default value is something else
+     * ->D3D7 unintialized D3D and reinitializes it. This way the context is destroyed, be the stateblock unchanged
+     */
+    for(state = 0; state <= STATE_HIGHEST; state++) {
+        IWineD3DDeviceImpl_MarkStateDirty(This, state);
+    }
+
     This->d3d_initialized = TRUE;
     return WINED3D_OK;
 }
@@ -3335,8 +3345,10 @@ static HRESULT WINAPI IWineD3DDeviceImpl
 static HRESULT WINAPI IWineD3DDeviceImpl_SetRenderState(IWineD3DDevice *iface, WINED3DRENDERSTATETYPE State, DWORD Value) {
 
     IWineD3DDeviceImpl  *This     = (IWineD3DDeviceImpl *)iface;
+    DWORD oldValue = This->stateBlock->renderState[State];
 
     TRACE("(%p)->state = %s(%d), value = %d\n", This, debug_d3drenderstate(State), State, Value);
+
     This->updateStateBlock->changed.renderState[State] = TRUE;
     This->updateStateBlock->set.renderState[State] = TRUE;
     This->updateStateBlock->renderState[State] = Value;
@@ -3347,7 +3359,12 @@ static HRESULT WINAPI IWineD3DDeviceImpl
         return WINED3D_OK;
     }
 
-    IWineD3DDeviceImpl_MarkStateDirty(This, STATE_RENDER(State));
+    /* Compared here and not before the assignment to allow proper stateblock recording */
+    if(Value == oldValue) {
+        TRACE("Application is setting the old value over, nothing to do\n");
+    } else {
+        IWineD3DDeviceImpl_MarkStateDirty(This, STATE_RENDER(State));
+    }
 
     return WINED3D_OK;
 }
@@ -4565,19 +4582,11 @@ #endif
         IWineD3DBaseTexture_Release(oldTexture);
     }
 
-    /* Reset color keying */
+    /* Color keying is affected by the texture. Temporarily mark the color key state (=alpha test)
+     * dirty until textures are integrated with the state management
+     */
     if(Stage == 0 && This->stateBlock->renderState[WINED3DRS_COLORKEYENABLE]) {
-        BOOL enable_ckey = FALSE;
-
-        if(pTexture) {
-            IWineD3DSurfaceImpl *surf = (IWineD3DSurfaceImpl *) ((IWineD3DTextureImpl *)pTexture)->surfaces[0];
-            if(surf->CKeyFlags & DDSD_CKSRCBLT) enable_ckey = TRUE;
-        }
-
-        if(enable_ckey) {
-            glAlphaFunc(GL_NOTEQUAL, 0.0);
-            checkGLcall("glAlphaFunc");
-        }
+        IWineD3DDeviceImpl_MarkStateDirty(This, STATE_RENDER(WINED3DRS_COLORKEYENABLE));
     }
 
     return WINED3D_OK;
@@ -6026,6 +6035,7 @@ static void device_reapply_stateblock(IW
 
     BOOL oldRecording;  
     IWineD3DStateBlockImpl *oldUpdateStateBlock;
+    DWORD i;
 
     /* Disable recording */
     oldUpdateStateBlock = This->updateStateBlock;
@@ -6036,6 +6046,13 @@ static void device_reapply_stateblock(IW
     /* Reapply the state block */ 
     IWineD3DStateBlock_Apply((IWineD3DStateBlock *)This->stateBlock);
 
+    /* Temporaryily mark all render states dirty to force reapplication
+     * until the context management for is integrated with the state management
+     */
+    for(i = 1; i < WINEHIGHEST_RENDER_STATE; i++) {
+        IWineD3DDeviceImpl_MarkStateDirty(This, STATE_RENDER(i));
+    }
+
     /* Restore recording */
     This->isRecordingState = oldRecording;
     This->updateStateBlock = oldUpdateStateBlock;
@@ -6049,7 +6066,6 @@ static void device_reapply_stateblock(IW
  * make this unnecessary */
 static void device_render_to_texture(IWineD3DDeviceImpl* This, BOOL isTexture) {
 
-    DWORD cullMode;
     BOOL oldRecording;
     IWineD3DStateBlockImpl *oldUpdateStateBlock;
 
@@ -6068,8 +6084,7 @@ static void device_render_to_texture(IWi
     }
     This->last_was_rhw = FALSE;
     This->proj_valid = FALSE;
-    IWineD3DDevice_GetRenderState((IWineD3DDevice*) This, WINED3DRS_CULLMODE, &cullMode);
-    IWineD3DDevice_SetRenderState((IWineD3DDevice*) This, WINED3DRS_CULLMODE, cullMode);
+    IWineD3DDeviceImpl_MarkStateDirty(This, WINED3DRS_CULLMODE);
 
     /* Restore recording */
     This->isRecordingState = oldRecording;
diff --git a/dlls/wined3d/drawprim.c b/dlls/wined3d/drawprim.c
index 38042ec..4dc8ced 100644
--- a/dlls/wined3d/drawprim.c
+++ b/dlls/wined3d/drawprim.c
@@ -332,20 +332,8 @@ static void primitiveInitState(
 
         } else if(This->stateBlock->renderState[WINED3DRS_FOGENABLE] 
                   && This->stateBlock->renderState[WINED3DRS_FOGVERTEXMODE] != WINED3DFOG_NONE) {
-            
-            if(GL_SUPPORT(EXT_FOG_COORD)) {
-                glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FRAGMENT_DEPTH_EXT);
-                checkGLcall("glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FRAGMENT_DEPTH_EXT)\n");
-                /* Reapply the fog range */
-                IWineD3DDevice_SetRenderState(iface, WINED3DRS_FOGSTART, This->stateBlock->renderState[WINED3DRS_FOGSTART]);
-                IWineD3DDevice_SetRenderState(iface, WINED3DRS_FOGEND, This->stateBlock->renderState[WINED3DRS_FOGEND]);
-                /* Restore the fog mode */
-                IWineD3DDevice_SetRenderState(iface, WINED3DRS_FOGTABLEMODE, This->stateBlock->renderState[WINED3DRS_FOGTABLEMODE]);
-            } else {
-                /* Enable GL_FOG again because we disabled it above */
-                glEnable(GL_FOG);
-                checkGLcall("glEnable(GL_FOG)");
-            }
+            /* Reapply the fog */
+            StateTable[STATE_RENDER(WINED3DRS_FOGENABLE)].apply(STATE_RENDER(WINED3DRS_FOGSTART), This->stateBlock);
         }
     }
 }
-- 
1.4.2.4



More information about the wine-patches mailing list