From 0d88a38238088ed5a36bbe56ec5c9b62106fa8c0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Stefan=20D=C3=B6singer?= Date: Wed, 11 Apr 2007 14:02:38 +0200 Subject: [PATCH] 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(+) diff --git a/dlls/wined3d/pixelshader.c b/dlls/wined3d/pixelshader.c index 962b3d5727b..6627c064773 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 099129bbb3f..bdf07b6d584 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 22c49c20e46..f02dcdb6072 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;