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 27 static void dump_material(const D3DMATERIAL *mat) 28 { 29 TRACE(" dwSize : %d\n", mat->dwSize); 30 } 31 32 static inline struct d3d_material *impl_from_IDirect3DMaterial(IDirect3DMaterial *iface) 33 { 34 return CONTAINING_RECORD(iface, struct d3d_material, IDirect3DMaterial_iface); 35 } 36 37 static inline struct d3d_material *impl_from_IDirect3DMaterial2(IDirect3DMaterial2 *iface) 38 { 39 return CONTAINING_RECORD(iface, struct d3d_material, IDirect3DMaterial2_iface); 40 } 41 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 *****************************************************************************/ 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 *****************************************************************************/ 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 *****************************************************************************/ 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 *****************************************************************************/ 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 *****************************************************************************/ 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 *****************************************************************************/ 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 *****************************************************************************/ 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 *****************************************************************************/ 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 *****************************************************************************/ 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 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 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 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 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 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 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 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 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 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 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 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 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 *****************************************************************************/ 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 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