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