kernel32: Moved device-related stubs from psapi to kernel32.
[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 IDirect3DMaterialImpl_2_GetHandle(IDirect3DMaterial2 *iface,
330         IDirect3DDevice2 *lpDirect3DDevice2, D3DMATERIALHANDLE *lpHandle)
331 {
332     TRACE("iface %p, device %p, handle %p.\n", iface, lpDirect3DDevice2, lpHandle);
333
334     return IDirect3DMaterial3_GetHandle((IDirect3DMaterial3 *)material_from_material2(iface), lpDirect3DDevice2 ?
335             (IDirect3DDevice3 *)&device_from_device2(lpDirect3DDevice2)->IDirect3DDevice3_vtbl : NULL, lpHandle);
336 }
337
338 static HRESULT WINAPI IDirect3DMaterialImpl_1_GetHandle(IDirect3DMaterial *iface,
339         IDirect3DDevice *lpDirect3DDevice, D3DMATERIALHANDLE *lpHandle)
340 {
341     TRACE("iface %p, device %p, handle %p.\n", iface, lpDirect3DDevice, lpHandle);
342
343     return IDirect3DMaterial3_GetHandle((IDirect3DMaterial3 *)material_from_material1(iface), lpDirect3DDevice ?
344             (IDirect3DDevice3 *)&device_from_device1(lpDirect3DDevice)->IDirect3DDevice3_vtbl : NULL, lpHandle);
345 }
346
347 static HRESULT WINAPI IDirect3DMaterialImpl_2_QueryInterface(LPDIRECT3DMATERIAL2 iface, REFIID riid,
348         LPVOID* obp)
349 {
350     TRACE("iface %p, riid %s, object %p.\n", iface, debugstr_guid(riid), obp);
351
352     return IDirect3DMaterial3_QueryInterface((IDirect3DMaterial3 *)material_from_material2(iface), riid, obp);
353 }
354
355 static HRESULT WINAPI IDirect3DMaterialImpl_1_QueryInterface(LPDIRECT3DMATERIAL iface, REFIID riid,
356         LPVOID* obp)
357 {
358     TRACE("iface %p, riid %s, object %p.\n", iface, debugstr_guid(riid), obp);
359
360     return IDirect3DMaterial3_QueryInterface((IDirect3DMaterial3 *)material_from_material1(iface), riid, obp);
361 }
362
363 static ULONG WINAPI IDirect3DMaterialImpl_2_AddRef(LPDIRECT3DMATERIAL2 iface)
364 {
365     TRACE("iface %p.\n", iface);
366
367     return IDirect3DMaterial3_AddRef((IDirect3DMaterial3 *)material_from_material2(iface));
368 }
369
370 static ULONG WINAPI IDirect3DMaterialImpl_1_AddRef(LPDIRECT3DMATERIAL iface)
371 {
372     TRACE("iface %p.\n", iface);
373
374     return IDirect3DMaterial3_AddRef((IDirect3DMaterial3 *)material_from_material1(iface));
375 }
376
377 static ULONG WINAPI IDirect3DMaterialImpl_2_Release(LPDIRECT3DMATERIAL2 iface)
378 {
379     TRACE("iface %p.\n", iface);
380
381     return IDirect3DMaterial3_Release((IDirect3DMaterial3 *)material_from_material2(iface));
382 }
383
384 static ULONG WINAPI IDirect3DMaterialImpl_1_Release(LPDIRECT3DMATERIAL iface)
385 {
386     TRACE("iface %p.\n", iface);
387
388     return IDirect3DMaterial3_Release((IDirect3DMaterial3 *)material_from_material1(iface));
389 }
390
391 static HRESULT WINAPI IDirect3DMaterialImpl_2_SetMaterial(LPDIRECT3DMATERIAL2 iface,
392         LPD3DMATERIAL lpMat)
393 {
394     TRACE("iface %p, material %p.\n", iface, lpMat);
395
396     return IDirect3DMaterial3_SetMaterial((IDirect3DMaterial3 *)material_from_material2(iface), lpMat);
397 }
398
399 static HRESULT WINAPI IDirect3DMaterialImpl_1_SetMaterial(LPDIRECT3DMATERIAL iface,
400         LPD3DMATERIAL lpMat)
401 {
402     TRACE("iface %p, material %p.\n", iface, lpMat);
403
404     return IDirect3DMaterial3_SetMaterial((IDirect3DMaterial3 *)material_from_material1(iface), lpMat);
405 }
406
407 static HRESULT WINAPI IDirect3DMaterialImpl_2_GetMaterial(LPDIRECT3DMATERIAL2 iface,
408         LPD3DMATERIAL lpMat)
409 {
410     TRACE("iface %p, material %p.\n", iface, lpMat);
411
412     return IDirect3DMaterial3_GetMaterial((IDirect3DMaterial3 *)material_from_material2(iface), lpMat);
413 }
414
415 static HRESULT WINAPI IDirect3DMaterialImpl_1_GetMaterial(LPDIRECT3DMATERIAL iface,
416         LPD3DMATERIAL lpMat)
417 {
418     TRACE("iface %p, material %p.\n", iface, lpMat);
419
420     return IDirect3DMaterial3_GetMaterial((IDirect3DMaterial3 *)material_from_material1(iface), lpMat);
421 }
422
423
424 /*****************************************************************************
425  * material_activate
426  *
427  * Uses IDirect3DDevice7::SetMaterial to activate the material
428  *
429  * Params:
430  *  This: Pointer to the material implementation to activate
431  *
432  *****************************************************************************/
433 void material_activate(IDirect3DMaterialImpl* This)
434 {
435     D3DMATERIAL7 d3d7mat;
436
437     TRACE("Activating material %p\n", This);
438     d3d7mat.u.diffuse = This->mat.u.diffuse;
439     d3d7mat.u1.ambient = This->mat.u1.ambient;
440     d3d7mat.u2.specular = This->mat.u2.specular;
441     d3d7mat.u3.emissive = This->mat.u3.emissive;
442     d3d7mat.u4.power = This->mat.u4.power;
443
444     IDirect3DDevice7_SetMaterial((IDirect3DDevice7 *)This->active_device, &d3d7mat);
445 }
446
447 static const struct IDirect3DMaterial3Vtbl d3d_material3_vtbl =
448 {
449     /*** IUnknown Methods ***/
450     IDirect3DMaterialImpl_QueryInterface,
451     IDirect3DMaterialImpl_AddRef,
452     IDirect3DMaterialImpl_Release,
453     /*** IDirect3DMaterial3 Methods ***/
454     IDirect3DMaterialImpl_SetMaterial,
455     IDirect3DMaterialImpl_GetMaterial,
456     IDirect3DMaterialImpl_GetHandle,
457 };
458
459 static const struct IDirect3DMaterial2Vtbl d3d_material2_vtbl =
460 {
461     /*** IUnknown Methods ***/
462     IDirect3DMaterialImpl_2_QueryInterface,
463     IDirect3DMaterialImpl_2_AddRef,
464     IDirect3DMaterialImpl_2_Release,
465     /*** IDirect3DMaterial2 Methods ***/
466     IDirect3DMaterialImpl_2_SetMaterial,
467     IDirect3DMaterialImpl_2_GetMaterial,
468     IDirect3DMaterialImpl_2_GetHandle,
469 };
470
471 static const struct IDirect3DMaterialVtbl d3d_material1_vtbl =
472 {
473     /*** IUnknown Methods ***/
474     IDirect3DMaterialImpl_1_QueryInterface,
475     IDirect3DMaterialImpl_1_AddRef,
476     IDirect3DMaterialImpl_1_Release,
477     /*** IDirect3DMaterial1 Methods ***/
478     IDirect3DMaterialImpl_Initialize,
479     IDirect3DMaterialImpl_1_SetMaterial,
480     IDirect3DMaterialImpl_1_GetMaterial,
481     IDirect3DMaterialImpl_1_GetHandle,
482     IDirect3DMaterialImpl_Reserve,
483     IDirect3DMaterialImpl_Unreserve
484 };
485
486 void d3d_material_init(IDirect3DMaterialImpl *material, IDirectDrawImpl *ddraw)
487 {
488     material->lpVtbl = &d3d_material3_vtbl;
489     material->IDirect3DMaterial2_vtbl = &d3d_material2_vtbl;
490     material->IDirect3DMaterial_vtbl = &d3d_material1_vtbl;
491     material->ref = 1;
492     material->ddraw = ddraw;
493 }