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 2350 wined3d_mutex_lock(); 2351 if (!surface->dc) 2352 { 2353 hr = DDERR_NODC; 2354 } 2355 else if (SUCCEEDED(hr = wined3d_texture_release_dc(surface->wined3d_texture, surface->sub_resource_idx, hdc))) 2356 { 2357 surface->dc = NULL; 2358 if (surface->surface_desc.ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE) 2359 hr = ddraw_surface_update_frontbuffer(surface, NULL, FALSE, 0); 2360 } 2361 wined3d_mutex_unlock(); 2362 2363 2364 return hr; 2365 } 2366 2367 static HRESULT WINAPI ddraw_surface4_ReleaseDC(IDirectDrawSurface4 *iface, HDC dc) 2368 { 2369 struct ddraw_surface *surface = impl_from_IDirectDrawSurface4(iface); 2370 2371 TRACE("iface %p, dc %p.\n", iface, dc); 2372 2373 return ddraw_surface7_ReleaseDC(&surface->IDirectDrawSurface7_iface, dc); 2374 } 2375 2376 static HRESULT WINAPI ddraw_surface3_ReleaseDC(IDirectDrawSurface3 *iface, HDC dc) 2377 { 2378 struct ddraw_surface *surface = impl_from_IDirectDrawSurface3(iface); 2379 2380 TRACE("iface %p, dc %p.\n", iface, dc); 2381 2382 return ddraw_surface7_ReleaseDC(&surface->IDirectDrawSurface7_iface, dc); 2383 } 2384 2385 static HRESULT WINAPI ddraw_surface2_ReleaseDC(IDirectDrawSurface2 *iface, HDC dc) 2386 { 2387 struct ddraw_surface *surface = impl_from_IDirectDrawSurface2(iface); 2388 2389 TRACE("iface %p, dc %p.\n", iface, dc); 2390 2391 return ddraw_surface7_ReleaseDC(&surface->IDirectDrawSurface7_iface, dc); 2392 } 2393 2394 static HRESULT WINAPI ddraw_surface1_ReleaseDC(IDirectDrawSurface *iface, HDC dc) 2395 { 2396 struct ddraw_surface *surface = impl_from_IDirectDrawSurface(iface); 2397 2398 TRACE("iface %p, dc %p.\n", iface, dc); 2399 2400 return ddraw_surface7_ReleaseDC(&surface->IDirectDrawSurface7_iface, dc); 2401 } 2402 2403 /***************************************************************************** 2404 * IDirectDrawSurface7::GetCaps 2405 * 2406 * Returns the surface's caps 2407 * 2408 * Params: 2409 * Caps: Address to write the caps to 2410 * 2411 * Returns: 2412 * DD_OK on success 2413 * DDERR_INVALIDPARAMS if Caps is NULL 2414 * 2415 *****************************************************************************/ 2416 static HRESULT WINAPI ddraw_surface7_GetCaps(IDirectDrawSurface7 *iface, DDSCAPS2 *Caps) 2417 { 2418 struct ddraw_surface *surface = impl_from_IDirectDrawSurface7(iface); 2419 2420 TRACE("iface %p, caps %p.\n", iface, Caps); 2421 2422 if(!Caps) 2423 return DDERR_INVALIDPARAMS; 2424 2425 *Caps = surface->surface_desc.ddsCaps; 2426 2427 return DD_OK; 2428 } 2429 2430 static HRESULT WINAPI ddraw_surface4_GetCaps(IDirectDrawSurface4 *iface, DDSCAPS2 *caps) 2431 { 2432 struct ddraw_surface *surface = impl_from_IDirectDrawSurface4(iface); 2433 2434 TRACE("iface %p, caps %p.\n", iface, caps); 2435 2436 return ddraw_surface7_GetCaps(&surface->IDirectDrawSurface7_iface, caps); 2437 } 2438 2439 static HRESULT WINAPI ddraw_surface3_GetCaps(IDirectDrawSurface3 *iface, DDSCAPS *caps) 2440 { 2441 struct ddraw_surface *surface = impl_from_IDirectDrawSurface3(iface); 2442 DDSCAPS2 caps2; 2443 HRESULT hr; 2444 2445 TRACE("iface %p, caps %p.\n", iface, caps); 2446 2447 hr = ddraw_surface7_GetCaps(&surface->IDirectDrawSurface7_iface, &caps2); 2448 if (FAILED(hr)) return hr; 2449 2450 caps->dwCaps = caps2.dwCaps; 2451 return hr; 2452 } 2453 2454 static HRESULT WINAPI ddraw_surface2_GetCaps(IDirectDrawSurface2 *iface, DDSCAPS *caps) 2455 { 2456 struct ddraw_surface *surface = impl_from_IDirectDrawSurface2(iface); 2457 DDSCAPS2 caps2; 2458 HRESULT hr; 2459 2460 TRACE("iface %p, caps %p.\n", iface, caps); 2461 2462 hr = ddraw_surface7_GetCaps(&surface->IDirectDrawSurface7_iface, &caps2); 2463 if (FAILED(hr)) return hr; 2464 2465 caps->dwCaps = caps2.dwCaps; 2466 return hr; 2467 } 2468 2469 static HRESULT WINAPI ddraw_surface1_GetCaps(IDirectDrawSurface *iface, DDSCAPS *caps) 2470 { 2471 struct ddraw_surface *surface = impl_from_IDirectDrawSurface(iface); 2472 DDSCAPS2 caps2; 2473 HRESULT hr; 2474 2475 TRACE("iface %p, caps %p.\n", iface, caps); 2476 2477 hr = ddraw_surface7_GetCaps(&surface->IDirectDrawSurface7_iface, &caps2); 2478 if (FAILED(hr)) return hr; 2479 2480 caps->dwCaps = caps2.dwCaps; 2481 return hr; 2482 } 2483 2484 static HRESULT WINAPI ddraw_surface7_SetPriority(IDirectDrawSurface7 *iface, DWORD priority) 2485 { 2486 struct ddraw_surface *surface = impl_from_IDirectDrawSurface7(iface); 2487 DWORD managed = DDSCAPS2_TEXTUREMANAGE | DDSCAPS2_D3DTEXTUREMANAGE; 2488 HRESULT hr; 2489 struct wined3d_resource *resource; 2490 2491 TRACE("iface %p, priority %u.\n", iface, priority); 2492 2493 wined3d_mutex_lock(); 2494 /* No need to check for offscreen plain surfaces or mipmap sublevels. SetPriority 2495 * calls on such surfaces segfault on Windows. */ 2496 if (!(surface->surface_desc.ddsCaps.dwCaps2 & managed)) 2497 { 2498 WARN("Called on non-managed texture returning DDERR_INVALIDPARAMS.\n"); 2499 hr = DDERR_INVALIDPARAMS; 2500 } 2501 else 2502 { 2503 resource = wined3d_texture_get_resource(surface->wined3d_texture); 2504 wined3d_resource_set_priority(resource, priority); 2505 hr = DD_OK; 2506 } 2507 wined3d_mutex_unlock(); 2508 2509 return hr; 2510 } 2511 2512 static HRESULT WINAPI ddraw_surface7_GetPriority(IDirectDrawSurface7 *iface, DWORD *priority) 2513 { 2514 struct ddraw_surface *surface = impl_from_IDirectDrawSurface7(iface); 2515 const struct wined3d_resource *resource; 2516 DWORD managed = DDSCAPS2_TEXTUREMANAGE | DDSCAPS2_D3DTEXTUREMANAGE; 2517 HRESULT hr; 2518 2519 TRACE("iface %p, priority %p.\n", iface, priority); 2520 2521 wined3d_mutex_lock(); 2522 if (surface->surface_desc.ddsCaps.dwCaps & DDSCAPS_OFFSCREENPLAIN) 2523 { 2524 WARN("Called on offscreenplain surface, returning DDERR_INVALIDOBJECT.\n"); 2525 hr = DDERR_INVALIDOBJECT; 2526 } 2527 else if (!(surface->surface_desc.ddsCaps.dwCaps2 & managed) || !surface->is_complex_root) 2528 { 2529 WARN("Called on non-managed texture or non-root surface, returning DDERR_INVALIDPARAMS.\n"); 2530 hr = DDERR_INVALIDPARAMS; 2531 } 2532 else 2533 { 2534 resource = wined3d_texture_get_resource(surface->wined3d_texture); 2535 *priority = wined3d_resource_get_priority(resource); 2536 hr = DD_OK; 2537 } 2538 wined3d_mutex_unlock(); 2539 2540 return hr; 2541 } 2542 2543 /***************************************************************************** 2544 * IDirectDrawSurface7::SetPrivateData 2545 * 2546 * Stores some data in the surface that is intended for the application's 2547 * use. 2548 * 2549 * Params: 2550 * tag: GUID that identifies the data 2551 * Data: Pointer to the private data 2552 * Size: Size of the private data 2553 * Flags: Some flags 2554 * 2555 * Returns: 2556 * D3D_OK on success, error code otherwise. 2557 * 2558 *****************************************************************************/ 2559 static HRESULT WINAPI ddraw_surface7_SetPrivateData(IDirectDrawSurface7 *iface, 2560 REFGUID tag, void *data, DWORD size, DWORD flags) 2561 { 2562 struct ddraw_surface *surface = impl_from_IDirectDrawSurface7(iface); 2563 HRESULT hr; 2564 2565 TRACE("iface %p, tag %s, data %p, data_size %u, flags %#x.\n", 2566 iface, debugstr_guid(tag), data, size, flags); 2567 2568 if (!data) 2569 { 2570 WARN("data is NULL, returning DDERR_INVALIDPARAMS.\n"); 2571 return DDERR_INVALIDPARAMS; 2572 } 2573 2574 wined3d_mutex_lock(); 2575 hr = wined3d_private_store_set_private_data(&surface->private_store, tag, data, size, flags); 2576 wined3d_mutex_unlock(); 2577 return hr_ddraw_from_wined3d(hr); 2578 } 2579 2580 static HRESULT WINAPI ddraw_surface4_SetPrivateData(IDirectDrawSurface4 *iface, 2581 REFGUID tag, void *data, DWORD size, DWORD flags) 2582 { 2583 struct ddraw_surface *surface = impl_from_IDirectDrawSurface4(iface); 2584 2585 TRACE("iface %p, tag %s, data %p, data_size %u, flags %#x.\n", 2586 iface, debugstr_guid(tag), data, size, flags); 2587 2588 return ddraw_surface7_SetPrivateData(&surface->IDirectDrawSurface7_iface, tag, data, size, flags); 2589 } 2590 2591 /***************************************************************************** 2592 * IDirectDrawSurface7::GetPrivateData 2593 * 2594 * Returns the private data set with IDirectDrawSurface7::SetPrivateData 2595 * 2596 * Params: 2597 * tag: GUID of the data to return 2598 * Data: Address where to write the data to 2599 * Size: Size of the buffer at Data 2600 * 2601 * Returns: 2602 * DD_OK on success 2603 * DDERR_INVALIDPARAMS if Data is NULL 2604 * 2605 *****************************************************************************/ 2606 static HRESULT WINAPI ddraw_surface7_GetPrivateData(IDirectDrawSurface7 *iface, REFGUID tag, void *data, DWORD *size) 2607 { 2608 struct ddraw_surface *surface = impl_from_IDirectDrawSurface7(iface); 2609 const struct wined3d_private_data *stored_data; 2610 HRESULT hr; 2611 2612 TRACE("iface %p, tag %s, data %p, data_size %p.\n", 2613 iface, debugstr_guid(tag), data, size); 2614 2615 wined3d_mutex_lock(); 2616 stored_data = wined3d_private_store_get_private_data(&surface->private_store, tag); 2617 if (!stored_data) 2618 { 2619 hr = DDERR_NOTFOUND; 2620 goto done; 2621 } 2622 if (!size) 2623 { 2624 hr = DDERR_INVALIDPARAMS; 2625 goto done; 2626 } 2627 if (*size < stored_data->size) 2628 { 2629 *size = stored_data->size; 2630 hr = DDERR_MOREDATA; 2631 goto done; 2632 } 2633 if (!data) 2634 { 2635 hr = DDERR_INVALIDPARAMS; 2636 goto done; 2637 } 2638 2639 *size = stored_data->size; 2640 memcpy(data, stored_data->content.data, stored_data->size); 2641 hr = DD_OK; 2642 2643 done: 2644 wined3d_mutex_unlock(); 2645 return hr; 2646 } 2647 2648 static HRESULT WINAPI ddraw_surface4_GetPrivateData(IDirectDrawSurface4 *iface, REFGUID tag, void *data, DWORD *size) 2649 { 2650 struct ddraw_surface *surface = impl_from_IDirectDrawSurface4(iface); 2651 2652 TRACE("iface %p, tag %s, data %p, data_size %p.\n", 2653 iface, debugstr_guid(tag), data, size); 2654 2655 return ddraw_surface7_GetPrivateData(&surface->IDirectDrawSurface7_iface, tag, data, size); 2656 } 2657 2658 /***************************************************************************** 2659 * IDirectDrawSurface7::FreePrivateData 2660 * 2661 * Frees private data stored in the surface 2662 * 2663 * Params: 2664 * tag: Tag of the data to free 2665 * 2666 * Returns: 2667 * D3D_OK on success, error code otherwise. 2668 * 2669 *****************************************************************************/ 2670 static HRESULT WINAPI ddraw_surface7_FreePrivateData(IDirectDrawSurface7 *iface, REFGUID tag) 2671 { 2672 struct ddraw_surface *surface = impl_from_IDirectDrawSurface7(iface); 2673 struct wined3d_private_data *entry; 2674 2675 TRACE("iface %p, tag %s.\n", iface, debugstr_guid(tag)); 2676 2677 wined3d_mutex_lock(); 2678 entry = wined3d_private_store_get_private_data(&surface->private_store, tag); 2679 if (!entry) 2680 { 2681 wined3d_mutex_unlock(); 2682 return DDERR_NOTFOUND; 2683 } 2684 2685 wined3d_private_store_free_private_data(&surface->private_store, entry); 2686 wined3d_mutex_unlock(); 2687 2688 return DD_OK; 2689 } 2690 2691 static HRESULT WINAPI ddraw_surface4_FreePrivateData(IDirectDrawSurface4 *iface, REFGUID tag) 2692 { 2693 struct ddraw_surface *surface = impl_from_IDirectDrawSurface4(iface); 2694 2695 TRACE("iface %p, tag %s.\n", iface, debugstr_guid(tag)); 2696 2697 return ddraw_surface7_FreePrivateData(&surface->IDirectDrawSurface7_iface, tag); 2698 } 2699 2700 /***************************************************************************** 2701 * IDirectDrawSurface7::PageLock 2702 * 2703 * Prevents a sysmem surface from being paged out 2704 * 2705 * Params: 2706 * Flags: Not used, must be 0(unchecked) 2707 * 2708 * Returns: 2709 * DD_OK, because it's a stub 2710 * 2711 *****************************************************************************/ 2712 static HRESULT WINAPI ddraw_surface7_PageLock(IDirectDrawSurface7 *iface, DWORD Flags) 2713 { 2714 TRACE("iface %p, flags %#x.\n", iface, Flags); 2715 2716 /* This is Windows memory management related - we don't need this */ 2717 return DD_OK; 2718 } 2719 2720 static HRESULT WINAPI ddraw_surface4_PageLock(IDirectDrawSurface4 *iface, DWORD flags) 2721 { 2722 struct ddraw_surface *surface = impl_from_IDirectDrawSurface4(iface); 2723 2724 TRACE("iface %p, flags %#x.\n", iface, flags); 2725 2726 return ddraw_surface7_PageLock(&surface->IDirectDrawSurface7_iface, flags); 2727 } 2728 2729 static HRESULT WINAPI ddraw_surface3_PageLock(IDirectDrawSurface3 *iface, DWORD flags) 2730 { 2731 struct ddraw_surface *surface = impl_from_IDirectDrawSurface3(iface); 2732 2733 TRACE("iface %p, flags %#x.\n", iface, flags); 2734 2735 return ddraw_surface7_PageLock(&surface->IDirectDrawSurface7_iface, flags); 2736 } 2737 2738 static HRESULT WINAPI ddraw_surface2_PageLock(IDirectDrawSurface2 *iface, DWORD flags) 2739 { 2740 struct ddraw_surface *surface = impl_from_IDirectDrawSurface2(iface); 2741 2742 TRACE("iface %p, flags %#x.\n", iface, flags); 2743 2744 return ddraw_surface7_PageLock(&surface->IDirectDrawSurface7_iface, flags); 2745 } 2746 2747 /***************************************************************************** 2748 * IDirectDrawSurface7::PageUnlock 2749 * 2750 * Allows a sysmem surface to be paged out 2751 * 2752 * Params: 2753 * Flags: Not used, must be 0(unchecked) 2754 * 2755 * Returns: 2756 * DD_OK, because it's a stub 2757 * 2758 *****************************************************************************/ 2759 static HRESULT WINAPI ddraw_surface7_PageUnlock(IDirectDrawSurface7 *iface, DWORD Flags) 2760 { 2761 TRACE("iface %p, flags %#x.\n", iface, Flags); 2762 2763 return DD_OK; 2764 } 2765 2766 static HRESULT WINAPI ddraw_surface4_PageUnlock(IDirectDrawSurface4 *iface, DWORD flags) 2767 { 2768 struct ddraw_surface *surface = impl_from_IDirectDrawSurface4(iface); 2769 2770 TRACE("iface %p, flags %#x.\n", iface, flags); 2771 2772 return ddraw_surface7_PageUnlock(&surface->IDirectDrawSurface7_iface, flags); 2773 } 2774 2775 static HRESULT WINAPI ddraw_surface3_PageUnlock(IDirectDrawSurface3 *iface, DWORD flags) 2776 { 2777 struct ddraw_surface *surface = impl_from_IDirectDrawSurface3(iface); 2778 2779 TRACE("iface %p, flags %#x.\n", iface, flags); 2780 2781 return ddraw_surface7_PageUnlock(&surface->IDirectDrawSurface7_iface, flags); 2782 } 2783 2784 static HRESULT WINAPI ddraw_surface2_PageUnlock(IDirectDrawSurface2 *iface, DWORD flags) 2785 { 2786 struct ddraw_surface *surface = impl_from_IDirectDrawSurface2(iface); 2787 2788 TRACE("iface %p, flags %#x.\n", iface, flags); 2789 2790 return ddraw_surface7_PageUnlock(&surface->IDirectDrawSurface7_iface, flags); 2791 } 2792 2793 /***************************************************************************** 2794 * IDirectDrawSurface7::BltBatch 2795 * 2796 * An unimplemented function 2797 * 2798 * Params: 2799 * ? 2800 * 2801 * Returns: 2802 * DDERR_UNSUPPORTED 2803 * 2804 *****************************************************************************/ 2805 static HRESULT WINAPI DECLSPEC_HOTPATCH ddraw_surface7_BltBatch(IDirectDrawSurface7 *iface, DDBLTBATCH *Batch, DWORD Count, DWORD Flags) 2806 { 2807 TRACE("iface %p, batch %p, count %u, flags %#x.\n", iface, Batch, Count, Flags); 2808 2809 /* MSDN: "not currently implemented" */ 2810 return DDERR_UNSUPPORTED; 2811 } 2812 2813 static HRESULT WINAPI DECLSPEC_HOTPATCH ddraw_surface4_BltBatch(IDirectDrawSurface4 *iface, DDBLTBATCH *batch, DWORD count, DWORD flags) 2814 { 2815 struct ddraw_surface *surface = impl_from_IDirectDrawSurface4(iface); 2816 2817 TRACE("iface %p, batch %p, count %u, flags %#x.\n", iface, batch, count, flags); 2818 2819 return ddraw_surface7_BltBatch(&surface->IDirectDrawSurface7_iface, batch, count, flags); 2820 } 2821 2822 static HRESULT WINAPI DECLSPEC_HOTPATCH ddraw_surface3_BltBatch(IDirectDrawSurface3 *iface, DDBLTBATCH *batch, DWORD count, DWORD flags) 2823 { 2824 struct ddraw_surface *surface = impl_from_IDirectDrawSurface3(iface); 2825 2826 TRACE("iface %p, batch %p, count %u, flags %#x.\n", iface, batch, count, flags); 2827 2828 return ddraw_surface7_BltBatch(&surface->IDirectDrawSurface7_iface, batch, count, flags); 2829 } 2830 2831 static HRESULT WINAPI DECLSPEC_HOTPATCH ddraw_surface2_BltBatch(IDirectDrawSurface2 *iface, DDBLTBATCH *batch, DWORD count, DWORD flags) 2832 { 2833 struct ddraw_surface *surface = impl_from_IDirectDrawSurface2(iface); 2834 2835 TRACE("iface %p, batch %p, count %u, flags %#x.\n", iface, batch, count, flags); 2836 2837 return ddraw_surface7_BltBatch(&surface->IDirectDrawSurface7_iface, batch, count, flags); 2838 } 2839 2840 static HRESULT WINAPI DECLSPEC_HOTPATCH ddraw_surface1_BltBatch(IDirectDrawSurface *iface, DDBLTBATCH *batch, DWORD count, DWORD flags) 2841 { 2842 struct ddraw_surface *surface = impl_from_IDirectDrawSurface(iface); 2843 2844 TRACE("iface %p, batch %p, count %u, flags %#x.\n", iface, batch, count, flags); 2845 2846 return ddraw_surface7_BltBatch(&surface->IDirectDrawSurface7_iface, batch, count, flags); 2847 } 2848 2849 /***************************************************************************** 2850 * IDirectDrawSurface7::EnumAttachedSurfaces 2851 * 2852 * Enumerates all surfaces attached to this surface 2853 * 2854 * Params: 2855 * context: Pointer to pass unmodified to the callback 2856 * cb: Callback function to call for each surface 2857 * 2858 * Returns: 2859 * DD_OK on success 2860 * DDERR_INVALIDPARAMS if cb is NULL 2861 * 2862 *****************************************************************************/ 2863 static HRESULT WINAPI ddraw_surface7_EnumAttachedSurfaces(IDirectDrawSurface7 *iface, 2864 void *context, LPDDENUMSURFACESCALLBACK7 cb) 2865 { 2866 struct ddraw_surface *surface = impl_from_IDirectDrawSurface7(iface); 2867 struct ddraw_surface *surf; 2868 DDSURFACEDESC2 desc; 2869 int i; 2870 2871 /* Attached surfaces aren't handled in WineD3D */ 2872 TRACE("iface %p, context %p, callback %p.\n", iface, context, cb); 2873 2874 if(!cb) 2875 return DDERR_INVALIDPARAMS; 2876 2877 wined3d_mutex_lock(); 2878 2879 for(i = 0; i < MAX_COMPLEX_ATTACHED; i++) 2880 { 2881 surf = surface->complex_array[i]; 2882 if(!surf) break; 2883 2884 ddraw_surface7_AddRef(&surf->IDirectDrawSurface7_iface); 2885 desc = surf->surface_desc; 2886 /* check: != DDENUMRET_OK or == DDENUMRET_CANCEL? */ 2887 if (cb(&surf->IDirectDrawSurface7_iface, &desc, context) == DDENUMRET_CANCEL) 2888 { 2889 wined3d_mutex_unlock(); 2890 return DD_OK; 2891 } 2892 } 2893 2894 for (surf = surface->next_attached; surf != NULL; surf = surf->next_attached) 2895 { 2896 ddraw_surface7_AddRef(&surf->IDirectDrawSurface7_iface); 2897 desc = surf->surface_desc; 2898 /* check: != DDENUMRET_OK or == DDENUMRET_CANCEL? */ 2899 if (cb(&surf->IDirectDrawSurface7_iface, &desc, context) == DDENUMRET_CANCEL) 2900 { 2901 wined3d_mutex_unlock(); 2902 return DD_OK; 2903 } 2904 } 2905 2906 TRACE(" end of enumeration.\n"); 2907 2908 wined3d_mutex_unlock(); 2909 2910 return DD_OK; 2911 } 2912 2913 struct callback_info2 2914 { 2915 LPDDENUMSURFACESCALLBACK2 callback; 2916 void *context; 2917 }; 2918 2919 struct callback_info 2920 { 2921 LPDDENUMSURFACESCALLBACK callback; 2922 void *context; 2923 }; 2924 2925 static HRESULT CALLBACK EnumCallback2(IDirectDrawSurface7 *surface, DDSURFACEDESC2 *surface_desc, void *context) 2926 { 2927 struct ddraw_surface *surface_impl = impl_from_IDirectDrawSurface7(surface); 2928 const struct callback_info2 *info = context; 2929 2930 ddraw_surface4_AddRef(&surface_impl->IDirectDrawSurface4_iface); 2931 ddraw_surface7_Release(surface); 2932 2933 return info->callback(&surface_impl->IDirectDrawSurface4_iface, surface_desc, info->context); 2934 } 2935 2936 static HRESULT CALLBACK EnumCallback(IDirectDrawSurface7 *surface, DDSURFACEDESC2 *surface_desc, void *context) 2937 { 2938 struct ddraw_surface *surface_impl = impl_from_IDirectDrawSurface7(surface); 2939 const struct callback_info *info = context; 2940 2941 ddraw_surface1_AddRef(&surface_impl->IDirectDrawSurface_iface); 2942 ddraw_surface7_Release(surface); 2943 2944 /* FIXME: Check surface_test.dwSize */ 2945 return info->callback(&surface_impl->IDirectDrawSurface_iface, 2946 (DDSURFACEDESC *)surface_desc, info->context); 2947 } 2948 2949 static HRESULT WINAPI ddraw_surface4_EnumAttachedSurfaces(IDirectDrawSurface4 *iface, 2950 void *context, LPDDENUMSURFACESCALLBACK2 callback) 2951 { 2952 struct ddraw_surface *surface = impl_from_IDirectDrawSurface4(iface); 2953 struct callback_info2 info; 2954 2955 TRACE("iface %p, context %p, callback %p.\n", iface, context, callback); 2956 2957 info.callback = callback; 2958 info.context = context; 2959 2960 return ddraw_surface7_EnumAttachedSurfaces(&surface->IDirectDrawSurface7_iface, 2961 &info, EnumCallback2); 2962 } 2963 2964 static HRESULT WINAPI ddraw_surface3_EnumAttachedSurfaces(IDirectDrawSurface3 *iface, 2965 void *context, LPDDENUMSURFACESCALLBACK callback) 2966 { 2967 struct ddraw_surface *surface = impl_from_IDirectDrawSurface3(iface); 2968 struct callback_info info; 2969 2970 TRACE("iface %p, context %p, callback %p.\n", iface, context, callback); 2971 2972 info.callback = callback; 2973 info.context = context; 2974 2975 return ddraw_surface7_EnumAttachedSurfaces(&surface->IDirectDrawSurface7_iface, 2976 &info, EnumCallback); 2977 } 2978 2979 static HRESULT WINAPI ddraw_surface2_EnumAttachedSurfaces(IDirectDrawSurface2 *iface, 2980 void *context, LPDDENUMSURFACESCALLBACK callback) 2981 { 2982 struct ddraw_surface *surface = impl_from_IDirectDrawSurface2(iface); 2983 struct callback_info info; 2984 2985 TRACE("iface %p, context %p, callback %p.\n", iface, context, callback); 2986 2987 info.callback = callback; 2988 info.context = context; 2989 2990 return ddraw_surface7_EnumAttachedSurfaces(&surface->IDirectDrawSurface7_iface, 2991 &info, EnumCallback); 2992 } 2993 2994 static HRESULT WINAPI ddraw_surface1_EnumAttachedSurfaces(IDirectDrawSurface *iface, 2995 void *context, LPDDENUMSURFACESCALLBACK callback) 2996 { 2997 struct ddraw_surface *surface = impl_from_IDirectDrawSurface(iface); 2998 struct callback_info info; 2999 3000 TRACE("iface %p, context %p, callback %p.\n", iface, context, callback); 3001 3002 info.callback = callback; 3003 info.context = context; 3004 3005 return ddraw_surface7_EnumAttachedSurfaces(&surface->IDirectDrawSurface7_iface, 3006 &info, EnumCallback); 3007 } 3008 3009 /***************************************************************************** 3010 * IDirectDrawSurface7::EnumOverlayZOrders 3011 * 3012 * "Enumerates the overlay surfaces on the specified destination" 3013 * 3014 * Params: 3015 * Flags: DDENUMOVERLAYZ_BACKTOFRONT or DDENUMOVERLAYZ_FRONTTOBACK 3016 * context: context to pass back to the callback 3017 * cb: callback function to call for each enumerated surface 3018 * 3019 * Returns: 3020 * DD_OK, because it's a stub 3021 * 3022 *****************************************************************************/ 3023 static HRESULT WINAPI ddraw_surface7_EnumOverlayZOrders(IDirectDrawSurface7 *iface, 3024 DWORD Flags, void *context, LPDDENUMSURFACESCALLBACK7 cb) 3025 { 3026 FIXME("iface %p, flags %#x, context %p, callback %p stub!\n", iface, Flags, context, cb); 3027 3028 return DD_OK; 3029 } 3030 3031 static HRESULT WINAPI ddraw_surface4_EnumOverlayZOrders(IDirectDrawSurface4 *iface, 3032 DWORD flags, void *context, LPDDENUMSURFACESCALLBACK2 callback) 3033 { 3034 struct ddraw_surface *surface = impl_from_IDirectDrawSurface4(iface); 3035 struct callback_info2 info; 3036 3037 TRACE("iface %p, flags %#x, context %p, callback %p.\n", iface, flags, context, callback); 3038 3039 info.callback = callback; 3040 info.context = context; 3041 3042 return ddraw_surface7_EnumOverlayZOrders(&surface->IDirectDrawSurface7_iface, 3043 flags, &info, EnumCallback2); 3044 } 3045 3046 static HRESULT WINAPI ddraw_surface3_EnumOverlayZOrders(IDirectDrawSurface3 *iface, 3047 DWORD flags, void *context, LPDDENUMSURFACESCALLBACK callback) 3048 { 3049 struct ddraw_surface *surface = impl_from_IDirectDrawSurface3(iface); 3050 struct callback_info info; 3051 3052 TRACE("iface %p, flags %#x, context %p, callback %p.\n", iface, flags, context, callback); 3053 3054 info.callback = callback; 3055 info.context = context; 3056 3057 return ddraw_surface7_EnumOverlayZOrders(&surface->IDirectDrawSurface7_iface, 3058 flags, &info, EnumCallback); 3059 } 3060 3061 static HRESULT WINAPI ddraw_surface2_EnumOverlayZOrders(IDirectDrawSurface2 *iface, 3062 DWORD flags, void *context, LPDDENUMSURFACESCALLBACK callback) 3063 { 3064 struct ddraw_surface *surface = impl_from_IDirectDrawSurface2(iface); 3065 struct callback_info info; 3066 3067 TRACE("iface %p, flags %#x, context %p, callback %p.\n", iface, flags, context, callback); 3068 3069 info.callback = callback; 3070 info.context = context; 3071 3072 return ddraw_surface7_EnumOverlayZOrders(&surface->IDirectDrawSurface7_iface, 3073 flags, &info, EnumCallback); 3074 } 3075 3076 static HRESULT WINAPI ddraw_surface1_EnumOverlayZOrders(IDirectDrawSurface *iface, 3077 DWORD flags, void *context, LPDDENUMSURFACESCALLBACK callback) 3078 { 3079 struct ddraw_surface *surface = impl_from_IDirectDrawSurface(iface); 3080 struct callback_info info; 3081 3082 TRACE("iface %p, flags %#x, context %p, callback %p.\n", iface, flags, context, callback); 3083 3084 info.callback = callback; 3085 info.context = context; 3086 3087 return ddraw_surface7_EnumOverlayZOrders(&surface->IDirectDrawSurface7_iface, 3088 flags, &info, EnumCallback); 3089 } 3090 3091 /***************************************************************************** 3092 * IDirectDrawSurface7::GetBltStatus 3093 * 3094 * Returns the blitting status 3095 * 3096 * Params: 3097 * Flags: DDGBS_CANBLT or DDGBS_ISBLTDONE 3098 * 3099 *****************************************************************************/ 3100 static HRESULT WINAPI ddraw_surface7_GetBltStatus(IDirectDrawSurface7 *iface, DWORD Flags) 3101 { 3102 TRACE("iface %p, flags %#x.\n", iface, Flags); 3103 3104 switch (Flags) 3105 { 3106 case WINEDDGBS_CANBLT: 3107 case WINEDDGBS_ISBLTDONE: 3108 return DD_OK; 3109 3110 default: 3111 return DDERR_INVALIDPARAMS; 3112 } 3113 } 3114 3115 static HRESULT WINAPI ddraw_surface4_GetBltStatus(IDirectDrawSurface4 *iface, DWORD flags) 3116 { 3117 struct ddraw_surface *surface = impl_from_IDirectDrawSurface4(iface); 3118 3119 TRACE("iface %p, flags %#x.\n", iface, flags); 3120 3121 return ddraw_surface7_GetBltStatus(&surface->IDirectDrawSurface7_iface, flags); 3122 } 3123 3124 static HRESULT WINAPI ddraw_surface3_GetBltStatus(IDirectDrawSurface3 *iface, DWORD flags) 3125 { 3126 struct ddraw_surface *surface = impl_from_IDirectDrawSurface3(iface); 3127 3128 TRACE("iface %p, flags %#x.\n", iface, flags); 3129 3130 return ddraw_surface7_GetBltStatus(&surface->IDirectDrawSurface7_iface, flags); 3131 } 3132 3133 static HRESULT WINAPI ddraw_surface2_GetBltStatus(IDirectDrawSurface2 *iface, DWORD flags) 3134 { 3135 struct ddraw_surface *surface = impl_from_IDirectDrawSurface2(iface); 3136 3137 TRACE("iface %p, flags %#x.\n", iface, flags); 3138 3139 return ddraw_surface7_GetBltStatus(&surface->IDirectDrawSurface7_iface, flags); 3140 } 3141 3142 static HRESULT WINAPI ddraw_surface1_GetBltStatus(IDirectDrawSurface *iface, DWORD flags) 3143 { 3144 struct ddraw_surface *surface = impl_from_IDirectDrawSurface(iface); 3145 3146 TRACE("iface %p, flags %#x.\n", iface, flags); 3147 3148 return ddraw_surface7_GetBltStatus(&surface->IDirectDrawSurface7_iface, flags); 3149 } 3150 3151 /***************************************************************************** 3152 * IDirectDrawSurface7::GetColorKey 3153 * 3154 * Returns the color key assigned to the surface 3155 * 3156 * Params: 3157 * Flags: Some flags 3158 * CKey: Address to store the key to 3159 * 3160 * Returns: 3161 * DD_OK on success 3162 * DDERR_INVALIDPARAMS if CKey is NULL 3163 * 3164 *****************************************************************************/ 3165 static HRESULT WINAPI ddraw_surface7_GetColorKey(IDirectDrawSurface7 *iface, DWORD Flags, DDCOLORKEY *CKey) 3166 { 3167 struct ddraw_surface *This = impl_from_IDirectDrawSurface7(iface); 3168 3169 TRACE("iface %p, flags %#x, color_key %p.\n", iface, Flags, CKey); 3170 3171 if(!CKey) 3172 return DDERR_INVALIDPARAMS; 3173 3174 wined3d_mutex_lock(); 3175 3176 switch (Flags) 3177 { 3178 case DDCKEY_DESTBLT: 3179 if (!(This->surface_desc.dwFlags & DDSD_CKDESTBLT)) 3180 { 3181 wined3d_mutex_unlock(); 3182 return DDERR_NOCOLORKEY; 3183 } 3184 *CKey = This->surface_desc.ddckCKDestBlt; 3185 break; 3186 3187 case DDCKEY_DESTOVERLAY: 3188 if (!(This->surface_desc.dwFlags & DDSD_CKDESTOVERLAY)) 3189 { 3190 wined3d_mutex_unlock(); 3191 return DDERR_NOCOLORKEY; 3192 } 3193 *CKey = This->surface_desc.u3.ddckCKDestOverlay; 3194 break; 3195 3196 case DDCKEY_SRCBLT: 3197 if (!(This->surface_desc.dwFlags & DDSD_CKSRCBLT)) 3198 { 3199 wined3d_mutex_unlock(); 3200 return DDERR_NOCOLORKEY; 3201 } 3202 *CKey = This->surface_desc.ddckCKSrcBlt; 3203 break; 3204 3205 case DDCKEY_SRCOVERLAY: 3206 if (!(This->surface_desc.dwFlags & DDSD_CKSRCOVERLAY)) 3207 { 3208 wined3d_mutex_unlock(); 3209 return DDERR_NOCOLORKEY; 3210 } 3211 *CKey = This->surface_desc.ddckCKSrcOverlay; 3212 break; 3213 3214 default: 3215 wined3d_mutex_unlock(); 3216 return DDERR_INVALIDPARAMS; 3217 } 3218 3219 wined3d_mutex_unlock(); 3220 3221 return DD_OK; 3222 } 3223 3224 static HRESULT WINAPI ddraw_surface4_GetColorKey(IDirectDrawSurface4 *iface, DWORD flags, DDCOLORKEY *color_key) 3225 { 3226 struct ddraw_surface *surface = impl_from_IDirectDrawSurface4(iface); 3227 3228 TRACE("iface %p, flags %#x, color_key %p.\n", iface, flags, color_key); 3229 3230 return ddraw_surface7_GetColorKey(&surface->IDirectDrawSurface7_iface, flags, color_key); 3231 } 3232 3233 static HRESULT WINAPI ddraw_surface3_GetColorKey(IDirectDrawSurface3 *iface, DWORD flags, DDCOLORKEY *color_key) 3234 { 3235 struct ddraw_surface *surface = impl_from_IDirectDrawSurface3(iface); 3236 3237 TRACE("iface %p, flags %#x, color_key %p.\n", iface, flags, color_key); 3238 3239 return ddraw_surface7_GetColorKey(&surface->IDirectDrawSurface7_iface, flags, color_key); 3240 } 3241 3242 static HRESULT WINAPI ddraw_surface2_GetColorKey(IDirectDrawSurface2 *iface, DWORD flags, DDCOLORKEY *color_key) 3243 { 3244 struct ddraw_surface *surface = impl_from_IDirectDrawSurface2(iface); 3245 3246 TRACE("iface %p, flags %#x, color_key %p.\n", iface, flags, color_key); 3247 3248 return ddraw_surface7_GetColorKey(&surface->IDirectDrawSurface7_iface, flags, color_key); 3249 } 3250 3251 static HRESULT WINAPI ddraw_surface1_GetColorKey(IDirectDrawSurface *iface, DWORD flags, DDCOLORKEY *color_key) 3252 { 3253 struct ddraw_surface *surface = impl_from_IDirectDrawSurface(iface); 3254 3255 TRACE("iface %p, flags %#x, color_key %p.\n", iface, flags, color_key); 3256 3257 return ddraw_surface7_GetColorKey(&surface->IDirectDrawSurface7_iface, flags, color_key); 3258 } 3259 3260 /***************************************************************************** 3261 * IDirectDrawSurface7::GetFlipStatus 3262 * 3263 * Returns the flipping status of the surface 3264 * 3265 * Params: 3266 * Flags: DDGFS_CANFLIP of DDGFS_ISFLIPDONE 3267 * 3268 *****************************************************************************/ 3269 static HRESULT WINAPI ddraw_surface7_GetFlipStatus(IDirectDrawSurface7 *iface, DWORD Flags) 3270 { 3271 TRACE("iface %p, flags %#x.\n", iface, Flags); 3272 3273 /* XXX: DDERR_INVALIDSURFACETYPE */ 3274 3275 switch (Flags) 3276 { 3277 case WINEDDGFS_CANFLIP: 3278 case WINEDDGFS_ISFLIPDONE: 3279 return DD_OK; 3280 3281 default: 3282 return DDERR_INVALIDPARAMS; 3283 } 3284 } 3285 3286 static HRESULT WINAPI ddraw_surface4_GetFlipStatus(IDirectDrawSurface4 *iface, DWORD flags) 3287 { 3288 struct ddraw_surface *surface = impl_from_IDirectDrawSurface4(iface); 3289 3290 TRACE("iface %p, flags %#x.\n", iface, flags); 3291 3292 return ddraw_surface7_GetFlipStatus(&surface->IDirectDrawSurface7_iface, flags); 3293 } 3294 3295 static HRESULT WINAPI ddraw_surface3_GetFlipStatus(IDirectDrawSurface3 *iface, DWORD flags) 3296 { 3297 struct ddraw_surface *surface = impl_from_IDirectDrawSurface3(iface); 3298 3299 TRACE("iface %p, flags %#x.\n", iface, flags); 3300 3301 return ddraw_surface7_GetFlipStatus(&surface->IDirectDrawSurface7_iface, flags); 3302 } 3303 3304 static HRESULT WINAPI ddraw_surface2_GetFlipStatus(IDirectDrawSurface2 *iface, DWORD flags) 3305 { 3306 struct ddraw_surface *surface = impl_from_IDirectDrawSurface2(iface); 3307 3308 TRACE("iface %p, flags %#x.\n", iface, flags); 3309 3310 return ddraw_surface7_GetFlipStatus(&surface->IDirectDrawSurface7_iface, flags); 3311 } 3312 3313 static HRESULT WINAPI ddraw_surface1_GetFlipStatus(IDirectDrawSurface *iface, DWORD flags) 3314 { 3315 struct ddraw_surface *surface = impl_from_IDirectDrawSurface(iface); 3316 3317 TRACE("iface %p, flags %#x.\n", iface, flags); 3318 3319 return ddraw_surface7_GetFlipStatus(&surface->IDirectDrawSurface7_iface, flags); 3320 } 3321 3322 /***************************************************************************** 3323 * IDirectDrawSurface7::GetOverlayPosition 3324 * 3325 * Returns the display coordinates of a visible and active overlay surface 3326 * 3327 * Params: 3328 * X 3329 * Y 3330 * 3331 * Returns: 3332 * DDERR_NOTAOVERLAYSURFACE, because it's a stub 3333 *****************************************************************************/ 3334 static HRESULT WINAPI ddraw_surface7_GetOverlayPosition(IDirectDrawSurface7 *iface, LONG *x, LONG *y) 3335 { 3336 struct ddraw_surface *surface = impl_from_IDirectDrawSurface7(iface); 3337 HRESULT hr; 3338 3339 TRACE("iface %p, x %p, y %p.\n", iface, x, y); 3340 3341 wined3d_mutex_lock(); 3342 hr = wined3d_texture_get_overlay_position(surface->wined3d_texture, 3343 surface->sub_resource_idx, x, y); 3344 wined3d_mutex_unlock(); 3345 3346 return hr; 3347 } 3348 3349 static HRESULT WINAPI ddraw_surface4_GetOverlayPosition(IDirectDrawSurface4 *iface, LONG *x, LONG *y) 3350 { 3351 struct ddraw_surface *surface = impl_from_IDirectDrawSurface4(iface); 3352 3353 TRACE("iface %p, x %p, y %p.\n", iface, x, y); 3354 3355 return ddraw_surface7_GetOverlayPosition(&surface->IDirectDrawSurface7_iface, x, y); 3356 } 3357 3358 static HRESULT WINAPI ddraw_surface3_GetOverlayPosition(IDirectDrawSurface3 *iface, LONG *x, LONG *y) 3359 { 3360 struct ddraw_surface *surface = impl_from_IDirectDrawSurface3(iface); 3361 3362 TRACE("iface %p, x %p, y %p.\n", iface, x, y); 3363 3364 return ddraw_surface7_GetOverlayPosition(&surface->IDirectDrawSurface7_iface, x, y); 3365 } 3366 3367 static HRESULT WINAPI ddraw_surface2_GetOverlayPosition(IDirectDrawSurface2 *iface, LONG *x, LONG *y) 3368 { 3369 struct ddraw_surface *surface = impl_from_IDirectDrawSurface2(iface); 3370 3371 TRACE("iface %p, x %p, y %p.\n", iface, x, y); 3372 3373 return ddraw_surface7_GetOverlayPosition(&surface->IDirectDrawSurface7_iface, x, y); 3374 } 3375 3376 static HRESULT WINAPI ddraw_surface1_GetOverlayPosition(IDirectDrawSurface *iface, LONG *x, LONG *y) 3377 { 3378 struct ddraw_surface *surface = impl_from_IDirectDrawSurface(iface); 3379 3380 TRACE("iface %p, x %p, y %p.\n", iface, x, y); 3381 3382 return ddraw_surface7_GetOverlayPosition(&surface->IDirectDrawSurface7_iface, x, y); 3383 } 3384 3385 /***************************************************************************** 3386 * IDirectDrawSurface7::GetPixelFormat 3387 * 3388 * Returns the pixel format of the Surface 3389 * 3390 * Params: 3391 * PixelFormat: Pointer to a DDPIXELFORMAT structure to which the pixel 3392 * format should be written 3393 * 3394 * Returns: 3395 * DD_OK on success 3396 * DDERR_INVALIDPARAMS if PixelFormat is NULL 3397 * 3398 *****************************************************************************/ 3399 static HRESULT WINAPI ddraw_surface7_GetPixelFormat(IDirectDrawSurface7 *iface, DDPIXELFORMAT *PixelFormat) 3400 { 3401 /* What is DDERR_INVALIDSURFACETYPE for here? */ 3402 struct ddraw_surface *surface = impl_from_IDirectDrawSurface7(iface); 3403 3404 TRACE("iface %p, pixel_format %p.\n", iface, PixelFormat); 3405 3406 if(!PixelFormat) 3407 return DDERR_INVALIDPARAMS; 3408 3409 wined3d_mutex_lock(); 3410 DD_STRUCT_COPY_BYSIZE(PixelFormat, &surface->surface_desc.u4.ddpfPixelFormat); 3411 wined3d_mutex_unlock(); 3412 3413 return DD_OK; 3414 } 3415 3416 static HRESULT WINAPI ddraw_surface4_GetPixelFormat(IDirectDrawSurface4 *iface, DDPIXELFORMAT *pixel_format) 3417 { 3418 struct ddraw_surface *surface = impl_from_IDirectDrawSurface4(iface); 3419 3420 TRACE("iface %p, pixel_format %p.\n", iface, pixel_format); 3421 3422 return ddraw_surface7_GetPixelFormat(&surface->IDirectDrawSurface7_iface, pixel_format); 3423 } 3424 3425 static HRESULT WINAPI ddraw_surface3_GetPixelFormat(IDirectDrawSurface3 *iface, DDPIXELFORMAT *pixel_format) 3426 { 3427 struct ddraw_surface *surface = impl_from_IDirectDrawSurface3(iface); 3428 3429 TRACE("iface %p, pixel_format %p.\n", iface, pixel_format); 3430 3431 return ddraw_surface7_GetPixelFormat(&surface->IDirectDrawSurface7_iface, pixel_format); 3432 } 3433 3434 static HRESULT WINAPI ddraw_surface2_GetPixelFormat(IDirectDrawSurface2 *iface, DDPIXELFORMAT *pixel_format) 3435 { 3436 struct ddraw_surface *surface = impl_from_IDirectDrawSurface2(iface); 3437 3438 TRACE("iface %p, pixel_format %p.\n", iface, pixel_format); 3439 3440 return ddraw_surface7_GetPixelFormat(&surface->IDirectDrawSurface7_iface, pixel_format); 3441 } 3442 3443 static HRESULT WINAPI ddraw_surface1_GetPixelFormat(IDirectDrawSurface *iface, DDPIXELFORMAT *pixel_format) 3444 { 3445 struct ddraw_surface *surface = impl_from_IDirectDrawSurface(iface); 3446 3447 TRACE("iface %p, pixel_format %p.\n", iface, pixel_format); 3448 3449 return ddraw_surface7_GetPixelFormat(&surface->IDirectDrawSurface7_iface, pixel_format); 3450 } 3451 3452 /***************************************************************************** 3453 * IDirectDrawSurface7::GetSurfaceDesc 3454 * 3455 * Returns the description of this surface 3456 * 3457 * Params: 3458 * DDSD: Address of a DDSURFACEDESC2 structure that is to be filled with the 3459 * surface desc 3460 * 3461 * Returns: 3462 * DD_OK on success 3463 * DDERR_INVALIDPARAMS if DDSD is NULL 3464 * 3465 *****************************************************************************/ 3466 static HRESULT WINAPI ddraw_surface7_GetSurfaceDesc(IDirectDrawSurface7 *iface, DDSURFACEDESC2 *DDSD) 3467 { 3468 struct ddraw_surface *surface = impl_from_IDirectDrawSurface7(iface); 3469 3470 TRACE("iface %p, surface_desc %p.\n", iface, DDSD); 3471 3472 if(!DDSD) 3473 return DDERR_INVALIDPARAMS; 3474 3475 if (DDSD->dwSize != sizeof(DDSURFACEDESC2)) 3476 { 3477 WARN("Incorrect struct size %d, returning DDERR_INVALIDPARAMS\n",DDSD->dwSize); 3478 return DDERR_INVALIDPARAMS; 3479 } 3480 3481 wined3d_mutex_lock(); 3482 DD_STRUCT_COPY_BYSIZE(DDSD, &surface->surface_desc); 3483 TRACE("Returning surface desc:\n"); 3484 if (TRACE_ON(ddraw)) DDRAW_dump_surface_desc(DDSD); 3485 wined3d_mutex_unlock(); 3486 3487 return DD_OK; 3488 } 3489 3490 static HRESULT WINAPI ddraw_surface4_GetSurfaceDesc(IDirectDrawSurface4 *iface, DDSURFACEDESC2 *DDSD) 3491 { 3492 struct ddraw_surface *surface = impl_from_IDirectDrawSurface4(iface); 3493 3494 TRACE("iface %p, surface_desc %p.\n", iface, DDSD); 3495 3496 return ddraw_surface7_GetSurfaceDesc(&surface->IDirectDrawSurface7_iface, DDSD); 3497 } 3498 3499 static HRESULT WINAPI ddraw_surface3_GetSurfaceDesc(IDirectDrawSurface3 *iface, DDSURFACEDESC *surface_desc) 3500 { 3501 struct ddraw_surface *surface = impl_from_IDirectDrawSurface3(iface); 3502 3503 TRACE("iface %p, surface_desc %p.\n", iface, surface_desc); 3504 3505 if (!surface_desc) return DDERR_INVALIDPARAMS; 3506 3507 if (surface_desc->dwSize != sizeof(DDSURFACEDESC)) 3508 { 3509 WARN("Incorrect structure size %u, returning DDERR_INVALIDPARAMS.\n", surface_desc->dwSize); 3510 return DDERR_INVALIDPARAMS; 3511 } 3512 3513 wined3d_mutex_lock(); 3514 DDSD2_to_DDSD(&surface->surface_desc, surface_desc); 3515 TRACE("Returning surface desc:\n"); 3516 if (TRACE_ON(ddraw)) 3517 { 3518 /* DDRAW_dump_surface_desc handles the smaller size */ 3519 DDRAW_dump_surface_desc((DDSURFACEDESC2 *)surface_desc); 3520 } 3521 wined3d_mutex_unlock(); 3522 3523 return DD_OK; 3524 } 3525 3526 static HRESULT WINAPI ddraw_surface2_GetSurfaceDesc(IDirectDrawSurface2 *iface, DDSURFACEDESC *DDSD) 3527 { 3528 struct ddraw_surface *surface = impl_from_IDirectDrawSurface2(iface); 3529 3530 TRACE("iface %p, surface_desc %p.\n", iface, DDSD); 3531 3532 return ddraw_surface3_GetSurfaceDesc(&surface->IDirectDrawSurface3_iface, DDSD); 3533 } 3534 3535 static HRESULT WINAPI ddraw_surface1_GetSurfaceDesc(IDirectDrawSurface *iface, DDSURFACEDESC *DDSD) 3536 { 3537 struct ddraw_surface *surface = impl_from_IDirectDrawSurface(iface); 3538 3539 TRACE("iface %p, surface_desc %p.\n", iface, DDSD); 3540 3541 return ddraw_surface3_GetSurfaceDesc(&surface->IDirectDrawSurface3_iface, DDSD); 3542 } 3543 3544 /***************************************************************************** 3545 * IDirectDrawSurface7::Initialize 3546 * 3547 * Initializes the surface. This is a no-op in Wine 3548 * 3549 * Params: 3550 * DD: Pointer to an DirectDraw interface 3551 * DDSD: Surface description for initialization 3552 * 3553 * Returns: 3554 * DDERR_ALREADYINITIALIZED 3555 * 3556 *****************************************************************************/ 3557 static HRESULT WINAPI ddraw_surface7_Initialize(IDirectDrawSurface7 *iface, 3558 IDirectDraw *ddraw, DDSURFACEDESC2 *surface_desc) 3559 { 3560 TRACE("iface %p, ddraw %p, surface_desc %p.\n", iface, ddraw, surface_desc); 3561 3562 return DDERR_ALREADYINITIALIZED; 3563 } 3564 3565 static HRESULT WINAPI ddraw_surface4_Initialize(IDirectDrawSurface4 *iface, 3566 IDirectDraw *ddraw, DDSURFACEDESC2 *surface_desc) 3567 { 3568 struct ddraw_surface *surface = impl_from_IDirectDrawSurface4(iface); 3569 3570 TRACE("iface %p, ddraw %p, surface_desc %p.\n", iface, ddraw, surface_desc); 3571 3572 return ddraw_surface7_Initialize(&surface->IDirectDrawSurface7_iface, 3573 ddraw, surface_desc); 3574 } 3575 3576 static HRESULT WINAPI ddraw_surface3_Initialize(IDirectDrawSurface3 *iface, 3577 IDirectDraw *ddraw, DDSURFACEDESC *surface_desc) 3578 { 3579 struct ddraw_surface *surface = impl_from_IDirectDrawSurface3(iface); 3580 DDSURFACEDESC2 surface_desc2; 3581 3582 TRACE("iface %p, ddraw %p, surface_desc %p.\n", iface, ddraw, surface_desc); 3583 3584 if (surface_desc) DDSD_to_DDSD2(surface_desc, &surface_desc2); 3585 return ddraw_surface7_Initialize(&surface->IDirectDrawSurface7_iface, 3586 ddraw, surface_desc ? &surface_desc2 : NULL); 3587 } 3588 3589 static HRESULT WINAPI ddraw_surface2_Initialize(IDirectDrawSurface2 *iface, 3590 IDirectDraw *ddraw, DDSURFACEDESC *surface_desc) 3591 { 3592 struct ddraw_surface *surface = impl_from_IDirectDrawSurface2(iface); 3593 DDSURFACEDESC2 surface_desc2; 3594 3595 TRACE("iface %p, ddraw %p, surface_desc %p.\n", iface, ddraw, surface_desc); 3596 3597 if (surface_desc) DDSD_to_DDSD2(surface_desc, &surface_desc2); 3598 return ddraw_surface7_Initialize(&surface->IDirectDrawSurface7_iface, 3599 ddraw, surface_desc ? &surface_desc2 : NULL); 3600 } 3601 3602 static HRESULT WINAPI ddraw_surface1_Initialize(IDirectDrawSurface *iface, 3603 IDirectDraw *ddraw, DDSURFACEDESC *surface_desc) 3604 { 3605 struct ddraw_surface *surface = impl_from_IDirectDrawSurface(iface); 3606 DDSURFACEDESC2 surface_desc2; 3607 3608 TRACE("iface %p, ddraw %p, surface_desc %p.\n", iface, ddraw, surface_desc); 3609 3610 if (surface_desc) DDSD_to_DDSD2(surface_desc, &surface_desc2); 3611 return ddraw_surface7_Initialize(&surface->IDirectDrawSurface7_iface, 3612 ddraw, surface_desc ? &surface_desc2 : NULL); 3613 } 3614 3615 /***************************************************************************** 3616 * IDirect3DTexture1::Initialize 3617 * 3618 * The sdk says it's not implemented 3619 * 3620 * Params: 3621 * ? 3622 * 3623 * Returns 3624 * DDERR_UNSUPPORTED 3625 * 3626 *****************************************************************************/ 3627 static HRESULT WINAPI d3d_texture1_Initialize(IDirect3DTexture *iface, 3628 IDirect3DDevice *device, IDirectDrawSurface *surface) 3629 { 3630 TRACE("iface %p, device %p, surface %p.\n", iface, device, surface); 3631 3632 return DDERR_UNSUPPORTED; /* Unchecked */ 3633 } 3634 3635 /***************************************************************************** 3636 * IDirectDrawSurface7::IsLost 3637 * 3638 * Checks if the surface is lost 3639 * 3640 * Returns: 3641 * DD_OK, if the surface is usable 3642 * DDERR_ISLOST if the surface is lost 3643 * 3644 *****************************************************************************/ 3645 static HRESULT WINAPI ddraw_surface7_IsLost(IDirectDrawSurface7 *iface) 3646 { 3647 struct ddraw_surface *surface = impl_from_IDirectDrawSurface7(iface); 3648 3649 TRACE("iface %p.\n", iface); 3650 3651 if (surface->ddraw->device_state != DDRAW_DEVICE_STATE_OK || surface->is_lost) 3652 return DDERR_SURFACELOST; 3653 3654 return DD_OK; 3655 } 3656 3657 static HRESULT WINAPI ddraw_surface4_IsLost(IDirectDrawSurface4 *iface) 3658 { 3659 struct ddraw_surface *surface = impl_from_IDirectDrawSurface4(iface); 3660 3661 TRACE("iface %p.\n", iface); 3662 3663 return ddraw_surface7_IsLost(&surface->IDirectDrawSurface7_iface); 3664 } 3665 3666 static HRESULT WINAPI ddraw_surface3_IsLost(IDirectDrawSurface3 *iface) 3667 { 3668 struct ddraw_surface *surface = impl_from_IDirectDrawSurface3(iface); 3669 3670 TRACE("iface %p.\n", iface); 3671 3672 return ddraw_surface7_IsLost(&surface->IDirectDrawSurface7_iface); 3673 } 3674 3675 static HRESULT WINAPI ddraw_surface2_IsLost(IDirectDrawSurface2 *iface) 3676 { 3677 struct ddraw_surface *surface = impl_from_IDirectDrawSurface2(iface); 3678 3679 TRACE("iface %p.\n", iface); 3680 3681 return ddraw_surface7_IsLost(&surface->IDirectDrawSurface7_iface); 3682 } 3683 3684 static HRESULT WINAPI ddraw_surface1_IsLost(IDirectDrawSurface *iface) 3685 { 3686 struct ddraw_surface *surface = impl_from_IDirectDrawSurface(iface); 3687 3688 TRACE("iface %p.\n", iface); 3689 3690 return ddraw_surface7_IsLost(&surface->IDirectDrawSurface7_iface); 3691 } 3692 3693 /***************************************************************************** 3694 * IDirectDrawSurface7::Restore 3695 * 3696 * Restores a lost surface. This makes the surface usable again, but 3697 * doesn't reload its old contents 3698 * 3699 * Returns: 3700 * DD_OK on success, error code otherwise. 3701 * 3702 *****************************************************************************/ 3703 static HRESULT WINAPI ddraw_surface7_Restore(IDirectDrawSurface7 *iface) 3704 { 3705 struct ddraw_surface *surface = impl_from_IDirectDrawSurface7(iface); 3706 3707 TRACE("iface %p.\n", iface); 3708 3709 if (surface->surface_desc.ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE) 3710 { 3711 struct wined3d_swapchain *swapchain = surface->ddraw->wined3d_swapchain; 3712 struct wined3d_sub_resource_desc wined3d_desc; 3713 struct wined3d_display_mode mode; 3714 HRESULT hr; 3715 3716 if (FAILED(hr = wined3d_swapchain_get_display_mode(swapchain, &mode, NULL))) 3717 { 3718 WARN("Failed to get display mode, hr %#x.\n", hr); 3719 return hr; 3720 } 3721 3722 if (FAILED(hr = wined3d_texture_get_sub_resource_desc(surface->wined3d_texture, 0, &wined3d_desc))) 3723 { 3724 WARN("Failed to get resource desc, hr %#x.\n", hr); 3725 return hr; 3726 } 3727 3728 if (mode.width != wined3d_desc.width || mode.height != wined3d_desc.height) 3729 { 3730 WARN("Display mode dimensions %ux%u don't match surface dimensions %ux%u.\n", 3731 mode.width, mode.height, wined3d_desc.width, wined3d_desc.height); 3732 return DDERR_WRONGMODE; 3733 } 3734 3735 if (mode.format_id != wined3d_desc.format) 3736 { 3737 WARN("Display mode format %#x doesn't match surface format %#x.\n", 3738 mode.format_id, wined3d_desc.format); 3739 return DDERR_WRONGMODE; 3740 } 3741 } 3742 3743 ddraw_update_lost_surfaces(surface->ddraw); 3744 surface->is_lost = FALSE; 3745 3746 return DD_OK; 3747 } 3748 3749 static HRESULT WINAPI ddraw_surface4_Restore(IDirectDrawSurface4 *iface) 3750 { 3751 struct ddraw_surface *surface = impl_from_IDirectDrawSurface4(iface); 3752 3753 TRACE("iface %p.\n", iface); 3754 3755 return ddraw_surface7_Restore(&surface->IDirectDrawSurface7_iface); 3756 } 3757 3758 static HRESULT WINAPI ddraw_surface3_Restore(IDirectDrawSurface3 *iface) 3759 { 3760 struct ddraw_surface *surface = impl_from_IDirectDrawSurface3(iface); 3761 3762 TRACE("iface %p.\n", iface); 3763 3764 return ddraw_surface7_Restore(&surface->IDirectDrawSurface7_iface); 3765 } 3766 3767 static HRESULT WINAPI ddraw_surface2_Restore(IDirectDrawSurface2 *iface) 3768 { 3769 struct ddraw_surface *surface = impl_from_IDirectDrawSurface2(iface); 3770 3771 TRACE("iface %p.\n", iface); 3772 3773 return ddraw_surface7_Restore(&surface->IDirectDrawSurface7_iface); 3774 } 3775 3776 static HRESULT WINAPI ddraw_surface1_Restore(IDirectDrawSurface *iface) 3777 { 3778 struct ddraw_surface *surface = impl_from_IDirectDrawSurface(iface); 3779 3780 TRACE("iface %p.\n", iface); 3781 3782 return ddraw_surface7_Restore(&surface->IDirectDrawSurface7_iface); 3783 } 3784 3785 /***************************************************************************** 3786 * IDirectDrawSurface7::SetOverlayPosition 3787 * 3788 * Changes the display coordinates of an overlay surface 3789 * 3790 * Params: 3791 * X: 3792 * Y: 3793 * 3794 * Returns: 3795 * DDERR_NOTAOVERLAYSURFACE, because we don't support overlays right now 3796 *****************************************************************************/ 3797 static HRESULT WINAPI ddraw_surface7_SetOverlayPosition(IDirectDrawSurface7 *iface, LONG x, LONG y) 3798 { 3799 struct ddraw_surface *surface = impl_from_IDirectDrawSurface7(iface); 3800 HRESULT hr; 3801 3802 TRACE("iface %p, x %d, y %d.\n", iface, x, y); 3803 3804 wined3d_mutex_lock(); 3805 hr = wined3d_texture_set_overlay_position(surface->wined3d_texture, 3806 surface->sub_resource_idx, x, y); 3807 wined3d_mutex_unlock(); 3808 3809 return hr; 3810 } 3811 3812 static HRESULT WINAPI ddraw_surface4_SetOverlayPosition(IDirectDrawSurface4 *iface, LONG x, LONG y) 3813 { 3814 struct ddraw_surface *surface = impl_from_IDirectDrawSurface4(iface); 3815 3816 TRACE("iface %p, x %d, y %d.\n", iface, x, y); 3817 3818 return ddraw_surface7_SetOverlayPosition(&surface->IDirectDrawSurface7_iface, x, y); 3819 } 3820 3821 static HRESULT WINAPI ddraw_surface3_SetOverlayPosition(IDirectDrawSurface3 *iface, LONG x, LONG y) 3822 { 3823 struct ddraw_surface *surface = impl_from_IDirectDrawSurface3(iface); 3824 3825 TRACE("iface %p, x %d, y %d.\n", iface, x, y); 3826 3827 return ddraw_surface7_SetOverlayPosition(&surface->IDirectDrawSurface7_iface, x, y); 3828 } 3829 3830 static HRESULT WINAPI ddraw_surface2_SetOverlayPosition(IDirectDrawSurface2 *iface, LONG x, LONG y) 3831 { 3832 struct ddraw_surface *surface = impl_from_IDirectDrawSurface2(iface); 3833 3834 TRACE("iface %p, x %d, y %d.\n", iface, x, y); 3835 3836 return ddraw_surface7_SetOverlayPosition(&surface->IDirectDrawSurface7_iface, x, y); 3837 } 3838 3839 static HRESULT WINAPI ddraw_surface1_SetOverlayPosition(IDirectDrawSurface *iface, LONG x, LONG y) 3840 { 3841 struct ddraw_surface *surface = impl_from_IDirectDrawSurface(iface); 3842 3843 TRACE("iface %p, x %d, y %d.\n", iface, x, y); 3844 3845 return ddraw_surface7_SetOverlayPosition(&surface->IDirectDrawSurface7_iface, x, y); 3846 } 3847 3848 /***************************************************************************** 3849 * IDirectDrawSurface7::UpdateOverlay 3850 * 3851 * Modifies the attributes of an overlay surface. 3852 * 3853 * Params: 3854 * SrcRect: The section of the source being used for the overlay 3855 * DstSurface: Address of the surface that is overlaid 3856 * DstRect: Place of the overlay 3857 * Flags: some DDOVER_* flags 3858 * 3859 * Returns: 3860 * DDERR_UNSUPPORTED, because we don't support overlays 3861 * 3862 *****************************************************************************/ 3863 static HRESULT WINAPI ddraw_surface7_UpdateOverlay(IDirectDrawSurface7 *iface, RECT *src_rect, 3864 IDirectDrawSurface7 *dst_surface, RECT *dst_rect, DWORD flags, DDOVERLAYFX *fx) 3865 { 3866 struct ddraw_surface *src_impl = impl_from_IDirectDrawSurface7(iface); 3867 struct ddraw_surface *dst_impl = unsafe_impl_from_IDirectDrawSurface7(dst_surface); 3868 struct wined3d_texture *dst_wined3d_texture = NULL; 3869 unsigned int dst_sub_resource_idx = 0; 3870 HRESULT hr; 3871 3872 TRACE("iface %p, src_rect %s, dst_surface %p, dst_rect %s, flags %#x, fx %p.\n", 3873 iface, wine_dbgstr_rect(src_rect), dst_surface, wine_dbgstr_rect(dst_rect), flags, fx); 3874 3875 if (fx) 3876 FIXME("Ignoring fx %p.\n", fx); 3877 3878 wined3d_mutex_lock(); 3879 if (dst_impl) 3880 { 3881 dst_wined3d_texture = dst_impl->wined3d_texture; 3882 dst_sub_resource_idx = dst_impl->sub_resource_idx; 3883 } 3884 hr = wined3d_texture_update_overlay(src_impl->wined3d_texture, src_impl->sub_resource_idx, 3885 src_rect, dst_wined3d_texture, dst_sub_resource_idx, dst_rect, flags); 3886 wined3d_mutex_unlock(); 3887 3888 switch (hr) 3889 { 3890 case WINED3DERR_INVALIDCALL: return DDERR_INVALIDPARAMS; 3891 case WINEDDERR_NOTAOVERLAYSURFACE: return DDERR_NOTAOVERLAYSURFACE; 3892 case WINEDDERR_OVERLAYNOTVISIBLE: return DDERR_OVERLAYNOTVISIBLE; 3893 default: 3894 return hr; 3895 } 3896 } 3897 3898 static HRESULT WINAPI ddraw_surface4_UpdateOverlay(IDirectDrawSurface4 *iface, RECT *src_rect, 3899 IDirectDrawSurface4 *dst_surface, RECT *dst_rect, DWORD flags, DDOVERLAYFX *fx) 3900 { 3901 struct ddraw_surface *src_impl = impl_from_IDirectDrawSurface4(iface); 3902 struct ddraw_surface *dst_impl = unsafe_impl_from_IDirectDrawSurface4(dst_surface); 3903 3904 TRACE("iface %p, src_rect %s, dst_surface %p, dst_rect %s, flags %#x, fx %p.\n", 3905 iface, wine_dbgstr_rect(src_rect), dst_surface, wine_dbgstr_rect(dst_rect), flags, fx); 3906 3907 return ddraw_surface7_UpdateOverlay(&src_impl->IDirectDrawSurface7_iface, src_rect, 3908 dst_impl ? &dst_impl->IDirectDrawSurface7_iface : NULL, dst_rect, flags, fx); 3909 } 3910 3911 static HRESULT WINAPI ddraw_surface3_UpdateOverlay(IDirectDrawSurface3 *iface, RECT *src_rect, 3912 IDirectDrawSurface3 *dst_surface, RECT *dst_rect, DWORD flags, DDOVERLAYFX *fx) 3913 { 3914 struct ddraw_surface *src_impl = impl_from_IDirectDrawSurface3(iface); 3915 struct ddraw_surface *dst_impl = unsafe_impl_from_IDirectDrawSurface3(dst_surface); 3916 3917 TRACE("iface %p, src_rect %s, dst_surface %p, dst_rect %s, flags %#x, fx %p.\n", 3918 iface, wine_dbgstr_rect(src_rect), dst_surface, wine_dbgstr_rect(dst_rect), flags, fx); 3919 3920 return ddraw_surface7_UpdateOverlay(&src_impl->IDirectDrawSurface7_iface, src_rect, 3921 dst_impl ? &dst_impl->IDirectDrawSurface7_iface : NULL, dst_rect, flags, fx); 3922 } 3923 3924 static HRESULT WINAPI ddraw_surface2_UpdateOverlay(IDirectDrawSurface2 *iface, RECT *src_rect, 3925 IDirectDrawSurface2 *dst_surface, RECT *dst_rect, DWORD flags, DDOVERLAYFX *fx) 3926 { 3927 struct ddraw_surface *src_impl = impl_from_IDirectDrawSurface2(iface); 3928 struct ddraw_surface *dst_impl = unsafe_impl_from_IDirectDrawSurface2(dst_surface); 3929 3930 TRACE("iface %p, src_rect %s, dst_surface %p, dst_rect %s, flags %#x, fx %p.\n", 3931 iface, wine_dbgstr_rect(src_rect), dst_surface, wine_dbgstr_rect(dst_rect), flags, fx); 3932 3933 return ddraw_surface7_UpdateOverlay(&src_impl->IDirectDrawSurface7_iface, src_rect, 3934 dst_impl ? &dst_impl->IDirectDrawSurface7_iface : NULL, dst_rect, flags, fx); 3935 } 3936 3937 static HRESULT WINAPI ddraw_surface1_UpdateOverlay(IDirectDrawSurface *iface, RECT *src_rect, 3938 IDirectDrawSurface *dst_surface, RECT *dst_rect, DWORD flags, DDOVERLAYFX *fx) 3939 { 3940 struct ddraw_surface *src_impl = impl_from_IDirectDrawSurface(iface); 3941 struct ddraw_surface *dst_impl = unsafe_impl_from_IDirectDrawSurface(dst_surface); 3942 3943 TRACE("iface %p, src_rect %s, dst_surface %p, dst_rect %s, flags %#x, fx %p.\n", 3944 iface, wine_dbgstr_rect(src_rect), dst_surface, wine_dbgstr_rect(dst_rect), flags, fx); 3945 3946 return ddraw_surface7_UpdateOverlay(&src_impl->IDirectDrawSurface7_iface, src_rect, 3947 dst_impl ? &dst_impl->IDirectDrawSurface7_iface : NULL, dst_rect, flags, fx); 3948 } 3949 3950 /***************************************************************************** 3951 * IDirectDrawSurface7::UpdateOverlayDisplay 3952 * 3953 * The DX7 sdk says that it's not implemented 3954 * 3955 * Params: 3956 * Flags: ? 3957 * 3958 * Returns: DDERR_UNSUPPORTED, because we don't support overlays 3959 * 3960 *****************************************************************************/ 3961 static HRESULT WINAPI ddraw_surface7_UpdateOverlayDisplay(IDirectDrawSurface7 *iface, DWORD Flags) 3962 { 3963 TRACE("iface %p, flags %#x.\n", iface, Flags); 3964 3965 return DDERR_UNSUPPORTED; 3966 } 3967 3968 static HRESULT WINAPI ddraw_surface4_UpdateOverlayDisplay(IDirectDrawSurface4 *iface, DWORD flags) 3969 { 3970 struct ddraw_surface *surface = impl_from_IDirectDrawSurface4(iface); 3971 3972 TRACE("iface %p, flags %#x.\n", iface, flags); 3973 3974 return ddraw_surface7_UpdateOverlayDisplay(&surface->IDirectDrawSurface7_iface, flags); 3975 } 3976 3977 static HRESULT WINAPI ddraw_surface3_UpdateOverlayDisplay(IDirectDrawSurface3 *iface, DWORD flags) 3978 { 3979 struct ddraw_surface *surface = impl_from_IDirectDrawSurface3(iface); 3980 3981 TRACE("iface %p, flags %#x.\n", iface, flags); 3982 3983 return ddraw_surface7_UpdateOverlayDisplay(&surface->IDirectDrawSurface7_iface, flags); 3984 } 3985 3986 static HRESULT WINAPI ddraw_surface2_UpdateOverlayDisplay(IDirectDrawSurface2 *iface, DWORD flags) 3987 { 3988 struct ddraw_surface *surface = impl_from_IDirectDrawSurface2(iface); 3989 3990 TRACE("iface %p, flags %#x.\n", iface, flags); 3991 3992 return ddraw_surface7_UpdateOverlayDisplay(&surface->IDirectDrawSurface7_iface, flags); 3993 } 3994 3995 static HRESULT WINAPI ddraw_surface1_UpdateOverlayDisplay(IDirectDrawSurface *iface, DWORD flags) 3996 { 3997 struct ddraw_surface *surface = impl_from_IDirectDrawSurface(iface); 3998 3999 TRACE("iface %p, flags %#x.\n", iface, flags); 4000 4001 return ddraw_surface7_UpdateOverlayDisplay(&surface->IDirectDrawSurface7_iface, flags); 4002 } 4003 4004 /***************************************************************************** 4005 * IDirectDrawSurface7::UpdateOverlayZOrder 4006 * 4007 * Sets an overlay's Z order 4008 * 4009 * Params: 4010 * Flags: DDOVERZ_* flags 4011 * DDSRef: Defines the relative position in the overlay chain 4012 * 4013 * Returns: 4014 * DDERR_NOTOVERLAYSURFACE, because we don't support overlays 4015 * 4016 *****************************************************************************/ 4017 static HRESULT WINAPI ddraw_surface7_UpdateOverlayZOrder(IDirectDrawSurface7 *iface, 4018 DWORD flags, IDirectDrawSurface7 *reference) 4019 { 4020 struct ddraw_surface *surface = impl_from_IDirectDrawSurface7(iface); 4021 4022 FIXME("iface %p, flags %#x, reference %p stub!\n", iface, flags, reference); 4023 4024 wined3d_mutex_lock(); 4025 if (!(surface->surface_desc.ddsCaps.dwCaps & DDSCAPS_OVERLAY)) 4026 { 4027 WARN("Not an overlay surface.\n"); 4028 wined3d_mutex_unlock(); 4029 return DDERR_NOTAOVERLAYSURFACE; 4030 } 4031 wined3d_mutex_unlock(); 4032 4033 return DD_OK; 4034 } 4035 4036 static HRESULT WINAPI ddraw_surface4_UpdateOverlayZOrder(IDirectDrawSurface4 *iface, 4037 DWORD flags, IDirectDrawSurface4 *reference) 4038 { 4039 struct ddraw_surface *surface = impl_from_IDirectDrawSurface4(iface); 4040 struct ddraw_surface *reference_impl = unsafe_impl_from_IDirectDrawSurface4(reference); 4041 4042 TRACE("iface %p, flags %#x, reference %p.\n", iface, flags, reference); 4043 4044 return ddraw_surface7_UpdateOverlayZOrder(&surface->IDirectDrawSurface7_iface, flags, 4045 reference_impl ? &reference_impl->IDirectDrawSurface7_iface : NULL); 4046 } 4047 4048 static HRESULT WINAPI ddraw_surface3_UpdateOverlayZOrder(IDirectDrawSurface3 *iface, 4049 DWORD flags, IDirectDrawSurface3 *reference) 4050 { 4051 struct ddraw_surface *surface = impl_from_IDirectDrawSurface3(iface); 4052 struct ddraw_surface *reference_impl = unsafe_impl_from_IDirectDrawSurface3(reference); 4053 4054 TRACE("iface %p, flags %#x, reference %p.\n", iface, flags, reference); 4055 4056 return ddraw_surface7_UpdateOverlayZOrder(&surface->IDirectDrawSurface7_iface, flags, 4057 reference_impl ? &reference_impl->IDirectDrawSurface7_iface : NULL); 4058 } 4059 4060 static HRESULT WINAPI ddraw_surface2_UpdateOverlayZOrder(IDirectDrawSurface2 *iface, 4061 DWORD flags, IDirectDrawSurface2 *reference) 4062 { 4063 struct ddraw_surface *surface = impl_from_IDirectDrawSurface2(iface); 4064 struct ddraw_surface *reference_impl = unsafe_impl_from_IDirectDrawSurface2(reference); 4065 4066 TRACE("iface %p, flags %#x, reference %p.\n", iface, flags, reference); 4067 4068 return ddraw_surface7_UpdateOverlayZOrder(&surface->IDirectDrawSurface7_iface, flags, 4069 reference_impl ? &reference_impl->IDirectDrawSurface7_iface : NULL); 4070 } 4071 4072 static HRESULT WINAPI ddraw_surface1_UpdateOverlayZOrder(IDirectDrawSurface *iface, 4073 DWORD flags, IDirectDrawSurface *reference) 4074 { 4075 struct ddraw_surface *surface = impl_from_IDirectDrawSurface(iface); 4076 struct ddraw_surface *reference_impl = unsafe_impl_from_IDirectDrawSurface(reference); 4077 4078 TRACE("iface %p, flags %#x, reference %p.\n", iface, flags, reference); 4079 4080 return ddraw_surface7_UpdateOverlayZOrder(&surface->IDirectDrawSurface7_iface, flags, 4081 reference_impl ? &reference_impl->IDirectDrawSurface7_iface : NULL); 4082 } 4083 4084 /***************************************************************************** 4085 * IDirectDrawSurface7::GetDDInterface 4086 * 4087 * Returns the IDirectDraw7 interface pointer of the DirectDraw object this 4088 * surface belongs to 4089 * 4090 * Params: 4091 * DD: Address to write the interface pointer to 4092 * 4093 * Returns: 4094 * DD_OK on success 4095 * DDERR_INVALIDPARAMS if DD is NULL 4096 * 4097 *****************************************************************************/ 4098 static HRESULT WINAPI ddraw_surface7_GetDDInterface(IDirectDrawSurface7 *iface, void **DD) 4099 { 4100 struct ddraw_surface *This = impl_from_IDirectDrawSurface7(iface); 4101 4102 TRACE("iface %p, ddraw %p.\n", iface, DD); 4103 4104 if(!DD) 4105 return DDERR_INVALIDPARAMS; 4106 4107 switch(This->version) 4108 { 4109 case 7: 4110 *DD = &This->ddraw->IDirectDraw7_iface; 4111 break; 4112 4113 case 4: 4114 *DD = &This->ddraw->IDirectDraw4_iface; 4115 break; 4116 4117 case 2: 4118 *DD = &This->ddraw->IDirectDraw2_iface; 4119 break; 4120 4121 case 1: 4122 *DD = &This->ddraw->IDirectDraw_iface; 4123 break; 4124 4125 } 4126 IUnknown_AddRef((IUnknown *)*DD); 4127 4128 return DD_OK; 4129 } 4130 4131 static HRESULT WINAPI ddraw_surface4_GetDDInterface(IDirectDrawSurface4 *iface, void **ddraw) 4132 { 4133 struct ddraw_surface *surface = impl_from_IDirectDrawSurface4(iface); 4134 4135 TRACE("iface %p, ddraw %p.\n", iface, ddraw); 4136 4137 return ddraw_surface7_GetDDInterface(&surface->IDirectDrawSurface7_iface, ddraw); 4138 } 4139 4140 static HRESULT WINAPI ddraw_surface3_GetDDInterface(IDirectDrawSurface3 *iface, void **ddraw) 4141 { 4142 struct ddraw_surface *surface = impl_from_IDirectDrawSurface3(iface); 4143 4144 TRACE("iface %p, ddraw %p.\n", iface, ddraw); 4145 4146 return ddraw_surface7_GetDDInterface(&surface->IDirectDrawSurface7_iface, ddraw); 4147 } 4148 4149 static HRESULT WINAPI ddraw_surface2_GetDDInterface(IDirectDrawSurface2 *iface, void **ddraw) 4150 { 4151 struct ddraw_surface *surface = impl_from_IDirectDrawSurface2(iface); 4152 4153 TRACE("iface %p, ddraw %p.\n", iface, ddraw); 4154 4155 return ddraw_surface7_GetDDInterface(&surface->IDirectDrawSurface7_iface, ddraw); 4156 } 4157 4158 static HRESULT WINAPI ddraw_surface7_ChangeUniquenessValue(IDirectDrawSurface7 *iface) 4159 { 4160 TRACE("iface %p.\n", iface); 4161 4162 return DD_OK; 4163 } 4164 4165 static HRESULT WINAPI ddraw_surface4_ChangeUniquenessValue(IDirectDrawSurface4 *iface) 4166 { 4167 struct ddraw_surface *surface = impl_from_IDirectDrawSurface4(iface); 4168 4169 TRACE("iface %p.\n", iface); 4170 4171 return ddraw_surface7_ChangeUniquenessValue(&surface->IDirectDrawSurface7_iface); 4172 } 4173 4174 static HRESULT WINAPI ddraw_surface7_GetUniquenessValue(IDirectDrawSurface7 *iface, DWORD *pValue) 4175 { 4176 TRACE("iface %p, value %p.\n", iface, pValue); 4177 4178 *pValue = 0; 4179 4180 return DD_OK; 4181 } 4182 4183 static HRESULT WINAPI ddraw_surface4_GetUniquenessValue(IDirectDrawSurface4 *iface, DWORD *pValue) 4184 { 4185 struct ddraw_surface *surface = impl_from_IDirectDrawSurface4(iface); 4186 4187 TRACE("iface %p, value %p.\n", iface, pValue); 4188 4189 return ddraw_surface7_GetUniquenessValue(&surface->IDirectDrawSurface7_iface, pValue); 4190 } 4191 4192 /***************************************************************************** 4193 * IDirectDrawSurface7::SetLOD 4194 * 4195 * Sets the level of detail of a texture 4196 * 4197 * Params: 4198 * MaxLOD: LOD to set 4199 * 4200 * Returns: 4201 * DD_OK on success 4202 * DDERR_INVALIDOBJECT if the surface is invalid for this method 4203 * 4204 *****************************************************************************/ 4205 static HRESULT WINAPI ddraw_surface7_SetLOD(IDirectDrawSurface7 *iface, DWORD MaxLOD) 4206 { 4207 struct ddraw_surface *surface = impl_from_IDirectDrawSurface7(iface); 4208 HRESULT hr; 4209 4210 TRACE("iface %p, lod %u.\n", iface, MaxLOD); 4211 4212 wined3d_mutex_lock(); 4213 if (!(surface->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_TEXTUREMANAGE)) 4214 { 4215 wined3d_mutex_unlock(); 4216 return DDERR_INVALIDOBJECT; 4217 } 4218 4219 hr = wined3d_texture_set_lod(surface->wined3d_texture, MaxLOD); 4220 wined3d_mutex_unlock(); 4221 4222 return hr; 4223 } 4224 4225 /***************************************************************************** 4226 * IDirectDrawSurface7::GetLOD 4227 * 4228 * Returns the level of detail of a Direct3D texture 4229 * 4230 * Params: 4231 * MaxLOD: Address to write the LOD to 4232 * 4233 * Returns: 4234 * DD_OK on success 4235 * DDERR_INVALIDPARAMS if MaxLOD is NULL 4236 * DDERR_INVALIDOBJECT if the surface is invalid for this method 4237 * 4238 *****************************************************************************/ 4239 static HRESULT WINAPI ddraw_surface7_GetLOD(IDirectDrawSurface7 *iface, DWORD *MaxLOD) 4240 { 4241 struct ddraw_surface *surface = impl_from_IDirectDrawSurface7(iface); 4242 4243 TRACE("iface %p, lod %p.\n", iface, MaxLOD); 4244 4245 if(!MaxLOD) 4246 return DDERR_INVALIDPARAMS; 4247 4248 wined3d_mutex_lock(); 4249 if (!(surface->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_TEXTUREMANAGE)) 4250 { 4251 wined3d_mutex_unlock(); 4252 return DDERR_INVALIDOBJECT; 4253 } 4254 4255 *MaxLOD = wined3d_texture_get_lod(surface->wined3d_texture); 4256 wined3d_mutex_unlock(); 4257 4258 return DD_OK; 4259 } 4260 4261 /***************************************************************************** 4262 * IDirectDrawSurface7::BltFast 4263 * 4264 * Performs a fast Blit. 4265 * 4266 * Params: 4267 * dstx: The x coordinate to blit to on the destination 4268 * dsty: The y coordinate to blit to on the destination 4269 * Source: The source surface 4270 * rsrc: The source rectangle 4271 * trans: Type of transfer. Some DDBLTFAST_* flags 4272 * 4273 * Returns: 4274 * DD_OK on success, error code otherwise. 4275 * 4276 *****************************************************************************/ 4277 static HRESULT WINAPI DECLSPEC_HOTPATCH ddraw_surface7_BltFast(IDirectDrawSurface7 *iface, 4278 DWORD dst_x, DWORD dst_y, IDirectDrawSurface7 *src_surface, RECT *src_rect, DWORD trans) 4279 { 4280 struct ddraw_surface *dst_impl = impl_from_IDirectDrawSurface7(iface); 4281 struct ddraw_surface *src_impl = unsafe_impl_from_IDirectDrawSurface7(src_surface); 4282 DWORD flags = WINED3D_BLT_SYNCHRONOUS; 4283 DWORD src_w, src_h, dst_w, dst_h; 4284 HRESULT hr = DD_OK; 4285 RECT dst_rect, s; 4286 4287 TRACE("iface %p, dst_x %u, dst_y %u, src_surface %p, src_rect %s, flags %#x.\n", 4288 iface, dst_x, dst_y, src_surface, wine_dbgstr_rect(src_rect), trans); 4289 4290 dst_w = dst_impl->surface_desc.dwWidth; 4291 dst_h = dst_impl->surface_desc.dwHeight; 4292 4293 if (!src_rect) 4294 { 4295 SetRect(&s, 0, 0, src_impl->surface_desc.dwWidth, src_impl->surface_desc.dwHeight); 4296 src_rect = &s; 4297 } 4298 4299 src_w = src_rect->right - src_rect->left; 4300 src_h = src_rect->bottom - src_rect->top; 4301 if (src_w > dst_w || dst_x > dst_w - src_w 4302 || src_h > dst_h || dst_y > dst_h - src_h) 4303 { 4304 WARN("Destination area out of bounds, returning DDERR_INVALIDRECT.\n"); 4305 return DDERR_INVALIDRECT; 4306 } 4307 4308 SetRect(&dst_rect, dst_x, dst_y, dst_x + src_w, dst_y + src_h); 4309 if (trans & DDBLTFAST_SRCCOLORKEY) 4310 flags |= WINED3D_BLT_SRC_CKEY; 4311 if (trans & DDBLTFAST_DESTCOLORKEY) 4312 flags |= WINED3D_BLT_DST_CKEY; 4313 if (trans & DDBLTFAST_WAIT) 4314 flags |= WINED3D_BLT_WAIT; 4315 if (trans & DDBLTFAST_DONOTWAIT) 4316 flags |= WINED3D_BLT_DO_NOT_WAIT; 4317 4318 wined3d_mutex_lock(); 4319 if (dst_impl->clipper) 4320 { 4321 wined3d_mutex_unlock(); 4322 WARN("Destination surface has a clipper set, returning DDERR_BLTFASTCANTCLIP.\n"); 4323 return DDERR_BLTFASTCANTCLIP; 4324 } 4325 4326 if (src_impl->surface_desc.ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE) 4327 hr = ddraw_surface_update_frontbuffer(src_impl, src_rect, TRUE, 0); 4328 if (SUCCEEDED(hr)) 4329 hr = wined3d_texture_blt(dst_impl->wined3d_texture, dst_impl->sub_resource_idx, &dst_rect, 4330 src_impl->wined3d_texture, src_impl->sub_resource_idx, src_rect, flags, NULL, WINED3D_TEXF_POINT); 4331 if (SUCCEEDED(hr) && (dst_impl->surface_desc.ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE)) 4332 hr = ddraw_surface_update_frontbuffer(dst_impl, &dst_rect, FALSE, 0); 4333 wined3d_mutex_unlock(); 4334 4335 switch(hr) 4336 { 4337 case WINED3DERR_NOTAVAILABLE: return DDERR_UNSUPPORTED; 4338 default: return hr; 4339 } 4340 } 4341 4342 static HRESULT WINAPI DECLSPEC_HOTPATCH ddraw_surface4_BltFast(IDirectDrawSurface4 *iface, DWORD dst_x, DWORD dst_y, 4343 IDirectDrawSurface4 *src_surface, RECT *src_rect, DWORD flags) 4344 { 4345 struct ddraw_surface *dst_impl = impl_from_IDirectDrawSurface4(iface); 4346 struct ddraw_surface *src_impl = unsafe_impl_from_IDirectDrawSurface4(src_surface); 4347 4348 TRACE("iface %p, dst_x %u, dst_y %u, src_surface %p, src_rect %s, flags %#x.\n", 4349 iface, dst_x, dst_y, src_surface, wine_dbgstr_rect(src_rect), flags); 4350 4351 return ddraw_surface7_BltFast(&dst_impl->IDirectDrawSurface7_iface, dst_x, dst_y, 4352 src_impl ? &src_impl->IDirectDrawSurface7_iface : NULL, src_rect, flags); 4353 } 4354 4355 static HRESULT WINAPI DECLSPEC_HOTPATCH ddraw_surface3_BltFast(IDirectDrawSurface3 *iface, DWORD dst_x, DWORD dst_y, 4356 IDirectDrawSurface3 *src_surface, RECT *src_rect, DWORD flags) 4357 { 4358 struct ddraw_surface *dst_impl = impl_from_IDirectDrawSurface3(iface); 4359 struct ddraw_surface *src_impl = unsafe_impl_from_IDirectDrawSurface3(src_surface); 4360 4361 TRACE("iface %p, dst_x %u, dst_y %u, src_surface %p, src_rect %s, flags %#x.\n", 4362 iface, dst_x, dst_y, src_surface, wine_dbgstr_rect(src_rect), flags); 4363 4364 return ddraw_surface7_BltFast(&dst_impl->IDirectDrawSurface7_iface, dst_x, dst_y, 4365 src_impl ? &src_impl->IDirectDrawSurface7_iface : NULL, src_rect, flags); 4366 } 4367 4368 static HRESULT WINAPI DECLSPEC_HOTPATCH ddraw_surface2_BltFast(IDirectDrawSurface2 *iface, DWORD dst_x, DWORD dst_y, 4369 IDirectDrawSurface2 *src_surface, RECT *src_rect, DWORD flags) 4370 { 4371 struct ddraw_surface *dst_impl = impl_from_IDirectDrawSurface2(iface); 4372 struct ddraw_surface *src_impl = unsafe_impl_from_IDirectDrawSurface2(src_surface); 4373 4374 TRACE("iface %p, dst_x %u, dst_y %u, src_surface %p, src_rect %s, flags %#x.\n", 4375 iface, dst_x, dst_y, src_surface, wine_dbgstr_rect(src_rect), flags); 4376 4377 return ddraw_surface7_BltFast(&dst_impl->IDirectDrawSurface7_iface, dst_x, dst_y, 4378 src_impl ? &src_impl->IDirectDrawSurface7_iface : NULL, src_rect, flags); 4379 } 4380 4381 static HRESULT WINAPI DECLSPEC_HOTPATCH ddraw_surface1_BltFast(IDirectDrawSurface *iface, DWORD dst_x, DWORD dst_y, 4382 IDirectDrawSurface *src_surface, RECT *src_rect, DWORD flags) 4383 { 4384 struct ddraw_surface *dst_impl = impl_from_IDirectDrawSurface(iface); 4385 struct ddraw_surface *src_impl = unsafe_impl_from_IDirectDrawSurface(src_surface); 4386 4387 TRACE("iface %p, dst_x %u, dst_y %u, src_surface %p, src_rect %s, flags %#x.\n", 4388 iface, dst_x, dst_y, src_surface, wine_dbgstr_rect(src_rect), flags); 4389 4390 return ddraw_surface7_BltFast(&dst_impl->IDirectDrawSurface7_iface, dst_x, dst_y, 4391 src_impl ? &src_impl->IDirectDrawSurface7_iface : NULL, src_rect, flags); 4392 } 4393 4394 /***************************************************************************** 4395 * IDirectDrawSurface7::GetClipper 4396 * 4397 * Returns the IDirectDrawClipper interface of the clipper assigned to this 4398 * surface 4399 * 4400 * Params: 4401 * Clipper: Address to store the interface pointer at 4402 * 4403 * Returns: 4404 * DD_OK on success 4405 * DDERR_INVALIDPARAMS if Clipper is NULL 4406 * DDERR_NOCLIPPERATTACHED if there's no clipper attached 4407 * 4408 *****************************************************************************/ 4409 static HRESULT WINAPI ddraw_surface7_GetClipper(IDirectDrawSurface7 *iface, IDirectDrawClipper **Clipper) 4410 { 4411 struct ddraw_surface *surface = impl_from_IDirectDrawSurface7(iface); 4412 4413 TRACE("iface %p, clipper %p.\n", iface, Clipper); 4414 4415 if (!Clipper) 4416 return DDERR_INVALIDPARAMS; 4417 4418 wined3d_mutex_lock(); 4419 if (!surface->clipper) 4420 { 4421 wined3d_mutex_unlock(); 4422 return DDERR_NOCLIPPERATTACHED; 4423 } 4424 4425 *Clipper = &surface->clipper->IDirectDrawClipper_iface; 4426 IDirectDrawClipper_AddRef(*Clipper); 4427 wined3d_mutex_unlock(); 4428 4429 return DD_OK; 4430 } 4431 4432 static HRESULT WINAPI ddraw_surface4_GetClipper(IDirectDrawSurface4 *iface, IDirectDrawClipper **clipper) 4433 { 4434 struct ddraw_surface *surface = impl_from_IDirectDrawSurface4(iface); 4435 4436 TRACE("iface %p, clipper %p.\n", iface, clipper); 4437 4438 return ddraw_surface7_GetClipper(&surface->IDirectDrawSurface7_iface, clipper); 4439 } 4440 4441 static HRESULT WINAPI ddraw_surface3_GetClipper(IDirectDrawSurface3 *iface, IDirectDrawClipper **clipper) 4442 { 4443 struct ddraw_surface *surface = impl_from_IDirectDrawSurface3(iface); 4444 4445 TRACE("iface %p, clipper %p.\n", iface, clipper); 4446 4447 return ddraw_surface7_GetClipper(&surface->IDirectDrawSurface7_iface, clipper); 4448 } 4449 4450 static HRESULT WINAPI ddraw_surface2_GetClipper(IDirectDrawSurface2 *iface, IDirectDrawClipper **clipper) 4451 { 4452 struct ddraw_surface *surface = impl_from_IDirectDrawSurface2(iface); 4453 4454 TRACE("iface %p, clipper %p.\n", iface, clipper); 4455 4456 return ddraw_surface7_GetClipper(&surface->IDirectDrawSurface7_iface, clipper); 4457 } 4458 4459 static HRESULT WINAPI ddraw_surface1_GetClipper(IDirectDrawSurface *iface, IDirectDrawClipper **clipper) 4460 { 4461 struct ddraw_surface *surface = impl_from_IDirectDrawSurface(iface); 4462 4463 TRACE("iface %p, clipper %p.\n", iface, clipper); 4464 4465 return ddraw_surface7_GetClipper(&surface->IDirectDrawSurface7_iface, clipper); 4466 } 4467 4468 /***************************************************************************** 4469 * IDirectDrawSurface7::SetClipper 4470 * 4471 * Sets a clipper for the surface 4472 * 4473 * Params: 4474 * Clipper: IDirectDrawClipper interface of the clipper to set 4475 * 4476 * Returns: 4477 * DD_OK on success 4478 * 4479 *****************************************************************************/ 4480 static HRESULT WINAPI ddraw_surface7_SetClipper(IDirectDrawSurface7 *iface, 4481 IDirectDrawClipper *iclipper) 4482 { 4483 struct ddraw_surface *This = impl_from_IDirectDrawSurface7(iface); 4484 struct ddraw_clipper *clipper = unsafe_impl_from_IDirectDrawClipper(iclipper); 4485 struct ddraw_clipper *old_clipper = This->clipper; 4486 HWND clipWindow; 4487 4488 TRACE("iface %p, clipper %p.\n", iface, iclipper); 4489 4490 wined3d_mutex_lock(); 4491 if (clipper == This->clipper) 4492 { 4493 wined3d_mutex_unlock(); 4494 return DD_OK; 4495 } 4496 4497 This->clipper = clipper; 4498 4499 if (clipper != NULL) 4500 IDirectDrawClipper_AddRef(iclipper); 4501 if (old_clipper) 4502 IDirectDrawClipper_Release(&old_clipper->IDirectDrawClipper_iface); 4503 4504 if ((This->surface_desc.ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE) && This->ddraw->wined3d_swapchain) 4505 { 4506 clipWindow = NULL; 4507 if(clipper) { 4508 IDirectDrawClipper_GetHWnd(iclipper, &clipWindow); 4509 } 4510 4511 if (clipWindow) 4512 { 4513 wined3d_swapchain_set_window(This->ddraw->wined3d_swapchain, clipWindow); 4514 ddraw_set_swapchain_window(This->ddraw, clipWindow); 4515 } 4516 else 4517 { 4518 wined3d_swapchain_set_window(This->ddraw->wined3d_swapchain, This->ddraw->d3d_window); 4519 ddraw_set_swapchain_window(This->ddraw, This->ddraw->dest_window); 4520 } 4521 } 4522 4523 wined3d_mutex_unlock(); 4524 4525 return DD_OK; 4526 } 4527 4528 static HRESULT WINAPI ddraw_surface4_SetClipper(IDirectDrawSurface4 *iface, IDirectDrawClipper *clipper) 4529 { 4530 struct ddraw_surface *surface = impl_from_IDirectDrawSurface4(iface); 4531 4532 TRACE("iface %p, clipper %p.\n", iface, clipper); 4533 4534 return ddraw_surface7_SetClipper(&surface->IDirectDrawSurface7_iface, clipper); 4535 } 4536 4537 static HRESULT WINAPI ddraw_surface3_SetClipper(IDirectDrawSurface3 *iface, IDirectDrawClipper *clipper) 4538 { 4539 struct ddraw_surface *surface = impl_from_IDirectDrawSurface3(iface); 4540 4541 TRACE("iface %p, clipper %p.\n", iface, clipper); 4542 4543 return ddraw_surface7_SetClipper(&surface->IDirectDrawSurface7_iface, clipper); 4544 } 4545 4546 static HRESULT WINAPI ddraw_surface2_SetClipper(IDirectDrawSurface2 *iface, IDirectDrawClipper *clipper) 4547 { 4548 struct ddraw_surface *surface = impl_from_IDirectDrawSurface2(iface); 4549 4550 TRACE("iface %p, clipper %p.\n", iface, clipper); 4551 4552 return ddraw_surface7_SetClipper(&surface->IDirectDrawSurface7_iface, clipper); 4553 } 4554 4555 static HRESULT WINAPI ddraw_surface1_SetClipper(IDirectDrawSurface *iface, IDirectDrawClipper *clipper) 4556 { 4557 struct ddraw_surface *surface = impl_from_IDirectDrawSurface(iface); 4558 4559 TRACE("iface %p, clipper %p.\n", iface, clipper); 4560 4561 return ddraw_surface7_SetClipper(&surface->IDirectDrawSurface7_iface, clipper); 4562 } 4563 4564 /***************************************************************************** 4565 * IDirectDrawSurface7::SetSurfaceDesc 4566 * 4567 * Sets the surface description. It can override the pixel format, the surface 4568 * memory, ... 4569 * It's not really tested. 4570 * 4571 * Params: 4572 * DDSD: Pointer to the new surface description to set 4573 * Flags: Some flags 4574 * 4575 * Returns: 4576 * DD_OK on success 4577 * DDERR_INVALIDPARAMS if DDSD is NULL 4578 * 4579 *****************************************************************************/ 4580 static HRESULT WINAPI ddraw_surface7_SetSurfaceDesc(IDirectDrawSurface7 *iface, DDSURFACEDESC2 *DDSD, DWORD Flags) 4581 { 4582 struct ddraw_surface *This = impl_from_IDirectDrawSurface7(iface); 4583 HRESULT hr; 4584 const DWORD allowed_flags = DDSD_LPSURFACE | DDSD_PIXELFORMAT | DDSD_WIDTH 4585 | DDSD_HEIGHT | DDSD_PITCH | DDSD_CAPS; 4586 enum wined3d_format_id format_id; 4587 UINT pitch, width, height; 4588 4589 TRACE("iface %p, surface_desc %p, flags %#x.\n", iface, DDSD, Flags); 4590 4591 if (!DDSD) 4592 { 4593 WARN("DDSD is NULL, returning DDERR_INVALIDPARAMS\n"); 4594 return DDERR_INVALIDPARAMS; 4595 } 4596 if (Flags) 4597 { 4598 WARN("Flags is %x, returning DDERR_INVALIDPARAMS\n", Flags); 4599 return DDERR_INVALIDPARAMS; 4600 } 4601 if (!(This->surface_desc.ddsCaps.dwCaps & DDSCAPS_SYSTEMMEMORY) 4602 || This->surface_desc.ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE 4603 || This->surface_desc.ddsCaps.dwCaps2 & (DDSCAPS2_TEXTUREMANAGE | DDSCAPS2_D3DTEXTUREMANAGE)) 4604 { 4605 WARN("Surface is not in system memory, returning DDERR_INVALIDSURFACETYPE.\n"); 4606 return DDERR_INVALIDSURFACETYPE; 4607 } 4608 4609 /* Tests show that only LPSURFACE and PIXELFORMAT can be set, and LPSURFACE is required 4610 * for PIXELFORMAT to work */ 4611 if (DDSD->dwFlags & ~allowed_flags) 4612 { 4613 WARN("Invalid flags (0x%08x) set, returning DDERR_INVALIDPARAMS\n", DDSD->dwFlags); 4614 return DDERR_INVALIDPARAMS; 4615 } 4616 if (!(DDSD->dwFlags & DDSD_LPSURFACE) || !DDSD->lpSurface) 4617 { 4618 WARN("DDSD_LPSURFACE is not set or lpSurface is NULL, returning DDERR_INVALIDPARAMS\n"); 4619 return DDERR_INVALIDPARAMS; 4620 } 4621 if ((DDSD->dwFlags & DDSD_CAPS) && DDSD->ddsCaps.dwCaps) 4622 { 4623 WARN("DDSD_CAPS is set, returning DDERR_INVALIDCAPS.\n"); 4624 return DDERR_INVALIDCAPS; 4625 } 4626 if (DDSD->dwFlags & DDSD_WIDTH) 4627 { 4628 if (!(DDSD->dwFlags & DDSD_PITCH)) 4629 { 4630 WARN("DDSD_WIDTH is set, but DDSD_PITCH is not, returning DDERR_INVALIDPARAMS.\n"); 4631 return DDERR_INVALIDPARAMS; 4632 } 4633 if (!DDSD->dwWidth || DDSD->u1.lPitch <= 0 || DDSD->u1.lPitch & 0x3) 4634 { 4635 WARN("Pitch is %d, width is %u, returning DDERR_INVALIDPARAMS.\n", 4636 DDSD->u1.lPitch, DDSD->dwWidth); 4637 return DDERR_INVALIDPARAMS; 4638 } 4639 if (DDSD->dwWidth != This->surface_desc.dwWidth) 4640 TRACE("Surface width changed from %u to %u.\n", This->surface_desc.dwWidth, DDSD->dwWidth); 4641 if (DDSD->u1.lPitch != This->surface_desc.u1.lPitch) 4642 TRACE("Surface pitch changed from %u to %u.\n", This->surface_desc.u1.lPitch, DDSD->u1.lPitch); 4643 pitch = DDSD->u1.lPitch; 4644 width = DDSD->dwWidth; 4645 } 4646 else if (DDSD->dwFlags & DDSD_PITCH) 4647 { 4648 WARN("DDSD_PITCH is set, but DDSD_WIDTH is not, returning DDERR_INVALIDPARAMS.\n"); 4649 return DDERR_INVALIDPARAMS; 4650 } 4651 else 4652 { 4653 pitch = This->surface_desc.u1.lPitch; 4654 width = This->surface_desc.dwWidth; 4655 } 4656 4657 if (DDSD->dwFlags & DDSD_HEIGHT) 4658 { 4659 if (!DDSD->dwHeight) 4660 { 4661 WARN("Height is 0, returning DDERR_INVALIDPARAMS.\n"); 4662 return DDERR_INVALIDPARAMS; 4663 } 4664 if (DDSD->dwHeight != This->surface_desc.dwHeight) 4665 TRACE("Surface height changed from %u to %u.\n", This->surface_desc.dwHeight, DDSD->dwHeight); 4666 height = DDSD->dwHeight; 4667 } 4668 else 4669 { 4670 height = This->surface_desc.dwHeight; 4671 } 4672 4673 wined3d_mutex_lock(); 4674 if (DDSD->dwFlags & DDSD_PIXELFORMAT) 4675 { 4676 enum wined3d_format_id current_format_id; 4677 format_id = wined3dformat_from_ddrawformat(&DDSD->u4.ddpfPixelFormat); 4678 4679 if (format_id == WINED3DFMT_UNKNOWN) 4680 { 4681 ERR("Requested to set an unknown pixelformat\n"); 4682 wined3d_mutex_unlock(); 4683 return DDERR_INVALIDPARAMS; 4684 } 4685 current_format_id = wined3dformat_from_ddrawformat(&This->surface_desc.u4.ddpfPixelFormat); 4686 if (format_id != current_format_id) 4687 TRACE("Surface format changed from %#x to %#x.\n", current_format_id, format_id); 4688 } 4689 else 4690 { 4691 format_id = wined3dformat_from_ddrawformat(&This->surface_desc.u4.ddpfPixelFormat); 4692 } 4693 4694 if (FAILED(hr = wined3d_texture_update_desc(This->wined3d_texture, width, height, 4695 format_id, WINED3D_MULTISAMPLE_NONE, 0, DDSD->lpSurface, pitch))) 4696 { 4697 WARN("Failed to update surface desc, hr %#x.\n", hr); 4698 wined3d_mutex_unlock(); 4699 return hr_ddraw_from_wined3d(hr); 4700 } 4701 4702 if (DDSD->dwFlags & DDSD_WIDTH) 4703 This->surface_desc.dwWidth = width; 4704 if (DDSD->dwFlags & DDSD_PITCH) 4705 This->surface_desc.u1.lPitch = DDSD->u1.lPitch; 4706 if (DDSD->dwFlags & DDSD_HEIGHT) 4707 This->surface_desc.dwHeight = height; 4708 if (DDSD->dwFlags & DDSD_PIXELFORMAT) 4709 This->surface_desc.u4.ddpfPixelFormat = DDSD->u4.ddpfPixelFormat; 4710 4711 wined3d_mutex_unlock(); 4712 4713 return DD_OK; 4714 } 4715 4716 static HRESULT WINAPI ddraw_surface4_SetSurfaceDesc(IDirectDrawSurface4 *iface, 4717 DDSURFACEDESC2 *surface_desc, DWORD flags) 4718 { 4719 struct ddraw_surface *surface = impl_from_IDirectDrawSurface4(iface); 4720 4721 TRACE("iface %p, surface_desc %p, flags %#x.\n", iface, surface_desc, flags); 4722 4723 return ddraw_surface7_SetSurfaceDesc(&surface->IDirectDrawSurface7_iface, 4724 surface_desc, flags); 4725 } 4726 4727 static HRESULT WINAPI ddraw_surface3_SetSurfaceDesc(IDirectDrawSurface3 *iface, 4728 DDSURFACEDESC *surface_desc, DWORD flags) 4729 { 4730 struct ddraw_surface *surface = impl_from_IDirectDrawSurface3(iface); 4731 DDSURFACEDESC2 surface_desc2; 4732 4733 TRACE("iface %p, surface_desc %p, flags %#x.\n", iface, surface_desc, flags); 4734 4735 if (surface_desc) DDSD_to_DDSD2(surface_desc, &surface_desc2); 4736 return ddraw_surface7_SetSurfaceDesc(&surface->IDirectDrawSurface7_iface, 4737 surface_desc ? &surface_desc2 : NULL, flags); 4738 } 4739 4740 static HRESULT WINAPI ddraw_surface7_GetPalette(IDirectDrawSurface7 *iface, IDirectDrawPalette **palette) 4741 { 4742 struct ddraw_surface *surface = impl_from_IDirectDrawSurface7(iface); 4743 struct ddraw_palette *palette_impl; 4744 HRESULT hr = DD_OK; 4745 4746 TRACE("iface %p, palette %p.\n", iface, palette); 4747 4748 if (!palette) 4749 return DDERR_INVALIDPARAMS; 4750 if (IDirectDrawSurface7_IsLost(iface) == DDERR_SURFACELOST) 4751 { 4752 WARN("Surface lost, returning DDERR_SURFACELOST.\n"); 4753 return DDERR_SURFACELOST; 4754 } 4755 4756 wined3d_mutex_lock(); 4757 if ((palette_impl = surface->palette)) 4758 { 4759 *palette = &palette_impl->IDirectDrawPalette_iface; 4760 IDirectDrawPalette_AddRef(*palette); 4761 } 4762 else 4763 { 4764 *palette = NULL; 4765 hr = DDERR_NOPALETTEATTACHED; 4766 } 4767 wined3d_mutex_unlock(); 4768 4769 return hr; 4770 } 4771 4772 static HRESULT WINAPI ddraw_surface4_GetPalette(IDirectDrawSurface4 *iface, IDirectDrawPalette **palette) 4773 { 4774 struct ddraw_surface *surface = impl_from_IDirectDrawSurface4(iface); 4775 4776 TRACE("iface %p, palette %p.\n", iface, palette); 4777 4778 return ddraw_surface7_GetPalette(&surface->IDirectDrawSurface7_iface, palette); 4779 } 4780 4781 static HRESULT WINAPI ddraw_surface3_GetPalette(IDirectDrawSurface3 *iface, IDirectDrawPalette **palette) 4782 { 4783 struct ddraw_surface *surface = impl_from_IDirectDrawSurface3(iface); 4784 4785 TRACE("iface %p, palette %p.\n", iface, palette); 4786 4787 return ddraw_surface7_GetPalette(&surface->IDirectDrawSurface7_iface, palette); 4788 } 4789 4790 static HRESULT WINAPI ddraw_surface2_GetPalette(IDirectDrawSurface2 *iface, IDirectDrawPalette **palette) 4791 { 4792 struct ddraw_surface *surface = impl_from_IDirectDrawSurface2(iface); 4793 4794 TRACE("iface %p, palette %p.\n", iface, palette); 4795 4796 return ddraw_surface7_GetPalette(&surface->IDirectDrawSurface7_iface, palette); 4797 } 4798 4799 static HRESULT WINAPI ddraw_surface1_GetPalette(IDirectDrawSurface *iface, IDirectDrawPalette **palette) 4800 { 4801 struct ddraw_surface *surface = impl_from_IDirectDrawSurface(iface); 4802 4803 TRACE("iface %p, palette %p.\n", iface, palette); 4804 4805 return ddraw_surface7_GetPalette(&surface->IDirectDrawSurface7_iface, palette); 4806 } 4807 4808 static HRESULT ddraw_surface_set_color_key(struct ddraw_surface *surface, DWORD flags, DDCOLORKEY *color_key) 4809 { 4810 DDCOLORKEY fixed_color_key; 4811 HRESULT hr = WINED3D_OK; 4812 4813 if (flags & DDCKEY_COLORSPACE) 4814 { 4815 if (color_key && color_key->dwColorSpaceLowValue != color_key->dwColorSpaceHighValue) 4816 { 4817 WARN("Range color keys are not supported, returning DDERR_NOCOLORKEYHW.\n"); 4818 return DDERR_NOCOLORKEYHW; 4819 } 4820 flags &= ~DDCKEY_COLORSPACE; 4821 } 4822 4823 wined3d_mutex_lock(); 4824 4825 if (color_key) 4826 { 4827 fixed_color_key.dwColorSpaceLowValue = fixed_color_key.dwColorSpaceHighValue = color_key->dwColorSpaceLowValue; 4828 switch (flags & ~DDCKEY_COLORSPACE) 4829 { 4830 case DDCKEY_DESTBLT: 4831 surface->surface_desc.ddckCKDestBlt = fixed_color_key; 4832 surface->surface_desc.dwFlags |= DDSD_CKDESTBLT; 4833 break; 4834 4835 case DDCKEY_DESTOVERLAY: 4836 surface->surface_desc.u3.ddckCKDestOverlay = fixed_color_key; 4837 surface->surface_desc.dwFlags |= DDSD_CKDESTOVERLAY; 4838 break; 4839 4840 case DDCKEY_SRCOVERLAY: 4841 surface->surface_desc.ddckCKSrcOverlay = fixed_color_key; 4842 surface->surface_desc.dwFlags |= DDSD_CKSRCOVERLAY; 4843 break; 4844 4845 case DDCKEY_SRCBLT: 4846 surface->surface_desc.ddckCKSrcBlt = fixed_color_key; 4847 surface->surface_desc.dwFlags |= DDSD_CKSRCBLT; 4848 break; 4849 4850 default: 4851 wined3d_mutex_unlock(); 4852 return DDERR_INVALIDPARAMS; 4853 } 4854 } 4855 else 4856 { 4857 switch (flags & ~DDCKEY_COLORSPACE) 4858 { 4859 case DDCKEY_DESTBLT: 4860 surface->surface_desc.dwFlags &= ~DDSD_CKDESTBLT; 4861 break; 4862 4863 case DDCKEY_DESTOVERLAY: 4864 surface->surface_desc.dwFlags &= ~DDSD_CKDESTOVERLAY; 4865 break; 4866 4867 case DDCKEY_SRCOVERLAY: 4868 surface->surface_desc.dwFlags &= ~DDSD_CKSRCOVERLAY; 4869 break; 4870 4871 case DDCKEY_SRCBLT: 4872 surface->surface_desc.dwFlags &= ~DDSD_CKSRCBLT; 4873 break; 4874 4875 default: 4876 wined3d_mutex_unlock(); 4877 return DDERR_INVALIDPARAMS; 4878 } 4879 } 4880 4881 if (surface->is_complex_root) 4882 hr = wined3d_texture_set_color_key(surface->wined3d_texture, flags, 4883 color_key ? (struct wined3d_color_key *)&fixed_color_key : NULL); 4884 4885 wined3d_mutex_unlock(); 4886 4887 return hr_ddraw_from_wined3d(hr); 4888 } 4889 4890 static HRESULT WINAPI ddraw_surface7_SetColorKey(IDirectDrawSurface7 *iface, DWORD flags, DDCOLORKEY *color_key) 4891 { 4892 struct ddraw_surface *surface = impl_from_IDirectDrawSurface7(iface); 4893 4894 TRACE("iface %p, flags %#x, color_key %p.\n", iface, flags, color_key); 4895 4896 if (surface->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_MIPMAPSUBLEVEL) 4897 return DDERR_NOTONMIPMAPSUBLEVEL; 4898 4899 return ddraw_surface_set_color_key(surface, flags, color_key); 4900 } 4901 4902 static HRESULT WINAPI ddraw_surface4_SetColorKey(IDirectDrawSurface4 *iface, DWORD flags, DDCOLORKEY *color_key) 4903 { 4904 struct ddraw_surface *surface = impl_from_IDirectDrawSurface4(iface); 4905 4906 TRACE("iface %p, flags %#x, color_key %p.\n", iface, flags, color_key); 4907 4908 return ddraw_surface_set_color_key(surface, flags, color_key); 4909 } 4910 4911 static HRESULT WINAPI ddraw_surface3_SetColorKey(IDirectDrawSurface3 *iface, DWORD flags, DDCOLORKEY *color_key) 4912 { 4913 struct ddraw_surface *surface = impl_from_IDirectDrawSurface3(iface); 4914 4915 TRACE("iface %p, flags %#x, color_key %p.\n", iface, flags, color_key); 4916 4917 return ddraw_surface_set_color_key(surface, flags, color_key); 4918 } 4919 4920 static HRESULT WINAPI ddraw_surface2_SetColorKey(IDirectDrawSurface2 *iface, DWORD flags, DDCOLORKEY *color_key) 4921 { 4922 struct ddraw_surface *surface = impl_from_IDirectDrawSurface2(iface); 4923 4924 TRACE("iface %p, flags %#x, color_key %p.\n", iface, flags, color_key); 4925 4926 return ddraw_surface_set_color_key(surface, flags, color_key); 4927 } 4928 4929 static HRESULT WINAPI ddraw_surface1_SetColorKey(IDirectDrawSurface *iface, DWORD flags, DDCOLORKEY *color_key) 4930 { 4931 struct ddraw_surface *surface = impl_from_IDirectDrawSurface(iface); 4932 4933 TRACE("iface %p, flags %#x, color_key %p.\n", iface, flags, color_key); 4934 4935 return ddraw_surface_set_color_key(surface, flags, color_key); 4936 } 4937 4938 static HRESULT WINAPI ddraw_surface7_SetPalette(IDirectDrawSurface7 *iface, IDirectDrawPalette *palette) 4939 { 4940 struct ddraw_surface *surface = impl_from_IDirectDrawSurface7(iface); 4941 4942 TRACE("iface %p, palette %p.\n", iface, palette); 4943 4944 if (surface->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_MIPMAPSUBLEVEL) 4945 return DDERR_NOTONMIPMAPSUBLEVEL; 4946 if (IDirectDrawSurface7_IsLost(iface) == DDERR_SURFACELOST) 4947 { 4948 WARN("Surface lost, returning DDERR_SURFACELOST.\n"); 4949 return DDERR_SURFACELOST; 4950 } 4951 4952 return ddraw_surface_set_palette(surface, palette); 4953 } 4954 4955 static HRESULT WINAPI ddraw_surface4_SetPalette(IDirectDrawSurface4 *iface, IDirectDrawPalette *palette) 4956 { 4957 struct ddraw_surface *surface = impl_from_IDirectDrawSurface4(iface); 4958 4959 TRACE("iface %p, palette %p.\n", iface, palette); 4960 4961 if (IDirectDrawSurface4_IsLost(iface) == DDERR_SURFACELOST) 4962 { 4963 WARN("Surface lost, returning DDERR_SURFACELOST.\n"); 4964 return DDERR_SURFACELOST; 4965 } 4966 4967 return ddraw_surface_set_palette(surface, palette); 4968 } 4969 4970 static HRESULT WINAPI ddraw_surface3_SetPalette(IDirectDrawSurface3 *iface, IDirectDrawPalette *palette) 4971 { 4972 struct ddraw_surface *surface = impl_from_IDirectDrawSurface3(iface); 4973 4974 TRACE("iface %p, palette %p.\n", iface, palette); 4975 4976 if (IDirectDrawSurface3_IsLost(iface) == DDERR_SURFACELOST) 4977 { 4978 WARN("Surface lost, returning DDERR_SURFACELOST.\n"); 4979 return DDERR_SURFACELOST; 4980 } 4981 4982 return ddraw_surface_set_palette(surface, palette); 4983 } 4984 4985 static HRESULT WINAPI ddraw_surface2_SetPalette(IDirectDrawSurface2 *iface, IDirectDrawPalette *palette) 4986 { 4987 struct ddraw_surface *surface = impl_from_IDirectDrawSurface2(iface); 4988 4989 TRACE("iface %p, palette %p.\n", iface, palette); 4990 4991 if (IDirectDrawSurface2_IsLost(iface) == DDERR_SURFACELOST) 4992 { 4993 WARN("Surface lost, returning DDERR_SURFACELOST.\n"); 4994 return DDERR_SURFACELOST; 4995 } 4996 4997 return ddraw_surface_set_palette(surface, palette); 4998 } 4999 5000 static HRESULT WINAPI ddraw_surface1_SetPalette(IDirectDrawSurface *iface, IDirectDrawPalette *palette) 5001 { 5002 struct ddraw_surface *surface = impl_from_IDirectDrawSurface(iface); 5003 5004 TRACE("iface %p, palette %p.\n", iface, palette); 5005 5006 if (IDirectDrawSurface_IsLost(iface) == DDERR_SURFACELOST) 5007 { 5008 WARN("Surface lost, returning DDERR_SURFACELOST.\n"); 5009 return DDERR_SURFACELOST; 5010 } 5011 5012 return ddraw_surface_set_palette(surface, palette); 5013 } 5014 5015 /********************************************************** 5016 * IDirectDrawGammaControl::GetGammaRamp 5017 * 5018 * Returns the current gamma ramp for a surface 5019 * 5020 * Params: 5021 * flags: Ignored 5022 * gamma_ramp: Address to write the ramp to 5023 * 5024 * Returns: 5025 * DD_OK on success 5026 * DDERR_INVALIDPARAMS if gamma_ramp is NULL 5027 * 5028 **********************************************************/ 5029 static HRESULT WINAPI ddraw_gamma_control_GetGammaRamp(IDirectDrawGammaControl *iface, 5030 DWORD flags, DDGAMMARAMP *gamma_ramp) 5031 { 5032 struct ddraw_surface *surface = impl_from_IDirectDrawGammaControl(iface); 5033 5034 TRACE("iface %p, flags %#x, gamma_ramp %p.\n", iface, flags, gamma_ramp); 5035 5036 if (!gamma_ramp) 5037 { 5038 WARN("Invalid gamma_ramp passed.\n"); 5039 return DDERR_INVALIDPARAMS; 5040 } 5041 5042 wined3d_mutex_lock(); 5043 if (surface->surface_desc.ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE) 5044 { 5045 /* Note: DDGAMMARAMP is compatible with struct wined3d_gamma_ramp. */ 5046 wined3d_device_get_gamma_ramp(surface->ddraw->wined3d_device, 0, (struct wined3d_gamma_ramp *)gamma_ramp); 5047 } 5048 else 5049 { 5050 ERR("Not implemented for non-primary surfaces.\n"); 5051 } 5052 wined3d_mutex_unlock(); 5053 5054 return DD_OK; 5055 } 5056 5057 /********************************************************** 5058 * IDirectDrawGammaControl::SetGammaRamp 5059 * 5060 * Sets the red, green and blue gamma ramps for 5061 * 5062 * Params: 5063 * flags: Can be DDSGR_CALIBRATE to request calibration 5064 * gamma_ramp: Structure containing the new gamma ramp 5065 * 5066 * Returns: 5067 * DD_OK on success 5068 * DDERR_INVALIDPARAMS if gamma_ramp is NULL 5069 * 5070 **********************************************************/ 5071 static HRESULT WINAPI ddraw_gamma_control_SetGammaRamp(IDirectDrawGammaControl *iface, 5072 DWORD flags, DDGAMMARAMP *gamma_ramp) 5073 { 5074 struct ddraw_surface *surface = impl_from_IDirectDrawGammaControl(iface); 5075 5076 TRACE("iface %p, flags %#x, gamma_ramp %p.\n", iface, flags, gamma_ramp); 5077 5078 if (!gamma_ramp) 5079 { 5080 WARN("Invalid gamma_ramp passed.\n"); 5081 return DDERR_INVALIDPARAMS; 5082 } 5083 5084 wined3d_mutex_lock(); 5085 if (surface->surface_desc.ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE) 5086 { 5087 /* Note: DDGAMMARAMP is compatible with struct wined3d_gamma_ramp. */ 5088 wined3d_device_set_gamma_ramp(surface->ddraw->wined3d_device, 5089 0, flags, (struct wined3d_gamma_ramp *)gamma_ramp); 5090 } 5091 else 5092 { 5093 ERR("Not implemented for non-primary surfaces.\n"); 5094 } 5095 wined3d_mutex_unlock(); 5096 5097 return DD_OK; 5098 } 5099 5100 /***************************************************************************** 5101 * IDirect3DTexture2::PaletteChanged 5102 * 5103 * Informs the texture about a palette change 5104 * 5105 * Params: 5106 * start: Start index of the change 5107 * count: The number of changed entries 5108 * 5109 * Returns 5110 * D3D_OK, because it's a stub 5111 * 5112 *****************************************************************************/ 5113 static HRESULT WINAPI d3d_texture2_PaletteChanged(IDirect3DTexture2 *iface, DWORD start, DWORD count) 5114 { 5115 FIXME("iface %p, start %u, count %u stub!\n", iface, start, count); 5116 5117 return D3D_OK; 5118 } 5119 5120 static HRESULT WINAPI d3d_texture1_PaletteChanged(IDirect3DTexture *iface, DWORD start, DWORD count) 5121 { 5122 struct ddraw_surface *surface = impl_from_IDirect3DTexture(iface); 5123 5124 TRACE("iface %p, start %u, count %u.\n", iface, start, count); 5125 5126 return d3d_texture2_PaletteChanged(&surface->IDirect3DTexture2_iface, start, count); 5127 } 5128 5129 /***************************************************************************** 5130 * IDirect3DTexture::Unload 5131 * 5132 * DX5 SDK: "The IDirect3DTexture2::Unload method is not implemented 5133 * 5134 * 5135 * Returns: 5136 * DDERR_UNSUPPORTED 5137 * 5138 *****************************************************************************/ 5139 static HRESULT WINAPI d3d_texture1_Unload(IDirect3DTexture *iface) 5140 { 5141 WARN("iface %p. Not implemented.\n", iface); 5142 5143 return DDERR_UNSUPPORTED; 5144 } 5145 5146 /***************************************************************************** 5147 * IDirect3DTexture2::GetHandle 5148 * 5149 * Returns handle for the texture. 5150 * 5151 * Params: 5152 * device: Device this handle is assigned to 5153 * handle: Address to store the handle at. 5154 * 5155 * Returns: 5156 * D3D_OK 5157 * 5158 *****************************************************************************/ 5159 static HRESULT WINAPI d3d_texture2_GetHandle(IDirect3DTexture2 *iface, 5160 IDirect3DDevice2 *device, D3DTEXTUREHANDLE *handle) 5161 { 5162 struct ddraw_surface *surface = impl_from_IDirect3DTexture2(iface); 5163 struct d3d_device *device_impl = unsafe_impl_from_IDirect3DDevice2(device); 5164 5165 TRACE("iface %p, device %p, handle %p.\n", iface, device, handle); 5166 5167 wined3d_mutex_lock(); 5168 5169 if (!surface->Handle) 5170 { 5171 DWORD h = ddraw_allocate_handle(&device_impl->handle_table, surface, DDRAW_HANDLE_SURFACE); 5172 if (h == DDRAW_INVALID_HANDLE) 5173 { 5174 ERR("Failed to allocate a texture handle.\n"); 5175 wined3d_mutex_unlock(); 5176 return DDERR_OUTOFMEMORY; 5177 } 5178 5179 surface->Handle = h + 1; 5180 } 5181 5182 TRACE("Returning handle %08x.\n", surface->Handle); 5183 *handle = surface->Handle; 5184 5185 wined3d_mutex_unlock(); 5186 5187 return D3D_OK; 5188 } 5189 5190 static HRESULT WINAPI d3d_texture1_GetHandle(IDirect3DTexture *iface, 5191 IDirect3DDevice *device, D3DTEXTUREHANDLE *handle) 5192 { 5193 struct ddraw_surface *surface = impl_from_IDirect3DTexture(iface); 5194 struct d3d_device *device_impl = unsafe_impl_from_IDirect3DDevice(device); 5195 5196 TRACE("iface %p, device %p, handle %p.\n", iface, device, handle); 5197 5198 return d3d_texture2_GetHandle(&surface->IDirect3DTexture2_iface, 5199 device_impl ? &device_impl->IDirect3DDevice2_iface : NULL, handle); 5200 } 5201 5202 /***************************************************************************** 5203 * get_sub_mimaplevel 5204 * 5205 * Helper function that returns the next mipmap level 5206 * 5207 * tex_ptr: Surface of which to return the next level 5208 * 5209 *****************************************************************************/ 5210 static struct ddraw_surface *get_sub_mimaplevel(struct ddraw_surface *surface) 5211 { 5212 /* Now go down the mipmap chain to the next surface */ 5213 static DDSCAPS2 mipmap_caps = { DDSCAPS_MIPMAP | DDSCAPS_TEXTURE, 0, 0, {0} }; 5214 IDirectDrawSurface7 *next_level; 5215 HRESULT hr; 5216 5217 hr = ddraw_surface7_GetAttachedSurface(&surface->IDirectDrawSurface7_iface, &mipmap_caps, &next_level); 5218 if (FAILED(hr)) return NULL; 5219 5220 ddraw_surface7_Release(next_level); 5221 5222 return impl_from_IDirectDrawSurface7(next_level); 5223 } 5224 5225 static BOOL compare_format(DDPIXELFORMAT *format1, DDPIXELFORMAT *format2) 5226 { 5227 if ((format1->dwFlags & (DDPF_RGB|DDPF_YUV|DDPF_FOURCC)) != 5228 (format2->dwFlags & (DDPF_RGB|DDPF_YUV|DDPF_FOURCC))) 5229 return FALSE; 5230 5231 if (format1->dwFlags & (DDPF_RGB|DDPF_YUV)) 5232 { 5233 if (!(format1->dwFlags & DDPF_ALPHA)) 5234 { 5235 /* The RGB and YUV bits are stored in the same fields */ 5236 if (format1->u1.dwRGBBitCount != format2->u1.dwRGBBitCount) 5237 return FALSE; 5238 5239 if (format1->u2.dwRBitMask != format2->u2.dwRBitMask) 5240 return FALSE; 5241 5242 if (format1->u3.dwGBitMask != format2->u3.dwGBitMask) 5243 return FALSE; 5244 5245 if (format1->u4.dwBBitMask != format2->u4.dwBBitMask) 5246 return FALSE; 5247 } 5248 5249 if (format1->dwFlags & (DDPF_ALPHAPIXELS | DDPF_ALPHA)) 5250 { 5251 if (format1->u5.dwRGBAlphaBitMask != format2->u5.dwRGBAlphaBitMask) 5252 return FALSE; 5253 } 5254 } 5255 5256 if (format1->dwFlags & DDPF_FOURCC) 5257 { 5258 if (format1->dwFourCC != format2->dwFourCC) 5259 return FALSE; 5260 } 5261 5262 return TRUE; 5263 } 5264 5265 /***************************************************************************** 5266 * IDirect3DTexture2::Load 5267 * 5268 * Loads a texture created with the DDSCAPS_ALLOCONLOAD 5269 * 5270 * This function isn't relayed to WineD3D because the whole interface is 5271 * implemented in DDraw only. For speed improvements an implementation which 5272 * takes OpenGL more into account could be placed into WineD3D. 5273 * 5274 * Params: 5275 * src_texture: Address of the texture to load 5276 * 5277 * Returns: 5278 * D3D_OK on success 5279 * D3DERR_TEXTURE_LOAD_FAILED. 5280 * 5281 *****************************************************************************/ 5282 static HRESULT WINAPI d3d_texture2_Load(IDirect3DTexture2 *iface, IDirect3DTexture2 *src_texture) 5283 { 5284 struct ddraw_surface *dst_surface = impl_from_IDirect3DTexture2(iface); 5285 struct ddraw_surface *src_surface = unsafe_impl_from_IDirect3DTexture2(src_texture); 5286 RECT src_rect, dst_rect; 5287 HRESULT hr; 5288 5289 TRACE("iface %p, src_texture %p.\n", iface, src_texture); 5290 5291 if (src_surface == dst_surface) 5292 { 5293 TRACE("copying surface %p to surface %p, why?\n", src_surface, dst_surface); 5294 return D3D_OK; 5295 } 5296 5297 wined3d_mutex_lock(); 5298 5299 for (;;) 5300 { 5301 DDSURFACEDESC *src_desc = (DDSURFACEDESC *)&src_surface->surface_desc; 5302 5303 TRACE("Copying surface %p to surface %p.\n", src_surface, dst_surface); 5304 5305 if (compare_format(&src_surface->surface_desc.u4.ddpfPixelFormat, 5306 &dst_surface->surface_desc.u4.ddpfPixelFormat)) 5307 { 5308 struct ddraw_palette *dst_pal, *src_pal; 5309 5310 /* Get the palettes */ 5311 dst_pal = dst_surface->palette; 5312 src_pal = src_surface->palette; 5313 5314 if (src_pal) 5315 { 5316 PALETTEENTRY palent[256]; 5317 5318 if (!dst_pal) 5319 { 5320 wined3d_mutex_unlock(); 5321 return DDERR_NOPALETTEATTACHED; 5322 } 5323 IDirectDrawPalette_GetEntries(&src_pal->IDirectDrawPalette_iface, 0, 0, 256, palent); 5324 IDirectDrawPalette_SetEntries(&dst_pal->IDirectDrawPalette_iface, 0, 0, 256, palent); 5325 } 5326 5327 if (src_desc->dwFlags & DDSD_CKSRCBLT) 5328 { 5329 IDirectDrawSurface7_SetColorKey(&dst_surface->IDirectDrawSurface7_iface, 5330 DDCKEY_SRCBLT, &src_desc->ddckCKSrcBlt); 5331 } 5332 } 5333 else 5334 { 5335 if (src_desc->dwFlags & DDSD_CKSRCBLT) 5336 return E_FAIL; 5337 } 5338 5339 /* Suppress the ALLOCONLOAD flag */ 5340 dst_surface->surface_desc.ddsCaps.dwCaps &= ~DDSCAPS_ALLOCONLOAD; 5341 5342 SetRect(&src_rect, 0, 0, src_surface->surface_desc.dwWidth, src_surface->surface_desc.dwHeight); 5343 SetRect(&dst_rect, 0, 0, dst_surface->surface_desc.dwWidth, dst_surface->surface_desc.dwHeight); 5344 5345 hr = wined3d_texture_blt(dst_surface->wined3d_texture, dst_surface->sub_resource_idx, &dst_rect, 5346 src_surface->wined3d_texture, src_surface->sub_resource_idx, &src_rect, 5347 0, NULL, WINED3D_TEXF_LINEAR); 5348 if (FAILED(hr)) 5349 { 5350 ERR("Failed to blit surface, hr %#x.\n", hr); 5351 wined3d_mutex_unlock(); 5352 return hr; 5353 } 5354 5355 if (src_surface->surface_desc.ddsCaps.dwCaps & DDSCAPS_MIPMAP) 5356 src_surface = get_sub_mimaplevel(src_surface); 5357 else 5358 src_surface = NULL; 5359 5360 if (dst_surface->surface_desc.ddsCaps.dwCaps & DDSCAPS_MIPMAP) 5361 dst_surface = get_sub_mimaplevel(dst_surface); 5362 else 5363 dst_surface = NULL; 5364 5365 if (src_surface && !dst_surface) 5366 return DDERR_NOTFOUND; 5367 5368 if (!src_surface || !dst_surface) 5369 break; 5370 } 5371 5372 wined3d_mutex_unlock(); 5373 5374 return hr; 5375 } 5376 5377 static HRESULT WINAPI d3d_texture1_Load(IDirect3DTexture *iface, IDirect3DTexture *src_texture) 5378 { 5379 struct ddraw_surface *dst_surface = impl_from_IDirect3DTexture(iface); 5380 struct ddraw_surface *src_surface = unsafe_impl_from_IDirect3DTexture(src_texture); 5381 5382 TRACE("iface %p, src_texture %p.\n", iface, src_texture); 5383 5384 return d3d_texture2_Load(&dst_surface->IDirect3DTexture2_iface, 5385 src_surface ? &src_surface->IDirect3DTexture2_iface : NULL); 5386 } 5387 5388 /***************************************************************************** 5389 * The VTable 5390 *****************************************************************************/ 5391 5392 static const struct IDirectDrawSurface7Vtbl ddraw_surface7_vtbl = 5393 { 5394 /* IUnknown */ 5395 ddraw_surface7_QueryInterface, 5396 ddraw_surface7_AddRef, 5397 ddraw_surface7_Release, 5398 /* IDirectDrawSurface */ 5399 ddraw_surface7_AddAttachedSurface, 5400 ddraw_surface7_AddOverlayDirtyRect, 5401 ddraw_surface7_Blt, 5402 ddraw_surface7_BltBatch, 5403 ddraw_surface7_BltFast, 5404 ddraw_surface7_DeleteAttachedSurface, 5405 ddraw_surface7_EnumAttachedSurfaces, 5406 ddraw_surface7_EnumOverlayZOrders, 5407 ddraw_surface7_Flip, 5408 ddraw_surface7_GetAttachedSurface, 5409 ddraw_surface7_GetBltStatus, 5410 ddraw_surface7_GetCaps, 5411 ddraw_surface7_GetClipper, 5412 ddraw_surface7_GetColorKey, 5413 ddraw_surface7_GetDC, 5414 ddraw_surface7_GetFlipStatus, 5415 ddraw_surface7_GetOverlayPosition, 5416 ddraw_surface7_GetPalette, 5417 ddraw_surface7_GetPixelFormat, 5418 ddraw_surface7_GetSurfaceDesc, 5419 ddraw_surface7_Initialize, 5420 ddraw_surface7_IsLost, 5421 ddraw_surface7_Lock, 5422 ddraw_surface7_ReleaseDC, 5423 ddraw_surface7_Restore, 5424 ddraw_surface7_SetClipper, 5425 ddraw_surface7_SetColorKey, 5426 ddraw_surface7_SetOverlayPosition, 5427 ddraw_surface7_SetPalette, 5428 ddraw_surface7_Unlock, 5429 ddraw_surface7_UpdateOverlay, 5430 ddraw_surface7_UpdateOverlayDisplay, 5431 ddraw_surface7_UpdateOverlayZOrder, 5432 /* IDirectDrawSurface2 */ 5433 ddraw_surface7_GetDDInterface, 5434 ddraw_surface7_PageLock, 5435 ddraw_surface7_PageUnlock, 5436 /* IDirectDrawSurface3 */ 5437 ddraw_surface7_SetSurfaceDesc, 5438 /* IDirectDrawSurface4 */ 5439 ddraw_surface7_SetPrivateData, 5440 ddraw_surface7_GetPrivateData, 5441 ddraw_surface7_FreePrivateData, 5442 ddraw_surface7_GetUniquenessValue, 5443 ddraw_surface7_ChangeUniquenessValue, 5444 /* IDirectDrawSurface7 */ 5445 ddraw_surface7_SetPriority, 5446 ddraw_surface7_GetPriority, 5447 ddraw_surface7_SetLOD, 5448 ddraw_surface7_GetLOD, 5449 }; 5450 5451 static const struct IDirectDrawSurface4Vtbl ddraw_surface4_vtbl = 5452 { 5453 /* IUnknown */ 5454 ddraw_surface4_QueryInterface, 5455 ddraw_surface4_AddRef, 5456 ddraw_surface4_Release, 5457 /* IDirectDrawSurface */ 5458 ddraw_surface4_AddAttachedSurface, 5459 ddraw_surface4_AddOverlayDirtyRect, 5460 ddraw_surface4_Blt, 5461 ddraw_surface4_BltBatch, 5462 ddraw_surface4_BltFast, 5463 ddraw_surface4_DeleteAttachedSurface, 5464 ddraw_surface4_EnumAttachedSurfaces, 5465 ddraw_surface4_EnumOverlayZOrders, 5466 ddraw_surface4_Flip, 5467 ddraw_surface4_GetAttachedSurface, 5468 ddraw_surface4_GetBltStatus, 5469 ddraw_surface4_GetCaps, 5470 ddraw_surface4_GetClipper, 5471 ddraw_surface4_GetColorKey, 5472 ddraw_surface4_GetDC, 5473 ddraw_surface4_GetFlipStatus, 5474 ddraw_surface4_GetOverlayPosition, 5475 ddraw_surface4_GetPalette, 5476 ddraw_surface4_GetPixelFormat, 5477 ddraw_surface4_GetSurfaceDesc, 5478 ddraw_surface4_Initialize, 5479 ddraw_surface4_IsLost, 5480 ddraw_surface4_Lock, 5481 ddraw_surface4_ReleaseDC, 5482 ddraw_surface4_Restore, 5483 ddraw_surface4_SetClipper, 5484 ddraw_surface4_SetColorKey, 5485 ddraw_surface4_SetOverlayPosition, 5486 ddraw_surface4_SetPalette, 5487 ddraw_surface4_Unlock, 5488 ddraw_surface4_UpdateOverlay, 5489 ddraw_surface4_UpdateOverlayDisplay, 5490 ddraw_surface4_UpdateOverlayZOrder, 5491 /* IDirectDrawSurface2 */ 5492 ddraw_surface4_GetDDInterface, 5493 ddraw_surface4_PageLock, 5494 ddraw_surface4_PageUnlock, 5495 /* IDirectDrawSurface3 */ 5496 ddraw_surface4_SetSurfaceDesc, 5497 /* IDirectDrawSurface4 */ 5498 ddraw_surface4_SetPrivateData, 5499 ddraw_surface4_GetPrivateData, 5500 ddraw_surface4_FreePrivateData, 5501 ddraw_surface4_GetUniquenessValue, 5502 ddraw_surface4_ChangeUniquenessValue, 5503 }; 5504 5505 static const struct IDirectDrawSurface3Vtbl ddraw_surface3_vtbl = 5506 { 5507 /* IUnknown */ 5508 ddraw_surface3_QueryInterface, 5509 ddraw_surface3_AddRef, 5510 ddraw_surface3_Release, 5511 /* IDirectDrawSurface */ 5512 ddraw_surface3_AddAttachedSurface, 5513 ddraw_surface3_AddOverlayDirtyRect, 5514 ddraw_surface3_Blt, 5515 ddraw_surface3_BltBatch, 5516 ddraw_surface3_BltFast, 5517 ddraw_surface3_DeleteAttachedSurface, 5518 ddraw_surface3_EnumAttachedSurfaces, 5519 ddraw_surface3_EnumOverlayZOrders, 5520 ddraw_surface3_Flip, 5521 ddraw_surface3_GetAttachedSurface, 5522 ddraw_surface3_GetBltStatus, 5523 ddraw_surface3_GetCaps, 5524 ddraw_surface3_GetClipper, 5525 ddraw_surface3_GetColorKey, 5526 ddraw_surface3_GetDC, 5527 ddraw_surface3_GetFlipStatus, 5528 ddraw_surface3_GetOverlayPosition, 5529 ddraw_surface3_GetPalette, 5530 ddraw_surface3_GetPixelFormat, 5531 ddraw_surface3_GetSurfaceDesc, 5532 ddraw_surface3_Initialize, 5533 ddraw_surface3_IsLost, 5534 ddraw_surface3_Lock, 5535 ddraw_surface3_ReleaseDC, 5536 ddraw_surface3_Restore, 5537 ddraw_surface3_SetClipper, 5538 ddraw_surface3_SetColorKey, 5539 ddraw_surface3_SetOverlayPosition, 5540 ddraw_surface3_SetPalette, 5541 ddraw_surface3_Unlock, 5542 ddraw_surface3_UpdateOverlay, 5543 ddraw_surface3_UpdateOverlayDisplay, 5544 ddraw_surface3_UpdateOverlayZOrder, 5545 /* IDirectDrawSurface2 */ 5546 ddraw_surface3_GetDDInterface, 5547 ddraw_surface3_PageLock, 5548 ddraw_surface3_PageUnlock, 5549 /* IDirectDrawSurface3 */ 5550 ddraw_surface3_SetSurfaceDesc, 5551 }; 5552 5553 static const struct IDirectDrawSurface2Vtbl ddraw_surface2_vtbl = 5554 { 5555 /* IUnknown */ 5556 ddraw_surface2_QueryInterface, 5557 ddraw_surface2_AddRef, 5558 ddraw_surface2_Release, 5559 /* IDirectDrawSurface */ 5560 ddraw_surface2_AddAttachedSurface, 5561 ddraw_surface2_AddOverlayDirtyRect, 5562 ddraw_surface2_Blt, 5563 ddraw_surface2_BltBatch, 5564 ddraw_surface2_BltFast, 5565 ddraw_surface2_DeleteAttachedSurface, 5566 ddraw_surface2_EnumAttachedSurfaces, 5567 ddraw_surface2_EnumOverlayZOrders, 5568 ddraw_surface2_Flip, 5569 ddraw_surface2_GetAttachedSurface, 5570 ddraw_surface2_GetBltStatus, 5571 ddraw_surface2_GetCaps, 5572 ddraw_surface2_GetClipper, 5573 ddraw_surface2_GetColorKey, 5574 ddraw_surface2_GetDC, 5575 ddraw_surface2_GetFlipStatus, 5576 ddraw_surface2_GetOverlayPosition, 5577 ddraw_surface2_GetPalette, 5578 ddraw_surface2_GetPixelFormat, 5579 ddraw_surface2_GetSurfaceDesc, 5580 ddraw_surface2_Initialize, 5581 ddraw_surface2_IsLost, 5582 ddraw_surface2_Lock, 5583 ddraw_surface2_ReleaseDC, 5584 ddraw_surface2_Restore, 5585 ddraw_surface2_SetClipper, 5586 ddraw_surface2_SetColorKey, 5587 ddraw_surface2_SetOverlayPosition, 5588 ddraw_surface2_SetPalette, 5589 ddraw_surface2_Unlock, 5590 ddraw_surface2_UpdateOverlay, 5591 ddraw_surface2_UpdateOverlayDisplay, 5592 ddraw_surface2_UpdateOverlayZOrder, 5593 /* IDirectDrawSurface2 */ 5594 ddraw_surface2_GetDDInterface, 5595 ddraw_surface2_PageLock, 5596 ddraw_surface2_PageUnlock, 5597 }; 5598 5599 static struct IDirectDrawSurfaceVtbl ddraw_surface1_vtbl = 5600 { 5601 /* IUnknown */ 5602 ddraw_surface1_QueryInterface, 5603 ddraw_surface1_AddRef, 5604 ddraw_surface1_Release, 5605 /* IDirectDrawSurface */ 5606 ddraw_surface1_AddAttachedSurface, 5607 ddraw_surface1_AddOverlayDirtyRect, 5608 ddraw_surface1_Blt, 5609 ddraw_surface1_BltBatch, 5610 ddraw_surface1_BltFast, 5611 ddraw_surface1_DeleteAttachedSurface, 5612 ddraw_surface1_EnumAttachedSurfaces, 5613 ddraw_surface1_EnumOverlayZOrders, 5614 ddraw_surface1_Flip, 5615 ddraw_surface1_GetAttachedSurface, 5616 ddraw_surface1_GetBltStatus, 5617 ddraw_surface1_GetCaps, 5618 ddraw_surface1_GetClipper, 5619 ddraw_surface1_GetColorKey, 5620 ddraw_surface1_GetDC, 5621 ddraw_surface1_GetFlipStatus, 5622 ddraw_surface1_GetOverlayPosition, 5623 ddraw_surface1_GetPalette, 5624 ddraw_surface1_GetPixelFormat, 5625 ddraw_surface1_GetSurfaceDesc, 5626 ddraw_surface1_Initialize, 5627 ddraw_surface1_IsLost, 5628 ddraw_surface1_Lock, 5629 ddraw_surface1_ReleaseDC, 5630 ddraw_surface1_Restore, 5631 ddraw_surface1_SetClipper, 5632 ddraw_surface1_SetColorKey, 5633 ddraw_surface1_SetOverlayPosition, 5634 ddraw_surface1_SetPalette, 5635 ddraw_surface1_Unlock, 5636 ddraw_surface1_UpdateOverlay, 5637 ddraw_surface1_UpdateOverlayDisplay, 5638 ddraw_surface1_UpdateOverlayZOrder, 5639 }; 5640 5641 static const struct IDirectDrawGammaControlVtbl ddraw_gamma_control_vtbl = 5642 { 5643 ddraw_gamma_control_QueryInterface, 5644 ddraw_gamma_control_AddRef, 5645 ddraw_gamma_control_Release, 5646 ddraw_gamma_control_GetGammaRamp, 5647 ddraw_gamma_control_SetGammaRamp, 5648 }; 5649 5650 static const struct IDirect3DTexture2Vtbl d3d_texture2_vtbl = 5651 { 5652 d3d_texture2_QueryInterface, 5653 d3d_texture2_AddRef, 5654 d3d_texture2_Release, 5655 d3d_texture2_GetHandle, 5656 d3d_texture2_PaletteChanged, 5657 d3d_texture2_Load, 5658 }; 5659 5660 static const struct IDirect3DTextureVtbl d3d_texture1_vtbl = 5661 { 5662 d3d_texture1_QueryInterface, 5663 d3d_texture1_AddRef, 5664 d3d_texture1_Release, 5665 d3d_texture1_Initialize, 5666 d3d_texture1_GetHandle, 5667 d3d_texture1_PaletteChanged, 5668 d3d_texture1_Load, 5669 d3d_texture1_Unload, 5670 }; 5671 5672 /* Some games (e.g. Tomb Raider 3) pass the wrong version of the 5673 * IDirectDrawSurface interface to ddraw methods. */ 5674 struct ddraw_surface *unsafe_impl_from_IDirectDrawSurface7(IDirectDrawSurface7 *iface) 5675 { 5676 if (!iface) return NULL; 5677 if (iface->lpVtbl != &ddraw_surface7_vtbl) 5678 { 5679 HRESULT hr = IDirectDrawSurface7_QueryInterface(iface, &IID_IDirectDrawSurface7, (void **)&iface); 5680 if (FAILED(hr)) 5681 { 5682 WARN("Object %p doesn't expose interface IDirectDrawSurface7.\n", iface); 5683 return NULL; 5684 } 5685 IDirectDrawSurface7_Release(iface); 5686 } 5687 return CONTAINING_RECORD(iface, struct ddraw_surface, IDirectDrawSurface7_iface); 5688 } 5689 5690 struct ddraw_surface *unsafe_impl_from_IDirectDrawSurface4(IDirectDrawSurface4 *iface) 5691 { 5692 if (!iface) return NULL; 5693 if (iface->lpVtbl != &ddraw_surface4_vtbl) 5694 { 5695 HRESULT hr = IDirectDrawSurface4_QueryInterface(iface, &IID_IDirectDrawSurface4, (void **)&iface); 5696 if (FAILED(hr)) 5697 { 5698 WARN("Object %p doesn't expose interface IDirectDrawSurface4.\n", iface); 5699 return NULL; 5700 } 5701 IDirectDrawSurface4_Release(iface); 5702 } 5703 return CONTAINING_RECORD(iface, struct ddraw_surface, IDirectDrawSurface4_iface); 5704 } 5705 5706 static struct ddraw_surface *unsafe_impl_from_IDirectDrawSurface3(IDirectDrawSurface3 *iface) 5707 { 5708 if (!iface) return NULL; 5709 if (iface->lpVtbl != &ddraw_surface3_vtbl) 5710 { 5711 HRESULT hr = IDirectDrawSurface3_QueryInterface(iface, &IID_IDirectDrawSurface3, (void **)&iface); 5712 if (FAILED(hr)) 5713 { 5714 WARN("Object %p doesn't expose interface IDirectDrawSurface3.\n", iface); 5715 return NULL; 5716 } 5717 IDirectDrawSurface3_Release(iface); 5718 } 5719 return CONTAINING_RECORD(iface, struct ddraw_surface, IDirectDrawSurface3_iface); 5720 } 5721 5722 static struct ddraw_surface *unsafe_impl_from_IDirectDrawSurface2(IDirectDrawSurface2 *iface) 5723 { 5724 if (!iface) return NULL; 5725 if (iface->lpVtbl != &ddraw_surface2_vtbl) 5726 { 5727 HRESULT hr = IDirectDrawSurface2_QueryInterface(iface, &IID_IDirectDrawSurface2, (void **)&iface); 5728 if (FAILED(hr)) 5729 { 5730 WARN("Object %p doesn't expose interface IDirectDrawSurface2.\n", iface); 5731 return NULL; 5732 } 5733 IDirectDrawSurface2_Release(iface); 5734 } 5735 return CONTAINING_RECORD(iface, struct ddraw_surface, IDirectDrawSurface2_iface); 5736 } 5737 5738 struct ddraw_surface *unsafe_impl_from_IDirectDrawSurface(IDirectDrawSurface *iface) 5739 { 5740 if (!iface) return NULL; 5741 if (iface->lpVtbl != &ddraw_surface1_vtbl) 5742 { 5743 HRESULT hr = IDirectDrawSurface_QueryInterface(iface, &IID_IDirectDrawSurface, (void **)&iface); 5744 if (FAILED(hr)) 5745 { 5746 WARN("Object %p doesn't expose interface IDirectDrawSurface.\n", iface); 5747 return NULL; 5748 } 5749 IDirectDrawSurface_Release(iface); 5750 } 5751 return CONTAINING_RECORD(iface, struct ddraw_surface, IDirectDrawSurface_iface); 5752 } 5753 5754 struct ddraw_surface *unsafe_impl_from_IDirect3DTexture2(IDirect3DTexture2 *iface) 5755 { 5756 if (!iface) return NULL; 5757 assert(iface->lpVtbl == &d3d_texture2_vtbl); 5758 return CONTAINING_RECORD(iface, struct ddraw_surface, IDirect3DTexture2_iface); 5759 } 5760 5761 struct ddraw_surface *unsafe_impl_from_IDirect3DTexture(IDirect3DTexture *iface) 5762 { 5763 if (!iface) return NULL; 5764 assert(iface->lpVtbl == &d3d_texture1_vtbl); 5765 return CONTAINING_RECORD(iface, struct ddraw_surface, IDirect3DTexture_iface); 5766 } 5767 5768 static void STDMETHODCALLTYPE ddraw_surface_wined3d_object_destroyed(void *parent) 5769 { 5770 struct ddraw_surface *surface = parent; 5771 5772 TRACE("surface %p.\n", surface); 5773 5774 /* This shouldn't happen, ddraw_surface_release_iface() should prevent the 5775 * surface from being destroyed in this case. */ 5776 if (surface->first_attached != surface) 5777 ERR("Surface is still attached to surface %p.\n", surface->first_attached); 5778 5779 while (surface->next_attached) 5780 if (FAILED(ddraw_surface_delete_attached_surface(surface, 5781 surface->next_attached, surface->next_attached->attached_iface))) 5782 ERR("DeleteAttachedSurface failed.\n"); 5783 5784 /* Having a texture handle set implies that the device still exists. */ 5785 if (surface->Handle) 5786 ddraw_free_handle(&surface->ddraw->d3ddevice->handle_table, surface->Handle - 1, DDRAW_HANDLE_SURFACE); 5787 5788 /* Reduce the ddraw surface count. */ 5789 list_remove(&surface->surface_list_entry); 5790 5791 if (surface->clipper) 5792 IDirectDrawClipper_Release(&surface->clipper->IDirectDrawClipper_iface); 5793 5794 if (surface == surface->ddraw->primary) 5795 surface->ddraw->primary = NULL; 5796 5797 wined3d_private_store_cleanup(&surface->private_store); 5798 5799 heap_free(surface); 5800 } 5801 5802 static const struct wined3d_parent_ops ddraw_surface_wined3d_parent_ops = 5803 { 5804 ddraw_surface_wined3d_object_destroyed, 5805 }; 5806 5807 static void STDMETHODCALLTYPE ddraw_texture_wined3d_object_destroyed(void *parent) 5808 { 5809 TRACE("parent %p.\n", parent); 5810 5811 heap_free(parent); 5812 } 5813 5814 static const struct wined3d_parent_ops ddraw_texture_wined3d_parent_ops = 5815 { 5816 ddraw_texture_wined3d_object_destroyed, 5817 }; 5818 5819 static HRESULT CDECL ddraw_reset_enum_callback(struct wined3d_resource *resource) 5820 { 5821 return DD_OK; 5822 } 5823 5824 HRESULT ddraw_surface_create(struct ddraw *ddraw, const DDSURFACEDESC2 *surface_desc, 5825 struct ddraw_surface **surface, IUnknown *outer_unknown, unsigned int version) 5826 { 5827 struct wined3d_sub_resource_desc wined3d_mip_desc; 5828 struct ddraw_surface *root, *mip, **attach; 5829 struct wined3d_resource_desc wined3d_desc; 5830 struct wined3d_texture *wined3d_texture; 5831 struct wined3d_display_mode mode; 5832 DDSURFACEDESC2 *desc, *mip_desc; 5833 struct ddraw_texture *texture; 5834 unsigned int layers = 1; 5835 unsigned int pitch = 0; 5836 UINT levels, i, j; 5837 HRESULT hr; 5838 5839 TRACE("ddraw %p, surface_desc %p, surface %p, outer_unknown %p, version %u.\n", 5840 ddraw, surface_desc, surface, outer_unknown, version); 5841 if (TRACE_ON(ddraw)) 5842 { 5843 TRACE("Requesting surface desc:\n"); 5844 DDRAW_dump_surface_desc(surface_desc); 5845 } 5846 5847 if (outer_unknown) 5848 return CLASS_E_NOAGGREGATION; 5849 5850 if (!surface) 5851 return E_POINTER; 5852 5853 if (!(texture = heap_alloc(sizeof(*texture)))) 5854 return E_OUTOFMEMORY; 5855 5856 texture->version = version; 5857 texture->surface_desc = *surface_desc; 5858 desc = &texture->surface_desc; 5859 5860 /* Ensure DDSD_CAPS is always set. */ 5861 desc->dwFlags |= DDSD_CAPS; 5862 5863 if (desc->ddsCaps.dwCaps & DDSCAPS_FLIP) 5864 { 5865 if (!(desc->dwFlags & DDSD_BACKBUFFERCOUNT) || !desc->u5.dwBackBufferCount) 5866 { 5867 WARN("Tried to create a flippable surface without any back buffers.\n"); 5868 heap_free(texture); 5869 return DDERR_INVALIDCAPS; 5870 } 5871 5872 if (!(desc->ddsCaps.dwCaps & DDSCAPS_COMPLEX)) 5873 { 5874 WARN("Tried to create a flippable surface without DDSCAPS_COMPLEX.\n"); 5875 heap_free(texture); 5876 return DDERR_INVALIDCAPS; 5877 } 5878 5879 if (desc->ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP) 5880 { 5881 WARN("Tried to create a flippable cubemap.\n"); 5882 heap_free(texture); 5883 return DDERR_INVALIDPARAMS; 5884 } 5885 5886 if (desc->ddsCaps.dwCaps & DDSCAPS_TEXTURE) 5887 { 5888 FIXME("Flippable textures not implemented.\n"); 5889 heap_free(texture); 5890 return DDERR_INVALIDCAPS; 5891 } 5892 } 5893 else 5894 { 5895 if (desc->dwFlags & DDSD_BACKBUFFERCOUNT) 5896 { 5897 WARN("Tried to specify a back buffer count for a non-flippable surface.\n"); 5898 hr = desc->ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP ? DDERR_INVALIDPARAMS : DDERR_INVALIDCAPS; 5899 heap_free(texture); 5900 return hr; 5901 } 5902 } 5903 5904 if (desc->ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE) 5905 { 5906 if (desc->ddsCaps.dwCaps & DDSCAPS_TEXTURE) 5907 { 5908 WARN("Tried to create a primary surface with DDSCAPS_TEXTURE.\n"); 5909 heap_free(texture); 5910 return DDERR_INVALIDCAPS; 5911 } 5912 5913 if ((desc->ddsCaps.dwCaps & DDSCAPS_COMPLEX) && !(desc->ddsCaps.dwCaps & DDSCAPS_FLIP)) 5914 { 5915 WARN("Tried to create a flippable primary surface without both DDSCAPS_FLIP and DDSCAPS_COMPLEX.\n"); 5916 heap_free(texture); 5917 return DDERR_INVALIDCAPS; 5918 } 5919 5920 if ((desc->ddsCaps.dwCaps & DDSCAPS_FLIP) && !(ddraw->cooperative_level & DDSCL_EXCLUSIVE)) 5921 { 5922 WARN("Tried to create a flippable primary surface without DDSCL_EXCLUSIVE.\n"); 5923 heap_free(texture); 5924 return DDERR_NOEXCLUSIVEMODE; 5925 } 5926 } 5927 5928 /* This is a special case in ddrawex, but not allowed in ddraw. */ 5929 if ((desc->ddsCaps.dwCaps & (DDSCAPS_VIDEOMEMORY | DDSCAPS_SYSTEMMEMORY)) 5930 == (DDSCAPS_VIDEOMEMORY | DDSCAPS_SYSTEMMEMORY)) 5931 { 5932 WARN("Tried to create a surface in both system and video memory.\n"); 5933 heap_free(texture); 5934 return DDERR_INVALIDCAPS; 5935 } 5936 5937 if ((desc->ddsCaps.dwCaps & (DDSCAPS_ALLOCONLOAD | DDSCAPS_MIPMAP)) 5938 && !(desc->ddsCaps.dwCaps & DDSCAPS_TEXTURE)) 5939 { 5940 WARN("Caps %#x require DDSCAPS_TEXTURE.\n", desc->ddsCaps.dwCaps); 5941 heap_free(texture); 5942 return DDERR_INVALIDCAPS; 5943 } 5944 5945 if ((desc->ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP_ALLFACES) 5946 && !(desc->ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP)) 5947 { 5948 WARN("Cube map faces requested without cube map flag.\n"); 5949 heap_free(texture); 5950 return DDERR_INVALIDCAPS; 5951 } 5952 5953 if ((desc->ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP) 5954 && !(desc->ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP_ALLFACES)) 5955 { 5956 WARN("Cube map without faces requested.\n"); 5957 heap_free(texture); 5958 return DDERR_INVALIDPARAMS; 5959 } 5960 5961 if ((desc->ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP) 5962 && (desc->ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP_ALLFACES) != DDSCAPS2_CUBEMAP_ALLFACES) 5963 FIXME("Partial cube maps not implemented.\n"); 5964 5965 if (desc->ddsCaps.dwCaps2 & (DDSCAPS2_TEXTUREMANAGE | DDSCAPS2_D3DTEXTUREMANAGE)) 5966 { 5967 if (!(desc->ddsCaps.dwCaps & DDSCAPS_TEXTURE)) 5968 { 5969 WARN("DDSCAPS2_TEXTUREMANAGE used without DDSCAPS_TEXTURE, returning DDERR_INVALIDCAPS.\n"); 5970 heap_free(texture); 5971 return DDERR_INVALIDCAPS; 5972 } 5973 if (desc->ddsCaps.dwCaps & (DDSCAPS_VIDEOMEMORY | DDSCAPS_SYSTEMMEMORY)) 5974 { 5975 WARN("DDSCAPS2_TEXTUREMANAGE used width DDSCAPS_VIDEOMEMORY " 5976 "or DDSCAPS_SYSTEMMEMORY, returning DDERR_INVALIDCAPS.\n"); 5977 heap_free(texture); 5978 return DDERR_INVALIDCAPS; 5979 } 5980 } 5981 5982 if (FAILED(hr = wined3d_get_adapter_display_mode(ddraw->wined3d, WINED3DADAPTER_DEFAULT, &mode, NULL))) 5983 { 5984 ERR("Failed to get display mode, hr %#x.\n", hr); 5985 heap_free(texture); 5986 return hr_ddraw_from_wined3d(hr); 5987 } 5988 5989 /* No pixelformat given? Use the current screen format. */ 5990 if (!(desc->dwFlags & DDSD_PIXELFORMAT)) 5991 { 5992 desc->dwFlags |= DDSD_PIXELFORMAT; 5993 desc->u4.ddpfPixelFormat.dwSize = sizeof(desc->u4.ddpfPixelFormat); 5994 ddrawformat_from_wined3dformat(&desc->u4.ddpfPixelFormat, mode.format_id); 5995 } 5996 5997 wined3d_desc.resource_type = WINED3D_RTYPE_TEXTURE_2D; 5998 wined3d_desc.format = wined3dformat_from_ddrawformat(&desc->u4.ddpfPixelFormat); 5999 if (wined3d_desc.format == WINED3DFMT_UNKNOWN) 6000 { 6001 WARN("Unsupported / unknown pixelformat.\n"); 6002 heap_free(texture); 6003 return DDERR_INVALIDPIXELFORMAT; 6004 } 6005 6006 /* No width or no height? Use the screen size. */ 6007 if (!(desc->dwFlags & DDSD_WIDTH) || !(desc->dwFlags & DDSD_HEIGHT)) 6008 { 6009 if (!(desc->ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE)) 6010 { 6011 WARN("No width / height specified.\n"); 6012 heap_free(texture); 6013 return DDERR_INVALIDPARAMS; 6014 } 6015 6016 desc->dwFlags |= DDSD_WIDTH | DDSD_HEIGHT; 6017 desc->dwWidth = mode.width; 6018 desc->dwHeight = mode.height; 6019 } 6020 6021 if (!desc->dwWidth || !desc->dwHeight) 6022 { 6023 heap_free(texture); 6024 return DDERR_INVALIDPARAMS; 6025 } 6026 6027 if (desc->ddsCaps.dwCaps & DDSCAPS_FLIP) 6028 desc->ddsCaps.dwCaps |= DDSCAPS_FRONTBUFFER; 6029 6030 if (desc->ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE) 6031 { 6032 /* The first surface is a front buffer, the back buffers are created 6033 * afterwards. */ 6034 desc->ddsCaps.dwCaps |= DDSCAPS_VISIBLE; 6035 if (ddraw->cooperative_level & DDSCL_EXCLUSIVE) 6036 { 6037 struct wined3d_swapchain_desc swapchain_desc; 6038 6039 wined3d_swapchain_get_desc(ddraw->wined3d_swapchain, &swapchain_desc); 6040 swapchain_desc.backbuffer_width = mode.width; 6041 swapchain_desc.backbuffer_height = mode.height; 6042 swapchain_desc.backbuffer_format = mode.format_id; 6043 6044 if (FAILED(hr = wined3d_device_reset(ddraw->wined3d_device, 6045 &swapchain_desc, NULL, ddraw_reset_enum_callback, TRUE))) 6046 { 6047 ERR("Failed to reset device.\n"); 6048 heap_free(texture); 6049 return hr_ddraw_from_wined3d(hr); 6050 } 6051 6052 wined3d_device_set_render_state(ddraw->wined3d_device, WINED3D_RS_ZENABLE, 6053 !!swapchain_desc.enable_auto_depth_stencil); 6054 } 6055 } 6056 6057 wined3d_desc.multisample_type = WINED3D_MULTISAMPLE_NONE; 6058 wined3d_desc.multisample_quality = 0; 6059 wined3d_desc.usage = 0; 6060 wined3d_desc.access = WINED3D_RESOURCE_ACCESS_GPU | WINED3D_RESOURCE_ACCESS_MAP_R | WINED3D_RESOURCE_ACCESS_MAP_W; 6061 wined3d_desc.width = desc->dwWidth; 6062 wined3d_desc.height = desc->dwHeight; 6063 wined3d_desc.depth = 1; 6064 wined3d_desc.size = 0; 6065 6066 if ((desc->ddsCaps.dwCaps & DDSCAPS_3DDEVICE) && (ddraw->flags & DDRAW_NO3D)) 6067 { 6068 WARN("The application requests a 3D capable surface, but the ddraw object was created without 3D support.\n"); 6069 /* Do not fail surface creation, only fail 3D device creation. */ 6070 } 6071 6072 /* Mipmap count fixes */ 6073 if (desc->ddsCaps.dwCaps & DDSCAPS_MIPMAP) 6074 { 6075 if (desc->ddsCaps.dwCaps & DDSCAPS_COMPLEX) 6076 { 6077 if (desc->dwFlags & DDSD_MIPMAPCOUNT) 6078 { 6079 /* Mipmap count is given, should not be 0. */ 6080 if (!desc->u2.dwMipMapCount) 6081 { 6082 heap_free(texture); 6083 return DDERR_INVALIDPARAMS; 6084 } 6085 } 6086 else 6087 { 6088 /* Undocumented feature: Create sublevels until either the 6089 * width or the height is 1. */ 6090 if (version == 7) 6091 desc->u2.dwMipMapCount = wined3d_log2i(max(desc->dwWidth, desc->dwHeight)) + 1; 6092 else 6093 desc->u2.dwMipMapCount = wined3d_log2i(min(desc->dwWidth, desc->dwHeight)) + 1; 6094 } 6095 } 6096 else 6097 { 6098 desc->u2.dwMipMapCount = 1; 6099 } 6100 6101 desc->dwFlags |= DDSD_MIPMAPCOUNT; 6102 levels = desc->u2.dwMipMapCount; 6103 } 6104 else 6105 { 6106 levels = 1; 6107 } 6108 6109 if (!(desc->ddsCaps.dwCaps & (DDSCAPS_VIDEOMEMORY | DDSCAPS_SYSTEMMEMORY))) 6110 { 6111 if (!(desc->ddsCaps.dwCaps2 & (DDSCAPS2_TEXTUREMANAGE | DDSCAPS2_D3DTEXTUREMANAGE))) 6112 { 6113 DWORD usage = 0; 6114 6115 if (desc->ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP) 6116 usage |= WINED3DUSAGE_LEGACY_CUBEMAP | WINED3DUSAGE_TEXTURE; 6117 else if (desc->ddsCaps.dwCaps & DDSCAPS_TEXTURE) 6118 usage |= WINED3DUSAGE_TEXTURE; 6119 6120 if (desc->ddsCaps.dwCaps & DDSCAPS_ZBUFFER) 6121 usage = WINED3DUSAGE_DEPTHSTENCIL; 6122 else if (desc->ddsCaps.dwCaps & DDSCAPS_3DDEVICE) 6123 usage = WINED3DUSAGE_RENDERTARGET; 6124 6125 if (SUCCEEDED(hr = wined3d_check_device_format(ddraw->wined3d, WINED3DADAPTER_DEFAULT, 6126 WINED3D_DEVICE_TYPE_HAL, mode.format_id, usage, WINED3D_RTYPE_TEXTURE_2D, wined3d_desc.format))) 6127 desc->ddsCaps.dwCaps |= DDSCAPS_VIDEOMEMORY; 6128 else 6129 desc->ddsCaps.dwCaps |= DDSCAPS_SYSTEMMEMORY; 6130 } 6131 else if (!(desc->ddsCaps.dwCaps & DDSCAPS_TEXTURE)) 6132 { 6133 /* Tests show surfaces without memory flags get these flags added 6134 * right after creation. */ 6135 desc->ddsCaps.dwCaps |= DDSCAPS_LOCALVIDMEM | DDSCAPS_VIDEOMEMORY; 6136 } 6137 } 6138 6139 if ((desc->ddsCaps.dwCaps & (DDSCAPS_OVERLAY | DDSCAPS_SYSTEMMEMORY)) 6140 == (DDSCAPS_OVERLAY | DDSCAPS_SYSTEMMEMORY)) 6141 { 6142 WARN("System memory overlays are not allowed.\n"); 6143 heap_free(texture); 6144 return DDERR_NOOVERLAYHW; 6145 } 6146 6147 if (desc->ddsCaps.dwCaps & DDSCAPS_SYSTEMMEMORY) 6148 { 6149 /* 6150 * The ddraw RGB device allows to use system memory surfaces as rendering target. 6151 * This does not cause problems because the RGB device does software rasterization 6152 * though it will fail with hardware accelerated ddraw. In order to be partially 6153 * compatible with games requesting explicitly the RGB device, we ignore the 6154 * specified location and try to create rendering targets in video memory if 6155 * possible. 6156 */ 6157 if ((desc->ddsCaps.dwCaps & DDSCAPS_3DDEVICE) && 6158 SUCCEEDED(hr = wined3d_check_device_format(ddraw->wined3d, WINED3DADAPTER_DEFAULT, 6159 WINED3D_DEVICE_TYPE_HAL, mode.format_id, WINED3DUSAGE_RENDERTARGET, 6160 WINED3D_RTYPE_TEXTURE_2D, wined3d_desc.format))) 6161 { 6162 FIXME("Application wants to create rendering target in system memory, using video memory instead\n"); 6163 wined3d_desc.usage |= WINED3DUSAGE_RENDERTARGET; 6164 } 6165 else 6166 wined3d_desc.access = WINED3D_RESOURCE_ACCESS_CPU 6167 | WINED3D_RESOURCE_ACCESS_MAP_R | WINED3D_RESOURCE_ACCESS_MAP_W; 6168 } 6169 else 6170 { 6171 if (desc->ddsCaps.dwCaps & DDSCAPS_TEXTURE) 6172 wined3d_desc.usage |= WINED3DUSAGE_TEXTURE; 6173 if (desc->ddsCaps.dwCaps & DDSCAPS_ZBUFFER) 6174 wined3d_desc.usage |= WINED3DUSAGE_DEPTHSTENCIL; 6175 else if (desc->ddsCaps.dwCaps & DDSCAPS_3DDEVICE) 6176 wined3d_desc.usage |= WINED3DUSAGE_RENDERTARGET; 6177 6178 if (desc->ddsCaps.dwCaps2 & (DDSCAPS2_TEXTUREMANAGE | DDSCAPS2_D3DTEXTUREMANAGE)) 6179 { 6180 wined3d_desc.access = WINED3D_RESOURCE_ACCESS_GPU | WINED3D_RESOURCE_ACCESS_CPU 6181 | WINED3D_RESOURCE_ACCESS_MAP_R | WINED3D_RESOURCE_ACCESS_MAP_W; 6182 /* Managed textures have the system memory flag set. */ 6183 desc->ddsCaps.dwCaps |= DDSCAPS_SYSTEMMEMORY; 6184 } 6185 else if (desc->ddsCaps.dwCaps & DDSCAPS_VIDEOMEMORY) 6186 { 6187 /* Videomemory adds localvidmem. This is mutually exclusive with 6188 * systemmemory and texturemanage. */ 6189 desc->ddsCaps.dwCaps |= DDSCAPS_LOCALVIDMEM; 6190 wined3d_desc.usage |= WINED3DUSAGE_DYNAMIC; 6191 } 6192 } 6193 6194 if (desc->dwFlags & DDSD_LPSURFACE) 6195 { 6196 if (wined3d_desc.access & WINED3D_RESOURCE_ACCESS_GPU) 6197 { 6198 WARN("User memory surfaces should not be GPU accessible.\n"); 6199 heap_free(texture); 6200 return DDERR_INVALIDCAPS; 6201 } 6202 6203 if (version < 4) 6204 { 6205 WARN("User memory surfaces not supported before version 4.\n"); 6206 heap_free(texture); 6207 return DDERR_INVALIDPARAMS; 6208 } 6209 6210 if (!desc->lpSurface) 6211 { 6212 WARN("NULL surface memory pointer specified.\n"); 6213 heap_free(texture); 6214 return DDERR_INVALIDPARAMS; 6215 } 6216 6217 if (format_is_compressed(&desc->u4.ddpfPixelFormat)) 6218 { 6219 if (version != 4 && (desc->dwFlags & DDSD_PITCH)) 6220 { 6221 WARN("Pitch specified on a compressed user memory surface.\n"); 6222 heap_free(texture); 6223 return DDERR_INVALIDPARAMS; 6224 } 6225 6226 if (!(desc->dwFlags & (DDSD_LINEARSIZE | DDSD_PITCH))) 6227 { 6228 WARN("Compressed user memory surfaces should explicitly specify the linear size.\n"); 6229 heap_free(texture); 6230 return DDERR_INVALIDPARAMS; 6231 } 6232 6233 if ((desc->dwFlags & DDSD_LINEARSIZE) 6234 && desc->u1.dwLinearSize < wined3d_calculate_format_pitch(ddraw->wined3d, WINED3DADAPTER_DEFAULT, 6235 wined3d_desc.format, wined3d_desc.width) * ((desc->dwHeight + 3) / 4)) 6236 { 6237 WARN("Invalid linear size %u specified.\n", desc->u1.dwLinearSize); 6238 heap_free(texture); 6239 return DDERR_INVALIDPARAMS; 6240 } 6241 } 6242 else 6243 { 6244 if (!(desc->dwFlags & DDSD_PITCH)) 6245 { 6246 WARN("User memory surfaces should explicitly specify the pitch.\n"); 6247 heap_free(texture); 6248 return DDERR_INVALIDPARAMS; 6249 } 6250 6251 if (desc->u1.lPitch < wined3d_calculate_format_pitch(ddraw->wined3d, WINED3DADAPTER_DEFAULT, 6252 wined3d_desc.format, wined3d_desc.width) || desc->u1.lPitch & 3) 6253 { 6254 WARN("Invalid pitch %u specified.\n", desc->u1.lPitch); 6255 heap_free(texture); 6256 return DDERR_INVALIDPARAMS; 6257 } 6258 6259 pitch = desc->u1.lPitch; 6260 } 6261 } 6262 6263 if (((desc->dwFlags & DDSD_CKDESTOVERLAY) 6264 && desc->u3.ddckCKDestOverlay.dwColorSpaceLowValue != desc->u3.ddckCKDestOverlay.dwColorSpaceHighValue) 6265 || ((desc->dwFlags & DDSD_CKDESTBLT) 6266 && desc->ddckCKDestBlt.dwColorSpaceLowValue != desc->ddckCKDestBlt.dwColorSpaceHighValue) 6267 || ((desc->dwFlags & DDSD_CKSRCOVERLAY) 6268 && desc->ddckCKSrcOverlay.dwColorSpaceLowValue != desc->ddckCKSrcOverlay.dwColorSpaceHighValue) 6269 || ((desc->dwFlags & DDSD_CKSRCBLT) 6270 && desc->ddckCKSrcBlt.dwColorSpaceLowValue != desc->ddckCKSrcBlt.dwColorSpaceHighValue)) 6271 { 6272 WARN("Range color keys not supported, returning DDERR_NOCOLORKEYHW.\n"); 6273 heap_free(texture); 6274 return DDERR_NOCOLORKEYHW; 6275 } 6276 6277 if (desc->ddsCaps.dwCaps & (DDSCAPS_OVERLAY)) 6278 wined3d_desc.usage |= WINED3DUSAGE_OVERLAY; 6279 6280 if (desc->ddsCaps.dwCaps & DDSCAPS_OWNDC) 6281 wined3d_desc.usage |= WINED3DUSAGE_OWNDC; 6282 6283 if (desc->ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP) 6284 { 6285 wined3d_desc.usage |= WINED3DUSAGE_LEGACY_CUBEMAP; 6286 layers = 6; 6287 } 6288 6289 /* Some applications assume surfaces will always be mapped at the same 6290 * address. Some of those also assume that this address is valid even when 6291 * the surface isn't mapped, and that updates done this way will be 6292 * visible on the screen. The game Nox is such an application, 6293 * Commandos: Behind Enemy Lines is another. Setting 6294 * WINED3D_TEXTURE_CREATE_GET_DC_LENIENT will ensure this. */ 6295 if (FAILED(hr = wined3d_texture_create(ddraw->wined3d_device, &wined3d_desc, layers, levels, 6296 WINED3D_TEXTURE_CREATE_GET_DC_LENIENT, NULL, texture, 6297 &ddraw_texture_wined3d_parent_ops, &wined3d_texture))) 6298 { 6299 WARN("Failed to create wined3d texture, hr %#x.\n", hr); 6300 heap_free(texture); 6301 return hr_ddraw_from_wined3d(hr); 6302 } 6303 6304 root = wined3d_texture_get_sub_resource_parent(wined3d_texture, 0); 6305 wined3d_texture_decref(wined3d_texture); 6306 root->is_complex_root = TRUE; 6307 texture->root = root; 6308 wined3d_device_incref(texture->wined3d_device = ddraw->wined3d_device); 6309 6310 if (desc->dwFlags & DDSD_CKDESTOVERLAY) 6311 wined3d_texture_set_color_key(wined3d_texture, DDCKEY_DESTOVERLAY, 6312 (struct wined3d_color_key *)&desc->u3.ddckCKDestOverlay); 6313 if (desc->dwFlags & DDSD_CKDESTBLT) 6314 wined3d_texture_set_color_key(wined3d_texture, DDCKEY_DESTBLT, 6315 (struct wined3d_color_key *)&desc->ddckCKDestBlt); 6316 if (desc->dwFlags & DDSD_CKSRCOVERLAY) 6317 wined3d_texture_set_color_key(wined3d_texture, DDCKEY_SRCOVERLAY, 6318 (struct wined3d_color_key *)&desc->ddckCKSrcOverlay); 6319 if (desc->dwFlags & DDSD_CKSRCBLT) 6320 wined3d_texture_set_color_key(wined3d_texture, DDCKEY_SRCBLT, 6321 (struct wined3d_color_key *)&desc->ddckCKSrcBlt); 6322 6323 for (i = 0; i < layers; ++i) 6324 { 6325 attach = &root->complex_array[layers - 1 - i]; 6326 6327 for (j = 0; j < levels; ++j) 6328 { 6329 mip = wined3d_texture_get_sub_resource_parent(wined3d_texture, i * levels + j); 6330 mip_desc = &mip->surface_desc; 6331 6332 if (j) 6333 { 6334 wined3d_texture_get_sub_resource_desc(wined3d_texture, i * levels + j, &wined3d_mip_desc); 6335 mip_desc->dwWidth = wined3d_mip_desc.width; 6336 mip_desc->dwHeight = wined3d_mip_desc.height; 6337 6338 mip_desc->ddsCaps.dwCaps2 |= DDSCAPS2_MIPMAPSUBLEVEL; 6339 } 6340 else 6341 { 6342 mip_desc->ddsCaps.dwCaps2 &= ~DDSCAPS2_MIPMAPSUBLEVEL; 6343 } 6344 6345 if (mip_desc->ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP) 6346 { 6347 mip_desc->ddsCaps.dwCaps2 &= ~DDSCAPS2_CUBEMAP_ALLFACES; 6348 6349 switch (i) 6350 { 6351 case WINED3D_CUBEMAP_FACE_POSITIVE_X: 6352 mip_desc->ddsCaps.dwCaps2 |= DDSCAPS2_CUBEMAP_POSITIVEX; 6353 break; 6354 case WINED3D_CUBEMAP_FACE_NEGATIVE_X: 6355 mip_desc->ddsCaps.dwCaps2 |= DDSCAPS2_CUBEMAP_NEGATIVEX; 6356 break; 6357 case WINED3D_CUBEMAP_FACE_POSITIVE_Y: 6358 mip_desc->ddsCaps.dwCaps2 |= DDSCAPS2_CUBEMAP_POSITIVEY; 6359 break; 6360 case WINED3D_CUBEMAP_FACE_NEGATIVE_Y: 6361 mip_desc->ddsCaps.dwCaps2 |= DDSCAPS2_CUBEMAP_NEGATIVEY; 6362 break; 6363 case WINED3D_CUBEMAP_FACE_POSITIVE_Z: 6364 mip_desc->ddsCaps.dwCaps2 |= DDSCAPS2_CUBEMAP_POSITIVEZ; 6365 break; 6366 case WINED3D_CUBEMAP_FACE_NEGATIVE_Z: 6367 mip_desc->ddsCaps.dwCaps2 |= DDSCAPS2_CUBEMAP_NEGATIVEZ; 6368 break; 6369 } 6370 6371 } 6372 6373 if (mip == root) 6374 continue; 6375 6376 *attach = mip; 6377 attach = &mip->complex_array[0]; 6378 } 6379 } 6380 6381 if ((desc->dwFlags & DDSD_LPSURFACE) && FAILED(hr = wined3d_texture_update_desc(wined3d_texture, 6382 wined3d_desc.width, wined3d_desc.height, wined3d_desc.format, 6383 WINED3D_MULTISAMPLE_NONE, 0, desc->lpSurface, pitch))) 6384 { 6385 ERR("Failed to set surface memory, hr %#x.\n", hr); 6386 goto fail; 6387 } 6388 6389 if (desc->dwFlags & DDSD_BACKBUFFERCOUNT) 6390 { 6391 unsigned int count = desc->u5.dwBackBufferCount; 6392 struct ddraw_surface *last = root; 6393 6394 attach = &last->complex_array[0]; 6395 for (i = 0; i < count; ++i) 6396 { 6397 if (!(texture = heap_alloc(sizeof(*texture)))) 6398 { 6399 hr = E_OUTOFMEMORY; 6400 goto fail; 6401 } 6402 6403 texture->version = version; 6404 texture->surface_desc = root->surface_desc; 6405 desc = &texture->surface_desc; 6406 6407 /* Only one surface in the flipping chain is a back buffer, one is 6408 * a front buffer, the others are just flippable surfaces. */ 6409 desc->ddsCaps.dwCaps &= ~(DDSCAPS_VISIBLE | DDSCAPS_PRIMARYSURFACE | DDSCAPS_FRONTBUFFER 6410 | DDSCAPS_BACKBUFFER); 6411 if (!i) 6412 desc->ddsCaps.dwCaps |= DDSCAPS_BACKBUFFER; 6413 desc->u5.dwBackBufferCount = 0; 6414 6415 if (FAILED(hr = wined3d_texture_create(ddraw->wined3d_device, &wined3d_desc, 1, 1, 6416 WINED3D_TEXTURE_CREATE_GET_DC_LENIENT, NULL, texture, 6417 &ddraw_texture_wined3d_parent_ops, &wined3d_texture))) 6418 { 6419 heap_free(texture); 6420 hr = hr_ddraw_from_wined3d(hr); 6421 goto fail; 6422 } 6423 6424 last = wined3d_texture_get_sub_resource_parent(wined3d_texture, 0); 6425 wined3d_texture_decref(wined3d_texture); 6426 texture->root = last; 6427 wined3d_device_incref(texture->wined3d_device = ddraw->wined3d_device); 6428 6429 if (desc->dwFlags & DDSD_CKDESTOVERLAY) 6430 wined3d_texture_set_color_key(wined3d_texture, DDCKEY_DESTOVERLAY, 6431 (struct wined3d_color_key *)&desc->u3.ddckCKDestOverlay); 6432 if (desc->dwFlags & DDSD_CKDESTBLT) 6433 wined3d_texture_set_color_key(wined3d_texture, DDCKEY_DESTBLT, 6434 (struct wined3d_color_key *)&desc->ddckCKDestBlt); 6435 if (desc->dwFlags & DDSD_CKSRCOVERLAY) 6436 wined3d_texture_set_color_key(wined3d_texture, DDCKEY_SRCOVERLAY, 6437 (struct wined3d_color_key *)&desc->ddckCKSrcOverlay); 6438 if (desc->dwFlags & DDSD_CKSRCBLT) 6439 wined3d_texture_set_color_key(wined3d_texture, DDCKEY_SRCBLT, 6440 (struct wined3d_color_key *)&desc->ddckCKSrcBlt); 6441 6442 *attach = last; 6443 attach = &last->complex_array[0]; 6444 } 6445 *attach = root; 6446 } 6447 6448 if (surface_desc->ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE) 6449 ddraw->primary = root; 6450 *surface = root; 6451 6452 return DD_OK; 6453 6454 fail: 6455 if (version == 7) 6456 IDirectDrawSurface7_Release(&root->IDirectDrawSurface7_iface); 6457 else if (version == 4) 6458 IDirectDrawSurface4_Release(&root->IDirectDrawSurface4_iface); 6459 else 6460 IDirectDrawSurface_Release(&root->IDirectDrawSurface_iface); 6461 6462 return hr; 6463 } 6464 6465 void ddraw_surface_init(struct ddraw_surface *surface, struct ddraw *ddraw, 6466 struct wined3d_texture *wined3d_texture, unsigned int sub_resource_idx, 6467 const struct wined3d_parent_ops **parent_ops) 6468 { 6469 struct ddraw_texture *texture = wined3d_texture_get_parent(wined3d_texture); 6470 unsigned int texture_level, row_pitch, slice_pitch; 6471 DDSURFACEDESC2 *desc = &surface->surface_desc; 6472 unsigned int version = texture->version; 6473 6474 surface->IDirectDrawSurface7_iface.lpVtbl = &ddraw_surface7_vtbl; 6475 surface->IDirectDrawSurface4_iface.lpVtbl = &ddraw_surface4_vtbl; 6476 surface->IDirectDrawSurface3_iface.lpVtbl = &ddraw_surface3_vtbl; 6477 surface->IDirectDrawSurface2_iface.lpVtbl = &ddraw_surface2_vtbl; 6478 surface->IDirectDrawSurface_iface.lpVtbl = &ddraw_surface1_vtbl; 6479 surface->IDirectDrawGammaControl_iface.lpVtbl = &ddraw_gamma_control_vtbl; 6480 surface->IDirect3DTexture2_iface.lpVtbl = &d3d_texture2_vtbl; 6481 surface->IDirect3DTexture_iface.lpVtbl = &d3d_texture1_vtbl; 6482 surface->iface_count = 1; 6483 surface->version = version; 6484 surface->ddraw = ddraw; 6485 6486 if (version == 7) 6487 { 6488 surface->ref7 = 1; 6489 surface->texture_outer = (IUnknown *)&surface->IDirectDrawSurface7_iface; 6490 } 6491 else if (version == 4) 6492 { 6493 surface->ref4 = 1; 6494 surface->texture_outer = (IUnknown *)&surface->IDirectDrawSurface4_iface; 6495 } 6496 else 6497 { 6498 surface->ref1 = 1; 6499 surface->texture_outer = (IUnknown *)&surface->IDirectDrawSurface_iface; 6500 } 6501 6502 *desc = texture->surface_desc; 6503 surface->first_attached = surface; 6504 6505 texture_level = desc->ddsCaps.dwCaps & DDSCAPS_MIPMAP ? sub_resource_idx % desc->u2.dwMipMapCount : 0; 6506 wined3d_texture_get_pitch(wined3d_texture, texture_level, &row_pitch, &slice_pitch); 6507 if (format_is_compressed(&desc->u4.ddpfPixelFormat)) 6508 { 6509 if (desc->dwFlags & DDSD_LPSURFACE) 6510 desc->u1.dwLinearSize = ~0u; 6511 else 6512 desc->u1.dwLinearSize = slice_pitch; 6513 desc->dwFlags |= DDSD_LINEARSIZE; 6514 desc->dwFlags &= ~(DDSD_LPSURFACE | DDSD_PITCH); 6515 } 6516 else 6517 { 6518 if (!(desc->dwFlags & DDSD_LPSURFACE)) 6519 desc->u1.lPitch = row_pitch; 6520 desc->dwFlags |= DDSD_PITCH; 6521 desc->dwFlags &= ~(DDSD_LPSURFACE | DDSD_LINEARSIZE); 6522 } 6523 desc->lpSurface = NULL; 6524 6525 wined3d_texture_incref(surface->wined3d_texture = wined3d_texture); 6526 surface->sub_resource_idx = sub_resource_idx; 6527 *parent_ops = &ddraw_surface_wined3d_parent_ops; 6528 6529 wined3d_private_store_init(&surface->private_store); 6530 } 6531 6532 static void STDMETHODCALLTYPE view_wined3d_object_destroyed(void *parent) 6533 { 6534 struct ddraw_surface *surface = parent; 6535 6536 /* If the surface reference count drops to zero, we release our reference 6537 * to the view, but don't clear the pointer yet, in case e.g. a 6538 * GetRenderTarget() call brings the surface back before the view is 6539 * actually destroyed. When the view is destroyed, we need to clear the 6540 * pointer, or a subsequent surface AddRef() would reference it again. 6541 * 6542 * This is safe because as long as the view still has a reference to the 6543 * texture, the surface is also still alive, and we're called before the 6544 * view releases that reference. */ 6545 surface->wined3d_rtv = NULL; 6546 } 6547 6548 static const struct wined3d_parent_ops ddraw_view_wined3d_parent_ops = 6549 { 6550 view_wined3d_object_destroyed, 6551 }; 6552 6553 struct wined3d_rendertarget_view *ddraw_surface_get_rendertarget_view(struct ddraw_surface *surface) 6554 { 6555 HRESULT hr; 6556 6557 if (surface->wined3d_rtv) 6558 return surface->wined3d_rtv; 6559 6560 if (FAILED(hr = wined3d_rendertarget_view_create_from_sub_resource(surface->wined3d_texture, 6561 surface->sub_resource_idx, surface, &ddraw_view_wined3d_parent_ops, &surface->wined3d_rtv))) 6562 { 6563 ERR("Failed to create rendertarget view, hr %#x.\n", hr); 6564 return NULL; 6565 } 6566 6567 return surface->wined3d_rtv; 6568 } 6569