gdi32: Implement the MoveTo entry point in the path driver.
[wine] / dlls / ddraw / surface.c
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 file contains the (internal) driver registration functions,
10  * driver enumeration APIs and DirectDraw creation functions.
11  *
12  * This library is free software; you can redistribute it and/or
13  * modify it under the terms of the GNU Lesser General Public
14  * License as published by the Free Software Foundation; either
15  * version 2.1 of the License, or (at your option) any later version.
16  *
17  * This library is distributed in the hope that it will be useful,
18  * but WITHOUT ANY WARRANTY; without even the implied warranty of
19  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
20  * Lesser General Public License for more details.
21  *
22  * You should have received a copy of the GNU Lesser General Public
23  * License along with this library; if not, write to the Free Software
24  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
25  */
26
27 #include "config.h"
28 #include "wine/port.h"
29
30 #include "ddraw_private.h"
31
32 WINE_DEFAULT_DEBUG_CHANNEL(ddraw);
33
34 static IDirectDrawSurfaceImpl *unsafe_impl_from_IDirectDrawSurface2(IDirectDrawSurface2 *iface);
35 static IDirectDrawSurfaceImpl *unsafe_impl_from_IDirectDrawSurface3(IDirectDrawSurface3 *iface);
36
37 static inline IDirectDrawSurfaceImpl *impl_from_IDirectDrawGammaControl(IDirectDrawGammaControl *iface)
38 {
39     return CONTAINING_RECORD(iface, IDirectDrawSurfaceImpl, IDirectDrawGammaControl_iface);
40 }
41
42 /* This is slow, of course. Also, in case of locks, we can't prevent other
43  * applications from drawing to the screen while we've locked the frontbuffer.
44  * We'd like to do this in wined3d instead, but for that to work wined3d needs
45  * to support windowless rendering first. */
46 static HRESULT ddraw_surface_update_frontbuffer(IDirectDrawSurfaceImpl *surface, const RECT *rect, BOOL read)
47 {
48     HDC surface_dc, screen_dc;
49     int x, y, w, h;
50     HRESULT hr;
51     BOOL ret;
52
53     if (!rect)
54     {
55         x = 0;
56         y = 0;
57         w = surface->surface_desc.dwWidth;
58         h = surface->surface_desc.dwHeight;
59     }
60     else
61     {
62         x = rect->left;
63         y = rect->top;
64         w = rect->right - rect->left;
65         h = rect->bottom - rect->top;
66     }
67
68     if (w <= 0 || h <= 0)
69         return DD_OK;
70
71     if (surface->ddraw->swapchain_window)
72     {
73         /* Nothing to do, we control the frontbuffer, or at least the parts we
74          * care about. */
75         if (read)
76             return DD_OK;
77
78         return wined3d_surface_blt(surface->ddraw->wined3d_frontbuffer, rect,
79                 surface->wined3d_surface, rect, 0, NULL, WINED3DTEXF_POINT);
80     }
81
82     if (FAILED(hr = wined3d_surface_getdc(surface->wined3d_surface, &surface_dc)))
83     {
84         ERR("Failed to get surface DC, hr %#x.\n", hr);
85         return hr;
86     }
87
88     if (!(screen_dc = GetDC(NULL)))
89     {
90         wined3d_surface_releasedc(surface->wined3d_surface, surface_dc);
91         ERR("Failed to get screen DC.\n");
92         return E_FAIL;
93     }
94
95     if (read)
96         ret = BitBlt(surface_dc, x, y, w, h,
97                 screen_dc, x, y, SRCCOPY);
98     else
99         ret = BitBlt(screen_dc, x, y, w, h,
100                 surface_dc, x, y, SRCCOPY);
101
102     ReleaseDC(NULL, screen_dc);
103     wined3d_surface_releasedc(surface->wined3d_surface, surface_dc);
104
105     if (!ret)
106     {
107         ERR("Failed to blit to/from screen.\n");
108         return E_FAIL;
109     }
110
111     return DD_OK;
112 }
113
114 /*****************************************************************************
115  * IUnknown parts follow
116  *****************************************************************************/
117
118 /*****************************************************************************
119  * IDirectDrawSurface7::QueryInterface
120  *
121  * A normal QueryInterface implementation. For QueryInterface rules
122  * see ddraw.c, IDirectDraw7::QueryInterface. This method
123  * can Query IDirectDrawSurface interfaces in all version, IDirect3DTexture
124  * in all versions, the IDirectDrawGammaControl interface and it can
125  * create an IDirect3DDevice. (Uses IDirect3D7::CreateDevice)
126  *
127  * Params:
128  *  riid: The interface id queried for
129  *  obj: Address to write the pointer to
130  *
131  * Returns:
132  *  S_OK on success
133  *  E_NOINTERFACE if the requested interface wasn't found
134  *
135  *****************************************************************************/
136 static HRESULT WINAPI ddraw_surface7_QueryInterface(IDirectDrawSurface7 *iface, REFIID riid, void **obj)
137 {
138     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface7(iface);
139
140     TRACE("iface %p, riid %s, object %p.\n", iface, debugstr_guid(riid), obj);
141
142     /* According to COM docs, if the QueryInterface fails, obj should be set to NULL */
143     *obj = NULL;
144
145     if(!riid)
146         return DDERR_INVALIDPARAMS;
147
148     if (IsEqualGUID(riid, &IID_IUnknown)
149      || IsEqualGUID(riid, &IID_IDirectDrawSurface7) )
150     {
151         IDirectDrawSurface7_AddRef(iface);
152         *obj = iface;
153         TRACE("(%p) returning IDirectDrawSurface7 interface at %p\n", This, *obj);
154         return S_OK;
155     }
156     else if (IsEqualGUID(riid, &IID_IDirectDrawSurface4))
157     {
158         IDirectDrawSurface4_AddRef(&This->IDirectDrawSurface4_iface);
159         *obj = &This->IDirectDrawSurface4_iface;
160         TRACE("(%p) returning IDirectDrawSurface4 interface at %p\n", This, *obj);
161         return S_OK;
162     }
163     else if (IsEqualGUID(riid, &IID_IDirectDrawSurface3))
164     {
165         IDirectDrawSurface3_AddRef(&This->IDirectDrawSurface3_iface);
166         *obj = &This->IDirectDrawSurface3_iface;
167         TRACE("(%p) returning IDirectDrawSurface3 interface at %p\n", This, *obj);
168         return S_OK;
169     }
170     else if (IsEqualGUID(riid, &IID_IDirectDrawSurface2))
171     {
172         IDirectDrawSurface2_AddRef(&This->IDirectDrawSurface2_iface);
173         *obj = &This->IDirectDrawSurface2_iface;
174         TRACE("(%p) returning IDirectDrawSurface2 interface at %p\n", This, *obj);
175         return S_OK;
176     }
177     else if (IsEqualGUID(riid, &IID_IDirectDrawSurface))
178     {
179         IDirectDrawSurface_AddRef(&This->IDirectDrawSurface_iface);
180         *obj = &This->IDirectDrawSurface_iface;
181         TRACE("(%p) returning IDirectDrawSurface interface at %p\n", This, *obj);
182         return S_OK;
183     }
184     else if( IsEqualGUID(riid, &IID_IDirectDrawGammaControl) )
185     {
186         IDirectDrawGammaControl_AddRef(&This->IDirectDrawGammaControl_iface);
187         *obj = &This->IDirectDrawGammaControl_iface;
188         TRACE("(%p) returning IDirectDrawGammaControl interface at %p\n", This, *obj);
189         return S_OK;
190     }
191     else if( IsEqualGUID(riid, &IID_D3DDEVICE_WineD3D) ||
192              IsEqualGUID(riid, &IID_IDirect3DHALDevice)||
193              IsEqualGUID(riid, &IID_IDirect3DRGBDevice) )
194     {
195         IDirect3DDevice7 *d3d;
196         IDirect3DDeviceImpl *device_impl;
197
198         /* Call into IDirect3D7 for creation */
199         IDirect3D7_CreateDevice(&This->ddraw->IDirect3D7_iface, riid, &This->IDirectDrawSurface7_iface,
200                 &d3d);
201
202         if (d3d)
203         {
204             device_impl = impl_from_IDirect3DDevice7(d3d);
205             *obj = &device_impl->IDirect3DDevice_iface;
206             TRACE("(%p) Returning IDirect3DDevice interface at %p\n", This, *obj);
207             return S_OK;
208         }
209
210         WARN("Unable to create a IDirect3DDevice instance, returning E_NOINTERFACE\n");
211         return E_NOINTERFACE;
212     }
213     else if (IsEqualGUID( &IID_IDirect3DTexture, riid ) ||
214              IsEqualGUID( &IID_IDirect3DTexture2, riid ))
215     {
216         if (IsEqualGUID( &IID_IDirect3DTexture, riid ))
217         {
218             *obj = &This->IDirect3DTexture_iface;
219             TRACE(" returning Direct3DTexture interface at %p.\n", *obj);
220         }
221         else
222         {
223             *obj = &This->IDirect3DTexture2_iface;
224             TRACE(" returning Direct3DTexture2 interface at %p.\n", *obj);
225         }
226         IUnknown_AddRef( (IUnknown *) *obj);
227         return S_OK;
228     }
229
230     ERR("No interface\n");
231     return E_NOINTERFACE;
232 }
233
234 static HRESULT WINAPI ddraw_surface4_QueryInterface(IDirectDrawSurface4 *iface, REFIID riid, void **object)
235 {
236     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface4(iface);
237     TRACE("iface %p, riid %s, object %p.\n", iface, debugstr_guid(riid), object);
238
239     return ddraw_surface7_QueryInterface(&This->IDirectDrawSurface7_iface, riid, object);
240 }
241
242 static HRESULT WINAPI ddraw_surface3_QueryInterface(IDirectDrawSurface3 *iface, REFIID riid, void **object)
243 {
244     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface3(iface);
245     TRACE("iface %p, riid %s, object %p.\n", iface, debugstr_guid(riid), object);
246
247     return ddraw_surface7_QueryInterface(&This->IDirectDrawSurface7_iface, riid, object);
248 }
249
250 static HRESULT WINAPI ddraw_surface2_QueryInterface(IDirectDrawSurface2 *iface, REFIID riid, void **object)
251 {
252     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface2(iface);
253     TRACE("iface %p, riid %s, object %p.\n", iface, debugstr_guid(riid), object);
254
255     return ddraw_surface7_QueryInterface(&This->IDirectDrawSurface7_iface, riid, object);
256 }
257
258 static HRESULT WINAPI ddraw_surface1_QueryInterface(IDirectDrawSurface *iface, REFIID riid, void **object)
259 {
260     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface(iface);
261     TRACE("iface %p, riid %s, object %p.\n", iface, debugstr_guid(riid), object);
262
263     return ddraw_surface7_QueryInterface(&This->IDirectDrawSurface7_iface, riid, object);
264 }
265
266 static HRESULT WINAPI ddraw_gamma_control_QueryInterface(IDirectDrawGammaControl *iface,
267         REFIID riid, void **object)
268 {
269     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawGammaControl(iface);
270
271     TRACE("iface %p, riid %s, object %p.\n", iface, debugstr_guid(riid), object);
272
273     return ddraw_surface7_QueryInterface(&This->IDirectDrawSurface7_iface, riid, object);
274 }
275
276 static HRESULT WINAPI d3d_texture2_QueryInterface(IDirect3DTexture2 *iface, REFIID riid, void **object)
277 {
278     IDirectDrawSurfaceImpl *This = impl_from_IDirect3DTexture2(iface);
279     TRACE("iface %p, riid %s, object %p.\n", iface, debugstr_guid(riid), object);
280
281     return ddraw_surface7_QueryInterface(&This->IDirectDrawSurface7_iface, riid, object);
282 }
283
284 static HRESULT WINAPI d3d_texture1_QueryInterface(IDirect3DTexture *iface, REFIID riid, void **object)
285 {
286     IDirectDrawSurfaceImpl *This = impl_from_IDirect3DTexture(iface);
287     TRACE("iface %p, riid %s, object %p.\n", iface, debugstr_guid(riid), object);
288
289     return ddraw_surface7_QueryInterface(&This->IDirectDrawSurface7_iface, riid, object);
290 }
291
292 static void ddraw_surface_add_iface(IDirectDrawSurfaceImpl *This)
293 {
294     ULONG iface_count = InterlockedIncrement(&This->iface_count);
295     TRACE("%p increasing iface count to %u.\n", This, iface_count);
296
297     if (iface_count == 1)
298     {
299         EnterCriticalSection(&ddraw_cs);
300         if (This->wined3d_surface)
301             wined3d_surface_incref(This->wined3d_surface);
302         if (This->wined3d_texture)
303             wined3d_texture_incref(This->wined3d_texture);
304         LeaveCriticalSection(&ddraw_cs);
305     }
306 }
307
308 /*****************************************************************************
309  * IDirectDrawSurface7::AddRef
310  *
311  * A normal addref implementation
312  *
313  * Returns:
314  *  The new refcount
315  *
316  *****************************************************************************/
317 static ULONG WINAPI ddraw_surface7_AddRef(IDirectDrawSurface7 *iface)
318 {
319     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface7(iface);
320     ULONG refcount = InterlockedIncrement(&This->ref7);
321
322     TRACE("iface %p increasing refcount to %u.\n", iface, refcount);
323
324     if (refcount == 1)
325     {
326         ddraw_surface_add_iface(This);
327     }
328
329     return refcount;
330 }
331
332 static ULONG WINAPI ddraw_surface4_AddRef(IDirectDrawSurface4 *iface)
333 {
334     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface4(iface);
335     ULONG refcount = InterlockedIncrement(&This->ref4);
336
337     TRACE("iface %p increasing refcount to %u.\n", iface, refcount);
338
339     if (refcount == 1)
340     {
341         ddraw_surface_add_iface(This);
342     }
343
344     return refcount;
345 }
346
347 static ULONG WINAPI ddraw_surface3_AddRef(IDirectDrawSurface3 *iface)
348 {
349     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface3(iface);
350     ULONG refcount = InterlockedIncrement(&This->ref3);
351
352     TRACE("iface %p increasing refcount to %u.\n", iface, refcount);
353
354     if (refcount == 1)
355     {
356         ddraw_surface_add_iface(This);
357     }
358
359     return refcount;
360 }
361
362 static ULONG WINAPI ddraw_surface2_AddRef(IDirectDrawSurface2 *iface)
363 {
364     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface2(iface);
365     ULONG refcount = InterlockedIncrement(&This->ref2);
366
367     TRACE("iface %p increasing refcount to %u.\n", iface, refcount);
368
369     if (refcount == 1)
370     {
371         ddraw_surface_add_iface(This);
372     }
373
374     return refcount;
375 }
376
377 static ULONG WINAPI ddraw_surface1_AddRef(IDirectDrawSurface *iface)
378 {
379     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface(iface);
380     ULONG refcount = InterlockedIncrement(&This->ref1);
381
382     TRACE("iface %p increasing refcount to %u.\n", iface, refcount);
383
384     if (refcount == 1)
385     {
386         ddraw_surface_add_iface(This);
387     }
388
389     return refcount;
390 }
391
392 static ULONG WINAPI ddraw_gamma_control_AddRef(IDirectDrawGammaControl *iface)
393 {
394     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawGammaControl(iface);
395     ULONG refcount = InterlockedIncrement(&This->gamma_count);
396
397     TRACE("iface %p increasing refcount to %u.\n", iface, refcount);
398
399     if (refcount == 1)
400     {
401         ddraw_surface_add_iface(This);
402     }
403
404     return refcount;
405 }
406
407 static ULONG WINAPI d3d_texture2_AddRef(IDirect3DTexture2 *iface)
408 {
409     IDirectDrawSurfaceImpl *This = impl_from_IDirect3DTexture2(iface);
410     TRACE("iface %p.\n", iface);
411
412     return ddraw_surface1_AddRef(&This->IDirectDrawSurface_iface);
413 }
414
415 static ULONG WINAPI d3d_texture1_AddRef(IDirect3DTexture *iface)
416 {
417     IDirectDrawSurfaceImpl *This = impl_from_IDirect3DTexture(iface);
418     TRACE("iface %p.\n", iface);
419
420     return ddraw_surface1_AddRef(&This->IDirectDrawSurface_iface);
421 }
422
423 /*****************************************************************************
424  * ddraw_surface_destroy
425  *
426  * A helper function for IDirectDrawSurface7::Release
427  *
428  * Frees the surface, regardless of its refcount.
429  *  See IDirectDrawSurface7::Release for more information
430  *
431  * Params:
432  *  This: Surface to free
433  *
434  *****************************************************************************/
435 void ddraw_surface_destroy(IDirectDrawSurfaceImpl *This)
436 {
437     TRACE("surface %p.\n", This);
438
439     /* Check the iface count and give a warning */
440     if(This->iface_count > 1)
441     {
442         /* This can happen when a complex surface is destroyed,
443          * because the 2nd surface was addref()ed when the app
444          * called GetAttachedSurface
445          */
446         WARN("(%p): Destroying surface with refcounts 7: %d 4: %d 3: %d 2: %d 1: %d\n",
447                 This, This->ref7, This->ref4, This->ref3, This->ref2, This->ref1);
448     }
449
450     if (This->wined3d_surface)
451         wined3d_surface_decref(This->wined3d_surface);
452 }
453
454 static void ddraw_surface_cleanup(IDirectDrawSurfaceImpl *surface)
455 {
456     IDirectDrawImpl *ddraw = surface->ddraw;
457     BOOL destroy_swapchain = FALSE;
458     IDirectDrawSurfaceImpl *surf;
459     IUnknown *ifaceToRelease;
460     UINT i;
461
462     TRACE("surface %p.\n", surface);
463
464     if ((ddraw->d3d_initialized && surface == ddraw->d3d_target
465             && DefaultSurfaceType == SURFACE_OPENGL)
466             || ((surface->surface_desc.ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE)
467             && DefaultSurfaceType != SURFACE_OPENGL))
468         destroy_swapchain = TRUE;
469
470     /* The refcount test shows that the palette is detached when the surface
471      * is destroyed. */
472     IDirectDrawSurface7_SetPalette(&surface->IDirectDrawSurface7_iface, NULL);
473
474     /* Loop through all complex attached surfaces and destroy them.
475      *
476      * Yet again, only the root can have more than one complexly attached
477      * surface, all the others have a total of one. */
478     for (i = 0; i < MAX_COMPLEX_ATTACHED; ++i)
479     {
480         if (!surface->complex_array[i])
481             break;
482
483         surf = surface->complex_array[i];
484         surface->complex_array[i] = NULL;
485         while (surf)
486         {
487             IDirectDrawSurfaceImpl *destroy = surf;
488             surf = surf->complex_array[0];              /* Iterate through the "tree" */
489             ddraw_surface_destroy(destroy);             /* Destroy it */
490         }
491     }
492
493     ifaceToRelease = surface->ifaceToRelease;
494
495     /* Destroy the root surface. */
496     ddraw_surface_destroy(surface);
497
498     if (ddraw->wined3d_swapchain && destroy_swapchain)
499         ddraw_destroy_swapchain(ddraw);
500
501     /* Reduce the ddraw refcount */
502     if (ifaceToRelease)
503         IUnknown_Release(ifaceToRelease);
504 }
505
506 ULONG ddraw_surface_release_iface(IDirectDrawSurfaceImpl *This)
507 {
508     ULONG iface_count = InterlockedDecrement(&This->iface_count);
509     TRACE("%p decreasing iface count to %u.\n", This, iface_count);
510
511     if (iface_count == 0)
512     {
513         /* Complex attached surfaces are destroyed implicitly when the root is released */
514         EnterCriticalSection(&ddraw_cs);
515         if(!This->is_complex_root)
516         {
517             WARN("(%p) Attempt to destroy a surface that is not a complex root\n", This);
518             LeaveCriticalSection(&ddraw_cs);
519             return iface_count;
520         }
521         if (This->wined3d_texture) /* If it's a texture, destroy the wined3d texture. */
522             wined3d_texture_decref(This->wined3d_texture);
523         else
524             ddraw_surface_cleanup(This);
525         LeaveCriticalSection(&ddraw_cs);
526     }
527
528     return iface_count;
529 }
530
531 /*****************************************************************************
532  * IDirectDrawSurface7::Release
533  *
534  * Reduces the surface's refcount by 1. If the refcount falls to 0, the
535  * surface is destroyed.
536  *
537  * Destroying the surface is a bit tricky. For the connection between
538  * WineD3DSurfaces and DirectDrawSurfaces see IDirectDraw7::CreateSurface
539  * It has a nice graph explaining the connection.
540  *
541  * What happens here is basically this:
542  * When a surface is destroyed, its WineD3DSurface is released,
543  * and the refcount of the DirectDraw interface is reduced by 1. If it has
544  * complex surfaces attached to it, then these surfaces are destroyed too,
545  * regardless of their refcount. If any surface being destroyed has another
546  * surface attached to it (with a "soft" attachment, not complex), then
547  * this surface is detached with DeleteAttachedSurface.
548  *
549  * When the surface is a texture, the WineD3DTexture is released.
550  * If the surface is the Direct3D render target, then the D3D
551  * capabilities of the WineD3DDevice are uninitialized, which causes the
552  * swapchain to be released.
553  *
554  * When a complex sublevel falls to ref zero, then this is ignored.
555  *
556  * Returns:
557  *  The new refcount
558  *
559  *****************************************************************************/
560 static ULONG WINAPI ddraw_surface7_Release(IDirectDrawSurface7 *iface)
561 {
562     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface7(iface);
563     ULONG refcount = InterlockedDecrement(&This->ref7);
564
565     TRACE("iface %p decreasing refcount to %u.\n", iface, refcount);
566
567     if (refcount == 0)
568     {
569         ddraw_surface_release_iface(This);
570     }
571
572     return refcount;
573 }
574
575 static ULONG WINAPI ddraw_surface4_Release(IDirectDrawSurface4 *iface)
576 {
577     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface4(iface);
578     ULONG refcount = InterlockedDecrement(&This->ref4);
579
580     TRACE("iface %p decreasing refcount to %u.\n", iface, refcount);
581
582     if (refcount == 0)
583     {
584         ddraw_surface_release_iface(This);
585     }
586
587     return refcount;
588 }
589
590 static ULONG WINAPI ddraw_surface3_Release(IDirectDrawSurface3 *iface)
591 {
592     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface3(iface);
593     ULONG refcount = InterlockedDecrement(&This->ref3);
594
595     TRACE("iface %p decreasing refcount to %u.\n", iface, refcount);
596
597     if (refcount == 0)
598     {
599         ddraw_surface_release_iface(This);
600     }
601
602     return refcount;
603 }
604
605 static ULONG WINAPI ddraw_surface2_Release(IDirectDrawSurface2 *iface)
606 {
607     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface2(iface);
608     ULONG refcount = InterlockedDecrement(&This->ref2);
609
610     TRACE("iface %p decreasing refcount to %u.\n", iface, refcount);
611
612     if (refcount == 0)
613     {
614         ddraw_surface_release_iface(This);
615     }
616
617     return refcount;
618 }
619
620 static ULONG WINAPI ddraw_surface1_Release(IDirectDrawSurface *iface)
621 {
622     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface(iface);
623     ULONG refcount = InterlockedDecrement(&This->ref1);
624
625     TRACE("iface %p decreasing refcount to %u.\n", iface, refcount);
626
627     if (refcount == 0)
628     {
629         ddraw_surface_release_iface(This);
630     }
631
632     return refcount;
633 }
634
635 static ULONG WINAPI ddraw_gamma_control_Release(IDirectDrawGammaControl *iface)
636 {
637     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawGammaControl(iface);
638     ULONG refcount = InterlockedDecrement(&This->gamma_count);
639
640     TRACE("iface %p decreasing refcount to %u.\n", iface, refcount);
641
642     if (refcount == 0)
643     {
644         ddraw_surface_release_iface(This);
645     }
646
647     return refcount;
648 }
649
650 static ULONG WINAPI d3d_texture2_Release(IDirect3DTexture2 *iface)
651 {
652     IDirectDrawSurfaceImpl *This = impl_from_IDirect3DTexture2(iface);
653     TRACE("iface %p.\n", iface);
654
655     return ddraw_surface1_Release(&This->IDirectDrawSurface_iface);
656 }
657
658 static ULONG WINAPI d3d_texture1_Release(IDirect3DTexture *iface)
659 {
660     IDirectDrawSurfaceImpl *This = impl_from_IDirect3DTexture(iface);
661     TRACE("iface %p.\n", iface);
662
663     return ddraw_surface1_Release(&This->IDirectDrawSurface_iface);
664 }
665
666 /*****************************************************************************
667  * IDirectDrawSurface7::GetAttachedSurface
668  *
669  * Returns an attached surface with the requested caps. Surface attachment
670  * and complex surfaces are not clearly described by the MSDN or sdk,
671  * so this method is tricky and likely to contain problems.
672  * This implementation searches the complex list first, then the
673  * attachment chain.
674  *
675  * The chains are searched from This down to the last surface in the chain,
676  * not from the first element in the chain. The first surface found is
677  * returned. The MSDN says that this method fails if more than one surface
678  * matches the caps, but it is not sure if that is right. The attachment
679  * structure may not even allow two matching surfaces.
680  *
681  * The found surface is AddRef-ed before it is returned.
682  *
683  * Params:
684  *  Caps: Pointer to a DDCAPS2 structure describing the caps asked for
685  *  Surface: Address to store the found surface
686  *
687  * Returns:
688  *  DD_OK on success
689  *  DDERR_INVALIDPARAMS if Caps or Surface is NULL
690  *  DDERR_NOTFOUND if no surface was found
691  *
692  *****************************************************************************/
693 static HRESULT WINAPI ddraw_surface7_GetAttachedSurface(IDirectDrawSurface7 *iface,
694         DDSCAPS2 *Caps, IDirectDrawSurface7 **Surface)
695 {
696     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface7(iface);
697     IDirectDrawSurfaceImpl *surf;
698     DDSCAPS2 our_caps;
699     int i;
700
701     TRACE("iface %p, caps %p, attachment %p.\n", iface, Caps, Surface);
702
703     EnterCriticalSection(&ddraw_cs);
704
705     if(This->version < 7)
706     {
707         /* Earlier dx apps put garbage into these members, clear them */
708         our_caps.dwCaps = Caps->dwCaps;
709         our_caps.dwCaps2 = 0;
710         our_caps.dwCaps3 = 0;
711         our_caps.dwCaps4 = 0;
712     }
713     else
714     {
715         our_caps = *Caps;
716     }
717
718     TRACE("(%p): Looking for caps: %x,%x,%x,%x\n", This, our_caps.dwCaps, our_caps.dwCaps2, our_caps.dwCaps3, our_caps.dwCaps4); /* FIXME: Better debugging */
719
720     for(i = 0; i < MAX_COMPLEX_ATTACHED; i++)
721     {
722         surf = This->complex_array[i];
723         if(!surf) break;
724
725         if (TRACE_ON(ddraw))
726         {
727             TRACE("Surface: (%p) caps: %x,%x,%x,%x\n", surf,
728                    surf->surface_desc.ddsCaps.dwCaps,
729                    surf->surface_desc.ddsCaps.dwCaps2,
730                    surf->surface_desc.ddsCaps.dwCaps3,
731                    surf->surface_desc.ddsCaps.dwCaps4);
732         }
733
734         if (((surf->surface_desc.ddsCaps.dwCaps & our_caps.dwCaps) == our_caps.dwCaps) &&
735             ((surf->surface_desc.ddsCaps.dwCaps2 & our_caps.dwCaps2) == our_caps.dwCaps2)) {
736
737             /* MSDN: "This method fails if more than one surface is attached
738              * that matches the capabilities requested."
739              *
740              * Not sure how to test this.
741              */
742
743             TRACE("(%p): Returning surface %p\n", This, surf);
744             TRACE("(%p): mipmapcount=%d\n", This, surf->mipmap_level);
745             *Surface = &surf->IDirectDrawSurface7_iface;
746             ddraw_surface7_AddRef(*Surface);
747             LeaveCriticalSection(&ddraw_cs);
748             return DD_OK;
749         }
750     }
751
752     /* Next, look at the attachment chain */
753     surf = This;
754
755     while( (surf = surf->next_attached) )
756     {
757         if (TRACE_ON(ddraw))
758         {
759             TRACE("Surface: (%p) caps: %x,%x,%x,%x\n", surf,
760                    surf->surface_desc.ddsCaps.dwCaps,
761                    surf->surface_desc.ddsCaps.dwCaps2,
762                    surf->surface_desc.ddsCaps.dwCaps3,
763                    surf->surface_desc.ddsCaps.dwCaps4);
764         }
765
766         if (((surf->surface_desc.ddsCaps.dwCaps & our_caps.dwCaps) == our_caps.dwCaps) &&
767             ((surf->surface_desc.ddsCaps.dwCaps2 & our_caps.dwCaps2) == our_caps.dwCaps2)) {
768
769             TRACE("(%p): Returning surface %p\n", This, surf);
770             *Surface = &surf->IDirectDrawSurface7_iface;
771             ddraw_surface7_AddRef(*Surface);
772             LeaveCriticalSection(&ddraw_cs);
773             return DD_OK;
774         }
775     }
776
777     TRACE("(%p) Didn't find a valid surface\n", This);
778     LeaveCriticalSection(&ddraw_cs);
779
780     *Surface = NULL;
781     return DDERR_NOTFOUND;
782 }
783
784 static HRESULT WINAPI ddraw_surface4_GetAttachedSurface(IDirectDrawSurface4 *iface,
785         DDSCAPS2 *caps, IDirectDrawSurface4 **attachment)
786 {
787     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface4(iface);
788     IDirectDrawSurface7 *attachment7;
789     IDirectDrawSurfaceImpl *attachment_impl;
790     HRESULT hr;
791
792     TRACE("iface %p, caps %p, attachment %p.\n", iface, caps, attachment);
793
794     hr = ddraw_surface7_GetAttachedSurface(&This->IDirectDrawSurface7_iface,
795             caps, &attachment7);
796     if (FAILED(hr))
797     {
798         *attachment = NULL;
799         return hr;
800     }
801     attachment_impl = impl_from_IDirectDrawSurface7(attachment7);
802     *attachment = &attachment_impl->IDirectDrawSurface4_iface;
803     ddraw_surface4_AddRef(*attachment);
804     ddraw_surface7_Release(attachment7);
805
806     return hr;
807 }
808
809 static HRESULT WINAPI ddraw_surface3_GetAttachedSurface(IDirectDrawSurface3 *iface,
810         DDSCAPS *caps, IDirectDrawSurface3 **attachment)
811 {
812     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface3(iface);
813     IDirectDrawSurface7 *attachment7;
814     IDirectDrawSurfaceImpl *attachment_impl;
815     DDSCAPS2 caps2;
816     HRESULT hr;
817
818     TRACE("iface %p, caps %p, attachment %p.\n", iface, caps, attachment);
819
820     caps2.dwCaps  = caps->dwCaps;
821     caps2.dwCaps2 = 0;
822     caps2.dwCaps3 = 0;
823     caps2.dwCaps4 = 0;
824
825     hr = ddraw_surface7_GetAttachedSurface(&This->IDirectDrawSurface7_iface,
826             &caps2, &attachment7);
827     if (FAILED(hr))
828     {
829         *attachment = NULL;
830         return hr;
831     }
832     attachment_impl = impl_from_IDirectDrawSurface7(attachment7);
833     *attachment = &attachment_impl->IDirectDrawSurface3_iface;
834     ddraw_surface3_AddRef(*attachment);
835     ddraw_surface7_Release(attachment7);
836
837     return hr;
838 }
839
840 static HRESULT WINAPI ddraw_surface2_GetAttachedSurface(IDirectDrawSurface2 *iface,
841         DDSCAPS *caps, IDirectDrawSurface2 **attachment)
842 {
843     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface2(iface);
844     IDirectDrawSurface7 *attachment7;
845     IDirectDrawSurfaceImpl *attachment_impl;
846     DDSCAPS2 caps2;
847     HRESULT hr;
848
849     TRACE("iface %p, caps %p, attachment %p.\n", iface, caps, attachment);
850
851     caps2.dwCaps  = caps->dwCaps;
852     caps2.dwCaps2 = 0;
853     caps2.dwCaps3 = 0;
854     caps2.dwCaps4 = 0;
855
856     hr = ddraw_surface7_GetAttachedSurface(&This->IDirectDrawSurface7_iface,
857             &caps2, &attachment7);
858     if (FAILED(hr))
859     {
860         *attachment = NULL;
861         return hr;
862     }
863     attachment_impl = impl_from_IDirectDrawSurface7(attachment7);
864     *attachment = &attachment_impl->IDirectDrawSurface2_iface;
865     ddraw_surface2_AddRef(*attachment);
866     ddraw_surface7_Release(attachment7);
867
868     return hr;
869 }
870
871 static HRESULT WINAPI ddraw_surface1_GetAttachedSurface(IDirectDrawSurface *iface,
872         DDSCAPS *caps, IDirectDrawSurface **attachment)
873 {
874     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface(iface);
875     IDirectDrawSurface7 *attachment7;
876     IDirectDrawSurfaceImpl *attachment_impl;
877     DDSCAPS2 caps2;
878     HRESULT hr;
879
880     TRACE("iface %p, caps %p, attachment %p.\n", iface, caps, attachment);
881
882     caps2.dwCaps  = caps->dwCaps;
883     caps2.dwCaps2 = 0;
884     caps2.dwCaps3 = 0;
885     caps2.dwCaps4 = 0;
886
887     hr = ddraw_surface7_GetAttachedSurface(&This->IDirectDrawSurface7_iface,
888             &caps2, &attachment7);
889     if (FAILED(hr))
890     {
891         *attachment = NULL;
892         return hr;
893     }
894     attachment_impl = impl_from_IDirectDrawSurface7(attachment7);
895     *attachment = &attachment_impl->IDirectDrawSurface_iface;
896     ddraw_surface1_AddRef(*attachment);
897     ddraw_surface7_Release(attachment7);
898
899     return hr;
900 }
901
902 /*****************************************************************************
903  * IDirectDrawSurface7::Lock
904  *
905  * Locks the surface and returns a pointer to the surface's memory
906  *
907  * Params:
908  *  Rect: Rectangle to lock. If NULL, the whole surface is locked
909  *  DDSD: Pointer to a DDSURFACEDESC2 which shall receive the surface's desc.
910  *  Flags: Locking flags, e.g Read only or write only
911  *  h: An event handle that's not used and must be NULL
912  *
913  * Returns:
914  *  DD_OK on success
915  *  DDERR_INVALIDPARAMS if DDSD is NULL
916  *  For more details, see IWineD3DSurface::LockRect
917  *
918  *****************************************************************************/
919 static HRESULT surface_lock(IDirectDrawSurfaceImpl *This,
920         RECT *Rect, DDSURFACEDESC2 *DDSD, DWORD Flags, HANDLE h)
921 {
922     WINED3DLOCKED_RECT LockedRect;
923     HRESULT hr = DD_OK;
924
925     TRACE("This %p, rect %s, surface_desc %p, flags %#x, h %p.\n",
926             This, wine_dbgstr_rect(Rect), DDSD, Flags, h);
927
928     /* This->surface_desc.dwWidth and dwHeight are changeable, thus lock */
929     EnterCriticalSection(&ddraw_cs);
930
931     /* Should I check for the handle to be NULL?
932      *
933      * The DDLOCK flags and the D3DLOCK flags are equal
934      * for the supported values. The others are ignored by WineD3D
935      */
936
937     /* Windows zeroes this if the rect is invalid */
938     DDSD->lpSurface = 0;
939
940     if (Rect)
941     {
942         if ((Rect->left < 0)
943                 || (Rect->top < 0)
944                 || (Rect->left > Rect->right)
945                 || (Rect->top > Rect->bottom)
946                 || (Rect->right > This->surface_desc.dwWidth)
947                 || (Rect->bottom > This->surface_desc.dwHeight))
948         {
949             WARN("Trying to lock an invalid rectangle, returning DDERR_INVALIDPARAMS\n");
950             LeaveCriticalSection(&ddraw_cs);
951             return DDERR_INVALIDPARAMS;
952         }
953     }
954
955     if (This->surface_desc.ddsCaps.dwCaps & DDSCAPS_FRONTBUFFER)
956         hr = ddraw_surface_update_frontbuffer(This, Rect, TRUE);
957     if (SUCCEEDED(hr))
958         hr = wined3d_surface_map(This->wined3d_surface, &LockedRect, Rect, Flags);
959     if (FAILED(hr))
960     {
961         LeaveCriticalSection(&ddraw_cs);
962         switch(hr)
963         {
964             /* D3D8 and D3D9 return the general D3DERR_INVALIDCALL error, but ddraw has a more
965              * specific error. But since IWineD3DSurface::LockRect returns that error in this
966              * only occasion, keep d3d8 and d3d9 free from the return value override. There are
967              * many different places where d3d8/9 would have to catch the DDERR_SURFACEBUSY, it
968              * is much easier to do it in one place in ddraw
969              */
970             case WINED3DERR_INVALIDCALL:    return DDERR_SURFACEBUSY;
971             default:                        return hr;
972         }
973     }
974
975     if (Flags & DDLOCK_READONLY)
976         memset(&This->ddraw->primary_lock, 0, sizeof(This->ddraw->primary_lock));
977     else if (Rect)
978         This->ddraw->primary_lock = *Rect;
979     else
980         SetRect(&This->ddraw->primary_lock, 0, 0, This->surface_desc.dwWidth, This->surface_desc.dwHeight);
981
982     /* Override the memory area. The pitch should be set already. Strangely windows
983      * does not set the LPSURFACE flag on locked surfaces !?!.
984      * DDSD->dwFlags |= DDSD_LPSURFACE;
985      */
986     This->surface_desc.lpSurface = LockedRect.pBits;
987     DD_STRUCT_COPY_BYSIZE(DDSD,&(This->surface_desc));
988
989     TRACE("locked surface returning description :\n");
990     if (TRACE_ON(ddraw)) DDRAW_dump_surface_desc(DDSD);
991
992     LeaveCriticalSection(&ddraw_cs);
993     return DD_OK;
994 }
995
996 static HRESULT WINAPI ddraw_surface7_Lock(IDirectDrawSurface7 *iface,
997         RECT *rect, DDSURFACEDESC2 *surface_desc, DWORD flags, HANDLE h)
998 {
999     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface7(iface);
1000     TRACE("iface %p, rect %s, surface_desc %p, flags %#x, h %p.\n",
1001             iface, wine_dbgstr_rect(rect), surface_desc, flags, h);
1002
1003     if (!surface_desc) return DDERR_INVALIDPARAMS;
1004     if (surface_desc->dwSize != sizeof(DDSURFACEDESC) &&
1005             surface_desc->dwSize != sizeof(DDSURFACEDESC2))
1006     {
1007         WARN("Invalid structure size %d, returning DDERR_INVALIDPARAMS\n", surface_desc->dwSize);
1008         return DDERR_INVALIDPARAMS;
1009     }
1010     return surface_lock(This, rect, surface_desc, flags, h);
1011 }
1012
1013 static HRESULT WINAPI ddraw_surface4_Lock(IDirectDrawSurface4 *iface, RECT *rect,
1014         DDSURFACEDESC2 *surface_desc, DWORD flags, HANDLE h)
1015 {
1016     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface4(iface);
1017     TRACE("iface %p, rect %s, surface_desc %p, flags %#x, h %p.\n",
1018             iface, wine_dbgstr_rect(rect), surface_desc, flags, h);
1019
1020     if (!surface_desc) return DDERR_INVALIDPARAMS;
1021     if (surface_desc->dwSize != sizeof(DDSURFACEDESC) &&
1022             surface_desc->dwSize != sizeof(DDSURFACEDESC2))
1023     {
1024         WARN("Invalid structure size %d, returning DDERR_INVALIDPARAMS\n", surface_desc->dwSize);
1025         return DDERR_INVALIDPARAMS;
1026     }
1027     return surface_lock(This, rect, surface_desc, flags, h);
1028 }
1029
1030 static HRESULT WINAPI ddraw_surface3_Lock(IDirectDrawSurface3 *iface, RECT *rect,
1031         DDSURFACEDESC *surface_desc, DWORD flags, HANDLE h)
1032 {
1033     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface3(iface);
1034     DDSURFACEDESC2 surface_desc2;
1035     HRESULT hr;
1036     TRACE("iface %p, rect %s, surface_desc %p, flags %#x, h %p.\n",
1037             iface, wine_dbgstr_rect(rect), surface_desc, flags, h);
1038
1039     if (!surface_desc) return DDERR_INVALIDPARAMS;
1040     if (surface_desc->dwSize != sizeof(DDSURFACEDESC) &&
1041             surface_desc->dwSize != sizeof(DDSURFACEDESC2))
1042     {
1043         WARN("Invalid structure size %d, returning DDERR_INVALIDPARAMS\n", surface_desc->dwSize);
1044         return DDERR_INVALIDPARAMS;
1045     }
1046
1047     surface_desc2.dwSize = surface_desc->dwSize;
1048     surface_desc2.dwFlags = 0;
1049     hr = surface_lock(This, rect, &surface_desc2, flags, h);
1050     DDSD2_to_DDSD(&surface_desc2, surface_desc);
1051     surface_desc->dwSize = surface_desc2.dwSize;
1052     return hr;
1053 }
1054
1055 static HRESULT WINAPI ddraw_surface2_Lock(IDirectDrawSurface2 *iface, RECT *rect,
1056         DDSURFACEDESC *surface_desc, DWORD flags, HANDLE h)
1057 {
1058     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface2(iface);
1059     DDSURFACEDESC2 surface_desc2;
1060     HRESULT hr;
1061     TRACE("iface %p, rect %s, surface_desc %p, flags %#x, h %p.\n",
1062             iface, wine_dbgstr_rect(rect), surface_desc, flags, h);
1063
1064     if (!surface_desc) return DDERR_INVALIDPARAMS;
1065     if (surface_desc->dwSize != sizeof(DDSURFACEDESC) &&
1066             surface_desc->dwSize != sizeof(DDSURFACEDESC2))
1067     {
1068         WARN("Invalid structure size %d, returning DDERR_INVALIDPARAMS\n", surface_desc->dwSize);
1069         return DDERR_INVALIDPARAMS;
1070     }
1071
1072     surface_desc2.dwSize = surface_desc->dwSize;
1073     surface_desc2.dwFlags = 0;
1074     hr = surface_lock(This, rect, &surface_desc2, flags, h);
1075     DDSD2_to_DDSD(&surface_desc2, surface_desc);
1076     surface_desc->dwSize = surface_desc2.dwSize;
1077     return hr;
1078 }
1079
1080 static HRESULT WINAPI ddraw_surface1_Lock(IDirectDrawSurface *iface, RECT *rect,
1081         DDSURFACEDESC *surface_desc, DWORD flags, HANDLE h)
1082 {
1083     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface(iface);
1084     DDSURFACEDESC2 surface_desc2;
1085     HRESULT hr;
1086     TRACE("iface %p, rect %s, surface_desc %p, flags %#x, h %p.\n",
1087             iface, wine_dbgstr_rect(rect), surface_desc, flags, h);
1088
1089     if (!surface_desc) return DDERR_INVALIDPARAMS;
1090     if (surface_desc->dwSize != sizeof(DDSURFACEDESC) &&
1091             surface_desc->dwSize != sizeof(DDSURFACEDESC2))
1092     {
1093         WARN("Invalid structure size %d, returning DDERR_INVALIDPARAMS\n", surface_desc->dwSize);
1094         return DDERR_INVALIDPARAMS;
1095     }
1096
1097     surface_desc2.dwSize = surface_desc->dwSize;
1098     surface_desc2.dwFlags = 0;
1099     hr = surface_lock(This, rect, &surface_desc2, flags, h);
1100     DDSD2_to_DDSD(&surface_desc2, surface_desc);
1101     surface_desc->dwSize = surface_desc2.dwSize;
1102     return hr;
1103 }
1104
1105 /*****************************************************************************
1106  * IDirectDrawSurface7::Unlock
1107  *
1108  * Unlocks an locked surface
1109  *
1110  * Params:
1111  *  Rect: Not used by this implementation
1112  *
1113  * Returns:
1114  *  D3D_OK on success
1115  *  For more details, see IWineD3DSurface::UnlockRect
1116  *
1117  *****************************************************************************/
1118 static HRESULT WINAPI ddraw_surface7_Unlock(IDirectDrawSurface7 *iface, RECT *pRect)
1119 {
1120     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface7(iface);
1121     HRESULT hr;
1122
1123     TRACE("iface %p, rect %s.\n", iface, wine_dbgstr_rect(pRect));
1124
1125     EnterCriticalSection(&ddraw_cs);
1126     hr = wined3d_surface_unmap(This->wined3d_surface);
1127     if (SUCCEEDED(hr))
1128     {
1129         if (This->surface_desc.ddsCaps.dwCaps & DDSCAPS_FRONTBUFFER)
1130             hr = ddraw_surface_update_frontbuffer(This, &This->ddraw->primary_lock, FALSE);
1131         This->surface_desc.lpSurface = NULL;
1132     }
1133     LeaveCriticalSection(&ddraw_cs);
1134     return hr;
1135 }
1136
1137 static HRESULT WINAPI ddraw_surface4_Unlock(IDirectDrawSurface4 *iface, RECT *pRect)
1138 {
1139     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface4(iface);
1140     TRACE("iface %p, rect %p.\n", iface, pRect);
1141
1142     return ddraw_surface7_Unlock(&This->IDirectDrawSurface7_iface, pRect);
1143 }
1144
1145 static HRESULT WINAPI ddraw_surface3_Unlock(IDirectDrawSurface3 *iface, void *data)
1146 {
1147     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface3(iface);
1148     TRACE("iface %p, data %p.\n", iface, data);
1149
1150     /* data might not be the LPRECT of later versions, so drop it. */
1151     return ddraw_surface7_Unlock(&This->IDirectDrawSurface7_iface, NULL);
1152 }
1153
1154 static HRESULT WINAPI ddraw_surface2_Unlock(IDirectDrawSurface2 *iface, void *data)
1155 {
1156     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface2(iface);
1157     TRACE("iface %p, data %p.\n", iface, data);
1158
1159     /* data might not be the LPRECT of later versions, so drop it. */
1160     return ddraw_surface7_Unlock(&This->IDirectDrawSurface7_iface, NULL);
1161 }
1162
1163 static HRESULT WINAPI ddraw_surface1_Unlock(IDirectDrawSurface *iface, void *data)
1164 {
1165     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface(iface);
1166     TRACE("iface %p, data %p.\n", iface, data);
1167
1168     /* data might not be the LPRECT of later versions, so drop it. */
1169     return ddraw_surface7_Unlock(&This->IDirectDrawSurface7_iface, NULL);
1170 }
1171
1172 /*****************************************************************************
1173  * IDirectDrawSurface7::Flip
1174  *
1175  * Flips a surface with the DDSCAPS_FLIP flag. The flip is relayed to
1176  * IWineD3DSurface::Flip. Because WineD3D doesn't handle attached surfaces,
1177  * the flip target is passed to WineD3D, even if the app didn't specify one
1178  *
1179  * Params:
1180  *  DestOverride: Specifies the surface that will become the new front
1181  *                buffer. If NULL, the current back buffer is used
1182  *  Flags: some DirectDraw flags, see include/ddraw.h
1183  *
1184  * Returns:
1185  *  DD_OK on success
1186  *  DDERR_NOTFLIPPABLE if no flip target could be found
1187  *  DDERR_INVALIDOBJECT if the surface isn't a front buffer
1188  *  For more details, see IWineD3DSurface::Flip
1189  *
1190  *****************************************************************************/
1191 static HRESULT WINAPI ddraw_surface7_Flip(IDirectDrawSurface7 *iface, IDirectDrawSurface7 *DestOverride, DWORD Flags)
1192 {
1193     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface7(iface);
1194     IDirectDrawSurfaceImpl *Override = unsafe_impl_from_IDirectDrawSurface7(DestOverride);
1195     IDirectDrawSurface7 *Override7;
1196     HRESULT hr;
1197
1198     TRACE("iface %p, dst %p, flags %#x.\n", iface, DestOverride, Flags);
1199
1200     /* Flip has to be called from a front buffer
1201      * What about overlay surfaces, AFAIK they can flip too?
1202      */
1203     if( !(This->surface_desc.ddsCaps.dwCaps & (DDSCAPS_FRONTBUFFER | DDSCAPS_OVERLAY)) )
1204         return DDERR_INVALIDOBJECT; /* Unchecked */
1205
1206     EnterCriticalSection(&ddraw_cs);
1207
1208     /* WineD3D doesn't keep track of attached surface, so find the target */
1209     if(!Override)
1210     {
1211         DDSCAPS2 Caps;
1212
1213         memset(&Caps, 0, sizeof(Caps));
1214         Caps.dwCaps |= DDSCAPS_BACKBUFFER;
1215         hr = ddraw_surface7_GetAttachedSurface(iface, &Caps, &Override7);
1216         if(hr != DD_OK)
1217         {
1218             ERR("Can't find a flip target\n");
1219             LeaveCriticalSection(&ddraw_cs);
1220             return DDERR_NOTFLIPPABLE; /* Unchecked */
1221         }
1222         Override = impl_from_IDirectDrawSurface7(Override7);
1223
1224         /* For the GetAttachedSurface */
1225         ddraw_surface7_Release(Override7);
1226     }
1227
1228     hr = wined3d_surface_flip(This->wined3d_surface, Override->wined3d_surface, Flags);
1229     if (SUCCEEDED(hr) && This->surface_desc.ddsCaps.dwCaps & DDSCAPS_FRONTBUFFER)
1230         hr = ddraw_surface_update_frontbuffer(This, NULL, FALSE);
1231
1232     LeaveCriticalSection(&ddraw_cs);
1233     return hr;
1234 }
1235
1236 static HRESULT WINAPI ddraw_surface4_Flip(IDirectDrawSurface4 *iface, IDirectDrawSurface4 *dst, DWORD flags)
1237 {
1238     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface4(iface);
1239     IDirectDrawSurfaceImpl *dst_impl = unsafe_impl_from_IDirectDrawSurface4(dst);
1240     TRACE("iface %p, dst %p, flags %#x.\n", iface, dst, flags);
1241
1242     return ddraw_surface7_Flip(&This->IDirectDrawSurface7_iface,
1243             dst_impl ? &dst_impl->IDirectDrawSurface7_iface : NULL, flags);
1244 }
1245
1246 static HRESULT WINAPI ddraw_surface3_Flip(IDirectDrawSurface3 *iface, IDirectDrawSurface3 *dst, DWORD flags)
1247 {
1248     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface3(iface);
1249     IDirectDrawSurfaceImpl *dst_impl = unsafe_impl_from_IDirectDrawSurface3(dst);
1250     TRACE("iface %p, dst %p, flags %#x.\n", iface, dst, flags);
1251
1252     return ddraw_surface7_Flip(&This->IDirectDrawSurface7_iface,
1253             dst_impl ? &dst_impl->IDirectDrawSurface7_iface : NULL, flags);
1254 }
1255
1256 static HRESULT WINAPI ddraw_surface2_Flip(IDirectDrawSurface2 *iface, IDirectDrawSurface2 *dst, DWORD flags)
1257 {
1258     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface2(iface);
1259     IDirectDrawSurfaceImpl *dst_impl = unsafe_impl_from_IDirectDrawSurface2(dst);
1260     TRACE("iface %p, dst %p, flags %#x.\n", iface, dst, flags);
1261
1262     return ddraw_surface7_Flip(&This->IDirectDrawSurface7_iface,
1263             dst_impl ? &dst_impl->IDirectDrawSurface7_iface : NULL, flags);
1264 }
1265
1266 static HRESULT WINAPI ddraw_surface1_Flip(IDirectDrawSurface *iface, IDirectDrawSurface *dst, DWORD flags)
1267 {
1268     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface(iface);
1269     IDirectDrawSurfaceImpl *dst_impl = unsafe_impl_from_IDirectDrawSurface(dst);
1270     TRACE("iface %p, dst %p, flags %#x.\n", iface, dst, flags);
1271
1272     return ddraw_surface7_Flip(&This->IDirectDrawSurface7_iface,
1273             dst_impl ? &dst_impl->IDirectDrawSurface7_iface : NULL, flags);
1274 }
1275
1276 /*****************************************************************************
1277  * IDirectDrawSurface7::Blt
1278  *
1279  * Performs a blit on the surface
1280  *
1281  * Params:
1282  *  DestRect: Destination rectangle, can be NULL
1283  *  SrcSurface: Source surface, can be NULL
1284  *  SrcRect: Source rectangle, can be NULL
1285  *  Flags: Blt flags
1286  *  DDBltFx: Some extended blt parameters, connected to the flags
1287  *
1288  * Returns:
1289  *  D3D_OK on success
1290  *  See IWineD3DSurface::Blt for more details
1291  *
1292  *****************************************************************************/
1293 static HRESULT WINAPI ddraw_surface7_Blt(IDirectDrawSurface7 *iface, RECT *DestRect,
1294         IDirectDrawSurface7 *SrcSurface, RECT *SrcRect, DWORD Flags, DDBLTFX *DDBltFx)
1295 {
1296     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface7(iface);
1297     IDirectDrawSurfaceImpl *Src = unsafe_impl_from_IDirectDrawSurface7(SrcSurface);
1298     HRESULT hr = DD_OK;
1299
1300     TRACE("iface %p, dst_rect %s, src_surface %p, src_rect %s, flags %#x, fx %p.\n",
1301             iface, wine_dbgstr_rect(DestRect), SrcSurface, wine_dbgstr_rect(SrcRect), Flags, DDBltFx);
1302
1303     /* Check for validity of the flags here. WineD3D Has the software-opengl selection path and would have
1304      * to check at 2 places, and sometimes do double checks. This also saves the call to wined3d :-)
1305      */
1306     if((Flags & DDBLT_KEYSRCOVERRIDE) && (!DDBltFx || Flags & DDBLT_KEYSRC)) {
1307         WARN("Invalid source color key parameters, returning DDERR_INVALIDPARAMS\n");
1308         return DDERR_INVALIDPARAMS;
1309     }
1310
1311     if((Flags & DDBLT_KEYDESTOVERRIDE) && (!DDBltFx || Flags & DDBLT_KEYDEST)) {
1312         WARN("Invalid destination color key parameters, returning DDERR_INVALIDPARAMS\n");
1313         return DDERR_INVALIDPARAMS;
1314     }
1315
1316     EnterCriticalSection(&ddraw_cs);
1317
1318     if(Flags & DDBLT_KEYSRC && (!Src || !(Src->surface_desc.dwFlags & DDSD_CKSRCBLT))) {
1319         WARN("DDBLT_KEYDEST blit without color key in surface, returning DDERR_INVALIDPARAMS\n");
1320         LeaveCriticalSection(&ddraw_cs);
1321         return DDERR_INVALIDPARAMS;
1322     }
1323
1324     /* TODO: Check if the DDBltFx contains any ddraw surface pointers. If it
1325      * does, copy the struct, and replace the ddraw surfaces with the wined3d
1326      * surfaces. So far no blitting operations using surfaces in the bltfx
1327      * struct are supported anyway. */
1328     if (Src && Src->surface_desc.ddsCaps.dwCaps & DDSCAPS_FRONTBUFFER)
1329         hr = ddraw_surface_update_frontbuffer(Src, SrcRect, TRUE);
1330     if (SUCCEEDED(hr))
1331         hr = wined3d_surface_blt(This->wined3d_surface, DestRect, Src ? Src->wined3d_surface : NULL,
1332                 SrcRect, Flags, (WINEDDBLTFX *)DDBltFx, WINED3DTEXF_LINEAR);
1333     if (SUCCEEDED(hr) && (This->surface_desc.ddsCaps.dwCaps & DDSCAPS_FRONTBUFFER))
1334         hr = ddraw_surface_update_frontbuffer(This, DestRect, FALSE);
1335
1336     LeaveCriticalSection(&ddraw_cs);
1337     switch(hr)
1338     {
1339         case WINED3DERR_NOTAVAILABLE:       return DDERR_UNSUPPORTED;
1340         case WINED3DERR_WRONGTEXTUREFORMAT: return DDERR_INVALIDPIXELFORMAT;
1341         default:                            return hr;
1342     }
1343 }
1344
1345 static HRESULT WINAPI ddraw_surface4_Blt(IDirectDrawSurface4 *iface, RECT *dst_rect,
1346         IDirectDrawSurface4 *src_surface, RECT *src_rect, DWORD flags, DDBLTFX *fx)
1347 {
1348     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface4(iface);
1349     IDirectDrawSurfaceImpl *src = unsafe_impl_from_IDirectDrawSurface4(src_surface);
1350     TRACE("iface %p, dst_rect %s, src_surface %p, src_rect %s, flags %#x, fx %p.\n",
1351             iface, wine_dbgstr_rect(dst_rect), src_surface, wine_dbgstr_rect(src_rect), flags, fx);
1352
1353     return ddraw_surface7_Blt(&This->IDirectDrawSurface7_iface, dst_rect,
1354             src ? &src->IDirectDrawSurface7_iface : NULL, src_rect, flags, fx);
1355 }
1356
1357 static HRESULT WINAPI ddraw_surface3_Blt(IDirectDrawSurface3 *iface, RECT *dst_rect,
1358         IDirectDrawSurface3 *src_surface, RECT *src_rect, DWORD flags, DDBLTFX *fx)
1359 {
1360     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface3(iface);
1361     IDirectDrawSurfaceImpl *src_impl = unsafe_impl_from_IDirectDrawSurface3(src_surface);
1362     TRACE("iface %p, dst_rect %s, src_surface %p, src_rect %s, flags %#x, fx %p.\n",
1363             iface, wine_dbgstr_rect(dst_rect), src_surface, wine_dbgstr_rect(src_rect), flags, fx);
1364
1365     return ddraw_surface7_Blt(&This->IDirectDrawSurface7_iface, dst_rect,
1366             src_impl ? &src_impl->IDirectDrawSurface7_iface : NULL, src_rect, flags, fx);
1367 }
1368
1369 static HRESULT WINAPI ddraw_surface2_Blt(IDirectDrawSurface2 *iface, RECT *dst_rect,
1370         IDirectDrawSurface2 *src_surface, RECT *src_rect, DWORD flags, DDBLTFX *fx)
1371 {
1372     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface2(iface);
1373     IDirectDrawSurfaceImpl *src_impl = unsafe_impl_from_IDirectDrawSurface2(src_surface);
1374     TRACE("iface %p, dst_rect %s, src_surface %p, src_rect %s, flags %#x, fx %p.\n",
1375             iface, wine_dbgstr_rect(dst_rect), src_surface, wine_dbgstr_rect(src_rect), flags, fx);
1376
1377     return ddraw_surface7_Blt(&This->IDirectDrawSurface7_iface, dst_rect,
1378             src_impl ? &src_impl->IDirectDrawSurface7_iface : NULL, src_rect, flags, fx);
1379 }
1380
1381 static HRESULT WINAPI ddraw_surface1_Blt(IDirectDrawSurface *iface, RECT *dst_rect,
1382         IDirectDrawSurface *src_surface, RECT *src_rect, DWORD flags, DDBLTFX *fx)
1383 {
1384     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface(iface);
1385     IDirectDrawSurfaceImpl *src_impl = unsafe_impl_from_IDirectDrawSurface(src_surface);
1386     TRACE("iface %p, dst_rect %s, src_surface %p, src_rect %s, flags %#x, fx %p.\n",
1387             iface, wine_dbgstr_rect(dst_rect), src_surface, wine_dbgstr_rect(src_rect), flags, fx);
1388
1389     return ddraw_surface7_Blt(&This->IDirectDrawSurface7_iface, dst_rect,
1390             src_impl ? &src_impl->IDirectDrawSurface7_iface : NULL, src_rect, flags, fx);
1391 }
1392
1393 /*****************************************************************************
1394  * IDirectDrawSurface7::AddAttachedSurface
1395  *
1396  * Attaches a surface to another surface. How the surface attachments work
1397  * is not totally understood yet, and this method is prone to problems.
1398  * The surface that is attached is AddRef-ed.
1399  *
1400  * Tests with complex surfaces suggest that the surface attachments form a
1401  * tree, but no method to test this has been found yet.
1402  *
1403  * The attachment list consists of a first surface (first_attached) and
1404  * for each surface a pointer to the next attached surface (next_attached).
1405  * For the first surface, and a surface that has no attachments
1406  * first_attached points to the surface itself. A surface that has
1407  * no successors in the chain has next_attached set to NULL.
1408  *
1409  * Newly attached surfaces are attached right after the root surface.
1410  * If a surface is attached to a complex surface compound, it's attached to
1411  * the surface that the app requested, not the complex root. See
1412  * GetAttachedSurface for a description how surfaces are found.
1413  *
1414  * This is how the current implementation works, and it was coded by looking
1415  * at the needs of the applications.
1416  *
1417  * So far only Z-Buffer attachments are tested, and they are activated in
1418  * WineD3D. Mipmaps could be tricky to activate in WineD3D.
1419  * Back buffers should work in 2D mode, but they are not tested(They can be
1420  * attached in older iface versions). Rendering to the front buffer and
1421  * switching between that and double buffering is not yet implemented in
1422  * WineD3D, so for 3D it might have unexpected results.
1423  *
1424  * ddraw_surface_attach_surface is the real thing,
1425  * ddraw_surface7_AddAttachedSurface is a wrapper around it that
1426  * performs additional checks. Version 7 of this interface is much more restrictive
1427  * than its predecessors.
1428  *
1429  * Params:
1430  *  Attach: Surface to attach to iface
1431  *
1432  * Returns:
1433  *  DD_OK on success
1434  *  DDERR_CANNOTATTACHSURFACE if the surface can't be attached for some reason
1435  *
1436  *****************************************************************************/
1437 static HRESULT ddraw_surface_attach_surface(IDirectDrawSurfaceImpl *This, IDirectDrawSurfaceImpl *Surf)
1438 {
1439     TRACE("surface %p, attachment %p.\n", This, Surf);
1440
1441     if(Surf == This)
1442         return DDERR_CANNOTATTACHSURFACE; /* unchecked */
1443
1444     EnterCriticalSection(&ddraw_cs);
1445
1446     /* Check if the surface is already attached somewhere */
1447     if (Surf->next_attached || Surf->first_attached != Surf)
1448     {
1449         /* TODO: Test for the structure of the manual attachment. Is it a
1450          * chain or a list? What happens if one surface is attached to 2
1451          * different surfaces? */
1452         WARN("Surface %p is already attached somewhere. next_attached %p, first_attached %p.\n",
1453                 Surf, Surf->next_attached, Surf->first_attached);
1454
1455         LeaveCriticalSection(&ddraw_cs);
1456         return DDERR_SURFACEALREADYATTACHED;
1457     }
1458
1459     /* This inserts the new surface at the 2nd position in the chain, right after the root surface */
1460     Surf->next_attached = This->next_attached;
1461     Surf->first_attached = This->first_attached;
1462     This->next_attached = Surf;
1463
1464     /* Check if the WineD3D depth stencil needs updating */
1465     if(This->ddraw->d3ddevice)
1466     {
1467         IDirect3DDeviceImpl_UpdateDepthStencil(This->ddraw->d3ddevice);
1468     }
1469
1470     LeaveCriticalSection(&ddraw_cs);
1471     return DD_OK;
1472 }
1473
1474 static HRESULT WINAPI ddraw_surface7_AddAttachedSurface(IDirectDrawSurface7 *iface, IDirectDrawSurface7 *attachment)
1475 {
1476     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface7(iface);
1477     IDirectDrawSurfaceImpl *attachment_impl = unsafe_impl_from_IDirectDrawSurface7(attachment);
1478     HRESULT hr;
1479
1480     TRACE("iface %p, attachment %p.\n", iface, attachment);
1481
1482     /* Version 7 of this interface seems to refuse everything except z buffers, as per msdn */
1483     if(!(attachment_impl->surface_desc.ddsCaps.dwCaps & DDSCAPS_ZBUFFER))
1484     {
1485
1486         WARN("Application tries to attach a non Z buffer surface. caps %08x\n",
1487               attachment_impl->surface_desc.ddsCaps.dwCaps);
1488         return DDERR_CANNOTATTACHSURFACE;
1489     }
1490
1491     hr = ddraw_surface_attach_surface(This, attachment_impl);
1492     if (FAILED(hr))
1493     {
1494         return hr;
1495     }
1496     ddraw_surface7_AddRef(attachment);
1497     attachment_impl->attached_iface = (IUnknown *)attachment;
1498     return hr;
1499 }
1500
1501 static HRESULT WINAPI ddraw_surface4_AddAttachedSurface(IDirectDrawSurface4 *iface, IDirectDrawSurface4 *attachment)
1502 {
1503     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface4(iface);
1504     IDirectDrawSurfaceImpl *attachment_impl = unsafe_impl_from_IDirectDrawSurface4(attachment);
1505     HRESULT hr;
1506
1507     TRACE("iface %p, attachment %p.\n", iface, attachment);
1508
1509     hr = ddraw_surface7_AddAttachedSurface(&This->IDirectDrawSurface7_iface,
1510             attachment_impl ? &attachment_impl->IDirectDrawSurface7_iface : NULL);
1511     if (FAILED(hr))
1512     {
1513         return hr;
1514     }
1515     ddraw_surface4_AddRef(attachment);
1516     ddraw_surface7_Release(&attachment_impl->IDirectDrawSurface7_iface);
1517     attachment_impl->attached_iface = (IUnknown *)attachment;
1518     return hr;
1519 }
1520 static HRESULT WINAPI ddraw_surface3_AddAttachedSurface(IDirectDrawSurface3 *iface, IDirectDrawSurface3 *attachment)
1521 {
1522     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface3(iface);
1523     IDirectDrawSurfaceImpl *attachment_impl = unsafe_impl_from_IDirectDrawSurface3(attachment);
1524     HRESULT hr;
1525
1526     TRACE("iface %p, attachment %p.\n", iface, attachment);
1527
1528     /* Tests suggest that
1529      * -> offscreen plain surfaces can be attached to other offscreen plain surfaces
1530      * -> offscreen plain surfaces can be attached to primaries
1531      * -> primaries can be attached to offscreen plain surfaces
1532      * -> z buffers can be attached to primaries */
1533     if (This->surface_desc.ddsCaps.dwCaps & (DDSCAPS_PRIMARYSURFACE | DDSCAPS_OFFSCREENPLAIN)
1534             && attachment_impl->surface_desc.ddsCaps.dwCaps & (DDSCAPS_PRIMARYSURFACE | DDSCAPS_OFFSCREENPLAIN))
1535     {
1536         /* Sizes have to match */
1537         if (attachment_impl->surface_desc.dwWidth != This->surface_desc.dwWidth
1538                 || attachment_impl->surface_desc.dwHeight != This->surface_desc.dwHeight)
1539         {
1540             WARN("Surface sizes do not match.\n");
1541             return DDERR_CANNOTATTACHSURFACE;
1542         }
1543         /* OK */
1544     }
1545     else if (This->surface_desc.ddsCaps.dwCaps & (DDSCAPS_PRIMARYSURFACE | DDSCAPS_3DDEVICE)
1546             && attachment_impl->surface_desc.ddsCaps.dwCaps & (DDSCAPS_ZBUFFER))
1547     {
1548         /* OK */
1549     }
1550     else
1551     {
1552         WARN("Invalid attachment combination.\n");
1553         return DDERR_CANNOTATTACHSURFACE;
1554     }
1555
1556     hr = ddraw_surface_attach_surface(This, attachment_impl);
1557     if (FAILED(hr))
1558     {
1559         return hr;
1560     }
1561     ddraw_surface3_AddRef(attachment);
1562     attachment_impl->attached_iface = (IUnknown *)attachment;
1563     return hr;
1564 }
1565
1566 static HRESULT WINAPI ddraw_surface2_AddAttachedSurface(IDirectDrawSurface2 *iface, IDirectDrawSurface2 *attachment)
1567 {
1568     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface2(iface);
1569     IDirectDrawSurfaceImpl *attachment_impl = unsafe_impl_from_IDirectDrawSurface2(attachment);
1570     HRESULT hr;
1571
1572     TRACE("iface %p, attachment %p.\n", iface, attachment);
1573
1574     hr = ddraw_surface3_AddAttachedSurface(&This->IDirectDrawSurface3_iface,
1575             attachment_impl ? &attachment_impl->IDirectDrawSurface3_iface : NULL);
1576     if (FAILED(hr))
1577     {
1578         return hr;
1579     }
1580     ddraw_surface2_AddRef(attachment);
1581     ddraw_surface3_Release(&attachment_impl->IDirectDrawSurface3_iface);
1582     attachment_impl->attached_iface = (IUnknown *)attachment;
1583     return hr;
1584 }
1585
1586 static HRESULT WINAPI ddraw_surface1_AddAttachedSurface(IDirectDrawSurface *iface, IDirectDrawSurface *attachment)
1587 {
1588     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface(iface);
1589     IDirectDrawSurfaceImpl *attachment_impl = unsafe_impl_from_IDirectDrawSurface(attachment);
1590     HRESULT hr;
1591
1592     TRACE("iface %p, attachment %p.\n", iface, attachment);
1593
1594     hr = ddraw_surface3_AddAttachedSurface(&This->IDirectDrawSurface3_iface,
1595             attachment_impl ? &attachment_impl->IDirectDrawSurface3_iface : NULL);
1596     if (FAILED(hr))
1597     {
1598         return hr;
1599     }
1600     ddraw_surface1_AddRef(attachment);
1601     ddraw_surface3_Release(&attachment_impl->IDirectDrawSurface3_iface);
1602     attachment_impl->attached_iface = (IUnknown *)attachment;
1603     return hr;
1604 }
1605
1606 /*****************************************************************************
1607  * IDirectDrawSurface7::DeleteAttachedSurface
1608  *
1609  * Removes a surface from the attachment chain. The surface's refcount
1610  * is decreased by one after it has been removed
1611  *
1612  * Params:
1613  *  Flags: Some flags, not used by this implementation
1614  *  Attach: Surface to detach
1615  *
1616  * Returns:
1617  *  DD_OK on success
1618  *  DDERR_SURFACENOTATTACHED if the surface isn't attached to
1619  *
1620  *****************************************************************************/
1621 static HRESULT ddraw_surface_delete_attached_surface(IDirectDrawSurfaceImpl *This,
1622         IDirectDrawSurfaceImpl *Surf, IUnknown *detach_iface)
1623 {
1624     IDirectDrawSurfaceImpl *Prev = This;
1625
1626     TRACE("surface %p, attachment %p, detach_iface %p.\n", This, Surf, detach_iface);
1627
1628     EnterCriticalSection(&ddraw_cs);
1629     if (!Surf || (Surf->first_attached != This) || (Surf == This) )
1630     {
1631         LeaveCriticalSection(&ddraw_cs);
1632         return DDERR_CANNOTDETACHSURFACE;
1633     }
1634
1635     if (Surf->attached_iface != detach_iface)
1636     {
1637         WARN("Surf->attach_iface %p != detach_iface %p.\n", Surf->attached_iface, detach_iface);
1638         LeaveCriticalSection(&ddraw_cs);
1639         return DDERR_SURFACENOTATTACHED;
1640     }
1641
1642     /* Remove MIPMAPSUBLEVEL if this seemed to be one */
1643     if (This->surface_desc.ddsCaps.dwCaps &
1644         Surf->surface_desc.ddsCaps.dwCaps & DDSCAPS_MIPMAP)
1645     {
1646         Surf->surface_desc.ddsCaps.dwCaps2 &= ~DDSCAPS2_MIPMAPSUBLEVEL;
1647         /* FIXME: we should probably also subtract from dwMipMapCount of this
1648          * and all parent surfaces */
1649     }
1650
1651     /* Find the predecessor of the detached surface */
1652     while(Prev)
1653     {
1654         if(Prev->next_attached == Surf) break;
1655         Prev = Prev->next_attached;
1656     }
1657
1658     /* There must be a surface, otherwise there's a bug */
1659     assert(Prev != NULL);
1660
1661     /* Unchain the surface */
1662     Prev->next_attached = Surf->next_attached;
1663     Surf->next_attached = NULL;
1664     Surf->first_attached = Surf;
1665
1666     /* Check if the WineD3D depth stencil needs updating */
1667     if(This->ddraw->d3ddevice)
1668     {
1669         IDirect3DDeviceImpl_UpdateDepthStencil(This->ddraw->d3ddevice);
1670     }
1671     LeaveCriticalSection(&ddraw_cs);
1672
1673     /* Set attached_iface to NULL before releasing it, the surface may go
1674      * away. */
1675     Surf->attached_iface = NULL;
1676     IUnknown_Release(detach_iface);
1677
1678     return DD_OK;
1679 }
1680
1681 static HRESULT WINAPI ddraw_surface7_DeleteAttachedSurface(IDirectDrawSurface7 *iface,
1682         DWORD flags, IDirectDrawSurface7 *attachment)
1683 {
1684     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface7(iface);
1685     IDirectDrawSurfaceImpl *attachment_impl = unsafe_impl_from_IDirectDrawSurface7(attachment);
1686
1687     TRACE("iface %p, flags %#x, attachment %p.\n", iface, flags, attachment);
1688
1689     return ddraw_surface_delete_attached_surface(This, attachment_impl, (IUnknown *)attachment);
1690 }
1691
1692 static HRESULT WINAPI ddraw_surface4_DeleteAttachedSurface(IDirectDrawSurface4 *iface,
1693         DWORD flags, IDirectDrawSurface4 *attachment)
1694 {
1695     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface4(iface);
1696     IDirectDrawSurfaceImpl *attachment_impl = unsafe_impl_from_IDirectDrawSurface4(attachment);
1697
1698     TRACE("iface %p, flags %#x, attachment %p.\n", iface, flags, attachment);
1699
1700     return ddraw_surface_delete_attached_surface(This, attachment_impl, (IUnknown *)attachment);
1701 }
1702
1703 static HRESULT WINAPI ddraw_surface3_DeleteAttachedSurface(IDirectDrawSurface3 *iface,
1704         DWORD flags, IDirectDrawSurface3 *attachment)
1705 {
1706     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface3(iface);
1707     IDirectDrawSurfaceImpl *attachment_impl = unsafe_impl_from_IDirectDrawSurface3(attachment);
1708
1709     TRACE("iface %p, flags %#x, attachment %p.\n", iface, flags, attachment);
1710
1711     return ddraw_surface_delete_attached_surface(This, attachment_impl, (IUnknown *)attachment);
1712 }
1713
1714 static HRESULT WINAPI ddraw_surface2_DeleteAttachedSurface(IDirectDrawSurface2 *iface,
1715         DWORD flags, IDirectDrawSurface2 *attachment)
1716 {
1717     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface2(iface);
1718     IDirectDrawSurfaceImpl *attachment_impl = unsafe_impl_from_IDirectDrawSurface2(attachment);
1719
1720     TRACE("iface %p, flags %#x, attachment %p.\n", iface, flags, attachment);
1721
1722     return ddraw_surface_delete_attached_surface(This, attachment_impl, (IUnknown *)attachment);
1723 }
1724
1725 static HRESULT WINAPI ddraw_surface1_DeleteAttachedSurface(IDirectDrawSurface *iface,
1726         DWORD flags, IDirectDrawSurface *attachment)
1727 {
1728     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface(iface);
1729     IDirectDrawSurfaceImpl *attachment_impl = unsafe_impl_from_IDirectDrawSurface(attachment);
1730
1731     TRACE("iface %p, flags %#x, attachment %p.\n", iface, flags, attachment);
1732
1733     return ddraw_surface_delete_attached_surface(This, attachment_impl, (IUnknown *)attachment);
1734 }
1735
1736 /*****************************************************************************
1737  * IDirectDrawSurface7::AddOverlayDirtyRect
1738  *
1739  * "This method is not currently implemented"
1740  *
1741  * Params:
1742  *  Rect: ?
1743  *
1744  * Returns:
1745  *  DDERR_UNSUPPORTED
1746  *
1747  *****************************************************************************/
1748 static HRESULT WINAPI ddraw_surface7_AddOverlayDirtyRect(IDirectDrawSurface7 *iface, RECT *Rect)
1749 {
1750     TRACE("iface %p, rect %s.\n", iface, wine_dbgstr_rect(Rect));
1751
1752     return DDERR_UNSUPPORTED; /* unchecked */
1753 }
1754
1755 static HRESULT WINAPI ddraw_surface4_AddOverlayDirtyRect(IDirectDrawSurface4 *iface, RECT *rect)
1756 {
1757     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface4(iface);
1758     TRACE("iface %p, rect %s.\n", iface, wine_dbgstr_rect(rect));
1759
1760     return ddraw_surface7_AddOverlayDirtyRect(&This->IDirectDrawSurface7_iface, rect);
1761 }
1762
1763 static HRESULT WINAPI ddraw_surface3_AddOverlayDirtyRect(IDirectDrawSurface3 *iface, RECT *rect)
1764 {
1765     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface3(iface);
1766     TRACE("iface %p, rect %s.\n", iface, wine_dbgstr_rect(rect));
1767
1768     return ddraw_surface7_AddOverlayDirtyRect(&This->IDirectDrawSurface7_iface, rect);
1769 }
1770
1771 static HRESULT WINAPI ddraw_surface2_AddOverlayDirtyRect(IDirectDrawSurface2 *iface, RECT *rect)
1772 {
1773     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface2(iface);
1774     TRACE("iface %p, rect %s.\n", iface, wine_dbgstr_rect(rect));
1775
1776     return ddraw_surface7_AddOverlayDirtyRect(&This->IDirectDrawSurface7_iface, rect);
1777 }
1778
1779 static HRESULT WINAPI ddraw_surface1_AddOverlayDirtyRect(IDirectDrawSurface *iface, RECT *rect)
1780 {
1781     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface(iface);
1782     TRACE("iface %p, rect %s.\n", iface, wine_dbgstr_rect(rect));
1783
1784     return ddraw_surface7_AddOverlayDirtyRect(&This->IDirectDrawSurface7_iface, rect);
1785 }
1786
1787 /*****************************************************************************
1788  * IDirectDrawSurface7::GetDC
1789  *
1790  * Returns a GDI device context for the surface
1791  *
1792  * Params:
1793  *  hdc: Address of a HDC variable to store the dc to
1794  *
1795  * Returns:
1796  *  DD_OK on success
1797  *  DDERR_INVALIDPARAMS if hdc is NULL
1798  *  For details, see IWineD3DSurface::GetDC
1799  *
1800  *****************************************************************************/
1801 static HRESULT WINAPI ddraw_surface7_GetDC(IDirectDrawSurface7 *iface, HDC *hdc)
1802 {
1803     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface7(iface);
1804     HRESULT hr = DD_OK;
1805
1806     TRACE("iface %p, dc %p.\n", iface, hdc);
1807
1808     if(!hdc)
1809         return DDERR_INVALIDPARAMS;
1810
1811     EnterCriticalSection(&ddraw_cs);
1812     if (This->surface_desc.ddsCaps.dwCaps & DDSCAPS_FRONTBUFFER)
1813         hr = ddraw_surface_update_frontbuffer(This, NULL, TRUE);
1814     if (SUCCEEDED(hr))
1815         hr = wined3d_surface_getdc(This->wined3d_surface, hdc);
1816     LeaveCriticalSection(&ddraw_cs);
1817     switch(hr)
1818     {
1819         /* Some, but not all errors set *hdc to NULL. E.g. DCALREADYCREATED does not
1820          * touch *hdc
1821          */
1822         case WINED3DERR_INVALIDCALL:
1823             if(hdc) *hdc = NULL;
1824             return DDERR_INVALIDPARAMS;
1825
1826         default: return hr;
1827     }
1828 }
1829
1830 static HRESULT WINAPI ddraw_surface4_GetDC(IDirectDrawSurface4 *iface, HDC *dc)
1831 {
1832     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface4(iface);
1833     TRACE("iface %p, dc %p.\n", iface, dc);
1834
1835     return ddraw_surface7_GetDC(&This->IDirectDrawSurface7_iface, dc);
1836 }
1837
1838 static HRESULT WINAPI ddraw_surface3_GetDC(IDirectDrawSurface3 *iface, HDC *dc)
1839 {
1840     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface3(iface);
1841     TRACE("iface %p, dc %p.\n", iface, dc);
1842
1843     return ddraw_surface7_GetDC(&This->IDirectDrawSurface7_iface, dc);
1844 }
1845
1846 static HRESULT WINAPI ddraw_surface2_GetDC(IDirectDrawSurface2 *iface, HDC *dc)
1847 {
1848     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface2(iface);
1849     TRACE("iface %p, dc %p.\n", iface, dc);
1850
1851     return ddraw_surface7_GetDC(&This->IDirectDrawSurface7_iface, dc);
1852 }
1853
1854 static HRESULT WINAPI ddraw_surface1_GetDC(IDirectDrawSurface *iface, HDC *dc)
1855 {
1856     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface(iface);
1857     TRACE("iface %p, dc %p.\n", iface, dc);
1858
1859     return ddraw_surface7_GetDC(&This->IDirectDrawSurface7_iface, dc);
1860 }
1861
1862 /*****************************************************************************
1863  * IDirectDrawSurface7::ReleaseDC
1864  *
1865  * Releases the DC that was constructed with GetDC
1866  *
1867  * Params:
1868  *  hdc: HDC to release
1869  *
1870  * Returns:
1871  *  DD_OK on success
1872  *  For more details, see IWineD3DSurface::ReleaseDC
1873  *
1874  *****************************************************************************/
1875 static HRESULT WINAPI ddraw_surface7_ReleaseDC(IDirectDrawSurface7 *iface, HDC hdc)
1876 {
1877     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface7(iface);
1878     HRESULT hr;
1879
1880     TRACE("iface %p, dc %p.\n", iface, hdc);
1881
1882     EnterCriticalSection(&ddraw_cs);
1883     hr = wined3d_surface_releasedc(This->wined3d_surface, hdc);
1884     if (SUCCEEDED(hr) && (This->surface_desc.ddsCaps.dwCaps & DDSCAPS_FRONTBUFFER))
1885         hr = ddraw_surface_update_frontbuffer(This, NULL, FALSE);
1886     LeaveCriticalSection(&ddraw_cs);
1887     return hr;
1888 }
1889
1890 static HRESULT WINAPI ddraw_surface4_ReleaseDC(IDirectDrawSurface4 *iface, HDC dc)
1891 {
1892     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface4(iface);
1893     TRACE("iface %p, dc %p.\n", iface, dc);
1894
1895     return ddraw_surface7_ReleaseDC(&This->IDirectDrawSurface7_iface, dc);
1896 }
1897
1898 static HRESULT WINAPI ddraw_surface3_ReleaseDC(IDirectDrawSurface3 *iface, HDC dc)
1899 {
1900     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface3(iface);
1901     TRACE("iface %p, dc %p.\n", iface, dc);
1902
1903     return ddraw_surface7_ReleaseDC(&This->IDirectDrawSurface7_iface, dc);
1904 }
1905
1906 static HRESULT WINAPI ddraw_surface2_ReleaseDC(IDirectDrawSurface2 *iface, HDC dc)
1907 {
1908     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface2(iface);
1909     TRACE("iface %p, dc %p.\n", iface, dc);
1910
1911     return ddraw_surface7_ReleaseDC(&This->IDirectDrawSurface7_iface, dc);
1912 }
1913
1914 static HRESULT WINAPI ddraw_surface1_ReleaseDC(IDirectDrawSurface *iface, HDC dc)
1915 {
1916     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface(iface);
1917     TRACE("iface %p, dc %p.\n", iface, dc);
1918
1919     return ddraw_surface7_ReleaseDC(&This->IDirectDrawSurface7_iface, dc);
1920 }
1921
1922 /*****************************************************************************
1923  * IDirectDrawSurface7::GetCaps
1924  *
1925  * Returns the surface's caps
1926  *
1927  * Params:
1928  *  Caps: Address to write the caps to
1929  *
1930  * Returns:
1931  *  DD_OK on success
1932  *  DDERR_INVALIDPARAMS if Caps is NULL
1933  *
1934  *****************************************************************************/
1935 static HRESULT WINAPI ddraw_surface7_GetCaps(IDirectDrawSurface7 *iface, DDSCAPS2 *Caps)
1936 {
1937     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface7(iface);
1938
1939     TRACE("iface %p, caps %p.\n", iface, Caps);
1940
1941     if(!Caps)
1942         return DDERR_INVALIDPARAMS;
1943
1944     *Caps = This->surface_desc.ddsCaps;
1945     return DD_OK;
1946 }
1947
1948 static HRESULT WINAPI ddraw_surface4_GetCaps(IDirectDrawSurface4 *iface, DDSCAPS2 *caps)
1949 {
1950     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface4(iface);
1951     TRACE("iface %p, caps %p.\n", iface, caps);
1952
1953     return ddraw_surface7_GetCaps(&This->IDirectDrawSurface7_iface, caps);
1954 }
1955
1956 static HRESULT WINAPI ddraw_surface3_GetCaps(IDirectDrawSurface3 *iface, DDSCAPS *caps)
1957 {
1958     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface3(iface);
1959     DDSCAPS2 caps2;
1960     HRESULT hr;
1961
1962     TRACE("iface %p, caps %p.\n", iface, caps);
1963
1964     hr = ddraw_surface7_GetCaps(&This->IDirectDrawSurface7_iface, &caps2);
1965     if (FAILED(hr)) return hr;
1966
1967     caps->dwCaps = caps2.dwCaps;
1968     return hr;
1969 }
1970
1971 static HRESULT WINAPI ddraw_surface2_GetCaps(IDirectDrawSurface2 *iface, DDSCAPS *caps)
1972 {
1973     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface2(iface);
1974     DDSCAPS2 caps2;
1975     HRESULT hr;
1976
1977     TRACE("iface %p, caps %p.\n", iface, caps);
1978
1979     hr = ddraw_surface7_GetCaps(&This->IDirectDrawSurface7_iface, &caps2);
1980     if (FAILED(hr)) return hr;
1981
1982     caps->dwCaps = caps2.dwCaps;
1983     return hr;
1984 }
1985
1986 static HRESULT WINAPI ddraw_surface1_GetCaps(IDirectDrawSurface *iface, DDSCAPS *caps)
1987 {
1988     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface(iface);
1989     DDSCAPS2 caps2;
1990     HRESULT hr;
1991
1992     TRACE("iface %p, caps %p.\n", iface, caps);
1993
1994     hr = ddraw_surface7_GetCaps(&This->IDirectDrawSurface7_iface, &caps2);
1995     if (FAILED(hr)) return hr;
1996
1997     caps->dwCaps = caps2.dwCaps;
1998     return hr;
1999 }
2000
2001 /*****************************************************************************
2002  * IDirectDrawSurface7::SetPriority
2003  *
2004  * Sets a texture priority for managed textures.
2005  *
2006  * Params:
2007  *  Priority: The new priority
2008  *
2009  * Returns:
2010  *  DD_OK on success
2011  *  For more details, see IWineD3DSurface::SetPriority
2012  *
2013  *****************************************************************************/
2014 static HRESULT WINAPI ddraw_surface7_SetPriority(IDirectDrawSurface7 *iface, DWORD Priority)
2015 {
2016     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface7(iface);
2017     HRESULT hr;
2018
2019     TRACE("iface %p, priority %u.\n", iface, Priority);
2020
2021     EnterCriticalSection(&ddraw_cs);
2022     hr = wined3d_surface_set_priority(This->wined3d_surface, Priority);
2023     LeaveCriticalSection(&ddraw_cs);
2024     return hr;
2025 }
2026
2027 /*****************************************************************************
2028  * IDirectDrawSurface7::GetPriority
2029  *
2030  * Returns the surface's priority
2031  *
2032  * Params:
2033  *  Priority: Address of a variable to write the priority to
2034  *
2035  * Returns:
2036  *  D3D_OK on success
2037  *  DDERR_INVALIDPARAMS if Priority == NULL
2038  *  For more details, see IWineD3DSurface::GetPriority
2039  *
2040  *****************************************************************************/
2041 static HRESULT WINAPI ddraw_surface7_GetPriority(IDirectDrawSurface7 *iface, DWORD *Priority)
2042 {
2043     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface7(iface);
2044
2045     TRACE("iface %p, priority %p.\n", iface, Priority);
2046
2047     if(!Priority)
2048     {
2049         return DDERR_INVALIDPARAMS;
2050     }
2051
2052     EnterCriticalSection(&ddraw_cs);
2053     *Priority = wined3d_surface_get_priority(This->wined3d_surface);
2054     LeaveCriticalSection(&ddraw_cs);
2055     return DD_OK;
2056 }
2057
2058 /*****************************************************************************
2059  * IDirectDrawSurface7::SetPrivateData
2060  *
2061  * Stores some data in the surface that is intended for the application's
2062  * use.
2063  *
2064  * Params:
2065  *  tag: GUID that identifies the data
2066  *  Data: Pointer to the private data
2067  *  Size: Size of the private data
2068  *  Flags: Some flags
2069  *
2070  * Returns:
2071  *  D3D_OK on success
2072  *  For more details, see IWineD3DSurface::SetPrivateData
2073  *
2074  *****************************************************************************/
2075 static HRESULT WINAPI ddraw_surface7_SetPrivateData(IDirectDrawSurface7 *iface,
2076         REFGUID tag, void *Data, DWORD Size, DWORD Flags)
2077 {
2078     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface7(iface);
2079     struct wined3d_resource *resource;
2080     HRESULT hr;
2081
2082     TRACE("iface %p, tag %s, data %p, data_size %u, flags %#x.\n",
2083             iface, debugstr_guid(tag), Data, Size, Flags);
2084
2085     EnterCriticalSection(&ddraw_cs);
2086     resource = wined3d_surface_get_resource(This->wined3d_surface);
2087     hr = wined3d_resource_set_private_data(resource, tag, Data, Size, Flags);
2088     LeaveCriticalSection(&ddraw_cs);
2089     switch(hr)
2090     {
2091         case WINED3DERR_INVALIDCALL:        return DDERR_INVALIDPARAMS;
2092         default:                            return hr;
2093     }
2094 }
2095
2096 static HRESULT WINAPI ddraw_surface4_SetPrivateData(IDirectDrawSurface4 *iface,
2097         REFGUID tag, void *data, DWORD size, DWORD flags)
2098 {
2099     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface4(iface);
2100     TRACE("iface %p, tag %s, data %p, data_size %u, flags %#x.\n",
2101                 iface, debugstr_guid(tag), data, size, flags);
2102
2103     return ddraw_surface7_SetPrivateData(&This->IDirectDrawSurface7_iface, tag, data, size, flags);
2104 }
2105
2106 /*****************************************************************************
2107  * IDirectDrawSurface7::GetPrivateData
2108  *
2109  * Returns the private data set with IDirectDrawSurface7::SetPrivateData
2110  *
2111  * Params:
2112  *  tag: GUID of the data to return
2113  *  Data: Address where to write the data to
2114  *  Size: Size of the buffer at Data
2115  *
2116  * Returns:
2117  *  DD_OK on success
2118  *  DDERR_INVALIDPARAMS if Data is NULL
2119  *  For more details, see IWineD3DSurface::GetPrivateData
2120  *
2121  *****************************************************************************/
2122 static HRESULT WINAPI ddraw_surface7_GetPrivateData(IDirectDrawSurface7 *iface, REFGUID tag, void *Data, DWORD *Size)
2123 {
2124     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface7(iface);
2125     struct wined3d_resource *resource;
2126     HRESULT hr;
2127
2128     TRACE("iface %p, tag %s, data %p, data_size %p.\n",
2129             iface, debugstr_guid(tag), Data, Size);
2130
2131     if(!Data)
2132         return DDERR_INVALIDPARAMS;
2133
2134     EnterCriticalSection(&ddraw_cs);
2135     resource = wined3d_surface_get_resource(This->wined3d_surface);
2136     hr = wined3d_resource_get_private_data(resource, tag, Data, Size);
2137     LeaveCriticalSection(&ddraw_cs);
2138     return hr;
2139 }
2140
2141 static HRESULT WINAPI ddraw_surface4_GetPrivateData(IDirectDrawSurface4 *iface, REFGUID tag, void *data, DWORD *size)
2142 {
2143     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface4(iface);
2144     TRACE("iface %p, tag %s, data %p, data_size %p.\n",
2145                 iface, debugstr_guid(tag), data, size);
2146
2147     return ddraw_surface7_GetPrivateData(&This->IDirectDrawSurface7_iface, tag, data, size);
2148 }
2149
2150 /*****************************************************************************
2151  * IDirectDrawSurface7::FreePrivateData
2152  *
2153  * Frees private data stored in the surface
2154  *
2155  * Params:
2156  *  tag: Tag of the data to free
2157  *
2158  * Returns:
2159  *  D3D_OK on success
2160  *  For more details, see IWineD3DSurface::FreePrivateData
2161  *
2162  *****************************************************************************/
2163 static HRESULT WINAPI ddraw_surface7_FreePrivateData(IDirectDrawSurface7 *iface, REFGUID tag)
2164 {
2165     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface7(iface);
2166     struct wined3d_resource *resource;
2167     HRESULT hr;
2168
2169     TRACE("iface %p, tag %s.\n", iface, debugstr_guid(tag));
2170
2171     EnterCriticalSection(&ddraw_cs);
2172     resource = wined3d_surface_get_resource(This->wined3d_surface);
2173     hr = wined3d_resource_free_private_data(resource, tag);
2174     LeaveCriticalSection(&ddraw_cs);
2175     return hr;
2176 }
2177
2178 static HRESULT WINAPI ddraw_surface4_FreePrivateData(IDirectDrawSurface4 *iface, REFGUID tag)
2179 {
2180     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface4(iface);
2181     TRACE("iface %p, tag %s.\n", iface, debugstr_guid(tag));
2182
2183     return ddraw_surface7_FreePrivateData(&This->IDirectDrawSurface7_iface, tag);
2184 }
2185
2186 /*****************************************************************************
2187  * IDirectDrawSurface7::PageLock
2188  *
2189  * Prevents a sysmem surface from being paged out
2190  *
2191  * Params:
2192  *  Flags: Not used, must be 0(unchecked)
2193  *
2194  * Returns:
2195  *  DD_OK, because it's a stub
2196  *
2197  *****************************************************************************/
2198 static HRESULT WINAPI ddraw_surface7_PageLock(IDirectDrawSurface7 *iface, DWORD Flags)
2199 {
2200     TRACE("iface %p, flags %#x.\n", iface, Flags);
2201
2202     /* This is Windows memory management related - we don't need this */
2203     return DD_OK;
2204 }
2205
2206 static HRESULT WINAPI ddraw_surface4_PageLock(IDirectDrawSurface4 *iface, DWORD flags)
2207 {
2208     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface4(iface);
2209     TRACE("iface %p, flags %#x.\n", iface, flags);
2210
2211     return ddraw_surface7_PageLock(&This->IDirectDrawSurface7_iface, flags);
2212 }
2213
2214 static HRESULT WINAPI ddraw_surface3_PageLock(IDirectDrawSurface3 *iface, DWORD flags)
2215 {
2216     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface3(iface);
2217     TRACE("iface %p, flags %#x.\n", iface, flags);
2218
2219     return ddraw_surface7_PageLock(&This->IDirectDrawSurface7_iface, flags);
2220 }
2221
2222 static HRESULT WINAPI ddraw_surface2_PageLock(IDirectDrawSurface2 *iface, DWORD flags)
2223 {
2224     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface2(iface);
2225     TRACE("iface %p, flags %#x.\n", iface, flags);
2226
2227     return ddraw_surface7_PageLock(&This->IDirectDrawSurface7_iface, flags);
2228 }
2229
2230 /*****************************************************************************
2231  * IDirectDrawSurface7::PageUnlock
2232  *
2233  * Allows a sysmem surface to be paged out
2234  *
2235  * Params:
2236  *  Flags: Not used, must be 0(unchecked)
2237  *
2238  * Returns:
2239  *  DD_OK, because it's a stub
2240  *
2241  *****************************************************************************/
2242 static HRESULT WINAPI ddraw_surface7_PageUnlock(IDirectDrawSurface7 *iface, DWORD Flags)
2243 {
2244     TRACE("iface %p, flags %#x.\n", iface, Flags);
2245
2246     return DD_OK;
2247 }
2248
2249 static HRESULT WINAPI ddraw_surface4_PageUnlock(IDirectDrawSurface4 *iface, DWORD flags)
2250 {
2251     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface4(iface);
2252     TRACE("iface %p, flags %#x.\n", iface, flags);
2253
2254     return ddraw_surface7_PageUnlock(&This->IDirectDrawSurface7_iface, flags);
2255 }
2256
2257 static HRESULT WINAPI ddraw_surface3_PageUnlock(IDirectDrawSurface3 *iface, DWORD flags)
2258 {
2259     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface3(iface);
2260     TRACE("iface %p, flags %#x.\n", iface, flags);
2261
2262     return ddraw_surface7_PageUnlock(&This->IDirectDrawSurface7_iface, flags);
2263 }
2264
2265 static HRESULT WINAPI ddraw_surface2_PageUnlock(IDirectDrawSurface2 *iface, DWORD flags)
2266 {
2267     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface2(iface);
2268     TRACE("iface %p, flags %#x.\n", iface, flags);
2269
2270     return ddraw_surface7_PageUnlock(&This->IDirectDrawSurface7_iface, flags);
2271 }
2272
2273 /*****************************************************************************
2274  * IDirectDrawSurface7::BltBatch
2275  *
2276  * An unimplemented function
2277  *
2278  * Params:
2279  *  ?
2280  *
2281  * Returns:
2282  *  DDERR_UNSUPPORTED
2283  *
2284  *****************************************************************************/
2285 static HRESULT WINAPI ddraw_surface7_BltBatch(IDirectDrawSurface7 *iface, DDBLTBATCH *Batch, DWORD Count, DWORD Flags)
2286 {
2287     TRACE("iface %p, batch %p, count %u, flags %#x.\n", iface, Batch, Count, Flags);
2288
2289     /* MSDN: "not currently implemented" */
2290     return DDERR_UNSUPPORTED;
2291 }
2292
2293 static HRESULT WINAPI ddraw_surface4_BltBatch(IDirectDrawSurface4 *iface, DDBLTBATCH *batch, DWORD count, DWORD flags)
2294 {
2295     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface4(iface);
2296     TRACE("iface %p, batch %p, count %u, flags %#x.\n", iface, batch, count, flags);
2297
2298     return ddraw_surface7_BltBatch(&This->IDirectDrawSurface7_iface, batch, count, flags);
2299 }
2300
2301 static HRESULT WINAPI ddraw_surface3_BltBatch(IDirectDrawSurface3 *iface, DDBLTBATCH *batch, DWORD count, DWORD flags)
2302 {
2303     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface3(iface);
2304     TRACE("iface %p, batch %p, count %u, flags %#x.\n", iface, batch, count, flags);
2305
2306     return ddraw_surface7_BltBatch(&This->IDirectDrawSurface7_iface, batch, count, flags);
2307 }
2308
2309 static HRESULT WINAPI ddraw_surface2_BltBatch(IDirectDrawSurface2 *iface, DDBLTBATCH *batch, DWORD count, DWORD flags)
2310 {
2311     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface2(iface);
2312     TRACE("iface %p, batch %p, count %u, flags %#x.\n", iface, batch, count, flags);
2313
2314     return ddraw_surface7_BltBatch(&This->IDirectDrawSurface7_iface, batch, count, flags);
2315 }
2316
2317 static HRESULT WINAPI ddraw_surface1_BltBatch(IDirectDrawSurface *iface, DDBLTBATCH *batch, DWORD count, DWORD flags)
2318 {
2319     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface(iface);
2320     TRACE("iface %p, batch %p, count %u, flags %#x.\n", iface, batch, count, flags);
2321
2322     return ddraw_surface7_BltBatch(&This->IDirectDrawSurface7_iface, batch, count, flags);
2323 }
2324
2325 /*****************************************************************************
2326  * IDirectDrawSurface7::EnumAttachedSurfaces
2327  *
2328  * Enumerates all surfaces attached to this surface
2329  *
2330  * Params:
2331  *  context: Pointer to pass unmodified to the callback
2332  *  cb: Callback function to call for each surface
2333  *
2334  * Returns:
2335  *  DD_OK on success
2336  *  DDERR_INVALIDPARAMS if cb is NULL
2337  *
2338  *****************************************************************************/
2339 static HRESULT WINAPI ddraw_surface7_EnumAttachedSurfaces(IDirectDrawSurface7 *iface,
2340         void *context, LPDDENUMSURFACESCALLBACK7 cb)
2341 {
2342     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface7(iface);
2343     IDirectDrawSurfaceImpl *surf;
2344     DDSURFACEDESC2 desc;
2345     int i;
2346
2347     /* Attached surfaces aren't handled in WineD3D */
2348     TRACE("iface %p, context %p, callback %p.\n", iface, context, cb);
2349
2350     if(!cb)
2351         return DDERR_INVALIDPARAMS;
2352
2353     EnterCriticalSection(&ddraw_cs);
2354     for(i = 0; i < MAX_COMPLEX_ATTACHED; i++)
2355     {
2356         surf = This->complex_array[i];
2357         if(!surf) break;
2358
2359         ddraw_surface7_AddRef(&surf->IDirectDrawSurface7_iface);
2360         desc = surf->surface_desc;
2361         /* check: != DDENUMRET_OK or == DDENUMRET_CANCEL? */
2362         if (cb(&surf->IDirectDrawSurface7_iface, &desc, context) == DDENUMRET_CANCEL)
2363         {
2364             LeaveCriticalSection(&ddraw_cs);
2365             return DD_OK;
2366         }
2367     }
2368
2369     for (surf = This->next_attached; surf != NULL; surf = surf->next_attached)
2370     {
2371         ddraw_surface7_AddRef(&surf->IDirectDrawSurface7_iface);
2372         desc = surf->surface_desc;
2373         /* check: != DDENUMRET_OK or == DDENUMRET_CANCEL? */
2374         if (cb(&surf->IDirectDrawSurface7_iface, &desc, context) == DDENUMRET_CANCEL)
2375         {
2376             LeaveCriticalSection(&ddraw_cs);
2377             return DD_OK;
2378         }
2379     }
2380
2381     TRACE(" end of enumeration.\n");
2382
2383     LeaveCriticalSection(&ddraw_cs);
2384     return DD_OK;
2385 }
2386
2387 struct callback_info2
2388 {
2389     LPDDENUMSURFACESCALLBACK2 callback;
2390     void *context;
2391 };
2392
2393 struct callback_info
2394 {
2395     LPDDENUMSURFACESCALLBACK callback;
2396     void *context;
2397 };
2398
2399 static HRESULT CALLBACK EnumCallback2(IDirectDrawSurface7 *surface, DDSURFACEDESC2 *surface_desc, void *context)
2400 {
2401     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface7(surface);
2402     const struct callback_info2 *info = context;
2403
2404     ddraw_surface4_AddRef(&This->IDirectDrawSurface4_iface);
2405     ddraw_surface7_Release(surface);
2406
2407     return info->callback(&This->IDirectDrawSurface4_iface, surface_desc, info->context);
2408 }
2409
2410 static HRESULT CALLBACK EnumCallback(IDirectDrawSurface7 *surface, DDSURFACEDESC2 *surface_desc, void *context)
2411 {
2412     IDirectDrawSurfaceImpl *surface_impl = impl_from_IDirectDrawSurface7(surface);
2413     const struct callback_info *info = context;
2414
2415     ddraw_surface1_AddRef(&surface_impl->IDirectDrawSurface_iface);
2416     ddraw_surface7_Release(surface);
2417
2418     /* FIXME: Check surface_test.dwSize */
2419     return info->callback(&surface_impl->IDirectDrawSurface_iface,
2420             (DDSURFACEDESC *)surface_desc, info->context);
2421 }
2422
2423 static HRESULT WINAPI ddraw_surface4_EnumAttachedSurfaces(IDirectDrawSurface4 *iface,
2424         void *context, LPDDENUMSURFACESCALLBACK2 callback)
2425 {
2426     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface4(iface);
2427     struct callback_info2 info;
2428
2429     TRACE("iface %p, context %p, callback %p.\n", iface, context, callback);
2430
2431     info.callback = callback;
2432     info.context  = context;
2433
2434     return ddraw_surface7_EnumAttachedSurfaces(&This->IDirectDrawSurface7_iface,
2435             &info, EnumCallback2);
2436 }
2437
2438 static HRESULT WINAPI ddraw_surface3_EnumAttachedSurfaces(IDirectDrawSurface3 *iface,
2439         void *context, LPDDENUMSURFACESCALLBACK callback)
2440 {
2441     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface3(iface);
2442     struct callback_info info;
2443
2444     TRACE("iface %p, context %p, callback %p.\n", iface, context, callback);
2445
2446     info.callback = callback;
2447     info.context  = context;
2448
2449     return ddraw_surface7_EnumAttachedSurfaces(&This->IDirectDrawSurface7_iface,
2450             &info, EnumCallback);
2451 }
2452
2453 static HRESULT WINAPI ddraw_surface2_EnumAttachedSurfaces(IDirectDrawSurface2 *iface,
2454         void *context, LPDDENUMSURFACESCALLBACK callback)
2455 {
2456     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface2(iface);
2457     struct callback_info info;
2458
2459     TRACE("iface %p, context %p, callback %p.\n", iface, context, callback);
2460
2461     info.callback = callback;
2462     info.context  = context;
2463
2464     return ddraw_surface7_EnumAttachedSurfaces(&This->IDirectDrawSurface7_iface,
2465             &info, EnumCallback);
2466 }
2467
2468 static HRESULT WINAPI ddraw_surface1_EnumAttachedSurfaces(IDirectDrawSurface *iface,
2469         void *context, LPDDENUMSURFACESCALLBACK callback)
2470 {
2471     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface(iface);
2472     struct callback_info info;
2473
2474     TRACE("iface %p, context %p, callback %p.\n", iface, context, callback);
2475
2476     info.callback = callback;
2477     info.context  = context;
2478
2479     return ddraw_surface7_EnumAttachedSurfaces(&This->IDirectDrawSurface7_iface,
2480             &info, EnumCallback);
2481 }
2482
2483 /*****************************************************************************
2484  * IDirectDrawSurface7::EnumOverlayZOrders
2485  *
2486  * "Enumerates the overlay surfaces on the specified destination"
2487  *
2488  * Params:
2489  *  Flags: DDENUMOVERLAYZ_BACKTOFRONT  or DDENUMOVERLAYZ_FRONTTOBACK
2490  *  context: context to pass back to the callback
2491  *  cb: callback function to call for each enumerated surface
2492  *
2493  * Returns:
2494  *  DD_OK, because it's a stub
2495  *
2496  *****************************************************************************/
2497 static HRESULT WINAPI ddraw_surface7_EnumOverlayZOrders(IDirectDrawSurface7 *iface,
2498         DWORD Flags, void *context, LPDDENUMSURFACESCALLBACK7 cb)
2499 {
2500     FIXME("iface %p, flags %#x, context %p, callback %p stub!\n", iface, Flags, context, cb);
2501
2502     return DD_OK;
2503 }
2504
2505 static HRESULT WINAPI ddraw_surface4_EnumOverlayZOrders(IDirectDrawSurface4 *iface,
2506         DWORD flags, void *context, LPDDENUMSURFACESCALLBACK2 callback)
2507 {
2508     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface4(iface);
2509     struct callback_info2 info;
2510
2511     TRACE("iface %p, flags %#x, context %p, callback %p.\n", iface, flags, context, callback);
2512
2513     info.callback = callback;
2514     info.context  = context;
2515
2516     return ddraw_surface7_EnumOverlayZOrders(&This->IDirectDrawSurface7_iface,
2517             flags, &info, EnumCallback2);
2518 }
2519
2520 static HRESULT WINAPI ddraw_surface3_EnumOverlayZOrders(IDirectDrawSurface3 *iface,
2521         DWORD flags, void *context, LPDDENUMSURFACESCALLBACK callback)
2522 {
2523     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface3(iface);
2524     struct callback_info info;
2525
2526     TRACE("iface %p, flags %#x, context %p, callback %p.\n", iface, flags, context, callback);
2527
2528     info.callback = callback;
2529     info.context  = context;
2530
2531     return ddraw_surface7_EnumOverlayZOrders(&This->IDirectDrawSurface7_iface,
2532             flags, &info, EnumCallback);
2533 }
2534
2535 static HRESULT WINAPI ddraw_surface2_EnumOverlayZOrders(IDirectDrawSurface2 *iface,
2536         DWORD flags, void *context, LPDDENUMSURFACESCALLBACK callback)
2537 {
2538     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface2(iface);
2539     struct callback_info info;
2540
2541     TRACE("iface %p, flags %#x, context %p, callback %p.\n", iface, flags, context, callback);
2542
2543     info.callback = callback;
2544     info.context  = context;
2545
2546     return ddraw_surface7_EnumOverlayZOrders(&This->IDirectDrawSurface7_iface,
2547             flags, &info, EnumCallback);
2548 }
2549
2550 static HRESULT WINAPI ddraw_surface1_EnumOverlayZOrders(IDirectDrawSurface *iface,
2551         DWORD flags, void *context, LPDDENUMSURFACESCALLBACK callback)
2552 {
2553     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface(iface);
2554     struct callback_info info;
2555
2556     TRACE("iface %p, flags %#x, context %p, callback %p.\n", iface, flags, context, callback);
2557
2558     info.callback = callback;
2559     info.context  = context;
2560
2561     return ddraw_surface7_EnumOverlayZOrders(&This->IDirectDrawSurface7_iface,
2562             flags, &info, EnumCallback);
2563 }
2564
2565 /*****************************************************************************
2566  * IDirectDrawSurface7::GetBltStatus
2567  *
2568  * Returns the blitting status
2569  *
2570  * Params:
2571  *  Flags: DDGBS_CANBLT or DDGBS_ISBLTDONE
2572  *
2573  * Returns:
2574  *  See IWineD3DSurface::Blt
2575  *
2576  *****************************************************************************/
2577 static HRESULT WINAPI ddraw_surface7_GetBltStatus(IDirectDrawSurface7 *iface, DWORD Flags)
2578 {
2579     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface7(iface);
2580     HRESULT hr;
2581
2582     TRACE("iface %p, flags %#x.\n", iface, Flags);
2583
2584     EnterCriticalSection(&ddraw_cs);
2585     hr = wined3d_surface_get_blt_status(This->wined3d_surface, Flags);
2586     LeaveCriticalSection(&ddraw_cs);
2587     switch(hr)
2588     {
2589         case WINED3DERR_INVALIDCALL:        return DDERR_INVALIDPARAMS;
2590         default:                            return hr;
2591     }
2592 }
2593
2594 static HRESULT WINAPI ddraw_surface4_GetBltStatus(IDirectDrawSurface4 *iface, DWORD flags)
2595 {
2596     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface4(iface);
2597     TRACE("iface %p, flags %#x.\n", iface, flags);
2598
2599     return ddraw_surface7_GetBltStatus(&This->IDirectDrawSurface7_iface, flags);
2600 }
2601
2602 static HRESULT WINAPI ddraw_surface3_GetBltStatus(IDirectDrawSurface3 *iface, DWORD flags)
2603 {
2604     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface3(iface);
2605     TRACE("iface %p, flags %#x.\n", iface, flags);
2606
2607     return ddraw_surface7_GetBltStatus(&This->IDirectDrawSurface7_iface, flags);
2608 }
2609
2610 static HRESULT WINAPI ddraw_surface2_GetBltStatus(IDirectDrawSurface2 *iface, DWORD flags)
2611 {
2612     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface2(iface);
2613     TRACE("iface %p, flags %#x.\n", iface, flags);
2614
2615     return ddraw_surface7_GetBltStatus(&This->IDirectDrawSurface7_iface, flags);
2616 }
2617
2618 static HRESULT WINAPI ddraw_surface1_GetBltStatus(IDirectDrawSurface *iface, DWORD flags)
2619 {
2620     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface(iface);
2621     TRACE("iface %p, flags %#x.\n", iface, flags);
2622
2623     return ddraw_surface7_GetBltStatus(&This->IDirectDrawSurface7_iface, flags);
2624 }
2625
2626 /*****************************************************************************
2627  * IDirectDrawSurface7::GetColorKey
2628  *
2629  * Returns the color key assigned to the surface
2630  *
2631  * Params:
2632  *  Flags: Some flags
2633  *  CKey: Address to store the key to
2634  *
2635  * Returns:
2636  *  DD_OK on success
2637  *  DDERR_INVALIDPARAMS if CKey is NULL
2638  *
2639  *****************************************************************************/
2640 static HRESULT WINAPI ddraw_surface7_GetColorKey(IDirectDrawSurface7 *iface, DWORD Flags, DDCOLORKEY *CKey)
2641 {
2642     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface7(iface);
2643
2644     TRACE("iface %p, flags %#x, color_key %p.\n", iface, Flags, CKey);
2645
2646     if(!CKey)
2647         return DDERR_INVALIDPARAMS;
2648
2649     EnterCriticalSection(&ddraw_cs);
2650
2651     switch (Flags)
2652     {
2653     case DDCKEY_DESTBLT:
2654         if (!(This->surface_desc.dwFlags & DDSD_CKDESTBLT))
2655         {
2656             LeaveCriticalSection(&ddraw_cs);
2657             return DDERR_NOCOLORKEY;
2658         }
2659         *CKey = This->surface_desc.ddckCKDestBlt;
2660         break;
2661
2662     case DDCKEY_DESTOVERLAY:
2663         if (!(This->surface_desc.dwFlags & DDSD_CKDESTOVERLAY))
2664             {
2665             LeaveCriticalSection(&ddraw_cs);
2666             return DDERR_NOCOLORKEY;
2667             }
2668         *CKey = This->surface_desc.u3.ddckCKDestOverlay;
2669         break;
2670
2671     case DDCKEY_SRCBLT:
2672         if (!(This->surface_desc.dwFlags & DDSD_CKSRCBLT))
2673         {
2674             LeaveCriticalSection(&ddraw_cs);
2675             return DDERR_NOCOLORKEY;
2676         }
2677         *CKey = This->surface_desc.ddckCKSrcBlt;
2678         break;
2679
2680     case DDCKEY_SRCOVERLAY:
2681         if (!(This->surface_desc.dwFlags & DDSD_CKSRCOVERLAY))
2682         {
2683             LeaveCriticalSection(&ddraw_cs);
2684             return DDERR_NOCOLORKEY;
2685         }
2686         *CKey = This->surface_desc.ddckCKSrcOverlay;
2687         break;
2688
2689     default:
2690         LeaveCriticalSection(&ddraw_cs);
2691         return DDERR_INVALIDPARAMS;
2692     }
2693
2694     LeaveCriticalSection(&ddraw_cs);
2695     return DD_OK;
2696 }
2697
2698 static HRESULT WINAPI ddraw_surface4_GetColorKey(IDirectDrawSurface4 *iface, DWORD flags, DDCOLORKEY *color_key)
2699 {
2700     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface4(iface);
2701     TRACE("iface %p, flags %#x, color_key %p.\n", iface, flags, color_key);
2702
2703     return ddraw_surface7_GetColorKey(&This->IDirectDrawSurface7_iface, flags, color_key);
2704 }
2705
2706 static HRESULT WINAPI ddraw_surface3_GetColorKey(IDirectDrawSurface3 *iface, DWORD flags, DDCOLORKEY *color_key)
2707 {
2708     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface3(iface);
2709     TRACE("iface %p, flags %#x, color_key %p.\n", iface, flags, color_key);
2710
2711     return ddraw_surface7_GetColorKey(&This->IDirectDrawSurface7_iface, flags, color_key);
2712 }
2713
2714 static HRESULT WINAPI ddraw_surface2_GetColorKey(IDirectDrawSurface2 *iface, DWORD flags, DDCOLORKEY *color_key)
2715 {
2716     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface2(iface);
2717     TRACE("iface %p, flags %#x, color_key %p.\n", iface, flags, color_key);
2718
2719     return ddraw_surface7_GetColorKey(&This->IDirectDrawSurface7_iface, flags, color_key);
2720 }
2721
2722 static HRESULT WINAPI ddraw_surface1_GetColorKey(IDirectDrawSurface *iface, DWORD flags, DDCOLORKEY *color_key)
2723 {
2724     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface(iface);
2725     TRACE("iface %p, flags %#x, color_key %p.\n", iface, flags, color_key);
2726
2727     return ddraw_surface7_GetColorKey(&This->IDirectDrawSurface7_iface, flags, color_key);
2728 }
2729
2730 /*****************************************************************************
2731  * IDirectDrawSurface7::GetFlipStatus
2732  *
2733  * Returns the flipping status of the surface
2734  *
2735  * Params:
2736  *  Flags: DDGFS_CANFLIP of DDGFS_ISFLIPDONE
2737  *
2738  * Returns:
2739  *  See IWineD3DSurface::GetFlipStatus
2740  *
2741  *****************************************************************************/
2742 static HRESULT WINAPI ddraw_surface7_GetFlipStatus(IDirectDrawSurface7 *iface, DWORD Flags)
2743 {
2744     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface7(iface);
2745     HRESULT hr;
2746
2747     TRACE("iface %p, flags %#x.\n", iface, Flags);
2748
2749     EnterCriticalSection(&ddraw_cs);
2750     hr = wined3d_surface_get_flip_status(This->wined3d_surface, Flags);
2751     LeaveCriticalSection(&ddraw_cs);
2752     switch(hr)
2753     {
2754         case WINED3DERR_INVALIDCALL:        return DDERR_INVALIDPARAMS;
2755         default:                            return hr;
2756     }
2757 }
2758
2759 static HRESULT WINAPI ddraw_surface4_GetFlipStatus(IDirectDrawSurface4 *iface, DWORD flags)
2760 {
2761     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface4(iface);
2762     TRACE("iface %p, flags %#x.\n", iface, flags);
2763
2764     return ddraw_surface7_GetFlipStatus(&This->IDirectDrawSurface7_iface, flags);
2765 }
2766
2767 static HRESULT WINAPI ddraw_surface3_GetFlipStatus(IDirectDrawSurface3 *iface, DWORD flags)
2768 {
2769     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface3(iface);
2770     TRACE("iface %p, flags %#x.\n", iface, flags);
2771
2772     return ddraw_surface7_GetFlipStatus(&This->IDirectDrawSurface7_iface, flags);
2773 }
2774
2775 static HRESULT WINAPI ddraw_surface2_GetFlipStatus(IDirectDrawSurface2 *iface, DWORD flags)
2776 {
2777     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface2(iface);
2778     TRACE("iface %p, flags %#x.\n", iface, flags);
2779
2780     return ddraw_surface7_GetFlipStatus(&This->IDirectDrawSurface7_iface, flags);
2781 }
2782
2783 static HRESULT WINAPI ddraw_surface1_GetFlipStatus(IDirectDrawSurface *iface, DWORD flags)
2784 {
2785     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface(iface);
2786     TRACE("iface %p, flags %#x.\n", iface, flags);
2787
2788     return ddraw_surface7_GetFlipStatus(&This->IDirectDrawSurface7_iface, flags);
2789 }
2790
2791 /*****************************************************************************
2792  * IDirectDrawSurface7::GetOverlayPosition
2793  *
2794  * Returns the display coordinates of a visible and active overlay surface
2795  *
2796  * Params:
2797  *  X
2798  *  Y
2799  *
2800  * Returns:
2801  *  DDERR_NOTAOVERLAYSURFACE, because it's a stub
2802  *****************************************************************************/
2803 static HRESULT WINAPI ddraw_surface7_GetOverlayPosition(IDirectDrawSurface7 *iface, LONG *X, LONG *Y)
2804 {
2805     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface7(iface);
2806     HRESULT hr;
2807
2808     TRACE("iface %p, x %p, y %p.\n", iface, X, Y);
2809
2810     EnterCriticalSection(&ddraw_cs);
2811     hr = wined3d_surface_get_overlay_position(This->wined3d_surface, X, Y);
2812     LeaveCriticalSection(&ddraw_cs);
2813     return hr;
2814 }
2815
2816 static HRESULT WINAPI ddraw_surface4_GetOverlayPosition(IDirectDrawSurface4 *iface, LONG *x, LONG *y)
2817 {
2818     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface4(iface);
2819     TRACE("iface %p, x %p, y %p.\n", iface, x, y);
2820
2821     return ddraw_surface7_GetOverlayPosition(&This->IDirectDrawSurface7_iface, x, y);
2822 }
2823
2824 static HRESULT WINAPI ddraw_surface3_GetOverlayPosition(IDirectDrawSurface3 *iface, LONG *x, LONG *y)
2825 {
2826     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface3(iface);
2827     TRACE("iface %p, x %p, y %p.\n", iface, x, y);
2828
2829     return ddraw_surface7_GetOverlayPosition(&This->IDirectDrawSurface7_iface, x, y);
2830 }
2831
2832 static HRESULT WINAPI ddraw_surface2_GetOverlayPosition(IDirectDrawSurface2 *iface, LONG *x, LONG *y)
2833 {
2834     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface2(iface);
2835     TRACE("iface %p, x %p, y %p.\n", iface, x, y);
2836
2837     return ddraw_surface7_GetOverlayPosition(&This->IDirectDrawSurface7_iface, x, y);
2838 }
2839
2840 static HRESULT WINAPI ddraw_surface1_GetOverlayPosition(IDirectDrawSurface *iface, LONG *x, LONG *y)
2841 {
2842     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface(iface);
2843     TRACE("iface %p, x %p, y %p.\n", iface, x, y);
2844
2845     return ddraw_surface7_GetOverlayPosition(&This->IDirectDrawSurface7_iface, x, y);
2846 }
2847
2848 /*****************************************************************************
2849  * IDirectDrawSurface7::GetPixelFormat
2850  *
2851  * Returns the pixel format of the Surface
2852  *
2853  * Params:
2854  *  PixelFormat: Pointer to a DDPIXELFORMAT structure to which the pixel
2855  *               format should be written
2856  *
2857  * Returns:
2858  *  DD_OK on success
2859  *  DDERR_INVALIDPARAMS if PixelFormat is NULL
2860  *
2861  *****************************************************************************/
2862 static HRESULT WINAPI ddraw_surface7_GetPixelFormat(IDirectDrawSurface7 *iface, DDPIXELFORMAT *PixelFormat)
2863 {
2864     /* What is DDERR_INVALIDSURFACETYPE for here? */
2865     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface7(iface);
2866
2867     TRACE("iface %p, pixel_format %p.\n", iface, PixelFormat);
2868
2869     if(!PixelFormat)
2870         return DDERR_INVALIDPARAMS;
2871
2872     EnterCriticalSection(&ddraw_cs);
2873     DD_STRUCT_COPY_BYSIZE(PixelFormat,&This->surface_desc.u4.ddpfPixelFormat);
2874     LeaveCriticalSection(&ddraw_cs);
2875
2876     return DD_OK;
2877 }
2878
2879 static HRESULT WINAPI ddraw_surface4_GetPixelFormat(IDirectDrawSurface4 *iface, DDPIXELFORMAT *pixel_format)
2880 {
2881     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface4(iface);
2882     TRACE("iface %p, pixel_format %p.\n", iface, pixel_format);
2883
2884     return ddraw_surface7_GetPixelFormat(&This->IDirectDrawSurface7_iface, pixel_format);
2885 }
2886
2887 static HRESULT WINAPI ddraw_surface3_GetPixelFormat(IDirectDrawSurface3 *iface, DDPIXELFORMAT *pixel_format)
2888 {
2889     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface3(iface);
2890     TRACE("iface %p, pixel_format %p.\n", iface, pixel_format);
2891
2892     return ddraw_surface7_GetPixelFormat(&This->IDirectDrawSurface7_iface, pixel_format);
2893 }
2894
2895 static HRESULT WINAPI ddraw_surface2_GetPixelFormat(IDirectDrawSurface2 *iface, DDPIXELFORMAT *pixel_format)
2896 {
2897     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface2(iface);
2898     TRACE("iface %p, pixel_format %p.\n", iface, pixel_format);
2899
2900     return ddraw_surface7_GetPixelFormat(&This->IDirectDrawSurface7_iface, pixel_format);
2901 }
2902
2903 static HRESULT WINAPI ddraw_surface1_GetPixelFormat(IDirectDrawSurface *iface, DDPIXELFORMAT *pixel_format)
2904 {
2905     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface(iface);
2906     TRACE("iface %p, pixel_format %p.\n", iface, pixel_format);
2907
2908     return ddraw_surface7_GetPixelFormat(&This->IDirectDrawSurface7_iface, pixel_format);
2909 }
2910
2911 /*****************************************************************************
2912  * IDirectDrawSurface7::GetSurfaceDesc
2913  *
2914  * Returns the description of this surface
2915  *
2916  * Params:
2917  *  DDSD: Address of a DDSURFACEDESC2 structure that is to be filled with the
2918  *        surface desc
2919  *
2920  * Returns:
2921  *  DD_OK on success
2922  *  DDERR_INVALIDPARAMS if DDSD is NULL
2923  *
2924  *****************************************************************************/
2925 static HRESULT WINAPI ddraw_surface7_GetSurfaceDesc(IDirectDrawSurface7 *iface, DDSURFACEDESC2 *DDSD)
2926 {
2927     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface7(iface);
2928
2929     TRACE("iface %p, surface_desc %p.\n", iface, DDSD);
2930
2931     if(!DDSD)
2932         return DDERR_INVALIDPARAMS;
2933
2934     if (DDSD->dwSize != sizeof(DDSURFACEDESC2))
2935     {
2936         WARN("Incorrect struct size %d, returning DDERR_INVALIDPARAMS\n",DDSD->dwSize);
2937         return DDERR_INVALIDPARAMS;
2938     }
2939
2940     EnterCriticalSection(&ddraw_cs);
2941     DD_STRUCT_COPY_BYSIZE(DDSD,&This->surface_desc);
2942     TRACE("Returning surface desc:\n");
2943     if (TRACE_ON(ddraw)) DDRAW_dump_surface_desc(DDSD);
2944
2945     LeaveCriticalSection(&ddraw_cs);
2946     return DD_OK;
2947 }
2948
2949 static HRESULT WINAPI ddraw_surface4_GetSurfaceDesc(IDirectDrawSurface4 *iface, DDSURFACEDESC2 *DDSD)
2950 {
2951     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface4(iface);
2952     TRACE("iface %p, surface_desc %p.\n", iface, DDSD);
2953
2954     return ddraw_surface7_GetSurfaceDesc(&This->IDirectDrawSurface7_iface, DDSD);
2955 }
2956
2957 static HRESULT WINAPI ddraw_surface3_GetSurfaceDesc(IDirectDrawSurface3 *iface, DDSURFACEDESC *surface_desc)
2958 {
2959     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface3(iface);
2960
2961     TRACE("iface %p, surface_desc %p.\n", iface, surface_desc);
2962
2963     if (!surface_desc) return DDERR_INVALIDPARAMS;
2964
2965     if (surface_desc->dwSize != sizeof(DDSURFACEDESC))
2966     {
2967         WARN("Incorrect structure size %u, returning DDERR_INVALIDPARAMS.\n", surface_desc->dwSize);
2968         return DDERR_INVALIDPARAMS;
2969     }
2970
2971     EnterCriticalSection(&ddraw_cs);
2972     DDSD2_to_DDSD(&This->surface_desc, surface_desc);
2973     TRACE("Returning surface desc:\n");
2974     if (TRACE_ON(ddraw))
2975     {
2976         /* DDRAW_dump_surface_desc handles the smaller size */
2977         DDRAW_dump_surface_desc((DDSURFACEDESC2 *)surface_desc);
2978     }
2979
2980     LeaveCriticalSection(&ddraw_cs);
2981     return DD_OK;
2982 }
2983
2984 static HRESULT WINAPI ddraw_surface2_GetSurfaceDesc(IDirectDrawSurface2 *iface, DDSURFACEDESC *DDSD)
2985 {
2986     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface2(iface);
2987     TRACE("iface %p, surface_desc %p.\n", iface, DDSD);
2988
2989     return ddraw_surface3_GetSurfaceDesc(&This->IDirectDrawSurface3_iface, DDSD);
2990 }
2991
2992 static HRESULT WINAPI ddraw_surface1_GetSurfaceDesc(IDirectDrawSurface *iface, DDSURFACEDESC *DDSD)
2993 {
2994     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface(iface);
2995     TRACE("iface %p, surface_desc %p.\n", iface, DDSD);
2996
2997     return ddraw_surface3_GetSurfaceDesc(&This->IDirectDrawSurface3_iface, DDSD);
2998 }
2999
3000 /*****************************************************************************
3001  * IDirectDrawSurface7::Initialize
3002  *
3003  * Initializes the surface. This is a no-op in Wine
3004  *
3005  * Params:
3006  *  DD: Pointer to an DirectDraw interface
3007  *  DDSD: Surface description for initialization
3008  *
3009  * Returns:
3010  *  DDERR_ALREADYINITIALIZED
3011  *
3012  *****************************************************************************/
3013 static HRESULT WINAPI ddraw_surface7_Initialize(IDirectDrawSurface7 *iface,
3014         IDirectDraw *ddraw, DDSURFACEDESC2 *surface_desc)
3015 {
3016     TRACE("iface %p, ddraw %p, surface_desc %p.\n", iface, ddraw, surface_desc);
3017
3018     return DDERR_ALREADYINITIALIZED;
3019 }
3020
3021 static HRESULT WINAPI ddraw_surface4_Initialize(IDirectDrawSurface4 *iface,
3022         IDirectDraw *ddraw, DDSURFACEDESC2 *surface_desc)
3023 {
3024     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface4(iface);
3025     TRACE("iface %p, ddraw %p, surface_desc %p.\n", iface, ddraw, surface_desc);
3026
3027     return ddraw_surface7_Initialize(&This->IDirectDrawSurface7_iface,
3028             ddraw, surface_desc);
3029 }
3030
3031 static HRESULT WINAPI ddraw_surface3_Initialize(IDirectDrawSurface3 *iface,
3032         IDirectDraw *ddraw, DDSURFACEDESC *surface_desc)
3033 {
3034     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface3(iface);
3035     DDSURFACEDESC2 surface_desc2;
3036     TRACE("iface %p, ddraw %p, surface_desc %p.\n", iface, ddraw, surface_desc);
3037
3038     if (surface_desc) DDSD_to_DDSD2(surface_desc, &surface_desc2);
3039     return ddraw_surface7_Initialize(&This->IDirectDrawSurface7_iface,
3040             ddraw, surface_desc ? &surface_desc2 : NULL);
3041 }
3042
3043 static HRESULT WINAPI ddraw_surface2_Initialize(IDirectDrawSurface2 *iface,
3044         IDirectDraw *ddraw, DDSURFACEDESC *surface_desc)
3045 {
3046     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface2(iface);
3047     DDSURFACEDESC2 surface_desc2;
3048     TRACE("iface %p, ddraw %p, surface_desc %p.\n", iface, ddraw, surface_desc);
3049
3050     if (surface_desc) DDSD_to_DDSD2(surface_desc, &surface_desc2);
3051     return ddraw_surface7_Initialize(&This->IDirectDrawSurface7_iface,
3052             ddraw, surface_desc ? &surface_desc2 : NULL);
3053 }
3054
3055 static HRESULT WINAPI ddraw_surface1_Initialize(IDirectDrawSurface *iface,
3056         IDirectDraw *ddraw, DDSURFACEDESC *surface_desc)
3057 {
3058     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface(iface);
3059     DDSURFACEDESC2 surface_desc2;
3060     TRACE("iface %p, ddraw %p, surface_desc %p.\n", iface, ddraw, surface_desc);
3061
3062     if (surface_desc) DDSD_to_DDSD2(surface_desc, &surface_desc2);
3063     return ddraw_surface7_Initialize(&This->IDirectDrawSurface7_iface,
3064             ddraw, surface_desc ? &surface_desc2 : NULL);
3065 }
3066
3067 /*****************************************************************************
3068  * IDirect3DTexture1::Initialize
3069  *
3070  * The sdk says it's not implemented
3071  *
3072  * Params:
3073  *  ?
3074  *
3075  * Returns
3076  *  DDERR_UNSUPPORTED
3077  *
3078  *****************************************************************************/
3079 static HRESULT WINAPI d3d_texture1_Initialize(IDirect3DTexture *iface,
3080         IDirect3DDevice *device, IDirectDrawSurface *surface)
3081 {
3082     TRACE("iface %p, device %p, surface %p.\n", iface, device, surface);
3083
3084     return DDERR_UNSUPPORTED; /* Unchecked */
3085 }
3086
3087 /*****************************************************************************
3088  * IDirectDrawSurface7::IsLost
3089  *
3090  * Checks if the surface is lost
3091  *
3092  * Returns:
3093  *  DD_OK, if the surface is usable
3094  *  DDERR_ISLOST if the surface is lost
3095  *  See IWineD3DSurface::IsLost for more details
3096  *
3097  *****************************************************************************/
3098 static HRESULT WINAPI ddraw_surface7_IsLost(IDirectDrawSurface7 *iface)
3099 {
3100     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface7(iface);
3101     HRESULT hr;
3102
3103     TRACE("iface %p.\n", iface);
3104
3105     EnterCriticalSection(&ddraw_cs);
3106     hr = wined3d_surface_is_lost(This->wined3d_surface);
3107     LeaveCriticalSection(&ddraw_cs);
3108     switch(hr)
3109     {
3110         /* D3D8 and 9 loose full devices, thus there's only a DEVICELOST error.
3111          * WineD3D uses the same error for surfaces
3112          */
3113         case WINED3DERR_DEVICELOST:         return DDERR_SURFACELOST;
3114         default:                            return hr;
3115     }
3116 }
3117
3118 static HRESULT WINAPI ddraw_surface4_IsLost(IDirectDrawSurface4 *iface)
3119 {
3120     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface4(iface);
3121     TRACE("iface %p.\n", iface);
3122
3123     return ddraw_surface7_IsLost(&This->IDirectDrawSurface7_iface);
3124 }
3125
3126 static HRESULT WINAPI ddraw_surface3_IsLost(IDirectDrawSurface3 *iface)
3127 {
3128     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface3(iface);
3129     TRACE("iface %p.\n", iface);
3130
3131     return ddraw_surface7_IsLost(&This->IDirectDrawSurface7_iface);
3132 }
3133
3134 static HRESULT WINAPI ddraw_surface2_IsLost(IDirectDrawSurface2 *iface)
3135 {
3136     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface2(iface);
3137     TRACE("iface %p.\n", iface);
3138
3139     return ddraw_surface7_IsLost(&This->IDirectDrawSurface7_iface);
3140 }
3141
3142 static HRESULT WINAPI ddraw_surface1_IsLost(IDirectDrawSurface *iface)
3143 {
3144     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface(iface);
3145     TRACE("iface %p.\n", iface);
3146
3147     return ddraw_surface7_IsLost(&This->IDirectDrawSurface7_iface);
3148 }
3149
3150 /*****************************************************************************
3151  * IDirectDrawSurface7::Restore
3152  *
3153  * Restores a lost surface. This makes the surface usable again, but
3154  * doesn't reload its old contents
3155  *
3156  * Returns:
3157  *  DD_OK on success
3158  *  See IWineD3DSurface::Restore for more details
3159  *
3160  *****************************************************************************/
3161 static HRESULT WINAPI ddraw_surface7_Restore(IDirectDrawSurface7 *iface)
3162 {
3163     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface7(iface);
3164     HRESULT hr;
3165
3166     TRACE("iface %p.\n", iface);
3167
3168     EnterCriticalSection(&ddraw_cs);
3169     hr = wined3d_surface_restore(This->wined3d_surface);
3170     LeaveCriticalSection(&ddraw_cs);
3171     return hr;
3172 }
3173
3174 static HRESULT WINAPI ddraw_surface4_Restore(IDirectDrawSurface4 *iface)
3175 {
3176     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface4(iface);
3177     TRACE("iface %p.\n", iface);
3178
3179     return ddraw_surface7_Restore(&This->IDirectDrawSurface7_iface);
3180 }
3181
3182 static HRESULT WINAPI ddraw_surface3_Restore(IDirectDrawSurface3 *iface)
3183 {
3184     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface3(iface);
3185     TRACE("iface %p.\n", iface);
3186
3187     return ddraw_surface7_Restore(&This->IDirectDrawSurface7_iface);
3188 }
3189
3190 static HRESULT WINAPI ddraw_surface2_Restore(IDirectDrawSurface2 *iface)
3191 {
3192     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface2(iface);
3193     TRACE("iface %p.\n", iface);
3194
3195     return ddraw_surface7_Restore(&This->IDirectDrawSurface7_iface);
3196 }
3197
3198 static HRESULT WINAPI ddraw_surface1_Restore(IDirectDrawSurface *iface)
3199 {
3200     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface(iface);
3201     TRACE("iface %p.\n", iface);
3202
3203     return ddraw_surface7_Restore(&This->IDirectDrawSurface7_iface);
3204 }
3205
3206 /*****************************************************************************
3207  * IDirectDrawSurface7::SetOverlayPosition
3208  *
3209  * Changes the display coordinates of an overlay surface
3210  *
3211  * Params:
3212  *  X:
3213  *  Y:
3214  *
3215  * Returns:
3216  *   DDERR_NOTAOVERLAYSURFACE, because we don't support overlays right now
3217  *****************************************************************************/
3218 static HRESULT WINAPI ddraw_surface7_SetOverlayPosition(IDirectDrawSurface7 *iface, LONG X, LONG Y)
3219 {
3220     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface7(iface);
3221     HRESULT hr;
3222
3223     TRACE("iface %p, x %d, y %d.\n", iface, X, Y);
3224
3225     EnterCriticalSection(&ddraw_cs);
3226     hr = wined3d_surface_set_overlay_position(This->wined3d_surface, X, Y);
3227     LeaveCriticalSection(&ddraw_cs);
3228     return hr;
3229 }
3230
3231 static HRESULT WINAPI ddraw_surface4_SetOverlayPosition(IDirectDrawSurface4 *iface, LONG x, LONG y)
3232 {
3233     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface4(iface);
3234     TRACE("iface %p, x %d, y %d.\n", iface, x, y);
3235
3236     return ddraw_surface7_SetOverlayPosition(&This->IDirectDrawSurface7_iface, x, y);
3237 }
3238
3239 static HRESULT WINAPI ddraw_surface3_SetOverlayPosition(IDirectDrawSurface3 *iface, LONG x, LONG y)
3240 {
3241     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface3(iface);
3242     TRACE("iface %p, x %d, y %d.\n", iface, x, y);
3243
3244     return ddraw_surface7_SetOverlayPosition(&This->IDirectDrawSurface7_iface, x, y);
3245 }
3246
3247 static HRESULT WINAPI ddraw_surface2_SetOverlayPosition(IDirectDrawSurface2 *iface, LONG x, LONG y)
3248 {
3249     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface2(iface);
3250     TRACE("iface %p, x %d, y %d.\n", iface, x, y);
3251
3252     return ddraw_surface7_SetOverlayPosition(&This->IDirectDrawSurface7_iface, x, y);
3253 }
3254
3255 static HRESULT WINAPI ddraw_surface1_SetOverlayPosition(IDirectDrawSurface *iface, LONG x, LONG y)
3256 {
3257     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface(iface);
3258     TRACE("iface %p, x %d, y %d.\n", iface, x, y);
3259
3260     return ddraw_surface7_SetOverlayPosition(&This->IDirectDrawSurface7_iface, x, y);
3261 }
3262
3263 /*****************************************************************************
3264  * IDirectDrawSurface7::UpdateOverlay
3265  *
3266  * Modifies the attributes of an overlay surface.
3267  *
3268  * Params:
3269  *  SrcRect: The section of the source being used for the overlay
3270  *  DstSurface: Address of the surface that is overlaid
3271  *  DstRect: Place of the overlay
3272  *  Flags: some DDOVER_* flags
3273  *
3274  * Returns:
3275  *  DDERR_UNSUPPORTED, because we don't support overlays
3276  *
3277  *****************************************************************************/
3278 static HRESULT WINAPI ddraw_surface7_UpdateOverlay(IDirectDrawSurface7 *iface, RECT *SrcRect,
3279         IDirectDrawSurface7 *DstSurface, RECT *DstRect, DWORD Flags, DDOVERLAYFX *FX)
3280 {
3281     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface7(iface);
3282     IDirectDrawSurfaceImpl *Dst = unsafe_impl_from_IDirectDrawSurface7(DstSurface);
3283     HRESULT hr;
3284
3285     TRACE("iface %p, src_rect %s, dst_surface %p, dst_rect %s, flags %#x, fx %p.\n",
3286             iface, wine_dbgstr_rect(SrcRect), DstSurface, wine_dbgstr_rect(DstRect), Flags, FX);
3287
3288     EnterCriticalSection(&ddraw_cs);
3289     hr = wined3d_surface_update_overlay(This->wined3d_surface, SrcRect,
3290             Dst ? Dst->wined3d_surface : NULL, DstRect, Flags, (WINEDDOVERLAYFX *)FX);
3291     LeaveCriticalSection(&ddraw_cs);
3292     switch(hr) {
3293         case WINED3DERR_INVALIDCALL:        return DDERR_INVALIDPARAMS;
3294         case WINEDDERR_NOTAOVERLAYSURFACE:  return DDERR_NOTAOVERLAYSURFACE;
3295         case WINEDDERR_OVERLAYNOTVISIBLE:   return DDERR_OVERLAYNOTVISIBLE;
3296         default:
3297             return hr;
3298     }
3299 }
3300
3301 static HRESULT WINAPI ddraw_surface4_UpdateOverlay(IDirectDrawSurface4 *iface, RECT *src_rect,
3302         IDirectDrawSurface4 *dst_surface, RECT *dst_rect, DWORD flags, DDOVERLAYFX *fx)
3303 {
3304     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface4(iface);
3305     IDirectDrawSurfaceImpl *dst_impl = unsafe_impl_from_IDirectDrawSurface4(dst_surface);
3306     TRACE("iface %p, src_rect %s, dst_surface %p, dst_rect %s, flags %#x, fx %p.\n",
3307             iface, wine_dbgstr_rect(src_rect), dst_surface, wine_dbgstr_rect(dst_rect), flags, fx);
3308
3309     return ddraw_surface7_UpdateOverlay(&This->IDirectDrawSurface7_iface, src_rect,
3310             dst_impl ? &dst_impl->IDirectDrawSurface7_iface : NULL, dst_rect, flags, fx);
3311 }
3312
3313 static HRESULT WINAPI ddraw_surface3_UpdateOverlay(IDirectDrawSurface3 *iface, RECT *src_rect,
3314         IDirectDrawSurface3 *dst_surface, RECT *dst_rect, DWORD flags, DDOVERLAYFX *fx)
3315 {
3316     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface3(iface);
3317     IDirectDrawSurfaceImpl *dst_impl = unsafe_impl_from_IDirectDrawSurface3(dst_surface);
3318     TRACE("iface %p, src_rect %s, dst_surface %p, dst_rect %s, flags %#x, fx %p.\n",
3319             iface, wine_dbgstr_rect(src_rect), dst_surface, wine_dbgstr_rect(dst_rect), flags, fx);
3320
3321     return ddraw_surface7_UpdateOverlay(&This->IDirectDrawSurface7_iface, src_rect,
3322             dst_impl ? &dst_impl->IDirectDrawSurface7_iface : NULL, dst_rect, flags, fx);
3323 }
3324
3325 static HRESULT WINAPI ddraw_surface2_UpdateOverlay(IDirectDrawSurface2 *iface, RECT *src_rect,
3326         IDirectDrawSurface2 *dst_surface, RECT *dst_rect, DWORD flags, DDOVERLAYFX *fx)
3327 {
3328     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface2(iface);
3329     IDirectDrawSurfaceImpl *dst_impl = unsafe_impl_from_IDirectDrawSurface2(dst_surface);
3330     TRACE("iface %p, src_rect %s, dst_surface %p, dst_rect %s, flags %#x, fx %p.\n",
3331             iface, wine_dbgstr_rect(src_rect), dst_surface, wine_dbgstr_rect(dst_rect), flags, fx);
3332
3333     return ddraw_surface7_UpdateOverlay(&This->IDirectDrawSurface7_iface, src_rect,
3334             dst_impl ? &dst_impl->IDirectDrawSurface7_iface : NULL, dst_rect, flags, fx);
3335 }
3336
3337 static HRESULT WINAPI ddraw_surface1_UpdateOverlay(IDirectDrawSurface *iface, RECT *src_rect,
3338         IDirectDrawSurface *dst_surface, RECT *dst_rect, DWORD flags, DDOVERLAYFX *fx)
3339 {
3340     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface(iface);
3341     IDirectDrawSurfaceImpl *dst_impl = unsafe_impl_from_IDirectDrawSurface(dst_surface);
3342     TRACE("iface %p, src_rect %s, dst_surface %p, dst_rect %s, flags %#x, fx %p.\n",
3343             iface, wine_dbgstr_rect(src_rect), dst_surface, wine_dbgstr_rect(dst_rect), flags, fx);
3344
3345     return ddraw_surface7_UpdateOverlay(&This->IDirectDrawSurface7_iface, src_rect,
3346             dst_impl ? &dst_impl->IDirectDrawSurface7_iface : NULL, dst_rect, flags, fx);
3347 }
3348
3349 /*****************************************************************************
3350  * IDirectDrawSurface7::UpdateOverlayDisplay
3351  *
3352  * The DX7 sdk says that it's not implemented
3353  *
3354  * Params:
3355  *  Flags: ?
3356  *
3357  * Returns: DDERR_UNSUPPORTED, because we don't support overlays
3358  *
3359  *****************************************************************************/
3360 static HRESULT WINAPI ddraw_surface7_UpdateOverlayDisplay(IDirectDrawSurface7 *iface, DWORD Flags)
3361 {
3362     TRACE("iface %p, flags %#x.\n", iface, Flags);
3363
3364     return DDERR_UNSUPPORTED;
3365 }
3366
3367 static HRESULT WINAPI ddraw_surface4_UpdateOverlayDisplay(IDirectDrawSurface4 *iface, DWORD flags)
3368 {
3369     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface4(iface);
3370     TRACE("iface %p, flags %#x.\n", iface, flags);
3371
3372     return ddraw_surface7_UpdateOverlayDisplay(&This->IDirectDrawSurface7_iface, flags);
3373 }
3374
3375 static HRESULT WINAPI ddraw_surface3_UpdateOverlayDisplay(IDirectDrawSurface3 *iface, DWORD flags)
3376 {
3377     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface3(iface);
3378     TRACE("iface %p, flags %#x.\n", iface, flags);
3379
3380     return ddraw_surface7_UpdateOverlayDisplay(&This->IDirectDrawSurface7_iface, flags);
3381 }
3382
3383 static HRESULT WINAPI ddraw_surface2_UpdateOverlayDisplay(IDirectDrawSurface2 *iface, DWORD flags)
3384 {
3385     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface2(iface);
3386     TRACE("iface %p, flags %#x.\n", iface, flags);
3387
3388     return ddraw_surface7_UpdateOverlayDisplay(&This->IDirectDrawSurface7_iface, flags);
3389 }
3390
3391 static HRESULT WINAPI ddraw_surface1_UpdateOverlayDisplay(IDirectDrawSurface *iface, DWORD flags)
3392 {
3393     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface(iface);
3394     TRACE("iface %p, flags %#x.\n", iface, flags);
3395
3396     return ddraw_surface7_UpdateOverlayDisplay(&This->IDirectDrawSurface7_iface, flags);
3397 }
3398
3399 /*****************************************************************************
3400  * IDirectDrawSurface7::UpdateOverlayZOrder
3401  *
3402  * Sets an overlay's Z order
3403  *
3404  * Params:
3405  *  Flags: DDOVERZ_* flags
3406  *  DDSRef: Defines the relative position in the overlay chain
3407  *
3408  * Returns:
3409  *  DDERR_NOTOVERLAYSURFACE, because we don't support overlays
3410  *
3411  *****************************************************************************/
3412 static HRESULT WINAPI ddraw_surface7_UpdateOverlayZOrder(IDirectDrawSurface7 *iface,
3413         DWORD Flags, IDirectDrawSurface7 *DDSRef)
3414 {
3415     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface7(iface);
3416     IDirectDrawSurfaceImpl *Ref = unsafe_impl_from_IDirectDrawSurface7(DDSRef);
3417     HRESULT hr;
3418
3419     TRACE("iface %p, flags %#x, reference %p.\n", iface, Flags, DDSRef);
3420
3421     EnterCriticalSection(&ddraw_cs);
3422     hr = wined3d_surface_update_overlay_z_order(This->wined3d_surface,
3423             Flags, Ref ? Ref->wined3d_surface : NULL);
3424     LeaveCriticalSection(&ddraw_cs);
3425     return hr;
3426 }
3427
3428 static HRESULT WINAPI ddraw_surface4_UpdateOverlayZOrder(IDirectDrawSurface4 *iface,
3429         DWORD flags, IDirectDrawSurface4 *reference)
3430 {
3431     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface4(iface);
3432     IDirectDrawSurfaceImpl *reference_impl = unsafe_impl_from_IDirectDrawSurface4(reference);
3433     TRACE("iface %p, flags %#x, reference %p.\n", iface, flags, reference);
3434
3435     return ddraw_surface7_UpdateOverlayZOrder(&This->IDirectDrawSurface7_iface, flags,
3436             reference_impl ? &reference_impl->IDirectDrawSurface7_iface : NULL);
3437 }
3438
3439 static HRESULT WINAPI ddraw_surface3_UpdateOverlayZOrder(IDirectDrawSurface3 *iface,
3440         DWORD flags, IDirectDrawSurface3 *reference)
3441 {
3442     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface3(iface);
3443     IDirectDrawSurfaceImpl *reference_impl = unsafe_impl_from_IDirectDrawSurface3(reference);
3444     TRACE("iface %p, flags %#x, reference %p.\n", iface, flags, reference);
3445
3446     return ddraw_surface7_UpdateOverlayZOrder(&This->IDirectDrawSurface7_iface, flags,
3447             reference_impl ? &reference_impl->IDirectDrawSurface7_iface : NULL);
3448 }
3449
3450 static HRESULT WINAPI ddraw_surface2_UpdateOverlayZOrder(IDirectDrawSurface2 *iface,
3451         DWORD flags, IDirectDrawSurface2 *reference)
3452 {
3453     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface2(iface);
3454     IDirectDrawSurfaceImpl *reference_impl = unsafe_impl_from_IDirectDrawSurface2(reference);
3455     TRACE("iface %p, flags %#x, reference %p.\n", iface, flags, reference);
3456
3457     return ddraw_surface7_UpdateOverlayZOrder(&This->IDirectDrawSurface7_iface, flags,
3458             reference_impl ? &reference_impl->IDirectDrawSurface7_iface : NULL);
3459 }
3460
3461 static HRESULT WINAPI ddraw_surface1_UpdateOverlayZOrder(IDirectDrawSurface *iface,
3462         DWORD flags, IDirectDrawSurface *reference)
3463 {
3464     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface(iface);
3465     IDirectDrawSurfaceImpl *reference_impl = unsafe_impl_from_IDirectDrawSurface(reference);
3466     TRACE("iface %p, flags %#x, reference %p.\n", iface, flags, reference);
3467
3468     return ddraw_surface7_UpdateOverlayZOrder(&This->IDirectDrawSurface7_iface, flags,
3469             reference_impl ? &reference_impl->IDirectDrawSurface7_iface : NULL);
3470 }
3471
3472 /*****************************************************************************
3473  * IDirectDrawSurface7::GetDDInterface
3474  *
3475  * Returns the IDirectDraw7 interface pointer of the DirectDraw object this
3476  * surface belongs to
3477  *
3478  * Params:
3479  *  DD: Address to write the interface pointer to
3480  *
3481  * Returns:
3482  *  DD_OK on success
3483  *  DDERR_INVALIDPARAMS if DD is NULL
3484  *
3485  *****************************************************************************/
3486 static HRESULT WINAPI ddraw_surface7_GetDDInterface(IDirectDrawSurface7 *iface, void **DD)
3487 {
3488     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface7(iface);
3489
3490     TRACE("iface %p, ddraw %p.\n", iface, DD);
3491
3492     if(!DD)
3493         return DDERR_INVALIDPARAMS;
3494
3495     switch(This->version)
3496     {
3497         case 7:
3498             *DD = &This->ddraw->IDirectDraw7_iface;
3499             break;
3500
3501         case 4:
3502             *DD = &This->ddraw->IDirectDraw4_iface;
3503             break;
3504
3505         case 2:
3506             *DD = &This->ddraw->IDirectDraw2_iface;
3507             break;
3508
3509         case 1:
3510             *DD = &This->ddraw->IDirectDraw_iface;
3511             break;
3512
3513     }
3514     IUnknown_AddRef((IUnknown *)*DD);
3515
3516     return DD_OK;
3517 }
3518
3519 static HRESULT WINAPI ddraw_surface4_GetDDInterface(IDirectDrawSurface4 *iface, void **ddraw)
3520 {
3521     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface4(iface);
3522     TRACE("iface %p, ddraw %p.\n", iface, ddraw);
3523
3524     return ddraw_surface7_GetDDInterface(&This->IDirectDrawSurface7_iface, ddraw);
3525 }
3526
3527 static HRESULT WINAPI ddraw_surface3_GetDDInterface(IDirectDrawSurface3 *iface, void **ddraw)
3528 {
3529     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface3(iface);
3530     TRACE("iface %p, ddraw %p.\n", iface, ddraw);
3531
3532     return ddraw_surface7_GetDDInterface(&This->IDirectDrawSurface7_iface, ddraw);
3533 }
3534
3535 static HRESULT WINAPI ddraw_surface2_GetDDInterface(IDirectDrawSurface2 *iface, void **ddraw)
3536 {
3537     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface2(iface);
3538     TRACE("iface %p, ddraw %p.\n", iface, ddraw);
3539
3540     return ddraw_surface7_GetDDInterface(&This->IDirectDrawSurface7_iface, ddraw);
3541 }
3542
3543 /* This seems also windows implementation specific - I don't think WineD3D needs this */
3544 static HRESULT WINAPI ddraw_surface7_ChangeUniquenessValue(IDirectDrawSurface7 *iface)
3545 {
3546     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface7(iface);
3547     volatile IDirectDrawSurfaceImpl* vThis = This;
3548
3549     TRACE("iface %p.\n", iface);
3550
3551     EnterCriticalSection(&ddraw_cs);
3552     /* A uniqueness value of 0 is apparently special.
3553      * This needs to be checked.
3554      * TODO: Write tests for this code and check if the volatile, interlocked stuff is really needed
3555      */
3556     while (1) {
3557         DWORD old_uniqueness_value = vThis->uniqueness_value;
3558         DWORD new_uniqueness_value = old_uniqueness_value+1;
3559
3560         if (old_uniqueness_value == 0) break;
3561         if (new_uniqueness_value == 0) new_uniqueness_value = 1;
3562
3563         if (InterlockedCompareExchange((LONG*)&vThis->uniqueness_value,
3564                                       old_uniqueness_value,
3565                                       new_uniqueness_value)
3566             == old_uniqueness_value)
3567             break;
3568     }
3569
3570     LeaveCriticalSection(&ddraw_cs);
3571     return DD_OK;
3572 }
3573
3574 static HRESULT WINAPI ddraw_surface4_ChangeUniquenessValue(IDirectDrawSurface4 *iface)
3575 {
3576     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface4(iface);
3577     TRACE("iface %p.\n", iface);
3578
3579     return ddraw_surface7_ChangeUniquenessValue(&This->IDirectDrawSurface7_iface);
3580 }
3581
3582 static HRESULT WINAPI ddraw_surface7_GetUniquenessValue(IDirectDrawSurface7 *iface, DWORD *pValue)
3583 {
3584     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface7(iface);
3585
3586     TRACE("iface %p, value %p.\n", iface, pValue);
3587
3588     EnterCriticalSection(&ddraw_cs);
3589     *pValue = This->uniqueness_value;
3590     LeaveCriticalSection(&ddraw_cs);
3591     return DD_OK;
3592 }
3593
3594 static HRESULT WINAPI ddraw_surface4_GetUniquenessValue(IDirectDrawSurface4 *iface, DWORD *pValue)
3595 {
3596     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface4(iface);
3597     TRACE("iface %p, value %p.\n", iface, pValue);
3598
3599     return ddraw_surface7_GetUniquenessValue(&This->IDirectDrawSurface7_iface, pValue);
3600 }
3601
3602 /*****************************************************************************
3603  * IDirectDrawSurface7::SetLOD
3604  *
3605  * Sets the level of detail of a texture
3606  *
3607  * Params:
3608  *  MaxLOD: LOD to set
3609  *
3610  * Returns:
3611  *  DD_OK on success
3612  *  DDERR_INVALIDOBJECT if the surface is invalid for this method
3613  *
3614  *****************************************************************************/
3615 static HRESULT WINAPI ddraw_surface7_SetLOD(IDirectDrawSurface7 *iface, DWORD MaxLOD)
3616 {
3617     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface7(iface);
3618     HRESULT hr;
3619
3620     TRACE("iface %p, lod %u.\n", iface, MaxLOD);
3621
3622     EnterCriticalSection(&ddraw_cs);
3623     if (!(This->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_TEXTUREMANAGE))
3624     {
3625         LeaveCriticalSection(&ddraw_cs);
3626         return DDERR_INVALIDOBJECT;
3627     }
3628
3629     if (!This->wined3d_texture)
3630     {
3631         ERR("(%p) The DirectDraw texture has no WineD3DTexture!\n", This);
3632         LeaveCriticalSection(&ddraw_cs);
3633         return DDERR_INVALIDOBJECT;
3634     }
3635
3636     hr = wined3d_texture_set_lod(This->wined3d_texture, MaxLOD);
3637     LeaveCriticalSection(&ddraw_cs);
3638     return hr;
3639 }
3640
3641 /*****************************************************************************
3642  * IDirectDrawSurface7::GetLOD
3643  *
3644  * Returns the level of detail of a Direct3D texture
3645  *
3646  * Params:
3647  *  MaxLOD: Address to write the LOD to
3648  *
3649  * Returns:
3650  *  DD_OK on success
3651  *  DDERR_INVALIDPARAMS if MaxLOD is NULL
3652  *  DDERR_INVALIDOBJECT if the surface is invalid for this method
3653  *
3654  *****************************************************************************/
3655 static HRESULT WINAPI ddraw_surface7_GetLOD(IDirectDrawSurface7 *iface, DWORD *MaxLOD)
3656 {
3657     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface7(iface);
3658
3659     TRACE("iface %p, lod %p.\n", iface, MaxLOD);
3660
3661     if(!MaxLOD)
3662         return DDERR_INVALIDPARAMS;
3663
3664     EnterCriticalSection(&ddraw_cs);
3665     if (!(This->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_TEXTUREMANAGE))
3666     {
3667         LeaveCriticalSection(&ddraw_cs);
3668         return DDERR_INVALIDOBJECT;
3669     }
3670
3671     *MaxLOD = wined3d_texture_get_lod(This->wined3d_texture);
3672     LeaveCriticalSection(&ddraw_cs);
3673     return DD_OK;
3674 }
3675
3676 /*****************************************************************************
3677  * IDirectDrawSurface7::BltFast
3678  *
3679  * Performs a fast Blit.
3680  *
3681  * Params:
3682  *  dstx: The x coordinate to blit to on the destination
3683  *  dsty: The y coordinate to blit to on the destination
3684  *  Source: The source surface
3685  *  rsrc: The source rectangle
3686  *  trans: Type of transfer. Some DDBLTFAST_* flags
3687  *
3688  * Returns:
3689  *  DD_OK on success
3690  *  For more details, see IWineD3DSurface::BltFast
3691  *
3692  *****************************************************************************/
3693 static HRESULT WINAPI ddraw_surface7_BltFast(IDirectDrawSurface7 *iface, DWORD dstx, DWORD dsty,
3694         IDirectDrawSurface7 *Source, RECT *rsrc, DWORD trans)
3695 {
3696     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface7(iface);
3697     IDirectDrawSurfaceImpl *src = unsafe_impl_from_IDirectDrawSurface7(Source);
3698     DWORD src_w, src_h, dst_w, dst_h;
3699     HRESULT hr = DD_OK;
3700
3701     TRACE("iface %p, dst_x %u, dst_y %u, src_surface %p, src_rect %s, flags %#x.\n",
3702             iface, dstx, dsty, Source, wine_dbgstr_rect(rsrc), trans);
3703
3704     dst_w = This->surface_desc.dwWidth;
3705     dst_h = This->surface_desc.dwHeight;
3706
3707     /* Source must be != NULL, This is not checked by windows. Windows happily throws a 0xc0000005
3708      * in that case
3709      */
3710     if(rsrc)
3711     {
3712         src_w = rsrc->right - rsrc->left;
3713         src_h = rsrc->bottom - rsrc->top;
3714     }
3715     else
3716     {
3717         src_w = src->surface_desc.dwWidth;
3718         src_h = src->surface_desc.dwHeight;
3719     }
3720
3721     if (src_w > dst_w || dstx > dst_w - src_w
3722             || src_h > dst_h || dsty > dst_h - src_h)
3723     {
3724         WARN("Destination area out of bounds, returning DDERR_INVALIDRECT.\n");
3725         return DDERR_INVALIDRECT;
3726     }
3727
3728     EnterCriticalSection(&ddraw_cs);
3729     if (src->surface_desc.ddsCaps.dwCaps & DDSCAPS_FRONTBUFFER)
3730         hr = ddraw_surface_update_frontbuffer(src, rsrc, TRUE);
3731     if (SUCCEEDED(hr))
3732         hr = wined3d_surface_bltfast(This->wined3d_surface, dstx, dsty,
3733                 src->wined3d_surface, rsrc, trans);
3734     if (SUCCEEDED(hr) && (This->surface_desc.ddsCaps.dwCaps & DDSCAPS_FRONTBUFFER))
3735     {
3736         RECT dst_rect = {dstx, dsty, dstx + src_w, dsty + src_h};
3737         hr = ddraw_surface_update_frontbuffer(This, &dst_rect, FALSE);
3738     }
3739     LeaveCriticalSection(&ddraw_cs);
3740     switch(hr)
3741     {
3742         case WINED3DERR_NOTAVAILABLE:           return DDERR_UNSUPPORTED;
3743         case WINED3DERR_WRONGTEXTUREFORMAT:     return DDERR_INVALIDPIXELFORMAT;
3744         default:                                return hr;
3745     }
3746 }
3747
3748 static HRESULT WINAPI ddraw_surface4_BltFast(IDirectDrawSurface4 *iface, DWORD dst_x, DWORD dst_y,
3749         IDirectDrawSurface4 *src_surface, RECT *src_rect, DWORD flags)
3750 {
3751     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface4(iface);
3752     IDirectDrawSurfaceImpl *src_impl = unsafe_impl_from_IDirectDrawSurface4(src_surface);
3753     TRACE("iface %p, dst_x %u, dst_y %u, src_surface %p, src_rect %s, flags %#x.\n",
3754             iface, dst_x, dst_y, src_surface, wine_dbgstr_rect(src_rect), flags);
3755
3756     return ddraw_surface7_BltFast(&This->IDirectDrawSurface7_iface, dst_x, dst_y,
3757             src_impl ? &src_impl->IDirectDrawSurface7_iface : NULL, src_rect, flags);
3758 }
3759
3760 static HRESULT WINAPI ddraw_surface3_BltFast(IDirectDrawSurface3 *iface, DWORD dst_x, DWORD dst_y,
3761         IDirectDrawSurface3 *src_surface, RECT *src_rect, DWORD flags)
3762 {
3763     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface3(iface);
3764     IDirectDrawSurfaceImpl *src_impl = unsafe_impl_from_IDirectDrawSurface3(src_surface);
3765     TRACE("iface %p, dst_x %u, dst_y %u, src_surface %p, src_rect %s, flags %#x.\n",
3766             iface, dst_x, dst_y, src_surface, wine_dbgstr_rect(src_rect), flags);
3767
3768     return ddraw_surface7_BltFast(&This->IDirectDrawSurface7_iface, dst_x, dst_y,
3769             src_impl ? &src_impl->IDirectDrawSurface7_iface : NULL, src_rect, flags);
3770 }
3771
3772 static HRESULT WINAPI ddraw_surface2_BltFast(IDirectDrawSurface2 *iface, DWORD dst_x, DWORD dst_y,
3773         IDirectDrawSurface2 *src_surface, RECT *src_rect, DWORD flags)
3774 {
3775     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface2(iface);
3776     IDirectDrawSurfaceImpl *src_impl = unsafe_impl_from_IDirectDrawSurface2(src_surface);
3777     TRACE("iface %p, dst_x %u, dst_y %u, src_surface %p, src_rect %s, flags %#x.\n",
3778             iface, dst_x, dst_y, src_surface, wine_dbgstr_rect(src_rect), flags);
3779
3780     return ddraw_surface7_BltFast(&This->IDirectDrawSurface7_iface, dst_x, dst_y,
3781             src_impl ? &src_impl->IDirectDrawSurface7_iface : NULL, src_rect, flags);
3782 }
3783
3784 static HRESULT WINAPI ddraw_surface1_BltFast(IDirectDrawSurface *iface, DWORD dst_x, DWORD dst_y,
3785         IDirectDrawSurface *src_surface, RECT *src_rect, DWORD flags)
3786 {
3787     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface(iface);
3788     IDirectDrawSurfaceImpl *src_impl = unsafe_impl_from_IDirectDrawSurface(src_surface);
3789     TRACE("iface %p, dst_x %u, dst_y %u, src_surface %p, src_rect %s, flags %#x.\n",
3790             iface, dst_x, dst_y, src_surface, wine_dbgstr_rect(src_rect), flags);
3791
3792     return ddraw_surface7_BltFast(&This->IDirectDrawSurface7_iface, dst_x, dst_y,
3793             src_impl ? &src_impl->IDirectDrawSurface7_iface : NULL, src_rect, flags);
3794 }
3795
3796 /*****************************************************************************
3797  * IDirectDrawSurface7::GetClipper
3798  *
3799  * Returns the IDirectDrawClipper interface of the clipper assigned to this
3800  * surface
3801  *
3802  * Params:
3803  *  Clipper: Address to store the interface pointer at
3804  *
3805  * Returns:
3806  *  DD_OK on success
3807  *  DDERR_INVALIDPARAMS if Clipper is NULL
3808  *  DDERR_NOCLIPPERATTACHED if there's no clipper attached
3809  *
3810  *****************************************************************************/
3811 static HRESULT WINAPI ddraw_surface7_GetClipper(IDirectDrawSurface7 *iface, IDirectDrawClipper **Clipper)
3812 {
3813     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface7(iface);
3814
3815     TRACE("iface %p, clipper %p.\n", iface, Clipper);
3816
3817     if(!Clipper)
3818     {
3819         LeaveCriticalSection(&ddraw_cs);
3820         return DDERR_INVALIDPARAMS;
3821     }
3822
3823     EnterCriticalSection(&ddraw_cs);
3824     if(This->clipper == NULL)
3825     {
3826         LeaveCriticalSection(&ddraw_cs);
3827         return DDERR_NOCLIPPERATTACHED;
3828     }
3829
3830     *Clipper = (IDirectDrawClipper *)This->clipper;
3831     IDirectDrawClipper_AddRef(*Clipper);
3832     LeaveCriticalSection(&ddraw_cs);
3833     return DD_OK;
3834 }
3835
3836 static HRESULT WINAPI ddraw_surface4_GetClipper(IDirectDrawSurface4 *iface, IDirectDrawClipper **clipper)
3837 {
3838     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface4(iface);
3839     TRACE("iface %p, clipper %p.\n", iface, clipper);
3840
3841     return ddraw_surface7_GetClipper(&This->IDirectDrawSurface7_iface, clipper);
3842 }
3843
3844 static HRESULT WINAPI ddraw_surface3_GetClipper(IDirectDrawSurface3 *iface, IDirectDrawClipper **clipper)
3845 {
3846     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface3(iface);
3847     TRACE("iface %p, clipper %p.\n", iface, clipper);
3848
3849     return ddraw_surface7_GetClipper(&This->IDirectDrawSurface7_iface, clipper);
3850 }
3851
3852 static HRESULT WINAPI ddraw_surface2_GetClipper(IDirectDrawSurface2 *iface, IDirectDrawClipper **clipper)
3853 {
3854     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface2(iface);
3855     TRACE("iface %p, clipper %p.\n", iface, clipper);
3856
3857     return ddraw_surface7_GetClipper(&This->IDirectDrawSurface7_iface, clipper);
3858 }
3859
3860 static HRESULT WINAPI ddraw_surface1_GetClipper(IDirectDrawSurface *iface, IDirectDrawClipper **clipper)
3861 {
3862     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface(iface);
3863     TRACE("iface %p, clipper %p.\n", iface, clipper);
3864
3865     return ddraw_surface7_GetClipper(&This->IDirectDrawSurface7_iface, clipper);
3866 }
3867
3868 /*****************************************************************************
3869  * IDirectDrawSurface7::SetClipper
3870  *
3871  * Sets a clipper for the surface
3872  *
3873  * Params:
3874  *  Clipper: IDirectDrawClipper interface of the clipper to set
3875  *
3876  * Returns:
3877  *  DD_OK on success
3878  *
3879  *****************************************************************************/
3880 static HRESULT WINAPI ddraw_surface7_SetClipper(IDirectDrawSurface7 *iface,
3881         IDirectDrawClipper *iclipper)
3882 {
3883     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface7(iface);
3884     IDirectDrawClipperImpl *clipper = unsafe_impl_from_IDirectDrawClipper(iclipper);
3885     IDirectDrawClipperImpl *oldClipper = This->clipper;
3886     HWND clipWindow;
3887     HRESULT hr;
3888
3889     TRACE("iface %p, clipper %p.\n", iface, iclipper);
3890
3891     EnterCriticalSection(&ddraw_cs);
3892     if (clipper == This->clipper)
3893     {
3894         LeaveCriticalSection(&ddraw_cs);
3895         return DD_OK;
3896     }
3897
3898     This->clipper = clipper;
3899
3900     if (clipper != NULL)
3901         IDirectDrawClipper_AddRef(iclipper);
3902     if(oldClipper)
3903         IDirectDrawClipper_Release(&oldClipper->IDirectDrawClipper_iface);
3904
3905     hr = wined3d_surface_set_clipper(This->wined3d_surface,
3906             This->clipper ? This->clipper->wineD3DClipper : NULL);
3907
3908     if ((This->surface_desc.ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE) && This->ddraw->wined3d_swapchain)
3909     {
3910         clipWindow = NULL;
3911         if(clipper) {
3912             IDirectDrawClipper_GetHWnd(iclipper, &clipWindow);
3913         }
3914
3915         if (clipWindow)
3916         {
3917             wined3d_swapchain_set_window(This->ddraw->wined3d_swapchain, clipWindow);
3918             This->ddraw->swapchain_window = clipWindow;
3919         }
3920         else
3921         {
3922             wined3d_swapchain_set_window(This->ddraw->wined3d_swapchain, This->ddraw->d3d_window);
3923             This->ddraw->swapchain_window = This->ddraw->dest_window;
3924         }
3925     }
3926
3927     LeaveCriticalSection(&ddraw_cs);
3928     return hr;
3929 }
3930
3931 static HRESULT WINAPI ddraw_surface4_SetClipper(IDirectDrawSurface4 *iface, IDirectDrawClipper *clipper)
3932 {
3933     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface4(iface);
3934     TRACE("iface %p, clipper %p.\n", iface, clipper);
3935
3936     return ddraw_surface7_SetClipper(&This->IDirectDrawSurface7_iface, clipper);
3937 }
3938
3939 static HRESULT WINAPI ddraw_surface3_SetClipper(IDirectDrawSurface3 *iface, IDirectDrawClipper *clipper)
3940 {
3941     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface3(iface);
3942     TRACE("iface %p, clipper %p.\n", iface, clipper);
3943
3944     return ddraw_surface7_SetClipper(&This->IDirectDrawSurface7_iface, clipper);
3945 }
3946
3947 static HRESULT WINAPI ddraw_surface2_SetClipper(IDirectDrawSurface2 *iface, IDirectDrawClipper *clipper)
3948 {
3949     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface2(iface);
3950     TRACE("iface %p, clipper %p.\n", iface, clipper);
3951
3952     return ddraw_surface7_SetClipper(&This->IDirectDrawSurface7_iface, clipper);
3953 }
3954
3955 static HRESULT WINAPI ddraw_surface1_SetClipper(IDirectDrawSurface *iface, IDirectDrawClipper *clipper)
3956 {
3957     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface(iface);
3958     TRACE("iface %p, clipper %p.\n", iface, clipper);
3959
3960     return ddraw_surface7_SetClipper(&This->IDirectDrawSurface7_iface, clipper);
3961 }
3962
3963 /*****************************************************************************
3964  * IDirectDrawSurface7::SetSurfaceDesc
3965  *
3966  * Sets the surface description. It can override the pixel format, the surface
3967  * memory, ...
3968  * It's not really tested.
3969  *
3970  * Params:
3971  * DDSD: Pointer to the new surface description to set
3972  * Flags: Some flags
3973  *
3974  * Returns:
3975  *  DD_OK on success
3976  *  DDERR_INVALIDPARAMS if DDSD is NULL
3977  *
3978  *****************************************************************************/
3979 static HRESULT WINAPI ddraw_surface7_SetSurfaceDesc(IDirectDrawSurface7 *iface, DDSURFACEDESC2 *DDSD, DWORD Flags)
3980 {
3981     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface7(iface);
3982     enum wined3d_format_id newFormat = WINED3DFMT_UNKNOWN;
3983     HRESULT hr;
3984
3985     TRACE("iface %p, surface_desc %p, flags %#x.\n", iface, DDSD, Flags);
3986
3987     if (!DDSD)
3988     {
3989         WARN("DDSD is NULL, returning DDERR_INVALIDPARAMS\n");
3990         return DDERR_INVALIDPARAMS;
3991     }
3992     if (Flags)
3993     {
3994         WARN("Flags is %x, returning DDERR_INVALIDPARAMS\n", Flags);
3995         return DDERR_INVALIDPARAMS;
3996     }
3997
3998     EnterCriticalSection(&ddraw_cs);
3999     if (DDSD->dwFlags & DDSD_PIXELFORMAT)
4000     {
4001         newFormat = PixelFormat_DD2WineD3D(&DDSD->u4.ddpfPixelFormat);
4002
4003         if(newFormat == WINED3DFMT_UNKNOWN)
4004         {
4005             ERR("Requested to set an unknown pixelformat\n");
4006             LeaveCriticalSection(&ddraw_cs);
4007             return DDERR_INVALIDPARAMS;
4008         }
4009         if(newFormat != PixelFormat_DD2WineD3D(&This->surface_desc.u4.ddpfPixelFormat) )
4010         {
4011             hr = wined3d_surface_set_format(This->wined3d_surface, newFormat);
4012             if (FAILED(hr))
4013             {
4014                 LeaveCriticalSection(&ddraw_cs);
4015                 return hr;
4016             }
4017         }
4018     }
4019     if (DDSD->dwFlags & DDSD_CKDESTOVERLAY)
4020     {
4021         wined3d_surface_set_color_key(This->wined3d_surface, DDCKEY_DESTOVERLAY,
4022                 (WINEDDCOLORKEY *)&DDSD->u3.ddckCKDestOverlay);
4023     }
4024     if (DDSD->dwFlags & DDSD_CKDESTBLT)
4025     {
4026         wined3d_surface_set_color_key(This->wined3d_surface, DDCKEY_DESTBLT,
4027                 (WINEDDCOLORKEY *)&DDSD->ddckCKDestBlt);
4028     }
4029     if (DDSD->dwFlags & DDSD_CKSRCOVERLAY)
4030     {
4031         wined3d_surface_set_color_key(This->wined3d_surface, DDCKEY_SRCOVERLAY,
4032                 (WINEDDCOLORKEY *)&DDSD->ddckCKSrcOverlay);
4033     }
4034     if (DDSD->dwFlags & DDSD_CKSRCBLT)
4035     {
4036         wined3d_surface_set_color_key(This->wined3d_surface, DDCKEY_SRCBLT,
4037                 (WINEDDCOLORKEY *)&DDSD->ddckCKSrcBlt);
4038     }
4039     if (DDSD->dwFlags & DDSD_LPSURFACE && DDSD->lpSurface)
4040     {
4041         hr = wined3d_surface_set_mem(This->wined3d_surface, DDSD->lpSurface);
4042         if (FAILED(hr))
4043         {
4044             /* No need for a trace here, wined3d does that for us */
4045             switch(hr)
4046             {
4047                 case WINED3DERR_INVALIDCALL:
4048                     LeaveCriticalSection(&ddraw_cs);
4049                     return DDERR_INVALIDPARAMS;
4050                 default:
4051                     break; /* Go on */
4052             }
4053         }
4054     }
4055
4056     This->surface_desc = *DDSD;
4057
4058     LeaveCriticalSection(&ddraw_cs);
4059     return DD_OK;
4060 }
4061
4062 static HRESULT WINAPI ddraw_surface4_SetSurfaceDesc(IDirectDrawSurface4 *iface,
4063         DDSURFACEDESC2 *surface_desc, DWORD flags)
4064 {
4065     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface4(iface);
4066     TRACE("iface %p, surface_desc %p, flags %#x.\n", iface, surface_desc, flags);
4067
4068     return ddraw_surface7_SetSurfaceDesc(&This->IDirectDrawSurface7_iface,
4069             surface_desc, flags);
4070 }
4071
4072 static HRESULT WINAPI ddraw_surface3_SetSurfaceDesc(IDirectDrawSurface3 *iface,
4073         DDSURFACEDESC *surface_desc, DWORD flags)
4074 {
4075     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface3(iface);
4076     DDSURFACEDESC2 surface_desc2;
4077     TRACE("iface %p, surface_desc %p, flags %#x.\n", iface, surface_desc, flags);
4078
4079     if (surface_desc) DDSD_to_DDSD2(surface_desc, &surface_desc2);
4080     return ddraw_surface7_SetSurfaceDesc(&This->IDirectDrawSurface7_iface,
4081             surface_desc ? &surface_desc2 : NULL, flags);
4082 }
4083
4084 /*****************************************************************************
4085  * IDirectDrawSurface7::GetPalette
4086  *
4087  * Returns the IDirectDrawPalette interface of the palette currently assigned
4088  * to the surface
4089  *
4090  * Params:
4091  *  Pal: Address to write the interface pointer to
4092  *
4093  * Returns:
4094  *  DD_OK on success
4095  *  DDERR_INVALIDPARAMS if Pal is NULL
4096  *
4097  *****************************************************************************/
4098 static HRESULT WINAPI ddraw_surface7_GetPalette(IDirectDrawSurface7 *iface, IDirectDrawPalette **Pal)
4099 {
4100     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface7(iface);
4101     struct wined3d_palette *wined3d_palette;
4102     HRESULT hr = DD_OK;
4103
4104     TRACE("iface %p, palette %p.\n", iface, Pal);
4105
4106     if(!Pal)
4107         return DDERR_INVALIDPARAMS;
4108
4109     EnterCriticalSection(&ddraw_cs);
4110     wined3d_palette = wined3d_surface_get_palette(This->wined3d_surface);
4111     if (wined3d_palette)
4112     {
4113         *Pal = wined3d_palette_get_parent(wined3d_palette);
4114         IDirectDrawPalette_AddRef(*Pal);
4115     }
4116     else
4117     {
4118         *Pal = NULL;
4119         hr = DDERR_NOPALETTEATTACHED;
4120     }
4121
4122     LeaveCriticalSection(&ddraw_cs);
4123     return hr;
4124 }
4125
4126 static HRESULT WINAPI ddraw_surface4_GetPalette(IDirectDrawSurface4 *iface, IDirectDrawPalette **palette)
4127 {
4128     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface4(iface);
4129     TRACE("iface %p, palette %p.\n", iface, palette);
4130
4131     return ddraw_surface7_GetPalette(&This->IDirectDrawSurface7_iface, palette);
4132 }
4133
4134 static HRESULT WINAPI ddraw_surface3_GetPalette(IDirectDrawSurface3 *iface, IDirectDrawPalette **palette)
4135 {
4136     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface3(iface);
4137     TRACE("iface %p, palette %p.\n", iface, palette);
4138
4139     return ddraw_surface7_GetPalette(&This->IDirectDrawSurface7_iface, palette);
4140 }
4141
4142 static HRESULT WINAPI ddraw_surface2_GetPalette(IDirectDrawSurface2 *iface, IDirectDrawPalette **palette)
4143 {
4144     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface2(iface);
4145     TRACE("iface %p, palette %p.\n", iface, palette);
4146
4147     return ddraw_surface7_GetPalette(&This->IDirectDrawSurface7_iface, palette);
4148 }
4149
4150 static HRESULT WINAPI ddraw_surface1_GetPalette(IDirectDrawSurface *iface, IDirectDrawPalette **palette)
4151 {
4152     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface(iface);
4153     TRACE("iface %p, palette %p.\n", iface, palette);
4154
4155     return ddraw_surface7_GetPalette(&This->IDirectDrawSurface7_iface, palette);
4156 }
4157
4158 /*****************************************************************************
4159  * SetColorKeyEnum
4160  *
4161  * EnumAttachedSurface callback for SetColorKey. Used to set color keys
4162  * recursively in the surface tree
4163  *
4164  *****************************************************************************/
4165 struct SCKContext
4166 {
4167     HRESULT ret;
4168     WINEDDCOLORKEY *CKey;
4169     DWORD Flags;
4170 };
4171
4172 static HRESULT WINAPI
4173 SetColorKeyEnum(IDirectDrawSurface7 *surface,
4174                 DDSURFACEDESC2 *desc,
4175                 void *context)
4176 {
4177     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface7(surface);
4178     struct SCKContext *ctx = context;
4179     HRESULT hr;
4180
4181     hr = wined3d_surface_set_color_key(This->wined3d_surface, ctx->Flags, ctx->CKey);
4182     if (FAILED(hr))
4183     {
4184         WARN("IWineD3DSurface_SetColorKey failed, hr = %08x\n", hr);
4185         ctx->ret = hr;
4186     }
4187
4188     ddraw_surface7_EnumAttachedSurfaces(surface, context, SetColorKeyEnum);
4189     ddraw_surface7_Release(surface);
4190
4191     return DDENUMRET_OK;
4192 }
4193
4194 /*****************************************************************************
4195  * IDirectDrawSurface7::SetColorKey
4196  *
4197  * Sets the color keying options for the surface. Observations showed that
4198  * in case of complex surfaces the color key has to be assigned to all
4199  * sublevels.
4200  *
4201  * Params:
4202  *  Flags: DDCKEY_*
4203  *  CKey: The new color key
4204  *
4205  * Returns:
4206  *  DD_OK on success
4207  *  See IWineD3DSurface::SetColorKey for details
4208  *
4209  *****************************************************************************/
4210 static HRESULT WINAPI ddraw_surface7_SetColorKey(IDirectDrawSurface7 *iface, DWORD Flags, DDCOLORKEY *CKey)
4211 {
4212     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface7(iface);
4213     DDCOLORKEY FixedCKey;
4214     struct SCKContext ctx = { DD_OK, (WINEDDCOLORKEY *) (CKey ? &FixedCKey : NULL), Flags };
4215
4216     TRACE("iface %p, flags %#x, color_key %p.\n", iface, Flags, CKey);
4217
4218     EnterCriticalSection(&ddraw_cs);
4219     if (CKey)
4220     {
4221         FixedCKey = *CKey;
4222         /* Handle case where dwColorSpaceHighValue < dwColorSpaceLowValue */
4223         if (FixedCKey.dwColorSpaceHighValue < FixedCKey.dwColorSpaceLowValue)
4224             FixedCKey.dwColorSpaceHighValue = FixedCKey.dwColorSpaceLowValue;
4225
4226         switch (Flags & ~DDCKEY_COLORSPACE)
4227         {
4228         case DDCKEY_DESTBLT:
4229             This->surface_desc.ddckCKDestBlt = FixedCKey;
4230             This->surface_desc.dwFlags |= DDSD_CKDESTBLT;
4231             break;
4232
4233         case DDCKEY_DESTOVERLAY:
4234             This->surface_desc.u3.ddckCKDestOverlay = FixedCKey;
4235             This->surface_desc.dwFlags |= DDSD_CKDESTOVERLAY;
4236             break;
4237
4238         case DDCKEY_SRCOVERLAY:
4239             This->surface_desc.ddckCKSrcOverlay = FixedCKey;
4240             This->surface_desc.dwFlags |= DDSD_CKSRCOVERLAY;
4241             break;
4242
4243         case DDCKEY_SRCBLT:
4244             This->surface_desc.ddckCKSrcBlt = FixedCKey;
4245             This->surface_desc.dwFlags |= DDSD_CKSRCBLT;
4246             break;
4247
4248         default:
4249             LeaveCriticalSection(&ddraw_cs);
4250             return DDERR_INVALIDPARAMS;
4251         }
4252     }
4253     else
4254     {
4255         switch (Flags & ~DDCKEY_COLORSPACE)
4256         {
4257         case DDCKEY_DESTBLT:
4258             This->surface_desc.dwFlags &= ~DDSD_CKDESTBLT;
4259             break;
4260
4261         case DDCKEY_DESTOVERLAY:
4262             This->surface_desc.dwFlags &= ~DDSD_CKDESTOVERLAY;
4263             break;
4264
4265         case DDCKEY_SRCOVERLAY:
4266             This->surface_desc.dwFlags &= ~DDSD_CKSRCOVERLAY;
4267             break;
4268
4269         case DDCKEY_SRCBLT:
4270             This->surface_desc.dwFlags &= ~DDSD_CKSRCBLT;
4271             break;
4272
4273         default:
4274             LeaveCriticalSection(&ddraw_cs);
4275             return DDERR_INVALIDPARAMS;
4276         }
4277     }
4278     ctx.ret = wined3d_surface_set_color_key(This->wined3d_surface, Flags, ctx.CKey);
4279     ddraw_surface7_EnumAttachedSurfaces(iface, &ctx, SetColorKeyEnum);
4280     LeaveCriticalSection(&ddraw_cs);
4281     switch(ctx.ret)
4282     {
4283         case WINED3DERR_INVALIDCALL:        return DDERR_INVALIDPARAMS;
4284         default:                            return ctx.ret;
4285     }
4286 }
4287
4288 static HRESULT WINAPI ddraw_surface4_SetColorKey(IDirectDrawSurface4 *iface, DWORD flags, DDCOLORKEY *color_key)
4289 {
4290     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface4(iface);
4291     TRACE("iface %p, flags %#x, color_key %p.\n", iface, flags, color_key);
4292
4293     return ddraw_surface7_SetColorKey(&This->IDirectDrawSurface7_iface, flags, color_key);
4294 }
4295
4296 static HRESULT WINAPI ddraw_surface3_SetColorKey(IDirectDrawSurface3 *iface, DWORD flags, DDCOLORKEY *color_key)
4297 {
4298     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface3(iface);
4299     TRACE("iface %p, flags %#x, color_key %p.\n", iface, flags, color_key);
4300
4301     return ddraw_surface7_SetColorKey(&This->IDirectDrawSurface7_iface, flags, color_key);
4302 }
4303
4304 static HRESULT WINAPI ddraw_surface2_SetColorKey(IDirectDrawSurface2 *iface, DWORD flags, DDCOLORKEY *color_key)
4305 {
4306     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface2(iface);
4307     TRACE("iface %p, flags %#x, color_key %p.\n", iface, flags, color_key);
4308
4309     return ddraw_surface7_SetColorKey(&This->IDirectDrawSurface7_iface, flags, color_key);
4310 }
4311
4312 static HRESULT WINAPI ddraw_surface1_SetColorKey(IDirectDrawSurface *iface, DWORD flags, DDCOLORKEY *color_key)
4313 {
4314     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface(iface);
4315     TRACE("iface %p, flags %#x, color_key %p.\n", iface, flags, color_key);
4316
4317     return ddraw_surface7_SetColorKey(&This->IDirectDrawSurface7_iface, flags, color_key);
4318 }
4319
4320 /*****************************************************************************
4321  * IDirectDrawSurface7::SetPalette
4322  *
4323  * Assigns a DirectDrawPalette object to the surface
4324  *
4325  * Params:
4326  *  Pal: Interface to the palette to set
4327  *
4328  * Returns:
4329  *  DD_OK on success
4330  *
4331  *****************************************************************************/
4332 static HRESULT WINAPI ddraw_surface7_SetPalette(IDirectDrawSurface7 *iface, IDirectDrawPalette *Pal)
4333 {
4334     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface7(iface);
4335     IDirectDrawPalette *oldPal;
4336     IDirectDrawSurfaceImpl *surf;
4337     IDirectDrawPaletteImpl *PalImpl = unsafe_impl_from_IDirectDrawPalette(Pal);
4338     HRESULT hr;
4339
4340     TRACE("iface %p, palette %p.\n", iface, Pal);
4341
4342     if (!(This->surface_desc.u4.ddpfPixelFormat.dwFlags & (DDPF_PALETTEINDEXED1 | DDPF_PALETTEINDEXED2 |
4343             DDPF_PALETTEINDEXED4 | DDPF_PALETTEINDEXED8 | DDPF_PALETTEINDEXEDTO8))) {
4344         return DDERR_INVALIDPIXELFORMAT;
4345     }
4346
4347     if (This->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_MIPMAPSUBLEVEL)
4348     {
4349         return DDERR_NOTONMIPMAPSUBLEVEL;
4350     }
4351
4352     /* Find the old palette */
4353     EnterCriticalSection(&ddraw_cs);
4354     hr = IDirectDrawSurface_GetPalette(iface, &oldPal);
4355     if(hr != DD_OK && hr != DDERR_NOPALETTEATTACHED)
4356     {
4357         LeaveCriticalSection(&ddraw_cs);
4358         return hr;
4359     }
4360     if(oldPal) IDirectDrawPalette_Release(oldPal);  /* For the GetPalette */
4361
4362     /* Set the new Palette */
4363     wined3d_surface_set_palette(This->wined3d_surface, PalImpl ? PalImpl->wineD3DPalette : NULL);
4364     /* AddRef the Palette */
4365     if(Pal) IDirectDrawPalette_AddRef(Pal);
4366
4367     /* Release the old palette */
4368     if(oldPal) IDirectDrawPalette_Release(oldPal);
4369
4370     /* Update the wined3d frontbuffer if this is the frontbuffer. */
4371     if ((This->surface_desc.ddsCaps.dwCaps & DDSCAPS_FRONTBUFFER) && This->ddraw->wined3d_frontbuffer)
4372     {
4373         hr = wined3d_surface_set_palette(This->ddraw->wined3d_frontbuffer, PalImpl ? PalImpl->wineD3DPalette : NULL);
4374         if (FAILED(hr))
4375             ERR("Failed to set frontbuffer palette, hr %#x.\n", hr);
4376     }
4377
4378     /* If this is a front buffer, also update the back buffers
4379      * TODO: How do things work for palettized cube textures?
4380      */
4381     if(This->surface_desc.ddsCaps.dwCaps & DDSCAPS_FRONTBUFFER)
4382     {
4383         /* For primary surfaces the tree is just a list, so the simpler scheme fits too */
4384         DDSCAPS2 caps2 = { DDSCAPS_PRIMARYSURFACE, 0, 0, 0 };
4385
4386         surf = This;
4387         while(1)
4388         {
4389             IDirectDrawSurface7 *attach;
4390             HRESULT hr;
4391             hr = ddraw_surface7_GetAttachedSurface(&surf->IDirectDrawSurface7_iface, &caps2, &attach);
4392             if(hr != DD_OK)
4393             {
4394                 break;
4395             }
4396
4397             TRACE("Setting palette on %p\n", attach);
4398             ddraw_surface7_SetPalette(attach, Pal);
4399             surf = impl_from_IDirectDrawSurface7(attach);
4400             ddraw_surface7_Release(attach);
4401         }
4402     }
4403
4404     LeaveCriticalSection(&ddraw_cs);
4405     return DD_OK;
4406 }
4407
4408 static HRESULT WINAPI ddraw_surface4_SetPalette(IDirectDrawSurface4 *iface, IDirectDrawPalette *palette)
4409 {
4410     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface4(iface);
4411     TRACE("iface %p, palette %p.\n", iface, palette);
4412
4413     return ddraw_surface7_SetPalette(&This->IDirectDrawSurface7_iface, palette);
4414 }
4415
4416 static HRESULT WINAPI ddraw_surface3_SetPalette(IDirectDrawSurface3 *iface, IDirectDrawPalette *palette)
4417 {
4418     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface3(iface);
4419     TRACE("iface %p, palette %p.\n", iface, palette);
4420
4421     return ddraw_surface7_SetPalette(&This->IDirectDrawSurface7_iface, palette);
4422 }
4423
4424 static HRESULT WINAPI ddraw_surface2_SetPalette(IDirectDrawSurface2 *iface, IDirectDrawPalette *palette)
4425 {
4426     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface2(iface);
4427     TRACE("iface %p, palette %p.\n", iface, palette);
4428
4429     return ddraw_surface7_SetPalette(&This->IDirectDrawSurface7_iface, palette);
4430 }
4431
4432 static HRESULT WINAPI ddraw_surface1_SetPalette(IDirectDrawSurface *iface, IDirectDrawPalette *palette)
4433 {
4434     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface(iface);
4435     TRACE("iface %p, palette %p.\n", iface, palette);
4436
4437     return ddraw_surface7_SetPalette(&This->IDirectDrawSurface7_iface, palette);
4438 }
4439
4440 /**********************************************************
4441  * IDirectDrawGammaControl::GetGammaRamp
4442  *
4443  * Returns the current gamma ramp for a surface
4444  *
4445  * Params:
4446  *  flags: Ignored
4447  *  gamma_ramp: Address to write the ramp to
4448  *
4449  * Returns:
4450  *  DD_OK on success
4451  *  DDERR_INVALIDPARAMS if gamma_ramp is NULL
4452  *
4453  **********************************************************/
4454 static HRESULT WINAPI ddraw_gamma_control_GetGammaRamp(IDirectDrawGammaControl *iface,
4455         DWORD flags, DDGAMMARAMP *gamma_ramp)
4456 {
4457     IDirectDrawSurfaceImpl *surface = impl_from_IDirectDrawGammaControl(iface);
4458
4459     TRACE("iface %p, flags %#x, gamma_ramp %p.\n", iface, flags, gamma_ramp);
4460
4461     if (!gamma_ramp)
4462     {
4463         WARN("Invalid gamma_ramp passed.\n");
4464         return DDERR_INVALIDPARAMS;
4465     }
4466
4467     EnterCriticalSection(&ddraw_cs);
4468     if (surface->surface_desc.ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE)
4469     {
4470         /* Note: DDGAMMARAMP is compatible with WINED3DGAMMARAMP. */
4471         wined3d_device_get_gamma_ramp(surface->ddraw->wined3d_device, 0, (WINED3DGAMMARAMP *)gamma_ramp);
4472     }
4473     else
4474     {
4475         ERR("Not implemented for non-primary surfaces.\n");
4476     }
4477     LeaveCriticalSection(&ddraw_cs);
4478
4479     return DD_OK;
4480 }
4481
4482 /**********************************************************
4483  * IDirectDrawGammaControl::SetGammaRamp
4484  *
4485  * Sets the red, green and blue gamma ramps for
4486  *
4487  * Params:
4488  *  flags: Can be DDSGR_CALIBRATE to request calibration
4489  *  gamma_ramp: Structure containing the new gamma ramp
4490  *
4491  * Returns:
4492  *  DD_OK on success
4493  *  DDERR_INVALIDPARAMS if gamma_ramp is NULL
4494  *
4495  **********************************************************/
4496 static HRESULT WINAPI ddraw_gamma_control_SetGammaRamp(IDirectDrawGammaControl *iface,
4497         DWORD flags, DDGAMMARAMP *gamma_ramp)
4498 {
4499     IDirectDrawSurfaceImpl *surface = impl_from_IDirectDrawGammaControl(iface);
4500
4501     TRACE("iface %p, flags %#x, gamma_ramp %p.\n", iface, flags, gamma_ramp);
4502
4503     if (!gamma_ramp)
4504     {
4505         WARN("Invalid gamma_ramp passed.\n");
4506         return DDERR_INVALIDPARAMS;
4507     }
4508
4509     EnterCriticalSection(&ddraw_cs);
4510     if (surface->surface_desc.ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE)
4511     {
4512         /* Note: DDGAMMARAMP is compatible with WINED3DGAMMARAMP */
4513         wined3d_device_set_gamma_ramp(surface->ddraw->wined3d_device, 0, flags, (WINED3DGAMMARAMP *)gamma_ramp);
4514     }
4515     else
4516     {
4517         ERR("Not implemented for non-primary surfaces.\n");
4518     }
4519     LeaveCriticalSection(&ddraw_cs);
4520
4521     return DD_OK;
4522 }
4523
4524 /*****************************************************************************
4525  * IDirect3DTexture2::PaletteChanged
4526  *
4527  * Informs the texture about a palette change
4528  *
4529  * Params:
4530  *  start: Start index of the change
4531  *  count: The number of changed entries
4532  *
4533  * Returns
4534  *  D3D_OK, because it's a stub
4535  *
4536  *****************************************************************************/
4537 static HRESULT WINAPI d3d_texture2_PaletteChanged(IDirect3DTexture2 *iface, DWORD start, DWORD count)
4538 {
4539     FIXME("iface %p, start %u, count %u stub!\n", iface, start, count);
4540
4541     return D3D_OK;
4542 }
4543
4544 static HRESULT WINAPI d3d_texture1_PaletteChanged(IDirect3DTexture *iface, DWORD start, DWORD count)
4545 {
4546     IDirectDrawSurfaceImpl *surface = impl_from_IDirect3DTexture(iface);
4547
4548     TRACE("iface %p, start %u, count %u.\n", iface, start, count);
4549
4550     return d3d_texture2_PaletteChanged(&surface->IDirect3DTexture2_iface, start, count);
4551 }
4552
4553 /*****************************************************************************
4554  * IDirect3DTexture::Unload
4555  *
4556  * DX5 SDK: "The IDirect3DTexture2::Unload method is not implemented
4557  *
4558  *
4559  * Returns:
4560  *  DDERR_UNSUPPORTED
4561  *
4562  *****************************************************************************/
4563 static HRESULT WINAPI d3d_texture1_Unload(IDirect3DTexture *iface)
4564 {
4565     WARN("iface %p. Not implemented.\n", iface);
4566
4567     return DDERR_UNSUPPORTED;
4568 }
4569
4570 /*****************************************************************************
4571  * IDirect3DTexture2::GetHandle
4572  *
4573  * Returns handle for the texture. At the moment, the interface
4574  * to the IWineD3DTexture is used.
4575  *
4576  * Params:
4577  *  device: Device this handle is assigned to
4578  *  handle: Address to store the handle at.
4579  *
4580  * Returns:
4581  *  D3D_OK
4582  *
4583  *****************************************************************************/
4584 static HRESULT WINAPI d3d_texture2_GetHandle(IDirect3DTexture2 *iface,
4585         IDirect3DDevice2 *device, D3DTEXTUREHANDLE *handle)
4586 {
4587     IDirectDrawSurfaceImpl *surface = impl_from_IDirect3DTexture2(iface);
4588     IDirect3DDeviceImpl *device_impl = unsafe_impl_from_IDirect3DDevice2(device);
4589
4590     TRACE("iface %p, device %p, handle %p.\n", iface, device, handle);
4591
4592     EnterCriticalSection(&ddraw_cs);
4593
4594     if (!surface->Handle)
4595     {
4596         DWORD h = ddraw_allocate_handle(&device_impl->handle_table, surface, DDRAW_HANDLE_SURFACE);
4597         if (h == DDRAW_INVALID_HANDLE)
4598         {
4599             ERR("Failed to allocate a texture handle.\n");
4600             LeaveCriticalSection(&ddraw_cs);
4601             return DDERR_OUTOFMEMORY;
4602         }
4603
4604         surface->Handle = h + 1;
4605     }
4606
4607     TRACE("Returning handle %08x.\n", surface->Handle);
4608     *handle = surface->Handle;
4609
4610     LeaveCriticalSection(&ddraw_cs);
4611
4612     return D3D_OK;
4613 }
4614
4615 static HRESULT WINAPI d3d_texture1_GetHandle(IDirect3DTexture *iface,
4616         IDirect3DDevice *device, D3DTEXTUREHANDLE *handle)
4617 {
4618     IDirectDrawSurfaceImpl *This = impl_from_IDirect3DTexture(iface);
4619     IDirect3DDeviceImpl *device_impl = unsafe_impl_from_IDirect3DDevice(device);
4620
4621     TRACE("iface %p, device %p, handle %p.\n", iface, device, handle);
4622
4623     return d3d_texture2_GetHandle(&This->IDirect3DTexture2_iface,
4624             device_impl ? &device_impl->IDirect3DDevice2_iface : NULL, handle);
4625 }
4626
4627 /*****************************************************************************
4628  * get_sub_mimaplevel
4629  *
4630  * Helper function that returns the next mipmap level
4631  *
4632  * tex_ptr: Surface of which to return the next level
4633  *
4634  *****************************************************************************/
4635 static IDirectDrawSurfaceImpl *get_sub_mimaplevel(IDirectDrawSurfaceImpl *surface)
4636 {
4637     /* Now go down the mipmap chain to the next surface */
4638     static DDSCAPS2 mipmap_caps = { DDSCAPS_MIPMAP | DDSCAPS_TEXTURE, 0, 0, 0 };
4639     IDirectDrawSurface7 *next_level;
4640     HRESULT hr;
4641
4642     hr = ddraw_surface7_GetAttachedSurface(&surface->IDirectDrawSurface7_iface, &mipmap_caps, &next_level);
4643     if (FAILED(hr)) return NULL;
4644
4645     ddraw_surface7_Release(next_level);
4646
4647     return impl_from_IDirectDrawSurface7(next_level);
4648 }
4649
4650 /*****************************************************************************
4651  * IDirect3DTexture2::Load
4652  *
4653  * Loads a texture created with the DDSCAPS_ALLOCONLOAD
4654  *
4655  * This function isn't relayed to WineD3D because the whole interface is
4656  * implemented in DDraw only. For speed improvements a implementation which
4657  * takes OpenGL more into account could be placed into WineD3D.
4658  *
4659  * Params:
4660  *  src_texture: Address of the texture to load
4661  *
4662  * Returns:
4663  *  D3D_OK on success
4664  *  D3DERR_TEXTURE_LOAD_FAILED.
4665  *
4666  *****************************************************************************/
4667 static HRESULT WINAPI d3d_texture2_Load(IDirect3DTexture2 *iface, IDirect3DTexture2 *src_texture)
4668 {
4669     IDirectDrawSurfaceImpl *dst_surface = impl_from_IDirect3DTexture2(iface);
4670     IDirectDrawSurfaceImpl *src_surface = unsafe_impl_from_IDirect3DTexture2(src_texture);
4671     HRESULT hr;
4672
4673     TRACE("iface %p, src_texture %p.\n", iface, src_texture);
4674
4675     if (src_surface == dst_surface)
4676     {
4677         TRACE("copying surface %p to surface %p, why?\n", src_surface, dst_surface);
4678         return D3D_OK;
4679     }
4680
4681     EnterCriticalSection(&ddraw_cs);
4682
4683     if (((src_surface->surface_desc.ddsCaps.dwCaps & DDSCAPS_MIPMAP)
4684             != (dst_surface->surface_desc.ddsCaps.dwCaps & DDSCAPS_MIPMAP))
4685             || (src_surface->surface_desc.u2.dwMipMapCount != dst_surface->surface_desc.u2.dwMipMapCount))
4686     {
4687         ERR("Trying to load surfaces with different mip-map counts.\n");
4688     }
4689
4690     for (;;)
4691     {
4692         struct wined3d_palette *wined3d_dst_pal, *wined3d_src_pal;
4693         IDirectDrawPalette *dst_pal = NULL, *src_pal = NULL;
4694         DDSURFACEDESC *src_desc, *dst_desc;
4695
4696         TRACE("Copying surface %p to surface %p (mipmap level %d).\n",
4697                 src_surface, dst_surface, src_surface->mipmap_level);
4698
4699         /* Suppress the ALLOCONLOAD flag */
4700         dst_surface->surface_desc.ddsCaps.dwCaps &= ~DDSCAPS_ALLOCONLOAD;
4701
4702         /* Get the palettes */
4703         wined3d_dst_pal = wined3d_surface_get_palette(dst_surface->wined3d_surface);
4704         if (wined3d_dst_pal)
4705             dst_pal = wined3d_palette_get_parent(wined3d_dst_pal);
4706
4707         wined3d_src_pal = wined3d_surface_get_palette(src_surface->wined3d_surface);
4708         if (wined3d_src_pal)
4709             src_pal = wined3d_palette_get_parent(wined3d_src_pal);
4710
4711         if (src_pal)
4712         {
4713             PALETTEENTRY palent[256];
4714
4715             if (!dst_pal)
4716             {
4717                 LeaveCriticalSection(&ddraw_cs);
4718                 return DDERR_NOPALETTEATTACHED;
4719             }
4720             IDirectDrawPalette_GetEntries(src_pal, 0, 0, 256, palent);
4721             IDirectDrawPalette_SetEntries(dst_pal, 0, 0, 256, palent);
4722         }
4723
4724         /* Copy one surface on the other */
4725         dst_desc = (DDSURFACEDESC *)&(dst_surface->surface_desc);
4726         src_desc = (DDSURFACEDESC *)&(src_surface->surface_desc);
4727
4728         if ((src_desc->dwWidth != dst_desc->dwWidth) || (src_desc->dwHeight != dst_desc->dwHeight))
4729         {
4730             /* Should also check for same pixel format, u1.lPitch, ... */
4731             ERR("Error in surface sizes.\n");
4732             LeaveCriticalSection(&ddraw_cs);
4733             return D3DERR_TEXTURE_LOAD_FAILED;
4734         }
4735         else
4736         {
4737             WINED3DLOCKED_RECT src_rect, dst_rect;
4738
4739             /* Copy also the ColorKeying stuff */
4740             if (src_desc->dwFlags & DDSD_CKSRCBLT)
4741             {
4742                 dst_desc->dwFlags |= DDSD_CKSRCBLT;
4743                 dst_desc->ddckCKSrcBlt.dwColorSpaceLowValue = src_desc->ddckCKSrcBlt.dwColorSpaceLowValue;
4744                 dst_desc->ddckCKSrcBlt.dwColorSpaceHighValue = src_desc->ddckCKSrcBlt.dwColorSpaceHighValue;
4745             }
4746
4747             /* Copy the main memory texture into the surface that corresponds
4748              * to the OpenGL texture object. */
4749
4750             hr = wined3d_surface_map(src_surface->wined3d_surface, &src_rect, NULL, 0);
4751             if (FAILED(hr))
4752             {
4753                 ERR("Failed to lock source surface, hr %#x.\n", hr);
4754                 LeaveCriticalSection(&ddraw_cs);
4755                 return D3DERR_TEXTURE_LOAD_FAILED;
4756             }
4757
4758             hr = wined3d_surface_map(dst_surface->wined3d_surface, &dst_rect, NULL, 0);
4759             if (FAILED(hr))
4760             {
4761                 ERR("Failed to lock destination surface, hr %#x.\n", hr);
4762                 wined3d_surface_unmap(src_surface->wined3d_surface);
4763                 LeaveCriticalSection(&ddraw_cs);
4764                 return D3DERR_TEXTURE_LOAD_FAILED;
4765             }
4766
4767             if (dst_surface->surface_desc.u4.ddpfPixelFormat.dwFlags & DDPF_FOURCC)
4768                 memcpy(dst_rect.pBits, src_rect.pBits, src_surface->surface_desc.u1.dwLinearSize);
4769             else
4770                 memcpy(dst_rect.pBits, src_rect.pBits, src_rect.Pitch * src_desc->dwHeight);
4771
4772             wined3d_surface_unmap(src_surface->wined3d_surface);
4773             wined3d_surface_unmap(dst_surface->wined3d_surface);
4774         }
4775
4776         if (src_surface->surface_desc.ddsCaps.dwCaps & DDSCAPS_MIPMAP)
4777             src_surface = get_sub_mimaplevel(src_surface);
4778         else
4779             src_surface = NULL;
4780
4781         if (dst_surface->surface_desc.ddsCaps.dwCaps & DDSCAPS_MIPMAP)
4782             dst_surface = get_sub_mimaplevel(dst_surface);
4783         else
4784             dst_surface = NULL;
4785
4786         if (!src_surface || !dst_surface)
4787         {
4788             if (src_surface != dst_surface)
4789                 ERR("Loading surface with different mipmap structure.\n");
4790             break;
4791         }
4792     }
4793
4794     LeaveCriticalSection(&ddraw_cs);
4795
4796     return hr;
4797 }
4798
4799 static HRESULT WINAPI d3d_texture1_Load(IDirect3DTexture *iface, IDirect3DTexture *src_texture)
4800 {
4801     IDirectDrawSurfaceImpl* This = impl_from_IDirect3DTexture(iface);
4802     IDirectDrawSurfaceImpl* src_surface = unsafe_impl_from_IDirect3DTexture(src_texture);
4803     TRACE("iface %p, src_texture %p.\n", iface, src_texture);
4804
4805     return d3d_texture2_Load(&This->IDirect3DTexture2_iface,
4806             src_surface ? &src_surface->IDirect3DTexture2_iface : NULL);
4807 }
4808
4809 /*****************************************************************************
4810  * The VTable
4811  *****************************************************************************/
4812
4813 static const struct IDirectDrawSurface7Vtbl ddraw_surface7_vtbl =
4814 {
4815     /* IUnknown */
4816     ddraw_surface7_QueryInterface,
4817     ddraw_surface7_AddRef,
4818     ddraw_surface7_Release,
4819     /* IDirectDrawSurface */
4820     ddraw_surface7_AddAttachedSurface,
4821     ddraw_surface7_AddOverlayDirtyRect,
4822     ddraw_surface7_Blt,
4823     ddraw_surface7_BltBatch,
4824     ddraw_surface7_BltFast,
4825     ddraw_surface7_DeleteAttachedSurface,
4826     ddraw_surface7_EnumAttachedSurfaces,
4827     ddraw_surface7_EnumOverlayZOrders,
4828     ddraw_surface7_Flip,
4829     ddraw_surface7_GetAttachedSurface,
4830     ddraw_surface7_GetBltStatus,
4831     ddraw_surface7_GetCaps,
4832     ddraw_surface7_GetClipper,
4833     ddraw_surface7_GetColorKey,
4834     ddraw_surface7_GetDC,
4835     ddraw_surface7_GetFlipStatus,
4836     ddraw_surface7_GetOverlayPosition,
4837     ddraw_surface7_GetPalette,
4838     ddraw_surface7_GetPixelFormat,
4839     ddraw_surface7_GetSurfaceDesc,
4840     ddraw_surface7_Initialize,
4841     ddraw_surface7_IsLost,
4842     ddraw_surface7_Lock,
4843     ddraw_surface7_ReleaseDC,
4844     ddraw_surface7_Restore,
4845     ddraw_surface7_SetClipper,
4846     ddraw_surface7_SetColorKey,
4847     ddraw_surface7_SetOverlayPosition,
4848     ddraw_surface7_SetPalette,
4849     ddraw_surface7_Unlock,
4850     ddraw_surface7_UpdateOverlay,
4851     ddraw_surface7_UpdateOverlayDisplay,
4852     ddraw_surface7_UpdateOverlayZOrder,
4853     /* IDirectDrawSurface2 */
4854     ddraw_surface7_GetDDInterface,
4855     ddraw_surface7_PageLock,
4856     ddraw_surface7_PageUnlock,
4857     /* IDirectDrawSurface3 */
4858     ddraw_surface7_SetSurfaceDesc,
4859     /* IDirectDrawSurface4 */
4860     ddraw_surface7_SetPrivateData,
4861     ddraw_surface7_GetPrivateData,
4862     ddraw_surface7_FreePrivateData,
4863     ddraw_surface7_GetUniquenessValue,
4864     ddraw_surface7_ChangeUniquenessValue,
4865     /* IDirectDrawSurface7 */
4866     ddraw_surface7_SetPriority,
4867     ddraw_surface7_GetPriority,
4868     ddraw_surface7_SetLOD,
4869     ddraw_surface7_GetLOD,
4870 };
4871
4872 static const struct IDirectDrawSurface4Vtbl ddraw_surface4_vtbl =
4873 {
4874     /* IUnknown */
4875     ddraw_surface4_QueryInterface,
4876     ddraw_surface4_AddRef,
4877     ddraw_surface4_Release,
4878     /* IDirectDrawSurface */
4879     ddraw_surface4_AddAttachedSurface,
4880     ddraw_surface4_AddOverlayDirtyRect,
4881     ddraw_surface4_Blt,
4882     ddraw_surface4_BltBatch,
4883     ddraw_surface4_BltFast,
4884     ddraw_surface4_DeleteAttachedSurface,
4885     ddraw_surface4_EnumAttachedSurfaces,
4886     ddraw_surface4_EnumOverlayZOrders,
4887     ddraw_surface4_Flip,
4888     ddraw_surface4_GetAttachedSurface,
4889     ddraw_surface4_GetBltStatus,
4890     ddraw_surface4_GetCaps,
4891     ddraw_surface4_GetClipper,
4892     ddraw_surface4_GetColorKey,
4893     ddraw_surface4_GetDC,
4894     ddraw_surface4_GetFlipStatus,
4895     ddraw_surface4_GetOverlayPosition,
4896     ddraw_surface4_GetPalette,
4897     ddraw_surface4_GetPixelFormat,
4898     ddraw_surface4_GetSurfaceDesc,
4899     ddraw_surface4_Initialize,
4900     ddraw_surface4_IsLost,
4901     ddraw_surface4_Lock,
4902     ddraw_surface4_ReleaseDC,
4903     ddraw_surface4_Restore,
4904     ddraw_surface4_SetClipper,
4905     ddraw_surface4_SetColorKey,
4906     ddraw_surface4_SetOverlayPosition,
4907     ddraw_surface4_SetPalette,
4908     ddraw_surface4_Unlock,
4909     ddraw_surface4_UpdateOverlay,
4910     ddraw_surface4_UpdateOverlayDisplay,
4911     ddraw_surface4_UpdateOverlayZOrder,
4912     /* IDirectDrawSurface2 */
4913     ddraw_surface4_GetDDInterface,
4914     ddraw_surface4_PageLock,
4915     ddraw_surface4_PageUnlock,
4916     /* IDirectDrawSurface3 */
4917     ddraw_surface4_SetSurfaceDesc,
4918     /* IDirectDrawSurface4 */
4919     ddraw_surface4_SetPrivateData,
4920     ddraw_surface4_GetPrivateData,
4921     ddraw_surface4_FreePrivateData,
4922     ddraw_surface4_GetUniquenessValue,
4923     ddraw_surface4_ChangeUniquenessValue,
4924 };
4925
4926 static const struct IDirectDrawSurface3Vtbl ddraw_surface3_vtbl =
4927 {
4928     /* IUnknown */
4929     ddraw_surface3_QueryInterface,
4930     ddraw_surface3_AddRef,
4931     ddraw_surface3_Release,
4932     /* IDirectDrawSurface */
4933     ddraw_surface3_AddAttachedSurface,
4934     ddraw_surface3_AddOverlayDirtyRect,
4935     ddraw_surface3_Blt,
4936     ddraw_surface3_BltBatch,
4937     ddraw_surface3_BltFast,
4938     ddraw_surface3_DeleteAttachedSurface,
4939     ddraw_surface3_EnumAttachedSurfaces,
4940     ddraw_surface3_EnumOverlayZOrders,
4941     ddraw_surface3_Flip,
4942     ddraw_surface3_GetAttachedSurface,
4943     ddraw_surface3_GetBltStatus,
4944     ddraw_surface3_GetCaps,
4945     ddraw_surface3_GetClipper,
4946     ddraw_surface3_GetColorKey,
4947     ddraw_surface3_GetDC,
4948     ddraw_surface3_GetFlipStatus,
4949     ddraw_surface3_GetOverlayPosition,
4950     ddraw_surface3_GetPalette,
4951     ddraw_surface3_GetPixelFormat,
4952     ddraw_surface3_GetSurfaceDesc,
4953     ddraw_surface3_Initialize,
4954     ddraw_surface3_IsLost,
4955     ddraw_surface3_Lock,
4956     ddraw_surface3_ReleaseDC,
4957     ddraw_surface3_Restore,
4958     ddraw_surface3_SetClipper,
4959     ddraw_surface3_SetColorKey,
4960     ddraw_surface3_SetOverlayPosition,
4961     ddraw_surface3_SetPalette,
4962     ddraw_surface3_Unlock,
4963     ddraw_surface3_UpdateOverlay,
4964     ddraw_surface3_UpdateOverlayDisplay,
4965     ddraw_surface3_UpdateOverlayZOrder,
4966     /* IDirectDrawSurface2 */
4967     ddraw_surface3_GetDDInterface,
4968     ddraw_surface3_PageLock,
4969     ddraw_surface3_PageUnlock,
4970     /* IDirectDrawSurface3 */
4971     ddraw_surface3_SetSurfaceDesc,
4972 };
4973
4974 static const struct IDirectDrawSurface2Vtbl ddraw_surface2_vtbl =
4975 {
4976     /* IUnknown */
4977     ddraw_surface2_QueryInterface,
4978     ddraw_surface2_AddRef,
4979     ddraw_surface2_Release,
4980     /* IDirectDrawSurface */
4981     ddraw_surface2_AddAttachedSurface,
4982     ddraw_surface2_AddOverlayDirtyRect,
4983     ddraw_surface2_Blt,
4984     ddraw_surface2_BltBatch,
4985     ddraw_surface2_BltFast,
4986     ddraw_surface2_DeleteAttachedSurface,
4987     ddraw_surface2_EnumAttachedSurfaces,
4988     ddraw_surface2_EnumOverlayZOrders,
4989     ddraw_surface2_Flip,
4990     ddraw_surface2_GetAttachedSurface,
4991     ddraw_surface2_GetBltStatus,
4992     ddraw_surface2_GetCaps,
4993     ddraw_surface2_GetClipper,
4994     ddraw_surface2_GetColorKey,
4995     ddraw_surface2_GetDC,
4996     ddraw_surface2_GetFlipStatus,
4997     ddraw_surface2_GetOverlayPosition,
4998     ddraw_surface2_GetPalette,
4999     ddraw_surface2_GetPixelFormat,
5000     ddraw_surface2_GetSurfaceDesc,
5001     ddraw_surface2_Initialize,
5002     ddraw_surface2_IsLost,
5003     ddraw_surface2_Lock,
5004     ddraw_surface2_ReleaseDC,
5005     ddraw_surface2_Restore,
5006     ddraw_surface2_SetClipper,
5007     ddraw_surface2_SetColorKey,
5008     ddraw_surface2_SetOverlayPosition,
5009     ddraw_surface2_SetPalette,
5010     ddraw_surface2_Unlock,
5011     ddraw_surface2_UpdateOverlay,
5012     ddraw_surface2_UpdateOverlayDisplay,
5013     ddraw_surface2_UpdateOverlayZOrder,
5014     /* IDirectDrawSurface2 */
5015     ddraw_surface2_GetDDInterface,
5016     ddraw_surface2_PageLock,
5017     ddraw_surface2_PageUnlock,
5018 };
5019
5020 static const struct IDirectDrawSurfaceVtbl ddraw_surface1_vtbl =
5021 {
5022     /* IUnknown */
5023     ddraw_surface1_QueryInterface,
5024     ddraw_surface1_AddRef,
5025     ddraw_surface1_Release,
5026     /* IDirectDrawSurface */
5027     ddraw_surface1_AddAttachedSurface,
5028     ddraw_surface1_AddOverlayDirtyRect,
5029     ddraw_surface1_Blt,
5030     ddraw_surface1_BltBatch,
5031     ddraw_surface1_BltFast,
5032     ddraw_surface1_DeleteAttachedSurface,
5033     ddraw_surface1_EnumAttachedSurfaces,
5034     ddraw_surface1_EnumOverlayZOrders,
5035     ddraw_surface1_Flip,
5036     ddraw_surface1_GetAttachedSurface,
5037     ddraw_surface1_GetBltStatus,
5038     ddraw_surface1_GetCaps,
5039     ddraw_surface1_GetClipper,
5040     ddraw_surface1_GetColorKey,
5041     ddraw_surface1_GetDC,
5042     ddraw_surface1_GetFlipStatus,
5043     ddraw_surface1_GetOverlayPosition,
5044     ddraw_surface1_GetPalette,
5045     ddraw_surface1_GetPixelFormat,
5046     ddraw_surface1_GetSurfaceDesc,
5047     ddraw_surface1_Initialize,
5048     ddraw_surface1_IsLost,
5049     ddraw_surface1_Lock,
5050     ddraw_surface1_ReleaseDC,
5051     ddraw_surface1_Restore,
5052     ddraw_surface1_SetClipper,
5053     ddraw_surface1_SetColorKey,
5054     ddraw_surface1_SetOverlayPosition,
5055     ddraw_surface1_SetPalette,
5056     ddraw_surface1_Unlock,
5057     ddraw_surface1_UpdateOverlay,
5058     ddraw_surface1_UpdateOverlayDisplay,
5059     ddraw_surface1_UpdateOverlayZOrder,
5060 };
5061
5062 static const struct IDirectDrawGammaControlVtbl ddraw_gamma_control_vtbl =
5063 {
5064     ddraw_gamma_control_QueryInterface,
5065     ddraw_gamma_control_AddRef,
5066     ddraw_gamma_control_Release,
5067     ddraw_gamma_control_GetGammaRamp,
5068     ddraw_gamma_control_SetGammaRamp,
5069 };
5070
5071 static const struct IDirect3DTexture2Vtbl d3d_texture2_vtbl =
5072 {
5073     d3d_texture2_QueryInterface,
5074     d3d_texture2_AddRef,
5075     d3d_texture2_Release,
5076     d3d_texture2_GetHandle,
5077     d3d_texture2_PaletteChanged,
5078     d3d_texture2_Load,
5079 };
5080
5081 static const struct IDirect3DTextureVtbl d3d_texture1_vtbl =
5082 {
5083     d3d_texture1_QueryInterface,
5084     d3d_texture1_AddRef,
5085     d3d_texture1_Release,
5086     d3d_texture1_Initialize,
5087     d3d_texture1_GetHandle,
5088     d3d_texture1_PaletteChanged,
5089     d3d_texture1_Load,
5090     d3d_texture1_Unload,
5091 };
5092
5093 IDirectDrawSurfaceImpl *unsafe_impl_from_IDirectDrawSurface7(IDirectDrawSurface7 *iface)
5094 {
5095     if (!iface) return NULL;
5096     assert(iface->lpVtbl == &ddraw_surface7_vtbl);
5097     return CONTAINING_RECORD(iface, IDirectDrawSurfaceImpl, IDirectDrawSurface7_iface);
5098 }
5099
5100 IDirectDrawSurfaceImpl *unsafe_impl_from_IDirectDrawSurface4(IDirectDrawSurface4 *iface)
5101 {
5102     if (!iface) return NULL;
5103     assert(iface->lpVtbl == &ddraw_surface4_vtbl);
5104     return CONTAINING_RECORD(iface, IDirectDrawSurfaceImpl, IDirectDrawSurface4_iface);
5105 }
5106
5107 static IDirectDrawSurfaceImpl *unsafe_impl_from_IDirectDrawSurface3(IDirectDrawSurface3 *iface)
5108 {
5109     if (!iface) return NULL;
5110     assert(iface->lpVtbl == &ddraw_surface3_vtbl);
5111     return CONTAINING_RECORD(iface, IDirectDrawSurfaceImpl, IDirectDrawSurface3_iface);
5112 }
5113
5114 static IDirectDrawSurfaceImpl *unsafe_impl_from_IDirectDrawSurface2(IDirectDrawSurface2 *iface)
5115 {
5116     if (!iface) return NULL;
5117     assert(iface->lpVtbl == &ddraw_surface2_vtbl);
5118     return CONTAINING_RECORD(iface, IDirectDrawSurfaceImpl, IDirectDrawSurface2_iface);
5119 }
5120
5121 IDirectDrawSurfaceImpl *unsafe_impl_from_IDirectDrawSurface(IDirectDrawSurface *iface)
5122 {
5123     if (!iface) return NULL;
5124     assert(iface->lpVtbl == &ddraw_surface1_vtbl);
5125     return CONTAINING_RECORD(iface, IDirectDrawSurfaceImpl, IDirectDrawSurface_iface);
5126 }
5127
5128 IDirectDrawSurfaceImpl *unsafe_impl_from_IDirect3DTexture2(IDirect3DTexture2 *iface)
5129 {
5130     if (!iface) return NULL;
5131     assert(iface->lpVtbl == &d3d_texture2_vtbl);
5132     return CONTAINING_RECORD(iface, IDirectDrawSurfaceImpl, IDirect3DTexture2_iface);
5133 }
5134
5135 IDirectDrawSurfaceImpl *unsafe_impl_from_IDirect3DTexture(IDirect3DTexture *iface)
5136 {
5137     if (!iface) return NULL;
5138     assert(iface->lpVtbl == &d3d_texture1_vtbl);
5139     return CONTAINING_RECORD(iface, IDirectDrawSurfaceImpl, IDirect3DTexture_iface);
5140 }
5141
5142 static void STDMETHODCALLTYPE ddraw_surface_wined3d_object_destroyed(void *parent)
5143 {
5144     IDirectDrawSurfaceImpl *surface = parent;
5145
5146     TRACE("surface %p.\n", surface);
5147
5148     /* Check for attached surfaces and detach them. */
5149     if (surface->first_attached != surface)
5150     {
5151         /* Well, this shouldn't happen: The surface being attached is
5152          * referenced in AddAttachedSurface(), so it shouldn't be released
5153          * until DeleteAttachedSurface() is called, because the refcount is
5154          * held. It looks like the application released it often enough to
5155          * force this. */
5156         WARN("Surface is still attached to surface %p.\n", surface->first_attached);
5157
5158         /* The refcount will drop to -1 here */
5159         if (FAILED(ddraw_surface_delete_attached_surface(surface->first_attached, surface, surface->attached_iface)))
5160             ERR("DeleteAttachedSurface failed.\n");
5161     }
5162
5163     while (surface->next_attached)
5164         if (FAILED(ddraw_surface_delete_attached_surface(surface,
5165                 surface->next_attached, surface->next_attached->attached_iface)))
5166             ERR("DeleteAttachedSurface failed.\n");
5167
5168     /* Having a texture handle set implies that the device still exists. */
5169     if (surface->Handle)
5170         ddraw_free_handle(&surface->ddraw->d3ddevice->handle_table, surface->Handle - 1, DDRAW_HANDLE_SURFACE);
5171
5172     /* Reduce the ddraw surface count. */
5173     list_remove(&surface->surface_list_entry);
5174
5175     if (surface == surface->ddraw->primary)
5176         surface->ddraw->primary = NULL;
5177
5178     HeapFree(GetProcessHeap(), 0, surface);
5179 }
5180
5181 const struct wined3d_parent_ops ddraw_surface_wined3d_parent_ops =
5182 {
5183     ddraw_surface_wined3d_object_destroyed,
5184 };
5185
5186 static void STDMETHODCALLTYPE ddraw_texture_wined3d_object_destroyed(void *parent)
5187 {
5188     IDirectDrawSurfaceImpl *surface = parent;
5189
5190     TRACE("surface %p.\n", surface);
5191
5192     ddraw_surface_cleanup(surface);
5193 }
5194
5195 static const struct wined3d_parent_ops ddraw_texture_wined3d_parent_ops =
5196 {
5197     ddraw_texture_wined3d_object_destroyed,
5198 };
5199
5200 HRESULT ddraw_surface_create_texture(IDirectDrawSurfaceImpl *surface)
5201 {
5202     const DDSURFACEDESC2 *desc = &surface->surface_desc;
5203     enum wined3d_format_id format;
5204     WINED3DPOOL pool;
5205     UINT levels;
5206
5207     if (desc->ddsCaps.dwCaps & DDSCAPS_MIPMAP)
5208         levels = desc->u2.dwMipMapCount;
5209     else
5210         levels = 1;
5211
5212     /* DDSCAPS_SYSTEMMEMORY textures are in WINED3DPOOL_SYSTEMMEM.
5213      * Should I forward the MANAGED cap to the managed pool? */
5214     if (desc->ddsCaps.dwCaps & DDSCAPS_SYSTEMMEMORY)
5215         pool = WINED3DPOOL_SYSTEMMEM;
5216     else
5217         pool = WINED3DPOOL_DEFAULT;
5218
5219     format = PixelFormat_DD2WineD3D(&surface->surface_desc.u4.ddpfPixelFormat);
5220     if (desc->ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP)
5221         return wined3d_texture_create_cube(surface->ddraw->wined3d_device, desc->dwWidth,
5222                 levels, 0, format, pool, surface, &ddraw_texture_wined3d_parent_ops, &surface->wined3d_texture);
5223     else
5224         return wined3d_texture_create_2d(surface->ddraw->wined3d_device, desc->dwWidth, desc->dwHeight,
5225                 levels, 0, format, pool, surface, &ddraw_texture_wined3d_parent_ops, &surface->wined3d_texture);
5226 }
5227
5228 HRESULT ddraw_surface_init(IDirectDrawSurfaceImpl *surface, IDirectDrawImpl *ddraw,
5229         DDSURFACEDESC2 *desc, UINT mip_level, UINT version)
5230 {
5231     WINED3DPOOL pool = WINED3DPOOL_DEFAULT;
5232     enum wined3d_format_id format;
5233     DWORD usage = 0;
5234     HRESULT hr;
5235
5236     if (!(desc->ddsCaps.dwCaps & (DDSCAPS_VIDEOMEMORY | DDSCAPS_SYSTEMMEMORY))
5237             && !((desc->ddsCaps.dwCaps & DDSCAPS_TEXTURE)
5238             && (desc->ddsCaps.dwCaps2 & DDSCAPS2_TEXTUREMANAGE)))
5239     {
5240         /* Tests show surfaces without memory flags get these flags added
5241          * right after creation. */
5242         desc->ddsCaps.dwCaps |= DDSCAPS_LOCALVIDMEM | DDSCAPS_VIDEOMEMORY;
5243     }
5244
5245     if (desc->ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE)
5246     {
5247         usage |= WINED3DUSAGE_RENDERTARGET;
5248         desc->ddsCaps.dwCaps |= DDSCAPS_VISIBLE;
5249     }
5250
5251     if ((desc->ddsCaps.dwCaps & DDSCAPS_3DDEVICE) && !(desc->ddsCaps.dwCaps & DDSCAPS_ZBUFFER))
5252     {
5253         usage |= WINED3DUSAGE_RENDERTARGET;
5254     }
5255
5256     if (desc->ddsCaps.dwCaps & (DDSCAPS_OVERLAY))
5257     {
5258         usage |= WINED3DUSAGE_OVERLAY;
5259     }
5260
5261     if (desc->ddsCaps.dwCaps & DDSCAPS_ZBUFFER)
5262         usage |= WINED3DUSAGE_DEPTHSTENCIL;
5263
5264     if (desc->ddsCaps.dwCaps & DDSCAPS_SYSTEMMEMORY)
5265     {
5266         pool = WINED3DPOOL_SYSTEMMEM;
5267     }
5268     else if (desc->ddsCaps.dwCaps2 & DDSCAPS2_TEXTUREMANAGE)
5269     {
5270         pool = WINED3DPOOL_MANAGED;
5271         /* Managed textures have the system memory flag set. */
5272         desc->ddsCaps.dwCaps |= DDSCAPS_SYSTEMMEMORY;
5273     }
5274     else if (desc->ddsCaps.dwCaps & DDSCAPS_VIDEOMEMORY)
5275     {
5276         /* Videomemory adds localvidmem. This is mutually exclusive with
5277          * systemmemory and texturemanage. */
5278         desc->ddsCaps.dwCaps |= DDSCAPS_LOCALVIDMEM;
5279     }
5280
5281     format = PixelFormat_DD2WineD3D(&desc->u4.ddpfPixelFormat);
5282     if (format == WINED3DFMT_UNKNOWN)
5283     {
5284         WARN("Unsupported / unknown pixelformat.\n");
5285         return DDERR_INVALIDPIXELFORMAT;
5286     }
5287
5288     surface->IDirectDrawSurface7_iface.lpVtbl = &ddraw_surface7_vtbl;
5289     surface->IDirectDrawSurface4_iface.lpVtbl = &ddraw_surface4_vtbl;
5290     surface->IDirectDrawSurface3_iface.lpVtbl = &ddraw_surface3_vtbl;
5291     surface->IDirectDrawSurface2_iface.lpVtbl = &ddraw_surface2_vtbl;
5292     surface->IDirectDrawSurface_iface.lpVtbl = &ddraw_surface1_vtbl;
5293     surface->IDirectDrawGammaControl_iface.lpVtbl = &ddraw_gamma_control_vtbl;
5294     surface->IDirect3DTexture2_iface.lpVtbl = &d3d_texture2_vtbl;
5295     surface->IDirect3DTexture_iface.lpVtbl = &d3d_texture1_vtbl;
5296     surface->iface_count = 1;
5297     surface->version = version;
5298     surface->ddraw = ddraw;
5299
5300     if (version == 7)
5301     {
5302         surface->ref7 = 1;
5303     }
5304     else if (version == 4)
5305     {
5306         surface->ref4 = 1;
5307     }
5308     else
5309     {
5310         surface->ref1 = 1;
5311     }
5312
5313     copy_to_surfacedesc2(&surface->surface_desc, desc);
5314
5315     surface->first_attached = surface;
5316
5317     hr = wined3d_surface_create(ddraw->wined3d_device, desc->dwWidth, desc->dwHeight, format,
5318             TRUE /* Lockable */, FALSE /* Discard */, mip_level, usage, pool,
5319             WINED3DMULTISAMPLE_NONE, 0 /* MultiSampleQuality */, DefaultSurfaceType, surface,
5320             &ddraw_surface_wined3d_parent_ops, &surface->wined3d_surface);
5321     if (FAILED(hr))
5322     {
5323         WARN("Failed to create wined3d surface, hr %#x.\n", hr);
5324         return hr;
5325     }
5326
5327     /* Anno 1602 stores the pitch right after surface creation, so make sure
5328      * it's there. TODO: Test other fourcc formats. */
5329     if (format == WINED3DFMT_DXT1 || format == WINED3DFMT_DXT2 || format == WINED3DFMT_DXT3
5330             || format == WINED3DFMT_DXT4 || format == WINED3DFMT_DXT5)
5331     {
5332         surface->surface_desc.dwFlags |= DDSD_LINEARSIZE;
5333         if (format == WINED3DFMT_DXT1)
5334         {
5335             surface->surface_desc.u1.dwLinearSize = max(4, desc->dwWidth) * max(4, desc->dwHeight) / 2;
5336         }
5337         else
5338         {
5339             surface->surface_desc.u1.dwLinearSize = max(4, desc->dwWidth) * max(4, desc->dwHeight);
5340         }
5341     }
5342     else
5343     {
5344         surface->surface_desc.dwFlags |= DDSD_PITCH;
5345         surface->surface_desc.u1.lPitch = wined3d_surface_get_pitch(surface->wined3d_surface);
5346     }
5347
5348     if (desc->dwFlags & DDSD_CKDESTOVERLAY)
5349     {
5350         wined3d_surface_set_color_key(surface->wined3d_surface, DDCKEY_DESTOVERLAY,
5351                 (WINEDDCOLORKEY *)&desc->u3.ddckCKDestOverlay);
5352     }
5353     if (desc->dwFlags & DDSD_CKDESTBLT)
5354     {
5355         wined3d_surface_set_color_key(surface->wined3d_surface, DDCKEY_DESTBLT,
5356                 (WINEDDCOLORKEY *)&desc->ddckCKDestBlt);
5357     }
5358     if (desc->dwFlags & DDSD_CKSRCOVERLAY)
5359     {
5360         wined3d_surface_set_color_key(surface->wined3d_surface, DDCKEY_SRCOVERLAY,
5361                 (WINEDDCOLORKEY *)&desc->ddckCKSrcOverlay);
5362     }
5363     if (desc->dwFlags & DDSD_CKSRCBLT)
5364     {
5365         wined3d_surface_set_color_key(surface->wined3d_surface, DDCKEY_SRCBLT,
5366                 (WINEDDCOLORKEY *)&desc->ddckCKSrcBlt);
5367     }
5368     if (desc->dwFlags & DDSD_LPSURFACE)
5369     {
5370         hr = wined3d_surface_set_mem(surface->wined3d_surface, desc->lpSurface);
5371         if (FAILED(hr))
5372         {
5373             ERR("Failed to set surface memory, hr %#x.\n", hr);
5374             wined3d_surface_decref(surface->wined3d_surface);
5375             return hr;
5376         }
5377     }
5378
5379     return DD_OK;
5380 }