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