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