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