push 1a3d31f62adec93e6e6d221f242eb86df2604322
[wine/hacks.git] / dlls / d3d8 / vertexshader.c
blob92bd1fea04feac7441ea344a1f996f4a82e2806e
1 /*
2 * IDirect3DVertexShader8 implementation
4 * Copyright 2002-2003 Jason Edmeades
5 * Raphael Junqueira
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
22 #include "config.h"
23 #include "d3d8_private.h"
25 WINE_DEFAULT_DEBUG_CHANNEL(d3d8);
27 /* IDirect3DVertexShader8 IUnknown parts follow: */
28 static HRESULT WINAPI IDirect3DVertexShader8Impl_QueryInterface(IDirect3DVertexShader8 *iface, REFIID riid, LPVOID* ppobj) {
29 IDirect3DVertexShader8Impl *This = (IDirect3DVertexShader8Impl *)iface;
31 if (IsEqualGUID(riid, &IID_IUnknown)
32 || IsEqualGUID(riid, &IID_IDirect3DVertexShader8)) {
33 IUnknown_AddRef(iface);
34 *ppobj = This;
35 return S_OK;
38 WARN("(%p)->(%s,%p),not found\n", This, debugstr_guid(riid), ppobj);
39 *ppobj = NULL;
40 return E_NOINTERFACE;
43 static ULONG WINAPI IDirect3DVertexShader8Impl_AddRef(IDirect3DVertexShader8 *iface) {
44 IDirect3DVertexShader8Impl *This = (IDirect3DVertexShader8Impl *)iface;
45 ULONG ref = InterlockedIncrement(&This->ref);
47 TRACE("(%p) : AddRef from %d\n", This, ref - 1);
49 if (ref == 1 && This->wineD3DVertexShader)
51 wined3d_mutex_lock();
52 IWineD3DVertexShader_AddRef(This->wineD3DVertexShader);
53 wined3d_mutex_unlock();
56 return ref;
59 static void STDMETHODCALLTYPE d3d8_vertexshader_wined3d_object_destroyed(void *parent)
61 IDirect3DVertexShader8Impl *shader = parent;
62 IDirect3DVertexDeclaration8_Release(shader->vertex_declaration);
63 HeapFree(GetProcessHeap(), 0, shader);
66 static ULONG WINAPI IDirect3DVertexShader8Impl_Release(IDirect3DVertexShader8 *iface) {
67 IDirect3DVertexShader8Impl *This = (IDirect3DVertexShader8Impl *)iface;
68 ULONG ref = InterlockedDecrement(&This->ref);
70 TRACE("(%p) : ReleaseRef to %d\n", This, ref);
72 if (ref == 0) {
73 if (This->wineD3DVertexShader)
75 wined3d_mutex_lock();
76 IWineD3DVertexShader_Release(This->wineD3DVertexShader);
77 wined3d_mutex_unlock();
79 else
81 d3d8_vertexshader_wined3d_object_destroyed(This);
84 return ref;
87 static const IDirect3DVertexShader8Vtbl Direct3DVertexShader8_Vtbl =
89 /* IUnknown */
90 IDirect3DVertexShader8Impl_QueryInterface,
91 IDirect3DVertexShader8Impl_AddRef,
92 IDirect3DVertexShader8Impl_Release,
95 static const struct wined3d_parent_ops d3d8_vertexshader_wined3d_parent_ops =
97 d3d8_vertexshader_wined3d_object_destroyed,
100 static HRESULT vertexshader_create_vertexdeclaration(IDirect3DDevice8Impl *device,
101 const DWORD *declaration, DWORD shader_handle, IDirect3DVertexDeclaration8 **decl_ptr)
103 IDirect3DVertexDeclaration8Impl *object;
104 HRESULT hr;
106 TRACE("device %p, declaration %p, shader_handle %#x, decl_ptr %p.\n",
107 device, declaration, shader_handle, decl_ptr);
109 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*object));
110 if (!object) {
111 ERR("Memory allocation failed\n");
112 *decl_ptr = NULL;
113 return D3DERR_OUTOFVIDEOMEMORY;
116 hr = vertexdeclaration_init(object, device, declaration, shader_handle);
117 if (FAILED(hr))
119 WARN("Failed to initialize vertex declaration, hr %#x.\n", hr);
120 HeapFree(GetProcessHeap(), 0, object);
121 return hr;
124 TRACE("Created vertex declaration %p.\n", object);
125 *decl_ptr = (IDirect3DVertexDeclaration8 *)object;
127 return D3D_OK;
130 HRESULT vertexshader_init(IDirect3DVertexShader8Impl *shader, IDirect3DDevice8Impl *device,
131 const DWORD *declaration, const DWORD *byte_code, DWORD shader_handle, DWORD usage)
133 const DWORD *token = declaration;
134 HRESULT hr;
136 /* Test if the vertex declaration is valid */
137 while (D3DVSD_END() != *token)
139 D3DVSD_TOKENTYPE token_type = ((*token & D3DVSD_TOKENTYPEMASK) >> D3DVSD_TOKENTYPESHIFT);
141 if (token_type == D3DVSD_TOKEN_STREAMDATA && !(token_type & 0x10000000))
143 DWORD type = ((*token & D3DVSD_DATATYPEMASK) >> D3DVSD_DATATYPESHIFT);
144 DWORD reg = ((*token & D3DVSD_VERTEXREGMASK) >> D3DVSD_VERTEXREGSHIFT);
146 if (reg == D3DVSDE_NORMAL && type != D3DVSDT_FLOAT3 && !byte_code)
148 WARN("Attempt to use a non-FLOAT3 normal with the fixed function function\n");
149 return D3DERR_INVALIDCALL;
152 token += parse_token(token);
155 shader->ref = 1;
156 shader->lpVtbl = &Direct3DVertexShader8_Vtbl;
158 hr = vertexshader_create_vertexdeclaration(device, declaration, shader_handle, &shader->vertex_declaration);
159 if (FAILED(hr))
161 WARN("Failed to create vertex declaration, hr %#x.\n", hr);
162 return hr;
165 if (byte_code)
167 if (usage) FIXME("Usage %#x not implemented.\n", usage);
169 wined3d_mutex_lock();
170 hr = IWineD3DDevice_CreateVertexShader(device->WineD3DDevice, byte_code,
171 NULL /* output signature */, &shader->wineD3DVertexShader,
172 (IUnknown *)shader, &d3d8_vertexshader_wined3d_parent_ops);
173 wined3d_mutex_unlock();
174 if (FAILED(hr))
176 WARN("Failed to create wined3d vertex shader, hr %#x.\n", hr);
177 IDirect3DVertexDeclaration8_Release(shader->vertex_declaration);
178 return hr;
181 load_local_constants(declaration, shader->wineD3DVertexShader);
184 return D3D_OK;