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