2 * Copyright 2002-2003 Jason Edmeades
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
8 * version 2.1 of the License, or (at your option) any later version.
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this library; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
21 #include "d3d8_private.h"
23 WINE_DEFAULT_DEBUG_CHANNEL(d3d8
);
25 static inline IDirect3DVertexShader8Impl
*impl_from_IDirect3DVertexShader8(IDirect3DVertexShader8
*iface
)
27 return CONTAINING_RECORD(iface
, IDirect3DVertexShader8Impl
, IDirect3DVertexShader8_iface
);
30 static HRESULT WINAPI
d3d8_vertexshader_QueryInterface(IDirect3DVertexShader8
*iface
, REFIID riid
, void **object
)
32 TRACE("iface %p, riid %s, object %p.\n", iface
, debugstr_guid(riid
), object
);
34 if (IsEqualGUID(riid
, &IID_IDirect3DVertexShader8
)
35 || IsEqualGUID(riid
, &IID_IUnknown
))
37 IUnknown_AddRef(iface
);
42 WARN("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(riid
));
48 static ULONG WINAPI
d3d8_vertexshader_AddRef(IDirect3DVertexShader8
*iface
)
50 IDirect3DVertexShader8Impl
*shader
= impl_from_IDirect3DVertexShader8(iface
);
51 ULONG refcount
= InterlockedIncrement(&shader
->ref
);
53 TRACE("%p increasing refcount to %u.\n", iface
, refcount
);
55 if (refcount
== 1 && shader
->wined3d_shader
)
58 wined3d_shader_incref(shader
->wined3d_shader
);
59 wined3d_mutex_unlock();
65 static void STDMETHODCALLTYPE
d3d8_vertexshader_wined3d_object_destroyed(void *parent
)
67 IDirect3DVertexShader8Impl
*shader
= parent
;
68 IDirect3DVertexDeclaration8_Release(shader
->vertex_declaration
);
69 HeapFree(GetProcessHeap(), 0, shader
);
72 static ULONG WINAPI
d3d8_vertexshader_Release(IDirect3DVertexShader8
*iface
)
74 IDirect3DVertexShader8Impl
*shader
= impl_from_IDirect3DVertexShader8(iface
);
75 ULONG refcount
= InterlockedDecrement(&shader
->ref
);
77 TRACE("%p decreasing refcount to %u.\n", iface
, refcount
);
81 if (shader
->wined3d_shader
)
84 wined3d_shader_decref(shader
->wined3d_shader
);
85 wined3d_mutex_unlock();
89 d3d8_vertexshader_wined3d_object_destroyed(shader
);
96 static const IDirect3DVertexShader8Vtbl d3d8_vertexshader_vtbl
=
99 d3d8_vertexshader_QueryInterface
,
100 d3d8_vertexshader_AddRef
,
101 d3d8_vertexshader_Release
,
104 static const struct wined3d_parent_ops d3d8_vertexshader_wined3d_parent_ops
=
106 d3d8_vertexshader_wined3d_object_destroyed
,
109 static HRESULT
d3d8_vertexshader_create_vertexdeclaration(IDirect3DDevice8Impl
*device
,
110 const DWORD
*declaration
, DWORD shader_handle
, IDirect3DVertexDeclaration8
**decl_ptr
)
112 IDirect3DVertexDeclaration8Impl
*object
;
115 TRACE("device %p, declaration %p, shader_handle %#x, decl_ptr %p.\n",
116 device
, declaration
, shader_handle
, decl_ptr
);
118 object
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(*object
));
121 ERR("Memory allocation failed.\n");
122 return E_OUTOFMEMORY
;
125 hr
= vertexdeclaration_init(object
, device
, declaration
, shader_handle
);
128 WARN("Failed to initialize vertex declaration, hr %#x.\n", hr
);
129 HeapFree(GetProcessHeap(), 0, object
);
133 TRACE("Created vertex declaration %p.\n", object
);
134 *decl_ptr
= (IDirect3DVertexDeclaration8
*)object
;
139 HRESULT
vertexshader_init(IDirect3DVertexShader8Impl
*shader
, IDirect3DDevice8Impl
*device
,
140 const DWORD
*declaration
, const DWORD
*byte_code
, DWORD shader_handle
, DWORD usage
)
142 const DWORD
*token
= declaration
;
145 /* Test if the vertex declaration is valid. */
146 while (D3DVSD_END() != *token
)
148 D3DVSD_TOKENTYPE token_type
= ((*token
& D3DVSD_TOKENTYPEMASK
) >> D3DVSD_TOKENTYPESHIFT
);
150 if (token_type
== D3DVSD_TOKEN_STREAMDATA
&& !(token_type
& 0x10000000))
152 DWORD type
= ((*token
& D3DVSD_DATATYPEMASK
) >> D3DVSD_DATATYPESHIFT
);
153 DWORD reg
= ((*token
& D3DVSD_VERTEXREGMASK
) >> D3DVSD_VERTEXREGSHIFT
);
155 if (reg
== D3DVSDE_NORMAL
&& type
!= D3DVSDT_FLOAT3
&& !byte_code
)
157 WARN("Attempt to use a non-FLOAT3 normal with the fixed function function\n");
158 return D3DERR_INVALIDCALL
;
161 token
+= parse_token(token
);
165 shader
->IDirect3DVertexShader8_iface
.lpVtbl
= &d3d8_vertexshader_vtbl
;
167 hr
= d3d8_vertexshader_create_vertexdeclaration(device
, declaration
, shader_handle
, &shader
->vertex_declaration
);
170 WARN("Failed to create vertex declaration, hr %#x.\n", hr
);
176 if (usage
) FIXME("Usage %#x not implemented.\n", usage
);
178 wined3d_mutex_lock();
179 hr
= IWineD3DDevice_CreateVertexShader(device
->WineD3DDevice
, byte_code
, NULL
/* output signature */,
180 shader
, &d3d8_vertexshader_wined3d_parent_ops
, &shader
->wined3d_shader
);
181 wined3d_mutex_unlock();
184 WARN("Failed to create wined3d vertex shader, hr %#x.\n", hr
);
185 IDirect3DVertexDeclaration8_Release(shader
->vertex_declaration
);
189 load_local_constants(declaration
, shader
->wined3d_shader
);
195 static inline IDirect3DPixelShader8Impl
*impl_from_IDirect3DPixelShader8(IDirect3DPixelShader8
*iface
)
197 return CONTAINING_RECORD(iface
, IDirect3DPixelShader8Impl
, IDirect3DPixelShader8_iface
);
200 static HRESULT WINAPI
d3d8_pixelshader_QueryInterface(IDirect3DPixelShader8
*iface
, REFIID riid
, void **object
)
202 TRACE("iface %p, riid %s, object %p.\n", iface
, debugstr_guid(riid
), object
);
204 if (IsEqualGUID(riid
, &IID_IDirect3DPixelShader8
)
205 || IsEqualGUID(riid
, &IID_IUnknown
))
207 IUnknown_AddRef(iface
);
212 WARN("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(riid
));
215 return E_NOINTERFACE
;
218 static ULONG WINAPI
d3d8_pixelshader_AddRef(IDirect3DPixelShader8
*iface
)
220 IDirect3DPixelShader8Impl
*shader
= impl_from_IDirect3DPixelShader8(iface
);
221 ULONG refcount
= InterlockedIncrement(&shader
->ref
);
223 TRACE("%p increasing refcount to %u.\n", iface
, refcount
);
227 wined3d_mutex_lock();
228 wined3d_shader_incref(shader
->wined3d_shader
);
229 wined3d_mutex_unlock();
235 static ULONG WINAPI
d3d8_pixelshader_Release(IDirect3DPixelShader8
*iface
)
237 IDirect3DPixelShader8Impl
*shader
= impl_from_IDirect3DPixelShader8(iface
);
238 ULONG refcount
= InterlockedDecrement(&shader
->ref
);
240 TRACE("%p decreasing refcount to %u.\n", iface
, refcount
);
244 wined3d_mutex_lock();
245 wined3d_shader_decref(shader
->wined3d_shader
);
246 wined3d_mutex_unlock();
252 static const IDirect3DPixelShader8Vtbl d3d8_pixelshader_vtbl
=
255 d3d8_pixelshader_QueryInterface
,
256 d3d8_pixelshader_AddRef
,
257 d3d8_pixelshader_Release
,
260 static void STDMETHODCALLTYPE
d3d8_pixelshader_wined3d_object_destroyed(void *parent
)
262 HeapFree(GetProcessHeap(), 0, parent
);
265 static const struct wined3d_parent_ops d3d8_pixelshader_wined3d_parent_ops
=
267 d3d8_pixelshader_wined3d_object_destroyed
,
270 HRESULT
pixelshader_init(IDirect3DPixelShader8Impl
*shader
, IDirect3DDevice8Impl
*device
,
271 const DWORD
*byte_code
, DWORD shader_handle
)
276 shader
->IDirect3DPixelShader8_iface
.lpVtbl
= &d3d8_pixelshader_vtbl
;
277 shader
->handle
= shader_handle
;
279 wined3d_mutex_lock();
280 hr
= IWineD3DDevice_CreatePixelShader(device
->WineD3DDevice
, byte_code
, NULL
, shader
,
281 &d3d8_pixelshader_wined3d_parent_ops
, &shader
->wined3d_shader
);
282 wined3d_mutex_unlock();
285 WARN("Failed to create wined3d pixel shader, hr %#x.\n", hr
);