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