winmm: Add a WARNing when winejoystick.drv is missing.
[wine.git] / dlls / ddraw / surface.c
blob819044214d53645a836403d5313afb85619b7769
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 "config.h"
25 #include "wine/port.h"
27 #include "ddraw_private.h"
29 WINE_DEFAULT_DEBUG_CHANNEL(ddraw);
31 static struct ddraw_surface *unsafe_impl_from_IDirectDrawSurface2(IDirectDrawSurface2 *iface);
32 static struct ddraw_surface *unsafe_impl_from_IDirectDrawSurface3(IDirectDrawSurface3 *iface);
34 static inline struct ddraw_surface *impl_from_IDirectDrawGammaControl(IDirectDrawGammaControl *iface)
36 return CONTAINING_RECORD(iface, struct ddraw_surface, IDirectDrawGammaControl_iface);
39 /* This is slow, of course. Also, in case of locks, we can't prevent other
40 * applications from drawing to the screen while we've locked the frontbuffer.
41 * We'd like to do this in wined3d instead, but for that to work wined3d needs
42 * to support windowless rendering first. */
43 HRESULT ddraw_surface_update_frontbuffer(struct ddraw_surface *surface,
44 const RECT *rect, BOOL read, unsigned int swap_interval)
46 struct wined3d_texture *dst_texture;
47 HDC surface_dc, screen_dc;
48 int x, y, w, h;
49 HRESULT hr;
50 BOOL ret;
51 RECT r;
53 if (surface->ddraw->flags & DDRAW_SWAPPED && !read)
55 surface->ddraw->flags &= ~DDRAW_SWAPPED;
56 rect = NULL;
59 if (!rect)
61 SetRect(&r, 0, 0, surface->surface_desc.dwWidth, surface->surface_desc.dwHeight);
62 rect = &r;
65 x = rect->left;
66 y = rect->top;
67 w = rect->right - rect->left;
68 h = rect->bottom - rect->top;
70 if (w <= 0 || h <= 0)
71 return DD_OK;
73 if (surface->ddraw->swapchain_window)
75 /* Nothing to do, we control the frontbuffer, or at least the parts we
76 * care about. */
77 if (read)
78 return DD_OK;
80 if (swap_interval)
81 dst_texture = wined3d_swapchain_get_back_buffer(surface->ddraw->wined3d_swapchain, 0);
82 else
83 dst_texture = surface->ddraw->wined3d_frontbuffer;
85 if (SUCCEEDED(hr = wined3d_texture_blt(dst_texture, 0, rect, surface->wined3d_texture,
86 surface->sub_resource_idx, rect, 0, NULL, WINED3D_TEXF_POINT)) && swap_interval)
88 hr = wined3d_swapchain_present(surface->ddraw->wined3d_swapchain, rect, rect, NULL, swap_interval, 0);
89 surface->ddraw->flags |= DDRAW_SWAPPED;
91 return hr;
94 if (FAILED(hr = wined3d_texture_get_dc(surface->wined3d_texture, surface->sub_resource_idx, &surface_dc)))
96 ERR("Failed to get surface DC, hr %#x.\n", hr);
97 return hr;
99 if (surface->palette)
100 wined3d_palette_apply_to_dc(surface->palette->wined3d_palette, surface_dc);
102 if (!(screen_dc = GetDC(NULL)))
104 wined3d_texture_release_dc(surface->wined3d_texture, surface->sub_resource_idx, surface_dc);
105 ERR("Failed to get screen DC.\n");
106 return E_FAIL;
109 if (read)
110 ret = BitBlt(surface_dc, x, y, w, h,
111 screen_dc, x, y, SRCCOPY);
112 else
113 ret = BitBlt(screen_dc, x, y, w, h,
114 surface_dc, x, y, SRCCOPY);
116 ReleaseDC(NULL, screen_dc);
117 wined3d_texture_release_dc(surface->wined3d_texture, surface->sub_resource_idx, surface_dc);
119 if (!ret)
121 ERR("Failed to blit to/from screen.\n");
122 return E_FAIL;
125 return DD_OK;
128 /*****************************************************************************
129 * IUnknown parts follow
130 *****************************************************************************/
132 /*****************************************************************************
133 * IDirectDrawSurface7::QueryInterface
135 * A normal QueryInterface implementation. For QueryInterface rules
136 * see ddraw.c, IDirectDraw7::QueryInterface. This method
137 * can Query IDirectDrawSurface interfaces in all version, IDirect3DTexture
138 * in all versions, the IDirectDrawGammaControl interface and it can
139 * create an IDirect3DDevice. (Uses IDirect3D7::CreateDevice)
141 * Params:
142 * riid: The interface id queried for
143 * obj: Address to write the pointer to
145 * Returns:
146 * S_OK on success
147 * E_NOINTERFACE if the requested interface wasn't found
149 *****************************************************************************/
150 static HRESULT WINAPI ddraw_surface7_QueryInterface(IDirectDrawSurface7 *iface, REFIID riid, void **obj)
152 struct ddraw_surface *This = impl_from_IDirectDrawSurface7(iface);
154 TRACE("iface %p, riid %s, object %p.\n", iface, debugstr_guid(riid), obj);
156 /* According to COM docs, if the QueryInterface fails, obj should be set to NULL */
157 *obj = NULL;
159 if(!riid)
160 return DDERR_INVALIDPARAMS;
162 if (IsEqualGUID(riid, &IID_IDirectDrawSurface7))
164 IDirectDrawSurface7_AddRef(iface);
165 *obj = iface;
166 TRACE("(%p) returning IDirectDrawSurface7 interface at %p\n", This, *obj);
167 return S_OK;
170 if (IsEqualGUID(riid, &IID_IDirectDrawSurface4))
172 IDirectDrawSurface4_AddRef(&This->IDirectDrawSurface4_iface);
173 *obj = &This->IDirectDrawSurface4_iface;
174 TRACE("(%p) returning IDirectDrawSurface4 interface at %p\n", This, *obj);
175 return S_OK;
178 if (IsEqualGUID(riid, &IID_IDirectDrawSurface3))
180 IDirectDrawSurface3_AddRef(&This->IDirectDrawSurface3_iface);
181 *obj = &This->IDirectDrawSurface3_iface;
182 TRACE("(%p) returning IDirectDrawSurface3 interface at %p\n", This, *obj);
183 return S_OK;
186 if (IsEqualGUID(riid, &IID_IDirectDrawSurface2))
188 IDirectDrawSurface2_AddRef(&This->IDirectDrawSurface2_iface);
189 *obj = &This->IDirectDrawSurface2_iface;
190 TRACE("(%p) returning IDirectDrawSurface2 interface at %p\n", This, *obj);
191 return S_OK;
194 if (IsEqualGUID(riid, &IID_IDirectDrawSurface)
195 || IsEqualGUID(riid, &IID_IUnknown))
197 IDirectDrawSurface_AddRef(&This->IDirectDrawSurface_iface);
198 *obj = &This->IDirectDrawSurface_iface;
199 TRACE("(%p) returning IDirectDrawSurface interface at %p\n", This, *obj);
200 return S_OK;
203 if (IsEqualGUID(riid, &IID_IDirectDrawGammaControl))
205 IDirectDrawGammaControl_AddRef(&This->IDirectDrawGammaControl_iface);
206 *obj = &This->IDirectDrawGammaControl_iface;
207 TRACE("(%p) returning IDirectDrawGammaControl interface at %p\n", This, *obj);
208 return S_OK;
211 if (IsEqualGUID(riid, &IID_IDirectDrawColorControl))
213 WARN("Color control not implemented.\n");
214 *obj = NULL;
215 return E_NOINTERFACE;
218 if (This->version != 7)
220 if (IsEqualGUID(riid, &IID_D3DDEVICE_WineD3D)
221 || IsEqualGUID(riid, &IID_IDirect3DHALDevice)
222 || IsEqualGUID(riid, &IID_IDirect3DRGBDevice))
224 wined3d_mutex_lock();
225 if (!This->device1)
227 HRESULT hr;
229 if (FAILED(hr = d3d_device_create(This->ddraw, This, (IUnknown *)&This->IDirectDrawSurface_iface,
230 1, &This->device1, (IUnknown *)&This->IDirectDrawSurface_iface)))
232 This->device1 = NULL;
233 wined3d_mutex_unlock();
234 WARN("Failed to create device, hr %#x.\n", hr);
235 return hr;
238 wined3d_mutex_unlock();
240 IDirect3DDevice_AddRef(&This->device1->IDirect3DDevice_iface);
241 *obj = &This->device1->IDirect3DDevice_iface;
242 return S_OK;
245 if (IsEqualGUID(&IID_IDirect3DTexture2, riid))
247 IDirect3DTexture2_AddRef(&This->IDirect3DTexture2_iface);
248 *obj = &This->IDirect3DTexture2_iface;
249 return S_OK;
252 if (IsEqualGUID( &IID_IDirect3DTexture, riid ))
254 IDirect3DTexture2_AddRef(&This->IDirect3DTexture_iface);
255 *obj = &This->IDirect3DTexture_iface;
256 return S_OK;
260 WARN("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(riid));
262 if (This->version != 7)
263 return E_INVALIDARG;
265 return E_NOINTERFACE;
268 static HRESULT WINAPI ddraw_surface4_QueryInterface(IDirectDrawSurface4 *iface, REFIID riid, void **object)
270 struct ddraw_surface *surface = impl_from_IDirectDrawSurface4(iface);
272 TRACE("iface %p, riid %s, object %p.\n", iface, debugstr_guid(riid), object);
274 return ddraw_surface7_QueryInterface(&surface->IDirectDrawSurface7_iface, riid, object);
277 static HRESULT WINAPI ddraw_surface3_QueryInterface(IDirectDrawSurface3 *iface, REFIID riid, void **object)
279 struct ddraw_surface *surface = impl_from_IDirectDrawSurface3(iface);
281 TRACE("iface %p, riid %s, object %p.\n", iface, debugstr_guid(riid), object);
283 return ddraw_surface7_QueryInterface(&surface->IDirectDrawSurface7_iface, riid, object);
286 static HRESULT WINAPI ddraw_surface2_QueryInterface(IDirectDrawSurface2 *iface, REFIID riid, void **object)
288 struct ddraw_surface *surface = impl_from_IDirectDrawSurface2(iface);
290 TRACE("iface %p, riid %s, object %p.\n", iface, debugstr_guid(riid), object);
292 return ddraw_surface7_QueryInterface(&surface->IDirectDrawSurface7_iface, riid, object);
295 static HRESULT WINAPI ddraw_surface1_QueryInterface(IDirectDrawSurface *iface, REFIID riid, void **object)
297 struct ddraw_surface *surface = impl_from_IDirectDrawSurface(iface);
299 TRACE("iface %p, riid %s, object %p.\n", iface, debugstr_guid(riid), object);
301 return ddraw_surface7_QueryInterface(&surface->IDirectDrawSurface7_iface, riid, object);
304 static HRESULT WINAPI ddraw_gamma_control_QueryInterface(IDirectDrawGammaControl *iface,
305 REFIID riid, void **object)
307 struct ddraw_surface *surface = impl_from_IDirectDrawGammaControl(iface);
309 TRACE("iface %p, riid %s, object %p.\n", iface, debugstr_guid(riid), object);
311 return ddraw_surface7_QueryInterface(&surface->IDirectDrawSurface7_iface, riid, object);
314 static HRESULT WINAPI d3d_texture2_QueryInterface(IDirect3DTexture2 *iface, REFIID riid, void **object)
316 struct ddraw_surface *surface = impl_from_IDirect3DTexture2(iface);
318 TRACE("iface %p, riid %s, object %p.\n", iface, debugstr_guid(riid), object);
320 return ddraw_surface7_QueryInterface(&surface->IDirectDrawSurface7_iface, riid, object);
323 static HRESULT WINAPI d3d_texture1_QueryInterface(IDirect3DTexture *iface, REFIID riid, void **object)
325 struct ddraw_surface *surface = impl_from_IDirect3DTexture(iface);
327 TRACE("iface %p, riid %s, object %p.\n", iface, debugstr_guid(riid), object);
329 return ddraw_surface7_QueryInterface(&surface->IDirectDrawSurface7_iface, riid, object);
332 static void ddraw_surface_add_iface(struct ddraw_surface *surface)
334 ULONG iface_count = InterlockedIncrement(&surface->iface_count);
335 TRACE("%p increasing iface count to %u.\n", surface, iface_count);
337 if (iface_count == 1)
339 if (surface->ifaceToRelease)
340 IUnknown_AddRef(surface->ifaceToRelease);
341 wined3d_mutex_lock();
342 if (surface->wined3d_rtv)
343 wined3d_rendertarget_view_incref(surface->wined3d_rtv);
344 wined3d_texture_incref(surface->wined3d_texture);
345 wined3d_mutex_unlock();
349 /*****************************************************************************
350 * IDirectDrawSurface7::AddRef
352 * A normal addref implementation
354 * Returns:
355 * The new refcount
357 *****************************************************************************/
358 static ULONG WINAPI ddraw_surface7_AddRef(IDirectDrawSurface7 *iface)
360 struct ddraw_surface *This = impl_from_IDirectDrawSurface7(iface);
361 ULONG refcount = InterlockedIncrement(&This->ref7);
363 TRACE("iface %p increasing refcount to %u.\n", iface, refcount);
365 if (refcount == 1)
367 ddraw_surface_add_iface(This);
370 return refcount;
373 static ULONG WINAPI ddraw_surface4_AddRef(IDirectDrawSurface4 *iface)
375 struct ddraw_surface *This = impl_from_IDirectDrawSurface4(iface);
376 ULONG refcount = InterlockedIncrement(&This->ref4);
378 TRACE("iface %p increasing refcount to %u.\n", iface, refcount);
380 if (refcount == 1)
382 ddraw_surface_add_iface(This);
385 return refcount;
388 static ULONG WINAPI ddraw_surface3_AddRef(IDirectDrawSurface3 *iface)
390 struct ddraw_surface *This = impl_from_IDirectDrawSurface3(iface);
391 ULONG refcount = InterlockedIncrement(&This->ref3);
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_surface2_AddRef(IDirectDrawSurface2 *iface)
405 struct ddraw_surface *This = impl_from_IDirectDrawSurface2(iface);
406 ULONG refcount = InterlockedIncrement(&This->ref2);
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_surface1_AddRef(IDirectDrawSurface *iface)
420 struct ddraw_surface *This = impl_from_IDirectDrawSurface(iface);
421 ULONG refcount = InterlockedIncrement(&This->ref1);
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_gamma_control_AddRef(IDirectDrawGammaControl *iface)
435 struct ddraw_surface *This = impl_from_IDirectDrawGammaControl(iface);
436 ULONG refcount = InterlockedIncrement(&This->gamma_count);
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 d3d_texture2_AddRef(IDirect3DTexture2 *iface)
450 struct ddraw_surface *surface = impl_from_IDirect3DTexture2(iface);
452 TRACE("iface %p.\n", iface);
454 return IUnknown_AddRef(surface->texture_outer);
457 static ULONG WINAPI d3d_texture1_AddRef(IDirect3DTexture *iface)
459 struct ddraw_surface *surface = impl_from_IDirect3DTexture(iface);
461 TRACE("iface %p.\n", iface);
463 return IUnknown_AddRef(surface->texture_outer);
466 static HRESULT ddraw_surface_set_palette(struct ddraw_surface *surface, IDirectDrawPalette *palette)
468 struct ddraw_palette *palette_impl = unsafe_impl_from_IDirectDrawPalette(palette);
469 struct ddraw_palette *prev;
471 TRACE("iface %p, palette %p.\n", surface, palette);
473 if (palette_impl && palette_impl->flags & DDPCAPS_ALPHA
474 && !(surface->surface_desc.ddsCaps.dwCaps & DDSCAPS_TEXTURE))
476 WARN("Alpha palette set on non-texture surface, returning DDERR_INVALIDSURFACETYPE.\n");
477 return DDERR_INVALIDSURFACETYPE;
480 if (!format_is_paletteindexed(&surface->surface_desc.u4.ddpfPixelFormat))
481 return DDERR_INVALIDPIXELFORMAT;
483 wined3d_mutex_lock();
485 prev = surface->palette;
486 if (surface->surface_desc.ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE)
488 if (prev)
489 prev->flags &= ~DDPCAPS_PRIMARYSURFACE;
490 if (palette_impl)
491 palette_impl->flags |= DDPCAPS_PRIMARYSURFACE;
492 wined3d_swapchain_set_palette(surface->ddraw->wined3d_swapchain,
493 palette_impl ? palette_impl->wined3d_palette : NULL);
494 ddraw_surface_update_frontbuffer(surface, NULL, FALSE, 0);
496 if (palette_impl)
497 IDirectDrawPalette_AddRef(&palette_impl->IDirectDrawPalette_iface);
498 if (prev)
499 IDirectDrawPalette_Release(&prev->IDirectDrawPalette_iface);
500 surface->palette = palette_impl;
502 wined3d_mutex_unlock();
504 return DD_OK;
507 static void ddraw_surface_cleanup(struct ddraw_surface *surface)
509 struct ddraw_surface *surf;
510 UINT i;
512 TRACE("surface %p.\n", surface);
514 /* The refcount test shows that the palette is detached when the surface
515 * is destroyed. */
516 ddraw_surface_set_palette(surface, NULL);
518 /* Loop through all complex attached surfaces and destroy them.
520 * Yet again, only the root can have more than one complexly attached
521 * surface, all the others have a total of one. */
522 for (i = 0; i < MAX_COMPLEX_ATTACHED; ++i)
524 if (!surface->complex_array[i])
525 break;
527 surf = surface->complex_array[i];
528 surface->complex_array[i] = NULL;
529 if (!surf->is_complex_root)
531 struct ddraw_texture *texture = wined3d_texture_get_parent(surf->wined3d_texture);
532 struct wined3d_device *wined3d_device = texture->wined3d_device;
533 struct ddraw_surface *root = texture->root;
535 ddraw_surface_cleanup(surf);
537 if (surf == root)
538 wined3d_device_decref(wined3d_device);
542 if (surface->device1)
543 IUnknown_Release(&surface->device1->IUnknown_inner);
545 if (surface->iface_count > 1)
547 /* This can happen when a complex surface is destroyed, because the
548 * 2nd surface was addref()ed when the app called
549 * GetAttachedSurface(). */
550 WARN("Destroying surface %p with refcounts 7: %u 4: %u 3: %u 2: %u 1: %u.\n",
551 surface, surface->ref7, surface->ref4, surface->ref3, surface->ref2, surface->ref1);
554 if (surface->wined3d_rtv)
555 wined3d_rendertarget_view_decref(surface->wined3d_rtv);
556 wined3d_texture_decref(surface->wined3d_texture);
559 static ULONG ddraw_surface_release_iface(struct ddraw_surface *This)
561 ULONG iface_count;
563 /* Prevent the surface from being destroyed if it's still attached to
564 * another surface. It will be destroyed when the root is destroyed. */
565 if (This->iface_count == 1 && This->attached_iface)
566 IUnknown_AddRef(This->attached_iface);
567 iface_count = InterlockedDecrement(&This->iface_count);
569 TRACE("%p decreasing iface count to %u.\n", This, iface_count);
571 if (iface_count == 0)
573 struct ddraw_texture *texture = wined3d_texture_get_parent(This->wined3d_texture);
574 struct wined3d_device *wined3d_device = texture->wined3d_device;
575 IUnknown *release_iface = This->ifaceToRelease;
577 /* Complex attached surfaces are destroyed implicitly when the root is released */
578 wined3d_mutex_lock();
579 if(!This->is_complex_root)
581 WARN("(%p) Attempt to destroy a surface that is not a complex root\n", This);
582 wined3d_mutex_unlock();
583 return iface_count;
585 ddraw_surface_cleanup(This);
586 wined3d_mutex_unlock();
588 if (release_iface)
589 IUnknown_Release(release_iface);
590 /* Release the device only after anything that may reference it (the
591 * wined3d texture and rendertarget view in particular) is released. */
592 wined3d_device_decref(wined3d_device);
595 return iface_count;
598 /*****************************************************************************
599 * IDirectDrawSurface7::Release
601 * Reduces the surface's refcount by 1. If the refcount falls to 0, the
602 * surface is destroyed.
604 * Destroying the surface is a bit tricky. For the connection between
605 * WineD3DSurfaces and DirectDrawSurfaces see IDirectDraw7::CreateSurface
606 * It has a nice graph explaining the connection.
608 * What happens here is basically this:
609 * When a surface is destroyed, its WineD3DSurface is released,
610 * and the refcount of the DirectDraw interface is reduced by 1. If it has
611 * complex surfaces attached to it, then these surfaces are destroyed too,
612 * regardless of their refcount. If any surface being destroyed has another
613 * surface attached to it (with a "soft" attachment, not complex), then
614 * this surface is detached with DeleteAttachedSurface.
616 * When the surface is a texture, the WineD3DTexture is released.
617 * If the surface is the Direct3D render target, then the D3D
618 * capabilities of the WineD3DDevice are uninitialized, which causes the
619 * swapchain to be released.
621 * When a complex sublevel falls to ref zero, then this is ignored.
623 * Returns:
624 * The new refcount
626 *****************************************************************************/
627 static ULONG WINAPI ddraw_surface7_Release(IDirectDrawSurface7 *iface)
629 struct ddraw_surface *This = impl_from_IDirectDrawSurface7(iface);
630 ULONG refcount = InterlockedDecrement(&This->ref7);
632 TRACE("iface %p decreasing refcount to %u.\n", iface, refcount);
634 if (refcount == 0)
636 ddraw_surface_release_iface(This);
639 return refcount;
642 static ULONG WINAPI ddraw_surface4_Release(IDirectDrawSurface4 *iface)
644 struct ddraw_surface *This = impl_from_IDirectDrawSurface4(iface);
645 ULONG refcount = InterlockedDecrement(&This->ref4);
647 TRACE("iface %p decreasing refcount to %u.\n", iface, refcount);
649 if (refcount == 0)
651 ddraw_surface_release_iface(This);
654 return refcount;
657 static ULONG WINAPI ddraw_surface3_Release(IDirectDrawSurface3 *iface)
659 struct ddraw_surface *This = impl_from_IDirectDrawSurface3(iface);
660 ULONG refcount = InterlockedDecrement(&This->ref3);
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_surface2_Release(IDirectDrawSurface2 *iface)
674 struct ddraw_surface *This = impl_from_IDirectDrawSurface2(iface);
675 ULONG refcount = InterlockedDecrement(&This->ref2);
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_surface1_Release(IDirectDrawSurface *iface)
689 struct ddraw_surface *This = impl_from_IDirectDrawSurface(iface);
690 ULONG refcount = InterlockedDecrement(&This->ref1);
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_gamma_control_Release(IDirectDrawGammaControl *iface)
704 struct ddraw_surface *This = impl_from_IDirectDrawGammaControl(iface);
705 ULONG refcount = InterlockedDecrement(&This->gamma_count);
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 d3d_texture2_Release(IDirect3DTexture2 *iface)
719 struct ddraw_surface *surface = impl_from_IDirect3DTexture2(iface);
721 TRACE("iface %p.\n", iface);
723 return IUnknown_Release(surface->texture_outer);
726 static ULONG WINAPI d3d_texture1_Release(IDirect3DTexture *iface)
728 struct ddraw_surface *surface = impl_from_IDirect3DTexture(iface);
730 TRACE("iface %p.\n", iface);
732 return IUnknown_Release(surface->texture_outer);
735 /*****************************************************************************
736 * IDirectDrawSurface7::GetAttachedSurface
738 * Returns an attached surface with the requested caps. Surface attachment
739 * and complex surfaces are not clearly described by the MSDN or sdk,
740 * so this method is tricky and likely to contain problems.
741 * This implementation searches the complex list first, then the
742 * attachment chain.
744 * The chains are searched from This down to the last surface in the chain,
745 * not from the first element in the chain. The first surface found is
746 * returned. The MSDN says that this method fails if more than one surface
747 * matches the caps, but it is not sure if that is right. The attachment
748 * structure may not even allow two matching surfaces.
750 * The found surface is AddRef-ed before it is returned.
752 * Params:
753 * Caps: Pointer to a DDCAPS2 structure describing the caps asked for
754 * Surface: Address to store the found surface
756 * Returns:
757 * DD_OK on success
758 * DDERR_INVALIDPARAMS if Caps or Surface is NULL
759 * DDERR_NOTFOUND if no surface was found
761 *****************************************************************************/
762 static HRESULT WINAPI ddraw_surface7_GetAttachedSurface(IDirectDrawSurface7 *iface,
763 DDSCAPS2 *Caps, IDirectDrawSurface7 **Surface)
765 struct ddraw_surface *This = impl_from_IDirectDrawSurface7(iface);
766 struct ddraw_surface *surf;
767 DDSCAPS2 our_caps;
768 int i;
770 TRACE("iface %p, caps %p, attachment %p.\n", iface, Caps, Surface);
772 wined3d_mutex_lock();
774 if(This->version < 7)
776 /* Earlier dx apps put garbage into these members, clear them */
777 our_caps.dwCaps = Caps->dwCaps;
778 our_caps.dwCaps2 = 0;
779 our_caps.dwCaps3 = 0;
780 our_caps.u1.dwCaps4 = 0;
782 else
784 our_caps = *Caps;
787 TRACE("(%p): Looking for caps: %x,%x,%x,%x\n", This, our_caps.dwCaps, our_caps.dwCaps2, our_caps.dwCaps3, our_caps.u1.dwCaps4); /* FIXME: Better debugging */
789 for(i = 0; i < MAX_COMPLEX_ATTACHED; i++)
791 surf = This->complex_array[i];
792 if(!surf) break;
794 TRACE("Surface: (%p) caps: %#x, %#x, %#x, %#x.\n", surf,
795 surf->surface_desc.ddsCaps.dwCaps,
796 surf->surface_desc.ddsCaps.dwCaps2,
797 surf->surface_desc.ddsCaps.dwCaps3,
798 surf->surface_desc.ddsCaps.u1.dwCaps4);
800 if (((surf->surface_desc.ddsCaps.dwCaps & our_caps.dwCaps) == our_caps.dwCaps) &&
801 ((surf->surface_desc.ddsCaps.dwCaps2 & our_caps.dwCaps2) == our_caps.dwCaps2)) {
803 /* MSDN: "This method fails if more than one surface is attached
804 * that matches the capabilities requested."
806 * Not sure how to test this.
809 TRACE("(%p): Returning surface %p\n", This, surf);
810 *Surface = &surf->IDirectDrawSurface7_iface;
811 ddraw_surface7_AddRef(*Surface);
812 wined3d_mutex_unlock();
814 return DD_OK;
818 /* Next, look at the attachment chain */
819 surf = This;
821 while( (surf = surf->next_attached) )
823 TRACE("Surface: (%p) caps: %#x, %#x, %#x, %#x.\n", surf,
824 surf->surface_desc.ddsCaps.dwCaps,
825 surf->surface_desc.ddsCaps.dwCaps2,
826 surf->surface_desc.ddsCaps.dwCaps3,
827 surf->surface_desc.ddsCaps.u1.dwCaps4);
829 if (((surf->surface_desc.ddsCaps.dwCaps & our_caps.dwCaps) == our_caps.dwCaps) &&
830 ((surf->surface_desc.ddsCaps.dwCaps2 & our_caps.dwCaps2) == our_caps.dwCaps2)) {
832 TRACE("(%p): Returning surface %p\n", This, surf);
833 *Surface = &surf->IDirectDrawSurface7_iface;
834 ddraw_surface7_AddRef(*Surface);
835 wined3d_mutex_unlock();
836 return DD_OK;
840 TRACE("(%p) Didn't find a valid surface\n", This);
842 wined3d_mutex_unlock();
844 *Surface = NULL;
845 return DDERR_NOTFOUND;
848 static HRESULT WINAPI ddraw_surface4_GetAttachedSurface(IDirectDrawSurface4 *iface,
849 DDSCAPS2 *caps, IDirectDrawSurface4 **attachment)
851 struct ddraw_surface *surface = impl_from_IDirectDrawSurface4(iface);
852 struct ddraw_surface *attachment_impl;
853 IDirectDrawSurface7 *attachment7;
854 HRESULT hr;
856 TRACE("iface %p, caps %p, attachment %p.\n", iface, caps, attachment);
858 hr = ddraw_surface7_GetAttachedSurface(&surface->IDirectDrawSurface7_iface,
859 caps, &attachment7);
860 if (FAILED(hr))
862 *attachment = NULL;
863 return hr;
865 attachment_impl = impl_from_IDirectDrawSurface7(attachment7);
866 *attachment = &attachment_impl->IDirectDrawSurface4_iface;
867 ddraw_surface4_AddRef(*attachment);
868 ddraw_surface7_Release(attachment7);
870 return hr;
873 static HRESULT WINAPI ddraw_surface3_GetAttachedSurface(IDirectDrawSurface3 *iface,
874 DDSCAPS *caps, IDirectDrawSurface3 **attachment)
876 struct ddraw_surface *surface = impl_from_IDirectDrawSurface3(iface);
877 struct ddraw_surface *attachment_impl;
878 IDirectDrawSurface7 *attachment7;
879 DDSCAPS2 caps2;
880 HRESULT hr;
882 TRACE("iface %p, caps %p, attachment %p.\n", iface, caps, attachment);
884 caps2.dwCaps = caps->dwCaps;
885 caps2.dwCaps2 = 0;
886 caps2.dwCaps3 = 0;
887 caps2.u1.dwCaps4 = 0;
889 hr = ddraw_surface7_GetAttachedSurface(&surface->IDirectDrawSurface7_iface,
890 &caps2, &attachment7);
891 if (FAILED(hr))
893 *attachment = NULL;
894 return hr;
896 attachment_impl = impl_from_IDirectDrawSurface7(attachment7);
897 *attachment = &attachment_impl->IDirectDrawSurface3_iface;
898 ddraw_surface3_AddRef(*attachment);
899 ddraw_surface7_Release(attachment7);
901 return hr;
904 static HRESULT WINAPI ddraw_surface2_GetAttachedSurface(IDirectDrawSurface2 *iface,
905 DDSCAPS *caps, IDirectDrawSurface2 **attachment)
907 struct ddraw_surface *surface = impl_from_IDirectDrawSurface2(iface);
908 struct ddraw_surface *attachment_impl;
909 IDirectDrawSurface7 *attachment7;
910 DDSCAPS2 caps2;
911 HRESULT hr;
913 TRACE("iface %p, caps %p, attachment %p.\n", iface, caps, attachment);
915 caps2.dwCaps = caps->dwCaps;
916 caps2.dwCaps2 = 0;
917 caps2.dwCaps3 = 0;
918 caps2.u1.dwCaps4 = 0;
920 hr = ddraw_surface7_GetAttachedSurface(&surface->IDirectDrawSurface7_iface,
921 &caps2, &attachment7);
922 if (FAILED(hr))
924 *attachment = NULL;
925 return hr;
927 attachment_impl = impl_from_IDirectDrawSurface7(attachment7);
928 *attachment = &attachment_impl->IDirectDrawSurface2_iface;
929 ddraw_surface2_AddRef(*attachment);
930 ddraw_surface7_Release(attachment7);
932 return hr;
935 static HRESULT WINAPI ddraw_surface1_GetAttachedSurface(IDirectDrawSurface *iface,
936 DDSCAPS *caps, IDirectDrawSurface **attachment)
938 struct ddraw_surface *surface = impl_from_IDirectDrawSurface(iface);
939 struct ddraw_surface *attachment_impl;
940 IDirectDrawSurface7 *attachment7;
941 DDSCAPS2 caps2;
942 HRESULT hr;
944 TRACE("iface %p, caps %p, attachment %p.\n", iface, caps, attachment);
946 caps2.dwCaps = caps->dwCaps;
947 caps2.dwCaps2 = 0;
948 caps2.dwCaps3 = 0;
949 caps2.u1.dwCaps4 = 0;
951 hr = ddraw_surface7_GetAttachedSurface(&surface->IDirectDrawSurface7_iface,
952 &caps2, &attachment7);
953 if (FAILED(hr))
955 *attachment = NULL;
956 return hr;
958 attachment_impl = impl_from_IDirectDrawSurface7(attachment7);
959 *attachment = &attachment_impl->IDirectDrawSurface_iface;
960 ddraw_surface1_AddRef(*attachment);
961 ddraw_surface7_Release(attachment7);
963 return hr;
966 /*****************************************************************************
967 * IDirectDrawSurface7::Lock
969 * Locks the surface and returns a pointer to the surface's memory
971 * Params:
972 * Rect: Rectangle to lock. If NULL, the whole surface is locked
973 * DDSD: Pointer to a DDSURFACEDESC2 which shall receive the surface's desc.
974 * Flags: Locking flags, e.g Read only or write only
975 * h: An event handle that's not used and must be NULL
977 * Returns:
978 * DD_OK on success
979 * DDERR_INVALIDPARAMS if DDSD is NULL
981 *****************************************************************************/
982 static HRESULT surface_lock(struct ddraw_surface *surface,
983 RECT *rect, DDSURFACEDESC2 *surface_desc, unsigned int surface_desc_size,
984 DWORD flags, HANDLE h)
986 struct wined3d_map_desc map_desc;
987 struct wined3d_box box;
988 HRESULT hr = DD_OK;
990 TRACE("surface %p, rect %s, surface_desc %p, surface_desc_size %u, flags %#x, h %p.\n",
991 surface, wine_dbgstr_rect(rect), surface_desc, surface_desc_size, flags, h);
993 /* surface->surface_desc.dwWidth and dwHeight are changeable, thus lock */
994 wined3d_mutex_lock();
996 /* Should I check for the handle to be NULL?
998 * The DDLOCK flags and the D3DLOCK flags are equal
999 * for the supported values. The others are ignored by WineD3D
1002 /* Windows zeroes this if the rect is invalid */
1003 surface_desc->lpSurface = NULL;
1005 if (rect)
1007 if ((rect->left < 0) || (rect->top < 0)
1008 || (rect->left > rect->right) || (rect->right > surface->surface_desc.dwWidth)
1009 || (rect->top > rect->bottom) || (rect->bottom > surface->surface_desc.dwHeight))
1011 WARN("Trying to lock an invalid rectangle, returning DDERR_INVALIDPARAMS\n");
1012 wined3d_mutex_unlock();
1013 return DDERR_INVALIDPARAMS;
1015 wined3d_box_set(&box, rect->left, rect->top, rect->right, rect->bottom, 0, 1);
1018 if (surface->surface_desc.ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE)
1019 hr = ddraw_surface_update_frontbuffer(surface, rect, TRUE, 0);
1020 if (SUCCEEDED(hr))
1021 hr = wined3d_resource_map(wined3d_texture_get_resource(surface->wined3d_texture),
1022 surface->sub_resource_idx, &map_desc, rect ? &box : NULL,
1023 wined3dmapflags_from_ddrawmapflags(flags));
1024 if (FAILED(hr))
1026 wined3d_mutex_unlock();
1027 switch(hr)
1029 /* D3D8 and D3D9 return the general D3DERR_INVALIDCALL error, but ddraw has a more
1030 * specific error. But since wined3d returns that error in this only occasion,
1031 * keep d3d8 and d3d9 free from the return value override. There are many different
1032 * places where d3d8/9 would have to catch the DDERR_SURFACEBUSY, it is much easier
1033 * to do it in one place in ddraw.
1035 case WINED3DERR_INVALIDCALL: return DDERR_SURFACEBUSY;
1036 default: return hr;
1040 if (surface->surface_desc.ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE)
1042 if (flags & DDLOCK_READONLY)
1043 SetRectEmpty(&surface->ddraw->primary_lock);
1044 else if (rect)
1045 surface->ddraw->primary_lock = *rect;
1046 else
1047 SetRect(&surface->ddraw->primary_lock, 0, 0, surface->surface_desc.dwWidth, surface->surface_desc.dwHeight);
1050 /* Windows does not set DDSD_LPSURFACE on locked surfaces. */
1051 DD_STRUCT_COPY_BYSIZE_(surface_desc, &surface->surface_desc, surface_desc_size, surface->surface_desc.dwSize);
1052 surface_desc->lpSurface = map_desc.data;
1054 TRACE("locked surface returning description :\n");
1055 if (TRACE_ON(ddraw))
1056 DDRAW_dump_surface_desc(surface_desc);
1058 wined3d_mutex_unlock();
1060 return DD_OK;
1063 static BOOL surface_validate_lock_desc(struct ddraw_surface *surface,
1064 const DDSURFACEDESC *desc, unsigned int *size)
1066 if (!desc)
1067 return FALSE;
1069 if (desc->dwSize == sizeof(DDSURFACEDESC) || desc->dwSize == sizeof(DDSURFACEDESC2))
1071 *size = desc->dwSize;
1072 return TRUE;
1075 if (surface->version == 7
1076 && surface->surface_desc.ddsCaps.dwCaps & DDSCAPS_TEXTURE
1077 && !(surface->surface_desc.ddsCaps.dwCaps & DDSCAPS_VIDEOMEMORY))
1079 if (desc->dwSize >= sizeof(DDSURFACEDESC2))
1080 *size = sizeof(DDSURFACEDESC2);
1081 else
1082 *size = sizeof(DDSURFACEDESC);
1083 return TRUE;
1086 WARN("Invalid structure size %u.\n", desc->dwSize);
1087 return FALSE;
1090 static HRESULT WINAPI ddraw_surface7_Lock(IDirectDrawSurface7 *iface,
1091 RECT *rect, DDSURFACEDESC2 *surface_desc, DWORD flags, HANDLE h)
1093 struct ddraw_surface *surface = impl_from_IDirectDrawSurface7(iface);
1094 unsigned int surface_desc_size;
1096 TRACE("iface %p, rect %s, surface_desc %p, flags %#x, h %p.\n",
1097 iface, wine_dbgstr_rect(rect), surface_desc, flags, h);
1099 if (!surface_validate_lock_desc(surface, (DDSURFACEDESC *)surface_desc, &surface_desc_size))
1100 return DDERR_INVALIDPARAMS;
1102 return surface_lock(surface, rect, surface_desc, surface_desc_size, flags, h);
1105 static HRESULT WINAPI ddraw_surface4_Lock(IDirectDrawSurface4 *iface, RECT *rect,
1106 DDSURFACEDESC2 *surface_desc, DWORD flags, HANDLE h)
1108 struct ddraw_surface *surface = impl_from_IDirectDrawSurface4(iface);
1109 unsigned int surface_desc_size;
1111 TRACE("iface %p, rect %s, surface_desc %p, flags %#x, h %p.\n",
1112 iface, wine_dbgstr_rect(rect), surface_desc, flags, h);
1114 if (!surface_validate_lock_desc(surface, (DDSURFACEDESC *)surface_desc, &surface_desc_size))
1115 return DDERR_INVALIDPARAMS;
1117 return surface_lock(surface, rect, surface_desc, surface_desc_size, flags, h);
1120 static HRESULT WINAPI ddraw_surface3_Lock(IDirectDrawSurface3 *iface, RECT *rect,
1121 DDSURFACEDESC *surface_desc, DWORD flags, HANDLE h)
1123 struct ddraw_surface *surface = impl_from_IDirectDrawSurface3(iface);
1124 unsigned int surface_desc_size;
1125 DDSURFACEDESC2 surface_desc2;
1126 HRESULT hr;
1128 TRACE("iface %p, rect %s, surface_desc %p, flags %#x, h %p.\n",
1129 iface, wine_dbgstr_rect(rect), surface_desc, flags, h);
1131 if (!surface_validate_lock_desc(surface, surface_desc, &surface_desc_size))
1132 return DDERR_INVALIDPARAMS;
1134 surface_desc2.dwSize = surface_desc->dwSize;
1135 surface_desc2.dwFlags = 0;
1136 hr = surface_lock(surface, rect, &surface_desc2, surface_desc_size, flags, h);
1137 DDSD2_to_DDSD(&surface_desc2, surface_desc);
1138 surface_desc->dwSize = surface_desc2.dwSize;
1139 return hr;
1142 static HRESULT WINAPI ddraw_surface2_Lock(IDirectDrawSurface2 *iface, RECT *rect,
1143 DDSURFACEDESC *surface_desc, DWORD flags, HANDLE h)
1145 struct ddraw_surface *surface = impl_from_IDirectDrawSurface2(iface);
1146 unsigned int surface_desc_size;
1147 DDSURFACEDESC2 surface_desc2;
1148 HRESULT hr;
1150 TRACE("iface %p, rect %s, surface_desc %p, flags %#x, h %p.\n",
1151 iface, wine_dbgstr_rect(rect), surface_desc, flags, h);
1153 if (!surface_validate_lock_desc(surface, surface_desc, &surface_desc_size))
1154 return DDERR_INVALIDPARAMS;
1156 surface_desc2.dwSize = surface_desc->dwSize;
1157 surface_desc2.dwFlags = 0;
1158 hr = surface_lock(surface, rect, &surface_desc2, surface_desc_size, flags, h);
1159 DDSD2_to_DDSD(&surface_desc2, surface_desc);
1160 surface_desc->dwSize = surface_desc2.dwSize;
1161 return hr;
1164 static HRESULT WINAPI ddraw_surface1_Lock(IDirectDrawSurface *iface, RECT *rect,
1165 DDSURFACEDESC *surface_desc, DWORD flags, HANDLE h)
1167 struct ddraw_surface *surface = impl_from_IDirectDrawSurface(iface);
1168 unsigned int surface_desc_size;
1169 DDSURFACEDESC2 surface_desc2;
1170 HRESULT hr;
1172 TRACE("iface %p, rect %s, surface_desc %p, flags %#x, h %p.\n",
1173 iface, wine_dbgstr_rect(rect), surface_desc, flags, h);
1175 if (!surface_validate_lock_desc(surface, surface_desc, &surface_desc_size))
1176 return DDERR_INVALIDPARAMS;
1178 surface_desc2.dwSize = surface_desc->dwSize;
1179 surface_desc2.dwFlags = 0;
1180 hr = surface_lock(surface, rect, &surface_desc2, surface_desc_size, flags, h);
1181 DDSD2_to_DDSD(&surface_desc2, surface_desc);
1182 surface_desc->dwSize = surface_desc2.dwSize;
1183 return hr;
1186 /*****************************************************************************
1187 * IDirectDrawSurface7::Unlock
1189 * Unlocks an locked surface
1191 * Params:
1192 * Rect: Not used by this implementation
1194 * Returns:
1195 * D3D_OK on success, error code otherwise.
1197 *****************************************************************************/
1198 static HRESULT WINAPI DECLSPEC_HOTPATCH ddraw_surface7_Unlock(IDirectDrawSurface7 *iface, RECT *pRect)
1200 struct ddraw_surface *surface = impl_from_IDirectDrawSurface7(iface);
1201 HRESULT hr;
1203 TRACE("iface %p, rect %s.\n", iface, wine_dbgstr_rect(pRect));
1205 wined3d_mutex_lock();
1206 hr = wined3d_resource_unmap(wined3d_texture_get_resource(surface->wined3d_texture), surface->sub_resource_idx);
1207 if (SUCCEEDED(hr) && surface->surface_desc.ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE)
1208 hr = ddraw_surface_update_frontbuffer(surface, &surface->ddraw->primary_lock, FALSE, 0);
1209 wined3d_mutex_unlock();
1211 return hr;
1214 static HRESULT WINAPI DECLSPEC_HOTPATCH ddraw_surface4_Unlock(IDirectDrawSurface4 *iface, RECT *pRect)
1216 struct ddraw_surface *surface = impl_from_IDirectDrawSurface4(iface);
1218 TRACE("iface %p, rect %p.\n", iface, pRect);
1220 return ddraw_surface7_Unlock(&surface->IDirectDrawSurface7_iface, pRect);
1223 static HRESULT WINAPI DECLSPEC_HOTPATCH ddraw_surface3_Unlock(IDirectDrawSurface3 *iface, void *data)
1225 struct ddraw_surface *surface = impl_from_IDirectDrawSurface3(iface);
1227 TRACE("iface %p, data %p.\n", iface, data);
1229 /* data might not be the LPRECT of later versions, so drop it. */
1230 return ddraw_surface7_Unlock(&surface->IDirectDrawSurface7_iface, NULL);
1233 static HRESULT WINAPI DECLSPEC_HOTPATCH ddraw_surface2_Unlock(IDirectDrawSurface2 *iface, void *data)
1235 struct ddraw_surface *surface = impl_from_IDirectDrawSurface2(iface);
1237 TRACE("iface %p, data %p.\n", iface, data);
1239 /* data might not be the LPRECT of later versions, so drop it. */
1240 return ddraw_surface7_Unlock(&surface->IDirectDrawSurface7_iface, NULL);
1243 static HRESULT WINAPI DECLSPEC_HOTPATCH ddraw_surface1_Unlock(IDirectDrawSurface *iface, void *data)
1245 struct ddraw_surface *surface = impl_from_IDirectDrawSurface(iface);
1247 TRACE("iface %p, data %p.\n", iface, data);
1249 /* data might not be the LPRECT of later versions, so drop it. */
1250 return ddraw_surface7_Unlock(&surface->IDirectDrawSurface7_iface, NULL);
1253 static unsigned int ddraw_swap_interval_from_flags(DWORD flags)
1255 if (flags & DDFLIP_NOVSYNC)
1256 return 0;
1258 switch (flags & (DDFLIP_INTERVAL2 | DDFLIP_INTERVAL3 | DDFLIP_INTERVAL4))
1260 case DDFLIP_INTERVAL2:
1261 return 2;
1262 case DDFLIP_INTERVAL3:
1263 return 3;
1264 case DDFLIP_INTERVAL4:
1265 return 4;
1266 default:
1267 return 1;
1271 static HRESULT WINAPI DECLSPEC_HOTPATCH ddraw_surface7_Flip(IDirectDrawSurface7 *iface,
1272 IDirectDrawSurface7 *src, DWORD flags)
1274 struct ddraw_surface *dst_impl = impl_from_IDirectDrawSurface7(iface);
1275 struct ddraw_surface *src_impl = unsafe_impl_from_IDirectDrawSurface7(src);
1276 struct wined3d_rendertarget_view *tmp_rtv, *src_rtv, *rtv;
1277 struct ddraw_texture *ddraw_texture, *prev_ddraw_texture;
1278 DDSCAPS2 caps = {DDSCAPS_FLIP, 0, 0, {0}};
1279 struct wined3d_texture *texture;
1280 IDirectDrawSurface7 *current;
1281 HRESULT hr;
1283 TRACE("iface %p, src %p, flags %#x.\n", iface, src, flags);
1285 if (src == iface || !(dst_impl->surface_desc.ddsCaps.dwCaps & (DDSCAPS_FRONTBUFFER | DDSCAPS_OVERLAY)))
1286 return DDERR_NOTFLIPPABLE;
1288 if (IDirectDrawSurface7_IsLost(iface) == DDERR_SURFACELOST)
1289 return DDERR_SURFACELOST;
1291 wined3d_mutex_lock();
1293 if ((dst_impl->surface_desc.ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE)
1294 && !(dst_impl->ddraw->cooperative_level & DDSCL_EXCLUSIVE))
1296 WARN("Not in exclusive mode.\n");
1297 wined3d_mutex_unlock();
1298 return DDERR_NOEXCLUSIVEMODE;
1301 tmp_rtv = ddraw_surface_get_rendertarget_view(dst_impl);
1302 if (dst_impl->sub_resource_idx)
1303 ERR("Invalid sub-resource index %u on surface %p.\n", dst_impl->sub_resource_idx, dst_impl);
1304 texture = dst_impl->wined3d_texture;
1305 rtv = wined3d_device_get_rendertarget_view(dst_impl->ddraw->wined3d_device, 0);
1306 ddraw_texture = wined3d_texture_get_parent(dst_impl->wined3d_texture);
1308 if (src_impl)
1310 for (current = iface; current != src;)
1312 if (FAILED(hr = ddraw_surface7_GetAttachedSurface(current, &caps, &current)))
1314 WARN("Surface %p is not on the same flip chain as surface %p.\n", src, iface);
1315 wined3d_mutex_unlock();
1316 return DDERR_NOTFLIPPABLE;
1318 ddraw_surface7_Release(current);
1319 if (current == iface)
1321 WARN("Surface %p is not on the same flip chain as surface %p.\n", src, iface);
1322 wined3d_mutex_unlock();
1323 return DDERR_NOTFLIPPABLE;
1327 src_rtv = ddraw_surface_get_rendertarget_view(src_impl);
1328 if (rtv == dst_impl->wined3d_rtv)
1329 wined3d_device_set_rendertarget_view(dst_impl->ddraw->wined3d_device, 0, src_rtv, FALSE);
1330 wined3d_rendertarget_view_set_parent(src_rtv, dst_impl);
1331 dst_impl->wined3d_rtv = src_rtv;
1332 wined3d_texture_set_sub_resource_parent(src_impl->wined3d_texture, 0, dst_impl);
1333 prev_ddraw_texture = wined3d_texture_get_parent(src_impl->wined3d_texture);
1334 wined3d_resource_set_parent(wined3d_texture_get_resource(src_impl->wined3d_texture), ddraw_texture);
1335 if (src_impl->sub_resource_idx)
1336 ERR("Invalid sub-resource index %u on surface %p.\n", src_impl->sub_resource_idx, src_impl);
1337 dst_impl->wined3d_texture = src_impl->wined3d_texture;
1338 ddraw_texture = prev_ddraw_texture;
1340 else
1342 for (current = iface;;)
1344 if (FAILED(hr = ddraw_surface7_GetAttachedSurface(current, &caps, &current)))
1346 ERR("Can't find a flip target\n");
1347 wined3d_mutex_unlock();
1348 return DDERR_NOTFLIPPABLE; /* Unchecked */
1350 ddraw_surface7_Release(current);
1351 if (current == iface)
1353 dst_impl = impl_from_IDirectDrawSurface7(iface);
1354 break;
1357 src_impl = impl_from_IDirectDrawSurface7(current);
1358 src_rtv = ddraw_surface_get_rendertarget_view(src_impl);
1359 if (rtv == dst_impl->wined3d_rtv)
1360 wined3d_device_set_rendertarget_view(dst_impl->ddraw->wined3d_device, 0, src_rtv, FALSE);
1361 wined3d_rendertarget_view_set_parent(src_rtv, dst_impl);
1362 dst_impl->wined3d_rtv = src_rtv;
1363 wined3d_texture_set_sub_resource_parent(src_impl->wined3d_texture, 0, dst_impl);
1364 prev_ddraw_texture = wined3d_texture_get_parent(src_impl->wined3d_texture);
1365 wined3d_resource_set_parent(wined3d_texture_get_resource(src_impl->wined3d_texture), ddraw_texture);
1366 ddraw_texture = prev_ddraw_texture;
1367 if (src_impl->sub_resource_idx)
1368 ERR("Invalid sub-resource index %u on surface %p.\n", src_impl->sub_resource_idx, src_impl);
1369 dst_impl->wined3d_texture = src_impl->wined3d_texture;
1370 dst_impl = src_impl;
1374 /* We don't have to worry about potential texture bindings, since
1375 * flippable surfaces can never be textures. */
1376 if (rtv == src_impl->wined3d_rtv)
1377 wined3d_device_set_rendertarget_view(dst_impl->ddraw->wined3d_device, 0, tmp_rtv, FALSE);
1378 wined3d_rendertarget_view_set_parent(tmp_rtv, src_impl);
1379 src_impl->wined3d_rtv = tmp_rtv;
1380 wined3d_texture_set_sub_resource_parent(texture, 0, src_impl);
1381 wined3d_resource_set_parent(wined3d_texture_get_resource(texture), ddraw_texture);
1382 src_impl->wined3d_texture = texture;
1384 if (flags & ~(DDFLIP_NOVSYNC | DDFLIP_INTERVAL2 | DDFLIP_INTERVAL3 | DDFLIP_INTERVAL4))
1386 static UINT once;
1387 if (!once++)
1388 FIXME("Ignoring flags %#x.\n", flags);
1389 else
1390 WARN("Ignoring flags %#x.\n", flags);
1393 if (dst_impl->surface_desc.ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE)
1394 hr = ddraw_surface_update_frontbuffer(dst_impl, NULL, FALSE, ddraw_swap_interval_from_flags(flags));
1395 else
1396 hr = DD_OK;
1398 wined3d_mutex_unlock();
1400 return hr;
1403 static HRESULT WINAPI DECLSPEC_HOTPATCH ddraw_surface4_Flip(IDirectDrawSurface4 *iface,
1404 IDirectDrawSurface4 *src, DWORD flags)
1406 struct ddraw_surface *surface = impl_from_IDirectDrawSurface4(iface);
1407 struct ddraw_surface *src_impl = unsafe_impl_from_IDirectDrawSurface4(src);
1409 TRACE("iface %p, src %p, flags %#x.\n", iface, src, flags);
1411 return ddraw_surface7_Flip(&surface->IDirectDrawSurface7_iface,
1412 src_impl ? &src_impl->IDirectDrawSurface7_iface : NULL, flags);
1415 static HRESULT WINAPI DECLSPEC_HOTPATCH ddraw_surface3_Flip(IDirectDrawSurface3 *iface,
1416 IDirectDrawSurface3 *src, DWORD flags)
1418 struct ddraw_surface *surface = impl_from_IDirectDrawSurface3(iface);
1419 struct ddraw_surface *src_impl = unsafe_impl_from_IDirectDrawSurface3(src);
1421 TRACE("iface %p, src %p, flags %#x.\n", iface, src, flags);
1423 return ddraw_surface7_Flip(&surface->IDirectDrawSurface7_iface,
1424 src_impl ? &src_impl->IDirectDrawSurface7_iface : NULL, flags);
1427 static HRESULT WINAPI DECLSPEC_HOTPATCH ddraw_surface2_Flip(IDirectDrawSurface2 *iface,
1428 IDirectDrawSurface2 *src, DWORD flags)
1430 struct ddraw_surface *surface = impl_from_IDirectDrawSurface2(iface);
1431 struct ddraw_surface *src_impl = unsafe_impl_from_IDirectDrawSurface2(src);
1433 TRACE("iface %p, src %p, flags %#x.\n", iface, src, flags);
1435 return ddraw_surface7_Flip(&surface->IDirectDrawSurface7_iface,
1436 src_impl ? &src_impl->IDirectDrawSurface7_iface : NULL, flags);
1439 static HRESULT WINAPI DECLSPEC_HOTPATCH ddraw_surface1_Flip(IDirectDrawSurface *iface,
1440 IDirectDrawSurface *src, DWORD flags)
1442 struct ddraw_surface *surface = impl_from_IDirectDrawSurface(iface);
1443 struct ddraw_surface *src_impl = unsafe_impl_from_IDirectDrawSurface(src);
1445 TRACE("iface %p, src %p, flags %#x.\n", iface, src, flags);
1447 return ddraw_surface7_Flip(&surface->IDirectDrawSurface7_iface,
1448 src_impl ? &src_impl->IDirectDrawSurface7_iface : NULL, flags);
1451 static HRESULT ddraw_surface_blt(struct ddraw_surface *dst_surface, const RECT *dst_rect,
1452 struct ddraw_surface *src_surface, const RECT *src_rect, DWORD flags, DWORD fill_colour,
1453 const struct wined3d_blt_fx *fx, enum wined3d_texture_filter_type filter)
1455 struct wined3d_device *wined3d_device = dst_surface->ddraw->wined3d_device;
1456 struct wined3d_color colour;
1457 DWORD wined3d_flags;
1459 if (flags & DDBLT_COLORFILL)
1461 wined3d_flags = WINED3DCLEAR_TARGET;
1462 if (!(flags & DDBLT_ASYNC))
1463 wined3d_flags |= WINED3DCLEAR_SYNCHRONOUS;
1465 if (!wined3d_colour_from_ddraw_colour(&dst_surface->surface_desc.u4.ddpfPixelFormat,
1466 dst_surface->palette, fill_colour, &colour))
1467 return DDERR_INVALIDPARAMS;
1469 return wined3d_device_clear_rendertarget_view(wined3d_device,
1470 ddraw_surface_get_rendertarget_view(dst_surface),
1471 dst_rect, wined3d_flags, &colour, 0.0f, 0);
1474 if (flags & DDBLT_DEPTHFILL)
1476 wined3d_flags = WINED3DCLEAR_ZBUFFER;
1477 if (!(flags & DDBLT_ASYNC))
1478 wined3d_flags |= WINED3DCLEAR_SYNCHRONOUS;
1480 if (!wined3d_colour_from_ddraw_colour(&dst_surface->surface_desc.u4.ddpfPixelFormat,
1481 dst_surface->palette, fill_colour, &colour))
1482 return DDERR_INVALIDPARAMS;
1484 return wined3d_device_clear_rendertarget_view(wined3d_device,
1485 ddraw_surface_get_rendertarget_view(dst_surface),
1486 dst_rect, wined3d_flags, NULL, colour.r, 0);
1489 wined3d_flags = flags & ~DDBLT_ASYNC;
1490 if (wined3d_flags & ~WINED3D_BLT_MASK)
1492 FIXME("Unhandled flags %#x.\n", flags);
1493 return E_NOTIMPL;
1496 if (!(flags & DDBLT_ASYNC))
1497 wined3d_flags |= WINED3D_BLT_SYNCHRONOUS;
1499 return wined3d_texture_blt(dst_surface->wined3d_texture, dst_surface->sub_resource_idx, dst_rect,
1500 src_surface->wined3d_texture, src_surface->sub_resource_idx, src_rect, wined3d_flags, fx, filter);
1503 static HRESULT ddraw_surface_blt_clipped(struct ddraw_surface *dst_surface, const RECT *dst_rect_in,
1504 struct ddraw_surface *src_surface, const RECT *src_rect_in, DWORD flags, DWORD fill_colour,
1505 const struct wined3d_blt_fx *fx, enum wined3d_texture_filter_type filter)
1507 RECT src_rect, dst_rect;
1508 float scale_x, scale_y;
1509 const RECT *clip_rect;
1510 UINT clip_list_size;
1511 RGNDATA *clip_list;
1512 HRESULT hr = DD_OK;
1513 UINT i;
1515 if (!dst_rect_in)
1516 SetRect(&dst_rect, 0, 0, dst_surface->surface_desc.dwWidth,
1517 dst_surface->surface_desc.dwHeight);
1518 else
1519 dst_rect = *dst_rect_in;
1521 if (IsRectEmpty(&dst_rect))
1522 return DDERR_INVALIDRECT;
1524 if (src_surface)
1526 if (!src_rect_in)
1527 SetRect(&src_rect, 0, 0, src_surface->surface_desc.dwWidth,
1528 src_surface->surface_desc.dwHeight);
1529 else
1530 src_rect = *src_rect_in;
1532 if (IsRectEmpty(&src_rect))
1533 return DDERR_INVALIDRECT;
1535 else
1537 SetRectEmpty(&src_rect);
1540 if (!dst_surface->clipper)
1542 if (src_surface && src_surface->surface_desc.ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE)
1543 hr = ddraw_surface_update_frontbuffer(src_surface, &src_rect, TRUE, 0);
1544 if (SUCCEEDED(hr))
1545 hr = ddraw_surface_blt(dst_surface, &dst_rect, src_surface, &src_rect, flags, fill_colour, fx, filter);
1546 if (SUCCEEDED(hr) && (dst_surface->surface_desc.ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE))
1547 hr = ddraw_surface_update_frontbuffer(dst_surface, &dst_rect, FALSE, 0);
1549 return hr;
1552 scale_x = (float)(src_rect.right - src_rect.left) / (float)(dst_rect.right - dst_rect.left);
1553 scale_y = (float)(src_rect.bottom - src_rect.top) / (float)(dst_rect.bottom - dst_rect.top);
1555 if (FAILED(hr = IDirectDrawClipper_GetClipList(&dst_surface->clipper->IDirectDrawClipper_iface,
1556 &dst_rect, NULL, &clip_list_size)))
1558 WARN("Failed to get clip list size, hr %#x.\n", hr);
1559 return hr;
1562 if (!(clip_list = heap_alloc(clip_list_size)))
1564 WARN("Failed to allocate clip list.\n");
1565 return E_OUTOFMEMORY;
1568 if (FAILED(hr = IDirectDrawClipper_GetClipList(&dst_surface->clipper->IDirectDrawClipper_iface,
1569 &dst_rect, clip_list, &clip_list_size)))
1571 WARN("Failed to get clip list, hr %#x.\n", hr);
1572 heap_free(clip_list);
1573 return hr;
1576 clip_rect = (RECT *)clip_list->Buffer;
1577 for (i = 0; i < clip_list->rdh.nCount; ++i)
1579 RECT src_rect_clipped = src_rect;
1581 if (src_surface)
1583 src_rect_clipped.left += (LONG)((clip_rect[i].left - dst_rect.left) * scale_x);
1584 src_rect_clipped.top += (LONG)((clip_rect[i].top - dst_rect.top) * scale_y);
1585 src_rect_clipped.right -= (LONG)((dst_rect.right - clip_rect[i].right) * scale_x);
1586 src_rect_clipped.bottom -= (LONG)((dst_rect.bottom - clip_rect[i].bottom) * scale_y);
1588 if (src_surface->surface_desc.ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE)
1590 if (FAILED(hr = ddraw_surface_update_frontbuffer(src_surface, &src_rect_clipped, TRUE, 0)))
1591 break;
1595 if (FAILED(hr = ddraw_surface_blt(dst_surface, &clip_rect[i],
1596 src_surface, &src_rect_clipped, flags, fill_colour, fx, filter)))
1597 break;
1599 if (dst_surface->surface_desc.ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE)
1601 if (FAILED(hr = ddraw_surface_update_frontbuffer(dst_surface, &clip_rect[i], FALSE, 0)))
1602 break;
1606 heap_free(clip_list);
1607 return hr;
1610 /*****************************************************************************
1611 * IDirectDrawSurface7::Blt
1613 * Performs a blit on the surface
1615 * Params:
1616 * DestRect: Destination rectangle, can be NULL
1617 * SrcSurface: Source surface, can be NULL
1618 * SrcRect: Source rectangle, can be NULL
1619 * Flags: Blt flags
1620 * DDBltFx: Some extended blt parameters, connected to the flags
1622 * Returns:
1623 * D3D_OK on success, error code otherwise.
1625 *****************************************************************************/
1626 static HRESULT WINAPI DECLSPEC_HOTPATCH ddraw_surface7_Blt(IDirectDrawSurface7 *iface, RECT *dst_rect,
1627 IDirectDrawSurface7 *src_surface, RECT *src_rect, DWORD flags, DDBLTFX *fx)
1629 struct ddraw_surface *dst_impl = impl_from_IDirectDrawSurface7(iface);
1630 struct ddraw_surface *src_impl = unsafe_impl_from_IDirectDrawSurface7(src_surface);
1631 struct wined3d_blt_fx wined3d_fx;
1632 DWORD unsupported_flags;
1633 DWORD fill_colour = 0;
1634 HRESULT hr = DD_OK;
1635 DDBLTFX rop_fx;
1637 TRACE("iface %p, dst_rect %s, src_surface %p, src_rect %s, flags %#x, fx %p.\n",
1638 iface, wine_dbgstr_rect(dst_rect), src_surface, wine_dbgstr_rect(src_rect), flags, fx);
1640 unsupported_flags = DDBLT_ALPHADEST
1641 | DDBLT_ALPHADESTCONSTOVERRIDE
1642 | DDBLT_ALPHADESTNEG
1643 | DDBLT_ALPHADESTSURFACEOVERRIDE
1644 | DDBLT_ALPHAEDGEBLEND
1645 | DDBLT_ALPHASRC
1646 | DDBLT_ALPHASRCCONSTOVERRIDE
1647 | DDBLT_ALPHASRCNEG
1648 | DDBLT_ALPHASRCSURFACEOVERRIDE
1649 | DDBLT_ZBUFFER
1650 | DDBLT_ZBUFFERDESTCONSTOVERRIDE
1651 | DDBLT_ZBUFFERDESTOVERRIDE
1652 | DDBLT_ZBUFFERSRCCONSTOVERRIDE
1653 | DDBLT_ZBUFFERSRCOVERRIDE;
1654 if (flags & unsupported_flags)
1656 WARN("Ignoring unsupported flags %#x.\n", flags & unsupported_flags);
1657 flags &= ~unsupported_flags;
1660 if ((flags & DDBLT_KEYSRCOVERRIDE) && (!fx || flags & DDBLT_KEYSRC))
1662 WARN("Invalid source color key parameters, returning DDERR_INVALIDPARAMS\n");
1663 return DDERR_INVALIDPARAMS;
1666 if ((flags & DDBLT_KEYDESTOVERRIDE) && (!fx || flags & DDBLT_KEYDEST))
1668 WARN("Invalid destination color key parameters, returning DDERR_INVALIDPARAMS\n");
1669 return DDERR_INVALIDPARAMS;
1672 if (flags & DDBLT_DDROPS)
1674 FIXME("DDBLT_DDROPS not implemented.\n");
1675 if (fx)
1676 FIXME(" rop %#x, pattern %p.\n", fx->dwDDROP, fx->u5.lpDDSPattern);
1677 return DDERR_NORASTEROPHW;
1680 wined3d_mutex_lock();
1682 if (flags & (DDBLT_COLORFILL | DDBLT_DEPTHFILL))
1684 if (flags & DDBLT_ROP)
1686 wined3d_mutex_unlock();
1687 WARN("DDBLT_ROP used with DDBLT_COLORFILL or DDBLT_DEPTHFILL, returning DDERR_INVALIDPARAMS.\n");
1688 return DDERR_INVALIDPARAMS;
1690 if (src_impl)
1692 wined3d_mutex_unlock();
1693 WARN("Depth or colorfill is not compatible with source surfaces, returning DDERR_INVALIDPARAMS\n");
1694 return DDERR_INVALIDPARAMS;
1696 if (!fx)
1698 wined3d_mutex_unlock();
1699 WARN("Depth or colorfill used with NULL fx, returning DDERR_INVALIDPARAMS.\n");
1700 return DDERR_INVALIDPARAMS;
1703 if ((flags & (DDBLT_COLORFILL | DDBLT_DEPTHFILL)) == (DDBLT_COLORFILL | DDBLT_DEPTHFILL))
1704 flags &= ~DDBLT_DEPTHFILL;
1706 if ((dst_impl->surface_desc.ddsCaps.dwCaps & DDSCAPS_ZBUFFER) && (flags & DDBLT_COLORFILL))
1708 wined3d_mutex_unlock();
1709 WARN("DDBLT_COLORFILL used on a depth buffer, returning DDERR_INVALIDPARAMS.\n");
1710 return DDERR_INVALIDPARAMS;
1712 if (!(dst_impl->surface_desc.ddsCaps.dwCaps & DDSCAPS_ZBUFFER) && (flags & DDBLT_DEPTHFILL))
1714 wined3d_mutex_unlock();
1715 WARN("DDBLT_DEPTHFILL used on a color buffer, returning DDERR_INVALIDPARAMS.\n");
1716 return DDERR_INVALIDPARAMS;
1720 if (flags & DDBLT_ROP)
1722 if (!fx)
1724 wined3d_mutex_unlock();
1725 WARN("DDBLT_ROP used with NULL fx, returning DDERR_INVALIDPARAMS.\n");
1726 return DDERR_INVALIDPARAMS;
1729 if (src_impl && src_rect
1730 && ((ULONG)src_rect->left >= src_rect->right || src_rect->right > src_impl->surface_desc.dwWidth
1731 || (ULONG)src_rect->top >= src_rect->bottom || src_rect->bottom > src_impl->surface_desc.dwHeight))
1733 WARN("Invalid source rectangle.\n");
1734 return DDERR_INVALIDRECT;
1737 flags &= ~DDBLT_ROP;
1738 switch (fx->dwROP)
1740 case SRCCOPY:
1741 break;
1743 case WHITENESS:
1744 case BLACKNESS:
1745 rop_fx = *fx;
1747 if (fx->dwROP == WHITENESS)
1748 rop_fx.u5.dwFillColor = 0xffffffff;
1749 else
1750 rop_fx.u5.dwFillColor = 0;
1752 if (dst_impl->surface_desc.ddsCaps.dwCaps & DDSCAPS_ZBUFFER)
1753 flags |= DDBLT_DEPTHFILL;
1754 else
1755 flags |= DDBLT_COLORFILL;
1757 fx = &rop_fx;
1758 break;
1760 default:
1761 wined3d_mutex_unlock();
1762 WARN("Unsupported ROP %#x used, returning DDERR_NORASTEROPHW.\n", fx->dwROP);
1763 return DDERR_NORASTEROPHW;
1767 if (!(flags & (DDBLT_COLORFILL | DDBLT_DEPTHFILL)) && !src_impl)
1769 WARN("No source surface.\n");
1770 return DDERR_INVALIDPARAMS;
1773 if (flags & DDBLT_KEYSRC && (!src_impl || !(src_impl->surface_desc.dwFlags & DDSD_CKSRCBLT)))
1775 WARN("DDBLT_KEYSRC blit without color key in surface, returning DDERR_INVALIDPARAMS\n");
1776 wined3d_mutex_unlock();
1777 return DDERR_INVALIDPARAMS;
1779 if (flags & DDBLT_KEYDEST && !(dst_impl->surface_desc.dwFlags & DDSD_CKDESTBLT))
1781 WARN("DDBLT_KEYDEST blit without color key in surface, returning DDERR_INVALIDPARAMS\n");
1782 wined3d_mutex_unlock();
1783 return DDERR_INVALIDPARAMS;
1786 if (fx)
1788 wined3d_fx.fx = fx->dwDDFX;
1789 fill_colour = fx->u5.dwFillColor;
1790 wined3d_fx.dst_color_key.color_space_low_value = fx->ddckDestColorkey.dwColorSpaceLowValue;
1791 wined3d_fx.dst_color_key.color_space_high_value = fx->ddckDestColorkey.dwColorSpaceHighValue;
1792 wined3d_fx.src_color_key.color_space_low_value = fx->ddckSrcColorkey.dwColorSpaceLowValue;
1793 wined3d_fx.src_color_key.color_space_high_value = fx->ddckSrcColorkey.dwColorSpaceHighValue;
1796 hr = ddraw_surface_blt_clipped(dst_impl, dst_rect, src_impl,
1797 src_rect, flags, fill_colour, fx ? &wined3d_fx : NULL, WINED3D_TEXF_LINEAR);
1799 wined3d_mutex_unlock();
1800 switch(hr)
1802 case WINED3DERR_NOTAVAILABLE: return DDERR_UNSUPPORTED;
1803 default: return hr;
1807 static HRESULT WINAPI DECLSPEC_HOTPATCH ddraw_surface4_Blt(IDirectDrawSurface4 *iface, RECT *dst_rect,
1808 IDirectDrawSurface4 *src_surface, RECT *src_rect, DWORD flags, DDBLTFX *fx)
1810 struct ddraw_surface *dst = impl_from_IDirectDrawSurface4(iface);
1811 struct ddraw_surface *src = unsafe_impl_from_IDirectDrawSurface4(src_surface);
1813 TRACE("iface %p, dst_rect %s, src_surface %p, src_rect %s, flags %#x, fx %p.\n",
1814 iface, wine_dbgstr_rect(dst_rect), src_surface, wine_dbgstr_rect(src_rect), flags, fx);
1816 return ddraw_surface7_Blt(&dst->IDirectDrawSurface7_iface, dst_rect,
1817 src ? &src->IDirectDrawSurface7_iface : NULL, src_rect, flags, fx);
1820 static HRESULT WINAPI DECLSPEC_HOTPATCH ddraw_surface3_Blt(IDirectDrawSurface3 *iface, RECT *dst_rect,
1821 IDirectDrawSurface3 *src_surface, RECT *src_rect, DWORD flags, DDBLTFX *fx)
1823 struct ddraw_surface *dst = impl_from_IDirectDrawSurface3(iface);
1824 struct ddraw_surface *src_impl = unsafe_impl_from_IDirectDrawSurface3(src_surface);
1826 TRACE("iface %p, dst_rect %s, src_surface %p, src_rect %s, flags %#x, fx %p.\n",
1827 iface, wine_dbgstr_rect(dst_rect), src_surface, wine_dbgstr_rect(src_rect), flags, fx);
1829 return ddraw_surface7_Blt(&dst->IDirectDrawSurface7_iface, dst_rect,
1830 src_impl ? &src_impl->IDirectDrawSurface7_iface : NULL, src_rect, flags, fx);
1833 static HRESULT WINAPI DECLSPEC_HOTPATCH ddraw_surface2_Blt(IDirectDrawSurface2 *iface, RECT *dst_rect,
1834 IDirectDrawSurface2 *src_surface, RECT *src_rect, DWORD flags, DDBLTFX *fx)
1836 struct ddraw_surface *dst = impl_from_IDirectDrawSurface2(iface);
1837 struct ddraw_surface *src_impl = unsafe_impl_from_IDirectDrawSurface2(src_surface);
1839 TRACE("iface %p, dst_rect %s, src_surface %p, src_rect %s, flags %#x, fx %p.\n",
1840 iface, wine_dbgstr_rect(dst_rect), src_surface, wine_dbgstr_rect(src_rect), flags, fx);
1842 return ddraw_surface7_Blt(&dst->IDirectDrawSurface7_iface, dst_rect,
1843 src_impl ? &src_impl->IDirectDrawSurface7_iface : NULL, src_rect, flags, fx);
1846 static HRESULT WINAPI DECLSPEC_HOTPATCH ddraw_surface1_Blt(IDirectDrawSurface *iface, RECT *dst_rect,
1847 IDirectDrawSurface *src_surface, RECT *src_rect, DWORD flags, DDBLTFX *fx)
1849 struct ddraw_surface *dst = impl_from_IDirectDrawSurface(iface);
1850 struct ddraw_surface *src_impl = unsafe_impl_from_IDirectDrawSurface(src_surface);
1852 TRACE("iface %p, dst_rect %s, src_surface %p, src_rect %s, flags %#x, fx %p.\n",
1853 iface, wine_dbgstr_rect(dst_rect), src_surface, wine_dbgstr_rect(src_rect), flags, fx);
1855 return ddraw_surface7_Blt(&dst->IDirectDrawSurface7_iface, dst_rect,
1856 src_impl ? &src_impl->IDirectDrawSurface7_iface : NULL, src_rect, flags, fx);
1859 /*****************************************************************************
1860 * IDirectDrawSurface7::AddAttachedSurface
1862 * Attaches a surface to another surface. How the surface attachments work
1863 * is not totally understood yet, and this method is prone to problems.
1864 * The surface that is attached is AddRef-ed.
1866 * Tests with complex surfaces suggest that the surface attachments form a
1867 * tree, but no method to test this has been found yet.
1869 * The attachment list consists of a first surface (first_attached) and
1870 * for each surface a pointer to the next attached surface (next_attached).
1871 * For the first surface, and a surface that has no attachments
1872 * first_attached points to the surface itself. A surface that has
1873 * no successors in the chain has next_attached set to NULL.
1875 * Newly attached surfaces are attached right after the root surface.
1876 * If a surface is attached to a complex surface compound, it's attached to
1877 * the surface that the app requested, not the complex root. See
1878 * GetAttachedSurface for a description how surfaces are found.
1880 * This is how the current implementation works, and it was coded by looking
1881 * at the needs of the applications.
1883 * So far only Z-Buffer attachments are tested, and they are activated in
1884 * WineD3D. Mipmaps could be tricky to activate in WineD3D.
1885 * Back buffers should work in 2D mode, but they are not tested(They can be
1886 * attached in older iface versions). Rendering to the front buffer and
1887 * switching between that and double buffering is not yet implemented in
1888 * WineD3D, so for 3D it might have unexpected results.
1890 * ddraw_surface_attach_surface is the real thing,
1891 * ddraw_surface7_AddAttachedSurface is a wrapper around it that
1892 * performs additional checks. Version 7 of this interface is much more restrictive
1893 * than its predecessors.
1895 * Params:
1896 * Attach: Surface to attach to iface
1898 * Returns:
1899 * DD_OK on success
1900 * DDERR_CANNOTATTACHSURFACE if the surface can't be attached for some reason
1902 *****************************************************************************/
1903 static HRESULT ddraw_surface_attach_surface(struct ddraw_surface *This, struct ddraw_surface *Surf)
1905 TRACE("surface %p, attachment %p.\n", This, Surf);
1907 if(Surf == This)
1908 return DDERR_CANNOTATTACHSURFACE; /* unchecked */
1910 wined3d_mutex_lock();
1912 /* Check if the surface is already attached somewhere */
1913 if (Surf->next_attached || Surf->first_attached != Surf)
1915 /* TODO: Test for the structure of the manual attachment. Is it a
1916 * chain or a list? What happens if one surface is attached to 2
1917 * different surfaces? */
1918 WARN("Surface %p is already attached somewhere. next_attached %p, first_attached %p.\n",
1919 Surf, Surf->next_attached, Surf->first_attached);
1921 wined3d_mutex_unlock();
1922 return DDERR_SURFACEALREADYATTACHED;
1925 /* This inserts the new surface at the 2nd position in the chain, right after the root surface */
1926 Surf->next_attached = This->next_attached;
1927 Surf->first_attached = This->first_attached;
1928 This->next_attached = Surf;
1930 /* Check if the WineD3D depth stencil needs updating */
1931 if (This->ddraw->d3ddevice)
1932 d3d_device_update_depth_stencil(This->ddraw->d3ddevice);
1934 wined3d_mutex_unlock();
1936 return DD_OK;
1939 static HRESULT WINAPI ddraw_surface7_AddAttachedSurface(IDirectDrawSurface7 *iface, IDirectDrawSurface7 *attachment)
1941 struct ddraw_surface *This = impl_from_IDirectDrawSurface7(iface);
1942 struct ddraw_surface *attachment_impl = unsafe_impl_from_IDirectDrawSurface7(attachment);
1943 HRESULT hr;
1945 TRACE("iface %p, attachment %p.\n", iface, attachment);
1947 /* Version 7 of this interface seems to refuse everything except z buffers, as per msdn */
1948 if(!(attachment_impl->surface_desc.ddsCaps.dwCaps & DDSCAPS_ZBUFFER))
1951 WARN("Application tries to attach a non Z buffer surface. caps %08x\n",
1952 attachment_impl->surface_desc.ddsCaps.dwCaps);
1953 return DDERR_CANNOTATTACHSURFACE;
1956 hr = ddraw_surface_attach_surface(This, attachment_impl);
1957 if (FAILED(hr))
1959 return hr;
1961 attachment_impl->attached_iface = (IUnknown *)attachment;
1962 IUnknown_AddRef(attachment_impl->attached_iface);
1963 return hr;
1966 static HRESULT WINAPI ddraw_surface4_AddAttachedSurface(IDirectDrawSurface4 *iface, IDirectDrawSurface4 *attachment)
1968 struct ddraw_surface *surface = impl_from_IDirectDrawSurface4(iface);
1969 struct ddraw_surface *attachment_impl = unsafe_impl_from_IDirectDrawSurface4(attachment);
1970 HRESULT hr;
1972 TRACE("iface %p, attachment %p.\n", iface, attachment);
1974 /* Tests suggest that
1975 * -> offscreen plain surfaces can be attached to other offscreen plain surfaces
1976 * -> offscreen plain surfaces can be attached to primaries
1977 * -> primaries can be attached to offscreen plain surfaces
1978 * -> z buffers can be attached to primaries */
1979 if (surface->surface_desc.ddsCaps.dwCaps & (DDSCAPS_PRIMARYSURFACE | DDSCAPS_OFFSCREENPLAIN)
1980 && attachment_impl->surface_desc.ddsCaps.dwCaps & (DDSCAPS_PRIMARYSURFACE | DDSCAPS_OFFSCREENPLAIN))
1982 /* Sizes have to match */
1983 if (attachment_impl->surface_desc.dwWidth != surface->surface_desc.dwWidth
1984 || attachment_impl->surface_desc.dwHeight != surface->surface_desc.dwHeight)
1986 WARN("Surface sizes do not match.\n");
1987 return DDERR_CANNOTATTACHSURFACE;
1990 else if (!(surface->surface_desc.ddsCaps.dwCaps & (DDSCAPS_PRIMARYSURFACE | DDSCAPS_3DDEVICE))
1991 || !(attachment_impl->surface_desc.ddsCaps.dwCaps & (DDSCAPS_ZBUFFER)))
1993 WARN("Invalid attachment combination.\n");
1994 return DDERR_CANNOTATTACHSURFACE;
1997 if (FAILED(hr = ddraw_surface_attach_surface(surface, attachment_impl)))
1998 return hr;
2000 attachment_impl->attached_iface = (IUnknown *)attachment;
2001 IUnknown_AddRef(attachment_impl->attached_iface);
2002 return hr;
2005 static HRESULT WINAPI ddraw_surface3_AddAttachedSurface(IDirectDrawSurface3 *iface, IDirectDrawSurface3 *attachment)
2007 struct ddraw_surface *surface = impl_from_IDirectDrawSurface3(iface);
2008 struct ddraw_surface *attachment_impl = unsafe_impl_from_IDirectDrawSurface3(attachment);
2009 HRESULT hr;
2011 TRACE("iface %p, attachment %p.\n", iface, attachment);
2013 if (FAILED(hr = ddraw_surface4_AddAttachedSurface(&surface->IDirectDrawSurface4_iface,
2014 attachment_impl ? &attachment_impl->IDirectDrawSurface4_iface : NULL)))
2015 return hr;
2017 attachment_impl->attached_iface = (IUnknown *)attachment;
2018 IUnknown_AddRef(attachment_impl->attached_iface);
2019 ddraw_surface4_Release(&attachment_impl->IDirectDrawSurface4_iface);
2020 return hr;
2023 static HRESULT WINAPI ddraw_surface2_AddAttachedSurface(IDirectDrawSurface2 *iface, IDirectDrawSurface2 *attachment)
2025 struct ddraw_surface *surface = impl_from_IDirectDrawSurface2(iface);
2026 struct ddraw_surface *attachment_impl = unsafe_impl_from_IDirectDrawSurface2(attachment);
2027 HRESULT hr;
2029 TRACE("iface %p, attachment %p.\n", iface, attachment);
2031 if (FAILED(hr = ddraw_surface4_AddAttachedSurface(&surface->IDirectDrawSurface4_iface,
2032 attachment_impl ? &attachment_impl->IDirectDrawSurface4_iface : NULL)))
2033 return hr;
2035 attachment_impl->attached_iface = (IUnknown *)attachment;
2036 IUnknown_AddRef(attachment_impl->attached_iface);
2037 ddraw_surface4_Release(&attachment_impl->IDirectDrawSurface4_iface);
2038 return hr;
2041 static HRESULT WINAPI ddraw_surface1_AddAttachedSurface(IDirectDrawSurface *iface, IDirectDrawSurface *attachment)
2043 struct ddraw_surface *surface = impl_from_IDirectDrawSurface(iface);
2044 struct ddraw_surface *attachment_impl = unsafe_impl_from_IDirectDrawSurface(attachment);
2045 HRESULT hr;
2047 TRACE("iface %p, attachment %p.\n", iface, attachment);
2049 if (FAILED(hr = ddraw_surface4_AddAttachedSurface(&surface->IDirectDrawSurface4_iface,
2050 attachment_impl ? &attachment_impl->IDirectDrawSurface4_iface : NULL)))
2051 return hr;
2053 attachment_impl->attached_iface = (IUnknown *)attachment;
2054 IUnknown_AddRef(attachment_impl->attached_iface);
2055 ddraw_surface4_Release(&attachment_impl->IDirectDrawSurface4_iface);
2056 return hr;
2059 /*****************************************************************************
2060 * IDirectDrawSurface7::DeleteAttachedSurface
2062 * Removes a surface from the attachment chain. The surface's refcount
2063 * is decreased by one after it has been removed
2065 * Params:
2066 * Flags: Some flags, not used by this implementation
2067 * Attach: Surface to detach
2069 * Returns:
2070 * DD_OK on success
2071 * DDERR_SURFACENOTATTACHED if the surface isn't attached to
2073 *****************************************************************************/
2074 static HRESULT ddraw_surface_delete_attached_surface(struct ddraw_surface *surface,
2075 struct ddraw_surface *attachment, IUnknown *detach_iface)
2077 struct ddraw_surface *prev = surface;
2079 TRACE("surface %p, attachment %p, detach_iface %p.\n", surface, attachment, detach_iface);
2081 wined3d_mutex_lock();
2082 if (!attachment || (attachment->first_attached != surface) || (attachment == surface) )
2084 wined3d_mutex_unlock();
2085 return DDERR_CANNOTDETACHSURFACE;
2088 if (attachment->attached_iface != detach_iface)
2090 WARN("attachment->attach_iface %p != detach_iface %p.\n", attachment->attached_iface, detach_iface);
2091 wined3d_mutex_unlock();
2092 return DDERR_SURFACENOTATTACHED;
2095 /* Remove MIPMAPSUBLEVEL if this seemed to be one */
2096 if (surface->surface_desc.ddsCaps.dwCaps & attachment->surface_desc.ddsCaps.dwCaps & DDSCAPS_MIPMAP)
2098 attachment->surface_desc.ddsCaps.dwCaps2 &= ~DDSCAPS2_MIPMAPSUBLEVEL;
2099 /* FIXME: we should probably also subtract from dwMipMapCount of this
2100 * and all parent surfaces */
2103 /* Find the predecessor of the detached surface */
2104 while (prev->next_attached != attachment)
2106 if (!(prev = prev->next_attached))
2108 ERR("Failed to find predecessor of %p.\n", attachment);
2109 wined3d_mutex_unlock();
2110 return DDERR_SURFACENOTATTACHED;
2114 /* Unchain the surface */
2115 prev->next_attached = attachment->next_attached;
2116 attachment->next_attached = NULL;
2117 attachment->first_attached = attachment;
2119 /* Check if the wined3d depth stencil needs updating. Note that we don't
2120 * just call d3d_device_update_depth_stencil() here since it uses
2121 * QueryInterface(). Some applications, SCP - Containment Breach in
2122 * particular, modify the QueryInterface() pointer in the surface vtbl
2123 * but don't cleanup properly after the relevant dll is unloaded. */
2124 if (attachment->surface_desc.ddsCaps.dwCaps & DDSCAPS_ZBUFFER
2125 && wined3d_device_get_depth_stencil_view(surface->ddraw->wined3d_device) == attachment->wined3d_rtv)
2126 wined3d_device_set_depth_stencil_view(surface->ddraw->wined3d_device, NULL);
2127 wined3d_mutex_unlock();
2129 /* Set attached_iface to NULL before releasing it, the surface may go
2130 * away. */
2131 attachment->attached_iface = NULL;
2132 IUnknown_Release(detach_iface);
2134 return DD_OK;
2137 static HRESULT WINAPI ddraw_surface7_DeleteAttachedSurface(IDirectDrawSurface7 *iface,
2138 DWORD flags, IDirectDrawSurface7 *attachment)
2140 struct ddraw_surface *surface = impl_from_IDirectDrawSurface7(iface);
2141 struct ddraw_surface *attachment_impl = unsafe_impl_from_IDirectDrawSurface7(attachment);
2143 TRACE("iface %p, flags %#x, attachment %p.\n", iface, flags, attachment);
2145 return ddraw_surface_delete_attached_surface(surface, attachment_impl, (IUnknown *)attachment);
2148 static HRESULT WINAPI ddraw_surface4_DeleteAttachedSurface(IDirectDrawSurface4 *iface,
2149 DWORD flags, IDirectDrawSurface4 *attachment)
2151 struct ddraw_surface *surface = impl_from_IDirectDrawSurface4(iface);
2152 struct ddraw_surface *attachment_impl = unsafe_impl_from_IDirectDrawSurface4(attachment);
2154 TRACE("iface %p, flags %#x, attachment %p.\n", iface, flags, attachment);
2156 return ddraw_surface_delete_attached_surface(surface, attachment_impl, (IUnknown *)attachment);
2159 static HRESULT WINAPI ddraw_surface3_DeleteAttachedSurface(IDirectDrawSurface3 *iface,
2160 DWORD flags, IDirectDrawSurface3 *attachment)
2162 struct ddraw_surface *surface = impl_from_IDirectDrawSurface3(iface);
2163 struct ddraw_surface *attachment_impl = unsafe_impl_from_IDirectDrawSurface3(attachment);
2165 TRACE("iface %p, flags %#x, attachment %p.\n", iface, flags, attachment);
2167 return ddraw_surface_delete_attached_surface(surface, attachment_impl, (IUnknown *)attachment);
2170 static HRESULT WINAPI ddraw_surface2_DeleteAttachedSurface(IDirectDrawSurface2 *iface,
2171 DWORD flags, IDirectDrawSurface2 *attachment)
2173 struct ddraw_surface *surface = impl_from_IDirectDrawSurface2(iface);
2174 struct ddraw_surface *attachment_impl = unsafe_impl_from_IDirectDrawSurface2(attachment);
2176 TRACE("iface %p, flags %#x, attachment %p.\n", iface, flags, attachment);
2178 return ddraw_surface_delete_attached_surface(surface, attachment_impl, (IUnknown *)attachment);
2181 static HRESULT WINAPI ddraw_surface1_DeleteAttachedSurface(IDirectDrawSurface *iface,
2182 DWORD flags, IDirectDrawSurface *attachment)
2184 struct ddraw_surface *surface = impl_from_IDirectDrawSurface(iface);
2185 struct ddraw_surface *attachment_impl = unsafe_impl_from_IDirectDrawSurface(attachment);
2187 TRACE("iface %p, flags %#x, attachment %p.\n", iface, flags, attachment);
2189 return ddraw_surface_delete_attached_surface(surface, attachment_impl, (IUnknown *)attachment);
2192 /*****************************************************************************
2193 * IDirectDrawSurface7::AddOverlayDirtyRect
2195 * "This method is not currently implemented"
2197 * Params:
2198 * Rect: ?
2200 * Returns:
2201 * DDERR_UNSUPPORTED
2203 *****************************************************************************/
2204 static HRESULT WINAPI ddraw_surface7_AddOverlayDirtyRect(IDirectDrawSurface7 *iface, RECT *Rect)
2206 TRACE("iface %p, rect %s.\n", iface, wine_dbgstr_rect(Rect));
2208 return DDERR_UNSUPPORTED; /* unchecked */
2211 static HRESULT WINAPI ddraw_surface4_AddOverlayDirtyRect(IDirectDrawSurface4 *iface, RECT *rect)
2213 struct ddraw_surface *surface = impl_from_IDirectDrawSurface4(iface);
2215 TRACE("iface %p, rect %s.\n", iface, wine_dbgstr_rect(rect));
2217 return ddraw_surface7_AddOverlayDirtyRect(&surface->IDirectDrawSurface7_iface, rect);
2220 static HRESULT WINAPI ddraw_surface3_AddOverlayDirtyRect(IDirectDrawSurface3 *iface, RECT *rect)
2222 struct ddraw_surface *surface = impl_from_IDirectDrawSurface3(iface);
2224 TRACE("iface %p, rect %s.\n", iface, wine_dbgstr_rect(rect));
2226 return ddraw_surface7_AddOverlayDirtyRect(&surface->IDirectDrawSurface7_iface, rect);
2229 static HRESULT WINAPI ddraw_surface2_AddOverlayDirtyRect(IDirectDrawSurface2 *iface, RECT *rect)
2231 struct ddraw_surface *surface = impl_from_IDirectDrawSurface2(iface);
2233 TRACE("iface %p, rect %s.\n", iface, wine_dbgstr_rect(rect));
2235 return ddraw_surface7_AddOverlayDirtyRect(&surface->IDirectDrawSurface7_iface, rect);
2238 static HRESULT WINAPI ddraw_surface1_AddOverlayDirtyRect(IDirectDrawSurface *iface, RECT *rect)
2240 struct ddraw_surface *surface = impl_from_IDirectDrawSurface(iface);
2242 TRACE("iface %p, rect %s.\n", iface, wine_dbgstr_rect(rect));
2244 return ddraw_surface7_AddOverlayDirtyRect(&surface->IDirectDrawSurface7_iface, rect);
2247 /*****************************************************************************
2248 * IDirectDrawSurface7::GetDC
2250 * Returns a GDI device context for the surface
2252 * Params:
2253 * hdc: Address of a HDC variable to store the dc to
2255 * Returns:
2256 * DD_OK on success
2257 * DDERR_INVALIDPARAMS if hdc is NULL
2259 *****************************************************************************/
2260 static HRESULT WINAPI ddraw_surface7_GetDC(IDirectDrawSurface7 *iface, HDC *dc)
2262 struct ddraw_surface *surface = impl_from_IDirectDrawSurface7(iface);
2263 HRESULT hr = DD_OK;
2265 TRACE("iface %p, dc %p.\n", iface, dc);
2267 if (!dc)
2268 return DDERR_INVALIDPARAMS;
2270 wined3d_mutex_lock();
2271 if (surface->dc)
2272 hr = DDERR_DCALREADYCREATED;
2273 else if (surface->surface_desc.ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE)
2274 hr = ddraw_surface_update_frontbuffer(surface, NULL, TRUE, 0);
2275 if (SUCCEEDED(hr))
2276 hr = wined3d_texture_get_dc(surface->wined3d_texture, surface->sub_resource_idx, dc);
2278 if (SUCCEEDED(hr))
2280 surface->dc = *dc;
2282 if (format_is_paletteindexed(&surface->surface_desc.u4.ddpfPixelFormat))
2284 const struct ddraw_palette *palette;
2286 if (surface->palette)
2287 palette = surface->palette;
2288 else if (surface->ddraw->primary)
2289 palette = surface->ddraw->primary->palette;
2290 else
2291 palette = NULL;
2293 if (palette)
2294 wined3d_palette_apply_to_dc(palette->wined3d_palette, *dc);
2298 wined3d_mutex_unlock();
2299 switch (hr)
2301 /* Some, but not all errors set *dc to NULL. E.g. DCALREADYCREATED
2302 * does not touch *dc. */
2303 case WINED3DERR_INVALIDCALL:
2304 *dc = NULL;
2305 return DDERR_CANTCREATEDC;
2307 default:
2308 return hr;
2312 static HRESULT WINAPI ddraw_surface4_GetDC(IDirectDrawSurface4 *iface, HDC *dc)
2314 struct ddraw_surface *surface = impl_from_IDirectDrawSurface4(iface);
2316 TRACE("iface %p, dc %p.\n", iface, dc);
2318 return ddraw_surface7_GetDC(&surface->IDirectDrawSurface7_iface, dc);
2321 static HRESULT WINAPI ddraw_surface3_GetDC(IDirectDrawSurface3 *iface, HDC *dc)
2323 struct ddraw_surface *surface = impl_from_IDirectDrawSurface3(iface);
2325 TRACE("iface %p, dc %p.\n", iface, dc);
2327 return ddraw_surface7_GetDC(&surface->IDirectDrawSurface7_iface, dc);
2330 static HRESULT WINAPI ddraw_surface2_GetDC(IDirectDrawSurface2 *iface, HDC *dc)
2332 struct ddraw_surface *surface = impl_from_IDirectDrawSurface2(iface);
2334 TRACE("iface %p, dc %p.\n", iface, dc);
2336 return ddraw_surface7_GetDC(&surface->IDirectDrawSurface7_iface, dc);
2339 static HRESULT WINAPI ddraw_surface1_GetDC(IDirectDrawSurface *iface, HDC *dc)
2341 struct ddraw_surface *surface = impl_from_IDirectDrawSurface(iface);
2343 TRACE("iface %p, dc %p.\n", iface, dc);
2345 return ddraw_surface7_GetDC(&surface->IDirectDrawSurface7_iface, dc);
2348 /*****************************************************************************
2349 * IDirectDrawSurface7::ReleaseDC
2351 * Releases the DC that was constructed with GetDC
2353 * Params:
2354 * hdc: HDC to release
2356 * Returns:
2357 * DD_OK on success, error code otherwise.
2359 *****************************************************************************/
2360 static HRESULT WINAPI ddraw_surface7_ReleaseDC(IDirectDrawSurface7 *iface, HDC hdc)
2362 struct ddraw_surface *surface = impl_from_IDirectDrawSurface7(iface);
2363 HRESULT hr;
2365 TRACE("iface %p, dc %p.\n", iface, hdc);
2367 wined3d_mutex_lock();
2368 if (!surface->dc)
2370 hr = DDERR_NODC;
2372 else if (SUCCEEDED(hr = wined3d_texture_release_dc(surface->wined3d_texture, surface->sub_resource_idx, hdc)))
2374 surface->dc = NULL;
2375 if (surface->surface_desc.ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE)
2376 hr = ddraw_surface_update_frontbuffer(surface, NULL, FALSE, 0);
2378 wined3d_mutex_unlock();
2381 return hr;
2384 static HRESULT WINAPI ddraw_surface4_ReleaseDC(IDirectDrawSurface4 *iface, HDC dc)
2386 struct ddraw_surface *surface = impl_from_IDirectDrawSurface4(iface);
2388 TRACE("iface %p, dc %p.\n", iface, dc);
2390 return ddraw_surface7_ReleaseDC(&surface->IDirectDrawSurface7_iface, dc);
2393 static HRESULT WINAPI ddraw_surface3_ReleaseDC(IDirectDrawSurface3 *iface, HDC dc)
2395 struct ddraw_surface *surface = impl_from_IDirectDrawSurface3(iface);
2397 TRACE("iface %p, dc %p.\n", iface, dc);
2399 return ddraw_surface7_ReleaseDC(&surface->IDirectDrawSurface7_iface, dc);
2402 static HRESULT WINAPI ddraw_surface2_ReleaseDC(IDirectDrawSurface2 *iface, HDC dc)
2404 struct ddraw_surface *surface = impl_from_IDirectDrawSurface2(iface);
2406 TRACE("iface %p, dc %p.\n", iface, dc);
2408 return ddraw_surface7_ReleaseDC(&surface->IDirectDrawSurface7_iface, dc);
2411 static HRESULT WINAPI ddraw_surface1_ReleaseDC(IDirectDrawSurface *iface, HDC dc)
2413 struct ddraw_surface *surface = impl_from_IDirectDrawSurface(iface);
2415 TRACE("iface %p, dc %p.\n", iface, dc);
2417 return ddraw_surface7_ReleaseDC(&surface->IDirectDrawSurface7_iface, dc);
2420 /*****************************************************************************
2421 * IDirectDrawSurface7::GetCaps
2423 * Returns the surface's caps
2425 * Params:
2426 * Caps: Address to write the caps to
2428 * Returns:
2429 * DD_OK on success
2430 * DDERR_INVALIDPARAMS if Caps is NULL
2432 *****************************************************************************/
2433 static HRESULT WINAPI ddraw_surface7_GetCaps(IDirectDrawSurface7 *iface, DDSCAPS2 *Caps)
2435 struct ddraw_surface *surface = impl_from_IDirectDrawSurface7(iface);
2437 TRACE("iface %p, caps %p.\n", iface, Caps);
2439 if(!Caps)
2440 return DDERR_INVALIDPARAMS;
2442 *Caps = surface->surface_desc.ddsCaps;
2444 return DD_OK;
2447 static HRESULT WINAPI ddraw_surface4_GetCaps(IDirectDrawSurface4 *iface, DDSCAPS2 *caps)
2449 struct ddraw_surface *surface = impl_from_IDirectDrawSurface4(iface);
2451 TRACE("iface %p, caps %p.\n", iface, caps);
2453 return ddraw_surface7_GetCaps(&surface->IDirectDrawSurface7_iface, caps);
2456 static HRESULT WINAPI ddraw_surface3_GetCaps(IDirectDrawSurface3 *iface, DDSCAPS *caps)
2458 struct ddraw_surface *surface = impl_from_IDirectDrawSurface3(iface);
2459 DDSCAPS2 caps2;
2460 HRESULT hr;
2462 TRACE("iface %p, caps %p.\n", iface, caps);
2464 hr = ddraw_surface7_GetCaps(&surface->IDirectDrawSurface7_iface, &caps2);
2465 if (FAILED(hr)) return hr;
2467 caps->dwCaps = caps2.dwCaps;
2468 return hr;
2471 static HRESULT WINAPI ddraw_surface2_GetCaps(IDirectDrawSurface2 *iface, DDSCAPS *caps)
2473 struct ddraw_surface *surface = impl_from_IDirectDrawSurface2(iface);
2474 DDSCAPS2 caps2;
2475 HRESULT hr;
2477 TRACE("iface %p, caps %p.\n", iface, caps);
2479 hr = ddraw_surface7_GetCaps(&surface->IDirectDrawSurface7_iface, &caps2);
2480 if (FAILED(hr)) return hr;
2482 caps->dwCaps = caps2.dwCaps;
2483 return hr;
2486 static HRESULT WINAPI ddraw_surface1_GetCaps(IDirectDrawSurface *iface, DDSCAPS *caps)
2488 struct ddraw_surface *surface = impl_from_IDirectDrawSurface(iface);
2489 DDSCAPS2 caps2;
2490 HRESULT hr;
2492 TRACE("iface %p, caps %p.\n", iface, caps);
2494 hr = ddraw_surface7_GetCaps(&surface->IDirectDrawSurface7_iface, &caps2);
2495 if (FAILED(hr)) return hr;
2497 caps->dwCaps = caps2.dwCaps;
2498 return hr;
2501 static HRESULT WINAPI ddraw_surface7_SetPriority(IDirectDrawSurface7 *iface, DWORD priority)
2503 struct ddraw_surface *surface = impl_from_IDirectDrawSurface7(iface);
2504 DWORD managed = DDSCAPS2_TEXTUREMANAGE | DDSCAPS2_D3DTEXTUREMANAGE;
2505 HRESULT hr;
2506 struct wined3d_resource *resource;
2508 TRACE("iface %p, priority %u.\n", iface, priority);
2510 wined3d_mutex_lock();
2511 /* No need to check for offscreen plain surfaces or mipmap sublevels. SetPriority
2512 * calls on such surfaces segfault on Windows. */
2513 if (!(surface->surface_desc.ddsCaps.dwCaps2 & managed))
2515 WARN("Called on non-managed texture returning DDERR_INVALIDPARAMS.\n");
2516 hr = DDERR_INVALIDPARAMS;
2518 else
2520 resource = wined3d_texture_get_resource(surface->wined3d_texture);
2521 wined3d_resource_set_priority(resource, priority);
2522 hr = DD_OK;
2524 wined3d_mutex_unlock();
2526 return hr;
2529 static HRESULT WINAPI ddraw_surface7_GetPriority(IDirectDrawSurface7 *iface, DWORD *priority)
2531 struct ddraw_surface *surface = impl_from_IDirectDrawSurface7(iface);
2532 const struct wined3d_resource *resource;
2533 DWORD managed = DDSCAPS2_TEXTUREMANAGE | DDSCAPS2_D3DTEXTUREMANAGE;
2534 HRESULT hr;
2536 TRACE("iface %p, priority %p.\n", iface, priority);
2538 wined3d_mutex_lock();
2539 if (surface->surface_desc.ddsCaps.dwCaps & DDSCAPS_OFFSCREENPLAIN)
2541 WARN("Called on offscreenplain surface, returning DDERR_INVALIDOBJECT.\n");
2542 hr = DDERR_INVALIDOBJECT;
2544 else if (!(surface->surface_desc.ddsCaps.dwCaps2 & managed) || !surface->is_complex_root)
2546 WARN("Called on non-managed texture or non-root surface, returning DDERR_INVALIDPARAMS.\n");
2547 hr = DDERR_INVALIDPARAMS;
2549 else
2551 resource = wined3d_texture_get_resource(surface->wined3d_texture);
2552 *priority = wined3d_resource_get_priority(resource);
2553 hr = DD_OK;
2555 wined3d_mutex_unlock();
2557 return hr;
2560 /*****************************************************************************
2561 * IDirectDrawSurface7::SetPrivateData
2563 * Stores some data in the surface that is intended for the application's
2564 * use.
2566 * Params:
2567 * tag: GUID that identifies the data
2568 * Data: Pointer to the private data
2569 * Size: Size of the private data
2570 * Flags: Some flags
2572 * Returns:
2573 * D3D_OK on success, error code otherwise.
2575 *****************************************************************************/
2576 static HRESULT WINAPI ddraw_surface7_SetPrivateData(IDirectDrawSurface7 *iface,
2577 REFGUID tag, void *data, DWORD size, DWORD flags)
2579 struct ddraw_surface *surface = impl_from_IDirectDrawSurface7(iface);
2580 HRESULT hr;
2582 TRACE("iface %p, tag %s, data %p, data_size %u, flags %#x.\n",
2583 iface, debugstr_guid(tag), data, size, flags);
2585 if (!data)
2587 WARN("data is NULL, returning DDERR_INVALIDPARAMS.\n");
2588 return DDERR_INVALIDPARAMS;
2591 wined3d_mutex_lock();
2592 hr = wined3d_private_store_set_private_data(&surface->private_store, tag, data, size, flags);
2593 wined3d_mutex_unlock();
2594 return hr_ddraw_from_wined3d(hr);
2597 static HRESULT WINAPI ddraw_surface4_SetPrivateData(IDirectDrawSurface4 *iface,
2598 REFGUID tag, void *data, DWORD size, DWORD flags)
2600 struct ddraw_surface *surface = impl_from_IDirectDrawSurface4(iface);
2602 TRACE("iface %p, tag %s, data %p, data_size %u, flags %#x.\n",
2603 iface, debugstr_guid(tag), data, size, flags);
2605 return ddraw_surface7_SetPrivateData(&surface->IDirectDrawSurface7_iface, tag, data, size, flags);
2608 /*****************************************************************************
2609 * IDirectDrawSurface7::GetPrivateData
2611 * Returns the private data set with IDirectDrawSurface7::SetPrivateData
2613 * Params:
2614 * tag: GUID of the data to return
2615 * Data: Address where to write the data to
2616 * Size: Size of the buffer at Data
2618 * Returns:
2619 * DD_OK on success
2620 * DDERR_INVALIDPARAMS if Data is NULL
2622 *****************************************************************************/
2623 static HRESULT WINAPI ddraw_surface7_GetPrivateData(IDirectDrawSurface7 *iface, REFGUID tag, void *data, DWORD *size)
2625 struct ddraw_surface *surface = impl_from_IDirectDrawSurface7(iface);
2626 const struct wined3d_private_data *stored_data;
2627 HRESULT hr;
2629 TRACE("iface %p, tag %s, data %p, data_size %p.\n",
2630 iface, debugstr_guid(tag), data, size);
2632 wined3d_mutex_lock();
2633 stored_data = wined3d_private_store_get_private_data(&surface->private_store, tag);
2634 if (!stored_data)
2636 hr = DDERR_NOTFOUND;
2637 goto done;
2639 if (!size)
2641 hr = DDERR_INVALIDPARAMS;
2642 goto done;
2644 if (*size < stored_data->size)
2646 *size = stored_data->size;
2647 hr = DDERR_MOREDATA;
2648 goto done;
2650 if (!data)
2652 hr = DDERR_INVALIDPARAMS;
2653 goto done;
2656 *size = stored_data->size;
2657 memcpy(data, stored_data->content.data, stored_data->size);
2658 hr = DD_OK;
2660 done:
2661 wined3d_mutex_unlock();
2662 return hr;
2665 static HRESULT WINAPI ddraw_surface4_GetPrivateData(IDirectDrawSurface4 *iface, REFGUID tag, void *data, DWORD *size)
2667 struct ddraw_surface *surface = impl_from_IDirectDrawSurface4(iface);
2669 TRACE("iface %p, tag %s, data %p, data_size %p.\n",
2670 iface, debugstr_guid(tag), data, size);
2672 return ddraw_surface7_GetPrivateData(&surface->IDirectDrawSurface7_iface, tag, data, size);
2675 /*****************************************************************************
2676 * IDirectDrawSurface7::FreePrivateData
2678 * Frees private data stored in the surface
2680 * Params:
2681 * tag: Tag of the data to free
2683 * Returns:
2684 * D3D_OK on success, error code otherwise.
2686 *****************************************************************************/
2687 static HRESULT WINAPI ddraw_surface7_FreePrivateData(IDirectDrawSurface7 *iface, REFGUID tag)
2689 struct ddraw_surface *surface = impl_from_IDirectDrawSurface7(iface);
2690 struct wined3d_private_data *entry;
2692 TRACE("iface %p, tag %s.\n", iface, debugstr_guid(tag));
2694 wined3d_mutex_lock();
2695 entry = wined3d_private_store_get_private_data(&surface->private_store, tag);
2696 if (!entry)
2698 wined3d_mutex_unlock();
2699 return DDERR_NOTFOUND;
2702 wined3d_private_store_free_private_data(&surface->private_store, entry);
2703 wined3d_mutex_unlock();
2705 return DD_OK;
2708 static HRESULT WINAPI ddraw_surface4_FreePrivateData(IDirectDrawSurface4 *iface, REFGUID tag)
2710 struct ddraw_surface *surface = impl_from_IDirectDrawSurface4(iface);
2712 TRACE("iface %p, tag %s.\n", iface, debugstr_guid(tag));
2714 return ddraw_surface7_FreePrivateData(&surface->IDirectDrawSurface7_iface, tag);
2717 /*****************************************************************************
2718 * IDirectDrawSurface7::PageLock
2720 * Prevents a sysmem surface from being paged out
2722 * Params:
2723 * Flags: Not used, must be 0(unchecked)
2725 * Returns:
2726 * DD_OK, because it's a stub
2728 *****************************************************************************/
2729 static HRESULT WINAPI ddraw_surface7_PageLock(IDirectDrawSurface7 *iface, DWORD Flags)
2731 TRACE("iface %p, flags %#x.\n", iface, Flags);
2733 /* This is Windows memory management related - we don't need this */
2734 return DD_OK;
2737 static HRESULT WINAPI ddraw_surface4_PageLock(IDirectDrawSurface4 *iface, DWORD flags)
2739 struct ddraw_surface *surface = impl_from_IDirectDrawSurface4(iface);
2741 TRACE("iface %p, flags %#x.\n", iface, flags);
2743 return ddraw_surface7_PageLock(&surface->IDirectDrawSurface7_iface, flags);
2746 static HRESULT WINAPI ddraw_surface3_PageLock(IDirectDrawSurface3 *iface, DWORD flags)
2748 struct ddraw_surface *surface = impl_from_IDirectDrawSurface3(iface);
2750 TRACE("iface %p, flags %#x.\n", iface, flags);
2752 return ddraw_surface7_PageLock(&surface->IDirectDrawSurface7_iface, flags);
2755 static HRESULT WINAPI ddraw_surface2_PageLock(IDirectDrawSurface2 *iface, DWORD flags)
2757 struct ddraw_surface *surface = impl_from_IDirectDrawSurface2(iface);
2759 TRACE("iface %p, flags %#x.\n", iface, flags);
2761 return ddraw_surface7_PageLock(&surface->IDirectDrawSurface7_iface, flags);
2764 /*****************************************************************************
2765 * IDirectDrawSurface7::PageUnlock
2767 * Allows a sysmem surface to be paged out
2769 * Params:
2770 * Flags: Not used, must be 0(unchecked)
2772 * Returns:
2773 * DD_OK, because it's a stub
2775 *****************************************************************************/
2776 static HRESULT WINAPI ddraw_surface7_PageUnlock(IDirectDrawSurface7 *iface, DWORD Flags)
2778 TRACE("iface %p, flags %#x.\n", iface, Flags);
2780 return DD_OK;
2783 static HRESULT WINAPI ddraw_surface4_PageUnlock(IDirectDrawSurface4 *iface, DWORD flags)
2785 struct ddraw_surface *surface = impl_from_IDirectDrawSurface4(iface);
2787 TRACE("iface %p, flags %#x.\n", iface, flags);
2789 return ddraw_surface7_PageUnlock(&surface->IDirectDrawSurface7_iface, flags);
2792 static HRESULT WINAPI ddraw_surface3_PageUnlock(IDirectDrawSurface3 *iface, DWORD flags)
2794 struct ddraw_surface *surface = impl_from_IDirectDrawSurface3(iface);
2796 TRACE("iface %p, flags %#x.\n", iface, flags);
2798 return ddraw_surface7_PageUnlock(&surface->IDirectDrawSurface7_iface, flags);
2801 static HRESULT WINAPI ddraw_surface2_PageUnlock(IDirectDrawSurface2 *iface, DWORD flags)
2803 struct ddraw_surface *surface = impl_from_IDirectDrawSurface2(iface);
2805 TRACE("iface %p, flags %#x.\n", iface, flags);
2807 return ddraw_surface7_PageUnlock(&surface->IDirectDrawSurface7_iface, flags);
2810 /*****************************************************************************
2811 * IDirectDrawSurface7::BltBatch
2813 * An unimplemented function
2815 * Params:
2818 * Returns:
2819 * DDERR_UNSUPPORTED
2821 *****************************************************************************/
2822 static HRESULT WINAPI DECLSPEC_HOTPATCH ddraw_surface7_BltBatch(IDirectDrawSurface7 *iface, DDBLTBATCH *Batch, DWORD Count, DWORD Flags)
2824 TRACE("iface %p, batch %p, count %u, flags %#x.\n", iface, Batch, Count, Flags);
2826 /* MSDN: "not currently implemented" */
2827 return DDERR_UNSUPPORTED;
2830 static HRESULT WINAPI DECLSPEC_HOTPATCH ddraw_surface4_BltBatch(IDirectDrawSurface4 *iface, DDBLTBATCH *batch, DWORD count, DWORD flags)
2832 struct ddraw_surface *surface = impl_from_IDirectDrawSurface4(iface);
2834 TRACE("iface %p, batch %p, count %u, flags %#x.\n", iface, batch, count, flags);
2836 return ddraw_surface7_BltBatch(&surface->IDirectDrawSurface7_iface, batch, count, flags);
2839 static HRESULT WINAPI DECLSPEC_HOTPATCH ddraw_surface3_BltBatch(IDirectDrawSurface3 *iface, DDBLTBATCH *batch, DWORD count, DWORD flags)
2841 struct ddraw_surface *surface = impl_from_IDirectDrawSurface3(iface);
2843 TRACE("iface %p, batch %p, count %u, flags %#x.\n", iface, batch, count, flags);
2845 return ddraw_surface7_BltBatch(&surface->IDirectDrawSurface7_iface, batch, count, flags);
2848 static HRESULT WINAPI DECLSPEC_HOTPATCH ddraw_surface2_BltBatch(IDirectDrawSurface2 *iface, DDBLTBATCH *batch, DWORD count, DWORD flags)
2850 struct ddraw_surface *surface = impl_from_IDirectDrawSurface2(iface);
2852 TRACE("iface %p, batch %p, count %u, flags %#x.\n", iface, batch, count, flags);
2854 return ddraw_surface7_BltBatch(&surface->IDirectDrawSurface7_iface, batch, count, flags);
2857 static HRESULT WINAPI DECLSPEC_HOTPATCH ddraw_surface1_BltBatch(IDirectDrawSurface *iface, DDBLTBATCH *batch, DWORD count, DWORD flags)
2859 struct ddraw_surface *surface = impl_from_IDirectDrawSurface(iface);
2861 TRACE("iface %p, batch %p, count %u, flags %#x.\n", iface, batch, count, flags);
2863 return ddraw_surface7_BltBatch(&surface->IDirectDrawSurface7_iface, batch, count, flags);
2866 /*****************************************************************************
2867 * IDirectDrawSurface7::EnumAttachedSurfaces
2869 * Enumerates all surfaces attached to this surface
2871 * Params:
2872 * context: Pointer to pass unmodified to the callback
2873 * cb: Callback function to call for each surface
2875 * Returns:
2876 * DD_OK on success
2877 * DDERR_INVALIDPARAMS if cb is NULL
2879 *****************************************************************************/
2880 static HRESULT WINAPI ddraw_surface7_EnumAttachedSurfaces(IDirectDrawSurface7 *iface,
2881 void *context, LPDDENUMSURFACESCALLBACK7 cb)
2883 struct ddraw_surface *surface = impl_from_IDirectDrawSurface7(iface);
2884 struct ddraw_surface *surf;
2885 DDSURFACEDESC2 desc;
2886 int i;
2888 /* Attached surfaces aren't handled in WineD3D */
2889 TRACE("iface %p, context %p, callback %p.\n", iface, context, cb);
2891 if(!cb)
2892 return DDERR_INVALIDPARAMS;
2894 wined3d_mutex_lock();
2896 for(i = 0; i < MAX_COMPLEX_ATTACHED; i++)
2898 surf = surface->complex_array[i];
2899 if(!surf) break;
2901 ddraw_surface7_AddRef(&surf->IDirectDrawSurface7_iface);
2902 desc = surf->surface_desc;
2903 /* check: != DDENUMRET_OK or == DDENUMRET_CANCEL? */
2904 if (cb(&surf->IDirectDrawSurface7_iface, &desc, context) == DDENUMRET_CANCEL)
2906 wined3d_mutex_unlock();
2907 return DD_OK;
2911 for (surf = surface->next_attached; surf != NULL; surf = surf->next_attached)
2913 ddraw_surface7_AddRef(&surf->IDirectDrawSurface7_iface);
2914 desc = surf->surface_desc;
2915 /* check: != DDENUMRET_OK or == DDENUMRET_CANCEL? */
2916 if (cb(&surf->IDirectDrawSurface7_iface, &desc, context) == DDENUMRET_CANCEL)
2918 wined3d_mutex_unlock();
2919 return DD_OK;
2923 TRACE(" end of enumeration.\n");
2925 wined3d_mutex_unlock();
2927 return DD_OK;
2930 struct callback_info2
2932 LPDDENUMSURFACESCALLBACK2 callback;
2933 void *context;
2936 struct callback_info
2938 LPDDENUMSURFACESCALLBACK callback;
2939 void *context;
2942 static HRESULT CALLBACK EnumCallback2(IDirectDrawSurface7 *surface, DDSURFACEDESC2 *surface_desc, void *context)
2944 struct ddraw_surface *surface_impl = impl_from_IDirectDrawSurface7(surface);
2945 const struct callback_info2 *info = context;
2947 ddraw_surface4_AddRef(&surface_impl->IDirectDrawSurface4_iface);
2948 ddraw_surface7_Release(surface);
2950 return info->callback(&surface_impl->IDirectDrawSurface4_iface, surface_desc, info->context);
2953 static HRESULT CALLBACK EnumCallback(IDirectDrawSurface7 *surface, DDSURFACEDESC2 *surface_desc, void *context)
2955 struct ddraw_surface *surface_impl = impl_from_IDirectDrawSurface7(surface);
2956 const struct callback_info *info = context;
2958 ddraw_surface1_AddRef(&surface_impl->IDirectDrawSurface_iface);
2959 ddraw_surface7_Release(surface);
2961 /* FIXME: Check surface_test.dwSize */
2962 return info->callback(&surface_impl->IDirectDrawSurface_iface,
2963 (DDSURFACEDESC *)surface_desc, info->context);
2966 static HRESULT WINAPI ddraw_surface4_EnumAttachedSurfaces(IDirectDrawSurface4 *iface,
2967 void *context, LPDDENUMSURFACESCALLBACK2 callback)
2969 struct ddraw_surface *surface = impl_from_IDirectDrawSurface4(iface);
2970 struct callback_info2 info;
2972 TRACE("iface %p, context %p, callback %p.\n", iface, context, callback);
2974 info.callback = callback;
2975 info.context = context;
2977 return ddraw_surface7_EnumAttachedSurfaces(&surface->IDirectDrawSurface7_iface,
2978 &info, EnumCallback2);
2981 static HRESULT WINAPI ddraw_surface3_EnumAttachedSurfaces(IDirectDrawSurface3 *iface,
2982 void *context, LPDDENUMSURFACESCALLBACK callback)
2984 struct ddraw_surface *surface = impl_from_IDirectDrawSurface3(iface);
2985 struct callback_info info;
2987 TRACE("iface %p, context %p, callback %p.\n", iface, context, callback);
2989 info.callback = callback;
2990 info.context = context;
2992 return ddraw_surface7_EnumAttachedSurfaces(&surface->IDirectDrawSurface7_iface,
2993 &info, EnumCallback);
2996 static HRESULT WINAPI ddraw_surface2_EnumAttachedSurfaces(IDirectDrawSurface2 *iface,
2997 void *context, LPDDENUMSURFACESCALLBACK callback)
2999 struct ddraw_surface *surface = impl_from_IDirectDrawSurface2(iface);
3000 struct callback_info info;
3002 TRACE("iface %p, context %p, callback %p.\n", iface, context, callback);
3004 info.callback = callback;
3005 info.context = context;
3007 return ddraw_surface7_EnumAttachedSurfaces(&surface->IDirectDrawSurface7_iface,
3008 &info, EnumCallback);
3011 static HRESULT WINAPI ddraw_surface1_EnumAttachedSurfaces(IDirectDrawSurface *iface,
3012 void *context, LPDDENUMSURFACESCALLBACK callback)
3014 struct ddraw_surface *surface = impl_from_IDirectDrawSurface(iface);
3015 struct callback_info info;
3017 TRACE("iface %p, context %p, callback %p.\n", iface, context, callback);
3019 info.callback = callback;
3020 info.context = context;
3022 return ddraw_surface7_EnumAttachedSurfaces(&surface->IDirectDrawSurface7_iface,
3023 &info, EnumCallback);
3026 /*****************************************************************************
3027 * IDirectDrawSurface7::EnumOverlayZOrders
3029 * "Enumerates the overlay surfaces on the specified destination"
3031 * Params:
3032 * Flags: DDENUMOVERLAYZ_BACKTOFRONT or DDENUMOVERLAYZ_FRONTTOBACK
3033 * context: context to pass back to the callback
3034 * cb: callback function to call for each enumerated surface
3036 * Returns:
3037 * DD_OK, because it's a stub
3039 *****************************************************************************/
3040 static HRESULT WINAPI ddraw_surface7_EnumOverlayZOrders(IDirectDrawSurface7 *iface,
3041 DWORD Flags, void *context, LPDDENUMSURFACESCALLBACK7 cb)
3043 FIXME("iface %p, flags %#x, context %p, callback %p stub!\n", iface, Flags, context, cb);
3045 return DD_OK;
3048 static HRESULT WINAPI ddraw_surface4_EnumOverlayZOrders(IDirectDrawSurface4 *iface,
3049 DWORD flags, void *context, LPDDENUMSURFACESCALLBACK2 callback)
3051 struct ddraw_surface *surface = impl_from_IDirectDrawSurface4(iface);
3052 struct callback_info2 info;
3054 TRACE("iface %p, flags %#x, context %p, callback %p.\n", iface, flags, context, callback);
3056 info.callback = callback;
3057 info.context = context;
3059 return ddraw_surface7_EnumOverlayZOrders(&surface->IDirectDrawSurface7_iface,
3060 flags, &info, EnumCallback2);
3063 static HRESULT WINAPI ddraw_surface3_EnumOverlayZOrders(IDirectDrawSurface3 *iface,
3064 DWORD flags, void *context, LPDDENUMSURFACESCALLBACK callback)
3066 struct ddraw_surface *surface = impl_from_IDirectDrawSurface3(iface);
3067 struct callback_info info;
3069 TRACE("iface %p, flags %#x, context %p, callback %p.\n", iface, flags, context, callback);
3071 info.callback = callback;
3072 info.context = context;
3074 return ddraw_surface7_EnumOverlayZOrders(&surface->IDirectDrawSurface7_iface,
3075 flags, &info, EnumCallback);
3078 static HRESULT WINAPI ddraw_surface2_EnumOverlayZOrders(IDirectDrawSurface2 *iface,
3079 DWORD flags, void *context, LPDDENUMSURFACESCALLBACK callback)
3081 struct ddraw_surface *surface = impl_from_IDirectDrawSurface2(iface);
3082 struct callback_info info;
3084 TRACE("iface %p, flags %#x, context %p, callback %p.\n", iface, flags, context, callback);
3086 info.callback = callback;
3087 info.context = context;
3089 return ddraw_surface7_EnumOverlayZOrders(&surface->IDirectDrawSurface7_iface,
3090 flags, &info, EnumCallback);
3093 static HRESULT WINAPI ddraw_surface1_EnumOverlayZOrders(IDirectDrawSurface *iface,
3094 DWORD flags, void *context, LPDDENUMSURFACESCALLBACK callback)
3096 struct ddraw_surface *surface = impl_from_IDirectDrawSurface(iface);
3097 struct callback_info info;
3099 TRACE("iface %p, flags %#x, context %p, callback %p.\n", iface, flags, context, callback);
3101 info.callback = callback;
3102 info.context = context;
3104 return ddraw_surface7_EnumOverlayZOrders(&surface->IDirectDrawSurface7_iface,
3105 flags, &info, EnumCallback);
3108 /*****************************************************************************
3109 * IDirectDrawSurface7::GetBltStatus
3111 * Returns the blitting status
3113 * Params:
3114 * Flags: DDGBS_CANBLT or DDGBS_ISBLTDONE
3116 *****************************************************************************/
3117 static HRESULT WINAPI ddraw_surface7_GetBltStatus(IDirectDrawSurface7 *iface, DWORD Flags)
3119 TRACE("iface %p, flags %#x.\n", iface, Flags);
3121 switch (Flags)
3123 case WINEDDGBS_CANBLT:
3124 case WINEDDGBS_ISBLTDONE:
3125 return DD_OK;
3127 default:
3128 return DDERR_INVALIDPARAMS;
3132 static HRESULT WINAPI ddraw_surface4_GetBltStatus(IDirectDrawSurface4 *iface, DWORD flags)
3134 struct ddraw_surface *surface = impl_from_IDirectDrawSurface4(iface);
3136 TRACE("iface %p, flags %#x.\n", iface, flags);
3138 return ddraw_surface7_GetBltStatus(&surface->IDirectDrawSurface7_iface, flags);
3141 static HRESULT WINAPI ddraw_surface3_GetBltStatus(IDirectDrawSurface3 *iface, DWORD flags)
3143 struct ddraw_surface *surface = impl_from_IDirectDrawSurface3(iface);
3145 TRACE("iface %p, flags %#x.\n", iface, flags);
3147 return ddraw_surface7_GetBltStatus(&surface->IDirectDrawSurface7_iface, flags);
3150 static HRESULT WINAPI ddraw_surface2_GetBltStatus(IDirectDrawSurface2 *iface, DWORD flags)
3152 struct ddraw_surface *surface = impl_from_IDirectDrawSurface2(iface);
3154 TRACE("iface %p, flags %#x.\n", iface, flags);
3156 return ddraw_surface7_GetBltStatus(&surface->IDirectDrawSurface7_iface, flags);
3159 static HRESULT WINAPI ddraw_surface1_GetBltStatus(IDirectDrawSurface *iface, DWORD flags)
3161 struct ddraw_surface *surface = impl_from_IDirectDrawSurface(iface);
3163 TRACE("iface %p, flags %#x.\n", iface, flags);
3165 return ddraw_surface7_GetBltStatus(&surface->IDirectDrawSurface7_iface, flags);
3168 /*****************************************************************************
3169 * IDirectDrawSurface7::GetColorKey
3171 * Returns the color key assigned to the surface
3173 * Params:
3174 * Flags: Some flags
3175 * CKey: Address to store the key to
3177 * Returns:
3178 * DD_OK on success
3179 * DDERR_INVALIDPARAMS if CKey is NULL
3181 *****************************************************************************/
3182 static HRESULT WINAPI ddraw_surface7_GetColorKey(IDirectDrawSurface7 *iface, DWORD Flags, DDCOLORKEY *CKey)
3184 struct ddraw_surface *This = impl_from_IDirectDrawSurface7(iface);
3186 TRACE("iface %p, flags %#x, color_key %p.\n", iface, Flags, CKey);
3188 if(!CKey)
3189 return DDERR_INVALIDPARAMS;
3191 wined3d_mutex_lock();
3193 switch (Flags)
3195 case DDCKEY_DESTBLT:
3196 if (!(This->surface_desc.dwFlags & DDSD_CKDESTBLT))
3198 wined3d_mutex_unlock();
3199 return DDERR_NOCOLORKEY;
3201 *CKey = This->surface_desc.ddckCKDestBlt;
3202 break;
3204 case DDCKEY_DESTOVERLAY:
3205 if (!(This->surface_desc.dwFlags & DDSD_CKDESTOVERLAY))
3207 wined3d_mutex_unlock();
3208 return DDERR_NOCOLORKEY;
3210 *CKey = This->surface_desc.u3.ddckCKDestOverlay;
3211 break;
3213 case DDCKEY_SRCBLT:
3214 if (!(This->surface_desc.dwFlags & DDSD_CKSRCBLT))
3216 wined3d_mutex_unlock();
3217 return DDERR_NOCOLORKEY;
3219 *CKey = This->surface_desc.ddckCKSrcBlt;
3220 break;
3222 case DDCKEY_SRCOVERLAY:
3223 if (!(This->surface_desc.dwFlags & DDSD_CKSRCOVERLAY))
3225 wined3d_mutex_unlock();
3226 return DDERR_NOCOLORKEY;
3228 *CKey = This->surface_desc.ddckCKSrcOverlay;
3229 break;
3231 default:
3232 wined3d_mutex_unlock();
3233 return DDERR_INVALIDPARAMS;
3236 wined3d_mutex_unlock();
3238 return DD_OK;
3241 static HRESULT WINAPI ddraw_surface4_GetColorKey(IDirectDrawSurface4 *iface, DWORD flags, DDCOLORKEY *color_key)
3243 struct ddraw_surface *surface = impl_from_IDirectDrawSurface4(iface);
3245 TRACE("iface %p, flags %#x, color_key %p.\n", iface, flags, color_key);
3247 return ddraw_surface7_GetColorKey(&surface->IDirectDrawSurface7_iface, flags, color_key);
3250 static HRESULT WINAPI ddraw_surface3_GetColorKey(IDirectDrawSurface3 *iface, DWORD flags, DDCOLORKEY *color_key)
3252 struct ddraw_surface *surface = impl_from_IDirectDrawSurface3(iface);
3254 TRACE("iface %p, flags %#x, color_key %p.\n", iface, flags, color_key);
3256 return ddraw_surface7_GetColorKey(&surface->IDirectDrawSurface7_iface, flags, color_key);
3259 static HRESULT WINAPI ddraw_surface2_GetColorKey(IDirectDrawSurface2 *iface, DWORD flags, DDCOLORKEY *color_key)
3261 struct ddraw_surface *surface = impl_from_IDirectDrawSurface2(iface);
3263 TRACE("iface %p, flags %#x, color_key %p.\n", iface, flags, color_key);
3265 return ddraw_surface7_GetColorKey(&surface->IDirectDrawSurface7_iface, flags, color_key);
3268 static HRESULT WINAPI ddraw_surface1_GetColorKey(IDirectDrawSurface *iface, DWORD flags, DDCOLORKEY *color_key)
3270 struct ddraw_surface *surface = impl_from_IDirectDrawSurface(iface);
3272 TRACE("iface %p, flags %#x, color_key %p.\n", iface, flags, color_key);
3274 return ddraw_surface7_GetColorKey(&surface->IDirectDrawSurface7_iface, flags, color_key);
3277 /*****************************************************************************
3278 * IDirectDrawSurface7::GetFlipStatus
3280 * Returns the flipping status of the surface
3282 * Params:
3283 * Flags: DDGFS_CANFLIP of DDGFS_ISFLIPDONE
3285 *****************************************************************************/
3286 static HRESULT WINAPI ddraw_surface7_GetFlipStatus(IDirectDrawSurface7 *iface, DWORD Flags)
3288 TRACE("iface %p, flags %#x.\n", iface, Flags);
3290 /* XXX: DDERR_INVALIDSURFACETYPE */
3292 switch (Flags)
3294 case WINEDDGFS_CANFLIP:
3295 case WINEDDGFS_ISFLIPDONE:
3296 return DD_OK;
3298 default:
3299 return DDERR_INVALIDPARAMS;
3303 static HRESULT WINAPI ddraw_surface4_GetFlipStatus(IDirectDrawSurface4 *iface, DWORD flags)
3305 struct ddraw_surface *surface = impl_from_IDirectDrawSurface4(iface);
3307 TRACE("iface %p, flags %#x.\n", iface, flags);
3309 return ddraw_surface7_GetFlipStatus(&surface->IDirectDrawSurface7_iface, flags);
3312 static HRESULT WINAPI ddraw_surface3_GetFlipStatus(IDirectDrawSurface3 *iface, DWORD flags)
3314 struct ddraw_surface *surface = impl_from_IDirectDrawSurface3(iface);
3316 TRACE("iface %p, flags %#x.\n", iface, flags);
3318 return ddraw_surface7_GetFlipStatus(&surface->IDirectDrawSurface7_iface, flags);
3321 static HRESULT WINAPI ddraw_surface2_GetFlipStatus(IDirectDrawSurface2 *iface, DWORD flags)
3323 struct ddraw_surface *surface = impl_from_IDirectDrawSurface2(iface);
3325 TRACE("iface %p, flags %#x.\n", iface, flags);
3327 return ddraw_surface7_GetFlipStatus(&surface->IDirectDrawSurface7_iface, flags);
3330 static HRESULT WINAPI ddraw_surface1_GetFlipStatus(IDirectDrawSurface *iface, DWORD flags)
3332 struct ddraw_surface *surface = impl_from_IDirectDrawSurface(iface);
3334 TRACE("iface %p, flags %#x.\n", iface, flags);
3336 return ddraw_surface7_GetFlipStatus(&surface->IDirectDrawSurface7_iface, flags);
3339 /*****************************************************************************
3340 * IDirectDrawSurface7::GetOverlayPosition
3342 * Returns the display coordinates of a visible and active overlay surface
3344 * Params:
3348 * Returns:
3349 * DDERR_NOTAOVERLAYSURFACE, because it's a stub
3350 *****************************************************************************/
3351 static HRESULT WINAPI ddraw_surface7_GetOverlayPosition(IDirectDrawSurface7 *iface, LONG *x, LONG *y)
3353 struct ddraw_surface *surface = impl_from_IDirectDrawSurface7(iface);
3354 HRESULT hr;
3356 TRACE("iface %p, x %p, y %p.\n", iface, x, y);
3358 wined3d_mutex_lock();
3359 hr = wined3d_texture_get_overlay_position(surface->wined3d_texture,
3360 surface->sub_resource_idx, x, y);
3361 wined3d_mutex_unlock();
3363 return hr;
3366 static HRESULT WINAPI ddraw_surface4_GetOverlayPosition(IDirectDrawSurface4 *iface, LONG *x, LONG *y)
3368 struct ddraw_surface *surface = impl_from_IDirectDrawSurface4(iface);
3370 TRACE("iface %p, x %p, y %p.\n", iface, x, y);
3372 return ddraw_surface7_GetOverlayPosition(&surface->IDirectDrawSurface7_iface, x, y);
3375 static HRESULT WINAPI ddraw_surface3_GetOverlayPosition(IDirectDrawSurface3 *iface, LONG *x, LONG *y)
3377 struct ddraw_surface *surface = impl_from_IDirectDrawSurface3(iface);
3379 TRACE("iface %p, x %p, y %p.\n", iface, x, y);
3381 return ddraw_surface7_GetOverlayPosition(&surface->IDirectDrawSurface7_iface, x, y);
3384 static HRESULT WINAPI ddraw_surface2_GetOverlayPosition(IDirectDrawSurface2 *iface, LONG *x, LONG *y)
3386 struct ddraw_surface *surface = impl_from_IDirectDrawSurface2(iface);
3388 TRACE("iface %p, x %p, y %p.\n", iface, x, y);
3390 return ddraw_surface7_GetOverlayPosition(&surface->IDirectDrawSurface7_iface, x, y);
3393 static HRESULT WINAPI ddraw_surface1_GetOverlayPosition(IDirectDrawSurface *iface, LONG *x, LONG *y)
3395 struct ddraw_surface *surface = impl_from_IDirectDrawSurface(iface);
3397 TRACE("iface %p, x %p, y %p.\n", iface, x, y);
3399 return ddraw_surface7_GetOverlayPosition(&surface->IDirectDrawSurface7_iface, x, y);
3402 /*****************************************************************************
3403 * IDirectDrawSurface7::GetPixelFormat
3405 * Returns the pixel format of the Surface
3407 * Params:
3408 * PixelFormat: Pointer to a DDPIXELFORMAT structure to which the pixel
3409 * format should be written
3411 * Returns:
3412 * DD_OK on success
3413 * DDERR_INVALIDPARAMS if PixelFormat is NULL
3415 *****************************************************************************/
3416 static HRESULT WINAPI ddraw_surface7_GetPixelFormat(IDirectDrawSurface7 *iface, DDPIXELFORMAT *PixelFormat)
3418 /* What is DDERR_INVALIDSURFACETYPE for here? */
3419 struct ddraw_surface *surface = impl_from_IDirectDrawSurface7(iface);
3421 TRACE("iface %p, pixel_format %p.\n", iface, PixelFormat);
3423 if(!PixelFormat)
3424 return DDERR_INVALIDPARAMS;
3426 wined3d_mutex_lock();
3427 DD_STRUCT_COPY_BYSIZE(PixelFormat, &surface->surface_desc.u4.ddpfPixelFormat);
3428 wined3d_mutex_unlock();
3430 return DD_OK;
3433 static HRESULT WINAPI ddraw_surface4_GetPixelFormat(IDirectDrawSurface4 *iface, DDPIXELFORMAT *pixel_format)
3435 struct ddraw_surface *surface = impl_from_IDirectDrawSurface4(iface);
3437 TRACE("iface %p, pixel_format %p.\n", iface, pixel_format);
3439 return ddraw_surface7_GetPixelFormat(&surface->IDirectDrawSurface7_iface, pixel_format);
3442 static HRESULT WINAPI ddraw_surface3_GetPixelFormat(IDirectDrawSurface3 *iface, DDPIXELFORMAT *pixel_format)
3444 struct ddraw_surface *surface = impl_from_IDirectDrawSurface3(iface);
3446 TRACE("iface %p, pixel_format %p.\n", iface, pixel_format);
3448 return ddraw_surface7_GetPixelFormat(&surface->IDirectDrawSurface7_iface, pixel_format);
3451 static HRESULT WINAPI ddraw_surface2_GetPixelFormat(IDirectDrawSurface2 *iface, DDPIXELFORMAT *pixel_format)
3453 struct ddraw_surface *surface = impl_from_IDirectDrawSurface2(iface);
3455 TRACE("iface %p, pixel_format %p.\n", iface, pixel_format);
3457 return ddraw_surface7_GetPixelFormat(&surface->IDirectDrawSurface7_iface, pixel_format);
3460 static HRESULT WINAPI ddraw_surface1_GetPixelFormat(IDirectDrawSurface *iface, DDPIXELFORMAT *pixel_format)
3462 struct ddraw_surface *surface = impl_from_IDirectDrawSurface(iface);
3464 TRACE("iface %p, pixel_format %p.\n", iface, pixel_format);
3466 return ddraw_surface7_GetPixelFormat(&surface->IDirectDrawSurface7_iface, pixel_format);
3469 /*****************************************************************************
3470 * IDirectDrawSurface7::GetSurfaceDesc
3472 * Returns the description of this surface
3474 * Params:
3475 * DDSD: Address of a DDSURFACEDESC2 structure that is to be filled with the
3476 * surface desc
3478 * Returns:
3479 * DD_OK on success
3480 * DDERR_INVALIDPARAMS if DDSD is NULL
3482 *****************************************************************************/
3483 static HRESULT WINAPI ddraw_surface7_GetSurfaceDesc(IDirectDrawSurface7 *iface, DDSURFACEDESC2 *DDSD)
3485 struct ddraw_surface *surface = impl_from_IDirectDrawSurface7(iface);
3487 TRACE("iface %p, surface_desc %p.\n", iface, DDSD);
3489 if(!DDSD)
3490 return DDERR_INVALIDPARAMS;
3492 if (DDSD->dwSize != sizeof(DDSURFACEDESC2))
3494 WARN("Incorrect struct size %d, returning DDERR_INVALIDPARAMS\n",DDSD->dwSize);
3495 return DDERR_INVALIDPARAMS;
3498 wined3d_mutex_lock();
3499 DD_STRUCT_COPY_BYSIZE(DDSD, &surface->surface_desc);
3500 TRACE("Returning surface desc:\n");
3501 if (TRACE_ON(ddraw)) DDRAW_dump_surface_desc(DDSD);
3502 wined3d_mutex_unlock();
3504 return DD_OK;
3507 static HRESULT WINAPI ddraw_surface4_GetSurfaceDesc(IDirectDrawSurface4 *iface, DDSURFACEDESC2 *DDSD)
3509 struct ddraw_surface *surface = impl_from_IDirectDrawSurface4(iface);
3511 TRACE("iface %p, surface_desc %p.\n", iface, DDSD);
3513 return ddraw_surface7_GetSurfaceDesc(&surface->IDirectDrawSurface7_iface, DDSD);
3516 static HRESULT WINAPI ddraw_surface3_GetSurfaceDesc(IDirectDrawSurface3 *iface, DDSURFACEDESC *surface_desc)
3518 struct ddraw_surface *surface = impl_from_IDirectDrawSurface3(iface);
3520 TRACE("iface %p, surface_desc %p.\n", iface, surface_desc);
3522 if (!surface_desc) return DDERR_INVALIDPARAMS;
3524 if (surface_desc->dwSize != sizeof(DDSURFACEDESC))
3526 WARN("Incorrect structure size %u, returning DDERR_INVALIDPARAMS.\n", surface_desc->dwSize);
3527 return DDERR_INVALIDPARAMS;
3530 wined3d_mutex_lock();
3531 DDSD2_to_DDSD(&surface->surface_desc, surface_desc);
3532 TRACE("Returning surface desc:\n");
3533 if (TRACE_ON(ddraw))
3535 /* DDRAW_dump_surface_desc handles the smaller size */
3536 DDRAW_dump_surface_desc((DDSURFACEDESC2 *)surface_desc);
3538 wined3d_mutex_unlock();
3540 return DD_OK;
3543 static HRESULT WINAPI ddraw_surface2_GetSurfaceDesc(IDirectDrawSurface2 *iface, DDSURFACEDESC *DDSD)
3545 struct ddraw_surface *surface = impl_from_IDirectDrawSurface2(iface);
3547 TRACE("iface %p, surface_desc %p.\n", iface, DDSD);
3549 return ddraw_surface3_GetSurfaceDesc(&surface->IDirectDrawSurface3_iface, DDSD);
3552 static HRESULT WINAPI ddraw_surface1_GetSurfaceDesc(IDirectDrawSurface *iface, DDSURFACEDESC *DDSD)
3554 struct ddraw_surface *surface = impl_from_IDirectDrawSurface(iface);
3556 TRACE("iface %p, surface_desc %p.\n", iface, DDSD);
3558 return ddraw_surface3_GetSurfaceDesc(&surface->IDirectDrawSurface3_iface, DDSD);
3561 /*****************************************************************************
3562 * IDirectDrawSurface7::Initialize
3564 * Initializes the surface. This is a no-op in Wine
3566 * Params:
3567 * DD: Pointer to an DirectDraw interface
3568 * DDSD: Surface description for initialization
3570 * Returns:
3571 * DDERR_ALREADYINITIALIZED
3573 *****************************************************************************/
3574 static HRESULT WINAPI ddraw_surface7_Initialize(IDirectDrawSurface7 *iface,
3575 IDirectDraw *ddraw, DDSURFACEDESC2 *surface_desc)
3577 TRACE("iface %p, ddraw %p, surface_desc %p.\n", iface, ddraw, surface_desc);
3579 return DDERR_ALREADYINITIALIZED;
3582 static HRESULT WINAPI ddraw_surface4_Initialize(IDirectDrawSurface4 *iface,
3583 IDirectDraw *ddraw, DDSURFACEDESC2 *surface_desc)
3585 struct ddraw_surface *surface = impl_from_IDirectDrawSurface4(iface);
3587 TRACE("iface %p, ddraw %p, surface_desc %p.\n", iface, ddraw, surface_desc);
3589 return ddraw_surface7_Initialize(&surface->IDirectDrawSurface7_iface,
3590 ddraw, surface_desc);
3593 static HRESULT WINAPI ddraw_surface3_Initialize(IDirectDrawSurface3 *iface,
3594 IDirectDraw *ddraw, DDSURFACEDESC *surface_desc)
3596 struct ddraw_surface *surface = impl_from_IDirectDrawSurface3(iface);
3597 DDSURFACEDESC2 surface_desc2;
3599 TRACE("iface %p, ddraw %p, surface_desc %p.\n", iface, ddraw, surface_desc);
3601 if (surface_desc) DDSD_to_DDSD2(surface_desc, &surface_desc2);
3602 return ddraw_surface7_Initialize(&surface->IDirectDrawSurface7_iface,
3603 ddraw, surface_desc ? &surface_desc2 : NULL);
3606 static HRESULT WINAPI ddraw_surface2_Initialize(IDirectDrawSurface2 *iface,
3607 IDirectDraw *ddraw, DDSURFACEDESC *surface_desc)
3609 struct ddraw_surface *surface = impl_from_IDirectDrawSurface2(iface);
3610 DDSURFACEDESC2 surface_desc2;
3612 TRACE("iface %p, ddraw %p, surface_desc %p.\n", iface, ddraw, surface_desc);
3614 if (surface_desc) DDSD_to_DDSD2(surface_desc, &surface_desc2);
3615 return ddraw_surface7_Initialize(&surface->IDirectDrawSurface7_iface,
3616 ddraw, surface_desc ? &surface_desc2 : NULL);
3619 static HRESULT WINAPI ddraw_surface1_Initialize(IDirectDrawSurface *iface,
3620 IDirectDraw *ddraw, DDSURFACEDESC *surface_desc)
3622 struct ddraw_surface *surface = impl_from_IDirectDrawSurface(iface);
3623 DDSURFACEDESC2 surface_desc2;
3625 TRACE("iface %p, ddraw %p, surface_desc %p.\n", iface, ddraw, surface_desc);
3627 if (surface_desc) DDSD_to_DDSD2(surface_desc, &surface_desc2);
3628 return ddraw_surface7_Initialize(&surface->IDirectDrawSurface7_iface,
3629 ddraw, surface_desc ? &surface_desc2 : NULL);
3632 /*****************************************************************************
3633 * IDirect3DTexture1::Initialize
3635 * The sdk says it's not implemented
3637 * Params:
3640 * Returns
3641 * DDERR_UNSUPPORTED
3643 *****************************************************************************/
3644 static HRESULT WINAPI d3d_texture1_Initialize(IDirect3DTexture *iface,
3645 IDirect3DDevice *device, IDirectDrawSurface *surface)
3647 TRACE("iface %p, device %p, surface %p.\n", iface, device, surface);
3649 return DDERR_UNSUPPORTED; /* Unchecked */
3652 /*****************************************************************************
3653 * IDirectDrawSurface7::IsLost
3655 * Checks if the surface is lost
3657 * Returns:
3658 * DD_OK, if the surface is usable
3659 * DDERR_ISLOST if the surface is lost
3661 *****************************************************************************/
3662 static HRESULT WINAPI ddraw_surface7_IsLost(IDirectDrawSurface7 *iface)
3664 struct ddraw_surface *surface = impl_from_IDirectDrawSurface7(iface);
3666 TRACE("iface %p.\n", iface);
3668 if (surface->ddraw->device_state != DDRAW_DEVICE_STATE_OK || surface->is_lost)
3669 return DDERR_SURFACELOST;
3671 return DD_OK;
3674 static HRESULT WINAPI ddraw_surface4_IsLost(IDirectDrawSurface4 *iface)
3676 struct ddraw_surface *surface = impl_from_IDirectDrawSurface4(iface);
3678 TRACE("iface %p.\n", iface);
3680 return ddraw_surface7_IsLost(&surface->IDirectDrawSurface7_iface);
3683 static HRESULT WINAPI ddraw_surface3_IsLost(IDirectDrawSurface3 *iface)
3685 struct ddraw_surface *surface = impl_from_IDirectDrawSurface3(iface);
3687 TRACE("iface %p.\n", iface);
3689 return ddraw_surface7_IsLost(&surface->IDirectDrawSurface7_iface);
3692 static HRESULT WINAPI ddraw_surface2_IsLost(IDirectDrawSurface2 *iface)
3694 struct ddraw_surface *surface = impl_from_IDirectDrawSurface2(iface);
3696 TRACE("iface %p.\n", iface);
3698 return ddraw_surface7_IsLost(&surface->IDirectDrawSurface7_iface);
3701 static HRESULT WINAPI ddraw_surface1_IsLost(IDirectDrawSurface *iface)
3703 struct ddraw_surface *surface = impl_from_IDirectDrawSurface(iface);
3705 TRACE("iface %p.\n", iface);
3707 return ddraw_surface7_IsLost(&surface->IDirectDrawSurface7_iface);
3710 /*****************************************************************************
3711 * IDirectDrawSurface7::Restore
3713 * Restores a lost surface. This makes the surface usable again, but
3714 * doesn't reload its old contents
3716 * Returns:
3717 * DD_OK on success, error code otherwise.
3719 *****************************************************************************/
3720 static HRESULT WINAPI ddraw_surface7_Restore(IDirectDrawSurface7 *iface)
3722 struct ddraw_surface *surface = impl_from_IDirectDrawSurface7(iface);
3724 TRACE("iface %p.\n", iface);
3726 if (surface->surface_desc.ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE)
3728 struct wined3d_swapchain *swapchain = surface->ddraw->wined3d_swapchain;
3729 struct wined3d_sub_resource_desc wined3d_desc;
3730 struct wined3d_display_mode mode;
3731 HRESULT hr;
3733 if (FAILED(hr = wined3d_swapchain_get_display_mode(swapchain, &mode, NULL)))
3735 WARN("Failed to get display mode, hr %#x.\n", hr);
3736 return hr;
3739 if (FAILED(hr = wined3d_texture_get_sub_resource_desc(surface->wined3d_texture, 0, &wined3d_desc)))
3741 WARN("Failed to get resource desc, hr %#x.\n", hr);
3742 return hr;
3745 if (mode.width != wined3d_desc.width || mode.height != wined3d_desc.height)
3747 WARN("Display mode dimensions %ux%u don't match surface dimensions %ux%u.\n",
3748 mode.width, mode.height, wined3d_desc.width, wined3d_desc.height);
3749 return DDERR_WRONGMODE;
3752 if (mode.format_id != wined3d_desc.format)
3754 WARN("Display mode format %#x doesn't match surface format %#x.\n",
3755 mode.format_id, wined3d_desc.format);
3756 return DDERR_WRONGMODE;
3760 ddraw_update_lost_surfaces(surface->ddraw);
3761 surface->is_lost = FALSE;
3763 return DD_OK;
3766 static HRESULT WINAPI ddraw_surface4_Restore(IDirectDrawSurface4 *iface)
3768 struct ddraw_surface *surface = impl_from_IDirectDrawSurface4(iface);
3770 TRACE("iface %p.\n", iface);
3772 return ddraw_surface7_Restore(&surface->IDirectDrawSurface7_iface);
3775 static HRESULT WINAPI ddraw_surface3_Restore(IDirectDrawSurface3 *iface)
3777 struct ddraw_surface *surface = impl_from_IDirectDrawSurface3(iface);
3779 TRACE("iface %p.\n", iface);
3781 return ddraw_surface7_Restore(&surface->IDirectDrawSurface7_iface);
3784 static HRESULT WINAPI ddraw_surface2_Restore(IDirectDrawSurface2 *iface)
3786 struct ddraw_surface *surface = impl_from_IDirectDrawSurface2(iface);
3788 TRACE("iface %p.\n", iface);
3790 return ddraw_surface7_Restore(&surface->IDirectDrawSurface7_iface);
3793 static HRESULT WINAPI ddraw_surface1_Restore(IDirectDrawSurface *iface)
3795 struct ddraw_surface *surface = impl_from_IDirectDrawSurface(iface);
3797 TRACE("iface %p.\n", iface);
3799 return ddraw_surface7_Restore(&surface->IDirectDrawSurface7_iface);
3802 /*****************************************************************************
3803 * IDirectDrawSurface7::SetOverlayPosition
3805 * Changes the display coordinates of an overlay surface
3807 * Params:
3808 * X:
3809 * Y:
3811 * Returns:
3812 * DDERR_NOTAOVERLAYSURFACE, because we don't support overlays right now
3813 *****************************************************************************/
3814 static HRESULT WINAPI ddraw_surface7_SetOverlayPosition(IDirectDrawSurface7 *iface, LONG x, LONG y)
3816 struct ddraw_surface *surface = impl_from_IDirectDrawSurface7(iface);
3817 HRESULT hr;
3819 TRACE("iface %p, x %d, y %d.\n", iface, x, y);
3821 wined3d_mutex_lock();
3822 hr = wined3d_texture_set_overlay_position(surface->wined3d_texture,
3823 surface->sub_resource_idx, x, y);
3824 wined3d_mutex_unlock();
3826 return hr;
3829 static HRESULT WINAPI ddraw_surface4_SetOverlayPosition(IDirectDrawSurface4 *iface, LONG x, LONG y)
3831 struct ddraw_surface *surface = impl_from_IDirectDrawSurface4(iface);
3833 TRACE("iface %p, x %d, y %d.\n", iface, x, y);
3835 return ddraw_surface7_SetOverlayPosition(&surface->IDirectDrawSurface7_iface, x, y);
3838 static HRESULT WINAPI ddraw_surface3_SetOverlayPosition(IDirectDrawSurface3 *iface, LONG x, LONG y)
3840 struct ddraw_surface *surface = impl_from_IDirectDrawSurface3(iface);
3842 TRACE("iface %p, x %d, y %d.\n", iface, x, y);
3844 return ddraw_surface7_SetOverlayPosition(&surface->IDirectDrawSurface7_iface, x, y);
3847 static HRESULT WINAPI ddraw_surface2_SetOverlayPosition(IDirectDrawSurface2 *iface, LONG x, LONG y)
3849 struct ddraw_surface *surface = impl_from_IDirectDrawSurface2(iface);
3851 TRACE("iface %p, x %d, y %d.\n", iface, x, y);
3853 return ddraw_surface7_SetOverlayPosition(&surface->IDirectDrawSurface7_iface, x, y);
3856 static HRESULT WINAPI ddraw_surface1_SetOverlayPosition(IDirectDrawSurface *iface, LONG x, LONG y)
3858 struct ddraw_surface *surface = impl_from_IDirectDrawSurface(iface);
3860 TRACE("iface %p, x %d, y %d.\n", iface, x, y);
3862 return ddraw_surface7_SetOverlayPosition(&surface->IDirectDrawSurface7_iface, x, y);
3865 /*****************************************************************************
3866 * IDirectDrawSurface7::UpdateOverlay
3868 * Modifies the attributes of an overlay surface.
3870 * Params:
3871 * SrcRect: The section of the source being used for the overlay
3872 * DstSurface: Address of the surface that is overlaid
3873 * DstRect: Place of the overlay
3874 * Flags: some DDOVER_* flags
3876 * Returns:
3877 * DDERR_UNSUPPORTED, because we don't support overlays
3879 *****************************************************************************/
3880 static HRESULT WINAPI ddraw_surface7_UpdateOverlay(IDirectDrawSurface7 *iface, RECT *src_rect,
3881 IDirectDrawSurface7 *dst_surface, RECT *dst_rect, DWORD flags, DDOVERLAYFX *fx)
3883 struct ddraw_surface *src_impl = impl_from_IDirectDrawSurface7(iface);
3884 struct ddraw_surface *dst_impl = unsafe_impl_from_IDirectDrawSurface7(dst_surface);
3885 struct wined3d_texture *dst_wined3d_texture = NULL;
3886 unsigned int dst_sub_resource_idx = 0;
3887 HRESULT hr;
3889 TRACE("iface %p, src_rect %s, dst_surface %p, dst_rect %s, flags %#x, fx %p.\n",
3890 iface, wine_dbgstr_rect(src_rect), dst_surface, wine_dbgstr_rect(dst_rect), flags, fx);
3892 if (fx)
3893 FIXME("Ignoring fx %p.\n", fx);
3895 wined3d_mutex_lock();
3896 if (dst_impl)
3898 dst_wined3d_texture = dst_impl->wined3d_texture;
3899 dst_sub_resource_idx = dst_impl->sub_resource_idx;
3901 hr = wined3d_texture_update_overlay(src_impl->wined3d_texture, src_impl->sub_resource_idx,
3902 src_rect, dst_wined3d_texture, dst_sub_resource_idx, dst_rect, flags);
3903 wined3d_mutex_unlock();
3905 switch (hr)
3907 case WINED3DERR_INVALIDCALL: return DDERR_INVALIDPARAMS;
3908 case WINEDDERR_NOTAOVERLAYSURFACE: return DDERR_NOTAOVERLAYSURFACE;
3909 case WINEDDERR_OVERLAYNOTVISIBLE: return DDERR_OVERLAYNOTVISIBLE;
3910 default:
3911 return hr;
3915 static HRESULT WINAPI ddraw_surface4_UpdateOverlay(IDirectDrawSurface4 *iface, RECT *src_rect,
3916 IDirectDrawSurface4 *dst_surface, RECT *dst_rect, DWORD flags, DDOVERLAYFX *fx)
3918 struct ddraw_surface *src_impl = impl_from_IDirectDrawSurface4(iface);
3919 struct ddraw_surface *dst_impl = unsafe_impl_from_IDirectDrawSurface4(dst_surface);
3921 TRACE("iface %p, src_rect %s, dst_surface %p, dst_rect %s, flags %#x, fx %p.\n",
3922 iface, wine_dbgstr_rect(src_rect), dst_surface, wine_dbgstr_rect(dst_rect), flags, fx);
3924 return ddraw_surface7_UpdateOverlay(&src_impl->IDirectDrawSurface7_iface, src_rect,
3925 dst_impl ? &dst_impl->IDirectDrawSurface7_iface : NULL, dst_rect, flags, fx);
3928 static HRESULT WINAPI ddraw_surface3_UpdateOverlay(IDirectDrawSurface3 *iface, RECT *src_rect,
3929 IDirectDrawSurface3 *dst_surface, RECT *dst_rect, DWORD flags, DDOVERLAYFX *fx)
3931 struct ddraw_surface *src_impl = impl_from_IDirectDrawSurface3(iface);
3932 struct ddraw_surface *dst_impl = unsafe_impl_from_IDirectDrawSurface3(dst_surface);
3934 TRACE("iface %p, src_rect %s, dst_surface %p, dst_rect %s, flags %#x, fx %p.\n",
3935 iface, wine_dbgstr_rect(src_rect), dst_surface, wine_dbgstr_rect(dst_rect), flags, fx);
3937 return ddraw_surface7_UpdateOverlay(&src_impl->IDirectDrawSurface7_iface, src_rect,
3938 dst_impl ? &dst_impl->IDirectDrawSurface7_iface : NULL, dst_rect, flags, fx);
3941 static HRESULT WINAPI ddraw_surface2_UpdateOverlay(IDirectDrawSurface2 *iface, RECT *src_rect,
3942 IDirectDrawSurface2 *dst_surface, RECT *dst_rect, DWORD flags, DDOVERLAYFX *fx)
3944 struct ddraw_surface *src_impl = impl_from_IDirectDrawSurface2(iface);
3945 struct ddraw_surface *dst_impl = unsafe_impl_from_IDirectDrawSurface2(dst_surface);
3947 TRACE("iface %p, src_rect %s, dst_surface %p, dst_rect %s, flags %#x, fx %p.\n",
3948 iface, wine_dbgstr_rect(src_rect), dst_surface, wine_dbgstr_rect(dst_rect), flags, fx);
3950 return ddraw_surface7_UpdateOverlay(&src_impl->IDirectDrawSurface7_iface, src_rect,
3951 dst_impl ? &dst_impl->IDirectDrawSurface7_iface : NULL, dst_rect, flags, fx);
3954 static HRESULT WINAPI ddraw_surface1_UpdateOverlay(IDirectDrawSurface *iface, RECT *src_rect,
3955 IDirectDrawSurface *dst_surface, RECT *dst_rect, DWORD flags, DDOVERLAYFX *fx)
3957 struct ddraw_surface *src_impl = impl_from_IDirectDrawSurface(iface);
3958 struct ddraw_surface *dst_impl = unsafe_impl_from_IDirectDrawSurface(dst_surface);
3960 TRACE("iface %p, src_rect %s, dst_surface %p, dst_rect %s, flags %#x, fx %p.\n",
3961 iface, wine_dbgstr_rect(src_rect), dst_surface, wine_dbgstr_rect(dst_rect), flags, fx);
3963 return ddraw_surface7_UpdateOverlay(&src_impl->IDirectDrawSurface7_iface, src_rect,
3964 dst_impl ? &dst_impl->IDirectDrawSurface7_iface : NULL, dst_rect, flags, fx);
3967 /*****************************************************************************
3968 * IDirectDrawSurface7::UpdateOverlayDisplay
3970 * The DX7 sdk says that it's not implemented
3972 * Params:
3973 * Flags: ?
3975 * Returns: DDERR_UNSUPPORTED, because we don't support overlays
3977 *****************************************************************************/
3978 static HRESULT WINAPI ddraw_surface7_UpdateOverlayDisplay(IDirectDrawSurface7 *iface, DWORD Flags)
3980 TRACE("iface %p, flags %#x.\n", iface, Flags);
3982 return DDERR_UNSUPPORTED;
3985 static HRESULT WINAPI ddraw_surface4_UpdateOverlayDisplay(IDirectDrawSurface4 *iface, DWORD flags)
3987 struct ddraw_surface *surface = impl_from_IDirectDrawSurface4(iface);
3989 TRACE("iface %p, flags %#x.\n", iface, flags);
3991 return ddraw_surface7_UpdateOverlayDisplay(&surface->IDirectDrawSurface7_iface, flags);
3994 static HRESULT WINAPI ddraw_surface3_UpdateOverlayDisplay(IDirectDrawSurface3 *iface, DWORD flags)
3996 struct ddraw_surface *surface = impl_from_IDirectDrawSurface3(iface);
3998 TRACE("iface %p, flags %#x.\n", iface, flags);
4000 return ddraw_surface7_UpdateOverlayDisplay(&surface->IDirectDrawSurface7_iface, flags);
4003 static HRESULT WINAPI ddraw_surface2_UpdateOverlayDisplay(IDirectDrawSurface2 *iface, DWORD flags)
4005 struct ddraw_surface *surface = impl_from_IDirectDrawSurface2(iface);
4007 TRACE("iface %p, flags %#x.\n", iface, flags);
4009 return ddraw_surface7_UpdateOverlayDisplay(&surface->IDirectDrawSurface7_iface, flags);
4012 static HRESULT WINAPI ddraw_surface1_UpdateOverlayDisplay(IDirectDrawSurface *iface, DWORD flags)
4014 struct ddraw_surface *surface = impl_from_IDirectDrawSurface(iface);
4016 TRACE("iface %p, flags %#x.\n", iface, flags);
4018 return ddraw_surface7_UpdateOverlayDisplay(&surface->IDirectDrawSurface7_iface, flags);
4021 /*****************************************************************************
4022 * IDirectDrawSurface7::UpdateOverlayZOrder
4024 * Sets an overlay's Z order
4026 * Params:
4027 * Flags: DDOVERZ_* flags
4028 * DDSRef: Defines the relative position in the overlay chain
4030 * Returns:
4031 * DDERR_NOTOVERLAYSURFACE, because we don't support overlays
4033 *****************************************************************************/
4034 static HRESULT WINAPI ddraw_surface7_UpdateOverlayZOrder(IDirectDrawSurface7 *iface,
4035 DWORD flags, IDirectDrawSurface7 *reference)
4037 struct ddraw_surface *surface = impl_from_IDirectDrawSurface7(iface);
4039 FIXME("iface %p, flags %#x, reference %p stub!\n", iface, flags, reference);
4041 wined3d_mutex_lock();
4042 if (!(surface->surface_desc.ddsCaps.dwCaps & DDSCAPS_OVERLAY))
4044 WARN("Not an overlay surface.\n");
4045 wined3d_mutex_unlock();
4046 return DDERR_NOTAOVERLAYSURFACE;
4048 wined3d_mutex_unlock();
4050 return DD_OK;
4053 static HRESULT WINAPI ddraw_surface4_UpdateOverlayZOrder(IDirectDrawSurface4 *iface,
4054 DWORD flags, IDirectDrawSurface4 *reference)
4056 struct ddraw_surface *surface = impl_from_IDirectDrawSurface4(iface);
4057 struct ddraw_surface *reference_impl = unsafe_impl_from_IDirectDrawSurface4(reference);
4059 TRACE("iface %p, flags %#x, reference %p.\n", iface, flags, reference);
4061 return ddraw_surface7_UpdateOverlayZOrder(&surface->IDirectDrawSurface7_iface, flags,
4062 reference_impl ? &reference_impl->IDirectDrawSurface7_iface : NULL);
4065 static HRESULT WINAPI ddraw_surface3_UpdateOverlayZOrder(IDirectDrawSurface3 *iface,
4066 DWORD flags, IDirectDrawSurface3 *reference)
4068 struct ddraw_surface *surface = impl_from_IDirectDrawSurface3(iface);
4069 struct ddraw_surface *reference_impl = unsafe_impl_from_IDirectDrawSurface3(reference);
4071 TRACE("iface %p, flags %#x, reference %p.\n", iface, flags, reference);
4073 return ddraw_surface7_UpdateOverlayZOrder(&surface->IDirectDrawSurface7_iface, flags,
4074 reference_impl ? &reference_impl->IDirectDrawSurface7_iface : NULL);
4077 static HRESULT WINAPI ddraw_surface2_UpdateOverlayZOrder(IDirectDrawSurface2 *iface,
4078 DWORD flags, IDirectDrawSurface2 *reference)
4080 struct ddraw_surface *surface = impl_from_IDirectDrawSurface2(iface);
4081 struct ddraw_surface *reference_impl = unsafe_impl_from_IDirectDrawSurface2(reference);
4083 TRACE("iface %p, flags %#x, reference %p.\n", iface, flags, reference);
4085 return ddraw_surface7_UpdateOverlayZOrder(&surface->IDirectDrawSurface7_iface, flags,
4086 reference_impl ? &reference_impl->IDirectDrawSurface7_iface : NULL);
4089 static HRESULT WINAPI ddraw_surface1_UpdateOverlayZOrder(IDirectDrawSurface *iface,
4090 DWORD flags, IDirectDrawSurface *reference)
4092 struct ddraw_surface *surface = impl_from_IDirectDrawSurface(iface);
4093 struct ddraw_surface *reference_impl = unsafe_impl_from_IDirectDrawSurface(reference);
4095 TRACE("iface %p, flags %#x, reference %p.\n", iface, flags, reference);
4097 return ddraw_surface7_UpdateOverlayZOrder(&surface->IDirectDrawSurface7_iface, flags,
4098 reference_impl ? &reference_impl->IDirectDrawSurface7_iface : NULL);
4101 /*****************************************************************************
4102 * IDirectDrawSurface7::GetDDInterface
4104 * Returns the IDirectDraw7 interface pointer of the DirectDraw object this
4105 * surface belongs to
4107 * Params:
4108 * DD: Address to write the interface pointer to
4110 * Returns:
4111 * DD_OK on success
4112 * DDERR_INVALIDPARAMS if DD is NULL
4114 *****************************************************************************/
4115 static HRESULT WINAPI ddraw_surface7_GetDDInterface(IDirectDrawSurface7 *iface, void **DD)
4117 struct ddraw_surface *This = impl_from_IDirectDrawSurface7(iface);
4119 TRACE("iface %p, ddraw %p.\n", iface, DD);
4121 if(!DD)
4122 return DDERR_INVALIDPARAMS;
4124 switch(This->version)
4126 case 7:
4127 *DD = &This->ddraw->IDirectDraw7_iface;
4128 break;
4130 case 4:
4131 *DD = &This->ddraw->IDirectDraw4_iface;
4132 break;
4134 case 2:
4135 *DD = &This->ddraw->IDirectDraw2_iface;
4136 break;
4138 case 1:
4139 *DD = &This->ddraw->IDirectDraw_iface;
4140 break;
4143 IUnknown_AddRef((IUnknown *)*DD);
4145 return DD_OK;
4148 static HRESULT WINAPI ddraw_surface4_GetDDInterface(IDirectDrawSurface4 *iface, void **ddraw)
4150 struct ddraw_surface *surface = impl_from_IDirectDrawSurface4(iface);
4152 TRACE("iface %p, ddraw %p.\n", iface, ddraw);
4154 return ddraw_surface7_GetDDInterface(&surface->IDirectDrawSurface7_iface, ddraw);
4157 static HRESULT WINAPI ddraw_surface3_GetDDInterface(IDirectDrawSurface3 *iface, void **ddraw)
4159 struct ddraw_surface *surface = impl_from_IDirectDrawSurface3(iface);
4161 TRACE("iface %p, ddraw %p.\n", iface, ddraw);
4163 return ddraw_surface7_GetDDInterface(&surface->IDirectDrawSurface7_iface, ddraw);
4166 static HRESULT WINAPI ddraw_surface2_GetDDInterface(IDirectDrawSurface2 *iface, void **ddraw)
4168 struct ddraw_surface *surface = impl_from_IDirectDrawSurface2(iface);
4170 TRACE("iface %p, ddraw %p.\n", iface, ddraw);
4172 return ddraw_surface7_GetDDInterface(&surface->IDirectDrawSurface7_iface, ddraw);
4175 static HRESULT WINAPI ddraw_surface7_ChangeUniquenessValue(IDirectDrawSurface7 *iface)
4177 TRACE("iface %p.\n", iface);
4179 return DD_OK;
4182 static HRESULT WINAPI ddraw_surface4_ChangeUniquenessValue(IDirectDrawSurface4 *iface)
4184 struct ddraw_surface *surface = impl_from_IDirectDrawSurface4(iface);
4186 TRACE("iface %p.\n", iface);
4188 return ddraw_surface7_ChangeUniquenessValue(&surface->IDirectDrawSurface7_iface);
4191 static HRESULT WINAPI ddraw_surface7_GetUniquenessValue(IDirectDrawSurface7 *iface, DWORD *pValue)
4193 TRACE("iface %p, value %p.\n", iface, pValue);
4195 *pValue = 0;
4197 return DD_OK;
4200 static HRESULT WINAPI ddraw_surface4_GetUniquenessValue(IDirectDrawSurface4 *iface, DWORD *pValue)
4202 struct ddraw_surface *surface = impl_from_IDirectDrawSurface4(iface);
4204 TRACE("iface %p, value %p.\n", iface, pValue);
4206 return ddraw_surface7_GetUniquenessValue(&surface->IDirectDrawSurface7_iface, pValue);
4209 /*****************************************************************************
4210 * IDirectDrawSurface7::SetLOD
4212 * Sets the level of detail of a texture
4214 * Params:
4215 * MaxLOD: LOD to set
4217 * Returns:
4218 * DD_OK on success
4219 * DDERR_INVALIDOBJECT if the surface is invalid for this method
4221 *****************************************************************************/
4222 static HRESULT WINAPI ddraw_surface7_SetLOD(IDirectDrawSurface7 *iface, DWORD MaxLOD)
4224 struct ddraw_surface *surface = impl_from_IDirectDrawSurface7(iface);
4225 HRESULT hr;
4227 TRACE("iface %p, lod %u.\n", iface, MaxLOD);
4229 wined3d_mutex_lock();
4230 if (!(surface->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_TEXTUREMANAGE))
4232 wined3d_mutex_unlock();
4233 return DDERR_INVALIDOBJECT;
4236 hr = wined3d_texture_set_lod(surface->wined3d_texture, MaxLOD);
4237 wined3d_mutex_unlock();
4239 return hr;
4242 /*****************************************************************************
4243 * IDirectDrawSurface7::GetLOD
4245 * Returns the level of detail of a Direct3D texture
4247 * Params:
4248 * MaxLOD: Address to write the LOD to
4250 * Returns:
4251 * DD_OK on success
4252 * DDERR_INVALIDPARAMS if MaxLOD is NULL
4253 * DDERR_INVALIDOBJECT if the surface is invalid for this method
4255 *****************************************************************************/
4256 static HRESULT WINAPI ddraw_surface7_GetLOD(IDirectDrawSurface7 *iface, DWORD *MaxLOD)
4258 struct ddraw_surface *surface = impl_from_IDirectDrawSurface7(iface);
4260 TRACE("iface %p, lod %p.\n", iface, MaxLOD);
4262 if(!MaxLOD)
4263 return DDERR_INVALIDPARAMS;
4265 wined3d_mutex_lock();
4266 if (!(surface->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_TEXTUREMANAGE))
4268 wined3d_mutex_unlock();
4269 return DDERR_INVALIDOBJECT;
4272 *MaxLOD = wined3d_texture_get_lod(surface->wined3d_texture);
4273 wined3d_mutex_unlock();
4275 return DD_OK;
4278 /*****************************************************************************
4279 * IDirectDrawSurface7::BltFast
4281 * Performs a fast Blit.
4283 * Params:
4284 * dstx: The x coordinate to blit to on the destination
4285 * dsty: The y coordinate to blit to on the destination
4286 * Source: The source surface
4287 * rsrc: The source rectangle
4288 * trans: Type of transfer. Some DDBLTFAST_* flags
4290 * Returns:
4291 * DD_OK on success, error code otherwise.
4293 *****************************************************************************/
4294 static HRESULT WINAPI DECLSPEC_HOTPATCH ddraw_surface7_BltFast(IDirectDrawSurface7 *iface,
4295 DWORD dst_x, DWORD dst_y, IDirectDrawSurface7 *src_surface, RECT *src_rect, DWORD trans)
4297 struct ddraw_surface *dst_impl = impl_from_IDirectDrawSurface7(iface);
4298 struct ddraw_surface *src_impl = unsafe_impl_from_IDirectDrawSurface7(src_surface);
4299 DWORD flags = WINED3D_BLT_SYNCHRONOUS;
4300 DWORD src_w, src_h, dst_w, dst_h;
4301 HRESULT hr = DD_OK;
4302 RECT dst_rect, s;
4304 TRACE("iface %p, dst_x %u, dst_y %u, src_surface %p, src_rect %s, flags %#x.\n",
4305 iface, dst_x, dst_y, src_surface, wine_dbgstr_rect(src_rect), trans);
4307 dst_w = dst_impl->surface_desc.dwWidth;
4308 dst_h = dst_impl->surface_desc.dwHeight;
4310 if (!src_rect)
4312 SetRect(&s, 0, 0, src_impl->surface_desc.dwWidth, src_impl->surface_desc.dwHeight);
4313 src_rect = &s;
4316 src_w = src_rect->right - src_rect->left;
4317 src_h = src_rect->bottom - src_rect->top;
4318 if (src_w > dst_w || dst_x > dst_w - src_w
4319 || src_h > dst_h || dst_y > dst_h - src_h)
4321 WARN("Destination area out of bounds, returning DDERR_INVALIDRECT.\n");
4322 return DDERR_INVALIDRECT;
4325 SetRect(&dst_rect, dst_x, dst_y, dst_x + src_w, dst_y + src_h);
4326 if (trans & DDBLTFAST_SRCCOLORKEY)
4327 flags |= WINED3D_BLT_SRC_CKEY;
4328 if (trans & DDBLTFAST_DESTCOLORKEY)
4329 flags |= WINED3D_BLT_DST_CKEY;
4330 if (trans & DDBLTFAST_WAIT)
4331 flags |= WINED3D_BLT_WAIT;
4332 if (trans & DDBLTFAST_DONOTWAIT)
4333 flags |= WINED3D_BLT_DO_NOT_WAIT;
4335 wined3d_mutex_lock();
4336 if (dst_impl->clipper)
4338 wined3d_mutex_unlock();
4339 WARN("Destination surface has a clipper set, returning DDERR_BLTFASTCANTCLIP.\n");
4340 return DDERR_BLTFASTCANTCLIP;
4343 if (src_impl->surface_desc.ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE)
4344 hr = ddraw_surface_update_frontbuffer(src_impl, src_rect, TRUE, 0);
4345 if (SUCCEEDED(hr))
4346 hr = wined3d_texture_blt(dst_impl->wined3d_texture, dst_impl->sub_resource_idx, &dst_rect,
4347 src_impl->wined3d_texture, src_impl->sub_resource_idx, src_rect, flags, NULL, WINED3D_TEXF_POINT);
4348 if (SUCCEEDED(hr) && (dst_impl->surface_desc.ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE))
4349 hr = ddraw_surface_update_frontbuffer(dst_impl, &dst_rect, FALSE, 0);
4350 wined3d_mutex_unlock();
4352 switch(hr)
4354 case WINED3DERR_NOTAVAILABLE: return DDERR_UNSUPPORTED;
4355 default: return hr;
4359 static HRESULT WINAPI DECLSPEC_HOTPATCH ddraw_surface4_BltFast(IDirectDrawSurface4 *iface, DWORD dst_x, DWORD dst_y,
4360 IDirectDrawSurface4 *src_surface, RECT *src_rect, DWORD flags)
4362 struct ddraw_surface *dst_impl = impl_from_IDirectDrawSurface4(iface);
4363 struct ddraw_surface *src_impl = unsafe_impl_from_IDirectDrawSurface4(src_surface);
4365 TRACE("iface %p, dst_x %u, dst_y %u, src_surface %p, src_rect %s, flags %#x.\n",
4366 iface, dst_x, dst_y, src_surface, wine_dbgstr_rect(src_rect), flags);
4368 return ddraw_surface7_BltFast(&dst_impl->IDirectDrawSurface7_iface, dst_x, dst_y,
4369 src_impl ? &src_impl->IDirectDrawSurface7_iface : NULL, src_rect, flags);
4372 static HRESULT WINAPI DECLSPEC_HOTPATCH ddraw_surface3_BltFast(IDirectDrawSurface3 *iface, DWORD dst_x, DWORD dst_y,
4373 IDirectDrawSurface3 *src_surface, RECT *src_rect, DWORD flags)
4375 struct ddraw_surface *dst_impl = impl_from_IDirectDrawSurface3(iface);
4376 struct ddraw_surface *src_impl = unsafe_impl_from_IDirectDrawSurface3(src_surface);
4378 TRACE("iface %p, dst_x %u, dst_y %u, src_surface %p, src_rect %s, flags %#x.\n",
4379 iface, dst_x, dst_y, src_surface, wine_dbgstr_rect(src_rect), flags);
4381 return ddraw_surface7_BltFast(&dst_impl->IDirectDrawSurface7_iface, dst_x, dst_y,
4382 src_impl ? &src_impl->IDirectDrawSurface7_iface : NULL, src_rect, flags);
4385 static HRESULT WINAPI DECLSPEC_HOTPATCH ddraw_surface2_BltFast(IDirectDrawSurface2 *iface, DWORD dst_x, DWORD dst_y,
4386 IDirectDrawSurface2 *src_surface, RECT *src_rect, DWORD flags)
4388 struct ddraw_surface *dst_impl = impl_from_IDirectDrawSurface2(iface);
4389 struct ddraw_surface *src_impl = unsafe_impl_from_IDirectDrawSurface2(src_surface);
4391 TRACE("iface %p, dst_x %u, dst_y %u, src_surface %p, src_rect %s, flags %#x.\n",
4392 iface, dst_x, dst_y, src_surface, wine_dbgstr_rect(src_rect), flags);
4394 return ddraw_surface7_BltFast(&dst_impl->IDirectDrawSurface7_iface, dst_x, dst_y,
4395 src_impl ? &src_impl->IDirectDrawSurface7_iface : NULL, src_rect, flags);
4398 static HRESULT WINAPI DECLSPEC_HOTPATCH ddraw_surface1_BltFast(IDirectDrawSurface *iface, DWORD dst_x, DWORD dst_y,
4399 IDirectDrawSurface *src_surface, RECT *src_rect, DWORD flags)
4401 struct ddraw_surface *dst_impl = impl_from_IDirectDrawSurface(iface);
4402 struct ddraw_surface *src_impl = unsafe_impl_from_IDirectDrawSurface(src_surface);
4404 TRACE("iface %p, dst_x %u, dst_y %u, src_surface %p, src_rect %s, flags %#x.\n",
4405 iface, dst_x, dst_y, src_surface, wine_dbgstr_rect(src_rect), flags);
4407 return ddraw_surface7_BltFast(&dst_impl->IDirectDrawSurface7_iface, dst_x, dst_y,
4408 src_impl ? &src_impl->IDirectDrawSurface7_iface : NULL, src_rect, flags);
4411 /*****************************************************************************
4412 * IDirectDrawSurface7::GetClipper
4414 * Returns the IDirectDrawClipper interface of the clipper assigned to this
4415 * surface
4417 * Params:
4418 * Clipper: Address to store the interface pointer at
4420 * Returns:
4421 * DD_OK on success
4422 * DDERR_INVALIDPARAMS if Clipper is NULL
4423 * DDERR_NOCLIPPERATTACHED if there's no clipper attached
4425 *****************************************************************************/
4426 static HRESULT WINAPI ddraw_surface7_GetClipper(IDirectDrawSurface7 *iface, IDirectDrawClipper **Clipper)
4428 struct ddraw_surface *surface = impl_from_IDirectDrawSurface7(iface);
4430 TRACE("iface %p, clipper %p.\n", iface, Clipper);
4432 if (!Clipper)
4433 return DDERR_INVALIDPARAMS;
4435 wined3d_mutex_lock();
4436 if (!surface->clipper)
4438 wined3d_mutex_unlock();
4439 return DDERR_NOCLIPPERATTACHED;
4442 *Clipper = &surface->clipper->IDirectDrawClipper_iface;
4443 IDirectDrawClipper_AddRef(*Clipper);
4444 wined3d_mutex_unlock();
4446 return DD_OK;
4449 static HRESULT WINAPI ddraw_surface4_GetClipper(IDirectDrawSurface4 *iface, IDirectDrawClipper **clipper)
4451 struct ddraw_surface *surface = impl_from_IDirectDrawSurface4(iface);
4453 TRACE("iface %p, clipper %p.\n", iface, clipper);
4455 return ddraw_surface7_GetClipper(&surface->IDirectDrawSurface7_iface, clipper);
4458 static HRESULT WINAPI ddraw_surface3_GetClipper(IDirectDrawSurface3 *iface, IDirectDrawClipper **clipper)
4460 struct ddraw_surface *surface = impl_from_IDirectDrawSurface3(iface);
4462 TRACE("iface %p, clipper %p.\n", iface, clipper);
4464 return ddraw_surface7_GetClipper(&surface->IDirectDrawSurface7_iface, clipper);
4467 static HRESULT WINAPI ddraw_surface2_GetClipper(IDirectDrawSurface2 *iface, IDirectDrawClipper **clipper)
4469 struct ddraw_surface *surface = impl_from_IDirectDrawSurface2(iface);
4471 TRACE("iface %p, clipper %p.\n", iface, clipper);
4473 return ddraw_surface7_GetClipper(&surface->IDirectDrawSurface7_iface, clipper);
4476 static HRESULT WINAPI ddraw_surface1_GetClipper(IDirectDrawSurface *iface, IDirectDrawClipper **clipper)
4478 struct ddraw_surface *surface = impl_from_IDirectDrawSurface(iface);
4480 TRACE("iface %p, clipper %p.\n", iface, clipper);
4482 return ddraw_surface7_GetClipper(&surface->IDirectDrawSurface7_iface, clipper);
4485 /*****************************************************************************
4486 * IDirectDrawSurface7::SetClipper
4488 * Sets a clipper for the surface
4490 * Params:
4491 * Clipper: IDirectDrawClipper interface of the clipper to set
4493 * Returns:
4494 * DD_OK on success
4496 *****************************************************************************/
4497 static HRESULT WINAPI ddraw_surface7_SetClipper(IDirectDrawSurface7 *iface,
4498 IDirectDrawClipper *iclipper)
4500 struct ddraw_surface *This = impl_from_IDirectDrawSurface7(iface);
4501 struct ddraw_clipper *clipper = unsafe_impl_from_IDirectDrawClipper(iclipper);
4502 struct ddraw_clipper *old_clipper = This->clipper;
4503 HWND clipWindow;
4505 TRACE("iface %p, clipper %p.\n", iface, iclipper);
4507 wined3d_mutex_lock();
4508 if (clipper == This->clipper)
4510 wined3d_mutex_unlock();
4511 return DD_OK;
4514 This->clipper = clipper;
4516 if (clipper != NULL)
4517 IDirectDrawClipper_AddRef(iclipper);
4518 if (old_clipper)
4519 IDirectDrawClipper_Release(&old_clipper->IDirectDrawClipper_iface);
4521 if ((This->surface_desc.ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE) && This->ddraw->wined3d_swapchain)
4523 clipWindow = NULL;
4524 if(clipper) {
4525 IDirectDrawClipper_GetHWnd(iclipper, &clipWindow);
4528 if (clipWindow)
4530 wined3d_swapchain_set_window(This->ddraw->wined3d_swapchain, clipWindow);
4531 ddraw_set_swapchain_window(This->ddraw, clipWindow);
4533 else
4535 wined3d_swapchain_set_window(This->ddraw->wined3d_swapchain, This->ddraw->d3d_window);
4536 ddraw_set_swapchain_window(This->ddraw, This->ddraw->dest_window);
4540 wined3d_mutex_unlock();
4542 return DD_OK;
4545 static HRESULT WINAPI ddraw_surface4_SetClipper(IDirectDrawSurface4 *iface, IDirectDrawClipper *clipper)
4547 struct ddraw_surface *surface = impl_from_IDirectDrawSurface4(iface);
4549 TRACE("iface %p, clipper %p.\n", iface, clipper);
4551 return ddraw_surface7_SetClipper(&surface->IDirectDrawSurface7_iface, clipper);
4554 static HRESULT WINAPI ddraw_surface3_SetClipper(IDirectDrawSurface3 *iface, IDirectDrawClipper *clipper)
4556 struct ddraw_surface *surface = impl_from_IDirectDrawSurface3(iface);
4558 TRACE("iface %p, clipper %p.\n", iface, clipper);
4560 return ddraw_surface7_SetClipper(&surface->IDirectDrawSurface7_iface, clipper);
4563 static HRESULT WINAPI ddraw_surface2_SetClipper(IDirectDrawSurface2 *iface, IDirectDrawClipper *clipper)
4565 struct ddraw_surface *surface = impl_from_IDirectDrawSurface2(iface);
4567 TRACE("iface %p, clipper %p.\n", iface, clipper);
4569 return ddraw_surface7_SetClipper(&surface->IDirectDrawSurface7_iface, clipper);
4572 static HRESULT WINAPI ddraw_surface1_SetClipper(IDirectDrawSurface *iface, IDirectDrawClipper *clipper)
4574 struct ddraw_surface *surface = impl_from_IDirectDrawSurface(iface);
4576 TRACE("iface %p, clipper %p.\n", iface, clipper);
4578 return ddraw_surface7_SetClipper(&surface->IDirectDrawSurface7_iface, clipper);
4581 /*****************************************************************************
4582 * IDirectDrawSurface7::SetSurfaceDesc
4584 * Sets the surface description. It can override the pixel format, the surface
4585 * memory, ...
4586 * It's not really tested.
4588 * Params:
4589 * DDSD: Pointer to the new surface description to set
4590 * Flags: Some flags
4592 * Returns:
4593 * DD_OK on success
4594 * DDERR_INVALIDPARAMS if DDSD is NULL
4596 *****************************************************************************/
4597 static HRESULT WINAPI ddraw_surface7_SetSurfaceDesc(IDirectDrawSurface7 *iface, DDSURFACEDESC2 *DDSD, DWORD Flags)
4599 struct ddraw_surface *This = impl_from_IDirectDrawSurface7(iface);
4600 HRESULT hr;
4601 const DWORD allowed_flags = DDSD_LPSURFACE | DDSD_PIXELFORMAT | DDSD_WIDTH
4602 | DDSD_HEIGHT | DDSD_PITCH | DDSD_CAPS;
4603 enum wined3d_format_id format_id;
4604 UINT pitch, width, height;
4606 TRACE("iface %p, surface_desc %p, flags %#x.\n", iface, DDSD, Flags);
4608 if (!DDSD)
4610 WARN("DDSD is NULL, returning DDERR_INVALIDPARAMS\n");
4611 return DDERR_INVALIDPARAMS;
4613 if (Flags)
4615 WARN("Flags is %x, returning DDERR_INVALIDPARAMS\n", Flags);
4616 return DDERR_INVALIDPARAMS;
4618 if (!(This->surface_desc.ddsCaps.dwCaps & DDSCAPS_SYSTEMMEMORY)
4619 || This->surface_desc.ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE
4620 || This->surface_desc.ddsCaps.dwCaps2 & (DDSCAPS2_TEXTUREMANAGE | DDSCAPS2_D3DTEXTUREMANAGE))
4622 WARN("Surface is not in system memory, returning DDERR_INVALIDSURFACETYPE.\n");
4623 return DDERR_INVALIDSURFACETYPE;
4626 /* Tests show that only LPSURFACE and PIXELFORMAT can be set, and LPSURFACE is required
4627 * for PIXELFORMAT to work */
4628 if (DDSD->dwFlags & ~allowed_flags)
4630 WARN("Invalid flags (0x%08x) set, returning DDERR_INVALIDPARAMS\n", DDSD->dwFlags);
4631 return DDERR_INVALIDPARAMS;
4633 if (!(DDSD->dwFlags & DDSD_LPSURFACE) || !DDSD->lpSurface)
4635 WARN("DDSD_LPSURFACE is not set or lpSurface is NULL, returning DDERR_INVALIDPARAMS\n");
4636 return DDERR_INVALIDPARAMS;
4638 if ((DDSD->dwFlags & DDSD_CAPS) && DDSD->ddsCaps.dwCaps)
4640 WARN("DDSD_CAPS is set, returning DDERR_INVALIDCAPS.\n");
4641 return DDERR_INVALIDCAPS;
4643 if (DDSD->dwFlags & DDSD_WIDTH)
4645 if (!(DDSD->dwFlags & DDSD_PITCH))
4647 WARN("DDSD_WIDTH is set, but DDSD_PITCH is not, returning DDERR_INVALIDPARAMS.\n");
4648 return DDERR_INVALIDPARAMS;
4650 if (!DDSD->dwWidth || DDSD->u1.lPitch <= 0 || DDSD->u1.lPitch & 0x3)
4652 WARN("Pitch is %d, width is %u, returning DDERR_INVALIDPARAMS.\n",
4653 DDSD->u1.lPitch, DDSD->dwWidth);
4654 return DDERR_INVALIDPARAMS;
4656 if (DDSD->dwWidth != This->surface_desc.dwWidth)
4657 TRACE("Surface width changed from %u to %u.\n", This->surface_desc.dwWidth, DDSD->dwWidth);
4658 if (DDSD->u1.lPitch != This->surface_desc.u1.lPitch)
4659 TRACE("Surface pitch changed from %u to %u.\n", This->surface_desc.u1.lPitch, DDSD->u1.lPitch);
4660 pitch = DDSD->u1.lPitch;
4661 width = DDSD->dwWidth;
4663 else if (DDSD->dwFlags & DDSD_PITCH)
4665 WARN("DDSD_PITCH is set, but DDSD_WIDTH is not, returning DDERR_INVALIDPARAMS.\n");
4666 return DDERR_INVALIDPARAMS;
4668 else
4670 pitch = This->surface_desc.u1.lPitch;
4671 width = This->surface_desc.dwWidth;
4674 if (DDSD->dwFlags & DDSD_HEIGHT)
4676 if (!DDSD->dwHeight)
4678 WARN("Height is 0, returning DDERR_INVALIDPARAMS.\n");
4679 return DDERR_INVALIDPARAMS;
4681 if (DDSD->dwHeight != This->surface_desc.dwHeight)
4682 TRACE("Surface height changed from %u to %u.\n", This->surface_desc.dwHeight, DDSD->dwHeight);
4683 height = DDSD->dwHeight;
4685 else
4687 height = This->surface_desc.dwHeight;
4690 wined3d_mutex_lock();
4691 if (DDSD->dwFlags & DDSD_PIXELFORMAT)
4693 enum wined3d_format_id current_format_id;
4694 format_id = wined3dformat_from_ddrawformat(&DDSD->u4.ddpfPixelFormat);
4696 if (format_id == WINED3DFMT_UNKNOWN)
4698 ERR("Requested to set an unknown pixelformat\n");
4699 wined3d_mutex_unlock();
4700 return DDERR_INVALIDPARAMS;
4702 current_format_id = wined3dformat_from_ddrawformat(&This->surface_desc.u4.ddpfPixelFormat);
4703 if (format_id != current_format_id)
4704 TRACE("Surface format changed from %#x to %#x.\n", current_format_id, format_id);
4706 else
4708 format_id = wined3dformat_from_ddrawformat(&This->surface_desc.u4.ddpfPixelFormat);
4711 if (FAILED(hr = wined3d_texture_update_desc(This->wined3d_texture, width, height,
4712 format_id, WINED3D_MULTISAMPLE_NONE, 0, DDSD->lpSurface, pitch)))
4714 WARN("Failed to update surface desc, hr %#x.\n", hr);
4715 wined3d_mutex_unlock();
4716 return hr_ddraw_from_wined3d(hr);
4719 if (DDSD->dwFlags & DDSD_WIDTH)
4720 This->surface_desc.dwWidth = width;
4721 if (DDSD->dwFlags & DDSD_PITCH)
4722 This->surface_desc.u1.lPitch = DDSD->u1.lPitch;
4723 if (DDSD->dwFlags & DDSD_HEIGHT)
4724 This->surface_desc.dwHeight = height;
4725 if (DDSD->dwFlags & DDSD_PIXELFORMAT)
4726 This->surface_desc.u4.ddpfPixelFormat = DDSD->u4.ddpfPixelFormat;
4728 wined3d_mutex_unlock();
4730 return DD_OK;
4733 static HRESULT WINAPI ddraw_surface4_SetSurfaceDesc(IDirectDrawSurface4 *iface,
4734 DDSURFACEDESC2 *surface_desc, DWORD flags)
4736 struct ddraw_surface *surface = impl_from_IDirectDrawSurface4(iface);
4738 TRACE("iface %p, surface_desc %p, flags %#x.\n", iface, surface_desc, flags);
4740 return ddraw_surface7_SetSurfaceDesc(&surface->IDirectDrawSurface7_iface,
4741 surface_desc, flags);
4744 static HRESULT WINAPI ddraw_surface3_SetSurfaceDesc(IDirectDrawSurface3 *iface,
4745 DDSURFACEDESC *surface_desc, DWORD flags)
4747 struct ddraw_surface *surface = impl_from_IDirectDrawSurface3(iface);
4748 DDSURFACEDESC2 surface_desc2;
4750 TRACE("iface %p, surface_desc %p, flags %#x.\n", iface, surface_desc, flags);
4752 if (surface_desc) DDSD_to_DDSD2(surface_desc, &surface_desc2);
4753 return ddraw_surface7_SetSurfaceDesc(&surface->IDirectDrawSurface7_iface,
4754 surface_desc ? &surface_desc2 : NULL, flags);
4757 static HRESULT WINAPI ddraw_surface7_GetPalette(IDirectDrawSurface7 *iface, IDirectDrawPalette **palette)
4759 struct ddraw_surface *surface = impl_from_IDirectDrawSurface7(iface);
4760 struct ddraw_palette *palette_impl;
4761 HRESULT hr = DD_OK;
4763 TRACE("iface %p, palette %p.\n", iface, palette);
4765 if (!palette)
4766 return DDERR_INVALIDPARAMS;
4767 if (IDirectDrawSurface7_IsLost(iface) == DDERR_SURFACELOST)
4769 WARN("Surface lost, returning DDERR_SURFACELOST.\n");
4770 return DDERR_SURFACELOST;
4773 wined3d_mutex_lock();
4774 if ((palette_impl = surface->palette))
4776 *palette = &palette_impl->IDirectDrawPalette_iface;
4777 IDirectDrawPalette_AddRef(*palette);
4779 else
4781 *palette = NULL;
4782 hr = DDERR_NOPALETTEATTACHED;
4784 wined3d_mutex_unlock();
4786 return hr;
4789 static HRESULT WINAPI ddraw_surface4_GetPalette(IDirectDrawSurface4 *iface, IDirectDrawPalette **palette)
4791 struct ddraw_surface *surface = impl_from_IDirectDrawSurface4(iface);
4793 TRACE("iface %p, palette %p.\n", iface, palette);
4795 return ddraw_surface7_GetPalette(&surface->IDirectDrawSurface7_iface, palette);
4798 static HRESULT WINAPI ddraw_surface3_GetPalette(IDirectDrawSurface3 *iface, IDirectDrawPalette **palette)
4800 struct ddraw_surface *surface = impl_from_IDirectDrawSurface3(iface);
4802 TRACE("iface %p, palette %p.\n", iface, palette);
4804 return ddraw_surface7_GetPalette(&surface->IDirectDrawSurface7_iface, palette);
4807 static HRESULT WINAPI ddraw_surface2_GetPalette(IDirectDrawSurface2 *iface, IDirectDrawPalette **palette)
4809 struct ddraw_surface *surface = impl_from_IDirectDrawSurface2(iface);
4811 TRACE("iface %p, palette %p.\n", iface, palette);
4813 return ddraw_surface7_GetPalette(&surface->IDirectDrawSurface7_iface, palette);
4816 static HRESULT WINAPI ddraw_surface1_GetPalette(IDirectDrawSurface *iface, IDirectDrawPalette **palette)
4818 struct ddraw_surface *surface = impl_from_IDirectDrawSurface(iface);
4820 TRACE("iface %p, palette %p.\n", iface, palette);
4822 return ddraw_surface7_GetPalette(&surface->IDirectDrawSurface7_iface, palette);
4825 static HRESULT ddraw_surface_set_color_key(struct ddraw_surface *surface, DWORD flags, DDCOLORKEY *color_key)
4827 DDCOLORKEY fixed_color_key;
4828 HRESULT hr = WINED3D_OK;
4830 if (flags & DDCKEY_COLORSPACE)
4832 if (color_key && color_key->dwColorSpaceLowValue != color_key->dwColorSpaceHighValue)
4834 WARN("Range color keys are not supported, returning DDERR_NOCOLORKEYHW.\n");
4835 return DDERR_NOCOLORKEYHW;
4837 flags &= ~DDCKEY_COLORSPACE;
4840 wined3d_mutex_lock();
4842 if (color_key)
4844 fixed_color_key.dwColorSpaceLowValue = fixed_color_key.dwColorSpaceHighValue = color_key->dwColorSpaceLowValue;
4845 switch (flags & ~DDCKEY_COLORSPACE)
4847 case DDCKEY_DESTBLT:
4848 surface->surface_desc.ddckCKDestBlt = fixed_color_key;
4849 surface->surface_desc.dwFlags |= DDSD_CKDESTBLT;
4850 break;
4852 case DDCKEY_DESTOVERLAY:
4853 surface->surface_desc.u3.ddckCKDestOverlay = fixed_color_key;
4854 surface->surface_desc.dwFlags |= DDSD_CKDESTOVERLAY;
4855 break;
4857 case DDCKEY_SRCOVERLAY:
4858 surface->surface_desc.ddckCKSrcOverlay = fixed_color_key;
4859 surface->surface_desc.dwFlags |= DDSD_CKSRCOVERLAY;
4860 break;
4862 case DDCKEY_SRCBLT:
4863 surface->surface_desc.ddckCKSrcBlt = fixed_color_key;
4864 surface->surface_desc.dwFlags |= DDSD_CKSRCBLT;
4865 break;
4867 default:
4868 wined3d_mutex_unlock();
4869 return DDERR_INVALIDPARAMS;
4872 else
4874 switch (flags & ~DDCKEY_COLORSPACE)
4876 case DDCKEY_DESTBLT:
4877 surface->surface_desc.dwFlags &= ~DDSD_CKDESTBLT;
4878 break;
4880 case DDCKEY_DESTOVERLAY:
4881 surface->surface_desc.dwFlags &= ~DDSD_CKDESTOVERLAY;
4882 break;
4884 case DDCKEY_SRCOVERLAY:
4885 surface->surface_desc.dwFlags &= ~DDSD_CKSRCOVERLAY;
4886 break;
4888 case DDCKEY_SRCBLT:
4889 surface->surface_desc.dwFlags &= ~DDSD_CKSRCBLT;
4890 break;
4892 default:
4893 wined3d_mutex_unlock();
4894 return DDERR_INVALIDPARAMS;
4898 if (surface->is_complex_root)
4899 hr = wined3d_texture_set_color_key(surface->wined3d_texture, flags,
4900 color_key ? (struct wined3d_color_key *)&fixed_color_key : NULL);
4902 wined3d_mutex_unlock();
4904 return hr_ddraw_from_wined3d(hr);
4907 static HRESULT WINAPI ddraw_surface7_SetColorKey(IDirectDrawSurface7 *iface, DWORD flags, DDCOLORKEY *color_key)
4909 struct ddraw_surface *surface = impl_from_IDirectDrawSurface7(iface);
4911 TRACE("iface %p, flags %#x, color_key %p.\n", iface, flags, color_key);
4913 if (surface->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_MIPMAPSUBLEVEL)
4914 return DDERR_NOTONMIPMAPSUBLEVEL;
4916 return ddraw_surface_set_color_key(surface, flags, color_key);
4919 static HRESULT WINAPI ddraw_surface4_SetColorKey(IDirectDrawSurface4 *iface, DWORD flags, DDCOLORKEY *color_key)
4921 struct ddraw_surface *surface = impl_from_IDirectDrawSurface4(iface);
4923 TRACE("iface %p, flags %#x, color_key %p.\n", iface, flags, color_key);
4925 return ddraw_surface_set_color_key(surface, flags, color_key);
4928 static HRESULT WINAPI ddraw_surface3_SetColorKey(IDirectDrawSurface3 *iface, DWORD flags, DDCOLORKEY *color_key)
4930 struct ddraw_surface *surface = impl_from_IDirectDrawSurface3(iface);
4932 TRACE("iface %p, flags %#x, color_key %p.\n", iface, flags, color_key);
4934 return ddraw_surface_set_color_key(surface, flags, color_key);
4937 static HRESULT WINAPI ddraw_surface2_SetColorKey(IDirectDrawSurface2 *iface, DWORD flags, DDCOLORKEY *color_key)
4939 struct ddraw_surface *surface = impl_from_IDirectDrawSurface2(iface);
4941 TRACE("iface %p, flags %#x, color_key %p.\n", iface, flags, color_key);
4943 return ddraw_surface_set_color_key(surface, flags, color_key);
4946 static HRESULT WINAPI ddraw_surface1_SetColorKey(IDirectDrawSurface *iface, DWORD flags, DDCOLORKEY *color_key)
4948 struct ddraw_surface *surface = impl_from_IDirectDrawSurface(iface);
4950 TRACE("iface %p, flags %#x, color_key %p.\n", iface, flags, color_key);
4952 return ddraw_surface_set_color_key(surface, flags, color_key);
4955 static HRESULT WINAPI ddraw_surface7_SetPalette(IDirectDrawSurface7 *iface, IDirectDrawPalette *palette)
4957 struct ddraw_surface *surface = impl_from_IDirectDrawSurface7(iface);
4959 TRACE("iface %p, palette %p.\n", iface, palette);
4961 if (surface->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_MIPMAPSUBLEVEL)
4962 return DDERR_NOTONMIPMAPSUBLEVEL;
4963 if (IDirectDrawSurface7_IsLost(iface) == DDERR_SURFACELOST)
4965 WARN("Surface lost, returning DDERR_SURFACELOST.\n");
4966 return DDERR_SURFACELOST;
4969 return ddraw_surface_set_palette(surface, palette);
4972 static HRESULT WINAPI ddraw_surface4_SetPalette(IDirectDrawSurface4 *iface, IDirectDrawPalette *palette)
4974 struct ddraw_surface *surface = impl_from_IDirectDrawSurface4(iface);
4976 TRACE("iface %p, palette %p.\n", iface, palette);
4978 if (IDirectDrawSurface4_IsLost(iface) == DDERR_SURFACELOST)
4980 WARN("Surface lost, returning DDERR_SURFACELOST.\n");
4981 return DDERR_SURFACELOST;
4984 return ddraw_surface_set_palette(surface, palette);
4987 static HRESULT WINAPI ddraw_surface3_SetPalette(IDirectDrawSurface3 *iface, IDirectDrawPalette *palette)
4989 struct ddraw_surface *surface = impl_from_IDirectDrawSurface3(iface);
4991 TRACE("iface %p, palette %p.\n", iface, palette);
4993 if (IDirectDrawSurface3_IsLost(iface) == DDERR_SURFACELOST)
4995 WARN("Surface lost, returning DDERR_SURFACELOST.\n");
4996 return DDERR_SURFACELOST;
4999 return ddraw_surface_set_palette(surface, palette);
5002 static HRESULT WINAPI ddraw_surface2_SetPalette(IDirectDrawSurface2 *iface, IDirectDrawPalette *palette)
5004 struct ddraw_surface *surface = impl_from_IDirectDrawSurface2(iface);
5006 TRACE("iface %p, palette %p.\n", iface, palette);
5008 if (IDirectDrawSurface2_IsLost(iface) == DDERR_SURFACELOST)
5010 WARN("Surface lost, returning DDERR_SURFACELOST.\n");
5011 return DDERR_SURFACELOST;
5014 return ddraw_surface_set_palette(surface, palette);
5017 static HRESULT WINAPI ddraw_surface1_SetPalette(IDirectDrawSurface *iface, IDirectDrawPalette *palette)
5019 struct ddraw_surface *surface = impl_from_IDirectDrawSurface(iface);
5021 TRACE("iface %p, palette %p.\n", iface, palette);
5023 if (IDirectDrawSurface_IsLost(iface) == DDERR_SURFACELOST)
5025 WARN("Surface lost, returning DDERR_SURFACELOST.\n");
5026 return DDERR_SURFACELOST;
5029 return ddraw_surface_set_palette(surface, palette);
5032 /**********************************************************
5033 * IDirectDrawGammaControl::GetGammaRamp
5035 * Returns the current gamma ramp for a surface
5037 * Params:
5038 * flags: Ignored
5039 * gamma_ramp: Address to write the ramp to
5041 * Returns:
5042 * DD_OK on success
5043 * DDERR_INVALIDPARAMS if gamma_ramp is NULL
5045 **********************************************************/
5046 static HRESULT WINAPI ddraw_gamma_control_GetGammaRamp(IDirectDrawGammaControl *iface,
5047 DWORD flags, DDGAMMARAMP *gamma_ramp)
5049 struct ddraw_surface *surface = impl_from_IDirectDrawGammaControl(iface);
5051 TRACE("iface %p, flags %#x, gamma_ramp %p.\n", iface, flags, gamma_ramp);
5053 if (!gamma_ramp)
5055 WARN("Invalid gamma_ramp passed.\n");
5056 return DDERR_INVALIDPARAMS;
5059 wined3d_mutex_lock();
5060 if (surface->surface_desc.ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE)
5062 /* Note: DDGAMMARAMP is compatible with struct wined3d_gamma_ramp. */
5063 wined3d_device_get_gamma_ramp(surface->ddraw->wined3d_device, 0, (struct wined3d_gamma_ramp *)gamma_ramp);
5065 else
5067 ERR("Not implemented for non-primary surfaces.\n");
5069 wined3d_mutex_unlock();
5071 return DD_OK;
5074 /**********************************************************
5075 * IDirectDrawGammaControl::SetGammaRamp
5077 * Sets the red, green and blue gamma ramps for
5079 * Params:
5080 * flags: Can be DDSGR_CALIBRATE to request calibration
5081 * gamma_ramp: Structure containing the new gamma ramp
5083 * Returns:
5084 * DD_OK on success
5085 * DDERR_INVALIDPARAMS if gamma_ramp is NULL
5087 **********************************************************/
5088 static HRESULT WINAPI ddraw_gamma_control_SetGammaRamp(IDirectDrawGammaControl *iface,
5089 DWORD flags, DDGAMMARAMP *gamma_ramp)
5091 struct ddraw_surface *surface = impl_from_IDirectDrawGammaControl(iface);
5093 TRACE("iface %p, flags %#x, gamma_ramp %p.\n", iface, flags, gamma_ramp);
5095 if (!gamma_ramp)
5097 WARN("Invalid gamma_ramp passed.\n");
5098 return DDERR_INVALIDPARAMS;
5101 wined3d_mutex_lock();
5102 if (surface->surface_desc.ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE)
5104 /* Note: DDGAMMARAMP is compatible with struct wined3d_gamma_ramp. */
5105 wined3d_device_set_gamma_ramp(surface->ddraw->wined3d_device,
5106 0, flags, (struct wined3d_gamma_ramp *)gamma_ramp);
5108 else
5110 ERR("Not implemented for non-primary surfaces.\n");
5112 wined3d_mutex_unlock();
5114 return DD_OK;
5117 /*****************************************************************************
5118 * IDirect3DTexture2::PaletteChanged
5120 * Informs the texture about a palette change
5122 * Params:
5123 * start: Start index of the change
5124 * count: The number of changed entries
5126 * Returns
5127 * D3D_OK, because it's a stub
5129 *****************************************************************************/
5130 static HRESULT WINAPI d3d_texture2_PaletteChanged(IDirect3DTexture2 *iface, DWORD start, DWORD count)
5132 FIXME("iface %p, start %u, count %u stub!\n", iface, start, count);
5134 return D3D_OK;
5137 static HRESULT WINAPI d3d_texture1_PaletteChanged(IDirect3DTexture *iface, DWORD start, DWORD count)
5139 struct ddraw_surface *surface = impl_from_IDirect3DTexture(iface);
5141 TRACE("iface %p, start %u, count %u.\n", iface, start, count);
5143 return d3d_texture2_PaletteChanged(&surface->IDirect3DTexture2_iface, start, count);
5146 /*****************************************************************************
5147 * IDirect3DTexture::Unload
5149 * DX5 SDK: "The IDirect3DTexture2::Unload method is not implemented
5152 * Returns:
5153 * DDERR_UNSUPPORTED
5155 *****************************************************************************/
5156 static HRESULT WINAPI d3d_texture1_Unload(IDirect3DTexture *iface)
5158 WARN("iface %p. Not implemented.\n", iface);
5160 return DDERR_UNSUPPORTED;
5163 /*****************************************************************************
5164 * IDirect3DTexture2::GetHandle
5166 * Returns handle for the texture.
5168 * Params:
5169 * device: Device this handle is assigned to
5170 * handle: Address to store the handle at.
5172 * Returns:
5173 * D3D_OK
5175 *****************************************************************************/
5176 static HRESULT WINAPI d3d_texture2_GetHandle(IDirect3DTexture2 *iface,
5177 IDirect3DDevice2 *device, D3DTEXTUREHANDLE *handle)
5179 struct ddraw_surface *surface = impl_from_IDirect3DTexture2(iface);
5180 struct d3d_device *device_impl = unsafe_impl_from_IDirect3DDevice2(device);
5182 TRACE("iface %p, device %p, handle %p.\n", iface, device, handle);
5184 wined3d_mutex_lock();
5186 if (!surface->Handle)
5188 DWORD h = ddraw_allocate_handle(&device_impl->handle_table, surface, DDRAW_HANDLE_SURFACE);
5189 if (h == DDRAW_INVALID_HANDLE)
5191 ERR("Failed to allocate a texture handle.\n");
5192 wined3d_mutex_unlock();
5193 return DDERR_OUTOFMEMORY;
5196 surface->Handle = h + 1;
5199 TRACE("Returning handle %08x.\n", surface->Handle);
5200 *handle = surface->Handle;
5202 wined3d_mutex_unlock();
5204 return D3D_OK;
5207 static HRESULT WINAPI d3d_texture1_GetHandle(IDirect3DTexture *iface,
5208 IDirect3DDevice *device, D3DTEXTUREHANDLE *handle)
5210 struct ddraw_surface *surface = impl_from_IDirect3DTexture(iface);
5211 struct d3d_device *device_impl = unsafe_impl_from_IDirect3DDevice(device);
5213 TRACE("iface %p, device %p, handle %p.\n", iface, device, handle);
5215 return d3d_texture2_GetHandle(&surface->IDirect3DTexture2_iface,
5216 device_impl ? &device_impl->IDirect3DDevice2_iface : NULL, handle);
5219 /*****************************************************************************
5220 * get_sub_mimaplevel
5222 * Helper function that returns the next mipmap level
5224 * tex_ptr: Surface of which to return the next level
5226 *****************************************************************************/
5227 static struct ddraw_surface *get_sub_mimaplevel(struct ddraw_surface *surface)
5229 /* Now go down the mipmap chain to the next surface */
5230 static DDSCAPS2 mipmap_caps = { DDSCAPS_MIPMAP | DDSCAPS_TEXTURE, 0, 0, {0} };
5231 IDirectDrawSurface7 *next_level;
5232 HRESULT hr;
5234 hr = ddraw_surface7_GetAttachedSurface(&surface->IDirectDrawSurface7_iface, &mipmap_caps, &next_level);
5235 if (FAILED(hr)) return NULL;
5237 ddraw_surface7_Release(next_level);
5239 return impl_from_IDirectDrawSurface7(next_level);
5242 /*****************************************************************************
5243 * IDirect3DTexture2::Load
5245 * Loads a texture created with the DDSCAPS_ALLOCONLOAD
5247 * This function isn't relayed to WineD3D because the whole interface is
5248 * implemented in DDraw only. For speed improvements an implementation which
5249 * takes OpenGL more into account could be placed into WineD3D.
5251 * Params:
5252 * src_texture: Address of the texture to load
5254 * Returns:
5255 * D3D_OK on success
5256 * D3DERR_TEXTURE_LOAD_FAILED.
5258 *****************************************************************************/
5259 static HRESULT WINAPI d3d_texture2_Load(IDirect3DTexture2 *iface, IDirect3DTexture2 *src_texture)
5261 struct ddraw_surface *dst_surface = impl_from_IDirect3DTexture2(iface);
5262 struct ddraw_surface *src_surface = unsafe_impl_from_IDirect3DTexture2(src_texture);
5263 struct wined3d_resource *dst_resource, *src_resource;
5264 HRESULT hr;
5266 TRACE("iface %p, src_texture %p.\n", iface, src_texture);
5268 if (src_surface == dst_surface)
5270 TRACE("copying surface %p to surface %p, why?\n", src_surface, dst_surface);
5271 return D3D_OK;
5274 wined3d_mutex_lock();
5276 dst_resource = wined3d_texture_get_resource(dst_surface->wined3d_texture);
5277 src_resource = wined3d_texture_get_resource(src_surface->wined3d_texture);
5279 if (((src_surface->surface_desc.ddsCaps.dwCaps & DDSCAPS_MIPMAP)
5280 != (dst_surface->surface_desc.ddsCaps.dwCaps & DDSCAPS_MIPMAP))
5281 || (src_surface->surface_desc.u2.dwMipMapCount != dst_surface->surface_desc.u2.dwMipMapCount))
5283 ERR("Trying to load surfaces with different mip-map counts.\n");
5286 for (;;)
5288 struct ddraw_palette *dst_pal, *src_pal;
5289 DDSURFACEDESC *src_desc, *dst_desc;
5291 TRACE("Copying surface %p to surface %p.\n", src_surface, dst_surface);
5293 /* Suppress the ALLOCONLOAD flag */
5294 dst_surface->surface_desc.ddsCaps.dwCaps &= ~DDSCAPS_ALLOCONLOAD;
5296 /* Get the palettes */
5297 dst_pal = dst_surface->palette;
5298 src_pal = src_surface->palette;
5300 if (src_pal)
5302 PALETTEENTRY palent[256];
5304 if (!dst_pal)
5306 wined3d_mutex_unlock();
5307 return DDERR_NOPALETTEATTACHED;
5309 IDirectDrawPalette_GetEntries(&src_pal->IDirectDrawPalette_iface, 0, 0, 256, palent);
5310 IDirectDrawPalette_SetEntries(&dst_pal->IDirectDrawPalette_iface, 0, 0, 256, palent);
5313 /* Copy one surface on the other */
5314 dst_desc = (DDSURFACEDESC *)&(dst_surface->surface_desc);
5315 src_desc = (DDSURFACEDESC *)&(src_surface->surface_desc);
5317 if ((src_desc->dwWidth != dst_desc->dwWidth) || (src_desc->dwHeight != dst_desc->dwHeight))
5319 /* Should also check for same pixel format, u1.lPitch, ... */
5320 ERR("Error in surface sizes.\n");
5321 wined3d_mutex_unlock();
5322 return D3DERR_TEXTURE_LOAD_FAILED;
5324 else
5326 struct wined3d_map_desc src_map_desc, dst_map_desc;
5328 /* Copy the src blit color key if the source has one, don't erase
5329 * the destination's ckey if the source has none */
5330 if (src_desc->dwFlags & DDSD_CKSRCBLT)
5332 IDirectDrawSurface7_SetColorKey(&dst_surface->IDirectDrawSurface7_iface,
5333 DDCKEY_SRCBLT, &src_desc->ddckCKSrcBlt);
5336 if (FAILED(hr = wined3d_resource_map(src_resource,
5337 src_surface->sub_resource_idx, &src_map_desc, NULL, WINED3D_MAP_READ)))
5339 ERR("Failed to lock source surface, hr %#x.\n", hr);
5340 wined3d_mutex_unlock();
5341 return D3DERR_TEXTURE_LOAD_FAILED;
5344 if (FAILED(hr = wined3d_resource_map(dst_resource,
5345 dst_surface->sub_resource_idx, &dst_map_desc, NULL, WINED3D_MAP_WRITE)))
5347 ERR("Failed to lock destination surface, hr %#x.\n", hr);
5348 wined3d_resource_unmap(src_resource, src_surface->sub_resource_idx);
5349 wined3d_mutex_unlock();
5350 return D3DERR_TEXTURE_LOAD_FAILED;
5353 if (dst_surface->surface_desc.u4.ddpfPixelFormat.dwFlags & DDPF_FOURCC)
5354 memcpy(dst_map_desc.data, src_map_desc.data, src_surface->surface_desc.u1.dwLinearSize);
5355 else
5356 memcpy(dst_map_desc.data, src_map_desc.data, src_map_desc.row_pitch * src_desc->dwHeight);
5358 wined3d_resource_unmap(dst_resource, dst_surface->sub_resource_idx);
5359 wined3d_resource_unmap(src_resource, src_surface->sub_resource_idx);
5362 if (src_surface->surface_desc.ddsCaps.dwCaps & DDSCAPS_MIPMAP)
5363 src_surface = get_sub_mimaplevel(src_surface);
5364 else
5365 src_surface = NULL;
5367 if (dst_surface->surface_desc.ddsCaps.dwCaps & DDSCAPS_MIPMAP)
5368 dst_surface = get_sub_mimaplevel(dst_surface);
5369 else
5370 dst_surface = NULL;
5372 if (!src_surface || !dst_surface)
5374 if (src_surface != dst_surface)
5375 ERR("Loading surface with different mipmap structure.\n");
5376 break;
5380 wined3d_mutex_unlock();
5382 return hr;
5385 static HRESULT WINAPI d3d_texture1_Load(IDirect3DTexture *iface, IDirect3DTexture *src_texture)
5387 struct ddraw_surface *dst_surface = impl_from_IDirect3DTexture(iface);
5388 struct ddraw_surface *src_surface = unsafe_impl_from_IDirect3DTexture(src_texture);
5390 TRACE("iface %p, src_texture %p.\n", iface, src_texture);
5392 return d3d_texture2_Load(&dst_surface->IDirect3DTexture2_iface,
5393 src_surface ? &src_surface->IDirect3DTexture2_iface : NULL);
5396 /*****************************************************************************
5397 * The VTable
5398 *****************************************************************************/
5400 static const struct IDirectDrawSurface7Vtbl ddraw_surface7_vtbl =
5402 /* IUnknown */
5403 ddraw_surface7_QueryInterface,
5404 ddraw_surface7_AddRef,
5405 ddraw_surface7_Release,
5406 /* IDirectDrawSurface */
5407 ddraw_surface7_AddAttachedSurface,
5408 ddraw_surface7_AddOverlayDirtyRect,
5409 ddraw_surface7_Blt,
5410 ddraw_surface7_BltBatch,
5411 ddraw_surface7_BltFast,
5412 ddraw_surface7_DeleteAttachedSurface,
5413 ddraw_surface7_EnumAttachedSurfaces,
5414 ddraw_surface7_EnumOverlayZOrders,
5415 ddraw_surface7_Flip,
5416 ddraw_surface7_GetAttachedSurface,
5417 ddraw_surface7_GetBltStatus,
5418 ddraw_surface7_GetCaps,
5419 ddraw_surface7_GetClipper,
5420 ddraw_surface7_GetColorKey,
5421 ddraw_surface7_GetDC,
5422 ddraw_surface7_GetFlipStatus,
5423 ddraw_surface7_GetOverlayPosition,
5424 ddraw_surface7_GetPalette,
5425 ddraw_surface7_GetPixelFormat,
5426 ddraw_surface7_GetSurfaceDesc,
5427 ddraw_surface7_Initialize,
5428 ddraw_surface7_IsLost,
5429 ddraw_surface7_Lock,
5430 ddraw_surface7_ReleaseDC,
5431 ddraw_surface7_Restore,
5432 ddraw_surface7_SetClipper,
5433 ddraw_surface7_SetColorKey,
5434 ddraw_surface7_SetOverlayPosition,
5435 ddraw_surface7_SetPalette,
5436 ddraw_surface7_Unlock,
5437 ddraw_surface7_UpdateOverlay,
5438 ddraw_surface7_UpdateOverlayDisplay,
5439 ddraw_surface7_UpdateOverlayZOrder,
5440 /* IDirectDrawSurface2 */
5441 ddraw_surface7_GetDDInterface,
5442 ddraw_surface7_PageLock,
5443 ddraw_surface7_PageUnlock,
5444 /* IDirectDrawSurface3 */
5445 ddraw_surface7_SetSurfaceDesc,
5446 /* IDirectDrawSurface4 */
5447 ddraw_surface7_SetPrivateData,
5448 ddraw_surface7_GetPrivateData,
5449 ddraw_surface7_FreePrivateData,
5450 ddraw_surface7_GetUniquenessValue,
5451 ddraw_surface7_ChangeUniquenessValue,
5452 /* IDirectDrawSurface7 */
5453 ddraw_surface7_SetPriority,
5454 ddraw_surface7_GetPriority,
5455 ddraw_surface7_SetLOD,
5456 ddraw_surface7_GetLOD,
5459 static const struct IDirectDrawSurface4Vtbl ddraw_surface4_vtbl =
5461 /* IUnknown */
5462 ddraw_surface4_QueryInterface,
5463 ddraw_surface4_AddRef,
5464 ddraw_surface4_Release,
5465 /* IDirectDrawSurface */
5466 ddraw_surface4_AddAttachedSurface,
5467 ddraw_surface4_AddOverlayDirtyRect,
5468 ddraw_surface4_Blt,
5469 ddraw_surface4_BltBatch,
5470 ddraw_surface4_BltFast,
5471 ddraw_surface4_DeleteAttachedSurface,
5472 ddraw_surface4_EnumAttachedSurfaces,
5473 ddraw_surface4_EnumOverlayZOrders,
5474 ddraw_surface4_Flip,
5475 ddraw_surface4_GetAttachedSurface,
5476 ddraw_surface4_GetBltStatus,
5477 ddraw_surface4_GetCaps,
5478 ddraw_surface4_GetClipper,
5479 ddraw_surface4_GetColorKey,
5480 ddraw_surface4_GetDC,
5481 ddraw_surface4_GetFlipStatus,
5482 ddraw_surface4_GetOverlayPosition,
5483 ddraw_surface4_GetPalette,
5484 ddraw_surface4_GetPixelFormat,
5485 ddraw_surface4_GetSurfaceDesc,
5486 ddraw_surface4_Initialize,
5487 ddraw_surface4_IsLost,
5488 ddraw_surface4_Lock,
5489 ddraw_surface4_ReleaseDC,
5490 ddraw_surface4_Restore,
5491 ddraw_surface4_SetClipper,
5492 ddraw_surface4_SetColorKey,
5493 ddraw_surface4_SetOverlayPosition,
5494 ddraw_surface4_SetPalette,
5495 ddraw_surface4_Unlock,
5496 ddraw_surface4_UpdateOverlay,
5497 ddraw_surface4_UpdateOverlayDisplay,
5498 ddraw_surface4_UpdateOverlayZOrder,
5499 /* IDirectDrawSurface2 */
5500 ddraw_surface4_GetDDInterface,
5501 ddraw_surface4_PageLock,
5502 ddraw_surface4_PageUnlock,
5503 /* IDirectDrawSurface3 */
5504 ddraw_surface4_SetSurfaceDesc,
5505 /* IDirectDrawSurface4 */
5506 ddraw_surface4_SetPrivateData,
5507 ddraw_surface4_GetPrivateData,
5508 ddraw_surface4_FreePrivateData,
5509 ddraw_surface4_GetUniquenessValue,
5510 ddraw_surface4_ChangeUniquenessValue,
5513 static const struct IDirectDrawSurface3Vtbl ddraw_surface3_vtbl =
5515 /* IUnknown */
5516 ddraw_surface3_QueryInterface,
5517 ddraw_surface3_AddRef,
5518 ddraw_surface3_Release,
5519 /* IDirectDrawSurface */
5520 ddraw_surface3_AddAttachedSurface,
5521 ddraw_surface3_AddOverlayDirtyRect,
5522 ddraw_surface3_Blt,
5523 ddraw_surface3_BltBatch,
5524 ddraw_surface3_BltFast,
5525 ddraw_surface3_DeleteAttachedSurface,
5526 ddraw_surface3_EnumAttachedSurfaces,
5527 ddraw_surface3_EnumOverlayZOrders,
5528 ddraw_surface3_Flip,
5529 ddraw_surface3_GetAttachedSurface,
5530 ddraw_surface3_GetBltStatus,
5531 ddraw_surface3_GetCaps,
5532 ddraw_surface3_GetClipper,
5533 ddraw_surface3_GetColorKey,
5534 ddraw_surface3_GetDC,
5535 ddraw_surface3_GetFlipStatus,
5536 ddraw_surface3_GetOverlayPosition,
5537 ddraw_surface3_GetPalette,
5538 ddraw_surface3_GetPixelFormat,
5539 ddraw_surface3_GetSurfaceDesc,
5540 ddraw_surface3_Initialize,
5541 ddraw_surface3_IsLost,
5542 ddraw_surface3_Lock,
5543 ddraw_surface3_ReleaseDC,
5544 ddraw_surface3_Restore,
5545 ddraw_surface3_SetClipper,
5546 ddraw_surface3_SetColorKey,
5547 ddraw_surface3_SetOverlayPosition,
5548 ddraw_surface3_SetPalette,
5549 ddraw_surface3_Unlock,
5550 ddraw_surface3_UpdateOverlay,
5551 ddraw_surface3_UpdateOverlayDisplay,
5552 ddraw_surface3_UpdateOverlayZOrder,
5553 /* IDirectDrawSurface2 */
5554 ddraw_surface3_GetDDInterface,
5555 ddraw_surface3_PageLock,
5556 ddraw_surface3_PageUnlock,
5557 /* IDirectDrawSurface3 */
5558 ddraw_surface3_SetSurfaceDesc,
5561 static const struct IDirectDrawSurface2Vtbl ddraw_surface2_vtbl =
5563 /* IUnknown */
5564 ddraw_surface2_QueryInterface,
5565 ddraw_surface2_AddRef,
5566 ddraw_surface2_Release,
5567 /* IDirectDrawSurface */
5568 ddraw_surface2_AddAttachedSurface,
5569 ddraw_surface2_AddOverlayDirtyRect,
5570 ddraw_surface2_Blt,
5571 ddraw_surface2_BltBatch,
5572 ddraw_surface2_BltFast,
5573 ddraw_surface2_DeleteAttachedSurface,
5574 ddraw_surface2_EnumAttachedSurfaces,
5575 ddraw_surface2_EnumOverlayZOrders,
5576 ddraw_surface2_Flip,
5577 ddraw_surface2_GetAttachedSurface,
5578 ddraw_surface2_GetBltStatus,
5579 ddraw_surface2_GetCaps,
5580 ddraw_surface2_GetClipper,
5581 ddraw_surface2_GetColorKey,
5582 ddraw_surface2_GetDC,
5583 ddraw_surface2_GetFlipStatus,
5584 ddraw_surface2_GetOverlayPosition,
5585 ddraw_surface2_GetPalette,
5586 ddraw_surface2_GetPixelFormat,
5587 ddraw_surface2_GetSurfaceDesc,
5588 ddraw_surface2_Initialize,
5589 ddraw_surface2_IsLost,
5590 ddraw_surface2_Lock,
5591 ddraw_surface2_ReleaseDC,
5592 ddraw_surface2_Restore,
5593 ddraw_surface2_SetClipper,
5594 ddraw_surface2_SetColorKey,
5595 ddraw_surface2_SetOverlayPosition,
5596 ddraw_surface2_SetPalette,
5597 ddraw_surface2_Unlock,
5598 ddraw_surface2_UpdateOverlay,
5599 ddraw_surface2_UpdateOverlayDisplay,
5600 ddraw_surface2_UpdateOverlayZOrder,
5601 /* IDirectDrawSurface2 */
5602 ddraw_surface2_GetDDInterface,
5603 ddraw_surface2_PageLock,
5604 ddraw_surface2_PageUnlock,
5607 static const struct IDirectDrawSurfaceVtbl ddraw_surface1_vtbl =
5609 /* IUnknown */
5610 ddraw_surface1_QueryInterface,
5611 ddraw_surface1_AddRef,
5612 ddraw_surface1_Release,
5613 /* IDirectDrawSurface */
5614 ddraw_surface1_AddAttachedSurface,
5615 ddraw_surface1_AddOverlayDirtyRect,
5616 ddraw_surface1_Blt,
5617 ddraw_surface1_BltBatch,
5618 ddraw_surface1_BltFast,
5619 ddraw_surface1_DeleteAttachedSurface,
5620 ddraw_surface1_EnumAttachedSurfaces,
5621 ddraw_surface1_EnumOverlayZOrders,
5622 ddraw_surface1_Flip,
5623 ddraw_surface1_GetAttachedSurface,
5624 ddraw_surface1_GetBltStatus,
5625 ddraw_surface1_GetCaps,
5626 ddraw_surface1_GetClipper,
5627 ddraw_surface1_GetColorKey,
5628 ddraw_surface1_GetDC,
5629 ddraw_surface1_GetFlipStatus,
5630 ddraw_surface1_GetOverlayPosition,
5631 ddraw_surface1_GetPalette,
5632 ddraw_surface1_GetPixelFormat,
5633 ddraw_surface1_GetSurfaceDesc,
5634 ddraw_surface1_Initialize,
5635 ddraw_surface1_IsLost,
5636 ddraw_surface1_Lock,
5637 ddraw_surface1_ReleaseDC,
5638 ddraw_surface1_Restore,
5639 ddraw_surface1_SetClipper,
5640 ddraw_surface1_SetColorKey,
5641 ddraw_surface1_SetOverlayPosition,
5642 ddraw_surface1_SetPalette,
5643 ddraw_surface1_Unlock,
5644 ddraw_surface1_UpdateOverlay,
5645 ddraw_surface1_UpdateOverlayDisplay,
5646 ddraw_surface1_UpdateOverlayZOrder,
5649 static const struct IDirectDrawGammaControlVtbl ddraw_gamma_control_vtbl =
5651 ddraw_gamma_control_QueryInterface,
5652 ddraw_gamma_control_AddRef,
5653 ddraw_gamma_control_Release,
5654 ddraw_gamma_control_GetGammaRamp,
5655 ddraw_gamma_control_SetGammaRamp,
5658 static const struct IDirect3DTexture2Vtbl d3d_texture2_vtbl =
5660 d3d_texture2_QueryInterface,
5661 d3d_texture2_AddRef,
5662 d3d_texture2_Release,
5663 d3d_texture2_GetHandle,
5664 d3d_texture2_PaletteChanged,
5665 d3d_texture2_Load,
5668 static const struct IDirect3DTextureVtbl d3d_texture1_vtbl =
5670 d3d_texture1_QueryInterface,
5671 d3d_texture1_AddRef,
5672 d3d_texture1_Release,
5673 d3d_texture1_Initialize,
5674 d3d_texture1_GetHandle,
5675 d3d_texture1_PaletteChanged,
5676 d3d_texture1_Load,
5677 d3d_texture1_Unload,
5680 /* Some games (e.g. Tomb Raider 3) pass the wrong version of the
5681 * IDirectDrawSurface interface to ddraw methods. */
5682 struct ddraw_surface *unsafe_impl_from_IDirectDrawSurface7(IDirectDrawSurface7 *iface)
5684 if (!iface) return NULL;
5685 if (iface->lpVtbl != &ddraw_surface7_vtbl)
5687 HRESULT hr = IDirectDrawSurface7_QueryInterface(iface, &IID_IDirectDrawSurface7, (void **)&iface);
5688 if (FAILED(hr))
5690 WARN("Object %p doesn't expose interface IDirectDrawSurface7.\n", iface);
5691 return NULL;
5693 IDirectDrawSurface7_Release(iface);
5695 return CONTAINING_RECORD(iface, struct ddraw_surface, IDirectDrawSurface7_iface);
5698 struct ddraw_surface *unsafe_impl_from_IDirectDrawSurface4(IDirectDrawSurface4 *iface)
5700 if (!iface) return NULL;
5701 if (iface->lpVtbl != &ddraw_surface4_vtbl)
5703 HRESULT hr = IDirectDrawSurface4_QueryInterface(iface, &IID_IDirectDrawSurface4, (void **)&iface);
5704 if (FAILED(hr))
5706 WARN("Object %p doesn't expose interface IDirectDrawSurface4.\n", iface);
5707 return NULL;
5709 IDirectDrawSurface4_Release(iface);
5711 return CONTAINING_RECORD(iface, struct ddraw_surface, IDirectDrawSurface4_iface);
5714 static struct ddraw_surface *unsafe_impl_from_IDirectDrawSurface3(IDirectDrawSurface3 *iface)
5716 if (!iface) return NULL;
5717 if (iface->lpVtbl != &ddraw_surface3_vtbl)
5719 HRESULT hr = IDirectDrawSurface3_QueryInterface(iface, &IID_IDirectDrawSurface3, (void **)&iface);
5720 if (FAILED(hr))
5722 WARN("Object %p doesn't expose interface IDirectDrawSurface3.\n", iface);
5723 return NULL;
5725 IDirectDrawSurface3_Release(iface);
5727 return CONTAINING_RECORD(iface, struct ddraw_surface, IDirectDrawSurface3_iface);
5730 static struct ddraw_surface *unsafe_impl_from_IDirectDrawSurface2(IDirectDrawSurface2 *iface)
5732 if (!iface) return NULL;
5733 if (iface->lpVtbl != &ddraw_surface2_vtbl)
5735 HRESULT hr = IDirectDrawSurface2_QueryInterface(iface, &IID_IDirectDrawSurface2, (void **)&iface);
5736 if (FAILED(hr))
5738 WARN("Object %p doesn't expose interface IDirectDrawSurface2.\n", iface);
5739 return NULL;
5741 IDirectDrawSurface2_Release(iface);
5743 return CONTAINING_RECORD(iface, struct ddraw_surface, IDirectDrawSurface2_iface);
5746 struct ddraw_surface *unsafe_impl_from_IDirectDrawSurface(IDirectDrawSurface *iface)
5748 if (!iface) return NULL;
5749 if (iface->lpVtbl != &ddraw_surface1_vtbl)
5751 HRESULT hr = IDirectDrawSurface_QueryInterface(iface, &IID_IDirectDrawSurface, (void **)&iface);
5752 if (FAILED(hr))
5754 WARN("Object %p doesn't expose interface IDirectDrawSurface.\n", iface);
5755 return NULL;
5757 IDirectDrawSurface_Release(iface);
5759 return CONTAINING_RECORD(iface, struct ddraw_surface, IDirectDrawSurface_iface);
5762 struct ddraw_surface *unsafe_impl_from_IDirect3DTexture2(IDirect3DTexture2 *iface)
5764 if (!iface) return NULL;
5765 assert(iface->lpVtbl == &d3d_texture2_vtbl);
5766 return CONTAINING_RECORD(iface, struct ddraw_surface, IDirect3DTexture2_iface);
5769 struct ddraw_surface *unsafe_impl_from_IDirect3DTexture(IDirect3DTexture *iface)
5771 if (!iface) return NULL;
5772 assert(iface->lpVtbl == &d3d_texture1_vtbl);
5773 return CONTAINING_RECORD(iface, struct ddraw_surface, IDirect3DTexture_iface);
5776 static void STDMETHODCALLTYPE ddraw_surface_wined3d_object_destroyed(void *parent)
5778 struct ddraw_surface *surface = parent;
5780 TRACE("surface %p.\n", surface);
5782 /* This shouldn't happen, ddraw_surface_release_iface() should prevent the
5783 * surface from being destroyed in this case. */
5784 if (surface->first_attached != surface)
5785 ERR("Surface is still attached to surface %p.\n", surface->first_attached);
5787 while (surface->next_attached)
5788 if (FAILED(ddraw_surface_delete_attached_surface(surface,
5789 surface->next_attached, surface->next_attached->attached_iface)))
5790 ERR("DeleteAttachedSurface failed.\n");
5792 /* Having a texture handle set implies that the device still exists. */
5793 if (surface->Handle)
5794 ddraw_free_handle(&surface->ddraw->d3ddevice->handle_table, surface->Handle - 1, DDRAW_HANDLE_SURFACE);
5796 /* Reduce the ddraw surface count. */
5797 list_remove(&surface->surface_list_entry);
5799 if (surface->clipper)
5800 IDirectDrawClipper_Release(&surface->clipper->IDirectDrawClipper_iface);
5802 if (surface == surface->ddraw->primary)
5803 surface->ddraw->primary = NULL;
5805 wined3d_private_store_cleanup(&surface->private_store);
5807 heap_free(surface);
5810 static const struct wined3d_parent_ops ddraw_surface_wined3d_parent_ops =
5812 ddraw_surface_wined3d_object_destroyed,
5815 static void STDMETHODCALLTYPE ddraw_texture_wined3d_object_destroyed(void *parent)
5817 TRACE("parent %p.\n", parent);
5819 heap_free(parent);
5822 static const struct wined3d_parent_ops ddraw_texture_wined3d_parent_ops =
5824 ddraw_texture_wined3d_object_destroyed,
5827 static HRESULT CDECL ddraw_reset_enum_callback(struct wined3d_resource *resource)
5829 return DD_OK;
5832 HRESULT ddraw_surface_create(struct ddraw *ddraw, const DDSURFACEDESC2 *surface_desc,
5833 struct ddraw_surface **surface, IUnknown *outer_unknown, unsigned int version)
5835 struct wined3d_sub_resource_desc wined3d_mip_desc;
5836 struct ddraw_surface *root, *mip, **attach;
5837 struct wined3d_resource_desc wined3d_desc;
5838 struct wined3d_texture *wined3d_texture;
5839 struct wined3d_display_mode mode;
5840 DDSURFACEDESC2 *desc, *mip_desc;
5841 struct ddraw_texture *texture;
5842 unsigned int layers = 1;
5843 unsigned int pitch = 0;
5844 UINT levels, i, j;
5845 HRESULT hr;
5847 TRACE("ddraw %p, surface_desc %p, surface %p, outer_unknown %p, version %u.\n",
5848 ddraw, surface_desc, surface, outer_unknown, version);
5849 if (TRACE_ON(ddraw))
5851 TRACE("Requesting surface desc:\n");
5852 DDRAW_dump_surface_desc(surface_desc);
5855 if (outer_unknown)
5856 return CLASS_E_NOAGGREGATION;
5858 if (!surface)
5859 return E_POINTER;
5861 if (!(texture = heap_alloc(sizeof(*texture))))
5862 return E_OUTOFMEMORY;
5864 texture->version = version;
5865 texture->surface_desc = *surface_desc;
5866 desc = &texture->surface_desc;
5868 /* Ensure DDSD_CAPS is always set. */
5869 desc->dwFlags |= DDSD_CAPS;
5871 if (desc->ddsCaps.dwCaps & DDSCAPS_FLIP)
5873 if (!(desc->dwFlags & DDSD_BACKBUFFERCOUNT) || !desc->u5.dwBackBufferCount)
5875 WARN("Tried to create a flippable surface without any back buffers.\n");
5876 heap_free(texture);
5877 return DDERR_INVALIDCAPS;
5880 if (!(desc->ddsCaps.dwCaps & DDSCAPS_COMPLEX))
5882 WARN("Tried to create a flippable surface without DDSCAPS_COMPLEX.\n");
5883 heap_free(texture);
5884 return DDERR_INVALIDCAPS;
5887 if (desc->ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP)
5889 WARN("Tried to create a flippable cubemap.\n");
5890 heap_free(texture);
5891 return DDERR_INVALIDPARAMS;
5894 if (desc->ddsCaps.dwCaps & DDSCAPS_TEXTURE)
5896 FIXME("Flippable textures not implemented.\n");
5897 heap_free(texture);
5898 return DDERR_INVALIDCAPS;
5901 else
5903 if (desc->dwFlags & DDSD_BACKBUFFERCOUNT)
5905 WARN("Tried to specify a back buffer count for a non-flippable surface.\n");
5906 hr = desc->ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP ? DDERR_INVALIDPARAMS : DDERR_INVALIDCAPS;
5907 heap_free(texture);
5908 return hr;
5912 if (desc->ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE)
5914 if (desc->ddsCaps.dwCaps & DDSCAPS_TEXTURE)
5916 WARN("Tried to create a primary surface with DDSCAPS_TEXTURE.\n");
5917 heap_free(texture);
5918 return DDERR_INVALIDCAPS;
5921 if ((desc->ddsCaps.dwCaps & DDSCAPS_COMPLEX) && !(desc->ddsCaps.dwCaps & DDSCAPS_FLIP))
5923 WARN("Tried to create a flippable primary surface without both DDSCAPS_FLIP and DDSCAPS_COMPLEX.\n");
5924 heap_free(texture);
5925 return DDERR_INVALIDCAPS;
5928 if ((desc->ddsCaps.dwCaps & DDSCAPS_FLIP) && !(ddraw->cooperative_level & DDSCL_EXCLUSIVE))
5930 WARN("Tried to create a flippable primary surface without DDSCL_EXCLUSIVE.\n");
5931 heap_free(texture);
5932 return DDERR_NOEXCLUSIVEMODE;
5936 /* This is a special case in ddrawex, but not allowed in ddraw. */
5937 if ((desc->ddsCaps.dwCaps & (DDSCAPS_VIDEOMEMORY | DDSCAPS_SYSTEMMEMORY))
5938 == (DDSCAPS_VIDEOMEMORY | DDSCAPS_SYSTEMMEMORY))
5940 WARN("Tried to create a surface in both system and video memory.\n");
5941 heap_free(texture);
5942 return DDERR_INVALIDCAPS;
5945 if ((desc->ddsCaps.dwCaps & (DDSCAPS_ALLOCONLOAD | DDSCAPS_MIPMAP))
5946 && !(desc->ddsCaps.dwCaps & DDSCAPS_TEXTURE))
5948 WARN("Caps %#x require DDSCAPS_TEXTURE.\n", desc->ddsCaps.dwCaps);
5949 heap_free(texture);
5950 return DDERR_INVALIDCAPS;
5953 if ((desc->ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP_ALLFACES)
5954 && !(desc->ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP))
5956 WARN("Cube map faces requested without cube map flag.\n");
5957 heap_free(texture);
5958 return DDERR_INVALIDCAPS;
5961 if ((desc->ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP)
5962 && !(desc->ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP_ALLFACES))
5964 WARN("Cube map without faces requested.\n");
5965 heap_free(texture);
5966 return DDERR_INVALIDPARAMS;
5969 if ((desc->ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP)
5970 && (desc->ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP_ALLFACES) != DDSCAPS2_CUBEMAP_ALLFACES)
5971 FIXME("Partial cube maps not implemented.\n");
5973 if (desc->ddsCaps.dwCaps2 & (DDSCAPS2_TEXTUREMANAGE | DDSCAPS2_D3DTEXTUREMANAGE))
5975 if (!(desc->ddsCaps.dwCaps & DDSCAPS_TEXTURE))
5977 WARN("DDSCAPS2_TEXTUREMANAGE used without DDSCAPS_TEXTURE, returning DDERR_INVALIDCAPS.\n");
5978 heap_free(texture);
5979 return DDERR_INVALIDCAPS;
5981 if (desc->ddsCaps.dwCaps & (DDSCAPS_VIDEOMEMORY | DDSCAPS_SYSTEMMEMORY))
5983 WARN("DDSCAPS2_TEXTUREMANAGE used width DDSCAPS_VIDEOMEMORY "
5984 "or DDSCAPS_SYSTEMMEMORY, returning DDERR_INVALIDCAPS.\n");
5985 heap_free(texture);
5986 return DDERR_INVALIDCAPS;
5990 if (FAILED(hr = wined3d_get_adapter_display_mode(ddraw->wined3d, WINED3DADAPTER_DEFAULT, &mode, NULL)))
5992 ERR("Failed to get display mode, hr %#x.\n", hr);
5993 heap_free(texture);
5994 return hr_ddraw_from_wined3d(hr);
5997 /* No pixelformat given? Use the current screen format. */
5998 if (!(desc->dwFlags & DDSD_PIXELFORMAT))
6000 desc->dwFlags |= DDSD_PIXELFORMAT;
6001 desc->u4.ddpfPixelFormat.dwSize = sizeof(desc->u4.ddpfPixelFormat);
6002 ddrawformat_from_wined3dformat(&desc->u4.ddpfPixelFormat, mode.format_id);
6005 wined3d_desc.resource_type = WINED3D_RTYPE_TEXTURE_2D;
6006 wined3d_desc.format = wined3dformat_from_ddrawformat(&desc->u4.ddpfPixelFormat);
6007 if (wined3d_desc.format == WINED3DFMT_UNKNOWN)
6009 WARN("Unsupported / unknown pixelformat.\n");
6010 heap_free(texture);
6011 return DDERR_INVALIDPIXELFORMAT;
6014 /* No width or no height? Use the screen size. */
6015 if (!(desc->dwFlags & DDSD_WIDTH) || !(desc->dwFlags & DDSD_HEIGHT))
6017 if (!(desc->ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE))
6019 WARN("No width / height specified.\n");
6020 heap_free(texture);
6021 return DDERR_INVALIDPARAMS;
6024 desc->dwFlags |= DDSD_WIDTH | DDSD_HEIGHT;
6025 desc->dwWidth = mode.width;
6026 desc->dwHeight = mode.height;
6029 if (!desc->dwWidth || !desc->dwHeight)
6031 heap_free(texture);
6032 return DDERR_INVALIDPARAMS;
6035 if (desc->ddsCaps.dwCaps & DDSCAPS_FLIP)
6036 desc->ddsCaps.dwCaps |= DDSCAPS_FRONTBUFFER;
6038 if (desc->ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE)
6040 /* The first surface is a front buffer, the back buffers are created
6041 * afterwards. */
6042 desc->ddsCaps.dwCaps |= DDSCAPS_VISIBLE;
6043 if (ddraw->cooperative_level & DDSCL_EXCLUSIVE)
6045 struct wined3d_swapchain_desc swapchain_desc;
6047 wined3d_swapchain_get_desc(ddraw->wined3d_swapchain, &swapchain_desc);
6048 swapchain_desc.backbuffer_width = mode.width;
6049 swapchain_desc.backbuffer_height = mode.height;
6050 swapchain_desc.backbuffer_format = mode.format_id;
6052 if (FAILED(hr = wined3d_device_reset(ddraw->wined3d_device,
6053 &swapchain_desc, NULL, ddraw_reset_enum_callback, TRUE)))
6055 ERR("Failed to reset device.\n");
6056 heap_free(texture);
6057 return hr_ddraw_from_wined3d(hr);
6060 wined3d_device_set_render_state(ddraw->wined3d_device, WINED3D_RS_ZENABLE,
6061 !!swapchain_desc.enable_auto_depth_stencil);
6065 wined3d_desc.multisample_type = WINED3D_MULTISAMPLE_NONE;
6066 wined3d_desc.multisample_quality = 0;
6067 wined3d_desc.usage = 0;
6068 wined3d_desc.bind_flags = 0;
6069 wined3d_desc.access = WINED3D_RESOURCE_ACCESS_GPU | WINED3D_RESOURCE_ACCESS_MAP_R | WINED3D_RESOURCE_ACCESS_MAP_W;
6070 wined3d_desc.width = desc->dwWidth;
6071 wined3d_desc.height = desc->dwHeight;
6072 wined3d_desc.depth = 1;
6073 wined3d_desc.size = 0;
6075 if ((desc->ddsCaps.dwCaps & DDSCAPS_3DDEVICE) && (ddraw->flags & DDRAW_NO3D))
6077 WARN("The application requests a 3D capable surface, but the ddraw object was created without 3D support.\n");
6078 /* Do not fail surface creation, only fail 3D device creation. */
6081 /* Mipmap count fixes */
6082 if (desc->ddsCaps.dwCaps & DDSCAPS_MIPMAP)
6084 if (desc->ddsCaps.dwCaps & DDSCAPS_COMPLEX)
6086 if (desc->dwFlags & DDSD_MIPMAPCOUNT)
6088 /* Mipmap count is given, should not be 0. */
6089 if (!desc->u2.dwMipMapCount)
6091 heap_free(texture);
6092 return DDERR_INVALIDPARAMS;
6095 else
6097 /* Undocumented feature: Create sublevels until either the
6098 * width or the height is 1. */
6099 if (version == 7)
6100 desc->u2.dwMipMapCount = wined3d_log2i(max(desc->dwWidth, desc->dwHeight)) + 1;
6101 else
6102 desc->u2.dwMipMapCount = wined3d_log2i(min(desc->dwWidth, desc->dwHeight)) + 1;
6105 else
6107 desc->u2.dwMipMapCount = 1;
6110 desc->dwFlags |= DDSD_MIPMAPCOUNT;
6111 levels = desc->u2.dwMipMapCount;
6113 else
6115 levels = 1;
6118 if (!(desc->ddsCaps.dwCaps & (DDSCAPS_VIDEOMEMORY | DDSCAPS_SYSTEMMEMORY)))
6120 if (!(desc->ddsCaps.dwCaps2 & (DDSCAPS2_TEXTUREMANAGE | DDSCAPS2_D3DTEXTUREMANAGE)))
6122 unsigned int bind_flags = 0;
6123 DWORD usage = 0;
6125 if (desc->ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP)
6127 usage |= WINED3DUSAGE_LEGACY_CUBEMAP;
6128 bind_flags |= WINED3D_BIND_SHADER_RESOURCE;
6130 else if (desc->ddsCaps.dwCaps & DDSCAPS_TEXTURE)
6132 bind_flags |= WINED3D_BIND_SHADER_RESOURCE;
6135 if (desc->ddsCaps.dwCaps & DDSCAPS_ZBUFFER)
6136 bind_flags |= WINED3D_BIND_DEPTH_STENCIL;
6137 else if (desc->ddsCaps.dwCaps & DDSCAPS_3DDEVICE)
6138 bind_flags |= WINED3D_BIND_RENDER_TARGET;
6140 if (!(ddraw->flags & DDRAW_NO3D) && SUCCEEDED(hr = wined3d_check_device_format(ddraw->wined3d,
6141 WINED3DADAPTER_DEFAULT, WINED3D_DEVICE_TYPE_HAL, mode.format_id,
6142 usage, bind_flags, WINED3D_RTYPE_TEXTURE_2D, wined3d_desc.format)))
6143 desc->ddsCaps.dwCaps |= DDSCAPS_VIDEOMEMORY;
6144 else
6145 desc->ddsCaps.dwCaps |= DDSCAPS_SYSTEMMEMORY;
6147 else if (!(desc->ddsCaps.dwCaps & DDSCAPS_TEXTURE))
6149 /* Tests show surfaces without memory flags get these flags added
6150 * right after creation. */
6151 desc->ddsCaps.dwCaps |= DDSCAPS_LOCALVIDMEM | DDSCAPS_VIDEOMEMORY;
6155 if ((desc->ddsCaps.dwCaps & (DDSCAPS_OVERLAY | DDSCAPS_SYSTEMMEMORY))
6156 == (DDSCAPS_OVERLAY | DDSCAPS_SYSTEMMEMORY))
6158 WARN("System memory overlays are not allowed.\n");
6159 heap_free(texture);
6160 return DDERR_NOOVERLAYHW;
6163 if (desc->ddsCaps.dwCaps & DDSCAPS_SYSTEMMEMORY)
6165 wined3d_desc.access = WINED3D_RESOURCE_ACCESS_CPU
6166 | WINED3D_RESOURCE_ACCESS_MAP_R | WINED3D_RESOURCE_ACCESS_MAP_W;
6168 else
6170 if (!(ddraw->flags & DDRAW_NO3D))
6172 if (desc->ddsCaps.dwCaps & DDSCAPS_TEXTURE)
6173 wined3d_desc.bind_flags |= WINED3D_BIND_SHADER_RESOURCE;
6174 if (desc->ddsCaps.dwCaps & DDSCAPS_ZBUFFER)
6175 wined3d_desc.bind_flags |= WINED3D_BIND_DEPTH_STENCIL;
6176 else if (desc->ddsCaps.dwCaps & DDSCAPS_3DDEVICE)
6177 wined3d_desc.bind_flags |= WINED3D_BIND_RENDER_TARGET;
6180 if (desc->ddsCaps.dwCaps2 & (DDSCAPS2_TEXTUREMANAGE | DDSCAPS2_D3DTEXTUREMANAGE))
6182 wined3d_desc.access = WINED3D_RESOURCE_ACCESS_GPU | WINED3D_RESOURCE_ACCESS_CPU
6183 | WINED3D_RESOURCE_ACCESS_MAP_R | WINED3D_RESOURCE_ACCESS_MAP_W;
6184 /* Managed textures have the system memory flag set. */
6185 desc->ddsCaps.dwCaps |= DDSCAPS_SYSTEMMEMORY;
6187 else if (desc->ddsCaps.dwCaps & DDSCAPS_VIDEOMEMORY)
6189 /* Videomemory adds localvidmem. This is mutually exclusive with
6190 * systemmemory and texturemanage. */
6191 desc->ddsCaps.dwCaps |= DDSCAPS_LOCALVIDMEM;
6192 /* Dynamic resources can't be written by the GPU. */
6193 if (!(wined3d_desc.bind_flags & (WINED3D_BIND_RENDER_TARGET | WINED3D_BIND_DEPTH_STENCIL)))
6194 wined3d_desc.usage |= WINED3DUSAGE_DYNAMIC;
6198 if (desc->dwFlags & DDSD_LPSURFACE)
6200 if (wined3d_desc.access & WINED3D_RESOURCE_ACCESS_GPU)
6202 WARN("User memory surfaces should not be GPU accessible.\n");
6203 heap_free(texture);
6204 return DDERR_INVALIDCAPS;
6207 if (version < 4)
6209 WARN("User memory surfaces not supported before version 4.\n");
6210 heap_free(texture);
6211 return DDERR_INVALIDPARAMS;
6214 if (!desc->lpSurface)
6216 WARN("NULL surface memory pointer specified.\n");
6217 heap_free(texture);
6218 return DDERR_INVALIDPARAMS;
6221 if (format_is_compressed(&desc->u4.ddpfPixelFormat))
6223 if (version != 4 && (desc->dwFlags & DDSD_PITCH))
6225 WARN("Pitch specified on a compressed user memory surface.\n");
6226 heap_free(texture);
6227 return DDERR_INVALIDPARAMS;
6230 if (!(desc->dwFlags & (DDSD_LINEARSIZE | DDSD_PITCH)))
6232 WARN("Compressed user memory surfaces should explicitly specify the linear size.\n");
6233 heap_free(texture);
6234 return DDERR_INVALIDPARAMS;
6237 if ((desc->dwFlags & DDSD_LINEARSIZE)
6238 && desc->u1.dwLinearSize < wined3d_calculate_format_pitch(ddraw->wined3d, WINED3DADAPTER_DEFAULT,
6239 wined3d_desc.format, wined3d_desc.width) * ((desc->dwHeight + 3) / 4))
6241 WARN("Invalid linear size %u specified.\n", desc->u1.dwLinearSize);
6242 heap_free(texture);
6243 return DDERR_INVALIDPARAMS;
6246 else
6248 if (!(desc->dwFlags & DDSD_PITCH))
6250 WARN("User memory surfaces should explicitly specify the pitch.\n");
6251 heap_free(texture);
6252 return DDERR_INVALIDPARAMS;
6255 if (desc->u1.lPitch < wined3d_calculate_format_pitch(ddraw->wined3d, WINED3DADAPTER_DEFAULT,
6256 wined3d_desc.format, wined3d_desc.width) || desc->u1.lPitch & 3)
6258 WARN("Invalid pitch %u specified.\n", desc->u1.lPitch);
6259 heap_free(texture);
6260 return DDERR_INVALIDPARAMS;
6263 pitch = desc->u1.lPitch;
6267 if (((desc->dwFlags & DDSD_CKDESTOVERLAY)
6268 && desc->u3.ddckCKDestOverlay.dwColorSpaceLowValue != desc->u3.ddckCKDestOverlay.dwColorSpaceHighValue)
6269 || ((desc->dwFlags & DDSD_CKDESTBLT)
6270 && desc->ddckCKDestBlt.dwColorSpaceLowValue != desc->ddckCKDestBlt.dwColorSpaceHighValue)
6271 || ((desc->dwFlags & DDSD_CKSRCOVERLAY)
6272 && desc->ddckCKSrcOverlay.dwColorSpaceLowValue != desc->ddckCKSrcOverlay.dwColorSpaceHighValue)
6273 || ((desc->dwFlags & DDSD_CKSRCBLT)
6274 && desc->ddckCKSrcBlt.dwColorSpaceLowValue != desc->ddckCKSrcBlt.dwColorSpaceHighValue))
6276 WARN("Range color keys not supported, returning DDERR_NOCOLORKEYHW.\n");
6277 heap_free(texture);
6278 return DDERR_NOCOLORKEYHW;
6281 if ((ddraw->flags & DDRAW_NO3D) && (desc->ddsCaps.dwCaps & DDSCAPS_VIDEOMEMORY))
6283 WARN("Video memory surfaces not supported without 3D support.\n");
6284 heap_free(texture);
6285 return DDERR_NODIRECTDRAWHW;
6288 if (desc->ddsCaps.dwCaps & (DDSCAPS_OVERLAY))
6289 wined3d_desc.usage |= WINED3DUSAGE_OVERLAY;
6291 if (desc->ddsCaps.dwCaps & DDSCAPS_OWNDC)
6292 wined3d_desc.usage |= WINED3DUSAGE_OWNDC;
6294 if (desc->ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP)
6296 wined3d_desc.usage |= WINED3DUSAGE_LEGACY_CUBEMAP;
6297 layers = 6;
6300 /* Some applications assume surfaces will always be mapped at the same
6301 * address. Some of those also assume that this address is valid even when
6302 * the surface isn't mapped, and that updates done this way will be
6303 * visible on the screen. The game Nox is such an application,
6304 * Commandos: Behind Enemy Lines is another. Setting
6305 * WINED3D_TEXTURE_CREATE_GET_DC_LENIENT will ensure this. */
6306 if (FAILED(hr = wined3d_texture_create(ddraw->wined3d_device, &wined3d_desc, layers, levels,
6307 WINED3D_TEXTURE_CREATE_GET_DC_LENIENT, NULL, texture,
6308 &ddraw_texture_wined3d_parent_ops, &wined3d_texture)))
6310 WARN("Failed to create wined3d texture, hr %#x.\n", hr);
6311 heap_free(texture);
6312 return hr_ddraw_from_wined3d(hr);
6315 root = wined3d_texture_get_sub_resource_parent(wined3d_texture, 0);
6316 wined3d_texture_decref(wined3d_texture);
6317 root->is_complex_root = TRUE;
6318 texture->root = root;
6319 wined3d_device_incref(texture->wined3d_device = ddraw->wined3d_device);
6321 if (desc->dwFlags & DDSD_CKDESTOVERLAY)
6322 wined3d_texture_set_color_key(wined3d_texture, DDCKEY_DESTOVERLAY,
6323 (struct wined3d_color_key *)&desc->u3.ddckCKDestOverlay);
6324 if (desc->dwFlags & DDSD_CKDESTBLT)
6325 wined3d_texture_set_color_key(wined3d_texture, DDCKEY_DESTBLT,
6326 (struct wined3d_color_key *)&desc->ddckCKDestBlt);
6327 if (desc->dwFlags & DDSD_CKSRCOVERLAY)
6328 wined3d_texture_set_color_key(wined3d_texture, DDCKEY_SRCOVERLAY,
6329 (struct wined3d_color_key *)&desc->ddckCKSrcOverlay);
6330 if (desc->dwFlags & DDSD_CKSRCBLT)
6331 wined3d_texture_set_color_key(wined3d_texture, DDCKEY_SRCBLT,
6332 (struct wined3d_color_key *)&desc->ddckCKSrcBlt);
6334 for (i = 0; i < layers; ++i)
6336 attach = &root->complex_array[layers - 1 - i];
6338 for (j = 0; j < levels; ++j)
6340 mip = wined3d_texture_get_sub_resource_parent(wined3d_texture, i * levels + j);
6341 mip_desc = &mip->surface_desc;
6343 if (j)
6345 wined3d_texture_get_sub_resource_desc(wined3d_texture, i * levels + j, &wined3d_mip_desc);
6346 mip_desc->dwWidth = wined3d_mip_desc.width;
6347 mip_desc->dwHeight = wined3d_mip_desc.height;
6349 mip_desc->ddsCaps.dwCaps2 |= DDSCAPS2_MIPMAPSUBLEVEL;
6351 else
6353 mip_desc->ddsCaps.dwCaps2 &= ~DDSCAPS2_MIPMAPSUBLEVEL;
6356 if (mip_desc->ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP)
6358 mip_desc->ddsCaps.dwCaps2 &= ~DDSCAPS2_CUBEMAP_ALLFACES;
6360 switch (i)
6362 case WINED3D_CUBEMAP_FACE_POSITIVE_X:
6363 mip_desc->ddsCaps.dwCaps2 |= DDSCAPS2_CUBEMAP_POSITIVEX;
6364 break;
6365 case WINED3D_CUBEMAP_FACE_NEGATIVE_X:
6366 mip_desc->ddsCaps.dwCaps2 |= DDSCAPS2_CUBEMAP_NEGATIVEX;
6367 break;
6368 case WINED3D_CUBEMAP_FACE_POSITIVE_Y:
6369 mip_desc->ddsCaps.dwCaps2 |= DDSCAPS2_CUBEMAP_POSITIVEY;
6370 break;
6371 case WINED3D_CUBEMAP_FACE_NEGATIVE_Y:
6372 mip_desc->ddsCaps.dwCaps2 |= DDSCAPS2_CUBEMAP_NEGATIVEY;
6373 break;
6374 case WINED3D_CUBEMAP_FACE_POSITIVE_Z:
6375 mip_desc->ddsCaps.dwCaps2 |= DDSCAPS2_CUBEMAP_POSITIVEZ;
6376 break;
6377 case WINED3D_CUBEMAP_FACE_NEGATIVE_Z:
6378 mip_desc->ddsCaps.dwCaps2 |= DDSCAPS2_CUBEMAP_NEGATIVEZ;
6379 break;
6384 if (mip == root)
6385 continue;
6387 *attach = mip;
6388 attach = &mip->complex_array[0];
6392 if ((desc->dwFlags & DDSD_LPSURFACE) && FAILED(hr = wined3d_texture_update_desc(wined3d_texture,
6393 wined3d_desc.width, wined3d_desc.height, wined3d_desc.format,
6394 WINED3D_MULTISAMPLE_NONE, 0, desc->lpSurface, pitch)))
6396 ERR("Failed to set surface memory, hr %#x.\n", hr);
6397 goto fail;
6400 if (desc->dwFlags & DDSD_BACKBUFFERCOUNT)
6402 unsigned int count = desc->u5.dwBackBufferCount;
6403 struct ddraw_surface *last = root;
6405 attach = &last->complex_array[0];
6406 for (i = 0; i < count; ++i)
6408 if (!(texture = heap_alloc(sizeof(*texture))))
6410 hr = E_OUTOFMEMORY;
6411 goto fail;
6414 texture->version = version;
6415 texture->surface_desc = root->surface_desc;
6416 desc = &texture->surface_desc;
6418 /* Only one surface in the flipping chain is a back buffer, one is
6419 * a front buffer, the others are just flippable surfaces. */
6420 desc->ddsCaps.dwCaps &= ~(DDSCAPS_VISIBLE | DDSCAPS_PRIMARYSURFACE | DDSCAPS_FRONTBUFFER
6421 | DDSCAPS_BACKBUFFER);
6422 if (!i)
6423 desc->ddsCaps.dwCaps |= DDSCAPS_BACKBUFFER;
6424 desc->u5.dwBackBufferCount = 0;
6426 if (FAILED(hr = wined3d_texture_create(ddraw->wined3d_device, &wined3d_desc, 1, 1,
6427 WINED3D_TEXTURE_CREATE_GET_DC_LENIENT, NULL, texture,
6428 &ddraw_texture_wined3d_parent_ops, &wined3d_texture)))
6430 heap_free(texture);
6431 hr = hr_ddraw_from_wined3d(hr);
6432 goto fail;
6435 last = wined3d_texture_get_sub_resource_parent(wined3d_texture, 0);
6436 wined3d_texture_decref(wined3d_texture);
6437 texture->root = last;
6438 wined3d_device_incref(texture->wined3d_device = ddraw->wined3d_device);
6440 if (desc->dwFlags & DDSD_CKDESTOVERLAY)
6441 wined3d_texture_set_color_key(wined3d_texture, DDCKEY_DESTOVERLAY,
6442 (struct wined3d_color_key *)&desc->u3.ddckCKDestOverlay);
6443 if (desc->dwFlags & DDSD_CKDESTBLT)
6444 wined3d_texture_set_color_key(wined3d_texture, DDCKEY_DESTBLT,
6445 (struct wined3d_color_key *)&desc->ddckCKDestBlt);
6446 if (desc->dwFlags & DDSD_CKSRCOVERLAY)
6447 wined3d_texture_set_color_key(wined3d_texture, DDCKEY_SRCOVERLAY,
6448 (struct wined3d_color_key *)&desc->ddckCKSrcOverlay);
6449 if (desc->dwFlags & DDSD_CKSRCBLT)
6450 wined3d_texture_set_color_key(wined3d_texture, DDCKEY_SRCBLT,
6451 (struct wined3d_color_key *)&desc->ddckCKSrcBlt);
6453 *attach = last;
6454 attach = &last->complex_array[0];
6456 *attach = root;
6459 if (surface_desc->ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE)
6460 ddraw->primary = root;
6461 *surface = root;
6463 return DD_OK;
6465 fail:
6466 if (version == 7)
6467 IDirectDrawSurface7_Release(&root->IDirectDrawSurface7_iface);
6468 else if (version == 4)
6469 IDirectDrawSurface4_Release(&root->IDirectDrawSurface4_iface);
6470 else
6471 IDirectDrawSurface_Release(&root->IDirectDrawSurface_iface);
6473 return hr;
6476 void ddraw_surface_init(struct ddraw_surface *surface, struct ddraw *ddraw,
6477 struct wined3d_texture *wined3d_texture, unsigned int sub_resource_idx,
6478 const struct wined3d_parent_ops **parent_ops)
6480 struct ddraw_texture *texture = wined3d_texture_get_parent(wined3d_texture);
6481 unsigned int texture_level, row_pitch, slice_pitch;
6482 DDSURFACEDESC2 *desc = &surface->surface_desc;
6483 unsigned int version = texture->version;
6485 surface->IDirectDrawSurface7_iface.lpVtbl = &ddraw_surface7_vtbl;
6486 surface->IDirectDrawSurface4_iface.lpVtbl = &ddraw_surface4_vtbl;
6487 surface->IDirectDrawSurface3_iface.lpVtbl = &ddraw_surface3_vtbl;
6488 surface->IDirectDrawSurface2_iface.lpVtbl = &ddraw_surface2_vtbl;
6489 surface->IDirectDrawSurface_iface.lpVtbl = &ddraw_surface1_vtbl;
6490 surface->IDirectDrawGammaControl_iface.lpVtbl = &ddraw_gamma_control_vtbl;
6491 surface->IDirect3DTexture2_iface.lpVtbl = &d3d_texture2_vtbl;
6492 surface->IDirect3DTexture_iface.lpVtbl = &d3d_texture1_vtbl;
6493 surface->iface_count = 1;
6494 surface->version = version;
6495 surface->ddraw = ddraw;
6497 if (version == 7)
6499 surface->ref7 = 1;
6500 surface->texture_outer = (IUnknown *)&surface->IDirectDrawSurface7_iface;
6502 else if (version == 4)
6504 surface->ref4 = 1;
6505 surface->texture_outer = (IUnknown *)&surface->IDirectDrawSurface4_iface;
6507 else
6509 surface->ref1 = 1;
6510 surface->texture_outer = (IUnknown *)&surface->IDirectDrawSurface_iface;
6513 *desc = texture->surface_desc;
6514 surface->first_attached = surface;
6516 texture_level = desc->ddsCaps.dwCaps & DDSCAPS_MIPMAP ? sub_resource_idx % desc->u2.dwMipMapCount : 0;
6517 wined3d_texture_get_pitch(wined3d_texture, texture_level, &row_pitch, &slice_pitch);
6518 if (format_is_compressed(&desc->u4.ddpfPixelFormat))
6520 if (desc->dwFlags & DDSD_LPSURFACE)
6521 desc->u1.dwLinearSize = ~0u;
6522 else
6523 desc->u1.dwLinearSize = slice_pitch;
6524 desc->dwFlags |= DDSD_LINEARSIZE;
6525 desc->dwFlags &= ~(DDSD_LPSURFACE | DDSD_PITCH);
6527 else
6529 if (!(desc->dwFlags & DDSD_LPSURFACE))
6530 desc->u1.lPitch = row_pitch;
6531 desc->dwFlags |= DDSD_PITCH;
6532 desc->dwFlags &= ~(DDSD_LPSURFACE | DDSD_LINEARSIZE);
6534 desc->lpSurface = NULL;
6536 wined3d_texture_incref(surface->wined3d_texture = wined3d_texture);
6537 surface->sub_resource_idx = sub_resource_idx;
6538 *parent_ops = &ddraw_surface_wined3d_parent_ops;
6540 wined3d_private_store_init(&surface->private_store);
6543 static void STDMETHODCALLTYPE view_wined3d_object_destroyed(void *parent)
6545 struct ddraw_surface *surface = parent;
6547 /* If the surface reference count drops to zero, we release our reference
6548 * to the view, but don't clear the pointer yet, in case e.g. a
6549 * GetRenderTarget() call brings the surface back before the view is
6550 * actually destroyed. When the view is destroyed, we need to clear the
6551 * pointer, or a subsequent surface AddRef() would reference it again.
6553 * This is safe because as long as the view still has a reference to the
6554 * texture, the surface is also still alive, and we're called before the
6555 * view releases that reference. */
6556 surface->wined3d_rtv = NULL;
6559 static const struct wined3d_parent_ops ddraw_view_wined3d_parent_ops =
6561 view_wined3d_object_destroyed,
6564 struct wined3d_rendertarget_view *ddraw_surface_get_rendertarget_view(struct ddraw_surface *surface)
6566 HRESULT hr;
6568 if (surface->wined3d_rtv)
6569 return surface->wined3d_rtv;
6571 if (FAILED(hr = wined3d_rendertarget_view_create_from_sub_resource(surface->wined3d_texture,
6572 surface->sub_resource_idx, surface, &ddraw_view_wined3d_parent_ops, &surface->wined3d_rtv)))
6574 ERR("Failed to create rendertarget view, hr %#x.\n", hr);
6575 return NULL;
6578 return surface->wined3d_rtv;