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