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