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