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