xref: /reactos/dll/directx/wine/ddraw/surface.c (revision f4d29a74)
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 
2350     wined3d_mutex_lock();
2351     if (!surface->dc)
2352     {
2353         hr = DDERR_NODC;
2354     }
2355     else if (SUCCEEDED(hr = wined3d_texture_release_dc(surface->wined3d_texture, surface->sub_resource_idx, hdc)))
2356     {
2357         surface->dc = NULL;
2358         if (surface->surface_desc.ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE)
2359             hr = ddraw_surface_update_frontbuffer(surface, NULL, FALSE, 0);
2360     }
2361     wined3d_mutex_unlock();
2362 
2363 
2364     return hr;
2365 }
2366 
2367 static HRESULT WINAPI ddraw_surface4_ReleaseDC(IDirectDrawSurface4 *iface, HDC dc)
2368 {
2369     struct ddraw_surface *surface = impl_from_IDirectDrawSurface4(iface);
2370 
2371     TRACE("iface %p, dc %p.\n", iface, dc);
2372 
2373     return ddraw_surface7_ReleaseDC(&surface->IDirectDrawSurface7_iface, dc);
2374 }
2375 
2376 static HRESULT WINAPI ddraw_surface3_ReleaseDC(IDirectDrawSurface3 *iface, HDC dc)
2377 {
2378     struct ddraw_surface *surface = impl_from_IDirectDrawSurface3(iface);
2379 
2380     TRACE("iface %p, dc %p.\n", iface, dc);
2381 
2382     return ddraw_surface7_ReleaseDC(&surface->IDirectDrawSurface7_iface, dc);
2383 }
2384 
2385 static HRESULT WINAPI ddraw_surface2_ReleaseDC(IDirectDrawSurface2 *iface, HDC dc)
2386 {
2387     struct ddraw_surface *surface = impl_from_IDirectDrawSurface2(iface);
2388 
2389     TRACE("iface %p, dc %p.\n", iface, dc);
2390 
2391     return ddraw_surface7_ReleaseDC(&surface->IDirectDrawSurface7_iface, dc);
2392 }
2393 
2394 static HRESULT WINAPI ddraw_surface1_ReleaseDC(IDirectDrawSurface *iface, HDC dc)
2395 {
2396     struct ddraw_surface *surface = impl_from_IDirectDrawSurface(iface);
2397 
2398     TRACE("iface %p, dc %p.\n", iface, dc);
2399 
2400     return ddraw_surface7_ReleaseDC(&surface->IDirectDrawSurface7_iface, dc);
2401 }
2402 
2403 /*****************************************************************************
2404  * IDirectDrawSurface7::GetCaps
2405  *
2406  * Returns the surface's caps
2407  *
2408  * Params:
2409  *  Caps: Address to write the caps to
2410  *
2411  * Returns:
2412  *  DD_OK on success
2413  *  DDERR_INVALIDPARAMS if Caps is NULL
2414  *
2415  *****************************************************************************/
2416 static HRESULT WINAPI ddraw_surface7_GetCaps(IDirectDrawSurface7 *iface, DDSCAPS2 *Caps)
2417 {
2418     struct ddraw_surface *surface = impl_from_IDirectDrawSurface7(iface);
2419 
2420     TRACE("iface %p, caps %p.\n", iface, Caps);
2421 
2422     if(!Caps)
2423         return DDERR_INVALIDPARAMS;
2424 
2425     *Caps = surface->surface_desc.ddsCaps;
2426 
2427     return DD_OK;
2428 }
2429 
2430 static HRESULT WINAPI ddraw_surface4_GetCaps(IDirectDrawSurface4 *iface, DDSCAPS2 *caps)
2431 {
2432     struct ddraw_surface *surface = impl_from_IDirectDrawSurface4(iface);
2433 
2434     TRACE("iface %p, caps %p.\n", iface, caps);
2435 
2436     return ddraw_surface7_GetCaps(&surface->IDirectDrawSurface7_iface, caps);
2437 }
2438 
2439 static HRESULT WINAPI ddraw_surface3_GetCaps(IDirectDrawSurface3 *iface, DDSCAPS *caps)
2440 {
2441     struct ddraw_surface *surface = impl_from_IDirectDrawSurface3(iface);
2442     DDSCAPS2 caps2;
2443     HRESULT hr;
2444 
2445     TRACE("iface %p, caps %p.\n", iface, caps);
2446 
2447     hr = ddraw_surface7_GetCaps(&surface->IDirectDrawSurface7_iface, &caps2);
2448     if (FAILED(hr)) return hr;
2449 
2450     caps->dwCaps = caps2.dwCaps;
2451     return hr;
2452 }
2453 
2454 static HRESULT WINAPI ddraw_surface2_GetCaps(IDirectDrawSurface2 *iface, DDSCAPS *caps)
2455 {
2456     struct ddraw_surface *surface = impl_from_IDirectDrawSurface2(iface);
2457     DDSCAPS2 caps2;
2458     HRESULT hr;
2459 
2460     TRACE("iface %p, caps %p.\n", iface, caps);
2461 
2462     hr = ddraw_surface7_GetCaps(&surface->IDirectDrawSurface7_iface, &caps2);
2463     if (FAILED(hr)) return hr;
2464 
2465     caps->dwCaps = caps2.dwCaps;
2466     return hr;
2467 }
2468 
2469 static HRESULT WINAPI ddraw_surface1_GetCaps(IDirectDrawSurface *iface, DDSCAPS *caps)
2470 {
2471     struct ddraw_surface *surface = impl_from_IDirectDrawSurface(iface);
2472     DDSCAPS2 caps2;
2473     HRESULT hr;
2474 
2475     TRACE("iface %p, caps %p.\n", iface, caps);
2476 
2477     hr = ddraw_surface7_GetCaps(&surface->IDirectDrawSurface7_iface, &caps2);
2478     if (FAILED(hr)) return hr;
2479 
2480     caps->dwCaps = caps2.dwCaps;
2481     return hr;
2482 }
2483 
2484 static HRESULT WINAPI ddraw_surface7_SetPriority(IDirectDrawSurface7 *iface, DWORD priority)
2485 {
2486     struct ddraw_surface *surface = impl_from_IDirectDrawSurface7(iface);
2487     DWORD managed = DDSCAPS2_TEXTUREMANAGE | DDSCAPS2_D3DTEXTUREMANAGE;
2488     HRESULT hr;
2489     struct wined3d_resource *resource;
2490 
2491     TRACE("iface %p, priority %u.\n", iface, priority);
2492 
2493     wined3d_mutex_lock();
2494     /* No need to check for offscreen plain surfaces or mipmap sublevels. SetPriority
2495      * calls on such surfaces segfault on Windows. */
2496     if (!(surface->surface_desc.ddsCaps.dwCaps2 & managed))
2497     {
2498         WARN("Called on non-managed texture returning DDERR_INVALIDPARAMS.\n");
2499         hr = DDERR_INVALIDPARAMS;
2500     }
2501     else
2502     {
2503         resource = wined3d_texture_get_resource(surface->wined3d_texture);
2504         wined3d_resource_set_priority(resource, priority);
2505         hr = DD_OK;
2506     }
2507     wined3d_mutex_unlock();
2508 
2509     return hr;
2510 }
2511 
2512 static HRESULT WINAPI ddraw_surface7_GetPriority(IDirectDrawSurface7 *iface, DWORD *priority)
2513 {
2514     struct ddraw_surface *surface = impl_from_IDirectDrawSurface7(iface);
2515     const struct wined3d_resource *resource;
2516     DWORD managed = DDSCAPS2_TEXTUREMANAGE | DDSCAPS2_D3DTEXTUREMANAGE;
2517     HRESULT hr;
2518 
2519     TRACE("iface %p, priority %p.\n", iface, priority);
2520 
2521     wined3d_mutex_lock();
2522     if (surface->surface_desc.ddsCaps.dwCaps & DDSCAPS_OFFSCREENPLAIN)
2523     {
2524         WARN("Called on offscreenplain surface, returning DDERR_INVALIDOBJECT.\n");
2525         hr = DDERR_INVALIDOBJECT;
2526     }
2527     else if (!(surface->surface_desc.ddsCaps.dwCaps2 & managed) || !surface->is_complex_root)
2528     {
2529         WARN("Called on non-managed texture or non-root surface, returning DDERR_INVALIDPARAMS.\n");
2530         hr = DDERR_INVALIDPARAMS;
2531     }
2532     else
2533     {
2534         resource = wined3d_texture_get_resource(surface->wined3d_texture);
2535         *priority = wined3d_resource_get_priority(resource);
2536         hr = DD_OK;
2537     }
2538     wined3d_mutex_unlock();
2539 
2540     return hr;
2541 }
2542 
2543 /*****************************************************************************
2544  * IDirectDrawSurface7::SetPrivateData
2545  *
2546  * Stores some data in the surface that is intended for the application's
2547  * use.
2548  *
2549  * Params:
2550  *  tag: GUID that identifies the data
2551  *  Data: Pointer to the private data
2552  *  Size: Size of the private data
2553  *  Flags: Some flags
2554  *
2555  * Returns:
2556  *  D3D_OK on success, error code otherwise.
2557  *
2558  *****************************************************************************/
2559 static HRESULT WINAPI ddraw_surface7_SetPrivateData(IDirectDrawSurface7 *iface,
2560         REFGUID tag, void *data, DWORD size, DWORD flags)
2561 {
2562     struct ddraw_surface *surface = impl_from_IDirectDrawSurface7(iface);
2563     HRESULT hr;
2564 
2565     TRACE("iface %p, tag %s, data %p, data_size %u, flags %#x.\n",
2566             iface, debugstr_guid(tag), data, size, flags);
2567 
2568     if (!data)
2569     {
2570         WARN("data is NULL, returning DDERR_INVALIDPARAMS.\n");
2571         return DDERR_INVALIDPARAMS;
2572     }
2573 
2574     wined3d_mutex_lock();
2575     hr = wined3d_private_store_set_private_data(&surface->private_store, tag, data, size, flags);
2576     wined3d_mutex_unlock();
2577     return hr_ddraw_from_wined3d(hr);
2578 }
2579 
2580 static HRESULT WINAPI ddraw_surface4_SetPrivateData(IDirectDrawSurface4 *iface,
2581         REFGUID tag, void *data, DWORD size, DWORD flags)
2582 {
2583     struct ddraw_surface *surface = impl_from_IDirectDrawSurface4(iface);
2584 
2585     TRACE("iface %p, tag %s, data %p, data_size %u, flags %#x.\n",
2586                 iface, debugstr_guid(tag), data, size, flags);
2587 
2588     return ddraw_surface7_SetPrivateData(&surface->IDirectDrawSurface7_iface, tag, data, size, flags);
2589 }
2590 
2591 /*****************************************************************************
2592  * IDirectDrawSurface7::GetPrivateData
2593  *
2594  * Returns the private data set with IDirectDrawSurface7::SetPrivateData
2595  *
2596  * Params:
2597  *  tag: GUID of the data to return
2598  *  Data: Address where to write the data to
2599  *  Size: Size of the buffer at Data
2600  *
2601  * Returns:
2602  *  DD_OK on success
2603  *  DDERR_INVALIDPARAMS if Data is NULL
2604  *
2605  *****************************************************************************/
2606 static HRESULT WINAPI ddraw_surface7_GetPrivateData(IDirectDrawSurface7 *iface, REFGUID tag, void *data, DWORD *size)
2607 {
2608     struct ddraw_surface *surface = impl_from_IDirectDrawSurface7(iface);
2609     const struct wined3d_private_data *stored_data;
2610     HRESULT hr;
2611 
2612     TRACE("iface %p, tag %s, data %p, data_size %p.\n",
2613             iface, debugstr_guid(tag), data, size);
2614 
2615     wined3d_mutex_lock();
2616     stored_data = wined3d_private_store_get_private_data(&surface->private_store, tag);
2617     if (!stored_data)
2618     {
2619         hr = DDERR_NOTFOUND;
2620         goto done;
2621     }
2622     if (!size)
2623     {
2624         hr = DDERR_INVALIDPARAMS;
2625         goto done;
2626     }
2627     if (*size < stored_data->size)
2628     {
2629         *size = stored_data->size;
2630         hr = DDERR_MOREDATA;
2631         goto done;
2632     }
2633     if (!data)
2634     {
2635         hr = DDERR_INVALIDPARAMS;
2636         goto done;
2637     }
2638 
2639     *size = stored_data->size;
2640     memcpy(data, stored_data->content.data, stored_data->size);
2641     hr = DD_OK;
2642 
2643 done:
2644     wined3d_mutex_unlock();
2645     return hr;
2646 }
2647 
2648 static HRESULT WINAPI ddraw_surface4_GetPrivateData(IDirectDrawSurface4 *iface, REFGUID tag, void *data, DWORD *size)
2649 {
2650     struct ddraw_surface *surface = impl_from_IDirectDrawSurface4(iface);
2651 
2652     TRACE("iface %p, tag %s, data %p, data_size %p.\n",
2653                 iface, debugstr_guid(tag), data, size);
2654 
2655     return ddraw_surface7_GetPrivateData(&surface->IDirectDrawSurface7_iface, tag, data, size);
2656 }
2657 
2658 /*****************************************************************************
2659  * IDirectDrawSurface7::FreePrivateData
2660  *
2661  * Frees private data stored in the surface
2662  *
2663  * Params:
2664  *  tag: Tag of the data to free
2665  *
2666  * Returns:
2667  *  D3D_OK on success, error code otherwise.
2668  *
2669  *****************************************************************************/
2670 static HRESULT WINAPI ddraw_surface7_FreePrivateData(IDirectDrawSurface7 *iface, REFGUID tag)
2671 {
2672     struct ddraw_surface *surface = impl_from_IDirectDrawSurface7(iface);
2673     struct wined3d_private_data *entry;
2674 
2675     TRACE("iface %p, tag %s.\n", iface, debugstr_guid(tag));
2676 
2677     wined3d_mutex_lock();
2678     entry = wined3d_private_store_get_private_data(&surface->private_store, tag);
2679     if (!entry)
2680     {
2681         wined3d_mutex_unlock();
2682         return DDERR_NOTFOUND;
2683     }
2684 
2685     wined3d_private_store_free_private_data(&surface->private_store, entry);
2686     wined3d_mutex_unlock();
2687 
2688     return DD_OK;
2689 }
2690 
2691 static HRESULT WINAPI ddraw_surface4_FreePrivateData(IDirectDrawSurface4 *iface, REFGUID tag)
2692 {
2693     struct ddraw_surface *surface = impl_from_IDirectDrawSurface4(iface);
2694 
2695     TRACE("iface %p, tag %s.\n", iface, debugstr_guid(tag));
2696 
2697     return ddraw_surface7_FreePrivateData(&surface->IDirectDrawSurface7_iface, tag);
2698 }
2699 
2700 /*****************************************************************************
2701  * IDirectDrawSurface7::PageLock
2702  *
2703  * Prevents a sysmem surface from being paged out
2704  *
2705  * Params:
2706  *  Flags: Not used, must be 0(unchecked)
2707  *
2708  * Returns:
2709  *  DD_OK, because it's a stub
2710  *
2711  *****************************************************************************/
2712 static HRESULT WINAPI ddraw_surface7_PageLock(IDirectDrawSurface7 *iface, DWORD Flags)
2713 {
2714     TRACE("iface %p, flags %#x.\n", iface, Flags);
2715 
2716     /* This is Windows memory management related - we don't need this */
2717     return DD_OK;
2718 }
2719 
2720 static HRESULT WINAPI ddraw_surface4_PageLock(IDirectDrawSurface4 *iface, DWORD flags)
2721 {
2722     struct ddraw_surface *surface = impl_from_IDirectDrawSurface4(iface);
2723 
2724     TRACE("iface %p, flags %#x.\n", iface, flags);
2725 
2726     return ddraw_surface7_PageLock(&surface->IDirectDrawSurface7_iface, flags);
2727 }
2728 
2729 static HRESULT WINAPI ddraw_surface3_PageLock(IDirectDrawSurface3 *iface, DWORD flags)
2730 {
2731     struct ddraw_surface *surface = impl_from_IDirectDrawSurface3(iface);
2732 
2733     TRACE("iface %p, flags %#x.\n", iface, flags);
2734 
2735     return ddraw_surface7_PageLock(&surface->IDirectDrawSurface7_iface, flags);
2736 }
2737 
2738 static HRESULT WINAPI ddraw_surface2_PageLock(IDirectDrawSurface2 *iface, DWORD flags)
2739 {
2740     struct ddraw_surface *surface = impl_from_IDirectDrawSurface2(iface);
2741 
2742     TRACE("iface %p, flags %#x.\n", iface, flags);
2743 
2744     return ddraw_surface7_PageLock(&surface->IDirectDrawSurface7_iface, flags);
2745 }
2746 
2747 /*****************************************************************************
2748  * IDirectDrawSurface7::PageUnlock
2749  *
2750  * Allows a sysmem surface to be paged out
2751  *
2752  * Params:
2753  *  Flags: Not used, must be 0(unchecked)
2754  *
2755  * Returns:
2756  *  DD_OK, because it's a stub
2757  *
2758  *****************************************************************************/
2759 static HRESULT WINAPI ddraw_surface7_PageUnlock(IDirectDrawSurface7 *iface, DWORD Flags)
2760 {
2761     TRACE("iface %p, flags %#x.\n", iface, Flags);
2762 
2763     return DD_OK;
2764 }
2765 
2766 static HRESULT WINAPI ddraw_surface4_PageUnlock(IDirectDrawSurface4 *iface, DWORD flags)
2767 {
2768     struct ddraw_surface *surface = impl_from_IDirectDrawSurface4(iface);
2769 
2770     TRACE("iface %p, flags %#x.\n", iface, flags);
2771 
2772     return ddraw_surface7_PageUnlock(&surface->IDirectDrawSurface7_iface, flags);
2773 }
2774 
2775 static HRESULT WINAPI ddraw_surface3_PageUnlock(IDirectDrawSurface3 *iface, DWORD flags)
2776 {
2777     struct ddraw_surface *surface = impl_from_IDirectDrawSurface3(iface);
2778 
2779     TRACE("iface %p, flags %#x.\n", iface, flags);
2780 
2781     return ddraw_surface7_PageUnlock(&surface->IDirectDrawSurface7_iface, flags);
2782 }
2783 
2784 static HRESULT WINAPI ddraw_surface2_PageUnlock(IDirectDrawSurface2 *iface, DWORD flags)
2785 {
2786     struct ddraw_surface *surface = impl_from_IDirectDrawSurface2(iface);
2787 
2788     TRACE("iface %p, flags %#x.\n", iface, flags);
2789 
2790     return ddraw_surface7_PageUnlock(&surface->IDirectDrawSurface7_iface, flags);
2791 }
2792 
2793 /*****************************************************************************
2794  * IDirectDrawSurface7::BltBatch
2795  *
2796  * An unimplemented function
2797  *
2798  * Params:
2799  *  ?
2800  *
2801  * Returns:
2802  *  DDERR_UNSUPPORTED
2803  *
2804  *****************************************************************************/
2805 static HRESULT WINAPI DECLSPEC_HOTPATCH ddraw_surface7_BltBatch(IDirectDrawSurface7 *iface, DDBLTBATCH *Batch, DWORD Count, DWORD Flags)
2806 {
2807     TRACE("iface %p, batch %p, count %u, flags %#x.\n", iface, Batch, Count, Flags);
2808 
2809     /* MSDN: "not currently implemented" */
2810     return DDERR_UNSUPPORTED;
2811 }
2812 
2813 static HRESULT WINAPI DECLSPEC_HOTPATCH ddraw_surface4_BltBatch(IDirectDrawSurface4 *iface, DDBLTBATCH *batch, DWORD count, DWORD flags)
2814 {
2815     struct ddraw_surface *surface = impl_from_IDirectDrawSurface4(iface);
2816 
2817     TRACE("iface %p, batch %p, count %u, flags %#x.\n", iface, batch, count, flags);
2818 
2819     return ddraw_surface7_BltBatch(&surface->IDirectDrawSurface7_iface, batch, count, flags);
2820 }
2821 
2822 static HRESULT WINAPI DECLSPEC_HOTPATCH ddraw_surface3_BltBatch(IDirectDrawSurface3 *iface, DDBLTBATCH *batch, DWORD count, DWORD flags)
2823 {
2824     struct ddraw_surface *surface = impl_from_IDirectDrawSurface3(iface);
2825 
2826     TRACE("iface %p, batch %p, count %u, flags %#x.\n", iface, batch, count, flags);
2827 
2828     return ddraw_surface7_BltBatch(&surface->IDirectDrawSurface7_iface, batch, count, flags);
2829 }
2830 
2831 static HRESULT WINAPI DECLSPEC_HOTPATCH ddraw_surface2_BltBatch(IDirectDrawSurface2 *iface, DDBLTBATCH *batch, DWORD count, DWORD flags)
2832 {
2833     struct ddraw_surface *surface = impl_from_IDirectDrawSurface2(iface);
2834 
2835     TRACE("iface %p, batch %p, count %u, flags %#x.\n", iface, batch, count, flags);
2836 
2837     return ddraw_surface7_BltBatch(&surface->IDirectDrawSurface7_iface, batch, count, flags);
2838 }
2839 
2840 static HRESULT WINAPI DECLSPEC_HOTPATCH ddraw_surface1_BltBatch(IDirectDrawSurface *iface, DDBLTBATCH *batch, DWORD count, DWORD flags)
2841 {
2842     struct ddraw_surface *surface = impl_from_IDirectDrawSurface(iface);
2843 
2844     TRACE("iface %p, batch %p, count %u, flags %#x.\n", iface, batch, count, flags);
2845 
2846     return ddraw_surface7_BltBatch(&surface->IDirectDrawSurface7_iface, batch, count, flags);
2847 }
2848 
2849 /*****************************************************************************
2850  * IDirectDrawSurface7::EnumAttachedSurfaces
2851  *
2852  * Enumerates all surfaces attached to this surface
2853  *
2854  * Params:
2855  *  context: Pointer to pass unmodified to the callback
2856  *  cb: Callback function to call for each surface
2857  *
2858  * Returns:
2859  *  DD_OK on success
2860  *  DDERR_INVALIDPARAMS if cb is NULL
2861  *
2862  *****************************************************************************/
2863 static HRESULT WINAPI ddraw_surface7_EnumAttachedSurfaces(IDirectDrawSurface7 *iface,
2864         void *context, LPDDENUMSURFACESCALLBACK7 cb)
2865 {
2866     struct ddraw_surface *surface = impl_from_IDirectDrawSurface7(iface);
2867     struct ddraw_surface *surf;
2868     DDSURFACEDESC2 desc;
2869     int i;
2870 
2871     /* Attached surfaces aren't handled in WineD3D */
2872     TRACE("iface %p, context %p, callback %p.\n", iface, context, cb);
2873 
2874     if(!cb)
2875         return DDERR_INVALIDPARAMS;
2876 
2877     wined3d_mutex_lock();
2878 
2879     for(i = 0; i < MAX_COMPLEX_ATTACHED; i++)
2880     {
2881         surf = surface->complex_array[i];
2882         if(!surf) break;
2883 
2884         ddraw_surface7_AddRef(&surf->IDirectDrawSurface7_iface);
2885         desc = surf->surface_desc;
2886         /* check: != DDENUMRET_OK or == DDENUMRET_CANCEL? */
2887         if (cb(&surf->IDirectDrawSurface7_iface, &desc, context) == DDENUMRET_CANCEL)
2888         {
2889             wined3d_mutex_unlock();
2890             return DD_OK;
2891         }
2892     }
2893 
2894     for (surf = surface->next_attached; surf != NULL; surf = surf->next_attached)
2895     {
2896         ddraw_surface7_AddRef(&surf->IDirectDrawSurface7_iface);
2897         desc = surf->surface_desc;
2898         /* check: != DDENUMRET_OK or == DDENUMRET_CANCEL? */
2899         if (cb(&surf->IDirectDrawSurface7_iface, &desc, context) == DDENUMRET_CANCEL)
2900         {
2901             wined3d_mutex_unlock();
2902             return DD_OK;
2903         }
2904     }
2905 
2906     TRACE(" end of enumeration.\n");
2907 
2908     wined3d_mutex_unlock();
2909 
2910     return DD_OK;
2911 }
2912 
2913 struct callback_info2
2914 {
2915     LPDDENUMSURFACESCALLBACK2 callback;
2916     void *context;
2917 };
2918 
2919 struct callback_info
2920 {
2921     LPDDENUMSURFACESCALLBACK callback;
2922     void *context;
2923 };
2924 
2925 static HRESULT CALLBACK EnumCallback2(IDirectDrawSurface7 *surface, DDSURFACEDESC2 *surface_desc, void *context)
2926 {
2927     struct ddraw_surface *surface_impl = impl_from_IDirectDrawSurface7(surface);
2928     const struct callback_info2 *info = context;
2929 
2930     ddraw_surface4_AddRef(&surface_impl->IDirectDrawSurface4_iface);
2931     ddraw_surface7_Release(surface);
2932 
2933     return info->callback(&surface_impl->IDirectDrawSurface4_iface, surface_desc, info->context);
2934 }
2935 
2936 static HRESULT CALLBACK EnumCallback(IDirectDrawSurface7 *surface, DDSURFACEDESC2 *surface_desc, void *context)
2937 {
2938     struct ddraw_surface *surface_impl = impl_from_IDirectDrawSurface7(surface);
2939     const struct callback_info *info = context;
2940 
2941     ddraw_surface1_AddRef(&surface_impl->IDirectDrawSurface_iface);
2942     ddraw_surface7_Release(surface);
2943 
2944     /* FIXME: Check surface_test.dwSize */
2945     return info->callback(&surface_impl->IDirectDrawSurface_iface,
2946             (DDSURFACEDESC *)surface_desc, info->context);
2947 }
2948 
2949 static HRESULT WINAPI ddraw_surface4_EnumAttachedSurfaces(IDirectDrawSurface4 *iface,
2950         void *context, LPDDENUMSURFACESCALLBACK2 callback)
2951 {
2952     struct ddraw_surface *surface = impl_from_IDirectDrawSurface4(iface);
2953     struct callback_info2 info;
2954 
2955     TRACE("iface %p, context %p, callback %p.\n", iface, context, callback);
2956 
2957     info.callback = callback;
2958     info.context  = context;
2959 
2960     return ddraw_surface7_EnumAttachedSurfaces(&surface->IDirectDrawSurface7_iface,
2961             &info, EnumCallback2);
2962 }
2963 
2964 static HRESULT WINAPI ddraw_surface3_EnumAttachedSurfaces(IDirectDrawSurface3 *iface,
2965         void *context, LPDDENUMSURFACESCALLBACK callback)
2966 {
2967     struct ddraw_surface *surface = impl_from_IDirectDrawSurface3(iface);
2968     struct callback_info info;
2969 
2970     TRACE("iface %p, context %p, callback %p.\n", iface, context, callback);
2971 
2972     info.callback = callback;
2973     info.context  = context;
2974 
2975     return ddraw_surface7_EnumAttachedSurfaces(&surface->IDirectDrawSurface7_iface,
2976             &info, EnumCallback);
2977 }
2978 
2979 static HRESULT WINAPI ddraw_surface2_EnumAttachedSurfaces(IDirectDrawSurface2 *iface,
2980         void *context, LPDDENUMSURFACESCALLBACK callback)
2981 {
2982     struct ddraw_surface *surface = impl_from_IDirectDrawSurface2(iface);
2983     struct callback_info info;
2984 
2985     TRACE("iface %p, context %p, callback %p.\n", iface, context, callback);
2986 
2987     info.callback = callback;
2988     info.context  = context;
2989 
2990     return ddraw_surface7_EnumAttachedSurfaces(&surface->IDirectDrawSurface7_iface,
2991             &info, EnumCallback);
2992 }
2993 
2994 static HRESULT WINAPI ddraw_surface1_EnumAttachedSurfaces(IDirectDrawSurface *iface,
2995         void *context, LPDDENUMSURFACESCALLBACK callback)
2996 {
2997     struct ddraw_surface *surface = impl_from_IDirectDrawSurface(iface);
2998     struct callback_info info;
2999 
3000     TRACE("iface %p, context %p, callback %p.\n", iface, context, callback);
3001 
3002     info.callback = callback;
3003     info.context  = context;
3004 
3005     return ddraw_surface7_EnumAttachedSurfaces(&surface->IDirectDrawSurface7_iface,
3006             &info, EnumCallback);
3007 }
3008 
3009 /*****************************************************************************
3010  * IDirectDrawSurface7::EnumOverlayZOrders
3011  *
3012  * "Enumerates the overlay surfaces on the specified destination"
3013  *
3014  * Params:
3015  *  Flags: DDENUMOVERLAYZ_BACKTOFRONT  or DDENUMOVERLAYZ_FRONTTOBACK
3016  *  context: context to pass back to the callback
3017  *  cb: callback function to call for each enumerated surface
3018  *
3019  * Returns:
3020  *  DD_OK, because it's a stub
3021  *
3022  *****************************************************************************/
3023 static HRESULT WINAPI ddraw_surface7_EnumOverlayZOrders(IDirectDrawSurface7 *iface,
3024         DWORD Flags, void *context, LPDDENUMSURFACESCALLBACK7 cb)
3025 {
3026     FIXME("iface %p, flags %#x, context %p, callback %p stub!\n", iface, Flags, context, cb);
3027 
3028     return DD_OK;
3029 }
3030 
3031 static HRESULT WINAPI ddraw_surface4_EnumOverlayZOrders(IDirectDrawSurface4 *iface,
3032         DWORD flags, void *context, LPDDENUMSURFACESCALLBACK2 callback)
3033 {
3034     struct ddraw_surface *surface = impl_from_IDirectDrawSurface4(iface);
3035     struct callback_info2 info;
3036 
3037     TRACE("iface %p, flags %#x, context %p, callback %p.\n", iface, flags, context, callback);
3038 
3039     info.callback = callback;
3040     info.context  = context;
3041 
3042     return ddraw_surface7_EnumOverlayZOrders(&surface->IDirectDrawSurface7_iface,
3043             flags, &info, EnumCallback2);
3044 }
3045 
3046 static HRESULT WINAPI ddraw_surface3_EnumOverlayZOrders(IDirectDrawSurface3 *iface,
3047         DWORD flags, void *context, LPDDENUMSURFACESCALLBACK callback)
3048 {
3049     struct ddraw_surface *surface = impl_from_IDirectDrawSurface3(iface);
3050     struct callback_info info;
3051 
3052     TRACE("iface %p, flags %#x, context %p, callback %p.\n", iface, flags, context, callback);
3053 
3054     info.callback = callback;
3055     info.context  = context;
3056 
3057     return ddraw_surface7_EnumOverlayZOrders(&surface->IDirectDrawSurface7_iface,
3058             flags, &info, EnumCallback);
3059 }
3060 
3061 static HRESULT WINAPI ddraw_surface2_EnumOverlayZOrders(IDirectDrawSurface2 *iface,
3062         DWORD flags, void *context, LPDDENUMSURFACESCALLBACK callback)
3063 {
3064     struct ddraw_surface *surface = impl_from_IDirectDrawSurface2(iface);
3065     struct callback_info info;
3066 
3067     TRACE("iface %p, flags %#x, context %p, callback %p.\n", iface, flags, context, callback);
3068 
3069     info.callback = callback;
3070     info.context  = context;
3071 
3072     return ddraw_surface7_EnumOverlayZOrders(&surface->IDirectDrawSurface7_iface,
3073             flags, &info, EnumCallback);
3074 }
3075 
3076 static HRESULT WINAPI ddraw_surface1_EnumOverlayZOrders(IDirectDrawSurface *iface,
3077         DWORD flags, void *context, LPDDENUMSURFACESCALLBACK callback)
3078 {
3079     struct ddraw_surface *surface = impl_from_IDirectDrawSurface(iface);
3080     struct callback_info info;
3081 
3082     TRACE("iface %p, flags %#x, context %p, callback %p.\n", iface, flags, context, callback);
3083 
3084     info.callback = callback;
3085     info.context  = context;
3086 
3087     return ddraw_surface7_EnumOverlayZOrders(&surface->IDirectDrawSurface7_iface,
3088             flags, &info, EnumCallback);
3089 }
3090 
3091 /*****************************************************************************
3092  * IDirectDrawSurface7::GetBltStatus
3093  *
3094  * Returns the blitting status
3095  *
3096  * Params:
3097  *  Flags: DDGBS_CANBLT or DDGBS_ISBLTDONE
3098  *
3099  *****************************************************************************/
3100 static HRESULT WINAPI ddraw_surface7_GetBltStatus(IDirectDrawSurface7 *iface, DWORD Flags)
3101 {
3102     TRACE("iface %p, flags %#x.\n", iface, Flags);
3103 
3104     switch (Flags)
3105     {
3106         case WINEDDGBS_CANBLT:
3107         case WINEDDGBS_ISBLTDONE:
3108             return DD_OK;
3109 
3110         default:
3111             return DDERR_INVALIDPARAMS;
3112     }
3113 }
3114 
3115 static HRESULT WINAPI ddraw_surface4_GetBltStatus(IDirectDrawSurface4 *iface, DWORD flags)
3116 {
3117     struct ddraw_surface *surface = impl_from_IDirectDrawSurface4(iface);
3118 
3119     TRACE("iface %p, flags %#x.\n", iface, flags);
3120 
3121     return ddraw_surface7_GetBltStatus(&surface->IDirectDrawSurface7_iface, flags);
3122 }
3123 
3124 static HRESULT WINAPI ddraw_surface3_GetBltStatus(IDirectDrawSurface3 *iface, DWORD flags)
3125 {
3126     struct ddraw_surface *surface = impl_from_IDirectDrawSurface3(iface);
3127 
3128     TRACE("iface %p, flags %#x.\n", iface, flags);
3129 
3130     return ddraw_surface7_GetBltStatus(&surface->IDirectDrawSurface7_iface, flags);
3131 }
3132 
3133 static HRESULT WINAPI ddraw_surface2_GetBltStatus(IDirectDrawSurface2 *iface, DWORD flags)
3134 {
3135     struct ddraw_surface *surface = impl_from_IDirectDrawSurface2(iface);
3136 
3137     TRACE("iface %p, flags %#x.\n", iface, flags);
3138 
3139     return ddraw_surface7_GetBltStatus(&surface->IDirectDrawSurface7_iface, flags);
3140 }
3141 
3142 static HRESULT WINAPI ddraw_surface1_GetBltStatus(IDirectDrawSurface *iface, DWORD flags)
3143 {
3144     struct ddraw_surface *surface = impl_from_IDirectDrawSurface(iface);
3145 
3146     TRACE("iface %p, flags %#x.\n", iface, flags);
3147 
3148     return ddraw_surface7_GetBltStatus(&surface->IDirectDrawSurface7_iface, flags);
3149 }
3150 
3151 /*****************************************************************************
3152  * IDirectDrawSurface7::GetColorKey
3153  *
3154  * Returns the color key assigned to the surface
3155  *
3156  * Params:
3157  *  Flags: Some flags
3158  *  CKey: Address to store the key to
3159  *
3160  * Returns:
3161  *  DD_OK on success
3162  *  DDERR_INVALIDPARAMS if CKey is NULL
3163  *
3164  *****************************************************************************/
3165 static HRESULT WINAPI ddraw_surface7_GetColorKey(IDirectDrawSurface7 *iface, DWORD Flags, DDCOLORKEY *CKey)
3166 {
3167     struct ddraw_surface *This = impl_from_IDirectDrawSurface7(iface);
3168 
3169     TRACE("iface %p, flags %#x, color_key %p.\n", iface, Flags, CKey);
3170 
3171     if(!CKey)
3172         return DDERR_INVALIDPARAMS;
3173 
3174     wined3d_mutex_lock();
3175 
3176     switch (Flags)
3177     {
3178     case DDCKEY_DESTBLT:
3179         if (!(This->surface_desc.dwFlags & DDSD_CKDESTBLT))
3180         {
3181             wined3d_mutex_unlock();
3182             return DDERR_NOCOLORKEY;
3183         }
3184         *CKey = This->surface_desc.ddckCKDestBlt;
3185         break;
3186 
3187     case DDCKEY_DESTOVERLAY:
3188         if (!(This->surface_desc.dwFlags & DDSD_CKDESTOVERLAY))
3189         {
3190             wined3d_mutex_unlock();
3191             return DDERR_NOCOLORKEY;
3192         }
3193         *CKey = This->surface_desc.u3.ddckCKDestOverlay;
3194         break;
3195 
3196     case DDCKEY_SRCBLT:
3197         if (!(This->surface_desc.dwFlags & DDSD_CKSRCBLT))
3198         {
3199             wined3d_mutex_unlock();
3200             return DDERR_NOCOLORKEY;
3201         }
3202         *CKey = This->surface_desc.ddckCKSrcBlt;
3203         break;
3204 
3205     case DDCKEY_SRCOVERLAY:
3206         if (!(This->surface_desc.dwFlags & DDSD_CKSRCOVERLAY))
3207         {
3208             wined3d_mutex_unlock();
3209             return DDERR_NOCOLORKEY;
3210         }
3211         *CKey = This->surface_desc.ddckCKSrcOverlay;
3212         break;
3213 
3214     default:
3215         wined3d_mutex_unlock();
3216         return DDERR_INVALIDPARAMS;
3217     }
3218 
3219     wined3d_mutex_unlock();
3220 
3221     return DD_OK;
3222 }
3223 
3224 static HRESULT WINAPI ddraw_surface4_GetColorKey(IDirectDrawSurface4 *iface, DWORD flags, DDCOLORKEY *color_key)
3225 {
3226     struct ddraw_surface *surface = impl_from_IDirectDrawSurface4(iface);
3227 
3228     TRACE("iface %p, flags %#x, color_key %p.\n", iface, flags, color_key);
3229 
3230     return ddraw_surface7_GetColorKey(&surface->IDirectDrawSurface7_iface, flags, color_key);
3231 }
3232 
3233 static HRESULT WINAPI ddraw_surface3_GetColorKey(IDirectDrawSurface3 *iface, DWORD flags, DDCOLORKEY *color_key)
3234 {
3235     struct ddraw_surface *surface = impl_from_IDirectDrawSurface3(iface);
3236 
3237     TRACE("iface %p, flags %#x, color_key %p.\n", iface, flags, color_key);
3238 
3239     return ddraw_surface7_GetColorKey(&surface->IDirectDrawSurface7_iface, flags, color_key);
3240 }
3241 
3242 static HRESULT WINAPI ddraw_surface2_GetColorKey(IDirectDrawSurface2 *iface, DWORD flags, DDCOLORKEY *color_key)
3243 {
3244     struct ddraw_surface *surface = impl_from_IDirectDrawSurface2(iface);
3245 
3246     TRACE("iface %p, flags %#x, color_key %p.\n", iface, flags, color_key);
3247 
3248     return ddraw_surface7_GetColorKey(&surface->IDirectDrawSurface7_iface, flags, color_key);
3249 }
3250 
3251 static HRESULT WINAPI ddraw_surface1_GetColorKey(IDirectDrawSurface *iface, DWORD flags, DDCOLORKEY *color_key)
3252 {
3253     struct ddraw_surface *surface = impl_from_IDirectDrawSurface(iface);
3254 
3255     TRACE("iface %p, flags %#x, color_key %p.\n", iface, flags, color_key);
3256 
3257     return ddraw_surface7_GetColorKey(&surface->IDirectDrawSurface7_iface, flags, color_key);
3258 }
3259 
3260 /*****************************************************************************
3261  * IDirectDrawSurface7::GetFlipStatus
3262  *
3263  * Returns the flipping status of the surface
3264  *
3265  * Params:
3266  *  Flags: DDGFS_CANFLIP of DDGFS_ISFLIPDONE
3267  *
3268  *****************************************************************************/
3269 static HRESULT WINAPI ddraw_surface7_GetFlipStatus(IDirectDrawSurface7 *iface, DWORD Flags)
3270 {
3271     TRACE("iface %p, flags %#x.\n", iface, Flags);
3272 
3273     /* XXX: DDERR_INVALIDSURFACETYPE */
3274 
3275     switch (Flags)
3276     {
3277         case WINEDDGFS_CANFLIP:
3278         case WINEDDGFS_ISFLIPDONE:
3279             return DD_OK;
3280 
3281         default:
3282             return DDERR_INVALIDPARAMS;
3283     }
3284 }
3285 
3286 static HRESULT WINAPI ddraw_surface4_GetFlipStatus(IDirectDrawSurface4 *iface, DWORD flags)
3287 {
3288     struct ddraw_surface *surface = impl_from_IDirectDrawSurface4(iface);
3289 
3290     TRACE("iface %p, flags %#x.\n", iface, flags);
3291 
3292     return ddraw_surface7_GetFlipStatus(&surface->IDirectDrawSurface7_iface, flags);
3293 }
3294 
3295 static HRESULT WINAPI ddraw_surface3_GetFlipStatus(IDirectDrawSurface3 *iface, DWORD flags)
3296 {
3297     struct ddraw_surface *surface = impl_from_IDirectDrawSurface3(iface);
3298 
3299     TRACE("iface %p, flags %#x.\n", iface, flags);
3300 
3301     return ddraw_surface7_GetFlipStatus(&surface->IDirectDrawSurface7_iface, flags);
3302 }
3303 
3304 static HRESULT WINAPI ddraw_surface2_GetFlipStatus(IDirectDrawSurface2 *iface, DWORD flags)
3305 {
3306     struct ddraw_surface *surface = impl_from_IDirectDrawSurface2(iface);
3307 
3308     TRACE("iface %p, flags %#x.\n", iface, flags);
3309 
3310     return ddraw_surface7_GetFlipStatus(&surface->IDirectDrawSurface7_iface, flags);
3311 }
3312 
3313 static HRESULT WINAPI ddraw_surface1_GetFlipStatus(IDirectDrawSurface *iface, DWORD flags)
3314 {
3315     struct ddraw_surface *surface = impl_from_IDirectDrawSurface(iface);
3316 
3317     TRACE("iface %p, flags %#x.\n", iface, flags);
3318 
3319     return ddraw_surface7_GetFlipStatus(&surface->IDirectDrawSurface7_iface, flags);
3320 }
3321 
3322 /*****************************************************************************
3323  * IDirectDrawSurface7::GetOverlayPosition
3324  *
3325  * Returns the display coordinates of a visible and active overlay surface
3326  *
3327  * Params:
3328  *  X
3329  *  Y
3330  *
3331  * Returns:
3332  *  DDERR_NOTAOVERLAYSURFACE, because it's a stub
3333  *****************************************************************************/
3334 static HRESULT WINAPI ddraw_surface7_GetOverlayPosition(IDirectDrawSurface7 *iface, LONG *x, LONG *y)
3335 {
3336     struct ddraw_surface *surface = impl_from_IDirectDrawSurface7(iface);
3337     HRESULT hr;
3338 
3339     TRACE("iface %p, x %p, y %p.\n", iface, x, y);
3340 
3341     wined3d_mutex_lock();
3342     hr = wined3d_texture_get_overlay_position(surface->wined3d_texture,
3343             surface->sub_resource_idx, x, y);
3344     wined3d_mutex_unlock();
3345 
3346     return hr;
3347 }
3348 
3349 static HRESULT WINAPI ddraw_surface4_GetOverlayPosition(IDirectDrawSurface4 *iface, LONG *x, LONG *y)
3350 {
3351     struct ddraw_surface *surface = impl_from_IDirectDrawSurface4(iface);
3352 
3353     TRACE("iface %p, x %p, y %p.\n", iface, x, y);
3354 
3355     return ddraw_surface7_GetOverlayPosition(&surface->IDirectDrawSurface7_iface, x, y);
3356 }
3357 
3358 static HRESULT WINAPI ddraw_surface3_GetOverlayPosition(IDirectDrawSurface3 *iface, LONG *x, LONG *y)
3359 {
3360     struct ddraw_surface *surface = impl_from_IDirectDrawSurface3(iface);
3361 
3362     TRACE("iface %p, x %p, y %p.\n", iface, x, y);
3363 
3364     return ddraw_surface7_GetOverlayPosition(&surface->IDirectDrawSurface7_iface, x, y);
3365 }
3366 
3367 static HRESULT WINAPI ddraw_surface2_GetOverlayPosition(IDirectDrawSurface2 *iface, LONG *x, LONG *y)
3368 {
3369     struct ddraw_surface *surface = impl_from_IDirectDrawSurface2(iface);
3370 
3371     TRACE("iface %p, x %p, y %p.\n", iface, x, y);
3372 
3373     return ddraw_surface7_GetOverlayPosition(&surface->IDirectDrawSurface7_iface, x, y);
3374 }
3375 
3376 static HRESULT WINAPI ddraw_surface1_GetOverlayPosition(IDirectDrawSurface *iface, LONG *x, LONG *y)
3377 {
3378     struct ddraw_surface *surface = impl_from_IDirectDrawSurface(iface);
3379 
3380     TRACE("iface %p, x %p, y %p.\n", iface, x, y);
3381 
3382     return ddraw_surface7_GetOverlayPosition(&surface->IDirectDrawSurface7_iface, x, y);
3383 }
3384 
3385 /*****************************************************************************
3386  * IDirectDrawSurface7::GetPixelFormat
3387  *
3388  * Returns the pixel format of the Surface
3389  *
3390  * Params:
3391  *  PixelFormat: Pointer to a DDPIXELFORMAT structure to which the pixel
3392  *               format should be written
3393  *
3394  * Returns:
3395  *  DD_OK on success
3396  *  DDERR_INVALIDPARAMS if PixelFormat is NULL
3397  *
3398  *****************************************************************************/
3399 static HRESULT WINAPI ddraw_surface7_GetPixelFormat(IDirectDrawSurface7 *iface, DDPIXELFORMAT *PixelFormat)
3400 {
3401     /* What is DDERR_INVALIDSURFACETYPE for here? */
3402     struct ddraw_surface *surface = impl_from_IDirectDrawSurface7(iface);
3403 
3404     TRACE("iface %p, pixel_format %p.\n", iface, PixelFormat);
3405 
3406     if(!PixelFormat)
3407         return DDERR_INVALIDPARAMS;
3408 
3409     wined3d_mutex_lock();
3410     DD_STRUCT_COPY_BYSIZE(PixelFormat, &surface->surface_desc.u4.ddpfPixelFormat);
3411     wined3d_mutex_unlock();
3412 
3413     return DD_OK;
3414 }
3415 
3416 static HRESULT WINAPI ddraw_surface4_GetPixelFormat(IDirectDrawSurface4 *iface, DDPIXELFORMAT *pixel_format)
3417 {
3418     struct ddraw_surface *surface = impl_from_IDirectDrawSurface4(iface);
3419 
3420     TRACE("iface %p, pixel_format %p.\n", iface, pixel_format);
3421 
3422     return ddraw_surface7_GetPixelFormat(&surface->IDirectDrawSurface7_iface, pixel_format);
3423 }
3424 
3425 static HRESULT WINAPI ddraw_surface3_GetPixelFormat(IDirectDrawSurface3 *iface, DDPIXELFORMAT *pixel_format)
3426 {
3427     struct ddraw_surface *surface = impl_from_IDirectDrawSurface3(iface);
3428 
3429     TRACE("iface %p, pixel_format %p.\n", iface, pixel_format);
3430 
3431     return ddraw_surface7_GetPixelFormat(&surface->IDirectDrawSurface7_iface, pixel_format);
3432 }
3433 
3434 static HRESULT WINAPI ddraw_surface2_GetPixelFormat(IDirectDrawSurface2 *iface, DDPIXELFORMAT *pixel_format)
3435 {
3436     struct ddraw_surface *surface = impl_from_IDirectDrawSurface2(iface);
3437 
3438     TRACE("iface %p, pixel_format %p.\n", iface, pixel_format);
3439 
3440     return ddraw_surface7_GetPixelFormat(&surface->IDirectDrawSurface7_iface, pixel_format);
3441 }
3442 
3443 static HRESULT WINAPI ddraw_surface1_GetPixelFormat(IDirectDrawSurface *iface, DDPIXELFORMAT *pixel_format)
3444 {
3445     struct ddraw_surface *surface = impl_from_IDirectDrawSurface(iface);
3446 
3447     TRACE("iface %p, pixel_format %p.\n", iface, pixel_format);
3448 
3449     return ddraw_surface7_GetPixelFormat(&surface->IDirectDrawSurface7_iface, pixel_format);
3450 }
3451 
3452 /*****************************************************************************
3453  * IDirectDrawSurface7::GetSurfaceDesc
3454  *
3455  * Returns the description of this surface
3456  *
3457  * Params:
3458  *  DDSD: Address of a DDSURFACEDESC2 structure that is to be filled with the
3459  *        surface desc
3460  *
3461  * Returns:
3462  *  DD_OK on success
3463  *  DDERR_INVALIDPARAMS if DDSD is NULL
3464  *
3465  *****************************************************************************/
3466 static HRESULT WINAPI ddraw_surface7_GetSurfaceDesc(IDirectDrawSurface7 *iface, DDSURFACEDESC2 *DDSD)
3467 {
3468     struct ddraw_surface *surface = impl_from_IDirectDrawSurface7(iface);
3469 
3470     TRACE("iface %p, surface_desc %p.\n", iface, DDSD);
3471 
3472     if(!DDSD)
3473         return DDERR_INVALIDPARAMS;
3474 
3475     if (DDSD->dwSize != sizeof(DDSURFACEDESC2))
3476     {
3477         WARN("Incorrect struct size %d, returning DDERR_INVALIDPARAMS\n",DDSD->dwSize);
3478         return DDERR_INVALIDPARAMS;
3479     }
3480 
3481     wined3d_mutex_lock();
3482     DD_STRUCT_COPY_BYSIZE(DDSD, &surface->surface_desc);
3483     TRACE("Returning surface desc:\n");
3484     if (TRACE_ON(ddraw)) DDRAW_dump_surface_desc(DDSD);
3485     wined3d_mutex_unlock();
3486 
3487     return DD_OK;
3488 }
3489 
3490 static HRESULT WINAPI ddraw_surface4_GetSurfaceDesc(IDirectDrawSurface4 *iface, DDSURFACEDESC2 *DDSD)
3491 {
3492     struct ddraw_surface *surface = impl_from_IDirectDrawSurface4(iface);
3493 
3494     TRACE("iface %p, surface_desc %p.\n", iface, DDSD);
3495 
3496     return ddraw_surface7_GetSurfaceDesc(&surface->IDirectDrawSurface7_iface, DDSD);
3497 }
3498 
3499 static HRESULT WINAPI ddraw_surface3_GetSurfaceDesc(IDirectDrawSurface3 *iface, DDSURFACEDESC *surface_desc)
3500 {
3501     struct ddraw_surface *surface = impl_from_IDirectDrawSurface3(iface);
3502 
3503     TRACE("iface %p, surface_desc %p.\n", iface, surface_desc);
3504 
3505     if (!surface_desc) return DDERR_INVALIDPARAMS;
3506 
3507     if (surface_desc->dwSize != sizeof(DDSURFACEDESC))
3508     {
3509         WARN("Incorrect structure size %u, returning DDERR_INVALIDPARAMS.\n", surface_desc->dwSize);
3510         return DDERR_INVALIDPARAMS;
3511     }
3512 
3513     wined3d_mutex_lock();
3514     DDSD2_to_DDSD(&surface->surface_desc, surface_desc);
3515     TRACE("Returning surface desc:\n");
3516     if (TRACE_ON(ddraw))
3517     {
3518         /* DDRAW_dump_surface_desc handles the smaller size */
3519         DDRAW_dump_surface_desc((DDSURFACEDESC2 *)surface_desc);
3520     }
3521     wined3d_mutex_unlock();
3522 
3523     return DD_OK;
3524 }
3525 
3526 static HRESULT WINAPI ddraw_surface2_GetSurfaceDesc(IDirectDrawSurface2 *iface, DDSURFACEDESC *DDSD)
3527 {
3528     struct ddraw_surface *surface = impl_from_IDirectDrawSurface2(iface);
3529 
3530     TRACE("iface %p, surface_desc %p.\n", iface, DDSD);
3531 
3532     return ddraw_surface3_GetSurfaceDesc(&surface->IDirectDrawSurface3_iface, DDSD);
3533 }
3534 
3535 static HRESULT WINAPI ddraw_surface1_GetSurfaceDesc(IDirectDrawSurface *iface, DDSURFACEDESC *DDSD)
3536 {
3537     struct ddraw_surface *surface = impl_from_IDirectDrawSurface(iface);
3538 
3539     TRACE("iface %p, surface_desc %p.\n", iface, DDSD);
3540 
3541     return ddraw_surface3_GetSurfaceDesc(&surface->IDirectDrawSurface3_iface, DDSD);
3542 }
3543 
3544 /*****************************************************************************
3545  * IDirectDrawSurface7::Initialize
3546  *
3547  * Initializes the surface. This is a no-op in Wine
3548  *
3549  * Params:
3550  *  DD: Pointer to an DirectDraw interface
3551  *  DDSD: Surface description for initialization
3552  *
3553  * Returns:
3554  *  DDERR_ALREADYINITIALIZED
3555  *
3556  *****************************************************************************/
3557 static HRESULT WINAPI ddraw_surface7_Initialize(IDirectDrawSurface7 *iface,
3558         IDirectDraw *ddraw, DDSURFACEDESC2 *surface_desc)
3559 {
3560     TRACE("iface %p, ddraw %p, surface_desc %p.\n", iface, ddraw, surface_desc);
3561 
3562     return DDERR_ALREADYINITIALIZED;
3563 }
3564 
3565 static HRESULT WINAPI ddraw_surface4_Initialize(IDirectDrawSurface4 *iface,
3566         IDirectDraw *ddraw, DDSURFACEDESC2 *surface_desc)
3567 {
3568     struct ddraw_surface *surface = impl_from_IDirectDrawSurface4(iface);
3569 
3570     TRACE("iface %p, ddraw %p, surface_desc %p.\n", iface, ddraw, surface_desc);
3571 
3572     return ddraw_surface7_Initialize(&surface->IDirectDrawSurface7_iface,
3573             ddraw, surface_desc);
3574 }
3575 
3576 static HRESULT WINAPI ddraw_surface3_Initialize(IDirectDrawSurface3 *iface,
3577         IDirectDraw *ddraw, DDSURFACEDESC *surface_desc)
3578 {
3579     struct ddraw_surface *surface = impl_from_IDirectDrawSurface3(iface);
3580     DDSURFACEDESC2 surface_desc2;
3581 
3582     TRACE("iface %p, ddraw %p, surface_desc %p.\n", iface, ddraw, surface_desc);
3583 
3584     if (surface_desc) DDSD_to_DDSD2(surface_desc, &surface_desc2);
3585     return ddraw_surface7_Initialize(&surface->IDirectDrawSurface7_iface,
3586             ddraw, surface_desc ? &surface_desc2 : NULL);
3587 }
3588 
3589 static HRESULT WINAPI ddraw_surface2_Initialize(IDirectDrawSurface2 *iface,
3590         IDirectDraw *ddraw, DDSURFACEDESC *surface_desc)
3591 {
3592     struct ddraw_surface *surface = impl_from_IDirectDrawSurface2(iface);
3593     DDSURFACEDESC2 surface_desc2;
3594 
3595     TRACE("iface %p, ddraw %p, surface_desc %p.\n", iface, ddraw, surface_desc);
3596 
3597     if (surface_desc) DDSD_to_DDSD2(surface_desc, &surface_desc2);
3598     return ddraw_surface7_Initialize(&surface->IDirectDrawSurface7_iface,
3599             ddraw, surface_desc ? &surface_desc2 : NULL);
3600 }
3601 
3602 static HRESULT WINAPI ddraw_surface1_Initialize(IDirectDrawSurface *iface,
3603         IDirectDraw *ddraw, DDSURFACEDESC *surface_desc)
3604 {
3605     struct ddraw_surface *surface = impl_from_IDirectDrawSurface(iface);
3606     DDSURFACEDESC2 surface_desc2;
3607 
3608     TRACE("iface %p, ddraw %p, surface_desc %p.\n", iface, ddraw, surface_desc);
3609 
3610     if (surface_desc) DDSD_to_DDSD2(surface_desc, &surface_desc2);
3611     return ddraw_surface7_Initialize(&surface->IDirectDrawSurface7_iface,
3612             ddraw, surface_desc ? &surface_desc2 : NULL);
3613 }
3614 
3615 /*****************************************************************************
3616  * IDirect3DTexture1::Initialize
3617  *
3618  * The sdk says it's not implemented
3619  *
3620  * Params:
3621  *  ?
3622  *
3623  * Returns
3624  *  DDERR_UNSUPPORTED
3625  *
3626  *****************************************************************************/
3627 static HRESULT WINAPI d3d_texture1_Initialize(IDirect3DTexture *iface,
3628         IDirect3DDevice *device, IDirectDrawSurface *surface)
3629 {
3630     TRACE("iface %p, device %p, surface %p.\n", iface, device, surface);
3631 
3632     return DDERR_UNSUPPORTED; /* Unchecked */
3633 }
3634 
3635 /*****************************************************************************
3636  * IDirectDrawSurface7::IsLost
3637  *
3638  * Checks if the surface is lost
3639  *
3640  * Returns:
3641  *  DD_OK, if the surface is usable
3642  *  DDERR_ISLOST if the surface is lost
3643  *
3644  *****************************************************************************/
3645 static HRESULT WINAPI ddraw_surface7_IsLost(IDirectDrawSurface7 *iface)
3646 {
3647     struct ddraw_surface *surface = impl_from_IDirectDrawSurface7(iface);
3648 
3649     TRACE("iface %p.\n", iface);
3650 
3651     if (surface->ddraw->device_state != DDRAW_DEVICE_STATE_OK || surface->is_lost)
3652         return DDERR_SURFACELOST;
3653 
3654     return DD_OK;
3655 }
3656 
3657 static HRESULT WINAPI ddraw_surface4_IsLost(IDirectDrawSurface4 *iface)
3658 {
3659     struct ddraw_surface *surface = impl_from_IDirectDrawSurface4(iface);
3660 
3661     TRACE("iface %p.\n", iface);
3662 
3663     return ddraw_surface7_IsLost(&surface->IDirectDrawSurface7_iface);
3664 }
3665 
3666 static HRESULT WINAPI ddraw_surface3_IsLost(IDirectDrawSurface3 *iface)
3667 {
3668     struct ddraw_surface *surface = impl_from_IDirectDrawSurface3(iface);
3669 
3670     TRACE("iface %p.\n", iface);
3671 
3672     return ddraw_surface7_IsLost(&surface->IDirectDrawSurface7_iface);
3673 }
3674 
3675 static HRESULT WINAPI ddraw_surface2_IsLost(IDirectDrawSurface2 *iface)
3676 {
3677     struct ddraw_surface *surface = impl_from_IDirectDrawSurface2(iface);
3678 
3679     TRACE("iface %p.\n", iface);
3680 
3681     return ddraw_surface7_IsLost(&surface->IDirectDrawSurface7_iface);
3682 }
3683 
3684 static HRESULT WINAPI ddraw_surface1_IsLost(IDirectDrawSurface *iface)
3685 {
3686     struct ddraw_surface *surface = impl_from_IDirectDrawSurface(iface);
3687 
3688     TRACE("iface %p.\n", iface);
3689 
3690     return ddraw_surface7_IsLost(&surface->IDirectDrawSurface7_iface);
3691 }
3692 
3693 /*****************************************************************************
3694  * IDirectDrawSurface7::Restore
3695  *
3696  * Restores a lost surface. This makes the surface usable again, but
3697  * doesn't reload its old contents
3698  *
3699  * Returns:
3700  *  DD_OK on success, error code otherwise.
3701  *
3702  *****************************************************************************/
3703 static HRESULT WINAPI ddraw_surface7_Restore(IDirectDrawSurface7 *iface)
3704 {
3705     struct ddraw_surface *surface = impl_from_IDirectDrawSurface7(iface);
3706 
3707     TRACE("iface %p.\n", iface);
3708 
3709     if (surface->surface_desc.ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE)
3710     {
3711         struct wined3d_swapchain *swapchain = surface->ddraw->wined3d_swapchain;
3712         struct wined3d_sub_resource_desc wined3d_desc;
3713         struct wined3d_display_mode mode;
3714         HRESULT hr;
3715 
3716         if (FAILED(hr = wined3d_swapchain_get_display_mode(swapchain, &mode, NULL)))
3717         {
3718             WARN("Failed to get display mode, hr %#x.\n", hr);
3719             return hr;
3720         }
3721 
3722         if (FAILED(hr = wined3d_texture_get_sub_resource_desc(surface->wined3d_texture, 0, &wined3d_desc)))
3723         {
3724             WARN("Failed to get resource desc, hr %#x.\n", hr);
3725             return hr;
3726         }
3727 
3728         if (mode.width != wined3d_desc.width || mode.height != wined3d_desc.height)
3729         {
3730             WARN("Display mode dimensions %ux%u don't match surface dimensions %ux%u.\n",
3731                     mode.width, mode.height, wined3d_desc.width, wined3d_desc.height);
3732             return DDERR_WRONGMODE;
3733         }
3734 
3735         if (mode.format_id != wined3d_desc.format)
3736         {
3737             WARN("Display mode format %#x doesn't match surface format %#x.\n",
3738                     mode.format_id, wined3d_desc.format);
3739             return DDERR_WRONGMODE;
3740         }
3741     }
3742 
3743     ddraw_update_lost_surfaces(surface->ddraw);
3744     surface->is_lost = FALSE;
3745 
3746     return DD_OK;
3747 }
3748 
3749 static HRESULT WINAPI ddraw_surface4_Restore(IDirectDrawSurface4 *iface)
3750 {
3751     struct ddraw_surface *surface = impl_from_IDirectDrawSurface4(iface);
3752 
3753     TRACE("iface %p.\n", iface);
3754 
3755     return ddraw_surface7_Restore(&surface->IDirectDrawSurface7_iface);
3756 }
3757 
3758 static HRESULT WINAPI ddraw_surface3_Restore(IDirectDrawSurface3 *iface)
3759 {
3760     struct ddraw_surface *surface = impl_from_IDirectDrawSurface3(iface);
3761 
3762     TRACE("iface %p.\n", iface);
3763 
3764     return ddraw_surface7_Restore(&surface->IDirectDrawSurface7_iface);
3765 }
3766 
3767 static HRESULT WINAPI ddraw_surface2_Restore(IDirectDrawSurface2 *iface)
3768 {
3769     struct ddraw_surface *surface = impl_from_IDirectDrawSurface2(iface);
3770 
3771     TRACE("iface %p.\n", iface);
3772 
3773     return ddraw_surface7_Restore(&surface->IDirectDrawSurface7_iface);
3774 }
3775 
3776 static HRESULT WINAPI ddraw_surface1_Restore(IDirectDrawSurface *iface)
3777 {
3778     struct ddraw_surface *surface = impl_from_IDirectDrawSurface(iface);
3779 
3780     TRACE("iface %p.\n", iface);
3781 
3782     return ddraw_surface7_Restore(&surface->IDirectDrawSurface7_iface);
3783 }
3784 
3785 /*****************************************************************************
3786  * IDirectDrawSurface7::SetOverlayPosition
3787  *
3788  * Changes the display coordinates of an overlay surface
3789  *
3790  * Params:
3791  *  X:
3792  *  Y:
3793  *
3794  * Returns:
3795  *   DDERR_NOTAOVERLAYSURFACE, because we don't support overlays right now
3796  *****************************************************************************/
3797 static HRESULT WINAPI ddraw_surface7_SetOverlayPosition(IDirectDrawSurface7 *iface, LONG x, LONG y)
3798 {
3799     struct ddraw_surface *surface = impl_from_IDirectDrawSurface7(iface);
3800     HRESULT hr;
3801 
3802     TRACE("iface %p, x %d, y %d.\n", iface, x, y);
3803 
3804     wined3d_mutex_lock();
3805     hr = wined3d_texture_set_overlay_position(surface->wined3d_texture,
3806             surface->sub_resource_idx, x, y);
3807     wined3d_mutex_unlock();
3808 
3809     return hr;
3810 }
3811 
3812 static HRESULT WINAPI ddraw_surface4_SetOverlayPosition(IDirectDrawSurface4 *iface, LONG x, LONG y)
3813 {
3814     struct ddraw_surface *surface = impl_from_IDirectDrawSurface4(iface);
3815 
3816     TRACE("iface %p, x %d, y %d.\n", iface, x, y);
3817 
3818     return ddraw_surface7_SetOverlayPosition(&surface->IDirectDrawSurface7_iface, x, y);
3819 }
3820 
3821 static HRESULT WINAPI ddraw_surface3_SetOverlayPosition(IDirectDrawSurface3 *iface, LONG x, LONG y)
3822 {
3823     struct ddraw_surface *surface = impl_from_IDirectDrawSurface3(iface);
3824 
3825     TRACE("iface %p, x %d, y %d.\n", iface, x, y);
3826 
3827     return ddraw_surface7_SetOverlayPosition(&surface->IDirectDrawSurface7_iface, x, y);
3828 }
3829 
3830 static HRESULT WINAPI ddraw_surface2_SetOverlayPosition(IDirectDrawSurface2 *iface, LONG x, LONG y)
3831 {
3832     struct ddraw_surface *surface = impl_from_IDirectDrawSurface2(iface);
3833 
3834     TRACE("iface %p, x %d, y %d.\n", iface, x, y);
3835 
3836     return ddraw_surface7_SetOverlayPosition(&surface->IDirectDrawSurface7_iface, x, y);
3837 }
3838 
3839 static HRESULT WINAPI ddraw_surface1_SetOverlayPosition(IDirectDrawSurface *iface, LONG x, LONG y)
3840 {
3841     struct ddraw_surface *surface = impl_from_IDirectDrawSurface(iface);
3842 
3843     TRACE("iface %p, x %d, y %d.\n", iface, x, y);
3844 
3845     return ddraw_surface7_SetOverlayPosition(&surface->IDirectDrawSurface7_iface, x, y);
3846 }
3847 
3848 /*****************************************************************************
3849  * IDirectDrawSurface7::UpdateOverlay
3850  *
3851  * Modifies the attributes of an overlay surface.
3852  *
3853  * Params:
3854  *  SrcRect: The section of the source being used for the overlay
3855  *  DstSurface: Address of the surface that is overlaid
3856  *  DstRect: Place of the overlay
3857  *  Flags: some DDOVER_* flags
3858  *
3859  * Returns:
3860  *  DDERR_UNSUPPORTED, because we don't support overlays
3861  *
3862  *****************************************************************************/
3863 static HRESULT WINAPI ddraw_surface7_UpdateOverlay(IDirectDrawSurface7 *iface, RECT *src_rect,
3864         IDirectDrawSurface7 *dst_surface, RECT *dst_rect, DWORD flags, DDOVERLAYFX *fx)
3865 {
3866     struct ddraw_surface *src_impl = impl_from_IDirectDrawSurface7(iface);
3867     struct ddraw_surface *dst_impl = unsafe_impl_from_IDirectDrawSurface7(dst_surface);
3868     struct wined3d_texture *dst_wined3d_texture = NULL;
3869     unsigned int dst_sub_resource_idx = 0;
3870     HRESULT hr;
3871 
3872     TRACE("iface %p, src_rect %s, dst_surface %p, dst_rect %s, flags %#x, fx %p.\n",
3873             iface, wine_dbgstr_rect(src_rect), dst_surface, wine_dbgstr_rect(dst_rect), flags, fx);
3874 
3875     if (fx)
3876         FIXME("Ignoring fx %p.\n", fx);
3877 
3878     wined3d_mutex_lock();
3879     if (dst_impl)
3880     {
3881         dst_wined3d_texture = dst_impl->wined3d_texture;
3882         dst_sub_resource_idx = dst_impl->sub_resource_idx;
3883     }
3884     hr = wined3d_texture_update_overlay(src_impl->wined3d_texture, src_impl->sub_resource_idx,
3885             src_rect, dst_wined3d_texture, dst_sub_resource_idx, dst_rect, flags);
3886     wined3d_mutex_unlock();
3887 
3888     switch (hr)
3889     {
3890         case WINED3DERR_INVALIDCALL:        return DDERR_INVALIDPARAMS;
3891         case WINEDDERR_NOTAOVERLAYSURFACE:  return DDERR_NOTAOVERLAYSURFACE;
3892         case WINEDDERR_OVERLAYNOTVISIBLE:   return DDERR_OVERLAYNOTVISIBLE;
3893         default:
3894             return hr;
3895     }
3896 }
3897 
3898 static HRESULT WINAPI ddraw_surface4_UpdateOverlay(IDirectDrawSurface4 *iface, RECT *src_rect,
3899         IDirectDrawSurface4 *dst_surface, RECT *dst_rect, DWORD flags, DDOVERLAYFX *fx)
3900 {
3901     struct ddraw_surface *src_impl = impl_from_IDirectDrawSurface4(iface);
3902     struct ddraw_surface *dst_impl = unsafe_impl_from_IDirectDrawSurface4(dst_surface);
3903 
3904     TRACE("iface %p, src_rect %s, dst_surface %p, dst_rect %s, flags %#x, fx %p.\n",
3905             iface, wine_dbgstr_rect(src_rect), dst_surface, wine_dbgstr_rect(dst_rect), flags, fx);
3906 
3907     return ddraw_surface7_UpdateOverlay(&src_impl->IDirectDrawSurface7_iface, src_rect,
3908             dst_impl ? &dst_impl->IDirectDrawSurface7_iface : NULL, dst_rect, flags, fx);
3909 }
3910 
3911 static HRESULT WINAPI ddraw_surface3_UpdateOverlay(IDirectDrawSurface3 *iface, RECT *src_rect,
3912         IDirectDrawSurface3 *dst_surface, RECT *dst_rect, DWORD flags, DDOVERLAYFX *fx)
3913 {
3914     struct ddraw_surface *src_impl = impl_from_IDirectDrawSurface3(iface);
3915     struct ddraw_surface *dst_impl = unsafe_impl_from_IDirectDrawSurface3(dst_surface);
3916 
3917     TRACE("iface %p, src_rect %s, dst_surface %p, dst_rect %s, flags %#x, fx %p.\n",
3918             iface, wine_dbgstr_rect(src_rect), dst_surface, wine_dbgstr_rect(dst_rect), flags, fx);
3919 
3920     return ddraw_surface7_UpdateOverlay(&src_impl->IDirectDrawSurface7_iface, src_rect,
3921             dst_impl ? &dst_impl->IDirectDrawSurface7_iface : NULL, dst_rect, flags, fx);
3922 }
3923 
3924 static HRESULT WINAPI ddraw_surface2_UpdateOverlay(IDirectDrawSurface2 *iface, RECT *src_rect,
3925         IDirectDrawSurface2 *dst_surface, RECT *dst_rect, DWORD flags, DDOVERLAYFX *fx)
3926 {
3927     struct ddraw_surface *src_impl = impl_from_IDirectDrawSurface2(iface);
3928     struct ddraw_surface *dst_impl = unsafe_impl_from_IDirectDrawSurface2(dst_surface);
3929 
3930     TRACE("iface %p, src_rect %s, dst_surface %p, dst_rect %s, flags %#x, fx %p.\n",
3931             iface, wine_dbgstr_rect(src_rect), dst_surface, wine_dbgstr_rect(dst_rect), flags, fx);
3932 
3933     return ddraw_surface7_UpdateOverlay(&src_impl->IDirectDrawSurface7_iface, src_rect,
3934             dst_impl ? &dst_impl->IDirectDrawSurface7_iface : NULL, dst_rect, flags, fx);
3935 }
3936 
3937 static HRESULT WINAPI ddraw_surface1_UpdateOverlay(IDirectDrawSurface *iface, RECT *src_rect,
3938         IDirectDrawSurface *dst_surface, RECT *dst_rect, DWORD flags, DDOVERLAYFX *fx)
3939 {
3940     struct ddraw_surface *src_impl = impl_from_IDirectDrawSurface(iface);
3941     struct ddraw_surface *dst_impl = unsafe_impl_from_IDirectDrawSurface(dst_surface);
3942 
3943     TRACE("iface %p, src_rect %s, dst_surface %p, dst_rect %s, flags %#x, fx %p.\n",
3944             iface, wine_dbgstr_rect(src_rect), dst_surface, wine_dbgstr_rect(dst_rect), flags, fx);
3945 
3946     return ddraw_surface7_UpdateOverlay(&src_impl->IDirectDrawSurface7_iface, src_rect,
3947             dst_impl ? &dst_impl->IDirectDrawSurface7_iface : NULL, dst_rect, flags, fx);
3948 }
3949 
3950 /*****************************************************************************
3951  * IDirectDrawSurface7::UpdateOverlayDisplay
3952  *
3953  * The DX7 sdk says that it's not implemented
3954  *
3955  * Params:
3956  *  Flags: ?
3957  *
3958  * Returns: DDERR_UNSUPPORTED, because we don't support overlays
3959  *
3960  *****************************************************************************/
3961 static HRESULT WINAPI ddraw_surface7_UpdateOverlayDisplay(IDirectDrawSurface7 *iface, DWORD Flags)
3962 {
3963     TRACE("iface %p, flags %#x.\n", iface, Flags);
3964 
3965     return DDERR_UNSUPPORTED;
3966 }
3967 
3968 static HRESULT WINAPI ddraw_surface4_UpdateOverlayDisplay(IDirectDrawSurface4 *iface, DWORD flags)
3969 {
3970     struct ddraw_surface *surface = impl_from_IDirectDrawSurface4(iface);
3971 
3972     TRACE("iface %p, flags %#x.\n", iface, flags);
3973 
3974     return ddraw_surface7_UpdateOverlayDisplay(&surface->IDirectDrawSurface7_iface, flags);
3975 }
3976 
3977 static HRESULT WINAPI ddraw_surface3_UpdateOverlayDisplay(IDirectDrawSurface3 *iface, DWORD flags)
3978 {
3979     struct ddraw_surface *surface = impl_from_IDirectDrawSurface3(iface);
3980 
3981     TRACE("iface %p, flags %#x.\n", iface, flags);
3982 
3983     return ddraw_surface7_UpdateOverlayDisplay(&surface->IDirectDrawSurface7_iface, flags);
3984 }
3985 
3986 static HRESULT WINAPI ddraw_surface2_UpdateOverlayDisplay(IDirectDrawSurface2 *iface, DWORD flags)
3987 {
3988     struct ddraw_surface *surface = impl_from_IDirectDrawSurface2(iface);
3989 
3990     TRACE("iface %p, flags %#x.\n", iface, flags);
3991 
3992     return ddraw_surface7_UpdateOverlayDisplay(&surface->IDirectDrawSurface7_iface, flags);
3993 }
3994 
3995 static HRESULT WINAPI ddraw_surface1_UpdateOverlayDisplay(IDirectDrawSurface *iface, DWORD flags)
3996 {
3997     struct ddraw_surface *surface = impl_from_IDirectDrawSurface(iface);
3998 
3999     TRACE("iface %p, flags %#x.\n", iface, flags);
4000 
4001     return ddraw_surface7_UpdateOverlayDisplay(&surface->IDirectDrawSurface7_iface, flags);
4002 }
4003 
4004 /*****************************************************************************
4005  * IDirectDrawSurface7::UpdateOverlayZOrder
4006  *
4007  * Sets an overlay's Z order
4008  *
4009  * Params:
4010  *  Flags: DDOVERZ_* flags
4011  *  DDSRef: Defines the relative position in the overlay chain
4012  *
4013  * Returns:
4014  *  DDERR_NOTOVERLAYSURFACE, because we don't support overlays
4015  *
4016  *****************************************************************************/
4017 static HRESULT WINAPI ddraw_surface7_UpdateOverlayZOrder(IDirectDrawSurface7 *iface,
4018         DWORD flags, IDirectDrawSurface7 *reference)
4019 {
4020     struct ddraw_surface *surface = impl_from_IDirectDrawSurface7(iface);
4021 
4022     FIXME("iface %p, flags %#x, reference %p stub!\n", iface, flags, reference);
4023 
4024     wined3d_mutex_lock();
4025     if (!(surface->surface_desc.ddsCaps.dwCaps & DDSCAPS_OVERLAY))
4026     {
4027         WARN("Not an overlay surface.\n");
4028         wined3d_mutex_unlock();
4029         return DDERR_NOTAOVERLAYSURFACE;
4030     }
4031     wined3d_mutex_unlock();
4032 
4033     return DD_OK;
4034 }
4035 
4036 static HRESULT WINAPI ddraw_surface4_UpdateOverlayZOrder(IDirectDrawSurface4 *iface,
4037         DWORD flags, IDirectDrawSurface4 *reference)
4038 {
4039     struct ddraw_surface *surface = impl_from_IDirectDrawSurface4(iface);
4040     struct ddraw_surface *reference_impl = unsafe_impl_from_IDirectDrawSurface4(reference);
4041 
4042     TRACE("iface %p, flags %#x, reference %p.\n", iface, flags, reference);
4043 
4044     return ddraw_surface7_UpdateOverlayZOrder(&surface->IDirectDrawSurface7_iface, flags,
4045             reference_impl ? &reference_impl->IDirectDrawSurface7_iface : NULL);
4046 }
4047 
4048 static HRESULT WINAPI ddraw_surface3_UpdateOverlayZOrder(IDirectDrawSurface3 *iface,
4049         DWORD flags, IDirectDrawSurface3 *reference)
4050 {
4051     struct ddraw_surface *surface = impl_from_IDirectDrawSurface3(iface);
4052     struct ddraw_surface *reference_impl = unsafe_impl_from_IDirectDrawSurface3(reference);
4053 
4054     TRACE("iface %p, flags %#x, reference %p.\n", iface, flags, reference);
4055 
4056     return ddraw_surface7_UpdateOverlayZOrder(&surface->IDirectDrawSurface7_iface, flags,
4057             reference_impl ? &reference_impl->IDirectDrawSurface7_iface : NULL);
4058 }
4059 
4060 static HRESULT WINAPI ddraw_surface2_UpdateOverlayZOrder(IDirectDrawSurface2 *iface,
4061         DWORD flags, IDirectDrawSurface2 *reference)
4062 {
4063     struct ddraw_surface *surface = impl_from_IDirectDrawSurface2(iface);
4064     struct ddraw_surface *reference_impl = unsafe_impl_from_IDirectDrawSurface2(reference);
4065 
4066     TRACE("iface %p, flags %#x, reference %p.\n", iface, flags, reference);
4067 
4068     return ddraw_surface7_UpdateOverlayZOrder(&surface->IDirectDrawSurface7_iface, flags,
4069             reference_impl ? &reference_impl->IDirectDrawSurface7_iface : NULL);
4070 }
4071 
4072 static HRESULT WINAPI ddraw_surface1_UpdateOverlayZOrder(IDirectDrawSurface *iface,
4073         DWORD flags, IDirectDrawSurface *reference)
4074 {
4075     struct ddraw_surface *surface = impl_from_IDirectDrawSurface(iface);
4076     struct ddraw_surface *reference_impl = unsafe_impl_from_IDirectDrawSurface(reference);
4077 
4078     TRACE("iface %p, flags %#x, reference %p.\n", iface, flags, reference);
4079 
4080     return ddraw_surface7_UpdateOverlayZOrder(&surface->IDirectDrawSurface7_iface, flags,
4081             reference_impl ? &reference_impl->IDirectDrawSurface7_iface : NULL);
4082 }
4083 
4084 /*****************************************************************************
4085  * IDirectDrawSurface7::GetDDInterface
4086  *
4087  * Returns the IDirectDraw7 interface pointer of the DirectDraw object this
4088  * surface belongs to
4089  *
4090  * Params:
4091  *  DD: Address to write the interface pointer to
4092  *
4093  * Returns:
4094  *  DD_OK on success
4095  *  DDERR_INVALIDPARAMS if DD is NULL
4096  *
4097  *****************************************************************************/
4098 static HRESULT WINAPI ddraw_surface7_GetDDInterface(IDirectDrawSurface7 *iface, void **DD)
4099 {
4100     struct ddraw_surface *This = impl_from_IDirectDrawSurface7(iface);
4101 
4102     TRACE("iface %p, ddraw %p.\n", iface, DD);
4103 
4104     if(!DD)
4105         return DDERR_INVALIDPARAMS;
4106 
4107     switch(This->version)
4108     {
4109         case 7:
4110             *DD = &This->ddraw->IDirectDraw7_iface;
4111             break;
4112 
4113         case 4:
4114             *DD = &This->ddraw->IDirectDraw4_iface;
4115             break;
4116 
4117         case 2:
4118             *DD = &This->ddraw->IDirectDraw2_iface;
4119             break;
4120 
4121         case 1:
4122             *DD = &This->ddraw->IDirectDraw_iface;
4123             break;
4124 
4125     }
4126     IUnknown_AddRef((IUnknown *)*DD);
4127 
4128     return DD_OK;
4129 }
4130 
4131 static HRESULT WINAPI ddraw_surface4_GetDDInterface(IDirectDrawSurface4 *iface, void **ddraw)
4132 {
4133     struct ddraw_surface *surface = impl_from_IDirectDrawSurface4(iface);
4134 
4135     TRACE("iface %p, ddraw %p.\n", iface, ddraw);
4136 
4137     return ddraw_surface7_GetDDInterface(&surface->IDirectDrawSurface7_iface, ddraw);
4138 }
4139 
4140 static HRESULT WINAPI ddraw_surface3_GetDDInterface(IDirectDrawSurface3 *iface, void **ddraw)
4141 {
4142     struct ddraw_surface *surface = impl_from_IDirectDrawSurface3(iface);
4143 
4144     TRACE("iface %p, ddraw %p.\n", iface, ddraw);
4145 
4146     return ddraw_surface7_GetDDInterface(&surface->IDirectDrawSurface7_iface, ddraw);
4147 }
4148 
4149 static HRESULT WINAPI ddraw_surface2_GetDDInterface(IDirectDrawSurface2 *iface, void **ddraw)
4150 {
4151     struct ddraw_surface *surface = impl_from_IDirectDrawSurface2(iface);
4152 
4153     TRACE("iface %p, ddraw %p.\n", iface, ddraw);
4154 
4155     return ddraw_surface7_GetDDInterface(&surface->IDirectDrawSurface7_iface, ddraw);
4156 }
4157 
4158 static HRESULT WINAPI ddraw_surface7_ChangeUniquenessValue(IDirectDrawSurface7 *iface)
4159 {
4160     TRACE("iface %p.\n", iface);
4161 
4162     return DD_OK;
4163 }
4164 
4165 static HRESULT WINAPI ddraw_surface4_ChangeUniquenessValue(IDirectDrawSurface4 *iface)
4166 {
4167     struct ddraw_surface *surface = impl_from_IDirectDrawSurface4(iface);
4168 
4169     TRACE("iface %p.\n", iface);
4170 
4171     return ddraw_surface7_ChangeUniquenessValue(&surface->IDirectDrawSurface7_iface);
4172 }
4173 
4174 static HRESULT WINAPI ddraw_surface7_GetUniquenessValue(IDirectDrawSurface7 *iface, DWORD *pValue)
4175 {
4176     TRACE("iface %p, value %p.\n", iface, pValue);
4177 
4178     *pValue = 0;
4179 
4180     return DD_OK;
4181 }
4182 
4183 static HRESULT WINAPI ddraw_surface4_GetUniquenessValue(IDirectDrawSurface4 *iface, DWORD *pValue)
4184 {
4185     struct ddraw_surface *surface = impl_from_IDirectDrawSurface4(iface);
4186 
4187     TRACE("iface %p, value %p.\n", iface, pValue);
4188 
4189     return ddraw_surface7_GetUniquenessValue(&surface->IDirectDrawSurface7_iface, pValue);
4190 }
4191 
4192 /*****************************************************************************
4193  * IDirectDrawSurface7::SetLOD
4194  *
4195  * Sets the level of detail of a texture
4196  *
4197  * Params:
4198  *  MaxLOD: LOD to set
4199  *
4200  * Returns:
4201  *  DD_OK on success
4202  *  DDERR_INVALIDOBJECT if the surface is invalid for this method
4203  *
4204  *****************************************************************************/
4205 static HRESULT WINAPI ddraw_surface7_SetLOD(IDirectDrawSurface7 *iface, DWORD MaxLOD)
4206 {
4207     struct ddraw_surface *surface = impl_from_IDirectDrawSurface7(iface);
4208     HRESULT hr;
4209 
4210     TRACE("iface %p, lod %u.\n", iface, MaxLOD);
4211 
4212     wined3d_mutex_lock();
4213     if (!(surface->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_TEXTUREMANAGE))
4214     {
4215         wined3d_mutex_unlock();
4216         return DDERR_INVALIDOBJECT;
4217     }
4218 
4219     hr = wined3d_texture_set_lod(surface->wined3d_texture, MaxLOD);
4220     wined3d_mutex_unlock();
4221 
4222     return hr;
4223 }
4224 
4225 /*****************************************************************************
4226  * IDirectDrawSurface7::GetLOD
4227  *
4228  * Returns the level of detail of a Direct3D texture
4229  *
4230  * Params:
4231  *  MaxLOD: Address to write the LOD to
4232  *
4233  * Returns:
4234  *  DD_OK on success
4235  *  DDERR_INVALIDPARAMS if MaxLOD is NULL
4236  *  DDERR_INVALIDOBJECT if the surface is invalid for this method
4237  *
4238  *****************************************************************************/
4239 static HRESULT WINAPI ddraw_surface7_GetLOD(IDirectDrawSurface7 *iface, DWORD *MaxLOD)
4240 {
4241     struct ddraw_surface *surface = impl_from_IDirectDrawSurface7(iface);
4242 
4243     TRACE("iface %p, lod %p.\n", iface, MaxLOD);
4244 
4245     if(!MaxLOD)
4246         return DDERR_INVALIDPARAMS;
4247 
4248     wined3d_mutex_lock();
4249     if (!(surface->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_TEXTUREMANAGE))
4250     {
4251         wined3d_mutex_unlock();
4252         return DDERR_INVALIDOBJECT;
4253     }
4254 
4255     *MaxLOD = wined3d_texture_get_lod(surface->wined3d_texture);
4256     wined3d_mutex_unlock();
4257 
4258     return DD_OK;
4259 }
4260 
4261 /*****************************************************************************
4262  * IDirectDrawSurface7::BltFast
4263  *
4264  * Performs a fast Blit.
4265  *
4266  * Params:
4267  *  dstx: The x coordinate to blit to on the destination
4268  *  dsty: The y coordinate to blit to on the destination
4269  *  Source: The source surface
4270  *  rsrc: The source rectangle
4271  *  trans: Type of transfer. Some DDBLTFAST_* flags
4272  *
4273  * Returns:
4274  *  DD_OK on success, error code otherwise.
4275  *
4276  *****************************************************************************/
4277 static HRESULT WINAPI DECLSPEC_HOTPATCH ddraw_surface7_BltFast(IDirectDrawSurface7 *iface,
4278         DWORD dst_x, DWORD dst_y, IDirectDrawSurface7 *src_surface, RECT *src_rect, DWORD trans)
4279 {
4280     struct ddraw_surface *dst_impl = impl_from_IDirectDrawSurface7(iface);
4281     struct ddraw_surface *src_impl = unsafe_impl_from_IDirectDrawSurface7(src_surface);
4282     DWORD flags = WINED3D_BLT_SYNCHRONOUS;
4283     DWORD src_w, src_h, dst_w, dst_h;
4284     HRESULT hr = DD_OK;
4285     RECT dst_rect, s;
4286 
4287     TRACE("iface %p, dst_x %u, dst_y %u, src_surface %p, src_rect %s, flags %#x.\n",
4288             iface, dst_x, dst_y, src_surface, wine_dbgstr_rect(src_rect), trans);
4289 
4290     dst_w = dst_impl->surface_desc.dwWidth;
4291     dst_h = dst_impl->surface_desc.dwHeight;
4292 
4293     if (!src_rect)
4294     {
4295         SetRect(&s, 0, 0, src_impl->surface_desc.dwWidth, src_impl->surface_desc.dwHeight);
4296         src_rect = &s;
4297     }
4298 
4299     src_w = src_rect->right - src_rect->left;
4300     src_h = src_rect->bottom - src_rect->top;
4301     if (src_w > dst_w || dst_x > dst_w - src_w
4302             || src_h > dst_h || dst_y > dst_h - src_h)
4303     {
4304         WARN("Destination area out of bounds, returning DDERR_INVALIDRECT.\n");
4305         return DDERR_INVALIDRECT;
4306     }
4307 
4308     SetRect(&dst_rect, dst_x, dst_y, dst_x + src_w, dst_y + src_h);
4309     if (trans & DDBLTFAST_SRCCOLORKEY)
4310         flags |= WINED3D_BLT_SRC_CKEY;
4311     if (trans & DDBLTFAST_DESTCOLORKEY)
4312         flags |= WINED3D_BLT_DST_CKEY;
4313     if (trans & DDBLTFAST_WAIT)
4314         flags |= WINED3D_BLT_WAIT;
4315     if (trans & DDBLTFAST_DONOTWAIT)
4316         flags |= WINED3D_BLT_DO_NOT_WAIT;
4317 
4318     wined3d_mutex_lock();
4319     if (dst_impl->clipper)
4320     {
4321         wined3d_mutex_unlock();
4322         WARN("Destination surface has a clipper set, returning DDERR_BLTFASTCANTCLIP.\n");
4323         return DDERR_BLTFASTCANTCLIP;
4324     }
4325 
4326     if (src_impl->surface_desc.ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE)
4327         hr = ddraw_surface_update_frontbuffer(src_impl, src_rect, TRUE, 0);
4328     if (SUCCEEDED(hr))
4329         hr = wined3d_texture_blt(dst_impl->wined3d_texture, dst_impl->sub_resource_idx, &dst_rect,
4330                 src_impl->wined3d_texture, src_impl->sub_resource_idx, src_rect, flags, NULL, WINED3D_TEXF_POINT);
4331     if (SUCCEEDED(hr) && (dst_impl->surface_desc.ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE))
4332         hr = ddraw_surface_update_frontbuffer(dst_impl, &dst_rect, FALSE, 0);
4333     wined3d_mutex_unlock();
4334 
4335     switch(hr)
4336     {
4337         case WINED3DERR_NOTAVAILABLE:           return DDERR_UNSUPPORTED;
4338         default:                                return hr;
4339     }
4340 }
4341 
4342 static HRESULT WINAPI DECLSPEC_HOTPATCH ddraw_surface4_BltFast(IDirectDrawSurface4 *iface, DWORD dst_x, DWORD dst_y,
4343         IDirectDrawSurface4 *src_surface, RECT *src_rect, DWORD flags)
4344 {
4345     struct ddraw_surface *dst_impl = impl_from_IDirectDrawSurface4(iface);
4346     struct ddraw_surface *src_impl = unsafe_impl_from_IDirectDrawSurface4(src_surface);
4347 
4348     TRACE("iface %p, dst_x %u, dst_y %u, src_surface %p, src_rect %s, flags %#x.\n",
4349             iface, dst_x, dst_y, src_surface, wine_dbgstr_rect(src_rect), flags);
4350 
4351     return ddraw_surface7_BltFast(&dst_impl->IDirectDrawSurface7_iface, dst_x, dst_y,
4352             src_impl ? &src_impl->IDirectDrawSurface7_iface : NULL, src_rect, flags);
4353 }
4354 
4355 static HRESULT WINAPI DECLSPEC_HOTPATCH ddraw_surface3_BltFast(IDirectDrawSurface3 *iface, DWORD dst_x, DWORD dst_y,
4356         IDirectDrawSurface3 *src_surface, RECT *src_rect, DWORD flags)
4357 {
4358     struct ddraw_surface *dst_impl = impl_from_IDirectDrawSurface3(iface);
4359     struct ddraw_surface *src_impl = unsafe_impl_from_IDirectDrawSurface3(src_surface);
4360 
4361     TRACE("iface %p, dst_x %u, dst_y %u, src_surface %p, src_rect %s, flags %#x.\n",
4362             iface, dst_x, dst_y, src_surface, wine_dbgstr_rect(src_rect), flags);
4363 
4364     return ddraw_surface7_BltFast(&dst_impl->IDirectDrawSurface7_iface, dst_x, dst_y,
4365             src_impl ? &src_impl->IDirectDrawSurface7_iface : NULL, src_rect, flags);
4366 }
4367 
4368 static HRESULT WINAPI DECLSPEC_HOTPATCH ddraw_surface2_BltFast(IDirectDrawSurface2 *iface, DWORD dst_x, DWORD dst_y,
4369         IDirectDrawSurface2 *src_surface, RECT *src_rect, DWORD flags)
4370 {
4371     struct ddraw_surface *dst_impl = impl_from_IDirectDrawSurface2(iface);
4372     struct ddraw_surface *src_impl = unsafe_impl_from_IDirectDrawSurface2(src_surface);
4373 
4374     TRACE("iface %p, dst_x %u, dst_y %u, src_surface %p, src_rect %s, flags %#x.\n",
4375             iface, dst_x, dst_y, src_surface, wine_dbgstr_rect(src_rect), flags);
4376 
4377     return ddraw_surface7_BltFast(&dst_impl->IDirectDrawSurface7_iface, dst_x, dst_y,
4378             src_impl ? &src_impl->IDirectDrawSurface7_iface : NULL, src_rect, flags);
4379 }
4380 
4381 static HRESULT WINAPI DECLSPEC_HOTPATCH ddraw_surface1_BltFast(IDirectDrawSurface *iface, DWORD dst_x, DWORD dst_y,
4382         IDirectDrawSurface *src_surface, RECT *src_rect, DWORD flags)
4383 {
4384     struct ddraw_surface *dst_impl = impl_from_IDirectDrawSurface(iface);
4385     struct ddraw_surface *src_impl = unsafe_impl_from_IDirectDrawSurface(src_surface);
4386 
4387     TRACE("iface %p, dst_x %u, dst_y %u, src_surface %p, src_rect %s, flags %#x.\n",
4388             iface, dst_x, dst_y, src_surface, wine_dbgstr_rect(src_rect), flags);
4389 
4390     return ddraw_surface7_BltFast(&dst_impl->IDirectDrawSurface7_iface, dst_x, dst_y,
4391             src_impl ? &src_impl->IDirectDrawSurface7_iface : NULL, src_rect, flags);
4392 }
4393 
4394 /*****************************************************************************
4395  * IDirectDrawSurface7::GetClipper
4396  *
4397  * Returns the IDirectDrawClipper interface of the clipper assigned to this
4398  * surface
4399  *
4400  * Params:
4401  *  Clipper: Address to store the interface pointer at
4402  *
4403  * Returns:
4404  *  DD_OK on success
4405  *  DDERR_INVALIDPARAMS if Clipper is NULL
4406  *  DDERR_NOCLIPPERATTACHED if there's no clipper attached
4407  *
4408  *****************************************************************************/
4409 static HRESULT WINAPI ddraw_surface7_GetClipper(IDirectDrawSurface7 *iface, IDirectDrawClipper **Clipper)
4410 {
4411     struct ddraw_surface *surface = impl_from_IDirectDrawSurface7(iface);
4412 
4413     TRACE("iface %p, clipper %p.\n", iface, Clipper);
4414 
4415     if (!Clipper)
4416         return DDERR_INVALIDPARAMS;
4417 
4418     wined3d_mutex_lock();
4419     if (!surface->clipper)
4420     {
4421         wined3d_mutex_unlock();
4422         return DDERR_NOCLIPPERATTACHED;
4423     }
4424 
4425     *Clipper = &surface->clipper->IDirectDrawClipper_iface;
4426     IDirectDrawClipper_AddRef(*Clipper);
4427     wined3d_mutex_unlock();
4428 
4429     return DD_OK;
4430 }
4431 
4432 static HRESULT WINAPI ddraw_surface4_GetClipper(IDirectDrawSurface4 *iface, IDirectDrawClipper **clipper)
4433 {
4434     struct ddraw_surface *surface = impl_from_IDirectDrawSurface4(iface);
4435 
4436     TRACE("iface %p, clipper %p.\n", iface, clipper);
4437 
4438     return ddraw_surface7_GetClipper(&surface->IDirectDrawSurface7_iface, clipper);
4439 }
4440 
4441 static HRESULT WINAPI ddraw_surface3_GetClipper(IDirectDrawSurface3 *iface, IDirectDrawClipper **clipper)
4442 {
4443     struct ddraw_surface *surface = impl_from_IDirectDrawSurface3(iface);
4444 
4445     TRACE("iface %p, clipper %p.\n", iface, clipper);
4446 
4447     return ddraw_surface7_GetClipper(&surface->IDirectDrawSurface7_iface, clipper);
4448 }
4449 
4450 static HRESULT WINAPI ddraw_surface2_GetClipper(IDirectDrawSurface2 *iface, IDirectDrawClipper **clipper)
4451 {
4452     struct ddraw_surface *surface = impl_from_IDirectDrawSurface2(iface);
4453 
4454     TRACE("iface %p, clipper %p.\n", iface, clipper);
4455 
4456     return ddraw_surface7_GetClipper(&surface->IDirectDrawSurface7_iface, clipper);
4457 }
4458 
4459 static HRESULT WINAPI ddraw_surface1_GetClipper(IDirectDrawSurface *iface, IDirectDrawClipper **clipper)
4460 {
4461     struct ddraw_surface *surface = impl_from_IDirectDrawSurface(iface);
4462 
4463     TRACE("iface %p, clipper %p.\n", iface, clipper);
4464 
4465     return ddraw_surface7_GetClipper(&surface->IDirectDrawSurface7_iface, clipper);
4466 }
4467 
4468 /*****************************************************************************
4469  * IDirectDrawSurface7::SetClipper
4470  *
4471  * Sets a clipper for the surface
4472  *
4473  * Params:
4474  *  Clipper: IDirectDrawClipper interface of the clipper to set
4475  *
4476  * Returns:
4477  *  DD_OK on success
4478  *
4479  *****************************************************************************/
4480 static HRESULT WINAPI ddraw_surface7_SetClipper(IDirectDrawSurface7 *iface,
4481         IDirectDrawClipper *iclipper)
4482 {
4483     struct ddraw_surface *This = impl_from_IDirectDrawSurface7(iface);
4484     struct ddraw_clipper *clipper = unsafe_impl_from_IDirectDrawClipper(iclipper);
4485     struct ddraw_clipper *old_clipper = This->clipper;
4486     HWND clipWindow;
4487 
4488     TRACE("iface %p, clipper %p.\n", iface, iclipper);
4489 
4490     wined3d_mutex_lock();
4491     if (clipper == This->clipper)
4492     {
4493         wined3d_mutex_unlock();
4494         return DD_OK;
4495     }
4496 
4497     This->clipper = clipper;
4498 
4499     if (clipper != NULL)
4500         IDirectDrawClipper_AddRef(iclipper);
4501     if (old_clipper)
4502         IDirectDrawClipper_Release(&old_clipper->IDirectDrawClipper_iface);
4503 
4504     if ((This->surface_desc.ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE) && This->ddraw->wined3d_swapchain)
4505     {
4506         clipWindow = NULL;
4507         if(clipper) {
4508             IDirectDrawClipper_GetHWnd(iclipper, &clipWindow);
4509         }
4510 
4511         if (clipWindow)
4512         {
4513             wined3d_swapchain_set_window(This->ddraw->wined3d_swapchain, clipWindow);
4514             ddraw_set_swapchain_window(This->ddraw, clipWindow);
4515         }
4516         else
4517         {
4518             wined3d_swapchain_set_window(This->ddraw->wined3d_swapchain, This->ddraw->d3d_window);
4519             ddraw_set_swapchain_window(This->ddraw, This->ddraw->dest_window);
4520         }
4521     }
4522 
4523     wined3d_mutex_unlock();
4524 
4525     return DD_OK;
4526 }
4527 
4528 static HRESULT WINAPI ddraw_surface4_SetClipper(IDirectDrawSurface4 *iface, IDirectDrawClipper *clipper)
4529 {
4530     struct ddraw_surface *surface = impl_from_IDirectDrawSurface4(iface);
4531 
4532     TRACE("iface %p, clipper %p.\n", iface, clipper);
4533 
4534     return ddraw_surface7_SetClipper(&surface->IDirectDrawSurface7_iface, clipper);
4535 }
4536 
4537 static HRESULT WINAPI ddraw_surface3_SetClipper(IDirectDrawSurface3 *iface, IDirectDrawClipper *clipper)
4538 {
4539     struct ddraw_surface *surface = impl_from_IDirectDrawSurface3(iface);
4540 
4541     TRACE("iface %p, clipper %p.\n", iface, clipper);
4542 
4543     return ddraw_surface7_SetClipper(&surface->IDirectDrawSurface7_iface, clipper);
4544 }
4545 
4546 static HRESULT WINAPI ddraw_surface2_SetClipper(IDirectDrawSurface2 *iface, IDirectDrawClipper *clipper)
4547 {
4548     struct ddraw_surface *surface = impl_from_IDirectDrawSurface2(iface);
4549 
4550     TRACE("iface %p, clipper %p.\n", iface, clipper);
4551 
4552     return ddraw_surface7_SetClipper(&surface->IDirectDrawSurface7_iface, clipper);
4553 }
4554 
4555 static HRESULT WINAPI ddraw_surface1_SetClipper(IDirectDrawSurface *iface, IDirectDrawClipper *clipper)
4556 {
4557     struct ddraw_surface *surface = impl_from_IDirectDrawSurface(iface);
4558 
4559     TRACE("iface %p, clipper %p.\n", iface, clipper);
4560 
4561     return ddraw_surface7_SetClipper(&surface->IDirectDrawSurface7_iface, clipper);
4562 }
4563 
4564 /*****************************************************************************
4565  * IDirectDrawSurface7::SetSurfaceDesc
4566  *
4567  * Sets the surface description. It can override the pixel format, the surface
4568  * memory, ...
4569  * It's not really tested.
4570  *
4571  * Params:
4572  * DDSD: Pointer to the new surface description to set
4573  * Flags: Some flags
4574  *
4575  * Returns:
4576  *  DD_OK on success
4577  *  DDERR_INVALIDPARAMS if DDSD is NULL
4578  *
4579  *****************************************************************************/
4580 static HRESULT WINAPI ddraw_surface7_SetSurfaceDesc(IDirectDrawSurface7 *iface, DDSURFACEDESC2 *DDSD, DWORD Flags)
4581 {
4582     struct ddraw_surface *This = impl_from_IDirectDrawSurface7(iface);
4583     HRESULT hr;
4584     const DWORD allowed_flags = DDSD_LPSURFACE | DDSD_PIXELFORMAT | DDSD_WIDTH
4585             | DDSD_HEIGHT | DDSD_PITCH | DDSD_CAPS;
4586     enum wined3d_format_id format_id;
4587     UINT pitch, width, height;
4588 
4589     TRACE("iface %p, surface_desc %p, flags %#x.\n", iface, DDSD, Flags);
4590 
4591     if (!DDSD)
4592     {
4593         WARN("DDSD is NULL, returning DDERR_INVALIDPARAMS\n");
4594         return DDERR_INVALIDPARAMS;
4595     }
4596     if (Flags)
4597     {
4598         WARN("Flags is %x, returning DDERR_INVALIDPARAMS\n", Flags);
4599         return DDERR_INVALIDPARAMS;
4600     }
4601     if (!(This->surface_desc.ddsCaps.dwCaps & DDSCAPS_SYSTEMMEMORY)
4602             || This->surface_desc.ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE
4603             || This->surface_desc.ddsCaps.dwCaps2 & (DDSCAPS2_TEXTUREMANAGE | DDSCAPS2_D3DTEXTUREMANAGE))
4604     {
4605         WARN("Surface is not in system memory, returning DDERR_INVALIDSURFACETYPE.\n");
4606         return DDERR_INVALIDSURFACETYPE;
4607     }
4608 
4609     /* Tests show that only LPSURFACE and PIXELFORMAT can be set, and LPSURFACE is required
4610      * for PIXELFORMAT to work */
4611     if (DDSD->dwFlags & ~allowed_flags)
4612     {
4613         WARN("Invalid flags (0x%08x) set, returning DDERR_INVALIDPARAMS\n", DDSD->dwFlags);
4614         return DDERR_INVALIDPARAMS;
4615     }
4616     if (!(DDSD->dwFlags & DDSD_LPSURFACE) || !DDSD->lpSurface)
4617     {
4618         WARN("DDSD_LPSURFACE is not set or lpSurface is NULL, returning DDERR_INVALIDPARAMS\n");
4619         return DDERR_INVALIDPARAMS;
4620     }
4621     if ((DDSD->dwFlags & DDSD_CAPS) && DDSD->ddsCaps.dwCaps)
4622     {
4623         WARN("DDSD_CAPS is set, returning DDERR_INVALIDCAPS.\n");
4624         return DDERR_INVALIDCAPS;
4625     }
4626     if (DDSD->dwFlags & DDSD_WIDTH)
4627     {
4628         if (!(DDSD->dwFlags & DDSD_PITCH))
4629         {
4630             WARN("DDSD_WIDTH is set, but DDSD_PITCH is not, returning DDERR_INVALIDPARAMS.\n");
4631             return DDERR_INVALIDPARAMS;
4632         }
4633         if (!DDSD->dwWidth || DDSD->u1.lPitch <= 0 || DDSD->u1.lPitch & 0x3)
4634         {
4635             WARN("Pitch is %d, width is %u, returning DDERR_INVALIDPARAMS.\n",
4636                     DDSD->u1.lPitch, DDSD->dwWidth);
4637             return DDERR_INVALIDPARAMS;
4638         }
4639         if (DDSD->dwWidth != This->surface_desc.dwWidth)
4640             TRACE("Surface width changed from %u to %u.\n", This->surface_desc.dwWidth, DDSD->dwWidth);
4641         if (DDSD->u1.lPitch != This->surface_desc.u1.lPitch)
4642             TRACE("Surface pitch changed from %u to %u.\n", This->surface_desc.u1.lPitch, DDSD->u1.lPitch);
4643         pitch = DDSD->u1.lPitch;
4644         width = DDSD->dwWidth;
4645     }
4646     else if (DDSD->dwFlags & DDSD_PITCH)
4647     {
4648         WARN("DDSD_PITCH is set, but DDSD_WIDTH is not, returning DDERR_INVALIDPARAMS.\n");
4649         return DDERR_INVALIDPARAMS;
4650     }
4651     else
4652     {
4653         pitch = This->surface_desc.u1.lPitch;
4654         width = This->surface_desc.dwWidth;
4655     }
4656 
4657     if (DDSD->dwFlags & DDSD_HEIGHT)
4658     {
4659         if (!DDSD->dwHeight)
4660         {
4661             WARN("Height is 0, returning DDERR_INVALIDPARAMS.\n");
4662             return DDERR_INVALIDPARAMS;
4663         }
4664         if (DDSD->dwHeight != This->surface_desc.dwHeight)
4665             TRACE("Surface height changed from %u to %u.\n", This->surface_desc.dwHeight, DDSD->dwHeight);
4666         height = DDSD->dwHeight;
4667     }
4668     else
4669     {
4670         height = This->surface_desc.dwHeight;
4671     }
4672 
4673     wined3d_mutex_lock();
4674     if (DDSD->dwFlags & DDSD_PIXELFORMAT)
4675     {
4676         enum wined3d_format_id current_format_id;
4677         format_id = wined3dformat_from_ddrawformat(&DDSD->u4.ddpfPixelFormat);
4678 
4679         if (format_id == WINED3DFMT_UNKNOWN)
4680         {
4681             ERR("Requested to set an unknown pixelformat\n");
4682             wined3d_mutex_unlock();
4683             return DDERR_INVALIDPARAMS;
4684         }
4685         current_format_id = wined3dformat_from_ddrawformat(&This->surface_desc.u4.ddpfPixelFormat);
4686         if (format_id != current_format_id)
4687             TRACE("Surface format changed from %#x to %#x.\n", current_format_id, format_id);
4688     }
4689     else
4690     {
4691         format_id = wined3dformat_from_ddrawformat(&This->surface_desc.u4.ddpfPixelFormat);
4692     }
4693 
4694     if (FAILED(hr = wined3d_texture_update_desc(This->wined3d_texture, width, height,
4695             format_id, WINED3D_MULTISAMPLE_NONE, 0, DDSD->lpSurface, pitch)))
4696     {
4697         WARN("Failed to update surface desc, hr %#x.\n", hr);
4698         wined3d_mutex_unlock();
4699         return hr_ddraw_from_wined3d(hr);
4700     }
4701 
4702     if (DDSD->dwFlags & DDSD_WIDTH)
4703         This->surface_desc.dwWidth = width;
4704     if (DDSD->dwFlags & DDSD_PITCH)
4705         This->surface_desc.u1.lPitch = DDSD->u1.lPitch;
4706     if (DDSD->dwFlags & DDSD_HEIGHT)
4707         This->surface_desc.dwHeight = height;
4708     if (DDSD->dwFlags & DDSD_PIXELFORMAT)
4709         This->surface_desc.u4.ddpfPixelFormat = DDSD->u4.ddpfPixelFormat;
4710 
4711     wined3d_mutex_unlock();
4712 
4713     return DD_OK;
4714 }
4715 
4716 static HRESULT WINAPI ddraw_surface4_SetSurfaceDesc(IDirectDrawSurface4 *iface,
4717         DDSURFACEDESC2 *surface_desc, DWORD flags)
4718 {
4719     struct ddraw_surface *surface = impl_from_IDirectDrawSurface4(iface);
4720 
4721     TRACE("iface %p, surface_desc %p, flags %#x.\n", iface, surface_desc, flags);
4722 
4723     return ddraw_surface7_SetSurfaceDesc(&surface->IDirectDrawSurface7_iface,
4724             surface_desc, flags);
4725 }
4726 
4727 static HRESULT WINAPI ddraw_surface3_SetSurfaceDesc(IDirectDrawSurface3 *iface,
4728         DDSURFACEDESC *surface_desc, DWORD flags)
4729 {
4730     struct ddraw_surface *surface = impl_from_IDirectDrawSurface3(iface);
4731     DDSURFACEDESC2 surface_desc2;
4732 
4733     TRACE("iface %p, surface_desc %p, flags %#x.\n", iface, surface_desc, flags);
4734 
4735     if (surface_desc) DDSD_to_DDSD2(surface_desc, &surface_desc2);
4736     return ddraw_surface7_SetSurfaceDesc(&surface->IDirectDrawSurface7_iface,
4737             surface_desc ? &surface_desc2 : NULL, flags);
4738 }
4739 
4740 static HRESULT WINAPI ddraw_surface7_GetPalette(IDirectDrawSurface7 *iface, IDirectDrawPalette **palette)
4741 {
4742     struct ddraw_surface *surface = impl_from_IDirectDrawSurface7(iface);
4743     struct ddraw_palette *palette_impl;
4744     HRESULT hr = DD_OK;
4745 
4746     TRACE("iface %p, palette %p.\n", iface, palette);
4747 
4748     if (!palette)
4749         return DDERR_INVALIDPARAMS;
4750     if (IDirectDrawSurface7_IsLost(iface) == DDERR_SURFACELOST)
4751     {
4752         WARN("Surface lost, returning DDERR_SURFACELOST.\n");
4753         return DDERR_SURFACELOST;
4754     }
4755 
4756     wined3d_mutex_lock();
4757     if ((palette_impl = surface->palette))
4758     {
4759         *palette = &palette_impl->IDirectDrawPalette_iface;
4760         IDirectDrawPalette_AddRef(*palette);
4761     }
4762     else
4763     {
4764         *palette = NULL;
4765         hr = DDERR_NOPALETTEATTACHED;
4766     }
4767     wined3d_mutex_unlock();
4768 
4769     return hr;
4770 }
4771 
4772 static HRESULT WINAPI ddraw_surface4_GetPalette(IDirectDrawSurface4 *iface, IDirectDrawPalette **palette)
4773 {
4774     struct ddraw_surface *surface = impl_from_IDirectDrawSurface4(iface);
4775 
4776     TRACE("iface %p, palette %p.\n", iface, palette);
4777 
4778     return ddraw_surface7_GetPalette(&surface->IDirectDrawSurface7_iface, palette);
4779 }
4780 
4781 static HRESULT WINAPI ddraw_surface3_GetPalette(IDirectDrawSurface3 *iface, IDirectDrawPalette **palette)
4782 {
4783     struct ddraw_surface *surface = impl_from_IDirectDrawSurface3(iface);
4784 
4785     TRACE("iface %p, palette %p.\n", iface, palette);
4786 
4787     return ddraw_surface7_GetPalette(&surface->IDirectDrawSurface7_iface, palette);
4788 }
4789 
4790 static HRESULT WINAPI ddraw_surface2_GetPalette(IDirectDrawSurface2 *iface, IDirectDrawPalette **palette)
4791 {
4792     struct ddraw_surface *surface = impl_from_IDirectDrawSurface2(iface);
4793 
4794     TRACE("iface %p, palette %p.\n", iface, palette);
4795 
4796     return ddraw_surface7_GetPalette(&surface->IDirectDrawSurface7_iface, palette);
4797 }
4798 
4799 static HRESULT WINAPI ddraw_surface1_GetPalette(IDirectDrawSurface *iface, IDirectDrawPalette **palette)
4800 {
4801     struct ddraw_surface *surface = impl_from_IDirectDrawSurface(iface);
4802 
4803     TRACE("iface %p, palette %p.\n", iface, palette);
4804 
4805     return ddraw_surface7_GetPalette(&surface->IDirectDrawSurface7_iface, palette);
4806 }
4807 
4808 static HRESULT ddraw_surface_set_color_key(struct ddraw_surface *surface, DWORD flags, DDCOLORKEY *color_key)
4809 {
4810     DDCOLORKEY fixed_color_key;
4811     HRESULT hr = WINED3D_OK;
4812 
4813     if (flags & DDCKEY_COLORSPACE)
4814     {
4815         if (color_key && color_key->dwColorSpaceLowValue != color_key->dwColorSpaceHighValue)
4816         {
4817             WARN("Range color keys are not supported, returning DDERR_NOCOLORKEYHW.\n");
4818             return DDERR_NOCOLORKEYHW;
4819         }
4820         flags &= ~DDCKEY_COLORSPACE;
4821     }
4822 
4823     wined3d_mutex_lock();
4824 
4825     if (color_key)
4826     {
4827         fixed_color_key.dwColorSpaceLowValue = fixed_color_key.dwColorSpaceHighValue = color_key->dwColorSpaceLowValue;
4828         switch (flags & ~DDCKEY_COLORSPACE)
4829         {
4830             case DDCKEY_DESTBLT:
4831                 surface->surface_desc.ddckCKDestBlt = fixed_color_key;
4832                 surface->surface_desc.dwFlags |= DDSD_CKDESTBLT;
4833                 break;
4834 
4835             case DDCKEY_DESTOVERLAY:
4836                 surface->surface_desc.u3.ddckCKDestOverlay = fixed_color_key;
4837                 surface->surface_desc.dwFlags |= DDSD_CKDESTOVERLAY;
4838                 break;
4839 
4840             case DDCKEY_SRCOVERLAY:
4841                 surface->surface_desc.ddckCKSrcOverlay = fixed_color_key;
4842                 surface->surface_desc.dwFlags |= DDSD_CKSRCOVERLAY;
4843                 break;
4844 
4845             case DDCKEY_SRCBLT:
4846                 surface->surface_desc.ddckCKSrcBlt = fixed_color_key;
4847                 surface->surface_desc.dwFlags |= DDSD_CKSRCBLT;
4848                 break;
4849 
4850             default:
4851                 wined3d_mutex_unlock();
4852                 return DDERR_INVALIDPARAMS;
4853         }
4854     }
4855     else
4856     {
4857         switch (flags & ~DDCKEY_COLORSPACE)
4858         {
4859             case DDCKEY_DESTBLT:
4860                 surface->surface_desc.dwFlags &= ~DDSD_CKDESTBLT;
4861                 break;
4862 
4863             case DDCKEY_DESTOVERLAY:
4864                 surface->surface_desc.dwFlags &= ~DDSD_CKDESTOVERLAY;
4865                 break;
4866 
4867             case DDCKEY_SRCOVERLAY:
4868                 surface->surface_desc.dwFlags &= ~DDSD_CKSRCOVERLAY;
4869                 break;
4870 
4871             case DDCKEY_SRCBLT:
4872                 surface->surface_desc.dwFlags &= ~DDSD_CKSRCBLT;
4873                 break;
4874 
4875             default:
4876                 wined3d_mutex_unlock();
4877                 return DDERR_INVALIDPARAMS;
4878         }
4879     }
4880 
4881     if (surface->is_complex_root)
4882         hr = wined3d_texture_set_color_key(surface->wined3d_texture, flags,
4883                 color_key ? (struct wined3d_color_key *)&fixed_color_key : NULL);
4884 
4885     wined3d_mutex_unlock();
4886 
4887     return hr_ddraw_from_wined3d(hr);
4888 }
4889 
4890 static HRESULT WINAPI ddraw_surface7_SetColorKey(IDirectDrawSurface7 *iface, DWORD flags, DDCOLORKEY *color_key)
4891 {
4892     struct ddraw_surface *surface = impl_from_IDirectDrawSurface7(iface);
4893 
4894     TRACE("iface %p, flags %#x, color_key %p.\n", iface, flags, color_key);
4895 
4896     if (surface->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_MIPMAPSUBLEVEL)
4897         return DDERR_NOTONMIPMAPSUBLEVEL;
4898 
4899     return ddraw_surface_set_color_key(surface, flags, color_key);
4900 }
4901 
4902 static HRESULT WINAPI ddraw_surface4_SetColorKey(IDirectDrawSurface4 *iface, DWORD flags, DDCOLORKEY *color_key)
4903 {
4904     struct ddraw_surface *surface = impl_from_IDirectDrawSurface4(iface);
4905 
4906     TRACE("iface %p, flags %#x, color_key %p.\n", iface, flags, color_key);
4907 
4908     return ddraw_surface_set_color_key(surface, flags, color_key);
4909 }
4910 
4911 static HRESULT WINAPI ddraw_surface3_SetColorKey(IDirectDrawSurface3 *iface, DWORD flags, DDCOLORKEY *color_key)
4912 {
4913     struct ddraw_surface *surface = impl_from_IDirectDrawSurface3(iface);
4914 
4915     TRACE("iface %p, flags %#x, color_key %p.\n", iface, flags, color_key);
4916 
4917     return ddraw_surface_set_color_key(surface, flags, color_key);
4918 }
4919 
4920 static HRESULT WINAPI ddraw_surface2_SetColorKey(IDirectDrawSurface2 *iface, DWORD flags, DDCOLORKEY *color_key)
4921 {
4922     struct ddraw_surface *surface = impl_from_IDirectDrawSurface2(iface);
4923 
4924     TRACE("iface %p, flags %#x, color_key %p.\n", iface, flags, color_key);
4925 
4926     return ddraw_surface_set_color_key(surface, flags, color_key);
4927 }
4928 
4929 static HRESULT WINAPI ddraw_surface1_SetColorKey(IDirectDrawSurface *iface, DWORD flags, DDCOLORKEY *color_key)
4930 {
4931     struct ddraw_surface *surface = impl_from_IDirectDrawSurface(iface);
4932 
4933     TRACE("iface %p, flags %#x, color_key %p.\n", iface, flags, color_key);
4934 
4935     return ddraw_surface_set_color_key(surface, flags, color_key);
4936 }
4937 
4938 static HRESULT WINAPI ddraw_surface7_SetPalette(IDirectDrawSurface7 *iface, IDirectDrawPalette *palette)
4939 {
4940     struct ddraw_surface *surface = impl_from_IDirectDrawSurface7(iface);
4941 
4942     TRACE("iface %p, palette %p.\n", iface, palette);
4943 
4944     if (surface->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_MIPMAPSUBLEVEL)
4945         return DDERR_NOTONMIPMAPSUBLEVEL;
4946     if (IDirectDrawSurface7_IsLost(iface) == DDERR_SURFACELOST)
4947     {
4948         WARN("Surface lost, returning DDERR_SURFACELOST.\n");
4949         return DDERR_SURFACELOST;
4950     }
4951 
4952     return ddraw_surface_set_palette(surface, palette);
4953 }
4954 
4955 static HRESULT WINAPI ddraw_surface4_SetPalette(IDirectDrawSurface4 *iface, IDirectDrawPalette *palette)
4956 {
4957     struct ddraw_surface *surface = impl_from_IDirectDrawSurface4(iface);
4958 
4959     TRACE("iface %p, palette %p.\n", iface, palette);
4960 
4961     if (IDirectDrawSurface4_IsLost(iface) == DDERR_SURFACELOST)
4962     {
4963         WARN("Surface lost, returning DDERR_SURFACELOST.\n");
4964         return DDERR_SURFACELOST;
4965     }
4966 
4967     return ddraw_surface_set_palette(surface, palette);
4968 }
4969 
4970 static HRESULT WINAPI ddraw_surface3_SetPalette(IDirectDrawSurface3 *iface, IDirectDrawPalette *palette)
4971 {
4972     struct ddraw_surface *surface = impl_from_IDirectDrawSurface3(iface);
4973 
4974     TRACE("iface %p, palette %p.\n", iface, palette);
4975 
4976     if (IDirectDrawSurface3_IsLost(iface) == DDERR_SURFACELOST)
4977     {
4978         WARN("Surface lost, returning DDERR_SURFACELOST.\n");
4979         return DDERR_SURFACELOST;
4980     }
4981 
4982     return ddraw_surface_set_palette(surface, palette);
4983 }
4984 
4985 static HRESULT WINAPI ddraw_surface2_SetPalette(IDirectDrawSurface2 *iface, IDirectDrawPalette *palette)
4986 {
4987     struct ddraw_surface *surface = impl_from_IDirectDrawSurface2(iface);
4988 
4989     TRACE("iface %p, palette %p.\n", iface, palette);
4990 
4991     if (IDirectDrawSurface2_IsLost(iface) == DDERR_SURFACELOST)
4992     {
4993         WARN("Surface lost, returning DDERR_SURFACELOST.\n");
4994         return DDERR_SURFACELOST;
4995     }
4996 
4997     return ddraw_surface_set_palette(surface, palette);
4998 }
4999 
5000 static HRESULT WINAPI ddraw_surface1_SetPalette(IDirectDrawSurface *iface, IDirectDrawPalette *palette)
5001 {
5002     struct ddraw_surface *surface = impl_from_IDirectDrawSurface(iface);
5003 
5004     TRACE("iface %p, palette %p.\n", iface, palette);
5005 
5006     if (IDirectDrawSurface_IsLost(iface) == DDERR_SURFACELOST)
5007     {
5008         WARN("Surface lost, returning DDERR_SURFACELOST.\n");
5009         return DDERR_SURFACELOST;
5010     }
5011 
5012     return ddraw_surface_set_palette(surface, palette);
5013 }
5014 
5015 /**********************************************************
5016  * IDirectDrawGammaControl::GetGammaRamp
5017  *
5018  * Returns the current gamma ramp for a surface
5019  *
5020  * Params:
5021  *  flags: Ignored
5022  *  gamma_ramp: Address to write the ramp to
5023  *
5024  * Returns:
5025  *  DD_OK on success
5026  *  DDERR_INVALIDPARAMS if gamma_ramp is NULL
5027  *
5028  **********************************************************/
5029 static HRESULT WINAPI ddraw_gamma_control_GetGammaRamp(IDirectDrawGammaControl *iface,
5030         DWORD flags, DDGAMMARAMP *gamma_ramp)
5031 {
5032     struct ddraw_surface *surface = impl_from_IDirectDrawGammaControl(iface);
5033 
5034     TRACE("iface %p, flags %#x, gamma_ramp %p.\n", iface, flags, gamma_ramp);
5035 
5036     if (!gamma_ramp)
5037     {
5038         WARN("Invalid gamma_ramp passed.\n");
5039         return DDERR_INVALIDPARAMS;
5040     }
5041 
5042     wined3d_mutex_lock();
5043     if (surface->surface_desc.ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE)
5044     {
5045         /* Note: DDGAMMARAMP is compatible with struct wined3d_gamma_ramp. */
5046         wined3d_device_get_gamma_ramp(surface->ddraw->wined3d_device, 0, (struct wined3d_gamma_ramp *)gamma_ramp);
5047     }
5048     else
5049     {
5050         ERR("Not implemented for non-primary surfaces.\n");
5051     }
5052     wined3d_mutex_unlock();
5053 
5054     return DD_OK;
5055 }
5056 
5057 /**********************************************************
5058  * IDirectDrawGammaControl::SetGammaRamp
5059  *
5060  * Sets the red, green and blue gamma ramps for
5061  *
5062  * Params:
5063  *  flags: Can be DDSGR_CALIBRATE to request calibration
5064  *  gamma_ramp: Structure containing the new gamma ramp
5065  *
5066  * Returns:
5067  *  DD_OK on success
5068  *  DDERR_INVALIDPARAMS if gamma_ramp is NULL
5069  *
5070  **********************************************************/
5071 static HRESULT WINAPI ddraw_gamma_control_SetGammaRamp(IDirectDrawGammaControl *iface,
5072         DWORD flags, DDGAMMARAMP *gamma_ramp)
5073 {
5074     struct ddraw_surface *surface = impl_from_IDirectDrawGammaControl(iface);
5075 
5076     TRACE("iface %p, flags %#x, gamma_ramp %p.\n", iface, flags, gamma_ramp);
5077 
5078     if (!gamma_ramp)
5079     {
5080         WARN("Invalid gamma_ramp passed.\n");
5081         return DDERR_INVALIDPARAMS;
5082     }
5083 
5084     wined3d_mutex_lock();
5085     if (surface->surface_desc.ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE)
5086     {
5087         /* Note: DDGAMMARAMP is compatible with struct wined3d_gamma_ramp. */
5088         wined3d_device_set_gamma_ramp(surface->ddraw->wined3d_device,
5089                 0, flags, (struct wined3d_gamma_ramp *)gamma_ramp);
5090     }
5091     else
5092     {
5093         ERR("Not implemented for non-primary surfaces.\n");
5094     }
5095     wined3d_mutex_unlock();
5096 
5097     return DD_OK;
5098 }
5099 
5100 /*****************************************************************************
5101  * IDirect3DTexture2::PaletteChanged
5102  *
5103  * Informs the texture about a palette change
5104  *
5105  * Params:
5106  *  start: Start index of the change
5107  *  count: The number of changed entries
5108  *
5109  * Returns
5110  *  D3D_OK, because it's a stub
5111  *
5112  *****************************************************************************/
5113 static HRESULT WINAPI d3d_texture2_PaletteChanged(IDirect3DTexture2 *iface, DWORD start, DWORD count)
5114 {
5115     FIXME("iface %p, start %u, count %u stub!\n", iface, start, count);
5116 
5117     return D3D_OK;
5118 }
5119 
5120 static HRESULT WINAPI d3d_texture1_PaletteChanged(IDirect3DTexture *iface, DWORD start, DWORD count)
5121 {
5122     struct ddraw_surface *surface = impl_from_IDirect3DTexture(iface);
5123 
5124     TRACE("iface %p, start %u, count %u.\n", iface, start, count);
5125 
5126     return d3d_texture2_PaletteChanged(&surface->IDirect3DTexture2_iface, start, count);
5127 }
5128 
5129 /*****************************************************************************
5130  * IDirect3DTexture::Unload
5131  *
5132  * DX5 SDK: "The IDirect3DTexture2::Unload method is not implemented
5133  *
5134  *
5135  * Returns:
5136  *  DDERR_UNSUPPORTED
5137  *
5138  *****************************************************************************/
5139 static HRESULT WINAPI d3d_texture1_Unload(IDirect3DTexture *iface)
5140 {
5141     WARN("iface %p. Not implemented.\n", iface);
5142 
5143     return DDERR_UNSUPPORTED;
5144 }
5145 
5146 /*****************************************************************************
5147  * IDirect3DTexture2::GetHandle
5148  *
5149  * Returns handle for the texture.
5150  *
5151  * Params:
5152  *  device: Device this handle is assigned to
5153  *  handle: Address to store the handle at.
5154  *
5155  * Returns:
5156  *  D3D_OK
5157  *
5158  *****************************************************************************/
5159 static HRESULT WINAPI d3d_texture2_GetHandle(IDirect3DTexture2 *iface,
5160         IDirect3DDevice2 *device, D3DTEXTUREHANDLE *handle)
5161 {
5162     struct ddraw_surface *surface = impl_from_IDirect3DTexture2(iface);
5163     struct d3d_device *device_impl = unsafe_impl_from_IDirect3DDevice2(device);
5164 
5165     TRACE("iface %p, device %p, handle %p.\n", iface, device, handle);
5166 
5167     wined3d_mutex_lock();
5168 
5169     if (!surface->Handle)
5170     {
5171         DWORD h = ddraw_allocate_handle(&device_impl->handle_table, surface, DDRAW_HANDLE_SURFACE);
5172         if (h == DDRAW_INVALID_HANDLE)
5173         {
5174             ERR("Failed to allocate a texture handle.\n");
5175             wined3d_mutex_unlock();
5176             return DDERR_OUTOFMEMORY;
5177         }
5178 
5179         surface->Handle = h + 1;
5180     }
5181 
5182     TRACE("Returning handle %08x.\n", surface->Handle);
5183     *handle = surface->Handle;
5184 
5185     wined3d_mutex_unlock();
5186 
5187     return D3D_OK;
5188 }
5189 
5190 static HRESULT WINAPI d3d_texture1_GetHandle(IDirect3DTexture *iface,
5191         IDirect3DDevice *device, D3DTEXTUREHANDLE *handle)
5192 {
5193     struct ddraw_surface *surface = impl_from_IDirect3DTexture(iface);
5194     struct d3d_device *device_impl = unsafe_impl_from_IDirect3DDevice(device);
5195 
5196     TRACE("iface %p, device %p, handle %p.\n", iface, device, handle);
5197 
5198     return d3d_texture2_GetHandle(&surface->IDirect3DTexture2_iface,
5199             device_impl ? &device_impl->IDirect3DDevice2_iface : NULL, handle);
5200 }
5201 
5202 /*****************************************************************************
5203  * get_sub_mimaplevel
5204  *
5205  * Helper function that returns the next mipmap level
5206  *
5207  * tex_ptr: Surface of which to return the next level
5208  *
5209  *****************************************************************************/
5210 static struct ddraw_surface *get_sub_mimaplevel(struct ddraw_surface *surface)
5211 {
5212     /* Now go down the mipmap chain to the next surface */
5213     static DDSCAPS2 mipmap_caps = { DDSCAPS_MIPMAP | DDSCAPS_TEXTURE, 0, 0, {0} };
5214     IDirectDrawSurface7 *next_level;
5215     HRESULT hr;
5216 
5217     hr = ddraw_surface7_GetAttachedSurface(&surface->IDirectDrawSurface7_iface, &mipmap_caps, &next_level);
5218     if (FAILED(hr)) return NULL;
5219 
5220     ddraw_surface7_Release(next_level);
5221 
5222     return impl_from_IDirectDrawSurface7(next_level);
5223 }
5224 
5225 static BOOL compare_format(DDPIXELFORMAT *format1, DDPIXELFORMAT *format2)
5226 {
5227     if ((format1->dwFlags & (DDPF_RGB|DDPF_YUV|DDPF_FOURCC)) !=
5228         (format2->dwFlags & (DDPF_RGB|DDPF_YUV|DDPF_FOURCC)))
5229         return FALSE;
5230 
5231     if (format1->dwFlags & (DDPF_RGB|DDPF_YUV))
5232     {
5233         if (!(format1->dwFlags & DDPF_ALPHA))
5234         {
5235             /* The RGB and YUV bits are stored in the same fields */
5236             if (format1->u1.dwRGBBitCount != format2->u1.dwRGBBitCount)
5237                 return FALSE;
5238 
5239             if (format1->u2.dwRBitMask != format2->u2.dwRBitMask)
5240                 return FALSE;
5241 
5242             if (format1->u3.dwGBitMask != format2->u3.dwGBitMask)
5243                 return FALSE;
5244 
5245             if (format1->u4.dwBBitMask != format2->u4.dwBBitMask)
5246                 return FALSE;
5247         }
5248 
5249         if (format1->dwFlags & (DDPF_ALPHAPIXELS | DDPF_ALPHA))
5250         {
5251             if (format1->u5.dwRGBAlphaBitMask != format2->u5.dwRGBAlphaBitMask)
5252                 return FALSE;
5253         }
5254     }
5255 
5256     if (format1->dwFlags & DDPF_FOURCC)
5257     {
5258         if (format1->dwFourCC != format2->dwFourCC)
5259             return FALSE;
5260     }
5261 
5262     return TRUE;
5263 }
5264 
5265 /*****************************************************************************
5266  * IDirect3DTexture2::Load
5267  *
5268  * Loads a texture created with the DDSCAPS_ALLOCONLOAD
5269  *
5270  * This function isn't relayed to WineD3D because the whole interface is
5271  * implemented in DDraw only. For speed improvements an implementation which
5272  * takes OpenGL more into account could be placed into WineD3D.
5273  *
5274  * Params:
5275  *  src_texture: Address of the texture to load
5276  *
5277  * Returns:
5278  *  D3D_OK on success
5279  *  D3DERR_TEXTURE_LOAD_FAILED.
5280  *
5281  *****************************************************************************/
5282 static HRESULT WINAPI d3d_texture2_Load(IDirect3DTexture2 *iface, IDirect3DTexture2 *src_texture)
5283 {
5284     struct ddraw_surface *dst_surface = impl_from_IDirect3DTexture2(iface);
5285     struct ddraw_surface *src_surface = unsafe_impl_from_IDirect3DTexture2(src_texture);
5286     RECT src_rect, dst_rect;
5287     HRESULT hr;
5288 
5289     TRACE("iface %p, src_texture %p.\n", iface, src_texture);
5290 
5291     if (src_surface == dst_surface)
5292     {
5293         TRACE("copying surface %p to surface %p, why?\n", src_surface, dst_surface);
5294         return D3D_OK;
5295     }
5296 
5297     wined3d_mutex_lock();
5298 
5299     for (;;)
5300     {
5301         DDSURFACEDESC *src_desc = (DDSURFACEDESC *)&src_surface->surface_desc;
5302 
5303         TRACE("Copying surface %p to surface %p.\n", src_surface, dst_surface);
5304 
5305         if (compare_format(&src_surface->surface_desc.u4.ddpfPixelFormat,
5306                            &dst_surface->surface_desc.u4.ddpfPixelFormat))
5307         {
5308             struct ddraw_palette *dst_pal, *src_pal;
5309 
5310             /* Get the palettes */
5311             dst_pal = dst_surface->palette;
5312             src_pal = src_surface->palette;
5313 
5314             if (src_pal)
5315             {
5316                 PALETTEENTRY palent[256];
5317 
5318                 if (!dst_pal)
5319                 {
5320                     wined3d_mutex_unlock();
5321                     return DDERR_NOPALETTEATTACHED;
5322                 }
5323                 IDirectDrawPalette_GetEntries(&src_pal->IDirectDrawPalette_iface, 0, 0, 256, palent);
5324                 IDirectDrawPalette_SetEntries(&dst_pal->IDirectDrawPalette_iface, 0, 0, 256, palent);
5325             }
5326 
5327             if (src_desc->dwFlags & DDSD_CKSRCBLT)
5328             {
5329                 IDirectDrawSurface7_SetColorKey(&dst_surface->IDirectDrawSurface7_iface,
5330                         DDCKEY_SRCBLT, &src_desc->ddckCKSrcBlt);
5331             }
5332         }
5333         else
5334         {
5335             if (src_desc->dwFlags & DDSD_CKSRCBLT)
5336                 return E_FAIL;
5337         }
5338 
5339         /* Suppress the ALLOCONLOAD flag */
5340         dst_surface->surface_desc.ddsCaps.dwCaps &= ~DDSCAPS_ALLOCONLOAD;
5341 
5342         SetRect(&src_rect, 0, 0, src_surface->surface_desc.dwWidth, src_surface->surface_desc.dwHeight);
5343         SetRect(&dst_rect, 0, 0, dst_surface->surface_desc.dwWidth, dst_surface->surface_desc.dwHeight);
5344 
5345         hr = wined3d_texture_blt(dst_surface->wined3d_texture, dst_surface->sub_resource_idx, &dst_rect,
5346                                  src_surface->wined3d_texture, src_surface->sub_resource_idx, &src_rect,
5347                                  0, NULL, WINED3D_TEXF_LINEAR);
5348         if (FAILED(hr))
5349         {
5350             ERR("Failed to blit surface, hr %#x.\n", hr);
5351             wined3d_mutex_unlock();
5352             return hr;
5353         }
5354 
5355         if (src_surface->surface_desc.ddsCaps.dwCaps & DDSCAPS_MIPMAP)
5356             src_surface = get_sub_mimaplevel(src_surface);
5357         else
5358             src_surface = NULL;
5359 
5360         if (dst_surface->surface_desc.ddsCaps.dwCaps & DDSCAPS_MIPMAP)
5361             dst_surface = get_sub_mimaplevel(dst_surface);
5362         else
5363             dst_surface = NULL;
5364 
5365         if (src_surface && !dst_surface)
5366             return DDERR_NOTFOUND;
5367 
5368         if (!src_surface || !dst_surface)
5369             break;
5370     }
5371 
5372     wined3d_mutex_unlock();
5373 
5374     return hr;
5375 }
5376 
5377 static HRESULT WINAPI d3d_texture1_Load(IDirect3DTexture *iface, IDirect3DTexture *src_texture)
5378 {
5379     struct ddraw_surface *dst_surface = impl_from_IDirect3DTexture(iface);
5380     struct ddraw_surface *src_surface = unsafe_impl_from_IDirect3DTexture(src_texture);
5381 
5382     TRACE("iface %p, src_texture %p.\n", iface, src_texture);
5383 
5384     return d3d_texture2_Load(&dst_surface->IDirect3DTexture2_iface,
5385             src_surface ? &src_surface->IDirect3DTexture2_iface : NULL);
5386 }
5387 
5388 /*****************************************************************************
5389  * The VTable
5390  *****************************************************************************/
5391 
5392 static const struct IDirectDrawSurface7Vtbl ddraw_surface7_vtbl =
5393 {
5394     /* IUnknown */
5395     ddraw_surface7_QueryInterface,
5396     ddraw_surface7_AddRef,
5397     ddraw_surface7_Release,
5398     /* IDirectDrawSurface */
5399     ddraw_surface7_AddAttachedSurface,
5400     ddraw_surface7_AddOverlayDirtyRect,
5401     ddraw_surface7_Blt,
5402     ddraw_surface7_BltBatch,
5403     ddraw_surface7_BltFast,
5404     ddraw_surface7_DeleteAttachedSurface,
5405     ddraw_surface7_EnumAttachedSurfaces,
5406     ddraw_surface7_EnumOverlayZOrders,
5407     ddraw_surface7_Flip,
5408     ddraw_surface7_GetAttachedSurface,
5409     ddraw_surface7_GetBltStatus,
5410     ddraw_surface7_GetCaps,
5411     ddraw_surface7_GetClipper,
5412     ddraw_surface7_GetColorKey,
5413     ddraw_surface7_GetDC,
5414     ddraw_surface7_GetFlipStatus,
5415     ddraw_surface7_GetOverlayPosition,
5416     ddraw_surface7_GetPalette,
5417     ddraw_surface7_GetPixelFormat,
5418     ddraw_surface7_GetSurfaceDesc,
5419     ddraw_surface7_Initialize,
5420     ddraw_surface7_IsLost,
5421     ddraw_surface7_Lock,
5422     ddraw_surface7_ReleaseDC,
5423     ddraw_surface7_Restore,
5424     ddraw_surface7_SetClipper,
5425     ddraw_surface7_SetColorKey,
5426     ddraw_surface7_SetOverlayPosition,
5427     ddraw_surface7_SetPalette,
5428     ddraw_surface7_Unlock,
5429     ddraw_surface7_UpdateOverlay,
5430     ddraw_surface7_UpdateOverlayDisplay,
5431     ddraw_surface7_UpdateOverlayZOrder,
5432     /* IDirectDrawSurface2 */
5433     ddraw_surface7_GetDDInterface,
5434     ddraw_surface7_PageLock,
5435     ddraw_surface7_PageUnlock,
5436     /* IDirectDrawSurface3 */
5437     ddraw_surface7_SetSurfaceDesc,
5438     /* IDirectDrawSurface4 */
5439     ddraw_surface7_SetPrivateData,
5440     ddraw_surface7_GetPrivateData,
5441     ddraw_surface7_FreePrivateData,
5442     ddraw_surface7_GetUniquenessValue,
5443     ddraw_surface7_ChangeUniquenessValue,
5444     /* IDirectDrawSurface7 */
5445     ddraw_surface7_SetPriority,
5446     ddraw_surface7_GetPriority,
5447     ddraw_surface7_SetLOD,
5448     ddraw_surface7_GetLOD,
5449 };
5450 
5451 static const struct IDirectDrawSurface4Vtbl ddraw_surface4_vtbl =
5452 {
5453     /* IUnknown */
5454     ddraw_surface4_QueryInterface,
5455     ddraw_surface4_AddRef,
5456     ddraw_surface4_Release,
5457     /* IDirectDrawSurface */
5458     ddraw_surface4_AddAttachedSurface,
5459     ddraw_surface4_AddOverlayDirtyRect,
5460     ddraw_surface4_Blt,
5461     ddraw_surface4_BltBatch,
5462     ddraw_surface4_BltFast,
5463     ddraw_surface4_DeleteAttachedSurface,
5464     ddraw_surface4_EnumAttachedSurfaces,
5465     ddraw_surface4_EnumOverlayZOrders,
5466     ddraw_surface4_Flip,
5467     ddraw_surface4_GetAttachedSurface,
5468     ddraw_surface4_GetBltStatus,
5469     ddraw_surface4_GetCaps,
5470     ddraw_surface4_GetClipper,
5471     ddraw_surface4_GetColorKey,
5472     ddraw_surface4_GetDC,
5473     ddraw_surface4_GetFlipStatus,
5474     ddraw_surface4_GetOverlayPosition,
5475     ddraw_surface4_GetPalette,
5476     ddraw_surface4_GetPixelFormat,
5477     ddraw_surface4_GetSurfaceDesc,
5478     ddraw_surface4_Initialize,
5479     ddraw_surface4_IsLost,
5480     ddraw_surface4_Lock,
5481     ddraw_surface4_ReleaseDC,
5482     ddraw_surface4_Restore,
5483     ddraw_surface4_SetClipper,
5484     ddraw_surface4_SetColorKey,
5485     ddraw_surface4_SetOverlayPosition,
5486     ddraw_surface4_SetPalette,
5487     ddraw_surface4_Unlock,
5488     ddraw_surface4_UpdateOverlay,
5489     ddraw_surface4_UpdateOverlayDisplay,
5490     ddraw_surface4_UpdateOverlayZOrder,
5491     /* IDirectDrawSurface2 */
5492     ddraw_surface4_GetDDInterface,
5493     ddraw_surface4_PageLock,
5494     ddraw_surface4_PageUnlock,
5495     /* IDirectDrawSurface3 */
5496     ddraw_surface4_SetSurfaceDesc,
5497     /* IDirectDrawSurface4 */
5498     ddraw_surface4_SetPrivateData,
5499     ddraw_surface4_GetPrivateData,
5500     ddraw_surface4_FreePrivateData,
5501     ddraw_surface4_GetUniquenessValue,
5502     ddraw_surface4_ChangeUniquenessValue,
5503 };
5504 
5505 static const struct IDirectDrawSurface3Vtbl ddraw_surface3_vtbl =
5506 {
5507     /* IUnknown */
5508     ddraw_surface3_QueryInterface,
5509     ddraw_surface3_AddRef,
5510     ddraw_surface3_Release,
5511     /* IDirectDrawSurface */
5512     ddraw_surface3_AddAttachedSurface,
5513     ddraw_surface3_AddOverlayDirtyRect,
5514     ddraw_surface3_Blt,
5515     ddraw_surface3_BltBatch,
5516     ddraw_surface3_BltFast,
5517     ddraw_surface3_DeleteAttachedSurface,
5518     ddraw_surface3_EnumAttachedSurfaces,
5519     ddraw_surface3_EnumOverlayZOrders,
5520     ddraw_surface3_Flip,
5521     ddraw_surface3_GetAttachedSurface,
5522     ddraw_surface3_GetBltStatus,
5523     ddraw_surface3_GetCaps,
5524     ddraw_surface3_GetClipper,
5525     ddraw_surface3_GetColorKey,
5526     ddraw_surface3_GetDC,
5527     ddraw_surface3_GetFlipStatus,
5528     ddraw_surface3_GetOverlayPosition,
5529     ddraw_surface3_GetPalette,
5530     ddraw_surface3_GetPixelFormat,
5531     ddraw_surface3_GetSurfaceDesc,
5532     ddraw_surface3_Initialize,
5533     ddraw_surface3_IsLost,
5534     ddraw_surface3_Lock,
5535     ddraw_surface3_ReleaseDC,
5536     ddraw_surface3_Restore,
5537     ddraw_surface3_SetClipper,
5538     ddraw_surface3_SetColorKey,
5539     ddraw_surface3_SetOverlayPosition,
5540     ddraw_surface3_SetPalette,
5541     ddraw_surface3_Unlock,
5542     ddraw_surface3_UpdateOverlay,
5543     ddraw_surface3_UpdateOverlayDisplay,
5544     ddraw_surface3_UpdateOverlayZOrder,
5545     /* IDirectDrawSurface2 */
5546     ddraw_surface3_GetDDInterface,
5547     ddraw_surface3_PageLock,
5548     ddraw_surface3_PageUnlock,
5549     /* IDirectDrawSurface3 */
5550     ddraw_surface3_SetSurfaceDesc,
5551 };
5552 
5553 static const struct IDirectDrawSurface2Vtbl ddraw_surface2_vtbl =
5554 {
5555     /* IUnknown */
5556     ddraw_surface2_QueryInterface,
5557     ddraw_surface2_AddRef,
5558     ddraw_surface2_Release,
5559     /* IDirectDrawSurface */
5560     ddraw_surface2_AddAttachedSurface,
5561     ddraw_surface2_AddOverlayDirtyRect,
5562     ddraw_surface2_Blt,
5563     ddraw_surface2_BltBatch,
5564     ddraw_surface2_BltFast,
5565     ddraw_surface2_DeleteAttachedSurface,
5566     ddraw_surface2_EnumAttachedSurfaces,
5567     ddraw_surface2_EnumOverlayZOrders,
5568     ddraw_surface2_Flip,
5569     ddraw_surface2_GetAttachedSurface,
5570     ddraw_surface2_GetBltStatus,
5571     ddraw_surface2_GetCaps,
5572     ddraw_surface2_GetClipper,
5573     ddraw_surface2_GetColorKey,
5574     ddraw_surface2_GetDC,
5575     ddraw_surface2_GetFlipStatus,
5576     ddraw_surface2_GetOverlayPosition,
5577     ddraw_surface2_GetPalette,
5578     ddraw_surface2_GetPixelFormat,
5579     ddraw_surface2_GetSurfaceDesc,
5580     ddraw_surface2_Initialize,
5581     ddraw_surface2_IsLost,
5582     ddraw_surface2_Lock,
5583     ddraw_surface2_ReleaseDC,
5584     ddraw_surface2_Restore,
5585     ddraw_surface2_SetClipper,
5586     ddraw_surface2_SetColorKey,
5587     ddraw_surface2_SetOverlayPosition,
5588     ddraw_surface2_SetPalette,
5589     ddraw_surface2_Unlock,
5590     ddraw_surface2_UpdateOverlay,
5591     ddraw_surface2_UpdateOverlayDisplay,
5592     ddraw_surface2_UpdateOverlayZOrder,
5593     /* IDirectDrawSurface2 */
5594     ddraw_surface2_GetDDInterface,
5595     ddraw_surface2_PageLock,
5596     ddraw_surface2_PageUnlock,
5597 };
5598 
5599 static struct IDirectDrawSurfaceVtbl ddraw_surface1_vtbl =
5600 {
5601     /* IUnknown */
5602     ddraw_surface1_QueryInterface,
5603     ddraw_surface1_AddRef,
5604     ddraw_surface1_Release,
5605     /* IDirectDrawSurface */
5606     ddraw_surface1_AddAttachedSurface,
5607     ddraw_surface1_AddOverlayDirtyRect,
5608     ddraw_surface1_Blt,
5609     ddraw_surface1_BltBatch,
5610     ddraw_surface1_BltFast,
5611     ddraw_surface1_DeleteAttachedSurface,
5612     ddraw_surface1_EnumAttachedSurfaces,
5613     ddraw_surface1_EnumOverlayZOrders,
5614     ddraw_surface1_Flip,
5615     ddraw_surface1_GetAttachedSurface,
5616     ddraw_surface1_GetBltStatus,
5617     ddraw_surface1_GetCaps,
5618     ddraw_surface1_GetClipper,
5619     ddraw_surface1_GetColorKey,
5620     ddraw_surface1_GetDC,
5621     ddraw_surface1_GetFlipStatus,
5622     ddraw_surface1_GetOverlayPosition,
5623     ddraw_surface1_GetPalette,
5624     ddraw_surface1_GetPixelFormat,
5625     ddraw_surface1_GetSurfaceDesc,
5626     ddraw_surface1_Initialize,
5627     ddraw_surface1_IsLost,
5628     ddraw_surface1_Lock,
5629     ddraw_surface1_ReleaseDC,
5630     ddraw_surface1_Restore,
5631     ddraw_surface1_SetClipper,
5632     ddraw_surface1_SetColorKey,
5633     ddraw_surface1_SetOverlayPosition,
5634     ddraw_surface1_SetPalette,
5635     ddraw_surface1_Unlock,
5636     ddraw_surface1_UpdateOverlay,
5637     ddraw_surface1_UpdateOverlayDisplay,
5638     ddraw_surface1_UpdateOverlayZOrder,
5639 };
5640 
5641 static const struct IDirectDrawGammaControlVtbl ddraw_gamma_control_vtbl =
5642 {
5643     ddraw_gamma_control_QueryInterface,
5644     ddraw_gamma_control_AddRef,
5645     ddraw_gamma_control_Release,
5646     ddraw_gamma_control_GetGammaRamp,
5647     ddraw_gamma_control_SetGammaRamp,
5648 };
5649 
5650 static const struct IDirect3DTexture2Vtbl d3d_texture2_vtbl =
5651 {
5652     d3d_texture2_QueryInterface,
5653     d3d_texture2_AddRef,
5654     d3d_texture2_Release,
5655     d3d_texture2_GetHandle,
5656     d3d_texture2_PaletteChanged,
5657     d3d_texture2_Load,
5658 };
5659 
5660 static const struct IDirect3DTextureVtbl d3d_texture1_vtbl =
5661 {
5662     d3d_texture1_QueryInterface,
5663     d3d_texture1_AddRef,
5664     d3d_texture1_Release,
5665     d3d_texture1_Initialize,
5666     d3d_texture1_GetHandle,
5667     d3d_texture1_PaletteChanged,
5668     d3d_texture1_Load,
5669     d3d_texture1_Unload,
5670 };
5671 
5672 /* Some games (e.g. Tomb Raider 3) pass the wrong version of the
5673  * IDirectDrawSurface interface to ddraw methods. */
5674 struct ddraw_surface *unsafe_impl_from_IDirectDrawSurface7(IDirectDrawSurface7 *iface)
5675 {
5676     if (!iface) return NULL;
5677     if (iface->lpVtbl != &ddraw_surface7_vtbl)
5678     {
5679         HRESULT hr = IDirectDrawSurface7_QueryInterface(iface, &IID_IDirectDrawSurface7, (void **)&iface);
5680         if (FAILED(hr))
5681         {
5682             WARN("Object %p doesn't expose interface IDirectDrawSurface7.\n", iface);
5683             return NULL;
5684         }
5685         IDirectDrawSurface7_Release(iface);
5686     }
5687     return CONTAINING_RECORD(iface, struct ddraw_surface, IDirectDrawSurface7_iface);
5688 }
5689 
5690 struct ddraw_surface *unsafe_impl_from_IDirectDrawSurface4(IDirectDrawSurface4 *iface)
5691 {
5692     if (!iface) return NULL;
5693     if (iface->lpVtbl != &ddraw_surface4_vtbl)
5694     {
5695         HRESULT hr = IDirectDrawSurface4_QueryInterface(iface, &IID_IDirectDrawSurface4, (void **)&iface);
5696         if (FAILED(hr))
5697         {
5698             WARN("Object %p doesn't expose interface IDirectDrawSurface4.\n", iface);
5699             return NULL;
5700         }
5701         IDirectDrawSurface4_Release(iface);
5702     }
5703     return CONTAINING_RECORD(iface, struct ddraw_surface, IDirectDrawSurface4_iface);
5704 }
5705 
5706 static struct ddraw_surface *unsafe_impl_from_IDirectDrawSurface3(IDirectDrawSurface3 *iface)
5707 {
5708     if (!iface) return NULL;
5709     if (iface->lpVtbl != &ddraw_surface3_vtbl)
5710     {
5711         HRESULT hr = IDirectDrawSurface3_QueryInterface(iface, &IID_IDirectDrawSurface3, (void **)&iface);
5712         if (FAILED(hr))
5713         {
5714             WARN("Object %p doesn't expose interface IDirectDrawSurface3.\n", iface);
5715             return NULL;
5716         }
5717         IDirectDrawSurface3_Release(iface);
5718     }
5719     return CONTAINING_RECORD(iface, struct ddraw_surface, IDirectDrawSurface3_iface);
5720 }
5721 
5722 static struct ddraw_surface *unsafe_impl_from_IDirectDrawSurface2(IDirectDrawSurface2 *iface)
5723 {
5724     if (!iface) return NULL;
5725     if (iface->lpVtbl != &ddraw_surface2_vtbl)
5726     {
5727         HRESULT hr = IDirectDrawSurface2_QueryInterface(iface, &IID_IDirectDrawSurface2, (void **)&iface);
5728         if (FAILED(hr))
5729         {
5730             WARN("Object %p doesn't expose interface IDirectDrawSurface2.\n", iface);
5731             return NULL;
5732         }
5733         IDirectDrawSurface2_Release(iface);
5734     }
5735     return CONTAINING_RECORD(iface, struct ddraw_surface, IDirectDrawSurface2_iface);
5736 }
5737 
5738 struct ddraw_surface *unsafe_impl_from_IDirectDrawSurface(IDirectDrawSurface *iface)
5739 {
5740     if (!iface) return NULL;
5741     if (iface->lpVtbl != &ddraw_surface1_vtbl)
5742     {
5743         HRESULT hr = IDirectDrawSurface_QueryInterface(iface, &IID_IDirectDrawSurface, (void **)&iface);
5744         if (FAILED(hr))
5745         {
5746             WARN("Object %p doesn't expose interface IDirectDrawSurface.\n", iface);
5747             return NULL;
5748         }
5749         IDirectDrawSurface_Release(iface);
5750     }
5751     return CONTAINING_RECORD(iface, struct ddraw_surface, IDirectDrawSurface_iface);
5752 }
5753 
5754 struct ddraw_surface *unsafe_impl_from_IDirect3DTexture2(IDirect3DTexture2 *iface)
5755 {
5756     if (!iface) return NULL;
5757     assert(iface->lpVtbl == &d3d_texture2_vtbl);
5758     return CONTAINING_RECORD(iface, struct ddraw_surface, IDirect3DTexture2_iface);
5759 }
5760 
5761 struct ddraw_surface *unsafe_impl_from_IDirect3DTexture(IDirect3DTexture *iface)
5762 {
5763     if (!iface) return NULL;
5764     assert(iface->lpVtbl == &d3d_texture1_vtbl);
5765     return CONTAINING_RECORD(iface, struct ddraw_surface, IDirect3DTexture_iface);
5766 }
5767 
5768 static void STDMETHODCALLTYPE ddraw_surface_wined3d_object_destroyed(void *parent)
5769 {
5770     struct ddraw_surface *surface = parent;
5771 
5772     TRACE("surface %p.\n", surface);
5773 
5774     /* This shouldn't happen, ddraw_surface_release_iface() should prevent the
5775      * surface from being destroyed in this case. */
5776     if (surface->first_attached != surface)
5777         ERR("Surface is still attached to surface %p.\n", surface->first_attached);
5778 
5779     while (surface->next_attached)
5780         if (FAILED(ddraw_surface_delete_attached_surface(surface,
5781                 surface->next_attached, surface->next_attached->attached_iface)))
5782             ERR("DeleteAttachedSurface failed.\n");
5783 
5784     /* Having a texture handle set implies that the device still exists. */
5785     if (surface->Handle)
5786         ddraw_free_handle(&surface->ddraw->d3ddevice->handle_table, surface->Handle - 1, DDRAW_HANDLE_SURFACE);
5787 
5788     /* Reduce the ddraw surface count. */
5789     list_remove(&surface->surface_list_entry);
5790 
5791     if (surface->clipper)
5792         IDirectDrawClipper_Release(&surface->clipper->IDirectDrawClipper_iface);
5793 
5794     if (surface == surface->ddraw->primary)
5795         surface->ddraw->primary = NULL;
5796 
5797     wined3d_private_store_cleanup(&surface->private_store);
5798 
5799     heap_free(surface);
5800 }
5801 
5802 static const struct wined3d_parent_ops ddraw_surface_wined3d_parent_ops =
5803 {
5804     ddraw_surface_wined3d_object_destroyed,
5805 };
5806 
5807 static void STDMETHODCALLTYPE ddraw_texture_wined3d_object_destroyed(void *parent)
5808 {
5809     TRACE("parent %p.\n", parent);
5810 
5811     heap_free(parent);
5812 }
5813 
5814 static const struct wined3d_parent_ops ddraw_texture_wined3d_parent_ops =
5815 {
5816     ddraw_texture_wined3d_object_destroyed,
5817 };
5818 
5819 static HRESULT CDECL ddraw_reset_enum_callback(struct wined3d_resource *resource)
5820 {
5821     return DD_OK;
5822 }
5823 
5824 HRESULT ddraw_surface_create(struct ddraw *ddraw, const DDSURFACEDESC2 *surface_desc,
5825         struct ddraw_surface **surface, IUnknown *outer_unknown, unsigned int version)
5826 {
5827     struct wined3d_sub_resource_desc wined3d_mip_desc;
5828     struct ddraw_surface *root, *mip, **attach;
5829     struct wined3d_resource_desc wined3d_desc;
5830     struct wined3d_texture *wined3d_texture;
5831     struct wined3d_display_mode mode;
5832     DDSURFACEDESC2 *desc, *mip_desc;
5833     struct ddraw_texture *texture;
5834     unsigned int layers = 1;
5835     unsigned int pitch = 0;
5836     UINT levels, i, j;
5837     HRESULT hr;
5838 
5839     TRACE("ddraw %p, surface_desc %p, surface %p, outer_unknown %p, version %u.\n",
5840             ddraw, surface_desc, surface, outer_unknown, version);
5841     if (TRACE_ON(ddraw))
5842     {
5843         TRACE("Requesting surface desc:\n");
5844         DDRAW_dump_surface_desc(surface_desc);
5845     }
5846 
5847     if (outer_unknown)
5848         return CLASS_E_NOAGGREGATION;
5849 
5850     if (!surface)
5851         return E_POINTER;
5852 
5853     if (!(texture = heap_alloc(sizeof(*texture))))
5854         return E_OUTOFMEMORY;
5855 
5856     texture->version = version;
5857     texture->surface_desc = *surface_desc;
5858     desc = &texture->surface_desc;
5859 
5860     /* Ensure DDSD_CAPS is always set. */
5861     desc->dwFlags |= DDSD_CAPS;
5862 
5863     if (desc->ddsCaps.dwCaps & DDSCAPS_FLIP)
5864     {
5865         if (!(desc->dwFlags & DDSD_BACKBUFFERCOUNT) || !desc->u5.dwBackBufferCount)
5866         {
5867             WARN("Tried to create a flippable surface without any back buffers.\n");
5868             heap_free(texture);
5869             return DDERR_INVALIDCAPS;
5870         }
5871 
5872         if (!(desc->ddsCaps.dwCaps & DDSCAPS_COMPLEX))
5873         {
5874             WARN("Tried to create a flippable surface without DDSCAPS_COMPLEX.\n");
5875             heap_free(texture);
5876             return DDERR_INVALIDCAPS;
5877         }
5878 
5879         if (desc->ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP)
5880         {
5881             WARN("Tried to create a flippable cubemap.\n");
5882             heap_free(texture);
5883             return DDERR_INVALIDPARAMS;
5884         }
5885 
5886         if (desc->ddsCaps.dwCaps & DDSCAPS_TEXTURE)
5887         {
5888             FIXME("Flippable textures not implemented.\n");
5889             heap_free(texture);
5890             return DDERR_INVALIDCAPS;
5891         }
5892     }
5893     else
5894     {
5895         if (desc->dwFlags & DDSD_BACKBUFFERCOUNT)
5896         {
5897             WARN("Tried to specify a back buffer count for a non-flippable surface.\n");
5898             hr = desc->ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP ? DDERR_INVALIDPARAMS : DDERR_INVALIDCAPS;
5899             heap_free(texture);
5900             return hr;
5901         }
5902     }
5903 
5904     if (desc->ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE)
5905     {
5906         if (desc->ddsCaps.dwCaps & DDSCAPS_TEXTURE)
5907         {
5908             WARN("Tried to create a primary surface with DDSCAPS_TEXTURE.\n");
5909             heap_free(texture);
5910             return DDERR_INVALIDCAPS;
5911         }
5912 
5913         if ((desc->ddsCaps.dwCaps & DDSCAPS_COMPLEX) && !(desc->ddsCaps.dwCaps & DDSCAPS_FLIP))
5914         {
5915             WARN("Tried to create a flippable primary surface without both DDSCAPS_FLIP and DDSCAPS_COMPLEX.\n");
5916             heap_free(texture);
5917             return DDERR_INVALIDCAPS;
5918         }
5919 
5920         if ((desc->ddsCaps.dwCaps & DDSCAPS_FLIP) && !(ddraw->cooperative_level & DDSCL_EXCLUSIVE))
5921         {
5922             WARN("Tried to create a flippable primary surface without DDSCL_EXCLUSIVE.\n");
5923             heap_free(texture);
5924             return DDERR_NOEXCLUSIVEMODE;
5925         }
5926     }
5927 
5928     /* This is a special case in ddrawex, but not allowed in ddraw. */
5929     if ((desc->ddsCaps.dwCaps & (DDSCAPS_VIDEOMEMORY | DDSCAPS_SYSTEMMEMORY))
5930             == (DDSCAPS_VIDEOMEMORY | DDSCAPS_SYSTEMMEMORY))
5931     {
5932         WARN("Tried to create a surface in both system and video memory.\n");
5933         heap_free(texture);
5934         return DDERR_INVALIDCAPS;
5935     }
5936 
5937     if ((desc->ddsCaps.dwCaps & (DDSCAPS_ALLOCONLOAD | DDSCAPS_MIPMAP))
5938             && !(desc->ddsCaps.dwCaps & DDSCAPS_TEXTURE))
5939     {
5940         WARN("Caps %#x require DDSCAPS_TEXTURE.\n", desc->ddsCaps.dwCaps);
5941         heap_free(texture);
5942         return DDERR_INVALIDCAPS;
5943     }
5944 
5945     if ((desc->ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP_ALLFACES)
5946             && !(desc->ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP))
5947     {
5948         WARN("Cube map faces requested without cube map flag.\n");
5949         heap_free(texture);
5950         return DDERR_INVALIDCAPS;
5951     }
5952 
5953     if ((desc->ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP)
5954             && !(desc->ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP_ALLFACES))
5955     {
5956         WARN("Cube map without faces requested.\n");
5957         heap_free(texture);
5958         return DDERR_INVALIDPARAMS;
5959     }
5960 
5961     if ((desc->ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP)
5962             && (desc->ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP_ALLFACES) != DDSCAPS2_CUBEMAP_ALLFACES)
5963         FIXME("Partial cube maps not implemented.\n");
5964 
5965     if (desc->ddsCaps.dwCaps2 & (DDSCAPS2_TEXTUREMANAGE | DDSCAPS2_D3DTEXTUREMANAGE))
5966     {
5967         if (!(desc->ddsCaps.dwCaps & DDSCAPS_TEXTURE))
5968         {
5969             WARN("DDSCAPS2_TEXTUREMANAGE used without DDSCAPS_TEXTURE, returning DDERR_INVALIDCAPS.\n");
5970             heap_free(texture);
5971             return DDERR_INVALIDCAPS;
5972         }
5973         if (desc->ddsCaps.dwCaps & (DDSCAPS_VIDEOMEMORY | DDSCAPS_SYSTEMMEMORY))
5974         {
5975             WARN("DDSCAPS2_TEXTUREMANAGE used width DDSCAPS_VIDEOMEMORY "
5976                     "or DDSCAPS_SYSTEMMEMORY, returning DDERR_INVALIDCAPS.\n");
5977             heap_free(texture);
5978             return DDERR_INVALIDCAPS;
5979         }
5980     }
5981 
5982     if (FAILED(hr = wined3d_get_adapter_display_mode(ddraw->wined3d, WINED3DADAPTER_DEFAULT, &mode, NULL)))
5983     {
5984         ERR("Failed to get display mode, hr %#x.\n", hr);
5985         heap_free(texture);
5986         return hr_ddraw_from_wined3d(hr);
5987     }
5988 
5989     /* No pixelformat given? Use the current screen format. */
5990     if (!(desc->dwFlags & DDSD_PIXELFORMAT))
5991     {
5992         desc->dwFlags |= DDSD_PIXELFORMAT;
5993         desc->u4.ddpfPixelFormat.dwSize = sizeof(desc->u4.ddpfPixelFormat);
5994         ddrawformat_from_wined3dformat(&desc->u4.ddpfPixelFormat, mode.format_id);
5995     }
5996 
5997     wined3d_desc.resource_type = WINED3D_RTYPE_TEXTURE_2D;
5998     wined3d_desc.format = wined3dformat_from_ddrawformat(&desc->u4.ddpfPixelFormat);
5999     if (wined3d_desc.format == WINED3DFMT_UNKNOWN)
6000     {
6001         WARN("Unsupported / unknown pixelformat.\n");
6002         heap_free(texture);
6003         return DDERR_INVALIDPIXELFORMAT;
6004     }
6005 
6006     /* No width or no height? Use the screen size. */
6007     if (!(desc->dwFlags & DDSD_WIDTH) || !(desc->dwFlags & DDSD_HEIGHT))
6008     {
6009         if (!(desc->ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE))
6010         {
6011             WARN("No width / height specified.\n");
6012             heap_free(texture);
6013             return DDERR_INVALIDPARAMS;
6014         }
6015 
6016         desc->dwFlags |= DDSD_WIDTH | DDSD_HEIGHT;
6017         desc->dwWidth = mode.width;
6018         desc->dwHeight = mode.height;
6019     }
6020 
6021     if (!desc->dwWidth || !desc->dwHeight)
6022     {
6023         heap_free(texture);
6024         return DDERR_INVALIDPARAMS;
6025     }
6026 
6027     if (desc->ddsCaps.dwCaps & DDSCAPS_FLIP)
6028         desc->ddsCaps.dwCaps |= DDSCAPS_FRONTBUFFER;
6029 
6030     if (desc->ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE)
6031     {
6032         /* The first surface is a front buffer, the back buffers are created
6033          * afterwards. */
6034         desc->ddsCaps.dwCaps |= DDSCAPS_VISIBLE;
6035         if (ddraw->cooperative_level & DDSCL_EXCLUSIVE)
6036         {
6037             struct wined3d_swapchain_desc swapchain_desc;
6038 
6039             wined3d_swapchain_get_desc(ddraw->wined3d_swapchain, &swapchain_desc);
6040             swapchain_desc.backbuffer_width = mode.width;
6041             swapchain_desc.backbuffer_height = mode.height;
6042             swapchain_desc.backbuffer_format = mode.format_id;
6043 
6044             if (FAILED(hr = wined3d_device_reset(ddraw->wined3d_device,
6045                     &swapchain_desc, NULL, ddraw_reset_enum_callback, TRUE)))
6046             {
6047                 ERR("Failed to reset device.\n");
6048                 heap_free(texture);
6049                 return hr_ddraw_from_wined3d(hr);
6050             }
6051 
6052             wined3d_device_set_render_state(ddraw->wined3d_device, WINED3D_RS_ZENABLE,
6053                     !!swapchain_desc.enable_auto_depth_stencil);
6054         }
6055     }
6056 
6057     wined3d_desc.multisample_type = WINED3D_MULTISAMPLE_NONE;
6058     wined3d_desc.multisample_quality = 0;
6059     wined3d_desc.usage = 0;
6060     wined3d_desc.access = WINED3D_RESOURCE_ACCESS_GPU | WINED3D_RESOURCE_ACCESS_MAP_R | WINED3D_RESOURCE_ACCESS_MAP_W;
6061     wined3d_desc.width = desc->dwWidth;
6062     wined3d_desc.height = desc->dwHeight;
6063     wined3d_desc.depth = 1;
6064     wined3d_desc.size = 0;
6065 
6066     if ((desc->ddsCaps.dwCaps & DDSCAPS_3DDEVICE) && (ddraw->flags & DDRAW_NO3D))
6067     {
6068         WARN("The application requests a 3D capable surface, but the ddraw object was created without 3D support.\n");
6069         /* Do not fail surface creation, only fail 3D device creation. */
6070     }
6071 
6072     /* Mipmap count fixes */
6073     if (desc->ddsCaps.dwCaps & DDSCAPS_MIPMAP)
6074     {
6075         if (desc->ddsCaps.dwCaps & DDSCAPS_COMPLEX)
6076         {
6077             if (desc->dwFlags & DDSD_MIPMAPCOUNT)
6078             {
6079                 /* Mipmap count is given, should not be 0. */
6080                 if (!desc->u2.dwMipMapCount)
6081                 {
6082                     heap_free(texture);
6083                     return DDERR_INVALIDPARAMS;
6084                 }
6085             }
6086             else
6087             {
6088                 /* Undocumented feature: Create sublevels until either the
6089                  * width or the height is 1. */
6090                 if (version == 7)
6091                     desc->u2.dwMipMapCount = wined3d_log2i(max(desc->dwWidth, desc->dwHeight)) + 1;
6092                 else
6093                     desc->u2.dwMipMapCount = wined3d_log2i(min(desc->dwWidth, desc->dwHeight)) + 1;
6094             }
6095         }
6096         else
6097         {
6098             desc->u2.dwMipMapCount = 1;
6099         }
6100 
6101         desc->dwFlags |= DDSD_MIPMAPCOUNT;
6102         levels = desc->u2.dwMipMapCount;
6103     }
6104     else
6105     {
6106         levels = 1;
6107     }
6108 
6109     if (!(desc->ddsCaps.dwCaps & (DDSCAPS_VIDEOMEMORY | DDSCAPS_SYSTEMMEMORY)))
6110     {
6111         if (!(desc->ddsCaps.dwCaps2 & (DDSCAPS2_TEXTUREMANAGE | DDSCAPS2_D3DTEXTUREMANAGE)))
6112         {
6113             DWORD usage = 0;
6114 
6115             if (desc->ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP)
6116                 usage |= WINED3DUSAGE_LEGACY_CUBEMAP | WINED3DUSAGE_TEXTURE;
6117             else if (desc->ddsCaps.dwCaps & DDSCAPS_TEXTURE)
6118                 usage |= WINED3DUSAGE_TEXTURE;
6119 
6120             if (desc->ddsCaps.dwCaps & DDSCAPS_ZBUFFER)
6121                 usage = WINED3DUSAGE_DEPTHSTENCIL;
6122             else if (desc->ddsCaps.dwCaps & DDSCAPS_3DDEVICE)
6123                 usage = WINED3DUSAGE_RENDERTARGET;
6124 
6125             if (SUCCEEDED(hr = wined3d_check_device_format(ddraw->wined3d, WINED3DADAPTER_DEFAULT,
6126                     WINED3D_DEVICE_TYPE_HAL, mode.format_id, usage, WINED3D_RTYPE_TEXTURE_2D, wined3d_desc.format)))
6127                 desc->ddsCaps.dwCaps |= DDSCAPS_VIDEOMEMORY;
6128             else
6129                 desc->ddsCaps.dwCaps |= DDSCAPS_SYSTEMMEMORY;
6130         }
6131         else if (!(desc->ddsCaps.dwCaps & DDSCAPS_TEXTURE))
6132         {
6133             /* Tests show surfaces without memory flags get these flags added
6134              * right after creation. */
6135             desc->ddsCaps.dwCaps |= DDSCAPS_LOCALVIDMEM | DDSCAPS_VIDEOMEMORY;
6136         }
6137     }
6138 
6139     if ((desc->ddsCaps.dwCaps & (DDSCAPS_OVERLAY | DDSCAPS_SYSTEMMEMORY))
6140             == (DDSCAPS_OVERLAY | DDSCAPS_SYSTEMMEMORY))
6141     {
6142         WARN("System memory overlays are not allowed.\n");
6143         heap_free(texture);
6144         return DDERR_NOOVERLAYHW;
6145     }
6146 
6147     if (desc->ddsCaps.dwCaps & DDSCAPS_SYSTEMMEMORY)
6148     {
6149         /*
6150          * The ddraw RGB device allows to use system memory surfaces as rendering target.
6151          * This does not cause problems because the RGB device does software rasterization
6152          * though it will fail with hardware accelerated ddraw. In order to be partially
6153          * compatible with games requesting explicitly the RGB device, we ignore the
6154          * specified location and try to create rendering targets in video memory if
6155          * possible.
6156          */
6157         if ((desc->ddsCaps.dwCaps & DDSCAPS_3DDEVICE) &&
6158             SUCCEEDED(hr = wined3d_check_device_format(ddraw->wined3d, WINED3DADAPTER_DEFAULT,
6159                         WINED3D_DEVICE_TYPE_HAL, mode.format_id, WINED3DUSAGE_RENDERTARGET,
6160                         WINED3D_RTYPE_TEXTURE_2D, wined3d_desc.format)))
6161         {
6162             FIXME("Application wants to create rendering target in system memory, using video memory instead\n");
6163             wined3d_desc.usage |= WINED3DUSAGE_RENDERTARGET;
6164         }
6165         else
6166             wined3d_desc.access = WINED3D_RESOURCE_ACCESS_CPU
6167                 | WINED3D_RESOURCE_ACCESS_MAP_R | WINED3D_RESOURCE_ACCESS_MAP_W;
6168     }
6169     else
6170     {
6171         if (desc->ddsCaps.dwCaps & DDSCAPS_TEXTURE)
6172             wined3d_desc.usage |= WINED3DUSAGE_TEXTURE;
6173         if (desc->ddsCaps.dwCaps & DDSCAPS_ZBUFFER)
6174             wined3d_desc.usage |= WINED3DUSAGE_DEPTHSTENCIL;
6175         else if (desc->ddsCaps.dwCaps & DDSCAPS_3DDEVICE)
6176             wined3d_desc.usage |= WINED3DUSAGE_RENDERTARGET;
6177 
6178         if (desc->ddsCaps.dwCaps2 & (DDSCAPS2_TEXTUREMANAGE | DDSCAPS2_D3DTEXTUREMANAGE))
6179         {
6180             wined3d_desc.access = WINED3D_RESOURCE_ACCESS_GPU | WINED3D_RESOURCE_ACCESS_CPU
6181                     | WINED3D_RESOURCE_ACCESS_MAP_R | WINED3D_RESOURCE_ACCESS_MAP_W;
6182             /* Managed textures have the system memory flag set. */
6183             desc->ddsCaps.dwCaps |= DDSCAPS_SYSTEMMEMORY;
6184         }
6185         else if (desc->ddsCaps.dwCaps & DDSCAPS_VIDEOMEMORY)
6186         {
6187             /* Videomemory adds localvidmem. This is mutually exclusive with
6188              * systemmemory and texturemanage. */
6189             desc->ddsCaps.dwCaps |= DDSCAPS_LOCALVIDMEM;
6190             wined3d_desc.usage |= WINED3DUSAGE_DYNAMIC;
6191         }
6192     }
6193 
6194     if (desc->dwFlags & DDSD_LPSURFACE)
6195     {
6196         if (wined3d_desc.access & WINED3D_RESOURCE_ACCESS_GPU)
6197         {
6198             WARN("User memory surfaces should not be GPU accessible.\n");
6199             heap_free(texture);
6200             return DDERR_INVALIDCAPS;
6201         }
6202 
6203         if (version < 4)
6204         {
6205             WARN("User memory surfaces not supported before version 4.\n");
6206             heap_free(texture);
6207             return DDERR_INVALIDPARAMS;
6208         }
6209 
6210         if (!desc->lpSurface)
6211         {
6212             WARN("NULL surface memory pointer specified.\n");
6213             heap_free(texture);
6214             return DDERR_INVALIDPARAMS;
6215         }
6216 
6217         if (format_is_compressed(&desc->u4.ddpfPixelFormat))
6218         {
6219             if (version != 4 && (desc->dwFlags & DDSD_PITCH))
6220             {
6221                 WARN("Pitch specified on a compressed user memory surface.\n");
6222                 heap_free(texture);
6223                 return DDERR_INVALIDPARAMS;
6224             }
6225 
6226             if (!(desc->dwFlags & (DDSD_LINEARSIZE | DDSD_PITCH)))
6227             {
6228                 WARN("Compressed user memory surfaces should explicitly specify the linear size.\n");
6229                 heap_free(texture);
6230                 return DDERR_INVALIDPARAMS;
6231             }
6232 
6233             if ((desc->dwFlags & DDSD_LINEARSIZE)
6234                     && desc->u1.dwLinearSize < wined3d_calculate_format_pitch(ddraw->wined3d, WINED3DADAPTER_DEFAULT,
6235                             wined3d_desc.format, wined3d_desc.width) * ((desc->dwHeight + 3) / 4))
6236             {
6237                 WARN("Invalid linear size %u specified.\n", desc->u1.dwLinearSize);
6238                 heap_free(texture);
6239                 return DDERR_INVALIDPARAMS;
6240             }
6241         }
6242         else
6243         {
6244             if (!(desc->dwFlags & DDSD_PITCH))
6245             {
6246                 WARN("User memory surfaces should explicitly specify the pitch.\n");
6247                 heap_free(texture);
6248                 return DDERR_INVALIDPARAMS;
6249             }
6250 
6251             if (desc->u1.lPitch < wined3d_calculate_format_pitch(ddraw->wined3d, WINED3DADAPTER_DEFAULT,
6252                     wined3d_desc.format, wined3d_desc.width) || desc->u1.lPitch & 3)
6253             {
6254                 WARN("Invalid pitch %u specified.\n", desc->u1.lPitch);
6255                 heap_free(texture);
6256                 return DDERR_INVALIDPARAMS;
6257             }
6258 
6259             pitch = desc->u1.lPitch;
6260         }
6261     }
6262 
6263     if (((desc->dwFlags & DDSD_CKDESTOVERLAY)
6264             && desc->u3.ddckCKDestOverlay.dwColorSpaceLowValue != desc->u3.ddckCKDestOverlay.dwColorSpaceHighValue)
6265             || ((desc->dwFlags & DDSD_CKDESTBLT)
6266             && desc->ddckCKDestBlt.dwColorSpaceLowValue != desc->ddckCKDestBlt.dwColorSpaceHighValue)
6267             || ((desc->dwFlags & DDSD_CKSRCOVERLAY)
6268             && desc->ddckCKSrcOverlay.dwColorSpaceLowValue != desc->ddckCKSrcOverlay.dwColorSpaceHighValue)
6269             || ((desc->dwFlags & DDSD_CKSRCBLT)
6270             && desc->ddckCKSrcBlt.dwColorSpaceLowValue != desc->ddckCKSrcBlt.dwColorSpaceHighValue))
6271     {
6272         WARN("Range color keys not supported, returning DDERR_NOCOLORKEYHW.\n");
6273         heap_free(texture);
6274         return DDERR_NOCOLORKEYHW;
6275     }
6276 
6277     if (desc->ddsCaps.dwCaps & (DDSCAPS_OVERLAY))
6278         wined3d_desc.usage |= WINED3DUSAGE_OVERLAY;
6279 
6280     if (desc->ddsCaps.dwCaps & DDSCAPS_OWNDC)
6281         wined3d_desc.usage |= WINED3DUSAGE_OWNDC;
6282 
6283     if (desc->ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP)
6284     {
6285         wined3d_desc.usage |= WINED3DUSAGE_LEGACY_CUBEMAP;
6286         layers = 6;
6287     }
6288 
6289     /* Some applications assume surfaces will always be mapped at the same
6290      * address. Some of those also assume that this address is valid even when
6291      * the surface isn't mapped, and that updates done this way will be
6292      * visible on the screen. The game Nox is such an application,
6293      * Commandos: Behind Enemy Lines is another. Setting
6294      * WINED3D_TEXTURE_CREATE_GET_DC_LENIENT will ensure this. */
6295     if (FAILED(hr = wined3d_texture_create(ddraw->wined3d_device, &wined3d_desc, layers, levels,
6296             WINED3D_TEXTURE_CREATE_GET_DC_LENIENT, NULL, texture,
6297             &ddraw_texture_wined3d_parent_ops, &wined3d_texture)))
6298     {
6299         WARN("Failed to create wined3d texture, hr %#x.\n", hr);
6300         heap_free(texture);
6301         return hr_ddraw_from_wined3d(hr);
6302     }
6303 
6304     root = wined3d_texture_get_sub_resource_parent(wined3d_texture, 0);
6305     wined3d_texture_decref(wined3d_texture);
6306     root->is_complex_root = TRUE;
6307     texture->root = root;
6308     wined3d_device_incref(texture->wined3d_device = ddraw->wined3d_device);
6309 
6310     if (desc->dwFlags & DDSD_CKDESTOVERLAY)
6311         wined3d_texture_set_color_key(wined3d_texture, DDCKEY_DESTOVERLAY,
6312                 (struct wined3d_color_key *)&desc->u3.ddckCKDestOverlay);
6313     if (desc->dwFlags & DDSD_CKDESTBLT)
6314         wined3d_texture_set_color_key(wined3d_texture, DDCKEY_DESTBLT,
6315                 (struct wined3d_color_key *)&desc->ddckCKDestBlt);
6316     if (desc->dwFlags & DDSD_CKSRCOVERLAY)
6317         wined3d_texture_set_color_key(wined3d_texture, DDCKEY_SRCOVERLAY,
6318                 (struct wined3d_color_key *)&desc->ddckCKSrcOverlay);
6319     if (desc->dwFlags & DDSD_CKSRCBLT)
6320         wined3d_texture_set_color_key(wined3d_texture, DDCKEY_SRCBLT,
6321                 (struct wined3d_color_key *)&desc->ddckCKSrcBlt);
6322 
6323     for (i = 0; i < layers; ++i)
6324     {
6325         attach = &root->complex_array[layers - 1 - i];
6326 
6327         for (j = 0; j < levels; ++j)
6328         {
6329             mip = wined3d_texture_get_sub_resource_parent(wined3d_texture, i * levels + j);
6330             mip_desc = &mip->surface_desc;
6331 
6332             if (j)
6333             {
6334                 wined3d_texture_get_sub_resource_desc(wined3d_texture, i * levels + j, &wined3d_mip_desc);
6335                 mip_desc->dwWidth = wined3d_mip_desc.width;
6336                 mip_desc->dwHeight = wined3d_mip_desc.height;
6337 
6338                 mip_desc->ddsCaps.dwCaps2 |= DDSCAPS2_MIPMAPSUBLEVEL;
6339             }
6340             else
6341             {
6342                 mip_desc->ddsCaps.dwCaps2 &= ~DDSCAPS2_MIPMAPSUBLEVEL;
6343             }
6344 
6345             if (mip_desc->ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP)
6346             {
6347                 mip_desc->ddsCaps.dwCaps2 &= ~DDSCAPS2_CUBEMAP_ALLFACES;
6348 
6349                 switch (i)
6350                 {
6351                     case WINED3D_CUBEMAP_FACE_POSITIVE_X:
6352                         mip_desc->ddsCaps.dwCaps2 |= DDSCAPS2_CUBEMAP_POSITIVEX;
6353                         break;
6354                     case WINED3D_CUBEMAP_FACE_NEGATIVE_X:
6355                         mip_desc->ddsCaps.dwCaps2 |= DDSCAPS2_CUBEMAP_NEGATIVEX;
6356                         break;
6357                     case WINED3D_CUBEMAP_FACE_POSITIVE_Y:
6358                         mip_desc->ddsCaps.dwCaps2 |= DDSCAPS2_CUBEMAP_POSITIVEY;
6359                         break;
6360                     case WINED3D_CUBEMAP_FACE_NEGATIVE_Y:
6361                         mip_desc->ddsCaps.dwCaps2 |= DDSCAPS2_CUBEMAP_NEGATIVEY;
6362                         break;
6363                     case WINED3D_CUBEMAP_FACE_POSITIVE_Z:
6364                         mip_desc->ddsCaps.dwCaps2 |= DDSCAPS2_CUBEMAP_POSITIVEZ;
6365                         break;
6366                     case WINED3D_CUBEMAP_FACE_NEGATIVE_Z:
6367                         mip_desc->ddsCaps.dwCaps2 |= DDSCAPS2_CUBEMAP_NEGATIVEZ;
6368                         break;
6369                 }
6370 
6371             }
6372 
6373             if (mip == root)
6374                 continue;
6375 
6376             *attach = mip;
6377             attach = &mip->complex_array[0];
6378         }
6379     }
6380 
6381     if ((desc->dwFlags & DDSD_LPSURFACE) && FAILED(hr = wined3d_texture_update_desc(wined3d_texture,
6382             wined3d_desc.width, wined3d_desc.height, wined3d_desc.format,
6383             WINED3D_MULTISAMPLE_NONE, 0, desc->lpSurface, pitch)))
6384     {
6385         ERR("Failed to set surface memory, hr %#x.\n", hr);
6386         goto fail;
6387     }
6388 
6389     if (desc->dwFlags & DDSD_BACKBUFFERCOUNT)
6390     {
6391         unsigned int count = desc->u5.dwBackBufferCount;
6392         struct ddraw_surface *last = root;
6393 
6394         attach = &last->complex_array[0];
6395         for (i = 0; i < count; ++i)
6396         {
6397             if (!(texture = heap_alloc(sizeof(*texture))))
6398             {
6399                 hr = E_OUTOFMEMORY;
6400                 goto fail;
6401             }
6402 
6403             texture->version = version;
6404             texture->surface_desc = root->surface_desc;
6405             desc = &texture->surface_desc;
6406 
6407             /* Only one surface in the flipping chain is a back buffer, one is
6408              * a front buffer, the others are just flippable surfaces. */
6409             desc->ddsCaps.dwCaps &= ~(DDSCAPS_VISIBLE | DDSCAPS_PRIMARYSURFACE | DDSCAPS_FRONTBUFFER
6410                     | DDSCAPS_BACKBUFFER);
6411             if (!i)
6412                 desc->ddsCaps.dwCaps |= DDSCAPS_BACKBUFFER;
6413             desc->u5.dwBackBufferCount = 0;
6414 
6415             if (FAILED(hr = wined3d_texture_create(ddraw->wined3d_device, &wined3d_desc, 1, 1,
6416                     WINED3D_TEXTURE_CREATE_GET_DC_LENIENT, NULL, texture,
6417                     &ddraw_texture_wined3d_parent_ops, &wined3d_texture)))
6418             {
6419                 heap_free(texture);
6420                 hr = hr_ddraw_from_wined3d(hr);
6421                 goto fail;
6422             }
6423 
6424             last = wined3d_texture_get_sub_resource_parent(wined3d_texture, 0);
6425             wined3d_texture_decref(wined3d_texture);
6426             texture->root = last;
6427             wined3d_device_incref(texture->wined3d_device = ddraw->wined3d_device);
6428 
6429             if (desc->dwFlags & DDSD_CKDESTOVERLAY)
6430                 wined3d_texture_set_color_key(wined3d_texture, DDCKEY_DESTOVERLAY,
6431                         (struct wined3d_color_key *)&desc->u3.ddckCKDestOverlay);
6432             if (desc->dwFlags & DDSD_CKDESTBLT)
6433                 wined3d_texture_set_color_key(wined3d_texture, DDCKEY_DESTBLT,
6434                         (struct wined3d_color_key *)&desc->ddckCKDestBlt);
6435             if (desc->dwFlags & DDSD_CKSRCOVERLAY)
6436                 wined3d_texture_set_color_key(wined3d_texture, DDCKEY_SRCOVERLAY,
6437                         (struct wined3d_color_key *)&desc->ddckCKSrcOverlay);
6438             if (desc->dwFlags & DDSD_CKSRCBLT)
6439                 wined3d_texture_set_color_key(wined3d_texture, DDCKEY_SRCBLT,
6440                         (struct wined3d_color_key *)&desc->ddckCKSrcBlt);
6441 
6442             *attach = last;
6443             attach = &last->complex_array[0];
6444         }
6445         *attach = root;
6446     }
6447 
6448     if (surface_desc->ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE)
6449         ddraw->primary = root;
6450     *surface = root;
6451 
6452     return DD_OK;
6453 
6454 fail:
6455     if (version == 7)
6456         IDirectDrawSurface7_Release(&root->IDirectDrawSurface7_iface);
6457     else if (version == 4)
6458         IDirectDrawSurface4_Release(&root->IDirectDrawSurface4_iface);
6459     else
6460         IDirectDrawSurface_Release(&root->IDirectDrawSurface_iface);
6461 
6462     return hr;
6463 }
6464 
6465 void ddraw_surface_init(struct ddraw_surface *surface, struct ddraw *ddraw,
6466         struct wined3d_texture *wined3d_texture, unsigned int sub_resource_idx,
6467         const struct wined3d_parent_ops **parent_ops)
6468 {
6469     struct ddraw_texture *texture = wined3d_texture_get_parent(wined3d_texture);
6470     unsigned int texture_level, row_pitch, slice_pitch;
6471     DDSURFACEDESC2 *desc = &surface->surface_desc;
6472     unsigned int version = texture->version;
6473 
6474     surface->IDirectDrawSurface7_iface.lpVtbl = &ddraw_surface7_vtbl;
6475     surface->IDirectDrawSurface4_iface.lpVtbl = &ddraw_surface4_vtbl;
6476     surface->IDirectDrawSurface3_iface.lpVtbl = &ddraw_surface3_vtbl;
6477     surface->IDirectDrawSurface2_iface.lpVtbl = &ddraw_surface2_vtbl;
6478     surface->IDirectDrawSurface_iface.lpVtbl = &ddraw_surface1_vtbl;
6479     surface->IDirectDrawGammaControl_iface.lpVtbl = &ddraw_gamma_control_vtbl;
6480     surface->IDirect3DTexture2_iface.lpVtbl = &d3d_texture2_vtbl;
6481     surface->IDirect3DTexture_iface.lpVtbl = &d3d_texture1_vtbl;
6482     surface->iface_count = 1;
6483     surface->version = version;
6484     surface->ddraw = ddraw;
6485 
6486     if (version == 7)
6487     {
6488         surface->ref7 = 1;
6489         surface->texture_outer = (IUnknown *)&surface->IDirectDrawSurface7_iface;
6490     }
6491     else if (version == 4)
6492     {
6493         surface->ref4 = 1;
6494         surface->texture_outer = (IUnknown *)&surface->IDirectDrawSurface4_iface;
6495     }
6496     else
6497     {
6498         surface->ref1 = 1;
6499         surface->texture_outer = (IUnknown *)&surface->IDirectDrawSurface_iface;
6500     }
6501 
6502     *desc = texture->surface_desc;
6503     surface->first_attached = surface;
6504 
6505     texture_level = desc->ddsCaps.dwCaps & DDSCAPS_MIPMAP ? sub_resource_idx % desc->u2.dwMipMapCount : 0;
6506     wined3d_texture_get_pitch(wined3d_texture, texture_level, &row_pitch, &slice_pitch);
6507     if (format_is_compressed(&desc->u4.ddpfPixelFormat))
6508     {
6509         if (desc->dwFlags & DDSD_LPSURFACE)
6510             desc->u1.dwLinearSize = ~0u;
6511         else
6512             desc->u1.dwLinearSize = slice_pitch;
6513         desc->dwFlags |= DDSD_LINEARSIZE;
6514         desc->dwFlags &= ~(DDSD_LPSURFACE | DDSD_PITCH);
6515     }
6516     else
6517     {
6518         if (!(desc->dwFlags & DDSD_LPSURFACE))
6519             desc->u1.lPitch = row_pitch;
6520         desc->dwFlags |= DDSD_PITCH;
6521         desc->dwFlags &= ~(DDSD_LPSURFACE | DDSD_LINEARSIZE);
6522     }
6523     desc->lpSurface = NULL;
6524 
6525     wined3d_texture_incref(surface->wined3d_texture = wined3d_texture);
6526     surface->sub_resource_idx = sub_resource_idx;
6527     *parent_ops = &ddraw_surface_wined3d_parent_ops;
6528 
6529     wined3d_private_store_init(&surface->private_store);
6530 }
6531 
6532 static void STDMETHODCALLTYPE view_wined3d_object_destroyed(void *parent)
6533 {
6534     struct ddraw_surface *surface = parent;
6535 
6536     /* If the surface reference count drops to zero, we release our reference
6537      * to the view, but don't clear the pointer yet, in case e.g. a
6538      * GetRenderTarget() call brings the surface back before the view is
6539      * actually destroyed. When the view is destroyed, we need to clear the
6540      * pointer, or a subsequent surface AddRef() would reference it again.
6541      *
6542      * This is safe because as long as the view still has a reference to the
6543      * texture, the surface is also still alive, and we're called before the
6544      * view releases that reference. */
6545     surface->wined3d_rtv = NULL;
6546 }
6547 
6548 static const struct wined3d_parent_ops ddraw_view_wined3d_parent_ops =
6549 {
6550     view_wined3d_object_destroyed,
6551 };
6552 
6553 struct wined3d_rendertarget_view *ddraw_surface_get_rendertarget_view(struct ddraw_surface *surface)
6554 {
6555     HRESULT hr;
6556 
6557     if (surface->wined3d_rtv)
6558         return surface->wined3d_rtv;
6559 
6560     if (FAILED(hr = wined3d_rendertarget_view_create_from_sub_resource(surface->wined3d_texture,
6561             surface->sub_resource_idx, surface, &ddraw_view_wined3d_parent_ops, &surface->wined3d_rtv)))
6562     {
6563         ERR("Failed to create rendertarget view, hr %#x.\n", hr);
6564         return NULL;
6565     }
6566 
6567     return surface->wined3d_rtv;
6568 }
6569