From 46572f682ceb651803d7ef6c166d514381ff42a2 Mon Sep 17 00:00:00 2001 From: Henri Verbeet Date: Mon, 15 Dec 2008 16:35:13 +0100 Subject: [PATCH] wined3d: Refuse to create shaders with a NULL function. --- dlls/d3d8/device.c | 59 +++++++++++++++++++++++++++++----------- dlls/d3d8/vertexshader.c | 2 +- dlls/d3d9/tests/shader.c | 10 ++++++- dlls/wined3d/device.c | 5 ++++ 4 files changed, 58 insertions(+), 18 deletions(-) diff --git a/dlls/d3d8/device.c b/dlls/d3d8/device.c index 58f698a57f0..41d85545d58 100644 --- a/dlls/d3d8/device.c +++ b/dlls/d3d8/device.c @@ -1599,20 +1599,28 @@ static HRESULT WINAPI IDirect3DDevice8Impl_CreateVertexShader(LPDIRECT3DDEVICE8 wined3d_vertex_declaration = ((IDirect3DVertexDeclaration8Impl *)object->vertex_declaration)->wined3d_vertex_declaration; - /* Usage is missing ... Use SetRenderState to set the sw vp render state in SetVertexShader */ - hrc = IWineD3DDevice_CreateVertexShader(This->WineD3DDevice, wined3d_vertex_declaration, pFunction, &object->wineD3DVertexShader, (IUnknown *)object); + if (pFunction) + { + /* Usage is missing ... Use SetRenderState to set the sw vp render state in SetVertexShader */ + hrc = IWineD3DDevice_CreateVertexShader(This->WineD3DDevice, wined3d_vertex_declaration, + pFunction, &object->wineD3DVertexShader, (IUnknown *)object); - if (FAILED(hrc)) { - /* free up object */ - FIXME("Call to IWineD3DDevice_CreateVertexShader failed\n"); - free_shader_handle(This, handle); - IDirect3DVertexDeclaration8_Release(object->vertex_declaration); - HeapFree(GetProcessHeap(), 0, object); - *ppShader = 0; - } else { - load_local_constants(pDeclaration, object->wineD3DVertexShader); - TRACE("(%p) : returning %p (handle %#x)\n", This, object, *ppShader); + if (FAILED(hrc)) + { + /* free up object */ + FIXME("Call to IWineD3DDevice_CreateVertexShader failed\n"); + free_shader_handle(This, handle); + IDirect3DVertexDeclaration8_Release(object->vertex_declaration); + HeapFree(GetProcessHeap(), 0, object); + *ppShader = 0; + } + else + { + load_local_constants(pDeclaration, object->wineD3DVertexShader); + TRACE("(%p) : returning %p (handle %#x)\n", This, object, *ppShader); + } } + LeaveCriticalSection(&d3d8_cs); return hrc; @@ -1706,9 +1714,19 @@ static HRESULT WINAPI IDirect3DDevice8Impl_SetVertexShader(LPDIRECT3DDEVICE8 ifa hrc = D3DERR_INVALIDCALL; } else { IDirect3DVertexShader8Impl *shader = This->shader_handles[pShader - (VS_HIGHESTFIXEDFXF + 1)]; - IWineD3DDevice_SetVertexDeclaration(This->WineD3DDevice, - shader ? ((IDirect3DVertexDeclaration8Impl *)shader->vertex_declaration)->wined3d_vertex_declaration : NULL); - hrc = IWineD3DDevice_SetVertexShader(This->WineD3DDevice, 0 == shader ? NULL : shader->wineD3DVertexShader); + + if (shader) + { + hrc = IWineD3DDevice_SetVertexDeclaration(This->WineD3DDevice, + ((IDirect3DVertexDeclaration8Impl *)shader->vertex_declaration)->wined3d_vertex_declaration); + if (SUCCEEDED(hrc)) + hrc = IWineD3DDevice_SetVertexShader(This->WineD3DDevice, shader->wineD3DVertexShader); + } + else + { + hrc = IWineD3DDevice_SetVertexDeclaration(This->WineD3DDevice, NULL); + if (SUCCEEDED(hrc)) hrc = IWineD3DDevice_SetVertexShader(This->WineD3DDevice, NULL); + } } } TRACE("(%p) : returning hr(%u)\n", This, hrc); @@ -1860,7 +1878,16 @@ static HRESULT WINAPI IDirect3DDevice8Impl_GetVertexShaderFunction(LPDIRECT3DDEV } shader = This->shader_handles[pVertexShader - (VS_HIGHESTFIXEDFXF + 1)]; - hr = IWineD3DVertexShader_GetFunction(shader->wineD3DVertexShader, pData, pSizeOfData); + if (shader->wineD3DVertexShader) + { + hr = IWineD3DVertexShader_GetFunction(shader->wineD3DVertexShader, pData, pSizeOfData); + } + else + { + *pSizeOfData = 0; + hr = D3D_OK; + } + LeaveCriticalSection(&d3d8_cs); return hr; } diff --git a/dlls/d3d8/vertexshader.c b/dlls/d3d8/vertexshader.c index bdc668541c2..8cd822b2744 100644 --- a/dlls/d3d8/vertexshader.c +++ b/dlls/d3d8/vertexshader.c @@ -57,7 +57,7 @@ static ULONG WINAPI IDirect3DVertexShader8Impl_Release(IDirect3DVertexShader8 *i if (ref == 0) { IDirect3DVertexDeclaration8_Release(This->vertex_declaration); - IWineD3DVertexShader_Release(This->wineD3DVertexShader); + if (This->wineD3DVertexShader) IWineD3DVertexShader_Release(This->wineD3DVertexShader); HeapFree(GetProcessHeap(), 0, This); } return ref; diff --git a/dlls/d3d9/tests/shader.c b/dlls/d3d9/tests/shader.c index dcf88519dc5..522f1280f2e 100644 --- a/dlls/d3d9/tests/shader.c +++ b/dlls/d3d9/tests/shader.c @@ -90,7 +90,11 @@ static void test_get_set_vertex_shader(IDirect3DDevice9 *device_ptr) HRESULT hret = 0; int shader_refcount = 0; int i = 0; - + + hret = IDirect3DDevice9_CreateVertexShader(device_ptr, NULL, &shader_ptr); + ok(hret == D3DERR_INVALIDCALL, "CreateVertexShader returned %#x, expected D3DERR_INVALIDCALL (%#x).\n", + hret, D3DERR_INVALIDCALL); + hret = IDirect3DDevice9_CreateVertexShader(device_ptr, simple_vs, &shader_ptr); ok(hret == D3D_OK && shader_ptr != NULL, "CreateVertexShader returned: hret 0x%x, shader_ptr %p. " "Expected hret 0x%x, shader_ptr != %p. Aborting.\n", hret, shader_ptr, D3D_OK, NULL); @@ -155,6 +159,10 @@ static void test_get_set_pixel_shader(IDirect3DDevice9 *device_ptr) int shader_refcount = 0; int i = 0; + hret = IDirect3DDevice9_CreatePixelShader(device_ptr, NULL, &shader_ptr); + ok(hret == D3DERR_INVALIDCALL, "CreatePixelShader returned %#x, expected D3DERR_INVALIDCALL (%#x).\n", + hret, D3DERR_INVALIDCALL); + hret = IDirect3DDevice9_CreatePixelShader(device_ptr, simple_ps, &shader_ptr); ok(hret == D3D_OK && shader_ptr != NULL, "CreatePixelShader returned: hret 0x%x, shader_ptr %p. " "Expected hret 0x%x, shader_ptr != %p. Aborting.\n", hret, shader_ptr, D3D_OK, NULL); diff --git a/dlls/wined3d/device.c b/dlls/wined3d/device.c index a99ff56f3de..b765f12a322 100644 --- a/dlls/wined3d/device.c +++ b/dlls/wined3d/device.c @@ -1874,6 +1874,9 @@ static HRESULT WINAPI IWineD3DDeviceImpl_CreateVertexShader(IWineD3DDevice *ifac IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface; IWineD3DVertexShaderImpl *object; /* NOTE: impl usage is ok, this is a create */ HRESULT hr = WINED3D_OK; + + if (!pFunction) return WINED3DERR_INVALIDCALL; + D3DCREATESHADEROBJECTINSTANCE(object, VertexShader) object->baseShader.shader_ins = IWineD3DVertexShaderImpl_shader_ins; @@ -1900,6 +1903,8 @@ static HRESULT WINAPI IWineD3DDeviceImpl_CreatePixelShader(IWineD3DDevice *iface IWineD3DPixelShaderImpl *object; /* NOTE: impl allowed, this is a create */ HRESULT hr = WINED3D_OK; + if (!pFunction) return WINED3DERR_INVALIDCALL; + D3DCREATESHADEROBJECTINSTANCE(object, PixelShader) object->baseShader.shader_ins = IWineD3DPixelShaderImpl_shader_ins; hr = IWineD3DPixelShader_SetFunction(*ppPixelShader, pFunction);