dmsynth: Remove DECLSPEC_HIDDEN usage.
[wine.git] / dlls / ddraw / surface.c
blob437f97f7491ae458db575badb5aaa4caf0f4c11e
1 /* DirectDraw Surface Implementation
3 * Copyright (c) 1997-2000 Marcus Meissner
4 * Copyright (c) 1998-2000 Lionel Ulmer
5 * Copyright (c) 2000-2001 TransGaming Technologies Inc.
6 * Copyright (c) 2006 Stefan Dösinger
7 * Copyright (c) 2011 Ričardas Barkauskas for CodeWeavers
9 * This library is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Lesser General Public
11 * License as published by the Free Software Foundation; either
12 * version 2.1 of the License, or (at your option) any later version.
14 * This library is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * Lesser General Public License for more details.
19 * You should have received a copy of the GNU Lesser General Public
20 * License along with this library; if not, write to the Free Software
21 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
24 #include "ddraw_private.h"
26 WINE_DEFAULT_DEBUG_CHANNEL(ddraw);
27 WINE_DECLARE_DEBUG_CHANNEL(fps);
29 static struct ddraw_surface *unsafe_impl_from_IDirectDrawSurface2(IDirectDrawSurface2 *iface);
30 static struct ddraw_surface *unsafe_impl_from_IDirectDrawSurface3(IDirectDrawSurface3 *iface);
32 static const struct wined3d_parent_ops ddraw_surface_wined3d_parent_ops;
33 static const struct wined3d_parent_ops ddraw_texture_wined3d_parent_ops;
34 static const struct wined3d_parent_ops ddraw_view_wined3d_parent_ops;
36 static inline struct ddraw_surface *impl_from_IDirectDrawGammaControl(IDirectDrawGammaControl *iface)
38 return CONTAINING_RECORD(iface, struct ddraw_surface, IDirectDrawGammaControl_iface);
41 static BOOL ddraw_surface_is_lost(const struct ddraw_surface *surface)
43 return ddraw_surface_can_be_lost(surface)
44 && (surface->ddraw->device_state != DDRAW_DEVICE_STATE_OK || surface->is_lost);
47 static BOOL ddraw_gdi_is_front(struct ddraw *ddraw)
49 struct ddraw_surface *surface;
51 if (!ddraw->gdi_surface || !(surface = wined3d_texture_get_sub_resource_parent(ddraw->gdi_surface, 0)))
52 return FALSE;
54 return surface->surface_desc.ddsCaps.dwCaps & DDSCAPS_FRONTBUFFER;
57 /* This is slow, of course. Also, in case of locks, we can't prevent other
58 * applications from drawing to the screen while we've locked the frontbuffer.
59 * We'd like to do this in wined3d instead, but for that to work wined3d needs
60 * to support windowless rendering first. */
61 HRESULT ddraw_surface_update_frontbuffer(struct ddraw_surface *surface,
62 const RECT *rect, BOOL read, unsigned int swap_interval)
64 struct wined3d_texture *dst_texture, *wined3d_texture;
65 struct ddraw *ddraw = surface->ddraw;
66 HDC surface_dc, screen_dc;
67 int x, y, w, h;
68 HRESULT hr;
69 BOOL ret;
70 RECT r;
72 TRACE("surface %p, rect %s, read %#x, swap_interval %u.\n",
73 surface, wine_dbgstr_rect(rect), read, swap_interval);
75 if (ddraw->flags & DDRAW_SWAPPED && !read)
77 ddraw->flags &= ~DDRAW_SWAPPED;
78 rect = NULL;
81 if (!rect)
83 SetRect(&r, 0, 0, surface->surface_desc.dwWidth, surface->surface_desc.dwHeight);
84 rect = &r;
87 x = rect->left;
88 y = rect->top;
89 w = rect->right - rect->left;
90 h = rect->bottom - rect->top;
92 if (w <= 0 || h <= 0)
93 return DD_OK;
95 if (!read && TRACE_ON(fps))
97 DWORD time = GetTickCount();
98 ++ddraw->frames;
100 /* every 1.5 seconds */
101 if (time - ddraw->prev_frame_time > 1500)
103 TRACE_(fps)("%p @ approx %.2ffps\n",
104 ddraw, 1000.0 * ddraw->frames / (time - ddraw->prev_frame_time));
105 ddraw->prev_frame_time = time;
106 ddraw->frames = 0;
110 /* The interaction between ddraw and GDI drawing is not all that well
111 * documented, and somewhat arcane. In ddraw exclusive mode, GDI draws
112 * seemingly go to the *original* frontbuffer/primary surface, while ddraw
113 * draws/flips go to the *current* frontbuffer surface. The bottom line is
114 * that if the current frontbuffer is not the GDI frontbuffer, and there's
115 * e.g. a popup window in front of the ddraw swapchain window, we can't
116 * use wined3d_swapchain_present() to get the ddraw contents to the screen
117 * while in exclusive mode, since it would get obscured by the popup
118 * window. On the other hand, if the current frontbuffer *is* the GDI
119 * frontbuffer, that's what's supposed to happen; the popup should obscure
120 * (part of) the ddraw swapchain window.
122 * This affects the "Deer Hunter" demo, which uses a popup window and GDI
123 * draws to draw part of the user interface. See also the "fswindow"
124 * sample is the DirectX 7 SDK. */
125 if (ddraw->swapchain_window && (!(ddraw->cooperative_level & DDSCL_EXCLUSIVE)
126 || ddraw->swapchain_window == GetForegroundWindow() || ddraw_gdi_is_front(ddraw)))
128 /* Nothing to do, we control the frontbuffer, or at least the parts we
129 * care about. */
130 if (read)
131 return DD_OK;
133 if (swap_interval)
134 dst_texture = wined3d_swapchain_get_back_buffer(ddraw->wined3d_swapchain, 0);
135 else
136 dst_texture = wined3d_swapchain_get_front_buffer(ddraw->wined3d_swapchain);
138 if (SUCCEEDED(hr = wined3d_device_context_blt(ddraw->immediate_context, dst_texture, 0, rect,
139 ddraw_surface_get_any_texture(surface, DDRAW_SURFACE_READ), surface->sub_resource_idx, rect, 0,
140 NULL, WINED3D_TEXF_POINT)) && swap_interval)
142 hr = wined3d_swapchain_present(ddraw->wined3d_swapchain, rect, rect, NULL, swap_interval, 0);
143 ddraw->flags |= DDRAW_SWAPPED;
145 return hr;
148 wined3d_texture = ddraw_surface_get_default_texture(surface, read ? (rect ? DDRAW_SURFACE_RW : DDRAW_SURFACE_WRITE)
149 : DDRAW_SURFACE_READ);
151 if (FAILED(hr = wined3d_texture_get_dc(wined3d_texture, surface->sub_resource_idx, &surface_dc)))
153 ERR("Failed to get surface DC, hr %#lx.\n", hr);
154 return hr;
156 if (surface->palette)
157 wined3d_palette_apply_to_dc(surface->palette->wined3d_palette, surface_dc);
159 if (!(screen_dc = GetDC(NULL)))
161 wined3d_texture_release_dc(wined3d_texture, surface->sub_resource_idx, surface_dc);
162 ERR("Failed to get screen DC.\n");
163 return E_FAIL;
166 if (read)
167 ret = BitBlt(surface_dc, x, y, w, h,
168 screen_dc, x, y, SRCCOPY);
169 else
170 ret = BitBlt(screen_dc, x, y, w, h,
171 surface_dc, x, y, SRCCOPY);
173 ReleaseDC(NULL, screen_dc);
174 wined3d_texture_release_dc(wined3d_texture, surface->sub_resource_idx, surface_dc);
176 if (!ret)
178 ERR("Failed to blit to/from screen.\n");
179 return E_FAIL;
182 return DD_OK;
185 /*****************************************************************************
186 * IUnknown parts follow
187 *****************************************************************************/
189 /*****************************************************************************
190 * IDirectDrawSurface7::QueryInterface
192 * A normal QueryInterface implementation. For QueryInterface rules
193 * see ddraw.c, IDirectDraw7::QueryInterface. This method
194 * can Query IDirectDrawSurface interfaces in all version, IDirect3DTexture
195 * in all versions, the IDirectDrawGammaControl interface and it can
196 * create an IDirect3DDevice. (Uses IDirect3D7::CreateDevice)
198 * Params:
199 * riid: The interface id queried for
200 * obj: Address to write the pointer to
202 * Returns:
203 * S_OK on success
204 * E_NOINTERFACE if the requested interface wasn't found
206 *****************************************************************************/
207 static HRESULT WINAPI ddraw_surface7_QueryInterface(IDirectDrawSurface7 *iface, REFIID riid, void **obj)
209 struct ddraw_surface *This = impl_from_IDirectDrawSurface7(iface);
211 TRACE("iface %p, riid %s, object %p.\n", iface, debugstr_guid(riid), obj);
213 /* According to COM docs, if the QueryInterface fails, obj should be set to NULL */
214 *obj = NULL;
216 if(!riid)
217 return DDERR_INVALIDPARAMS;
219 if (IsEqualGUID(riid, &IID_IDirectDrawSurface7))
221 IDirectDrawSurface7_AddRef(iface);
222 *obj = iface;
223 TRACE("(%p) returning IDirectDrawSurface7 interface at %p\n", This, *obj);
224 return S_OK;
227 if (IsEqualGUID(riid, &IID_IDirectDrawSurface4))
229 IDirectDrawSurface4_AddRef(&This->IDirectDrawSurface4_iface);
230 *obj = &This->IDirectDrawSurface4_iface;
231 TRACE("(%p) returning IDirectDrawSurface4 interface at %p\n", This, *obj);
232 return S_OK;
235 if (IsEqualGUID(riid, &IID_IDirectDrawSurface3))
237 IDirectDrawSurface3_AddRef(&This->IDirectDrawSurface3_iface);
238 *obj = &This->IDirectDrawSurface3_iface;
239 TRACE("(%p) returning IDirectDrawSurface3 interface at %p\n", This, *obj);
240 return S_OK;
243 if (IsEqualGUID(riid, &IID_IDirectDrawSurface2))
245 IDirectDrawSurface2_AddRef(&This->IDirectDrawSurface2_iface);
246 *obj = &This->IDirectDrawSurface2_iface;
247 TRACE("(%p) returning IDirectDrawSurface2 interface at %p\n", This, *obj);
248 return S_OK;
251 if (IsEqualGUID(riid, &IID_IDirectDrawSurface)
252 || IsEqualGUID(riid, &IID_IUnknown))
254 IDirectDrawSurface_AddRef(&This->IDirectDrawSurface_iface);
255 *obj = &This->IDirectDrawSurface_iface;
256 TRACE("(%p) returning IDirectDrawSurface interface at %p\n", This, *obj);
257 return S_OK;
260 if (IsEqualGUID(riid, &IID_IDirectDrawGammaControl))
262 IDirectDrawGammaControl_AddRef(&This->IDirectDrawGammaControl_iface);
263 *obj = &This->IDirectDrawGammaControl_iface;
264 TRACE("(%p) returning IDirectDrawGammaControl interface at %p\n", This, *obj);
265 return S_OK;
268 if (IsEqualGUID(riid, &IID_IDirectDrawColorControl))
270 WARN("Color control not implemented.\n");
271 *obj = NULL;
272 return E_NOINTERFACE;
275 if (This->version != 7)
277 if (IsEqualGUID(riid, &IID_D3DDEVICE_WineD3D)
278 || IsEqualGUID(riid, &IID_IDirect3DHALDevice)
279 || IsEqualGUID(riid, &IID_IDirect3DRGBDevice))
281 wined3d_mutex_lock();
282 if (!This->device1)
284 HRESULT hr;
286 if (FAILED(hr = d3d_device_create(This->ddraw, riid, This, (IUnknown *)&This->IDirectDrawSurface_iface,
287 1, &This->device1, (IUnknown *)&This->IDirectDrawSurface_iface)))
289 This->device1 = NULL;
290 wined3d_mutex_unlock();
291 WARN("Failed to create device, hr %#lx.\n", hr);
292 return hr;
295 wined3d_mutex_unlock();
297 IDirect3DDevice_AddRef(&This->device1->IDirect3DDevice_iface);
298 *obj = &This->device1->IDirect3DDevice_iface;
299 return S_OK;
302 if (IsEqualGUID(&IID_IDirect3DTexture2, riid))
304 IDirect3DTexture2_AddRef(&This->IDirect3DTexture2_iface);
305 *obj = &This->IDirect3DTexture2_iface;
306 return S_OK;
309 if (IsEqualGUID( &IID_IDirect3DTexture, riid ))
311 IDirect3DTexture2_AddRef(&This->IDirect3DTexture_iface);
312 *obj = &This->IDirect3DTexture_iface;
313 return S_OK;
317 WARN("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(riid));
319 if (This->version != 7)
320 return E_INVALIDARG;
322 return E_NOINTERFACE;
325 static HRESULT WINAPI ddraw_surface4_QueryInterface(IDirectDrawSurface4 *iface, REFIID riid, void **object)
327 struct ddraw_surface *surface = impl_from_IDirectDrawSurface4(iface);
329 TRACE("iface %p, riid %s, object %p.\n", iface, debugstr_guid(riid), object);
331 return ddraw_surface7_QueryInterface(&surface->IDirectDrawSurface7_iface, riid, object);
334 static HRESULT WINAPI ddraw_surface3_QueryInterface(IDirectDrawSurface3 *iface, REFIID riid, void **object)
336 struct ddraw_surface *surface = impl_from_IDirectDrawSurface3(iface);
338 TRACE("iface %p, riid %s, object %p.\n", iface, debugstr_guid(riid), object);
340 return ddraw_surface7_QueryInterface(&surface->IDirectDrawSurface7_iface, riid, object);
343 static HRESULT WINAPI ddraw_surface2_QueryInterface(IDirectDrawSurface2 *iface, REFIID riid, void **object)
345 struct ddraw_surface *surface = impl_from_IDirectDrawSurface2(iface);
347 TRACE("iface %p, riid %s, object %p.\n", iface, debugstr_guid(riid), object);
349 return ddraw_surface7_QueryInterface(&surface->IDirectDrawSurface7_iface, riid, object);
352 static HRESULT WINAPI ddraw_surface1_QueryInterface(IDirectDrawSurface *iface, REFIID riid, void **object)
354 struct ddraw_surface *surface = impl_from_IDirectDrawSurface(iface);
356 TRACE("iface %p, riid %s, object %p.\n", iface, debugstr_guid(riid), object);
358 return ddraw_surface7_QueryInterface(&surface->IDirectDrawSurface7_iface, riid, object);
361 static HRESULT WINAPI ddraw_gamma_control_QueryInterface(IDirectDrawGammaControl *iface,
362 REFIID riid, void **object)
364 struct ddraw_surface *surface = impl_from_IDirectDrawGammaControl(iface);
366 TRACE("iface %p, riid %s, object %p.\n", iface, debugstr_guid(riid), object);
368 return ddraw_surface7_QueryInterface(&surface->IDirectDrawSurface7_iface, riid, object);
371 static HRESULT WINAPI d3d_texture2_QueryInterface(IDirect3DTexture2 *iface, REFIID riid, void **object)
373 struct ddraw_surface *surface = impl_from_IDirect3DTexture2(iface);
375 TRACE("iface %p, riid %s, object %p.\n", iface, debugstr_guid(riid), object);
377 return ddraw_surface7_QueryInterface(&surface->IDirectDrawSurface7_iface, riid, object);
380 static HRESULT WINAPI d3d_texture1_QueryInterface(IDirect3DTexture *iface, REFIID riid, void **object)
382 struct ddraw_surface *surface = impl_from_IDirect3DTexture(iface);
384 TRACE("iface %p, riid %s, object %p.\n", iface, debugstr_guid(riid), object);
386 return ddraw_surface7_QueryInterface(&surface->IDirectDrawSurface7_iface, riid, object);
389 static void ddraw_surface_add_iface(struct ddraw_surface *surface)
391 ULONG iface_count = InterlockedIncrement(&surface->iface_count);
392 TRACE("%p increasing iface count to %lu.\n", surface, iface_count);
394 if (iface_count == 1)
396 if (surface->ifaceToRelease)
397 IUnknown_AddRef(surface->ifaceToRelease);
398 wined3d_mutex_lock();
399 if (surface->wined3d_rtv)
400 wined3d_rendertarget_view_incref(surface->wined3d_rtv);
401 wined3d_texture_incref(surface->draw_texture ? surface->draw_texture : surface->wined3d_texture);
402 wined3d_mutex_unlock();
406 /*****************************************************************************
407 * IDirectDrawSurface7::AddRef
409 * A normal addref implementation
411 * Returns:
412 * The new refcount
414 *****************************************************************************/
415 static ULONG WINAPI ddraw_surface7_AddRef(IDirectDrawSurface7 *iface)
417 struct ddraw_surface *This = impl_from_IDirectDrawSurface7(iface);
418 ULONG refcount = InterlockedIncrement(&This->ref7);
420 TRACE("iface %p increasing refcount to %lu.\n", iface, refcount);
422 if (refcount == 1)
424 ddraw_surface_add_iface(This);
427 return refcount;
430 static ULONG WINAPI ddraw_surface4_AddRef(IDirectDrawSurface4 *iface)
432 struct ddraw_surface *This = impl_from_IDirectDrawSurface4(iface);
433 ULONG refcount = InterlockedIncrement(&This->ref4);
435 TRACE("iface %p increasing refcount to %lu.\n", iface, refcount);
437 if (refcount == 1)
439 ddraw_surface_add_iface(This);
442 return refcount;
445 static ULONG WINAPI ddraw_surface3_AddRef(IDirectDrawSurface3 *iface)
447 struct ddraw_surface *This = impl_from_IDirectDrawSurface3(iface);
448 ULONG refcount = InterlockedIncrement(&This->ref3);
450 TRACE("iface %p increasing refcount to %lu.\n", iface, refcount);
452 if (refcount == 1)
454 ddraw_surface_add_iface(This);
457 return refcount;
460 static ULONG WINAPI ddraw_surface2_AddRef(IDirectDrawSurface2 *iface)
462 struct ddraw_surface *This = impl_from_IDirectDrawSurface2(iface);
463 ULONG refcount = InterlockedIncrement(&This->ref2);
465 TRACE("iface %p increasing refcount to %lu.\n", iface, refcount);
467 if (refcount == 1)
469 ddraw_surface_add_iface(This);
472 return refcount;
475 static ULONG WINAPI ddraw_surface1_AddRef(IDirectDrawSurface *iface)
477 struct ddraw_surface *This = impl_from_IDirectDrawSurface(iface);
478 ULONG refcount = InterlockedIncrement(&This->ref1);
480 TRACE("iface %p increasing refcount to %lu.\n", iface, refcount);
482 if (refcount == 1)
484 ddraw_surface_add_iface(This);
487 return refcount;
490 static ULONG WINAPI ddraw_gamma_control_AddRef(IDirectDrawGammaControl *iface)
492 struct ddraw_surface *This = impl_from_IDirectDrawGammaControl(iface);
493 ULONG refcount = InterlockedIncrement(&This->gamma_count);
495 TRACE("iface %p increasing refcount to %lu.\n", iface, refcount);
497 if (refcount == 1)
499 ddraw_surface_add_iface(This);
502 return refcount;
505 static ULONG WINAPI d3d_texture2_AddRef(IDirect3DTexture2 *iface)
507 struct ddraw_surface *surface = impl_from_IDirect3DTexture2(iface);
509 TRACE("iface %p.\n", iface);
511 return IUnknown_AddRef(surface->texture_outer);
514 static ULONG WINAPI d3d_texture1_AddRef(IDirect3DTexture *iface)
516 struct ddraw_surface *surface = impl_from_IDirect3DTexture(iface);
518 TRACE("iface %p.\n", iface);
520 return IUnknown_AddRef(surface->texture_outer);
523 static HRESULT ddraw_surface_set_palette(struct ddraw_surface *surface, IDirectDrawPalette *palette)
525 struct ddraw_palette *palette_impl = unsafe_impl_from_IDirectDrawPalette(palette);
526 struct ddraw_palette *prev;
528 TRACE("iface %p, palette %p.\n", surface, palette);
530 if (palette_impl && palette_impl->flags & DDPCAPS_ALPHA
531 && !(surface->surface_desc.ddsCaps.dwCaps & DDSCAPS_TEXTURE))
533 WARN("Alpha palette set on non-texture surface, returning DDERR_INVALIDSURFACETYPE.\n");
534 return DDERR_INVALIDSURFACETYPE;
537 if (!format_is_paletteindexed(&surface->surface_desc.u4.ddpfPixelFormat))
538 return DDERR_INVALIDPIXELFORMAT;
540 wined3d_mutex_lock();
542 prev = surface->palette;
543 if (surface->surface_desc.ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE)
545 if (prev)
546 prev->flags &= ~DDPCAPS_PRIMARYSURFACE;
547 if (palette_impl)
548 palette_impl->flags |= DDPCAPS_PRIMARYSURFACE;
549 wined3d_swapchain_set_palette(surface->ddraw->wined3d_swapchain,
550 palette_impl ? palette_impl->wined3d_palette : NULL);
551 ddraw_surface_update_frontbuffer(surface, NULL, FALSE, 0);
553 if (palette_impl)
554 IDirectDrawPalette_AddRef(&palette_impl->IDirectDrawPalette_iface);
555 if (prev)
556 IDirectDrawPalette_Release(&prev->IDirectDrawPalette_iface);
557 surface->palette = palette_impl;
559 wined3d_mutex_unlock();
561 return DD_OK;
564 static void ddraw_surface_cleanup(struct ddraw_surface *surface)
566 struct ddraw_surface *surf;
567 UINT i;
569 TRACE("surface %p.\n", surface);
571 /* The refcount test shows that the palette is detached when the surface
572 * is destroyed. */
573 ddraw_surface_set_palette(surface, NULL);
575 /* Loop through all complex attached surfaces and destroy them.
577 * Yet again, only the root can have more than one complexly attached
578 * surface, all the others have a total of one. */
579 for (i = 0; i < MAX_COMPLEX_ATTACHED; ++i)
581 if (!surface->complex_array[i])
582 break;
584 surf = surface->complex_array[i];
585 surface->complex_array[i] = NULL;
586 if (!surf->is_root)
588 struct ddraw_texture *texture = wined3d_texture_get_parent(surf->wined3d_texture);
589 struct wined3d_device *wined3d_device = texture->wined3d_device;
590 struct ddraw_surface *root = texture->root;
592 ddraw_surface_cleanup(surf);
594 if (surf == root)
595 wined3d_device_decref(wined3d_device);
599 if (surface->device1)
600 IUnknown_Release(&surface->device1->IUnknown_inner);
602 if (surface->iface_count > 1)
604 /* This can happen when a complex surface is destroyed, because the
605 * 2nd surface was addref()ed when the app called
606 * GetAttachedSurface(). */
607 WARN("Destroying surface %p with refcounts 7: %lu 4: %lu 3: %lu 2: %lu 1: %lu.\n",
608 surface, surface->ref7, surface->ref4, surface->ref3, surface->ref2, surface->ref1);
611 if (surface->wined3d_rtv)
612 wined3d_rendertarget_view_decref(surface->wined3d_rtv);
613 wined3d_texture_decref(surface->draw_texture ? surface->draw_texture : surface->wined3d_texture);
616 static ULONG ddraw_surface_release_iface(struct ddraw_surface *This)
618 ULONG iface_count;
620 /* Prevent the surface from being destroyed if it's still attached to
621 * another surface. It will be destroyed when the root is destroyed. */
622 if (This->iface_count == 1 && This->attached_iface)
623 IUnknown_AddRef(This->attached_iface);
624 iface_count = InterlockedDecrement(&This->iface_count);
626 TRACE("%p decreasing iface count to %lu.\n", This, iface_count);
628 if (iface_count == 0)
630 struct ddraw_texture *texture = wined3d_texture_get_parent(This->wined3d_texture);
631 struct wined3d_device *wined3d_device = texture->wined3d_device;
632 IUnknown *release_iface = This->ifaceToRelease;
634 /* Complex attached surfaces are destroyed implicitly when the root is released */
635 wined3d_mutex_lock();
636 if (!This->is_root)
638 WARN("(%p) Attempt to destroy a surface that is not a complex root\n", This);
639 wined3d_mutex_unlock();
640 return iface_count;
642 ddraw_surface_cleanup(This);
643 wined3d_mutex_unlock();
645 if (release_iface)
646 IUnknown_Release(release_iface);
647 /* Release the device only after anything that may reference it (the
648 * wined3d texture and rendertarget view in particular) is released. */
649 wined3d_device_decref(wined3d_device);
652 return iface_count;
655 /*****************************************************************************
656 * IDirectDrawSurface7::Release
658 * Reduces the surface's refcount by 1. If the refcount falls to 0, the
659 * surface is destroyed.
661 * Destroying the surface is a bit tricky. For the connection between
662 * WineD3DSurfaces and DirectDrawSurfaces see IDirectDraw7::CreateSurface
663 * It has a nice graph explaining the connection.
665 * What happens here is basically this:
666 * When a surface is destroyed, its WineD3DSurface is released,
667 * and the refcount of the DirectDraw interface is reduced by 1. If it has
668 * complex surfaces attached to it, then these surfaces are destroyed too,
669 * regardless of their refcount. If any surface being destroyed has another
670 * surface attached to it (with a "soft" attachment, not complex), then
671 * this surface is detached with DeleteAttachedSurface.
673 * When the surface is a texture, the WineD3DTexture is released.
674 * If the surface is the Direct3D render target, then the D3D
675 * capabilities of the WineD3DDevice are uninitialized, which causes the
676 * swapchain to be released.
678 * When a complex sublevel falls to ref zero, then this is ignored.
680 * Returns:
681 * The new refcount
683 *****************************************************************************/
684 static ULONG WINAPI ddraw_surface7_Release(IDirectDrawSurface7 *iface)
686 struct ddraw_surface *This = impl_from_IDirectDrawSurface7(iface);
687 ULONG refcount = InterlockedDecrement(&This->ref7);
689 TRACE("iface %p decreasing refcount to %lu.\n", iface, refcount);
691 if (refcount == 0)
693 ddraw_surface_release_iface(This);
696 return refcount;
699 static ULONG WINAPI ddraw_surface4_Release(IDirectDrawSurface4 *iface)
701 struct ddraw_surface *This = impl_from_IDirectDrawSurface4(iface);
702 ULONG refcount = InterlockedDecrement(&This->ref4);
704 TRACE("iface %p decreasing refcount to %lu.\n", iface, refcount);
706 if (refcount == 0)
708 ddraw_surface_release_iface(This);
711 return refcount;
714 static ULONG WINAPI ddraw_surface3_Release(IDirectDrawSurface3 *iface)
716 struct ddraw_surface *This = impl_from_IDirectDrawSurface3(iface);
717 ULONG refcount = InterlockedDecrement(&This->ref3);
719 TRACE("iface %p decreasing refcount to %lu.\n", iface, refcount);
721 if (refcount == 0)
723 ddraw_surface_release_iface(This);
726 return refcount;
729 static ULONG WINAPI ddraw_surface2_Release(IDirectDrawSurface2 *iface)
731 struct ddraw_surface *This = impl_from_IDirectDrawSurface2(iface);
732 ULONG refcount = InterlockedDecrement(&This->ref2);
734 TRACE("iface %p decreasing refcount to %lu.\n", iface, refcount);
736 if (refcount == 0)
738 ddraw_surface_release_iface(This);
741 return refcount;
744 static ULONG WINAPI ddraw_surface1_Release(IDirectDrawSurface *iface)
746 struct ddraw_surface *This = impl_from_IDirectDrawSurface(iface);
747 ULONG refcount = InterlockedDecrement(&This->ref1);
749 TRACE("iface %p decreasing refcount to %lu.\n", iface, refcount);
751 if (refcount == 0)
753 ddraw_surface_release_iface(This);
756 return refcount;
759 static ULONG WINAPI ddraw_gamma_control_Release(IDirectDrawGammaControl *iface)
761 struct ddraw_surface *This = impl_from_IDirectDrawGammaControl(iface);
762 ULONG refcount = InterlockedDecrement(&This->gamma_count);
764 TRACE("iface %p decreasing refcount to %lu.\n", iface, refcount);
766 if (refcount == 0)
768 ddraw_surface_release_iface(This);
771 return refcount;
774 static ULONG WINAPI d3d_texture2_Release(IDirect3DTexture2 *iface)
776 struct ddraw_surface *surface = impl_from_IDirect3DTexture2(iface);
778 TRACE("iface %p.\n", iface);
780 return IUnknown_Release(surface->texture_outer);
783 static ULONG WINAPI d3d_texture1_Release(IDirect3DTexture *iface)
785 struct ddraw_surface *surface = impl_from_IDirect3DTexture(iface);
787 TRACE("iface %p.\n", iface);
789 return IUnknown_Release(surface->texture_outer);
792 /*****************************************************************************
793 * IDirectDrawSurface7::GetAttachedSurface
795 * Returns an attached surface with the requested caps. Surface attachment
796 * and complex surfaces are not clearly described by the MSDN or sdk,
797 * so this method is tricky and likely to contain problems.
798 * This implementation searches the complex list first, then the
799 * attachment chain.
801 * The chains are searched from This down to the last surface in the chain,
802 * not from the first element in the chain. The first surface found is
803 * returned. The MSDN says that this method fails if more than one surface
804 * matches the caps, but it is not sure if that is right. The attachment
805 * structure may not even allow two matching surfaces.
807 * The found surface is AddRef-ed before it is returned.
809 * Params:
810 * Caps: Pointer to a DDCAPS2 structure describing the caps asked for
811 * Surface: Address to store the found surface
813 * Returns:
814 * DD_OK on success
815 * DDERR_INVALIDPARAMS if Caps or Surface is NULL
816 * DDERR_NOTFOUND if no surface was found
818 *****************************************************************************/
819 static HRESULT WINAPI ddraw_surface7_GetAttachedSurface(IDirectDrawSurface7 *iface,
820 DDSCAPS2 *caps, IDirectDrawSurface7 **surface)
822 struct ddraw_surface *head_surface = impl_from_IDirectDrawSurface7(iface);
823 struct ddraw_surface *surf;
824 DDSCAPS2 our_caps;
825 int i;
827 TRACE("iface %p, caps %p, attachment %p.\n", iface, caps, surface);
829 if (ddraw_surface_is_lost(head_surface))
831 WARN("Surface %p is lost.\n", head_surface);
833 *surface = NULL;
834 return DDERR_SURFACELOST;
837 wined3d_mutex_lock();
839 if(head_surface->version < 7)
841 /* Earlier dx apps put garbage into these members, clear them */
842 our_caps.dwCaps = caps->dwCaps;
843 our_caps.dwCaps2 = 0;
844 our_caps.dwCaps3 = 0;
845 our_caps.u1.dwCaps4 = 0;
847 else
849 our_caps = *caps;
852 TRACE("head_surface %p, looking for caps %#lx, %#lx, %#lx, %#lx.\n", head_surface, our_caps.dwCaps,
853 our_caps.dwCaps2, our_caps.dwCaps3, our_caps.u1.dwCaps4); /* FIXME: Better debugging */
855 for(i = 0; i < MAX_COMPLEX_ATTACHED; i++)
857 surf = head_surface->complex_array[i];
858 if(!surf) break;
860 TRACE("Surface %p, caps %#lx, %#lx, %#lx, %#lx.\n", surf,
861 surf->surface_desc.ddsCaps.dwCaps,
862 surf->surface_desc.ddsCaps.dwCaps2,
863 surf->surface_desc.ddsCaps.dwCaps3,
864 surf->surface_desc.ddsCaps.u1.dwCaps4);
866 if (((surf->surface_desc.ddsCaps.dwCaps & our_caps.dwCaps) == our_caps.dwCaps) &&
867 ((surf->surface_desc.ddsCaps.dwCaps2 & our_caps.dwCaps2) == our_caps.dwCaps2)) {
869 /* MSDN: "This method fails if more than one surface is attached
870 * that matches the capabilities requested."
872 * Not sure how to test this.
875 TRACE("head_surface %p, returning surface %p.\n", head_surface, surf);
876 *surface = &surf->IDirectDrawSurface7_iface;
877 ddraw_surface7_AddRef(*surface);
878 wined3d_mutex_unlock();
880 return DD_OK;
884 /* Next, look at the attachment chain */
885 surf = head_surface;
887 while( (surf = surf->next_attached) )
889 TRACE("Surface %p, caps %#lx, %#lx, %#lx, %#lx.\n", surf,
890 surf->surface_desc.ddsCaps.dwCaps,
891 surf->surface_desc.ddsCaps.dwCaps2,
892 surf->surface_desc.ddsCaps.dwCaps3,
893 surf->surface_desc.ddsCaps.u1.dwCaps4);
895 if (((surf->surface_desc.ddsCaps.dwCaps & our_caps.dwCaps) == our_caps.dwCaps) &&
896 ((surf->surface_desc.ddsCaps.dwCaps2 & our_caps.dwCaps2) == our_caps.dwCaps2)) {
898 TRACE("head_surface %p, returning surface %p.\n", head_surface, surf);
899 *surface = &surf->IDirectDrawSurface7_iface;
900 ddraw_surface7_AddRef(*surface);
901 wined3d_mutex_unlock();
902 return DD_OK;
906 TRACE("head_surface %p, didn't find a valid surface.\n", head_surface);
908 wined3d_mutex_unlock();
910 *surface = NULL;
911 return DDERR_NOTFOUND;
914 static HRESULT WINAPI ddraw_surface4_GetAttachedSurface(IDirectDrawSurface4 *iface,
915 DDSCAPS2 *caps, IDirectDrawSurface4 **attachment)
917 struct ddraw_surface *surface = impl_from_IDirectDrawSurface4(iface);
918 struct ddraw_surface *attachment_impl;
919 IDirectDrawSurface7 *attachment7;
920 HRESULT hr;
922 TRACE("iface %p, caps %p, attachment %p.\n", iface, caps, attachment);
924 hr = ddraw_surface7_GetAttachedSurface(&surface->IDirectDrawSurface7_iface,
925 caps, &attachment7);
926 if (FAILED(hr))
928 *attachment = NULL;
929 return hr;
931 attachment_impl = impl_from_IDirectDrawSurface7(attachment7);
932 *attachment = &attachment_impl->IDirectDrawSurface4_iface;
933 ddraw_surface4_AddRef(*attachment);
934 ddraw_surface7_Release(attachment7);
936 return hr;
939 static HRESULT WINAPI ddraw_surface3_GetAttachedSurface(IDirectDrawSurface3 *iface,
940 DDSCAPS *caps, IDirectDrawSurface3 **attachment)
942 struct ddraw_surface *surface = impl_from_IDirectDrawSurface3(iface);
943 struct ddraw_surface *attachment_impl;
944 IDirectDrawSurface7 *attachment7;
945 DDSCAPS2 caps2;
946 HRESULT hr;
948 TRACE("iface %p, caps %p, attachment %p.\n", iface, caps, attachment);
950 caps2.dwCaps = caps->dwCaps;
951 caps2.dwCaps2 = 0;
952 caps2.dwCaps3 = 0;
953 caps2.u1.dwCaps4 = 0;
955 hr = ddraw_surface7_GetAttachedSurface(&surface->IDirectDrawSurface7_iface,
956 &caps2, &attachment7);
957 if (FAILED(hr))
959 *attachment = NULL;
960 return hr;
962 attachment_impl = impl_from_IDirectDrawSurface7(attachment7);
963 *attachment = &attachment_impl->IDirectDrawSurface3_iface;
964 ddraw_surface3_AddRef(*attachment);
965 ddraw_surface7_Release(attachment7);
967 return hr;
970 static HRESULT WINAPI ddraw_surface2_GetAttachedSurface(IDirectDrawSurface2 *iface,
971 DDSCAPS *caps, IDirectDrawSurface2 **attachment)
973 struct ddraw_surface *surface = impl_from_IDirectDrawSurface2(iface);
974 struct ddraw_surface *attachment_impl;
975 IDirectDrawSurface7 *attachment7;
976 DDSCAPS2 caps2;
977 HRESULT hr;
979 TRACE("iface %p, caps %p, attachment %p.\n", iface, caps, attachment);
981 caps2.dwCaps = caps->dwCaps;
982 caps2.dwCaps2 = 0;
983 caps2.dwCaps3 = 0;
984 caps2.u1.dwCaps4 = 0;
986 hr = ddraw_surface7_GetAttachedSurface(&surface->IDirectDrawSurface7_iface,
987 &caps2, &attachment7);
988 if (FAILED(hr))
990 *attachment = NULL;
991 return hr;
993 attachment_impl = impl_from_IDirectDrawSurface7(attachment7);
994 *attachment = &attachment_impl->IDirectDrawSurface2_iface;
995 ddraw_surface2_AddRef(*attachment);
996 ddraw_surface7_Release(attachment7);
998 return hr;
1001 static HRESULT WINAPI ddraw_surface1_GetAttachedSurface(IDirectDrawSurface *iface,
1002 DDSCAPS *caps, IDirectDrawSurface **attachment)
1004 struct ddraw_surface *surface = impl_from_IDirectDrawSurface(iface);
1005 struct ddraw_surface *attachment_impl;
1006 IDirectDrawSurface7 *attachment7;
1007 DDSCAPS2 caps2;
1008 HRESULT hr;
1010 TRACE("iface %p, caps %p, attachment %p.\n", iface, caps, attachment);
1012 caps2.dwCaps = caps->dwCaps;
1013 caps2.dwCaps2 = 0;
1014 caps2.dwCaps3 = 0;
1015 caps2.u1.dwCaps4 = 0;
1017 hr = ddraw_surface7_GetAttachedSurface(&surface->IDirectDrawSurface7_iface,
1018 &caps2, &attachment7);
1019 if (FAILED(hr))
1021 *attachment = NULL;
1022 return hr;
1024 attachment_impl = impl_from_IDirectDrawSurface7(attachment7);
1025 *attachment = &attachment_impl->IDirectDrawSurface_iface;
1026 ddraw_surface1_AddRef(*attachment);
1027 ddraw_surface7_Release(attachment7);
1029 return hr;
1032 /*****************************************************************************
1033 * IDirectDrawSurface7::Lock
1035 * Locks the surface and returns a pointer to the surface's memory
1037 * Params:
1038 * Rect: Rectangle to lock. If NULL, the whole surface is locked
1039 * DDSD: Pointer to a DDSURFACEDESC2 which shall receive the surface's desc.
1040 * Flags: Locking flags, e.g Read only or write only
1041 * h: An event handle that's not used and must be NULL
1043 * Returns:
1044 * DD_OK on success
1045 * DDERR_INVALIDPARAMS if DDSD is NULL
1047 *****************************************************************************/
1048 static HRESULT surface_lock(struct ddraw_surface *surface,
1049 RECT *rect, DDSURFACEDESC2 *surface_desc, unsigned int surface_desc_size,
1050 DWORD flags, HANDLE h)
1052 struct wined3d_map_desc map_desc;
1053 unsigned int wined3d_flags;
1054 struct wined3d_box box;
1055 HRESULT hr = DD_OK;
1057 TRACE("surface %p, rect %s, surface_desc %p, surface_desc_size %u, flags %#lx, h %p.\n",
1058 surface, wine_dbgstr_rect(rect), surface_desc, surface_desc_size, flags, h);
1060 /* surface->surface_desc.dwWidth and dwHeight are changeable, thus lock */
1061 wined3d_mutex_lock();
1063 /* Should I check for the handle to be NULL?
1065 * The DDLOCK flags and the D3DLOCK flags are equal
1066 * for the supported values. The others are ignored by WineD3D
1069 /* Windows zeroes this if the rect is invalid */
1070 surface_desc->lpSurface = NULL;
1072 if (rect)
1074 if ((rect->left < 0) || (rect->top < 0)
1075 || (rect->left > rect->right) || (rect->right > surface->surface_desc.dwWidth)
1076 || (rect->top > rect->bottom) || (rect->bottom > surface->surface_desc.dwHeight))
1078 WARN("Trying to lock an invalid rectangle, returning DDERR_INVALIDPARAMS\n");
1079 wined3d_mutex_unlock();
1080 return DDERR_INVALIDPARAMS;
1082 wined3d_box_set(&box, rect->left, rect->top, rect->right, rect->bottom, 0, 1);
1085 if (surface->surface_desc.ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE)
1086 hr = ddraw_surface_update_frontbuffer(surface, rect, TRUE, 0);
1087 if (SUCCEEDED(hr))
1089 wined3d_flags = wined3dmapflags_from_ddrawmapflags(flags);
1090 hr = wined3d_resource_map(wined3d_texture_get_resource
1091 (ddraw_surface_get_default_texture(surface, wined3d_flags & WINED3D_MAP_WRITE ? DDRAW_SURFACE_RW
1092 : DDRAW_SURFACE_READ)), surface->sub_resource_idx, &map_desc, rect ? &box : NULL, wined3d_flags);
1094 if (FAILED(hr))
1096 wined3d_mutex_unlock();
1097 switch(hr)
1099 /* D3D8 and D3D9 return the general D3DERR_INVALIDCALL error, but ddraw has a more
1100 * specific error. But since wined3d returns that error in this only occasion,
1101 * keep d3d8 and d3d9 free from the return value override. There are many different
1102 * places where d3d8/9 would have to catch the DDERR_SURFACEBUSY, it is much easier
1103 * to do it in one place in ddraw.
1105 case WINED3DERR_INVALIDCALL: return DDERR_SURFACEBUSY;
1106 default: return hr;
1110 if (surface->surface_desc.ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE)
1112 if (flags & DDLOCK_READONLY)
1113 SetRectEmpty(&surface->ddraw->primary_lock);
1114 else if (rect)
1115 surface->ddraw->primary_lock = *rect;
1116 else
1117 SetRect(&surface->ddraw->primary_lock, 0, 0, surface->surface_desc.dwWidth, surface->surface_desc.dwHeight);
1120 /* Windows does not set DDSD_LPSURFACE on locked surfaces. */
1121 DD_STRUCT_COPY_BYSIZE_(surface_desc, &surface->surface_desc, surface_desc_size, surface->surface_desc.dwSize);
1122 surface_desc->lpSurface = map_desc.data;
1124 TRACE("locked surface returning description :\n");
1125 if (TRACE_ON(ddraw))
1126 DDRAW_dump_surface_desc(surface_desc);
1128 wined3d_mutex_unlock();
1130 return DD_OK;
1133 static BOOL surface_validate_lock_desc(struct ddraw_surface *surface,
1134 const DDSURFACEDESC *desc, unsigned int *size)
1136 if (!desc)
1137 return FALSE;
1139 if (desc->dwSize == sizeof(DDSURFACEDESC) || desc->dwSize == sizeof(DDSURFACEDESC2))
1141 *size = desc->dwSize;
1142 return TRUE;
1145 if (surface->version == 7
1146 && surface->surface_desc.ddsCaps.dwCaps & DDSCAPS_TEXTURE
1147 && !(surface->surface_desc.ddsCaps.dwCaps & DDSCAPS_VIDEOMEMORY))
1149 if (desc->dwSize >= sizeof(DDSURFACEDESC2))
1150 *size = sizeof(DDSURFACEDESC2);
1151 else
1152 *size = sizeof(DDSURFACEDESC);
1153 return TRUE;
1156 WARN("Invalid structure size %lu.\n", desc->dwSize);
1157 return FALSE;
1160 static HRESULT WINAPI ddraw_surface7_Lock(IDirectDrawSurface7 *iface,
1161 RECT *rect, DDSURFACEDESC2 *surface_desc, DWORD flags, HANDLE h)
1163 struct ddraw_surface *surface = impl_from_IDirectDrawSurface7(iface);
1164 unsigned int surface_desc_size;
1166 TRACE("iface %p, rect %s, surface_desc %p, flags %#lx, h %p.\n",
1167 iface, wine_dbgstr_rect(rect), surface_desc, flags, h);
1169 if (!surface_validate_lock_desc(surface, (DDSURFACEDESC *)surface_desc, &surface_desc_size))
1170 return DDERR_INVALIDPARAMS;
1172 if (ddraw_surface_is_lost(surface))
1174 WARN("Surface is lost.\n");
1175 return DDERR_SURFACELOST;
1178 return surface_lock(surface, rect, surface_desc, surface_desc_size, flags, h);
1181 static HRESULT WINAPI ddraw_surface4_Lock(IDirectDrawSurface4 *iface, RECT *rect,
1182 DDSURFACEDESC2 *surface_desc, DWORD flags, HANDLE h)
1184 struct ddraw_surface *surface = impl_from_IDirectDrawSurface4(iface);
1185 unsigned int surface_desc_size;
1187 TRACE("iface %p, rect %s, surface_desc %p, flags %#lx, h %p.\n",
1188 iface, wine_dbgstr_rect(rect), surface_desc, flags, h);
1190 if (!surface_validate_lock_desc(surface, (DDSURFACEDESC *)surface_desc, &surface_desc_size))
1191 return DDERR_INVALIDPARAMS;
1193 if (ddraw_surface_is_lost(surface))
1195 WARN("Surface is lost.\n");
1196 return DDERR_SURFACELOST;
1199 return surface_lock(surface, rect, surface_desc, surface_desc_size, flags, h);
1202 static HRESULT ddraw_surface_lock_ddsd(struct ddraw_surface *surface, RECT *rect,
1203 DDSURFACEDESC *surface_desc, DWORD flags, HANDLE h)
1205 unsigned int surface_desc_size;
1206 DDSURFACEDESC2 surface_desc2;
1207 HRESULT hr;
1209 if (!surface_validate_lock_desc(surface, surface_desc, &surface_desc_size))
1210 return DDERR_INVALIDPARAMS;
1212 if (ddraw_surface_is_lost(surface))
1214 WARN("Surface is lost.\n");
1215 return DDERR_SURFACELOST;
1218 surface_desc2.dwSize = surface_desc->dwSize;
1219 surface_desc2.dwFlags = 0;
1220 hr = surface_lock(surface, rect, &surface_desc2, surface_desc_size, flags, h);
1221 DDSD2_to_DDSD(&surface_desc2, surface_desc);
1222 surface_desc->dwSize = surface_desc2.dwSize;
1223 return hr;
1226 static HRESULT WINAPI ddraw_surface3_Lock(IDirectDrawSurface3 *iface, RECT *rect,
1227 DDSURFACEDESC *surface_desc, DWORD flags, HANDLE h)
1229 struct ddraw_surface *surface = impl_from_IDirectDrawSurface3(iface);
1231 TRACE("iface %p, rect %s, surface_desc %p, flags %#lx, h %p.\n",
1232 iface, wine_dbgstr_rect(rect), surface_desc, flags, h);
1234 return ddraw_surface_lock_ddsd(surface, rect, surface_desc, flags, h);
1237 static HRESULT WINAPI ddraw_surface2_Lock(IDirectDrawSurface2 *iface, RECT *rect,
1238 DDSURFACEDESC *surface_desc, DWORD flags, HANDLE h)
1240 struct ddraw_surface *surface = impl_from_IDirectDrawSurface2(iface);
1242 TRACE("iface %p, rect %s, surface_desc %p, flags %#lx, h %p.\n",
1243 iface, wine_dbgstr_rect(rect), surface_desc, flags, h);
1245 return ddraw_surface_lock_ddsd(surface, rect, surface_desc, flags, h);
1248 static HRESULT WINAPI ddraw_surface1_Lock(IDirectDrawSurface *iface, RECT *rect,
1249 DDSURFACEDESC *surface_desc, DWORD flags, HANDLE h)
1251 struct ddraw_surface *surface = impl_from_IDirectDrawSurface(iface);
1253 TRACE("iface %p, rect %s, surface_desc %p, flags %#lx, h %p.\n",
1254 iface, wine_dbgstr_rect(rect), surface_desc, flags, h);
1256 return ddraw_surface_lock_ddsd(surface, rect, surface_desc, flags, h);
1259 /* FRAPS hooks IDirectDrawSurface::Unlock and expects the version 1 method to be called when the
1260 * game uses later interfaces. */
1261 static HRESULT WINAPI DECLSPEC_HOTPATCH ddraw_surface1_Unlock(IDirectDrawSurface *iface, void *data)
1263 struct ddraw_surface *surface = impl_from_IDirectDrawSurface(iface);
1264 HRESULT hr;
1266 TRACE("iface %p, data %p.\n", iface, data);
1268 wined3d_mutex_lock();
1269 hr = wined3d_resource_unmap(wined3d_texture_get_resource
1270 (ddraw_surface_get_default_texture(surface, 0)), surface->sub_resource_idx);
1271 if (SUCCEEDED(hr) && surface->surface_desc.ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE)
1272 hr = ddraw_surface_update_frontbuffer(surface, &surface->ddraw->primary_lock, FALSE, 0);
1273 wined3d_mutex_unlock();
1275 return hr;
1278 static HRESULT WINAPI DECLSPEC_HOTPATCH ddraw_surface7_Unlock(IDirectDrawSurface7 *iface, RECT *rect)
1280 struct ddraw_surface *surface = impl_from_IDirectDrawSurface7(iface);
1282 TRACE("iface %p, rect %s.\n", iface, wine_dbgstr_rect(rect));
1284 return ddraw_surface1_Unlock(&surface->IDirectDrawSurface_iface, NULL);
1287 static HRESULT WINAPI DECLSPEC_HOTPATCH ddraw_surface4_Unlock(IDirectDrawSurface4 *iface, RECT *rect)
1289 struct ddraw_surface *surface = impl_from_IDirectDrawSurface4(iface);
1291 TRACE("iface %p, rect %s.\n", iface, wine_dbgstr_rect(rect));
1293 return ddraw_surface1_Unlock(&surface->IDirectDrawSurface_iface, NULL);
1296 static HRESULT WINAPI DECLSPEC_HOTPATCH ddraw_surface3_Unlock(IDirectDrawSurface3 *iface, void *data)
1298 struct ddraw_surface *surface = impl_from_IDirectDrawSurface3(iface);
1300 TRACE("iface %p, data %p.\n", iface, data);
1302 return ddraw_surface1_Unlock(&surface->IDirectDrawSurface_iface, data);
1305 static HRESULT WINAPI DECLSPEC_HOTPATCH ddraw_surface2_Unlock(IDirectDrawSurface2 *iface, void *data)
1307 struct ddraw_surface *surface = impl_from_IDirectDrawSurface2(iface);
1309 TRACE("iface %p, data %p.\n", iface, data);
1311 return ddraw_surface1_Unlock(&surface->IDirectDrawSurface_iface, data);
1314 static unsigned int ddraw_swap_interval_from_flags(DWORD flags)
1316 if (flags & DDFLIP_NOVSYNC)
1317 return 0;
1319 switch (flags & (DDFLIP_INTERVAL2 | DDFLIP_INTERVAL3 | DDFLIP_INTERVAL4))
1321 case DDFLIP_INTERVAL2:
1322 return 2;
1323 case DDFLIP_INTERVAL3:
1324 return 3;
1325 case DDFLIP_INTERVAL4:
1326 return 4;
1327 default:
1328 return 1;
1332 static void ddraw_texture_rename_to(struct ddraw_texture *dst_texture, struct wined3d_texture *wined3d_texture,
1333 struct wined3d_texture *draw_texture, struct wined3d_rendertarget_view *rtv, void *texture_memory)
1335 struct ddraw_surface *dst_surface = dst_texture->root;
1336 struct wined3d_rendertarget_view *current_rtv;
1338 /* We don't have to worry about potential texture bindings, since
1339 * flippable surfaces can never be textures. */
1341 current_rtv = wined3d_device_context_get_rendertarget_view(dst_surface->ddraw->immediate_context, 0);
1342 if (current_rtv == dst_surface->wined3d_rtv)
1343 wined3d_device_context_set_rendertarget_views(dst_surface->ddraw->immediate_context, 0, 1, &rtv, FALSE);
1344 wined3d_rendertarget_view_set_parent(rtv, dst_surface, &ddraw_view_wined3d_parent_ops);
1345 dst_surface->wined3d_rtv = rtv;
1347 if (dst_surface->sub_resource_idx)
1348 ERR("Invalid sub-resource index %u for surface %p.\n", dst_surface->sub_resource_idx, dst_surface);
1350 if (draw_texture)
1352 wined3d_texture_set_sub_resource_parent(draw_texture, 0, dst_surface, &ddraw_surface_wined3d_parent_ops);
1353 wined3d_texture_set_sub_resource_parent(wined3d_texture, 0, dst_surface, &ddraw_null_wined3d_parent_ops);
1354 wined3d_resource_set_parent(wined3d_texture_get_resource(draw_texture),
1355 dst_texture, &ddraw_texture_wined3d_parent_ops);
1356 wined3d_resource_set_parent(wined3d_texture_get_resource(wined3d_texture),
1357 dst_texture, &ddraw_null_wined3d_parent_ops);
1359 else
1361 wined3d_texture_set_sub_resource_parent(wined3d_texture, 0, dst_surface, &ddraw_surface_wined3d_parent_ops);
1362 wined3d_resource_set_parent(wined3d_texture_get_resource(wined3d_texture),
1363 dst_texture, &ddraw_texture_wined3d_parent_ops);
1366 dst_surface->wined3d_texture = wined3d_texture;
1367 dst_surface->draw_texture = draw_texture;
1369 dst_texture->texture_memory = texture_memory;
1372 /* FRAPS hooks IDirectDrawSurface::Flip and expects the version 1 method to be called when the
1373 * game uses later interfaces. */
1374 static HRESULT WINAPI DECLSPEC_HOTPATCH ddraw_surface1_Flip(IDirectDrawSurface *iface,
1375 IDirectDrawSurface *src, DWORD flags)
1377 struct ddraw_surface *dst_impl = impl_from_IDirectDrawSurface(iface);
1378 struct ddraw_surface *src_impl = unsafe_impl_from_IDirectDrawSurface(src);
1379 struct ddraw_texture *dst_ddraw_texture, *src_ddraw_texture;
1380 struct wined3d_texture *texture, *draw_texture;
1381 struct wined3d_rendertarget_view *tmp_rtv;
1382 DDSCAPS caps = {DDSCAPS_FLIP};
1383 IDirectDrawSurface *current;
1384 void *texture_memory;
1385 HRESULT hr;
1387 TRACE("iface %p, src %p, flags %#lx.\n", iface, src, flags);
1389 if (src == iface || !(dst_impl->surface_desc.ddsCaps.dwCaps & (DDSCAPS_FRONTBUFFER | DDSCAPS_OVERLAY)))
1390 return DDERR_NOTFLIPPABLE;
1392 if (ddraw_surface_is_lost(dst_impl))
1393 return DDERR_SURFACELOST;
1395 wined3d_mutex_lock();
1397 if ((dst_impl->surface_desc.ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE)
1398 && !(dst_impl->ddraw->cooperative_level & DDSCL_EXCLUSIVE))
1400 WARN("Not in exclusive mode.\n");
1401 wined3d_mutex_unlock();
1402 return DDERR_NOEXCLUSIVEMODE;
1405 tmp_rtv = ddraw_surface_get_rendertarget_view(dst_impl);
1406 texture = dst_impl->wined3d_texture;
1407 dst_ddraw_texture = wined3d_texture_get_parent(dst_impl->wined3d_texture);
1408 texture_memory = dst_ddraw_texture->texture_memory;
1409 draw_texture = dst_impl->draw_texture;
1411 if (src_impl)
1413 for (current = iface; current != src;)
1415 if (FAILED(hr = ddraw_surface1_GetAttachedSurface(current, &caps, &current)))
1417 WARN("Surface %p is not on the same flip chain as surface %p.\n", src, iface);
1418 wined3d_mutex_unlock();
1419 return DDERR_NOTFLIPPABLE;
1421 ddraw_surface1_Release(current);
1422 if (current == iface)
1424 WARN("Surface %p is not on the same flip chain as surface %p.\n", src, iface);
1425 wined3d_mutex_unlock();
1426 return DDERR_NOTFLIPPABLE;
1430 src_ddraw_texture = wined3d_texture_get_parent(src_impl->wined3d_texture);
1432 ddraw_texture_rename_to(dst_ddraw_texture, src_impl->wined3d_texture, src_impl->draw_texture,
1433 ddraw_surface_get_rendertarget_view(src_impl), src_ddraw_texture->texture_memory);
1435 dst_ddraw_texture = src_ddraw_texture;
1437 else
1439 for (current = iface;;)
1441 if (FAILED(hr = ddraw_surface1_GetAttachedSurface(current, &caps, &current)))
1443 ERR("Can't find a flip target\n");
1444 wined3d_mutex_unlock();
1445 return DDERR_NOTFLIPPABLE; /* Unchecked */
1447 ddraw_surface1_Release(current);
1448 if (current == iface)
1450 dst_impl = impl_from_IDirectDrawSurface(iface);
1451 break;
1454 src_impl = impl_from_IDirectDrawSurface(current);
1455 src_ddraw_texture = wined3d_texture_get_parent(src_impl->wined3d_texture);
1457 ddraw_texture_rename_to(dst_ddraw_texture, src_impl->wined3d_texture, src_impl->draw_texture,
1458 ddraw_surface_get_rendertarget_view(src_impl), src_ddraw_texture->texture_memory);
1460 dst_ddraw_texture = src_ddraw_texture;
1461 dst_impl = src_impl;
1465 ddraw_texture_rename_to(dst_ddraw_texture, texture, draw_texture, tmp_rtv, texture_memory);
1467 if (flags & ~(DDFLIP_NOVSYNC | DDFLIP_INTERVAL2 | DDFLIP_INTERVAL3 | DDFLIP_INTERVAL4))
1469 static UINT once;
1470 if (!once++)
1471 FIXME("Ignoring flags %#lx.\n", flags);
1472 else
1473 WARN("Ignoring flags %#lx.\n", flags);
1476 if (dst_impl->surface_desc.ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE)
1477 hr = ddraw_surface_update_frontbuffer(dst_impl, NULL, FALSE, ddraw_swap_interval_from_flags(flags));
1478 else
1479 hr = DD_OK;
1481 wined3d_mutex_unlock();
1483 return hr;
1486 static HRESULT WINAPI DECLSPEC_HOTPATCH ddraw_surface7_Flip(IDirectDrawSurface7 *iface,
1487 IDirectDrawSurface7 *src, DWORD flags)
1489 struct ddraw_surface *surface = impl_from_IDirectDrawSurface7(iface);
1490 struct ddraw_surface *src_impl = unsafe_impl_from_IDirectDrawSurface7(src);
1492 TRACE("iface %p, src %p, flags %#lx.\n", iface, src, flags);
1494 return ddraw_surface1_Flip(&surface->IDirectDrawSurface_iface,
1495 src_impl ? &src_impl->IDirectDrawSurface_iface : NULL, flags);
1498 static HRESULT WINAPI DECLSPEC_HOTPATCH ddraw_surface4_Flip(IDirectDrawSurface4 *iface,
1499 IDirectDrawSurface4 *src, DWORD flags)
1501 struct ddraw_surface *surface = impl_from_IDirectDrawSurface4(iface);
1502 struct ddraw_surface *src_impl = unsafe_impl_from_IDirectDrawSurface4(src);
1504 TRACE("iface %p, src %p, flags %#lx.\n", iface, src, flags);
1506 return ddraw_surface1_Flip(&surface->IDirectDrawSurface_iface,
1507 src_impl ? &src_impl->IDirectDrawSurface_iface : NULL, flags);
1510 static HRESULT WINAPI DECLSPEC_HOTPATCH ddraw_surface3_Flip(IDirectDrawSurface3 *iface,
1511 IDirectDrawSurface3 *src, DWORD flags)
1513 struct ddraw_surface *surface = impl_from_IDirectDrawSurface3(iface);
1514 struct ddraw_surface *src_impl = unsafe_impl_from_IDirectDrawSurface3(src);
1516 TRACE("iface %p, src %p, flags %#lx.\n", iface, src, flags);
1518 return ddraw_surface1_Flip(&surface->IDirectDrawSurface_iface,
1519 src_impl ? &src_impl->IDirectDrawSurface_iface : NULL, flags);
1522 static HRESULT WINAPI DECLSPEC_HOTPATCH ddraw_surface2_Flip(IDirectDrawSurface2 *iface,
1523 IDirectDrawSurface2 *src, DWORD flags)
1525 struct ddraw_surface *surface = impl_from_IDirectDrawSurface2(iface);
1526 struct ddraw_surface *src_impl = unsafe_impl_from_IDirectDrawSurface2(src);
1528 TRACE("iface %p, src %p, flags %#lx.\n", iface, src, flags);
1530 return ddraw_surface1_Flip(&surface->IDirectDrawSurface_iface,
1531 src_impl ? &src_impl->IDirectDrawSurface_iface : NULL, flags);
1534 static HRESULT ddraw_surface_blt(struct ddraw_surface *dst_surface, const RECT *dst_rect,
1535 struct ddraw_surface *src_surface, const RECT *src_rect, DWORD flags, DWORD fill_colour,
1536 const struct wined3d_blt_fx *fx, enum wined3d_texture_filter_type filter)
1538 struct ddraw *ddraw = dst_surface->ddraw;
1539 struct wined3d_device *wined3d_device = ddraw->wined3d_device;
1540 struct wined3d_color colour;
1541 DWORD wined3d_flags;
1543 if (flags & DDBLT_COLORFILL)
1545 wined3d_flags = WINED3DCLEAR_TARGET;
1546 if (!(flags & DDBLT_ASYNC))
1547 wined3d_flags |= WINED3DCLEAR_SYNCHRONOUS;
1549 if (!wined3d_colour_from_ddraw_colour(&dst_surface->surface_desc.u4.ddpfPixelFormat,
1550 dst_surface->palette, fill_colour, &colour))
1551 return DDERR_INVALIDPARAMS;
1553 wined3d_device_apply_stateblock(wined3d_device, ddraw->state);
1554 ddraw_surface_get_draw_texture(dst_surface, dst_rect ? DDRAW_SURFACE_RW : DDRAW_SURFACE_WRITE);
1555 return wined3d_device_context_clear_rendertarget_view(ddraw->immediate_context,
1556 ddraw_surface_get_rendertarget_view(dst_surface),
1557 dst_rect, wined3d_flags, &colour, 0.0f, 0);
1560 if (flags & DDBLT_DEPTHFILL)
1562 wined3d_flags = WINED3DCLEAR_ZBUFFER;
1563 if (!(flags & DDBLT_ASYNC))
1564 wined3d_flags |= WINED3DCLEAR_SYNCHRONOUS;
1566 if (!wined3d_colour_from_ddraw_colour(&dst_surface->surface_desc.u4.ddpfPixelFormat,
1567 dst_surface->palette, fill_colour, &colour))
1568 return DDERR_INVALIDPARAMS;
1570 wined3d_device_apply_stateblock(wined3d_device, ddraw->state);
1571 ddraw_surface_get_draw_texture(dst_surface, dst_rect ? DDRAW_SURFACE_RW : DDRAW_SURFACE_WRITE);
1572 return wined3d_device_context_clear_rendertarget_view(ddraw->immediate_context,
1573 ddraw_surface_get_rendertarget_view(dst_surface),
1574 dst_rect, wined3d_flags, NULL, colour.r, 0);
1577 wined3d_flags = flags & ~DDBLT_ASYNC;
1578 if (wined3d_flags & ~WINED3D_BLT_MASK)
1580 FIXME("Unhandled flags %#lx.\n", flags);
1581 return E_NOTIMPL;
1584 if (!(flags & DDBLT_ASYNC))
1585 wined3d_flags |= WINED3D_BLT_SYNCHRONOUS;
1587 return wined3d_device_context_blt(ddraw->immediate_context,
1588 ddraw_surface_get_any_texture(dst_surface, DDRAW_SURFACE_RW), dst_surface->sub_resource_idx, dst_rect,
1589 ddraw_surface_get_any_texture(src_surface, DDRAW_SURFACE_READ), src_surface->sub_resource_idx, src_rect,
1590 wined3d_flags, fx, filter);
1593 static HRESULT ddraw_surface_blt_clipped(struct ddraw_surface *dst_surface, const RECT *dst_rect_in,
1594 struct ddraw_surface *src_surface, const RECT *src_rect_in, DWORD flags, DWORD fill_colour,
1595 const struct wined3d_blt_fx *fx, enum wined3d_texture_filter_type filter)
1597 RECT src_rect, dst_rect;
1598 float scale_x, scale_y;
1599 const RECT *clip_rect;
1600 DWORD clip_list_size;
1601 RGNDATA *clip_list;
1602 HRESULT hr = DD_OK;
1603 UINT i;
1605 if (!dst_rect_in)
1606 SetRect(&dst_rect, 0, 0, dst_surface->surface_desc.dwWidth,
1607 dst_surface->surface_desc.dwHeight);
1608 else
1609 dst_rect = *dst_rect_in;
1611 if (IsRectEmpty(&dst_rect))
1612 return DDERR_INVALIDRECT;
1614 if (src_surface)
1616 if (!src_rect_in)
1617 SetRect(&src_rect, 0, 0, src_surface->surface_desc.dwWidth,
1618 src_surface->surface_desc.dwHeight);
1619 else
1620 src_rect = *src_rect_in;
1622 if (IsRectEmpty(&src_rect))
1623 return DDERR_INVALIDRECT;
1625 else
1627 SetRectEmpty(&src_rect);
1630 if (!dst_surface->clipper)
1632 if (src_surface && src_surface->surface_desc.ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE)
1633 hr = ddraw_surface_update_frontbuffer(src_surface, &src_rect, TRUE, 0);
1634 if (SUCCEEDED(hr))
1635 hr = ddraw_surface_blt(dst_surface, &dst_rect, src_surface, &src_rect, flags, fill_colour, fx, filter);
1636 if (SUCCEEDED(hr) && (dst_surface->surface_desc.ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE))
1637 hr = ddraw_surface_update_frontbuffer(dst_surface, &dst_rect, FALSE, 0);
1639 return hr;
1642 if (!ddraw_clipper_is_valid(dst_surface->clipper))
1644 FIXME("Attempting to blit with an invalid clipper.\n");
1645 return DDERR_INVALIDPARAMS;
1648 scale_x = (float)(src_rect.right - src_rect.left) / (float)(dst_rect.right - dst_rect.left);
1649 scale_y = (float)(src_rect.bottom - src_rect.top) / (float)(dst_rect.bottom - dst_rect.top);
1651 if (FAILED(hr = IDirectDrawClipper_GetClipList(&dst_surface->clipper->IDirectDrawClipper_iface,
1652 &dst_rect, NULL, &clip_list_size)))
1654 WARN("Failed to get clip list size, hr %#lx.\n", hr);
1655 return hr;
1658 if (!(clip_list = heap_alloc(clip_list_size)))
1660 WARN("Failed to allocate clip list.\n");
1661 return E_OUTOFMEMORY;
1664 if (FAILED(hr = IDirectDrawClipper_GetClipList(&dst_surface->clipper->IDirectDrawClipper_iface,
1665 &dst_rect, clip_list, &clip_list_size)))
1667 WARN("Failed to get clip list, hr %#lx.\n", hr);
1668 heap_free(clip_list);
1669 return hr;
1672 clip_rect = (RECT *)clip_list->Buffer;
1673 for (i = 0; i < clip_list->rdh.nCount; ++i)
1675 RECT src_rect_clipped = src_rect;
1677 if (src_surface)
1679 src_rect_clipped.left += (LONG)((clip_rect[i].left - dst_rect.left) * scale_x);
1680 src_rect_clipped.top += (LONG)((clip_rect[i].top - dst_rect.top) * scale_y);
1681 src_rect_clipped.right -= (LONG)((dst_rect.right - clip_rect[i].right) * scale_x);
1682 src_rect_clipped.bottom -= (LONG)((dst_rect.bottom - clip_rect[i].bottom) * scale_y);
1684 if (src_surface->surface_desc.ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE)
1686 if (FAILED(hr = ddraw_surface_update_frontbuffer(src_surface, &src_rect_clipped, TRUE, 0)))
1687 break;
1691 if (FAILED(hr = ddraw_surface_blt(dst_surface, &clip_rect[i],
1692 src_surface, &src_rect_clipped, flags, fill_colour, fx, filter)))
1693 break;
1695 if (dst_surface->surface_desc.ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE)
1697 if (FAILED(hr = ddraw_surface_update_frontbuffer(dst_surface, &clip_rect[i], FALSE, 0)))
1698 break;
1702 heap_free(clip_list);
1703 return hr;
1706 /* FRAPS hooks IDirectDrawSurface::Blt and expects the version 1 method to be called when the
1707 * game uses later interfaces. */
1708 static HRESULT WINAPI DECLSPEC_HOTPATCH ddraw_surface1_Blt(IDirectDrawSurface *iface, RECT *dst_rect,
1709 IDirectDrawSurface *src_surface, RECT *src_rect, DWORD flags, DDBLTFX *fx)
1711 struct ddraw_surface *dst_impl = impl_from_IDirectDrawSurface(iface);
1712 struct ddraw_surface *src_impl = unsafe_impl_from_IDirectDrawSurface(src_surface);
1713 struct wined3d_blt_fx wined3d_fx = {0};
1714 DWORD unsupported_flags;
1715 DWORD fill_colour = 0;
1716 HRESULT hr = DD_OK;
1717 DDBLTFX rop_fx;
1719 TRACE("iface %p, dst_rect %s, src_surface %p, src_rect %s, flags %#lx, fx %p.\n",
1720 iface, wine_dbgstr_rect(dst_rect), src_surface, wine_dbgstr_rect(src_rect), flags, fx);
1722 unsupported_flags = DDBLT_ALPHADEST
1723 | DDBLT_ALPHADESTCONSTOVERRIDE
1724 | DDBLT_ALPHADESTNEG
1725 | DDBLT_ALPHADESTSURFACEOVERRIDE
1726 | DDBLT_ALPHAEDGEBLEND
1727 | DDBLT_ALPHASRC
1728 | DDBLT_ALPHASRCCONSTOVERRIDE
1729 | DDBLT_ALPHASRCNEG
1730 | DDBLT_ALPHASRCSURFACEOVERRIDE
1731 | DDBLT_ZBUFFER
1732 | DDBLT_ZBUFFERDESTCONSTOVERRIDE
1733 | DDBLT_ZBUFFERDESTOVERRIDE
1734 | DDBLT_ZBUFFERSRCCONSTOVERRIDE
1735 | DDBLT_ZBUFFERSRCOVERRIDE;
1736 if (flags & unsupported_flags)
1738 WARN("Ignoring unsupported flags %#lx.\n", flags & unsupported_flags);
1739 flags &= ~unsupported_flags;
1742 if ((flags & DDBLT_KEYSRCOVERRIDE) && (!fx || flags & DDBLT_KEYSRC))
1744 WARN("Invalid source color key parameters, returning DDERR_INVALIDPARAMS\n");
1745 return DDERR_INVALIDPARAMS;
1748 if ((flags & DDBLT_KEYDESTOVERRIDE) && (!fx || flags & DDBLT_KEYDEST))
1750 WARN("Invalid destination color key parameters, returning DDERR_INVALIDPARAMS\n");
1751 return DDERR_INVALIDPARAMS;
1754 if (flags & DDBLT_DDROPS)
1756 FIXME("DDBLT_DDROPS not implemented.\n");
1757 if (fx)
1758 FIXME(" rop %#lx, pattern %p.\n", fx->dwDDROP, fx->u5.lpDDSPattern);
1759 return DDERR_NORASTEROPHW;
1762 wined3d_mutex_lock();
1764 if (flags & (DDBLT_COLORFILL | DDBLT_DEPTHFILL))
1766 if (flags & DDBLT_ROP)
1768 wined3d_mutex_unlock();
1769 WARN("DDBLT_ROP used with DDBLT_COLORFILL or DDBLT_DEPTHFILL, returning DDERR_INVALIDPARAMS.\n");
1770 return DDERR_INVALIDPARAMS;
1772 if (src_impl)
1774 wined3d_mutex_unlock();
1775 WARN("Depth or colorfill is not compatible with source surfaces, returning DDERR_INVALIDPARAMS\n");
1776 return DDERR_INVALIDPARAMS;
1778 if (!fx)
1780 wined3d_mutex_unlock();
1781 WARN("Depth or colorfill used with NULL fx, returning DDERR_INVALIDPARAMS.\n");
1782 return DDERR_INVALIDPARAMS;
1785 if ((flags & (DDBLT_COLORFILL | DDBLT_DEPTHFILL)) == (DDBLT_COLORFILL | DDBLT_DEPTHFILL))
1786 flags &= ~DDBLT_DEPTHFILL;
1788 if ((dst_impl->surface_desc.ddsCaps.dwCaps & DDSCAPS_ZBUFFER) && (flags & DDBLT_COLORFILL))
1790 wined3d_mutex_unlock();
1791 WARN("DDBLT_COLORFILL used on a depth buffer, returning DDERR_INVALIDPARAMS.\n");
1792 return DDERR_INVALIDPARAMS;
1794 if (!(dst_impl->surface_desc.ddsCaps.dwCaps & DDSCAPS_ZBUFFER) && (flags & DDBLT_DEPTHFILL))
1796 wined3d_mutex_unlock();
1797 WARN("DDBLT_DEPTHFILL used on a color buffer, returning DDERR_INVALIDPARAMS.\n");
1798 return DDERR_INVALIDPARAMS;
1802 if (flags & DDBLT_ROP)
1804 if (!fx)
1806 wined3d_mutex_unlock();
1807 WARN("DDBLT_ROP used with NULL fx, returning DDERR_INVALIDPARAMS.\n");
1808 return DDERR_INVALIDPARAMS;
1811 if (src_impl && src_rect
1812 && ((ULONG)src_rect->left >= src_rect->right || src_rect->right > src_impl->surface_desc.dwWidth
1813 || (ULONG)src_rect->top >= src_rect->bottom || src_rect->bottom > src_impl->surface_desc.dwHeight))
1815 wined3d_mutex_unlock();
1816 WARN("Invalid source rectangle.\n");
1817 return DDERR_INVALIDRECT;
1820 flags &= ~DDBLT_ROP;
1821 switch (fx->dwROP)
1823 case SRCCOPY:
1824 break;
1826 case WHITENESS:
1827 case BLACKNESS:
1828 rop_fx = *fx;
1830 if (fx->dwROP == WHITENESS)
1831 rop_fx.u5.dwFillColor = 0xffffffff;
1832 else
1833 rop_fx.u5.dwFillColor = 0;
1835 if (dst_impl->surface_desc.ddsCaps.dwCaps & DDSCAPS_ZBUFFER)
1836 flags |= DDBLT_DEPTHFILL;
1837 else
1838 flags |= DDBLT_COLORFILL;
1840 fx = &rop_fx;
1841 break;
1843 default:
1844 wined3d_mutex_unlock();
1845 WARN("Unsupported ROP %#lx used, returning DDERR_NORASTEROPHW.\n", fx->dwROP);
1846 return DDERR_NORASTEROPHW;
1850 if (!(flags & (DDBLT_COLORFILL | DDBLT_DEPTHFILL)) && !src_impl)
1852 WARN("No source surface.\n");
1853 wined3d_mutex_unlock();
1854 return DDERR_INVALIDPARAMS;
1857 if (flags & DDBLT_KEYSRC && (!src_impl || !(src_impl->surface_desc.dwFlags & DDSD_CKSRCBLT)))
1859 WARN("DDBLT_KEYSRC blit without color key in surface, returning DDERR_INVALIDPARAMS\n");
1860 wined3d_mutex_unlock();
1861 return DDERR_INVALIDPARAMS;
1863 if (flags & DDBLT_KEYDEST && !(dst_impl->surface_desc.dwFlags & DDSD_CKDESTBLT))
1865 WARN("DDBLT_KEYDEST blit without color key in surface, returning DDERR_INVALIDPARAMS\n");
1866 wined3d_mutex_unlock();
1867 return DDERR_INVALIDPARAMS;
1870 if (fx)
1872 wined3d_fx.fx = fx->dwDDFX;
1873 fill_colour = fx->u5.dwFillColor;
1874 wined3d_fx.dst_color_key.color_space_low_value = fx->ddckDestColorkey.dwColorSpaceLowValue;
1875 wined3d_fx.dst_color_key.color_space_high_value = fx->ddckDestColorkey.dwColorSpaceHighValue;
1876 wined3d_fx.src_color_key.color_space_low_value = fx->ddckSrcColorkey.dwColorSpaceLowValue;
1877 wined3d_fx.src_color_key.color_space_high_value = fx->ddckSrcColorkey.dwColorSpaceHighValue;
1880 hr = ddraw_surface_blt_clipped(dst_impl, dst_rect, src_impl,
1881 src_rect, flags, fill_colour, fx ? &wined3d_fx : NULL, WINED3D_TEXF_LINEAR);
1883 wined3d_mutex_unlock();
1884 switch(hr)
1886 case WINED3DERR_NOTAVAILABLE: return DDERR_UNSUPPORTED;
1887 default: return hr;
1891 static HRESULT WINAPI DECLSPEC_HOTPATCH ddraw_surface7_Blt(IDirectDrawSurface7 *iface, RECT *dst_rect,
1892 IDirectDrawSurface7 *src_surface, RECT *src_rect, DWORD flags, DDBLTFX *fx)
1894 struct ddraw_surface *dst = impl_from_IDirectDrawSurface7(iface);
1895 struct ddraw_surface *src = unsafe_impl_from_IDirectDrawSurface7(src_surface);
1897 TRACE("iface %p, dst_rect %s, src_surface %p, src_rect %s, flags %#lx, fx %p.\n",
1898 iface, wine_dbgstr_rect(dst_rect), src_surface, wine_dbgstr_rect(src_rect), flags, fx);
1900 return ddraw_surface1_Blt(&dst->IDirectDrawSurface_iface, dst_rect,
1901 src ? &src->IDirectDrawSurface_iface : NULL, src_rect, flags, fx);
1904 static HRESULT WINAPI DECLSPEC_HOTPATCH ddraw_surface4_Blt(IDirectDrawSurface4 *iface, RECT *dst_rect,
1905 IDirectDrawSurface4 *src_surface, RECT *src_rect, DWORD flags, DDBLTFX *fx)
1907 struct ddraw_surface *dst = impl_from_IDirectDrawSurface4(iface);
1908 struct ddraw_surface *src = unsafe_impl_from_IDirectDrawSurface4(src_surface);
1910 TRACE("iface %p, dst_rect %s, src_surface %p, src_rect %s, flags %#lx, fx %p.\n",
1911 iface, wine_dbgstr_rect(dst_rect), src_surface, wine_dbgstr_rect(src_rect), flags, fx);
1913 return ddraw_surface1_Blt(&dst->IDirectDrawSurface_iface, dst_rect,
1914 src ? &src->IDirectDrawSurface_iface : NULL, src_rect, flags, fx);
1917 static HRESULT WINAPI DECLSPEC_HOTPATCH ddraw_surface3_Blt(IDirectDrawSurface3 *iface, RECT *dst_rect,
1918 IDirectDrawSurface3 *src_surface, RECT *src_rect, DWORD flags, DDBLTFX *fx)
1920 struct ddraw_surface *dst = impl_from_IDirectDrawSurface3(iface);
1921 struct ddraw_surface *src = unsafe_impl_from_IDirectDrawSurface3(src_surface);
1923 TRACE("iface %p, dst_rect %s, src_surface %p, src_rect %s, flags %#lx, fx %p.\n",
1924 iface, wine_dbgstr_rect(dst_rect), src_surface, wine_dbgstr_rect(src_rect), flags, fx);
1926 return ddraw_surface1_Blt(&dst->IDirectDrawSurface_iface, dst_rect,
1927 src ? &src->IDirectDrawSurface_iface : NULL, src_rect, flags, fx);
1930 static HRESULT WINAPI DECLSPEC_HOTPATCH ddraw_surface2_Blt(IDirectDrawSurface2 *iface, RECT *dst_rect,
1931 IDirectDrawSurface2 *src_surface, RECT *src_rect, DWORD flags, DDBLTFX *fx)
1933 struct ddraw_surface *dst = impl_from_IDirectDrawSurface2(iface);
1934 struct ddraw_surface *src = unsafe_impl_from_IDirectDrawSurface2(src_surface);
1936 TRACE("iface %p, dst_rect %s, src_surface %p, src_rect %s, flags %#lx, fx %p.\n",
1937 iface, wine_dbgstr_rect(dst_rect), src_surface, wine_dbgstr_rect(src_rect), flags, fx);
1939 return ddraw_surface1_Blt(&dst->IDirectDrawSurface_iface, dst_rect,
1940 src ? &src->IDirectDrawSurface_iface : NULL, src_rect, flags, fx);
1943 /*****************************************************************************
1944 * IDirectDrawSurface7::AddAttachedSurface
1946 * Attaches a surface to another surface. How the surface attachments work
1947 * is not totally understood yet, and this method is prone to problems.
1948 * The surface that is attached is AddRef-ed.
1950 * Tests with complex surfaces suggest that the surface attachments form a
1951 * tree, but no method to test this has been found yet.
1953 * The attachment list consists of a first surface (first_attached) and
1954 * for each surface a pointer to the next attached surface (next_attached).
1955 * For the first surface, and a surface that has no attachments
1956 * first_attached points to the surface itself. A surface that has
1957 * no successors in the chain has next_attached set to NULL.
1959 * Newly attached surfaces are attached right after the root surface.
1960 * If a surface is attached to a complex surface compound, it's attached to
1961 * the surface that the app requested, not the complex root. See
1962 * GetAttachedSurface for a description how surfaces are found.
1964 * This is how the current implementation works, and it was coded by looking
1965 * at the needs of the applications.
1967 * So far only Z-Buffer attachments are tested, and they are activated in
1968 * WineD3D. Mipmaps could be tricky to activate in WineD3D.
1969 * Back buffers should work in 2D mode, but they are not tested(They can be
1970 * attached in older iface versions). Rendering to the front buffer and
1971 * switching between that and double buffering is not yet implemented in
1972 * WineD3D, so for 3D it might have unexpected results.
1974 * ddraw_surface_attach_surface is the real thing,
1975 * ddraw_surface7_AddAttachedSurface is a wrapper around it that
1976 * performs additional checks. Version 7 of this interface is much more restrictive
1977 * than its predecessors.
1979 * Params:
1980 * Attach: Surface to attach to iface
1982 * Returns:
1983 * DD_OK on success
1984 * DDERR_CANNOTATTACHSURFACE if the surface can't be attached for some reason
1986 *****************************************************************************/
1987 static HRESULT ddraw_surface_attach_surface(struct ddraw_surface *This, struct ddraw_surface *Surf)
1989 TRACE("surface %p, attachment %p.\n", This, Surf);
1991 if(Surf == This)
1992 return DDERR_CANNOTATTACHSURFACE; /* unchecked */
1994 wined3d_mutex_lock();
1996 /* Check if the surface is already attached somewhere */
1997 if (Surf->next_attached || Surf->first_attached != Surf)
1999 /* TODO: Test for the structure of the manual attachment. Is it a
2000 * chain or a list? What happens if one surface is attached to 2
2001 * different surfaces? */
2002 WARN("Surface %p is already attached somewhere. next_attached %p, first_attached %p.\n",
2003 Surf, Surf->next_attached, Surf->first_attached);
2005 wined3d_mutex_unlock();
2006 return DDERR_SURFACEALREADYATTACHED;
2009 /* This inserts the new surface at the 2nd position in the chain, right after the root surface */
2010 Surf->next_attached = This->next_attached;
2011 Surf->first_attached = This->first_attached;
2012 This->next_attached = Surf;
2014 /* Check if the WineD3D depth stencil needs updating */
2015 if (This->ddraw->d3ddevice)
2016 d3d_device_update_depth_stencil(This->ddraw->d3ddevice);
2018 wined3d_mutex_unlock();
2020 return DD_OK;
2023 static HRESULT WINAPI ddraw_surface7_AddAttachedSurface(IDirectDrawSurface7 *iface, IDirectDrawSurface7 *attachment)
2025 struct ddraw_surface *This = impl_from_IDirectDrawSurface7(iface);
2026 struct ddraw_surface *attachment_impl = unsafe_impl_from_IDirectDrawSurface7(attachment);
2027 HRESULT hr;
2029 TRACE("iface %p, attachment %p.\n", iface, attachment);
2031 /* Version 7 of this interface seems to refuse everything except z buffers, as per msdn */
2032 if(!(attachment_impl->surface_desc.ddsCaps.dwCaps & DDSCAPS_ZBUFFER))
2035 WARN("Application tries to attach a non Z buffer surface. caps %#lx.\n",
2036 attachment_impl->surface_desc.ddsCaps.dwCaps);
2037 return DDERR_CANNOTATTACHSURFACE;
2040 hr = ddraw_surface_attach_surface(This, attachment_impl);
2041 if (FAILED(hr))
2043 return hr;
2045 attachment_impl->attached_iface = (IUnknown *)attachment;
2046 IUnknown_AddRef(attachment_impl->attached_iface);
2047 return hr;
2050 static HRESULT WINAPI ddraw_surface4_AddAttachedSurface(IDirectDrawSurface4 *iface, IDirectDrawSurface4 *attachment)
2052 struct ddraw_surface *surface = impl_from_IDirectDrawSurface4(iface);
2053 struct ddraw_surface *attachment_impl = unsafe_impl_from_IDirectDrawSurface4(attachment);
2054 HRESULT hr;
2056 TRACE("iface %p, attachment %p.\n", iface, attachment);
2058 /* Tests suggest that
2059 * -> offscreen plain surfaces can be attached to other offscreen plain surfaces
2060 * -> offscreen plain surfaces can be attached to primaries
2061 * -> primaries can be attached to offscreen plain surfaces
2062 * -> z buffers can be attached to primaries */
2063 if (surface->surface_desc.ddsCaps.dwCaps & (DDSCAPS_PRIMARYSURFACE | DDSCAPS_OFFSCREENPLAIN)
2064 && attachment_impl->surface_desc.ddsCaps.dwCaps & (DDSCAPS_PRIMARYSURFACE | DDSCAPS_OFFSCREENPLAIN))
2066 /* Sizes have to match */
2067 if (attachment_impl->surface_desc.dwWidth != surface->surface_desc.dwWidth
2068 || attachment_impl->surface_desc.dwHeight != surface->surface_desc.dwHeight)
2070 WARN("Surface sizes do not match.\n");
2071 return DDERR_CANNOTATTACHSURFACE;
2074 else if (!(surface->surface_desc.ddsCaps.dwCaps & (DDSCAPS_PRIMARYSURFACE | DDSCAPS_3DDEVICE))
2075 || !(attachment_impl->surface_desc.ddsCaps.dwCaps & (DDSCAPS_ZBUFFER)))
2077 WARN("Invalid attachment combination.\n");
2078 return DDERR_CANNOTATTACHSURFACE;
2081 if (FAILED(hr = ddraw_surface_attach_surface(surface, attachment_impl)))
2082 return hr;
2084 attachment_impl->attached_iface = (IUnknown *)attachment;
2085 IUnknown_AddRef(attachment_impl->attached_iface);
2086 return hr;
2089 static HRESULT WINAPI ddraw_surface3_AddAttachedSurface(IDirectDrawSurface3 *iface, IDirectDrawSurface3 *attachment)
2091 struct ddraw_surface *surface = impl_from_IDirectDrawSurface3(iface);
2092 struct ddraw_surface *attachment_impl = unsafe_impl_from_IDirectDrawSurface3(attachment);
2093 HRESULT hr;
2095 TRACE("iface %p, attachment %p.\n", iface, attachment);
2097 if (FAILED(hr = ddraw_surface4_AddAttachedSurface(&surface->IDirectDrawSurface4_iface,
2098 attachment_impl ? &attachment_impl->IDirectDrawSurface4_iface : NULL)))
2099 return hr;
2101 attachment_impl->attached_iface = (IUnknown *)attachment;
2102 IUnknown_AddRef(attachment_impl->attached_iface);
2103 ddraw_surface4_Release(&attachment_impl->IDirectDrawSurface4_iface);
2104 return hr;
2107 static HRESULT WINAPI ddraw_surface2_AddAttachedSurface(IDirectDrawSurface2 *iface, IDirectDrawSurface2 *attachment)
2109 struct ddraw_surface *surface = impl_from_IDirectDrawSurface2(iface);
2110 struct ddraw_surface *attachment_impl = unsafe_impl_from_IDirectDrawSurface2(attachment);
2111 HRESULT hr;
2113 TRACE("iface %p, attachment %p.\n", iface, attachment);
2115 if (FAILED(hr = ddraw_surface4_AddAttachedSurface(&surface->IDirectDrawSurface4_iface,
2116 attachment_impl ? &attachment_impl->IDirectDrawSurface4_iface : NULL)))
2117 return hr;
2119 attachment_impl->attached_iface = (IUnknown *)attachment;
2120 IUnknown_AddRef(attachment_impl->attached_iface);
2121 ddraw_surface4_Release(&attachment_impl->IDirectDrawSurface4_iface);
2122 return hr;
2125 static HRESULT WINAPI ddraw_surface1_AddAttachedSurface(IDirectDrawSurface *iface, IDirectDrawSurface *attachment)
2127 struct ddraw_surface *surface = impl_from_IDirectDrawSurface(iface);
2128 struct ddraw_surface *attachment_impl = unsafe_impl_from_IDirectDrawSurface(attachment);
2129 HRESULT hr;
2131 TRACE("iface %p, attachment %p.\n", iface, attachment);
2133 if (FAILED(hr = ddraw_surface4_AddAttachedSurface(&surface->IDirectDrawSurface4_iface,
2134 attachment_impl ? &attachment_impl->IDirectDrawSurface4_iface : NULL)))
2135 return hr;
2137 attachment_impl->attached_iface = (IUnknown *)attachment;
2138 IUnknown_AddRef(attachment_impl->attached_iface);
2139 ddraw_surface4_Release(&attachment_impl->IDirectDrawSurface4_iface);
2140 return hr;
2143 /*****************************************************************************
2144 * IDirectDrawSurface7::DeleteAttachedSurface
2146 * Removes a surface from the attachment chain. The surface's refcount
2147 * is decreased by one after it has been removed
2149 * Params:
2150 * Flags: Some flags, not used by this implementation
2151 * Attach: Surface to detach
2153 * Returns:
2154 * DD_OK on success
2155 * DDERR_SURFACENOTATTACHED if the surface isn't attached to
2157 *****************************************************************************/
2158 static HRESULT ddraw_surface_delete_attached_surface(struct ddraw_surface *surface,
2159 struct ddraw_surface *attachment, IUnknown *detach_iface)
2161 struct wined3d_rendertarget_view *dsv;
2162 struct ddraw_surface *prev = surface;
2164 TRACE("surface %p, attachment %p, detach_iface %p.\n", surface, attachment, detach_iface);
2166 wined3d_mutex_lock();
2167 if (!attachment || (attachment->first_attached != surface) || (attachment == surface) )
2169 wined3d_mutex_unlock();
2170 return DDERR_CANNOTDETACHSURFACE;
2173 if (attachment->attached_iface != detach_iface)
2175 WARN("attachment->attach_iface %p != detach_iface %p.\n", attachment->attached_iface, detach_iface);
2176 wined3d_mutex_unlock();
2177 return DDERR_SURFACENOTATTACHED;
2180 /* Remove MIPMAPSUBLEVEL if this seemed to be one */
2181 if (surface->surface_desc.ddsCaps.dwCaps & attachment->surface_desc.ddsCaps.dwCaps & DDSCAPS_MIPMAP)
2183 attachment->surface_desc.ddsCaps.dwCaps2 &= ~DDSCAPS2_MIPMAPSUBLEVEL;
2184 /* FIXME: we should probably also subtract from dwMipMapCount of this
2185 * and all parent surfaces */
2188 /* Find the predecessor of the detached surface */
2189 while (prev->next_attached != attachment)
2191 if (!(prev = prev->next_attached))
2193 ERR("Failed to find predecessor of %p.\n", attachment);
2194 wined3d_mutex_unlock();
2195 return DDERR_SURFACENOTATTACHED;
2199 /* Unchain the surface */
2200 prev->next_attached = attachment->next_attached;
2201 attachment->next_attached = NULL;
2202 attachment->first_attached = attachment;
2204 /* Check if the wined3d depth stencil needs updating. Note that we don't
2205 * just call d3d_device_update_depth_stencil() here since it uses
2206 * QueryInterface(). Some applications, SCP - Containment Breach in
2207 * particular, modify the QueryInterface() pointer in the surface vtbl
2208 * but don't cleanup properly after the relevant dll is unloaded. */
2209 dsv = wined3d_device_context_get_depth_stencil_view(surface->ddraw->immediate_context);
2210 if (attachment->surface_desc.ddsCaps.dwCaps & DDSCAPS_ZBUFFER && dsv == attachment->wined3d_rtv)
2211 wined3d_device_context_set_depth_stencil_view(surface->ddraw->immediate_context, NULL);
2212 wined3d_mutex_unlock();
2214 /* Set attached_iface to NULL before releasing it, the surface may go
2215 * away. */
2216 attachment->attached_iface = NULL;
2217 IUnknown_Release(detach_iface);
2219 return DD_OK;
2222 static HRESULT WINAPI ddraw_surface7_DeleteAttachedSurface(IDirectDrawSurface7 *iface,
2223 DWORD flags, IDirectDrawSurface7 *attachment)
2225 struct ddraw_surface *surface = impl_from_IDirectDrawSurface7(iface);
2226 struct ddraw_surface *attachment_impl = unsafe_impl_from_IDirectDrawSurface7(attachment);
2228 TRACE("iface %p, flags %#lx, attachment %p.\n", iface, flags, attachment);
2230 return ddraw_surface_delete_attached_surface(surface, attachment_impl, (IUnknown *)attachment);
2233 static HRESULT WINAPI ddraw_surface4_DeleteAttachedSurface(IDirectDrawSurface4 *iface,
2234 DWORD flags, IDirectDrawSurface4 *attachment)
2236 struct ddraw_surface *surface = impl_from_IDirectDrawSurface4(iface);
2237 struct ddraw_surface *attachment_impl = unsafe_impl_from_IDirectDrawSurface4(attachment);
2239 TRACE("iface %p, flags %#lx, attachment %p.\n", iface, flags, attachment);
2241 return ddraw_surface_delete_attached_surface(surface, attachment_impl, (IUnknown *)attachment);
2244 static HRESULT WINAPI ddraw_surface3_DeleteAttachedSurface(IDirectDrawSurface3 *iface,
2245 DWORD flags, IDirectDrawSurface3 *attachment)
2247 struct ddraw_surface *surface = impl_from_IDirectDrawSurface3(iface);
2248 struct ddraw_surface *attachment_impl = unsafe_impl_from_IDirectDrawSurface3(attachment);
2250 TRACE("iface %p, flags %#lx, attachment %p.\n", iface, flags, attachment);
2252 return ddraw_surface_delete_attached_surface(surface, attachment_impl, (IUnknown *)attachment);
2255 static HRESULT WINAPI ddraw_surface2_DeleteAttachedSurface(IDirectDrawSurface2 *iface,
2256 DWORD flags, IDirectDrawSurface2 *attachment)
2258 struct ddraw_surface *surface = impl_from_IDirectDrawSurface2(iface);
2259 struct ddraw_surface *attachment_impl = unsafe_impl_from_IDirectDrawSurface2(attachment);
2261 TRACE("iface %p, flags %#lx, attachment %p.\n", iface, flags, attachment);
2263 return ddraw_surface_delete_attached_surface(surface, attachment_impl, (IUnknown *)attachment);
2266 static HRESULT WINAPI ddraw_surface1_DeleteAttachedSurface(IDirectDrawSurface *iface,
2267 DWORD flags, IDirectDrawSurface *attachment)
2269 struct ddraw_surface *surface = impl_from_IDirectDrawSurface(iface);
2270 struct ddraw_surface *attachment_impl = unsafe_impl_from_IDirectDrawSurface(attachment);
2272 TRACE("iface %p, flags %#lx, attachment %p.\n", iface, flags, attachment);
2274 return ddraw_surface_delete_attached_surface(surface, attachment_impl, (IUnknown *)attachment);
2277 /*****************************************************************************
2278 * IDirectDrawSurface7::AddOverlayDirtyRect
2280 * "This method is not currently implemented"
2282 * Params:
2283 * Rect: ?
2285 * Returns:
2286 * DDERR_UNSUPPORTED
2288 *****************************************************************************/
2289 static HRESULT WINAPI ddraw_surface7_AddOverlayDirtyRect(IDirectDrawSurface7 *iface, RECT *Rect)
2291 TRACE("iface %p, rect %s.\n", iface, wine_dbgstr_rect(Rect));
2293 return DDERR_UNSUPPORTED; /* unchecked */
2296 static HRESULT WINAPI ddraw_surface4_AddOverlayDirtyRect(IDirectDrawSurface4 *iface, RECT *rect)
2298 struct ddraw_surface *surface = impl_from_IDirectDrawSurface4(iface);
2300 TRACE("iface %p, rect %s.\n", iface, wine_dbgstr_rect(rect));
2302 return ddraw_surface7_AddOverlayDirtyRect(&surface->IDirectDrawSurface7_iface, rect);
2305 static HRESULT WINAPI ddraw_surface3_AddOverlayDirtyRect(IDirectDrawSurface3 *iface, RECT *rect)
2307 struct ddraw_surface *surface = impl_from_IDirectDrawSurface3(iface);
2309 TRACE("iface %p, rect %s.\n", iface, wine_dbgstr_rect(rect));
2311 return ddraw_surface7_AddOverlayDirtyRect(&surface->IDirectDrawSurface7_iface, rect);
2314 static HRESULT WINAPI ddraw_surface2_AddOverlayDirtyRect(IDirectDrawSurface2 *iface, RECT *rect)
2316 struct ddraw_surface *surface = impl_from_IDirectDrawSurface2(iface);
2318 TRACE("iface %p, rect %s.\n", iface, wine_dbgstr_rect(rect));
2320 return ddraw_surface7_AddOverlayDirtyRect(&surface->IDirectDrawSurface7_iface, rect);
2323 static HRESULT WINAPI ddraw_surface1_AddOverlayDirtyRect(IDirectDrawSurface *iface, RECT *rect)
2325 struct ddraw_surface *surface = impl_from_IDirectDrawSurface(iface);
2327 TRACE("iface %p, rect %s.\n", iface, wine_dbgstr_rect(rect));
2329 return ddraw_surface7_AddOverlayDirtyRect(&surface->IDirectDrawSurface7_iface, rect);
2332 /*****************************************************************************
2333 * IDirectDrawSurface7::GetDC
2335 * Returns a GDI device context for the surface
2337 * Params:
2338 * hdc: Address of a HDC variable to store the dc to
2340 * Returns:
2341 * DD_OK on success
2342 * DDERR_INVALIDPARAMS if hdc is NULL
2344 *****************************************************************************/
2345 static HRESULT WINAPI ddraw_surface7_GetDC(IDirectDrawSurface7 *iface, HDC *dc)
2347 struct ddraw_surface *surface = impl_from_IDirectDrawSurface7(iface);
2348 HRESULT hr = DD_OK;
2350 TRACE("iface %p, dc %p.\n", iface, dc);
2352 if (!dc)
2353 return DDERR_INVALIDPARAMS;
2355 wined3d_mutex_lock();
2356 if (surface->dc)
2357 hr = DDERR_DCALREADYCREATED;
2358 else if (surface->surface_desc.ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE)
2359 hr = ddraw_surface_update_frontbuffer(surface, NULL, TRUE, 0);
2360 if (SUCCEEDED(hr))
2361 hr = wined3d_texture_get_dc(ddraw_surface_get_default_texture(surface, DDRAW_SURFACE_RW), surface->sub_resource_idx, dc);
2363 if (SUCCEEDED(hr))
2365 surface->dc = *dc;
2367 if (format_is_paletteindexed(&surface->surface_desc.u4.ddpfPixelFormat))
2369 const struct ddraw_palette *palette;
2371 if (surface->palette)
2372 palette = surface->palette;
2373 else if (surface->ddraw->primary)
2374 palette = surface->ddraw->primary->palette;
2375 else
2376 palette = NULL;
2378 if (palette)
2379 wined3d_palette_apply_to_dc(palette->wined3d_palette, *dc);
2383 wined3d_mutex_unlock();
2384 switch (hr)
2386 /* Some, but not all errors set *dc to NULL. E.g. DCALREADYCREATED
2387 * does not touch *dc. */
2388 case WINED3DERR_INVALIDCALL:
2389 *dc = NULL;
2390 return DDERR_CANTCREATEDC;
2392 default:
2393 return hr;
2397 static HRESULT WINAPI ddraw_surface4_GetDC(IDirectDrawSurface4 *iface, HDC *dc)
2399 struct ddraw_surface *surface = impl_from_IDirectDrawSurface4(iface);
2401 TRACE("iface %p, dc %p.\n", iface, dc);
2403 return ddraw_surface7_GetDC(&surface->IDirectDrawSurface7_iface, dc);
2406 static HRESULT WINAPI ddraw_surface3_GetDC(IDirectDrawSurface3 *iface, HDC *dc)
2408 struct ddraw_surface *surface = impl_from_IDirectDrawSurface3(iface);
2410 TRACE("iface %p, dc %p.\n", iface, dc);
2412 return ddraw_surface7_GetDC(&surface->IDirectDrawSurface7_iface, dc);
2415 static HRESULT WINAPI ddraw_surface2_GetDC(IDirectDrawSurface2 *iface, HDC *dc)
2417 struct ddraw_surface *surface = impl_from_IDirectDrawSurface2(iface);
2419 TRACE("iface %p, dc %p.\n", iface, dc);
2421 return ddraw_surface7_GetDC(&surface->IDirectDrawSurface7_iface, dc);
2424 static HRESULT WINAPI ddraw_surface1_GetDC(IDirectDrawSurface *iface, HDC *dc)
2426 struct ddraw_surface *surface = impl_from_IDirectDrawSurface(iface);
2428 TRACE("iface %p, dc %p.\n", iface, dc);
2430 return ddraw_surface7_GetDC(&surface->IDirectDrawSurface7_iface, dc);
2433 /*****************************************************************************
2434 * IDirectDrawSurface7::ReleaseDC
2436 * Releases the DC that was constructed with GetDC
2438 * Params:
2439 * hdc: HDC to release
2441 * Returns:
2442 * DD_OK on success, error code otherwise.
2444 *****************************************************************************/
2445 static HRESULT WINAPI ddraw_surface7_ReleaseDC(IDirectDrawSurface7 *iface, HDC hdc)
2447 struct ddraw_surface *surface = impl_from_IDirectDrawSurface7(iface);
2448 HRESULT hr;
2450 TRACE("iface %p, dc %p.\n", iface, hdc);
2452 wined3d_mutex_lock();
2453 if (!surface->dc)
2455 hr = DDERR_NODC;
2457 else if (SUCCEEDED(hr = wined3d_texture_release_dc(ddraw_surface_get_default_texture(surface, 0),
2458 surface->sub_resource_idx, hdc)))
2460 surface->dc = NULL;
2461 if (surface->surface_desc.ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE)
2462 hr = ddraw_surface_update_frontbuffer(surface, NULL, FALSE, 0);
2464 wined3d_mutex_unlock();
2467 return hr;
2470 static HRESULT WINAPI ddraw_surface4_ReleaseDC(IDirectDrawSurface4 *iface, HDC dc)
2472 struct ddraw_surface *surface = impl_from_IDirectDrawSurface4(iface);
2474 TRACE("iface %p, dc %p.\n", iface, dc);
2476 return ddraw_surface7_ReleaseDC(&surface->IDirectDrawSurface7_iface, dc);
2479 static HRESULT WINAPI ddraw_surface3_ReleaseDC(IDirectDrawSurface3 *iface, HDC dc)
2481 struct ddraw_surface *surface = impl_from_IDirectDrawSurface3(iface);
2483 TRACE("iface %p, dc %p.\n", iface, dc);
2485 return ddraw_surface7_ReleaseDC(&surface->IDirectDrawSurface7_iface, dc);
2488 static HRESULT WINAPI ddraw_surface2_ReleaseDC(IDirectDrawSurface2 *iface, HDC dc)
2490 struct ddraw_surface *surface = impl_from_IDirectDrawSurface2(iface);
2492 TRACE("iface %p, dc %p.\n", iface, dc);
2494 return ddraw_surface7_ReleaseDC(&surface->IDirectDrawSurface7_iface, dc);
2497 static HRESULT WINAPI ddraw_surface1_ReleaseDC(IDirectDrawSurface *iface, HDC dc)
2499 struct ddraw_surface *surface = impl_from_IDirectDrawSurface(iface);
2501 TRACE("iface %p, dc %p.\n", iface, dc);
2503 return ddraw_surface7_ReleaseDC(&surface->IDirectDrawSurface7_iface, dc);
2506 /*****************************************************************************
2507 * IDirectDrawSurface7::GetCaps
2509 * Returns the surface's caps
2511 * Params:
2512 * Caps: Address to write the caps to
2514 * Returns:
2515 * DD_OK on success
2516 * DDERR_INVALIDPARAMS if Caps is NULL
2518 *****************************************************************************/
2519 static HRESULT WINAPI ddraw_surface7_GetCaps(IDirectDrawSurface7 *iface, DDSCAPS2 *Caps)
2521 struct ddraw_surface *surface = impl_from_IDirectDrawSurface7(iface);
2523 TRACE("iface %p, caps %p.\n", iface, Caps);
2525 if(!Caps)
2526 return DDERR_INVALIDPARAMS;
2528 *Caps = surface->surface_desc.ddsCaps;
2530 return DD_OK;
2533 static HRESULT WINAPI ddraw_surface4_GetCaps(IDirectDrawSurface4 *iface, DDSCAPS2 *caps)
2535 struct ddraw_surface *surface = impl_from_IDirectDrawSurface4(iface);
2537 TRACE("iface %p, caps %p.\n", iface, caps);
2539 return ddraw_surface7_GetCaps(&surface->IDirectDrawSurface7_iface, caps);
2542 static HRESULT WINAPI ddraw_surface3_GetCaps(IDirectDrawSurface3 *iface, DDSCAPS *caps)
2544 struct ddraw_surface *surface = impl_from_IDirectDrawSurface3(iface);
2545 DDSCAPS2 caps2;
2546 HRESULT hr;
2548 TRACE("iface %p, caps %p.\n", iface, caps);
2550 hr = ddraw_surface7_GetCaps(&surface->IDirectDrawSurface7_iface, &caps2);
2551 if (FAILED(hr)) return hr;
2553 caps->dwCaps = caps2.dwCaps;
2554 return hr;
2557 static HRESULT WINAPI ddraw_surface2_GetCaps(IDirectDrawSurface2 *iface, DDSCAPS *caps)
2559 struct ddraw_surface *surface = impl_from_IDirectDrawSurface2(iface);
2560 DDSCAPS2 caps2;
2561 HRESULT hr;
2563 TRACE("iface %p, caps %p.\n", iface, caps);
2565 hr = ddraw_surface7_GetCaps(&surface->IDirectDrawSurface7_iface, &caps2);
2566 if (FAILED(hr)) return hr;
2568 caps->dwCaps = caps2.dwCaps;
2569 return hr;
2572 static HRESULT WINAPI ddraw_surface1_GetCaps(IDirectDrawSurface *iface, DDSCAPS *caps)
2574 struct ddraw_surface *surface = impl_from_IDirectDrawSurface(iface);
2575 DDSCAPS2 caps2;
2576 HRESULT hr;
2578 TRACE("iface %p, caps %p.\n", iface, caps);
2580 hr = ddraw_surface7_GetCaps(&surface->IDirectDrawSurface7_iface, &caps2);
2581 if (FAILED(hr)) return hr;
2583 caps->dwCaps = caps2.dwCaps;
2584 return hr;
2587 static HRESULT WINAPI ddraw_surface7_SetPriority(IDirectDrawSurface7 *iface, DWORD priority)
2589 struct ddraw_surface *surface = impl_from_IDirectDrawSurface7(iface);
2590 DWORD managed = DDSCAPS2_TEXTUREMANAGE | DDSCAPS2_D3DTEXTUREMANAGE;
2591 HRESULT hr;
2592 struct wined3d_resource *resource;
2594 TRACE("iface %p, priority %lu.\n", iface, priority);
2596 wined3d_mutex_lock();
2597 /* No need to check for offscreen plain surfaces or mipmap sublevels. SetPriority
2598 * calls on such surfaces segfault on Windows. */
2599 if (!(surface->surface_desc.ddsCaps.dwCaps2 & managed))
2601 WARN("Called on non-managed texture returning DDERR_INVALIDPARAMS.\n");
2602 hr = DDERR_INVALIDPARAMS;
2604 else
2606 resource = wined3d_texture_get_resource(surface->wined3d_texture);
2607 wined3d_resource_set_priority(resource, priority);
2608 if (surface->draw_texture)
2609 wined3d_resource_set_priority(wined3d_texture_get_resource(surface->draw_texture), priority);
2611 hr = DD_OK;
2613 wined3d_mutex_unlock();
2615 return hr;
2618 static HRESULT WINAPI ddraw_surface7_GetPriority(IDirectDrawSurface7 *iface, DWORD *priority)
2620 struct ddraw_surface *surface = impl_from_IDirectDrawSurface7(iface);
2621 const struct wined3d_resource *resource;
2622 DWORD managed = DDSCAPS2_TEXTUREMANAGE | DDSCAPS2_D3DTEXTUREMANAGE;
2623 HRESULT hr;
2625 TRACE("iface %p, priority %p.\n", iface, priority);
2627 wined3d_mutex_lock();
2628 if (surface->surface_desc.ddsCaps.dwCaps & DDSCAPS_OFFSCREENPLAIN)
2630 WARN("Called on offscreenplain surface, returning DDERR_INVALIDOBJECT.\n");
2631 hr = DDERR_INVALIDOBJECT;
2633 else if (!(surface->surface_desc.ddsCaps.dwCaps2 & managed) || !surface->is_root)
2635 WARN("Called on non-managed texture or non-root surface, returning DDERR_INVALIDPARAMS.\n");
2636 hr = DDERR_INVALIDPARAMS;
2638 else
2640 resource = wined3d_texture_get_resource(surface->wined3d_texture);
2641 *priority = wined3d_resource_get_priority(resource);
2642 hr = DD_OK;
2644 wined3d_mutex_unlock();
2646 return hr;
2649 /*****************************************************************************
2650 * IDirectDrawSurface7::SetPrivateData
2652 * Stores some data in the surface that is intended for the application's
2653 * use.
2655 * Params:
2656 * tag: GUID that identifies the data
2657 * Data: Pointer to the private data
2658 * Size: Size of the private data
2659 * Flags: Some flags
2661 * Returns:
2662 * D3D_OK on success, error code otherwise.
2664 *****************************************************************************/
2665 static HRESULT WINAPI ddraw_surface7_SetPrivateData(IDirectDrawSurface7 *iface,
2666 REFGUID tag, void *data, DWORD size, DWORD flags)
2668 struct ddraw_surface *surface = impl_from_IDirectDrawSurface7(iface);
2669 HRESULT hr;
2671 TRACE("iface %p, tag %s, data %p, data_size %lu, flags %#lx.\n",
2672 iface, debugstr_guid(tag), data, size, flags);
2674 if (!data)
2676 WARN("data is NULL, returning DDERR_INVALIDPARAMS.\n");
2677 return DDERR_INVALIDPARAMS;
2680 wined3d_mutex_lock();
2681 hr = wined3d_private_store_set_private_data(&surface->private_store, tag, data, size, flags);
2682 wined3d_mutex_unlock();
2683 return hr_ddraw_from_wined3d(hr);
2686 static HRESULT WINAPI ddraw_surface4_SetPrivateData(IDirectDrawSurface4 *iface,
2687 REFGUID tag, void *data, DWORD size, DWORD flags)
2689 struct ddraw_surface *surface = impl_from_IDirectDrawSurface4(iface);
2691 TRACE("iface %p, tag %s, data %p, data_size %lu, flags %#lx.\n",
2692 iface, debugstr_guid(tag), data, size, flags);
2694 return ddraw_surface7_SetPrivateData(&surface->IDirectDrawSurface7_iface, tag, data, size, flags);
2697 /*****************************************************************************
2698 * IDirectDrawSurface7::GetPrivateData
2700 * Returns the private data set with IDirectDrawSurface7::SetPrivateData
2702 * Params:
2703 * tag: GUID of the data to return
2704 * Data: Address where to write the data to
2705 * Size: Size of the buffer at Data
2707 * Returns:
2708 * DD_OK on success
2709 * DDERR_INVALIDPARAMS if Data is NULL
2711 *****************************************************************************/
2712 static HRESULT WINAPI ddraw_surface7_GetPrivateData(IDirectDrawSurface7 *iface, REFGUID tag, void *data, DWORD *size)
2714 struct ddraw_surface *surface = impl_from_IDirectDrawSurface7(iface);
2715 const struct wined3d_private_data *stored_data;
2716 HRESULT hr;
2718 TRACE("iface %p, tag %s, data %p, data_size %p.\n",
2719 iface, debugstr_guid(tag), data, size);
2721 wined3d_mutex_lock();
2722 stored_data = wined3d_private_store_get_private_data(&surface->private_store, tag);
2723 if (!stored_data)
2725 hr = DDERR_NOTFOUND;
2726 goto done;
2728 if (!size)
2730 hr = DDERR_INVALIDPARAMS;
2731 goto done;
2733 if (*size < stored_data->size)
2735 *size = stored_data->size;
2736 hr = DDERR_MOREDATA;
2737 goto done;
2739 if (!data)
2741 hr = DDERR_INVALIDPARAMS;
2742 goto done;
2745 *size = stored_data->size;
2746 memcpy(data, stored_data->content.data, stored_data->size);
2747 hr = DD_OK;
2749 done:
2750 wined3d_mutex_unlock();
2751 return hr;
2754 static HRESULT WINAPI ddraw_surface4_GetPrivateData(IDirectDrawSurface4 *iface, REFGUID tag, void *data, DWORD *size)
2756 struct ddraw_surface *surface = impl_from_IDirectDrawSurface4(iface);
2758 TRACE("iface %p, tag %s, data %p, data_size %p.\n",
2759 iface, debugstr_guid(tag), data, size);
2761 return ddraw_surface7_GetPrivateData(&surface->IDirectDrawSurface7_iface, tag, data, size);
2764 /*****************************************************************************
2765 * IDirectDrawSurface7::FreePrivateData
2767 * Frees private data stored in the surface
2769 * Params:
2770 * tag: Tag of the data to free
2772 * Returns:
2773 * D3D_OK on success, error code otherwise.
2775 *****************************************************************************/
2776 static HRESULT WINAPI ddraw_surface7_FreePrivateData(IDirectDrawSurface7 *iface, REFGUID tag)
2778 struct ddraw_surface *surface = impl_from_IDirectDrawSurface7(iface);
2779 struct wined3d_private_data *entry;
2781 TRACE("iface %p, tag %s.\n", iface, debugstr_guid(tag));
2783 wined3d_mutex_lock();
2784 entry = wined3d_private_store_get_private_data(&surface->private_store, tag);
2785 if (!entry)
2787 wined3d_mutex_unlock();
2788 return DDERR_NOTFOUND;
2791 wined3d_private_store_free_private_data(&surface->private_store, entry);
2792 wined3d_mutex_unlock();
2794 return DD_OK;
2797 static HRESULT WINAPI ddraw_surface4_FreePrivateData(IDirectDrawSurface4 *iface, REFGUID tag)
2799 struct ddraw_surface *surface = impl_from_IDirectDrawSurface4(iface);
2801 TRACE("iface %p, tag %s.\n", iface, debugstr_guid(tag));
2803 return ddraw_surface7_FreePrivateData(&surface->IDirectDrawSurface7_iface, tag);
2806 /*****************************************************************************
2807 * IDirectDrawSurface7::PageLock
2809 * Prevents a sysmem surface from being paged out
2811 * Params:
2812 * Flags: Not used, must be 0(unchecked)
2814 * Returns:
2815 * DD_OK, because it's a stub
2817 *****************************************************************************/
2818 static HRESULT WINAPI ddraw_surface7_PageLock(IDirectDrawSurface7 *iface, DWORD Flags)
2820 TRACE("iface %p, flags %#lx.\n", iface, Flags);
2822 /* This is Windows memory management related - we don't need this */
2823 return DD_OK;
2826 static HRESULT WINAPI ddraw_surface4_PageLock(IDirectDrawSurface4 *iface, DWORD flags)
2828 struct ddraw_surface *surface = impl_from_IDirectDrawSurface4(iface);
2830 TRACE("iface %p, flags %#lx.\n", iface, flags);
2832 return ddraw_surface7_PageLock(&surface->IDirectDrawSurface7_iface, flags);
2835 static HRESULT WINAPI ddraw_surface3_PageLock(IDirectDrawSurface3 *iface, DWORD flags)
2837 struct ddraw_surface *surface = impl_from_IDirectDrawSurface3(iface);
2839 TRACE("iface %p, flags %#lx.\n", iface, flags);
2841 return ddraw_surface7_PageLock(&surface->IDirectDrawSurface7_iface, flags);
2844 static HRESULT WINAPI ddraw_surface2_PageLock(IDirectDrawSurface2 *iface, DWORD flags)
2846 struct ddraw_surface *surface = impl_from_IDirectDrawSurface2(iface);
2848 TRACE("iface %p, flags %#lx.\n", iface, flags);
2850 return ddraw_surface7_PageLock(&surface->IDirectDrawSurface7_iface, flags);
2853 /*****************************************************************************
2854 * IDirectDrawSurface7::PageUnlock
2856 * Allows a sysmem surface to be paged out
2858 * Params:
2859 * Flags: Not used, must be 0(unchecked)
2861 * Returns:
2862 * DD_OK, because it's a stub
2864 *****************************************************************************/
2865 static HRESULT WINAPI ddraw_surface7_PageUnlock(IDirectDrawSurface7 *iface, DWORD Flags)
2867 TRACE("iface %p, flags %#lx.\n", iface, Flags);
2869 return DD_OK;
2872 static HRESULT WINAPI ddraw_surface4_PageUnlock(IDirectDrawSurface4 *iface, DWORD flags)
2874 struct ddraw_surface *surface = impl_from_IDirectDrawSurface4(iface);
2876 TRACE("iface %p, flags %#lx.\n", iface, flags);
2878 return ddraw_surface7_PageUnlock(&surface->IDirectDrawSurface7_iface, flags);
2881 static HRESULT WINAPI ddraw_surface3_PageUnlock(IDirectDrawSurface3 *iface, DWORD flags)
2883 struct ddraw_surface *surface = impl_from_IDirectDrawSurface3(iface);
2885 TRACE("iface %p, flags %#lx.\n", iface, flags);
2887 return ddraw_surface7_PageUnlock(&surface->IDirectDrawSurface7_iface, flags);
2890 static HRESULT WINAPI ddraw_surface2_PageUnlock(IDirectDrawSurface2 *iface, DWORD flags)
2892 struct ddraw_surface *surface = impl_from_IDirectDrawSurface2(iface);
2894 TRACE("iface %p, flags %#lx.\n", iface, flags);
2896 return ddraw_surface7_PageUnlock(&surface->IDirectDrawSurface7_iface, flags);
2899 /*****************************************************************************
2900 * IDirectDrawSurface7::BltBatch
2902 * An unimplemented function
2904 * Params:
2907 * Returns:
2908 * DDERR_UNSUPPORTED
2910 *****************************************************************************/
2911 static HRESULT WINAPI DECLSPEC_HOTPATCH ddraw_surface7_BltBatch(IDirectDrawSurface7 *iface, DDBLTBATCH *Batch, DWORD Count, DWORD Flags)
2913 TRACE("iface %p, batch %p, count %lu, flags %#lx.\n", iface, Batch, Count, Flags);
2915 /* MSDN: "not currently implemented" */
2916 return DDERR_UNSUPPORTED;
2919 static HRESULT WINAPI DECLSPEC_HOTPATCH ddraw_surface4_BltBatch(IDirectDrawSurface4 *iface, DDBLTBATCH *batch, DWORD count, DWORD flags)
2921 struct ddraw_surface *surface = impl_from_IDirectDrawSurface4(iface);
2923 TRACE("iface %p, batch %p, count %lu, flags %#lx.\n", iface, batch, count, flags);
2925 return ddraw_surface7_BltBatch(&surface->IDirectDrawSurface7_iface, batch, count, flags);
2928 static HRESULT WINAPI DECLSPEC_HOTPATCH ddraw_surface3_BltBatch(IDirectDrawSurface3 *iface, DDBLTBATCH *batch, DWORD count, DWORD flags)
2930 struct ddraw_surface *surface = impl_from_IDirectDrawSurface3(iface);
2932 TRACE("iface %p, batch %p, count %lu, flags %#lx.\n", iface, batch, count, flags);
2934 return ddraw_surface7_BltBatch(&surface->IDirectDrawSurface7_iface, batch, count, flags);
2937 static HRESULT WINAPI DECLSPEC_HOTPATCH ddraw_surface2_BltBatch(IDirectDrawSurface2 *iface, DDBLTBATCH *batch, DWORD count, DWORD flags)
2939 struct ddraw_surface *surface = impl_from_IDirectDrawSurface2(iface);
2941 TRACE("iface %p, batch %p, count %lu, flags %#lx.\n", iface, batch, count, flags);
2943 return ddraw_surface7_BltBatch(&surface->IDirectDrawSurface7_iface, batch, count, flags);
2946 static HRESULT WINAPI DECLSPEC_HOTPATCH ddraw_surface1_BltBatch(IDirectDrawSurface *iface, DDBLTBATCH *batch, DWORD count, DWORD flags)
2948 struct ddraw_surface *surface = impl_from_IDirectDrawSurface(iface);
2950 TRACE("iface %p, batch %p, count %lu, flags %#lx.\n", iface, batch, count, flags);
2952 return ddraw_surface7_BltBatch(&surface->IDirectDrawSurface7_iface, batch, count, flags);
2955 /*****************************************************************************
2956 * IDirectDrawSurface7::EnumAttachedSurfaces
2958 * Enumerates all surfaces attached to this surface
2960 * Params:
2961 * context: Pointer to pass unmodified to the callback
2962 * cb: Callback function to call for each surface
2964 * Returns:
2965 * DD_OK on success
2966 * DDERR_INVALIDPARAMS if cb is NULL
2968 *****************************************************************************/
2969 static HRESULT WINAPI ddraw_surface7_EnumAttachedSurfaces(IDirectDrawSurface7 *iface,
2970 void *context, LPDDENUMSURFACESCALLBACK7 cb)
2972 struct ddraw_surface *surface = impl_from_IDirectDrawSurface7(iface);
2973 struct ddraw_surface *surf;
2974 DDSURFACEDESC2 desc;
2975 int i;
2977 /* Attached surfaces aren't handled in WineD3D */
2978 TRACE("iface %p, context %p, callback %p.\n", iface, context, cb);
2980 if(!cb)
2981 return DDERR_INVALIDPARAMS;
2983 wined3d_mutex_lock();
2985 for(i = 0; i < MAX_COMPLEX_ATTACHED; i++)
2987 surf = surface->complex_array[i];
2988 if(!surf) break;
2990 ddraw_surface7_AddRef(&surf->IDirectDrawSurface7_iface);
2991 desc = surf->surface_desc;
2992 /* check: != DDENUMRET_OK or == DDENUMRET_CANCEL? */
2993 if (cb(&surf->IDirectDrawSurface7_iface, &desc, context) == DDENUMRET_CANCEL)
2995 wined3d_mutex_unlock();
2996 return DD_OK;
3000 for (surf = surface->next_attached; surf != NULL; surf = surf->next_attached)
3002 ddraw_surface7_AddRef(&surf->IDirectDrawSurface7_iface);
3003 desc = surf->surface_desc;
3004 /* check: != DDENUMRET_OK or == DDENUMRET_CANCEL? */
3005 if (cb(&surf->IDirectDrawSurface7_iface, &desc, context) == DDENUMRET_CANCEL)
3007 wined3d_mutex_unlock();
3008 return DD_OK;
3012 TRACE(" end of enumeration.\n");
3014 wined3d_mutex_unlock();
3016 return DD_OK;
3019 struct callback_info2
3021 LPDDENUMSURFACESCALLBACK2 callback;
3022 void *context;
3025 struct callback_info
3027 LPDDENUMSURFACESCALLBACK callback;
3028 void *context;
3031 static HRESULT CALLBACK EnumCallback2(IDirectDrawSurface7 *surface, DDSURFACEDESC2 *surface_desc, void *context)
3033 struct ddraw_surface *surface_impl = impl_from_IDirectDrawSurface7(surface);
3034 const struct callback_info2 *info = context;
3036 ddraw_surface4_AddRef(&surface_impl->IDirectDrawSurface4_iface);
3037 ddraw_surface7_Release(surface);
3039 return info->callback(&surface_impl->IDirectDrawSurface4_iface, surface_desc, info->context);
3042 static HRESULT CALLBACK EnumCallback(IDirectDrawSurface7 *surface, DDSURFACEDESC2 *surface_desc, void *context)
3044 struct ddraw_surface *surface_impl = impl_from_IDirectDrawSurface7(surface);
3045 const struct callback_info *info = context;
3047 ddraw_surface1_AddRef(&surface_impl->IDirectDrawSurface_iface);
3048 ddraw_surface7_Release(surface);
3050 /* FIXME: Check surface_test.dwSize */
3051 return info->callback(&surface_impl->IDirectDrawSurface_iface,
3052 (DDSURFACEDESC *)surface_desc, info->context);
3055 static HRESULT WINAPI ddraw_surface4_EnumAttachedSurfaces(IDirectDrawSurface4 *iface,
3056 void *context, LPDDENUMSURFACESCALLBACK2 callback)
3058 struct ddraw_surface *surface = impl_from_IDirectDrawSurface4(iface);
3059 struct callback_info2 info;
3061 TRACE("iface %p, context %p, callback %p.\n", iface, context, callback);
3063 info.callback = callback;
3064 info.context = context;
3066 return ddraw_surface7_EnumAttachedSurfaces(&surface->IDirectDrawSurface7_iface,
3067 &info, EnumCallback2);
3070 static HRESULT WINAPI ddraw_surface3_EnumAttachedSurfaces(IDirectDrawSurface3 *iface,
3071 void *context, LPDDENUMSURFACESCALLBACK callback)
3073 struct ddraw_surface *surface = impl_from_IDirectDrawSurface3(iface);
3074 struct callback_info info;
3076 TRACE("iface %p, context %p, callback %p.\n", iface, context, callback);
3078 info.callback = callback;
3079 info.context = context;
3081 return ddraw_surface7_EnumAttachedSurfaces(&surface->IDirectDrawSurface7_iface,
3082 &info, EnumCallback);
3085 static HRESULT WINAPI ddraw_surface2_EnumAttachedSurfaces(IDirectDrawSurface2 *iface,
3086 void *context, LPDDENUMSURFACESCALLBACK callback)
3088 struct ddraw_surface *surface = impl_from_IDirectDrawSurface2(iface);
3089 struct callback_info info;
3091 TRACE("iface %p, context %p, callback %p.\n", iface, context, callback);
3093 info.callback = callback;
3094 info.context = context;
3096 return ddraw_surface7_EnumAttachedSurfaces(&surface->IDirectDrawSurface7_iface,
3097 &info, EnumCallback);
3100 static HRESULT WINAPI ddraw_surface1_EnumAttachedSurfaces(IDirectDrawSurface *iface,
3101 void *context, LPDDENUMSURFACESCALLBACK callback)
3103 struct ddraw_surface *surface = impl_from_IDirectDrawSurface(iface);
3104 struct callback_info info;
3106 TRACE("iface %p, context %p, callback %p.\n", iface, context, callback);
3108 info.callback = callback;
3109 info.context = context;
3111 return ddraw_surface7_EnumAttachedSurfaces(&surface->IDirectDrawSurface7_iface,
3112 &info, EnumCallback);
3115 /*****************************************************************************
3116 * IDirectDrawSurface7::EnumOverlayZOrders
3118 * "Enumerates the overlay surfaces on the specified destination"
3120 * Params:
3121 * Flags: DDENUMOVERLAYZ_BACKTOFRONT or DDENUMOVERLAYZ_FRONTTOBACK
3122 * context: context to pass back to the callback
3123 * cb: callback function to call for each enumerated surface
3125 * Returns:
3126 * DD_OK, because it's a stub
3128 *****************************************************************************/
3129 static HRESULT WINAPI ddraw_surface7_EnumOverlayZOrders(IDirectDrawSurface7 *iface,
3130 DWORD Flags, void *context, LPDDENUMSURFACESCALLBACK7 cb)
3132 FIXME("iface %p, flags %#lx, context %p, callback %p stub!\n", iface, Flags, context, cb);
3134 return DD_OK;
3137 static HRESULT WINAPI ddraw_surface4_EnumOverlayZOrders(IDirectDrawSurface4 *iface,
3138 DWORD flags, void *context, LPDDENUMSURFACESCALLBACK2 callback)
3140 struct ddraw_surface *surface = impl_from_IDirectDrawSurface4(iface);
3141 struct callback_info2 info;
3143 TRACE("iface %p, flags %#lx, context %p, callback %p.\n", iface, flags, context, callback);
3145 info.callback = callback;
3146 info.context = context;
3148 return ddraw_surface7_EnumOverlayZOrders(&surface->IDirectDrawSurface7_iface,
3149 flags, &info, EnumCallback2);
3152 static HRESULT WINAPI ddraw_surface3_EnumOverlayZOrders(IDirectDrawSurface3 *iface,
3153 DWORD flags, void *context, LPDDENUMSURFACESCALLBACK callback)
3155 struct ddraw_surface *surface = impl_from_IDirectDrawSurface3(iface);
3156 struct callback_info info;
3158 TRACE("iface %p, flags %#lx, context %p, callback %p.\n", iface, flags, context, callback);
3160 info.callback = callback;
3161 info.context = context;
3163 return ddraw_surface7_EnumOverlayZOrders(&surface->IDirectDrawSurface7_iface,
3164 flags, &info, EnumCallback);
3167 static HRESULT WINAPI ddraw_surface2_EnumOverlayZOrders(IDirectDrawSurface2 *iface,
3168 DWORD flags, void *context, LPDDENUMSURFACESCALLBACK callback)
3170 struct ddraw_surface *surface = impl_from_IDirectDrawSurface2(iface);
3171 struct callback_info info;
3173 TRACE("iface %p, flags %#lx, context %p, callback %p.\n", iface, flags, context, callback);
3175 info.callback = callback;
3176 info.context = context;
3178 return ddraw_surface7_EnumOverlayZOrders(&surface->IDirectDrawSurface7_iface,
3179 flags, &info, EnumCallback);
3182 static HRESULT WINAPI ddraw_surface1_EnumOverlayZOrders(IDirectDrawSurface *iface,
3183 DWORD flags, void *context, LPDDENUMSURFACESCALLBACK callback)
3185 struct ddraw_surface *surface = impl_from_IDirectDrawSurface(iface);
3186 struct callback_info info;
3188 TRACE("iface %p, flags %#lx, context %p, callback %p.\n", iface, flags, context, callback);
3190 info.callback = callback;
3191 info.context = context;
3193 return ddraw_surface7_EnumOverlayZOrders(&surface->IDirectDrawSurface7_iface,
3194 flags, &info, EnumCallback);
3197 /*****************************************************************************
3198 * IDirectDrawSurface7::GetBltStatus
3200 * Returns the blitting status
3202 * Params:
3203 * Flags: DDGBS_CANBLT or DDGBS_ISBLTDONE
3205 *****************************************************************************/
3206 static HRESULT WINAPI ddraw_surface7_GetBltStatus(IDirectDrawSurface7 *iface, DWORD Flags)
3208 TRACE("iface %p, flags %#lx.\n", iface, Flags);
3210 switch (Flags)
3212 case WINEDDGBS_CANBLT:
3213 case WINEDDGBS_ISBLTDONE:
3214 return DD_OK;
3216 default:
3217 return DDERR_INVALIDPARAMS;
3221 static HRESULT WINAPI ddraw_surface4_GetBltStatus(IDirectDrawSurface4 *iface, DWORD flags)
3223 struct ddraw_surface *surface = impl_from_IDirectDrawSurface4(iface);
3225 TRACE("iface %p, flags %#lx.\n", iface, flags);
3227 return ddraw_surface7_GetBltStatus(&surface->IDirectDrawSurface7_iface, flags);
3230 static HRESULT WINAPI ddraw_surface3_GetBltStatus(IDirectDrawSurface3 *iface, DWORD flags)
3232 struct ddraw_surface *surface = impl_from_IDirectDrawSurface3(iface);
3234 TRACE("iface %p, flags %#lx.\n", iface, flags);
3236 return ddraw_surface7_GetBltStatus(&surface->IDirectDrawSurface7_iface, flags);
3239 static HRESULT WINAPI ddraw_surface2_GetBltStatus(IDirectDrawSurface2 *iface, DWORD flags)
3241 struct ddraw_surface *surface = impl_from_IDirectDrawSurface2(iface);
3243 TRACE("iface %p, flags %#lx.\n", iface, flags);
3245 return ddraw_surface7_GetBltStatus(&surface->IDirectDrawSurface7_iface, flags);
3248 static HRESULT WINAPI ddraw_surface1_GetBltStatus(IDirectDrawSurface *iface, DWORD flags)
3250 struct ddraw_surface *surface = impl_from_IDirectDrawSurface(iface);
3252 TRACE("iface %p, flags %#lx.\n", iface, flags);
3254 return ddraw_surface7_GetBltStatus(&surface->IDirectDrawSurface7_iface, flags);
3257 /*****************************************************************************
3258 * IDirectDrawSurface7::GetColorKey
3260 * Returns the color key assigned to the surface
3262 * Params:
3263 * Flags: Some flags
3264 * CKey: Address to store the key to
3266 * Returns:
3267 * DD_OK on success
3268 * DDERR_INVALIDPARAMS if CKey is NULL
3270 *****************************************************************************/
3271 static HRESULT WINAPI ddraw_surface7_GetColorKey(IDirectDrawSurface7 *iface, DWORD Flags, DDCOLORKEY *CKey)
3273 struct ddraw_surface *This = impl_from_IDirectDrawSurface7(iface);
3275 TRACE("iface %p, flags %#lx, color_key %p.\n", iface, Flags, CKey);
3277 if(!CKey)
3278 return DDERR_INVALIDPARAMS;
3280 wined3d_mutex_lock();
3282 switch (Flags)
3284 case DDCKEY_DESTBLT:
3285 if (!(This->surface_desc.dwFlags & DDSD_CKDESTBLT))
3287 wined3d_mutex_unlock();
3288 return DDERR_NOCOLORKEY;
3290 *CKey = This->surface_desc.ddckCKDestBlt;
3291 break;
3293 case DDCKEY_DESTOVERLAY:
3294 if (!(This->surface_desc.dwFlags & DDSD_CKDESTOVERLAY))
3296 wined3d_mutex_unlock();
3297 return DDERR_NOCOLORKEY;
3299 *CKey = This->surface_desc.u3.ddckCKDestOverlay;
3300 break;
3302 case DDCKEY_SRCBLT:
3303 if (!(This->surface_desc.dwFlags & DDSD_CKSRCBLT))
3305 wined3d_mutex_unlock();
3306 return DDERR_NOCOLORKEY;
3308 *CKey = This->surface_desc.ddckCKSrcBlt;
3309 break;
3311 case DDCKEY_SRCOVERLAY:
3312 if (!(This->surface_desc.dwFlags & DDSD_CKSRCOVERLAY))
3314 wined3d_mutex_unlock();
3315 return DDERR_NOCOLORKEY;
3317 *CKey = This->surface_desc.ddckCKSrcOverlay;
3318 break;
3320 default:
3321 wined3d_mutex_unlock();
3322 return DDERR_INVALIDPARAMS;
3325 wined3d_mutex_unlock();
3327 return DD_OK;
3330 static HRESULT WINAPI ddraw_surface4_GetColorKey(IDirectDrawSurface4 *iface, DWORD flags, DDCOLORKEY *color_key)
3332 struct ddraw_surface *surface = impl_from_IDirectDrawSurface4(iface);
3334 TRACE("iface %p, flags %#lx, color_key %p.\n", iface, flags, color_key);
3336 return ddraw_surface7_GetColorKey(&surface->IDirectDrawSurface7_iface, flags, color_key);
3339 static HRESULT WINAPI ddraw_surface3_GetColorKey(IDirectDrawSurface3 *iface, DWORD flags, DDCOLORKEY *color_key)
3341 struct ddraw_surface *surface = impl_from_IDirectDrawSurface3(iface);
3343 TRACE("iface %p, flags %#lx, color_key %p.\n", iface, flags, color_key);
3345 return ddraw_surface7_GetColorKey(&surface->IDirectDrawSurface7_iface, flags, color_key);
3348 static HRESULT WINAPI ddraw_surface2_GetColorKey(IDirectDrawSurface2 *iface, DWORD flags, DDCOLORKEY *color_key)
3350 struct ddraw_surface *surface = impl_from_IDirectDrawSurface2(iface);
3352 TRACE("iface %p, flags %#lx, color_key %p.\n", iface, flags, color_key);
3354 return ddraw_surface7_GetColorKey(&surface->IDirectDrawSurface7_iface, flags, color_key);
3357 static HRESULT WINAPI ddraw_surface1_GetColorKey(IDirectDrawSurface *iface, DWORD flags, DDCOLORKEY *color_key)
3359 struct ddraw_surface *surface = impl_from_IDirectDrawSurface(iface);
3361 TRACE("iface %p, flags %#lx, color_key %p.\n", iface, flags, color_key);
3363 return ddraw_surface7_GetColorKey(&surface->IDirectDrawSurface7_iface, flags, color_key);
3366 /*****************************************************************************
3367 * IDirectDrawSurface7::GetFlipStatus
3369 * Returns the flipping status of the surface
3371 * Params:
3372 * Flags: DDGFS_CANFLIP of DDGFS_ISFLIPDONE
3374 *****************************************************************************/
3375 static HRESULT WINAPI ddraw_surface7_GetFlipStatus(IDirectDrawSurface7 *iface, DWORD Flags)
3377 TRACE("iface %p, flags %#lx.\n", iface, Flags);
3379 /* XXX: DDERR_INVALIDSURFACETYPE */
3381 switch (Flags)
3383 case WINEDDGFS_CANFLIP:
3384 case WINEDDGFS_ISFLIPDONE:
3385 return DD_OK;
3387 default:
3388 return DDERR_INVALIDPARAMS;
3392 static HRESULT WINAPI ddraw_surface4_GetFlipStatus(IDirectDrawSurface4 *iface, DWORD flags)
3394 struct ddraw_surface *surface = impl_from_IDirectDrawSurface4(iface);
3396 TRACE("iface %p, flags %#lx.\n", iface, flags);
3398 return ddraw_surface7_GetFlipStatus(&surface->IDirectDrawSurface7_iface, flags);
3401 static HRESULT WINAPI ddraw_surface3_GetFlipStatus(IDirectDrawSurface3 *iface, DWORD flags)
3403 struct ddraw_surface *surface = impl_from_IDirectDrawSurface3(iface);
3405 TRACE("iface %p, flags %#lx.\n", iface, flags);
3407 return ddraw_surface7_GetFlipStatus(&surface->IDirectDrawSurface7_iface, flags);
3410 static HRESULT WINAPI ddraw_surface2_GetFlipStatus(IDirectDrawSurface2 *iface, DWORD flags)
3412 struct ddraw_surface *surface = impl_from_IDirectDrawSurface2(iface);
3414 TRACE("iface %p, flags %#lx.\n", iface, flags);
3416 return ddraw_surface7_GetFlipStatus(&surface->IDirectDrawSurface7_iface, flags);
3419 static HRESULT WINAPI ddraw_surface1_GetFlipStatus(IDirectDrawSurface *iface, DWORD flags)
3421 struct ddraw_surface *surface = impl_from_IDirectDrawSurface(iface);
3423 TRACE("iface %p, flags %#lx.\n", iface, flags);
3425 return ddraw_surface7_GetFlipStatus(&surface->IDirectDrawSurface7_iface, flags);
3428 /*****************************************************************************
3429 * IDirectDrawSurface7::GetOverlayPosition
3431 * Returns the display coordinates of a visible and active overlay surface
3433 * Params:
3437 * Returns:
3438 * DDERR_NOTAOVERLAYSURFACE, because it's a stub
3439 *****************************************************************************/
3440 static HRESULT WINAPI ddraw_surface7_GetOverlayPosition(IDirectDrawSurface7 *iface, LONG *x, LONG *y)
3442 struct ddraw_surface *surface = impl_from_IDirectDrawSurface7(iface);
3443 HRESULT hr;
3445 TRACE("iface %p, x %p, y %p.\n", iface, x, y);
3447 wined3d_mutex_lock();
3448 hr = wined3d_texture_get_overlay_position(surface->wined3d_texture,
3449 surface->sub_resource_idx, x, y);
3450 wined3d_mutex_unlock();
3452 return hr;
3455 static HRESULT WINAPI ddraw_surface4_GetOverlayPosition(IDirectDrawSurface4 *iface, LONG *x, LONG *y)
3457 struct ddraw_surface *surface = impl_from_IDirectDrawSurface4(iface);
3459 TRACE("iface %p, x %p, y %p.\n", iface, x, y);
3461 return ddraw_surface7_GetOverlayPosition(&surface->IDirectDrawSurface7_iface, x, y);
3464 static HRESULT WINAPI ddraw_surface3_GetOverlayPosition(IDirectDrawSurface3 *iface, LONG *x, LONG *y)
3466 struct ddraw_surface *surface = impl_from_IDirectDrawSurface3(iface);
3468 TRACE("iface %p, x %p, y %p.\n", iface, x, y);
3470 return ddraw_surface7_GetOverlayPosition(&surface->IDirectDrawSurface7_iface, x, y);
3473 static HRESULT WINAPI ddraw_surface2_GetOverlayPosition(IDirectDrawSurface2 *iface, LONG *x, LONG *y)
3475 struct ddraw_surface *surface = impl_from_IDirectDrawSurface2(iface);
3477 TRACE("iface %p, x %p, y %p.\n", iface, x, y);
3479 return ddraw_surface7_GetOverlayPosition(&surface->IDirectDrawSurface7_iface, x, y);
3482 static HRESULT WINAPI ddraw_surface1_GetOverlayPosition(IDirectDrawSurface *iface, LONG *x, LONG *y)
3484 struct ddraw_surface *surface = impl_from_IDirectDrawSurface(iface);
3486 TRACE("iface %p, x %p, y %p.\n", iface, x, y);
3488 return ddraw_surface7_GetOverlayPosition(&surface->IDirectDrawSurface7_iface, x, y);
3491 /*****************************************************************************
3492 * IDirectDrawSurface7::GetPixelFormat
3494 * Returns the pixel format of the Surface
3496 * Params:
3497 * PixelFormat: Pointer to a DDPIXELFORMAT structure to which the pixel
3498 * format should be written
3500 * Returns:
3501 * DD_OK on success
3502 * DDERR_INVALIDPARAMS if PixelFormat is NULL
3504 *****************************************************************************/
3505 static HRESULT WINAPI ddraw_surface7_GetPixelFormat(IDirectDrawSurface7 *iface, DDPIXELFORMAT *PixelFormat)
3507 /* What is DDERR_INVALIDSURFACETYPE for here? */
3508 struct ddraw_surface *surface = impl_from_IDirectDrawSurface7(iface);
3510 TRACE("iface %p, pixel_format %p.\n", iface, PixelFormat);
3512 if(!PixelFormat)
3513 return DDERR_INVALIDPARAMS;
3515 wined3d_mutex_lock();
3516 DD_STRUCT_COPY_BYSIZE(PixelFormat, &surface->surface_desc.u4.ddpfPixelFormat);
3517 wined3d_mutex_unlock();
3519 return DD_OK;
3522 static HRESULT WINAPI ddraw_surface4_GetPixelFormat(IDirectDrawSurface4 *iface, DDPIXELFORMAT *pixel_format)
3524 struct ddraw_surface *surface = impl_from_IDirectDrawSurface4(iface);
3526 TRACE("iface %p, pixel_format %p.\n", iface, pixel_format);
3528 return ddraw_surface7_GetPixelFormat(&surface->IDirectDrawSurface7_iface, pixel_format);
3531 static HRESULT WINAPI ddraw_surface3_GetPixelFormat(IDirectDrawSurface3 *iface, DDPIXELFORMAT *pixel_format)
3533 struct ddraw_surface *surface = impl_from_IDirectDrawSurface3(iface);
3535 TRACE("iface %p, pixel_format %p.\n", iface, pixel_format);
3537 return ddraw_surface7_GetPixelFormat(&surface->IDirectDrawSurface7_iface, pixel_format);
3540 static HRESULT WINAPI ddraw_surface2_GetPixelFormat(IDirectDrawSurface2 *iface, DDPIXELFORMAT *pixel_format)
3542 struct ddraw_surface *surface = impl_from_IDirectDrawSurface2(iface);
3544 TRACE("iface %p, pixel_format %p.\n", iface, pixel_format);
3546 return ddraw_surface7_GetPixelFormat(&surface->IDirectDrawSurface7_iface, pixel_format);
3549 static HRESULT WINAPI ddraw_surface1_GetPixelFormat(IDirectDrawSurface *iface, DDPIXELFORMAT *pixel_format)
3551 struct ddraw_surface *surface = impl_from_IDirectDrawSurface(iface);
3553 TRACE("iface %p, pixel_format %p.\n", iface, pixel_format);
3555 return ddraw_surface7_GetPixelFormat(&surface->IDirectDrawSurface7_iface, pixel_format);
3558 /*****************************************************************************
3559 * IDirectDrawSurface7::GetSurfaceDesc
3561 * Returns the description of this surface
3563 * Params:
3564 * DDSD: Address of a DDSURFACEDESC2 structure that is to be filled with the
3565 * surface desc
3567 * Returns:
3568 * DD_OK on success
3569 * DDERR_INVALIDPARAMS if DDSD is NULL
3571 *****************************************************************************/
3572 static HRESULT WINAPI ddraw_surface7_GetSurfaceDesc(IDirectDrawSurface7 *iface, DDSURFACEDESC2 *surface_desc)
3574 struct ddraw_surface *surface = impl_from_IDirectDrawSurface7(iface);
3576 TRACE("iface %p, surface_desc %p.\n", iface, surface_desc);
3578 if (!surface_desc) return DDERR_INVALIDPARAMS;
3580 if (surface_desc->dwSize != sizeof(DDSURFACEDESC2))
3582 WARN("Incorrect struct size %lu.\n", surface_desc->dwSize);
3583 return DDERR_INVALIDPARAMS;
3586 wined3d_mutex_lock();
3587 DD_STRUCT_COPY_BYSIZE(surface_desc, &surface->surface_desc);
3588 TRACE("Returning surface desc:\n");
3589 if (TRACE_ON(ddraw)) DDRAW_dump_surface_desc(surface_desc);
3590 wined3d_mutex_unlock();
3592 return DD_OK;
3595 static HRESULT WINAPI ddraw_surface4_GetSurfaceDesc(IDirectDrawSurface4 *iface, DDSURFACEDESC2 *DDSD)
3597 struct ddraw_surface *surface = impl_from_IDirectDrawSurface4(iface);
3599 TRACE("iface %p, surface_desc %p.\n", iface, DDSD);
3601 return ddraw_surface7_GetSurfaceDesc(&surface->IDirectDrawSurface7_iface, DDSD);
3604 static HRESULT WINAPI ddraw_surface3_GetSurfaceDesc(IDirectDrawSurface3 *iface, DDSURFACEDESC *surface_desc)
3606 struct ddraw_surface *surface = impl_from_IDirectDrawSurface3(iface);
3608 TRACE("iface %p, surface_desc %p.\n", iface, surface_desc);
3610 if (!surface_desc) return DDERR_INVALIDPARAMS;
3612 if (surface_desc->dwSize != sizeof(DDSURFACEDESC))
3614 WARN("Incorrect structure size %lu.\n", surface_desc->dwSize);
3615 return DDERR_INVALIDPARAMS;
3618 wined3d_mutex_lock();
3619 DDSD2_to_DDSD(&surface->surface_desc, surface_desc);
3620 TRACE("Returning surface desc:\n");
3621 if (TRACE_ON(ddraw))
3623 /* DDRAW_dump_surface_desc handles the smaller size */
3624 DDRAW_dump_surface_desc((DDSURFACEDESC2 *)surface_desc);
3626 wined3d_mutex_unlock();
3628 return DD_OK;
3631 static HRESULT WINAPI ddraw_surface2_GetSurfaceDesc(IDirectDrawSurface2 *iface, DDSURFACEDESC *DDSD)
3633 struct ddraw_surface *surface = impl_from_IDirectDrawSurface2(iface);
3635 TRACE("iface %p, surface_desc %p.\n", iface, DDSD);
3637 return ddraw_surface3_GetSurfaceDesc(&surface->IDirectDrawSurface3_iface, DDSD);
3640 static HRESULT WINAPI ddraw_surface1_GetSurfaceDesc(IDirectDrawSurface *iface, DDSURFACEDESC *DDSD)
3642 struct ddraw_surface *surface = impl_from_IDirectDrawSurface(iface);
3644 TRACE("iface %p, surface_desc %p.\n", iface, DDSD);
3646 return ddraw_surface3_GetSurfaceDesc(&surface->IDirectDrawSurface3_iface, DDSD);
3649 /*****************************************************************************
3650 * IDirectDrawSurface7::Initialize
3652 * Initializes the surface. This is a no-op in Wine
3654 * Params:
3655 * DD: Pointer to an DirectDraw interface
3656 * DDSD: Surface description for initialization
3658 * Returns:
3659 * DDERR_ALREADYINITIALIZED
3661 *****************************************************************************/
3662 static HRESULT WINAPI ddraw_surface7_Initialize(IDirectDrawSurface7 *iface,
3663 IDirectDraw *ddraw, DDSURFACEDESC2 *surface_desc)
3665 TRACE("iface %p, ddraw %p, surface_desc %p.\n", iface, ddraw, surface_desc);
3667 return DDERR_ALREADYINITIALIZED;
3670 static HRESULT WINAPI ddraw_surface4_Initialize(IDirectDrawSurface4 *iface,
3671 IDirectDraw *ddraw, DDSURFACEDESC2 *surface_desc)
3673 struct ddraw_surface *surface = impl_from_IDirectDrawSurface4(iface);
3675 TRACE("iface %p, ddraw %p, surface_desc %p.\n", iface, ddraw, surface_desc);
3677 return ddraw_surface7_Initialize(&surface->IDirectDrawSurface7_iface,
3678 ddraw, surface_desc);
3681 static HRESULT WINAPI ddraw_surface3_Initialize(IDirectDrawSurface3 *iface,
3682 IDirectDraw *ddraw, DDSURFACEDESC *surface_desc)
3684 struct ddraw_surface *surface = impl_from_IDirectDrawSurface3(iface);
3685 DDSURFACEDESC2 surface_desc2;
3687 TRACE("iface %p, ddraw %p, surface_desc %p.\n", iface, ddraw, surface_desc);
3689 if (surface_desc) DDSD_to_DDSD2(surface_desc, &surface_desc2);
3690 return ddraw_surface7_Initialize(&surface->IDirectDrawSurface7_iface,
3691 ddraw, surface_desc ? &surface_desc2 : NULL);
3694 static HRESULT WINAPI ddraw_surface2_Initialize(IDirectDrawSurface2 *iface,
3695 IDirectDraw *ddraw, DDSURFACEDESC *surface_desc)
3697 struct ddraw_surface *surface = impl_from_IDirectDrawSurface2(iface);
3698 DDSURFACEDESC2 surface_desc2;
3700 TRACE("iface %p, ddraw %p, surface_desc %p.\n", iface, ddraw, surface_desc);
3702 if (surface_desc) DDSD_to_DDSD2(surface_desc, &surface_desc2);
3703 return ddraw_surface7_Initialize(&surface->IDirectDrawSurface7_iface,
3704 ddraw, surface_desc ? &surface_desc2 : NULL);
3707 static HRESULT WINAPI ddraw_surface1_Initialize(IDirectDrawSurface *iface,
3708 IDirectDraw *ddraw, DDSURFACEDESC *surface_desc)
3710 struct ddraw_surface *surface = impl_from_IDirectDrawSurface(iface);
3711 DDSURFACEDESC2 surface_desc2;
3713 TRACE("iface %p, ddraw %p, surface_desc %p.\n", iface, ddraw, surface_desc);
3715 if (surface_desc) DDSD_to_DDSD2(surface_desc, &surface_desc2);
3716 return ddraw_surface7_Initialize(&surface->IDirectDrawSurface7_iface,
3717 ddraw, surface_desc ? &surface_desc2 : NULL);
3720 /*****************************************************************************
3721 * IDirect3DTexture1::Initialize
3723 * The sdk says it's not implemented
3725 * Params:
3728 * Returns
3729 * DDERR_UNSUPPORTED
3731 *****************************************************************************/
3732 static HRESULT WINAPI d3d_texture1_Initialize(IDirect3DTexture *iface,
3733 IDirect3DDevice *device, IDirectDrawSurface *surface)
3735 TRACE("iface %p, device %p, surface %p.\n", iface, device, surface);
3737 return DDERR_UNSUPPORTED; /* Unchecked */
3740 /*****************************************************************************
3741 * IDirectDrawSurface7::IsLost
3743 * Checks if the surface is lost
3745 * Returns:
3746 * DD_OK, if the surface is usable
3747 * DDERR_ISLOST if the surface is lost
3749 *****************************************************************************/
3750 static HRESULT WINAPI ddraw_surface7_IsLost(IDirectDrawSurface7 *iface)
3752 struct ddraw_surface *surface = impl_from_IDirectDrawSurface7(iface);
3754 TRACE("iface %p.\n", iface);
3756 return ddraw_surface_is_lost(surface) ? DDERR_SURFACELOST : DD_OK;
3759 static HRESULT WINAPI ddraw_surface4_IsLost(IDirectDrawSurface4 *iface)
3761 struct ddraw_surface *surface = impl_from_IDirectDrawSurface4(iface);
3763 TRACE("iface %p.\n", iface);
3765 return ddraw_surface_is_lost(surface) ? DDERR_SURFACELOST : DD_OK;
3768 static HRESULT WINAPI ddraw_surface3_IsLost(IDirectDrawSurface3 *iface)
3770 struct ddraw_surface *surface = impl_from_IDirectDrawSurface3(iface);
3772 TRACE("iface %p.\n", iface);
3774 return ddraw_surface_is_lost(surface) ? DDERR_SURFACELOST : DD_OK;
3777 static HRESULT WINAPI ddraw_surface2_IsLost(IDirectDrawSurface2 *iface)
3779 struct ddraw_surface *surface = impl_from_IDirectDrawSurface2(iface);
3781 TRACE("iface %p.\n", iface);
3783 return ddraw_surface_is_lost(surface) ? DDERR_SURFACELOST : DD_OK;
3786 static HRESULT WINAPI ddraw_surface1_IsLost(IDirectDrawSurface *iface)
3788 struct ddraw_surface *surface = impl_from_IDirectDrawSurface(iface);
3790 TRACE("iface %p.\n", iface);
3792 return ddraw_surface_is_lost(surface) ? DDERR_SURFACELOST : DD_OK;
3795 /*****************************************************************************
3796 * IDirectDrawSurface7::Restore
3798 * Restores a lost surface. This makes the surface usable again, but
3799 * doesn't reload its old contents
3801 * Returns:
3802 * DD_OK on success, error code otherwise.
3804 *****************************************************************************/
3805 static HRESULT WINAPI ddraw_surface7_Restore(IDirectDrawSurface7 *iface)
3807 struct ddraw_surface *surface = impl_from_IDirectDrawSurface7(iface);
3808 struct ddraw_surface *attachment;
3809 unsigned int i;
3811 TRACE("iface %p.\n", iface);
3813 if (surface->surface_desc.ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE)
3815 struct wined3d_swapchain *swapchain = surface->ddraw->wined3d_swapchain;
3816 struct wined3d_sub_resource_desc wined3d_desc;
3817 struct wined3d_display_mode mode;
3818 HRESULT hr;
3820 if (FAILED(hr = wined3d_swapchain_get_display_mode(swapchain, &mode, NULL)))
3822 WARN("Failed to get display mode, hr %#lx.\n", hr);
3823 return hr;
3826 if (FAILED(hr = wined3d_texture_get_sub_resource_desc(surface->wined3d_texture, 0, &wined3d_desc)))
3828 WARN("Failed to get resource desc, hr %#lx.\n", hr);
3829 return hr;
3832 if (mode.width != wined3d_desc.width || mode.height != wined3d_desc.height)
3834 WARN("Display mode dimensions %ux%u don't match surface dimensions %ux%u.\n",
3835 mode.width, mode.height, wined3d_desc.width, wined3d_desc.height);
3836 return DDERR_WRONGMODE;
3839 if (mode.format_id != wined3d_desc.format)
3841 WARN("Display mode format %#x doesn't match surface format %#x.\n",
3842 mode.format_id, wined3d_desc.format);
3843 return DDERR_WRONGMODE;
3847 if (!ddraw_surface_can_be_lost(surface))
3848 return DD_OK;
3849 ddraw_update_lost_surfaces(surface->ddraw);
3850 if (surface->ddraw->device_state == DDRAW_DEVICE_STATE_LOST)
3851 return DDERR_WRONGMODE;
3853 surface->is_lost = FALSE;
3855 for(i = 0; i < MAX_COMPLEX_ATTACHED; i++)
3857 attachment = surface->complex_array[i];
3858 while (attachment)
3860 attachment->is_lost = FALSE;
3861 attachment = attachment->complex_array[0];
3862 if (attachment == surface->complex_array[i])
3863 break;
3867 return DD_OK;
3870 static HRESULT WINAPI ddraw_surface4_Restore(IDirectDrawSurface4 *iface)
3872 struct ddraw_surface *surface = impl_from_IDirectDrawSurface4(iface);
3874 TRACE("iface %p.\n", iface);
3876 return ddraw_surface7_Restore(&surface->IDirectDrawSurface7_iface);
3879 static HRESULT WINAPI ddraw_surface3_Restore(IDirectDrawSurface3 *iface)
3881 struct ddraw_surface *surface = impl_from_IDirectDrawSurface3(iface);
3883 TRACE("iface %p.\n", iface);
3885 return ddraw_surface7_Restore(&surface->IDirectDrawSurface7_iface);
3888 static HRESULT WINAPI ddraw_surface2_Restore(IDirectDrawSurface2 *iface)
3890 struct ddraw_surface *surface = impl_from_IDirectDrawSurface2(iface);
3892 TRACE("iface %p.\n", iface);
3894 return ddraw_surface7_Restore(&surface->IDirectDrawSurface7_iface);
3897 static HRESULT WINAPI ddraw_surface1_Restore(IDirectDrawSurface *iface)
3899 struct ddraw_surface *surface = impl_from_IDirectDrawSurface(iface);
3901 TRACE("iface %p.\n", iface);
3903 return ddraw_surface7_Restore(&surface->IDirectDrawSurface7_iface);
3906 /*****************************************************************************
3907 * IDirectDrawSurface7::SetOverlayPosition
3909 * Changes the display coordinates of an overlay surface
3911 * Params:
3912 * X:
3913 * Y:
3915 * Returns:
3916 * DDERR_NOTAOVERLAYSURFACE, because we don't support overlays right now
3917 *****************************************************************************/
3918 static HRESULT WINAPI ddraw_surface7_SetOverlayPosition(IDirectDrawSurface7 *iface, LONG x, LONG y)
3920 struct ddraw_surface *surface = impl_from_IDirectDrawSurface7(iface);
3921 HRESULT hr;
3923 TRACE("iface %p, x %ld, y %ld.\n", iface, x, y);
3925 wined3d_mutex_lock();
3926 hr = wined3d_texture_set_overlay_position(surface->wined3d_texture,
3927 surface->sub_resource_idx, x, y);
3928 wined3d_mutex_unlock();
3930 return hr;
3933 static HRESULT WINAPI ddraw_surface4_SetOverlayPosition(IDirectDrawSurface4 *iface, LONG x, LONG y)
3935 struct ddraw_surface *surface = impl_from_IDirectDrawSurface4(iface);
3937 TRACE("iface %p, x %ld, y %ld.\n", iface, x, y);
3939 return ddraw_surface7_SetOverlayPosition(&surface->IDirectDrawSurface7_iface, x, y);
3942 static HRESULT WINAPI ddraw_surface3_SetOverlayPosition(IDirectDrawSurface3 *iface, LONG x, LONG y)
3944 struct ddraw_surface *surface = impl_from_IDirectDrawSurface3(iface);
3946 TRACE("iface %p, x %ld, y %ld.\n", iface, x, y);
3948 return ddraw_surface7_SetOverlayPosition(&surface->IDirectDrawSurface7_iface, x, y);
3951 static HRESULT WINAPI ddraw_surface2_SetOverlayPosition(IDirectDrawSurface2 *iface, LONG x, LONG y)
3953 struct ddraw_surface *surface = impl_from_IDirectDrawSurface2(iface);
3955 TRACE("iface %p, x %ld, y %ld.\n", iface, x, y);
3957 return ddraw_surface7_SetOverlayPosition(&surface->IDirectDrawSurface7_iface, x, y);
3960 static HRESULT WINAPI ddraw_surface1_SetOverlayPosition(IDirectDrawSurface *iface, LONG x, LONG y)
3962 struct ddraw_surface *surface = impl_from_IDirectDrawSurface(iface);
3964 TRACE("iface %p, x %ld, y %ld.\n", iface, x, y);
3966 return ddraw_surface7_SetOverlayPosition(&surface->IDirectDrawSurface7_iface, x, y);
3969 /*****************************************************************************
3970 * IDirectDrawSurface7::UpdateOverlay
3972 * Modifies the attributes of an overlay surface.
3974 * Params:
3975 * SrcRect: The section of the source being used for the overlay
3976 * DstSurface: Address of the surface that is overlaid
3977 * DstRect: Place of the overlay
3978 * Flags: some DDOVER_* flags
3980 * Returns:
3981 * DDERR_UNSUPPORTED, because we don't support overlays
3983 *****************************************************************************/
3984 static HRESULT WINAPI ddraw_surface7_UpdateOverlay(IDirectDrawSurface7 *iface, RECT *src_rect,
3985 IDirectDrawSurface7 *dst_surface, RECT *dst_rect, DWORD flags, DDOVERLAYFX *fx)
3987 struct ddraw_surface *src_impl = impl_from_IDirectDrawSurface7(iface);
3988 struct ddraw_surface *dst_impl = unsafe_impl_from_IDirectDrawSurface7(dst_surface);
3989 struct wined3d_texture *dst_wined3d_texture = NULL;
3990 unsigned int dst_sub_resource_idx = 0;
3991 HRESULT hr;
3993 TRACE("iface %p, src_rect %s, dst_surface %p, dst_rect %s, flags %#lx, fx %p.\n",
3994 iface, wine_dbgstr_rect(src_rect), dst_surface, wine_dbgstr_rect(dst_rect), flags, fx);
3996 if (fx)
3997 FIXME("Ignoring fx %p.\n", fx);
3999 wined3d_mutex_lock();
4000 if (dst_impl)
4002 dst_wined3d_texture = dst_impl->wined3d_texture;
4003 dst_sub_resource_idx = dst_impl->sub_resource_idx;
4005 hr = wined3d_texture_update_overlay(src_impl->wined3d_texture, src_impl->sub_resource_idx,
4006 src_rect, dst_wined3d_texture, dst_sub_resource_idx, dst_rect, flags);
4007 wined3d_mutex_unlock();
4009 return hr_ddraw_from_wined3d(hr);
4012 static HRESULT WINAPI ddraw_surface4_UpdateOverlay(IDirectDrawSurface4 *iface, RECT *src_rect,
4013 IDirectDrawSurface4 *dst_surface, RECT *dst_rect, DWORD flags, DDOVERLAYFX *fx)
4015 struct ddraw_surface *src_impl = impl_from_IDirectDrawSurface4(iface);
4016 struct ddraw_surface *dst_impl = unsafe_impl_from_IDirectDrawSurface4(dst_surface);
4018 TRACE("iface %p, src_rect %s, dst_surface %p, dst_rect %s, flags %#lx, fx %p.\n",
4019 iface, wine_dbgstr_rect(src_rect), dst_surface, wine_dbgstr_rect(dst_rect), flags, fx);
4021 return ddraw_surface7_UpdateOverlay(&src_impl->IDirectDrawSurface7_iface, src_rect,
4022 dst_impl ? &dst_impl->IDirectDrawSurface7_iface : NULL, dst_rect, flags, fx);
4025 static HRESULT WINAPI ddraw_surface3_UpdateOverlay(IDirectDrawSurface3 *iface, RECT *src_rect,
4026 IDirectDrawSurface3 *dst_surface, RECT *dst_rect, DWORD flags, DDOVERLAYFX *fx)
4028 struct ddraw_surface *src_impl = impl_from_IDirectDrawSurface3(iface);
4029 struct ddraw_surface *dst_impl = unsafe_impl_from_IDirectDrawSurface3(dst_surface);
4031 TRACE("iface %p, src_rect %s, dst_surface %p, dst_rect %s, flags %#lx, fx %p.\n",
4032 iface, wine_dbgstr_rect(src_rect), dst_surface, wine_dbgstr_rect(dst_rect), flags, fx);
4034 return ddraw_surface7_UpdateOverlay(&src_impl->IDirectDrawSurface7_iface, src_rect,
4035 dst_impl ? &dst_impl->IDirectDrawSurface7_iface : NULL, dst_rect, flags, fx);
4038 static HRESULT WINAPI ddraw_surface2_UpdateOverlay(IDirectDrawSurface2 *iface, RECT *src_rect,
4039 IDirectDrawSurface2 *dst_surface, RECT *dst_rect, DWORD flags, DDOVERLAYFX *fx)
4041 struct ddraw_surface *src_impl = impl_from_IDirectDrawSurface2(iface);
4042 struct ddraw_surface *dst_impl = unsafe_impl_from_IDirectDrawSurface2(dst_surface);
4044 TRACE("iface %p, src_rect %s, dst_surface %p, dst_rect %s, flags %#lx, fx %p.\n",
4045 iface, wine_dbgstr_rect(src_rect), dst_surface, wine_dbgstr_rect(dst_rect), flags, fx);
4047 return ddraw_surface7_UpdateOverlay(&src_impl->IDirectDrawSurface7_iface, src_rect,
4048 dst_impl ? &dst_impl->IDirectDrawSurface7_iface : NULL, dst_rect, flags, fx);
4051 static HRESULT WINAPI ddraw_surface1_UpdateOverlay(IDirectDrawSurface *iface, RECT *src_rect,
4052 IDirectDrawSurface *dst_surface, RECT *dst_rect, DWORD flags, DDOVERLAYFX *fx)
4054 struct ddraw_surface *src_impl = impl_from_IDirectDrawSurface(iface);
4055 struct ddraw_surface *dst_impl = unsafe_impl_from_IDirectDrawSurface(dst_surface);
4057 TRACE("iface %p, src_rect %s, dst_surface %p, dst_rect %s, flags %#lx, fx %p.\n",
4058 iface, wine_dbgstr_rect(src_rect), dst_surface, wine_dbgstr_rect(dst_rect), flags, fx);
4060 return ddraw_surface7_UpdateOverlay(&src_impl->IDirectDrawSurface7_iface, src_rect,
4061 dst_impl ? &dst_impl->IDirectDrawSurface7_iface : NULL, dst_rect, flags, fx);
4064 /*****************************************************************************
4065 * IDirectDrawSurface7::UpdateOverlayDisplay
4067 * The DX7 sdk says that it's not implemented
4069 * Params:
4070 * Flags: ?
4072 * Returns: DDERR_UNSUPPORTED, because we don't support overlays
4074 *****************************************************************************/
4075 static HRESULT WINAPI ddraw_surface7_UpdateOverlayDisplay(IDirectDrawSurface7 *iface, DWORD Flags)
4077 TRACE("iface %p, flags %#lx.\n", iface, Flags);
4079 return DDERR_UNSUPPORTED;
4082 static HRESULT WINAPI ddraw_surface4_UpdateOverlayDisplay(IDirectDrawSurface4 *iface, DWORD flags)
4084 struct ddraw_surface *surface = impl_from_IDirectDrawSurface4(iface);
4086 TRACE("iface %p, flags %#lx.\n", iface, flags);
4088 return ddraw_surface7_UpdateOverlayDisplay(&surface->IDirectDrawSurface7_iface, flags);
4091 static HRESULT WINAPI ddraw_surface3_UpdateOverlayDisplay(IDirectDrawSurface3 *iface, DWORD flags)
4093 struct ddraw_surface *surface = impl_from_IDirectDrawSurface3(iface);
4095 TRACE("iface %p, flags %#lx.\n", iface, flags);
4097 return ddraw_surface7_UpdateOverlayDisplay(&surface->IDirectDrawSurface7_iface, flags);
4100 static HRESULT WINAPI ddraw_surface2_UpdateOverlayDisplay(IDirectDrawSurface2 *iface, DWORD flags)
4102 struct ddraw_surface *surface = impl_from_IDirectDrawSurface2(iface);
4104 TRACE("iface %p, flags %#lx.\n", iface, flags);
4106 return ddraw_surface7_UpdateOverlayDisplay(&surface->IDirectDrawSurface7_iface, flags);
4109 static HRESULT WINAPI ddraw_surface1_UpdateOverlayDisplay(IDirectDrawSurface *iface, DWORD flags)
4111 struct ddraw_surface *surface = impl_from_IDirectDrawSurface(iface);
4113 TRACE("iface %p, flags %#lx.\n", iface, flags);
4115 return ddraw_surface7_UpdateOverlayDisplay(&surface->IDirectDrawSurface7_iface, flags);
4118 /*****************************************************************************
4119 * IDirectDrawSurface7::UpdateOverlayZOrder
4121 * Sets an overlay's Z order
4123 * Params:
4124 * Flags: DDOVERZ_* flags
4125 * DDSRef: Defines the relative position in the overlay chain
4127 * Returns:
4128 * DDERR_NOTOVERLAYSURFACE, because we don't support overlays
4130 *****************************************************************************/
4131 static HRESULT WINAPI ddraw_surface7_UpdateOverlayZOrder(IDirectDrawSurface7 *iface,
4132 DWORD flags, IDirectDrawSurface7 *reference)
4134 struct ddraw_surface *surface = impl_from_IDirectDrawSurface7(iface);
4136 FIXME("iface %p, flags %#lx, reference %p stub!\n", iface, flags, reference);
4138 wined3d_mutex_lock();
4139 if (!(surface->surface_desc.ddsCaps.dwCaps & DDSCAPS_OVERLAY))
4141 WARN("Not an overlay surface.\n");
4142 wined3d_mutex_unlock();
4143 return DDERR_NOTAOVERLAYSURFACE;
4145 wined3d_mutex_unlock();
4147 return DD_OK;
4150 static HRESULT WINAPI ddraw_surface4_UpdateOverlayZOrder(IDirectDrawSurface4 *iface,
4151 DWORD flags, IDirectDrawSurface4 *reference)
4153 struct ddraw_surface *surface = impl_from_IDirectDrawSurface4(iface);
4154 struct ddraw_surface *reference_impl = unsafe_impl_from_IDirectDrawSurface4(reference);
4156 TRACE("iface %p, flags %#lx, reference %p.\n", iface, flags, reference);
4158 return ddraw_surface7_UpdateOverlayZOrder(&surface->IDirectDrawSurface7_iface, flags,
4159 reference_impl ? &reference_impl->IDirectDrawSurface7_iface : NULL);
4162 static HRESULT WINAPI ddraw_surface3_UpdateOverlayZOrder(IDirectDrawSurface3 *iface,
4163 DWORD flags, IDirectDrawSurface3 *reference)
4165 struct ddraw_surface *surface = impl_from_IDirectDrawSurface3(iface);
4166 struct ddraw_surface *reference_impl = unsafe_impl_from_IDirectDrawSurface3(reference);
4168 TRACE("iface %p, flags %#lx, reference %p.\n", iface, flags, reference);
4170 return ddraw_surface7_UpdateOverlayZOrder(&surface->IDirectDrawSurface7_iface, flags,
4171 reference_impl ? &reference_impl->IDirectDrawSurface7_iface : NULL);
4174 static HRESULT WINAPI ddraw_surface2_UpdateOverlayZOrder(IDirectDrawSurface2 *iface,
4175 DWORD flags, IDirectDrawSurface2 *reference)
4177 struct ddraw_surface *surface = impl_from_IDirectDrawSurface2(iface);
4178 struct ddraw_surface *reference_impl = unsafe_impl_from_IDirectDrawSurface2(reference);
4180 TRACE("iface %p, flags %#lx, reference %p.\n", iface, flags, reference);
4182 return ddraw_surface7_UpdateOverlayZOrder(&surface->IDirectDrawSurface7_iface, flags,
4183 reference_impl ? &reference_impl->IDirectDrawSurface7_iface : NULL);
4186 static HRESULT WINAPI ddraw_surface1_UpdateOverlayZOrder(IDirectDrawSurface *iface,
4187 DWORD flags, IDirectDrawSurface *reference)
4189 struct ddraw_surface *surface = impl_from_IDirectDrawSurface(iface);
4190 struct ddraw_surface *reference_impl = unsafe_impl_from_IDirectDrawSurface(reference);
4192 TRACE("iface %p, flags %#lx, reference %p.\n", iface, flags, reference);
4194 return ddraw_surface7_UpdateOverlayZOrder(&surface->IDirectDrawSurface7_iface, flags,
4195 reference_impl ? &reference_impl->IDirectDrawSurface7_iface : NULL);
4198 /*****************************************************************************
4199 * IDirectDrawSurface7::GetDDInterface
4201 * Returns the IDirectDraw7 interface pointer of the DirectDraw object this
4202 * surface belongs to
4204 * Params:
4205 * DD: Address to write the interface pointer to
4207 * Returns:
4208 * DD_OK on success
4209 * DDERR_INVALIDPARAMS if DD is NULL
4211 *****************************************************************************/
4212 static HRESULT WINAPI ddraw_surface7_GetDDInterface(IDirectDrawSurface7 *iface, void **DD)
4214 struct ddraw_surface *This = impl_from_IDirectDrawSurface7(iface);
4216 TRACE("iface %p, ddraw %p.\n", iface, DD);
4218 if(!DD)
4219 return DDERR_INVALIDPARAMS;
4221 switch(This->version)
4223 case 7:
4224 *DD = &This->ddraw->IDirectDraw7_iface;
4225 break;
4227 case 4:
4228 *DD = &This->ddraw->IDirectDraw4_iface;
4229 break;
4231 case 2:
4232 *DD = &This->ddraw->IDirectDraw2_iface;
4233 break;
4235 case 1:
4236 *DD = &This->ddraw->IDirectDraw_iface;
4237 break;
4240 IUnknown_AddRef((IUnknown *)*DD);
4242 return DD_OK;
4245 static HRESULT WINAPI ddraw_surface4_GetDDInterface(IDirectDrawSurface4 *iface, void **ddraw)
4247 struct ddraw_surface *surface = impl_from_IDirectDrawSurface4(iface);
4249 TRACE("iface %p, ddraw %p.\n", iface, ddraw);
4251 return ddraw_surface7_GetDDInterface(&surface->IDirectDrawSurface7_iface, ddraw);
4254 static HRESULT WINAPI ddraw_surface3_GetDDInterface(IDirectDrawSurface3 *iface, void **ddraw)
4256 struct ddraw_surface *surface = impl_from_IDirectDrawSurface3(iface);
4258 TRACE("iface %p, ddraw %p.\n", iface, ddraw);
4260 return ddraw_surface7_GetDDInterface(&surface->IDirectDrawSurface7_iface, ddraw);
4263 static HRESULT WINAPI ddraw_surface2_GetDDInterface(IDirectDrawSurface2 *iface, void **ddraw)
4265 struct ddraw_surface *surface = impl_from_IDirectDrawSurface2(iface);
4267 TRACE("iface %p, ddraw %p.\n", iface, ddraw);
4269 return ddraw_surface7_GetDDInterface(&surface->IDirectDrawSurface7_iface, ddraw);
4272 static HRESULT WINAPI ddraw_surface7_ChangeUniquenessValue(IDirectDrawSurface7 *iface)
4274 TRACE("iface %p.\n", iface);
4276 return DD_OK;
4279 static HRESULT WINAPI ddraw_surface4_ChangeUniquenessValue(IDirectDrawSurface4 *iface)
4281 struct ddraw_surface *surface = impl_from_IDirectDrawSurface4(iface);
4283 TRACE("iface %p.\n", iface);
4285 return ddraw_surface7_ChangeUniquenessValue(&surface->IDirectDrawSurface7_iface);
4288 static HRESULT WINAPI ddraw_surface7_GetUniquenessValue(IDirectDrawSurface7 *iface, DWORD *pValue)
4290 TRACE("iface %p, value %p.\n", iface, pValue);
4292 *pValue = 0;
4294 return DD_OK;
4297 static HRESULT WINAPI ddraw_surface4_GetUniquenessValue(IDirectDrawSurface4 *iface, DWORD *pValue)
4299 struct ddraw_surface *surface = impl_from_IDirectDrawSurface4(iface);
4301 TRACE("iface %p, value %p.\n", iface, pValue);
4303 return ddraw_surface7_GetUniquenessValue(&surface->IDirectDrawSurface7_iface, pValue);
4306 /*****************************************************************************
4307 * IDirectDrawSurface7::SetLOD
4309 * Sets the level of detail of a texture
4311 * Params:
4312 * MaxLOD: LOD to set
4314 * Returns:
4315 * DD_OK on success
4316 * DDERR_INVALIDOBJECT if the surface is invalid for this method
4318 *****************************************************************************/
4319 static HRESULT WINAPI ddraw_surface7_SetLOD(IDirectDrawSurface7 *iface, DWORD MaxLOD)
4321 struct ddraw_surface *surface = impl_from_IDirectDrawSurface7(iface);
4322 HRESULT hr;
4324 TRACE("iface %p, lod %lu.\n", iface, MaxLOD);
4326 wined3d_mutex_lock();
4327 if (!(surface->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_TEXTUREMANAGE))
4329 wined3d_mutex_unlock();
4330 return DDERR_INVALIDOBJECT;
4333 hr = wined3d_texture_set_lod(surface->wined3d_texture, MaxLOD);
4334 if (SUCCEEDED(hr) && surface->draw_texture)
4335 hr = wined3d_texture_set_lod(surface->draw_texture, MaxLOD);
4336 wined3d_mutex_unlock();
4338 return hr;
4341 /*****************************************************************************
4342 * IDirectDrawSurface7::GetLOD
4344 * Returns the level of detail of a Direct3D texture
4346 * Params:
4347 * MaxLOD: Address to write the LOD to
4349 * Returns:
4350 * DD_OK on success
4351 * DDERR_INVALIDPARAMS if MaxLOD is NULL
4352 * DDERR_INVALIDOBJECT if the surface is invalid for this method
4354 *****************************************************************************/
4355 static HRESULT WINAPI ddraw_surface7_GetLOD(IDirectDrawSurface7 *iface, DWORD *MaxLOD)
4357 struct ddraw_surface *surface = impl_from_IDirectDrawSurface7(iface);
4359 TRACE("iface %p, lod %p.\n", iface, MaxLOD);
4361 if(!MaxLOD)
4362 return DDERR_INVALIDPARAMS;
4364 wined3d_mutex_lock();
4365 if (!(surface->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_TEXTUREMANAGE))
4367 wined3d_mutex_unlock();
4368 return DDERR_INVALIDOBJECT;
4371 *MaxLOD = wined3d_texture_get_lod(surface->wined3d_texture);
4372 wined3d_mutex_unlock();
4374 return DD_OK;
4377 /*****************************************************************************
4378 * IDirectDrawSurface7::BltFast
4380 * Performs a fast Blit.
4382 * Params:
4383 * dstx: The x coordinate to blit to on the destination
4384 * dsty: The y coordinate to blit to on the destination
4385 * Source: The source surface
4386 * rsrc: The source rectangle
4387 * trans: Type of transfer. Some DDBLTFAST_* flags
4389 * Returns:
4390 * DD_OK on success, error code otherwise.
4392 *****************************************************************************/
4393 static HRESULT WINAPI DECLSPEC_HOTPATCH ddraw_surface7_BltFast(IDirectDrawSurface7 *iface,
4394 DWORD dst_x, DWORD dst_y, IDirectDrawSurface7 *src_surface, RECT *src_rect, DWORD trans)
4396 struct ddraw_surface *dst_impl = impl_from_IDirectDrawSurface7(iface);
4397 struct ddraw_surface *src_impl = unsafe_impl_from_IDirectDrawSurface7(src_surface);
4398 DWORD flags = WINED3D_BLT_SYNCHRONOUS;
4399 DWORD src_w, src_h, dst_w, dst_h;
4400 HRESULT hr = DD_OK;
4401 RECT dst_rect, s;
4403 TRACE("iface %p, dst_x %lu, dst_y %lu, src_surface %p, src_rect %s, flags %#lx.\n",
4404 iface, dst_x, dst_y, src_surface, wine_dbgstr_rect(src_rect), trans);
4406 dst_w = dst_impl->surface_desc.dwWidth;
4407 dst_h = dst_impl->surface_desc.dwHeight;
4409 if (!src_rect)
4411 SetRect(&s, 0, 0, src_impl->surface_desc.dwWidth, src_impl->surface_desc.dwHeight);
4412 src_rect = &s;
4415 src_w = src_rect->right - src_rect->left;
4416 src_h = src_rect->bottom - src_rect->top;
4417 if (src_w > dst_w || dst_x > dst_w - src_w
4418 || src_h > dst_h || dst_y > dst_h - src_h)
4420 WARN("Destination area out of bounds, returning DDERR_INVALIDRECT.\n");
4421 return DDERR_INVALIDRECT;
4424 SetRect(&dst_rect, dst_x, dst_y, dst_x + src_w, dst_y + src_h);
4425 if (trans & DDBLTFAST_SRCCOLORKEY)
4426 flags |= WINED3D_BLT_SRC_CKEY;
4427 if (trans & DDBLTFAST_DESTCOLORKEY)
4428 flags |= WINED3D_BLT_DST_CKEY;
4429 if (trans & DDBLTFAST_WAIT)
4430 flags |= WINED3D_BLT_WAIT;
4431 if (trans & DDBLTFAST_DONOTWAIT)
4432 flags |= WINED3D_BLT_DO_NOT_WAIT;
4434 wined3d_mutex_lock();
4435 if (dst_impl->clipper)
4437 wined3d_mutex_unlock();
4438 WARN("Destination surface has a clipper set, returning DDERR_BLTFASTCANTCLIP.\n");
4439 return DDERR_BLTFASTCANTCLIP;
4442 if (src_impl->surface_desc.ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE)
4443 hr = ddraw_surface_update_frontbuffer(src_impl, src_rect, TRUE, 0);
4444 if (SUCCEEDED(hr))
4445 hr = wined3d_device_context_blt(dst_impl->ddraw->immediate_context,
4446 ddraw_surface_get_any_texture(dst_impl, DDRAW_SURFACE_RW), dst_impl->sub_resource_idx, &dst_rect,
4447 ddraw_surface_get_any_texture(src_impl,DDRAW_SURFACE_READ), src_impl->sub_resource_idx, src_rect,
4448 flags, NULL, WINED3D_TEXF_POINT);
4449 if (SUCCEEDED(hr) && (dst_impl->surface_desc.ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE))
4450 hr = ddraw_surface_update_frontbuffer(dst_impl, &dst_rect, FALSE, 0);
4451 wined3d_mutex_unlock();
4453 switch(hr)
4455 case WINED3DERR_NOTAVAILABLE: return DDERR_UNSUPPORTED;
4456 default: return hr;
4460 static HRESULT WINAPI DECLSPEC_HOTPATCH ddraw_surface4_BltFast(IDirectDrawSurface4 *iface, DWORD dst_x, DWORD dst_y,
4461 IDirectDrawSurface4 *src_surface, RECT *src_rect, DWORD flags)
4463 struct ddraw_surface *dst_impl = impl_from_IDirectDrawSurface4(iface);
4464 struct ddraw_surface *src_impl = unsafe_impl_from_IDirectDrawSurface4(src_surface);
4466 TRACE("iface %p, dst_x %lu, dst_y %lu, src_surface %p, src_rect %s, flags %#lx.\n",
4467 iface, dst_x, dst_y, src_surface, wine_dbgstr_rect(src_rect), flags);
4469 return ddraw_surface7_BltFast(&dst_impl->IDirectDrawSurface7_iface, dst_x, dst_y,
4470 src_impl ? &src_impl->IDirectDrawSurface7_iface : NULL, src_rect, flags);
4473 static HRESULT WINAPI DECLSPEC_HOTPATCH ddraw_surface3_BltFast(IDirectDrawSurface3 *iface, DWORD dst_x, DWORD dst_y,
4474 IDirectDrawSurface3 *src_surface, RECT *src_rect, DWORD flags)
4476 struct ddraw_surface *dst_impl = impl_from_IDirectDrawSurface3(iface);
4477 struct ddraw_surface *src_impl = unsafe_impl_from_IDirectDrawSurface3(src_surface);
4479 TRACE("iface %p, dst_x %lu, dst_y %lu, src_surface %p, src_rect %s, flags %#lx.\n",
4480 iface, dst_x, dst_y, src_surface, wine_dbgstr_rect(src_rect), flags);
4482 return ddraw_surface7_BltFast(&dst_impl->IDirectDrawSurface7_iface, dst_x, dst_y,
4483 src_impl ? &src_impl->IDirectDrawSurface7_iface : NULL, src_rect, flags);
4486 static HRESULT WINAPI DECLSPEC_HOTPATCH ddraw_surface2_BltFast(IDirectDrawSurface2 *iface, DWORD dst_x, DWORD dst_y,
4487 IDirectDrawSurface2 *src_surface, RECT *src_rect, DWORD flags)
4489 struct ddraw_surface *dst_impl = impl_from_IDirectDrawSurface2(iface);
4490 struct ddraw_surface *src_impl = unsafe_impl_from_IDirectDrawSurface2(src_surface);
4492 TRACE("iface %p, dst_x %lu, dst_y %lu, src_surface %p, src_rect %s, flags %#lx.\n",
4493 iface, dst_x, dst_y, src_surface, wine_dbgstr_rect(src_rect), flags);
4495 return ddraw_surface7_BltFast(&dst_impl->IDirectDrawSurface7_iface, dst_x, dst_y,
4496 src_impl ? &src_impl->IDirectDrawSurface7_iface : NULL, src_rect, flags);
4499 static HRESULT WINAPI DECLSPEC_HOTPATCH ddraw_surface1_BltFast(IDirectDrawSurface *iface, DWORD dst_x, DWORD dst_y,
4500 IDirectDrawSurface *src_surface, RECT *src_rect, DWORD flags)
4502 struct ddraw_surface *dst_impl = impl_from_IDirectDrawSurface(iface);
4503 struct ddraw_surface *src_impl = unsafe_impl_from_IDirectDrawSurface(src_surface);
4505 TRACE("iface %p, dst_x %lu, dst_y %lu, src_surface %p, src_rect %s, flags %#lx.\n",
4506 iface, dst_x, dst_y, src_surface, wine_dbgstr_rect(src_rect), flags);
4508 return ddraw_surface7_BltFast(&dst_impl->IDirectDrawSurface7_iface, dst_x, dst_y,
4509 src_impl ? &src_impl->IDirectDrawSurface7_iface : NULL, src_rect, flags);
4512 static HRESULT WINAPI ddraw_surface7_GetClipper(IDirectDrawSurface7 *iface, IDirectDrawClipper **clipper)
4514 struct ddraw_surface *surface = impl_from_IDirectDrawSurface7(iface);
4516 TRACE("iface %p, clipper %p.\n", iface, clipper);
4518 if (!clipper)
4519 return DDERR_INVALIDPARAMS;
4521 wined3d_mutex_lock();
4522 if (!surface->clipper)
4524 wined3d_mutex_unlock();
4525 *clipper = NULL;
4526 return DDERR_NOCLIPPERATTACHED;
4529 *clipper = &surface->clipper->IDirectDrawClipper_iface;
4530 if (ddraw_clipper_is_valid(surface->clipper))
4531 IDirectDrawClipper_AddRef(*clipper);
4532 wined3d_mutex_unlock();
4534 return DD_OK;
4537 static HRESULT WINAPI ddraw_surface4_GetClipper(IDirectDrawSurface4 *iface, IDirectDrawClipper **clipper)
4539 struct ddraw_surface *surface = impl_from_IDirectDrawSurface4(iface);
4541 TRACE("iface %p, clipper %p.\n", iface, clipper);
4543 return ddraw_surface7_GetClipper(&surface->IDirectDrawSurface7_iface, clipper);
4546 static HRESULT WINAPI ddraw_surface3_GetClipper(IDirectDrawSurface3 *iface, IDirectDrawClipper **clipper)
4548 struct ddraw_surface *surface = impl_from_IDirectDrawSurface3(iface);
4550 TRACE("iface %p, clipper %p.\n", iface, clipper);
4552 return ddraw_surface7_GetClipper(&surface->IDirectDrawSurface7_iface, clipper);
4555 static HRESULT WINAPI ddraw_surface2_GetClipper(IDirectDrawSurface2 *iface, IDirectDrawClipper **clipper)
4557 struct ddraw_surface *surface = impl_from_IDirectDrawSurface2(iface);
4559 TRACE("iface %p, clipper %p.\n", iface, clipper);
4561 return ddraw_surface7_GetClipper(&surface->IDirectDrawSurface7_iface, clipper);
4564 static HRESULT WINAPI ddraw_surface1_GetClipper(IDirectDrawSurface *iface, IDirectDrawClipper **clipper)
4566 struct ddraw_surface *surface = impl_from_IDirectDrawSurface(iface);
4568 TRACE("iface %p, clipper %p.\n", iface, clipper);
4570 return ddraw_surface7_GetClipper(&surface->IDirectDrawSurface7_iface, clipper);
4573 /*****************************************************************************
4574 * IDirectDrawSurface7::SetClipper
4576 * Sets a clipper for the surface
4578 * Params:
4579 * Clipper: IDirectDrawClipper interface of the clipper to set
4581 * Returns:
4582 * DD_OK on success
4584 *****************************************************************************/
4585 static HRESULT WINAPI ddraw_surface7_SetClipper(IDirectDrawSurface7 *iface,
4586 IDirectDrawClipper *iclipper)
4588 struct ddraw_surface *This = impl_from_IDirectDrawSurface7(iface);
4589 struct ddraw_clipper *clipper = unsafe_impl_from_IDirectDrawClipper(iclipper);
4590 struct ddraw_clipper *old_clipper = This->clipper;
4591 HWND clipWindow;
4593 TRACE("iface %p, clipper %p.\n", iface, iclipper);
4595 wined3d_mutex_lock();
4596 if (clipper == This->clipper)
4598 wined3d_mutex_unlock();
4599 return DD_OK;
4602 This->clipper = clipper;
4604 if (clipper != NULL)
4605 IDirectDrawClipper_AddRef(iclipper);
4606 if (old_clipper && ddraw_clipper_is_valid(old_clipper))
4607 IDirectDrawClipper_Release(&old_clipper->IDirectDrawClipper_iface);
4609 if ((This->surface_desc.ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE) && This->ddraw->wined3d_swapchain)
4611 clipWindow = NULL;
4612 if(clipper) {
4613 IDirectDrawClipper_GetHWnd(iclipper, &clipWindow);
4616 if (clipWindow)
4618 wined3d_swapchain_set_window(This->ddraw->wined3d_swapchain, clipWindow);
4619 ddraw_set_swapchain_window(This->ddraw, clipWindow);
4621 else
4623 wined3d_swapchain_set_window(This->ddraw->wined3d_swapchain, This->ddraw->d3d_window);
4624 ddraw_set_swapchain_window(This->ddraw, This->ddraw->dest_window);
4628 wined3d_mutex_unlock();
4630 return DD_OK;
4633 static HRESULT WINAPI ddraw_surface4_SetClipper(IDirectDrawSurface4 *iface, IDirectDrawClipper *clipper)
4635 struct ddraw_surface *surface = impl_from_IDirectDrawSurface4(iface);
4637 TRACE("iface %p, clipper %p.\n", iface, clipper);
4639 return ddraw_surface7_SetClipper(&surface->IDirectDrawSurface7_iface, clipper);
4642 static HRESULT WINAPI ddraw_surface3_SetClipper(IDirectDrawSurface3 *iface, IDirectDrawClipper *clipper)
4644 struct ddraw_surface *surface = impl_from_IDirectDrawSurface3(iface);
4646 TRACE("iface %p, clipper %p.\n", iface, clipper);
4648 return ddraw_surface7_SetClipper(&surface->IDirectDrawSurface7_iface, clipper);
4651 static HRESULT WINAPI ddraw_surface2_SetClipper(IDirectDrawSurface2 *iface, IDirectDrawClipper *clipper)
4653 struct ddraw_surface *surface = impl_from_IDirectDrawSurface2(iface);
4655 TRACE("iface %p, clipper %p.\n", iface, clipper);
4657 return ddraw_surface7_SetClipper(&surface->IDirectDrawSurface7_iface, clipper);
4660 static HRESULT WINAPI ddraw_surface1_SetClipper(IDirectDrawSurface *iface, IDirectDrawClipper *clipper)
4662 struct ddraw_surface *surface = impl_from_IDirectDrawSurface(iface);
4664 TRACE("iface %p, clipper %p.\n", iface, clipper);
4666 return ddraw_surface7_SetClipper(&surface->IDirectDrawSurface7_iface, clipper);
4669 static HRESULT ddraw_surface_set_wined3d_textures_colour_key(struct ddraw_surface *surface, DWORD flags,
4670 struct wined3d_color_key *color_key)
4672 HRESULT hr;
4674 hr = wined3d_texture_set_color_key(surface->wined3d_texture, flags, color_key);
4675 if (surface->draw_texture && SUCCEEDED(hr))
4676 hr = wined3d_texture_set_color_key(surface->draw_texture, flags, color_key);
4678 return hr;
4681 static void ddraw_surface_sync_color_keys(struct ddraw_surface *surface)
4683 const DDSURFACEDESC2 *desc = &surface->surface_desc;
4685 if (desc->dwFlags & DDSD_CKDESTOVERLAY)
4686 ddraw_surface_set_wined3d_textures_colour_key(surface, DDCKEY_DESTOVERLAY,
4687 (struct wined3d_color_key *)&desc->u3.ddckCKDestOverlay);
4688 if (desc->dwFlags & DDSD_CKDESTBLT)
4689 ddraw_surface_set_wined3d_textures_colour_key(surface, DDCKEY_DESTBLT,
4690 (struct wined3d_color_key *)&desc->ddckCKDestBlt);
4691 if (desc->dwFlags & DDSD_CKSRCOVERLAY)
4692 ddraw_surface_set_wined3d_textures_colour_key(surface, DDCKEY_SRCOVERLAY,
4693 (struct wined3d_color_key *)&desc->ddckCKSrcOverlay);
4694 if (desc->dwFlags & DDSD_CKSRCBLT)
4695 ddraw_surface_set_wined3d_textures_colour_key(surface, DDCKEY_SRCBLT,
4696 (struct wined3d_color_key *)&desc->ddckCKSrcBlt);
4699 static HRESULT WINAPI ddraw_surface7_SetSurfaceDesc(IDirectDrawSurface7 *iface, DDSURFACEDESC2 *DDSD, DWORD Flags)
4701 struct ddraw_surface *surface = impl_from_IDirectDrawSurface7(iface);
4702 enum wined3d_format_id current_format_id, format_id;
4703 HRESULT hr;
4704 const DWORD allowed_flags = DDSD_LPSURFACE | DDSD_PIXELFORMAT | DDSD_WIDTH
4705 | DDSD_HEIGHT | DDSD_PITCH | DDSD_CAPS;
4706 UINT pitch, width, height;
4708 TRACE("iface %p, surface_desc %p, flags %#lx.\n", iface, DDSD, Flags);
4710 if (!DDSD)
4712 WARN("DDSD is NULL, returning DDERR_INVALIDPARAMS\n");
4713 return DDERR_INVALIDPARAMS;
4715 if (Flags)
4717 WARN("Flags is %lx, returning DDERR_INVALIDPARAMS\n", Flags);
4718 return DDERR_INVALIDPARAMS;
4720 if (!(surface->surface_desc.ddsCaps.dwCaps & DDSCAPS_SYSTEMMEMORY)
4721 || surface->surface_desc.ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE
4722 || surface->surface_desc.ddsCaps.dwCaps2 & (DDSCAPS2_TEXTUREMANAGE | DDSCAPS2_D3DTEXTUREMANAGE))
4724 WARN("Surface is not in system memory, returning DDERR_INVALIDSURFACETYPE.\n");
4725 return DDERR_INVALIDSURFACETYPE;
4728 if (DDSD->dwFlags & ~allowed_flags)
4730 WARN("Invalid flags %#lx set, returning DDERR_INVALIDPARAMS\n", DDSD->dwFlags);
4731 return DDERR_INVALIDPARAMS;
4733 if (!(DDSD->dwFlags & DDSD_LPSURFACE) || !DDSD->lpSurface)
4735 WARN("DDSD_LPSURFACE is not set or lpSurface is NULL, returning DDERR_INVALIDPARAMS\n");
4736 return DDERR_INVALIDPARAMS;
4738 if ((DDSD->dwFlags & DDSD_CAPS) && DDSD->ddsCaps.dwCaps)
4740 WARN("DDSD_CAPS is set, returning DDERR_INVALIDCAPS.\n");
4741 return DDERR_INVALIDCAPS;
4743 if (DDSD->dwFlags & DDSD_WIDTH)
4745 if (!(DDSD->dwFlags & DDSD_PITCH))
4747 WARN("DDSD_WIDTH is set, but DDSD_PITCH is not, returning DDERR_INVALIDPARAMS.\n");
4748 return DDERR_INVALIDPARAMS;
4750 if (!DDSD->dwWidth || DDSD->u1.lPitch <= 0 || DDSD->u1.lPitch & 0x3)
4752 WARN("Pitch is %ld, width is %lu, returning DDERR_INVALIDPARAMS.\n",
4753 DDSD->u1.lPitch, DDSD->dwWidth);
4754 return DDERR_INVALIDPARAMS;
4756 if (DDSD->dwWidth != surface->surface_desc.dwWidth)
4757 TRACE("Surface width changed from %lu to %lu.\n", surface->surface_desc.dwWidth, DDSD->dwWidth);
4758 if (DDSD->u1.lPitch != surface->surface_desc.u1.lPitch)
4759 TRACE("Surface pitch changed from %lu to %lu.\n", surface->surface_desc.u1.lPitch, DDSD->u1.lPitch);
4760 pitch = DDSD->u1.lPitch;
4761 width = DDSD->dwWidth;
4763 else if (DDSD->dwFlags & DDSD_PITCH)
4765 WARN("DDSD_PITCH is set, but DDSD_WIDTH is not, returning DDERR_INVALIDPARAMS.\n");
4766 return DDERR_INVALIDPARAMS;
4768 else
4770 pitch = surface->surface_desc.u1.lPitch;
4771 width = surface->surface_desc.dwWidth;
4774 if (DDSD->dwFlags & DDSD_HEIGHT)
4776 if (!DDSD->dwHeight)
4778 WARN("Height is 0, returning DDERR_INVALIDPARAMS.\n");
4779 return DDERR_INVALIDPARAMS;
4781 if (DDSD->dwHeight != surface->surface_desc.dwHeight)
4782 TRACE("Surface height changed from %lu to %lu.\n", surface->surface_desc.dwHeight, DDSD->dwHeight);
4783 height = DDSD->dwHeight;
4785 else
4787 height = surface->surface_desc.dwHeight;
4790 wined3d_mutex_lock();
4791 if (DDSD->dwFlags & DDSD_PIXELFORMAT)
4793 format_id = wined3dformat_from_ddrawformat(&DDSD->u4.ddpfPixelFormat);
4795 if (format_id == WINED3DFMT_UNKNOWN)
4797 ERR("Requested to set an unknown pixelformat\n");
4798 wined3d_mutex_unlock();
4799 return DDERR_INVALIDPARAMS;
4801 current_format_id = wined3dformat_from_ddrawformat(&surface->surface_desc.u4.ddpfPixelFormat);
4802 if (format_id != current_format_id)
4803 TRACE("Surface format changed from %#x to %#x.\n", current_format_id, format_id);
4805 else
4807 current_format_id = format_id = wined3dformat_from_ddrawformat(&surface->surface_desc.u4.ddpfPixelFormat);
4810 if (width == surface->surface_desc.dwWidth && height == surface->surface_desc.dwHeight
4811 && format_id == current_format_id)
4813 /* Updating memory only. */
4815 if (FAILED(hr = wined3d_texture_update_desc(surface->wined3d_texture,
4816 surface->sub_resource_idx, DDSD->lpSurface, pitch)))
4818 WARN("Failed to update surface desc, hr %#lx.\n", hr);
4819 wined3d_mutex_unlock();
4820 return hr_ddraw_from_wined3d(hr);
4823 else
4825 struct ddraw_texture *ddraw_texture = wined3d_texture_get_parent(surface->wined3d_texture);
4826 struct wined3d_rendertarget_view *old_rtv = surface->wined3d_rtv;
4827 struct wined3d_texture *old_draw_texture = surface->draw_texture;
4828 struct wined3d_texture *old_texture = surface->wined3d_texture;
4829 struct wined3d_texture *new_texture, *new_draw_texture = NULL;
4830 struct wined3d_resource_desc wined3d_desc;
4831 struct ddraw *ddraw = surface->ddraw;
4833 /* Updating surface attributes; recreate the texture. */
4835 if (wined3d_texture_get_level_count(old_texture) > 1
4836 || (surface->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP_ALLFACES))
4838 FIXME("Texture has multiple sub-resources, not supported.\n");
4839 wined3d_mutex_unlock();
4840 return DDERR_INVALIDPARAMS;
4843 /* Create the new textures. */
4845 wined3d_resource_get_desc(wined3d_texture_get_resource(old_texture), &wined3d_desc);
4847 wined3d_desc.width = width;
4848 wined3d_desc.height = height;
4849 wined3d_desc.format = format_id;
4851 if (FAILED(hr = wined3d_texture_create(ddraw->wined3d_device, &wined3d_desc, 1, 1,
4852 WINED3D_TEXTURE_CREATE_GET_DC_LENIENT, NULL, NULL, &ddraw_null_wined3d_parent_ops, &new_texture)))
4854 ERR("Failed to create texture, hr %#lx.\n", hr);
4855 wined3d_mutex_unlock();
4856 return hr_ddraw_from_wined3d(hr);
4859 if (FAILED(hr = wined3d_texture_update_desc(new_texture, 0, DDSD->lpSurface, pitch)))
4861 ERR("Failed to set user memory, hr %#lx.\n", hr);
4862 wined3d_texture_decref(new_texture);
4863 wined3d_mutex_unlock();
4864 return hr_ddraw_from_wined3d(hr);
4867 if (old_draw_texture)
4869 wined3d_resource_get_desc(wined3d_texture_get_resource(old_draw_texture), &wined3d_desc);
4871 wined3d_desc.width = width;
4872 wined3d_desc.height = height;
4873 wined3d_desc.format = format_id;
4875 if (FAILED(hr = wined3d_texture_create(ddraw->wined3d_device, &wined3d_desc, 1, 1,
4876 0, NULL, NULL, &ddraw_null_wined3d_parent_ops, &new_draw_texture)))
4878 ERR("Failed to create draw texture, hr %#lx.\n", hr);
4879 wined3d_texture_decref(new_texture);
4880 wined3d_mutex_unlock();
4881 return hr_ddraw_from_wined3d(hr);
4885 wined3d_resource_set_parent(wined3d_texture_get_resource(old_texture),
4886 NULL, &ddraw_null_wined3d_parent_ops);
4887 wined3d_texture_set_sub_resource_parent(old_texture, 0, NULL, &ddraw_null_wined3d_parent_ops);
4889 if (surface->draw_texture)
4891 wined3d_resource_set_parent(wined3d_texture_get_resource(old_draw_texture),
4892 NULL, &ddraw_null_wined3d_parent_ops);
4893 wined3d_texture_set_sub_resource_parent(old_draw_texture, 0, NULL, &ddraw_null_wined3d_parent_ops);
4895 wined3d_resource_set_parent(wined3d_texture_get_resource(new_draw_texture),
4896 ddraw_texture, &ddraw_texture_wined3d_parent_ops);
4897 wined3d_resource_set_parent(wined3d_texture_get_resource(new_texture),
4898 ddraw_texture, &ddraw_null_wined3d_parent_ops);
4900 wined3d_texture_set_sub_resource_parent(new_draw_texture, 0, surface, &ddraw_surface_wined3d_parent_ops);
4901 wined3d_texture_set_sub_resource_parent(new_texture, 0, surface, &ddraw_null_wined3d_parent_ops);
4903 wined3d_texture_decref(old_draw_texture);
4905 else
4907 wined3d_resource_set_parent(wined3d_texture_get_resource(new_texture),
4908 ddraw_texture, &ddraw_texture_wined3d_parent_ops);
4910 wined3d_texture_set_sub_resource_parent(new_texture, 0, surface, &ddraw_surface_wined3d_parent_ops);
4913 surface->wined3d_texture = new_texture;
4914 surface->draw_texture = new_draw_texture;
4916 wined3d_texture_decref(old_texture);
4918 /* Don't try to replace existing bound textures. Testing implies that
4919 * SetSurfaceDesc() doesn't quite work with texture surfaces anyway:
4920 * it succeeds, and mapping the surface does return the new user memory,
4921 * but drawing from the surface doesn't actually sample from that
4922 * memory. */
4924 /* Destroy the existing RTV. */
4926 if (old_rtv)
4928 struct wined3d_rendertarget_view *current_rtv, *new_rtv;
4930 surface->wined3d_rtv = NULL;
4932 current_rtv = wined3d_device_context_get_rendertarget_view(ddraw->immediate_context, 0);
4933 if (old_rtv == current_rtv)
4935 new_rtv = ddraw_surface_get_rendertarget_view(surface);
4936 wined3d_device_context_set_rendertarget_views(ddraw->immediate_context, 0, 1, &new_rtv, FALSE);
4939 wined3d_rendertarget_view_set_parent(old_rtv, NULL, &ddraw_null_wined3d_parent_ops);
4940 wined3d_rendertarget_view_decref(old_rtv);
4943 ddraw_surface_sync_color_keys(surface);
4945 /* No need to sync the LOD or overlays; neither can be set on sysmem
4946 * surfaces, and SetSurfaceDesc() can only be used on sysmem surfaces.
4948 * No need to sync the palette either, since wined3d doesn't track it
4949 * except on primary surfaces, and SetSurfaceDesc() is illegal on those
4950 * too. */
4953 if (DDSD->dwFlags & DDSD_WIDTH)
4954 surface->surface_desc.dwWidth = width;
4955 if (DDSD->dwFlags & DDSD_PITCH)
4956 surface->surface_desc.u1.lPitch = DDSD->u1.lPitch;
4957 if (DDSD->dwFlags & DDSD_HEIGHT)
4958 surface->surface_desc.dwHeight = height;
4959 if (DDSD->dwFlags & DDSD_PIXELFORMAT)
4960 surface->surface_desc.u4.ddpfPixelFormat = DDSD->u4.ddpfPixelFormat;
4962 wined3d_mutex_unlock();
4964 return DD_OK;
4967 static HRESULT WINAPI ddraw_surface4_SetSurfaceDesc(IDirectDrawSurface4 *iface,
4968 DDSURFACEDESC2 *surface_desc, DWORD flags)
4970 struct ddraw_surface *surface = impl_from_IDirectDrawSurface4(iface);
4972 TRACE("iface %p, surface_desc %p, flags %#lx.\n", iface, surface_desc, flags);
4974 return ddraw_surface7_SetSurfaceDesc(&surface->IDirectDrawSurface7_iface,
4975 surface_desc, flags);
4978 static HRESULT WINAPI ddraw_surface3_SetSurfaceDesc(IDirectDrawSurface3 *iface,
4979 DDSURFACEDESC *surface_desc, DWORD flags)
4981 struct ddraw_surface *surface = impl_from_IDirectDrawSurface3(iface);
4982 DDSURFACEDESC2 surface_desc2;
4984 TRACE("iface %p, surface_desc %p, flags %#lx.\n", iface, surface_desc, flags);
4986 if (surface_desc) DDSD_to_DDSD2(surface_desc, &surface_desc2);
4987 return ddraw_surface7_SetSurfaceDesc(&surface->IDirectDrawSurface7_iface,
4988 surface_desc ? &surface_desc2 : NULL, flags);
4991 static HRESULT WINAPI ddraw_surface7_GetPalette(IDirectDrawSurface7 *iface, IDirectDrawPalette **palette)
4993 struct ddraw_surface *surface = impl_from_IDirectDrawSurface7(iface);
4994 struct ddraw_palette *palette_impl;
4995 HRESULT hr = DD_OK;
4997 TRACE("iface %p, palette %p.\n", iface, palette);
4999 if (!palette)
5000 return DDERR_INVALIDPARAMS;
5001 if (ddraw_surface_is_lost(surface))
5003 WARN("Surface lost, returning DDERR_SURFACELOST.\n");
5004 return DDERR_SURFACELOST;
5007 wined3d_mutex_lock();
5008 if ((palette_impl = surface->palette))
5010 *palette = &palette_impl->IDirectDrawPalette_iface;
5011 IDirectDrawPalette_AddRef(*palette);
5013 else
5015 *palette = NULL;
5016 hr = DDERR_NOPALETTEATTACHED;
5018 wined3d_mutex_unlock();
5020 return hr;
5023 static HRESULT WINAPI ddraw_surface4_GetPalette(IDirectDrawSurface4 *iface, IDirectDrawPalette **palette)
5025 struct ddraw_surface *surface = impl_from_IDirectDrawSurface4(iface);
5027 TRACE("iface %p, palette %p.\n", iface, palette);
5029 return ddraw_surface7_GetPalette(&surface->IDirectDrawSurface7_iface, palette);
5032 static HRESULT WINAPI ddraw_surface3_GetPalette(IDirectDrawSurface3 *iface, IDirectDrawPalette **palette)
5034 struct ddraw_surface *surface = impl_from_IDirectDrawSurface3(iface);
5036 TRACE("iface %p, palette %p.\n", iface, palette);
5038 return ddraw_surface7_GetPalette(&surface->IDirectDrawSurface7_iface, palette);
5041 static HRESULT WINAPI ddraw_surface2_GetPalette(IDirectDrawSurface2 *iface, IDirectDrawPalette **palette)
5043 struct ddraw_surface *surface = impl_from_IDirectDrawSurface2(iface);
5045 TRACE("iface %p, palette %p.\n", iface, palette);
5047 return ddraw_surface7_GetPalette(&surface->IDirectDrawSurface7_iface, palette);
5050 static HRESULT WINAPI ddraw_surface1_GetPalette(IDirectDrawSurface *iface, IDirectDrawPalette **palette)
5052 struct ddraw_surface *surface = impl_from_IDirectDrawSurface(iface);
5054 TRACE("iface %p, palette %p.\n", iface, palette);
5056 return ddraw_surface7_GetPalette(&surface->IDirectDrawSurface7_iface, palette);
5059 static HRESULT ddraw_surface_set_color_key(struct ddraw_surface *surface, DWORD flags, DDCOLORKEY *color_key)
5061 DDCOLORKEY fixed_color_key;
5062 HRESULT hr = WINED3D_OK;
5064 if (flags & DDCKEY_COLORSPACE)
5066 if (color_key && color_key->dwColorSpaceLowValue != color_key->dwColorSpaceHighValue)
5068 WARN("Range color keys are not supported, returning DDERR_NOCOLORKEYHW.\n");
5069 return DDERR_NOCOLORKEYHW;
5071 flags &= ~DDCKEY_COLORSPACE;
5074 wined3d_mutex_lock();
5076 if (color_key)
5078 fixed_color_key.dwColorSpaceLowValue = fixed_color_key.dwColorSpaceHighValue = color_key->dwColorSpaceLowValue;
5079 switch (flags & ~DDCKEY_COLORSPACE)
5081 case DDCKEY_DESTBLT:
5082 surface->surface_desc.ddckCKDestBlt = fixed_color_key;
5083 surface->surface_desc.dwFlags |= DDSD_CKDESTBLT;
5084 break;
5086 case DDCKEY_DESTOVERLAY:
5087 surface->surface_desc.u3.ddckCKDestOverlay = fixed_color_key;
5088 surface->surface_desc.dwFlags |= DDSD_CKDESTOVERLAY;
5089 break;
5091 case DDCKEY_SRCOVERLAY:
5092 surface->surface_desc.ddckCKSrcOverlay = fixed_color_key;
5093 surface->surface_desc.dwFlags |= DDSD_CKSRCOVERLAY;
5094 break;
5096 case DDCKEY_SRCBLT:
5097 surface->surface_desc.ddckCKSrcBlt = fixed_color_key;
5098 surface->surface_desc.dwFlags |= DDSD_CKSRCBLT;
5099 break;
5101 default:
5102 wined3d_mutex_unlock();
5103 return DDERR_INVALIDPARAMS;
5106 else
5108 switch (flags & ~DDCKEY_COLORSPACE)
5110 case DDCKEY_DESTBLT:
5111 surface->surface_desc.dwFlags &= ~DDSD_CKDESTBLT;
5112 break;
5114 case DDCKEY_DESTOVERLAY:
5115 surface->surface_desc.dwFlags &= ~DDSD_CKDESTOVERLAY;
5116 break;
5118 case DDCKEY_SRCOVERLAY:
5119 surface->surface_desc.dwFlags &= ~DDSD_CKSRCOVERLAY;
5120 break;
5122 case DDCKEY_SRCBLT:
5123 surface->surface_desc.dwFlags &= ~DDSD_CKSRCBLT;
5124 break;
5126 default:
5127 wined3d_mutex_unlock();
5128 return DDERR_INVALIDPARAMS;
5132 if (surface->is_root)
5133 hr = ddraw_surface_set_wined3d_textures_colour_key(surface, flags,
5134 color_key ? (struct wined3d_color_key *)&fixed_color_key : NULL);
5136 wined3d_mutex_unlock();
5138 return hr_ddraw_from_wined3d(hr);
5141 static HRESULT WINAPI ddraw_surface7_SetColorKey(IDirectDrawSurface7 *iface, DWORD flags, DDCOLORKEY *color_key)
5143 struct ddraw_surface *surface = impl_from_IDirectDrawSurface7(iface);
5145 TRACE("iface %p, flags %#lx, color_key %p.\n", iface, flags, color_key);
5147 if (surface->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_MIPMAPSUBLEVEL)
5148 return DDERR_NOTONMIPMAPSUBLEVEL;
5150 return ddraw_surface_set_color_key(surface, flags, color_key);
5153 static HRESULT WINAPI ddraw_surface4_SetColorKey(IDirectDrawSurface4 *iface, DWORD flags, DDCOLORKEY *color_key)
5155 struct ddraw_surface *surface = impl_from_IDirectDrawSurface4(iface);
5157 TRACE("iface %p, flags %#lx, color_key %p.\n", iface, flags, color_key);
5159 return ddraw_surface_set_color_key(surface, flags, color_key);
5162 static HRESULT WINAPI ddraw_surface3_SetColorKey(IDirectDrawSurface3 *iface, DWORD flags, DDCOLORKEY *color_key)
5164 struct ddraw_surface *surface = impl_from_IDirectDrawSurface3(iface);
5166 TRACE("iface %p, flags %#lx, color_key %p.\n", iface, flags, color_key);
5168 return ddraw_surface_set_color_key(surface, flags, color_key);
5171 static HRESULT WINAPI ddraw_surface2_SetColorKey(IDirectDrawSurface2 *iface, DWORD flags, DDCOLORKEY *color_key)
5173 struct ddraw_surface *surface = impl_from_IDirectDrawSurface2(iface);
5175 TRACE("iface %p, flags %#lx, color_key %p.\n", iface, flags, color_key);
5177 return ddraw_surface_set_color_key(surface, flags, color_key);
5180 static HRESULT WINAPI ddraw_surface1_SetColorKey(IDirectDrawSurface *iface, DWORD flags, DDCOLORKEY *color_key)
5182 struct ddraw_surface *surface = impl_from_IDirectDrawSurface(iface);
5184 TRACE("iface %p, flags %#lx, color_key %p.\n", iface, flags, color_key);
5186 return ddraw_surface_set_color_key(surface, flags, color_key);
5189 static HRESULT WINAPI ddraw_surface7_SetPalette(IDirectDrawSurface7 *iface, IDirectDrawPalette *palette)
5191 struct ddraw_surface *surface = impl_from_IDirectDrawSurface7(iface);
5193 TRACE("iface %p, palette %p.\n", iface, palette);
5195 if (surface->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_MIPMAPSUBLEVEL)
5196 return DDERR_NOTONMIPMAPSUBLEVEL;
5197 if (ddraw_surface_is_lost(surface))
5199 WARN("Surface lost, returning DDERR_SURFACELOST.\n");
5200 return DDERR_SURFACELOST;
5203 return ddraw_surface_set_palette(surface, palette);
5206 static HRESULT WINAPI ddraw_surface4_SetPalette(IDirectDrawSurface4 *iface, IDirectDrawPalette *palette)
5208 struct ddraw_surface *surface = impl_from_IDirectDrawSurface4(iface);
5210 TRACE("iface %p, palette %p.\n", iface, palette);
5212 if (ddraw_surface_is_lost(surface))
5214 WARN("Surface lost, returning DDERR_SURFACELOST.\n");
5215 return DDERR_SURFACELOST;
5218 return ddraw_surface_set_palette(surface, palette);
5221 static HRESULT WINAPI ddraw_surface3_SetPalette(IDirectDrawSurface3 *iface, IDirectDrawPalette *palette)
5223 struct ddraw_surface *surface = impl_from_IDirectDrawSurface3(iface);
5225 TRACE("iface %p, palette %p.\n", iface, palette);
5227 if (ddraw_surface_is_lost(surface))
5229 WARN("Surface lost, returning DDERR_SURFACELOST.\n");
5230 return DDERR_SURFACELOST;
5233 return ddraw_surface_set_palette(surface, palette);
5236 static HRESULT WINAPI ddraw_surface2_SetPalette(IDirectDrawSurface2 *iface, IDirectDrawPalette *palette)
5238 struct ddraw_surface *surface = impl_from_IDirectDrawSurface2(iface);
5240 TRACE("iface %p, palette %p.\n", iface, palette);
5242 if (ddraw_surface_is_lost(surface))
5244 WARN("Surface lost, returning DDERR_SURFACELOST.\n");
5245 return DDERR_SURFACELOST;
5248 return ddraw_surface_set_palette(surface, palette);
5251 static HRESULT WINAPI ddraw_surface1_SetPalette(IDirectDrawSurface *iface, IDirectDrawPalette *palette)
5253 struct ddraw_surface *surface = impl_from_IDirectDrawSurface(iface);
5255 TRACE("iface %p, palette %p.\n", iface, palette);
5257 if (ddraw_surface_is_lost(surface))
5259 WARN("Surface lost, returning DDERR_SURFACELOST.\n");
5260 return DDERR_SURFACELOST;
5263 return ddraw_surface_set_palette(surface, palette);
5266 /**********************************************************
5267 * IDirectDrawGammaControl::GetGammaRamp
5269 * Returns the current gamma ramp for a surface
5271 * Params:
5272 * flags: Ignored
5273 * gamma_ramp: Address to write the ramp to
5275 * Returns:
5276 * DD_OK on success
5277 * DDERR_INVALIDPARAMS if gamma_ramp is NULL
5279 **********************************************************/
5280 static HRESULT WINAPI ddraw_gamma_control_GetGammaRamp(IDirectDrawGammaControl *iface,
5281 DWORD flags, DDGAMMARAMP *gamma_ramp)
5283 struct ddraw_surface *surface = impl_from_IDirectDrawGammaControl(iface);
5285 TRACE("iface %p, flags %#lx, gamma_ramp %p.\n", iface, flags, gamma_ramp);
5287 if (!gamma_ramp)
5289 WARN("Invalid gamma_ramp passed.\n");
5290 return DDERR_INVALIDPARAMS;
5293 wined3d_mutex_lock();
5294 if (surface->surface_desc.ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE)
5296 /* Note: DDGAMMARAMP is compatible with struct wined3d_gamma_ramp. */
5297 wined3d_device_get_gamma_ramp(surface->ddraw->wined3d_device, 0, (struct wined3d_gamma_ramp *)gamma_ramp);
5299 else
5301 ERR("Not implemented for non-primary surfaces.\n");
5303 wined3d_mutex_unlock();
5305 return DD_OK;
5308 /**********************************************************
5309 * IDirectDrawGammaControl::SetGammaRamp
5311 * Sets the red, green and blue gamma ramps for
5313 * Params:
5314 * flags: Can be DDSGR_CALIBRATE to request calibration
5315 * gamma_ramp: Structure containing the new gamma ramp
5317 * Returns:
5318 * DD_OK on success
5319 * DDERR_INVALIDPARAMS if gamma_ramp is NULL
5321 **********************************************************/
5322 static HRESULT WINAPI ddraw_gamma_control_SetGammaRamp(IDirectDrawGammaControl *iface,
5323 DWORD flags, DDGAMMARAMP *gamma_ramp)
5325 struct ddraw_surface *surface = impl_from_IDirectDrawGammaControl(iface);
5327 TRACE("iface %p, flags %#lx, gamma_ramp %p.\n", iface, flags, gamma_ramp);
5329 if (!gamma_ramp)
5331 WARN("Invalid gamma_ramp passed.\n");
5332 return DDERR_INVALIDPARAMS;
5335 wined3d_mutex_lock();
5336 if (surface->surface_desc.ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE)
5338 /* Note: DDGAMMARAMP is compatible with struct wined3d_gamma_ramp. */
5339 wined3d_device_set_gamma_ramp(surface->ddraw->wined3d_device,
5340 0, flags, (struct wined3d_gamma_ramp *)gamma_ramp);
5342 else
5344 ERR("Not implemented for non-primary surfaces.\n");
5346 wined3d_mutex_unlock();
5348 return DD_OK;
5351 /*****************************************************************************
5352 * IDirect3DTexture2::PaletteChanged
5354 * Informs the texture about a palette change
5356 * Params:
5357 * start: Start index of the change
5358 * count: The number of changed entries
5360 * Returns
5361 * D3D_OK, because it's a stub
5363 *****************************************************************************/
5364 static HRESULT WINAPI d3d_texture2_PaletteChanged(IDirect3DTexture2 *iface, DWORD start, DWORD count)
5366 FIXME("iface %p, start %lu, count %lu stub!\n", iface, start, count);
5368 return D3D_OK;
5371 static HRESULT WINAPI d3d_texture1_PaletteChanged(IDirect3DTexture *iface, DWORD start, DWORD count)
5373 struct ddraw_surface *surface = impl_from_IDirect3DTexture(iface);
5375 TRACE("iface %p, start %lu, count %lu.\n", iface, start, count);
5377 return d3d_texture2_PaletteChanged(&surface->IDirect3DTexture2_iface, start, count);
5380 /*****************************************************************************
5381 * IDirect3DTexture::Unload
5383 * DX5 SDK: "The IDirect3DTexture2::Unload method is not implemented
5386 * Returns:
5387 * DDERR_UNSUPPORTED
5389 *****************************************************************************/
5390 static HRESULT WINAPI d3d_texture1_Unload(IDirect3DTexture *iface)
5392 WARN("iface %p. Not implemented.\n", iface);
5394 return DDERR_UNSUPPORTED;
5397 /*****************************************************************************
5398 * IDirect3DTexture2::GetHandle
5400 * Returns handle for the texture.
5402 * Params:
5403 * device: Device this handle is assigned to
5404 * handle: Address to store the handle at.
5406 * Returns:
5407 * D3D_OK
5409 *****************************************************************************/
5410 static HRESULT WINAPI d3d_texture2_GetHandle(IDirect3DTexture2 *iface,
5411 IDirect3DDevice2 *device, D3DTEXTUREHANDLE *handle)
5413 struct ddraw_surface *surface = impl_from_IDirect3DTexture2(iface);
5414 struct d3d_device *device_impl = unsafe_impl_from_IDirect3DDevice2(device);
5416 TRACE("iface %p, device %p, handle %p.\n", iface, device, handle);
5418 wined3d_mutex_lock();
5420 if (!surface->Handle)
5422 DWORD h = ddraw_allocate_handle(&device_impl->handle_table, surface, DDRAW_HANDLE_SURFACE);
5423 if (h == DDRAW_INVALID_HANDLE)
5425 ERR("Failed to allocate a texture handle.\n");
5426 wined3d_mutex_unlock();
5427 return DDERR_OUTOFMEMORY;
5430 surface->Handle = h + 1;
5433 TRACE("Returning handle %08lx.\n", surface->Handle);
5434 *handle = surface->Handle;
5436 wined3d_mutex_unlock();
5438 return D3D_OK;
5441 static HRESULT WINAPI d3d_texture1_GetHandle(IDirect3DTexture *iface,
5442 IDirect3DDevice *device, D3DTEXTUREHANDLE *handle)
5444 struct ddraw_surface *surface = impl_from_IDirect3DTexture(iface);
5445 struct d3d_device *device_impl = unsafe_impl_from_IDirect3DDevice(device);
5447 TRACE("iface %p, device %p, handle %p.\n", iface, device, handle);
5449 return d3d_texture2_GetHandle(&surface->IDirect3DTexture2_iface,
5450 device_impl ? &device_impl->IDirect3DDevice2_iface : NULL, handle);
5453 /*****************************************************************************
5454 * get_sub_mimaplevel
5456 * Helper function that returns the next mipmap level
5458 * tex_ptr: Surface of which to return the next level
5460 *****************************************************************************/
5461 static struct ddraw_surface *get_sub_mimaplevel(struct ddraw_surface *surface)
5463 /* Now go down the mipmap chain to the next surface */
5464 static DDSCAPS2 mipmap_caps = { DDSCAPS_MIPMAP | DDSCAPS_TEXTURE, 0, 0, {0} };
5465 IDirectDrawSurface7 *next_level;
5466 HRESULT hr;
5468 hr = ddraw_surface7_GetAttachedSurface(&surface->IDirectDrawSurface7_iface, &mipmap_caps, &next_level);
5469 if (FAILED(hr)) return NULL;
5471 ddraw_surface7_Release(next_level);
5473 return impl_from_IDirectDrawSurface7(next_level);
5476 /*****************************************************************************
5477 * IDirect3DTexture2::Load
5479 * Loads a texture created with the DDSCAPS_ALLOCONLOAD
5481 * This function isn't relayed to WineD3D because the whole interface is
5482 * implemented in DDraw only. For speed improvements an implementation which
5483 * takes OpenGL more into account could be placed into WineD3D.
5485 * Params:
5486 * src_texture: Address of the texture to load
5488 * Returns:
5489 * D3D_OK on success
5490 * D3DERR_TEXTURE_LOAD_FAILED.
5492 *****************************************************************************/
5493 static HRESULT WINAPI d3d_texture2_Load(IDirect3DTexture2 *iface, IDirect3DTexture2 *src_texture)
5495 struct ddraw_surface *dst_surface = impl_from_IDirect3DTexture2(iface);
5496 struct ddraw_surface *src_surface = unsafe_impl_from_IDirect3DTexture2(src_texture);
5497 struct wined3d_resource *dst_resource, *src_resource;
5498 HRESULT hr;
5500 TRACE("iface %p, src_texture %p.\n", iface, src_texture);
5502 if (src_surface == dst_surface)
5504 TRACE("copying surface %p to surface %p, why?\n", src_surface, dst_surface);
5505 return D3D_OK;
5508 wined3d_mutex_lock();
5510 dst_resource = wined3d_texture_get_resource(ddraw_surface_get_default_texture(dst_surface, DDRAW_SURFACE_WRITE));
5511 src_resource = wined3d_texture_get_resource(ddraw_surface_get_default_texture(src_surface, DDRAW_SURFACE_READ));
5513 if (((src_surface->surface_desc.ddsCaps.dwCaps & DDSCAPS_MIPMAP)
5514 != (dst_surface->surface_desc.ddsCaps.dwCaps & DDSCAPS_MIPMAP))
5515 || (src_surface->surface_desc.u2.dwMipMapCount != dst_surface->surface_desc.u2.dwMipMapCount))
5517 ERR("Trying to load surfaces with different mip-map counts.\n");
5520 for (;;)
5522 struct ddraw_palette *dst_pal, *src_pal;
5523 DDSURFACEDESC *src_desc, *dst_desc;
5525 TRACE("Copying surface %p to surface %p.\n", src_surface, dst_surface);
5527 /* Suppress the ALLOCONLOAD flag */
5528 dst_surface->surface_desc.ddsCaps.dwCaps &= ~DDSCAPS_ALLOCONLOAD;
5530 /* Get the palettes */
5531 dst_pal = dst_surface->palette;
5532 src_pal = src_surface->palette;
5534 if (src_pal)
5536 PALETTEENTRY palent[256];
5538 if (!dst_pal)
5540 wined3d_mutex_unlock();
5541 return DDERR_NOPALETTEATTACHED;
5543 IDirectDrawPalette_GetEntries(&src_pal->IDirectDrawPalette_iface, 0, 0, 256, palent);
5544 IDirectDrawPalette_SetEntries(&dst_pal->IDirectDrawPalette_iface, 0, 0, 256, palent);
5547 /* Copy one surface on the other */
5548 dst_desc = (DDSURFACEDESC *)&(dst_surface->surface_desc);
5549 src_desc = (DDSURFACEDESC *)&(src_surface->surface_desc);
5551 if ((src_desc->dwWidth != dst_desc->dwWidth) || (src_desc->dwHeight != dst_desc->dwHeight))
5553 /* Should also check for same pixel format, u1.lPitch, ... */
5554 ERR("Error in surface sizes.\n");
5555 wined3d_mutex_unlock();
5556 return D3DERR_TEXTURE_LOAD_FAILED;
5558 else
5560 struct wined3d_map_desc src_map_desc, dst_map_desc;
5562 /* Copy the src blit color key if the source has one, don't erase
5563 * the destination's ckey if the source has none */
5564 if (src_desc->dwFlags & DDSD_CKSRCBLT)
5566 IDirectDrawSurface7_SetColorKey(&dst_surface->IDirectDrawSurface7_iface,
5567 DDCKEY_SRCBLT, &src_desc->ddckCKSrcBlt);
5570 if (FAILED(hr = wined3d_resource_map(src_resource,
5571 src_surface->sub_resource_idx, &src_map_desc, NULL, WINED3D_MAP_READ)))
5573 ERR("Failed to lock source surface, hr %#lx.\n", hr);
5574 wined3d_mutex_unlock();
5575 return D3DERR_TEXTURE_LOAD_FAILED;
5578 if (FAILED(hr = wined3d_resource_map(dst_resource,
5579 dst_surface->sub_resource_idx, &dst_map_desc, NULL, WINED3D_MAP_WRITE)))
5581 ERR("Failed to lock destination surface, hr %#lx.\n", hr);
5582 wined3d_resource_unmap(src_resource, src_surface->sub_resource_idx);
5583 wined3d_mutex_unlock();
5584 return D3DERR_TEXTURE_LOAD_FAILED;
5587 if (dst_surface->surface_desc.u4.ddpfPixelFormat.dwFlags & DDPF_FOURCC)
5588 memcpy(dst_map_desc.data, src_map_desc.data, src_surface->surface_desc.u1.dwLinearSize);
5589 else
5590 memcpy(dst_map_desc.data, src_map_desc.data, src_map_desc.row_pitch * src_desc->dwHeight);
5592 wined3d_resource_unmap(dst_resource, dst_surface->sub_resource_idx);
5593 wined3d_resource_unmap(src_resource, src_surface->sub_resource_idx);
5596 if (src_surface->surface_desc.ddsCaps.dwCaps & DDSCAPS_MIPMAP)
5597 src_surface = get_sub_mimaplevel(src_surface);
5598 else
5599 src_surface = NULL;
5601 if (dst_surface->surface_desc.ddsCaps.dwCaps & DDSCAPS_MIPMAP)
5602 dst_surface = get_sub_mimaplevel(dst_surface);
5603 else
5604 dst_surface = NULL;
5606 if (!src_surface || !dst_surface)
5608 if (src_surface != dst_surface)
5609 ERR("Loading surface with different mipmap structure.\n");
5610 break;
5614 wined3d_mutex_unlock();
5616 return hr;
5619 static HRESULT WINAPI d3d_texture1_Load(IDirect3DTexture *iface, IDirect3DTexture *src_texture)
5621 struct ddraw_surface *dst_surface = impl_from_IDirect3DTexture(iface);
5622 struct ddraw_surface *src_surface = unsafe_impl_from_IDirect3DTexture(src_texture);
5624 TRACE("iface %p, src_texture %p.\n", iface, src_texture);
5626 return d3d_texture2_Load(&dst_surface->IDirect3DTexture2_iface,
5627 src_surface ? &src_surface->IDirect3DTexture2_iface : NULL);
5630 /*****************************************************************************
5631 * The VTable
5632 *****************************************************************************/
5634 /* Some windowed mode wrappers expect this vtbl to be writable. */
5635 static struct IDirectDrawSurface7Vtbl ddraw_surface7_vtbl =
5637 /* IUnknown */
5638 ddraw_surface7_QueryInterface,
5639 ddraw_surface7_AddRef,
5640 ddraw_surface7_Release,
5641 /* IDirectDrawSurface */
5642 ddraw_surface7_AddAttachedSurface,
5643 ddraw_surface7_AddOverlayDirtyRect,
5644 ddraw_surface7_Blt,
5645 ddraw_surface7_BltBatch,
5646 ddraw_surface7_BltFast,
5647 ddraw_surface7_DeleteAttachedSurface,
5648 ddraw_surface7_EnumAttachedSurfaces,
5649 ddraw_surface7_EnumOverlayZOrders,
5650 ddraw_surface7_Flip,
5651 ddraw_surface7_GetAttachedSurface,
5652 ddraw_surface7_GetBltStatus,
5653 ddraw_surface7_GetCaps,
5654 ddraw_surface7_GetClipper,
5655 ddraw_surface7_GetColorKey,
5656 ddraw_surface7_GetDC,
5657 ddraw_surface7_GetFlipStatus,
5658 ddraw_surface7_GetOverlayPosition,
5659 ddraw_surface7_GetPalette,
5660 ddraw_surface7_GetPixelFormat,
5661 ddraw_surface7_GetSurfaceDesc,
5662 ddraw_surface7_Initialize,
5663 ddraw_surface7_IsLost,
5664 ddraw_surface7_Lock,
5665 ddraw_surface7_ReleaseDC,
5666 ddraw_surface7_Restore,
5667 ddraw_surface7_SetClipper,
5668 ddraw_surface7_SetColorKey,
5669 ddraw_surface7_SetOverlayPosition,
5670 ddraw_surface7_SetPalette,
5671 ddraw_surface7_Unlock,
5672 ddraw_surface7_UpdateOverlay,
5673 ddraw_surface7_UpdateOverlayDisplay,
5674 ddraw_surface7_UpdateOverlayZOrder,
5675 /* IDirectDrawSurface2 */
5676 ddraw_surface7_GetDDInterface,
5677 ddraw_surface7_PageLock,
5678 ddraw_surface7_PageUnlock,
5679 /* IDirectDrawSurface3 */
5680 ddraw_surface7_SetSurfaceDesc,
5681 /* IDirectDrawSurface4 */
5682 ddraw_surface7_SetPrivateData,
5683 ddraw_surface7_GetPrivateData,
5684 ddraw_surface7_FreePrivateData,
5685 ddraw_surface7_GetUniquenessValue,
5686 ddraw_surface7_ChangeUniquenessValue,
5687 /* IDirectDrawSurface7 */
5688 ddraw_surface7_SetPriority,
5689 ddraw_surface7_GetPriority,
5690 ddraw_surface7_SetLOD,
5691 ddraw_surface7_GetLOD,
5694 /* Some windowed mode wrappers expect this vtbl to be writable. */
5695 static struct IDirectDrawSurface4Vtbl ddraw_surface4_vtbl =
5697 /* IUnknown */
5698 ddraw_surface4_QueryInterface,
5699 ddraw_surface4_AddRef,
5700 ddraw_surface4_Release,
5701 /* IDirectDrawSurface */
5702 ddraw_surface4_AddAttachedSurface,
5703 ddraw_surface4_AddOverlayDirtyRect,
5704 ddraw_surface4_Blt,
5705 ddraw_surface4_BltBatch,
5706 ddraw_surface4_BltFast,
5707 ddraw_surface4_DeleteAttachedSurface,
5708 ddraw_surface4_EnumAttachedSurfaces,
5709 ddraw_surface4_EnumOverlayZOrders,
5710 ddraw_surface4_Flip,
5711 ddraw_surface4_GetAttachedSurface,
5712 ddraw_surface4_GetBltStatus,
5713 ddraw_surface4_GetCaps,
5714 ddraw_surface4_GetClipper,
5715 ddraw_surface4_GetColorKey,
5716 ddraw_surface4_GetDC,
5717 ddraw_surface4_GetFlipStatus,
5718 ddraw_surface4_GetOverlayPosition,
5719 ddraw_surface4_GetPalette,
5720 ddraw_surface4_GetPixelFormat,
5721 ddraw_surface4_GetSurfaceDesc,
5722 ddraw_surface4_Initialize,
5723 ddraw_surface4_IsLost,
5724 ddraw_surface4_Lock,
5725 ddraw_surface4_ReleaseDC,
5726 ddraw_surface4_Restore,
5727 ddraw_surface4_SetClipper,
5728 ddraw_surface4_SetColorKey,
5729 ddraw_surface4_SetOverlayPosition,
5730 ddraw_surface4_SetPalette,
5731 ddraw_surface4_Unlock,
5732 ddraw_surface4_UpdateOverlay,
5733 ddraw_surface4_UpdateOverlayDisplay,
5734 ddraw_surface4_UpdateOverlayZOrder,
5735 /* IDirectDrawSurface2 */
5736 ddraw_surface4_GetDDInterface,
5737 ddraw_surface4_PageLock,
5738 ddraw_surface4_PageUnlock,
5739 /* IDirectDrawSurface3 */
5740 ddraw_surface4_SetSurfaceDesc,
5741 /* IDirectDrawSurface4 */
5742 ddraw_surface4_SetPrivateData,
5743 ddraw_surface4_GetPrivateData,
5744 ddraw_surface4_FreePrivateData,
5745 ddraw_surface4_GetUniquenessValue,
5746 ddraw_surface4_ChangeUniquenessValue,
5749 /* Some windowed mode wrappers expect this vtbl to be writable. */
5750 static struct IDirectDrawSurface3Vtbl ddraw_surface3_vtbl =
5752 /* IUnknown */
5753 ddraw_surface3_QueryInterface,
5754 ddraw_surface3_AddRef,
5755 ddraw_surface3_Release,
5756 /* IDirectDrawSurface */
5757 ddraw_surface3_AddAttachedSurface,
5758 ddraw_surface3_AddOverlayDirtyRect,
5759 ddraw_surface3_Blt,
5760 ddraw_surface3_BltBatch,
5761 ddraw_surface3_BltFast,
5762 ddraw_surface3_DeleteAttachedSurface,
5763 ddraw_surface3_EnumAttachedSurfaces,
5764 ddraw_surface3_EnumOverlayZOrders,
5765 ddraw_surface3_Flip,
5766 ddraw_surface3_GetAttachedSurface,
5767 ddraw_surface3_GetBltStatus,
5768 ddraw_surface3_GetCaps,
5769 ddraw_surface3_GetClipper,
5770 ddraw_surface3_GetColorKey,
5771 ddraw_surface3_GetDC,
5772 ddraw_surface3_GetFlipStatus,
5773 ddraw_surface3_GetOverlayPosition,
5774 ddraw_surface3_GetPalette,
5775 ddraw_surface3_GetPixelFormat,
5776 ddraw_surface3_GetSurfaceDesc,
5777 ddraw_surface3_Initialize,
5778 ddraw_surface3_IsLost,
5779 ddraw_surface3_Lock,
5780 ddraw_surface3_ReleaseDC,
5781 ddraw_surface3_Restore,
5782 ddraw_surface3_SetClipper,
5783 ddraw_surface3_SetColorKey,
5784 ddraw_surface3_SetOverlayPosition,
5785 ddraw_surface3_SetPalette,
5786 ddraw_surface3_Unlock,
5787 ddraw_surface3_UpdateOverlay,
5788 ddraw_surface3_UpdateOverlayDisplay,
5789 ddraw_surface3_UpdateOverlayZOrder,
5790 /* IDirectDrawSurface2 */
5791 ddraw_surface3_GetDDInterface,
5792 ddraw_surface3_PageLock,
5793 ddraw_surface3_PageUnlock,
5794 /* IDirectDrawSurface3 */
5795 ddraw_surface3_SetSurfaceDesc,
5798 /* Some windowed mode wrappers expect this vtbl to be writable. */
5799 static struct IDirectDrawSurface2Vtbl ddraw_surface2_vtbl =
5801 /* IUnknown */
5802 ddraw_surface2_QueryInterface,
5803 ddraw_surface2_AddRef,
5804 ddraw_surface2_Release,
5805 /* IDirectDrawSurface */
5806 ddraw_surface2_AddAttachedSurface,
5807 ddraw_surface2_AddOverlayDirtyRect,
5808 ddraw_surface2_Blt,
5809 ddraw_surface2_BltBatch,
5810 ddraw_surface2_BltFast,
5811 ddraw_surface2_DeleteAttachedSurface,
5812 ddraw_surface2_EnumAttachedSurfaces,
5813 ddraw_surface2_EnumOverlayZOrders,
5814 ddraw_surface2_Flip,
5815 ddraw_surface2_GetAttachedSurface,
5816 ddraw_surface2_GetBltStatus,
5817 ddraw_surface2_GetCaps,
5818 ddraw_surface2_GetClipper,
5819 ddraw_surface2_GetColorKey,
5820 ddraw_surface2_GetDC,
5821 ddraw_surface2_GetFlipStatus,
5822 ddraw_surface2_GetOverlayPosition,
5823 ddraw_surface2_GetPalette,
5824 ddraw_surface2_GetPixelFormat,
5825 ddraw_surface2_GetSurfaceDesc,
5826 ddraw_surface2_Initialize,
5827 ddraw_surface2_IsLost,
5828 ddraw_surface2_Lock,
5829 ddraw_surface2_ReleaseDC,
5830 ddraw_surface2_Restore,
5831 ddraw_surface2_SetClipper,
5832 ddraw_surface2_SetColorKey,
5833 ddraw_surface2_SetOverlayPosition,
5834 ddraw_surface2_SetPalette,
5835 ddraw_surface2_Unlock,
5836 ddraw_surface2_UpdateOverlay,
5837 ddraw_surface2_UpdateOverlayDisplay,
5838 ddraw_surface2_UpdateOverlayZOrder,
5839 /* IDirectDrawSurface2 */
5840 ddraw_surface2_GetDDInterface,
5841 ddraw_surface2_PageLock,
5842 ddraw_surface2_PageUnlock,
5845 /* Bad Mojo Redux expects this vtbl to be writable. */
5846 static struct IDirectDrawSurfaceVtbl ddraw_surface1_vtbl =
5848 /* IUnknown */
5849 ddraw_surface1_QueryInterface,
5850 ddraw_surface1_AddRef,
5851 ddraw_surface1_Release,
5852 /* IDirectDrawSurface */
5853 ddraw_surface1_AddAttachedSurface,
5854 ddraw_surface1_AddOverlayDirtyRect,
5855 ddraw_surface1_Blt,
5856 ddraw_surface1_BltBatch,
5857 ddraw_surface1_BltFast,
5858 ddraw_surface1_DeleteAttachedSurface,
5859 ddraw_surface1_EnumAttachedSurfaces,
5860 ddraw_surface1_EnumOverlayZOrders,
5861 ddraw_surface1_Flip,
5862 ddraw_surface1_GetAttachedSurface,
5863 ddraw_surface1_GetBltStatus,
5864 ddraw_surface1_GetCaps,
5865 ddraw_surface1_GetClipper,
5866 ddraw_surface1_GetColorKey,
5867 ddraw_surface1_GetDC,
5868 ddraw_surface1_GetFlipStatus,
5869 ddraw_surface1_GetOverlayPosition,
5870 ddraw_surface1_GetPalette,
5871 ddraw_surface1_GetPixelFormat,
5872 ddraw_surface1_GetSurfaceDesc,
5873 ddraw_surface1_Initialize,
5874 ddraw_surface1_IsLost,
5875 ddraw_surface1_Lock,
5876 ddraw_surface1_ReleaseDC,
5877 ddraw_surface1_Restore,
5878 ddraw_surface1_SetClipper,
5879 ddraw_surface1_SetColorKey,
5880 ddraw_surface1_SetOverlayPosition,
5881 ddraw_surface1_SetPalette,
5882 ddraw_surface1_Unlock,
5883 ddraw_surface1_UpdateOverlay,
5884 ddraw_surface1_UpdateOverlayDisplay,
5885 ddraw_surface1_UpdateOverlayZOrder,
5888 static const struct IDirectDrawGammaControlVtbl ddraw_gamma_control_vtbl =
5890 ddraw_gamma_control_QueryInterface,
5891 ddraw_gamma_control_AddRef,
5892 ddraw_gamma_control_Release,
5893 ddraw_gamma_control_GetGammaRamp,
5894 ddraw_gamma_control_SetGammaRamp,
5897 static const struct IDirect3DTexture2Vtbl d3d_texture2_vtbl =
5899 d3d_texture2_QueryInterface,
5900 d3d_texture2_AddRef,
5901 d3d_texture2_Release,
5902 d3d_texture2_GetHandle,
5903 d3d_texture2_PaletteChanged,
5904 d3d_texture2_Load,
5907 static const struct IDirect3DTextureVtbl d3d_texture1_vtbl =
5909 d3d_texture1_QueryInterface,
5910 d3d_texture1_AddRef,
5911 d3d_texture1_Release,
5912 d3d_texture1_Initialize,
5913 d3d_texture1_GetHandle,
5914 d3d_texture1_PaletteChanged,
5915 d3d_texture1_Load,
5916 d3d_texture1_Unload,
5919 /* Some games (e.g. Tomb Raider 3) pass the wrong version of the
5920 * IDirectDrawSurface interface to ddraw methods. */
5921 struct ddraw_surface *unsafe_impl_from_IDirectDrawSurface7(IDirectDrawSurface7 *iface)
5923 if (!iface) return NULL;
5924 if (iface->lpVtbl != &ddraw_surface7_vtbl)
5926 HRESULT hr = IDirectDrawSurface7_QueryInterface(iface, &IID_IDirectDrawSurface7, (void **)&iface);
5927 if (FAILED(hr))
5929 WARN("Object %p doesn't expose interface IDirectDrawSurface7.\n", iface);
5930 return NULL;
5932 IDirectDrawSurface7_Release(iface);
5934 return CONTAINING_RECORD(iface, struct ddraw_surface, IDirectDrawSurface7_iface);
5937 struct ddraw_surface *unsafe_impl_from_IDirectDrawSurface4(IDirectDrawSurface4 *iface)
5939 if (!iface) return NULL;
5940 if (iface->lpVtbl != &ddraw_surface4_vtbl)
5942 HRESULT hr = IDirectDrawSurface4_QueryInterface(iface, &IID_IDirectDrawSurface4, (void **)&iface);
5943 if (FAILED(hr))
5945 WARN("Object %p doesn't expose interface IDirectDrawSurface4.\n", iface);
5946 return NULL;
5948 IDirectDrawSurface4_Release(iface);
5950 return CONTAINING_RECORD(iface, struct ddraw_surface, IDirectDrawSurface4_iface);
5953 static struct ddraw_surface *unsafe_impl_from_IDirectDrawSurface3(IDirectDrawSurface3 *iface)
5955 if (!iface) return NULL;
5956 if (iface->lpVtbl != &ddraw_surface3_vtbl)
5958 HRESULT hr = IDirectDrawSurface3_QueryInterface(iface, &IID_IDirectDrawSurface3, (void **)&iface);
5959 if (FAILED(hr))
5961 WARN("Object %p doesn't expose interface IDirectDrawSurface3.\n", iface);
5962 return NULL;
5964 IDirectDrawSurface3_Release(iface);
5966 return CONTAINING_RECORD(iface, struct ddraw_surface, IDirectDrawSurface3_iface);
5969 static struct ddraw_surface *unsafe_impl_from_IDirectDrawSurface2(IDirectDrawSurface2 *iface)
5971 if (!iface) return NULL;
5972 if (iface->lpVtbl != &ddraw_surface2_vtbl)
5974 HRESULT hr = IDirectDrawSurface2_QueryInterface(iface, &IID_IDirectDrawSurface2, (void **)&iface);
5975 if (FAILED(hr))
5977 WARN("Object %p doesn't expose interface IDirectDrawSurface2.\n", iface);
5978 return NULL;
5980 IDirectDrawSurface2_Release(iface);
5982 return CONTAINING_RECORD(iface, struct ddraw_surface, IDirectDrawSurface2_iface);
5985 struct ddraw_surface *unsafe_impl_from_IDirectDrawSurface(IDirectDrawSurface *iface)
5987 if (!iface) return NULL;
5988 if (iface->lpVtbl != &ddraw_surface1_vtbl)
5990 HRESULT hr = IDirectDrawSurface_QueryInterface(iface, &IID_IDirectDrawSurface, (void **)&iface);
5991 if (FAILED(hr))
5993 WARN("Object %p doesn't expose interface IDirectDrawSurface.\n", iface);
5994 return NULL;
5996 IDirectDrawSurface_Release(iface);
5998 return CONTAINING_RECORD(iface, struct ddraw_surface, IDirectDrawSurface_iface);
6001 struct ddraw_surface *unsafe_impl_from_IDirect3DTexture2(IDirect3DTexture2 *iface)
6003 if (!iface) return NULL;
6004 assert(iface->lpVtbl == &d3d_texture2_vtbl);
6005 return CONTAINING_RECORD(iface, struct ddraw_surface, IDirect3DTexture2_iface);
6008 struct ddraw_surface *unsafe_impl_from_IDirect3DTexture(IDirect3DTexture *iface)
6010 if (!iface) return NULL;
6011 assert(iface->lpVtbl == &d3d_texture1_vtbl);
6012 return CONTAINING_RECORD(iface, struct ddraw_surface, IDirect3DTexture_iface);
6015 static void STDMETHODCALLTYPE ddraw_surface_wined3d_object_destroyed(void *parent)
6017 struct ddraw_surface *surface = parent;
6019 TRACE("surface %p.\n", surface);
6021 /* This shouldn't happen, ddraw_surface_release_iface() should prevent the
6022 * surface from being destroyed in this case. */
6023 if (surface->first_attached != surface)
6024 ERR("Surface is still attached to surface %p.\n", surface->first_attached);
6026 while (surface->next_attached)
6027 if (FAILED(ddraw_surface_delete_attached_surface(surface,
6028 surface->next_attached, surface->next_attached->attached_iface)))
6029 ERR("DeleteAttachedSurface failed.\n");
6031 /* Having a texture handle set implies that the device still exists. */
6032 if (surface->Handle)
6033 ddraw_free_handle(&surface->ddraw->d3ddevice->handle_table, surface->Handle - 1, DDRAW_HANDLE_SURFACE);
6035 /* Reduce the ddraw surface count. */
6036 list_remove(&surface->surface_list_entry);
6038 if (surface->clipper && ddraw_clipper_is_valid(surface->clipper))
6039 IDirectDrawClipper_Release(&surface->clipper->IDirectDrawClipper_iface);
6041 if (surface == surface->ddraw->primary)
6043 surface->ddraw->primary = NULL;
6044 surface->ddraw->gdi_surface = NULL;
6047 wined3d_private_store_cleanup(&surface->private_store);
6049 if (surface->draw_texture)
6050 wined3d_texture_decref(surface->wined3d_texture);
6052 heap_free(surface);
6055 static const struct wined3d_parent_ops ddraw_surface_wined3d_parent_ops =
6057 ddraw_surface_wined3d_object_destroyed,
6060 static void ddraw_surface_init(struct ddraw_surface *surface, struct ddraw *ddraw,
6061 struct wined3d_texture *wined3d_texture, unsigned int sub_resource_idx)
6063 struct ddraw_texture *texture = wined3d_texture_get_parent(wined3d_texture);
6064 unsigned int version = texture->version;
6066 surface->IDirectDrawSurface7_iface.lpVtbl = &ddraw_surface7_vtbl;
6067 surface->IDirectDrawSurface4_iface.lpVtbl = &ddraw_surface4_vtbl;
6068 surface->IDirectDrawSurface3_iface.lpVtbl = &ddraw_surface3_vtbl;
6069 surface->IDirectDrawSurface2_iface.lpVtbl = &ddraw_surface2_vtbl;
6070 surface->IDirectDrawSurface_iface.lpVtbl = &ddraw_surface1_vtbl;
6071 surface->IDirectDrawGammaControl_iface.lpVtbl = &ddraw_gamma_control_vtbl;
6072 surface->IDirect3DTexture2_iface.lpVtbl = &d3d_texture2_vtbl;
6073 surface->IDirect3DTexture_iface.lpVtbl = &d3d_texture1_vtbl;
6074 surface->iface_count = 1;
6075 surface->version = version;
6076 surface->ddraw = ddraw;
6078 if (version == 7)
6080 surface->ref7 = 1;
6081 surface->texture_outer = (IUnknown *)&surface->IDirectDrawSurface7_iface;
6083 else if (version == 4)
6085 surface->ref4 = 1;
6086 surface->texture_outer = (IUnknown *)&surface->IDirectDrawSurface4_iface;
6088 else
6090 surface->ref1 = 1;
6091 surface->texture_outer = (IUnknown *)&surface->IDirectDrawSurface_iface;
6094 surface->first_attached = surface;
6096 wined3d_texture_incref(surface->wined3d_texture = wined3d_texture);
6097 surface->sub_resource_idx = sub_resource_idx;
6098 surface->texture_location = DDRAW_SURFACE_LOCATION_DEFAULT;
6100 wined3d_private_store_init(&surface->private_store);
6103 static void STDMETHODCALLTYPE ddraw_texture_wined3d_object_destroyed(void *parent)
6105 struct ddraw_texture *texture = parent;
6107 TRACE("texture %p, texture_memory %p.\n", texture, texture->texture_memory);
6109 heap_free(texture->texture_memory);
6110 heap_free(parent);
6113 static const struct wined3d_parent_ops ddraw_texture_wined3d_parent_ops =
6115 ddraw_texture_wined3d_object_destroyed,
6118 static HRESULT CDECL ddraw_reset_enum_callback(struct wined3d_resource *resource)
6120 return DD_OK;
6123 static HRESULT ddraw_surface_reserve_memory(struct wined3d_texture *wined3d_texture,
6124 unsigned int sub_resource_count)
6126 static const unsigned int extra_size = 0x10000;
6128 struct ddraw_texture *texture = wined3d_texture_get_parent(wined3d_texture);
6129 struct wined3d_resource_desc resource_desc;
6130 struct wined3d_sub_resource_desc desc;
6131 unsigned int pitch, slice_pitch;
6132 HRESULT hr = WINED3D_OK;
6133 unsigned int offset, i;
6135 wined3d_resource_get_desc(wined3d_texture_get_resource(wined3d_texture), &resource_desc);
6136 if (!(texture->texture_memory = heap_alloc_zero(resource_desc.size + extra_size)))
6138 ERR("Out of memory.\n");
6139 return E_OUTOFMEMORY;
6141 TRACE("texture->texture_memory %p.\n", texture->texture_memory);
6143 offset = 0;
6144 for (i = 0; i < sub_resource_count; ++i)
6146 if (FAILED(hr = wined3d_texture_get_sub_resource_desc(wined3d_texture, i, &desc)))
6148 ERR("Subresource %u not found.\n", i);
6149 heap_free(texture->texture_memory);
6150 texture->texture_memory = NULL;
6151 return hr;
6153 wined3d_texture_get_pitch(wined3d_texture, i, &pitch, &slice_pitch);
6155 if (FAILED(hr = wined3d_texture_update_desc(wined3d_texture, i,
6156 (BYTE *)texture->texture_memory + offset, pitch)))
6158 heap_free(texture->texture_memory);
6159 texture->texture_memory = NULL;
6160 break;
6162 offset += desc.size;
6164 return hr;
6167 static void wined3d_resource_desc_from_ddraw(struct ddraw *ddraw,
6168 struct wined3d_resource_desc *wined3d_desc, const DDSURFACEDESC2 *desc)
6170 const DWORD caps = desc->ddsCaps.dwCaps;
6171 const DWORD caps2 = desc->ddsCaps.dwCaps2;
6173 wined3d_desc->resource_type = WINED3D_RTYPE_TEXTURE_2D;
6174 wined3d_desc->format = wined3dformat_from_ddrawformat(&desc->u4.ddpfPixelFormat);
6175 wined3d_desc->multisample_type = WINED3D_MULTISAMPLE_NONE;
6176 wined3d_desc->multisample_quality = 0;
6177 wined3d_desc->usage = WINED3DUSAGE_VIDMEM_ACCOUNTING;
6178 wined3d_desc->bind_flags = 0;
6179 wined3d_desc->access = WINED3D_RESOURCE_ACCESS_GPU | WINED3D_RESOURCE_ACCESS_MAP_R | WINED3D_RESOURCE_ACCESS_MAP_W;
6180 wined3d_desc->width = desc->dwWidth;
6181 wined3d_desc->height = desc->dwHeight;
6182 wined3d_desc->depth = 1;
6183 wined3d_desc->size = 0;
6185 if ((caps & DDSCAPS_SYSTEMMEMORY) && !(caps2 & (DDSCAPS2_TEXTUREMANAGE | DDSCAPS2_D3DTEXTUREMANAGE)))
6187 wined3d_desc->access = WINED3D_RESOURCE_ACCESS_CPU
6188 | WINED3D_RESOURCE_ACCESS_MAP_R | WINED3D_RESOURCE_ACCESS_MAP_W;
6190 else
6192 if (!(ddraw->flags & DDRAW_NO3D))
6194 if (caps & DDSCAPS_TEXTURE)
6195 wined3d_desc->bind_flags |= WINED3D_BIND_SHADER_RESOURCE;
6196 if (caps & DDSCAPS_ZBUFFER)
6197 wined3d_desc->bind_flags |= WINED3D_BIND_DEPTH_STENCIL;
6198 else if (caps & DDSCAPS_3DDEVICE)
6199 wined3d_desc->bind_flags |= WINED3D_BIND_RENDER_TARGET;
6202 if (caps2 & (DDSCAPS2_TEXTUREMANAGE | DDSCAPS2_D3DTEXTUREMANAGE))
6204 wined3d_desc->bind_flags &= ~WINED3D_BIND_RENDER_TARGET;
6205 wined3d_desc->access |= WINED3D_RESOURCE_ACCESS_CPU;
6206 wined3d_desc->usage |= WINED3DUSAGE_MANAGED;
6208 else if (caps & DDSCAPS_VIDEOMEMORY)
6210 /* Dynamic resources can't be written by the GPU. */
6211 if (!(wined3d_desc->bind_flags & (WINED3D_BIND_RENDER_TARGET | WINED3D_BIND_DEPTH_STENCIL)))
6212 wined3d_desc->usage |= WINED3DUSAGE_DYNAMIC;
6216 if (caps & DDSCAPS_OVERLAY)
6217 wined3d_desc->usage |= WINED3DUSAGE_OVERLAY;
6219 if (caps & DDSCAPS_OWNDC)
6220 wined3d_desc->usage |= WINED3DUSAGE_OWNDC;
6222 if (caps2 & DDSCAPS2_CUBEMAP)
6223 wined3d_desc->usage |= WINED3DUSAGE_LEGACY_CUBEMAP;
6226 static bool need_draw_texture(unsigned int draw_bind_flags, const struct wined3d_resource_desc *desc)
6228 if (!draw_bind_flags)
6229 return false;
6231 /* If we have a GPU texture that includes all the necessary bind flags, we
6232 * don't need a separate draw texture. */
6233 if ((desc->access & WINED3D_RESOURCE_ACCESS_GPU) && ((desc->bind_flags & draw_bind_flags) == draw_bind_flags))
6234 return false;
6236 return true;
6239 static HRESULT ddraw_texture_init(struct ddraw_texture *texture, struct ddraw *ddraw,
6240 unsigned int layers, unsigned int levels, bool sysmem_fallback, bool reserve_memory)
6242 struct wined3d_device *wined3d_device = ddraw->wined3d_device;
6243 const DDSURFACEDESC2 *desc = &texture->surface_desc;
6244 struct wined3d_texture *draw_texture = NULL;
6245 struct wined3d_resource_desc wined3d_desc;
6246 struct wined3d_texture *wined3d_texture;
6247 struct ddraw_surface *parent, *root;
6248 unsigned int bind_flags;
6249 unsigned int pitch = 0;
6250 unsigned int i, j;
6251 HRESULT hr;
6253 wined3d_resource_desc_from_ddraw(ddraw, &wined3d_desc, desc);
6255 if (wined3d_desc.format == WINED3DFMT_UNKNOWN)
6257 WARN("Unsupported / unknown pixelformat.\n");
6258 return DDERR_INVALIDPIXELFORMAT;
6261 /* Validate the pitch. */
6262 if (desc->dwFlags & DDSD_LPSURFACE)
6264 if (format_is_compressed(&desc->u4.ddpfPixelFormat))
6266 if ((desc->dwFlags & DDSD_LINEARSIZE)
6267 && desc->u1.dwLinearSize < wined3d_calculate_format_pitch(ddraw->wined3d_adapter,
6268 wined3d_desc.format, wined3d_desc.width) * ((wined3d_desc.height + 3) / 4))
6270 WARN("Invalid linear size %lu specified.\n", desc->u1.dwLinearSize);
6271 return DDERR_INVALIDPARAMS;
6274 else
6276 if (desc->u1.lPitch < wined3d_calculate_format_pitch(ddraw->wined3d_adapter,
6277 wined3d_desc.format, wined3d_desc.width) || desc->u1.lPitch & 3)
6279 WARN("Invalid pitch %lu specified.\n", desc->u1.lPitch);
6280 return DDERR_INVALIDPARAMS;
6283 pitch = desc->u1.lPitch;
6287 bind_flags = 0;
6288 if ((desc->ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP)
6289 || (desc->ddsCaps.dwCaps & DDSCAPS_TEXTURE))
6290 bind_flags |= WINED3D_BIND_SHADER_RESOURCE;
6292 if (desc->ddsCaps.dwCaps & DDSCAPS_ZBUFFER)
6293 bind_flags |= WINED3D_BIND_DEPTH_STENCIL;
6294 else if (desc->ddsCaps.dwCaps & DDSCAPS_3DDEVICE)
6295 bind_flags |= WINED3D_BIND_RENDER_TARGET;
6297 if (need_draw_texture(bind_flags, &wined3d_desc))
6299 struct wined3d_resource_desc draw_texture_desc;
6301 draw_texture_desc = wined3d_desc;
6302 draw_texture_desc.bind_flags = bind_flags;
6303 draw_texture_desc.access = WINED3D_RESOURCE_ACCESS_GPU;
6304 draw_texture_desc.usage = 0;
6306 if (FAILED(hr = wined3d_texture_create(wined3d_device, &draw_texture_desc, layers,
6307 levels, 0, NULL, texture, &ddraw_texture_wined3d_parent_ops, &draw_texture)))
6308 WARN("Failed to create draw texture, hr %#lx.\n", hr);
6311 /* Some applications assume surfaces will always be mapped at the same
6312 * address. Some of those also assume that this address is valid even when
6313 * the surface isn't mapped, and that updates done this way will be
6314 * visible on the screen. The game Nox is such an application,
6315 * Commandos: Behind Enemy Lines is another. Setting
6316 * WINED3D_TEXTURE_CREATE_GET_DC_LENIENT will ensure this. */
6318 if (draw_texture)
6320 if (FAILED(hr = wined3d_texture_create(wined3d_device, &wined3d_desc,
6321 layers, levels, WINED3D_TEXTURE_CREATE_GET_DC_LENIENT, NULL,
6322 NULL, &ddraw_null_wined3d_parent_ops, &wined3d_texture)))
6323 goto fail;
6325 wined3d_resource_set_parent(wined3d_texture_get_resource(wined3d_texture),
6326 texture, &ddraw_null_wined3d_parent_ops);
6328 else
6330 if (FAILED(hr = wined3d_texture_create(wined3d_device, &wined3d_desc,
6331 layers, levels, WINED3D_TEXTURE_CREATE_GET_DC_LENIENT, NULL,
6332 texture, &ddraw_texture_wined3d_parent_ops, &wined3d_texture)))
6333 return hr;
6336 if ((desc->dwFlags & DDSD_LPSURFACE)
6337 && FAILED(hr = wined3d_texture_update_desc(wined3d_texture, 0, desc->lpSurface, pitch)))
6339 ERR("Failed to set surface memory, hr %#lx.\n", hr);
6340 goto fail;
6343 for (i = 0; i < layers; ++i)
6345 struct ddraw_surface *prev_level = NULL;
6347 for (j = 0; j < levels; ++j)
6349 struct wined3d_sub_resource_desc wined3d_mip_desc;
6350 unsigned int sub_resource_idx = i * levels + j;
6351 unsigned int row_pitch, slice_pitch;
6352 struct ddraw_surface *mip;
6353 DDSURFACEDESC2 *mip_desc;
6355 if (!(mip = heap_alloc_zero(sizeof(*mip))))
6357 hr = DDERR_OUTOFVIDEOMEMORY;
6358 goto fail;
6361 ddraw_surface_init(mip, ddraw, wined3d_texture, sub_resource_idx);
6363 if (draw_texture)
6365 wined3d_texture_set_sub_resource_parent(draw_texture, sub_resource_idx,
6366 mip, &ddraw_surface_wined3d_parent_ops);
6367 wined3d_texture_set_sub_resource_parent(wined3d_texture, sub_resource_idx,
6368 mip, &ddraw_null_wined3d_parent_ops);
6369 wined3d_texture_incref(mip->draw_texture = draw_texture);
6371 else
6373 wined3d_texture_set_sub_resource_parent(wined3d_texture, sub_resource_idx,
6374 mip, &ddraw_surface_wined3d_parent_ops);
6377 mip->sysmem_fallback = sysmem_fallback;
6378 mip_desc = &mip->surface_desc;
6380 *mip_desc = *desc;
6382 wined3d_texture_get_pitch(wined3d_texture, j, &row_pitch, &slice_pitch);
6383 if (format_is_compressed(&desc->u4.ddpfPixelFormat))
6385 if (desc->dwFlags & DDSD_LPSURFACE)
6386 mip_desc->u1.dwLinearSize = ~0u;
6387 else
6388 mip_desc->u1.dwLinearSize = slice_pitch;
6389 mip_desc->dwFlags |= DDSD_LINEARSIZE;
6390 mip_desc->dwFlags &= ~DDSD_PITCH;
6392 else
6394 if (!(desc->dwFlags & DDSD_LPSURFACE))
6395 mip_desc->u1.lPitch = row_pitch;
6396 mip_desc->dwFlags |= DDSD_PITCH;
6397 mip_desc->dwFlags &= ~DDSD_LINEARSIZE;
6400 mip_desc->dwFlags &= ~DDSD_LPSURFACE;
6401 mip_desc->lpSurface = NULL;
6403 if (desc->ddsCaps.dwCaps & DDSCAPS_MIPMAP)
6404 mip_desc->u2.dwMipMapCount = levels - j;
6406 if (j)
6408 wined3d_texture_get_sub_resource_desc(wined3d_texture, sub_resource_idx, &wined3d_mip_desc);
6409 mip_desc->dwWidth = wined3d_mip_desc.width;
6410 mip_desc->dwHeight = wined3d_mip_desc.height;
6412 mip_desc->ddsCaps.dwCaps2 |= DDSCAPS2_MIPMAPSUBLEVEL;
6414 else
6416 mip_desc->ddsCaps.dwCaps2 &= ~DDSCAPS2_MIPMAPSUBLEVEL;
6419 if (mip_desc->ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP)
6421 mip_desc->ddsCaps.dwCaps2 &= ~DDSCAPS2_CUBEMAP_ALLFACES;
6423 switch (i)
6425 case WINED3D_CUBEMAP_FACE_POSITIVE_X:
6426 mip_desc->ddsCaps.dwCaps2 |= DDSCAPS2_CUBEMAP_POSITIVEX;
6427 break;
6428 case WINED3D_CUBEMAP_FACE_NEGATIVE_X:
6429 mip_desc->ddsCaps.dwCaps2 |= DDSCAPS2_CUBEMAP_NEGATIVEX;
6430 break;
6431 case WINED3D_CUBEMAP_FACE_POSITIVE_Y:
6432 mip_desc->ddsCaps.dwCaps2 |= DDSCAPS2_CUBEMAP_POSITIVEY;
6433 break;
6434 case WINED3D_CUBEMAP_FACE_NEGATIVE_Y:
6435 mip_desc->ddsCaps.dwCaps2 |= DDSCAPS2_CUBEMAP_NEGATIVEY;
6436 break;
6437 case WINED3D_CUBEMAP_FACE_POSITIVE_Z:
6438 mip_desc->ddsCaps.dwCaps2 |= DDSCAPS2_CUBEMAP_POSITIVEZ;
6439 break;
6440 case WINED3D_CUBEMAP_FACE_NEGATIVE_Z:
6441 mip_desc->ddsCaps.dwCaps2 |= DDSCAPS2_CUBEMAP_NEGATIVEZ;
6442 break;
6447 ddraw_update_lost_surfaces(ddraw);
6448 list_add_head(&ddraw->surface_list, &mip->surface_list_entry);
6450 TRACE("Created ddraw surface %p.\n", mip);
6452 if (!j)
6454 if (!i)
6455 texture->root = mip;
6456 else
6457 texture->root->complex_array[layers - 1 - i] = mip;
6459 else if (j == 1 && !i)
6461 texture->root->complex_array[layers - 1] = mip;
6463 else
6465 prev_level->complex_array[0] = mip;
6467 prev_level = mip;
6471 root = texture->root;
6473 wined3d_device_incref(texture->wined3d_device = ddraw->wined3d_device);
6475 ddraw_surface_sync_color_keys(root);
6477 wined3d_texture_decref(wined3d_texture);
6478 if (draw_texture)
6479 wined3d_texture_decref(draw_texture);
6481 if (reserve_memory && FAILED(hr = ddraw_surface_reserve_memory(wined3d_texture, 1)))
6483 hr = hr_ddraw_from_wined3d(hr);
6484 goto fail;
6487 TRACE("Surface %p, created draw_texture %p, wined3d_texture %p.\n", root, draw_texture, wined3d_texture);
6488 return D3D_OK;
6490 fail:
6491 if (draw_texture)
6492 wined3d_texture_decref(draw_texture);
6494 parent = wined3d_texture_get_sub_resource_parent(draw_texture, 0);
6495 if (texture->version == 7)
6496 IDirectDrawSurface7_Release(&parent->IDirectDrawSurface7_iface);
6497 else if (texture->version == 4)
6498 IDirectDrawSurface4_Release(&parent->IDirectDrawSurface4_iface);
6499 else
6500 IDirectDrawSurface_Release(&parent->IDirectDrawSurface_iface);
6501 return hr;
6504 HRESULT ddraw_surface_create(struct ddraw *ddraw, const DDSURFACEDESC2 *surface_desc,
6505 struct ddraw_surface **surface, IUnknown *outer_unknown, unsigned int version)
6507 DDPIXELFORMAT wined3d_display_mode_format;
6508 struct ddraw_surface *root, **attach;
6509 struct wined3d_display_mode mode;
6510 struct ddraw_texture *texture;
6511 BOOL sysmem_fallback = FALSE;
6512 unsigned int layers = 1;
6513 DDSURFACEDESC2 *desc;
6514 bool reserve_memory;
6515 UINT levels, i;
6516 HRESULT hr;
6518 TRACE("ddraw %p, surface_desc %p, surface %p, outer_unknown %p, version %u.\n",
6519 ddraw, surface_desc, surface, outer_unknown, version);
6520 if (TRACE_ON(ddraw))
6522 TRACE("Requesting surface desc:\n");
6523 DDRAW_dump_surface_desc(surface_desc);
6526 if (outer_unknown)
6527 return CLASS_E_NOAGGREGATION;
6529 if (!surface)
6530 return E_POINTER;
6532 if (!(texture = heap_alloc(sizeof(*texture))))
6533 return E_OUTOFMEMORY;
6535 texture->texture_memory = NULL;
6536 texture->version = version;
6537 texture->surface_desc = *surface_desc;
6538 desc = &texture->surface_desc;
6540 /* Ensure DDSD_CAPS is always set. */
6541 desc->dwFlags |= DDSD_CAPS;
6543 if ((desc->ddsCaps.dwCaps & DDSCAPS_COMPLEX)
6544 && !(desc->ddsCaps.dwCaps & (DDSCAPS_FLIP | DDSCAPS_MIPMAP))
6545 && !(desc->ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP))
6547 WARN("DDSCAPS_COMPLEX specified for a surface which is neither flippable, mipmapped, nor a cubemap.\n");
6548 heap_free(texture);
6549 return DDERR_INVALIDCAPS;
6552 if ((desc->dwFlags & DDSD_MIPMAPCOUNT) && !(desc->ddsCaps.dwCaps & DDSCAPS_COMPLEX))
6554 /* This is illegal even if there is only one mipmap level. */
6555 WARN("DDSD_MIPMAPCOUNT specified without DDSCAPS_COMPLEX.\n");
6556 heap_free(texture);
6557 return DDERR_INVALIDCAPS;
6560 if (desc->ddsCaps.dwCaps & DDSCAPS_FLIP)
6562 if (!(desc->dwFlags & DDSD_BACKBUFFERCOUNT) || !desc->u5.dwBackBufferCount)
6564 WARN("Tried to create a flippable surface without any back buffers.\n");
6565 heap_free(texture);
6566 return DDERR_INVALIDCAPS;
6569 if (!(desc->ddsCaps.dwCaps & DDSCAPS_COMPLEX))
6571 WARN("Tried to create a flippable surface without DDSCAPS_COMPLEX.\n");
6572 heap_free(texture);
6573 return DDERR_INVALIDCAPS;
6576 if (desc->ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP)
6578 WARN("Tried to create a flippable cubemap.\n");
6579 heap_free(texture);
6580 return DDERR_INVALIDPARAMS;
6583 if (desc->ddsCaps.dwCaps & DDSCAPS_TEXTURE)
6585 FIXME("Flippable textures not implemented.\n");
6586 heap_free(texture);
6587 return DDERR_INVALIDCAPS;
6590 else
6592 if (desc->dwFlags & DDSD_BACKBUFFERCOUNT)
6594 WARN("Tried to specify a back buffer count for a non-flippable surface.\n");
6595 hr = desc->ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP ? DDERR_INVALIDPARAMS : DDERR_INVALIDCAPS;
6596 heap_free(texture);
6597 return hr;
6601 if (desc->ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE)
6603 if (desc->ddsCaps.dwCaps & DDSCAPS_TEXTURE)
6605 WARN("Tried to create a primary surface with DDSCAPS_TEXTURE.\n");
6606 heap_free(texture);
6607 return DDERR_INVALIDCAPS;
6610 if ((desc->ddsCaps.dwCaps & DDSCAPS_COMPLEX) && !(desc->ddsCaps.dwCaps & DDSCAPS_FLIP))
6612 WARN("Tried to create a flippable primary surface without both DDSCAPS_FLIP and DDSCAPS_COMPLEX.\n");
6613 heap_free(texture);
6614 return DDERR_INVALIDCAPS;
6617 if ((desc->ddsCaps.dwCaps & DDSCAPS_FLIP) && !(ddraw->cooperative_level & DDSCL_EXCLUSIVE))
6619 WARN("Tried to create a flippable primary surface without DDSCL_EXCLUSIVE.\n");
6620 heap_free(texture);
6621 return DDERR_NOEXCLUSIVEMODE;
6625 /* This is a special case in ddrawex, but not allowed in ddraw. */
6626 if ((desc->ddsCaps.dwCaps & (DDSCAPS_VIDEOMEMORY | DDSCAPS_SYSTEMMEMORY))
6627 == (DDSCAPS_VIDEOMEMORY | DDSCAPS_SYSTEMMEMORY))
6629 WARN("Tried to create a surface in both system and video memory.\n");
6630 heap_free(texture);
6631 return DDERR_INVALIDCAPS;
6634 if ((desc->ddsCaps.dwCaps & (DDSCAPS_ALLOCONLOAD | DDSCAPS_MIPMAP))
6635 && !(desc->ddsCaps.dwCaps & DDSCAPS_TEXTURE))
6637 WARN("Caps %#lx require DDSCAPS_TEXTURE.\n", desc->ddsCaps.dwCaps);
6638 heap_free(texture);
6639 return DDERR_INVALIDCAPS;
6642 if ((desc->ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP_ALLFACES)
6643 && !(desc->ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP))
6645 WARN("Cube map faces requested without cube map flag.\n");
6646 heap_free(texture);
6647 return DDERR_INVALIDCAPS;
6650 if ((desc->ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP)
6651 && !(desc->ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP_ALLFACES))
6653 WARN("Cube map without faces requested.\n");
6654 heap_free(texture);
6655 return DDERR_INVALIDPARAMS;
6658 if ((desc->ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP)
6659 && (desc->ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP_ALLFACES) != DDSCAPS2_CUBEMAP_ALLFACES)
6660 FIXME("Partial cube maps not implemented.\n");
6662 if (desc->ddsCaps.dwCaps2 & (DDSCAPS2_TEXTUREMANAGE | DDSCAPS2_D3DTEXTUREMANAGE))
6664 if (!(desc->ddsCaps.dwCaps & DDSCAPS_TEXTURE))
6666 WARN("DDSCAPS2_TEXTUREMANAGE used without DDSCAPS_TEXTURE, returning DDERR_INVALIDCAPS.\n");
6667 heap_free(texture);
6668 return DDERR_INVALIDCAPS;
6670 if (desc->ddsCaps.dwCaps & (DDSCAPS_VIDEOMEMORY | DDSCAPS_SYSTEMMEMORY))
6672 WARN("DDSCAPS2_TEXTUREMANAGE used with DDSCAPS_VIDEOMEMORY "
6673 "or DDSCAPS_SYSTEMMEMORY, returning DDERR_INVALIDCAPS.\n");
6674 heap_free(texture);
6675 return DDERR_INVALIDCAPS;
6679 if (desc->ddsCaps.dwCaps & DDSCAPS_WRITEONLY
6680 && !(desc->ddsCaps.dwCaps2 & (DDSCAPS2_TEXTUREMANAGE | DDSCAPS2_D3DTEXTUREMANAGE)))
6682 WARN("DDSCAPS_WRITEONLY used without DDSCAPS2_TEXTUREMANAGE, returning DDERR_INVALIDCAPS.\n");
6683 heap_free(texture);
6684 return DDERR_INVALIDCAPS;
6687 if (FAILED(hr = wined3d_output_get_display_mode(ddraw->wined3d_output, &mode, NULL)))
6689 ERR("Failed to get display mode, hr %#lx.\n", hr);
6690 heap_free(texture);
6691 return hr_ddraw_from_wined3d(hr);
6694 wined3d_display_mode_format.dwSize = sizeof(wined3d_display_mode_format);
6695 ddrawformat_from_wined3dformat(&wined3d_display_mode_format, mode.format_id);
6697 /* No pixelformat given? Use the current screen format. */
6698 if (!(desc->dwFlags & DDSD_PIXELFORMAT))
6700 desc->dwFlags |= DDSD_PIXELFORMAT;
6701 desc->u4.ddpfPixelFormat = wined3d_display_mode_format;
6704 /* No width or no height? Use the screen size. */
6705 if (!(desc->dwFlags & DDSD_WIDTH) || !(desc->dwFlags & DDSD_HEIGHT))
6707 if (!(desc->ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE))
6709 WARN("No width / height specified.\n");
6710 heap_free(texture);
6711 return DDERR_INVALIDPARAMS;
6714 desc->dwFlags |= DDSD_WIDTH | DDSD_HEIGHT;
6715 desc->dwWidth = mode.width;
6716 desc->dwHeight = mode.height;
6719 if (!desc->dwWidth || !desc->dwHeight)
6721 heap_free(texture);
6722 return DDERR_INVALIDPARAMS;
6725 if (desc->ddsCaps.dwCaps & DDSCAPS_FLIP)
6726 desc->ddsCaps.dwCaps |= DDSCAPS_FRONTBUFFER;
6728 if (desc->ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE)
6730 /* The first surface is a front buffer, the back buffers are created
6731 * afterwards. */
6732 desc->ddsCaps.dwCaps |= DDSCAPS_VISIBLE;
6733 if (ddraw->cooperative_level & DDSCL_EXCLUSIVE)
6735 struct wined3d_swapchain_desc swapchain_desc;
6737 wined3d_swapchain_get_desc(ddraw->wined3d_swapchain, &swapchain_desc);
6738 swapchain_desc.backbuffer_width = mode.width;
6739 swapchain_desc.backbuffer_height = mode.height;
6740 swapchain_desc.backbuffer_format = mode.format_id;
6742 if (ddraw->d3ddevice)
6744 if (ddraw->d3ddevice->recording)
6745 wined3d_stateblock_decref(ddraw->d3ddevice->recording);
6746 ddraw->d3ddevice->recording = NULL;
6747 ddraw->d3ddevice->update_state = ddraw->d3ddevice->state;
6749 wined3d_stateblock_reset(ddraw->state);
6751 if (FAILED(hr = wined3d_device_reset(ddraw->wined3d_device,
6752 &swapchain_desc, NULL, ddraw_reset_enum_callback, TRUE)))
6754 ERR("Failed to reset device.\n");
6755 heap_free(texture);
6756 return hr_ddraw_from_wined3d(hr);
6759 wined3d_stateblock_set_render_state(ddraw->state, WINED3D_RS_ZENABLE,
6760 !!swapchain_desc.enable_auto_depth_stencil);
6764 if ((desc->ddsCaps.dwCaps & DDSCAPS_3DDEVICE) && (ddraw->flags & DDRAW_NO3D))
6766 WARN("The application requests a 3D capable surface, but the ddraw object was created without 3D support.\n");
6767 /* Do not fail surface creation, only fail 3D device creation. */
6770 /* Mipmap count fixes */
6771 if (desc->ddsCaps.dwCaps & DDSCAPS_MIPMAP)
6773 if (desc->ddsCaps.dwCaps & DDSCAPS_COMPLEX)
6775 if (desc->dwFlags & DDSD_MIPMAPCOUNT)
6777 /* Mipmap count is given, should not be 0. */
6778 if (!desc->u2.dwMipMapCount)
6780 heap_free(texture);
6781 return DDERR_INVALIDPARAMS;
6784 else
6786 /* Undocumented feature: Create sublevels until either the
6787 * width or the height is 1. */
6788 if (version == 7)
6789 desc->u2.dwMipMapCount = wined3d_log2i(max(desc->dwWidth, desc->dwHeight)) + 1;
6790 else
6791 desc->u2.dwMipMapCount = wined3d_log2i(min(desc->dwWidth, desc->dwHeight)) + 1;
6794 else
6796 desc->u2.dwMipMapCount = 1;
6799 desc->dwFlags |= DDSD_MIPMAPCOUNT;
6800 levels = desc->u2.dwMipMapCount;
6802 else
6804 levels = 1;
6807 if (!(desc->ddsCaps.dwCaps & (DDSCAPS_VIDEOMEMORY | DDSCAPS_SYSTEMMEMORY)))
6809 if (!(desc->ddsCaps.dwCaps2 & (DDSCAPS2_TEXTUREMANAGE | DDSCAPS2_D3DTEXTUREMANAGE)))
6811 unsigned int bind_flags = 0;
6812 DWORD usage = 0;
6814 if (desc->ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP)
6816 usage |= WINED3DUSAGE_LEGACY_CUBEMAP;
6817 bind_flags |= WINED3D_BIND_SHADER_RESOURCE;
6819 else if (desc->ddsCaps.dwCaps & DDSCAPS_TEXTURE)
6821 bind_flags |= WINED3D_BIND_SHADER_RESOURCE;
6824 if (desc->ddsCaps.dwCaps & DDSCAPS_ZBUFFER)
6825 bind_flags |= WINED3D_BIND_DEPTH_STENCIL;
6826 else if (desc->ddsCaps.dwCaps & DDSCAPS_3DDEVICE)
6827 bind_flags |= WINED3D_BIND_RENDER_TARGET;
6829 if (!(ddraw->flags & DDRAW_NO3D) && SUCCEEDED(hr = wined3d_check_device_format(ddraw->wined3d,
6830 ddraw->wined3d_adapter, WINED3D_DEVICE_TYPE_HAL, mode.format_id,
6831 usage, bind_flags, WINED3D_RTYPE_TEXTURE_2D, wined3dformat_from_ddrawformat(&desc->u4.ddpfPixelFormat))))
6833 desc->ddsCaps.dwCaps |= DDSCAPS_VIDEOMEMORY;
6835 else
6837 desc->ddsCaps.dwCaps |= DDSCAPS_SYSTEMMEMORY;
6838 sysmem_fallback = TRUE;
6841 else if (!(desc->ddsCaps.dwCaps & DDSCAPS_TEXTURE))
6843 /* Tests show surfaces without memory flags get these flags added
6844 * right after creation. */
6845 desc->ddsCaps.dwCaps |= DDSCAPS_LOCALVIDMEM | DDSCAPS_VIDEOMEMORY;
6849 if ((desc->ddsCaps.dwCaps & (DDSCAPS_OVERLAY | DDSCAPS_SYSTEMMEMORY))
6850 == (DDSCAPS_OVERLAY | DDSCAPS_SYSTEMMEMORY))
6852 WARN("System memory overlays are not allowed.\n");
6853 heap_free(texture);
6854 return DDERR_NOOVERLAYHW;
6857 if (desc->ddsCaps.dwCaps2 & (DDSCAPS2_TEXTUREMANAGE | DDSCAPS2_D3DTEXTUREMANAGE))
6858 desc->ddsCaps.dwCaps |= DDSCAPS_SYSTEMMEMORY;
6860 if (desc->ddsCaps.dwCaps & DDSCAPS_VIDEOMEMORY)
6861 desc->ddsCaps.dwCaps |= DDSCAPS_LOCALVIDMEM;
6863 if (desc->dwFlags & DDSD_LPSURFACE)
6865 if (!(desc->ddsCaps.dwCaps & DDSCAPS_SYSTEMMEMORY))
6867 WARN("User memory surfaces should not be GPU accessible.\n");
6868 heap_free(texture);
6869 return DDERR_INVALIDCAPS;
6872 if (version < 4)
6874 WARN("User memory surfaces not supported before version 4.\n");
6875 heap_free(texture);
6876 return DDERR_INVALIDPARAMS;
6879 if (!desc->lpSurface)
6881 WARN("NULL surface memory pointer specified.\n");
6882 heap_free(texture);
6883 return DDERR_INVALIDPARAMS;
6886 if (format_is_compressed(&desc->u4.ddpfPixelFormat))
6888 if (version != 4 && (desc->dwFlags & DDSD_PITCH))
6890 WARN("Pitch specified on a compressed user memory surface.\n");
6891 heap_free(texture);
6892 return DDERR_INVALIDPARAMS;
6895 if (!(desc->dwFlags & (DDSD_LINEARSIZE | DDSD_PITCH)))
6897 WARN("Compressed user memory surfaces should explicitly specify the linear size.\n");
6898 heap_free(texture);
6899 return DDERR_INVALIDPARAMS;
6902 else
6904 if (!(desc->dwFlags & DDSD_PITCH))
6906 WARN("User memory surfaces should explicitly specify the pitch.\n");
6907 heap_free(texture);
6908 return DDERR_INVALIDPARAMS;
6913 if (((desc->dwFlags & DDSD_CKDESTOVERLAY)
6914 && desc->u3.ddckCKDestOverlay.dwColorSpaceLowValue != desc->u3.ddckCKDestOverlay.dwColorSpaceHighValue)
6915 || ((desc->dwFlags & DDSD_CKDESTBLT)
6916 && desc->ddckCKDestBlt.dwColorSpaceLowValue != desc->ddckCKDestBlt.dwColorSpaceHighValue)
6917 || ((desc->dwFlags & DDSD_CKSRCOVERLAY)
6918 && desc->ddckCKSrcOverlay.dwColorSpaceLowValue != desc->ddckCKSrcOverlay.dwColorSpaceHighValue)
6919 || ((desc->dwFlags & DDSD_CKSRCBLT)
6920 && desc->ddckCKSrcBlt.dwColorSpaceLowValue != desc->ddckCKSrcBlt.dwColorSpaceHighValue))
6922 WARN("Range color keys not supported, returning DDERR_NOCOLORKEYHW.\n");
6923 heap_free(texture);
6924 return DDERR_NOCOLORKEYHW;
6927 if ((ddraw->flags & DDRAW_NO3D) && (desc->ddsCaps.dwCaps & DDSCAPS_VIDEOMEMORY))
6929 WARN("Video memory surfaces not supported without 3D support.\n");
6930 heap_free(texture);
6931 return DDERR_NODIRECTDRAWHW;
6934 if (desc->ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP)
6935 layers = 6;
6937 reserve_memory = !(desc->dwFlags & DDSD_LPSURFACE)
6938 && desc->ddsCaps.dwCaps & DDSCAPS_VIDEOMEMORY
6939 && wined3d_display_mode_format.u1.dwRGBBitCount <= 16;
6941 if (FAILED(hr = ddraw_texture_init(texture, ddraw, layers, levels, sysmem_fallback, reserve_memory)))
6943 WARN("Failed to create wined3d texture, hr %#lx.\n", hr);
6944 heap_free(texture);
6945 return hr_ddraw_from_wined3d(hr);
6948 root = texture->root;
6949 root->is_root = TRUE;
6951 if (desc->dwFlags & DDSD_BACKBUFFERCOUNT)
6953 unsigned int count = desc->u5.dwBackBufferCount;
6954 struct ddraw_surface *last = root;
6956 attach = &last->complex_array[0];
6957 for (i = 0; i < count; ++i)
6959 if (!(texture = heap_alloc(sizeof(*texture))))
6961 hr = E_OUTOFMEMORY;
6962 goto fail;
6965 texture->texture_memory = NULL;
6966 texture->version = version;
6967 texture->surface_desc = root->surface_desc;
6968 desc = &texture->surface_desc;
6970 /* Only one surface in the flipping chain is a back buffer, one is
6971 * a front buffer, the others are just flippable surfaces. */
6972 desc->ddsCaps.dwCaps &= ~(DDSCAPS_VISIBLE | DDSCAPS_PRIMARYSURFACE | DDSCAPS_FRONTBUFFER
6973 | DDSCAPS_BACKBUFFER);
6974 if (!i)
6975 desc->ddsCaps.dwCaps |= DDSCAPS_BACKBUFFER;
6976 desc->u5.dwBackBufferCount = 0;
6978 if (FAILED(hr = ddraw_texture_init(texture, ddraw, 1, 1, sysmem_fallback, reserve_memory)))
6980 heap_free(texture);
6981 hr = hr_ddraw_from_wined3d(hr);
6982 goto fail;
6985 last = texture->root;
6987 *attach = last;
6988 attach = &last->complex_array[0];
6990 *attach = root;
6993 if (surface_desc->ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE)
6995 ddraw->primary = root;
6996 ddraw->gdi_surface = root->wined3d_texture;
6998 *surface = root;
7000 return DD_OK;
7002 fail:
7003 if (version == 7)
7004 IDirectDrawSurface7_Release(&root->IDirectDrawSurface7_iface);
7005 else if (version == 4)
7006 IDirectDrawSurface4_Release(&root->IDirectDrawSurface4_iface);
7007 else
7008 IDirectDrawSurface_Release(&root->IDirectDrawSurface_iface);
7010 return hr;
7013 static void STDMETHODCALLTYPE view_wined3d_object_destroyed(void *parent)
7015 struct ddraw_surface *surface = parent;
7017 /* If the surface reference count drops to zero, we release our reference
7018 * to the view, but don't clear the pointer yet, in case e.g. a
7019 * GetRenderTarget() call brings the surface back before the view is
7020 * actually destroyed. When the view is destroyed, we need to clear the
7021 * pointer, or a subsequent surface AddRef() would reference it again.
7023 * This is safe because as long as the view still has a reference to the
7024 * texture, the surface is also still alive, and we're called before the
7025 * view releases that reference. */
7026 surface->wined3d_rtv = NULL;
7029 static const struct wined3d_parent_ops ddraw_view_wined3d_parent_ops =
7031 view_wined3d_object_destroyed,
7034 struct wined3d_rendertarget_view *ddraw_surface_get_rendertarget_view(struct ddraw_surface *surface)
7036 struct wined3d_texture *wined3d_texture;
7037 HRESULT hr;
7039 if (surface->wined3d_rtv)
7040 return surface->wined3d_rtv;
7042 wined3d_texture = surface->draw_texture ? surface->draw_texture : surface->wined3d_texture;
7043 if (FAILED(hr = wined3d_rendertarget_view_create_from_sub_resource(wined3d_texture,
7044 surface->sub_resource_idx, surface, &ddraw_view_wined3d_parent_ops, &surface->wined3d_rtv)))
7046 ERR("Failed to create rendertarget view, hr %#lx.\n", hr);
7047 return NULL;
7050 return surface->wined3d_rtv;