winmm: GetDeviceID only considers a single name per entry.
[wine] / dlls / ddraw / material.c
1 /* Direct3D Material
2  * Copyright (c) 2002 Lionel ULMER
3  * Copyright (c) 2006 Stefan DÖSINGER
4  *
5  * This file contains the implementation of Direct3DMaterial.
6  *
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.
11  *
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.
16  *
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
20  */
21
22 #include "config.h"
23 #include "wine/port.h"
24
25 #include "ddraw_private.h"
26
27 WINE_DEFAULT_DEBUG_CHANNEL(ddraw);
28
29 static void dump_material(const D3DMATERIAL *mat)
30 {
31     TRACE("  dwSize : %d\n", mat->dwSize);
32 }
33
34 static inline IDirect3DMaterialImpl *material_from_material1(IDirect3DMaterial *iface)
35 {
36     return (IDirect3DMaterialImpl *)((char*)iface - FIELD_OFFSET(IDirect3DMaterialImpl, IDirect3DMaterial_vtbl));
37 }
38
39 static inline IDirect3DMaterialImpl *material_from_material2(IDirect3DMaterial2 *iface)
40 {
41     return (IDirect3DMaterialImpl *)((char*)iface - FIELD_OFFSET(IDirect3DMaterialImpl, IDirect3DMaterial2_vtbl));
42 }
43
44 /*****************************************************************************
45  * IUnknown Methods.
46  *****************************************************************************/
47
48 /*****************************************************************************
49  * IDirect3DMaterial3::QueryInterface
50  *
51  * QueryInterface for IDirect3DMaterial. Can query all IDirect3DMaterial
52  * versions.
53  *
54  * Params:
55  *  riid: Interface id queried for
56  *  obj: Address to pass the interface pointer back
57  *
58  * Returns:
59  *  S_OK on success
60  *  E_NOINTERFACE if the requested interface wasn't found
61  *
62  *****************************************************************************/
63 static HRESULT WINAPI
64 IDirect3DMaterialImpl_QueryInterface(IDirect3DMaterial3 *iface,
65                                      REFIID riid,
66                                      LPVOID* obp)
67 {
68     IDirect3DMaterialImpl *This = (IDirect3DMaterialImpl *)iface;
69
70     TRACE("iface %p, riid %s, object %p.\n", iface, debugstr_guid(riid), obp);
71
72     *obp = NULL;
73
74     if ( IsEqualGUID( &IID_IUnknown,  riid ) ) {
75         IUnknown_AddRef(iface);
76         *obp = iface;
77         TRACE("  Creating IUnknown interface at %p.\n", *obp);
78         return S_OK;
79     }
80     if ( IsEqualGUID( &IID_IDirect3DMaterial, riid ) ) {
81         IDirect3DMaterial_AddRef((IDirect3DMaterial *)&This->IDirect3DMaterial_vtbl);
82         *obp = &This->IDirect3DMaterial_vtbl;
83         TRACE("  Creating IDirect3DMaterial interface %p\n", *obp);
84         return S_OK;
85     }
86     if ( IsEqualGUID( &IID_IDirect3DMaterial2, riid ) ) {
87         IDirect3DMaterial_AddRef((IDirect3DMaterial2 *)&This->IDirect3DMaterial2_vtbl);
88         *obp = &This->IDirect3DMaterial2_vtbl;
89         TRACE("  Creating IDirect3DMaterial2 interface %p\n", *obp);
90         return S_OK;
91     }
92     if ( IsEqualGUID( &IID_IDirect3DMaterial3, riid ) ) {
93         IDirect3DMaterial3_AddRef((IDirect3DMaterial3 *)This);
94         *obp = This;
95         TRACE("  Creating IDirect3DMaterial3 interface %p\n", *obp);
96         return S_OK;
97     }
98     FIXME("(%p): interface for IID %s NOT found!\n", This, debugstr_guid(riid));
99     return E_NOINTERFACE;
100 }
101
102 /*****************************************************************************
103  * IDirect3DMaterial3::AddRef
104  *
105  * Increases the refcount.
106  *
107  * Returns:
108  *  The new refcount
109  *
110  *****************************************************************************/
111 static ULONG WINAPI
112 IDirect3DMaterialImpl_AddRef(IDirect3DMaterial3 *iface)
113 {
114     IDirect3DMaterialImpl *This = (IDirect3DMaterialImpl *)iface;
115     ULONG ref = InterlockedIncrement(&This->ref);
116
117     TRACE("%p increasing refcount to %u.\n", This, ref);
118
119     return ref;
120 }
121
122 /*****************************************************************************
123  * IDirect3DMaterial3::Release
124  *
125  * Reduces the refcount by one. If the refcount falls to 0, the object
126  * is destroyed
127  *
128  * Returns:
129  *  The new refcount
130  *
131  *****************************************************************************/
132 static ULONG WINAPI
133 IDirect3DMaterialImpl_Release(IDirect3DMaterial3 *iface)
134 {
135     IDirect3DMaterialImpl *This = (IDirect3DMaterialImpl *)iface;
136     ULONG ref = InterlockedDecrement(&This->ref);
137
138     TRACE("%p decreasing refcount to %u.\n", This, ref);
139
140     if (!ref)
141     {
142         if(This->Handle)
143         {
144             EnterCriticalSection(&ddraw_cs);
145             ddraw_free_handle(&This->ddraw->d3ddevice->handle_table, This->Handle - 1, DDRAW_HANDLE_MATERIAL);
146             LeaveCriticalSection(&ddraw_cs);
147         }
148
149         HeapFree(GetProcessHeap(), 0, This);
150         return 0;
151     }
152     return ref;
153 }
154
155 /*****************************************************************************
156  * IDirect3DMaterial Methods
157  *****************************************************************************/
158
159 /*****************************************************************************
160  * IDirect3DMaterial::Initialize
161  *
162  * A no-op initialization
163  *
164  * Params:
165  *  Direct3D: Pointer to a Direct3D interface
166  *
167  * Returns:
168  *  D3D_OK
169  *
170  *****************************************************************************/
171 static HRESULT WINAPI
172 IDirect3DMaterialImpl_Initialize(IDirect3DMaterial *iface,
173                                   IDirect3D *Direct3D)
174 {
175     TRACE("iface %p, d3d %p.\n", iface, Direct3D);
176
177     return D3D_OK;
178 }
179
180 /*****************************************************************************
181  * IDirect3DMaterial::Reserve
182  *
183  * DirectX 5 sdk: "The IDirect3DMaterial2::Reserve method is not implemented"
184  * Odd. They seem to have mixed their interfaces.
185  *
186  * Returns:
187  *  DDERR_UNSUPPORTED
188  *
189  *****************************************************************************/
190 static HRESULT WINAPI
191 IDirect3DMaterialImpl_Reserve(IDirect3DMaterial *iface)
192 {
193     TRACE("iface %p.\n", iface);
194
195     return DDERR_UNSUPPORTED;
196 }
197
198 /*****************************************************************************
199  * IDirect3DMaterial::Unreserve
200  *
201  * Not supported too
202  *
203  * Returns:
204  *  DDERR_UNSUPPORTED
205  *
206  *****************************************************************************/
207 static HRESULT WINAPI
208 IDirect3DMaterialImpl_Unreserve(IDirect3DMaterial *iface)
209 {
210     TRACE("iface %p.\n", iface);
211
212     return DDERR_UNSUPPORTED;
213 }
214
215 /*****************************************************************************
216  * IDirect3DMaterial3::SetMaterial
217  *
218  * Sets the material description
219  *
220  * Params:
221  *  Mat: Material to set
222  *
223  * Returns:
224  *  D3D_OK on success
225  *  DDERR_INVALIDPARAMS if Mat is NULL
226  *
227  *****************************************************************************/
228 static HRESULT WINAPI
229 IDirect3DMaterialImpl_SetMaterial(IDirect3DMaterial3 *iface,
230                                   D3DMATERIAL *lpMat)
231 {
232     IDirect3DMaterialImpl *This = (IDirect3DMaterialImpl *)iface;
233
234     TRACE("iface %p, material %p.\n", iface, lpMat);
235     if (TRACE_ON(ddraw))
236         dump_material(lpMat);
237
238     /* Stores the material */
239     EnterCriticalSection(&ddraw_cs);
240     memset(&This->mat, 0, sizeof(This->mat));
241     memcpy(&This->mat, lpMat, lpMat->dwSize);
242     LeaveCriticalSection(&ddraw_cs);
243
244     return DD_OK;
245 }
246
247 /*****************************************************************************
248  * IDirect3DMaterial3::GetMaterial
249  *
250  * Returns the material assigned to this interface
251  *
252  * Params:
253  *  Mat: Pointer to a D3DMATERIAL structure to store the material description
254  *
255  * Returns:
256  *  D3D_OK on success
257  *  DDERR_INVALIDPARAMS if Mat is NULL
258  *
259  *****************************************************************************/
260 static HRESULT WINAPI
261 IDirect3DMaterialImpl_GetMaterial(IDirect3DMaterial3 *iface,
262                                   D3DMATERIAL *lpMat)
263 {
264     IDirect3DMaterialImpl *This = (IDirect3DMaterialImpl *)iface;
265     DWORD dwSize;
266
267     TRACE("iface %p, material %p.\n", iface, lpMat);
268     if (TRACE_ON(ddraw))
269     {
270         TRACE("  Returning material : ");
271         dump_material(&This->mat);
272     }
273
274     /* Copies the material structure */
275     EnterCriticalSection(&ddraw_cs);
276     dwSize = lpMat->dwSize;
277     memcpy(lpMat, &This->mat, dwSize);
278     LeaveCriticalSection(&ddraw_cs);
279
280     return DD_OK;
281 }
282
283 /*****************************************************************************
284  * IDirect3DMaterial3::GetHandle
285  *
286  * Returns a handle for the material interface. The handle is simply a
287  * pointer to the material implementation
288  *
289  * Params:
290  *  Direct3DDevice3: The device this handle is assigned to
291  *  Handle: Address to write the handle to
292  *
293  * Returns:
294  *  D3D_OK on success
295  *  DDERR_INVALIDPARAMS if Handle is NULL
296  *
297  *****************************************************************************/
298 static HRESULT WINAPI
299 IDirect3DMaterialImpl_GetHandle(IDirect3DMaterial3 *iface,
300                                 IDirect3DDevice3 *lpDirect3DDevice3,
301                                 D3DMATERIALHANDLE *lpHandle)
302 {
303     IDirect3DMaterialImpl *This = (IDirect3DMaterialImpl *)iface;
304     IDirect3DDeviceImpl *device = device_from_device3(lpDirect3DDevice3);
305
306     TRACE("iface %p, device %p, handle %p.\n", iface, lpDirect3DDevice3, lpHandle);
307
308     EnterCriticalSection(&ddraw_cs);
309     This->active_device = device;
310     if(!This->Handle)
311     {
312         DWORD h = ddraw_allocate_handle(&device->handle_table, This, DDRAW_HANDLE_MATERIAL);
313         if (h == DDRAW_INVALID_HANDLE)
314         {
315             ERR("Failed to allocate a material handle.\n");
316             LeaveCriticalSection(&ddraw_cs);
317             return DDERR_INVALIDPARAMS;   /* Unchecked */
318         }
319
320         This->Handle = h + 1;
321     }
322     *lpHandle = This->Handle;
323     TRACE(" returning handle %08x.\n", *lpHandle);
324     LeaveCriticalSection(&ddraw_cs);
325
326     return D3D_OK;
327 }
328
329 static HRESULT WINAPI
330 Thunk_IDirect3DMaterialImpl_2_GetHandle(LPDIRECT3DMATERIAL2 iface,
331                                         LPDIRECT3DDEVICE2 lpDirect3DDevice2,
332                                         LPD3DMATERIALHANDLE lpHandle)
333 {
334     TRACE("iface %p, device %p, handle %p.\n", iface, lpDirect3DDevice2, lpHandle);
335
336     return IDirect3DMaterial3_GetHandle((IDirect3DMaterial3 *)material_from_material2(iface), lpDirect3DDevice2 ?
337             (IDirect3DDevice3 *)&device_from_device2(lpDirect3DDevice2)->IDirect3DDevice3_vtbl : NULL, lpHandle);
338 }
339
340 static HRESULT WINAPI
341 Thunk_IDirect3DMaterialImpl_1_GetHandle(LPDIRECT3DMATERIAL iface,
342                                         LPDIRECT3DDEVICE lpDirect3DDevice,
343                                         LPD3DMATERIALHANDLE lpHandle)
344 {
345     TRACE("iface %p, device %p, handle %p.\n", iface, lpDirect3DDevice, lpHandle);
346
347     return IDirect3DMaterial3_GetHandle((IDirect3DMaterial3 *)material_from_material1(iface), lpDirect3DDevice ?
348             (IDirect3DDevice3 *)&device_from_device1(lpDirect3DDevice)->IDirect3DDevice3_vtbl : NULL, lpHandle);
349 }
350
351 static HRESULT WINAPI
352 Thunk_IDirect3DMaterialImpl_2_QueryInterface(LPDIRECT3DMATERIAL2 iface,
353                                              REFIID riid,
354                                              LPVOID* obp)
355 {
356     TRACE("iface %p, riid %s, object %p.\n", iface, debugstr_guid(riid), obp);
357
358     return IDirect3DMaterial3_QueryInterface((IDirect3DMaterial3 *)material_from_material2(iface), riid, obp);
359 }
360
361 static HRESULT WINAPI
362 Thunk_IDirect3DMaterialImpl_1_QueryInterface(LPDIRECT3DMATERIAL iface,
363                                              REFIID riid,
364                                              LPVOID* obp)
365 {
366     TRACE("iface %p, riid %s, object %p.\n", iface, debugstr_guid(riid), obp);
367
368     return IDirect3DMaterial3_QueryInterface((IDirect3DMaterial3 *)material_from_material1(iface), riid, obp);
369 }
370
371 static ULONG WINAPI
372 Thunk_IDirect3DMaterialImpl_2_AddRef(LPDIRECT3DMATERIAL2 iface)
373 {
374     TRACE("iface %p.\n", iface);
375
376     return IDirect3DMaterial3_AddRef((IDirect3DMaterial3 *)material_from_material2(iface));
377 }
378
379 static ULONG WINAPI
380 Thunk_IDirect3DMaterialImpl_1_AddRef(LPDIRECT3DMATERIAL iface)
381 {
382     TRACE("iface %p.\n", iface);
383
384     return IDirect3DMaterial3_AddRef((IDirect3DMaterial3 *)material_from_material1(iface));
385 }
386
387 static ULONG WINAPI
388 Thunk_IDirect3DMaterialImpl_2_Release(LPDIRECT3DMATERIAL2 iface)
389 {
390     TRACE("iface %p.\n", iface);
391
392     return IDirect3DMaterial3_Release((IDirect3DMaterial3 *)material_from_material2(iface));
393 }
394
395 static ULONG WINAPI
396 Thunk_IDirect3DMaterialImpl_1_Release(LPDIRECT3DMATERIAL iface)
397 {
398     TRACE("iface %p.\n", iface);
399
400     return IDirect3DMaterial3_Release((IDirect3DMaterial3 *)material_from_material1(iface));
401 }
402
403 static HRESULT WINAPI
404 Thunk_IDirect3DMaterialImpl_2_SetMaterial(LPDIRECT3DMATERIAL2 iface,
405                                           LPD3DMATERIAL lpMat)
406 {
407     TRACE("iface %p, material %p.\n", iface, lpMat);
408
409     return IDirect3DMaterial3_SetMaterial((IDirect3DMaterial3 *)material_from_material2(iface), lpMat);
410 }
411
412 static HRESULT WINAPI
413 Thunk_IDirect3DMaterialImpl_1_SetMaterial(LPDIRECT3DMATERIAL iface,
414                                           LPD3DMATERIAL lpMat)
415 {
416     TRACE("iface %p, material %p.\n", iface, lpMat);
417
418     return IDirect3DMaterial3_SetMaterial((IDirect3DMaterial3 *)material_from_material1(iface), lpMat);
419 }
420
421 static HRESULT WINAPI
422 Thunk_IDirect3DMaterialImpl_2_GetMaterial(LPDIRECT3DMATERIAL2 iface,
423                                           LPD3DMATERIAL lpMat)
424 {
425     TRACE("iface %p, material %p.\n", iface, lpMat);
426
427     return IDirect3DMaterial3_GetMaterial((IDirect3DMaterial3 *)material_from_material2(iface), lpMat);
428 }
429
430 static HRESULT WINAPI
431 Thunk_IDirect3DMaterialImpl_1_GetMaterial(LPDIRECT3DMATERIAL iface,
432                                           LPD3DMATERIAL lpMat)
433 {
434     TRACE("iface %p, material %p.\n", iface, lpMat);
435
436     return IDirect3DMaterial3_GetMaterial((IDirect3DMaterial3 *)material_from_material1(iface), lpMat);
437 }
438
439
440 /*****************************************************************************
441  * material_activate
442  *
443  * Uses IDirect3DDevice7::SetMaterial to activate the material
444  *
445  * Params:
446  *  This: Pointer to the material implementation to activate
447  *
448  *****************************************************************************/
449 void material_activate(IDirect3DMaterialImpl* This)
450 {
451     D3DMATERIAL7 d3d7mat;
452
453     TRACE("Activating material %p\n", This);
454     d3d7mat.u.diffuse = This->mat.u.diffuse;
455     d3d7mat.u1.ambient = This->mat.u1.ambient;
456     d3d7mat.u2.specular = This->mat.u2.specular;
457     d3d7mat.u3.emissive = This->mat.u3.emissive;
458     d3d7mat.u4.power = This->mat.u4.power;
459
460     IDirect3DDevice7_SetMaterial((IDirect3DDevice7 *)This->active_device, &d3d7mat);
461 }
462
463 static const struct IDirect3DMaterial3Vtbl d3d_material3_vtbl =
464 {
465     /*** IUnknown Methods ***/
466     IDirect3DMaterialImpl_QueryInterface,
467     IDirect3DMaterialImpl_AddRef,
468     IDirect3DMaterialImpl_Release,
469     /*** IDirect3DMaterial3 Methods ***/
470     IDirect3DMaterialImpl_SetMaterial,
471     IDirect3DMaterialImpl_GetMaterial,
472     IDirect3DMaterialImpl_GetHandle,
473 };
474
475 static const struct IDirect3DMaterial2Vtbl d3d_material2_vtbl =
476 {
477     /*** IUnknown Methods ***/
478     Thunk_IDirect3DMaterialImpl_2_QueryInterface,
479     Thunk_IDirect3DMaterialImpl_2_AddRef,
480     Thunk_IDirect3DMaterialImpl_2_Release,
481     /*** IDirect3DMaterial2 Methods ***/
482     Thunk_IDirect3DMaterialImpl_2_SetMaterial,
483     Thunk_IDirect3DMaterialImpl_2_GetMaterial,
484     Thunk_IDirect3DMaterialImpl_2_GetHandle,
485 };
486
487 static const struct IDirect3DMaterialVtbl d3d_material1_vtbl =
488 {
489     /*** IUnknown Methods ***/
490     Thunk_IDirect3DMaterialImpl_1_QueryInterface,
491     Thunk_IDirect3DMaterialImpl_1_AddRef,
492     Thunk_IDirect3DMaterialImpl_1_Release,
493     /*** IDirect3DMaterial1 Methods ***/
494     IDirect3DMaterialImpl_Initialize,
495     Thunk_IDirect3DMaterialImpl_1_SetMaterial,
496     Thunk_IDirect3DMaterialImpl_1_GetMaterial,
497     Thunk_IDirect3DMaterialImpl_1_GetHandle,
498     IDirect3DMaterialImpl_Reserve,
499     IDirect3DMaterialImpl_Unreserve
500 };
501
502 void d3d_material_init(IDirect3DMaterialImpl *material, IDirectDrawImpl *ddraw)
503 {
504     material->lpVtbl = &d3d_material3_vtbl;
505     material->IDirect3DMaterial2_vtbl = &d3d_material2_vtbl;
506     material->IDirect3DMaterial_vtbl = &d3d_material1_vtbl;
507     material->ref = 1;
508     material->ddraw = ddraw;
509 }