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