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