2 * Copyright (c) 2002 Lionel ULMER
3 * Copyright (c) 2006 Stefan DÖSINGER
5 * This file contains the implementation of Direct3DMaterial.
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.
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.
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
23 #include "wine/port.h"
25 #include "ddraw_private.h"
27 WINE_DEFAULT_DEBUG_CHANNEL(ddraw
);
29 static void dump_material(const D3DMATERIAL
*mat
)
31 TRACE(" dwSize : %d\n", mat
->dwSize
);
34 static inline struct d3d_material
*impl_from_IDirect3DMaterial(IDirect3DMaterial
*iface
)
36 return CONTAINING_RECORD(iface
, struct d3d_material
, IDirect3DMaterial_iface
);
39 static inline struct d3d_material
*impl_from_IDirect3DMaterial2(IDirect3DMaterial2
*iface
)
41 return CONTAINING_RECORD(iface
, struct d3d_material
, IDirect3DMaterial2_iface
);
44 static inline struct d3d_material
*impl_from_IDirect3DMaterial3(IDirect3DMaterial3
*iface
)
46 return CONTAINING_RECORD(iface
, struct d3d_material
, IDirect3DMaterial3_iface
);
49 /*****************************************************************************
51 *****************************************************************************/
53 /*****************************************************************************
54 * IDirect3DMaterial3::QueryInterface
56 * QueryInterface for IDirect3DMaterial. Can query all IDirect3DMaterial
60 * riid: Interface id queried for
61 * obj: Address to pass the interface pointer back
65 * E_NOINTERFACE if the requested interface wasn't found
67 *****************************************************************************/
68 static HRESULT WINAPI
d3d_material3_QueryInterface(IDirect3DMaterial3
*iface
, REFIID riid
, void **obp
)
70 struct d3d_material
*material
= impl_from_IDirect3DMaterial3(iface
);
72 TRACE("iface %p, riid %s, object %p.\n", iface
, debugstr_guid(riid
), obp
);
76 if (IsEqualGUID(&IID_IUnknown
, riid
))
78 IUnknown_AddRef(iface
);
80 TRACE(" Creating IUnknown interface at %p.\n", *obp
);
83 if (IsEqualGUID(&IID_IDirect3DMaterial
, riid
))
85 IDirect3DMaterial_AddRef(&material
->IDirect3DMaterial_iface
);
86 *obp
= &material
->IDirect3DMaterial_iface
;
87 TRACE(" Creating IDirect3DMaterial interface %p\n", *obp
);
90 if (IsEqualGUID(&IID_IDirect3DMaterial2
, riid
))
92 IDirect3DMaterial2_AddRef(&material
->IDirect3DMaterial2_iface
);
93 *obp
= &material
->IDirect3DMaterial2_iface
;
94 TRACE(" Creating IDirect3DMaterial2 interface %p\n", *obp
);
97 if (IsEqualGUID(&IID_IDirect3DMaterial3
, riid
))
99 IDirect3DMaterial3_AddRef(&material
->IDirect3DMaterial3_iface
);
100 *obp
= &material
->IDirect3DMaterial3_iface
;
101 TRACE(" Creating IDirect3DMaterial3 interface %p\n", *obp
);
105 WARN("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(riid
));
107 return E_NOINTERFACE
;
110 /*****************************************************************************
111 * IDirect3DMaterial3::AddRef
113 * Increases the refcount.
118 *****************************************************************************/
119 static ULONG WINAPI
d3d_material3_AddRef(IDirect3DMaterial3
*iface
)
121 struct d3d_material
*material
= impl_from_IDirect3DMaterial3(iface
);
122 ULONG ref
= InterlockedIncrement(&material
->ref
);
124 TRACE("%p increasing refcount to %u.\n", material
, ref
);
129 /*****************************************************************************
130 * IDirect3DMaterial3::Release
132 * Reduces the refcount by one. If the refcount falls to 0, the object
138 *****************************************************************************/
139 static ULONG WINAPI
d3d_material3_Release(IDirect3DMaterial3
*iface
)
141 struct d3d_material
*material
= impl_from_IDirect3DMaterial3(iface
);
142 ULONG ref
= InterlockedDecrement(&material
->ref
);
144 TRACE("%p decreasing refcount to %u.\n", material
, ref
);
148 if (material
->Handle
)
150 wined3d_mutex_lock();
151 ddraw_free_handle(&material
->ddraw
->d3ddevice
->handle_table
, material
->Handle
- 1, DDRAW_HANDLE_MATERIAL
);
152 wined3d_mutex_unlock();
155 HeapFree(GetProcessHeap(), 0, material
);
161 /*****************************************************************************
162 * IDirect3DMaterial Methods
163 *****************************************************************************/
165 /*****************************************************************************
166 * IDirect3DMaterial::Initialize
168 * A no-op initialization
171 * Direct3D: Pointer to a Direct3D interface
176 *****************************************************************************/
177 static HRESULT WINAPI
d3d_material1_Initialize(IDirect3DMaterial
*iface
, IDirect3D
*d3d
)
179 TRACE("iface %p, d3d %p.\n", iface
, d3d
);
184 /*****************************************************************************
185 * IDirect3DMaterial::Reserve
187 * DirectX 5 sdk: "The IDirect3DMaterial2::Reserve method is not implemented"
188 * Odd. They seem to have mixed their interfaces.
193 *****************************************************************************/
194 static HRESULT WINAPI
d3d_material1_Reserve(IDirect3DMaterial
*iface
)
196 TRACE("iface %p.\n", iface
);
198 return DDERR_UNSUPPORTED
;
201 /*****************************************************************************
202 * IDirect3DMaterial::Unreserve
209 *****************************************************************************/
210 static HRESULT WINAPI
d3d_material1_Unreserve(IDirect3DMaterial
*iface
)
212 TRACE("iface %p.\n", iface
);
214 return DDERR_UNSUPPORTED
;
217 /*****************************************************************************
218 * IDirect3DMaterial3::SetMaterial
220 * Sets the material description
223 * Mat: Material to set
227 * DDERR_INVALIDPARAMS if Mat is NULL
229 *****************************************************************************/
230 static HRESULT WINAPI
d3d_material3_SetMaterial(IDirect3DMaterial3
*iface
, D3DMATERIAL
*mat
)
232 struct d3d_material
*material
= impl_from_IDirect3DMaterial3(iface
);
234 TRACE("iface %p, mat %p.\n", iface
, mat
);
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();
247 /*****************************************************************************
248 * IDirect3DMaterial3::GetMaterial
250 * Returns the material assigned to this interface
253 * Mat: Pointer to a D3DMATERIAL structure to store the material description
257 * DDERR_INVALIDPARAMS if Mat is NULL
259 *****************************************************************************/
260 static HRESULT WINAPI
d3d_material3_GetMaterial(IDirect3DMaterial3
*iface
, D3DMATERIAL
*mat
)
262 struct d3d_material
*material
= impl_from_IDirect3DMaterial3(iface
);
265 TRACE("iface %p, mat %p.\n", iface
, mat
);
268 TRACE(" Returning material : ");
269 dump_material(&material
->mat
);
272 /* Copies the material structure */
273 wined3d_mutex_lock();
274 dwSize
= mat
->dwSize
;
275 memcpy(mat
, &material
->mat
, dwSize
);
276 wined3d_mutex_unlock();
281 /*****************************************************************************
282 * IDirect3DMaterial3::GetHandle
284 * Returns a handle for the material interface. The handle is simply a
285 * pointer to the material implementation
288 * Direct3DDevice3: The device this handle is assigned to
289 * Handle: Address to write the handle to
293 * DDERR_INVALIDPARAMS if Handle is NULL
295 *****************************************************************************/
296 static HRESULT WINAPI
d3d_material3_GetHandle(IDirect3DMaterial3
*iface
,
297 IDirect3DDevice3
*device
, D3DMATERIALHANDLE
*handle
)
299 struct d3d_material
*material
= impl_from_IDirect3DMaterial3(iface
);
300 struct d3d_device
*device_impl
= unsafe_impl_from_IDirect3DDevice3(device
);
302 TRACE("iface %p, device %p, handle %p.\n", iface
, device
, handle
);
304 wined3d_mutex_lock();
305 material
->active_device
= device_impl
;
306 if (!material
->Handle
)
308 DWORD h
= ddraw_allocate_handle(&device_impl
->handle_table
, material
, DDRAW_HANDLE_MATERIAL
);
309 if (h
== DDRAW_INVALID_HANDLE
)
311 ERR("Failed to allocate a material handle.\n");
312 wined3d_mutex_unlock();
313 return DDERR_INVALIDPARAMS
; /* Unchecked */
316 material
->Handle
= h
+ 1;
318 *handle
= material
->Handle
;
319 TRACE(" returning handle %08x.\n", *handle
);
320 wined3d_mutex_unlock();
325 static HRESULT WINAPI
d3d_material2_GetHandle(IDirect3DMaterial2
*iface
,
326 IDirect3DDevice2
*device
, D3DMATERIALHANDLE
*handle
)
328 struct d3d_material
*material
= impl_from_IDirect3DMaterial2(iface
);
329 struct d3d_device
*device_impl
= unsafe_impl_from_IDirect3DDevice2(device
);
331 TRACE("iface %p, device %p, handle %p.\n", iface
, device
, handle
);
333 return d3d_material3_GetHandle(&material
->IDirect3DMaterial3_iface
,
334 device_impl
? &device_impl
->IDirect3DDevice3_iface
: NULL
, handle
);
337 static HRESULT WINAPI
d3d_material1_GetHandle(IDirect3DMaterial
*iface
,
338 IDirect3DDevice
*device
, D3DMATERIALHANDLE
*handle
)
340 struct d3d_material
*material
= impl_from_IDirect3DMaterial(iface
);
341 struct d3d_device
*device_impl
= unsafe_impl_from_IDirect3DDevice(device
);
343 TRACE("iface %p, device %p, handle %p.\n", iface
, device
, handle
);
345 return d3d_material3_GetHandle(&material
->IDirect3DMaterial3_iface
,
346 device_impl
? &device_impl
->IDirect3DDevice3_iface
: NULL
, handle
);
349 static HRESULT WINAPI
d3d_material2_QueryInterface(IDirect3DMaterial2
*iface
, REFIID riid
, void **object
)
351 struct d3d_material
*material
= impl_from_IDirect3DMaterial2(iface
);
353 TRACE("iface %p, riid %s, object %p.\n", iface
, debugstr_guid(riid
), object
);
355 return d3d_material3_QueryInterface(&material
->IDirect3DMaterial3_iface
, riid
, object
);
358 static HRESULT WINAPI
d3d_material1_QueryInterface(IDirect3DMaterial
*iface
, REFIID riid
, void **object
)
360 struct d3d_material
*material
= impl_from_IDirect3DMaterial(iface
);
362 TRACE("iface %p, riid %s, object %p.\n", iface
, debugstr_guid(riid
), object
);
364 return d3d_material3_QueryInterface(&material
->IDirect3DMaterial3_iface
, riid
, object
);
367 static ULONG WINAPI
d3d_material2_AddRef(IDirect3DMaterial2
*iface
)
369 struct d3d_material
*material
= impl_from_IDirect3DMaterial2(iface
);
371 TRACE("iface %p.\n", iface
);
373 return d3d_material3_AddRef(&material
->IDirect3DMaterial3_iface
);
376 static ULONG WINAPI
d3d_material1_AddRef(IDirect3DMaterial
*iface
)
378 struct d3d_material
*material
= impl_from_IDirect3DMaterial(iface
);
380 TRACE("iface %p.\n", iface
);
382 return d3d_material3_AddRef(&material
->IDirect3DMaterial3_iface
);
385 static ULONG WINAPI
d3d_material2_Release(IDirect3DMaterial2
*iface
)
387 struct d3d_material
*material
= impl_from_IDirect3DMaterial2(iface
);
389 TRACE("iface %p.\n", iface
);
391 return d3d_material3_Release(&material
->IDirect3DMaterial3_iface
);
394 static ULONG WINAPI
d3d_material1_Release(IDirect3DMaterial
*iface
)
396 struct d3d_material
*material
= impl_from_IDirect3DMaterial(iface
);
398 TRACE("iface %p.\n", iface
);
400 return d3d_material3_Release(&material
->IDirect3DMaterial3_iface
);
403 static HRESULT WINAPI
d3d_material2_SetMaterial(IDirect3DMaterial2
*iface
, D3DMATERIAL
*mat
)
405 struct d3d_material
*material
= impl_from_IDirect3DMaterial2(iface
);
407 TRACE("iface %p, material %p.\n", iface
, mat
);
409 return d3d_material3_SetMaterial(&material
->IDirect3DMaterial3_iface
, mat
);
412 static HRESULT WINAPI
d3d_material1_SetMaterial(IDirect3DMaterial
*iface
, D3DMATERIAL
*mat
)
414 struct d3d_material
*material
= impl_from_IDirect3DMaterial(iface
);
416 TRACE("iface %p, material %p.\n", iface
, mat
);
418 return d3d_material3_SetMaterial(&material
->IDirect3DMaterial3_iface
, mat
);
421 static HRESULT WINAPI
d3d_material2_GetMaterial(IDirect3DMaterial2
*iface
, D3DMATERIAL
*mat
)
423 struct d3d_material
*material
= impl_from_IDirect3DMaterial2(iface
);
425 TRACE("iface %p, material %p.\n", iface
, mat
);
427 return d3d_material3_GetMaterial(&material
->IDirect3DMaterial3_iface
, mat
);
430 static HRESULT WINAPI
d3d_material1_GetMaterial(IDirect3DMaterial
*iface
, D3DMATERIAL
*mat
)
432 struct d3d_material
*material
= impl_from_IDirect3DMaterial(iface
);
434 TRACE("iface %p, material %p.\n", iface
, mat
);
436 return d3d_material3_GetMaterial(&material
->IDirect3DMaterial3_iface
, mat
);
440 /*****************************************************************************
443 * Uses IDirect3DDevice7::SetMaterial to activate the material
446 * This: Pointer to the material implementation to activate
448 *****************************************************************************/
449 void material_activate(struct d3d_material
*material
)
451 D3DMATERIAL7 d3d7mat
;
453 TRACE("Activating material %p.\n", material
);
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
;
461 IDirect3DDevice7_SetMaterial(&material
->active_device
->IDirect3DDevice7_iface
, &d3d7mat
);
464 static const struct IDirect3DMaterial3Vtbl d3d_material3_vtbl
=
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
,
476 static const struct IDirect3DMaterial2Vtbl d3d_material2_vtbl
=
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
,
488 static const struct IDirect3DMaterialVtbl d3d_material1_vtbl
=
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
,
503 struct d3d_material
*d3d_material_create(struct ddraw
*ddraw
)
505 struct d3d_material
*material
;
507 material
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(*material
));
511 material
->IDirect3DMaterial3_iface
.lpVtbl
= &d3d_material3_vtbl
;
512 material
->IDirect3DMaterial2_iface
.lpVtbl
= &d3d_material2_vtbl
;
513 material
->IDirect3DMaterial_iface
.lpVtbl
= &d3d_material1_vtbl
;
515 material
->ddraw
= ddraw
;