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