Stefan Dösinger : wined3d: Dirtify the shader and declaration states if the bound interface is destroyed .

Alexandre Julliard julliard at wine.codeweavers.com
Thu Apr 12 09:59:53 CDT 2007


Module: wine
Branch: master
Commit: 0d88a38238088ed5a36bbe56ec5c9b62106fa8c0
URL:    http://source.winehq.org/git/wine.git/?a=commit;h=0d88a38238088ed5a36bbe56ec5c9b62106fa8c0

Author: Stefan Dösinger <stefan at codeweavers.com>
Date:   Wed Apr 11 14:02:38 2007 +0200

wined3d: Dirtify the shader and declaration states if the bound interface is destroyed.

---

 dlls/wined3d/pixelshader.c       |   12 ++++++++++++
 dlls/wined3d/vertexdeclaration.c |    5 +++++
 dlls/wined3d/vertexshader.c      |    5 +++++
 3 files changed, 22 insertions(+), 0 deletions(-)

diff --git a/dlls/wined3d/pixelshader.c b/dlls/wined3d/pixelshader.c
index 962b3d5..6627c06 100644
--- a/dlls/wined3d/pixelshader.c
+++ b/dlls/wined3d/pixelshader.c
@@ -73,6 +73,18 @@ static ULONG  WINAPI IWineD3DPixelShaderImpl_Release(IWineD3DPixelShader *iface)
     TRACE("(%p) : Releasing from %d\n", This, This->ref);
     ref = InterlockedDecrement(&This->ref);
     if (ref == 0) {
+        /* SetPixelShader does not AddRef. If the bound pixel shader is destroyed, the pointer in the stateblock remains
+         * unchanged. Drawing again will most likely crash, even on windows. A problem can occur if the application creates
+         * a new pixel shader which resides at the same address. Then SetPixelShader will think it is a NOP change, and won't
+         * dirtify the state.
+         *
+         * Do NOT call GetPixelShader here. This will addRef and cause a recursion. And do NOT set the pixel shader to NULL,
+         * Windows does not do that(Although no test exists since they'd crash randomly)
+         */
+        if(iface == ((IWineD3DDeviceImpl *) This->baseShader.device)->stateBlock->pixelShader) {
+            IWineD3DDeviceImpl_MarkStateDirty((IWineD3DDeviceImpl *) This->baseShader.device, STATE_PIXELSHADER);
+        }
+
         if (This->baseShader.shader_mode == SHADER_GLSL && This->baseShader.prgId != 0) {
             struct list *linked_programs = &This->baseShader.linked_programs;
 
diff --git a/dlls/wined3d/vertexdeclaration.c b/dlls/wined3d/vertexdeclaration.c
index 099129b..bdf07b6 100644
--- a/dlls/wined3d/vertexdeclaration.c
+++ b/dlls/wined3d/vertexdeclaration.c
@@ -98,6 +98,11 @@ static ULONG WINAPI IWineD3DVertexDeclarationImpl_Release(IWineD3DVertexDeclarat
     TRACE("(%p) : Releasing from %d\n", This, This->ref);
     ref = InterlockedDecrement(&This->ref);
     if (ref == 0) {
+        if(iface == This->wineD3DDevice->stateBlock->vertexDecl) {
+            /* See comment in PixelShader::Release */
+            IWineD3DDeviceImpl_MarkStateDirty(This->wineD3DDevice, STATE_VDECL);
+        }
+
         HeapFree(GetProcessHeap(), 0, This->pDeclarationWine);
         HeapFree(GetProcessHeap(), 0, This);
     }
diff --git a/dlls/wined3d/vertexshader.c b/dlls/wined3d/vertexshader.c
index 22c49c2..f02dcdb 100644
--- a/dlls/wined3d/vertexshader.c
+++ b/dlls/wined3d/vertexshader.c
@@ -464,6 +464,11 @@ static ULONG WINAPI IWineD3DVertexShaderImpl_Release(IWineD3DVertexShader *iface
     TRACE("(%p) : Releasing from %d\n", This, This->ref);
     ref = InterlockedDecrement(&This->ref);
     if (ref == 0) {
+        if(iface == ((IWineD3DDeviceImpl *) This->baseShader.device)->stateBlock->vertexShader) {
+            /* See comment in PixelShader::Release */
+            IWineD3DDeviceImpl_MarkStateDirty((IWineD3DDeviceImpl *) This->baseShader.device, STATE_VSHADER);
+        }
+
         if (This->baseShader.shader_mode == SHADER_GLSL && This->baseShader.prgId != 0) {
             struct list *linked_programs = &This->baseShader.linked_programs;
 




More information about the wine-cvs mailing list