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