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