Synchronize with trunk r58457.
[reactos.git] / dll / directx / wine / 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 struct d3d_material *impl_from_IDirect3DMaterial(IDirect3DMaterial *iface)
35 {
36 return CONTAINING_RECORD(iface, struct d3d_material, IDirect3DMaterial_iface);
37 }
38
39 static inline struct d3d_material *impl_from_IDirect3DMaterial2(IDirect3DMaterial2 *iface)
40 {
41 return CONTAINING_RECORD(iface, struct d3d_material, IDirect3DMaterial2_iface);
42 }
43
44 static inline struct d3d_material *impl_from_IDirect3DMaterial3(IDirect3DMaterial3 *iface)
45 {
46 return CONTAINING_RECORD(iface, struct d3d_material, IDirect3DMaterial3_iface);
47 }
48
49 /*****************************************************************************
50 * IUnknown Methods.
51 *****************************************************************************/
52
53 /*****************************************************************************
54 * IDirect3DMaterial3::QueryInterface
55 *
56 * QueryInterface for IDirect3DMaterial. Can query all IDirect3DMaterial
57 * versions.
58 *
59 * Params:
60 * riid: Interface id queried for
61 * obj: Address to pass the interface pointer back
62 *
63 * Returns:
64 * S_OK on success
65 * E_NOINTERFACE if the requested interface wasn't found
66 *
67 *****************************************************************************/
68 static HRESULT WINAPI d3d_material3_QueryInterface(IDirect3DMaterial3 *iface, REFIID riid, void **obp)
69 {
70 struct d3d_material *material = impl_from_IDirect3DMaterial3(iface);
71
72 TRACE("iface %p, riid %s, object %p.\n", iface, debugstr_guid(riid), obp);
73
74 *obp = NULL;
75
76 if (IsEqualGUID(&IID_IUnknown, riid))
77 {
78 IDirect3DMaterial3_AddRef(iface);
79 *obp = iface;
80 TRACE(" Creating IUnknown interface at %p.\n", *obp);
81 return S_OK;
82 }
83 if (IsEqualGUID(&IID_IDirect3DMaterial, riid))
84 {
85 IDirect3DMaterial_AddRef(&material->IDirect3DMaterial_iface);
86 *obp = &material->IDirect3DMaterial_iface;
87 TRACE(" Creating IDirect3DMaterial interface %p\n", *obp);
88 return S_OK;
89 }
90 if (IsEqualGUID(&IID_IDirect3DMaterial2, riid))
91 {
92 IDirect3DMaterial2_AddRef(&material->IDirect3DMaterial2_iface);
93 *obp = &material->IDirect3DMaterial2_iface;
94 TRACE(" Creating IDirect3DMaterial2 interface %p\n", *obp);
95 return S_OK;
96 }
97 if (IsEqualGUID(&IID_IDirect3DMaterial3, riid))
98 {
99 IDirect3DMaterial3_AddRef(&material->IDirect3DMaterial3_iface);
100 *obp = &material->IDirect3DMaterial3_iface;
101 TRACE(" Creating IDirect3DMaterial3 interface %p\n", *obp);
102 return S_OK;
103 }
104
105 WARN("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(riid));
106
107 return E_NOINTERFACE;
108 }
109
110 /*****************************************************************************
111 * IDirect3DMaterial3::AddRef
112 *
113 * Increases the refcount.
114 *
115 * Returns:
116 * The new refcount
117 *
118 *****************************************************************************/
119 static ULONG WINAPI d3d_material3_AddRef(IDirect3DMaterial3 *iface)
120 {
121 struct d3d_material *material = impl_from_IDirect3DMaterial3(iface);
122 ULONG ref = InterlockedIncrement(&material->ref);
123
124 TRACE("%p increasing refcount to %u.\n", material, ref);
125
126 return ref;
127 }
128
129 /*****************************************************************************
130 * IDirect3DMaterial3::Release
131 *
132 * Reduces the refcount by one. If the refcount falls to 0, the object
133 * is destroyed
134 *
135 * Returns:
136 * The new refcount
137 *
138 *****************************************************************************/
139 static ULONG WINAPI d3d_material3_Release(IDirect3DMaterial3 *iface)
140 {
141 struct d3d_material *material = impl_from_IDirect3DMaterial3(iface);
142 ULONG ref = InterlockedDecrement(&material->ref);
143
144 TRACE("%p decreasing refcount to %u.\n", material, ref);
145
146 if (!ref)
147 {
148 if (material->Handle)
149 {
150 wined3d_mutex_lock();
151 ddraw_free_handle(&material->ddraw->d3ddevice->handle_table, material->Handle - 1, DDRAW_HANDLE_MATERIAL);
152 wined3d_mutex_unlock();
153 }
154
155 HeapFree(GetProcessHeap(), 0, material);
156 }
157
158 return ref;
159 }
160
161 /*****************************************************************************
162 * IDirect3DMaterial Methods
163 *****************************************************************************/
164
165 /*****************************************************************************
166 * IDirect3DMaterial::Initialize
167 *
168 * A no-op initialization
169 *
170 * Params:
171 * Direct3D: Pointer to a Direct3D interface
172 *
173 * Returns:
174 * D3D_OK
175 *
176 *****************************************************************************/
177 static HRESULT WINAPI d3d_material1_Initialize(IDirect3DMaterial *iface, IDirect3D *d3d)
178 {
179 TRACE("iface %p, d3d %p.\n", iface, d3d);
180
181 return D3D_OK;
182 }
183
184 /*****************************************************************************
185 * IDirect3DMaterial::Reserve
186 *
187 * DirectX 5 sdk: "The IDirect3DMaterial2::Reserve method is not implemented"
188 * Odd. They seem to have mixed their interfaces.
189 *
190 * Returns:
191 * DDERR_UNSUPPORTED
192 *
193 *****************************************************************************/
194 static HRESULT WINAPI d3d_material1_Reserve(IDirect3DMaterial *iface)
195 {
196 TRACE("iface %p.\n", iface);
197
198 return DDERR_UNSUPPORTED;
199 }
200
201 /*****************************************************************************
202 * IDirect3DMaterial::Unreserve
203 *
204 * Not supported too
205 *
206 * Returns:
207 * DDERR_UNSUPPORTED
208 *
209 *****************************************************************************/
210 static HRESULT WINAPI d3d_material1_Unreserve(IDirect3DMaterial *iface)
211 {
212 TRACE("iface %p.\n", iface);
213
214 return DDERR_UNSUPPORTED;
215 }
216
217 /*****************************************************************************
218 * IDirect3DMaterial3::SetMaterial
219 *
220 * Sets the material description
221 *
222 * Params:
223 * Mat: Material to set
224 *
225 * Returns:
226 * D3D_OK on success
227 * DDERR_INVALIDPARAMS if Mat is NULL
228 *
229 *****************************************************************************/
230 static HRESULT WINAPI d3d_material3_SetMaterial(IDirect3DMaterial3 *iface, D3DMATERIAL *mat)
231 {
232 struct d3d_material *material = impl_from_IDirect3DMaterial3(iface);
233
234 TRACE("iface %p, mat %p.\n", iface, mat);
235 if (TRACE_ON(ddraw))
236 dump_material(mat);
237
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();
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 d3d_material3_GetMaterial(IDirect3DMaterial3 *iface, D3DMATERIAL *mat)
261 {
262 struct d3d_material *material = impl_from_IDirect3DMaterial3(iface);
263 DWORD dwSize;
264
265 TRACE("iface %p, mat %p.\n", iface, mat);
266 if (TRACE_ON(ddraw))
267 {
268 TRACE(" Returning material : ");
269 dump_material(&material->mat);
270 }
271
272 /* Copies the material structure */
273 wined3d_mutex_lock();
274 dwSize = mat->dwSize;
275 memcpy(mat, &material->mat, dwSize);
276 wined3d_mutex_unlock();
277
278 return DD_OK;
279 }
280
281 /*****************************************************************************
282 * IDirect3DMaterial3::GetHandle
283 *
284 * Returns a handle for the material interface. The handle is simply a
285 * pointer to the material implementation
286 *
287 * Params:
288 * Direct3DDevice3: The device this handle is assigned to
289 * Handle: Address to write the handle to
290 *
291 * Returns:
292 * D3D_OK on success
293 * DDERR_INVALIDPARAMS if Handle is NULL
294 *
295 *****************************************************************************/
296 static HRESULT WINAPI d3d_material3_GetHandle(IDirect3DMaterial3 *iface,
297 IDirect3DDevice3 *device, D3DMATERIALHANDLE *handle)
298 {
299 struct d3d_material *material = impl_from_IDirect3DMaterial3(iface);
300 struct d3d_device *device_impl = unsafe_impl_from_IDirect3DDevice3(device);
301
302 TRACE("iface %p, device %p, handle %p.\n", iface, device, handle);
303
304 wined3d_mutex_lock();
305 material->active_device = device_impl;
306 if (!material->Handle)
307 {
308 DWORD h = ddraw_allocate_handle(&device_impl->handle_table, material, DDRAW_HANDLE_MATERIAL);
309 if (h == DDRAW_INVALID_HANDLE)
310 {
311 ERR("Failed to allocate a material handle.\n");
312 wined3d_mutex_unlock();
313 return DDERR_INVALIDPARAMS; /* Unchecked */
314 }
315
316 material->Handle = h + 1;
317 }
318 *handle = material->Handle;
319 TRACE(" returning handle %08x.\n", *handle);
320 wined3d_mutex_unlock();
321
322 return D3D_OK;
323 }
324
325 static HRESULT WINAPI d3d_material2_GetHandle(IDirect3DMaterial2 *iface,
326 IDirect3DDevice2 *device, D3DMATERIALHANDLE *handle)
327 {
328 struct d3d_material *material = impl_from_IDirect3DMaterial2(iface);
329 struct d3d_device *device_impl = unsafe_impl_from_IDirect3DDevice2(device);
330
331 TRACE("iface %p, device %p, handle %p.\n", iface, device, handle);
332
333 return d3d_material3_GetHandle(&material->IDirect3DMaterial3_iface,
334 device_impl ? &device_impl->IDirect3DDevice3_iface : NULL, handle);
335 }
336
337 static HRESULT WINAPI d3d_material1_GetHandle(IDirect3DMaterial *iface,
338 IDirect3DDevice *device, D3DMATERIALHANDLE *handle)
339 {
340 struct d3d_material *material = impl_from_IDirect3DMaterial(iface);
341 struct d3d_device *device_impl = unsafe_impl_from_IDirect3DDevice(device);
342
343 TRACE("iface %p, device %p, handle %p.\n", iface, device, handle);
344
345 return d3d_material3_GetHandle(&material->IDirect3DMaterial3_iface,
346 device_impl ? &device_impl->IDirect3DDevice3_iface : NULL, handle);
347 }
348
349 static HRESULT WINAPI d3d_material2_QueryInterface(IDirect3DMaterial2 *iface, REFIID riid, void **object)
350 {
351 struct d3d_material *material = impl_from_IDirect3DMaterial2(iface);
352
353 TRACE("iface %p, riid %s, object %p.\n", iface, debugstr_guid(riid), object);
354
355 return d3d_material3_QueryInterface(&material->IDirect3DMaterial3_iface, riid, object);
356 }
357
358 static HRESULT WINAPI d3d_material1_QueryInterface(IDirect3DMaterial *iface, REFIID riid, void **object)
359 {
360 struct d3d_material *material = impl_from_IDirect3DMaterial(iface);
361
362 TRACE("iface %p, riid %s, object %p.\n", iface, debugstr_guid(riid), object);
363
364 return d3d_material3_QueryInterface(&material->IDirect3DMaterial3_iface, riid, object);
365 }
366
367 static ULONG WINAPI d3d_material2_AddRef(IDirect3DMaterial2 *iface)
368 {
369 struct d3d_material *material = impl_from_IDirect3DMaterial2(iface);
370
371 TRACE("iface %p.\n", iface);
372
373 return d3d_material3_AddRef(&material->IDirect3DMaterial3_iface);
374 }
375
376 static ULONG WINAPI d3d_material1_AddRef(IDirect3DMaterial *iface)
377 {
378 struct d3d_material *material = impl_from_IDirect3DMaterial(iface);
379
380 TRACE("iface %p.\n", iface);
381
382 return d3d_material3_AddRef(&material->IDirect3DMaterial3_iface);
383 }
384
385 static ULONG WINAPI d3d_material2_Release(IDirect3DMaterial2 *iface)
386 {
387 struct d3d_material *material = impl_from_IDirect3DMaterial2(iface);
388
389 TRACE("iface %p.\n", iface);
390
391 return d3d_material3_Release(&material->IDirect3DMaterial3_iface);
392 }
393
394 static ULONG WINAPI d3d_material1_Release(IDirect3DMaterial *iface)
395 {
396 struct d3d_material *material = impl_from_IDirect3DMaterial(iface);
397
398 TRACE("iface %p.\n", iface);
399
400 return d3d_material3_Release(&material->IDirect3DMaterial3_iface);
401 }
402
403 static HRESULT WINAPI d3d_material2_SetMaterial(IDirect3DMaterial2 *iface, D3DMATERIAL *mat)
404 {
405 struct d3d_material *material = impl_from_IDirect3DMaterial2(iface);
406
407 TRACE("iface %p, material %p.\n", iface, mat);
408
409 return d3d_material3_SetMaterial(&material->IDirect3DMaterial3_iface, mat);
410 }
411
412 static HRESULT WINAPI d3d_material1_SetMaterial(IDirect3DMaterial *iface, D3DMATERIAL *mat)
413 {
414 struct d3d_material *material = impl_from_IDirect3DMaterial(iface);
415
416 TRACE("iface %p, material %p.\n", iface, mat);
417
418 return d3d_material3_SetMaterial(&material->IDirect3DMaterial3_iface, mat);
419 }
420
421 static HRESULT WINAPI d3d_material2_GetMaterial(IDirect3DMaterial2 *iface, D3DMATERIAL *mat)
422 {
423 struct d3d_material *material = impl_from_IDirect3DMaterial2(iface);
424
425 TRACE("iface %p, material %p.\n", iface, mat);
426
427 return d3d_material3_GetMaterial(&material->IDirect3DMaterial3_iface, mat);
428 }
429
430 static HRESULT WINAPI d3d_material1_GetMaterial(IDirect3DMaterial *iface, D3DMATERIAL *mat)
431 {
432 struct d3d_material *material = impl_from_IDirect3DMaterial(iface);
433
434 TRACE("iface %p, material %p.\n", iface, mat);
435
436 return d3d_material3_GetMaterial(&material->IDirect3DMaterial3_iface, mat);
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(struct d3d_material *material)
450 {
451 D3DMATERIAL7 d3d7mat;
452
453 TRACE("Activating material %p.\n", material);
454
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;
460
461 IDirect3DDevice7_SetMaterial(&material->active_device->IDirect3DDevice7_iface, &d3d7mat);
462 }
463
464 static const struct IDirect3DMaterial3Vtbl d3d_material3_vtbl =
465 {
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,
474 };
475
476 static const struct IDirect3DMaterial2Vtbl d3d_material2_vtbl =
477 {
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,
486 };
487
488 static const struct IDirect3DMaterialVtbl d3d_material1_vtbl =
489 {
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,
501 };
502
503 struct d3d_material *d3d_material_create(struct ddraw *ddraw)
504 {
505 struct d3d_material *material;
506
507 material = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*material));
508 if (!material)
509 return NULL;
510
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;
516
517 return material;
518 }