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 IDirectDrawSurface7 *gdi_surface; 2097 struct ddraw_surface *gdi_impl; 2098 HRESULT hr; 2099 2100 TRACE("iface %p.\n", iface); 2101 2102 wined3d_mutex_lock(); 2103 2104 if (FAILED(hr = IDirectDraw7_GetGDISurface(iface, &gdi_surface))) 2105 { 2106 WARN("Failed to retrieve GDI surface, hr %#x.\n", hr); 2107 wined3d_mutex_unlock(); 2108 return hr; 2109 } 2110 2111 gdi_impl = impl_from_IDirectDrawSurface7(gdi_surface); 2112 if (gdi_impl->surface_desc.ddsCaps.dwCaps & DDSCAPS_FRONTBUFFER) 2113 hr = DD_OK; 2114 else 2115 hr = IDirectDrawSurface7_Flip(&ddraw->primary->IDirectDrawSurface7_iface, gdi_surface, DDFLIP_WAIT); 2116 IDirectDrawSurface7_Release(gdi_surface); 2117 2118 wined3d_mutex_unlock(); 2119 2120 return hr; 2121 } 2122 2123 static HRESULT WINAPI ddraw4_FlipToGDISurface(IDirectDraw4 *iface) 2124 { 2125 struct ddraw *ddraw = impl_from_IDirectDraw4(iface); 2126 2127 TRACE("iface %p.\n", iface); 2128 2129 return ddraw7_FlipToGDISurface(&ddraw->IDirectDraw7_iface); 2130 } 2131 2132 static HRESULT WINAPI ddraw2_FlipToGDISurface(IDirectDraw2 *iface) 2133 { 2134 struct ddraw *ddraw = impl_from_IDirectDraw2(iface); 2135 2136 TRACE("iface %p.\n", iface); 2137 2138 return ddraw7_FlipToGDISurface(&ddraw->IDirectDraw7_iface); 2139 } 2140 2141 static HRESULT WINAPI ddraw1_FlipToGDISurface(IDirectDraw *iface) 2142 { 2143 struct ddraw *ddraw = impl_from_IDirectDraw(iface); 2144 2145 TRACE("iface %p.\n", iface); 2146 2147 return ddraw7_FlipToGDISurface(&ddraw->IDirectDraw7_iface); 2148 } 2149 2150 /***************************************************************************** 2151 * IDirectDraw7::WaitForVerticalBlank 2152 * 2153 * This method allows applications to get in sync with the vertical blank 2154 * interval. 2155 * The wormhole demo in the DirectX 7 sdk uses this call, and it doesn't 2156 * redraw the screen, most likely because of this stub 2157 * 2158 * Parameters: 2159 * Flags: one of DDWAITVB_BLOCKBEGIN, DDWAITVB_BLOCKBEGINEVENT 2160 * or DDWAITVB_BLOCKEND 2161 * h: Not used, according to MSDN 2162 * 2163 * Returns: 2164 * Always returns DD_OK 2165 * 2166 *****************************************************************************/ 2167 static HRESULT WINAPI ddraw7_WaitForVerticalBlank(IDirectDraw7 *iface, DWORD Flags, HANDLE event) 2168 { 2169 static BOOL hide; 2170 2171 TRACE("iface %p, flags %#x, event %p.\n", iface, Flags, event); 2172 2173 /* This function is called often, so print the fixme only once */ 2174 if(!hide) 2175 { 2176 FIXME("iface %p, flags %#x, event %p stub!\n", iface, Flags, event); 2177 hide = TRUE; 2178 } 2179 2180 /* MSDN says DDWAITVB_BLOCKBEGINEVENT is not supported */ 2181 if(Flags & DDWAITVB_BLOCKBEGINEVENT) 2182 return DDERR_UNSUPPORTED; /* unchecked */ 2183 2184 return DD_OK; 2185 } 2186 2187 static HRESULT WINAPI ddraw4_WaitForVerticalBlank(IDirectDraw4 *iface, DWORD flags, HANDLE event) 2188 { 2189 struct ddraw *ddraw = impl_from_IDirectDraw4(iface); 2190 2191 TRACE("iface %p, flags %#x, event %p.\n", iface, flags, event); 2192 2193 return ddraw7_WaitForVerticalBlank(&ddraw->IDirectDraw7_iface, flags, event); 2194 } 2195 2196 static HRESULT WINAPI ddraw2_WaitForVerticalBlank(IDirectDraw2 *iface, DWORD flags, HANDLE event) 2197 { 2198 struct ddraw *ddraw = impl_from_IDirectDraw2(iface); 2199 2200 TRACE("iface %p, flags %#x, event %p.\n", iface, flags, event); 2201 2202 return ddraw7_WaitForVerticalBlank(&ddraw->IDirectDraw7_iface, flags, event); 2203 } 2204 2205 static HRESULT WINAPI ddraw1_WaitForVerticalBlank(IDirectDraw *iface, DWORD flags, HANDLE event) 2206 { 2207 struct ddraw *ddraw = impl_from_IDirectDraw(iface); 2208 2209 TRACE("iface %p, flags %#x, event %p.\n", iface, flags, event); 2210 2211 return ddraw7_WaitForVerticalBlank(&ddraw->IDirectDraw7_iface, flags, event); 2212 } 2213 2214 static HRESULT WINAPI ddraw7_GetScanLine(IDirectDraw7 *iface, DWORD *Scanline) 2215 { 2216 struct ddraw *ddraw = impl_from_IDirectDraw7(iface); 2217 struct wined3d_raster_status raster_status; 2218 HRESULT hr; 2219 2220 TRACE("iface %p, line %p.\n", iface, Scanline); 2221 2222 wined3d_mutex_lock(); 2223 hr = wined3d_get_adapter_raster_status(ddraw->wined3d, WINED3DADAPTER_DEFAULT, &raster_status); 2224 wined3d_mutex_unlock(); 2225 if (FAILED(hr)) 2226 { 2227 WARN("Failed to get raster status, hr %#x.\n", hr); 2228 return hr; 2229 } 2230 2231 *Scanline = raster_status.scan_line; 2232 2233 if (raster_status.in_vblank) 2234 return DDERR_VERTICALBLANKINPROGRESS; 2235 2236 return DD_OK; 2237 } 2238 2239 static HRESULT WINAPI ddraw4_GetScanLine(IDirectDraw4 *iface, DWORD *line) 2240 { 2241 struct ddraw *ddraw = impl_from_IDirectDraw4(iface); 2242 2243 TRACE("iface %p, line %p.\n", iface, line); 2244 2245 return ddraw7_GetScanLine(&ddraw->IDirectDraw7_iface, line); 2246 } 2247 2248 static HRESULT WINAPI ddraw2_GetScanLine(IDirectDraw2 *iface, DWORD *line) 2249 { 2250 struct ddraw *ddraw = impl_from_IDirectDraw2(iface); 2251 2252 TRACE("iface %p, line %p.\n", iface, line); 2253 2254 return ddraw7_GetScanLine(&ddraw->IDirectDraw7_iface, line); 2255 } 2256 2257 static HRESULT WINAPI ddraw1_GetScanLine(IDirectDraw *iface, DWORD *line) 2258 { 2259 struct ddraw *ddraw = impl_from_IDirectDraw(iface); 2260 2261 TRACE("iface %p, line %p.\n", iface, line); 2262 2263 return ddraw7_GetScanLine(&ddraw->IDirectDraw7_iface, line); 2264 } 2265 2266 static HRESULT WINAPI ddraw7_TestCooperativeLevel(IDirectDraw7 *iface) 2267 { 2268 struct ddraw *ddraw = impl_from_IDirectDraw7(iface); 2269 2270 TRACE("iface %p.\n", iface); 2271 2272 return ddraw->device_state == DDRAW_DEVICE_STATE_LOST ? DDERR_NOEXCLUSIVEMODE : DD_OK; 2273 } 2274 2275 static HRESULT WINAPI ddraw4_TestCooperativeLevel(IDirectDraw4 *iface) 2276 { 2277 struct ddraw *ddraw = impl_from_IDirectDraw4(iface); 2278 2279 TRACE("iface %p.\n", iface); 2280 2281 return ddraw7_TestCooperativeLevel(&ddraw->IDirectDraw7_iface); 2282 } 2283 2284 /***************************************************************************** 2285 * IDirectDraw7::GetGDISurface 2286 * 2287 * Returns the surface that GDI is treating as the primary surface. 2288 * For Wine this is the front buffer 2289 * 2290 * Params: 2291 * GDISurface: Address to write the surface pointer to 2292 * 2293 * Returns: 2294 * DD_OK if the surface was found 2295 * DDERR_NOTFOUND if the GDI surface wasn't found 2296 * 2297 *****************************************************************************/ 2298 static HRESULT WINAPI ddraw7_GetGDISurface(IDirectDraw7 *iface, IDirectDrawSurface7 **GDISurface) 2299 { 2300 struct ddraw *ddraw = impl_from_IDirectDraw7(iface); 2301 2302 TRACE("iface %p, surface %p.\n", iface, GDISurface); 2303 2304 wined3d_mutex_lock(); 2305 2306 if (!(*GDISurface = &ddraw->primary->IDirectDrawSurface7_iface)) 2307 { 2308 WARN("Primary not created yet.\n"); 2309 wined3d_mutex_unlock(); 2310 return DDERR_NOTFOUND; 2311 } 2312 IDirectDrawSurface7_AddRef(*GDISurface); 2313 2314 wined3d_mutex_unlock(); 2315 2316 return DD_OK; 2317 } 2318 2319 static HRESULT WINAPI ddraw4_GetGDISurface(IDirectDraw4 *iface, IDirectDrawSurface4 **surface) 2320 { 2321 struct ddraw *ddraw = impl_from_IDirectDraw4(iface); 2322 struct ddraw_surface *surface_impl; 2323 IDirectDrawSurface7 *surface7; 2324 HRESULT hr; 2325 2326 TRACE("iface %p, surface %p.\n", iface, surface); 2327 2328 hr = ddraw7_GetGDISurface(&ddraw->IDirectDraw7_iface, &surface7); 2329 if (FAILED(hr)) 2330 { 2331 *surface = NULL; 2332 return hr; 2333 } 2334 surface_impl = impl_from_IDirectDrawSurface7(surface7); 2335 *surface = &surface_impl->IDirectDrawSurface4_iface; 2336 IDirectDrawSurface4_AddRef(*surface); 2337 IDirectDrawSurface7_Release(surface7); 2338 2339 return hr; 2340 } 2341 2342 static HRESULT WINAPI ddraw2_GetGDISurface(IDirectDraw2 *iface, IDirectDrawSurface **surface) 2343 { 2344 struct ddraw *ddraw = impl_from_IDirectDraw2(iface); 2345 struct ddraw_surface *surface_impl; 2346 IDirectDrawSurface7 *surface7; 2347 HRESULT hr; 2348 2349 TRACE("iface %p, surface %p.\n", iface, surface); 2350 2351 hr = ddraw7_GetGDISurface(&ddraw->IDirectDraw7_iface, &surface7); 2352 if (FAILED(hr)) 2353 { 2354 *surface = NULL; 2355 return hr; 2356 } 2357 surface_impl = impl_from_IDirectDrawSurface7(surface7); 2358 *surface = &surface_impl->IDirectDrawSurface_iface; 2359 IDirectDrawSurface_AddRef(*surface); 2360 IDirectDrawSurface7_Release(surface7); 2361 2362 return hr; 2363 } 2364 2365 static HRESULT WINAPI ddraw1_GetGDISurface(IDirectDraw *iface, IDirectDrawSurface **surface) 2366 { 2367 struct ddraw *ddraw = impl_from_IDirectDraw(iface); 2368 struct ddraw_surface *surface_impl; 2369 IDirectDrawSurface7 *surface7; 2370 HRESULT hr; 2371 2372 TRACE("iface %p, surface %p.\n", iface, surface); 2373 2374 hr = ddraw7_GetGDISurface(&ddraw->IDirectDraw7_iface, &surface7); 2375 if (FAILED(hr)) 2376 { 2377 *surface = NULL; 2378 return hr; 2379 } 2380 surface_impl = impl_from_IDirectDrawSurface7(surface7); 2381 *surface = &surface_impl->IDirectDrawSurface_iface; 2382 IDirectDrawSurface_AddRef(*surface); 2383 IDirectDrawSurface7_Release(surface7); 2384 2385 return hr; 2386 } 2387 2388 struct displaymodescallback_context 2389 { 2390 LPDDENUMMODESCALLBACK func; 2391 void *context; 2392 }; 2393 2394 static HRESULT CALLBACK EnumDisplayModesCallbackThunk(DDSURFACEDESC2 *surface_desc, void *context) 2395 { 2396 struct displaymodescallback_context *cbcontext = context; 2397 DDSURFACEDESC desc; 2398 2399 DDSD2_to_DDSD(surface_desc, &desc); 2400 return cbcontext->func(&desc, cbcontext->context); 2401 } 2402 2403 /***************************************************************************** 2404 * IDirectDraw7::EnumDisplayModes 2405 * 2406 * Enumerates the supported Display modes. The modes can be filtered with 2407 * the DDSD parameter. 2408 * 2409 * Params: 2410 * Flags: can be DDEDM_REFRESHRATES and DDEDM_STANDARDVGAMODES. For old ddraw 2411 * versions (3 and older?) this is reserved and must be 0. 2412 * DDSD: Surface description to filter the modes 2413 * Context: Pointer passed back to the callback function 2414 * cb: Application-provided callback function 2415 * 2416 * Returns: 2417 * DD_OK on success 2418 * DDERR_INVALIDPARAMS if the callback wasn't set 2419 * 2420 *****************************************************************************/ 2421 static HRESULT WINAPI ddraw7_EnumDisplayModes(IDirectDraw7 *iface, DWORD Flags, 2422 DDSURFACEDESC2 *DDSD, void *Context, LPDDENUMMODESCALLBACK2 cb) 2423 { 2424 struct ddraw *ddraw = impl_from_IDirectDraw7(iface); 2425 struct wined3d_display_mode *enum_modes = NULL; 2426 struct wined3d_display_mode mode; 2427 unsigned int modenum, fmt; 2428 DDSURFACEDESC2 callback_sd; 2429 unsigned enum_mode_count = 0, enum_mode_array_size = 16; 2430 DDPIXELFORMAT pixelformat; 2431 2432 static const enum wined3d_format_id checkFormatList[] = 2433 { 2434 WINED3DFMT_B8G8R8X8_UNORM, 2435 WINED3DFMT_B5G6R5_UNORM, 2436 WINED3DFMT_P8_UINT, 2437 }; 2438 2439 TRACE("iface %p, flags %#x, surface_desc %p, context %p, callback %p.\n", 2440 iface, Flags, DDSD, Context, cb); 2441 2442 if (!cb) 2443 return DDERR_INVALIDPARAMS; 2444 2445 if (!(enum_modes = heap_alloc(enum_mode_array_size * sizeof(*enum_modes)))) 2446 return DDERR_OUTOFMEMORY; 2447 2448 wined3d_mutex_lock(); 2449 2450 pixelformat.dwSize = sizeof(pixelformat); 2451 for(fmt = 0; fmt < ARRAY_SIZE(checkFormatList); fmt++) 2452 { 2453 modenum = 0; 2454 while (wined3d_enum_adapter_modes(ddraw->wined3d, WINED3DADAPTER_DEFAULT, checkFormatList[fmt], 2455 WINED3D_SCANLINE_ORDERING_UNKNOWN, modenum++, &mode) == WINED3D_OK) 2456 { 2457 BOOL found = FALSE; 2458 unsigned i; 2459 2460 ddrawformat_from_wined3dformat(&pixelformat, mode.format_id); 2461 if (DDSD) 2462 { 2463 if (DDSD->dwFlags & DDSD_WIDTH && mode.width != DDSD->dwWidth) 2464 continue; 2465 if (DDSD->dwFlags & DDSD_HEIGHT && mode.height != DDSD->dwHeight) 2466 continue; 2467 if (DDSD->dwFlags & DDSD_REFRESHRATE && mode.refresh_rate != DDSD->u2.dwRefreshRate) 2468 continue; 2469 if (DDSD->dwFlags & DDSD_PIXELFORMAT 2470 && pixelformat.u1.dwRGBBitCount != DDSD->u4.ddpfPixelFormat.u1.dwRGBBitCount) 2471 continue; 2472 } 2473 2474 /* DX docs state EnumDisplayMode should return only unique modes */ 2475 for (i = 0; i < enum_mode_count; i++) 2476 { 2477 if (enum_modes[i].width == mode.width && enum_modes[i].height == mode.height 2478 && enum_modes[i].format_id == mode.format_id 2479 && (enum_modes[i].refresh_rate == mode.refresh_rate || !(Flags & DDEDM_REFRESHRATES))) 2480 { 2481 found = TRUE; 2482 break; 2483 } 2484 } 2485 if(found) continue; 2486 2487 memset(&callback_sd, 0, sizeof(callback_sd)); 2488 callback_sd.dwSize = sizeof(callback_sd); 2489 callback_sd.u4.ddpfPixelFormat.dwSize = sizeof(DDPIXELFORMAT); 2490 2491 callback_sd.dwFlags = DDSD_HEIGHT|DDSD_WIDTH|DDSD_PIXELFORMAT|DDSD_PITCH|DDSD_REFRESHRATE; 2492 if (Flags & DDEDM_REFRESHRATES) 2493 callback_sd.u2.dwRefreshRate = mode.refresh_rate; 2494 2495 callback_sd.dwWidth = mode.width; 2496 callback_sd.dwHeight = mode.height; 2497 2498 callback_sd.u4.ddpfPixelFormat=pixelformat; 2499 2500 /* Calc pitch and DWORD align like MSDN says */ 2501 callback_sd.u1.lPitch = (callback_sd.u4.ddpfPixelFormat.u1.dwRGBBitCount / 8) * mode.width; 2502 callback_sd.u1.lPitch = (callback_sd.u1.lPitch + 3) & ~3; 2503 2504 TRACE("Enumerating %dx%dx%d @%d\n", callback_sd.dwWidth, callback_sd.dwHeight, callback_sd.u4.ddpfPixelFormat.u1.dwRGBBitCount, 2505 callback_sd.u2.dwRefreshRate); 2506 2507 if(cb(&callback_sd, Context) == DDENUMRET_CANCEL) 2508 { 2509 TRACE("Application asked to terminate the enumeration\n"); 2510 heap_free(enum_modes); 2511 wined3d_mutex_unlock(); 2512 return DD_OK; 2513 } 2514 2515 if (enum_mode_count == enum_mode_array_size) 2516 { 2517 struct wined3d_display_mode *new_enum_modes; 2518 2519 enum_mode_array_size *= 2; 2520 if (!(new_enum_modes = heap_realloc(enum_modes, enum_mode_array_size * sizeof(*new_enum_modes)))) 2521 { 2522 heap_free(enum_modes); 2523 wined3d_mutex_unlock(); 2524 return DDERR_OUTOFMEMORY; 2525 } 2526 2527 enum_modes = new_enum_modes; 2528 } 2529 enum_modes[enum_mode_count++] = mode; 2530 } 2531 } 2532 2533 TRACE("End of enumeration\n"); 2534 heap_free(enum_modes); 2535 wined3d_mutex_unlock(); 2536 2537 return DD_OK; 2538 } 2539 2540 static HRESULT WINAPI ddraw4_EnumDisplayModes(IDirectDraw4 *iface, DWORD flags, 2541 DDSURFACEDESC2 *surface_desc, void *context, LPDDENUMMODESCALLBACK2 callback) 2542 { 2543 struct ddraw *ddraw = impl_from_IDirectDraw4(iface); 2544 2545 TRACE("iface %p, flags %#x, surface_desc %p, context %p, callback %p.\n", 2546 iface, flags, surface_desc, context, callback); 2547 2548 return ddraw7_EnumDisplayModes(&ddraw->IDirectDraw7_iface, flags, surface_desc, context, callback); 2549 } 2550 2551 static HRESULT WINAPI ddraw2_EnumDisplayModes(IDirectDraw2 *iface, DWORD flags, 2552 DDSURFACEDESC *surface_desc, void *context, LPDDENUMMODESCALLBACK callback) 2553 { 2554 struct ddraw *ddraw = impl_from_IDirectDraw2(iface); 2555 struct displaymodescallback_context cbcontext; 2556 DDSURFACEDESC2 surface_desc2; 2557 2558 TRACE("iface %p, flags %#x, surface_desc %p, context %p, callback %p.\n", 2559 iface, flags, surface_desc, context, callback); 2560 2561 cbcontext.func = callback; 2562 cbcontext.context = context; 2563 2564 if (surface_desc) DDSD_to_DDSD2(surface_desc, &surface_desc2); 2565 return ddraw7_EnumDisplayModes(&ddraw->IDirectDraw7_iface, flags, 2566 surface_desc ? &surface_desc2 : NULL, &cbcontext, EnumDisplayModesCallbackThunk); 2567 } 2568 2569 static HRESULT WINAPI ddraw1_EnumDisplayModes(IDirectDraw *iface, DWORD flags, 2570 DDSURFACEDESC *surface_desc, void *context, LPDDENUMMODESCALLBACK callback) 2571 { 2572 struct ddraw *ddraw = impl_from_IDirectDraw(iface); 2573 struct displaymodescallback_context cbcontext; 2574 DDSURFACEDESC2 surface_desc2; 2575 2576 TRACE("iface %p, flags %#x, surface_desc %p, context %p, callback %p.\n", 2577 iface, flags, surface_desc, context, callback); 2578 2579 cbcontext.func = callback; 2580 cbcontext.context = context; 2581 2582 if (surface_desc) DDSD_to_DDSD2(surface_desc, &surface_desc2); 2583 return ddraw7_EnumDisplayModes(&ddraw->IDirectDraw7_iface, flags, 2584 surface_desc ? &surface_desc2 : NULL, &cbcontext, EnumDisplayModesCallbackThunk); 2585 } 2586 2587 /***************************************************************************** 2588 * IDirectDraw7::EvaluateMode 2589 * 2590 * Used with IDirectDraw7::StartModeTest to test video modes. 2591 * EvaluateMode is used to pass or fail a mode, and continue with the next 2592 * mode 2593 * 2594 * Params: 2595 * Flags: DDEM_MODEPASSED or DDEM_MODEFAILED 2596 * Timeout: Returns the amount of seconds left before the mode would have 2597 * been failed automatically 2598 * 2599 * Returns: 2600 * This implementation always DD_OK, because it's a stub 2601 * 2602 *****************************************************************************/ 2603 static HRESULT WINAPI ddraw7_EvaluateMode(IDirectDraw7 *iface, DWORD Flags, DWORD *Timeout) 2604 { 2605 FIXME("iface %p, flags %#x, timeout %p stub!\n", iface, Flags, Timeout); 2606 2607 /* When implementing this, implement it in WineD3D */ 2608 2609 return DD_OK; 2610 } 2611 2612 /***************************************************************************** 2613 * IDirectDraw7::GetDeviceIdentifier 2614 * 2615 * Returns the device identifier, which gives information about the driver 2616 * Our device identifier is defined at the beginning of this file. 2617 * 2618 * Params: 2619 * DDDI: Address for the returned structure 2620 * Flags: Can be DDGDI_GETHOSTIDENTIFIER 2621 * 2622 * Returns: 2623 * On success it returns DD_OK 2624 * DDERR_INVALIDPARAMS if DDDI is NULL 2625 * 2626 *****************************************************************************/ 2627 static HRESULT WINAPI ddraw7_GetDeviceIdentifier(IDirectDraw7 *iface, 2628 DDDEVICEIDENTIFIER2 *DDDI, DWORD Flags) 2629 { 2630 struct ddraw *ddraw = impl_from_IDirectDraw7(iface); 2631 struct wined3d_adapter_identifier adapter_id; 2632 HRESULT hr = S_OK; 2633 2634 TRACE("iface %p, device_identifier %p, flags %#x.\n", iface, DDDI, Flags); 2635 2636 if (!DDDI) 2637 return DDERR_INVALIDPARAMS; 2638 2639 if (Flags & DDGDI_GETHOSTIDENTIFIER) 2640 { 2641 /* The DDGDI_GETHOSTIDENTIFIER returns the information about the 2D 2642 * host adapter, if there's a secondary 3D adapter. This doesn't apply 2643 * to any modern hardware, nor is it interesting for Wine, so ignore it. 2644 * Size of DDDEVICEIDENTIFIER2 may be aligned to 8 bytes and thus 4 2645 * bytes too long. So only copy the relevant part of the structure 2646 */ 2647 2648 memcpy(DDDI, &deviceidentifier, FIELD_OFFSET(DDDEVICEIDENTIFIER2, dwWHQLLevel) + sizeof(DWORD)); 2649 return DD_OK; 2650 } 2651 2652 /* Drakan: Order of the Flame expects accurate D3D device information from ddraw */ 2653 adapter_id.driver = DDDI->szDriver; 2654 adapter_id.driver_size = sizeof(DDDI->szDriver); 2655 adapter_id.description = DDDI->szDescription; 2656 adapter_id.description_size = sizeof(DDDI->szDescription); 2657 adapter_id.device_name_size = 0; 2658 wined3d_mutex_lock(); 2659 hr = wined3d_get_adapter_identifier(ddraw->wined3d, WINED3DADAPTER_DEFAULT, 0x0, &adapter_id); 2660 wined3d_mutex_unlock(); 2661 if (FAILED(hr)) return hr; 2662 2663 DDDI->liDriverVersion = adapter_id.driver_version; 2664 DDDI->dwVendorId = adapter_id.vendor_id; 2665 DDDI->dwDeviceId = adapter_id.device_id; 2666 DDDI->dwSubSysId = adapter_id.subsystem_id; 2667 DDDI->dwRevision = adapter_id.revision; 2668 DDDI->guidDeviceIdentifier = adapter_id.device_identifier; 2669 DDDI->dwWHQLLevel = adapter_id.whql_level; 2670 return DD_OK; 2671 } 2672 2673 static HRESULT WINAPI ddraw4_GetDeviceIdentifier(IDirectDraw4 *iface, 2674 DDDEVICEIDENTIFIER *identifier, DWORD flags) 2675 { 2676 struct ddraw *ddraw = impl_from_IDirectDraw4(iface); 2677 DDDEVICEIDENTIFIER2 identifier2; 2678 HRESULT hr; 2679 2680 TRACE("iface %p, identifier %p, flags %#x.\n", iface, identifier, flags); 2681 2682 hr = ddraw7_GetDeviceIdentifier(&ddraw->IDirectDraw7_iface, &identifier2, flags); 2683 DDRAW_Convert_DDDEVICEIDENTIFIER_2_To_1(&identifier2, identifier); 2684 2685 return hr; 2686 } 2687 2688 /***************************************************************************** 2689 * IDirectDraw7::GetSurfaceFromDC 2690 * 2691 * Returns the Surface for a GDI device context handle. 2692 * Is this related to IDirectDrawSurface::GetDC ??? 2693 * 2694 * Params: 2695 * hdc: hdc to return the surface for 2696 * Surface: Address to write the surface pointer to 2697 * 2698 * Returns: 2699 * Always returns DD_OK because it's a stub 2700 * 2701 *****************************************************************************/ 2702 static HRESULT WINAPI ddraw7_GetSurfaceFromDC(IDirectDraw7 *iface, 2703 HDC dc, IDirectDrawSurface7 **surface) 2704 { 2705 struct ddraw *ddraw = impl_from_IDirectDraw7(iface); 2706 struct ddraw_surface *surface_impl; 2707 2708 TRACE("iface %p, dc %p, surface %p.\n", iface, dc, surface); 2709 2710 if (!surface) 2711 return E_INVALIDARG; 2712 2713 if (!dc) 2714 goto done; 2715 2716 wined3d_mutex_lock(); 2717 LIST_FOR_EACH_ENTRY(surface_impl, &ddraw->surface_list, struct ddraw_surface, surface_list_entry) 2718 { 2719 if (surface_impl->dc != dc) 2720 continue; 2721 2722 TRACE("Found surface %p for dc %p.\n", surface_impl, dc); 2723 *surface = &surface_impl->IDirectDrawSurface7_iface; 2724 IDirectDrawSurface7_AddRef(*surface); 2725 wined3d_mutex_unlock(); 2726 return DD_OK; 2727 } 2728 wined3d_mutex_unlock(); 2729 2730 done: 2731 TRACE("No surface found for dc %p.\n", dc); 2732 *surface = NULL; 2733 return DDERR_NOTFOUND; 2734 } 2735 2736 static HRESULT WINAPI ddraw4_GetSurfaceFromDC(IDirectDraw4 *iface, HDC dc, 2737 IDirectDrawSurface4 **surface) 2738 { 2739 struct ddraw *ddraw = impl_from_IDirectDraw4(iface); 2740 struct ddraw_surface *surface_impl; 2741 IDirectDrawSurface7 *surface7; 2742 HRESULT hr; 2743 2744 TRACE("iface %p, dc %p, surface %p.\n", iface, dc, surface); 2745 2746 if (!surface) return E_INVALIDARG; 2747 2748 hr = ddraw7_GetSurfaceFromDC(&ddraw->IDirectDraw7_iface, dc, &surface7); 2749 if (FAILED(hr)) 2750 { 2751 *surface = NULL; 2752 return hr; 2753 } 2754 surface_impl = impl_from_IDirectDrawSurface7(surface7); 2755 /* Tests say this is true */ 2756 *surface = (IDirectDrawSurface4 *)&surface_impl->IDirectDrawSurface_iface; 2757 IDirectDrawSurface_AddRef(&surface_impl->IDirectDrawSurface_iface); 2758 IDirectDrawSurface7_Release(surface7); 2759 2760 return hr; 2761 } 2762 2763 static HRESULT CALLBACK restore_callback(IDirectDrawSurface7 *surface, DDSURFACEDESC2 *desc, void *context) 2764 { 2765 IDirectDrawSurface_Restore(surface); 2766 IDirectDrawSurface_Release(surface); 2767 2768 return DDENUMRET_OK; 2769 } 2770 2771 static HRESULT WINAPI ddraw7_RestoreAllSurfaces(IDirectDraw7 *iface) 2772 { 2773 TRACE("iface %p.\n", iface); 2774 2775 return IDirectDraw7_EnumSurfaces(iface, DDENUMSURFACES_ALL | DDENUMSURFACES_DOESEXIST, 2776 NULL, NULL, restore_callback); 2777 } 2778 2779 static HRESULT WINAPI ddraw4_RestoreAllSurfaces(IDirectDraw4 *iface) 2780 { 2781 struct ddraw *ddraw = impl_from_IDirectDraw4(iface); 2782 2783 TRACE("iface %p.\n", iface); 2784 2785 return ddraw7_RestoreAllSurfaces(&ddraw->IDirectDraw7_iface); 2786 } 2787 2788 /***************************************************************************** 2789 * IDirectDraw7::StartModeTest 2790 * 2791 * Tests the specified video modes to update the system registry with 2792 * refresh rate information. StartModeTest starts the mode test, 2793 * EvaluateMode is used to fail or pass a mode. If EvaluateMode 2794 * isn't called within 15 seconds, the mode is failed automatically 2795 * 2796 * As refresh rates are handled by the X server, I don't think this 2797 * Method is important 2798 * 2799 * Params: 2800 * Modes: An array of mode specifications 2801 * NumModes: The number of modes in Modes 2802 * Flags: Some flags... 2803 * 2804 * Returns: 2805 * Returns DDERR_TESTFINISHED if flags contains DDSMT_ISTESTREQUIRED, 2806 * if no modes are passed, DDERR_INVALIDPARAMS is returned, 2807 * otherwise DD_OK 2808 * 2809 *****************************************************************************/ 2810 static HRESULT WINAPI ddraw7_StartModeTest(IDirectDraw7 *iface, SIZE *Modes, DWORD NumModes, DWORD Flags) 2811 { 2812 FIXME("iface %p, modes %p, mode_count %u, flags %#x partial stub!\n", 2813 iface, Modes, NumModes, Flags); 2814 2815 /* This looks sane */ 2816 if( (!Modes) || (NumModes == 0) ) return DDERR_INVALIDPARAMS; 2817 2818 /* DDSMT_ISTESTREQUIRED asks if a mode test is necessary. 2819 * As it is not, DDERR_TESTFINISHED is returned 2820 * (hopefully that's correct 2821 * 2822 if(Flags & DDSMT_ISTESTREQUIRED) return DDERR_TESTFINISHED; 2823 * well, that value doesn't (yet) exist in the wine headers, so ignore it 2824 */ 2825 2826 return DD_OK; 2827 } 2828 2829 static HRESULT WINAPI ddraw7_CreateSurface(IDirectDraw7 *iface, DDSURFACEDESC2 *surface_desc, 2830 IDirectDrawSurface7 **surface, IUnknown *outer_unknown) 2831 { 2832 struct ddraw *ddraw = impl_from_IDirectDraw7(iface); 2833 struct ddraw_surface *impl; 2834 HRESULT hr; 2835 2836 TRACE("iface %p, surface_desc %p, surface %p, outer_unknown %p.\n", 2837 iface, surface_desc, surface, outer_unknown); 2838 2839 wined3d_mutex_lock(); 2840 2841 if (!(ddraw->cooperative_level & (DDSCL_NORMAL | DDSCL_EXCLUSIVE))) 2842 { 2843 WARN("Cooperative level not set.\n"); 2844 wined3d_mutex_unlock(); 2845 return DDERR_NOCOOPERATIVELEVELSET; 2846 } 2847 2848 if(surface_desc == NULL || surface_desc->dwSize != sizeof(DDSURFACEDESC2)) 2849 { 2850 WARN("Application supplied invalid surface descriptor\n"); 2851 wined3d_mutex_unlock(); 2852 return DDERR_INVALIDPARAMS; 2853 } 2854 2855 __TRY 2856 { 2857 *surface = NULL; 2858 } 2859 __EXCEPT_PAGE_FAULT 2860 { 2861 WARN("Surface pointer %p is invalid.\n", surface); 2862 wined3d_mutex_unlock(); 2863 return DDERR_INVALIDPARAMS; 2864 } 2865 __ENDTRY; 2866 2867 if(surface_desc->ddsCaps.dwCaps & (DDSCAPS_FRONTBUFFER | DDSCAPS_BACKBUFFER)) 2868 { 2869 if (TRACE_ON(ddraw)) 2870 { 2871 TRACE(" (%p) Requesting surface desc :\n", iface); 2872 DDRAW_dump_surface_desc(surface_desc); 2873 } 2874 2875 WARN("Application tried to create an explicit front or back buffer\n"); 2876 wined3d_mutex_unlock(); 2877 return DDERR_INVALIDCAPS; 2878 } 2879 2880 hr = ddraw_surface_create(ddraw, surface_desc, &impl, outer_unknown, 7); 2881 wined3d_mutex_unlock(); 2882 if (FAILED(hr)) 2883 return hr; 2884 2885 *surface = &impl->IDirectDrawSurface7_iface; 2886 IDirectDraw7_AddRef(iface); 2887 impl->ifaceToRelease = (IUnknown *)iface; 2888 2889 return hr; 2890 } 2891 2892 static HRESULT WINAPI ddraw4_CreateSurface(IDirectDraw4 *iface, 2893 DDSURFACEDESC2 *surface_desc, IDirectDrawSurface4 **surface, IUnknown *outer_unknown) 2894 { 2895 struct ddraw *ddraw = impl_from_IDirectDraw4(iface); 2896 struct ddraw_surface *impl; 2897 HRESULT hr; 2898 2899 TRACE("iface %p, surface_desc %p, surface %p, outer_unknown %p.\n", 2900 iface, surface_desc, surface, outer_unknown); 2901 2902 wined3d_mutex_lock(); 2903 2904 if (!(ddraw->cooperative_level & (DDSCL_NORMAL | DDSCL_EXCLUSIVE))) 2905 { 2906 WARN("Cooperative level not set.\n"); 2907 wined3d_mutex_unlock(); 2908 return DDERR_NOCOOPERATIVELEVELSET; 2909 } 2910 2911 if(surface_desc == NULL || surface_desc->dwSize != sizeof(DDSURFACEDESC2)) 2912 { 2913 WARN("Application supplied invalid surface descriptor\n"); 2914 wined3d_mutex_unlock(); 2915 return DDERR_INVALIDPARAMS; 2916 } 2917 2918 __TRY 2919 { 2920 *surface = NULL; 2921 } 2922 __EXCEPT_PAGE_FAULT 2923 { 2924 WARN("Surface pointer %p is invalid.\n", surface); 2925 wined3d_mutex_unlock(); 2926 return DDERR_INVALIDPARAMS; 2927 } 2928 __ENDTRY; 2929 2930 if(surface_desc->ddsCaps.dwCaps & (DDSCAPS_FRONTBUFFER | DDSCAPS_BACKBUFFER)) 2931 { 2932 if (TRACE_ON(ddraw)) 2933 { 2934 TRACE(" (%p) Requesting surface desc :\n", iface); 2935 DDRAW_dump_surface_desc(surface_desc); 2936 } 2937 2938 WARN("Application tried to create an explicit front or back buffer\n"); 2939 wined3d_mutex_unlock(); 2940 return DDERR_INVALIDCAPS; 2941 } 2942 2943 hr = ddraw_surface_create(ddraw, surface_desc, &impl, outer_unknown, 4); 2944 wined3d_mutex_unlock(); 2945 if (FAILED(hr)) 2946 return hr; 2947 2948 *surface = &impl->IDirectDrawSurface4_iface; 2949 IDirectDraw4_AddRef(iface); 2950 impl->ifaceToRelease = (IUnknown *)iface; 2951 2952 return hr; 2953 } 2954 2955 static HRESULT WINAPI ddraw2_CreateSurface(IDirectDraw2 *iface, 2956 DDSURFACEDESC *surface_desc, IDirectDrawSurface **surface, IUnknown *outer_unknown) 2957 { 2958 struct ddraw *ddraw = impl_from_IDirectDraw2(iface); 2959 struct ddraw_surface *impl; 2960 HRESULT hr; 2961 DDSURFACEDESC2 surface_desc2; 2962 2963 TRACE("iface %p, surface_desc %p, surface %p, outer_unknown %p.\n", 2964 iface, surface_desc, surface, outer_unknown); 2965 2966 wined3d_mutex_lock(); 2967 2968 if (!(ddraw->cooperative_level & (DDSCL_NORMAL | DDSCL_EXCLUSIVE))) 2969 { 2970 WARN("Cooperative level not set.\n"); 2971 wined3d_mutex_unlock(); 2972 return DDERR_NOCOOPERATIVELEVELSET; 2973 } 2974 2975 if(surface_desc == NULL || surface_desc->dwSize != sizeof(DDSURFACEDESC)) 2976 { 2977 WARN("Application supplied invalid surface descriptor\n"); 2978 wined3d_mutex_unlock(); 2979 return DDERR_INVALIDPARAMS; 2980 } 2981 2982 __TRY 2983 { 2984 *surface = NULL; 2985 } 2986 __EXCEPT_PAGE_FAULT 2987 { 2988 WARN("Surface pointer %p is invalid.\n", surface); 2989 wined3d_mutex_unlock(); 2990 return DDERR_INVALIDPARAMS; 2991 } 2992 __ENDTRY; 2993 2994 DDSD_to_DDSD2(surface_desc, &surface_desc2); 2995 if(surface_desc->ddsCaps.dwCaps & (DDSCAPS_FRONTBUFFER | DDSCAPS_BACKBUFFER)) 2996 { 2997 if (TRACE_ON(ddraw)) 2998 { 2999 TRACE(" (%p) Requesting surface desc :\n", iface); 3000 DDRAW_dump_surface_desc((DDSURFACEDESC2 *)surface_desc); 3001 } 3002 3003 WARN("Application tried to create an explicit front or back buffer\n"); 3004 wined3d_mutex_unlock(); 3005 return DDERR_INVALIDCAPS; 3006 } 3007 3008 hr = ddraw_surface_create(ddraw, &surface_desc2, &impl, outer_unknown, 2); 3009 wined3d_mutex_unlock(); 3010 if (FAILED(hr)) 3011 return hr; 3012 3013 *surface = &impl->IDirectDrawSurface_iface; 3014 impl->ifaceToRelease = NULL; 3015 3016 return hr; 3017 } 3018 3019 static HRESULT WINAPI ddraw1_CreateSurface(IDirectDraw *iface, 3020 DDSURFACEDESC *surface_desc, IDirectDrawSurface **surface, IUnknown *outer_unknown) 3021 { 3022 struct ddraw *ddraw = impl_from_IDirectDraw(iface); 3023 struct ddraw_surface *impl; 3024 HRESULT hr; 3025 DDSURFACEDESC2 surface_desc2; 3026 3027 TRACE("iface %p, surface_desc %p, surface %p, outer_unknown %p.\n", 3028 iface, surface_desc, surface, outer_unknown); 3029 3030 wined3d_mutex_lock(); 3031 3032 if (!(ddraw->cooperative_level & (DDSCL_NORMAL | DDSCL_EXCLUSIVE))) 3033 { 3034 WARN("Cooperative level not set.\n"); 3035 wined3d_mutex_unlock(); 3036 return DDERR_NOCOOPERATIVELEVELSET; 3037 } 3038 3039 if(surface_desc == NULL || surface_desc->dwSize != sizeof(DDSURFACEDESC)) 3040 { 3041 WARN("Application supplied invalid surface descriptor\n"); 3042 wined3d_mutex_unlock(); 3043 return DDERR_INVALIDPARAMS; 3044 } 3045 3046 __TRY 3047 { 3048 *surface = NULL; 3049 } 3050 __EXCEPT_PAGE_FAULT 3051 { 3052 WARN("Surface pointer %p is invalid.\n", surface); 3053 wined3d_mutex_unlock(); 3054 return DDERR_INVALIDPARAMS; 3055 } 3056 __ENDTRY; 3057 3058 if ((surface_desc->ddsCaps.dwCaps & (DDSCAPS_PRIMARYSURFACE | DDSCAPS_BACKBUFFER)) 3059 == (DDSCAPS_PRIMARYSURFACE | DDSCAPS_BACKBUFFER) 3060 || (surface_desc->ddsCaps.dwCaps & (DDSCAPS_FLIP | DDSCAPS_FRONTBUFFER)) 3061 == ((DDSCAPS_FLIP | DDSCAPS_FRONTBUFFER))) 3062 { 3063 WARN("Application tried to create an explicit front or back buffer.\n"); 3064 wined3d_mutex_unlock(); 3065 return DDERR_INVALIDCAPS; 3066 } 3067 3068 DDSD_to_DDSD2(surface_desc, &surface_desc2); 3069 hr = ddraw_surface_create(ddraw, &surface_desc2, &impl, outer_unknown, 1); 3070 wined3d_mutex_unlock(); 3071 if (FAILED(hr)) 3072 return hr; 3073 3074 *surface = &impl->IDirectDrawSurface_iface; 3075 impl->ifaceToRelease = NULL; 3076 3077 return hr; 3078 } 3079 3080 static BOOL 3081 Main_DirectDraw_DDPIXELFORMAT_Match(const DDPIXELFORMAT *requested, 3082 const DDPIXELFORMAT *provided) 3083 { 3084 /* Some flags must be present in both or neither for a match. */ 3085 static const DWORD must_match = DDPF_PALETTEINDEXED1 | DDPF_PALETTEINDEXED2 3086 | DDPF_PALETTEINDEXED4 | DDPF_PALETTEINDEXED8 | DDPF_FOURCC 3087 | DDPF_ZBUFFER | DDPF_STENCILBUFFER; 3088 3089 if ((requested->dwFlags & provided->dwFlags) != requested->dwFlags) 3090 return FALSE; 3091 3092 if ((requested->dwFlags & must_match) != (provided->dwFlags & must_match)) 3093 return FALSE; 3094 3095 if (requested->dwFlags & DDPF_FOURCC) 3096 if (requested->dwFourCC != provided->dwFourCC) 3097 return FALSE; 3098 3099 if (requested->dwFlags & (DDPF_RGB|DDPF_YUV|DDPF_ZBUFFER|DDPF_ALPHA 3100 |DDPF_LUMINANCE|DDPF_BUMPDUDV)) 3101 if (requested->u1.dwRGBBitCount != provided->u1.dwRGBBitCount) 3102 return FALSE; 3103 3104 if (requested->dwFlags & (DDPF_RGB|DDPF_YUV|DDPF_STENCILBUFFER 3105 |DDPF_LUMINANCE|DDPF_BUMPDUDV)) 3106 if (requested->u2.dwRBitMask != provided->u2.dwRBitMask) 3107 return FALSE; 3108 3109 if (requested->dwFlags & (DDPF_RGB|DDPF_YUV|DDPF_ZBUFFER|DDPF_BUMPDUDV)) 3110 if (requested->u3.dwGBitMask != provided->u3.dwGBitMask) 3111 return FALSE; 3112 3113 /* I could be wrong about the bumpmapping. MSDN docs are vague. */ 3114 if (requested->dwFlags & (DDPF_RGB|DDPF_YUV|DDPF_STENCILBUFFER 3115 |DDPF_BUMPDUDV)) 3116 if (requested->u4.dwBBitMask != provided->u4.dwBBitMask) 3117 return FALSE; 3118 3119 if (requested->dwFlags & (DDPF_ALPHAPIXELS|DDPF_ZPIXELS)) 3120 if (requested->u5.dwRGBAlphaBitMask != provided->u5.dwRGBAlphaBitMask) 3121 return FALSE; 3122 3123 return TRUE; 3124 } 3125 3126 static BOOL ddraw_match_surface_desc(const DDSURFACEDESC2 *requested, const DDSURFACEDESC2 *provided) 3127 { 3128 struct compare_info 3129 { 3130 DWORD flag; 3131 ptrdiff_t offset; 3132 size_t size; 3133 }; 3134 3135 #define CMP(FLAG, FIELD) \ 3136 { DDSD_##FLAG, offsetof(DDSURFACEDESC2, FIELD), \ 3137 sizeof(((DDSURFACEDESC2 *)(NULL))->FIELD) } 3138 3139 static const struct compare_info compare[] = 3140 { 3141 CMP(ALPHABITDEPTH, dwAlphaBitDepth), 3142 CMP(BACKBUFFERCOUNT, u5.dwBackBufferCount), 3143 CMP(CAPS, ddsCaps), 3144 CMP(CKDESTBLT, ddckCKDestBlt), 3145 CMP(CKDESTOVERLAY, u3 /* ddckCKDestOverlay */), 3146 CMP(CKSRCBLT, ddckCKSrcBlt), 3147 CMP(CKSRCOVERLAY, ddckCKSrcOverlay), 3148 CMP(HEIGHT, dwHeight), 3149 CMP(LINEARSIZE, u1 /* dwLinearSize */), 3150 CMP(LPSURFACE, lpSurface), 3151 CMP(MIPMAPCOUNT, u2 /* dwMipMapCount */), 3152 CMP(PITCH, u1 /* lPitch */), 3153 /* PIXELFORMAT: manual */ 3154 CMP(REFRESHRATE, u2 /* dwRefreshRate */), 3155 CMP(TEXTURESTAGE, dwTextureStage), 3156 CMP(WIDTH, dwWidth), 3157 /* ZBUFFERBITDEPTH: "obsolete" */ 3158 }; 3159 3160 #undef CMP 3161 3162 unsigned int i; 3163 3164 if ((requested->dwFlags & provided->dwFlags) != requested->dwFlags) 3165 return FALSE; 3166 3167 for (i=0; i < ARRAY_SIZE(compare); i++) 3168 { 3169 if (requested->dwFlags & compare[i].flag 3170 && memcmp((const char *)provided + compare[i].offset, 3171 (const char *)requested + compare[i].offset, 3172 compare[i].size) != 0) 3173 return FALSE; 3174 } 3175 3176 if (requested->dwFlags & DDSD_PIXELFORMAT) 3177 { 3178 if (!Main_DirectDraw_DDPIXELFORMAT_Match(&requested->u4.ddpfPixelFormat, 3179 &provided->u4.ddpfPixelFormat)) 3180 return FALSE; 3181 } 3182 3183 return TRUE; 3184 } 3185 3186 struct surfacescallback2_context 3187 { 3188 LPDDENUMSURFACESCALLBACK2 func; 3189 void *context; 3190 }; 3191 3192 struct surfacescallback_context 3193 { 3194 LPDDENUMSURFACESCALLBACK func; 3195 void *context; 3196 }; 3197 3198 static HRESULT CALLBACK EnumSurfacesCallback2Thunk(IDirectDrawSurface7 *surface, 3199 DDSURFACEDESC2 *surface_desc, void *context) 3200 { 3201 struct ddraw_surface *surface_impl = impl_from_IDirectDrawSurface7(surface); 3202 struct surfacescallback2_context *cbcontext = context; 3203 3204 IDirectDrawSurface4_AddRef(&surface_impl->IDirectDrawSurface4_iface); 3205 IDirectDrawSurface7_Release(surface); 3206 3207 return cbcontext->func(&surface_impl->IDirectDrawSurface4_iface, 3208 surface_desc, cbcontext->context); 3209 } 3210 3211 static HRESULT CALLBACK EnumSurfacesCallbackThunk(IDirectDrawSurface7 *surface, 3212 DDSURFACEDESC2 *surface_desc, void *context) 3213 { 3214 struct ddraw_surface *surface_impl = impl_from_IDirectDrawSurface7(surface); 3215 struct surfacescallback_context *cbcontext = context; 3216 3217 IDirectDrawSurface_AddRef(&surface_impl->IDirectDrawSurface_iface); 3218 IDirectDrawSurface7_Release(surface); 3219 3220 return cbcontext->func(&surface_impl->IDirectDrawSurface_iface, 3221 (DDSURFACEDESC *)surface_desc, cbcontext->context); 3222 } 3223 3224 /***************************************************************************** 3225 * IDirectDraw7::EnumSurfaces 3226 * 3227 * Loops through all surfaces attached to this device and calls the 3228 * application callback. This can't be relayed to WineD3DDevice, 3229 * because some WineD3DSurfaces' parents are IParent objects 3230 * 3231 * Params: 3232 * Flags: Some filtering flags. See IDirectDrawImpl_EnumSurfacesCallback 3233 * DDSD: Description to filter for 3234 * Context: Application-provided pointer, it's passed unmodified to the 3235 * Callback function 3236 * Callback: Address to call for each surface 3237 * 3238 * Returns: 3239 * DDERR_INVALIDPARAMS if the callback is NULL 3240 * DD_OK on success 3241 * 3242 *****************************************************************************/ 3243 static HRESULT WINAPI ddraw7_EnumSurfaces(IDirectDraw7 *iface, DWORD Flags, 3244 DDSURFACEDESC2 *DDSD, void *Context, LPDDENUMSURFACESCALLBACK7 Callback) 3245 { 3246 struct ddraw *ddraw = impl_from_IDirectDraw7(iface); 3247 struct ddraw_surface *surf; 3248 DWORD match_flags = Flags & (DDENUMSURFACES_ALL | DDENUMSURFACES_NOMATCH | DDENUMSURFACES_MATCH); 3249 3250 TRACE("iface %p, flags %#x, surface_desc %p, context %p, callback %p.\n", 3251 iface, Flags, DDSD, Context, Callback); 3252 3253 if (!Callback) 3254 return DDERR_INVALIDPARAMS; 3255 3256 if (Flags & DDENUMSURFACES_CANBECREATED) 3257 { 3258 IDirectDrawSurface7 *surface; 3259 DDSURFACEDESC2 testdesc; 3260 HRESULT hr; 3261 3262 if (match_flags != DDENUMSURFACES_MATCH) 3263 return DDERR_INVALIDPARAMS; 3264 3265 if (!DDSD) 3266 return DDERR_INVALIDPARAMS; 3267 3268 memcpy(&testdesc, DDSD, sizeof(testdesc)); 3269 if (!(testdesc.dwFlags & DDSD_WIDTH)) 3270 { 3271 testdesc.dwFlags |= DDSD_WIDTH; 3272 testdesc.dwWidth = 512; 3273 } 3274 if (!(testdesc.dwFlags & DDSD_HEIGHT)) 3275 { 3276 testdesc.dwFlags |= DDSD_HEIGHT; 3277 testdesc.dwHeight = 512; 3278 } 3279 3280 hr = IDirectDraw7_CreateSurface(iface, &testdesc, &surface, NULL); 3281 if (SUCCEEDED(hr)) 3282 { 3283 surf = unsafe_impl_from_IDirectDrawSurface7(surface); 3284 Callback(NULL, &surf->surface_desc, Context); 3285 IDirectDrawSurface7_Release(surface); 3286 } 3287 else 3288 ERR("Failed to create surface, hr %#x.\n", hr); 3289 } 3290 else if (Flags & DDENUMSURFACES_DOESEXIST) 3291 { 3292 BOOL all, nomatch; 3293 DDSURFACEDESC2 desc; 3294 struct list *entry, *entry2; 3295 3296 /* a combination of match flags is not allowed */ 3297 if (match_flags != 0 && 3298 match_flags != DDENUMSURFACES_ALL && 3299 match_flags != DDENUMSURFACES_MATCH && 3300 match_flags != DDENUMSURFACES_NOMATCH) 3301 return DDERR_INVALIDPARAMS; 3302 3303 all = (Flags & DDENUMSURFACES_ALL) != 0; 3304 nomatch = (Flags & DDENUMSURFACES_NOMATCH) != 0; 3305 3306 if (!all && !DDSD) 3307 return DDERR_INVALIDPARAMS; 3308 3309 wined3d_mutex_lock(); 3310 3311 /* Use the _SAFE enumeration, the app may destroy enumerated surfaces */ 3312 LIST_FOR_EACH_SAFE(entry, entry2, &ddraw->surface_list) 3313 { 3314 surf = LIST_ENTRY(entry, struct ddraw_surface, surface_list_entry); 3315 3316 if (!surf->iface_count) 3317 { 3318 WARN("Not enumerating surface %p because it doesn't have any references.\n", surf); 3319 continue; 3320 } 3321 3322 if (all || (nomatch != ddraw_match_surface_desc(DDSD, &surf->surface_desc))) 3323 { 3324 TRACE("Enumerating surface %p.\n", surf); 3325 desc = surf->surface_desc; 3326 IDirectDrawSurface7_AddRef(&surf->IDirectDrawSurface7_iface); 3327 if (Callback(&surf->IDirectDrawSurface7_iface, &desc, Context) != DDENUMRET_OK) 3328 { 3329 wined3d_mutex_unlock(); 3330 return DD_OK; 3331 } 3332 } 3333 } 3334 3335 wined3d_mutex_unlock(); 3336 } 3337 else 3338 return DDERR_INVALIDPARAMS; 3339 3340 return DD_OK; 3341 } 3342 3343 static HRESULT WINAPI ddraw4_EnumSurfaces(IDirectDraw4 *iface, DWORD flags, 3344 DDSURFACEDESC2 *surface_desc, void *context, LPDDENUMSURFACESCALLBACK2 callback) 3345 { 3346 struct ddraw *ddraw = impl_from_IDirectDraw4(iface); 3347 struct surfacescallback2_context cbcontext; 3348 3349 TRACE("iface %p, flags %#x, surface_desc %p, context %p, callback %p.\n", 3350 iface, flags, surface_desc, context, callback); 3351 3352 cbcontext.func = callback; 3353 cbcontext.context = context; 3354 3355 return ddraw7_EnumSurfaces(&ddraw->IDirectDraw7_iface, flags, surface_desc, 3356 &cbcontext, EnumSurfacesCallback2Thunk); 3357 } 3358 3359 static HRESULT WINAPI ddraw2_EnumSurfaces(IDirectDraw2 *iface, DWORD flags, 3360 DDSURFACEDESC *surface_desc, void *context, LPDDENUMSURFACESCALLBACK callback) 3361 { 3362 struct ddraw *ddraw = impl_from_IDirectDraw2(iface); 3363 struct surfacescallback_context cbcontext; 3364 DDSURFACEDESC2 surface_desc2; 3365 3366 TRACE("iface %p, flags %#x, surface_desc %p, context %p, callback %p.\n", 3367 iface, flags, surface_desc, context, callback); 3368 3369 cbcontext.func = callback; 3370 cbcontext.context = context; 3371 3372 if (surface_desc) DDSD_to_DDSD2(surface_desc, &surface_desc2); 3373 return ddraw7_EnumSurfaces(&ddraw->IDirectDraw7_iface, flags, 3374 surface_desc ? &surface_desc2 : NULL, &cbcontext, EnumSurfacesCallbackThunk); 3375 } 3376 3377 static HRESULT WINAPI ddraw1_EnumSurfaces(IDirectDraw *iface, DWORD flags, 3378 DDSURFACEDESC *surface_desc, void *context, LPDDENUMSURFACESCALLBACK callback) 3379 { 3380 struct ddraw *ddraw = impl_from_IDirectDraw(iface); 3381 struct surfacescallback_context cbcontext; 3382 DDSURFACEDESC2 surface_desc2; 3383 3384 TRACE("iface %p, flags %#x, surface_desc %p, context %p, callback %p.\n", 3385 iface, flags, surface_desc, context, callback); 3386 3387 cbcontext.func = callback; 3388 cbcontext.context = context; 3389 3390 if (surface_desc) DDSD_to_DDSD2(surface_desc, &surface_desc2); 3391 return ddraw7_EnumSurfaces(&ddraw->IDirectDraw7_iface, flags, 3392 surface_desc ? &surface_desc2 : NULL, &cbcontext, EnumSurfacesCallbackThunk); 3393 } 3394 3395 /***************************************************************************** 3396 * DirectDrawCreateClipper (DDRAW.@) 3397 * 3398 * Creates a new IDirectDrawClipper object. 3399 * 3400 * Params: 3401 * Clipper: Address to write the interface pointer to 3402 * UnkOuter: For aggregation support, which ddraw doesn't have. Has to be 3403 * NULL 3404 * 3405 * Returns: 3406 * CLASS_E_NOAGGREGATION if UnkOuter != NULL 3407 * E_OUTOFMEMORY if allocating the object failed 3408 * 3409 *****************************************************************************/ 3410 HRESULT WINAPI DirectDrawCreateClipper(DWORD flags, IDirectDrawClipper **clipper, IUnknown *outer_unknown) 3411 { 3412 struct ddraw_clipper *object; 3413 HRESULT hr; 3414 3415 TRACE("flags %#x, clipper %p, outer_unknown %p.\n", 3416 flags, clipper, outer_unknown); 3417 3418 if (outer_unknown) 3419 return CLASS_E_NOAGGREGATION; 3420 3421 wined3d_mutex_lock(); 3422 3423 if (!(object = heap_alloc_zero(sizeof(*object)))) 3424 { 3425 wined3d_mutex_unlock(); 3426 return E_OUTOFMEMORY; 3427 } 3428 3429 hr = ddraw_clipper_init(object); 3430 if (FAILED(hr)) 3431 { 3432 WARN("Failed to initialize clipper, hr %#x.\n", hr); 3433 heap_free(object); 3434 wined3d_mutex_unlock(); 3435 return hr; 3436 } 3437 3438 TRACE("Created clipper %p.\n", object); 3439 *clipper = &object->IDirectDrawClipper_iface; 3440 wined3d_mutex_unlock(); 3441 3442 return DD_OK; 3443 } 3444 3445 /***************************************************************************** 3446 * IDirectDraw7::CreateClipper 3447 * 3448 * Creates a DDraw clipper. See DirectDrawCreateClipper for details 3449 * 3450 *****************************************************************************/ 3451 static HRESULT WINAPI ddraw7_CreateClipper(IDirectDraw7 *iface, DWORD Flags, 3452 IDirectDrawClipper **Clipper, IUnknown *UnkOuter) 3453 { 3454 TRACE("iface %p, flags %#x, clipper %p, outer_unknown %p.\n", 3455 iface, Flags, Clipper, UnkOuter); 3456 3457 return DirectDrawCreateClipper(Flags, Clipper, UnkOuter); 3458 } 3459 3460 static HRESULT WINAPI ddraw4_CreateClipper(IDirectDraw4 *iface, DWORD flags, 3461 IDirectDrawClipper **clipper, IUnknown *outer_unknown) 3462 { 3463 struct ddraw *ddraw = impl_from_IDirectDraw4(iface); 3464 3465 TRACE("iface %p, flags %#x, clipper %p, outer_unknown %p.\n", 3466 iface, flags, clipper, outer_unknown); 3467 3468 return ddraw7_CreateClipper(&ddraw->IDirectDraw7_iface, flags, clipper, outer_unknown); 3469 } 3470 3471 static HRESULT WINAPI ddraw2_CreateClipper(IDirectDraw2 *iface, 3472 DWORD flags, IDirectDrawClipper **clipper, IUnknown *outer_unknown) 3473 { 3474 struct ddraw *ddraw = impl_from_IDirectDraw2(iface); 3475 3476 TRACE("iface %p, flags %#x, clipper %p, outer_unknown %p.\n", 3477 iface, flags, clipper, outer_unknown); 3478 3479 return ddraw7_CreateClipper(&ddraw->IDirectDraw7_iface, flags, clipper, outer_unknown); 3480 } 3481 3482 static HRESULT WINAPI ddraw1_CreateClipper(IDirectDraw *iface, 3483 DWORD flags, IDirectDrawClipper **clipper, IUnknown *outer_unknown) 3484 { 3485 struct ddraw *ddraw = impl_from_IDirectDraw(iface); 3486 3487 TRACE("iface %p, flags %#x, clipper %p, outer_unknown %p.\n", 3488 iface, flags, clipper, outer_unknown); 3489 3490 return ddraw7_CreateClipper(&ddraw->IDirectDraw7_iface, flags, clipper, outer_unknown); 3491 } 3492 3493 /***************************************************************************** 3494 * IDirectDraw7::CreatePalette 3495 * 3496 * Creates a new IDirectDrawPalette object 3497 * 3498 * Params: 3499 * Flags: The flags for the new clipper 3500 * ColorTable: Color table to assign to the new clipper 3501 * Palette: Address to write the interface pointer to 3502 * UnkOuter: For aggregation support, which ddraw doesn't have. Has to be 3503 * NULL 3504 * 3505 * Returns: 3506 * CLASS_E_NOAGGREGATION if UnkOuter != NULL 3507 * E_OUTOFMEMORY if allocating the object failed 3508 * 3509 *****************************************************************************/ 3510 static HRESULT WINAPI ddraw7_CreatePalette(IDirectDraw7 *iface, DWORD Flags, 3511 PALETTEENTRY *ColorTable, IDirectDrawPalette **Palette, IUnknown *pUnkOuter) 3512 { 3513 struct ddraw *ddraw = impl_from_IDirectDraw7(iface); 3514 struct ddraw_palette *object; 3515 HRESULT hr; 3516 3517 TRACE("iface %p, flags %#x, color_table %p, palette %p, outer_unknown %p.\n", 3518 iface, Flags, ColorTable, Palette, pUnkOuter); 3519 3520 if (pUnkOuter) 3521 return CLASS_E_NOAGGREGATION; 3522 3523 wined3d_mutex_lock(); 3524 3525 /* The refcount test shows that a cooplevel is required for this */ 3526 if (!ddraw->cooperative_level) 3527 { 3528 WARN("No cooperative level set, returning DDERR_NOCOOPERATIVELEVELSET\n"); 3529 wined3d_mutex_unlock(); 3530 return DDERR_NOCOOPERATIVELEVELSET; 3531 } 3532 3533 if (!(object = heap_alloc(sizeof(*object)))) 3534 { 3535 ERR("Out of memory when allocating memory for a palette implementation\n"); 3536 wined3d_mutex_unlock(); 3537 return E_OUTOFMEMORY; 3538 } 3539 3540 hr = ddraw_palette_init(object, ddraw, Flags, ColorTable); 3541 if (FAILED(hr)) 3542 { 3543 WARN("Failed to initialize palette, hr %#x.\n", hr); 3544 heap_free(object); 3545 wined3d_mutex_unlock(); 3546 return hr; 3547 } 3548 3549 TRACE("Created palette %p.\n", object); 3550 *Palette = &object->IDirectDrawPalette_iface; 3551 wined3d_mutex_unlock(); 3552 3553 return DD_OK; 3554 } 3555 3556 static HRESULT WINAPI ddraw4_CreatePalette(IDirectDraw4 *iface, DWORD flags, PALETTEENTRY *entries, 3557 IDirectDrawPalette **palette, IUnknown *outer_unknown) 3558 { 3559 struct ddraw *ddraw = impl_from_IDirectDraw4(iface); 3560 HRESULT hr; 3561 3562 TRACE("iface %p, flags %#x, entries %p, palette %p, outer_unknown %p.\n", 3563 iface, flags, entries, palette, outer_unknown); 3564 3565 hr = ddraw7_CreatePalette(&ddraw->IDirectDraw7_iface, flags, entries, palette, outer_unknown); 3566 if (SUCCEEDED(hr) && *palette) 3567 { 3568 struct ddraw_palette *impl = impl_from_IDirectDrawPalette(*palette); 3569 IDirectDraw7_Release(&ddraw->IDirectDraw7_iface); 3570 IDirectDraw4_AddRef(iface); 3571 impl->ifaceToRelease = (IUnknown *)iface; 3572 } 3573 return hr; 3574 } 3575 3576 static HRESULT WINAPI ddraw2_CreatePalette(IDirectDraw2 *iface, DWORD flags, 3577 PALETTEENTRY *entries, IDirectDrawPalette **palette, IUnknown *outer_unknown) 3578 { 3579 struct ddraw *ddraw = impl_from_IDirectDraw2(iface); 3580 HRESULT hr; 3581 3582 TRACE("iface %p, flags %#x, entries %p, palette %p, outer_unknown %p.\n", 3583 iface, flags, entries, palette, outer_unknown); 3584 3585 hr = ddraw7_CreatePalette(&ddraw->IDirectDraw7_iface, flags, entries, palette, outer_unknown); 3586 if (SUCCEEDED(hr) && *palette) 3587 { 3588 struct ddraw_palette *impl = impl_from_IDirectDrawPalette(*palette); 3589 IDirectDraw7_Release(&ddraw->IDirectDraw7_iface); 3590 impl->ifaceToRelease = NULL; 3591 } 3592 3593 return hr; 3594 } 3595 3596 static HRESULT WINAPI ddraw1_CreatePalette(IDirectDraw *iface, DWORD flags, 3597 PALETTEENTRY *entries, IDirectDrawPalette **palette, IUnknown *outer_unknown) 3598 { 3599 struct ddraw *ddraw = impl_from_IDirectDraw(iface); 3600 HRESULT hr; 3601 3602 TRACE("iface %p, flags %#x, entries %p, palette %p, outer_unknown %p.\n", 3603 iface, flags, entries, palette, outer_unknown); 3604 3605 hr = ddraw7_CreatePalette(&ddraw->IDirectDraw7_iface, flags, entries, palette, outer_unknown); 3606 if (SUCCEEDED(hr) && *palette) 3607 { 3608 struct ddraw_palette *impl = impl_from_IDirectDrawPalette(*palette); 3609 IDirectDraw7_Release(&ddraw->IDirectDraw7_iface); 3610 impl->ifaceToRelease = NULL; 3611 } 3612 3613 return hr; 3614 } 3615 3616 /***************************************************************************** 3617 * IDirectDraw7::DuplicateSurface 3618 * 3619 * Duplicates a surface. The surface memory points to the same memory as 3620 * the original surface, and it's released when the last surface referencing 3621 * it is released. I guess that's beyond Wine's surface management right now 3622 * (Idea: create a new DDraw surface with the same WineD3DSurface. I need a 3623 * test application to implement this) 3624 * 3625 * Params: 3626 * Src: Address of the source surface 3627 * Dest: Address to write the new surface pointer to 3628 * 3629 * Returns: 3630 * See IDirectDraw7::CreateSurface 3631 * 3632 *****************************************************************************/ 3633 static HRESULT WINAPI ddraw7_DuplicateSurface(IDirectDraw7 *iface, 3634 IDirectDrawSurface7 *Src, IDirectDrawSurface7 **Dest) 3635 { 3636 struct ddraw_surface *src_surface = unsafe_impl_from_IDirectDrawSurface7(Src); 3637 3638 FIXME("iface %p, src %p, dst %p partial stub!\n", iface, Src, Dest); 3639 3640 /* For now, simply create a new, independent surface */ 3641 return IDirectDraw7_CreateSurface(iface, &src_surface->surface_desc, Dest, NULL); 3642 } 3643 3644 static HRESULT WINAPI ddraw4_DuplicateSurface(IDirectDraw4 *iface, IDirectDrawSurface4 *src, 3645 IDirectDrawSurface4 **dst) 3646 { 3647 struct ddraw_surface *src_impl = unsafe_impl_from_IDirectDrawSurface4(src); 3648 struct ddraw *ddraw = impl_from_IDirectDraw4(iface); 3649 struct ddraw_surface *dst_impl; 3650 IDirectDrawSurface7 *dst7; 3651 HRESULT hr; 3652 3653 TRACE("iface %p, src %p, dst %p.\n", iface, src, dst); 3654 3655 hr = ddraw7_DuplicateSurface(&ddraw->IDirectDraw7_iface, 3656 src_impl ? &src_impl->IDirectDrawSurface7_iface : NULL, &dst7); 3657 if (FAILED(hr)) 3658 { 3659 *dst = NULL; 3660 return hr; 3661 } 3662 dst_impl = impl_from_IDirectDrawSurface7(dst7); 3663 *dst = &dst_impl->IDirectDrawSurface4_iface; 3664 IDirectDrawSurface4_AddRef(*dst); 3665 IDirectDrawSurface7_Release(dst7); 3666 3667 return hr; 3668 } 3669 3670 static HRESULT WINAPI ddraw2_DuplicateSurface(IDirectDraw2 *iface, 3671 IDirectDrawSurface *src, IDirectDrawSurface **dst) 3672 { 3673 struct ddraw_surface *src_impl = unsafe_impl_from_IDirectDrawSurface(src); 3674 struct ddraw *ddraw = impl_from_IDirectDraw2(iface); 3675 struct ddraw_surface *dst_impl; 3676 IDirectDrawSurface7 *dst7; 3677 HRESULT hr; 3678 3679 TRACE("iface %p, src %p, dst %p.\n", iface, src, dst); 3680 3681 hr = ddraw7_DuplicateSurface(&ddraw->IDirectDraw7_iface, 3682 src_impl ? &src_impl->IDirectDrawSurface7_iface : NULL, &dst7); 3683 if (FAILED(hr)) 3684 return hr; 3685 dst_impl = impl_from_IDirectDrawSurface7(dst7); 3686 *dst = &dst_impl->IDirectDrawSurface_iface; 3687 IDirectDrawSurface_AddRef(*dst); 3688 IDirectDrawSurface7_Release(dst7); 3689 3690 return hr; 3691 } 3692 3693 static HRESULT WINAPI ddraw1_DuplicateSurface(IDirectDraw *iface, IDirectDrawSurface *src, 3694 IDirectDrawSurface **dst) 3695 { 3696 struct ddraw_surface *src_impl = unsafe_impl_from_IDirectDrawSurface(src); 3697 struct ddraw *ddraw = impl_from_IDirectDraw(iface); 3698 struct ddraw_surface *dst_impl; 3699 IDirectDrawSurface7 *dst7; 3700 HRESULT hr; 3701 3702 TRACE("iface %p, src %p, dst %p.\n", iface, src, dst); 3703 3704 hr = ddraw7_DuplicateSurface(&ddraw->IDirectDraw7_iface, 3705 src_impl ? &src_impl->IDirectDrawSurface7_iface : NULL, &dst7); 3706 if (FAILED(hr)) 3707 return hr; 3708 dst_impl = impl_from_IDirectDrawSurface7(dst7); 3709 *dst = &dst_impl->IDirectDrawSurface_iface; 3710 IDirectDrawSurface_AddRef(*dst); 3711 IDirectDrawSurface7_Release(dst7); 3712 3713 return hr; 3714 } 3715 3716 /***************************************************************************** 3717 * IDirect3D7::EnumDevices 3718 * 3719 * The EnumDevices method for IDirect3D7. It enumerates all supported 3720 * D3D7 devices. Currently the T&L, HAL and RGB devices are enumerated. 3721 * 3722 * Params: 3723 * callback: Function to call for each enumerated device 3724 * context: Pointer to pass back to the app 3725 * 3726 * Returns: 3727 * D3D_OK, or the return value of the GetCaps call 3728 * 3729 *****************************************************************************/ 3730 static HRESULT WINAPI d3d7_EnumDevices(IDirect3D7 *iface, LPD3DENUMDEVICESCALLBACK7 callback, void *context) 3731 { 3732 struct ddraw *ddraw = impl_from_IDirect3D7(iface); 3733 D3DDEVICEDESC7 device_desc7; 3734 DWORD dev_caps; 3735 HRESULT hr; 3736 size_t i; 3737 3738 TRACE("iface %p, callback %p, context %p.\n", iface, callback, context); 3739 3740 if (!callback) 3741 return DDERR_INVALIDPARAMS; 3742 3743 wined3d_mutex_lock(); 3744 3745 if (FAILED(hr = ddraw_get_d3dcaps(ddraw, &device_desc7))) 3746 { 3747 wined3d_mutex_unlock(); 3748 return hr; 3749 } 3750 3751 dev_caps = device_desc7.dwDevCaps; 3752 3753 for (i = 0; i < ARRAY_SIZE(device_list7); i++) 3754 { 3755 HRESULT ret; 3756 3757 device_desc7.deviceGUID = *device_list7[i].device_guid; 3758 device_desc7.dwDevCaps = dev_caps & ~device_list7[i].remove_caps; 3759 3760 ret = callback(device_list7[i].interface_name, device_list7[i].device_name, &device_desc7, context); 3761 if (ret != DDENUMRET_OK) 3762 { 3763 TRACE("Application cancelled the enumeration.\n"); 3764 wined3d_mutex_unlock(); 3765 return D3D_OK; 3766 } 3767 } 3768 3769 TRACE("End of enumeration.\n"); 3770 3771 wined3d_mutex_unlock(); 3772 3773 return D3D_OK; 3774 } 3775 3776 /***************************************************************************** 3777 * IDirect3D3::EnumDevices 3778 * 3779 * Enumerates all supported Direct3DDevice interfaces. This is the 3780 * implementation for Direct3D 1 to Direc3D 3, Version 7 has its own. 3781 * 3782 * Versions 1, 2 and 3 3783 * 3784 * Params: 3785 * callback: Application-provided routine to call for each enumerated device 3786 * Context: Pointer to pass to the callback 3787 * 3788 * Returns: 3789 * D3D_OK on success, 3790 * The result of IDirect3DImpl_GetCaps if it failed 3791 * 3792 *****************************************************************************/ 3793 static HRESULT WINAPI d3d3_EnumDevices(IDirect3D3 *iface, LPD3DENUMDEVICESCALLBACK callback, void *context) 3794 { 3795 static CHAR wined3d_description[] = "Wine D3DDevice using WineD3D and OpenGL"; 3796 3797 struct ddraw *ddraw = impl_from_IDirect3D3(iface); 3798 D3DDEVICEDESC device_desc1, hal_desc, hel_desc; 3799 D3DDEVICEDESC7 device_desc7; 3800 HRESULT hr; 3801 3802 /* Some games (Motoracer 2 demo) have the bad idea to modify the device 3803 * name string. Let's put the string in a sufficiently sized array in 3804 * writable memory. */ 3805 char device_name[50]; 3806 strcpy(device_name,"Direct3D HEL"); 3807 3808 TRACE("iface %p, callback %p, context %p.\n", iface, callback, context); 3809 3810 if (!callback) 3811 return DDERR_INVALIDPARAMS; 3812 3813 wined3d_mutex_lock(); 3814 3815 if (FAILED(hr = ddraw_get_d3dcaps(ddraw, &device_desc7))) 3816 { 3817 wined3d_mutex_unlock(); 3818 return hr; 3819 } 3820 ddraw_d3dcaps1_from_7(&device_desc1, &device_desc7); 3821 3822 /* Do I have to enumerate the reference id? Note from old d3d7: 3823 * "It seems that enumerating the reference IID on Direct3D 1 games 3824 * (AvP / Motoracer2) breaks them". So do not enumerate this iid in V1 3825 * 3826 * There's a registry key HKLM\Software\Microsoft\Direct3D\Drivers, 3827 * EnumReference which enables / disables enumerating the reference 3828 * rasterizer. It's a DWORD, 0 means disabled, 2 means enabled. The 3829 * enablerefrast.reg and disablerefrast.reg files in the DirectX 7.0 sdk 3830 * demo directory suggest this. 3831 * 3832 * Some games(GTA 2) seem to use the second enumerated device, so I have 3833 * to enumerate at least 2 devices. So enumerate the reference device to 3834 * have 2 devices. 3835 * 3836 * Other games (Rollcage) tell emulation and hal device apart by certain 3837 * flags. Rollcage expects D3DPTEXTURECAPS_POW2 to be set (yeah, it is a 3838 * limitation flag), and it refuses all devices that have the perspective 3839 * flag set. This way it refuses the emulation device, and HAL devices 3840 * never have POW2 unset in d3d7 on windows. */ 3841 if (ddraw->d3dversion != 1) 3842 { 3843 static CHAR reference_description[] = "RGB Direct3D emulation"; 3844 3845 TRACE("Enumerating WineD3D D3DDevice interface.\n"); 3846 hal_desc = device_desc1; 3847 hel_desc = device_desc1; 3848 /* The rgb device has the pow2 flag set in the hel caps, but not in the hal caps. */ 3849 hal_desc.dpcLineCaps.dwTextureCaps &= ~(D3DPTEXTURECAPS_POW2 3850 | D3DPTEXTURECAPS_NONPOW2CONDITIONAL | D3DPTEXTURECAPS_PERSPECTIVE); 3851 hal_desc.dpcTriCaps.dwTextureCaps &= ~(D3DPTEXTURECAPS_POW2 3852 | D3DPTEXTURECAPS_NONPOW2CONDITIONAL | D3DPTEXTURECAPS_PERSPECTIVE); 3853 /* RGB, RAMP and MMX devices have a HAL dcmColorModel of 0 */ 3854 hal_desc.dcmColorModel = 0; 3855 /* RGB, RAMP and MMX devices cannot report HAL hardware flags */ 3856 hal_desc.dwFlags = 0; 3857 3858 hr = callback((GUID *)&IID_IDirect3DRGBDevice, reference_description, 3859 device_name, &hal_desc, &hel_desc, context); 3860 if (hr != D3DENUMRET_OK) 3861 { 3862 TRACE("Application cancelled the enumeration.\n"); 3863 wined3d_mutex_unlock(); 3864 return D3D_OK; 3865 } 3866 } 3867 3868 strcpy(device_name,"Direct3D HAL"); 3869 3870 TRACE("Enumerating HAL Direct3D device.\n"); 3871 hal_desc = device_desc1; 3872 hel_desc = device_desc1; 3873 3874 /* The hal device does not have the pow2 flag set in hel, but in hal. */ 3875 hel_desc.dpcLineCaps.dwTextureCaps &= ~(D3DPTEXTURECAPS_POW2 3876 | D3DPTEXTURECAPS_NONPOW2CONDITIONAL | D3DPTEXTURECAPS_PERSPECTIVE); 3877 hel_desc.dpcTriCaps.dwTextureCaps &= ~(D3DPTEXTURECAPS_POW2 3878 | D3DPTEXTURECAPS_NONPOW2CONDITIONAL | D3DPTEXTURECAPS_PERSPECTIVE); 3879 /* HAL devices have a HEL dcmColorModel of 0 */ 3880 hel_desc.dcmColorModel = 0; 3881 3882 hr = callback((GUID *)&IID_IDirect3DHALDevice, wined3d_description, 3883 device_name, &hal_desc, &hel_desc, context); 3884 if (hr != D3DENUMRET_OK) 3885 { 3886 TRACE("Application cancelled the enumeration.\n"); 3887 wined3d_mutex_unlock(); 3888 return D3D_OK; 3889 } 3890 3891 TRACE("End of enumeration.\n"); 3892 3893 wined3d_mutex_unlock(); 3894 3895 return D3D_OK; 3896 } 3897 3898 static HRESULT WINAPI d3d2_EnumDevices(IDirect3D2 *iface, LPD3DENUMDEVICESCALLBACK callback, void *context) 3899 { 3900 struct ddraw *ddraw = impl_from_IDirect3D2(iface); 3901 3902 TRACE("iface %p, callback %p, context %p.\n", iface, callback, context); 3903 3904 return d3d3_EnumDevices(&ddraw->IDirect3D3_iface, callback, context); 3905 } 3906 3907 static HRESULT WINAPI d3d1_EnumDevices(IDirect3D *iface, LPD3DENUMDEVICESCALLBACK callback, void *context) 3908 { 3909 struct ddraw *ddraw = impl_from_IDirect3D(iface); 3910 3911 TRACE("iface %p, callback %p, context %p.\n", iface, callback, context); 3912 3913 return d3d3_EnumDevices(&ddraw->IDirect3D3_iface, callback, context); 3914 } 3915 3916 /***************************************************************************** 3917 * IDirect3D3::CreateLight 3918 * 3919 * Creates an IDirect3DLight interface. This interface is used in 3920 * Direct3D3 or earlier for lighting. In Direct3D7 it has been replaced 3921 * by the DIRECT3DLIGHT7 structure. Wine's Direct3DLight implementation 3922 * uses the IDirect3DDevice7 interface with D3D7 lights. 3923 * 3924 * Versions 1, 2 and 3 3925 * 3926 * Params: 3927 * light: Address to store the new interface pointer 3928 * outer_unknown: Basically for aggregation, but ddraw doesn't support it. 3929 * Must be NULL 3930 * 3931 * Returns: 3932 * D3D_OK on success 3933 * DDERR_OUTOFMEMORY if memory allocation failed 3934 * CLASS_E_NOAGGREGATION if outer_unknown != NULL 3935 * 3936 *****************************************************************************/ 3937 static HRESULT WINAPI d3d3_CreateLight(IDirect3D3 *iface, IDirect3DLight **light, 3938 IUnknown *outer_unknown) 3939 { 3940 struct ddraw *ddraw = impl_from_IDirect3D3(iface); 3941 struct d3d_light *object; 3942 3943 TRACE("iface %p, light %p, outer_unknown %p.\n", iface, light, outer_unknown); 3944 3945 if (outer_unknown) 3946 return CLASS_E_NOAGGREGATION; 3947 3948 if (!(object = heap_alloc_zero(sizeof(*object)))) 3949 { 3950 ERR("Failed to allocate light memory.\n"); 3951 return DDERR_OUTOFMEMORY; 3952 } 3953 3954 d3d_light_init(object, ddraw); 3955 3956 TRACE("Created light %p.\n", object); 3957 *light = &object->IDirect3DLight_iface; 3958 3959 return D3D_OK; 3960 } 3961 3962 static HRESULT WINAPI d3d2_CreateLight(IDirect3D2 *iface, IDirect3DLight **light, IUnknown *outer_unknown) 3963 { 3964 struct ddraw *ddraw = impl_from_IDirect3D2(iface); 3965 3966 TRACE("iface %p, light %p, outer_unknown %p.\n", iface, light, outer_unknown); 3967 3968 return d3d3_CreateLight(&ddraw->IDirect3D3_iface, light, outer_unknown); 3969 } 3970 3971 static HRESULT WINAPI d3d1_CreateLight(IDirect3D *iface, IDirect3DLight **light, IUnknown *outer_unknown) 3972 { 3973 struct ddraw *ddraw = impl_from_IDirect3D(iface); 3974 3975 TRACE("iface %p, light %p, outer_unknown %p.\n", iface, light, outer_unknown); 3976 3977 return d3d3_CreateLight(&ddraw->IDirect3D3_iface, light, outer_unknown); 3978 } 3979 3980 /***************************************************************************** 3981 * IDirect3D3::CreateMaterial 3982 * 3983 * Creates an IDirect3DMaterial interface. This interface is used by Direct3D3 3984 * and older versions. The IDirect3DMaterial implementation wraps its 3985 * functionality to IDirect3DDevice7::SetMaterial and friends. 3986 * 3987 * Versions 1, 2 and 3 3988 * 3989 * Params: 3990 * material: Address to store the new interface's pointer to 3991 * outer_unknown: Basically for aggregation, but ddraw doesn't support it. 3992 * Must be NULL 3993 * 3994 * Returns: 3995 * D3D_OK on success 3996 * DDERR_OUTOFMEMORY if memory allocation failed 3997 * CLASS_E_NOAGGREGATION if outer_unknown != NULL 3998 * 3999 *****************************************************************************/ 4000 static HRESULT WINAPI d3d3_CreateMaterial(IDirect3D3 *iface, IDirect3DMaterial3 **material, 4001 IUnknown *outer_unknown) 4002 { 4003 struct ddraw *ddraw = impl_from_IDirect3D3(iface); 4004 struct d3d_material *object; 4005 4006 TRACE("iface %p, material %p, outer_unknown %p.\n", iface, material, outer_unknown); 4007 4008 if (outer_unknown) return CLASS_E_NOAGGREGATION; 4009 4010 object = d3d_material_create(ddraw); 4011 if (!object) 4012 { 4013 ERR("Failed to allocate material memory.\n"); 4014 return DDERR_OUTOFMEMORY; 4015 } 4016 4017 TRACE("Created material %p.\n", object); 4018 *material = &object->IDirect3DMaterial3_iface; 4019 4020 return D3D_OK; 4021 } 4022 4023 static HRESULT WINAPI d3d2_CreateMaterial(IDirect3D2 *iface, IDirect3DMaterial2 **material, 4024 IUnknown *outer_unknown) 4025 { 4026 struct ddraw *ddraw = impl_from_IDirect3D2(iface); 4027 struct d3d_material *object; 4028 4029 TRACE("iface %p, material %p, outer_unknown %p.\n", iface, material, outer_unknown); 4030 4031 object = d3d_material_create(ddraw); 4032 if (!object) 4033 { 4034 ERR("Failed to allocate material memory.\n"); 4035 return DDERR_OUTOFMEMORY; 4036 } 4037 4038 TRACE("Created material %p.\n", object); 4039 *material = &object->IDirect3DMaterial2_iface; 4040 4041 return D3D_OK; 4042 } 4043 4044 static HRESULT WINAPI d3d1_CreateMaterial(IDirect3D *iface, IDirect3DMaterial **material, 4045 IUnknown *outer_unknown) 4046 { 4047 struct ddraw *ddraw = impl_from_IDirect3D(iface); 4048 struct d3d_material *object; 4049 4050 TRACE("iface %p, material %p, outer_unknown %p.\n", iface, material, outer_unknown); 4051 4052 object = d3d_material_create(ddraw); 4053 if (!object) 4054 { 4055 ERR("Failed to allocate material memory.\n"); 4056 return DDERR_OUTOFMEMORY; 4057 } 4058 4059 TRACE("Created material %p.\n", object); 4060 *material = &object->IDirect3DMaterial_iface; 4061 4062 return D3D_OK; 4063 } 4064 4065 /***************************************************************************** 4066 * IDirect3D3::CreateViewport 4067 * 4068 * Creates an IDirect3DViewport interface. This interface is used 4069 * by Direct3D and earlier versions for Viewport management. In Direct3D7 4070 * it has been replaced by a viewport structure and 4071 * IDirect3DDevice7::*Viewport. Wine's IDirect3DViewport implementation 4072 * uses the IDirect3DDevice7 methods for its functionality 4073 * 4074 * Params: 4075 * Viewport: Address to store the new interface pointer 4076 * outer_unknown: Basically for aggregation, but ddraw doesn't support it. 4077 * Must be NULL 4078 * 4079 * Returns: 4080 * D3D_OK on success 4081 * DDERR_OUTOFMEMORY if memory allocation failed 4082 * CLASS_E_NOAGGREGATION if outer_unknown != NULL 4083 * 4084 *****************************************************************************/ 4085 static HRESULT WINAPI d3d3_CreateViewport(IDirect3D3 *iface, IDirect3DViewport3 **viewport, 4086 IUnknown *outer_unknown) 4087 { 4088 struct ddraw *ddraw = impl_from_IDirect3D3(iface); 4089 struct d3d_viewport *object; 4090 4091 TRACE("iface %p, viewport %p, outer_unknown %p.\n", iface, viewport, outer_unknown); 4092 4093 if (outer_unknown) return CLASS_E_NOAGGREGATION; 4094 4095 if (!(object = heap_alloc_zero(sizeof(*object)))) 4096 { 4097 ERR("Failed to allocate viewport memory.\n"); 4098 return DDERR_OUTOFMEMORY; 4099 } 4100 4101 d3d_viewport_init(object, ddraw); 4102 4103 TRACE("Created viewport %p.\n", object); 4104 *viewport = &object->IDirect3DViewport3_iface; 4105 4106 return D3D_OK; 4107 } 4108 4109 static HRESULT WINAPI d3d2_CreateViewport(IDirect3D2 *iface, IDirect3DViewport2 **viewport, IUnknown *outer_unknown) 4110 { 4111 struct ddraw *ddraw = impl_from_IDirect3D2(iface); 4112 4113 TRACE("iface %p, viewport %p, outer_unknown %p.\n", iface, viewport, outer_unknown); 4114 4115 return d3d3_CreateViewport(&ddraw->IDirect3D3_iface, (IDirect3DViewport3 **)viewport, 4116 outer_unknown); 4117 } 4118 4119 static HRESULT WINAPI d3d1_CreateViewport(IDirect3D *iface, IDirect3DViewport **viewport, IUnknown *outer_unknown) 4120 { 4121 struct ddraw *ddraw = impl_from_IDirect3D(iface); 4122 4123 TRACE("iface %p, viewport %p, outer_unknown %p.\n", iface, viewport, outer_unknown); 4124 4125 return d3d3_CreateViewport(&ddraw->IDirect3D3_iface, (IDirect3DViewport3 **)viewport, 4126 outer_unknown); 4127 } 4128 4129 /***************************************************************************** 4130 * IDirect3D3::FindDevice 4131 * 4132 * This method finds a device with the requested properties and returns a 4133 * device description 4134 * 4135 * Versions 1, 2 and 3 4136 * Params: 4137 * fds: Describes the requested device characteristics 4138 * fdr: Returns the device description 4139 * 4140 * Returns: 4141 * D3D_OK on success 4142 * DDERR_INVALIDPARAMS if no device was found 4143 * 4144 *****************************************************************************/ 4145 static HRESULT WINAPI d3d3_FindDevice(IDirect3D3 *iface, D3DFINDDEVICESEARCH *fds, D3DFINDDEVICERESULT *fdr) 4146 { 4147 struct ddraw *ddraw = impl_from_IDirect3D3(iface); 4148 D3DDEVICEDESC7 desc7; 4149 D3DDEVICEDESC desc1; 4150 HRESULT hr; 4151 4152 TRACE("iface %p, fds %p, fdr %p.\n", iface, fds, fdr); 4153 4154 if (!fds || !fdr) return DDERR_INVALIDPARAMS; 4155 4156 if (fds->dwSize != sizeof(D3DFINDDEVICESEARCH) || (fdr->dwSize != sizeof(D3DFINDDEVICERESULT1) && 4157 fdr->dwSize != sizeof(D3DFINDDEVICERESULT2) && fdr->dwSize != sizeof(D3DFINDDEVICERESULT))) 4158 return DDERR_INVALIDPARAMS; 4159 4160 if ((fds->dwFlags & D3DFDS_COLORMODEL) 4161 && fds->dcmColorModel != D3DCOLOR_RGB) 4162 { 4163 WARN("Trying to request a non-RGB D3D color model. Not supported.\n"); 4164 return DDERR_INVALIDPARAMS; /* No real idea what to return here :-) */ 4165 } 4166 4167 if (fds->dwFlags & D3DFDS_GUID) 4168 { 4169 TRACE("Trying to match guid %s.\n", debugstr_guid(&(fds->guid))); 4170 if (!IsEqualGUID(&IID_D3DDEVICE_WineD3D, &fds->guid) 4171 && !IsEqualGUID(&IID_IDirect3DHALDevice, &fds->guid) 4172 && !IsEqualGUID(&IID_IDirect3DRGBDevice, &fds->guid)) 4173 { 4174 WARN("No match for this GUID.\n"); 4175 return DDERR_NOTFOUND; 4176 } 4177 } 4178 4179 /* Get the caps */ 4180 if (FAILED(hr = ddraw_get_d3dcaps(ddraw, &desc7))) 4181 return hr; 4182 4183 /* Now return our own GUID */ 4184 ddraw_d3dcaps1_from_7(&desc1, &desc7); 4185 fdr->guid = IID_D3DDEVICE_WineD3D; 4186 4187 if (fdr->dwSize == sizeof(D3DFINDDEVICERESULT1)) 4188 { 4189 D3DFINDDEVICERESULT1 *fdr1 = (D3DFINDDEVICERESULT1 *)fdr; 4190 memcpy(&fdr1->ddHwDesc, &desc1, sizeof(fdr1->ddHwDesc)); 4191 memcpy(&fdr1->ddSwDesc, &desc1, sizeof(fdr1->ddSwDesc)); 4192 } 4193 else if (fdr->dwSize == sizeof(D3DFINDDEVICERESULT2)) 4194 { 4195 D3DFINDDEVICERESULT2 *fdr2 = (D3DFINDDEVICERESULT2 *)fdr; 4196 memcpy(&fdr2->ddHwDesc, &desc1, sizeof(fdr2->ddHwDesc)); 4197 memcpy(&fdr2->ddSwDesc, &desc1, sizeof(fdr2->ddSwDesc)); 4198 } 4199 else 4200 { 4201 fdr->ddHwDesc = desc1; 4202 fdr->ddSwDesc = desc1; 4203 } 4204 4205 TRACE("Returning Wine's wined3d device with (undumped) capabilities.\n"); 4206 4207 return D3D_OK; 4208 } 4209 4210 static HRESULT WINAPI d3d2_FindDevice(IDirect3D2 *iface, D3DFINDDEVICESEARCH *fds, D3DFINDDEVICERESULT *fdr) 4211 { 4212 struct ddraw *ddraw = impl_from_IDirect3D2(iface); 4213 4214 TRACE("iface %p, fds %p, fdr %p.\n", iface, fds, fdr); 4215 4216 return d3d3_FindDevice(&ddraw->IDirect3D3_iface, fds, fdr); 4217 } 4218 4219 static HRESULT WINAPI d3d1_FindDevice(IDirect3D *iface, D3DFINDDEVICESEARCH *fds, D3DFINDDEVICERESULT *fdr) 4220 { 4221 struct ddraw *ddraw = impl_from_IDirect3D(iface); 4222 4223 TRACE("iface %p, fds %p, fdr %p.\n", iface, fds, fdr); 4224 4225 return d3d3_FindDevice(&ddraw->IDirect3D3_iface, fds, fdr); 4226 } 4227 4228 /***************************************************************************** 4229 * IDirect3D7::CreateDevice 4230 * 4231 * Creates an IDirect3DDevice7 interface. 4232 * 4233 * Versions 2, 3 and 7. IDirect3DDevice 1 interfaces are interfaces to 4234 * DirectDraw surfaces and are created with 4235 * IDirectDrawSurface::QueryInterface. This method uses CreateDevice to 4236 * create the device object and QueryInterfaces for IDirect3DDevice 4237 * 4238 * Params: 4239 * refiid: IID of the device to create 4240 * Surface: Initial rendertarget 4241 * Device: Address to return the interface pointer 4242 * 4243 * Returns: 4244 * D3D_OK on success 4245 * DDERR_OUTOFMEMORY if memory allocation failed 4246 * DDERR_INVALIDPARAMS if a device exists already 4247 * 4248 *****************************************************************************/ 4249 static HRESULT WINAPI d3d7_CreateDevice(IDirect3D7 *iface, REFCLSID riid, 4250 IDirectDrawSurface7 *surface, IDirect3DDevice7 **device) 4251 { 4252 struct ddraw_surface *target = unsafe_impl_from_IDirectDrawSurface7(surface); 4253 struct ddraw *ddraw = impl_from_IDirect3D7(iface); 4254 struct d3d_device *object; 4255 HRESULT hr; 4256 4257 TRACE("iface %p, riid %s, surface %p, device %p.\n", iface, debugstr_guid(riid), surface, device); 4258 4259 wined3d_mutex_lock(); 4260 if (SUCCEEDED(hr = d3d_device_create(ddraw, riid, target, (IUnknown *)surface, 7, &object, NULL))) 4261 { 4262 *device = &object->IDirect3DDevice7_iface; 4263 } 4264 else 4265 { 4266 WARN("Failed to create device, hr %#x.\n", hr); 4267 *device = NULL; 4268 } 4269 wined3d_mutex_unlock(); 4270 4271 return hr; 4272 } 4273 4274 static HRESULT WINAPI d3d3_CreateDevice(IDirect3D3 *iface, REFCLSID riid, 4275 IDirectDrawSurface4 *surface, IDirect3DDevice3 **device, IUnknown *outer_unknown) 4276 { 4277 struct ddraw_surface *surface_impl = unsafe_impl_from_IDirectDrawSurface4(surface); 4278 struct ddraw *ddraw = impl_from_IDirect3D3(iface); 4279 struct d3d_device *device_impl; 4280 HRESULT hr; 4281 4282 TRACE("iface %p, riid %s, surface %p, device %p, outer_unknown %p.\n", 4283 iface, debugstr_guid(riid), surface, device, outer_unknown); 4284 4285 if (outer_unknown) 4286 return CLASS_E_NOAGGREGATION; 4287 4288 wined3d_mutex_lock(); 4289 if (SUCCEEDED(hr = d3d_device_create(ddraw, riid, surface_impl, (IUnknown *)surface, 3, &device_impl, NULL))) 4290 { 4291 *device = &device_impl->IDirect3DDevice3_iface; 4292 } 4293 else 4294 { 4295 WARN("Failed to create device, hr %#x.\n", hr); 4296 *device = NULL; 4297 } 4298 wined3d_mutex_unlock(); 4299 4300 return hr; 4301 } 4302 4303 static HRESULT WINAPI d3d2_CreateDevice(IDirect3D2 *iface, REFCLSID riid, 4304 IDirectDrawSurface *surface, IDirect3DDevice2 **device) 4305 { 4306 struct ddraw_surface *surface_impl = unsafe_impl_from_IDirectDrawSurface(surface); 4307 struct ddraw *ddraw = impl_from_IDirect3D2(iface); 4308 struct d3d_device *device_impl; 4309 HRESULT hr; 4310 4311 TRACE("iface %p, riid %s, surface %p, device %p.\n", 4312 iface, debugstr_guid(riid), surface, device); 4313 4314 wined3d_mutex_lock(); 4315 if (SUCCEEDED(hr = d3d_device_create(ddraw, riid, surface_impl, (IUnknown *)surface, 2, &device_impl, NULL))) 4316 { 4317 *device = &device_impl->IDirect3DDevice2_iface; 4318 } 4319 else 4320 { 4321 WARN("Failed to create device, hr %#x.\n", hr); 4322 *device = NULL; 4323 } 4324 wined3d_mutex_unlock(); 4325 4326 return hr; 4327 } 4328 4329 /***************************************************************************** 4330 * IDirect3D7::CreateVertexBuffer 4331 * 4332 * Creates a new vertex buffer object and returns a IDirect3DVertexBuffer7 4333 * interface. 4334 * 4335 * Versions 3 and 7 4336 * 4337 * Params: 4338 * desc: Requested Vertex buffer properties 4339 * vertex_buffer: Address to return the interface pointer at 4340 * flags: Some flags, should be 0 4341 * 4342 * Returns 4343 * D3D_OK on success 4344 * DDERR_OUTOFMEMORY if memory allocation failed 4345 * DDERR_INVALIDPARAMS if desc or vertex_buffer is NULL 4346 * 4347 *****************************************************************************/ 4348 static HRESULT WINAPI d3d7_CreateVertexBuffer(IDirect3D7 *iface, D3DVERTEXBUFFERDESC *desc, 4349 IDirect3DVertexBuffer7 **vertex_buffer, DWORD flags) 4350 { 4351 struct ddraw *ddraw = impl_from_IDirect3D7(iface); 4352 struct d3d_vertex_buffer *object; 4353 HRESULT hr; 4354 4355 TRACE("iface %p, desc %p, vertex_buffer %p, flags %#x.\n", 4356 iface, desc, vertex_buffer, flags); 4357 4358 if (!vertex_buffer || !desc) return DDERR_INVALIDPARAMS; 4359 4360 hr = d3d_vertex_buffer_create(&object, ddraw, desc); 4361 if (hr == D3D_OK) 4362 { 4363 TRACE("Created vertex buffer %p.\n", object); 4364 *vertex_buffer = &object->IDirect3DVertexBuffer7_iface; 4365 } 4366 else 4367 WARN("Failed to create vertex buffer, hr %#x.\n", hr); 4368 4369 return hr; 4370 } 4371 4372 static HRESULT WINAPI d3d3_CreateVertexBuffer(IDirect3D3 *iface, D3DVERTEXBUFFERDESC *desc, 4373 IDirect3DVertexBuffer **vertex_buffer, DWORD flags, IUnknown *outer_unknown) 4374 { 4375 struct ddraw *ddraw = impl_from_IDirect3D3(iface); 4376 struct d3d_vertex_buffer *object; 4377 HRESULT hr; 4378 4379 TRACE("iface %p, desc %p, vertex_buffer %p, flags %#x, outer_unknown %p.\n", 4380 iface, desc, vertex_buffer, flags, outer_unknown); 4381 4382 if (outer_unknown) 4383 return CLASS_E_NOAGGREGATION; 4384 if (!vertex_buffer || !desc) 4385 return DDERR_INVALIDPARAMS; 4386 4387 hr = d3d_vertex_buffer_create(&object, ddraw, desc); 4388 if (hr == D3D_OK) 4389 { 4390 TRACE("Created vertex buffer %p.\n", object); 4391 *vertex_buffer = (IDirect3DVertexBuffer *)&object->IDirect3DVertexBuffer7_iface; 4392 } 4393 else 4394 WARN("Failed to create vertex buffer, hr %#x.\n", hr); 4395 4396 return hr; 4397 } 4398 4399 /***************************************************************************** 4400 * IDirect3D7::EnumZBufferFormats 4401 * 4402 * Enumerates all supported Z buffer pixel formats 4403 * 4404 * Versions 3 and 7 4405 * 4406 * Params: 4407 * device_iid: 4408 * callback: callback to call for each pixel format 4409 * context: Pointer to pass back to the callback 4410 * 4411 * Returns: 4412 * D3D_OK on success 4413 * DDERR_INVALIDPARAMS if callback is NULL 4414 * 4415 *****************************************************************************/ 4416 static HRESULT WINAPI d3d7_EnumZBufferFormats(IDirect3D7 *iface, REFCLSID device_iid, 4417 LPD3DENUMPIXELFORMATSCALLBACK callback, void *context) 4418 { 4419 struct ddraw *ddraw = impl_from_IDirect3D7(iface); 4420 struct wined3d_display_mode mode; 4421 enum wined3d_device_type type; 4422 unsigned int i; 4423 HRESULT hr; 4424 4425 /* Order matters. Specifically, BattleZone II (full version) expects the 4426 * 16-bit depth formats to be listed before the 24 and 32 ones. */ 4427 static const enum wined3d_format_id formats[] = 4428 { 4429 WINED3DFMT_S1_UINT_D15_UNORM, 4430 WINED3DFMT_D16_UNORM, 4431 WINED3DFMT_X8D24_UNORM, 4432 WINED3DFMT_S4X4_UINT_D24_UNORM, 4433 WINED3DFMT_D24_UNORM_S8_UINT, 4434 WINED3DFMT_D32_UNORM, 4435 }; 4436 4437 TRACE("iface %p, device_iid %s, callback %p, context %p.\n", 4438 iface, debugstr_guid(device_iid), callback, context); 4439 4440 if (!callback) return DDERR_INVALIDPARAMS; 4441 4442 if (IsEqualGUID(device_iid, &IID_IDirect3DHALDevice) 4443 || IsEqualGUID(device_iid, &IID_IDirect3DTnLHalDevice) 4444 || IsEqualGUID(device_iid, &IID_D3DDEVICE_WineD3D)) 4445 { 4446 TRACE("Asked for HAL device.\n"); 4447 type = WINED3D_DEVICE_TYPE_HAL; 4448 } 4449 else if (IsEqualGUID(device_iid, &IID_IDirect3DRGBDevice) 4450 || IsEqualGUID(device_iid, &IID_IDirect3DMMXDevice)) 4451 { 4452 TRACE("Asked for SW device.\n"); 4453 type = WINED3D_DEVICE_TYPE_SW; 4454 } 4455 else if (IsEqualGUID(device_iid, &IID_IDirect3DRefDevice)) 4456 { 4457 TRACE("Asked for REF device.\n"); 4458 type = WINED3D_DEVICE_TYPE_REF; 4459 } 4460 else if (IsEqualGUID(device_iid, &IID_IDirect3DNullDevice)) 4461 { 4462 TRACE("Asked for NULLREF device.\n"); 4463 type = WINED3D_DEVICE_TYPE_NULLREF; 4464 } 4465 else 4466 { 4467 FIXME("Unexpected device GUID %s.\n", debugstr_guid(device_iid)); 4468 type = WINED3D_DEVICE_TYPE_HAL; 4469 } 4470 4471 wined3d_mutex_lock(); 4472 /* We need an adapter format from somewhere to please wined3d and WGL. 4473 * Use the current display mode. So far all cards offer the same depth 4474 * stencil format for all modes, but if some do not and applications do 4475 * not like that we'll have to find some workaround, like iterating over 4476 * all imaginable formats and collecting all the depth stencil formats we 4477 * can get. */ 4478 if (FAILED(hr = wined3d_get_adapter_display_mode(ddraw->wined3d, WINED3DADAPTER_DEFAULT, &mode, NULL))) 4479 { 4480 ERR("Failed to get display mode, hr %#x.\n", hr); 4481 wined3d_mutex_unlock(); 4482 return hr; 4483 } 4484 4485 for (i = 0; i < ARRAY_SIZE(formats); ++i) 4486 { 4487 if (SUCCEEDED(wined3d_check_device_format(ddraw->wined3d, WINED3DADAPTER_DEFAULT, type, mode.format_id, 4488 WINED3DUSAGE_DEPTHSTENCIL, WINED3D_RTYPE_TEXTURE_2D, formats[i]))) 4489 { 4490 DDPIXELFORMAT pformat; 4491 4492 memset(&pformat, 0, sizeof(pformat)); 4493 pformat.dwSize = sizeof(pformat); 4494 ddrawformat_from_wined3dformat(&pformat, formats[i]); 4495 4496 TRACE("Enumerating wined3d format %#x.\n", formats[i]); 4497 hr = callback(&pformat, context); 4498 if (hr != DDENUMRET_OK) 4499 { 4500 TRACE("Format enumeration cancelled by application.\n"); 4501 wined3d_mutex_unlock(); 4502 return D3D_OK; 4503 } 4504 } 4505 } 4506 4507 /* Historically some windows drivers used dwZBufferBitDepth=24 for WINED3DFMT_X8D24_UNORM, 4508 * while others used dwZBufferBitDepth=32. In either case the pitch matches a 32 bits per 4509 * pixel format, so we use dwZBufferBitDepth=32. Some games expect 24. Windows Vista and 4510 * newer enumerate both versions, so we do the same(bug 22434) */ 4511 if (SUCCEEDED(wined3d_check_device_format(ddraw->wined3d, WINED3DADAPTER_DEFAULT, type, mode.format_id, 4512 WINED3DUSAGE_DEPTHSTENCIL, WINED3D_RTYPE_TEXTURE_2D, WINED3DFMT_X8D24_UNORM))) 4513 { 4514 DDPIXELFORMAT x8d24 = 4515 { 4516 sizeof(x8d24), DDPF_ZBUFFER, 0, 4517 {24}, {0x00000000}, {0x00ffffff}, {0x00000000} 4518 }; 4519 TRACE("Enumerating WINED3DFMT_X8D24_UNORM, dwZBufferBitDepth=24 version\n"); 4520 callback(&x8d24, context); 4521 } 4522 4523 TRACE("End of enumeration.\n"); 4524 4525 wined3d_mutex_unlock(); 4526 4527 return D3D_OK; 4528 } 4529 4530 static HRESULT WINAPI d3d3_EnumZBufferFormats(IDirect3D3 *iface, REFCLSID device_iid, 4531 LPD3DENUMPIXELFORMATSCALLBACK callback, void *context) 4532 { 4533 struct ddraw *ddraw = impl_from_IDirect3D3(iface); 4534 4535 TRACE("iface %p, device_iid %s, callback %p, context %p.\n", 4536 iface, debugstr_guid(device_iid), callback, context); 4537 4538 return d3d7_EnumZBufferFormats(&ddraw->IDirect3D7_iface, device_iid, callback, context); 4539 } 4540 4541 /***************************************************************************** 4542 * IDirect3D7::EvictManagedTextures 4543 * 4544 * Removes all managed textures (=surfaces with DDSCAPS2_TEXTUREMANAGE or 4545 * DDSCAPS2_D3DTEXTUREMANAGE caps) to be removed from video memory. 4546 * 4547 * Versions 3 and 7 4548 * 4549 * Returns: 4550 * D3D_OK, because it's a stub 4551 * 4552 *****************************************************************************/ 4553 static HRESULT WINAPI d3d7_EvictManagedTextures(IDirect3D7 *iface) 4554 { 4555 struct ddraw *ddraw = impl_from_IDirect3D7(iface); 4556 4557 TRACE("iface %p!\n", iface); 4558 4559 wined3d_mutex_lock(); 4560 if (ddraw->flags & DDRAW_D3D_INITIALIZED) 4561 wined3d_device_evict_managed_resources(ddraw->wined3d_device); 4562 wined3d_mutex_unlock(); 4563 4564 return D3D_OK; 4565 } 4566 4567 static HRESULT WINAPI d3d3_EvictManagedTextures(IDirect3D3 *iface) 4568 { 4569 struct ddraw *ddraw = impl_from_IDirect3D3(iface); 4570 4571 TRACE("iface %p.\n", iface); 4572 4573 return d3d7_EvictManagedTextures(&ddraw->IDirect3D7_iface); 4574 } 4575 4576 /***************************************************************************** 4577 * IDirectDraw7 VTable 4578 *****************************************************************************/ 4579 static const struct IDirectDraw7Vtbl ddraw7_vtbl = 4580 { 4581 /* IUnknown */ 4582 ddraw7_QueryInterface, 4583 ddraw7_AddRef, 4584 ddraw7_Release, 4585 /* IDirectDraw */ 4586 ddraw7_Compact, 4587 ddraw7_CreateClipper, 4588 ddraw7_CreatePalette, 4589 ddraw7_CreateSurface, 4590 ddraw7_DuplicateSurface, 4591 ddraw7_EnumDisplayModes, 4592 ddraw7_EnumSurfaces, 4593 ddraw7_FlipToGDISurface, 4594 ddraw7_GetCaps, 4595 ddraw7_GetDisplayMode, 4596 ddraw7_GetFourCCCodes, 4597 ddraw7_GetGDISurface, 4598 ddraw7_GetMonitorFrequency, 4599 ddraw7_GetScanLine, 4600 ddraw7_GetVerticalBlankStatus, 4601 ddraw7_Initialize, 4602 ddraw7_RestoreDisplayMode, 4603 ddraw7_SetCooperativeLevel, 4604 ddraw7_SetDisplayMode, 4605 ddraw7_WaitForVerticalBlank, 4606 /* IDirectDraw2 */ 4607 ddraw7_GetAvailableVidMem, 4608 /* IDirectDraw3 */ 4609 ddraw7_GetSurfaceFromDC, 4610 /* IDirectDraw4 */ 4611 ddraw7_RestoreAllSurfaces, 4612 ddraw7_TestCooperativeLevel, 4613 ddraw7_GetDeviceIdentifier, 4614 /* IDirectDraw7 */ 4615 ddraw7_StartModeTest, 4616 ddraw7_EvaluateMode 4617 }; 4618 4619 static const struct IDirectDraw4Vtbl ddraw4_vtbl = 4620 { 4621 /* IUnknown */ 4622 ddraw4_QueryInterface, 4623 ddraw4_AddRef, 4624 ddraw4_Release, 4625 /* IDirectDraw */ 4626 ddraw4_Compact, 4627 ddraw4_CreateClipper, 4628 ddraw4_CreatePalette, 4629 ddraw4_CreateSurface, 4630 ddraw4_DuplicateSurface, 4631 ddraw4_EnumDisplayModes, 4632 ddraw4_EnumSurfaces, 4633 ddraw4_FlipToGDISurface, 4634 ddraw4_GetCaps, 4635 ddraw4_GetDisplayMode, 4636 ddraw4_GetFourCCCodes, 4637 ddraw4_GetGDISurface, 4638 ddraw4_GetMonitorFrequency, 4639 ddraw4_GetScanLine, 4640 ddraw4_GetVerticalBlankStatus, 4641 ddraw4_Initialize, 4642 ddraw4_RestoreDisplayMode, 4643 ddraw4_SetCooperativeLevel, 4644 ddraw4_SetDisplayMode, 4645 ddraw4_WaitForVerticalBlank, 4646 /* IDirectDraw2 */ 4647 ddraw4_GetAvailableVidMem, 4648 /* IDirectDraw3 */ 4649 ddraw4_GetSurfaceFromDC, 4650 /* IDirectDraw4 */ 4651 ddraw4_RestoreAllSurfaces, 4652 ddraw4_TestCooperativeLevel, 4653 ddraw4_GetDeviceIdentifier, 4654 }; 4655 4656 static const struct IDirectDraw2Vtbl ddraw2_vtbl = 4657 { 4658 /* IUnknown */ 4659 ddraw2_QueryInterface, 4660 ddraw2_AddRef, 4661 ddraw2_Release, 4662 /* IDirectDraw */ 4663 ddraw2_Compact, 4664 ddraw2_CreateClipper, 4665 ddraw2_CreatePalette, 4666 ddraw2_CreateSurface, 4667 ddraw2_DuplicateSurface, 4668 ddraw2_EnumDisplayModes, 4669 ddraw2_EnumSurfaces, 4670 ddraw2_FlipToGDISurface, 4671 ddraw2_GetCaps, 4672 ddraw2_GetDisplayMode, 4673 ddraw2_GetFourCCCodes, 4674 ddraw2_GetGDISurface, 4675 ddraw2_GetMonitorFrequency, 4676 ddraw2_GetScanLine, 4677 ddraw2_GetVerticalBlankStatus, 4678 ddraw2_Initialize, 4679 ddraw2_RestoreDisplayMode, 4680 ddraw2_SetCooperativeLevel, 4681 ddraw2_SetDisplayMode, 4682 ddraw2_WaitForVerticalBlank, 4683 /* IDirectDraw2 */ 4684 ddraw2_GetAvailableVidMem, 4685 }; 4686 4687 static struct IDirectDrawVtbl ddraw1_vtbl = 4688 { 4689 /* IUnknown */ 4690 ddraw1_QueryInterface, 4691 ddraw1_AddRef, 4692 ddraw1_Release, 4693 /* IDirectDraw */ 4694 ddraw1_Compact, 4695 ddraw1_CreateClipper, 4696 ddraw1_CreatePalette, 4697 ddraw1_CreateSurface, 4698 ddraw1_DuplicateSurface, 4699 ddraw1_EnumDisplayModes, 4700 ddraw1_EnumSurfaces, 4701 ddraw1_FlipToGDISurface, 4702 ddraw1_GetCaps, 4703 ddraw1_GetDisplayMode, 4704 ddraw1_GetFourCCCodes, 4705 ddraw1_GetGDISurface, 4706 ddraw1_GetMonitorFrequency, 4707 ddraw1_GetScanLine, 4708 ddraw1_GetVerticalBlankStatus, 4709 ddraw1_Initialize, 4710 ddraw1_RestoreDisplayMode, 4711 ddraw1_SetCooperativeLevel, 4712 ddraw1_SetDisplayMode, 4713 ddraw1_WaitForVerticalBlank, 4714 }; 4715 4716 static const struct IDirect3D7Vtbl d3d7_vtbl = 4717 { 4718 /* IUnknown methods */ 4719 d3d7_QueryInterface, 4720 d3d7_AddRef, 4721 d3d7_Release, 4722 /* IDirect3D7 methods */ 4723 d3d7_EnumDevices, 4724 d3d7_CreateDevice, 4725 d3d7_CreateVertexBuffer, 4726 d3d7_EnumZBufferFormats, 4727 d3d7_EvictManagedTextures 4728 }; 4729 4730 static const struct IDirect3D3Vtbl d3d3_vtbl = 4731 { 4732 /* IUnknown methods */ 4733 d3d3_QueryInterface, 4734 d3d3_AddRef, 4735 d3d3_Release, 4736 /* IDirect3D3 methods */ 4737 d3d3_EnumDevices, 4738 d3d3_CreateLight, 4739 d3d3_CreateMaterial, 4740 d3d3_CreateViewport, 4741 d3d3_FindDevice, 4742 d3d3_CreateDevice, 4743 d3d3_CreateVertexBuffer, 4744 d3d3_EnumZBufferFormats, 4745 d3d3_EvictManagedTextures 4746 }; 4747 4748 static const struct IDirect3D2Vtbl d3d2_vtbl = 4749 { 4750 /* IUnknown methods */ 4751 d3d2_QueryInterface, 4752 d3d2_AddRef, 4753 d3d2_Release, 4754 /* IDirect3D2 methods */ 4755 d3d2_EnumDevices, 4756 d3d2_CreateLight, 4757 d3d2_CreateMaterial, 4758 d3d2_CreateViewport, 4759 d3d2_FindDevice, 4760 d3d2_CreateDevice 4761 }; 4762 4763 static const struct IDirect3DVtbl d3d1_vtbl = 4764 { 4765 /* IUnknown methods */ 4766 d3d1_QueryInterface, 4767 d3d1_AddRef, 4768 d3d1_Release, 4769 /* IDirect3D methods */ 4770 d3d1_Initialize, 4771 d3d1_EnumDevices, 4772 d3d1_CreateLight, 4773 d3d1_CreateMaterial, 4774 d3d1_CreateViewport, 4775 d3d1_FindDevice 4776 }; 4777 4778 /***************************************************************************** 4779 * ddraw_find_decl 4780 * 4781 * Finds the WineD3D vertex declaration for a specific fvf, and creates one 4782 * if none was found. 4783 * 4784 * This function is in ddraw.c and the DDraw object space because D3D7 4785 * vertex buffers are created using the IDirect3D interface to the ddraw 4786 * object, so they can be valid across D3D devices(theoretically. The ddraw 4787 * object also owns the wined3d device 4788 * 4789 * Parameters: 4790 * This: Device 4791 * fvf: Fvf to find the decl for 4792 * 4793 * Returns: 4794 * NULL in case of an error, the vertex declaration for the FVF otherwise. 4795 * 4796 *****************************************************************************/ 4797 struct wined3d_vertex_declaration *ddraw_find_decl(struct ddraw *This, DWORD fvf) 4798 { 4799 struct wined3d_vertex_declaration *pDecl = NULL; 4800 HRESULT hr; 4801 int p, low, high; /* deliberately signed */ 4802 struct FvfToDecl *convertedDecls = This->decls; 4803 4804 TRACE("Searching for declaration for fvf %08x... ", fvf); 4805 4806 low = 0; 4807 high = This->numConvertedDecls - 1; 4808 while(low <= high) { 4809 p = (low + high) >> 1; 4810 TRACE("%d ", p); 4811 if(convertedDecls[p].fvf == fvf) { 4812 TRACE("found %p\n", convertedDecls[p].decl); 4813 return convertedDecls[p].decl; 4814 } else if(convertedDecls[p].fvf < fvf) { 4815 low = p + 1; 4816 } else { 4817 high = p - 1; 4818 } 4819 } 4820 TRACE("not found. Creating and inserting at position %d.\n", low); 4821 4822 hr = wined3d_vertex_declaration_create_from_fvf(This->wined3d_device, 4823 fvf, This, &ddraw_null_wined3d_parent_ops, &pDecl); 4824 if (hr != S_OK) return NULL; 4825 4826 if (This->declArraySize == This->numConvertedDecls) 4827 { 4828 unsigned int grow = max(This->declArraySize / 2, 8); 4829 4830 if (!(convertedDecls = heap_realloc(convertedDecls, 4831 (This->numConvertedDecls + grow) * sizeof(*convertedDecls)))) 4832 { 4833 wined3d_vertex_declaration_decref(pDecl); 4834 return NULL; 4835 } 4836 This->decls = convertedDecls; 4837 This->declArraySize += grow; 4838 } 4839 4840 memmove(convertedDecls + low + 1, convertedDecls + low, sizeof(convertedDecls[0]) * (This->numConvertedDecls - low)); 4841 convertedDecls[low].decl = pDecl; 4842 convertedDecls[low].fvf = fvf; 4843 This->numConvertedDecls++; 4844 4845 TRACE("Returning %p. %d decls in array\n", pDecl, This->numConvertedDecls); 4846 return pDecl; 4847 } 4848 4849 static inline struct ddraw *ddraw_from_device_parent(struct wined3d_device_parent *device_parent) 4850 { 4851 return CONTAINING_RECORD(device_parent, struct ddraw, device_parent); 4852 } 4853 4854 static void CDECL device_parent_wined3d_device_created(struct wined3d_device_parent *device_parent, 4855 struct wined3d_device *device) 4856 { 4857 TRACE("device_parent %p, device %p.\n", device_parent, device); 4858 } 4859 4860 /* This is run from device_process_message() in wined3d, we can't take the 4861 * wined3d mutex. */ 4862 /* FIXME: We only get mode change notifications in exclusive mode, but we 4863 * should mark surfaces as lost on mode changes in DDSCL_NORMAL mode as well. */ 4864 static void CDECL device_parent_mode_changed(struct wined3d_device_parent *device_parent) 4865 { 4866 struct ddraw *ddraw = ddraw_from_device_parent(device_parent); 4867 MONITORINFO monitor_info; 4868 HMONITOR monitor; 4869 RECT *r; 4870 4871 TRACE("device_parent %p.\n", device_parent); 4872 4873 if (!(ddraw->cooperative_level & DDSCL_EXCLUSIVE) || !ddraw->swapchain_window) 4874 { 4875 TRACE("Nothing to resize.\n"); 4876 return; 4877 } 4878 4879 monitor = MonitorFromWindow(ddraw->swapchain_window, MONITOR_DEFAULTTOPRIMARY); 4880 monitor_info.cbSize = sizeof(monitor_info); 4881 if (!GetMonitorInfoW(monitor, &monitor_info)) 4882 { 4883 ERR("Failed to get monitor info.\n"); 4884 return; 4885 } 4886 4887 r = &monitor_info.rcMonitor; 4888 TRACE("Resizing window %p to %s.\n", ddraw->swapchain_window, wine_dbgstr_rect(r)); 4889 4890 if (!SetWindowPos(ddraw->swapchain_window, HWND_TOP, r->left, r->top, 4891 r->right - r->left, r->bottom - r->top, SWP_SHOWWINDOW | SWP_NOACTIVATE)) 4892 ERR("Failed to resize window.\n"); 4893 4894 InterlockedCompareExchange(&ddraw->device_state, DDRAW_DEVICE_STATE_NOT_RESTORED, DDRAW_DEVICE_STATE_OK); 4895 } 4896 4897 static void CDECL device_parent_activate(struct wined3d_device_parent *device_parent, BOOL activate) 4898 { 4899 struct ddraw *ddraw = ddraw_from_device_parent(device_parent); 4900 4901 TRACE("device_parent %p, activate %#x.\n", device_parent, activate); 4902 4903 if (!activate) 4904 { 4905 ddraw->device_state = DDRAW_DEVICE_STATE_LOST; 4906 exclusive_window = NULL; 4907 } 4908 else 4909 { 4910 InterlockedCompareExchange(&ddraw->device_state, DDRAW_DEVICE_STATE_NOT_RESTORED, DDRAW_DEVICE_STATE_LOST); 4911 } 4912 } 4913 4914 void ddraw_update_lost_surfaces(struct ddraw *ddraw) 4915 { 4916 struct ddraw_surface *surface; 4917 4918 if (ddraw->device_state != DDRAW_DEVICE_STATE_NOT_RESTORED) 4919 return; 4920 4921 LIST_FOR_EACH_ENTRY(surface, &ddraw->surface_list, struct ddraw_surface, surface_list_entry) 4922 { 4923 surface->is_lost = TRUE; 4924 } 4925 ddraw->device_state = DDRAW_DEVICE_STATE_OK; 4926 } 4927 4928 static HRESULT CDECL device_parent_surface_created(struct wined3d_device_parent *device_parent, 4929 struct wined3d_texture *wined3d_texture, unsigned int sub_resource_idx, 4930 void **parent, const struct wined3d_parent_ops **parent_ops) 4931 { 4932 struct ddraw *ddraw = ddraw_from_device_parent(device_parent); 4933 struct ddraw_surface *ddraw_surface; 4934 4935 TRACE("device_parent %p, wined3d_texture %p, sub_resource_idx %u, parent %p, parent_ops %p.\n", 4936 device_parent, wined3d_texture, sub_resource_idx, parent, parent_ops); 4937 4938 /* We have a swapchain or wined3d internal texture. */ 4939 if (!wined3d_texture_get_parent(wined3d_texture) || wined3d_texture_get_parent(wined3d_texture) == ddraw) 4940 { 4941 *parent = NULL; 4942 *parent_ops = &ddraw_null_wined3d_parent_ops; 4943 4944 return DD_OK; 4945 } 4946 4947 if (!(ddraw_surface = heap_alloc_zero(sizeof(*ddraw_surface)))) 4948 { 4949 ERR("Failed to allocate surface memory.\n"); 4950 return DDERR_OUTOFVIDEOMEMORY; 4951 } 4952 4953 ddraw_surface_init(ddraw_surface, ddraw, wined3d_texture, sub_resource_idx, parent_ops); 4954 *parent = ddraw_surface; 4955 4956 ddraw_update_lost_surfaces(ddraw); 4957 list_add_head(&ddraw->surface_list, &ddraw_surface->surface_list_entry); 4958 4959 TRACE("Created ddraw surface %p.\n", ddraw_surface); 4960 4961 return DD_OK; 4962 } 4963 4964 static HRESULT CDECL device_parent_volume_created(struct wined3d_device_parent *device_parent, 4965 struct wined3d_texture *wined3d_texture, unsigned int sub_resource_idx, 4966 void **parent, const struct wined3d_parent_ops **parent_ops) 4967 { 4968 TRACE("device_parent %p, texture %p, sub_resource_idx %u, parent %p, parent_ops %p.\n", 4969 device_parent, wined3d_texture, sub_resource_idx, parent, parent_ops); 4970 4971 *parent = NULL; 4972 *parent_ops = &ddraw_null_wined3d_parent_ops; 4973 4974 return DD_OK; 4975 } 4976 4977 static void STDMETHODCALLTYPE ddraw_frontbuffer_destroyed(void *parent) 4978 { 4979 struct ddraw *ddraw = parent; 4980 ddraw->wined3d_frontbuffer = NULL; 4981 } 4982 4983 static const struct wined3d_parent_ops ddraw_frontbuffer_parent_ops = 4984 { 4985 ddraw_frontbuffer_destroyed, 4986 }; 4987 4988 static HRESULT CDECL device_parent_create_swapchain_texture(struct wined3d_device_parent *device_parent, 4989 void *container_parent, const struct wined3d_resource_desc *desc, DWORD texture_flags, 4990 struct wined3d_texture **texture) 4991 { 4992 struct ddraw *ddraw = ddraw_from_device_parent(device_parent); 4993 HRESULT hr; 4994 4995 TRACE("device_parent %p, container_parent %p, desc %p, texture flags %#x, texture %p.\n", 4996 device_parent, container_parent, desc, texture_flags, texture); 4997 4998 if (ddraw->wined3d_frontbuffer) 4999 { 5000 ERR("Frontbuffer already created.\n"); 5001 return E_FAIL; 5002 } 5003 5004 if (FAILED(hr = wined3d_texture_create(ddraw->wined3d_device, desc, 1, 1, 5005 texture_flags | WINED3D_TEXTURE_CREATE_MAPPABLE, NULL, ddraw, &ddraw_frontbuffer_parent_ops, texture))) 5006 { 5007 WARN("Failed to create texture, hr %#x.\n", hr); 5008 return hr; 5009 } 5010 5011 ddraw->wined3d_frontbuffer = *texture; 5012 5013 return hr; 5014 } 5015 5016 static HRESULT CDECL device_parent_create_swapchain(struct wined3d_device_parent *device_parent, 5017 struct wined3d_swapchain_desc *desc, struct wined3d_swapchain **swapchain) 5018 { 5019 struct ddraw *ddraw = ddraw_from_device_parent(device_parent); 5020 HRESULT hr; 5021 5022 TRACE("device_parent %p, desc %p, swapchain %p.\n", device_parent, desc, swapchain); 5023 5024 if (ddraw->wined3d_swapchain) 5025 { 5026 ERR("Swapchain already created.\n"); 5027 return E_FAIL; 5028 } 5029 5030 if (FAILED(hr = wined3d_swapchain_create(ddraw->wined3d_device, desc, NULL, 5031 &ddraw_null_wined3d_parent_ops, swapchain))) 5032 WARN("Failed to create swapchain, hr %#x.\n", hr); 5033 5034 return hr; 5035 } 5036 5037 static const struct wined3d_device_parent_ops ddraw_wined3d_device_parent_ops = 5038 { 5039 device_parent_wined3d_device_created, 5040 device_parent_mode_changed, 5041 device_parent_activate, 5042 device_parent_surface_created, 5043 device_parent_volume_created, 5044 device_parent_create_swapchain_texture, 5045 device_parent_create_swapchain, 5046 }; 5047 5048 HRESULT ddraw_init(struct ddraw *ddraw, DWORD flags, enum wined3d_device_type device_type) 5049 { 5050 WINED3DCAPS caps; 5051 HRESULT hr; 5052 5053 ddraw->IDirectDraw7_iface.lpVtbl = &ddraw7_vtbl; 5054 ddraw->IDirectDraw_iface.lpVtbl = &ddraw1_vtbl; 5055 ddraw->IDirectDraw2_iface.lpVtbl = &ddraw2_vtbl; 5056 ddraw->IDirectDraw4_iface.lpVtbl = &ddraw4_vtbl; 5057 ddraw->IDirect3D_iface.lpVtbl = &d3d1_vtbl; 5058 ddraw->IDirect3D2_iface.lpVtbl = &d3d2_vtbl; 5059 ddraw->IDirect3D3_iface.lpVtbl = &d3d3_vtbl; 5060 ddraw->IDirect3D7_iface.lpVtbl = &d3d7_vtbl; 5061 ddraw->device_parent.ops = &ddraw_wined3d_device_parent_ops; 5062 ddraw->numIfaces = 1; 5063 ddraw->ref7 = 1; 5064 5065 flags |= DDRAW_WINED3D_FLAGS; 5066 if (!(ddraw->wined3d = wined3d_create(flags))) 5067 { 5068 flags |= WINED3D_NO3D; 5069 if (!(ddraw->wined3d = wined3d_create(flags))) 5070 { 5071 WARN("Failed to create a wined3d object.\n"); 5072 return E_FAIL; 5073 } 5074 } 5075 5076 if (FAILED(hr = wined3d_get_device_caps(ddraw->wined3d, WINED3DADAPTER_DEFAULT, device_type, &caps))) 5077 { 5078 ERR("Failed to get device caps, hr %#x.\n", hr); 5079 wined3d_decref(ddraw->wined3d); 5080 return E_FAIL; 5081 } 5082 5083 if (!(caps.ddraw_caps.caps & WINEDDCAPS_3D)) 5084 { 5085 WARN("Created a wined3d object without 3D support.\n"); 5086 ddraw->flags |= DDRAW_NO3D; 5087 } 5088 5089 if (FAILED(hr = wined3d_device_create(ddraw->wined3d, WINED3DADAPTER_DEFAULT, device_type, 5090 NULL, 0, DDRAW_STRIDE_ALIGNMENT, &ddraw->device_parent, &ddraw->wined3d_device))) 5091 { 5092 WARN("Failed to create a wined3d device, hr %#x.\n", hr); 5093 wined3d_decref(ddraw->wined3d); 5094 return hr; 5095 } 5096 5097 list_init(&ddraw->surface_list); 5098 5099 return DD_OK; 5100 } 5101