dcomp: Add DCompositionCreateDevice() stub.
[wine.git] / dlls / ddraw / surface.c
blob0ca19d4f8a5d52a00663c6f31852443abc22bb44
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);
28 static struct ddraw_surface *unsafe_impl_from_IDirectDrawSurface2(IDirectDrawSurface2 *iface);
29 static struct ddraw_surface *unsafe_impl_from_IDirectDrawSurface3(IDirectDrawSurface3 *iface);
31 static inline struct ddraw_surface *impl_from_IDirectDrawGammaControl(IDirectDrawGammaControl *iface)
33 return CONTAINING_RECORD(iface, struct ddraw_surface, IDirectDrawGammaControl_iface);
36 static BOOL ddraw_surface_is_lost(const struct ddraw_surface *surface)
38 return ddraw_surface_can_be_lost(surface)
39 && (surface->ddraw->device_state != DDRAW_DEVICE_STATE_OK || surface->is_lost);
42 static BOOL ddraw_gdi_is_front(struct ddraw *ddraw)
44 struct ddraw_surface *surface;
46 if (!ddraw->gdi_surface || !(surface = wined3d_texture_get_sub_resource_parent(ddraw->gdi_surface, 0)))
47 return FALSE;
49 return surface->surface_desc.ddsCaps.dwCaps & DDSCAPS_FRONTBUFFER;
52 /* This is slow, of course. Also, in case of locks, we can't prevent other
53 * applications from drawing to the screen while we've locked the frontbuffer.
54 * We'd like to do this in wined3d instead, but for that to work wined3d needs
55 * to support windowless rendering first. */
56 HRESULT ddraw_surface_update_frontbuffer(struct ddraw_surface *surface,
57 const RECT *rect, BOOL read, unsigned int swap_interval)
59 struct ddraw *ddraw = surface->ddraw;
60 struct wined3d_texture *dst_texture;
61 HDC surface_dc, screen_dc;
62 int x, y, w, h;
63 HRESULT hr;
64 BOOL ret;
65 RECT r;
67 if (ddraw->flags & DDRAW_SWAPPED && !read)
69 ddraw->flags &= ~DDRAW_SWAPPED;
70 rect = NULL;
73 if (!rect)
75 SetRect(&r, 0, 0, surface->surface_desc.dwWidth, surface->surface_desc.dwHeight);
76 rect = &r;
79 x = rect->left;
80 y = rect->top;
81 w = rect->right - rect->left;
82 h = rect->bottom - rect->top;
84 if (w <= 0 || h <= 0)
85 return DD_OK;
87 /* The interaction between ddraw and GDI drawing is not all that well
88 * documented, and somewhat arcane. In ddraw exclusive mode, GDI draws
89 * seemingly go to the *original* frontbuffer/primary surface, while ddraw
90 * draws/flips go to the *current* frontbuffer surface. The bottom line is
91 * that if the current frontbuffer is not the GDI frontbuffer, and there's
92 * e.g. a popup window in front of the ddraw swapchain window, we can't
93 * use wined3d_swapchain_present() to get the ddraw contents to the screen
94 * while in exclusive mode, since it would get obscured by the popup
95 * window. On the other hand, if the current frontbuffer *is* the GDI
96 * frontbuffer, that's what's supposed to happen; the popup should obscure
97 * (oart of) the ddraw swapchain window.
99 * This affects the "Deer Hunter" demo, which uses a popup window and GDI
100 * draws to draw part of the user interface. See also the "fswindow"
101 * sample is the DirectX 7 SDK. */
102 if (ddraw->swapchain_window && (!(ddraw->cooperative_level & DDSCL_EXCLUSIVE)
103 || ddraw->swapchain_window == GetForegroundWindow() || ddraw_gdi_is_front(ddraw)))
105 /* Nothing to do, we control the frontbuffer, or at least the parts we
106 * care about. */
107 if (read)
108 return DD_OK;
110 if (swap_interval)
111 dst_texture = wined3d_swapchain_get_back_buffer(ddraw->wined3d_swapchain, 0);
112 else
113 dst_texture = ddraw->wined3d_frontbuffer;
115 if (SUCCEEDED(hr = wined3d_texture_blt(dst_texture, 0, rect, surface->wined3d_texture,
116 surface->sub_resource_idx, rect, 0, NULL, WINED3D_TEXF_POINT)) && swap_interval)
118 hr = wined3d_swapchain_present(ddraw->wined3d_swapchain, rect, rect, NULL, swap_interval, 0);
119 ddraw->flags |= DDRAW_SWAPPED;
121 return hr;
124 if (FAILED(hr = wined3d_texture_get_dc(surface->wined3d_texture, surface->sub_resource_idx, &surface_dc)))
126 ERR("Failed to get surface DC, hr %#x.\n", hr);
127 return hr;
129 if (surface->palette)
130 wined3d_palette_apply_to_dc(surface->palette->wined3d_palette, surface_dc);
132 if (!(screen_dc = GetDC(NULL)))
134 wined3d_texture_release_dc(surface->wined3d_texture, surface->sub_resource_idx, surface_dc);
135 ERR("Failed to get screen DC.\n");
136 return E_FAIL;
139 if (read)
140 ret = BitBlt(surface_dc, x, y, w, h,
141 screen_dc, x, y, SRCCOPY);
142 else
143 ret = BitBlt(screen_dc, x, y, w, h,
144 surface_dc, x, y, SRCCOPY);
146 ReleaseDC(NULL, screen_dc);
147 wined3d_texture_release_dc(surface->wined3d_texture, surface->sub_resource_idx, surface_dc);
149 if (!ret)
151 ERR("Failed to blit to/from screen.\n");
152 return E_FAIL;
155 return DD_OK;
158 /*****************************************************************************
159 * IUnknown parts follow
160 *****************************************************************************/
162 /*****************************************************************************
163 * IDirectDrawSurface7::QueryInterface
165 * A normal QueryInterface implementation. For QueryInterface rules
166 * see ddraw.c, IDirectDraw7::QueryInterface. This method
167 * can Query IDirectDrawSurface interfaces in all version, IDirect3DTexture
168 * in all versions, the IDirectDrawGammaControl interface and it can
169 * create an IDirect3DDevice. (Uses IDirect3D7::CreateDevice)
171 * Params:
172 * riid: The interface id queried for
173 * obj: Address to write the pointer to
175 * Returns:
176 * S_OK on success
177 * E_NOINTERFACE if the requested interface wasn't found
179 *****************************************************************************/
180 static HRESULT WINAPI ddraw_surface7_QueryInterface(IDirectDrawSurface7 *iface, REFIID riid, void **obj)
182 struct ddraw_surface *This = impl_from_IDirectDrawSurface7(iface);
184 TRACE("iface %p, riid %s, object %p.\n", iface, debugstr_guid(riid), obj);
186 /* According to COM docs, if the QueryInterface fails, obj should be set to NULL */
187 *obj = NULL;
189 if(!riid)
190 return DDERR_INVALIDPARAMS;
192 if (IsEqualGUID(riid, &IID_IDirectDrawSurface7))
194 IDirectDrawSurface7_AddRef(iface);
195 *obj = iface;
196 TRACE("(%p) returning IDirectDrawSurface7 interface at %p\n", This, *obj);
197 return S_OK;
200 if (IsEqualGUID(riid, &IID_IDirectDrawSurface4))
202 IDirectDrawSurface4_AddRef(&This->IDirectDrawSurface4_iface);
203 *obj = &This->IDirectDrawSurface4_iface;
204 TRACE("(%p) returning IDirectDrawSurface4 interface at %p\n", This, *obj);
205 return S_OK;
208 if (IsEqualGUID(riid, &IID_IDirectDrawSurface3))
210 IDirectDrawSurface3_AddRef(&This->IDirectDrawSurface3_iface);
211 *obj = &This->IDirectDrawSurface3_iface;
212 TRACE("(%p) returning IDirectDrawSurface3 interface at %p\n", This, *obj);
213 return S_OK;
216 if (IsEqualGUID(riid, &IID_IDirectDrawSurface2))
218 IDirectDrawSurface2_AddRef(&This->IDirectDrawSurface2_iface);
219 *obj = &This->IDirectDrawSurface2_iface;
220 TRACE("(%p) returning IDirectDrawSurface2 interface at %p\n", This, *obj);
221 return S_OK;
224 if (IsEqualGUID(riid, &IID_IDirectDrawSurface)
225 || IsEqualGUID(riid, &IID_IUnknown))
227 IDirectDrawSurface_AddRef(&This->IDirectDrawSurface_iface);
228 *obj = &This->IDirectDrawSurface_iface;
229 TRACE("(%p) returning IDirectDrawSurface interface at %p\n", This, *obj);
230 return S_OK;
233 if (IsEqualGUID(riid, &IID_IDirectDrawGammaControl))
235 IDirectDrawGammaControl_AddRef(&This->IDirectDrawGammaControl_iface);
236 *obj = &This->IDirectDrawGammaControl_iface;
237 TRACE("(%p) returning IDirectDrawGammaControl interface at %p\n", This, *obj);
238 return S_OK;
241 if (IsEqualGUID(riid, &IID_IDirectDrawColorControl))
243 WARN("Color control not implemented.\n");
244 *obj = NULL;
245 return E_NOINTERFACE;
248 if (This->version != 7)
250 if (IsEqualGUID(riid, &IID_D3DDEVICE_WineD3D)
251 || IsEqualGUID(riid, &IID_IDirect3DHALDevice)
252 || IsEqualGUID(riid, &IID_IDirect3DRGBDevice))
254 wined3d_mutex_lock();
255 if (!This->device1)
257 HRESULT hr;
259 if (FAILED(hr = d3d_device_create(This->ddraw, This, (IUnknown *)&This->IDirectDrawSurface_iface,
260 1, &This->device1, (IUnknown *)&This->IDirectDrawSurface_iface)))
262 This->device1 = NULL;
263 wined3d_mutex_unlock();
264 WARN("Failed to create device, hr %#x.\n", hr);
265 return hr;
268 wined3d_mutex_unlock();
270 IDirect3DDevice_AddRef(&This->device1->IDirect3DDevice_iface);
271 *obj = &This->device1->IDirect3DDevice_iface;
272 return S_OK;
275 if (IsEqualGUID(&IID_IDirect3DTexture2, riid))
277 IDirect3DTexture2_AddRef(&This->IDirect3DTexture2_iface);
278 *obj = &This->IDirect3DTexture2_iface;
279 return S_OK;
282 if (IsEqualGUID( &IID_IDirect3DTexture, riid ))
284 IDirect3DTexture2_AddRef(&This->IDirect3DTexture_iface);
285 *obj = &This->IDirect3DTexture_iface;
286 return S_OK;
290 WARN("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(riid));
292 if (This->version != 7)
293 return E_INVALIDARG;
295 return E_NOINTERFACE;
298 static HRESULT WINAPI ddraw_surface4_QueryInterface(IDirectDrawSurface4 *iface, REFIID riid, void **object)
300 struct ddraw_surface *surface = impl_from_IDirectDrawSurface4(iface);
302 TRACE("iface %p, riid %s, object %p.\n", iface, debugstr_guid(riid), object);
304 return ddraw_surface7_QueryInterface(&surface->IDirectDrawSurface7_iface, riid, object);
307 static HRESULT WINAPI ddraw_surface3_QueryInterface(IDirectDrawSurface3 *iface, REFIID riid, void **object)
309 struct ddraw_surface *surface = impl_from_IDirectDrawSurface3(iface);
311 TRACE("iface %p, riid %s, object %p.\n", iface, debugstr_guid(riid), object);
313 return ddraw_surface7_QueryInterface(&surface->IDirectDrawSurface7_iface, riid, object);
316 static HRESULT WINAPI ddraw_surface2_QueryInterface(IDirectDrawSurface2 *iface, REFIID riid, void **object)
318 struct ddraw_surface *surface = impl_from_IDirectDrawSurface2(iface);
320 TRACE("iface %p, riid %s, object %p.\n", iface, debugstr_guid(riid), object);
322 return ddraw_surface7_QueryInterface(&surface->IDirectDrawSurface7_iface, riid, object);
325 static HRESULT WINAPI ddraw_surface1_QueryInterface(IDirectDrawSurface *iface, REFIID riid, void **object)
327 struct ddraw_surface *surface = impl_from_IDirectDrawSurface(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_gamma_control_QueryInterface(IDirectDrawGammaControl *iface,
335 REFIID riid, void **object)
337 struct ddraw_surface *surface = impl_from_IDirectDrawGammaControl(iface);
339 TRACE("iface %p, riid %s, object %p.\n", iface, debugstr_guid(riid), object);
341 return ddraw_surface7_QueryInterface(&surface->IDirectDrawSurface7_iface, riid, object);
344 static HRESULT WINAPI d3d_texture2_QueryInterface(IDirect3DTexture2 *iface, REFIID riid, void **object)
346 struct ddraw_surface *surface = impl_from_IDirect3DTexture2(iface);
348 TRACE("iface %p, riid %s, object %p.\n", iface, debugstr_guid(riid), object);
350 return ddraw_surface7_QueryInterface(&surface->IDirectDrawSurface7_iface, riid, object);
353 static HRESULT WINAPI d3d_texture1_QueryInterface(IDirect3DTexture *iface, REFIID riid, void **object)
355 struct ddraw_surface *surface = impl_from_IDirect3DTexture(iface);
357 TRACE("iface %p, riid %s, object %p.\n", iface, debugstr_guid(riid), object);
359 return ddraw_surface7_QueryInterface(&surface->IDirectDrawSurface7_iface, riid, object);
362 static void ddraw_surface_add_iface(struct ddraw_surface *surface)
364 ULONG iface_count = InterlockedIncrement(&surface->iface_count);
365 TRACE("%p increasing iface count to %u.\n", surface, iface_count);
367 if (iface_count == 1)
369 if (surface->ifaceToRelease)
370 IUnknown_AddRef(surface->ifaceToRelease);
371 wined3d_mutex_lock();
372 if (surface->wined3d_rtv)
373 wined3d_rendertarget_view_incref(surface->wined3d_rtv);
374 wined3d_texture_incref(surface->wined3d_texture);
375 wined3d_mutex_unlock();
379 /*****************************************************************************
380 * IDirectDrawSurface7::AddRef
382 * A normal addref implementation
384 * Returns:
385 * The new refcount
387 *****************************************************************************/
388 static ULONG WINAPI ddraw_surface7_AddRef(IDirectDrawSurface7 *iface)
390 struct ddraw_surface *This = impl_from_IDirectDrawSurface7(iface);
391 ULONG refcount = InterlockedIncrement(&This->ref7);
393 TRACE("iface %p increasing refcount to %u.\n", iface, refcount);
395 if (refcount == 1)
397 ddraw_surface_add_iface(This);
400 return refcount;
403 static ULONG WINAPI ddraw_surface4_AddRef(IDirectDrawSurface4 *iface)
405 struct ddraw_surface *This = impl_from_IDirectDrawSurface4(iface);
406 ULONG refcount = InterlockedIncrement(&This->ref4);
408 TRACE("iface %p increasing refcount to %u.\n", iface, refcount);
410 if (refcount == 1)
412 ddraw_surface_add_iface(This);
415 return refcount;
418 static ULONG WINAPI ddraw_surface3_AddRef(IDirectDrawSurface3 *iface)
420 struct ddraw_surface *This = impl_from_IDirectDrawSurface3(iface);
421 ULONG refcount = InterlockedIncrement(&This->ref3);
423 TRACE("iface %p increasing refcount to %u.\n", iface, refcount);
425 if (refcount == 1)
427 ddraw_surface_add_iface(This);
430 return refcount;
433 static ULONG WINAPI ddraw_surface2_AddRef(IDirectDrawSurface2 *iface)
435 struct ddraw_surface *This = impl_from_IDirectDrawSurface2(iface);
436 ULONG refcount = InterlockedIncrement(&This->ref2);
438 TRACE("iface %p increasing refcount to %u.\n", iface, refcount);
440 if (refcount == 1)
442 ddraw_surface_add_iface(This);
445 return refcount;
448 static ULONG WINAPI ddraw_surface1_AddRef(IDirectDrawSurface *iface)
450 struct ddraw_surface *This = impl_from_IDirectDrawSurface(iface);
451 ULONG refcount = InterlockedIncrement(&This->ref1);
453 TRACE("iface %p increasing refcount to %u.\n", iface, refcount);
455 if (refcount == 1)
457 ddraw_surface_add_iface(This);
460 return refcount;
463 static ULONG WINAPI ddraw_gamma_control_AddRef(IDirectDrawGammaControl *iface)
465 struct ddraw_surface *This = impl_from_IDirectDrawGammaControl(iface);
466 ULONG refcount = InterlockedIncrement(&This->gamma_count);
468 TRACE("iface %p increasing refcount to %u.\n", iface, refcount);
470 if (refcount == 1)
472 ddraw_surface_add_iface(This);
475 return refcount;
478 static ULONG WINAPI d3d_texture2_AddRef(IDirect3DTexture2 *iface)
480 struct ddraw_surface *surface = impl_from_IDirect3DTexture2(iface);
482 TRACE("iface %p.\n", iface);
484 return IUnknown_AddRef(surface->texture_outer);
487 static ULONG WINAPI d3d_texture1_AddRef(IDirect3DTexture *iface)
489 struct ddraw_surface *surface = impl_from_IDirect3DTexture(iface);
491 TRACE("iface %p.\n", iface);
493 return IUnknown_AddRef(surface->texture_outer);
496 static HRESULT ddraw_surface_set_palette(struct ddraw_surface *surface, IDirectDrawPalette *palette)
498 struct ddraw_palette *palette_impl = unsafe_impl_from_IDirectDrawPalette(palette);
499 struct ddraw_palette *prev;
501 TRACE("iface %p, palette %p.\n", surface, palette);
503 if (palette_impl && palette_impl->flags & DDPCAPS_ALPHA
504 && !(surface->surface_desc.ddsCaps.dwCaps & DDSCAPS_TEXTURE))
506 WARN("Alpha palette set on non-texture surface, returning DDERR_INVALIDSURFACETYPE.\n");
507 return DDERR_INVALIDSURFACETYPE;
510 if (!format_is_paletteindexed(&surface->surface_desc.u4.ddpfPixelFormat))
511 return DDERR_INVALIDPIXELFORMAT;
513 wined3d_mutex_lock();
515 prev = surface->palette;
516 if (surface->surface_desc.ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE)
518 if (prev)
519 prev->flags &= ~DDPCAPS_PRIMARYSURFACE;
520 if (palette_impl)
521 palette_impl->flags |= DDPCAPS_PRIMARYSURFACE;
522 wined3d_swapchain_set_palette(surface->ddraw->wined3d_swapchain,
523 palette_impl ? palette_impl->wined3d_palette : NULL);
524 ddraw_surface_update_frontbuffer(surface, NULL, FALSE, 0);
526 if (palette_impl)
527 IDirectDrawPalette_AddRef(&palette_impl->IDirectDrawPalette_iface);
528 if (prev)
529 IDirectDrawPalette_Release(&prev->IDirectDrawPalette_iface);
530 surface->palette = palette_impl;
532 wined3d_mutex_unlock();
534 return DD_OK;
537 static void ddraw_surface_cleanup(struct ddraw_surface *surface)
539 struct ddraw_surface *surf;
540 UINT i;
542 TRACE("surface %p.\n", surface);
544 /* The refcount test shows that the palette is detached when the surface
545 * is destroyed. */
546 ddraw_surface_set_palette(surface, NULL);
548 /* Loop through all complex attached surfaces and destroy them.
550 * Yet again, only the root can have more than one complexly attached
551 * surface, all the others have a total of one. */
552 for (i = 0; i < MAX_COMPLEX_ATTACHED; ++i)
554 if (!surface->complex_array[i])
555 break;
557 surf = surface->complex_array[i];
558 surface->complex_array[i] = NULL;
559 if (!surf->is_complex_root)
561 struct ddraw_texture *texture = wined3d_texture_get_parent(surf->wined3d_texture);
562 struct wined3d_device *wined3d_device = texture->wined3d_device;
563 struct ddraw_surface *root = texture->root;
565 ddraw_surface_cleanup(surf);
567 if (surf == root)
568 wined3d_device_decref(wined3d_device);
572 if (surface->device1)
573 IUnknown_Release(&surface->device1->IUnknown_inner);
575 if (surface->iface_count > 1)
577 /* This can happen when a complex surface is destroyed, because the
578 * 2nd surface was addref()ed when the app called
579 * GetAttachedSurface(). */
580 WARN("Destroying surface %p with refcounts 7: %u 4: %u 3: %u 2: %u 1: %u.\n",
581 surface, surface->ref7, surface->ref4, surface->ref3, surface->ref2, surface->ref1);
584 if (surface->wined3d_rtv)
585 wined3d_rendertarget_view_decref(surface->wined3d_rtv);
586 wined3d_texture_decref(surface->wined3d_texture);
589 static ULONG ddraw_surface_release_iface(struct ddraw_surface *This)
591 ULONG iface_count;
593 /* Prevent the surface from being destroyed if it's still attached to
594 * another surface. It will be destroyed when the root is destroyed. */
595 if (This->iface_count == 1 && This->attached_iface)
596 IUnknown_AddRef(This->attached_iface);
597 iface_count = InterlockedDecrement(&This->iface_count);
599 TRACE("%p decreasing iface count to %u.\n", This, iface_count);
601 if (iface_count == 0)
603 struct ddraw_texture *texture = wined3d_texture_get_parent(This->wined3d_texture);
604 struct wined3d_device *wined3d_device = texture->wined3d_device;
605 IUnknown *release_iface = This->ifaceToRelease;
607 /* Complex attached surfaces are destroyed implicitly when the root is released */
608 wined3d_mutex_lock();
609 if(!This->is_complex_root)
611 WARN("(%p) Attempt to destroy a surface that is not a complex root\n", This);
612 wined3d_mutex_unlock();
613 return iface_count;
615 ddraw_surface_cleanup(This);
616 wined3d_mutex_unlock();
618 if (release_iface)
619 IUnknown_Release(release_iface);
620 /* Release the device only after anything that may reference it (the
621 * wined3d texture and rendertarget view in particular) is released. */
622 wined3d_device_decref(wined3d_device);
625 return iface_count;
628 /*****************************************************************************
629 * IDirectDrawSurface7::Release
631 * Reduces the surface's refcount by 1. If the refcount falls to 0, the
632 * surface is destroyed.
634 * Destroying the surface is a bit tricky. For the connection between
635 * WineD3DSurfaces and DirectDrawSurfaces see IDirectDraw7::CreateSurface
636 * It has a nice graph explaining the connection.
638 * What happens here is basically this:
639 * When a surface is destroyed, its WineD3DSurface is released,
640 * and the refcount of the DirectDraw interface is reduced by 1. If it has
641 * complex surfaces attached to it, then these surfaces are destroyed too,
642 * regardless of their refcount. If any surface being destroyed has another
643 * surface attached to it (with a "soft" attachment, not complex), then
644 * this surface is detached with DeleteAttachedSurface.
646 * When the surface is a texture, the WineD3DTexture is released.
647 * If the surface is the Direct3D render target, then the D3D
648 * capabilities of the WineD3DDevice are uninitialized, which causes the
649 * swapchain to be released.
651 * When a complex sublevel falls to ref zero, then this is ignored.
653 * Returns:
654 * The new refcount
656 *****************************************************************************/
657 static ULONG WINAPI ddraw_surface7_Release(IDirectDrawSurface7 *iface)
659 struct ddraw_surface *This = impl_from_IDirectDrawSurface7(iface);
660 ULONG refcount = InterlockedDecrement(&This->ref7);
662 TRACE("iface %p decreasing refcount to %u.\n", iface, refcount);
664 if (refcount == 0)
666 ddraw_surface_release_iface(This);
669 return refcount;
672 static ULONG WINAPI ddraw_surface4_Release(IDirectDrawSurface4 *iface)
674 struct ddraw_surface *This = impl_from_IDirectDrawSurface4(iface);
675 ULONG refcount = InterlockedDecrement(&This->ref4);
677 TRACE("iface %p decreasing refcount to %u.\n", iface, refcount);
679 if (refcount == 0)
681 ddraw_surface_release_iface(This);
684 return refcount;
687 static ULONG WINAPI ddraw_surface3_Release(IDirectDrawSurface3 *iface)
689 struct ddraw_surface *This = impl_from_IDirectDrawSurface3(iface);
690 ULONG refcount = InterlockedDecrement(&This->ref3);
692 TRACE("iface %p decreasing refcount to %u.\n", iface, refcount);
694 if (refcount == 0)
696 ddraw_surface_release_iface(This);
699 return refcount;
702 static ULONG WINAPI ddraw_surface2_Release(IDirectDrawSurface2 *iface)
704 struct ddraw_surface *This = impl_from_IDirectDrawSurface2(iface);
705 ULONG refcount = InterlockedDecrement(&This->ref2);
707 TRACE("iface %p decreasing refcount to %u.\n", iface, refcount);
709 if (refcount == 0)
711 ddraw_surface_release_iface(This);
714 return refcount;
717 static ULONG WINAPI ddraw_surface1_Release(IDirectDrawSurface *iface)
719 struct ddraw_surface *This = impl_from_IDirectDrawSurface(iface);
720 ULONG refcount = InterlockedDecrement(&This->ref1);
722 TRACE("iface %p decreasing refcount to %u.\n", iface, refcount);
724 if (refcount == 0)
726 ddraw_surface_release_iface(This);
729 return refcount;
732 static ULONG WINAPI ddraw_gamma_control_Release(IDirectDrawGammaControl *iface)
734 struct ddraw_surface *This = impl_from_IDirectDrawGammaControl(iface);
735 ULONG refcount = InterlockedDecrement(&This->gamma_count);
737 TRACE("iface %p decreasing refcount to %u.\n", iface, refcount);
739 if (refcount == 0)
741 ddraw_surface_release_iface(This);
744 return refcount;
747 static ULONG WINAPI d3d_texture2_Release(IDirect3DTexture2 *iface)
749 struct ddraw_surface *surface = impl_from_IDirect3DTexture2(iface);
751 TRACE("iface %p.\n", iface);
753 return IUnknown_Release(surface->texture_outer);
756 static ULONG WINAPI d3d_texture1_Release(IDirect3DTexture *iface)
758 struct ddraw_surface *surface = impl_from_IDirect3DTexture(iface);
760 TRACE("iface %p.\n", iface);
762 return IUnknown_Release(surface->texture_outer);
765 /*****************************************************************************
766 * IDirectDrawSurface7::GetAttachedSurface
768 * Returns an attached surface with the requested caps. Surface attachment
769 * and complex surfaces are not clearly described by the MSDN or sdk,
770 * so this method is tricky and likely to contain problems.
771 * This implementation searches the complex list first, then the
772 * attachment chain.
774 * The chains are searched from This down to the last surface in the chain,
775 * not from the first element in the chain. The first surface found is
776 * returned. The MSDN says that this method fails if more than one surface
777 * matches the caps, but it is not sure if that is right. The attachment
778 * structure may not even allow two matching surfaces.
780 * The found surface is AddRef-ed before it is returned.
782 * Params:
783 * Caps: Pointer to a DDCAPS2 structure describing the caps asked for
784 * Surface: Address to store the found surface
786 * Returns:
787 * DD_OK on success
788 * DDERR_INVALIDPARAMS if Caps or Surface is NULL
789 * DDERR_NOTFOUND if no surface was found
791 *****************************************************************************/
792 static HRESULT WINAPI ddraw_surface7_GetAttachedSurface(IDirectDrawSurface7 *iface,
793 DDSCAPS2 *caps, IDirectDrawSurface7 **surface)
795 struct ddraw_surface *head_surface = impl_from_IDirectDrawSurface7(iface);
796 struct ddraw_surface *surf;
797 DDSCAPS2 our_caps;
798 int i;
800 TRACE("iface %p, caps %p, attachment %p.\n", iface, caps, surface);
802 if (ddraw_surface_is_lost(head_surface))
804 WARN("Surface %p is lost.\n", head_surface);
806 *surface = NULL;
807 return DDERR_SURFACELOST;
810 wined3d_mutex_lock();
812 if(head_surface->version < 7)
814 /* Earlier dx apps put garbage into these members, clear them */
815 our_caps.dwCaps = caps->dwCaps;
816 our_caps.dwCaps2 = 0;
817 our_caps.dwCaps3 = 0;
818 our_caps.u1.dwCaps4 = 0;
820 else
822 our_caps = *caps;
825 TRACE("head_surface %p, looking for caps %#x, %#x, %#x, %#x.\n", head_surface, our_caps.dwCaps,
826 our_caps.dwCaps2, our_caps.dwCaps3, our_caps.u1.dwCaps4); /* FIXME: Better debugging */
828 for(i = 0; i < MAX_COMPLEX_ATTACHED; i++)
830 surf = head_surface->complex_array[i];
831 if(!surf) break;
833 TRACE("Surface %p, caps %#x, %#x, %#x, %#x.\n", surf,
834 surf->surface_desc.ddsCaps.dwCaps,
835 surf->surface_desc.ddsCaps.dwCaps2,
836 surf->surface_desc.ddsCaps.dwCaps3,
837 surf->surface_desc.ddsCaps.u1.dwCaps4);
839 if (((surf->surface_desc.ddsCaps.dwCaps & our_caps.dwCaps) == our_caps.dwCaps) &&
840 ((surf->surface_desc.ddsCaps.dwCaps2 & our_caps.dwCaps2) == our_caps.dwCaps2)) {
842 /* MSDN: "This method fails if more than one surface is attached
843 * that matches the capabilities requested."
845 * Not sure how to test this.
848 TRACE("head_surface %p, returning surface %p.\n", head_surface, surf);
849 *surface = &surf->IDirectDrawSurface7_iface;
850 ddraw_surface7_AddRef(*surface);
851 wined3d_mutex_unlock();
853 return DD_OK;
857 /* Next, look at the attachment chain */
858 surf = head_surface;
860 while( (surf = surf->next_attached) )
862 TRACE("Surface %p, caps %#x, %#x, %#x, %#x.\n", surf,
863 surf->surface_desc.ddsCaps.dwCaps,
864 surf->surface_desc.ddsCaps.dwCaps2,
865 surf->surface_desc.ddsCaps.dwCaps3,
866 surf->surface_desc.ddsCaps.u1.dwCaps4);
868 if (((surf->surface_desc.ddsCaps.dwCaps & our_caps.dwCaps) == our_caps.dwCaps) &&
869 ((surf->surface_desc.ddsCaps.dwCaps2 & our_caps.dwCaps2) == our_caps.dwCaps2)) {
871 TRACE("head_surface %p, returning surface %p.\n", head_surface, surf);
872 *surface = &surf->IDirectDrawSurface7_iface;
873 ddraw_surface7_AddRef(*surface);
874 wined3d_mutex_unlock();
875 return DD_OK;
879 TRACE("head_surface %p, didn't find a valid surface.\n", head_surface);
881 wined3d_mutex_unlock();
883 *surface = NULL;
884 return DDERR_NOTFOUND;
887 static HRESULT WINAPI ddraw_surface4_GetAttachedSurface(IDirectDrawSurface4 *iface,
888 DDSCAPS2 *caps, IDirectDrawSurface4 **attachment)
890 struct ddraw_surface *surface = impl_from_IDirectDrawSurface4(iface);
891 struct ddraw_surface *attachment_impl;
892 IDirectDrawSurface7 *attachment7;
893 HRESULT hr;
895 TRACE("iface %p, caps %p, attachment %p.\n", iface, caps, attachment);
897 hr = ddraw_surface7_GetAttachedSurface(&surface->IDirectDrawSurface7_iface,
898 caps, &attachment7);
899 if (FAILED(hr))
901 *attachment = NULL;
902 return hr;
904 attachment_impl = impl_from_IDirectDrawSurface7(attachment7);
905 *attachment = &attachment_impl->IDirectDrawSurface4_iface;
906 ddraw_surface4_AddRef(*attachment);
907 ddraw_surface7_Release(attachment7);
909 return hr;
912 static HRESULT WINAPI ddraw_surface3_GetAttachedSurface(IDirectDrawSurface3 *iface,
913 DDSCAPS *caps, IDirectDrawSurface3 **attachment)
915 struct ddraw_surface *surface = impl_from_IDirectDrawSurface3(iface);
916 struct ddraw_surface *attachment_impl;
917 IDirectDrawSurface7 *attachment7;
918 DDSCAPS2 caps2;
919 HRESULT hr;
921 TRACE("iface %p, caps %p, attachment %p.\n", iface, caps, attachment);
923 caps2.dwCaps = caps->dwCaps;
924 caps2.dwCaps2 = 0;
925 caps2.dwCaps3 = 0;
926 caps2.u1.dwCaps4 = 0;
928 hr = ddraw_surface7_GetAttachedSurface(&surface->IDirectDrawSurface7_iface,
929 &caps2, &attachment7);
930 if (FAILED(hr))
932 *attachment = NULL;
933 return hr;
935 attachment_impl = impl_from_IDirectDrawSurface7(attachment7);
936 *attachment = &attachment_impl->IDirectDrawSurface3_iface;
937 ddraw_surface3_AddRef(*attachment);
938 ddraw_surface7_Release(attachment7);
940 return hr;
943 static HRESULT WINAPI ddraw_surface2_GetAttachedSurface(IDirectDrawSurface2 *iface,
944 DDSCAPS *caps, IDirectDrawSurface2 **attachment)
946 struct ddraw_surface *surface = impl_from_IDirectDrawSurface2(iface);
947 struct ddraw_surface *attachment_impl;
948 IDirectDrawSurface7 *attachment7;
949 DDSCAPS2 caps2;
950 HRESULT hr;
952 TRACE("iface %p, caps %p, attachment %p.\n", iface, caps, attachment);
954 caps2.dwCaps = caps->dwCaps;
955 caps2.dwCaps2 = 0;
956 caps2.dwCaps3 = 0;
957 caps2.u1.dwCaps4 = 0;
959 hr = ddraw_surface7_GetAttachedSurface(&surface->IDirectDrawSurface7_iface,
960 &caps2, &attachment7);
961 if (FAILED(hr))
963 *attachment = NULL;
964 return hr;
966 attachment_impl = impl_from_IDirectDrawSurface7(attachment7);
967 *attachment = &attachment_impl->IDirectDrawSurface2_iface;
968 ddraw_surface2_AddRef(*attachment);
969 ddraw_surface7_Release(attachment7);
971 return hr;
974 static HRESULT WINAPI ddraw_surface1_GetAttachedSurface(IDirectDrawSurface *iface,
975 DDSCAPS *caps, IDirectDrawSurface **attachment)
977 struct ddraw_surface *surface = impl_from_IDirectDrawSurface(iface);
978 struct ddraw_surface *attachment_impl;
979 IDirectDrawSurface7 *attachment7;
980 DDSCAPS2 caps2;
981 HRESULT hr;
983 TRACE("iface %p, caps %p, attachment %p.\n", iface, caps, attachment);
985 caps2.dwCaps = caps->dwCaps;
986 caps2.dwCaps2 = 0;
987 caps2.dwCaps3 = 0;
988 caps2.u1.dwCaps4 = 0;
990 hr = ddraw_surface7_GetAttachedSurface(&surface->IDirectDrawSurface7_iface,
991 &caps2, &attachment7);
992 if (FAILED(hr))
994 *attachment = NULL;
995 return hr;
997 attachment_impl = impl_from_IDirectDrawSurface7(attachment7);
998 *attachment = &attachment_impl->IDirectDrawSurface_iface;
999 ddraw_surface1_AddRef(*attachment);
1000 ddraw_surface7_Release(attachment7);
1002 return hr;
1005 /*****************************************************************************
1006 * IDirectDrawSurface7::Lock
1008 * Locks the surface and returns a pointer to the surface's memory
1010 * Params:
1011 * Rect: Rectangle to lock. If NULL, the whole surface is locked
1012 * DDSD: Pointer to a DDSURFACEDESC2 which shall receive the surface's desc.
1013 * Flags: Locking flags, e.g Read only or write only
1014 * h: An event handle that's not used and must be NULL
1016 * Returns:
1017 * DD_OK on success
1018 * DDERR_INVALIDPARAMS if DDSD is NULL
1020 *****************************************************************************/
1021 static HRESULT surface_lock(struct ddraw_surface *surface,
1022 RECT *rect, DDSURFACEDESC2 *surface_desc, unsigned int surface_desc_size,
1023 DWORD flags, HANDLE h)
1025 struct wined3d_map_desc map_desc;
1026 struct wined3d_box box;
1027 HRESULT hr = DD_OK;
1029 TRACE("surface %p, rect %s, surface_desc %p, surface_desc_size %u, flags %#x, h %p.\n",
1030 surface, wine_dbgstr_rect(rect), surface_desc, surface_desc_size, flags, h);
1032 /* surface->surface_desc.dwWidth and dwHeight are changeable, thus lock */
1033 wined3d_mutex_lock();
1035 /* Should I check for the handle to be NULL?
1037 * The DDLOCK flags and the D3DLOCK flags are equal
1038 * for the supported values. The others are ignored by WineD3D
1041 /* Windows zeroes this if the rect is invalid */
1042 surface_desc->lpSurface = NULL;
1044 if (rect)
1046 if ((rect->left < 0) || (rect->top < 0)
1047 || (rect->left > rect->right) || (rect->right > surface->surface_desc.dwWidth)
1048 || (rect->top > rect->bottom) || (rect->bottom > surface->surface_desc.dwHeight))
1050 WARN("Trying to lock an invalid rectangle, returning DDERR_INVALIDPARAMS\n");
1051 wined3d_mutex_unlock();
1052 return DDERR_INVALIDPARAMS;
1054 wined3d_box_set(&box, rect->left, rect->top, rect->right, rect->bottom, 0, 1);
1057 if (surface->surface_desc.ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE)
1058 hr = ddraw_surface_update_frontbuffer(surface, rect, TRUE, 0);
1059 if (SUCCEEDED(hr))
1060 hr = wined3d_resource_map(wined3d_texture_get_resource(surface->wined3d_texture),
1061 surface->sub_resource_idx, &map_desc, rect ? &box : NULL,
1062 wined3dmapflags_from_ddrawmapflags(flags));
1063 if (FAILED(hr))
1065 wined3d_mutex_unlock();
1066 switch(hr)
1068 /* D3D8 and D3D9 return the general D3DERR_INVALIDCALL error, but ddraw has a more
1069 * specific error. But since wined3d returns that error in this only occasion,
1070 * keep d3d8 and d3d9 free from the return value override. There are many different
1071 * places where d3d8/9 would have to catch the DDERR_SURFACEBUSY, it is much easier
1072 * to do it in one place in ddraw.
1074 case WINED3DERR_INVALIDCALL: return DDERR_SURFACEBUSY;
1075 default: return hr;
1079 if (surface->surface_desc.ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE)
1081 if (flags & DDLOCK_READONLY)
1082 SetRectEmpty(&surface->ddraw->primary_lock);
1083 else if (rect)
1084 surface->ddraw->primary_lock = *rect;
1085 else
1086 SetRect(&surface->ddraw->primary_lock, 0, 0, surface->surface_desc.dwWidth, surface->surface_desc.dwHeight);
1089 /* Windows does not set DDSD_LPSURFACE on locked surfaces. */
1090 DD_STRUCT_COPY_BYSIZE_(surface_desc, &surface->surface_desc, surface_desc_size, surface->surface_desc.dwSize);
1091 surface_desc->lpSurface = map_desc.data;
1093 TRACE("locked surface returning description :\n");
1094 if (TRACE_ON(ddraw))
1095 DDRAW_dump_surface_desc(surface_desc);
1097 wined3d_mutex_unlock();
1099 return DD_OK;
1102 static BOOL surface_validate_lock_desc(struct ddraw_surface *surface,
1103 const DDSURFACEDESC *desc, unsigned int *size)
1105 if (!desc)
1106 return FALSE;
1108 if (desc->dwSize == sizeof(DDSURFACEDESC) || desc->dwSize == sizeof(DDSURFACEDESC2))
1110 *size = desc->dwSize;
1111 return TRUE;
1114 if (surface->version == 7
1115 && surface->surface_desc.ddsCaps.dwCaps & DDSCAPS_TEXTURE
1116 && !(surface->surface_desc.ddsCaps.dwCaps & DDSCAPS_VIDEOMEMORY))
1118 if (desc->dwSize >= sizeof(DDSURFACEDESC2))
1119 *size = sizeof(DDSURFACEDESC2);
1120 else
1121 *size = sizeof(DDSURFACEDESC);
1122 return TRUE;
1125 WARN("Invalid structure size %u.\n", desc->dwSize);
1126 return FALSE;
1129 static HRESULT WINAPI ddraw_surface7_Lock(IDirectDrawSurface7 *iface,
1130 RECT *rect, DDSURFACEDESC2 *surface_desc, DWORD flags, HANDLE h)
1132 struct ddraw_surface *surface = impl_from_IDirectDrawSurface7(iface);
1133 unsigned int surface_desc_size;
1135 TRACE("iface %p, rect %s, surface_desc %p, flags %#x, h %p.\n",
1136 iface, wine_dbgstr_rect(rect), surface_desc, flags, h);
1138 if (!surface_validate_lock_desc(surface, (DDSURFACEDESC *)surface_desc, &surface_desc_size))
1139 return DDERR_INVALIDPARAMS;
1141 if (ddraw_surface_is_lost(surface))
1143 WARN("Surface is lost.\n");
1144 return DDERR_SURFACELOST;
1147 return surface_lock(surface, rect, surface_desc, surface_desc_size, flags, h);
1150 static HRESULT WINAPI ddraw_surface4_Lock(IDirectDrawSurface4 *iface, RECT *rect,
1151 DDSURFACEDESC2 *surface_desc, DWORD flags, HANDLE h)
1153 struct ddraw_surface *surface = impl_from_IDirectDrawSurface4(iface);
1154 unsigned int surface_desc_size;
1156 TRACE("iface %p, rect %s, surface_desc %p, flags %#x, h %p.\n",
1157 iface, wine_dbgstr_rect(rect), surface_desc, flags, h);
1159 if (!surface_validate_lock_desc(surface, (DDSURFACEDESC *)surface_desc, &surface_desc_size))
1160 return DDERR_INVALIDPARAMS;
1162 if (ddraw_surface_is_lost(surface))
1164 WARN("Surface is lost.\n");
1165 return DDERR_SURFACELOST;
1168 return surface_lock(surface, rect, surface_desc, surface_desc_size, flags, h);
1171 static HRESULT ddraw_surface_lock_ddsd(struct ddraw_surface *surface, RECT *rect,
1172 DDSURFACEDESC *surface_desc, DWORD flags, HANDLE h)
1174 unsigned int surface_desc_size;
1175 DDSURFACEDESC2 surface_desc2;
1176 HRESULT hr;
1178 if (!surface_validate_lock_desc(surface, surface_desc, &surface_desc_size))
1179 return DDERR_INVALIDPARAMS;
1181 if (ddraw_surface_is_lost(surface))
1183 WARN("Surface is lost.\n");
1184 return DDERR_SURFACELOST;
1187 surface_desc2.dwSize = surface_desc->dwSize;
1188 surface_desc2.dwFlags = 0;
1189 hr = surface_lock(surface, rect, &surface_desc2, surface_desc_size, flags, h);
1190 DDSD2_to_DDSD(&surface_desc2, surface_desc);
1191 surface_desc->dwSize = surface_desc2.dwSize;
1192 return hr;
1195 static HRESULT WINAPI ddraw_surface3_Lock(IDirectDrawSurface3 *iface, RECT *rect,
1196 DDSURFACEDESC *surface_desc, DWORD flags, HANDLE h)
1198 struct ddraw_surface *surface = impl_from_IDirectDrawSurface3(iface);
1200 TRACE("iface %p, rect %s, surface_desc %p, flags %#x, h %p.\n",
1201 iface, wine_dbgstr_rect(rect), surface_desc, flags, h);
1203 return ddraw_surface_lock_ddsd(surface, rect, surface_desc, flags, h);
1206 static HRESULT WINAPI ddraw_surface2_Lock(IDirectDrawSurface2 *iface, RECT *rect,
1207 DDSURFACEDESC *surface_desc, DWORD flags, HANDLE h)
1209 struct ddraw_surface *surface = impl_from_IDirectDrawSurface2(iface);
1211 TRACE("iface %p, rect %s, surface_desc %p, flags %#x, h %p.\n",
1212 iface, wine_dbgstr_rect(rect), surface_desc, flags, h);
1214 return ddraw_surface_lock_ddsd(surface, rect, surface_desc, flags, h);
1217 static HRESULT WINAPI ddraw_surface1_Lock(IDirectDrawSurface *iface, RECT *rect,
1218 DDSURFACEDESC *surface_desc, DWORD flags, HANDLE h)
1220 struct ddraw_surface *surface = impl_from_IDirectDrawSurface(iface);
1222 TRACE("iface %p, rect %s, surface_desc %p, flags %#x, h %p.\n",
1223 iface, wine_dbgstr_rect(rect), surface_desc, flags, h);
1225 return ddraw_surface_lock_ddsd(surface, rect, surface_desc, flags, h);
1228 /* FRAPS hooks IDirectDrawSurface::Unlock and expects the version 1 method to be called when the
1229 * game uses later interfaces. */
1230 static HRESULT WINAPI DECLSPEC_HOTPATCH ddraw_surface1_Unlock(IDirectDrawSurface *iface, void *data)
1232 struct ddraw_surface *surface = impl_from_IDirectDrawSurface(iface);
1233 HRESULT hr;
1235 TRACE("iface %p, data %p.\n", iface, data);
1237 wined3d_mutex_lock();
1238 hr = wined3d_resource_unmap(wined3d_texture_get_resource(surface->wined3d_texture), surface->sub_resource_idx);
1239 if (SUCCEEDED(hr) && surface->surface_desc.ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE)
1240 hr = ddraw_surface_update_frontbuffer(surface, &surface->ddraw->primary_lock, FALSE, 0);
1241 wined3d_mutex_unlock();
1243 return hr;
1246 static HRESULT WINAPI DECLSPEC_HOTPATCH ddraw_surface7_Unlock(IDirectDrawSurface7 *iface, RECT *rect)
1248 struct ddraw_surface *surface = impl_from_IDirectDrawSurface7(iface);
1250 TRACE("iface %p, rect %s.\n", iface, wine_dbgstr_rect(rect));
1252 return ddraw_surface1_Unlock(&surface->IDirectDrawSurface_iface, NULL);
1255 static HRESULT WINAPI DECLSPEC_HOTPATCH ddraw_surface4_Unlock(IDirectDrawSurface4 *iface, RECT *rect)
1257 struct ddraw_surface *surface = impl_from_IDirectDrawSurface4(iface);
1259 TRACE("iface %p, rect %s.\n", iface, wine_dbgstr_rect(rect));
1261 return ddraw_surface1_Unlock(&surface->IDirectDrawSurface_iface, NULL);
1264 static HRESULT WINAPI DECLSPEC_HOTPATCH ddraw_surface3_Unlock(IDirectDrawSurface3 *iface, void *data)
1266 struct ddraw_surface *surface = impl_from_IDirectDrawSurface3(iface);
1268 TRACE("iface %p, data %p.\n", iface, data);
1270 return ddraw_surface1_Unlock(&surface->IDirectDrawSurface_iface, data);
1273 static HRESULT WINAPI DECLSPEC_HOTPATCH ddraw_surface2_Unlock(IDirectDrawSurface2 *iface, void *data)
1275 struct ddraw_surface *surface = impl_from_IDirectDrawSurface2(iface);
1277 TRACE("iface %p, data %p.\n", iface, data);
1279 return ddraw_surface1_Unlock(&surface->IDirectDrawSurface_iface, data);
1282 static unsigned int ddraw_swap_interval_from_flags(DWORD flags)
1284 if (flags & DDFLIP_NOVSYNC)
1285 return 0;
1287 switch (flags & (DDFLIP_INTERVAL2 | DDFLIP_INTERVAL3 | DDFLIP_INTERVAL4))
1289 case DDFLIP_INTERVAL2:
1290 return 2;
1291 case DDFLIP_INTERVAL3:
1292 return 3;
1293 case DDFLIP_INTERVAL4:
1294 return 4;
1295 default:
1296 return 1;
1300 /* FRAPS hooks IDirectDrawSurface::Flip and expects the version 1 method to be called when the
1301 * game uses later interfaces. */
1302 static HRESULT WINAPI DECLSPEC_HOTPATCH ddraw_surface1_Flip(IDirectDrawSurface *iface,
1303 IDirectDrawSurface *src, DWORD flags)
1305 struct ddraw_surface *dst_impl = impl_from_IDirectDrawSurface(iface);
1306 struct ddraw_surface *src_impl = unsafe_impl_from_IDirectDrawSurface(src);
1307 struct ddraw_texture *dst_ddraw_texture, *src_ddraw_texture;
1308 struct wined3d_rendertarget_view *tmp_rtv, *src_rtv, *rtv;
1309 DDSCAPS caps = {DDSCAPS_FLIP};
1310 struct wined3d_texture *texture;
1311 IDirectDrawSurface *current;
1312 void *texture_memory;
1313 HRESULT hr;
1315 TRACE("iface %p, src %p, flags %#x.\n", iface, src, flags);
1317 if (src == iface || !(dst_impl->surface_desc.ddsCaps.dwCaps & (DDSCAPS_FRONTBUFFER | DDSCAPS_OVERLAY)))
1318 return DDERR_NOTFLIPPABLE;
1320 if (ddraw_surface_is_lost(dst_impl))
1321 return DDERR_SURFACELOST;
1323 wined3d_mutex_lock();
1325 if ((dst_impl->surface_desc.ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE)
1326 && !(dst_impl->ddraw->cooperative_level & DDSCL_EXCLUSIVE))
1328 WARN("Not in exclusive mode.\n");
1329 wined3d_mutex_unlock();
1330 return DDERR_NOEXCLUSIVEMODE;
1333 tmp_rtv = ddraw_surface_get_rendertarget_view(dst_impl);
1334 if (dst_impl->sub_resource_idx)
1335 ERR("Invalid sub-resource index %u on surface %p.\n", dst_impl->sub_resource_idx, dst_impl);
1336 texture = dst_impl->wined3d_texture;
1337 rtv = wined3d_device_get_rendertarget_view(dst_impl->ddraw->wined3d_device, 0);
1338 dst_ddraw_texture = wined3d_texture_get_parent(dst_impl->wined3d_texture);
1339 texture_memory = dst_ddraw_texture->texture_memory;
1341 if (src_impl)
1343 for (current = iface; current != src;)
1345 if (FAILED(hr = ddraw_surface1_GetAttachedSurface(current, &caps, &current)))
1347 WARN("Surface %p is not on the same flip chain as surface %p.\n", src, iface);
1348 wined3d_mutex_unlock();
1349 return DDERR_NOTFLIPPABLE;
1351 ddraw_surface1_Release(current);
1352 if (current == iface)
1354 WARN("Surface %p is not on the same flip chain as surface %p.\n", src, iface);
1355 wined3d_mutex_unlock();
1356 return DDERR_NOTFLIPPABLE;
1360 src_rtv = ddraw_surface_get_rendertarget_view(src_impl);
1361 if (rtv == dst_impl->wined3d_rtv)
1362 wined3d_device_set_rendertarget_view(dst_impl->ddraw->wined3d_device, 0, src_rtv, FALSE);
1363 wined3d_rendertarget_view_set_parent(src_rtv, dst_impl);
1364 dst_impl->wined3d_rtv = src_rtv;
1365 wined3d_texture_set_sub_resource_parent(src_impl->wined3d_texture, 0, dst_impl);
1366 src_ddraw_texture = wined3d_texture_get_parent(src_impl->wined3d_texture);
1367 dst_ddraw_texture->texture_memory = src_ddraw_texture->texture_memory;
1368 wined3d_resource_set_parent(wined3d_texture_get_resource(src_impl->wined3d_texture), dst_ddraw_texture);
1369 dst_ddraw_texture = src_ddraw_texture;
1370 if (src_impl->sub_resource_idx)
1371 ERR("Invalid sub-resource index %u on surface %p.\n", src_impl->sub_resource_idx, src_impl);
1372 dst_impl->wined3d_texture = src_impl->wined3d_texture;
1374 else
1376 for (current = iface;;)
1378 if (FAILED(hr = ddraw_surface1_GetAttachedSurface(current, &caps, &current)))
1380 ERR("Can't find a flip target\n");
1381 wined3d_mutex_unlock();
1382 return DDERR_NOTFLIPPABLE; /* Unchecked */
1384 ddraw_surface1_Release(current);
1385 if (current == iface)
1387 dst_impl = impl_from_IDirectDrawSurface(iface);
1388 break;
1391 src_impl = impl_from_IDirectDrawSurface(current);
1392 src_rtv = ddraw_surface_get_rendertarget_view(src_impl);
1393 if (rtv == dst_impl->wined3d_rtv)
1394 wined3d_device_set_rendertarget_view(dst_impl->ddraw->wined3d_device, 0, src_rtv, FALSE);
1395 wined3d_rendertarget_view_set_parent(src_rtv, dst_impl);
1396 dst_impl->wined3d_rtv = src_rtv;
1397 wined3d_texture_set_sub_resource_parent(src_impl->wined3d_texture, 0, dst_impl);
1398 src_ddraw_texture = wined3d_texture_get_parent(src_impl->wined3d_texture);
1399 dst_ddraw_texture->texture_memory = src_ddraw_texture->texture_memory;
1400 wined3d_resource_set_parent(wined3d_texture_get_resource(src_impl->wined3d_texture), dst_ddraw_texture);
1401 dst_ddraw_texture = src_ddraw_texture;
1402 if (src_impl->sub_resource_idx)
1403 ERR("Invalid sub-resource index %u on surface %p.\n", src_impl->sub_resource_idx, src_impl);
1404 dst_impl->wined3d_texture = src_impl->wined3d_texture;
1405 dst_impl = src_impl;
1409 /* We don't have to worry about potential texture bindings, since
1410 * flippable surfaces can never be textures. */
1411 if (rtv == src_impl->wined3d_rtv)
1412 wined3d_device_set_rendertarget_view(dst_impl->ddraw->wined3d_device, 0, tmp_rtv, FALSE);
1413 wined3d_rendertarget_view_set_parent(tmp_rtv, src_impl);
1414 src_impl->wined3d_rtv = tmp_rtv;
1415 wined3d_texture_set_sub_resource_parent(texture, 0, src_impl);
1416 dst_ddraw_texture->texture_memory = texture_memory;
1417 wined3d_resource_set_parent(wined3d_texture_get_resource(texture), dst_ddraw_texture);
1418 src_impl->wined3d_texture = texture;
1420 if (flags & ~(DDFLIP_NOVSYNC | DDFLIP_INTERVAL2 | DDFLIP_INTERVAL3 | DDFLIP_INTERVAL4))
1422 static UINT once;
1423 if (!once++)
1424 FIXME("Ignoring flags %#x.\n", flags);
1425 else
1426 WARN("Ignoring flags %#x.\n", flags);
1429 if (dst_impl->surface_desc.ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE)
1430 hr = ddraw_surface_update_frontbuffer(dst_impl, NULL, FALSE, ddraw_swap_interval_from_flags(flags));
1431 else
1432 hr = DD_OK;
1434 wined3d_mutex_unlock();
1436 return hr;
1439 static HRESULT WINAPI DECLSPEC_HOTPATCH ddraw_surface7_Flip(IDirectDrawSurface7 *iface,
1440 IDirectDrawSurface7 *src, DWORD flags)
1442 struct ddraw_surface *surface = impl_from_IDirectDrawSurface7(iface);
1443 struct ddraw_surface *src_impl = unsafe_impl_from_IDirectDrawSurface7(src);
1445 TRACE("iface %p, src %p, flags %#x.\n", iface, src, flags);
1447 return ddraw_surface1_Flip(&surface->IDirectDrawSurface_iface,
1448 src_impl ? &src_impl->IDirectDrawSurface_iface : NULL, flags);
1451 static HRESULT WINAPI DECLSPEC_HOTPATCH ddraw_surface4_Flip(IDirectDrawSurface4 *iface,
1452 IDirectDrawSurface4 *src, DWORD flags)
1454 struct ddraw_surface *surface = impl_from_IDirectDrawSurface4(iface);
1455 struct ddraw_surface *src_impl = unsafe_impl_from_IDirectDrawSurface4(src);
1457 TRACE("iface %p, src %p, flags %#x.\n", iface, src, flags);
1459 return ddraw_surface1_Flip(&surface->IDirectDrawSurface_iface,
1460 src_impl ? &src_impl->IDirectDrawSurface_iface : NULL, flags);
1463 static HRESULT WINAPI DECLSPEC_HOTPATCH ddraw_surface3_Flip(IDirectDrawSurface3 *iface,
1464 IDirectDrawSurface3 *src, DWORD flags)
1466 struct ddraw_surface *surface = impl_from_IDirectDrawSurface3(iface);
1467 struct ddraw_surface *src_impl = unsafe_impl_from_IDirectDrawSurface3(src);
1469 TRACE("iface %p, src %p, flags %#x.\n", iface, src, flags);
1471 return ddraw_surface1_Flip(&surface->IDirectDrawSurface_iface,
1472 src_impl ? &src_impl->IDirectDrawSurface_iface : NULL, flags);
1475 static HRESULT WINAPI DECLSPEC_HOTPATCH ddraw_surface2_Flip(IDirectDrawSurface2 *iface,
1476 IDirectDrawSurface2 *src, DWORD flags)
1478 struct ddraw_surface *surface = impl_from_IDirectDrawSurface2(iface);
1479 struct ddraw_surface *src_impl = unsafe_impl_from_IDirectDrawSurface2(src);
1481 TRACE("iface %p, src %p, flags %#x.\n", iface, src, flags);
1483 return ddraw_surface1_Flip(&surface->IDirectDrawSurface_iface,
1484 src_impl ? &src_impl->IDirectDrawSurface_iface : NULL, flags);
1487 static HRESULT ddraw_surface_blt(struct ddraw_surface *dst_surface, const RECT *dst_rect,
1488 struct ddraw_surface *src_surface, const RECT *src_rect, DWORD flags, DWORD fill_colour,
1489 const struct wined3d_blt_fx *fx, enum wined3d_texture_filter_type filter)
1491 struct wined3d_device *wined3d_device = dst_surface->ddraw->wined3d_device;
1492 struct wined3d_color colour;
1493 DWORD wined3d_flags;
1495 if (flags & DDBLT_COLORFILL)
1497 wined3d_flags = WINED3DCLEAR_TARGET;
1498 if (!(flags & DDBLT_ASYNC))
1499 wined3d_flags |= WINED3DCLEAR_SYNCHRONOUS;
1501 if (!wined3d_colour_from_ddraw_colour(&dst_surface->surface_desc.u4.ddpfPixelFormat,
1502 dst_surface->palette, fill_colour, &colour))
1503 return DDERR_INVALIDPARAMS;
1505 wined3d_device_apply_stateblock(wined3d_device, dst_surface->ddraw->state);
1506 return wined3d_device_clear_rendertarget_view(wined3d_device,
1507 ddraw_surface_get_rendertarget_view(dst_surface),
1508 dst_rect, wined3d_flags, &colour, 0.0f, 0);
1511 if (flags & DDBLT_DEPTHFILL)
1513 wined3d_flags = WINED3DCLEAR_ZBUFFER;
1514 if (!(flags & DDBLT_ASYNC))
1515 wined3d_flags |= WINED3DCLEAR_SYNCHRONOUS;
1517 if (!wined3d_colour_from_ddraw_colour(&dst_surface->surface_desc.u4.ddpfPixelFormat,
1518 dst_surface->palette, fill_colour, &colour))
1519 return DDERR_INVALIDPARAMS;
1521 wined3d_device_apply_stateblock(wined3d_device, dst_surface->ddraw->state);
1522 return wined3d_device_clear_rendertarget_view(wined3d_device,
1523 ddraw_surface_get_rendertarget_view(dst_surface),
1524 dst_rect, wined3d_flags, NULL, colour.r, 0);
1527 wined3d_flags = flags & ~DDBLT_ASYNC;
1528 if (wined3d_flags & ~WINED3D_BLT_MASK)
1530 FIXME("Unhandled flags %#x.\n", flags);
1531 return E_NOTIMPL;
1534 if (!(flags & DDBLT_ASYNC))
1535 wined3d_flags |= WINED3D_BLT_SYNCHRONOUS;
1537 return wined3d_texture_blt(dst_surface->wined3d_texture, dst_surface->sub_resource_idx, dst_rect,
1538 src_surface->wined3d_texture, src_surface->sub_resource_idx, src_rect, wined3d_flags, fx, filter);
1541 static HRESULT ddraw_surface_blt_clipped(struct ddraw_surface *dst_surface, const RECT *dst_rect_in,
1542 struct ddraw_surface *src_surface, const RECT *src_rect_in, DWORD flags, DWORD fill_colour,
1543 const struct wined3d_blt_fx *fx, enum wined3d_texture_filter_type filter)
1545 RECT src_rect, dst_rect;
1546 float scale_x, scale_y;
1547 const RECT *clip_rect;
1548 UINT clip_list_size;
1549 RGNDATA *clip_list;
1550 HRESULT hr = DD_OK;
1551 UINT i;
1553 if (!dst_rect_in)
1554 SetRect(&dst_rect, 0, 0, dst_surface->surface_desc.dwWidth,
1555 dst_surface->surface_desc.dwHeight);
1556 else
1557 dst_rect = *dst_rect_in;
1559 if (IsRectEmpty(&dst_rect))
1560 return DDERR_INVALIDRECT;
1562 if (src_surface)
1564 if (!src_rect_in)
1565 SetRect(&src_rect, 0, 0, src_surface->surface_desc.dwWidth,
1566 src_surface->surface_desc.dwHeight);
1567 else
1568 src_rect = *src_rect_in;
1570 if (IsRectEmpty(&src_rect))
1571 return DDERR_INVALIDRECT;
1573 else
1575 SetRectEmpty(&src_rect);
1578 if (!dst_surface->clipper)
1580 if (src_surface && src_surface->surface_desc.ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE)
1581 hr = ddraw_surface_update_frontbuffer(src_surface, &src_rect, TRUE, 0);
1582 if (SUCCEEDED(hr))
1583 hr = ddraw_surface_blt(dst_surface, &dst_rect, src_surface, &src_rect, flags, fill_colour, fx, filter);
1584 if (SUCCEEDED(hr) && (dst_surface->surface_desc.ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE))
1585 hr = ddraw_surface_update_frontbuffer(dst_surface, &dst_rect, FALSE, 0);
1587 return hr;
1590 if (!ddraw_clipper_is_valid(dst_surface->clipper))
1592 FIXME("Attempting to blit with an invalid clipper.\n");
1593 return DDERR_INVALIDPARAMS;
1596 scale_x = (float)(src_rect.right - src_rect.left) / (float)(dst_rect.right - dst_rect.left);
1597 scale_y = (float)(src_rect.bottom - src_rect.top) / (float)(dst_rect.bottom - dst_rect.top);
1599 if (FAILED(hr = IDirectDrawClipper_GetClipList(&dst_surface->clipper->IDirectDrawClipper_iface,
1600 &dst_rect, NULL, &clip_list_size)))
1602 WARN("Failed to get clip list size, hr %#x.\n", hr);
1603 return hr;
1606 if (!(clip_list = heap_alloc(clip_list_size)))
1608 WARN("Failed to allocate clip list.\n");
1609 return E_OUTOFMEMORY;
1612 if (FAILED(hr = IDirectDrawClipper_GetClipList(&dst_surface->clipper->IDirectDrawClipper_iface,
1613 &dst_rect, clip_list, &clip_list_size)))
1615 WARN("Failed to get clip list, hr %#x.\n", hr);
1616 heap_free(clip_list);
1617 return hr;
1620 clip_rect = (RECT *)clip_list->Buffer;
1621 for (i = 0; i < clip_list->rdh.nCount; ++i)
1623 RECT src_rect_clipped = src_rect;
1625 if (src_surface)
1627 src_rect_clipped.left += (LONG)((clip_rect[i].left - dst_rect.left) * scale_x);
1628 src_rect_clipped.top += (LONG)((clip_rect[i].top - dst_rect.top) * scale_y);
1629 src_rect_clipped.right -= (LONG)((dst_rect.right - clip_rect[i].right) * scale_x);
1630 src_rect_clipped.bottom -= (LONG)((dst_rect.bottom - clip_rect[i].bottom) * scale_y);
1632 if (src_surface->surface_desc.ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE)
1634 if (FAILED(hr = ddraw_surface_update_frontbuffer(src_surface, &src_rect_clipped, TRUE, 0)))
1635 break;
1639 if (FAILED(hr = ddraw_surface_blt(dst_surface, &clip_rect[i],
1640 src_surface, &src_rect_clipped, flags, fill_colour, fx, filter)))
1641 break;
1643 if (dst_surface->surface_desc.ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE)
1645 if (FAILED(hr = ddraw_surface_update_frontbuffer(dst_surface, &clip_rect[i], FALSE, 0)))
1646 break;
1650 heap_free(clip_list);
1651 return hr;
1654 /* FRAPS hooks IDirectDrawSurface::Blt and expects the version 1 method to be called when the
1655 * game uses later interfaces. */
1656 static HRESULT WINAPI DECLSPEC_HOTPATCH ddraw_surface1_Blt(IDirectDrawSurface *iface, RECT *dst_rect,
1657 IDirectDrawSurface *src_surface, RECT *src_rect, DWORD flags, DDBLTFX *fx)
1659 struct ddraw_surface *dst_impl = impl_from_IDirectDrawSurface(iface);
1660 struct ddraw_surface *src_impl = unsafe_impl_from_IDirectDrawSurface(src_surface);
1661 struct wined3d_blt_fx wined3d_fx;
1662 DWORD unsupported_flags;
1663 DWORD fill_colour = 0;
1664 HRESULT hr = DD_OK;
1665 DDBLTFX rop_fx;
1667 TRACE("iface %p, dst_rect %s, src_surface %p, src_rect %s, flags %#x, fx %p.\n",
1668 iface, wine_dbgstr_rect(dst_rect), src_surface, wine_dbgstr_rect(src_rect), flags, fx);
1670 unsupported_flags = DDBLT_ALPHADEST
1671 | DDBLT_ALPHADESTCONSTOVERRIDE
1672 | DDBLT_ALPHADESTNEG
1673 | DDBLT_ALPHADESTSURFACEOVERRIDE
1674 | DDBLT_ALPHAEDGEBLEND
1675 | DDBLT_ALPHASRC
1676 | DDBLT_ALPHASRCCONSTOVERRIDE
1677 | DDBLT_ALPHASRCNEG
1678 | DDBLT_ALPHASRCSURFACEOVERRIDE
1679 | DDBLT_ZBUFFER
1680 | DDBLT_ZBUFFERDESTCONSTOVERRIDE
1681 | DDBLT_ZBUFFERDESTOVERRIDE
1682 | DDBLT_ZBUFFERSRCCONSTOVERRIDE
1683 | DDBLT_ZBUFFERSRCOVERRIDE;
1684 if (flags & unsupported_flags)
1686 WARN("Ignoring unsupported flags %#x.\n", flags & unsupported_flags);
1687 flags &= ~unsupported_flags;
1690 if ((flags & DDBLT_KEYSRCOVERRIDE) && (!fx || flags & DDBLT_KEYSRC))
1692 WARN("Invalid source color key parameters, returning DDERR_INVALIDPARAMS\n");
1693 return DDERR_INVALIDPARAMS;
1696 if ((flags & DDBLT_KEYDESTOVERRIDE) && (!fx || flags & DDBLT_KEYDEST))
1698 WARN("Invalid destination color key parameters, returning DDERR_INVALIDPARAMS\n");
1699 return DDERR_INVALIDPARAMS;
1702 if (flags & DDBLT_DDROPS)
1704 FIXME("DDBLT_DDROPS not implemented.\n");
1705 if (fx)
1706 FIXME(" rop %#x, pattern %p.\n", fx->dwDDROP, fx->u5.lpDDSPattern);
1707 return DDERR_NORASTEROPHW;
1710 wined3d_mutex_lock();
1712 if (flags & (DDBLT_COLORFILL | DDBLT_DEPTHFILL))
1714 if (flags & DDBLT_ROP)
1716 wined3d_mutex_unlock();
1717 WARN("DDBLT_ROP used with DDBLT_COLORFILL or DDBLT_DEPTHFILL, returning DDERR_INVALIDPARAMS.\n");
1718 return DDERR_INVALIDPARAMS;
1720 if (src_impl)
1722 wined3d_mutex_unlock();
1723 WARN("Depth or colorfill is not compatible with source surfaces, returning DDERR_INVALIDPARAMS\n");
1724 return DDERR_INVALIDPARAMS;
1726 if (!fx)
1728 wined3d_mutex_unlock();
1729 WARN("Depth or colorfill used with NULL fx, returning DDERR_INVALIDPARAMS.\n");
1730 return DDERR_INVALIDPARAMS;
1733 if ((flags & (DDBLT_COLORFILL | DDBLT_DEPTHFILL)) == (DDBLT_COLORFILL | DDBLT_DEPTHFILL))
1734 flags &= ~DDBLT_DEPTHFILL;
1736 if ((dst_impl->surface_desc.ddsCaps.dwCaps & DDSCAPS_ZBUFFER) && (flags & DDBLT_COLORFILL))
1738 wined3d_mutex_unlock();
1739 WARN("DDBLT_COLORFILL used on a depth buffer, returning DDERR_INVALIDPARAMS.\n");
1740 return DDERR_INVALIDPARAMS;
1742 if (!(dst_impl->surface_desc.ddsCaps.dwCaps & DDSCAPS_ZBUFFER) && (flags & DDBLT_DEPTHFILL))
1744 wined3d_mutex_unlock();
1745 WARN("DDBLT_DEPTHFILL used on a color buffer, returning DDERR_INVALIDPARAMS.\n");
1746 return DDERR_INVALIDPARAMS;
1750 if (flags & DDBLT_ROP)
1752 if (!fx)
1754 wined3d_mutex_unlock();
1755 WARN("DDBLT_ROP used with NULL fx, returning DDERR_INVALIDPARAMS.\n");
1756 return DDERR_INVALIDPARAMS;
1759 if (src_impl && src_rect
1760 && ((ULONG)src_rect->left >= src_rect->right || src_rect->right > src_impl->surface_desc.dwWidth
1761 || (ULONG)src_rect->top >= src_rect->bottom || src_rect->bottom > src_impl->surface_desc.dwHeight))
1763 wined3d_mutex_unlock();
1764 WARN("Invalid source rectangle.\n");
1765 return DDERR_INVALIDRECT;
1768 flags &= ~DDBLT_ROP;
1769 switch (fx->dwROP)
1771 case SRCCOPY:
1772 break;
1774 case WHITENESS:
1775 case BLACKNESS:
1776 rop_fx = *fx;
1778 if (fx->dwROP == WHITENESS)
1779 rop_fx.u5.dwFillColor = 0xffffffff;
1780 else
1781 rop_fx.u5.dwFillColor = 0;
1783 if (dst_impl->surface_desc.ddsCaps.dwCaps & DDSCAPS_ZBUFFER)
1784 flags |= DDBLT_DEPTHFILL;
1785 else
1786 flags |= DDBLT_COLORFILL;
1788 fx = &rop_fx;
1789 break;
1791 default:
1792 wined3d_mutex_unlock();
1793 WARN("Unsupported ROP %#x used, returning DDERR_NORASTEROPHW.\n", fx->dwROP);
1794 return DDERR_NORASTEROPHW;
1798 if (!(flags & (DDBLT_COLORFILL | DDBLT_DEPTHFILL)) && !src_impl)
1800 WARN("No source surface.\n");
1801 wined3d_mutex_unlock();
1802 return DDERR_INVALIDPARAMS;
1805 if (flags & DDBLT_KEYSRC && (!src_impl || !(src_impl->surface_desc.dwFlags & DDSD_CKSRCBLT)))
1807 WARN("DDBLT_KEYSRC blit without color key in surface, returning DDERR_INVALIDPARAMS\n");
1808 wined3d_mutex_unlock();
1809 return DDERR_INVALIDPARAMS;
1811 if (flags & DDBLT_KEYDEST && !(dst_impl->surface_desc.dwFlags & DDSD_CKDESTBLT))
1813 WARN("DDBLT_KEYDEST blit without color key in surface, returning DDERR_INVALIDPARAMS\n");
1814 wined3d_mutex_unlock();
1815 return DDERR_INVALIDPARAMS;
1818 if (fx)
1820 wined3d_fx.fx = fx->dwDDFX;
1821 fill_colour = fx->u5.dwFillColor;
1822 wined3d_fx.dst_color_key.color_space_low_value = fx->ddckDestColorkey.dwColorSpaceLowValue;
1823 wined3d_fx.dst_color_key.color_space_high_value = fx->ddckDestColorkey.dwColorSpaceHighValue;
1824 wined3d_fx.src_color_key.color_space_low_value = fx->ddckSrcColorkey.dwColorSpaceLowValue;
1825 wined3d_fx.src_color_key.color_space_high_value = fx->ddckSrcColorkey.dwColorSpaceHighValue;
1828 hr = ddraw_surface_blt_clipped(dst_impl, dst_rect, src_impl,
1829 src_rect, flags, fill_colour, fx ? &wined3d_fx : NULL, WINED3D_TEXF_LINEAR);
1831 wined3d_mutex_unlock();
1832 switch(hr)
1834 case WINED3DERR_NOTAVAILABLE: return DDERR_UNSUPPORTED;
1835 default: return hr;
1839 static HRESULT WINAPI DECLSPEC_HOTPATCH ddraw_surface7_Blt(IDirectDrawSurface7 *iface, RECT *dst_rect,
1840 IDirectDrawSurface7 *src_surface, RECT *src_rect, DWORD flags, DDBLTFX *fx)
1842 struct ddraw_surface *dst = impl_from_IDirectDrawSurface7(iface);
1843 struct ddraw_surface *src = unsafe_impl_from_IDirectDrawSurface7(src_surface);
1845 TRACE("iface %p, dst_rect %s, src_surface %p, src_rect %s, flags %#x, fx %p.\n",
1846 iface, wine_dbgstr_rect(dst_rect), src_surface, wine_dbgstr_rect(src_rect), flags, fx);
1848 return ddraw_surface1_Blt(&dst->IDirectDrawSurface_iface, dst_rect,
1849 src ? &src->IDirectDrawSurface_iface : NULL, src_rect, flags, fx);
1852 static HRESULT WINAPI DECLSPEC_HOTPATCH ddraw_surface4_Blt(IDirectDrawSurface4 *iface, RECT *dst_rect,
1853 IDirectDrawSurface4 *src_surface, RECT *src_rect, DWORD flags, DDBLTFX *fx)
1855 struct ddraw_surface *dst = impl_from_IDirectDrawSurface4(iface);
1856 struct ddraw_surface *src = unsafe_impl_from_IDirectDrawSurface4(src_surface);
1858 TRACE("iface %p, dst_rect %s, src_surface %p, src_rect %s, flags %#x, fx %p.\n",
1859 iface, wine_dbgstr_rect(dst_rect), src_surface, wine_dbgstr_rect(src_rect), flags, fx);
1861 return ddraw_surface1_Blt(&dst->IDirectDrawSurface_iface, dst_rect,
1862 src ? &src->IDirectDrawSurface_iface : NULL, src_rect, flags, fx);
1865 static HRESULT WINAPI DECLSPEC_HOTPATCH ddraw_surface3_Blt(IDirectDrawSurface3 *iface, RECT *dst_rect,
1866 IDirectDrawSurface3 *src_surface, RECT *src_rect, DWORD flags, DDBLTFX *fx)
1868 struct ddraw_surface *dst = impl_from_IDirectDrawSurface3(iface);
1869 struct ddraw_surface *src = unsafe_impl_from_IDirectDrawSurface3(src_surface);
1871 TRACE("iface %p, dst_rect %s, src_surface %p, src_rect %s, flags %#x, fx %p.\n",
1872 iface, wine_dbgstr_rect(dst_rect), src_surface, wine_dbgstr_rect(src_rect), flags, fx);
1874 return ddraw_surface1_Blt(&dst->IDirectDrawSurface_iface, dst_rect,
1875 src ? &src->IDirectDrawSurface_iface : NULL, src_rect, flags, fx);
1878 static HRESULT WINAPI DECLSPEC_HOTPATCH ddraw_surface2_Blt(IDirectDrawSurface2 *iface, RECT *dst_rect,
1879 IDirectDrawSurface2 *src_surface, RECT *src_rect, DWORD flags, DDBLTFX *fx)
1881 struct ddraw_surface *dst = impl_from_IDirectDrawSurface2(iface);
1882 struct ddraw_surface *src = unsafe_impl_from_IDirectDrawSurface2(src_surface);
1884 TRACE("iface %p, dst_rect %s, src_surface %p, src_rect %s, flags %#x, fx %p.\n",
1885 iface, wine_dbgstr_rect(dst_rect), src_surface, wine_dbgstr_rect(src_rect), flags, fx);
1887 return ddraw_surface1_Blt(&dst->IDirectDrawSurface_iface, dst_rect,
1888 src ? &src->IDirectDrawSurface_iface : NULL, src_rect, flags, fx);
1891 /*****************************************************************************
1892 * IDirectDrawSurface7::AddAttachedSurface
1894 * Attaches a surface to another surface. How the surface attachments work
1895 * is not totally understood yet, and this method is prone to problems.
1896 * The surface that is attached is AddRef-ed.
1898 * Tests with complex surfaces suggest that the surface attachments form a
1899 * tree, but no method to test this has been found yet.
1901 * The attachment list consists of a first surface (first_attached) and
1902 * for each surface a pointer to the next attached surface (next_attached).
1903 * For the first surface, and a surface that has no attachments
1904 * first_attached points to the surface itself. A surface that has
1905 * no successors in the chain has next_attached set to NULL.
1907 * Newly attached surfaces are attached right after the root surface.
1908 * If a surface is attached to a complex surface compound, it's attached to
1909 * the surface that the app requested, not the complex root. See
1910 * GetAttachedSurface for a description how surfaces are found.
1912 * This is how the current implementation works, and it was coded by looking
1913 * at the needs of the applications.
1915 * So far only Z-Buffer attachments are tested, and they are activated in
1916 * WineD3D. Mipmaps could be tricky to activate in WineD3D.
1917 * Back buffers should work in 2D mode, but they are not tested(They can be
1918 * attached in older iface versions). Rendering to the front buffer and
1919 * switching between that and double buffering is not yet implemented in
1920 * WineD3D, so for 3D it might have unexpected results.
1922 * ddraw_surface_attach_surface is the real thing,
1923 * ddraw_surface7_AddAttachedSurface is a wrapper around it that
1924 * performs additional checks. Version 7 of this interface is much more restrictive
1925 * than its predecessors.
1927 * Params:
1928 * Attach: Surface to attach to iface
1930 * Returns:
1931 * DD_OK on success
1932 * DDERR_CANNOTATTACHSURFACE if the surface can't be attached for some reason
1934 *****************************************************************************/
1935 static HRESULT ddraw_surface_attach_surface(struct ddraw_surface *This, struct ddraw_surface *Surf)
1937 TRACE("surface %p, attachment %p.\n", This, Surf);
1939 if(Surf == This)
1940 return DDERR_CANNOTATTACHSURFACE; /* unchecked */
1942 wined3d_mutex_lock();
1944 /* Check if the surface is already attached somewhere */
1945 if (Surf->next_attached || Surf->first_attached != Surf)
1947 /* TODO: Test for the structure of the manual attachment. Is it a
1948 * chain or a list? What happens if one surface is attached to 2
1949 * different surfaces? */
1950 WARN("Surface %p is already attached somewhere. next_attached %p, first_attached %p.\n",
1951 Surf, Surf->next_attached, Surf->first_attached);
1953 wined3d_mutex_unlock();
1954 return DDERR_SURFACEALREADYATTACHED;
1957 /* This inserts the new surface at the 2nd position in the chain, right after the root surface */
1958 Surf->next_attached = This->next_attached;
1959 Surf->first_attached = This->first_attached;
1960 This->next_attached = Surf;
1962 /* Check if the WineD3D depth stencil needs updating */
1963 if (This->ddraw->d3ddevice)
1964 d3d_device_update_depth_stencil(This->ddraw->d3ddevice);
1966 wined3d_mutex_unlock();
1968 return DD_OK;
1971 static HRESULT WINAPI ddraw_surface7_AddAttachedSurface(IDirectDrawSurface7 *iface, IDirectDrawSurface7 *attachment)
1973 struct ddraw_surface *This = impl_from_IDirectDrawSurface7(iface);
1974 struct ddraw_surface *attachment_impl = unsafe_impl_from_IDirectDrawSurface7(attachment);
1975 HRESULT hr;
1977 TRACE("iface %p, attachment %p.\n", iface, attachment);
1979 /* Version 7 of this interface seems to refuse everything except z buffers, as per msdn */
1980 if(!(attachment_impl->surface_desc.ddsCaps.dwCaps & DDSCAPS_ZBUFFER))
1983 WARN("Application tries to attach a non Z buffer surface. caps %08x\n",
1984 attachment_impl->surface_desc.ddsCaps.dwCaps);
1985 return DDERR_CANNOTATTACHSURFACE;
1988 hr = ddraw_surface_attach_surface(This, attachment_impl);
1989 if (FAILED(hr))
1991 return hr;
1993 attachment_impl->attached_iface = (IUnknown *)attachment;
1994 IUnknown_AddRef(attachment_impl->attached_iface);
1995 return hr;
1998 static HRESULT WINAPI ddraw_surface4_AddAttachedSurface(IDirectDrawSurface4 *iface, IDirectDrawSurface4 *attachment)
2000 struct ddraw_surface *surface = impl_from_IDirectDrawSurface4(iface);
2001 struct ddraw_surface *attachment_impl = unsafe_impl_from_IDirectDrawSurface4(attachment);
2002 HRESULT hr;
2004 TRACE("iface %p, attachment %p.\n", iface, attachment);
2006 /* Tests suggest that
2007 * -> offscreen plain surfaces can be attached to other offscreen plain surfaces
2008 * -> offscreen plain surfaces can be attached to primaries
2009 * -> primaries can be attached to offscreen plain surfaces
2010 * -> z buffers can be attached to primaries */
2011 if (surface->surface_desc.ddsCaps.dwCaps & (DDSCAPS_PRIMARYSURFACE | DDSCAPS_OFFSCREENPLAIN)
2012 && attachment_impl->surface_desc.ddsCaps.dwCaps & (DDSCAPS_PRIMARYSURFACE | DDSCAPS_OFFSCREENPLAIN))
2014 /* Sizes have to match */
2015 if (attachment_impl->surface_desc.dwWidth != surface->surface_desc.dwWidth
2016 || attachment_impl->surface_desc.dwHeight != surface->surface_desc.dwHeight)
2018 WARN("Surface sizes do not match.\n");
2019 return DDERR_CANNOTATTACHSURFACE;
2022 else if (!(surface->surface_desc.ddsCaps.dwCaps & (DDSCAPS_PRIMARYSURFACE | DDSCAPS_3DDEVICE))
2023 || !(attachment_impl->surface_desc.ddsCaps.dwCaps & (DDSCAPS_ZBUFFER)))
2025 WARN("Invalid attachment combination.\n");
2026 return DDERR_CANNOTATTACHSURFACE;
2029 if (FAILED(hr = ddraw_surface_attach_surface(surface, attachment_impl)))
2030 return hr;
2032 attachment_impl->attached_iface = (IUnknown *)attachment;
2033 IUnknown_AddRef(attachment_impl->attached_iface);
2034 return hr;
2037 static HRESULT WINAPI ddraw_surface3_AddAttachedSurface(IDirectDrawSurface3 *iface, IDirectDrawSurface3 *attachment)
2039 struct ddraw_surface *surface = impl_from_IDirectDrawSurface3(iface);
2040 struct ddraw_surface *attachment_impl = unsafe_impl_from_IDirectDrawSurface3(attachment);
2041 HRESULT hr;
2043 TRACE("iface %p, attachment %p.\n", iface, attachment);
2045 if (FAILED(hr = ddraw_surface4_AddAttachedSurface(&surface->IDirectDrawSurface4_iface,
2046 attachment_impl ? &attachment_impl->IDirectDrawSurface4_iface : NULL)))
2047 return hr;
2049 attachment_impl->attached_iface = (IUnknown *)attachment;
2050 IUnknown_AddRef(attachment_impl->attached_iface);
2051 ddraw_surface4_Release(&attachment_impl->IDirectDrawSurface4_iface);
2052 return hr;
2055 static HRESULT WINAPI ddraw_surface2_AddAttachedSurface(IDirectDrawSurface2 *iface, IDirectDrawSurface2 *attachment)
2057 struct ddraw_surface *surface = impl_from_IDirectDrawSurface2(iface);
2058 struct ddraw_surface *attachment_impl = unsafe_impl_from_IDirectDrawSurface2(attachment);
2059 HRESULT hr;
2061 TRACE("iface %p, attachment %p.\n", iface, attachment);
2063 if (FAILED(hr = ddraw_surface4_AddAttachedSurface(&surface->IDirectDrawSurface4_iface,
2064 attachment_impl ? &attachment_impl->IDirectDrawSurface4_iface : NULL)))
2065 return hr;
2067 attachment_impl->attached_iface = (IUnknown *)attachment;
2068 IUnknown_AddRef(attachment_impl->attached_iface);
2069 ddraw_surface4_Release(&attachment_impl->IDirectDrawSurface4_iface);
2070 return hr;
2073 static HRESULT WINAPI ddraw_surface1_AddAttachedSurface(IDirectDrawSurface *iface, IDirectDrawSurface *attachment)
2075 struct ddraw_surface *surface = impl_from_IDirectDrawSurface(iface);
2076 struct ddraw_surface *attachment_impl = unsafe_impl_from_IDirectDrawSurface(attachment);
2077 HRESULT hr;
2079 TRACE("iface %p, attachment %p.\n", iface, attachment);
2081 if (FAILED(hr = ddraw_surface4_AddAttachedSurface(&surface->IDirectDrawSurface4_iface,
2082 attachment_impl ? &attachment_impl->IDirectDrawSurface4_iface : NULL)))
2083 return hr;
2085 attachment_impl->attached_iface = (IUnknown *)attachment;
2086 IUnknown_AddRef(attachment_impl->attached_iface);
2087 ddraw_surface4_Release(&attachment_impl->IDirectDrawSurface4_iface);
2088 return hr;
2091 /*****************************************************************************
2092 * IDirectDrawSurface7::DeleteAttachedSurface
2094 * Removes a surface from the attachment chain. The surface's refcount
2095 * is decreased by one after it has been removed
2097 * Params:
2098 * Flags: Some flags, not used by this implementation
2099 * Attach: Surface to detach
2101 * Returns:
2102 * DD_OK on success
2103 * DDERR_SURFACENOTATTACHED if the surface isn't attached to
2105 *****************************************************************************/
2106 static HRESULT ddraw_surface_delete_attached_surface(struct ddraw_surface *surface,
2107 struct ddraw_surface *attachment, IUnknown *detach_iface)
2109 struct ddraw_surface *prev = surface;
2111 TRACE("surface %p, attachment %p, detach_iface %p.\n", surface, attachment, detach_iface);
2113 wined3d_mutex_lock();
2114 if (!attachment || (attachment->first_attached != surface) || (attachment == surface) )
2116 wined3d_mutex_unlock();
2117 return DDERR_CANNOTDETACHSURFACE;
2120 if (attachment->attached_iface != detach_iface)
2122 WARN("attachment->attach_iface %p != detach_iface %p.\n", attachment->attached_iface, detach_iface);
2123 wined3d_mutex_unlock();
2124 return DDERR_SURFACENOTATTACHED;
2127 /* Remove MIPMAPSUBLEVEL if this seemed to be one */
2128 if (surface->surface_desc.ddsCaps.dwCaps & attachment->surface_desc.ddsCaps.dwCaps & DDSCAPS_MIPMAP)
2130 attachment->surface_desc.ddsCaps.dwCaps2 &= ~DDSCAPS2_MIPMAPSUBLEVEL;
2131 /* FIXME: we should probably also subtract from dwMipMapCount of this
2132 * and all parent surfaces */
2135 /* Find the predecessor of the detached surface */
2136 while (prev->next_attached != attachment)
2138 if (!(prev = prev->next_attached))
2140 ERR("Failed to find predecessor of %p.\n", attachment);
2141 wined3d_mutex_unlock();
2142 return DDERR_SURFACENOTATTACHED;
2146 /* Unchain the surface */
2147 prev->next_attached = attachment->next_attached;
2148 attachment->next_attached = NULL;
2149 attachment->first_attached = attachment;
2151 /* Check if the wined3d depth stencil needs updating. Note that we don't
2152 * just call d3d_device_update_depth_stencil() here since it uses
2153 * QueryInterface(). Some applications, SCP - Containment Breach in
2154 * particular, modify the QueryInterface() pointer in the surface vtbl
2155 * but don't cleanup properly after the relevant dll is unloaded. */
2156 if (attachment->surface_desc.ddsCaps.dwCaps & DDSCAPS_ZBUFFER
2157 && wined3d_device_get_depth_stencil_view(surface->ddraw->wined3d_device) == attachment->wined3d_rtv)
2158 wined3d_device_set_depth_stencil_view(surface->ddraw->wined3d_device, NULL);
2159 wined3d_mutex_unlock();
2161 /* Set attached_iface to NULL before releasing it, the surface may go
2162 * away. */
2163 attachment->attached_iface = NULL;
2164 IUnknown_Release(detach_iface);
2166 return DD_OK;
2169 static HRESULT WINAPI ddraw_surface7_DeleteAttachedSurface(IDirectDrawSurface7 *iface,
2170 DWORD flags, IDirectDrawSurface7 *attachment)
2172 struct ddraw_surface *surface = impl_from_IDirectDrawSurface7(iface);
2173 struct ddraw_surface *attachment_impl = unsafe_impl_from_IDirectDrawSurface7(attachment);
2175 TRACE("iface %p, flags %#x, attachment %p.\n", iface, flags, attachment);
2177 return ddraw_surface_delete_attached_surface(surface, attachment_impl, (IUnknown *)attachment);
2180 static HRESULT WINAPI ddraw_surface4_DeleteAttachedSurface(IDirectDrawSurface4 *iface,
2181 DWORD flags, IDirectDrawSurface4 *attachment)
2183 struct ddraw_surface *surface = impl_from_IDirectDrawSurface4(iface);
2184 struct ddraw_surface *attachment_impl = unsafe_impl_from_IDirectDrawSurface4(attachment);
2186 TRACE("iface %p, flags %#x, attachment %p.\n", iface, flags, attachment);
2188 return ddraw_surface_delete_attached_surface(surface, attachment_impl, (IUnknown *)attachment);
2191 static HRESULT WINAPI ddraw_surface3_DeleteAttachedSurface(IDirectDrawSurface3 *iface,
2192 DWORD flags, IDirectDrawSurface3 *attachment)
2194 struct ddraw_surface *surface = impl_from_IDirectDrawSurface3(iface);
2195 struct ddraw_surface *attachment_impl = unsafe_impl_from_IDirectDrawSurface3(attachment);
2197 TRACE("iface %p, flags %#x, attachment %p.\n", iface, flags, attachment);
2199 return ddraw_surface_delete_attached_surface(surface, attachment_impl, (IUnknown *)attachment);
2202 static HRESULT WINAPI ddraw_surface2_DeleteAttachedSurface(IDirectDrawSurface2 *iface,
2203 DWORD flags, IDirectDrawSurface2 *attachment)
2205 struct ddraw_surface *surface = impl_from_IDirectDrawSurface2(iface);
2206 struct ddraw_surface *attachment_impl = unsafe_impl_from_IDirectDrawSurface2(attachment);
2208 TRACE("iface %p, flags %#x, attachment %p.\n", iface, flags, attachment);
2210 return ddraw_surface_delete_attached_surface(surface, attachment_impl, (IUnknown *)attachment);
2213 static HRESULT WINAPI ddraw_surface1_DeleteAttachedSurface(IDirectDrawSurface *iface,
2214 DWORD flags, IDirectDrawSurface *attachment)
2216 struct ddraw_surface *surface = impl_from_IDirectDrawSurface(iface);
2217 struct ddraw_surface *attachment_impl = unsafe_impl_from_IDirectDrawSurface(attachment);
2219 TRACE("iface %p, flags %#x, attachment %p.\n", iface, flags, attachment);
2221 return ddraw_surface_delete_attached_surface(surface, attachment_impl, (IUnknown *)attachment);
2224 /*****************************************************************************
2225 * IDirectDrawSurface7::AddOverlayDirtyRect
2227 * "This method is not currently implemented"
2229 * Params:
2230 * Rect: ?
2232 * Returns:
2233 * DDERR_UNSUPPORTED
2235 *****************************************************************************/
2236 static HRESULT WINAPI ddraw_surface7_AddOverlayDirtyRect(IDirectDrawSurface7 *iface, RECT *Rect)
2238 TRACE("iface %p, rect %s.\n", iface, wine_dbgstr_rect(Rect));
2240 return DDERR_UNSUPPORTED; /* unchecked */
2243 static HRESULT WINAPI ddraw_surface4_AddOverlayDirtyRect(IDirectDrawSurface4 *iface, RECT *rect)
2245 struct ddraw_surface *surface = impl_from_IDirectDrawSurface4(iface);
2247 TRACE("iface %p, rect %s.\n", iface, wine_dbgstr_rect(rect));
2249 return ddraw_surface7_AddOverlayDirtyRect(&surface->IDirectDrawSurface7_iface, rect);
2252 static HRESULT WINAPI ddraw_surface3_AddOverlayDirtyRect(IDirectDrawSurface3 *iface, RECT *rect)
2254 struct ddraw_surface *surface = impl_from_IDirectDrawSurface3(iface);
2256 TRACE("iface %p, rect %s.\n", iface, wine_dbgstr_rect(rect));
2258 return ddraw_surface7_AddOverlayDirtyRect(&surface->IDirectDrawSurface7_iface, rect);
2261 static HRESULT WINAPI ddraw_surface2_AddOverlayDirtyRect(IDirectDrawSurface2 *iface, RECT *rect)
2263 struct ddraw_surface *surface = impl_from_IDirectDrawSurface2(iface);
2265 TRACE("iface %p, rect %s.\n", iface, wine_dbgstr_rect(rect));
2267 return ddraw_surface7_AddOverlayDirtyRect(&surface->IDirectDrawSurface7_iface, rect);
2270 static HRESULT WINAPI ddraw_surface1_AddOverlayDirtyRect(IDirectDrawSurface *iface, RECT *rect)
2272 struct ddraw_surface *surface = impl_from_IDirectDrawSurface(iface);
2274 TRACE("iface %p, rect %s.\n", iface, wine_dbgstr_rect(rect));
2276 return ddraw_surface7_AddOverlayDirtyRect(&surface->IDirectDrawSurface7_iface, rect);
2279 /*****************************************************************************
2280 * IDirectDrawSurface7::GetDC
2282 * Returns a GDI device context for the surface
2284 * Params:
2285 * hdc: Address of a HDC variable to store the dc to
2287 * Returns:
2288 * DD_OK on success
2289 * DDERR_INVALIDPARAMS if hdc is NULL
2291 *****************************************************************************/
2292 static HRESULT WINAPI ddraw_surface7_GetDC(IDirectDrawSurface7 *iface, HDC *dc)
2294 struct ddraw_surface *surface = impl_from_IDirectDrawSurface7(iface);
2295 HRESULT hr = DD_OK;
2297 TRACE("iface %p, dc %p.\n", iface, dc);
2299 if (!dc)
2300 return DDERR_INVALIDPARAMS;
2302 wined3d_mutex_lock();
2303 if (surface->dc)
2304 hr = DDERR_DCALREADYCREATED;
2305 else if (surface->surface_desc.ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE)
2306 hr = ddraw_surface_update_frontbuffer(surface, NULL, TRUE, 0);
2307 if (SUCCEEDED(hr))
2308 hr = wined3d_texture_get_dc(surface->wined3d_texture, surface->sub_resource_idx, dc);
2310 if (SUCCEEDED(hr))
2312 surface->dc = *dc;
2314 if (format_is_paletteindexed(&surface->surface_desc.u4.ddpfPixelFormat))
2316 const struct ddraw_palette *palette;
2318 if (surface->palette)
2319 palette = surface->palette;
2320 else if (surface->ddraw->primary)
2321 palette = surface->ddraw->primary->palette;
2322 else
2323 palette = NULL;
2325 if (palette)
2326 wined3d_palette_apply_to_dc(palette->wined3d_palette, *dc);
2330 wined3d_mutex_unlock();
2331 switch (hr)
2333 /* Some, but not all errors set *dc to NULL. E.g. DCALREADYCREATED
2334 * does not touch *dc. */
2335 case WINED3DERR_INVALIDCALL:
2336 *dc = NULL;
2337 return DDERR_CANTCREATEDC;
2339 default:
2340 return hr;
2344 static HRESULT WINAPI ddraw_surface4_GetDC(IDirectDrawSurface4 *iface, HDC *dc)
2346 struct ddraw_surface *surface = impl_from_IDirectDrawSurface4(iface);
2348 TRACE("iface %p, dc %p.\n", iface, dc);
2350 return ddraw_surface7_GetDC(&surface->IDirectDrawSurface7_iface, dc);
2353 static HRESULT WINAPI ddraw_surface3_GetDC(IDirectDrawSurface3 *iface, HDC *dc)
2355 struct ddraw_surface *surface = impl_from_IDirectDrawSurface3(iface);
2357 TRACE("iface %p, dc %p.\n", iface, dc);
2359 return ddraw_surface7_GetDC(&surface->IDirectDrawSurface7_iface, dc);
2362 static HRESULT WINAPI ddraw_surface2_GetDC(IDirectDrawSurface2 *iface, HDC *dc)
2364 struct ddraw_surface *surface = impl_from_IDirectDrawSurface2(iface);
2366 TRACE("iface %p, dc %p.\n", iface, dc);
2368 return ddraw_surface7_GetDC(&surface->IDirectDrawSurface7_iface, dc);
2371 static HRESULT WINAPI ddraw_surface1_GetDC(IDirectDrawSurface *iface, HDC *dc)
2373 struct ddraw_surface *surface = impl_from_IDirectDrawSurface(iface);
2375 TRACE("iface %p, dc %p.\n", iface, dc);
2377 return ddraw_surface7_GetDC(&surface->IDirectDrawSurface7_iface, dc);
2380 /*****************************************************************************
2381 * IDirectDrawSurface7::ReleaseDC
2383 * Releases the DC that was constructed with GetDC
2385 * Params:
2386 * hdc: HDC to release
2388 * Returns:
2389 * DD_OK on success, error code otherwise.
2391 *****************************************************************************/
2392 static HRESULT WINAPI ddraw_surface7_ReleaseDC(IDirectDrawSurface7 *iface, HDC hdc)
2394 struct ddraw_surface *surface = impl_from_IDirectDrawSurface7(iface);
2395 HRESULT hr;
2397 TRACE("iface %p, dc %p.\n", iface, hdc);
2399 wined3d_mutex_lock();
2400 if (!surface->dc)
2402 hr = DDERR_NODC;
2404 else if (SUCCEEDED(hr = wined3d_texture_release_dc(surface->wined3d_texture, surface->sub_resource_idx, hdc)))
2406 surface->dc = NULL;
2407 if (surface->surface_desc.ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE)
2408 hr = ddraw_surface_update_frontbuffer(surface, NULL, FALSE, 0);
2410 wined3d_mutex_unlock();
2413 return hr;
2416 static HRESULT WINAPI ddraw_surface4_ReleaseDC(IDirectDrawSurface4 *iface, HDC dc)
2418 struct ddraw_surface *surface = impl_from_IDirectDrawSurface4(iface);
2420 TRACE("iface %p, dc %p.\n", iface, dc);
2422 return ddraw_surface7_ReleaseDC(&surface->IDirectDrawSurface7_iface, dc);
2425 static HRESULT WINAPI ddraw_surface3_ReleaseDC(IDirectDrawSurface3 *iface, HDC dc)
2427 struct ddraw_surface *surface = impl_from_IDirectDrawSurface3(iface);
2429 TRACE("iface %p, dc %p.\n", iface, dc);
2431 return ddraw_surface7_ReleaseDC(&surface->IDirectDrawSurface7_iface, dc);
2434 static HRESULT WINAPI ddraw_surface2_ReleaseDC(IDirectDrawSurface2 *iface, HDC dc)
2436 struct ddraw_surface *surface = impl_from_IDirectDrawSurface2(iface);
2438 TRACE("iface %p, dc %p.\n", iface, dc);
2440 return ddraw_surface7_ReleaseDC(&surface->IDirectDrawSurface7_iface, dc);
2443 static HRESULT WINAPI ddraw_surface1_ReleaseDC(IDirectDrawSurface *iface, HDC dc)
2445 struct ddraw_surface *surface = impl_from_IDirectDrawSurface(iface);
2447 TRACE("iface %p, dc %p.\n", iface, dc);
2449 return ddraw_surface7_ReleaseDC(&surface->IDirectDrawSurface7_iface, dc);
2452 /*****************************************************************************
2453 * IDirectDrawSurface7::GetCaps
2455 * Returns the surface's caps
2457 * Params:
2458 * Caps: Address to write the caps to
2460 * Returns:
2461 * DD_OK on success
2462 * DDERR_INVALIDPARAMS if Caps is NULL
2464 *****************************************************************************/
2465 static HRESULT WINAPI ddraw_surface7_GetCaps(IDirectDrawSurface7 *iface, DDSCAPS2 *Caps)
2467 struct ddraw_surface *surface = impl_from_IDirectDrawSurface7(iface);
2469 TRACE("iface %p, caps %p.\n", iface, Caps);
2471 if(!Caps)
2472 return DDERR_INVALIDPARAMS;
2474 *Caps = surface->surface_desc.ddsCaps;
2476 return DD_OK;
2479 static HRESULT WINAPI ddraw_surface4_GetCaps(IDirectDrawSurface4 *iface, DDSCAPS2 *caps)
2481 struct ddraw_surface *surface = impl_from_IDirectDrawSurface4(iface);
2483 TRACE("iface %p, caps %p.\n", iface, caps);
2485 return ddraw_surface7_GetCaps(&surface->IDirectDrawSurface7_iface, caps);
2488 static HRESULT WINAPI ddraw_surface3_GetCaps(IDirectDrawSurface3 *iface, DDSCAPS *caps)
2490 struct ddraw_surface *surface = impl_from_IDirectDrawSurface3(iface);
2491 DDSCAPS2 caps2;
2492 HRESULT hr;
2494 TRACE("iface %p, caps %p.\n", iface, caps);
2496 hr = ddraw_surface7_GetCaps(&surface->IDirectDrawSurface7_iface, &caps2);
2497 if (FAILED(hr)) return hr;
2499 caps->dwCaps = caps2.dwCaps;
2500 return hr;
2503 static HRESULT WINAPI ddraw_surface2_GetCaps(IDirectDrawSurface2 *iface, DDSCAPS *caps)
2505 struct ddraw_surface *surface = impl_from_IDirectDrawSurface2(iface);
2506 DDSCAPS2 caps2;
2507 HRESULT hr;
2509 TRACE("iface %p, caps %p.\n", iface, caps);
2511 hr = ddraw_surface7_GetCaps(&surface->IDirectDrawSurface7_iface, &caps2);
2512 if (FAILED(hr)) return hr;
2514 caps->dwCaps = caps2.dwCaps;
2515 return hr;
2518 static HRESULT WINAPI ddraw_surface1_GetCaps(IDirectDrawSurface *iface, DDSCAPS *caps)
2520 struct ddraw_surface *surface = impl_from_IDirectDrawSurface(iface);
2521 DDSCAPS2 caps2;
2522 HRESULT hr;
2524 TRACE("iface %p, caps %p.\n", iface, caps);
2526 hr = ddraw_surface7_GetCaps(&surface->IDirectDrawSurface7_iface, &caps2);
2527 if (FAILED(hr)) return hr;
2529 caps->dwCaps = caps2.dwCaps;
2530 return hr;
2533 static HRESULT WINAPI ddraw_surface7_SetPriority(IDirectDrawSurface7 *iface, DWORD priority)
2535 struct ddraw_surface *surface = impl_from_IDirectDrawSurface7(iface);
2536 DWORD managed = DDSCAPS2_TEXTUREMANAGE | DDSCAPS2_D3DTEXTUREMANAGE;
2537 HRESULT hr;
2538 struct wined3d_resource *resource;
2540 TRACE("iface %p, priority %u.\n", iface, priority);
2542 wined3d_mutex_lock();
2543 /* No need to check for offscreen plain surfaces or mipmap sublevels. SetPriority
2544 * calls on such surfaces segfault on Windows. */
2545 if (!(surface->surface_desc.ddsCaps.dwCaps2 & managed))
2547 WARN("Called on non-managed texture returning DDERR_INVALIDPARAMS.\n");
2548 hr = DDERR_INVALIDPARAMS;
2550 else
2552 resource = wined3d_texture_get_resource(surface->wined3d_texture);
2553 wined3d_resource_set_priority(resource, priority);
2554 hr = DD_OK;
2556 wined3d_mutex_unlock();
2558 return hr;
2561 static HRESULT WINAPI ddraw_surface7_GetPriority(IDirectDrawSurface7 *iface, DWORD *priority)
2563 struct ddraw_surface *surface = impl_from_IDirectDrawSurface7(iface);
2564 const struct wined3d_resource *resource;
2565 DWORD managed = DDSCAPS2_TEXTUREMANAGE | DDSCAPS2_D3DTEXTUREMANAGE;
2566 HRESULT hr;
2568 TRACE("iface %p, priority %p.\n", iface, priority);
2570 wined3d_mutex_lock();
2571 if (surface->surface_desc.ddsCaps.dwCaps & DDSCAPS_OFFSCREENPLAIN)
2573 WARN("Called on offscreenplain surface, returning DDERR_INVALIDOBJECT.\n");
2574 hr = DDERR_INVALIDOBJECT;
2576 else if (!(surface->surface_desc.ddsCaps.dwCaps2 & managed) || !surface->is_complex_root)
2578 WARN("Called on non-managed texture or non-root surface, returning DDERR_INVALIDPARAMS.\n");
2579 hr = DDERR_INVALIDPARAMS;
2581 else
2583 resource = wined3d_texture_get_resource(surface->wined3d_texture);
2584 *priority = wined3d_resource_get_priority(resource);
2585 hr = DD_OK;
2587 wined3d_mutex_unlock();
2589 return hr;
2592 /*****************************************************************************
2593 * IDirectDrawSurface7::SetPrivateData
2595 * Stores some data in the surface that is intended for the application's
2596 * use.
2598 * Params:
2599 * tag: GUID that identifies the data
2600 * Data: Pointer to the private data
2601 * Size: Size of the private data
2602 * Flags: Some flags
2604 * Returns:
2605 * D3D_OK on success, error code otherwise.
2607 *****************************************************************************/
2608 static HRESULT WINAPI ddraw_surface7_SetPrivateData(IDirectDrawSurface7 *iface,
2609 REFGUID tag, void *data, DWORD size, DWORD flags)
2611 struct ddraw_surface *surface = impl_from_IDirectDrawSurface7(iface);
2612 HRESULT hr;
2614 TRACE("iface %p, tag %s, data %p, data_size %u, flags %#x.\n",
2615 iface, debugstr_guid(tag), data, size, flags);
2617 if (!data)
2619 WARN("data is NULL, returning DDERR_INVALIDPARAMS.\n");
2620 return DDERR_INVALIDPARAMS;
2623 wined3d_mutex_lock();
2624 hr = wined3d_private_store_set_private_data(&surface->private_store, tag, data, size, flags);
2625 wined3d_mutex_unlock();
2626 return hr_ddraw_from_wined3d(hr);
2629 static HRESULT WINAPI ddraw_surface4_SetPrivateData(IDirectDrawSurface4 *iface,
2630 REFGUID tag, void *data, DWORD size, DWORD flags)
2632 struct ddraw_surface *surface = impl_from_IDirectDrawSurface4(iface);
2634 TRACE("iface %p, tag %s, data %p, data_size %u, flags %#x.\n",
2635 iface, debugstr_guid(tag), data, size, flags);
2637 return ddraw_surface7_SetPrivateData(&surface->IDirectDrawSurface7_iface, tag, data, size, flags);
2640 /*****************************************************************************
2641 * IDirectDrawSurface7::GetPrivateData
2643 * Returns the private data set with IDirectDrawSurface7::SetPrivateData
2645 * Params:
2646 * tag: GUID of the data to return
2647 * Data: Address where to write the data to
2648 * Size: Size of the buffer at Data
2650 * Returns:
2651 * DD_OK on success
2652 * DDERR_INVALIDPARAMS if Data is NULL
2654 *****************************************************************************/
2655 static HRESULT WINAPI ddraw_surface7_GetPrivateData(IDirectDrawSurface7 *iface, REFGUID tag, void *data, DWORD *size)
2657 struct ddraw_surface *surface = impl_from_IDirectDrawSurface7(iface);
2658 const struct wined3d_private_data *stored_data;
2659 HRESULT hr;
2661 TRACE("iface %p, tag %s, data %p, data_size %p.\n",
2662 iface, debugstr_guid(tag), data, size);
2664 wined3d_mutex_lock();
2665 stored_data = wined3d_private_store_get_private_data(&surface->private_store, tag);
2666 if (!stored_data)
2668 hr = DDERR_NOTFOUND;
2669 goto done;
2671 if (!size)
2673 hr = DDERR_INVALIDPARAMS;
2674 goto done;
2676 if (*size < stored_data->size)
2678 *size = stored_data->size;
2679 hr = DDERR_MOREDATA;
2680 goto done;
2682 if (!data)
2684 hr = DDERR_INVALIDPARAMS;
2685 goto done;
2688 *size = stored_data->size;
2689 memcpy(data, stored_data->content.data, stored_data->size);
2690 hr = DD_OK;
2692 done:
2693 wined3d_mutex_unlock();
2694 return hr;
2697 static HRESULT WINAPI ddraw_surface4_GetPrivateData(IDirectDrawSurface4 *iface, REFGUID tag, void *data, DWORD *size)
2699 struct ddraw_surface *surface = impl_from_IDirectDrawSurface4(iface);
2701 TRACE("iface %p, tag %s, data %p, data_size %p.\n",
2702 iface, debugstr_guid(tag), data, size);
2704 return ddraw_surface7_GetPrivateData(&surface->IDirectDrawSurface7_iface, tag, data, size);
2707 /*****************************************************************************
2708 * IDirectDrawSurface7::FreePrivateData
2710 * Frees private data stored in the surface
2712 * Params:
2713 * tag: Tag of the data to free
2715 * Returns:
2716 * D3D_OK on success, error code otherwise.
2718 *****************************************************************************/
2719 static HRESULT WINAPI ddraw_surface7_FreePrivateData(IDirectDrawSurface7 *iface, REFGUID tag)
2721 struct ddraw_surface *surface = impl_from_IDirectDrawSurface7(iface);
2722 struct wined3d_private_data *entry;
2724 TRACE("iface %p, tag %s.\n", iface, debugstr_guid(tag));
2726 wined3d_mutex_lock();
2727 entry = wined3d_private_store_get_private_data(&surface->private_store, tag);
2728 if (!entry)
2730 wined3d_mutex_unlock();
2731 return DDERR_NOTFOUND;
2734 wined3d_private_store_free_private_data(&surface->private_store, entry);
2735 wined3d_mutex_unlock();
2737 return DD_OK;
2740 static HRESULT WINAPI ddraw_surface4_FreePrivateData(IDirectDrawSurface4 *iface, REFGUID tag)
2742 struct ddraw_surface *surface = impl_from_IDirectDrawSurface4(iface);
2744 TRACE("iface %p, tag %s.\n", iface, debugstr_guid(tag));
2746 return ddraw_surface7_FreePrivateData(&surface->IDirectDrawSurface7_iface, tag);
2749 /*****************************************************************************
2750 * IDirectDrawSurface7::PageLock
2752 * Prevents a sysmem surface from being paged out
2754 * Params:
2755 * Flags: Not used, must be 0(unchecked)
2757 * Returns:
2758 * DD_OK, because it's a stub
2760 *****************************************************************************/
2761 static HRESULT WINAPI ddraw_surface7_PageLock(IDirectDrawSurface7 *iface, DWORD Flags)
2763 TRACE("iface %p, flags %#x.\n", iface, Flags);
2765 /* This is Windows memory management related - we don't need this */
2766 return DD_OK;
2769 static HRESULT WINAPI ddraw_surface4_PageLock(IDirectDrawSurface4 *iface, DWORD flags)
2771 struct ddraw_surface *surface = impl_from_IDirectDrawSurface4(iface);
2773 TRACE("iface %p, flags %#x.\n", iface, flags);
2775 return ddraw_surface7_PageLock(&surface->IDirectDrawSurface7_iface, flags);
2778 static HRESULT WINAPI ddraw_surface3_PageLock(IDirectDrawSurface3 *iface, DWORD flags)
2780 struct ddraw_surface *surface = impl_from_IDirectDrawSurface3(iface);
2782 TRACE("iface %p, flags %#x.\n", iface, flags);
2784 return ddraw_surface7_PageLock(&surface->IDirectDrawSurface7_iface, flags);
2787 static HRESULT WINAPI ddraw_surface2_PageLock(IDirectDrawSurface2 *iface, DWORD flags)
2789 struct ddraw_surface *surface = impl_from_IDirectDrawSurface2(iface);
2791 TRACE("iface %p, flags %#x.\n", iface, flags);
2793 return ddraw_surface7_PageLock(&surface->IDirectDrawSurface7_iface, flags);
2796 /*****************************************************************************
2797 * IDirectDrawSurface7::PageUnlock
2799 * Allows a sysmem surface to be paged out
2801 * Params:
2802 * Flags: Not used, must be 0(unchecked)
2804 * Returns:
2805 * DD_OK, because it's a stub
2807 *****************************************************************************/
2808 static HRESULT WINAPI ddraw_surface7_PageUnlock(IDirectDrawSurface7 *iface, DWORD Flags)
2810 TRACE("iface %p, flags %#x.\n", iface, Flags);
2812 return DD_OK;
2815 static HRESULT WINAPI ddraw_surface4_PageUnlock(IDirectDrawSurface4 *iface, DWORD flags)
2817 struct ddraw_surface *surface = impl_from_IDirectDrawSurface4(iface);
2819 TRACE("iface %p, flags %#x.\n", iface, flags);
2821 return ddraw_surface7_PageUnlock(&surface->IDirectDrawSurface7_iface, flags);
2824 static HRESULT WINAPI ddraw_surface3_PageUnlock(IDirectDrawSurface3 *iface, DWORD flags)
2826 struct ddraw_surface *surface = impl_from_IDirectDrawSurface3(iface);
2828 TRACE("iface %p, flags %#x.\n", iface, flags);
2830 return ddraw_surface7_PageUnlock(&surface->IDirectDrawSurface7_iface, flags);
2833 static HRESULT WINAPI ddraw_surface2_PageUnlock(IDirectDrawSurface2 *iface, DWORD flags)
2835 struct ddraw_surface *surface = impl_from_IDirectDrawSurface2(iface);
2837 TRACE("iface %p, flags %#x.\n", iface, flags);
2839 return ddraw_surface7_PageUnlock(&surface->IDirectDrawSurface7_iface, flags);
2842 /*****************************************************************************
2843 * IDirectDrawSurface7::BltBatch
2845 * An unimplemented function
2847 * Params:
2850 * Returns:
2851 * DDERR_UNSUPPORTED
2853 *****************************************************************************/
2854 static HRESULT WINAPI DECLSPEC_HOTPATCH ddraw_surface7_BltBatch(IDirectDrawSurface7 *iface, DDBLTBATCH *Batch, DWORD Count, DWORD Flags)
2856 TRACE("iface %p, batch %p, count %u, flags %#x.\n", iface, Batch, Count, Flags);
2858 /* MSDN: "not currently implemented" */
2859 return DDERR_UNSUPPORTED;
2862 static HRESULT WINAPI DECLSPEC_HOTPATCH ddraw_surface4_BltBatch(IDirectDrawSurface4 *iface, DDBLTBATCH *batch, DWORD count, DWORD flags)
2864 struct ddraw_surface *surface = impl_from_IDirectDrawSurface4(iface);
2866 TRACE("iface %p, batch %p, count %u, flags %#x.\n", iface, batch, count, flags);
2868 return ddraw_surface7_BltBatch(&surface->IDirectDrawSurface7_iface, batch, count, flags);
2871 static HRESULT WINAPI DECLSPEC_HOTPATCH ddraw_surface3_BltBatch(IDirectDrawSurface3 *iface, DDBLTBATCH *batch, DWORD count, DWORD flags)
2873 struct ddraw_surface *surface = impl_from_IDirectDrawSurface3(iface);
2875 TRACE("iface %p, batch %p, count %u, flags %#x.\n", iface, batch, count, flags);
2877 return ddraw_surface7_BltBatch(&surface->IDirectDrawSurface7_iface, batch, count, flags);
2880 static HRESULT WINAPI DECLSPEC_HOTPATCH ddraw_surface2_BltBatch(IDirectDrawSurface2 *iface, DDBLTBATCH *batch, DWORD count, DWORD flags)
2882 struct ddraw_surface *surface = impl_from_IDirectDrawSurface2(iface);
2884 TRACE("iface %p, batch %p, count %u, flags %#x.\n", iface, batch, count, flags);
2886 return ddraw_surface7_BltBatch(&surface->IDirectDrawSurface7_iface, batch, count, flags);
2889 static HRESULT WINAPI DECLSPEC_HOTPATCH ddraw_surface1_BltBatch(IDirectDrawSurface *iface, DDBLTBATCH *batch, DWORD count, DWORD flags)
2891 struct ddraw_surface *surface = impl_from_IDirectDrawSurface(iface);
2893 TRACE("iface %p, batch %p, count %u, flags %#x.\n", iface, batch, count, flags);
2895 return ddraw_surface7_BltBatch(&surface->IDirectDrawSurface7_iface, batch, count, flags);
2898 /*****************************************************************************
2899 * IDirectDrawSurface7::EnumAttachedSurfaces
2901 * Enumerates all surfaces attached to this surface
2903 * Params:
2904 * context: Pointer to pass unmodified to the callback
2905 * cb: Callback function to call for each surface
2907 * Returns:
2908 * DD_OK on success
2909 * DDERR_INVALIDPARAMS if cb is NULL
2911 *****************************************************************************/
2912 static HRESULT WINAPI ddraw_surface7_EnumAttachedSurfaces(IDirectDrawSurface7 *iface,
2913 void *context, LPDDENUMSURFACESCALLBACK7 cb)
2915 struct ddraw_surface *surface = impl_from_IDirectDrawSurface7(iface);
2916 struct ddraw_surface *surf;
2917 DDSURFACEDESC2 desc;
2918 int i;
2920 /* Attached surfaces aren't handled in WineD3D */
2921 TRACE("iface %p, context %p, callback %p.\n", iface, context, cb);
2923 if(!cb)
2924 return DDERR_INVALIDPARAMS;
2926 wined3d_mutex_lock();
2928 for(i = 0; i < MAX_COMPLEX_ATTACHED; i++)
2930 surf = surface->complex_array[i];
2931 if(!surf) break;
2933 ddraw_surface7_AddRef(&surf->IDirectDrawSurface7_iface);
2934 desc = surf->surface_desc;
2935 /* check: != DDENUMRET_OK or == DDENUMRET_CANCEL? */
2936 if (cb(&surf->IDirectDrawSurface7_iface, &desc, context) == DDENUMRET_CANCEL)
2938 wined3d_mutex_unlock();
2939 return DD_OK;
2943 for (surf = surface->next_attached; surf != NULL; surf = surf->next_attached)
2945 ddraw_surface7_AddRef(&surf->IDirectDrawSurface7_iface);
2946 desc = surf->surface_desc;
2947 /* check: != DDENUMRET_OK or == DDENUMRET_CANCEL? */
2948 if (cb(&surf->IDirectDrawSurface7_iface, &desc, context) == DDENUMRET_CANCEL)
2950 wined3d_mutex_unlock();
2951 return DD_OK;
2955 TRACE(" end of enumeration.\n");
2957 wined3d_mutex_unlock();
2959 return DD_OK;
2962 struct callback_info2
2964 LPDDENUMSURFACESCALLBACK2 callback;
2965 void *context;
2968 struct callback_info
2970 LPDDENUMSURFACESCALLBACK callback;
2971 void *context;
2974 static HRESULT CALLBACK EnumCallback2(IDirectDrawSurface7 *surface, DDSURFACEDESC2 *surface_desc, void *context)
2976 struct ddraw_surface *surface_impl = impl_from_IDirectDrawSurface7(surface);
2977 const struct callback_info2 *info = context;
2979 ddraw_surface4_AddRef(&surface_impl->IDirectDrawSurface4_iface);
2980 ddraw_surface7_Release(surface);
2982 return info->callback(&surface_impl->IDirectDrawSurface4_iface, surface_desc, info->context);
2985 static HRESULT CALLBACK EnumCallback(IDirectDrawSurface7 *surface, DDSURFACEDESC2 *surface_desc, void *context)
2987 struct ddraw_surface *surface_impl = impl_from_IDirectDrawSurface7(surface);
2988 const struct callback_info *info = context;
2990 ddraw_surface1_AddRef(&surface_impl->IDirectDrawSurface_iface);
2991 ddraw_surface7_Release(surface);
2993 /* FIXME: Check surface_test.dwSize */
2994 return info->callback(&surface_impl->IDirectDrawSurface_iface,
2995 (DDSURFACEDESC *)surface_desc, info->context);
2998 static HRESULT WINAPI ddraw_surface4_EnumAttachedSurfaces(IDirectDrawSurface4 *iface,
2999 void *context, LPDDENUMSURFACESCALLBACK2 callback)
3001 struct ddraw_surface *surface = impl_from_IDirectDrawSurface4(iface);
3002 struct callback_info2 info;
3004 TRACE("iface %p, context %p, callback %p.\n", iface, context, callback);
3006 info.callback = callback;
3007 info.context = context;
3009 return ddraw_surface7_EnumAttachedSurfaces(&surface->IDirectDrawSurface7_iface,
3010 &info, EnumCallback2);
3013 static HRESULT WINAPI ddraw_surface3_EnumAttachedSurfaces(IDirectDrawSurface3 *iface,
3014 void *context, LPDDENUMSURFACESCALLBACK callback)
3016 struct ddraw_surface *surface = impl_from_IDirectDrawSurface3(iface);
3017 struct callback_info info;
3019 TRACE("iface %p, context %p, callback %p.\n", iface, context, callback);
3021 info.callback = callback;
3022 info.context = context;
3024 return ddraw_surface7_EnumAttachedSurfaces(&surface->IDirectDrawSurface7_iface,
3025 &info, EnumCallback);
3028 static HRESULT WINAPI ddraw_surface2_EnumAttachedSurfaces(IDirectDrawSurface2 *iface,
3029 void *context, LPDDENUMSURFACESCALLBACK callback)
3031 struct ddraw_surface *surface = impl_from_IDirectDrawSurface2(iface);
3032 struct callback_info info;
3034 TRACE("iface %p, context %p, callback %p.\n", iface, context, callback);
3036 info.callback = callback;
3037 info.context = context;
3039 return ddraw_surface7_EnumAttachedSurfaces(&surface->IDirectDrawSurface7_iface,
3040 &info, EnumCallback);
3043 static HRESULT WINAPI ddraw_surface1_EnumAttachedSurfaces(IDirectDrawSurface *iface,
3044 void *context, LPDDENUMSURFACESCALLBACK callback)
3046 struct ddraw_surface *surface = impl_from_IDirectDrawSurface(iface);
3047 struct callback_info info;
3049 TRACE("iface %p, context %p, callback %p.\n", iface, context, callback);
3051 info.callback = callback;
3052 info.context = context;
3054 return ddraw_surface7_EnumAttachedSurfaces(&surface->IDirectDrawSurface7_iface,
3055 &info, EnumCallback);
3058 /*****************************************************************************
3059 * IDirectDrawSurface7::EnumOverlayZOrders
3061 * "Enumerates the overlay surfaces on the specified destination"
3063 * Params:
3064 * Flags: DDENUMOVERLAYZ_BACKTOFRONT or DDENUMOVERLAYZ_FRONTTOBACK
3065 * context: context to pass back to the callback
3066 * cb: callback function to call for each enumerated surface
3068 * Returns:
3069 * DD_OK, because it's a stub
3071 *****************************************************************************/
3072 static HRESULT WINAPI ddraw_surface7_EnumOverlayZOrders(IDirectDrawSurface7 *iface,
3073 DWORD Flags, void *context, LPDDENUMSURFACESCALLBACK7 cb)
3075 FIXME("iface %p, flags %#x, context %p, callback %p stub!\n", iface, Flags, context, cb);
3077 return DD_OK;
3080 static HRESULT WINAPI ddraw_surface4_EnumOverlayZOrders(IDirectDrawSurface4 *iface,
3081 DWORD flags, void *context, LPDDENUMSURFACESCALLBACK2 callback)
3083 struct ddraw_surface *surface = impl_from_IDirectDrawSurface4(iface);
3084 struct callback_info2 info;
3086 TRACE("iface %p, flags %#x, context %p, callback %p.\n", iface, flags, context, callback);
3088 info.callback = callback;
3089 info.context = context;
3091 return ddraw_surface7_EnumOverlayZOrders(&surface->IDirectDrawSurface7_iface,
3092 flags, &info, EnumCallback2);
3095 static HRESULT WINAPI ddraw_surface3_EnumOverlayZOrders(IDirectDrawSurface3 *iface,
3096 DWORD flags, void *context, LPDDENUMSURFACESCALLBACK callback)
3098 struct ddraw_surface *surface = impl_from_IDirectDrawSurface3(iface);
3099 struct callback_info info;
3101 TRACE("iface %p, flags %#x, context %p, callback %p.\n", iface, flags, context, callback);
3103 info.callback = callback;
3104 info.context = context;
3106 return ddraw_surface7_EnumOverlayZOrders(&surface->IDirectDrawSurface7_iface,
3107 flags, &info, EnumCallback);
3110 static HRESULT WINAPI ddraw_surface2_EnumOverlayZOrders(IDirectDrawSurface2 *iface,
3111 DWORD flags, void *context, LPDDENUMSURFACESCALLBACK callback)
3113 struct ddraw_surface *surface = impl_from_IDirectDrawSurface2(iface);
3114 struct callback_info info;
3116 TRACE("iface %p, flags %#x, context %p, callback %p.\n", iface, flags, context, callback);
3118 info.callback = callback;
3119 info.context = context;
3121 return ddraw_surface7_EnumOverlayZOrders(&surface->IDirectDrawSurface7_iface,
3122 flags, &info, EnumCallback);
3125 static HRESULT WINAPI ddraw_surface1_EnumOverlayZOrders(IDirectDrawSurface *iface,
3126 DWORD flags, void *context, LPDDENUMSURFACESCALLBACK callback)
3128 struct ddraw_surface *surface = impl_from_IDirectDrawSurface(iface);
3129 struct callback_info info;
3131 TRACE("iface %p, flags %#x, context %p, callback %p.\n", iface, flags, context, callback);
3133 info.callback = callback;
3134 info.context = context;
3136 return ddraw_surface7_EnumOverlayZOrders(&surface->IDirectDrawSurface7_iface,
3137 flags, &info, EnumCallback);
3140 /*****************************************************************************
3141 * IDirectDrawSurface7::GetBltStatus
3143 * Returns the blitting status
3145 * Params:
3146 * Flags: DDGBS_CANBLT or DDGBS_ISBLTDONE
3148 *****************************************************************************/
3149 static HRESULT WINAPI ddraw_surface7_GetBltStatus(IDirectDrawSurface7 *iface, DWORD Flags)
3151 TRACE("iface %p, flags %#x.\n", iface, Flags);
3153 switch (Flags)
3155 case WINEDDGBS_CANBLT:
3156 case WINEDDGBS_ISBLTDONE:
3157 return DD_OK;
3159 default:
3160 return DDERR_INVALIDPARAMS;
3164 static HRESULT WINAPI ddraw_surface4_GetBltStatus(IDirectDrawSurface4 *iface, DWORD flags)
3166 struct ddraw_surface *surface = impl_from_IDirectDrawSurface4(iface);
3168 TRACE("iface %p, flags %#x.\n", iface, flags);
3170 return ddraw_surface7_GetBltStatus(&surface->IDirectDrawSurface7_iface, flags);
3173 static HRESULT WINAPI ddraw_surface3_GetBltStatus(IDirectDrawSurface3 *iface, DWORD flags)
3175 struct ddraw_surface *surface = impl_from_IDirectDrawSurface3(iface);
3177 TRACE("iface %p, flags %#x.\n", iface, flags);
3179 return ddraw_surface7_GetBltStatus(&surface->IDirectDrawSurface7_iface, flags);
3182 static HRESULT WINAPI ddraw_surface2_GetBltStatus(IDirectDrawSurface2 *iface, DWORD flags)
3184 struct ddraw_surface *surface = impl_from_IDirectDrawSurface2(iface);
3186 TRACE("iface %p, flags %#x.\n", iface, flags);
3188 return ddraw_surface7_GetBltStatus(&surface->IDirectDrawSurface7_iface, flags);
3191 static HRESULT WINAPI ddraw_surface1_GetBltStatus(IDirectDrawSurface *iface, DWORD flags)
3193 struct ddraw_surface *surface = impl_from_IDirectDrawSurface(iface);
3195 TRACE("iface %p, flags %#x.\n", iface, flags);
3197 return ddraw_surface7_GetBltStatus(&surface->IDirectDrawSurface7_iface, flags);
3200 /*****************************************************************************
3201 * IDirectDrawSurface7::GetColorKey
3203 * Returns the color key assigned to the surface
3205 * Params:
3206 * Flags: Some flags
3207 * CKey: Address to store the key to
3209 * Returns:
3210 * DD_OK on success
3211 * DDERR_INVALIDPARAMS if CKey is NULL
3213 *****************************************************************************/
3214 static HRESULT WINAPI ddraw_surface7_GetColorKey(IDirectDrawSurface7 *iface, DWORD Flags, DDCOLORKEY *CKey)
3216 struct ddraw_surface *This = impl_from_IDirectDrawSurface7(iface);
3218 TRACE("iface %p, flags %#x, color_key %p.\n", iface, Flags, CKey);
3220 if(!CKey)
3221 return DDERR_INVALIDPARAMS;
3223 wined3d_mutex_lock();
3225 switch (Flags)
3227 case DDCKEY_DESTBLT:
3228 if (!(This->surface_desc.dwFlags & DDSD_CKDESTBLT))
3230 wined3d_mutex_unlock();
3231 return DDERR_NOCOLORKEY;
3233 *CKey = This->surface_desc.ddckCKDestBlt;
3234 break;
3236 case DDCKEY_DESTOVERLAY:
3237 if (!(This->surface_desc.dwFlags & DDSD_CKDESTOVERLAY))
3239 wined3d_mutex_unlock();
3240 return DDERR_NOCOLORKEY;
3242 *CKey = This->surface_desc.u3.ddckCKDestOverlay;
3243 break;
3245 case DDCKEY_SRCBLT:
3246 if (!(This->surface_desc.dwFlags & DDSD_CKSRCBLT))
3248 wined3d_mutex_unlock();
3249 return DDERR_NOCOLORKEY;
3251 *CKey = This->surface_desc.ddckCKSrcBlt;
3252 break;
3254 case DDCKEY_SRCOVERLAY:
3255 if (!(This->surface_desc.dwFlags & DDSD_CKSRCOVERLAY))
3257 wined3d_mutex_unlock();
3258 return DDERR_NOCOLORKEY;
3260 *CKey = This->surface_desc.ddckCKSrcOverlay;
3261 break;
3263 default:
3264 wined3d_mutex_unlock();
3265 return DDERR_INVALIDPARAMS;
3268 wined3d_mutex_unlock();
3270 return DD_OK;
3273 static HRESULT WINAPI ddraw_surface4_GetColorKey(IDirectDrawSurface4 *iface, DWORD flags, DDCOLORKEY *color_key)
3275 struct ddraw_surface *surface = impl_from_IDirectDrawSurface4(iface);
3277 TRACE("iface %p, flags %#x, color_key %p.\n", iface, flags, color_key);
3279 return ddraw_surface7_GetColorKey(&surface->IDirectDrawSurface7_iface, flags, color_key);
3282 static HRESULT WINAPI ddraw_surface3_GetColorKey(IDirectDrawSurface3 *iface, DWORD flags, DDCOLORKEY *color_key)
3284 struct ddraw_surface *surface = impl_from_IDirectDrawSurface3(iface);
3286 TRACE("iface %p, flags %#x, color_key %p.\n", iface, flags, color_key);
3288 return ddraw_surface7_GetColorKey(&surface->IDirectDrawSurface7_iface, flags, color_key);
3291 static HRESULT WINAPI ddraw_surface2_GetColorKey(IDirectDrawSurface2 *iface, DWORD flags, DDCOLORKEY *color_key)
3293 struct ddraw_surface *surface = impl_from_IDirectDrawSurface2(iface);
3295 TRACE("iface %p, flags %#x, color_key %p.\n", iface, flags, color_key);
3297 return ddraw_surface7_GetColorKey(&surface->IDirectDrawSurface7_iface, flags, color_key);
3300 static HRESULT WINAPI ddraw_surface1_GetColorKey(IDirectDrawSurface *iface, DWORD flags, DDCOLORKEY *color_key)
3302 struct ddraw_surface *surface = impl_from_IDirectDrawSurface(iface);
3304 TRACE("iface %p, flags %#x, color_key %p.\n", iface, flags, color_key);
3306 return ddraw_surface7_GetColorKey(&surface->IDirectDrawSurface7_iface, flags, color_key);
3309 /*****************************************************************************
3310 * IDirectDrawSurface7::GetFlipStatus
3312 * Returns the flipping status of the surface
3314 * Params:
3315 * Flags: DDGFS_CANFLIP of DDGFS_ISFLIPDONE
3317 *****************************************************************************/
3318 static HRESULT WINAPI ddraw_surface7_GetFlipStatus(IDirectDrawSurface7 *iface, DWORD Flags)
3320 TRACE("iface %p, flags %#x.\n", iface, Flags);
3322 /* XXX: DDERR_INVALIDSURFACETYPE */
3324 switch (Flags)
3326 case WINEDDGFS_CANFLIP:
3327 case WINEDDGFS_ISFLIPDONE:
3328 return DD_OK;
3330 default:
3331 return DDERR_INVALIDPARAMS;
3335 static HRESULT WINAPI ddraw_surface4_GetFlipStatus(IDirectDrawSurface4 *iface, DWORD flags)
3337 struct ddraw_surface *surface = impl_from_IDirectDrawSurface4(iface);
3339 TRACE("iface %p, flags %#x.\n", iface, flags);
3341 return ddraw_surface7_GetFlipStatus(&surface->IDirectDrawSurface7_iface, flags);
3344 static HRESULT WINAPI ddraw_surface3_GetFlipStatus(IDirectDrawSurface3 *iface, DWORD flags)
3346 struct ddraw_surface *surface = impl_from_IDirectDrawSurface3(iface);
3348 TRACE("iface %p, flags %#x.\n", iface, flags);
3350 return ddraw_surface7_GetFlipStatus(&surface->IDirectDrawSurface7_iface, flags);
3353 static HRESULT WINAPI ddraw_surface2_GetFlipStatus(IDirectDrawSurface2 *iface, DWORD flags)
3355 struct ddraw_surface *surface = impl_from_IDirectDrawSurface2(iface);
3357 TRACE("iface %p, flags %#x.\n", iface, flags);
3359 return ddraw_surface7_GetFlipStatus(&surface->IDirectDrawSurface7_iface, flags);
3362 static HRESULT WINAPI ddraw_surface1_GetFlipStatus(IDirectDrawSurface *iface, DWORD flags)
3364 struct ddraw_surface *surface = impl_from_IDirectDrawSurface(iface);
3366 TRACE("iface %p, flags %#x.\n", iface, flags);
3368 return ddraw_surface7_GetFlipStatus(&surface->IDirectDrawSurface7_iface, flags);
3371 /*****************************************************************************
3372 * IDirectDrawSurface7::GetOverlayPosition
3374 * Returns the display coordinates of a visible and active overlay surface
3376 * Params:
3380 * Returns:
3381 * DDERR_NOTAOVERLAYSURFACE, because it's a stub
3382 *****************************************************************************/
3383 static HRESULT WINAPI ddraw_surface7_GetOverlayPosition(IDirectDrawSurface7 *iface, LONG *x, LONG *y)
3385 struct ddraw_surface *surface = impl_from_IDirectDrawSurface7(iface);
3386 HRESULT hr;
3388 TRACE("iface %p, x %p, y %p.\n", iface, x, y);
3390 wined3d_mutex_lock();
3391 hr = wined3d_texture_get_overlay_position(surface->wined3d_texture,
3392 surface->sub_resource_idx, x, y);
3393 wined3d_mutex_unlock();
3395 return hr;
3398 static HRESULT WINAPI ddraw_surface4_GetOverlayPosition(IDirectDrawSurface4 *iface, LONG *x, LONG *y)
3400 struct ddraw_surface *surface = impl_from_IDirectDrawSurface4(iface);
3402 TRACE("iface %p, x %p, y %p.\n", iface, x, y);
3404 return ddraw_surface7_GetOverlayPosition(&surface->IDirectDrawSurface7_iface, x, y);
3407 static HRESULT WINAPI ddraw_surface3_GetOverlayPosition(IDirectDrawSurface3 *iface, LONG *x, LONG *y)
3409 struct ddraw_surface *surface = impl_from_IDirectDrawSurface3(iface);
3411 TRACE("iface %p, x %p, y %p.\n", iface, x, y);
3413 return ddraw_surface7_GetOverlayPosition(&surface->IDirectDrawSurface7_iface, x, y);
3416 static HRESULT WINAPI ddraw_surface2_GetOverlayPosition(IDirectDrawSurface2 *iface, LONG *x, LONG *y)
3418 struct ddraw_surface *surface = impl_from_IDirectDrawSurface2(iface);
3420 TRACE("iface %p, x %p, y %p.\n", iface, x, y);
3422 return ddraw_surface7_GetOverlayPosition(&surface->IDirectDrawSurface7_iface, x, y);
3425 static HRESULT WINAPI ddraw_surface1_GetOverlayPosition(IDirectDrawSurface *iface, LONG *x, LONG *y)
3427 struct ddraw_surface *surface = impl_from_IDirectDrawSurface(iface);
3429 TRACE("iface %p, x %p, y %p.\n", iface, x, y);
3431 return ddraw_surface7_GetOverlayPosition(&surface->IDirectDrawSurface7_iface, x, y);
3434 /*****************************************************************************
3435 * IDirectDrawSurface7::GetPixelFormat
3437 * Returns the pixel format of the Surface
3439 * Params:
3440 * PixelFormat: Pointer to a DDPIXELFORMAT structure to which the pixel
3441 * format should be written
3443 * Returns:
3444 * DD_OK on success
3445 * DDERR_INVALIDPARAMS if PixelFormat is NULL
3447 *****************************************************************************/
3448 static HRESULT WINAPI ddraw_surface7_GetPixelFormat(IDirectDrawSurface7 *iface, DDPIXELFORMAT *PixelFormat)
3450 /* What is DDERR_INVALIDSURFACETYPE for here? */
3451 struct ddraw_surface *surface = impl_from_IDirectDrawSurface7(iface);
3453 TRACE("iface %p, pixel_format %p.\n", iface, PixelFormat);
3455 if(!PixelFormat)
3456 return DDERR_INVALIDPARAMS;
3458 wined3d_mutex_lock();
3459 DD_STRUCT_COPY_BYSIZE(PixelFormat, &surface->surface_desc.u4.ddpfPixelFormat);
3460 wined3d_mutex_unlock();
3462 return DD_OK;
3465 static HRESULT WINAPI ddraw_surface4_GetPixelFormat(IDirectDrawSurface4 *iface, DDPIXELFORMAT *pixel_format)
3467 struct ddraw_surface *surface = impl_from_IDirectDrawSurface4(iface);
3469 TRACE("iface %p, pixel_format %p.\n", iface, pixel_format);
3471 return ddraw_surface7_GetPixelFormat(&surface->IDirectDrawSurface7_iface, pixel_format);
3474 static HRESULT WINAPI ddraw_surface3_GetPixelFormat(IDirectDrawSurface3 *iface, DDPIXELFORMAT *pixel_format)
3476 struct ddraw_surface *surface = impl_from_IDirectDrawSurface3(iface);
3478 TRACE("iface %p, pixel_format %p.\n", iface, pixel_format);
3480 return ddraw_surface7_GetPixelFormat(&surface->IDirectDrawSurface7_iface, pixel_format);
3483 static HRESULT WINAPI ddraw_surface2_GetPixelFormat(IDirectDrawSurface2 *iface, DDPIXELFORMAT *pixel_format)
3485 struct ddraw_surface *surface = impl_from_IDirectDrawSurface2(iface);
3487 TRACE("iface %p, pixel_format %p.\n", iface, pixel_format);
3489 return ddraw_surface7_GetPixelFormat(&surface->IDirectDrawSurface7_iface, pixel_format);
3492 static HRESULT WINAPI ddraw_surface1_GetPixelFormat(IDirectDrawSurface *iface, DDPIXELFORMAT *pixel_format)
3494 struct ddraw_surface *surface = impl_from_IDirectDrawSurface(iface);
3496 TRACE("iface %p, pixel_format %p.\n", iface, pixel_format);
3498 return ddraw_surface7_GetPixelFormat(&surface->IDirectDrawSurface7_iface, pixel_format);
3501 /*****************************************************************************
3502 * IDirectDrawSurface7::GetSurfaceDesc
3504 * Returns the description of this surface
3506 * Params:
3507 * DDSD: Address of a DDSURFACEDESC2 structure that is to be filled with the
3508 * surface desc
3510 * Returns:
3511 * DD_OK on success
3512 * DDERR_INVALIDPARAMS if DDSD is NULL
3514 *****************************************************************************/
3515 static HRESULT WINAPI ddraw_surface7_GetSurfaceDesc(IDirectDrawSurface7 *iface, DDSURFACEDESC2 *DDSD)
3517 struct ddraw_surface *surface = impl_from_IDirectDrawSurface7(iface);
3519 TRACE("iface %p, surface_desc %p.\n", iface, DDSD);
3521 if(!DDSD)
3522 return DDERR_INVALIDPARAMS;
3524 if (DDSD->dwSize != sizeof(DDSURFACEDESC2))
3526 WARN("Incorrect struct size %d, returning DDERR_INVALIDPARAMS\n",DDSD->dwSize);
3527 return DDERR_INVALIDPARAMS;
3530 wined3d_mutex_lock();
3531 DD_STRUCT_COPY_BYSIZE(DDSD, &surface->surface_desc);
3532 TRACE("Returning surface desc:\n");
3533 if (TRACE_ON(ddraw)) DDRAW_dump_surface_desc(DDSD);
3534 wined3d_mutex_unlock();
3536 return DD_OK;
3539 static HRESULT WINAPI ddraw_surface4_GetSurfaceDesc(IDirectDrawSurface4 *iface, DDSURFACEDESC2 *DDSD)
3541 struct ddraw_surface *surface = impl_from_IDirectDrawSurface4(iface);
3543 TRACE("iface %p, surface_desc %p.\n", iface, DDSD);
3545 return ddraw_surface7_GetSurfaceDesc(&surface->IDirectDrawSurface7_iface, DDSD);
3548 static HRESULT WINAPI ddraw_surface3_GetSurfaceDesc(IDirectDrawSurface3 *iface, DDSURFACEDESC *surface_desc)
3550 struct ddraw_surface *surface = impl_from_IDirectDrawSurface3(iface);
3552 TRACE("iface %p, surface_desc %p.\n", iface, surface_desc);
3554 if (!surface_desc) return DDERR_INVALIDPARAMS;
3556 if (surface_desc->dwSize != sizeof(DDSURFACEDESC))
3558 WARN("Incorrect structure size %u, returning DDERR_INVALIDPARAMS.\n", surface_desc->dwSize);
3559 return DDERR_INVALIDPARAMS;
3562 wined3d_mutex_lock();
3563 DDSD2_to_DDSD(&surface->surface_desc, surface_desc);
3564 TRACE("Returning surface desc:\n");
3565 if (TRACE_ON(ddraw))
3567 /* DDRAW_dump_surface_desc handles the smaller size */
3568 DDRAW_dump_surface_desc((DDSURFACEDESC2 *)surface_desc);
3570 wined3d_mutex_unlock();
3572 return DD_OK;
3575 static HRESULT WINAPI ddraw_surface2_GetSurfaceDesc(IDirectDrawSurface2 *iface, DDSURFACEDESC *DDSD)
3577 struct ddraw_surface *surface = impl_from_IDirectDrawSurface2(iface);
3579 TRACE("iface %p, surface_desc %p.\n", iface, DDSD);
3581 return ddraw_surface3_GetSurfaceDesc(&surface->IDirectDrawSurface3_iface, DDSD);
3584 static HRESULT WINAPI ddraw_surface1_GetSurfaceDesc(IDirectDrawSurface *iface, DDSURFACEDESC *DDSD)
3586 struct ddraw_surface *surface = impl_from_IDirectDrawSurface(iface);
3588 TRACE("iface %p, surface_desc %p.\n", iface, DDSD);
3590 return ddraw_surface3_GetSurfaceDesc(&surface->IDirectDrawSurface3_iface, DDSD);
3593 /*****************************************************************************
3594 * IDirectDrawSurface7::Initialize
3596 * Initializes the surface. This is a no-op in Wine
3598 * Params:
3599 * DD: Pointer to an DirectDraw interface
3600 * DDSD: Surface description for initialization
3602 * Returns:
3603 * DDERR_ALREADYINITIALIZED
3605 *****************************************************************************/
3606 static HRESULT WINAPI ddraw_surface7_Initialize(IDirectDrawSurface7 *iface,
3607 IDirectDraw *ddraw, DDSURFACEDESC2 *surface_desc)
3609 TRACE("iface %p, ddraw %p, surface_desc %p.\n", iface, ddraw, surface_desc);
3611 return DDERR_ALREADYINITIALIZED;
3614 static HRESULT WINAPI ddraw_surface4_Initialize(IDirectDrawSurface4 *iface,
3615 IDirectDraw *ddraw, DDSURFACEDESC2 *surface_desc)
3617 struct ddraw_surface *surface = impl_from_IDirectDrawSurface4(iface);
3619 TRACE("iface %p, ddraw %p, surface_desc %p.\n", iface, ddraw, surface_desc);
3621 return ddraw_surface7_Initialize(&surface->IDirectDrawSurface7_iface,
3622 ddraw, surface_desc);
3625 static HRESULT WINAPI ddraw_surface3_Initialize(IDirectDrawSurface3 *iface,
3626 IDirectDraw *ddraw, DDSURFACEDESC *surface_desc)
3628 struct ddraw_surface *surface = impl_from_IDirectDrawSurface3(iface);
3629 DDSURFACEDESC2 surface_desc2;
3631 TRACE("iface %p, ddraw %p, surface_desc %p.\n", iface, ddraw, surface_desc);
3633 if (surface_desc) DDSD_to_DDSD2(surface_desc, &surface_desc2);
3634 return ddraw_surface7_Initialize(&surface->IDirectDrawSurface7_iface,
3635 ddraw, surface_desc ? &surface_desc2 : NULL);
3638 static HRESULT WINAPI ddraw_surface2_Initialize(IDirectDrawSurface2 *iface,
3639 IDirectDraw *ddraw, DDSURFACEDESC *surface_desc)
3641 struct ddraw_surface *surface = impl_from_IDirectDrawSurface2(iface);
3642 DDSURFACEDESC2 surface_desc2;
3644 TRACE("iface %p, ddraw %p, surface_desc %p.\n", iface, ddraw, surface_desc);
3646 if (surface_desc) DDSD_to_DDSD2(surface_desc, &surface_desc2);
3647 return ddraw_surface7_Initialize(&surface->IDirectDrawSurface7_iface,
3648 ddraw, surface_desc ? &surface_desc2 : NULL);
3651 static HRESULT WINAPI ddraw_surface1_Initialize(IDirectDrawSurface *iface,
3652 IDirectDraw *ddraw, DDSURFACEDESC *surface_desc)
3654 struct ddraw_surface *surface = impl_from_IDirectDrawSurface(iface);
3655 DDSURFACEDESC2 surface_desc2;
3657 TRACE("iface %p, ddraw %p, surface_desc %p.\n", iface, ddraw, surface_desc);
3659 if (surface_desc) DDSD_to_DDSD2(surface_desc, &surface_desc2);
3660 return ddraw_surface7_Initialize(&surface->IDirectDrawSurface7_iface,
3661 ddraw, surface_desc ? &surface_desc2 : NULL);
3664 /*****************************************************************************
3665 * IDirect3DTexture1::Initialize
3667 * The sdk says it's not implemented
3669 * Params:
3672 * Returns
3673 * DDERR_UNSUPPORTED
3675 *****************************************************************************/
3676 static HRESULT WINAPI d3d_texture1_Initialize(IDirect3DTexture *iface,
3677 IDirect3DDevice *device, IDirectDrawSurface *surface)
3679 TRACE("iface %p, device %p, surface %p.\n", iface, device, surface);
3681 return DDERR_UNSUPPORTED; /* Unchecked */
3684 /*****************************************************************************
3685 * IDirectDrawSurface7::IsLost
3687 * Checks if the surface is lost
3689 * Returns:
3690 * DD_OK, if the surface is usable
3691 * DDERR_ISLOST if the surface is lost
3693 *****************************************************************************/
3694 static HRESULT WINAPI ddraw_surface7_IsLost(IDirectDrawSurface7 *iface)
3696 struct ddraw_surface *surface = impl_from_IDirectDrawSurface7(iface);
3698 TRACE("iface %p.\n", iface);
3700 return ddraw_surface_is_lost(surface) ? DDERR_SURFACELOST : DD_OK;
3703 static HRESULT WINAPI ddraw_surface4_IsLost(IDirectDrawSurface4 *iface)
3705 struct ddraw_surface *surface = impl_from_IDirectDrawSurface4(iface);
3707 TRACE("iface %p.\n", iface);
3709 return ddraw_surface_is_lost(surface) ? DDERR_SURFACELOST : DD_OK;
3712 static HRESULT WINAPI ddraw_surface3_IsLost(IDirectDrawSurface3 *iface)
3714 struct ddraw_surface *surface = impl_from_IDirectDrawSurface3(iface);
3716 TRACE("iface %p.\n", iface);
3718 return ddraw_surface_is_lost(surface) ? DDERR_SURFACELOST : DD_OK;
3721 static HRESULT WINAPI ddraw_surface2_IsLost(IDirectDrawSurface2 *iface)
3723 struct ddraw_surface *surface = impl_from_IDirectDrawSurface2(iface);
3725 TRACE("iface %p.\n", iface);
3727 return ddraw_surface_is_lost(surface) ? DDERR_SURFACELOST : DD_OK;
3730 static HRESULT WINAPI ddraw_surface1_IsLost(IDirectDrawSurface *iface)
3732 struct ddraw_surface *surface = impl_from_IDirectDrawSurface(iface);
3734 TRACE("iface %p.\n", iface);
3736 return ddraw_surface_is_lost(surface) ? DDERR_SURFACELOST : DD_OK;
3739 /*****************************************************************************
3740 * IDirectDrawSurface7::Restore
3742 * Restores a lost surface. This makes the surface usable again, but
3743 * doesn't reload its old contents
3745 * Returns:
3746 * DD_OK on success, error code otherwise.
3748 *****************************************************************************/
3749 static HRESULT WINAPI ddraw_surface7_Restore(IDirectDrawSurface7 *iface)
3751 struct ddraw_surface *surface = impl_from_IDirectDrawSurface7(iface);
3752 unsigned int i;
3754 TRACE("iface %p.\n", iface);
3756 if (surface->surface_desc.ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE)
3758 struct wined3d_swapchain *swapchain = surface->ddraw->wined3d_swapchain;
3759 struct wined3d_sub_resource_desc wined3d_desc;
3760 struct wined3d_display_mode mode;
3761 HRESULT hr;
3763 if (FAILED(hr = wined3d_swapchain_get_display_mode(swapchain, &mode, NULL)))
3765 WARN("Failed to get display mode, hr %#x.\n", hr);
3766 return hr;
3769 if (FAILED(hr = wined3d_texture_get_sub_resource_desc(surface->wined3d_texture, 0, &wined3d_desc)))
3771 WARN("Failed to get resource desc, hr %#x.\n", hr);
3772 return hr;
3775 if (mode.width != wined3d_desc.width || mode.height != wined3d_desc.height)
3777 WARN("Display mode dimensions %ux%u don't match surface dimensions %ux%u.\n",
3778 mode.width, mode.height, wined3d_desc.width, wined3d_desc.height);
3779 return DDERR_WRONGMODE;
3782 if (mode.format_id != wined3d_desc.format)
3784 WARN("Display mode format %#x doesn't match surface format %#x.\n",
3785 mode.format_id, wined3d_desc.format);
3786 return DDERR_WRONGMODE;
3790 if (!ddraw_surface_can_be_lost(surface))
3791 return DD_OK;
3792 ddraw_update_lost_surfaces(surface->ddraw);
3793 if (surface->ddraw->device_state == DDRAW_DEVICE_STATE_LOST)
3794 return DDERR_WRONGMODE;
3796 surface->is_lost = FALSE;
3797 for(i = 0; i < MAX_COMPLEX_ATTACHED; i++)
3799 if (surface->complex_array[i])
3800 surface->complex_array[i]->is_lost = FALSE;
3803 return DD_OK;
3806 static HRESULT WINAPI ddraw_surface4_Restore(IDirectDrawSurface4 *iface)
3808 struct ddraw_surface *surface = impl_from_IDirectDrawSurface4(iface);
3810 TRACE("iface %p.\n", iface);
3812 return ddraw_surface7_Restore(&surface->IDirectDrawSurface7_iface);
3815 static HRESULT WINAPI ddraw_surface3_Restore(IDirectDrawSurface3 *iface)
3817 struct ddraw_surface *surface = impl_from_IDirectDrawSurface3(iface);
3819 TRACE("iface %p.\n", iface);
3821 return ddraw_surface7_Restore(&surface->IDirectDrawSurface7_iface);
3824 static HRESULT WINAPI ddraw_surface2_Restore(IDirectDrawSurface2 *iface)
3826 struct ddraw_surface *surface = impl_from_IDirectDrawSurface2(iface);
3828 TRACE("iface %p.\n", iface);
3830 return ddraw_surface7_Restore(&surface->IDirectDrawSurface7_iface);
3833 static HRESULT WINAPI ddraw_surface1_Restore(IDirectDrawSurface *iface)
3835 struct ddraw_surface *surface = impl_from_IDirectDrawSurface(iface);
3837 TRACE("iface %p.\n", iface);
3839 return ddraw_surface7_Restore(&surface->IDirectDrawSurface7_iface);
3842 /*****************************************************************************
3843 * IDirectDrawSurface7::SetOverlayPosition
3845 * Changes the display coordinates of an overlay surface
3847 * Params:
3848 * X:
3849 * Y:
3851 * Returns:
3852 * DDERR_NOTAOVERLAYSURFACE, because we don't support overlays right now
3853 *****************************************************************************/
3854 static HRESULT WINAPI ddraw_surface7_SetOverlayPosition(IDirectDrawSurface7 *iface, LONG x, LONG y)
3856 struct ddraw_surface *surface = impl_from_IDirectDrawSurface7(iface);
3857 HRESULT hr;
3859 TRACE("iface %p, x %d, y %d.\n", iface, x, y);
3861 wined3d_mutex_lock();
3862 hr = wined3d_texture_set_overlay_position(surface->wined3d_texture,
3863 surface->sub_resource_idx, x, y);
3864 wined3d_mutex_unlock();
3866 return hr;
3869 static HRESULT WINAPI ddraw_surface4_SetOverlayPosition(IDirectDrawSurface4 *iface, LONG x, LONG y)
3871 struct ddraw_surface *surface = impl_from_IDirectDrawSurface4(iface);
3873 TRACE("iface %p, x %d, y %d.\n", iface, x, y);
3875 return ddraw_surface7_SetOverlayPosition(&surface->IDirectDrawSurface7_iface, x, y);
3878 static HRESULT WINAPI ddraw_surface3_SetOverlayPosition(IDirectDrawSurface3 *iface, LONG x, LONG y)
3880 struct ddraw_surface *surface = impl_from_IDirectDrawSurface3(iface);
3882 TRACE("iface %p, x %d, y %d.\n", iface, x, y);
3884 return ddraw_surface7_SetOverlayPosition(&surface->IDirectDrawSurface7_iface, x, y);
3887 static HRESULT WINAPI ddraw_surface2_SetOverlayPosition(IDirectDrawSurface2 *iface, LONG x, LONG y)
3889 struct ddraw_surface *surface = impl_from_IDirectDrawSurface2(iface);
3891 TRACE("iface %p, x %d, y %d.\n", iface, x, y);
3893 return ddraw_surface7_SetOverlayPosition(&surface->IDirectDrawSurface7_iface, x, y);
3896 static HRESULT WINAPI ddraw_surface1_SetOverlayPosition(IDirectDrawSurface *iface, LONG x, LONG y)
3898 struct ddraw_surface *surface = impl_from_IDirectDrawSurface(iface);
3900 TRACE("iface %p, x %d, y %d.\n", iface, x, y);
3902 return ddraw_surface7_SetOverlayPosition(&surface->IDirectDrawSurface7_iface, x, y);
3905 /*****************************************************************************
3906 * IDirectDrawSurface7::UpdateOverlay
3908 * Modifies the attributes of an overlay surface.
3910 * Params:
3911 * SrcRect: The section of the source being used for the overlay
3912 * DstSurface: Address of the surface that is overlaid
3913 * DstRect: Place of the overlay
3914 * Flags: some DDOVER_* flags
3916 * Returns:
3917 * DDERR_UNSUPPORTED, because we don't support overlays
3919 *****************************************************************************/
3920 static HRESULT WINAPI ddraw_surface7_UpdateOverlay(IDirectDrawSurface7 *iface, RECT *src_rect,
3921 IDirectDrawSurface7 *dst_surface, RECT *dst_rect, DWORD flags, DDOVERLAYFX *fx)
3923 struct ddraw_surface *src_impl = impl_from_IDirectDrawSurface7(iface);
3924 struct ddraw_surface *dst_impl = unsafe_impl_from_IDirectDrawSurface7(dst_surface);
3925 struct wined3d_texture *dst_wined3d_texture = NULL;
3926 unsigned int dst_sub_resource_idx = 0;
3927 HRESULT hr;
3929 TRACE("iface %p, src_rect %s, dst_surface %p, dst_rect %s, flags %#x, fx %p.\n",
3930 iface, wine_dbgstr_rect(src_rect), dst_surface, wine_dbgstr_rect(dst_rect), flags, fx);
3932 if (fx)
3933 FIXME("Ignoring fx %p.\n", fx);
3935 wined3d_mutex_lock();
3936 if (dst_impl)
3938 dst_wined3d_texture = dst_impl->wined3d_texture;
3939 dst_sub_resource_idx = dst_impl->sub_resource_idx;
3941 hr = wined3d_texture_update_overlay(src_impl->wined3d_texture, src_impl->sub_resource_idx,
3942 src_rect, dst_wined3d_texture, dst_sub_resource_idx, dst_rect, flags);
3943 wined3d_mutex_unlock();
3945 return hr_ddraw_from_wined3d(hr);
3948 static HRESULT WINAPI ddraw_surface4_UpdateOverlay(IDirectDrawSurface4 *iface, RECT *src_rect,
3949 IDirectDrawSurface4 *dst_surface, RECT *dst_rect, DWORD flags, DDOVERLAYFX *fx)
3951 struct ddraw_surface *src_impl = impl_from_IDirectDrawSurface4(iface);
3952 struct ddraw_surface *dst_impl = unsafe_impl_from_IDirectDrawSurface4(dst_surface);
3954 TRACE("iface %p, src_rect %s, dst_surface %p, dst_rect %s, flags %#x, fx %p.\n",
3955 iface, wine_dbgstr_rect(src_rect), dst_surface, wine_dbgstr_rect(dst_rect), flags, fx);
3957 return ddraw_surface7_UpdateOverlay(&src_impl->IDirectDrawSurface7_iface, src_rect,
3958 dst_impl ? &dst_impl->IDirectDrawSurface7_iface : NULL, dst_rect, flags, fx);
3961 static HRESULT WINAPI ddraw_surface3_UpdateOverlay(IDirectDrawSurface3 *iface, RECT *src_rect,
3962 IDirectDrawSurface3 *dst_surface, RECT *dst_rect, DWORD flags, DDOVERLAYFX *fx)
3964 struct ddraw_surface *src_impl = impl_from_IDirectDrawSurface3(iface);
3965 struct ddraw_surface *dst_impl = unsafe_impl_from_IDirectDrawSurface3(dst_surface);
3967 TRACE("iface %p, src_rect %s, dst_surface %p, dst_rect %s, flags %#x, fx %p.\n",
3968 iface, wine_dbgstr_rect(src_rect), dst_surface, wine_dbgstr_rect(dst_rect), flags, fx);
3970 return ddraw_surface7_UpdateOverlay(&src_impl->IDirectDrawSurface7_iface, src_rect,
3971 dst_impl ? &dst_impl->IDirectDrawSurface7_iface : NULL, dst_rect, flags, fx);
3974 static HRESULT WINAPI ddraw_surface2_UpdateOverlay(IDirectDrawSurface2 *iface, RECT *src_rect,
3975 IDirectDrawSurface2 *dst_surface, RECT *dst_rect, DWORD flags, DDOVERLAYFX *fx)
3977 struct ddraw_surface *src_impl = impl_from_IDirectDrawSurface2(iface);
3978 struct ddraw_surface *dst_impl = unsafe_impl_from_IDirectDrawSurface2(dst_surface);
3980 TRACE("iface %p, src_rect %s, dst_surface %p, dst_rect %s, flags %#x, fx %p.\n",
3981 iface, wine_dbgstr_rect(src_rect), dst_surface, wine_dbgstr_rect(dst_rect), flags, fx);
3983 return ddraw_surface7_UpdateOverlay(&src_impl->IDirectDrawSurface7_iface, src_rect,
3984 dst_impl ? &dst_impl->IDirectDrawSurface7_iface : NULL, dst_rect, flags, fx);
3987 static HRESULT WINAPI ddraw_surface1_UpdateOverlay(IDirectDrawSurface *iface, RECT *src_rect,
3988 IDirectDrawSurface *dst_surface, RECT *dst_rect, DWORD flags, DDOVERLAYFX *fx)
3990 struct ddraw_surface *src_impl = impl_from_IDirectDrawSurface(iface);
3991 struct ddraw_surface *dst_impl = unsafe_impl_from_IDirectDrawSurface(dst_surface);
3993 TRACE("iface %p, src_rect %s, dst_surface %p, dst_rect %s, flags %#x, fx %p.\n",
3994 iface, wine_dbgstr_rect(src_rect), dst_surface, wine_dbgstr_rect(dst_rect), flags, fx);
3996 return ddraw_surface7_UpdateOverlay(&src_impl->IDirectDrawSurface7_iface, src_rect,
3997 dst_impl ? &dst_impl->IDirectDrawSurface7_iface : NULL, dst_rect, flags, fx);
4000 /*****************************************************************************
4001 * IDirectDrawSurface7::UpdateOverlayDisplay
4003 * The DX7 sdk says that it's not implemented
4005 * Params:
4006 * Flags: ?
4008 * Returns: DDERR_UNSUPPORTED, because we don't support overlays
4010 *****************************************************************************/
4011 static HRESULT WINAPI ddraw_surface7_UpdateOverlayDisplay(IDirectDrawSurface7 *iface, DWORD Flags)
4013 TRACE("iface %p, flags %#x.\n", iface, Flags);
4015 return DDERR_UNSUPPORTED;
4018 static HRESULT WINAPI ddraw_surface4_UpdateOverlayDisplay(IDirectDrawSurface4 *iface, DWORD flags)
4020 struct ddraw_surface *surface = impl_from_IDirectDrawSurface4(iface);
4022 TRACE("iface %p, flags %#x.\n", iface, flags);
4024 return ddraw_surface7_UpdateOverlayDisplay(&surface->IDirectDrawSurface7_iface, flags);
4027 static HRESULT WINAPI ddraw_surface3_UpdateOverlayDisplay(IDirectDrawSurface3 *iface, DWORD flags)
4029 struct ddraw_surface *surface = impl_from_IDirectDrawSurface3(iface);
4031 TRACE("iface %p, flags %#x.\n", iface, flags);
4033 return ddraw_surface7_UpdateOverlayDisplay(&surface->IDirectDrawSurface7_iface, flags);
4036 static HRESULT WINAPI ddraw_surface2_UpdateOverlayDisplay(IDirectDrawSurface2 *iface, DWORD flags)
4038 struct ddraw_surface *surface = impl_from_IDirectDrawSurface2(iface);
4040 TRACE("iface %p, flags %#x.\n", iface, flags);
4042 return ddraw_surface7_UpdateOverlayDisplay(&surface->IDirectDrawSurface7_iface, flags);
4045 static HRESULT WINAPI ddraw_surface1_UpdateOverlayDisplay(IDirectDrawSurface *iface, DWORD flags)
4047 struct ddraw_surface *surface = impl_from_IDirectDrawSurface(iface);
4049 TRACE("iface %p, flags %#x.\n", iface, flags);
4051 return ddraw_surface7_UpdateOverlayDisplay(&surface->IDirectDrawSurface7_iface, flags);
4054 /*****************************************************************************
4055 * IDirectDrawSurface7::UpdateOverlayZOrder
4057 * Sets an overlay's Z order
4059 * Params:
4060 * Flags: DDOVERZ_* flags
4061 * DDSRef: Defines the relative position in the overlay chain
4063 * Returns:
4064 * DDERR_NOTOVERLAYSURFACE, because we don't support overlays
4066 *****************************************************************************/
4067 static HRESULT WINAPI ddraw_surface7_UpdateOverlayZOrder(IDirectDrawSurface7 *iface,
4068 DWORD flags, IDirectDrawSurface7 *reference)
4070 struct ddraw_surface *surface = impl_from_IDirectDrawSurface7(iface);
4072 FIXME("iface %p, flags %#x, reference %p stub!\n", iface, flags, reference);
4074 wined3d_mutex_lock();
4075 if (!(surface->surface_desc.ddsCaps.dwCaps & DDSCAPS_OVERLAY))
4077 WARN("Not an overlay surface.\n");
4078 wined3d_mutex_unlock();
4079 return DDERR_NOTAOVERLAYSURFACE;
4081 wined3d_mutex_unlock();
4083 return DD_OK;
4086 static HRESULT WINAPI ddraw_surface4_UpdateOverlayZOrder(IDirectDrawSurface4 *iface,
4087 DWORD flags, IDirectDrawSurface4 *reference)
4089 struct ddraw_surface *surface = impl_from_IDirectDrawSurface4(iface);
4090 struct ddraw_surface *reference_impl = unsafe_impl_from_IDirectDrawSurface4(reference);
4092 TRACE("iface %p, flags %#x, reference %p.\n", iface, flags, reference);
4094 return ddraw_surface7_UpdateOverlayZOrder(&surface->IDirectDrawSurface7_iface, flags,
4095 reference_impl ? &reference_impl->IDirectDrawSurface7_iface : NULL);
4098 static HRESULT WINAPI ddraw_surface3_UpdateOverlayZOrder(IDirectDrawSurface3 *iface,
4099 DWORD flags, IDirectDrawSurface3 *reference)
4101 struct ddraw_surface *surface = impl_from_IDirectDrawSurface3(iface);
4102 struct ddraw_surface *reference_impl = unsafe_impl_from_IDirectDrawSurface3(reference);
4104 TRACE("iface %p, flags %#x, reference %p.\n", iface, flags, reference);
4106 return ddraw_surface7_UpdateOverlayZOrder(&surface->IDirectDrawSurface7_iface, flags,
4107 reference_impl ? &reference_impl->IDirectDrawSurface7_iface : NULL);
4110 static HRESULT WINAPI ddraw_surface2_UpdateOverlayZOrder(IDirectDrawSurface2 *iface,
4111 DWORD flags, IDirectDrawSurface2 *reference)
4113 struct ddraw_surface *surface = impl_from_IDirectDrawSurface2(iface);
4114 struct ddraw_surface *reference_impl = unsafe_impl_from_IDirectDrawSurface2(reference);
4116 TRACE("iface %p, flags %#x, reference %p.\n", iface, flags, reference);
4118 return ddraw_surface7_UpdateOverlayZOrder(&surface->IDirectDrawSurface7_iface, flags,
4119 reference_impl ? &reference_impl->IDirectDrawSurface7_iface : NULL);
4122 static HRESULT WINAPI ddraw_surface1_UpdateOverlayZOrder(IDirectDrawSurface *iface,
4123 DWORD flags, IDirectDrawSurface *reference)
4125 struct ddraw_surface *surface = impl_from_IDirectDrawSurface(iface);
4126 struct ddraw_surface *reference_impl = unsafe_impl_from_IDirectDrawSurface(reference);
4128 TRACE("iface %p, flags %#x, reference %p.\n", iface, flags, reference);
4130 return ddraw_surface7_UpdateOverlayZOrder(&surface->IDirectDrawSurface7_iface, flags,
4131 reference_impl ? &reference_impl->IDirectDrawSurface7_iface : NULL);
4134 /*****************************************************************************
4135 * IDirectDrawSurface7::GetDDInterface
4137 * Returns the IDirectDraw7 interface pointer of the DirectDraw object this
4138 * surface belongs to
4140 * Params:
4141 * DD: Address to write the interface pointer to
4143 * Returns:
4144 * DD_OK on success
4145 * DDERR_INVALIDPARAMS if DD is NULL
4147 *****************************************************************************/
4148 static HRESULT WINAPI ddraw_surface7_GetDDInterface(IDirectDrawSurface7 *iface, void **DD)
4150 struct ddraw_surface *This = impl_from_IDirectDrawSurface7(iface);
4152 TRACE("iface %p, ddraw %p.\n", iface, DD);
4154 if(!DD)
4155 return DDERR_INVALIDPARAMS;
4157 switch(This->version)
4159 case 7:
4160 *DD = &This->ddraw->IDirectDraw7_iface;
4161 break;
4163 case 4:
4164 *DD = &This->ddraw->IDirectDraw4_iface;
4165 break;
4167 case 2:
4168 *DD = &This->ddraw->IDirectDraw2_iface;
4169 break;
4171 case 1:
4172 *DD = &This->ddraw->IDirectDraw_iface;
4173 break;
4176 IUnknown_AddRef((IUnknown *)*DD);
4178 return DD_OK;
4181 static HRESULT WINAPI ddraw_surface4_GetDDInterface(IDirectDrawSurface4 *iface, void **ddraw)
4183 struct ddraw_surface *surface = impl_from_IDirectDrawSurface4(iface);
4185 TRACE("iface %p, ddraw %p.\n", iface, ddraw);
4187 return ddraw_surface7_GetDDInterface(&surface->IDirectDrawSurface7_iface, ddraw);
4190 static HRESULT WINAPI ddraw_surface3_GetDDInterface(IDirectDrawSurface3 *iface, void **ddraw)
4192 struct ddraw_surface *surface = impl_from_IDirectDrawSurface3(iface);
4194 TRACE("iface %p, ddraw %p.\n", iface, ddraw);
4196 return ddraw_surface7_GetDDInterface(&surface->IDirectDrawSurface7_iface, ddraw);
4199 static HRESULT WINAPI ddraw_surface2_GetDDInterface(IDirectDrawSurface2 *iface, void **ddraw)
4201 struct ddraw_surface *surface = impl_from_IDirectDrawSurface2(iface);
4203 TRACE("iface %p, ddraw %p.\n", iface, ddraw);
4205 return ddraw_surface7_GetDDInterface(&surface->IDirectDrawSurface7_iface, ddraw);
4208 static HRESULT WINAPI ddraw_surface7_ChangeUniquenessValue(IDirectDrawSurface7 *iface)
4210 TRACE("iface %p.\n", iface);
4212 return DD_OK;
4215 static HRESULT WINAPI ddraw_surface4_ChangeUniquenessValue(IDirectDrawSurface4 *iface)
4217 struct ddraw_surface *surface = impl_from_IDirectDrawSurface4(iface);
4219 TRACE("iface %p.\n", iface);
4221 return ddraw_surface7_ChangeUniquenessValue(&surface->IDirectDrawSurface7_iface);
4224 static HRESULT WINAPI ddraw_surface7_GetUniquenessValue(IDirectDrawSurface7 *iface, DWORD *pValue)
4226 TRACE("iface %p, value %p.\n", iface, pValue);
4228 *pValue = 0;
4230 return DD_OK;
4233 static HRESULT WINAPI ddraw_surface4_GetUniquenessValue(IDirectDrawSurface4 *iface, DWORD *pValue)
4235 struct ddraw_surface *surface = impl_from_IDirectDrawSurface4(iface);
4237 TRACE("iface %p, value %p.\n", iface, pValue);
4239 return ddraw_surface7_GetUniquenessValue(&surface->IDirectDrawSurface7_iface, pValue);
4242 /*****************************************************************************
4243 * IDirectDrawSurface7::SetLOD
4245 * Sets the level of detail of a texture
4247 * Params:
4248 * MaxLOD: LOD to set
4250 * Returns:
4251 * DD_OK on success
4252 * DDERR_INVALIDOBJECT if the surface is invalid for this method
4254 *****************************************************************************/
4255 static HRESULT WINAPI ddraw_surface7_SetLOD(IDirectDrawSurface7 *iface, DWORD MaxLOD)
4257 struct ddraw_surface *surface = impl_from_IDirectDrawSurface7(iface);
4258 HRESULT hr;
4260 TRACE("iface %p, lod %u.\n", iface, MaxLOD);
4262 wined3d_mutex_lock();
4263 if (!(surface->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_TEXTUREMANAGE))
4265 wined3d_mutex_unlock();
4266 return DDERR_INVALIDOBJECT;
4269 hr = wined3d_texture_set_lod(surface->wined3d_texture, MaxLOD);
4270 wined3d_mutex_unlock();
4272 return hr;
4275 /*****************************************************************************
4276 * IDirectDrawSurface7::GetLOD
4278 * Returns the level of detail of a Direct3D texture
4280 * Params:
4281 * MaxLOD: Address to write the LOD to
4283 * Returns:
4284 * DD_OK on success
4285 * DDERR_INVALIDPARAMS if MaxLOD is NULL
4286 * DDERR_INVALIDOBJECT if the surface is invalid for this method
4288 *****************************************************************************/
4289 static HRESULT WINAPI ddraw_surface7_GetLOD(IDirectDrawSurface7 *iface, DWORD *MaxLOD)
4291 struct ddraw_surface *surface = impl_from_IDirectDrawSurface7(iface);
4293 TRACE("iface %p, lod %p.\n", iface, MaxLOD);
4295 if(!MaxLOD)
4296 return DDERR_INVALIDPARAMS;
4298 wined3d_mutex_lock();
4299 if (!(surface->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_TEXTUREMANAGE))
4301 wined3d_mutex_unlock();
4302 return DDERR_INVALIDOBJECT;
4305 *MaxLOD = wined3d_texture_get_lod(surface->wined3d_texture);
4306 wined3d_mutex_unlock();
4308 return DD_OK;
4311 /*****************************************************************************
4312 * IDirectDrawSurface7::BltFast
4314 * Performs a fast Blit.
4316 * Params:
4317 * dstx: The x coordinate to blit to on the destination
4318 * dsty: The y coordinate to blit to on the destination
4319 * Source: The source surface
4320 * rsrc: The source rectangle
4321 * trans: Type of transfer. Some DDBLTFAST_* flags
4323 * Returns:
4324 * DD_OK on success, error code otherwise.
4326 *****************************************************************************/
4327 static HRESULT WINAPI DECLSPEC_HOTPATCH ddraw_surface7_BltFast(IDirectDrawSurface7 *iface,
4328 DWORD dst_x, DWORD dst_y, IDirectDrawSurface7 *src_surface, RECT *src_rect, DWORD trans)
4330 struct ddraw_surface *dst_impl = impl_from_IDirectDrawSurface7(iface);
4331 struct ddraw_surface *src_impl = unsafe_impl_from_IDirectDrawSurface7(src_surface);
4332 DWORD flags = WINED3D_BLT_SYNCHRONOUS;
4333 DWORD src_w, src_h, dst_w, dst_h;
4334 HRESULT hr = DD_OK;
4335 RECT dst_rect, s;
4337 TRACE("iface %p, dst_x %u, dst_y %u, src_surface %p, src_rect %s, flags %#x.\n",
4338 iface, dst_x, dst_y, src_surface, wine_dbgstr_rect(src_rect), trans);
4340 dst_w = dst_impl->surface_desc.dwWidth;
4341 dst_h = dst_impl->surface_desc.dwHeight;
4343 if (!src_rect)
4345 SetRect(&s, 0, 0, src_impl->surface_desc.dwWidth, src_impl->surface_desc.dwHeight);
4346 src_rect = &s;
4349 src_w = src_rect->right - src_rect->left;
4350 src_h = src_rect->bottom - src_rect->top;
4351 if (src_w > dst_w || dst_x > dst_w - src_w
4352 || src_h > dst_h || dst_y > dst_h - src_h)
4354 WARN("Destination area out of bounds, returning DDERR_INVALIDRECT.\n");
4355 return DDERR_INVALIDRECT;
4358 SetRect(&dst_rect, dst_x, dst_y, dst_x + src_w, dst_y + src_h);
4359 if (trans & DDBLTFAST_SRCCOLORKEY)
4360 flags |= WINED3D_BLT_SRC_CKEY;
4361 if (trans & DDBLTFAST_DESTCOLORKEY)
4362 flags |= WINED3D_BLT_DST_CKEY;
4363 if (trans & DDBLTFAST_WAIT)
4364 flags |= WINED3D_BLT_WAIT;
4365 if (trans & DDBLTFAST_DONOTWAIT)
4366 flags |= WINED3D_BLT_DO_NOT_WAIT;
4368 wined3d_mutex_lock();
4369 if (dst_impl->clipper)
4371 wined3d_mutex_unlock();
4372 WARN("Destination surface has a clipper set, returning DDERR_BLTFASTCANTCLIP.\n");
4373 return DDERR_BLTFASTCANTCLIP;
4376 if (src_impl->surface_desc.ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE)
4377 hr = ddraw_surface_update_frontbuffer(src_impl, src_rect, TRUE, 0);
4378 if (SUCCEEDED(hr))
4379 hr = wined3d_texture_blt(dst_impl->wined3d_texture, dst_impl->sub_resource_idx, &dst_rect,
4380 src_impl->wined3d_texture, src_impl->sub_resource_idx, src_rect, flags, NULL, WINED3D_TEXF_POINT);
4381 if (SUCCEEDED(hr) && (dst_impl->surface_desc.ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE))
4382 hr = ddraw_surface_update_frontbuffer(dst_impl, &dst_rect, FALSE, 0);
4383 wined3d_mutex_unlock();
4385 switch(hr)
4387 case WINED3DERR_NOTAVAILABLE: return DDERR_UNSUPPORTED;
4388 default: return hr;
4392 static HRESULT WINAPI DECLSPEC_HOTPATCH ddraw_surface4_BltFast(IDirectDrawSurface4 *iface, DWORD dst_x, DWORD dst_y,
4393 IDirectDrawSurface4 *src_surface, RECT *src_rect, DWORD flags)
4395 struct ddraw_surface *dst_impl = impl_from_IDirectDrawSurface4(iface);
4396 struct ddraw_surface *src_impl = unsafe_impl_from_IDirectDrawSurface4(src_surface);
4398 TRACE("iface %p, dst_x %u, dst_y %u, src_surface %p, src_rect %s, flags %#x.\n",
4399 iface, dst_x, dst_y, src_surface, wine_dbgstr_rect(src_rect), flags);
4401 return ddraw_surface7_BltFast(&dst_impl->IDirectDrawSurface7_iface, dst_x, dst_y,
4402 src_impl ? &src_impl->IDirectDrawSurface7_iface : NULL, src_rect, flags);
4405 static HRESULT WINAPI DECLSPEC_HOTPATCH ddraw_surface3_BltFast(IDirectDrawSurface3 *iface, DWORD dst_x, DWORD dst_y,
4406 IDirectDrawSurface3 *src_surface, RECT *src_rect, DWORD flags)
4408 struct ddraw_surface *dst_impl = impl_from_IDirectDrawSurface3(iface);
4409 struct ddraw_surface *src_impl = unsafe_impl_from_IDirectDrawSurface3(src_surface);
4411 TRACE("iface %p, dst_x %u, dst_y %u, src_surface %p, src_rect %s, flags %#x.\n",
4412 iface, dst_x, dst_y, src_surface, wine_dbgstr_rect(src_rect), flags);
4414 return ddraw_surface7_BltFast(&dst_impl->IDirectDrawSurface7_iface, dst_x, dst_y,
4415 src_impl ? &src_impl->IDirectDrawSurface7_iface : NULL, src_rect, flags);
4418 static HRESULT WINAPI DECLSPEC_HOTPATCH ddraw_surface2_BltFast(IDirectDrawSurface2 *iface, DWORD dst_x, DWORD dst_y,
4419 IDirectDrawSurface2 *src_surface, RECT *src_rect, DWORD flags)
4421 struct ddraw_surface *dst_impl = impl_from_IDirectDrawSurface2(iface);
4422 struct ddraw_surface *src_impl = unsafe_impl_from_IDirectDrawSurface2(src_surface);
4424 TRACE("iface %p, dst_x %u, dst_y %u, src_surface %p, src_rect %s, flags %#x.\n",
4425 iface, dst_x, dst_y, src_surface, wine_dbgstr_rect(src_rect), flags);
4427 return ddraw_surface7_BltFast(&dst_impl->IDirectDrawSurface7_iface, dst_x, dst_y,
4428 src_impl ? &src_impl->IDirectDrawSurface7_iface : NULL, src_rect, flags);
4431 static HRESULT WINAPI DECLSPEC_HOTPATCH ddraw_surface1_BltFast(IDirectDrawSurface *iface, DWORD dst_x, DWORD dst_y,
4432 IDirectDrawSurface *src_surface, RECT *src_rect, DWORD flags)
4434 struct ddraw_surface *dst_impl = impl_from_IDirectDrawSurface(iface);
4435 struct ddraw_surface *src_impl = unsafe_impl_from_IDirectDrawSurface(src_surface);
4437 TRACE("iface %p, dst_x %u, dst_y %u, src_surface %p, src_rect %s, flags %#x.\n",
4438 iface, dst_x, dst_y, src_surface, wine_dbgstr_rect(src_rect), flags);
4440 return ddraw_surface7_BltFast(&dst_impl->IDirectDrawSurface7_iface, dst_x, dst_y,
4441 src_impl ? &src_impl->IDirectDrawSurface7_iface : NULL, src_rect, flags);
4444 static HRESULT WINAPI ddraw_surface7_GetClipper(IDirectDrawSurface7 *iface, IDirectDrawClipper **clipper)
4446 struct ddraw_surface *surface = impl_from_IDirectDrawSurface7(iface);
4448 TRACE("iface %p, clipper %p.\n", iface, clipper);
4450 if (!clipper)
4451 return DDERR_INVALIDPARAMS;
4453 wined3d_mutex_lock();
4454 if (!surface->clipper)
4456 wined3d_mutex_unlock();
4457 *clipper = NULL;
4458 return DDERR_NOCLIPPERATTACHED;
4461 *clipper = &surface->clipper->IDirectDrawClipper_iface;
4462 if (ddraw_clipper_is_valid(surface->clipper))
4463 IDirectDrawClipper_AddRef(*clipper);
4464 wined3d_mutex_unlock();
4466 return DD_OK;
4469 static HRESULT WINAPI ddraw_surface4_GetClipper(IDirectDrawSurface4 *iface, IDirectDrawClipper **clipper)
4471 struct ddraw_surface *surface = impl_from_IDirectDrawSurface4(iface);
4473 TRACE("iface %p, clipper %p.\n", iface, clipper);
4475 return ddraw_surface7_GetClipper(&surface->IDirectDrawSurface7_iface, clipper);
4478 static HRESULT WINAPI ddraw_surface3_GetClipper(IDirectDrawSurface3 *iface, IDirectDrawClipper **clipper)
4480 struct ddraw_surface *surface = impl_from_IDirectDrawSurface3(iface);
4482 TRACE("iface %p, clipper %p.\n", iface, clipper);
4484 return ddraw_surface7_GetClipper(&surface->IDirectDrawSurface7_iface, clipper);
4487 static HRESULT WINAPI ddraw_surface2_GetClipper(IDirectDrawSurface2 *iface, IDirectDrawClipper **clipper)
4489 struct ddraw_surface *surface = impl_from_IDirectDrawSurface2(iface);
4491 TRACE("iface %p, clipper %p.\n", iface, clipper);
4493 return ddraw_surface7_GetClipper(&surface->IDirectDrawSurface7_iface, clipper);
4496 static HRESULT WINAPI ddraw_surface1_GetClipper(IDirectDrawSurface *iface, IDirectDrawClipper **clipper)
4498 struct ddraw_surface *surface = impl_from_IDirectDrawSurface(iface);
4500 TRACE("iface %p, clipper %p.\n", iface, clipper);
4502 return ddraw_surface7_GetClipper(&surface->IDirectDrawSurface7_iface, clipper);
4505 /*****************************************************************************
4506 * IDirectDrawSurface7::SetClipper
4508 * Sets a clipper for the surface
4510 * Params:
4511 * Clipper: IDirectDrawClipper interface of the clipper to set
4513 * Returns:
4514 * DD_OK on success
4516 *****************************************************************************/
4517 static HRESULT WINAPI ddraw_surface7_SetClipper(IDirectDrawSurface7 *iface,
4518 IDirectDrawClipper *iclipper)
4520 struct ddraw_surface *This = impl_from_IDirectDrawSurface7(iface);
4521 struct ddraw_clipper *clipper = unsafe_impl_from_IDirectDrawClipper(iclipper);
4522 struct ddraw_clipper *old_clipper = This->clipper;
4523 HWND clipWindow;
4525 TRACE("iface %p, clipper %p.\n", iface, iclipper);
4527 wined3d_mutex_lock();
4528 if (clipper == This->clipper)
4530 wined3d_mutex_unlock();
4531 return DD_OK;
4534 This->clipper = clipper;
4536 if (clipper != NULL)
4537 IDirectDrawClipper_AddRef(iclipper);
4538 if (old_clipper && ddraw_clipper_is_valid(old_clipper))
4539 IDirectDrawClipper_Release(&old_clipper->IDirectDrawClipper_iface);
4541 if ((This->surface_desc.ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE) && This->ddraw->wined3d_swapchain)
4543 clipWindow = NULL;
4544 if(clipper) {
4545 IDirectDrawClipper_GetHWnd(iclipper, &clipWindow);
4548 if (clipWindow)
4550 wined3d_swapchain_set_window(This->ddraw->wined3d_swapchain, clipWindow);
4551 ddraw_set_swapchain_window(This->ddraw, clipWindow);
4553 else
4555 wined3d_swapchain_set_window(This->ddraw->wined3d_swapchain, This->ddraw->d3d_window);
4556 ddraw_set_swapchain_window(This->ddraw, This->ddraw->dest_window);
4560 wined3d_mutex_unlock();
4562 return DD_OK;
4565 static HRESULT WINAPI ddraw_surface4_SetClipper(IDirectDrawSurface4 *iface, IDirectDrawClipper *clipper)
4567 struct ddraw_surface *surface = impl_from_IDirectDrawSurface4(iface);
4569 TRACE("iface %p, clipper %p.\n", iface, clipper);
4571 return ddraw_surface7_SetClipper(&surface->IDirectDrawSurface7_iface, clipper);
4574 static HRESULT WINAPI ddraw_surface3_SetClipper(IDirectDrawSurface3 *iface, IDirectDrawClipper *clipper)
4576 struct ddraw_surface *surface = impl_from_IDirectDrawSurface3(iface);
4578 TRACE("iface %p, clipper %p.\n", iface, clipper);
4580 return ddraw_surface7_SetClipper(&surface->IDirectDrawSurface7_iface, clipper);
4583 static HRESULT WINAPI ddraw_surface2_SetClipper(IDirectDrawSurface2 *iface, IDirectDrawClipper *clipper)
4585 struct ddraw_surface *surface = impl_from_IDirectDrawSurface2(iface);
4587 TRACE("iface %p, clipper %p.\n", iface, clipper);
4589 return ddraw_surface7_SetClipper(&surface->IDirectDrawSurface7_iface, clipper);
4592 static HRESULT WINAPI ddraw_surface1_SetClipper(IDirectDrawSurface *iface, IDirectDrawClipper *clipper)
4594 struct ddraw_surface *surface = impl_from_IDirectDrawSurface(iface);
4596 TRACE("iface %p, clipper %p.\n", iface, clipper);
4598 return ddraw_surface7_SetClipper(&surface->IDirectDrawSurface7_iface, clipper);
4601 /*****************************************************************************
4602 * IDirectDrawSurface7::SetSurfaceDesc
4604 * Sets the surface description. It can override the pixel format, the surface
4605 * memory, ...
4606 * It's not really tested.
4608 * Params:
4609 * DDSD: Pointer to the new surface description to set
4610 * Flags: Some flags
4612 * Returns:
4613 * DD_OK on success
4614 * DDERR_INVALIDPARAMS if DDSD is NULL
4616 *****************************************************************************/
4617 static HRESULT WINAPI ddraw_surface7_SetSurfaceDesc(IDirectDrawSurface7 *iface, DDSURFACEDESC2 *DDSD, DWORD Flags)
4619 struct ddraw_surface *surface = impl_from_IDirectDrawSurface7(iface);
4620 HRESULT hr;
4621 const DWORD allowed_flags = DDSD_LPSURFACE | DDSD_PIXELFORMAT | DDSD_WIDTH
4622 | DDSD_HEIGHT | DDSD_PITCH | DDSD_CAPS;
4623 enum wined3d_format_id format_id;
4624 UINT pitch, width, height;
4626 TRACE("iface %p, surface_desc %p, flags %#x.\n", iface, DDSD, Flags);
4628 if (!DDSD)
4630 WARN("DDSD is NULL, returning DDERR_INVALIDPARAMS\n");
4631 return DDERR_INVALIDPARAMS;
4633 if (Flags)
4635 WARN("Flags is %x, returning DDERR_INVALIDPARAMS\n", Flags);
4636 return DDERR_INVALIDPARAMS;
4638 if (!(surface->surface_desc.ddsCaps.dwCaps & DDSCAPS_SYSTEMMEMORY)
4639 || surface->surface_desc.ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE
4640 || surface->surface_desc.ddsCaps.dwCaps2 & (DDSCAPS2_TEXTUREMANAGE | DDSCAPS2_D3DTEXTUREMANAGE))
4642 WARN("Surface is not in system memory, returning DDERR_INVALIDSURFACETYPE.\n");
4643 return DDERR_INVALIDSURFACETYPE;
4646 /* Tests show that only LPSURFACE and PIXELFORMAT can be set, and LPSURFACE is required
4647 * for PIXELFORMAT to work */
4648 if (DDSD->dwFlags & ~allowed_flags)
4650 WARN("Invalid flags (0x%08x) set, returning DDERR_INVALIDPARAMS\n", DDSD->dwFlags);
4651 return DDERR_INVALIDPARAMS;
4653 if (!(DDSD->dwFlags & DDSD_LPSURFACE) || !DDSD->lpSurface)
4655 WARN("DDSD_LPSURFACE is not set or lpSurface is NULL, returning DDERR_INVALIDPARAMS\n");
4656 return DDERR_INVALIDPARAMS;
4658 if ((DDSD->dwFlags & DDSD_CAPS) && DDSD->ddsCaps.dwCaps)
4660 WARN("DDSD_CAPS is set, returning DDERR_INVALIDCAPS.\n");
4661 return DDERR_INVALIDCAPS;
4663 if (DDSD->dwFlags & DDSD_WIDTH)
4665 if (!(DDSD->dwFlags & DDSD_PITCH))
4667 WARN("DDSD_WIDTH is set, but DDSD_PITCH is not, returning DDERR_INVALIDPARAMS.\n");
4668 return DDERR_INVALIDPARAMS;
4670 if (!DDSD->dwWidth || DDSD->u1.lPitch <= 0 || DDSD->u1.lPitch & 0x3)
4672 WARN("Pitch is %d, width is %u, returning DDERR_INVALIDPARAMS.\n",
4673 DDSD->u1.lPitch, DDSD->dwWidth);
4674 return DDERR_INVALIDPARAMS;
4676 if (DDSD->dwWidth != surface->surface_desc.dwWidth)
4677 TRACE("Surface width changed from %u to %u.\n", surface->surface_desc.dwWidth, DDSD->dwWidth);
4678 if (DDSD->u1.lPitch != surface->surface_desc.u1.lPitch)
4679 TRACE("Surface pitch changed from %u to %u.\n", surface->surface_desc.u1.lPitch, DDSD->u1.lPitch);
4680 pitch = DDSD->u1.lPitch;
4681 width = DDSD->dwWidth;
4683 else if (DDSD->dwFlags & DDSD_PITCH)
4685 WARN("DDSD_PITCH is set, but DDSD_WIDTH is not, returning DDERR_INVALIDPARAMS.\n");
4686 return DDERR_INVALIDPARAMS;
4688 else
4690 pitch = surface->surface_desc.u1.lPitch;
4691 width = surface->surface_desc.dwWidth;
4694 if (DDSD->dwFlags & DDSD_HEIGHT)
4696 if (!DDSD->dwHeight)
4698 WARN("Height is 0, returning DDERR_INVALIDPARAMS.\n");
4699 return DDERR_INVALIDPARAMS;
4701 if (DDSD->dwHeight != surface->surface_desc.dwHeight)
4702 TRACE("Surface height changed from %u to %u.\n", surface->surface_desc.dwHeight, DDSD->dwHeight);
4703 height = DDSD->dwHeight;
4705 else
4707 height = surface->surface_desc.dwHeight;
4710 wined3d_mutex_lock();
4711 if (DDSD->dwFlags & DDSD_PIXELFORMAT)
4713 enum wined3d_format_id current_format_id;
4714 format_id = wined3dformat_from_ddrawformat(&DDSD->u4.ddpfPixelFormat);
4716 if (format_id == WINED3DFMT_UNKNOWN)
4718 ERR("Requested to set an unknown pixelformat\n");
4719 wined3d_mutex_unlock();
4720 return DDERR_INVALIDPARAMS;
4722 current_format_id = wined3dformat_from_ddrawformat(&surface->surface_desc.u4.ddpfPixelFormat);
4723 if (format_id != current_format_id)
4724 TRACE("Surface format changed from %#x to %#x.\n", current_format_id, format_id);
4726 else
4728 format_id = wined3dformat_from_ddrawformat(&surface->surface_desc.u4.ddpfPixelFormat);
4731 if (FAILED(hr = wined3d_texture_update_desc(surface->wined3d_texture, surface->sub_resource_idx,
4732 width, height, format_id, WINED3D_MULTISAMPLE_NONE, 0, DDSD->lpSurface, pitch)))
4734 WARN("Failed to update surface desc, hr %#x.\n", hr);
4735 wined3d_mutex_unlock();
4736 return hr_ddraw_from_wined3d(hr);
4739 if (DDSD->dwFlags & DDSD_WIDTH)
4740 surface->surface_desc.dwWidth = width;
4741 if (DDSD->dwFlags & DDSD_PITCH)
4742 surface->surface_desc.u1.lPitch = DDSD->u1.lPitch;
4743 if (DDSD->dwFlags & DDSD_HEIGHT)
4744 surface->surface_desc.dwHeight = height;
4745 if (DDSD->dwFlags & DDSD_PIXELFORMAT)
4746 surface->surface_desc.u4.ddpfPixelFormat = DDSD->u4.ddpfPixelFormat;
4748 wined3d_mutex_unlock();
4750 return DD_OK;
4753 static HRESULT WINAPI ddraw_surface4_SetSurfaceDesc(IDirectDrawSurface4 *iface,
4754 DDSURFACEDESC2 *surface_desc, DWORD flags)
4756 struct ddraw_surface *surface = impl_from_IDirectDrawSurface4(iface);
4758 TRACE("iface %p, surface_desc %p, flags %#x.\n", iface, surface_desc, flags);
4760 return ddraw_surface7_SetSurfaceDesc(&surface->IDirectDrawSurface7_iface,
4761 surface_desc, flags);
4764 static HRESULT WINAPI ddraw_surface3_SetSurfaceDesc(IDirectDrawSurface3 *iface,
4765 DDSURFACEDESC *surface_desc, DWORD flags)
4767 struct ddraw_surface *surface = impl_from_IDirectDrawSurface3(iface);
4768 DDSURFACEDESC2 surface_desc2;
4770 TRACE("iface %p, surface_desc %p, flags %#x.\n", iface, surface_desc, flags);
4772 if (surface_desc) DDSD_to_DDSD2(surface_desc, &surface_desc2);
4773 return ddraw_surface7_SetSurfaceDesc(&surface->IDirectDrawSurface7_iface,
4774 surface_desc ? &surface_desc2 : NULL, flags);
4777 static HRESULT WINAPI ddraw_surface7_GetPalette(IDirectDrawSurface7 *iface, IDirectDrawPalette **palette)
4779 struct ddraw_surface *surface = impl_from_IDirectDrawSurface7(iface);
4780 struct ddraw_palette *palette_impl;
4781 HRESULT hr = DD_OK;
4783 TRACE("iface %p, palette %p.\n", iface, palette);
4785 if (!palette)
4786 return DDERR_INVALIDPARAMS;
4787 if (ddraw_surface_is_lost(surface))
4789 WARN("Surface lost, returning DDERR_SURFACELOST.\n");
4790 return DDERR_SURFACELOST;
4793 wined3d_mutex_lock();
4794 if ((palette_impl = surface->palette))
4796 *palette = &palette_impl->IDirectDrawPalette_iface;
4797 IDirectDrawPalette_AddRef(*palette);
4799 else
4801 *palette = NULL;
4802 hr = DDERR_NOPALETTEATTACHED;
4804 wined3d_mutex_unlock();
4806 return hr;
4809 static HRESULT WINAPI ddraw_surface4_GetPalette(IDirectDrawSurface4 *iface, IDirectDrawPalette **palette)
4811 struct ddraw_surface *surface = impl_from_IDirectDrawSurface4(iface);
4813 TRACE("iface %p, palette %p.\n", iface, palette);
4815 return ddraw_surface7_GetPalette(&surface->IDirectDrawSurface7_iface, palette);
4818 static HRESULT WINAPI ddraw_surface3_GetPalette(IDirectDrawSurface3 *iface, IDirectDrawPalette **palette)
4820 struct ddraw_surface *surface = impl_from_IDirectDrawSurface3(iface);
4822 TRACE("iface %p, palette %p.\n", iface, palette);
4824 return ddraw_surface7_GetPalette(&surface->IDirectDrawSurface7_iface, palette);
4827 static HRESULT WINAPI ddraw_surface2_GetPalette(IDirectDrawSurface2 *iface, IDirectDrawPalette **palette)
4829 struct ddraw_surface *surface = impl_from_IDirectDrawSurface2(iface);
4831 TRACE("iface %p, palette %p.\n", iface, palette);
4833 return ddraw_surface7_GetPalette(&surface->IDirectDrawSurface7_iface, palette);
4836 static HRESULT WINAPI ddraw_surface1_GetPalette(IDirectDrawSurface *iface, IDirectDrawPalette **palette)
4838 struct ddraw_surface *surface = impl_from_IDirectDrawSurface(iface);
4840 TRACE("iface %p, palette %p.\n", iface, palette);
4842 return ddraw_surface7_GetPalette(&surface->IDirectDrawSurface7_iface, palette);
4845 static HRESULT ddraw_surface_set_color_key(struct ddraw_surface *surface, DWORD flags, DDCOLORKEY *color_key)
4847 DDCOLORKEY fixed_color_key;
4848 HRESULT hr = WINED3D_OK;
4850 if (flags & DDCKEY_COLORSPACE)
4852 if (color_key && color_key->dwColorSpaceLowValue != color_key->dwColorSpaceHighValue)
4854 WARN("Range color keys are not supported, returning DDERR_NOCOLORKEYHW.\n");
4855 return DDERR_NOCOLORKEYHW;
4857 flags &= ~DDCKEY_COLORSPACE;
4860 wined3d_mutex_lock();
4862 if (color_key)
4864 fixed_color_key.dwColorSpaceLowValue = fixed_color_key.dwColorSpaceHighValue = color_key->dwColorSpaceLowValue;
4865 switch (flags & ~DDCKEY_COLORSPACE)
4867 case DDCKEY_DESTBLT:
4868 surface->surface_desc.ddckCKDestBlt = fixed_color_key;
4869 surface->surface_desc.dwFlags |= DDSD_CKDESTBLT;
4870 break;
4872 case DDCKEY_DESTOVERLAY:
4873 surface->surface_desc.u3.ddckCKDestOverlay = fixed_color_key;
4874 surface->surface_desc.dwFlags |= DDSD_CKDESTOVERLAY;
4875 break;
4877 case DDCKEY_SRCOVERLAY:
4878 surface->surface_desc.ddckCKSrcOverlay = fixed_color_key;
4879 surface->surface_desc.dwFlags |= DDSD_CKSRCOVERLAY;
4880 break;
4882 case DDCKEY_SRCBLT:
4883 surface->surface_desc.ddckCKSrcBlt = fixed_color_key;
4884 surface->surface_desc.dwFlags |= DDSD_CKSRCBLT;
4885 break;
4887 default:
4888 wined3d_mutex_unlock();
4889 return DDERR_INVALIDPARAMS;
4892 else
4894 switch (flags & ~DDCKEY_COLORSPACE)
4896 case DDCKEY_DESTBLT:
4897 surface->surface_desc.dwFlags &= ~DDSD_CKDESTBLT;
4898 break;
4900 case DDCKEY_DESTOVERLAY:
4901 surface->surface_desc.dwFlags &= ~DDSD_CKDESTOVERLAY;
4902 break;
4904 case DDCKEY_SRCOVERLAY:
4905 surface->surface_desc.dwFlags &= ~DDSD_CKSRCOVERLAY;
4906 break;
4908 case DDCKEY_SRCBLT:
4909 surface->surface_desc.dwFlags &= ~DDSD_CKSRCBLT;
4910 break;
4912 default:
4913 wined3d_mutex_unlock();
4914 return DDERR_INVALIDPARAMS;
4918 if (surface->is_complex_root)
4919 hr = wined3d_texture_set_color_key(surface->wined3d_texture, flags,
4920 color_key ? (struct wined3d_color_key *)&fixed_color_key : NULL);
4922 wined3d_mutex_unlock();
4924 return hr_ddraw_from_wined3d(hr);
4927 static HRESULT WINAPI ddraw_surface7_SetColorKey(IDirectDrawSurface7 *iface, DWORD flags, DDCOLORKEY *color_key)
4929 struct ddraw_surface *surface = impl_from_IDirectDrawSurface7(iface);
4931 TRACE("iface %p, flags %#x, color_key %p.\n", iface, flags, color_key);
4933 if (surface->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_MIPMAPSUBLEVEL)
4934 return DDERR_NOTONMIPMAPSUBLEVEL;
4936 return ddraw_surface_set_color_key(surface, flags, color_key);
4939 static HRESULT WINAPI ddraw_surface4_SetColorKey(IDirectDrawSurface4 *iface, DWORD flags, DDCOLORKEY *color_key)
4941 struct ddraw_surface *surface = impl_from_IDirectDrawSurface4(iface);
4943 TRACE("iface %p, flags %#x, color_key %p.\n", iface, flags, color_key);
4945 return ddraw_surface_set_color_key(surface, flags, color_key);
4948 static HRESULT WINAPI ddraw_surface3_SetColorKey(IDirectDrawSurface3 *iface, DWORD flags, DDCOLORKEY *color_key)
4950 struct ddraw_surface *surface = impl_from_IDirectDrawSurface3(iface);
4952 TRACE("iface %p, flags %#x, color_key %p.\n", iface, flags, color_key);
4954 return ddraw_surface_set_color_key(surface, flags, color_key);
4957 static HRESULT WINAPI ddraw_surface2_SetColorKey(IDirectDrawSurface2 *iface, DWORD flags, DDCOLORKEY *color_key)
4959 struct ddraw_surface *surface = impl_from_IDirectDrawSurface2(iface);
4961 TRACE("iface %p, flags %#x, color_key %p.\n", iface, flags, color_key);
4963 return ddraw_surface_set_color_key(surface, flags, color_key);
4966 static HRESULT WINAPI ddraw_surface1_SetColorKey(IDirectDrawSurface *iface, DWORD flags, DDCOLORKEY *color_key)
4968 struct ddraw_surface *surface = impl_from_IDirectDrawSurface(iface);
4970 TRACE("iface %p, flags %#x, color_key %p.\n", iface, flags, color_key);
4972 return ddraw_surface_set_color_key(surface, flags, color_key);
4975 static HRESULT WINAPI ddraw_surface7_SetPalette(IDirectDrawSurface7 *iface, IDirectDrawPalette *palette)
4977 struct ddraw_surface *surface = impl_from_IDirectDrawSurface7(iface);
4979 TRACE("iface %p, palette %p.\n", iface, palette);
4981 if (surface->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_MIPMAPSUBLEVEL)
4982 return DDERR_NOTONMIPMAPSUBLEVEL;
4983 if (ddraw_surface_is_lost(surface))
4985 WARN("Surface lost, returning DDERR_SURFACELOST.\n");
4986 return DDERR_SURFACELOST;
4989 return ddraw_surface_set_palette(surface, palette);
4992 static HRESULT WINAPI ddraw_surface4_SetPalette(IDirectDrawSurface4 *iface, IDirectDrawPalette *palette)
4994 struct ddraw_surface *surface = impl_from_IDirectDrawSurface4(iface);
4996 TRACE("iface %p, palette %p.\n", iface, palette);
4998 if (ddraw_surface_is_lost(surface))
5000 WARN("Surface lost, returning DDERR_SURFACELOST.\n");
5001 return DDERR_SURFACELOST;
5004 return ddraw_surface_set_palette(surface, palette);
5007 static HRESULT WINAPI ddraw_surface3_SetPalette(IDirectDrawSurface3 *iface, IDirectDrawPalette *palette)
5009 struct ddraw_surface *surface = impl_from_IDirectDrawSurface3(iface);
5011 TRACE("iface %p, palette %p.\n", iface, palette);
5013 if (ddraw_surface_is_lost(surface))
5015 WARN("Surface lost, returning DDERR_SURFACELOST.\n");
5016 return DDERR_SURFACELOST;
5019 return ddraw_surface_set_palette(surface, palette);
5022 static HRESULT WINAPI ddraw_surface2_SetPalette(IDirectDrawSurface2 *iface, IDirectDrawPalette *palette)
5024 struct ddraw_surface *surface = impl_from_IDirectDrawSurface2(iface);
5026 TRACE("iface %p, palette %p.\n", iface, palette);
5028 if (ddraw_surface_is_lost(surface))
5030 WARN("Surface lost, returning DDERR_SURFACELOST.\n");
5031 return DDERR_SURFACELOST;
5034 return ddraw_surface_set_palette(surface, palette);
5037 static HRESULT WINAPI ddraw_surface1_SetPalette(IDirectDrawSurface *iface, IDirectDrawPalette *palette)
5039 struct ddraw_surface *surface = impl_from_IDirectDrawSurface(iface);
5041 TRACE("iface %p, palette %p.\n", iface, palette);
5043 if (ddraw_surface_is_lost(surface))
5045 WARN("Surface lost, returning DDERR_SURFACELOST.\n");
5046 return DDERR_SURFACELOST;
5049 return ddraw_surface_set_palette(surface, palette);
5052 /**********************************************************
5053 * IDirectDrawGammaControl::GetGammaRamp
5055 * Returns the current gamma ramp for a surface
5057 * Params:
5058 * flags: Ignored
5059 * gamma_ramp: Address to write the ramp to
5061 * Returns:
5062 * DD_OK on success
5063 * DDERR_INVALIDPARAMS if gamma_ramp is NULL
5065 **********************************************************/
5066 static HRESULT WINAPI ddraw_gamma_control_GetGammaRamp(IDirectDrawGammaControl *iface,
5067 DWORD flags, DDGAMMARAMP *gamma_ramp)
5069 struct ddraw_surface *surface = impl_from_IDirectDrawGammaControl(iface);
5071 TRACE("iface %p, flags %#x, gamma_ramp %p.\n", iface, flags, gamma_ramp);
5073 if (!gamma_ramp)
5075 WARN("Invalid gamma_ramp passed.\n");
5076 return DDERR_INVALIDPARAMS;
5079 wined3d_mutex_lock();
5080 if (surface->surface_desc.ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE)
5082 /* Note: DDGAMMARAMP is compatible with struct wined3d_gamma_ramp. */
5083 wined3d_device_get_gamma_ramp(surface->ddraw->wined3d_device, 0, (struct wined3d_gamma_ramp *)gamma_ramp);
5085 else
5087 ERR("Not implemented for non-primary surfaces.\n");
5089 wined3d_mutex_unlock();
5091 return DD_OK;
5094 /**********************************************************
5095 * IDirectDrawGammaControl::SetGammaRamp
5097 * Sets the red, green and blue gamma ramps for
5099 * Params:
5100 * flags: Can be DDSGR_CALIBRATE to request calibration
5101 * gamma_ramp: Structure containing the new gamma ramp
5103 * Returns:
5104 * DD_OK on success
5105 * DDERR_INVALIDPARAMS if gamma_ramp is NULL
5107 **********************************************************/
5108 static HRESULT WINAPI ddraw_gamma_control_SetGammaRamp(IDirectDrawGammaControl *iface,
5109 DWORD flags, DDGAMMARAMP *gamma_ramp)
5111 struct ddraw_surface *surface = impl_from_IDirectDrawGammaControl(iface);
5113 TRACE("iface %p, flags %#x, gamma_ramp %p.\n", iface, flags, gamma_ramp);
5115 if (!gamma_ramp)
5117 WARN("Invalid gamma_ramp passed.\n");
5118 return DDERR_INVALIDPARAMS;
5121 wined3d_mutex_lock();
5122 if (surface->surface_desc.ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE)
5124 /* Note: DDGAMMARAMP is compatible with struct wined3d_gamma_ramp. */
5125 wined3d_device_set_gamma_ramp(surface->ddraw->wined3d_device,
5126 0, flags, (struct wined3d_gamma_ramp *)gamma_ramp);
5128 else
5130 ERR("Not implemented for non-primary surfaces.\n");
5132 wined3d_mutex_unlock();
5134 return DD_OK;
5137 /*****************************************************************************
5138 * IDirect3DTexture2::PaletteChanged
5140 * Informs the texture about a palette change
5142 * Params:
5143 * start: Start index of the change
5144 * count: The number of changed entries
5146 * Returns
5147 * D3D_OK, because it's a stub
5149 *****************************************************************************/
5150 static HRESULT WINAPI d3d_texture2_PaletteChanged(IDirect3DTexture2 *iface, DWORD start, DWORD count)
5152 FIXME("iface %p, start %u, count %u stub!\n", iface, start, count);
5154 return D3D_OK;
5157 static HRESULT WINAPI d3d_texture1_PaletteChanged(IDirect3DTexture *iface, DWORD start, DWORD count)
5159 struct ddraw_surface *surface = impl_from_IDirect3DTexture(iface);
5161 TRACE("iface %p, start %u, count %u.\n", iface, start, count);
5163 return d3d_texture2_PaletteChanged(&surface->IDirect3DTexture2_iface, start, count);
5166 /*****************************************************************************
5167 * IDirect3DTexture::Unload
5169 * DX5 SDK: "The IDirect3DTexture2::Unload method is not implemented
5172 * Returns:
5173 * DDERR_UNSUPPORTED
5175 *****************************************************************************/
5176 static HRESULT WINAPI d3d_texture1_Unload(IDirect3DTexture *iface)
5178 WARN("iface %p. Not implemented.\n", iface);
5180 return DDERR_UNSUPPORTED;
5183 /*****************************************************************************
5184 * IDirect3DTexture2::GetHandle
5186 * Returns handle for the texture.
5188 * Params:
5189 * device: Device this handle is assigned to
5190 * handle: Address to store the handle at.
5192 * Returns:
5193 * D3D_OK
5195 *****************************************************************************/
5196 static HRESULT WINAPI d3d_texture2_GetHandle(IDirect3DTexture2 *iface,
5197 IDirect3DDevice2 *device, D3DTEXTUREHANDLE *handle)
5199 struct ddraw_surface *surface = impl_from_IDirect3DTexture2(iface);
5200 struct d3d_device *device_impl = unsafe_impl_from_IDirect3DDevice2(device);
5202 TRACE("iface %p, device %p, handle %p.\n", iface, device, handle);
5204 wined3d_mutex_lock();
5206 if (!surface->Handle)
5208 DWORD h = ddraw_allocate_handle(&device_impl->handle_table, surface, DDRAW_HANDLE_SURFACE);
5209 if (h == DDRAW_INVALID_HANDLE)
5211 ERR("Failed to allocate a texture handle.\n");
5212 wined3d_mutex_unlock();
5213 return DDERR_OUTOFMEMORY;
5216 surface->Handle = h + 1;
5219 TRACE("Returning handle %08x.\n", surface->Handle);
5220 *handle = surface->Handle;
5222 wined3d_mutex_unlock();
5224 return D3D_OK;
5227 static HRESULT WINAPI d3d_texture1_GetHandle(IDirect3DTexture *iface,
5228 IDirect3DDevice *device, D3DTEXTUREHANDLE *handle)
5230 struct ddraw_surface *surface = impl_from_IDirect3DTexture(iface);
5231 struct d3d_device *device_impl = unsafe_impl_from_IDirect3DDevice(device);
5233 TRACE("iface %p, device %p, handle %p.\n", iface, device, handle);
5235 return d3d_texture2_GetHandle(&surface->IDirect3DTexture2_iface,
5236 device_impl ? &device_impl->IDirect3DDevice2_iface : NULL, handle);
5239 /*****************************************************************************
5240 * get_sub_mimaplevel
5242 * Helper function that returns the next mipmap level
5244 * tex_ptr: Surface of which to return the next level
5246 *****************************************************************************/
5247 static struct ddraw_surface *get_sub_mimaplevel(struct ddraw_surface *surface)
5249 /* Now go down the mipmap chain to the next surface */
5250 static DDSCAPS2 mipmap_caps = { DDSCAPS_MIPMAP | DDSCAPS_TEXTURE, 0, 0, {0} };
5251 IDirectDrawSurface7 *next_level;
5252 HRESULT hr;
5254 hr = ddraw_surface7_GetAttachedSurface(&surface->IDirectDrawSurface7_iface, &mipmap_caps, &next_level);
5255 if (FAILED(hr)) return NULL;
5257 ddraw_surface7_Release(next_level);
5259 return impl_from_IDirectDrawSurface7(next_level);
5262 /*****************************************************************************
5263 * IDirect3DTexture2::Load
5265 * Loads a texture created with the DDSCAPS_ALLOCONLOAD
5267 * This function isn't relayed to WineD3D because the whole interface is
5268 * implemented in DDraw only. For speed improvements an implementation which
5269 * takes OpenGL more into account could be placed into WineD3D.
5271 * Params:
5272 * src_texture: Address of the texture to load
5274 * Returns:
5275 * D3D_OK on success
5276 * D3DERR_TEXTURE_LOAD_FAILED.
5278 *****************************************************************************/
5279 static HRESULT WINAPI d3d_texture2_Load(IDirect3DTexture2 *iface, IDirect3DTexture2 *src_texture)
5281 struct ddraw_surface *dst_surface = impl_from_IDirect3DTexture2(iface);
5282 struct ddraw_surface *src_surface = unsafe_impl_from_IDirect3DTexture2(src_texture);
5283 struct wined3d_resource *dst_resource, *src_resource;
5284 HRESULT hr;
5286 TRACE("iface %p, src_texture %p.\n", iface, src_texture);
5288 if (src_surface == dst_surface)
5290 TRACE("copying surface %p to surface %p, why?\n", src_surface, dst_surface);
5291 return D3D_OK;
5294 wined3d_mutex_lock();
5296 dst_resource = wined3d_texture_get_resource(dst_surface->wined3d_texture);
5297 src_resource = wined3d_texture_get_resource(src_surface->wined3d_texture);
5299 if (((src_surface->surface_desc.ddsCaps.dwCaps & DDSCAPS_MIPMAP)
5300 != (dst_surface->surface_desc.ddsCaps.dwCaps & DDSCAPS_MIPMAP))
5301 || (src_surface->surface_desc.u2.dwMipMapCount != dst_surface->surface_desc.u2.dwMipMapCount))
5303 ERR("Trying to load surfaces with different mip-map counts.\n");
5306 for (;;)
5308 struct ddraw_palette *dst_pal, *src_pal;
5309 DDSURFACEDESC *src_desc, *dst_desc;
5311 TRACE("Copying surface %p to surface %p.\n", src_surface, dst_surface);
5313 /* Suppress the ALLOCONLOAD flag */
5314 dst_surface->surface_desc.ddsCaps.dwCaps &= ~DDSCAPS_ALLOCONLOAD;
5316 /* Get the palettes */
5317 dst_pal = dst_surface->palette;
5318 src_pal = src_surface->palette;
5320 if (src_pal)
5322 PALETTEENTRY palent[256];
5324 if (!dst_pal)
5326 wined3d_mutex_unlock();
5327 return DDERR_NOPALETTEATTACHED;
5329 IDirectDrawPalette_GetEntries(&src_pal->IDirectDrawPalette_iface, 0, 0, 256, palent);
5330 IDirectDrawPalette_SetEntries(&dst_pal->IDirectDrawPalette_iface, 0, 0, 256, palent);
5333 /* Copy one surface on the other */
5334 dst_desc = (DDSURFACEDESC *)&(dst_surface->surface_desc);
5335 src_desc = (DDSURFACEDESC *)&(src_surface->surface_desc);
5337 if ((src_desc->dwWidth != dst_desc->dwWidth) || (src_desc->dwHeight != dst_desc->dwHeight))
5339 /* Should also check for same pixel format, u1.lPitch, ... */
5340 ERR("Error in surface sizes.\n");
5341 wined3d_mutex_unlock();
5342 return D3DERR_TEXTURE_LOAD_FAILED;
5344 else
5346 struct wined3d_map_desc src_map_desc, dst_map_desc;
5348 /* Copy the src blit color key if the source has one, don't erase
5349 * the destination's ckey if the source has none */
5350 if (src_desc->dwFlags & DDSD_CKSRCBLT)
5352 IDirectDrawSurface7_SetColorKey(&dst_surface->IDirectDrawSurface7_iface,
5353 DDCKEY_SRCBLT, &src_desc->ddckCKSrcBlt);
5356 if (FAILED(hr = wined3d_resource_map(src_resource,
5357 src_surface->sub_resource_idx, &src_map_desc, NULL, WINED3D_MAP_READ)))
5359 ERR("Failed to lock source surface, hr %#x.\n", hr);
5360 wined3d_mutex_unlock();
5361 return D3DERR_TEXTURE_LOAD_FAILED;
5364 if (FAILED(hr = wined3d_resource_map(dst_resource,
5365 dst_surface->sub_resource_idx, &dst_map_desc, NULL, WINED3D_MAP_WRITE)))
5367 ERR("Failed to lock destination surface, hr %#x.\n", hr);
5368 wined3d_resource_unmap(src_resource, src_surface->sub_resource_idx);
5369 wined3d_mutex_unlock();
5370 return D3DERR_TEXTURE_LOAD_FAILED;
5373 if (dst_surface->surface_desc.u4.ddpfPixelFormat.dwFlags & DDPF_FOURCC)
5374 memcpy(dst_map_desc.data, src_map_desc.data, src_surface->surface_desc.u1.dwLinearSize);
5375 else
5376 memcpy(dst_map_desc.data, src_map_desc.data, src_map_desc.row_pitch * src_desc->dwHeight);
5378 wined3d_resource_unmap(dst_resource, dst_surface->sub_resource_idx);
5379 wined3d_resource_unmap(src_resource, src_surface->sub_resource_idx);
5382 if (src_surface->surface_desc.ddsCaps.dwCaps & DDSCAPS_MIPMAP)
5383 src_surface = get_sub_mimaplevel(src_surface);
5384 else
5385 src_surface = NULL;
5387 if (dst_surface->surface_desc.ddsCaps.dwCaps & DDSCAPS_MIPMAP)
5388 dst_surface = get_sub_mimaplevel(dst_surface);
5389 else
5390 dst_surface = NULL;
5392 if (!src_surface || !dst_surface)
5394 if (src_surface != dst_surface)
5395 ERR("Loading surface with different mipmap structure.\n");
5396 break;
5400 wined3d_mutex_unlock();
5402 return hr;
5405 static HRESULT WINAPI d3d_texture1_Load(IDirect3DTexture *iface, IDirect3DTexture *src_texture)
5407 struct ddraw_surface *dst_surface = impl_from_IDirect3DTexture(iface);
5408 struct ddraw_surface *src_surface = unsafe_impl_from_IDirect3DTexture(src_texture);
5410 TRACE("iface %p, src_texture %p.\n", iface, src_texture);
5412 return d3d_texture2_Load(&dst_surface->IDirect3DTexture2_iface,
5413 src_surface ? &src_surface->IDirect3DTexture2_iface : NULL);
5416 /*****************************************************************************
5417 * The VTable
5418 *****************************************************************************/
5420 /* Some windowed mode wrappers expect this vtbl to be writable. */
5421 static struct IDirectDrawSurface7Vtbl ddraw_surface7_vtbl =
5423 /* IUnknown */
5424 ddraw_surface7_QueryInterface,
5425 ddraw_surface7_AddRef,
5426 ddraw_surface7_Release,
5427 /* IDirectDrawSurface */
5428 ddraw_surface7_AddAttachedSurface,
5429 ddraw_surface7_AddOverlayDirtyRect,
5430 ddraw_surface7_Blt,
5431 ddraw_surface7_BltBatch,
5432 ddraw_surface7_BltFast,
5433 ddraw_surface7_DeleteAttachedSurface,
5434 ddraw_surface7_EnumAttachedSurfaces,
5435 ddraw_surface7_EnumOverlayZOrders,
5436 ddraw_surface7_Flip,
5437 ddraw_surface7_GetAttachedSurface,
5438 ddraw_surface7_GetBltStatus,
5439 ddraw_surface7_GetCaps,
5440 ddraw_surface7_GetClipper,
5441 ddraw_surface7_GetColorKey,
5442 ddraw_surface7_GetDC,
5443 ddraw_surface7_GetFlipStatus,
5444 ddraw_surface7_GetOverlayPosition,
5445 ddraw_surface7_GetPalette,
5446 ddraw_surface7_GetPixelFormat,
5447 ddraw_surface7_GetSurfaceDesc,
5448 ddraw_surface7_Initialize,
5449 ddraw_surface7_IsLost,
5450 ddraw_surface7_Lock,
5451 ddraw_surface7_ReleaseDC,
5452 ddraw_surface7_Restore,
5453 ddraw_surface7_SetClipper,
5454 ddraw_surface7_SetColorKey,
5455 ddraw_surface7_SetOverlayPosition,
5456 ddraw_surface7_SetPalette,
5457 ddraw_surface7_Unlock,
5458 ddraw_surface7_UpdateOverlay,
5459 ddraw_surface7_UpdateOverlayDisplay,
5460 ddraw_surface7_UpdateOverlayZOrder,
5461 /* IDirectDrawSurface2 */
5462 ddraw_surface7_GetDDInterface,
5463 ddraw_surface7_PageLock,
5464 ddraw_surface7_PageUnlock,
5465 /* IDirectDrawSurface3 */
5466 ddraw_surface7_SetSurfaceDesc,
5467 /* IDirectDrawSurface4 */
5468 ddraw_surface7_SetPrivateData,
5469 ddraw_surface7_GetPrivateData,
5470 ddraw_surface7_FreePrivateData,
5471 ddraw_surface7_GetUniquenessValue,
5472 ddraw_surface7_ChangeUniquenessValue,
5473 /* IDirectDrawSurface7 */
5474 ddraw_surface7_SetPriority,
5475 ddraw_surface7_GetPriority,
5476 ddraw_surface7_SetLOD,
5477 ddraw_surface7_GetLOD,
5480 /* Some windowed mode wrappers expect this vtbl to be writable. */
5481 static struct IDirectDrawSurface4Vtbl ddraw_surface4_vtbl =
5483 /* IUnknown */
5484 ddraw_surface4_QueryInterface,
5485 ddraw_surface4_AddRef,
5486 ddraw_surface4_Release,
5487 /* IDirectDrawSurface */
5488 ddraw_surface4_AddAttachedSurface,
5489 ddraw_surface4_AddOverlayDirtyRect,
5490 ddraw_surface4_Blt,
5491 ddraw_surface4_BltBatch,
5492 ddraw_surface4_BltFast,
5493 ddraw_surface4_DeleteAttachedSurface,
5494 ddraw_surface4_EnumAttachedSurfaces,
5495 ddraw_surface4_EnumOverlayZOrders,
5496 ddraw_surface4_Flip,
5497 ddraw_surface4_GetAttachedSurface,
5498 ddraw_surface4_GetBltStatus,
5499 ddraw_surface4_GetCaps,
5500 ddraw_surface4_GetClipper,
5501 ddraw_surface4_GetColorKey,
5502 ddraw_surface4_GetDC,
5503 ddraw_surface4_GetFlipStatus,
5504 ddraw_surface4_GetOverlayPosition,
5505 ddraw_surface4_GetPalette,
5506 ddraw_surface4_GetPixelFormat,
5507 ddraw_surface4_GetSurfaceDesc,
5508 ddraw_surface4_Initialize,
5509 ddraw_surface4_IsLost,
5510 ddraw_surface4_Lock,
5511 ddraw_surface4_ReleaseDC,
5512 ddraw_surface4_Restore,
5513 ddraw_surface4_SetClipper,
5514 ddraw_surface4_SetColorKey,
5515 ddraw_surface4_SetOverlayPosition,
5516 ddraw_surface4_SetPalette,
5517 ddraw_surface4_Unlock,
5518 ddraw_surface4_UpdateOverlay,
5519 ddraw_surface4_UpdateOverlayDisplay,
5520 ddraw_surface4_UpdateOverlayZOrder,
5521 /* IDirectDrawSurface2 */
5522 ddraw_surface4_GetDDInterface,
5523 ddraw_surface4_PageLock,
5524 ddraw_surface4_PageUnlock,
5525 /* IDirectDrawSurface3 */
5526 ddraw_surface4_SetSurfaceDesc,
5527 /* IDirectDrawSurface4 */
5528 ddraw_surface4_SetPrivateData,
5529 ddraw_surface4_GetPrivateData,
5530 ddraw_surface4_FreePrivateData,
5531 ddraw_surface4_GetUniquenessValue,
5532 ddraw_surface4_ChangeUniquenessValue,
5535 /* Some windowed mode wrappers expect this vtbl to be writable. */
5536 static struct IDirectDrawSurface3Vtbl ddraw_surface3_vtbl =
5538 /* IUnknown */
5539 ddraw_surface3_QueryInterface,
5540 ddraw_surface3_AddRef,
5541 ddraw_surface3_Release,
5542 /* IDirectDrawSurface */
5543 ddraw_surface3_AddAttachedSurface,
5544 ddraw_surface3_AddOverlayDirtyRect,
5545 ddraw_surface3_Blt,
5546 ddraw_surface3_BltBatch,
5547 ddraw_surface3_BltFast,
5548 ddraw_surface3_DeleteAttachedSurface,
5549 ddraw_surface3_EnumAttachedSurfaces,
5550 ddraw_surface3_EnumOverlayZOrders,
5551 ddraw_surface3_Flip,
5552 ddraw_surface3_GetAttachedSurface,
5553 ddraw_surface3_GetBltStatus,
5554 ddraw_surface3_GetCaps,
5555 ddraw_surface3_GetClipper,
5556 ddraw_surface3_GetColorKey,
5557 ddraw_surface3_GetDC,
5558 ddraw_surface3_GetFlipStatus,
5559 ddraw_surface3_GetOverlayPosition,
5560 ddraw_surface3_GetPalette,
5561 ddraw_surface3_GetPixelFormat,
5562 ddraw_surface3_GetSurfaceDesc,
5563 ddraw_surface3_Initialize,
5564 ddraw_surface3_IsLost,
5565 ddraw_surface3_Lock,
5566 ddraw_surface3_ReleaseDC,
5567 ddraw_surface3_Restore,
5568 ddraw_surface3_SetClipper,
5569 ddraw_surface3_SetColorKey,
5570 ddraw_surface3_SetOverlayPosition,
5571 ddraw_surface3_SetPalette,
5572 ddraw_surface3_Unlock,
5573 ddraw_surface3_UpdateOverlay,
5574 ddraw_surface3_UpdateOverlayDisplay,
5575 ddraw_surface3_UpdateOverlayZOrder,
5576 /* IDirectDrawSurface2 */
5577 ddraw_surface3_GetDDInterface,
5578 ddraw_surface3_PageLock,
5579 ddraw_surface3_PageUnlock,
5580 /* IDirectDrawSurface3 */
5581 ddraw_surface3_SetSurfaceDesc,
5584 /* Some windowed mode wrappers expect this vtbl to be writable. */
5585 static struct IDirectDrawSurface2Vtbl ddraw_surface2_vtbl =
5587 /* IUnknown */
5588 ddraw_surface2_QueryInterface,
5589 ddraw_surface2_AddRef,
5590 ddraw_surface2_Release,
5591 /* IDirectDrawSurface */
5592 ddraw_surface2_AddAttachedSurface,
5593 ddraw_surface2_AddOverlayDirtyRect,
5594 ddraw_surface2_Blt,
5595 ddraw_surface2_BltBatch,
5596 ddraw_surface2_BltFast,
5597 ddraw_surface2_DeleteAttachedSurface,
5598 ddraw_surface2_EnumAttachedSurfaces,
5599 ddraw_surface2_EnumOverlayZOrders,
5600 ddraw_surface2_Flip,
5601 ddraw_surface2_GetAttachedSurface,
5602 ddraw_surface2_GetBltStatus,
5603 ddraw_surface2_GetCaps,
5604 ddraw_surface2_GetClipper,
5605 ddraw_surface2_GetColorKey,
5606 ddraw_surface2_GetDC,
5607 ddraw_surface2_GetFlipStatus,
5608 ddraw_surface2_GetOverlayPosition,
5609 ddraw_surface2_GetPalette,
5610 ddraw_surface2_GetPixelFormat,
5611 ddraw_surface2_GetSurfaceDesc,
5612 ddraw_surface2_Initialize,
5613 ddraw_surface2_IsLost,
5614 ddraw_surface2_Lock,
5615 ddraw_surface2_ReleaseDC,
5616 ddraw_surface2_Restore,
5617 ddraw_surface2_SetClipper,
5618 ddraw_surface2_SetColorKey,
5619 ddraw_surface2_SetOverlayPosition,
5620 ddraw_surface2_SetPalette,
5621 ddraw_surface2_Unlock,
5622 ddraw_surface2_UpdateOverlay,
5623 ddraw_surface2_UpdateOverlayDisplay,
5624 ddraw_surface2_UpdateOverlayZOrder,
5625 /* IDirectDrawSurface2 */
5626 ddraw_surface2_GetDDInterface,
5627 ddraw_surface2_PageLock,
5628 ddraw_surface2_PageUnlock,
5631 /* Bad Mojo Redux expects this vtbl to be writable. */
5632 static struct IDirectDrawSurfaceVtbl ddraw_surface1_vtbl =
5634 /* IUnknown */
5635 ddraw_surface1_QueryInterface,
5636 ddraw_surface1_AddRef,
5637 ddraw_surface1_Release,
5638 /* IDirectDrawSurface */
5639 ddraw_surface1_AddAttachedSurface,
5640 ddraw_surface1_AddOverlayDirtyRect,
5641 ddraw_surface1_Blt,
5642 ddraw_surface1_BltBatch,
5643 ddraw_surface1_BltFast,
5644 ddraw_surface1_DeleteAttachedSurface,
5645 ddraw_surface1_EnumAttachedSurfaces,
5646 ddraw_surface1_EnumOverlayZOrders,
5647 ddraw_surface1_Flip,
5648 ddraw_surface1_GetAttachedSurface,
5649 ddraw_surface1_GetBltStatus,
5650 ddraw_surface1_GetCaps,
5651 ddraw_surface1_GetClipper,
5652 ddraw_surface1_GetColorKey,
5653 ddraw_surface1_GetDC,
5654 ddraw_surface1_GetFlipStatus,
5655 ddraw_surface1_GetOverlayPosition,
5656 ddraw_surface1_GetPalette,
5657 ddraw_surface1_GetPixelFormat,
5658 ddraw_surface1_GetSurfaceDesc,
5659 ddraw_surface1_Initialize,
5660 ddraw_surface1_IsLost,
5661 ddraw_surface1_Lock,
5662 ddraw_surface1_ReleaseDC,
5663 ddraw_surface1_Restore,
5664 ddraw_surface1_SetClipper,
5665 ddraw_surface1_SetColorKey,
5666 ddraw_surface1_SetOverlayPosition,
5667 ddraw_surface1_SetPalette,
5668 ddraw_surface1_Unlock,
5669 ddraw_surface1_UpdateOverlay,
5670 ddraw_surface1_UpdateOverlayDisplay,
5671 ddraw_surface1_UpdateOverlayZOrder,
5674 static const struct IDirectDrawGammaControlVtbl ddraw_gamma_control_vtbl =
5676 ddraw_gamma_control_QueryInterface,
5677 ddraw_gamma_control_AddRef,
5678 ddraw_gamma_control_Release,
5679 ddraw_gamma_control_GetGammaRamp,
5680 ddraw_gamma_control_SetGammaRamp,
5683 static const struct IDirect3DTexture2Vtbl d3d_texture2_vtbl =
5685 d3d_texture2_QueryInterface,
5686 d3d_texture2_AddRef,
5687 d3d_texture2_Release,
5688 d3d_texture2_GetHandle,
5689 d3d_texture2_PaletteChanged,
5690 d3d_texture2_Load,
5693 static const struct IDirect3DTextureVtbl d3d_texture1_vtbl =
5695 d3d_texture1_QueryInterface,
5696 d3d_texture1_AddRef,
5697 d3d_texture1_Release,
5698 d3d_texture1_Initialize,
5699 d3d_texture1_GetHandle,
5700 d3d_texture1_PaletteChanged,
5701 d3d_texture1_Load,
5702 d3d_texture1_Unload,
5705 /* Some games (e.g. Tomb Raider 3) pass the wrong version of the
5706 * IDirectDrawSurface interface to ddraw methods. */
5707 struct ddraw_surface *unsafe_impl_from_IDirectDrawSurface7(IDirectDrawSurface7 *iface)
5709 if (!iface) return NULL;
5710 if (iface->lpVtbl != &ddraw_surface7_vtbl)
5712 HRESULT hr = IDirectDrawSurface7_QueryInterface(iface, &IID_IDirectDrawSurface7, (void **)&iface);
5713 if (FAILED(hr))
5715 WARN("Object %p doesn't expose interface IDirectDrawSurface7.\n", iface);
5716 return NULL;
5718 IDirectDrawSurface7_Release(iface);
5720 return CONTAINING_RECORD(iface, struct ddraw_surface, IDirectDrawSurface7_iface);
5723 struct ddraw_surface *unsafe_impl_from_IDirectDrawSurface4(IDirectDrawSurface4 *iface)
5725 if (!iface) return NULL;
5726 if (iface->lpVtbl != &ddraw_surface4_vtbl)
5728 HRESULT hr = IDirectDrawSurface4_QueryInterface(iface, &IID_IDirectDrawSurface4, (void **)&iface);
5729 if (FAILED(hr))
5731 WARN("Object %p doesn't expose interface IDirectDrawSurface4.\n", iface);
5732 return NULL;
5734 IDirectDrawSurface4_Release(iface);
5736 return CONTAINING_RECORD(iface, struct ddraw_surface, IDirectDrawSurface4_iface);
5739 static struct ddraw_surface *unsafe_impl_from_IDirectDrawSurface3(IDirectDrawSurface3 *iface)
5741 if (!iface) return NULL;
5742 if (iface->lpVtbl != &ddraw_surface3_vtbl)
5744 HRESULT hr = IDirectDrawSurface3_QueryInterface(iface, &IID_IDirectDrawSurface3, (void **)&iface);
5745 if (FAILED(hr))
5747 WARN("Object %p doesn't expose interface IDirectDrawSurface3.\n", iface);
5748 return NULL;
5750 IDirectDrawSurface3_Release(iface);
5752 return CONTAINING_RECORD(iface, struct ddraw_surface, IDirectDrawSurface3_iface);
5755 static struct ddraw_surface *unsafe_impl_from_IDirectDrawSurface2(IDirectDrawSurface2 *iface)
5757 if (!iface) return NULL;
5758 if (iface->lpVtbl != &ddraw_surface2_vtbl)
5760 HRESULT hr = IDirectDrawSurface2_QueryInterface(iface, &IID_IDirectDrawSurface2, (void **)&iface);
5761 if (FAILED(hr))
5763 WARN("Object %p doesn't expose interface IDirectDrawSurface2.\n", iface);
5764 return NULL;
5766 IDirectDrawSurface2_Release(iface);
5768 return CONTAINING_RECORD(iface, struct ddraw_surface, IDirectDrawSurface2_iface);
5771 struct ddraw_surface *unsafe_impl_from_IDirectDrawSurface(IDirectDrawSurface *iface)
5773 if (!iface) return NULL;
5774 if (iface->lpVtbl != &ddraw_surface1_vtbl)
5776 HRESULT hr = IDirectDrawSurface_QueryInterface(iface, &IID_IDirectDrawSurface, (void **)&iface);
5777 if (FAILED(hr))
5779 WARN("Object %p doesn't expose interface IDirectDrawSurface.\n", iface);
5780 return NULL;
5782 IDirectDrawSurface_Release(iface);
5784 return CONTAINING_RECORD(iface, struct ddraw_surface, IDirectDrawSurface_iface);
5787 struct ddraw_surface *unsafe_impl_from_IDirect3DTexture2(IDirect3DTexture2 *iface)
5789 if (!iface) return NULL;
5790 assert(iface->lpVtbl == &d3d_texture2_vtbl);
5791 return CONTAINING_RECORD(iface, struct ddraw_surface, IDirect3DTexture2_iface);
5794 struct ddraw_surface *unsafe_impl_from_IDirect3DTexture(IDirect3DTexture *iface)
5796 if (!iface) return NULL;
5797 assert(iface->lpVtbl == &d3d_texture1_vtbl);
5798 return CONTAINING_RECORD(iface, struct ddraw_surface, IDirect3DTexture_iface);
5801 static void STDMETHODCALLTYPE ddraw_surface_wined3d_object_destroyed(void *parent)
5803 struct ddraw_surface *surface = parent;
5805 TRACE("surface %p.\n", surface);
5807 /* This shouldn't happen, ddraw_surface_release_iface() should prevent the
5808 * surface from being destroyed in this case. */
5809 if (surface->first_attached != surface)
5810 ERR("Surface is still attached to surface %p.\n", surface->first_attached);
5812 while (surface->next_attached)
5813 if (FAILED(ddraw_surface_delete_attached_surface(surface,
5814 surface->next_attached, surface->next_attached->attached_iface)))
5815 ERR("DeleteAttachedSurface failed.\n");
5817 /* Having a texture handle set implies that the device still exists. */
5818 if (surface->Handle)
5819 ddraw_free_handle(&surface->ddraw->d3ddevice->handle_table, surface->Handle - 1, DDRAW_HANDLE_SURFACE);
5821 /* Reduce the ddraw surface count. */
5822 list_remove(&surface->surface_list_entry);
5824 if (surface->clipper && ddraw_clipper_is_valid(surface->clipper))
5825 IDirectDrawClipper_Release(&surface->clipper->IDirectDrawClipper_iface);
5827 if (surface == surface->ddraw->primary)
5829 surface->ddraw->primary = NULL;
5830 surface->ddraw->gdi_surface = NULL;
5833 wined3d_private_store_cleanup(&surface->private_store);
5835 heap_free(surface);
5838 static const struct wined3d_parent_ops ddraw_surface_wined3d_parent_ops =
5840 ddraw_surface_wined3d_object_destroyed,
5843 static void STDMETHODCALLTYPE ddraw_texture_wined3d_object_destroyed(void *parent)
5845 struct ddraw_texture *texture = parent;
5847 TRACE("texture %p, texture_memory %p.\n", texture, texture->texture_memory);
5849 heap_free(texture->texture_memory);
5850 heap_free(parent);
5853 static const struct wined3d_parent_ops ddraw_texture_wined3d_parent_ops =
5855 ddraw_texture_wined3d_object_destroyed,
5858 static HRESULT CDECL ddraw_reset_enum_callback(struct wined3d_resource *resource)
5860 return DD_OK;
5863 static HRESULT ddraw_surface_reserve_memory(struct wined3d_texture *wined3d_texture)
5865 static const unsigned int extra_size = 0x10000;
5867 struct ddraw_texture *texture = wined3d_texture_get_parent(wined3d_texture);
5868 struct wined3d_resource_desc resource_desc;
5869 struct wined3d_sub_resource_desc desc;
5870 unsigned int pitch, slice_pitch;
5871 unsigned int sub_resource_idx;
5872 HRESULT hr = WINED3D_OK;
5873 unsigned int offset;
5875 wined3d_resource_get_desc(wined3d_texture_get_resource(wined3d_texture), &resource_desc);
5876 if (!(texture->texture_memory = heap_alloc_zero(resource_desc.size + extra_size)))
5878 ERR("Out of memory.\n");
5879 return E_OUTOFMEMORY;
5881 TRACE("texture->texture_memory %p.\n", texture->texture_memory);
5883 offset = 0;
5884 sub_resource_idx = 0;
5885 while (wined3d_texture_get_sub_resource_desc(wined3d_texture, sub_resource_idx, &desc)
5886 == WINED3D_OK)
5888 wined3d_texture_get_pitch(wined3d_texture, sub_resource_idx, &pitch, &slice_pitch);
5890 if (FAILED(hr = wined3d_texture_update_desc(wined3d_texture, sub_resource_idx,
5891 desc.width, desc.height, resource_desc.format,
5892 desc.multisample_type, desc.multisample_quality,
5893 (BYTE *)texture->texture_memory + offset, pitch)))
5895 heap_free(texture->texture_memory);
5896 texture->texture_memory = NULL;
5897 break;
5899 ++sub_resource_idx;
5900 offset += desc.size;
5902 return hr;
5905 HRESULT ddraw_surface_create(struct ddraw *ddraw, const DDSURFACEDESC2 *surface_desc,
5906 struct ddraw_surface **surface, IUnknown *outer_unknown, unsigned int version)
5908 struct wined3d_sub_resource_desc wined3d_mip_desc;
5909 struct ddraw_surface *root, *mip, **attach;
5910 struct wined3d_resource_desc wined3d_desc;
5911 DDPIXELFORMAT wined3d_display_mode_format;
5912 struct wined3d_texture *wined3d_texture;
5913 struct wined3d_display_mode mode;
5914 DDSURFACEDESC2 *desc, *mip_desc;
5915 struct ddraw_texture *texture;
5916 BOOL sysmem_fallback = FALSE;
5917 unsigned int layers = 1;
5918 unsigned int pitch = 0;
5919 BOOL reserve_memory;
5920 UINT levels, i, j;
5921 HRESULT hr;
5923 TRACE("ddraw %p, surface_desc %p, surface %p, outer_unknown %p, version %u.\n",
5924 ddraw, surface_desc, surface, outer_unknown, version);
5925 if (TRACE_ON(ddraw))
5927 TRACE("Requesting surface desc:\n");
5928 DDRAW_dump_surface_desc(surface_desc);
5931 if (outer_unknown)
5932 return CLASS_E_NOAGGREGATION;
5934 if (!surface)
5935 return E_POINTER;
5937 if (!(texture = heap_alloc(sizeof(*texture))))
5938 return E_OUTOFMEMORY;
5940 texture->texture_memory = NULL;
5941 texture->version = version;
5942 texture->surface_desc = *surface_desc;
5943 desc = &texture->surface_desc;
5945 /* Ensure DDSD_CAPS is always set. */
5946 desc->dwFlags |= DDSD_CAPS;
5948 if (desc->ddsCaps.dwCaps & DDSCAPS_FLIP)
5950 if (!(desc->dwFlags & DDSD_BACKBUFFERCOUNT) || !desc->u5.dwBackBufferCount)
5952 WARN("Tried to create a flippable surface without any back buffers.\n");
5953 heap_free(texture);
5954 return DDERR_INVALIDCAPS;
5957 if (!(desc->ddsCaps.dwCaps & DDSCAPS_COMPLEX))
5959 WARN("Tried to create a flippable surface without DDSCAPS_COMPLEX.\n");
5960 heap_free(texture);
5961 return DDERR_INVALIDCAPS;
5964 if (desc->ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP)
5966 WARN("Tried to create a flippable cubemap.\n");
5967 heap_free(texture);
5968 return DDERR_INVALIDPARAMS;
5971 if (desc->ddsCaps.dwCaps & DDSCAPS_TEXTURE)
5973 FIXME("Flippable textures not implemented.\n");
5974 heap_free(texture);
5975 return DDERR_INVALIDCAPS;
5978 else
5980 if (desc->dwFlags & DDSD_BACKBUFFERCOUNT)
5982 WARN("Tried to specify a back buffer count for a non-flippable surface.\n");
5983 hr = desc->ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP ? DDERR_INVALIDPARAMS : DDERR_INVALIDCAPS;
5984 heap_free(texture);
5985 return hr;
5989 if (desc->ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE)
5991 if (desc->ddsCaps.dwCaps & DDSCAPS_TEXTURE)
5993 WARN("Tried to create a primary surface with DDSCAPS_TEXTURE.\n");
5994 heap_free(texture);
5995 return DDERR_INVALIDCAPS;
5998 if ((desc->ddsCaps.dwCaps & DDSCAPS_COMPLEX) && !(desc->ddsCaps.dwCaps & DDSCAPS_FLIP))
6000 WARN("Tried to create a flippable primary surface without both DDSCAPS_FLIP and DDSCAPS_COMPLEX.\n");
6001 heap_free(texture);
6002 return DDERR_INVALIDCAPS;
6005 if ((desc->ddsCaps.dwCaps & DDSCAPS_FLIP) && !(ddraw->cooperative_level & DDSCL_EXCLUSIVE))
6007 WARN("Tried to create a flippable primary surface without DDSCL_EXCLUSIVE.\n");
6008 heap_free(texture);
6009 return DDERR_NOEXCLUSIVEMODE;
6013 /* This is a special case in ddrawex, but not allowed in ddraw. */
6014 if ((desc->ddsCaps.dwCaps & (DDSCAPS_VIDEOMEMORY | DDSCAPS_SYSTEMMEMORY))
6015 == (DDSCAPS_VIDEOMEMORY | DDSCAPS_SYSTEMMEMORY))
6017 WARN("Tried to create a surface in both system and video memory.\n");
6018 heap_free(texture);
6019 return DDERR_INVALIDCAPS;
6022 if ((desc->ddsCaps.dwCaps & (DDSCAPS_ALLOCONLOAD | DDSCAPS_MIPMAP))
6023 && !(desc->ddsCaps.dwCaps & DDSCAPS_TEXTURE))
6025 WARN("Caps %#x require DDSCAPS_TEXTURE.\n", desc->ddsCaps.dwCaps);
6026 heap_free(texture);
6027 return DDERR_INVALIDCAPS;
6030 if ((desc->ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP_ALLFACES)
6031 && !(desc->ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP))
6033 WARN("Cube map faces requested without cube map flag.\n");
6034 heap_free(texture);
6035 return DDERR_INVALIDCAPS;
6038 if ((desc->ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP)
6039 && !(desc->ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP_ALLFACES))
6041 WARN("Cube map without faces requested.\n");
6042 heap_free(texture);
6043 return DDERR_INVALIDPARAMS;
6046 if ((desc->ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP)
6047 && (desc->ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP_ALLFACES) != DDSCAPS2_CUBEMAP_ALLFACES)
6048 FIXME("Partial cube maps not implemented.\n");
6050 if (desc->ddsCaps.dwCaps2 & (DDSCAPS2_TEXTUREMANAGE | DDSCAPS2_D3DTEXTUREMANAGE))
6052 if (!(desc->ddsCaps.dwCaps & DDSCAPS_TEXTURE))
6054 WARN("DDSCAPS2_TEXTUREMANAGE used without DDSCAPS_TEXTURE, returning DDERR_INVALIDCAPS.\n");
6055 heap_free(texture);
6056 return DDERR_INVALIDCAPS;
6058 if (desc->ddsCaps.dwCaps & (DDSCAPS_VIDEOMEMORY | DDSCAPS_SYSTEMMEMORY))
6060 WARN("DDSCAPS2_TEXTUREMANAGE used with DDSCAPS_VIDEOMEMORY "
6061 "or DDSCAPS_SYSTEMMEMORY, returning DDERR_INVALIDCAPS.\n");
6062 heap_free(texture);
6063 return DDERR_INVALIDCAPS;
6067 if (desc->ddsCaps.dwCaps & DDSCAPS_WRITEONLY
6068 && !(desc->ddsCaps.dwCaps2 & (DDSCAPS2_TEXTUREMANAGE | DDSCAPS2_D3DTEXTUREMANAGE)))
6070 WARN("DDSCAPS_WRITEONLY used without DDSCAPS2_TEXTUREMANAGE, returning DDERR_INVALIDCAPS.\n");
6071 heap_free(texture);
6072 return DDERR_INVALIDCAPS;
6075 if (FAILED(hr = wined3d_output_get_display_mode(ddraw->wined3d_output, &mode, NULL)))
6077 ERR("Failed to get display mode, hr %#x.\n", hr);
6078 heap_free(texture);
6079 return hr_ddraw_from_wined3d(hr);
6082 wined3d_display_mode_format.dwSize = sizeof(wined3d_display_mode_format);
6083 ddrawformat_from_wined3dformat(&wined3d_display_mode_format, mode.format_id);
6085 /* No pixelformat given? Use the current screen format. */
6086 if (!(desc->dwFlags & DDSD_PIXELFORMAT))
6088 desc->dwFlags |= DDSD_PIXELFORMAT;
6089 desc->u4.ddpfPixelFormat = wined3d_display_mode_format;
6092 wined3d_desc.resource_type = WINED3D_RTYPE_TEXTURE_2D;
6093 wined3d_desc.format = wined3dformat_from_ddrawformat(&desc->u4.ddpfPixelFormat);
6094 if (wined3d_desc.format == WINED3DFMT_UNKNOWN)
6096 WARN("Unsupported / unknown pixelformat.\n");
6097 heap_free(texture);
6098 return DDERR_INVALIDPIXELFORMAT;
6101 /* No width or no height? Use the screen size. */
6102 if (!(desc->dwFlags & DDSD_WIDTH) || !(desc->dwFlags & DDSD_HEIGHT))
6104 if (!(desc->ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE))
6106 WARN("No width / height specified.\n");
6107 heap_free(texture);
6108 return DDERR_INVALIDPARAMS;
6111 desc->dwFlags |= DDSD_WIDTH | DDSD_HEIGHT;
6112 desc->dwWidth = mode.width;
6113 desc->dwHeight = mode.height;
6116 if (!desc->dwWidth || !desc->dwHeight)
6118 heap_free(texture);
6119 return DDERR_INVALIDPARAMS;
6122 if (desc->ddsCaps.dwCaps & DDSCAPS_FLIP)
6123 desc->ddsCaps.dwCaps |= DDSCAPS_FRONTBUFFER;
6125 if (desc->ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE)
6127 /* The first surface is a front buffer, the back buffers are created
6128 * afterwards. */
6129 desc->ddsCaps.dwCaps |= DDSCAPS_VISIBLE;
6130 if (ddraw->cooperative_level & DDSCL_EXCLUSIVE)
6132 struct wined3d_swapchain_desc swapchain_desc;
6134 wined3d_swapchain_get_desc(ddraw->wined3d_swapchain, &swapchain_desc);
6135 swapchain_desc.backbuffer_width = mode.width;
6136 swapchain_desc.backbuffer_height = mode.height;
6137 swapchain_desc.backbuffer_format = mode.format_id;
6139 if (ddraw->d3ddevice)
6141 if (ddraw->d3ddevice->recording)
6142 wined3d_stateblock_decref(ddraw->d3ddevice->recording);
6143 ddraw->d3ddevice->recording = NULL;
6144 ddraw->d3ddevice->update_state = ddraw->d3ddevice->state;
6146 wined3d_stateblock_reset(ddraw->state);
6148 if (FAILED(hr = wined3d_device_reset(ddraw->wined3d_device,
6149 &swapchain_desc, NULL, ddraw_reset_enum_callback, TRUE)))
6151 ERR("Failed to reset device.\n");
6152 heap_free(texture);
6153 return hr_ddraw_from_wined3d(hr);
6156 wined3d_stateblock_set_render_state(ddraw->state, WINED3D_RS_ZENABLE,
6157 !!swapchain_desc.enable_auto_depth_stencil);
6161 wined3d_desc.multisample_type = WINED3D_MULTISAMPLE_NONE;
6162 wined3d_desc.multisample_quality = 0;
6163 wined3d_desc.usage = 0;
6164 wined3d_desc.bind_flags = 0;
6165 wined3d_desc.access = WINED3D_RESOURCE_ACCESS_GPU | WINED3D_RESOURCE_ACCESS_MAP_R | WINED3D_RESOURCE_ACCESS_MAP_W;
6166 wined3d_desc.width = desc->dwWidth;
6167 wined3d_desc.height = desc->dwHeight;
6168 wined3d_desc.depth = 1;
6169 wined3d_desc.size = 0;
6171 if ((desc->ddsCaps.dwCaps & DDSCAPS_3DDEVICE) && (ddraw->flags & DDRAW_NO3D))
6173 WARN("The application requests a 3D capable surface, but the ddraw object was created without 3D support.\n");
6174 /* Do not fail surface creation, only fail 3D device creation. */
6177 /* Mipmap count fixes */
6178 if (desc->ddsCaps.dwCaps & DDSCAPS_MIPMAP)
6180 if (desc->ddsCaps.dwCaps & DDSCAPS_COMPLEX)
6182 if (desc->dwFlags & DDSD_MIPMAPCOUNT)
6184 /* Mipmap count is given, should not be 0. */
6185 if (!desc->u2.dwMipMapCount)
6187 heap_free(texture);
6188 return DDERR_INVALIDPARAMS;
6191 else
6193 /* Undocumented feature: Create sublevels until either the
6194 * width or the height is 1. */
6195 if (version == 7)
6196 desc->u2.dwMipMapCount = wined3d_log2i(max(desc->dwWidth, desc->dwHeight)) + 1;
6197 else
6198 desc->u2.dwMipMapCount = wined3d_log2i(min(desc->dwWidth, desc->dwHeight)) + 1;
6201 else
6203 desc->u2.dwMipMapCount = 1;
6206 desc->dwFlags |= DDSD_MIPMAPCOUNT;
6207 levels = desc->u2.dwMipMapCount;
6209 else
6211 levels = 1;
6214 if (!(desc->ddsCaps.dwCaps & (DDSCAPS_VIDEOMEMORY | DDSCAPS_SYSTEMMEMORY)))
6216 if (!(desc->ddsCaps.dwCaps2 & (DDSCAPS2_TEXTUREMANAGE | DDSCAPS2_D3DTEXTUREMANAGE)))
6218 unsigned int bind_flags = 0;
6219 DWORD usage = 0;
6221 if (desc->ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP)
6223 usage |= WINED3DUSAGE_LEGACY_CUBEMAP;
6224 bind_flags |= WINED3D_BIND_SHADER_RESOURCE;
6226 else if (desc->ddsCaps.dwCaps & DDSCAPS_TEXTURE)
6228 bind_flags |= WINED3D_BIND_SHADER_RESOURCE;
6231 if (desc->ddsCaps.dwCaps & DDSCAPS_ZBUFFER)
6232 bind_flags |= WINED3D_BIND_DEPTH_STENCIL;
6233 else if (desc->ddsCaps.dwCaps & DDSCAPS_3DDEVICE)
6234 bind_flags |= WINED3D_BIND_RENDER_TARGET;
6236 if (!(ddraw->flags & DDRAW_NO3D) && SUCCEEDED(hr = wined3d_check_device_format(ddraw->wined3d,
6237 ddraw->wined3d_adapter, WINED3D_DEVICE_TYPE_HAL, mode.format_id,
6238 usage, bind_flags, WINED3D_RTYPE_TEXTURE_2D, wined3d_desc.format)))
6240 desc->ddsCaps.dwCaps |= DDSCAPS_VIDEOMEMORY;
6242 else
6244 desc->ddsCaps.dwCaps |= DDSCAPS_SYSTEMMEMORY;
6245 sysmem_fallback = TRUE;
6248 else if (!(desc->ddsCaps.dwCaps & DDSCAPS_TEXTURE))
6250 /* Tests show surfaces without memory flags get these flags added
6251 * right after creation. */
6252 desc->ddsCaps.dwCaps |= DDSCAPS_LOCALVIDMEM | DDSCAPS_VIDEOMEMORY;
6256 if ((desc->ddsCaps.dwCaps & (DDSCAPS_OVERLAY | DDSCAPS_SYSTEMMEMORY))
6257 == (DDSCAPS_OVERLAY | DDSCAPS_SYSTEMMEMORY))
6259 WARN("System memory overlays are not allowed.\n");
6260 heap_free(texture);
6261 return DDERR_NOOVERLAYHW;
6264 if (desc->ddsCaps.dwCaps & DDSCAPS_SYSTEMMEMORY)
6266 wined3d_desc.access = WINED3D_RESOURCE_ACCESS_CPU
6267 | WINED3D_RESOURCE_ACCESS_MAP_R | WINED3D_RESOURCE_ACCESS_MAP_W;
6269 else
6271 if (!(ddraw->flags & DDRAW_NO3D))
6273 if (desc->ddsCaps.dwCaps & DDSCAPS_TEXTURE)
6274 wined3d_desc.bind_flags |= WINED3D_BIND_SHADER_RESOURCE;
6275 if (desc->ddsCaps.dwCaps & DDSCAPS_ZBUFFER)
6276 wined3d_desc.bind_flags |= WINED3D_BIND_DEPTH_STENCIL;
6277 else if (desc->ddsCaps.dwCaps & DDSCAPS_3DDEVICE)
6278 wined3d_desc.bind_flags |= WINED3D_BIND_RENDER_TARGET;
6281 if (desc->ddsCaps.dwCaps2 & (DDSCAPS2_TEXTUREMANAGE | DDSCAPS2_D3DTEXTUREMANAGE))
6283 wined3d_desc.bind_flags &= ~WINED3D_BIND_RENDER_TARGET;
6284 wined3d_desc.access = WINED3D_RESOURCE_ACCESS_GPU | WINED3D_RESOURCE_ACCESS_CPU
6285 | WINED3D_RESOURCE_ACCESS_MAP_R | WINED3D_RESOURCE_ACCESS_MAP_W;
6286 /* Managed textures have the system memory flag set. */
6287 desc->ddsCaps.dwCaps |= DDSCAPS_SYSTEMMEMORY;
6289 else if (desc->ddsCaps.dwCaps & DDSCAPS_VIDEOMEMORY)
6291 /* Videomemory adds localvidmem. This is mutually exclusive with
6292 * systemmemory and texturemanage. */
6293 desc->ddsCaps.dwCaps |= DDSCAPS_LOCALVIDMEM;
6294 /* Dynamic resources can't be written by the GPU. */
6295 if (!(wined3d_desc.bind_flags & (WINED3D_BIND_RENDER_TARGET | WINED3D_BIND_DEPTH_STENCIL)))
6296 wined3d_desc.usage |= WINED3DUSAGE_DYNAMIC;
6300 if (desc->dwFlags & DDSD_LPSURFACE)
6302 if (wined3d_desc.access & WINED3D_RESOURCE_ACCESS_GPU)
6304 WARN("User memory surfaces should not be GPU accessible.\n");
6305 heap_free(texture);
6306 return DDERR_INVALIDCAPS;
6309 if (version < 4)
6311 WARN("User memory surfaces not supported before version 4.\n");
6312 heap_free(texture);
6313 return DDERR_INVALIDPARAMS;
6316 if (!desc->lpSurface)
6318 WARN("NULL surface memory pointer specified.\n");
6319 heap_free(texture);
6320 return DDERR_INVALIDPARAMS;
6323 if (format_is_compressed(&desc->u4.ddpfPixelFormat))
6325 if (version != 4 && (desc->dwFlags & DDSD_PITCH))
6327 WARN("Pitch specified on a compressed user memory surface.\n");
6328 heap_free(texture);
6329 return DDERR_INVALIDPARAMS;
6332 if (!(desc->dwFlags & (DDSD_LINEARSIZE | DDSD_PITCH)))
6334 WARN("Compressed user memory surfaces should explicitly specify the linear size.\n");
6335 heap_free(texture);
6336 return DDERR_INVALIDPARAMS;
6339 if ((desc->dwFlags & DDSD_LINEARSIZE)
6340 && desc->u1.dwLinearSize < wined3d_calculate_format_pitch(ddraw->wined3d_adapter,
6341 wined3d_desc.format, wined3d_desc.width) * ((desc->dwHeight + 3) / 4))
6343 WARN("Invalid linear size %u specified.\n", desc->u1.dwLinearSize);
6344 heap_free(texture);
6345 return DDERR_INVALIDPARAMS;
6348 else
6350 if (!(desc->dwFlags & DDSD_PITCH))
6352 WARN("User memory surfaces should explicitly specify the pitch.\n");
6353 heap_free(texture);
6354 return DDERR_INVALIDPARAMS;
6357 if (desc->u1.lPitch < wined3d_calculate_format_pitch(ddraw->wined3d_adapter,
6358 wined3d_desc.format, wined3d_desc.width) || desc->u1.lPitch & 3)
6360 WARN("Invalid pitch %u specified.\n", desc->u1.lPitch);
6361 heap_free(texture);
6362 return DDERR_INVALIDPARAMS;
6365 pitch = desc->u1.lPitch;
6369 if (((desc->dwFlags & DDSD_CKDESTOVERLAY)
6370 && desc->u3.ddckCKDestOverlay.dwColorSpaceLowValue != desc->u3.ddckCKDestOverlay.dwColorSpaceHighValue)
6371 || ((desc->dwFlags & DDSD_CKDESTBLT)
6372 && desc->ddckCKDestBlt.dwColorSpaceLowValue != desc->ddckCKDestBlt.dwColorSpaceHighValue)
6373 || ((desc->dwFlags & DDSD_CKSRCOVERLAY)
6374 && desc->ddckCKSrcOverlay.dwColorSpaceLowValue != desc->ddckCKSrcOverlay.dwColorSpaceHighValue)
6375 || ((desc->dwFlags & DDSD_CKSRCBLT)
6376 && desc->ddckCKSrcBlt.dwColorSpaceLowValue != desc->ddckCKSrcBlt.dwColorSpaceHighValue))
6378 WARN("Range color keys not supported, returning DDERR_NOCOLORKEYHW.\n");
6379 heap_free(texture);
6380 return DDERR_NOCOLORKEYHW;
6383 if ((ddraw->flags & DDRAW_NO3D) && (desc->ddsCaps.dwCaps & DDSCAPS_VIDEOMEMORY))
6385 WARN("Video memory surfaces not supported without 3D support.\n");
6386 heap_free(texture);
6387 return DDERR_NODIRECTDRAWHW;
6390 if (desc->ddsCaps.dwCaps & (DDSCAPS_OVERLAY))
6391 wined3d_desc.usage |= WINED3DUSAGE_OVERLAY;
6393 if (desc->ddsCaps.dwCaps & DDSCAPS_OWNDC)
6394 wined3d_desc.usage |= WINED3DUSAGE_OWNDC;
6396 if (desc->ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP)
6398 wined3d_desc.usage |= WINED3DUSAGE_LEGACY_CUBEMAP;
6399 layers = 6;
6402 /* Some applications assume surfaces will always be mapped at the same
6403 * address. Some of those also assume that this address is valid even when
6404 * the surface isn't mapped, and that updates done this way will be
6405 * visible on the screen. The game Nox is such an application,
6406 * Commandos: Behind Enemy Lines is another. Setting
6407 * WINED3D_TEXTURE_CREATE_GET_DC_LENIENT will ensure this. */
6408 if (FAILED(hr = wined3d_texture_create(ddraw->wined3d_device, &wined3d_desc, layers, levels,
6409 WINED3D_TEXTURE_CREATE_GET_DC_LENIENT, NULL, texture,
6410 &ddraw_texture_wined3d_parent_ops, &wined3d_texture)))
6412 WARN("Failed to create wined3d texture, hr %#x.\n", hr);
6413 heap_free(texture);
6414 return hr_ddraw_from_wined3d(hr);
6417 root = wined3d_texture_get_sub_resource_parent(wined3d_texture, 0);
6418 wined3d_texture_decref(wined3d_texture);
6419 root->is_complex_root = TRUE;
6420 root->sysmem_fallback = sysmem_fallback;
6421 texture->root = root;
6422 wined3d_device_incref(texture->wined3d_device = ddraw->wined3d_device);
6424 if (desc->dwFlags & DDSD_CKDESTOVERLAY)
6425 wined3d_texture_set_color_key(wined3d_texture, DDCKEY_DESTOVERLAY,
6426 (struct wined3d_color_key *)&desc->u3.ddckCKDestOverlay);
6427 if (desc->dwFlags & DDSD_CKDESTBLT)
6428 wined3d_texture_set_color_key(wined3d_texture, DDCKEY_DESTBLT,
6429 (struct wined3d_color_key *)&desc->ddckCKDestBlt);
6430 if (desc->dwFlags & DDSD_CKSRCOVERLAY)
6431 wined3d_texture_set_color_key(wined3d_texture, DDCKEY_SRCOVERLAY,
6432 (struct wined3d_color_key *)&desc->ddckCKSrcOverlay);
6433 if (desc->dwFlags & DDSD_CKSRCBLT)
6434 wined3d_texture_set_color_key(wined3d_texture, DDCKEY_SRCBLT,
6435 (struct wined3d_color_key *)&desc->ddckCKSrcBlt);
6437 for (i = 0; i < layers; ++i)
6439 attach = &root->complex_array[layers - 1 - i];
6441 for (j = 0; j < levels; ++j)
6443 mip = wined3d_texture_get_sub_resource_parent(wined3d_texture, i * levels + j);
6444 mip->sysmem_fallback = sysmem_fallback;
6445 mip_desc = &mip->surface_desc;
6446 if (desc->ddsCaps.dwCaps & DDSCAPS_MIPMAP)
6447 mip_desc->u2.dwMipMapCount = levels - j;
6449 if (j)
6451 wined3d_texture_get_sub_resource_desc(wined3d_texture, i * levels + j, &wined3d_mip_desc);
6452 mip_desc->dwWidth = wined3d_mip_desc.width;
6453 mip_desc->dwHeight = wined3d_mip_desc.height;
6455 mip_desc->ddsCaps.dwCaps2 |= DDSCAPS2_MIPMAPSUBLEVEL;
6457 else
6459 mip_desc->ddsCaps.dwCaps2 &= ~DDSCAPS2_MIPMAPSUBLEVEL;
6462 if (mip_desc->ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP)
6464 mip_desc->ddsCaps.dwCaps2 &= ~DDSCAPS2_CUBEMAP_ALLFACES;
6466 switch (i)
6468 case WINED3D_CUBEMAP_FACE_POSITIVE_X:
6469 mip_desc->ddsCaps.dwCaps2 |= DDSCAPS2_CUBEMAP_POSITIVEX;
6470 break;
6471 case WINED3D_CUBEMAP_FACE_NEGATIVE_X:
6472 mip_desc->ddsCaps.dwCaps2 |= DDSCAPS2_CUBEMAP_NEGATIVEX;
6473 break;
6474 case WINED3D_CUBEMAP_FACE_POSITIVE_Y:
6475 mip_desc->ddsCaps.dwCaps2 |= DDSCAPS2_CUBEMAP_POSITIVEY;
6476 break;
6477 case WINED3D_CUBEMAP_FACE_NEGATIVE_Y:
6478 mip_desc->ddsCaps.dwCaps2 |= DDSCAPS2_CUBEMAP_NEGATIVEY;
6479 break;
6480 case WINED3D_CUBEMAP_FACE_POSITIVE_Z:
6481 mip_desc->ddsCaps.dwCaps2 |= DDSCAPS2_CUBEMAP_POSITIVEZ;
6482 break;
6483 case WINED3D_CUBEMAP_FACE_NEGATIVE_Z:
6484 mip_desc->ddsCaps.dwCaps2 |= DDSCAPS2_CUBEMAP_NEGATIVEZ;
6485 break;
6490 if (mip == root)
6491 continue;
6493 *attach = mip;
6494 attach = &mip->complex_array[0];
6498 if ((desc->dwFlags & DDSD_LPSURFACE) && FAILED(hr = wined3d_texture_update_desc(wined3d_texture, 0,
6499 wined3d_desc.width, wined3d_desc.height, wined3d_desc.format,
6500 WINED3D_MULTISAMPLE_NONE, 0, desc->lpSurface, pitch)))
6502 ERR("Failed to set surface memory, hr %#x.\n", hr);
6503 goto fail;
6506 reserve_memory = !(desc->dwFlags & DDSD_LPSURFACE)
6507 && desc->ddsCaps.dwCaps & DDSCAPS_VIDEOMEMORY
6508 && wined3d_display_mode_format.u1.dwRGBBitCount <= 16;
6510 if (reserve_memory && FAILED(hr = ddraw_surface_reserve_memory(wined3d_texture)))
6512 ERR("Failed to reserve surface memory, hr %#x.\n", hr);
6513 goto fail;
6516 if (desc->dwFlags & DDSD_BACKBUFFERCOUNT)
6518 unsigned int count = desc->u5.dwBackBufferCount;
6519 struct ddraw_surface *last = root;
6521 attach = &last->complex_array[0];
6522 for (i = 0; i < count; ++i)
6524 if (!(texture = heap_alloc(sizeof(*texture))))
6526 hr = E_OUTOFMEMORY;
6527 goto fail;
6530 texture->texture_memory = NULL;
6531 texture->version = version;
6532 texture->surface_desc = root->surface_desc;
6533 desc = &texture->surface_desc;
6535 /* Only one surface in the flipping chain is a back buffer, one is
6536 * a front buffer, the others are just flippable surfaces. */
6537 desc->ddsCaps.dwCaps &= ~(DDSCAPS_VISIBLE | DDSCAPS_PRIMARYSURFACE | DDSCAPS_FRONTBUFFER
6538 | DDSCAPS_BACKBUFFER);
6539 if (!i)
6540 desc->ddsCaps.dwCaps |= DDSCAPS_BACKBUFFER;
6541 desc->u5.dwBackBufferCount = 0;
6543 if (FAILED(hr = wined3d_texture_create(ddraw->wined3d_device, &wined3d_desc, 1, 1,
6544 WINED3D_TEXTURE_CREATE_GET_DC_LENIENT, NULL, texture,
6545 &ddraw_texture_wined3d_parent_ops, &wined3d_texture)))
6547 heap_free(texture);
6548 hr = hr_ddraw_from_wined3d(hr);
6549 goto fail;
6552 last = wined3d_texture_get_sub_resource_parent(wined3d_texture, 0);
6553 last->sysmem_fallback = sysmem_fallback;
6554 wined3d_texture_decref(wined3d_texture);
6555 texture->root = last;
6556 wined3d_device_incref(texture->wined3d_device = ddraw->wined3d_device);
6558 if (desc->dwFlags & DDSD_CKDESTOVERLAY)
6559 wined3d_texture_set_color_key(wined3d_texture, DDCKEY_DESTOVERLAY,
6560 (struct wined3d_color_key *)&desc->u3.ddckCKDestOverlay);
6561 if (desc->dwFlags & DDSD_CKDESTBLT)
6562 wined3d_texture_set_color_key(wined3d_texture, DDCKEY_DESTBLT,
6563 (struct wined3d_color_key *)&desc->ddckCKDestBlt);
6564 if (desc->dwFlags & DDSD_CKSRCOVERLAY)
6565 wined3d_texture_set_color_key(wined3d_texture, DDCKEY_SRCOVERLAY,
6566 (struct wined3d_color_key *)&desc->ddckCKSrcOverlay);
6567 if (desc->dwFlags & DDSD_CKSRCBLT)
6568 wined3d_texture_set_color_key(wined3d_texture, DDCKEY_SRCBLT,
6569 (struct wined3d_color_key *)&desc->ddckCKSrcBlt);
6571 if (reserve_memory && FAILED(hr = ddraw_surface_reserve_memory(wined3d_texture)))
6573 hr = hr_ddraw_from_wined3d(hr);
6574 goto fail;
6577 *attach = last;
6578 attach = &last->complex_array[0];
6580 *attach = root;
6583 if (surface_desc->ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE)
6585 ddraw->primary = root;
6586 ddraw->gdi_surface = root->wined3d_texture;
6588 *surface = root;
6590 return DD_OK;
6592 fail:
6593 if (version == 7)
6594 IDirectDrawSurface7_Release(&root->IDirectDrawSurface7_iface);
6595 else if (version == 4)
6596 IDirectDrawSurface4_Release(&root->IDirectDrawSurface4_iface);
6597 else
6598 IDirectDrawSurface_Release(&root->IDirectDrawSurface_iface);
6600 return hr;
6603 void ddraw_surface_init(struct ddraw_surface *surface, struct ddraw *ddraw,
6604 struct wined3d_texture *wined3d_texture, unsigned int sub_resource_idx,
6605 const struct wined3d_parent_ops **parent_ops)
6607 struct ddraw_texture *texture = wined3d_texture_get_parent(wined3d_texture);
6608 unsigned int texture_level, row_pitch, slice_pitch;
6609 DDSURFACEDESC2 *desc = &surface->surface_desc;
6610 unsigned int version = texture->version;
6612 surface->IDirectDrawSurface7_iface.lpVtbl = &ddraw_surface7_vtbl;
6613 surface->IDirectDrawSurface4_iface.lpVtbl = &ddraw_surface4_vtbl;
6614 surface->IDirectDrawSurface3_iface.lpVtbl = &ddraw_surface3_vtbl;
6615 surface->IDirectDrawSurface2_iface.lpVtbl = &ddraw_surface2_vtbl;
6616 surface->IDirectDrawSurface_iface.lpVtbl = &ddraw_surface1_vtbl;
6617 surface->IDirectDrawGammaControl_iface.lpVtbl = &ddraw_gamma_control_vtbl;
6618 surface->IDirect3DTexture2_iface.lpVtbl = &d3d_texture2_vtbl;
6619 surface->IDirect3DTexture_iface.lpVtbl = &d3d_texture1_vtbl;
6620 surface->iface_count = 1;
6621 surface->version = version;
6622 surface->ddraw = ddraw;
6624 if (version == 7)
6626 surface->ref7 = 1;
6627 surface->texture_outer = (IUnknown *)&surface->IDirectDrawSurface7_iface;
6629 else if (version == 4)
6631 surface->ref4 = 1;
6632 surface->texture_outer = (IUnknown *)&surface->IDirectDrawSurface4_iface;
6634 else
6636 surface->ref1 = 1;
6637 surface->texture_outer = (IUnknown *)&surface->IDirectDrawSurface_iface;
6640 *desc = texture->surface_desc;
6641 surface->first_attached = surface;
6643 texture_level = desc->ddsCaps.dwCaps & DDSCAPS_MIPMAP ? sub_resource_idx % desc->u2.dwMipMapCount : 0;
6644 wined3d_texture_get_pitch(wined3d_texture, texture_level, &row_pitch, &slice_pitch);
6645 if (format_is_compressed(&desc->u4.ddpfPixelFormat))
6647 if (desc->dwFlags & DDSD_LPSURFACE)
6648 desc->u1.dwLinearSize = ~0u;
6649 else
6650 desc->u1.dwLinearSize = slice_pitch;
6651 desc->dwFlags |= DDSD_LINEARSIZE;
6652 desc->dwFlags &= ~(DDSD_LPSURFACE | DDSD_PITCH);
6654 else
6656 if (!(desc->dwFlags & DDSD_LPSURFACE))
6657 desc->u1.lPitch = row_pitch;
6658 desc->dwFlags |= DDSD_PITCH;
6659 desc->dwFlags &= ~(DDSD_LPSURFACE | DDSD_LINEARSIZE);
6661 desc->lpSurface = NULL;
6663 wined3d_texture_incref(surface->wined3d_texture = wined3d_texture);
6664 surface->sub_resource_idx = sub_resource_idx;
6665 *parent_ops = &ddraw_surface_wined3d_parent_ops;
6667 wined3d_private_store_init(&surface->private_store);
6670 static void STDMETHODCALLTYPE view_wined3d_object_destroyed(void *parent)
6672 struct ddraw_surface *surface = parent;
6674 /* If the surface reference count drops to zero, we release our reference
6675 * to the view, but don't clear the pointer yet, in case e.g. a
6676 * GetRenderTarget() call brings the surface back before the view is
6677 * actually destroyed. When the view is destroyed, we need to clear the
6678 * pointer, or a subsequent surface AddRef() would reference it again.
6680 * This is safe because as long as the view still has a reference to the
6681 * texture, the surface is also still alive, and we're called before the
6682 * view releases that reference. */
6683 surface->wined3d_rtv = NULL;
6686 static const struct wined3d_parent_ops ddraw_view_wined3d_parent_ops =
6688 view_wined3d_object_destroyed,
6691 struct wined3d_rendertarget_view *ddraw_surface_get_rendertarget_view(struct ddraw_surface *surface)
6693 HRESULT hr;
6695 if (surface->wined3d_rtv)
6696 return surface->wined3d_rtv;
6698 if (FAILED(hr = wined3d_rendertarget_view_create_from_sub_resource(surface->wined3d_texture,
6699 surface->sub_resource_idx, surface, &ddraw_view_wined3d_parent_ops, &surface->wined3d_rtv)))
6701 ERR("Failed to create rendertarget view, hr %#x.\n", hr);
6702 return NULL;
6705 return surface->wined3d_rtv;