1 /* 2 * Copyright 1997-2000 Marcus Meissner 3 * Copyright 1998-2000 Lionel Ulmer 4 * Copyright 2000-2001 TransGaming Technologies Inc. 5 * Copyright 2006 Stefan Dösinger 6 * Copyright 2008 Denver Gingerich 7 * Copyright 2007-2008, 2011, 2013 Stefan Dösinger for CodeWeavers 8 * 9 * This library is free software; you can redistribute it and/or 10 * modify it under the terms of the GNU Lesser General Public 11 * License as published by the Free Software Foundation; either 12 * version 2.1 of the License, or (at your option) any later version. 13 * 14 * This library is distributed in the hope that it will be useful, 15 * but WITHOUT ANY WARRANTY; without even the implied warranty of 16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 17 * Lesser General Public License for more details. 18 * 19 * You should have received a copy of the GNU Lesser General Public 20 * License along with this library; if not, write to the Free Software 21 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA 22 */ 23 24 #include "config.h" 25 #include "wine/port.h" 26 27 #include "ddraw_private.h" 28 29 #include "wine/exception.h" 30 31 WINE_DEFAULT_DEBUG_CHANNEL(ddraw); 32 33 static const struct ddraw *exclusive_ddraw; 34 static HWND exclusive_window; 35 36 /* Device identifier. Don't relay it to WineD3D */ 37 static const DDDEVICEIDENTIFIER2 deviceidentifier = 38 { 39 "vga.dll", /* default 2D driver */ 40 "DirectDraw HAL", 41 { { 0x00010001, 0x00010001 } }, 42 0, 0, 0, 0, 43 /* a8373c10-7ac4-4deb-849a-009844d08b2d */ 44 {0xa8373c10,0x7ac4,0x4deb, {0x84,0x9a,0x00,0x98,0x44,0xd0,0x8b,0x2d}}, 45 0 46 }; 47 48 static struct enum_device_entry 49 { 50 char interface_name[100]; 51 char device_name[100]; 52 const GUID *device_guid; 53 DWORD remove_caps; 54 } device_list7[] = 55 { 56 /* T&L HAL device */ 57 { 58 "WINE Direct3D7 Hardware Transform and Lighting acceleration using WineD3D", 59 "Wine D3D7 T&L HAL", 60 &IID_IDirect3DTnLHalDevice, 61 0, 62 }, 63 64 /* HAL device */ 65 { 66 "WINE Direct3D7 Hardware acceleration using WineD3D", 67 "Direct3D HAL", 68 &IID_IDirect3DHALDevice, 69 0, 70 }, 71 72 /* RGB device */ 73 { 74 "WINE Direct3D7 RGB Software Emulation using WineD3D", 75 "Wine D3D7 RGB", 76 &IID_IDirect3DRGBDevice, 77 D3DDEVCAPS_HWTRANSFORMANDLIGHT, 78 }, 79 }; 80 81 static void STDMETHODCALLTYPE ddraw_null_wined3d_object_destroyed(void *parent) {} 82 83 const struct wined3d_parent_ops ddraw_null_wined3d_parent_ops = 84 { 85 ddraw_null_wined3d_object_destroyed, 86 }; 87 88 static inline struct ddraw *impl_from_IDirectDraw(IDirectDraw *iface) 89 { 90 return CONTAINING_RECORD(iface, struct ddraw, IDirectDraw_iface); 91 } 92 93 static inline struct ddraw *impl_from_IDirectDraw2(IDirectDraw2 *iface) 94 { 95 return CONTAINING_RECORD(iface, struct ddraw, IDirectDraw2_iface); 96 } 97 98 static inline struct ddraw *impl_from_IDirectDraw4(IDirectDraw4 *iface) 99 { 100 return CONTAINING_RECORD(iface, struct ddraw, IDirectDraw4_iface); 101 } 102 103 static inline struct ddraw *impl_from_IDirectDraw7(IDirectDraw7 *iface) 104 { 105 return CONTAINING_RECORD(iface, struct ddraw, IDirectDraw7_iface); 106 } 107 108 static inline struct ddraw *impl_from_IDirect3D(IDirect3D *iface) 109 { 110 return CONTAINING_RECORD(iface, struct ddraw, IDirect3D_iface); 111 } 112 113 static inline struct ddraw *impl_from_IDirect3D2(IDirect3D2 *iface) 114 { 115 return CONTAINING_RECORD(iface, struct ddraw, IDirect3D2_iface); 116 } 117 118 static inline struct ddraw *impl_from_IDirect3D3(IDirect3D3 *iface) 119 { 120 return CONTAINING_RECORD(iface, struct ddraw, IDirect3D3_iface); 121 } 122 123 static inline struct ddraw *impl_from_IDirect3D7(IDirect3D7 *iface) 124 { 125 return CONTAINING_RECORD(iface, struct ddraw, IDirect3D7_iface); 126 } 127 128 static HRESULT WINAPI ddraw7_QueryInterface(IDirectDraw7 *iface, REFIID riid, void **out) 129 { 130 struct ddraw *ddraw = impl_from_IDirectDraw7(iface); 131 132 TRACE("iface %p, riid %s, out %p.\n", iface, debugstr_guid(riid), out); 133 134 if (!riid) 135 { 136 *out = NULL; 137 return DDERR_INVALIDPARAMS; 138 } 139 140 /* The refcount unit test revealed that an IDirect3D7 interface can only 141 * be queried from a DirectDraw object that was created as an IDirectDraw7 142 * interface. The older interfaces can query any IDirect3D version except 143 * 7, because they are all initially created as IDirectDraw. This isn't 144 * really crucial behavior, and messy to implement with the common 145 * creation function, so it has been left out here. */ 146 if (IsEqualGUID(&IID_IDirectDraw7, riid) 147 || IsEqualGUID(&IID_IUnknown, riid)) 148 { 149 *out = &ddraw->IDirectDraw7_iface; 150 TRACE("Returning IDirectDraw7 interface %p.\n", *out); 151 } 152 else if (IsEqualGUID(&IID_IDirectDraw4, riid)) 153 { 154 *out = &ddraw->IDirectDraw4_iface; 155 TRACE("Returning IDirectDraw4 interface %p.\n", *out); 156 } 157 else if (IsEqualGUID(&IID_IDirectDraw2, riid)) 158 { 159 *out = &ddraw->IDirectDraw2_iface; 160 TRACE("Returning IDirectDraw2 interface %p.\n", *out); 161 } 162 else if (IsEqualGUID(&IID_IDirectDraw, riid)) 163 { 164 *out = &ddraw->IDirectDraw_iface; 165 TRACE("Returning IDirectDraw interface %p.\n", *out); 166 } 167 else if (IsEqualGUID(&IID_IDirect3D7, riid)) 168 { 169 ddraw->d3dversion = 7; 170 *out = &ddraw->IDirect3D7_iface; 171 TRACE("Returning Direct3D7 interface %p.\n", *out); 172 } 173 else if (IsEqualGUID(&IID_IDirect3D3, riid)) 174 { 175 ddraw->d3dversion = 3; 176 *out = &ddraw->IDirect3D3_iface; 177 TRACE("Returning Direct3D3 interface %p.\n", *out); 178 } 179 else if (IsEqualGUID(&IID_IDirect3D2, riid)) 180 { 181 ddraw->d3dversion = 2; 182 *out = &ddraw->IDirect3D2_iface; 183 TRACE("Returning Direct3D2 interface %p.\n", *out); 184 } 185 else if (IsEqualGUID(&IID_IDirect3D, riid)) 186 { 187 ddraw->d3dversion = 1; 188 *out = &ddraw->IDirect3D_iface; 189 TRACE("Returning Direct3D interface %p.\n", *out); 190 } 191 /* Unknown interface */ 192 else 193 { 194 WARN("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(riid)); 195 *out = NULL; 196 return E_NOINTERFACE; 197 } 198 199 IUnknown_AddRef((IUnknown *)*out); 200 return S_OK; 201 } 202 203 static HRESULT WINAPI ddraw4_QueryInterface(IDirectDraw4 *iface, REFIID riid, void **object) 204 { 205 struct ddraw *ddraw = impl_from_IDirectDraw4(iface); 206 207 TRACE("iface %p, riid %s, object %p.\n", iface, debugstr_guid(riid), object); 208 209 return ddraw7_QueryInterface(&ddraw->IDirectDraw7_iface, riid, object); 210 } 211 212 static HRESULT WINAPI ddraw2_QueryInterface(IDirectDraw2 *iface, REFIID riid, void **object) 213 { 214 struct ddraw *ddraw = impl_from_IDirectDraw2(iface); 215 216 TRACE("iface %p, riid %s, object %p.\n", iface, debugstr_guid(riid), object); 217 218 return ddraw7_QueryInterface(&ddraw->IDirectDraw7_iface, riid, object); 219 } 220 221 static HRESULT WINAPI ddraw1_QueryInterface(IDirectDraw *iface, REFIID riid, void **object) 222 { 223 struct ddraw *ddraw = impl_from_IDirectDraw(iface); 224 225 TRACE("iface %p, riid %s, object %p.\n", iface, debugstr_guid(riid), object); 226 227 return ddraw7_QueryInterface(&ddraw->IDirectDraw7_iface, riid, object); 228 } 229 230 static HRESULT WINAPI d3d7_QueryInterface(IDirect3D7 *iface, REFIID riid, void **object) 231 { 232 struct ddraw *ddraw = impl_from_IDirect3D7(iface); 233 234 TRACE("iface %p, riid %s, object %p.\n", iface, debugstr_guid(riid), object); 235 236 return ddraw7_QueryInterface(&ddraw->IDirectDraw7_iface, riid, object); 237 } 238 239 static HRESULT WINAPI d3d3_QueryInterface(IDirect3D3 *iface, REFIID riid, void **object) 240 { 241 struct ddraw *ddraw = impl_from_IDirect3D3(iface); 242 243 TRACE("iface %p, riid %s, object %p.\n", iface, debugstr_guid(riid), object); 244 245 return ddraw7_QueryInterface(&ddraw->IDirectDraw7_iface, riid, object); 246 } 247 248 static HRESULT WINAPI d3d2_QueryInterface(IDirect3D2 *iface, REFIID riid, void **object) 249 { 250 struct ddraw *ddraw = impl_from_IDirect3D2(iface); 251 252 TRACE("iface %p, riid %s, object %p.\n", iface, debugstr_guid(riid), object); 253 254 return ddraw7_QueryInterface(&ddraw->IDirectDraw7_iface, riid, object); 255 } 256 257 static HRESULT WINAPI d3d1_QueryInterface(IDirect3D *iface, REFIID riid, void **object) 258 { 259 struct ddraw *ddraw = impl_from_IDirect3D(iface); 260 261 TRACE("iface %p, riid %s, object %p.\n", iface, debugstr_guid(riid), object); 262 263 return ddraw7_QueryInterface(&ddraw->IDirectDraw7_iface, riid, object); 264 } 265 266 /***************************************************************************** 267 * IDirectDraw7::AddRef 268 * 269 * Increases the interfaces refcount, basically 270 * 271 * DDraw refcounting is a bit tricky. The different DirectDraw interface 272 * versions have individual refcounts, but the IDirect3D interfaces do not. 273 * All interfaces are from one object, that means calling QueryInterface on an 274 * IDirectDraw7 interface for an IDirectDraw4 interface does not create a new 275 * ddraw object. 276 * 277 * That means all AddRef and Release implementations of IDirectDrawX work 278 * with their own counter, and IDirect3DX::AddRef thunk to IDirectDraw (1), 279 * except of IDirect3D7 which thunks to IDirectDraw7 280 * 281 * Returns: The new refcount 282 * 283 *****************************************************************************/ 284 static ULONG WINAPI ddraw7_AddRef(IDirectDraw7 *iface) 285 { 286 struct ddraw *This = impl_from_IDirectDraw7(iface); 287 ULONG ref = InterlockedIncrement(&This->ref7); 288 289 TRACE("%p increasing refcount to %u.\n", This, ref); 290 291 if(ref == 1) InterlockedIncrement(&This->numIfaces); 292 293 return ref; 294 } 295 296 static ULONG WINAPI ddraw4_AddRef(IDirectDraw4 *iface) 297 { 298 struct ddraw *This = impl_from_IDirectDraw4(iface); 299 ULONG ref = InterlockedIncrement(&This->ref4); 300 301 TRACE("%p increasing refcount to %u.\n", This, ref); 302 303 if (ref == 1) InterlockedIncrement(&This->numIfaces); 304 305 return ref; 306 } 307 308 static ULONG WINAPI ddraw2_AddRef(IDirectDraw2 *iface) 309 { 310 struct ddraw *This = impl_from_IDirectDraw2(iface); 311 ULONG ref = InterlockedIncrement(&This->ref2); 312 313 TRACE("%p increasing refcount to %u.\n", This, ref); 314 315 if (ref == 1) InterlockedIncrement(&This->numIfaces); 316 317 return ref; 318 } 319 320 static ULONG WINAPI ddraw1_AddRef(IDirectDraw *iface) 321 { 322 struct ddraw *This = impl_from_IDirectDraw(iface); 323 ULONG ref = InterlockedIncrement(&This->ref1); 324 325 TRACE("%p increasing refcount to %u.\n", This, ref); 326 327 if (ref == 1) InterlockedIncrement(&This->numIfaces); 328 329 return ref; 330 } 331 332 static ULONG WINAPI d3d7_AddRef(IDirect3D7 *iface) 333 { 334 struct ddraw *This = impl_from_IDirect3D7(iface); 335 336 TRACE("iface %p.\n", iface); 337 338 return ddraw7_AddRef(&This->IDirectDraw7_iface); 339 } 340 341 static ULONG WINAPI d3d3_AddRef(IDirect3D3 *iface) 342 { 343 struct ddraw *This = impl_from_IDirect3D3(iface); 344 345 TRACE("iface %p.\n", iface); 346 347 return ddraw1_AddRef(&This->IDirectDraw_iface); 348 } 349 350 static ULONG WINAPI d3d2_AddRef(IDirect3D2 *iface) 351 { 352 struct ddraw *This = impl_from_IDirect3D2(iface); 353 354 TRACE("iface %p.\n", iface); 355 356 return ddraw1_AddRef(&This->IDirectDraw_iface); 357 } 358 359 static ULONG WINAPI d3d1_AddRef(IDirect3D *iface) 360 { 361 struct ddraw *This = impl_from_IDirect3D(iface); 362 363 TRACE("iface %p.\n", iface); 364 365 return ddraw1_AddRef(&This->IDirectDraw_iface); 366 } 367 368 static void ddraw_destroy_swapchain(struct ddraw *ddraw) 369 { 370 TRACE("Destroying the swapchain.\n"); 371 372 wined3d_swapchain_decref(ddraw->wined3d_swapchain); 373 ddraw->wined3d_swapchain = NULL; 374 375 if (!(ddraw->flags & DDRAW_NO3D)) 376 { 377 UINT i; 378 379 for (i = 0; i < ddraw->numConvertedDecls; ++i) 380 { 381 wined3d_vertex_declaration_decref(ddraw->decls[i].decl); 382 } 383 heap_free(ddraw->decls); 384 ddraw->numConvertedDecls = 0; 385 386 if (FAILED(wined3d_device_uninit_3d(ddraw->wined3d_device))) 387 { 388 ERR("Failed to uninit 3D.\n"); 389 } 390 else 391 { 392 /* Free the d3d window if one was created. */ 393 if (ddraw->d3d_window && ddraw->d3d_window != ddraw->dest_window) 394 { 395 TRACE("Destroying the hidden render window %p.\n", ddraw->d3d_window); 396 DestroyWindow(ddraw->d3d_window); 397 ddraw->d3d_window = 0; 398 } 399 } 400 401 ddraw->flags &= ~DDRAW_D3D_INITIALIZED; 402 } 403 else 404 { 405 wined3d_device_uninit_gdi(ddraw->wined3d_device); 406 } 407 408 ddraw_set_swapchain_window(ddraw, NULL); 409 410 TRACE("Swapchain destroyed.\n"); 411 } 412 413 /***************************************************************************** 414 * ddraw_destroy 415 * 416 * Destroys a ddraw object if all refcounts are 0. This is to share code 417 * between the IDirectDrawX::Release functions 418 * 419 * Params: 420 * This: DirectDraw object to destroy 421 * 422 *****************************************************************************/ 423 static void ddraw_destroy(struct ddraw *This) 424 { 425 IDirectDraw7_SetCooperativeLevel(&This->IDirectDraw7_iface, NULL, DDSCL_NORMAL); 426 IDirectDraw7_RestoreDisplayMode(&This->IDirectDraw7_iface); 427 428 /* Destroy the device window if we created one */ 429 if(This->devicewindow != 0) 430 { 431 TRACE(" (%p) Destroying the device window %p\n", This, This->devicewindow); 432 DestroyWindow(This->devicewindow); 433 This->devicewindow = 0; 434 } 435 436 wined3d_mutex_lock(); 437 list_remove(&This->ddraw_list_entry); 438 wined3d_mutex_unlock(); 439 440 if (This->wined3d_swapchain) 441 ddraw_destroy_swapchain(This); 442 wined3d_device_decref(This->wined3d_device); 443 wined3d_decref(This->wined3d); 444 445 if (This->d3ddevice) 446 This->d3ddevice->ddraw = NULL; 447 448 /* Now free the object */ 449 heap_free(This); 450 } 451 452 /***************************************************************************** 453 * IDirectDraw7::Release 454 * 455 * Decreases the refcount. If the refcount falls to 0, the object is destroyed 456 * 457 * Returns: The new refcount 458 *****************************************************************************/ 459 static ULONG WINAPI ddraw7_Release(IDirectDraw7 *iface) 460 { 461 struct ddraw *This = impl_from_IDirectDraw7(iface); 462 ULONG ref = InterlockedDecrement(&This->ref7); 463 464 TRACE("%p decreasing refcount to %u.\n", This, ref); 465 466 if (!ref && !InterlockedDecrement(&This->numIfaces)) 467 ddraw_destroy(This); 468 469 return ref; 470 } 471 472 static ULONG WINAPI ddraw4_Release(IDirectDraw4 *iface) 473 { 474 struct ddraw *This = impl_from_IDirectDraw4(iface); 475 ULONG ref = InterlockedDecrement(&This->ref4); 476 477 TRACE("%p decreasing refcount to %u.\n", This, ref); 478 479 if (!ref && !InterlockedDecrement(&This->numIfaces)) 480 ddraw_destroy(This); 481 482 return ref; 483 } 484 485 static ULONG WINAPI ddraw2_Release(IDirectDraw2 *iface) 486 { 487 struct ddraw *This = impl_from_IDirectDraw2(iface); 488 ULONG ref = InterlockedDecrement(&This->ref2); 489 490 TRACE("%p decreasing refcount to %u.\n", This, ref); 491 492 if (!ref && !InterlockedDecrement(&This->numIfaces)) 493 ddraw_destroy(This); 494 495 return ref; 496 } 497 498 static ULONG WINAPI ddraw1_Release(IDirectDraw *iface) 499 { 500 struct ddraw *This = impl_from_IDirectDraw(iface); 501 ULONG ref = InterlockedDecrement(&This->ref1); 502 503 TRACE("%p decreasing refcount to %u.\n", This, ref); 504 505 if (!ref && !InterlockedDecrement(&This->numIfaces)) 506 ddraw_destroy(This); 507 508 return ref; 509 } 510 511 static ULONG WINAPI d3d7_Release(IDirect3D7 *iface) 512 { 513 struct ddraw *This = impl_from_IDirect3D7(iface); 514 515 TRACE("iface %p.\n", iface); 516 517 return ddraw7_Release(&This->IDirectDraw7_iface); 518 } 519 520 static ULONG WINAPI d3d3_Release(IDirect3D3 *iface) 521 { 522 struct ddraw *This = impl_from_IDirect3D3(iface); 523 524 TRACE("iface %p.\n", iface); 525 526 return ddraw1_Release(&This->IDirectDraw_iface); 527 } 528 529 static ULONG WINAPI d3d2_Release(IDirect3D2 *iface) 530 { 531 struct ddraw *This = impl_from_IDirect3D2(iface); 532 533 TRACE("iface %p.\n", iface); 534 535 return ddraw1_Release(&This->IDirectDraw_iface); 536 } 537 538 static ULONG WINAPI d3d1_Release(IDirect3D *iface) 539 { 540 struct ddraw *This = impl_from_IDirect3D(iface); 541 542 TRACE("iface %p.\n", iface); 543 544 return ddraw1_Release(&This->IDirectDraw_iface); 545 } 546 547 /***************************************************************************** 548 * IDirectDraw methods 549 *****************************************************************************/ 550 551 static HRESULT ddraw_set_focus_window(struct ddraw *ddraw, HWND window) 552 { 553 /* FIXME: This looks wrong, exclusive mode should imply a destination 554 * window. */ 555 if ((ddraw->cooperative_level & DDSCL_EXCLUSIVE) && ddraw->dest_window) 556 { 557 TRACE("Setting DDSCL_SETFOCUSWINDOW with an already set window, returning DDERR_HWNDALREADYSET.\n"); 558 return DDERR_HWNDALREADYSET; 559 } 560 561 ddraw->focuswindow = window; 562 563 return DD_OK; 564 } 565 566 static HRESULT ddraw_attach_d3d_device(struct ddraw *ddraw, 567 struct wined3d_swapchain_desc *swapchain_desc) 568 { 569 HWND window = swapchain_desc->device_window; 570 HRESULT hr; 571 572 TRACE("ddraw %p.\n", ddraw); 573 574 if (!window || window == GetDesktopWindow()) 575 { 576 window = CreateWindowExA(0, DDRAW_WINDOW_CLASS_NAME, "Hidden D3D Window", 577 WS_DISABLED, 0, 0, GetSystemMetrics(SM_CXSCREEN), GetSystemMetrics(SM_CYSCREEN), 578 NULL, NULL, NULL, NULL); 579 if (!window) 580 { 581 ERR("Failed to create window, last error %#x.\n", GetLastError()); 582 return E_FAIL; 583 } 584 585 ShowWindow(window, SW_HIDE); /* Just to be sure */ 586 WARN("No window for the Direct3DDevice, created hidden window %p.\n", window); 587 588 swapchain_desc->device_window = window; 589 } 590 else 591 { 592 TRACE("Using existing window %p for Direct3D rendering.\n", window); 593 } 594 ddraw->d3d_window = window; 595 596 /* Set this NOW, otherwise creating the depth stencil surface will cause a 597 * recursive loop until ram or emulated video memory is full. */ 598 ddraw->flags |= DDRAW_D3D_INITIALIZED; 599 hr = wined3d_device_init_3d(ddraw->wined3d_device, swapchain_desc); 600 if (FAILED(hr)) 601 { 602 ddraw->flags &= ~DDRAW_D3D_INITIALIZED; 603 return hr; 604 } 605 606 ddraw->declArraySize = 2; 607 if (!(ddraw->decls = heap_alloc_zero(ddraw->declArraySize * sizeof(*ddraw->decls)))) 608 { 609 ERR("Error allocating an array for the converted vertex decls.\n"); 610 ddraw->declArraySize = 0; 611 hr = wined3d_device_uninit_3d(ddraw->wined3d_device); 612 return E_OUTOFMEMORY; 613 } 614 615 TRACE("Successfully initialized 3D.\n"); 616 617 return DD_OK; 618 } 619 620 static HRESULT ddraw_create_swapchain(struct ddraw *ddraw, HWND window, BOOL windowed) 621 { 622 struct wined3d_swapchain_desc swapchain_desc; 623 struct wined3d_display_mode mode; 624 HRESULT hr = WINED3D_OK; 625 626 if (FAILED(hr = wined3d_get_adapter_display_mode(ddraw->wined3d, WINED3DADAPTER_DEFAULT, &mode, NULL))) 627 { 628 ERR("Failed to get display mode.\n"); 629 return hr; 630 } 631 632 memset(&swapchain_desc, 0, sizeof(swapchain_desc)); 633 swapchain_desc.backbuffer_width = mode.width; 634 swapchain_desc.backbuffer_height = mode.height; 635 swapchain_desc.backbuffer_format = mode.format_id; 636 swapchain_desc.backbuffer_usage = WINED3DUSAGE_RENDERTARGET; 637 swapchain_desc.swap_effect = WINED3D_SWAP_EFFECT_COPY; 638 swapchain_desc.device_window = window; 639 swapchain_desc.windowed = windowed; 640 swapchain_desc.flags = WINED3D_SWAPCHAIN_ALLOW_MODE_SWITCH; 641 642 if (!(ddraw->flags & DDRAW_NO3D)) 643 hr = ddraw_attach_d3d_device(ddraw, &swapchain_desc); 644 else 645 hr = wined3d_device_init_gdi(ddraw->wined3d_device, &swapchain_desc); 646 647 if (FAILED(hr)) 648 { 649 ERR("Failed to create swapchain, hr %#x.\n", hr); 650 return hr; 651 } 652 653 if (!(ddraw->wined3d_swapchain = wined3d_device_get_swapchain(ddraw->wined3d_device, 0))) 654 { 655 ERR("Failed to get swapchain.\n"); 656 return DDERR_INVALIDPARAMS; 657 } 658 659 wined3d_swapchain_incref(ddraw->wined3d_swapchain); 660 ddraw_set_swapchain_window(ddraw, window); 661 662 if (ddraw->primary && ddraw->primary->palette) 663 wined3d_swapchain_set_palette(ddraw->wined3d_swapchain, ddraw->primary->palette->wined3d_palette); 664 665 return DD_OK; 666 } 667 668 /***************************************************************************** 669 * IDirectDraw7::RestoreDisplayMode 670 * 671 * Restores the display mode to what it was at creation time. Basically. 672 * 673 * Returns 674 * DD_OK on success 675 * DDERR_NOEXCLUSIVE mode if the device isn't in fullscreen mode 676 * 677 *****************************************************************************/ 678 static HRESULT WINAPI ddraw7_RestoreDisplayMode(IDirectDraw7 *iface) 679 { 680 struct ddraw *ddraw = impl_from_IDirectDraw7(iface); 681 HRESULT hr; 682 683 TRACE("iface %p.\n", iface); 684 685 wined3d_mutex_lock(); 686 687 if (!(ddraw->flags & DDRAW_RESTORE_MODE)) 688 { 689 wined3d_mutex_unlock(); 690 return DD_OK; 691 } 692 693 if (exclusive_ddraw && exclusive_ddraw != ddraw) 694 { 695 wined3d_mutex_unlock(); 696 return DDERR_NOEXCLUSIVEMODE; 697 } 698 699 if (SUCCEEDED(hr = wined3d_set_adapter_display_mode(ddraw->wined3d, WINED3DADAPTER_DEFAULT, NULL))) 700 ddraw->flags &= ~DDRAW_RESTORE_MODE; 701 702 InterlockedCompareExchange(&ddraw->device_state, DDRAW_DEVICE_STATE_NOT_RESTORED, DDRAW_DEVICE_STATE_OK); 703 704 wined3d_mutex_unlock(); 705 706 return hr; 707 } 708 709 static HRESULT WINAPI ddraw4_RestoreDisplayMode(IDirectDraw4 *iface) 710 { 711 struct ddraw *ddraw = impl_from_IDirectDraw4(iface); 712 713 TRACE("iface %p.\n", iface); 714 715 return ddraw7_RestoreDisplayMode(&ddraw->IDirectDraw7_iface); 716 } 717 718 static HRESULT WINAPI ddraw2_RestoreDisplayMode(IDirectDraw2 *iface) 719 { 720 struct ddraw *ddraw = impl_from_IDirectDraw2(iface); 721 722 TRACE("iface %p.\n", iface); 723 724 return ddraw7_RestoreDisplayMode(&ddraw->IDirectDraw7_iface); 725 } 726 727 static HRESULT WINAPI ddraw1_RestoreDisplayMode(IDirectDraw *iface) 728 { 729 struct ddraw *ddraw = impl_from_IDirectDraw(iface); 730 731 TRACE("iface %p.\n", iface); 732 733 return ddraw7_RestoreDisplayMode(&ddraw->IDirectDraw7_iface); 734 } 735 736 /***************************************************************************** 737 * IDirectDraw7::SetCooperativeLevel 738 * 739 * Sets the cooperative level for the DirectDraw object, and the window 740 * assigned to it. The cooperative level determines the general behavior 741 * of the DirectDraw application 742 * 743 * Warning: This is quite tricky, as it's not really documented which 744 * cooperative levels can be combined with each other. If a game fails 745 * after this function, try to check the cooperative levels passed on 746 * Windows, and if it returns something different. 747 * 748 * If you think that this function caused the failure because it writes a 749 * fixme, be sure to run again with a +ddraw trace. 750 * 751 * What is known about cooperative levels (See the ddraw modes test): 752 * DDSCL_EXCLUSIVE requires DDSCL_FULLSCREEN. 753 * DDSCL_NORMAL is not compatible with DDSCL_EXCLUSIVE. 754 * Unlike what msdn claims, DDSCL_NORMAL | DDSCL_FULLSCREEN is allowed. 755 * DDSCL_SETFOCUSWINDOW can be passed only in DDSCL_NORMAL mode, but after that 756 * DDSCL_EXCLUSIVE can be activated. 757 * DDSCL_SETFOCUSWINDOW may only be used with DDSCL_NOWINDOWCHANGES or 758 * DDSCL_CREATEDEVICEWINDOW. 759 * 760 * Handled flags: DDSCL_NORMAL, DDSCL_FULLSCREEN, DDSCL_EXCLUSIVE, 761 * DDSCL_CREATEDEVICEWINDOW, DDSCL_SETDEVICEWINDOW 762 * DDSCL_SETFOCUSWINDOW (partially), 763 * DDSCL_MULTITHREADED (work in progress) 764 * DDSCL_FPUPRESERVE (see device.c) 765 * 766 * Unsure about this: DDSCL_FPUSETUP 767 * 768 * These don't seem very important for wine: 769 * DDSCL_ALLOWREBOOT, DDSCL_NOWINDOWCHANGES, DDSCL_ALLOWMODEX 770 * 771 * Returns: 772 * DD_OK if the cooperative level was set successfully 773 * DDERR_INVALIDPARAMS if the passed cooperative level combination is invalid 774 * DDERR_HWNDALREADYSET if DDSCL_SETFOCUSWINDOW is passed in exclusive mode 775 * (Probably others too, have to investigate) 776 * 777 *****************************************************************************/ 778 static HRESULT ddraw_set_cooperative_level(struct ddraw *ddraw, HWND window, 779 DWORD cooplevel, BOOL restore_mode_on_normal) 780 { 781 struct wined3d_rendertarget_view *rtv = NULL, *dsv = NULL; 782 struct wined3d_stateblock *stateblock; 783 BOOL restore_state = FALSE; 784 HRESULT hr; 785 786 TRACE("ddraw %p, window %p, flags %#x, restore_mode_on_normal %x.\n", ddraw, window, cooplevel, 787 restore_mode_on_normal); 788 DDRAW_dump_cooperativelevel(cooplevel); 789 790 wined3d_mutex_lock(); 791 792 if (ddraw->flags & DDRAW_SCL_RECURSIVE) 793 { 794 WARN("Recursive call, returning DD_OK.\n"); 795 hr = DD_OK; 796 goto done; 797 } 798 ddraw->flags |= DDRAW_SCL_RECURSIVE; 799 800 /* Tests suggest that we need one of them: */ 801 if(!(cooplevel & (DDSCL_SETFOCUSWINDOW | 802 DDSCL_NORMAL | 803 DDSCL_EXCLUSIVE ))) 804 { 805 TRACE("Incorrect cooplevel flags, returning DDERR_INVALIDPARAMS\n"); 806 hr = DDERR_INVALIDPARAMS; 807 goto done; 808 } 809 810 if ((cooplevel & DDSCL_CREATEDEVICEWINDOW) && !(cooplevel & DDSCL_EXCLUSIVE)) 811 { 812 WARN("DDSCL_CREATEDEVICEWINDOW requires DDSCL_EXCLUSIVE.\n"); 813 hr = DDERR_INVALIDPARAMS; 814 goto done; 815 } 816 817 /* Handle those levels first which set various hwnds */ 818 if ((cooplevel & DDSCL_SETFOCUSWINDOW) && !(cooplevel & DDSCL_CREATEDEVICEWINDOW)) 819 { 820 /* This isn't compatible with a lot of flags */ 821 if (cooplevel & (DDSCL_MULTITHREADED 822 | DDSCL_FPUSETUP 823 | DDSCL_FPUPRESERVE 824 | DDSCL_ALLOWREBOOT 825 | DDSCL_ALLOWMODEX 826 | DDSCL_SETDEVICEWINDOW 827 | DDSCL_NORMAL 828 | DDSCL_EXCLUSIVE 829 | DDSCL_FULLSCREEN)) 830 { 831 WARN("Called with incompatible flags, returning DDERR_INVALIDPARAMS.\n"); 832 hr = DDERR_INVALIDPARAMS; 833 goto done; 834 } 835 836 hr = ddraw_set_focus_window(ddraw, window); 837 goto done; 838 } 839 840 if (cooplevel & DDSCL_EXCLUSIVE) 841 { 842 if (!(cooplevel & DDSCL_FULLSCREEN) || !(window || (cooplevel & DDSCL_CREATEDEVICEWINDOW))) 843 { 844 WARN("DDSCL_EXCLUSIVE requires DDSCL_FULLSCREEN and a window.\n"); 845 hr = DDERR_INVALIDPARAMS; 846 goto done; 847 } 848 849 if (cooplevel & DDSCL_CREATEDEVICEWINDOW) 850 { 851 HWND device_window; 852 853 if (!ddraw->focuswindow && !(cooplevel & DDSCL_SETFOCUSWINDOW)) 854 { 855 WARN("No focus window set.\n"); 856 hr = DDERR_NOFOCUSWINDOW; 857 goto done; 858 } 859 860 device_window = CreateWindowExA(0, DDRAW_WINDOW_CLASS_NAME, "DirectDrawDeviceWnd", 861 WS_POPUP, 0, 0, GetSystemMetrics(SM_CXSCREEN), GetSystemMetrics(SM_CYSCREEN), 862 NULL, NULL, NULL, NULL); 863 if (!device_window) 864 { 865 ERR("Failed to create window, last error %#x.\n", GetLastError()); 866 hr = E_FAIL; 867 goto done; 868 } 869 870 ShowWindow(device_window, SW_SHOW); 871 TRACE("Created a device window %p.\n", device_window); 872 873 /* Native apparently leaks the created device window if setting the 874 * focus window below fails. */ 875 ddraw->cooperative_level |= DDSCL_CREATEDEVICEWINDOW; 876 ddraw->devicewindow = device_window; 877 878 if (cooplevel & DDSCL_SETFOCUSWINDOW) 879 { 880 if (!window) 881 { 882 hr = DDERR_NOHWND; 883 goto done; 884 } 885 886 if (FAILED(hr = ddraw_set_focus_window(ddraw, window))) 887 goto done; 888 } 889 890 window = device_window; 891 } 892 } 893 else 894 { 895 if (ddraw->cooperative_level & DDSCL_CREATEDEVICEWINDOW) 896 DestroyWindow(ddraw->devicewindow); 897 ddraw->devicewindow = NULL; 898 ddraw->focuswindow = NULL; 899 } 900 901 if ((cooplevel & DDSCL_FULLSCREEN) != (ddraw->cooperative_level & DDSCL_FULLSCREEN) || window != ddraw->dest_window) 902 { 903 if (ddraw->cooperative_level & DDSCL_FULLSCREEN) 904 wined3d_device_restore_fullscreen_window(ddraw->wined3d_device, ddraw->dest_window, NULL); 905 906 if (cooplevel & DDSCL_FULLSCREEN) 907 { 908 struct wined3d_display_mode display_mode; 909 910 wined3d_get_adapter_display_mode(ddraw->wined3d, WINED3DADAPTER_DEFAULT, &display_mode, NULL); 911 wined3d_device_setup_fullscreen_window(ddraw->wined3d_device, window, 912 display_mode.width, display_mode.height); 913 } 914 } 915 916 if ((cooplevel & DDSCL_EXCLUSIVE) && exclusive_window != window) 917 { 918 ddraw->device_state = DDRAW_DEVICE_STATE_NOT_RESTORED; 919 exclusive_window = window; 920 } 921 922 if (cooplevel & DDSCL_MULTITHREADED && !(ddraw->cooperative_level & DDSCL_MULTITHREADED)) 923 wined3d_device_set_multithreaded(ddraw->wined3d_device); 924 925 if (ddraw->wined3d_swapchain) 926 { 927 if (!(ddraw->flags & DDRAW_NO3D)) 928 { 929 restore_state = TRUE; 930 931 if (FAILED(hr = wined3d_stateblock_create(ddraw->wined3d_device, WINED3D_SBT_ALL, &stateblock))) 932 { 933 ERR("Failed to create stateblock, hr %#x.\n", hr); 934 goto done; 935 } 936 937 wined3d_stateblock_capture(stateblock); 938 rtv = wined3d_device_get_rendertarget_view(ddraw->wined3d_device, 0); 939 /* Rendering to ddraw->wined3d_frontbuffer. */ 940 if (rtv && !wined3d_rendertarget_view_get_sub_resource_parent(rtv)) 941 rtv = NULL; 942 else if (rtv) 943 wined3d_rendertarget_view_incref(rtv); 944 945 if ((dsv = wined3d_device_get_depth_stencil_view(ddraw->wined3d_device))) 946 wined3d_rendertarget_view_incref(dsv); 947 } 948 949 ddraw_destroy_swapchain(ddraw); 950 } 951 952 if (FAILED(hr = ddraw_create_swapchain(ddraw, window, !(cooplevel & DDSCL_FULLSCREEN)))) 953 ERR("Failed to create swapchain, hr %#x.\n", hr); 954 955 if (restore_state) 956 { 957 if (dsv) 958 { 959 wined3d_device_set_depth_stencil_view(ddraw->wined3d_device, dsv); 960 wined3d_rendertarget_view_decref(dsv); 961 } 962 963 if (rtv) 964 { 965 wined3d_device_set_rendertarget_view(ddraw->wined3d_device, 0, rtv, FALSE); 966 wined3d_rendertarget_view_decref(rtv); 967 } 968 969 wined3d_stateblock_apply(stateblock); 970 wined3d_stateblock_decref(stateblock); 971 } 972 973 if (!(cooplevel & DDSCL_EXCLUSIVE) && (ddraw->cooperative_level & DDSCL_EXCLUSIVE) 974 && restore_mode_on_normal) 975 { 976 hr = ddraw7_RestoreDisplayMode(&ddraw->IDirectDraw7_iface); 977 if (FAILED(hr)) 978 ERR("RestoreDisplayMode failed\n"); 979 } 980 981 if ((ddraw->cooperative_level & DDSCL_EXCLUSIVE) 982 && (window != ddraw->dest_window || !(cooplevel & DDSCL_EXCLUSIVE))) 983 wined3d_device_release_focus_window(ddraw->wined3d_device); 984 985 if ((cooplevel & DDSCL_EXCLUSIVE) 986 && (window != ddraw->dest_window || !(ddraw->cooperative_level & DDSCL_EXCLUSIVE))) 987 { 988 hr = wined3d_device_acquire_focus_window(ddraw->wined3d_device, window); 989 if (FAILED(hr)) 990 { 991 ERR("Failed to acquire focus window, hr %#x.\n", hr); 992 goto done; 993 } 994 } 995 996 /* Unhandled flags */ 997 if (cooplevel & DDSCL_ALLOWREBOOT) 998 WARN("Unhandled flag DDSCL_ALLOWREBOOT, harmless\n"); 999 if (cooplevel & DDSCL_ALLOWMODEX) 1000 WARN("Unhandled flag DDSCL_ALLOWMODEX, harmless\n"); 1001 if (cooplevel & DDSCL_FPUSETUP) 1002 WARN("Unhandled flag DDSCL_FPUSETUP, harmless\n"); 1003 1004 if (cooplevel & DDSCL_EXCLUSIVE) 1005 exclusive_ddraw = ddraw; 1006 else if (exclusive_ddraw == ddraw) 1007 exclusive_ddraw = NULL; 1008 1009 /* Store the cooperative_level */ 1010 ddraw->cooperative_level = cooplevel; 1011 ddraw->dest_window = window; 1012 1013 TRACE("SetCooperativeLevel returning DD_OK\n"); 1014 hr = DD_OK; 1015 done: 1016 ddraw->flags &= ~DDRAW_SCL_RECURSIVE; 1017 wined3d_mutex_unlock(); 1018 1019 return hr; 1020 } 1021 1022 static HRESULT WINAPI ddraw7_SetCooperativeLevel(IDirectDraw7 *iface, HWND window, DWORD flags) 1023 { 1024 struct ddraw *ddraw = impl_from_IDirectDraw7(iface); 1025 1026 TRACE("iface %p, window %p, flags %#x.\n", iface, window, flags); 1027 1028 return ddraw_set_cooperative_level(ddraw, window, flags, !(ddraw->flags & DDRAW_SCL_DDRAW1)); 1029 } 1030 1031 static HRESULT WINAPI ddraw4_SetCooperativeLevel(IDirectDraw4 *iface, HWND window, DWORD flags) 1032 { 1033 struct ddraw *ddraw = impl_from_IDirectDraw4(iface); 1034 1035 TRACE("iface %p, window %p, flags %#x.\n", iface, window, flags); 1036 1037 return ddraw_set_cooperative_level(ddraw, window, flags, !(ddraw->flags & DDRAW_SCL_DDRAW1)); 1038 } 1039 1040 static HRESULT WINAPI ddraw2_SetCooperativeLevel(IDirectDraw2 *iface, HWND window, DWORD flags) 1041 { 1042 struct ddraw *ddraw = impl_from_IDirectDraw2(iface); 1043 1044 TRACE("iface %p, window %p, flags %#x.\n", iface, window, flags); 1045 1046 return ddraw_set_cooperative_level(ddraw, window, flags, !(ddraw->flags & DDRAW_SCL_DDRAW1)); 1047 } 1048 1049 static HRESULT WINAPI ddraw1_SetCooperativeLevel(IDirectDraw *iface, HWND window, DWORD flags) 1050 { 1051 struct ddraw *ddraw = impl_from_IDirectDraw(iface); 1052 HRESULT hr; 1053 1054 TRACE("iface %p, window %p, flags %#x.\n", iface, window, flags); 1055 1056 hr = ddraw_set_cooperative_level(ddraw, window, flags, FALSE); 1057 if (SUCCEEDED(hr)) 1058 ddraw->flags |= DDRAW_SCL_DDRAW1; 1059 return hr; 1060 } 1061 1062 /***************************************************************************** 1063 * IDirectDraw7::SetDisplayMode 1064 * 1065 * Sets the display screen resolution, color depth and refresh frequency 1066 * when in fullscreen mode (in theory). 1067 * Possible return values listed in the SDK suggest that this method fails 1068 * when not in fullscreen mode, but this is wrong. Windows 2000 happily sets 1069 * the display mode in DDSCL_NORMAL mode without an hwnd specified. 1070 * It seems to be valid to pass 0 for With and Height, this has to be tested 1071 * It could mean that the current video mode should be left as-is. (But why 1072 * call it then?) 1073 * 1074 * Params: 1075 * Height, Width: Screen dimension 1076 * BPP: Color depth in Bits per pixel 1077 * Refreshrate: Screen refresh rate 1078 * Flags: Other stuff 1079 * 1080 * Returns 1081 * DD_OK on success 1082 * 1083 *****************************************************************************/ 1084 static HRESULT WINAPI ddraw7_SetDisplayMode(IDirectDraw7 *iface, DWORD width, DWORD height, 1085 DWORD bpp, DWORD refresh_rate, DWORD flags) 1086 { 1087 struct ddraw *ddraw = impl_from_IDirectDraw7(iface); 1088 struct wined3d_display_mode mode; 1089 enum wined3d_format_id format; 1090 HRESULT hr; 1091 1092 TRACE("iface %p, width %u, height %u, bpp %u, refresh_rate %u, flags %#x.\n", 1093 iface, width, height, bpp, refresh_rate, flags); 1094 1095 if (force_refresh_rate != 0) 1096 { 1097 TRACE("ForceRefreshRate overriding passed-in refresh rate (%u Hz) to %u Hz\n", 1098 refresh_rate, force_refresh_rate); 1099 refresh_rate = force_refresh_rate; 1100 } 1101 1102 wined3d_mutex_lock(); 1103 1104 if (exclusive_ddraw && exclusive_ddraw != ddraw) 1105 { 1106 wined3d_mutex_unlock(); 1107 return DDERR_NOEXCLUSIVEMODE; 1108 } 1109 1110 if (!width || !height) 1111 { 1112 /* It looks like Need for Speed Porsche Unleashed expects DD_OK here. */ 1113 wined3d_mutex_unlock(); 1114 return DD_OK; 1115 } 1116 1117 switch (bpp) 1118 { 1119 case 8: format = WINED3DFMT_P8_UINT; break; 1120 case 15: format = WINED3DFMT_B5G5R5X1_UNORM; break; 1121 case 16: format = WINED3DFMT_B5G6R5_UNORM; break; 1122 case 24: format = WINED3DFMT_B8G8R8_UNORM; break; 1123 case 32: format = WINED3DFMT_B8G8R8X8_UNORM; break; 1124 default: format = WINED3DFMT_UNKNOWN; break; 1125 } 1126 1127 mode.width = width; 1128 mode.height = height; 1129 mode.refresh_rate = refresh_rate; 1130 mode.format_id = format; 1131 mode.scanline_ordering = WINED3D_SCANLINE_ORDERING_UNKNOWN; 1132 1133 /* TODO: The possible return values from msdn suggest that the screen mode 1134 * can't be changed if a surface is locked or some drawing is in progress. */ 1135 if (SUCCEEDED(hr = wined3d_set_adapter_display_mode(ddraw->wined3d, WINED3DADAPTER_DEFAULT, &mode))) 1136 { 1137 if (ddraw->primary) 1138 { 1139 DDSURFACEDESC2 *surface_desc = &ddraw->primary->surface_desc; 1140 1141 if (FAILED(hr = wined3d_swapchain_resize_buffers(ddraw->wined3d_swapchain, 0, 1142 surface_desc->dwWidth, surface_desc->dwHeight, mode.format_id, WINED3D_MULTISAMPLE_NONE, 0))) 1143 ERR("Failed to resize buffers, hr %#x.\n", hr); 1144 else 1145 ddrawformat_from_wined3dformat(&ddraw->primary->surface_desc.u4.ddpfPixelFormat, mode.format_id); 1146 } 1147 ddraw->flags |= DDRAW_RESTORE_MODE; 1148 } 1149 1150 InterlockedCompareExchange(&ddraw->device_state, DDRAW_DEVICE_STATE_NOT_RESTORED, DDRAW_DEVICE_STATE_OK); 1151 1152 wined3d_mutex_unlock(); 1153 1154 switch (hr) 1155 { 1156 case WINED3DERR_NOTAVAILABLE: return DDERR_UNSUPPORTED; 1157 default: return hr; 1158 } 1159 } 1160 1161 static HRESULT WINAPI ddraw4_SetDisplayMode(IDirectDraw4 *iface, DWORD width, DWORD height, 1162 DWORD bpp, DWORD refresh_rate, DWORD flags) 1163 { 1164 struct ddraw *ddraw = impl_from_IDirectDraw4(iface); 1165 1166 TRACE("iface %p, width %u, height %u, bpp %u, refresh_rate %u, flags %#x.\n", 1167 iface, width, height, bpp, refresh_rate, flags); 1168 1169 return ddraw7_SetDisplayMode(&ddraw->IDirectDraw7_iface, width, height, bpp, refresh_rate, flags); 1170 } 1171 1172 static HRESULT WINAPI ddraw2_SetDisplayMode(IDirectDraw2 *iface, 1173 DWORD width, DWORD height, DWORD bpp, DWORD refresh_rate, DWORD flags) 1174 { 1175 struct ddraw *ddraw = impl_from_IDirectDraw2(iface); 1176 1177 TRACE("iface %p, width %u, height %u, bpp %u, refresh_rate %u, flags %#x.\n", 1178 iface, width, height, bpp, refresh_rate, flags); 1179 1180 return ddraw7_SetDisplayMode(&ddraw->IDirectDraw7_iface, width, height, bpp, refresh_rate, flags); 1181 } 1182 1183 static HRESULT WINAPI ddraw1_SetDisplayMode(IDirectDraw *iface, DWORD width, DWORD height, DWORD bpp) 1184 { 1185 struct ddraw *ddraw = impl_from_IDirectDraw(iface); 1186 1187 TRACE("iface %p, width %u, height %u, bpp %u.\n", iface, width, height, bpp); 1188 1189 return ddraw7_SetDisplayMode(&ddraw->IDirectDraw7_iface, width, height, bpp, 0, 0); 1190 } 1191 1192 void ddraw_d3dcaps1_from_7(D3DDEVICEDESC *caps1, D3DDEVICEDESC7 *caps7) 1193 { 1194 memset(caps1, 0, sizeof(*caps1)); 1195 caps1->dwSize = sizeof(*caps1); 1196 caps1->dwFlags = D3DDD_COLORMODEL 1197 | D3DDD_DEVCAPS 1198 | D3DDD_TRANSFORMCAPS 1199 | D3DDD_BCLIPPING 1200 | D3DDD_LIGHTINGCAPS 1201 | D3DDD_LINECAPS 1202 | D3DDD_TRICAPS 1203 | D3DDD_DEVICERENDERBITDEPTH 1204 | D3DDD_DEVICEZBUFFERBITDEPTH 1205 | D3DDD_MAXBUFFERSIZE 1206 | D3DDD_MAXVERTEXCOUNT; 1207 caps1->dcmColorModel = D3DCOLOR_RGB; 1208 caps1->dwDevCaps = caps7->dwDevCaps; 1209 caps1->dtcTransformCaps.dwSize = sizeof(caps1->dtcTransformCaps); 1210 caps1->dtcTransformCaps.dwCaps = D3DTRANSFORMCAPS_CLIP; 1211 caps1->bClipping = TRUE; 1212 caps1->dlcLightingCaps.dwSize = sizeof(caps1->dlcLightingCaps); 1213 caps1->dlcLightingCaps.dwCaps = D3DLIGHTCAPS_DIRECTIONAL 1214 | D3DLIGHTCAPS_PARALLELPOINT 1215 | D3DLIGHTCAPS_POINT 1216 | D3DLIGHTCAPS_SPOT; 1217 caps1->dlcLightingCaps.dwLightingModel = D3DLIGHTINGMODEL_RGB; 1218 caps1->dlcLightingCaps.dwNumLights = caps7->dwMaxActiveLights; 1219 caps1->dpcLineCaps = caps7->dpcLineCaps; 1220 caps1->dpcTriCaps = caps7->dpcTriCaps; 1221 caps1->dwDeviceRenderBitDepth = caps7->dwDeviceRenderBitDepth; 1222 caps1->dwDeviceZBufferBitDepth = caps7->dwDeviceZBufferBitDepth; 1223 caps1->dwMaxBufferSize = 0; 1224 caps1->dwMaxVertexCount = 65536; 1225 caps1->dwMinTextureWidth = caps7->dwMinTextureWidth; 1226 caps1->dwMinTextureHeight = caps7->dwMinTextureHeight; 1227 caps1->dwMaxTextureWidth = caps7->dwMaxTextureWidth; 1228 caps1->dwMaxTextureHeight = caps7->dwMaxTextureHeight; 1229 caps1->dwMinStippleWidth = 1; 1230 caps1->dwMinStippleHeight = 1; 1231 caps1->dwMaxStippleWidth = 32; 1232 caps1->dwMaxStippleHeight = 32; 1233 caps1->dwMaxTextureRepeat = caps7->dwMaxTextureRepeat; 1234 caps1->dwMaxTextureAspectRatio = caps7->dwMaxTextureAspectRatio; 1235 caps1->dwMaxAnisotropy = caps7->dwMaxAnisotropy; 1236 caps1->dvGuardBandLeft = caps7->dvGuardBandLeft; 1237 caps1->dvGuardBandTop = caps7->dvGuardBandTop; 1238 caps1->dvGuardBandRight = caps7->dvGuardBandRight; 1239 caps1->dvGuardBandBottom = caps7->dvGuardBandBottom; 1240 caps1->dvExtentsAdjust = caps7->dvExtentsAdjust; 1241 caps1->dwStencilCaps = caps7->dwStencilCaps; 1242 caps1->dwFVFCaps = caps7->dwFVFCaps; 1243 caps1->dwTextureOpCaps = caps7->dwTextureOpCaps; 1244 caps1->wMaxTextureBlendStages = caps7->wMaxTextureBlendStages; 1245 caps1->wMaxSimultaneousTextures = caps7->wMaxSimultaneousTextures; 1246 } 1247 1248 HRESULT ddraw_get_d3dcaps(const struct ddraw *ddraw, D3DDEVICEDESC7 *caps) 1249 { 1250 WINED3DCAPS wined3d_caps; 1251 HRESULT hr; 1252 1253 TRACE("ddraw %p, caps %p.\n", ddraw, caps); 1254 1255 memset(&wined3d_caps, 0, sizeof(wined3d_caps)); 1256 1257 wined3d_mutex_lock(); 1258 hr = wined3d_get_device_caps(ddraw->wined3d, 0, WINED3D_DEVICE_TYPE_HAL, &wined3d_caps); 1259 wined3d_mutex_unlock(); 1260 if (FAILED(hr)) 1261 { 1262 WARN("Failed to get device caps, hr %#x.\n", hr); 1263 return hr; 1264 } 1265 1266 caps->dwDevCaps = wined3d_caps.DevCaps; 1267 caps->dpcLineCaps.dwMiscCaps = wined3d_caps.PrimitiveMiscCaps; 1268 caps->dpcLineCaps.dwRasterCaps = wined3d_caps.RasterCaps; 1269 caps->dpcLineCaps.dwZCmpCaps = wined3d_caps.ZCmpCaps; 1270 caps->dpcLineCaps.dwSrcBlendCaps = wined3d_caps.SrcBlendCaps; 1271 caps->dpcLineCaps.dwDestBlendCaps = wined3d_caps.DestBlendCaps; 1272 caps->dpcLineCaps.dwAlphaCmpCaps = wined3d_caps.AlphaCmpCaps; 1273 caps->dpcLineCaps.dwShadeCaps = wined3d_caps.ShadeCaps; 1274 caps->dpcLineCaps.dwTextureCaps = wined3d_caps.TextureCaps; 1275 caps->dpcLineCaps.dwTextureFilterCaps = wined3d_caps.TextureFilterCaps; 1276 caps->dpcLineCaps.dwTextureAddressCaps = wined3d_caps.TextureAddressCaps; 1277 1278 caps->dwMaxTextureWidth = wined3d_caps.MaxTextureWidth; 1279 caps->dwMaxTextureHeight = wined3d_caps.MaxTextureHeight; 1280 1281 caps->dwMaxTextureRepeat = wined3d_caps.MaxTextureRepeat; 1282 caps->dwMaxTextureAspectRatio = wined3d_caps.MaxTextureAspectRatio; 1283 caps->dwMaxAnisotropy = wined3d_caps.MaxAnisotropy; 1284 caps->dvMaxVertexW = wined3d_caps.MaxVertexW; 1285 1286 caps->dvGuardBandLeft = wined3d_caps.GuardBandLeft; 1287 caps->dvGuardBandTop = wined3d_caps.GuardBandTop; 1288 caps->dvGuardBandRight = wined3d_caps.GuardBandRight; 1289 caps->dvGuardBandBottom = wined3d_caps.GuardBandBottom; 1290 1291 caps->dvExtentsAdjust = wined3d_caps.ExtentsAdjust; 1292 caps->dwStencilCaps = wined3d_caps.StencilCaps; 1293 1294 caps->dwFVFCaps = wined3d_caps.FVFCaps; 1295 caps->dwTextureOpCaps = wined3d_caps.TextureOpCaps; 1296 1297 caps->dwVertexProcessingCaps = wined3d_caps.VertexProcessingCaps; 1298 caps->dwMaxActiveLights = wined3d_caps.MaxActiveLights; 1299 1300 /* Remove all non-d3d7 caps */ 1301 caps->dwDevCaps &= ( 1302 D3DDEVCAPS_FLOATTLVERTEX | D3DDEVCAPS_SORTINCREASINGZ | D3DDEVCAPS_SORTDECREASINGZ | 1303 D3DDEVCAPS_SORTEXACT | D3DDEVCAPS_EXECUTESYSTEMMEMORY | D3DDEVCAPS_EXECUTEVIDEOMEMORY | 1304 D3DDEVCAPS_TLVERTEXSYSTEMMEMORY | D3DDEVCAPS_TLVERTEXVIDEOMEMORY | D3DDEVCAPS_TEXTURESYSTEMMEMORY | 1305 D3DDEVCAPS_TEXTUREVIDEOMEMORY | D3DDEVCAPS_DRAWPRIMTLVERTEX | D3DDEVCAPS_CANRENDERAFTERFLIP | 1306 D3DDEVCAPS_TEXTURENONLOCALVIDMEM | D3DDEVCAPS_DRAWPRIMITIVES2 | D3DDEVCAPS_SEPARATETEXTUREMEMORIES | 1307 D3DDEVCAPS_DRAWPRIMITIVES2EX | D3DDEVCAPS_HWTRANSFORMANDLIGHT | D3DDEVCAPS_CANBLTSYSTONONLOCAL | 1308 D3DDEVCAPS_HWRASTERIZATION); 1309 1310 caps->dwStencilCaps &= ( 1311 D3DSTENCILCAPS_KEEP | D3DSTENCILCAPS_ZERO | D3DSTENCILCAPS_REPLACE | 1312 D3DSTENCILCAPS_INCRSAT | D3DSTENCILCAPS_DECRSAT | D3DSTENCILCAPS_INVERT | 1313 D3DSTENCILCAPS_INCR | D3DSTENCILCAPS_DECR); 1314 1315 /* FVF caps ?*/ 1316 1317 caps->dwTextureOpCaps &= ( 1318 D3DTEXOPCAPS_DISABLE | D3DTEXOPCAPS_SELECTARG1 | D3DTEXOPCAPS_SELECTARG2 | 1319 D3DTEXOPCAPS_MODULATE | D3DTEXOPCAPS_MODULATE2X | D3DTEXOPCAPS_MODULATE4X | 1320 D3DTEXOPCAPS_ADD | D3DTEXOPCAPS_ADDSIGNED | D3DTEXOPCAPS_ADDSIGNED2X | 1321 D3DTEXOPCAPS_SUBTRACT | D3DTEXOPCAPS_ADDSMOOTH | D3DTEXOPCAPS_BLENDTEXTUREALPHA | 1322 D3DTEXOPCAPS_BLENDFACTORALPHA | D3DTEXOPCAPS_BLENDTEXTUREALPHAPM | D3DTEXOPCAPS_BLENDCURRENTALPHA | 1323 D3DTEXOPCAPS_PREMODULATE | D3DTEXOPCAPS_MODULATEALPHA_ADDCOLOR | D3DTEXOPCAPS_MODULATECOLOR_ADDALPHA | 1324 D3DTEXOPCAPS_MODULATEINVALPHA_ADDCOLOR | D3DTEXOPCAPS_MODULATEINVCOLOR_ADDALPHA | D3DTEXOPCAPS_BUMPENVMAP | 1325 D3DTEXOPCAPS_BUMPENVMAPLUMINANCE | D3DTEXOPCAPS_DOTPRODUCT3); 1326 1327 caps->dwVertexProcessingCaps &= ( 1328 D3DVTXPCAPS_TEXGEN | D3DVTXPCAPS_MATERIALSOURCE7 | D3DVTXPCAPS_VERTEXFOG | 1329 D3DVTXPCAPS_DIRECTIONALLIGHTS | D3DVTXPCAPS_POSITIONALLIGHTS | D3DVTXPCAPS_LOCALVIEWER); 1330 1331 caps->dpcLineCaps.dwMiscCaps &= ( 1332 D3DPMISCCAPS_MASKPLANES | D3DPMISCCAPS_MASKZ | D3DPMISCCAPS_LINEPATTERNREP | 1333 D3DPMISCCAPS_CONFORMANT | D3DPMISCCAPS_CULLNONE | D3DPMISCCAPS_CULLCW | 1334 D3DPMISCCAPS_CULLCCW); 1335 1336 caps->dpcLineCaps.dwRasterCaps &= ( 1337 D3DPRASTERCAPS_DITHER | D3DPRASTERCAPS_ROP2 | D3DPRASTERCAPS_XOR | 1338 D3DPRASTERCAPS_PAT | D3DPRASTERCAPS_ZTEST | D3DPRASTERCAPS_SUBPIXEL | 1339 D3DPRASTERCAPS_SUBPIXELX | D3DPRASTERCAPS_FOGVERTEX | D3DPRASTERCAPS_FOGTABLE | 1340 D3DPRASTERCAPS_STIPPLE | D3DPRASTERCAPS_ANTIALIASSORTDEPENDENT | D3DPRASTERCAPS_ANTIALIASSORTINDEPENDENT | 1341 D3DPRASTERCAPS_ANTIALIASEDGES | D3DPRASTERCAPS_MIPMAPLODBIAS | D3DPRASTERCAPS_ZBIAS | 1342 D3DPRASTERCAPS_ZBUFFERLESSHSR | D3DPRASTERCAPS_FOGRANGE | D3DPRASTERCAPS_ANISOTROPY | 1343 D3DPRASTERCAPS_WBUFFER | D3DPRASTERCAPS_TRANSLUCENTSORTINDEPENDENT | D3DPRASTERCAPS_WFOG | 1344 D3DPRASTERCAPS_ZFOG); 1345 1346 caps->dpcLineCaps.dwZCmpCaps &= ( 1347 D3DPCMPCAPS_NEVER | D3DPCMPCAPS_LESS | D3DPCMPCAPS_EQUAL | 1348 D3DPCMPCAPS_LESSEQUAL | D3DPCMPCAPS_GREATER | D3DPCMPCAPS_NOTEQUAL | 1349 D3DPCMPCAPS_GREATEREQUAL | D3DPCMPCAPS_ALWAYS); 1350 1351 caps->dpcLineCaps.dwSrcBlendCaps &= ( 1352 D3DPBLENDCAPS_ZERO | D3DPBLENDCAPS_ONE | D3DPBLENDCAPS_SRCCOLOR | 1353 D3DPBLENDCAPS_INVSRCCOLOR | D3DPBLENDCAPS_SRCALPHA | D3DPBLENDCAPS_INVSRCALPHA | 1354 D3DPBLENDCAPS_DESTALPHA | D3DPBLENDCAPS_INVDESTALPHA | D3DPBLENDCAPS_DESTCOLOR | 1355 D3DPBLENDCAPS_INVDESTCOLOR | D3DPBLENDCAPS_SRCALPHASAT | D3DPBLENDCAPS_BOTHSRCALPHA | 1356 D3DPBLENDCAPS_BOTHINVSRCALPHA); 1357 1358 caps->dpcLineCaps.dwDestBlendCaps &= ( 1359 D3DPBLENDCAPS_ZERO | D3DPBLENDCAPS_ONE | D3DPBLENDCAPS_SRCCOLOR | 1360 D3DPBLENDCAPS_INVSRCCOLOR | D3DPBLENDCAPS_SRCALPHA | D3DPBLENDCAPS_INVSRCALPHA | 1361 D3DPBLENDCAPS_DESTALPHA | D3DPBLENDCAPS_INVDESTALPHA | D3DPBLENDCAPS_DESTCOLOR | 1362 D3DPBLENDCAPS_INVDESTCOLOR | D3DPBLENDCAPS_SRCALPHASAT | D3DPBLENDCAPS_BOTHSRCALPHA | 1363 D3DPBLENDCAPS_BOTHINVSRCALPHA); 1364 1365 caps->dpcLineCaps.dwAlphaCmpCaps &= ( 1366 D3DPCMPCAPS_NEVER | D3DPCMPCAPS_LESS | D3DPCMPCAPS_EQUAL | 1367 D3DPCMPCAPS_LESSEQUAL | D3DPCMPCAPS_GREATER | D3DPCMPCAPS_NOTEQUAL | 1368 D3DPCMPCAPS_GREATEREQUAL | D3DPCMPCAPS_ALWAYS); 1369 1370 caps->dpcLineCaps.dwShadeCaps &= ( 1371 D3DPSHADECAPS_COLORFLATMONO | D3DPSHADECAPS_COLORFLATRGB | D3DPSHADECAPS_COLORGOURAUDMONO | 1372 D3DPSHADECAPS_COLORGOURAUDRGB | D3DPSHADECAPS_COLORPHONGMONO | D3DPSHADECAPS_COLORPHONGRGB | 1373 D3DPSHADECAPS_SPECULARFLATMONO | D3DPSHADECAPS_SPECULARFLATRGB | D3DPSHADECAPS_SPECULARGOURAUDMONO | 1374 D3DPSHADECAPS_SPECULARGOURAUDRGB | D3DPSHADECAPS_SPECULARPHONGMONO | D3DPSHADECAPS_SPECULARPHONGRGB | 1375 D3DPSHADECAPS_ALPHAFLATBLEND | D3DPSHADECAPS_ALPHAFLATSTIPPLED | D3DPSHADECAPS_ALPHAGOURAUDBLEND | 1376 D3DPSHADECAPS_ALPHAGOURAUDSTIPPLED | D3DPSHADECAPS_ALPHAPHONGBLEND | D3DPSHADECAPS_ALPHAPHONGSTIPPLED | 1377 D3DPSHADECAPS_FOGFLAT | D3DPSHADECAPS_FOGGOURAUD | D3DPSHADECAPS_FOGPHONG); 1378 1379 caps->dpcLineCaps.dwTextureCaps &= ( 1380 D3DPTEXTURECAPS_PERSPECTIVE | D3DPTEXTURECAPS_POW2 | D3DPTEXTURECAPS_ALPHA | 1381 D3DPTEXTURECAPS_TRANSPARENCY | D3DPTEXTURECAPS_BORDER | D3DPTEXTURECAPS_SQUAREONLY | 1382 D3DPTEXTURECAPS_TEXREPEATNOTSCALEDBYSIZE | D3DPTEXTURECAPS_ALPHAPALETTE| D3DPTEXTURECAPS_NONPOW2CONDITIONAL | 1383 D3DPTEXTURECAPS_PROJECTED | D3DPTEXTURECAPS_CUBEMAP | D3DPTEXTURECAPS_COLORKEYBLEND); 1384 1385 caps->dpcLineCaps.dwTextureFilterCaps &= ( 1386 D3DPTFILTERCAPS_NEAREST | D3DPTFILTERCAPS_LINEAR | D3DPTFILTERCAPS_MIPNEAREST | 1387 D3DPTFILTERCAPS_MIPLINEAR | D3DPTFILTERCAPS_LINEARMIPNEAREST | D3DPTFILTERCAPS_LINEARMIPLINEAR | 1388 D3DPTFILTERCAPS_MINFPOINT | D3DPTFILTERCAPS_MINFLINEAR | D3DPTFILTERCAPS_MINFANISOTROPIC | 1389 D3DPTFILTERCAPS_MIPFPOINT | D3DPTFILTERCAPS_MIPFLINEAR | D3DPTFILTERCAPS_MAGFPOINT | 1390 D3DPTFILTERCAPS_MAGFLINEAR | D3DPTFILTERCAPS_MAGFANISOTROPIC | D3DPTFILTERCAPS_MAGFAFLATCUBIC | 1391 D3DPTFILTERCAPS_MAGFGAUSSIANCUBIC); 1392 1393 caps->dpcLineCaps.dwTextureAddressCaps &= ( 1394 D3DPTADDRESSCAPS_WRAP | D3DPTADDRESSCAPS_MIRROR | D3DPTADDRESSCAPS_CLAMP | 1395 D3DPTADDRESSCAPS_BORDER | D3DPTADDRESSCAPS_INDEPENDENTUV); 1396 1397 if (!(caps->dpcLineCaps.dwTextureCaps & D3DPTEXTURECAPS_POW2)) 1398 { 1399 /* DirectX7 always has the np2 flag set, no matter what the card 1400 * supports. Some old games (Rollcage) check the caps incorrectly. 1401 * If wined3d supports nonpow2 textures it also has np2 conditional 1402 * support. */ 1403 caps->dpcLineCaps.dwTextureCaps |= D3DPTEXTURECAPS_POW2 | D3DPTEXTURECAPS_NONPOW2CONDITIONAL; 1404 } 1405 1406 /* Fill the missing members, and do some fixup */ 1407 caps->dpcLineCaps.dwSize = sizeof(caps->dpcLineCaps); 1408 caps->dpcLineCaps.dwTextureBlendCaps = D3DPTBLENDCAPS_ADD 1409 | D3DPTBLENDCAPS_MODULATEMASK 1410 | D3DPTBLENDCAPS_COPY 1411 | D3DPTBLENDCAPS_DECAL 1412 | D3DPTBLENDCAPS_DECALALPHA 1413 | D3DPTBLENDCAPS_DECALMASK 1414 | D3DPTBLENDCAPS_MODULATE 1415 | D3DPTBLENDCAPS_MODULATEALPHA; 1416 caps->dpcLineCaps.dwStippleWidth = 32; 1417 caps->dpcLineCaps.dwStippleHeight = 32; 1418 /* Use the same for the TriCaps */ 1419 caps->dpcTriCaps = caps->dpcLineCaps; 1420 1421 caps->dwDeviceRenderBitDepth = DDBD_16 | DDBD_24 | DDBD_32; 1422 caps->dwDeviceZBufferBitDepth = DDBD_16 | DDBD_24; 1423 caps->dwMinTextureWidth = 1; 1424 caps->dwMinTextureHeight = 1; 1425 1426 /* Convert DWORDs safely to WORDs */ 1427 caps->wMaxTextureBlendStages = min(wined3d_caps.MaxTextureBlendStages, 0xffff); 1428 caps->wMaxSimultaneousTextures = min(wined3d_caps.MaxSimultaneousTextures, 0xffff); 1429 caps->wMaxUserClipPlanes = min(wined3d_caps.MaxUserClipPlanes, D3DMAXUSERCLIPPLANES); 1430 caps->wMaxVertexBlendMatrices = min(wined3d_caps.MaxVertexBlendMatrices, 0xffff); 1431 1432 caps->deviceGUID = IID_IDirect3DTnLHalDevice; 1433 1434 caps->dwReserved1 = 0; 1435 caps->dwReserved2 = 0; 1436 caps->dwReserved3 = 0; 1437 caps->dwReserved4 = 0; 1438 1439 return DD_OK; 1440 } 1441 1442 HRESULT CALLBACK enum_zbuffer(DDPIXELFORMAT *format, void *ctx) 1443 { 1444 DDCAPS *caps = ctx; 1445 1446 switch (format->u1.dwZBufferBitDepth) 1447 { 1448 case 8: 1449 caps->dwZBufferBitDepths |= DDBD_8; 1450 break; 1451 case 16: 1452 caps->dwZBufferBitDepths |= DDBD_16; 1453 break; 1454 case 24: 1455 caps->dwZBufferBitDepths |= DDBD_24; 1456 break; 1457 case 32: 1458 caps->dwZBufferBitDepths |= DDBD_32; 1459 break; 1460 } 1461 return D3DENUMRET_OK; 1462 } 1463 1464 /***************************************************************************** 1465 * IDirectDraw7::GetCaps 1466 * 1467 * Returns the drives capabilities 1468 * 1469 * Used for version 1, 2, 4 and 7 1470 * 1471 * Params: 1472 * DriverCaps: Structure to write the Hardware accelerated caps to 1473 * HelCaps: Structure to write the emulation caps to 1474 * 1475 * Returns 1476 * This implementation returns DD_OK only 1477 * 1478 *****************************************************************************/ 1479 static HRESULT WINAPI ddraw7_GetCaps(IDirectDraw7 *iface, DDCAPS *DriverCaps, DDCAPS *HELCaps) 1480 { 1481 struct ddraw *ddraw = impl_from_IDirectDraw7(iface); 1482 DDCAPS caps; 1483 WINED3DCAPS winecaps; 1484 HRESULT hr; 1485 DDSCAPS2 ddscaps = {0, 0, 0, {0}}; 1486 1487 TRACE("iface %p, driver_caps %p, hel_caps %p.\n", iface, DriverCaps, HELCaps); 1488 1489 /* One structure must be != NULL */ 1490 if (!DriverCaps && !HELCaps) 1491 { 1492 WARN("Invalid parameters.\n"); 1493 return DDERR_INVALIDPARAMS; 1494 } 1495 1496 memset(&caps, 0, sizeof(caps)); 1497 memset(&winecaps, 0, sizeof(winecaps)); 1498 caps.dwSize = sizeof(caps); 1499 1500 wined3d_mutex_lock(); 1501 hr = wined3d_device_get_device_caps(ddraw->wined3d_device, &winecaps); 1502 if (FAILED(hr)) 1503 { 1504 WARN("Failed to get device caps, %#x.\n", hr); 1505 wined3d_mutex_unlock(); 1506 return hr; 1507 } 1508 1509 hr = IDirectDraw7_GetAvailableVidMem(iface, &ddscaps, &caps.dwVidMemTotal, &caps.dwVidMemFree); 1510 if (FAILED(hr)) 1511 { 1512 WARN("IDirectDraw7::GetAvailableVidMem failed\n"); 1513 wined3d_mutex_unlock(); 1514 return hr; 1515 } 1516 1517 hr = IDirectDraw7_GetFourCCCodes(iface, &caps.dwNumFourCCCodes, NULL); 1518 wined3d_mutex_unlock(); 1519 if (FAILED(hr)) 1520 { 1521 WARN("IDirectDraw7::GetFourCCCodes failed\n"); 1522 return hr; 1523 } 1524 1525 caps.dwCaps = winecaps.ddraw_caps.caps; 1526 caps.dwCaps2 = winecaps.ddraw_caps.caps2; 1527 caps.dwCKeyCaps = winecaps.ddraw_caps.color_key_caps; 1528 caps.dwFXCaps = winecaps.ddraw_caps.fx_caps; 1529 caps.dwPalCaps = DDPCAPS_8BIT | DDPCAPS_PRIMARYSURFACE; 1530 caps.ddsCaps.dwCaps = winecaps.ddraw_caps.dds_caps; 1531 caps.dwSVBCaps = winecaps.ddraw_caps.svb_caps; 1532 caps.dwSVBCKeyCaps = winecaps.ddraw_caps.svb_color_key_caps; 1533 caps.dwSVBFXCaps = winecaps.ddraw_caps.svb_fx_caps; 1534 caps.dwVSBCaps = winecaps.ddraw_caps.vsb_caps; 1535 caps.dwVSBCKeyCaps = winecaps.ddraw_caps.vsb_color_key_caps; 1536 caps.dwVSBFXCaps = winecaps.ddraw_caps.vsb_fx_caps; 1537 caps.dwSSBCaps = winecaps.ddraw_caps.ssb_caps; 1538 caps.dwSSBCKeyCaps = winecaps.ddraw_caps.ssb_color_key_caps; 1539 caps.dwSSBFXCaps = winecaps.ddraw_caps.ssb_fx_caps; 1540 1541 caps.dwCaps |= DDCAPS_ALIGNSTRIDE; 1542 caps.dwAlignStrideAlign = DDRAW_STRIDE_ALIGNMENT; 1543 1544 caps.ddsOldCaps.dwCaps = caps.ddsCaps.dwCaps; 1545 1546 IDirect3D7_EnumZBufferFormats(&ddraw->IDirect3D7_iface, &IID_IDirect3DHALDevice, enum_zbuffer, &caps); 1547 1548 if(DriverCaps) 1549 { 1550 DD_STRUCT_COPY_BYSIZE(DriverCaps, &caps); 1551 if (TRACE_ON(ddraw)) 1552 { 1553 TRACE("Driver Caps :\n"); 1554 DDRAW_dump_DDCAPS(DriverCaps); 1555 } 1556 1557 } 1558 if(HELCaps) 1559 { 1560 DD_STRUCT_COPY_BYSIZE(HELCaps, &caps); 1561 if (TRACE_ON(ddraw)) 1562 { 1563 TRACE("HEL Caps :\n"); 1564 DDRAW_dump_DDCAPS(HELCaps); 1565 } 1566 } 1567 1568 return DD_OK; 1569 } 1570 1571 static HRESULT WINAPI ddraw4_GetCaps(IDirectDraw4 *iface, DDCAPS *driver_caps, DDCAPS *hel_caps) 1572 { 1573 struct ddraw *ddraw = impl_from_IDirectDraw4(iface); 1574 1575 TRACE("iface %p, driver_caps %p, hel_caps %p.\n", iface, driver_caps, hel_caps); 1576 1577 return ddraw7_GetCaps(&ddraw->IDirectDraw7_iface, driver_caps, hel_caps); 1578 } 1579 1580 static HRESULT WINAPI ddraw2_GetCaps(IDirectDraw2 *iface, DDCAPS *driver_caps, DDCAPS *hel_caps) 1581 { 1582 struct ddraw *ddraw = impl_from_IDirectDraw2(iface); 1583 1584 TRACE("iface %p, driver_caps %p, hel_caps %p.\n", iface, driver_caps, hel_caps); 1585 1586 return ddraw7_GetCaps(&ddraw->IDirectDraw7_iface, driver_caps, hel_caps); 1587 } 1588 1589 static HRESULT WINAPI ddraw1_GetCaps(IDirectDraw *iface, DDCAPS *driver_caps, DDCAPS *hel_caps) 1590 { 1591 struct ddraw *ddraw = impl_from_IDirectDraw(iface); 1592 1593 TRACE("iface %p, driver_caps %p, hel_caps %p.\n", iface, driver_caps, hel_caps); 1594 1595 return ddraw7_GetCaps(&ddraw->IDirectDraw7_iface, driver_caps, hel_caps); 1596 } 1597 1598 /***************************************************************************** 1599 * IDirectDraw7::Compact 1600 * 1601 * No idea what it does, MSDN says it's not implemented. 1602 * 1603 * Returns 1604 * DD_OK, but this is unchecked 1605 * 1606 *****************************************************************************/ 1607 static HRESULT WINAPI ddraw7_Compact(IDirectDraw7 *iface) 1608 { 1609 TRACE("iface %p.\n", iface); 1610 1611 return DD_OK; 1612 } 1613 1614 static HRESULT WINAPI ddraw4_Compact(IDirectDraw4 *iface) 1615 { 1616 struct ddraw *ddraw = impl_from_IDirectDraw4(iface); 1617 1618 TRACE("iface %p.\n", iface); 1619 1620 return ddraw7_Compact(&ddraw->IDirectDraw7_iface); 1621 } 1622 1623 static HRESULT WINAPI ddraw2_Compact(IDirectDraw2 *iface) 1624 { 1625 struct ddraw *ddraw = impl_from_IDirectDraw2(iface); 1626 1627 TRACE("iface %p.\n", iface); 1628 1629 return ddraw7_Compact(&ddraw->IDirectDraw7_iface); 1630 } 1631 1632 static HRESULT WINAPI ddraw1_Compact(IDirectDraw *iface) 1633 { 1634 struct ddraw *ddraw = impl_from_IDirectDraw(iface); 1635 1636 TRACE("iface %p.\n", iface); 1637 1638 return ddraw7_Compact(&ddraw->IDirectDraw7_iface); 1639 } 1640 1641 /***************************************************************************** 1642 * IDirectDraw7::GetDisplayMode 1643 * 1644 * Returns information about the current display mode 1645 * 1646 * Exists in versions 1, 2, 4 and 7 1647 * 1648 * Params: 1649 * DDSD: Address of a surface description structure to write the info to 1650 * 1651 * Returns 1652 * DD_OK 1653 * 1654 *****************************************************************************/ 1655 static HRESULT WINAPI ddraw7_GetDisplayMode(IDirectDraw7 *iface, DDSURFACEDESC2 *DDSD) 1656 { 1657 struct ddraw *ddraw = impl_from_IDirectDraw7(iface); 1658 struct wined3d_display_mode mode; 1659 HRESULT hr; 1660 1661 TRACE("iface %p, surface_desc %p.\n", iface, DDSD); 1662 1663 /* This seems sane */ 1664 if (!DDSD || (DDSD->dwSize != sizeof(DDSURFACEDESC) && DDSD->dwSize != sizeof(DDSURFACEDESC2))) 1665 return DDERR_INVALIDPARAMS; 1666 1667 wined3d_mutex_lock(); 1668 1669 if (FAILED(hr = wined3d_get_adapter_display_mode(ddraw->wined3d, WINED3DADAPTER_DEFAULT, &mode, NULL))) 1670 { 1671 ERR("Failed to get display mode, hr %#x.\n", hr); 1672 wined3d_mutex_unlock(); 1673 return hr; 1674 } 1675 1676 memset(DDSD, 0, DDSD->dwSize); 1677 DDSD->dwSize = sizeof(*DDSD); 1678 DDSD->dwFlags |= DDSD_HEIGHT | DDSD_WIDTH | DDSD_PIXELFORMAT | DDSD_PITCH | DDSD_REFRESHRATE; 1679 DDSD->dwWidth = mode.width; 1680 DDSD->dwHeight = mode.height; 1681 DDSD->u2.dwRefreshRate = 60; 1682 DDSD->ddsCaps.dwCaps = 0; 1683 DDSD->u4.ddpfPixelFormat.dwSize = sizeof(DDSD->u4.ddpfPixelFormat); 1684 ddrawformat_from_wined3dformat(&DDSD->u4.ddpfPixelFormat, mode.format_id); 1685 DDSD->u1.lPitch = mode.width * DDSD->u4.ddpfPixelFormat.u1.dwRGBBitCount / 8; 1686 1687 if(TRACE_ON(ddraw)) 1688 { 1689 TRACE("Returning surface desc :\n"); 1690 DDRAW_dump_surface_desc(DDSD); 1691 } 1692 1693 wined3d_mutex_unlock(); 1694 1695 return DD_OK; 1696 } 1697 1698 static HRESULT WINAPI ddraw4_GetDisplayMode(IDirectDraw4 *iface, DDSURFACEDESC2 *surface_desc) 1699 { 1700 struct ddraw *ddraw = impl_from_IDirectDraw4(iface); 1701 1702 TRACE("iface %p, surface_desc %p.\n", iface, surface_desc); 1703 1704 return ddraw7_GetDisplayMode(&ddraw->IDirectDraw7_iface, surface_desc); 1705 } 1706 1707 static HRESULT WINAPI ddraw2_GetDisplayMode(IDirectDraw2 *iface, DDSURFACEDESC *surface_desc) 1708 { 1709 struct ddraw *ddraw = impl_from_IDirectDraw2(iface); 1710 HRESULT hr; 1711 1712 TRACE("iface %p, surface_desc %p.\n", iface, surface_desc); 1713 1714 hr = ddraw7_GetDisplayMode(&ddraw->IDirectDraw7_iface, (DDSURFACEDESC2 *)surface_desc); 1715 if (SUCCEEDED(hr)) surface_desc->dwSize = sizeof(*surface_desc); 1716 return hr; 1717 } 1718 1719 static HRESULT WINAPI ddraw1_GetDisplayMode(IDirectDraw *iface, DDSURFACEDESC *surface_desc) 1720 { 1721 struct ddraw *ddraw = impl_from_IDirectDraw(iface); 1722 HRESULT hr; 1723 1724 TRACE("iface %p, surface_desc %p.\n", iface, surface_desc); 1725 1726 hr = ddraw7_GetDisplayMode(&ddraw->IDirectDraw7_iface, (DDSURFACEDESC2 *)surface_desc); 1727 if (SUCCEEDED(hr)) surface_desc->dwSize = sizeof(*surface_desc); 1728 return hr; 1729 } 1730 1731 /***************************************************************************** 1732 * IDirectDraw7::GetFourCCCodes 1733 * 1734 * Returns an array of supported FourCC codes. 1735 * 1736 * Exists in versions 1, 2, 4 and 7 1737 * 1738 * Params: 1739 * NumCodes: Contains the number of Codes that Codes can carry. Returns the number 1740 * of enumerated codes 1741 * Codes: Pointer to an array of DWORDs where the supported codes are written 1742 * to 1743 * 1744 * Returns 1745 * Always returns DD_OK, as it's a stub for now 1746 * 1747 *****************************************************************************/ 1748 static HRESULT WINAPI ddraw7_GetFourCCCodes(IDirectDraw7 *iface, DWORD *NumCodes, DWORD *Codes) 1749 { 1750 struct ddraw *ddraw = impl_from_IDirectDraw7(iface); 1751 static const enum wined3d_format_id formats[] = 1752 { 1753 WINED3DFMT_YUY2, WINED3DFMT_UYVY, WINED3DFMT_YV12, 1754 WINED3DFMT_DXT1, WINED3DFMT_DXT2, WINED3DFMT_DXT3, WINED3DFMT_DXT4, WINED3DFMT_DXT5, 1755 WINED3DFMT_ATI2N, WINED3DFMT_NVHU, WINED3DFMT_NVHS 1756 }; 1757 struct wined3d_display_mode mode; 1758 DWORD count = 0, i, outsize; 1759 HRESULT hr; 1760 1761 TRACE("iface %p, codes_count %p, codes %p.\n", iface, NumCodes, Codes); 1762 1763 if (FAILED(hr = wined3d_get_adapter_display_mode(ddraw->wined3d, WINED3DADAPTER_DEFAULT, &mode, NULL))) 1764 { 1765 ERR("Failed to get display mode, hr %#x.\n", hr); 1766 return hr; 1767 } 1768 1769 outsize = NumCodes && Codes ? *NumCodes : 0; 1770 1771 for (i = 0; i < ARRAY_SIZE(formats); ++i) 1772 { 1773 if (SUCCEEDED(wined3d_check_device_format(ddraw->wined3d, WINED3DADAPTER_DEFAULT, WINED3D_DEVICE_TYPE_HAL, 1774 mode.format_id, 0, WINED3D_RTYPE_TEXTURE_2D, formats[i]))) 1775 { 1776 if (count < outsize) 1777 Codes[count] = formats[i]; 1778 ++count; 1779 } 1780 } 1781 if(NumCodes) { 1782 TRACE("Returning %u FourCC codes\n", count); 1783 *NumCodes = count; 1784 } 1785 1786 return DD_OK; 1787 } 1788 1789 static HRESULT WINAPI ddraw4_GetFourCCCodes(IDirectDraw4 *iface, DWORD *codes_count, DWORD *codes) 1790 { 1791 struct ddraw *ddraw = impl_from_IDirectDraw4(iface); 1792 1793 TRACE("iface %p, codes_count %p, codes %p.\n", iface, codes_count, codes); 1794 1795 return ddraw7_GetFourCCCodes(&ddraw->IDirectDraw7_iface, codes_count, codes); 1796 } 1797 1798 static HRESULT WINAPI ddraw2_GetFourCCCodes(IDirectDraw2 *iface, DWORD *codes_count, DWORD *codes) 1799 { 1800 struct ddraw *ddraw = impl_from_IDirectDraw2(iface); 1801 1802 TRACE("iface %p, codes_count %p, codes %p.\n", iface, codes_count, codes); 1803 1804 return ddraw7_GetFourCCCodes(&ddraw->IDirectDraw7_iface, codes_count, codes); 1805 } 1806 1807 static HRESULT WINAPI ddraw1_GetFourCCCodes(IDirectDraw *iface, DWORD *codes_count, DWORD *codes) 1808 { 1809 struct ddraw *ddraw = impl_from_IDirectDraw(iface); 1810 1811 TRACE("iface %p, codes_count %p, codes %p.\n", iface, codes_count, codes); 1812 1813 return ddraw7_GetFourCCCodes(&ddraw->IDirectDraw7_iface, codes_count, codes); 1814 } 1815 1816 static HRESULT WINAPI ddraw7_GetMonitorFrequency(IDirectDraw7 *iface, DWORD *frequency) 1817 { 1818 struct ddraw *ddraw = impl_from_IDirectDraw7(iface); 1819 struct wined3d_display_mode mode; 1820 HRESULT hr; 1821 1822 TRACE("iface %p, frequency %p.\n", iface, frequency); 1823 1824 wined3d_mutex_lock(); 1825 hr = wined3d_get_adapter_display_mode(ddraw->wined3d, WINED3DADAPTER_DEFAULT, &mode, NULL); 1826 wined3d_mutex_unlock(); 1827 if (FAILED(hr)) 1828 { 1829 WARN("Failed to get display mode, hr %#x.\n", hr); 1830 return hr; 1831 } 1832 1833 *frequency = mode.refresh_rate; 1834 1835 return DD_OK; 1836 } 1837 1838 static HRESULT WINAPI ddraw4_GetMonitorFrequency(IDirectDraw4 *iface, DWORD *frequency) 1839 { 1840 struct ddraw *ddraw = impl_from_IDirectDraw4(iface); 1841 1842 TRACE("iface %p, frequency %p.\n", iface, frequency); 1843 1844 return ddraw7_GetMonitorFrequency(&ddraw->IDirectDraw7_iface, frequency); 1845 } 1846 1847 static HRESULT WINAPI ddraw2_GetMonitorFrequency(IDirectDraw2 *iface, DWORD *frequency) 1848 { 1849 struct ddraw *ddraw = impl_from_IDirectDraw2(iface); 1850 1851 TRACE("iface %p, frequency %p.\n", iface, frequency); 1852 1853 return ddraw7_GetMonitorFrequency(&ddraw->IDirectDraw7_iface, frequency); 1854 } 1855 1856 static HRESULT WINAPI ddraw1_GetMonitorFrequency(IDirectDraw *iface, DWORD *frequency) 1857 { 1858 struct ddraw *ddraw = impl_from_IDirectDraw(iface); 1859 1860 TRACE("iface %p, frequency %p.\n", iface, frequency); 1861 1862 return ddraw7_GetMonitorFrequency(&ddraw->IDirectDraw7_iface, frequency); 1863 } 1864 1865 static HRESULT WINAPI ddraw7_GetVerticalBlankStatus(IDirectDraw7 *iface, BOOL *status) 1866 { 1867 struct ddraw *ddraw = impl_from_IDirectDraw7(iface); 1868 struct wined3d_raster_status raster_status; 1869 HRESULT hr; 1870 1871 TRACE("iface %p, status %p.\n", iface, status); 1872 1873 if(!status) 1874 return DDERR_INVALIDPARAMS; 1875 1876 wined3d_mutex_lock(); 1877 hr = wined3d_get_adapter_raster_status(ddraw->wined3d, WINED3DADAPTER_DEFAULT, &raster_status); 1878 wined3d_mutex_unlock(); 1879 if (FAILED(hr)) 1880 { 1881 WARN("Failed to get raster status, hr %#x.\n", hr); 1882 return hr; 1883 } 1884 1885 *status = raster_status.in_vblank; 1886 1887 return DD_OK; 1888 } 1889 1890 static HRESULT WINAPI ddraw4_GetVerticalBlankStatus(IDirectDraw4 *iface, BOOL *status) 1891 { 1892 struct ddraw *ddraw = impl_from_IDirectDraw4(iface); 1893 1894 TRACE("iface %p, status %p.\n", iface, status); 1895 1896 return ddraw7_GetVerticalBlankStatus(&ddraw->IDirectDraw7_iface, status); 1897 } 1898 1899 static HRESULT WINAPI ddraw2_GetVerticalBlankStatus(IDirectDraw2 *iface, BOOL *status) 1900 { 1901 struct ddraw *ddraw = impl_from_IDirectDraw2(iface); 1902 1903 TRACE("iface %p, status %p.\n", iface, status); 1904 1905 return ddraw7_GetVerticalBlankStatus(&ddraw->IDirectDraw7_iface, status); 1906 } 1907 1908 static HRESULT WINAPI ddraw1_GetVerticalBlankStatus(IDirectDraw *iface, BOOL *status) 1909 { 1910 struct ddraw *ddraw = impl_from_IDirectDraw(iface); 1911 1912 TRACE("iface %p, status %p.\n", iface, status); 1913 1914 return ddraw7_GetVerticalBlankStatus(&ddraw->IDirectDraw7_iface, status); 1915 } 1916 1917 /***************************************************************************** 1918 * IDirectDraw7::GetAvailableVidMem 1919 * 1920 * Returns the total and free video memory 1921 * 1922 * Params: 1923 * caps: Specifies the memory type asked for 1924 * total: Pointer to a DWORD to be filled with the total memory 1925 * free: Pointer to a DWORD to be filled with the free memory 1926 * 1927 * Returns 1928 * DD_OK on success 1929 * DDERR_INVALIDPARAMS if free and total are NULL 1930 * 1931 *****************************************************************************/ 1932 static HRESULT WINAPI ddraw7_GetAvailableVidMem(IDirectDraw7 *iface, DDSCAPS2 *caps, DWORD *total, 1933 DWORD *free) 1934 { 1935 unsigned int framebuffer_size, total_vidmem, free_vidmem; 1936 struct ddraw *ddraw = impl_from_IDirectDraw7(iface); 1937 struct wined3d_display_mode mode; 1938 HRESULT hr = DD_OK; 1939 1940 TRACE("iface %p, caps %p, total %p, free %p.\n", iface, caps, total, free); 1941 1942 if (!total && !free) 1943 return DDERR_INVALIDPARAMS; 1944 1945 if (TRACE_ON(ddraw)) 1946 { 1947 TRACE("Asked for memory with description: "); 1948 DDRAW_dump_DDSCAPS2(caps); 1949 } 1950 wined3d_mutex_lock(); 1951 1952 /* Todo: System memory vs local video memory vs non-local video memory 1953 * The MSDN also mentions differences between texture memory and other 1954 * resources, but that's not important 1955 */ 1956 1957 /* Some applications (e.g. 3DMark 2000) assume that the reported amount of 1958 * video memory doesn't include the memory used by the default framebuffer. 1959 */ 1960 if (FAILED(hr = wined3d_get_adapter_display_mode(ddraw->wined3d, WINED3DADAPTER_DEFAULT, &mode, NULL))) 1961 { 1962 WARN("Failed to get display mode, hr %#x.\n", hr); 1963 wined3d_mutex_unlock(); 1964 return hr; 1965 } 1966 framebuffer_size = wined3d_calculate_format_pitch(ddraw->wined3d, WINED3DADAPTER_DEFAULT, 1967 mode.format_id, mode.width); 1968 framebuffer_size *= mode.height; 1969 1970 if (free) 1971 { 1972 free_vidmem = wined3d_device_get_available_texture_mem(ddraw->wined3d_device); 1973 *free = framebuffer_size > free_vidmem ? 0 : free_vidmem - framebuffer_size; 1974 TRACE("Free video memory %#x.\n", *free); 1975 } 1976 1977 if (total) 1978 { 1979 struct wined3d_adapter_identifier desc = {0}; 1980 1981 hr = wined3d_get_adapter_identifier(ddraw->wined3d, WINED3DADAPTER_DEFAULT, 0, &desc); 1982 total_vidmem = min(UINT_MAX, desc.video_memory); 1983 *total = framebuffer_size > total_vidmem ? 0 : total_vidmem - framebuffer_size; 1984 TRACE("Total video memory %#x.\n", *total); 1985 } 1986 1987 wined3d_mutex_unlock(); 1988 1989 return hr; 1990 } 1991 1992 static HRESULT WINAPI ddraw4_GetAvailableVidMem(IDirectDraw4 *iface, 1993 DDSCAPS2 *caps, DWORD *total, DWORD *free) 1994 { 1995 struct ddraw *ddraw = impl_from_IDirectDraw4(iface); 1996 1997 TRACE("iface %p, caps %p, total %p, free %p.\n", iface, caps, total, free); 1998 1999 return ddraw7_GetAvailableVidMem(&ddraw->IDirectDraw7_iface, caps, total, free); 2000 } 2001 2002 static HRESULT WINAPI ddraw2_GetAvailableVidMem(IDirectDraw2 *iface, 2003 DDSCAPS *caps, DWORD *total, DWORD *free) 2004 { 2005 struct ddraw *ddraw = impl_from_IDirectDraw2(iface); 2006 DDSCAPS2 caps2; 2007 2008 TRACE("iface %p, caps %p, total %p, free %p.\n", iface, caps, total, free); 2009 2010 DDRAW_Convert_DDSCAPS_1_To_2(caps, &caps2); 2011 return ddraw7_GetAvailableVidMem(&ddraw->IDirectDraw7_iface, &caps2, total, free); 2012 } 2013 2014 /***************************************************************************** 2015 * IDirectDraw7::Initialize 2016 * 2017 * Initializes a DirectDraw interface. 2018 * 2019 * Params: 2020 * GUID: Interface identifier. Well, don't know what this is really good 2021 * for 2022 * 2023 * Returns 2024 * Returns DD_OK on the first call, 2025 * DDERR_ALREADYINITIALIZED on repeated calls 2026 * 2027 *****************************************************************************/ 2028 static HRESULT WINAPI ddraw7_Initialize(IDirectDraw7 *iface, GUID *guid) 2029 { 2030 struct ddraw *ddraw = impl_from_IDirectDraw7(iface); 2031 2032 TRACE("iface %p, guid %s.\n", iface, debugstr_guid(guid)); 2033 2034 if (ddraw->flags & DDRAW_INITIALIZED) 2035 return DDERR_ALREADYINITIALIZED; 2036 2037 /* FIXME: To properly take the GUID into account we should call 2038 * ddraw_init() here instead of in DDRAW_Create(). */ 2039 if (guid) 2040 FIXME("Ignoring guid %s.\n", debugstr_guid(guid)); 2041 2042 ddraw->flags |= DDRAW_INITIALIZED; 2043 return DD_OK; 2044 } 2045 2046 static HRESULT WINAPI ddraw4_Initialize(IDirectDraw4 *iface, GUID *guid) 2047 { 2048 struct ddraw *ddraw = impl_from_IDirectDraw4(iface); 2049 2050 TRACE("iface %p, guid %s.\n", iface, debugstr_guid(guid)); 2051 2052 return ddraw7_Initialize(&ddraw->IDirectDraw7_iface, guid); 2053 } 2054 2055 static HRESULT WINAPI ddraw2_Initialize(IDirectDraw2 *iface, GUID *guid) 2056 { 2057 struct ddraw *ddraw = impl_from_IDirectDraw2(iface); 2058 2059 TRACE("iface %p, guid %s.\n", iface, debugstr_guid(guid)); 2060 2061 return ddraw7_Initialize(&ddraw->IDirectDraw7_iface, guid); 2062 } 2063 2064 static HRESULT WINAPI ddraw1_Initialize(IDirectDraw *iface, GUID *guid) 2065 { 2066 struct ddraw *ddraw = impl_from_IDirectDraw(iface); 2067 2068 TRACE("iface %p, guid %s.\n", iface, debugstr_guid(guid)); 2069 2070 return ddraw7_Initialize(&ddraw->IDirectDraw7_iface, guid); 2071 } 2072 2073 static HRESULT WINAPI d3d1_Initialize(IDirect3D *iface, REFIID riid) 2074 { 2075 TRACE("iface %p, riid %s.\n", iface, debugstr_guid(riid)); 2076 2077 return DDERR_ALREADYINITIALIZED; 2078 } 2079 2080 /***************************************************************************** 2081 * IDirectDraw7::FlipToGDISurface 2082 * 2083 * "Makes the surface that the GDI writes to the primary surface" 2084 * Looks like some windows specific thing we don't have to care about. 2085 * According to MSDN it permits GDI dialog boxes in FULLSCREEN mode. Good to 2086 * show error boxes ;) 2087 * Well, just return DD_OK. 2088 * 2089 * Returns: 2090 * Always returns DD_OK 2091 * 2092 *****************************************************************************/ 2093 static HRESULT WINAPI ddraw7_FlipToGDISurface(IDirectDraw7 *iface) 2094 { 2095 struct ddraw *ddraw = impl_from_IDirectDraw7(iface); 2096 2097 TRACE("iface %p.\n", iface); 2098 2099 ddraw->flags |= DDRAW_GDI_FLIP; 2100 2101 if (ddraw->primary) 2102 ddraw_surface_update_frontbuffer(ddraw->primary, NULL, FALSE); 2103 2104 return DD_OK; 2105 } 2106 2107 static HRESULT WINAPI ddraw4_FlipToGDISurface(IDirectDraw4 *iface) 2108 { 2109 struct ddraw *ddraw = impl_from_IDirectDraw4(iface); 2110 2111 TRACE("iface %p.\n", iface); 2112 2113 return ddraw7_FlipToGDISurface(&ddraw->IDirectDraw7_iface); 2114 } 2115 2116 static HRESULT WINAPI ddraw2_FlipToGDISurface(IDirectDraw2 *iface) 2117 { 2118 struct ddraw *ddraw = impl_from_IDirectDraw2(iface); 2119 2120 TRACE("iface %p.\n", iface); 2121 2122 return ddraw7_FlipToGDISurface(&ddraw->IDirectDraw7_iface); 2123 } 2124 2125 static HRESULT WINAPI ddraw1_FlipToGDISurface(IDirectDraw *iface) 2126 { 2127 struct ddraw *ddraw = impl_from_IDirectDraw(iface); 2128 2129 TRACE("iface %p.\n", iface); 2130 2131 return ddraw7_FlipToGDISurface(&ddraw->IDirectDraw7_iface); 2132 } 2133 2134 /***************************************************************************** 2135 * IDirectDraw7::WaitForVerticalBlank 2136 * 2137 * This method allows applications to get in sync with the vertical blank 2138 * interval. 2139 * The wormhole demo in the DirectX 7 sdk uses this call, and it doesn't 2140 * redraw the screen, most likely because of this stub 2141 * 2142 * Parameters: 2143 * Flags: one of DDWAITVB_BLOCKBEGIN, DDWAITVB_BLOCKBEGINEVENT 2144 * or DDWAITVB_BLOCKEND 2145 * h: Not used, according to MSDN 2146 * 2147 * Returns: 2148 * Always returns DD_OK 2149 * 2150 *****************************************************************************/ 2151 static HRESULT WINAPI ddraw7_WaitForVerticalBlank(IDirectDraw7 *iface, DWORD Flags, HANDLE event) 2152 { 2153 static BOOL hide; 2154 2155 TRACE("iface %p, flags %#x, event %p.\n", iface, Flags, event); 2156 2157 /* This function is called often, so print the fixme only once */ 2158 if(!hide) 2159 { 2160 FIXME("iface %p, flags %#x, event %p stub!\n", iface, Flags, event); 2161 hide = TRUE; 2162 } 2163 2164 /* MSDN says DDWAITVB_BLOCKBEGINEVENT is not supported */ 2165 if(Flags & DDWAITVB_BLOCKBEGINEVENT) 2166 return DDERR_UNSUPPORTED; /* unchecked */ 2167 2168 return DD_OK; 2169 } 2170 2171 static HRESULT WINAPI ddraw4_WaitForVerticalBlank(IDirectDraw4 *iface, DWORD flags, HANDLE event) 2172 { 2173 struct ddraw *ddraw = impl_from_IDirectDraw4(iface); 2174 2175 TRACE("iface %p, flags %#x, event %p.\n", iface, flags, event); 2176 2177 return ddraw7_WaitForVerticalBlank(&ddraw->IDirectDraw7_iface, flags, event); 2178 } 2179 2180 static HRESULT WINAPI ddraw2_WaitForVerticalBlank(IDirectDraw2 *iface, DWORD flags, HANDLE event) 2181 { 2182 struct ddraw *ddraw = impl_from_IDirectDraw2(iface); 2183 2184 TRACE("iface %p, flags %#x, event %p.\n", iface, flags, event); 2185 2186 return ddraw7_WaitForVerticalBlank(&ddraw->IDirectDraw7_iface, flags, event); 2187 } 2188 2189 static HRESULT WINAPI ddraw1_WaitForVerticalBlank(IDirectDraw *iface, DWORD flags, HANDLE event) 2190 { 2191 struct ddraw *ddraw = impl_from_IDirectDraw(iface); 2192 2193 TRACE("iface %p, flags %#x, event %p.\n", iface, flags, event); 2194 2195 return ddraw7_WaitForVerticalBlank(&ddraw->IDirectDraw7_iface, flags, event); 2196 } 2197 2198 static HRESULT WINAPI ddraw7_GetScanLine(IDirectDraw7 *iface, DWORD *Scanline) 2199 { 2200 struct ddraw *ddraw = impl_from_IDirectDraw7(iface); 2201 struct wined3d_raster_status raster_status; 2202 HRESULT hr; 2203 2204 TRACE("iface %p, line %p.\n", iface, Scanline); 2205 2206 wined3d_mutex_lock(); 2207 hr = wined3d_get_adapter_raster_status(ddraw->wined3d, WINED3DADAPTER_DEFAULT, &raster_status); 2208 wined3d_mutex_unlock(); 2209 if (FAILED(hr)) 2210 { 2211 WARN("Failed to get raster status, hr %#x.\n", hr); 2212 return hr; 2213 } 2214 2215 *Scanline = raster_status.scan_line; 2216 2217 if (raster_status.in_vblank) 2218 return DDERR_VERTICALBLANKINPROGRESS; 2219 2220 return DD_OK; 2221 } 2222 2223 static HRESULT WINAPI ddraw4_GetScanLine(IDirectDraw4 *iface, DWORD *line) 2224 { 2225 struct ddraw *ddraw = impl_from_IDirectDraw4(iface); 2226 2227 TRACE("iface %p, line %p.\n", iface, line); 2228 2229 return ddraw7_GetScanLine(&ddraw->IDirectDraw7_iface, line); 2230 } 2231 2232 static HRESULT WINAPI ddraw2_GetScanLine(IDirectDraw2 *iface, DWORD *line) 2233 { 2234 struct ddraw *ddraw = impl_from_IDirectDraw2(iface); 2235 2236 TRACE("iface %p, line %p.\n", iface, line); 2237 2238 return ddraw7_GetScanLine(&ddraw->IDirectDraw7_iface, line); 2239 } 2240 2241 static HRESULT WINAPI ddraw1_GetScanLine(IDirectDraw *iface, DWORD *line) 2242 { 2243 struct ddraw *ddraw = impl_from_IDirectDraw(iface); 2244 2245 TRACE("iface %p, line %p.\n", iface, line); 2246 2247 return ddraw7_GetScanLine(&ddraw->IDirectDraw7_iface, line); 2248 } 2249 2250 static HRESULT WINAPI ddraw7_TestCooperativeLevel(IDirectDraw7 *iface) 2251 { 2252 struct ddraw *ddraw = impl_from_IDirectDraw7(iface); 2253 2254 TRACE("iface %p.\n", iface); 2255 2256 return ddraw->device_state == DDRAW_DEVICE_STATE_LOST ? DDERR_NOEXCLUSIVEMODE : DD_OK; 2257 } 2258 2259 static HRESULT WINAPI ddraw4_TestCooperativeLevel(IDirectDraw4 *iface) 2260 { 2261 struct ddraw *ddraw = impl_from_IDirectDraw4(iface); 2262 2263 TRACE("iface %p.\n", iface); 2264 2265 return ddraw7_TestCooperativeLevel(&ddraw->IDirectDraw7_iface); 2266 } 2267 2268 /***************************************************************************** 2269 * IDirectDraw7::GetGDISurface 2270 * 2271 * Returns the surface that GDI is treating as the primary surface. 2272 * For Wine this is the front buffer 2273 * 2274 * Params: 2275 * GDISurface: Address to write the surface pointer to 2276 * 2277 * Returns: 2278 * DD_OK if the surface was found 2279 * DDERR_NOTFOUND if the GDI surface wasn't found 2280 * 2281 *****************************************************************************/ 2282 static HRESULT WINAPI ddraw7_GetGDISurface(IDirectDraw7 *iface, IDirectDrawSurface7 **GDISurface) 2283 { 2284 struct ddraw *ddraw = impl_from_IDirectDraw7(iface); 2285 2286 TRACE("iface %p, surface %p.\n", iface, GDISurface); 2287 2288 wined3d_mutex_lock(); 2289 2290 if (!(*GDISurface = &ddraw->primary->IDirectDrawSurface7_iface)) 2291 { 2292 WARN("Primary not created yet.\n"); 2293 wined3d_mutex_unlock(); 2294 return DDERR_NOTFOUND; 2295 } 2296 IDirectDrawSurface7_AddRef(*GDISurface); 2297 2298 wined3d_mutex_unlock(); 2299 2300 return DD_OK; 2301 } 2302 2303 static HRESULT WINAPI ddraw4_GetGDISurface(IDirectDraw4 *iface, IDirectDrawSurface4 **surface) 2304 { 2305 struct ddraw *ddraw = impl_from_IDirectDraw4(iface); 2306 struct ddraw_surface *surface_impl; 2307 IDirectDrawSurface7 *surface7; 2308 HRESULT hr; 2309 2310 TRACE("iface %p, surface %p.\n", iface, surface); 2311 2312 hr = ddraw7_GetGDISurface(&ddraw->IDirectDraw7_iface, &surface7); 2313 if (FAILED(hr)) 2314 { 2315 *surface = NULL; 2316 return hr; 2317 } 2318 surface_impl = impl_from_IDirectDrawSurface7(surface7); 2319 *surface = &surface_impl->IDirectDrawSurface4_iface; 2320 IDirectDrawSurface4_AddRef(*surface); 2321 IDirectDrawSurface7_Release(surface7); 2322 2323 return hr; 2324 } 2325 2326 static HRESULT WINAPI ddraw2_GetGDISurface(IDirectDraw2 *iface, IDirectDrawSurface **surface) 2327 { 2328 struct ddraw *ddraw = impl_from_IDirectDraw2(iface); 2329 struct ddraw_surface *surface_impl; 2330 IDirectDrawSurface7 *surface7; 2331 HRESULT hr; 2332 2333 TRACE("iface %p, surface %p.\n", iface, surface); 2334 2335 hr = ddraw7_GetGDISurface(&ddraw->IDirectDraw7_iface, &surface7); 2336 if (FAILED(hr)) 2337 { 2338 *surface = NULL; 2339 return hr; 2340 } 2341 surface_impl = impl_from_IDirectDrawSurface7(surface7); 2342 *surface = &surface_impl->IDirectDrawSurface_iface; 2343 IDirectDrawSurface_AddRef(*surface); 2344 IDirectDrawSurface7_Release(surface7); 2345 2346 return hr; 2347 } 2348 2349 static HRESULT WINAPI ddraw1_GetGDISurface(IDirectDraw *iface, IDirectDrawSurface **surface) 2350 { 2351 struct ddraw *ddraw = impl_from_IDirectDraw(iface); 2352 struct ddraw_surface *surface_impl; 2353 IDirectDrawSurface7 *surface7; 2354 HRESULT hr; 2355 2356 TRACE("iface %p, surface %p.\n", iface, surface); 2357 2358 hr = ddraw7_GetGDISurface(&ddraw->IDirectDraw7_iface, &surface7); 2359 if (FAILED(hr)) 2360 { 2361 *surface = NULL; 2362 return hr; 2363 } 2364 surface_impl = impl_from_IDirectDrawSurface7(surface7); 2365 *surface = &surface_impl->IDirectDrawSurface_iface; 2366 IDirectDrawSurface_AddRef(*surface); 2367 IDirectDrawSurface7_Release(surface7); 2368 2369 return hr; 2370 } 2371 2372 struct displaymodescallback_context 2373 { 2374 LPDDENUMMODESCALLBACK func; 2375 void *context; 2376 }; 2377 2378 static HRESULT CALLBACK EnumDisplayModesCallbackThunk(DDSURFACEDESC2 *surface_desc, void *context) 2379 { 2380 struct displaymodescallback_context *cbcontext = context; 2381 DDSURFACEDESC desc; 2382 2383 DDSD2_to_DDSD(surface_desc, &desc); 2384 return cbcontext->func(&desc, cbcontext->context); 2385 } 2386 2387 /***************************************************************************** 2388 * IDirectDraw7::EnumDisplayModes 2389 * 2390 * Enumerates the supported Display modes. The modes can be filtered with 2391 * the DDSD parameter. 2392 * 2393 * Params: 2394 * Flags: can be DDEDM_REFRESHRATES and DDEDM_STANDARDVGAMODES. For old ddraw 2395 * versions (3 and older?) this is reserved and must be 0. 2396 * DDSD: Surface description to filter the modes 2397 * Context: Pointer passed back to the callback function 2398 * cb: Application-provided callback function 2399 * 2400 * Returns: 2401 * DD_OK on success 2402 * DDERR_INVALIDPARAMS if the callback wasn't set 2403 * 2404 *****************************************************************************/ 2405 static HRESULT WINAPI ddraw7_EnumDisplayModes(IDirectDraw7 *iface, DWORD Flags, 2406 DDSURFACEDESC2 *DDSD, void *Context, LPDDENUMMODESCALLBACK2 cb) 2407 { 2408 struct ddraw *ddraw = impl_from_IDirectDraw7(iface); 2409 struct wined3d_display_mode *enum_modes = NULL; 2410 struct wined3d_display_mode mode; 2411 unsigned int modenum, fmt; 2412 DDSURFACEDESC2 callback_sd; 2413 unsigned enum_mode_count = 0, enum_mode_array_size = 16; 2414 DDPIXELFORMAT pixelformat; 2415 2416 static const enum wined3d_format_id checkFormatList[] = 2417 { 2418 WINED3DFMT_B8G8R8X8_UNORM, 2419 WINED3DFMT_B5G6R5_UNORM, 2420 WINED3DFMT_P8_UINT, 2421 }; 2422 2423 TRACE("iface %p, flags %#x, surface_desc %p, context %p, callback %p.\n", 2424 iface, Flags, DDSD, Context, cb); 2425 2426 if (!cb) 2427 return DDERR_INVALIDPARAMS; 2428 2429 if (!(enum_modes = heap_alloc(enum_mode_array_size * sizeof(*enum_modes)))) 2430 return DDERR_OUTOFMEMORY; 2431 2432 wined3d_mutex_lock(); 2433 2434 pixelformat.dwSize = sizeof(pixelformat); 2435 for(fmt = 0; fmt < ARRAY_SIZE(checkFormatList); fmt++) 2436 { 2437 modenum = 0; 2438 while (wined3d_enum_adapter_modes(ddraw->wined3d, WINED3DADAPTER_DEFAULT, checkFormatList[fmt], 2439 WINED3D_SCANLINE_ORDERING_UNKNOWN, modenum++, &mode) == WINED3D_OK) 2440 { 2441 BOOL found = FALSE; 2442 unsigned i; 2443 2444 ddrawformat_from_wined3dformat(&pixelformat, mode.format_id); 2445 if (DDSD) 2446 { 2447 if (DDSD->dwFlags & DDSD_WIDTH && mode.width != DDSD->dwWidth) 2448 continue; 2449 if (DDSD->dwFlags & DDSD_HEIGHT && mode.height != DDSD->dwHeight) 2450 continue; 2451 if (DDSD->dwFlags & DDSD_REFRESHRATE && mode.refresh_rate != DDSD->u2.dwRefreshRate) 2452 continue; 2453 if (DDSD->dwFlags & DDSD_PIXELFORMAT 2454 && pixelformat.u1.dwRGBBitCount != DDSD->u4.ddpfPixelFormat.u1.dwRGBBitCount) 2455 continue; 2456 } 2457 2458 /* DX docs state EnumDisplayMode should return only unique modes */ 2459 for (i = 0; i < enum_mode_count; i++) 2460 { 2461 if (enum_modes[i].width == mode.width && enum_modes[i].height == mode.height 2462 && enum_modes[i].format_id == mode.format_id 2463 && (enum_modes[i].refresh_rate == mode.refresh_rate || !(Flags & DDEDM_REFRESHRATES))) 2464 { 2465 found = TRUE; 2466 break; 2467 } 2468 } 2469 if(found) continue; 2470 2471 memset(&callback_sd, 0, sizeof(callback_sd)); 2472 callback_sd.dwSize = sizeof(callback_sd); 2473 callback_sd.u4.ddpfPixelFormat.dwSize = sizeof(DDPIXELFORMAT); 2474 2475 callback_sd.dwFlags = DDSD_HEIGHT|DDSD_WIDTH|DDSD_PIXELFORMAT|DDSD_PITCH|DDSD_REFRESHRATE; 2476 if (Flags & DDEDM_REFRESHRATES) 2477 callback_sd.u2.dwRefreshRate = mode.refresh_rate; 2478 2479 callback_sd.dwWidth = mode.width; 2480 callback_sd.dwHeight = mode.height; 2481 2482 callback_sd.u4.ddpfPixelFormat=pixelformat; 2483 2484 /* Calc pitch and DWORD align like MSDN says */ 2485 callback_sd.u1.lPitch = (callback_sd.u4.ddpfPixelFormat.u1.dwRGBBitCount / 8) * mode.width; 2486 callback_sd.u1.lPitch = (callback_sd.u1.lPitch + 3) & ~3; 2487 2488 TRACE("Enumerating %dx%dx%d @%d\n", callback_sd.dwWidth, callback_sd.dwHeight, callback_sd.u4.ddpfPixelFormat.u1.dwRGBBitCount, 2489 callback_sd.u2.dwRefreshRate); 2490 2491 if(cb(&callback_sd, Context) == DDENUMRET_CANCEL) 2492 { 2493 TRACE("Application asked to terminate the enumeration\n"); 2494 heap_free(enum_modes); 2495 wined3d_mutex_unlock(); 2496 return DD_OK; 2497 } 2498 2499 if (enum_mode_count == enum_mode_array_size) 2500 { 2501 struct wined3d_display_mode *new_enum_modes; 2502 2503 enum_mode_array_size *= 2; 2504 if (!(new_enum_modes = heap_realloc(enum_modes, enum_mode_array_size * sizeof(*new_enum_modes)))) 2505 { 2506 heap_free(enum_modes); 2507 wined3d_mutex_unlock(); 2508 return DDERR_OUTOFMEMORY; 2509 } 2510 2511 enum_modes = new_enum_modes; 2512 } 2513 enum_modes[enum_mode_count++] = mode; 2514 } 2515 } 2516 2517 TRACE("End of enumeration\n"); 2518 heap_free(enum_modes); 2519 wined3d_mutex_unlock(); 2520 2521 return DD_OK; 2522 } 2523 2524 static HRESULT WINAPI ddraw4_EnumDisplayModes(IDirectDraw4 *iface, DWORD flags, 2525 DDSURFACEDESC2 *surface_desc, void *context, LPDDENUMMODESCALLBACK2 callback) 2526 { 2527 struct ddraw *ddraw = impl_from_IDirectDraw4(iface); 2528 2529 TRACE("iface %p, flags %#x, surface_desc %p, context %p, callback %p.\n", 2530 iface, flags, surface_desc, context, callback); 2531 2532 return ddraw7_EnumDisplayModes(&ddraw->IDirectDraw7_iface, flags, surface_desc, context, callback); 2533 } 2534 2535 static HRESULT WINAPI ddraw2_EnumDisplayModes(IDirectDraw2 *iface, DWORD flags, 2536 DDSURFACEDESC *surface_desc, void *context, LPDDENUMMODESCALLBACK callback) 2537 { 2538 struct ddraw *ddraw = impl_from_IDirectDraw2(iface); 2539 struct displaymodescallback_context cbcontext; 2540 DDSURFACEDESC2 surface_desc2; 2541 2542 TRACE("iface %p, flags %#x, surface_desc %p, context %p, callback %p.\n", 2543 iface, flags, surface_desc, context, callback); 2544 2545 cbcontext.func = callback; 2546 cbcontext.context = context; 2547 2548 if (surface_desc) DDSD_to_DDSD2(surface_desc, &surface_desc2); 2549 return ddraw7_EnumDisplayModes(&ddraw->IDirectDraw7_iface, flags, 2550 surface_desc ? &surface_desc2 : NULL, &cbcontext, EnumDisplayModesCallbackThunk); 2551 } 2552 2553 static HRESULT WINAPI ddraw1_EnumDisplayModes(IDirectDraw *iface, DWORD flags, 2554 DDSURFACEDESC *surface_desc, void *context, LPDDENUMMODESCALLBACK callback) 2555 { 2556 struct ddraw *ddraw = impl_from_IDirectDraw(iface); 2557 struct displaymodescallback_context cbcontext; 2558 DDSURFACEDESC2 surface_desc2; 2559 2560 TRACE("iface %p, flags %#x, surface_desc %p, context %p, callback %p.\n", 2561 iface, flags, surface_desc, context, callback); 2562 2563 cbcontext.func = callback; 2564 cbcontext.context = context; 2565 2566 if (surface_desc) DDSD_to_DDSD2(surface_desc, &surface_desc2); 2567 return ddraw7_EnumDisplayModes(&ddraw->IDirectDraw7_iface, flags, 2568 surface_desc ? &surface_desc2 : NULL, &cbcontext, EnumDisplayModesCallbackThunk); 2569 } 2570 2571 /***************************************************************************** 2572 * IDirectDraw7::EvaluateMode 2573 * 2574 * Used with IDirectDraw7::StartModeTest to test video modes. 2575 * EvaluateMode is used to pass or fail a mode, and continue with the next 2576 * mode 2577 * 2578 * Params: 2579 * Flags: DDEM_MODEPASSED or DDEM_MODEFAILED 2580 * Timeout: Returns the amount of seconds left before the mode would have 2581 * been failed automatically 2582 * 2583 * Returns: 2584 * This implementation always DD_OK, because it's a stub 2585 * 2586 *****************************************************************************/ 2587 static HRESULT WINAPI ddraw7_EvaluateMode(IDirectDraw7 *iface, DWORD Flags, DWORD *Timeout) 2588 { 2589 FIXME("iface %p, flags %#x, timeout %p stub!\n", iface, Flags, Timeout); 2590 2591 /* When implementing this, implement it in WineD3D */ 2592 2593 return DD_OK; 2594 } 2595 2596 /***************************************************************************** 2597 * IDirectDraw7::GetDeviceIdentifier 2598 * 2599 * Returns the device identifier, which gives information about the driver 2600 * Our device identifier is defined at the beginning of this file. 2601 * 2602 * Params: 2603 * DDDI: Address for the returned structure 2604 * Flags: Can be DDGDI_GETHOSTIDENTIFIER 2605 * 2606 * Returns: 2607 * On success it returns DD_OK 2608 * DDERR_INVALIDPARAMS if DDDI is NULL 2609 * 2610 *****************************************************************************/ 2611 static HRESULT WINAPI ddraw7_GetDeviceIdentifier(IDirectDraw7 *iface, 2612 DDDEVICEIDENTIFIER2 *DDDI, DWORD Flags) 2613 { 2614 struct ddraw *ddraw = impl_from_IDirectDraw7(iface); 2615 struct wined3d_adapter_identifier adapter_id; 2616 HRESULT hr = S_OK; 2617 2618 TRACE("iface %p, device_identifier %p, flags %#x.\n", iface, DDDI, Flags); 2619 2620 if (!DDDI) 2621 return DDERR_INVALIDPARAMS; 2622 2623 if (Flags & DDGDI_GETHOSTIDENTIFIER) 2624 { 2625 /* The DDGDI_GETHOSTIDENTIFIER returns the information about the 2D 2626 * host adapter, if there's a secondary 3D adapter. This doesn't apply 2627 * to any modern hardware, nor is it interesting for Wine, so ignore it. 2628 * Size of DDDEVICEIDENTIFIER2 may be aligned to 8 bytes and thus 4 2629 * bytes too long. So only copy the relevant part of the structure 2630 */ 2631 2632 memcpy(DDDI, &deviceidentifier, FIELD_OFFSET(DDDEVICEIDENTIFIER2, dwWHQLLevel) + sizeof(DWORD)); 2633 return DD_OK; 2634 } 2635 2636 /* Drakan: Order of the Flame expects accurate D3D device information from ddraw */ 2637 adapter_id.driver = DDDI->szDriver; 2638 adapter_id.driver_size = sizeof(DDDI->szDriver); 2639 adapter_id.description = DDDI->szDescription; 2640 adapter_id.description_size = sizeof(DDDI->szDescription); 2641 adapter_id.device_name_size = 0; 2642 wined3d_mutex_lock(); 2643 hr = wined3d_get_adapter_identifier(ddraw->wined3d, WINED3DADAPTER_DEFAULT, 0x0, &adapter_id); 2644 wined3d_mutex_unlock(); 2645 if (FAILED(hr)) return hr; 2646 2647 DDDI->liDriverVersion = adapter_id.driver_version; 2648 DDDI->dwVendorId = adapter_id.vendor_id; 2649 DDDI->dwDeviceId = adapter_id.device_id; 2650 DDDI->dwSubSysId = adapter_id.subsystem_id; 2651 DDDI->dwRevision = adapter_id.revision; 2652 DDDI->guidDeviceIdentifier = adapter_id.device_identifier; 2653 DDDI->dwWHQLLevel = adapter_id.whql_level; 2654 return DD_OK; 2655 } 2656 2657 static HRESULT WINAPI ddraw4_GetDeviceIdentifier(IDirectDraw4 *iface, 2658 DDDEVICEIDENTIFIER *identifier, DWORD flags) 2659 { 2660 struct ddraw *ddraw = impl_from_IDirectDraw4(iface); 2661 DDDEVICEIDENTIFIER2 identifier2; 2662 HRESULT hr; 2663 2664 TRACE("iface %p, identifier %p, flags %#x.\n", iface, identifier, flags); 2665 2666 hr = ddraw7_GetDeviceIdentifier(&ddraw->IDirectDraw7_iface, &identifier2, flags); 2667 DDRAW_Convert_DDDEVICEIDENTIFIER_2_To_1(&identifier2, identifier); 2668 2669 return hr; 2670 } 2671 2672 /***************************************************************************** 2673 * IDirectDraw7::GetSurfaceFromDC 2674 * 2675 * Returns the Surface for a GDI device context handle. 2676 * Is this related to IDirectDrawSurface::GetDC ??? 2677 * 2678 * Params: 2679 * hdc: hdc to return the surface for 2680 * Surface: Address to write the surface pointer to 2681 * 2682 * Returns: 2683 * Always returns DD_OK because it's a stub 2684 * 2685 *****************************************************************************/ 2686 static HRESULT WINAPI ddraw7_GetSurfaceFromDC(IDirectDraw7 *iface, 2687 HDC dc, IDirectDrawSurface7 **surface) 2688 { 2689 struct ddraw *ddraw = impl_from_IDirectDraw7(iface); 2690 struct ddraw_surface *surface_impl; 2691 2692 TRACE("iface %p, dc %p, surface %p.\n", iface, dc, surface); 2693 2694 if (!surface) 2695 return E_INVALIDARG; 2696 2697 if (!dc) 2698 goto done; 2699 2700 wined3d_mutex_lock(); 2701 LIST_FOR_EACH_ENTRY(surface_impl, &ddraw->surface_list, struct ddraw_surface, surface_list_entry) 2702 { 2703 if (surface_impl->dc != dc) 2704 continue; 2705 2706 TRACE("Found surface %p for dc %p.\n", surface_impl, dc); 2707 *surface = &surface_impl->IDirectDrawSurface7_iface; 2708 IDirectDrawSurface7_AddRef(*surface); 2709 wined3d_mutex_unlock(); 2710 return DD_OK; 2711 } 2712 wined3d_mutex_unlock(); 2713 2714 done: 2715 TRACE("No surface found for dc %p.\n", dc); 2716 *surface = NULL; 2717 return DDERR_NOTFOUND; 2718 } 2719 2720 static HRESULT WINAPI ddraw4_GetSurfaceFromDC(IDirectDraw4 *iface, HDC dc, 2721 IDirectDrawSurface4 **surface) 2722 { 2723 struct ddraw *ddraw = impl_from_IDirectDraw4(iface); 2724 struct ddraw_surface *surface_impl; 2725 IDirectDrawSurface7 *surface7; 2726 HRESULT hr; 2727 2728 TRACE("iface %p, dc %p, surface %p.\n", iface, dc, surface); 2729 2730 if (!surface) return E_INVALIDARG; 2731 2732 hr = ddraw7_GetSurfaceFromDC(&ddraw->IDirectDraw7_iface, dc, &surface7); 2733 if (FAILED(hr)) 2734 { 2735 *surface = NULL; 2736 return hr; 2737 } 2738 surface_impl = impl_from_IDirectDrawSurface7(surface7); 2739 /* Tests say this is true */ 2740 *surface = (IDirectDrawSurface4 *)&surface_impl->IDirectDrawSurface_iface; 2741 IDirectDrawSurface_AddRef(&surface_impl->IDirectDrawSurface_iface); 2742 IDirectDrawSurface7_Release(surface7); 2743 2744 return hr; 2745 } 2746 2747 static HRESULT CALLBACK restore_callback(IDirectDrawSurface7 *surface, DDSURFACEDESC2 *desc, void *context) 2748 { 2749 IDirectDrawSurface_Restore(surface); 2750 IDirectDrawSurface_Release(surface); 2751 2752 return DDENUMRET_OK; 2753 } 2754 2755 static HRESULT WINAPI ddraw7_RestoreAllSurfaces(IDirectDraw7 *iface) 2756 { 2757 TRACE("iface %p.\n", iface); 2758 2759 return IDirectDraw7_EnumSurfaces(iface, DDENUMSURFACES_ALL | DDENUMSURFACES_DOESEXIST, 2760 NULL, NULL, restore_callback); 2761 } 2762 2763 static HRESULT WINAPI ddraw4_RestoreAllSurfaces(IDirectDraw4 *iface) 2764 { 2765 struct ddraw *ddraw = impl_from_IDirectDraw4(iface); 2766 2767 TRACE("iface %p.\n", iface); 2768 2769 return ddraw7_RestoreAllSurfaces(&ddraw->IDirectDraw7_iface); 2770 } 2771 2772 /***************************************************************************** 2773 * IDirectDraw7::StartModeTest 2774 * 2775 * Tests the specified video modes to update the system registry with 2776 * refresh rate information. StartModeTest starts the mode test, 2777 * EvaluateMode is used to fail or pass a mode. If EvaluateMode 2778 * isn't called within 15 seconds, the mode is failed automatically 2779 * 2780 * As refresh rates are handled by the X server, I don't think this 2781 * Method is important 2782 * 2783 * Params: 2784 * Modes: An array of mode specifications 2785 * NumModes: The number of modes in Modes 2786 * Flags: Some flags... 2787 * 2788 * Returns: 2789 * Returns DDERR_TESTFINISHED if flags contains DDSMT_ISTESTREQUIRED, 2790 * if no modes are passed, DDERR_INVALIDPARAMS is returned, 2791 * otherwise DD_OK 2792 * 2793 *****************************************************************************/ 2794 static HRESULT WINAPI ddraw7_StartModeTest(IDirectDraw7 *iface, SIZE *Modes, DWORD NumModes, DWORD Flags) 2795 { 2796 FIXME("iface %p, modes %p, mode_count %u, flags %#x partial stub!\n", 2797 iface, Modes, NumModes, Flags); 2798 2799 /* This looks sane */ 2800 if( (!Modes) || (NumModes == 0) ) return DDERR_INVALIDPARAMS; 2801 2802 /* DDSMT_ISTESTREQUIRED asks if a mode test is necessary. 2803 * As it is not, DDERR_TESTFINISHED is returned 2804 * (hopefully that's correct 2805 * 2806 if(Flags & DDSMT_ISTESTREQUIRED) return DDERR_TESTFINISHED; 2807 * well, that value doesn't (yet) exist in the wine headers, so ignore it 2808 */ 2809 2810 return DD_OK; 2811 } 2812 2813 static HRESULT WINAPI ddraw7_CreateSurface(IDirectDraw7 *iface, DDSURFACEDESC2 *surface_desc, 2814 IDirectDrawSurface7 **surface, IUnknown *outer_unknown) 2815 { 2816 struct ddraw *ddraw = impl_from_IDirectDraw7(iface); 2817 struct ddraw_surface *impl; 2818 HRESULT hr; 2819 2820 TRACE("iface %p, surface_desc %p, surface %p, outer_unknown %p.\n", 2821 iface, surface_desc, surface, outer_unknown); 2822 2823 wined3d_mutex_lock(); 2824 2825 if (!(ddraw->cooperative_level & (DDSCL_NORMAL | DDSCL_EXCLUSIVE))) 2826 { 2827 WARN("Cooperative level not set.\n"); 2828 wined3d_mutex_unlock(); 2829 return DDERR_NOCOOPERATIVELEVELSET; 2830 } 2831 2832 if(surface_desc == NULL || surface_desc->dwSize != sizeof(DDSURFACEDESC2)) 2833 { 2834 WARN("Application supplied invalid surface descriptor\n"); 2835 wined3d_mutex_unlock(); 2836 return DDERR_INVALIDPARAMS; 2837 } 2838 2839 __TRY 2840 { 2841 *surface = NULL; 2842 } 2843 __EXCEPT_PAGE_FAULT 2844 { 2845 WARN("Surface pointer %p is invalid.\n", surface); 2846 wined3d_mutex_unlock(); 2847 return DDERR_INVALIDPARAMS; 2848 } 2849 __ENDTRY; 2850 2851 if(surface_desc->ddsCaps.dwCaps & (DDSCAPS_FRONTBUFFER | DDSCAPS_BACKBUFFER)) 2852 { 2853 if (TRACE_ON(ddraw)) 2854 { 2855 TRACE(" (%p) Requesting surface desc :\n", iface); 2856 DDRAW_dump_surface_desc(surface_desc); 2857 } 2858 2859 WARN("Application tried to create an explicit front or back buffer\n"); 2860 wined3d_mutex_unlock(); 2861 return DDERR_INVALIDCAPS; 2862 } 2863 2864 hr = ddraw_surface_create(ddraw, surface_desc, &impl, outer_unknown, 7); 2865 wined3d_mutex_unlock(); 2866 if (FAILED(hr)) 2867 return hr; 2868 2869 *surface = &impl->IDirectDrawSurface7_iface; 2870 IDirectDraw7_AddRef(iface); 2871 impl->ifaceToRelease = (IUnknown *)iface; 2872 2873 return hr; 2874 } 2875 2876 static HRESULT WINAPI ddraw4_CreateSurface(IDirectDraw4 *iface, 2877 DDSURFACEDESC2 *surface_desc, IDirectDrawSurface4 **surface, IUnknown *outer_unknown) 2878 { 2879 struct ddraw *ddraw = impl_from_IDirectDraw4(iface); 2880 struct ddraw_surface *impl; 2881 HRESULT hr; 2882 2883 TRACE("iface %p, surface_desc %p, surface %p, outer_unknown %p.\n", 2884 iface, surface_desc, surface, outer_unknown); 2885 2886 wined3d_mutex_lock(); 2887 2888 if (!(ddraw->cooperative_level & (DDSCL_NORMAL | DDSCL_EXCLUSIVE))) 2889 { 2890 WARN("Cooperative level not set.\n"); 2891 wined3d_mutex_unlock(); 2892 return DDERR_NOCOOPERATIVELEVELSET; 2893 } 2894 2895 if(surface_desc == NULL || surface_desc->dwSize != sizeof(DDSURFACEDESC2)) 2896 { 2897 WARN("Application supplied invalid surface descriptor\n"); 2898 wined3d_mutex_unlock(); 2899 return DDERR_INVALIDPARAMS; 2900 } 2901 2902 __TRY 2903 { 2904 *surface = NULL; 2905 } 2906 __EXCEPT_PAGE_FAULT 2907 { 2908 WARN("Surface pointer %p is invalid.\n", surface); 2909 wined3d_mutex_unlock(); 2910 return DDERR_INVALIDPARAMS; 2911 } 2912 __ENDTRY; 2913 2914 if(surface_desc->ddsCaps.dwCaps & (DDSCAPS_FRONTBUFFER | DDSCAPS_BACKBUFFER)) 2915 { 2916 if (TRACE_ON(ddraw)) 2917 { 2918 TRACE(" (%p) Requesting surface desc :\n", iface); 2919 DDRAW_dump_surface_desc(surface_desc); 2920 } 2921 2922 WARN("Application tried to create an explicit front or back buffer\n"); 2923 wined3d_mutex_unlock(); 2924 return DDERR_INVALIDCAPS; 2925 } 2926 2927 hr = ddraw_surface_create(ddraw, surface_desc, &impl, outer_unknown, 4); 2928 wined3d_mutex_unlock(); 2929 if (FAILED(hr)) 2930 return hr; 2931 2932 *surface = &impl->IDirectDrawSurface4_iface; 2933 IDirectDraw4_AddRef(iface); 2934 impl->ifaceToRelease = (IUnknown *)iface; 2935 2936 return hr; 2937 } 2938 2939 static HRESULT WINAPI ddraw2_CreateSurface(IDirectDraw2 *iface, 2940 DDSURFACEDESC *surface_desc, IDirectDrawSurface **surface, IUnknown *outer_unknown) 2941 { 2942 struct ddraw *ddraw = impl_from_IDirectDraw2(iface); 2943 struct ddraw_surface *impl; 2944 HRESULT hr; 2945 DDSURFACEDESC2 surface_desc2; 2946 2947 TRACE("iface %p, surface_desc %p, surface %p, outer_unknown %p.\n", 2948 iface, surface_desc, surface, outer_unknown); 2949 2950 wined3d_mutex_lock(); 2951 2952 if (!(ddraw->cooperative_level & (DDSCL_NORMAL | DDSCL_EXCLUSIVE))) 2953 { 2954 WARN("Cooperative level not set.\n"); 2955 wined3d_mutex_unlock(); 2956 return DDERR_NOCOOPERATIVELEVELSET; 2957 } 2958 2959 if(surface_desc == NULL || surface_desc->dwSize != sizeof(DDSURFACEDESC)) 2960 { 2961 WARN("Application supplied invalid surface descriptor\n"); 2962 wined3d_mutex_unlock(); 2963 return DDERR_INVALIDPARAMS; 2964 } 2965 2966 __TRY 2967 { 2968 *surface = NULL; 2969 } 2970 __EXCEPT_PAGE_FAULT 2971 { 2972 WARN("Surface pointer %p is invalid.\n", surface); 2973 wined3d_mutex_unlock(); 2974 return DDERR_INVALIDPARAMS; 2975 } 2976 __ENDTRY; 2977 2978 DDSD_to_DDSD2(surface_desc, &surface_desc2); 2979 if(surface_desc->ddsCaps.dwCaps & (DDSCAPS_FRONTBUFFER | DDSCAPS_BACKBUFFER)) 2980 { 2981 if (TRACE_ON(ddraw)) 2982 { 2983 TRACE(" (%p) Requesting surface desc :\n", iface); 2984 DDRAW_dump_surface_desc((DDSURFACEDESC2 *)surface_desc); 2985 } 2986 2987 WARN("Application tried to create an explicit front or back buffer\n"); 2988 wined3d_mutex_unlock(); 2989 return DDERR_INVALIDCAPS; 2990 } 2991 2992 hr = ddraw_surface_create(ddraw, &surface_desc2, &impl, outer_unknown, 2); 2993 wined3d_mutex_unlock(); 2994 if (FAILED(hr)) 2995 return hr; 2996 2997 *surface = &impl->IDirectDrawSurface_iface; 2998 impl->ifaceToRelease = NULL; 2999 3000 return hr; 3001 } 3002 3003 static HRESULT WINAPI ddraw1_CreateSurface(IDirectDraw *iface, 3004 DDSURFACEDESC *surface_desc, IDirectDrawSurface **surface, IUnknown *outer_unknown) 3005 { 3006 struct ddraw *ddraw = impl_from_IDirectDraw(iface); 3007 struct ddraw_surface *impl; 3008 HRESULT hr; 3009 DDSURFACEDESC2 surface_desc2; 3010 3011 TRACE("iface %p, surface_desc %p, surface %p, outer_unknown %p.\n", 3012 iface, surface_desc, surface, outer_unknown); 3013 3014 wined3d_mutex_lock(); 3015 3016 if (!(ddraw->cooperative_level & (DDSCL_NORMAL | DDSCL_EXCLUSIVE))) 3017 { 3018 WARN("Cooperative level not set.\n"); 3019 wined3d_mutex_unlock(); 3020 return DDERR_NOCOOPERATIVELEVELSET; 3021 } 3022 3023 if(surface_desc == NULL || surface_desc->dwSize != sizeof(DDSURFACEDESC)) 3024 { 3025 WARN("Application supplied invalid surface descriptor\n"); 3026 wined3d_mutex_unlock(); 3027 return DDERR_INVALIDPARAMS; 3028 } 3029 3030 __TRY 3031 { 3032 *surface = NULL; 3033 } 3034 __EXCEPT_PAGE_FAULT 3035 { 3036 WARN("Surface pointer %p is invalid.\n", surface); 3037 wined3d_mutex_unlock(); 3038 return DDERR_INVALIDPARAMS; 3039 } 3040 __ENDTRY; 3041 3042 if ((surface_desc->ddsCaps.dwCaps & (DDSCAPS_PRIMARYSURFACE | DDSCAPS_BACKBUFFER)) 3043 == (DDSCAPS_PRIMARYSURFACE | DDSCAPS_BACKBUFFER) 3044 || (surface_desc->ddsCaps.dwCaps & (DDSCAPS_FLIP | DDSCAPS_FRONTBUFFER)) 3045 == ((DDSCAPS_FLIP | DDSCAPS_FRONTBUFFER))) 3046 { 3047 WARN("Application tried to create an explicit front or back buffer.\n"); 3048 wined3d_mutex_unlock(); 3049 return DDERR_INVALIDCAPS; 3050 } 3051 3052 DDSD_to_DDSD2(surface_desc, &surface_desc2); 3053 hr = ddraw_surface_create(ddraw, &surface_desc2, &impl, outer_unknown, 1); 3054 wined3d_mutex_unlock(); 3055 if (FAILED(hr)) 3056 return hr; 3057 3058 *surface = &impl->IDirectDrawSurface_iface; 3059 impl->ifaceToRelease = NULL; 3060 3061 return hr; 3062 } 3063 3064 static BOOL 3065 Main_DirectDraw_DDPIXELFORMAT_Match(const DDPIXELFORMAT *requested, 3066 const DDPIXELFORMAT *provided) 3067 { 3068 /* Some flags must be present in both or neither for a match. */ 3069 static const DWORD must_match = DDPF_PALETTEINDEXED1 | DDPF_PALETTEINDEXED2 3070 | DDPF_PALETTEINDEXED4 | DDPF_PALETTEINDEXED8 | DDPF_FOURCC 3071 | DDPF_ZBUFFER | DDPF_STENCILBUFFER; 3072 3073 if ((requested->dwFlags & provided->dwFlags) != requested->dwFlags) 3074 return FALSE; 3075 3076 if ((requested->dwFlags & must_match) != (provided->dwFlags & must_match)) 3077 return FALSE; 3078 3079 if (requested->dwFlags & DDPF_FOURCC) 3080 if (requested->dwFourCC != provided->dwFourCC) 3081 return FALSE; 3082 3083 if (requested->dwFlags & (DDPF_RGB|DDPF_YUV|DDPF_ZBUFFER|DDPF_ALPHA 3084 |DDPF_LUMINANCE|DDPF_BUMPDUDV)) 3085 if (requested->u1.dwRGBBitCount != provided->u1.dwRGBBitCount) 3086 return FALSE; 3087 3088 if (requested->dwFlags & (DDPF_RGB|DDPF_YUV|DDPF_STENCILBUFFER 3089 |DDPF_LUMINANCE|DDPF_BUMPDUDV)) 3090 if (requested->u2.dwRBitMask != provided->u2.dwRBitMask) 3091 return FALSE; 3092 3093 if (requested->dwFlags & (DDPF_RGB|DDPF_YUV|DDPF_ZBUFFER|DDPF_BUMPDUDV)) 3094 if (requested->u3.dwGBitMask != provided->u3.dwGBitMask) 3095 return FALSE; 3096 3097 /* I could be wrong about the bumpmapping. MSDN docs are vague. */ 3098 if (requested->dwFlags & (DDPF_RGB|DDPF_YUV|DDPF_STENCILBUFFER 3099 |DDPF_BUMPDUDV)) 3100 if (requested->u4.dwBBitMask != provided->u4.dwBBitMask) 3101 return FALSE; 3102 3103 if (requested->dwFlags & (DDPF_ALPHAPIXELS|DDPF_ZPIXELS)) 3104 if (requested->u5.dwRGBAlphaBitMask != provided->u5.dwRGBAlphaBitMask) 3105 return FALSE; 3106 3107 return TRUE; 3108 } 3109 3110 static BOOL ddraw_match_surface_desc(const DDSURFACEDESC2 *requested, const DDSURFACEDESC2 *provided) 3111 { 3112 struct compare_info 3113 { 3114 DWORD flag; 3115 ptrdiff_t offset; 3116 size_t size; 3117 }; 3118 3119 #define CMP(FLAG, FIELD) \ 3120 { DDSD_##FLAG, offsetof(DDSURFACEDESC2, FIELD), \ 3121 sizeof(((DDSURFACEDESC2 *)(NULL))->FIELD) } 3122 3123 static const struct compare_info compare[] = 3124 { 3125 CMP(ALPHABITDEPTH, dwAlphaBitDepth), 3126 CMP(BACKBUFFERCOUNT, u5.dwBackBufferCount), 3127 CMP(CAPS, ddsCaps), 3128 CMP(CKDESTBLT, ddckCKDestBlt), 3129 CMP(CKDESTOVERLAY, u3 /* ddckCKDestOverlay */), 3130 CMP(CKSRCBLT, ddckCKSrcBlt), 3131 CMP(CKSRCOVERLAY, ddckCKSrcOverlay), 3132 CMP(HEIGHT, dwHeight), 3133 CMP(LINEARSIZE, u1 /* dwLinearSize */), 3134 CMP(LPSURFACE, lpSurface), 3135 CMP(MIPMAPCOUNT, u2 /* dwMipMapCount */), 3136 CMP(PITCH, u1 /* lPitch */), 3137 /* PIXELFORMAT: manual */ 3138 CMP(REFRESHRATE, u2 /* dwRefreshRate */), 3139 CMP(TEXTURESTAGE, dwTextureStage), 3140 CMP(WIDTH, dwWidth), 3141 /* ZBUFFERBITDEPTH: "obsolete" */ 3142 }; 3143 3144 #undef CMP 3145 3146 unsigned int i; 3147 3148 if ((requested->dwFlags & provided->dwFlags) != requested->dwFlags) 3149 return FALSE; 3150 3151 for (i=0; i < ARRAY_SIZE(compare); i++) 3152 { 3153 if (requested->dwFlags & compare[i].flag 3154 && memcmp((const char *)provided + compare[i].offset, 3155 (const char *)requested + compare[i].offset, 3156 compare[i].size) != 0) 3157 return FALSE; 3158 } 3159 3160 if (requested->dwFlags & DDSD_PIXELFORMAT) 3161 { 3162 if (!Main_DirectDraw_DDPIXELFORMAT_Match(&requested->u4.ddpfPixelFormat, 3163 &provided->u4.ddpfPixelFormat)) 3164 return FALSE; 3165 } 3166 3167 return TRUE; 3168 } 3169 3170 struct surfacescallback2_context 3171 { 3172 LPDDENUMSURFACESCALLBACK2 func; 3173 void *context; 3174 }; 3175 3176 struct surfacescallback_context 3177 { 3178 LPDDENUMSURFACESCALLBACK func; 3179 void *context; 3180 }; 3181 3182 static HRESULT CALLBACK EnumSurfacesCallback2Thunk(IDirectDrawSurface7 *surface, 3183 DDSURFACEDESC2 *surface_desc, void *context) 3184 { 3185 struct ddraw_surface *surface_impl = impl_from_IDirectDrawSurface7(surface); 3186 struct surfacescallback2_context *cbcontext = context; 3187 3188 IDirectDrawSurface4_AddRef(&surface_impl->IDirectDrawSurface4_iface); 3189 IDirectDrawSurface7_Release(surface); 3190 3191 return cbcontext->func(&surface_impl->IDirectDrawSurface4_iface, 3192 surface_desc, cbcontext->context); 3193 } 3194 3195 static HRESULT CALLBACK EnumSurfacesCallbackThunk(IDirectDrawSurface7 *surface, 3196 DDSURFACEDESC2 *surface_desc, void *context) 3197 { 3198 struct ddraw_surface *surface_impl = impl_from_IDirectDrawSurface7(surface); 3199 struct surfacescallback_context *cbcontext = context; 3200 3201 IDirectDrawSurface_AddRef(&surface_impl->IDirectDrawSurface_iface); 3202 IDirectDrawSurface7_Release(surface); 3203 3204 return cbcontext->func(&surface_impl->IDirectDrawSurface_iface, 3205 (DDSURFACEDESC *)surface_desc, cbcontext->context); 3206 } 3207 3208 /***************************************************************************** 3209 * IDirectDraw7::EnumSurfaces 3210 * 3211 * Loops through all surfaces attached to this device and calls the 3212 * application callback. This can't be relayed to WineD3DDevice, 3213 * because some WineD3DSurfaces' parents are IParent objects 3214 * 3215 * Params: 3216 * Flags: Some filtering flags. See IDirectDrawImpl_EnumSurfacesCallback 3217 * DDSD: Description to filter for 3218 * Context: Application-provided pointer, it's passed unmodified to the 3219 * Callback function 3220 * Callback: Address to call for each surface 3221 * 3222 * Returns: 3223 * DDERR_INVALIDPARAMS if the callback is NULL 3224 * DD_OK on success 3225 * 3226 *****************************************************************************/ 3227 static HRESULT WINAPI ddraw7_EnumSurfaces(IDirectDraw7 *iface, DWORD Flags, 3228 DDSURFACEDESC2 *DDSD, void *Context, LPDDENUMSURFACESCALLBACK7 Callback) 3229 { 3230 struct ddraw *ddraw = impl_from_IDirectDraw7(iface); 3231 struct ddraw_surface *surf; 3232 DWORD match_flags = Flags & (DDENUMSURFACES_ALL | DDENUMSURFACES_NOMATCH | DDENUMSURFACES_MATCH); 3233 3234 TRACE("iface %p, flags %#x, surface_desc %p, context %p, callback %p.\n", 3235 iface, Flags, DDSD, Context, Callback); 3236 3237 if (!Callback) 3238 return DDERR_INVALIDPARAMS; 3239 3240 if (Flags & DDENUMSURFACES_CANBECREATED) 3241 { 3242 IDirectDrawSurface7 *surface; 3243 DDSURFACEDESC2 testdesc; 3244 HRESULT hr; 3245 3246 if (match_flags != DDENUMSURFACES_MATCH) 3247 return DDERR_INVALIDPARAMS; 3248 3249 if (!DDSD) 3250 return DDERR_INVALIDPARAMS; 3251 3252 memcpy(&testdesc, DDSD, sizeof(testdesc)); 3253 if (!(testdesc.dwFlags & DDSD_WIDTH)) 3254 { 3255 testdesc.dwFlags |= DDSD_WIDTH; 3256 testdesc.dwWidth = 512; 3257 } 3258 if (!(testdesc.dwFlags & DDSD_HEIGHT)) 3259 { 3260 testdesc.dwFlags |= DDSD_HEIGHT; 3261 testdesc.dwHeight = 512; 3262 } 3263 3264 hr = IDirectDraw7_CreateSurface(iface, &testdesc, &surface, NULL); 3265 if (SUCCEEDED(hr)) 3266 { 3267 surf = unsafe_impl_from_IDirectDrawSurface7(surface); 3268 Callback(NULL, &surf->surface_desc, Context); 3269 IDirectDrawSurface7_Release(surface); 3270 } 3271 else 3272 ERR("Failed to create surface, hr %#x.\n", hr); 3273 } 3274 else if (Flags & DDENUMSURFACES_DOESEXIST) 3275 { 3276 BOOL all, nomatch; 3277 DDSURFACEDESC2 desc; 3278 struct list *entry, *entry2; 3279 3280 /* a combination of match flags is not allowed */ 3281 if (match_flags != 0 && 3282 match_flags != DDENUMSURFACES_ALL && 3283 match_flags != DDENUMSURFACES_MATCH && 3284 match_flags != DDENUMSURFACES_NOMATCH) 3285 return DDERR_INVALIDPARAMS; 3286 3287 all = (Flags & DDENUMSURFACES_ALL) != 0; 3288 nomatch = (Flags & DDENUMSURFACES_NOMATCH) != 0; 3289 3290 if (!all && !DDSD) 3291 return DDERR_INVALIDPARAMS; 3292 3293 wined3d_mutex_lock(); 3294 3295 /* Use the _SAFE enumeration, the app may destroy enumerated surfaces */ 3296 LIST_FOR_EACH_SAFE(entry, entry2, &ddraw->surface_list) 3297 { 3298 surf = LIST_ENTRY(entry, struct ddraw_surface, surface_list_entry); 3299 3300 if (!surf->iface_count) 3301 { 3302 WARN("Not enumerating surface %p because it doesn't have any references.\n", surf); 3303 continue; 3304 } 3305 3306 if (all || (nomatch != ddraw_match_surface_desc(DDSD, &surf->surface_desc))) 3307 { 3308 TRACE("Enumerating surface %p.\n", surf); 3309 desc = surf->surface_desc; 3310 IDirectDrawSurface7_AddRef(&surf->IDirectDrawSurface7_iface); 3311 if (Callback(&surf->IDirectDrawSurface7_iface, &desc, Context) != DDENUMRET_OK) 3312 { 3313 wined3d_mutex_unlock(); 3314 return DD_OK; 3315 } 3316 } 3317 } 3318 3319 wined3d_mutex_unlock(); 3320 } 3321 else 3322 return DDERR_INVALIDPARAMS; 3323 3324 return DD_OK; 3325 } 3326 3327 static HRESULT WINAPI ddraw4_EnumSurfaces(IDirectDraw4 *iface, DWORD flags, 3328 DDSURFACEDESC2 *surface_desc, void *context, LPDDENUMSURFACESCALLBACK2 callback) 3329 { 3330 struct ddraw *ddraw = impl_from_IDirectDraw4(iface); 3331 struct surfacescallback2_context cbcontext; 3332 3333 TRACE("iface %p, flags %#x, surface_desc %p, context %p, callback %p.\n", 3334 iface, flags, surface_desc, context, callback); 3335 3336 cbcontext.func = callback; 3337 cbcontext.context = context; 3338 3339 return ddraw7_EnumSurfaces(&ddraw->IDirectDraw7_iface, flags, surface_desc, 3340 &cbcontext, EnumSurfacesCallback2Thunk); 3341 } 3342 3343 static HRESULT WINAPI ddraw2_EnumSurfaces(IDirectDraw2 *iface, DWORD flags, 3344 DDSURFACEDESC *surface_desc, void *context, LPDDENUMSURFACESCALLBACK callback) 3345 { 3346 struct ddraw *ddraw = impl_from_IDirectDraw2(iface); 3347 struct surfacescallback_context cbcontext; 3348 DDSURFACEDESC2 surface_desc2; 3349 3350 TRACE("iface %p, flags %#x, surface_desc %p, context %p, callback %p.\n", 3351 iface, flags, surface_desc, context, callback); 3352 3353 cbcontext.func = callback; 3354 cbcontext.context = context; 3355 3356 if (surface_desc) DDSD_to_DDSD2(surface_desc, &surface_desc2); 3357 return ddraw7_EnumSurfaces(&ddraw->IDirectDraw7_iface, flags, 3358 surface_desc ? &surface_desc2 : NULL, &cbcontext, EnumSurfacesCallbackThunk); 3359 } 3360 3361 static HRESULT WINAPI ddraw1_EnumSurfaces(IDirectDraw *iface, DWORD flags, 3362 DDSURFACEDESC *surface_desc, void *context, LPDDENUMSURFACESCALLBACK callback) 3363 { 3364 struct ddraw *ddraw = impl_from_IDirectDraw(iface); 3365 struct surfacescallback_context cbcontext; 3366 DDSURFACEDESC2 surface_desc2; 3367 3368 TRACE("iface %p, flags %#x, surface_desc %p, context %p, callback %p.\n", 3369 iface, flags, surface_desc, context, callback); 3370 3371 cbcontext.func = callback; 3372 cbcontext.context = context; 3373 3374 if (surface_desc) DDSD_to_DDSD2(surface_desc, &surface_desc2); 3375 return ddraw7_EnumSurfaces(&ddraw->IDirectDraw7_iface, flags, 3376 surface_desc ? &surface_desc2 : NULL, &cbcontext, EnumSurfacesCallbackThunk); 3377 } 3378 3379 /***************************************************************************** 3380 * DirectDrawCreateClipper (DDRAW.@) 3381 * 3382 * Creates a new IDirectDrawClipper object. 3383 * 3384 * Params: 3385 * Clipper: Address to write the interface pointer to 3386 * UnkOuter: For aggregation support, which ddraw doesn't have. Has to be 3387 * NULL 3388 * 3389 * Returns: 3390 * CLASS_E_NOAGGREGATION if UnkOuter != NULL 3391 * E_OUTOFMEMORY if allocating the object failed 3392 * 3393 *****************************************************************************/ 3394 HRESULT WINAPI DirectDrawCreateClipper(DWORD flags, IDirectDrawClipper **clipper, IUnknown *outer_unknown) 3395 { 3396 struct ddraw_clipper *object; 3397 HRESULT hr; 3398 3399 TRACE("flags %#x, clipper %p, outer_unknown %p.\n", 3400 flags, clipper, outer_unknown); 3401 3402 if (outer_unknown) 3403 return CLASS_E_NOAGGREGATION; 3404 3405 wined3d_mutex_lock(); 3406 3407 if (!(object = heap_alloc_zero(sizeof(*object)))) 3408 { 3409 wined3d_mutex_unlock(); 3410 return E_OUTOFMEMORY; 3411 } 3412 3413 hr = ddraw_clipper_init(object); 3414 if (FAILED(hr)) 3415 { 3416 WARN("Failed to initialize clipper, hr %#x.\n", hr); 3417 heap_free(object); 3418 wined3d_mutex_unlock(); 3419 return hr; 3420 } 3421 3422 TRACE("Created clipper %p.\n", object); 3423 *clipper = &object->IDirectDrawClipper_iface; 3424 wined3d_mutex_unlock(); 3425 3426 return DD_OK; 3427 } 3428 3429 /***************************************************************************** 3430 * IDirectDraw7::CreateClipper 3431 * 3432 * Creates a DDraw clipper. See DirectDrawCreateClipper for details 3433 * 3434 *****************************************************************************/ 3435 static HRESULT WINAPI ddraw7_CreateClipper(IDirectDraw7 *iface, DWORD Flags, 3436 IDirectDrawClipper **Clipper, IUnknown *UnkOuter) 3437 { 3438 TRACE("iface %p, flags %#x, clipper %p, outer_unknown %p.\n", 3439 iface, Flags, Clipper, UnkOuter); 3440 3441 return DirectDrawCreateClipper(Flags, Clipper, UnkOuter); 3442 } 3443 3444 static HRESULT WINAPI ddraw4_CreateClipper(IDirectDraw4 *iface, DWORD flags, 3445 IDirectDrawClipper **clipper, IUnknown *outer_unknown) 3446 { 3447 struct ddraw *ddraw = impl_from_IDirectDraw4(iface); 3448 3449 TRACE("iface %p, flags %#x, clipper %p, outer_unknown %p.\n", 3450 iface, flags, clipper, outer_unknown); 3451 3452 return ddraw7_CreateClipper(&ddraw->IDirectDraw7_iface, flags, clipper, outer_unknown); 3453 } 3454 3455 static HRESULT WINAPI ddraw2_CreateClipper(IDirectDraw2 *iface, 3456 DWORD flags, IDirectDrawClipper **clipper, IUnknown *outer_unknown) 3457 { 3458 struct ddraw *ddraw = impl_from_IDirectDraw2(iface); 3459 3460 TRACE("iface %p, flags %#x, clipper %p, outer_unknown %p.\n", 3461 iface, flags, clipper, outer_unknown); 3462 3463 return ddraw7_CreateClipper(&ddraw->IDirectDraw7_iface, flags, clipper, outer_unknown); 3464 } 3465 3466 static HRESULT WINAPI ddraw1_CreateClipper(IDirectDraw *iface, 3467 DWORD flags, IDirectDrawClipper **clipper, IUnknown *outer_unknown) 3468 { 3469 struct ddraw *ddraw = impl_from_IDirectDraw(iface); 3470 3471 TRACE("iface %p, flags %#x, clipper %p, outer_unknown %p.\n", 3472 iface, flags, clipper, outer_unknown); 3473 3474 return ddraw7_CreateClipper(&ddraw->IDirectDraw7_iface, flags, clipper, outer_unknown); 3475 } 3476 3477 /***************************************************************************** 3478 * IDirectDraw7::CreatePalette 3479 * 3480 * Creates a new IDirectDrawPalette object 3481 * 3482 * Params: 3483 * Flags: The flags for the new clipper 3484 * ColorTable: Color table to assign to the new clipper 3485 * Palette: Address to write the interface pointer to 3486 * UnkOuter: For aggregation support, which ddraw doesn't have. Has to be 3487 * NULL 3488 * 3489 * Returns: 3490 * CLASS_E_NOAGGREGATION if UnkOuter != NULL 3491 * E_OUTOFMEMORY if allocating the object failed 3492 * 3493 *****************************************************************************/ 3494 static HRESULT WINAPI ddraw7_CreatePalette(IDirectDraw7 *iface, DWORD Flags, 3495 PALETTEENTRY *ColorTable, IDirectDrawPalette **Palette, IUnknown *pUnkOuter) 3496 { 3497 struct ddraw *ddraw = impl_from_IDirectDraw7(iface); 3498 struct ddraw_palette *object; 3499 HRESULT hr; 3500 3501 TRACE("iface %p, flags %#x, color_table %p, palette %p, outer_unknown %p.\n", 3502 iface, Flags, ColorTable, Palette, pUnkOuter); 3503 3504 if (pUnkOuter) 3505 return CLASS_E_NOAGGREGATION; 3506 3507 wined3d_mutex_lock(); 3508 3509 /* The refcount test shows that a cooplevel is required for this */ 3510 if (!ddraw->cooperative_level) 3511 { 3512 WARN("No cooperative level set, returning DDERR_NOCOOPERATIVELEVELSET\n"); 3513 wined3d_mutex_unlock(); 3514 return DDERR_NOCOOPERATIVELEVELSET; 3515 } 3516 3517 if (!(object = heap_alloc(sizeof(*object)))) 3518 { 3519 ERR("Out of memory when allocating memory for a palette implementation\n"); 3520 wined3d_mutex_unlock(); 3521 return E_OUTOFMEMORY; 3522 } 3523 3524 hr = ddraw_palette_init(object, ddraw, Flags, ColorTable); 3525 if (FAILED(hr)) 3526 { 3527 WARN("Failed to initialize palette, hr %#x.\n", hr); 3528 heap_free(object); 3529 wined3d_mutex_unlock(); 3530 return hr; 3531 } 3532 3533 TRACE("Created palette %p.\n", object); 3534 *Palette = &object->IDirectDrawPalette_iface; 3535 wined3d_mutex_unlock(); 3536 3537 return DD_OK; 3538 } 3539 3540 static HRESULT WINAPI ddraw4_CreatePalette(IDirectDraw4 *iface, DWORD flags, PALETTEENTRY *entries, 3541 IDirectDrawPalette **palette, IUnknown *outer_unknown) 3542 { 3543 struct ddraw *ddraw = impl_from_IDirectDraw4(iface); 3544 HRESULT hr; 3545 3546 TRACE("iface %p, flags %#x, entries %p, palette %p, outer_unknown %p.\n", 3547 iface, flags, entries, palette, outer_unknown); 3548 3549 hr = ddraw7_CreatePalette(&ddraw->IDirectDraw7_iface, flags, entries, palette, outer_unknown); 3550 if (SUCCEEDED(hr) && *palette) 3551 { 3552 struct ddraw_palette *impl = impl_from_IDirectDrawPalette(*palette); 3553 IDirectDraw7_Release(&ddraw->IDirectDraw7_iface); 3554 IDirectDraw4_AddRef(iface); 3555 impl->ifaceToRelease = (IUnknown *)iface; 3556 } 3557 return hr; 3558 } 3559 3560 static HRESULT WINAPI ddraw2_CreatePalette(IDirectDraw2 *iface, DWORD flags, 3561 PALETTEENTRY *entries, IDirectDrawPalette **palette, IUnknown *outer_unknown) 3562 { 3563 struct ddraw *ddraw = impl_from_IDirectDraw2(iface); 3564 HRESULT hr; 3565 3566 TRACE("iface %p, flags %#x, entries %p, palette %p, outer_unknown %p.\n", 3567 iface, flags, entries, palette, outer_unknown); 3568 3569 hr = ddraw7_CreatePalette(&ddraw->IDirectDraw7_iface, flags, entries, palette, outer_unknown); 3570 if (SUCCEEDED(hr) && *palette) 3571 { 3572 struct ddraw_palette *impl = impl_from_IDirectDrawPalette(*palette); 3573 IDirectDraw7_Release(&ddraw->IDirectDraw7_iface); 3574 impl->ifaceToRelease = NULL; 3575 } 3576 3577 return hr; 3578 } 3579 3580 static HRESULT WINAPI ddraw1_CreatePalette(IDirectDraw *iface, DWORD flags, 3581 PALETTEENTRY *entries, IDirectDrawPalette **palette, IUnknown *outer_unknown) 3582 { 3583 struct ddraw *ddraw = impl_from_IDirectDraw(iface); 3584 HRESULT hr; 3585 3586 TRACE("iface %p, flags %#x, entries %p, palette %p, outer_unknown %p.\n", 3587 iface, flags, entries, palette, outer_unknown); 3588 3589 hr = ddraw7_CreatePalette(&ddraw->IDirectDraw7_iface, flags, entries, palette, outer_unknown); 3590 if (SUCCEEDED(hr) && *palette) 3591 { 3592 struct ddraw_palette *impl = impl_from_IDirectDrawPalette(*palette); 3593 IDirectDraw7_Release(&ddraw->IDirectDraw7_iface); 3594 impl->ifaceToRelease = NULL; 3595 } 3596 3597 return hr; 3598 } 3599 3600 /***************************************************************************** 3601 * IDirectDraw7::DuplicateSurface 3602 * 3603 * Duplicates a surface. The surface memory points to the same memory as 3604 * the original surface, and it's released when the last surface referencing 3605 * it is released. I guess that's beyond Wine's surface management right now 3606 * (Idea: create a new DDraw surface with the same WineD3DSurface. I need a 3607 * test application to implement this) 3608 * 3609 * Params: 3610 * Src: Address of the source surface 3611 * Dest: Address to write the new surface pointer to 3612 * 3613 * Returns: 3614 * See IDirectDraw7::CreateSurface 3615 * 3616 *****************************************************************************/ 3617 static HRESULT WINAPI ddraw7_DuplicateSurface(IDirectDraw7 *iface, 3618 IDirectDrawSurface7 *Src, IDirectDrawSurface7 **Dest) 3619 { 3620 struct ddraw_surface *src_surface = unsafe_impl_from_IDirectDrawSurface7(Src); 3621 3622 FIXME("iface %p, src %p, dst %p partial stub!\n", iface, Src, Dest); 3623 3624 /* For now, simply create a new, independent surface */ 3625 return IDirectDraw7_CreateSurface(iface, &src_surface->surface_desc, Dest, NULL); 3626 } 3627 3628 static HRESULT WINAPI ddraw4_DuplicateSurface(IDirectDraw4 *iface, IDirectDrawSurface4 *src, 3629 IDirectDrawSurface4 **dst) 3630 { 3631 struct ddraw_surface *src_impl = unsafe_impl_from_IDirectDrawSurface4(src); 3632 struct ddraw *ddraw = impl_from_IDirectDraw4(iface); 3633 struct ddraw_surface *dst_impl; 3634 IDirectDrawSurface7 *dst7; 3635 HRESULT hr; 3636 3637 TRACE("iface %p, src %p, dst %p.\n", iface, src, dst); 3638 3639 hr = ddraw7_DuplicateSurface(&ddraw->IDirectDraw7_iface, 3640 src_impl ? &src_impl->IDirectDrawSurface7_iface : NULL, &dst7); 3641 if (FAILED(hr)) 3642 { 3643 *dst = NULL; 3644 return hr; 3645 } 3646 dst_impl = impl_from_IDirectDrawSurface7(dst7); 3647 *dst = &dst_impl->IDirectDrawSurface4_iface; 3648 IDirectDrawSurface4_AddRef(*dst); 3649 IDirectDrawSurface7_Release(dst7); 3650 3651 return hr; 3652 } 3653 3654 static HRESULT WINAPI ddraw2_DuplicateSurface(IDirectDraw2 *iface, 3655 IDirectDrawSurface *src, IDirectDrawSurface **dst) 3656 { 3657 struct ddraw_surface *src_impl = unsafe_impl_from_IDirectDrawSurface(src); 3658 struct ddraw *ddraw = impl_from_IDirectDraw2(iface); 3659 struct ddraw_surface *dst_impl; 3660 IDirectDrawSurface7 *dst7; 3661 HRESULT hr; 3662 3663 TRACE("iface %p, src %p, dst %p.\n", iface, src, dst); 3664 3665 hr = ddraw7_DuplicateSurface(&ddraw->IDirectDraw7_iface, 3666 src_impl ? &src_impl->IDirectDrawSurface7_iface : NULL, &dst7); 3667 if (FAILED(hr)) 3668 return hr; 3669 dst_impl = impl_from_IDirectDrawSurface7(dst7); 3670 *dst = &dst_impl->IDirectDrawSurface_iface; 3671 IDirectDrawSurface_AddRef(*dst); 3672 IDirectDrawSurface7_Release(dst7); 3673 3674 return hr; 3675 } 3676 3677 static HRESULT WINAPI ddraw1_DuplicateSurface(IDirectDraw *iface, IDirectDrawSurface *src, 3678 IDirectDrawSurface **dst) 3679 { 3680 struct ddraw_surface *src_impl = unsafe_impl_from_IDirectDrawSurface(src); 3681 struct ddraw *ddraw = impl_from_IDirectDraw(iface); 3682 struct ddraw_surface *dst_impl; 3683 IDirectDrawSurface7 *dst7; 3684 HRESULT hr; 3685 3686 TRACE("iface %p, src %p, dst %p.\n", iface, src, dst); 3687 3688 hr = ddraw7_DuplicateSurface(&ddraw->IDirectDraw7_iface, 3689 src_impl ? &src_impl->IDirectDrawSurface7_iface : NULL, &dst7); 3690 if (FAILED(hr)) 3691 return hr; 3692 dst_impl = impl_from_IDirectDrawSurface7(dst7); 3693 *dst = &dst_impl->IDirectDrawSurface_iface; 3694 IDirectDrawSurface_AddRef(*dst); 3695 IDirectDrawSurface7_Release(dst7); 3696 3697 return hr; 3698 } 3699 3700 /***************************************************************************** 3701 * IDirect3D7::EnumDevices 3702 * 3703 * The EnumDevices method for IDirect3D7. It enumerates all supported 3704 * D3D7 devices. Currently the T&L, HAL and RGB devices are enumerated. 3705 * 3706 * Params: 3707 * callback: Function to call for each enumerated device 3708 * context: Pointer to pass back to the app 3709 * 3710 * Returns: 3711 * D3D_OK, or the return value of the GetCaps call 3712 * 3713 *****************************************************************************/ 3714 static HRESULT WINAPI d3d7_EnumDevices(IDirect3D7 *iface, LPD3DENUMDEVICESCALLBACK7 callback, void *context) 3715 { 3716 struct ddraw *ddraw = impl_from_IDirect3D7(iface); 3717 D3DDEVICEDESC7 device_desc7; 3718 DWORD dev_caps; 3719 HRESULT hr; 3720 size_t i; 3721 3722 TRACE("iface %p, callback %p, context %p.\n", iface, callback, context); 3723 3724 if (!callback) 3725 return DDERR_INVALIDPARAMS; 3726 3727 wined3d_mutex_lock(); 3728 3729 if (FAILED(hr = ddraw_get_d3dcaps(ddraw, &device_desc7))) 3730 { 3731 wined3d_mutex_unlock(); 3732 return hr; 3733 } 3734 3735 dev_caps = device_desc7.dwDevCaps; 3736 3737 for (i = 0; i < ARRAY_SIZE(device_list7); i++) 3738 { 3739 HRESULT ret; 3740 3741 device_desc7.deviceGUID = *device_list7[i].device_guid; 3742 device_desc7.dwDevCaps = dev_caps & ~device_list7[i].remove_caps; 3743 3744 ret = callback(device_list7[i].interface_name, device_list7[i].device_name, &device_desc7, context); 3745 if (ret != DDENUMRET_OK) 3746 { 3747 TRACE("Application cancelled the enumeration.\n"); 3748 wined3d_mutex_unlock(); 3749 return D3D_OK; 3750 } 3751 } 3752 3753 TRACE("End of enumeration.\n"); 3754 3755 wined3d_mutex_unlock(); 3756 3757 return D3D_OK; 3758 } 3759 3760 /***************************************************************************** 3761 * IDirect3D3::EnumDevices 3762 * 3763 * Enumerates all supported Direct3DDevice interfaces. This is the 3764 * implementation for Direct3D 1 to Direc3D 3, Version 7 has its own. 3765 * 3766 * Versions 1, 2 and 3 3767 * 3768 * Params: 3769 * callback: Application-provided routine to call for each enumerated device 3770 * Context: Pointer to pass to the callback 3771 * 3772 * Returns: 3773 * D3D_OK on success, 3774 * The result of IDirect3DImpl_GetCaps if it failed 3775 * 3776 *****************************************************************************/ 3777 static HRESULT WINAPI d3d3_EnumDevices(IDirect3D3 *iface, LPD3DENUMDEVICESCALLBACK callback, void *context) 3778 { 3779 static CHAR wined3d_description[] = "Wine D3DDevice using WineD3D and OpenGL"; 3780 3781 struct ddraw *ddraw = impl_from_IDirect3D3(iface); 3782 D3DDEVICEDESC device_desc1, hal_desc, hel_desc; 3783 D3DDEVICEDESC7 device_desc7; 3784 HRESULT hr; 3785 3786 /* Some games (Motoracer 2 demo) have the bad idea to modify the device 3787 * name string. Let's put the string in a sufficiently sized array in 3788 * writable memory. */ 3789 char device_name[50]; 3790 strcpy(device_name,"Direct3D HEL"); 3791 3792 TRACE("iface %p, callback %p, context %p.\n", iface, callback, context); 3793 3794 if (!callback) 3795 return DDERR_INVALIDPARAMS; 3796 3797 wined3d_mutex_lock(); 3798 3799 if (FAILED(hr = ddraw_get_d3dcaps(ddraw, &device_desc7))) 3800 { 3801 wined3d_mutex_unlock(); 3802 return hr; 3803 } 3804 ddraw_d3dcaps1_from_7(&device_desc1, &device_desc7); 3805 3806 /* Do I have to enumerate the reference id? Note from old d3d7: 3807 * "It seems that enumerating the reference IID on Direct3D 1 games 3808 * (AvP / Motoracer2) breaks them". So do not enumerate this iid in V1 3809 * 3810 * There's a registry key HKLM\Software\Microsoft\Direct3D\Drivers, 3811 * EnumReference which enables / disables enumerating the reference 3812 * rasterizer. It's a DWORD, 0 means disabled, 2 means enabled. The 3813 * enablerefrast.reg and disablerefrast.reg files in the DirectX 7.0 sdk 3814 * demo directory suggest this. 3815 * 3816 * Some games(GTA 2) seem to use the second enumerated device, so I have 3817 * to enumerate at least 2 devices. So enumerate the reference device to 3818 * have 2 devices. 3819 * 3820 * Other games (Rollcage) tell emulation and hal device apart by certain 3821 * flags. Rollcage expects D3DPTEXTURECAPS_POW2 to be set (yeah, it is a 3822 * limitation flag), and it refuses all devices that have the perspective 3823 * flag set. This way it refuses the emulation device, and HAL devices 3824 * never have POW2 unset in d3d7 on windows. */ 3825 if (ddraw->d3dversion != 1) 3826 { 3827 static CHAR reference_description[] = "RGB Direct3D emulation"; 3828 3829 TRACE("Enumerating WineD3D D3DDevice interface.\n"); 3830 hal_desc = device_desc1; 3831 hel_desc = device_desc1; 3832 /* The rgb device has the pow2 flag set in the hel caps, but not in the hal caps. */ 3833 hal_desc.dpcLineCaps.dwTextureCaps &= ~(D3DPTEXTURECAPS_POW2 3834 | D3DPTEXTURECAPS_NONPOW2CONDITIONAL | D3DPTEXTURECAPS_PERSPECTIVE); 3835 hal_desc.dpcTriCaps.dwTextureCaps &= ~(D3DPTEXTURECAPS_POW2 3836 | D3DPTEXTURECAPS_NONPOW2CONDITIONAL | D3DPTEXTURECAPS_PERSPECTIVE); 3837 /* RGB, RAMP and MMX devices have a HAL dcmColorModel of 0 */ 3838 hal_desc.dcmColorModel = 0; 3839 /* RGB, RAMP and MMX devices cannot report HAL hardware flags */ 3840 hal_desc.dwFlags = 0; 3841 3842 hr = callback((GUID *)&IID_IDirect3DRGBDevice, reference_description, 3843 device_name, &hal_desc, &hel_desc, context); 3844 if (hr != D3DENUMRET_OK) 3845 { 3846 TRACE("Application cancelled the enumeration.\n"); 3847 wined3d_mutex_unlock(); 3848 return D3D_OK; 3849 } 3850 } 3851 3852 strcpy(device_name,"Direct3D HAL"); 3853 3854 TRACE("Enumerating HAL Direct3D device.\n"); 3855 hal_desc = device_desc1; 3856 hel_desc = device_desc1; 3857 3858 /* The hal device does not have the pow2 flag set in hel, but in hal. */ 3859 hel_desc.dpcLineCaps.dwTextureCaps &= ~(D3DPTEXTURECAPS_POW2 3860 | D3DPTEXTURECAPS_NONPOW2CONDITIONAL | D3DPTEXTURECAPS_PERSPECTIVE); 3861 hel_desc.dpcTriCaps.dwTextureCaps &= ~(D3DPTEXTURECAPS_POW2 3862 | D3DPTEXTURECAPS_NONPOW2CONDITIONAL | D3DPTEXTURECAPS_PERSPECTIVE); 3863 /* HAL devices have a HEL dcmColorModel of 0 */ 3864 hel_desc.dcmColorModel = 0; 3865 3866 hr = callback((GUID *)&IID_IDirect3DHALDevice, wined3d_description, 3867 device_name, &hal_desc, &hel_desc, context); 3868 if (hr != D3DENUMRET_OK) 3869 { 3870 TRACE("Application cancelled the enumeration.\n"); 3871 wined3d_mutex_unlock(); 3872 return D3D_OK; 3873 } 3874 3875 TRACE("End of enumeration.\n"); 3876 3877 wined3d_mutex_unlock(); 3878 3879 return D3D_OK; 3880 } 3881 3882 static HRESULT WINAPI d3d2_EnumDevices(IDirect3D2 *iface, LPD3DENUMDEVICESCALLBACK callback, void *context) 3883 { 3884 struct ddraw *ddraw = impl_from_IDirect3D2(iface); 3885 3886 TRACE("iface %p, callback %p, context %p.\n", iface, callback, context); 3887 3888 return d3d3_EnumDevices(&ddraw->IDirect3D3_iface, callback, context); 3889 } 3890 3891 static HRESULT WINAPI d3d1_EnumDevices(IDirect3D *iface, LPD3DENUMDEVICESCALLBACK callback, void *context) 3892 { 3893 struct ddraw *ddraw = impl_from_IDirect3D(iface); 3894 3895 TRACE("iface %p, callback %p, context %p.\n", iface, callback, context); 3896 3897 return d3d3_EnumDevices(&ddraw->IDirect3D3_iface, callback, context); 3898 } 3899 3900 /***************************************************************************** 3901 * IDirect3D3::CreateLight 3902 * 3903 * Creates an IDirect3DLight interface. This interface is used in 3904 * Direct3D3 or earlier for lighting. In Direct3D7 it has been replaced 3905 * by the DIRECT3DLIGHT7 structure. Wine's Direct3DLight implementation 3906 * uses the IDirect3DDevice7 interface with D3D7 lights. 3907 * 3908 * Versions 1, 2 and 3 3909 * 3910 * Params: 3911 * light: Address to store the new interface pointer 3912 * outer_unknown: Basically for aggregation, but ddraw doesn't support it. 3913 * Must be NULL 3914 * 3915 * Returns: 3916 * D3D_OK on success 3917 * DDERR_OUTOFMEMORY if memory allocation failed 3918 * CLASS_E_NOAGGREGATION if outer_unknown != NULL 3919 * 3920 *****************************************************************************/ 3921 static HRESULT WINAPI d3d3_CreateLight(IDirect3D3 *iface, IDirect3DLight **light, 3922 IUnknown *outer_unknown) 3923 { 3924 struct ddraw *ddraw = impl_from_IDirect3D3(iface); 3925 struct d3d_light *object; 3926 3927 TRACE("iface %p, light %p, outer_unknown %p.\n", iface, light, outer_unknown); 3928 3929 if (outer_unknown) 3930 return CLASS_E_NOAGGREGATION; 3931 3932 if (!(object = heap_alloc_zero(sizeof(*object)))) 3933 { 3934 ERR("Failed to allocate light memory.\n"); 3935 return DDERR_OUTOFMEMORY; 3936 } 3937 3938 d3d_light_init(object, ddraw); 3939 3940 TRACE("Created light %p.\n", object); 3941 *light = &object->IDirect3DLight_iface; 3942 3943 return D3D_OK; 3944 } 3945 3946 static HRESULT WINAPI d3d2_CreateLight(IDirect3D2 *iface, IDirect3DLight **light, IUnknown *outer_unknown) 3947 { 3948 struct ddraw *ddraw = impl_from_IDirect3D2(iface); 3949 3950 TRACE("iface %p, light %p, outer_unknown %p.\n", iface, light, outer_unknown); 3951 3952 return d3d3_CreateLight(&ddraw->IDirect3D3_iface, light, outer_unknown); 3953 } 3954 3955 static HRESULT WINAPI d3d1_CreateLight(IDirect3D *iface, IDirect3DLight **light, IUnknown *outer_unknown) 3956 { 3957 struct ddraw *ddraw = impl_from_IDirect3D(iface); 3958 3959 TRACE("iface %p, light %p, outer_unknown %p.\n", iface, light, outer_unknown); 3960 3961 return d3d3_CreateLight(&ddraw->IDirect3D3_iface, light, outer_unknown); 3962 } 3963 3964 /***************************************************************************** 3965 * IDirect3D3::CreateMaterial 3966 * 3967 * Creates an IDirect3DMaterial interface. This interface is used by Direct3D3 3968 * and older versions. The IDirect3DMaterial implementation wraps its 3969 * functionality to IDirect3DDevice7::SetMaterial and friends. 3970 * 3971 * Versions 1, 2 and 3 3972 * 3973 * Params: 3974 * material: Address to store the new interface's pointer to 3975 * outer_unknown: Basically for aggregation, but ddraw doesn't support it. 3976 * Must be NULL 3977 * 3978 * Returns: 3979 * D3D_OK on success 3980 * DDERR_OUTOFMEMORY if memory allocation failed 3981 * CLASS_E_NOAGGREGATION if outer_unknown != NULL 3982 * 3983 *****************************************************************************/ 3984 static HRESULT WINAPI d3d3_CreateMaterial(IDirect3D3 *iface, IDirect3DMaterial3 **material, 3985 IUnknown *outer_unknown) 3986 { 3987 struct ddraw *ddraw = impl_from_IDirect3D3(iface); 3988 struct d3d_material *object; 3989 3990 TRACE("iface %p, material %p, outer_unknown %p.\n", iface, material, outer_unknown); 3991 3992 if (outer_unknown) return CLASS_E_NOAGGREGATION; 3993 3994 object = d3d_material_create(ddraw); 3995 if (!object) 3996 { 3997 ERR("Failed to allocate material memory.\n"); 3998 return DDERR_OUTOFMEMORY; 3999 } 4000 4001 TRACE("Created material %p.\n", object); 4002 *material = &object->IDirect3DMaterial3_iface; 4003 4004 return D3D_OK; 4005 } 4006 4007 static HRESULT WINAPI d3d2_CreateMaterial(IDirect3D2 *iface, IDirect3DMaterial2 **material, 4008 IUnknown *outer_unknown) 4009 { 4010 struct ddraw *ddraw = impl_from_IDirect3D2(iface); 4011 struct d3d_material *object; 4012 4013 TRACE("iface %p, material %p, outer_unknown %p.\n", iface, material, outer_unknown); 4014 4015 object = d3d_material_create(ddraw); 4016 if (!object) 4017 { 4018 ERR("Failed to allocate material memory.\n"); 4019 return DDERR_OUTOFMEMORY; 4020 } 4021 4022 TRACE("Created material %p.\n", object); 4023 *material = &object->IDirect3DMaterial2_iface; 4024 4025 return D3D_OK; 4026 } 4027 4028 static HRESULT WINAPI d3d1_CreateMaterial(IDirect3D *iface, IDirect3DMaterial **material, 4029 IUnknown *outer_unknown) 4030 { 4031 struct ddraw *ddraw = impl_from_IDirect3D(iface); 4032 struct d3d_material *object; 4033 4034 TRACE("iface %p, material %p, outer_unknown %p.\n", iface, material, outer_unknown); 4035 4036 object = d3d_material_create(ddraw); 4037 if (!object) 4038 { 4039 ERR("Failed to allocate material memory.\n"); 4040 return DDERR_OUTOFMEMORY; 4041 } 4042 4043 TRACE("Created material %p.\n", object); 4044 *material = &object->IDirect3DMaterial_iface; 4045 4046 return D3D_OK; 4047 } 4048 4049 /***************************************************************************** 4050 * IDirect3D3::CreateViewport 4051 * 4052 * Creates an IDirect3DViewport interface. This interface is used 4053 * by Direct3D and earlier versions for Viewport management. In Direct3D7 4054 * it has been replaced by a viewport structure and 4055 * IDirect3DDevice7::*Viewport. Wine's IDirect3DViewport implementation 4056 * uses the IDirect3DDevice7 methods for its functionality 4057 * 4058 * Params: 4059 * Viewport: Address to store the new interface pointer 4060 * outer_unknown: Basically for aggregation, but ddraw doesn't support it. 4061 * Must be NULL 4062 * 4063 * Returns: 4064 * D3D_OK on success 4065 * DDERR_OUTOFMEMORY if memory allocation failed 4066 * CLASS_E_NOAGGREGATION if outer_unknown != NULL 4067 * 4068 *****************************************************************************/ 4069 static HRESULT WINAPI d3d3_CreateViewport(IDirect3D3 *iface, IDirect3DViewport3 **viewport, 4070 IUnknown *outer_unknown) 4071 { 4072 struct ddraw *ddraw = impl_from_IDirect3D3(iface); 4073 struct d3d_viewport *object; 4074 4075 TRACE("iface %p, viewport %p, outer_unknown %p.\n", iface, viewport, outer_unknown); 4076 4077 if (outer_unknown) return CLASS_E_NOAGGREGATION; 4078 4079 if (!(object = heap_alloc_zero(sizeof(*object)))) 4080 { 4081 ERR("Failed to allocate viewport memory.\n"); 4082 return DDERR_OUTOFMEMORY; 4083 } 4084 4085 d3d_viewport_init(object, ddraw); 4086 4087 TRACE("Created viewport %p.\n", object); 4088 *viewport = &object->IDirect3DViewport3_iface; 4089 4090 return D3D_OK; 4091 } 4092 4093 static HRESULT WINAPI d3d2_CreateViewport(IDirect3D2 *iface, IDirect3DViewport2 **viewport, IUnknown *outer_unknown) 4094 { 4095 struct ddraw *ddraw = impl_from_IDirect3D2(iface); 4096 4097 TRACE("iface %p, viewport %p, outer_unknown %p.\n", iface, viewport, outer_unknown); 4098 4099 return d3d3_CreateViewport(&ddraw->IDirect3D3_iface, (IDirect3DViewport3 **)viewport, 4100 outer_unknown); 4101 } 4102 4103 static HRESULT WINAPI d3d1_CreateViewport(IDirect3D *iface, IDirect3DViewport **viewport, IUnknown *outer_unknown) 4104 { 4105 struct ddraw *ddraw = impl_from_IDirect3D(iface); 4106 4107 TRACE("iface %p, viewport %p, outer_unknown %p.\n", iface, viewport, outer_unknown); 4108 4109 return d3d3_CreateViewport(&ddraw->IDirect3D3_iface, (IDirect3DViewport3 **)viewport, 4110 outer_unknown); 4111 } 4112 4113 /***************************************************************************** 4114 * IDirect3D3::FindDevice 4115 * 4116 * This method finds a device with the requested properties and returns a 4117 * device description 4118 * 4119 * Versions 1, 2 and 3 4120 * Params: 4121 * fds: Describes the requested device characteristics 4122 * fdr: Returns the device description 4123 * 4124 * Returns: 4125 * D3D_OK on success 4126 * DDERR_INVALIDPARAMS if no device was found 4127 * 4128 *****************************************************************************/ 4129 static HRESULT WINAPI d3d3_FindDevice(IDirect3D3 *iface, D3DFINDDEVICESEARCH *fds, D3DFINDDEVICERESULT *fdr) 4130 { 4131 struct ddraw *ddraw = impl_from_IDirect3D3(iface); 4132 D3DDEVICEDESC7 desc7; 4133 D3DDEVICEDESC desc1; 4134 HRESULT hr; 4135 4136 TRACE("iface %p, fds %p, fdr %p.\n", iface, fds, fdr); 4137 4138 if (!fds || !fdr) return DDERR_INVALIDPARAMS; 4139 4140 if (fds->dwSize != sizeof(D3DFINDDEVICESEARCH) || (fdr->dwSize != sizeof(D3DFINDDEVICERESULT1) && 4141 fdr->dwSize != sizeof(D3DFINDDEVICERESULT2) && fdr->dwSize != sizeof(D3DFINDDEVICERESULT))) 4142 return DDERR_INVALIDPARAMS; 4143 4144 if ((fds->dwFlags & D3DFDS_COLORMODEL) 4145 && fds->dcmColorModel != D3DCOLOR_RGB) 4146 { 4147 WARN("Trying to request a non-RGB D3D color model. Not supported.\n"); 4148 return DDERR_INVALIDPARAMS; /* No real idea what to return here :-) */ 4149 } 4150 4151 if (fds->dwFlags & D3DFDS_GUID) 4152 { 4153 TRACE("Trying to match guid %s.\n", debugstr_guid(&(fds->guid))); 4154 if (!IsEqualGUID(&IID_D3DDEVICE_WineD3D, &fds->guid) 4155 && !IsEqualGUID(&IID_IDirect3DHALDevice, &fds->guid) 4156 && !IsEqualGUID(&IID_IDirect3DRGBDevice, &fds->guid)) 4157 { 4158 WARN("No match for this GUID.\n"); 4159 return DDERR_NOTFOUND; 4160 } 4161 } 4162 4163 /* Get the caps */ 4164 if (FAILED(hr = ddraw_get_d3dcaps(ddraw, &desc7))) 4165 return hr; 4166 4167 /* Now return our own GUID */ 4168 ddraw_d3dcaps1_from_7(&desc1, &desc7); 4169 fdr->guid = IID_D3DDEVICE_WineD3D; 4170 4171 if (fdr->dwSize == sizeof(D3DFINDDEVICERESULT1)) 4172 { 4173 D3DFINDDEVICERESULT1 *fdr1 = (D3DFINDDEVICERESULT1 *)fdr; 4174 memcpy(&fdr1->ddHwDesc, &desc1, sizeof(fdr1->ddHwDesc)); 4175 memcpy(&fdr1->ddSwDesc, &desc1, sizeof(fdr1->ddSwDesc)); 4176 } 4177 else if (fdr->dwSize == sizeof(D3DFINDDEVICERESULT2)) 4178 { 4179 D3DFINDDEVICERESULT2 *fdr2 = (D3DFINDDEVICERESULT2 *)fdr; 4180 memcpy(&fdr2->ddHwDesc, &desc1, sizeof(fdr2->ddHwDesc)); 4181 memcpy(&fdr2->ddSwDesc, &desc1, sizeof(fdr2->ddSwDesc)); 4182 } 4183 else 4184 { 4185 fdr->ddHwDesc = desc1; 4186 fdr->ddSwDesc = desc1; 4187 } 4188 4189 TRACE("Returning Wine's wined3d device with (undumped) capabilities.\n"); 4190 4191 return D3D_OK; 4192 } 4193 4194 static HRESULT WINAPI d3d2_FindDevice(IDirect3D2 *iface, D3DFINDDEVICESEARCH *fds, D3DFINDDEVICERESULT *fdr) 4195 { 4196 struct ddraw *ddraw = impl_from_IDirect3D2(iface); 4197 4198 TRACE("iface %p, fds %p, fdr %p.\n", iface, fds, fdr); 4199 4200 return d3d3_FindDevice(&ddraw->IDirect3D3_iface, fds, fdr); 4201 } 4202 4203 static HRESULT WINAPI d3d1_FindDevice(IDirect3D *iface, D3DFINDDEVICESEARCH *fds, D3DFINDDEVICERESULT *fdr) 4204 { 4205 struct ddraw *ddraw = impl_from_IDirect3D(iface); 4206 4207 TRACE("iface %p, fds %p, fdr %p.\n", iface, fds, fdr); 4208 4209 return d3d3_FindDevice(&ddraw->IDirect3D3_iface, fds, fdr); 4210 } 4211 4212 /***************************************************************************** 4213 * IDirect3D7::CreateDevice 4214 * 4215 * Creates an IDirect3DDevice7 interface. 4216 * 4217 * Versions 2, 3 and 7. IDirect3DDevice 1 interfaces are interfaces to 4218 * DirectDraw surfaces and are created with 4219 * IDirectDrawSurface::QueryInterface. This method uses CreateDevice to 4220 * create the device object and QueryInterfaces for IDirect3DDevice 4221 * 4222 * Params: 4223 * refiid: IID of the device to create 4224 * Surface: Initial rendertarget 4225 * Device: Address to return the interface pointer 4226 * 4227 * Returns: 4228 * D3D_OK on success 4229 * DDERR_OUTOFMEMORY if memory allocation failed 4230 * DDERR_INVALIDPARAMS if a device exists already 4231 * 4232 *****************************************************************************/ 4233 static HRESULT WINAPI d3d7_CreateDevice(IDirect3D7 *iface, REFCLSID riid, 4234 IDirectDrawSurface7 *surface, IDirect3DDevice7 **device) 4235 { 4236 struct ddraw_surface *target = unsafe_impl_from_IDirectDrawSurface7(surface); 4237 struct ddraw *ddraw = impl_from_IDirect3D7(iface); 4238 struct d3d_device *object; 4239 HRESULT hr; 4240 4241 TRACE("iface %p, riid %s, surface %p, device %p.\n", iface, debugstr_guid(riid), surface, device); 4242 4243 wined3d_mutex_lock(); 4244 if (SUCCEEDED(hr = d3d_device_create(ddraw, riid, target, (IUnknown *)surface, 7, &object, NULL))) 4245 { 4246 *device = &object->IDirect3DDevice7_iface; 4247 } 4248 else 4249 { 4250 WARN("Failed to create device, hr %#x.\n", hr); 4251 *device = NULL; 4252 } 4253 wined3d_mutex_unlock(); 4254 4255 return hr; 4256 } 4257 4258 static HRESULT WINAPI d3d3_CreateDevice(IDirect3D3 *iface, REFCLSID riid, 4259 IDirectDrawSurface4 *surface, IDirect3DDevice3 **device, IUnknown *outer_unknown) 4260 { 4261 struct ddraw_surface *surface_impl = unsafe_impl_from_IDirectDrawSurface4(surface); 4262 struct ddraw *ddraw = impl_from_IDirect3D3(iface); 4263 struct d3d_device *device_impl; 4264 HRESULT hr; 4265 4266 TRACE("iface %p, riid %s, surface %p, device %p, outer_unknown %p.\n", 4267 iface, debugstr_guid(riid), surface, device, outer_unknown); 4268 4269 if (outer_unknown) 4270 return CLASS_E_NOAGGREGATION; 4271 4272 wined3d_mutex_lock(); 4273 if (SUCCEEDED(hr = d3d_device_create(ddraw, riid, surface_impl, (IUnknown *)surface, 3, &device_impl, NULL))) 4274 { 4275 *device = &device_impl->IDirect3DDevice3_iface; 4276 } 4277 else 4278 { 4279 WARN("Failed to create device, hr %#x.\n", hr); 4280 *device = NULL; 4281 } 4282 wined3d_mutex_unlock(); 4283 4284 return hr; 4285 } 4286 4287 static HRESULT WINAPI d3d2_CreateDevice(IDirect3D2 *iface, REFCLSID riid, 4288 IDirectDrawSurface *surface, IDirect3DDevice2 **device) 4289 { 4290 struct ddraw_surface *surface_impl = unsafe_impl_from_IDirectDrawSurface(surface); 4291 struct ddraw *ddraw = impl_from_IDirect3D2(iface); 4292 struct d3d_device *device_impl; 4293 HRESULT hr; 4294 4295 TRACE("iface %p, riid %s, surface %p, device %p.\n", 4296 iface, debugstr_guid(riid), surface, device); 4297 4298 wined3d_mutex_lock(); 4299 if (SUCCEEDED(hr = d3d_device_create(ddraw, riid, surface_impl, (IUnknown *)surface, 2, &device_impl, NULL))) 4300 { 4301 *device = &device_impl->IDirect3DDevice2_iface; 4302 } 4303 else 4304 { 4305 WARN("Failed to create device, hr %#x.\n", hr); 4306 *device = NULL; 4307 } 4308 wined3d_mutex_unlock(); 4309 4310 return hr; 4311 } 4312 4313 /***************************************************************************** 4314 * IDirect3D7::CreateVertexBuffer 4315 * 4316 * Creates a new vertex buffer object and returns a IDirect3DVertexBuffer7 4317 * interface. 4318 * 4319 * Versions 3 and 7 4320 * 4321 * Params: 4322 * desc: Requested Vertex buffer properties 4323 * vertex_buffer: Address to return the interface pointer at 4324 * flags: Some flags, should be 0 4325 * 4326 * Returns 4327 * D3D_OK on success 4328 * DDERR_OUTOFMEMORY if memory allocation failed 4329 * DDERR_INVALIDPARAMS if desc or vertex_buffer is NULL 4330 * 4331 *****************************************************************************/ 4332 static HRESULT WINAPI d3d7_CreateVertexBuffer(IDirect3D7 *iface, D3DVERTEXBUFFERDESC *desc, 4333 IDirect3DVertexBuffer7 **vertex_buffer, DWORD flags) 4334 { 4335 struct ddraw *ddraw = impl_from_IDirect3D7(iface); 4336 struct d3d_vertex_buffer *object; 4337 HRESULT hr; 4338 4339 TRACE("iface %p, desc %p, vertex_buffer %p, flags %#x.\n", 4340 iface, desc, vertex_buffer, flags); 4341 4342 if (!vertex_buffer || !desc) return DDERR_INVALIDPARAMS; 4343 4344 hr = d3d_vertex_buffer_create(&object, ddraw, desc); 4345 if (hr == D3D_OK) 4346 { 4347 TRACE("Created vertex buffer %p.\n", object); 4348 *vertex_buffer = &object->IDirect3DVertexBuffer7_iface; 4349 } 4350 else 4351 WARN("Failed to create vertex buffer, hr %#x.\n", hr); 4352 4353 return hr; 4354 } 4355 4356 static HRESULT WINAPI d3d3_CreateVertexBuffer(IDirect3D3 *iface, D3DVERTEXBUFFERDESC *desc, 4357 IDirect3DVertexBuffer **vertex_buffer, DWORD flags, IUnknown *outer_unknown) 4358 { 4359 struct ddraw *ddraw = impl_from_IDirect3D3(iface); 4360 struct d3d_vertex_buffer *object; 4361 HRESULT hr; 4362 4363 TRACE("iface %p, desc %p, vertex_buffer %p, flags %#x, outer_unknown %p.\n", 4364 iface, desc, vertex_buffer, flags, outer_unknown); 4365 4366 if (outer_unknown) 4367 return CLASS_E_NOAGGREGATION; 4368 if (!vertex_buffer || !desc) 4369 return DDERR_INVALIDPARAMS; 4370 4371 hr = d3d_vertex_buffer_create(&object, ddraw, desc); 4372 if (hr == D3D_OK) 4373 { 4374 TRACE("Created vertex buffer %p.\n", object); 4375 *vertex_buffer = (IDirect3DVertexBuffer *)&object->IDirect3DVertexBuffer7_iface; 4376 } 4377 else 4378 WARN("Failed to create vertex buffer, hr %#x.\n", hr); 4379 4380 return hr; 4381 } 4382 4383 /***************************************************************************** 4384 * IDirect3D7::EnumZBufferFormats 4385 * 4386 * Enumerates all supported Z buffer pixel formats 4387 * 4388 * Versions 3 and 7 4389 * 4390 * Params: 4391 * device_iid: 4392 * callback: callback to call for each pixel format 4393 * context: Pointer to pass back to the callback 4394 * 4395 * Returns: 4396 * D3D_OK on success 4397 * DDERR_INVALIDPARAMS if callback is NULL 4398 * 4399 *****************************************************************************/ 4400 static HRESULT WINAPI d3d7_EnumZBufferFormats(IDirect3D7 *iface, REFCLSID device_iid, 4401 LPD3DENUMPIXELFORMATSCALLBACK callback, void *context) 4402 { 4403 struct ddraw *ddraw = impl_from_IDirect3D7(iface); 4404 struct wined3d_display_mode mode; 4405 enum wined3d_device_type type; 4406 unsigned int i; 4407 HRESULT hr; 4408 4409 /* Order matters. Specifically, BattleZone II (full version) expects the 4410 * 16-bit depth formats to be listed before the 24 and 32 ones. */ 4411 static const enum wined3d_format_id formats[] = 4412 { 4413 WINED3DFMT_S1_UINT_D15_UNORM, 4414 WINED3DFMT_D16_UNORM, 4415 WINED3DFMT_X8D24_UNORM, 4416 WINED3DFMT_S4X4_UINT_D24_UNORM, 4417 WINED3DFMT_D24_UNORM_S8_UINT, 4418 WINED3DFMT_D32_UNORM, 4419 }; 4420 4421 TRACE("iface %p, device_iid %s, callback %p, context %p.\n", 4422 iface, debugstr_guid(device_iid), callback, context); 4423 4424 if (!callback) return DDERR_INVALIDPARAMS; 4425 4426 if (IsEqualGUID(device_iid, &IID_IDirect3DHALDevice) 4427 || IsEqualGUID(device_iid, &IID_IDirect3DTnLHalDevice) 4428 || IsEqualGUID(device_iid, &IID_D3DDEVICE_WineD3D)) 4429 { 4430 TRACE("Asked for HAL device.\n"); 4431 type = WINED3D_DEVICE_TYPE_HAL; 4432 } 4433 else if (IsEqualGUID(device_iid, &IID_IDirect3DRGBDevice) 4434 || IsEqualGUID(device_iid, &IID_IDirect3DMMXDevice)) 4435 { 4436 TRACE("Asked for SW device.\n"); 4437 type = WINED3D_DEVICE_TYPE_SW; 4438 } 4439 else if (IsEqualGUID(device_iid, &IID_IDirect3DRefDevice)) 4440 { 4441 TRACE("Asked for REF device.\n"); 4442 type = WINED3D_DEVICE_TYPE_REF; 4443 } 4444 else if (IsEqualGUID(device_iid, &IID_IDirect3DNullDevice)) 4445 { 4446 TRACE("Asked for NULLREF device.\n"); 4447 type = WINED3D_DEVICE_TYPE_NULLREF; 4448 } 4449 else 4450 { 4451 FIXME("Unexpected device GUID %s.\n", debugstr_guid(device_iid)); 4452 type = WINED3D_DEVICE_TYPE_HAL; 4453 } 4454 4455 wined3d_mutex_lock(); 4456 /* We need an adapter format from somewhere to please wined3d and WGL. 4457 * Use the current display mode. So far all cards offer the same depth 4458 * stencil format for all modes, but if some do not and applications do 4459 * not like that we'll have to find some workaround, like iterating over 4460 * all imaginable formats and collecting all the depth stencil formats we 4461 * can get. */ 4462 if (FAILED(hr = wined3d_get_adapter_display_mode(ddraw->wined3d, WINED3DADAPTER_DEFAULT, &mode, NULL))) 4463 { 4464 ERR("Failed to get display mode, hr %#x.\n", hr); 4465 wined3d_mutex_unlock(); 4466 return hr; 4467 } 4468 4469 for (i = 0; i < ARRAY_SIZE(formats); ++i) 4470 { 4471 if (SUCCEEDED(wined3d_check_device_format(ddraw->wined3d, WINED3DADAPTER_DEFAULT, type, mode.format_id, 4472 WINED3DUSAGE_DEPTHSTENCIL, WINED3D_RTYPE_TEXTURE_2D, formats[i]))) 4473 { 4474 DDPIXELFORMAT pformat; 4475 4476 memset(&pformat, 0, sizeof(pformat)); 4477 pformat.dwSize = sizeof(pformat); 4478 ddrawformat_from_wined3dformat(&pformat, formats[i]); 4479 4480 TRACE("Enumerating wined3d format %#x.\n", formats[i]); 4481 hr = callback(&pformat, context); 4482 if (hr != DDENUMRET_OK) 4483 { 4484 TRACE("Format enumeration cancelled by application.\n"); 4485 wined3d_mutex_unlock(); 4486 return D3D_OK; 4487 } 4488 } 4489 } 4490 4491 /* Historically some windows drivers used dwZBufferBitDepth=24 for WINED3DFMT_X8D24_UNORM, 4492 * while others used dwZBufferBitDepth=32. In either case the pitch matches a 32 bits per 4493 * pixel format, so we use dwZBufferBitDepth=32. Some games expect 24. Windows Vista and 4494 * newer enumerate both versions, so we do the same(bug 22434) */ 4495 if (SUCCEEDED(wined3d_check_device_format(ddraw->wined3d, WINED3DADAPTER_DEFAULT, type, mode.format_id, 4496 WINED3DUSAGE_DEPTHSTENCIL, WINED3D_RTYPE_TEXTURE_2D, WINED3DFMT_X8D24_UNORM))) 4497 { 4498 DDPIXELFORMAT x8d24 = 4499 { 4500 sizeof(x8d24), DDPF_ZBUFFER, 0, 4501 {24}, {0x00000000}, {0x00ffffff}, {0x00000000} 4502 }; 4503 TRACE("Enumerating WINED3DFMT_X8D24_UNORM, dwZBufferBitDepth=24 version\n"); 4504 callback(&x8d24, context); 4505 } 4506 4507 TRACE("End of enumeration.\n"); 4508 4509 wined3d_mutex_unlock(); 4510 4511 return D3D_OK; 4512 } 4513 4514 static HRESULT WINAPI d3d3_EnumZBufferFormats(IDirect3D3 *iface, REFCLSID device_iid, 4515 LPD3DENUMPIXELFORMATSCALLBACK callback, void *context) 4516 { 4517 struct ddraw *ddraw = impl_from_IDirect3D3(iface); 4518 4519 TRACE("iface %p, device_iid %s, callback %p, context %p.\n", 4520 iface, debugstr_guid(device_iid), callback, context); 4521 4522 return d3d7_EnumZBufferFormats(&ddraw->IDirect3D7_iface, device_iid, callback, context); 4523 } 4524 4525 /***************************************************************************** 4526 * IDirect3D7::EvictManagedTextures 4527 * 4528 * Removes all managed textures (=surfaces with DDSCAPS2_TEXTUREMANAGE or 4529 * DDSCAPS2_D3DTEXTUREMANAGE caps) to be removed from video memory. 4530 * 4531 * Versions 3 and 7 4532 * 4533 * Returns: 4534 * D3D_OK, because it's a stub 4535 * 4536 *****************************************************************************/ 4537 static HRESULT WINAPI d3d7_EvictManagedTextures(IDirect3D7 *iface) 4538 { 4539 struct ddraw *ddraw = impl_from_IDirect3D7(iface); 4540 4541 TRACE("iface %p!\n", iface); 4542 4543 wined3d_mutex_lock(); 4544 if (ddraw->flags & DDRAW_D3D_INITIALIZED) 4545 wined3d_device_evict_managed_resources(ddraw->wined3d_device); 4546 wined3d_mutex_unlock(); 4547 4548 return D3D_OK; 4549 } 4550 4551 static HRESULT WINAPI d3d3_EvictManagedTextures(IDirect3D3 *iface) 4552 { 4553 struct ddraw *ddraw = impl_from_IDirect3D3(iface); 4554 4555 TRACE("iface %p.\n", iface); 4556 4557 return d3d7_EvictManagedTextures(&ddraw->IDirect3D7_iface); 4558 } 4559 4560 /***************************************************************************** 4561 * IDirectDraw7 VTable 4562 *****************************************************************************/ 4563 static const struct IDirectDraw7Vtbl ddraw7_vtbl = 4564 { 4565 /* IUnknown */ 4566 ddraw7_QueryInterface, 4567 ddraw7_AddRef, 4568 ddraw7_Release, 4569 /* IDirectDraw */ 4570 ddraw7_Compact, 4571 ddraw7_CreateClipper, 4572 ddraw7_CreatePalette, 4573 ddraw7_CreateSurface, 4574 ddraw7_DuplicateSurface, 4575 ddraw7_EnumDisplayModes, 4576 ddraw7_EnumSurfaces, 4577 ddraw7_FlipToGDISurface, 4578 ddraw7_GetCaps, 4579 ddraw7_GetDisplayMode, 4580 ddraw7_GetFourCCCodes, 4581 ddraw7_GetGDISurface, 4582 ddraw7_GetMonitorFrequency, 4583 ddraw7_GetScanLine, 4584 ddraw7_GetVerticalBlankStatus, 4585 ddraw7_Initialize, 4586 ddraw7_RestoreDisplayMode, 4587 ddraw7_SetCooperativeLevel, 4588 ddraw7_SetDisplayMode, 4589 ddraw7_WaitForVerticalBlank, 4590 /* IDirectDraw2 */ 4591 ddraw7_GetAvailableVidMem, 4592 /* IDirectDraw3 */ 4593 ddraw7_GetSurfaceFromDC, 4594 /* IDirectDraw4 */ 4595 ddraw7_RestoreAllSurfaces, 4596 ddraw7_TestCooperativeLevel, 4597 ddraw7_GetDeviceIdentifier, 4598 /* IDirectDraw7 */ 4599 ddraw7_StartModeTest, 4600 ddraw7_EvaluateMode 4601 }; 4602 4603 static const struct IDirectDraw4Vtbl ddraw4_vtbl = 4604 { 4605 /* IUnknown */ 4606 ddraw4_QueryInterface, 4607 ddraw4_AddRef, 4608 ddraw4_Release, 4609 /* IDirectDraw */ 4610 ddraw4_Compact, 4611 ddraw4_CreateClipper, 4612 ddraw4_CreatePalette, 4613 ddraw4_CreateSurface, 4614 ddraw4_DuplicateSurface, 4615 ddraw4_EnumDisplayModes, 4616 ddraw4_EnumSurfaces, 4617 ddraw4_FlipToGDISurface, 4618 ddraw4_GetCaps, 4619 ddraw4_GetDisplayMode, 4620 ddraw4_GetFourCCCodes, 4621 ddraw4_GetGDISurface, 4622 ddraw4_GetMonitorFrequency, 4623 ddraw4_GetScanLine, 4624 ddraw4_GetVerticalBlankStatus, 4625 ddraw4_Initialize, 4626 ddraw4_RestoreDisplayMode, 4627 ddraw4_SetCooperativeLevel, 4628 ddraw4_SetDisplayMode, 4629 ddraw4_WaitForVerticalBlank, 4630 /* IDirectDraw2 */ 4631 ddraw4_GetAvailableVidMem, 4632 /* IDirectDraw3 */ 4633 ddraw4_GetSurfaceFromDC, 4634 /* IDirectDraw4 */ 4635 ddraw4_RestoreAllSurfaces, 4636 ddraw4_TestCooperativeLevel, 4637 ddraw4_GetDeviceIdentifier, 4638 }; 4639 4640 static const struct IDirectDraw2Vtbl ddraw2_vtbl = 4641 { 4642 /* IUnknown */ 4643 ddraw2_QueryInterface, 4644 ddraw2_AddRef, 4645 ddraw2_Release, 4646 /* IDirectDraw */ 4647 ddraw2_Compact, 4648 ddraw2_CreateClipper, 4649 ddraw2_CreatePalette, 4650 ddraw2_CreateSurface, 4651 ddraw2_DuplicateSurface, 4652 ddraw2_EnumDisplayModes, 4653 ddraw2_EnumSurfaces, 4654 ddraw2_FlipToGDISurface, 4655 ddraw2_GetCaps, 4656 ddraw2_GetDisplayMode, 4657 ddraw2_GetFourCCCodes, 4658 ddraw2_GetGDISurface, 4659 ddraw2_GetMonitorFrequency, 4660 ddraw2_GetScanLine, 4661 ddraw2_GetVerticalBlankStatus, 4662 ddraw2_Initialize, 4663 ddraw2_RestoreDisplayMode, 4664 ddraw2_SetCooperativeLevel, 4665 ddraw2_SetDisplayMode, 4666 ddraw2_WaitForVerticalBlank, 4667 /* IDirectDraw2 */ 4668 ddraw2_GetAvailableVidMem, 4669 }; 4670 4671 static struct IDirectDrawVtbl ddraw1_vtbl = 4672 { 4673 /* IUnknown */ 4674 ddraw1_QueryInterface, 4675 ddraw1_AddRef, 4676 ddraw1_Release, 4677 /* IDirectDraw */ 4678 ddraw1_Compact, 4679 ddraw1_CreateClipper, 4680 ddraw1_CreatePalette, 4681 ddraw1_CreateSurface, 4682 ddraw1_DuplicateSurface, 4683 ddraw1_EnumDisplayModes, 4684 ddraw1_EnumSurfaces, 4685 ddraw1_FlipToGDISurface, 4686 ddraw1_GetCaps, 4687 ddraw1_GetDisplayMode, 4688 ddraw1_GetFourCCCodes, 4689 ddraw1_GetGDISurface, 4690 ddraw1_GetMonitorFrequency, 4691 ddraw1_GetScanLine, 4692 ddraw1_GetVerticalBlankStatus, 4693 ddraw1_Initialize, 4694 ddraw1_RestoreDisplayMode, 4695 ddraw1_SetCooperativeLevel, 4696 ddraw1_SetDisplayMode, 4697 ddraw1_WaitForVerticalBlank, 4698 }; 4699 4700 static const struct IDirect3D7Vtbl d3d7_vtbl = 4701 { 4702 /* IUnknown methods */ 4703 d3d7_QueryInterface, 4704 d3d7_AddRef, 4705 d3d7_Release, 4706 /* IDirect3D7 methods */ 4707 d3d7_EnumDevices, 4708 d3d7_CreateDevice, 4709 d3d7_CreateVertexBuffer, 4710 d3d7_EnumZBufferFormats, 4711 d3d7_EvictManagedTextures 4712 }; 4713 4714 static const struct IDirect3D3Vtbl d3d3_vtbl = 4715 { 4716 /* IUnknown methods */ 4717 d3d3_QueryInterface, 4718 d3d3_AddRef, 4719 d3d3_Release, 4720 /* IDirect3D3 methods */ 4721 d3d3_EnumDevices, 4722 d3d3_CreateLight, 4723 d3d3_CreateMaterial, 4724 d3d3_CreateViewport, 4725 d3d3_FindDevice, 4726 d3d3_CreateDevice, 4727 d3d3_CreateVertexBuffer, 4728 d3d3_EnumZBufferFormats, 4729 d3d3_EvictManagedTextures 4730 }; 4731 4732 static const struct IDirect3D2Vtbl d3d2_vtbl = 4733 { 4734 /* IUnknown methods */ 4735 d3d2_QueryInterface, 4736 d3d2_AddRef, 4737 d3d2_Release, 4738 /* IDirect3D2 methods */ 4739 d3d2_EnumDevices, 4740 d3d2_CreateLight, 4741 d3d2_CreateMaterial, 4742 d3d2_CreateViewport, 4743 d3d2_FindDevice, 4744 d3d2_CreateDevice 4745 }; 4746 4747 static const struct IDirect3DVtbl d3d1_vtbl = 4748 { 4749 /* IUnknown methods */ 4750 d3d1_QueryInterface, 4751 d3d1_AddRef, 4752 d3d1_Release, 4753 /* IDirect3D methods */ 4754 d3d1_Initialize, 4755 d3d1_EnumDevices, 4756 d3d1_CreateLight, 4757 d3d1_CreateMaterial, 4758 d3d1_CreateViewport, 4759 d3d1_FindDevice 4760 }; 4761 4762 /***************************************************************************** 4763 * ddraw_find_decl 4764 * 4765 * Finds the WineD3D vertex declaration for a specific fvf, and creates one 4766 * if none was found. 4767 * 4768 * This function is in ddraw.c and the DDraw object space because D3D7 4769 * vertex buffers are created using the IDirect3D interface to the ddraw 4770 * object, so they can be valid across D3D devices(theoretically. The ddraw 4771 * object also owns the wined3d device 4772 * 4773 * Parameters: 4774 * This: Device 4775 * fvf: Fvf to find the decl for 4776 * 4777 * Returns: 4778 * NULL in case of an error, the vertex declaration for the FVF otherwise. 4779 * 4780 *****************************************************************************/ 4781 struct wined3d_vertex_declaration *ddraw_find_decl(struct ddraw *This, DWORD fvf) 4782 { 4783 struct wined3d_vertex_declaration *pDecl = NULL; 4784 HRESULT hr; 4785 int p, low, high; /* deliberately signed */ 4786 struct FvfToDecl *convertedDecls = This->decls; 4787 4788 TRACE("Searching for declaration for fvf %08x... ", fvf); 4789 4790 low = 0; 4791 high = This->numConvertedDecls - 1; 4792 while(low <= high) { 4793 p = (low + high) >> 1; 4794 TRACE("%d ", p); 4795 if(convertedDecls[p].fvf == fvf) { 4796 TRACE("found %p\n", convertedDecls[p].decl); 4797 return convertedDecls[p].decl; 4798 } else if(convertedDecls[p].fvf < fvf) { 4799 low = p + 1; 4800 } else { 4801 high = p - 1; 4802 } 4803 } 4804 TRACE("not found. Creating and inserting at position %d.\n", low); 4805 4806 hr = wined3d_vertex_declaration_create_from_fvf(This->wined3d_device, 4807 fvf, This, &ddraw_null_wined3d_parent_ops, &pDecl); 4808 if (hr != S_OK) return NULL; 4809 4810 if (This->declArraySize == This->numConvertedDecls) 4811 { 4812 unsigned int grow = max(This->declArraySize / 2, 8); 4813 4814 if (!(convertedDecls = heap_realloc(convertedDecls, 4815 (This->numConvertedDecls + grow) * sizeof(*convertedDecls)))) 4816 { 4817 wined3d_vertex_declaration_decref(pDecl); 4818 return NULL; 4819 } 4820 This->decls = convertedDecls; 4821 This->declArraySize += grow; 4822 } 4823 4824 memmove(convertedDecls + low + 1, convertedDecls + low, sizeof(convertedDecls[0]) * (This->numConvertedDecls - low)); 4825 convertedDecls[low].decl = pDecl; 4826 convertedDecls[low].fvf = fvf; 4827 This->numConvertedDecls++; 4828 4829 TRACE("Returning %p. %d decls in array\n", pDecl, This->numConvertedDecls); 4830 return pDecl; 4831 } 4832 4833 static inline struct ddraw *ddraw_from_device_parent(struct wined3d_device_parent *device_parent) 4834 { 4835 return CONTAINING_RECORD(device_parent, struct ddraw, device_parent); 4836 } 4837 4838 static void CDECL device_parent_wined3d_device_created(struct wined3d_device_parent *device_parent, 4839 struct wined3d_device *device) 4840 { 4841 TRACE("device_parent %p, device %p.\n", device_parent, device); 4842 } 4843 4844 /* This is run from device_process_message() in wined3d, we can't take the 4845 * wined3d mutex. */ 4846 /* FIXME: We only get mode change notifications in exclusive mode, but we 4847 * should mark surfaces as lost on mode changes in DDSCL_NORMAL mode as well. */ 4848 static void CDECL device_parent_mode_changed(struct wined3d_device_parent *device_parent) 4849 { 4850 struct ddraw *ddraw = ddraw_from_device_parent(device_parent); 4851 MONITORINFO monitor_info; 4852 HMONITOR monitor; 4853 RECT *r; 4854 4855 TRACE("device_parent %p.\n", device_parent); 4856 4857 if (!(ddraw->cooperative_level & DDSCL_EXCLUSIVE) || !ddraw->swapchain_window) 4858 { 4859 TRACE("Nothing to resize.\n"); 4860 return; 4861 } 4862 4863 monitor = MonitorFromWindow(ddraw->swapchain_window, MONITOR_DEFAULTTOPRIMARY); 4864 monitor_info.cbSize = sizeof(monitor_info); 4865 if (!GetMonitorInfoW(monitor, &monitor_info)) 4866 { 4867 ERR("Failed to get monitor info.\n"); 4868 return; 4869 } 4870 4871 r = &monitor_info.rcMonitor; 4872 TRACE("Resizing window %p to %s.\n", ddraw->swapchain_window, wine_dbgstr_rect(r)); 4873 4874 if (!SetWindowPos(ddraw->swapchain_window, HWND_TOP, r->left, r->top, 4875 r->right - r->left, r->bottom - r->top, SWP_SHOWWINDOW | SWP_NOACTIVATE)) 4876 ERR("Failed to resize window.\n"); 4877 4878 InterlockedCompareExchange(&ddraw->device_state, DDRAW_DEVICE_STATE_NOT_RESTORED, DDRAW_DEVICE_STATE_OK); 4879 } 4880 4881 static void CDECL device_parent_activate(struct wined3d_device_parent *device_parent, BOOL activate) 4882 { 4883 struct ddraw *ddraw = ddraw_from_device_parent(device_parent); 4884 4885 TRACE("device_parent %p, activate %#x.\n", device_parent, activate); 4886 4887 if (!activate) 4888 { 4889 ddraw->device_state = DDRAW_DEVICE_STATE_LOST; 4890 exclusive_window = NULL; 4891 } 4892 else 4893 { 4894 InterlockedCompareExchange(&ddraw->device_state, DDRAW_DEVICE_STATE_NOT_RESTORED, DDRAW_DEVICE_STATE_LOST); 4895 } 4896 } 4897 4898 void ddraw_update_lost_surfaces(struct ddraw *ddraw) 4899 { 4900 struct ddraw_surface *surface; 4901 4902 if (ddraw->device_state != DDRAW_DEVICE_STATE_NOT_RESTORED) 4903 return; 4904 4905 LIST_FOR_EACH_ENTRY(surface, &ddraw->surface_list, struct ddraw_surface, surface_list_entry) 4906 { 4907 surface->is_lost = TRUE; 4908 } 4909 ddraw->device_state = DDRAW_DEVICE_STATE_OK; 4910 } 4911 4912 static HRESULT CDECL device_parent_surface_created(struct wined3d_device_parent *device_parent, 4913 struct wined3d_texture *wined3d_texture, unsigned int sub_resource_idx, 4914 void **parent, const struct wined3d_parent_ops **parent_ops) 4915 { 4916 struct ddraw *ddraw = ddraw_from_device_parent(device_parent); 4917 struct ddraw_surface *ddraw_surface; 4918 4919 TRACE("device_parent %p, wined3d_texture %p, sub_resource_idx %u, parent %p, parent_ops %p.\n", 4920 device_parent, wined3d_texture, sub_resource_idx, parent, parent_ops); 4921 4922 /* We have a swapchain or wined3d internal texture. */ 4923 if (!wined3d_texture_get_parent(wined3d_texture) || wined3d_texture_get_parent(wined3d_texture) == ddraw) 4924 { 4925 *parent = NULL; 4926 *parent_ops = &ddraw_null_wined3d_parent_ops; 4927 4928 return DD_OK; 4929 } 4930 4931 if (!(ddraw_surface = heap_alloc_zero(sizeof(*ddraw_surface)))) 4932 { 4933 ERR("Failed to allocate surface memory.\n"); 4934 return DDERR_OUTOFVIDEOMEMORY; 4935 } 4936 4937 ddraw_surface_init(ddraw_surface, ddraw, wined3d_texture, sub_resource_idx, parent_ops); 4938 *parent = ddraw_surface; 4939 4940 ddraw_update_lost_surfaces(ddraw); 4941 list_add_head(&ddraw->surface_list, &ddraw_surface->surface_list_entry); 4942 4943 TRACE("Created ddraw surface %p.\n", ddraw_surface); 4944 4945 return DD_OK; 4946 } 4947 4948 static HRESULT CDECL device_parent_volume_created(struct wined3d_device_parent *device_parent, 4949 struct wined3d_texture *wined3d_texture, unsigned int sub_resource_idx, 4950 void **parent, const struct wined3d_parent_ops **parent_ops) 4951 { 4952 TRACE("device_parent %p, texture %p, sub_resource_idx %u, parent %p, parent_ops %p.\n", 4953 device_parent, wined3d_texture, sub_resource_idx, parent, parent_ops); 4954 4955 *parent = NULL; 4956 *parent_ops = &ddraw_null_wined3d_parent_ops; 4957 4958 return DD_OK; 4959 } 4960 4961 static void STDMETHODCALLTYPE ddraw_frontbuffer_destroyed(void *parent) 4962 { 4963 struct ddraw *ddraw = parent; 4964 ddraw->wined3d_frontbuffer = NULL; 4965 } 4966 4967 static const struct wined3d_parent_ops ddraw_frontbuffer_parent_ops = 4968 { 4969 ddraw_frontbuffer_destroyed, 4970 }; 4971 4972 static HRESULT CDECL device_parent_create_swapchain_texture(struct wined3d_device_parent *device_parent, 4973 void *container_parent, const struct wined3d_resource_desc *desc, DWORD texture_flags, 4974 struct wined3d_texture **texture) 4975 { 4976 struct ddraw *ddraw = ddraw_from_device_parent(device_parent); 4977 HRESULT hr; 4978 4979 TRACE("device_parent %p, container_parent %p, desc %p, texture flags %#x, texture %p.\n", 4980 device_parent, container_parent, desc, texture_flags, texture); 4981 4982 if (ddraw->wined3d_frontbuffer) 4983 { 4984 ERR("Frontbuffer already created.\n"); 4985 return E_FAIL; 4986 } 4987 4988 if (FAILED(hr = wined3d_texture_create(ddraw->wined3d_device, desc, 1, 1, 4989 texture_flags | WINED3D_TEXTURE_CREATE_MAPPABLE, NULL, ddraw, &ddraw_frontbuffer_parent_ops, texture))) 4990 { 4991 WARN("Failed to create texture, hr %#x.\n", hr); 4992 return hr; 4993 } 4994 4995 ddraw->wined3d_frontbuffer = *texture; 4996 4997 return hr; 4998 } 4999 5000 static HRESULT CDECL device_parent_create_swapchain(struct wined3d_device_parent *device_parent, 5001 struct wined3d_swapchain_desc *desc, struct wined3d_swapchain **swapchain) 5002 { 5003 struct ddraw *ddraw = ddraw_from_device_parent(device_parent); 5004 HRESULT hr; 5005 5006 TRACE("device_parent %p, desc %p, swapchain %p.\n", device_parent, desc, swapchain); 5007 5008 if (ddraw->wined3d_swapchain) 5009 { 5010 ERR("Swapchain already created.\n"); 5011 return E_FAIL; 5012 } 5013 5014 if (FAILED(hr = wined3d_swapchain_create(ddraw->wined3d_device, desc, NULL, 5015 &ddraw_null_wined3d_parent_ops, swapchain))) 5016 WARN("Failed to create swapchain, hr %#x.\n", hr); 5017 5018 return hr; 5019 } 5020 5021 static const struct wined3d_device_parent_ops ddraw_wined3d_device_parent_ops = 5022 { 5023 device_parent_wined3d_device_created, 5024 device_parent_mode_changed, 5025 device_parent_activate, 5026 device_parent_surface_created, 5027 device_parent_volume_created, 5028 device_parent_create_swapchain_texture, 5029 device_parent_create_swapchain, 5030 }; 5031 5032 HRESULT ddraw_init(struct ddraw *ddraw, DWORD flags, enum wined3d_device_type device_type) 5033 { 5034 WINED3DCAPS caps; 5035 HRESULT hr; 5036 5037 ddraw->IDirectDraw7_iface.lpVtbl = &ddraw7_vtbl; 5038 ddraw->IDirectDraw_iface.lpVtbl = &ddraw1_vtbl; 5039 ddraw->IDirectDraw2_iface.lpVtbl = &ddraw2_vtbl; 5040 ddraw->IDirectDraw4_iface.lpVtbl = &ddraw4_vtbl; 5041 ddraw->IDirect3D_iface.lpVtbl = &d3d1_vtbl; 5042 ddraw->IDirect3D2_iface.lpVtbl = &d3d2_vtbl; 5043 ddraw->IDirect3D3_iface.lpVtbl = &d3d3_vtbl; 5044 ddraw->IDirect3D7_iface.lpVtbl = &d3d7_vtbl; 5045 ddraw->device_parent.ops = &ddraw_wined3d_device_parent_ops; 5046 ddraw->numIfaces = 1; 5047 ddraw->ref7 = 1; 5048 5049 flags |= DDRAW_WINED3D_FLAGS; 5050 if (!(ddraw->wined3d = wined3d_create(flags))) 5051 { 5052 flags |= WINED3D_NO3D; 5053 if (!(ddraw->wined3d = wined3d_create(flags))) 5054 { 5055 WARN("Failed to create a wined3d object.\n"); 5056 return E_FAIL; 5057 } 5058 } 5059 5060 if (FAILED(hr = wined3d_get_device_caps(ddraw->wined3d, WINED3DADAPTER_DEFAULT, device_type, &caps))) 5061 { 5062 ERR("Failed to get device caps, hr %#x.\n", hr); 5063 wined3d_decref(ddraw->wined3d); 5064 return E_FAIL; 5065 } 5066 5067 if (!(caps.ddraw_caps.caps & WINEDDCAPS_3D)) 5068 { 5069 WARN("Created a wined3d object without 3D support.\n"); 5070 ddraw->flags |= DDRAW_NO3D; 5071 } 5072 5073 if (FAILED(hr = wined3d_device_create(ddraw->wined3d, WINED3DADAPTER_DEFAULT, device_type, 5074 NULL, 0, DDRAW_STRIDE_ALIGNMENT, &ddraw->device_parent, &ddraw->wined3d_device))) 5075 { 5076 WARN("Failed to create a wined3d device, hr %#x.\n", hr); 5077 wined3d_decref(ddraw->wined3d); 5078 return hr; 5079 } 5080 5081 list_init(&ddraw->surface_list); 5082 5083 return DD_OK; 5084 } 5085