1 /* 2 * Copyright (c) 1998-2004 Lionel Ulmer 3 * Copyright (c) 2002-2005 Christian Costa 4 * Copyright (c) 2006-2009, 2011-2013 Stefan Dösinger 5 * Copyright (c) 2008 Alexander Dorofeyev 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 * IDirect3DDevice implementation, version 1, 2, 3 and 7. Rendering is relayed 22 * to WineD3D, some minimal DirectDraw specific management is handled here. 23 * The Direct3DDevice is NOT the parent of the WineD3DDevice, because d3d 24 * is initialized when DirectDraw creates the primary surface. 25 * Some type management is necessary, because some D3D types changed between 26 * D3D7 and D3D9. 27 * 28 */ 29 30 #include "config.h" 31 #include "wine/port.h" 32 33 #include "ddraw_private.h" 34 35 WINE_DEFAULT_DEBUG_CHANNEL(ddraw); 36 WINE_DECLARE_DEBUG_CHANNEL(winediag); 37 38 /* The device ID */ 39 const GUID IID_D3DDEVICE_WineD3D = { 40 0xaef72d43, 41 0xb09a, 42 0x4b7b, 43 { 0xb7,0x98,0xc6,0x8a,0x77,0x2d,0x72,0x2a } 44 }; 45 46 static inline void set_fpu_control_word(WORD fpucw) 47 { 48 #if defined(__i386__) && defined(__GNUC__) 49 __asm__ volatile ("fldcw %0" : : "m" (fpucw)); 50 #elif defined(__i386__) && defined(_MSC_VER) 51 __asm fldcw fpucw; 52 #endif 53 } 54 55 static inline WORD d3d_fpu_setup(void) 56 { 57 WORD oldcw; 58 59 #if defined(__i386__) && defined(__GNUC__) 60 __asm__ volatile ("fnstcw %0" : "=m" (oldcw)); 61 #elif defined(__i386__) && defined(_MSC_VER) 62 __asm fnstcw oldcw; 63 #else 64 static BOOL warned = FALSE; 65 if(!warned) 66 { 67 FIXME("FPUPRESERVE not implemented for this platform / compiler\n"); 68 warned = TRUE; 69 } 70 return 0; 71 #endif 72 73 set_fpu_control_word(0x37f); 74 75 return oldcw; 76 } 77 78 static inline struct d3d_device *impl_from_IUnknown(IUnknown *iface) 79 { 80 return CONTAINING_RECORD(iface, struct d3d_device, IUnknown_inner); 81 } 82 83 static HRESULT WINAPI d3d_device_inner_QueryInterface(IUnknown *iface, REFIID riid, void **out) 84 { 85 struct d3d_device *device = impl_from_IUnknown(iface); 86 87 TRACE("iface %p, riid %s, out %p.\n", iface, debugstr_guid(riid), out); 88 89 if (!riid) 90 { 91 *out = NULL; 92 return DDERR_INVALIDPARAMS; 93 } 94 95 if (IsEqualGUID(&IID_IUnknown, riid)) 96 { 97 IDirect3DDevice7_AddRef(&device->IDirect3DDevice7_iface); 98 *out = &device->IDirect3DDevice7_iface; 99 return S_OK; 100 } 101 102 if (device->version == 7) 103 { 104 if (IsEqualGUID(&IID_IDirect3DDevice7, riid)) 105 { 106 IDirect3DDevice7_AddRef(&device->IDirect3DDevice7_iface); 107 *out = &device->IDirect3DDevice7_iface; 108 return S_OK; 109 } 110 } 111 else 112 { 113 if (IsEqualGUID(&IID_IDirect3DDevice3, riid) && device->version == 3) 114 { 115 IDirect3DDevice3_AddRef(&device->IDirect3DDevice3_iface); 116 *out = &device->IDirect3DDevice3_iface; 117 return S_OK; 118 } 119 120 if (IsEqualGUID(&IID_IDirect3DDevice2, riid) && device->version >= 2) 121 { 122 IDirect3DDevice2_AddRef(&device->IDirect3DDevice2_iface); 123 *out = &device->IDirect3DDevice2_iface; 124 return S_OK; 125 } 126 127 if (IsEqualGUID(&IID_IDirect3DDevice, riid)) 128 { 129 IDirect3DDevice_AddRef(&device->IDirect3DDevice_iface); 130 *out = &device->IDirect3DDevice_iface; 131 return S_OK; 132 } 133 } 134 135 WARN("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(riid)); 136 137 *out = NULL; 138 return E_NOINTERFACE; 139 } 140 141 static HRESULT WINAPI d3d_device7_QueryInterface(IDirect3DDevice7 *iface, REFIID riid, void **out) 142 { 143 struct d3d_device *device = impl_from_IDirect3DDevice7(iface); 144 145 TRACE("iface %p, riid %s, out %p.\n", iface, debugstr_guid(riid), out); 146 147 return IUnknown_QueryInterface(device->outer_unknown, riid, out); 148 } 149 150 static HRESULT WINAPI d3d_device3_QueryInterface(IDirect3DDevice3 *iface, REFIID riid, void **out) 151 { 152 struct d3d_device *device = impl_from_IDirect3DDevice3(iface); 153 154 TRACE("iface %p, riid %s, out %p.\n", iface, debugstr_guid(riid), out); 155 156 return IUnknown_QueryInterface(device->outer_unknown, riid, out); 157 } 158 159 static HRESULT WINAPI d3d_device2_QueryInterface(IDirect3DDevice2 *iface, REFIID riid, void **out) 160 { 161 struct d3d_device *device = impl_from_IDirect3DDevice2(iface); 162 163 TRACE("iface %p, riid %s, out %p.\n", iface, debugstr_guid(riid), out); 164 165 return IUnknown_QueryInterface(device->outer_unknown, riid, out); 166 } 167 168 static HRESULT WINAPI d3d_device1_QueryInterface(IDirect3DDevice *iface, REFIID riid, void **out) 169 { 170 struct d3d_device *device = impl_from_IDirect3DDevice(iface); 171 172 TRACE("iface %p, riid %s, out %p.\n", iface, debugstr_guid(riid), out); 173 174 return IUnknown_QueryInterface(device->outer_unknown, riid, out); 175 } 176 177 static ULONG WINAPI d3d_device_inner_AddRef(IUnknown *iface) 178 { 179 struct d3d_device *device = impl_from_IUnknown(iface); 180 ULONG ref = InterlockedIncrement(&device->ref); 181 182 TRACE("%p increasing refcount to %u.\n", device, ref); 183 184 return ref; 185 } 186 187 static ULONG WINAPI d3d_device7_AddRef(IDirect3DDevice7 *iface) 188 { 189 struct d3d_device *device = impl_from_IDirect3DDevice7(iface); 190 191 TRACE("iface %p.\n", iface); 192 193 return IUnknown_AddRef(device->outer_unknown); 194 } 195 196 static ULONG WINAPI d3d_device3_AddRef(IDirect3DDevice3 *iface) 197 { 198 struct d3d_device *device = impl_from_IDirect3DDevice3(iface); 199 200 TRACE("iface %p.\n", iface); 201 202 return IUnknown_AddRef(device->outer_unknown); 203 } 204 205 static ULONG WINAPI d3d_device2_AddRef(IDirect3DDevice2 *iface) 206 { 207 struct d3d_device *device = impl_from_IDirect3DDevice2(iface); 208 209 TRACE("iface %p.\n", iface); 210 211 return IUnknown_AddRef(device->outer_unknown); 212 } 213 214 static ULONG WINAPI d3d_device1_AddRef(IDirect3DDevice *iface) 215 { 216 struct d3d_device *device = impl_from_IDirect3DDevice(iface); 217 218 TRACE("iface %p.\n", iface); 219 220 return IUnknown_AddRef(device->outer_unknown); 221 } 222 223 static ULONG WINAPI d3d_device_inner_Release(IUnknown *iface) 224 { 225 struct d3d_device *This = impl_from_IUnknown(iface); 226 ULONG ref = InterlockedDecrement(&This->ref); 227 IUnknown *rt_iface; 228 229 TRACE("%p decreasing refcount to %u.\n", This, ref); 230 231 /* This method doesn't destroy the wined3d device, because it's still in 232 * use for 2D rendering. IDirectDrawSurface7::Release will destroy the 233 * wined3d device when the render target is released. */ 234 if (!ref) 235 { 236 DWORD i; 237 struct list *vp_entry, *vp_entry2; 238 239 wined3d_mutex_lock(); 240 241 /* There is no need to unset any resources here, wined3d will take 242 * care of that on uninit_3d(). */ 243 244 if (This->index_buffer) 245 wined3d_buffer_decref(This->index_buffer); 246 if (This->vertex_buffer) 247 wined3d_buffer_decref(This->vertex_buffer); 248 249 wined3d_device_set_rendertarget_view(This->wined3d_device, 0, NULL, FALSE); 250 251 /* Release the wined3d device. This won't destroy it. */ 252 if (!wined3d_device_decref(This->wined3d_device)) 253 ERR("The wined3d device (%p) was destroyed unexpectedly.\n", This->wined3d_device); 254 255 /* The texture handles should be unset by now, but there might be some bits 256 * missing in our reference counting(needs test). Do a sanity check. */ 257 for (i = 0; i < This->handle_table.entry_count; ++i) 258 { 259 struct ddraw_handle_entry *entry = &This->handle_table.entries[i]; 260 261 switch (entry->type) 262 { 263 case DDRAW_HANDLE_FREE: 264 break; 265 266 case DDRAW_HANDLE_MATERIAL: 267 { 268 struct d3d_material *m = entry->object; 269 FIXME("Material handle %#x (%p) not unset properly.\n", i + 1, m); 270 m->Handle = 0; 271 break; 272 } 273 274 case DDRAW_HANDLE_MATRIX: 275 { 276 /* No FIXME here because this might happen because of sloppy applications. */ 277 WARN("Leftover matrix handle %#x (%p), deleting.\n", i + 1, entry->object); 278 IDirect3DDevice_DeleteMatrix(&This->IDirect3DDevice_iface, i + 1); 279 break; 280 } 281 282 case DDRAW_HANDLE_STATEBLOCK: 283 { 284 /* No FIXME here because this might happen because of sloppy applications. */ 285 WARN("Leftover stateblock handle %#x (%p), deleting.\n", i + 1, entry->object); 286 IDirect3DDevice7_DeleteStateBlock(&This->IDirect3DDevice7_iface, i + 1); 287 break; 288 } 289 290 case DDRAW_HANDLE_SURFACE: 291 { 292 struct ddraw_surface *surf = entry->object; 293 FIXME("Texture handle %#x (%p) not unset properly.\n", i + 1, surf); 294 surf->Handle = 0; 295 break; 296 } 297 298 default: 299 FIXME("Handle %#x (%p) has unknown type %#x.\n", i + 1, entry->object, entry->type); 300 break; 301 } 302 } 303 304 ddraw_handle_table_destroy(&This->handle_table); 305 306 LIST_FOR_EACH_SAFE(vp_entry, vp_entry2, &This->viewport_list) 307 { 308 struct d3d_viewport *vp = LIST_ENTRY(vp_entry, struct d3d_viewport, entry); 309 IDirect3DDevice3_DeleteViewport(&This->IDirect3DDevice3_iface, &vp->IDirect3DViewport3_iface); 310 } 311 312 TRACE("Releasing render target %p.\n", This->rt_iface); 313 rt_iface = This->rt_iface; 314 This->rt_iface = NULL; 315 if (This->version != 1) 316 IUnknown_Release(rt_iface); 317 TRACE("Render target release done.\n"); 318 319 /* Releasing the render target above may have released the last 320 * reference to the ddraw object. */ 321 if (This->ddraw) 322 This->ddraw->d3ddevice = NULL; 323 324 /* Now free the structure */ 325 heap_free(This); 326 wined3d_mutex_unlock(); 327 } 328 329 TRACE("Done\n"); 330 return ref; 331 } 332 333 static ULONG WINAPI d3d_device7_Release(IDirect3DDevice7 *iface) 334 { 335 struct d3d_device *device = impl_from_IDirect3DDevice7(iface); 336 337 TRACE("iface %p.\n", iface); 338 339 return IUnknown_Release(device->outer_unknown); 340 } 341 342 static ULONG WINAPI d3d_device3_Release(IDirect3DDevice3 *iface) 343 { 344 struct d3d_device *device = impl_from_IDirect3DDevice3(iface); 345 346 TRACE("iface %p.\n", iface); 347 348 return IUnknown_Release(device->outer_unknown); 349 } 350 351 static ULONG WINAPI d3d_device2_Release(IDirect3DDevice2 *iface) 352 { 353 struct d3d_device *device = impl_from_IDirect3DDevice2(iface); 354 355 TRACE("iface %p.\n", iface); 356 357 return IUnknown_Release(device->outer_unknown); 358 } 359 360 static ULONG WINAPI d3d_device1_Release(IDirect3DDevice *iface) 361 { 362 struct d3d_device *device = impl_from_IDirect3DDevice(iface); 363 364 TRACE("iface %p.\n", iface); 365 366 return IUnknown_Release(device->outer_unknown); 367 } 368 369 /***************************************************************************** 370 * IDirect3DDevice Methods 371 *****************************************************************************/ 372 373 /***************************************************************************** 374 * IDirect3DDevice::Initialize 375 * 376 * Initializes a Direct3DDevice. This implementation is a no-op, as all 377 * initialization is done at create time. 378 * 379 * Exists in Version 1 380 * 381 * Parameters: 382 * No idea what they mean, as the MSDN page is gone 383 * 384 * Returns: DD_OK 385 * 386 *****************************************************************************/ 387 static HRESULT WINAPI d3d_device1_Initialize(IDirect3DDevice *iface, 388 IDirect3D *d3d, GUID *guid, D3DDEVICEDESC *device_desc) 389 { 390 /* It shouldn't be crucial, but print a FIXME, I'm interested if 391 * any game calls it and when. */ 392 FIXME("iface %p, d3d %p, guid %s, device_desc %p nop!\n", 393 iface, d3d, debugstr_guid(guid), device_desc); 394 395 return D3D_OK; 396 } 397 398 static HRESULT d3d_device7_GetCaps(IDirect3DDevice7 *iface, D3DDEVICEDESC7 *device_desc) 399 { 400 struct d3d_device *device = impl_from_IDirect3DDevice7(iface); 401 402 TRACE("iface %p, device_desc %p.\n", iface, device_desc); 403 404 if (!device_desc) 405 { 406 WARN("device_desc is NULL, returning DDERR_INVALIDPARAMS.\n"); 407 return DDERR_INVALIDPARAMS; 408 } 409 410 /* Call the same function used by IDirect3D, this saves code */ 411 return ddraw_get_d3dcaps(device->ddraw, device_desc); 412 } 413 414 static HRESULT WINAPI d3d_device7_GetCaps_FPUSetup(IDirect3DDevice7 *iface, D3DDEVICEDESC7 *desc) 415 { 416 return d3d_device7_GetCaps(iface, desc); 417 } 418 419 static HRESULT WINAPI d3d_device7_GetCaps_FPUPreserve(IDirect3DDevice7 *iface, D3DDEVICEDESC7 *desc) 420 { 421 HRESULT hr; 422 WORD old_fpucw; 423 424 old_fpucw = d3d_fpu_setup(); 425 hr = d3d_device7_GetCaps(iface, desc); 426 set_fpu_control_word(old_fpucw); 427 428 return hr; 429 } 430 /***************************************************************************** 431 * IDirect3DDevice3::GetCaps 432 * 433 * Retrieves the capabilities of the hardware device and the emulation 434 * device. For Wine, hardware and emulation are the same (it's all HW). 435 * 436 * This implementation is used for Version 1, 2, and 3. Version 7 has its own 437 * 438 * Parameters: 439 * HWDesc: Structure to fill with the HW caps 440 * HelDesc: Structure to fill with the hardware emulation caps 441 * 442 * Returns: 443 * D3D_OK on success 444 * D3DERR_* if a problem occurs. See WineD3D 445 * 446 *****************************************************************************/ 447 448 /* There are 3 versions of D3DDEVICEDESC. All 3 share the same name because 449 * Microsoft just expanded the existing structure without naming them 450 * D3DDEVICEDESC2 and D3DDEVICEDESC3. Which version is used have depends 451 * on the version of the DirectX SDK. DirectX 6+ and Wine use the latest 452 * one with 252 bytes. 453 * 454 * All 3 versions are allowed as parameters and only the specified amount of 455 * bytes is written. 456 * 457 * Note that Direct3D7 and earlier are not available in native Win64 458 * ddraw.dll builds, so possible size differences between 32 bit and 459 * 64 bit are a non-issue. 460 */ 461 static inline BOOL check_d3ddevicedesc_size(DWORD size) 462 { 463 if (size == FIELD_OFFSET(D3DDEVICEDESC, dwMinTextureWidth) /* 172 */ 464 || size == FIELD_OFFSET(D3DDEVICEDESC, dwMaxTextureRepeat) /* 204 */ 465 || size == sizeof(D3DDEVICEDESC) /* 252 */) return TRUE; 466 return FALSE; 467 } 468 469 static HRESULT WINAPI d3d_device3_GetCaps(IDirect3DDevice3 *iface, 470 D3DDEVICEDESC *HWDesc, D3DDEVICEDESC *HelDesc) 471 { 472 struct d3d_device *device = impl_from_IDirect3DDevice3(iface); 473 D3DDEVICEDESC7 desc7; 474 D3DDEVICEDESC desc1; 475 HRESULT hr; 476 477 TRACE("iface %p, hw_desc %p, hel_desc %p.\n", iface, HWDesc, HelDesc); 478 479 if (!HWDesc) 480 { 481 WARN("HWDesc is NULL, returning DDERR_INVALIDPARAMS.\n"); 482 return DDERR_INVALIDPARAMS; 483 } 484 if (!check_d3ddevicedesc_size(HWDesc->dwSize)) 485 { 486 WARN("HWDesc->dwSize is %u, returning DDERR_INVALIDPARAMS.\n", HWDesc->dwSize); 487 return DDERR_INVALIDPARAMS; 488 } 489 if (!HelDesc) 490 { 491 WARN("HelDesc is NULL, returning DDERR_INVALIDPARAMS.\n"); 492 return DDERR_INVALIDPARAMS; 493 } 494 if (!check_d3ddevicedesc_size(HelDesc->dwSize)) 495 { 496 WARN("HelDesc->dwSize is %u, returning DDERR_INVALIDPARAMS.\n", HelDesc->dwSize); 497 return DDERR_INVALIDPARAMS; 498 } 499 500 if (FAILED(hr = ddraw_get_d3dcaps(device->ddraw, &desc7))) 501 return hr; 502 503 ddraw_d3dcaps1_from_7(&desc1, &desc7); 504 DD_STRUCT_COPY_BYSIZE(HWDesc, &desc1); 505 DD_STRUCT_COPY_BYSIZE(HelDesc, &desc1); 506 return D3D_OK; 507 } 508 509 static HRESULT WINAPI d3d_device2_GetCaps(IDirect3DDevice2 *iface, 510 D3DDEVICEDESC *hw_desc, D3DDEVICEDESC *hel_desc) 511 { 512 struct d3d_device *device = impl_from_IDirect3DDevice2(iface); 513 514 TRACE("iface %p, hw_desc %p, hel_desc %p.\n", iface, hw_desc, hel_desc); 515 516 return d3d_device3_GetCaps(&device->IDirect3DDevice3_iface, hw_desc, hel_desc); 517 } 518 519 static HRESULT WINAPI d3d_device1_GetCaps(IDirect3DDevice *iface, 520 D3DDEVICEDESC *hw_desc, D3DDEVICEDESC *hel_desc) 521 { 522 struct d3d_device *device = impl_from_IDirect3DDevice(iface); 523 524 TRACE("iface %p, hw_desc %p, hel_desc %p.\n", iface, hw_desc, hel_desc); 525 526 return d3d_device3_GetCaps(&device->IDirect3DDevice3_iface, hw_desc, hel_desc); 527 } 528 529 /***************************************************************************** 530 * IDirect3DDevice2::SwapTextureHandles 531 * 532 * Swaps the texture handles of 2 Texture interfaces. Version 1 and 2 533 * 534 * Parameters: 535 * Tex1, Tex2: The 2 Textures to swap 536 * 537 * Returns: 538 * D3D_OK 539 * 540 *****************************************************************************/ 541 static HRESULT WINAPI d3d_device2_SwapTextureHandles(IDirect3DDevice2 *iface, 542 IDirect3DTexture2 *tex1, IDirect3DTexture2 *tex2) 543 { 544 struct d3d_device *device = impl_from_IDirect3DDevice2(iface); 545 struct ddraw_surface *surf1 = unsafe_impl_from_IDirect3DTexture2(tex1); 546 struct ddraw_surface *surf2 = unsafe_impl_from_IDirect3DTexture2(tex2); 547 DWORD h1, h2; 548 549 TRACE("iface %p, tex1 %p, tex2 %p.\n", iface, tex1, tex2); 550 551 wined3d_mutex_lock(); 552 553 h1 = surf1->Handle - 1; 554 h2 = surf2->Handle - 1; 555 device->handle_table.entries[h1].object = surf2; 556 device->handle_table.entries[h2].object = surf1; 557 surf2->Handle = h1 + 1; 558 surf1->Handle = h2 + 1; 559 560 wined3d_mutex_unlock(); 561 562 return D3D_OK; 563 } 564 565 static HRESULT WINAPI d3d_device1_SwapTextureHandles(IDirect3DDevice *iface, 566 IDirect3DTexture *tex1, IDirect3DTexture *tex2) 567 { 568 struct d3d_device *device = impl_from_IDirect3DDevice(iface); 569 struct ddraw_surface *surf1 = unsafe_impl_from_IDirect3DTexture(tex1); 570 struct ddraw_surface *surf2 = unsafe_impl_from_IDirect3DTexture(tex2); 571 IDirect3DTexture2 *t1 = surf1 ? &surf1->IDirect3DTexture2_iface : NULL; 572 IDirect3DTexture2 *t2 = surf2 ? &surf2->IDirect3DTexture2_iface : NULL; 573 574 TRACE("iface %p, tex1 %p, tex2 %p.\n", iface, tex1, tex2); 575 576 return d3d_device2_SwapTextureHandles(&device->IDirect3DDevice2_iface, t1, t2); 577 } 578 579 /***************************************************************************** 580 * IDirect3DDevice3::GetStats 581 * 582 * This method seems to retrieve some stats from the device. 583 * The MSDN documentation doesn't exist any more, but the D3DSTATS 584 * structure suggests that the amount of drawn primitives and processed 585 * vertices is returned. 586 * 587 * Exists in Version 1, 2 and 3 588 * 589 * Parameters: 590 * Stats: Pointer to a D3DSTATS structure to be filled 591 * 592 * Returns: 593 * D3D_OK on success 594 * DDERR_INVALIDPARAMS if Stats == NULL 595 * 596 *****************************************************************************/ 597 static HRESULT WINAPI d3d_device3_GetStats(IDirect3DDevice3 *iface, D3DSTATS *Stats) 598 { 599 FIXME("iface %p, stats %p stub!\n", iface, Stats); 600 601 if(!Stats) 602 return DDERR_INVALIDPARAMS; 603 604 /* Fill the Stats with 0 */ 605 Stats->dwTrianglesDrawn = 0; 606 Stats->dwLinesDrawn = 0; 607 Stats->dwPointsDrawn = 0; 608 Stats->dwSpansDrawn = 0; 609 Stats->dwVerticesProcessed = 0; 610 611 return D3D_OK; 612 } 613 614 static HRESULT WINAPI d3d_device2_GetStats(IDirect3DDevice2 *iface, D3DSTATS *stats) 615 { 616 struct d3d_device *device = impl_from_IDirect3DDevice2(iface); 617 618 TRACE("iface %p, stats %p.\n", iface, stats); 619 620 return d3d_device3_GetStats(&device->IDirect3DDevice3_iface, stats); 621 } 622 623 static HRESULT WINAPI d3d_device1_GetStats(IDirect3DDevice *iface, D3DSTATS *stats) 624 { 625 struct d3d_device *device = impl_from_IDirect3DDevice(iface); 626 627 TRACE("iface %p, stats %p.\n", iface, stats); 628 629 return d3d_device3_GetStats(&device->IDirect3DDevice3_iface, stats); 630 } 631 632 /***************************************************************************** 633 * IDirect3DDevice::CreateExecuteBuffer 634 * 635 * Creates an IDirect3DExecuteBuffer, used for rendering with a 636 * Direct3DDevice. 637 * 638 * Version 1 only. 639 * 640 * Params: 641 * Desc: Buffer description 642 * ExecuteBuffer: Address to return the Interface pointer at 643 * UnkOuter: Must be NULL. Basically for aggregation, which ddraw doesn't 644 * support 645 * 646 * Returns: 647 * CLASS_E_NOAGGREGATION if UnkOuter != NULL 648 * DDERR_OUTOFMEMORY if we ran out of memory 649 * D3D_OK on success 650 * 651 *****************************************************************************/ 652 static HRESULT WINAPI d3d_device1_CreateExecuteBuffer(IDirect3DDevice *iface, 653 D3DEXECUTEBUFFERDESC *buffer_desc, IDirect3DExecuteBuffer **ExecuteBuffer, IUnknown *outer_unknown) 654 { 655 struct d3d_device *device = impl_from_IDirect3DDevice(iface); 656 struct d3d_execute_buffer *object; 657 HRESULT hr; 658 659 TRACE("iface %p, buffer_desc %p, buffer %p, outer_unknown %p.\n", 660 iface, buffer_desc, ExecuteBuffer, outer_unknown); 661 662 if (outer_unknown) 663 return CLASS_E_NOAGGREGATION; 664 665 /* Allocate the new Execute Buffer */ 666 if (!(object = heap_alloc_zero(sizeof(*object)))) 667 { 668 ERR("Failed to allocate execute buffer memory.\n"); 669 return DDERR_OUTOFMEMORY; 670 } 671 672 hr = d3d_execute_buffer_init(object, device, buffer_desc); 673 if (FAILED(hr)) 674 { 675 WARN("Failed to initialize execute buffer, hr %#x.\n", hr); 676 heap_free(object); 677 return hr; 678 } 679 680 *ExecuteBuffer = &object->IDirect3DExecuteBuffer_iface; 681 682 TRACE(" Returning IDirect3DExecuteBuffer at %p, implementation is at %p\n", *ExecuteBuffer, object); 683 684 return D3D_OK; 685 } 686 687 /***************************************************************************** 688 * IDirect3DDevice::Execute 689 * 690 * Executes all the stuff in an execute buffer. 691 * 692 * Params: 693 * ExecuteBuffer: The buffer to execute 694 * Viewport: The viewport used for rendering 695 * Flags: Some flags 696 * 697 * Returns: 698 * DDERR_INVALIDPARAMS if ExecuteBuffer == NULL 699 * D3D_OK on success 700 * 701 *****************************************************************************/ 702 static HRESULT WINAPI d3d_device1_Execute(IDirect3DDevice *iface, 703 IDirect3DExecuteBuffer *ExecuteBuffer, IDirect3DViewport *viewport, DWORD flags) 704 { 705 struct d3d_device *device = impl_from_IDirect3DDevice(iface); 706 struct d3d_execute_buffer *buffer = unsafe_impl_from_IDirect3DExecuteBuffer(ExecuteBuffer); 707 struct d3d_viewport *viewport_impl = unsafe_impl_from_IDirect3DViewport(viewport); 708 HRESULT hr; 709 710 TRACE("iface %p, buffer %p, viewport %p, flags %#x.\n", iface, ExecuteBuffer, viewport, flags); 711 712 if(!buffer) 713 return DDERR_INVALIDPARAMS; 714 715 /* Execute... */ 716 wined3d_mutex_lock(); 717 hr = d3d_execute_buffer_execute(buffer, device, viewport_impl); 718 wined3d_mutex_unlock(); 719 720 return hr; 721 } 722 723 /***************************************************************************** 724 * IDirect3DDevice3::AddViewport 725 * 726 * Add a Direct3DViewport to the device's viewport list. These viewports 727 * are wrapped to IDirect3DDevice7 viewports in viewport.c 728 * 729 * Exists in Version 1, 2 and 3. Note that IDirect3DViewport 1, 2 and 3 730 * are the same interfaces. 731 * 732 * Params: 733 * Viewport: The viewport to add 734 * 735 * Returns: 736 * DDERR_INVALIDPARAMS if Viewport == NULL 737 * D3D_OK on success 738 * 739 *****************************************************************************/ 740 static HRESULT WINAPI d3d_device3_AddViewport(IDirect3DDevice3 *iface, IDirect3DViewport3 *viewport) 741 { 742 struct d3d_device *device = impl_from_IDirect3DDevice3(iface); 743 struct d3d_viewport *vp = unsafe_impl_from_IDirect3DViewport3(viewport); 744 745 TRACE("iface %p, viewport %p.\n", iface, viewport); 746 747 /* Sanity check */ 748 if(!vp) 749 return DDERR_INVALIDPARAMS; 750 751 wined3d_mutex_lock(); 752 IDirect3DViewport3_AddRef(viewport); 753 list_add_head(&device->viewport_list, &vp->entry); 754 /* Viewport must be usable for Clear() after AddViewport, so set active_device here. */ 755 vp->active_device = device; 756 wined3d_mutex_unlock(); 757 758 return D3D_OK; 759 } 760 761 static HRESULT WINAPI d3d_device2_AddViewport(IDirect3DDevice2 *iface, 762 IDirect3DViewport2 *viewport) 763 { 764 struct d3d_device *device = impl_from_IDirect3DDevice2(iface); 765 struct d3d_viewport *vp = unsafe_impl_from_IDirect3DViewport2(viewport); 766 767 TRACE("iface %p, viewport %p.\n", iface, viewport); 768 769 return d3d_device3_AddViewport(&device->IDirect3DDevice3_iface, &vp->IDirect3DViewport3_iface); 770 } 771 772 static HRESULT WINAPI d3d_device1_AddViewport(IDirect3DDevice *iface, IDirect3DViewport *viewport) 773 { 774 struct d3d_device *device = impl_from_IDirect3DDevice(iface); 775 struct d3d_viewport *vp = unsafe_impl_from_IDirect3DViewport(viewport); 776 777 TRACE("iface %p, viewport %p.\n", iface, viewport); 778 779 return d3d_device3_AddViewport(&device->IDirect3DDevice3_iface, &vp->IDirect3DViewport3_iface); 780 } 781 782 /***************************************************************************** 783 * IDirect3DDevice3::DeleteViewport 784 * 785 * Deletes a Direct3DViewport from the device's viewport list. 786 * 787 * Exists in Version 1, 2 and 3. Note that all Viewport interface versions 788 * are equal. 789 * 790 * Params: 791 * Viewport: The viewport to delete 792 * 793 * Returns: 794 * D3D_OK on success 795 * DDERR_INVALIDPARAMS if the viewport wasn't found in the list 796 * 797 *****************************************************************************/ 798 static HRESULT WINAPI d3d_device3_DeleteViewport(IDirect3DDevice3 *iface, IDirect3DViewport3 *viewport) 799 { 800 struct d3d_device *device = impl_from_IDirect3DDevice3(iface); 801 struct d3d_viewport *vp = unsafe_impl_from_IDirect3DViewport3(viewport); 802 803 TRACE("iface %p, viewport %p.\n", iface, viewport); 804 805 if (!vp) 806 { 807 WARN("NULL viewport, returning DDERR_INVALIDPARAMS\n"); 808 return DDERR_INVALIDPARAMS; 809 } 810 811 wined3d_mutex_lock(); 812 813 if (vp->active_device != device) 814 { 815 WARN("Viewport %p active device is %p.\n", vp, vp->active_device); 816 wined3d_mutex_unlock(); 817 return DDERR_INVALIDPARAMS; 818 } 819 820 if (device->current_viewport == vp) 821 { 822 TRACE("Deleting current viewport, unsetting and releasing\n"); 823 IDirect3DViewport3_Release(viewport); 824 device->current_viewport = NULL; 825 } 826 827 vp->active_device = NULL; 828 list_remove(&vp->entry); 829 830 IDirect3DViewport3_Release(viewport); 831 832 wined3d_mutex_unlock(); 833 834 return D3D_OK; 835 } 836 837 static HRESULT WINAPI d3d_device2_DeleteViewport(IDirect3DDevice2 *iface, IDirect3DViewport2 *viewport) 838 { 839 struct d3d_device *device = impl_from_IDirect3DDevice2(iface); 840 struct d3d_viewport *vp = unsafe_impl_from_IDirect3DViewport2(viewport); 841 842 TRACE("iface %p, viewport %p.\n", iface, viewport); 843 844 return d3d_device3_DeleteViewport(&device->IDirect3DDevice3_iface, 845 vp ? &vp->IDirect3DViewport3_iface : NULL); 846 } 847 848 static HRESULT WINAPI d3d_device1_DeleteViewport(IDirect3DDevice *iface, IDirect3DViewport *viewport) 849 { 850 struct d3d_device *device = impl_from_IDirect3DDevice(iface); 851 struct d3d_viewport *vp = unsafe_impl_from_IDirect3DViewport(viewport); 852 853 TRACE("iface %p, viewport %p.\n", iface, viewport); 854 855 return d3d_device3_DeleteViewport(&device->IDirect3DDevice3_iface, 856 vp ? &vp->IDirect3DViewport3_iface : NULL); 857 } 858 859 /***************************************************************************** 860 * IDirect3DDevice3::NextViewport 861 * 862 * Returns a viewport from the viewport list, depending on the 863 * passed viewport and the flags. 864 * 865 * Exists in Version 1, 2 and 3. Note that all Viewport interface versions 866 * are equal. 867 * 868 * Params: 869 * Viewport: Viewport to use for beginning the search 870 * Flags: D3DNEXT_NEXT, D3DNEXT_HEAD or D3DNEXT_TAIL 871 * 872 * Returns: 873 * D3D_OK on success 874 * DDERR_INVALIDPARAMS if the flags were wrong, or Viewport was NULL 875 * 876 *****************************************************************************/ 877 static HRESULT WINAPI d3d_device3_NextViewport(IDirect3DDevice3 *iface, 878 IDirect3DViewport3 *Viewport3, IDirect3DViewport3 **lplpDirect3DViewport3, DWORD flags) 879 { 880 struct d3d_device *This = impl_from_IDirect3DDevice3(iface); 881 struct d3d_viewport *vp = unsafe_impl_from_IDirect3DViewport3(Viewport3); 882 struct d3d_viewport *next; 883 struct list *entry; 884 885 TRACE("iface %p, viewport %p, next %p, flags %#x.\n", 886 iface, Viewport3, lplpDirect3DViewport3, flags); 887 888 if(!vp) 889 { 890 *lplpDirect3DViewport3 = NULL; 891 return DDERR_INVALIDPARAMS; 892 } 893 894 895 wined3d_mutex_lock(); 896 switch (flags) 897 { 898 case D3DNEXT_NEXT: 899 entry = list_next(&This->viewport_list, &vp->entry); 900 break; 901 902 case D3DNEXT_HEAD: 903 entry = list_head(&This->viewport_list); 904 break; 905 906 case D3DNEXT_TAIL: 907 entry = list_tail(&This->viewport_list); 908 break; 909 910 default: 911 WARN("Invalid flags %#x.\n", flags); 912 *lplpDirect3DViewport3 = NULL; 913 wined3d_mutex_unlock(); 914 return DDERR_INVALIDPARAMS; 915 } 916 917 if (entry) 918 { 919 next = LIST_ENTRY(entry, struct d3d_viewport, entry); 920 *lplpDirect3DViewport3 = &next->IDirect3DViewport3_iface; 921 } 922 else 923 *lplpDirect3DViewport3 = NULL; 924 925 wined3d_mutex_unlock(); 926 927 return D3D_OK; 928 } 929 930 static HRESULT WINAPI d3d_device2_NextViewport(IDirect3DDevice2 *iface, 931 IDirect3DViewport2 *viewport, IDirect3DViewport2 **next, DWORD flags) 932 { 933 struct d3d_device *device = impl_from_IDirect3DDevice2(iface); 934 struct d3d_viewport *vp = unsafe_impl_from_IDirect3DViewport2(viewport); 935 IDirect3DViewport3 *res; 936 HRESULT hr; 937 938 TRACE("iface %p, viewport %p, next %p, flags %#x.\n", 939 iface, viewport, next, flags); 940 941 hr = d3d_device3_NextViewport(&device->IDirect3DDevice3_iface, 942 &vp->IDirect3DViewport3_iface, &res, flags); 943 *next = (IDirect3DViewport2 *)res; 944 return hr; 945 } 946 947 static HRESULT WINAPI d3d_device1_NextViewport(IDirect3DDevice *iface, 948 IDirect3DViewport *viewport, IDirect3DViewport **next, DWORD flags) 949 { 950 struct d3d_device *device = impl_from_IDirect3DDevice(iface); 951 struct d3d_viewport *vp = unsafe_impl_from_IDirect3DViewport(viewport); 952 IDirect3DViewport3 *res; 953 HRESULT hr; 954 955 TRACE("iface %p, viewport %p, next %p, flags %#x.\n", 956 iface, viewport, next, flags); 957 958 hr = d3d_device3_NextViewport(&device->IDirect3DDevice3_iface, 959 &vp->IDirect3DViewport3_iface, &res, flags); 960 *next = (IDirect3DViewport *)res; 961 return hr; 962 } 963 964 /***************************************************************************** 965 * IDirect3DDevice::Pick 966 * 967 * Executes an execute buffer without performing rendering. Instead, a 968 * list of primitives that intersect with (x1,y1) of the passed rectangle 969 * is created. IDirect3DDevice::GetPickRecords can be used to retrieve 970 * this list. 971 * 972 * Version 1 only 973 * 974 * Params: 975 * ExecuteBuffer: Buffer to execute 976 * Viewport: Viewport to use for execution 977 * Flags: None are defined, according to the SDK 978 * Rect: Specifies the coordinates to be picked. Only x1 and y2 are used, 979 * x2 and y2 are ignored. 980 * 981 * Returns: 982 * D3D_OK because it's a stub 983 * 984 *****************************************************************************/ 985 static HRESULT WINAPI d3d_device1_Pick(IDirect3DDevice *iface, IDirect3DExecuteBuffer *buffer, 986 IDirect3DViewport *viewport, DWORD flags, D3DRECT *rect) 987 { 988 FIXME("iface %p, buffer %p, viewport %p, flags %#x, rect %s stub!\n", 989 iface, buffer, viewport, flags, wine_dbgstr_rect((RECT *)rect)); 990 991 return D3D_OK; 992 } 993 994 /***************************************************************************** 995 * IDirect3DDevice::GetPickRecords 996 * 997 * Retrieves the pick records generated by IDirect3DDevice::GetPickRecords 998 * 999 * Version 1 only 1000 * 1001 * Params: 1002 * Count: Pointer to a DWORD containing the numbers of pick records to 1003 * retrieve 1004 * D3DPickRec: Address to store the resulting D3DPICKRECORD array. 1005 * 1006 * Returns: 1007 * D3D_OK, because it's a stub 1008 * 1009 *****************************************************************************/ 1010 static HRESULT WINAPI d3d_device1_GetPickRecords(IDirect3DDevice *iface, 1011 DWORD *count, D3DPICKRECORD *records) 1012 { 1013 FIXME("iface %p, count %p, records %p stub!\n", iface, count, records); 1014 1015 return D3D_OK; 1016 } 1017 1018 /***************************************************************************** 1019 * IDirect3DDevice7::EnumTextureformats 1020 * 1021 * Enumerates the supported texture formats. It checks against a list of all possible 1022 * formats to see if WineD3D supports it. If so, then it is passed to the app. 1023 * 1024 * This is for Version 7 and 3, older versions have a different 1025 * callback function and their own implementation 1026 * 1027 * Params: 1028 * Callback: Callback to call for each enumerated format 1029 * Arg: Argument to pass to the callback 1030 * 1031 * Returns: 1032 * D3D_OK on success 1033 * DDERR_INVALIDPARAMS if Callback == NULL 1034 * 1035 *****************************************************************************/ 1036 static HRESULT d3d_device7_EnumTextureFormats(IDirect3DDevice7 *iface, 1037 LPD3DENUMPIXELFORMATSCALLBACK callback, void *context) 1038 { 1039 struct d3d_device *device = impl_from_IDirect3DDevice7(iface); 1040 struct wined3d_display_mode mode; 1041 HRESULT hr; 1042 unsigned int i; 1043 1044 static const enum wined3d_format_id FormatList[] = 1045 { 1046 /* 16 bit */ 1047 WINED3DFMT_B5G5R5X1_UNORM, 1048 WINED3DFMT_B5G5R5A1_UNORM, 1049 WINED3DFMT_B4G4R4A4_UNORM, 1050 WINED3DFMT_B5G6R5_UNORM, 1051 /* 32 bit */ 1052 WINED3DFMT_B8G8R8X8_UNORM, 1053 WINED3DFMT_B8G8R8A8_UNORM, 1054 /* 8 bit */ 1055 WINED3DFMT_B2G3R3_UNORM, 1056 WINED3DFMT_P8_UINT, 1057 /* FOURCC codes */ 1058 WINED3DFMT_DXT1, 1059 WINED3DFMT_DXT2, 1060 WINED3DFMT_DXT3, 1061 WINED3DFMT_DXT4, 1062 WINED3DFMT_DXT5, 1063 }; 1064 1065 static const enum wined3d_format_id BumpFormatList[] = 1066 { 1067 WINED3DFMT_R8G8_SNORM, 1068 WINED3DFMT_R5G5_SNORM_L6_UNORM, 1069 WINED3DFMT_R8G8_SNORM_L8X8_UNORM, 1070 WINED3DFMT_R10G11B11_SNORM, 1071 WINED3DFMT_R10G10B10_SNORM_A2_UNORM 1072 }; 1073 1074 TRACE("iface %p, callback %p, context %p.\n", iface, callback, context); 1075 1076 if (!callback) 1077 return DDERR_INVALIDPARAMS; 1078 1079 wined3d_mutex_lock(); 1080 1081 memset(&mode, 0, sizeof(mode)); 1082 if (FAILED(hr = wined3d_get_adapter_display_mode(device->ddraw->wined3d, WINED3DADAPTER_DEFAULT, &mode, NULL))) 1083 { 1084 wined3d_mutex_unlock(); 1085 WARN("Cannot get the current adapter format\n"); 1086 return hr; 1087 } 1088 1089 for (i = 0; i < ARRAY_SIZE(FormatList); ++i) 1090 { 1091 if (wined3d_check_device_format(device->ddraw->wined3d, WINED3DADAPTER_DEFAULT, WINED3D_DEVICE_TYPE_HAL, 1092 mode.format_id, WINED3DUSAGE_TEXTURE, WINED3D_RTYPE_TEXTURE_2D, FormatList[i]) == D3D_OK) 1093 { 1094 DDPIXELFORMAT pformat; 1095 1096 memset(&pformat, 0, sizeof(pformat)); 1097 pformat.dwSize = sizeof(pformat); 1098 ddrawformat_from_wined3dformat(&pformat, FormatList[i]); 1099 1100 TRACE("Enumerating WineD3DFormat %d\n", FormatList[i]); 1101 hr = callback(&pformat, context); 1102 if(hr != DDENUMRET_OK) 1103 { 1104 TRACE("Format enumeration cancelled by application\n"); 1105 wined3d_mutex_unlock(); 1106 return D3D_OK; 1107 } 1108 } 1109 } 1110 1111 for (i = 0; i < ARRAY_SIZE(BumpFormatList); ++i) 1112 { 1113 if (wined3d_check_device_format(device->ddraw->wined3d, WINED3DADAPTER_DEFAULT, 1114 WINED3D_DEVICE_TYPE_HAL, mode.format_id, WINED3DUSAGE_TEXTURE | WINED3DUSAGE_QUERY_LEGACYBUMPMAP, 1115 WINED3D_RTYPE_TEXTURE_2D, BumpFormatList[i]) == D3D_OK) 1116 { 1117 DDPIXELFORMAT pformat; 1118 1119 memset(&pformat, 0, sizeof(pformat)); 1120 pformat.dwSize = sizeof(pformat); 1121 ddrawformat_from_wined3dformat(&pformat, BumpFormatList[i]); 1122 1123 TRACE("Enumerating WineD3DFormat %d\n", BumpFormatList[i]); 1124 hr = callback(&pformat, context); 1125 if(hr != DDENUMRET_OK) 1126 { 1127 TRACE("Format enumeration cancelled by application\n"); 1128 wined3d_mutex_unlock(); 1129 return D3D_OK; 1130 } 1131 } 1132 } 1133 TRACE("End of enumeration\n"); 1134 wined3d_mutex_unlock(); 1135 1136 return D3D_OK; 1137 } 1138 1139 static HRESULT WINAPI d3d_device7_EnumTextureFormats_FPUSetup(IDirect3DDevice7 *iface, 1140 LPD3DENUMPIXELFORMATSCALLBACK callback, void *context) 1141 { 1142 return d3d_device7_EnumTextureFormats(iface, callback, context); 1143 } 1144 1145 static HRESULT WINAPI d3d_device7_EnumTextureFormats_FPUPreserve(IDirect3DDevice7 *iface, 1146 LPD3DENUMPIXELFORMATSCALLBACK callback, void *context) 1147 { 1148 HRESULT hr; 1149 WORD old_fpucw; 1150 1151 old_fpucw = d3d_fpu_setup(); 1152 hr = d3d_device7_EnumTextureFormats(iface, callback, context); 1153 set_fpu_control_word(old_fpucw); 1154 1155 return hr; 1156 } 1157 1158 static HRESULT WINAPI d3d_device3_EnumTextureFormats(IDirect3DDevice3 *iface, 1159 LPD3DENUMPIXELFORMATSCALLBACK callback, void *context) 1160 { 1161 struct d3d_device *device = impl_from_IDirect3DDevice3(iface); 1162 1163 TRACE("iface %p, callback %p, context %p.\n", iface, callback, context); 1164 1165 return IDirect3DDevice7_EnumTextureFormats(&device->IDirect3DDevice7_iface, callback, context); 1166 } 1167 1168 /***************************************************************************** 1169 * IDirect3DDevice2::EnumTextureformats 1170 * 1171 * EnumTextureFormats for Version 1 and 2, see 1172 * IDirect3DDevice7::EnumTextureFormats for a more detailed description. 1173 * 1174 * This version has a different callback and does not enumerate FourCC 1175 * formats 1176 * 1177 *****************************************************************************/ 1178 static HRESULT WINAPI d3d_device2_EnumTextureFormats(IDirect3DDevice2 *iface, 1179 LPD3DENUMTEXTUREFORMATSCALLBACK callback, void *context) 1180 { 1181 struct d3d_device *device = impl_from_IDirect3DDevice2(iface); 1182 struct wined3d_display_mode mode; 1183 HRESULT hr; 1184 unsigned int i; 1185 1186 static const enum wined3d_format_id FormatList[] = 1187 { 1188 /* 16 bit */ 1189 WINED3DFMT_B5G5R5X1_UNORM, 1190 WINED3DFMT_B5G5R5A1_UNORM, 1191 WINED3DFMT_B4G4R4A4_UNORM, 1192 WINED3DFMT_B5G6R5_UNORM, 1193 /* 32 bit */ 1194 WINED3DFMT_B8G8R8X8_UNORM, 1195 WINED3DFMT_B8G8R8A8_UNORM, 1196 /* 8 bit */ 1197 WINED3DFMT_B2G3R3_UNORM, 1198 WINED3DFMT_P8_UINT, 1199 /* FOURCC codes - Not in this version*/ 1200 }; 1201 1202 TRACE("iface %p, callback %p, context %p.\n", iface, callback, context); 1203 1204 if (!callback) 1205 return DDERR_INVALIDPARAMS; 1206 1207 wined3d_mutex_lock(); 1208 1209 memset(&mode, 0, sizeof(mode)); 1210 if (FAILED(hr = wined3d_get_adapter_display_mode(device->ddraw->wined3d, WINED3DADAPTER_DEFAULT, &mode, NULL))) 1211 { 1212 wined3d_mutex_unlock(); 1213 WARN("Cannot get the current adapter format\n"); 1214 return hr; 1215 } 1216 1217 for (i = 0; i < ARRAY_SIZE(FormatList); ++i) 1218 { 1219 if (wined3d_check_device_format(device->ddraw->wined3d, 0, WINED3D_DEVICE_TYPE_HAL, 1220 mode.format_id, WINED3DUSAGE_TEXTURE, WINED3D_RTYPE_TEXTURE_2D, FormatList[i]) == D3D_OK) 1221 { 1222 DDSURFACEDESC sdesc; 1223 1224 memset(&sdesc, 0, sizeof(sdesc)); 1225 sdesc.dwSize = sizeof(sdesc); 1226 sdesc.dwFlags = DDSD_PIXELFORMAT | DDSD_CAPS; 1227 sdesc.ddsCaps.dwCaps = DDSCAPS_TEXTURE; 1228 sdesc.ddpfPixelFormat.dwSize = sizeof(sdesc.ddpfPixelFormat); 1229 ddrawformat_from_wined3dformat(&sdesc.ddpfPixelFormat, FormatList[i]); 1230 1231 TRACE("Enumerating WineD3DFormat %d\n", FormatList[i]); 1232 hr = callback(&sdesc, context); 1233 if(hr != DDENUMRET_OK) 1234 { 1235 TRACE("Format enumeration cancelled by application\n"); 1236 wined3d_mutex_unlock(); 1237 return D3D_OK; 1238 } 1239 } 1240 } 1241 TRACE("End of enumeration\n"); 1242 wined3d_mutex_unlock(); 1243 1244 return D3D_OK; 1245 } 1246 1247 static HRESULT WINAPI d3d_device1_EnumTextureFormats(IDirect3DDevice *iface, 1248 LPD3DENUMTEXTUREFORMATSCALLBACK callback, void *context) 1249 { 1250 struct d3d_device *device = impl_from_IDirect3DDevice(iface); 1251 1252 TRACE("iface %p, callback %p, context %p.\n", iface, callback, context); 1253 1254 return d3d_device2_EnumTextureFormats(&device->IDirect3DDevice2_iface, callback, context); 1255 } 1256 1257 /***************************************************************************** 1258 * IDirect3DDevice::CreateMatrix 1259 * 1260 * Creates a matrix handle. A handle is created and memory for a D3DMATRIX is 1261 * allocated for the handle. 1262 * 1263 * Version 1 only 1264 * 1265 * Params 1266 * D3DMatHandle: Address to return the handle at 1267 * 1268 * Returns: 1269 * D3D_OK on success 1270 * DDERR_INVALIDPARAMS if D3DMatHandle = NULL 1271 * 1272 *****************************************************************************/ 1273 static HRESULT WINAPI d3d_device1_CreateMatrix(IDirect3DDevice *iface, D3DMATRIXHANDLE *D3DMatHandle) 1274 { 1275 struct d3d_device *device = impl_from_IDirect3DDevice(iface); 1276 D3DMATRIX *matrix; 1277 DWORD h; 1278 1279 TRACE("iface %p, matrix_handle %p.\n", iface, D3DMatHandle); 1280 1281 if(!D3DMatHandle) 1282 return DDERR_INVALIDPARAMS; 1283 1284 if (!(matrix = heap_alloc_zero(sizeof(*matrix)))) 1285 { 1286 ERR("Out of memory when allocating a D3DMATRIX\n"); 1287 return DDERR_OUTOFMEMORY; 1288 } 1289 1290 wined3d_mutex_lock(); 1291 1292 h = ddraw_allocate_handle(&device->handle_table, matrix, DDRAW_HANDLE_MATRIX); 1293 if (h == DDRAW_INVALID_HANDLE) 1294 { 1295 ERR("Failed to allocate a matrix handle.\n"); 1296 heap_free(matrix); 1297 wined3d_mutex_unlock(); 1298 return DDERR_OUTOFMEMORY; 1299 } 1300 1301 *D3DMatHandle = h + 1; 1302 1303 TRACE(" returning matrix handle %d\n", *D3DMatHandle); 1304 1305 wined3d_mutex_unlock(); 1306 1307 return D3D_OK; 1308 } 1309 1310 /***************************************************************************** 1311 * IDirect3DDevice::SetMatrix 1312 * 1313 * Sets a matrix for a matrix handle. The matrix is copied into the memory 1314 * allocated for the handle 1315 * 1316 * Version 1 only 1317 * 1318 * Params: 1319 * D3DMatHandle: Handle to set the matrix to 1320 * D3DMatrix: Matrix to set 1321 * 1322 * Returns: 1323 * D3D_OK on success 1324 * DDERR_INVALIDPARAMS if the handle of the matrix is invalid or the matrix 1325 * to set is NULL 1326 * 1327 *****************************************************************************/ 1328 static HRESULT WINAPI d3d_device1_SetMatrix(IDirect3DDevice *iface, 1329 D3DMATRIXHANDLE D3DMatHandle, D3DMATRIX *D3DMatrix) 1330 { 1331 struct d3d_device *This = impl_from_IDirect3DDevice(iface); 1332 D3DMATRIX *m; 1333 1334 TRACE("iface %p, matrix_handle %#x, matrix %p.\n", iface, D3DMatHandle, D3DMatrix); 1335 1336 if (!D3DMatrix) return DDERR_INVALIDPARAMS; 1337 1338 wined3d_mutex_lock(); 1339 1340 m = ddraw_get_object(&This->handle_table, D3DMatHandle - 1, DDRAW_HANDLE_MATRIX); 1341 if (!m) 1342 { 1343 WARN("Invalid matrix handle.\n"); 1344 wined3d_mutex_unlock(); 1345 return DDERR_INVALIDPARAMS; 1346 } 1347 1348 if (TRACE_ON(ddraw)) 1349 dump_D3DMATRIX(D3DMatrix); 1350 1351 *m = *D3DMatrix; 1352 1353 if (D3DMatHandle == This->world) 1354 wined3d_device_set_transform(This->wined3d_device, 1355 WINED3D_TS_WORLD_MATRIX(0), (struct wined3d_matrix *)D3DMatrix); 1356 1357 if (D3DMatHandle == This->view) 1358 wined3d_device_set_transform(This->wined3d_device, 1359 WINED3D_TS_VIEW, (struct wined3d_matrix *)D3DMatrix); 1360 1361 if (D3DMatHandle == This->proj) 1362 wined3d_device_set_transform(This->wined3d_device, 1363 WINED3D_TS_PROJECTION, (struct wined3d_matrix *)D3DMatrix); 1364 1365 wined3d_mutex_unlock(); 1366 1367 return D3D_OK; 1368 } 1369 1370 /***************************************************************************** 1371 * IDirect3DDevice::GetMatrix 1372 * 1373 * Returns the content of a D3DMATRIX handle 1374 * 1375 * Version 1 only 1376 * 1377 * Params: 1378 * D3DMatHandle: Matrix handle to read the content from 1379 * D3DMatrix: Address to store the content at 1380 * 1381 * Returns: 1382 * D3D_OK on success 1383 * DDERR_INVALIDPARAMS if D3DMatHandle is invalid or D3DMatrix is NULL 1384 * 1385 *****************************************************************************/ 1386 static HRESULT WINAPI d3d_device1_GetMatrix(IDirect3DDevice *iface, 1387 D3DMATRIXHANDLE D3DMatHandle, D3DMATRIX *D3DMatrix) 1388 { 1389 struct d3d_device *device = impl_from_IDirect3DDevice(iface); 1390 D3DMATRIX *m; 1391 1392 TRACE("iface %p, matrix_handle %#x, matrix %p.\n", iface, D3DMatHandle, D3DMatrix); 1393 1394 if (!D3DMatrix) return DDERR_INVALIDPARAMS; 1395 1396 wined3d_mutex_lock(); 1397 1398 m = ddraw_get_object(&device->handle_table, D3DMatHandle - 1, DDRAW_HANDLE_MATRIX); 1399 if (!m) 1400 { 1401 WARN("Invalid matrix handle.\n"); 1402 wined3d_mutex_unlock(); 1403 return DDERR_INVALIDPARAMS; 1404 } 1405 1406 *D3DMatrix = *m; 1407 1408 wined3d_mutex_unlock(); 1409 1410 return D3D_OK; 1411 } 1412 1413 /***************************************************************************** 1414 * IDirect3DDevice::DeleteMatrix 1415 * 1416 * Destroys a Matrix handle. Frees the memory and unsets the handle data 1417 * 1418 * Version 1 only 1419 * 1420 * Params: 1421 * D3DMatHandle: Handle to destroy 1422 * 1423 * Returns: 1424 * D3D_OK on success 1425 * DDERR_INVALIDPARAMS if D3DMatHandle is invalid 1426 * 1427 *****************************************************************************/ 1428 static HRESULT WINAPI d3d_device1_DeleteMatrix(IDirect3DDevice *iface, D3DMATRIXHANDLE D3DMatHandle) 1429 { 1430 struct d3d_device *device = impl_from_IDirect3DDevice(iface); 1431 D3DMATRIX *m; 1432 1433 TRACE("iface %p, matrix_handle %#x.\n", iface, D3DMatHandle); 1434 1435 wined3d_mutex_lock(); 1436 1437 m = ddraw_free_handle(&device->handle_table, D3DMatHandle - 1, DDRAW_HANDLE_MATRIX); 1438 if (!m) 1439 { 1440 WARN("Invalid matrix handle.\n"); 1441 wined3d_mutex_unlock(); 1442 return DDERR_INVALIDPARAMS; 1443 } 1444 1445 wined3d_mutex_unlock(); 1446 1447 heap_free(m); 1448 1449 return D3D_OK; 1450 } 1451 1452 /***************************************************************************** 1453 * IDirect3DDevice7::BeginScene 1454 * 1455 * This method must be called before any rendering is performed. 1456 * IDirect3DDevice::EndScene has to be called after the scene is complete 1457 * 1458 * Version 1, 2, 3 and 7 1459 * 1460 * Returns: 1461 * D3D_OK on success, 1462 * D3DERR_SCENE_IN_SCENE if WineD3D returns an error(Only in case of an already 1463 * started scene). 1464 * 1465 *****************************************************************************/ 1466 static HRESULT d3d_device7_BeginScene(IDirect3DDevice7 *iface) 1467 { 1468 struct d3d_device *device = impl_from_IDirect3DDevice7(iface); 1469 HRESULT hr; 1470 1471 TRACE("iface %p.\n", iface); 1472 1473 wined3d_mutex_lock(); 1474 hr = wined3d_device_begin_scene(device->wined3d_device); 1475 wined3d_mutex_unlock(); 1476 1477 if(hr == WINED3D_OK) return D3D_OK; 1478 else return D3DERR_SCENE_IN_SCENE; /* TODO: Other possible causes of failure */ 1479 } 1480 1481 static HRESULT WINAPI d3d_device7_BeginScene_FPUSetup(IDirect3DDevice7 *iface) 1482 { 1483 return d3d_device7_BeginScene(iface); 1484 } 1485 1486 static HRESULT WINAPI d3d_device7_BeginScene_FPUPreserve(IDirect3DDevice7 *iface) 1487 { 1488 HRESULT hr; 1489 WORD old_fpucw; 1490 1491 old_fpucw = d3d_fpu_setup(); 1492 hr = d3d_device7_BeginScene(iface); 1493 set_fpu_control_word(old_fpucw); 1494 1495 return hr; 1496 } 1497 1498 static HRESULT WINAPI d3d_device3_BeginScene(IDirect3DDevice3 *iface) 1499 { 1500 struct d3d_device *device = impl_from_IDirect3DDevice3(iface); 1501 1502 TRACE("iface %p.\n", iface); 1503 1504 return IDirect3DDevice7_BeginScene(&device->IDirect3DDevice7_iface); 1505 } 1506 1507 static HRESULT WINAPI d3d_device2_BeginScene(IDirect3DDevice2 *iface) 1508 { 1509 struct d3d_device *device = impl_from_IDirect3DDevice2(iface); 1510 1511 TRACE("iface %p.\n", iface); 1512 1513 return IDirect3DDevice7_BeginScene(&device->IDirect3DDevice7_iface); 1514 } 1515 1516 static HRESULT WINAPI d3d_device1_BeginScene(IDirect3DDevice *iface) 1517 { 1518 struct d3d_device *device = impl_from_IDirect3DDevice(iface); 1519 1520 TRACE("iface %p.\n", iface); 1521 1522 return IDirect3DDevice7_BeginScene(&device->IDirect3DDevice7_iface); 1523 } 1524 1525 /***************************************************************************** 1526 * IDirect3DDevice7::EndScene 1527 * 1528 * Ends a scene that has been begun with IDirect3DDevice7::BeginScene. 1529 * This method must be called after rendering is finished. 1530 * 1531 * Version 1, 2, 3 and 7 1532 * 1533 * Returns: 1534 * D3D_OK on success, 1535 * D3DERR_SCENE_NOT_IN_SCENE is returned if WineD3D returns an error. It does 1536 * that only if the scene was already ended. 1537 * 1538 *****************************************************************************/ 1539 static HRESULT d3d_device7_EndScene(IDirect3DDevice7 *iface) 1540 { 1541 struct d3d_device *device = impl_from_IDirect3DDevice7(iface); 1542 HRESULT hr; 1543 1544 TRACE("iface %p.\n", iface); 1545 1546 wined3d_mutex_lock(); 1547 hr = wined3d_device_end_scene(device->wined3d_device); 1548 wined3d_mutex_unlock(); 1549 1550 if(hr == WINED3D_OK) return D3D_OK; 1551 else return D3DERR_SCENE_NOT_IN_SCENE; 1552 } 1553 1554 static HRESULT WINAPI DECLSPEC_HOTPATCH d3d_device7_EndScene_FPUSetup(IDirect3DDevice7 *iface) 1555 { 1556 return d3d_device7_EndScene(iface); 1557 } 1558 1559 static HRESULT WINAPI DECLSPEC_HOTPATCH d3d_device7_EndScene_FPUPreserve(IDirect3DDevice7 *iface) 1560 { 1561 HRESULT hr; 1562 WORD old_fpucw; 1563 1564 old_fpucw = d3d_fpu_setup(); 1565 hr = d3d_device7_EndScene(iface); 1566 set_fpu_control_word(old_fpucw); 1567 1568 return hr; 1569 } 1570 1571 static HRESULT WINAPI DECLSPEC_HOTPATCH d3d_device3_EndScene(IDirect3DDevice3 *iface) 1572 { 1573 struct d3d_device *device = impl_from_IDirect3DDevice3(iface); 1574 1575 TRACE("iface %p.\n", iface); 1576 1577 return IDirect3DDevice7_EndScene(&device->IDirect3DDevice7_iface); 1578 } 1579 1580 static HRESULT WINAPI DECLSPEC_HOTPATCH d3d_device2_EndScene(IDirect3DDevice2 *iface) 1581 { 1582 struct d3d_device *device = impl_from_IDirect3DDevice2(iface); 1583 1584 TRACE("iface %p.\n", iface); 1585 1586 return IDirect3DDevice7_EndScene(&device->IDirect3DDevice7_iface); 1587 } 1588 1589 static HRESULT WINAPI DECLSPEC_HOTPATCH d3d_device1_EndScene(IDirect3DDevice *iface) 1590 { 1591 struct d3d_device *device = impl_from_IDirect3DDevice(iface); 1592 1593 TRACE("iface %p.\n", iface); 1594 1595 return IDirect3DDevice7_EndScene(&device->IDirect3DDevice7_iface); 1596 } 1597 1598 /***************************************************************************** 1599 * IDirect3DDevice7::GetDirect3D 1600 * 1601 * Returns the IDirect3D(= interface to the DirectDraw object) used to create 1602 * this device. 1603 * 1604 * Params: 1605 * Direct3D7: Address to store the interface pointer at 1606 * 1607 * Returns: 1608 * D3D_OK on success 1609 * DDERR_INVALIDPARAMS if Direct3D7 == NULL 1610 * 1611 *****************************************************************************/ 1612 static HRESULT WINAPI d3d_device7_GetDirect3D(IDirect3DDevice7 *iface, IDirect3D7 **d3d) 1613 { 1614 struct d3d_device *device = impl_from_IDirect3DDevice7(iface); 1615 1616 TRACE("iface %p, d3d %p.\n", iface, d3d); 1617 1618 if (!d3d) 1619 return DDERR_INVALIDPARAMS; 1620 1621 *d3d = &device->ddraw->IDirect3D7_iface; 1622 IDirect3D7_AddRef(*d3d); 1623 1624 TRACE("Returning interface %p.\n", *d3d); 1625 return D3D_OK; 1626 } 1627 1628 static HRESULT WINAPI d3d_device3_GetDirect3D(IDirect3DDevice3 *iface, IDirect3D3 **d3d) 1629 { 1630 struct d3d_device *device = impl_from_IDirect3DDevice3(iface); 1631 1632 TRACE("iface %p, d3d %p.\n", iface, d3d); 1633 1634 if (!d3d) 1635 return DDERR_INVALIDPARAMS; 1636 1637 *d3d = &device->ddraw->IDirect3D3_iface; 1638 IDirect3D3_AddRef(*d3d); 1639 1640 TRACE("Returning interface %p.\n", *d3d); 1641 return D3D_OK; 1642 } 1643 1644 static HRESULT WINAPI d3d_device2_GetDirect3D(IDirect3DDevice2 *iface, IDirect3D2 **d3d) 1645 { 1646 struct d3d_device *device = impl_from_IDirect3DDevice2(iface); 1647 1648 TRACE("iface %p, d3d %p.\n", iface, d3d); 1649 1650 if (!d3d) 1651 return DDERR_INVALIDPARAMS; 1652 1653 *d3d = &device->ddraw->IDirect3D2_iface; 1654 IDirect3D2_AddRef(*d3d); 1655 1656 TRACE("Returning interface %p.\n", *d3d); 1657 return D3D_OK; 1658 } 1659 1660 static HRESULT WINAPI d3d_device1_GetDirect3D(IDirect3DDevice *iface, IDirect3D **d3d) 1661 { 1662 struct d3d_device *device = impl_from_IDirect3DDevice(iface); 1663 1664 TRACE("iface %p, d3d %p.\n", iface, d3d); 1665 1666 if (!d3d) 1667 return DDERR_INVALIDPARAMS; 1668 1669 *d3d = &device->ddraw->IDirect3D_iface; 1670 IDirect3D_AddRef(*d3d); 1671 1672 TRACE("Returning interface %p.\n", *d3d); 1673 return D3D_OK; 1674 } 1675 1676 /***************************************************************************** 1677 * IDirect3DDevice3::SetCurrentViewport 1678 * 1679 * Sets a Direct3DViewport as the current viewport. 1680 * For the thunks note that all viewport interface versions are equal 1681 * 1682 * Params: 1683 * Direct3DViewport3: The viewport to set 1684 * 1685 * Version 2 and 3 1686 * 1687 * Returns: 1688 * D3D_OK on success 1689 * (Is a NULL viewport valid?) 1690 * 1691 *****************************************************************************/ 1692 static HRESULT WINAPI d3d_device3_SetCurrentViewport(IDirect3DDevice3 *iface, IDirect3DViewport3 *Direct3DViewport3) 1693 { 1694 struct d3d_device *This = impl_from_IDirect3DDevice3(iface); 1695 struct d3d_viewport *vp = unsafe_impl_from_IDirect3DViewport3(Direct3DViewport3); 1696 1697 TRACE("iface %p, viewport %p.\n", iface, Direct3DViewport3); 1698 1699 if (!vp) 1700 { 1701 WARN("Direct3DViewport3 is NULL, returning DDERR_INVALIDPARAMS\n"); 1702 return DDERR_INVALIDPARAMS; 1703 } 1704 1705 wined3d_mutex_lock(); 1706 /* Do nothing if the specified viewport is the same as the current one */ 1707 if (This->current_viewport == vp) 1708 { 1709 wined3d_mutex_unlock(); 1710 return D3D_OK; 1711 } 1712 1713 if (vp->active_device != This) 1714 { 1715 WARN("Viewport %p active device is %p.\n", vp, vp->active_device); 1716 wined3d_mutex_unlock(); 1717 return DDERR_INVALIDPARAMS; 1718 } 1719 1720 /* Release previous viewport and AddRef the new one */ 1721 if (This->current_viewport) 1722 { 1723 TRACE("ViewportImpl is at %p, interface is at %p\n", This->current_viewport, 1724 &This->current_viewport->IDirect3DViewport3_iface); 1725 IDirect3DViewport3_Release(&This->current_viewport->IDirect3DViewport3_iface); 1726 } 1727 IDirect3DViewport3_AddRef(Direct3DViewport3); 1728 1729 /* Set this viewport as the current viewport */ 1730 This->current_viewport = vp; 1731 1732 /* Activate this viewport */ 1733 viewport_activate(This->current_viewport, FALSE); 1734 1735 wined3d_mutex_unlock(); 1736 1737 return D3D_OK; 1738 } 1739 1740 static HRESULT WINAPI d3d_device2_SetCurrentViewport(IDirect3DDevice2 *iface, IDirect3DViewport2 *viewport) 1741 { 1742 struct d3d_device *device = impl_from_IDirect3DDevice2(iface); 1743 struct d3d_viewport *vp = unsafe_impl_from_IDirect3DViewport2(viewport); 1744 1745 TRACE("iface %p, viewport %p.\n", iface, viewport); 1746 1747 return d3d_device3_SetCurrentViewport(&device->IDirect3DDevice3_iface, 1748 vp ? &vp->IDirect3DViewport3_iface : NULL); 1749 } 1750 1751 /***************************************************************************** 1752 * IDirect3DDevice3::GetCurrentViewport 1753 * 1754 * Returns the currently active viewport. 1755 * 1756 * Version 2 and 3 1757 * 1758 * Params: 1759 * Direct3DViewport3: Address to return the interface pointer at 1760 * 1761 * Returns: 1762 * D3D_OK on success 1763 * DDERR_INVALIDPARAMS if Direct3DViewport == NULL 1764 * 1765 *****************************************************************************/ 1766 static HRESULT WINAPI d3d_device3_GetCurrentViewport(IDirect3DDevice3 *iface, IDirect3DViewport3 **viewport) 1767 { 1768 struct d3d_device *device = impl_from_IDirect3DDevice3(iface); 1769 1770 TRACE("iface %p, viewport %p.\n", iface, viewport); 1771 1772 wined3d_mutex_lock(); 1773 if (!device->current_viewport) 1774 { 1775 wined3d_mutex_unlock(); 1776 WARN("No current viewport, returning D3DERR_NOCURRENTVIEWPORT\n"); 1777 return D3DERR_NOCURRENTVIEWPORT; 1778 } 1779 1780 *viewport = &device->current_viewport->IDirect3DViewport3_iface; 1781 IDirect3DViewport3_AddRef(*viewport); 1782 1783 TRACE("Returning interface %p.\n", *viewport); 1784 wined3d_mutex_unlock(); 1785 return D3D_OK; 1786 } 1787 1788 static HRESULT WINAPI d3d_device2_GetCurrentViewport(IDirect3DDevice2 *iface, IDirect3DViewport2 **viewport) 1789 { 1790 struct d3d_device *device = impl_from_IDirect3DDevice2(iface); 1791 1792 TRACE("iface %p, viewport %p.\n", iface, viewport); 1793 1794 return d3d_device3_GetCurrentViewport(&device->IDirect3DDevice3_iface, 1795 (IDirect3DViewport3 **)viewport); 1796 } 1797 1798 static BOOL validate_surface_palette(struct ddraw_surface *surface) 1799 { 1800 return !format_is_paletteindexed(&surface->surface_desc.u4.ddpfPixelFormat) 1801 || surface->palette; 1802 } 1803 1804 static HRESULT d3d_device_set_render_target(struct d3d_device *device, 1805 struct ddraw_surface *target, IUnknown *rt_iface) 1806 { 1807 HRESULT hr; 1808 1809 if (device->rt_iface == rt_iface) 1810 { 1811 TRACE("No-op SetRenderTarget operation, not doing anything\n"); 1812 return D3D_OK; 1813 } 1814 if (!target) 1815 { 1816 WARN("Trying to set render target to NULL.\n"); 1817 return DDERR_INVALIDPARAMS; 1818 } 1819 1820 if (FAILED(hr = wined3d_device_set_rendertarget_view(device->wined3d_device, 1821 0, ddraw_surface_get_rendertarget_view(target), FALSE))) 1822 return hr; 1823 1824 IUnknown_AddRef(rt_iface); 1825 IUnknown_Release(device->rt_iface); 1826 device->rt_iface = rt_iface; 1827 d3d_device_update_depth_stencil(device); 1828 1829 return D3D_OK; 1830 } 1831 1832 static HRESULT d3d_device7_SetRenderTarget(IDirect3DDevice7 *iface, 1833 IDirectDrawSurface7 *target, DWORD flags) 1834 { 1835 struct ddraw_surface *target_impl = unsafe_impl_from_IDirectDrawSurface7(target); 1836 struct d3d_device *device = impl_from_IDirect3DDevice7(iface); 1837 HRESULT hr; 1838 1839 TRACE("iface %p, target %p, flags %#x.\n", iface, target, flags); 1840 1841 wined3d_mutex_lock(); 1842 1843 if (!validate_surface_palette(target_impl)) 1844 { 1845 WARN("Surface %p has an indexed pixel format, but no palette.\n", target_impl); 1846 wined3d_mutex_unlock(); 1847 return DDERR_INVALIDCAPS; 1848 } 1849 1850 if (!(target_impl->surface_desc.ddsCaps.dwCaps & DDSCAPS_3DDEVICE)) 1851 { 1852 WARN("Surface %p is not a render target.\n", target_impl); 1853 wined3d_mutex_unlock(); 1854 return DDERR_INVALIDCAPS; 1855 } 1856 1857 if (device->hw && !(target_impl->surface_desc.ddsCaps.dwCaps & DDSCAPS_VIDEOMEMORY)) 1858 { 1859 WARN("Surface %p is not in video memory.\n", target_impl); 1860 wined3d_mutex_unlock(); 1861 return DDERR_INVALIDPARAMS; 1862 } 1863 1864 if (target_impl->surface_desc.ddsCaps.dwCaps & DDSCAPS_ZBUFFER) 1865 { 1866 WARN("Surface %p is a depth buffer.\n", target_impl); 1867 IDirectDrawSurface7_AddRef(target); 1868 IUnknown_Release(device->rt_iface); 1869 device->rt_iface = (IUnknown *)target; 1870 wined3d_mutex_unlock(); 1871 return DDERR_INVALIDPIXELFORMAT; 1872 } 1873 1874 hr = d3d_device_set_render_target(device, target_impl, (IUnknown *)target); 1875 wined3d_mutex_unlock(); 1876 return hr; 1877 } 1878 1879 static HRESULT WINAPI d3d_device7_SetRenderTarget_FPUSetup(IDirect3DDevice7 *iface, 1880 IDirectDrawSurface7 *NewTarget, DWORD flags) 1881 { 1882 return d3d_device7_SetRenderTarget(iface, NewTarget, flags); 1883 } 1884 1885 static HRESULT WINAPI d3d_device7_SetRenderTarget_FPUPreserve(IDirect3DDevice7 *iface, 1886 IDirectDrawSurface7 *NewTarget, DWORD flags) 1887 { 1888 HRESULT hr; 1889 WORD old_fpucw; 1890 1891 old_fpucw = d3d_fpu_setup(); 1892 hr = d3d_device7_SetRenderTarget(iface, NewTarget, flags); 1893 set_fpu_control_word(old_fpucw); 1894 1895 return hr; 1896 } 1897 1898 static HRESULT WINAPI d3d_device3_SetRenderTarget(IDirect3DDevice3 *iface, 1899 IDirectDrawSurface4 *target, DWORD flags) 1900 { 1901 struct ddraw_surface *target_impl = unsafe_impl_from_IDirectDrawSurface4(target); 1902 struct d3d_device *device = impl_from_IDirect3DDevice3(iface); 1903 HRESULT hr; 1904 1905 TRACE("iface %p, target %p, flags %#x.\n", iface, target, flags); 1906 1907 wined3d_mutex_lock(); 1908 1909 if (!validate_surface_palette(target_impl)) 1910 { 1911 WARN("Surface %p has an indexed pixel format, but no palette.\n", target_impl); 1912 wined3d_mutex_unlock(); 1913 return DDERR_INVALIDCAPS; 1914 } 1915 1916 if (!(target_impl->surface_desc.ddsCaps.dwCaps & DDSCAPS_3DDEVICE)) 1917 { 1918 WARN("Surface %p is not a render target.\n", target_impl); 1919 wined3d_mutex_unlock(); 1920 return DDERR_INVALIDCAPS; 1921 } 1922 1923 if (target_impl->surface_desc.ddsCaps.dwCaps & DDSCAPS_ZBUFFER) 1924 { 1925 WARN("Surface %p is a depth buffer.\n", target_impl); 1926 IDirectDrawSurface4_AddRef(target); 1927 IUnknown_Release(device->rt_iface); 1928 device->rt_iface = (IUnknown *)target; 1929 wined3d_mutex_unlock(); 1930 return DDERR_INVALIDPIXELFORMAT; 1931 } 1932 1933 if (device->hw && !(target_impl->surface_desc.ddsCaps.dwCaps & DDSCAPS_VIDEOMEMORY)) 1934 { 1935 WARN("Surface %p is not in video memory.\n", target_impl); 1936 IDirectDrawSurface4_AddRef(target); 1937 IUnknown_Release(device->rt_iface); 1938 device->rt_iface = (IUnknown *)target; 1939 wined3d_mutex_unlock(); 1940 return D3D_OK; 1941 } 1942 1943 hr = d3d_device_set_render_target(device, target_impl, (IUnknown *)target); 1944 wined3d_mutex_unlock(); 1945 return hr; 1946 } 1947 1948 static HRESULT WINAPI d3d_device2_SetRenderTarget(IDirect3DDevice2 *iface, 1949 IDirectDrawSurface *target, DWORD flags) 1950 { 1951 struct ddraw_surface *target_impl = unsafe_impl_from_IDirectDrawSurface(target); 1952 struct d3d_device *device = impl_from_IDirect3DDevice2(iface); 1953 HRESULT hr; 1954 1955 TRACE("iface %p, target %p, flags %#x.\n", iface, target, flags); 1956 1957 wined3d_mutex_lock(); 1958 1959 if (!validate_surface_palette(target_impl)) 1960 { 1961 WARN("Surface %p has an indexed pixel format, but no palette.\n", target_impl); 1962 wined3d_mutex_unlock(); 1963 return DDERR_INVALIDCAPS; 1964 } 1965 1966 if (!(target_impl->surface_desc.ddsCaps.dwCaps & DDSCAPS_3DDEVICE)) 1967 { 1968 WARN("Surface %p is not a render target.\n", target_impl); 1969 wined3d_mutex_unlock(); 1970 return DDERR_INVALIDCAPS; 1971 } 1972 1973 if (target_impl->surface_desc.ddsCaps.dwCaps & DDSCAPS_ZBUFFER) 1974 { 1975 WARN("Surface %p is a depth buffer.\n", target_impl); 1976 IUnknown_Release(device->rt_iface); 1977 device->rt_iface = (IUnknown *)target; 1978 wined3d_mutex_unlock(); 1979 return DDERR_INVALIDPIXELFORMAT; 1980 } 1981 1982 if (device->hw && !(target_impl->surface_desc.ddsCaps.dwCaps & DDSCAPS_VIDEOMEMORY)) 1983 { 1984 WARN("Surface %p is not in video memory.\n", target_impl); 1985 IDirectDrawSurface_AddRef(target); 1986 IUnknown_Release(device->rt_iface); 1987 device->rt_iface = (IUnknown *)target; 1988 wined3d_mutex_unlock(); 1989 return D3D_OK; 1990 } 1991 1992 hr = d3d_device_set_render_target(device, target_impl, (IUnknown *)target); 1993 wined3d_mutex_unlock(); 1994 return hr; 1995 } 1996 1997 /***************************************************************************** 1998 * IDirect3DDevice7::GetRenderTarget 1999 * 2000 * Returns the current render target. 2001 * This is handled locally, because the WineD3D render target's parent 2002 * is an IParent 2003 * 2004 * Version 2, 3 and 7 2005 * 2006 * Params: 2007 * RenderTarget: Address to store the surface interface pointer 2008 * 2009 * Returns: 2010 * D3D_OK on success 2011 * DDERR_INVALIDPARAMS if RenderTarget == NULL 2012 * 2013 *****************************************************************************/ 2014 static HRESULT WINAPI d3d_device7_GetRenderTarget(IDirect3DDevice7 *iface, IDirectDrawSurface7 **RenderTarget) 2015 { 2016 struct d3d_device *device = impl_from_IDirect3DDevice7(iface); 2017 HRESULT hr; 2018 2019 TRACE("iface %p, target %p.\n", iface, RenderTarget); 2020 2021 if(!RenderTarget) 2022 return DDERR_INVALIDPARAMS; 2023 2024 wined3d_mutex_lock(); 2025 hr = IUnknown_QueryInterface(device->rt_iface, &IID_IDirectDrawSurface7, (void **)RenderTarget); 2026 wined3d_mutex_unlock(); 2027 2028 return hr; 2029 } 2030 2031 static HRESULT WINAPI d3d_device3_GetRenderTarget(IDirect3DDevice3 *iface, IDirectDrawSurface4 **RenderTarget) 2032 { 2033 struct d3d_device *device = impl_from_IDirect3DDevice3(iface); 2034 IDirectDrawSurface7 *RenderTarget7; 2035 struct ddraw_surface *RenderTargetImpl; 2036 HRESULT hr; 2037 2038 TRACE("iface %p, target %p.\n", iface, RenderTarget); 2039 2040 if(!RenderTarget) 2041 return DDERR_INVALIDPARAMS; 2042 2043 hr = d3d_device7_GetRenderTarget(&device->IDirect3DDevice7_iface, &RenderTarget7); 2044 if(hr != D3D_OK) return hr; 2045 RenderTargetImpl = impl_from_IDirectDrawSurface7(RenderTarget7); 2046 *RenderTarget = &RenderTargetImpl->IDirectDrawSurface4_iface; 2047 IDirectDrawSurface4_AddRef(*RenderTarget); 2048 IDirectDrawSurface7_Release(RenderTarget7); 2049 return D3D_OK; 2050 } 2051 2052 static HRESULT WINAPI d3d_device2_GetRenderTarget(IDirect3DDevice2 *iface, IDirectDrawSurface **RenderTarget) 2053 { 2054 struct d3d_device *device = impl_from_IDirect3DDevice2(iface); 2055 IDirectDrawSurface7 *RenderTarget7; 2056 struct ddraw_surface *RenderTargetImpl; 2057 HRESULT hr; 2058 2059 TRACE("iface %p, target %p.\n", iface, RenderTarget); 2060 2061 if(!RenderTarget) 2062 return DDERR_INVALIDPARAMS; 2063 2064 hr = d3d_device7_GetRenderTarget(&device->IDirect3DDevice7_iface, &RenderTarget7); 2065 if(hr != D3D_OK) return hr; 2066 RenderTargetImpl = impl_from_IDirectDrawSurface7(RenderTarget7); 2067 *RenderTarget = &RenderTargetImpl->IDirectDrawSurface_iface; 2068 IDirectDrawSurface_AddRef(*RenderTarget); 2069 IDirectDrawSurface7_Release(RenderTarget7); 2070 return D3D_OK; 2071 } 2072 2073 /***************************************************************************** 2074 * IDirect3DDevice3::Begin 2075 * 2076 * Begins a description block of vertices. This is similar to glBegin() 2077 * and glEnd(). After a call to IDirect3DDevice3::End, the vertices 2078 * described with IDirect3DDevice::Vertex are drawn. 2079 * 2080 * Version 2 and 3 2081 * 2082 * Params: 2083 * PrimitiveType: The type of primitives to draw 2084 * VertexTypeDesc: A flexible vertex format description of the vertices 2085 * Flags: Some flags.. 2086 * 2087 * Returns: 2088 * D3D_OK on success 2089 * 2090 *****************************************************************************/ 2091 static HRESULT WINAPI d3d_device3_Begin(IDirect3DDevice3 *iface, 2092 D3DPRIMITIVETYPE primitive_type, DWORD fvf, DWORD flags) 2093 { 2094 struct d3d_device *device = impl_from_IDirect3DDevice3(iface); 2095 2096 TRACE("iface %p, primitive_type %#x, fvf %#x, flags %#x.\n", 2097 iface, primitive_type, fvf, flags); 2098 2099 wined3d_mutex_lock(); 2100 device->primitive_type = primitive_type; 2101 device->vertex_type = fvf; 2102 device->render_flags = flags; 2103 device->vertex_size = get_flexible_vertex_size(device->vertex_type); 2104 device->nb_vertices = 0; 2105 wined3d_mutex_unlock(); 2106 2107 return D3D_OK; 2108 } 2109 2110 static HRESULT WINAPI d3d_device2_Begin(IDirect3DDevice2 *iface, 2111 D3DPRIMITIVETYPE primitive_type, D3DVERTEXTYPE vertex_type, DWORD flags) 2112 { 2113 struct d3d_device *device = impl_from_IDirect3DDevice2(iface); 2114 DWORD fvf; 2115 2116 TRACE("iface %p, primitive_type %#x, vertex_type %#x, flags %#x.\n", 2117 iface, primitive_type, vertex_type, flags); 2118 2119 switch (vertex_type) 2120 { 2121 case D3DVT_VERTEX: fvf = D3DFVF_VERTEX; break; 2122 case D3DVT_LVERTEX: fvf = D3DFVF_LVERTEX; break; 2123 case D3DVT_TLVERTEX: fvf = D3DFVF_TLVERTEX; break; 2124 default: 2125 ERR("Unexpected vertex type %#x.\n", vertex_type); 2126 return DDERR_INVALIDPARAMS; /* Should never happen */ 2127 }; 2128 2129 return d3d_device3_Begin(&device->IDirect3DDevice3_iface, primitive_type, fvf, flags); 2130 } 2131 2132 /***************************************************************************** 2133 * IDirect3DDevice3::BeginIndexed 2134 * 2135 * Draws primitives based on vertices in a vertex array which are specified 2136 * by indices. 2137 * 2138 * Version 2 and 3 2139 * 2140 * Params: 2141 * PrimitiveType: Primitive type to draw 2142 * VertexType: A FVF description of the vertex format 2143 * Vertices: pointer to an array containing the vertices 2144 * NumVertices: The number of vertices in the vertex array 2145 * Flags: Some flags ... 2146 * 2147 * Returns: 2148 * D3D_OK, because it's a stub 2149 * 2150 *****************************************************************************/ 2151 static HRESULT WINAPI d3d_device3_BeginIndexed(IDirect3DDevice3 *iface, 2152 D3DPRIMITIVETYPE primitive_type, DWORD fvf, 2153 void *vertices, DWORD vertex_count, DWORD flags) 2154 { 2155 FIXME("iface %p, primitive_type %#x, fvf %#x, vertices %p, vertex_count %u, flags %#x stub!\n", 2156 iface, primitive_type, fvf, vertices, vertex_count, flags); 2157 2158 return D3D_OK; 2159 } 2160 2161 2162 static HRESULT WINAPI d3d_device2_BeginIndexed(IDirect3DDevice2 *iface, 2163 D3DPRIMITIVETYPE primitive_type, D3DVERTEXTYPE vertex_type, 2164 void *vertices, DWORD vertex_count, DWORD flags) 2165 { 2166 struct d3d_device *device = impl_from_IDirect3DDevice2(iface); 2167 DWORD fvf; 2168 2169 TRACE("iface %p, primitive_type %#x, vertex_type %#x, vertices %p, vertex_count %u, flags %#x stub!\n", 2170 iface, primitive_type, vertex_type, vertices, vertex_count, flags); 2171 2172 switch (vertex_type) 2173 { 2174 case D3DVT_VERTEX: fvf = D3DFVF_VERTEX; break; 2175 case D3DVT_LVERTEX: fvf = D3DFVF_LVERTEX; break; 2176 case D3DVT_TLVERTEX: fvf = D3DFVF_TLVERTEX; break; 2177 default: 2178 ERR("Unexpected vertex type %#x.\n", vertex_type); 2179 return DDERR_INVALIDPARAMS; /* Should never happen */ 2180 }; 2181 2182 return d3d_device3_BeginIndexed(&device->IDirect3DDevice3_iface, 2183 primitive_type, fvf, vertices, vertex_count, flags); 2184 } 2185 2186 /***************************************************************************** 2187 * IDirect3DDevice3::Vertex 2188 * 2189 * Draws a vertex as described by IDirect3DDevice3::Begin. It places all 2190 * drawn vertices in a vertex buffer. If the buffer is too small, its 2191 * size is increased. 2192 * 2193 * Version 2 and 3 2194 * 2195 * Params: 2196 * Vertex: Pointer to the vertex 2197 * 2198 * Returns: 2199 * D3D_OK, on success 2200 * DDERR_INVALIDPARAMS if Vertex is NULL 2201 * 2202 *****************************************************************************/ 2203 static HRESULT WINAPI d3d_device3_Vertex(IDirect3DDevice3 *iface, void *vertex) 2204 { 2205 struct d3d_device *device = impl_from_IDirect3DDevice3(iface); 2206 2207 TRACE("iface %p, vertex %p.\n", iface, vertex); 2208 2209 if (!vertex) 2210 return DDERR_INVALIDPARAMS; 2211 2212 wined3d_mutex_lock(); 2213 if ((device->nb_vertices + 1) * device->vertex_size > device->buffer_size) 2214 { 2215 BYTE *old_buffer; 2216 2217 device->buffer_size = device->buffer_size ? device->buffer_size * 2 : device->vertex_size * 3; 2218 old_buffer = device->sysmem_vertex_buffer; 2219 device->sysmem_vertex_buffer = heap_alloc(device->buffer_size); 2220 if (old_buffer) 2221 { 2222 memcpy(device->sysmem_vertex_buffer, old_buffer, device->nb_vertices * device->vertex_size); 2223 heap_free(old_buffer); 2224 } 2225 } 2226 2227 memcpy(device->sysmem_vertex_buffer + device->nb_vertices++ * device->vertex_size, vertex, device->vertex_size); 2228 wined3d_mutex_unlock(); 2229 2230 return D3D_OK; 2231 } 2232 2233 static HRESULT WINAPI d3d_device2_Vertex(IDirect3DDevice2 *iface, void *vertex) 2234 { 2235 struct d3d_device *device = impl_from_IDirect3DDevice2(iface); 2236 2237 TRACE("iface %p, vertex %p.\n", iface, vertex); 2238 2239 return d3d_device3_Vertex(&device->IDirect3DDevice3_iface, vertex); 2240 } 2241 2242 /***************************************************************************** 2243 * IDirect3DDevice3::Index 2244 * 2245 * Specifies an index to a vertex to be drawn. The vertex array has to 2246 * be specified with BeginIndexed first. 2247 * 2248 * Parameters: 2249 * VertexIndex: The index of the vertex to draw 2250 * 2251 * Returns: 2252 * D3D_OK because it's a stub 2253 * 2254 *****************************************************************************/ 2255 static HRESULT WINAPI d3d_device3_Index(IDirect3DDevice3 *iface, WORD index) 2256 { 2257 FIXME("iface %p, index %#x stub!\n", iface, index); 2258 2259 return D3D_OK; 2260 } 2261 2262 static HRESULT WINAPI d3d_device2_Index(IDirect3DDevice2 *iface, WORD index) 2263 { 2264 struct d3d_device *device = impl_from_IDirect3DDevice2(iface); 2265 2266 TRACE("iface %p, index %#x.\n", iface, index); 2267 2268 return d3d_device3_Index(&device->IDirect3DDevice3_iface, index); 2269 } 2270 2271 /***************************************************************************** 2272 * IDirect3DDevice7::GetRenderState 2273 * 2274 * Returns the value of a render state. The possible render states are 2275 * defined in include/d3dtypes.h 2276 * 2277 * Version 2, 3 and 7 2278 * 2279 * Params: 2280 * RenderStateType: Render state to return the current setting of 2281 * Value: Address to store the value at 2282 * 2283 * Returns: 2284 * D3D_OK on success, 2285 * DDERR_INVALIDPARAMS if Value == NULL 2286 * 2287 *****************************************************************************/ 2288 static HRESULT d3d_device7_GetRenderState(IDirect3DDevice7 *iface, 2289 D3DRENDERSTATETYPE state, DWORD *value) 2290 { 2291 struct d3d_device *device = impl_from_IDirect3DDevice7(iface); 2292 HRESULT hr = D3D_OK; 2293 2294 TRACE("iface %p, state %#x, value %p.\n", iface, state, value); 2295 2296 if (!value) 2297 return DDERR_INVALIDPARAMS; 2298 2299 wined3d_mutex_lock(); 2300 switch (state) 2301 { 2302 case D3DRENDERSTATE_TEXTUREMAG: 2303 { 2304 enum wined3d_texture_filter_type tex_mag; 2305 2306 tex_mag = wined3d_device_get_sampler_state(device->wined3d_device, 0, WINED3D_SAMP_MAG_FILTER); 2307 switch (tex_mag) 2308 { 2309 case WINED3D_TEXF_POINT: 2310 *value = D3DFILTER_NEAREST; 2311 break; 2312 case WINED3D_TEXF_LINEAR: 2313 *value = D3DFILTER_LINEAR; 2314 break; 2315 default: 2316 ERR("Unhandled texture mag %d !\n",tex_mag); 2317 *value = 0; 2318 } 2319 break; 2320 } 2321 2322 case D3DRENDERSTATE_TEXTUREMIN: 2323 { 2324 enum wined3d_texture_filter_type tex_min; 2325 enum wined3d_texture_filter_type tex_mip; 2326 2327 tex_min = wined3d_device_get_sampler_state(device->wined3d_device, 0, WINED3D_SAMP_MIN_FILTER); 2328 tex_mip = wined3d_device_get_sampler_state(device->wined3d_device, 0, WINED3D_SAMP_MIP_FILTER); 2329 switch (tex_min) 2330 { 2331 case WINED3D_TEXF_POINT: 2332 switch (tex_mip) 2333 { 2334 case WINED3D_TEXF_NONE: 2335 *value = D3DFILTER_NEAREST; 2336 break; 2337 case WINED3D_TEXF_POINT: 2338 *value = D3DFILTER_MIPNEAREST; 2339 break; 2340 case WINED3D_TEXF_LINEAR: 2341 *value = D3DFILTER_LINEARMIPNEAREST; 2342 break; 2343 default: 2344 ERR("Unhandled mip filter %#x.\n", tex_mip); 2345 *value = D3DFILTER_NEAREST; 2346 break; 2347 } 2348 break; 2349 case WINED3D_TEXF_LINEAR: 2350 switch (tex_mip) 2351 { 2352 case WINED3D_TEXF_NONE: 2353 *value = D3DFILTER_LINEAR; 2354 break; 2355 case WINED3D_TEXF_POINT: 2356 *value = D3DFILTER_MIPLINEAR; 2357 break; 2358 case WINED3D_TEXF_LINEAR: 2359 *value = D3DFILTER_LINEARMIPLINEAR; 2360 break; 2361 default: 2362 ERR("Unhandled mip filter %#x.\n", tex_mip); 2363 *value = D3DFILTER_LINEAR; 2364 break; 2365 } 2366 break; 2367 default: 2368 ERR("Unhandled texture min filter %#x.\n",tex_min); 2369 *value = D3DFILTER_NEAREST; 2370 break; 2371 } 2372 break; 2373 } 2374 2375 case D3DRENDERSTATE_TEXTUREADDRESS: 2376 case D3DRENDERSTATE_TEXTUREADDRESSU: 2377 *value = wined3d_device_get_sampler_state(device->wined3d_device, 0, WINED3D_SAMP_ADDRESS_U); 2378 break; 2379 case D3DRENDERSTATE_TEXTUREADDRESSV: 2380 *value = wined3d_device_get_sampler_state(device->wined3d_device, 0, WINED3D_SAMP_ADDRESS_V); 2381 break; 2382 2383 case D3DRENDERSTATE_BORDERCOLOR: 2384 FIXME("Unhandled render state D3DRENDERSTATE_BORDERCOLOR.\n"); 2385 hr = E_NOTIMPL; 2386 break; 2387 2388 case D3DRENDERSTATE_TEXTUREHANDLE: 2389 case D3DRENDERSTATE_TEXTUREMAPBLEND: 2390 WARN("Render state %#x is invalid in d3d7.\n", state); 2391 hr = DDERR_INVALIDPARAMS; 2392 break; 2393 2394 case D3DRENDERSTATE_ZBIAS: 2395 *value = wined3d_device_get_render_state(device->wined3d_device, WINED3D_RS_DEPTHBIAS); 2396 break; 2397 2398 default: 2399 if (state >= D3DRENDERSTATE_STIPPLEPATTERN00 2400 && state <= D3DRENDERSTATE_STIPPLEPATTERN31) 2401 { 2402 FIXME("Unhandled stipple pattern render state (%#x).\n", state); 2403 hr = E_NOTIMPL; 2404 break; 2405 } 2406 *value = wined3d_device_get_render_state(device->wined3d_device, state); 2407 } 2408 wined3d_mutex_unlock(); 2409 2410 return hr; 2411 } 2412 2413 static HRESULT WINAPI d3d_device7_GetRenderState_FPUSetup(IDirect3DDevice7 *iface, 2414 D3DRENDERSTATETYPE state, DWORD *value) 2415 { 2416 return d3d_device7_GetRenderState(iface, state, value); 2417 } 2418 2419 static HRESULT WINAPI d3d_device7_GetRenderState_FPUPreserve(IDirect3DDevice7 *iface, 2420 D3DRENDERSTATETYPE state, DWORD *value) 2421 { 2422 HRESULT hr; 2423 WORD old_fpucw; 2424 2425 old_fpucw = d3d_fpu_setup(); 2426 hr = d3d_device7_GetRenderState(iface, state, value); 2427 set_fpu_control_word(old_fpucw); 2428 2429 return hr; 2430 } 2431 2432 static HRESULT WINAPI d3d_device3_GetRenderState(IDirect3DDevice3 *iface, 2433 D3DRENDERSTATETYPE state, DWORD *value) 2434 { 2435 struct d3d_device *device = impl_from_IDirect3DDevice3(iface); 2436 2437 TRACE("iface %p, state %#x, value %p.\n", iface, state, value); 2438 2439 switch (state) 2440 { 2441 case D3DRENDERSTATE_TEXTUREHANDLE: 2442 { 2443 /* This state is wrapped to SetTexture in SetRenderState, so 2444 * it has to be wrapped to GetTexture here. */ 2445 struct wined3d_texture *tex = NULL; 2446 *value = 0; 2447 2448 wined3d_mutex_lock(); 2449 if ((tex = wined3d_device_get_texture(device->wined3d_device, 0))) 2450 { 2451 /* The parent of the texture is the IDirectDrawSurface7 2452 * interface of the ddraw surface. */ 2453 struct ddraw_texture *parent = wined3d_texture_get_parent(tex); 2454 if (parent) 2455 *value = parent->root->Handle; 2456 } 2457 wined3d_mutex_unlock(); 2458 2459 return D3D_OK; 2460 } 2461 2462 case D3DRENDERSTATE_TEXTUREMAPBLEND: 2463 { 2464 /* D3DRENDERSTATE_TEXTUREMAPBLEND is mapped to texture state stages in SetRenderState; reverse 2465 the mapping to get the value. */ 2466 DWORD colorop, colorarg1, colorarg2; 2467 DWORD alphaop, alphaarg1, alphaarg2; 2468 2469 wined3d_mutex_lock(); 2470 2471 device->legacyTextureBlending = TRUE; 2472 2473 colorop = wined3d_device_get_texture_stage_state(device->wined3d_device, 0, WINED3D_TSS_COLOR_OP); 2474 colorarg1 = wined3d_device_get_texture_stage_state(device->wined3d_device, 0, WINED3D_TSS_COLOR_ARG1); 2475 colorarg2 = wined3d_device_get_texture_stage_state(device->wined3d_device, 0, WINED3D_TSS_COLOR_ARG2); 2476 alphaop = wined3d_device_get_texture_stage_state(device->wined3d_device, 0, WINED3D_TSS_ALPHA_OP); 2477 alphaarg1 = wined3d_device_get_texture_stage_state(device->wined3d_device, 0, WINED3D_TSS_ALPHA_ARG1); 2478 alphaarg2 = wined3d_device_get_texture_stage_state(device->wined3d_device, 0, WINED3D_TSS_ALPHA_ARG2); 2479 2480 if (colorop == WINED3D_TOP_SELECT_ARG1 && colorarg1 == WINED3DTA_TEXTURE 2481 && alphaop == WINED3D_TOP_SELECT_ARG1 && alphaarg1 == WINED3DTA_TEXTURE) 2482 *value = D3DTBLEND_DECAL; 2483 else if (colorop == WINED3D_TOP_SELECT_ARG1 && colorarg1 == WINED3DTA_TEXTURE 2484 && alphaop == WINED3D_TOP_MODULATE 2485 && alphaarg1 == WINED3DTA_TEXTURE && alphaarg2 == WINED3DTA_CURRENT) 2486 *value = D3DTBLEND_DECALALPHA; 2487 else if (colorop == WINED3D_TOP_MODULATE 2488 && colorarg1 == WINED3DTA_TEXTURE && colorarg2 == WINED3DTA_CURRENT 2489 && alphaop == WINED3D_TOP_MODULATE 2490 && alphaarg1 == WINED3DTA_TEXTURE && alphaarg2 == WINED3DTA_CURRENT) 2491 *value = D3DTBLEND_MODULATEALPHA; 2492 else 2493 { 2494 struct wined3d_texture *tex = NULL; 2495 BOOL tex_alpha = FALSE; 2496 DDPIXELFORMAT ddfmt; 2497 2498 if ((tex = wined3d_device_get_texture(device->wined3d_device, 0))) 2499 { 2500 struct wined3d_resource_desc desc; 2501 2502 wined3d_resource_get_desc(wined3d_texture_get_resource(tex), &desc); 2503 ddfmt.dwSize = sizeof(ddfmt); 2504 ddrawformat_from_wined3dformat(&ddfmt, desc.format); 2505 if (ddfmt.u5.dwRGBAlphaBitMask) 2506 tex_alpha = TRUE; 2507 } 2508 2509 if (!(colorop == WINED3D_TOP_MODULATE 2510 && colorarg1 == WINED3DTA_TEXTURE && colorarg2 == WINED3DTA_CURRENT 2511 && alphaop == (tex_alpha ? WINED3D_TOP_SELECT_ARG1 : WINED3D_TOP_SELECT_ARG2) 2512 && alphaarg1 == WINED3DTA_TEXTURE && alphaarg2 == WINED3DTA_CURRENT)) 2513 ERR("Unexpected texture stage state setup, returning D3DTBLEND_MODULATE - likely erroneous.\n"); 2514 2515 *value = D3DTBLEND_MODULATE; 2516 } 2517 2518 wined3d_mutex_unlock(); 2519 2520 return D3D_OK; 2521 } 2522 2523 case D3DRENDERSTATE_LIGHTING: 2524 case D3DRENDERSTATE_NORMALIZENORMALS: 2525 case D3DRENDERSTATE_LOCALVIEWER: 2526 *value = 0xffffffff; 2527 return D3D_OK; 2528 2529 default: 2530 return IDirect3DDevice7_GetRenderState(&device->IDirect3DDevice7_iface, state, value); 2531 } 2532 } 2533 2534 static HRESULT WINAPI d3d_device2_GetRenderState(IDirect3DDevice2 *iface, 2535 D3DRENDERSTATETYPE state, DWORD *value) 2536 { 2537 struct d3d_device *device = impl_from_IDirect3DDevice2(iface); 2538 2539 TRACE("iface %p, state %#x, value %p.\n", iface, state, value); 2540 2541 return IDirect3DDevice3_GetRenderState(&device->IDirect3DDevice3_iface, state, value); 2542 } 2543 2544 /***************************************************************************** 2545 * IDirect3DDevice7::SetRenderState 2546 * 2547 * Sets a render state. The possible render states are defined in 2548 * include/d3dtypes.h 2549 * 2550 * Version 2, 3 and 7 2551 * 2552 * Params: 2553 * RenderStateType: State to set 2554 * Value: Value to assign to that state 2555 * 2556 *****************************************************************************/ 2557 static HRESULT d3d_device7_SetRenderState(IDirect3DDevice7 *iface, 2558 D3DRENDERSTATETYPE state, DWORD value) 2559 { 2560 struct d3d_device *device = impl_from_IDirect3DDevice7(iface); 2561 HRESULT hr = D3D_OK; 2562 2563 TRACE("iface %p, state %#x, value %#x.\n", iface, state, value); 2564 2565 wined3d_mutex_lock(); 2566 /* Some render states need special care */ 2567 switch (state) 2568 { 2569 /* 2570 * The ddraw texture filter mapping works like this: 2571 * D3DFILTER_NEAREST Point min/mag, no mip 2572 * D3DFILTER_MIPNEAREST Point min/mag, point mip 2573 * D3DFILTER_LINEARMIPNEAREST: Point min/mag, linear mip 2574 * 2575 * D3DFILTER_LINEAR Linear min/mag, no mip 2576 * D3DFILTER_MIPLINEAR Linear min/mag, point mip 2577 * D3DFILTER_LINEARMIPLINEAR Linear min/mag, linear mip 2578 * 2579 * This is the opposite of the GL naming convention, 2580 * D3DFILTER_LINEARMIPNEAREST corresponds to GL_NEAREST_MIPMAP_LINEAR. 2581 */ 2582 case D3DRENDERSTATE_TEXTUREMAG: 2583 { 2584 enum wined3d_texture_filter_type tex_mag; 2585 2586 switch (value) 2587 { 2588 case D3DFILTER_NEAREST: 2589 case D3DFILTER_MIPNEAREST: 2590 case D3DFILTER_LINEARMIPNEAREST: 2591 tex_mag = WINED3D_TEXF_POINT; 2592 break; 2593 case D3DFILTER_LINEAR: 2594 case D3DFILTER_MIPLINEAR: 2595 case D3DFILTER_LINEARMIPLINEAR: 2596 tex_mag = WINED3D_TEXF_LINEAR; 2597 break; 2598 default: 2599 tex_mag = WINED3D_TEXF_POINT; 2600 FIXME("Unhandled texture mag %#x.\n", value); 2601 break; 2602 } 2603 2604 wined3d_device_set_sampler_state(device->wined3d_device, 0, WINED3D_SAMP_MAG_FILTER, tex_mag); 2605 break; 2606 } 2607 2608 case D3DRENDERSTATE_TEXTUREMIN: 2609 { 2610 enum wined3d_texture_filter_type tex_min; 2611 enum wined3d_texture_filter_type tex_mip; 2612 2613 switch (value) 2614 { 2615 case D3DFILTER_NEAREST: 2616 tex_min = WINED3D_TEXF_POINT; 2617 tex_mip = WINED3D_TEXF_NONE; 2618 break; 2619 case D3DFILTER_LINEAR: 2620 tex_min = WINED3D_TEXF_LINEAR; 2621 tex_mip = WINED3D_TEXF_NONE; 2622 break; 2623 case D3DFILTER_MIPNEAREST: 2624 tex_min = WINED3D_TEXF_POINT; 2625 tex_mip = WINED3D_TEXF_POINT; 2626 break; 2627 case D3DFILTER_MIPLINEAR: 2628 tex_min = WINED3D_TEXF_LINEAR; 2629 tex_mip = WINED3D_TEXF_POINT; 2630 break; 2631 case D3DFILTER_LINEARMIPNEAREST: 2632 tex_min = WINED3D_TEXF_POINT; 2633 tex_mip = WINED3D_TEXF_LINEAR; 2634 break; 2635 case D3DFILTER_LINEARMIPLINEAR: 2636 tex_min = WINED3D_TEXF_LINEAR; 2637 tex_mip = WINED3D_TEXF_LINEAR; 2638 break; 2639 2640 default: 2641 FIXME("Unhandled texture min %#x.\n",value); 2642 tex_min = WINED3D_TEXF_POINT; 2643 tex_mip = WINED3D_TEXF_NONE; 2644 break; 2645 } 2646 2647 wined3d_device_set_sampler_state(device->wined3d_device, 2648 0, WINED3D_SAMP_MIP_FILTER, tex_mip); 2649 wined3d_device_set_sampler_state(device->wined3d_device, 2650 0, WINED3D_SAMP_MIN_FILTER, tex_min); 2651 break; 2652 } 2653 2654 case D3DRENDERSTATE_TEXTUREADDRESS: 2655 wined3d_device_set_sampler_state(device->wined3d_device, 2656 0, WINED3D_SAMP_ADDRESS_V, value); 2657 /* Drop through */ 2658 case D3DRENDERSTATE_TEXTUREADDRESSU: 2659 wined3d_device_set_sampler_state(device->wined3d_device, 2660 0, WINED3D_SAMP_ADDRESS_U, value); 2661 break; 2662 case D3DRENDERSTATE_TEXTUREADDRESSV: 2663 wined3d_device_set_sampler_state(device->wined3d_device, 2664 0, WINED3D_SAMP_ADDRESS_V, value); 2665 break; 2666 2667 case D3DRENDERSTATE_BORDERCOLOR: 2668 /* This should probably just forward to the corresponding sampler 2669 * state. Needs tests. */ 2670 FIXME("Unhandled render state D3DRENDERSTATE_BORDERCOLOR.\n"); 2671 hr = E_NOTIMPL; 2672 break; 2673 2674 case D3DRENDERSTATE_TEXTUREHANDLE: 2675 case D3DRENDERSTATE_TEXTUREMAPBLEND: 2676 WARN("Render state %#x is invalid in d3d7.\n", state); 2677 hr = DDERR_INVALIDPARAMS; 2678 break; 2679 2680 case D3DRENDERSTATE_ZBIAS: 2681 wined3d_device_set_render_state(device->wined3d_device, WINED3D_RS_DEPTHBIAS, value); 2682 break; 2683 2684 default: 2685 if (state >= D3DRENDERSTATE_STIPPLEPATTERN00 2686 && state <= D3DRENDERSTATE_STIPPLEPATTERN31) 2687 { 2688 FIXME("Unhandled stipple pattern render state (%#x).\n", state); 2689 hr = E_NOTIMPL; 2690 break; 2691 } 2692 2693 wined3d_device_set_render_state(device->wined3d_device, state, value); 2694 break; 2695 } 2696 wined3d_mutex_unlock(); 2697 2698 return hr; 2699 } 2700 2701 static HRESULT WINAPI d3d_device7_SetRenderState_FPUSetup(IDirect3DDevice7 *iface, 2702 D3DRENDERSTATETYPE state, DWORD value) 2703 { 2704 return d3d_device7_SetRenderState(iface, state, value); 2705 } 2706 2707 static HRESULT WINAPI d3d_device7_SetRenderState_FPUPreserve(IDirect3DDevice7 *iface, 2708 D3DRENDERSTATETYPE state, DWORD value) 2709 { 2710 HRESULT hr; 2711 WORD old_fpucw; 2712 2713 old_fpucw = d3d_fpu_setup(); 2714 hr = d3d_device7_SetRenderState(iface, state, value); 2715 set_fpu_control_word(old_fpucw); 2716 2717 return hr; 2718 } 2719 2720 static HRESULT WINAPI d3d_device3_SetRenderState(IDirect3DDevice3 *iface, 2721 D3DRENDERSTATETYPE state, DWORD value) 2722 { 2723 /* Note about D3DRENDERSTATE_TEXTUREMAPBLEND implementation: most of values 2724 for this state can be directly mapped to texture stage colorop and alphaop, but 2725 D3DTBLEND_MODULATE is tricky: it uses alpha from texture when available and alpha 2726 from diffuse otherwise. So changing the texture must be monitored in SetTexture to modify 2727 alphaarg when needed. 2728 2729 Aliens vs Predator 1 depends on accurate D3DTBLEND_MODULATE emulation 2730 2731 Legacy texture blending (TEXTUREMAPBLEND) and texture stage states: directx6 docs state that 2732 TEXTUREMAPBLEND is deprecated, yet can still be used. Games must not use both or results 2733 are undefined. D3DTBLEND_MODULATE mode in particular is dependent on texture pixel format and 2734 requires fixup of stage 0 texture states when texture changes, but this fixup can interfere 2735 with games not using this deprecated state. So a flag 'legacyTextureBlending' has to be kept 2736 in device - TRUE if the app is using TEXTUREMAPBLEND. 2737 2738 Tests show that setting TEXTUREMAPBLEND on native doesn't seem to change values returned by 2739 GetTextureStageState and vice versa. Not so on Wine, but it is 'undefined' anyway so, probably, ok, 2740 unless some broken game will be found that cares. */ 2741 2742 struct d3d_device *device = impl_from_IDirect3DDevice3(iface); 2743 HRESULT hr; 2744 2745 TRACE("iface %p, state %#x, value %#x.\n", iface, state, value); 2746 2747 if (state >= D3DSTATE_OVERRIDE_BIAS) 2748 { 2749 WARN("Unhandled state %#x.\n", state); 2750 return DDERR_INVALIDPARAMS; 2751 } 2752 2753 wined3d_mutex_lock(); 2754 2755 switch (state) 2756 { 2757 case D3DRENDERSTATE_TEXTUREHANDLE: 2758 { 2759 struct ddraw_surface *surf; 2760 2761 if (value == 0) 2762 { 2763 hr = wined3d_device_set_texture(device->wined3d_device, 0, NULL); 2764 break; 2765 } 2766 2767 surf = ddraw_get_object(&device->handle_table, value - 1, DDRAW_HANDLE_SURFACE); 2768 if (!surf) 2769 { 2770 WARN("Invalid texture handle.\n"); 2771 hr = DDERR_INVALIDPARAMS; 2772 break; 2773 } 2774 2775 hr = IDirect3DDevice3_SetTexture(iface, 0, &surf->IDirect3DTexture2_iface); 2776 break; 2777 } 2778 2779 case D3DRENDERSTATE_TEXTUREMAPBLEND: 2780 { 2781 device->legacyTextureBlending = TRUE; 2782 2783 switch (value) 2784 { 2785 case D3DTBLEND_MODULATE: 2786 { 2787 struct wined3d_texture *tex = NULL; 2788 BOOL tex_alpha = FALSE; 2789 DDPIXELFORMAT ddfmt; 2790 2791 if ((tex = wined3d_device_get_texture(device->wined3d_device, 0))) 2792 { 2793 struct wined3d_resource_desc desc; 2794 2795 wined3d_resource_get_desc(wined3d_texture_get_resource(tex), &desc); 2796 ddfmt.dwSize = sizeof(ddfmt); 2797 ddrawformat_from_wined3dformat(&ddfmt, desc.format); 2798 if (ddfmt.u5.dwRGBAlphaBitMask) 2799 tex_alpha = TRUE; 2800 } 2801 2802 if (tex_alpha) 2803 wined3d_device_set_texture_stage_state(device->wined3d_device, 2804 0, WINED3D_TSS_ALPHA_OP, WINED3D_TOP_SELECT_ARG1); 2805 else 2806 wined3d_device_set_texture_stage_state(device->wined3d_device, 2807 0, WINED3D_TSS_ALPHA_OP, WINED3D_TOP_SELECT_ARG2); 2808 wined3d_device_set_texture_stage_state(device->wined3d_device, 2809 0, WINED3D_TSS_ALPHA_ARG1, WINED3DTA_TEXTURE); 2810 wined3d_device_set_texture_stage_state(device->wined3d_device, 2811 0, WINED3D_TSS_ALPHA_ARG2, WINED3DTA_CURRENT); 2812 wined3d_device_set_texture_stage_state(device->wined3d_device, 2813 0, WINED3D_TSS_COLOR_ARG1, WINED3DTA_TEXTURE); 2814 wined3d_device_set_texture_stage_state(device->wined3d_device, 2815 0, WINED3D_TSS_COLOR_ARG2, WINED3DTA_CURRENT); 2816 wined3d_device_set_texture_stage_state(device->wined3d_device, 2817 0, WINED3D_TSS_COLOR_OP, WINED3D_TOP_MODULATE); 2818 break; 2819 } 2820 2821 case D3DTBLEND_ADD: 2822 wined3d_device_set_texture_stage_state(device->wined3d_device, 2823 0, WINED3D_TSS_COLOR_OP, WINED3D_TOP_ADD); 2824 wined3d_device_set_texture_stage_state(device->wined3d_device, 2825 0, WINED3D_TSS_COLOR_ARG1, WINED3DTA_TEXTURE); 2826 wined3d_device_set_texture_stage_state(device->wined3d_device, 2827 0, WINED3D_TSS_COLOR_ARG2, WINED3DTA_CURRENT); 2828 wined3d_device_set_texture_stage_state(device->wined3d_device, 2829 0, WINED3D_TSS_ALPHA_OP, WINED3D_TOP_SELECT_ARG2); 2830 wined3d_device_set_texture_stage_state(device->wined3d_device, 2831 0, WINED3D_TSS_ALPHA_ARG2, WINED3DTA_CURRENT); 2832 break; 2833 2834 case D3DTBLEND_MODULATEALPHA: 2835 wined3d_device_set_texture_stage_state(device->wined3d_device, 2836 0, WINED3D_TSS_COLOR_ARG1, WINED3DTA_TEXTURE); 2837 wined3d_device_set_texture_stage_state(device->wined3d_device, 2838 0, WINED3D_TSS_ALPHA_ARG1, WINED3DTA_TEXTURE); 2839 wined3d_device_set_texture_stage_state(device->wined3d_device, 2840 0, WINED3D_TSS_COLOR_ARG2, WINED3DTA_CURRENT); 2841 wined3d_device_set_texture_stage_state(device->wined3d_device, 2842 0, WINED3D_TSS_ALPHA_ARG2, WINED3DTA_CURRENT); 2843 wined3d_device_set_texture_stage_state(device->wined3d_device, 2844 0, WINED3D_TSS_COLOR_OP, WINED3D_TOP_MODULATE); 2845 wined3d_device_set_texture_stage_state(device->wined3d_device, 2846 0, WINED3D_TSS_ALPHA_OP, WINED3D_TOP_MODULATE); 2847 break; 2848 2849 case D3DTBLEND_COPY: 2850 case D3DTBLEND_DECAL: 2851 wined3d_device_set_texture_stage_state(device->wined3d_device, 2852 0, WINED3D_TSS_COLOR_ARG1, WINED3DTA_TEXTURE); 2853 wined3d_device_set_texture_stage_state(device->wined3d_device, 2854 0, WINED3D_TSS_ALPHA_ARG1, WINED3DTA_TEXTURE); 2855 wined3d_device_set_texture_stage_state(device->wined3d_device, 2856 0, WINED3D_TSS_COLOR_OP, WINED3D_TOP_SELECT_ARG1); 2857 wined3d_device_set_texture_stage_state(device->wined3d_device, 2858 0, WINED3D_TSS_ALPHA_OP, WINED3D_TOP_SELECT_ARG1); 2859 break; 2860 2861 case D3DTBLEND_DECALALPHA: 2862 wined3d_device_set_texture_stage_state(device->wined3d_device, 2863 0, WINED3D_TSS_COLOR_OP, WINED3D_TOP_BLEND_TEXTURE_ALPHA); 2864 wined3d_device_set_texture_stage_state(device->wined3d_device, 2865 0, WINED3D_TSS_COLOR_ARG1, WINED3DTA_TEXTURE); 2866 wined3d_device_set_texture_stage_state(device->wined3d_device, 2867 0, WINED3D_TSS_COLOR_ARG2, WINED3DTA_CURRENT); 2868 wined3d_device_set_texture_stage_state(device->wined3d_device, 2869 0, WINED3D_TSS_ALPHA_OP, WINED3D_TOP_SELECT_ARG2); 2870 wined3d_device_set_texture_stage_state(device->wined3d_device, 2871 0, WINED3D_TSS_ALPHA_ARG2, WINED3DTA_CURRENT); 2872 break; 2873 2874 default: 2875 FIXME("Unhandled texture environment %#x.\n", value); 2876 } 2877 2878 hr = D3D_OK; 2879 break; 2880 } 2881 2882 case D3DRENDERSTATE_LIGHTING: 2883 case D3DRENDERSTATE_NORMALIZENORMALS: 2884 case D3DRENDERSTATE_LOCALVIEWER: 2885 hr = D3D_OK; 2886 break; 2887 2888 default: 2889 hr = IDirect3DDevice7_SetRenderState(&device->IDirect3DDevice7_iface, state, value); 2890 break; 2891 } 2892 wined3d_mutex_unlock(); 2893 2894 return hr; 2895 } 2896 2897 static HRESULT WINAPI d3d_device2_SetRenderState(IDirect3DDevice2 *iface, 2898 D3DRENDERSTATETYPE state, DWORD value) 2899 { 2900 struct d3d_device *device = impl_from_IDirect3DDevice2(iface); 2901 2902 TRACE("iface %p, state %#x, value %#x.\n", iface, state, value); 2903 2904 return IDirect3DDevice3_SetRenderState(&device->IDirect3DDevice3_iface, state, value); 2905 } 2906 2907 /***************************************************************************** 2908 * Direct3DDevice3::SetLightState 2909 * 2910 * Sets a light state for Direct3DDevice3 and Direct3DDevice2. The 2911 * light states are forwarded to Direct3DDevice7 render states 2912 * 2913 * Version 2 and 3 2914 * 2915 * Params: 2916 * LightStateType: The light state to change 2917 * Value: The value to assign to that light state 2918 * 2919 * Returns: 2920 * D3D_OK on success 2921 * DDERR_INVALIDPARAMS if the parameters were incorrect 2922 * Also check IDirect3DDevice7::SetRenderState 2923 * 2924 *****************************************************************************/ 2925 static HRESULT WINAPI d3d_device3_SetLightState(IDirect3DDevice3 *iface, 2926 D3DLIGHTSTATETYPE state, DWORD value) 2927 { 2928 struct d3d_device *device = impl_from_IDirect3DDevice3(iface); 2929 HRESULT hr; 2930 2931 TRACE("iface %p, state %#x, value %#x.\n", iface, state, value); 2932 2933 if (!state || (state > D3DLIGHTSTATE_COLORVERTEX)) 2934 { 2935 TRACE("Unexpected Light State Type\n"); 2936 return DDERR_INVALIDPARAMS; 2937 } 2938 2939 wined3d_mutex_lock(); 2940 if (state == D3DLIGHTSTATE_MATERIAL) 2941 { 2942 if (value) 2943 { 2944 struct d3d_material *m; 2945 2946 if (!(m = ddraw_get_object(&device->handle_table, value - 1, DDRAW_HANDLE_MATERIAL))) 2947 { 2948 WARN("Invalid material handle.\n"); 2949 wined3d_mutex_unlock(); 2950 return DDERR_INVALIDPARAMS; 2951 } 2952 2953 material_activate(m); 2954 } 2955 2956 device->material = value; 2957 } 2958 else if (state == D3DLIGHTSTATE_COLORMODEL) 2959 { 2960 switch (value) 2961 { 2962 case D3DCOLOR_MONO: 2963 ERR("DDCOLOR_MONO should not happen!\n"); 2964 break; 2965 case D3DCOLOR_RGB: 2966 /* We are already in this mode */ 2967 TRACE("Setting color model to RGB (no-op).\n"); 2968 break; 2969 default: 2970 ERR("Unknown color model!\n"); 2971 wined3d_mutex_unlock(); 2972 return DDERR_INVALIDPARAMS; 2973 } 2974 } 2975 else 2976 { 2977 D3DRENDERSTATETYPE rs; 2978 switch (state) 2979 { 2980 case D3DLIGHTSTATE_AMBIENT: /* 2 */ 2981 rs = D3DRENDERSTATE_AMBIENT; 2982 break; 2983 case D3DLIGHTSTATE_FOGMODE: /* 4 */ 2984 rs = D3DRENDERSTATE_FOGVERTEXMODE; 2985 break; 2986 case D3DLIGHTSTATE_FOGSTART: /* 5 */ 2987 rs = D3DRENDERSTATE_FOGSTART; 2988 break; 2989 case D3DLIGHTSTATE_FOGEND: /* 6 */ 2990 rs = D3DRENDERSTATE_FOGEND; 2991 break; 2992 case D3DLIGHTSTATE_FOGDENSITY: /* 7 */ 2993 rs = D3DRENDERSTATE_FOGDENSITY; 2994 break; 2995 case D3DLIGHTSTATE_COLORVERTEX: /* 8 */ 2996 rs = D3DRENDERSTATE_COLORVERTEX; 2997 break; 2998 default: 2999 FIXME("Unhandled D3DLIGHTSTATETYPE %#x.\n", state); 3000 wined3d_mutex_unlock(); 3001 return DDERR_INVALIDPARAMS; 3002 } 3003 3004 hr = IDirect3DDevice7_SetRenderState(&device->IDirect3DDevice7_iface, rs, value); 3005 wined3d_mutex_unlock(); 3006 return hr; 3007 } 3008 wined3d_mutex_unlock(); 3009 3010 return D3D_OK; 3011 } 3012 3013 static HRESULT WINAPI d3d_device2_SetLightState(IDirect3DDevice2 *iface, 3014 D3DLIGHTSTATETYPE state, DWORD value) 3015 { 3016 struct d3d_device *device = impl_from_IDirect3DDevice2(iface); 3017 3018 TRACE("iface %p, state %#x, value %#x.\n", iface, state, value); 3019 3020 return d3d_device3_SetLightState(&device->IDirect3DDevice3_iface, state, value); 3021 } 3022 3023 /***************************************************************************** 3024 * IDirect3DDevice3::GetLightState 3025 * 3026 * Returns the current setting of a light state. The state is read from 3027 * the Direct3DDevice7 render state. 3028 * 3029 * Version 2 and 3 3030 * 3031 * Params: 3032 * LightStateType: The light state to return 3033 * Value: The address to store the light state setting at 3034 * 3035 * Returns: 3036 * D3D_OK on success 3037 * DDDERR_INVALIDPARAMS if the parameters were incorrect 3038 * Also see IDirect3DDevice7::GetRenderState 3039 * 3040 *****************************************************************************/ 3041 static HRESULT WINAPI d3d_device3_GetLightState(IDirect3DDevice3 *iface, 3042 D3DLIGHTSTATETYPE state, DWORD *value) 3043 { 3044 struct d3d_device *device = impl_from_IDirect3DDevice3(iface); 3045 HRESULT hr; 3046 3047 TRACE("iface %p, state %#x, value %p.\n", iface, state, value); 3048 3049 if (!state || (state > D3DLIGHTSTATE_COLORVERTEX)) 3050 { 3051 TRACE("Unexpected Light State Type\n"); 3052 return DDERR_INVALIDPARAMS; 3053 } 3054 3055 if (!value) 3056 return DDERR_INVALIDPARAMS; 3057 3058 wined3d_mutex_lock(); 3059 if (state == D3DLIGHTSTATE_MATERIAL) 3060 { 3061 *value = device->material; 3062 } 3063 else if (state == D3DLIGHTSTATE_COLORMODEL) 3064 { 3065 *value = D3DCOLOR_RGB; 3066 } 3067 else 3068 { 3069 D3DRENDERSTATETYPE rs; 3070 switch (state) 3071 { 3072 case D3DLIGHTSTATE_AMBIENT: /* 2 */ 3073 rs = D3DRENDERSTATE_AMBIENT; 3074 break; 3075 case D3DLIGHTSTATE_FOGMODE: /* 4 */ 3076 rs = D3DRENDERSTATE_FOGVERTEXMODE; 3077 break; 3078 case D3DLIGHTSTATE_FOGSTART: /* 5 */ 3079 rs = D3DRENDERSTATE_FOGSTART; 3080 break; 3081 case D3DLIGHTSTATE_FOGEND: /* 6 */ 3082 rs = D3DRENDERSTATE_FOGEND; 3083 break; 3084 case D3DLIGHTSTATE_FOGDENSITY: /* 7 */ 3085 rs = D3DRENDERSTATE_FOGDENSITY; 3086 break; 3087 case D3DLIGHTSTATE_COLORVERTEX: /* 8 */ 3088 rs = D3DRENDERSTATE_COLORVERTEX; 3089 break; 3090 default: 3091 FIXME("Unhandled D3DLIGHTSTATETYPE %#x.\n", state); 3092 wined3d_mutex_unlock(); 3093 return DDERR_INVALIDPARAMS; 3094 } 3095 3096 hr = IDirect3DDevice7_GetRenderState(&device->IDirect3DDevice7_iface, rs, value); 3097 wined3d_mutex_unlock(); 3098 return hr; 3099 } 3100 wined3d_mutex_unlock(); 3101 3102 return D3D_OK; 3103 } 3104 3105 static HRESULT WINAPI d3d_device2_GetLightState(IDirect3DDevice2 *iface, 3106 D3DLIGHTSTATETYPE state, DWORD *value) 3107 { 3108 struct d3d_device *device = impl_from_IDirect3DDevice2(iface); 3109 3110 TRACE("iface %p, state %#x, value %p.\n", iface, state, value); 3111 3112 return d3d_device3_GetLightState(&device->IDirect3DDevice3_iface, state, value); 3113 } 3114 3115 /***************************************************************************** 3116 * IDirect3DDevice7::SetTransform 3117 * 3118 * Assigns a D3DMATRIX to a transform type. The transform types are defined 3119 * in include/d3dtypes.h. 3120 * The D3DTRANSFORMSTATE_WORLD (=1) is translated to D3DTS_WORLDMATRIX(0) 3121 * (=255) for wined3d, because the 1 transform state was removed in d3d8 3122 * and WineD3D already understands the replacement D3DTS_WORLDMATRIX(0) 3123 * 3124 * Version 2, 3 and 7 3125 * 3126 * Params: 3127 * TransformStateType: transform state to set 3128 * Matrix: Matrix to assign to the state 3129 * 3130 * Returns: 3131 * D3D_OK on success 3132 * DDERR_INVALIDPARAMS if Matrix == NULL 3133 * 3134 *****************************************************************************/ 3135 static HRESULT d3d_device7_SetTransform(IDirect3DDevice7 *iface, 3136 D3DTRANSFORMSTATETYPE state, D3DMATRIX *matrix) 3137 { 3138 struct d3d_device *device = impl_from_IDirect3DDevice7(iface); 3139 enum wined3d_transform_state wined3d_state; 3140 3141 TRACE("iface %p, state %#x, matrix %p.\n", iface, state, matrix); 3142 3143 switch (state) 3144 { 3145 case D3DTRANSFORMSTATE_WORLD: 3146 wined3d_state = WINED3D_TS_WORLD_MATRIX(0); 3147 break; 3148 case D3DTRANSFORMSTATE_WORLD1: 3149 wined3d_state = WINED3D_TS_WORLD_MATRIX(1); 3150 break; 3151 case D3DTRANSFORMSTATE_WORLD2: 3152 wined3d_state = WINED3D_TS_WORLD_MATRIX(2); 3153 break; 3154 case D3DTRANSFORMSTATE_WORLD3: 3155 wined3d_state = WINED3D_TS_WORLD_MATRIX(3); 3156 break; 3157 default: 3158 wined3d_state = state; 3159 } 3160 3161 if (!matrix) 3162 return DDERR_INVALIDPARAMS; 3163 3164 /* Note: D3DMATRIX is compatible with struct wined3d_matrix. */ 3165 wined3d_mutex_lock(); 3166 wined3d_device_set_transform(device->wined3d_device, wined3d_state, (struct wined3d_matrix *)matrix); 3167 wined3d_mutex_unlock(); 3168 3169 return D3D_OK; 3170 } 3171 3172 static HRESULT WINAPI d3d_device7_SetTransform_FPUSetup(IDirect3DDevice7 *iface, 3173 D3DTRANSFORMSTATETYPE state, D3DMATRIX *matrix) 3174 { 3175 return d3d_device7_SetTransform(iface, state, matrix); 3176 } 3177 3178 static HRESULT WINAPI d3d_device7_SetTransform_FPUPreserve(IDirect3DDevice7 *iface, 3179 D3DTRANSFORMSTATETYPE state, D3DMATRIX *matrix) 3180 { 3181 HRESULT hr; 3182 WORD old_fpucw; 3183 3184 old_fpucw = d3d_fpu_setup(); 3185 hr = d3d_device7_SetTransform(iface, state, matrix); 3186 set_fpu_control_word(old_fpucw); 3187 3188 return hr; 3189 } 3190 3191 static HRESULT WINAPI d3d_device3_SetTransform(IDirect3DDevice3 *iface, 3192 D3DTRANSFORMSTATETYPE state, D3DMATRIX *matrix) 3193 { 3194 struct d3d_device *device = impl_from_IDirect3DDevice3(iface); 3195 3196 TRACE("iface %p, state %#x, matrix %p.\n", iface, state, matrix); 3197 3198 if (!matrix) 3199 return DDERR_INVALIDPARAMS; 3200 3201 if (state == D3DTRANSFORMSTATE_PROJECTION) 3202 { 3203 D3DMATRIX projection; 3204 3205 wined3d_mutex_lock(); 3206 multiply_matrix(&projection, &device->legacy_clipspace, matrix); 3207 wined3d_device_set_transform(device->wined3d_device, 3208 WINED3D_TS_PROJECTION, (struct wined3d_matrix *)&projection); 3209 device->legacy_projection = *matrix; 3210 wined3d_mutex_unlock(); 3211 3212 return D3D_OK; 3213 } 3214 3215 return IDirect3DDevice7_SetTransform(&device->IDirect3DDevice7_iface, state, matrix); 3216 } 3217 3218 static HRESULT WINAPI d3d_device2_SetTransform(IDirect3DDevice2 *iface, 3219 D3DTRANSFORMSTATETYPE state, D3DMATRIX *matrix) 3220 { 3221 struct d3d_device *device = impl_from_IDirect3DDevice2(iface); 3222 3223 TRACE("iface %p, state %#x, matrix %p.\n", iface, state, matrix); 3224 3225 return IDirect3DDevice3_SetTransform(&device->IDirect3DDevice3_iface, state, matrix); 3226 } 3227 3228 /***************************************************************************** 3229 * IDirect3DDevice7::GetTransform 3230 * 3231 * Returns the matrix assigned to a transform state 3232 * D3DTRANSFORMSTATE_WORLD is translated to D3DTS_WORLDMATRIX(0), see 3233 * SetTransform 3234 * 3235 * Params: 3236 * TransformStateType: State to read the matrix from 3237 * Matrix: Address to store the matrix at 3238 * 3239 * Returns: 3240 * D3D_OK on success 3241 * DDERR_INVALIDPARAMS if Matrix == NULL 3242 * 3243 *****************************************************************************/ 3244 static HRESULT d3d_device7_GetTransform(IDirect3DDevice7 *iface, 3245 D3DTRANSFORMSTATETYPE state, D3DMATRIX *matrix) 3246 { 3247 struct d3d_device *device = impl_from_IDirect3DDevice7(iface); 3248 enum wined3d_transform_state wined3d_state; 3249 3250 TRACE("iface %p, state %#x, matrix %p.\n", iface, state, matrix); 3251 3252 switch (state) 3253 { 3254 case D3DTRANSFORMSTATE_WORLD: 3255 wined3d_state = WINED3D_TS_WORLD_MATRIX(0); 3256 break; 3257 case D3DTRANSFORMSTATE_WORLD1: 3258 wined3d_state = WINED3D_TS_WORLD_MATRIX(1); 3259 break; 3260 case D3DTRANSFORMSTATE_WORLD2: 3261 wined3d_state = WINED3D_TS_WORLD_MATRIX(2); 3262 break; 3263 case D3DTRANSFORMSTATE_WORLD3: 3264 wined3d_state = WINED3D_TS_WORLD_MATRIX(3); 3265 break; 3266 default: 3267 wined3d_state = state; 3268 } 3269 3270 if (!matrix) 3271 return DDERR_INVALIDPARAMS; 3272 3273 /* Note: D3DMATRIX is compatible with struct wined3d_matrix. */ 3274 wined3d_mutex_lock(); 3275 wined3d_device_get_transform(device->wined3d_device, wined3d_state, (struct wined3d_matrix *)matrix); 3276 wined3d_mutex_unlock(); 3277 3278 return D3D_OK; 3279 } 3280 3281 static HRESULT WINAPI d3d_device7_GetTransform_FPUSetup(IDirect3DDevice7 *iface, 3282 D3DTRANSFORMSTATETYPE state, D3DMATRIX *matrix) 3283 { 3284 return d3d_device7_GetTransform(iface, state, matrix); 3285 } 3286 3287 static HRESULT WINAPI d3d_device7_GetTransform_FPUPreserve(IDirect3DDevice7 *iface, 3288 D3DTRANSFORMSTATETYPE state, D3DMATRIX *matrix) 3289 { 3290 HRESULT hr; 3291 WORD old_fpucw; 3292 3293 old_fpucw = d3d_fpu_setup(); 3294 hr = d3d_device7_GetTransform(iface, state, matrix); 3295 set_fpu_control_word(old_fpucw); 3296 3297 return hr; 3298 } 3299 3300 static HRESULT WINAPI d3d_device3_GetTransform(IDirect3DDevice3 *iface, 3301 D3DTRANSFORMSTATETYPE state, D3DMATRIX *matrix) 3302 { 3303 struct d3d_device *device = impl_from_IDirect3DDevice3(iface); 3304 3305 TRACE("iface %p, state %#x, matrix %p.\n", iface, state, matrix); 3306 3307 if (!matrix) 3308 return DDERR_INVALIDPARAMS; 3309 3310 if (state == D3DTRANSFORMSTATE_PROJECTION) 3311 { 3312 wined3d_mutex_lock(); 3313 *matrix = device->legacy_projection; 3314 wined3d_mutex_unlock(); 3315 return DD_OK; 3316 } 3317 3318 return IDirect3DDevice7_GetTransform(&device->IDirect3DDevice7_iface, state, matrix); 3319 } 3320 3321 static HRESULT WINAPI d3d_device2_GetTransform(IDirect3DDevice2 *iface, 3322 D3DTRANSFORMSTATETYPE state, D3DMATRIX *matrix) 3323 { 3324 struct d3d_device *device = impl_from_IDirect3DDevice2(iface); 3325 3326 TRACE("iface %p, state %#x, matrix %p.\n", iface, state, matrix); 3327 3328 return IDirect3DDevice3_GetTransform(&device->IDirect3DDevice3_iface, state, matrix); 3329 } 3330 3331 /***************************************************************************** 3332 * IDirect3DDevice7::MultiplyTransform 3333 * 3334 * Multiplies the already-set transform matrix of a transform state 3335 * with another matrix. For the world matrix, see SetTransform 3336 * 3337 * Version 2, 3 and 7 3338 * 3339 * Params: 3340 * TransformStateType: Transform state to multiply 3341 * D3DMatrix Matrix to multiply with. 3342 * 3343 * Returns 3344 * D3D_OK on success 3345 * DDERR_INVALIDPARAMS if D3DMatrix is NULL 3346 * 3347 *****************************************************************************/ 3348 static HRESULT d3d_device7_MultiplyTransform(IDirect3DDevice7 *iface, 3349 D3DTRANSFORMSTATETYPE state, D3DMATRIX *matrix) 3350 { 3351 struct d3d_device *device = impl_from_IDirect3DDevice7(iface); 3352 enum wined3d_transform_state wined3d_state; 3353 3354 TRACE("iface %p, state %#x, matrix %p.\n", iface, state, matrix); 3355 3356 switch (state) 3357 { 3358 case D3DTRANSFORMSTATE_WORLD: 3359 wined3d_state = WINED3D_TS_WORLD_MATRIX(0); 3360 break; 3361 case D3DTRANSFORMSTATE_WORLD1: 3362 wined3d_state = WINED3D_TS_WORLD_MATRIX(1); 3363 break; 3364 case D3DTRANSFORMSTATE_WORLD2: 3365 wined3d_state = WINED3D_TS_WORLD_MATRIX(2); 3366 break; 3367 case D3DTRANSFORMSTATE_WORLD3: 3368 wined3d_state = WINED3D_TS_WORLD_MATRIX(3); 3369 break; 3370 default: 3371 wined3d_state = state; 3372 } 3373 3374 /* Note: D3DMATRIX is compatible with struct wined3d_matrix. */ 3375 wined3d_mutex_lock(); 3376 wined3d_device_multiply_transform(device->wined3d_device, 3377 wined3d_state, (struct wined3d_matrix *)matrix); 3378 wined3d_mutex_unlock(); 3379 3380 return D3D_OK; 3381 } 3382 3383 static HRESULT WINAPI d3d_device7_MultiplyTransform_FPUSetup(IDirect3DDevice7 *iface, 3384 D3DTRANSFORMSTATETYPE state, D3DMATRIX *matrix) 3385 { 3386 return d3d_device7_MultiplyTransform(iface, state, matrix); 3387 } 3388 3389 static HRESULT WINAPI d3d_device7_MultiplyTransform_FPUPreserve(IDirect3DDevice7 *iface, 3390 D3DTRANSFORMSTATETYPE state, D3DMATRIX *matrix) 3391 { 3392 HRESULT hr; 3393 WORD old_fpucw; 3394 3395 old_fpucw = d3d_fpu_setup(); 3396 hr = d3d_device7_MultiplyTransform(iface, state, matrix); 3397 set_fpu_control_word(old_fpucw); 3398 3399 return hr; 3400 } 3401 3402 static HRESULT WINAPI d3d_device3_MultiplyTransform(IDirect3DDevice3 *iface, 3403 D3DTRANSFORMSTATETYPE state, D3DMATRIX *matrix) 3404 { 3405 struct d3d_device *device = impl_from_IDirect3DDevice3(iface); 3406 3407 TRACE("iface %p, state %#x, matrix %p.\n", iface, state, matrix); 3408 3409 if (state == D3DTRANSFORMSTATE_PROJECTION) 3410 { 3411 D3DMATRIX projection, tmp; 3412 3413 wined3d_mutex_lock(); 3414 multiply_matrix(&tmp, &device->legacy_projection, matrix); 3415 multiply_matrix(&projection, &device->legacy_clipspace, &tmp); 3416 wined3d_device_set_transform(device->wined3d_device, 3417 WINED3D_TS_PROJECTION, (struct wined3d_matrix *)&projection); 3418 device->legacy_projection = tmp; 3419 wined3d_mutex_unlock(); 3420 3421 return D3D_OK; 3422 } 3423 3424 return IDirect3DDevice7_MultiplyTransform(&device->IDirect3DDevice7_iface, state, matrix); 3425 } 3426 3427 static HRESULT WINAPI d3d_device2_MultiplyTransform(IDirect3DDevice2 *iface, 3428 D3DTRANSFORMSTATETYPE state, D3DMATRIX *matrix) 3429 { 3430 struct d3d_device *device = impl_from_IDirect3DDevice2(iface); 3431 3432 TRACE("iface %p, state %#x, matrix %p.\n", iface, state, matrix); 3433 3434 return IDirect3DDevice3_MultiplyTransform(&device->IDirect3DDevice3_iface, state, matrix); 3435 } 3436 3437 /***************************************************************************** 3438 * IDirect3DDevice7::DrawPrimitive 3439 * 3440 * Draws primitives based on vertices in an application-provided pointer 3441 * 3442 * Version 2, 3 and 7. The IDirect3DDevice2 thunk converts the fixed vertex type into 3443 * an FVF format for D3D7 3444 * 3445 * Params: 3446 * PrimitiveType: The type of the primitives to draw 3447 * Vertex type: Flexible vertex format vertex description 3448 * Vertices: Pointer to the vertex array 3449 * VertexCount: The number of vertices to draw 3450 * Flags: As usual a few flags 3451 * 3452 * Returns: 3453 * D3D_OK on success 3454 * DDERR_INVALIDPARAMS if Vertices is NULL 3455 * 3456 *****************************************************************************/ 3457 3458 /* The caller is responsible for wined3d locking */ 3459 static HRESULT d3d_device_prepare_vertex_buffer(struct d3d_device *device, UINT min_size) 3460 { 3461 HRESULT hr; 3462 3463 if (device->vertex_buffer_size < min_size || !device->vertex_buffer) 3464 { 3465 UINT size = max(device->vertex_buffer_size * 2, min_size); 3466 struct wined3d_buffer_desc desc; 3467 struct wined3d_buffer *buffer; 3468 3469 TRACE("Growing vertex buffer to %u bytes\n", size); 3470 3471 desc.byte_width = size; 3472 desc.usage = WINED3DUSAGE_DYNAMIC | WINED3DUSAGE_WRITEONLY; 3473 desc.bind_flags = WINED3D_BIND_VERTEX_BUFFER; 3474 desc.access = WINED3D_RESOURCE_ACCESS_GPU | WINED3D_RESOURCE_ACCESS_MAP_R | WINED3D_RESOURCE_ACCESS_MAP_W; 3475 desc.misc_flags = 0; 3476 desc.structure_byte_stride = 0; 3477 3478 if (FAILED(hr = wined3d_buffer_create(device->wined3d_device, &desc, 3479 NULL, NULL, &ddraw_null_wined3d_parent_ops, &buffer))) 3480 { 3481 ERR("Failed to create vertex buffer, hr %#x.\n", hr); 3482 return hr; 3483 } 3484 3485 if (device->vertex_buffer) 3486 wined3d_buffer_decref(device->vertex_buffer); 3487 3488 device->vertex_buffer = buffer; 3489 device->vertex_buffer_size = size; 3490 device->vertex_buffer_pos = 0; 3491 } 3492 return D3D_OK; 3493 } 3494 3495 static HRESULT d3d_device7_DrawPrimitive(IDirect3DDevice7 *iface, 3496 D3DPRIMITIVETYPE primitive_type, DWORD fvf, void *vertices, 3497 DWORD vertex_count, DWORD flags) 3498 { 3499 struct d3d_device *device = impl_from_IDirect3DDevice7(iface); 3500 struct wined3d_map_desc wined3d_map_desc; 3501 struct wined3d_box wined3d_box = {0}; 3502 UINT stride, vb_pos, size, align; 3503 struct wined3d_resource *vb; 3504 HRESULT hr; 3505 3506 TRACE("iface %p, primitive_type %#x, fvf %#x, vertices %p, vertex_count %u, flags %#x.\n", 3507 iface, primitive_type, fvf, vertices, vertex_count, flags); 3508 3509 if (!vertex_count) 3510 { 3511 WARN("0 vertex count.\n"); 3512 return D3D_OK; 3513 } 3514 3515 /* Get the stride */ 3516 stride = get_flexible_vertex_size(fvf); 3517 size = vertex_count * stride; 3518 3519 wined3d_mutex_lock(); 3520 hr = d3d_device_prepare_vertex_buffer(device, size); 3521 if (FAILED(hr)) 3522 goto done; 3523 3524 vb_pos = device->vertex_buffer_pos; 3525 align = vb_pos % stride; 3526 if (align) align = stride - align; 3527 if (vb_pos + size + align > device->vertex_buffer_size) 3528 vb_pos = 0; 3529 else 3530 vb_pos += align; 3531 3532 wined3d_box.left = vb_pos; 3533 wined3d_box.right = vb_pos + size; 3534 vb = wined3d_buffer_get_resource(device->vertex_buffer); 3535 if (FAILED(hr = wined3d_resource_map(vb, 0, &wined3d_map_desc, &wined3d_box, 3536 WINED3D_MAP_WRITE | (vb_pos ? WINED3D_MAP_NOOVERWRITE : WINED3D_MAP_DISCARD)))) 3537 goto done; 3538 memcpy(wined3d_map_desc.data, vertices, size); 3539 wined3d_resource_unmap(vb, 0); 3540 device->vertex_buffer_pos = vb_pos + size; 3541 3542 hr = wined3d_device_set_stream_source(device->wined3d_device, 0, device->vertex_buffer, 0, stride); 3543 if (FAILED(hr)) 3544 goto done; 3545 3546 wined3d_device_set_vertex_declaration(device->wined3d_device, ddraw_find_decl(device->ddraw, fvf)); 3547 wined3d_device_set_primitive_type(device->wined3d_device, primitive_type, 0); 3548 hr = wined3d_device_draw_primitive(device->wined3d_device, vb_pos / stride, vertex_count); 3549 3550 done: 3551 wined3d_mutex_unlock(); 3552 return hr; 3553 } 3554 3555 static HRESULT WINAPI d3d_device7_DrawPrimitive_FPUSetup(IDirect3DDevice7 *iface, 3556 D3DPRIMITIVETYPE primitive_type, DWORD fvf, void *vertices, 3557 DWORD vertex_count, DWORD flags) 3558 { 3559 return d3d_device7_DrawPrimitive(iface, primitive_type, fvf, vertices, vertex_count, flags); 3560 } 3561 3562 static HRESULT WINAPI d3d_device7_DrawPrimitive_FPUPreserve(IDirect3DDevice7 *iface, 3563 D3DPRIMITIVETYPE primitive_type, DWORD fvf, void *vertices, 3564 DWORD vertex_count, DWORD flags) 3565 { 3566 HRESULT hr; 3567 WORD old_fpucw; 3568 3569 old_fpucw = d3d_fpu_setup(); 3570 hr = d3d_device7_DrawPrimitive(iface, primitive_type, fvf, vertices, vertex_count, flags); 3571 set_fpu_control_word(old_fpucw); 3572 3573 return hr; 3574 } 3575 3576 static void setup_lighting(const struct d3d_device *device, DWORD fvf, DWORD flags) 3577 { 3578 BOOL enable = TRUE; 3579 3580 /* Ignore the D3DFVF_XYZRHW case here, wined3d takes care of that */ 3581 if (!device->material || !(fvf & D3DFVF_NORMAL) || (flags & D3DDP_DONOTLIGHT)) 3582 enable = FALSE; 3583 3584 wined3d_device_set_render_state(device->wined3d_device, WINED3D_RS_LIGHTING, enable); 3585 } 3586 3587 3588 static HRESULT WINAPI d3d_device3_DrawPrimitive(IDirect3DDevice3 *iface, 3589 D3DPRIMITIVETYPE primitive_type, DWORD fvf, void *vertices, DWORD vertex_count, 3590 DWORD flags) 3591 { 3592 struct d3d_device *device = impl_from_IDirect3DDevice3(iface); 3593 3594 TRACE("iface %p, primitive_type %#x, fvf %#x, vertices %p, vertex_count %u, flags %#x.\n", 3595 iface, primitive_type, fvf, vertices, vertex_count, flags); 3596 3597 setup_lighting(device, fvf, flags); 3598 3599 return IDirect3DDevice7_DrawPrimitive(&device->IDirect3DDevice7_iface, 3600 primitive_type, fvf, vertices, vertex_count, flags); 3601 } 3602 3603 static HRESULT WINAPI d3d_device2_DrawPrimitive(IDirect3DDevice2 *iface, 3604 D3DPRIMITIVETYPE primitive_type, D3DVERTEXTYPE vertex_type, void *vertices, 3605 DWORD vertex_count, DWORD flags) 3606 { 3607 struct d3d_device *device = impl_from_IDirect3DDevice2(iface); 3608 DWORD fvf; 3609 3610 TRACE("iface %p, primitive_type %#x, vertex_type %#x, vertices %p, vertex_count %u, flags %#x.\n", 3611 iface, primitive_type, vertex_type, vertices, vertex_count, flags); 3612 3613 switch (vertex_type) 3614 { 3615 case D3DVT_VERTEX: fvf = D3DFVF_VERTEX; break; 3616 case D3DVT_LVERTEX: fvf = D3DFVF_LVERTEX; break; 3617 case D3DVT_TLVERTEX: fvf = D3DFVF_TLVERTEX; break; 3618 default: 3619 FIXME("Unhandled vertex type %#x.\n", vertex_type); 3620 return DDERR_INVALIDPARAMS; /* Should never happen */ 3621 } 3622 3623 return d3d_device3_DrawPrimitive(&device->IDirect3DDevice3_iface, 3624 primitive_type, fvf, vertices, vertex_count, flags); 3625 } 3626 3627 /***************************************************************************** 3628 * IDirect3DDevice7::DrawIndexedPrimitive 3629 * 3630 * Draws vertices from an application-provided pointer, based on the index 3631 * numbers in a WORD array. 3632 * 3633 * Version 2, 3 and 7. The version 7 thunk translates the vertex type into 3634 * an FVF format for D3D7 3635 * 3636 * Params: 3637 * PrimitiveType: The primitive type to draw 3638 * VertexType: The FVF vertex description 3639 * Vertices: Pointer to the vertex array 3640 * VertexCount: ? 3641 * Indices: Pointer to the index array 3642 * IndexCount: Number of indices = Number of vertices to draw 3643 * Flags: As usual, some flags 3644 * 3645 * Returns: 3646 * D3D_OK on success 3647 * DDERR_INVALIDPARAMS if Vertices or Indices is NULL 3648 * 3649 *****************************************************************************/ 3650 /* The caller is responsible for wined3d locking */ 3651 static HRESULT d3d_device_prepare_index_buffer(struct d3d_device *device, UINT min_size) 3652 { 3653 HRESULT hr; 3654 3655 if (device->index_buffer_size < min_size || !device->index_buffer) 3656 { 3657 UINT size = max(device->index_buffer_size * 2, min_size); 3658 struct wined3d_buffer_desc desc; 3659 struct wined3d_buffer *buffer; 3660 3661 TRACE("Growing index buffer to %u bytes\n", size); 3662 3663 desc.byte_width = size; 3664 desc.usage = WINED3DUSAGE_DYNAMIC | WINED3DUSAGE_WRITEONLY | WINED3DUSAGE_STATICDECL; 3665 desc.bind_flags = WINED3D_BIND_INDEX_BUFFER; 3666 desc.access = WINED3D_RESOURCE_ACCESS_GPU | WINED3D_RESOURCE_ACCESS_MAP_R | WINED3D_RESOURCE_ACCESS_MAP_W; 3667 desc.misc_flags = 0; 3668 desc.structure_byte_stride = 0; 3669 3670 if (FAILED(hr = wined3d_buffer_create(device->wined3d_device, &desc, 3671 NULL, NULL, &ddraw_null_wined3d_parent_ops, &buffer))) 3672 { 3673 ERR("Failed to create index buffer, hr %#x.\n", hr); 3674 return hr; 3675 } 3676 3677 if (device->index_buffer) 3678 wined3d_buffer_decref(device->index_buffer); 3679 device->index_buffer = buffer; 3680 device->index_buffer_size = size; 3681 device->index_buffer_pos = 0; 3682 } 3683 return D3D_OK; 3684 } 3685 3686 static HRESULT d3d_device7_DrawIndexedPrimitive(IDirect3DDevice7 *iface, 3687 D3DPRIMITIVETYPE primitive_type, DWORD fvf, void *vertices, DWORD vertex_count, 3688 WORD *indices, DWORD index_count, DWORD flags) 3689 { 3690 struct d3d_device *device = impl_from_IDirect3DDevice7(iface); 3691 HRESULT hr; 3692 UINT stride = get_flexible_vertex_size(fvf); 3693 UINT vtx_size = stride * vertex_count, idx_size = index_count * sizeof(*indices); 3694 struct wined3d_map_desc wined3d_map_desc; 3695 struct wined3d_box wined3d_box = {0}; 3696 struct wined3d_resource *ib, *vb; 3697 UINT vb_pos, ib_pos, align; 3698 3699 TRACE("iface %p, primitive_type %#x, fvf %#x, vertices %p, vertex_count %u, " 3700 "indices %p, index_count %u, flags %#x.\n", 3701 iface, primitive_type, fvf, vertices, vertex_count, indices, index_count, flags); 3702 3703 if (!vertex_count || !index_count) 3704 { 3705 WARN("0 vertex or index count.\n"); 3706 return D3D_OK; 3707 } 3708 3709 /* Set the D3DDevice's FVF */ 3710 wined3d_mutex_lock(); 3711 3712 hr = d3d_device_prepare_vertex_buffer(device, vtx_size); 3713 if (FAILED(hr)) 3714 goto done; 3715 3716 vb_pos = device->vertex_buffer_pos; 3717 align = vb_pos % stride; 3718 if (align) align = stride - align; 3719 if (vb_pos + vtx_size + align > device->vertex_buffer_size) 3720 vb_pos = 0; 3721 else 3722 vb_pos += align; 3723 3724 wined3d_box.left = vb_pos; 3725 wined3d_box.right = vb_pos + vtx_size; 3726 vb = wined3d_buffer_get_resource(device->vertex_buffer); 3727 if (FAILED(hr = wined3d_resource_map(vb, 0, &wined3d_map_desc, &wined3d_box, 3728 WINED3D_MAP_WRITE | (vb_pos ? WINED3D_MAP_NOOVERWRITE : WINED3D_MAP_DISCARD)))) 3729 goto done; 3730 memcpy(wined3d_map_desc.data, vertices, vtx_size); 3731 wined3d_resource_unmap(vb, 0); 3732 device->vertex_buffer_pos = vb_pos + vtx_size; 3733 3734 hr = d3d_device_prepare_index_buffer(device, idx_size); 3735 if (FAILED(hr)) 3736 goto done; 3737 ib_pos = device->index_buffer_pos; 3738 if (device->index_buffer_size - idx_size < ib_pos) 3739 ib_pos = 0; 3740 3741 wined3d_box.left = ib_pos; 3742 wined3d_box.right = ib_pos + idx_size; 3743 ib = wined3d_buffer_get_resource(device->index_buffer); 3744 if (FAILED(hr = wined3d_resource_map(ib, 0, &wined3d_map_desc, &wined3d_box, 3745 WINED3D_MAP_WRITE | (ib_pos ? WINED3D_MAP_NOOVERWRITE : WINED3D_MAP_DISCARD)))) 3746 goto done; 3747 memcpy(wined3d_map_desc.data, indices, idx_size); 3748 wined3d_resource_unmap(ib, 0); 3749 device->index_buffer_pos = ib_pos + idx_size; 3750 3751 hr = wined3d_device_set_stream_source(device->wined3d_device, 0, device->vertex_buffer, 0, stride); 3752 if (FAILED(hr)) 3753 goto done; 3754 wined3d_device_set_index_buffer(device->wined3d_device, device->index_buffer, WINED3DFMT_R16_UINT, 0); 3755 3756 wined3d_device_set_vertex_declaration(device->wined3d_device, ddraw_find_decl(device->ddraw, fvf)); 3757 wined3d_device_set_primitive_type(device->wined3d_device, primitive_type, 0); 3758 wined3d_device_set_base_vertex_index(device->wined3d_device, vb_pos / stride); 3759 hr = wined3d_device_draw_indexed_primitive(device->wined3d_device, ib_pos / sizeof(*indices), index_count); 3760 3761 done: 3762 wined3d_mutex_unlock(); 3763 return hr; 3764 } 3765 3766 static HRESULT WINAPI d3d_device7_DrawIndexedPrimitive_FPUSetup(IDirect3DDevice7 *iface, 3767 D3DPRIMITIVETYPE primitive_type, DWORD fvf, void *vertices, DWORD vertex_count, 3768 WORD *indices, DWORD index_count, DWORD flags) 3769 { 3770 return d3d_device7_DrawIndexedPrimitive(iface, primitive_type, fvf, 3771 vertices, vertex_count, indices, index_count, flags); 3772 } 3773 3774 static HRESULT WINAPI d3d_device7_DrawIndexedPrimitive_FPUPreserve(IDirect3DDevice7 *iface, 3775 D3DPRIMITIVETYPE primitive_type, DWORD fvf, void *vertices, DWORD vertex_count, 3776 WORD *indices, DWORD index_count, DWORD flags) 3777 { 3778 HRESULT hr; 3779 WORD old_fpucw; 3780 3781 old_fpucw = d3d_fpu_setup(); 3782 hr = d3d_device7_DrawIndexedPrimitive(iface, primitive_type, fvf, 3783 vertices, vertex_count, indices, index_count, flags); 3784 set_fpu_control_word(old_fpucw); 3785 3786 return hr; 3787 } 3788 3789 static HRESULT WINAPI d3d_device3_DrawIndexedPrimitive(IDirect3DDevice3 *iface, 3790 D3DPRIMITIVETYPE primitive_type, DWORD fvf, void *vertices, DWORD vertex_count, 3791 WORD *indices, DWORD index_count, DWORD flags) 3792 { 3793 struct d3d_device *device = impl_from_IDirect3DDevice3(iface); 3794 3795 TRACE("iface %p, primitive_type %#x, fvf %#x, vertices %p, vertex_count %u, " 3796 "indices %p, index_count %u, flags %#x.\n", 3797 iface, primitive_type, fvf, vertices, vertex_count, indices, index_count, flags); 3798 3799 setup_lighting(device, fvf, flags); 3800 3801 return IDirect3DDevice7_DrawIndexedPrimitive(&device->IDirect3DDevice7_iface, 3802 primitive_type, fvf, vertices, vertex_count, indices, index_count, flags); 3803 } 3804 3805 static HRESULT WINAPI d3d_device2_DrawIndexedPrimitive(IDirect3DDevice2 *iface, 3806 D3DPRIMITIVETYPE primitive_type, D3DVERTEXTYPE vertex_type, void *vertices, 3807 DWORD vertex_count, WORD *indices, DWORD index_count, DWORD flags) 3808 { 3809 struct d3d_device *device = impl_from_IDirect3DDevice2(iface); 3810 DWORD fvf; 3811 3812 TRACE("iface %p, primitive_type %#x, vertex_type %#x, vertices %p, vertex_count %u, " 3813 "indices %p, index_count %u, flags %#x.\n", 3814 iface, primitive_type, vertex_type, vertices, vertex_count, indices, index_count, flags); 3815 3816 switch (vertex_type) 3817 { 3818 case D3DVT_VERTEX: fvf = D3DFVF_VERTEX; break; 3819 case D3DVT_LVERTEX: fvf = D3DFVF_LVERTEX; break; 3820 case D3DVT_TLVERTEX: fvf = D3DFVF_TLVERTEX; break; 3821 default: 3822 ERR("Unhandled vertex type %#x.\n", vertex_type); 3823 return DDERR_INVALIDPARAMS; /* Should never happen */ 3824 } 3825 3826 return d3d_device3_DrawIndexedPrimitive(&device->IDirect3DDevice3_iface, 3827 primitive_type, fvf, vertices, vertex_count, indices, index_count, flags); 3828 } 3829 3830 /***************************************************************************** 3831 * IDirect3DDevice3::End 3832 * 3833 * Ends a draw begun with IDirect3DDevice3::Begin or 3834 * IDirect3DDevice::BeginIndexed. The vertices specified with 3835 * IDirect3DDevice::Vertex or IDirect3DDevice::Index are drawn using 3836 * the IDirect3DDevice3::DrawPrimitive method. So far only 3837 * non-indexed mode is supported 3838 * 3839 * Version 2 and 3 3840 * 3841 * Params: 3842 * Flags: Some flags, as usual. Don't know which are defined 3843 * 3844 * Returns: 3845 * The return value of IDirect3DDevice3::DrawPrimitive 3846 * 3847 *****************************************************************************/ 3848 static HRESULT WINAPI d3d_device3_End(IDirect3DDevice3 *iface, DWORD flags) 3849 { 3850 struct d3d_device *device = impl_from_IDirect3DDevice3(iface); 3851 3852 TRACE("iface %p, flags %#x.\n", iface, flags); 3853 3854 return d3d_device3_DrawPrimitive(&device->IDirect3DDevice3_iface, device->primitive_type, 3855 device->vertex_type, device->sysmem_vertex_buffer, device->nb_vertices, device->render_flags); 3856 } 3857 3858 static HRESULT WINAPI d3d_device2_End(IDirect3DDevice2 *iface, DWORD flags) 3859 { 3860 struct d3d_device *device = impl_from_IDirect3DDevice2(iface); 3861 3862 TRACE("iface %p, flags %#x.\n", iface, flags); 3863 3864 return d3d_device3_End(&device->IDirect3DDevice3_iface, flags); 3865 } 3866 3867 /***************************************************************************** 3868 * IDirect3DDevice7::SetClipStatus 3869 * 3870 * Sets the clip status. This defines things as clipping conditions and 3871 * the extents of the clipping region. 3872 * 3873 * Version 2, 3 and 7 3874 * 3875 * Params: 3876 * ClipStatus: 3877 * 3878 * Returns: 3879 * D3D_OK because it's a stub 3880 * (DDERR_INVALIDPARAMS if ClipStatus == NULL) 3881 * 3882 *****************************************************************************/ 3883 static HRESULT WINAPI d3d_device7_SetClipStatus(IDirect3DDevice7 *iface, D3DCLIPSTATUS *clip_status) 3884 { 3885 FIXME("iface %p, clip_status %p stub!\n", iface, clip_status); 3886 3887 return D3D_OK; 3888 } 3889 3890 static HRESULT WINAPI d3d_device3_SetClipStatus(IDirect3DDevice3 *iface, D3DCLIPSTATUS *clip_status) 3891 { 3892 struct d3d_device *device = impl_from_IDirect3DDevice3(iface); 3893 3894 TRACE("iface %p, clip_status %p.\n", iface, clip_status); 3895 3896 return IDirect3DDevice7_SetClipStatus(&device->IDirect3DDevice7_iface, clip_status); 3897 } 3898 3899 static HRESULT WINAPI d3d_device2_SetClipStatus(IDirect3DDevice2 *iface, D3DCLIPSTATUS *clip_status) 3900 { 3901 struct d3d_device *device = impl_from_IDirect3DDevice2(iface); 3902 3903 TRACE("iface %p, clip_status %p.\n", iface, clip_status); 3904 3905 return IDirect3DDevice7_SetClipStatus(&device->IDirect3DDevice7_iface, clip_status); 3906 } 3907 3908 /***************************************************************************** 3909 * IDirect3DDevice7::GetClipStatus 3910 * 3911 * Returns the clip status 3912 * 3913 * Params: 3914 * ClipStatus: Address to write the clip status to 3915 * 3916 * Returns: 3917 * D3D_OK because it's a stub 3918 * 3919 *****************************************************************************/ 3920 static HRESULT WINAPI d3d_device7_GetClipStatus(IDirect3DDevice7 *iface, D3DCLIPSTATUS *clip_status) 3921 { 3922 FIXME("iface %p, clip_status %p stub!\n", iface, clip_status); 3923 3924 return D3D_OK; 3925 } 3926 3927 static HRESULT WINAPI d3d_device3_GetClipStatus(IDirect3DDevice3 *iface, D3DCLIPSTATUS *clip_status) 3928 { 3929 struct d3d_device *device = impl_from_IDirect3DDevice3(iface); 3930 3931 TRACE("iface %p, clip_status %p.\n", iface, clip_status); 3932 3933 return IDirect3DDevice7_GetClipStatus(&device->IDirect3DDevice7_iface, clip_status); 3934 } 3935 3936 static HRESULT WINAPI d3d_device2_GetClipStatus(IDirect3DDevice2 *iface, D3DCLIPSTATUS *clip_status) 3937 { 3938 struct d3d_device *device = impl_from_IDirect3DDevice2(iface); 3939 3940 TRACE("iface %p, clip_status %p.\n", iface, clip_status); 3941 3942 return IDirect3DDevice7_GetClipStatus(&device->IDirect3DDevice7_iface, clip_status); 3943 } 3944 3945 /***************************************************************************** 3946 * IDirect3DDevice::DrawPrimitiveStrided 3947 * 3948 * Draws vertices described by a D3DDRAWPRIMITIVESTRIDEDDATA structure. 3949 * 3950 * Version 3 and 7 3951 * 3952 * Params: 3953 * PrimitiveType: The primitive type to draw 3954 * VertexType: The FVF description of the vertices to draw (for the stride??) 3955 * D3DDrawPrimStrideData: A D3DDRAWPRIMITIVESTRIDEDDATA structure describing 3956 * the vertex data locations 3957 * VertexCount: The number of vertices to draw 3958 * Flags: Some flags 3959 * 3960 * Returns: 3961 * D3D_OK, because it's a stub 3962 * (DDERR_INVALIDPARAMS if D3DDrawPrimStrideData is NULL) 3963 * 3964 *****************************************************************************/ 3965 static void pack_strided_data(BYTE *dst, DWORD count, const D3DDRAWPRIMITIVESTRIDEDDATA *src, DWORD fvf) 3966 { 3967 DWORD i, tex, offset; 3968 3969 for (i = 0; i < count; i++) 3970 { 3971 /* The contents of the strided data are determined by the fvf, 3972 * not by the members set in src. So it's valid 3973 * to have diffuse.lpvData set to 0xdeadbeef if the diffuse flag is 3974 * not set in the fvf. */ 3975 if (fvf & D3DFVF_POSITION_MASK) 3976 { 3977 offset = i * src->position.dwStride; 3978 if (fvf & D3DFVF_XYZRHW) 3979 { 3980 memcpy(dst, ((BYTE *)src->position.lpvData) + offset, 4 * sizeof(float)); 3981 dst += 4 * sizeof(float); 3982 } 3983 else 3984 { 3985 memcpy(dst, ((BYTE *)src->position.lpvData) + offset, 3 * sizeof(float)); 3986 dst += 3 * sizeof(float); 3987 } 3988 } 3989 3990 if (fvf & D3DFVF_NORMAL) 3991 { 3992 offset = i * src->normal.dwStride; 3993 memcpy(dst, ((BYTE *)src->normal.lpvData) + offset, 3 * sizeof(float)); 3994 dst += 3 * sizeof(float); 3995 } 3996 3997 if (fvf & D3DFVF_DIFFUSE) 3998 { 3999 offset = i * src->diffuse.dwStride; 4000 memcpy(dst, ((BYTE *)src->diffuse.lpvData) + offset, sizeof(DWORD)); 4001 dst += sizeof(DWORD); 4002 } 4003 4004 if (fvf & D3DFVF_SPECULAR) 4005 { 4006 offset = i * src->specular.dwStride; 4007 memcpy(dst, ((BYTE *)src->specular.lpvData) + offset, sizeof(DWORD)); 4008 dst += sizeof(DWORD); 4009 } 4010 4011 for (tex = 0; tex < GET_TEXCOUNT_FROM_FVF(fvf); ++tex) 4012 { 4013 DWORD attrib_count = GET_TEXCOORD_SIZE_FROM_FVF(fvf, tex); 4014 offset = i * src->textureCoords[tex].dwStride; 4015 memcpy(dst, ((BYTE *)src->textureCoords[tex].lpvData) + offset, attrib_count * sizeof(float)); 4016 dst += attrib_count * sizeof(float); 4017 } 4018 } 4019 } 4020 4021 static HRESULT d3d_device7_DrawPrimitiveStrided(IDirect3DDevice7 *iface, D3DPRIMITIVETYPE primitive_type, 4022 DWORD fvf, D3DDRAWPRIMITIVESTRIDEDDATA *strided_data, DWORD vertex_count, DWORD flags) 4023 { 4024 struct d3d_device *device = impl_from_IDirect3DDevice7(iface); 4025 HRESULT hr; 4026 UINT dst_stride = get_flexible_vertex_size(fvf); 4027 UINT dst_size = dst_stride * vertex_count; 4028 struct wined3d_map_desc wined3d_map_desc; 4029 struct wined3d_box wined3d_box = {0}; 4030 struct wined3d_resource *vb; 4031 UINT vb_pos, align; 4032 4033 TRACE("iface %p, primitive_type %#x, fvf %#x, strided_data %p, vertex_count %u, flags %#x.\n", 4034 iface, primitive_type, fvf, strided_data, vertex_count, flags); 4035 4036 if (!vertex_count) 4037 { 4038 WARN("0 vertex count.\n"); 4039 return D3D_OK; 4040 } 4041 4042 wined3d_mutex_lock(); 4043 hr = d3d_device_prepare_vertex_buffer(device, dst_size); 4044 if (FAILED(hr)) 4045 goto done; 4046 4047 vb_pos = device->vertex_buffer_pos; 4048 align = vb_pos % dst_stride; 4049 if (align) align = dst_stride - align; 4050 if (vb_pos + dst_size + align > device->vertex_buffer_size) 4051 vb_pos = 0; 4052 else 4053 vb_pos += align; 4054 4055 wined3d_box.left = vb_pos; 4056 wined3d_box.right = vb_pos + dst_size; 4057 vb = wined3d_buffer_get_resource(device->vertex_buffer); 4058 if (FAILED(hr = wined3d_resource_map(vb, 0, &wined3d_map_desc, &wined3d_box, 4059 WINED3D_MAP_WRITE | (vb_pos ? WINED3D_MAP_NOOVERWRITE : WINED3D_MAP_DISCARD)))) 4060 goto done; 4061 pack_strided_data(wined3d_map_desc.data, vertex_count, strided_data, fvf); 4062 wined3d_resource_unmap(vb, 0); 4063 device->vertex_buffer_pos = vb_pos + dst_size; 4064 4065 hr = wined3d_device_set_stream_source(device->wined3d_device, 0, device->vertex_buffer, 0, dst_stride); 4066 if (FAILED(hr)) 4067 goto done; 4068 wined3d_device_set_vertex_declaration(device->wined3d_device, ddraw_find_decl(device->ddraw, fvf)); 4069 4070 wined3d_device_set_primitive_type(device->wined3d_device, primitive_type, 0); 4071 hr = wined3d_device_draw_primitive(device->wined3d_device, vb_pos / dst_stride, vertex_count); 4072 4073 done: 4074 wined3d_mutex_unlock(); 4075 return hr; 4076 } 4077 4078 static HRESULT WINAPI d3d_device7_DrawPrimitiveStrided_FPUSetup(IDirect3DDevice7 *iface, 4079 D3DPRIMITIVETYPE PrimitiveType, DWORD VertexType, 4080 D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData, DWORD VertexCount, DWORD Flags) 4081 { 4082 return d3d_device7_DrawPrimitiveStrided(iface, PrimitiveType, 4083 VertexType, D3DDrawPrimStrideData, VertexCount, Flags); 4084 } 4085 4086 static HRESULT WINAPI d3d_device7_DrawPrimitiveStrided_FPUPreserve(IDirect3DDevice7 *iface, 4087 D3DPRIMITIVETYPE PrimitiveType, DWORD VertexType, 4088 D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData, DWORD VertexCount, DWORD Flags) 4089 { 4090 HRESULT hr; 4091 WORD old_fpucw; 4092 4093 old_fpucw = d3d_fpu_setup(); 4094 hr = d3d_device7_DrawPrimitiveStrided(iface, PrimitiveType, 4095 VertexType, D3DDrawPrimStrideData, VertexCount, Flags); 4096 set_fpu_control_word(old_fpucw); 4097 4098 return hr; 4099 } 4100 4101 static HRESULT WINAPI d3d_device3_DrawPrimitiveStrided(IDirect3DDevice3 *iface, 4102 D3DPRIMITIVETYPE PrimitiveType, DWORD VertexType, 4103 D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData, DWORD VertexCount, DWORD Flags) 4104 { 4105 struct d3d_device *device = impl_from_IDirect3DDevice3(iface); 4106 4107 TRACE("iface %p, primitive_type %#x, FVF %#x, strided_data %p, vertex_count %u, flags %#x.\n", 4108 iface, PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Flags); 4109 4110 setup_lighting(device, VertexType, Flags); 4111 4112 return IDirect3DDevice7_DrawPrimitiveStrided(&device->IDirect3DDevice7_iface, 4113 PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Flags); 4114 } 4115 4116 /***************************************************************************** 4117 * IDirect3DDevice7::DrawIndexedPrimitiveStrided 4118 * 4119 * Draws primitives specified by strided data locations based on indices 4120 * 4121 * Version 3 and 7 4122 * 4123 * Params: 4124 * PrimitiveType: 4125 * 4126 * Returns: 4127 * D3D_OK, because it's a stub 4128 * (DDERR_INVALIDPARAMS if D3DDrawPrimStrideData is NULL) 4129 * (DDERR_INVALIDPARAMS if Indices is NULL) 4130 * 4131 *****************************************************************************/ 4132 static HRESULT d3d_device7_DrawIndexedPrimitiveStrided(IDirect3DDevice7 *iface, 4133 D3DPRIMITIVETYPE primitive_type, DWORD fvf, D3DDRAWPRIMITIVESTRIDEDDATA *strided_data, 4134 DWORD vertex_count, WORD *indices, DWORD index_count, DWORD flags) 4135 { 4136 struct d3d_device *device = impl_from_IDirect3DDevice7(iface); 4137 UINT vtx_dst_stride = get_flexible_vertex_size(fvf); 4138 UINT vtx_dst_size = vertex_count * vtx_dst_stride; 4139 UINT idx_size = index_count * sizeof(WORD); 4140 struct wined3d_map_desc wined3d_map_desc; 4141 struct wined3d_box wined3d_box = {0}; 4142 struct wined3d_resource *ib, *vb; 4143 UINT vb_pos, align; 4144 UINT ib_pos; 4145 HRESULT hr; 4146 4147 TRACE("iface %p, primitive_type %#x, fvf %#x, strided_data %p, " 4148 "vertex_count %u, indices %p, index_count %u, flags %#x.\n", 4149 iface, primitive_type, fvf, strided_data, vertex_count, indices, index_count, flags); 4150 4151 if (!vertex_count || !index_count) 4152 { 4153 WARN("0 vertex or index count.\n"); 4154 return D3D_OK; 4155 } 4156 4157 wined3d_mutex_lock(); 4158 4159 hr = d3d_device_prepare_vertex_buffer(device, vtx_dst_size); 4160 if (FAILED(hr)) 4161 goto done; 4162 4163 vb_pos = device->vertex_buffer_pos; 4164 align = vb_pos % vtx_dst_stride; 4165 if (align) align = vtx_dst_stride - align; 4166 if (vb_pos + vtx_dst_size + align > device->vertex_buffer_size) 4167 vb_pos = 0; 4168 else 4169 vb_pos += align; 4170 4171 wined3d_box.left = vb_pos; 4172 wined3d_box.right = vb_pos + vtx_dst_size; 4173 vb = wined3d_buffer_get_resource(device->vertex_buffer); 4174 if (FAILED(hr = wined3d_resource_map(vb, 0, &wined3d_map_desc, &wined3d_box, 4175 WINED3D_MAP_WRITE | (vb_pos ? WINED3D_MAP_NOOVERWRITE : WINED3D_MAP_DISCARD)))) 4176 goto done; 4177 pack_strided_data(wined3d_map_desc.data, vertex_count, strided_data, fvf); 4178 wined3d_resource_unmap(vb, 0); 4179 device->vertex_buffer_pos = vb_pos + vtx_dst_size; 4180 4181 hr = d3d_device_prepare_index_buffer(device, idx_size); 4182 if (FAILED(hr)) 4183 goto done; 4184 ib_pos = device->index_buffer_pos; 4185 if (device->index_buffer_size - idx_size < ib_pos) 4186 ib_pos = 0; 4187 4188 wined3d_box.left = ib_pos; 4189 wined3d_box.right = ib_pos + idx_size; 4190 ib = wined3d_buffer_get_resource(device->index_buffer); 4191 if (FAILED(hr = wined3d_resource_map(ib, 0, &wined3d_map_desc, &wined3d_box, 4192 WINED3D_MAP_WRITE | (ib_pos ? WINED3D_MAP_NOOVERWRITE : WINED3D_MAP_DISCARD)))) 4193 goto done; 4194 memcpy(wined3d_map_desc.data, indices, idx_size); 4195 wined3d_resource_unmap(ib, 0); 4196 device->index_buffer_pos = ib_pos + idx_size; 4197 4198 hr = wined3d_device_set_stream_source(device->wined3d_device, 0, device->vertex_buffer, 0, vtx_dst_stride); 4199 if (FAILED(hr)) 4200 goto done; 4201 wined3d_device_set_index_buffer(device->wined3d_device, device->index_buffer, WINED3DFMT_R16_UINT, 0); 4202 wined3d_device_set_base_vertex_index(device->wined3d_device, vb_pos / vtx_dst_stride); 4203 4204 wined3d_device_set_vertex_declaration(device->wined3d_device, ddraw_find_decl(device->ddraw, fvf)); 4205 wined3d_device_set_primitive_type(device->wined3d_device, primitive_type, 0); 4206 hr = wined3d_device_draw_indexed_primitive(device->wined3d_device, ib_pos / sizeof(WORD), index_count); 4207 4208 done: 4209 wined3d_mutex_unlock(); 4210 return hr; 4211 } 4212 4213 static HRESULT WINAPI d3d_device7_DrawIndexedPrimitiveStrided_FPUSetup(IDirect3DDevice7 *iface, 4214 D3DPRIMITIVETYPE PrimitiveType, DWORD VertexType, 4215 D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData, DWORD VertexCount, 4216 WORD *Indices, DWORD IndexCount, DWORD Flags) 4217 { 4218 return d3d_device7_DrawIndexedPrimitiveStrided(iface, PrimitiveType, VertexType, 4219 D3DDrawPrimStrideData, VertexCount, Indices, IndexCount, Flags); 4220 } 4221 4222 static HRESULT WINAPI d3d_device7_DrawIndexedPrimitiveStrided_FPUPreserve(IDirect3DDevice7 *iface, 4223 D3DPRIMITIVETYPE PrimitiveType, DWORD VertexType, 4224 D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData, DWORD VertexCount, 4225 WORD *Indices, DWORD IndexCount, DWORD Flags) 4226 { 4227 HRESULT hr; 4228 WORD old_fpucw; 4229 4230 old_fpucw = d3d_fpu_setup(); 4231 hr = d3d_device7_DrawIndexedPrimitiveStrided(iface, PrimitiveType, VertexType, 4232 D3DDrawPrimStrideData, VertexCount, Indices, IndexCount, Flags); 4233 set_fpu_control_word(old_fpucw); 4234 4235 return hr; 4236 } 4237 4238 static HRESULT WINAPI d3d_device3_DrawIndexedPrimitiveStrided(IDirect3DDevice3 *iface, 4239 D3DPRIMITIVETYPE PrimitiveType, DWORD VertexType, 4240 D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData, DWORD VertexCount, WORD *Indices, 4241 DWORD IndexCount, DWORD Flags) 4242 { 4243 struct d3d_device *device = impl_from_IDirect3DDevice3(iface); 4244 4245 TRACE("iface %p, primitive_type %#x, FVF %#x, strided_data %p, vertex_count %u, indices %p, index_count %u, flags %#x.\n", 4246 iface, PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Indices, IndexCount, Flags); 4247 4248 setup_lighting(device, VertexType, Flags); 4249 4250 return IDirect3DDevice7_DrawIndexedPrimitiveStrided(&device->IDirect3DDevice7_iface, 4251 PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Indices, IndexCount, Flags); 4252 } 4253 4254 /***************************************************************************** 4255 * IDirect3DDevice7::DrawPrimitiveVB 4256 * 4257 * Draws primitives from a vertex buffer to the screen. 4258 * 4259 * Version 3 and 7 4260 * 4261 * Params: 4262 * PrimitiveType: Type of primitive to be rendered. 4263 * D3DVertexBuf: Source Vertex Buffer 4264 * StartVertex: Index of the first vertex from the buffer to be rendered 4265 * NumVertices: Number of vertices to be rendered 4266 * Flags: Can be D3DDP_WAIT to wait until rendering has finished 4267 * 4268 * Return values 4269 * D3D_OK on success 4270 * DDERR_INVALIDPARAMS if D3DVertexBuf is NULL 4271 * 4272 *****************************************************************************/ 4273 static HRESULT d3d_device7_DrawPrimitiveVB(IDirect3DDevice7 *iface, D3DPRIMITIVETYPE primitive_type, 4274 IDirect3DVertexBuffer7 *vb, DWORD start_vertex, DWORD vertex_count, DWORD flags) 4275 { 4276 struct d3d_device *device = impl_from_IDirect3DDevice7(iface); 4277 struct d3d_vertex_buffer *vb_impl = unsafe_impl_from_IDirect3DVertexBuffer7(vb); 4278 HRESULT hr; 4279 DWORD stride; 4280 4281 TRACE("iface %p, primitive_type %#x, vb %p, start_vertex %u, vertex_count %u, flags %#x.\n", 4282 iface, primitive_type, vb, start_vertex, vertex_count, flags); 4283 4284 if (!vertex_count) 4285 { 4286 WARN("0 vertex count.\n"); 4287 return D3D_OK; 4288 } 4289 4290 stride = get_flexible_vertex_size(vb_impl->fvf); 4291 4292 wined3d_mutex_lock(); 4293 wined3d_device_set_vertex_declaration(device->wined3d_device, vb_impl->wined3d_declaration); 4294 if (FAILED(hr = wined3d_device_set_stream_source(device->wined3d_device, 4295 0, vb_impl->wined3d_buffer, 0, stride))) 4296 { 4297 WARN("Failed to set stream source, hr %#x.\n", hr); 4298 wined3d_mutex_unlock(); 4299 return hr; 4300 } 4301 4302 /* Now draw the primitives */ 4303 wined3d_device_set_primitive_type(device->wined3d_device, primitive_type, 0); 4304 hr = wined3d_device_draw_primitive(device->wined3d_device, start_vertex, vertex_count); 4305 4306 wined3d_mutex_unlock(); 4307 4308 return hr; 4309 } 4310 4311 static HRESULT WINAPI d3d_device7_DrawPrimitiveVB_FPUSetup(IDirect3DDevice7 *iface, D3DPRIMITIVETYPE PrimitiveType, 4312 IDirect3DVertexBuffer7 *D3DVertexBuf, DWORD StartVertex, DWORD NumVertices, DWORD Flags) 4313 { 4314 return d3d_device7_DrawPrimitiveVB(iface, PrimitiveType, D3DVertexBuf, StartVertex, NumVertices, Flags); 4315 } 4316 4317 static HRESULT WINAPI d3d_device7_DrawPrimitiveVB_FPUPreserve(IDirect3DDevice7 *iface, D3DPRIMITIVETYPE PrimitiveType, 4318 IDirect3DVertexBuffer7 *D3DVertexBuf, DWORD StartVertex, DWORD NumVertices, DWORD Flags) 4319 { 4320 HRESULT hr; 4321 WORD old_fpucw; 4322 4323 old_fpucw = d3d_fpu_setup(); 4324 hr = d3d_device7_DrawPrimitiveVB(iface, PrimitiveType, D3DVertexBuf, StartVertex, NumVertices, Flags); 4325 set_fpu_control_word(old_fpucw); 4326 4327 return hr; 4328 } 4329 4330 static HRESULT WINAPI d3d_device3_DrawPrimitiveVB(IDirect3DDevice3 *iface, D3DPRIMITIVETYPE PrimitiveType, 4331 IDirect3DVertexBuffer *D3DVertexBuf, DWORD StartVertex, DWORD NumVertices, DWORD Flags) 4332 { 4333 struct d3d_device *device = impl_from_IDirect3DDevice3(iface); 4334 struct d3d_vertex_buffer *vb = unsafe_impl_from_IDirect3DVertexBuffer7((IDirect3DVertexBuffer7 *)D3DVertexBuf); 4335 4336 TRACE("iface %p, primitive_type %#x, vb %p, start_vertex %u, vertex_count %u, flags %#x.\n", 4337 iface, PrimitiveType, D3DVertexBuf, StartVertex, NumVertices, Flags); 4338 4339 setup_lighting(device, vb->fvf, Flags); 4340 4341 return IDirect3DDevice7_DrawPrimitiveVB(&device->IDirect3DDevice7_iface, 4342 PrimitiveType, &vb->IDirect3DVertexBuffer7_iface, StartVertex, NumVertices, Flags); 4343 } 4344 4345 /***************************************************************************** 4346 * IDirect3DDevice7::DrawIndexedPrimitiveVB 4347 * 4348 * Draws primitives from a vertex buffer to the screen 4349 * 4350 * Params: 4351 * PrimitiveType: Type of primitive to be rendered. 4352 * D3DVertexBuf: Source Vertex Buffer 4353 * StartVertex: Index of the first vertex from the buffer to be rendered 4354 * NumVertices: Number of vertices to be rendered 4355 * Indices: Array of DWORDs used to index into the Vertices 4356 * IndexCount: Number of indices in Indices 4357 * Flags: Can be D3DDP_WAIT to wait until rendering has finished 4358 * 4359 * Return values 4360 * 4361 *****************************************************************************/ 4362 static HRESULT d3d_device7_DrawIndexedPrimitiveVB(IDirect3DDevice7 *iface, 4363 D3DPRIMITIVETYPE primitive_type, IDirect3DVertexBuffer7 *vb, 4364 DWORD start_vertex, DWORD vertex_count, WORD *indices, DWORD index_count, DWORD flags) 4365 { 4366 struct d3d_device *device = impl_from_IDirect3DDevice7(iface); 4367 struct d3d_vertex_buffer *vb_impl = unsafe_impl_from_IDirect3DVertexBuffer7(vb); 4368 DWORD stride = get_flexible_vertex_size(vb_impl->fvf); 4369 struct wined3d_map_desc wined3d_map_desc; 4370 struct wined3d_box wined3d_box = {0}; 4371 struct wined3d_resource *ib; 4372 HRESULT hr; 4373 UINT ib_pos; 4374 4375 TRACE("iface %p, primitive_type %#x, vb %p, start_vertex %u, " 4376 "vertex_count %u, indices %p, index_count %u, flags %#x.\n", 4377 iface, primitive_type, vb, start_vertex, vertex_count, indices, index_count, flags); 4378 4379 if (!vertex_count || !index_count) 4380 { 4381 WARN("0 vertex or index count.\n"); 4382 return D3D_OK; 4383 } 4384 4385 /* Steps: 4386 * 1) Upload the indices to the index buffer 4387 * 2) Set the index source 4388 * 3) Set the Vertex Buffer as the Stream source 4389 * 4) Call wined3d_device_draw_indexed_primitive() 4390 */ 4391 4392 wined3d_mutex_lock(); 4393 4394 wined3d_device_set_vertex_declaration(device->wined3d_device, vb_impl->wined3d_declaration); 4395 4396 hr = d3d_device_prepare_index_buffer(device, index_count * sizeof(WORD)); 4397 if (FAILED(hr)) 4398 { 4399 wined3d_mutex_unlock(); 4400 return hr; 4401 } 4402 ib_pos = device->index_buffer_pos; 4403 4404 if (device->index_buffer_size - index_count * sizeof(WORD) < ib_pos) 4405 ib_pos = 0; 4406 4407 /* Copy the index stream into the index buffer. */ 4408 wined3d_box.left = ib_pos; 4409 wined3d_box.right = ib_pos + index_count * sizeof(WORD); 4410 ib = wined3d_buffer_get_resource(device->index_buffer); 4411 if (FAILED(hr = wined3d_resource_map(ib, 0, &wined3d_map_desc, &wined3d_box, 4412 WINED3D_MAP_WRITE | (ib_pos ? WINED3D_MAP_NOOVERWRITE : WINED3D_MAP_DISCARD)))) 4413 { 4414 ERR("Failed to map buffer, hr %#x.\n", hr); 4415 wined3d_mutex_unlock(); 4416 return hr; 4417 } 4418 memcpy(wined3d_map_desc.data, indices, index_count * sizeof(WORD)); 4419 wined3d_resource_unmap(ib, 0); 4420 device->index_buffer_pos = ib_pos + index_count * sizeof(WORD); 4421 4422 /* Set the index stream */ 4423 wined3d_device_set_base_vertex_index(device->wined3d_device, start_vertex); 4424 wined3d_device_set_index_buffer(device->wined3d_device, device->index_buffer, WINED3DFMT_R16_UINT, 0); 4425 4426 /* Set the vertex stream source */ 4427 if (FAILED(hr = wined3d_device_set_stream_source(device->wined3d_device, 4428 0, vb_impl->wined3d_buffer, 0, stride))) 4429 { 4430 ERR("(%p) IDirect3DDevice::SetStreamSource failed with hr = %08x\n", device, hr); 4431 wined3d_mutex_unlock(); 4432 return hr; 4433 } 4434 4435 wined3d_device_set_primitive_type(device->wined3d_device, primitive_type, 0); 4436 hr = wined3d_device_draw_indexed_primitive(device->wined3d_device, ib_pos / sizeof(WORD), index_count); 4437 4438 wined3d_mutex_unlock(); 4439 4440 return hr; 4441 } 4442 4443 static HRESULT WINAPI d3d_device7_DrawIndexedPrimitiveVB_FPUSetup(IDirect3DDevice7 *iface, 4444 D3DPRIMITIVETYPE PrimitiveType, IDirect3DVertexBuffer7 *D3DVertexBuf, 4445 DWORD StartVertex, DWORD NumVertices, WORD *Indices, DWORD IndexCount, DWORD Flags) 4446 { 4447 return d3d_device7_DrawIndexedPrimitiveVB(iface, PrimitiveType, 4448 D3DVertexBuf, StartVertex, NumVertices, Indices, IndexCount, Flags); 4449 } 4450 4451 static HRESULT WINAPI d3d_device7_DrawIndexedPrimitiveVB_FPUPreserve(IDirect3DDevice7 *iface, 4452 D3DPRIMITIVETYPE PrimitiveType, IDirect3DVertexBuffer7 *D3DVertexBuf, 4453 DWORD StartVertex, DWORD NumVertices, WORD *Indices, DWORD IndexCount, DWORD Flags) 4454 { 4455 HRESULT hr; 4456 WORD old_fpucw; 4457 4458 old_fpucw = d3d_fpu_setup(); 4459 hr = d3d_device7_DrawIndexedPrimitiveVB(iface, PrimitiveType, 4460 D3DVertexBuf, StartVertex, NumVertices, Indices, IndexCount, Flags); 4461 set_fpu_control_word(old_fpucw); 4462 4463 return hr; 4464 } 4465 4466 static HRESULT WINAPI d3d_device3_DrawIndexedPrimitiveVB(IDirect3DDevice3 *iface, 4467 D3DPRIMITIVETYPE PrimitiveType, IDirect3DVertexBuffer *D3DVertexBuf, WORD *Indices, 4468 DWORD IndexCount, DWORD Flags) 4469 { 4470 struct d3d_device *device = impl_from_IDirect3DDevice3(iface); 4471 struct d3d_vertex_buffer *vb = unsafe_impl_from_IDirect3DVertexBuffer7((IDirect3DVertexBuffer7 *)D3DVertexBuf); 4472 4473 TRACE("iface %p, primitive_type %#x, vb %p, indices %p, index_count %u, flags %#x.\n", 4474 iface, PrimitiveType, D3DVertexBuf, Indices, IndexCount, Flags); 4475 4476 setup_lighting(device, vb->fvf, Flags); 4477 4478 return IDirect3DDevice7_DrawIndexedPrimitiveVB(&device->IDirect3DDevice7_iface, PrimitiveType, 4479 &vb->IDirect3DVertexBuffer7_iface, 0, IndexCount, Indices, IndexCount, Flags); 4480 } 4481 4482 /***************************************************************************** 4483 * IDirect3DDevice7::ComputeSphereVisibility 4484 * 4485 * Calculates the visibility of spheres in the current viewport. The spheres 4486 * are passed in the Centers and Radii arrays, the results are passed back 4487 * in the ReturnValues array. Return values are either completely visible, 4488 * partially visible or completely invisible. 4489 * The return value consists of a combination of D3DCLIP_* flags, or is 4490 * 0 if the sphere is completely visible (according to the SDK, not checked) 4491 * 4492 * Version 3 and 7 4493 * 4494 * Params: 4495 * Centers: Array containing the sphere centers 4496 * Radii: Array containing the sphere radii 4497 * NumSpheres: The number of centers and radii in the arrays 4498 * Flags: Some flags 4499 * ReturnValues: Array to write the results to 4500 * 4501 * Returns: 4502 * D3D_OK 4503 * (DDERR_INVALIDPARAMS if Centers, Radii or ReturnValues are NULL) 4504 * (D3DERR_INVALIDMATRIX if the combined world, view and proj matrix 4505 * is singular) 4506 * 4507 *****************************************************************************/ 4508 4509 static DWORD in_plane(UINT idx, struct wined3d_vec4 p, D3DVECTOR center, D3DVALUE radius, BOOL equality) 4510 { 4511 float distance, norm; 4512 4513 norm = sqrtf(p.x * p.x + p.y * p.y + p.z * p.z); 4514 distance = (p.x * center.u1.x + p.y * center.u2.y + p.z * center.u3.z + p.w) / norm; 4515 4516 if (equality) 4517 { 4518 if (fabs(distance) <= radius) 4519 return D3DSTATUS_CLIPUNIONLEFT << idx; 4520 if (distance <= -radius) 4521 return (D3DSTATUS_CLIPUNIONLEFT | D3DSTATUS_CLIPINTERSECTIONLEFT) << idx; 4522 } 4523 else 4524 { 4525 if (fabs(distance) < radius) 4526 return D3DSTATUS_CLIPUNIONLEFT << idx; 4527 if (distance < -radius) 4528 return (D3DSTATUS_CLIPUNIONLEFT | D3DSTATUS_CLIPINTERSECTIONLEFT) << idx; 4529 } 4530 return 0; 4531 } 4532 4533 static void prepare_clip_space_planes(struct d3d_device *device, struct wined3d_vec4 *plane) 4534 { 4535 D3DMATRIX m, temp; 4536 4537 /* We want the wined3d matrices since those include the legacy viewport 4538 * transformation. */ 4539 wined3d_mutex_lock(); 4540 wined3d_device_get_transform(device->wined3d_device, 4541 WINED3D_TS_WORLD, (struct wined3d_matrix *)&m); 4542 4543 wined3d_device_get_transform(device->wined3d_device, 4544 WINED3D_TS_VIEW, (struct wined3d_matrix *)&temp); 4545 multiply_matrix(&m, &temp, &m); 4546 4547 wined3d_device_get_transform(device->wined3d_device, 4548 WINED3D_TS_PROJECTION, (struct wined3d_matrix *)&temp); 4549 multiply_matrix(&m, &temp, &m); 4550 wined3d_mutex_unlock(); 4551 4552 /* Left plane. */ 4553 plane[0].x = m._14 + m._11; 4554 plane[0].y = m._24 + m._21; 4555 plane[0].z = m._34 + m._31; 4556 plane[0].w = m._44 + m._41; 4557 4558 /* Right plane. */ 4559 plane[1].x = m._14 - m._11; 4560 plane[1].y = m._24 - m._21; 4561 plane[1].z = m._34 - m._31; 4562 plane[1].w = m._44 - m._41; 4563 4564 /* Top plane. */ 4565 plane[2].x = m._14 - m._12; 4566 plane[2].y = m._24 - m._22; 4567 plane[2].z = m._34 - m._32; 4568 plane[2].w = m._44 - m._42; 4569 4570 /* Bottom plane. */ 4571 plane[3].x = m._14 + m._12; 4572 plane[3].y = m._24 + m._22; 4573 plane[3].z = m._34 + m._32; 4574 plane[3].w = m._44 + m._42; 4575 4576 /* Front plane. */ 4577 plane[4].x = m._13; 4578 plane[4].y = m._23; 4579 plane[4].z = m._33; 4580 plane[4].w = m._43; 4581 4582 /* Back plane. */ 4583 plane[5].x = m._14 - m._13; 4584 plane[5].y = m._24 - m._23; 4585 plane[5].z = m._34 - m._33; 4586 plane[5].w = m._44 - m._43; 4587 } 4588 4589 static void compute_sphere_visibility(struct wined3d_vec4 plane[12], DWORD enabled_planes, BOOL equality, 4590 D3DVECTOR *centers, D3DVALUE *radii, DWORD sphere_count, DWORD *return_values) 4591 { 4592 UINT i, j; 4593 4594 for (i = 0; i < sphere_count; ++i) 4595 { 4596 return_values[i] = 0; 4597 for (j = 0; j < 12; ++j) 4598 if (enabled_planes & 1u << j) 4599 return_values[i] |= in_plane(j, plane[j], centers[i], radii[i], equality); 4600 } 4601 } 4602 4603 static HRESULT WINAPI d3d_device7_ComputeSphereVisibility(IDirect3DDevice7 *iface, 4604 D3DVECTOR *centers, D3DVALUE *radii, DWORD sphere_count, DWORD flags, DWORD *return_values) 4605 { 4606 struct wined3d_vec4 plane[12]; 4607 DWORD enabled_planes = 0x3f; 4608 DWORD user_clip_planes; 4609 UINT j; 4610 4611 TRACE("iface %p, centers %p, radii %p, sphere_count %u, flags %#x, return_values %p.\n", 4612 iface, centers, radii, sphere_count, flags, return_values); 4613 4614 prepare_clip_space_planes(impl_from_IDirect3DDevice7(iface), plane); 4615 4616 IDirect3DDevice7_GetRenderState(iface, D3DRENDERSTATE_CLIPPLANEENABLE, &user_clip_planes); 4617 enabled_planes |= user_clip_planes << 6; 4618 for (j = 6; j < 12; ++j) 4619 IDirect3DDevice7_GetClipPlane(iface, j - 6, (D3DVALUE *)&plane[j]); 4620 4621 compute_sphere_visibility(plane, enabled_planes, FALSE, centers, radii, sphere_count, return_values); 4622 return D3D_OK; 4623 } 4624 4625 static HRESULT WINAPI d3d_device3_ComputeSphereVisibility(IDirect3DDevice3 *iface, 4626 D3DVECTOR *centers, D3DVALUE *radii, DWORD sphere_count, DWORD flags, DWORD *return_values) 4627 { 4628 static const DWORD enabled_planes = 0x3f; 4629 struct wined3d_vec4 plane[6]; 4630 unsigned int i, j; 4631 4632 TRACE("iface %p, centers %p, radii %p, sphere_count %u, flags %#x, return_values %p.\n", 4633 iface, centers, radii, sphere_count, flags, return_values); 4634 4635 prepare_clip_space_planes(impl_from_IDirect3DDevice3(iface), plane); 4636 4637 compute_sphere_visibility(plane, enabled_planes, TRUE, centers, radii, sphere_count, return_values); 4638 for (i = 0; i < sphere_count; ++i) 4639 { 4640 BOOL intersect_frustum = FALSE, outside_frustum = FALSE; 4641 DWORD d3d7_result = return_values[i]; 4642 4643 return_values[i] = 0; 4644 4645 for (j = 0; j < 6; ++j) 4646 { 4647 DWORD clip = (d3d7_result >> j) & (D3DSTATUS_CLIPUNIONLEFT | D3DSTATUS_CLIPINTERSECTIONLEFT); 4648 4649 if (clip == D3DSTATUS_CLIPUNIONLEFT) 4650 { 4651 return_values[i] |= D3DVIS_INTERSECT_LEFT << j * 2; 4652 intersect_frustum = TRUE; 4653 } 4654 else if (clip) 4655 { 4656 return_values[i] |= D3DVIS_OUTSIDE_LEFT << j * 2; 4657 outside_frustum = TRUE; 4658 } 4659 } 4660 if (outside_frustum) 4661 return_values[i] |= D3DVIS_OUTSIDE_FRUSTUM; 4662 else if (intersect_frustum) 4663 return_values[i] |= D3DVIS_INTERSECT_FRUSTUM; 4664 } 4665 return D3D_OK; 4666 } 4667 4668 /***************************************************************************** 4669 * IDirect3DDevice7::GetTexture 4670 * 4671 * Returns the texture interface handle assigned to a texture stage. 4672 * The returned texture is AddRefed. This is taken from old ddraw, 4673 * not checked in Windows. 4674 * 4675 * Version 3 and 7 4676 * 4677 * Params: 4678 * Stage: Texture stage to read the texture from 4679 * Texture: Address to store the interface pointer at 4680 * 4681 * Returns: 4682 * D3D_OK on success 4683 * DDERR_INVALIDPARAMS if Texture is NULL 4684 * 4685 *****************************************************************************/ 4686 static HRESULT d3d_device7_GetTexture(IDirect3DDevice7 *iface, 4687 DWORD stage, IDirectDrawSurface7 **texture) 4688 { 4689 struct d3d_device *device = impl_from_IDirect3DDevice7(iface); 4690 struct wined3d_texture *wined3d_texture; 4691 struct ddraw_texture *ddraw_texture; 4692 4693 TRACE("iface %p, stage %u, texture %p.\n", iface, stage, texture); 4694 4695 if (!texture) 4696 return DDERR_INVALIDPARAMS; 4697 4698 wined3d_mutex_lock(); 4699 if (!(wined3d_texture = wined3d_device_get_texture(device->wined3d_device, stage))) 4700 { 4701 *texture = NULL; 4702 wined3d_mutex_unlock(); 4703 return D3D_OK; 4704 } 4705 4706 ddraw_texture = wined3d_texture_get_parent(wined3d_texture); 4707 *texture = &ddraw_texture->root->IDirectDrawSurface7_iface; 4708 IDirectDrawSurface7_AddRef(*texture); 4709 wined3d_mutex_unlock(); 4710 4711 return D3D_OK; 4712 } 4713 4714 static HRESULT WINAPI d3d_device7_GetTexture_FPUSetup(IDirect3DDevice7 *iface, 4715 DWORD stage, IDirectDrawSurface7 **Texture) 4716 { 4717 return d3d_device7_GetTexture(iface, stage, Texture); 4718 } 4719 4720 static HRESULT WINAPI d3d_device7_GetTexture_FPUPreserve(IDirect3DDevice7 *iface, 4721 DWORD stage, IDirectDrawSurface7 **Texture) 4722 { 4723 HRESULT hr; 4724 WORD old_fpucw; 4725 4726 old_fpucw = d3d_fpu_setup(); 4727 hr = d3d_device7_GetTexture(iface, stage, Texture); 4728 set_fpu_control_word(old_fpucw); 4729 4730 return hr; 4731 } 4732 4733 static HRESULT WINAPI d3d_device3_GetTexture(IDirect3DDevice3 *iface, DWORD stage, IDirect3DTexture2 **Texture2) 4734 { 4735 struct d3d_device *device = impl_from_IDirect3DDevice3(iface); 4736 struct ddraw_surface *ret_val_impl; 4737 HRESULT ret; 4738 IDirectDrawSurface7 *ret_val; 4739 4740 TRACE("iface %p, stage %u, texture %p.\n", iface, stage, Texture2); 4741 4742 ret = IDirect3DDevice7_GetTexture(&device->IDirect3DDevice7_iface, stage, &ret_val); 4743 4744 ret_val_impl = unsafe_impl_from_IDirectDrawSurface7(ret_val); 4745 *Texture2 = ret_val_impl ? &ret_val_impl->IDirect3DTexture2_iface : NULL; 4746 4747 TRACE("Returning texture %p.\n", *Texture2); 4748 4749 return ret; 4750 } 4751 4752 /***************************************************************************** 4753 * IDirect3DDevice7::SetTexture 4754 * 4755 * Assigns a texture to a texture stage. Is the texture AddRef-ed? 4756 * 4757 * Version 3 and 7 4758 * 4759 * Params: 4760 * Stage: The stage to assign the texture to 4761 * Texture: Interface pointer to the texture surface 4762 * 4763 * Returns 4764 * D3D_OK on success 4765 * 4766 *****************************************************************************/ 4767 static HRESULT d3d_device7_SetTexture(IDirect3DDevice7 *iface, 4768 DWORD stage, IDirectDrawSurface7 *texture) 4769 { 4770 struct d3d_device *device = impl_from_IDirect3DDevice7(iface); 4771 struct ddraw_surface *surf = unsafe_impl_from_IDirectDrawSurface7(texture); 4772 struct wined3d_texture *wined3d_texture = NULL; 4773 HRESULT hr; 4774 4775 TRACE("iface %p, stage %u, texture %p.\n", iface, stage, texture); 4776 4777 if (surf && (surf->surface_desc.ddsCaps.dwCaps & DDSCAPS_TEXTURE)) 4778 wined3d_texture = surf->wined3d_texture; 4779 4780 wined3d_mutex_lock(); 4781 hr = wined3d_device_set_texture(device->wined3d_device, stage, wined3d_texture); 4782 wined3d_mutex_unlock(); 4783 4784 return hr; 4785 } 4786 4787 static HRESULT WINAPI d3d_device7_SetTexture_FPUSetup(IDirect3DDevice7 *iface, 4788 DWORD stage, IDirectDrawSurface7 *texture) 4789 { 4790 return d3d_device7_SetTexture(iface, stage, texture); 4791 } 4792 4793 static HRESULT WINAPI d3d_device7_SetTexture_FPUPreserve(IDirect3DDevice7 *iface, 4794 DWORD stage, IDirectDrawSurface7 *texture) 4795 { 4796 HRESULT hr; 4797 WORD old_fpucw; 4798 4799 old_fpucw = d3d_fpu_setup(); 4800 hr = d3d_device7_SetTexture(iface, stage, texture); 4801 set_fpu_control_word(old_fpucw); 4802 4803 return hr; 4804 } 4805 4806 static HRESULT WINAPI d3d_device3_SetTexture(IDirect3DDevice3 *iface, 4807 DWORD stage, IDirect3DTexture2 *texture) 4808 { 4809 struct d3d_device *device = impl_from_IDirect3DDevice3(iface); 4810 struct ddraw_surface *tex = unsafe_impl_from_IDirect3DTexture2(texture); 4811 DWORD texmapblend; 4812 HRESULT hr; 4813 4814 TRACE("iface %p, stage %u, texture %p.\n", iface, stage, texture); 4815 4816 wined3d_mutex_lock(); 4817 4818 if (device->legacyTextureBlending) 4819 IDirect3DDevice3_GetRenderState(iface, D3DRENDERSTATE_TEXTUREMAPBLEND, &texmapblend); 4820 4821 hr = IDirect3DDevice7_SetTexture(&device->IDirect3DDevice7_iface, stage, &tex->IDirectDrawSurface7_iface); 4822 4823 if (device->legacyTextureBlending && texmapblend == D3DTBLEND_MODULATE) 4824 { 4825 /* This fixup is required by the way D3DTBLEND_MODULATE maps to texture stage states. 4826 See d3d_device3_SetRenderState() for details. */ 4827 struct wined3d_texture *tex = NULL; 4828 BOOL tex_alpha = FALSE; 4829 DDPIXELFORMAT ddfmt; 4830 4831 if ((tex = wined3d_device_get_texture(device->wined3d_device, 0))) 4832 { 4833 struct wined3d_resource_desc desc; 4834 4835 wined3d_resource_get_desc(wined3d_texture_get_resource(tex), &desc); 4836 ddfmt.dwSize = sizeof(ddfmt); 4837 ddrawformat_from_wined3dformat(&ddfmt, desc.format); 4838 if (ddfmt.u5.dwRGBAlphaBitMask) 4839 tex_alpha = TRUE; 4840 } 4841 4842 /* Args 1 and 2 are already set to WINED3DTA_TEXTURE/WINED3DTA_CURRENT in case of D3DTBLEND_MODULATE */ 4843 if (tex_alpha) 4844 wined3d_device_set_texture_stage_state(device->wined3d_device, 4845 0, WINED3D_TSS_ALPHA_OP, WINED3D_TOP_SELECT_ARG1); 4846 else 4847 wined3d_device_set_texture_stage_state(device->wined3d_device, 4848 0, WINED3D_TSS_ALPHA_OP, WINED3D_TOP_SELECT_ARG2); 4849 } 4850 4851 wined3d_mutex_unlock(); 4852 4853 return hr; 4854 } 4855 4856 static const struct tss_lookup 4857 { 4858 BOOL sampler_state; 4859 union 4860 { 4861 enum wined3d_texture_stage_state texture_state; 4862 enum wined3d_sampler_state sampler_state; 4863 } u; 4864 } 4865 tss_lookup[] = 4866 { 4867 {FALSE, {WINED3D_TSS_INVALID}}, /* 0, unused */ 4868 {FALSE, {WINED3D_TSS_COLOR_OP}}, /* 1, D3DTSS_COLOROP */ 4869 {FALSE, {WINED3D_TSS_COLOR_ARG1}}, /* 2, D3DTSS_COLORARG1 */ 4870 {FALSE, {WINED3D_TSS_COLOR_ARG2}}, /* 3, D3DTSS_COLORARG2 */ 4871 {FALSE, {WINED3D_TSS_ALPHA_OP}}, /* 4, D3DTSS_ALPHAOP */ 4872 {FALSE, {WINED3D_TSS_ALPHA_ARG1}}, /* 5, D3DTSS_ALPHAARG1 */ 4873 {FALSE, {WINED3D_TSS_ALPHA_ARG2}}, /* 6, D3DTSS_ALPHAARG2 */ 4874 {FALSE, {WINED3D_TSS_BUMPENV_MAT00}}, /* 7, D3DTSS_BUMPENVMAT00 */ 4875 {FALSE, {WINED3D_TSS_BUMPENV_MAT01}}, /* 8, D3DTSS_BUMPENVMAT01 */ 4876 {FALSE, {WINED3D_TSS_BUMPENV_MAT10}}, /* 9, D3DTSS_BUMPENVMAT10 */ 4877 {FALSE, {WINED3D_TSS_BUMPENV_MAT11}}, /* 10, D3DTSS_BUMPENVMAT11 */ 4878 {FALSE, {WINED3D_TSS_TEXCOORD_INDEX}}, /* 11, D3DTSS_TEXCOORDINDEX */ 4879 {TRUE, {WINED3D_SAMP_ADDRESS_U}}, /* 12, D3DTSS_ADDRESS */ 4880 {TRUE, {WINED3D_SAMP_ADDRESS_U}}, /* 13, D3DTSS_ADDRESSU */ 4881 {TRUE, {WINED3D_SAMP_ADDRESS_V}}, /* 14, D3DTSS_ADDRESSV */ 4882 {TRUE, {WINED3D_SAMP_BORDER_COLOR}}, /* 15, D3DTSS_BORDERCOLOR */ 4883 {TRUE, {WINED3D_SAMP_MAG_FILTER}}, /* 16, D3DTSS_MAGFILTER */ 4884 {TRUE, {WINED3D_SAMP_MIN_FILTER}}, /* 17, D3DTSS_MINFILTER */ 4885 {TRUE, {WINED3D_SAMP_MIP_FILTER}}, /* 18, D3DTSS_MIPFILTER */ 4886 {TRUE, {WINED3D_SAMP_MIPMAP_LOD_BIAS}}, /* 19, D3DTSS_MIPMAPLODBIAS */ 4887 {TRUE, {WINED3D_SAMP_MAX_MIP_LEVEL}}, /* 20, D3DTSS_MAXMIPLEVEL */ 4888 {TRUE, {WINED3D_SAMP_MAX_ANISOTROPY}}, /* 21, D3DTSS_MAXANISOTROPY */ 4889 {FALSE, {WINED3D_TSS_BUMPENV_LSCALE}}, /* 22, D3DTSS_BUMPENVLSCALE */ 4890 {FALSE, {WINED3D_TSS_BUMPENV_LOFFSET}}, /* 23, D3DTSS_BUMPENVLOFFSET */ 4891 {FALSE, {WINED3D_TSS_TEXTURE_TRANSFORM_FLAGS}}, /* 24, D3DTSS_TEXTURETRANSFORMFLAGS */ 4892 }; 4893 4894 /***************************************************************************** 4895 * IDirect3DDevice7::GetTextureStageState 4896 * 4897 * Retrieves a state from a texture stage. 4898 * 4899 * Version 3 and 7 4900 * 4901 * Params: 4902 * Stage: The stage to retrieve the state from 4903 * TexStageStateType: The state type to retrieve 4904 * State: Address to store the state's value at 4905 * 4906 * Returns: 4907 * D3D_OK on success 4908 * DDERR_INVALIDPARAMS if State is NULL 4909 * 4910 *****************************************************************************/ 4911 static HRESULT d3d_device7_GetTextureStageState(IDirect3DDevice7 *iface, 4912 DWORD stage, D3DTEXTURESTAGESTATETYPE state, DWORD *value) 4913 { 4914 struct d3d_device *device = impl_from_IDirect3DDevice7(iface); 4915 const struct tss_lookup *l; 4916 4917 TRACE("iface %p, stage %u, state %#x, value %p.\n", 4918 iface, stage, state, value); 4919 4920 if (!value) 4921 return DDERR_INVALIDPARAMS; 4922 4923 if (state > D3DTSS_TEXTURETRANSFORMFLAGS) 4924 { 4925 WARN("Invalid state %#x passed.\n", state); 4926 return DD_OK; 4927 } 4928 4929 l = &tss_lookup[state]; 4930 4931 wined3d_mutex_lock(); 4932 4933 if (l->sampler_state) 4934 { 4935 *value = wined3d_device_get_sampler_state(device->wined3d_device, stage, l->u.sampler_state); 4936 4937 switch (state) 4938 { 4939 /* Mipfilter is a sampler state with different values */ 4940 case D3DTSS_MIPFILTER: 4941 { 4942 switch (*value) 4943 { 4944 case WINED3D_TEXF_NONE: 4945 *value = D3DTFP_NONE; 4946 break; 4947 case WINED3D_TEXF_POINT: 4948 *value = D3DTFP_POINT; 4949 break; 4950 case WINED3D_TEXF_LINEAR: 4951 *value = D3DTFP_LINEAR; 4952 break; 4953 default: 4954 ERR("Unexpected mipfilter value %#x.\n", *value); 4955 *value = D3DTFP_NONE; 4956 break; 4957 } 4958 break; 4959 } 4960 4961 /* Magfilter has slightly different values */ 4962 case D3DTSS_MAGFILTER: 4963 { 4964 switch (*value) 4965 { 4966 case WINED3D_TEXF_POINT: 4967 *value = D3DTFG_POINT; 4968 break; 4969 case WINED3D_TEXF_LINEAR: 4970 *value = D3DTFG_LINEAR; 4971 break; 4972 case WINED3D_TEXF_ANISOTROPIC: 4973 *value = D3DTFG_ANISOTROPIC; 4974 break; 4975 case WINED3D_TEXF_FLAT_CUBIC: 4976 *value = D3DTFG_FLATCUBIC; 4977 break; 4978 case WINED3D_TEXF_GAUSSIAN_CUBIC: 4979 *value = D3DTFG_GAUSSIANCUBIC; 4980 break; 4981 default: 4982 ERR("Unexpected wined3d mag filter value %#x.\n", *value); 4983 *value = D3DTFG_POINT; 4984 break; 4985 } 4986 break; 4987 } 4988 4989 default: 4990 break; 4991 } 4992 } 4993 else 4994 { 4995 *value = wined3d_device_get_texture_stage_state(device->wined3d_device, stage, l->u.texture_state); 4996 } 4997 4998 wined3d_mutex_unlock(); 4999 5000 return D3D_OK; 5001 } 5002 5003 static HRESULT WINAPI d3d_device7_GetTextureStageState_FPUSetup(IDirect3DDevice7 *iface, 5004 DWORD stage, D3DTEXTURESTAGESTATETYPE state, DWORD *value) 5005 { 5006 return d3d_device7_GetTextureStageState(iface, stage, state, value); 5007 } 5008 5009 static HRESULT WINAPI d3d_device7_GetTextureStageState_FPUPreserve(IDirect3DDevice7 *iface, 5010 DWORD stage, D3DTEXTURESTAGESTATETYPE state, DWORD *value) 5011 { 5012 HRESULT hr; 5013 WORD old_fpucw; 5014 5015 old_fpucw = d3d_fpu_setup(); 5016 hr = d3d_device7_GetTextureStageState(iface, stage, state, value); 5017 set_fpu_control_word(old_fpucw); 5018 5019 return hr; 5020 } 5021 5022 static HRESULT WINAPI d3d_device3_GetTextureStageState(IDirect3DDevice3 *iface, 5023 DWORD stage, D3DTEXTURESTAGESTATETYPE state, DWORD *value) 5024 { 5025 struct d3d_device *device = impl_from_IDirect3DDevice3(iface); 5026 5027 TRACE("iface %p, stage %u, state %#x, value %p.\n", 5028 iface, stage, state, value); 5029 5030 return IDirect3DDevice7_GetTextureStageState(&device->IDirect3DDevice7_iface, stage, state, value); 5031 } 5032 5033 /***************************************************************************** 5034 * IDirect3DDevice7::SetTextureStageState 5035 * 5036 * Sets a texture stage state. Some stage types need to be handled specially, 5037 * because they do not exist in WineD3D and were moved to another place 5038 * 5039 * Version 3 and 7 5040 * 5041 * Params: 5042 * Stage: The stage to modify 5043 * TexStageStateType: The state to change 5044 * State: The new value for the state 5045 * 5046 * Returns: 5047 * D3D_OK on success 5048 * 5049 *****************************************************************************/ 5050 static HRESULT d3d_device7_SetTextureStageState(IDirect3DDevice7 *iface, 5051 DWORD stage, D3DTEXTURESTAGESTATETYPE state, DWORD value) 5052 { 5053 struct d3d_device *device = impl_from_IDirect3DDevice7(iface); 5054 const struct tss_lookup *l; 5055 5056 TRACE("iface %p, stage %u, state %#x, value %#x.\n", 5057 iface, stage, state, value); 5058 5059 if (state > D3DTSS_TEXTURETRANSFORMFLAGS) 5060 { 5061 WARN("Invalid state %#x passed.\n", state); 5062 return DD_OK; 5063 } 5064 5065 l = &tss_lookup[state]; 5066 5067 wined3d_mutex_lock(); 5068 5069 if (l->sampler_state) 5070 { 5071 switch (state) 5072 { 5073 /* Mipfilter is a sampler state with different values */ 5074 case D3DTSS_MIPFILTER: 5075 { 5076 switch (value) 5077 { 5078 case D3DTFP_NONE: 5079 value = WINED3D_TEXF_NONE; 5080 break; 5081 case D3DTFP_POINT: 5082 value = WINED3D_TEXF_POINT; 5083 break; 5084 case 0: /* Unchecked */ 5085 case D3DTFP_LINEAR: 5086 value = WINED3D_TEXF_LINEAR; 5087 break; 5088 default: 5089 ERR("Unexpected mipfilter value %#x.\n", value); 5090 value = WINED3D_TEXF_NONE; 5091 break; 5092 } 5093 break; 5094 } 5095 5096 /* Magfilter has slightly different values */ 5097 case D3DTSS_MAGFILTER: 5098 { 5099 switch (value) 5100 { 5101 case D3DTFG_POINT: 5102 value = WINED3D_TEXF_POINT; 5103 break; 5104 case D3DTFG_LINEAR: 5105 value = WINED3D_TEXF_LINEAR; 5106 break; 5107 case D3DTFG_FLATCUBIC: 5108 value = WINED3D_TEXF_FLAT_CUBIC; 5109 break; 5110 case D3DTFG_GAUSSIANCUBIC: 5111 value = WINED3D_TEXF_GAUSSIAN_CUBIC; 5112 break; 5113 case D3DTFG_ANISOTROPIC: 5114 value = WINED3D_TEXF_ANISOTROPIC; 5115 break; 5116 default: 5117 ERR("Unexpected d3d7 mag filter value %#x.\n", value); 5118 value = WINED3D_TEXF_POINT; 5119 break; 5120 } 5121 break; 5122 } 5123 5124 case D3DTSS_ADDRESS: 5125 wined3d_device_set_sampler_state(device->wined3d_device, stage, WINED3D_SAMP_ADDRESS_V, value); 5126 break; 5127 5128 default: 5129 break; 5130 } 5131 5132 wined3d_device_set_sampler_state(device->wined3d_device, stage, l->u.sampler_state, value); 5133 } 5134 else 5135 { 5136 wined3d_device_set_texture_stage_state(device->wined3d_device, stage, l->u.texture_state, value); 5137 } 5138 5139 wined3d_mutex_unlock(); 5140 5141 return D3D_OK; 5142 } 5143 5144 static HRESULT WINAPI d3d_device7_SetTextureStageState_FPUSetup(IDirect3DDevice7 *iface, 5145 DWORD stage, D3DTEXTURESTAGESTATETYPE state, DWORD value) 5146 { 5147 return d3d_device7_SetTextureStageState(iface, stage, state, value); 5148 } 5149 5150 static HRESULT WINAPI d3d_device7_SetTextureStageState_FPUPreserve(IDirect3DDevice7 *iface, 5151 DWORD stage, D3DTEXTURESTAGESTATETYPE state, DWORD value) 5152 { 5153 HRESULT hr; 5154 WORD old_fpucw; 5155 5156 old_fpucw = d3d_fpu_setup(); 5157 hr = d3d_device7_SetTextureStageState(iface, stage, state, value); 5158 set_fpu_control_word(old_fpucw); 5159 5160 return hr; 5161 } 5162 5163 static HRESULT WINAPI d3d_device3_SetTextureStageState(IDirect3DDevice3 *iface, 5164 DWORD stage, D3DTEXTURESTAGESTATETYPE state, DWORD value) 5165 { 5166 struct d3d_device *device = impl_from_IDirect3DDevice3(iface); 5167 5168 TRACE("iface %p, stage %u, state %#x, value %#x.\n", 5169 iface, stage, state, value); 5170 5171 return IDirect3DDevice7_SetTextureStageState(&device->IDirect3DDevice7_iface, stage, state, value); 5172 } 5173 5174 /***************************************************************************** 5175 * IDirect3DDevice7::ValidateDevice 5176 * 5177 * SDK: "Reports the device's ability to render the currently set 5178 * texture-blending operations in a single pass". Whatever that means 5179 * exactly... 5180 * 5181 * Version 3 and 7 5182 * 5183 * Params: 5184 * NumPasses: Address to write the number of necessary passes for the 5185 * desired effect to. 5186 * 5187 * Returns: 5188 * D3D_OK on success 5189 * 5190 *****************************************************************************/ 5191 static HRESULT d3d_device7_ValidateDevice(IDirect3DDevice7 *iface, DWORD *pass_count) 5192 { 5193 struct d3d_device *device = impl_from_IDirect3DDevice7(iface); 5194 HRESULT hr; 5195 5196 TRACE("iface %p, pass_count %p.\n", iface, pass_count); 5197 5198 wined3d_mutex_lock(); 5199 hr = wined3d_device_validate_device(device->wined3d_device, pass_count); 5200 wined3d_mutex_unlock(); 5201 5202 return hr; 5203 } 5204 5205 static HRESULT WINAPI d3d_device7_ValidateDevice_FPUSetup(IDirect3DDevice7 *iface, DWORD *pass_count) 5206 { 5207 return d3d_device7_ValidateDevice(iface, pass_count); 5208 } 5209 5210 static HRESULT WINAPI d3d_device7_ValidateDevice_FPUPreserve(IDirect3DDevice7 *iface, DWORD *pass_count) 5211 { 5212 HRESULT hr; 5213 WORD old_fpucw; 5214 5215 old_fpucw = d3d_fpu_setup(); 5216 hr = d3d_device7_ValidateDevice(iface, pass_count); 5217 set_fpu_control_word(old_fpucw); 5218 5219 return hr; 5220 } 5221 5222 static HRESULT WINAPI d3d_device3_ValidateDevice(IDirect3DDevice3 *iface, DWORD *pass_count) 5223 { 5224 struct d3d_device *device = impl_from_IDirect3DDevice3(iface); 5225 5226 TRACE("iface %p, pass_count %p.\n", iface, pass_count); 5227 5228 return IDirect3DDevice7_ValidateDevice(&device->IDirect3DDevice7_iface, pass_count); 5229 } 5230 5231 /***************************************************************************** 5232 * IDirect3DDevice7::Clear 5233 * 5234 * Fills the render target, the z buffer and the stencil buffer with a 5235 * clear color / value 5236 * 5237 * Version 7 only 5238 * 5239 * Params: 5240 * Count: Number of rectangles in Rects must be 0 if Rects is NULL 5241 * Rects: Rectangles to clear. If NULL, the whole surface is cleared 5242 * Flags: Some flags, as usual 5243 * Color: Clear color for the render target 5244 * Z: Clear value for the Z buffer 5245 * Stencil: Clear value to store in each stencil buffer entry 5246 * 5247 * Returns: 5248 * D3D_OK on success 5249 * 5250 *****************************************************************************/ 5251 static HRESULT d3d_device7_Clear(IDirect3DDevice7 *iface, DWORD count, 5252 D3DRECT *rects, DWORD flags, D3DCOLOR color, D3DVALUE z, DWORD stencil) 5253 { 5254 const struct wined3d_color c = 5255 { 5256 ((color >> 16) & 0xff) / 255.0f, 5257 ((color >> 8) & 0xff) / 255.0f, 5258 (color & 0xff) / 255.0f, 5259 ((color >> 24) & 0xff) / 255.0f, 5260 }; 5261 struct d3d_device *This = impl_from_IDirect3DDevice7(iface); 5262 HRESULT hr; 5263 5264 TRACE("iface %p, count %u, rects %p, flags %#x, color 0x%08x, z %.8e, stencil %#x.\n", 5265 iface, count, rects, flags, color, z, stencil); 5266 5267 if (count && !rects) 5268 { 5269 WARN("count %u with NULL rects.\n", count); 5270 count = 0; 5271 } 5272 5273 wined3d_mutex_lock(); 5274 hr = wined3d_device_clear(This->wined3d_device, count, (RECT *)rects, flags, &c, z, stencil); 5275 wined3d_mutex_unlock(); 5276 5277 return hr; 5278 } 5279 5280 static HRESULT WINAPI d3d_device7_Clear_FPUSetup(IDirect3DDevice7 *iface, DWORD count, 5281 D3DRECT *rects, DWORD flags, D3DCOLOR color, D3DVALUE z, DWORD stencil) 5282 { 5283 return d3d_device7_Clear(iface, count, rects, flags, color, z, stencil); 5284 } 5285 5286 static HRESULT WINAPI d3d_device7_Clear_FPUPreserve(IDirect3DDevice7 *iface, DWORD count, 5287 D3DRECT *rects, DWORD flags, D3DCOLOR color, D3DVALUE z, DWORD stencil) 5288 { 5289 HRESULT hr; 5290 WORD old_fpucw; 5291 5292 old_fpucw = d3d_fpu_setup(); 5293 hr = d3d_device7_Clear(iface, count, rects, flags, color, z, stencil); 5294 set_fpu_control_word(old_fpucw); 5295 5296 return hr; 5297 } 5298 5299 /***************************************************************************** 5300 * IDirect3DDevice7::SetViewport 5301 * 5302 * Sets the current viewport. 5303 * 5304 * Version 7 only, but IDirect3DViewport uses this call for older 5305 * versions 5306 * 5307 * Params: 5308 * Data: The new viewport to set 5309 * 5310 * Returns: 5311 * D3D_OK on success 5312 * DDERR_INVALIDPARAMS if Data is NULL 5313 * 5314 *****************************************************************************/ 5315 static HRESULT d3d_device7_SetViewport(IDirect3DDevice7 *iface, D3DVIEWPORT7 *viewport) 5316 { 5317 struct d3d_device *device = impl_from_IDirect3DDevice7(iface); 5318 struct wined3d_viewport vp; 5319 5320 TRACE("iface %p, viewport %p.\n", iface, viewport); 5321 5322 if (!viewport) 5323 return DDERR_INVALIDPARAMS; 5324 5325 vp.x = viewport->dwX; 5326 vp.y = viewport->dwY; 5327 vp.width = viewport->dwWidth; 5328 vp.height = viewport->dwHeight; 5329 vp.min_z = viewport->dvMinZ; 5330 vp.max_z = viewport->dvMaxZ; 5331 5332 wined3d_mutex_lock(); 5333 wined3d_device_set_viewport(device->wined3d_device, &vp); 5334 wined3d_mutex_unlock(); 5335 5336 return D3D_OK; 5337 } 5338 5339 static HRESULT WINAPI d3d_device7_SetViewport_FPUSetup(IDirect3DDevice7 *iface, D3DVIEWPORT7 *viewport) 5340 { 5341 return d3d_device7_SetViewport(iface, viewport); 5342 } 5343 5344 static HRESULT WINAPI d3d_device7_SetViewport_FPUPreserve(IDirect3DDevice7 *iface, D3DVIEWPORT7 *viewport) 5345 { 5346 HRESULT hr; 5347 WORD old_fpucw; 5348 5349 old_fpucw = d3d_fpu_setup(); 5350 hr = d3d_device7_SetViewport(iface, viewport); 5351 set_fpu_control_word(old_fpucw); 5352 5353 return hr; 5354 } 5355 5356 /***************************************************************************** 5357 * IDirect3DDevice::GetViewport 5358 * 5359 * Returns the current viewport 5360 * 5361 * Version 7 5362 * 5363 * Params: 5364 * Data: D3D7Viewport structure to write the viewport information to 5365 * 5366 * Returns: 5367 * D3D_OK on success 5368 * DDERR_INVALIDPARAMS if Data is NULL 5369 * 5370 *****************************************************************************/ 5371 static HRESULT d3d_device7_GetViewport(IDirect3DDevice7 *iface, D3DVIEWPORT7 *viewport) 5372 { 5373 struct d3d_device *device = impl_from_IDirect3DDevice7(iface); 5374 struct wined3d_viewport wined3d_viewport; 5375 5376 TRACE("iface %p, viewport %p.\n", iface, viewport); 5377 5378 if (!viewport) 5379 return DDERR_INVALIDPARAMS; 5380 5381 wined3d_mutex_lock(); 5382 wined3d_device_get_viewport(device->wined3d_device, &wined3d_viewport); 5383 wined3d_mutex_unlock(); 5384 5385 viewport->dwX = wined3d_viewport.x; 5386 viewport->dwY = wined3d_viewport.y; 5387 viewport->dwWidth = wined3d_viewport.width; 5388 viewport->dwHeight = wined3d_viewport.height; 5389 viewport->dvMinZ = wined3d_viewport.min_z; 5390 viewport->dvMaxZ = wined3d_viewport.max_z; 5391 5392 return D3D_OK; 5393 } 5394 5395 static HRESULT WINAPI d3d_device7_GetViewport_FPUSetup(IDirect3DDevice7 *iface, D3DVIEWPORT7 *viewport) 5396 { 5397 return d3d_device7_GetViewport(iface, viewport); 5398 } 5399 5400 static HRESULT WINAPI d3d_device7_GetViewport_FPUPreserve(IDirect3DDevice7 *iface, D3DVIEWPORT7 *viewport) 5401 { 5402 HRESULT hr; 5403 WORD old_fpucw; 5404 5405 old_fpucw = d3d_fpu_setup(); 5406 hr = d3d_device7_GetViewport(iface, viewport); 5407 set_fpu_control_word(old_fpucw); 5408 5409 return hr; 5410 } 5411 5412 /***************************************************************************** 5413 * IDirect3DDevice7::SetMaterial 5414 * 5415 * Sets the Material 5416 * 5417 * Version 7 5418 * 5419 * Params: 5420 * Mat: The material to set 5421 * 5422 * Returns: 5423 * D3D_OK on success 5424 * DDERR_INVALIDPARAMS if Mat is NULL. 5425 * 5426 *****************************************************************************/ 5427 static HRESULT d3d_device7_SetMaterial(IDirect3DDevice7 *iface, D3DMATERIAL7 *material) 5428 { 5429 struct d3d_device *device = impl_from_IDirect3DDevice7(iface); 5430 5431 TRACE("iface %p, material %p.\n", iface, material); 5432 5433 if (!material) 5434 return DDERR_INVALIDPARAMS; 5435 5436 wined3d_mutex_lock(); 5437 /* Note: D3DMATERIAL7 is compatible with struct wined3d_material. */ 5438 wined3d_device_set_material(device->wined3d_device, (struct wined3d_material *)material); 5439 wined3d_mutex_unlock(); 5440 5441 return D3D_OK; 5442 } 5443 5444 static HRESULT WINAPI d3d_device7_SetMaterial_FPUSetup(IDirect3DDevice7 *iface, D3DMATERIAL7 *material) 5445 { 5446 return d3d_device7_SetMaterial(iface, material); 5447 } 5448 5449 static HRESULT WINAPI d3d_device7_SetMaterial_FPUPreserve(IDirect3DDevice7 *iface, D3DMATERIAL7 *material) 5450 { 5451 HRESULT hr; 5452 WORD old_fpucw; 5453 5454 old_fpucw = d3d_fpu_setup(); 5455 hr = d3d_device7_SetMaterial(iface, material); 5456 set_fpu_control_word(old_fpucw); 5457 5458 return hr; 5459 } 5460 5461 /***************************************************************************** 5462 * IDirect3DDevice7::GetMaterial 5463 * 5464 * Returns the current material 5465 * 5466 * Version 7 5467 * 5468 * Params: 5469 * Mat: D3DMATERIAL7 structure to write the material parameters to 5470 * 5471 * Returns: 5472 * D3D_OK on success 5473 * DDERR_INVALIDPARAMS if Mat is NULL 5474 * 5475 *****************************************************************************/ 5476 static HRESULT d3d_device7_GetMaterial(IDirect3DDevice7 *iface, D3DMATERIAL7 *material) 5477 { 5478 struct d3d_device *device = impl_from_IDirect3DDevice7(iface); 5479 5480 TRACE("iface %p, material %p.\n", iface, material); 5481 5482 wined3d_mutex_lock(); 5483 /* Note: D3DMATERIAL7 is compatible with struct wined3d_material. */ 5484 wined3d_device_get_material(device->wined3d_device, (struct wined3d_material *)material); 5485 wined3d_mutex_unlock(); 5486 5487 return D3D_OK; 5488 } 5489 5490 static HRESULT WINAPI d3d_device7_GetMaterial_FPUSetup(IDirect3DDevice7 *iface, D3DMATERIAL7 *material) 5491 { 5492 return d3d_device7_GetMaterial(iface, material); 5493 } 5494 5495 static HRESULT WINAPI d3d_device7_GetMaterial_FPUPreserve(IDirect3DDevice7 *iface, D3DMATERIAL7 *material) 5496 { 5497 HRESULT hr; 5498 WORD old_fpucw; 5499 5500 old_fpucw = d3d_fpu_setup(); 5501 hr = d3d_device7_GetMaterial(iface, material); 5502 set_fpu_control_word(old_fpucw); 5503 5504 return hr; 5505 } 5506 5507 /***************************************************************************** 5508 * IDirect3DDevice7::SetLight 5509 * 5510 * Assigns a light to a light index, but doesn't activate it yet. 5511 * 5512 * Version 7, IDirect3DLight uses this method for older versions 5513 * 5514 * Params: 5515 * LightIndex: The index of the new light 5516 * Light: A D3DLIGHT7 structure describing the light 5517 * 5518 * Returns: 5519 * D3D_OK on success 5520 * 5521 *****************************************************************************/ 5522 static HRESULT d3d_device7_SetLight(IDirect3DDevice7 *iface, DWORD light_idx, D3DLIGHT7 *light) 5523 { 5524 struct d3d_device *device = impl_from_IDirect3DDevice7(iface); 5525 HRESULT hr; 5526 5527 TRACE("iface %p, light_idx %u, light %p.\n", iface, light_idx, light); 5528 5529 wined3d_mutex_lock(); 5530 /* Note: D3DLIGHT7 is compatible with struct wined3d_light. */ 5531 hr = wined3d_device_set_light(device->wined3d_device, light_idx, (struct wined3d_light *)light); 5532 wined3d_mutex_unlock(); 5533 5534 return hr_ddraw_from_wined3d(hr); 5535 } 5536 5537 static HRESULT WINAPI d3d_device7_SetLight_FPUSetup(IDirect3DDevice7 *iface, DWORD light_idx, D3DLIGHT7 *light) 5538 { 5539 return d3d_device7_SetLight(iface, light_idx, light); 5540 } 5541 5542 static HRESULT WINAPI d3d_device7_SetLight_FPUPreserve(IDirect3DDevice7 *iface, DWORD light_idx, D3DLIGHT7 *light) 5543 { 5544 HRESULT hr; 5545 WORD old_fpucw; 5546 5547 old_fpucw = d3d_fpu_setup(); 5548 hr = d3d_device7_SetLight(iface, light_idx, light); 5549 set_fpu_control_word(old_fpucw); 5550 5551 return hr; 5552 } 5553 5554 /***************************************************************************** 5555 * IDirect3DDevice7::GetLight 5556 * 5557 * Returns the light assigned to a light index 5558 * 5559 * Params: 5560 * Light: Structure to write the light information to 5561 * 5562 * Returns: 5563 * D3D_OK on success 5564 * DDERR_INVALIDPARAMS if Light is NULL 5565 * 5566 *****************************************************************************/ 5567 static HRESULT d3d_device7_GetLight(IDirect3DDevice7 *iface, DWORD light_idx, D3DLIGHT7 *light) 5568 { 5569 struct d3d_device *device = impl_from_IDirect3DDevice7(iface); 5570 HRESULT rc; 5571 5572 TRACE("iface %p, light_idx %u, light %p.\n", iface, light_idx, light); 5573 5574 wined3d_mutex_lock(); 5575 /* Note: D3DLIGHT7 is compatible with struct wined3d_light. */ 5576 rc = wined3d_device_get_light(device->wined3d_device, light_idx, (struct wined3d_light *)light); 5577 wined3d_mutex_unlock(); 5578 5579 /* Translate the result. WineD3D returns other values than D3D7 */ 5580 return hr_ddraw_from_wined3d(rc); 5581 } 5582 5583 static HRESULT WINAPI d3d_device7_GetLight_FPUSetup(IDirect3DDevice7 *iface, DWORD light_idx, D3DLIGHT7 *light) 5584 { 5585 return d3d_device7_GetLight(iface, light_idx, light); 5586 } 5587 5588 static HRESULT WINAPI d3d_device7_GetLight_FPUPreserve(IDirect3DDevice7 *iface, DWORD light_idx, D3DLIGHT7 *light) 5589 { 5590 HRESULT hr; 5591 WORD old_fpucw; 5592 5593 old_fpucw = d3d_fpu_setup(); 5594 hr = d3d_device7_GetLight(iface, light_idx, light); 5595 set_fpu_control_word(old_fpucw); 5596 5597 return hr; 5598 } 5599 5600 /***************************************************************************** 5601 * IDirect3DDevice7::BeginStateBlock 5602 * 5603 * Begins recording to a stateblock 5604 * 5605 * Version 7 5606 * 5607 * Returns: 5608 * D3D_OK on success 5609 * 5610 *****************************************************************************/ 5611 static HRESULT d3d_device7_BeginStateBlock(IDirect3DDevice7 *iface) 5612 { 5613 struct d3d_device *device = impl_from_IDirect3DDevice7(iface); 5614 HRESULT hr; 5615 5616 TRACE("iface %p.\n", iface); 5617 5618 wined3d_mutex_lock(); 5619 hr = wined3d_device_begin_stateblock(device->wined3d_device); 5620 wined3d_mutex_unlock(); 5621 5622 return hr_ddraw_from_wined3d(hr); 5623 } 5624 5625 static HRESULT WINAPI d3d_device7_BeginStateBlock_FPUSetup(IDirect3DDevice7 *iface) 5626 { 5627 return d3d_device7_BeginStateBlock(iface); 5628 } 5629 5630 static HRESULT WINAPI d3d_device7_BeginStateBlock_FPUPreserve(IDirect3DDevice7 *iface) 5631 { 5632 HRESULT hr; 5633 WORD old_fpucw; 5634 5635 old_fpucw = d3d_fpu_setup(); 5636 hr = d3d_device7_BeginStateBlock(iface); 5637 set_fpu_control_word(old_fpucw); 5638 5639 return hr; 5640 } 5641 5642 /***************************************************************************** 5643 * IDirect3DDevice7::EndStateBlock 5644 * 5645 * Stops recording to a state block and returns the created stateblock 5646 * handle. 5647 * 5648 * Version 7 5649 * 5650 * Params: 5651 * BlockHandle: Address to store the stateblock's handle to 5652 * 5653 * Returns: 5654 * D3D_OK on success 5655 * DDERR_INVALIDPARAMS if BlockHandle is NULL 5656 * 5657 *****************************************************************************/ 5658 static HRESULT d3d_device7_EndStateBlock(IDirect3DDevice7 *iface, DWORD *stateblock) 5659 { 5660 struct d3d_device *device = impl_from_IDirect3DDevice7(iface); 5661 struct wined3d_stateblock *wined3d_sb; 5662 HRESULT hr; 5663 DWORD h; 5664 5665 TRACE("iface %p, stateblock %p.\n", iface, stateblock); 5666 5667 if (!stateblock) 5668 return DDERR_INVALIDPARAMS; 5669 5670 wined3d_mutex_lock(); 5671 5672 hr = wined3d_device_end_stateblock(device->wined3d_device, &wined3d_sb); 5673 if (FAILED(hr)) 5674 { 5675 WARN("Failed to end stateblock, hr %#x.\n", hr); 5676 wined3d_mutex_unlock(); 5677 *stateblock = 0; 5678 return hr_ddraw_from_wined3d(hr); 5679 } 5680 5681 h = ddraw_allocate_handle(&device->handle_table, wined3d_sb, DDRAW_HANDLE_STATEBLOCK); 5682 if (h == DDRAW_INVALID_HANDLE) 5683 { 5684 ERR("Failed to allocate a stateblock handle.\n"); 5685 wined3d_stateblock_decref(wined3d_sb); 5686 wined3d_mutex_unlock(); 5687 *stateblock = 0; 5688 return DDERR_OUTOFMEMORY; 5689 } 5690 5691 wined3d_mutex_unlock(); 5692 *stateblock = h + 1; 5693 5694 return hr_ddraw_from_wined3d(hr); 5695 } 5696 5697 static HRESULT WINAPI d3d_device7_EndStateBlock_FPUSetup(IDirect3DDevice7 *iface, DWORD *stateblock) 5698 { 5699 return d3d_device7_EndStateBlock(iface, stateblock); 5700 } 5701 5702 static HRESULT WINAPI d3d_device7_EndStateBlock_FPUPreserve(IDirect3DDevice7 *iface, DWORD *stateblock) 5703 { 5704 HRESULT hr; 5705 WORD old_fpucw; 5706 5707 old_fpucw = d3d_fpu_setup(); 5708 hr = d3d_device7_EndStateBlock(iface, stateblock); 5709 set_fpu_control_word(old_fpucw); 5710 5711 return hr; 5712 } 5713 5714 /***************************************************************************** 5715 * IDirect3DDevice7::PreLoad 5716 * 5717 * Allows the app to signal that a texture will be used soon, to allow 5718 * the Direct3DDevice to load it to the video card in the meantime. 5719 * 5720 * Version 7 5721 * 5722 * Params: 5723 * Texture: The texture to preload 5724 * 5725 * Returns: 5726 * D3D_OK on success 5727 * DDERR_INVALIDPARAMS if Texture is NULL 5728 * 5729 *****************************************************************************/ 5730 static HRESULT d3d_device7_PreLoad(IDirect3DDevice7 *iface, IDirectDrawSurface7 *texture) 5731 { 5732 struct ddraw_surface *surface = unsafe_impl_from_IDirectDrawSurface7(texture); 5733 5734 TRACE("iface %p, texture %p.\n", iface, texture); 5735 5736 if (!texture) 5737 return DDERR_INVALIDPARAMS; 5738 5739 wined3d_mutex_lock(); 5740 wined3d_resource_preload(wined3d_texture_get_resource(surface->wined3d_texture)); 5741 wined3d_mutex_unlock(); 5742 5743 return D3D_OK; 5744 } 5745 5746 static HRESULT WINAPI d3d_device7_PreLoad_FPUSetup(IDirect3DDevice7 *iface, IDirectDrawSurface7 *texture) 5747 { 5748 return d3d_device7_PreLoad(iface, texture); 5749 } 5750 5751 static HRESULT WINAPI d3d_device7_PreLoad_FPUPreserve(IDirect3DDevice7 *iface, IDirectDrawSurface7 *texture) 5752 { 5753 HRESULT hr; 5754 WORD old_fpucw; 5755 5756 old_fpucw = d3d_fpu_setup(); 5757 hr = d3d_device7_PreLoad(iface, texture); 5758 set_fpu_control_word(old_fpucw); 5759 5760 return hr; 5761 } 5762 5763 /***************************************************************************** 5764 * IDirect3DDevice7::ApplyStateBlock 5765 * 5766 * Activates the state stored in a state block handle. 5767 * 5768 * Params: 5769 * BlockHandle: The stateblock handle to activate 5770 * 5771 * Returns: 5772 * D3D_OK on success 5773 * D3DERR_INVALIDSTATEBLOCK if BlockHandle is NULL 5774 * 5775 *****************************************************************************/ 5776 static HRESULT d3d_device7_ApplyStateBlock(IDirect3DDevice7 *iface, DWORD stateblock) 5777 { 5778 struct d3d_device *device = impl_from_IDirect3DDevice7(iface); 5779 struct wined3d_stateblock *wined3d_sb; 5780 5781 TRACE("iface %p, stateblock %#x.\n", iface, stateblock); 5782 5783 wined3d_mutex_lock(); 5784 wined3d_sb = ddraw_get_object(&device->handle_table, stateblock - 1, DDRAW_HANDLE_STATEBLOCK); 5785 if (!wined3d_sb) 5786 { 5787 WARN("Invalid stateblock handle.\n"); 5788 wined3d_mutex_unlock(); 5789 return D3DERR_INVALIDSTATEBLOCK; 5790 } 5791 5792 wined3d_stateblock_apply(wined3d_sb); 5793 wined3d_mutex_unlock(); 5794 5795 return D3D_OK; 5796 } 5797 5798 static HRESULT WINAPI d3d_device7_ApplyStateBlock_FPUSetup(IDirect3DDevice7 *iface, DWORD stateblock) 5799 { 5800 return d3d_device7_ApplyStateBlock(iface, stateblock); 5801 } 5802 5803 static HRESULT WINAPI d3d_device7_ApplyStateBlock_FPUPreserve(IDirect3DDevice7 *iface, DWORD stateblock) 5804 { 5805 HRESULT hr; 5806 WORD old_fpucw; 5807 5808 old_fpucw = d3d_fpu_setup(); 5809 hr = d3d_device7_ApplyStateBlock(iface, stateblock); 5810 set_fpu_control_word(old_fpucw); 5811 5812 return hr; 5813 } 5814 5815 /***************************************************************************** 5816 * IDirect3DDevice7::CaptureStateBlock 5817 * 5818 * Updates a stateblock's values to the values currently set for the device 5819 * 5820 * Version 7 5821 * 5822 * Params: 5823 * BlockHandle: Stateblock to update 5824 * 5825 * Returns: 5826 * D3D_OK on success 5827 * D3DERR_INVALIDSTATEBLOCK if BlockHandle is NULL 5828 * 5829 *****************************************************************************/ 5830 static HRESULT d3d_device7_CaptureStateBlock(IDirect3DDevice7 *iface, DWORD stateblock) 5831 { 5832 struct d3d_device *device = impl_from_IDirect3DDevice7(iface); 5833 struct wined3d_stateblock *wined3d_sb; 5834 5835 TRACE("iface %p, stateblock %#x.\n", iface, stateblock); 5836 5837 wined3d_mutex_lock(); 5838 wined3d_sb = ddraw_get_object(&device->handle_table, stateblock - 1, DDRAW_HANDLE_STATEBLOCK); 5839 if (!wined3d_sb) 5840 { 5841 WARN("Invalid stateblock handle.\n"); 5842 wined3d_mutex_unlock(); 5843 return D3DERR_INVALIDSTATEBLOCK; 5844 } 5845 5846 wined3d_stateblock_capture(wined3d_sb); 5847 wined3d_mutex_unlock(); 5848 5849 return D3D_OK; 5850 } 5851 5852 static HRESULT WINAPI d3d_device7_CaptureStateBlock_FPUSetup(IDirect3DDevice7 *iface, DWORD stateblock) 5853 { 5854 return d3d_device7_CaptureStateBlock(iface, stateblock); 5855 } 5856 5857 static HRESULT WINAPI d3d_device7_CaptureStateBlock_FPUPreserve(IDirect3DDevice7 *iface, DWORD stateblock) 5858 { 5859 HRESULT hr; 5860 WORD old_fpucw; 5861 5862 old_fpucw = d3d_fpu_setup(); 5863 hr = d3d_device7_CaptureStateBlock(iface, stateblock); 5864 set_fpu_control_word(old_fpucw); 5865 5866 return hr; 5867 } 5868 5869 /***************************************************************************** 5870 * IDirect3DDevice7::DeleteStateBlock 5871 * 5872 * Deletes a stateblock handle. This means releasing the WineD3DStateBlock 5873 * 5874 * Version 7 5875 * 5876 * Params: 5877 * BlockHandle: Stateblock handle to delete 5878 * 5879 * Returns: 5880 * D3D_OK on success 5881 * D3DERR_INVALIDSTATEBLOCK if BlockHandle is 0 5882 * 5883 *****************************************************************************/ 5884 static HRESULT d3d_device7_DeleteStateBlock(IDirect3DDevice7 *iface, DWORD stateblock) 5885 { 5886 struct d3d_device *device = impl_from_IDirect3DDevice7(iface); 5887 struct wined3d_stateblock *wined3d_sb; 5888 ULONG ref; 5889 5890 TRACE("iface %p, stateblock %#x.\n", iface, stateblock); 5891 5892 wined3d_mutex_lock(); 5893 5894 wined3d_sb = ddraw_free_handle(&device->handle_table, stateblock - 1, DDRAW_HANDLE_STATEBLOCK); 5895 if (!wined3d_sb) 5896 { 5897 WARN("Invalid stateblock handle.\n"); 5898 wined3d_mutex_unlock(); 5899 return D3DERR_INVALIDSTATEBLOCK; 5900 } 5901 5902 if ((ref = wined3d_stateblock_decref(wined3d_sb))) 5903 { 5904 ERR("Something is still holding stateblock %p (refcount %u).\n", wined3d_sb, ref); 5905 } 5906 5907 wined3d_mutex_unlock(); 5908 5909 return D3D_OK; 5910 } 5911 5912 static HRESULT WINAPI d3d_device7_DeleteStateBlock_FPUSetup(IDirect3DDevice7 *iface, DWORD stateblock) 5913 { 5914 return d3d_device7_DeleteStateBlock(iface, stateblock); 5915 } 5916 5917 static HRESULT WINAPI d3d_device7_DeleteStateBlock_FPUPreserve(IDirect3DDevice7 *iface, DWORD stateblock) 5918 { 5919 HRESULT hr; 5920 WORD old_fpucw; 5921 5922 old_fpucw = d3d_fpu_setup(); 5923 hr = d3d_device7_DeleteStateBlock(iface, stateblock); 5924 set_fpu_control_word(old_fpucw); 5925 5926 return hr; 5927 } 5928 5929 /***************************************************************************** 5930 * IDirect3DDevice7::CreateStateBlock 5931 * 5932 * Creates a new state block handle. 5933 * 5934 * Version 7 5935 * 5936 * Params: 5937 * Type: The state block type 5938 * BlockHandle: Address to write the created handle to 5939 * 5940 * Returns: 5941 * D3D_OK on success 5942 * DDERR_INVALIDPARAMS if BlockHandle is NULL 5943 * 5944 *****************************************************************************/ 5945 static HRESULT d3d_device7_CreateStateBlock(IDirect3DDevice7 *iface, 5946 D3DSTATEBLOCKTYPE type, DWORD *stateblock) 5947 { 5948 struct d3d_device *device = impl_from_IDirect3DDevice7(iface); 5949 struct wined3d_stateblock *wined3d_sb; 5950 HRESULT hr; 5951 DWORD h; 5952 5953 TRACE("iface %p, type %#x, stateblock %p.\n", iface, type, stateblock); 5954 5955 if (!stateblock) 5956 return DDERR_INVALIDPARAMS; 5957 5958 if (type != D3DSBT_ALL 5959 && type != D3DSBT_PIXELSTATE 5960 && type != D3DSBT_VERTEXSTATE) 5961 { 5962 WARN("Unexpected stateblock type, returning DDERR_INVALIDPARAMS\n"); 5963 return DDERR_INVALIDPARAMS; 5964 } 5965 5966 wined3d_mutex_lock(); 5967 5968 /* The D3DSTATEBLOCKTYPE enum is fine here. */ 5969 hr = wined3d_stateblock_create(device->wined3d_device, type, &wined3d_sb); 5970 if (FAILED(hr)) 5971 { 5972 WARN("Failed to create stateblock, hr %#x.\n", hr); 5973 wined3d_mutex_unlock(); 5974 return hr_ddraw_from_wined3d(hr); 5975 } 5976 5977 h = ddraw_allocate_handle(&device->handle_table, wined3d_sb, DDRAW_HANDLE_STATEBLOCK); 5978 if (h == DDRAW_INVALID_HANDLE) 5979 { 5980 ERR("Failed to allocate stateblock handle.\n"); 5981 wined3d_stateblock_decref(wined3d_sb); 5982 wined3d_mutex_unlock(); 5983 return DDERR_OUTOFMEMORY; 5984 } 5985 5986 *stateblock = h + 1; 5987 wined3d_mutex_unlock(); 5988 5989 return hr_ddraw_from_wined3d(hr); 5990 } 5991 5992 static HRESULT WINAPI d3d_device7_CreateStateBlock_FPUSetup(IDirect3DDevice7 *iface, 5993 D3DSTATEBLOCKTYPE type, DWORD *stateblock) 5994 { 5995 return d3d_device7_CreateStateBlock(iface, type, stateblock); 5996 } 5997 5998 static HRESULT WINAPI d3d_device7_CreateStateBlock_FPUPreserve(IDirect3DDevice7 *iface, 5999 D3DSTATEBLOCKTYPE type, DWORD *stateblock) 6000 { 6001 HRESULT hr; 6002 WORD old_fpucw; 6003 6004 old_fpucw = d3d_fpu_setup(); 6005 hr = d3d_device7_CreateStateBlock(iface, type, stateblock); 6006 set_fpu_control_word(old_fpucw); 6007 6008 return hr; 6009 } 6010 6011 static BOOL is_mip_level_subset(struct ddraw_surface *dest, struct ddraw_surface *src) 6012 { 6013 struct ddraw_surface *src_level, *dest_level; 6014 IDirectDrawSurface7 *temp; 6015 DDSURFACEDESC2 ddsd; 6016 BOOL levelFound; /* at least one suitable sublevel in dest found */ 6017 6018 /* To satisfy "destination is mip level subset of source" criteria (regular texture counts as 1 level), 6019 * 1) there must be at least one mip level in destination that matched dimensions of some mip level in source and 6020 * 2) there must be no destination levels that don't match any levels in source. Otherwise it's INVALIDPARAMS. 6021 */ 6022 levelFound = FALSE; 6023 6024 src_level = src; 6025 dest_level = dest; 6026 6027 for (;src_level && dest_level;) 6028 { 6029 if (src_level->surface_desc.dwWidth == dest_level->surface_desc.dwWidth && 6030 src_level->surface_desc.dwHeight == dest_level->surface_desc.dwHeight) 6031 { 6032 levelFound = TRUE; 6033 6034 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE; 6035 ddsd.ddsCaps.dwCaps2 = DDSCAPS2_MIPMAPSUBLEVEL; 6036 IDirectDrawSurface7_GetAttachedSurface(&dest_level->IDirectDrawSurface7_iface, &ddsd.ddsCaps, &temp); 6037 6038 if (dest_level != dest) IDirectDrawSurface7_Release(&dest_level->IDirectDrawSurface7_iface); 6039 6040 dest_level = unsafe_impl_from_IDirectDrawSurface7(temp); 6041 } 6042 6043 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE; 6044 ddsd.ddsCaps.dwCaps2 = DDSCAPS2_MIPMAPSUBLEVEL; 6045 IDirectDrawSurface7_GetAttachedSurface(&src_level->IDirectDrawSurface7_iface, &ddsd.ddsCaps, &temp); 6046 6047 if (src_level != src) IDirectDrawSurface7_Release(&src_level->IDirectDrawSurface7_iface); 6048 6049 src_level = unsafe_impl_from_IDirectDrawSurface7(temp); 6050 } 6051 6052 if (src_level && src_level != src) IDirectDrawSurface7_Release(&src_level->IDirectDrawSurface7_iface); 6053 if (dest_level && dest_level != dest) IDirectDrawSurface7_Release(&dest_level->IDirectDrawSurface7_iface); 6054 6055 return !dest_level && levelFound; 6056 } 6057 6058 static void copy_mipmap_chain(struct d3d_device *device, struct ddraw_surface *dst, 6059 struct ddraw_surface *src, const POINT *DestPoint, const RECT *SrcRect) 6060 { 6061 struct ddraw_surface *dst_level, *src_level; 6062 IDirectDrawSurface7 *temp; 6063 DDSURFACEDESC2 ddsd; 6064 POINT point; 6065 RECT src_rect; 6066 HRESULT hr; 6067 IDirectDrawPalette *pal = NULL, *pal_src = NULL; 6068 DWORD ckeyflag; 6069 DDCOLORKEY ddckey; 6070 6071 /* Copy palette, if possible. */ 6072 IDirectDrawSurface7_GetPalette(&src->IDirectDrawSurface7_iface, &pal_src); 6073 IDirectDrawSurface7_GetPalette(&dst->IDirectDrawSurface7_iface, &pal); 6074 6075 if (pal_src != NULL && pal != NULL) 6076 { 6077 PALETTEENTRY palent[256]; 6078 6079 IDirectDrawPalette_GetEntries(pal_src, 0, 0, 256, palent); 6080 IDirectDrawPalette_SetEntries(pal, 0, 0, 256, palent); 6081 } 6082 6083 if (pal) IDirectDrawPalette_Release(pal); 6084 if (pal_src) IDirectDrawPalette_Release(pal_src); 6085 6086 /* Copy colorkeys, if present. */ 6087 for (ckeyflag = DDCKEY_DESTBLT; ckeyflag <= DDCKEY_SRCOVERLAY; ckeyflag <<= 1) 6088 { 6089 hr = IDirectDrawSurface7_GetColorKey(&src->IDirectDrawSurface7_iface, ckeyflag, &ddckey); 6090 6091 if (SUCCEEDED(hr)) 6092 { 6093 IDirectDrawSurface7_SetColorKey(&dst->IDirectDrawSurface7_iface, ckeyflag, &ddckey); 6094 } 6095 } 6096 6097 src_level = src; 6098 dst_level = dst; 6099 6100 point = *DestPoint; 6101 src_rect = *SrcRect; 6102 6103 for (;src_level && dst_level;) 6104 { 6105 if (src_level->surface_desc.dwWidth == dst_level->surface_desc.dwWidth 6106 && src_level->surface_desc.dwHeight == dst_level->surface_desc.dwHeight) 6107 { 6108 UINT src_w = src_rect.right - src_rect.left; 6109 UINT src_h = src_rect.bottom - src_rect.top; 6110 RECT dst_rect = {point.x, point.y, point.x + src_w, point.y + src_h}; 6111 6112 if (FAILED(hr = wined3d_texture_blt(dst_level->wined3d_texture, dst_level->sub_resource_idx, &dst_rect, 6113 src_level->wined3d_texture, src_level->sub_resource_idx, &src_rect, 0, NULL, WINED3D_TEXF_POINT))) 6114 ERR("Blit failed, hr %#x.\n", hr); 6115 6116 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE; 6117 ddsd.ddsCaps.dwCaps2 = DDSCAPS2_MIPMAPSUBLEVEL; 6118 IDirectDrawSurface7_GetAttachedSurface(&dst_level->IDirectDrawSurface7_iface, &ddsd.ddsCaps, &temp); 6119 6120 if (dst_level != dst) 6121 IDirectDrawSurface7_Release(&dst_level->IDirectDrawSurface7_iface); 6122 6123 dst_level = unsafe_impl_from_IDirectDrawSurface7(temp); 6124 } 6125 6126 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE; 6127 ddsd.ddsCaps.dwCaps2 = DDSCAPS2_MIPMAPSUBLEVEL; 6128 IDirectDrawSurface7_GetAttachedSurface(&src_level->IDirectDrawSurface7_iface, &ddsd.ddsCaps, &temp); 6129 6130 if (src_level != src) IDirectDrawSurface7_Release(&src_level->IDirectDrawSurface7_iface); 6131 6132 src_level = unsafe_impl_from_IDirectDrawSurface7(temp); 6133 6134 point.x /= 2; 6135 point.y /= 2; 6136 6137 src_rect.top /= 2; 6138 src_rect.left /= 2; 6139 src_rect.right = (src_rect.right + 1) / 2; 6140 src_rect.bottom = (src_rect.bottom + 1) / 2; 6141 } 6142 6143 if (src_level && src_level != src) 6144 IDirectDrawSurface7_Release(&src_level->IDirectDrawSurface7_iface); 6145 if (dst_level && dst_level != dst) 6146 IDirectDrawSurface7_Release(&dst_level->IDirectDrawSurface7_iface); 6147 } 6148 6149 /***************************************************************************** 6150 * IDirect3DDevice7::Load 6151 * 6152 * Loads a rectangular area from the source into the destination texture. 6153 * It can also copy the source to the faces of a cubic environment map 6154 * 6155 * Version 7 6156 * 6157 * Params: 6158 * DestTex: Destination texture 6159 * DestPoint: Point in the destination where the source image should be 6160 * written to 6161 * SrcTex: Source texture 6162 * SrcRect: Source rectangle 6163 * Flags: Cubemap faces to load (DDSCAPS2_CUBEMAP_ALLFACES, DDSCAPS2_CUBEMAP_POSITIVEX, 6164 * DDSCAPS2_CUBEMAP_NEGATIVEX, DDSCAPS2_CUBEMAP_POSITIVEY, DDSCAPS2_CUBEMAP_NEGATIVEY, 6165 * DDSCAPS2_CUBEMAP_POSITIVEZ, DDSCAPS2_CUBEMAP_NEGATIVEZ) 6166 * 6167 * Returns: 6168 * D3D_OK on success 6169 * DDERR_INVALIDPARAMS if dst_texture or src_texture is NULL, broken coordinates or anything unexpected. 6170 * 6171 * 6172 *****************************************************************************/ 6173 static HRESULT d3d_device7_Load(IDirect3DDevice7 *iface, IDirectDrawSurface7 *dst_texture, POINT *dst_pos, 6174 IDirectDrawSurface7 *src_texture, RECT *src_rect, DWORD flags) 6175 { 6176 struct d3d_device *device = impl_from_IDirect3DDevice7(iface); 6177 struct ddraw_surface *dest = unsafe_impl_from_IDirectDrawSurface7(dst_texture); 6178 struct ddraw_surface *src = unsafe_impl_from_IDirectDrawSurface7(src_texture); 6179 POINT destpoint; 6180 RECT srcrect; 6181 6182 TRACE("iface %p, dst_texture %p, dst_pos %s, src_texture %p, src_rect %s, flags %#x.\n", 6183 iface, dst_texture, wine_dbgstr_point(dst_pos), src_texture, wine_dbgstr_rect(src_rect), flags); 6184 6185 if( (!src) || (!dest) ) 6186 return DDERR_INVALIDPARAMS; 6187 6188 wined3d_mutex_lock(); 6189 6190 if (!src_rect) 6191 SetRect(&srcrect, 0, 0, src->surface_desc.dwWidth, src->surface_desc.dwHeight); 6192 else 6193 srcrect = *src_rect; 6194 6195 if (!dst_pos) 6196 destpoint.x = destpoint.y = 0; 6197 else 6198 destpoint = *dst_pos; 6199 6200 /* Check bad dimensions. dst_pos is validated against src, not dest, because 6201 * destination can be a subset of mip levels, in which case actual coordinates used 6202 * for it may be divided. If any dimension of dest is larger than source, it can't be 6203 * mip level subset, so an error can be returned early. 6204 */ 6205 if (IsRectEmpty(&srcrect) || srcrect.right > src->surface_desc.dwWidth || 6206 srcrect.bottom > src->surface_desc.dwHeight || 6207 destpoint.x + srcrect.right - srcrect.left > src->surface_desc.dwWidth || 6208 destpoint.y + srcrect.bottom - srcrect.top > src->surface_desc.dwHeight || 6209 dest->surface_desc.dwWidth > src->surface_desc.dwWidth || 6210 dest->surface_desc.dwHeight > src->surface_desc.dwHeight) 6211 { 6212 wined3d_mutex_unlock(); 6213 return DDERR_INVALIDPARAMS; 6214 } 6215 6216 /* Must be top level surfaces. */ 6217 if (src->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_MIPMAPSUBLEVEL || 6218 dest->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_MIPMAPSUBLEVEL) 6219 { 6220 wined3d_mutex_unlock(); 6221 return DDERR_INVALIDPARAMS; 6222 } 6223 6224 if (src->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP) 6225 { 6226 struct ddraw_surface *src_face, *dest_face; 6227 DWORD src_face_flag, dest_face_flag; 6228 IDirectDrawSurface7 *temp; 6229 DDSURFACEDESC2 ddsd; 6230 int i; 6231 6232 if (!(dest->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP)) 6233 { 6234 wined3d_mutex_unlock(); 6235 return DDERR_INVALIDPARAMS; 6236 } 6237 6238 /* Iterate through cube faces 2 times. First time is just to check INVALIDPARAMS conditions, second 6239 * time it's actual surface loading. */ 6240 for (i = 0; i < 2; i++) 6241 { 6242 dest_face = dest; 6243 src_face = src; 6244 6245 for (;dest_face && src_face;) 6246 { 6247 src_face_flag = src_face->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP_ALLFACES; 6248 dest_face_flag = dest_face->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP_ALLFACES; 6249 6250 if (src_face_flag == dest_face_flag) 6251 { 6252 if (i == 0) 6253 { 6254 /* Destination mip levels must be subset of source mip levels. */ 6255 if (!is_mip_level_subset(dest_face, src_face)) 6256 { 6257 wined3d_mutex_unlock(); 6258 return DDERR_INVALIDPARAMS; 6259 } 6260 } 6261 else if (flags & dest_face_flag) 6262 { 6263 copy_mipmap_chain(device, dest_face, src_face, &destpoint, &srcrect); 6264 } 6265 6266 if (src_face_flag < DDSCAPS2_CUBEMAP_NEGATIVEZ) 6267 { 6268 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE; 6269 ddsd.ddsCaps.dwCaps2 = DDSCAPS2_CUBEMAP | (src_face_flag << 1); 6270 IDirectDrawSurface7_GetAttachedSurface(&src->IDirectDrawSurface7_iface, &ddsd.ddsCaps, &temp); 6271 6272 if (src_face != src) IDirectDrawSurface7_Release(&src_face->IDirectDrawSurface7_iface); 6273 6274 src_face = unsafe_impl_from_IDirectDrawSurface7(temp); 6275 } 6276 else 6277 { 6278 if (src_face != src) IDirectDrawSurface7_Release(&src_face->IDirectDrawSurface7_iface); 6279 6280 src_face = NULL; 6281 } 6282 } 6283 6284 if (dest_face_flag < DDSCAPS2_CUBEMAP_NEGATIVEZ) 6285 { 6286 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE; 6287 ddsd.ddsCaps.dwCaps2 = DDSCAPS2_CUBEMAP | (dest_face_flag << 1); 6288 IDirectDrawSurface7_GetAttachedSurface(&dest->IDirectDrawSurface7_iface, &ddsd.ddsCaps, &temp); 6289 6290 if (dest_face != dest) IDirectDrawSurface7_Release(&dest_face->IDirectDrawSurface7_iface); 6291 6292 dest_face = unsafe_impl_from_IDirectDrawSurface7(temp); 6293 } 6294 else 6295 { 6296 if (dest_face != dest) IDirectDrawSurface7_Release(&dest_face->IDirectDrawSurface7_iface); 6297 6298 dest_face = NULL; 6299 } 6300 } 6301 6302 if (i == 0) 6303 { 6304 /* Native returns error if src faces are not subset of dest faces. */ 6305 if (src_face) 6306 { 6307 wined3d_mutex_unlock(); 6308 return DDERR_INVALIDPARAMS; 6309 } 6310 } 6311 } 6312 6313 wined3d_mutex_unlock(); 6314 return D3D_OK; 6315 } 6316 else if (dest->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP) 6317 { 6318 wined3d_mutex_unlock(); 6319 return DDERR_INVALIDPARAMS; 6320 } 6321 6322 /* Handle non cube map textures. */ 6323 6324 /* Destination mip levels must be subset of source mip levels. */ 6325 if (!is_mip_level_subset(dest, src)) 6326 { 6327 wined3d_mutex_unlock(); 6328 return DDERR_INVALIDPARAMS; 6329 } 6330 6331 copy_mipmap_chain(device, dest, src, &destpoint, &srcrect); 6332 6333 wined3d_mutex_unlock(); 6334 6335 return D3D_OK; 6336 } 6337 6338 static HRESULT WINAPI d3d_device7_Load_FPUSetup(IDirect3DDevice7 *iface, IDirectDrawSurface7 *dst_texture, 6339 POINT *dst_pos, IDirectDrawSurface7 *src_texture, RECT *src_rect, DWORD flags) 6340 { 6341 return d3d_device7_Load(iface, dst_texture, dst_pos, src_texture, src_rect, flags); 6342 } 6343 6344 static HRESULT WINAPI d3d_device7_Load_FPUPreserve(IDirect3DDevice7 *iface, IDirectDrawSurface7 *dst_texture, 6345 POINT *dst_pos, IDirectDrawSurface7 *src_texture, RECT *src_rect, DWORD flags) 6346 { 6347 HRESULT hr; 6348 WORD old_fpucw; 6349 6350 old_fpucw = d3d_fpu_setup(); 6351 hr = d3d_device7_Load(iface, dst_texture, dst_pos, src_texture, src_rect, flags); 6352 set_fpu_control_word(old_fpucw); 6353 6354 return hr; 6355 } 6356 6357 /***************************************************************************** 6358 * IDirect3DDevice7::LightEnable 6359 * 6360 * Enables or disables a light 6361 * 6362 * Version 7, IDirect3DLight uses this method too. 6363 * 6364 * Params: 6365 * LightIndex: The index of the light to enable / disable 6366 * Enable: Enable or disable the light 6367 * 6368 * Returns: 6369 * D3D_OK on success 6370 * 6371 *****************************************************************************/ 6372 static HRESULT d3d_device7_LightEnable(IDirect3DDevice7 *iface, DWORD light_idx, BOOL enabled) 6373 { 6374 struct d3d_device *device = impl_from_IDirect3DDevice7(iface); 6375 HRESULT hr; 6376 6377 TRACE("iface %p, light_idx %u, enabled %#x.\n", iface, light_idx, enabled); 6378 6379 wined3d_mutex_lock(); 6380 hr = wined3d_device_set_light_enable(device->wined3d_device, light_idx, enabled); 6381 wined3d_mutex_unlock(); 6382 6383 return hr_ddraw_from_wined3d(hr); 6384 } 6385 6386 static HRESULT WINAPI d3d_device7_LightEnable_FPUSetup(IDirect3DDevice7 *iface, DWORD light_idx, BOOL enabled) 6387 { 6388 return d3d_device7_LightEnable(iface, light_idx, enabled); 6389 } 6390 6391 static HRESULT WINAPI d3d_device7_LightEnable_FPUPreserve(IDirect3DDevice7 *iface, DWORD light_idx, BOOL enabled) 6392 { 6393 HRESULT hr; 6394 WORD old_fpucw; 6395 6396 old_fpucw = d3d_fpu_setup(); 6397 hr = d3d_device7_LightEnable(iface, light_idx, enabled); 6398 set_fpu_control_word(old_fpucw); 6399 6400 return hr; 6401 } 6402 6403 /***************************************************************************** 6404 * IDirect3DDevice7::GetLightEnable 6405 * 6406 * Retrieves if the light with the given index is enabled or not 6407 * 6408 * Version 7 6409 * 6410 * Params: 6411 * LightIndex: Index of desired light 6412 * Enable: Pointer to a BOOL which contains the result 6413 * 6414 * Returns: 6415 * D3D_OK on success 6416 * DDERR_INVALIDPARAMS if Enable is NULL 6417 * 6418 *****************************************************************************/ 6419 static HRESULT d3d_device7_GetLightEnable(IDirect3DDevice7 *iface, DWORD light_idx, BOOL *enabled) 6420 { 6421 struct d3d_device *device = impl_from_IDirect3DDevice7(iface); 6422 HRESULT hr; 6423 6424 TRACE("iface %p, light_idx %u, enabled %p.\n", iface, light_idx, enabled); 6425 6426 if (!enabled) 6427 return DDERR_INVALIDPARAMS; 6428 6429 wined3d_mutex_lock(); 6430 hr = wined3d_device_get_light_enable(device->wined3d_device, light_idx, enabled); 6431 wined3d_mutex_unlock(); 6432 6433 return hr_ddraw_from_wined3d(hr); 6434 } 6435 6436 static HRESULT WINAPI d3d_device7_GetLightEnable_FPUSetup(IDirect3DDevice7 *iface, DWORD light_idx, BOOL *enabled) 6437 { 6438 return d3d_device7_GetLightEnable(iface, light_idx, enabled); 6439 } 6440 6441 static HRESULT WINAPI d3d_device7_GetLightEnable_FPUPreserve(IDirect3DDevice7 *iface, DWORD light_idx, BOOL *enabled) 6442 { 6443 HRESULT hr; 6444 WORD old_fpucw; 6445 6446 old_fpucw = d3d_fpu_setup(); 6447 hr = d3d_device7_GetLightEnable(iface, light_idx, enabled); 6448 set_fpu_control_word(old_fpucw); 6449 6450 return hr; 6451 } 6452 6453 /***************************************************************************** 6454 * IDirect3DDevice7::SetClipPlane 6455 * 6456 * Sets custom clipping plane 6457 * 6458 * Version 7 6459 * 6460 * Params: 6461 * Index: The index of the clipping plane 6462 * PlaneEquation: An equation defining the clipping plane 6463 * 6464 * Returns: 6465 * D3D_OK on success 6466 * DDERR_INVALIDPARAMS if PlaneEquation is NULL 6467 * 6468 *****************************************************************************/ 6469 static HRESULT d3d_device7_SetClipPlane(IDirect3DDevice7 *iface, DWORD idx, D3DVALUE *plane) 6470 { 6471 struct d3d_device *device = impl_from_IDirect3DDevice7(iface); 6472 const struct wined3d_vec4 *wined3d_plane; 6473 HRESULT hr; 6474 6475 TRACE("iface %p, idx %u, plane %p.\n", iface, idx, plane); 6476 6477 if (!plane) 6478 return DDERR_INVALIDPARAMS; 6479 6480 wined3d_plane = (struct wined3d_vec4 *)plane; 6481 6482 wined3d_mutex_lock(); 6483 hr = wined3d_device_set_clip_plane(device->wined3d_device, idx, wined3d_plane); 6484 if (idx < ARRAY_SIZE(device->user_clip_planes)) 6485 { 6486 device->user_clip_planes[idx] = *wined3d_plane; 6487 if (hr == WINED3DERR_INVALIDCALL) 6488 { 6489 WARN("Clip plane %u is not supported.\n", idx); 6490 hr = D3D_OK; 6491 } 6492 } 6493 wined3d_mutex_unlock(); 6494 6495 return hr; 6496 } 6497 6498 static HRESULT WINAPI d3d_device7_SetClipPlane_FPUSetup(IDirect3DDevice7 *iface, DWORD idx, D3DVALUE *plane) 6499 { 6500 return d3d_device7_SetClipPlane(iface, idx, plane); 6501 } 6502 6503 static HRESULT WINAPI d3d_device7_SetClipPlane_FPUPreserve(IDirect3DDevice7 *iface, DWORD idx, D3DVALUE *plane) 6504 { 6505 HRESULT hr; 6506 WORD old_fpucw; 6507 6508 old_fpucw = d3d_fpu_setup(); 6509 hr = d3d_device7_SetClipPlane(iface, idx, plane); 6510 set_fpu_control_word(old_fpucw); 6511 6512 return hr; 6513 } 6514 6515 /***************************************************************************** 6516 * IDirect3DDevice7::GetClipPlane 6517 * 6518 * Returns the clipping plane with a specific index 6519 * 6520 * Params: 6521 * Index: The index of the desired plane 6522 * PlaneEquation: Address to store the plane equation to 6523 * 6524 * Returns: 6525 * D3D_OK on success 6526 * DDERR_INVALIDPARAMS if PlaneEquation is NULL 6527 * 6528 *****************************************************************************/ 6529 static HRESULT d3d_device7_GetClipPlane(IDirect3DDevice7 *iface, DWORD idx, D3DVALUE *plane) 6530 { 6531 struct d3d_device *device = impl_from_IDirect3DDevice7(iface); 6532 struct wined3d_vec4 *wined3d_plane; 6533 HRESULT hr; 6534 6535 TRACE("iface %p, idx %u, plane %p.\n", iface, idx, plane); 6536 6537 if (!plane) 6538 return DDERR_INVALIDPARAMS; 6539 6540 wined3d_plane = (struct wined3d_vec4 *)plane; 6541 6542 wined3d_mutex_lock(); 6543 hr = wined3d_device_get_clip_plane(device->wined3d_device, idx, wined3d_plane); 6544 if (hr == WINED3DERR_INVALIDCALL && idx < ARRAY_SIZE(device->user_clip_planes)) 6545 { 6546 WARN("Clip plane %u is not supported.\n", idx); 6547 *wined3d_plane = device->user_clip_planes[idx]; 6548 hr = D3D_OK; 6549 } 6550 wined3d_mutex_unlock(); 6551 6552 return hr; 6553 } 6554 6555 static HRESULT WINAPI d3d_device7_GetClipPlane_FPUSetup(IDirect3DDevice7 *iface, DWORD idx, D3DVALUE *plane) 6556 { 6557 return d3d_device7_GetClipPlane(iface, idx, plane); 6558 } 6559 6560 static HRESULT WINAPI d3d_device7_GetClipPlane_FPUPreserve(IDirect3DDevice7 *iface, DWORD idx, D3DVALUE *plane) 6561 { 6562 HRESULT hr; 6563 WORD old_fpucw; 6564 6565 old_fpucw = d3d_fpu_setup(); 6566 hr = d3d_device7_GetClipPlane(iface, idx, plane); 6567 set_fpu_control_word(old_fpucw); 6568 6569 return hr; 6570 } 6571 6572 /***************************************************************************** 6573 * IDirect3DDevice7::GetInfo 6574 * 6575 * Retrieves some information about the device. The DirectX sdk says that 6576 * this version returns S_FALSE for all retail builds of DirectX, that's what 6577 * this implementation does. 6578 * 6579 * Params: 6580 * DevInfoID: Information type requested 6581 * DevInfoStruct: Pointer to a structure to store the info to 6582 * Size: Size of the structure 6583 * 6584 * Returns: 6585 * S_FALSE, because it's a non-debug driver 6586 * 6587 *****************************************************************************/ 6588 static HRESULT WINAPI d3d_device7_GetInfo(IDirect3DDevice7 *iface, DWORD info_id, void *info, DWORD info_size) 6589 { 6590 TRACE("iface %p, info_id %#x, info %p, info_size %u.\n", 6591 iface, info_id, info, info_size); 6592 6593 if (TRACE_ON(ddraw)) 6594 { 6595 TRACE(" info requested : "); 6596 switch (info_id) 6597 { 6598 case D3DDEVINFOID_TEXTUREMANAGER: TRACE("D3DDEVINFOID_TEXTUREMANAGER\n"); break; 6599 case D3DDEVINFOID_D3DTEXTUREMANAGER: TRACE("D3DDEVINFOID_D3DTEXTUREMANAGER\n"); break; 6600 case D3DDEVINFOID_TEXTURING: TRACE("D3DDEVINFOID_TEXTURING\n"); break; 6601 default: ERR(" invalid flag !!!\n"); return DDERR_INVALIDPARAMS; 6602 } 6603 } 6604 6605 return S_FALSE; /* According to MSDN, this is valid for a non-debug driver */ 6606 } 6607 6608 /* For performance optimization, devices created in FPUSETUP and FPUPRESERVE modes 6609 * have separate vtables. Simple functions where this doesn't matter like GetDirect3D 6610 * are not duplicated. 6611 6612 * Device created with DDSCL_FPUSETUP (d3d7 default) - device methods assume that FPU 6613 * has already been setup for optimal d3d operation. 6614 6615 * Device created with DDSCL_FPUPRESERVE - resets and restores FPU mode when necessary in 6616 * d3d calls (FPU may be in a mode non-suitable for d3d when the app calls d3d). Required 6617 * by Sacrifice (game). */ 6618 static const struct IDirect3DDevice7Vtbl d3d_device7_fpu_setup_vtbl = 6619 { 6620 /*** IUnknown Methods ***/ 6621 d3d_device7_QueryInterface, 6622 d3d_device7_AddRef, 6623 d3d_device7_Release, 6624 /*** IDirect3DDevice7 ***/ 6625 d3d_device7_GetCaps_FPUSetup, 6626 d3d_device7_EnumTextureFormats_FPUSetup, 6627 d3d_device7_BeginScene_FPUSetup, 6628 d3d_device7_EndScene_FPUSetup, 6629 d3d_device7_GetDirect3D, 6630 d3d_device7_SetRenderTarget_FPUSetup, 6631 d3d_device7_GetRenderTarget, 6632 d3d_device7_Clear_FPUSetup, 6633 d3d_device7_SetTransform_FPUSetup, 6634 d3d_device7_GetTransform_FPUSetup, 6635 d3d_device7_SetViewport_FPUSetup, 6636 d3d_device7_MultiplyTransform_FPUSetup, 6637 d3d_device7_GetViewport_FPUSetup, 6638 d3d_device7_SetMaterial_FPUSetup, 6639 d3d_device7_GetMaterial_FPUSetup, 6640 d3d_device7_SetLight_FPUSetup, 6641 d3d_device7_GetLight_FPUSetup, 6642 d3d_device7_SetRenderState_FPUSetup, 6643 d3d_device7_GetRenderState_FPUSetup, 6644 d3d_device7_BeginStateBlock_FPUSetup, 6645 d3d_device7_EndStateBlock_FPUSetup, 6646 d3d_device7_PreLoad_FPUSetup, 6647 d3d_device7_DrawPrimitive_FPUSetup, 6648 d3d_device7_DrawIndexedPrimitive_FPUSetup, 6649 d3d_device7_SetClipStatus, 6650 d3d_device7_GetClipStatus, 6651 d3d_device7_DrawPrimitiveStrided_FPUSetup, 6652 d3d_device7_DrawIndexedPrimitiveStrided_FPUSetup, 6653 d3d_device7_DrawPrimitiveVB_FPUSetup, 6654 d3d_device7_DrawIndexedPrimitiveVB_FPUSetup, 6655 d3d_device7_ComputeSphereVisibility, 6656 d3d_device7_GetTexture_FPUSetup, 6657 d3d_device7_SetTexture_FPUSetup, 6658 d3d_device7_GetTextureStageState_FPUSetup, 6659 d3d_device7_SetTextureStageState_FPUSetup, 6660 d3d_device7_ValidateDevice_FPUSetup, 6661 d3d_device7_ApplyStateBlock_FPUSetup, 6662 d3d_device7_CaptureStateBlock_FPUSetup, 6663 d3d_device7_DeleteStateBlock_FPUSetup, 6664 d3d_device7_CreateStateBlock_FPUSetup, 6665 d3d_device7_Load_FPUSetup, 6666 d3d_device7_LightEnable_FPUSetup, 6667 d3d_device7_GetLightEnable_FPUSetup, 6668 d3d_device7_SetClipPlane_FPUSetup, 6669 d3d_device7_GetClipPlane_FPUSetup, 6670 d3d_device7_GetInfo 6671 }; 6672 6673 static const struct IDirect3DDevice7Vtbl d3d_device7_fpu_preserve_vtbl = 6674 { 6675 /*** IUnknown Methods ***/ 6676 d3d_device7_QueryInterface, 6677 d3d_device7_AddRef, 6678 d3d_device7_Release, 6679 /*** IDirect3DDevice7 ***/ 6680 d3d_device7_GetCaps_FPUPreserve, 6681 d3d_device7_EnumTextureFormats_FPUPreserve, 6682 d3d_device7_BeginScene_FPUPreserve, 6683 d3d_device7_EndScene_FPUPreserve, 6684 d3d_device7_GetDirect3D, 6685 d3d_device7_SetRenderTarget_FPUPreserve, 6686 d3d_device7_GetRenderTarget, 6687 d3d_device7_Clear_FPUPreserve, 6688 d3d_device7_SetTransform_FPUPreserve, 6689 d3d_device7_GetTransform_FPUPreserve, 6690 d3d_device7_SetViewport_FPUPreserve, 6691 d3d_device7_MultiplyTransform_FPUPreserve, 6692 d3d_device7_GetViewport_FPUPreserve, 6693 d3d_device7_SetMaterial_FPUPreserve, 6694 d3d_device7_GetMaterial_FPUPreserve, 6695 d3d_device7_SetLight_FPUPreserve, 6696 d3d_device7_GetLight_FPUPreserve, 6697 d3d_device7_SetRenderState_FPUPreserve, 6698 d3d_device7_GetRenderState_FPUPreserve, 6699 d3d_device7_BeginStateBlock_FPUPreserve, 6700 d3d_device7_EndStateBlock_FPUPreserve, 6701 d3d_device7_PreLoad_FPUPreserve, 6702 d3d_device7_DrawPrimitive_FPUPreserve, 6703 d3d_device7_DrawIndexedPrimitive_FPUPreserve, 6704 d3d_device7_SetClipStatus, 6705 d3d_device7_GetClipStatus, 6706 d3d_device7_DrawPrimitiveStrided_FPUPreserve, 6707 d3d_device7_DrawIndexedPrimitiveStrided_FPUPreserve, 6708 d3d_device7_DrawPrimitiveVB_FPUPreserve, 6709 d3d_device7_DrawIndexedPrimitiveVB_FPUPreserve, 6710 d3d_device7_ComputeSphereVisibility, 6711 d3d_device7_GetTexture_FPUPreserve, 6712 d3d_device7_SetTexture_FPUPreserve, 6713 d3d_device7_GetTextureStageState_FPUPreserve, 6714 d3d_device7_SetTextureStageState_FPUPreserve, 6715 d3d_device7_ValidateDevice_FPUPreserve, 6716 d3d_device7_ApplyStateBlock_FPUPreserve, 6717 d3d_device7_CaptureStateBlock_FPUPreserve, 6718 d3d_device7_DeleteStateBlock_FPUPreserve, 6719 d3d_device7_CreateStateBlock_FPUPreserve, 6720 d3d_device7_Load_FPUPreserve, 6721 d3d_device7_LightEnable_FPUPreserve, 6722 d3d_device7_GetLightEnable_FPUPreserve, 6723 d3d_device7_SetClipPlane_FPUPreserve, 6724 d3d_device7_GetClipPlane_FPUPreserve, 6725 d3d_device7_GetInfo 6726 }; 6727 6728 static const struct IDirect3DDevice3Vtbl d3d_device3_vtbl = 6729 { 6730 /*** IUnknown Methods ***/ 6731 d3d_device3_QueryInterface, 6732 d3d_device3_AddRef, 6733 d3d_device3_Release, 6734 /*** IDirect3DDevice3 ***/ 6735 d3d_device3_GetCaps, 6736 d3d_device3_GetStats, 6737 d3d_device3_AddViewport, 6738 d3d_device3_DeleteViewport, 6739 d3d_device3_NextViewport, 6740 d3d_device3_EnumTextureFormats, 6741 d3d_device3_BeginScene, 6742 d3d_device3_EndScene, 6743 d3d_device3_GetDirect3D, 6744 d3d_device3_SetCurrentViewport, 6745 d3d_device3_GetCurrentViewport, 6746 d3d_device3_SetRenderTarget, 6747 d3d_device3_GetRenderTarget, 6748 d3d_device3_Begin, 6749 d3d_device3_BeginIndexed, 6750 d3d_device3_Vertex, 6751 d3d_device3_Index, 6752 d3d_device3_End, 6753 d3d_device3_GetRenderState, 6754 d3d_device3_SetRenderState, 6755 d3d_device3_GetLightState, 6756 d3d_device3_SetLightState, 6757 d3d_device3_SetTransform, 6758 d3d_device3_GetTransform, 6759 d3d_device3_MultiplyTransform, 6760 d3d_device3_DrawPrimitive, 6761 d3d_device3_DrawIndexedPrimitive, 6762 d3d_device3_SetClipStatus, 6763 d3d_device3_GetClipStatus, 6764 d3d_device3_DrawPrimitiveStrided, 6765 d3d_device3_DrawIndexedPrimitiveStrided, 6766 d3d_device3_DrawPrimitiveVB, 6767 d3d_device3_DrawIndexedPrimitiveVB, 6768 d3d_device3_ComputeSphereVisibility, 6769 d3d_device3_GetTexture, 6770 d3d_device3_SetTexture, 6771 d3d_device3_GetTextureStageState, 6772 d3d_device3_SetTextureStageState, 6773 d3d_device3_ValidateDevice 6774 }; 6775 6776 static const struct IDirect3DDevice2Vtbl d3d_device2_vtbl = 6777 { 6778 /*** IUnknown Methods ***/ 6779 d3d_device2_QueryInterface, 6780 d3d_device2_AddRef, 6781 d3d_device2_Release, 6782 /*** IDirect3DDevice2 ***/ 6783 d3d_device2_GetCaps, 6784 d3d_device2_SwapTextureHandles, 6785 d3d_device2_GetStats, 6786 d3d_device2_AddViewport, 6787 d3d_device2_DeleteViewport, 6788 d3d_device2_NextViewport, 6789 d3d_device2_EnumTextureFormats, 6790 d3d_device2_BeginScene, 6791 d3d_device2_EndScene, 6792 d3d_device2_GetDirect3D, 6793 d3d_device2_SetCurrentViewport, 6794 d3d_device2_GetCurrentViewport, 6795 d3d_device2_SetRenderTarget, 6796 d3d_device2_GetRenderTarget, 6797 d3d_device2_Begin, 6798 d3d_device2_BeginIndexed, 6799 d3d_device2_Vertex, 6800 d3d_device2_Index, 6801 d3d_device2_End, 6802 d3d_device2_GetRenderState, 6803 d3d_device2_SetRenderState, 6804 d3d_device2_GetLightState, 6805 d3d_device2_SetLightState, 6806 d3d_device2_SetTransform, 6807 d3d_device2_GetTransform, 6808 d3d_device2_MultiplyTransform, 6809 d3d_device2_DrawPrimitive, 6810 d3d_device2_DrawIndexedPrimitive, 6811 d3d_device2_SetClipStatus, 6812 d3d_device2_GetClipStatus 6813 }; 6814 6815 static const struct IDirect3DDeviceVtbl d3d_device1_vtbl = 6816 { 6817 /*** IUnknown Methods ***/ 6818 d3d_device1_QueryInterface, 6819 d3d_device1_AddRef, 6820 d3d_device1_Release, 6821 /*** IDirect3DDevice1 ***/ 6822 d3d_device1_Initialize, 6823 d3d_device1_GetCaps, 6824 d3d_device1_SwapTextureHandles, 6825 d3d_device1_CreateExecuteBuffer, 6826 d3d_device1_GetStats, 6827 d3d_device1_Execute, 6828 d3d_device1_AddViewport, 6829 d3d_device1_DeleteViewport, 6830 d3d_device1_NextViewport, 6831 d3d_device1_Pick, 6832 d3d_device1_GetPickRecords, 6833 d3d_device1_EnumTextureFormats, 6834 d3d_device1_CreateMatrix, 6835 d3d_device1_SetMatrix, 6836 d3d_device1_GetMatrix, 6837 d3d_device1_DeleteMatrix, 6838 d3d_device1_BeginScene, 6839 d3d_device1_EndScene, 6840 d3d_device1_GetDirect3D 6841 }; 6842 6843 static const struct IUnknownVtbl d3d_device_inner_vtbl = 6844 { 6845 d3d_device_inner_QueryInterface, 6846 d3d_device_inner_AddRef, 6847 d3d_device_inner_Release, 6848 }; 6849 6850 struct d3d_device *unsafe_impl_from_IDirect3DDevice7(IDirect3DDevice7 *iface) 6851 { 6852 if (!iface) return NULL; 6853 assert((iface->lpVtbl == &d3d_device7_fpu_preserve_vtbl) || (iface->lpVtbl == &d3d_device7_fpu_setup_vtbl)); 6854 return CONTAINING_RECORD(iface, struct d3d_device, IDirect3DDevice7_iface); 6855 } 6856 6857 struct d3d_device *unsafe_impl_from_IDirect3DDevice3(IDirect3DDevice3 *iface) 6858 { 6859 if (!iface) return NULL; 6860 assert(iface->lpVtbl == &d3d_device3_vtbl); 6861 return CONTAINING_RECORD(iface, struct d3d_device, IDirect3DDevice3_iface); 6862 } 6863 6864 struct d3d_device *unsafe_impl_from_IDirect3DDevice2(IDirect3DDevice2 *iface) 6865 { 6866 if (!iface) return NULL; 6867 assert(iface->lpVtbl == &d3d_device2_vtbl); 6868 return CONTAINING_RECORD(iface, struct d3d_device, IDirect3DDevice2_iface); 6869 } 6870 6871 struct d3d_device *unsafe_impl_from_IDirect3DDevice(IDirect3DDevice *iface) 6872 { 6873 if (!iface) return NULL; 6874 assert(iface->lpVtbl == &d3d_device1_vtbl); 6875 return CONTAINING_RECORD(iface, struct d3d_device, IDirect3DDevice_iface); 6876 } 6877 6878 enum wined3d_depth_buffer_type d3d_device_update_depth_stencil(struct d3d_device *device) 6879 { 6880 IDirectDrawSurface7 *depthStencil = NULL; 6881 IDirectDrawSurface7 *render_target; 6882 static DDSCAPS2 depthcaps = { DDSCAPS_ZBUFFER, 0, 0, {0} }; 6883 struct ddraw_surface *dsi; 6884 6885 if (device->rt_iface && SUCCEEDED(IUnknown_QueryInterface(device->rt_iface, 6886 &IID_IDirectDrawSurface7, (void **)&render_target))) 6887 { 6888 IDirectDrawSurface7_GetAttachedSurface(render_target, &depthcaps, &depthStencil); 6889 IDirectDrawSurface7_Release(render_target); 6890 } 6891 if (!depthStencil) 6892 { 6893 TRACE("Setting wined3d depth stencil to NULL\n"); 6894 wined3d_device_set_depth_stencil_view(device->wined3d_device, NULL); 6895 return WINED3D_ZB_FALSE; 6896 } 6897 6898 dsi = impl_from_IDirectDrawSurface7(depthStencil); 6899 wined3d_device_set_depth_stencil_view(device->wined3d_device, 6900 ddraw_surface_get_rendertarget_view(dsi)); 6901 6902 IDirectDrawSurface7_Release(depthStencil); 6903 return WINED3D_ZB_TRUE; 6904 } 6905 6906 static HRESULT d3d_device_init(struct d3d_device *device, struct ddraw *ddraw, BOOL hw, 6907 struct ddraw_surface *target, IUnknown *rt_iface, UINT version, IUnknown *outer_unknown) 6908 { 6909 static const D3DMATRIX ident = 6910 { 6911 1.0f, 0.0f, 0.0f, 0.0f, 6912 0.0f, 1.0f, 0.0f, 0.0f, 6913 0.0f, 0.0f, 1.0f, 0.0f, 6914 0.0f, 0.0f, 0.0f, 1.0f, 6915 }; 6916 HRESULT hr; 6917 6918 if (ddraw->cooperative_level & DDSCL_FPUPRESERVE) 6919 device->IDirect3DDevice7_iface.lpVtbl = &d3d_device7_fpu_preserve_vtbl; 6920 else 6921 device->IDirect3DDevice7_iface.lpVtbl = &d3d_device7_fpu_setup_vtbl; 6922 6923 device->IDirect3DDevice3_iface.lpVtbl = &d3d_device3_vtbl; 6924 device->IDirect3DDevice2_iface.lpVtbl = &d3d_device2_vtbl; 6925 device->IDirect3DDevice_iface.lpVtbl = &d3d_device1_vtbl; 6926 device->IUnknown_inner.lpVtbl = &d3d_device_inner_vtbl; 6927 device->ref = 1; 6928 device->version = version; 6929 device->hw = hw; 6930 6931 if (outer_unknown) 6932 device->outer_unknown = outer_unknown; 6933 else 6934 device->outer_unknown = &device->IUnknown_inner; 6935 6936 device->ddraw = ddraw; 6937 list_init(&device->viewport_list); 6938 6939 if (!ddraw_handle_table_init(&device->handle_table, 64)) 6940 { 6941 ERR("Failed to initialize handle table.\n"); 6942 return DDERR_OUTOFMEMORY; 6943 } 6944 6945 device->legacyTextureBlending = FALSE; 6946 device->legacy_projection = ident; 6947 device->legacy_clipspace = ident; 6948 6949 /* This is for convenience. */ 6950 device->wined3d_device = ddraw->wined3d_device; 6951 wined3d_device_incref(ddraw->wined3d_device); 6952 6953 /* Render to the back buffer */ 6954 if (FAILED(hr = wined3d_device_set_rendertarget_view(ddraw->wined3d_device, 6955 0, ddraw_surface_get_rendertarget_view(target), TRUE))) 6956 { 6957 ERR("Failed to set render target, hr %#x.\n", hr); 6958 ddraw_handle_table_destroy(&device->handle_table); 6959 return hr; 6960 } 6961 6962 device->rt_iface = rt_iface; 6963 if (version != 1) 6964 IUnknown_AddRef(device->rt_iface); 6965 6966 ddraw->d3ddevice = device; 6967 6968 wined3d_device_set_render_state(ddraw->wined3d_device, WINED3D_RS_ZENABLE, 6969 d3d_device_update_depth_stencil(device)); 6970 if (version == 1) /* Color keying is initially enabled for version 1 devices. */ 6971 wined3d_device_set_render_state(ddraw->wined3d_device, WINED3D_RS_COLORKEYENABLE, TRUE); 6972 else if (version == 2) 6973 wined3d_device_set_render_state(ddraw->wined3d_device, WINED3D_RS_SPECULARENABLE, TRUE); 6974 if (version < 7) 6975 wined3d_device_set_render_state(ddraw->wined3d_device, WINED3D_RS_NORMALIZENORMALS, TRUE); 6976 6977 return D3D_OK; 6978 } 6979 6980 HRESULT d3d_device_create(struct ddraw *ddraw, const GUID *guid, struct ddraw_surface *target, IUnknown *rt_iface, 6981 UINT version, struct d3d_device **device, IUnknown *outer_unknown) 6982 { 6983 struct d3d_device *object; 6984 BOOL hw = TRUE; 6985 HRESULT hr; 6986 6987 TRACE("ddraw %p, guid %s, target %p, version %u, device %p, outer_unknown %p.\n", 6988 ddraw, debugstr_guid(guid), target, version, device, outer_unknown); 6989 6990 if (IsEqualGUID(guid, &IID_IDirect3DRGBDevice)) 6991 hw = FALSE; 6992 6993 if (!(target->surface_desc.ddsCaps.dwCaps & DDSCAPS_3DDEVICE) 6994 || (target->surface_desc.ddsCaps.dwCaps & DDSCAPS_ZBUFFER)) 6995 { 6996 WARN("Surface %p is not a render target.\n", target); 6997 return DDERR_INVALIDCAPS; 6998 } 6999 7000 if (!validate_surface_palette(target)) 7001 { 7002 WARN("Surface %p has an indexed pixel format, but no palette.\n", target); 7003 return DDERR_NOPALETTEATTACHED; 7004 } 7005 7006 if (hw && !(target->surface_desc.ddsCaps.dwCaps & DDSCAPS_VIDEOMEMORY)) 7007 { 7008 WARN("Surface %p is not in video memory.\n", target); 7009 return D3DERR_SURFACENOTINVIDMEM; 7010 } 7011 7012 if (ddraw->flags & DDRAW_NO3D) 7013 { 7014 ERR_(winediag)("The application wants to create a Direct3D device, " 7015 "but the current DirectDrawRenderer does not support this.\n"); 7016 7017 return DDERR_NO3D; 7018 } 7019 7020 if (ddraw->d3ddevice) 7021 { 7022 FIXME("Only one Direct3D device per DirectDraw object supported.\n"); 7023 return DDERR_INVALIDPARAMS; 7024 } 7025 7026 if (!(object = heap_alloc_zero(sizeof(*object)))) 7027 { 7028 ERR("Failed to allocate device memory.\n"); 7029 return DDERR_OUTOFMEMORY; 7030 } 7031 7032 if (FAILED(hr = d3d_device_init(object, ddraw, hw, target, rt_iface, version, outer_unknown))) 7033 { 7034 WARN("Failed to initialize device, hr %#x.\n", hr); 7035 heap_free(object); 7036 return hr; 7037 } 7038 7039 TRACE("Created device %p.\n", object); 7040 *device = object; 7041 7042 return D3D_OK; 7043 } 7044