Release 1.5.0.
[wine/multimedia.git] / dlls / ddraw / material.c
blob98f43c0aaa751f203239cafe4938955044021635
1 /* Direct3D Material
2 * Copyright (c) 2002 Lionel ULMER
3 * Copyright (c) 2006 Stefan DÖSINGER
5 * This file contains the implementation of Direct3DMaterial.
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 "wine/port.h"
25 #include "ddraw_private.h"
27 WINE_DEFAULT_DEBUG_CHANNEL(ddraw);
29 static void dump_material(const D3DMATERIAL *mat)
31 TRACE(" dwSize : %d\n", mat->dwSize);
34 static inline struct d3d_material *impl_from_IDirect3DMaterial(IDirect3DMaterial *iface)
36 return CONTAINING_RECORD(iface, struct d3d_material, IDirect3DMaterial_iface);
39 static inline struct d3d_material *impl_from_IDirect3DMaterial2(IDirect3DMaterial2 *iface)
41 return CONTAINING_RECORD(iface, struct d3d_material, IDirect3DMaterial2_iface);
44 static inline struct d3d_material *impl_from_IDirect3DMaterial3(IDirect3DMaterial3 *iface)
46 return CONTAINING_RECORD(iface, struct d3d_material, IDirect3DMaterial3_iface);
49 /*****************************************************************************
50 * IUnknown Methods.
51 *****************************************************************************/
53 /*****************************************************************************
54 * IDirect3DMaterial3::QueryInterface
56 * QueryInterface for IDirect3DMaterial. Can query all IDirect3DMaterial
57 * versions.
59 * Params:
60 * riid: Interface id queried for
61 * obj: Address to pass the interface pointer back
63 * Returns:
64 * S_OK on success
65 * E_NOINTERFACE if the requested interface wasn't found
67 *****************************************************************************/
68 static HRESULT WINAPI d3d_material3_QueryInterface(IDirect3DMaterial3 *iface, REFIID riid, void **obp)
70 struct d3d_material *material = impl_from_IDirect3DMaterial3(iface);
72 TRACE("iface %p, riid %s, object %p.\n", iface, debugstr_guid(riid), obp);
74 *obp = NULL;
76 if (IsEqualGUID(&IID_IUnknown, riid))
78 IUnknown_AddRef(iface);
79 *obp = iface;
80 TRACE(" Creating IUnknown interface at %p.\n", *obp);
81 return S_OK;
83 if (IsEqualGUID(&IID_IDirect3DMaterial, riid))
85 IDirect3DMaterial_AddRef(&material->IDirect3DMaterial_iface);
86 *obp = &material->IDirect3DMaterial_iface;
87 TRACE(" Creating IDirect3DMaterial interface %p\n", *obp);
88 return S_OK;
90 if (IsEqualGUID(&IID_IDirect3DMaterial2, riid))
92 IDirect3DMaterial2_AddRef(&material->IDirect3DMaterial2_iface);
93 *obp = &material->IDirect3DMaterial2_iface;
94 TRACE(" Creating IDirect3DMaterial2 interface %p\n", *obp);
95 return S_OK;
97 if (IsEqualGUID(&IID_IDirect3DMaterial3, riid))
99 IDirect3DMaterial3_AddRef(&material->IDirect3DMaterial3_iface);
100 *obp = &material->IDirect3DMaterial3_iface;
101 TRACE(" Creating IDirect3DMaterial3 interface %p\n", *obp);
102 return S_OK;
105 WARN("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(riid));
107 return E_NOINTERFACE;
110 /*****************************************************************************
111 * IDirect3DMaterial3::AddRef
113 * Increases the refcount.
115 * Returns:
116 * The new refcount
118 *****************************************************************************/
119 static ULONG WINAPI d3d_material3_AddRef(IDirect3DMaterial3 *iface)
121 struct d3d_material *material = impl_from_IDirect3DMaterial3(iface);
122 ULONG ref = InterlockedIncrement(&material->ref);
124 TRACE("%p increasing refcount to %u.\n", material, ref);
126 return ref;
129 /*****************************************************************************
130 * IDirect3DMaterial3::Release
132 * Reduces the refcount by one. If the refcount falls to 0, the object
133 * is destroyed
135 * Returns:
136 * The new refcount
138 *****************************************************************************/
139 static ULONG WINAPI d3d_material3_Release(IDirect3DMaterial3 *iface)
141 struct d3d_material *material = impl_from_IDirect3DMaterial3(iface);
142 ULONG ref = InterlockedDecrement(&material->ref);
144 TRACE("%p decreasing refcount to %u.\n", material, ref);
146 if (!ref)
148 if (material->Handle)
150 wined3d_mutex_lock();
151 ddraw_free_handle(&material->ddraw->d3ddevice->handle_table, material->Handle - 1, DDRAW_HANDLE_MATERIAL);
152 wined3d_mutex_unlock();
155 HeapFree(GetProcessHeap(), 0, material);
158 return ref;
161 /*****************************************************************************
162 * IDirect3DMaterial Methods
163 *****************************************************************************/
165 /*****************************************************************************
166 * IDirect3DMaterial::Initialize
168 * A no-op initialization
170 * Params:
171 * Direct3D: Pointer to a Direct3D interface
173 * Returns:
174 * D3D_OK
176 *****************************************************************************/
177 static HRESULT WINAPI d3d_material1_Initialize(IDirect3DMaterial *iface, IDirect3D *d3d)
179 TRACE("iface %p, d3d %p.\n", iface, d3d);
181 return D3D_OK;
184 /*****************************************************************************
185 * IDirect3DMaterial::Reserve
187 * DirectX 5 sdk: "The IDirect3DMaterial2::Reserve method is not implemented"
188 * Odd. They seem to have mixed their interfaces.
190 * Returns:
191 * DDERR_UNSUPPORTED
193 *****************************************************************************/
194 static HRESULT WINAPI d3d_material1_Reserve(IDirect3DMaterial *iface)
196 TRACE("iface %p.\n", iface);
198 return DDERR_UNSUPPORTED;
201 /*****************************************************************************
202 * IDirect3DMaterial::Unreserve
204 * Not supported too
206 * Returns:
207 * DDERR_UNSUPPORTED
209 *****************************************************************************/
210 static HRESULT WINAPI d3d_material1_Unreserve(IDirect3DMaterial *iface)
212 TRACE("iface %p.\n", iface);
214 return DDERR_UNSUPPORTED;
217 /*****************************************************************************
218 * IDirect3DMaterial3::SetMaterial
220 * Sets the material description
222 * Params:
223 * Mat: Material to set
225 * Returns:
226 * D3D_OK on success
227 * DDERR_INVALIDPARAMS if Mat is NULL
229 *****************************************************************************/
230 static HRESULT WINAPI d3d_material3_SetMaterial(IDirect3DMaterial3 *iface, D3DMATERIAL *mat)
232 struct d3d_material *material = impl_from_IDirect3DMaterial3(iface);
234 TRACE("iface %p, mat %p.\n", iface, mat);
235 if (TRACE_ON(ddraw))
236 dump_material(mat);
238 /* Stores the material */
239 wined3d_mutex_lock();
240 memset(&material->mat, 0, sizeof(material->mat));
241 memcpy(&material->mat, mat, mat->dwSize);
242 wined3d_mutex_unlock();
244 return DD_OK;
247 /*****************************************************************************
248 * IDirect3DMaterial3::GetMaterial
250 * Returns the material assigned to this interface
252 * Params:
253 * Mat: Pointer to a D3DMATERIAL structure to store the material description
255 * Returns:
256 * D3D_OK on success
257 * DDERR_INVALIDPARAMS if Mat is NULL
259 *****************************************************************************/
260 static HRESULT WINAPI d3d_material3_GetMaterial(IDirect3DMaterial3 *iface, D3DMATERIAL *mat)
262 struct d3d_material *material = impl_from_IDirect3DMaterial3(iface);
263 DWORD dwSize;
265 TRACE("iface %p, mat %p.\n", iface, mat);
266 if (TRACE_ON(ddraw))
268 TRACE(" Returning material : ");
269 dump_material(&material->mat);
272 /* Copies the material structure */
273 wined3d_mutex_lock();
274 dwSize = mat->dwSize;
275 memcpy(mat, &material->mat, dwSize);
276 wined3d_mutex_unlock();
278 return DD_OK;
281 /*****************************************************************************
282 * IDirect3DMaterial3::GetHandle
284 * Returns a handle for the material interface. The handle is simply a
285 * pointer to the material implementation
287 * Params:
288 * Direct3DDevice3: The device this handle is assigned to
289 * Handle: Address to write the handle to
291 * Returns:
292 * D3D_OK on success
293 * DDERR_INVALIDPARAMS if Handle is NULL
295 *****************************************************************************/
296 static HRESULT WINAPI d3d_material3_GetHandle(IDirect3DMaterial3 *iface,
297 IDirect3DDevice3 *device, D3DMATERIALHANDLE *handle)
299 struct d3d_material *material = impl_from_IDirect3DMaterial3(iface);
300 IDirect3DDeviceImpl *device_impl = unsafe_impl_from_IDirect3DDevice3(device);
302 TRACE("iface %p, device %p, handle %p.\n", iface, device, handle);
304 wined3d_mutex_lock();
305 material->active_device = device_impl;
306 if (!material->Handle)
308 DWORD h = ddraw_allocate_handle(&device_impl->handle_table, material, DDRAW_HANDLE_MATERIAL);
309 if (h == DDRAW_INVALID_HANDLE)
311 ERR("Failed to allocate a material handle.\n");
312 wined3d_mutex_unlock();
313 return DDERR_INVALIDPARAMS; /* Unchecked */
316 material->Handle = h + 1;
318 *handle = material->Handle;
319 TRACE(" returning handle %08x.\n", *handle);
320 wined3d_mutex_unlock();
322 return D3D_OK;
325 static HRESULT WINAPI d3d_material2_GetHandle(IDirect3DMaterial2 *iface,
326 IDirect3DDevice2 *device, D3DMATERIALHANDLE *handle)
328 struct d3d_material *material = impl_from_IDirect3DMaterial2(iface);
329 IDirect3DDeviceImpl *device_impl = unsafe_impl_from_IDirect3DDevice2(device);
331 TRACE("iface %p, device %p, handle %p.\n", iface, device, handle);
333 return d3d_material3_GetHandle(&material->IDirect3DMaterial3_iface,
334 device_impl ? &device_impl->IDirect3DDevice3_iface : NULL, handle);
337 static HRESULT WINAPI d3d_material1_GetHandle(IDirect3DMaterial *iface,
338 IDirect3DDevice *device, D3DMATERIALHANDLE *handle)
340 struct d3d_material *material = impl_from_IDirect3DMaterial(iface);
341 IDirect3DDeviceImpl *device_impl = unsafe_impl_from_IDirect3DDevice(device);
343 TRACE("iface %p, device %p, handle %p.\n", iface, device, handle);
345 return d3d_material3_GetHandle(&material->IDirect3DMaterial3_iface,
346 device_impl ? &device_impl->IDirect3DDevice3_iface : NULL, handle);
349 static HRESULT WINAPI d3d_material2_QueryInterface(IDirect3DMaterial2 *iface, REFIID riid, void **object)
351 struct d3d_material *material = impl_from_IDirect3DMaterial2(iface);
353 TRACE("iface %p, riid %s, object %p.\n", iface, debugstr_guid(riid), object);
355 return d3d_material3_QueryInterface(&material->IDirect3DMaterial3_iface, riid, object);
358 static HRESULT WINAPI d3d_material1_QueryInterface(IDirect3DMaterial *iface, REFIID riid, void **object)
360 struct d3d_material *material = impl_from_IDirect3DMaterial(iface);
362 TRACE("iface %p, riid %s, object %p.\n", iface, debugstr_guid(riid), object);
364 return d3d_material3_QueryInterface(&material->IDirect3DMaterial3_iface, riid, object);
367 static ULONG WINAPI d3d_material2_AddRef(IDirect3DMaterial2 *iface)
369 struct d3d_material *material = impl_from_IDirect3DMaterial2(iface);
371 TRACE("iface %p.\n", iface);
373 return d3d_material3_AddRef(&material->IDirect3DMaterial3_iface);
376 static ULONG WINAPI d3d_material1_AddRef(IDirect3DMaterial *iface)
378 struct d3d_material *material = impl_from_IDirect3DMaterial(iface);
380 TRACE("iface %p.\n", iface);
382 return d3d_material3_AddRef(&material->IDirect3DMaterial3_iface);
385 static ULONG WINAPI d3d_material2_Release(IDirect3DMaterial2 *iface)
387 struct d3d_material *material = impl_from_IDirect3DMaterial2(iface);
389 TRACE("iface %p.\n", iface);
391 return d3d_material3_Release(&material->IDirect3DMaterial3_iface);
394 static ULONG WINAPI d3d_material1_Release(IDirect3DMaterial *iface)
396 struct d3d_material *material = impl_from_IDirect3DMaterial(iface);
398 TRACE("iface %p.\n", iface);
400 return d3d_material3_Release(&material->IDirect3DMaterial3_iface);
403 static HRESULT WINAPI d3d_material2_SetMaterial(IDirect3DMaterial2 *iface, D3DMATERIAL *mat)
405 struct d3d_material *material = impl_from_IDirect3DMaterial2(iface);
407 TRACE("iface %p, material %p.\n", iface, mat);
409 return d3d_material3_SetMaterial(&material->IDirect3DMaterial3_iface, mat);
412 static HRESULT WINAPI d3d_material1_SetMaterial(IDirect3DMaterial *iface, D3DMATERIAL *mat)
414 struct d3d_material *material = impl_from_IDirect3DMaterial(iface);
416 TRACE("iface %p, material %p.\n", iface, mat);
418 return d3d_material3_SetMaterial(&material->IDirect3DMaterial3_iface, mat);
421 static HRESULT WINAPI d3d_material2_GetMaterial(IDirect3DMaterial2 *iface, D3DMATERIAL *mat)
423 struct d3d_material *material = impl_from_IDirect3DMaterial2(iface);
425 TRACE("iface %p, material %p.\n", iface, mat);
427 return d3d_material3_GetMaterial(&material->IDirect3DMaterial3_iface, mat);
430 static HRESULT WINAPI d3d_material1_GetMaterial(IDirect3DMaterial *iface, D3DMATERIAL *mat)
432 struct d3d_material *material = impl_from_IDirect3DMaterial(iface);
434 TRACE("iface %p, material %p.\n", iface, mat);
436 return d3d_material3_GetMaterial(&material->IDirect3DMaterial3_iface, mat);
440 /*****************************************************************************
441 * material_activate
443 * Uses IDirect3DDevice7::SetMaterial to activate the material
445 * Params:
446 * This: Pointer to the material implementation to activate
448 *****************************************************************************/
449 void material_activate(struct d3d_material *material)
451 D3DMATERIAL7 d3d7mat;
453 TRACE("Activating material %p.\n", material);
455 d3d7mat.u.diffuse = material->mat.u.diffuse;
456 d3d7mat.u1.ambient = material->mat.u1.ambient;
457 d3d7mat.u2.specular = material->mat.u2.specular;
458 d3d7mat.u3.emissive = material->mat.u3.emissive;
459 d3d7mat.u4.power = material->mat.u4.power;
461 IDirect3DDevice7_SetMaterial(&material->active_device->IDirect3DDevice7_iface, &d3d7mat);
464 static const struct IDirect3DMaterial3Vtbl d3d_material3_vtbl =
466 /*** IUnknown Methods ***/
467 d3d_material3_QueryInterface,
468 d3d_material3_AddRef,
469 d3d_material3_Release,
470 /*** IDirect3DMaterial3 Methods ***/
471 d3d_material3_SetMaterial,
472 d3d_material3_GetMaterial,
473 d3d_material3_GetHandle,
476 static const struct IDirect3DMaterial2Vtbl d3d_material2_vtbl =
478 /*** IUnknown Methods ***/
479 d3d_material2_QueryInterface,
480 d3d_material2_AddRef,
481 d3d_material2_Release,
482 /*** IDirect3DMaterial2 Methods ***/
483 d3d_material2_SetMaterial,
484 d3d_material2_GetMaterial,
485 d3d_material2_GetHandle,
488 static const struct IDirect3DMaterialVtbl d3d_material1_vtbl =
490 /*** IUnknown Methods ***/
491 d3d_material1_QueryInterface,
492 d3d_material1_AddRef,
493 d3d_material1_Release,
494 /*** IDirect3DMaterial1 Methods ***/
495 d3d_material1_Initialize,
496 d3d_material1_SetMaterial,
497 d3d_material1_GetMaterial,
498 d3d_material1_GetHandle,
499 d3d_material1_Reserve,
500 d3d_material1_Unreserve,
503 struct d3d_material *d3d_material_create(struct ddraw *ddraw)
505 struct d3d_material *material;
507 material = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*material));
508 if (!material)
509 return NULL;
511 material->IDirect3DMaterial3_iface.lpVtbl = &d3d_material3_vtbl;
512 material->IDirect3DMaterial2_iface.lpVtbl = &d3d_material2_vtbl;
513 material->IDirect3DMaterial_iface.lpVtbl = &d3d_material1_vtbl;
514 material->ref = 1;
515 material->ddraw = ddraw;
517 return material;