From afed6a3f77dc43e1ccc21cc1099621073b8030a4 Mon Sep 17 00:00:00 2001 From: Henri Verbeet Date: Wed, 23 Sep 2009 18:42:07 +0200 Subject: [PATCH] d3d8: Add a separate function for vertex shader initialization. --- dlls/d3d8/d3d8_private.h | 8 +-- dlls/d3d8/device.c | 124 ++++++++++----------------------------- dlls/d3d8/vertexshader.c | 90 +++++++++++++++++++++++++++- 3 files changed, 122 insertions(+), 100 deletions(-) diff --git a/dlls/d3d8/d3d8_private.h b/dlls/d3d8/d3d8_private.h index e79d3367af2..89d05c903a9 100644 --- a/dlls/d3d8/d3d8_private.h +++ b/dlls/d3d8/d3d8_private.h @@ -586,11 +586,6 @@ DECLARE_INTERFACE_(IDirect3DPixelShader8,IUnknown) #define IDirect3DPixelShader8_AddRef(p) (p)->lpVtbl->AddRef(p) #define IDirect3DPixelShader8_Release(p) (p)->lpVtbl->Release(p) -/***************************************************************************** - * Predeclare the interface implementation structures - */ -extern const IDirect3DVertexShader8Vtbl Direct3DVertexShader8_Vtbl DECLSPEC_HIDDEN; - /***************************************************************************** * IDirect3DVertexShader implementation structure */ @@ -603,6 +598,9 @@ struct IDirect3DVertexShader8Impl { IWineD3DVertexShader *wineD3DVertexShader; }; +HRESULT vertexshader_init(IDirect3DVertexShader8Impl *shader, IDirect3DDevice8Impl *device, + const DWORD *declaration, const DWORD *byte_code, DWORD shader_handle, DWORD usage) DECLSPEC_HIDDEN; + #define D3D8_MAX_VERTEX_SHADER_CONSTANTF 256 diff --git a/dlls/d3d8/device.c b/dlls/d3d8/device.c index 1e68ce3f7b0..3bb329f7203 100644 --- a/dlls/d3d8/device.c +++ b/dlls/d3d8/device.c @@ -1716,119 +1716,55 @@ static HRESULT WINAPI IDirect3DDevice8Impl_ProcessVertices(LPDIRECT3DDEVICE8 ifa return hr; } -static HRESULT IDirect3DDevice8Impl_CreateVertexDeclaration(IDirect3DDevice8 *iface, CONST DWORD *declaration, IDirect3DVertexDeclaration8 **decl_ptr) { +static HRESULT WINAPI IDirect3DDevice8Impl_CreateVertexShader(IDirect3DDevice8 *iface, + const DWORD *declaration, const DWORD *byte_code, DWORD *shader, DWORD usage) +{ IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface; - IDirect3DVertexDeclaration8Impl *object; + IDirect3DVertexShader8Impl *object; + DWORD shader_handle; + DWORD handle; HRESULT hr; - TRACE("(%p) : declaration %p\n", This, declaration); + TRACE("iface %p, declaration %p, byte_code %p, shader %p, usage %#x.\n", + iface, declaration, byte_code, shader, usage); object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*object)); - if (!object) { - ERR("Memory allocation failed\n"); - *decl_ptr = NULL; - return D3DERR_OUTOFVIDEOMEMORY; - } - - hr = vertexdeclaration_init(object, This, declaration); - if (FAILED(hr)) + if (!object) { - WARN("Failed to initialize vertex declaration, hr %#x.\n", hr); - HeapFree(GetProcessHeap(), 0, object); - return hr; - } - - TRACE("Created vertex declaration %p.\n", object); - *decl_ptr = (IDirect3DVertexDeclaration8 *)object; - - return D3D_OK; -} - -static HRESULT WINAPI IDirect3DDevice8Impl_CreateVertexShader(LPDIRECT3DDEVICE8 iface, CONST DWORD* pDeclaration, CONST DWORD* pFunction, DWORD* ppShader, DWORD Usage) { - IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface; - HRESULT hrc = D3D_OK; - IDirect3DVertexShader8Impl *object; - const DWORD *token = pDeclaration; - DWORD handle; - - /* Test if the vertex declaration is valid */ - while (D3DVSD_END() != *token) { - D3DVSD_TOKENTYPE token_type = ((*token & D3DVSD_TOKENTYPEMASK) >> D3DVSD_TOKENTYPESHIFT); - - if (token_type == D3DVSD_TOKEN_STREAMDATA && !(token_type & 0x10000000)) { - DWORD type = ((*token & D3DVSD_DATATYPEMASK) >> D3DVSD_DATATYPESHIFT); - DWORD reg = ((*token & D3DVSD_VERTEXREGMASK) >> D3DVSD_VERTEXREGSHIFT); - - if(reg == D3DVSDE_NORMAL && type != D3DVSDT_FLOAT3 && !pFunction) { - WARN("Attempt to use a non-FLOAT3 normal with the fixed function function\n"); - return D3DERR_INVALIDCALL; - } - } - token += parse_token(token); - } - - /* Setup a stub object for now */ - object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*object)); - TRACE("(%p) : pFunction(%p), ppShader(%p)\n", This, pFunction, ppShader); - if (NULL == object) { - FIXME("Allocation of memory failed\n"); - *ppShader = 0; - return D3DERR_OUTOFVIDEOMEMORY; - } - - object->ref = 1; - object->lpVtbl = &Direct3DVertexShader8_Vtbl; - - hrc = IDirect3DDevice8Impl_CreateVertexDeclaration(iface, pDeclaration, &object->vertex_declaration); - if (FAILED(hrc)) { - ERR("(%p) : IDirect3DDeviceImpl_CreateVertexDeclaration call failed\n", This); - HeapFree(GetProcessHeap(), 0, object); - *ppShader = 0; - return D3DERR_INVALIDCALL; + ERR("Failed to allocate vertex shader memory.\n"); + *shader = 0; + return E_OUTOFMEMORY; } wined3d_mutex_lock(); handle = d3d8_allocate_handle(&This->handle_table, object, D3D8_HANDLE_VS); + wined3d_mutex_unlock(); if (handle == D3D8_INVALID_HANDLE) { - ERR("Failed to allocate shader handle\n"); - wined3d_mutex_unlock(); - IDirect3DVertexDeclaration8_Release(object->vertex_declaration); + ERR("Failed to allocate vertex shader handle.\n"); HeapFree(GetProcessHeap(), 0, object); - *ppShader = 0; + *shader = 0; return E_OUTOFMEMORY; } - else + + shader_handle = handle + VS_HIGHESTFIXEDFXF + 1; + + hr = vertexshader_init(object, This, declaration, byte_code, shader_handle, usage); + if (FAILED(hr)) { - DWORD shader_handle = handle + VS_HIGHESTFIXEDFXF + 1; - *ppShader = ((IDirect3DVertexDeclaration8Impl *)object->vertex_declaration)->shader_handle = shader_handle; + WARN("Failed to initialize vertex shader, hr %#x.\n", hr); + wined3d_mutex_lock(); + d3d8_free_handle(&This->handle_table, handle, D3D8_HANDLE_VS); + wined3d_mutex_unlock(); + HeapFree(GetProcessHeap(), 0, object); + *shader = 0; + return hr; } - if (pFunction) - { - /* Usage is missing ... Use SetRenderState to set the sw vp render state in SetVertexShader */ - hrc = IWineD3DDevice_CreateVertexShader(This->WineD3DDevice, pFunction, - NULL /* output signature */, &object->wineD3DVertexShader, (IUnknown *)object); + TRACE("Created vertex shader %p (handle %#x).\n", object, shader_handle); + *shader = shader_handle; - if (FAILED(hrc)) - { - /* free up object */ - FIXME("Call to IWineD3DDevice_CreateVertexShader failed\n"); - d3d8_free_handle(&This->handle_table, handle, D3D8_HANDLE_VS); - 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); - } - } - - wined3d_mutex_unlock(); - - return hrc; + return D3D_OK; } static IDirect3DVertexDeclaration8Impl *IDirect3DDevice8Impl_FindDecl(IDirect3DDevice8Impl *This, DWORD fvf) diff --git a/dlls/d3d8/vertexshader.c b/dlls/d3d8/vertexshader.c index 1a9b5ea9535..2e5842104df 100644 --- a/dlls/d3d8/vertexshader.c +++ b/dlls/d3d8/vertexshader.c @@ -68,10 +68,98 @@ static ULONG WINAPI IDirect3DVertexShader8Impl_Release(IDirect3DVertexShader8 *i return ref; } -const IDirect3DVertexShader8Vtbl Direct3DVertexShader8_Vtbl = +static const IDirect3DVertexShader8Vtbl Direct3DVertexShader8_Vtbl = { /* IUnknown */ IDirect3DVertexShader8Impl_QueryInterface, IDirect3DVertexShader8Impl_AddRef, IDirect3DVertexShader8Impl_Release, }; + +static HRESULT vertexshader_create_vertexdeclaration(IDirect3DDevice8Impl *device, + const DWORD *declaration, DWORD shader_handle, IDirect3DVertexDeclaration8 **decl_ptr) +{ + IDirect3DVertexDeclaration8Impl *object; + HRESULT hr; + + TRACE("device %p, declaration %p, shader_handle %#x, decl_ptr %p.\n", + device, declaration, shader_handle, decl_ptr); + + object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*object)); + if (!object) { + ERR("Memory allocation failed\n"); + *decl_ptr = NULL; + return D3DERR_OUTOFVIDEOMEMORY; + } + + hr = vertexdeclaration_init(object, device, declaration); + if (FAILED(hr)) + { + WARN("Failed to initialize vertex declaration, hr %#x.\n", hr); + HeapFree(GetProcessHeap(), 0, object); + return hr; + } + + object->shader_handle = shader_handle; + + TRACE("Created vertex declaration %p.\n", object); + *decl_ptr = (IDirect3DVertexDeclaration8 *)object; + + return D3D_OK; +} + +HRESULT vertexshader_init(IDirect3DVertexShader8Impl *shader, IDirect3DDevice8Impl *device, + const DWORD *declaration, const DWORD *byte_code, DWORD shader_handle, DWORD usage) +{ + const DWORD *token = declaration; + HRESULT hr; + + /* Test if the vertex declaration is valid */ + while (D3DVSD_END() != *token) + { + D3DVSD_TOKENTYPE token_type = ((*token & D3DVSD_TOKENTYPEMASK) >> D3DVSD_TOKENTYPESHIFT); + + if (token_type == D3DVSD_TOKEN_STREAMDATA && !(token_type & 0x10000000)) + { + DWORD type = ((*token & D3DVSD_DATATYPEMASK) >> D3DVSD_DATATYPESHIFT); + DWORD reg = ((*token & D3DVSD_VERTEXREGMASK) >> D3DVSD_VERTEXREGSHIFT); + + if (reg == D3DVSDE_NORMAL && type != D3DVSDT_FLOAT3 && !byte_code) + { + WARN("Attempt to use a non-FLOAT3 normal with the fixed function function\n"); + return D3DERR_INVALIDCALL; + } + } + token += parse_token(token); + } + + shader->ref = 1; + shader->lpVtbl = &Direct3DVertexShader8_Vtbl; + + hr = vertexshader_create_vertexdeclaration(device, declaration, shader_handle, &shader->vertex_declaration); + if (FAILED(hr)) + { + WARN("Failed to create vertex declaration, hr %#x.\n", hr); + return hr; + } + + if (byte_code) + { + if (usage) FIXME("Usage %#x not implemented.\n", usage); + + wined3d_mutex_lock(); + hr = IWineD3DDevice_CreateVertexShader(device->WineD3DDevice, byte_code, + NULL /* output signature */, &shader->wineD3DVertexShader, (IUnknown *)shader); + wined3d_mutex_unlock(); + if (FAILED(hr)) + { + WARN("Failed to create wined3d vertex shader, hr %#x.\n", hr); + IDirect3DVertexDeclaration8_Release(shader->vertex_declaration); + return hr; + } + + load_local_constants(declaration, shader->wineD3DVertexShader); + } + + return D3D_OK; +}