1 /* DirectDraw Surface Implementation 2 * 3 * Copyright (c) 1997-2000 Marcus Meissner 4 * Copyright (c) 1998-2000 Lionel Ulmer 5 * Copyright (c) 2000-2001 TransGaming Technologies Inc. 6 * Copyright (c) 2006 Stefan Dösinger 7 * Copyright (c) 2011 Ričardas Barkauskas 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 WINE_DEFAULT_DEBUG_CHANNEL(ddraw); 30 31 static struct ddraw_surface *unsafe_impl_from_IDirectDrawSurface2(IDirectDrawSurface2 *iface); 32 static struct ddraw_surface *unsafe_impl_from_IDirectDrawSurface3(IDirectDrawSurface3 *iface); 33 34 static inline struct ddraw_surface *impl_from_IDirectDrawGammaControl(IDirectDrawGammaControl *iface) 35 { 36 return CONTAINING_RECORD(iface, struct ddraw_surface, IDirectDrawGammaControl_iface); 37 } 38 39 /* This is slow, of course. Also, in case of locks, we can't prevent other 40 * applications from drawing to the screen while we've locked the frontbuffer. 41 * We'd like to do this in wined3d instead, but for that to work wined3d needs 42 * to support windowless rendering first. */ 43 HRESULT ddraw_surface_update_frontbuffer(struct ddraw_surface *surface, 44 const RECT *rect, BOOL read, unsigned int swap_interval) 45 { 46 struct wined3d_texture *dst_texture; 47 HDC surface_dc, screen_dc; 48 int x, y, w, h; 49 HRESULT hr; 50 BOOL ret; 51 RECT r; 52 53 if (surface->ddraw->flags & DDRAW_SWAPPED && !read) 54 { 55 surface->ddraw->flags &= ~DDRAW_SWAPPED; 56 rect = NULL; 57 } 58 59 if (!rect) 60 { 61 SetRect(&r, 0, 0, surface->surface_desc.dwWidth, surface->surface_desc.dwHeight); 62 rect = &r; 63 } 64 65 x = rect->left; 66 y = rect->top; 67 w = rect->right - rect->left; 68 h = rect->bottom - rect->top; 69 70 if (w <= 0 || h <= 0) 71 return DD_OK; 72 73 if (surface->ddraw->swapchain_window && !(surface->ddraw->flags & DDRAW_GDI_FLIP)) 74 { 75 /* Nothing to do, we control the frontbuffer, or at least the parts we 76 * care about. */ 77 if (read) 78 return DD_OK; 79 80 if (swap_interval) 81 dst_texture = wined3d_swapchain_get_back_buffer(surface->ddraw->wined3d_swapchain, 0); 82 else 83 dst_texture = surface->ddraw->wined3d_frontbuffer; 84 85 if (SUCCEEDED(hr = wined3d_texture_blt(dst_texture, 0, rect, surface->wined3d_texture, 86 surface->sub_resource_idx, rect, 0, NULL, WINED3D_TEXF_POINT)) && swap_interval) 87 { 88 hr = wined3d_swapchain_present(surface->ddraw->wined3d_swapchain, rect, rect, NULL, swap_interval, 0); 89 surface->ddraw->flags |= DDRAW_SWAPPED; 90 } 91 return hr; 92 } 93 94 if (FAILED(hr = wined3d_texture_get_dc(surface->wined3d_texture, surface->sub_resource_idx, &surface_dc))) 95 { 96 ERR("Failed to get surface DC, hr %#x.\n", hr); 97 return hr; 98 } 99 if (surface->palette) 100 wined3d_palette_apply_to_dc(surface->palette->wined3d_palette, surface_dc); 101 102 if (!(screen_dc = GetDC(NULL))) 103 { 104 wined3d_texture_release_dc(surface->wined3d_texture, surface->sub_resource_idx, surface_dc); 105 ERR("Failed to get screen DC.\n"); 106 return E_FAIL; 107 } 108 109 if (read) 110 ret = BitBlt(surface_dc, x, y, w, h, 111 screen_dc, x, y, SRCCOPY); 112 else 113 ret = BitBlt(screen_dc, x, y, w, h, 114 surface_dc, x, y, SRCCOPY); 115 116 ReleaseDC(NULL, screen_dc); 117 wined3d_texture_release_dc(surface->wined3d_texture, surface->sub_resource_idx, surface_dc); 118 119 if (!ret) 120 { 121 ERR("Failed to blit to/from screen.\n"); 122 return E_FAIL; 123 } 124 125 return DD_OK; 126 } 127 128 /***************************************************************************** 129 * IUnknown parts follow 130 *****************************************************************************/ 131 132 /***************************************************************************** 133 * IDirectDrawSurface7::QueryInterface 134 * 135 * A normal QueryInterface implementation. For QueryInterface rules 136 * see ddraw.c, IDirectDraw7::QueryInterface. This method 137 * can Query IDirectDrawSurface interfaces in all version, IDirect3DTexture 138 * in all versions, the IDirectDrawGammaControl interface and it can 139 * create an IDirect3DDevice. (Uses IDirect3D7::CreateDevice) 140 * 141 * Params: 142 * riid: The interface id queried for 143 * obj: Address to write the pointer to 144 * 145 * Returns: 146 * S_OK on success 147 * E_NOINTERFACE if the requested interface wasn't found 148 * 149 *****************************************************************************/ 150 static HRESULT WINAPI ddraw_surface7_QueryInterface(IDirectDrawSurface7 *iface, REFIID riid, void **obj) 151 { 152 struct ddraw_surface *This = impl_from_IDirectDrawSurface7(iface); 153 154 TRACE("iface %p, riid %s, object %p.\n", iface, debugstr_guid(riid), obj); 155 156 /* According to COM docs, if the QueryInterface fails, obj should be set to NULL */ 157 *obj = NULL; 158 159 if(!riid) 160 return DDERR_INVALIDPARAMS; 161 162 if (IsEqualGUID(riid, &IID_IDirectDrawSurface7)) 163 { 164 IDirectDrawSurface7_AddRef(iface); 165 *obj = iface; 166 TRACE("(%p) returning IDirectDrawSurface7 interface at %p\n", This, *obj); 167 return S_OK; 168 } 169 170 if (IsEqualGUID(riid, &IID_IDirectDrawSurface4)) 171 { 172 IDirectDrawSurface4_AddRef(&This->IDirectDrawSurface4_iface); 173 *obj = &This->IDirectDrawSurface4_iface; 174 TRACE("(%p) returning IDirectDrawSurface4 interface at %p\n", This, *obj); 175 return S_OK; 176 } 177 178 if (IsEqualGUID(riid, &IID_IDirectDrawSurface3)) 179 { 180 IDirectDrawSurface3_AddRef(&This->IDirectDrawSurface3_iface); 181 *obj = &This->IDirectDrawSurface3_iface; 182 TRACE("(%p) returning IDirectDrawSurface3 interface at %p\n", This, *obj); 183 return S_OK; 184 } 185 186 if (IsEqualGUID(riid, &IID_IDirectDrawSurface2)) 187 { 188 IDirectDrawSurface2_AddRef(&This->IDirectDrawSurface2_iface); 189 *obj = &This->IDirectDrawSurface2_iface; 190 TRACE("(%p) returning IDirectDrawSurface2 interface at %p\n", This, *obj); 191 return S_OK; 192 } 193 194 if (IsEqualGUID(riid, &IID_IDirectDrawSurface) 195 || IsEqualGUID(riid, &IID_IUnknown)) 196 { 197 IDirectDrawSurface_AddRef(&This->IDirectDrawSurface_iface); 198 *obj = &This->IDirectDrawSurface_iface; 199 TRACE("(%p) returning IDirectDrawSurface interface at %p\n", This, *obj); 200 return S_OK; 201 } 202 203 if (IsEqualGUID(riid, &IID_IDirectDrawGammaControl)) 204 { 205 IDirectDrawGammaControl_AddRef(&This->IDirectDrawGammaControl_iface); 206 *obj = &This->IDirectDrawGammaControl_iface; 207 TRACE("(%p) returning IDirectDrawGammaControl interface at %p\n", This, *obj); 208 return S_OK; 209 } 210 211 if (IsEqualGUID(riid, &IID_IDirectDrawColorControl)) 212 { 213 WARN("Color control not implemented.\n"); 214 *obj = NULL; 215 return E_NOINTERFACE; 216 } 217 218 if (This->version != 7) 219 { 220 if (IsEqualGUID(riid, &IID_D3DDEVICE_WineD3D) 221 || IsEqualGUID(riid, &IID_IDirect3DHALDevice) 222 || IsEqualGUID(riid, &IID_IDirect3DRGBDevice)) 223 { 224 wined3d_mutex_lock(); 225 if (!This->device1) 226 { 227 HRESULT hr; 228 229 if (FAILED(hr = d3d_device_create(This->ddraw, riid, This, (IUnknown *)&This->IDirectDrawSurface_iface, 230 1, &This->device1, (IUnknown *)&This->IDirectDrawSurface_iface))) 231 { 232 This->device1 = NULL; 233 wined3d_mutex_unlock(); 234 WARN("Failed to create device, hr %#x.\n", hr); 235 return hr; 236 } 237 } 238 wined3d_mutex_unlock(); 239 240 IDirect3DDevice_AddRef(&This->device1->IDirect3DDevice_iface); 241 *obj = &This->device1->IDirect3DDevice_iface; 242 return S_OK; 243 } 244 245 if (IsEqualGUID(&IID_IDirect3DTexture2, riid)) 246 { 247 IDirect3DTexture2_AddRef(&This->IDirect3DTexture2_iface); 248 *obj = &This->IDirect3DTexture2_iface; 249 return S_OK; 250 } 251 252 if (IsEqualGUID( &IID_IDirect3DTexture, riid )) 253 { 254 IDirect3DTexture2_AddRef(&This->IDirect3DTexture_iface); 255 *obj = &This->IDirect3DTexture_iface; 256 return S_OK; 257 } 258 } 259 260 WARN("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(riid)); 261 262 if (This->version != 7) 263 return E_INVALIDARG; 264 265 return E_NOINTERFACE; 266 } 267 268 static HRESULT WINAPI ddraw_surface4_QueryInterface(IDirectDrawSurface4 *iface, REFIID riid, void **object) 269 { 270 struct ddraw_surface *surface = impl_from_IDirectDrawSurface4(iface); 271 272 TRACE("iface %p, riid %s, object %p.\n", iface, debugstr_guid(riid), object); 273 274 return ddraw_surface7_QueryInterface(&surface->IDirectDrawSurface7_iface, riid, object); 275 } 276 277 static HRESULT WINAPI ddraw_surface3_QueryInterface(IDirectDrawSurface3 *iface, REFIID riid, void **object) 278 { 279 struct ddraw_surface *surface = impl_from_IDirectDrawSurface3(iface); 280 281 TRACE("iface %p, riid %s, object %p.\n", iface, debugstr_guid(riid), object); 282 283 return ddraw_surface7_QueryInterface(&surface->IDirectDrawSurface7_iface, riid, object); 284 } 285 286 static HRESULT WINAPI ddraw_surface2_QueryInterface(IDirectDrawSurface2 *iface, REFIID riid, void **object) 287 { 288 struct ddraw_surface *surface = impl_from_IDirectDrawSurface2(iface); 289 290 TRACE("iface %p, riid %s, object %p.\n", iface, debugstr_guid(riid), object); 291 292 return ddraw_surface7_QueryInterface(&surface->IDirectDrawSurface7_iface, riid, object); 293 } 294 295 static HRESULT WINAPI ddraw_surface1_QueryInterface(IDirectDrawSurface *iface, REFIID riid, void **object) 296 { 297 struct ddraw_surface *surface = impl_from_IDirectDrawSurface(iface); 298 299 TRACE("iface %p, riid %s, object %p.\n", iface, debugstr_guid(riid), object); 300 301 return ddraw_surface7_QueryInterface(&surface->IDirectDrawSurface7_iface, riid, object); 302 } 303 304 static HRESULT WINAPI ddraw_gamma_control_QueryInterface(IDirectDrawGammaControl *iface, 305 REFIID riid, void **object) 306 { 307 struct ddraw_surface *surface = impl_from_IDirectDrawGammaControl(iface); 308 309 TRACE("iface %p, riid %s, object %p.\n", iface, debugstr_guid(riid), object); 310 311 return ddraw_surface7_QueryInterface(&surface->IDirectDrawSurface7_iface, riid, object); 312 } 313 314 static HRESULT WINAPI d3d_texture2_QueryInterface(IDirect3DTexture2 *iface, REFIID riid, void **object) 315 { 316 struct ddraw_surface *surface = impl_from_IDirect3DTexture2(iface); 317 318 TRACE("iface %p, riid %s, object %p.\n", iface, debugstr_guid(riid), object); 319 320 return ddraw_surface7_QueryInterface(&surface->IDirectDrawSurface7_iface, riid, object); 321 } 322 323 static HRESULT WINAPI d3d_texture1_QueryInterface(IDirect3DTexture *iface, REFIID riid, void **object) 324 { 325 struct ddraw_surface *surface = impl_from_IDirect3DTexture(iface); 326 327 TRACE("iface %p, riid %s, object %p.\n", iface, debugstr_guid(riid), object); 328 329 return ddraw_surface7_QueryInterface(&surface->IDirectDrawSurface7_iface, riid, object); 330 } 331 332 static void ddraw_surface_add_iface(struct ddraw_surface *surface) 333 { 334 ULONG iface_count = InterlockedIncrement(&surface->iface_count); 335 TRACE("%p increasing iface count to %u.\n", surface, iface_count); 336 337 if (iface_count == 1) 338 { 339 if (surface->ifaceToRelease) 340 IUnknown_AddRef(surface->ifaceToRelease); 341 wined3d_mutex_lock(); 342 if (surface->wined3d_rtv) 343 wined3d_rendertarget_view_incref(surface->wined3d_rtv); 344 wined3d_texture_incref(surface->wined3d_texture); 345 wined3d_mutex_unlock(); 346 } 347 } 348 349 /***************************************************************************** 350 * IDirectDrawSurface7::AddRef 351 * 352 * A normal addref implementation 353 * 354 * Returns: 355 * The new refcount 356 * 357 *****************************************************************************/ 358 static ULONG WINAPI ddraw_surface7_AddRef(IDirectDrawSurface7 *iface) 359 { 360 struct ddraw_surface *This = impl_from_IDirectDrawSurface7(iface); 361 ULONG refcount = InterlockedIncrement(&This->ref7); 362 363 TRACE("iface %p increasing refcount to %u.\n", iface, refcount); 364 365 if (refcount == 1) 366 { 367 ddraw_surface_add_iface(This); 368 } 369 370 return refcount; 371 } 372 373 static ULONG WINAPI ddraw_surface4_AddRef(IDirectDrawSurface4 *iface) 374 { 375 struct ddraw_surface *This = impl_from_IDirectDrawSurface4(iface); 376 ULONG refcount = InterlockedIncrement(&This->ref4); 377 378 TRACE("iface %p increasing refcount to %u.\n", iface, refcount); 379 380 if (refcount == 1) 381 { 382 ddraw_surface_add_iface(This); 383 } 384 385 return refcount; 386 } 387 388 static ULONG WINAPI ddraw_surface3_AddRef(IDirectDrawSurface3 *iface) 389 { 390 struct ddraw_surface *This = impl_from_IDirectDrawSurface3(iface); 391 ULONG refcount = InterlockedIncrement(&This->ref3); 392 393 TRACE("iface %p increasing refcount to %u.\n", iface, refcount); 394 395 if (refcount == 1) 396 { 397 ddraw_surface_add_iface(This); 398 } 399 400 return refcount; 401 } 402 403 static ULONG WINAPI ddraw_surface2_AddRef(IDirectDrawSurface2 *iface) 404 { 405 struct ddraw_surface *This = impl_from_IDirectDrawSurface2(iface); 406 ULONG refcount = InterlockedIncrement(&This->ref2); 407 408 TRACE("iface %p increasing refcount to %u.\n", iface, refcount); 409 410 if (refcount == 1) 411 { 412 ddraw_surface_add_iface(This); 413 } 414 415 return refcount; 416 } 417 418 static ULONG WINAPI ddraw_surface1_AddRef(IDirectDrawSurface *iface) 419 { 420 struct ddraw_surface *This = impl_from_IDirectDrawSurface(iface); 421 ULONG refcount = InterlockedIncrement(&This->ref1); 422 423 TRACE("iface %p increasing refcount to %u.\n", iface, refcount); 424 425 if (refcount == 1) 426 { 427 ddraw_surface_add_iface(This); 428 } 429 430 return refcount; 431 } 432 433 static ULONG WINAPI ddraw_gamma_control_AddRef(IDirectDrawGammaControl *iface) 434 { 435 struct ddraw_surface *This = impl_from_IDirectDrawGammaControl(iface); 436 ULONG refcount = InterlockedIncrement(&This->gamma_count); 437 438 TRACE("iface %p increasing refcount to %u.\n", iface, refcount); 439 440 if (refcount == 1) 441 { 442 ddraw_surface_add_iface(This); 443 } 444 445 return refcount; 446 } 447 448 static ULONG WINAPI d3d_texture2_AddRef(IDirect3DTexture2 *iface) 449 { 450 struct ddraw_surface *surface = impl_from_IDirect3DTexture2(iface); 451 452 TRACE("iface %p.\n", iface); 453 454 return IUnknown_AddRef(surface->texture_outer); 455 } 456 457 static ULONG WINAPI d3d_texture1_AddRef(IDirect3DTexture *iface) 458 { 459 struct ddraw_surface *surface = impl_from_IDirect3DTexture(iface); 460 461 TRACE("iface %p.\n", iface); 462 463 return IUnknown_AddRef(surface->texture_outer); 464 } 465 466 static HRESULT ddraw_surface_set_palette(struct ddraw_surface *surface, IDirectDrawPalette *palette) 467 { 468 struct ddraw_palette *palette_impl = unsafe_impl_from_IDirectDrawPalette(palette); 469 struct ddraw_palette *prev; 470 471 TRACE("iface %p, palette %p.\n", surface, palette); 472 473 if (palette_impl && palette_impl->flags & DDPCAPS_ALPHA 474 && !(surface->surface_desc.ddsCaps.dwCaps & DDSCAPS_TEXTURE)) 475 { 476 WARN("Alpha palette set on non-texture surface, returning DDERR_INVALIDSURFACETYPE.\n"); 477 return DDERR_INVALIDSURFACETYPE; 478 } 479 480 if (!format_is_paletteindexed(&surface->surface_desc.u4.ddpfPixelFormat)) 481 return DDERR_INVALIDPIXELFORMAT; 482 483 wined3d_mutex_lock(); 484 485 prev = surface->palette; 486 if (surface->surface_desc.ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE) 487 { 488 if (prev) 489 prev->flags &= ~DDPCAPS_PRIMARYSURFACE; 490 if (palette_impl) 491 palette_impl->flags |= DDPCAPS_PRIMARYSURFACE; 492 wined3d_swapchain_set_palette(surface->ddraw->wined3d_swapchain, 493 palette_impl ? palette_impl->wined3d_palette : NULL); 494 ddraw_surface_update_frontbuffer(surface, NULL, FALSE, 0); 495 } 496 if (palette_impl) 497 IDirectDrawPalette_AddRef(&palette_impl->IDirectDrawPalette_iface); 498 if (prev) 499 IDirectDrawPalette_Release(&prev->IDirectDrawPalette_iface); 500 surface->palette = palette_impl; 501 502 wined3d_mutex_unlock(); 503 504 return DD_OK; 505 } 506 507 static void ddraw_surface_cleanup(struct ddraw_surface *surface) 508 { 509 struct ddraw_surface *surf; 510 UINT i; 511 512 TRACE("surface %p.\n", surface); 513 514 /* The refcount test shows that the palette is detached when the surface 515 * is destroyed. */ 516 ddraw_surface_set_palette(surface, NULL); 517 518 /* Loop through all complex attached surfaces and destroy them. 519 * 520 * Yet again, only the root can have more than one complexly attached 521 * surface, all the others have a total of one. */ 522 for (i = 0; i < MAX_COMPLEX_ATTACHED; ++i) 523 { 524 if (!surface->complex_array[i]) 525 break; 526 527 surf = surface->complex_array[i]; 528 surface->complex_array[i] = NULL; 529 if (!surf->is_complex_root) 530 ddraw_surface_cleanup(surf); 531 } 532 533 if (surface->device1) 534 IUnknown_Release(&surface->device1->IUnknown_inner); 535 536 if (surface->iface_count > 1) 537 { 538 /* This can happen when a complex surface is destroyed, because the 539 * 2nd surface was addref()ed when the app called 540 * GetAttachedSurface(). */ 541 WARN("Destroying surface %p with refcounts 7: %u 4: %u 3: %u 2: %u 1: %u.\n", 542 surface, surface->ref7, surface->ref4, surface->ref3, surface->ref2, surface->ref1); 543 } 544 545 if (surface->wined3d_rtv) 546 wined3d_rendertarget_view_decref(surface->wined3d_rtv); 547 wined3d_texture_decref(surface->wined3d_texture); 548 } 549 550 static ULONG ddraw_surface_release_iface(struct ddraw_surface *This) 551 { 552 ULONG iface_count; 553 554 /* Prevent the surface from being destroyed if it's still attached to 555 * another surface. It will be destroyed when the root is destroyed. */ 556 if (This->iface_count == 1 && This->attached_iface) 557 IUnknown_AddRef(This->attached_iface); 558 iface_count = InterlockedDecrement(&This->iface_count); 559 560 TRACE("%p decreasing iface count to %u.\n", This, iface_count); 561 562 if (iface_count == 0) 563 { 564 struct ddraw_texture *texture = wined3d_texture_get_parent(This->wined3d_texture); 565 struct wined3d_device *wined3d_device = texture->wined3d_device; 566 IUnknown *release_iface = This->ifaceToRelease; 567 568 /* Complex attached surfaces are destroyed implicitly when the root is released */ 569 wined3d_mutex_lock(); 570 if(!This->is_complex_root) 571 { 572 WARN("(%p) Attempt to destroy a surface that is not a complex root\n", This); 573 wined3d_mutex_unlock(); 574 return iface_count; 575 } 576 ddraw_surface_cleanup(This); 577 wined3d_mutex_unlock(); 578 579 if (release_iface) 580 IUnknown_Release(release_iface); 581 /* Release the device only after anything that may reference it (the 582 * wined3d texture and rendertarget view in particular) is released. */ 583 wined3d_device_decref(wined3d_device); 584 } 585 586 return iface_count; 587 } 588 589 /***************************************************************************** 590 * IDirectDrawSurface7::Release 591 * 592 * Reduces the surface's refcount by 1. If the refcount falls to 0, the 593 * surface is destroyed. 594 * 595 * Destroying the surface is a bit tricky. For the connection between 596 * WineD3DSurfaces and DirectDrawSurfaces see IDirectDraw7::CreateSurface 597 * It has a nice graph explaining the connection. 598 * 599 * What happens here is basically this: 600 * When a surface is destroyed, its WineD3DSurface is released, 601 * and the refcount of the DirectDraw interface is reduced by 1. If it has 602 * complex surfaces attached to it, then these surfaces are destroyed too, 603 * regardless of their refcount. If any surface being destroyed has another 604 * surface attached to it (with a "soft" attachment, not complex), then 605 * this surface is detached with DeleteAttachedSurface. 606 * 607 * When the surface is a texture, the WineD3DTexture is released. 608 * If the surface is the Direct3D render target, then the D3D 609 * capabilities of the WineD3DDevice are uninitialized, which causes the 610 * swapchain to be released. 611 * 612 * When a complex sublevel falls to ref zero, then this is ignored. 613 * 614 * Returns: 615 * The new refcount 616 * 617 *****************************************************************************/ 618 static ULONG WINAPI ddraw_surface7_Release(IDirectDrawSurface7 *iface) 619 { 620 struct ddraw_surface *This = impl_from_IDirectDrawSurface7(iface); 621 ULONG refcount = InterlockedDecrement(&This->ref7); 622 623 TRACE("iface %p decreasing refcount to %u.\n", iface, refcount); 624 625 if (refcount == 0) 626 { 627 ddraw_surface_release_iface(This); 628 } 629 630 return refcount; 631 } 632 633 static ULONG WINAPI ddraw_surface4_Release(IDirectDrawSurface4 *iface) 634 { 635 struct ddraw_surface *This = impl_from_IDirectDrawSurface4(iface); 636 ULONG refcount = InterlockedDecrement(&This->ref4); 637 638 TRACE("iface %p decreasing refcount to %u.\n", iface, refcount); 639 640 if (refcount == 0) 641 { 642 ddraw_surface_release_iface(This); 643 } 644 645 return refcount; 646 } 647 648 static ULONG WINAPI ddraw_surface3_Release(IDirectDrawSurface3 *iface) 649 { 650 struct ddraw_surface *This = impl_from_IDirectDrawSurface3(iface); 651 ULONG refcount = InterlockedDecrement(&This->ref3); 652 653 TRACE("iface %p decreasing refcount to %u.\n", iface, refcount); 654 655 if (refcount == 0) 656 { 657 ddraw_surface_release_iface(This); 658 } 659 660 return refcount; 661 } 662 663 static ULONG WINAPI ddraw_surface2_Release(IDirectDrawSurface2 *iface) 664 { 665 struct ddraw_surface *This = impl_from_IDirectDrawSurface2(iface); 666 ULONG refcount = InterlockedDecrement(&This->ref2); 667 668 TRACE("iface %p decreasing refcount to %u.\n", iface, refcount); 669 670 if (refcount == 0) 671 { 672 ddraw_surface_release_iface(This); 673 } 674 675 return refcount; 676 } 677 678 static ULONG WINAPI ddraw_surface1_Release(IDirectDrawSurface *iface) 679 { 680 struct ddraw_surface *This = impl_from_IDirectDrawSurface(iface); 681 ULONG refcount = InterlockedDecrement(&This->ref1); 682 683 TRACE("iface %p decreasing refcount to %u.\n", iface, refcount); 684 685 if (refcount == 0) 686 { 687 ddraw_surface_release_iface(This); 688 } 689 690 return refcount; 691 } 692 693 static ULONG WINAPI ddraw_gamma_control_Release(IDirectDrawGammaControl *iface) 694 { 695 struct ddraw_surface *This = impl_from_IDirectDrawGammaControl(iface); 696 ULONG refcount = InterlockedDecrement(&This->gamma_count); 697 698 TRACE("iface %p decreasing refcount to %u.\n", iface, refcount); 699 700 if (refcount == 0) 701 { 702 ddraw_surface_release_iface(This); 703 } 704 705 return refcount; 706 } 707 708 static ULONG WINAPI d3d_texture2_Release(IDirect3DTexture2 *iface) 709 { 710 struct ddraw_surface *surface = impl_from_IDirect3DTexture2(iface); 711 712 TRACE("iface %p.\n", iface); 713 714 return IUnknown_Release(surface->texture_outer); 715 } 716 717 static ULONG WINAPI d3d_texture1_Release(IDirect3DTexture *iface) 718 { 719 struct ddraw_surface *surface = impl_from_IDirect3DTexture(iface); 720 721 TRACE("iface %p.\n", iface); 722 723 return IUnknown_Release(surface->texture_outer); 724 } 725 726 /***************************************************************************** 727 * IDirectDrawSurface7::GetAttachedSurface 728 * 729 * Returns an attached surface with the requested caps. Surface attachment 730 * and complex surfaces are not clearly described by the MSDN or sdk, 731 * so this method is tricky and likely to contain problems. 732 * This implementation searches the complex list first, then the 733 * attachment chain. 734 * 735 * The chains are searched from This down to the last surface in the chain, 736 * not from the first element in the chain. The first surface found is 737 * returned. The MSDN says that this method fails if more than one surface 738 * matches the caps, but it is not sure if that is right. The attachment 739 * structure may not even allow two matching surfaces. 740 * 741 * The found surface is AddRef-ed before it is returned. 742 * 743 * Params: 744 * Caps: Pointer to a DDCAPS2 structure describing the caps asked for 745 * Surface: Address to store the found surface 746 * 747 * Returns: 748 * DD_OK on success 749 * DDERR_INVALIDPARAMS if Caps or Surface is NULL 750 * DDERR_NOTFOUND if no surface was found 751 * 752 *****************************************************************************/ 753 static HRESULT WINAPI ddraw_surface7_GetAttachedSurface(IDirectDrawSurface7 *iface, 754 DDSCAPS2 *Caps, IDirectDrawSurface7 **Surface) 755 { 756 struct ddraw_surface *This = impl_from_IDirectDrawSurface7(iface); 757 struct ddraw_surface *surf; 758 DDSCAPS2 our_caps; 759 int i; 760 761 TRACE("iface %p, caps %p, attachment %p.\n", iface, Caps, Surface); 762 763 wined3d_mutex_lock(); 764 765 if(This->version < 7) 766 { 767 /* Earlier dx apps put garbage into these members, clear them */ 768 our_caps.dwCaps = Caps->dwCaps; 769 our_caps.dwCaps2 = 0; 770 our_caps.dwCaps3 = 0; 771 our_caps.u1.dwCaps4 = 0; 772 } 773 else 774 { 775 our_caps = *Caps; 776 } 777 778 TRACE("(%p): Looking for caps: %x,%x,%x,%x\n", This, our_caps.dwCaps, our_caps.dwCaps2, our_caps.dwCaps3, our_caps.u1.dwCaps4); /* FIXME: Better debugging */ 779 780 for(i = 0; i < MAX_COMPLEX_ATTACHED; i++) 781 { 782 surf = This->complex_array[i]; 783 if(!surf) break; 784 785 TRACE("Surface: (%p) caps: %#x, %#x, %#x, %#x.\n", surf, 786 surf->surface_desc.ddsCaps.dwCaps, 787 surf->surface_desc.ddsCaps.dwCaps2, 788 surf->surface_desc.ddsCaps.dwCaps3, 789 surf->surface_desc.ddsCaps.u1.dwCaps4); 790 791 if (((surf->surface_desc.ddsCaps.dwCaps & our_caps.dwCaps) == our_caps.dwCaps) && 792 ((surf->surface_desc.ddsCaps.dwCaps2 & our_caps.dwCaps2) == our_caps.dwCaps2)) { 793 794 /* MSDN: "This method fails if more than one surface is attached 795 * that matches the capabilities requested." 796 * 797 * Not sure how to test this. 798 */ 799 800 TRACE("(%p): Returning surface %p\n", This, surf); 801 *Surface = &surf->IDirectDrawSurface7_iface; 802 ddraw_surface7_AddRef(*Surface); 803 wined3d_mutex_unlock(); 804 805 return DD_OK; 806 } 807 } 808 809 /* Next, look at the attachment chain */ 810 surf = This; 811 812 while( (surf = surf->next_attached) ) 813 { 814 TRACE("Surface: (%p) caps: %#x, %#x, %#x, %#x.\n", surf, 815 surf->surface_desc.ddsCaps.dwCaps, 816 surf->surface_desc.ddsCaps.dwCaps2, 817 surf->surface_desc.ddsCaps.dwCaps3, 818 surf->surface_desc.ddsCaps.u1.dwCaps4); 819 820 if (((surf->surface_desc.ddsCaps.dwCaps & our_caps.dwCaps) == our_caps.dwCaps) && 821 ((surf->surface_desc.ddsCaps.dwCaps2 & our_caps.dwCaps2) == our_caps.dwCaps2)) { 822 823 TRACE("(%p): Returning surface %p\n", This, surf); 824 *Surface = &surf->IDirectDrawSurface7_iface; 825 ddraw_surface7_AddRef(*Surface); 826 wined3d_mutex_unlock(); 827 return DD_OK; 828 } 829 } 830 831 TRACE("(%p) Didn't find a valid surface\n", This); 832 833 wined3d_mutex_unlock(); 834 835 *Surface = NULL; 836 return DDERR_NOTFOUND; 837 } 838 839 static HRESULT WINAPI ddraw_surface4_GetAttachedSurface(IDirectDrawSurface4 *iface, 840 DDSCAPS2 *caps, IDirectDrawSurface4 **attachment) 841 { 842 struct ddraw_surface *surface = impl_from_IDirectDrawSurface4(iface); 843 struct ddraw_surface *attachment_impl; 844 IDirectDrawSurface7 *attachment7; 845 HRESULT hr; 846 847 TRACE("iface %p, caps %p, attachment %p.\n", iface, caps, attachment); 848 849 hr = ddraw_surface7_GetAttachedSurface(&surface->IDirectDrawSurface7_iface, 850 caps, &attachment7); 851 if (FAILED(hr)) 852 { 853 *attachment = NULL; 854 return hr; 855 } 856 attachment_impl = impl_from_IDirectDrawSurface7(attachment7); 857 *attachment = &attachment_impl->IDirectDrawSurface4_iface; 858 ddraw_surface4_AddRef(*attachment); 859 ddraw_surface7_Release(attachment7); 860 861 return hr; 862 } 863 864 static HRESULT WINAPI ddraw_surface3_GetAttachedSurface(IDirectDrawSurface3 *iface, 865 DDSCAPS *caps, IDirectDrawSurface3 **attachment) 866 { 867 struct ddraw_surface *surface = impl_from_IDirectDrawSurface3(iface); 868 struct ddraw_surface *attachment_impl; 869 IDirectDrawSurface7 *attachment7; 870 DDSCAPS2 caps2; 871 HRESULT hr; 872 873 TRACE("iface %p, caps %p, attachment %p.\n", iface, caps, attachment); 874 875 caps2.dwCaps = caps->dwCaps; 876 caps2.dwCaps2 = 0; 877 caps2.dwCaps3 = 0; 878 caps2.u1.dwCaps4 = 0; 879 880 hr = ddraw_surface7_GetAttachedSurface(&surface->IDirectDrawSurface7_iface, 881 &caps2, &attachment7); 882 if (FAILED(hr)) 883 { 884 *attachment = NULL; 885 return hr; 886 } 887 attachment_impl = impl_from_IDirectDrawSurface7(attachment7); 888 *attachment = &attachment_impl->IDirectDrawSurface3_iface; 889 ddraw_surface3_AddRef(*attachment); 890 ddraw_surface7_Release(attachment7); 891 892 return hr; 893 } 894 895 static HRESULT WINAPI ddraw_surface2_GetAttachedSurface(IDirectDrawSurface2 *iface, 896 DDSCAPS *caps, IDirectDrawSurface2 **attachment) 897 { 898 struct ddraw_surface *surface = impl_from_IDirectDrawSurface2(iface); 899 struct ddraw_surface *attachment_impl; 900 IDirectDrawSurface7 *attachment7; 901 DDSCAPS2 caps2; 902 HRESULT hr; 903 904 TRACE("iface %p, caps %p, attachment %p.\n", iface, caps, attachment); 905 906 caps2.dwCaps = caps->dwCaps; 907 caps2.dwCaps2 = 0; 908 caps2.dwCaps3 = 0; 909 caps2.u1.dwCaps4 = 0; 910 911 hr = ddraw_surface7_GetAttachedSurface(&surface->IDirectDrawSurface7_iface, 912 &caps2, &attachment7); 913 if (FAILED(hr)) 914 { 915 *attachment = NULL; 916 return hr; 917 } 918 attachment_impl = impl_from_IDirectDrawSurface7(attachment7); 919 *attachment = &attachment_impl->IDirectDrawSurface2_iface; 920 ddraw_surface2_AddRef(*attachment); 921 ddraw_surface7_Release(attachment7); 922 923 return hr; 924 } 925 926 static HRESULT WINAPI ddraw_surface1_GetAttachedSurface(IDirectDrawSurface *iface, 927 DDSCAPS *caps, IDirectDrawSurface **attachment) 928 { 929 struct ddraw_surface *surface = impl_from_IDirectDrawSurface(iface); 930 struct ddraw_surface *attachment_impl; 931 IDirectDrawSurface7 *attachment7; 932 DDSCAPS2 caps2; 933 HRESULT hr; 934 935 TRACE("iface %p, caps %p, attachment %p.\n", iface, caps, attachment); 936 937 caps2.dwCaps = caps->dwCaps; 938 caps2.dwCaps2 = 0; 939 caps2.dwCaps3 = 0; 940 caps2.u1.dwCaps4 = 0; 941 942 hr = ddraw_surface7_GetAttachedSurface(&surface->IDirectDrawSurface7_iface, 943 &caps2, &attachment7); 944 if (FAILED(hr)) 945 { 946 *attachment = NULL; 947 return hr; 948 } 949 attachment_impl = impl_from_IDirectDrawSurface7(attachment7); 950 *attachment = &attachment_impl->IDirectDrawSurface_iface; 951 ddraw_surface1_AddRef(*attachment); 952 ddraw_surface7_Release(attachment7); 953 954 return hr; 955 } 956 957 /***************************************************************************** 958 * IDirectDrawSurface7::Lock 959 * 960 * Locks the surface and returns a pointer to the surface's memory 961 * 962 * Params: 963 * Rect: Rectangle to lock. If NULL, the whole surface is locked 964 * DDSD: Pointer to a DDSURFACEDESC2 which shall receive the surface's desc. 965 * Flags: Locking flags, e.g Read only or write only 966 * h: An event handle that's not used and must be NULL 967 * 968 * Returns: 969 * DD_OK on success 970 * DDERR_INVALIDPARAMS if DDSD is NULL 971 * 972 *****************************************************************************/ 973 static HRESULT surface_lock(struct ddraw_surface *surface, 974 RECT *rect, DDSURFACEDESC2 *surface_desc, unsigned int surface_desc_size, 975 DWORD flags, HANDLE h) 976 { 977 struct wined3d_map_desc map_desc; 978 struct wined3d_box box; 979 HRESULT hr = DD_OK; 980 981 TRACE("surface %p, rect %s, surface_desc %p, surface_desc_size %u, flags %#x, h %p.\n", 982 surface, wine_dbgstr_rect(rect), surface_desc, surface_desc_size, flags, h); 983 984 /* surface->surface_desc.dwWidth and dwHeight are changeable, thus lock */ 985 wined3d_mutex_lock(); 986 987 /* Should I check for the handle to be NULL? 988 * 989 * The DDLOCK flags and the D3DLOCK flags are equal 990 * for the supported values. The others are ignored by WineD3D 991 */ 992 993 /* Windows zeroes this if the rect is invalid */ 994 surface_desc->lpSurface = NULL; 995 996 if (rect) 997 { 998 if ((rect->left < 0) || (rect->top < 0) 999 || (rect->left > rect->right) || (rect->right > surface->surface_desc.dwWidth) 1000 || (rect->top > rect->bottom) || (rect->bottom > surface->surface_desc.dwHeight)) 1001 { 1002 WARN("Trying to lock an invalid rectangle, returning DDERR_INVALIDPARAMS\n"); 1003 wined3d_mutex_unlock(); 1004 return DDERR_INVALIDPARAMS; 1005 } 1006 wined3d_box_set(&box, rect->left, rect->top, rect->right, rect->bottom, 0, 1); 1007 } 1008 1009 if (surface->surface_desc.ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE) 1010 hr = ddraw_surface_update_frontbuffer(surface, rect, TRUE, 0); 1011 if (SUCCEEDED(hr)) 1012 hr = wined3d_resource_map(wined3d_texture_get_resource(surface->wined3d_texture), 1013 surface->sub_resource_idx, &map_desc, rect ? &box : NULL, 1014 wined3dmapflags_from_ddrawmapflags(flags)); 1015 if (FAILED(hr)) 1016 { 1017 wined3d_mutex_unlock(); 1018 switch(hr) 1019 { 1020 /* D3D8 and D3D9 return the general D3DERR_INVALIDCALL error, but ddraw has a more 1021 * specific error. But since wined3d returns that error in this only occasion, 1022 * keep d3d8 and d3d9 free from the return value override. There are many different 1023 * places where d3d8/9 would have to catch the DDERR_SURFACEBUSY, it is much easier 1024 * to do it in one place in ddraw. 1025 */ 1026 case WINED3DERR_INVALIDCALL: return DDERR_SURFACEBUSY; 1027 default: return hr; 1028 } 1029 } 1030 1031 if (surface->surface_desc.ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE) 1032 { 1033 if (flags & DDLOCK_READONLY) 1034 SetRectEmpty(&surface->ddraw->primary_lock); 1035 else if (rect) 1036 surface->ddraw->primary_lock = *rect; 1037 else 1038 SetRect(&surface->ddraw->primary_lock, 0, 0, surface->surface_desc.dwWidth, surface->surface_desc.dwHeight); 1039 } 1040 1041 /* Windows does not set DDSD_LPSURFACE on locked surfaces. */ 1042 DD_STRUCT_COPY_BYSIZE_(surface_desc, &surface->surface_desc, surface_desc_size, surface->surface_desc.dwSize); 1043 surface_desc->lpSurface = map_desc.data; 1044 1045 TRACE("locked surface returning description :\n"); 1046 if (TRACE_ON(ddraw)) 1047 DDRAW_dump_surface_desc(surface_desc); 1048 1049 wined3d_mutex_unlock(); 1050 1051 return DD_OK; 1052 } 1053 1054 static BOOL surface_validate_lock_desc(struct ddraw_surface *surface, 1055 const DDSURFACEDESC *desc, unsigned int *size) 1056 { 1057 if (!desc) 1058 return FALSE; 1059 1060 if (desc->dwSize == sizeof(DDSURFACEDESC) || desc->dwSize == sizeof(DDSURFACEDESC2)) 1061 { 1062 *size = desc->dwSize; 1063 return TRUE; 1064 } 1065 1066 if (surface->version == 7 1067 && surface->surface_desc.ddsCaps.dwCaps & DDSCAPS_TEXTURE 1068 && !(surface->surface_desc.ddsCaps.dwCaps & DDSCAPS_VIDEOMEMORY)) 1069 { 1070 if (desc->dwSize >= sizeof(DDSURFACEDESC2)) 1071 *size = sizeof(DDSURFACEDESC2); 1072 else 1073 *size = sizeof(DDSURFACEDESC); 1074 return TRUE; 1075 } 1076 1077 WARN("Invalid structure size %u.\n", desc->dwSize); 1078 return FALSE; 1079 } 1080 1081 static HRESULT WINAPI ddraw_surface7_Lock(IDirectDrawSurface7 *iface, 1082 RECT *rect, DDSURFACEDESC2 *surface_desc, DWORD flags, HANDLE h) 1083 { 1084 struct ddraw_surface *surface = impl_from_IDirectDrawSurface7(iface); 1085 unsigned int surface_desc_size; 1086 1087 TRACE("iface %p, rect %s, surface_desc %p, flags %#x, h %p.\n", 1088 iface, wine_dbgstr_rect(rect), surface_desc, flags, h); 1089 1090 if (!surface_validate_lock_desc(surface, (DDSURFACEDESC *)surface_desc, &surface_desc_size)) 1091 return DDERR_INVALIDPARAMS; 1092 1093 return surface_lock(surface, rect, surface_desc, surface_desc_size, flags, h); 1094 } 1095 1096 static HRESULT WINAPI ddraw_surface4_Lock(IDirectDrawSurface4 *iface, RECT *rect, 1097 DDSURFACEDESC2 *surface_desc, DWORD flags, HANDLE h) 1098 { 1099 struct ddraw_surface *surface = impl_from_IDirectDrawSurface4(iface); 1100 unsigned int surface_desc_size; 1101 1102 TRACE("iface %p, rect %s, surface_desc %p, flags %#x, h %p.\n", 1103 iface, wine_dbgstr_rect(rect), surface_desc, flags, h); 1104 1105 if (!surface_validate_lock_desc(surface, (DDSURFACEDESC *)surface_desc, &surface_desc_size)) 1106 return DDERR_INVALIDPARAMS; 1107 1108 return surface_lock(surface, rect, surface_desc, surface_desc_size, flags, h); 1109 } 1110 1111 static HRESULT WINAPI ddraw_surface3_Lock(IDirectDrawSurface3 *iface, RECT *rect, 1112 DDSURFACEDESC *surface_desc, DWORD flags, HANDLE h) 1113 { 1114 struct ddraw_surface *surface = impl_from_IDirectDrawSurface3(iface); 1115 unsigned int surface_desc_size; 1116 DDSURFACEDESC2 surface_desc2; 1117 HRESULT hr; 1118 1119 TRACE("iface %p, rect %s, surface_desc %p, flags %#x, h %p.\n", 1120 iface, wine_dbgstr_rect(rect), surface_desc, flags, h); 1121 1122 if (!surface_validate_lock_desc(surface, surface_desc, &surface_desc_size)) 1123 return DDERR_INVALIDPARAMS; 1124 1125 surface_desc2.dwSize = surface_desc->dwSize; 1126 surface_desc2.dwFlags = 0; 1127 hr = surface_lock(surface, rect, &surface_desc2, surface_desc_size, flags, h); 1128 DDSD2_to_DDSD(&surface_desc2, surface_desc); 1129 surface_desc->dwSize = surface_desc2.dwSize; 1130 return hr; 1131 } 1132 1133 static HRESULT WINAPI ddraw_surface2_Lock(IDirectDrawSurface2 *iface, RECT *rect, 1134 DDSURFACEDESC *surface_desc, DWORD flags, HANDLE h) 1135 { 1136 struct ddraw_surface *surface = impl_from_IDirectDrawSurface2(iface); 1137 unsigned int surface_desc_size; 1138 DDSURFACEDESC2 surface_desc2; 1139 HRESULT hr; 1140 1141 TRACE("iface %p, rect %s, surface_desc %p, flags %#x, h %p.\n", 1142 iface, wine_dbgstr_rect(rect), surface_desc, flags, h); 1143 1144 if (!surface_validate_lock_desc(surface, surface_desc, &surface_desc_size)) 1145 return DDERR_INVALIDPARAMS; 1146 1147 surface_desc2.dwSize = surface_desc->dwSize; 1148 surface_desc2.dwFlags = 0; 1149 hr = surface_lock(surface, rect, &surface_desc2, surface_desc_size, flags, h); 1150 DDSD2_to_DDSD(&surface_desc2, surface_desc); 1151 surface_desc->dwSize = surface_desc2.dwSize; 1152 return hr; 1153 } 1154 1155 static HRESULT WINAPI ddraw_surface1_Lock(IDirectDrawSurface *iface, RECT *rect, 1156 DDSURFACEDESC *surface_desc, DWORD flags, HANDLE h) 1157 { 1158 struct ddraw_surface *surface = impl_from_IDirectDrawSurface(iface); 1159 unsigned int surface_desc_size; 1160 DDSURFACEDESC2 surface_desc2; 1161 HRESULT hr; 1162 1163 TRACE("iface %p, rect %s, surface_desc %p, flags %#x, h %p.\n", 1164 iface, wine_dbgstr_rect(rect), surface_desc, flags, h); 1165 1166 if (!surface_validate_lock_desc(surface, surface_desc, &surface_desc_size)) 1167 return DDERR_INVALIDPARAMS; 1168 1169 surface_desc2.dwSize = surface_desc->dwSize; 1170 surface_desc2.dwFlags = 0; 1171 hr = surface_lock(surface, rect, &surface_desc2, surface_desc_size, flags, h); 1172 DDSD2_to_DDSD(&surface_desc2, surface_desc); 1173 surface_desc->dwSize = surface_desc2.dwSize; 1174 return hr; 1175 } 1176 1177 /***************************************************************************** 1178 * IDirectDrawSurface7::Unlock 1179 * 1180 * Unlocks an locked surface 1181 * 1182 * Params: 1183 * Rect: Not used by this implementation 1184 * 1185 * Returns: 1186 * D3D_OK on success, error code otherwise. 1187 * 1188 *****************************************************************************/ 1189 static HRESULT WINAPI DECLSPEC_HOTPATCH ddraw_surface7_Unlock(IDirectDrawSurface7 *iface, RECT *pRect) 1190 { 1191 struct ddraw_surface *surface = impl_from_IDirectDrawSurface7(iface); 1192 HRESULT hr; 1193 1194 TRACE("iface %p, rect %s.\n", iface, wine_dbgstr_rect(pRect)); 1195 1196 wined3d_mutex_lock(); 1197 hr = wined3d_resource_unmap(wined3d_texture_get_resource(surface->wined3d_texture), surface->sub_resource_idx); 1198 if (SUCCEEDED(hr) && surface->surface_desc.ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE) 1199 hr = ddraw_surface_update_frontbuffer(surface, &surface->ddraw->primary_lock, FALSE, 0); 1200 wined3d_mutex_unlock(); 1201 1202 return hr; 1203 } 1204 1205 static HRESULT WINAPI DECLSPEC_HOTPATCH ddraw_surface4_Unlock(IDirectDrawSurface4 *iface, RECT *pRect) 1206 { 1207 struct ddraw_surface *surface = impl_from_IDirectDrawSurface4(iface); 1208 1209 TRACE("iface %p, rect %p.\n", iface, pRect); 1210 1211 return ddraw_surface7_Unlock(&surface->IDirectDrawSurface7_iface, pRect); 1212 } 1213 1214 static HRESULT WINAPI DECLSPEC_HOTPATCH ddraw_surface3_Unlock(IDirectDrawSurface3 *iface, void *data) 1215 { 1216 struct ddraw_surface *surface = impl_from_IDirectDrawSurface3(iface); 1217 1218 TRACE("iface %p, data %p.\n", iface, data); 1219 1220 /* data might not be the LPRECT of later versions, so drop it. */ 1221 return ddraw_surface7_Unlock(&surface->IDirectDrawSurface7_iface, NULL); 1222 } 1223 1224 static HRESULT WINAPI DECLSPEC_HOTPATCH ddraw_surface2_Unlock(IDirectDrawSurface2 *iface, void *data) 1225 { 1226 struct ddraw_surface *surface = impl_from_IDirectDrawSurface2(iface); 1227 1228 TRACE("iface %p, data %p.\n", iface, data); 1229 1230 /* data might not be the LPRECT of later versions, so drop it. */ 1231 return ddraw_surface7_Unlock(&surface->IDirectDrawSurface7_iface, NULL); 1232 } 1233 1234 static HRESULT WINAPI DECLSPEC_HOTPATCH ddraw_surface1_Unlock(IDirectDrawSurface *iface, void *data) 1235 { 1236 struct ddraw_surface *surface = impl_from_IDirectDrawSurface(iface); 1237 1238 TRACE("iface %p, data %p.\n", iface, data); 1239 1240 /* data might not be the LPRECT of later versions, so drop it. */ 1241 return ddraw_surface7_Unlock(&surface->IDirectDrawSurface7_iface, NULL); 1242 } 1243 1244 static unsigned int ddraw_swap_interval_from_flags(DWORD flags) 1245 { 1246 if (flags & DDFLIP_NOVSYNC) 1247 return 0; 1248 1249 switch (flags & (DDFLIP_INTERVAL2 | DDFLIP_INTERVAL3 | DDFLIP_INTERVAL4)) 1250 { 1251 case DDFLIP_INTERVAL2: 1252 return 2; 1253 case DDFLIP_INTERVAL3: 1254 return 3; 1255 case DDFLIP_INTERVAL4: 1256 return 4; 1257 default: 1258 return 1; 1259 } 1260 } 1261 1262 static HRESULT WINAPI DECLSPEC_HOTPATCH ddraw_surface7_Flip(IDirectDrawSurface7 *iface, 1263 IDirectDrawSurface7 *src, DWORD flags) 1264 { 1265 struct ddraw_surface *dst_impl = impl_from_IDirectDrawSurface7(iface); 1266 struct ddraw_surface *src_impl = unsafe_impl_from_IDirectDrawSurface7(src); 1267 struct wined3d_rendertarget_view *tmp_rtv, *src_rtv, *rtv; 1268 struct ddraw_texture *ddraw_texture, *prev_ddraw_texture; 1269 DDSCAPS2 caps = {DDSCAPS_FLIP, 0, 0, {0}}; 1270 struct wined3d_texture *texture; 1271 IDirectDrawSurface7 *current; 1272 HRESULT hr; 1273 1274 TRACE("iface %p, src %p, flags %#x.\n", iface, src, flags); 1275 1276 if (src == iface || !(dst_impl->surface_desc.ddsCaps.dwCaps & (DDSCAPS_FRONTBUFFER | DDSCAPS_OVERLAY))) 1277 return DDERR_NOTFLIPPABLE; 1278 1279 if (IDirectDrawSurface7_IsLost(iface) == DDERR_SURFACELOST) 1280 return DDERR_SURFACELOST; 1281 1282 wined3d_mutex_lock(); 1283 1284 if ((dst_impl->surface_desc.ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE) 1285 && !(dst_impl->ddraw->cooperative_level & DDSCL_EXCLUSIVE)) 1286 { 1287 WARN("Not in exclusive mode.\n"); 1288 wined3d_mutex_unlock(); 1289 return DDERR_NOEXCLUSIVEMODE; 1290 } 1291 1292 tmp_rtv = ddraw_surface_get_rendertarget_view(dst_impl); 1293 if (dst_impl->sub_resource_idx) 1294 ERR("Invalid sub-resource index %u on surface %p.\n", dst_impl->sub_resource_idx, dst_impl); 1295 texture = dst_impl->wined3d_texture; 1296 rtv = wined3d_device_get_rendertarget_view(dst_impl->ddraw->wined3d_device, 0); 1297 ddraw_texture = wined3d_texture_get_parent(dst_impl->wined3d_texture); 1298 1299 if (src_impl) 1300 { 1301 for (current = iface; current != src;) 1302 { 1303 if (FAILED(hr = ddraw_surface7_GetAttachedSurface(current, &caps, ¤t))) 1304 { 1305 WARN("Surface %p is not on the same flip chain as surface %p.\n", src, iface); 1306 wined3d_mutex_unlock(); 1307 return DDERR_NOTFLIPPABLE; 1308 } 1309 ddraw_surface7_Release(current); 1310 if (current == iface) 1311 { 1312 WARN("Surface %p is not on the same flip chain as surface %p.\n", src, iface); 1313 wined3d_mutex_unlock(); 1314 return DDERR_NOTFLIPPABLE; 1315 } 1316 } 1317 1318 src_rtv = ddraw_surface_get_rendertarget_view(src_impl); 1319 if (rtv == dst_impl->wined3d_rtv) 1320 wined3d_device_set_rendertarget_view(dst_impl->ddraw->wined3d_device, 0, src_rtv, FALSE); 1321 wined3d_rendertarget_view_set_parent(src_rtv, dst_impl); 1322 dst_impl->wined3d_rtv = src_rtv; 1323 wined3d_texture_set_sub_resource_parent(src_impl->wined3d_texture, 0, dst_impl); 1324 prev_ddraw_texture = wined3d_texture_get_parent(src_impl->wined3d_texture); 1325 wined3d_resource_set_parent(wined3d_texture_get_resource(src_impl->wined3d_texture), ddraw_texture); 1326 if (src_impl->sub_resource_idx) 1327 ERR("Invalid sub-resource index %u on surface %p.\n", src_impl->sub_resource_idx, src_impl); 1328 dst_impl->wined3d_texture = src_impl->wined3d_texture; 1329 ddraw_texture = prev_ddraw_texture; 1330 } 1331 else 1332 { 1333 for (current = iface;;) 1334 { 1335 if (FAILED(hr = ddraw_surface7_GetAttachedSurface(current, &caps, ¤t))) 1336 { 1337 ERR("Can't find a flip target\n"); 1338 wined3d_mutex_unlock(); 1339 return DDERR_NOTFLIPPABLE; /* Unchecked */ 1340 } 1341 ddraw_surface7_Release(current); 1342 if (current == iface) 1343 { 1344 dst_impl = impl_from_IDirectDrawSurface7(iface); 1345 break; 1346 } 1347 1348 src_impl = impl_from_IDirectDrawSurface7(current); 1349 src_rtv = ddraw_surface_get_rendertarget_view(src_impl); 1350 if (rtv == dst_impl->wined3d_rtv) 1351 wined3d_device_set_rendertarget_view(dst_impl->ddraw->wined3d_device, 0, src_rtv, FALSE); 1352 wined3d_rendertarget_view_set_parent(src_rtv, dst_impl); 1353 dst_impl->wined3d_rtv = src_rtv; 1354 wined3d_texture_set_sub_resource_parent(src_impl->wined3d_texture, 0, dst_impl); 1355 prev_ddraw_texture = wined3d_texture_get_parent(src_impl->wined3d_texture); 1356 wined3d_resource_set_parent(wined3d_texture_get_resource(src_impl->wined3d_texture), ddraw_texture); 1357 ddraw_texture = prev_ddraw_texture; 1358 if (src_impl->sub_resource_idx) 1359 ERR("Invalid sub-resource index %u on surface %p.\n", src_impl->sub_resource_idx, src_impl); 1360 dst_impl->wined3d_texture = src_impl->wined3d_texture; 1361 dst_impl = src_impl; 1362 } 1363 } 1364 1365 /* We don't have to worry about potential texture bindings, since 1366 * flippable surfaces can never be textures. */ 1367 if (rtv == src_impl->wined3d_rtv) 1368 wined3d_device_set_rendertarget_view(dst_impl->ddraw->wined3d_device, 0, tmp_rtv, FALSE); 1369 wined3d_rendertarget_view_set_parent(tmp_rtv, src_impl); 1370 src_impl->wined3d_rtv = tmp_rtv; 1371 wined3d_texture_set_sub_resource_parent(texture, 0, src_impl); 1372 wined3d_resource_set_parent(wined3d_texture_get_resource(texture), ddraw_texture); 1373 src_impl->wined3d_texture = texture; 1374 1375 if (flags & ~(DDFLIP_NOVSYNC | DDFLIP_INTERVAL2 | DDFLIP_INTERVAL3 | DDFLIP_INTERVAL4)) 1376 { 1377 static UINT once; 1378 if (!once++) 1379 FIXME("Ignoring flags %#x.\n", flags); 1380 else 1381 WARN("Ignoring flags %#x.\n", flags); 1382 } 1383 1384 if (dst_impl->surface_desc.ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE) 1385 hr = ddraw_surface_update_frontbuffer(dst_impl, NULL, FALSE, ddraw_swap_interval_from_flags(flags)); 1386 else 1387 hr = DD_OK; 1388 1389 wined3d_mutex_unlock(); 1390 1391 return hr; 1392 } 1393 1394 static HRESULT WINAPI DECLSPEC_HOTPATCH ddraw_surface4_Flip(IDirectDrawSurface4 *iface, 1395 IDirectDrawSurface4 *src, DWORD flags) 1396 { 1397 struct ddraw_surface *surface = impl_from_IDirectDrawSurface4(iface); 1398 struct ddraw_surface *src_impl = unsafe_impl_from_IDirectDrawSurface4(src); 1399 1400 TRACE("iface %p, src %p, flags %#x.\n", iface, src, flags); 1401 1402 return ddraw_surface7_Flip(&surface->IDirectDrawSurface7_iface, 1403 src_impl ? &src_impl->IDirectDrawSurface7_iface : NULL, flags); 1404 } 1405 1406 static HRESULT WINAPI DECLSPEC_HOTPATCH ddraw_surface3_Flip(IDirectDrawSurface3 *iface, 1407 IDirectDrawSurface3 *src, DWORD flags) 1408 { 1409 struct ddraw_surface *surface = impl_from_IDirectDrawSurface3(iface); 1410 struct ddraw_surface *src_impl = unsafe_impl_from_IDirectDrawSurface3(src); 1411 1412 TRACE("iface %p, src %p, flags %#x.\n", iface, src, flags); 1413 1414 return ddraw_surface7_Flip(&surface->IDirectDrawSurface7_iface, 1415 src_impl ? &src_impl->IDirectDrawSurface7_iface : NULL, flags); 1416 } 1417 1418 static HRESULT WINAPI DECLSPEC_HOTPATCH ddraw_surface2_Flip(IDirectDrawSurface2 *iface, 1419 IDirectDrawSurface2 *src, DWORD flags) 1420 { 1421 struct ddraw_surface *surface = impl_from_IDirectDrawSurface2(iface); 1422 struct ddraw_surface *src_impl = unsafe_impl_from_IDirectDrawSurface2(src); 1423 1424 TRACE("iface %p, src %p, flags %#x.\n", iface, src, flags); 1425 1426 return ddraw_surface7_Flip(&surface->IDirectDrawSurface7_iface, 1427 src_impl ? &src_impl->IDirectDrawSurface7_iface : NULL, flags); 1428 } 1429 1430 static HRESULT WINAPI DECLSPEC_HOTPATCH ddraw_surface1_Flip(IDirectDrawSurface *iface, 1431 IDirectDrawSurface *src, DWORD flags) 1432 { 1433 struct ddraw_surface *surface = impl_from_IDirectDrawSurface(iface); 1434 struct ddraw_surface *src_impl = unsafe_impl_from_IDirectDrawSurface(src); 1435 1436 TRACE("iface %p, src %p, flags %#x.\n", iface, src, flags); 1437 1438 return ddraw_surface7_Flip(&surface->IDirectDrawSurface7_iface, 1439 src_impl ? &src_impl->IDirectDrawSurface7_iface : NULL, flags); 1440 } 1441 1442 static HRESULT ddraw_surface_blt(struct ddraw_surface *dst_surface, const RECT *dst_rect, 1443 struct ddraw_surface *src_surface, const RECT *src_rect, DWORD flags, DWORD fill_colour, 1444 const struct wined3d_blt_fx *fx, enum wined3d_texture_filter_type filter) 1445 { 1446 struct wined3d_device *wined3d_device = dst_surface->ddraw->wined3d_device; 1447 struct wined3d_color colour; 1448 DWORD wined3d_flags; 1449 1450 if (flags & DDBLT_COLORFILL) 1451 { 1452 if (!wined3d_colour_from_ddraw_colour(&dst_surface->surface_desc.u4.ddpfPixelFormat, 1453 dst_surface->palette, fill_colour, &colour)) 1454 return DDERR_INVALIDPARAMS; 1455 1456 return wined3d_device_clear_rendertarget_view(wined3d_device, 1457 ddraw_surface_get_rendertarget_view(dst_surface), 1458 dst_rect, WINED3DCLEAR_TARGET, &colour, 0.0f, 0); 1459 } 1460 1461 if (flags & DDBLT_DEPTHFILL) 1462 { 1463 if (!wined3d_colour_from_ddraw_colour(&dst_surface->surface_desc.u4.ddpfPixelFormat, 1464 dst_surface->palette, fill_colour, &colour)) 1465 return DDERR_INVALIDPARAMS; 1466 1467 return wined3d_device_clear_rendertarget_view(wined3d_device, 1468 ddraw_surface_get_rendertarget_view(dst_surface), 1469 dst_rect, WINED3DCLEAR_ZBUFFER, NULL, colour.r, 0); 1470 } 1471 1472 wined3d_flags = flags & ~DDBLT_ASYNC; 1473 if (wined3d_flags & ~WINED3D_BLT_MASK) 1474 { 1475 FIXME("Unhandled flags %#x.\n", flags); 1476 return E_NOTIMPL; 1477 } 1478 1479 if (!(flags & DDBLT_ASYNC)) 1480 wined3d_flags |= WINED3D_BLT_SYNCHRONOUS; 1481 1482 return wined3d_texture_blt(dst_surface->wined3d_texture, dst_surface->sub_resource_idx, dst_rect, 1483 src_surface->wined3d_texture, src_surface->sub_resource_idx, src_rect, wined3d_flags, fx, filter); 1484 } 1485 1486 static HRESULT ddraw_surface_blt_clipped(struct ddraw_surface *dst_surface, const RECT *dst_rect_in, 1487 struct ddraw_surface *src_surface, const RECT *src_rect_in, DWORD flags, DWORD fill_colour, 1488 const struct wined3d_blt_fx *fx, enum wined3d_texture_filter_type filter) 1489 { 1490 RECT src_rect, dst_rect; 1491 float scale_x, scale_y; 1492 const RECT *clip_rect; 1493 UINT clip_list_size; 1494 RGNDATA *clip_list; 1495 HRESULT hr = DD_OK; 1496 UINT i; 1497 1498 if (!dst_rect_in) 1499 SetRect(&dst_rect, 0, 0, dst_surface->surface_desc.dwWidth, 1500 dst_surface->surface_desc.dwHeight); 1501 else 1502 dst_rect = *dst_rect_in; 1503 1504 if (IsRectEmpty(&dst_rect)) 1505 return DDERR_INVALIDRECT; 1506 1507 if (src_surface) 1508 { 1509 if (!src_rect_in) 1510 SetRect(&src_rect, 0, 0, src_surface->surface_desc.dwWidth, 1511 src_surface->surface_desc.dwHeight); 1512 else 1513 src_rect = *src_rect_in; 1514 1515 if (IsRectEmpty(&src_rect)) 1516 return DDERR_INVALIDRECT; 1517 } 1518 else 1519 { 1520 SetRectEmpty(&src_rect); 1521 } 1522 1523 if (!dst_surface->clipper) 1524 { 1525 if (src_surface && src_surface->surface_desc.ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE) 1526 hr = ddraw_surface_update_frontbuffer(src_surface, &src_rect, TRUE, 0); 1527 if (SUCCEEDED(hr)) 1528 hr = ddraw_surface_blt(dst_surface, &dst_rect, src_surface, &src_rect, flags, fill_colour, fx, filter); 1529 if (SUCCEEDED(hr) && (dst_surface->surface_desc.ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE)) 1530 hr = ddraw_surface_update_frontbuffer(dst_surface, &dst_rect, FALSE, 0); 1531 1532 return hr; 1533 } 1534 1535 scale_x = (float)(src_rect.right - src_rect.left) / (float)(dst_rect.right - dst_rect.left); 1536 scale_y = (float)(src_rect.bottom - src_rect.top) / (float)(dst_rect.bottom - dst_rect.top); 1537 1538 if (FAILED(hr = IDirectDrawClipper_GetClipList(&dst_surface->clipper->IDirectDrawClipper_iface, 1539 &dst_rect, NULL, &clip_list_size))) 1540 { 1541 WARN("Failed to get clip list size, hr %#x.\n", hr); 1542 return hr; 1543 } 1544 1545 if (!(clip_list = heap_alloc(clip_list_size))) 1546 { 1547 WARN("Failed to allocate clip list.\n"); 1548 return E_OUTOFMEMORY; 1549 } 1550 1551 if (FAILED(hr = IDirectDrawClipper_GetClipList(&dst_surface->clipper->IDirectDrawClipper_iface, 1552 &dst_rect, clip_list, &clip_list_size))) 1553 { 1554 WARN("Failed to get clip list, hr %#x.\n", hr); 1555 heap_free(clip_list); 1556 return hr; 1557 } 1558 1559 clip_rect = (RECT *)clip_list->Buffer; 1560 for (i = 0; i < clip_list->rdh.nCount; ++i) 1561 { 1562 RECT src_rect_clipped = src_rect; 1563 1564 if (src_surface) 1565 { 1566 src_rect_clipped.left += (LONG)((clip_rect[i].left - dst_rect.left) * scale_x); 1567 src_rect_clipped.top += (LONG)((clip_rect[i].top - dst_rect.top) * scale_y); 1568 src_rect_clipped.right -= (LONG)((dst_rect.right - clip_rect[i].right) * scale_x); 1569 src_rect_clipped.bottom -= (LONG)((dst_rect.bottom - clip_rect[i].bottom) * scale_y); 1570 1571 if (src_surface->surface_desc.ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE) 1572 { 1573 if (FAILED(hr = ddraw_surface_update_frontbuffer(src_surface, &src_rect_clipped, TRUE, 0))) 1574 break; 1575 } 1576 } 1577 1578 if (FAILED(hr = ddraw_surface_blt(dst_surface, &clip_rect[i], 1579 src_surface, &src_rect_clipped, flags, fill_colour, fx, filter))) 1580 break; 1581 1582 if (dst_surface->surface_desc.ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE) 1583 { 1584 if (FAILED(hr = ddraw_surface_update_frontbuffer(dst_surface, &clip_rect[i], FALSE, 0))) 1585 break; 1586 } 1587 } 1588 1589 heap_free(clip_list); 1590 return hr; 1591 } 1592 1593 /***************************************************************************** 1594 * IDirectDrawSurface7::Blt 1595 * 1596 * Performs a blit on the surface 1597 * 1598 * Params: 1599 * DestRect: Destination rectangle, can be NULL 1600 * SrcSurface: Source surface, can be NULL 1601 * SrcRect: Source rectangle, can be NULL 1602 * Flags: Blt flags 1603 * DDBltFx: Some extended blt parameters, connected to the flags 1604 * 1605 * Returns: 1606 * D3D_OK on success, error code otherwise. 1607 * 1608 *****************************************************************************/ 1609 static HRESULT WINAPI DECLSPEC_HOTPATCH ddraw_surface7_Blt(IDirectDrawSurface7 *iface, RECT *dst_rect, 1610 IDirectDrawSurface7 *src_surface, RECT *src_rect, DWORD flags, DDBLTFX *fx) 1611 { 1612 struct ddraw_surface *dst_impl = impl_from_IDirectDrawSurface7(iface); 1613 struct ddraw_surface *src_impl = unsafe_impl_from_IDirectDrawSurface7(src_surface); 1614 struct wined3d_blt_fx wined3d_fx; 1615 DWORD unsupported_flags; 1616 DWORD fill_colour = 0; 1617 HRESULT hr = DD_OK; 1618 DDBLTFX rop_fx; 1619 1620 TRACE("iface %p, dst_rect %s, src_surface %p, src_rect %s, flags %#x, fx %p.\n", 1621 iface, wine_dbgstr_rect(dst_rect), src_surface, wine_dbgstr_rect(src_rect), flags, fx); 1622 1623 unsupported_flags = DDBLT_ALPHADEST 1624 | DDBLT_ALPHADESTCONSTOVERRIDE 1625 | DDBLT_ALPHADESTNEG 1626 | DDBLT_ALPHADESTSURFACEOVERRIDE 1627 | DDBLT_ALPHAEDGEBLEND 1628 | DDBLT_ALPHASRC 1629 | DDBLT_ALPHASRCCONSTOVERRIDE 1630 | DDBLT_ALPHASRCNEG 1631 | DDBLT_ALPHASRCSURFACEOVERRIDE 1632 | DDBLT_ZBUFFER 1633 | DDBLT_ZBUFFERDESTCONSTOVERRIDE 1634 | DDBLT_ZBUFFERDESTOVERRIDE 1635 | DDBLT_ZBUFFERSRCCONSTOVERRIDE 1636 | DDBLT_ZBUFFERSRCOVERRIDE; 1637 if (flags & unsupported_flags) 1638 { 1639 WARN("Ignoring unsupported flags %#x.\n", flags & unsupported_flags); 1640 flags &= ~unsupported_flags; 1641 } 1642 1643 if ((flags & DDBLT_KEYSRCOVERRIDE) && (!fx || flags & DDBLT_KEYSRC)) 1644 { 1645 WARN("Invalid source color key parameters, returning DDERR_INVALIDPARAMS\n"); 1646 return DDERR_INVALIDPARAMS; 1647 } 1648 1649 if ((flags & DDBLT_KEYDESTOVERRIDE) && (!fx || flags & DDBLT_KEYDEST)) 1650 { 1651 WARN("Invalid destination color key parameters, returning DDERR_INVALIDPARAMS\n"); 1652 return DDERR_INVALIDPARAMS; 1653 } 1654 1655 if (flags & DDBLT_DDROPS) 1656 { 1657 FIXME("DDBLT_DDROPS not implemented.\n"); 1658 if (fx) 1659 FIXME(" rop %#x, pattern %p.\n", fx->dwDDROP, fx->u5.lpDDSPattern); 1660 return DDERR_NORASTEROPHW; 1661 } 1662 1663 wined3d_mutex_lock(); 1664 1665 if (flags & (DDBLT_COLORFILL | DDBLT_DEPTHFILL)) 1666 { 1667 if (flags & DDBLT_ROP) 1668 { 1669 wined3d_mutex_unlock(); 1670 WARN("DDBLT_ROP used with DDBLT_COLORFILL or DDBLT_DEPTHFILL, returning DDERR_INVALIDPARAMS.\n"); 1671 return DDERR_INVALIDPARAMS; 1672 } 1673 if (src_impl) 1674 { 1675 wined3d_mutex_unlock(); 1676 WARN("Depth or colorfill is not compatible with source surfaces, returning DDERR_INVALIDPARAMS\n"); 1677 return DDERR_INVALIDPARAMS; 1678 } 1679 if (!fx) 1680 { 1681 wined3d_mutex_unlock(); 1682 WARN("Depth or colorfill used with NULL fx, returning DDERR_INVALIDPARAMS.\n"); 1683 return DDERR_INVALIDPARAMS; 1684 } 1685 1686 if ((flags & (DDBLT_COLORFILL | DDBLT_DEPTHFILL)) == (DDBLT_COLORFILL | DDBLT_DEPTHFILL)) 1687 flags &= ~DDBLT_DEPTHFILL; 1688 1689 if ((dst_impl->surface_desc.ddsCaps.dwCaps & DDSCAPS_ZBUFFER) && (flags & DDBLT_COLORFILL)) 1690 { 1691 wined3d_mutex_unlock(); 1692 WARN("DDBLT_COLORFILL used on a depth buffer, returning DDERR_INVALIDPARAMS.\n"); 1693 return DDERR_INVALIDPARAMS; 1694 } 1695 if (!(dst_impl->surface_desc.ddsCaps.dwCaps & DDSCAPS_ZBUFFER) && (flags & DDBLT_DEPTHFILL)) 1696 { 1697 wined3d_mutex_unlock(); 1698 WARN("DDBLT_DEPTHFILL used on a color buffer, returning DDERR_INVALIDPARAMS.\n"); 1699 return DDERR_INVALIDPARAMS; 1700 } 1701 } 1702 1703 if (flags & DDBLT_ROP) 1704 { 1705 if (!fx) 1706 { 1707 wined3d_mutex_unlock(); 1708 WARN("DDBLT_ROP used with NULL fx, returning DDERR_INVALIDPARAMS.\n"); 1709 return DDERR_INVALIDPARAMS; 1710 } 1711 1712 if (src_impl && src_rect 1713 && ((ULONG)src_rect->left >= src_rect->right || src_rect->right > src_impl->surface_desc.dwWidth 1714 || (ULONG)src_rect->top >= src_rect->bottom || src_rect->bottom > src_impl->surface_desc.dwHeight)) 1715 { 1716 WARN("Invalid source rectangle.\n"); 1717 return DDERR_INVALIDRECT; 1718 } 1719 1720 flags &= ~DDBLT_ROP; 1721 switch (fx->dwROP) 1722 { 1723 case SRCCOPY: 1724 break; 1725 1726 case WHITENESS: 1727 case BLACKNESS: 1728 rop_fx = *fx; 1729 1730 if (fx->dwROP == WHITENESS) 1731 rop_fx.u5.dwFillColor = 0xffffffff; 1732 else 1733 rop_fx.u5.dwFillColor = 0; 1734 1735 if (dst_impl->surface_desc.ddsCaps.dwCaps & DDSCAPS_ZBUFFER) 1736 flags |= DDBLT_DEPTHFILL; 1737 else 1738 flags |= DDBLT_COLORFILL; 1739 1740 fx = &rop_fx; 1741 break; 1742 1743 default: 1744 wined3d_mutex_unlock(); 1745 WARN("Unsupported ROP %#x used, returning DDERR_NORASTEROPHW.\n", fx->dwROP); 1746 return DDERR_NORASTEROPHW; 1747 } 1748 } 1749 1750 if (!(flags & (DDBLT_COLORFILL | DDBLT_DEPTHFILL)) && !src_impl) 1751 { 1752 WARN("No source surface.\n"); 1753 return DDERR_INVALIDPARAMS; 1754 } 1755 1756 if (flags & DDBLT_KEYSRC && (!src_impl || !(src_impl->surface_desc.dwFlags & DDSD_CKSRCBLT))) 1757 { 1758 WARN("DDBLT_KEYSRC blit without color key in surface, returning DDERR_INVALIDPARAMS\n"); 1759 wined3d_mutex_unlock(); 1760 return DDERR_INVALIDPARAMS; 1761 } 1762 if (flags & DDBLT_KEYDEST && !(dst_impl->surface_desc.dwFlags & DDSD_CKDESTBLT)) 1763 { 1764 WARN("DDBLT_KEYDEST blit without color key in surface, returning DDERR_INVALIDPARAMS\n"); 1765 wined3d_mutex_unlock(); 1766 return DDERR_INVALIDPARAMS; 1767 } 1768 1769 if (fx) 1770 { 1771 wined3d_fx.fx = fx->dwDDFX; 1772 fill_colour = fx->u5.dwFillColor; 1773 wined3d_fx.dst_color_key.color_space_low_value = fx->ddckDestColorkey.dwColorSpaceLowValue; 1774 wined3d_fx.dst_color_key.color_space_high_value = fx->ddckDestColorkey.dwColorSpaceHighValue; 1775 wined3d_fx.src_color_key.color_space_low_value = fx->ddckSrcColorkey.dwColorSpaceLowValue; 1776 wined3d_fx.src_color_key.color_space_high_value = fx->ddckSrcColorkey.dwColorSpaceHighValue; 1777 } 1778 1779 hr = ddraw_surface_blt_clipped(dst_impl, dst_rect, src_impl, 1780 src_rect, flags, fill_colour, fx ? &wined3d_fx : NULL, WINED3D_TEXF_LINEAR); 1781 1782 wined3d_mutex_unlock(); 1783 switch(hr) 1784 { 1785 case WINED3DERR_NOTAVAILABLE: return DDERR_UNSUPPORTED; 1786 default: return hr; 1787 } 1788 } 1789 1790 static HRESULT WINAPI DECLSPEC_HOTPATCH ddraw_surface4_Blt(IDirectDrawSurface4 *iface, RECT *dst_rect, 1791 IDirectDrawSurface4 *src_surface, RECT *src_rect, DWORD flags, DDBLTFX *fx) 1792 { 1793 struct ddraw_surface *dst = impl_from_IDirectDrawSurface4(iface); 1794 struct ddraw_surface *src = unsafe_impl_from_IDirectDrawSurface4(src_surface); 1795 1796 TRACE("iface %p, dst_rect %s, src_surface %p, src_rect %s, flags %#x, fx %p.\n", 1797 iface, wine_dbgstr_rect(dst_rect), src_surface, wine_dbgstr_rect(src_rect), flags, fx); 1798 1799 return ddraw_surface7_Blt(&dst->IDirectDrawSurface7_iface, dst_rect, 1800 src ? &src->IDirectDrawSurface7_iface : NULL, src_rect, flags, fx); 1801 } 1802 1803 static HRESULT WINAPI DECLSPEC_HOTPATCH ddraw_surface3_Blt(IDirectDrawSurface3 *iface, RECT *dst_rect, 1804 IDirectDrawSurface3 *src_surface, RECT *src_rect, DWORD flags, DDBLTFX *fx) 1805 { 1806 struct ddraw_surface *dst = impl_from_IDirectDrawSurface3(iface); 1807 struct ddraw_surface *src_impl = unsafe_impl_from_IDirectDrawSurface3(src_surface); 1808 1809 TRACE("iface %p, dst_rect %s, src_surface %p, src_rect %s, flags %#x, fx %p.\n", 1810 iface, wine_dbgstr_rect(dst_rect), src_surface, wine_dbgstr_rect(src_rect), flags, fx); 1811 1812 return ddraw_surface7_Blt(&dst->IDirectDrawSurface7_iface, dst_rect, 1813 src_impl ? &src_impl->IDirectDrawSurface7_iface : NULL, src_rect, flags, fx); 1814 } 1815 1816 static HRESULT WINAPI DECLSPEC_HOTPATCH ddraw_surface2_Blt(IDirectDrawSurface2 *iface, RECT *dst_rect, 1817 IDirectDrawSurface2 *src_surface, RECT *src_rect, DWORD flags, DDBLTFX *fx) 1818 { 1819 struct ddraw_surface *dst = impl_from_IDirectDrawSurface2(iface); 1820 struct ddraw_surface *src_impl = unsafe_impl_from_IDirectDrawSurface2(src_surface); 1821 1822 TRACE("iface %p, dst_rect %s, src_surface %p, src_rect %s, flags %#x, fx %p.\n", 1823 iface, wine_dbgstr_rect(dst_rect), src_surface, wine_dbgstr_rect(src_rect), flags, fx); 1824 1825 return ddraw_surface7_Blt(&dst->IDirectDrawSurface7_iface, dst_rect, 1826 src_impl ? &src_impl->IDirectDrawSurface7_iface : NULL, src_rect, flags, fx); 1827 } 1828 1829 static HRESULT WINAPI DECLSPEC_HOTPATCH ddraw_surface1_Blt(IDirectDrawSurface *iface, RECT *dst_rect, 1830 IDirectDrawSurface *src_surface, RECT *src_rect, DWORD flags, DDBLTFX *fx) 1831 { 1832 struct ddraw_surface *dst = impl_from_IDirectDrawSurface(iface); 1833 struct ddraw_surface *src_impl = unsafe_impl_from_IDirectDrawSurface(src_surface); 1834 1835 TRACE("iface %p, dst_rect %s, src_surface %p, src_rect %s, flags %#x, fx %p.\n", 1836 iface, wine_dbgstr_rect(dst_rect), src_surface, wine_dbgstr_rect(src_rect), flags, fx); 1837 1838 return ddraw_surface7_Blt(&dst->IDirectDrawSurface7_iface, dst_rect, 1839 src_impl ? &src_impl->IDirectDrawSurface7_iface : NULL, src_rect, flags, fx); 1840 } 1841 1842 /***************************************************************************** 1843 * IDirectDrawSurface7::AddAttachedSurface 1844 * 1845 * Attaches a surface to another surface. How the surface attachments work 1846 * is not totally understood yet, and this method is prone to problems. 1847 * The surface that is attached is AddRef-ed. 1848 * 1849 * Tests with complex surfaces suggest that the surface attachments form a 1850 * tree, but no method to test this has been found yet. 1851 * 1852 * The attachment list consists of a first surface (first_attached) and 1853 * for each surface a pointer to the next attached surface (next_attached). 1854 * For the first surface, and a surface that has no attachments 1855 * first_attached points to the surface itself. A surface that has 1856 * no successors in the chain has next_attached set to NULL. 1857 * 1858 * Newly attached surfaces are attached right after the root surface. 1859 * If a surface is attached to a complex surface compound, it's attached to 1860 * the surface that the app requested, not the complex root. See 1861 * GetAttachedSurface for a description how surfaces are found. 1862 * 1863 * This is how the current implementation works, and it was coded by looking 1864 * at the needs of the applications. 1865 * 1866 * So far only Z-Buffer attachments are tested, and they are activated in 1867 * WineD3D. Mipmaps could be tricky to activate in WineD3D. 1868 * Back buffers should work in 2D mode, but they are not tested(They can be 1869 * attached in older iface versions). Rendering to the front buffer and 1870 * switching between that and double buffering is not yet implemented in 1871 * WineD3D, so for 3D it might have unexpected results. 1872 * 1873 * ddraw_surface_attach_surface is the real thing, 1874 * ddraw_surface7_AddAttachedSurface is a wrapper around it that 1875 * performs additional checks. Version 7 of this interface is much more restrictive 1876 * than its predecessors. 1877 * 1878 * Params: 1879 * Attach: Surface to attach to iface 1880 * 1881 * Returns: 1882 * DD_OK on success 1883 * DDERR_CANNOTATTACHSURFACE if the surface can't be attached for some reason 1884 * 1885 *****************************************************************************/ 1886 static HRESULT ddraw_surface_attach_surface(struct ddraw_surface *This, struct ddraw_surface *Surf) 1887 { 1888 TRACE("surface %p, attachment %p.\n", This, Surf); 1889 1890 if(Surf == This) 1891 return DDERR_CANNOTATTACHSURFACE; /* unchecked */ 1892 1893 wined3d_mutex_lock(); 1894 1895 /* Check if the surface is already attached somewhere */ 1896 if (Surf->next_attached || Surf->first_attached != Surf) 1897 { 1898 /* TODO: Test for the structure of the manual attachment. Is it a 1899 * chain or a list? What happens if one surface is attached to 2 1900 * different surfaces? */ 1901 WARN("Surface %p is already attached somewhere. next_attached %p, first_attached %p.\n", 1902 Surf, Surf->next_attached, Surf->first_attached); 1903 1904 wined3d_mutex_unlock(); 1905 return DDERR_SURFACEALREADYATTACHED; 1906 } 1907 1908 /* This inserts the new surface at the 2nd position in the chain, right after the root surface */ 1909 Surf->next_attached = This->next_attached; 1910 Surf->first_attached = This->first_attached; 1911 This->next_attached = Surf; 1912 1913 /* Check if the WineD3D depth stencil needs updating */ 1914 if (This->ddraw->d3ddevice) 1915 d3d_device_update_depth_stencil(This->ddraw->d3ddevice); 1916 1917 wined3d_mutex_unlock(); 1918 1919 return DD_OK; 1920 } 1921 1922 static HRESULT WINAPI ddraw_surface7_AddAttachedSurface(IDirectDrawSurface7 *iface, IDirectDrawSurface7 *attachment) 1923 { 1924 struct ddraw_surface *This = impl_from_IDirectDrawSurface7(iface); 1925 struct ddraw_surface *attachment_impl = unsafe_impl_from_IDirectDrawSurface7(attachment); 1926 HRESULT hr; 1927 1928 TRACE("iface %p, attachment %p.\n", iface, attachment); 1929 1930 /* Version 7 of this interface seems to refuse everything except z buffers, as per msdn */ 1931 if(!(attachment_impl->surface_desc.ddsCaps.dwCaps & DDSCAPS_ZBUFFER)) 1932 { 1933 1934 WARN("Application tries to attach a non Z buffer surface. caps %08x\n", 1935 attachment_impl->surface_desc.ddsCaps.dwCaps); 1936 return DDERR_CANNOTATTACHSURFACE; 1937 } 1938 1939 hr = ddraw_surface_attach_surface(This, attachment_impl); 1940 if (FAILED(hr)) 1941 { 1942 return hr; 1943 } 1944 attachment_impl->attached_iface = (IUnknown *)attachment; 1945 IUnknown_AddRef(attachment_impl->attached_iface); 1946 return hr; 1947 } 1948 1949 static HRESULT WINAPI ddraw_surface4_AddAttachedSurface(IDirectDrawSurface4 *iface, IDirectDrawSurface4 *attachment) 1950 { 1951 struct ddraw_surface *surface = impl_from_IDirectDrawSurface4(iface); 1952 struct ddraw_surface *attachment_impl = unsafe_impl_from_IDirectDrawSurface4(attachment); 1953 HRESULT hr; 1954 1955 TRACE("iface %p, attachment %p.\n", iface, attachment); 1956 1957 /* Tests suggest that 1958 * -> offscreen plain surfaces can be attached to other offscreen plain surfaces 1959 * -> offscreen plain surfaces can be attached to primaries 1960 * -> primaries can be attached to offscreen plain surfaces 1961 * -> z buffers can be attached to primaries */ 1962 if (surface->surface_desc.ddsCaps.dwCaps & (DDSCAPS_PRIMARYSURFACE | DDSCAPS_OFFSCREENPLAIN) 1963 && attachment_impl->surface_desc.ddsCaps.dwCaps & (DDSCAPS_PRIMARYSURFACE | DDSCAPS_OFFSCREENPLAIN)) 1964 { 1965 /* Sizes have to match */ 1966 if (attachment_impl->surface_desc.dwWidth != surface->surface_desc.dwWidth 1967 || attachment_impl->surface_desc.dwHeight != surface->surface_desc.dwHeight) 1968 { 1969 WARN("Surface sizes do not match.\n"); 1970 return DDERR_CANNOTATTACHSURFACE; 1971 } 1972 } 1973 else if (!(surface->surface_desc.ddsCaps.dwCaps & (DDSCAPS_PRIMARYSURFACE | DDSCAPS_3DDEVICE)) 1974 || !(attachment_impl->surface_desc.ddsCaps.dwCaps & (DDSCAPS_ZBUFFER))) 1975 { 1976 WARN("Invalid attachment combination.\n"); 1977 return DDERR_CANNOTATTACHSURFACE; 1978 } 1979 1980 if (FAILED(hr = ddraw_surface_attach_surface(surface, attachment_impl))) 1981 return hr; 1982 1983 attachment_impl->attached_iface = (IUnknown *)attachment; 1984 IUnknown_AddRef(attachment_impl->attached_iface); 1985 return hr; 1986 } 1987 1988 static HRESULT WINAPI ddraw_surface3_AddAttachedSurface(IDirectDrawSurface3 *iface, IDirectDrawSurface3 *attachment) 1989 { 1990 struct ddraw_surface *surface = impl_from_IDirectDrawSurface3(iface); 1991 struct ddraw_surface *attachment_impl = unsafe_impl_from_IDirectDrawSurface3(attachment); 1992 HRESULT hr; 1993 1994 TRACE("iface %p, attachment %p.\n", iface, attachment); 1995 1996 if (FAILED(hr = ddraw_surface4_AddAttachedSurface(&surface->IDirectDrawSurface4_iface, 1997 attachment_impl ? &attachment_impl->IDirectDrawSurface4_iface : NULL))) 1998 return hr; 1999 2000 attachment_impl->attached_iface = (IUnknown *)attachment; 2001 IUnknown_AddRef(attachment_impl->attached_iface); 2002 ddraw_surface4_Release(&attachment_impl->IDirectDrawSurface4_iface); 2003 return hr; 2004 } 2005 2006 static HRESULT WINAPI ddraw_surface2_AddAttachedSurface(IDirectDrawSurface2 *iface, IDirectDrawSurface2 *attachment) 2007 { 2008 struct ddraw_surface *surface = impl_from_IDirectDrawSurface2(iface); 2009 struct ddraw_surface *attachment_impl = unsafe_impl_from_IDirectDrawSurface2(attachment); 2010 HRESULT hr; 2011 2012 TRACE("iface %p, attachment %p.\n", iface, attachment); 2013 2014 if (FAILED(hr = ddraw_surface4_AddAttachedSurface(&surface->IDirectDrawSurface4_iface, 2015 attachment_impl ? &attachment_impl->IDirectDrawSurface4_iface : NULL))) 2016 return hr; 2017 2018 attachment_impl->attached_iface = (IUnknown *)attachment; 2019 IUnknown_AddRef(attachment_impl->attached_iface); 2020 ddraw_surface4_Release(&attachment_impl->IDirectDrawSurface4_iface); 2021 return hr; 2022 } 2023 2024 static HRESULT WINAPI ddraw_surface1_AddAttachedSurface(IDirectDrawSurface *iface, IDirectDrawSurface *attachment) 2025 { 2026 struct ddraw_surface *surface = impl_from_IDirectDrawSurface(iface); 2027 struct ddraw_surface *attachment_impl = unsafe_impl_from_IDirectDrawSurface(attachment); 2028 HRESULT hr; 2029 2030 TRACE("iface %p, attachment %p.\n", iface, attachment); 2031 2032 if (FAILED(hr = ddraw_surface4_AddAttachedSurface(&surface->IDirectDrawSurface4_iface, 2033 attachment_impl ? &attachment_impl->IDirectDrawSurface4_iface : NULL))) 2034 return hr; 2035 2036 attachment_impl->attached_iface = (IUnknown *)attachment; 2037 IUnknown_AddRef(attachment_impl->attached_iface); 2038 ddraw_surface4_Release(&attachment_impl->IDirectDrawSurface4_iface); 2039 return hr; 2040 } 2041 2042 /***************************************************************************** 2043 * IDirectDrawSurface7::DeleteAttachedSurface 2044 * 2045 * Removes a surface from the attachment chain. The surface's refcount 2046 * is decreased by one after it has been removed 2047 * 2048 * Params: 2049 * Flags: Some flags, not used by this implementation 2050 * Attach: Surface to detach 2051 * 2052 * Returns: 2053 * DD_OK on success 2054 * DDERR_SURFACENOTATTACHED if the surface isn't attached to 2055 * 2056 *****************************************************************************/ 2057 static HRESULT ddraw_surface_delete_attached_surface(struct ddraw_surface *surface, 2058 struct ddraw_surface *attachment, IUnknown *detach_iface) 2059 { 2060 struct ddraw_surface *prev = surface; 2061 2062 TRACE("surface %p, attachment %p, detach_iface %p.\n", surface, attachment, detach_iface); 2063 2064 wined3d_mutex_lock(); 2065 if (!attachment || (attachment->first_attached != surface) || (attachment == surface) ) 2066 { 2067 wined3d_mutex_unlock(); 2068 return DDERR_CANNOTDETACHSURFACE; 2069 } 2070 2071 if (attachment->attached_iface != detach_iface) 2072 { 2073 WARN("attachment->attach_iface %p != detach_iface %p.\n", attachment->attached_iface, detach_iface); 2074 wined3d_mutex_unlock(); 2075 return DDERR_SURFACENOTATTACHED; 2076 } 2077 2078 /* Remove MIPMAPSUBLEVEL if this seemed to be one */ 2079 if (surface->surface_desc.ddsCaps.dwCaps & attachment->surface_desc.ddsCaps.dwCaps & DDSCAPS_MIPMAP) 2080 { 2081 attachment->surface_desc.ddsCaps.dwCaps2 &= ~DDSCAPS2_MIPMAPSUBLEVEL; 2082 /* FIXME: we should probably also subtract from dwMipMapCount of this 2083 * and all parent surfaces */ 2084 } 2085 2086 /* Find the predecessor of the detached surface */ 2087 while (prev->next_attached != attachment) 2088 { 2089 if (!(prev = prev->next_attached)) 2090 { 2091 ERR("Failed to find predecessor of %p.\n", attachment); 2092 wined3d_mutex_unlock(); 2093 return DDERR_SURFACENOTATTACHED; 2094 } 2095 } 2096 2097 /* Unchain the surface */ 2098 prev->next_attached = attachment->next_attached; 2099 attachment->next_attached = NULL; 2100 attachment->first_attached = attachment; 2101 2102 /* Check if the wined3d depth stencil needs updating. Note that we don't 2103 * just call d3d_device_update_depth_stencil() here since it uses 2104 * QueryInterface(). Some applications, SCP - Containment Breach in 2105 * particular, modify the QueryInterface() pointer in the surface vtbl 2106 * but don't cleanup properly after the relevant dll is unloaded. */ 2107 if (attachment->surface_desc.ddsCaps.dwCaps & DDSCAPS_ZBUFFER 2108 && wined3d_device_get_depth_stencil_view(surface->ddraw->wined3d_device) == attachment->wined3d_rtv) 2109 wined3d_device_set_depth_stencil_view(surface->ddraw->wined3d_device, NULL); 2110 wined3d_mutex_unlock(); 2111 2112 /* Set attached_iface to NULL before releasing it, the surface may go 2113 * away. */ 2114 attachment->attached_iface = NULL; 2115 IUnknown_Release(detach_iface); 2116 2117 return DD_OK; 2118 } 2119 2120 static HRESULT WINAPI ddraw_surface7_DeleteAttachedSurface(IDirectDrawSurface7 *iface, 2121 DWORD flags, IDirectDrawSurface7 *attachment) 2122 { 2123 struct ddraw_surface *surface = impl_from_IDirectDrawSurface7(iface); 2124 struct ddraw_surface *attachment_impl = unsafe_impl_from_IDirectDrawSurface7(attachment); 2125 2126 TRACE("iface %p, flags %#x, attachment %p.\n", iface, flags, attachment); 2127 2128 return ddraw_surface_delete_attached_surface(surface, attachment_impl, (IUnknown *)attachment); 2129 } 2130 2131 static HRESULT WINAPI ddraw_surface4_DeleteAttachedSurface(IDirectDrawSurface4 *iface, 2132 DWORD flags, IDirectDrawSurface4 *attachment) 2133 { 2134 struct ddraw_surface *surface = impl_from_IDirectDrawSurface4(iface); 2135 struct ddraw_surface *attachment_impl = unsafe_impl_from_IDirectDrawSurface4(attachment); 2136 2137 TRACE("iface %p, flags %#x, attachment %p.\n", iface, flags, attachment); 2138 2139 return ddraw_surface_delete_attached_surface(surface, attachment_impl, (IUnknown *)attachment); 2140 } 2141 2142 static HRESULT WINAPI ddraw_surface3_DeleteAttachedSurface(IDirectDrawSurface3 *iface, 2143 DWORD flags, IDirectDrawSurface3 *attachment) 2144 { 2145 struct ddraw_surface *surface = impl_from_IDirectDrawSurface3(iface); 2146 struct ddraw_surface *attachment_impl = unsafe_impl_from_IDirectDrawSurface3(attachment); 2147 2148 TRACE("iface %p, flags %#x, attachment %p.\n", iface, flags, attachment); 2149 2150 return ddraw_surface_delete_attached_surface(surface, attachment_impl, (IUnknown *)attachment); 2151 } 2152 2153 static HRESULT WINAPI ddraw_surface2_DeleteAttachedSurface(IDirectDrawSurface2 *iface, 2154 DWORD flags, IDirectDrawSurface2 *attachment) 2155 { 2156 struct ddraw_surface *surface = impl_from_IDirectDrawSurface2(iface); 2157 struct ddraw_surface *attachment_impl = unsafe_impl_from_IDirectDrawSurface2(attachment); 2158 2159 TRACE("iface %p, flags %#x, attachment %p.\n", iface, flags, attachment); 2160 2161 return ddraw_surface_delete_attached_surface(surface, attachment_impl, (IUnknown *)attachment); 2162 } 2163 2164 static HRESULT WINAPI ddraw_surface1_DeleteAttachedSurface(IDirectDrawSurface *iface, 2165 DWORD flags, IDirectDrawSurface *attachment) 2166 { 2167 struct ddraw_surface *surface = impl_from_IDirectDrawSurface(iface); 2168 struct ddraw_surface *attachment_impl = unsafe_impl_from_IDirectDrawSurface(attachment); 2169 2170 TRACE("iface %p, flags %#x, attachment %p.\n", iface, flags, attachment); 2171 2172 return ddraw_surface_delete_attached_surface(surface, attachment_impl, (IUnknown *)attachment); 2173 } 2174 2175 /***************************************************************************** 2176 * IDirectDrawSurface7::AddOverlayDirtyRect 2177 * 2178 * "This method is not currently implemented" 2179 * 2180 * Params: 2181 * Rect: ? 2182 * 2183 * Returns: 2184 * DDERR_UNSUPPORTED 2185 * 2186 *****************************************************************************/ 2187 static HRESULT WINAPI ddraw_surface7_AddOverlayDirtyRect(IDirectDrawSurface7 *iface, RECT *Rect) 2188 { 2189 TRACE("iface %p, rect %s.\n", iface, wine_dbgstr_rect(Rect)); 2190 2191 return DDERR_UNSUPPORTED; /* unchecked */ 2192 } 2193 2194 static HRESULT WINAPI ddraw_surface4_AddOverlayDirtyRect(IDirectDrawSurface4 *iface, RECT *rect) 2195 { 2196 struct ddraw_surface *surface = impl_from_IDirectDrawSurface4(iface); 2197 2198 TRACE("iface %p, rect %s.\n", iface, wine_dbgstr_rect(rect)); 2199 2200 return ddraw_surface7_AddOverlayDirtyRect(&surface->IDirectDrawSurface7_iface, rect); 2201 } 2202 2203 static HRESULT WINAPI ddraw_surface3_AddOverlayDirtyRect(IDirectDrawSurface3 *iface, RECT *rect) 2204 { 2205 struct ddraw_surface *surface = impl_from_IDirectDrawSurface3(iface); 2206 2207 TRACE("iface %p, rect %s.\n", iface, wine_dbgstr_rect(rect)); 2208 2209 return ddraw_surface7_AddOverlayDirtyRect(&surface->IDirectDrawSurface7_iface, rect); 2210 } 2211 2212 static HRESULT WINAPI ddraw_surface2_AddOverlayDirtyRect(IDirectDrawSurface2 *iface, RECT *rect) 2213 { 2214 struct ddraw_surface *surface = impl_from_IDirectDrawSurface2(iface); 2215 2216 TRACE("iface %p, rect %s.\n", iface, wine_dbgstr_rect(rect)); 2217 2218 return ddraw_surface7_AddOverlayDirtyRect(&surface->IDirectDrawSurface7_iface, rect); 2219 } 2220 2221 static HRESULT WINAPI ddraw_surface1_AddOverlayDirtyRect(IDirectDrawSurface *iface, RECT *rect) 2222 { 2223 struct ddraw_surface *surface = impl_from_IDirectDrawSurface(iface); 2224 2225 TRACE("iface %p, rect %s.\n", iface, wine_dbgstr_rect(rect)); 2226 2227 return ddraw_surface7_AddOverlayDirtyRect(&surface->IDirectDrawSurface7_iface, rect); 2228 } 2229 2230 /***************************************************************************** 2231 * IDirectDrawSurface7::GetDC 2232 * 2233 * Returns a GDI device context for the surface 2234 * 2235 * Params: 2236 * hdc: Address of a HDC variable to store the dc to 2237 * 2238 * Returns: 2239 * DD_OK on success 2240 * DDERR_INVALIDPARAMS if hdc is NULL 2241 * 2242 *****************************************************************************/ 2243 static HRESULT WINAPI ddraw_surface7_GetDC(IDirectDrawSurface7 *iface, HDC *dc) 2244 { 2245 struct ddraw_surface *surface = impl_from_IDirectDrawSurface7(iface); 2246 HRESULT hr = DD_OK; 2247 2248 TRACE("iface %p, dc %p.\n", iface, dc); 2249 2250 if (!dc) 2251 return DDERR_INVALIDPARAMS; 2252 2253 wined3d_mutex_lock(); 2254 if (surface->dc) 2255 hr = DDERR_DCALREADYCREATED; 2256 else if (surface->surface_desc.ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE) 2257 hr = ddraw_surface_update_frontbuffer(surface, NULL, TRUE, 0); 2258 if (SUCCEEDED(hr)) 2259 hr = wined3d_texture_get_dc(surface->wined3d_texture, surface->sub_resource_idx, dc); 2260 2261 if (SUCCEEDED(hr)) 2262 { 2263 surface->dc = *dc; 2264 2265 if (format_is_paletteindexed(&surface->surface_desc.u4.ddpfPixelFormat)) 2266 { 2267 const struct ddraw_palette *palette; 2268 2269 if (surface->palette) 2270 palette = surface->palette; 2271 else if (surface->ddraw->primary) 2272 palette = surface->ddraw->primary->palette; 2273 else 2274 palette = NULL; 2275 2276 if (palette) 2277 wined3d_palette_apply_to_dc(palette->wined3d_palette, *dc); 2278 } 2279 } 2280 2281 wined3d_mutex_unlock(); 2282 switch (hr) 2283 { 2284 /* Some, but not all errors set *dc to NULL. E.g. DCALREADYCREATED 2285 * does not touch *dc. */ 2286 case WINED3DERR_INVALIDCALL: 2287 *dc = NULL; 2288 return DDERR_CANTCREATEDC; 2289 2290 default: 2291 return hr; 2292 } 2293 } 2294 2295 static HRESULT WINAPI ddraw_surface4_GetDC(IDirectDrawSurface4 *iface, HDC *dc) 2296 { 2297 struct ddraw_surface *surface = impl_from_IDirectDrawSurface4(iface); 2298 2299 TRACE("iface %p, dc %p.\n", iface, dc); 2300 2301 return ddraw_surface7_GetDC(&surface->IDirectDrawSurface7_iface, dc); 2302 } 2303 2304 static HRESULT WINAPI ddraw_surface3_GetDC(IDirectDrawSurface3 *iface, HDC *dc) 2305 { 2306 struct ddraw_surface *surface = impl_from_IDirectDrawSurface3(iface); 2307 2308 TRACE("iface %p, dc %p.\n", iface, dc); 2309 2310 return ddraw_surface7_GetDC(&surface->IDirectDrawSurface7_iface, dc); 2311 } 2312 2313 static HRESULT WINAPI ddraw_surface2_GetDC(IDirectDrawSurface2 *iface, HDC *dc) 2314 { 2315 struct ddraw_surface *surface = impl_from_IDirectDrawSurface2(iface); 2316 2317 TRACE("iface %p, dc %p.\n", iface, dc); 2318 2319 return ddraw_surface7_GetDC(&surface->IDirectDrawSurface7_iface, dc); 2320 } 2321 2322 static HRESULT WINAPI ddraw_surface1_GetDC(IDirectDrawSurface *iface, HDC *dc) 2323 { 2324 struct ddraw_surface *surface = impl_from_IDirectDrawSurface(iface); 2325 2326 TRACE("iface %p, dc %p.\n", iface, dc); 2327 2328 return ddraw_surface7_GetDC(&surface->IDirectDrawSurface7_iface, dc); 2329 } 2330 2331 /***************************************************************************** 2332 * IDirectDrawSurface7::ReleaseDC 2333 * 2334 * Releases the DC that was constructed with GetDC 2335 * 2336 * Params: 2337 * hdc: HDC to release 2338 * 2339 * Returns: 2340 * DD_OK on success, error code otherwise. 2341 * 2342 *****************************************************************************/ 2343 static HRESULT WINAPI ddraw_surface7_ReleaseDC(IDirectDrawSurface7 *iface, HDC hdc) 2344 { 2345 struct ddraw_surface *surface = impl_from_IDirectDrawSurface7(iface); 2346 HRESULT hr; 2347 2348 TRACE("iface %p, dc %p.\n", iface, hdc); 2349 #ifdef __REACTOS__ 2350 GdiFlush(); 2351 #endif 2352 wined3d_mutex_lock(); 2353 if (!surface->dc) 2354 { 2355 hr = DDERR_NODC; 2356 } 2357 else if (SUCCEEDED(hr = wined3d_texture_release_dc(surface->wined3d_texture, surface->sub_resource_idx, hdc))) 2358 { 2359 surface->dc = NULL; 2360 if (surface->surface_desc.ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE) 2361 hr = ddraw_surface_update_frontbuffer(surface, NULL, FALSE, 0); 2362 } 2363 wined3d_mutex_unlock(); 2364 2365 2366 return hr; 2367 } 2368 2369 static HRESULT WINAPI ddraw_surface4_ReleaseDC(IDirectDrawSurface4 *iface, HDC dc) 2370 { 2371 struct ddraw_surface *surface = impl_from_IDirectDrawSurface4(iface); 2372 2373 TRACE("iface %p, dc %p.\n", iface, dc); 2374 2375 return ddraw_surface7_ReleaseDC(&surface->IDirectDrawSurface7_iface, dc); 2376 } 2377 2378 static HRESULT WINAPI ddraw_surface3_ReleaseDC(IDirectDrawSurface3 *iface, HDC dc) 2379 { 2380 struct ddraw_surface *surface = impl_from_IDirectDrawSurface3(iface); 2381 2382 TRACE("iface %p, dc %p.\n", iface, dc); 2383 2384 return ddraw_surface7_ReleaseDC(&surface->IDirectDrawSurface7_iface, dc); 2385 } 2386 2387 static HRESULT WINAPI ddraw_surface2_ReleaseDC(IDirectDrawSurface2 *iface, HDC dc) 2388 { 2389 struct ddraw_surface *surface = impl_from_IDirectDrawSurface2(iface); 2390 2391 TRACE("iface %p, dc %p.\n", iface, dc); 2392 2393 return ddraw_surface7_ReleaseDC(&surface->IDirectDrawSurface7_iface, dc); 2394 } 2395 2396 static HRESULT WINAPI ddraw_surface1_ReleaseDC(IDirectDrawSurface *iface, HDC dc) 2397 { 2398 struct ddraw_surface *surface = impl_from_IDirectDrawSurface(iface); 2399 2400 TRACE("iface %p, dc %p.\n", iface, dc); 2401 2402 return ddraw_surface7_ReleaseDC(&surface->IDirectDrawSurface7_iface, dc); 2403 } 2404 2405 /***************************************************************************** 2406 * IDirectDrawSurface7::GetCaps 2407 * 2408 * Returns the surface's caps 2409 * 2410 * Params: 2411 * Caps: Address to write the caps to 2412 * 2413 * Returns: 2414 * DD_OK on success 2415 * DDERR_INVALIDPARAMS if Caps is NULL 2416 * 2417 *****************************************************************************/ 2418 static HRESULT WINAPI ddraw_surface7_GetCaps(IDirectDrawSurface7 *iface, DDSCAPS2 *Caps) 2419 { 2420 struct ddraw_surface *surface = impl_from_IDirectDrawSurface7(iface); 2421 2422 TRACE("iface %p, caps %p.\n", iface, Caps); 2423 2424 if(!Caps) 2425 return DDERR_INVALIDPARAMS; 2426 2427 *Caps = surface->surface_desc.ddsCaps; 2428 2429 return DD_OK; 2430 } 2431 2432 static HRESULT WINAPI ddraw_surface4_GetCaps(IDirectDrawSurface4 *iface, DDSCAPS2 *caps) 2433 { 2434 struct ddraw_surface *surface = impl_from_IDirectDrawSurface4(iface); 2435 2436 TRACE("iface %p, caps %p.\n", iface, caps); 2437 2438 return ddraw_surface7_GetCaps(&surface->IDirectDrawSurface7_iface, caps); 2439 } 2440 2441 static HRESULT WINAPI ddraw_surface3_GetCaps(IDirectDrawSurface3 *iface, DDSCAPS *caps) 2442 { 2443 struct ddraw_surface *surface = impl_from_IDirectDrawSurface3(iface); 2444 DDSCAPS2 caps2; 2445 HRESULT hr; 2446 2447 TRACE("iface %p, caps %p.\n", iface, caps); 2448 2449 hr = ddraw_surface7_GetCaps(&surface->IDirectDrawSurface7_iface, &caps2); 2450 if (FAILED(hr)) return hr; 2451 2452 caps->dwCaps = caps2.dwCaps; 2453 return hr; 2454 } 2455 2456 static HRESULT WINAPI ddraw_surface2_GetCaps(IDirectDrawSurface2 *iface, DDSCAPS *caps) 2457 { 2458 struct ddraw_surface *surface = impl_from_IDirectDrawSurface2(iface); 2459 DDSCAPS2 caps2; 2460 HRESULT hr; 2461 2462 TRACE("iface %p, caps %p.\n", iface, caps); 2463 2464 hr = ddraw_surface7_GetCaps(&surface->IDirectDrawSurface7_iface, &caps2); 2465 if (FAILED(hr)) return hr; 2466 2467 caps->dwCaps = caps2.dwCaps; 2468 return hr; 2469 } 2470 2471 static HRESULT WINAPI ddraw_surface1_GetCaps(IDirectDrawSurface *iface, DDSCAPS *caps) 2472 { 2473 struct ddraw_surface *surface = impl_from_IDirectDrawSurface(iface); 2474 DDSCAPS2 caps2; 2475 HRESULT hr; 2476 2477 TRACE("iface %p, caps %p.\n", iface, caps); 2478 2479 hr = ddraw_surface7_GetCaps(&surface->IDirectDrawSurface7_iface, &caps2); 2480 if (FAILED(hr)) return hr; 2481 2482 caps->dwCaps = caps2.dwCaps; 2483 return hr; 2484 } 2485 2486 static HRESULT WINAPI ddraw_surface7_SetPriority(IDirectDrawSurface7 *iface, DWORD priority) 2487 { 2488 struct ddraw_surface *surface = impl_from_IDirectDrawSurface7(iface); 2489 DWORD managed = DDSCAPS2_TEXTUREMANAGE | DDSCAPS2_D3DTEXTUREMANAGE; 2490 HRESULT hr; 2491 struct wined3d_resource *resource; 2492 2493 TRACE("iface %p, priority %u.\n", iface, priority); 2494 2495 wined3d_mutex_lock(); 2496 /* No need to check for offscreen plain surfaces or mipmap sublevels. SetPriority 2497 * calls on such surfaces segfault on Windows. */ 2498 if (!(surface->surface_desc.ddsCaps.dwCaps2 & managed)) 2499 { 2500 WARN("Called on non-managed texture returning DDERR_INVALIDPARAMS.\n"); 2501 hr = DDERR_INVALIDPARAMS; 2502 } 2503 else 2504 { 2505 resource = wined3d_texture_get_resource(surface->wined3d_texture); 2506 wined3d_resource_set_priority(resource, priority); 2507 hr = DD_OK; 2508 } 2509 wined3d_mutex_unlock(); 2510 2511 return hr; 2512 } 2513 2514 static HRESULT WINAPI ddraw_surface7_GetPriority(IDirectDrawSurface7 *iface, DWORD *priority) 2515 { 2516 struct ddraw_surface *surface = impl_from_IDirectDrawSurface7(iface); 2517 const struct wined3d_resource *resource; 2518 DWORD managed = DDSCAPS2_TEXTUREMANAGE | DDSCAPS2_D3DTEXTUREMANAGE; 2519 HRESULT hr; 2520 2521 TRACE("iface %p, priority %p.\n", iface, priority); 2522 2523 wined3d_mutex_lock(); 2524 if (surface->surface_desc.ddsCaps.dwCaps & DDSCAPS_OFFSCREENPLAIN) 2525 { 2526 WARN("Called on offscreenplain surface, returning DDERR_INVALIDOBJECT.\n"); 2527 hr = DDERR_INVALIDOBJECT; 2528 } 2529 else if (!(surface->surface_desc.ddsCaps.dwCaps2 & managed) || !surface->is_complex_root) 2530 { 2531 WARN("Called on non-managed texture or non-root surface, returning DDERR_INVALIDPARAMS.\n"); 2532 hr = DDERR_INVALIDPARAMS; 2533 } 2534 else 2535 { 2536 resource = wined3d_texture_get_resource(surface->wined3d_texture); 2537 *priority = wined3d_resource_get_priority(resource); 2538 hr = DD_OK; 2539 } 2540 wined3d_mutex_unlock(); 2541 2542 return hr; 2543 } 2544 2545 /***************************************************************************** 2546 * IDirectDrawSurface7::SetPrivateData 2547 * 2548 * Stores some data in the surface that is intended for the application's 2549 * use. 2550 * 2551 * Params: 2552 * tag: GUID that identifies the data 2553 * Data: Pointer to the private data 2554 * Size: Size of the private data 2555 * Flags: Some flags 2556 * 2557 * Returns: 2558 * D3D_OK on success, error code otherwise. 2559 * 2560 *****************************************************************************/ 2561 static HRESULT WINAPI ddraw_surface7_SetPrivateData(IDirectDrawSurface7 *iface, 2562 REFGUID tag, void *data, DWORD size, DWORD flags) 2563 { 2564 struct ddraw_surface *surface = impl_from_IDirectDrawSurface7(iface); 2565 HRESULT hr; 2566 2567 TRACE("iface %p, tag %s, data %p, data_size %u, flags %#x.\n", 2568 iface, debugstr_guid(tag), data, size, flags); 2569 2570 if (!data) 2571 { 2572 WARN("data is NULL, returning DDERR_INVALIDPARAMS.\n"); 2573 return DDERR_INVALIDPARAMS; 2574 } 2575 2576 wined3d_mutex_lock(); 2577 hr = wined3d_private_store_set_private_data(&surface->private_store, tag, data, size, flags); 2578 wined3d_mutex_unlock(); 2579 return hr_ddraw_from_wined3d(hr); 2580 } 2581 2582 static HRESULT WINAPI ddraw_surface4_SetPrivateData(IDirectDrawSurface4 *iface, 2583 REFGUID tag, void *data, DWORD size, DWORD flags) 2584 { 2585 struct ddraw_surface *surface = impl_from_IDirectDrawSurface4(iface); 2586 2587 TRACE("iface %p, tag %s, data %p, data_size %u, flags %#x.\n", 2588 iface, debugstr_guid(tag), data, size, flags); 2589 2590 return ddraw_surface7_SetPrivateData(&surface->IDirectDrawSurface7_iface, tag, data, size, flags); 2591 } 2592 2593 /***************************************************************************** 2594 * IDirectDrawSurface7::GetPrivateData 2595 * 2596 * Returns the private data set with IDirectDrawSurface7::SetPrivateData 2597 * 2598 * Params: 2599 * tag: GUID of the data to return 2600 * Data: Address where to write the data to 2601 * Size: Size of the buffer at Data 2602 * 2603 * Returns: 2604 * DD_OK on success 2605 * DDERR_INVALIDPARAMS if Data is NULL 2606 * 2607 *****************************************************************************/ 2608 static HRESULT WINAPI ddraw_surface7_GetPrivateData(IDirectDrawSurface7 *iface, REFGUID tag, void *data, DWORD *size) 2609 { 2610 struct ddraw_surface *surface = impl_from_IDirectDrawSurface7(iface); 2611 const struct wined3d_private_data *stored_data; 2612 HRESULT hr; 2613 2614 TRACE("iface %p, tag %s, data %p, data_size %p.\n", 2615 iface, debugstr_guid(tag), data, size); 2616 2617 wined3d_mutex_lock(); 2618 stored_data = wined3d_private_store_get_private_data(&surface->private_store, tag); 2619 if (!stored_data) 2620 { 2621 hr = DDERR_NOTFOUND; 2622 goto done; 2623 } 2624 if (!size) 2625 { 2626 hr = DDERR_INVALIDPARAMS; 2627 goto done; 2628 } 2629 if (*size < stored_data->size) 2630 { 2631 *size = stored_data->size; 2632 hr = DDERR_MOREDATA; 2633 goto done; 2634 } 2635 if (!data) 2636 { 2637 hr = DDERR_INVALIDPARAMS; 2638 goto done; 2639 } 2640 2641 *size = stored_data->size; 2642 memcpy(data, stored_data->content.data, stored_data->size); 2643 hr = DD_OK; 2644 2645 done: 2646 wined3d_mutex_unlock(); 2647 return hr; 2648 } 2649 2650 static HRESULT WINAPI ddraw_surface4_GetPrivateData(IDirectDrawSurface4 *iface, REFGUID tag, void *data, DWORD *size) 2651 { 2652 struct ddraw_surface *surface = impl_from_IDirectDrawSurface4(iface); 2653 2654 TRACE("iface %p, tag %s, data %p, data_size %p.\n", 2655 iface, debugstr_guid(tag), data, size); 2656 2657 return ddraw_surface7_GetPrivateData(&surface->IDirectDrawSurface7_iface, tag, data, size); 2658 } 2659 2660 /***************************************************************************** 2661 * IDirectDrawSurface7::FreePrivateData 2662 * 2663 * Frees private data stored in the surface 2664 * 2665 * Params: 2666 * tag: Tag of the data to free 2667 * 2668 * Returns: 2669 * D3D_OK on success, error code otherwise. 2670 * 2671 *****************************************************************************/ 2672 static HRESULT WINAPI ddraw_surface7_FreePrivateData(IDirectDrawSurface7 *iface, REFGUID tag) 2673 { 2674 struct ddraw_surface *surface = impl_from_IDirectDrawSurface7(iface); 2675 struct wined3d_private_data *entry; 2676 2677 TRACE("iface %p, tag %s.\n", iface, debugstr_guid(tag)); 2678 2679 wined3d_mutex_lock(); 2680 entry = wined3d_private_store_get_private_data(&surface->private_store, tag); 2681 if (!entry) 2682 { 2683 wined3d_mutex_unlock(); 2684 return DDERR_NOTFOUND; 2685 } 2686 2687 wined3d_private_store_free_private_data(&surface->private_store, entry); 2688 wined3d_mutex_unlock(); 2689 2690 return DD_OK; 2691 } 2692 2693 static HRESULT WINAPI ddraw_surface4_FreePrivateData(IDirectDrawSurface4 *iface, REFGUID tag) 2694 { 2695 struct ddraw_surface *surface = impl_from_IDirectDrawSurface4(iface); 2696 2697 TRACE("iface %p, tag %s.\n", iface, debugstr_guid(tag)); 2698 2699 return ddraw_surface7_FreePrivateData(&surface->IDirectDrawSurface7_iface, tag); 2700 } 2701 2702 /***************************************************************************** 2703 * IDirectDrawSurface7::PageLock 2704 * 2705 * Prevents a sysmem surface from being paged out 2706 * 2707 * Params: 2708 * Flags: Not used, must be 0(unchecked) 2709 * 2710 * Returns: 2711 * DD_OK, because it's a stub 2712 * 2713 *****************************************************************************/ 2714 static HRESULT WINAPI ddraw_surface7_PageLock(IDirectDrawSurface7 *iface, DWORD Flags) 2715 { 2716 TRACE("iface %p, flags %#x.\n", iface, Flags); 2717 2718 /* This is Windows memory management related - we don't need this */ 2719 return DD_OK; 2720 } 2721 2722 static HRESULT WINAPI ddraw_surface4_PageLock(IDirectDrawSurface4 *iface, DWORD flags) 2723 { 2724 struct ddraw_surface *surface = impl_from_IDirectDrawSurface4(iface); 2725 2726 TRACE("iface %p, flags %#x.\n", iface, flags); 2727 2728 return ddraw_surface7_PageLock(&surface->IDirectDrawSurface7_iface, flags); 2729 } 2730 2731 static HRESULT WINAPI ddraw_surface3_PageLock(IDirectDrawSurface3 *iface, DWORD flags) 2732 { 2733 struct ddraw_surface *surface = impl_from_IDirectDrawSurface3(iface); 2734 2735 TRACE("iface %p, flags %#x.\n", iface, flags); 2736 2737 return ddraw_surface7_PageLock(&surface->IDirectDrawSurface7_iface, flags); 2738 } 2739 2740 static HRESULT WINAPI ddraw_surface2_PageLock(IDirectDrawSurface2 *iface, DWORD flags) 2741 { 2742 struct ddraw_surface *surface = impl_from_IDirectDrawSurface2(iface); 2743 2744 TRACE("iface %p, flags %#x.\n", iface, flags); 2745 2746 return ddraw_surface7_PageLock(&surface->IDirectDrawSurface7_iface, flags); 2747 } 2748 2749 /***************************************************************************** 2750 * IDirectDrawSurface7::PageUnlock 2751 * 2752 * Allows a sysmem surface to be paged out 2753 * 2754 * Params: 2755 * Flags: Not used, must be 0(unchecked) 2756 * 2757 * Returns: 2758 * DD_OK, because it's a stub 2759 * 2760 *****************************************************************************/ 2761 static HRESULT WINAPI ddraw_surface7_PageUnlock(IDirectDrawSurface7 *iface, DWORD Flags) 2762 { 2763 TRACE("iface %p, flags %#x.\n", iface, Flags); 2764 2765 return DD_OK; 2766 } 2767 2768 static HRESULT WINAPI ddraw_surface4_PageUnlock(IDirectDrawSurface4 *iface, DWORD flags) 2769 { 2770 struct ddraw_surface *surface = impl_from_IDirectDrawSurface4(iface); 2771 2772 TRACE("iface %p, flags %#x.\n", iface, flags); 2773 2774 return ddraw_surface7_PageUnlock(&surface->IDirectDrawSurface7_iface, flags); 2775 } 2776 2777 static HRESULT WINAPI ddraw_surface3_PageUnlock(IDirectDrawSurface3 *iface, DWORD flags) 2778 { 2779 struct ddraw_surface *surface = impl_from_IDirectDrawSurface3(iface); 2780 2781 TRACE("iface %p, flags %#x.\n", iface, flags); 2782 2783 return ddraw_surface7_PageUnlock(&surface->IDirectDrawSurface7_iface, flags); 2784 } 2785 2786 static HRESULT WINAPI ddraw_surface2_PageUnlock(IDirectDrawSurface2 *iface, DWORD flags) 2787 { 2788 struct ddraw_surface *surface = impl_from_IDirectDrawSurface2(iface); 2789 2790 TRACE("iface %p, flags %#x.\n", iface, flags); 2791 2792 return ddraw_surface7_PageUnlock(&surface->IDirectDrawSurface7_iface, flags); 2793 } 2794 2795 /***************************************************************************** 2796 * IDirectDrawSurface7::BltBatch 2797 * 2798 * An unimplemented function 2799 * 2800 * Params: 2801 * ? 2802 * 2803 * Returns: 2804 * DDERR_UNSUPPORTED 2805 * 2806 *****************************************************************************/ 2807 static HRESULT WINAPI DECLSPEC_HOTPATCH ddraw_surface7_BltBatch(IDirectDrawSurface7 *iface, DDBLTBATCH *Batch, DWORD Count, DWORD Flags) 2808 { 2809 TRACE("iface %p, batch %p, count %u, flags %#x.\n", iface, Batch, Count, Flags); 2810 2811 /* MSDN: "not currently implemented" */ 2812 return DDERR_UNSUPPORTED; 2813 } 2814 2815 static HRESULT WINAPI DECLSPEC_HOTPATCH ddraw_surface4_BltBatch(IDirectDrawSurface4 *iface, DDBLTBATCH *batch, DWORD count, DWORD flags) 2816 { 2817 struct ddraw_surface *surface = impl_from_IDirectDrawSurface4(iface); 2818 2819 TRACE("iface %p, batch %p, count %u, flags %#x.\n", iface, batch, count, flags); 2820 2821 return ddraw_surface7_BltBatch(&surface->IDirectDrawSurface7_iface, batch, count, flags); 2822 } 2823 2824 static HRESULT WINAPI DECLSPEC_HOTPATCH ddraw_surface3_BltBatch(IDirectDrawSurface3 *iface, DDBLTBATCH *batch, DWORD count, DWORD flags) 2825 { 2826 struct ddraw_surface *surface = impl_from_IDirectDrawSurface3(iface); 2827 2828 TRACE("iface %p, batch %p, count %u, flags %#x.\n", iface, batch, count, flags); 2829 2830 return ddraw_surface7_BltBatch(&surface->IDirectDrawSurface7_iface, batch, count, flags); 2831 } 2832 2833 static HRESULT WINAPI DECLSPEC_HOTPATCH ddraw_surface2_BltBatch(IDirectDrawSurface2 *iface, DDBLTBATCH *batch, DWORD count, DWORD flags) 2834 { 2835 struct ddraw_surface *surface = impl_from_IDirectDrawSurface2(iface); 2836 2837 TRACE("iface %p, batch %p, count %u, flags %#x.\n", iface, batch, count, flags); 2838 2839 return ddraw_surface7_BltBatch(&surface->IDirectDrawSurface7_iface, batch, count, flags); 2840 } 2841 2842 static HRESULT WINAPI DECLSPEC_HOTPATCH ddraw_surface1_BltBatch(IDirectDrawSurface *iface, DDBLTBATCH *batch, DWORD count, DWORD flags) 2843 { 2844 struct ddraw_surface *surface = impl_from_IDirectDrawSurface(iface); 2845 2846 TRACE("iface %p, batch %p, count %u, flags %#x.\n", iface, batch, count, flags); 2847 2848 return ddraw_surface7_BltBatch(&surface->IDirectDrawSurface7_iface, batch, count, flags); 2849 } 2850 2851 /***************************************************************************** 2852 * IDirectDrawSurface7::EnumAttachedSurfaces 2853 * 2854 * Enumerates all surfaces attached to this surface 2855 * 2856 * Params: 2857 * context: Pointer to pass unmodified to the callback 2858 * cb: Callback function to call for each surface 2859 * 2860 * Returns: 2861 * DD_OK on success 2862 * DDERR_INVALIDPARAMS if cb is NULL 2863 * 2864 *****************************************************************************/ 2865 static HRESULT WINAPI ddraw_surface7_EnumAttachedSurfaces(IDirectDrawSurface7 *iface, 2866 void *context, LPDDENUMSURFACESCALLBACK7 cb) 2867 { 2868 struct ddraw_surface *surface = impl_from_IDirectDrawSurface7(iface); 2869 struct ddraw_surface *surf; 2870 DDSURFACEDESC2 desc; 2871 int i; 2872 2873 /* Attached surfaces aren't handled in WineD3D */ 2874 TRACE("iface %p, context %p, callback %p.\n", iface, context, cb); 2875 2876 if(!cb) 2877 return DDERR_INVALIDPARAMS; 2878 2879 wined3d_mutex_lock(); 2880 2881 for(i = 0; i < MAX_COMPLEX_ATTACHED; i++) 2882 { 2883 surf = surface->complex_array[i]; 2884 if(!surf) break; 2885 2886 ddraw_surface7_AddRef(&surf->IDirectDrawSurface7_iface); 2887 desc = surf->surface_desc; 2888 /* check: != DDENUMRET_OK or == DDENUMRET_CANCEL? */ 2889 if (cb(&surf->IDirectDrawSurface7_iface, &desc, context) == DDENUMRET_CANCEL) 2890 { 2891 wined3d_mutex_unlock(); 2892 return DD_OK; 2893 } 2894 } 2895 2896 for (surf = surface->next_attached; surf != NULL; surf = surf->next_attached) 2897 { 2898 ddraw_surface7_AddRef(&surf->IDirectDrawSurface7_iface); 2899 desc = surf->surface_desc; 2900 /* check: != DDENUMRET_OK or == DDENUMRET_CANCEL? */ 2901 if (cb(&surf->IDirectDrawSurface7_iface, &desc, context) == DDENUMRET_CANCEL) 2902 { 2903 wined3d_mutex_unlock(); 2904 return DD_OK; 2905 } 2906 } 2907 2908 TRACE(" end of enumeration.\n"); 2909 2910 wined3d_mutex_unlock(); 2911 2912 return DD_OK; 2913 } 2914 2915 struct callback_info2 2916 { 2917 LPDDENUMSURFACESCALLBACK2 callback; 2918 void *context; 2919 }; 2920 2921 struct callback_info 2922 { 2923 LPDDENUMSURFACESCALLBACK callback; 2924 void *context; 2925 }; 2926 2927 static HRESULT CALLBACK EnumCallback2(IDirectDrawSurface7 *surface, DDSURFACEDESC2 *surface_desc, void *context) 2928 { 2929 struct ddraw_surface *surface_impl = impl_from_IDirectDrawSurface7(surface); 2930 const struct callback_info2 *info = context; 2931 2932 ddraw_surface4_AddRef(&surface_impl->IDirectDrawSurface4_iface); 2933 ddraw_surface7_Release(surface); 2934 2935 return info->callback(&surface_impl->IDirectDrawSurface4_iface, surface_desc, info->context); 2936 } 2937 2938 static HRESULT CALLBACK EnumCallback(IDirectDrawSurface7 *surface, DDSURFACEDESC2 *surface_desc, void *context) 2939 { 2940 struct ddraw_surface *surface_impl = impl_from_IDirectDrawSurface7(surface); 2941 const struct callback_info *info = context; 2942 2943 ddraw_surface1_AddRef(&surface_impl->IDirectDrawSurface_iface); 2944 ddraw_surface7_Release(surface); 2945 2946 /* FIXME: Check surface_test.dwSize */ 2947 return info->callback(&surface_impl->IDirectDrawSurface_iface, 2948 (DDSURFACEDESC *)surface_desc, info->context); 2949 } 2950 2951 static HRESULT WINAPI ddraw_surface4_EnumAttachedSurfaces(IDirectDrawSurface4 *iface, 2952 void *context, LPDDENUMSURFACESCALLBACK2 callback) 2953 { 2954 struct ddraw_surface *surface = impl_from_IDirectDrawSurface4(iface); 2955 struct callback_info2 info; 2956 2957 TRACE("iface %p, context %p, callback %p.\n", iface, context, callback); 2958 2959 info.callback = callback; 2960 info.context = context; 2961 2962 return ddraw_surface7_EnumAttachedSurfaces(&surface->IDirectDrawSurface7_iface, 2963 &info, EnumCallback2); 2964 } 2965 2966 static HRESULT WINAPI ddraw_surface3_EnumAttachedSurfaces(IDirectDrawSurface3 *iface, 2967 void *context, LPDDENUMSURFACESCALLBACK callback) 2968 { 2969 struct ddraw_surface *surface = impl_from_IDirectDrawSurface3(iface); 2970 struct callback_info info; 2971 2972 TRACE("iface %p, context %p, callback %p.\n", iface, context, callback); 2973 2974 info.callback = callback; 2975 info.context = context; 2976 2977 return ddraw_surface7_EnumAttachedSurfaces(&surface->IDirectDrawSurface7_iface, 2978 &info, EnumCallback); 2979 } 2980 2981 static HRESULT WINAPI ddraw_surface2_EnumAttachedSurfaces(IDirectDrawSurface2 *iface, 2982 void *context, LPDDENUMSURFACESCALLBACK callback) 2983 { 2984 struct ddraw_surface *surface = impl_from_IDirectDrawSurface2(iface); 2985 struct callback_info info; 2986 2987 TRACE("iface %p, context %p, callback %p.\n", iface, context, callback); 2988 2989 info.callback = callback; 2990 info.context = context; 2991 2992 return ddraw_surface7_EnumAttachedSurfaces(&surface->IDirectDrawSurface7_iface, 2993 &info, EnumCallback); 2994 } 2995 2996 static HRESULT WINAPI ddraw_surface1_EnumAttachedSurfaces(IDirectDrawSurface *iface, 2997 void *context, LPDDENUMSURFACESCALLBACK callback) 2998 { 2999 struct ddraw_surface *surface = impl_from_IDirectDrawSurface(iface); 3000 struct callback_info info; 3001 3002 TRACE("iface %p, context %p, callback %p.\n", iface, context, callback); 3003 3004 info.callback = callback; 3005 info.context = context; 3006 3007 return ddraw_surface7_EnumAttachedSurfaces(&surface->IDirectDrawSurface7_iface, 3008 &info, EnumCallback); 3009 } 3010 3011 /***************************************************************************** 3012 * IDirectDrawSurface7::EnumOverlayZOrders 3013 * 3014 * "Enumerates the overlay surfaces on the specified destination" 3015 * 3016 * Params: 3017 * Flags: DDENUMOVERLAYZ_BACKTOFRONT or DDENUMOVERLAYZ_FRONTTOBACK 3018 * context: context to pass back to the callback 3019 * cb: callback function to call for each enumerated surface 3020 * 3021 * Returns: 3022 * DD_OK, because it's a stub 3023 * 3024 *****************************************************************************/ 3025 static HRESULT WINAPI ddraw_surface7_EnumOverlayZOrders(IDirectDrawSurface7 *iface, 3026 DWORD Flags, void *context, LPDDENUMSURFACESCALLBACK7 cb) 3027 { 3028 FIXME("iface %p, flags %#x, context %p, callback %p stub!\n", iface, Flags, context, cb); 3029 3030 return DD_OK; 3031 } 3032 3033 static HRESULT WINAPI ddraw_surface4_EnumOverlayZOrders(IDirectDrawSurface4 *iface, 3034 DWORD flags, void *context, LPDDENUMSURFACESCALLBACK2 callback) 3035 { 3036 struct ddraw_surface *surface = impl_from_IDirectDrawSurface4(iface); 3037 struct callback_info2 info; 3038 3039 TRACE("iface %p, flags %#x, context %p, callback %p.\n", iface, flags, context, callback); 3040 3041 info.callback = callback; 3042 info.context = context; 3043 3044 return ddraw_surface7_EnumOverlayZOrders(&surface->IDirectDrawSurface7_iface, 3045 flags, &info, EnumCallback2); 3046 } 3047 3048 static HRESULT WINAPI ddraw_surface3_EnumOverlayZOrders(IDirectDrawSurface3 *iface, 3049 DWORD flags, void *context, LPDDENUMSURFACESCALLBACK callback) 3050 { 3051 struct ddraw_surface *surface = impl_from_IDirectDrawSurface3(iface); 3052 struct callback_info info; 3053 3054 TRACE("iface %p, flags %#x, context %p, callback %p.\n", iface, flags, context, callback); 3055 3056 info.callback = callback; 3057 info.context = context; 3058 3059 return ddraw_surface7_EnumOverlayZOrders(&surface->IDirectDrawSurface7_iface, 3060 flags, &info, EnumCallback); 3061 } 3062 3063 static HRESULT WINAPI ddraw_surface2_EnumOverlayZOrders(IDirectDrawSurface2 *iface, 3064 DWORD flags, void *context, LPDDENUMSURFACESCALLBACK callback) 3065 { 3066 struct ddraw_surface *surface = impl_from_IDirectDrawSurface2(iface); 3067 struct callback_info info; 3068 3069 TRACE("iface %p, flags %#x, context %p, callback %p.\n", iface, flags, context, callback); 3070 3071 info.callback = callback; 3072 info.context = context; 3073 3074 return ddraw_surface7_EnumOverlayZOrders(&surface->IDirectDrawSurface7_iface, 3075 flags, &info, EnumCallback); 3076 } 3077 3078 static HRESULT WINAPI ddraw_surface1_EnumOverlayZOrders(IDirectDrawSurface *iface, 3079 DWORD flags, void *context, LPDDENUMSURFACESCALLBACK callback) 3080 { 3081 struct ddraw_surface *surface = impl_from_IDirectDrawSurface(iface); 3082 struct callback_info info; 3083 3084 TRACE("iface %p, flags %#x, context %p, callback %p.\n", iface, flags, context, callback); 3085 3086 info.callback = callback; 3087 info.context = context; 3088 3089 return ddraw_surface7_EnumOverlayZOrders(&surface->IDirectDrawSurface7_iface, 3090 flags, &info, EnumCallback); 3091 } 3092 3093 /***************************************************************************** 3094 * IDirectDrawSurface7::GetBltStatus 3095 * 3096 * Returns the blitting status 3097 * 3098 * Params: 3099 * Flags: DDGBS_CANBLT or DDGBS_ISBLTDONE 3100 * 3101 *****************************************************************************/ 3102 static HRESULT WINAPI ddraw_surface7_GetBltStatus(IDirectDrawSurface7 *iface, DWORD Flags) 3103 { 3104 TRACE("iface %p, flags %#x.\n", iface, Flags); 3105 3106 switch (Flags) 3107 { 3108 case WINEDDGBS_CANBLT: 3109 case WINEDDGBS_ISBLTDONE: 3110 return DD_OK; 3111 3112 default: 3113 return DDERR_INVALIDPARAMS; 3114 } 3115 } 3116 3117 static HRESULT WINAPI ddraw_surface4_GetBltStatus(IDirectDrawSurface4 *iface, DWORD flags) 3118 { 3119 struct ddraw_surface *surface = impl_from_IDirectDrawSurface4(iface); 3120 3121 TRACE("iface %p, flags %#x.\n", iface, flags); 3122 3123 return ddraw_surface7_GetBltStatus(&surface->IDirectDrawSurface7_iface, flags); 3124 } 3125 3126 static HRESULT WINAPI ddraw_surface3_GetBltStatus(IDirectDrawSurface3 *iface, DWORD flags) 3127 { 3128 struct ddraw_surface *surface = impl_from_IDirectDrawSurface3(iface); 3129 3130 TRACE("iface %p, flags %#x.\n", iface, flags); 3131 3132 return ddraw_surface7_GetBltStatus(&surface->IDirectDrawSurface7_iface, flags); 3133 } 3134 3135 static HRESULT WINAPI ddraw_surface2_GetBltStatus(IDirectDrawSurface2 *iface, DWORD flags) 3136 { 3137 struct ddraw_surface *surface = impl_from_IDirectDrawSurface2(iface); 3138 3139 TRACE("iface %p, flags %#x.\n", iface, flags); 3140 3141 return ddraw_surface7_GetBltStatus(&surface->IDirectDrawSurface7_iface, flags); 3142 } 3143 3144 static HRESULT WINAPI ddraw_surface1_GetBltStatus(IDirectDrawSurface *iface, DWORD flags) 3145 { 3146 struct ddraw_surface *surface = impl_from_IDirectDrawSurface(iface); 3147 3148 TRACE("iface %p, flags %#x.\n", iface, flags); 3149 3150 return ddraw_surface7_GetBltStatus(&surface->IDirectDrawSurface7_iface, flags); 3151 } 3152 3153 /***************************************************************************** 3154 * IDirectDrawSurface7::GetColorKey 3155 * 3156 * Returns the color key assigned to the surface 3157 * 3158 * Params: 3159 * Flags: Some flags 3160 * CKey: Address to store the key to 3161 * 3162 * Returns: 3163 * DD_OK on success 3164 * DDERR_INVALIDPARAMS if CKey is NULL 3165 * 3166 *****************************************************************************/ 3167 static HRESULT WINAPI ddraw_surface7_GetColorKey(IDirectDrawSurface7 *iface, DWORD Flags, DDCOLORKEY *CKey) 3168 { 3169 struct ddraw_surface *This = impl_from_IDirectDrawSurface7(iface); 3170 3171 TRACE("iface %p, flags %#x, color_key %p.\n", iface, Flags, CKey); 3172 3173 if(!CKey) 3174 return DDERR_INVALIDPARAMS; 3175 3176 wined3d_mutex_lock(); 3177 3178 switch (Flags) 3179 { 3180 case DDCKEY_DESTBLT: 3181 if (!(This->surface_desc.dwFlags & DDSD_CKDESTBLT)) 3182 { 3183 wined3d_mutex_unlock(); 3184 return DDERR_NOCOLORKEY; 3185 } 3186 *CKey = This->surface_desc.ddckCKDestBlt; 3187 break; 3188 3189 case DDCKEY_DESTOVERLAY: 3190 if (!(This->surface_desc.dwFlags & DDSD_CKDESTOVERLAY)) 3191 { 3192 wined3d_mutex_unlock(); 3193 return DDERR_NOCOLORKEY; 3194 } 3195 *CKey = This->surface_desc.u3.ddckCKDestOverlay; 3196 break; 3197 3198 case DDCKEY_SRCBLT: 3199 if (!(This->surface_desc.dwFlags & DDSD_CKSRCBLT)) 3200 { 3201 wined3d_mutex_unlock(); 3202 return DDERR_NOCOLORKEY; 3203 } 3204 *CKey = This->surface_desc.ddckCKSrcBlt; 3205 break; 3206 3207 case DDCKEY_SRCOVERLAY: 3208 if (!(This->surface_desc.dwFlags & DDSD_CKSRCOVERLAY)) 3209 { 3210 wined3d_mutex_unlock(); 3211 return DDERR_NOCOLORKEY; 3212 } 3213 *CKey = This->surface_desc.ddckCKSrcOverlay; 3214 break; 3215 3216 default: 3217 wined3d_mutex_unlock(); 3218 return DDERR_INVALIDPARAMS; 3219 } 3220 3221 wined3d_mutex_unlock(); 3222 3223 return DD_OK; 3224 } 3225 3226 static HRESULT WINAPI ddraw_surface4_GetColorKey(IDirectDrawSurface4 *iface, DWORD flags, DDCOLORKEY *color_key) 3227 { 3228 struct ddraw_surface *surface = impl_from_IDirectDrawSurface4(iface); 3229 3230 TRACE("iface %p, flags %#x, color_key %p.\n", iface, flags, color_key); 3231 3232 return ddraw_surface7_GetColorKey(&surface->IDirectDrawSurface7_iface, flags, color_key); 3233 } 3234 3235 static HRESULT WINAPI ddraw_surface3_GetColorKey(IDirectDrawSurface3 *iface, DWORD flags, DDCOLORKEY *color_key) 3236 { 3237 struct ddraw_surface *surface = impl_from_IDirectDrawSurface3(iface); 3238 3239 TRACE("iface %p, flags %#x, color_key %p.\n", iface, flags, color_key); 3240 3241 return ddraw_surface7_GetColorKey(&surface->IDirectDrawSurface7_iface, flags, color_key); 3242 } 3243 3244 static HRESULT WINAPI ddraw_surface2_GetColorKey(IDirectDrawSurface2 *iface, DWORD flags, DDCOLORKEY *color_key) 3245 { 3246 struct ddraw_surface *surface = impl_from_IDirectDrawSurface2(iface); 3247 3248 TRACE("iface %p, flags %#x, color_key %p.\n", iface, flags, color_key); 3249 3250 return ddraw_surface7_GetColorKey(&surface->IDirectDrawSurface7_iface, flags, color_key); 3251 } 3252 3253 static HRESULT WINAPI ddraw_surface1_GetColorKey(IDirectDrawSurface *iface, DWORD flags, DDCOLORKEY *color_key) 3254 { 3255 struct ddraw_surface *surface = impl_from_IDirectDrawSurface(iface); 3256 3257 TRACE("iface %p, flags %#x, color_key %p.\n", iface, flags, color_key); 3258 3259 return ddraw_surface7_GetColorKey(&surface->IDirectDrawSurface7_iface, flags, color_key); 3260 } 3261 3262 /***************************************************************************** 3263 * IDirectDrawSurface7::GetFlipStatus 3264 * 3265 * Returns the flipping status of the surface 3266 * 3267 * Params: 3268 * Flags: DDGFS_CANFLIP of DDGFS_ISFLIPDONE 3269 * 3270 *****************************************************************************/ 3271 static HRESULT WINAPI ddraw_surface7_GetFlipStatus(IDirectDrawSurface7 *iface, DWORD Flags) 3272 { 3273 TRACE("iface %p, flags %#x.\n", iface, Flags); 3274 3275 /* XXX: DDERR_INVALIDSURFACETYPE */ 3276 3277 switch (Flags) 3278 { 3279 case WINEDDGFS_CANFLIP: 3280 case WINEDDGFS_ISFLIPDONE: 3281 return DD_OK; 3282 3283 default: 3284 return DDERR_INVALIDPARAMS; 3285 } 3286 } 3287 3288 static HRESULT WINAPI ddraw_surface4_GetFlipStatus(IDirectDrawSurface4 *iface, DWORD flags) 3289 { 3290 struct ddraw_surface *surface = impl_from_IDirectDrawSurface4(iface); 3291 3292 TRACE("iface %p, flags %#x.\n", iface, flags); 3293 3294 return ddraw_surface7_GetFlipStatus(&surface->IDirectDrawSurface7_iface, flags); 3295 } 3296 3297 static HRESULT WINAPI ddraw_surface3_GetFlipStatus(IDirectDrawSurface3 *iface, DWORD flags) 3298 { 3299 struct ddraw_surface *surface = impl_from_IDirectDrawSurface3(iface); 3300 3301 TRACE("iface %p, flags %#x.\n", iface, flags); 3302 3303 return ddraw_surface7_GetFlipStatus(&surface->IDirectDrawSurface7_iface, flags); 3304 } 3305 3306 static HRESULT WINAPI ddraw_surface2_GetFlipStatus(IDirectDrawSurface2 *iface, DWORD flags) 3307 { 3308 struct ddraw_surface *surface = impl_from_IDirectDrawSurface2(iface); 3309 3310 TRACE("iface %p, flags %#x.\n", iface, flags); 3311 3312 return ddraw_surface7_GetFlipStatus(&surface->IDirectDrawSurface7_iface, flags); 3313 } 3314 3315 static HRESULT WINAPI ddraw_surface1_GetFlipStatus(IDirectDrawSurface *iface, DWORD flags) 3316 { 3317 struct ddraw_surface *surface = impl_from_IDirectDrawSurface(iface); 3318 3319 TRACE("iface %p, flags %#x.\n", iface, flags); 3320 3321 return ddraw_surface7_GetFlipStatus(&surface->IDirectDrawSurface7_iface, flags); 3322 } 3323 3324 /***************************************************************************** 3325 * IDirectDrawSurface7::GetOverlayPosition 3326 * 3327 * Returns the display coordinates of a visible and active overlay surface 3328 * 3329 * Params: 3330 * X 3331 * Y 3332 * 3333 * Returns: 3334 * DDERR_NOTAOVERLAYSURFACE, because it's a stub 3335 *****************************************************************************/ 3336 static HRESULT WINAPI ddraw_surface7_GetOverlayPosition(IDirectDrawSurface7 *iface, LONG *x, LONG *y) 3337 { 3338 struct ddraw_surface *surface = impl_from_IDirectDrawSurface7(iface); 3339 HRESULT hr; 3340 3341 TRACE("iface %p, x %p, y %p.\n", iface, x, y); 3342 3343 wined3d_mutex_lock(); 3344 hr = wined3d_texture_get_overlay_position(surface->wined3d_texture, 3345 surface->sub_resource_idx, x, y); 3346 wined3d_mutex_unlock(); 3347 3348 return hr; 3349 } 3350 3351 static HRESULT WINAPI ddraw_surface4_GetOverlayPosition(IDirectDrawSurface4 *iface, LONG *x, LONG *y) 3352 { 3353 struct ddraw_surface *surface = impl_from_IDirectDrawSurface4(iface); 3354 3355 TRACE("iface %p, x %p, y %p.\n", iface, x, y); 3356 3357 return ddraw_surface7_GetOverlayPosition(&surface->IDirectDrawSurface7_iface, x, y); 3358 } 3359 3360 static HRESULT WINAPI ddraw_surface3_GetOverlayPosition(IDirectDrawSurface3 *iface, LONG *x, LONG *y) 3361 { 3362 struct ddraw_surface *surface = impl_from_IDirectDrawSurface3(iface); 3363 3364 TRACE("iface %p, x %p, y %p.\n", iface, x, y); 3365 3366 return ddraw_surface7_GetOverlayPosition(&surface->IDirectDrawSurface7_iface, x, y); 3367 } 3368 3369 static HRESULT WINAPI ddraw_surface2_GetOverlayPosition(IDirectDrawSurface2 *iface, LONG *x, LONG *y) 3370 { 3371 struct ddraw_surface *surface = impl_from_IDirectDrawSurface2(iface); 3372 3373 TRACE("iface %p, x %p, y %p.\n", iface, x, y); 3374 3375 return ddraw_surface7_GetOverlayPosition(&surface->IDirectDrawSurface7_iface, x, y); 3376 } 3377 3378 static HRESULT WINAPI ddraw_surface1_GetOverlayPosition(IDirectDrawSurface *iface, LONG *x, LONG *y) 3379 { 3380 struct ddraw_surface *surface = impl_from_IDirectDrawSurface(iface); 3381 3382 TRACE("iface %p, x %p, y %p.\n", iface, x, y); 3383 3384 return ddraw_surface7_GetOverlayPosition(&surface->IDirectDrawSurface7_iface, x, y); 3385 } 3386 3387 /***************************************************************************** 3388 * IDirectDrawSurface7::GetPixelFormat 3389 * 3390 * Returns the pixel format of the Surface 3391 * 3392 * Params: 3393 * PixelFormat: Pointer to a DDPIXELFORMAT structure to which the pixel 3394 * format should be written 3395 * 3396 * Returns: 3397 * DD_OK on success 3398 * DDERR_INVALIDPARAMS if PixelFormat is NULL 3399 * 3400 *****************************************************************************/ 3401 static HRESULT WINAPI ddraw_surface7_GetPixelFormat(IDirectDrawSurface7 *iface, DDPIXELFORMAT *PixelFormat) 3402 { 3403 /* What is DDERR_INVALIDSURFACETYPE for here? */ 3404 struct ddraw_surface *surface = impl_from_IDirectDrawSurface7(iface); 3405 3406 TRACE("iface %p, pixel_format %p.\n", iface, PixelFormat); 3407 3408 if(!PixelFormat) 3409 return DDERR_INVALIDPARAMS; 3410 3411 wined3d_mutex_lock(); 3412 DD_STRUCT_COPY_BYSIZE(PixelFormat, &surface->surface_desc.u4.ddpfPixelFormat); 3413 wined3d_mutex_unlock(); 3414 3415 return DD_OK; 3416 } 3417 3418 static HRESULT WINAPI ddraw_surface4_GetPixelFormat(IDirectDrawSurface4 *iface, DDPIXELFORMAT *pixel_format) 3419 { 3420 struct ddraw_surface *surface = impl_from_IDirectDrawSurface4(iface); 3421 3422 TRACE("iface %p, pixel_format %p.\n", iface, pixel_format); 3423 3424 return ddraw_surface7_GetPixelFormat(&surface->IDirectDrawSurface7_iface, pixel_format); 3425 } 3426 3427 static HRESULT WINAPI ddraw_surface3_GetPixelFormat(IDirectDrawSurface3 *iface, DDPIXELFORMAT *pixel_format) 3428 { 3429 struct ddraw_surface *surface = impl_from_IDirectDrawSurface3(iface); 3430 3431 TRACE("iface %p, pixel_format %p.\n", iface, pixel_format); 3432 3433 return ddraw_surface7_GetPixelFormat(&surface->IDirectDrawSurface7_iface, pixel_format); 3434 } 3435 3436 static HRESULT WINAPI ddraw_surface2_GetPixelFormat(IDirectDrawSurface2 *iface, DDPIXELFORMAT *pixel_format) 3437 { 3438 struct ddraw_surface *surface = impl_from_IDirectDrawSurface2(iface); 3439 3440 TRACE("iface %p, pixel_format %p.\n", iface, pixel_format); 3441 3442 return ddraw_surface7_GetPixelFormat(&surface->IDirectDrawSurface7_iface, pixel_format); 3443 } 3444 3445 static HRESULT WINAPI ddraw_surface1_GetPixelFormat(IDirectDrawSurface *iface, DDPIXELFORMAT *pixel_format) 3446 { 3447 struct ddraw_surface *surface = impl_from_IDirectDrawSurface(iface); 3448 3449 TRACE("iface %p, pixel_format %p.\n", iface, pixel_format); 3450 3451 return ddraw_surface7_GetPixelFormat(&surface->IDirectDrawSurface7_iface, pixel_format); 3452 } 3453 3454 /***************************************************************************** 3455 * IDirectDrawSurface7::GetSurfaceDesc 3456 * 3457 * Returns the description of this surface 3458 * 3459 * Params: 3460 * DDSD: Address of a DDSURFACEDESC2 structure that is to be filled with the 3461 * surface desc 3462 * 3463 * Returns: 3464 * DD_OK on success 3465 * DDERR_INVALIDPARAMS if DDSD is NULL 3466 * 3467 *****************************************************************************/ 3468 static HRESULT WINAPI ddraw_surface7_GetSurfaceDesc(IDirectDrawSurface7 *iface, DDSURFACEDESC2 *DDSD) 3469 { 3470 struct ddraw_surface *surface = impl_from_IDirectDrawSurface7(iface); 3471 3472 TRACE("iface %p, surface_desc %p.\n", iface, DDSD); 3473 3474 if(!DDSD) 3475 return DDERR_INVALIDPARAMS; 3476 3477 if (DDSD->dwSize != sizeof(DDSURFACEDESC2)) 3478 { 3479 WARN("Incorrect struct size %d, returning DDERR_INVALIDPARAMS\n",DDSD->dwSize); 3480 return DDERR_INVALIDPARAMS; 3481 } 3482 3483 wined3d_mutex_lock(); 3484 DD_STRUCT_COPY_BYSIZE(DDSD, &surface->surface_desc); 3485 TRACE("Returning surface desc:\n"); 3486 if (TRACE_ON(ddraw)) DDRAW_dump_surface_desc(DDSD); 3487 wined3d_mutex_unlock(); 3488 3489 return DD_OK; 3490 } 3491 3492 static HRESULT WINAPI ddraw_surface4_GetSurfaceDesc(IDirectDrawSurface4 *iface, DDSURFACEDESC2 *DDSD) 3493 { 3494 struct ddraw_surface *surface = impl_from_IDirectDrawSurface4(iface); 3495 3496 TRACE("iface %p, surface_desc %p.\n", iface, DDSD); 3497 3498 return ddraw_surface7_GetSurfaceDesc(&surface->IDirectDrawSurface7_iface, DDSD); 3499 } 3500 3501 static HRESULT WINAPI ddraw_surface3_GetSurfaceDesc(IDirectDrawSurface3 *iface, DDSURFACEDESC *surface_desc) 3502 { 3503 struct ddraw_surface *surface = impl_from_IDirectDrawSurface3(iface); 3504 3505 TRACE("iface %p, surface_desc %p.\n", iface, surface_desc); 3506 3507 if (!surface_desc) return DDERR_INVALIDPARAMS; 3508 3509 if (surface_desc->dwSize != sizeof(DDSURFACEDESC)) 3510 { 3511 WARN("Incorrect structure size %u, returning DDERR_INVALIDPARAMS.\n", surface_desc->dwSize); 3512 return DDERR_INVALIDPARAMS; 3513 } 3514 3515 wined3d_mutex_lock(); 3516 DDSD2_to_DDSD(&surface->surface_desc, surface_desc); 3517 TRACE("Returning surface desc:\n"); 3518 if (TRACE_ON(ddraw)) 3519 { 3520 /* DDRAW_dump_surface_desc handles the smaller size */ 3521 DDRAW_dump_surface_desc((DDSURFACEDESC2 *)surface_desc); 3522 } 3523 wined3d_mutex_unlock(); 3524 3525 return DD_OK; 3526 } 3527 3528 static HRESULT WINAPI ddraw_surface2_GetSurfaceDesc(IDirectDrawSurface2 *iface, DDSURFACEDESC *DDSD) 3529 { 3530 struct ddraw_surface *surface = impl_from_IDirectDrawSurface2(iface); 3531 3532 TRACE("iface %p, surface_desc %p.\n", iface, DDSD); 3533 3534 return ddraw_surface3_GetSurfaceDesc(&surface->IDirectDrawSurface3_iface, DDSD); 3535 } 3536 3537 static HRESULT WINAPI ddraw_surface1_GetSurfaceDesc(IDirectDrawSurface *iface, DDSURFACEDESC *DDSD) 3538 { 3539 struct ddraw_surface *surface = impl_from_IDirectDrawSurface(iface); 3540 3541 TRACE("iface %p, surface_desc %p.\n", iface, DDSD); 3542 3543 return ddraw_surface3_GetSurfaceDesc(&surface->IDirectDrawSurface3_iface, DDSD); 3544 } 3545 3546 /***************************************************************************** 3547 * IDirectDrawSurface7::Initialize 3548 * 3549 * Initializes the surface. This is a no-op in Wine 3550 * 3551 * Params: 3552 * DD: Pointer to an DirectDraw interface 3553 * DDSD: Surface description for initialization 3554 * 3555 * Returns: 3556 * DDERR_ALREADYINITIALIZED 3557 * 3558 *****************************************************************************/ 3559 static HRESULT WINAPI ddraw_surface7_Initialize(IDirectDrawSurface7 *iface, 3560 IDirectDraw *ddraw, DDSURFACEDESC2 *surface_desc) 3561 { 3562 TRACE("iface %p, ddraw %p, surface_desc %p.\n", iface, ddraw, surface_desc); 3563 3564 return DDERR_ALREADYINITIALIZED; 3565 } 3566 3567 static HRESULT WINAPI ddraw_surface4_Initialize(IDirectDrawSurface4 *iface, 3568 IDirectDraw *ddraw, DDSURFACEDESC2 *surface_desc) 3569 { 3570 struct ddraw_surface *surface = impl_from_IDirectDrawSurface4(iface); 3571 3572 TRACE("iface %p, ddraw %p, surface_desc %p.\n", iface, ddraw, surface_desc); 3573 3574 return ddraw_surface7_Initialize(&surface->IDirectDrawSurface7_iface, 3575 ddraw, surface_desc); 3576 } 3577 3578 static HRESULT WINAPI ddraw_surface3_Initialize(IDirectDrawSurface3 *iface, 3579 IDirectDraw *ddraw, DDSURFACEDESC *surface_desc) 3580 { 3581 struct ddraw_surface *surface = impl_from_IDirectDrawSurface3(iface); 3582 DDSURFACEDESC2 surface_desc2; 3583 3584 TRACE("iface %p, ddraw %p, surface_desc %p.\n", iface, ddraw, surface_desc); 3585 3586 if (surface_desc) DDSD_to_DDSD2(surface_desc, &surface_desc2); 3587 return ddraw_surface7_Initialize(&surface->IDirectDrawSurface7_iface, 3588 ddraw, surface_desc ? &surface_desc2 : NULL); 3589 } 3590 3591 static HRESULT WINAPI ddraw_surface2_Initialize(IDirectDrawSurface2 *iface, 3592 IDirectDraw *ddraw, DDSURFACEDESC *surface_desc) 3593 { 3594 struct ddraw_surface *surface = impl_from_IDirectDrawSurface2(iface); 3595 DDSURFACEDESC2 surface_desc2; 3596 3597 TRACE("iface %p, ddraw %p, surface_desc %p.\n", iface, ddraw, surface_desc); 3598 3599 if (surface_desc) DDSD_to_DDSD2(surface_desc, &surface_desc2); 3600 return ddraw_surface7_Initialize(&surface->IDirectDrawSurface7_iface, 3601 ddraw, surface_desc ? &surface_desc2 : NULL); 3602 } 3603 3604 static HRESULT WINAPI ddraw_surface1_Initialize(IDirectDrawSurface *iface, 3605 IDirectDraw *ddraw, DDSURFACEDESC *surface_desc) 3606 { 3607 struct ddraw_surface *surface = impl_from_IDirectDrawSurface(iface); 3608 DDSURFACEDESC2 surface_desc2; 3609 3610 TRACE("iface %p, ddraw %p, surface_desc %p.\n", iface, ddraw, surface_desc); 3611 3612 if (surface_desc) DDSD_to_DDSD2(surface_desc, &surface_desc2); 3613 return ddraw_surface7_Initialize(&surface->IDirectDrawSurface7_iface, 3614 ddraw, surface_desc ? &surface_desc2 : NULL); 3615 } 3616 3617 /***************************************************************************** 3618 * IDirect3DTexture1::Initialize 3619 * 3620 * The sdk says it's not implemented 3621 * 3622 * Params: 3623 * ? 3624 * 3625 * Returns 3626 * DDERR_UNSUPPORTED 3627 * 3628 *****************************************************************************/ 3629 static HRESULT WINAPI d3d_texture1_Initialize(IDirect3DTexture *iface, 3630 IDirect3DDevice *device, IDirectDrawSurface *surface) 3631 { 3632 TRACE("iface %p, device %p, surface %p.\n", iface, device, surface); 3633 3634 return DDERR_UNSUPPORTED; /* Unchecked */ 3635 } 3636 3637 /***************************************************************************** 3638 * IDirectDrawSurface7::IsLost 3639 * 3640 * Checks if the surface is lost 3641 * 3642 * Returns: 3643 * DD_OK, if the surface is usable 3644 * DDERR_ISLOST if the surface is lost 3645 * 3646 *****************************************************************************/ 3647 static HRESULT WINAPI ddraw_surface7_IsLost(IDirectDrawSurface7 *iface) 3648 { 3649 struct ddraw_surface *surface = impl_from_IDirectDrawSurface7(iface); 3650 3651 TRACE("iface %p.\n", iface); 3652 3653 if (surface->ddraw->device_state != DDRAW_DEVICE_STATE_OK || surface->is_lost) 3654 return DDERR_SURFACELOST; 3655 3656 return DD_OK; 3657 } 3658 3659 static HRESULT WINAPI ddraw_surface4_IsLost(IDirectDrawSurface4 *iface) 3660 { 3661 struct ddraw_surface *surface = impl_from_IDirectDrawSurface4(iface); 3662 3663 TRACE("iface %p.\n", iface); 3664 3665 return ddraw_surface7_IsLost(&surface->IDirectDrawSurface7_iface); 3666 } 3667 3668 static HRESULT WINAPI ddraw_surface3_IsLost(IDirectDrawSurface3 *iface) 3669 { 3670 struct ddraw_surface *surface = impl_from_IDirectDrawSurface3(iface); 3671 3672 TRACE("iface %p.\n", iface); 3673 3674 return ddraw_surface7_IsLost(&surface->IDirectDrawSurface7_iface); 3675 } 3676 3677 static HRESULT WINAPI ddraw_surface2_IsLost(IDirectDrawSurface2 *iface) 3678 { 3679 struct ddraw_surface *surface = impl_from_IDirectDrawSurface2(iface); 3680 3681 TRACE("iface %p.\n", iface); 3682 3683 return ddraw_surface7_IsLost(&surface->IDirectDrawSurface7_iface); 3684 } 3685 3686 static HRESULT WINAPI ddraw_surface1_IsLost(IDirectDrawSurface *iface) 3687 { 3688 struct ddraw_surface *surface = impl_from_IDirectDrawSurface(iface); 3689 3690 TRACE("iface %p.\n", iface); 3691 3692 return ddraw_surface7_IsLost(&surface->IDirectDrawSurface7_iface); 3693 } 3694 3695 /***************************************************************************** 3696 * IDirectDrawSurface7::Restore 3697 * 3698 * Restores a lost surface. This makes the surface usable again, but 3699 * doesn't reload its old contents 3700 * 3701 * Returns: 3702 * DD_OK on success, error code otherwise. 3703 * 3704 *****************************************************************************/ 3705 static HRESULT WINAPI ddraw_surface7_Restore(IDirectDrawSurface7 *iface) 3706 { 3707 struct ddraw_surface *surface = impl_from_IDirectDrawSurface7(iface); 3708 3709 TRACE("iface %p.\n", iface); 3710 3711 if (surface->surface_desc.ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE) 3712 { 3713 struct wined3d_swapchain *swapchain = surface->ddraw->wined3d_swapchain; 3714 struct wined3d_sub_resource_desc wined3d_desc; 3715 struct wined3d_display_mode mode; 3716 HRESULT hr; 3717 3718 if (FAILED(hr = wined3d_swapchain_get_display_mode(swapchain, &mode, NULL))) 3719 { 3720 WARN("Failed to get display mode, hr %#x.\n", hr); 3721 return hr; 3722 } 3723 3724 if (FAILED(hr = wined3d_texture_get_sub_resource_desc(surface->wined3d_texture, 0, &wined3d_desc))) 3725 { 3726 WARN("Failed to get resource desc, hr %#x.\n", hr); 3727 return hr; 3728 } 3729 3730 if (mode.width != wined3d_desc.width || mode.height != wined3d_desc.height) 3731 { 3732 WARN("Display mode dimensions %ux%u don't match surface dimensions %ux%u.\n", 3733 mode.width, mode.height, wined3d_desc.width, wined3d_desc.height); 3734 return DDERR_WRONGMODE; 3735 } 3736 3737 if (mode.format_id != wined3d_desc.format) 3738 { 3739 WARN("Display mode format %#x doesn't match surface format %#x.\n", 3740 mode.format_id, wined3d_desc.format); 3741 return DDERR_WRONGMODE; 3742 } 3743 } 3744 3745 ddraw_update_lost_surfaces(surface->ddraw); 3746 surface->is_lost = FALSE; 3747 3748 return DD_OK; 3749 } 3750 3751 static HRESULT WINAPI ddraw_surface4_Restore(IDirectDrawSurface4 *iface) 3752 { 3753 struct ddraw_surface *surface = impl_from_IDirectDrawSurface4(iface); 3754 3755 TRACE("iface %p.\n", iface); 3756 3757 return ddraw_surface7_Restore(&surface->IDirectDrawSurface7_iface); 3758 } 3759 3760 static HRESULT WINAPI ddraw_surface3_Restore(IDirectDrawSurface3 *iface) 3761 { 3762 struct ddraw_surface *surface = impl_from_IDirectDrawSurface3(iface); 3763 3764 TRACE("iface %p.\n", iface); 3765 3766 return ddraw_surface7_Restore(&surface->IDirectDrawSurface7_iface); 3767 } 3768 3769 static HRESULT WINAPI ddraw_surface2_Restore(IDirectDrawSurface2 *iface) 3770 { 3771 struct ddraw_surface *surface = impl_from_IDirectDrawSurface2(iface); 3772 3773 TRACE("iface %p.\n", iface); 3774 3775 return ddraw_surface7_Restore(&surface->IDirectDrawSurface7_iface); 3776 } 3777 3778 static HRESULT WINAPI ddraw_surface1_Restore(IDirectDrawSurface *iface) 3779 { 3780 struct ddraw_surface *surface = impl_from_IDirectDrawSurface(iface); 3781 3782 TRACE("iface %p.\n", iface); 3783 3784 return ddraw_surface7_Restore(&surface->IDirectDrawSurface7_iface); 3785 } 3786 3787 /***************************************************************************** 3788 * IDirectDrawSurface7::SetOverlayPosition 3789 * 3790 * Changes the display coordinates of an overlay surface 3791 * 3792 * Params: 3793 * X: 3794 * Y: 3795 * 3796 * Returns: 3797 * DDERR_NOTAOVERLAYSURFACE, because we don't support overlays right now 3798 *****************************************************************************/ 3799 static HRESULT WINAPI ddraw_surface7_SetOverlayPosition(IDirectDrawSurface7 *iface, LONG x, LONG y) 3800 { 3801 struct ddraw_surface *surface = impl_from_IDirectDrawSurface7(iface); 3802 HRESULT hr; 3803 3804 TRACE("iface %p, x %d, y %d.\n", iface, x, y); 3805 3806 wined3d_mutex_lock(); 3807 hr = wined3d_texture_set_overlay_position(surface->wined3d_texture, 3808 surface->sub_resource_idx, x, y); 3809 wined3d_mutex_unlock(); 3810 3811 return hr; 3812 } 3813 3814 static HRESULT WINAPI ddraw_surface4_SetOverlayPosition(IDirectDrawSurface4 *iface, LONG x, LONG y) 3815 { 3816 struct ddraw_surface *surface = impl_from_IDirectDrawSurface4(iface); 3817 3818 TRACE("iface %p, x %d, y %d.\n", iface, x, y); 3819 3820 return ddraw_surface7_SetOverlayPosition(&surface->IDirectDrawSurface7_iface, x, y); 3821 } 3822 3823 static HRESULT WINAPI ddraw_surface3_SetOverlayPosition(IDirectDrawSurface3 *iface, LONG x, LONG y) 3824 { 3825 struct ddraw_surface *surface = impl_from_IDirectDrawSurface3(iface); 3826 3827 TRACE("iface %p, x %d, y %d.\n", iface, x, y); 3828 3829 return ddraw_surface7_SetOverlayPosition(&surface->IDirectDrawSurface7_iface, x, y); 3830 } 3831 3832 static HRESULT WINAPI ddraw_surface2_SetOverlayPosition(IDirectDrawSurface2 *iface, LONG x, LONG y) 3833 { 3834 struct ddraw_surface *surface = impl_from_IDirectDrawSurface2(iface); 3835 3836 TRACE("iface %p, x %d, y %d.\n", iface, x, y); 3837 3838 return ddraw_surface7_SetOverlayPosition(&surface->IDirectDrawSurface7_iface, x, y); 3839 } 3840 3841 static HRESULT WINAPI ddraw_surface1_SetOverlayPosition(IDirectDrawSurface *iface, LONG x, LONG y) 3842 { 3843 struct ddraw_surface *surface = impl_from_IDirectDrawSurface(iface); 3844 3845 TRACE("iface %p, x %d, y %d.\n", iface, x, y); 3846 3847 return ddraw_surface7_SetOverlayPosition(&surface->IDirectDrawSurface7_iface, x, y); 3848 } 3849 3850 /***************************************************************************** 3851 * IDirectDrawSurface7::UpdateOverlay 3852 * 3853 * Modifies the attributes of an overlay surface. 3854 * 3855 * Params: 3856 * SrcRect: The section of the source being used for the overlay 3857 * DstSurface: Address of the surface that is overlaid 3858 * DstRect: Place of the overlay 3859 * Flags: some DDOVER_* flags 3860 * 3861 * Returns: 3862 * DDERR_UNSUPPORTED, because we don't support overlays 3863 * 3864 *****************************************************************************/ 3865 static HRESULT WINAPI ddraw_surface7_UpdateOverlay(IDirectDrawSurface7 *iface, RECT *src_rect, 3866 IDirectDrawSurface7 *dst_surface, RECT *dst_rect, DWORD flags, DDOVERLAYFX *fx) 3867 { 3868 struct ddraw_surface *src_impl = impl_from_IDirectDrawSurface7(iface); 3869 struct ddraw_surface *dst_impl = unsafe_impl_from_IDirectDrawSurface7(dst_surface); 3870 struct wined3d_texture *dst_wined3d_texture = NULL; 3871 unsigned int dst_sub_resource_idx = 0; 3872 HRESULT hr; 3873 3874 TRACE("iface %p, src_rect %s, dst_surface %p, dst_rect %s, flags %#x, fx %p.\n", 3875 iface, wine_dbgstr_rect(src_rect), dst_surface, wine_dbgstr_rect(dst_rect), flags, fx); 3876 3877 if (fx) 3878 FIXME("Ignoring fx %p.\n", fx); 3879 3880 wined3d_mutex_lock(); 3881 if (dst_impl) 3882 { 3883 dst_wined3d_texture = dst_impl->wined3d_texture; 3884 dst_sub_resource_idx = dst_impl->sub_resource_idx; 3885 } 3886 hr = wined3d_texture_update_overlay(src_impl->wined3d_texture, src_impl->sub_resource_idx, 3887 src_rect, dst_wined3d_texture, dst_sub_resource_idx, dst_rect, flags); 3888 wined3d_mutex_unlock(); 3889 3890 switch (hr) 3891 { 3892 case WINED3DERR_INVALIDCALL: return DDERR_INVALIDPARAMS; 3893 case WINEDDERR_NOTAOVERLAYSURFACE: return DDERR_NOTAOVERLAYSURFACE; 3894 case WINEDDERR_OVERLAYNOTVISIBLE: return DDERR_OVERLAYNOTVISIBLE; 3895 default: 3896 return hr; 3897 } 3898 } 3899 3900 static HRESULT WINAPI ddraw_surface4_UpdateOverlay(IDirectDrawSurface4 *iface, RECT *src_rect, 3901 IDirectDrawSurface4 *dst_surface, RECT *dst_rect, DWORD flags, DDOVERLAYFX *fx) 3902 { 3903 struct ddraw_surface *src_impl = impl_from_IDirectDrawSurface4(iface); 3904 struct ddraw_surface *dst_impl = unsafe_impl_from_IDirectDrawSurface4(dst_surface); 3905 3906 TRACE("iface %p, src_rect %s, dst_surface %p, dst_rect %s, flags %#x, fx %p.\n", 3907 iface, wine_dbgstr_rect(src_rect), dst_surface, wine_dbgstr_rect(dst_rect), flags, fx); 3908 3909 return ddraw_surface7_UpdateOverlay(&src_impl->IDirectDrawSurface7_iface, src_rect, 3910 dst_impl ? &dst_impl->IDirectDrawSurface7_iface : NULL, dst_rect, flags, fx); 3911 } 3912 3913 static HRESULT WINAPI ddraw_surface3_UpdateOverlay(IDirectDrawSurface3 *iface, RECT *src_rect, 3914 IDirectDrawSurface3 *dst_surface, RECT *dst_rect, DWORD flags, DDOVERLAYFX *fx) 3915 { 3916 struct ddraw_surface *src_impl = impl_from_IDirectDrawSurface3(iface); 3917 struct ddraw_surface *dst_impl = unsafe_impl_from_IDirectDrawSurface3(dst_surface); 3918 3919 TRACE("iface %p, src_rect %s, dst_surface %p, dst_rect %s, flags %#x, fx %p.\n", 3920 iface, wine_dbgstr_rect(src_rect), dst_surface, wine_dbgstr_rect(dst_rect), flags, fx); 3921 3922 return ddraw_surface7_UpdateOverlay(&src_impl->IDirectDrawSurface7_iface, src_rect, 3923 dst_impl ? &dst_impl->IDirectDrawSurface7_iface : NULL, dst_rect, flags, fx); 3924 } 3925 3926 static HRESULT WINAPI ddraw_surface2_UpdateOverlay(IDirectDrawSurface2 *iface, RECT *src_rect, 3927 IDirectDrawSurface2 *dst_surface, RECT *dst_rect, DWORD flags, DDOVERLAYFX *fx) 3928 { 3929 struct ddraw_surface *src_impl = impl_from_IDirectDrawSurface2(iface); 3930 struct ddraw_surface *dst_impl = unsafe_impl_from_IDirectDrawSurface2(dst_surface); 3931 3932 TRACE("iface %p, src_rect %s, dst_surface %p, dst_rect %s, flags %#x, fx %p.\n", 3933 iface, wine_dbgstr_rect(src_rect), dst_surface, wine_dbgstr_rect(dst_rect), flags, fx); 3934 3935 return ddraw_surface7_UpdateOverlay(&src_impl->IDirectDrawSurface7_iface, src_rect, 3936 dst_impl ? &dst_impl->IDirectDrawSurface7_iface : NULL, dst_rect, flags, fx); 3937 } 3938 3939 static HRESULT WINAPI ddraw_surface1_UpdateOverlay(IDirectDrawSurface *iface, RECT *src_rect, 3940 IDirectDrawSurface *dst_surface, RECT *dst_rect, DWORD flags, DDOVERLAYFX *fx) 3941 { 3942 struct ddraw_surface *src_impl = impl_from_IDirectDrawSurface(iface); 3943 struct ddraw_surface *dst_impl = unsafe_impl_from_IDirectDrawSurface(dst_surface); 3944 3945 TRACE("iface %p, src_rect %s, dst_surface %p, dst_rect %s, flags %#x, fx %p.\n", 3946 iface, wine_dbgstr_rect(src_rect), dst_surface, wine_dbgstr_rect(dst_rect), flags, fx); 3947 3948 return ddraw_surface7_UpdateOverlay(&src_impl->IDirectDrawSurface7_iface, src_rect, 3949 dst_impl ? &dst_impl->IDirectDrawSurface7_iface : NULL, dst_rect, flags, fx); 3950 } 3951 3952 /***************************************************************************** 3953 * IDirectDrawSurface7::UpdateOverlayDisplay 3954 * 3955 * The DX7 sdk says that it's not implemented 3956 * 3957 * Params: 3958 * Flags: ? 3959 * 3960 * Returns: DDERR_UNSUPPORTED, because we don't support overlays 3961 * 3962 *****************************************************************************/ 3963 static HRESULT WINAPI ddraw_surface7_UpdateOverlayDisplay(IDirectDrawSurface7 *iface, DWORD Flags) 3964 { 3965 TRACE("iface %p, flags %#x.\n", iface, Flags); 3966 3967 return DDERR_UNSUPPORTED; 3968 } 3969 3970 static HRESULT WINAPI ddraw_surface4_UpdateOverlayDisplay(IDirectDrawSurface4 *iface, DWORD flags) 3971 { 3972 struct ddraw_surface *surface = impl_from_IDirectDrawSurface4(iface); 3973 3974 TRACE("iface %p, flags %#x.\n", iface, flags); 3975 3976 return ddraw_surface7_UpdateOverlayDisplay(&surface->IDirectDrawSurface7_iface, flags); 3977 } 3978 3979 static HRESULT WINAPI ddraw_surface3_UpdateOverlayDisplay(IDirectDrawSurface3 *iface, DWORD flags) 3980 { 3981 struct ddraw_surface *surface = impl_from_IDirectDrawSurface3(iface); 3982 3983 TRACE("iface %p, flags %#x.\n", iface, flags); 3984 3985 return ddraw_surface7_UpdateOverlayDisplay(&surface->IDirectDrawSurface7_iface, flags); 3986 } 3987 3988 static HRESULT WINAPI ddraw_surface2_UpdateOverlayDisplay(IDirectDrawSurface2 *iface, DWORD flags) 3989 { 3990 struct ddraw_surface *surface = impl_from_IDirectDrawSurface2(iface); 3991 3992 TRACE("iface %p, flags %#x.\n", iface, flags); 3993 3994 return ddraw_surface7_UpdateOverlayDisplay(&surface->IDirectDrawSurface7_iface, flags); 3995 } 3996 3997 static HRESULT WINAPI ddraw_surface1_UpdateOverlayDisplay(IDirectDrawSurface *iface, DWORD flags) 3998 { 3999 struct ddraw_surface *surface = impl_from_IDirectDrawSurface(iface); 4000 4001 TRACE("iface %p, flags %#x.\n", iface, flags); 4002 4003 return ddraw_surface7_UpdateOverlayDisplay(&surface->IDirectDrawSurface7_iface, flags); 4004 } 4005 4006 /***************************************************************************** 4007 * IDirectDrawSurface7::UpdateOverlayZOrder 4008 * 4009 * Sets an overlay's Z order 4010 * 4011 * Params: 4012 * Flags: DDOVERZ_* flags 4013 * DDSRef: Defines the relative position in the overlay chain 4014 * 4015 * Returns: 4016 * DDERR_NOTOVERLAYSURFACE, because we don't support overlays 4017 * 4018 *****************************************************************************/ 4019 static HRESULT WINAPI ddraw_surface7_UpdateOverlayZOrder(IDirectDrawSurface7 *iface, 4020 DWORD flags, IDirectDrawSurface7 *reference) 4021 { 4022 struct ddraw_surface *surface = impl_from_IDirectDrawSurface7(iface); 4023 4024 FIXME("iface %p, flags %#x, reference %p stub!\n", iface, flags, reference); 4025 4026 wined3d_mutex_lock(); 4027 if (!(surface->surface_desc.ddsCaps.dwCaps & DDSCAPS_OVERLAY)) 4028 { 4029 WARN("Not an overlay surface.\n"); 4030 wined3d_mutex_unlock(); 4031 return DDERR_NOTAOVERLAYSURFACE; 4032 } 4033 wined3d_mutex_unlock(); 4034 4035 return DD_OK; 4036 } 4037 4038 static HRESULT WINAPI ddraw_surface4_UpdateOverlayZOrder(IDirectDrawSurface4 *iface, 4039 DWORD flags, IDirectDrawSurface4 *reference) 4040 { 4041 struct ddraw_surface *surface = impl_from_IDirectDrawSurface4(iface); 4042 struct ddraw_surface *reference_impl = unsafe_impl_from_IDirectDrawSurface4(reference); 4043 4044 TRACE("iface %p, flags %#x, reference %p.\n", iface, flags, reference); 4045 4046 return ddraw_surface7_UpdateOverlayZOrder(&surface->IDirectDrawSurface7_iface, flags, 4047 reference_impl ? &reference_impl->IDirectDrawSurface7_iface : NULL); 4048 } 4049 4050 static HRESULT WINAPI ddraw_surface3_UpdateOverlayZOrder(IDirectDrawSurface3 *iface, 4051 DWORD flags, IDirectDrawSurface3 *reference) 4052 { 4053 struct ddraw_surface *surface = impl_from_IDirectDrawSurface3(iface); 4054 struct ddraw_surface *reference_impl = unsafe_impl_from_IDirectDrawSurface3(reference); 4055 4056 TRACE("iface %p, flags %#x, reference %p.\n", iface, flags, reference); 4057 4058 return ddraw_surface7_UpdateOverlayZOrder(&surface->IDirectDrawSurface7_iface, flags, 4059 reference_impl ? &reference_impl->IDirectDrawSurface7_iface : NULL); 4060 } 4061 4062 static HRESULT WINAPI ddraw_surface2_UpdateOverlayZOrder(IDirectDrawSurface2 *iface, 4063 DWORD flags, IDirectDrawSurface2 *reference) 4064 { 4065 struct ddraw_surface *surface = impl_from_IDirectDrawSurface2(iface); 4066 struct ddraw_surface *reference_impl = unsafe_impl_from_IDirectDrawSurface2(reference); 4067 4068 TRACE("iface %p, flags %#x, reference %p.\n", iface, flags, reference); 4069 4070 return ddraw_surface7_UpdateOverlayZOrder(&surface->IDirectDrawSurface7_iface, flags, 4071 reference_impl ? &reference_impl->IDirectDrawSurface7_iface : NULL); 4072 } 4073 4074 static HRESULT WINAPI ddraw_surface1_UpdateOverlayZOrder(IDirectDrawSurface *iface, 4075 DWORD flags, IDirectDrawSurface *reference) 4076 { 4077 struct ddraw_surface *surface = impl_from_IDirectDrawSurface(iface); 4078 struct ddraw_surface *reference_impl = unsafe_impl_from_IDirectDrawSurface(reference); 4079 4080 TRACE("iface %p, flags %#x, reference %p.\n", iface, flags, reference); 4081 4082 return ddraw_surface7_UpdateOverlayZOrder(&surface->IDirectDrawSurface7_iface, flags, 4083 reference_impl ? &reference_impl->IDirectDrawSurface7_iface : NULL); 4084 } 4085 4086 /***************************************************************************** 4087 * IDirectDrawSurface7::GetDDInterface 4088 * 4089 * Returns the IDirectDraw7 interface pointer of the DirectDraw object this 4090 * surface belongs to 4091 * 4092 * Params: 4093 * DD: Address to write the interface pointer to 4094 * 4095 * Returns: 4096 * DD_OK on success 4097 * DDERR_INVALIDPARAMS if DD is NULL 4098 * 4099 *****************************************************************************/ 4100 static HRESULT WINAPI ddraw_surface7_GetDDInterface(IDirectDrawSurface7 *iface, void **DD) 4101 { 4102 struct ddraw_surface *This = impl_from_IDirectDrawSurface7(iface); 4103 4104 TRACE("iface %p, ddraw %p.\n", iface, DD); 4105 4106 if(!DD) 4107 return DDERR_INVALIDPARAMS; 4108 4109 switch(This->version) 4110 { 4111 case 7: 4112 *DD = &This->ddraw->IDirectDraw7_iface; 4113 break; 4114 4115 case 4: 4116 *DD = &This->ddraw->IDirectDraw4_iface; 4117 break; 4118 4119 case 2: 4120 *DD = &This->ddraw->IDirectDraw2_iface; 4121 break; 4122 4123 case 1: 4124 *DD = &This->ddraw->IDirectDraw_iface; 4125 break; 4126 4127 } 4128 IUnknown_AddRef((IUnknown *)*DD); 4129 4130 return DD_OK; 4131 } 4132 4133 static HRESULT WINAPI ddraw_surface4_GetDDInterface(IDirectDrawSurface4 *iface, void **ddraw) 4134 { 4135 struct ddraw_surface *surface = impl_from_IDirectDrawSurface4(iface); 4136 4137 TRACE("iface %p, ddraw %p.\n", iface, ddraw); 4138 4139 return ddraw_surface7_GetDDInterface(&surface->IDirectDrawSurface7_iface, ddraw); 4140 } 4141 4142 static HRESULT WINAPI ddraw_surface3_GetDDInterface(IDirectDrawSurface3 *iface, void **ddraw) 4143 { 4144 struct ddraw_surface *surface = impl_from_IDirectDrawSurface3(iface); 4145 4146 TRACE("iface %p, ddraw %p.\n", iface, ddraw); 4147 4148 return ddraw_surface7_GetDDInterface(&surface->IDirectDrawSurface7_iface, ddraw); 4149 } 4150 4151 static HRESULT WINAPI ddraw_surface2_GetDDInterface(IDirectDrawSurface2 *iface, void **ddraw) 4152 { 4153 struct ddraw_surface *surface = impl_from_IDirectDrawSurface2(iface); 4154 4155 TRACE("iface %p, ddraw %p.\n", iface, ddraw); 4156 4157 return ddraw_surface7_GetDDInterface(&surface->IDirectDrawSurface7_iface, ddraw); 4158 } 4159 4160 static HRESULT WINAPI ddraw_surface7_ChangeUniquenessValue(IDirectDrawSurface7 *iface) 4161 { 4162 TRACE("iface %p.\n", iface); 4163 4164 return DD_OK; 4165 } 4166 4167 static HRESULT WINAPI ddraw_surface4_ChangeUniquenessValue(IDirectDrawSurface4 *iface) 4168 { 4169 struct ddraw_surface *surface = impl_from_IDirectDrawSurface4(iface); 4170 4171 TRACE("iface %p.\n", iface); 4172 4173 return ddraw_surface7_ChangeUniquenessValue(&surface->IDirectDrawSurface7_iface); 4174 } 4175 4176 static HRESULT WINAPI ddraw_surface7_GetUniquenessValue(IDirectDrawSurface7 *iface, DWORD *pValue) 4177 { 4178 TRACE("iface %p, value %p.\n", iface, pValue); 4179 4180 *pValue = 0; 4181 4182 return DD_OK; 4183 } 4184 4185 static HRESULT WINAPI ddraw_surface4_GetUniquenessValue(IDirectDrawSurface4 *iface, DWORD *pValue) 4186 { 4187 struct ddraw_surface *surface = impl_from_IDirectDrawSurface4(iface); 4188 4189 TRACE("iface %p, value %p.\n", iface, pValue); 4190 4191 return ddraw_surface7_GetUniquenessValue(&surface->IDirectDrawSurface7_iface, pValue); 4192 } 4193 4194 /***************************************************************************** 4195 * IDirectDrawSurface7::SetLOD 4196 * 4197 * Sets the level of detail of a texture 4198 * 4199 * Params: 4200 * MaxLOD: LOD to set 4201 * 4202 * Returns: 4203 * DD_OK on success 4204 * DDERR_INVALIDOBJECT if the surface is invalid for this method 4205 * 4206 *****************************************************************************/ 4207 static HRESULT WINAPI ddraw_surface7_SetLOD(IDirectDrawSurface7 *iface, DWORD MaxLOD) 4208 { 4209 struct ddraw_surface *surface = impl_from_IDirectDrawSurface7(iface); 4210 HRESULT hr; 4211 4212 TRACE("iface %p, lod %u.\n", iface, MaxLOD); 4213 4214 wined3d_mutex_lock(); 4215 if (!(surface->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_TEXTUREMANAGE)) 4216 { 4217 wined3d_mutex_unlock(); 4218 return DDERR_INVALIDOBJECT; 4219 } 4220 4221 hr = wined3d_texture_set_lod(surface->wined3d_texture, MaxLOD); 4222 wined3d_mutex_unlock(); 4223 4224 return hr; 4225 } 4226 4227 /***************************************************************************** 4228 * IDirectDrawSurface7::GetLOD 4229 * 4230 * Returns the level of detail of a Direct3D texture 4231 * 4232 * Params: 4233 * MaxLOD: Address to write the LOD to 4234 * 4235 * Returns: 4236 * DD_OK on success 4237 * DDERR_INVALIDPARAMS if MaxLOD is NULL 4238 * DDERR_INVALIDOBJECT if the surface is invalid for this method 4239 * 4240 *****************************************************************************/ 4241 static HRESULT WINAPI ddraw_surface7_GetLOD(IDirectDrawSurface7 *iface, DWORD *MaxLOD) 4242 { 4243 struct ddraw_surface *surface = impl_from_IDirectDrawSurface7(iface); 4244 4245 TRACE("iface %p, lod %p.\n", iface, MaxLOD); 4246 4247 if(!MaxLOD) 4248 return DDERR_INVALIDPARAMS; 4249 4250 wined3d_mutex_lock(); 4251 if (!(surface->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_TEXTUREMANAGE)) 4252 { 4253 wined3d_mutex_unlock(); 4254 return DDERR_INVALIDOBJECT; 4255 } 4256 4257 *MaxLOD = wined3d_texture_get_lod(surface->wined3d_texture); 4258 wined3d_mutex_unlock(); 4259 4260 return DD_OK; 4261 } 4262 4263 /***************************************************************************** 4264 * IDirectDrawSurface7::BltFast 4265 * 4266 * Performs a fast Blit. 4267 * 4268 * Params: 4269 * dstx: The x coordinate to blit to on the destination 4270 * dsty: The y coordinate to blit to on the destination 4271 * Source: The source surface 4272 * rsrc: The source rectangle 4273 * trans: Type of transfer. Some DDBLTFAST_* flags 4274 * 4275 * Returns: 4276 * DD_OK on success, error code otherwise. 4277 * 4278 *****************************************************************************/ 4279 static HRESULT WINAPI DECLSPEC_HOTPATCH ddraw_surface7_BltFast(IDirectDrawSurface7 *iface, 4280 DWORD dst_x, DWORD dst_y, IDirectDrawSurface7 *src_surface, RECT *src_rect, DWORD trans) 4281 { 4282 struct ddraw_surface *dst_impl = impl_from_IDirectDrawSurface7(iface); 4283 struct ddraw_surface *src_impl = unsafe_impl_from_IDirectDrawSurface7(src_surface); 4284 DWORD flags = WINED3D_BLT_SYNCHRONOUS; 4285 DWORD src_w, src_h, dst_w, dst_h; 4286 HRESULT hr = DD_OK; 4287 RECT dst_rect, s; 4288 4289 TRACE("iface %p, dst_x %u, dst_y %u, src_surface %p, src_rect %s, flags %#x.\n", 4290 iface, dst_x, dst_y, src_surface, wine_dbgstr_rect(src_rect), trans); 4291 4292 dst_w = dst_impl->surface_desc.dwWidth; 4293 dst_h = dst_impl->surface_desc.dwHeight; 4294 4295 if (!src_rect) 4296 { 4297 SetRect(&s, 0, 0, src_impl->surface_desc.dwWidth, src_impl->surface_desc.dwHeight); 4298 src_rect = &s; 4299 } 4300 4301 src_w = src_rect->right - src_rect->left; 4302 src_h = src_rect->bottom - src_rect->top; 4303 if (src_w > dst_w || dst_x > dst_w - src_w 4304 || src_h > dst_h || dst_y > dst_h - src_h) 4305 { 4306 WARN("Destination area out of bounds, returning DDERR_INVALIDRECT.\n"); 4307 return DDERR_INVALIDRECT; 4308 } 4309 4310 SetRect(&dst_rect, dst_x, dst_y, dst_x + src_w, dst_y + src_h); 4311 if (trans & DDBLTFAST_SRCCOLORKEY) 4312 flags |= WINED3D_BLT_SRC_CKEY; 4313 if (trans & DDBLTFAST_DESTCOLORKEY) 4314 flags |= WINED3D_BLT_DST_CKEY; 4315 if (trans & DDBLTFAST_WAIT) 4316 flags |= WINED3D_BLT_WAIT; 4317 if (trans & DDBLTFAST_DONOTWAIT) 4318 flags |= WINED3D_BLT_DO_NOT_WAIT; 4319 4320 wined3d_mutex_lock(); 4321 if (dst_impl->clipper) 4322 { 4323 wined3d_mutex_unlock(); 4324 WARN("Destination surface has a clipper set, returning DDERR_BLTFASTCANTCLIP.\n"); 4325 return DDERR_BLTFASTCANTCLIP; 4326 } 4327 4328 if (src_impl->surface_desc.ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE) 4329 hr = ddraw_surface_update_frontbuffer(src_impl, src_rect, TRUE, 0); 4330 if (SUCCEEDED(hr)) 4331 hr = wined3d_texture_blt(dst_impl->wined3d_texture, dst_impl->sub_resource_idx, &dst_rect, 4332 src_impl->wined3d_texture, src_impl->sub_resource_idx, src_rect, flags, NULL, WINED3D_TEXF_POINT); 4333 if (SUCCEEDED(hr) && (dst_impl->surface_desc.ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE)) 4334 hr = ddraw_surface_update_frontbuffer(dst_impl, &dst_rect, FALSE, 0); 4335 wined3d_mutex_unlock(); 4336 4337 switch(hr) 4338 { 4339 case WINED3DERR_NOTAVAILABLE: return DDERR_UNSUPPORTED; 4340 default: return hr; 4341 } 4342 } 4343 4344 static HRESULT WINAPI DECLSPEC_HOTPATCH ddraw_surface4_BltFast(IDirectDrawSurface4 *iface, DWORD dst_x, DWORD dst_y, 4345 IDirectDrawSurface4 *src_surface, RECT *src_rect, DWORD flags) 4346 { 4347 struct ddraw_surface *dst_impl = impl_from_IDirectDrawSurface4(iface); 4348 struct ddraw_surface *src_impl = unsafe_impl_from_IDirectDrawSurface4(src_surface); 4349 4350 TRACE("iface %p, dst_x %u, dst_y %u, src_surface %p, src_rect %s, flags %#x.\n", 4351 iface, dst_x, dst_y, src_surface, wine_dbgstr_rect(src_rect), flags); 4352 4353 return ddraw_surface7_BltFast(&dst_impl->IDirectDrawSurface7_iface, dst_x, dst_y, 4354 src_impl ? &src_impl->IDirectDrawSurface7_iface : NULL, src_rect, flags); 4355 } 4356 4357 static HRESULT WINAPI DECLSPEC_HOTPATCH ddraw_surface3_BltFast(IDirectDrawSurface3 *iface, DWORD dst_x, DWORD dst_y, 4358 IDirectDrawSurface3 *src_surface, RECT *src_rect, DWORD flags) 4359 { 4360 struct ddraw_surface *dst_impl = impl_from_IDirectDrawSurface3(iface); 4361 struct ddraw_surface *src_impl = unsafe_impl_from_IDirectDrawSurface3(src_surface); 4362 4363 TRACE("iface %p, dst_x %u, dst_y %u, src_surface %p, src_rect %s, flags %#x.\n", 4364 iface, dst_x, dst_y, src_surface, wine_dbgstr_rect(src_rect), flags); 4365 4366 return ddraw_surface7_BltFast(&dst_impl->IDirectDrawSurface7_iface, dst_x, dst_y, 4367 src_impl ? &src_impl->IDirectDrawSurface7_iface : NULL, src_rect, flags); 4368 } 4369 4370 static HRESULT WINAPI DECLSPEC_HOTPATCH ddraw_surface2_BltFast(IDirectDrawSurface2 *iface, DWORD dst_x, DWORD dst_y, 4371 IDirectDrawSurface2 *src_surface, RECT *src_rect, DWORD flags) 4372 { 4373 struct ddraw_surface *dst_impl = impl_from_IDirectDrawSurface2(iface); 4374 struct ddraw_surface *src_impl = unsafe_impl_from_IDirectDrawSurface2(src_surface); 4375 4376 TRACE("iface %p, dst_x %u, dst_y %u, src_surface %p, src_rect %s, flags %#x.\n", 4377 iface, dst_x, dst_y, src_surface, wine_dbgstr_rect(src_rect), flags); 4378 4379 return ddraw_surface7_BltFast(&dst_impl->IDirectDrawSurface7_iface, dst_x, dst_y, 4380 src_impl ? &src_impl->IDirectDrawSurface7_iface : NULL, src_rect, flags); 4381 } 4382 4383 static HRESULT WINAPI DECLSPEC_HOTPATCH ddraw_surface1_BltFast(IDirectDrawSurface *iface, DWORD dst_x, DWORD dst_y, 4384 IDirectDrawSurface *src_surface, RECT *src_rect, DWORD flags) 4385 { 4386 struct ddraw_surface *dst_impl = impl_from_IDirectDrawSurface(iface); 4387 struct ddraw_surface *src_impl = unsafe_impl_from_IDirectDrawSurface(src_surface); 4388 4389 TRACE("iface %p, dst_x %u, dst_y %u, src_surface %p, src_rect %s, flags %#x.\n", 4390 iface, dst_x, dst_y, src_surface, wine_dbgstr_rect(src_rect), flags); 4391 4392 return ddraw_surface7_BltFast(&dst_impl->IDirectDrawSurface7_iface, dst_x, dst_y, 4393 src_impl ? &src_impl->IDirectDrawSurface7_iface : NULL, src_rect, flags); 4394 } 4395 4396 /***************************************************************************** 4397 * IDirectDrawSurface7::GetClipper 4398 * 4399 * Returns the IDirectDrawClipper interface of the clipper assigned to this 4400 * surface 4401 * 4402 * Params: 4403 * Clipper: Address to store the interface pointer at 4404 * 4405 * Returns: 4406 * DD_OK on success 4407 * DDERR_INVALIDPARAMS if Clipper is NULL 4408 * DDERR_NOCLIPPERATTACHED if there's no clipper attached 4409 * 4410 *****************************************************************************/ 4411 static HRESULT WINAPI ddraw_surface7_GetClipper(IDirectDrawSurface7 *iface, IDirectDrawClipper **Clipper) 4412 { 4413 struct ddraw_surface *surface = impl_from_IDirectDrawSurface7(iface); 4414 4415 TRACE("iface %p, clipper %p.\n", iface, Clipper); 4416 4417 if (!Clipper) 4418 return DDERR_INVALIDPARAMS; 4419 4420 wined3d_mutex_lock(); 4421 if (!surface->clipper) 4422 { 4423 wined3d_mutex_unlock(); 4424 return DDERR_NOCLIPPERATTACHED; 4425 } 4426 4427 *Clipper = &surface->clipper->IDirectDrawClipper_iface; 4428 IDirectDrawClipper_AddRef(*Clipper); 4429 wined3d_mutex_unlock(); 4430 4431 return DD_OK; 4432 } 4433 4434 static HRESULT WINAPI ddraw_surface4_GetClipper(IDirectDrawSurface4 *iface, IDirectDrawClipper **clipper) 4435 { 4436 struct ddraw_surface *surface = impl_from_IDirectDrawSurface4(iface); 4437 4438 TRACE("iface %p, clipper %p.\n", iface, clipper); 4439 4440 return ddraw_surface7_GetClipper(&surface->IDirectDrawSurface7_iface, clipper); 4441 } 4442 4443 static HRESULT WINAPI ddraw_surface3_GetClipper(IDirectDrawSurface3 *iface, IDirectDrawClipper **clipper) 4444 { 4445 struct ddraw_surface *surface = impl_from_IDirectDrawSurface3(iface); 4446 4447 TRACE("iface %p, clipper %p.\n", iface, clipper); 4448 4449 return ddraw_surface7_GetClipper(&surface->IDirectDrawSurface7_iface, clipper); 4450 } 4451 4452 static HRESULT WINAPI ddraw_surface2_GetClipper(IDirectDrawSurface2 *iface, IDirectDrawClipper **clipper) 4453 { 4454 struct ddraw_surface *surface = impl_from_IDirectDrawSurface2(iface); 4455 4456 TRACE("iface %p, clipper %p.\n", iface, clipper); 4457 4458 return ddraw_surface7_GetClipper(&surface->IDirectDrawSurface7_iface, clipper); 4459 } 4460 4461 static HRESULT WINAPI ddraw_surface1_GetClipper(IDirectDrawSurface *iface, IDirectDrawClipper **clipper) 4462 { 4463 struct ddraw_surface *surface = impl_from_IDirectDrawSurface(iface); 4464 4465 TRACE("iface %p, clipper %p.\n", iface, clipper); 4466 4467 return ddraw_surface7_GetClipper(&surface->IDirectDrawSurface7_iface, clipper); 4468 } 4469 4470 /***************************************************************************** 4471 * IDirectDrawSurface7::SetClipper 4472 * 4473 * Sets a clipper for the surface 4474 * 4475 * Params: 4476 * Clipper: IDirectDrawClipper interface of the clipper to set 4477 * 4478 * Returns: 4479 * DD_OK on success 4480 * 4481 *****************************************************************************/ 4482 static HRESULT WINAPI ddraw_surface7_SetClipper(IDirectDrawSurface7 *iface, 4483 IDirectDrawClipper *iclipper) 4484 { 4485 struct ddraw_surface *This = impl_from_IDirectDrawSurface7(iface); 4486 struct ddraw_clipper *clipper = unsafe_impl_from_IDirectDrawClipper(iclipper); 4487 struct ddraw_clipper *old_clipper = This->clipper; 4488 HWND clipWindow; 4489 4490 TRACE("iface %p, clipper %p.\n", iface, iclipper); 4491 4492 wined3d_mutex_lock(); 4493 if (clipper == This->clipper) 4494 { 4495 wined3d_mutex_unlock(); 4496 return DD_OK; 4497 } 4498 4499 This->clipper = clipper; 4500 4501 if (clipper != NULL) 4502 IDirectDrawClipper_AddRef(iclipper); 4503 if (old_clipper) 4504 IDirectDrawClipper_Release(&old_clipper->IDirectDrawClipper_iface); 4505 4506 if ((This->surface_desc.ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE) && This->ddraw->wined3d_swapchain) 4507 { 4508 clipWindow = NULL; 4509 if(clipper) { 4510 IDirectDrawClipper_GetHWnd(iclipper, &clipWindow); 4511 } 4512 4513 if (clipWindow) 4514 { 4515 wined3d_swapchain_set_window(This->ddraw->wined3d_swapchain, clipWindow); 4516 ddraw_set_swapchain_window(This->ddraw, clipWindow); 4517 } 4518 else 4519 { 4520 wined3d_swapchain_set_window(This->ddraw->wined3d_swapchain, This->ddraw->d3d_window); 4521 ddraw_set_swapchain_window(This->ddraw, This->ddraw->dest_window); 4522 } 4523 } 4524 4525 wined3d_mutex_unlock(); 4526 4527 return DD_OK; 4528 } 4529 4530 static HRESULT WINAPI ddraw_surface4_SetClipper(IDirectDrawSurface4 *iface, IDirectDrawClipper *clipper) 4531 { 4532 struct ddraw_surface *surface = impl_from_IDirectDrawSurface4(iface); 4533 4534 TRACE("iface %p, clipper %p.\n", iface, clipper); 4535 4536 return ddraw_surface7_SetClipper(&surface->IDirectDrawSurface7_iface, clipper); 4537 } 4538 4539 static HRESULT WINAPI ddraw_surface3_SetClipper(IDirectDrawSurface3 *iface, IDirectDrawClipper *clipper) 4540 { 4541 struct ddraw_surface *surface = impl_from_IDirectDrawSurface3(iface); 4542 4543 TRACE("iface %p, clipper %p.\n", iface, clipper); 4544 4545 return ddraw_surface7_SetClipper(&surface->IDirectDrawSurface7_iface, clipper); 4546 } 4547 4548 static HRESULT WINAPI ddraw_surface2_SetClipper(IDirectDrawSurface2 *iface, IDirectDrawClipper *clipper) 4549 { 4550 struct ddraw_surface *surface = impl_from_IDirectDrawSurface2(iface); 4551 4552 TRACE("iface %p, clipper %p.\n", iface, clipper); 4553 4554 return ddraw_surface7_SetClipper(&surface->IDirectDrawSurface7_iface, clipper); 4555 } 4556 4557 static HRESULT WINAPI ddraw_surface1_SetClipper(IDirectDrawSurface *iface, IDirectDrawClipper *clipper) 4558 { 4559 struct ddraw_surface *surface = impl_from_IDirectDrawSurface(iface); 4560 4561 TRACE("iface %p, clipper %p.\n", iface, clipper); 4562 4563 return ddraw_surface7_SetClipper(&surface->IDirectDrawSurface7_iface, clipper); 4564 } 4565 4566 /***************************************************************************** 4567 * IDirectDrawSurface7::SetSurfaceDesc 4568 * 4569 * Sets the surface description. It can override the pixel format, the surface 4570 * memory, ... 4571 * It's not really tested. 4572 * 4573 * Params: 4574 * DDSD: Pointer to the new surface description to set 4575 * Flags: Some flags 4576 * 4577 * Returns: 4578 * DD_OK on success 4579 * DDERR_INVALIDPARAMS if DDSD is NULL 4580 * 4581 *****************************************************************************/ 4582 static HRESULT WINAPI ddraw_surface7_SetSurfaceDesc(IDirectDrawSurface7 *iface, DDSURFACEDESC2 *DDSD, DWORD Flags) 4583 { 4584 struct ddraw_surface *This = impl_from_IDirectDrawSurface7(iface); 4585 HRESULT hr; 4586 const DWORD allowed_flags = DDSD_LPSURFACE | DDSD_PIXELFORMAT | DDSD_WIDTH 4587 | DDSD_HEIGHT | DDSD_PITCH | DDSD_CAPS; 4588 enum wined3d_format_id format_id; 4589 UINT pitch, width, height; 4590 4591 TRACE("iface %p, surface_desc %p, flags %#x.\n", iface, DDSD, Flags); 4592 4593 if (!DDSD) 4594 { 4595 WARN("DDSD is NULL, returning DDERR_INVALIDPARAMS\n"); 4596 return DDERR_INVALIDPARAMS; 4597 } 4598 if (Flags) 4599 { 4600 WARN("Flags is %x, returning DDERR_INVALIDPARAMS\n", Flags); 4601 return DDERR_INVALIDPARAMS; 4602 } 4603 if (!(This->surface_desc.ddsCaps.dwCaps & DDSCAPS_SYSTEMMEMORY) 4604 || This->surface_desc.ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE 4605 || This->surface_desc.ddsCaps.dwCaps2 & (DDSCAPS2_TEXTUREMANAGE | DDSCAPS2_D3DTEXTUREMANAGE)) 4606 { 4607 WARN("Surface is not in system memory, returning DDERR_INVALIDSURFACETYPE.\n"); 4608 return DDERR_INVALIDSURFACETYPE; 4609 } 4610 4611 /* Tests show that only LPSURFACE and PIXELFORMAT can be set, and LPSURFACE is required 4612 * for PIXELFORMAT to work */ 4613 if (DDSD->dwFlags & ~allowed_flags) 4614 { 4615 WARN("Invalid flags (0x%08x) set, returning DDERR_INVALIDPARAMS\n", DDSD->dwFlags); 4616 return DDERR_INVALIDPARAMS; 4617 } 4618 if (!(DDSD->dwFlags & DDSD_LPSURFACE) || !DDSD->lpSurface) 4619 { 4620 WARN("DDSD_LPSURFACE is not set or lpSurface is NULL, returning DDERR_INVALIDPARAMS\n"); 4621 return DDERR_INVALIDPARAMS; 4622 } 4623 if ((DDSD->dwFlags & DDSD_CAPS) && DDSD->ddsCaps.dwCaps) 4624 { 4625 WARN("DDSD_CAPS is set, returning DDERR_INVALIDCAPS.\n"); 4626 return DDERR_INVALIDCAPS; 4627 } 4628 if (DDSD->dwFlags & DDSD_WIDTH) 4629 { 4630 if (!(DDSD->dwFlags & DDSD_PITCH)) 4631 { 4632 WARN("DDSD_WIDTH is set, but DDSD_PITCH is not, returning DDERR_INVALIDPARAMS.\n"); 4633 return DDERR_INVALIDPARAMS; 4634 } 4635 if (!DDSD->dwWidth || DDSD->u1.lPitch <= 0 || DDSD->u1.lPitch & 0x3) 4636 { 4637 WARN("Pitch is %d, width is %u, returning DDERR_INVALIDPARAMS.\n", 4638 DDSD->u1.lPitch, DDSD->dwWidth); 4639 return DDERR_INVALIDPARAMS; 4640 } 4641 if (DDSD->dwWidth != This->surface_desc.dwWidth) 4642 TRACE("Surface width changed from %u to %u.\n", This->surface_desc.dwWidth, DDSD->dwWidth); 4643 if (DDSD->u1.lPitch != This->surface_desc.u1.lPitch) 4644 TRACE("Surface pitch changed from %u to %u.\n", This->surface_desc.u1.lPitch, DDSD->u1.lPitch); 4645 pitch = DDSD->u1.lPitch; 4646 width = DDSD->dwWidth; 4647 } 4648 else if (DDSD->dwFlags & DDSD_PITCH) 4649 { 4650 WARN("DDSD_PITCH is set, but DDSD_WIDTH is not, returning DDERR_INVALIDPARAMS.\n"); 4651 return DDERR_INVALIDPARAMS; 4652 } 4653 else 4654 { 4655 pitch = This->surface_desc.u1.lPitch; 4656 width = This->surface_desc.dwWidth; 4657 } 4658 4659 if (DDSD->dwFlags & DDSD_HEIGHT) 4660 { 4661 if (!DDSD->dwHeight) 4662 { 4663 WARN("Height is 0, returning DDERR_INVALIDPARAMS.\n"); 4664 return DDERR_INVALIDPARAMS; 4665 } 4666 if (DDSD->dwHeight != This->surface_desc.dwHeight) 4667 TRACE("Surface height changed from %u to %u.\n", This->surface_desc.dwHeight, DDSD->dwHeight); 4668 height = DDSD->dwHeight; 4669 } 4670 else 4671 { 4672 height = This->surface_desc.dwHeight; 4673 } 4674 4675 wined3d_mutex_lock(); 4676 if (DDSD->dwFlags & DDSD_PIXELFORMAT) 4677 { 4678 enum wined3d_format_id current_format_id; 4679 format_id = wined3dformat_from_ddrawformat(&DDSD->u4.ddpfPixelFormat); 4680 4681 if (format_id == WINED3DFMT_UNKNOWN) 4682 { 4683 ERR("Requested to set an unknown pixelformat\n"); 4684 wined3d_mutex_unlock(); 4685 return DDERR_INVALIDPARAMS; 4686 } 4687 current_format_id = wined3dformat_from_ddrawformat(&This->surface_desc.u4.ddpfPixelFormat); 4688 if (format_id != current_format_id) 4689 TRACE("Surface format changed from %#x to %#x.\n", current_format_id, format_id); 4690 } 4691 else 4692 { 4693 format_id = wined3dformat_from_ddrawformat(&This->surface_desc.u4.ddpfPixelFormat); 4694 } 4695 4696 if (FAILED(hr = wined3d_texture_update_desc(This->wined3d_texture, width, height, 4697 format_id, WINED3D_MULTISAMPLE_NONE, 0, DDSD->lpSurface, pitch))) 4698 { 4699 WARN("Failed to update surface desc, hr %#x.\n", hr); 4700 wined3d_mutex_unlock(); 4701 return hr_ddraw_from_wined3d(hr); 4702 } 4703 4704 if (DDSD->dwFlags & DDSD_WIDTH) 4705 This->surface_desc.dwWidth = width; 4706 if (DDSD->dwFlags & DDSD_PITCH) 4707 This->surface_desc.u1.lPitch = DDSD->u1.lPitch; 4708 if (DDSD->dwFlags & DDSD_HEIGHT) 4709 This->surface_desc.dwHeight = height; 4710 if (DDSD->dwFlags & DDSD_PIXELFORMAT) 4711 This->surface_desc.u4.ddpfPixelFormat = DDSD->u4.ddpfPixelFormat; 4712 4713 wined3d_mutex_unlock(); 4714 4715 return DD_OK; 4716 } 4717 4718 static HRESULT WINAPI ddraw_surface4_SetSurfaceDesc(IDirectDrawSurface4 *iface, 4719 DDSURFACEDESC2 *surface_desc, DWORD flags) 4720 { 4721 struct ddraw_surface *surface = impl_from_IDirectDrawSurface4(iface); 4722 4723 TRACE("iface %p, surface_desc %p, flags %#x.\n", iface, surface_desc, flags); 4724 4725 return ddraw_surface7_SetSurfaceDesc(&surface->IDirectDrawSurface7_iface, 4726 surface_desc, flags); 4727 } 4728 4729 static HRESULT WINAPI ddraw_surface3_SetSurfaceDesc(IDirectDrawSurface3 *iface, 4730 DDSURFACEDESC *surface_desc, DWORD flags) 4731 { 4732 struct ddraw_surface *surface = impl_from_IDirectDrawSurface3(iface); 4733 DDSURFACEDESC2 surface_desc2; 4734 4735 TRACE("iface %p, surface_desc %p, flags %#x.\n", iface, surface_desc, flags); 4736 4737 if (surface_desc) DDSD_to_DDSD2(surface_desc, &surface_desc2); 4738 return ddraw_surface7_SetSurfaceDesc(&surface->IDirectDrawSurface7_iface, 4739 surface_desc ? &surface_desc2 : NULL, flags); 4740 } 4741 4742 static HRESULT WINAPI ddraw_surface7_GetPalette(IDirectDrawSurface7 *iface, IDirectDrawPalette **palette) 4743 { 4744 struct ddraw_surface *surface = impl_from_IDirectDrawSurface7(iface); 4745 struct ddraw_palette *palette_impl; 4746 HRESULT hr = DD_OK; 4747 4748 TRACE("iface %p, palette %p.\n", iface, palette); 4749 4750 if (!palette) 4751 return DDERR_INVALIDPARAMS; 4752 if (IDirectDrawSurface7_IsLost(iface) == DDERR_SURFACELOST) 4753 { 4754 WARN("Surface lost, returning DDERR_SURFACELOST.\n"); 4755 return DDERR_SURFACELOST; 4756 } 4757 4758 wined3d_mutex_lock(); 4759 if ((palette_impl = surface->palette)) 4760 { 4761 *palette = &palette_impl->IDirectDrawPalette_iface; 4762 IDirectDrawPalette_AddRef(*palette); 4763 } 4764 else 4765 { 4766 *palette = NULL; 4767 hr = DDERR_NOPALETTEATTACHED; 4768 } 4769 wined3d_mutex_unlock(); 4770 4771 return hr; 4772 } 4773 4774 static HRESULT WINAPI ddraw_surface4_GetPalette(IDirectDrawSurface4 *iface, IDirectDrawPalette **palette) 4775 { 4776 struct ddraw_surface *surface = impl_from_IDirectDrawSurface4(iface); 4777 4778 TRACE("iface %p, palette %p.\n", iface, palette); 4779 4780 return ddraw_surface7_GetPalette(&surface->IDirectDrawSurface7_iface, palette); 4781 } 4782 4783 static HRESULT WINAPI ddraw_surface3_GetPalette(IDirectDrawSurface3 *iface, IDirectDrawPalette **palette) 4784 { 4785 struct ddraw_surface *surface = impl_from_IDirectDrawSurface3(iface); 4786 4787 TRACE("iface %p, palette %p.\n", iface, palette); 4788 4789 return ddraw_surface7_GetPalette(&surface->IDirectDrawSurface7_iface, palette); 4790 } 4791 4792 static HRESULT WINAPI ddraw_surface2_GetPalette(IDirectDrawSurface2 *iface, IDirectDrawPalette **palette) 4793 { 4794 struct ddraw_surface *surface = impl_from_IDirectDrawSurface2(iface); 4795 4796 TRACE("iface %p, palette %p.\n", iface, palette); 4797 4798 return ddraw_surface7_GetPalette(&surface->IDirectDrawSurface7_iface, palette); 4799 } 4800 4801 static HRESULT WINAPI ddraw_surface1_GetPalette(IDirectDrawSurface *iface, IDirectDrawPalette **palette) 4802 { 4803 struct ddraw_surface *surface = impl_from_IDirectDrawSurface(iface); 4804 4805 TRACE("iface %p, palette %p.\n", iface, palette); 4806 4807 return ddraw_surface7_GetPalette(&surface->IDirectDrawSurface7_iface, palette); 4808 } 4809 4810 static HRESULT ddraw_surface_set_color_key(struct ddraw_surface *surface, DWORD flags, DDCOLORKEY *color_key) 4811 { 4812 DDCOLORKEY fixed_color_key; 4813 HRESULT hr = WINED3D_OK; 4814 4815 if (flags & DDCKEY_COLORSPACE) 4816 { 4817 if (color_key && color_key->dwColorSpaceLowValue != color_key->dwColorSpaceHighValue) 4818 { 4819 WARN("Range color keys are not supported, returning DDERR_NOCOLORKEYHW.\n"); 4820 return DDERR_NOCOLORKEYHW; 4821 } 4822 flags &= ~DDCKEY_COLORSPACE; 4823 } 4824 4825 wined3d_mutex_lock(); 4826 4827 if (color_key) 4828 { 4829 fixed_color_key.dwColorSpaceLowValue = fixed_color_key.dwColorSpaceHighValue = color_key->dwColorSpaceLowValue; 4830 switch (flags & ~DDCKEY_COLORSPACE) 4831 { 4832 case DDCKEY_DESTBLT: 4833 surface->surface_desc.ddckCKDestBlt = fixed_color_key; 4834 surface->surface_desc.dwFlags |= DDSD_CKDESTBLT; 4835 break; 4836 4837 case DDCKEY_DESTOVERLAY: 4838 surface->surface_desc.u3.ddckCKDestOverlay = fixed_color_key; 4839 surface->surface_desc.dwFlags |= DDSD_CKDESTOVERLAY; 4840 break; 4841 4842 case DDCKEY_SRCOVERLAY: 4843 surface->surface_desc.ddckCKSrcOverlay = fixed_color_key; 4844 surface->surface_desc.dwFlags |= DDSD_CKSRCOVERLAY; 4845 break; 4846 4847 case DDCKEY_SRCBLT: 4848 surface->surface_desc.ddckCKSrcBlt = fixed_color_key; 4849 surface->surface_desc.dwFlags |= DDSD_CKSRCBLT; 4850 break; 4851 4852 default: 4853 wined3d_mutex_unlock(); 4854 return DDERR_INVALIDPARAMS; 4855 } 4856 } 4857 else 4858 { 4859 switch (flags & ~DDCKEY_COLORSPACE) 4860 { 4861 case DDCKEY_DESTBLT: 4862 surface->surface_desc.dwFlags &= ~DDSD_CKDESTBLT; 4863 break; 4864 4865 case DDCKEY_DESTOVERLAY: 4866 surface->surface_desc.dwFlags &= ~DDSD_CKDESTOVERLAY; 4867 break; 4868 4869 case DDCKEY_SRCOVERLAY: 4870 surface->surface_desc.dwFlags &= ~DDSD_CKSRCOVERLAY; 4871 break; 4872 4873 case DDCKEY_SRCBLT: 4874 surface->surface_desc.dwFlags &= ~DDSD_CKSRCBLT; 4875 break; 4876 4877 default: 4878 wined3d_mutex_unlock(); 4879 return DDERR_INVALIDPARAMS; 4880 } 4881 } 4882 4883 if (surface->is_complex_root) 4884 hr = wined3d_texture_set_color_key(surface->wined3d_texture, flags, 4885 color_key ? (struct wined3d_color_key *)&fixed_color_key : NULL); 4886 4887 wined3d_mutex_unlock(); 4888 4889 return hr_ddraw_from_wined3d(hr); 4890 } 4891 4892 static HRESULT WINAPI ddraw_surface7_SetColorKey(IDirectDrawSurface7 *iface, DWORD flags, DDCOLORKEY *color_key) 4893 { 4894 struct ddraw_surface *surface = impl_from_IDirectDrawSurface7(iface); 4895 4896 TRACE("iface %p, flags %#x, color_key %p.\n", iface, flags, color_key); 4897 4898 if (surface->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_MIPMAPSUBLEVEL) 4899 return DDERR_NOTONMIPMAPSUBLEVEL; 4900 4901 return ddraw_surface_set_color_key(surface, flags, color_key); 4902 } 4903 4904 static HRESULT WINAPI ddraw_surface4_SetColorKey(IDirectDrawSurface4 *iface, DWORD flags, DDCOLORKEY *color_key) 4905 { 4906 struct ddraw_surface *surface = impl_from_IDirectDrawSurface4(iface); 4907 4908 TRACE("iface %p, flags %#x, color_key %p.\n", iface, flags, color_key); 4909 4910 return ddraw_surface_set_color_key(surface, flags, color_key); 4911 } 4912 4913 static HRESULT WINAPI ddraw_surface3_SetColorKey(IDirectDrawSurface3 *iface, DWORD flags, DDCOLORKEY *color_key) 4914 { 4915 struct ddraw_surface *surface = impl_from_IDirectDrawSurface3(iface); 4916 4917 TRACE("iface %p, flags %#x, color_key %p.\n", iface, flags, color_key); 4918 4919 return ddraw_surface_set_color_key(surface, flags, color_key); 4920 } 4921 4922 static HRESULT WINAPI ddraw_surface2_SetColorKey(IDirectDrawSurface2 *iface, DWORD flags, DDCOLORKEY *color_key) 4923 { 4924 struct ddraw_surface *surface = impl_from_IDirectDrawSurface2(iface); 4925 4926 TRACE("iface %p, flags %#x, color_key %p.\n", iface, flags, color_key); 4927 4928 return ddraw_surface_set_color_key(surface, flags, color_key); 4929 } 4930 4931 static HRESULT WINAPI ddraw_surface1_SetColorKey(IDirectDrawSurface *iface, DWORD flags, DDCOLORKEY *color_key) 4932 { 4933 struct ddraw_surface *surface = impl_from_IDirectDrawSurface(iface); 4934 4935 TRACE("iface %p, flags %#x, color_key %p.\n", iface, flags, color_key); 4936 4937 return ddraw_surface_set_color_key(surface, flags, color_key); 4938 } 4939 4940 static HRESULT WINAPI ddraw_surface7_SetPalette(IDirectDrawSurface7 *iface, IDirectDrawPalette *palette) 4941 { 4942 struct ddraw_surface *surface = impl_from_IDirectDrawSurface7(iface); 4943 4944 TRACE("iface %p, palette %p.\n", iface, palette); 4945 4946 if (surface->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_MIPMAPSUBLEVEL) 4947 return DDERR_NOTONMIPMAPSUBLEVEL; 4948 if (IDirectDrawSurface7_IsLost(iface) == DDERR_SURFACELOST) 4949 { 4950 WARN("Surface lost, returning DDERR_SURFACELOST.\n"); 4951 return DDERR_SURFACELOST; 4952 } 4953 4954 return ddraw_surface_set_palette(surface, palette); 4955 } 4956 4957 static HRESULT WINAPI ddraw_surface4_SetPalette(IDirectDrawSurface4 *iface, IDirectDrawPalette *palette) 4958 { 4959 struct ddraw_surface *surface = impl_from_IDirectDrawSurface4(iface); 4960 4961 TRACE("iface %p, palette %p.\n", iface, palette); 4962 4963 if (IDirectDrawSurface4_IsLost(iface) == DDERR_SURFACELOST) 4964 { 4965 WARN("Surface lost, returning DDERR_SURFACELOST.\n"); 4966 return DDERR_SURFACELOST; 4967 } 4968 4969 return ddraw_surface_set_palette(surface, palette); 4970 } 4971 4972 static HRESULT WINAPI ddraw_surface3_SetPalette(IDirectDrawSurface3 *iface, IDirectDrawPalette *palette) 4973 { 4974 struct ddraw_surface *surface = impl_from_IDirectDrawSurface3(iface); 4975 4976 TRACE("iface %p, palette %p.\n", iface, palette); 4977 4978 if (IDirectDrawSurface3_IsLost(iface) == DDERR_SURFACELOST) 4979 { 4980 WARN("Surface lost, returning DDERR_SURFACELOST.\n"); 4981 return DDERR_SURFACELOST; 4982 } 4983 4984 return ddraw_surface_set_palette(surface, palette); 4985 } 4986 4987 static HRESULT WINAPI ddraw_surface2_SetPalette(IDirectDrawSurface2 *iface, IDirectDrawPalette *palette) 4988 { 4989 struct ddraw_surface *surface = impl_from_IDirectDrawSurface2(iface); 4990 4991 TRACE("iface %p, palette %p.\n", iface, palette); 4992 4993 if (IDirectDrawSurface2_IsLost(iface) == DDERR_SURFACELOST) 4994 { 4995 WARN("Surface lost, returning DDERR_SURFACELOST.\n"); 4996 return DDERR_SURFACELOST; 4997 } 4998 4999 return ddraw_surface_set_palette(surface, palette); 5000 } 5001 5002 static HRESULT WINAPI ddraw_surface1_SetPalette(IDirectDrawSurface *iface, IDirectDrawPalette *palette) 5003 { 5004 struct ddraw_surface *surface = impl_from_IDirectDrawSurface(iface); 5005 5006 TRACE("iface %p, palette %p.\n", iface, palette); 5007 5008 if (IDirectDrawSurface_IsLost(iface) == DDERR_SURFACELOST) 5009 { 5010 WARN("Surface lost, returning DDERR_SURFACELOST.\n"); 5011 return DDERR_SURFACELOST; 5012 } 5013 5014 return ddraw_surface_set_palette(surface, palette); 5015 } 5016 5017 /********************************************************** 5018 * IDirectDrawGammaControl::GetGammaRamp 5019 * 5020 * Returns the current gamma ramp for a surface 5021 * 5022 * Params: 5023 * flags: Ignored 5024 * gamma_ramp: Address to write the ramp to 5025 * 5026 * Returns: 5027 * DD_OK on success 5028 * DDERR_INVALIDPARAMS if gamma_ramp is NULL 5029 * 5030 **********************************************************/ 5031 static HRESULT WINAPI ddraw_gamma_control_GetGammaRamp(IDirectDrawGammaControl *iface, 5032 DWORD flags, DDGAMMARAMP *gamma_ramp) 5033 { 5034 struct ddraw_surface *surface = impl_from_IDirectDrawGammaControl(iface); 5035 5036 TRACE("iface %p, flags %#x, gamma_ramp %p.\n", iface, flags, gamma_ramp); 5037 5038 if (!gamma_ramp) 5039 { 5040 WARN("Invalid gamma_ramp passed.\n"); 5041 return DDERR_INVALIDPARAMS; 5042 } 5043 5044 wined3d_mutex_lock(); 5045 if (surface->surface_desc.ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE) 5046 { 5047 /* Note: DDGAMMARAMP is compatible with struct wined3d_gamma_ramp. */ 5048 wined3d_device_get_gamma_ramp(surface->ddraw->wined3d_device, 0, (struct wined3d_gamma_ramp *)gamma_ramp); 5049 } 5050 else 5051 { 5052 ERR("Not implemented for non-primary surfaces.\n"); 5053 } 5054 wined3d_mutex_unlock(); 5055 5056 return DD_OK; 5057 } 5058 5059 /********************************************************** 5060 * IDirectDrawGammaControl::SetGammaRamp 5061 * 5062 * Sets the red, green and blue gamma ramps for 5063 * 5064 * Params: 5065 * flags: Can be DDSGR_CALIBRATE to request calibration 5066 * gamma_ramp: Structure containing the new gamma ramp 5067 * 5068 * Returns: 5069 * DD_OK on success 5070 * DDERR_INVALIDPARAMS if gamma_ramp is NULL 5071 * 5072 **********************************************************/ 5073 static HRESULT WINAPI ddraw_gamma_control_SetGammaRamp(IDirectDrawGammaControl *iface, 5074 DWORD flags, DDGAMMARAMP *gamma_ramp) 5075 { 5076 struct ddraw_surface *surface = impl_from_IDirectDrawGammaControl(iface); 5077 5078 TRACE("iface %p, flags %#x, gamma_ramp %p.\n", iface, flags, gamma_ramp); 5079 5080 if (!gamma_ramp) 5081 { 5082 WARN("Invalid gamma_ramp passed.\n"); 5083 return DDERR_INVALIDPARAMS; 5084 } 5085 5086 wined3d_mutex_lock(); 5087 if (surface->surface_desc.ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE) 5088 { 5089 /* Note: DDGAMMARAMP is compatible with struct wined3d_gamma_ramp. */ 5090 wined3d_device_set_gamma_ramp(surface->ddraw->wined3d_device, 5091 0, flags, (struct wined3d_gamma_ramp *)gamma_ramp); 5092 } 5093 else 5094 { 5095 ERR("Not implemented for non-primary surfaces.\n"); 5096 } 5097 wined3d_mutex_unlock(); 5098 5099 return DD_OK; 5100 } 5101 5102 /***************************************************************************** 5103 * IDirect3DTexture2::PaletteChanged 5104 * 5105 * Informs the texture about a palette change 5106 * 5107 * Params: 5108 * start: Start index of the change 5109 * count: The number of changed entries 5110 * 5111 * Returns 5112 * D3D_OK, because it's a stub 5113 * 5114 *****************************************************************************/ 5115 static HRESULT WINAPI d3d_texture2_PaletteChanged(IDirect3DTexture2 *iface, DWORD start, DWORD count) 5116 { 5117 FIXME("iface %p, start %u, count %u stub!\n", iface, start, count); 5118 5119 return D3D_OK; 5120 } 5121 5122 static HRESULT WINAPI d3d_texture1_PaletteChanged(IDirect3DTexture *iface, DWORD start, DWORD count) 5123 { 5124 struct ddraw_surface *surface = impl_from_IDirect3DTexture(iface); 5125 5126 TRACE("iface %p, start %u, count %u.\n", iface, start, count); 5127 5128 return d3d_texture2_PaletteChanged(&surface->IDirect3DTexture2_iface, start, count); 5129 } 5130 5131 /***************************************************************************** 5132 * IDirect3DTexture::Unload 5133 * 5134 * DX5 SDK: "The IDirect3DTexture2::Unload method is not implemented 5135 * 5136 * 5137 * Returns: 5138 * DDERR_UNSUPPORTED 5139 * 5140 *****************************************************************************/ 5141 static HRESULT WINAPI d3d_texture1_Unload(IDirect3DTexture *iface) 5142 { 5143 WARN("iface %p. Not implemented.\n", iface); 5144 5145 return DDERR_UNSUPPORTED; 5146 } 5147 5148 /***************************************************************************** 5149 * IDirect3DTexture2::GetHandle 5150 * 5151 * Returns handle for the texture. 5152 * 5153 * Params: 5154 * device: Device this handle is assigned to 5155 * handle: Address to store the handle at. 5156 * 5157 * Returns: 5158 * D3D_OK 5159 * 5160 *****************************************************************************/ 5161 static HRESULT WINAPI d3d_texture2_GetHandle(IDirect3DTexture2 *iface, 5162 IDirect3DDevice2 *device, D3DTEXTUREHANDLE *handle) 5163 { 5164 struct ddraw_surface *surface = impl_from_IDirect3DTexture2(iface); 5165 struct d3d_device *device_impl = unsafe_impl_from_IDirect3DDevice2(device); 5166 5167 TRACE("iface %p, device %p, handle %p.\n", iface, device, handle); 5168 5169 wined3d_mutex_lock(); 5170 5171 if (!surface->Handle) 5172 { 5173 DWORD h = ddraw_allocate_handle(&device_impl->handle_table, surface, DDRAW_HANDLE_SURFACE); 5174 if (h == DDRAW_INVALID_HANDLE) 5175 { 5176 ERR("Failed to allocate a texture handle.\n"); 5177 wined3d_mutex_unlock(); 5178 return DDERR_OUTOFMEMORY; 5179 } 5180 5181 surface->Handle = h + 1; 5182 } 5183 5184 TRACE("Returning handle %08x.\n", surface->Handle); 5185 *handle = surface->Handle; 5186 5187 wined3d_mutex_unlock(); 5188 5189 return D3D_OK; 5190 } 5191 5192 static HRESULT WINAPI d3d_texture1_GetHandle(IDirect3DTexture *iface, 5193 IDirect3DDevice *device, D3DTEXTUREHANDLE *handle) 5194 { 5195 struct ddraw_surface *surface = impl_from_IDirect3DTexture(iface); 5196 struct d3d_device *device_impl = unsafe_impl_from_IDirect3DDevice(device); 5197 5198 TRACE("iface %p, device %p, handle %p.\n", iface, device, handle); 5199 5200 return d3d_texture2_GetHandle(&surface->IDirect3DTexture2_iface, 5201 device_impl ? &device_impl->IDirect3DDevice2_iface : NULL, handle); 5202 } 5203 5204 /***************************************************************************** 5205 * get_sub_mimaplevel 5206 * 5207 * Helper function that returns the next mipmap level 5208 * 5209 * tex_ptr: Surface of which to return the next level 5210 * 5211 *****************************************************************************/ 5212 static struct ddraw_surface *get_sub_mimaplevel(struct ddraw_surface *surface) 5213 { 5214 /* Now go down the mipmap chain to the next surface */ 5215 static DDSCAPS2 mipmap_caps = { DDSCAPS_MIPMAP | DDSCAPS_TEXTURE, 0, 0, {0} }; 5216 IDirectDrawSurface7 *next_level; 5217 HRESULT hr; 5218 5219 hr = ddraw_surface7_GetAttachedSurface(&surface->IDirectDrawSurface7_iface, &mipmap_caps, &next_level); 5220 if (FAILED(hr)) return NULL; 5221 5222 ddraw_surface7_Release(next_level); 5223 5224 return impl_from_IDirectDrawSurface7(next_level); 5225 } 5226 5227 static BOOL compare_format(DDPIXELFORMAT *format1, DDPIXELFORMAT *format2) 5228 { 5229 if ((format1->dwFlags & (DDPF_RGB|DDPF_YUV|DDPF_FOURCC)) != 5230 (format2->dwFlags & (DDPF_RGB|DDPF_YUV|DDPF_FOURCC))) 5231 return FALSE; 5232 5233 if (format1->dwFlags & (DDPF_RGB|DDPF_YUV)) 5234 { 5235 if (!(format1->dwFlags & DDPF_ALPHA)) 5236 { 5237 /* The RGB and YUV bits are stored in the same fields */ 5238 if (format1->u1.dwRGBBitCount != format2->u1.dwRGBBitCount) 5239 return FALSE; 5240 5241 if (format1->u2.dwRBitMask != format2->u2.dwRBitMask) 5242 return FALSE; 5243 5244 if (format1->u3.dwGBitMask != format2->u3.dwGBitMask) 5245 return FALSE; 5246 5247 if (format1->u4.dwBBitMask != format2->u4.dwBBitMask) 5248 return FALSE; 5249 } 5250 5251 if (format1->dwFlags & (DDPF_ALPHAPIXELS | DDPF_ALPHA)) 5252 { 5253 if (format1->u5.dwRGBAlphaBitMask != format2->u5.dwRGBAlphaBitMask) 5254 return FALSE; 5255 } 5256 } 5257 5258 if (format1->dwFlags & DDPF_FOURCC) 5259 { 5260 if (format1->dwFourCC != format2->dwFourCC) 5261 return FALSE; 5262 } 5263 5264 return TRUE; 5265 } 5266 5267 /***************************************************************************** 5268 * IDirect3DTexture2::Load 5269 * 5270 * Loads a texture created with the DDSCAPS_ALLOCONLOAD 5271 * 5272 * This function isn't relayed to WineD3D because the whole interface is 5273 * implemented in DDraw only. For speed improvements an implementation which 5274 * takes OpenGL more into account could be placed into WineD3D. 5275 * 5276 * Params: 5277 * src_texture: Address of the texture to load 5278 * 5279 * Returns: 5280 * D3D_OK on success 5281 * D3DERR_TEXTURE_LOAD_FAILED. 5282 * 5283 *****************************************************************************/ 5284 static HRESULT WINAPI d3d_texture2_Load(IDirect3DTexture2 *iface, IDirect3DTexture2 *src_texture) 5285 { 5286 struct ddraw_surface *dst_surface = impl_from_IDirect3DTexture2(iface); 5287 struct ddraw_surface *src_surface = unsafe_impl_from_IDirect3DTexture2(src_texture); 5288 RECT src_rect, dst_rect; 5289 HRESULT hr; 5290 5291 TRACE("iface %p, src_texture %p.\n", iface, src_texture); 5292 5293 if (src_surface == dst_surface) 5294 { 5295 TRACE("copying surface %p to surface %p, why?\n", src_surface, dst_surface); 5296 return D3D_OK; 5297 } 5298 5299 wined3d_mutex_lock(); 5300 5301 for (;;) 5302 { 5303 DDSURFACEDESC *src_desc = (DDSURFACEDESC *)&src_surface->surface_desc; 5304 5305 TRACE("Copying surface %p to surface %p.\n", src_surface, dst_surface); 5306 5307 if (compare_format(&src_surface->surface_desc.u4.ddpfPixelFormat, 5308 &dst_surface->surface_desc.u4.ddpfPixelFormat)) 5309 { 5310 struct ddraw_palette *dst_pal, *src_pal; 5311 5312 /* Get the palettes */ 5313 dst_pal = dst_surface->palette; 5314 src_pal = src_surface->palette; 5315 5316 if (src_pal) 5317 { 5318 PALETTEENTRY palent[256]; 5319 5320 if (!dst_pal) 5321 { 5322 wined3d_mutex_unlock(); 5323 return DDERR_NOPALETTEATTACHED; 5324 } 5325 IDirectDrawPalette_GetEntries(&src_pal->IDirectDrawPalette_iface, 0, 0, 256, palent); 5326 IDirectDrawPalette_SetEntries(&dst_pal->IDirectDrawPalette_iface, 0, 0, 256, palent); 5327 } 5328 5329 if (src_desc->dwFlags & DDSD_CKSRCBLT) 5330 { 5331 IDirectDrawSurface7_SetColorKey(&dst_surface->IDirectDrawSurface7_iface, 5332 DDCKEY_SRCBLT, &src_desc->ddckCKSrcBlt); 5333 } 5334 } 5335 else 5336 { 5337 if (src_desc->dwFlags & DDSD_CKSRCBLT) 5338 return E_FAIL; 5339 } 5340 5341 /* Suppress the ALLOCONLOAD flag */ 5342 dst_surface->surface_desc.ddsCaps.dwCaps &= ~DDSCAPS_ALLOCONLOAD; 5343 5344 SetRect(&src_rect, 0, 0, src_surface->surface_desc.dwWidth, src_surface->surface_desc.dwHeight); 5345 SetRect(&dst_rect, 0, 0, dst_surface->surface_desc.dwWidth, dst_surface->surface_desc.dwHeight); 5346 5347 hr = wined3d_texture_blt(dst_surface->wined3d_texture, dst_surface->sub_resource_idx, &dst_rect, 5348 src_surface->wined3d_texture, src_surface->sub_resource_idx, &src_rect, 5349 0, NULL, WINED3D_TEXF_LINEAR); 5350 if (FAILED(hr)) 5351 { 5352 ERR("Failed to blit surface, hr %#x.\n", hr); 5353 wined3d_mutex_unlock(); 5354 return hr; 5355 } 5356 5357 if (src_surface->surface_desc.ddsCaps.dwCaps & DDSCAPS_MIPMAP) 5358 src_surface = get_sub_mimaplevel(src_surface); 5359 else 5360 src_surface = NULL; 5361 5362 if (dst_surface->surface_desc.ddsCaps.dwCaps & DDSCAPS_MIPMAP) 5363 dst_surface = get_sub_mimaplevel(dst_surface); 5364 else 5365 dst_surface = NULL; 5366 5367 if (src_surface && !dst_surface) 5368 return DDERR_NOTFOUND; 5369 5370 if (!src_surface || !dst_surface) 5371 break; 5372 } 5373 5374 wined3d_mutex_unlock(); 5375 5376 return hr; 5377 } 5378 5379 static HRESULT WINAPI d3d_texture1_Load(IDirect3DTexture *iface, IDirect3DTexture *src_texture) 5380 { 5381 struct ddraw_surface *dst_surface = impl_from_IDirect3DTexture(iface); 5382 struct ddraw_surface *src_surface = unsafe_impl_from_IDirect3DTexture(src_texture); 5383 5384 TRACE("iface %p, src_texture %p.\n", iface, src_texture); 5385 5386 return d3d_texture2_Load(&dst_surface->IDirect3DTexture2_iface, 5387 src_surface ? &src_surface->IDirect3DTexture2_iface : NULL); 5388 } 5389 5390 /***************************************************************************** 5391 * The VTable 5392 *****************************************************************************/ 5393 5394 static const struct IDirectDrawSurface7Vtbl ddraw_surface7_vtbl = 5395 { 5396 /* IUnknown */ 5397 ddraw_surface7_QueryInterface, 5398 ddraw_surface7_AddRef, 5399 ddraw_surface7_Release, 5400 /* IDirectDrawSurface */ 5401 ddraw_surface7_AddAttachedSurface, 5402 ddraw_surface7_AddOverlayDirtyRect, 5403 ddraw_surface7_Blt, 5404 ddraw_surface7_BltBatch, 5405 ddraw_surface7_BltFast, 5406 ddraw_surface7_DeleteAttachedSurface, 5407 ddraw_surface7_EnumAttachedSurfaces, 5408 ddraw_surface7_EnumOverlayZOrders, 5409 ddraw_surface7_Flip, 5410 ddraw_surface7_GetAttachedSurface, 5411 ddraw_surface7_GetBltStatus, 5412 ddraw_surface7_GetCaps, 5413 ddraw_surface7_GetClipper, 5414 ddraw_surface7_GetColorKey, 5415 ddraw_surface7_GetDC, 5416 ddraw_surface7_GetFlipStatus, 5417 ddraw_surface7_GetOverlayPosition, 5418 ddraw_surface7_GetPalette, 5419 ddraw_surface7_GetPixelFormat, 5420 ddraw_surface7_GetSurfaceDesc, 5421 ddraw_surface7_Initialize, 5422 ddraw_surface7_IsLost, 5423 ddraw_surface7_Lock, 5424 ddraw_surface7_ReleaseDC, 5425 ddraw_surface7_Restore, 5426 ddraw_surface7_SetClipper, 5427 ddraw_surface7_SetColorKey, 5428 ddraw_surface7_SetOverlayPosition, 5429 ddraw_surface7_SetPalette, 5430 ddraw_surface7_Unlock, 5431 ddraw_surface7_UpdateOverlay, 5432 ddraw_surface7_UpdateOverlayDisplay, 5433 ddraw_surface7_UpdateOverlayZOrder, 5434 /* IDirectDrawSurface2 */ 5435 ddraw_surface7_GetDDInterface, 5436 ddraw_surface7_PageLock, 5437 ddraw_surface7_PageUnlock, 5438 /* IDirectDrawSurface3 */ 5439 ddraw_surface7_SetSurfaceDesc, 5440 /* IDirectDrawSurface4 */ 5441 ddraw_surface7_SetPrivateData, 5442 ddraw_surface7_GetPrivateData, 5443 ddraw_surface7_FreePrivateData, 5444 ddraw_surface7_GetUniquenessValue, 5445 ddraw_surface7_ChangeUniquenessValue, 5446 /* IDirectDrawSurface7 */ 5447 ddraw_surface7_SetPriority, 5448 ddraw_surface7_GetPriority, 5449 ddraw_surface7_SetLOD, 5450 ddraw_surface7_GetLOD, 5451 }; 5452 5453 static const struct IDirectDrawSurface4Vtbl ddraw_surface4_vtbl = 5454 { 5455 /* IUnknown */ 5456 ddraw_surface4_QueryInterface, 5457 ddraw_surface4_AddRef, 5458 ddraw_surface4_Release, 5459 /* IDirectDrawSurface */ 5460 ddraw_surface4_AddAttachedSurface, 5461 ddraw_surface4_AddOverlayDirtyRect, 5462 ddraw_surface4_Blt, 5463 ddraw_surface4_BltBatch, 5464 ddraw_surface4_BltFast, 5465 ddraw_surface4_DeleteAttachedSurface, 5466 ddraw_surface4_EnumAttachedSurfaces, 5467 ddraw_surface4_EnumOverlayZOrders, 5468 ddraw_surface4_Flip, 5469 ddraw_surface4_GetAttachedSurface, 5470 ddraw_surface4_GetBltStatus, 5471 ddraw_surface4_GetCaps, 5472 ddraw_surface4_GetClipper, 5473 ddraw_surface4_GetColorKey, 5474 ddraw_surface4_GetDC, 5475 ddraw_surface4_GetFlipStatus, 5476 ddraw_surface4_GetOverlayPosition, 5477 ddraw_surface4_GetPalette, 5478 ddraw_surface4_GetPixelFormat, 5479 ddraw_surface4_GetSurfaceDesc, 5480 ddraw_surface4_Initialize, 5481 ddraw_surface4_IsLost, 5482 ddraw_surface4_Lock, 5483 ddraw_surface4_ReleaseDC, 5484 ddraw_surface4_Restore, 5485 ddraw_surface4_SetClipper, 5486 ddraw_surface4_SetColorKey, 5487 ddraw_surface4_SetOverlayPosition, 5488 ddraw_surface4_SetPalette, 5489 ddraw_surface4_Unlock, 5490 ddraw_surface4_UpdateOverlay, 5491 ddraw_surface4_UpdateOverlayDisplay, 5492 ddraw_surface4_UpdateOverlayZOrder, 5493 /* IDirectDrawSurface2 */ 5494 ddraw_surface4_GetDDInterface, 5495 ddraw_surface4_PageLock, 5496 ddraw_surface4_PageUnlock, 5497 /* IDirectDrawSurface3 */ 5498 ddraw_surface4_SetSurfaceDesc, 5499 /* IDirectDrawSurface4 */ 5500 ddraw_surface4_SetPrivateData, 5501 ddraw_surface4_GetPrivateData, 5502 ddraw_surface4_FreePrivateData, 5503 ddraw_surface4_GetUniquenessValue, 5504 ddraw_surface4_ChangeUniquenessValue, 5505 }; 5506 5507 static const struct IDirectDrawSurface3Vtbl ddraw_surface3_vtbl = 5508 { 5509 /* IUnknown */ 5510 ddraw_surface3_QueryInterface, 5511 ddraw_surface3_AddRef, 5512 ddraw_surface3_Release, 5513 /* IDirectDrawSurface */ 5514 ddraw_surface3_AddAttachedSurface, 5515 ddraw_surface3_AddOverlayDirtyRect, 5516 ddraw_surface3_Blt, 5517 ddraw_surface3_BltBatch, 5518 ddraw_surface3_BltFast, 5519 ddraw_surface3_DeleteAttachedSurface, 5520 ddraw_surface3_EnumAttachedSurfaces, 5521 ddraw_surface3_EnumOverlayZOrders, 5522 ddraw_surface3_Flip, 5523 ddraw_surface3_GetAttachedSurface, 5524 ddraw_surface3_GetBltStatus, 5525 ddraw_surface3_GetCaps, 5526 ddraw_surface3_GetClipper, 5527 ddraw_surface3_GetColorKey, 5528 ddraw_surface3_GetDC, 5529 ddraw_surface3_GetFlipStatus, 5530 ddraw_surface3_GetOverlayPosition, 5531 ddraw_surface3_GetPalette, 5532 ddraw_surface3_GetPixelFormat, 5533 ddraw_surface3_GetSurfaceDesc, 5534 ddraw_surface3_Initialize, 5535 ddraw_surface3_IsLost, 5536 ddraw_surface3_Lock, 5537 ddraw_surface3_ReleaseDC, 5538 ddraw_surface3_Restore, 5539 ddraw_surface3_SetClipper, 5540 ddraw_surface3_SetColorKey, 5541 ddraw_surface3_SetOverlayPosition, 5542 ddraw_surface3_SetPalette, 5543 ddraw_surface3_Unlock, 5544 ddraw_surface3_UpdateOverlay, 5545 ddraw_surface3_UpdateOverlayDisplay, 5546 ddraw_surface3_UpdateOverlayZOrder, 5547 /* IDirectDrawSurface2 */ 5548 ddraw_surface3_GetDDInterface, 5549 ddraw_surface3_PageLock, 5550 ddraw_surface3_PageUnlock, 5551 /* IDirectDrawSurface3 */ 5552 ddraw_surface3_SetSurfaceDesc, 5553 }; 5554 5555 static const struct IDirectDrawSurface2Vtbl ddraw_surface2_vtbl = 5556 { 5557 /* IUnknown */ 5558 ddraw_surface2_QueryInterface, 5559 ddraw_surface2_AddRef, 5560 ddraw_surface2_Release, 5561 /* IDirectDrawSurface */ 5562 ddraw_surface2_AddAttachedSurface, 5563 ddraw_surface2_AddOverlayDirtyRect, 5564 ddraw_surface2_Blt, 5565 ddraw_surface2_BltBatch, 5566 ddraw_surface2_BltFast, 5567 ddraw_surface2_DeleteAttachedSurface, 5568 ddraw_surface2_EnumAttachedSurfaces, 5569 ddraw_surface2_EnumOverlayZOrders, 5570 ddraw_surface2_Flip, 5571 ddraw_surface2_GetAttachedSurface, 5572 ddraw_surface2_GetBltStatus, 5573 ddraw_surface2_GetCaps, 5574 ddraw_surface2_GetClipper, 5575 ddraw_surface2_GetColorKey, 5576 ddraw_surface2_GetDC, 5577 ddraw_surface2_GetFlipStatus, 5578 ddraw_surface2_GetOverlayPosition, 5579 ddraw_surface2_GetPalette, 5580 ddraw_surface2_GetPixelFormat, 5581 ddraw_surface2_GetSurfaceDesc, 5582 ddraw_surface2_Initialize, 5583 ddraw_surface2_IsLost, 5584 ddraw_surface2_Lock, 5585 ddraw_surface2_ReleaseDC, 5586 ddraw_surface2_Restore, 5587 ddraw_surface2_SetClipper, 5588 ddraw_surface2_SetColorKey, 5589 ddraw_surface2_SetOverlayPosition, 5590 ddraw_surface2_SetPalette, 5591 ddraw_surface2_Unlock, 5592 ddraw_surface2_UpdateOverlay, 5593 ddraw_surface2_UpdateOverlayDisplay, 5594 ddraw_surface2_UpdateOverlayZOrder, 5595 /* IDirectDrawSurface2 */ 5596 ddraw_surface2_GetDDInterface, 5597 ddraw_surface2_PageLock, 5598 ddraw_surface2_PageUnlock, 5599 }; 5600 5601 static struct IDirectDrawSurfaceVtbl ddraw_surface1_vtbl = 5602 { 5603 /* IUnknown */ 5604 ddraw_surface1_QueryInterface, 5605 ddraw_surface1_AddRef, 5606 ddraw_surface1_Release, 5607 /* IDirectDrawSurface */ 5608 ddraw_surface1_AddAttachedSurface, 5609 ddraw_surface1_AddOverlayDirtyRect, 5610 ddraw_surface1_Blt, 5611 ddraw_surface1_BltBatch, 5612 ddraw_surface1_BltFast, 5613 ddraw_surface1_DeleteAttachedSurface, 5614 ddraw_surface1_EnumAttachedSurfaces, 5615 ddraw_surface1_EnumOverlayZOrders, 5616 ddraw_surface1_Flip, 5617 ddraw_surface1_GetAttachedSurface, 5618 ddraw_surface1_GetBltStatus, 5619 ddraw_surface1_GetCaps, 5620 ddraw_surface1_GetClipper, 5621 ddraw_surface1_GetColorKey, 5622 ddraw_surface1_GetDC, 5623 ddraw_surface1_GetFlipStatus, 5624 ddraw_surface1_GetOverlayPosition, 5625 ddraw_surface1_GetPalette, 5626 ddraw_surface1_GetPixelFormat, 5627 ddraw_surface1_GetSurfaceDesc, 5628 ddraw_surface1_Initialize, 5629 ddraw_surface1_IsLost, 5630 ddraw_surface1_Lock, 5631 ddraw_surface1_ReleaseDC, 5632 ddraw_surface1_Restore, 5633 ddraw_surface1_SetClipper, 5634 ddraw_surface1_SetColorKey, 5635 ddraw_surface1_SetOverlayPosition, 5636 ddraw_surface1_SetPalette, 5637 ddraw_surface1_Unlock, 5638 ddraw_surface1_UpdateOverlay, 5639 ddraw_surface1_UpdateOverlayDisplay, 5640 ddraw_surface1_UpdateOverlayZOrder, 5641 }; 5642 5643 static const struct IDirectDrawGammaControlVtbl ddraw_gamma_control_vtbl = 5644 { 5645 ddraw_gamma_control_QueryInterface, 5646 ddraw_gamma_control_AddRef, 5647 ddraw_gamma_control_Release, 5648 ddraw_gamma_control_GetGammaRamp, 5649 ddraw_gamma_control_SetGammaRamp, 5650 }; 5651 5652 static const struct IDirect3DTexture2Vtbl d3d_texture2_vtbl = 5653 { 5654 d3d_texture2_QueryInterface, 5655 d3d_texture2_AddRef, 5656 d3d_texture2_Release, 5657 d3d_texture2_GetHandle, 5658 d3d_texture2_PaletteChanged, 5659 d3d_texture2_Load, 5660 }; 5661 5662 static const struct IDirect3DTextureVtbl d3d_texture1_vtbl = 5663 { 5664 d3d_texture1_QueryInterface, 5665 d3d_texture1_AddRef, 5666 d3d_texture1_Release, 5667 d3d_texture1_Initialize, 5668 d3d_texture1_GetHandle, 5669 d3d_texture1_PaletteChanged, 5670 d3d_texture1_Load, 5671 d3d_texture1_Unload, 5672 }; 5673 5674 /* Some games (e.g. Tomb Raider 3) pass the wrong version of the 5675 * IDirectDrawSurface interface to ddraw methods. */ 5676 struct ddraw_surface *unsafe_impl_from_IDirectDrawSurface7(IDirectDrawSurface7 *iface) 5677 { 5678 if (!iface) return NULL; 5679 if (iface->lpVtbl != &ddraw_surface7_vtbl) 5680 { 5681 HRESULT hr = IDirectDrawSurface7_QueryInterface(iface, &IID_IDirectDrawSurface7, (void **)&iface); 5682 if (FAILED(hr)) 5683 { 5684 WARN("Object %p doesn't expose interface IDirectDrawSurface7.\n", iface); 5685 return NULL; 5686 } 5687 IDirectDrawSurface7_Release(iface); 5688 } 5689 return CONTAINING_RECORD(iface, struct ddraw_surface, IDirectDrawSurface7_iface); 5690 } 5691 5692 struct ddraw_surface *unsafe_impl_from_IDirectDrawSurface4(IDirectDrawSurface4 *iface) 5693 { 5694 if (!iface) return NULL; 5695 if (iface->lpVtbl != &ddraw_surface4_vtbl) 5696 { 5697 HRESULT hr = IDirectDrawSurface4_QueryInterface(iface, &IID_IDirectDrawSurface4, (void **)&iface); 5698 if (FAILED(hr)) 5699 { 5700 WARN("Object %p doesn't expose interface IDirectDrawSurface4.\n", iface); 5701 return NULL; 5702 } 5703 IDirectDrawSurface4_Release(iface); 5704 } 5705 return CONTAINING_RECORD(iface, struct ddraw_surface, IDirectDrawSurface4_iface); 5706 } 5707 5708 static struct ddraw_surface *unsafe_impl_from_IDirectDrawSurface3(IDirectDrawSurface3 *iface) 5709 { 5710 if (!iface) return NULL; 5711 if (iface->lpVtbl != &ddraw_surface3_vtbl) 5712 { 5713 HRESULT hr = IDirectDrawSurface3_QueryInterface(iface, &IID_IDirectDrawSurface3, (void **)&iface); 5714 if (FAILED(hr)) 5715 { 5716 WARN("Object %p doesn't expose interface IDirectDrawSurface3.\n", iface); 5717 return NULL; 5718 } 5719 IDirectDrawSurface3_Release(iface); 5720 } 5721 return CONTAINING_RECORD(iface, struct ddraw_surface, IDirectDrawSurface3_iface); 5722 } 5723 5724 static struct ddraw_surface *unsafe_impl_from_IDirectDrawSurface2(IDirectDrawSurface2 *iface) 5725 { 5726 if (!iface) return NULL; 5727 if (iface->lpVtbl != &ddraw_surface2_vtbl) 5728 { 5729 HRESULT hr = IDirectDrawSurface2_QueryInterface(iface, &IID_IDirectDrawSurface2, (void **)&iface); 5730 if (FAILED(hr)) 5731 { 5732 WARN("Object %p doesn't expose interface IDirectDrawSurface2.\n", iface); 5733 return NULL; 5734 } 5735 IDirectDrawSurface2_Release(iface); 5736 } 5737 return CONTAINING_RECORD(iface, struct ddraw_surface, IDirectDrawSurface2_iface); 5738 } 5739 5740 struct ddraw_surface *unsafe_impl_from_IDirectDrawSurface(IDirectDrawSurface *iface) 5741 { 5742 if (!iface) return NULL; 5743 if (iface->lpVtbl != &ddraw_surface1_vtbl) 5744 { 5745 HRESULT hr = IDirectDrawSurface_QueryInterface(iface, &IID_IDirectDrawSurface, (void **)&iface); 5746 if (FAILED(hr)) 5747 { 5748 WARN("Object %p doesn't expose interface IDirectDrawSurface.\n", iface); 5749 return NULL; 5750 } 5751 IDirectDrawSurface_Release(iface); 5752 } 5753 return CONTAINING_RECORD(iface, struct ddraw_surface, IDirectDrawSurface_iface); 5754 } 5755 5756 struct ddraw_surface *unsafe_impl_from_IDirect3DTexture2(IDirect3DTexture2 *iface) 5757 { 5758 if (!iface) return NULL; 5759 assert(iface->lpVtbl == &d3d_texture2_vtbl); 5760 return CONTAINING_RECORD(iface, struct ddraw_surface, IDirect3DTexture2_iface); 5761 } 5762 5763 struct ddraw_surface *unsafe_impl_from_IDirect3DTexture(IDirect3DTexture *iface) 5764 { 5765 if (!iface) return NULL; 5766 assert(iface->lpVtbl == &d3d_texture1_vtbl); 5767 return CONTAINING_RECORD(iface, struct ddraw_surface, IDirect3DTexture_iface); 5768 } 5769 5770 static void STDMETHODCALLTYPE ddraw_surface_wined3d_object_destroyed(void *parent) 5771 { 5772 struct ddraw_surface *surface = parent; 5773 5774 TRACE("surface %p.\n", surface); 5775 5776 /* This shouldn't happen, ddraw_surface_release_iface() should prevent the 5777 * surface from being destroyed in this case. */ 5778 if (surface->first_attached != surface) 5779 ERR("Surface is still attached to surface %p.\n", surface->first_attached); 5780 5781 while (surface->next_attached) 5782 if (FAILED(ddraw_surface_delete_attached_surface(surface, 5783 surface->next_attached, surface->next_attached->attached_iface))) 5784 ERR("DeleteAttachedSurface failed.\n"); 5785 5786 /* Having a texture handle set implies that the device still exists. */ 5787 if (surface->Handle) 5788 ddraw_free_handle(&surface->ddraw->d3ddevice->handle_table, surface->Handle - 1, DDRAW_HANDLE_SURFACE); 5789 5790 /* Reduce the ddraw surface count. */ 5791 list_remove(&surface->surface_list_entry); 5792 5793 if (surface->clipper) 5794 IDirectDrawClipper_Release(&surface->clipper->IDirectDrawClipper_iface); 5795 5796 if (surface == surface->ddraw->primary) 5797 surface->ddraw->primary = NULL; 5798 5799 wined3d_private_store_cleanup(&surface->private_store); 5800 5801 heap_free(surface); 5802 } 5803 5804 static const struct wined3d_parent_ops ddraw_surface_wined3d_parent_ops = 5805 { 5806 ddraw_surface_wined3d_object_destroyed, 5807 }; 5808 5809 static void STDMETHODCALLTYPE ddraw_texture_wined3d_object_destroyed(void *parent) 5810 { 5811 TRACE("parent %p.\n", parent); 5812 5813 heap_free(parent); 5814 } 5815 5816 static const struct wined3d_parent_ops ddraw_texture_wined3d_parent_ops = 5817 { 5818 ddraw_texture_wined3d_object_destroyed, 5819 }; 5820 5821 static HRESULT CDECL ddraw_reset_enum_callback(struct wined3d_resource *resource) 5822 { 5823 return DD_OK; 5824 } 5825 5826 HRESULT ddraw_surface_create(struct ddraw *ddraw, const DDSURFACEDESC2 *surface_desc, 5827 struct ddraw_surface **surface, IUnknown *outer_unknown, unsigned int version) 5828 { 5829 struct wined3d_sub_resource_desc wined3d_mip_desc; 5830 struct ddraw_surface *root, *mip, **attach; 5831 struct wined3d_resource_desc wined3d_desc; 5832 struct wined3d_texture *wined3d_texture; 5833 struct wined3d_display_mode mode; 5834 DDSURFACEDESC2 *desc, *mip_desc; 5835 struct ddraw_texture *texture; 5836 unsigned int layers = 1; 5837 unsigned int pitch = 0; 5838 UINT levels, i, j; 5839 HRESULT hr; 5840 5841 TRACE("ddraw %p, surface_desc %p, surface %p, outer_unknown %p, version %u.\n", 5842 ddraw, surface_desc, surface, outer_unknown, version); 5843 if (TRACE_ON(ddraw)) 5844 { 5845 TRACE("Requesting surface desc:\n"); 5846 DDRAW_dump_surface_desc(surface_desc); 5847 } 5848 5849 if (outer_unknown) 5850 return CLASS_E_NOAGGREGATION; 5851 5852 if (!surface) 5853 return E_POINTER; 5854 5855 if (!(texture = heap_alloc(sizeof(*texture)))) 5856 return E_OUTOFMEMORY; 5857 5858 texture->version = version; 5859 texture->surface_desc = *surface_desc; 5860 desc = &texture->surface_desc; 5861 5862 /* Ensure DDSD_CAPS is always set. */ 5863 desc->dwFlags |= DDSD_CAPS; 5864 5865 if (desc->ddsCaps.dwCaps & DDSCAPS_FLIP) 5866 { 5867 if (!(desc->dwFlags & DDSD_BACKBUFFERCOUNT) || !desc->u5.dwBackBufferCount) 5868 { 5869 WARN("Tried to create a flippable surface without any back buffers.\n"); 5870 heap_free(texture); 5871 return DDERR_INVALIDCAPS; 5872 } 5873 5874 if (!(desc->ddsCaps.dwCaps & DDSCAPS_COMPLEX)) 5875 { 5876 WARN("Tried to create a flippable surface without DDSCAPS_COMPLEX.\n"); 5877 heap_free(texture); 5878 return DDERR_INVALIDCAPS; 5879 } 5880 5881 if (desc->ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP) 5882 { 5883 WARN("Tried to create a flippable cubemap.\n"); 5884 heap_free(texture); 5885 return DDERR_INVALIDPARAMS; 5886 } 5887 5888 if (desc->ddsCaps.dwCaps & DDSCAPS_TEXTURE) 5889 { 5890 FIXME("Flippable textures not implemented.\n"); 5891 heap_free(texture); 5892 return DDERR_INVALIDCAPS; 5893 } 5894 } 5895 else 5896 { 5897 if (desc->dwFlags & DDSD_BACKBUFFERCOUNT) 5898 { 5899 WARN("Tried to specify a back buffer count for a non-flippable surface.\n"); 5900 hr = desc->ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP ? DDERR_INVALIDPARAMS : DDERR_INVALIDCAPS; 5901 heap_free(texture); 5902 return hr; 5903 } 5904 } 5905 5906 if (desc->ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE) 5907 { 5908 if (desc->ddsCaps.dwCaps & DDSCAPS_TEXTURE) 5909 { 5910 WARN("Tried to create a primary surface with DDSCAPS_TEXTURE.\n"); 5911 heap_free(texture); 5912 return DDERR_INVALIDCAPS; 5913 } 5914 5915 if ((desc->ddsCaps.dwCaps & DDSCAPS_COMPLEX) && !(desc->ddsCaps.dwCaps & DDSCAPS_FLIP)) 5916 { 5917 WARN("Tried to create a flippable primary surface without both DDSCAPS_FLIP and DDSCAPS_COMPLEX.\n"); 5918 heap_free(texture); 5919 return DDERR_INVALIDCAPS; 5920 } 5921 5922 if ((desc->ddsCaps.dwCaps & DDSCAPS_FLIP) && !(ddraw->cooperative_level & DDSCL_EXCLUSIVE)) 5923 { 5924 WARN("Tried to create a flippable primary surface without DDSCL_EXCLUSIVE.\n"); 5925 heap_free(texture); 5926 return DDERR_NOEXCLUSIVEMODE; 5927 } 5928 } 5929 5930 /* This is a special case in ddrawex, but not allowed in ddraw. */ 5931 if ((desc->ddsCaps.dwCaps & (DDSCAPS_VIDEOMEMORY | DDSCAPS_SYSTEMMEMORY)) 5932 == (DDSCAPS_VIDEOMEMORY | DDSCAPS_SYSTEMMEMORY)) 5933 { 5934 WARN("Tried to create a surface in both system and video memory.\n"); 5935 heap_free(texture); 5936 return DDERR_INVALIDCAPS; 5937 } 5938 5939 if ((desc->ddsCaps.dwCaps & (DDSCAPS_ALLOCONLOAD | DDSCAPS_MIPMAP)) 5940 && !(desc->ddsCaps.dwCaps & DDSCAPS_TEXTURE)) 5941 { 5942 WARN("Caps %#x require DDSCAPS_TEXTURE.\n", desc->ddsCaps.dwCaps); 5943 heap_free(texture); 5944 return DDERR_INVALIDCAPS; 5945 } 5946 5947 if ((desc->ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP_ALLFACES) 5948 && !(desc->ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP)) 5949 { 5950 WARN("Cube map faces requested without cube map flag.\n"); 5951 heap_free(texture); 5952 return DDERR_INVALIDCAPS; 5953 } 5954 5955 if ((desc->ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP) 5956 && !(desc->ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP_ALLFACES)) 5957 { 5958 WARN("Cube map without faces requested.\n"); 5959 heap_free(texture); 5960 return DDERR_INVALIDPARAMS; 5961 } 5962 5963 if ((desc->ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP) 5964 && (desc->ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP_ALLFACES) != DDSCAPS2_CUBEMAP_ALLFACES) 5965 FIXME("Partial cube maps not implemented.\n"); 5966 5967 if (desc->ddsCaps.dwCaps2 & (DDSCAPS2_TEXTUREMANAGE | DDSCAPS2_D3DTEXTUREMANAGE)) 5968 { 5969 if (!(desc->ddsCaps.dwCaps & DDSCAPS_TEXTURE)) 5970 { 5971 WARN("DDSCAPS2_TEXTUREMANAGE used without DDSCAPS_TEXTURE, returning DDERR_INVALIDCAPS.\n"); 5972 heap_free(texture); 5973 return DDERR_INVALIDCAPS; 5974 } 5975 if (desc->ddsCaps.dwCaps & (DDSCAPS_VIDEOMEMORY | DDSCAPS_SYSTEMMEMORY)) 5976 { 5977 WARN("DDSCAPS2_TEXTUREMANAGE used width DDSCAPS_VIDEOMEMORY " 5978 "or DDSCAPS_SYSTEMMEMORY, returning DDERR_INVALIDCAPS.\n"); 5979 heap_free(texture); 5980 return DDERR_INVALIDCAPS; 5981 } 5982 } 5983 5984 if (FAILED(hr = wined3d_get_adapter_display_mode(ddraw->wined3d, WINED3DADAPTER_DEFAULT, &mode, NULL))) 5985 { 5986 ERR("Failed to get display mode, hr %#x.\n", hr); 5987 heap_free(texture); 5988 return hr_ddraw_from_wined3d(hr); 5989 } 5990 5991 /* No pixelformat given? Use the current screen format. */ 5992 if (!(desc->dwFlags & DDSD_PIXELFORMAT)) 5993 { 5994 desc->dwFlags |= DDSD_PIXELFORMAT; 5995 desc->u4.ddpfPixelFormat.dwSize = sizeof(desc->u4.ddpfPixelFormat); 5996 ddrawformat_from_wined3dformat(&desc->u4.ddpfPixelFormat, mode.format_id); 5997 } 5998 5999 wined3d_desc.resource_type = WINED3D_RTYPE_TEXTURE_2D; 6000 wined3d_desc.format = wined3dformat_from_ddrawformat(&desc->u4.ddpfPixelFormat); 6001 if (wined3d_desc.format == WINED3DFMT_UNKNOWN) 6002 { 6003 WARN("Unsupported / unknown pixelformat.\n"); 6004 heap_free(texture); 6005 return DDERR_INVALIDPIXELFORMAT; 6006 } 6007 6008 /* No width or no height? Use the screen size. */ 6009 if (!(desc->dwFlags & DDSD_WIDTH) || !(desc->dwFlags & DDSD_HEIGHT)) 6010 { 6011 if (!(desc->ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE)) 6012 { 6013 WARN("No width / height specified.\n"); 6014 heap_free(texture); 6015 return DDERR_INVALIDPARAMS; 6016 } 6017 6018 desc->dwFlags |= DDSD_WIDTH | DDSD_HEIGHT; 6019 desc->dwWidth = mode.width; 6020 desc->dwHeight = mode.height; 6021 } 6022 6023 if (!desc->dwWidth || !desc->dwHeight) 6024 { 6025 heap_free(texture); 6026 return DDERR_INVALIDPARAMS; 6027 } 6028 6029 if (desc->ddsCaps.dwCaps & DDSCAPS_FLIP) 6030 desc->ddsCaps.dwCaps |= DDSCAPS_FRONTBUFFER; 6031 6032 if (desc->ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE) 6033 { 6034 /* The first surface is a front buffer, the back buffers are created 6035 * afterwards. */ 6036 desc->ddsCaps.dwCaps |= DDSCAPS_VISIBLE; 6037 if (ddraw->cooperative_level & DDSCL_EXCLUSIVE) 6038 { 6039 struct wined3d_swapchain_desc swapchain_desc; 6040 6041 wined3d_swapchain_get_desc(ddraw->wined3d_swapchain, &swapchain_desc); 6042 swapchain_desc.backbuffer_width = mode.width; 6043 swapchain_desc.backbuffer_height = mode.height; 6044 swapchain_desc.backbuffer_format = mode.format_id; 6045 6046 if (FAILED(hr = wined3d_device_reset(ddraw->wined3d_device, 6047 &swapchain_desc, NULL, ddraw_reset_enum_callback, TRUE))) 6048 { 6049 ERR("Failed to reset device.\n"); 6050 heap_free(texture); 6051 return hr_ddraw_from_wined3d(hr); 6052 } 6053 6054 wined3d_device_set_render_state(ddraw->wined3d_device, WINED3D_RS_ZENABLE, 6055 !!swapchain_desc.enable_auto_depth_stencil); 6056 } 6057 } 6058 6059 wined3d_desc.multisample_type = WINED3D_MULTISAMPLE_NONE; 6060 wined3d_desc.multisample_quality = 0; 6061 wined3d_desc.usage = 0; 6062 wined3d_desc.access = WINED3D_RESOURCE_ACCESS_GPU | WINED3D_RESOURCE_ACCESS_MAP_R | WINED3D_RESOURCE_ACCESS_MAP_W; 6063 wined3d_desc.width = desc->dwWidth; 6064 wined3d_desc.height = desc->dwHeight; 6065 wined3d_desc.depth = 1; 6066 wined3d_desc.size = 0; 6067 6068 if ((desc->ddsCaps.dwCaps & DDSCAPS_3DDEVICE) && (ddraw->flags & DDRAW_NO3D)) 6069 { 6070 WARN("The application requests a 3D capable surface, but the ddraw object was created without 3D support.\n"); 6071 /* Do not fail surface creation, only fail 3D device creation. */ 6072 } 6073 6074 /* Mipmap count fixes */ 6075 if (desc->ddsCaps.dwCaps & DDSCAPS_MIPMAP) 6076 { 6077 if (desc->ddsCaps.dwCaps & DDSCAPS_COMPLEX) 6078 { 6079 if (desc->dwFlags & DDSD_MIPMAPCOUNT) 6080 { 6081 /* Mipmap count is given, should not be 0. */ 6082 if (!desc->u2.dwMipMapCount) 6083 { 6084 heap_free(texture); 6085 return DDERR_INVALIDPARAMS; 6086 } 6087 } 6088 else 6089 { 6090 /* Undocumented feature: Create sublevels until either the 6091 * width or the height is 1. */ 6092 if (version == 7) 6093 desc->u2.dwMipMapCount = wined3d_log2i(max(desc->dwWidth, desc->dwHeight)) + 1; 6094 else 6095 desc->u2.dwMipMapCount = wined3d_log2i(min(desc->dwWidth, desc->dwHeight)) + 1; 6096 } 6097 } 6098 else 6099 { 6100 desc->u2.dwMipMapCount = 1; 6101 } 6102 6103 desc->dwFlags |= DDSD_MIPMAPCOUNT; 6104 levels = desc->u2.dwMipMapCount; 6105 } 6106 else 6107 { 6108 levels = 1; 6109 } 6110 6111 if (!(desc->ddsCaps.dwCaps & (DDSCAPS_VIDEOMEMORY | DDSCAPS_SYSTEMMEMORY))) 6112 { 6113 if (!(desc->ddsCaps.dwCaps2 & (DDSCAPS2_TEXTUREMANAGE | DDSCAPS2_D3DTEXTUREMANAGE))) 6114 { 6115 DWORD usage = 0; 6116 6117 if (desc->ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP) 6118 usage |= WINED3DUSAGE_LEGACY_CUBEMAP | WINED3DUSAGE_TEXTURE; 6119 else if (desc->ddsCaps.dwCaps & DDSCAPS_TEXTURE) 6120 usage |= WINED3DUSAGE_TEXTURE; 6121 6122 if (desc->ddsCaps.dwCaps & DDSCAPS_ZBUFFER) 6123 usage = WINED3DUSAGE_DEPTHSTENCIL; 6124 else if (desc->ddsCaps.dwCaps & DDSCAPS_3DDEVICE) 6125 usage = WINED3DUSAGE_RENDERTARGET; 6126 6127 if (SUCCEEDED(hr = wined3d_check_device_format(ddraw->wined3d, WINED3DADAPTER_DEFAULT, 6128 WINED3D_DEVICE_TYPE_HAL, mode.format_id, usage, WINED3D_RTYPE_TEXTURE_2D, wined3d_desc.format))) 6129 desc->ddsCaps.dwCaps |= DDSCAPS_VIDEOMEMORY; 6130 else 6131 desc->ddsCaps.dwCaps |= DDSCAPS_SYSTEMMEMORY; 6132 } 6133 else if (!(desc->ddsCaps.dwCaps & DDSCAPS_TEXTURE)) 6134 { 6135 /* Tests show surfaces without memory flags get these flags added 6136 * right after creation. */ 6137 desc->ddsCaps.dwCaps |= DDSCAPS_LOCALVIDMEM | DDSCAPS_VIDEOMEMORY; 6138 } 6139 } 6140 6141 if ((desc->ddsCaps.dwCaps & (DDSCAPS_OVERLAY | DDSCAPS_SYSTEMMEMORY)) 6142 == (DDSCAPS_OVERLAY | DDSCAPS_SYSTEMMEMORY)) 6143 { 6144 WARN("System memory overlays are not allowed.\n"); 6145 heap_free(texture); 6146 return DDERR_NOOVERLAYHW; 6147 } 6148 6149 if (desc->ddsCaps.dwCaps & DDSCAPS_SYSTEMMEMORY) 6150 { 6151 /* 6152 * The ddraw RGB device allows to use system memory surfaces as rendering target. 6153 * This does not cause problems because the RGB device does software rasterization 6154 * though it will fail with hardware accelerated ddraw. In order to be partially 6155 * compatible with games requesting explicitly the RGB device, we ignore the 6156 * specified location and try to create rendering targets in video memory if 6157 * possible. 6158 */ 6159 if ((desc->ddsCaps.dwCaps & DDSCAPS_3DDEVICE) && 6160 SUCCEEDED(hr = wined3d_check_device_format(ddraw->wined3d, WINED3DADAPTER_DEFAULT, 6161 WINED3D_DEVICE_TYPE_HAL, mode.format_id, WINED3DUSAGE_RENDERTARGET, 6162 WINED3D_RTYPE_TEXTURE_2D, wined3d_desc.format))) 6163 { 6164 FIXME("Application wants to create rendering target in system memory, using video memory instead\n"); 6165 wined3d_desc.usage |= WINED3DUSAGE_RENDERTARGET; 6166 } 6167 else 6168 wined3d_desc.access = WINED3D_RESOURCE_ACCESS_CPU 6169 | WINED3D_RESOURCE_ACCESS_MAP_R | WINED3D_RESOURCE_ACCESS_MAP_W; 6170 } 6171 else 6172 { 6173 if (desc->ddsCaps.dwCaps & DDSCAPS_TEXTURE) 6174 wined3d_desc.usage |= WINED3DUSAGE_TEXTURE; 6175 if (desc->ddsCaps.dwCaps & DDSCAPS_ZBUFFER) 6176 wined3d_desc.usage |= WINED3DUSAGE_DEPTHSTENCIL; 6177 else if (desc->ddsCaps.dwCaps & DDSCAPS_3DDEVICE) 6178 wined3d_desc.usage |= WINED3DUSAGE_RENDERTARGET; 6179 6180 if (desc->ddsCaps.dwCaps2 & (DDSCAPS2_TEXTUREMANAGE | DDSCAPS2_D3DTEXTUREMANAGE)) 6181 { 6182 wined3d_desc.access = WINED3D_RESOURCE_ACCESS_GPU | WINED3D_RESOURCE_ACCESS_CPU 6183 | WINED3D_RESOURCE_ACCESS_MAP_R | WINED3D_RESOURCE_ACCESS_MAP_W; 6184 /* Managed textures have the system memory flag set. */ 6185 desc->ddsCaps.dwCaps |= DDSCAPS_SYSTEMMEMORY; 6186 } 6187 else if (desc->ddsCaps.dwCaps & DDSCAPS_VIDEOMEMORY) 6188 { 6189 /* Videomemory adds localvidmem. This is mutually exclusive with 6190 * systemmemory and texturemanage. */ 6191 desc->ddsCaps.dwCaps |= DDSCAPS_LOCALVIDMEM; 6192 wined3d_desc.usage |= WINED3DUSAGE_DYNAMIC; 6193 } 6194 } 6195 6196 if (desc->dwFlags & DDSD_LPSURFACE) 6197 { 6198 if (wined3d_desc.access & WINED3D_RESOURCE_ACCESS_GPU) 6199 { 6200 WARN("User memory surfaces should not be GPU accessible.\n"); 6201 heap_free(texture); 6202 return DDERR_INVALIDCAPS; 6203 } 6204 6205 if (version < 4) 6206 { 6207 WARN("User memory surfaces not supported before version 4.\n"); 6208 heap_free(texture); 6209 return DDERR_INVALIDPARAMS; 6210 } 6211 6212 if (!desc->lpSurface) 6213 { 6214 WARN("NULL surface memory pointer specified.\n"); 6215 heap_free(texture); 6216 return DDERR_INVALIDPARAMS; 6217 } 6218 6219 if (format_is_compressed(&desc->u4.ddpfPixelFormat)) 6220 { 6221 if (version != 4 && (desc->dwFlags & DDSD_PITCH)) 6222 { 6223 WARN("Pitch specified on a compressed user memory surface.\n"); 6224 heap_free(texture); 6225 return DDERR_INVALIDPARAMS; 6226 } 6227 6228 if (!(desc->dwFlags & (DDSD_LINEARSIZE | DDSD_PITCH))) 6229 { 6230 WARN("Compressed user memory surfaces should explicitly specify the linear size.\n"); 6231 heap_free(texture); 6232 return DDERR_INVALIDPARAMS; 6233 } 6234 6235 if ((desc->dwFlags & DDSD_LINEARSIZE) 6236 && desc->u1.dwLinearSize < wined3d_calculate_format_pitch(ddraw->wined3d, WINED3DADAPTER_DEFAULT, 6237 wined3d_desc.format, wined3d_desc.width) * ((desc->dwHeight + 3) / 4)) 6238 { 6239 WARN("Invalid linear size %u specified.\n", desc->u1.dwLinearSize); 6240 heap_free(texture); 6241 return DDERR_INVALIDPARAMS; 6242 } 6243 } 6244 else 6245 { 6246 if (!(desc->dwFlags & DDSD_PITCH)) 6247 { 6248 WARN("User memory surfaces should explicitly specify the pitch.\n"); 6249 heap_free(texture); 6250 return DDERR_INVALIDPARAMS; 6251 } 6252 6253 if (desc->u1.lPitch < wined3d_calculate_format_pitch(ddraw->wined3d, WINED3DADAPTER_DEFAULT, 6254 wined3d_desc.format, wined3d_desc.width) || desc->u1.lPitch & 3) 6255 { 6256 WARN("Invalid pitch %u specified.\n", desc->u1.lPitch); 6257 heap_free(texture); 6258 return DDERR_INVALIDPARAMS; 6259 } 6260 6261 pitch = desc->u1.lPitch; 6262 } 6263 } 6264 6265 if (((desc->dwFlags & DDSD_CKDESTOVERLAY) 6266 && desc->u3.ddckCKDestOverlay.dwColorSpaceLowValue != desc->u3.ddckCKDestOverlay.dwColorSpaceHighValue) 6267 || ((desc->dwFlags & DDSD_CKDESTBLT) 6268 && desc->ddckCKDestBlt.dwColorSpaceLowValue != desc->ddckCKDestBlt.dwColorSpaceHighValue) 6269 || ((desc->dwFlags & DDSD_CKSRCOVERLAY) 6270 && desc->ddckCKSrcOverlay.dwColorSpaceLowValue != desc->ddckCKSrcOverlay.dwColorSpaceHighValue) 6271 || ((desc->dwFlags & DDSD_CKSRCBLT) 6272 && desc->ddckCKSrcBlt.dwColorSpaceLowValue != desc->ddckCKSrcBlt.dwColorSpaceHighValue)) 6273 { 6274 WARN("Range color keys not supported, returning DDERR_NOCOLORKEYHW.\n"); 6275 heap_free(texture); 6276 return DDERR_NOCOLORKEYHW; 6277 } 6278 6279 if (desc->ddsCaps.dwCaps & (DDSCAPS_OVERLAY)) 6280 wined3d_desc.usage |= WINED3DUSAGE_OVERLAY; 6281 6282 if (desc->ddsCaps.dwCaps & DDSCAPS_OWNDC) 6283 wined3d_desc.usage |= WINED3DUSAGE_OWNDC; 6284 6285 if (desc->ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP) 6286 { 6287 wined3d_desc.usage |= WINED3DUSAGE_LEGACY_CUBEMAP; 6288 layers = 6; 6289 } 6290 6291 /* Some applications assume surfaces will always be mapped at the same 6292 * address. Some of those also assume that this address is valid even when 6293 * the surface isn't mapped, and that updates done this way will be 6294 * visible on the screen. The game Nox is such an application, 6295 * Commandos: Behind Enemy Lines is another. Setting 6296 * WINED3D_TEXTURE_CREATE_GET_DC_LENIENT will ensure this. */ 6297 if (FAILED(hr = wined3d_texture_create(ddraw->wined3d_device, &wined3d_desc, layers, levels, 6298 WINED3D_TEXTURE_CREATE_GET_DC_LENIENT, NULL, texture, 6299 &ddraw_texture_wined3d_parent_ops, &wined3d_texture))) 6300 { 6301 WARN("Failed to create wined3d texture, hr %#x.\n", hr); 6302 heap_free(texture); 6303 return hr_ddraw_from_wined3d(hr); 6304 } 6305 6306 root = wined3d_texture_get_sub_resource_parent(wined3d_texture, 0); 6307 wined3d_texture_decref(wined3d_texture); 6308 root->is_complex_root = TRUE; 6309 texture->root = root; 6310 wined3d_device_incref(texture->wined3d_device = ddraw->wined3d_device); 6311 6312 if (desc->dwFlags & DDSD_CKDESTOVERLAY) 6313 wined3d_texture_set_color_key(wined3d_texture, DDCKEY_DESTOVERLAY, 6314 (struct wined3d_color_key *)&desc->u3.ddckCKDestOverlay); 6315 if (desc->dwFlags & DDSD_CKDESTBLT) 6316 wined3d_texture_set_color_key(wined3d_texture, DDCKEY_DESTBLT, 6317 (struct wined3d_color_key *)&desc->ddckCKDestBlt); 6318 if (desc->dwFlags & DDSD_CKSRCOVERLAY) 6319 wined3d_texture_set_color_key(wined3d_texture, DDCKEY_SRCOVERLAY, 6320 (struct wined3d_color_key *)&desc->ddckCKSrcOverlay); 6321 if (desc->dwFlags & DDSD_CKSRCBLT) 6322 wined3d_texture_set_color_key(wined3d_texture, DDCKEY_SRCBLT, 6323 (struct wined3d_color_key *)&desc->ddckCKSrcBlt); 6324 6325 for (i = 0; i < layers; ++i) 6326 { 6327 attach = &root->complex_array[layers - 1 - i]; 6328 6329 for (j = 0; j < levels; ++j) 6330 { 6331 mip = wined3d_texture_get_sub_resource_parent(wined3d_texture, i * levels + j); 6332 mip_desc = &mip->surface_desc; 6333 6334 if (j) 6335 { 6336 wined3d_texture_get_sub_resource_desc(wined3d_texture, i * levels + j, &wined3d_mip_desc); 6337 mip_desc->dwWidth = wined3d_mip_desc.width; 6338 mip_desc->dwHeight = wined3d_mip_desc.height; 6339 6340 mip_desc->ddsCaps.dwCaps2 |= DDSCAPS2_MIPMAPSUBLEVEL; 6341 } 6342 else 6343 { 6344 mip_desc->ddsCaps.dwCaps2 &= ~DDSCAPS2_MIPMAPSUBLEVEL; 6345 } 6346 6347 if (mip_desc->ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP) 6348 { 6349 mip_desc->ddsCaps.dwCaps2 &= ~DDSCAPS2_CUBEMAP_ALLFACES; 6350 6351 switch (i) 6352 { 6353 case WINED3D_CUBEMAP_FACE_POSITIVE_X: 6354 mip_desc->ddsCaps.dwCaps2 |= DDSCAPS2_CUBEMAP_POSITIVEX; 6355 break; 6356 case WINED3D_CUBEMAP_FACE_NEGATIVE_X: 6357 mip_desc->ddsCaps.dwCaps2 |= DDSCAPS2_CUBEMAP_NEGATIVEX; 6358 break; 6359 case WINED3D_CUBEMAP_FACE_POSITIVE_Y: 6360 mip_desc->ddsCaps.dwCaps2 |= DDSCAPS2_CUBEMAP_POSITIVEY; 6361 break; 6362 case WINED3D_CUBEMAP_FACE_NEGATIVE_Y: 6363 mip_desc->ddsCaps.dwCaps2 |= DDSCAPS2_CUBEMAP_NEGATIVEY; 6364 break; 6365 case WINED3D_CUBEMAP_FACE_POSITIVE_Z: 6366 mip_desc->ddsCaps.dwCaps2 |= DDSCAPS2_CUBEMAP_POSITIVEZ; 6367 break; 6368 case WINED3D_CUBEMAP_FACE_NEGATIVE_Z: 6369 mip_desc->ddsCaps.dwCaps2 |= DDSCAPS2_CUBEMAP_NEGATIVEZ; 6370 break; 6371 } 6372 6373 } 6374 6375 if (mip == root) 6376 continue; 6377 6378 *attach = mip; 6379 attach = &mip->complex_array[0]; 6380 } 6381 } 6382 6383 if ((desc->dwFlags & DDSD_LPSURFACE) && FAILED(hr = wined3d_texture_update_desc(wined3d_texture, 6384 wined3d_desc.width, wined3d_desc.height, wined3d_desc.format, 6385 WINED3D_MULTISAMPLE_NONE, 0, desc->lpSurface, pitch))) 6386 { 6387 ERR("Failed to set surface memory, hr %#x.\n", hr); 6388 goto fail; 6389 } 6390 6391 if (desc->dwFlags & DDSD_BACKBUFFERCOUNT) 6392 { 6393 unsigned int count = desc->u5.dwBackBufferCount; 6394 struct ddraw_surface *last = root; 6395 6396 attach = &last->complex_array[0]; 6397 for (i = 0; i < count; ++i) 6398 { 6399 if (!(texture = heap_alloc(sizeof(*texture)))) 6400 { 6401 hr = E_OUTOFMEMORY; 6402 goto fail; 6403 } 6404 6405 texture->version = version; 6406 texture->surface_desc = root->surface_desc; 6407 desc = &texture->surface_desc; 6408 6409 /* Only one surface in the flipping chain is a back buffer, one is 6410 * a front buffer, the others are just flippable surfaces. */ 6411 desc->ddsCaps.dwCaps &= ~(DDSCAPS_VISIBLE | DDSCAPS_PRIMARYSURFACE | DDSCAPS_FRONTBUFFER 6412 | DDSCAPS_BACKBUFFER); 6413 if (!i) 6414 desc->ddsCaps.dwCaps |= DDSCAPS_BACKBUFFER; 6415 desc->u5.dwBackBufferCount = 0; 6416 6417 if (FAILED(hr = wined3d_texture_create(ddraw->wined3d_device, &wined3d_desc, 1, 1, 6418 WINED3D_TEXTURE_CREATE_GET_DC_LENIENT, NULL, texture, 6419 &ddraw_texture_wined3d_parent_ops, &wined3d_texture))) 6420 { 6421 heap_free(texture); 6422 hr = hr_ddraw_from_wined3d(hr); 6423 goto fail; 6424 } 6425 6426 last = wined3d_texture_get_sub_resource_parent(wined3d_texture, 0); 6427 wined3d_texture_decref(wined3d_texture); 6428 texture->root = last; 6429 wined3d_device_incref(texture->wined3d_device = ddraw->wined3d_device); 6430 6431 if (desc->dwFlags & DDSD_CKDESTOVERLAY) 6432 wined3d_texture_set_color_key(wined3d_texture, DDCKEY_DESTOVERLAY, 6433 (struct wined3d_color_key *)&desc->u3.ddckCKDestOverlay); 6434 if (desc->dwFlags & DDSD_CKDESTBLT) 6435 wined3d_texture_set_color_key(wined3d_texture, DDCKEY_DESTBLT, 6436 (struct wined3d_color_key *)&desc->ddckCKDestBlt); 6437 if (desc->dwFlags & DDSD_CKSRCOVERLAY) 6438 wined3d_texture_set_color_key(wined3d_texture, DDCKEY_SRCOVERLAY, 6439 (struct wined3d_color_key *)&desc->ddckCKSrcOverlay); 6440 if (desc->dwFlags & DDSD_CKSRCBLT) 6441 wined3d_texture_set_color_key(wined3d_texture, DDCKEY_SRCBLT, 6442 (struct wined3d_color_key *)&desc->ddckCKSrcBlt); 6443 6444 *attach = last; 6445 attach = &last->complex_array[0]; 6446 } 6447 *attach = root; 6448 } 6449 6450 if (surface_desc->ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE) 6451 ddraw->primary = root; 6452 *surface = root; 6453 6454 return DD_OK; 6455 6456 fail: 6457 if (version == 7) 6458 IDirectDrawSurface7_Release(&root->IDirectDrawSurface7_iface); 6459 else if (version == 4) 6460 IDirectDrawSurface4_Release(&root->IDirectDrawSurface4_iface); 6461 else 6462 IDirectDrawSurface_Release(&root->IDirectDrawSurface_iface); 6463 6464 return hr; 6465 } 6466 6467 void ddraw_surface_init(struct ddraw_surface *surface, struct ddraw *ddraw, 6468 struct wined3d_texture *wined3d_texture, unsigned int sub_resource_idx, 6469 const struct wined3d_parent_ops **parent_ops) 6470 { 6471 struct ddraw_texture *texture = wined3d_texture_get_parent(wined3d_texture); 6472 unsigned int texture_level, row_pitch, slice_pitch; 6473 DDSURFACEDESC2 *desc = &surface->surface_desc; 6474 unsigned int version = texture->version; 6475 6476 surface->IDirectDrawSurface7_iface.lpVtbl = &ddraw_surface7_vtbl; 6477 surface->IDirectDrawSurface4_iface.lpVtbl = &ddraw_surface4_vtbl; 6478 surface->IDirectDrawSurface3_iface.lpVtbl = &ddraw_surface3_vtbl; 6479 surface->IDirectDrawSurface2_iface.lpVtbl = &ddraw_surface2_vtbl; 6480 surface->IDirectDrawSurface_iface.lpVtbl = &ddraw_surface1_vtbl; 6481 surface->IDirectDrawGammaControl_iface.lpVtbl = &ddraw_gamma_control_vtbl; 6482 surface->IDirect3DTexture2_iface.lpVtbl = &d3d_texture2_vtbl; 6483 surface->IDirect3DTexture_iface.lpVtbl = &d3d_texture1_vtbl; 6484 surface->iface_count = 1; 6485 surface->version = version; 6486 surface->ddraw = ddraw; 6487 6488 if (version == 7) 6489 { 6490 surface->ref7 = 1; 6491 surface->texture_outer = (IUnknown *)&surface->IDirectDrawSurface7_iface; 6492 } 6493 else if (version == 4) 6494 { 6495 surface->ref4 = 1; 6496 surface->texture_outer = (IUnknown *)&surface->IDirectDrawSurface4_iface; 6497 } 6498 else 6499 { 6500 surface->ref1 = 1; 6501 surface->texture_outer = (IUnknown *)&surface->IDirectDrawSurface_iface; 6502 } 6503 6504 *desc = texture->surface_desc; 6505 surface->first_attached = surface; 6506 6507 texture_level = desc->ddsCaps.dwCaps & DDSCAPS_MIPMAP ? sub_resource_idx % desc->u2.dwMipMapCount : 0; 6508 wined3d_texture_get_pitch(wined3d_texture, texture_level, &row_pitch, &slice_pitch); 6509 if (format_is_compressed(&desc->u4.ddpfPixelFormat)) 6510 { 6511 if (desc->dwFlags & DDSD_LPSURFACE) 6512 desc->u1.dwLinearSize = ~0u; 6513 else 6514 desc->u1.dwLinearSize = slice_pitch; 6515 desc->dwFlags |= DDSD_LINEARSIZE; 6516 desc->dwFlags &= ~(DDSD_LPSURFACE | DDSD_PITCH); 6517 } 6518 else 6519 { 6520 if (!(desc->dwFlags & DDSD_LPSURFACE)) 6521 desc->u1.lPitch = row_pitch; 6522 desc->dwFlags |= DDSD_PITCH; 6523 desc->dwFlags &= ~(DDSD_LPSURFACE | DDSD_LINEARSIZE); 6524 } 6525 desc->lpSurface = NULL; 6526 6527 wined3d_texture_incref(surface->wined3d_texture = wined3d_texture); 6528 surface->sub_resource_idx = sub_resource_idx; 6529 *parent_ops = &ddraw_surface_wined3d_parent_ops; 6530 6531 wined3d_private_store_init(&surface->private_store); 6532 } 6533 6534 static void STDMETHODCALLTYPE view_wined3d_object_destroyed(void *parent) 6535 { 6536 struct ddraw_surface *surface = parent; 6537 6538 /* If the surface reference count drops to zero, we release our reference 6539 * to the view, but don't clear the pointer yet, in case e.g. a 6540 * GetRenderTarget() call brings the surface back before the view is 6541 * actually destroyed. When the view is destroyed, we need to clear the 6542 * pointer, or a subsequent surface AddRef() would reference it again. 6543 * 6544 * This is safe because as long as the view still has a reference to the 6545 * texture, the surface is also still alive, and we're called before the 6546 * view releases that reference. */ 6547 surface->wined3d_rtv = NULL; 6548 } 6549 6550 static const struct wined3d_parent_ops ddraw_view_wined3d_parent_ops = 6551 { 6552 view_wined3d_object_destroyed, 6553 }; 6554 6555 struct wined3d_rendertarget_view *ddraw_surface_get_rendertarget_view(struct ddraw_surface *surface) 6556 { 6557 HRESULT hr; 6558 6559 if (surface->wined3d_rtv) 6560 return surface->wined3d_rtv; 6561 6562 if (FAILED(hr = wined3d_rendertarget_view_create_from_sub_resource(surface->wined3d_texture, 6563 surface->sub_resource_idx, surface, &ddraw_view_wined3d_parent_ops, &surface->wined3d_rtv))) 6564 { 6565 ERR("Failed to create rendertarget view, hr %#x.\n", hr); 6566 return NULL; 6567 } 6568 6569 return surface->wined3d_rtv; 6570 } 6571