1 /* DirectDraw Surface Implementation
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
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.
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.
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
24 #include "ddraw_private.h"
26 WINE_DEFAULT_DEBUG_CHANNEL(ddraw
);
27 WINE_DECLARE_DEBUG_CHANNEL(fps
);
29 static struct ddraw_surface
*unsafe_impl_from_IDirectDrawSurface2(IDirectDrawSurface2
*iface
);
30 static struct ddraw_surface
*unsafe_impl_from_IDirectDrawSurface3(IDirectDrawSurface3
*iface
);
32 static const struct wined3d_parent_ops ddraw_surface_wined3d_parent_ops
;
33 static const struct wined3d_parent_ops ddraw_texture_wined3d_parent_ops
;
34 static const struct wined3d_parent_ops ddraw_view_wined3d_parent_ops
;
36 static inline struct ddraw_surface
*impl_from_IDirectDrawGammaControl(IDirectDrawGammaControl
*iface
)
38 return CONTAINING_RECORD(iface
, struct ddraw_surface
, IDirectDrawGammaControl_iface
);
41 static BOOL
ddraw_surface_is_lost(const struct ddraw_surface
*surface
)
43 return ddraw_surface_can_be_lost(surface
)
44 && (surface
->ddraw
->device_state
!= DDRAW_DEVICE_STATE_OK
|| surface
->is_lost
);
47 static BOOL
ddraw_gdi_is_front(struct ddraw
*ddraw
)
49 struct ddraw_surface
*surface
;
51 if (!ddraw
->gdi_surface
|| !(surface
= wined3d_texture_get_sub_resource_parent(ddraw
->gdi_surface
, 0)))
54 return surface
->surface_desc
.ddsCaps
.dwCaps
& DDSCAPS_FRONTBUFFER
;
57 /* This is slow, of course. Also, in case of locks, we can't prevent other
58 * applications from drawing to the screen while we've locked the frontbuffer.
59 * We'd like to do this in wined3d instead, but for that to work wined3d needs
60 * to support windowless rendering first. */
61 HRESULT
ddraw_surface_update_frontbuffer(struct ddraw_surface
*surface
,
62 const RECT
*rect
, BOOL read
, unsigned int swap_interval
)
64 struct wined3d_texture
*dst_texture
, *wined3d_texture
;
65 struct ddraw
*ddraw
= surface
->ddraw
;
66 HDC surface_dc
, screen_dc
;
72 TRACE("surface %p, rect %s, read %#x, swap_interval %u.\n",
73 surface
, wine_dbgstr_rect(rect
), read
, swap_interval
);
75 if (ddraw
->flags
& DDRAW_SWAPPED
&& !read
)
77 ddraw
->flags
&= ~DDRAW_SWAPPED
;
83 SetRect(&r
, 0, 0, surface
->surface_desc
.dwWidth
, surface
->surface_desc
.dwHeight
);
89 w
= rect
->right
- rect
->left
;
90 h
= rect
->bottom
- rect
->top
;
95 if (!read
&& TRACE_ON(fps
))
97 DWORD time
= GetTickCount();
100 /* every 1.5 seconds */
101 if (time
- ddraw
->prev_frame_time
> 1500)
103 TRACE_(fps
)("%p @ approx %.2ffps\n",
104 ddraw
, 1000.0 * ddraw
->frames
/ (time
- ddraw
->prev_frame_time
));
105 ddraw
->prev_frame_time
= time
;
110 /* The interaction between ddraw and GDI drawing is not all that well
111 * documented, and somewhat arcane. In ddraw exclusive mode, GDI draws
112 * seemingly go to the *original* frontbuffer/primary surface, while ddraw
113 * draws/flips go to the *current* frontbuffer surface. The bottom line is
114 * that if the current frontbuffer is not the GDI frontbuffer, and there's
115 * e.g. a popup window in front of the ddraw swapchain window, we can't
116 * use wined3d_swapchain_present() to get the ddraw contents to the screen
117 * while in exclusive mode, since it would get obscured by the popup
118 * window. On the other hand, if the current frontbuffer *is* the GDI
119 * frontbuffer, that's what's supposed to happen; the popup should obscure
120 * (part of) the ddraw swapchain window.
122 * This affects the "Deer Hunter" demo, which uses a popup window and GDI
123 * draws to draw part of the user interface. See also the "fswindow"
124 * sample is the DirectX 7 SDK. */
125 if (ddraw
->swapchain_window
&& (!(ddraw
->cooperative_level
& DDSCL_EXCLUSIVE
)
126 || ddraw
->swapchain_window
== GetForegroundWindow() || ddraw_gdi_is_front(ddraw
)))
128 /* Nothing to do, we control the frontbuffer, or at least the parts we
134 dst_texture
= wined3d_swapchain_get_back_buffer(ddraw
->wined3d_swapchain
, 0);
136 dst_texture
= wined3d_swapchain_get_front_buffer(ddraw
->wined3d_swapchain
);
138 if (SUCCEEDED(hr
= wined3d_device_context_blt(ddraw
->immediate_context
, dst_texture
, 0, rect
,
139 ddraw_surface_get_any_texture(surface
, DDRAW_SURFACE_READ
), surface
->sub_resource_idx
, rect
, 0,
140 NULL
, WINED3D_TEXF_POINT
)) && swap_interval
)
142 hr
= wined3d_swapchain_present(ddraw
->wined3d_swapchain
, rect
, rect
, NULL
, swap_interval
, 0);
143 ddraw
->flags
|= DDRAW_SWAPPED
;
148 wined3d_texture
= ddraw_surface_get_default_texture(surface
, read
? (rect
? DDRAW_SURFACE_RW
: DDRAW_SURFACE_WRITE
)
149 : DDRAW_SURFACE_READ
);
151 if (FAILED(hr
= wined3d_texture_get_dc(wined3d_texture
, surface
->sub_resource_idx
, &surface_dc
)))
153 ERR("Failed to get surface DC, hr %#lx.\n", hr
);
156 if (surface
->palette
)
157 wined3d_palette_apply_to_dc(surface
->palette
->wined3d_palette
, surface_dc
);
159 if (!(screen_dc
= GetDC(NULL
)))
161 wined3d_texture_release_dc(wined3d_texture
, surface
->sub_resource_idx
, surface_dc
);
162 ERR("Failed to get screen DC.\n");
167 ret
= BitBlt(surface_dc
, x
, y
, w
, h
,
168 screen_dc
, x
, y
, SRCCOPY
);
170 ret
= BitBlt(screen_dc
, x
, y
, w
, h
,
171 surface_dc
, x
, y
, SRCCOPY
);
173 ReleaseDC(NULL
, screen_dc
);
174 wined3d_texture_release_dc(wined3d_texture
, surface
->sub_resource_idx
, surface_dc
);
178 ERR("Failed to blit to/from screen.\n");
185 /*****************************************************************************
186 * IUnknown parts follow
187 *****************************************************************************/
189 /*****************************************************************************
190 * IDirectDrawSurface7::QueryInterface
192 * A normal QueryInterface implementation. For QueryInterface rules
193 * see ddraw.c, IDirectDraw7::QueryInterface. This method
194 * can Query IDirectDrawSurface interfaces in all version, IDirect3DTexture
195 * in all versions, the IDirectDrawGammaControl interface and it can
196 * create an IDirect3DDevice. (Uses IDirect3D7::CreateDevice)
199 * riid: The interface id queried for
200 * obj: Address to write the pointer to
204 * E_NOINTERFACE if the requested interface wasn't found
206 *****************************************************************************/
207 static HRESULT WINAPI
ddraw_surface7_QueryInterface(IDirectDrawSurface7
*iface
, REFIID riid
, void **obj
)
209 struct ddraw_surface
*This
= impl_from_IDirectDrawSurface7(iface
);
211 TRACE("iface %p, riid %s, object %p.\n", iface
, debugstr_guid(riid
), obj
);
213 /* According to COM docs, if the QueryInterface fails, obj should be set to NULL */
217 return DDERR_INVALIDPARAMS
;
219 if (IsEqualGUID(riid
, &IID_IDirectDrawSurface7
))
221 IDirectDrawSurface7_AddRef(iface
);
223 TRACE("(%p) returning IDirectDrawSurface7 interface at %p\n", This
, *obj
);
227 if (IsEqualGUID(riid
, &IID_IDirectDrawSurface4
))
229 IDirectDrawSurface4_AddRef(&This
->IDirectDrawSurface4_iface
);
230 *obj
= &This
->IDirectDrawSurface4_iface
;
231 TRACE("(%p) returning IDirectDrawSurface4 interface at %p\n", This
, *obj
);
235 if (IsEqualGUID(riid
, &IID_IDirectDrawSurface3
))
237 IDirectDrawSurface3_AddRef(&This
->IDirectDrawSurface3_iface
);
238 *obj
= &This
->IDirectDrawSurface3_iface
;
239 TRACE("(%p) returning IDirectDrawSurface3 interface at %p\n", This
, *obj
);
243 if (IsEqualGUID(riid
, &IID_IDirectDrawSurface2
))
245 IDirectDrawSurface2_AddRef(&This
->IDirectDrawSurface2_iface
);
246 *obj
= &This
->IDirectDrawSurface2_iface
;
247 TRACE("(%p) returning IDirectDrawSurface2 interface at %p\n", This
, *obj
);
251 if (IsEqualGUID(riid
, &IID_IDirectDrawSurface
)
252 || IsEqualGUID(riid
, &IID_IUnknown
))
254 IDirectDrawSurface_AddRef(&This
->IDirectDrawSurface_iface
);
255 *obj
= &This
->IDirectDrawSurface_iface
;
256 TRACE("(%p) returning IDirectDrawSurface interface at %p\n", This
, *obj
);
260 if (IsEqualGUID(riid
, &IID_IDirectDrawGammaControl
))
262 IDirectDrawGammaControl_AddRef(&This
->IDirectDrawGammaControl_iface
);
263 *obj
= &This
->IDirectDrawGammaControl_iface
;
264 TRACE("(%p) returning IDirectDrawGammaControl interface at %p\n", This
, *obj
);
268 if (IsEqualGUID(riid
, &IID_IDirectDrawColorControl
))
270 WARN("Color control not implemented.\n");
272 return E_NOINTERFACE
;
275 if (This
->version
!= 7)
277 if (IsEqualGUID(riid
, &IID_D3DDEVICE_WineD3D
)
278 || IsEqualGUID(riid
, &IID_IDirect3DHALDevice
)
279 || IsEqualGUID(riid
, &IID_IDirect3DRGBDevice
))
281 wined3d_mutex_lock();
286 if (FAILED(hr
= d3d_device_create(This
->ddraw
, riid
, This
, (IUnknown
*)&This
->IDirectDrawSurface_iface
,
287 1, &This
->device1
, (IUnknown
*)&This
->IDirectDrawSurface_iface
)))
289 This
->device1
= NULL
;
290 wined3d_mutex_unlock();
291 WARN("Failed to create device, hr %#lx.\n", hr
);
295 wined3d_mutex_unlock();
297 IDirect3DDevice_AddRef(&This
->device1
->IDirect3DDevice_iface
);
298 *obj
= &This
->device1
->IDirect3DDevice_iface
;
302 if (IsEqualGUID(&IID_IDirect3DTexture2
, riid
))
304 IDirect3DTexture2_AddRef(&This
->IDirect3DTexture2_iface
);
305 *obj
= &This
->IDirect3DTexture2_iface
;
309 if (IsEqualGUID( &IID_IDirect3DTexture
, riid
))
311 IDirect3DTexture2_AddRef(&This
->IDirect3DTexture_iface
);
312 *obj
= &This
->IDirect3DTexture_iface
;
317 WARN("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(riid
));
319 if (This
->version
!= 7)
322 return E_NOINTERFACE
;
325 static HRESULT WINAPI
ddraw_surface4_QueryInterface(IDirectDrawSurface4
*iface
, REFIID riid
, void **object
)
327 struct ddraw_surface
*surface
= impl_from_IDirectDrawSurface4(iface
);
329 TRACE("iface %p, riid %s, object %p.\n", iface
, debugstr_guid(riid
), object
);
331 return ddraw_surface7_QueryInterface(&surface
->IDirectDrawSurface7_iface
, riid
, object
);
334 static HRESULT WINAPI
ddraw_surface3_QueryInterface(IDirectDrawSurface3
*iface
, REFIID riid
, void **object
)
336 struct ddraw_surface
*surface
= impl_from_IDirectDrawSurface3(iface
);
338 TRACE("iface %p, riid %s, object %p.\n", iface
, debugstr_guid(riid
), object
);
340 return ddraw_surface7_QueryInterface(&surface
->IDirectDrawSurface7_iface
, riid
, object
);
343 static HRESULT WINAPI
ddraw_surface2_QueryInterface(IDirectDrawSurface2
*iface
, REFIID riid
, void **object
)
345 struct ddraw_surface
*surface
= impl_from_IDirectDrawSurface2(iface
);
347 TRACE("iface %p, riid %s, object %p.\n", iface
, debugstr_guid(riid
), object
);
349 return ddraw_surface7_QueryInterface(&surface
->IDirectDrawSurface7_iface
, riid
, object
);
352 static HRESULT WINAPI
ddraw_surface1_QueryInterface(IDirectDrawSurface
*iface
, REFIID riid
, void **object
)
354 struct ddraw_surface
*surface
= impl_from_IDirectDrawSurface(iface
);
356 TRACE("iface %p, riid %s, object %p.\n", iface
, debugstr_guid(riid
), object
);
358 return ddraw_surface7_QueryInterface(&surface
->IDirectDrawSurface7_iface
, riid
, object
);
361 static HRESULT WINAPI
ddraw_gamma_control_QueryInterface(IDirectDrawGammaControl
*iface
,
362 REFIID riid
, void **object
)
364 struct ddraw_surface
*surface
= impl_from_IDirectDrawGammaControl(iface
);
366 TRACE("iface %p, riid %s, object %p.\n", iface
, debugstr_guid(riid
), object
);
368 return ddraw_surface7_QueryInterface(&surface
->IDirectDrawSurface7_iface
, riid
, object
);
371 static HRESULT WINAPI
d3d_texture2_QueryInterface(IDirect3DTexture2
*iface
, REFIID riid
, void **object
)
373 struct ddraw_surface
*surface
= impl_from_IDirect3DTexture2(iface
);
375 TRACE("iface %p, riid %s, object %p.\n", iface
, debugstr_guid(riid
), object
);
377 return ddraw_surface7_QueryInterface(&surface
->IDirectDrawSurface7_iface
, riid
, object
);
380 static HRESULT WINAPI
d3d_texture1_QueryInterface(IDirect3DTexture
*iface
, REFIID riid
, void **object
)
382 struct ddraw_surface
*surface
= impl_from_IDirect3DTexture(iface
);
384 TRACE("iface %p, riid %s, object %p.\n", iface
, debugstr_guid(riid
), object
);
386 return ddraw_surface7_QueryInterface(&surface
->IDirectDrawSurface7_iface
, riid
, object
);
389 static void ddraw_surface_add_iface(struct ddraw_surface
*surface
)
391 ULONG iface_count
= InterlockedIncrement(&surface
->iface_count
);
392 TRACE("%p increasing iface count to %lu.\n", surface
, iface_count
);
394 if (iface_count
== 1)
396 if (surface
->ifaceToRelease
)
397 IUnknown_AddRef(surface
->ifaceToRelease
);
398 wined3d_mutex_lock();
399 if (surface
->wined3d_rtv
)
400 wined3d_rendertarget_view_incref(surface
->wined3d_rtv
);
401 wined3d_texture_incref(surface
->draw_texture
? surface
->draw_texture
: surface
->wined3d_texture
);
402 wined3d_mutex_unlock();
406 /*****************************************************************************
407 * IDirectDrawSurface7::AddRef
409 * A normal addref implementation
414 *****************************************************************************/
415 static ULONG WINAPI
ddraw_surface7_AddRef(IDirectDrawSurface7
*iface
)
417 struct ddraw_surface
*This
= impl_from_IDirectDrawSurface7(iface
);
418 ULONG refcount
= InterlockedIncrement(&This
->ref7
);
420 TRACE("iface %p increasing refcount to %lu.\n", iface
, refcount
);
424 ddraw_surface_add_iface(This
);
430 static ULONG WINAPI
ddraw_surface4_AddRef(IDirectDrawSurface4
*iface
)
432 struct ddraw_surface
*This
= impl_from_IDirectDrawSurface4(iface
);
433 ULONG refcount
= InterlockedIncrement(&This
->ref4
);
435 TRACE("iface %p increasing refcount to %lu.\n", iface
, refcount
);
439 ddraw_surface_add_iface(This
);
445 static ULONG WINAPI
ddraw_surface3_AddRef(IDirectDrawSurface3
*iface
)
447 struct ddraw_surface
*This
= impl_from_IDirectDrawSurface3(iface
);
448 ULONG refcount
= InterlockedIncrement(&This
->ref3
);
450 TRACE("iface %p increasing refcount to %lu.\n", iface
, refcount
);
454 ddraw_surface_add_iface(This
);
460 static ULONG WINAPI
ddraw_surface2_AddRef(IDirectDrawSurface2
*iface
)
462 struct ddraw_surface
*This
= impl_from_IDirectDrawSurface2(iface
);
463 ULONG refcount
= InterlockedIncrement(&This
->ref2
);
465 TRACE("iface %p increasing refcount to %lu.\n", iface
, refcount
);
469 ddraw_surface_add_iface(This
);
475 static ULONG WINAPI
ddraw_surface1_AddRef(IDirectDrawSurface
*iface
)
477 struct ddraw_surface
*This
= impl_from_IDirectDrawSurface(iface
);
478 ULONG refcount
= InterlockedIncrement(&This
->ref1
);
480 TRACE("iface %p increasing refcount to %lu.\n", iface
, refcount
);
484 ddraw_surface_add_iface(This
);
490 static ULONG WINAPI
ddraw_gamma_control_AddRef(IDirectDrawGammaControl
*iface
)
492 struct ddraw_surface
*This
= impl_from_IDirectDrawGammaControl(iface
);
493 ULONG refcount
= InterlockedIncrement(&This
->gamma_count
);
495 TRACE("iface %p increasing refcount to %lu.\n", iface
, refcount
);
499 ddraw_surface_add_iface(This
);
505 static ULONG WINAPI
d3d_texture2_AddRef(IDirect3DTexture2
*iface
)
507 struct ddraw_surface
*surface
= impl_from_IDirect3DTexture2(iface
);
509 TRACE("iface %p.\n", iface
);
511 return IUnknown_AddRef(surface
->texture_outer
);
514 static ULONG WINAPI
d3d_texture1_AddRef(IDirect3DTexture
*iface
)
516 struct ddraw_surface
*surface
= impl_from_IDirect3DTexture(iface
);
518 TRACE("iface %p.\n", iface
);
520 return IUnknown_AddRef(surface
->texture_outer
);
523 static HRESULT
ddraw_surface_set_palette(struct ddraw_surface
*surface
, IDirectDrawPalette
*palette
)
525 struct ddraw_palette
*palette_impl
= unsafe_impl_from_IDirectDrawPalette(palette
);
526 struct ddraw_palette
*prev
;
528 TRACE("iface %p, palette %p.\n", surface
, palette
);
530 if (palette_impl
&& palette_impl
->flags
& DDPCAPS_ALPHA
531 && !(surface
->surface_desc
.ddsCaps
.dwCaps
& DDSCAPS_TEXTURE
))
533 WARN("Alpha palette set on non-texture surface, returning DDERR_INVALIDSURFACETYPE.\n");
534 return DDERR_INVALIDSURFACETYPE
;
537 if (!format_is_paletteindexed(&surface
->surface_desc
.u4
.ddpfPixelFormat
))
538 return DDERR_INVALIDPIXELFORMAT
;
540 wined3d_mutex_lock();
542 prev
= surface
->palette
;
543 if (surface
->surface_desc
.ddsCaps
.dwCaps
& DDSCAPS_PRIMARYSURFACE
)
546 prev
->flags
&= ~DDPCAPS_PRIMARYSURFACE
;
548 palette_impl
->flags
|= DDPCAPS_PRIMARYSURFACE
;
549 wined3d_swapchain_set_palette(surface
->ddraw
->wined3d_swapchain
,
550 palette_impl
? palette_impl
->wined3d_palette
: NULL
);
551 ddraw_surface_update_frontbuffer(surface
, NULL
, FALSE
, 0);
554 IDirectDrawPalette_AddRef(&palette_impl
->IDirectDrawPalette_iface
);
556 IDirectDrawPalette_Release(&prev
->IDirectDrawPalette_iface
);
557 surface
->palette
= palette_impl
;
559 wined3d_mutex_unlock();
564 static void ddraw_surface_cleanup(struct ddraw_surface
*surface
)
566 struct ddraw_surface
*surf
;
569 TRACE("surface %p.\n", surface
);
571 /* The refcount test shows that the palette is detached when the surface
573 ddraw_surface_set_palette(surface
, NULL
);
575 /* Loop through all complex attached surfaces and destroy them.
577 * Yet again, only the root can have more than one complexly attached
578 * surface, all the others have a total of one. */
579 for (i
= 0; i
< MAX_COMPLEX_ATTACHED
; ++i
)
581 if (!surface
->complex_array
[i
])
584 surf
= surface
->complex_array
[i
];
585 surface
->complex_array
[i
] = NULL
;
588 struct ddraw_texture
*texture
= wined3d_texture_get_parent(surf
->wined3d_texture
);
589 struct wined3d_device
*wined3d_device
= texture
->wined3d_device
;
590 struct ddraw_surface
*root
= texture
->root
;
592 ddraw_surface_cleanup(surf
);
595 wined3d_device_decref(wined3d_device
);
599 if (surface
->device1
)
600 IUnknown_Release(&surface
->device1
->IUnknown_inner
);
602 if (surface
->iface_count
> 1)
604 /* This can happen when a complex surface is destroyed, because the
605 * 2nd surface was addref()ed when the app called
606 * GetAttachedSurface(). */
607 WARN("Destroying surface %p with refcounts 7: %lu 4: %lu 3: %lu 2: %lu 1: %lu.\n",
608 surface
, surface
->ref7
, surface
->ref4
, surface
->ref3
, surface
->ref2
, surface
->ref1
);
611 if (surface
->wined3d_rtv
)
612 wined3d_rendertarget_view_decref(surface
->wined3d_rtv
);
613 wined3d_texture_decref(surface
->draw_texture
? surface
->draw_texture
: surface
->wined3d_texture
);
616 static ULONG
ddraw_surface_release_iface(struct ddraw_surface
*This
)
620 /* Prevent the surface from being destroyed if it's still attached to
621 * another surface. It will be destroyed when the root is destroyed. */
622 if (This
->iface_count
== 1 && This
->attached_iface
)
623 IUnknown_AddRef(This
->attached_iface
);
624 iface_count
= InterlockedDecrement(&This
->iface_count
);
626 TRACE("%p decreasing iface count to %lu.\n", This
, iface_count
);
628 if (iface_count
== 0)
630 struct ddraw_texture
*texture
= wined3d_texture_get_parent(This
->wined3d_texture
);
631 struct wined3d_device
*wined3d_device
= texture
->wined3d_device
;
632 IUnknown
*release_iface
= This
->ifaceToRelease
;
634 /* Complex attached surfaces are destroyed implicitly when the root is released */
635 wined3d_mutex_lock();
638 WARN("(%p) Attempt to destroy a surface that is not a complex root\n", This
);
639 wined3d_mutex_unlock();
642 ddraw_surface_cleanup(This
);
643 wined3d_mutex_unlock();
646 IUnknown_Release(release_iface
);
647 /* Release the device only after anything that may reference it (the
648 * wined3d texture and rendertarget view in particular) is released. */
649 wined3d_device_decref(wined3d_device
);
655 /*****************************************************************************
656 * IDirectDrawSurface7::Release
658 * Reduces the surface's refcount by 1. If the refcount falls to 0, the
659 * surface is destroyed.
661 * Destroying the surface is a bit tricky. For the connection between
662 * WineD3DSurfaces and DirectDrawSurfaces see IDirectDraw7::CreateSurface
663 * It has a nice graph explaining the connection.
665 * What happens here is basically this:
666 * When a surface is destroyed, its WineD3DSurface is released,
667 * and the refcount of the DirectDraw interface is reduced by 1. If it has
668 * complex surfaces attached to it, then these surfaces are destroyed too,
669 * regardless of their refcount. If any surface being destroyed has another
670 * surface attached to it (with a "soft" attachment, not complex), then
671 * this surface is detached with DeleteAttachedSurface.
673 * When the surface is a texture, the WineD3DTexture is released.
674 * If the surface is the Direct3D render target, then the D3D
675 * capabilities of the WineD3DDevice are uninitialized, which causes the
676 * swapchain to be released.
678 * When a complex sublevel falls to ref zero, then this is ignored.
683 *****************************************************************************/
684 static ULONG WINAPI
ddraw_surface7_Release(IDirectDrawSurface7
*iface
)
686 struct ddraw_surface
*This
= impl_from_IDirectDrawSurface7(iface
);
687 ULONG refcount
= InterlockedDecrement(&This
->ref7
);
689 TRACE("iface %p decreasing refcount to %lu.\n", iface
, refcount
);
693 ddraw_surface_release_iface(This
);
699 static ULONG WINAPI
ddraw_surface4_Release(IDirectDrawSurface4
*iface
)
701 struct ddraw_surface
*This
= impl_from_IDirectDrawSurface4(iface
);
702 ULONG refcount
= InterlockedDecrement(&This
->ref4
);
704 TRACE("iface %p decreasing refcount to %lu.\n", iface
, refcount
);
708 ddraw_surface_release_iface(This
);
714 static ULONG WINAPI
ddraw_surface3_Release(IDirectDrawSurface3
*iface
)
716 struct ddraw_surface
*This
= impl_from_IDirectDrawSurface3(iface
);
717 ULONG refcount
= InterlockedDecrement(&This
->ref3
);
719 TRACE("iface %p decreasing refcount to %lu.\n", iface
, refcount
);
723 ddraw_surface_release_iface(This
);
729 static ULONG WINAPI
ddraw_surface2_Release(IDirectDrawSurface2
*iface
)
731 struct ddraw_surface
*This
= impl_from_IDirectDrawSurface2(iface
);
732 ULONG refcount
= InterlockedDecrement(&This
->ref2
);
734 TRACE("iface %p decreasing refcount to %lu.\n", iface
, refcount
);
738 ddraw_surface_release_iface(This
);
744 static ULONG WINAPI
ddraw_surface1_Release(IDirectDrawSurface
*iface
)
746 struct ddraw_surface
*This
= impl_from_IDirectDrawSurface(iface
);
747 ULONG refcount
= InterlockedDecrement(&This
->ref1
);
749 TRACE("iface %p decreasing refcount to %lu.\n", iface
, refcount
);
753 ddraw_surface_release_iface(This
);
759 static ULONG WINAPI
ddraw_gamma_control_Release(IDirectDrawGammaControl
*iface
)
761 struct ddraw_surface
*This
= impl_from_IDirectDrawGammaControl(iface
);
762 ULONG refcount
= InterlockedDecrement(&This
->gamma_count
);
764 TRACE("iface %p decreasing refcount to %lu.\n", iface
, refcount
);
768 ddraw_surface_release_iface(This
);
774 static ULONG WINAPI
d3d_texture2_Release(IDirect3DTexture2
*iface
)
776 struct ddraw_surface
*surface
= impl_from_IDirect3DTexture2(iface
);
778 TRACE("iface %p.\n", iface
);
780 return IUnknown_Release(surface
->texture_outer
);
783 static ULONG WINAPI
d3d_texture1_Release(IDirect3DTexture
*iface
)
785 struct ddraw_surface
*surface
= impl_from_IDirect3DTexture(iface
);
787 TRACE("iface %p.\n", iface
);
789 return IUnknown_Release(surface
->texture_outer
);
792 /*****************************************************************************
793 * IDirectDrawSurface7::GetAttachedSurface
795 * Returns an attached surface with the requested caps. Surface attachment
796 * and complex surfaces are not clearly described by the MSDN or sdk,
797 * so this method is tricky and likely to contain problems.
798 * This implementation searches the complex list first, then the
801 * The chains are searched from This down to the last surface in the chain,
802 * not from the first element in the chain. The first surface found is
803 * returned. The MSDN says that this method fails if more than one surface
804 * matches the caps, but it is not sure if that is right. The attachment
805 * structure may not even allow two matching surfaces.
807 * The found surface is AddRef-ed before it is returned.
810 * Caps: Pointer to a DDCAPS2 structure describing the caps asked for
811 * Surface: Address to store the found surface
815 * DDERR_INVALIDPARAMS if Caps or Surface is NULL
816 * DDERR_NOTFOUND if no surface was found
818 *****************************************************************************/
819 static HRESULT WINAPI
ddraw_surface7_GetAttachedSurface(IDirectDrawSurface7
*iface
,
820 DDSCAPS2
*caps
, IDirectDrawSurface7
**surface
)
822 struct ddraw_surface
*head_surface
= impl_from_IDirectDrawSurface7(iface
);
823 struct ddraw_surface
*surf
;
827 TRACE("iface %p, caps %p, attachment %p.\n", iface
, caps
, surface
);
829 if (ddraw_surface_is_lost(head_surface
))
831 WARN("Surface %p is lost.\n", head_surface
);
834 return DDERR_SURFACELOST
;
837 wined3d_mutex_lock();
839 if(head_surface
->version
< 7)
841 /* Earlier dx apps put garbage into these members, clear them */
842 our_caps
.dwCaps
= caps
->dwCaps
;
843 our_caps
.dwCaps2
= 0;
844 our_caps
.dwCaps3
= 0;
845 our_caps
.u1
.dwCaps4
= 0;
852 TRACE("head_surface %p, looking for caps %#lx, %#lx, %#lx, %#lx.\n", head_surface
, our_caps
.dwCaps
,
853 our_caps
.dwCaps2
, our_caps
.dwCaps3
, our_caps
.u1
.dwCaps4
); /* FIXME: Better debugging */
855 for(i
= 0; i
< MAX_COMPLEX_ATTACHED
; i
++)
857 surf
= head_surface
->complex_array
[i
];
860 TRACE("Surface %p, caps %#lx, %#lx, %#lx, %#lx.\n", surf
,
861 surf
->surface_desc
.ddsCaps
.dwCaps
,
862 surf
->surface_desc
.ddsCaps
.dwCaps2
,
863 surf
->surface_desc
.ddsCaps
.dwCaps3
,
864 surf
->surface_desc
.ddsCaps
.u1
.dwCaps4
);
866 if (((surf
->surface_desc
.ddsCaps
.dwCaps
& our_caps
.dwCaps
) == our_caps
.dwCaps
) &&
867 ((surf
->surface_desc
.ddsCaps
.dwCaps2
& our_caps
.dwCaps2
) == our_caps
.dwCaps2
)) {
869 /* MSDN: "This method fails if more than one surface is attached
870 * that matches the capabilities requested."
872 * Not sure how to test this.
875 TRACE("head_surface %p, returning surface %p.\n", head_surface
, surf
);
876 *surface
= &surf
->IDirectDrawSurface7_iface
;
877 ddraw_surface7_AddRef(*surface
);
878 wined3d_mutex_unlock();
884 /* Next, look at the attachment chain */
887 while( (surf
= surf
->next_attached
) )
889 TRACE("Surface %p, caps %#lx, %#lx, %#lx, %#lx.\n", surf
,
890 surf
->surface_desc
.ddsCaps
.dwCaps
,
891 surf
->surface_desc
.ddsCaps
.dwCaps2
,
892 surf
->surface_desc
.ddsCaps
.dwCaps3
,
893 surf
->surface_desc
.ddsCaps
.u1
.dwCaps4
);
895 if (((surf
->surface_desc
.ddsCaps
.dwCaps
& our_caps
.dwCaps
) == our_caps
.dwCaps
) &&
896 ((surf
->surface_desc
.ddsCaps
.dwCaps2
& our_caps
.dwCaps2
) == our_caps
.dwCaps2
)) {
898 TRACE("head_surface %p, returning surface %p.\n", head_surface
, surf
);
899 *surface
= &surf
->IDirectDrawSurface7_iface
;
900 ddraw_surface7_AddRef(*surface
);
901 wined3d_mutex_unlock();
906 TRACE("head_surface %p, didn't find a valid surface.\n", head_surface
);
908 wined3d_mutex_unlock();
911 return DDERR_NOTFOUND
;
914 static HRESULT WINAPI
ddraw_surface4_GetAttachedSurface(IDirectDrawSurface4
*iface
,
915 DDSCAPS2
*caps
, IDirectDrawSurface4
**attachment
)
917 struct ddraw_surface
*surface
= impl_from_IDirectDrawSurface4(iface
);
918 struct ddraw_surface
*attachment_impl
;
919 IDirectDrawSurface7
*attachment7
;
922 TRACE("iface %p, caps %p, attachment %p.\n", iface
, caps
, attachment
);
924 hr
= ddraw_surface7_GetAttachedSurface(&surface
->IDirectDrawSurface7_iface
,
931 attachment_impl
= impl_from_IDirectDrawSurface7(attachment7
);
932 *attachment
= &attachment_impl
->IDirectDrawSurface4_iface
;
933 ddraw_surface4_AddRef(*attachment
);
934 ddraw_surface7_Release(attachment7
);
939 static HRESULT WINAPI
ddraw_surface3_GetAttachedSurface(IDirectDrawSurface3
*iface
,
940 DDSCAPS
*caps
, IDirectDrawSurface3
**attachment
)
942 struct ddraw_surface
*surface
= impl_from_IDirectDrawSurface3(iface
);
943 struct ddraw_surface
*attachment_impl
;
944 IDirectDrawSurface7
*attachment7
;
948 TRACE("iface %p, caps %p, attachment %p.\n", iface
, caps
, attachment
);
950 caps2
.dwCaps
= caps
->dwCaps
;
953 caps2
.u1
.dwCaps4
= 0;
955 hr
= ddraw_surface7_GetAttachedSurface(&surface
->IDirectDrawSurface7_iface
,
956 &caps2
, &attachment7
);
962 attachment_impl
= impl_from_IDirectDrawSurface7(attachment7
);
963 *attachment
= &attachment_impl
->IDirectDrawSurface3_iface
;
964 ddraw_surface3_AddRef(*attachment
);
965 ddraw_surface7_Release(attachment7
);
970 static HRESULT WINAPI
ddraw_surface2_GetAttachedSurface(IDirectDrawSurface2
*iface
,
971 DDSCAPS
*caps
, IDirectDrawSurface2
**attachment
)
973 struct ddraw_surface
*surface
= impl_from_IDirectDrawSurface2(iface
);
974 struct ddraw_surface
*attachment_impl
;
975 IDirectDrawSurface7
*attachment7
;
979 TRACE("iface %p, caps %p, attachment %p.\n", iface
, caps
, attachment
);
981 caps2
.dwCaps
= caps
->dwCaps
;
984 caps2
.u1
.dwCaps4
= 0;
986 hr
= ddraw_surface7_GetAttachedSurface(&surface
->IDirectDrawSurface7_iface
,
987 &caps2
, &attachment7
);
993 attachment_impl
= impl_from_IDirectDrawSurface7(attachment7
);
994 *attachment
= &attachment_impl
->IDirectDrawSurface2_iface
;
995 ddraw_surface2_AddRef(*attachment
);
996 ddraw_surface7_Release(attachment7
);
1001 static HRESULT WINAPI
ddraw_surface1_GetAttachedSurface(IDirectDrawSurface
*iface
,
1002 DDSCAPS
*caps
, IDirectDrawSurface
**attachment
)
1004 struct ddraw_surface
*surface
= impl_from_IDirectDrawSurface(iface
);
1005 struct ddraw_surface
*attachment_impl
;
1006 IDirectDrawSurface7
*attachment7
;
1010 TRACE("iface %p, caps %p, attachment %p.\n", iface
, caps
, attachment
);
1012 caps2
.dwCaps
= caps
->dwCaps
;
1015 caps2
.u1
.dwCaps4
= 0;
1017 hr
= ddraw_surface7_GetAttachedSurface(&surface
->IDirectDrawSurface7_iface
,
1018 &caps2
, &attachment7
);
1024 attachment_impl
= impl_from_IDirectDrawSurface7(attachment7
);
1025 *attachment
= &attachment_impl
->IDirectDrawSurface_iface
;
1026 ddraw_surface1_AddRef(*attachment
);
1027 ddraw_surface7_Release(attachment7
);
1032 /*****************************************************************************
1033 * IDirectDrawSurface7::Lock
1035 * Locks the surface and returns a pointer to the surface's memory
1038 * Rect: Rectangle to lock. If NULL, the whole surface is locked
1039 * DDSD: Pointer to a DDSURFACEDESC2 which shall receive the surface's desc.
1040 * Flags: Locking flags, e.g Read only or write only
1041 * h: An event handle that's not used and must be NULL
1045 * DDERR_INVALIDPARAMS if DDSD is NULL
1047 *****************************************************************************/
1048 static HRESULT
surface_lock(struct ddraw_surface
*surface
,
1049 RECT
*rect
, DDSURFACEDESC2
*surface_desc
, unsigned int surface_desc_size
,
1050 DWORD flags
, HANDLE h
)
1052 struct wined3d_map_desc map_desc
;
1053 unsigned int wined3d_flags
;
1054 struct wined3d_box box
;
1057 TRACE("surface %p, rect %s, surface_desc %p, surface_desc_size %u, flags %#lx, h %p.\n",
1058 surface
, wine_dbgstr_rect(rect
), surface_desc
, surface_desc_size
, flags
, h
);
1060 /* surface->surface_desc.dwWidth and dwHeight are changeable, thus lock */
1061 wined3d_mutex_lock();
1063 /* Should I check for the handle to be NULL?
1065 * The DDLOCK flags and the D3DLOCK flags are equal
1066 * for the supported values. The others are ignored by WineD3D
1069 /* Windows zeroes this if the rect is invalid */
1070 surface_desc
->lpSurface
= NULL
;
1074 if ((rect
->left
< 0) || (rect
->top
< 0)
1075 || (rect
->left
> rect
->right
) || (rect
->right
> surface
->surface_desc
.dwWidth
)
1076 || (rect
->top
> rect
->bottom
) || (rect
->bottom
> surface
->surface_desc
.dwHeight
))
1078 WARN("Trying to lock an invalid rectangle, returning DDERR_INVALIDPARAMS\n");
1079 wined3d_mutex_unlock();
1080 return DDERR_INVALIDPARAMS
;
1082 wined3d_box_set(&box
, rect
->left
, rect
->top
, rect
->right
, rect
->bottom
, 0, 1);
1085 if (surface
->surface_desc
.ddsCaps
.dwCaps
& DDSCAPS_PRIMARYSURFACE
)
1086 hr
= ddraw_surface_update_frontbuffer(surface
, rect
, TRUE
, 0);
1089 wined3d_flags
= wined3dmapflags_from_ddrawmapflags(flags
);
1090 hr
= wined3d_resource_map(wined3d_texture_get_resource
1091 (ddraw_surface_get_default_texture(surface
, wined3d_flags
& WINED3D_MAP_WRITE
? DDRAW_SURFACE_RW
1092 : DDRAW_SURFACE_READ
)), surface
->sub_resource_idx
, &map_desc
, rect
? &box
: NULL
, wined3d_flags
);
1096 wined3d_mutex_unlock();
1099 /* D3D8 and D3D9 return the general D3DERR_INVALIDCALL error, but ddraw has a more
1100 * specific error. But since wined3d returns that error in this only occasion,
1101 * keep d3d8 and d3d9 free from the return value override. There are many different
1102 * places where d3d8/9 would have to catch the DDERR_SURFACEBUSY, it is much easier
1103 * to do it in one place in ddraw.
1105 case WINED3DERR_INVALIDCALL
: return DDERR_SURFACEBUSY
;
1110 if (surface
->surface_desc
.ddsCaps
.dwCaps
& DDSCAPS_PRIMARYSURFACE
)
1112 if (flags
& DDLOCK_READONLY
)
1113 SetRectEmpty(&surface
->ddraw
->primary_lock
);
1115 surface
->ddraw
->primary_lock
= *rect
;
1117 SetRect(&surface
->ddraw
->primary_lock
, 0, 0, surface
->surface_desc
.dwWidth
, surface
->surface_desc
.dwHeight
);
1120 /* Windows does not set DDSD_LPSURFACE on locked surfaces. */
1121 DD_STRUCT_COPY_BYSIZE_(surface_desc
, &surface
->surface_desc
, surface_desc_size
, surface
->surface_desc
.dwSize
);
1122 surface_desc
->lpSurface
= map_desc
.data
;
1124 TRACE("locked surface returning description :\n");
1125 if (TRACE_ON(ddraw
))
1126 DDRAW_dump_surface_desc(surface_desc
);
1128 wined3d_mutex_unlock();
1133 static BOOL
surface_validate_lock_desc(struct ddraw_surface
*surface
,
1134 const DDSURFACEDESC
*desc
, unsigned int *size
)
1139 if (desc
->dwSize
== sizeof(DDSURFACEDESC
) || desc
->dwSize
== sizeof(DDSURFACEDESC2
))
1141 *size
= desc
->dwSize
;
1145 if (surface
->version
== 7
1146 && surface
->surface_desc
.ddsCaps
.dwCaps
& DDSCAPS_TEXTURE
1147 && !(surface
->surface_desc
.ddsCaps
.dwCaps
& DDSCAPS_VIDEOMEMORY
))
1149 if (desc
->dwSize
>= sizeof(DDSURFACEDESC2
))
1150 *size
= sizeof(DDSURFACEDESC2
);
1152 *size
= sizeof(DDSURFACEDESC
);
1156 WARN("Invalid structure size %lu.\n", desc
->dwSize
);
1160 static HRESULT WINAPI
ddraw_surface7_Lock(IDirectDrawSurface7
*iface
,
1161 RECT
*rect
, DDSURFACEDESC2
*surface_desc
, DWORD flags
, HANDLE h
)
1163 struct ddraw_surface
*surface
= impl_from_IDirectDrawSurface7(iface
);
1164 unsigned int surface_desc_size
;
1166 TRACE("iface %p, rect %s, surface_desc %p, flags %#lx, h %p.\n",
1167 iface
, wine_dbgstr_rect(rect
), surface_desc
, flags
, h
);
1169 if (!surface_validate_lock_desc(surface
, (DDSURFACEDESC
*)surface_desc
, &surface_desc_size
))
1170 return DDERR_INVALIDPARAMS
;
1172 if (ddraw_surface_is_lost(surface
))
1174 WARN("Surface is lost.\n");
1175 return DDERR_SURFACELOST
;
1178 return surface_lock(surface
, rect
, surface_desc
, surface_desc_size
, flags
, h
);
1181 static HRESULT WINAPI
ddraw_surface4_Lock(IDirectDrawSurface4
*iface
, RECT
*rect
,
1182 DDSURFACEDESC2
*surface_desc
, DWORD flags
, HANDLE h
)
1184 struct ddraw_surface
*surface
= impl_from_IDirectDrawSurface4(iface
);
1185 unsigned int surface_desc_size
;
1187 TRACE("iface %p, rect %s, surface_desc %p, flags %#lx, h %p.\n",
1188 iface
, wine_dbgstr_rect(rect
), surface_desc
, flags
, h
);
1190 if (!surface_validate_lock_desc(surface
, (DDSURFACEDESC
*)surface_desc
, &surface_desc_size
))
1191 return DDERR_INVALIDPARAMS
;
1193 if (ddraw_surface_is_lost(surface
))
1195 WARN("Surface is lost.\n");
1196 return DDERR_SURFACELOST
;
1199 return surface_lock(surface
, rect
, surface_desc
, surface_desc_size
, flags
, h
);
1202 static HRESULT
ddraw_surface_lock_ddsd(struct ddraw_surface
*surface
, RECT
*rect
,
1203 DDSURFACEDESC
*surface_desc
, DWORD flags
, HANDLE h
)
1205 unsigned int surface_desc_size
;
1206 DDSURFACEDESC2 surface_desc2
;
1209 if (!surface_validate_lock_desc(surface
, surface_desc
, &surface_desc_size
))
1210 return DDERR_INVALIDPARAMS
;
1212 if (ddraw_surface_is_lost(surface
))
1214 WARN("Surface is lost.\n");
1215 return DDERR_SURFACELOST
;
1218 surface_desc2
.dwSize
= surface_desc
->dwSize
;
1219 surface_desc2
.dwFlags
= 0;
1220 hr
= surface_lock(surface
, rect
, &surface_desc2
, surface_desc_size
, flags
, h
);
1221 DDSD2_to_DDSD(&surface_desc2
, surface_desc
);
1222 surface_desc
->dwSize
= surface_desc2
.dwSize
;
1226 static HRESULT WINAPI
ddraw_surface3_Lock(IDirectDrawSurface3
*iface
, RECT
*rect
,
1227 DDSURFACEDESC
*surface_desc
, DWORD flags
, HANDLE h
)
1229 struct ddraw_surface
*surface
= impl_from_IDirectDrawSurface3(iface
);
1231 TRACE("iface %p, rect %s, surface_desc %p, flags %#lx, h %p.\n",
1232 iface
, wine_dbgstr_rect(rect
), surface_desc
, flags
, h
);
1234 return ddraw_surface_lock_ddsd(surface
, rect
, surface_desc
, flags
, h
);
1237 static HRESULT WINAPI
ddraw_surface2_Lock(IDirectDrawSurface2
*iface
, RECT
*rect
,
1238 DDSURFACEDESC
*surface_desc
, DWORD flags
, HANDLE h
)
1240 struct ddraw_surface
*surface
= impl_from_IDirectDrawSurface2(iface
);
1242 TRACE("iface %p, rect %s, surface_desc %p, flags %#lx, h %p.\n",
1243 iface
, wine_dbgstr_rect(rect
), surface_desc
, flags
, h
);
1245 return ddraw_surface_lock_ddsd(surface
, rect
, surface_desc
, flags
, h
);
1248 static HRESULT WINAPI
ddraw_surface1_Lock(IDirectDrawSurface
*iface
, RECT
*rect
,
1249 DDSURFACEDESC
*surface_desc
, DWORD flags
, HANDLE h
)
1251 struct ddraw_surface
*surface
= impl_from_IDirectDrawSurface(iface
);
1253 TRACE("iface %p, rect %s, surface_desc %p, flags %#lx, h %p.\n",
1254 iface
, wine_dbgstr_rect(rect
), surface_desc
, flags
, h
);
1256 return ddraw_surface_lock_ddsd(surface
, rect
, surface_desc
, flags
, h
);
1259 /* FRAPS hooks IDirectDrawSurface::Unlock and expects the version 1 method to be called when the
1260 * game uses later interfaces. */
1261 static HRESULT WINAPI DECLSPEC_HOTPATCH
ddraw_surface1_Unlock(IDirectDrawSurface
*iface
, void *data
)
1263 struct ddraw_surface
*surface
= impl_from_IDirectDrawSurface(iface
);
1266 TRACE("iface %p, data %p.\n", iface
, data
);
1268 wined3d_mutex_lock();
1269 hr
= wined3d_resource_unmap(wined3d_texture_get_resource
1270 (ddraw_surface_get_default_texture(surface
, 0)), surface
->sub_resource_idx
);
1271 if (SUCCEEDED(hr
) && surface
->surface_desc
.ddsCaps
.dwCaps
& DDSCAPS_PRIMARYSURFACE
)
1272 hr
= ddraw_surface_update_frontbuffer(surface
, &surface
->ddraw
->primary_lock
, FALSE
, 0);
1273 wined3d_mutex_unlock();
1278 static HRESULT WINAPI DECLSPEC_HOTPATCH
ddraw_surface7_Unlock(IDirectDrawSurface7
*iface
, RECT
*rect
)
1280 struct ddraw_surface
*surface
= impl_from_IDirectDrawSurface7(iface
);
1282 TRACE("iface %p, rect %s.\n", iface
, wine_dbgstr_rect(rect
));
1284 return ddraw_surface1_Unlock(&surface
->IDirectDrawSurface_iface
, NULL
);
1287 static HRESULT WINAPI DECLSPEC_HOTPATCH
ddraw_surface4_Unlock(IDirectDrawSurface4
*iface
, RECT
*rect
)
1289 struct ddraw_surface
*surface
= impl_from_IDirectDrawSurface4(iface
);
1291 TRACE("iface %p, rect %s.\n", iface
, wine_dbgstr_rect(rect
));
1293 return ddraw_surface1_Unlock(&surface
->IDirectDrawSurface_iface
, NULL
);
1296 static HRESULT WINAPI DECLSPEC_HOTPATCH
ddraw_surface3_Unlock(IDirectDrawSurface3
*iface
, void *data
)
1298 struct ddraw_surface
*surface
= impl_from_IDirectDrawSurface3(iface
);
1300 TRACE("iface %p, data %p.\n", iface
, data
);
1302 return ddraw_surface1_Unlock(&surface
->IDirectDrawSurface_iface
, data
);
1305 static HRESULT WINAPI DECLSPEC_HOTPATCH
ddraw_surface2_Unlock(IDirectDrawSurface2
*iface
, void *data
)
1307 struct ddraw_surface
*surface
= impl_from_IDirectDrawSurface2(iface
);
1309 TRACE("iface %p, data %p.\n", iface
, data
);
1311 return ddraw_surface1_Unlock(&surface
->IDirectDrawSurface_iface
, data
);
1314 static unsigned int ddraw_swap_interval_from_flags(DWORD flags
)
1316 if (flags
& DDFLIP_NOVSYNC
)
1319 switch (flags
& (DDFLIP_INTERVAL2
| DDFLIP_INTERVAL3
| DDFLIP_INTERVAL4
))
1321 case DDFLIP_INTERVAL2
:
1323 case DDFLIP_INTERVAL3
:
1325 case DDFLIP_INTERVAL4
:
1332 static void ddraw_texture_rename_to(struct ddraw_texture
*dst_texture
, struct wined3d_texture
*wined3d_texture
,
1333 struct wined3d_texture
*draw_texture
, struct wined3d_rendertarget_view
*rtv
, void *texture_memory
)
1335 struct ddraw_surface
*dst_surface
= dst_texture
->root
;
1336 struct wined3d_rendertarget_view
*current_rtv
;
1338 /* We don't have to worry about potential texture bindings, since
1339 * flippable surfaces can never be textures. */
1341 current_rtv
= wined3d_device_context_get_rendertarget_view(dst_surface
->ddraw
->immediate_context
, 0);
1342 if (current_rtv
== dst_surface
->wined3d_rtv
)
1343 wined3d_device_context_set_rendertarget_views(dst_surface
->ddraw
->immediate_context
, 0, 1, &rtv
, FALSE
);
1344 wined3d_rendertarget_view_set_parent(rtv
, dst_surface
, &ddraw_view_wined3d_parent_ops
);
1345 dst_surface
->wined3d_rtv
= rtv
;
1347 if (dst_surface
->sub_resource_idx
)
1348 ERR("Invalid sub-resource index %u for surface %p.\n", dst_surface
->sub_resource_idx
, dst_surface
);
1352 wined3d_texture_set_sub_resource_parent(draw_texture
, 0, dst_surface
, &ddraw_surface_wined3d_parent_ops
);
1353 wined3d_texture_set_sub_resource_parent(wined3d_texture
, 0, dst_surface
, &ddraw_null_wined3d_parent_ops
);
1354 wined3d_resource_set_parent(wined3d_texture_get_resource(draw_texture
),
1355 dst_texture
, &ddraw_texture_wined3d_parent_ops
);
1356 wined3d_resource_set_parent(wined3d_texture_get_resource(wined3d_texture
),
1357 dst_texture
, &ddraw_null_wined3d_parent_ops
);
1361 wined3d_texture_set_sub_resource_parent(wined3d_texture
, 0, dst_surface
, &ddraw_surface_wined3d_parent_ops
);
1362 wined3d_resource_set_parent(wined3d_texture_get_resource(wined3d_texture
),
1363 dst_texture
, &ddraw_texture_wined3d_parent_ops
);
1366 dst_surface
->wined3d_texture
= wined3d_texture
;
1367 dst_surface
->draw_texture
= draw_texture
;
1369 dst_texture
->texture_memory
= texture_memory
;
1372 /* FRAPS hooks IDirectDrawSurface::Flip and expects the version 1 method to be called when the
1373 * game uses later interfaces. */
1374 static HRESULT WINAPI DECLSPEC_HOTPATCH
ddraw_surface1_Flip(IDirectDrawSurface
*iface
,
1375 IDirectDrawSurface
*src
, DWORD flags
)
1377 struct ddraw_surface
*dst_impl
= impl_from_IDirectDrawSurface(iface
);
1378 struct ddraw_surface
*src_impl
= unsafe_impl_from_IDirectDrawSurface(src
);
1379 struct ddraw_texture
*dst_ddraw_texture
, *src_ddraw_texture
;
1380 struct wined3d_texture
*texture
, *draw_texture
;
1381 struct wined3d_rendertarget_view
*tmp_rtv
;
1382 DDSCAPS caps
= {DDSCAPS_FLIP
};
1383 IDirectDrawSurface
*current
;
1384 void *texture_memory
;
1387 TRACE("iface %p, src %p, flags %#lx.\n", iface
, src
, flags
);
1389 if (src
== iface
|| !(dst_impl
->surface_desc
.ddsCaps
.dwCaps
& (DDSCAPS_FRONTBUFFER
| DDSCAPS_OVERLAY
)))
1390 return DDERR_NOTFLIPPABLE
;
1392 if (ddraw_surface_is_lost(dst_impl
))
1393 return DDERR_SURFACELOST
;
1395 wined3d_mutex_lock();
1397 if ((dst_impl
->surface_desc
.ddsCaps
.dwCaps
& DDSCAPS_PRIMARYSURFACE
)
1398 && !(dst_impl
->ddraw
->cooperative_level
& DDSCL_EXCLUSIVE
))
1400 WARN("Not in exclusive mode.\n");
1401 wined3d_mutex_unlock();
1402 return DDERR_NOEXCLUSIVEMODE
;
1405 tmp_rtv
= ddraw_surface_get_rendertarget_view(dst_impl
);
1406 texture
= dst_impl
->wined3d_texture
;
1407 dst_ddraw_texture
= wined3d_texture_get_parent(dst_impl
->wined3d_texture
);
1408 texture_memory
= dst_ddraw_texture
->texture_memory
;
1409 draw_texture
= dst_impl
->draw_texture
;
1413 for (current
= iface
; current
!= src
;)
1415 if (FAILED(hr
= ddraw_surface1_GetAttachedSurface(current
, &caps
, ¤t
)))
1417 WARN("Surface %p is not on the same flip chain as surface %p.\n", src
, iface
);
1418 wined3d_mutex_unlock();
1419 return DDERR_NOTFLIPPABLE
;
1421 ddraw_surface1_Release(current
);
1422 if (current
== iface
)
1424 WARN("Surface %p is not on the same flip chain as surface %p.\n", src
, iface
);
1425 wined3d_mutex_unlock();
1426 return DDERR_NOTFLIPPABLE
;
1430 src_ddraw_texture
= wined3d_texture_get_parent(src_impl
->wined3d_texture
);
1432 ddraw_texture_rename_to(dst_ddraw_texture
, src_impl
->wined3d_texture
, src_impl
->draw_texture
,
1433 ddraw_surface_get_rendertarget_view(src_impl
), src_ddraw_texture
->texture_memory
);
1435 dst_ddraw_texture
= src_ddraw_texture
;
1439 for (current
= iface
;;)
1441 if (FAILED(hr
= ddraw_surface1_GetAttachedSurface(current
, &caps
, ¤t
)))
1443 ERR("Can't find a flip target\n");
1444 wined3d_mutex_unlock();
1445 return DDERR_NOTFLIPPABLE
; /* Unchecked */
1447 ddraw_surface1_Release(current
);
1448 if (current
== iface
)
1450 dst_impl
= impl_from_IDirectDrawSurface(iface
);
1454 src_impl
= impl_from_IDirectDrawSurface(current
);
1455 src_ddraw_texture
= wined3d_texture_get_parent(src_impl
->wined3d_texture
);
1457 ddraw_texture_rename_to(dst_ddraw_texture
, src_impl
->wined3d_texture
, src_impl
->draw_texture
,
1458 ddraw_surface_get_rendertarget_view(src_impl
), src_ddraw_texture
->texture_memory
);
1460 dst_ddraw_texture
= src_ddraw_texture
;
1461 dst_impl
= src_impl
;
1465 ddraw_texture_rename_to(dst_ddraw_texture
, texture
, draw_texture
, tmp_rtv
, texture_memory
);
1467 if (flags
& ~(DDFLIP_NOVSYNC
| DDFLIP_INTERVAL2
| DDFLIP_INTERVAL3
| DDFLIP_INTERVAL4
))
1471 FIXME("Ignoring flags %#lx.\n", flags
);
1473 WARN("Ignoring flags %#lx.\n", flags
);
1476 if (dst_impl
->surface_desc
.ddsCaps
.dwCaps
& DDSCAPS_PRIMARYSURFACE
)
1477 hr
= ddraw_surface_update_frontbuffer(dst_impl
, NULL
, FALSE
, ddraw_swap_interval_from_flags(flags
));
1481 wined3d_mutex_unlock();
1486 static HRESULT WINAPI DECLSPEC_HOTPATCH
ddraw_surface7_Flip(IDirectDrawSurface7
*iface
,
1487 IDirectDrawSurface7
*src
, DWORD flags
)
1489 struct ddraw_surface
*surface
= impl_from_IDirectDrawSurface7(iface
);
1490 struct ddraw_surface
*src_impl
= unsafe_impl_from_IDirectDrawSurface7(src
);
1492 TRACE("iface %p, src %p, flags %#lx.\n", iface
, src
, flags
);
1494 return ddraw_surface1_Flip(&surface
->IDirectDrawSurface_iface
,
1495 src_impl
? &src_impl
->IDirectDrawSurface_iface
: NULL
, flags
);
1498 static HRESULT WINAPI DECLSPEC_HOTPATCH
ddraw_surface4_Flip(IDirectDrawSurface4
*iface
,
1499 IDirectDrawSurface4
*src
, DWORD flags
)
1501 struct ddraw_surface
*surface
= impl_from_IDirectDrawSurface4(iface
);
1502 struct ddraw_surface
*src_impl
= unsafe_impl_from_IDirectDrawSurface4(src
);
1504 TRACE("iface %p, src %p, flags %#lx.\n", iface
, src
, flags
);
1506 return ddraw_surface1_Flip(&surface
->IDirectDrawSurface_iface
,
1507 src_impl
? &src_impl
->IDirectDrawSurface_iface
: NULL
, flags
);
1510 static HRESULT WINAPI DECLSPEC_HOTPATCH
ddraw_surface3_Flip(IDirectDrawSurface3
*iface
,
1511 IDirectDrawSurface3
*src
, DWORD flags
)
1513 struct ddraw_surface
*surface
= impl_from_IDirectDrawSurface3(iface
);
1514 struct ddraw_surface
*src_impl
= unsafe_impl_from_IDirectDrawSurface3(src
);
1516 TRACE("iface %p, src %p, flags %#lx.\n", iface
, src
, flags
);
1518 return ddraw_surface1_Flip(&surface
->IDirectDrawSurface_iface
,
1519 src_impl
? &src_impl
->IDirectDrawSurface_iface
: NULL
, flags
);
1522 static HRESULT WINAPI DECLSPEC_HOTPATCH
ddraw_surface2_Flip(IDirectDrawSurface2
*iface
,
1523 IDirectDrawSurface2
*src
, DWORD flags
)
1525 struct ddraw_surface
*surface
= impl_from_IDirectDrawSurface2(iface
);
1526 struct ddraw_surface
*src_impl
= unsafe_impl_from_IDirectDrawSurface2(src
);
1528 TRACE("iface %p, src %p, flags %#lx.\n", iface
, src
, flags
);
1530 return ddraw_surface1_Flip(&surface
->IDirectDrawSurface_iface
,
1531 src_impl
? &src_impl
->IDirectDrawSurface_iface
: NULL
, flags
);
1534 static HRESULT
ddraw_surface_blt(struct ddraw_surface
*dst_surface
, const RECT
*dst_rect
,
1535 struct ddraw_surface
*src_surface
, const RECT
*src_rect
, DWORD flags
, DWORD fill_colour
,
1536 const struct wined3d_blt_fx
*fx
, enum wined3d_texture_filter_type filter
)
1538 struct ddraw
*ddraw
= dst_surface
->ddraw
;
1539 struct wined3d_device
*wined3d_device
= ddraw
->wined3d_device
;
1540 struct wined3d_color colour
;
1541 DWORD wined3d_flags
;
1543 if (flags
& DDBLT_COLORFILL
)
1545 wined3d_flags
= WINED3DCLEAR_TARGET
;
1546 if (!(flags
& DDBLT_ASYNC
))
1547 wined3d_flags
|= WINED3DCLEAR_SYNCHRONOUS
;
1549 if (!wined3d_colour_from_ddraw_colour(&dst_surface
->surface_desc
.u4
.ddpfPixelFormat
,
1550 dst_surface
->palette
, fill_colour
, &colour
))
1551 return DDERR_INVALIDPARAMS
;
1553 wined3d_device_apply_stateblock(wined3d_device
, ddraw
->state
);
1554 ddraw_surface_get_draw_texture(dst_surface
, dst_rect
? DDRAW_SURFACE_RW
: DDRAW_SURFACE_WRITE
);
1555 return wined3d_device_context_clear_rendertarget_view(ddraw
->immediate_context
,
1556 ddraw_surface_get_rendertarget_view(dst_surface
),
1557 dst_rect
, wined3d_flags
, &colour
, 0.0f
, 0);
1560 if (flags
& DDBLT_DEPTHFILL
)
1562 wined3d_flags
= WINED3DCLEAR_ZBUFFER
;
1563 if (!(flags
& DDBLT_ASYNC
))
1564 wined3d_flags
|= WINED3DCLEAR_SYNCHRONOUS
;
1566 if (!wined3d_colour_from_ddraw_colour(&dst_surface
->surface_desc
.u4
.ddpfPixelFormat
,
1567 dst_surface
->palette
, fill_colour
, &colour
))
1568 return DDERR_INVALIDPARAMS
;
1570 wined3d_device_apply_stateblock(wined3d_device
, ddraw
->state
);
1571 ddraw_surface_get_draw_texture(dst_surface
, dst_rect
? DDRAW_SURFACE_RW
: DDRAW_SURFACE_WRITE
);
1572 return wined3d_device_context_clear_rendertarget_view(ddraw
->immediate_context
,
1573 ddraw_surface_get_rendertarget_view(dst_surface
),
1574 dst_rect
, wined3d_flags
, NULL
, colour
.r
, 0);
1577 wined3d_flags
= flags
& ~DDBLT_ASYNC
;
1578 if (wined3d_flags
& ~WINED3D_BLT_MASK
)
1580 FIXME("Unhandled flags %#lx.\n", flags
);
1584 if (!(flags
& DDBLT_ASYNC
))
1585 wined3d_flags
|= WINED3D_BLT_SYNCHRONOUS
;
1587 return wined3d_device_context_blt(ddraw
->immediate_context
,
1588 ddraw_surface_get_any_texture(dst_surface
, DDRAW_SURFACE_RW
), dst_surface
->sub_resource_idx
, dst_rect
,
1589 ddraw_surface_get_any_texture(src_surface
, DDRAW_SURFACE_READ
), src_surface
->sub_resource_idx
, src_rect
,
1590 wined3d_flags
, fx
, filter
);
1593 static HRESULT
ddraw_surface_blt_clipped(struct ddraw_surface
*dst_surface
, const RECT
*dst_rect_in
,
1594 struct ddraw_surface
*src_surface
, const RECT
*src_rect_in
, DWORD flags
, DWORD fill_colour
,
1595 const struct wined3d_blt_fx
*fx
, enum wined3d_texture_filter_type filter
)
1597 RECT src_rect
, dst_rect
;
1598 float scale_x
, scale_y
;
1599 const RECT
*clip_rect
;
1600 DWORD clip_list_size
;
1606 SetRect(&dst_rect
, 0, 0, dst_surface
->surface_desc
.dwWidth
,
1607 dst_surface
->surface_desc
.dwHeight
);
1609 dst_rect
= *dst_rect_in
;
1611 if (IsRectEmpty(&dst_rect
))
1612 return DDERR_INVALIDRECT
;
1617 SetRect(&src_rect
, 0, 0, src_surface
->surface_desc
.dwWidth
,
1618 src_surface
->surface_desc
.dwHeight
);
1620 src_rect
= *src_rect_in
;
1622 if (IsRectEmpty(&src_rect
))
1623 return DDERR_INVALIDRECT
;
1627 SetRectEmpty(&src_rect
);
1630 if (!dst_surface
->clipper
)
1632 if (src_surface
&& src_surface
->surface_desc
.ddsCaps
.dwCaps
& DDSCAPS_PRIMARYSURFACE
)
1633 hr
= ddraw_surface_update_frontbuffer(src_surface
, &src_rect
, TRUE
, 0);
1635 hr
= ddraw_surface_blt(dst_surface
, &dst_rect
, src_surface
, &src_rect
, flags
, fill_colour
, fx
, filter
);
1636 if (SUCCEEDED(hr
) && (dst_surface
->surface_desc
.ddsCaps
.dwCaps
& DDSCAPS_PRIMARYSURFACE
))
1637 hr
= ddraw_surface_update_frontbuffer(dst_surface
, &dst_rect
, FALSE
, 0);
1642 if (!ddraw_clipper_is_valid(dst_surface
->clipper
))
1644 FIXME("Attempting to blit with an invalid clipper.\n");
1645 return DDERR_INVALIDPARAMS
;
1648 scale_x
= (float)(src_rect
.right
- src_rect
.left
) / (float)(dst_rect
.right
- dst_rect
.left
);
1649 scale_y
= (float)(src_rect
.bottom
- src_rect
.top
) / (float)(dst_rect
.bottom
- dst_rect
.top
);
1651 if (FAILED(hr
= IDirectDrawClipper_GetClipList(&dst_surface
->clipper
->IDirectDrawClipper_iface
,
1652 &dst_rect
, NULL
, &clip_list_size
)))
1654 WARN("Failed to get clip list size, hr %#lx.\n", hr
);
1658 if (!(clip_list
= heap_alloc(clip_list_size
)))
1660 WARN("Failed to allocate clip list.\n");
1661 return E_OUTOFMEMORY
;
1664 if (FAILED(hr
= IDirectDrawClipper_GetClipList(&dst_surface
->clipper
->IDirectDrawClipper_iface
,
1665 &dst_rect
, clip_list
, &clip_list_size
)))
1667 WARN("Failed to get clip list, hr %#lx.\n", hr
);
1668 heap_free(clip_list
);
1672 clip_rect
= (RECT
*)clip_list
->Buffer
;
1673 for (i
= 0; i
< clip_list
->rdh
.nCount
; ++i
)
1675 RECT src_rect_clipped
= src_rect
;
1679 src_rect_clipped
.left
+= (LONG
)((clip_rect
[i
].left
- dst_rect
.left
) * scale_x
);
1680 src_rect_clipped
.top
+= (LONG
)((clip_rect
[i
].top
- dst_rect
.top
) * scale_y
);
1681 src_rect_clipped
.right
-= (LONG
)((dst_rect
.right
- clip_rect
[i
].right
) * scale_x
);
1682 src_rect_clipped
.bottom
-= (LONG
)((dst_rect
.bottom
- clip_rect
[i
].bottom
) * scale_y
);
1684 if (src_surface
->surface_desc
.ddsCaps
.dwCaps
& DDSCAPS_PRIMARYSURFACE
)
1686 if (FAILED(hr
= ddraw_surface_update_frontbuffer(src_surface
, &src_rect_clipped
, TRUE
, 0)))
1691 if (FAILED(hr
= ddraw_surface_blt(dst_surface
, &clip_rect
[i
],
1692 src_surface
, &src_rect_clipped
, flags
, fill_colour
, fx
, filter
)))
1695 if (dst_surface
->surface_desc
.ddsCaps
.dwCaps
& DDSCAPS_PRIMARYSURFACE
)
1697 if (FAILED(hr
= ddraw_surface_update_frontbuffer(dst_surface
, &clip_rect
[i
], FALSE
, 0)))
1702 heap_free(clip_list
);
1706 /* FRAPS hooks IDirectDrawSurface::Blt and expects the version 1 method to be called when the
1707 * game uses later interfaces. */
1708 static HRESULT WINAPI DECLSPEC_HOTPATCH
ddraw_surface1_Blt(IDirectDrawSurface
*iface
, RECT
*dst_rect
,
1709 IDirectDrawSurface
*src_surface
, RECT
*src_rect
, DWORD flags
, DDBLTFX
*fx
)
1711 struct ddraw_surface
*dst_impl
= impl_from_IDirectDrawSurface(iface
);
1712 struct ddraw_surface
*src_impl
= unsafe_impl_from_IDirectDrawSurface(src_surface
);
1713 struct wined3d_blt_fx wined3d_fx
= {0};
1714 DWORD unsupported_flags
;
1715 DWORD fill_colour
= 0;
1719 TRACE("iface %p, dst_rect %s, src_surface %p, src_rect %s, flags %#lx, fx %p.\n",
1720 iface
, wine_dbgstr_rect(dst_rect
), src_surface
, wine_dbgstr_rect(src_rect
), flags
, fx
);
1722 unsupported_flags
= DDBLT_ALPHADEST
1723 | DDBLT_ALPHADESTCONSTOVERRIDE
1724 | DDBLT_ALPHADESTNEG
1725 | DDBLT_ALPHADESTSURFACEOVERRIDE
1726 | DDBLT_ALPHAEDGEBLEND
1728 | DDBLT_ALPHASRCCONSTOVERRIDE
1730 | DDBLT_ALPHASRCSURFACEOVERRIDE
1732 | DDBLT_ZBUFFERDESTCONSTOVERRIDE
1733 | DDBLT_ZBUFFERDESTOVERRIDE
1734 | DDBLT_ZBUFFERSRCCONSTOVERRIDE
1735 | DDBLT_ZBUFFERSRCOVERRIDE
;
1736 if (flags
& unsupported_flags
)
1738 WARN("Ignoring unsupported flags %#lx.\n", flags
& unsupported_flags
);
1739 flags
&= ~unsupported_flags
;
1742 if ((flags
& DDBLT_KEYSRCOVERRIDE
) && (!fx
|| flags
& DDBLT_KEYSRC
))
1744 WARN("Invalid source color key parameters, returning DDERR_INVALIDPARAMS\n");
1745 return DDERR_INVALIDPARAMS
;
1748 if ((flags
& DDBLT_KEYDESTOVERRIDE
) && (!fx
|| flags
& DDBLT_KEYDEST
))
1750 WARN("Invalid destination color key parameters, returning DDERR_INVALIDPARAMS\n");
1751 return DDERR_INVALIDPARAMS
;
1754 if (flags
& DDBLT_DDROPS
)
1756 FIXME("DDBLT_DDROPS not implemented.\n");
1758 FIXME(" rop %#lx, pattern %p.\n", fx
->dwDDROP
, fx
->u5
.lpDDSPattern
);
1759 return DDERR_NORASTEROPHW
;
1762 wined3d_mutex_lock();
1764 if (flags
& (DDBLT_COLORFILL
| DDBLT_DEPTHFILL
))
1766 if (flags
& DDBLT_ROP
)
1768 wined3d_mutex_unlock();
1769 WARN("DDBLT_ROP used with DDBLT_COLORFILL or DDBLT_DEPTHFILL, returning DDERR_INVALIDPARAMS.\n");
1770 return DDERR_INVALIDPARAMS
;
1774 wined3d_mutex_unlock();
1775 WARN("Depth or colorfill is not compatible with source surfaces, returning DDERR_INVALIDPARAMS\n");
1776 return DDERR_INVALIDPARAMS
;
1780 wined3d_mutex_unlock();
1781 WARN("Depth or colorfill used with NULL fx, returning DDERR_INVALIDPARAMS.\n");
1782 return DDERR_INVALIDPARAMS
;
1785 if ((flags
& (DDBLT_COLORFILL
| DDBLT_DEPTHFILL
)) == (DDBLT_COLORFILL
| DDBLT_DEPTHFILL
))
1786 flags
&= ~DDBLT_DEPTHFILL
;
1788 if ((dst_impl
->surface_desc
.ddsCaps
.dwCaps
& DDSCAPS_ZBUFFER
) && (flags
& DDBLT_COLORFILL
))
1790 wined3d_mutex_unlock();
1791 WARN("DDBLT_COLORFILL used on a depth buffer, returning DDERR_INVALIDPARAMS.\n");
1792 return DDERR_INVALIDPARAMS
;
1794 if (!(dst_impl
->surface_desc
.ddsCaps
.dwCaps
& DDSCAPS_ZBUFFER
) && (flags
& DDBLT_DEPTHFILL
))
1796 wined3d_mutex_unlock();
1797 WARN("DDBLT_DEPTHFILL used on a color buffer, returning DDERR_INVALIDPARAMS.\n");
1798 return DDERR_INVALIDPARAMS
;
1802 if (flags
& DDBLT_ROP
)
1806 wined3d_mutex_unlock();
1807 WARN("DDBLT_ROP used with NULL fx, returning DDERR_INVALIDPARAMS.\n");
1808 return DDERR_INVALIDPARAMS
;
1811 if (src_impl
&& src_rect
1812 && ((ULONG
)src_rect
->left
>= src_rect
->right
|| src_rect
->right
> src_impl
->surface_desc
.dwWidth
1813 || (ULONG
)src_rect
->top
>= src_rect
->bottom
|| src_rect
->bottom
> src_impl
->surface_desc
.dwHeight
))
1815 wined3d_mutex_unlock();
1816 WARN("Invalid source rectangle.\n");
1817 return DDERR_INVALIDRECT
;
1820 flags
&= ~DDBLT_ROP
;
1830 if (fx
->dwROP
== WHITENESS
)
1831 rop_fx
.u5
.dwFillColor
= 0xffffffff;
1833 rop_fx
.u5
.dwFillColor
= 0;
1835 if (dst_impl
->surface_desc
.ddsCaps
.dwCaps
& DDSCAPS_ZBUFFER
)
1836 flags
|= DDBLT_DEPTHFILL
;
1838 flags
|= DDBLT_COLORFILL
;
1844 wined3d_mutex_unlock();
1845 WARN("Unsupported ROP %#lx used, returning DDERR_NORASTEROPHW.\n", fx
->dwROP
);
1846 return DDERR_NORASTEROPHW
;
1850 if (!(flags
& (DDBLT_COLORFILL
| DDBLT_DEPTHFILL
)) && !src_impl
)
1852 WARN("No source surface.\n");
1853 wined3d_mutex_unlock();
1854 return DDERR_INVALIDPARAMS
;
1857 if (flags
& DDBLT_KEYSRC
&& (!src_impl
|| !(src_impl
->surface_desc
.dwFlags
& DDSD_CKSRCBLT
)))
1859 WARN("DDBLT_KEYSRC blit without color key in surface, returning DDERR_INVALIDPARAMS\n");
1860 wined3d_mutex_unlock();
1861 return DDERR_INVALIDPARAMS
;
1863 if (flags
& DDBLT_KEYDEST
&& !(dst_impl
->surface_desc
.dwFlags
& DDSD_CKDESTBLT
))
1865 WARN("DDBLT_KEYDEST blit without color key in surface, returning DDERR_INVALIDPARAMS\n");
1866 wined3d_mutex_unlock();
1867 return DDERR_INVALIDPARAMS
;
1872 wined3d_fx
.fx
= fx
->dwDDFX
;
1873 fill_colour
= fx
->u5
.dwFillColor
;
1874 wined3d_fx
.dst_color_key
.color_space_low_value
= fx
->ddckDestColorkey
.dwColorSpaceLowValue
;
1875 wined3d_fx
.dst_color_key
.color_space_high_value
= fx
->ddckDestColorkey
.dwColorSpaceHighValue
;
1876 wined3d_fx
.src_color_key
.color_space_low_value
= fx
->ddckSrcColorkey
.dwColorSpaceLowValue
;
1877 wined3d_fx
.src_color_key
.color_space_high_value
= fx
->ddckSrcColorkey
.dwColorSpaceHighValue
;
1880 hr
= ddraw_surface_blt_clipped(dst_impl
, dst_rect
, src_impl
,
1881 src_rect
, flags
, fill_colour
, fx
? &wined3d_fx
: NULL
, WINED3D_TEXF_LINEAR
);
1883 wined3d_mutex_unlock();
1886 case WINED3DERR_NOTAVAILABLE
: return DDERR_UNSUPPORTED
;
1891 static HRESULT WINAPI DECLSPEC_HOTPATCH
ddraw_surface7_Blt(IDirectDrawSurface7
*iface
, RECT
*dst_rect
,
1892 IDirectDrawSurface7
*src_surface
, RECT
*src_rect
, DWORD flags
, DDBLTFX
*fx
)
1894 struct ddraw_surface
*dst
= impl_from_IDirectDrawSurface7(iface
);
1895 struct ddraw_surface
*src
= unsafe_impl_from_IDirectDrawSurface7(src_surface
);
1897 TRACE("iface %p, dst_rect %s, src_surface %p, src_rect %s, flags %#lx, fx %p.\n",
1898 iface
, wine_dbgstr_rect(dst_rect
), src_surface
, wine_dbgstr_rect(src_rect
), flags
, fx
);
1900 return ddraw_surface1_Blt(&dst
->IDirectDrawSurface_iface
, dst_rect
,
1901 src
? &src
->IDirectDrawSurface_iface
: NULL
, src_rect
, flags
, fx
);
1904 static HRESULT WINAPI DECLSPEC_HOTPATCH
ddraw_surface4_Blt(IDirectDrawSurface4
*iface
, RECT
*dst_rect
,
1905 IDirectDrawSurface4
*src_surface
, RECT
*src_rect
, DWORD flags
, DDBLTFX
*fx
)
1907 struct ddraw_surface
*dst
= impl_from_IDirectDrawSurface4(iface
);
1908 struct ddraw_surface
*src
= unsafe_impl_from_IDirectDrawSurface4(src_surface
);
1910 TRACE("iface %p, dst_rect %s, src_surface %p, src_rect %s, flags %#lx, fx %p.\n",
1911 iface
, wine_dbgstr_rect(dst_rect
), src_surface
, wine_dbgstr_rect(src_rect
), flags
, fx
);
1913 return ddraw_surface1_Blt(&dst
->IDirectDrawSurface_iface
, dst_rect
,
1914 src
? &src
->IDirectDrawSurface_iface
: NULL
, src_rect
, flags
, fx
);
1917 static HRESULT WINAPI DECLSPEC_HOTPATCH
ddraw_surface3_Blt(IDirectDrawSurface3
*iface
, RECT
*dst_rect
,
1918 IDirectDrawSurface3
*src_surface
, RECT
*src_rect
, DWORD flags
, DDBLTFX
*fx
)
1920 struct ddraw_surface
*dst
= impl_from_IDirectDrawSurface3(iface
);
1921 struct ddraw_surface
*src
= unsafe_impl_from_IDirectDrawSurface3(src_surface
);
1923 TRACE("iface %p, dst_rect %s, src_surface %p, src_rect %s, flags %#lx, fx %p.\n",
1924 iface
, wine_dbgstr_rect(dst_rect
), src_surface
, wine_dbgstr_rect(src_rect
), flags
, fx
);
1926 return ddraw_surface1_Blt(&dst
->IDirectDrawSurface_iface
, dst_rect
,
1927 src
? &src
->IDirectDrawSurface_iface
: NULL
, src_rect
, flags
, fx
);
1930 static HRESULT WINAPI DECLSPEC_HOTPATCH
ddraw_surface2_Blt(IDirectDrawSurface2
*iface
, RECT
*dst_rect
,
1931 IDirectDrawSurface2
*src_surface
, RECT
*src_rect
, DWORD flags
, DDBLTFX
*fx
)
1933 struct ddraw_surface
*dst
= impl_from_IDirectDrawSurface2(iface
);
1934 struct ddraw_surface
*src
= unsafe_impl_from_IDirectDrawSurface2(src_surface
);
1936 TRACE("iface %p, dst_rect %s, src_surface %p, src_rect %s, flags %#lx, fx %p.\n",
1937 iface
, wine_dbgstr_rect(dst_rect
), src_surface
, wine_dbgstr_rect(src_rect
), flags
, fx
);
1939 return ddraw_surface1_Blt(&dst
->IDirectDrawSurface_iface
, dst_rect
,
1940 src
? &src
->IDirectDrawSurface_iface
: NULL
, src_rect
, flags
, fx
);
1943 /*****************************************************************************
1944 * IDirectDrawSurface7::AddAttachedSurface
1946 * Attaches a surface to another surface. How the surface attachments work
1947 * is not totally understood yet, and this method is prone to problems.
1948 * The surface that is attached is AddRef-ed.
1950 * Tests with complex surfaces suggest that the surface attachments form a
1951 * tree, but no method to test this has been found yet.
1953 * The attachment list consists of a first surface (first_attached) and
1954 * for each surface a pointer to the next attached surface (next_attached).
1955 * For the first surface, and a surface that has no attachments
1956 * first_attached points to the surface itself. A surface that has
1957 * no successors in the chain has next_attached set to NULL.
1959 * Newly attached surfaces are attached right after the root surface.
1960 * If a surface is attached to a complex surface compound, it's attached to
1961 * the surface that the app requested, not the complex root. See
1962 * GetAttachedSurface for a description how surfaces are found.
1964 * This is how the current implementation works, and it was coded by looking
1965 * at the needs of the applications.
1967 * So far only Z-Buffer attachments are tested, and they are activated in
1968 * WineD3D. Mipmaps could be tricky to activate in WineD3D.
1969 * Back buffers should work in 2D mode, but they are not tested(They can be
1970 * attached in older iface versions). Rendering to the front buffer and
1971 * switching between that and double buffering is not yet implemented in
1972 * WineD3D, so for 3D it might have unexpected results.
1974 * ddraw_surface_attach_surface is the real thing,
1975 * ddraw_surface7_AddAttachedSurface is a wrapper around it that
1976 * performs additional checks. Version 7 of this interface is much more restrictive
1977 * than its predecessors.
1980 * Attach: Surface to attach to iface
1984 * DDERR_CANNOTATTACHSURFACE if the surface can't be attached for some reason
1986 *****************************************************************************/
1987 static HRESULT
ddraw_surface_attach_surface(struct ddraw_surface
*This
, struct ddraw_surface
*Surf
)
1989 TRACE("surface %p, attachment %p.\n", This
, Surf
);
1992 return DDERR_CANNOTATTACHSURFACE
; /* unchecked */
1994 wined3d_mutex_lock();
1996 /* Check if the surface is already attached somewhere */
1997 if (Surf
->next_attached
|| Surf
->first_attached
!= Surf
)
1999 /* TODO: Test for the structure of the manual attachment. Is it a
2000 * chain or a list? What happens if one surface is attached to 2
2001 * different surfaces? */
2002 WARN("Surface %p is already attached somewhere. next_attached %p, first_attached %p.\n",
2003 Surf
, Surf
->next_attached
, Surf
->first_attached
);
2005 wined3d_mutex_unlock();
2006 return DDERR_SURFACEALREADYATTACHED
;
2009 /* This inserts the new surface at the 2nd position in the chain, right after the root surface */
2010 Surf
->next_attached
= This
->next_attached
;
2011 Surf
->first_attached
= This
->first_attached
;
2012 This
->next_attached
= Surf
;
2014 /* Check if the WineD3D depth stencil needs updating */
2015 if (This
->ddraw
->d3ddevice
)
2016 d3d_device_update_depth_stencil(This
->ddraw
->d3ddevice
);
2018 wined3d_mutex_unlock();
2023 static HRESULT WINAPI
ddraw_surface7_AddAttachedSurface(IDirectDrawSurface7
*iface
, IDirectDrawSurface7
*attachment
)
2025 struct ddraw_surface
*This
= impl_from_IDirectDrawSurface7(iface
);
2026 struct ddraw_surface
*attachment_impl
= unsafe_impl_from_IDirectDrawSurface7(attachment
);
2029 TRACE("iface %p, attachment %p.\n", iface
, attachment
);
2031 /* Version 7 of this interface seems to refuse everything except z buffers, as per msdn */
2032 if(!(attachment_impl
->surface_desc
.ddsCaps
.dwCaps
& DDSCAPS_ZBUFFER
))
2035 WARN("Application tries to attach a non Z buffer surface. caps %#lx.\n",
2036 attachment_impl
->surface_desc
.ddsCaps
.dwCaps
);
2037 return DDERR_CANNOTATTACHSURFACE
;
2040 hr
= ddraw_surface_attach_surface(This
, attachment_impl
);
2045 attachment_impl
->attached_iface
= (IUnknown
*)attachment
;
2046 IUnknown_AddRef(attachment_impl
->attached_iface
);
2050 static HRESULT WINAPI
ddraw_surface4_AddAttachedSurface(IDirectDrawSurface4
*iface
, IDirectDrawSurface4
*attachment
)
2052 struct ddraw_surface
*surface
= impl_from_IDirectDrawSurface4(iface
);
2053 struct ddraw_surface
*attachment_impl
= unsafe_impl_from_IDirectDrawSurface4(attachment
);
2056 TRACE("iface %p, attachment %p.\n", iface
, attachment
);
2058 /* Tests suggest that
2059 * -> offscreen plain surfaces can be attached to other offscreen plain surfaces
2060 * -> offscreen plain surfaces can be attached to primaries
2061 * -> primaries can be attached to offscreen plain surfaces
2062 * -> z buffers can be attached to primaries */
2063 if (surface
->surface_desc
.ddsCaps
.dwCaps
& (DDSCAPS_PRIMARYSURFACE
| DDSCAPS_OFFSCREENPLAIN
)
2064 && attachment_impl
->surface_desc
.ddsCaps
.dwCaps
& (DDSCAPS_PRIMARYSURFACE
| DDSCAPS_OFFSCREENPLAIN
))
2066 /* Sizes have to match */
2067 if (attachment_impl
->surface_desc
.dwWidth
!= surface
->surface_desc
.dwWidth
2068 || attachment_impl
->surface_desc
.dwHeight
!= surface
->surface_desc
.dwHeight
)
2070 WARN("Surface sizes do not match.\n");
2071 return DDERR_CANNOTATTACHSURFACE
;
2074 else if (!(surface
->surface_desc
.ddsCaps
.dwCaps
& (DDSCAPS_PRIMARYSURFACE
| DDSCAPS_3DDEVICE
))
2075 || !(attachment_impl
->surface_desc
.ddsCaps
.dwCaps
& (DDSCAPS_ZBUFFER
)))
2077 WARN("Invalid attachment combination.\n");
2078 return DDERR_CANNOTATTACHSURFACE
;
2081 if (FAILED(hr
= ddraw_surface_attach_surface(surface
, attachment_impl
)))
2084 attachment_impl
->attached_iface
= (IUnknown
*)attachment
;
2085 IUnknown_AddRef(attachment_impl
->attached_iface
);
2089 static HRESULT WINAPI
ddraw_surface3_AddAttachedSurface(IDirectDrawSurface3
*iface
, IDirectDrawSurface3
*attachment
)
2091 struct ddraw_surface
*surface
= impl_from_IDirectDrawSurface3(iface
);
2092 struct ddraw_surface
*attachment_impl
= unsafe_impl_from_IDirectDrawSurface3(attachment
);
2095 TRACE("iface %p, attachment %p.\n", iface
, attachment
);
2097 if (FAILED(hr
= ddraw_surface4_AddAttachedSurface(&surface
->IDirectDrawSurface4_iface
,
2098 attachment_impl
? &attachment_impl
->IDirectDrawSurface4_iface
: NULL
)))
2101 attachment_impl
->attached_iface
= (IUnknown
*)attachment
;
2102 IUnknown_AddRef(attachment_impl
->attached_iface
);
2103 ddraw_surface4_Release(&attachment_impl
->IDirectDrawSurface4_iface
);
2107 static HRESULT WINAPI
ddraw_surface2_AddAttachedSurface(IDirectDrawSurface2
*iface
, IDirectDrawSurface2
*attachment
)
2109 struct ddraw_surface
*surface
= impl_from_IDirectDrawSurface2(iface
);
2110 struct ddraw_surface
*attachment_impl
= unsafe_impl_from_IDirectDrawSurface2(attachment
);
2113 TRACE("iface %p, attachment %p.\n", iface
, attachment
);
2115 if (FAILED(hr
= ddraw_surface4_AddAttachedSurface(&surface
->IDirectDrawSurface4_iface
,
2116 attachment_impl
? &attachment_impl
->IDirectDrawSurface4_iface
: NULL
)))
2119 attachment_impl
->attached_iface
= (IUnknown
*)attachment
;
2120 IUnknown_AddRef(attachment_impl
->attached_iface
);
2121 ddraw_surface4_Release(&attachment_impl
->IDirectDrawSurface4_iface
);
2125 static HRESULT WINAPI
ddraw_surface1_AddAttachedSurface(IDirectDrawSurface
*iface
, IDirectDrawSurface
*attachment
)
2127 struct ddraw_surface
*surface
= impl_from_IDirectDrawSurface(iface
);
2128 struct ddraw_surface
*attachment_impl
= unsafe_impl_from_IDirectDrawSurface(attachment
);
2131 TRACE("iface %p, attachment %p.\n", iface
, attachment
);
2133 if (FAILED(hr
= ddraw_surface4_AddAttachedSurface(&surface
->IDirectDrawSurface4_iface
,
2134 attachment_impl
? &attachment_impl
->IDirectDrawSurface4_iface
: NULL
)))
2137 attachment_impl
->attached_iface
= (IUnknown
*)attachment
;
2138 IUnknown_AddRef(attachment_impl
->attached_iface
);
2139 ddraw_surface4_Release(&attachment_impl
->IDirectDrawSurface4_iface
);
2143 /*****************************************************************************
2144 * IDirectDrawSurface7::DeleteAttachedSurface
2146 * Removes a surface from the attachment chain. The surface's refcount
2147 * is decreased by one after it has been removed
2150 * Flags: Some flags, not used by this implementation
2151 * Attach: Surface to detach
2155 * DDERR_SURFACENOTATTACHED if the surface isn't attached to
2157 *****************************************************************************/
2158 static HRESULT
ddraw_surface_delete_attached_surface(struct ddraw_surface
*surface
,
2159 struct ddraw_surface
*attachment
, IUnknown
*detach_iface
)
2161 struct wined3d_rendertarget_view
*dsv
;
2162 struct ddraw_surface
*prev
= surface
;
2164 TRACE("surface %p, attachment %p, detach_iface %p.\n", surface
, attachment
, detach_iface
);
2166 wined3d_mutex_lock();
2167 if (!attachment
|| (attachment
->first_attached
!= surface
) || (attachment
== surface
) )
2169 wined3d_mutex_unlock();
2170 return DDERR_CANNOTDETACHSURFACE
;
2173 if (attachment
->attached_iface
!= detach_iface
)
2175 WARN("attachment->attach_iface %p != detach_iface %p.\n", attachment
->attached_iface
, detach_iface
);
2176 wined3d_mutex_unlock();
2177 return DDERR_SURFACENOTATTACHED
;
2180 /* Remove MIPMAPSUBLEVEL if this seemed to be one */
2181 if (surface
->surface_desc
.ddsCaps
.dwCaps
& attachment
->surface_desc
.ddsCaps
.dwCaps
& DDSCAPS_MIPMAP
)
2183 attachment
->surface_desc
.ddsCaps
.dwCaps2
&= ~DDSCAPS2_MIPMAPSUBLEVEL
;
2184 /* FIXME: we should probably also subtract from dwMipMapCount of this
2185 * and all parent surfaces */
2188 /* Find the predecessor of the detached surface */
2189 while (prev
->next_attached
!= attachment
)
2191 if (!(prev
= prev
->next_attached
))
2193 ERR("Failed to find predecessor of %p.\n", attachment
);
2194 wined3d_mutex_unlock();
2195 return DDERR_SURFACENOTATTACHED
;
2199 /* Unchain the surface */
2200 prev
->next_attached
= attachment
->next_attached
;
2201 attachment
->next_attached
= NULL
;
2202 attachment
->first_attached
= attachment
;
2204 /* Check if the wined3d depth stencil needs updating. Note that we don't
2205 * just call d3d_device_update_depth_stencil() here since it uses
2206 * QueryInterface(). Some applications, SCP - Containment Breach in
2207 * particular, modify the QueryInterface() pointer in the surface vtbl
2208 * but don't cleanup properly after the relevant dll is unloaded. */
2209 dsv
= wined3d_device_context_get_depth_stencil_view(surface
->ddraw
->immediate_context
);
2210 if (attachment
->surface_desc
.ddsCaps
.dwCaps
& DDSCAPS_ZBUFFER
&& dsv
== attachment
->wined3d_rtv
)
2211 wined3d_device_context_set_depth_stencil_view(surface
->ddraw
->immediate_context
, NULL
);
2212 wined3d_mutex_unlock();
2214 /* Set attached_iface to NULL before releasing it, the surface may go
2216 attachment
->attached_iface
= NULL
;
2217 IUnknown_Release(detach_iface
);
2222 static HRESULT WINAPI
ddraw_surface7_DeleteAttachedSurface(IDirectDrawSurface7
*iface
,
2223 DWORD flags
, IDirectDrawSurface7
*attachment
)
2225 struct ddraw_surface
*surface
= impl_from_IDirectDrawSurface7(iface
);
2226 struct ddraw_surface
*attachment_impl
= unsafe_impl_from_IDirectDrawSurface7(attachment
);
2228 TRACE("iface %p, flags %#lx, attachment %p.\n", iface
, flags
, attachment
);
2230 return ddraw_surface_delete_attached_surface(surface
, attachment_impl
, (IUnknown
*)attachment
);
2233 static HRESULT WINAPI
ddraw_surface4_DeleteAttachedSurface(IDirectDrawSurface4
*iface
,
2234 DWORD flags
, IDirectDrawSurface4
*attachment
)
2236 struct ddraw_surface
*surface
= impl_from_IDirectDrawSurface4(iface
);
2237 struct ddraw_surface
*attachment_impl
= unsafe_impl_from_IDirectDrawSurface4(attachment
);
2239 TRACE("iface %p, flags %#lx, attachment %p.\n", iface
, flags
, attachment
);
2241 return ddraw_surface_delete_attached_surface(surface
, attachment_impl
, (IUnknown
*)attachment
);
2244 static HRESULT WINAPI
ddraw_surface3_DeleteAttachedSurface(IDirectDrawSurface3
*iface
,
2245 DWORD flags
, IDirectDrawSurface3
*attachment
)
2247 struct ddraw_surface
*surface
= impl_from_IDirectDrawSurface3(iface
);
2248 struct ddraw_surface
*attachment_impl
= unsafe_impl_from_IDirectDrawSurface3(attachment
);
2250 TRACE("iface %p, flags %#lx, attachment %p.\n", iface
, flags
, attachment
);
2252 return ddraw_surface_delete_attached_surface(surface
, attachment_impl
, (IUnknown
*)attachment
);
2255 static HRESULT WINAPI
ddraw_surface2_DeleteAttachedSurface(IDirectDrawSurface2
*iface
,
2256 DWORD flags
, IDirectDrawSurface2
*attachment
)
2258 struct ddraw_surface
*surface
= impl_from_IDirectDrawSurface2(iface
);
2259 struct ddraw_surface
*attachment_impl
= unsafe_impl_from_IDirectDrawSurface2(attachment
);
2261 TRACE("iface %p, flags %#lx, attachment %p.\n", iface
, flags
, attachment
);
2263 return ddraw_surface_delete_attached_surface(surface
, attachment_impl
, (IUnknown
*)attachment
);
2266 static HRESULT WINAPI
ddraw_surface1_DeleteAttachedSurface(IDirectDrawSurface
*iface
,
2267 DWORD flags
, IDirectDrawSurface
*attachment
)
2269 struct ddraw_surface
*surface
= impl_from_IDirectDrawSurface(iface
);
2270 struct ddraw_surface
*attachment_impl
= unsafe_impl_from_IDirectDrawSurface(attachment
);
2272 TRACE("iface %p, flags %#lx, attachment %p.\n", iface
, flags
, attachment
);
2274 return ddraw_surface_delete_attached_surface(surface
, attachment_impl
, (IUnknown
*)attachment
);
2277 /*****************************************************************************
2278 * IDirectDrawSurface7::AddOverlayDirtyRect
2280 * "This method is not currently implemented"
2288 *****************************************************************************/
2289 static HRESULT WINAPI
ddraw_surface7_AddOverlayDirtyRect(IDirectDrawSurface7
*iface
, RECT
*Rect
)
2291 TRACE("iface %p, rect %s.\n", iface
, wine_dbgstr_rect(Rect
));
2293 return DDERR_UNSUPPORTED
; /* unchecked */
2296 static HRESULT WINAPI
ddraw_surface4_AddOverlayDirtyRect(IDirectDrawSurface4
*iface
, RECT
*rect
)
2298 struct ddraw_surface
*surface
= impl_from_IDirectDrawSurface4(iface
);
2300 TRACE("iface %p, rect %s.\n", iface
, wine_dbgstr_rect(rect
));
2302 return ddraw_surface7_AddOverlayDirtyRect(&surface
->IDirectDrawSurface7_iface
, rect
);
2305 static HRESULT WINAPI
ddraw_surface3_AddOverlayDirtyRect(IDirectDrawSurface3
*iface
, RECT
*rect
)
2307 struct ddraw_surface
*surface
= impl_from_IDirectDrawSurface3(iface
);
2309 TRACE("iface %p, rect %s.\n", iface
, wine_dbgstr_rect(rect
));
2311 return ddraw_surface7_AddOverlayDirtyRect(&surface
->IDirectDrawSurface7_iface
, rect
);
2314 static HRESULT WINAPI
ddraw_surface2_AddOverlayDirtyRect(IDirectDrawSurface2
*iface
, RECT
*rect
)
2316 struct ddraw_surface
*surface
= impl_from_IDirectDrawSurface2(iface
);
2318 TRACE("iface %p, rect %s.\n", iface
, wine_dbgstr_rect(rect
));
2320 return ddraw_surface7_AddOverlayDirtyRect(&surface
->IDirectDrawSurface7_iface
, rect
);
2323 static HRESULT WINAPI
ddraw_surface1_AddOverlayDirtyRect(IDirectDrawSurface
*iface
, RECT
*rect
)
2325 struct ddraw_surface
*surface
= impl_from_IDirectDrawSurface(iface
);
2327 TRACE("iface %p, rect %s.\n", iface
, wine_dbgstr_rect(rect
));
2329 return ddraw_surface7_AddOverlayDirtyRect(&surface
->IDirectDrawSurface7_iface
, rect
);
2332 /*****************************************************************************
2333 * IDirectDrawSurface7::GetDC
2335 * Returns a GDI device context for the surface
2338 * hdc: Address of a HDC variable to store the dc to
2342 * DDERR_INVALIDPARAMS if hdc is NULL
2344 *****************************************************************************/
2345 static HRESULT WINAPI
ddraw_surface7_GetDC(IDirectDrawSurface7
*iface
, HDC
*dc
)
2347 struct ddraw_surface
*surface
= impl_from_IDirectDrawSurface7(iface
);
2350 TRACE("iface %p, dc %p.\n", iface
, dc
);
2353 return DDERR_INVALIDPARAMS
;
2355 wined3d_mutex_lock();
2357 hr
= DDERR_DCALREADYCREATED
;
2358 else if (surface
->surface_desc
.ddsCaps
.dwCaps
& DDSCAPS_PRIMARYSURFACE
)
2359 hr
= ddraw_surface_update_frontbuffer(surface
, NULL
, TRUE
, 0);
2361 hr
= wined3d_texture_get_dc(ddraw_surface_get_default_texture(surface
, DDRAW_SURFACE_RW
), surface
->sub_resource_idx
, dc
);
2367 if (format_is_paletteindexed(&surface
->surface_desc
.u4
.ddpfPixelFormat
))
2369 const struct ddraw_palette
*palette
;
2371 if (surface
->palette
)
2372 palette
= surface
->palette
;
2373 else if (surface
->ddraw
->primary
)
2374 palette
= surface
->ddraw
->primary
->palette
;
2379 wined3d_palette_apply_to_dc(palette
->wined3d_palette
, *dc
);
2383 wined3d_mutex_unlock();
2386 /* Some, but not all errors set *dc to NULL. E.g. DCALREADYCREATED
2387 * does not touch *dc. */
2388 case WINED3DERR_INVALIDCALL
:
2390 return DDERR_CANTCREATEDC
;
2397 static HRESULT WINAPI
ddraw_surface4_GetDC(IDirectDrawSurface4
*iface
, HDC
*dc
)
2399 struct ddraw_surface
*surface
= impl_from_IDirectDrawSurface4(iface
);
2401 TRACE("iface %p, dc %p.\n", iface
, dc
);
2403 return ddraw_surface7_GetDC(&surface
->IDirectDrawSurface7_iface
, dc
);
2406 static HRESULT WINAPI
ddraw_surface3_GetDC(IDirectDrawSurface3
*iface
, HDC
*dc
)
2408 struct ddraw_surface
*surface
= impl_from_IDirectDrawSurface3(iface
);
2410 TRACE("iface %p, dc %p.\n", iface
, dc
);
2412 return ddraw_surface7_GetDC(&surface
->IDirectDrawSurface7_iface
, dc
);
2415 static HRESULT WINAPI
ddraw_surface2_GetDC(IDirectDrawSurface2
*iface
, HDC
*dc
)
2417 struct ddraw_surface
*surface
= impl_from_IDirectDrawSurface2(iface
);
2419 TRACE("iface %p, dc %p.\n", iface
, dc
);
2421 return ddraw_surface7_GetDC(&surface
->IDirectDrawSurface7_iface
, dc
);
2424 static HRESULT WINAPI
ddraw_surface1_GetDC(IDirectDrawSurface
*iface
, HDC
*dc
)
2426 struct ddraw_surface
*surface
= impl_from_IDirectDrawSurface(iface
);
2428 TRACE("iface %p, dc %p.\n", iface
, dc
);
2430 return ddraw_surface7_GetDC(&surface
->IDirectDrawSurface7_iface
, dc
);
2433 /*****************************************************************************
2434 * IDirectDrawSurface7::ReleaseDC
2436 * Releases the DC that was constructed with GetDC
2439 * hdc: HDC to release
2442 * DD_OK on success, error code otherwise.
2444 *****************************************************************************/
2445 static HRESULT WINAPI
ddraw_surface7_ReleaseDC(IDirectDrawSurface7
*iface
, HDC hdc
)
2447 struct ddraw_surface
*surface
= impl_from_IDirectDrawSurface7(iface
);
2450 TRACE("iface %p, dc %p.\n", iface
, hdc
);
2452 wined3d_mutex_lock();
2457 else if (SUCCEEDED(hr
= wined3d_texture_release_dc(ddraw_surface_get_default_texture(surface
, 0),
2458 surface
->sub_resource_idx
, hdc
)))
2461 if (surface
->surface_desc
.ddsCaps
.dwCaps
& DDSCAPS_PRIMARYSURFACE
)
2462 hr
= ddraw_surface_update_frontbuffer(surface
, NULL
, FALSE
, 0);
2464 wined3d_mutex_unlock();
2470 static HRESULT WINAPI
ddraw_surface4_ReleaseDC(IDirectDrawSurface4
*iface
, HDC dc
)
2472 struct ddraw_surface
*surface
= impl_from_IDirectDrawSurface4(iface
);
2474 TRACE("iface %p, dc %p.\n", iface
, dc
);
2476 return ddraw_surface7_ReleaseDC(&surface
->IDirectDrawSurface7_iface
, dc
);
2479 static HRESULT WINAPI
ddraw_surface3_ReleaseDC(IDirectDrawSurface3
*iface
, HDC dc
)
2481 struct ddraw_surface
*surface
= impl_from_IDirectDrawSurface3(iface
);
2483 TRACE("iface %p, dc %p.\n", iface
, dc
);
2485 return ddraw_surface7_ReleaseDC(&surface
->IDirectDrawSurface7_iface
, dc
);
2488 static HRESULT WINAPI
ddraw_surface2_ReleaseDC(IDirectDrawSurface2
*iface
, HDC dc
)
2490 struct ddraw_surface
*surface
= impl_from_IDirectDrawSurface2(iface
);
2492 TRACE("iface %p, dc %p.\n", iface
, dc
);
2494 return ddraw_surface7_ReleaseDC(&surface
->IDirectDrawSurface7_iface
, dc
);
2497 static HRESULT WINAPI
ddraw_surface1_ReleaseDC(IDirectDrawSurface
*iface
, HDC dc
)
2499 struct ddraw_surface
*surface
= impl_from_IDirectDrawSurface(iface
);
2501 TRACE("iface %p, dc %p.\n", iface
, dc
);
2503 return ddraw_surface7_ReleaseDC(&surface
->IDirectDrawSurface7_iface
, dc
);
2506 /*****************************************************************************
2507 * IDirectDrawSurface7::GetCaps
2509 * Returns the surface's caps
2512 * Caps: Address to write the caps to
2516 * DDERR_INVALIDPARAMS if Caps is NULL
2518 *****************************************************************************/
2519 static HRESULT WINAPI
ddraw_surface7_GetCaps(IDirectDrawSurface7
*iface
, DDSCAPS2
*Caps
)
2521 struct ddraw_surface
*surface
= impl_from_IDirectDrawSurface7(iface
);
2523 TRACE("iface %p, caps %p.\n", iface
, Caps
);
2526 return DDERR_INVALIDPARAMS
;
2528 *Caps
= surface
->surface_desc
.ddsCaps
;
2533 static HRESULT WINAPI
ddraw_surface4_GetCaps(IDirectDrawSurface4
*iface
, DDSCAPS2
*caps
)
2535 struct ddraw_surface
*surface
= impl_from_IDirectDrawSurface4(iface
);
2537 TRACE("iface %p, caps %p.\n", iface
, caps
);
2539 return ddraw_surface7_GetCaps(&surface
->IDirectDrawSurface7_iface
, caps
);
2542 static HRESULT WINAPI
ddraw_surface3_GetCaps(IDirectDrawSurface3
*iface
, DDSCAPS
*caps
)
2544 struct ddraw_surface
*surface
= impl_from_IDirectDrawSurface3(iface
);
2548 TRACE("iface %p, caps %p.\n", iface
, caps
);
2550 hr
= ddraw_surface7_GetCaps(&surface
->IDirectDrawSurface7_iface
, &caps2
);
2551 if (FAILED(hr
)) return hr
;
2553 caps
->dwCaps
= caps2
.dwCaps
;
2557 static HRESULT WINAPI
ddraw_surface2_GetCaps(IDirectDrawSurface2
*iface
, DDSCAPS
*caps
)
2559 struct ddraw_surface
*surface
= impl_from_IDirectDrawSurface2(iface
);
2563 TRACE("iface %p, caps %p.\n", iface
, caps
);
2565 hr
= ddraw_surface7_GetCaps(&surface
->IDirectDrawSurface7_iface
, &caps2
);
2566 if (FAILED(hr
)) return hr
;
2568 caps
->dwCaps
= caps2
.dwCaps
;
2572 static HRESULT WINAPI
ddraw_surface1_GetCaps(IDirectDrawSurface
*iface
, DDSCAPS
*caps
)
2574 struct ddraw_surface
*surface
= impl_from_IDirectDrawSurface(iface
);
2578 TRACE("iface %p, caps %p.\n", iface
, caps
);
2580 hr
= ddraw_surface7_GetCaps(&surface
->IDirectDrawSurface7_iface
, &caps2
);
2581 if (FAILED(hr
)) return hr
;
2583 caps
->dwCaps
= caps2
.dwCaps
;
2587 static HRESULT WINAPI
ddraw_surface7_SetPriority(IDirectDrawSurface7
*iface
, DWORD priority
)
2589 struct ddraw_surface
*surface
= impl_from_IDirectDrawSurface7(iface
);
2590 DWORD managed
= DDSCAPS2_TEXTUREMANAGE
| DDSCAPS2_D3DTEXTUREMANAGE
;
2592 struct wined3d_resource
*resource
;
2594 TRACE("iface %p, priority %lu.\n", iface
, priority
);
2596 wined3d_mutex_lock();
2597 /* No need to check for offscreen plain surfaces or mipmap sublevels. SetPriority
2598 * calls on such surfaces segfault on Windows. */
2599 if (!(surface
->surface_desc
.ddsCaps
.dwCaps2
& managed
))
2601 WARN("Called on non-managed texture returning DDERR_INVALIDPARAMS.\n");
2602 hr
= DDERR_INVALIDPARAMS
;
2606 resource
= wined3d_texture_get_resource(surface
->wined3d_texture
);
2607 wined3d_resource_set_priority(resource
, priority
);
2608 if (surface
->draw_texture
)
2609 wined3d_resource_set_priority(wined3d_texture_get_resource(surface
->draw_texture
), priority
);
2613 wined3d_mutex_unlock();
2618 static HRESULT WINAPI
ddraw_surface7_GetPriority(IDirectDrawSurface7
*iface
, DWORD
*priority
)
2620 struct ddraw_surface
*surface
= impl_from_IDirectDrawSurface7(iface
);
2621 const struct wined3d_resource
*resource
;
2622 DWORD managed
= DDSCAPS2_TEXTUREMANAGE
| DDSCAPS2_D3DTEXTUREMANAGE
;
2625 TRACE("iface %p, priority %p.\n", iface
, priority
);
2627 wined3d_mutex_lock();
2628 if (surface
->surface_desc
.ddsCaps
.dwCaps
& DDSCAPS_OFFSCREENPLAIN
)
2630 WARN("Called on offscreenplain surface, returning DDERR_INVALIDOBJECT.\n");
2631 hr
= DDERR_INVALIDOBJECT
;
2633 else if (!(surface
->surface_desc
.ddsCaps
.dwCaps2
& managed
) || !surface
->is_root
)
2635 WARN("Called on non-managed texture or non-root surface, returning DDERR_INVALIDPARAMS.\n");
2636 hr
= DDERR_INVALIDPARAMS
;
2640 resource
= wined3d_texture_get_resource(surface
->wined3d_texture
);
2641 *priority
= wined3d_resource_get_priority(resource
);
2644 wined3d_mutex_unlock();
2649 /*****************************************************************************
2650 * IDirectDrawSurface7::SetPrivateData
2652 * Stores some data in the surface that is intended for the application's
2656 * tag: GUID that identifies the data
2657 * Data: Pointer to the private data
2658 * Size: Size of the private data
2662 * D3D_OK on success, error code otherwise.
2664 *****************************************************************************/
2665 static HRESULT WINAPI
ddraw_surface7_SetPrivateData(IDirectDrawSurface7
*iface
,
2666 REFGUID tag
, void *data
, DWORD size
, DWORD flags
)
2668 struct ddraw_surface
*surface
= impl_from_IDirectDrawSurface7(iface
);
2671 TRACE("iface %p, tag %s, data %p, data_size %lu, flags %#lx.\n",
2672 iface
, debugstr_guid(tag
), data
, size
, flags
);
2676 WARN("data is NULL, returning DDERR_INVALIDPARAMS.\n");
2677 return DDERR_INVALIDPARAMS
;
2680 wined3d_mutex_lock();
2681 hr
= wined3d_private_store_set_private_data(&surface
->private_store
, tag
, data
, size
, flags
);
2682 wined3d_mutex_unlock();
2683 return hr_ddraw_from_wined3d(hr
);
2686 static HRESULT WINAPI
ddraw_surface4_SetPrivateData(IDirectDrawSurface4
*iface
,
2687 REFGUID tag
, void *data
, DWORD size
, DWORD flags
)
2689 struct ddraw_surface
*surface
= impl_from_IDirectDrawSurface4(iface
);
2691 TRACE("iface %p, tag %s, data %p, data_size %lu, flags %#lx.\n",
2692 iface
, debugstr_guid(tag
), data
, size
, flags
);
2694 return ddraw_surface7_SetPrivateData(&surface
->IDirectDrawSurface7_iface
, tag
, data
, size
, flags
);
2697 /*****************************************************************************
2698 * IDirectDrawSurface7::GetPrivateData
2700 * Returns the private data set with IDirectDrawSurface7::SetPrivateData
2703 * tag: GUID of the data to return
2704 * Data: Address where to write the data to
2705 * Size: Size of the buffer at Data
2709 * DDERR_INVALIDPARAMS if Data is NULL
2711 *****************************************************************************/
2712 static HRESULT WINAPI
ddraw_surface7_GetPrivateData(IDirectDrawSurface7
*iface
, REFGUID tag
, void *data
, DWORD
*size
)
2714 struct ddraw_surface
*surface
= impl_from_IDirectDrawSurface7(iface
);
2715 const struct wined3d_private_data
*stored_data
;
2718 TRACE("iface %p, tag %s, data %p, data_size %p.\n",
2719 iface
, debugstr_guid(tag
), data
, size
);
2721 wined3d_mutex_lock();
2722 stored_data
= wined3d_private_store_get_private_data(&surface
->private_store
, tag
);
2725 hr
= DDERR_NOTFOUND
;
2730 hr
= DDERR_INVALIDPARAMS
;
2733 if (*size
< stored_data
->size
)
2735 *size
= stored_data
->size
;
2736 hr
= DDERR_MOREDATA
;
2741 hr
= DDERR_INVALIDPARAMS
;
2745 *size
= stored_data
->size
;
2746 memcpy(data
, stored_data
->content
.data
, stored_data
->size
);
2750 wined3d_mutex_unlock();
2754 static HRESULT WINAPI
ddraw_surface4_GetPrivateData(IDirectDrawSurface4
*iface
, REFGUID tag
, void *data
, DWORD
*size
)
2756 struct ddraw_surface
*surface
= impl_from_IDirectDrawSurface4(iface
);
2758 TRACE("iface %p, tag %s, data %p, data_size %p.\n",
2759 iface
, debugstr_guid(tag
), data
, size
);
2761 return ddraw_surface7_GetPrivateData(&surface
->IDirectDrawSurface7_iface
, tag
, data
, size
);
2764 /*****************************************************************************
2765 * IDirectDrawSurface7::FreePrivateData
2767 * Frees private data stored in the surface
2770 * tag: Tag of the data to free
2773 * D3D_OK on success, error code otherwise.
2775 *****************************************************************************/
2776 static HRESULT WINAPI
ddraw_surface7_FreePrivateData(IDirectDrawSurface7
*iface
, REFGUID tag
)
2778 struct ddraw_surface
*surface
= impl_from_IDirectDrawSurface7(iface
);
2779 struct wined3d_private_data
*entry
;
2781 TRACE("iface %p, tag %s.\n", iface
, debugstr_guid(tag
));
2783 wined3d_mutex_lock();
2784 entry
= wined3d_private_store_get_private_data(&surface
->private_store
, tag
);
2787 wined3d_mutex_unlock();
2788 return DDERR_NOTFOUND
;
2791 wined3d_private_store_free_private_data(&surface
->private_store
, entry
);
2792 wined3d_mutex_unlock();
2797 static HRESULT WINAPI
ddraw_surface4_FreePrivateData(IDirectDrawSurface4
*iface
, REFGUID tag
)
2799 struct ddraw_surface
*surface
= impl_from_IDirectDrawSurface4(iface
);
2801 TRACE("iface %p, tag %s.\n", iface
, debugstr_guid(tag
));
2803 return ddraw_surface7_FreePrivateData(&surface
->IDirectDrawSurface7_iface
, tag
);
2806 /*****************************************************************************
2807 * IDirectDrawSurface7::PageLock
2809 * Prevents a sysmem surface from being paged out
2812 * Flags: Not used, must be 0(unchecked)
2815 * DD_OK, because it's a stub
2817 *****************************************************************************/
2818 static HRESULT WINAPI
ddraw_surface7_PageLock(IDirectDrawSurface7
*iface
, DWORD Flags
)
2820 TRACE("iface %p, flags %#lx.\n", iface
, Flags
);
2822 /* This is Windows memory management related - we don't need this */
2826 static HRESULT WINAPI
ddraw_surface4_PageLock(IDirectDrawSurface4
*iface
, DWORD flags
)
2828 struct ddraw_surface
*surface
= impl_from_IDirectDrawSurface4(iface
);
2830 TRACE("iface %p, flags %#lx.\n", iface
, flags
);
2832 return ddraw_surface7_PageLock(&surface
->IDirectDrawSurface7_iface
, flags
);
2835 static HRESULT WINAPI
ddraw_surface3_PageLock(IDirectDrawSurface3
*iface
, DWORD flags
)
2837 struct ddraw_surface
*surface
= impl_from_IDirectDrawSurface3(iface
);
2839 TRACE("iface %p, flags %#lx.\n", iface
, flags
);
2841 return ddraw_surface7_PageLock(&surface
->IDirectDrawSurface7_iface
, flags
);
2844 static HRESULT WINAPI
ddraw_surface2_PageLock(IDirectDrawSurface2
*iface
, DWORD flags
)
2846 struct ddraw_surface
*surface
= impl_from_IDirectDrawSurface2(iface
);
2848 TRACE("iface %p, flags %#lx.\n", iface
, flags
);
2850 return ddraw_surface7_PageLock(&surface
->IDirectDrawSurface7_iface
, flags
);
2853 /*****************************************************************************
2854 * IDirectDrawSurface7::PageUnlock
2856 * Allows a sysmem surface to be paged out
2859 * Flags: Not used, must be 0(unchecked)
2862 * DD_OK, because it's a stub
2864 *****************************************************************************/
2865 static HRESULT WINAPI
ddraw_surface7_PageUnlock(IDirectDrawSurface7
*iface
, DWORD Flags
)
2867 TRACE("iface %p, flags %#lx.\n", iface
, Flags
);
2872 static HRESULT WINAPI
ddraw_surface4_PageUnlock(IDirectDrawSurface4
*iface
, DWORD flags
)
2874 struct ddraw_surface
*surface
= impl_from_IDirectDrawSurface4(iface
);
2876 TRACE("iface %p, flags %#lx.\n", iface
, flags
);
2878 return ddraw_surface7_PageUnlock(&surface
->IDirectDrawSurface7_iface
, flags
);
2881 static HRESULT WINAPI
ddraw_surface3_PageUnlock(IDirectDrawSurface3
*iface
, DWORD flags
)
2883 struct ddraw_surface
*surface
= impl_from_IDirectDrawSurface3(iface
);
2885 TRACE("iface %p, flags %#lx.\n", iface
, flags
);
2887 return ddraw_surface7_PageUnlock(&surface
->IDirectDrawSurface7_iface
, flags
);
2890 static HRESULT WINAPI
ddraw_surface2_PageUnlock(IDirectDrawSurface2
*iface
, DWORD flags
)
2892 struct ddraw_surface
*surface
= impl_from_IDirectDrawSurface2(iface
);
2894 TRACE("iface %p, flags %#lx.\n", iface
, flags
);
2896 return ddraw_surface7_PageUnlock(&surface
->IDirectDrawSurface7_iface
, flags
);
2899 /*****************************************************************************
2900 * IDirectDrawSurface7::BltBatch
2902 * An unimplemented function
2910 *****************************************************************************/
2911 static HRESULT WINAPI DECLSPEC_HOTPATCH
ddraw_surface7_BltBatch(IDirectDrawSurface7
*iface
, DDBLTBATCH
*Batch
, DWORD Count
, DWORD Flags
)
2913 TRACE("iface %p, batch %p, count %lu, flags %#lx.\n", iface
, Batch
, Count
, Flags
);
2915 /* MSDN: "not currently implemented" */
2916 return DDERR_UNSUPPORTED
;
2919 static HRESULT WINAPI DECLSPEC_HOTPATCH
ddraw_surface4_BltBatch(IDirectDrawSurface4
*iface
, DDBLTBATCH
*batch
, DWORD count
, DWORD flags
)
2921 struct ddraw_surface
*surface
= impl_from_IDirectDrawSurface4(iface
);
2923 TRACE("iface %p, batch %p, count %lu, flags %#lx.\n", iface
, batch
, count
, flags
);
2925 return ddraw_surface7_BltBatch(&surface
->IDirectDrawSurface7_iface
, batch
, count
, flags
);
2928 static HRESULT WINAPI DECLSPEC_HOTPATCH
ddraw_surface3_BltBatch(IDirectDrawSurface3
*iface
, DDBLTBATCH
*batch
, DWORD count
, DWORD flags
)
2930 struct ddraw_surface
*surface
= impl_from_IDirectDrawSurface3(iface
);
2932 TRACE("iface %p, batch %p, count %lu, flags %#lx.\n", iface
, batch
, count
, flags
);
2934 return ddraw_surface7_BltBatch(&surface
->IDirectDrawSurface7_iface
, batch
, count
, flags
);
2937 static HRESULT WINAPI DECLSPEC_HOTPATCH
ddraw_surface2_BltBatch(IDirectDrawSurface2
*iface
, DDBLTBATCH
*batch
, DWORD count
, DWORD flags
)
2939 struct ddraw_surface
*surface
= impl_from_IDirectDrawSurface2(iface
);
2941 TRACE("iface %p, batch %p, count %lu, flags %#lx.\n", iface
, batch
, count
, flags
);
2943 return ddraw_surface7_BltBatch(&surface
->IDirectDrawSurface7_iface
, batch
, count
, flags
);
2946 static HRESULT WINAPI DECLSPEC_HOTPATCH
ddraw_surface1_BltBatch(IDirectDrawSurface
*iface
, DDBLTBATCH
*batch
, DWORD count
, DWORD flags
)
2948 struct ddraw_surface
*surface
= impl_from_IDirectDrawSurface(iface
);
2950 TRACE("iface %p, batch %p, count %lu, flags %#lx.\n", iface
, batch
, count
, flags
);
2952 return ddraw_surface7_BltBatch(&surface
->IDirectDrawSurface7_iface
, batch
, count
, flags
);
2955 /*****************************************************************************
2956 * IDirectDrawSurface7::EnumAttachedSurfaces
2958 * Enumerates all surfaces attached to this surface
2961 * context: Pointer to pass unmodified to the callback
2962 * cb: Callback function to call for each surface
2966 * DDERR_INVALIDPARAMS if cb is NULL
2968 *****************************************************************************/
2969 static HRESULT WINAPI
ddraw_surface7_EnumAttachedSurfaces(IDirectDrawSurface7
*iface
,
2970 void *context
, LPDDENUMSURFACESCALLBACK7 cb
)
2972 struct ddraw_surface
*surface
= impl_from_IDirectDrawSurface7(iface
);
2973 struct ddraw_surface
*surf
;
2974 DDSURFACEDESC2 desc
;
2977 /* Attached surfaces aren't handled in WineD3D */
2978 TRACE("iface %p, context %p, callback %p.\n", iface
, context
, cb
);
2981 return DDERR_INVALIDPARAMS
;
2983 wined3d_mutex_lock();
2985 for(i
= 0; i
< MAX_COMPLEX_ATTACHED
; i
++)
2987 surf
= surface
->complex_array
[i
];
2990 ddraw_surface7_AddRef(&surf
->IDirectDrawSurface7_iface
);
2991 desc
= surf
->surface_desc
;
2992 /* check: != DDENUMRET_OK or == DDENUMRET_CANCEL? */
2993 if (cb(&surf
->IDirectDrawSurface7_iface
, &desc
, context
) == DDENUMRET_CANCEL
)
2995 wined3d_mutex_unlock();
3000 for (surf
= surface
->next_attached
; surf
!= NULL
; surf
= surf
->next_attached
)
3002 ddraw_surface7_AddRef(&surf
->IDirectDrawSurface7_iface
);
3003 desc
= surf
->surface_desc
;
3004 /* check: != DDENUMRET_OK or == DDENUMRET_CANCEL? */
3005 if (cb(&surf
->IDirectDrawSurface7_iface
, &desc
, context
) == DDENUMRET_CANCEL
)
3007 wined3d_mutex_unlock();
3012 TRACE(" end of enumeration.\n");
3014 wined3d_mutex_unlock();
3019 struct callback_info2
3021 LPDDENUMSURFACESCALLBACK2 callback
;
3025 struct callback_info
3027 LPDDENUMSURFACESCALLBACK callback
;
3031 static HRESULT CALLBACK
EnumCallback2(IDirectDrawSurface7
*surface
, DDSURFACEDESC2
*surface_desc
, void *context
)
3033 struct ddraw_surface
*surface_impl
= impl_from_IDirectDrawSurface7(surface
);
3034 const struct callback_info2
*info
= context
;
3036 ddraw_surface4_AddRef(&surface_impl
->IDirectDrawSurface4_iface
);
3037 ddraw_surface7_Release(surface
);
3039 return info
->callback(&surface_impl
->IDirectDrawSurface4_iface
, surface_desc
, info
->context
);
3042 static HRESULT CALLBACK
EnumCallback(IDirectDrawSurface7
*surface
, DDSURFACEDESC2
*surface_desc
, void *context
)
3044 struct ddraw_surface
*surface_impl
= impl_from_IDirectDrawSurface7(surface
);
3045 const struct callback_info
*info
= context
;
3047 ddraw_surface1_AddRef(&surface_impl
->IDirectDrawSurface_iface
);
3048 ddraw_surface7_Release(surface
);
3050 /* FIXME: Check surface_test.dwSize */
3051 return info
->callback(&surface_impl
->IDirectDrawSurface_iface
,
3052 (DDSURFACEDESC
*)surface_desc
, info
->context
);
3055 static HRESULT WINAPI
ddraw_surface4_EnumAttachedSurfaces(IDirectDrawSurface4
*iface
,
3056 void *context
, LPDDENUMSURFACESCALLBACK2 callback
)
3058 struct ddraw_surface
*surface
= impl_from_IDirectDrawSurface4(iface
);
3059 struct callback_info2 info
;
3061 TRACE("iface %p, context %p, callback %p.\n", iface
, context
, callback
);
3063 info
.callback
= callback
;
3064 info
.context
= context
;
3066 return ddraw_surface7_EnumAttachedSurfaces(&surface
->IDirectDrawSurface7_iface
,
3067 &info
, EnumCallback2
);
3070 static HRESULT WINAPI
ddraw_surface3_EnumAttachedSurfaces(IDirectDrawSurface3
*iface
,
3071 void *context
, LPDDENUMSURFACESCALLBACK callback
)
3073 struct ddraw_surface
*surface
= impl_from_IDirectDrawSurface3(iface
);
3074 struct callback_info info
;
3076 TRACE("iface %p, context %p, callback %p.\n", iface
, context
, callback
);
3078 info
.callback
= callback
;
3079 info
.context
= context
;
3081 return ddraw_surface7_EnumAttachedSurfaces(&surface
->IDirectDrawSurface7_iface
,
3082 &info
, EnumCallback
);
3085 static HRESULT WINAPI
ddraw_surface2_EnumAttachedSurfaces(IDirectDrawSurface2
*iface
,
3086 void *context
, LPDDENUMSURFACESCALLBACK callback
)
3088 struct ddraw_surface
*surface
= impl_from_IDirectDrawSurface2(iface
);
3089 struct callback_info info
;
3091 TRACE("iface %p, context %p, callback %p.\n", iface
, context
, callback
);
3093 info
.callback
= callback
;
3094 info
.context
= context
;
3096 return ddraw_surface7_EnumAttachedSurfaces(&surface
->IDirectDrawSurface7_iface
,
3097 &info
, EnumCallback
);
3100 static HRESULT WINAPI
ddraw_surface1_EnumAttachedSurfaces(IDirectDrawSurface
*iface
,
3101 void *context
, LPDDENUMSURFACESCALLBACK callback
)
3103 struct ddraw_surface
*surface
= impl_from_IDirectDrawSurface(iface
);
3104 struct callback_info info
;
3106 TRACE("iface %p, context %p, callback %p.\n", iface
, context
, callback
);
3108 info
.callback
= callback
;
3109 info
.context
= context
;
3111 return ddraw_surface7_EnumAttachedSurfaces(&surface
->IDirectDrawSurface7_iface
,
3112 &info
, EnumCallback
);
3115 /*****************************************************************************
3116 * IDirectDrawSurface7::EnumOverlayZOrders
3118 * "Enumerates the overlay surfaces on the specified destination"
3121 * Flags: DDENUMOVERLAYZ_BACKTOFRONT or DDENUMOVERLAYZ_FRONTTOBACK
3122 * context: context to pass back to the callback
3123 * cb: callback function to call for each enumerated surface
3126 * DD_OK, because it's a stub
3128 *****************************************************************************/
3129 static HRESULT WINAPI
ddraw_surface7_EnumOverlayZOrders(IDirectDrawSurface7
*iface
,
3130 DWORD Flags
, void *context
, LPDDENUMSURFACESCALLBACK7 cb
)
3132 FIXME("iface %p, flags %#lx, context %p, callback %p stub!\n", iface
, Flags
, context
, cb
);
3137 static HRESULT WINAPI
ddraw_surface4_EnumOverlayZOrders(IDirectDrawSurface4
*iface
,
3138 DWORD flags
, void *context
, LPDDENUMSURFACESCALLBACK2 callback
)
3140 struct ddraw_surface
*surface
= impl_from_IDirectDrawSurface4(iface
);
3141 struct callback_info2 info
;
3143 TRACE("iface %p, flags %#lx, context %p, callback %p.\n", iface
, flags
, context
, callback
);
3145 info
.callback
= callback
;
3146 info
.context
= context
;
3148 return ddraw_surface7_EnumOverlayZOrders(&surface
->IDirectDrawSurface7_iface
,
3149 flags
, &info
, EnumCallback2
);
3152 static HRESULT WINAPI
ddraw_surface3_EnumOverlayZOrders(IDirectDrawSurface3
*iface
,
3153 DWORD flags
, void *context
, LPDDENUMSURFACESCALLBACK callback
)
3155 struct ddraw_surface
*surface
= impl_from_IDirectDrawSurface3(iface
);
3156 struct callback_info info
;
3158 TRACE("iface %p, flags %#lx, context %p, callback %p.\n", iface
, flags
, context
, callback
);
3160 info
.callback
= callback
;
3161 info
.context
= context
;
3163 return ddraw_surface7_EnumOverlayZOrders(&surface
->IDirectDrawSurface7_iface
,
3164 flags
, &info
, EnumCallback
);
3167 static HRESULT WINAPI
ddraw_surface2_EnumOverlayZOrders(IDirectDrawSurface2
*iface
,
3168 DWORD flags
, void *context
, LPDDENUMSURFACESCALLBACK callback
)
3170 struct ddraw_surface
*surface
= impl_from_IDirectDrawSurface2(iface
);
3171 struct callback_info info
;
3173 TRACE("iface %p, flags %#lx, context %p, callback %p.\n", iface
, flags
, context
, callback
);
3175 info
.callback
= callback
;
3176 info
.context
= context
;
3178 return ddraw_surface7_EnumOverlayZOrders(&surface
->IDirectDrawSurface7_iface
,
3179 flags
, &info
, EnumCallback
);
3182 static HRESULT WINAPI
ddraw_surface1_EnumOverlayZOrders(IDirectDrawSurface
*iface
,
3183 DWORD flags
, void *context
, LPDDENUMSURFACESCALLBACK callback
)
3185 struct ddraw_surface
*surface
= impl_from_IDirectDrawSurface(iface
);
3186 struct callback_info info
;
3188 TRACE("iface %p, flags %#lx, context %p, callback %p.\n", iface
, flags
, context
, callback
);
3190 info
.callback
= callback
;
3191 info
.context
= context
;
3193 return ddraw_surface7_EnumOverlayZOrders(&surface
->IDirectDrawSurface7_iface
,
3194 flags
, &info
, EnumCallback
);
3197 /*****************************************************************************
3198 * IDirectDrawSurface7::GetBltStatus
3200 * Returns the blitting status
3203 * Flags: DDGBS_CANBLT or DDGBS_ISBLTDONE
3205 *****************************************************************************/
3206 static HRESULT WINAPI
ddraw_surface7_GetBltStatus(IDirectDrawSurface7
*iface
, DWORD Flags
)
3208 TRACE("iface %p, flags %#lx.\n", iface
, Flags
);
3212 case WINEDDGBS_CANBLT
:
3213 case WINEDDGBS_ISBLTDONE
:
3217 return DDERR_INVALIDPARAMS
;
3221 static HRESULT WINAPI
ddraw_surface4_GetBltStatus(IDirectDrawSurface4
*iface
, DWORD flags
)
3223 struct ddraw_surface
*surface
= impl_from_IDirectDrawSurface4(iface
);
3225 TRACE("iface %p, flags %#lx.\n", iface
, flags
);
3227 return ddraw_surface7_GetBltStatus(&surface
->IDirectDrawSurface7_iface
, flags
);
3230 static HRESULT WINAPI
ddraw_surface3_GetBltStatus(IDirectDrawSurface3
*iface
, DWORD flags
)
3232 struct ddraw_surface
*surface
= impl_from_IDirectDrawSurface3(iface
);
3234 TRACE("iface %p, flags %#lx.\n", iface
, flags
);
3236 return ddraw_surface7_GetBltStatus(&surface
->IDirectDrawSurface7_iface
, flags
);
3239 static HRESULT WINAPI
ddraw_surface2_GetBltStatus(IDirectDrawSurface2
*iface
, DWORD flags
)
3241 struct ddraw_surface
*surface
= impl_from_IDirectDrawSurface2(iface
);
3243 TRACE("iface %p, flags %#lx.\n", iface
, flags
);
3245 return ddraw_surface7_GetBltStatus(&surface
->IDirectDrawSurface7_iface
, flags
);
3248 static HRESULT WINAPI
ddraw_surface1_GetBltStatus(IDirectDrawSurface
*iface
, DWORD flags
)
3250 struct ddraw_surface
*surface
= impl_from_IDirectDrawSurface(iface
);
3252 TRACE("iface %p, flags %#lx.\n", iface
, flags
);
3254 return ddraw_surface7_GetBltStatus(&surface
->IDirectDrawSurface7_iface
, flags
);
3257 /*****************************************************************************
3258 * IDirectDrawSurface7::GetColorKey
3260 * Returns the color key assigned to the surface
3264 * CKey: Address to store the key to
3268 * DDERR_INVALIDPARAMS if CKey is NULL
3270 *****************************************************************************/
3271 static HRESULT WINAPI
ddraw_surface7_GetColorKey(IDirectDrawSurface7
*iface
, DWORD Flags
, DDCOLORKEY
*CKey
)
3273 struct ddraw_surface
*This
= impl_from_IDirectDrawSurface7(iface
);
3275 TRACE("iface %p, flags %#lx, color_key %p.\n", iface
, Flags
, CKey
);
3278 return DDERR_INVALIDPARAMS
;
3280 wined3d_mutex_lock();
3284 case DDCKEY_DESTBLT
:
3285 if (!(This
->surface_desc
.dwFlags
& DDSD_CKDESTBLT
))
3287 wined3d_mutex_unlock();
3288 return DDERR_NOCOLORKEY
;
3290 *CKey
= This
->surface_desc
.ddckCKDestBlt
;
3293 case DDCKEY_DESTOVERLAY
:
3294 if (!(This
->surface_desc
.dwFlags
& DDSD_CKDESTOVERLAY
))
3296 wined3d_mutex_unlock();
3297 return DDERR_NOCOLORKEY
;
3299 *CKey
= This
->surface_desc
.u3
.ddckCKDestOverlay
;
3303 if (!(This
->surface_desc
.dwFlags
& DDSD_CKSRCBLT
))
3305 wined3d_mutex_unlock();
3306 return DDERR_NOCOLORKEY
;
3308 *CKey
= This
->surface_desc
.ddckCKSrcBlt
;
3311 case DDCKEY_SRCOVERLAY
:
3312 if (!(This
->surface_desc
.dwFlags
& DDSD_CKSRCOVERLAY
))
3314 wined3d_mutex_unlock();
3315 return DDERR_NOCOLORKEY
;
3317 *CKey
= This
->surface_desc
.ddckCKSrcOverlay
;
3321 wined3d_mutex_unlock();
3322 return DDERR_INVALIDPARAMS
;
3325 wined3d_mutex_unlock();
3330 static HRESULT WINAPI
ddraw_surface4_GetColorKey(IDirectDrawSurface4
*iface
, DWORD flags
, DDCOLORKEY
*color_key
)
3332 struct ddraw_surface
*surface
= impl_from_IDirectDrawSurface4(iface
);
3334 TRACE("iface %p, flags %#lx, color_key %p.\n", iface
, flags
, color_key
);
3336 return ddraw_surface7_GetColorKey(&surface
->IDirectDrawSurface7_iface
, flags
, color_key
);
3339 static HRESULT WINAPI
ddraw_surface3_GetColorKey(IDirectDrawSurface3
*iface
, DWORD flags
, DDCOLORKEY
*color_key
)
3341 struct ddraw_surface
*surface
= impl_from_IDirectDrawSurface3(iface
);
3343 TRACE("iface %p, flags %#lx, color_key %p.\n", iface
, flags
, color_key
);
3345 return ddraw_surface7_GetColorKey(&surface
->IDirectDrawSurface7_iface
, flags
, color_key
);
3348 static HRESULT WINAPI
ddraw_surface2_GetColorKey(IDirectDrawSurface2
*iface
, DWORD flags
, DDCOLORKEY
*color_key
)
3350 struct ddraw_surface
*surface
= impl_from_IDirectDrawSurface2(iface
);
3352 TRACE("iface %p, flags %#lx, color_key %p.\n", iface
, flags
, color_key
);
3354 return ddraw_surface7_GetColorKey(&surface
->IDirectDrawSurface7_iface
, flags
, color_key
);
3357 static HRESULT WINAPI
ddraw_surface1_GetColorKey(IDirectDrawSurface
*iface
, DWORD flags
, DDCOLORKEY
*color_key
)
3359 struct ddraw_surface
*surface
= impl_from_IDirectDrawSurface(iface
);
3361 TRACE("iface %p, flags %#lx, color_key %p.\n", iface
, flags
, color_key
);
3363 return ddraw_surface7_GetColorKey(&surface
->IDirectDrawSurface7_iface
, flags
, color_key
);
3366 /*****************************************************************************
3367 * IDirectDrawSurface7::GetFlipStatus
3369 * Returns the flipping status of the surface
3372 * Flags: DDGFS_CANFLIP of DDGFS_ISFLIPDONE
3374 *****************************************************************************/
3375 static HRESULT WINAPI
ddraw_surface7_GetFlipStatus(IDirectDrawSurface7
*iface
, DWORD Flags
)
3377 TRACE("iface %p, flags %#lx.\n", iface
, Flags
);
3379 /* XXX: DDERR_INVALIDSURFACETYPE */
3383 case WINEDDGFS_CANFLIP
:
3384 case WINEDDGFS_ISFLIPDONE
:
3388 return DDERR_INVALIDPARAMS
;
3392 static HRESULT WINAPI
ddraw_surface4_GetFlipStatus(IDirectDrawSurface4
*iface
, DWORD flags
)
3394 struct ddraw_surface
*surface
= impl_from_IDirectDrawSurface4(iface
);
3396 TRACE("iface %p, flags %#lx.\n", iface
, flags
);
3398 return ddraw_surface7_GetFlipStatus(&surface
->IDirectDrawSurface7_iface
, flags
);
3401 static HRESULT WINAPI
ddraw_surface3_GetFlipStatus(IDirectDrawSurface3
*iface
, DWORD flags
)
3403 struct ddraw_surface
*surface
= impl_from_IDirectDrawSurface3(iface
);
3405 TRACE("iface %p, flags %#lx.\n", iface
, flags
);
3407 return ddraw_surface7_GetFlipStatus(&surface
->IDirectDrawSurface7_iface
, flags
);
3410 static HRESULT WINAPI
ddraw_surface2_GetFlipStatus(IDirectDrawSurface2
*iface
, DWORD flags
)
3412 struct ddraw_surface
*surface
= impl_from_IDirectDrawSurface2(iface
);
3414 TRACE("iface %p, flags %#lx.\n", iface
, flags
);
3416 return ddraw_surface7_GetFlipStatus(&surface
->IDirectDrawSurface7_iface
, flags
);
3419 static HRESULT WINAPI
ddraw_surface1_GetFlipStatus(IDirectDrawSurface
*iface
, DWORD flags
)
3421 struct ddraw_surface
*surface
= impl_from_IDirectDrawSurface(iface
);
3423 TRACE("iface %p, flags %#lx.\n", iface
, flags
);
3425 return ddraw_surface7_GetFlipStatus(&surface
->IDirectDrawSurface7_iface
, flags
);
3428 /*****************************************************************************
3429 * IDirectDrawSurface7::GetOverlayPosition
3431 * Returns the display coordinates of a visible and active overlay surface
3438 * DDERR_NOTAOVERLAYSURFACE, because it's a stub
3439 *****************************************************************************/
3440 static HRESULT WINAPI
ddraw_surface7_GetOverlayPosition(IDirectDrawSurface7
*iface
, LONG
*x
, LONG
*y
)
3442 struct ddraw_surface
*surface
= impl_from_IDirectDrawSurface7(iface
);
3445 TRACE("iface %p, x %p, y %p.\n", iface
, x
, y
);
3447 wined3d_mutex_lock();
3448 hr
= wined3d_texture_get_overlay_position(surface
->wined3d_texture
,
3449 surface
->sub_resource_idx
, x
, y
);
3450 wined3d_mutex_unlock();
3455 static HRESULT WINAPI
ddraw_surface4_GetOverlayPosition(IDirectDrawSurface4
*iface
, LONG
*x
, LONG
*y
)
3457 struct ddraw_surface
*surface
= impl_from_IDirectDrawSurface4(iface
);
3459 TRACE("iface %p, x %p, y %p.\n", iface
, x
, y
);
3461 return ddraw_surface7_GetOverlayPosition(&surface
->IDirectDrawSurface7_iface
, x
, y
);
3464 static HRESULT WINAPI
ddraw_surface3_GetOverlayPosition(IDirectDrawSurface3
*iface
, LONG
*x
, LONG
*y
)
3466 struct ddraw_surface
*surface
= impl_from_IDirectDrawSurface3(iface
);
3468 TRACE("iface %p, x %p, y %p.\n", iface
, x
, y
);
3470 return ddraw_surface7_GetOverlayPosition(&surface
->IDirectDrawSurface7_iface
, x
, y
);
3473 static HRESULT WINAPI
ddraw_surface2_GetOverlayPosition(IDirectDrawSurface2
*iface
, LONG
*x
, LONG
*y
)
3475 struct ddraw_surface
*surface
= impl_from_IDirectDrawSurface2(iface
);
3477 TRACE("iface %p, x %p, y %p.\n", iface
, x
, y
);
3479 return ddraw_surface7_GetOverlayPosition(&surface
->IDirectDrawSurface7_iface
, x
, y
);
3482 static HRESULT WINAPI
ddraw_surface1_GetOverlayPosition(IDirectDrawSurface
*iface
, LONG
*x
, LONG
*y
)
3484 struct ddraw_surface
*surface
= impl_from_IDirectDrawSurface(iface
);
3486 TRACE("iface %p, x %p, y %p.\n", iface
, x
, y
);
3488 return ddraw_surface7_GetOverlayPosition(&surface
->IDirectDrawSurface7_iface
, x
, y
);
3491 /*****************************************************************************
3492 * IDirectDrawSurface7::GetPixelFormat
3494 * Returns the pixel format of the Surface
3497 * PixelFormat: Pointer to a DDPIXELFORMAT structure to which the pixel
3498 * format should be written
3502 * DDERR_INVALIDPARAMS if PixelFormat is NULL
3504 *****************************************************************************/
3505 static HRESULT WINAPI
ddraw_surface7_GetPixelFormat(IDirectDrawSurface7
*iface
, DDPIXELFORMAT
*PixelFormat
)
3507 /* What is DDERR_INVALIDSURFACETYPE for here? */
3508 struct ddraw_surface
*surface
= impl_from_IDirectDrawSurface7(iface
);
3510 TRACE("iface %p, pixel_format %p.\n", iface
, PixelFormat
);
3513 return DDERR_INVALIDPARAMS
;
3515 wined3d_mutex_lock();
3516 DD_STRUCT_COPY_BYSIZE(PixelFormat
, &surface
->surface_desc
.u4
.ddpfPixelFormat
);
3517 wined3d_mutex_unlock();
3522 static HRESULT WINAPI
ddraw_surface4_GetPixelFormat(IDirectDrawSurface4
*iface
, DDPIXELFORMAT
*pixel_format
)
3524 struct ddraw_surface
*surface
= impl_from_IDirectDrawSurface4(iface
);
3526 TRACE("iface %p, pixel_format %p.\n", iface
, pixel_format
);
3528 return ddraw_surface7_GetPixelFormat(&surface
->IDirectDrawSurface7_iface
, pixel_format
);
3531 static HRESULT WINAPI
ddraw_surface3_GetPixelFormat(IDirectDrawSurface3
*iface
, DDPIXELFORMAT
*pixel_format
)
3533 struct ddraw_surface
*surface
= impl_from_IDirectDrawSurface3(iface
);
3535 TRACE("iface %p, pixel_format %p.\n", iface
, pixel_format
);
3537 return ddraw_surface7_GetPixelFormat(&surface
->IDirectDrawSurface7_iface
, pixel_format
);
3540 static HRESULT WINAPI
ddraw_surface2_GetPixelFormat(IDirectDrawSurface2
*iface
, DDPIXELFORMAT
*pixel_format
)
3542 struct ddraw_surface
*surface
= impl_from_IDirectDrawSurface2(iface
);
3544 TRACE("iface %p, pixel_format %p.\n", iface
, pixel_format
);
3546 return ddraw_surface7_GetPixelFormat(&surface
->IDirectDrawSurface7_iface
, pixel_format
);
3549 static HRESULT WINAPI
ddraw_surface1_GetPixelFormat(IDirectDrawSurface
*iface
, DDPIXELFORMAT
*pixel_format
)
3551 struct ddraw_surface
*surface
= impl_from_IDirectDrawSurface(iface
);
3553 TRACE("iface %p, pixel_format %p.\n", iface
, pixel_format
);
3555 return ddraw_surface7_GetPixelFormat(&surface
->IDirectDrawSurface7_iface
, pixel_format
);
3558 /*****************************************************************************
3559 * IDirectDrawSurface7::GetSurfaceDesc
3561 * Returns the description of this surface
3564 * DDSD: Address of a DDSURFACEDESC2 structure that is to be filled with the
3569 * DDERR_INVALIDPARAMS if DDSD is NULL
3571 *****************************************************************************/
3572 static HRESULT WINAPI
ddraw_surface7_GetSurfaceDesc(IDirectDrawSurface7
*iface
, DDSURFACEDESC2
*surface_desc
)
3574 struct ddraw_surface
*surface
= impl_from_IDirectDrawSurface7(iface
);
3576 TRACE("iface %p, surface_desc %p.\n", iface
, surface_desc
);
3578 if (!surface_desc
) return DDERR_INVALIDPARAMS
;
3580 if (surface_desc
->dwSize
!= sizeof(DDSURFACEDESC2
))
3582 WARN("Incorrect struct size %lu.\n", surface_desc
->dwSize
);
3583 return DDERR_INVALIDPARAMS
;
3586 wined3d_mutex_lock();
3587 DD_STRUCT_COPY_BYSIZE(surface_desc
, &surface
->surface_desc
);
3588 TRACE("Returning surface desc:\n");
3589 if (TRACE_ON(ddraw
)) DDRAW_dump_surface_desc(surface_desc
);
3590 wined3d_mutex_unlock();
3595 static HRESULT WINAPI
ddraw_surface4_GetSurfaceDesc(IDirectDrawSurface4
*iface
, DDSURFACEDESC2
*DDSD
)
3597 struct ddraw_surface
*surface
= impl_from_IDirectDrawSurface4(iface
);
3599 TRACE("iface %p, surface_desc %p.\n", iface
, DDSD
);
3601 return ddraw_surface7_GetSurfaceDesc(&surface
->IDirectDrawSurface7_iface
, DDSD
);
3604 static HRESULT WINAPI
ddraw_surface3_GetSurfaceDesc(IDirectDrawSurface3
*iface
, DDSURFACEDESC
*surface_desc
)
3606 struct ddraw_surface
*surface
= impl_from_IDirectDrawSurface3(iface
);
3608 TRACE("iface %p, surface_desc %p.\n", iface
, surface_desc
);
3610 if (!surface_desc
) return DDERR_INVALIDPARAMS
;
3612 if (surface_desc
->dwSize
!= sizeof(DDSURFACEDESC
))
3614 WARN("Incorrect structure size %lu.\n", surface_desc
->dwSize
);
3615 return DDERR_INVALIDPARAMS
;
3618 wined3d_mutex_lock();
3619 DDSD2_to_DDSD(&surface
->surface_desc
, surface_desc
);
3620 TRACE("Returning surface desc:\n");
3621 if (TRACE_ON(ddraw
))
3623 /* DDRAW_dump_surface_desc handles the smaller size */
3624 DDRAW_dump_surface_desc((DDSURFACEDESC2
*)surface_desc
);
3626 wined3d_mutex_unlock();
3631 static HRESULT WINAPI
ddraw_surface2_GetSurfaceDesc(IDirectDrawSurface2
*iface
, DDSURFACEDESC
*DDSD
)
3633 struct ddraw_surface
*surface
= impl_from_IDirectDrawSurface2(iface
);
3635 TRACE("iface %p, surface_desc %p.\n", iface
, DDSD
);
3637 return ddraw_surface3_GetSurfaceDesc(&surface
->IDirectDrawSurface3_iface
, DDSD
);
3640 static HRESULT WINAPI
ddraw_surface1_GetSurfaceDesc(IDirectDrawSurface
*iface
, DDSURFACEDESC
*DDSD
)
3642 struct ddraw_surface
*surface
= impl_from_IDirectDrawSurface(iface
);
3644 TRACE("iface %p, surface_desc %p.\n", iface
, DDSD
);
3646 return ddraw_surface3_GetSurfaceDesc(&surface
->IDirectDrawSurface3_iface
, DDSD
);
3649 /*****************************************************************************
3650 * IDirectDrawSurface7::Initialize
3652 * Initializes the surface. This is a no-op in Wine
3655 * DD: Pointer to an DirectDraw interface
3656 * DDSD: Surface description for initialization
3659 * DDERR_ALREADYINITIALIZED
3661 *****************************************************************************/
3662 static HRESULT WINAPI
ddraw_surface7_Initialize(IDirectDrawSurface7
*iface
,
3663 IDirectDraw
*ddraw
, DDSURFACEDESC2
*surface_desc
)
3665 TRACE("iface %p, ddraw %p, surface_desc %p.\n", iface
, ddraw
, surface_desc
);
3667 return DDERR_ALREADYINITIALIZED
;
3670 static HRESULT WINAPI
ddraw_surface4_Initialize(IDirectDrawSurface4
*iface
,
3671 IDirectDraw
*ddraw
, DDSURFACEDESC2
*surface_desc
)
3673 struct ddraw_surface
*surface
= impl_from_IDirectDrawSurface4(iface
);
3675 TRACE("iface %p, ddraw %p, surface_desc %p.\n", iface
, ddraw
, surface_desc
);
3677 return ddraw_surface7_Initialize(&surface
->IDirectDrawSurface7_iface
,
3678 ddraw
, surface_desc
);
3681 static HRESULT WINAPI
ddraw_surface3_Initialize(IDirectDrawSurface3
*iface
,
3682 IDirectDraw
*ddraw
, DDSURFACEDESC
*surface_desc
)
3684 struct ddraw_surface
*surface
= impl_from_IDirectDrawSurface3(iface
);
3685 DDSURFACEDESC2 surface_desc2
;
3687 TRACE("iface %p, ddraw %p, surface_desc %p.\n", iface
, ddraw
, surface_desc
);
3689 if (surface_desc
) DDSD_to_DDSD2(surface_desc
, &surface_desc2
);
3690 return ddraw_surface7_Initialize(&surface
->IDirectDrawSurface7_iface
,
3691 ddraw
, surface_desc
? &surface_desc2
: NULL
);
3694 static HRESULT WINAPI
ddraw_surface2_Initialize(IDirectDrawSurface2
*iface
,
3695 IDirectDraw
*ddraw
, DDSURFACEDESC
*surface_desc
)
3697 struct ddraw_surface
*surface
= impl_from_IDirectDrawSurface2(iface
);
3698 DDSURFACEDESC2 surface_desc2
;
3700 TRACE("iface %p, ddraw %p, surface_desc %p.\n", iface
, ddraw
, surface_desc
);
3702 if (surface_desc
) DDSD_to_DDSD2(surface_desc
, &surface_desc2
);
3703 return ddraw_surface7_Initialize(&surface
->IDirectDrawSurface7_iface
,
3704 ddraw
, surface_desc
? &surface_desc2
: NULL
);
3707 static HRESULT WINAPI
ddraw_surface1_Initialize(IDirectDrawSurface
*iface
,
3708 IDirectDraw
*ddraw
, DDSURFACEDESC
*surface_desc
)
3710 struct ddraw_surface
*surface
= impl_from_IDirectDrawSurface(iface
);
3711 DDSURFACEDESC2 surface_desc2
;
3713 TRACE("iface %p, ddraw %p, surface_desc %p.\n", iface
, ddraw
, surface_desc
);
3715 if (surface_desc
) DDSD_to_DDSD2(surface_desc
, &surface_desc2
);
3716 return ddraw_surface7_Initialize(&surface
->IDirectDrawSurface7_iface
,
3717 ddraw
, surface_desc
? &surface_desc2
: NULL
);
3720 /*****************************************************************************
3721 * IDirect3DTexture1::Initialize
3723 * The sdk says it's not implemented
3731 *****************************************************************************/
3732 static HRESULT WINAPI
d3d_texture1_Initialize(IDirect3DTexture
*iface
,
3733 IDirect3DDevice
*device
, IDirectDrawSurface
*surface
)
3735 TRACE("iface %p, device %p, surface %p.\n", iface
, device
, surface
);
3737 return DDERR_UNSUPPORTED
; /* Unchecked */
3740 /*****************************************************************************
3741 * IDirectDrawSurface7::IsLost
3743 * Checks if the surface is lost
3746 * DD_OK, if the surface is usable
3747 * DDERR_ISLOST if the surface is lost
3749 *****************************************************************************/
3750 static HRESULT WINAPI
ddraw_surface7_IsLost(IDirectDrawSurface7
*iface
)
3752 struct ddraw_surface
*surface
= impl_from_IDirectDrawSurface7(iface
);
3754 TRACE("iface %p.\n", iface
);
3756 return ddraw_surface_is_lost(surface
) ? DDERR_SURFACELOST
: DD_OK
;
3759 static HRESULT WINAPI
ddraw_surface4_IsLost(IDirectDrawSurface4
*iface
)
3761 struct ddraw_surface
*surface
= impl_from_IDirectDrawSurface4(iface
);
3763 TRACE("iface %p.\n", iface
);
3765 return ddraw_surface_is_lost(surface
) ? DDERR_SURFACELOST
: DD_OK
;
3768 static HRESULT WINAPI
ddraw_surface3_IsLost(IDirectDrawSurface3
*iface
)
3770 struct ddraw_surface
*surface
= impl_from_IDirectDrawSurface3(iface
);
3772 TRACE("iface %p.\n", iface
);
3774 return ddraw_surface_is_lost(surface
) ? DDERR_SURFACELOST
: DD_OK
;
3777 static HRESULT WINAPI
ddraw_surface2_IsLost(IDirectDrawSurface2
*iface
)
3779 struct ddraw_surface
*surface
= impl_from_IDirectDrawSurface2(iface
);
3781 TRACE("iface %p.\n", iface
);
3783 return ddraw_surface_is_lost(surface
) ? DDERR_SURFACELOST
: DD_OK
;
3786 static HRESULT WINAPI
ddraw_surface1_IsLost(IDirectDrawSurface
*iface
)
3788 struct ddraw_surface
*surface
= impl_from_IDirectDrawSurface(iface
);
3790 TRACE("iface %p.\n", iface
);
3792 return ddraw_surface_is_lost(surface
) ? DDERR_SURFACELOST
: DD_OK
;
3795 /*****************************************************************************
3796 * IDirectDrawSurface7::Restore
3798 * Restores a lost surface. This makes the surface usable again, but
3799 * doesn't reload its old contents
3802 * DD_OK on success, error code otherwise.
3804 *****************************************************************************/
3805 static HRESULT WINAPI
ddraw_surface7_Restore(IDirectDrawSurface7
*iface
)
3807 struct ddraw_surface
*surface
= impl_from_IDirectDrawSurface7(iface
);
3808 struct ddraw_surface
*attachment
;
3811 TRACE("iface %p.\n", iface
);
3813 if (surface
->surface_desc
.ddsCaps
.dwCaps
& DDSCAPS_PRIMARYSURFACE
)
3815 struct wined3d_swapchain
*swapchain
= surface
->ddraw
->wined3d_swapchain
;
3816 struct wined3d_sub_resource_desc wined3d_desc
;
3817 struct wined3d_display_mode mode
;
3820 if (FAILED(hr
= wined3d_swapchain_get_display_mode(swapchain
, &mode
, NULL
)))
3822 WARN("Failed to get display mode, hr %#lx.\n", hr
);
3826 if (FAILED(hr
= wined3d_texture_get_sub_resource_desc(surface
->wined3d_texture
, 0, &wined3d_desc
)))
3828 WARN("Failed to get resource desc, hr %#lx.\n", hr
);
3832 if (mode
.width
!= wined3d_desc
.width
|| mode
.height
!= wined3d_desc
.height
)
3834 WARN("Display mode dimensions %ux%u don't match surface dimensions %ux%u.\n",
3835 mode
.width
, mode
.height
, wined3d_desc
.width
, wined3d_desc
.height
);
3836 return DDERR_WRONGMODE
;
3839 if (mode
.format_id
!= wined3d_desc
.format
)
3841 WARN("Display mode format %#x doesn't match surface format %#x.\n",
3842 mode
.format_id
, wined3d_desc
.format
);
3843 return DDERR_WRONGMODE
;
3847 if (!ddraw_surface_can_be_lost(surface
))
3849 ddraw_update_lost_surfaces(surface
->ddraw
);
3850 if (surface
->ddraw
->device_state
== DDRAW_DEVICE_STATE_LOST
)
3851 return DDERR_WRONGMODE
;
3853 surface
->is_lost
= FALSE
;
3855 for(i
= 0; i
< MAX_COMPLEX_ATTACHED
; i
++)
3857 attachment
= surface
->complex_array
[i
];
3860 attachment
->is_lost
= FALSE
;
3861 attachment
= attachment
->complex_array
[0];
3862 if (attachment
== surface
->complex_array
[i
])
3870 static HRESULT WINAPI
ddraw_surface4_Restore(IDirectDrawSurface4
*iface
)
3872 struct ddraw_surface
*surface
= impl_from_IDirectDrawSurface4(iface
);
3874 TRACE("iface %p.\n", iface
);
3876 return ddraw_surface7_Restore(&surface
->IDirectDrawSurface7_iface
);
3879 static HRESULT WINAPI
ddraw_surface3_Restore(IDirectDrawSurface3
*iface
)
3881 struct ddraw_surface
*surface
= impl_from_IDirectDrawSurface3(iface
);
3883 TRACE("iface %p.\n", iface
);
3885 return ddraw_surface7_Restore(&surface
->IDirectDrawSurface7_iface
);
3888 static HRESULT WINAPI
ddraw_surface2_Restore(IDirectDrawSurface2
*iface
)
3890 struct ddraw_surface
*surface
= impl_from_IDirectDrawSurface2(iface
);
3892 TRACE("iface %p.\n", iface
);
3894 return ddraw_surface7_Restore(&surface
->IDirectDrawSurface7_iface
);
3897 static HRESULT WINAPI
ddraw_surface1_Restore(IDirectDrawSurface
*iface
)
3899 struct ddraw_surface
*surface
= impl_from_IDirectDrawSurface(iface
);
3901 TRACE("iface %p.\n", iface
);
3903 return ddraw_surface7_Restore(&surface
->IDirectDrawSurface7_iface
);
3906 /*****************************************************************************
3907 * IDirectDrawSurface7::SetOverlayPosition
3909 * Changes the display coordinates of an overlay surface
3916 * DDERR_NOTAOVERLAYSURFACE, because we don't support overlays right now
3917 *****************************************************************************/
3918 static HRESULT WINAPI
ddraw_surface7_SetOverlayPosition(IDirectDrawSurface7
*iface
, LONG x
, LONG y
)
3920 struct ddraw_surface
*surface
= impl_from_IDirectDrawSurface7(iface
);
3923 TRACE("iface %p, x %ld, y %ld.\n", iface
, x
, y
);
3925 wined3d_mutex_lock();
3926 hr
= wined3d_texture_set_overlay_position(surface
->wined3d_texture
,
3927 surface
->sub_resource_idx
, x
, y
);
3928 wined3d_mutex_unlock();
3933 static HRESULT WINAPI
ddraw_surface4_SetOverlayPosition(IDirectDrawSurface4
*iface
, LONG x
, LONG y
)
3935 struct ddraw_surface
*surface
= impl_from_IDirectDrawSurface4(iface
);
3937 TRACE("iface %p, x %ld, y %ld.\n", iface
, x
, y
);
3939 return ddraw_surface7_SetOverlayPosition(&surface
->IDirectDrawSurface7_iface
, x
, y
);
3942 static HRESULT WINAPI
ddraw_surface3_SetOverlayPosition(IDirectDrawSurface3
*iface
, LONG x
, LONG y
)
3944 struct ddraw_surface
*surface
= impl_from_IDirectDrawSurface3(iface
);
3946 TRACE("iface %p, x %ld, y %ld.\n", iface
, x
, y
);
3948 return ddraw_surface7_SetOverlayPosition(&surface
->IDirectDrawSurface7_iface
, x
, y
);
3951 static HRESULT WINAPI
ddraw_surface2_SetOverlayPosition(IDirectDrawSurface2
*iface
, LONG x
, LONG y
)
3953 struct ddraw_surface
*surface
= impl_from_IDirectDrawSurface2(iface
);
3955 TRACE("iface %p, x %ld, y %ld.\n", iface
, x
, y
);
3957 return ddraw_surface7_SetOverlayPosition(&surface
->IDirectDrawSurface7_iface
, x
, y
);
3960 static HRESULT WINAPI
ddraw_surface1_SetOverlayPosition(IDirectDrawSurface
*iface
, LONG x
, LONG y
)
3962 struct ddraw_surface
*surface
= impl_from_IDirectDrawSurface(iface
);
3964 TRACE("iface %p, x %ld, y %ld.\n", iface
, x
, y
);
3966 return ddraw_surface7_SetOverlayPosition(&surface
->IDirectDrawSurface7_iface
, x
, y
);
3969 /*****************************************************************************
3970 * IDirectDrawSurface7::UpdateOverlay
3972 * Modifies the attributes of an overlay surface.
3975 * SrcRect: The section of the source being used for the overlay
3976 * DstSurface: Address of the surface that is overlaid
3977 * DstRect: Place of the overlay
3978 * Flags: some DDOVER_* flags
3981 * DDERR_UNSUPPORTED, because we don't support overlays
3983 *****************************************************************************/
3984 static HRESULT WINAPI
ddraw_surface7_UpdateOverlay(IDirectDrawSurface7
*iface
, RECT
*src_rect
,
3985 IDirectDrawSurface7
*dst_surface
, RECT
*dst_rect
, DWORD flags
, DDOVERLAYFX
*fx
)
3987 struct ddraw_surface
*src_impl
= impl_from_IDirectDrawSurface7(iface
);
3988 struct ddraw_surface
*dst_impl
= unsafe_impl_from_IDirectDrawSurface7(dst_surface
);
3989 struct wined3d_texture
*dst_wined3d_texture
= NULL
;
3990 unsigned int dst_sub_resource_idx
= 0;
3993 TRACE("iface %p, src_rect %s, dst_surface %p, dst_rect %s, flags %#lx, fx %p.\n",
3994 iface
, wine_dbgstr_rect(src_rect
), dst_surface
, wine_dbgstr_rect(dst_rect
), flags
, fx
);
3997 FIXME("Ignoring fx %p.\n", fx
);
3999 wined3d_mutex_lock();
4002 dst_wined3d_texture
= dst_impl
->wined3d_texture
;
4003 dst_sub_resource_idx
= dst_impl
->sub_resource_idx
;
4005 hr
= wined3d_texture_update_overlay(src_impl
->wined3d_texture
, src_impl
->sub_resource_idx
,
4006 src_rect
, dst_wined3d_texture
, dst_sub_resource_idx
, dst_rect
, flags
);
4007 wined3d_mutex_unlock();
4009 return hr_ddraw_from_wined3d(hr
);
4012 static HRESULT WINAPI
ddraw_surface4_UpdateOverlay(IDirectDrawSurface4
*iface
, RECT
*src_rect
,
4013 IDirectDrawSurface4
*dst_surface
, RECT
*dst_rect
, DWORD flags
, DDOVERLAYFX
*fx
)
4015 struct ddraw_surface
*src_impl
= impl_from_IDirectDrawSurface4(iface
);
4016 struct ddraw_surface
*dst_impl
= unsafe_impl_from_IDirectDrawSurface4(dst_surface
);
4018 TRACE("iface %p, src_rect %s, dst_surface %p, dst_rect %s, flags %#lx, fx %p.\n",
4019 iface
, wine_dbgstr_rect(src_rect
), dst_surface
, wine_dbgstr_rect(dst_rect
), flags
, fx
);
4021 return ddraw_surface7_UpdateOverlay(&src_impl
->IDirectDrawSurface7_iface
, src_rect
,
4022 dst_impl
? &dst_impl
->IDirectDrawSurface7_iface
: NULL
, dst_rect
, flags
, fx
);
4025 static HRESULT WINAPI
ddraw_surface3_UpdateOverlay(IDirectDrawSurface3
*iface
, RECT
*src_rect
,
4026 IDirectDrawSurface3
*dst_surface
, RECT
*dst_rect
, DWORD flags
, DDOVERLAYFX
*fx
)
4028 struct ddraw_surface
*src_impl
= impl_from_IDirectDrawSurface3(iface
);
4029 struct ddraw_surface
*dst_impl
= unsafe_impl_from_IDirectDrawSurface3(dst_surface
);
4031 TRACE("iface %p, src_rect %s, dst_surface %p, dst_rect %s, flags %#lx, fx %p.\n",
4032 iface
, wine_dbgstr_rect(src_rect
), dst_surface
, wine_dbgstr_rect(dst_rect
), flags
, fx
);
4034 return ddraw_surface7_UpdateOverlay(&src_impl
->IDirectDrawSurface7_iface
, src_rect
,
4035 dst_impl
? &dst_impl
->IDirectDrawSurface7_iface
: NULL
, dst_rect
, flags
, fx
);
4038 static HRESULT WINAPI
ddraw_surface2_UpdateOverlay(IDirectDrawSurface2
*iface
, RECT
*src_rect
,
4039 IDirectDrawSurface2
*dst_surface
, RECT
*dst_rect
, DWORD flags
, DDOVERLAYFX
*fx
)
4041 struct ddraw_surface
*src_impl
= impl_from_IDirectDrawSurface2(iface
);
4042 struct ddraw_surface
*dst_impl
= unsafe_impl_from_IDirectDrawSurface2(dst_surface
);
4044 TRACE("iface %p, src_rect %s, dst_surface %p, dst_rect %s, flags %#lx, fx %p.\n",
4045 iface
, wine_dbgstr_rect(src_rect
), dst_surface
, wine_dbgstr_rect(dst_rect
), flags
, fx
);
4047 return ddraw_surface7_UpdateOverlay(&src_impl
->IDirectDrawSurface7_iface
, src_rect
,
4048 dst_impl
? &dst_impl
->IDirectDrawSurface7_iface
: NULL
, dst_rect
, flags
, fx
);
4051 static HRESULT WINAPI
ddraw_surface1_UpdateOverlay(IDirectDrawSurface
*iface
, RECT
*src_rect
,
4052 IDirectDrawSurface
*dst_surface
, RECT
*dst_rect
, DWORD flags
, DDOVERLAYFX
*fx
)
4054 struct ddraw_surface
*src_impl
= impl_from_IDirectDrawSurface(iface
);
4055 struct ddraw_surface
*dst_impl
= unsafe_impl_from_IDirectDrawSurface(dst_surface
);
4057 TRACE("iface %p, src_rect %s, dst_surface %p, dst_rect %s, flags %#lx, fx %p.\n",
4058 iface
, wine_dbgstr_rect(src_rect
), dst_surface
, wine_dbgstr_rect(dst_rect
), flags
, fx
);
4060 return ddraw_surface7_UpdateOverlay(&src_impl
->IDirectDrawSurface7_iface
, src_rect
,
4061 dst_impl
? &dst_impl
->IDirectDrawSurface7_iface
: NULL
, dst_rect
, flags
, fx
);
4064 /*****************************************************************************
4065 * IDirectDrawSurface7::UpdateOverlayDisplay
4067 * The DX7 sdk says that it's not implemented
4072 * Returns: DDERR_UNSUPPORTED, because we don't support overlays
4074 *****************************************************************************/
4075 static HRESULT WINAPI
ddraw_surface7_UpdateOverlayDisplay(IDirectDrawSurface7
*iface
, DWORD Flags
)
4077 TRACE("iface %p, flags %#lx.\n", iface
, Flags
);
4079 return DDERR_UNSUPPORTED
;
4082 static HRESULT WINAPI
ddraw_surface4_UpdateOverlayDisplay(IDirectDrawSurface4
*iface
, DWORD flags
)
4084 struct ddraw_surface
*surface
= impl_from_IDirectDrawSurface4(iface
);
4086 TRACE("iface %p, flags %#lx.\n", iface
, flags
);
4088 return ddraw_surface7_UpdateOverlayDisplay(&surface
->IDirectDrawSurface7_iface
, flags
);
4091 static HRESULT WINAPI
ddraw_surface3_UpdateOverlayDisplay(IDirectDrawSurface3
*iface
, DWORD flags
)
4093 struct ddraw_surface
*surface
= impl_from_IDirectDrawSurface3(iface
);
4095 TRACE("iface %p, flags %#lx.\n", iface
, flags
);
4097 return ddraw_surface7_UpdateOverlayDisplay(&surface
->IDirectDrawSurface7_iface
, flags
);
4100 static HRESULT WINAPI
ddraw_surface2_UpdateOverlayDisplay(IDirectDrawSurface2
*iface
, DWORD flags
)
4102 struct ddraw_surface
*surface
= impl_from_IDirectDrawSurface2(iface
);
4104 TRACE("iface %p, flags %#lx.\n", iface
, flags
);
4106 return ddraw_surface7_UpdateOverlayDisplay(&surface
->IDirectDrawSurface7_iface
, flags
);
4109 static HRESULT WINAPI
ddraw_surface1_UpdateOverlayDisplay(IDirectDrawSurface
*iface
, DWORD flags
)
4111 struct ddraw_surface
*surface
= impl_from_IDirectDrawSurface(iface
);
4113 TRACE("iface %p, flags %#lx.\n", iface
, flags
);
4115 return ddraw_surface7_UpdateOverlayDisplay(&surface
->IDirectDrawSurface7_iface
, flags
);
4118 /*****************************************************************************
4119 * IDirectDrawSurface7::UpdateOverlayZOrder
4121 * Sets an overlay's Z order
4124 * Flags: DDOVERZ_* flags
4125 * DDSRef: Defines the relative position in the overlay chain
4128 * DDERR_NOTOVERLAYSURFACE, because we don't support overlays
4130 *****************************************************************************/
4131 static HRESULT WINAPI
ddraw_surface7_UpdateOverlayZOrder(IDirectDrawSurface7
*iface
,
4132 DWORD flags
, IDirectDrawSurface7
*reference
)
4134 struct ddraw_surface
*surface
= impl_from_IDirectDrawSurface7(iface
);
4136 FIXME("iface %p, flags %#lx, reference %p stub!\n", iface
, flags
, reference
);
4138 wined3d_mutex_lock();
4139 if (!(surface
->surface_desc
.ddsCaps
.dwCaps
& DDSCAPS_OVERLAY
))
4141 WARN("Not an overlay surface.\n");
4142 wined3d_mutex_unlock();
4143 return DDERR_NOTAOVERLAYSURFACE
;
4145 wined3d_mutex_unlock();
4150 static HRESULT WINAPI
ddraw_surface4_UpdateOverlayZOrder(IDirectDrawSurface4
*iface
,
4151 DWORD flags
, IDirectDrawSurface4
*reference
)
4153 struct ddraw_surface
*surface
= impl_from_IDirectDrawSurface4(iface
);
4154 struct ddraw_surface
*reference_impl
= unsafe_impl_from_IDirectDrawSurface4(reference
);
4156 TRACE("iface %p, flags %#lx, reference %p.\n", iface
, flags
, reference
);
4158 return ddraw_surface7_UpdateOverlayZOrder(&surface
->IDirectDrawSurface7_iface
, flags
,
4159 reference_impl
? &reference_impl
->IDirectDrawSurface7_iface
: NULL
);
4162 static HRESULT WINAPI
ddraw_surface3_UpdateOverlayZOrder(IDirectDrawSurface3
*iface
,
4163 DWORD flags
, IDirectDrawSurface3
*reference
)
4165 struct ddraw_surface
*surface
= impl_from_IDirectDrawSurface3(iface
);
4166 struct ddraw_surface
*reference_impl
= unsafe_impl_from_IDirectDrawSurface3(reference
);
4168 TRACE("iface %p, flags %#lx, reference %p.\n", iface
, flags
, reference
);
4170 return ddraw_surface7_UpdateOverlayZOrder(&surface
->IDirectDrawSurface7_iface
, flags
,
4171 reference_impl
? &reference_impl
->IDirectDrawSurface7_iface
: NULL
);
4174 static HRESULT WINAPI
ddraw_surface2_UpdateOverlayZOrder(IDirectDrawSurface2
*iface
,
4175 DWORD flags
, IDirectDrawSurface2
*reference
)
4177 struct ddraw_surface
*surface
= impl_from_IDirectDrawSurface2(iface
);
4178 struct ddraw_surface
*reference_impl
= unsafe_impl_from_IDirectDrawSurface2(reference
);
4180 TRACE("iface %p, flags %#lx, reference %p.\n", iface
, flags
, reference
);
4182 return ddraw_surface7_UpdateOverlayZOrder(&surface
->IDirectDrawSurface7_iface
, flags
,
4183 reference_impl
? &reference_impl
->IDirectDrawSurface7_iface
: NULL
);
4186 static HRESULT WINAPI
ddraw_surface1_UpdateOverlayZOrder(IDirectDrawSurface
*iface
,
4187 DWORD flags
, IDirectDrawSurface
*reference
)
4189 struct ddraw_surface
*surface
= impl_from_IDirectDrawSurface(iface
);
4190 struct ddraw_surface
*reference_impl
= unsafe_impl_from_IDirectDrawSurface(reference
);
4192 TRACE("iface %p, flags %#lx, reference %p.\n", iface
, flags
, reference
);
4194 return ddraw_surface7_UpdateOverlayZOrder(&surface
->IDirectDrawSurface7_iface
, flags
,
4195 reference_impl
? &reference_impl
->IDirectDrawSurface7_iface
: NULL
);
4198 /*****************************************************************************
4199 * IDirectDrawSurface7::GetDDInterface
4201 * Returns the IDirectDraw7 interface pointer of the DirectDraw object this
4202 * surface belongs to
4205 * DD: Address to write the interface pointer to
4209 * DDERR_INVALIDPARAMS if DD is NULL
4211 *****************************************************************************/
4212 static HRESULT WINAPI
ddraw_surface7_GetDDInterface(IDirectDrawSurface7
*iface
, void **DD
)
4214 struct ddraw_surface
*This
= impl_from_IDirectDrawSurface7(iface
);
4216 TRACE("iface %p, ddraw %p.\n", iface
, DD
);
4219 return DDERR_INVALIDPARAMS
;
4221 switch(This
->version
)
4224 *DD
= &This
->ddraw
->IDirectDraw7_iface
;
4228 *DD
= &This
->ddraw
->IDirectDraw4_iface
;
4232 *DD
= &This
->ddraw
->IDirectDraw2_iface
;
4236 *DD
= &This
->ddraw
->IDirectDraw_iface
;
4240 IUnknown_AddRef((IUnknown
*)*DD
);
4245 static HRESULT WINAPI
ddraw_surface4_GetDDInterface(IDirectDrawSurface4
*iface
, void **ddraw
)
4247 struct ddraw_surface
*surface
= impl_from_IDirectDrawSurface4(iface
);
4249 TRACE("iface %p, ddraw %p.\n", iface
, ddraw
);
4251 return ddraw_surface7_GetDDInterface(&surface
->IDirectDrawSurface7_iface
, ddraw
);
4254 static HRESULT WINAPI
ddraw_surface3_GetDDInterface(IDirectDrawSurface3
*iface
, void **ddraw
)
4256 struct ddraw_surface
*surface
= impl_from_IDirectDrawSurface3(iface
);
4258 TRACE("iface %p, ddraw %p.\n", iface
, ddraw
);
4260 return ddraw_surface7_GetDDInterface(&surface
->IDirectDrawSurface7_iface
, ddraw
);
4263 static HRESULT WINAPI
ddraw_surface2_GetDDInterface(IDirectDrawSurface2
*iface
, void **ddraw
)
4265 struct ddraw_surface
*surface
= impl_from_IDirectDrawSurface2(iface
);
4267 TRACE("iface %p, ddraw %p.\n", iface
, ddraw
);
4269 return ddraw_surface7_GetDDInterface(&surface
->IDirectDrawSurface7_iface
, ddraw
);
4272 static HRESULT WINAPI
ddraw_surface7_ChangeUniquenessValue(IDirectDrawSurface7
*iface
)
4274 TRACE("iface %p.\n", iface
);
4279 static HRESULT WINAPI
ddraw_surface4_ChangeUniquenessValue(IDirectDrawSurface4
*iface
)
4281 struct ddraw_surface
*surface
= impl_from_IDirectDrawSurface4(iface
);
4283 TRACE("iface %p.\n", iface
);
4285 return ddraw_surface7_ChangeUniquenessValue(&surface
->IDirectDrawSurface7_iface
);
4288 static HRESULT WINAPI
ddraw_surface7_GetUniquenessValue(IDirectDrawSurface7
*iface
, DWORD
*pValue
)
4290 TRACE("iface %p, value %p.\n", iface
, pValue
);
4297 static HRESULT WINAPI
ddraw_surface4_GetUniquenessValue(IDirectDrawSurface4
*iface
, DWORD
*pValue
)
4299 struct ddraw_surface
*surface
= impl_from_IDirectDrawSurface4(iface
);
4301 TRACE("iface %p, value %p.\n", iface
, pValue
);
4303 return ddraw_surface7_GetUniquenessValue(&surface
->IDirectDrawSurface7_iface
, pValue
);
4306 /*****************************************************************************
4307 * IDirectDrawSurface7::SetLOD
4309 * Sets the level of detail of a texture
4312 * MaxLOD: LOD to set
4316 * DDERR_INVALIDOBJECT if the surface is invalid for this method
4318 *****************************************************************************/
4319 static HRESULT WINAPI
ddraw_surface7_SetLOD(IDirectDrawSurface7
*iface
, DWORD MaxLOD
)
4321 struct ddraw_surface
*surface
= impl_from_IDirectDrawSurface7(iface
);
4324 TRACE("iface %p, lod %lu.\n", iface
, MaxLOD
);
4326 wined3d_mutex_lock();
4327 if (!(surface
->surface_desc
.ddsCaps
.dwCaps2
& DDSCAPS2_TEXTUREMANAGE
))
4329 wined3d_mutex_unlock();
4330 return DDERR_INVALIDOBJECT
;
4333 hr
= wined3d_texture_set_lod(surface
->wined3d_texture
, MaxLOD
);
4334 if (SUCCEEDED(hr
) && surface
->draw_texture
)
4335 hr
= wined3d_texture_set_lod(surface
->draw_texture
, MaxLOD
);
4336 wined3d_mutex_unlock();
4341 /*****************************************************************************
4342 * IDirectDrawSurface7::GetLOD
4344 * Returns the level of detail of a Direct3D texture
4347 * MaxLOD: Address to write the LOD to
4351 * DDERR_INVALIDPARAMS if MaxLOD is NULL
4352 * DDERR_INVALIDOBJECT if the surface is invalid for this method
4354 *****************************************************************************/
4355 static HRESULT WINAPI
ddraw_surface7_GetLOD(IDirectDrawSurface7
*iface
, DWORD
*MaxLOD
)
4357 struct ddraw_surface
*surface
= impl_from_IDirectDrawSurface7(iface
);
4359 TRACE("iface %p, lod %p.\n", iface
, MaxLOD
);
4362 return DDERR_INVALIDPARAMS
;
4364 wined3d_mutex_lock();
4365 if (!(surface
->surface_desc
.ddsCaps
.dwCaps2
& DDSCAPS2_TEXTUREMANAGE
))
4367 wined3d_mutex_unlock();
4368 return DDERR_INVALIDOBJECT
;
4371 *MaxLOD
= wined3d_texture_get_lod(surface
->wined3d_texture
);
4372 wined3d_mutex_unlock();
4377 /*****************************************************************************
4378 * IDirectDrawSurface7::BltFast
4380 * Performs a fast Blit.
4383 * dstx: The x coordinate to blit to on the destination
4384 * dsty: The y coordinate to blit to on the destination
4385 * Source: The source surface
4386 * rsrc: The source rectangle
4387 * trans: Type of transfer. Some DDBLTFAST_* flags
4390 * DD_OK on success, error code otherwise.
4392 *****************************************************************************/
4393 static HRESULT WINAPI DECLSPEC_HOTPATCH
ddraw_surface7_BltFast(IDirectDrawSurface7
*iface
,
4394 DWORD dst_x
, DWORD dst_y
, IDirectDrawSurface7
*src_surface
, RECT
*src_rect
, DWORD trans
)
4396 struct ddraw_surface
*dst_impl
= impl_from_IDirectDrawSurface7(iface
);
4397 struct ddraw_surface
*src_impl
= unsafe_impl_from_IDirectDrawSurface7(src_surface
);
4398 DWORD flags
= WINED3D_BLT_SYNCHRONOUS
;
4399 DWORD src_w
, src_h
, dst_w
, dst_h
;
4403 TRACE("iface %p, dst_x %lu, dst_y %lu, src_surface %p, src_rect %s, flags %#lx.\n",
4404 iface
, dst_x
, dst_y
, src_surface
, wine_dbgstr_rect(src_rect
), trans
);
4406 dst_w
= dst_impl
->surface_desc
.dwWidth
;
4407 dst_h
= dst_impl
->surface_desc
.dwHeight
;
4411 SetRect(&s
, 0, 0, src_impl
->surface_desc
.dwWidth
, src_impl
->surface_desc
.dwHeight
);
4415 src_w
= src_rect
->right
- src_rect
->left
;
4416 src_h
= src_rect
->bottom
- src_rect
->top
;
4417 if (src_w
> dst_w
|| dst_x
> dst_w
- src_w
4418 || src_h
> dst_h
|| dst_y
> dst_h
- src_h
)
4420 WARN("Destination area out of bounds, returning DDERR_INVALIDRECT.\n");
4421 return DDERR_INVALIDRECT
;
4424 SetRect(&dst_rect
, dst_x
, dst_y
, dst_x
+ src_w
, dst_y
+ src_h
);
4425 if (trans
& DDBLTFAST_SRCCOLORKEY
)
4426 flags
|= WINED3D_BLT_SRC_CKEY
;
4427 if (trans
& DDBLTFAST_DESTCOLORKEY
)
4428 flags
|= WINED3D_BLT_DST_CKEY
;
4429 if (trans
& DDBLTFAST_WAIT
)
4430 flags
|= WINED3D_BLT_WAIT
;
4431 if (trans
& DDBLTFAST_DONOTWAIT
)
4432 flags
|= WINED3D_BLT_DO_NOT_WAIT
;
4434 wined3d_mutex_lock();
4435 if (dst_impl
->clipper
)
4437 wined3d_mutex_unlock();
4438 WARN("Destination surface has a clipper set, returning DDERR_BLTFASTCANTCLIP.\n");
4439 return DDERR_BLTFASTCANTCLIP
;
4442 if (src_impl
->surface_desc
.ddsCaps
.dwCaps
& DDSCAPS_PRIMARYSURFACE
)
4443 hr
= ddraw_surface_update_frontbuffer(src_impl
, src_rect
, TRUE
, 0);
4445 hr
= wined3d_device_context_blt(dst_impl
->ddraw
->immediate_context
,
4446 ddraw_surface_get_any_texture(dst_impl
, DDRAW_SURFACE_RW
), dst_impl
->sub_resource_idx
, &dst_rect
,
4447 ddraw_surface_get_any_texture(src_impl
,DDRAW_SURFACE_READ
), src_impl
->sub_resource_idx
, src_rect
,
4448 flags
, NULL
, WINED3D_TEXF_POINT
);
4449 if (SUCCEEDED(hr
) && (dst_impl
->surface_desc
.ddsCaps
.dwCaps
& DDSCAPS_PRIMARYSURFACE
))
4450 hr
= ddraw_surface_update_frontbuffer(dst_impl
, &dst_rect
, FALSE
, 0);
4451 wined3d_mutex_unlock();
4455 case WINED3DERR_NOTAVAILABLE
: return DDERR_UNSUPPORTED
;
4460 static HRESULT WINAPI DECLSPEC_HOTPATCH
ddraw_surface4_BltFast(IDirectDrawSurface4
*iface
, DWORD dst_x
, DWORD dst_y
,
4461 IDirectDrawSurface4
*src_surface
, RECT
*src_rect
, DWORD flags
)
4463 struct ddraw_surface
*dst_impl
= impl_from_IDirectDrawSurface4(iface
);
4464 struct ddraw_surface
*src_impl
= unsafe_impl_from_IDirectDrawSurface4(src_surface
);
4466 TRACE("iface %p, dst_x %lu, dst_y %lu, src_surface %p, src_rect %s, flags %#lx.\n",
4467 iface
, dst_x
, dst_y
, src_surface
, wine_dbgstr_rect(src_rect
), flags
);
4469 return ddraw_surface7_BltFast(&dst_impl
->IDirectDrawSurface7_iface
, dst_x
, dst_y
,
4470 src_impl
? &src_impl
->IDirectDrawSurface7_iface
: NULL
, src_rect
, flags
);
4473 static HRESULT WINAPI DECLSPEC_HOTPATCH
ddraw_surface3_BltFast(IDirectDrawSurface3
*iface
, DWORD dst_x
, DWORD dst_y
,
4474 IDirectDrawSurface3
*src_surface
, RECT
*src_rect
, DWORD flags
)
4476 struct ddraw_surface
*dst_impl
= impl_from_IDirectDrawSurface3(iface
);
4477 struct ddraw_surface
*src_impl
= unsafe_impl_from_IDirectDrawSurface3(src_surface
);
4479 TRACE("iface %p, dst_x %lu, dst_y %lu, src_surface %p, src_rect %s, flags %#lx.\n",
4480 iface
, dst_x
, dst_y
, src_surface
, wine_dbgstr_rect(src_rect
), flags
);
4482 return ddraw_surface7_BltFast(&dst_impl
->IDirectDrawSurface7_iface
, dst_x
, dst_y
,
4483 src_impl
? &src_impl
->IDirectDrawSurface7_iface
: NULL
, src_rect
, flags
);
4486 static HRESULT WINAPI DECLSPEC_HOTPATCH
ddraw_surface2_BltFast(IDirectDrawSurface2
*iface
, DWORD dst_x
, DWORD dst_y
,
4487 IDirectDrawSurface2
*src_surface
, RECT
*src_rect
, DWORD flags
)
4489 struct ddraw_surface
*dst_impl
= impl_from_IDirectDrawSurface2(iface
);
4490 struct ddraw_surface
*src_impl
= unsafe_impl_from_IDirectDrawSurface2(src_surface
);
4492 TRACE("iface %p, dst_x %lu, dst_y %lu, src_surface %p, src_rect %s, flags %#lx.\n",
4493 iface
, dst_x
, dst_y
, src_surface
, wine_dbgstr_rect(src_rect
), flags
);
4495 return ddraw_surface7_BltFast(&dst_impl
->IDirectDrawSurface7_iface
, dst_x
, dst_y
,
4496 src_impl
? &src_impl
->IDirectDrawSurface7_iface
: NULL
, src_rect
, flags
);
4499 static HRESULT WINAPI DECLSPEC_HOTPATCH
ddraw_surface1_BltFast(IDirectDrawSurface
*iface
, DWORD dst_x
, DWORD dst_y
,
4500 IDirectDrawSurface
*src_surface
, RECT
*src_rect
, DWORD flags
)
4502 struct ddraw_surface
*dst_impl
= impl_from_IDirectDrawSurface(iface
);
4503 struct ddraw_surface
*src_impl
= unsafe_impl_from_IDirectDrawSurface(src_surface
);
4505 TRACE("iface %p, dst_x %lu, dst_y %lu, src_surface %p, src_rect %s, flags %#lx.\n",
4506 iface
, dst_x
, dst_y
, src_surface
, wine_dbgstr_rect(src_rect
), flags
);
4508 return ddraw_surface7_BltFast(&dst_impl
->IDirectDrawSurface7_iface
, dst_x
, dst_y
,
4509 src_impl
? &src_impl
->IDirectDrawSurface7_iface
: NULL
, src_rect
, flags
);
4512 static HRESULT WINAPI
ddraw_surface7_GetClipper(IDirectDrawSurface7
*iface
, IDirectDrawClipper
**clipper
)
4514 struct ddraw_surface
*surface
= impl_from_IDirectDrawSurface7(iface
);
4516 TRACE("iface %p, clipper %p.\n", iface
, clipper
);
4519 return DDERR_INVALIDPARAMS
;
4521 wined3d_mutex_lock();
4522 if (!surface
->clipper
)
4524 wined3d_mutex_unlock();
4526 return DDERR_NOCLIPPERATTACHED
;
4529 *clipper
= &surface
->clipper
->IDirectDrawClipper_iface
;
4530 if (ddraw_clipper_is_valid(surface
->clipper
))
4531 IDirectDrawClipper_AddRef(*clipper
);
4532 wined3d_mutex_unlock();
4537 static HRESULT WINAPI
ddraw_surface4_GetClipper(IDirectDrawSurface4
*iface
, IDirectDrawClipper
**clipper
)
4539 struct ddraw_surface
*surface
= impl_from_IDirectDrawSurface4(iface
);
4541 TRACE("iface %p, clipper %p.\n", iface
, clipper
);
4543 return ddraw_surface7_GetClipper(&surface
->IDirectDrawSurface7_iface
, clipper
);
4546 static HRESULT WINAPI
ddraw_surface3_GetClipper(IDirectDrawSurface3
*iface
, IDirectDrawClipper
**clipper
)
4548 struct ddraw_surface
*surface
= impl_from_IDirectDrawSurface3(iface
);
4550 TRACE("iface %p, clipper %p.\n", iface
, clipper
);
4552 return ddraw_surface7_GetClipper(&surface
->IDirectDrawSurface7_iface
, clipper
);
4555 static HRESULT WINAPI
ddraw_surface2_GetClipper(IDirectDrawSurface2
*iface
, IDirectDrawClipper
**clipper
)
4557 struct ddraw_surface
*surface
= impl_from_IDirectDrawSurface2(iface
);
4559 TRACE("iface %p, clipper %p.\n", iface
, clipper
);
4561 return ddraw_surface7_GetClipper(&surface
->IDirectDrawSurface7_iface
, clipper
);
4564 static HRESULT WINAPI
ddraw_surface1_GetClipper(IDirectDrawSurface
*iface
, IDirectDrawClipper
**clipper
)
4566 struct ddraw_surface
*surface
= impl_from_IDirectDrawSurface(iface
);
4568 TRACE("iface %p, clipper %p.\n", iface
, clipper
);
4570 return ddraw_surface7_GetClipper(&surface
->IDirectDrawSurface7_iface
, clipper
);
4573 /*****************************************************************************
4574 * IDirectDrawSurface7::SetClipper
4576 * Sets a clipper for the surface
4579 * Clipper: IDirectDrawClipper interface of the clipper to set
4584 *****************************************************************************/
4585 static HRESULT WINAPI
ddraw_surface7_SetClipper(IDirectDrawSurface7
*iface
,
4586 IDirectDrawClipper
*iclipper
)
4588 struct ddraw_surface
*This
= impl_from_IDirectDrawSurface7(iface
);
4589 struct ddraw_clipper
*clipper
= unsafe_impl_from_IDirectDrawClipper(iclipper
);
4590 struct ddraw_clipper
*old_clipper
= This
->clipper
;
4593 TRACE("iface %p, clipper %p.\n", iface
, iclipper
);
4595 wined3d_mutex_lock();
4596 if (clipper
== This
->clipper
)
4598 wined3d_mutex_unlock();
4602 This
->clipper
= clipper
;
4604 if (clipper
!= NULL
)
4605 IDirectDrawClipper_AddRef(iclipper
);
4606 if (old_clipper
&& ddraw_clipper_is_valid(old_clipper
))
4607 IDirectDrawClipper_Release(&old_clipper
->IDirectDrawClipper_iface
);
4609 if ((This
->surface_desc
.ddsCaps
.dwCaps
& DDSCAPS_PRIMARYSURFACE
) && This
->ddraw
->wined3d_swapchain
)
4613 IDirectDrawClipper_GetHWnd(iclipper
, &clipWindow
);
4618 wined3d_swapchain_set_window(This
->ddraw
->wined3d_swapchain
, clipWindow
);
4619 ddraw_set_swapchain_window(This
->ddraw
, clipWindow
);
4623 wined3d_swapchain_set_window(This
->ddraw
->wined3d_swapchain
, This
->ddraw
->d3d_window
);
4624 ddraw_set_swapchain_window(This
->ddraw
, This
->ddraw
->dest_window
);
4628 wined3d_mutex_unlock();
4633 static HRESULT WINAPI
ddraw_surface4_SetClipper(IDirectDrawSurface4
*iface
, IDirectDrawClipper
*clipper
)
4635 struct ddraw_surface
*surface
= impl_from_IDirectDrawSurface4(iface
);
4637 TRACE("iface %p, clipper %p.\n", iface
, clipper
);
4639 return ddraw_surface7_SetClipper(&surface
->IDirectDrawSurface7_iface
, clipper
);
4642 static HRESULT WINAPI
ddraw_surface3_SetClipper(IDirectDrawSurface3
*iface
, IDirectDrawClipper
*clipper
)
4644 struct ddraw_surface
*surface
= impl_from_IDirectDrawSurface3(iface
);
4646 TRACE("iface %p, clipper %p.\n", iface
, clipper
);
4648 return ddraw_surface7_SetClipper(&surface
->IDirectDrawSurface7_iface
, clipper
);
4651 static HRESULT WINAPI
ddraw_surface2_SetClipper(IDirectDrawSurface2
*iface
, IDirectDrawClipper
*clipper
)
4653 struct ddraw_surface
*surface
= impl_from_IDirectDrawSurface2(iface
);
4655 TRACE("iface %p, clipper %p.\n", iface
, clipper
);
4657 return ddraw_surface7_SetClipper(&surface
->IDirectDrawSurface7_iface
, clipper
);
4660 static HRESULT WINAPI
ddraw_surface1_SetClipper(IDirectDrawSurface
*iface
, IDirectDrawClipper
*clipper
)
4662 struct ddraw_surface
*surface
= impl_from_IDirectDrawSurface(iface
);
4664 TRACE("iface %p, clipper %p.\n", iface
, clipper
);
4666 return ddraw_surface7_SetClipper(&surface
->IDirectDrawSurface7_iface
, clipper
);
4669 static HRESULT
ddraw_surface_set_wined3d_textures_colour_key(struct ddraw_surface
*surface
, DWORD flags
,
4670 struct wined3d_color_key
*color_key
)
4674 hr
= wined3d_texture_set_color_key(surface
->wined3d_texture
, flags
, color_key
);
4675 if (surface
->draw_texture
&& SUCCEEDED(hr
))
4676 hr
= wined3d_texture_set_color_key(surface
->draw_texture
, flags
, color_key
);
4681 static void ddraw_surface_sync_color_keys(struct ddraw_surface
*surface
)
4683 const DDSURFACEDESC2
*desc
= &surface
->surface_desc
;
4685 if (desc
->dwFlags
& DDSD_CKDESTOVERLAY
)
4686 ddraw_surface_set_wined3d_textures_colour_key(surface
, DDCKEY_DESTOVERLAY
,
4687 (struct wined3d_color_key
*)&desc
->u3
.ddckCKDestOverlay
);
4688 if (desc
->dwFlags
& DDSD_CKDESTBLT
)
4689 ddraw_surface_set_wined3d_textures_colour_key(surface
, DDCKEY_DESTBLT
,
4690 (struct wined3d_color_key
*)&desc
->ddckCKDestBlt
);
4691 if (desc
->dwFlags
& DDSD_CKSRCOVERLAY
)
4692 ddraw_surface_set_wined3d_textures_colour_key(surface
, DDCKEY_SRCOVERLAY
,
4693 (struct wined3d_color_key
*)&desc
->ddckCKSrcOverlay
);
4694 if (desc
->dwFlags
& DDSD_CKSRCBLT
)
4695 ddraw_surface_set_wined3d_textures_colour_key(surface
, DDCKEY_SRCBLT
,
4696 (struct wined3d_color_key
*)&desc
->ddckCKSrcBlt
);
4699 static HRESULT WINAPI
ddraw_surface7_SetSurfaceDesc(IDirectDrawSurface7
*iface
, DDSURFACEDESC2
*DDSD
, DWORD Flags
)
4701 struct ddraw_surface
*surface
= impl_from_IDirectDrawSurface7(iface
);
4702 enum wined3d_format_id current_format_id
, format_id
;
4704 const DWORD allowed_flags
= DDSD_LPSURFACE
| DDSD_PIXELFORMAT
| DDSD_WIDTH
4705 | DDSD_HEIGHT
| DDSD_PITCH
| DDSD_CAPS
;
4706 UINT pitch
, width
, height
;
4708 TRACE("iface %p, surface_desc %p, flags %#lx.\n", iface
, DDSD
, Flags
);
4712 WARN("DDSD is NULL, returning DDERR_INVALIDPARAMS\n");
4713 return DDERR_INVALIDPARAMS
;
4717 WARN("Flags is %lx, returning DDERR_INVALIDPARAMS\n", Flags
);
4718 return DDERR_INVALIDPARAMS
;
4720 if (!(surface
->surface_desc
.ddsCaps
.dwCaps
& DDSCAPS_SYSTEMMEMORY
)
4721 || surface
->surface_desc
.ddsCaps
.dwCaps
& DDSCAPS_PRIMARYSURFACE
4722 || surface
->surface_desc
.ddsCaps
.dwCaps2
& (DDSCAPS2_TEXTUREMANAGE
| DDSCAPS2_D3DTEXTUREMANAGE
))
4724 WARN("Surface is not in system memory, returning DDERR_INVALIDSURFACETYPE.\n");
4725 return DDERR_INVALIDSURFACETYPE
;
4728 if (DDSD
->dwFlags
& ~allowed_flags
)
4730 WARN("Invalid flags %#lx set, returning DDERR_INVALIDPARAMS\n", DDSD
->dwFlags
);
4731 return DDERR_INVALIDPARAMS
;
4733 if (!(DDSD
->dwFlags
& DDSD_LPSURFACE
) || !DDSD
->lpSurface
)
4735 WARN("DDSD_LPSURFACE is not set or lpSurface is NULL, returning DDERR_INVALIDPARAMS\n");
4736 return DDERR_INVALIDPARAMS
;
4738 if ((DDSD
->dwFlags
& DDSD_CAPS
) && DDSD
->ddsCaps
.dwCaps
)
4740 WARN("DDSD_CAPS is set, returning DDERR_INVALIDCAPS.\n");
4741 return DDERR_INVALIDCAPS
;
4743 if (DDSD
->dwFlags
& DDSD_WIDTH
)
4745 if (!(DDSD
->dwFlags
& DDSD_PITCH
))
4747 WARN("DDSD_WIDTH is set, but DDSD_PITCH is not, returning DDERR_INVALIDPARAMS.\n");
4748 return DDERR_INVALIDPARAMS
;
4750 if (!DDSD
->dwWidth
|| DDSD
->u1
.lPitch
<= 0 || DDSD
->u1
.lPitch
& 0x3)
4752 WARN("Pitch is %ld, width is %lu, returning DDERR_INVALIDPARAMS.\n",
4753 DDSD
->u1
.lPitch
, DDSD
->dwWidth
);
4754 return DDERR_INVALIDPARAMS
;
4756 if (DDSD
->dwWidth
!= surface
->surface_desc
.dwWidth
)
4757 TRACE("Surface width changed from %lu to %lu.\n", surface
->surface_desc
.dwWidth
, DDSD
->dwWidth
);
4758 if (DDSD
->u1
.lPitch
!= surface
->surface_desc
.u1
.lPitch
)
4759 TRACE("Surface pitch changed from %lu to %lu.\n", surface
->surface_desc
.u1
.lPitch
, DDSD
->u1
.lPitch
);
4760 pitch
= DDSD
->u1
.lPitch
;
4761 width
= DDSD
->dwWidth
;
4763 else if (DDSD
->dwFlags
& DDSD_PITCH
)
4765 WARN("DDSD_PITCH is set, but DDSD_WIDTH is not, returning DDERR_INVALIDPARAMS.\n");
4766 return DDERR_INVALIDPARAMS
;
4770 pitch
= surface
->surface_desc
.u1
.lPitch
;
4771 width
= surface
->surface_desc
.dwWidth
;
4774 if (DDSD
->dwFlags
& DDSD_HEIGHT
)
4776 if (!DDSD
->dwHeight
)
4778 WARN("Height is 0, returning DDERR_INVALIDPARAMS.\n");
4779 return DDERR_INVALIDPARAMS
;
4781 if (DDSD
->dwHeight
!= surface
->surface_desc
.dwHeight
)
4782 TRACE("Surface height changed from %lu to %lu.\n", surface
->surface_desc
.dwHeight
, DDSD
->dwHeight
);
4783 height
= DDSD
->dwHeight
;
4787 height
= surface
->surface_desc
.dwHeight
;
4790 wined3d_mutex_lock();
4791 if (DDSD
->dwFlags
& DDSD_PIXELFORMAT
)
4793 format_id
= wined3dformat_from_ddrawformat(&DDSD
->u4
.ddpfPixelFormat
);
4795 if (format_id
== WINED3DFMT_UNKNOWN
)
4797 ERR("Requested to set an unknown pixelformat\n");
4798 wined3d_mutex_unlock();
4799 return DDERR_INVALIDPARAMS
;
4801 current_format_id
= wined3dformat_from_ddrawformat(&surface
->surface_desc
.u4
.ddpfPixelFormat
);
4802 if (format_id
!= current_format_id
)
4803 TRACE("Surface format changed from %#x to %#x.\n", current_format_id
, format_id
);
4807 current_format_id
= format_id
= wined3dformat_from_ddrawformat(&surface
->surface_desc
.u4
.ddpfPixelFormat
);
4810 if (width
== surface
->surface_desc
.dwWidth
&& height
== surface
->surface_desc
.dwHeight
4811 && format_id
== current_format_id
)
4813 /* Updating memory only. */
4815 if (FAILED(hr
= wined3d_texture_update_desc(surface
->wined3d_texture
, surface
->sub_resource_idx
,
4816 width
, height
, format_id
, WINED3D_MULTISAMPLE_NONE
, 0, DDSD
->lpSurface
, pitch
)))
4818 WARN("Failed to update surface desc, hr %#lx.\n", hr
);
4819 wined3d_mutex_unlock();
4820 return hr_ddraw_from_wined3d(hr
);
4825 struct ddraw_texture
*ddraw_texture
= wined3d_texture_get_parent(surface
->wined3d_texture
);
4826 struct wined3d_rendertarget_view
*old_rtv
= surface
->wined3d_rtv
;
4827 struct wined3d_texture
*old_draw_texture
= surface
->draw_texture
;
4828 struct wined3d_texture
*old_texture
= surface
->wined3d_texture
;
4829 struct wined3d_texture
*new_texture
, *new_draw_texture
= NULL
;
4830 struct wined3d_resource_desc wined3d_desc
;
4831 struct ddraw
*ddraw
= surface
->ddraw
;
4833 /* Updating surface attributes; recreate the texture. */
4835 if (wined3d_texture_get_level_count(old_texture
) > 1
4836 || (surface
->surface_desc
.ddsCaps
.dwCaps2
& DDSCAPS2_CUBEMAP_ALLFACES
))
4838 FIXME("Texture has multiple sub-resources, not supported.\n");
4839 wined3d_mutex_unlock();
4840 return DDERR_INVALIDPARAMS
;
4843 /* Create the new textures. */
4845 wined3d_resource_get_desc(wined3d_texture_get_resource(old_texture
), &wined3d_desc
);
4847 wined3d_desc
.width
= width
;
4848 wined3d_desc
.height
= height
;
4849 wined3d_desc
.format
= format_id
;
4851 if (FAILED(hr
= wined3d_texture_create(ddraw
->wined3d_device
, &wined3d_desc
, 1, 1,
4852 WINED3D_TEXTURE_CREATE_GET_DC_LENIENT
, NULL
, NULL
, &ddraw_null_wined3d_parent_ops
, &new_texture
)))
4854 ERR("Failed to create texture, hr %#lx.\n", hr
);
4855 wined3d_mutex_unlock();
4856 return hr_ddraw_from_wined3d(hr
);
4859 if (FAILED(hr
= wined3d_texture_update_desc(new_texture
, 0, width
, height
,
4860 format_id
, WINED3D_MULTISAMPLE_NONE
, 0, DDSD
->lpSurface
, pitch
)))
4862 ERR("Failed to set user memory, hr %#lx.\n", hr
);
4863 wined3d_texture_decref(new_texture
);
4864 wined3d_mutex_unlock();
4865 return hr_ddraw_from_wined3d(hr
);
4868 if (old_draw_texture
)
4870 wined3d_resource_get_desc(wined3d_texture_get_resource(old_draw_texture
), &wined3d_desc
);
4872 wined3d_desc
.width
= width
;
4873 wined3d_desc
.height
= height
;
4874 wined3d_desc
.format
= format_id
;
4876 if (FAILED(hr
= wined3d_texture_create(ddraw
->wined3d_device
, &wined3d_desc
, 1, 1,
4877 0, NULL
, NULL
, &ddraw_null_wined3d_parent_ops
, &new_draw_texture
)))
4879 ERR("Failed to create draw texture, hr %#lx.\n", hr
);
4880 wined3d_texture_decref(new_texture
);
4881 wined3d_mutex_unlock();
4882 return hr_ddraw_from_wined3d(hr
);
4886 wined3d_resource_set_parent(wined3d_texture_get_resource(old_texture
),
4887 NULL
, &ddraw_null_wined3d_parent_ops
);
4888 wined3d_texture_set_sub_resource_parent(old_texture
, 0, NULL
, &ddraw_null_wined3d_parent_ops
);
4890 if (surface
->draw_texture
)
4892 wined3d_resource_set_parent(wined3d_texture_get_resource(old_draw_texture
),
4893 NULL
, &ddraw_null_wined3d_parent_ops
);
4894 wined3d_texture_set_sub_resource_parent(old_draw_texture
, 0, NULL
, &ddraw_null_wined3d_parent_ops
);
4896 wined3d_resource_set_parent(wined3d_texture_get_resource(new_draw_texture
),
4897 ddraw_texture
, &ddraw_texture_wined3d_parent_ops
);
4898 wined3d_resource_set_parent(wined3d_texture_get_resource(new_texture
),
4899 ddraw_texture
, &ddraw_null_wined3d_parent_ops
);
4901 wined3d_texture_set_sub_resource_parent(new_draw_texture
, 0, surface
, &ddraw_surface_wined3d_parent_ops
);
4902 wined3d_texture_set_sub_resource_parent(new_texture
, 0, surface
, &ddraw_null_wined3d_parent_ops
);
4904 wined3d_texture_decref(old_draw_texture
);
4908 wined3d_resource_set_parent(wined3d_texture_get_resource(new_texture
),
4909 ddraw_texture
, &ddraw_texture_wined3d_parent_ops
);
4911 wined3d_texture_set_sub_resource_parent(new_texture
, 0, surface
, &ddraw_surface_wined3d_parent_ops
);
4914 surface
->wined3d_texture
= new_texture
;
4915 surface
->draw_texture
= new_draw_texture
;
4917 wined3d_texture_decref(old_texture
);
4919 /* Don't try to replace existing bound textures. Testing implies that
4920 * SetSurfaceDesc() doesn't quite work with texture surfaces anyway:
4921 * it succeeds, and mapping the surface does return the new user memory,
4922 * but drawing from the surface doesn't actually sample from that
4925 /* Destroy the existing RTV. */
4929 struct wined3d_rendertarget_view
*current_rtv
, *new_rtv
;
4931 surface
->wined3d_rtv
= NULL
;
4933 current_rtv
= wined3d_device_context_get_rendertarget_view(ddraw
->immediate_context
, 0);
4934 if (old_rtv
== current_rtv
)
4936 new_rtv
= ddraw_surface_get_rendertarget_view(surface
);
4937 wined3d_device_context_set_rendertarget_views(ddraw
->immediate_context
, 0, 1, &new_rtv
, FALSE
);
4940 wined3d_rendertarget_view_set_parent(old_rtv
, NULL
, &ddraw_null_wined3d_parent_ops
);
4941 wined3d_rendertarget_view_decref(old_rtv
);
4944 ddraw_surface_sync_color_keys(surface
);
4946 /* No need to sync the LOD or overlays; neither can be set on sysmem
4947 * surfaces, and SetSurfaceDesc() can only be used on sysmem surfaces.
4949 * No need to sync the palette either, since wined3d doesn't track it
4950 * except on primary surfaces, and SetSurfaceDesc() is illegal on those
4954 if (DDSD
->dwFlags
& DDSD_WIDTH
)
4955 surface
->surface_desc
.dwWidth
= width
;
4956 if (DDSD
->dwFlags
& DDSD_PITCH
)
4957 surface
->surface_desc
.u1
.lPitch
= DDSD
->u1
.lPitch
;
4958 if (DDSD
->dwFlags
& DDSD_HEIGHT
)
4959 surface
->surface_desc
.dwHeight
= height
;
4960 if (DDSD
->dwFlags
& DDSD_PIXELFORMAT
)
4961 surface
->surface_desc
.u4
.ddpfPixelFormat
= DDSD
->u4
.ddpfPixelFormat
;
4963 wined3d_mutex_unlock();
4968 static HRESULT WINAPI
ddraw_surface4_SetSurfaceDesc(IDirectDrawSurface4
*iface
,
4969 DDSURFACEDESC2
*surface_desc
, DWORD flags
)
4971 struct ddraw_surface
*surface
= impl_from_IDirectDrawSurface4(iface
);
4973 TRACE("iface %p, surface_desc %p, flags %#lx.\n", iface
, surface_desc
, flags
);
4975 return ddraw_surface7_SetSurfaceDesc(&surface
->IDirectDrawSurface7_iface
,
4976 surface_desc
, flags
);
4979 static HRESULT WINAPI
ddraw_surface3_SetSurfaceDesc(IDirectDrawSurface3
*iface
,
4980 DDSURFACEDESC
*surface_desc
, DWORD flags
)
4982 struct ddraw_surface
*surface
= impl_from_IDirectDrawSurface3(iface
);
4983 DDSURFACEDESC2 surface_desc2
;
4985 TRACE("iface %p, surface_desc %p, flags %#lx.\n", iface
, surface_desc
, flags
);
4987 if (surface_desc
) DDSD_to_DDSD2(surface_desc
, &surface_desc2
);
4988 return ddraw_surface7_SetSurfaceDesc(&surface
->IDirectDrawSurface7_iface
,
4989 surface_desc
? &surface_desc2
: NULL
, flags
);
4992 static HRESULT WINAPI
ddraw_surface7_GetPalette(IDirectDrawSurface7
*iface
, IDirectDrawPalette
**palette
)
4994 struct ddraw_surface
*surface
= impl_from_IDirectDrawSurface7(iface
);
4995 struct ddraw_palette
*palette_impl
;
4998 TRACE("iface %p, palette %p.\n", iface
, palette
);
5001 return DDERR_INVALIDPARAMS
;
5002 if (ddraw_surface_is_lost(surface
))
5004 WARN("Surface lost, returning DDERR_SURFACELOST.\n");
5005 return DDERR_SURFACELOST
;
5008 wined3d_mutex_lock();
5009 if ((palette_impl
= surface
->palette
))
5011 *palette
= &palette_impl
->IDirectDrawPalette_iface
;
5012 IDirectDrawPalette_AddRef(*palette
);
5017 hr
= DDERR_NOPALETTEATTACHED
;
5019 wined3d_mutex_unlock();
5024 static HRESULT WINAPI
ddraw_surface4_GetPalette(IDirectDrawSurface4
*iface
, IDirectDrawPalette
**palette
)
5026 struct ddraw_surface
*surface
= impl_from_IDirectDrawSurface4(iface
);
5028 TRACE("iface %p, palette %p.\n", iface
, palette
);
5030 return ddraw_surface7_GetPalette(&surface
->IDirectDrawSurface7_iface
, palette
);
5033 static HRESULT WINAPI
ddraw_surface3_GetPalette(IDirectDrawSurface3
*iface
, IDirectDrawPalette
**palette
)
5035 struct ddraw_surface
*surface
= impl_from_IDirectDrawSurface3(iface
);
5037 TRACE("iface %p, palette %p.\n", iface
, palette
);
5039 return ddraw_surface7_GetPalette(&surface
->IDirectDrawSurface7_iface
, palette
);
5042 static HRESULT WINAPI
ddraw_surface2_GetPalette(IDirectDrawSurface2
*iface
, IDirectDrawPalette
**palette
)
5044 struct ddraw_surface
*surface
= impl_from_IDirectDrawSurface2(iface
);
5046 TRACE("iface %p, palette %p.\n", iface
, palette
);
5048 return ddraw_surface7_GetPalette(&surface
->IDirectDrawSurface7_iface
, palette
);
5051 static HRESULT WINAPI
ddraw_surface1_GetPalette(IDirectDrawSurface
*iface
, IDirectDrawPalette
**palette
)
5053 struct ddraw_surface
*surface
= impl_from_IDirectDrawSurface(iface
);
5055 TRACE("iface %p, palette %p.\n", iface
, palette
);
5057 return ddraw_surface7_GetPalette(&surface
->IDirectDrawSurface7_iface
, palette
);
5060 static HRESULT
ddraw_surface_set_color_key(struct ddraw_surface
*surface
, DWORD flags
, DDCOLORKEY
*color_key
)
5062 DDCOLORKEY fixed_color_key
;
5063 HRESULT hr
= WINED3D_OK
;
5065 if (flags
& DDCKEY_COLORSPACE
)
5067 if (color_key
&& color_key
->dwColorSpaceLowValue
!= color_key
->dwColorSpaceHighValue
)
5069 WARN("Range color keys are not supported, returning DDERR_NOCOLORKEYHW.\n");
5070 return DDERR_NOCOLORKEYHW
;
5072 flags
&= ~DDCKEY_COLORSPACE
;
5075 wined3d_mutex_lock();
5079 fixed_color_key
.dwColorSpaceLowValue
= fixed_color_key
.dwColorSpaceHighValue
= color_key
->dwColorSpaceLowValue
;
5080 switch (flags
& ~DDCKEY_COLORSPACE
)
5082 case DDCKEY_DESTBLT
:
5083 surface
->surface_desc
.ddckCKDestBlt
= fixed_color_key
;
5084 surface
->surface_desc
.dwFlags
|= DDSD_CKDESTBLT
;
5087 case DDCKEY_DESTOVERLAY
:
5088 surface
->surface_desc
.u3
.ddckCKDestOverlay
= fixed_color_key
;
5089 surface
->surface_desc
.dwFlags
|= DDSD_CKDESTOVERLAY
;
5092 case DDCKEY_SRCOVERLAY
:
5093 surface
->surface_desc
.ddckCKSrcOverlay
= fixed_color_key
;
5094 surface
->surface_desc
.dwFlags
|= DDSD_CKSRCOVERLAY
;
5098 surface
->surface_desc
.ddckCKSrcBlt
= fixed_color_key
;
5099 surface
->surface_desc
.dwFlags
|= DDSD_CKSRCBLT
;
5103 wined3d_mutex_unlock();
5104 return DDERR_INVALIDPARAMS
;
5109 switch (flags
& ~DDCKEY_COLORSPACE
)
5111 case DDCKEY_DESTBLT
:
5112 surface
->surface_desc
.dwFlags
&= ~DDSD_CKDESTBLT
;
5115 case DDCKEY_DESTOVERLAY
:
5116 surface
->surface_desc
.dwFlags
&= ~DDSD_CKDESTOVERLAY
;
5119 case DDCKEY_SRCOVERLAY
:
5120 surface
->surface_desc
.dwFlags
&= ~DDSD_CKSRCOVERLAY
;
5124 surface
->surface_desc
.dwFlags
&= ~DDSD_CKSRCBLT
;
5128 wined3d_mutex_unlock();
5129 return DDERR_INVALIDPARAMS
;
5133 if (surface
->is_root
)
5134 hr
= ddraw_surface_set_wined3d_textures_colour_key(surface
, flags
,
5135 color_key
? (struct wined3d_color_key
*)&fixed_color_key
: NULL
);
5137 wined3d_mutex_unlock();
5139 return hr_ddraw_from_wined3d(hr
);
5142 static HRESULT WINAPI
ddraw_surface7_SetColorKey(IDirectDrawSurface7
*iface
, DWORD flags
, DDCOLORKEY
*color_key
)
5144 struct ddraw_surface
*surface
= impl_from_IDirectDrawSurface7(iface
);
5146 TRACE("iface %p, flags %#lx, color_key %p.\n", iface
, flags
, color_key
);
5148 if (surface
->surface_desc
.ddsCaps
.dwCaps2
& DDSCAPS2_MIPMAPSUBLEVEL
)
5149 return DDERR_NOTONMIPMAPSUBLEVEL
;
5151 return ddraw_surface_set_color_key(surface
, flags
, color_key
);
5154 static HRESULT WINAPI
ddraw_surface4_SetColorKey(IDirectDrawSurface4
*iface
, DWORD flags
, DDCOLORKEY
*color_key
)
5156 struct ddraw_surface
*surface
= impl_from_IDirectDrawSurface4(iface
);
5158 TRACE("iface %p, flags %#lx, color_key %p.\n", iface
, flags
, color_key
);
5160 return ddraw_surface_set_color_key(surface
, flags
, color_key
);
5163 static HRESULT WINAPI
ddraw_surface3_SetColorKey(IDirectDrawSurface3
*iface
, DWORD flags
, DDCOLORKEY
*color_key
)
5165 struct ddraw_surface
*surface
= impl_from_IDirectDrawSurface3(iface
);
5167 TRACE("iface %p, flags %#lx, color_key %p.\n", iface
, flags
, color_key
);
5169 return ddraw_surface_set_color_key(surface
, flags
, color_key
);
5172 static HRESULT WINAPI
ddraw_surface2_SetColorKey(IDirectDrawSurface2
*iface
, DWORD flags
, DDCOLORKEY
*color_key
)
5174 struct ddraw_surface
*surface
= impl_from_IDirectDrawSurface2(iface
);
5176 TRACE("iface %p, flags %#lx, color_key %p.\n", iface
, flags
, color_key
);
5178 return ddraw_surface_set_color_key(surface
, flags
, color_key
);
5181 static HRESULT WINAPI
ddraw_surface1_SetColorKey(IDirectDrawSurface
*iface
, DWORD flags
, DDCOLORKEY
*color_key
)
5183 struct ddraw_surface
*surface
= impl_from_IDirectDrawSurface(iface
);
5185 TRACE("iface %p, flags %#lx, color_key %p.\n", iface
, flags
, color_key
);
5187 return ddraw_surface_set_color_key(surface
, flags
, color_key
);
5190 static HRESULT WINAPI
ddraw_surface7_SetPalette(IDirectDrawSurface7
*iface
, IDirectDrawPalette
*palette
)
5192 struct ddraw_surface
*surface
= impl_from_IDirectDrawSurface7(iface
);
5194 TRACE("iface %p, palette %p.\n", iface
, palette
);
5196 if (surface
->surface_desc
.ddsCaps
.dwCaps2
& DDSCAPS2_MIPMAPSUBLEVEL
)
5197 return DDERR_NOTONMIPMAPSUBLEVEL
;
5198 if (ddraw_surface_is_lost(surface
))
5200 WARN("Surface lost, returning DDERR_SURFACELOST.\n");
5201 return DDERR_SURFACELOST
;
5204 return ddraw_surface_set_palette(surface
, palette
);
5207 static HRESULT WINAPI
ddraw_surface4_SetPalette(IDirectDrawSurface4
*iface
, IDirectDrawPalette
*palette
)
5209 struct ddraw_surface
*surface
= impl_from_IDirectDrawSurface4(iface
);
5211 TRACE("iface %p, palette %p.\n", iface
, palette
);
5213 if (ddraw_surface_is_lost(surface
))
5215 WARN("Surface lost, returning DDERR_SURFACELOST.\n");
5216 return DDERR_SURFACELOST
;
5219 return ddraw_surface_set_palette(surface
, palette
);
5222 static HRESULT WINAPI
ddraw_surface3_SetPalette(IDirectDrawSurface3
*iface
, IDirectDrawPalette
*palette
)
5224 struct ddraw_surface
*surface
= impl_from_IDirectDrawSurface3(iface
);
5226 TRACE("iface %p, palette %p.\n", iface
, palette
);
5228 if (ddraw_surface_is_lost(surface
))
5230 WARN("Surface lost, returning DDERR_SURFACELOST.\n");
5231 return DDERR_SURFACELOST
;
5234 return ddraw_surface_set_palette(surface
, palette
);
5237 static HRESULT WINAPI
ddraw_surface2_SetPalette(IDirectDrawSurface2
*iface
, IDirectDrawPalette
*palette
)
5239 struct ddraw_surface
*surface
= impl_from_IDirectDrawSurface2(iface
);
5241 TRACE("iface %p, palette %p.\n", iface
, palette
);
5243 if (ddraw_surface_is_lost(surface
))
5245 WARN("Surface lost, returning DDERR_SURFACELOST.\n");
5246 return DDERR_SURFACELOST
;
5249 return ddraw_surface_set_palette(surface
, palette
);
5252 static HRESULT WINAPI
ddraw_surface1_SetPalette(IDirectDrawSurface
*iface
, IDirectDrawPalette
*palette
)
5254 struct ddraw_surface
*surface
= impl_from_IDirectDrawSurface(iface
);
5256 TRACE("iface %p, palette %p.\n", iface
, palette
);
5258 if (ddraw_surface_is_lost(surface
))
5260 WARN("Surface lost, returning DDERR_SURFACELOST.\n");
5261 return DDERR_SURFACELOST
;
5264 return ddraw_surface_set_palette(surface
, palette
);
5267 /**********************************************************
5268 * IDirectDrawGammaControl::GetGammaRamp
5270 * Returns the current gamma ramp for a surface
5274 * gamma_ramp: Address to write the ramp to
5278 * DDERR_INVALIDPARAMS if gamma_ramp is NULL
5280 **********************************************************/
5281 static HRESULT WINAPI
ddraw_gamma_control_GetGammaRamp(IDirectDrawGammaControl
*iface
,
5282 DWORD flags
, DDGAMMARAMP
*gamma_ramp
)
5284 struct ddraw_surface
*surface
= impl_from_IDirectDrawGammaControl(iface
);
5286 TRACE("iface %p, flags %#lx, gamma_ramp %p.\n", iface
, flags
, gamma_ramp
);
5290 WARN("Invalid gamma_ramp passed.\n");
5291 return DDERR_INVALIDPARAMS
;
5294 wined3d_mutex_lock();
5295 if (surface
->surface_desc
.ddsCaps
.dwCaps
& DDSCAPS_PRIMARYSURFACE
)
5297 /* Note: DDGAMMARAMP is compatible with struct wined3d_gamma_ramp. */
5298 wined3d_device_get_gamma_ramp(surface
->ddraw
->wined3d_device
, 0, (struct wined3d_gamma_ramp
*)gamma_ramp
);
5302 ERR("Not implemented for non-primary surfaces.\n");
5304 wined3d_mutex_unlock();
5309 /**********************************************************
5310 * IDirectDrawGammaControl::SetGammaRamp
5312 * Sets the red, green and blue gamma ramps for
5315 * flags: Can be DDSGR_CALIBRATE to request calibration
5316 * gamma_ramp: Structure containing the new gamma ramp
5320 * DDERR_INVALIDPARAMS if gamma_ramp is NULL
5322 **********************************************************/
5323 static HRESULT WINAPI
ddraw_gamma_control_SetGammaRamp(IDirectDrawGammaControl
*iface
,
5324 DWORD flags
, DDGAMMARAMP
*gamma_ramp
)
5326 struct ddraw_surface
*surface
= impl_from_IDirectDrawGammaControl(iface
);
5328 TRACE("iface %p, flags %#lx, gamma_ramp %p.\n", iface
, flags
, gamma_ramp
);
5332 WARN("Invalid gamma_ramp passed.\n");
5333 return DDERR_INVALIDPARAMS
;
5336 wined3d_mutex_lock();
5337 if (surface
->surface_desc
.ddsCaps
.dwCaps
& DDSCAPS_PRIMARYSURFACE
)
5339 /* Note: DDGAMMARAMP is compatible with struct wined3d_gamma_ramp. */
5340 wined3d_device_set_gamma_ramp(surface
->ddraw
->wined3d_device
,
5341 0, flags
, (struct wined3d_gamma_ramp
*)gamma_ramp
);
5345 ERR("Not implemented for non-primary surfaces.\n");
5347 wined3d_mutex_unlock();
5352 /*****************************************************************************
5353 * IDirect3DTexture2::PaletteChanged
5355 * Informs the texture about a palette change
5358 * start: Start index of the change
5359 * count: The number of changed entries
5362 * D3D_OK, because it's a stub
5364 *****************************************************************************/
5365 static HRESULT WINAPI
d3d_texture2_PaletteChanged(IDirect3DTexture2
*iface
, DWORD start
, DWORD count
)
5367 FIXME("iface %p, start %lu, count %lu stub!\n", iface
, start
, count
);
5372 static HRESULT WINAPI
d3d_texture1_PaletteChanged(IDirect3DTexture
*iface
, DWORD start
, DWORD count
)
5374 struct ddraw_surface
*surface
= impl_from_IDirect3DTexture(iface
);
5376 TRACE("iface %p, start %lu, count %lu.\n", iface
, start
, count
);
5378 return d3d_texture2_PaletteChanged(&surface
->IDirect3DTexture2_iface
, start
, count
);
5381 /*****************************************************************************
5382 * IDirect3DTexture::Unload
5384 * DX5 SDK: "The IDirect3DTexture2::Unload method is not implemented
5390 *****************************************************************************/
5391 static HRESULT WINAPI
d3d_texture1_Unload(IDirect3DTexture
*iface
)
5393 WARN("iface %p. Not implemented.\n", iface
);
5395 return DDERR_UNSUPPORTED
;
5398 /*****************************************************************************
5399 * IDirect3DTexture2::GetHandle
5401 * Returns handle for the texture.
5404 * device: Device this handle is assigned to
5405 * handle: Address to store the handle at.
5410 *****************************************************************************/
5411 static HRESULT WINAPI
d3d_texture2_GetHandle(IDirect3DTexture2
*iface
,
5412 IDirect3DDevice2
*device
, D3DTEXTUREHANDLE
*handle
)
5414 struct ddraw_surface
*surface
= impl_from_IDirect3DTexture2(iface
);
5415 struct d3d_device
*device_impl
= unsafe_impl_from_IDirect3DDevice2(device
);
5417 TRACE("iface %p, device %p, handle %p.\n", iface
, device
, handle
);
5419 wined3d_mutex_lock();
5421 if (!surface
->Handle
)
5423 DWORD h
= ddraw_allocate_handle(&device_impl
->handle_table
, surface
, DDRAW_HANDLE_SURFACE
);
5424 if (h
== DDRAW_INVALID_HANDLE
)
5426 ERR("Failed to allocate a texture handle.\n");
5427 wined3d_mutex_unlock();
5428 return DDERR_OUTOFMEMORY
;
5431 surface
->Handle
= h
+ 1;
5434 TRACE("Returning handle %08lx.\n", surface
->Handle
);
5435 *handle
= surface
->Handle
;
5437 wined3d_mutex_unlock();
5442 static HRESULT WINAPI
d3d_texture1_GetHandle(IDirect3DTexture
*iface
,
5443 IDirect3DDevice
*device
, D3DTEXTUREHANDLE
*handle
)
5445 struct ddraw_surface
*surface
= impl_from_IDirect3DTexture(iface
);
5446 struct d3d_device
*device_impl
= unsafe_impl_from_IDirect3DDevice(device
);
5448 TRACE("iface %p, device %p, handle %p.\n", iface
, device
, handle
);
5450 return d3d_texture2_GetHandle(&surface
->IDirect3DTexture2_iface
,
5451 device_impl
? &device_impl
->IDirect3DDevice2_iface
: NULL
, handle
);
5454 /*****************************************************************************
5455 * get_sub_mimaplevel
5457 * Helper function that returns the next mipmap level
5459 * tex_ptr: Surface of which to return the next level
5461 *****************************************************************************/
5462 static struct ddraw_surface
*get_sub_mimaplevel(struct ddraw_surface
*surface
)
5464 /* Now go down the mipmap chain to the next surface */
5465 static DDSCAPS2 mipmap_caps
= { DDSCAPS_MIPMAP
| DDSCAPS_TEXTURE
, 0, 0, {0} };
5466 IDirectDrawSurface7
*next_level
;
5469 hr
= ddraw_surface7_GetAttachedSurface(&surface
->IDirectDrawSurface7_iface
, &mipmap_caps
, &next_level
);
5470 if (FAILED(hr
)) return NULL
;
5472 ddraw_surface7_Release(next_level
);
5474 return impl_from_IDirectDrawSurface7(next_level
);
5477 /*****************************************************************************
5478 * IDirect3DTexture2::Load
5480 * Loads a texture created with the DDSCAPS_ALLOCONLOAD
5482 * This function isn't relayed to WineD3D because the whole interface is
5483 * implemented in DDraw only. For speed improvements an implementation which
5484 * takes OpenGL more into account could be placed into WineD3D.
5487 * src_texture: Address of the texture to load
5491 * D3DERR_TEXTURE_LOAD_FAILED.
5493 *****************************************************************************/
5494 static HRESULT WINAPI
d3d_texture2_Load(IDirect3DTexture2
*iface
, IDirect3DTexture2
*src_texture
)
5496 struct ddraw_surface
*dst_surface
= impl_from_IDirect3DTexture2(iface
);
5497 struct ddraw_surface
*src_surface
= unsafe_impl_from_IDirect3DTexture2(src_texture
);
5498 struct wined3d_resource
*dst_resource
, *src_resource
;
5501 TRACE("iface %p, src_texture %p.\n", iface
, src_texture
);
5503 if (src_surface
== dst_surface
)
5505 TRACE("copying surface %p to surface %p, why?\n", src_surface
, dst_surface
);
5509 wined3d_mutex_lock();
5511 dst_resource
= wined3d_texture_get_resource(ddraw_surface_get_default_texture(dst_surface
, DDRAW_SURFACE_WRITE
));
5512 src_resource
= wined3d_texture_get_resource(ddraw_surface_get_default_texture(src_surface
, DDRAW_SURFACE_READ
));
5514 if (((src_surface
->surface_desc
.ddsCaps
.dwCaps
& DDSCAPS_MIPMAP
)
5515 != (dst_surface
->surface_desc
.ddsCaps
.dwCaps
& DDSCAPS_MIPMAP
))
5516 || (src_surface
->surface_desc
.u2
.dwMipMapCount
!= dst_surface
->surface_desc
.u2
.dwMipMapCount
))
5518 ERR("Trying to load surfaces with different mip-map counts.\n");
5523 struct ddraw_palette
*dst_pal
, *src_pal
;
5524 DDSURFACEDESC
*src_desc
, *dst_desc
;
5526 TRACE("Copying surface %p to surface %p.\n", src_surface
, dst_surface
);
5528 /* Suppress the ALLOCONLOAD flag */
5529 dst_surface
->surface_desc
.ddsCaps
.dwCaps
&= ~DDSCAPS_ALLOCONLOAD
;
5531 /* Get the palettes */
5532 dst_pal
= dst_surface
->palette
;
5533 src_pal
= src_surface
->palette
;
5537 PALETTEENTRY palent
[256];
5541 wined3d_mutex_unlock();
5542 return DDERR_NOPALETTEATTACHED
;
5544 IDirectDrawPalette_GetEntries(&src_pal
->IDirectDrawPalette_iface
, 0, 0, 256, palent
);
5545 IDirectDrawPalette_SetEntries(&dst_pal
->IDirectDrawPalette_iface
, 0, 0, 256, palent
);
5548 /* Copy one surface on the other */
5549 dst_desc
= (DDSURFACEDESC
*)&(dst_surface
->surface_desc
);
5550 src_desc
= (DDSURFACEDESC
*)&(src_surface
->surface_desc
);
5552 if ((src_desc
->dwWidth
!= dst_desc
->dwWidth
) || (src_desc
->dwHeight
!= dst_desc
->dwHeight
))
5554 /* Should also check for same pixel format, u1.lPitch, ... */
5555 ERR("Error in surface sizes.\n");
5556 wined3d_mutex_unlock();
5557 return D3DERR_TEXTURE_LOAD_FAILED
;
5561 struct wined3d_map_desc src_map_desc
, dst_map_desc
;
5563 /* Copy the src blit color key if the source has one, don't erase
5564 * the destination's ckey if the source has none */
5565 if (src_desc
->dwFlags
& DDSD_CKSRCBLT
)
5567 IDirectDrawSurface7_SetColorKey(&dst_surface
->IDirectDrawSurface7_iface
,
5568 DDCKEY_SRCBLT
, &src_desc
->ddckCKSrcBlt
);
5571 if (FAILED(hr
= wined3d_resource_map(src_resource
,
5572 src_surface
->sub_resource_idx
, &src_map_desc
, NULL
, WINED3D_MAP_READ
)))
5574 ERR("Failed to lock source surface, hr %#lx.\n", hr
);
5575 wined3d_mutex_unlock();
5576 return D3DERR_TEXTURE_LOAD_FAILED
;
5579 if (FAILED(hr
= wined3d_resource_map(dst_resource
,
5580 dst_surface
->sub_resource_idx
, &dst_map_desc
, NULL
, WINED3D_MAP_WRITE
)))
5582 ERR("Failed to lock destination surface, hr %#lx.\n", hr
);
5583 wined3d_resource_unmap(src_resource
, src_surface
->sub_resource_idx
);
5584 wined3d_mutex_unlock();
5585 return D3DERR_TEXTURE_LOAD_FAILED
;
5588 if (dst_surface
->surface_desc
.u4
.ddpfPixelFormat
.dwFlags
& DDPF_FOURCC
)
5589 memcpy(dst_map_desc
.data
, src_map_desc
.data
, src_surface
->surface_desc
.u1
.dwLinearSize
);
5591 memcpy(dst_map_desc
.data
, src_map_desc
.data
, src_map_desc
.row_pitch
* src_desc
->dwHeight
);
5593 wined3d_resource_unmap(dst_resource
, dst_surface
->sub_resource_idx
);
5594 wined3d_resource_unmap(src_resource
, src_surface
->sub_resource_idx
);
5597 if (src_surface
->surface_desc
.ddsCaps
.dwCaps
& DDSCAPS_MIPMAP
)
5598 src_surface
= get_sub_mimaplevel(src_surface
);
5602 if (dst_surface
->surface_desc
.ddsCaps
.dwCaps
& DDSCAPS_MIPMAP
)
5603 dst_surface
= get_sub_mimaplevel(dst_surface
);
5607 if (!src_surface
|| !dst_surface
)
5609 if (src_surface
!= dst_surface
)
5610 ERR("Loading surface with different mipmap structure.\n");
5615 wined3d_mutex_unlock();
5620 static HRESULT WINAPI
d3d_texture1_Load(IDirect3DTexture
*iface
, IDirect3DTexture
*src_texture
)
5622 struct ddraw_surface
*dst_surface
= impl_from_IDirect3DTexture(iface
);
5623 struct ddraw_surface
*src_surface
= unsafe_impl_from_IDirect3DTexture(src_texture
);
5625 TRACE("iface %p, src_texture %p.\n", iface
, src_texture
);
5627 return d3d_texture2_Load(&dst_surface
->IDirect3DTexture2_iface
,
5628 src_surface
? &src_surface
->IDirect3DTexture2_iface
: NULL
);
5631 /*****************************************************************************
5633 *****************************************************************************/
5635 /* Some windowed mode wrappers expect this vtbl to be writable. */
5636 static struct IDirectDrawSurface7Vtbl ddraw_surface7_vtbl
=
5639 ddraw_surface7_QueryInterface
,
5640 ddraw_surface7_AddRef
,
5641 ddraw_surface7_Release
,
5642 /* IDirectDrawSurface */
5643 ddraw_surface7_AddAttachedSurface
,
5644 ddraw_surface7_AddOverlayDirtyRect
,
5646 ddraw_surface7_BltBatch
,
5647 ddraw_surface7_BltFast
,
5648 ddraw_surface7_DeleteAttachedSurface
,
5649 ddraw_surface7_EnumAttachedSurfaces
,
5650 ddraw_surface7_EnumOverlayZOrders
,
5651 ddraw_surface7_Flip
,
5652 ddraw_surface7_GetAttachedSurface
,
5653 ddraw_surface7_GetBltStatus
,
5654 ddraw_surface7_GetCaps
,
5655 ddraw_surface7_GetClipper
,
5656 ddraw_surface7_GetColorKey
,
5657 ddraw_surface7_GetDC
,
5658 ddraw_surface7_GetFlipStatus
,
5659 ddraw_surface7_GetOverlayPosition
,
5660 ddraw_surface7_GetPalette
,
5661 ddraw_surface7_GetPixelFormat
,
5662 ddraw_surface7_GetSurfaceDesc
,
5663 ddraw_surface7_Initialize
,
5664 ddraw_surface7_IsLost
,
5665 ddraw_surface7_Lock
,
5666 ddraw_surface7_ReleaseDC
,
5667 ddraw_surface7_Restore
,
5668 ddraw_surface7_SetClipper
,
5669 ddraw_surface7_SetColorKey
,
5670 ddraw_surface7_SetOverlayPosition
,
5671 ddraw_surface7_SetPalette
,
5672 ddraw_surface7_Unlock
,
5673 ddraw_surface7_UpdateOverlay
,
5674 ddraw_surface7_UpdateOverlayDisplay
,
5675 ddraw_surface7_UpdateOverlayZOrder
,
5676 /* IDirectDrawSurface2 */
5677 ddraw_surface7_GetDDInterface
,
5678 ddraw_surface7_PageLock
,
5679 ddraw_surface7_PageUnlock
,
5680 /* IDirectDrawSurface3 */
5681 ddraw_surface7_SetSurfaceDesc
,
5682 /* IDirectDrawSurface4 */
5683 ddraw_surface7_SetPrivateData
,
5684 ddraw_surface7_GetPrivateData
,
5685 ddraw_surface7_FreePrivateData
,
5686 ddraw_surface7_GetUniquenessValue
,
5687 ddraw_surface7_ChangeUniquenessValue
,
5688 /* IDirectDrawSurface7 */
5689 ddraw_surface7_SetPriority
,
5690 ddraw_surface7_GetPriority
,
5691 ddraw_surface7_SetLOD
,
5692 ddraw_surface7_GetLOD
,
5695 /* Some windowed mode wrappers expect this vtbl to be writable. */
5696 static struct IDirectDrawSurface4Vtbl ddraw_surface4_vtbl
=
5699 ddraw_surface4_QueryInterface
,
5700 ddraw_surface4_AddRef
,
5701 ddraw_surface4_Release
,
5702 /* IDirectDrawSurface */
5703 ddraw_surface4_AddAttachedSurface
,
5704 ddraw_surface4_AddOverlayDirtyRect
,
5706 ddraw_surface4_BltBatch
,
5707 ddraw_surface4_BltFast
,
5708 ddraw_surface4_DeleteAttachedSurface
,
5709 ddraw_surface4_EnumAttachedSurfaces
,
5710 ddraw_surface4_EnumOverlayZOrders
,
5711 ddraw_surface4_Flip
,
5712 ddraw_surface4_GetAttachedSurface
,
5713 ddraw_surface4_GetBltStatus
,
5714 ddraw_surface4_GetCaps
,
5715 ddraw_surface4_GetClipper
,
5716 ddraw_surface4_GetColorKey
,
5717 ddraw_surface4_GetDC
,
5718 ddraw_surface4_GetFlipStatus
,
5719 ddraw_surface4_GetOverlayPosition
,
5720 ddraw_surface4_GetPalette
,
5721 ddraw_surface4_GetPixelFormat
,
5722 ddraw_surface4_GetSurfaceDesc
,
5723 ddraw_surface4_Initialize
,
5724 ddraw_surface4_IsLost
,
5725 ddraw_surface4_Lock
,
5726 ddraw_surface4_ReleaseDC
,
5727 ddraw_surface4_Restore
,
5728 ddraw_surface4_SetClipper
,
5729 ddraw_surface4_SetColorKey
,
5730 ddraw_surface4_SetOverlayPosition
,
5731 ddraw_surface4_SetPalette
,
5732 ddraw_surface4_Unlock
,
5733 ddraw_surface4_UpdateOverlay
,
5734 ddraw_surface4_UpdateOverlayDisplay
,
5735 ddraw_surface4_UpdateOverlayZOrder
,
5736 /* IDirectDrawSurface2 */
5737 ddraw_surface4_GetDDInterface
,
5738 ddraw_surface4_PageLock
,
5739 ddraw_surface4_PageUnlock
,
5740 /* IDirectDrawSurface3 */
5741 ddraw_surface4_SetSurfaceDesc
,
5742 /* IDirectDrawSurface4 */
5743 ddraw_surface4_SetPrivateData
,
5744 ddraw_surface4_GetPrivateData
,
5745 ddraw_surface4_FreePrivateData
,
5746 ddraw_surface4_GetUniquenessValue
,
5747 ddraw_surface4_ChangeUniquenessValue
,
5750 /* Some windowed mode wrappers expect this vtbl to be writable. */
5751 static struct IDirectDrawSurface3Vtbl ddraw_surface3_vtbl
=
5754 ddraw_surface3_QueryInterface
,
5755 ddraw_surface3_AddRef
,
5756 ddraw_surface3_Release
,
5757 /* IDirectDrawSurface */
5758 ddraw_surface3_AddAttachedSurface
,
5759 ddraw_surface3_AddOverlayDirtyRect
,
5761 ddraw_surface3_BltBatch
,
5762 ddraw_surface3_BltFast
,
5763 ddraw_surface3_DeleteAttachedSurface
,
5764 ddraw_surface3_EnumAttachedSurfaces
,
5765 ddraw_surface3_EnumOverlayZOrders
,
5766 ddraw_surface3_Flip
,
5767 ddraw_surface3_GetAttachedSurface
,
5768 ddraw_surface3_GetBltStatus
,
5769 ddraw_surface3_GetCaps
,
5770 ddraw_surface3_GetClipper
,
5771 ddraw_surface3_GetColorKey
,
5772 ddraw_surface3_GetDC
,
5773 ddraw_surface3_GetFlipStatus
,
5774 ddraw_surface3_GetOverlayPosition
,
5775 ddraw_surface3_GetPalette
,
5776 ddraw_surface3_GetPixelFormat
,
5777 ddraw_surface3_GetSurfaceDesc
,
5778 ddraw_surface3_Initialize
,
5779 ddraw_surface3_IsLost
,
5780 ddraw_surface3_Lock
,
5781 ddraw_surface3_ReleaseDC
,
5782 ddraw_surface3_Restore
,
5783 ddraw_surface3_SetClipper
,
5784 ddraw_surface3_SetColorKey
,
5785 ddraw_surface3_SetOverlayPosition
,
5786 ddraw_surface3_SetPalette
,
5787 ddraw_surface3_Unlock
,
5788 ddraw_surface3_UpdateOverlay
,
5789 ddraw_surface3_UpdateOverlayDisplay
,
5790 ddraw_surface3_UpdateOverlayZOrder
,
5791 /* IDirectDrawSurface2 */
5792 ddraw_surface3_GetDDInterface
,
5793 ddraw_surface3_PageLock
,
5794 ddraw_surface3_PageUnlock
,
5795 /* IDirectDrawSurface3 */
5796 ddraw_surface3_SetSurfaceDesc
,
5799 /* Some windowed mode wrappers expect this vtbl to be writable. */
5800 static struct IDirectDrawSurface2Vtbl ddraw_surface2_vtbl
=
5803 ddraw_surface2_QueryInterface
,
5804 ddraw_surface2_AddRef
,
5805 ddraw_surface2_Release
,
5806 /* IDirectDrawSurface */
5807 ddraw_surface2_AddAttachedSurface
,
5808 ddraw_surface2_AddOverlayDirtyRect
,
5810 ddraw_surface2_BltBatch
,
5811 ddraw_surface2_BltFast
,
5812 ddraw_surface2_DeleteAttachedSurface
,
5813 ddraw_surface2_EnumAttachedSurfaces
,
5814 ddraw_surface2_EnumOverlayZOrders
,
5815 ddraw_surface2_Flip
,
5816 ddraw_surface2_GetAttachedSurface
,
5817 ddraw_surface2_GetBltStatus
,
5818 ddraw_surface2_GetCaps
,
5819 ddraw_surface2_GetClipper
,
5820 ddraw_surface2_GetColorKey
,
5821 ddraw_surface2_GetDC
,
5822 ddraw_surface2_GetFlipStatus
,
5823 ddraw_surface2_GetOverlayPosition
,
5824 ddraw_surface2_GetPalette
,
5825 ddraw_surface2_GetPixelFormat
,
5826 ddraw_surface2_GetSurfaceDesc
,
5827 ddraw_surface2_Initialize
,
5828 ddraw_surface2_IsLost
,
5829 ddraw_surface2_Lock
,
5830 ddraw_surface2_ReleaseDC
,
5831 ddraw_surface2_Restore
,
5832 ddraw_surface2_SetClipper
,
5833 ddraw_surface2_SetColorKey
,
5834 ddraw_surface2_SetOverlayPosition
,
5835 ddraw_surface2_SetPalette
,
5836 ddraw_surface2_Unlock
,
5837 ddraw_surface2_UpdateOverlay
,
5838 ddraw_surface2_UpdateOverlayDisplay
,
5839 ddraw_surface2_UpdateOverlayZOrder
,
5840 /* IDirectDrawSurface2 */
5841 ddraw_surface2_GetDDInterface
,
5842 ddraw_surface2_PageLock
,
5843 ddraw_surface2_PageUnlock
,
5846 /* Bad Mojo Redux expects this vtbl to be writable. */
5847 static struct IDirectDrawSurfaceVtbl ddraw_surface1_vtbl
=
5850 ddraw_surface1_QueryInterface
,
5851 ddraw_surface1_AddRef
,
5852 ddraw_surface1_Release
,
5853 /* IDirectDrawSurface */
5854 ddraw_surface1_AddAttachedSurface
,
5855 ddraw_surface1_AddOverlayDirtyRect
,
5857 ddraw_surface1_BltBatch
,
5858 ddraw_surface1_BltFast
,
5859 ddraw_surface1_DeleteAttachedSurface
,
5860 ddraw_surface1_EnumAttachedSurfaces
,
5861 ddraw_surface1_EnumOverlayZOrders
,
5862 ddraw_surface1_Flip
,
5863 ddraw_surface1_GetAttachedSurface
,
5864 ddraw_surface1_GetBltStatus
,
5865 ddraw_surface1_GetCaps
,
5866 ddraw_surface1_GetClipper
,
5867 ddraw_surface1_GetColorKey
,
5868 ddraw_surface1_GetDC
,
5869 ddraw_surface1_GetFlipStatus
,
5870 ddraw_surface1_GetOverlayPosition
,
5871 ddraw_surface1_GetPalette
,
5872 ddraw_surface1_GetPixelFormat
,
5873 ddraw_surface1_GetSurfaceDesc
,
5874 ddraw_surface1_Initialize
,
5875 ddraw_surface1_IsLost
,
5876 ddraw_surface1_Lock
,
5877 ddraw_surface1_ReleaseDC
,
5878 ddraw_surface1_Restore
,
5879 ddraw_surface1_SetClipper
,
5880 ddraw_surface1_SetColorKey
,
5881 ddraw_surface1_SetOverlayPosition
,
5882 ddraw_surface1_SetPalette
,
5883 ddraw_surface1_Unlock
,
5884 ddraw_surface1_UpdateOverlay
,
5885 ddraw_surface1_UpdateOverlayDisplay
,
5886 ddraw_surface1_UpdateOverlayZOrder
,
5889 static const struct IDirectDrawGammaControlVtbl ddraw_gamma_control_vtbl
=
5891 ddraw_gamma_control_QueryInterface
,
5892 ddraw_gamma_control_AddRef
,
5893 ddraw_gamma_control_Release
,
5894 ddraw_gamma_control_GetGammaRamp
,
5895 ddraw_gamma_control_SetGammaRamp
,
5898 static const struct IDirect3DTexture2Vtbl d3d_texture2_vtbl
=
5900 d3d_texture2_QueryInterface
,
5901 d3d_texture2_AddRef
,
5902 d3d_texture2_Release
,
5903 d3d_texture2_GetHandle
,
5904 d3d_texture2_PaletteChanged
,
5908 static const struct IDirect3DTextureVtbl d3d_texture1_vtbl
=
5910 d3d_texture1_QueryInterface
,
5911 d3d_texture1_AddRef
,
5912 d3d_texture1_Release
,
5913 d3d_texture1_Initialize
,
5914 d3d_texture1_GetHandle
,
5915 d3d_texture1_PaletteChanged
,
5917 d3d_texture1_Unload
,
5920 /* Some games (e.g. Tomb Raider 3) pass the wrong version of the
5921 * IDirectDrawSurface interface to ddraw methods. */
5922 struct ddraw_surface
*unsafe_impl_from_IDirectDrawSurface7(IDirectDrawSurface7
*iface
)
5924 if (!iface
) return NULL
;
5925 if (iface
->lpVtbl
!= &ddraw_surface7_vtbl
)
5927 HRESULT hr
= IDirectDrawSurface7_QueryInterface(iface
, &IID_IDirectDrawSurface7
, (void **)&iface
);
5930 WARN("Object %p doesn't expose interface IDirectDrawSurface7.\n", iface
);
5933 IDirectDrawSurface7_Release(iface
);
5935 return CONTAINING_RECORD(iface
, struct ddraw_surface
, IDirectDrawSurface7_iface
);
5938 struct ddraw_surface
*unsafe_impl_from_IDirectDrawSurface4(IDirectDrawSurface4
*iface
)
5940 if (!iface
) return NULL
;
5941 if (iface
->lpVtbl
!= &ddraw_surface4_vtbl
)
5943 HRESULT hr
= IDirectDrawSurface4_QueryInterface(iface
, &IID_IDirectDrawSurface4
, (void **)&iface
);
5946 WARN("Object %p doesn't expose interface IDirectDrawSurface4.\n", iface
);
5949 IDirectDrawSurface4_Release(iface
);
5951 return CONTAINING_RECORD(iface
, struct ddraw_surface
, IDirectDrawSurface4_iface
);
5954 static struct ddraw_surface
*unsafe_impl_from_IDirectDrawSurface3(IDirectDrawSurface3
*iface
)
5956 if (!iface
) return NULL
;
5957 if (iface
->lpVtbl
!= &ddraw_surface3_vtbl
)
5959 HRESULT hr
= IDirectDrawSurface3_QueryInterface(iface
, &IID_IDirectDrawSurface3
, (void **)&iface
);
5962 WARN("Object %p doesn't expose interface IDirectDrawSurface3.\n", iface
);
5965 IDirectDrawSurface3_Release(iface
);
5967 return CONTAINING_RECORD(iface
, struct ddraw_surface
, IDirectDrawSurface3_iface
);
5970 static struct ddraw_surface
*unsafe_impl_from_IDirectDrawSurface2(IDirectDrawSurface2
*iface
)
5972 if (!iface
) return NULL
;
5973 if (iface
->lpVtbl
!= &ddraw_surface2_vtbl
)
5975 HRESULT hr
= IDirectDrawSurface2_QueryInterface(iface
, &IID_IDirectDrawSurface2
, (void **)&iface
);
5978 WARN("Object %p doesn't expose interface IDirectDrawSurface2.\n", iface
);
5981 IDirectDrawSurface2_Release(iface
);
5983 return CONTAINING_RECORD(iface
, struct ddraw_surface
, IDirectDrawSurface2_iface
);
5986 struct ddraw_surface
*unsafe_impl_from_IDirectDrawSurface(IDirectDrawSurface
*iface
)
5988 if (!iface
) return NULL
;
5989 if (iface
->lpVtbl
!= &ddraw_surface1_vtbl
)
5991 HRESULT hr
= IDirectDrawSurface_QueryInterface(iface
, &IID_IDirectDrawSurface
, (void **)&iface
);
5994 WARN("Object %p doesn't expose interface IDirectDrawSurface.\n", iface
);
5997 IDirectDrawSurface_Release(iface
);
5999 return CONTAINING_RECORD(iface
, struct ddraw_surface
, IDirectDrawSurface_iface
);
6002 struct ddraw_surface
*unsafe_impl_from_IDirect3DTexture2(IDirect3DTexture2
*iface
)
6004 if (!iface
) return NULL
;
6005 assert(iface
->lpVtbl
== &d3d_texture2_vtbl
);
6006 return CONTAINING_RECORD(iface
, struct ddraw_surface
, IDirect3DTexture2_iface
);
6009 struct ddraw_surface
*unsafe_impl_from_IDirect3DTexture(IDirect3DTexture
*iface
)
6011 if (!iface
) return NULL
;
6012 assert(iface
->lpVtbl
== &d3d_texture1_vtbl
);
6013 return CONTAINING_RECORD(iface
, struct ddraw_surface
, IDirect3DTexture_iface
);
6016 static void STDMETHODCALLTYPE
ddraw_surface_wined3d_object_destroyed(void *parent
)
6018 struct ddraw_surface
*surface
= parent
;
6020 TRACE("surface %p.\n", surface
);
6022 /* This shouldn't happen, ddraw_surface_release_iface() should prevent the
6023 * surface from being destroyed in this case. */
6024 if (surface
->first_attached
!= surface
)
6025 ERR("Surface is still attached to surface %p.\n", surface
->first_attached
);
6027 while (surface
->next_attached
)
6028 if (FAILED(ddraw_surface_delete_attached_surface(surface
,
6029 surface
->next_attached
, surface
->next_attached
->attached_iface
)))
6030 ERR("DeleteAttachedSurface failed.\n");
6032 /* Having a texture handle set implies that the device still exists. */
6033 if (surface
->Handle
)
6034 ddraw_free_handle(&surface
->ddraw
->d3ddevice
->handle_table
, surface
->Handle
- 1, DDRAW_HANDLE_SURFACE
);
6036 /* Reduce the ddraw surface count. */
6037 list_remove(&surface
->surface_list_entry
);
6039 if (surface
->clipper
&& ddraw_clipper_is_valid(surface
->clipper
))
6040 IDirectDrawClipper_Release(&surface
->clipper
->IDirectDrawClipper_iface
);
6042 if (surface
== surface
->ddraw
->primary
)
6044 surface
->ddraw
->primary
= NULL
;
6045 surface
->ddraw
->gdi_surface
= NULL
;
6048 wined3d_private_store_cleanup(&surface
->private_store
);
6050 if (surface
->draw_texture
)
6051 wined3d_texture_decref(surface
->wined3d_texture
);
6056 static const struct wined3d_parent_ops ddraw_surface_wined3d_parent_ops
=
6058 ddraw_surface_wined3d_object_destroyed
,
6061 static void ddraw_surface_init(struct ddraw_surface
*surface
, struct ddraw
*ddraw
,
6062 struct wined3d_texture
*wined3d_texture
, unsigned int sub_resource_idx
)
6064 struct ddraw_texture
*texture
= wined3d_texture_get_parent(wined3d_texture
);
6065 unsigned int version
= texture
->version
;
6067 surface
->IDirectDrawSurface7_iface
.lpVtbl
= &ddraw_surface7_vtbl
;
6068 surface
->IDirectDrawSurface4_iface
.lpVtbl
= &ddraw_surface4_vtbl
;
6069 surface
->IDirectDrawSurface3_iface
.lpVtbl
= &ddraw_surface3_vtbl
;
6070 surface
->IDirectDrawSurface2_iface
.lpVtbl
= &ddraw_surface2_vtbl
;
6071 surface
->IDirectDrawSurface_iface
.lpVtbl
= &ddraw_surface1_vtbl
;
6072 surface
->IDirectDrawGammaControl_iface
.lpVtbl
= &ddraw_gamma_control_vtbl
;
6073 surface
->IDirect3DTexture2_iface
.lpVtbl
= &d3d_texture2_vtbl
;
6074 surface
->IDirect3DTexture_iface
.lpVtbl
= &d3d_texture1_vtbl
;
6075 surface
->iface_count
= 1;
6076 surface
->version
= version
;
6077 surface
->ddraw
= ddraw
;
6082 surface
->texture_outer
= (IUnknown
*)&surface
->IDirectDrawSurface7_iface
;
6084 else if (version
== 4)
6087 surface
->texture_outer
= (IUnknown
*)&surface
->IDirectDrawSurface4_iface
;
6092 surface
->texture_outer
= (IUnknown
*)&surface
->IDirectDrawSurface_iface
;
6095 surface
->first_attached
= surface
;
6097 wined3d_texture_incref(surface
->wined3d_texture
= wined3d_texture
);
6098 surface
->sub_resource_idx
= sub_resource_idx
;
6099 surface
->texture_location
= DDRAW_SURFACE_LOCATION_DEFAULT
;
6101 wined3d_private_store_init(&surface
->private_store
);
6104 static void STDMETHODCALLTYPE
ddraw_texture_wined3d_object_destroyed(void *parent
)
6106 struct ddraw_texture
*texture
= parent
;
6108 TRACE("texture %p, texture_memory %p.\n", texture
, texture
->texture_memory
);
6110 heap_free(texture
->texture_memory
);
6114 static const struct wined3d_parent_ops ddraw_texture_wined3d_parent_ops
=
6116 ddraw_texture_wined3d_object_destroyed
,
6119 static HRESULT CDECL
ddraw_reset_enum_callback(struct wined3d_resource
*resource
)
6124 static HRESULT
ddraw_surface_reserve_memory(struct wined3d_texture
*wined3d_texture
,
6125 unsigned int sub_resource_count
)
6127 static const unsigned int extra_size
= 0x10000;
6129 struct ddraw_texture
*texture
= wined3d_texture_get_parent(wined3d_texture
);
6130 struct wined3d_resource_desc resource_desc
;
6131 struct wined3d_sub_resource_desc desc
;
6132 unsigned int pitch
, slice_pitch
;
6133 HRESULT hr
= WINED3D_OK
;
6134 unsigned int offset
, i
;
6136 wined3d_resource_get_desc(wined3d_texture_get_resource(wined3d_texture
), &resource_desc
);
6137 if (!(texture
->texture_memory
= heap_alloc_zero(resource_desc
.size
+ extra_size
)))
6139 ERR("Out of memory.\n");
6140 return E_OUTOFMEMORY
;
6142 TRACE("texture->texture_memory %p.\n", texture
->texture_memory
);
6145 for (i
= 0; i
< sub_resource_count
; ++i
)
6147 if (FAILED(hr
= wined3d_texture_get_sub_resource_desc(wined3d_texture
, i
, &desc
)))
6149 ERR("Subresource %u not found.\n", i
);
6150 heap_free(texture
->texture_memory
);
6151 texture
->texture_memory
= NULL
;
6154 wined3d_texture_get_pitch(wined3d_texture
, i
, &pitch
, &slice_pitch
);
6156 if (FAILED(hr
= wined3d_texture_update_desc(wined3d_texture
, i
,
6157 desc
.width
, desc
.height
, resource_desc
.format
,
6158 desc
.multisample_type
, desc
.multisample_quality
,
6159 (BYTE
*)texture
->texture_memory
+ offset
, pitch
)))
6161 heap_free(texture
->texture_memory
);
6162 texture
->texture_memory
= NULL
;
6165 offset
+= desc
.size
;
6170 static void wined3d_resource_desc_from_ddraw(struct ddraw
*ddraw
,
6171 struct wined3d_resource_desc
*wined3d_desc
, const DDSURFACEDESC2
*desc
)
6173 const DWORD caps
= desc
->ddsCaps
.dwCaps
;
6174 const DWORD caps2
= desc
->ddsCaps
.dwCaps2
;
6176 wined3d_desc
->resource_type
= WINED3D_RTYPE_TEXTURE_2D
;
6177 wined3d_desc
->format
= wined3dformat_from_ddrawformat(&desc
->u4
.ddpfPixelFormat
);
6178 wined3d_desc
->multisample_type
= WINED3D_MULTISAMPLE_NONE
;
6179 wined3d_desc
->multisample_quality
= 0;
6180 wined3d_desc
->usage
= WINED3DUSAGE_VIDMEM_ACCOUNTING
;
6181 wined3d_desc
->bind_flags
= 0;
6182 wined3d_desc
->access
= WINED3D_RESOURCE_ACCESS_GPU
| WINED3D_RESOURCE_ACCESS_MAP_R
| WINED3D_RESOURCE_ACCESS_MAP_W
;
6183 wined3d_desc
->width
= desc
->dwWidth
;
6184 wined3d_desc
->height
= desc
->dwHeight
;
6185 wined3d_desc
->depth
= 1;
6186 wined3d_desc
->size
= 0;
6188 if ((caps
& DDSCAPS_SYSTEMMEMORY
) && !(caps2
& (DDSCAPS2_TEXTUREMANAGE
| DDSCAPS2_D3DTEXTUREMANAGE
)))
6190 wined3d_desc
->access
= WINED3D_RESOURCE_ACCESS_CPU
6191 | WINED3D_RESOURCE_ACCESS_MAP_R
| WINED3D_RESOURCE_ACCESS_MAP_W
;
6195 if (!(ddraw
->flags
& DDRAW_NO3D
))
6197 if (caps
& DDSCAPS_TEXTURE
)
6198 wined3d_desc
->bind_flags
|= WINED3D_BIND_SHADER_RESOURCE
;
6199 if (caps
& DDSCAPS_ZBUFFER
)
6200 wined3d_desc
->bind_flags
|= WINED3D_BIND_DEPTH_STENCIL
;
6201 else if (caps
& DDSCAPS_3DDEVICE
)
6202 wined3d_desc
->bind_flags
|= WINED3D_BIND_RENDER_TARGET
;
6205 if (caps2
& (DDSCAPS2_TEXTUREMANAGE
| DDSCAPS2_D3DTEXTUREMANAGE
))
6207 wined3d_desc
->bind_flags
&= ~WINED3D_BIND_RENDER_TARGET
;
6208 wined3d_desc
->access
|= WINED3D_RESOURCE_ACCESS_CPU
;
6209 wined3d_desc
->usage
|= WINED3DUSAGE_MANAGED
;
6211 else if (caps
& DDSCAPS_VIDEOMEMORY
)
6213 /* Dynamic resources can't be written by the GPU. */
6214 if (!(wined3d_desc
->bind_flags
& (WINED3D_BIND_RENDER_TARGET
| WINED3D_BIND_DEPTH_STENCIL
)))
6215 wined3d_desc
->usage
|= WINED3DUSAGE_DYNAMIC
;
6219 if (caps
& DDSCAPS_OVERLAY
)
6220 wined3d_desc
->usage
|= WINED3DUSAGE_OVERLAY
;
6222 if (caps
& DDSCAPS_OWNDC
)
6223 wined3d_desc
->usage
|= WINED3DUSAGE_OWNDC
;
6225 if (caps2
& DDSCAPS2_CUBEMAP
)
6226 wined3d_desc
->usage
|= WINED3DUSAGE_LEGACY_CUBEMAP
;
6229 static bool need_draw_texture(unsigned int draw_bind_flags
, const struct wined3d_resource_desc
*desc
)
6231 if (!draw_bind_flags
)
6234 /* If we have a GPU texture that includes all the necessary bind flags, we
6235 * don't need a separate draw texture. */
6236 if ((desc
->access
& WINED3D_RESOURCE_ACCESS_GPU
) && ((desc
->bind_flags
& draw_bind_flags
) == draw_bind_flags
))
6242 static HRESULT
ddraw_texture_init(struct ddraw_texture
*texture
, struct ddraw
*ddraw
,
6243 unsigned int layers
, unsigned int levels
, bool sysmem_fallback
, bool reserve_memory
)
6245 struct wined3d_device
*wined3d_device
= ddraw
->wined3d_device
;
6246 const DDSURFACEDESC2
*desc
= &texture
->surface_desc
;
6247 struct wined3d_texture
*draw_texture
= NULL
;
6248 struct wined3d_resource_desc wined3d_desc
;
6249 struct wined3d_texture
*wined3d_texture
;
6250 struct ddraw_surface
*parent
, *root
;
6251 unsigned int bind_flags
;
6252 unsigned int pitch
= 0;
6256 wined3d_resource_desc_from_ddraw(ddraw
, &wined3d_desc
, desc
);
6258 if (wined3d_desc
.format
== WINED3DFMT_UNKNOWN
)
6260 WARN("Unsupported / unknown pixelformat.\n");
6261 return DDERR_INVALIDPIXELFORMAT
;
6264 /* Validate the pitch. */
6265 if (desc
->dwFlags
& DDSD_LPSURFACE
)
6267 if (format_is_compressed(&desc
->u4
.ddpfPixelFormat
))
6269 if ((desc
->dwFlags
& DDSD_LINEARSIZE
)
6270 && desc
->u1
.dwLinearSize
< wined3d_calculate_format_pitch(ddraw
->wined3d_adapter
,
6271 wined3d_desc
.format
, wined3d_desc
.width
) * ((wined3d_desc
.height
+ 3) / 4))
6273 WARN("Invalid linear size %lu specified.\n", desc
->u1
.dwLinearSize
);
6274 return DDERR_INVALIDPARAMS
;
6279 if (desc
->u1
.lPitch
< wined3d_calculate_format_pitch(ddraw
->wined3d_adapter
,
6280 wined3d_desc
.format
, wined3d_desc
.width
) || desc
->u1
.lPitch
& 3)
6282 WARN("Invalid pitch %lu specified.\n", desc
->u1
.lPitch
);
6283 return DDERR_INVALIDPARAMS
;
6286 pitch
= desc
->u1
.lPitch
;
6291 if ((desc
->ddsCaps
.dwCaps2
& DDSCAPS2_CUBEMAP
)
6292 || (desc
->ddsCaps
.dwCaps
& DDSCAPS_TEXTURE
))
6293 bind_flags
|= WINED3D_BIND_SHADER_RESOURCE
;
6295 if (desc
->ddsCaps
.dwCaps
& DDSCAPS_ZBUFFER
)
6296 bind_flags
|= WINED3D_BIND_DEPTH_STENCIL
;
6297 else if (desc
->ddsCaps
.dwCaps
& DDSCAPS_3DDEVICE
)
6298 bind_flags
|= WINED3D_BIND_RENDER_TARGET
;
6300 if (need_draw_texture(bind_flags
, &wined3d_desc
))
6302 struct wined3d_resource_desc draw_texture_desc
;
6304 draw_texture_desc
= wined3d_desc
;
6305 draw_texture_desc
.bind_flags
= bind_flags
;
6306 draw_texture_desc
.access
= WINED3D_RESOURCE_ACCESS_GPU
;
6307 draw_texture_desc
.usage
= 0;
6309 if (FAILED(hr
= wined3d_texture_create(wined3d_device
, &draw_texture_desc
, layers
,
6310 levels
, 0, NULL
, texture
, &ddraw_texture_wined3d_parent_ops
, &draw_texture
)))
6311 WARN("Failed to create draw texture, hr %#lx.\n", hr
);
6314 /* Some applications assume surfaces will always be mapped at the same
6315 * address. Some of those also assume that this address is valid even when
6316 * the surface isn't mapped, and that updates done this way will be
6317 * visible on the screen. The game Nox is such an application,
6318 * Commandos: Behind Enemy Lines is another. Setting
6319 * WINED3D_TEXTURE_CREATE_GET_DC_LENIENT will ensure this. */
6323 if (FAILED(hr
= wined3d_texture_create(wined3d_device
, &wined3d_desc
,
6324 layers
, levels
, WINED3D_TEXTURE_CREATE_GET_DC_LENIENT
, NULL
,
6325 NULL
, &ddraw_null_wined3d_parent_ops
, &wined3d_texture
)))
6328 wined3d_resource_set_parent(wined3d_texture_get_resource(wined3d_texture
),
6329 texture
, &ddraw_null_wined3d_parent_ops
);
6333 if (FAILED(hr
= wined3d_texture_create(wined3d_device
, &wined3d_desc
,
6334 layers
, levels
, WINED3D_TEXTURE_CREATE_GET_DC_LENIENT
, NULL
,
6335 texture
, &ddraw_texture_wined3d_parent_ops
, &wined3d_texture
)))
6339 if ((desc
->dwFlags
& DDSD_LPSURFACE
) && FAILED(hr
= wined3d_texture_update_desc(wined3d_texture
, 0,
6340 wined3d_desc
.width
, wined3d_desc
.height
, wined3d_desc
.format
,
6341 WINED3D_MULTISAMPLE_NONE
, 0, desc
->lpSurface
, pitch
)))
6343 ERR("Failed to set surface memory, hr %#lx.\n", hr
);
6347 for (i
= 0; i
< layers
; ++i
)
6349 struct ddraw_surface
*prev_level
= NULL
;
6351 for (j
= 0; j
< levels
; ++j
)
6353 struct wined3d_sub_resource_desc wined3d_mip_desc
;
6354 unsigned int sub_resource_idx
= i
* levels
+ j
;
6355 unsigned int row_pitch
, slice_pitch
;
6356 struct ddraw_surface
*mip
;
6357 DDSURFACEDESC2
*mip_desc
;
6359 if (!(mip
= heap_alloc_zero(sizeof(*mip
))))
6361 hr
= DDERR_OUTOFVIDEOMEMORY
;
6365 ddraw_surface_init(mip
, ddraw
, wined3d_texture
, sub_resource_idx
);
6369 wined3d_texture_set_sub_resource_parent(draw_texture
, sub_resource_idx
,
6370 mip
, &ddraw_surface_wined3d_parent_ops
);
6371 wined3d_texture_set_sub_resource_parent(wined3d_texture
, sub_resource_idx
,
6372 mip
, &ddraw_null_wined3d_parent_ops
);
6373 wined3d_texture_incref(mip
->draw_texture
= draw_texture
);
6377 wined3d_texture_set_sub_resource_parent(wined3d_texture
, sub_resource_idx
,
6378 mip
, &ddraw_surface_wined3d_parent_ops
);
6381 mip
->sysmem_fallback
= sysmem_fallback
;
6382 mip_desc
= &mip
->surface_desc
;
6386 wined3d_texture_get_pitch(wined3d_texture
, j
, &row_pitch
, &slice_pitch
);
6387 if (format_is_compressed(&desc
->u4
.ddpfPixelFormat
))
6389 if (desc
->dwFlags
& DDSD_LPSURFACE
)
6390 mip_desc
->u1
.dwLinearSize
= ~0u;
6392 mip_desc
->u1
.dwLinearSize
= slice_pitch
;
6393 mip_desc
->dwFlags
|= DDSD_LINEARSIZE
;
6394 mip_desc
->dwFlags
&= ~DDSD_PITCH
;
6398 if (!(desc
->dwFlags
& DDSD_LPSURFACE
))
6399 mip_desc
->u1
.lPitch
= row_pitch
;
6400 mip_desc
->dwFlags
|= DDSD_PITCH
;
6401 mip_desc
->dwFlags
&= ~DDSD_LINEARSIZE
;
6404 mip_desc
->dwFlags
&= ~DDSD_LPSURFACE
;
6405 mip_desc
->lpSurface
= NULL
;
6407 if (desc
->ddsCaps
.dwCaps
& DDSCAPS_MIPMAP
)
6408 mip_desc
->u2
.dwMipMapCount
= levels
- j
;
6412 wined3d_texture_get_sub_resource_desc(wined3d_texture
, sub_resource_idx
, &wined3d_mip_desc
);
6413 mip_desc
->dwWidth
= wined3d_mip_desc
.width
;
6414 mip_desc
->dwHeight
= wined3d_mip_desc
.height
;
6416 mip_desc
->ddsCaps
.dwCaps2
|= DDSCAPS2_MIPMAPSUBLEVEL
;
6420 mip_desc
->ddsCaps
.dwCaps2
&= ~DDSCAPS2_MIPMAPSUBLEVEL
;
6423 if (mip_desc
->ddsCaps
.dwCaps2
& DDSCAPS2_CUBEMAP
)
6425 mip_desc
->ddsCaps
.dwCaps2
&= ~DDSCAPS2_CUBEMAP_ALLFACES
;
6429 case WINED3D_CUBEMAP_FACE_POSITIVE_X
:
6430 mip_desc
->ddsCaps
.dwCaps2
|= DDSCAPS2_CUBEMAP_POSITIVEX
;
6432 case WINED3D_CUBEMAP_FACE_NEGATIVE_X
:
6433 mip_desc
->ddsCaps
.dwCaps2
|= DDSCAPS2_CUBEMAP_NEGATIVEX
;
6435 case WINED3D_CUBEMAP_FACE_POSITIVE_Y
:
6436 mip_desc
->ddsCaps
.dwCaps2
|= DDSCAPS2_CUBEMAP_POSITIVEY
;
6438 case WINED3D_CUBEMAP_FACE_NEGATIVE_Y
:
6439 mip_desc
->ddsCaps
.dwCaps2
|= DDSCAPS2_CUBEMAP_NEGATIVEY
;
6441 case WINED3D_CUBEMAP_FACE_POSITIVE_Z
:
6442 mip_desc
->ddsCaps
.dwCaps2
|= DDSCAPS2_CUBEMAP_POSITIVEZ
;
6444 case WINED3D_CUBEMAP_FACE_NEGATIVE_Z
:
6445 mip_desc
->ddsCaps
.dwCaps2
|= DDSCAPS2_CUBEMAP_NEGATIVEZ
;
6451 ddraw_update_lost_surfaces(ddraw
);
6452 list_add_head(&ddraw
->surface_list
, &mip
->surface_list_entry
);
6454 TRACE("Created ddraw surface %p.\n", mip
);
6459 texture
->root
= mip
;
6461 texture
->root
->complex_array
[layers
- 1 - i
] = mip
;
6463 else if (j
== 1 && !i
)
6465 texture
->root
->complex_array
[layers
- 1] = mip
;
6469 prev_level
->complex_array
[0] = mip
;
6475 root
= texture
->root
;
6477 wined3d_device_incref(texture
->wined3d_device
= ddraw
->wined3d_device
);
6479 ddraw_surface_sync_color_keys(root
);
6481 wined3d_texture_decref(wined3d_texture
);
6483 wined3d_texture_decref(draw_texture
);
6485 if (reserve_memory
&& FAILED(hr
= ddraw_surface_reserve_memory(wined3d_texture
, 1)))
6487 hr
= hr_ddraw_from_wined3d(hr
);
6491 TRACE("Surface %p, created draw_texture %p, wined3d_texture %p.\n", root
, draw_texture
, wined3d_texture
);
6496 wined3d_texture_decref(draw_texture
);
6498 parent
= wined3d_texture_get_sub_resource_parent(draw_texture
, 0);
6499 if (texture
->version
== 7)
6500 IDirectDrawSurface7_Release(&parent
->IDirectDrawSurface7_iface
);
6501 else if (texture
->version
== 4)
6502 IDirectDrawSurface4_Release(&parent
->IDirectDrawSurface4_iface
);
6504 IDirectDrawSurface_Release(&parent
->IDirectDrawSurface_iface
);
6508 HRESULT
ddraw_surface_create(struct ddraw
*ddraw
, const DDSURFACEDESC2
*surface_desc
,
6509 struct ddraw_surface
**surface
, IUnknown
*outer_unknown
, unsigned int version
)
6511 DDPIXELFORMAT wined3d_display_mode_format
;
6512 struct ddraw_surface
*root
, **attach
;
6513 struct wined3d_display_mode mode
;
6514 struct ddraw_texture
*texture
;
6515 BOOL sysmem_fallback
= FALSE
;
6516 unsigned int layers
= 1;
6517 DDSURFACEDESC2
*desc
;
6518 bool reserve_memory
;
6522 TRACE("ddraw %p, surface_desc %p, surface %p, outer_unknown %p, version %u.\n",
6523 ddraw
, surface_desc
, surface
, outer_unknown
, version
);
6524 if (TRACE_ON(ddraw
))
6526 TRACE("Requesting surface desc:\n");
6527 DDRAW_dump_surface_desc(surface_desc
);
6531 return CLASS_E_NOAGGREGATION
;
6536 if (!(texture
= heap_alloc(sizeof(*texture
))))
6537 return E_OUTOFMEMORY
;
6539 texture
->texture_memory
= NULL
;
6540 texture
->version
= version
;
6541 texture
->surface_desc
= *surface_desc
;
6542 desc
= &texture
->surface_desc
;
6544 /* Ensure DDSD_CAPS is always set. */
6545 desc
->dwFlags
|= DDSD_CAPS
;
6547 if ((desc
->ddsCaps
.dwCaps
& DDSCAPS_COMPLEX
)
6548 && !(desc
->ddsCaps
.dwCaps
& (DDSCAPS_FLIP
| DDSCAPS_MIPMAP
))
6549 && !(desc
->ddsCaps
.dwCaps2
& DDSCAPS2_CUBEMAP
))
6551 WARN("DDSCAPS_COMPLEX specified for a surface which is neither flippable, mipmapped, nor a cubemap.\n");
6553 return DDERR_INVALIDCAPS
;
6556 if ((desc
->dwFlags
& DDSD_MIPMAPCOUNT
) && !(desc
->ddsCaps
.dwCaps
& DDSCAPS_COMPLEX
))
6558 /* This is illegal even if there is only one mipmap level. */
6559 WARN("DDSD_MIPMAPCOUNT specified without DDSCAPS_COMPLEX.\n");
6561 return DDERR_INVALIDCAPS
;
6564 if (desc
->ddsCaps
.dwCaps
& DDSCAPS_FLIP
)
6566 if (!(desc
->dwFlags
& DDSD_BACKBUFFERCOUNT
) || !desc
->u5
.dwBackBufferCount
)
6568 WARN("Tried to create a flippable surface without any back buffers.\n");
6570 return DDERR_INVALIDCAPS
;
6573 if (!(desc
->ddsCaps
.dwCaps
& DDSCAPS_COMPLEX
))
6575 WARN("Tried to create a flippable surface without DDSCAPS_COMPLEX.\n");
6577 return DDERR_INVALIDCAPS
;
6580 if (desc
->ddsCaps
.dwCaps2
& DDSCAPS2_CUBEMAP
)
6582 WARN("Tried to create a flippable cubemap.\n");
6584 return DDERR_INVALIDPARAMS
;
6587 if (desc
->ddsCaps
.dwCaps
& DDSCAPS_TEXTURE
)
6589 FIXME("Flippable textures not implemented.\n");
6591 return DDERR_INVALIDCAPS
;
6596 if (desc
->dwFlags
& DDSD_BACKBUFFERCOUNT
)
6598 WARN("Tried to specify a back buffer count for a non-flippable surface.\n");
6599 hr
= desc
->ddsCaps
.dwCaps2
& DDSCAPS2_CUBEMAP
? DDERR_INVALIDPARAMS
: DDERR_INVALIDCAPS
;
6605 if (desc
->ddsCaps
.dwCaps
& DDSCAPS_PRIMARYSURFACE
)
6607 if (desc
->ddsCaps
.dwCaps
& DDSCAPS_TEXTURE
)
6609 WARN("Tried to create a primary surface with DDSCAPS_TEXTURE.\n");
6611 return DDERR_INVALIDCAPS
;
6614 if ((desc
->ddsCaps
.dwCaps
& DDSCAPS_COMPLEX
) && !(desc
->ddsCaps
.dwCaps
& DDSCAPS_FLIP
))
6616 WARN("Tried to create a flippable primary surface without both DDSCAPS_FLIP and DDSCAPS_COMPLEX.\n");
6618 return DDERR_INVALIDCAPS
;
6621 if ((desc
->ddsCaps
.dwCaps
& DDSCAPS_FLIP
) && !(ddraw
->cooperative_level
& DDSCL_EXCLUSIVE
))
6623 WARN("Tried to create a flippable primary surface without DDSCL_EXCLUSIVE.\n");
6625 return DDERR_NOEXCLUSIVEMODE
;
6629 /* This is a special case in ddrawex, but not allowed in ddraw. */
6630 if ((desc
->ddsCaps
.dwCaps
& (DDSCAPS_VIDEOMEMORY
| DDSCAPS_SYSTEMMEMORY
))
6631 == (DDSCAPS_VIDEOMEMORY
| DDSCAPS_SYSTEMMEMORY
))
6633 WARN("Tried to create a surface in both system and video memory.\n");
6635 return DDERR_INVALIDCAPS
;
6638 if ((desc
->ddsCaps
.dwCaps
& (DDSCAPS_ALLOCONLOAD
| DDSCAPS_MIPMAP
))
6639 && !(desc
->ddsCaps
.dwCaps
& DDSCAPS_TEXTURE
))
6641 WARN("Caps %#lx require DDSCAPS_TEXTURE.\n", desc
->ddsCaps
.dwCaps
);
6643 return DDERR_INVALIDCAPS
;
6646 if ((desc
->ddsCaps
.dwCaps2
& DDSCAPS2_CUBEMAP_ALLFACES
)
6647 && !(desc
->ddsCaps
.dwCaps2
& DDSCAPS2_CUBEMAP
))
6649 WARN("Cube map faces requested without cube map flag.\n");
6651 return DDERR_INVALIDCAPS
;
6654 if ((desc
->ddsCaps
.dwCaps2
& DDSCAPS2_CUBEMAP
)
6655 && !(desc
->ddsCaps
.dwCaps2
& DDSCAPS2_CUBEMAP_ALLFACES
))
6657 WARN("Cube map without faces requested.\n");
6659 return DDERR_INVALIDPARAMS
;
6662 if ((desc
->ddsCaps
.dwCaps2
& DDSCAPS2_CUBEMAP
)
6663 && (desc
->ddsCaps
.dwCaps2
& DDSCAPS2_CUBEMAP_ALLFACES
) != DDSCAPS2_CUBEMAP_ALLFACES
)
6664 FIXME("Partial cube maps not implemented.\n");
6666 if (desc
->ddsCaps
.dwCaps2
& (DDSCAPS2_TEXTUREMANAGE
| DDSCAPS2_D3DTEXTUREMANAGE
))
6668 if (!(desc
->ddsCaps
.dwCaps
& DDSCAPS_TEXTURE
))
6670 WARN("DDSCAPS2_TEXTUREMANAGE used without DDSCAPS_TEXTURE, returning DDERR_INVALIDCAPS.\n");
6672 return DDERR_INVALIDCAPS
;
6674 if (desc
->ddsCaps
.dwCaps
& (DDSCAPS_VIDEOMEMORY
| DDSCAPS_SYSTEMMEMORY
))
6676 WARN("DDSCAPS2_TEXTUREMANAGE used with DDSCAPS_VIDEOMEMORY "
6677 "or DDSCAPS_SYSTEMMEMORY, returning DDERR_INVALIDCAPS.\n");
6679 return DDERR_INVALIDCAPS
;
6683 if (desc
->ddsCaps
.dwCaps
& DDSCAPS_WRITEONLY
6684 && !(desc
->ddsCaps
.dwCaps2
& (DDSCAPS2_TEXTUREMANAGE
| DDSCAPS2_D3DTEXTUREMANAGE
)))
6686 WARN("DDSCAPS_WRITEONLY used without DDSCAPS2_TEXTUREMANAGE, returning DDERR_INVALIDCAPS.\n");
6688 return DDERR_INVALIDCAPS
;
6691 if (FAILED(hr
= wined3d_output_get_display_mode(ddraw
->wined3d_output
, &mode
, NULL
)))
6693 ERR("Failed to get display mode, hr %#lx.\n", hr
);
6695 return hr_ddraw_from_wined3d(hr
);
6698 wined3d_display_mode_format
.dwSize
= sizeof(wined3d_display_mode_format
);
6699 ddrawformat_from_wined3dformat(&wined3d_display_mode_format
, mode
.format_id
);
6701 /* No pixelformat given? Use the current screen format. */
6702 if (!(desc
->dwFlags
& DDSD_PIXELFORMAT
))
6704 desc
->dwFlags
|= DDSD_PIXELFORMAT
;
6705 desc
->u4
.ddpfPixelFormat
= wined3d_display_mode_format
;
6708 /* No width or no height? Use the screen size. */
6709 if (!(desc
->dwFlags
& DDSD_WIDTH
) || !(desc
->dwFlags
& DDSD_HEIGHT
))
6711 if (!(desc
->ddsCaps
.dwCaps
& DDSCAPS_PRIMARYSURFACE
))
6713 WARN("No width / height specified.\n");
6715 return DDERR_INVALIDPARAMS
;
6718 desc
->dwFlags
|= DDSD_WIDTH
| DDSD_HEIGHT
;
6719 desc
->dwWidth
= mode
.width
;
6720 desc
->dwHeight
= mode
.height
;
6723 if (!desc
->dwWidth
|| !desc
->dwHeight
)
6726 return DDERR_INVALIDPARAMS
;
6729 if (desc
->ddsCaps
.dwCaps
& DDSCAPS_FLIP
)
6730 desc
->ddsCaps
.dwCaps
|= DDSCAPS_FRONTBUFFER
;
6732 if (desc
->ddsCaps
.dwCaps
& DDSCAPS_PRIMARYSURFACE
)
6734 /* The first surface is a front buffer, the back buffers are created
6736 desc
->ddsCaps
.dwCaps
|= DDSCAPS_VISIBLE
;
6737 if (ddraw
->cooperative_level
& DDSCL_EXCLUSIVE
)
6739 struct wined3d_swapchain_desc swapchain_desc
;
6741 wined3d_swapchain_get_desc(ddraw
->wined3d_swapchain
, &swapchain_desc
);
6742 swapchain_desc
.backbuffer_width
= mode
.width
;
6743 swapchain_desc
.backbuffer_height
= mode
.height
;
6744 swapchain_desc
.backbuffer_format
= mode
.format_id
;
6746 if (ddraw
->d3ddevice
)
6748 if (ddraw
->d3ddevice
->recording
)
6749 wined3d_stateblock_decref(ddraw
->d3ddevice
->recording
);
6750 ddraw
->d3ddevice
->recording
= NULL
;
6751 ddraw
->d3ddevice
->update_state
= ddraw
->d3ddevice
->state
;
6753 wined3d_stateblock_reset(ddraw
->state
);
6755 if (FAILED(hr
= wined3d_device_reset(ddraw
->wined3d_device
,
6756 &swapchain_desc
, NULL
, ddraw_reset_enum_callback
, TRUE
)))
6758 ERR("Failed to reset device.\n");
6760 return hr_ddraw_from_wined3d(hr
);
6763 wined3d_stateblock_set_render_state(ddraw
->state
, WINED3D_RS_ZENABLE
,
6764 !!swapchain_desc
.enable_auto_depth_stencil
);
6768 if ((desc
->ddsCaps
.dwCaps
& DDSCAPS_3DDEVICE
) && (ddraw
->flags
& DDRAW_NO3D
))
6770 WARN("The application requests a 3D capable surface, but the ddraw object was created without 3D support.\n");
6771 /* Do not fail surface creation, only fail 3D device creation. */
6774 /* Mipmap count fixes */
6775 if (desc
->ddsCaps
.dwCaps
& DDSCAPS_MIPMAP
)
6777 if (desc
->ddsCaps
.dwCaps
& DDSCAPS_COMPLEX
)
6779 if (desc
->dwFlags
& DDSD_MIPMAPCOUNT
)
6781 /* Mipmap count is given, should not be 0. */
6782 if (!desc
->u2
.dwMipMapCount
)
6785 return DDERR_INVALIDPARAMS
;
6790 /* Undocumented feature: Create sublevels until either the
6791 * width or the height is 1. */
6793 desc
->u2
.dwMipMapCount
= wined3d_log2i(max(desc
->dwWidth
, desc
->dwHeight
)) + 1;
6795 desc
->u2
.dwMipMapCount
= wined3d_log2i(min(desc
->dwWidth
, desc
->dwHeight
)) + 1;
6800 desc
->u2
.dwMipMapCount
= 1;
6803 desc
->dwFlags
|= DDSD_MIPMAPCOUNT
;
6804 levels
= desc
->u2
.dwMipMapCount
;
6811 if (!(desc
->ddsCaps
.dwCaps
& (DDSCAPS_VIDEOMEMORY
| DDSCAPS_SYSTEMMEMORY
)))
6813 if (!(desc
->ddsCaps
.dwCaps2
& (DDSCAPS2_TEXTUREMANAGE
| DDSCAPS2_D3DTEXTUREMANAGE
)))
6815 unsigned int bind_flags
= 0;
6818 if (desc
->ddsCaps
.dwCaps2
& DDSCAPS2_CUBEMAP
)
6820 usage
|= WINED3DUSAGE_LEGACY_CUBEMAP
;
6821 bind_flags
|= WINED3D_BIND_SHADER_RESOURCE
;
6823 else if (desc
->ddsCaps
.dwCaps
& DDSCAPS_TEXTURE
)
6825 bind_flags
|= WINED3D_BIND_SHADER_RESOURCE
;
6828 if (desc
->ddsCaps
.dwCaps
& DDSCAPS_ZBUFFER
)
6829 bind_flags
|= WINED3D_BIND_DEPTH_STENCIL
;
6830 else if (desc
->ddsCaps
.dwCaps
& DDSCAPS_3DDEVICE
)
6831 bind_flags
|= WINED3D_BIND_RENDER_TARGET
;
6833 if (!(ddraw
->flags
& DDRAW_NO3D
) && SUCCEEDED(hr
= wined3d_check_device_format(ddraw
->wined3d
,
6834 ddraw
->wined3d_adapter
, WINED3D_DEVICE_TYPE_HAL
, mode
.format_id
,
6835 usage
, bind_flags
, WINED3D_RTYPE_TEXTURE_2D
, wined3dformat_from_ddrawformat(&desc
->u4
.ddpfPixelFormat
))))
6837 desc
->ddsCaps
.dwCaps
|= DDSCAPS_VIDEOMEMORY
;
6841 desc
->ddsCaps
.dwCaps
|= DDSCAPS_SYSTEMMEMORY
;
6842 sysmem_fallback
= TRUE
;
6845 else if (!(desc
->ddsCaps
.dwCaps
& DDSCAPS_TEXTURE
))
6847 /* Tests show surfaces without memory flags get these flags added
6848 * right after creation. */
6849 desc
->ddsCaps
.dwCaps
|= DDSCAPS_LOCALVIDMEM
| DDSCAPS_VIDEOMEMORY
;
6853 if ((desc
->ddsCaps
.dwCaps
& (DDSCAPS_OVERLAY
| DDSCAPS_SYSTEMMEMORY
))
6854 == (DDSCAPS_OVERLAY
| DDSCAPS_SYSTEMMEMORY
))
6856 WARN("System memory overlays are not allowed.\n");
6858 return DDERR_NOOVERLAYHW
;
6861 if (desc
->ddsCaps
.dwCaps2
& (DDSCAPS2_TEXTUREMANAGE
| DDSCAPS2_D3DTEXTUREMANAGE
))
6862 desc
->ddsCaps
.dwCaps
|= DDSCAPS_SYSTEMMEMORY
;
6864 if (desc
->ddsCaps
.dwCaps
& DDSCAPS_VIDEOMEMORY
)
6865 desc
->ddsCaps
.dwCaps
|= DDSCAPS_LOCALVIDMEM
;
6867 if (desc
->dwFlags
& DDSD_LPSURFACE
)
6869 if (!(desc
->ddsCaps
.dwCaps
& DDSCAPS_SYSTEMMEMORY
))
6871 WARN("User memory surfaces should not be GPU accessible.\n");
6873 return DDERR_INVALIDCAPS
;
6878 WARN("User memory surfaces not supported before version 4.\n");
6880 return DDERR_INVALIDPARAMS
;
6883 if (!desc
->lpSurface
)
6885 WARN("NULL surface memory pointer specified.\n");
6887 return DDERR_INVALIDPARAMS
;
6890 if (format_is_compressed(&desc
->u4
.ddpfPixelFormat
))
6892 if (version
!= 4 && (desc
->dwFlags
& DDSD_PITCH
))
6894 WARN("Pitch specified on a compressed user memory surface.\n");
6896 return DDERR_INVALIDPARAMS
;
6899 if (!(desc
->dwFlags
& (DDSD_LINEARSIZE
| DDSD_PITCH
)))
6901 WARN("Compressed user memory surfaces should explicitly specify the linear size.\n");
6903 return DDERR_INVALIDPARAMS
;
6908 if (!(desc
->dwFlags
& DDSD_PITCH
))
6910 WARN("User memory surfaces should explicitly specify the pitch.\n");
6912 return DDERR_INVALIDPARAMS
;
6917 if (((desc
->dwFlags
& DDSD_CKDESTOVERLAY
)
6918 && desc
->u3
.ddckCKDestOverlay
.dwColorSpaceLowValue
!= desc
->u3
.ddckCKDestOverlay
.dwColorSpaceHighValue
)
6919 || ((desc
->dwFlags
& DDSD_CKDESTBLT
)
6920 && desc
->ddckCKDestBlt
.dwColorSpaceLowValue
!= desc
->ddckCKDestBlt
.dwColorSpaceHighValue
)
6921 || ((desc
->dwFlags
& DDSD_CKSRCOVERLAY
)
6922 && desc
->ddckCKSrcOverlay
.dwColorSpaceLowValue
!= desc
->ddckCKSrcOverlay
.dwColorSpaceHighValue
)
6923 || ((desc
->dwFlags
& DDSD_CKSRCBLT
)
6924 && desc
->ddckCKSrcBlt
.dwColorSpaceLowValue
!= desc
->ddckCKSrcBlt
.dwColorSpaceHighValue
))
6926 WARN("Range color keys not supported, returning DDERR_NOCOLORKEYHW.\n");
6928 return DDERR_NOCOLORKEYHW
;
6931 if ((ddraw
->flags
& DDRAW_NO3D
) && (desc
->ddsCaps
.dwCaps
& DDSCAPS_VIDEOMEMORY
))
6933 WARN("Video memory surfaces not supported without 3D support.\n");
6935 return DDERR_NODIRECTDRAWHW
;
6938 if (desc
->ddsCaps
.dwCaps2
& DDSCAPS2_CUBEMAP
)
6941 reserve_memory
= !(desc
->dwFlags
& DDSD_LPSURFACE
)
6942 && desc
->ddsCaps
.dwCaps
& DDSCAPS_VIDEOMEMORY
6943 && wined3d_display_mode_format
.u1
.dwRGBBitCount
<= 16;
6945 if (FAILED(hr
= ddraw_texture_init(texture
, ddraw
, layers
, levels
, sysmem_fallback
, reserve_memory
)))
6947 WARN("Failed to create wined3d texture, hr %#lx.\n", hr
);
6949 return hr_ddraw_from_wined3d(hr
);
6952 root
= texture
->root
;
6953 root
->is_root
= TRUE
;
6955 if (desc
->dwFlags
& DDSD_BACKBUFFERCOUNT
)
6957 unsigned int count
= desc
->u5
.dwBackBufferCount
;
6958 struct ddraw_surface
*last
= root
;
6960 attach
= &last
->complex_array
[0];
6961 for (i
= 0; i
< count
; ++i
)
6963 if (!(texture
= heap_alloc(sizeof(*texture
))))
6969 texture
->texture_memory
= NULL
;
6970 texture
->version
= version
;
6971 texture
->surface_desc
= root
->surface_desc
;
6972 desc
= &texture
->surface_desc
;
6974 /* Only one surface in the flipping chain is a back buffer, one is
6975 * a front buffer, the others are just flippable surfaces. */
6976 desc
->ddsCaps
.dwCaps
&= ~(DDSCAPS_VISIBLE
| DDSCAPS_PRIMARYSURFACE
| DDSCAPS_FRONTBUFFER
6977 | DDSCAPS_BACKBUFFER
);
6979 desc
->ddsCaps
.dwCaps
|= DDSCAPS_BACKBUFFER
;
6980 desc
->u5
.dwBackBufferCount
= 0;
6982 if (FAILED(hr
= ddraw_texture_init(texture
, ddraw
, 1, 1, sysmem_fallback
, reserve_memory
)))
6985 hr
= hr_ddraw_from_wined3d(hr
);
6989 last
= texture
->root
;
6992 attach
= &last
->complex_array
[0];
6997 if (surface_desc
->ddsCaps
.dwCaps
& DDSCAPS_PRIMARYSURFACE
)
6999 ddraw
->primary
= root
;
7000 ddraw
->gdi_surface
= root
->wined3d_texture
;
7008 IDirectDrawSurface7_Release(&root
->IDirectDrawSurface7_iface
);
7009 else if (version
== 4)
7010 IDirectDrawSurface4_Release(&root
->IDirectDrawSurface4_iface
);
7012 IDirectDrawSurface_Release(&root
->IDirectDrawSurface_iface
);
7017 static void STDMETHODCALLTYPE
view_wined3d_object_destroyed(void *parent
)
7019 struct ddraw_surface
*surface
= parent
;
7021 /* If the surface reference count drops to zero, we release our reference
7022 * to the view, but don't clear the pointer yet, in case e.g. a
7023 * GetRenderTarget() call brings the surface back before the view is
7024 * actually destroyed. When the view is destroyed, we need to clear the
7025 * pointer, or a subsequent surface AddRef() would reference it again.
7027 * This is safe because as long as the view still has a reference to the
7028 * texture, the surface is also still alive, and we're called before the
7029 * view releases that reference. */
7030 surface
->wined3d_rtv
= NULL
;
7033 static const struct wined3d_parent_ops ddraw_view_wined3d_parent_ops
=
7035 view_wined3d_object_destroyed
,
7038 struct wined3d_rendertarget_view
*ddraw_surface_get_rendertarget_view(struct ddraw_surface
*surface
)
7040 struct wined3d_texture
*wined3d_texture
;
7043 if (surface
->wined3d_rtv
)
7044 return surface
->wined3d_rtv
;
7046 wined3d_texture
= surface
->draw_texture
? surface
->draw_texture
: surface
->wined3d_texture
;
7047 if (FAILED(hr
= wined3d_rendertarget_view_create_from_sub_resource(wined3d_texture
,
7048 surface
->sub_resource_idx
, surface
, &ddraw_view_wined3d_parent_ops
, &surface
->wined3d_rtv
)))
7050 ERR("Failed to create rendertarget view, hr %#lx.\n", hr
);
7054 return surface
->wined3d_rtv
;