push 52d6b63ba2f2d4f9b02b6b922d27bff05a60596f
[wine/hacks.git] / dlls / d3d8 / vertexshader.c
blob1f00aa0bd7b0f99628eeb1033d7dbe6561e31745
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 TRACE("iface %p, riid %s, object %p.\n", iface, debugstr_guid(riid), ppobj);
33 if (IsEqualGUID(riid, &IID_IUnknown)
34 || IsEqualGUID(riid, &IID_IDirect3DVertexShader8)) {
35 IUnknown_AddRef(iface);
36 *ppobj = This;
37 return S_OK;
40 WARN("(%p)->(%s,%p),not found\n", This, debugstr_guid(riid), ppobj);
41 *ppobj = NULL;
42 return E_NOINTERFACE;
45 static ULONG WINAPI IDirect3DVertexShader8Impl_AddRef(IDirect3DVertexShader8 *iface) {
46 IDirect3DVertexShader8Impl *This = (IDirect3DVertexShader8Impl *)iface;
47 ULONG ref = InterlockedIncrement(&This->ref);
49 TRACE("%p increasing refcount to %u.\n", iface, ref);
51 if (ref == 1 && This->wineD3DVertexShader)
53 wined3d_mutex_lock();
54 IWineD3DVertexShader_AddRef(This->wineD3DVertexShader);
55 wined3d_mutex_unlock();
58 return ref;
61 static void STDMETHODCALLTYPE d3d8_vertexshader_wined3d_object_destroyed(void *parent)
63 IDirect3DVertexShader8Impl *shader = parent;
64 IDirect3DVertexDeclaration8_Release(shader->vertex_declaration);
65 HeapFree(GetProcessHeap(), 0, shader);
68 static ULONG WINAPI IDirect3DVertexShader8Impl_Release(IDirect3DVertexShader8 *iface) {
69 IDirect3DVertexShader8Impl *This = (IDirect3DVertexShader8Impl *)iface;
70 ULONG ref = InterlockedDecrement(&This->ref);
72 TRACE("%p decreasing refcount to %u.\n", iface, ref);
74 if (ref == 0) {
75 if (This->wineD3DVertexShader)
77 wined3d_mutex_lock();
78 IWineD3DVertexShader_Release(This->wineD3DVertexShader);
79 wined3d_mutex_unlock();
81 else
83 d3d8_vertexshader_wined3d_object_destroyed(This);
86 return ref;
89 static const IDirect3DVertexShader8Vtbl Direct3DVertexShader8_Vtbl =
91 /* IUnknown */
92 IDirect3DVertexShader8Impl_QueryInterface,
93 IDirect3DVertexShader8Impl_AddRef,
94 IDirect3DVertexShader8Impl_Release,
97 static const struct wined3d_parent_ops d3d8_vertexshader_wined3d_parent_ops =
99 d3d8_vertexshader_wined3d_object_destroyed,
102 static HRESULT vertexshader_create_vertexdeclaration(IDirect3DDevice8Impl *device,
103 const DWORD *declaration, DWORD shader_handle, IDirect3DVertexDeclaration8 **decl_ptr)
105 IDirect3DVertexDeclaration8Impl *object;
106 HRESULT hr;
108 TRACE("device %p, declaration %p, shader_handle %#x, decl_ptr %p.\n",
109 device, declaration, shader_handle, decl_ptr);
111 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*object));
112 if (!object) {
113 ERR("Memory allocation failed\n");
114 *decl_ptr = NULL;
115 return D3DERR_OUTOFVIDEOMEMORY;
118 hr = vertexdeclaration_init(object, device, declaration, shader_handle);
119 if (FAILED(hr))
121 WARN("Failed to initialize vertex declaration, hr %#x.\n", hr);
122 HeapFree(GetProcessHeap(), 0, object);
123 return hr;
126 TRACE("Created vertex declaration %p.\n", object);
127 *decl_ptr = (IDirect3DVertexDeclaration8 *)object;
129 return D3D_OK;
132 HRESULT vertexshader_init(IDirect3DVertexShader8Impl *shader, IDirect3DDevice8Impl *device,
133 const DWORD *declaration, const DWORD *byte_code, DWORD shader_handle, DWORD usage)
135 const DWORD *token = declaration;
136 HRESULT hr;
138 /* Test if the vertex declaration is valid */
139 while (D3DVSD_END() != *token)
141 D3DVSD_TOKENTYPE token_type = ((*token & D3DVSD_TOKENTYPEMASK) >> D3DVSD_TOKENTYPESHIFT);
143 if (token_type == D3DVSD_TOKEN_STREAMDATA && !(token_type & 0x10000000))
145 DWORD type = ((*token & D3DVSD_DATATYPEMASK) >> D3DVSD_DATATYPESHIFT);
146 DWORD reg = ((*token & D3DVSD_VERTEXREGMASK) >> D3DVSD_VERTEXREGSHIFT);
148 if (reg == D3DVSDE_NORMAL && type != D3DVSDT_FLOAT3 && !byte_code)
150 WARN("Attempt to use a non-FLOAT3 normal with the fixed function function\n");
151 return D3DERR_INVALIDCALL;
154 token += parse_token(token);
157 shader->ref = 1;
158 shader->lpVtbl = &Direct3DVertexShader8_Vtbl;
160 hr = vertexshader_create_vertexdeclaration(device, declaration, shader_handle, &shader->vertex_declaration);
161 if (FAILED(hr))
163 WARN("Failed to create vertex declaration, hr %#x.\n", hr);
164 return hr;
167 if (byte_code)
169 if (usage) FIXME("Usage %#x not implemented.\n", usage);
171 wined3d_mutex_lock();
172 hr = IWineD3DDevice_CreateVertexShader(device->WineD3DDevice, byte_code,
173 NULL /* output signature */, &shader->wineD3DVertexShader,
174 (IUnknown *)shader, &d3d8_vertexshader_wined3d_parent_ops);
175 wined3d_mutex_unlock();
176 if (FAILED(hr))
178 WARN("Failed to create wined3d vertex shader, hr %#x.\n", hr);
179 IDirect3DVertexDeclaration8_Release(shader->vertex_declaration);
180 return hr;
183 load_local_constants(declaration, shader->wineD3DVertexShader);
186 return D3D_OK;