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