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