d3dx9: Implement D3DXAssembleShaderFromFile.
[wine] / dlls / ddraw / ddraw.c
1 /*
2  * Copyright 1997-2000 Marcus Meissner
3  * Copyright 1998-2000 Lionel Ulmer
4  * Copyright 2000-2001 TransGaming Technologies Inc.
5  * Copyright 2006 Stefan Dösinger
6  * Copyright 2008 Denver Gingerich
7  *
8  * This library is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU Lesser General Public
10  * License as published by the Free Software Foundation; either
11  * version 2.1 of the License, or (at your option) any later version.
12  *
13  * This library is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16  * Lesser General Public License for more details.
17  *
18  * You should have received a copy of the GNU Lesser General Public
19  * License along with this library; if not, write to the Free Software
20  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
21  */
22
23 #include "config.h"
24 #include "wine/port.h"
25
26 #include <assert.h>
27 #include <stdarg.h>
28 #include <string.h>
29 #include <stdlib.h>
30
31 #define COBJMACROS
32 #define NONAMELESSUNION
33
34 #include "windef.h"
35 #include "winbase.h"
36 #include "winerror.h"
37 #include "wingdi.h"
38 #include "wine/exception.h"
39
40 #include "ddraw.h"
41 #include "d3d.h"
42
43 #include "ddraw_private.h"
44 #include "wine/debug.h"
45
46 WINE_DEFAULT_DEBUG_CHANNEL(ddraw);
47
48 /* Device identifier. Don't relay it to WineD3D */
49 static const DDDEVICEIDENTIFIER2 deviceidentifier =
50 {
51     "display",
52     "DirectDraw HAL",
53     { { 0x00010001, 0x00010001 } },
54     0, 0, 0, 0,
55     /* a8373c10-7ac4-4deb-849a-009844d08b2d */
56     {0xa8373c10,0x7ac4,0x4deb, {0x84,0x9a,0x00,0x98,0x44,0xd0,0x8b,0x2d}},
57     0
58 };
59
60 static void STDMETHODCALLTYPE ddraw_null_wined3d_object_destroyed(void *parent) {}
61
62 const struct wined3d_parent_ops ddraw_null_wined3d_parent_ops =
63 {
64     ddraw_null_wined3d_object_destroyed,
65 };
66
67 static inline IDirectDrawImpl *ddraw_from_ddraw1(IDirectDraw *iface)
68 {
69     return (IDirectDrawImpl *)((char*)iface - FIELD_OFFSET(IDirectDrawImpl, IDirectDraw_vtbl));
70 }
71
72 static inline IDirectDrawImpl *ddraw_from_ddraw2(IDirectDraw2 *iface)
73 {
74     return (IDirectDrawImpl *)((char*)iface - FIELD_OFFSET(IDirectDrawImpl, IDirectDraw2_vtbl));
75 }
76
77 static inline IDirectDrawImpl *ddraw_from_ddraw3(IDirectDraw3 *iface)
78 {
79     return (IDirectDrawImpl *)((char*)iface - FIELD_OFFSET(IDirectDrawImpl, IDirectDraw3_vtbl));
80 }
81
82 static inline IDirectDrawImpl *ddraw_from_ddraw4(IDirectDraw4 *iface)
83 {
84     return (IDirectDrawImpl *)((char*)iface - FIELD_OFFSET(IDirectDrawImpl, IDirectDraw4_vtbl));
85 }
86
87 /*****************************************************************************
88  * IUnknown Methods
89  *****************************************************************************/
90
91 /*****************************************************************************
92  * IDirectDraw7::QueryInterface
93  *
94  * Queries different interfaces of the DirectDraw object. It can return
95  * IDirectDraw interfaces in version 1, 2, 4 and 7, and IDirect3D interfaces
96  * in version 1, 2, 3 and 7. An IDirect3DDevice can be created with this
97  * method.
98  * The returned interface is AddRef()-ed before it's returned
99  *
100  * Used for version 1, 2, 4 and 7
101  *
102  * Params:
103  *  refiid: Interface ID asked for
104  *  obj: Used to return the interface pointer
105  *
106  * Returns:
107  *  S_OK if an interface was found
108  *  E_NOINTERFACE if the requested interface wasn't found
109  *
110  *****************************************************************************/
111 static HRESULT WINAPI ddraw7_QueryInterface(IDirectDraw7 *iface, REFIID refiid, void **obj)
112 {
113     IDirectDrawImpl *This = (IDirectDrawImpl *)iface;
114
115     TRACE("(%p)->(%s,%p)\n", This, debugstr_guid(refiid), obj);
116
117     /* Can change surface impl type */
118     EnterCriticalSection(&ddraw_cs);
119
120     /* According to COM docs, if the QueryInterface fails, obj should be set to NULL */
121     *obj = NULL;
122
123     if(!refiid)
124     {
125         LeaveCriticalSection(&ddraw_cs);
126         return DDERR_INVALIDPARAMS;
127     }
128
129     /* Check DirectDraw Interfaces */
130     if ( IsEqualGUID( &IID_IUnknown, refiid ) ||
131          IsEqualGUID( &IID_IDirectDraw7, refiid ) )
132     {
133         *obj = This;
134         TRACE("(%p) Returning IDirectDraw7 interface at %p\n", This, *obj);
135     }
136     else if ( IsEqualGUID( &IID_IDirectDraw4, refiid ) )
137     {
138         *obj = &This->IDirectDraw4_vtbl;
139         TRACE("(%p) Returning IDirectDraw4 interface at %p\n", This, *obj);
140     }
141     else if ( IsEqualGUID( &IID_IDirectDraw3, refiid ) )
142     {
143         /* This Interface exists in ddrawex.dll, it is implemented in a wrapper */
144         WARN("IDirectDraw3 is not valid in ddraw.dll\n");
145         *obj = NULL;
146         LeaveCriticalSection(&ddraw_cs);
147         return E_NOINTERFACE;
148     }
149     else if ( IsEqualGUID( &IID_IDirectDraw2, refiid ) )
150     {
151         *obj = &This->IDirectDraw2_vtbl;
152         TRACE("(%p) Returning IDirectDraw2 interface at %p\n", This, *obj);
153     }
154     else if ( IsEqualGUID( &IID_IDirectDraw, refiid ) )
155     {
156         *obj = &This->IDirectDraw_vtbl;
157         TRACE("(%p) Returning IDirectDraw interface at %p\n", This, *obj);
158     }
159
160     /* Direct3D
161      * The refcount unit test revealed that an IDirect3D7 interface can only be queried
162      * from a DirectDraw object that was created as an IDirectDraw7 interface. No idea
163      * who had this idea and why. The older interfaces can query and IDirect3D version
164      * because they are all created as IDirectDraw(1). This isn't really crucial behavior,
165      * and messy to implement with the common creation function, so it has been left out here.
166      */
167     else if ( IsEqualGUID( &IID_IDirect3D  , refiid ) ||
168               IsEqualGUID( &IID_IDirect3D2 , refiid ) ||
169               IsEqualGUID( &IID_IDirect3D3 , refiid ) ||
170               IsEqualGUID( &IID_IDirect3D7 , refiid ) )
171     {
172         /* Check the surface implementation */
173         if(This->ImplType == SURFACE_UNKNOWN)
174         {
175             /* Apps may create the IDirect3D Interface before the primary surface.
176              * set the surface implementation */
177             This->ImplType = SURFACE_OPENGL;
178             TRACE("(%p) Choosing OpenGL surfaces because a Direct3D interface was requested\n", This);
179         }
180         else if(This->ImplType != SURFACE_OPENGL && DefaultSurfaceType == SURFACE_UNKNOWN)
181         {
182             ERR("(%p) The App is requesting a D3D device, but a non-OpenGL surface type was choosen. Prepare for trouble!\n", This);
183             ERR(" (%p) You may want to contact wine-devel for help\n", This);
184             /* Should I assert(0) here??? */
185         }
186         else if(This->ImplType != SURFACE_OPENGL)
187         {
188             WARN("The app requests a Direct3D interface, but non-opengl surfaces where set in winecfg\n");
189             /* Do not abort here, only reject 3D Device creation */
190         }
191
192         if ( IsEqualGUID( &IID_IDirect3D  , refiid ) )
193         {
194             This->d3dversion = 1;
195             *obj = &This->IDirect3D_vtbl;
196             TRACE(" returning Direct3D interface at %p.\n", *obj);
197         }
198         else if ( IsEqualGUID( &IID_IDirect3D2  , refiid ) )
199         {
200             This->d3dversion = 2;
201             *obj = &This->IDirect3D2_vtbl;
202             TRACE(" returning Direct3D2 interface at %p.\n", *obj);
203         }
204         else if ( IsEqualGUID( &IID_IDirect3D3  , refiid ) )
205         {
206             This->d3dversion = 3;
207             *obj = &This->IDirect3D3_vtbl;
208             TRACE(" returning Direct3D3 interface at %p.\n", *obj);
209         }
210         else if(IsEqualGUID( &IID_IDirect3D7  , refiid ))
211         {
212             This->d3dversion = 7;
213             *obj = &This->IDirect3D7_vtbl;
214             TRACE(" returning Direct3D7 interface at %p.\n", *obj);
215         }
216     }
217     else if (IsEqualGUID(refiid, &IID_IWineD3DDeviceParent))
218     {
219         *obj = &This->device_parent_vtbl;
220     }
221
222     /* Unknown interface */
223     else
224     {
225         ERR("(%p)->(%s, %p): No interface found\n", This, debugstr_guid(refiid), obj);
226         LeaveCriticalSection(&ddraw_cs);
227         return E_NOINTERFACE;
228     }
229
230     IUnknown_AddRef( (IUnknown *) *obj );
231     LeaveCriticalSection(&ddraw_cs);
232     return S_OK;
233 }
234
235 static HRESULT WINAPI ddraw4_QueryInterface(IDirectDraw4 *iface, REFIID riid, void **object)
236 {
237     TRACE("iface %p, riid %s, object %p.\n", iface, debugstr_guid(riid), object);
238
239     return ddraw7_QueryInterface((IDirectDraw7 *)ddraw_from_ddraw4(iface), riid, object);
240 }
241
242 static HRESULT WINAPI ddraw3_QueryInterface(IDirectDraw3 *iface, REFIID riid, void **object)
243 {
244     TRACE("iface %p, riid %s, object %p.\n", iface, debugstr_guid(riid), object);
245
246     return ddraw7_QueryInterface((IDirectDraw7 *)ddraw_from_ddraw3(iface), riid, object);
247 }
248
249 static HRESULT WINAPI ddraw2_QueryInterface(IDirectDraw2 *iface, REFIID riid, void **object)
250 {
251     TRACE("iface %p, riid %s, object %p.\n", iface, debugstr_guid(riid), object);
252
253     return ddraw7_QueryInterface((IDirectDraw7 *)ddraw_from_ddraw2(iface), riid, object);
254 }
255
256 static HRESULT WINAPI ddraw1_QueryInterface(IDirectDraw *iface, REFIID riid, void **object)
257 {
258     TRACE("iface %p, riid %s, object %p.\n", iface, debugstr_guid(riid), object);
259
260     return ddraw7_QueryInterface((IDirectDraw7 *)ddraw_from_ddraw1(iface), riid, object);
261 }
262
263 /*****************************************************************************
264  * IDirectDraw7::AddRef
265  *
266  * Increases the interfaces refcount, basically
267  *
268  * DDraw refcounting is a bit tricky. The different DirectDraw interface
269  * versions have individual refcounts, but the IDirect3D interfaces do not.
270  * All interfaces are from one object, that means calling QueryInterface on an
271  * IDirectDraw7 interface for an IDirectDraw4 interface does not create a new
272  * IDirectDrawImpl object.
273  *
274  * That means all AddRef and Release implementations of IDirectDrawX work
275  * with their own counter, and IDirect3DX::AddRef thunk to IDirectDraw (1),
276  * except of IDirect3D7 which thunks to IDirectDraw7
277  *
278  * Returns: The new refcount
279  *
280  *****************************************************************************/
281 static ULONG WINAPI ddraw7_AddRef(IDirectDraw7 *iface)
282 {
283     IDirectDrawImpl *This = (IDirectDrawImpl *)iface;
284     ULONG ref = InterlockedIncrement(&This->ref7);
285
286     TRACE("(%p) : incrementing IDirectDraw7 refcount from %u.\n", This, ref -1);
287
288     if(ref == 1) InterlockedIncrement(&This->numIfaces);
289
290     return ref;
291 }
292
293 static ULONG WINAPI ddraw4_AddRef(IDirectDraw4 *iface)
294 {
295     IDirectDrawImpl *ddraw = ddraw_from_ddraw4(iface);
296     ULONG ref = InterlockedIncrement(&ddraw->ref4);
297
298     TRACE("%p increasing refcount to %u.\n", ddraw, ref);
299
300     if (ref == 1) InterlockedIncrement(&ddraw->numIfaces);
301
302     return ref;
303 }
304
305 static ULONG WINAPI ddraw3_AddRef(IDirectDraw3 *iface)
306 {
307     IDirectDrawImpl *ddraw = ddraw_from_ddraw3(iface);
308     ULONG ref = InterlockedIncrement(&ddraw->ref3);
309
310     TRACE("%p increasing refcount to %u.\n", ddraw, ref);
311
312     if (ref == 1) InterlockedIncrement(&ddraw->numIfaces);
313
314     return ref;
315 }
316
317 static ULONG WINAPI ddraw2_AddRef(IDirectDraw2 *iface)
318 {
319     IDirectDrawImpl *ddraw = ddraw_from_ddraw2(iface);
320     ULONG ref = InterlockedIncrement(&ddraw->ref2);
321
322     TRACE("%p increasing refcount to %u.\n", ddraw, ref);
323
324     if (ref == 1) InterlockedIncrement(&ddraw->numIfaces);
325
326     return ref;
327 }
328
329 static ULONG WINAPI ddraw1_AddRef(IDirectDraw *iface)
330 {
331     IDirectDrawImpl *ddraw = ddraw_from_ddraw1(iface);
332     ULONG ref = InterlockedIncrement(&ddraw->ref1);
333
334     TRACE("%p increasing refcount to %u.\n", ddraw, ref);
335
336     if (ref == 1) InterlockedIncrement(&ddraw->numIfaces);
337
338     return ref;
339 }
340
341 /*****************************************************************************
342  * ddraw_destroy
343  *
344  * Destroys a ddraw object if all refcounts are 0. This is to share code
345  * between the IDirectDrawX::Release functions
346  *
347  * Params:
348  *  This: DirectDraw object to destroy
349  *
350  *****************************************************************************/
351 static void ddraw_destroy(IDirectDrawImpl *This)
352 {
353     IDirectDraw7_SetCooperativeLevel((IDirectDraw7 *)This, NULL, DDSCL_NORMAL);
354     IDirectDraw7_RestoreDisplayMode((IDirectDraw7 *)This);
355
356     /* Destroy the device window if we created one */
357     if(This->devicewindow != 0)
358     {
359         TRACE(" (%p) Destroying the device window %p\n", This, This->devicewindow);
360         DestroyWindow(This->devicewindow);
361         This->devicewindow = 0;
362     }
363
364     EnterCriticalSection(&ddraw_cs);
365     list_remove(&This->ddraw_list_entry);
366     LeaveCriticalSection(&ddraw_cs);
367
368     /* Release the attached WineD3D stuff */
369     IWineD3DDevice_Release(This->wineD3DDevice);
370     IWineD3D_Release(This->wineD3D);
371
372     /* Now free the object */
373     HeapFree(GetProcessHeap(), 0, This);
374 }
375
376 /*****************************************************************************
377  * IDirectDraw7::Release
378  *
379  * Decreases the refcount. If the refcount falls to 0, the object is destroyed
380  *
381  * Returns: The new refcount
382  *****************************************************************************/
383 static ULONG WINAPI ddraw7_Release(IDirectDraw7 *iface)
384 {
385     IDirectDrawImpl *This = (IDirectDrawImpl *)iface;
386     ULONG ref = InterlockedDecrement(&This->ref7);
387
388     TRACE("(%p)->() decrementing IDirectDraw7 refcount from %u.\n", This, ref +1);
389
390     if (!ref && !InterlockedDecrement(&This->numIfaces))
391         ddraw_destroy(This);
392
393     return ref;
394 }
395
396 static ULONG WINAPI ddraw4_Release(IDirectDraw4 *iface)
397 {
398     IDirectDrawImpl *ddraw = ddraw_from_ddraw4(iface);
399     ULONG ref = InterlockedDecrement(&ddraw->ref4);
400
401     TRACE("%p decreasing refcount to %u.\n", ddraw, ref);
402
403     if (!ref && !InterlockedDecrement(&ddraw->numIfaces))
404         ddraw_destroy(ddraw);
405
406     return ref;
407 }
408
409 static ULONG WINAPI ddraw3_Release(IDirectDraw3 *iface)
410 {
411     IDirectDrawImpl *ddraw = ddraw_from_ddraw3(iface);
412     ULONG ref = InterlockedDecrement(&ddraw->ref3);
413
414     TRACE("%p decreasing refcount to %u.\n", ddraw, ref);
415
416     if (!ref && !InterlockedDecrement(&ddraw->numIfaces))
417         ddraw_destroy(ddraw);
418
419     return ref;
420 }
421
422 static ULONG WINAPI ddraw2_Release(IDirectDraw2 *iface)
423 {
424     IDirectDrawImpl *ddraw = ddraw_from_ddraw2(iface);
425     ULONG ref = InterlockedDecrement(&ddraw->ref2);
426
427     TRACE("%p decreasing refcount to %u.\n", ddraw, ref);
428
429     if (!ref && !InterlockedDecrement(&ddraw->numIfaces))
430         ddraw_destroy(ddraw);
431
432     return ref;
433 }
434
435 static ULONG WINAPI ddraw1_Release(IDirectDraw *iface)
436 {
437     IDirectDrawImpl *ddraw = ddraw_from_ddraw1(iface);
438     ULONG ref = InterlockedDecrement(&ddraw->ref1);
439
440     TRACE("%p decreasing refcount to %u.\n", ddraw, ref);
441
442     if (!ref && !InterlockedDecrement(&ddraw->numIfaces))
443         ddraw_destroy(ddraw);
444
445     return ref;
446 }
447
448 /*****************************************************************************
449  * IDirectDraw methods
450  *****************************************************************************/
451
452 /*****************************************************************************
453  * IDirectDraw7::SetCooperativeLevel
454  *
455  * Sets the cooperative level for the DirectDraw object, and the window
456  * assigned to it. The cooperative level determines the general behavior
457  * of the DirectDraw application
458  *
459  * Warning: This is quite tricky, as it's not really documented which
460  * cooperative levels can be combined with each other. If a game fails
461  * after this function, try to check the cooperative levels passed on
462  * Windows, and if it returns something different.
463  *
464  * If you think that this function caused the failure because it writes a
465  * fixme, be sure to run again with a +ddraw trace.
466  *
467  * What is known about cooperative levels (See the ddraw modes test):
468  * DDSCL_EXCLUSIVE and DDSCL_FULLSCREEN must be used with each other
469  * DDSCL_NORMAL is not compatible with DDSCL_EXCLUSIVE or DDSCL_FULLSCREEN
470  * DDSCL_SETFOCUSWINDOW can be passed only in DDSCL_NORMAL mode, but after that
471  * DDSCL_FULLSCREEN can be activated
472  * DDSCL_SETFOCUSWINDOW may only be used with DDSCL_NOWINDOWCHANGES
473  *
474  * Handled flags: DDSCL_NORMAL, DDSCL_FULLSCREEN, DDSCL_EXCLUSIVE,
475  *                DDSCL_SETFOCUSWINDOW (partially),
476  *                DDSCL_MULTITHREADED (work in progress)
477  *
478  * Unhandled flags, which should be implemented
479  *  DDSCL_SETDEVICEWINDOW: Sets a window specially used for rendering (I don't
480  *  expect any difference to a normal window for wine)
481  *  DDSCL_CREATEDEVICEWINDOW: Tells ddraw to create its own window for
482  *  rendering (Possible test case: Half-Life)
483  *
484  * Unsure about these: DDSCL_FPUSETUP DDSCL_FPURESERVE
485  *
486  * These don't seem very important for wine:
487  *  DDSCL_ALLOWREBOOT, DDSCL_NOWINDOWCHANGES, DDSCL_ALLOWMODEX
488  *
489  * Returns:
490  *  DD_OK if the cooperative level was set successfully
491  *  DDERR_INVALIDPARAMS if the passed cooperative level combination is invalid
492  *  DDERR_HWNDALREADYSET if DDSCL_SETFOCUSWINDOW is passed in exclusive mode
493  *   (Probably others too, have to investigate)
494  *
495  *****************************************************************************/
496 static HRESULT WINAPI ddraw7_SetCooperativeLevel(IDirectDraw7 *iface, HWND hwnd, DWORD cooplevel)
497 {
498     IDirectDrawImpl *This = (IDirectDrawImpl *)iface;
499     HWND window;
500
501     TRACE("(%p)->(%p,%08x)\n",This,hwnd,cooplevel);
502     DDRAW_dump_cooperativelevel(cooplevel);
503
504     EnterCriticalSection(&ddraw_cs);
505
506     /* Get the old window */
507     window = This->dest_window;
508
509     /* Tests suggest that we need one of them: */
510     if(!(cooplevel & (DDSCL_SETFOCUSWINDOW |
511                       DDSCL_NORMAL         |
512                       DDSCL_EXCLUSIVE      )))
513     {
514         TRACE("Incorrect cooplevel flags, returning DDERR_INVALIDPARAMS\n");
515         LeaveCriticalSection(&ddraw_cs);
516         return DDERR_INVALIDPARAMS;
517     }
518
519     /* Handle those levels first which set various hwnds */
520     if(cooplevel & DDSCL_SETFOCUSWINDOW)
521     {
522         /* This isn't compatible with a lot of flags */
523         if(cooplevel & ( DDSCL_MULTITHREADED   |
524                          DDSCL_FPUSETUP        |
525                          DDSCL_FPUPRESERVE     |
526                          DDSCL_ALLOWREBOOT     |
527                          DDSCL_ALLOWMODEX      |
528                          DDSCL_SETDEVICEWINDOW |
529                          DDSCL_NORMAL          |
530                          DDSCL_EXCLUSIVE       |
531                          DDSCL_FULLSCREEN      ) )
532         {
533             TRACE("Called with incompatible flags, returning DDERR_INVALIDPARAMS\n");
534             LeaveCriticalSection(&ddraw_cs);
535             return DDERR_INVALIDPARAMS;
536         }
537         else if( (This->cooperative_level & DDSCL_FULLSCREEN) && window)
538         {
539             TRACE("Setting DDSCL_SETFOCUSWINDOW with an already set window, returning DDERR_HWNDALREADYSET\n");
540             LeaveCriticalSection(&ddraw_cs);
541             return DDERR_HWNDALREADYSET;
542         }
543
544         This->focuswindow = hwnd;
545         /* Won't use the hwnd param for anything else */
546         hwnd = NULL;
547
548         /* Use the focus window for drawing too */
549         This->dest_window = This->focuswindow;
550
551         /* Destroy the device window, if we have one */
552         if(This->devicewindow)
553         {
554             DestroyWindow(This->devicewindow);
555             This->devicewindow = NULL;
556         }
557     }
558     /* DDSCL_NORMAL or DDSCL_FULLSCREEN | DDSCL_EXCLUSIVE */
559     if(cooplevel & DDSCL_NORMAL)
560     {
561         /* Can't coexist with fullscreen or exclusive */
562         if(cooplevel & (DDSCL_FULLSCREEN | DDSCL_EXCLUSIVE) )
563         {
564             TRACE("(%p) DDSCL_NORMAL is not compative with DDSCL_FULLSCREEN or DDSCL_EXCLUSIVE\n", This);
565             LeaveCriticalSection(&ddraw_cs);
566             return DDERR_INVALIDPARAMS;
567         }
568
569         /* Switching from fullscreen? */
570         if(This->cooperative_level & DDSCL_FULLSCREEN)
571         {
572             This->cooperative_level &= ~DDSCL_FULLSCREEN;
573             This->cooperative_level &= ~DDSCL_EXCLUSIVE;
574             This->cooperative_level &= ~DDSCL_ALLOWMODEX;
575
576             IWineD3DDevice_ReleaseFocusWindow(This->wineD3DDevice);
577         }
578
579         /* Don't override focus windows or private device windows */
580         if( hwnd &&
581             !(This->focuswindow) &&
582             !(This->devicewindow) &&
583             (hwnd != window) )
584         {
585             This->dest_window = hwnd;
586         }
587     }
588     else if(cooplevel & DDSCL_FULLSCREEN)
589     {
590         /* Needs DDSCL_EXCLUSIVE */
591         if(!(cooplevel & DDSCL_EXCLUSIVE) )
592         {
593             TRACE("(%p) DDSCL_FULLSCREEN needs DDSCL_EXCLUSIVE\n", This);
594             LeaveCriticalSection(&ddraw_cs);
595             return DDERR_INVALIDPARAMS;
596         }
597         /* Need a HWND
598         if(hwnd == 0)
599         {
600             TRACE("(%p) DDSCL_FULLSCREEN needs a HWND\n", This);
601             return DDERR_INVALIDPARAMS;
602         }
603         */
604
605         This->cooperative_level &= ~DDSCL_NORMAL;
606
607         /* Don't override focus windows or private device windows */
608         if( hwnd &&
609             !(This->focuswindow) &&
610             !(This->devicewindow) &&
611             (hwnd != window) )
612         {
613             HRESULT hr = IWineD3DDevice_AcquireFocusWindow(This->wineD3DDevice, hwnd);
614             if (FAILED(hr))
615             {
616                 ERR("Failed to acquire focus window, hr %#x.\n", hr);
617                 LeaveCriticalSection(&ddraw_cs);
618                 return hr;
619             }
620             This->dest_window = hwnd;
621         }
622     }
623     else if(cooplevel & DDSCL_EXCLUSIVE)
624     {
625         TRACE("(%p) DDSCL_EXCLUSIVE needs DDSCL_FULLSCREEN\n", This);
626         LeaveCriticalSection(&ddraw_cs);
627         return DDERR_INVALIDPARAMS;
628     }
629
630     if(cooplevel & DDSCL_CREATEDEVICEWINDOW)
631     {
632         /* Don't create a device window if a focus window is set */
633         if( !(This->focuswindow) )
634         {
635             HWND devicewindow = CreateWindowExA(0, DDRAW_WINDOW_CLASS_NAME, "DDraw device window",
636                     WS_POPUP, 0, 0, GetSystemMetrics(SM_CXSCREEN), GetSystemMetrics(SM_CYSCREEN),
637                     NULL, NULL, NULL, NULL);
638             if (!devicewindow)
639             {
640                 ERR("Failed to create window, last error %#x.\n", GetLastError());
641                 LeaveCriticalSection(&ddraw_cs);
642                 return E_FAIL;
643             }
644
645             ShowWindow(devicewindow, SW_SHOW);   /* Just to be sure */
646             TRACE("(%p) Created a DDraw device window. HWND=%p\n", This, devicewindow);
647
648             This->devicewindow = devicewindow;
649             This->dest_window = devicewindow;
650         }
651     }
652
653     if(cooplevel & DDSCL_MULTITHREADED && !(This->cooperative_level & DDSCL_MULTITHREADED))
654     {
655         /* Enable thread safety in wined3d */
656         IWineD3DDevice_SetMultithreaded(This->wineD3DDevice);
657     }
658
659     /* Unhandled flags */
660     if(cooplevel & DDSCL_ALLOWREBOOT)
661         WARN("(%p) Unhandled flag DDSCL_ALLOWREBOOT, harmless\n", This);
662     if(cooplevel & DDSCL_ALLOWMODEX)
663         WARN("(%p) Unhandled flag DDSCL_ALLOWMODEX, harmless\n", This);
664     if(cooplevel & DDSCL_FPUSETUP)
665         WARN("(%p) Unhandled flag DDSCL_FPUSETUP, harmless\n", This);
666
667     /* Store the cooperative_level */
668     This->cooperative_level |= cooplevel;
669     TRACE("SetCooperativeLevel retuning DD_OK\n");
670     LeaveCriticalSection(&ddraw_cs);
671     return DD_OK;
672 }
673
674 static HRESULT WINAPI ddraw4_SetCooperativeLevel(IDirectDraw4 *iface, HWND window, DWORD flags)
675 {
676     TRACE("iface %p, window %p, flags %#x.\n", iface, window, flags);
677
678     return ddraw7_SetCooperativeLevel((IDirectDraw7 *)ddraw_from_ddraw4(iface), window, flags);
679 }
680
681 static HRESULT WINAPI ddraw3_SetCooperativeLevel(IDirectDraw3 *iface, HWND window, DWORD flags)
682 {
683     TRACE("iface %p, window %p, flags %#x.\n", iface, window, flags);
684
685     return ddraw7_SetCooperativeLevel((IDirectDraw7 *)ddraw_from_ddraw3(iface), window, flags);
686 }
687
688 static HRESULT WINAPI ddraw2_SetCooperativeLevel(IDirectDraw2 *iface, HWND window, DWORD flags)
689 {
690     TRACE("iface %p, window %p, flags %#x.\n", iface, window, flags);
691
692     return ddraw7_SetCooperativeLevel((IDirectDraw7 *)ddraw_from_ddraw2(iface), window, flags);
693 }
694
695 static HRESULT WINAPI ddraw1_SetCooperativeLevel(IDirectDraw *iface, HWND window, DWORD flags)
696 {
697     TRACE("iface %p, window %p, flags %#x.\n", iface, window, flags);
698
699     return ddraw7_SetCooperativeLevel((IDirectDraw7 *)ddraw_from_ddraw1(iface), window, flags);
700 }
701
702 /*****************************************************************************
703  *
704  * Helper function for SetDisplayMode and RestoreDisplayMode
705  *
706  * Implements DirectDraw's SetDisplayMode, but ignores the value of
707  * ForceRefreshRate, since it is already handled by
708  * ddraw7_SetDisplayMode.  RestoreDisplayMode can use this function
709  * without worrying that ForceRefreshRate will override the refresh rate.  For
710  * argument and return value documentation, see
711  * ddraw7_SetDisplayMode.
712  *
713  *****************************************************************************/
714 static HRESULT ddraw_set_display_mode(IDirectDraw7 *iface, DWORD Width, DWORD Height,
715         DWORD BPP, DWORD RefreshRate, DWORD Flags)
716 {
717     IDirectDrawImpl *This = (IDirectDrawImpl *)iface;
718     WINED3DDISPLAYMODE Mode;
719     HRESULT hr;
720     TRACE("(%p)->(%d,%d,%d,%d,%x): Relay!\n", This, Width, Height, BPP, RefreshRate, Flags);
721
722     EnterCriticalSection(&ddraw_cs);
723     if( !Width || !Height )
724     {
725         ERR("Width=%d, Height=%d, what to do?\n", Width, Height);
726         /* It looks like Need for Speed Porsche Unleashed expects DD_OK here */
727         LeaveCriticalSection(&ddraw_cs);
728         return DD_OK;
729     }
730
731     /* Check the exclusive mode
732     if(!(This->cooperative_level & DDSCL_EXCLUSIVE))
733         return DDERR_NOEXCLUSIVEMODE;
734      * This is WRONG. Don't know if the SDK is completely
735      * wrong and if there are any conditions when DDERR_NOEXCLUSIVE
736      * is returned, but Half-Life 1.1.1.1 (Steam version)
737      * depends on this
738      */
739
740     Mode.Width = Width;
741     Mode.Height = Height;
742     Mode.RefreshRate = RefreshRate;
743     switch(BPP)
744     {
745         case 8:  Mode.Format = WINED3DFMT_P8_UINT;          break;
746         case 15: Mode.Format = WINED3DFMT_B5G5R5X1_UNORM;   break;
747         case 16: Mode.Format = WINED3DFMT_B5G6R5_UNORM;     break;
748         case 24: Mode.Format = WINED3DFMT_B8G8R8_UNORM;     break;
749         case 32: Mode.Format = WINED3DFMT_B8G8R8X8_UNORM;   break;
750     }
751
752     /* TODO: The possible return values from msdn suggest that
753      * the screen mode can't be changed if a surface is locked
754      * or some drawing is in progress
755      */
756
757     /* TODO: Lose the primary surface */
758     hr = IWineD3DDevice_SetDisplayMode(This->wineD3DDevice,
759                                        0, /* First swapchain */
760                                        &Mode);
761     LeaveCriticalSection(&ddraw_cs);
762     switch(hr)
763     {
764         case WINED3DERR_NOTAVAILABLE:       return DDERR_UNSUPPORTED;
765         default:                            return hr;
766     }
767 }
768
769 /*****************************************************************************
770  * IDirectDraw7::SetDisplayMode
771  *
772  * Sets the display screen resolution, color depth and refresh frequency
773  * when in fullscreen mode (in theory).
774  * Possible return values listed in the SDK suggest that this method fails
775  * when not in fullscreen mode, but this is wrong. Windows 2000 happily sets
776  * the display mode in DDSCL_NORMAL mode without an hwnd specified.
777  * It seems to be valid to pass 0 for With and Height, this has to be tested
778  * It could mean that the current video mode should be left as-is. (But why
779  * call it then?)
780  *
781  * Params:
782  *  Height, Width: Screen dimension
783  *  BPP: Color depth in Bits per pixel
784  *  Refreshrate: Screen refresh rate
785  *  Flags: Other stuff
786  *
787  * Returns
788  *  DD_OK on success
789  *
790  *****************************************************************************/
791 static HRESULT WINAPI ddraw7_SetDisplayMode(IDirectDraw7 *iface, DWORD Width, DWORD Height,
792         DWORD BPP, DWORD RefreshRate, DWORD Flags)
793 {
794     if (force_refresh_rate != 0)
795     {
796         TRACE("ForceRefreshRate overriding passed-in refresh rate (%d Hz) to %d Hz\n", RefreshRate, force_refresh_rate);
797         RefreshRate = force_refresh_rate;
798     }
799
800     return ddraw_set_display_mode(iface, Width, Height, BPP, RefreshRate, Flags);
801 }
802
803 static HRESULT WINAPI ddraw4_SetDisplayMode(IDirectDraw4 *iface,
804         DWORD width, DWORD height, DWORD bpp, DWORD refresh_rate, DWORD flags)
805 {
806     TRACE("iface %p, width %u, height %u, bpp %u, refresh_rate %u, flags %#x.\n",
807             iface, width, height, bpp, refresh_rate, flags);
808
809     return ddraw7_SetDisplayMode((IDirectDraw7 *)ddraw_from_ddraw4(iface),
810             width, height, bpp, refresh_rate, flags);
811 }
812
813 static HRESULT WINAPI ddraw3_SetDisplayMode(IDirectDraw3 *iface,
814         DWORD width, DWORD height, DWORD bpp, DWORD refresh_rate, DWORD flags)
815 {
816     TRACE("iface %p, width %u, height %u, bpp %u, refresh_rate %u, flags %#x.\n",
817             iface, width, height, bpp, refresh_rate, flags);
818
819     return ddraw7_SetDisplayMode((IDirectDraw7 *)ddraw_from_ddraw3(iface),
820             width, height, bpp, refresh_rate, flags);
821 }
822
823 static HRESULT WINAPI ddraw2_SetDisplayMode(IDirectDraw2 *iface,
824         DWORD width, DWORD height, DWORD bpp, DWORD refresh_rate, DWORD flags)
825 {
826     TRACE("iface %p, width %u, height %u, bpp %u, refresh_rate %u, flags %#x.\n",
827             iface, width, height, bpp, refresh_rate, flags);
828
829     return ddraw7_SetDisplayMode((IDirectDraw7 *)ddraw_from_ddraw2(iface),
830             width, height, bpp, refresh_rate, flags);
831 }
832
833 static HRESULT WINAPI ddraw1_SetDisplayMode(IDirectDraw *iface, DWORD width, DWORD height, DWORD bpp)
834 {
835     TRACE("iface %p, width %u, height %u, bpp %u.\n", iface, width, height, bpp);
836
837     return ddraw7_SetDisplayMode((IDirectDraw7 *)ddraw_from_ddraw1(iface), width, height, bpp, 0, 0);
838 }
839
840 /*****************************************************************************
841  * IDirectDraw7::RestoreDisplayMode
842  *
843  * Restores the display mode to what it was at creation time. Basically.
844  *
845  * A problem arises when there are 2 DirectDraw objects using the same hwnd:
846  *  -> DD_1 finds the screen at 1400x1050x32 when created, sets it to 640x480x16
847  *  -> DD_2 is created, finds the screen at 640x480x16, sets it to 1024x768x32
848  *  -> DD_1 is released. The screen should be left at 1024x768x32.
849  *  -> DD_2 is released. The screen should be set to 1400x1050x32
850  * This case is unhandled right now, but Empire Earth does it this way.
851  * (But perhaps there is something in SetCooperativeLevel to prevent this)
852  *
853  * The msdn says that this method resets the display mode to what it was before
854  * SetDisplayMode was called. What if SetDisplayModes is called 2 times??
855  *
856  * Returns
857  *  DD_OK on success
858  *  DDERR_NOEXCLUSIVE mode if the device isn't in fullscreen mode
859  *
860  *****************************************************************************/
861 static HRESULT WINAPI ddraw7_RestoreDisplayMode(IDirectDraw7 *iface)
862 {
863     IDirectDrawImpl *This = (IDirectDrawImpl *)iface;
864     TRACE("(%p)\n", This);
865
866     return ddraw_set_display_mode(iface, This->orig_width, This->orig_height, This->orig_bpp, 0, 0);
867 }
868
869 static HRESULT WINAPI ddraw4_RestoreDisplayMode(IDirectDraw4 *iface)
870 {
871     TRACE("iface %p.\n", iface);
872
873     return ddraw7_RestoreDisplayMode((IDirectDraw7 *)ddraw_from_ddraw4(iface));
874 }
875
876 static HRESULT WINAPI ddraw3_RestoreDisplayMode(IDirectDraw3 *iface)
877 {
878     TRACE("iface %p.\n", iface);
879
880     return ddraw7_RestoreDisplayMode((IDirectDraw7 *)ddraw_from_ddraw3(iface));
881 }
882
883 static HRESULT WINAPI ddraw2_RestoreDisplayMode(IDirectDraw2 *iface)
884 {
885     TRACE("iface %p.\n", iface);
886
887     return ddraw7_RestoreDisplayMode((IDirectDraw7 *)ddraw_from_ddraw2(iface));
888 }
889
890 static HRESULT WINAPI ddraw1_RestoreDisplayMode(IDirectDraw *iface)
891 {
892     TRACE("iface %p.\n", iface);
893
894     return ddraw7_RestoreDisplayMode((IDirectDraw7 *)ddraw_from_ddraw1(iface));
895 }
896
897 /*****************************************************************************
898  * IDirectDraw7::GetCaps
899  *
900  * Returns the drives capabilities
901  *
902  * Used for version 1, 2, 4 and 7
903  *
904  * Params:
905  *  DriverCaps: Structure to write the Hardware accelerated caps to
906  *  HelCaps: Structure to write the emulation caps to
907  *
908  * Returns
909  *  This implementation returns DD_OK only
910  *
911  *****************************************************************************/
912 static HRESULT WINAPI ddraw7_GetCaps(IDirectDraw7 *iface, DDCAPS *DriverCaps, DDCAPS *HELCaps)
913 {
914     IDirectDrawImpl *This = (IDirectDrawImpl *)iface;
915     DDCAPS caps;
916     WINED3DCAPS winecaps;
917     HRESULT hr;
918     DDSCAPS2 ddscaps = {0, 0, 0, 0};
919     TRACE("(%p)->(%p,%p)\n", This, DriverCaps, HELCaps);
920
921     /* One structure must be != NULL */
922     if( (!DriverCaps) && (!HELCaps) )
923     {
924         ERR("(%p) Invalid params to ddraw7_GetCaps\n", This);
925         return DDERR_INVALIDPARAMS;
926     }
927
928     memset(&caps, 0, sizeof(caps));
929     memset(&winecaps, 0, sizeof(winecaps));
930     caps.dwSize = sizeof(caps);
931     EnterCriticalSection(&ddraw_cs);
932     hr = IWineD3DDevice_GetDeviceCaps(This->wineD3DDevice, &winecaps);
933     if(FAILED(hr)) {
934         WARN("IWineD3DDevice::GetDeviceCaps failed\n");
935         LeaveCriticalSection(&ddraw_cs);
936         return hr;
937     }
938
939     hr = IDirectDraw7_GetAvailableVidMem(iface, &ddscaps, &caps.dwVidMemTotal, &caps.dwVidMemFree);
940     LeaveCriticalSection(&ddraw_cs);
941     if(FAILED(hr)) {
942         WARN("IDirectDraw7::GetAvailableVidMem failed\n");
943         return hr;
944     }
945
946     caps.dwCaps = winecaps.DirectDrawCaps.Caps;
947     caps.dwCaps2 = winecaps.DirectDrawCaps.Caps2;
948     caps.dwCKeyCaps = winecaps.DirectDrawCaps.CKeyCaps;
949     caps.dwFXCaps = winecaps.DirectDrawCaps.FXCaps;
950     caps.dwPalCaps = winecaps.DirectDrawCaps.PalCaps;
951     caps.ddsCaps.dwCaps = winecaps.DirectDrawCaps.ddsCaps;
952     caps.dwSVBCaps = winecaps.DirectDrawCaps.SVBCaps;
953     caps.dwSVBCKeyCaps = winecaps.DirectDrawCaps.SVBCKeyCaps;
954     caps.dwSVBFXCaps = winecaps.DirectDrawCaps.SVBFXCaps;
955     caps.dwVSBCaps = winecaps.DirectDrawCaps.VSBCaps;
956     caps.dwVSBCKeyCaps = winecaps.DirectDrawCaps.VSBCKeyCaps;
957     caps.dwVSBFXCaps = winecaps.DirectDrawCaps.VSBFXCaps;
958     caps.dwSSBCaps = winecaps.DirectDrawCaps.SSBCaps;
959     caps.dwSSBCKeyCaps = winecaps.DirectDrawCaps.SSBCKeyCaps;
960     caps.dwSSBFXCaps = winecaps.DirectDrawCaps.SSBFXCaps;
961
962     /* Even if WineD3D supports 3D rendering, remove the cap if ddraw is configured
963      * not to use it
964      */
965     if(DefaultSurfaceType == SURFACE_GDI) {
966         caps.dwCaps &= ~DDCAPS_3D;
967         caps.ddsCaps.dwCaps &= ~(DDSCAPS_3DDEVICE | DDSCAPS_MIPMAP | DDSCAPS_TEXTURE | DDSCAPS_ZBUFFER);
968     }
969     if(winecaps.DirectDrawCaps.StrideAlign != 0) {
970         caps.dwCaps |= DDCAPS_ALIGNSTRIDE;
971         caps.dwAlignStrideAlign = winecaps.DirectDrawCaps.StrideAlign;
972     }
973
974     if(DriverCaps)
975     {
976         DD_STRUCT_COPY_BYSIZE(DriverCaps, &caps);
977         if (TRACE_ON(ddraw))
978         {
979             TRACE("Driver Caps :\n");
980             DDRAW_dump_DDCAPS(DriverCaps);
981         }
982
983     }
984     if(HELCaps)
985     {
986         DD_STRUCT_COPY_BYSIZE(HELCaps, &caps);
987         if (TRACE_ON(ddraw))
988         {
989             TRACE("HEL Caps :\n");
990             DDRAW_dump_DDCAPS(HELCaps);
991         }
992     }
993
994     return DD_OK;
995 }
996
997 static HRESULT WINAPI ddraw4_GetCaps(IDirectDraw4 *iface, DDCAPS *driver_caps, DDCAPS *hel_caps)
998 {
999     TRACE("iface %p, driver_caps %p, hel_caps %p.\n", iface, driver_caps, hel_caps);
1000
1001     return ddraw7_GetCaps((IDirectDraw7 *)ddraw_from_ddraw4(iface), driver_caps, hel_caps);
1002 }
1003
1004 static HRESULT WINAPI ddraw3_GetCaps(IDirectDraw3 *iface, DDCAPS *driver_caps, DDCAPS *hel_caps)
1005 {
1006     TRACE("iface %p, driver_caps %p, hel_caps %p.\n", iface, driver_caps, hel_caps);
1007
1008     return ddraw7_GetCaps((IDirectDraw7 *)ddraw_from_ddraw3(iface), driver_caps, hel_caps);
1009 }
1010
1011 static HRESULT WINAPI ddraw2_GetCaps(IDirectDraw2 *iface, DDCAPS *driver_caps, DDCAPS *hel_caps)
1012 {
1013     TRACE("iface %p, driver_caps %p, hel_caps %p.\n", iface, driver_caps, hel_caps);
1014
1015     return ddraw7_GetCaps((IDirectDraw7 *)ddraw_from_ddraw2(iface), driver_caps, hel_caps);
1016 }
1017
1018 static HRESULT WINAPI ddraw1_GetCaps(IDirectDraw *iface, DDCAPS *driver_caps, DDCAPS *hel_caps)
1019 {
1020     TRACE("iface %p, driver_caps %p, hel_caps %p.\n", iface, driver_caps, hel_caps);
1021
1022     return ddraw7_GetCaps((IDirectDraw7 *)ddraw_from_ddraw1(iface), driver_caps, hel_caps);
1023 }
1024
1025 /*****************************************************************************
1026  * IDirectDraw7::Compact
1027  *
1028  * No idea what it does, MSDN says it's not implemented.
1029  *
1030  * Returns
1031  *  DD_OK, but this is unchecked
1032  *
1033  *****************************************************************************/
1034 static HRESULT WINAPI ddraw7_Compact(IDirectDraw7 *iface)
1035 {
1036     IDirectDrawImpl *This = (IDirectDrawImpl *)iface;
1037     TRACE("(%p)\n", This);
1038
1039     return DD_OK;
1040 }
1041
1042 static HRESULT WINAPI ddraw4_Compact(IDirectDraw4 *iface)
1043 {
1044     TRACE("iface %p.\n", iface);
1045
1046     return ddraw7_Compact((IDirectDraw7 *)ddraw_from_ddraw4(iface));
1047 }
1048
1049 static HRESULT WINAPI ddraw3_Compact(IDirectDraw3 *iface)
1050 {
1051     TRACE("iface %p.\n", iface);
1052
1053     return ddraw7_Compact((IDirectDraw7 *)ddraw_from_ddraw3(iface));
1054 }
1055
1056 static HRESULT WINAPI ddraw2_Compact(IDirectDraw2 *iface)
1057 {
1058     TRACE("iface %p.\n", iface);
1059
1060     return ddraw7_Compact((IDirectDraw7 *)ddraw_from_ddraw2(iface));
1061 }
1062
1063 static HRESULT WINAPI ddraw1_Compact(IDirectDraw *iface)
1064 {
1065     TRACE("iface %p.\n", iface);
1066
1067     return ddraw7_Compact((IDirectDraw7 *)ddraw_from_ddraw1(iface));
1068 }
1069
1070 /*****************************************************************************
1071  * IDirectDraw7::GetDisplayMode
1072  *
1073  * Returns information about the current display mode
1074  *
1075  * Exists in Version 1, 2, 4 and 7
1076  *
1077  * Params:
1078  *  DDSD: Address of a surface description structure to write the info to
1079  *
1080  * Returns
1081  *  DD_OK
1082  *
1083  *****************************************************************************/
1084 static HRESULT WINAPI ddraw7_GetDisplayMode(IDirectDraw7 *iface, DDSURFACEDESC2 *DDSD)
1085 {
1086     IDirectDrawImpl *This = (IDirectDrawImpl *)iface;
1087     HRESULT hr;
1088     WINED3DDISPLAYMODE Mode;
1089     DWORD Size;
1090     TRACE("(%p)->(%p): Relay\n", This, DDSD);
1091
1092     EnterCriticalSection(&ddraw_cs);
1093     /* This seems sane */
1094     if (!DDSD)
1095     {
1096         LeaveCriticalSection(&ddraw_cs);
1097         return DDERR_INVALIDPARAMS;
1098     }
1099
1100     /* The necessary members of LPDDSURFACEDESC and LPDDSURFACEDESC2 are equal,
1101      * so one method can be used for all versions (Hopefully)
1102      */
1103     hr = IWineD3DDevice_GetDisplayMode(This->wineD3DDevice,
1104                                       0 /* swapchain 0 */,
1105                                       &Mode);
1106     if( hr != D3D_OK )
1107     {
1108         ERR(" (%p) IWineD3DDevice::GetDisplayMode returned %08x\n", This, hr);
1109         LeaveCriticalSection(&ddraw_cs);
1110         return hr;
1111     }
1112
1113     Size = DDSD->dwSize;
1114     memset(DDSD, 0, Size);
1115
1116     DDSD->dwSize = Size;
1117     DDSD->dwFlags |= DDSD_HEIGHT | DDSD_WIDTH | DDSD_PIXELFORMAT | DDSD_PITCH | DDSD_REFRESHRATE;
1118     DDSD->dwWidth = Mode.Width;
1119     DDSD->dwHeight = Mode.Height;
1120     DDSD->u2.dwRefreshRate = 60;
1121     DDSD->ddsCaps.dwCaps = 0;
1122     DDSD->u4.ddpfPixelFormat.dwSize = sizeof(DDSD->u4.ddpfPixelFormat);
1123     PixelFormat_WineD3DtoDD(&DDSD->u4.ddpfPixelFormat, Mode.Format);
1124     DDSD->u1.lPitch = Mode.Width * DDSD->u4.ddpfPixelFormat.u1.dwRGBBitCount / 8;
1125
1126     if(TRACE_ON(ddraw))
1127     {
1128         TRACE("Returning surface desc :\n");
1129         DDRAW_dump_surface_desc(DDSD);
1130     }
1131
1132     LeaveCriticalSection(&ddraw_cs);
1133     return DD_OK;
1134 }
1135
1136 static HRESULT WINAPI ddraw4_GetDisplayMode(IDirectDraw4 *iface, DDSURFACEDESC2 *surface_desc)
1137 {
1138     TRACE("iface %p, surface_desc %p.\n", iface, surface_desc);
1139
1140     return ddraw7_GetDisplayMode((IDirectDraw7 *)ddraw_from_ddraw4(iface), surface_desc);
1141 }
1142
1143 static HRESULT WINAPI ddraw3_GetDisplayMode(IDirectDraw3 *iface, DDSURFACEDESC *surface_desc)
1144 {
1145     TRACE("iface %p, surface_desc %p.\n", iface, surface_desc);
1146
1147     return ddraw7_GetDisplayMode((IDirectDraw7 *)ddraw_from_ddraw3(iface), (DDSURFACEDESC2 *)surface_desc);
1148 }
1149
1150 static HRESULT WINAPI ddraw2_GetDisplayMode(IDirectDraw2 *iface, DDSURFACEDESC *surface_desc)
1151 {
1152     TRACE("iface %p, surface_desc %p.\n", iface, surface_desc);
1153
1154     return ddraw7_GetDisplayMode((IDirectDraw7 *)ddraw_from_ddraw2(iface), (DDSURFACEDESC2 *)surface_desc);
1155 }
1156
1157 static HRESULT WINAPI ddraw1_GetDisplayMode(IDirectDraw *iface, DDSURFACEDESC *surface_desc)
1158 {
1159     TRACE("iface %p, surface_desc %p.\n", iface, surface_desc);
1160
1161     return ddraw7_GetDisplayMode((IDirectDraw7 *)ddraw_from_ddraw1(iface), (DDSURFACEDESC2 *)surface_desc);
1162 }
1163
1164 /*****************************************************************************
1165  * IDirectDraw7::GetFourCCCodes
1166  *
1167  * Returns an array of supported FourCC codes.
1168  *
1169  * Exists in Version 1, 2, 4 and 7
1170  *
1171  * Params:
1172  *  NumCodes: Contains the number of Codes that Codes can carry. Returns the number
1173  *            of enumerated codes
1174  *  Codes: Pointer to an array of DWORDs where the supported codes are written
1175  *         to
1176  *
1177  * Returns
1178  *  Always returns DD_OK, as it's a stub for now
1179  *
1180  *****************************************************************************/
1181 static HRESULT WINAPI ddraw7_GetFourCCCodes(IDirectDraw7 *iface, DWORD *NumCodes, DWORD *Codes)
1182 {
1183     IDirectDrawImpl *This = (IDirectDrawImpl *)iface;
1184     WINED3DFORMAT formats[] = {
1185         WINED3DFMT_YUY2, WINED3DFMT_UYVY, WINED3DFMT_YV12,
1186         WINED3DFMT_DXT1, WINED3DFMT_DXT2, WINED3DFMT_DXT3, WINED3DFMT_DXT4, WINED3DFMT_DXT5,
1187         WINED3DFMT_ATI2N, WINED3DFMT_NVHU, WINED3DFMT_NVHS
1188     };
1189     DWORD count = 0, i, outsize;
1190     HRESULT hr;
1191     WINED3DDISPLAYMODE d3ddm;
1192     WINED3DSURFTYPE type = This->ImplType;
1193     TRACE("(%p)->(%p, %p)\n", This, NumCodes, Codes);
1194
1195     IWineD3DDevice_GetDisplayMode(This->wineD3DDevice,
1196                                   0 /* swapchain 0 */,
1197                                   &d3ddm);
1198
1199     outsize = NumCodes && Codes ? *NumCodes : 0;
1200
1201     if(type == SURFACE_UNKNOWN) type = SURFACE_GDI;
1202
1203     for(i = 0; i < (sizeof(formats) / sizeof(formats[0])); i++) {
1204         hr = IWineD3D_CheckDeviceFormat(This->wineD3D,
1205                                         WINED3DADAPTER_DEFAULT,
1206                                         WINED3DDEVTYPE_HAL,
1207                                         d3ddm.Format /* AdapterFormat */,
1208                                         0 /* usage */,
1209                                         WINED3DRTYPE_SURFACE,
1210                                         formats[i],
1211                                         type);
1212         if(SUCCEEDED(hr)) {
1213             if(count < outsize) {
1214                 Codes[count] = formats[i];
1215             }
1216             count++;
1217         }
1218     }
1219     if(NumCodes) {
1220         TRACE("Returning %u FourCC codes\n", count);
1221         *NumCodes = count;
1222     }
1223
1224     return DD_OK;
1225 }
1226
1227 static HRESULT WINAPI ddraw4_GetFourCCCodes(IDirectDraw4 *iface, DWORD *codes_count, DWORD *codes)
1228 {
1229     TRACE("iface %p, codes_count %p, codes %p.\n", iface, codes_count, codes);
1230
1231     return ddraw7_GetFourCCCodes((IDirectDraw7 *)ddraw_from_ddraw4(iface), codes_count, codes);
1232 }
1233
1234 static HRESULT WINAPI ddraw3_GetFourCCCodes(IDirectDraw3 *iface, DWORD *codes_count, DWORD *codes)
1235 {
1236     TRACE("iface %p, codes_count %p, codes %p.\n", iface, codes_count, codes);
1237
1238     return ddraw7_GetFourCCCodes((IDirectDraw7 *)ddraw_from_ddraw3(iface), codes_count, codes);
1239 }
1240
1241 static HRESULT WINAPI ddraw2_GetFourCCCodes(IDirectDraw2 *iface, DWORD *codes_count, DWORD *codes)
1242 {
1243     TRACE("iface %p, codes_count %p, codes %p.\n", iface, codes_count, codes);
1244
1245     return ddraw7_GetFourCCCodes((IDirectDraw7 *)ddraw_from_ddraw2(iface), codes_count, codes);
1246 }
1247
1248 static HRESULT WINAPI ddraw1_GetFourCCCodes(IDirectDraw *iface, DWORD *codes_count, DWORD *codes)
1249 {
1250     TRACE("iface %p, codes_count %p, codes %p.\n", iface, codes_count, codes);
1251
1252     return ddraw7_GetFourCCCodes((IDirectDraw7 *)ddraw_from_ddraw1(iface), codes_count, codes);
1253 }
1254
1255 /*****************************************************************************
1256  * IDirectDraw7::GetMonitorFrequency
1257  *
1258  * Returns the monitor's frequency
1259  *
1260  * Exists in Version 1, 2, 4 and 7
1261  *
1262  * Params:
1263  *  Freq: Pointer to a DWORD to write the frequency to
1264  *
1265  * Returns
1266  *  Always returns DD_OK
1267  *
1268  *****************************************************************************/
1269 static HRESULT WINAPI ddraw7_GetMonitorFrequency(IDirectDraw7 *iface, DWORD *Freq)
1270 {
1271     IDirectDrawImpl *This = (IDirectDrawImpl *)iface;
1272     TRACE("(%p)->(%p)\n", This, Freq);
1273
1274     /* Ideally this should be in WineD3D, as it concerns the screen setup,
1275      * but for now this should make the games happy
1276      */
1277     *Freq = 60;
1278     return DD_OK;
1279 }
1280
1281 static HRESULT WINAPI ddraw4_GetMonitorFrequency(IDirectDraw4 *iface, DWORD *frequency)
1282 {
1283     TRACE("iface %p, frequency %p.\n", iface, frequency);
1284
1285     return ddraw7_GetMonitorFrequency((IDirectDraw7 *)ddraw_from_ddraw4(iface), frequency);
1286 }
1287
1288 static HRESULT WINAPI ddraw3_GetMonitorFrequency(IDirectDraw3 *iface, DWORD *frequency)
1289 {
1290     TRACE("iface %p, frequency %p.\n", iface, frequency);
1291
1292     return ddraw7_GetMonitorFrequency((IDirectDraw7 *)ddraw_from_ddraw3(iface), frequency);
1293 }
1294
1295 static HRESULT WINAPI ddraw2_GetMonitorFrequency(IDirectDraw2 *iface, DWORD *frequency)
1296 {
1297     TRACE("iface %p, frequency %p.\n", iface, frequency);
1298
1299     return ddraw7_GetMonitorFrequency((IDirectDraw7 *)ddraw_from_ddraw2(iface), frequency);
1300 }
1301
1302 static HRESULT WINAPI ddraw1_GetMonitorFrequency(IDirectDraw *iface, DWORD *frequency)
1303 {
1304     TRACE("iface %p, frequency %p.\n", iface, frequency);
1305
1306     return ddraw7_GetMonitorFrequency((IDirectDraw7 *)ddraw_from_ddraw1(iface), frequency);
1307 }
1308
1309 /*****************************************************************************
1310  * IDirectDraw7::GetVerticalBlankStatus
1311  *
1312  * Returns the Vertical blank status of the monitor. This should be in WineD3D
1313  * too basically, but as it's a semi stub, I didn't create a function there
1314  *
1315  * Params:
1316  *  status: Pointer to a BOOL to be filled with the vertical blank status
1317  *
1318  * Returns
1319  *  DD_OK on success
1320  *  DDERR_INVALIDPARAMS if status is NULL
1321  *
1322  *****************************************************************************/
1323 static HRESULT WINAPI ddraw7_GetVerticalBlankStatus(IDirectDraw7 *iface, BOOL *status)
1324 {
1325     IDirectDrawImpl *This = (IDirectDrawImpl *)iface;
1326     TRACE("(%p)->(%p)\n", This, status);
1327
1328     /* This looks sane, the MSDN suggests it too */
1329     EnterCriticalSection(&ddraw_cs);
1330     if(!status)
1331     {
1332         LeaveCriticalSection(&ddraw_cs);
1333         return DDERR_INVALIDPARAMS;
1334     }
1335
1336     *status = This->fake_vblank;
1337     This->fake_vblank = !This->fake_vblank;
1338     LeaveCriticalSection(&ddraw_cs);
1339     return DD_OK;
1340 }
1341
1342 static HRESULT WINAPI ddraw4_GetVerticalBlankStatus(IDirectDraw4 *iface, BOOL *status)
1343 {
1344     TRACE("iface %p, status %p.\n", iface, status);
1345
1346     return ddraw7_GetVerticalBlankStatus((IDirectDraw7 *)ddraw_from_ddraw4(iface), status);
1347 }
1348
1349 static HRESULT WINAPI ddraw3_GetVerticalBlankStatus(IDirectDraw3 *iface, BOOL *status)
1350 {
1351     TRACE("iface %p, status %p.\n", iface, status);
1352
1353     return ddraw7_GetVerticalBlankStatus((IDirectDraw7 *)ddraw_from_ddraw3(iface), status);
1354 }
1355
1356 static HRESULT WINAPI ddraw2_GetVerticalBlankStatus(IDirectDraw2 *iface, BOOL *status)
1357 {
1358     TRACE("iface %p, status %p.\n", iface, status);
1359
1360     return ddraw7_GetVerticalBlankStatus((IDirectDraw7 *)ddraw_from_ddraw2(iface), status);
1361 }
1362
1363 static HRESULT WINAPI ddraw1_GetVerticalBlankStatus(IDirectDraw *iface, BOOL *status)
1364 {
1365     TRACE("iface %p, status %p.\n", iface, status);
1366
1367     return ddraw7_GetVerticalBlankStatus((IDirectDraw7 *)ddraw_from_ddraw1(iface), status);
1368 }
1369
1370 /*****************************************************************************
1371  * IDirectDraw7::GetAvailableVidMem
1372  *
1373  * Returns the total and free video memory
1374  *
1375  * Params:
1376  *  Caps: Specifies the memory type asked for
1377  *  total: Pointer to a DWORD to be filled with the total memory
1378  *  free: Pointer to a DWORD to be filled with the free memory
1379  *
1380  * Returns
1381  *  DD_OK on success
1382  *  DDERR_INVALIDPARAMS of free and total are NULL
1383  *
1384  *****************************************************************************/
1385 static HRESULT WINAPI ddraw7_GetAvailableVidMem(IDirectDraw7 *iface, DDSCAPS2 *Caps, DWORD *total, DWORD *free)
1386 {
1387     IDirectDrawImpl *This = (IDirectDrawImpl *)iface;
1388     TRACE("(%p)->(%p, %p, %p)\n", This, Caps, total, free);
1389
1390     if(TRACE_ON(ddraw))
1391     {
1392         TRACE("(%p) Asked for memory with description: ", This);
1393         DDRAW_dump_DDSCAPS2(Caps);
1394     }
1395     EnterCriticalSection(&ddraw_cs);
1396
1397     /* Todo: System memory vs local video memory vs non-local video memory
1398      * The MSDN also mentions differences between texture memory and other
1399      * resources, but that's not important
1400      */
1401
1402     if( (!total) && (!free) )
1403     {
1404         LeaveCriticalSection(&ddraw_cs);
1405         return DDERR_INVALIDPARAMS;
1406     }
1407
1408     if(total) *total = This->total_vidmem;
1409     if(free) *free = IWineD3DDevice_GetAvailableTextureMem(This->wineD3DDevice);
1410
1411     LeaveCriticalSection(&ddraw_cs);
1412     return DD_OK;
1413 }
1414
1415 static HRESULT WINAPI ddraw4_GetAvailableVidMem(IDirectDraw4 *iface,
1416         DDSCAPS2 *caps, DWORD *total, DWORD *free)
1417 {
1418     TRACE("iface %p, caps %p, total %p, free %p.\n", iface, caps, total, free);
1419
1420     return ddraw7_GetAvailableVidMem((IDirectDraw7 *)ddraw_from_ddraw4(iface), caps, total, free);
1421 }
1422
1423 static HRESULT WINAPI ddraw3_GetAvailableVidMem(IDirectDraw3 *iface,
1424         DDSCAPS *caps, DWORD *total, DWORD *free)
1425 {
1426     DDSCAPS2 caps2;
1427
1428     TRACE("iface %p, caps %p, total %p, free %p.\n", iface, caps, total, free);
1429
1430     DDRAW_Convert_DDSCAPS_1_To_2(caps, &caps2);
1431     return ddraw7_GetAvailableVidMem((IDirectDraw7 *)ddraw_from_ddraw3(iface), &caps2, total, free);
1432 }
1433
1434 static HRESULT WINAPI ddraw2_GetAvailableVidMem(IDirectDraw2 *iface,
1435         DDSCAPS *caps, DWORD *total, DWORD *free)
1436 {
1437     DDSCAPS2 caps2;
1438
1439     TRACE("iface %p, caps %p, total %p, free %p.\n", iface, caps, total, free);
1440
1441     DDRAW_Convert_DDSCAPS_1_To_2(caps, &caps2);
1442     return ddraw7_GetAvailableVidMem((IDirectDraw7 *)ddraw_from_ddraw2(iface), &caps2, total, free);
1443 }
1444
1445 /*****************************************************************************
1446  * IDirectDraw7::Initialize
1447  *
1448  * Initializes a DirectDraw interface.
1449  *
1450  * Params:
1451  *  GUID: Interface identifier. Well, don't know what this is really good
1452  *   for
1453  *
1454  * Returns
1455  *  Returns DD_OK on the first call,
1456  *  DDERR_ALREADYINITIALIZED on repeated calls
1457  *
1458  *****************************************************************************/
1459 static HRESULT WINAPI ddraw7_Initialize(IDirectDraw7 *iface, GUID *Guid)
1460 {
1461     IDirectDrawImpl *This = (IDirectDrawImpl *)iface;
1462     TRACE("(%p)->(%s): No-op\n", This, debugstr_guid(Guid));
1463
1464     if(This->initialized)
1465     {
1466         return DDERR_ALREADYINITIALIZED;
1467     }
1468     else
1469     {
1470         return DD_OK;
1471     }
1472 }
1473
1474 static HRESULT WINAPI ddraw4_Initialize(IDirectDraw4 *iface, GUID *guid)
1475 {
1476     TRACE("iface %p, guid %s.\n", iface, debugstr_guid(guid));
1477
1478     return ddraw7_Initialize((IDirectDraw7 *)ddraw_from_ddraw4(iface), guid);
1479 }
1480
1481 static HRESULT WINAPI ddraw3_Initialize(IDirectDraw3 *iface, GUID *guid)
1482 {
1483     TRACE("iface %p, guid %s.\n", iface, debugstr_guid(guid));
1484
1485     return ddraw7_Initialize((IDirectDraw7 *)ddraw_from_ddraw3(iface), guid);
1486 }
1487
1488 static HRESULT WINAPI ddraw2_Initialize(IDirectDraw2 *iface, GUID *guid)
1489 {
1490     TRACE("iface %p, guid %s.\n", iface, debugstr_guid(guid));
1491
1492     return ddraw7_Initialize((IDirectDraw7 *)ddraw_from_ddraw2(iface), guid);
1493 }
1494
1495 static HRESULT WINAPI ddraw1_Initialize(IDirectDraw *iface, GUID *guid)
1496 {
1497     TRACE("iface %p, guid %s.\n", iface, debugstr_guid(guid));
1498
1499     return ddraw7_Initialize((IDirectDraw7 *)ddraw_from_ddraw1(iface), guid);
1500 }
1501
1502 /*****************************************************************************
1503  * IDirectDraw7::FlipToGDISurface
1504  *
1505  * "Makes the surface that the GDI writes to the primary surface"
1506  * Looks like some windows specific thing we don't have to care about.
1507  * According to MSDN it permits GDI dialog boxes in FULLSCREEN mode. Good to
1508  * show error boxes ;)
1509  * Well, just return DD_OK.
1510  *
1511  * Returns:
1512  *  Always returns DD_OK
1513  *
1514  *****************************************************************************/
1515 static HRESULT WINAPI ddraw7_FlipToGDISurface(IDirectDraw7 *iface)
1516 {
1517     IDirectDrawImpl *This = (IDirectDrawImpl *)iface;
1518     TRACE("(%p)\n", This);
1519
1520     return DD_OK;
1521 }
1522
1523 static HRESULT WINAPI ddraw4_FlipToGDISurface(IDirectDraw4 *iface)
1524 {
1525     TRACE("iface %p.\n", iface);
1526
1527     return ddraw7_FlipToGDISurface((IDirectDraw7 *)ddraw_from_ddraw4(iface));
1528 }
1529
1530 static HRESULT WINAPI ddraw3_FlipToGDISurface(IDirectDraw3 *iface)
1531 {
1532     TRACE("iface %p.\n", iface);
1533
1534     return ddraw7_FlipToGDISurface((IDirectDraw7 *)ddraw_from_ddraw3(iface));
1535 }
1536
1537 static HRESULT WINAPI ddraw2_FlipToGDISurface(IDirectDraw2 *iface)
1538 {
1539     TRACE("iface %p.\n", iface);
1540
1541     return ddraw7_FlipToGDISurface((IDirectDraw7 *)ddraw_from_ddraw2(iface));
1542 }
1543
1544 static HRESULT WINAPI ddraw1_FlipToGDISurface(IDirectDraw *iface)
1545 {
1546     TRACE("iface %p.\n", iface);
1547
1548     return ddraw7_FlipToGDISurface((IDirectDraw7 *)ddraw_from_ddraw1(iface));
1549 }
1550
1551 /*****************************************************************************
1552  * IDirectDraw7::WaitForVerticalBlank
1553  *
1554  * This method allows applications to get in sync with the vertical blank
1555  * interval.
1556  * The wormhole demo in the DirectX 7 sdk uses this call, and it doesn't
1557  * redraw the screen, most likely because of this stub
1558  *
1559  * Parameters:
1560  *  Flags: one of DDWAITVB_BLOCKBEGIN, DDWAITVB_BLOCKBEGINEVENT
1561  *         or DDWAITVB_BLOCKEND
1562  *  h: Not used, according to MSDN
1563  *
1564  * Returns:
1565  *  Always returns DD_OK
1566  *
1567  *****************************************************************************/
1568 static HRESULT WINAPI ddraw7_WaitForVerticalBlank(IDirectDraw7 *iface, DWORD Flags, HANDLE h)
1569 {
1570     IDirectDrawImpl *This = (IDirectDrawImpl *)iface;
1571     static BOOL hide = FALSE;
1572
1573     /* This function is called often, so print the fixme only once */
1574     if(!hide)
1575     {
1576         FIXME("(%p)->(%x,%p): Stub\n", This, Flags, h);
1577         hide = TRUE;
1578     }
1579
1580     /* MSDN says DDWAITVB_BLOCKBEGINEVENT is not supported */
1581     if(Flags & DDWAITVB_BLOCKBEGINEVENT)
1582         return DDERR_UNSUPPORTED; /* unchecked */
1583
1584     return DD_OK;
1585 }
1586
1587 static HRESULT WINAPI ddraw4_WaitForVerticalBlank(IDirectDraw4 *iface, DWORD flags, HANDLE event)
1588 {
1589     TRACE("iface %p, flags %#x, event %p.\n", iface, flags, event);
1590
1591     return ddraw7_WaitForVerticalBlank((IDirectDraw7 *)ddraw_from_ddraw4(iface), flags, event);
1592 }
1593
1594 static HRESULT WINAPI ddraw3_WaitForVerticalBlank(IDirectDraw3 *iface, DWORD flags, HANDLE event)
1595 {
1596     TRACE("iface %p, flags %#x, event %p.\n", iface, flags, event);
1597
1598     return ddraw7_WaitForVerticalBlank((IDirectDraw7 *)ddraw_from_ddraw3(iface), flags, event);
1599 }
1600
1601 static HRESULT WINAPI ddraw2_WaitForVerticalBlank(IDirectDraw2 *iface, DWORD flags, HANDLE event)
1602 {
1603     TRACE("iface %p, flags %#x, event %p.\n", iface, flags, event);
1604
1605     return ddraw7_WaitForVerticalBlank((IDirectDraw7 *)ddraw_from_ddraw2(iface), flags, event);
1606 }
1607
1608 static HRESULT WINAPI ddraw1_WaitForVerticalBlank(IDirectDraw *iface, DWORD flags, HANDLE event)
1609 {
1610     TRACE("iface %p, flags %#x, event %p.\n", iface, flags, event);
1611
1612     return ddraw7_WaitForVerticalBlank((IDirectDraw7 *)ddraw_from_ddraw1(iface), flags, event);
1613 }
1614
1615 /*****************************************************************************
1616  * IDirectDraw7::GetScanLine
1617  *
1618  * Returns the scan line that is being drawn on the monitor
1619  *
1620  * Parameters:
1621  *  Scanline: Address to write the scan line value to
1622  *
1623  * Returns:
1624  *  Always returns DD_OK
1625  *
1626  *****************************************************************************/
1627 static HRESULT WINAPI ddraw7_GetScanLine(IDirectDraw7 *iface, DWORD *Scanline)
1628 {
1629     IDirectDrawImpl *This = (IDirectDrawImpl *)iface;
1630     static BOOL hide = FALSE;
1631     WINED3DDISPLAYMODE Mode;
1632
1633     /* This function is called often, so print the fixme only once */
1634     EnterCriticalSection(&ddraw_cs);
1635     if(!hide)
1636     {
1637         FIXME("(%p)->(%p): Semi-Stub\n", This, Scanline);
1638         hide = TRUE;
1639     }
1640
1641     IWineD3DDevice_GetDisplayMode(This->wineD3DDevice,
1642                                   0,
1643                                   &Mode);
1644
1645     /* Fake the line sweeping of the monitor */
1646     /* FIXME: We should synchronize with a source to keep the refresh rate */
1647     *Scanline = This->cur_scanline++;
1648     /* Assume 20 scan lines in the vertical blank */
1649     if (This->cur_scanline >= Mode.Height + 20)
1650         This->cur_scanline = 0;
1651
1652     LeaveCriticalSection(&ddraw_cs);
1653     return DD_OK;
1654 }
1655
1656 static HRESULT WINAPI ddraw4_GetScanLine(IDirectDraw4 *iface, DWORD *line)
1657 {
1658     TRACE("iface %p, line %p.\n", iface, line);
1659
1660     return ddraw7_GetScanLine((IDirectDraw7 *)ddraw_from_ddraw4(iface), line);
1661 }
1662
1663 static HRESULT WINAPI ddraw3_GetScanLine(IDirectDraw3 *iface, DWORD *line)
1664 {
1665     TRACE("iface %p, line %p.\n", iface, line);
1666
1667     return ddraw7_GetScanLine((IDirectDraw7 *)ddraw_from_ddraw3(iface), line);
1668 }
1669
1670 static HRESULT WINAPI ddraw2_GetScanLine(IDirectDraw2 *iface, DWORD *line)
1671 {
1672     TRACE("iface %p, line %p.\n", iface, line);
1673
1674     return ddraw7_GetScanLine((IDirectDraw7 *)ddraw_from_ddraw2(iface), line);
1675 }
1676
1677 static HRESULT WINAPI ddraw1_GetScanLine(IDirectDraw *iface, DWORD *line)
1678 {
1679     TRACE("iface %p, line %p.\n", iface, line);
1680
1681     return ddraw7_GetScanLine((IDirectDraw7 *)ddraw_from_ddraw1(iface), line);
1682 }
1683
1684 /*****************************************************************************
1685  * IDirectDraw7::TestCooperativeLevel
1686  *
1687  * Informs the application about the state of the video adapter, depending
1688  * on the cooperative level
1689  *
1690  * Returns:
1691  *  DD_OK if the device is in a sane state
1692  *  DDERR_NOEXCLUSIVEMODE or DDERR_EXCLUSIVEMODEALREADYSET
1693  *  if the state is not correct(See below)
1694  *
1695  *****************************************************************************/
1696 static HRESULT WINAPI ddraw7_TestCooperativeLevel(IDirectDraw7 *iface)
1697 {
1698     TRACE("iface %p.\n", iface);
1699
1700     return DD_OK;
1701 }
1702
1703 static HRESULT WINAPI ddraw4_TestCooperativeLevel(IDirectDraw4 *iface)
1704 {
1705     TRACE("iface %p.\n", iface);
1706
1707     return ddraw7_TestCooperativeLevel((IDirectDraw7 *)ddraw_from_ddraw4(iface));
1708 }
1709
1710 /*****************************************************************************
1711  * IDirectDraw7::GetGDISurface
1712  *
1713  * Returns the surface that GDI is treating as the primary surface.
1714  * For Wine this is the front buffer
1715  *
1716  * Params:
1717  *  GDISurface: Address to write the surface pointer to
1718  *
1719  * Returns:
1720  *  DD_OK if the surface was found
1721  *  DDERR_NOTFOUND if the GDI surface wasn't found
1722  *
1723  *****************************************************************************/
1724 static HRESULT WINAPI ddraw7_GetGDISurface(IDirectDraw7 *iface, IDirectDrawSurface7 **GDISurface)
1725 {
1726     IDirectDrawImpl *This = (IDirectDrawImpl *)iface;
1727     IWineD3DSurface *Surf;
1728     IDirectDrawSurface7 *ddsurf;
1729     HRESULT hr;
1730     DDSCAPS2 ddsCaps;
1731     TRACE("(%p)->(%p)\n", This, GDISurface);
1732
1733     /* Get the back buffer from the wineD3DDevice and search its
1734      * attached surfaces for the front buffer
1735      */
1736     EnterCriticalSection(&ddraw_cs);
1737     hr = IWineD3DDevice_GetBackBuffer(This->wineD3DDevice,
1738                                       0, /* SwapChain */
1739                                       0, /* first back buffer*/
1740                                       WINED3DBACKBUFFER_TYPE_MONO,
1741                                       &Surf);
1742
1743     if( (hr != D3D_OK) ||
1744         (!Surf) )
1745     {
1746         ERR("IWineD3DDevice::GetBackBuffer failed\n");
1747         LeaveCriticalSection(&ddraw_cs);
1748         return DDERR_NOTFOUND;
1749     }
1750
1751     /* GetBackBuffer AddRef()ed the surface, release it */
1752     IWineD3DSurface_Release(Surf);
1753
1754     IWineD3DSurface_GetParent(Surf,
1755                               (IUnknown **) &ddsurf);
1756     IDirectDrawSurface7_Release(ddsurf);  /* For the GetParent */
1757
1758     /* Find the front buffer */
1759     ddsCaps.dwCaps = DDSCAPS_FRONTBUFFER;
1760     hr = IDirectDrawSurface7_GetAttachedSurface(ddsurf,
1761                                                 &ddsCaps,
1762                                                 GDISurface);
1763     if(hr != DD_OK)
1764     {
1765         ERR("IDirectDrawSurface7::GetAttachedSurface failed, hr = %x\n", hr);
1766     }
1767
1768     /* The AddRef is OK this time */
1769     LeaveCriticalSection(&ddraw_cs);
1770     return hr;
1771 }
1772
1773 static HRESULT WINAPI ddraw4_GetGDISurface(IDirectDraw4 *iface, IDirectDrawSurface4 **surface)
1774 {
1775     TRACE("iface %p, surface %p.\n", iface, surface);
1776
1777     return ddraw7_GetGDISurface((IDirectDraw7 *)ddraw_from_ddraw4(iface), (IDirectDrawSurface7 **)surface);
1778 }
1779
1780 static HRESULT WINAPI ddraw3_GetGDISurface(IDirectDraw3 *iface, IDirectDrawSurface **surface)
1781 {
1782     IDirectDrawSurface7 *surface7;
1783     HRESULT hr;
1784
1785     TRACE("iface %p, surface %p.\n", iface, surface);
1786
1787     hr = ddraw7_GetGDISurface((IDirectDraw7 *)ddraw_from_ddraw3(iface), &surface7);
1788     *surface = surface7 ? (IDirectDrawSurface *)&((IDirectDrawSurfaceImpl *)surface7)->IDirectDrawSurface3_vtbl : NULL;
1789
1790     return hr;
1791 }
1792
1793 static HRESULT WINAPI ddraw2_GetGDISurface(IDirectDraw2 *iface, IDirectDrawSurface **surface)
1794 {
1795     IDirectDrawSurface7 *surface7;
1796     HRESULT hr;
1797
1798     TRACE("iface %p, surface %p.\n", iface, surface);
1799
1800     hr = ddraw7_GetGDISurface((IDirectDraw7 *)ddraw_from_ddraw2(iface), &surface7);
1801     *surface = surface7 ? (IDirectDrawSurface *)&((IDirectDrawSurfaceImpl *)surface7)->IDirectDrawSurface3_vtbl : NULL;
1802
1803     return hr;
1804 }
1805
1806 static HRESULT WINAPI ddraw1_GetGDISurface(IDirectDraw *iface, IDirectDrawSurface **surface)
1807 {
1808     IDirectDrawSurface7 *surface7;
1809     HRESULT hr;
1810
1811     TRACE("iface %p, surface %p.\n", iface, surface);
1812
1813     hr = ddraw7_GetGDISurface((IDirectDraw7 *)ddraw_from_ddraw1(iface), &surface7);
1814     *surface = surface7 ? (IDirectDrawSurface *)&((IDirectDrawSurfaceImpl *)surface7)->IDirectDrawSurface3_vtbl : NULL;
1815
1816     return hr;
1817 }
1818
1819 struct displaymodescallback_context
1820 {
1821     LPDDENUMMODESCALLBACK func;
1822     void *context;
1823 };
1824
1825 static HRESULT CALLBACK EnumDisplayModesCallbackThunk(DDSURFACEDESC2 *surface_desc, void *context)
1826 {
1827     struct displaymodescallback_context *cbcontext = context;
1828     DDSURFACEDESC desc;
1829
1830     memcpy(&desc, surface_desc, sizeof(desc));
1831     desc.dwSize = sizeof(desc);
1832
1833     return cbcontext->func(&desc, cbcontext->context);
1834 }
1835
1836 /*****************************************************************************
1837  * IDirectDraw7::EnumDisplayModes
1838  *
1839  * Enumerates the supported Display modes. The modes can be filtered with
1840  * the DDSD parameter.
1841  *
1842  * Params:
1843  *  Flags: can be DDEDM_REFRESHRATES and DDEDM_STANDARDVGAMODES
1844  *  DDSD: Surface description to filter the modes
1845  *  Context: Pointer passed back to the callback function
1846  *  cb: Application-provided callback function
1847  *
1848  * Returns:
1849  *  DD_OK on success
1850  *  DDERR_INVALIDPARAMS if the callback wasn't set
1851  *
1852  *****************************************************************************/
1853 static HRESULT WINAPI ddraw7_EnumDisplayModes(IDirectDraw7 *iface, DWORD Flags,
1854         DDSURFACEDESC2 *DDSD, void *Context, LPDDENUMMODESCALLBACK2 cb)
1855 {
1856     IDirectDrawImpl *This = (IDirectDrawImpl *)iface;
1857     unsigned int modenum, fmt;
1858     WINED3DFORMAT pixelformat = WINED3DFMT_UNKNOWN;
1859     WINED3DDISPLAYMODE mode;
1860     DDSURFACEDESC2 callback_sd;
1861     WINED3DDISPLAYMODE *enum_modes = NULL;
1862     unsigned enum_mode_count = 0, enum_mode_array_size = 0;
1863
1864     WINED3DFORMAT checkFormatList[] =
1865     {
1866         WINED3DFMT_B8G8R8X8_UNORM,
1867         WINED3DFMT_B5G6R5_UNORM,
1868         WINED3DFMT_P8_UINT,
1869     };
1870
1871     TRACE("(%p)->(%p,%p,%p): Relay\n", This, DDSD, Context, cb);
1872
1873     EnterCriticalSection(&ddraw_cs);
1874     /* This looks sane */
1875     if(!cb)
1876     {
1877         LeaveCriticalSection(&ddraw_cs);
1878         return DDERR_INVALIDPARAMS;
1879     }
1880
1881     if(DDSD)
1882     {
1883         if ((DDSD->dwFlags & DDSD_PIXELFORMAT) && (DDSD->u4.ddpfPixelFormat.dwFlags & DDPF_RGB) )
1884             pixelformat = PixelFormat_DD2WineD3D(&DDSD->u4.ddpfPixelFormat);
1885     }
1886
1887     if(!(Flags & DDEDM_REFRESHRATES))
1888     {
1889         enum_mode_array_size = 16;
1890         enum_modes = HeapAlloc(GetProcessHeap(), 0, sizeof(WINED3DDISPLAYMODE) * enum_mode_array_size);
1891         if (!enum_modes)
1892         {
1893             ERR("Out of memory\n");
1894             LeaveCriticalSection(&ddraw_cs);
1895             return DDERR_OUTOFMEMORY;
1896         }
1897     }
1898
1899     for(fmt = 0; fmt < (sizeof(checkFormatList) / sizeof(checkFormatList[0])); fmt++)
1900     {
1901         if(pixelformat != WINED3DFMT_UNKNOWN && checkFormatList[fmt] != pixelformat)
1902         {
1903             continue;
1904         }
1905
1906         modenum = 0;
1907         while(IWineD3D_EnumAdapterModes(This->wineD3D,
1908                                         WINED3DADAPTER_DEFAULT,
1909                                         checkFormatList[fmt],
1910                                         modenum++,
1911                                         &mode) == WINED3D_OK)
1912         {
1913             if(DDSD)
1914             {
1915                 if(DDSD->dwFlags & DDSD_WIDTH && mode.Width != DDSD->dwWidth) continue;
1916                 if(DDSD->dwFlags & DDSD_HEIGHT && mode.Height != DDSD->dwHeight) continue;
1917             }
1918
1919             if(!(Flags & DDEDM_REFRESHRATES))
1920             {
1921                 /* DX docs state EnumDisplayMode should return only unique modes. If DDEDM_REFRESHRATES is not set, refresh
1922                  * rate doesn't matter when determining if the mode is unique. So modes only differing in refresh rate have
1923                  * to be reduced to a single unique result in such case.
1924                  */
1925                 BOOL found = FALSE;
1926                 unsigned i;
1927
1928                 for (i = 0; i < enum_mode_count; i++)
1929                 {
1930                     if(enum_modes[i].Width == mode.Width && enum_modes[i].Height == mode.Height &&
1931                        enum_modes[i].Format == mode.Format)
1932                     {
1933                         found = TRUE;
1934                         break;
1935                     }
1936                 }
1937
1938                 if(found) continue;
1939             }
1940
1941             memset(&callback_sd, 0, sizeof(callback_sd));
1942             callback_sd.dwSize = sizeof(callback_sd);
1943             callback_sd.u4.ddpfPixelFormat.dwSize = sizeof(DDPIXELFORMAT);
1944
1945             callback_sd.dwFlags = DDSD_HEIGHT|DDSD_WIDTH|DDSD_PIXELFORMAT|DDSD_PITCH;
1946             if(Flags & DDEDM_REFRESHRATES)
1947             {
1948                 callback_sd.dwFlags |= DDSD_REFRESHRATE;
1949                 callback_sd.u2.dwRefreshRate = mode.RefreshRate;
1950             }
1951
1952             callback_sd.dwWidth = mode.Width;
1953             callback_sd.dwHeight = mode.Height;
1954
1955             PixelFormat_WineD3DtoDD(&callback_sd.u4.ddpfPixelFormat, mode.Format);
1956
1957             /* Calc pitch and DWORD align like MSDN says */
1958             callback_sd.u1.lPitch = (callback_sd.u4.ddpfPixelFormat.u1.dwRGBBitCount / 8) * mode.Width;
1959             callback_sd.u1.lPitch = (callback_sd.u1.lPitch + 3) & ~3;
1960
1961             TRACE("Enumerating %dx%dx%d @%d\n", callback_sd.dwWidth, callback_sd.dwHeight, callback_sd.u4.ddpfPixelFormat.u1.dwRGBBitCount,
1962               callback_sd.u2.dwRefreshRate);
1963
1964             if(cb(&callback_sd, Context) == DDENUMRET_CANCEL)
1965             {
1966                 TRACE("Application asked to terminate the enumeration\n");
1967                 HeapFree(GetProcessHeap(), 0, enum_modes);
1968                 LeaveCriticalSection(&ddraw_cs);
1969                 return DD_OK;
1970             }
1971
1972             if(!(Flags & DDEDM_REFRESHRATES))
1973             {
1974                 if (enum_mode_count == enum_mode_array_size)
1975                 {
1976                     WINED3DDISPLAYMODE *new_enum_modes;
1977
1978                     enum_mode_array_size *= 2;
1979                     new_enum_modes = HeapReAlloc(GetProcessHeap(), 0, enum_modes, sizeof(WINED3DDISPLAYMODE) * enum_mode_array_size);
1980
1981                     if (!new_enum_modes)
1982                     {
1983                         ERR("Out of memory\n");
1984                         HeapFree(GetProcessHeap(), 0, enum_modes);
1985                         LeaveCriticalSection(&ddraw_cs);
1986                         return DDERR_OUTOFMEMORY;
1987                     }
1988
1989                     enum_modes = new_enum_modes;
1990                 }
1991
1992                 enum_modes[enum_mode_count++] = mode;
1993             }
1994         }
1995     }
1996
1997     TRACE("End of enumeration\n");
1998     HeapFree(GetProcessHeap(), 0, enum_modes);
1999     LeaveCriticalSection(&ddraw_cs);
2000     return DD_OK;
2001 }
2002
2003 static HRESULT WINAPI ddraw4_EnumDisplayModes(IDirectDraw4 *iface, DWORD flags,
2004         DDSURFACEDESC2 *surface_desc, void *context, LPDDENUMMODESCALLBACK2 callback)
2005 {
2006     TRACE("iface %p, flags %#x, surface_desc %p, context %p, callback %p.\n",
2007             iface, flags, surface_desc, context, callback);
2008
2009     return ddraw7_EnumDisplayModes((IDirectDraw7 *)ddraw_from_ddraw4(iface), flags,
2010             surface_desc, context, callback);
2011 }
2012
2013 static HRESULT WINAPI ddraw3_EnumDisplayModes(IDirectDraw3 *iface, DWORD flags,
2014         DDSURFACEDESC *surface_desc, void *context, LPDDENUMMODESCALLBACK callback)
2015 {
2016     struct displaymodescallback_context cbcontext;
2017
2018     TRACE("iface %p, flags %#x, surface_desc %p, context %p, callback %p.\n",
2019             iface, flags, surface_desc, context, callback);
2020
2021     cbcontext.func = callback;
2022     cbcontext.context = context;
2023
2024     return ddraw7_EnumDisplayModes((IDirectDraw7 *)ddraw_from_ddraw3(iface), flags,
2025             (DDSURFACEDESC2 *)surface_desc, &cbcontext, EnumDisplayModesCallbackThunk);
2026 }
2027
2028 static HRESULT WINAPI ddraw2_EnumDisplayModes(IDirectDraw2 *iface, DWORD flags,
2029         DDSURFACEDESC *surface_desc, void *context, LPDDENUMMODESCALLBACK callback)
2030 {
2031     struct displaymodescallback_context cbcontext;
2032
2033     TRACE("iface %p, flags %#x, surface_desc %p, context %p, callback %p.\n",
2034             iface, flags, surface_desc, context, callback);
2035
2036     cbcontext.func = callback;
2037     cbcontext.context = context;
2038
2039     return ddraw7_EnumDisplayModes((IDirectDraw7 *)ddraw_from_ddraw2(iface), flags,
2040             (DDSURFACEDESC2 *)surface_desc, &cbcontext, EnumDisplayModesCallbackThunk);
2041 }
2042
2043 static HRESULT WINAPI ddraw1_EnumDisplayModes(IDirectDraw *iface, DWORD flags,
2044         DDSURFACEDESC *surface_desc, void *context, LPDDENUMMODESCALLBACK callback)
2045 {
2046     struct displaymodescallback_context cbcontext;
2047
2048     TRACE("iface %p, flags %#x, surface_desc %p, context %p, callback %p.\n",
2049             iface, flags, surface_desc, context, callback);
2050
2051     cbcontext.func = callback;
2052     cbcontext.context = context;
2053
2054     return ddraw7_EnumDisplayModes((IDirectDraw7 *)ddraw_from_ddraw1(iface), flags,
2055             (DDSURFACEDESC2 *)surface_desc, &cbcontext, EnumDisplayModesCallbackThunk);
2056 }
2057
2058 /*****************************************************************************
2059  * IDirectDraw7::EvaluateMode
2060  *
2061  * Used with IDirectDraw7::StartModeTest to test video modes.
2062  * EvaluateMode is used to pass or fail a mode, and continue with the next
2063  * mode
2064  *
2065  * Params:
2066  *  Flags: DDEM_MODEPASSED or DDEM_MODEFAILED
2067  *  Timeout: Returns the amount of seconds left before the mode would have
2068  *           been failed automatically
2069  *
2070  * Returns:
2071  *  This implementation always DD_OK, because it's a stub
2072  *
2073  *****************************************************************************/
2074 static HRESULT WINAPI ddraw7_EvaluateMode(IDirectDraw7 *iface, DWORD Flags, DWORD *Timeout)
2075 {
2076     IDirectDrawImpl *This = (IDirectDrawImpl *)iface;
2077     FIXME("(%p)->(%d,%p): Stub!\n", This, Flags, Timeout);
2078
2079     /* When implementing this, implement it in WineD3D */
2080
2081     return DD_OK;
2082 }
2083
2084 /*****************************************************************************
2085  * IDirectDraw7::GetDeviceIdentifier
2086  *
2087  * Returns the device identifier, which gives information about the driver
2088  * Our device identifier is defined at the beginning of this file.
2089  *
2090  * Params:
2091  *  DDDI: Address for the returned structure
2092  *  Flags: Can be DDGDI_GETHOSTIDENTIFIER
2093  *
2094  * Returns:
2095  *  On success it returns DD_OK
2096  *  DDERR_INVALIDPARAMS if DDDI is NULL
2097  *
2098  *****************************************************************************/
2099 static HRESULT WINAPI ddraw7_GetDeviceIdentifier(IDirectDraw7 *iface,
2100         DDDEVICEIDENTIFIER2 *DDDI, DWORD Flags)
2101 {
2102     IDirectDrawImpl *This = (IDirectDrawImpl *)iface;
2103     TRACE("(%p)->(%p,%08x)\n", This, DDDI, Flags);
2104
2105     if(!DDDI)
2106         return DDERR_INVALIDPARAMS;
2107
2108     /* The DDGDI_GETHOSTIDENTIFIER returns the information about the 2D
2109      * host adapter, if there's a secondary 3D adapter. This doesn't apply
2110      * to any modern hardware, nor is it interesting for Wine, so ignore it.
2111      * Size of DDDEVICEIDENTIFIER2 may be aligned to 8 bytes and thus 4
2112      * bytes too long. So only copy the relevant part of the structure
2113      */
2114
2115     memcpy(DDDI, &deviceidentifier, FIELD_OFFSET(DDDEVICEIDENTIFIER2, dwWHQLLevel) + sizeof(DWORD));
2116     return DD_OK;
2117 }
2118
2119 static HRESULT WINAPI ddraw4_GetDeviceIdentifier(IDirectDraw4 *iface,
2120         DDDEVICEIDENTIFIER *identifier, DWORD flags)
2121 {
2122     DDDEVICEIDENTIFIER2 identifier2;
2123     HRESULT hr;
2124
2125     TRACE("iface %p, identifier %p, flags %#x.\n", iface, identifier, flags);
2126
2127     hr = ddraw7_GetDeviceIdentifier((IDirectDraw7 *)ddraw_from_ddraw4(iface), &identifier2, flags);
2128     DDRAW_Convert_DDDEVICEIDENTIFIER_2_To_1(&identifier2, identifier);
2129
2130     return hr;
2131 }
2132
2133 /*****************************************************************************
2134  * IDirectDraw7::GetSurfaceFromDC
2135  *
2136  * Returns the Surface for a GDI device context handle.
2137  * Is this related to IDirectDrawSurface::GetDC ???
2138  *
2139  * Params:
2140  *  hdc: hdc to return the surface for
2141  *  Surface: Address to write the surface pointer to
2142  *
2143  * Returns:
2144  *  Always returns DD_OK because it's a stub
2145  *
2146  *****************************************************************************/
2147 static HRESULT WINAPI ddraw7_GetSurfaceFromDC(IDirectDraw7 *iface, HDC hdc, IDirectDrawSurface7 **Surface)
2148 {
2149     IDirectDrawImpl *This = (IDirectDrawImpl *)iface;
2150     IWineD3DSurface *wined3d_surface;
2151     HRESULT hr;
2152
2153     TRACE("iface %p, dc %p, surface %p.\n", iface, hdc, Surface);
2154
2155     if (!Surface) return E_INVALIDARG;
2156
2157     hr = IWineD3DDevice_GetSurfaceFromDC(This->wineD3DDevice, hdc, &wined3d_surface);
2158     if (FAILED(hr))
2159     {
2160         TRACE("No surface found for dc %p.\n", hdc);
2161         *Surface = NULL;
2162         return DDERR_NOTFOUND;
2163     }
2164
2165     IWineD3DSurface_GetParent(wined3d_surface, (IUnknown **)Surface);
2166     TRACE("Returning surface %p.\n", Surface);
2167     return DD_OK;
2168 }
2169
2170 static HRESULT WINAPI ddraw4_GetSurfaceFromDC(IDirectDraw4 *iface, HDC dc, IDirectDrawSurface4 **surface)
2171 {
2172     IDirectDrawSurface7 *surface7;
2173     HRESULT hr;
2174
2175     TRACE("iface %p, dc %p, surface %p.\n", iface, dc, surface);
2176
2177     if (!surface) return E_INVALIDARG;
2178
2179     hr = ddraw7_GetSurfaceFromDC((IDirectDraw7 *)ddraw_from_ddraw4(iface), dc, &surface7);
2180     *surface = surface7 ? (IDirectDrawSurface4 *)&((IDirectDrawSurfaceImpl *)surface7)->IDirectDrawSurface3_vtbl : NULL;
2181
2182     return hr;
2183 }
2184
2185 static HRESULT WINAPI ddraw3_GetSurfaceFromDC(IDirectDraw3 *iface, HDC dc, IDirectDrawSurface **surface)
2186 {
2187     TRACE("iface %p, dc %p, surface %p.\n", iface, dc, surface);
2188
2189     return ddraw7_GetSurfaceFromDC((IDirectDraw7 *)ddraw_from_ddraw3(iface),
2190             dc, (IDirectDrawSurface7 **)surface);
2191 }
2192
2193 /*****************************************************************************
2194  * IDirectDraw7::RestoreAllSurfaces
2195  *
2196  * Calls the restore method of all surfaces
2197  *
2198  * Params:
2199  *
2200  * Returns:
2201  *  Always returns DD_OK because it's a stub
2202  *
2203  *****************************************************************************/
2204 static HRESULT WINAPI ddraw7_RestoreAllSurfaces(IDirectDraw7 *iface)
2205 {
2206     IDirectDrawImpl *This = (IDirectDrawImpl *)iface;
2207     FIXME("(%p): Stub\n", This);
2208
2209     /* This isn't hard to implement: Enumerate all WineD3D surfaces,
2210      * get their parent and call their restore method. Do not implement
2211      * it in WineD3D, as restoring a surface means re-creating the
2212      * WineD3DDSurface
2213      */
2214     return DD_OK;
2215 }
2216
2217 static HRESULT WINAPI ddraw4_RestoreAllSurfaces(IDirectDraw4 *iface)
2218 {
2219     TRACE("iface %p.\n", iface);
2220
2221     return ddraw7_RestoreAllSurfaces((IDirectDraw7 *)ddraw_from_ddraw4(iface));
2222 }
2223
2224 /*****************************************************************************
2225  * IDirectDraw7::StartModeTest
2226  *
2227  * Tests the specified video modes to update the system registry with
2228  * refresh rate information. StartModeTest starts the mode test,
2229  * EvaluateMode is used to fail or pass a mode. If EvaluateMode
2230  * isn't called within 15 seconds, the mode is failed automatically
2231  *
2232  * As refresh rates are handled by the X server, I don't think this
2233  * Method is important
2234  *
2235  * Params:
2236  *  Modes: An array of mode specifications
2237  *  NumModes: The number of modes in Modes
2238  *  Flags: Some flags...
2239  *
2240  * Returns:
2241  *  Returns DDERR_TESTFINISHED if flags contains DDSMT_ISTESTREQUIRED,
2242  *  if no modes are passed, DDERR_INVALIDPARAMS is returned,
2243  *  otherwise DD_OK
2244  *
2245  *****************************************************************************/
2246 static HRESULT WINAPI ddraw7_StartModeTest(IDirectDraw7 *iface, SIZE *Modes, DWORD NumModes, DWORD Flags)
2247 {
2248     IDirectDrawImpl *This = (IDirectDrawImpl *)iface;
2249     WARN("(%p)->(%p, %d, %x): Semi-Stub, most likely harmless\n", This, Modes, NumModes, Flags);
2250
2251     /* This looks sane */
2252     if( (!Modes) || (NumModes == 0) ) return DDERR_INVALIDPARAMS;
2253
2254     /* DDSMT_ISTESTREQUIRED asks if a mode test is necessary.
2255      * As it is not, DDERR_TESTFINISHED is returned
2256      * (hopefully that's correct
2257      *
2258     if(Flags & DDSMT_ISTESTREQUIRED) return DDERR_TESTFINISHED;
2259      * well, that value doesn't (yet) exist in the wine headers, so ignore it
2260      */
2261
2262     return DD_OK;
2263 }
2264
2265 /*****************************************************************************
2266  * ddraw_recreate_surfaces_cb
2267  *
2268  * Enumeration callback for ddraw_recreate_surface.
2269  * It re-recreates the WineD3DSurface. It's pretty straightforward
2270  *
2271  *****************************************************************************/
2272 HRESULT WINAPI ddraw_recreate_surfaces_cb(IDirectDrawSurface7 *surf, DDSURFACEDESC2 *desc, void *Context)
2273 {
2274     IDirectDrawSurfaceImpl *surfImpl = (IDirectDrawSurfaceImpl *)surf;
2275     IDirectDrawImpl *This = surfImpl->ddraw;
2276     IUnknown *Parent;
2277     IWineD3DSurface *wineD3DSurface;
2278     IWineD3DSwapChain *swapchain;
2279     HRESULT hr;
2280     IWineD3DClipper *clipper = NULL;
2281
2282     WINED3DSURFACE_DESC     Desc;
2283     WINED3DFORMAT           Format;
2284     DWORD                   Usage;
2285     WINED3DPOOL             Pool;
2286
2287     WINED3DMULTISAMPLE_TYPE MultiSampleType;
2288     DWORD                   MultiSampleQuality;
2289     UINT                    Width;
2290     UINT                    Height;
2291
2292     TRACE("(%p): Enumerated Surface %p\n", This, surfImpl);
2293
2294     /* For the enumeration */
2295     IDirectDrawSurface7_Release(surf);
2296
2297     if(surfImpl->ImplType == This->ImplType) return DDENUMRET_OK; /* Continue */
2298
2299     /* Get the objects */
2300     swapchain = surfImpl->wineD3DSwapChain;
2301     surfImpl->wineD3DSwapChain = NULL;
2302     wineD3DSurface = surfImpl->WineD3DSurface;
2303
2304     /* get the clipper */
2305     IWineD3DSurface_GetClipper(wineD3DSurface, &clipper);
2306
2307     /* Get the surface properties */
2308     hr = IWineD3DSurface_GetDesc(wineD3DSurface, &Desc);
2309     if(hr != D3D_OK) return hr;
2310
2311     Format = Desc.format;
2312     Usage = Desc.usage;
2313     Pool = Desc.pool;
2314     MultiSampleType = Desc.multisample_type;
2315     MultiSampleQuality = Desc.multisample_quality;
2316     Width = Desc.width;
2317     Height = Desc.height;
2318
2319     IWineD3DSurface_GetParent(wineD3DSurface, &Parent);
2320
2321     /* Create the new surface */
2322     hr = IWineD3DDevice_CreateSurface(This->wineD3DDevice, Width, Height, Format,
2323             TRUE /* Lockable */, FALSE /* Discard */, surfImpl->mipmap_level, &surfImpl->WineD3DSurface, Usage, Pool,
2324             MultiSampleType, MultiSampleQuality, This->ImplType, Parent, &ddraw_null_wined3d_parent_ops);
2325     IUnknown_Release(Parent);
2326     if (FAILED(hr))
2327     {
2328         surfImpl->WineD3DSurface = wineD3DSurface;
2329         return hr;
2330     }
2331
2332     IWineD3DSurface_SetClipper(surfImpl->WineD3DSurface, clipper);
2333
2334     /* TODO: Copy the surface content, except for render targets */
2335
2336     /* If there's a swapchain, it owns the wined3d surfaces. So Destroy
2337      * the swapchain
2338      */
2339     if(swapchain) {
2340         /* The backbuffers have the swapchain set as well, but the primary
2341          * owns it and destroys it
2342          */
2343         if(surfImpl->surface_desc.ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE) {
2344             IWineD3DDevice_UninitGDI(This->wineD3DDevice, D3D7CB_DestroySwapChain);
2345         }
2346         surfImpl->isRenderTarget = FALSE;
2347     } else {
2348         if(IWineD3DSurface_Release(wineD3DSurface) == 0)
2349             TRACE("Surface released successful, next surface\n");
2350         else
2351             ERR("Something's still holding the old WineD3DSurface\n");
2352     }
2353
2354     surfImpl->ImplType = This->ImplType;
2355
2356     if(clipper)
2357     {
2358         IWineD3DClipper_Release(clipper);
2359     }
2360     return DDENUMRET_OK;
2361 }
2362
2363 /*****************************************************************************
2364  * ddraw_recreate_surfaces
2365  *
2366  * A function, that converts all wineD3DSurfaces to the new implementation type
2367  * It enumerates all surfaces with IWineD3DDevice::EnumSurfaces, creates a
2368  * new WineD3DSurface, copies the content and releases the old surface
2369  *
2370  *****************************************************************************/
2371 static HRESULT ddraw_recreate_surfaces(IDirectDrawImpl *This)
2372 {
2373     DDSURFACEDESC2 desc;
2374     TRACE("(%p): Switch to implementation %d\n", This, This->ImplType);
2375
2376     if(This->ImplType != SURFACE_OPENGL && This->d3d_initialized)
2377     {
2378         /* Should happen almost never */
2379         FIXME("(%p) Switching to non-opengl surfaces with d3d started. Is this a bug?\n", This);
2380         /* Shutdown d3d */
2381         IWineD3DDevice_Uninit3D(This->wineD3DDevice, D3D7CB_DestroySwapChain);
2382     }
2383     /* Contrary: D3D starting is handled by the caller, because it knows the render target */
2384
2385     memset(&desc, 0, sizeof(desc));
2386     desc.dwSize = sizeof(desc);
2387
2388     return IDirectDraw7_EnumSurfaces((IDirectDraw7 *)This, 0, &desc, This, ddraw_recreate_surfaces_cb);
2389 }
2390
2391 ULONG WINAPI D3D7CB_DestroySwapChain(IWineD3DSwapChain *pSwapChain) {
2392     IUnknown* swapChainParent;
2393     TRACE("(%p) call back\n", pSwapChain);
2394
2395     IWineD3DSwapChain_GetParent(pSwapChain, &swapChainParent);
2396     IUnknown_Release(swapChainParent);
2397     return IUnknown_Release(swapChainParent);
2398 }
2399
2400 /*****************************************************************************
2401  * ddraw_create_surface
2402  *
2403  * A helper function for IDirectDraw7::CreateSurface. It creates a new surface
2404  * with the passed parameters.
2405  *
2406  * Params:
2407  *  DDSD: Description of the surface to create
2408  *  Surf: Address to store the interface pointer at
2409  *
2410  * Returns:
2411  *  DD_OK on success
2412  *
2413  *****************************************************************************/
2414 static HRESULT ddraw_create_surface(IDirectDrawImpl *This, DDSURFACEDESC2 *pDDSD,
2415         IDirectDrawSurfaceImpl **ppSurf, UINT level)
2416 {
2417     HRESULT hr;
2418     UINT Width, Height;
2419     WINED3DFORMAT Format = WINED3DFMT_UNKNOWN;
2420     DWORD Usage = 0;
2421     WINED3DSURFTYPE ImplType = This->ImplType;
2422     WINED3DSURFACE_DESC Desc;
2423     WINED3DPOOL Pool = WINED3DPOOL_DEFAULT;
2424
2425     if (TRACE_ON(ddraw))
2426     {
2427         TRACE(" (%p) Requesting surface desc :\n", This);
2428         DDRAW_dump_surface_desc(pDDSD);
2429     }
2430
2431     /* Select the surface type, if it wasn't choosen yet */
2432     if(ImplType == SURFACE_UNKNOWN)
2433     {
2434         /* Use GL Surfaces if a D3DDEVICE Surface is requested */
2435         if(pDDSD->ddsCaps.dwCaps & DDSCAPS_3DDEVICE)
2436         {
2437             TRACE("(%p) Choosing GL surfaces because a 3DDEVICE Surface was requested\n", This);
2438             ImplType = SURFACE_OPENGL;
2439         }
2440
2441         /* Otherwise use GDI surfaces for now */
2442         else
2443         {
2444             TRACE("(%p) Choosing GDI surfaces for 2D rendering\n", This);
2445             ImplType = SURFACE_GDI;
2446         }
2447
2448         /* Policy if all surface implementations are available:
2449          * First, check if a default type was set with winecfg. If not,
2450          * try Xrender surfaces, and use them if they work. Next, check if
2451          * accelerated OpenGL is available, and use GL surfaces in this
2452          * case. If all else fails, use GDI surfaces. If a 3DDEVICE surface
2453          * was created, always use OpenGL surfaces.
2454          *
2455          * (Note: Xrender surfaces are not implemented for now, the
2456          * unaccelerated implementation uses GDI to render in Software)
2457          */
2458
2459         /* Store the type. If it needs to be changed, all WineD3DSurfaces have to
2460          * be re-created. This could be done with IDirectDrawSurface7::Restore
2461          */
2462         This->ImplType = ImplType;
2463     }
2464     else
2465     {
2466         if ((pDDSD->ddsCaps.dwCaps & DDSCAPS_3DDEVICE)
2467                 && (This->ImplType != SURFACE_OPENGL)
2468                 && DefaultSurfaceType == SURFACE_UNKNOWN)
2469         {
2470             /* We have to change to OpenGL,
2471              * and re-create all WineD3DSurfaces
2472              */
2473             ImplType = SURFACE_OPENGL;
2474             This->ImplType = ImplType;
2475             TRACE("(%p) Re-creating all surfaces\n", This);
2476             ddraw_recreate_surfaces(This);
2477             TRACE("(%p) Done recreating all surfaces\n", This);
2478         }
2479         else if(This->ImplType != SURFACE_OPENGL && pDDSD->ddsCaps.dwCaps & DDSCAPS_3DDEVICE)
2480         {
2481             WARN("The application requests a 3D capable surface, but a non-opengl surface was set in the registry\n");
2482             /* Do not fail surface creation, only fail 3D device creation */
2483         }
2484     }
2485
2486     if (!(pDDSD->ddsCaps.dwCaps & (DDSCAPS_VIDEOMEMORY | DDSCAPS_SYSTEMMEMORY)) &&
2487         !((pDDSD->ddsCaps.dwCaps & DDSCAPS_TEXTURE) && (pDDSD->ddsCaps.dwCaps2 & DDSCAPS2_TEXTUREMANAGE)) )
2488     {
2489         /* Tests show surfaces without memory flags get these flags added right after creation. */
2490         pDDSD->ddsCaps.dwCaps |= DDSCAPS_LOCALVIDMEM | DDSCAPS_VIDEOMEMORY;
2491     }
2492     /* Get the correct wined3d usage */
2493     if (pDDSD->ddsCaps.dwCaps & (DDSCAPS_PRIMARYSURFACE |
2494                                  DDSCAPS_3DDEVICE       ) )
2495     {
2496         Usage |= WINED3DUSAGE_RENDERTARGET;
2497
2498         pDDSD->ddsCaps.dwCaps |= DDSCAPS_VISIBLE;
2499     }
2500     if (pDDSD->ddsCaps.dwCaps & (DDSCAPS_OVERLAY))
2501     {
2502         Usage |= WINED3DUSAGE_OVERLAY;
2503     }
2504     if(This->depthstencil || (pDDSD->ddsCaps.dwCaps & DDSCAPS_ZBUFFER) )
2505     {
2506         /* The depth stencil creation callback sets this flag.
2507          * Set the WineD3D usage to let it know that it's a depth
2508          * Stencil surface.
2509          */
2510         Usage |= WINED3DUSAGE_DEPTHSTENCIL;
2511     }
2512     if(pDDSD->ddsCaps.dwCaps & DDSCAPS_SYSTEMMEMORY)
2513     {
2514         Pool = WINED3DPOOL_SYSTEMMEM;
2515     }
2516     else if(pDDSD->ddsCaps.dwCaps2 & DDSCAPS2_TEXTUREMANAGE)
2517     {
2518         Pool = WINED3DPOOL_MANAGED;
2519         /* Managed textures have the system memory flag set */
2520         pDDSD->ddsCaps.dwCaps |= DDSCAPS_SYSTEMMEMORY;
2521     }
2522     else if(pDDSD->ddsCaps.dwCaps & DDSCAPS_VIDEOMEMORY)
2523     {
2524         /* Videomemory adds localvidmem, this is mutually exclusive with systemmemory
2525          * and texturemanage
2526          */
2527         pDDSD->ddsCaps.dwCaps |= DDSCAPS_LOCALVIDMEM;
2528     }
2529
2530     Format = PixelFormat_DD2WineD3D(&pDDSD->u4.ddpfPixelFormat);
2531     if(Format == WINED3DFMT_UNKNOWN)
2532     {
2533         ERR("Unsupported / Unknown pixelformat\n");
2534         return DDERR_INVALIDPIXELFORMAT;
2535     }
2536
2537     /* Create the Surface object */
2538     *ppSurf = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDirectDrawSurfaceImpl));
2539     if(!*ppSurf)
2540     {
2541         ERR("(%p) Error allocating memory for a surface\n", This);
2542         return DDERR_OUTOFVIDEOMEMORY;
2543     }
2544     (*ppSurf)->lpVtbl = &IDirectDrawSurface7_Vtbl;
2545     (*ppSurf)->IDirectDrawSurface3_vtbl = &IDirectDrawSurface3_Vtbl;
2546     (*ppSurf)->IDirectDrawGammaControl_vtbl = &IDirectDrawGammaControl_Vtbl;
2547     (*ppSurf)->IDirect3DTexture2_vtbl = &IDirect3DTexture2_Vtbl;
2548     (*ppSurf)->IDirect3DTexture_vtbl = &IDirect3DTexture1_Vtbl;
2549     (*ppSurf)->ref = 1;
2550     (*ppSurf)->version = 7;
2551     TRACE("%p->version = %d\n", (*ppSurf), (*ppSurf)->version);
2552     (*ppSurf)->ddraw = This;
2553     (*ppSurf)->surface_desc.dwSize = sizeof(DDSURFACEDESC2);
2554     (*ppSurf)->surface_desc.u4.ddpfPixelFormat.dwSize = sizeof(DDPIXELFORMAT);
2555     DD_STRUCT_COPY_BYSIZE(&(*ppSurf)->surface_desc, pDDSD);
2556
2557     /* Surface attachments */
2558     (*ppSurf)->next_attached = NULL;
2559     (*ppSurf)->first_attached = *ppSurf;
2560
2561     /* Needed to re-create the surface on an implementation change */
2562     (*ppSurf)->ImplType = ImplType;
2563
2564     /* For D3DDevice creation */
2565     (*ppSurf)->isRenderTarget = FALSE;
2566
2567     /* A trace message for debugging */
2568     TRACE("(%p) Created IDirectDrawSurface implementation structure at %p\n", This, *ppSurf);
2569
2570     /* Now create the WineD3D Surface */
2571     hr = IWineD3DDevice_CreateSurface(This->wineD3DDevice, pDDSD->dwWidth, pDDSD->dwHeight, Format,
2572             TRUE /* Lockable */, FALSE /* Discard */, level, &(*ppSurf)->WineD3DSurface,
2573             Usage, Pool, WINED3DMULTISAMPLE_NONE, 0 /* MultiSampleQuality */, ImplType,
2574             (IUnknown *)*ppSurf, &ddraw_null_wined3d_parent_ops);
2575
2576     if(hr != D3D_OK)
2577     {
2578         ERR("IWineD3DDevice::CreateSurface failed. hr = %08x\n", hr);
2579         return hr;
2580     }
2581
2582     /* Increase the surface counter, and attach the surface */
2583     InterlockedIncrement(&This->surfaces);
2584     list_add_head(&This->surface_list, &(*ppSurf)->surface_list_entry);
2585
2586     /* Here we could store all created surfaces in the DirectDrawImpl structure,
2587      * But this could also be delegated to WineDDraw, as it keeps track of all its
2588      * resources. Not implemented for now, as there are more important things ;)
2589      */
2590
2591     /* Get the pixel format of the WineD3DSurface and store it.
2592      * Don't use the Format choosen above, WineD3D might have
2593      * changed it
2594      */
2595     (*ppSurf)->surface_desc.dwFlags |= DDSD_PIXELFORMAT;
2596     hr = IWineD3DSurface_GetDesc((*ppSurf)->WineD3DSurface, &Desc);
2597     if(hr != D3D_OK)
2598     {
2599         ERR("IWineD3DSurface::GetDesc failed\n");
2600         IDirectDrawSurface7_Release( (IDirectDrawSurface7 *) *ppSurf);
2601         return hr;
2602     }
2603
2604     Format = Desc.format;
2605     Width = Desc.width;
2606     Height = Desc.height;
2607
2608     if(Format == WINED3DFMT_UNKNOWN)
2609     {
2610         FIXME("IWineD3DSurface::GetDesc returned WINED3DFMT_UNKNOWN\n");
2611     }
2612     PixelFormat_WineD3DtoDD( &(*ppSurf)->surface_desc.u4.ddpfPixelFormat, Format);
2613
2614     /* Anno 1602 stores the pitch right after surface creation, so make sure it's there.
2615      * I can't LockRect() the surface here because if OpenGL surfaces are in use, the
2616      * WineD3DDevice might not be usable for 3D yet, so an extra method was created.
2617      * TODO: Test other fourcc formats
2618      */
2619     if(Format == WINED3DFMT_DXT1 || Format == WINED3DFMT_DXT2 || Format == WINED3DFMT_DXT3 ||
2620        Format == WINED3DFMT_DXT4 || Format == WINED3DFMT_DXT5)
2621     {
2622         (*ppSurf)->surface_desc.dwFlags |= DDSD_LINEARSIZE;
2623         if(Format == WINED3DFMT_DXT1)
2624         {
2625             (*ppSurf)->surface_desc.u1.dwLinearSize = max(4, Width) * max(4, Height) / 2;
2626         }
2627         else
2628         {
2629             (*ppSurf)->surface_desc.u1.dwLinearSize = max(4, Width) * max(4, Height);
2630         }
2631     }
2632     else
2633     {
2634         (*ppSurf)->surface_desc.dwFlags |= DDSD_PITCH;
2635         (*ppSurf)->surface_desc.u1.lPitch = IWineD3DSurface_GetPitch((*ppSurf)->WineD3DSurface);
2636     }
2637
2638     /* Application passed a color key? Set it! */
2639     if(pDDSD->dwFlags & DDSD_CKDESTOVERLAY)
2640     {
2641         IWineD3DSurface_SetColorKey((*ppSurf)->WineD3DSurface,
2642                                     DDCKEY_DESTOVERLAY,
2643                                     (WINEDDCOLORKEY *) &pDDSD->u3.ddckCKDestOverlay);
2644     }
2645     if(pDDSD->dwFlags & DDSD_CKDESTBLT)
2646     {
2647         IWineD3DSurface_SetColorKey((*ppSurf)->WineD3DSurface,
2648                                     DDCKEY_DESTBLT,
2649                                     (WINEDDCOLORKEY *) &pDDSD->ddckCKDestBlt);
2650     }
2651     if(pDDSD->dwFlags & DDSD_CKSRCOVERLAY)
2652     {
2653         IWineD3DSurface_SetColorKey((*ppSurf)->WineD3DSurface,
2654                                     DDCKEY_SRCOVERLAY,
2655                                     (WINEDDCOLORKEY *) &pDDSD->ddckCKSrcOverlay);
2656     }
2657     if(pDDSD->dwFlags & DDSD_CKSRCBLT)
2658     {
2659         IWineD3DSurface_SetColorKey((*ppSurf)->WineD3DSurface,
2660                                     DDCKEY_SRCBLT,
2661                                     (WINEDDCOLORKEY *) &pDDSD->ddckCKSrcBlt);
2662     }
2663     if ( pDDSD->dwFlags & DDSD_LPSURFACE)
2664     {
2665         hr = IWineD3DSurface_SetMem((*ppSurf)->WineD3DSurface, pDDSD->lpSurface);
2666         if(hr != WINED3D_OK)
2667         {
2668             /* No need for a trace here, wined3d does that for us */
2669             IDirectDrawSurface7_Release((IDirectDrawSurface7 *)*ppSurf);
2670             return hr;
2671         }
2672     }
2673
2674     return DD_OK;
2675 }
2676 /*****************************************************************************
2677  * CreateAdditionalSurfaces
2678  *
2679  * Creates a new mipmap chain.
2680  *
2681  * Params:
2682  *  root: Root surface to attach the newly created chain to
2683  *  count: number of surfaces to create
2684  *  DDSD: Description of the surface. Intentionally not a pointer to avoid side
2685  *        effects on the caller
2686  *  CubeFaceRoot: Whether the new surface is a root of a cube map face. This
2687  *                creates an additional surface without the mipmapping flags
2688  *
2689  *****************************************************************************/
2690 static HRESULT
2691 CreateAdditionalSurfaces(IDirectDrawImpl *This,
2692                          IDirectDrawSurfaceImpl *root,
2693                          UINT count,
2694                          DDSURFACEDESC2 DDSD,
2695                          BOOL CubeFaceRoot)
2696 {
2697     UINT i, j, level = 0;
2698     HRESULT hr;
2699     IDirectDrawSurfaceImpl *last = root;
2700
2701     for(i = 0; i < count; i++)
2702     {
2703         IDirectDrawSurfaceImpl *object2 = NULL;
2704
2705         /* increase the mipmap level, but only if a mipmap is created
2706          * In this case, also halve the size
2707          */
2708         if(DDSD.ddsCaps.dwCaps & DDSCAPS_MIPMAP && !CubeFaceRoot)
2709         {
2710             level++;
2711             if(DDSD.dwWidth > 1) DDSD.dwWidth /= 2;
2712             if(DDSD.dwHeight > 1) DDSD.dwHeight /= 2;
2713             /* Set the mipmap sublevel flag according to msdn */
2714             DDSD.ddsCaps.dwCaps2 |= DDSCAPS2_MIPMAPSUBLEVEL;
2715         }
2716         else
2717         {
2718             DDSD.ddsCaps.dwCaps2 &= ~DDSCAPS2_MIPMAPSUBLEVEL;
2719         }
2720         CubeFaceRoot = FALSE;
2721
2722         hr = ddraw_create_surface(This, &DDSD, &object2, level);
2723         if(hr != DD_OK)
2724         {
2725             return hr;
2726         }
2727
2728         /* Add the new surface to the complex attachment array */
2729         for(j = 0; j < MAX_COMPLEX_ATTACHED; j++)
2730         {
2731             if(last->complex_array[j]) continue;
2732             last->complex_array[j] = object2;
2733             break;
2734         }
2735         last = object2;
2736
2737         /* Remove the (possible) back buffer cap from the new surface description,
2738          * because only one surface in the flipping chain is a back buffer, one
2739          * is a front buffer, the others are just primary surfaces.
2740          */
2741         DDSD.ddsCaps.dwCaps &= ~DDSCAPS_BACKBUFFER;
2742     }
2743     return DD_OK;
2744 }
2745
2746 /* Must set all attached surfaces (e.g. mipmaps) versions as well */
2747 static void ddraw_set_surface_version(IDirectDrawSurfaceImpl *surface, UINT version)
2748 {
2749     unsigned int i;
2750
2751     TRACE("surface %p, version %u -> %u.\n", surface, surface->version, version);
2752
2753     surface->version = version;
2754     for (i = 0; i < MAX_COMPLEX_ATTACHED; ++i)
2755     {
2756         if (!surface->complex_array[i]) break;
2757         ddraw_set_surface_version(surface->complex_array[i], version);
2758     }
2759     while ((surface = surface->next_attached))
2760     {
2761         ddraw_set_surface_version(surface, version);
2762     }
2763 }
2764
2765 /*****************************************************************************
2766  * ddraw_attach_d3d_device
2767  *
2768  * Initializes the D3D capabilities of WineD3D
2769  *
2770  * Params:
2771  *  primary: The primary surface for D3D
2772  *
2773  * Returns
2774  *  DD_OK on success,
2775  *  DDERR_* otherwise
2776  *
2777  *****************************************************************************/
2778 static HRESULT ddraw_attach_d3d_device(IDirectDrawImpl *ddraw, IDirectDrawSurfaceImpl *primary)
2779 {
2780     WINED3DPRESENT_PARAMETERS localParameters;
2781     HWND window = ddraw->dest_window;
2782     HRESULT hr;
2783
2784     TRACE("ddraw %p, primary %p.\n", ddraw, primary);
2785
2786     if (!window || window == GetDesktopWindow())
2787     {
2788         window = CreateWindowExA(0, DDRAW_WINDOW_CLASS_NAME, "Hidden D3D Window",
2789                 WS_DISABLED, 0, 0, GetSystemMetrics(SM_CXSCREEN), GetSystemMetrics(SM_CYSCREEN),
2790                 NULL, NULL, NULL, NULL);
2791         if (!window)
2792         {
2793             ERR("Failed to create window, last error %#x.\n", GetLastError());
2794             return E_FAIL;
2795         }
2796
2797         ShowWindow(window, SW_HIDE);   /* Just to be sure */
2798         WARN("No window for the Direct3DDevice, created hidden window %p.\n", window);
2799     }
2800     else
2801     {
2802         TRACE("Using existing window %p for Direct3D rendering.\n", window);
2803     }
2804     ddraw->d3d_window = window;
2805
2806     /* Store the future Render Target surface */
2807     ddraw->d3d_target = primary;
2808
2809     /* Use the surface description for the device parameters, not the device
2810      * settings. The application might render to an offscreen surface. */
2811     localParameters.BackBufferWidth = primary->surface_desc.dwWidth;
2812     localParameters.BackBufferHeight = primary->surface_desc.dwHeight;
2813     localParameters.BackBufferFormat = PixelFormat_DD2WineD3D(&primary->surface_desc.u4.ddpfPixelFormat);
2814     localParameters.BackBufferCount = (primary->surface_desc.dwFlags & DDSD_BACKBUFFERCOUNT)
2815             ? primary->surface_desc.dwBackBufferCount : 0;
2816     localParameters.MultiSampleType = WINED3DMULTISAMPLE_NONE;
2817     localParameters.MultiSampleQuality = 0;
2818     localParameters.SwapEffect = WINED3DSWAPEFFECT_COPY;
2819     localParameters.hDeviceWindow = window;
2820     localParameters.Windowed = !(ddraw->cooperative_level & DDSCL_FULLSCREEN);
2821     localParameters.EnableAutoDepthStencil = TRUE;
2822     localParameters.AutoDepthStencilFormat = WINED3DFMT_D16_UNORM;
2823     localParameters.Flags = 0;
2824     localParameters.FullScreen_RefreshRateInHz = WINED3DPRESENT_RATE_DEFAULT;
2825     localParameters.PresentationInterval = WINED3DPRESENT_INTERVAL_DEFAULT;
2826
2827     /* Set this NOW, otherwise creating the depth stencil surface will cause a
2828      * recursive loop until ram or emulated video memory is full. */
2829     ddraw->d3d_initialized = TRUE;
2830     hr = IWineD3DDevice_Init3D(ddraw->wineD3DDevice, &localParameters);
2831     if (FAILED(hr))
2832     {
2833         ddraw->d3d_target = NULL;
2834         ddraw->d3d_initialized = FALSE;
2835         return hr;
2836     }
2837
2838     ddraw->declArraySize = 2;
2839     ddraw->decls = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*ddraw->decls) * ddraw->declArraySize);
2840     if (!ddraw->decls)
2841     {
2842         ERR("Error allocating an array for the converted vertex decls.\n");
2843         ddraw->declArraySize = 0;
2844         hr = IWineD3DDevice_Uninit3D(ddraw->wineD3DDevice, D3D7CB_DestroySwapChain);
2845         return E_OUTOFMEMORY;
2846     }
2847
2848     TRACE("Successfully initialized 3D.\n");
2849
2850     return DD_OK;
2851 }
2852
2853 static HRESULT ddraw_create_gdi_swapchain(IDirectDrawImpl *ddraw, IDirectDrawSurfaceImpl *primary)
2854 {
2855     WINED3DPRESENT_PARAMETERS presentation_parameters;
2856     HWND window;
2857     HRESULT hr;
2858
2859     window = ddraw->dest_window;
2860
2861     memset(&presentation_parameters, 0, sizeof(presentation_parameters));
2862
2863     /* Use the surface description for the device parameters, not the device
2864      * settings. The application might render to an offscreen surface. */
2865     presentation_parameters.BackBufferWidth = primary->surface_desc.dwWidth;
2866     presentation_parameters.BackBufferHeight = primary->surface_desc.dwHeight;
2867     presentation_parameters.BackBufferFormat = PixelFormat_DD2WineD3D(&primary->surface_desc.u4.ddpfPixelFormat);
2868     presentation_parameters.BackBufferCount = (primary->surface_desc.dwFlags & DDSD_BACKBUFFERCOUNT)
2869             ? primary->surface_desc.dwBackBufferCount : 0;
2870     presentation_parameters.MultiSampleType = WINED3DMULTISAMPLE_NONE;
2871     presentation_parameters.MultiSampleQuality = 0;
2872     presentation_parameters.SwapEffect = WINED3DSWAPEFFECT_FLIP;
2873     presentation_parameters.hDeviceWindow = window;
2874     presentation_parameters.Windowed = !(ddraw->cooperative_level & DDSCL_FULLSCREEN);
2875     presentation_parameters.EnableAutoDepthStencil = FALSE; /* Not on GDI swapchains */
2876     presentation_parameters.AutoDepthStencilFormat = 0;
2877     presentation_parameters.Flags = 0;
2878     presentation_parameters.FullScreen_RefreshRateInHz = WINED3DPRESENT_RATE_DEFAULT;
2879     presentation_parameters.PresentationInterval = WINED3DPRESENT_INTERVAL_DEFAULT;
2880
2881     ddraw->d3d_target = primary;
2882     hr = IWineD3DDevice_InitGDI(ddraw->wineD3DDevice, &presentation_parameters);
2883     ddraw->d3d_target = NULL;
2884     if (FAILED(hr))
2885     {
2886         WARN("Failed to initialize GDI ddraw implementation, hr %#x.\n", hr);
2887         primary->wineD3DSwapChain = NULL;
2888     }
2889
2890     return hr;
2891 }
2892
2893 /*****************************************************************************
2894  * IDirectDraw7::CreateSurface
2895  *
2896  * Creates a new IDirectDrawSurface object and returns its interface.
2897  *
2898  * The surface connections with wined3d are a bit tricky. Basically it works
2899  * like this:
2900  *
2901  * |------------------------|               |-----------------|
2902  * | DDraw surface          |               | WineD3DSurface  |
2903  * |                        |               |                 |
2904  * |        WineD3DSurface  |-------------->|                 |
2905  * |        Child           |<------------->| Parent          |
2906  * |------------------------|               |-----------------|
2907  *
2908  * The DDraw surface is the parent of the wined3d surface, and it releases
2909  * the WineD3DSurface when the ddraw surface is destroyed.
2910  *
2911  * However, for all surfaces which can be in a container in WineD3D,
2912  * we have to do this. These surfaces are usually complex surfaces,
2913  * so this concerns primary surfaces with a front and a back buffer,
2914  * and textures.
2915  *
2916  * |------------------------|               |-----------------|
2917  * | DDraw surface          |               | Container       |
2918  * |                        |               |                 |
2919  * |                  Child |<------------->| Parent          |
2920  * |                Texture |<------------->|                 |
2921  * |         WineD3DSurface |<----|         |          Levels |<--|
2922  * | Complex connection     |     |         |                 |   |
2923  * |------------------------|     |         |-----------------|   |
2924  *  ^                             |                               |
2925  *  |                             |                               |
2926  *  |                             |                               |
2927  *  |    |------------------|     |         |-----------------|   |
2928  *  |    | IParent          |     |-------->| WineD3DSurface  |   |
2929  *  |    |                  |               |                 |   |
2930  *  |    |            Child |<------------->| Parent          |   |
2931  *  |    |                  |               |       Container |<--|
2932  *  |    |------------------|               |-----------------|   |
2933  *  |                                                             |
2934  *  |   |----------------------|                                  |
2935  *  |   | DDraw surface 2      |                                  |
2936  *  |   |                      |                                  |
2937  *  |<->| Complex root   Child |                                  |
2938  *  |   |              Texture |                                  |
2939  *  |   |       WineD3DSurface |<----|                            |
2940  *  |   |----------------------|     |                            |
2941  *  |                                |                            |
2942  *  |    |---------------------|     |      |-----------------|   |
2943  *  |    | IParent             |     |----->| WineD3DSurface  |   |
2944  *  |    |                     |            |                 |   |
2945  *  |    |               Child |<---------->| Parent          |   |
2946  *  |    |---------------------|            |       Container |<--|
2947  *  |                                       |-----------------|   |
2948  *  |                                                             |
2949  *  |             ---More surfaces can follow---                  |
2950  *
2951  * The reason is that the IWineD3DSwapchain(render target container)
2952  * and the IWineD3DTexure(Texture container) release the parents
2953  * of their surface's children, but by releasing the complex root
2954  * the surfaces which are complexly attached to it are destroyed
2955  * too. See IDirectDrawSurface::Release for a more detailed
2956  * explanation.
2957  *
2958  * Params:
2959  *  DDSD: Description of the surface to create
2960  *  Surf: Address to store the interface pointer at
2961  *  UnkOuter: Basically for aggregation support, but ddraw doesn't support
2962  *            aggregation, so it has to be NULL
2963  *
2964  * Returns:
2965  *  DD_OK on success
2966  *  CLASS_E_NOAGGREGATION if UnkOuter != NULL
2967  *  DDERR_* if an error occurs
2968  *
2969  *****************************************************************************/
2970 static HRESULT WINAPI ddraw7_CreateSurface(IDirectDraw7 *iface,
2971         DDSURFACEDESC2 *DDSD, IDirectDrawSurface7 **Surf, IUnknown *UnkOuter)
2972 {
2973     IDirectDrawImpl *This = (IDirectDrawImpl *)iface;
2974     IDirectDrawSurfaceImpl *object = NULL;
2975     HRESULT hr;
2976     LONG extra_surfaces = 0;
2977     DDSURFACEDESC2 desc2;
2978     WINED3DDISPLAYMODE Mode;
2979     const DWORD sysvidmem = DDSCAPS_VIDEOMEMORY | DDSCAPS_SYSTEMMEMORY;
2980
2981     TRACE("(%p)->(%p,%p,%p)\n", This, DDSD, Surf, UnkOuter);
2982
2983     /* Some checks before we start */
2984     if (TRACE_ON(ddraw))
2985     {
2986         TRACE(" (%p) Requesting surface desc :\n", This);
2987         DDRAW_dump_surface_desc(DDSD);
2988     }
2989     EnterCriticalSection(&ddraw_cs);
2990
2991     if (UnkOuter != NULL)
2992     {
2993         FIXME("(%p) : outer != NULL?\n", This);
2994         LeaveCriticalSection(&ddraw_cs);
2995         return CLASS_E_NOAGGREGATION; /* unchecked */
2996     }
2997
2998     if (Surf == NULL)
2999     {
3000         FIXME("(%p) You want to get back a surface? Don't give NULL ptrs!\n", This);
3001         LeaveCriticalSection(&ddraw_cs);
3002         return E_POINTER; /* unchecked */
3003     }
3004
3005     if (!(DDSD->dwFlags & DDSD_CAPS))
3006     {
3007         /* DVIDEO.DLL does forget the DDSD_CAPS flag ... *sigh* */
3008         DDSD->dwFlags |= DDSD_CAPS;
3009     }
3010
3011     if (DDSD->ddsCaps.dwCaps & DDSCAPS_ALLOCONLOAD)
3012     {
3013         /* If the surface is of the 'alloconload' type, ignore the LPSURFACE field */
3014         DDSD->dwFlags &= ~DDSD_LPSURFACE;
3015     }
3016
3017     if ((DDSD->dwFlags & DDSD_LPSURFACE) && (DDSD->lpSurface == NULL))
3018     {
3019         /* Frank Herbert's Dune specifies a null pointer for the surface, ignore the LPSURFACE field */
3020         WARN("(%p) Null surface pointer specified, ignore it!\n", This);
3021         DDSD->dwFlags &= ~DDSD_LPSURFACE;
3022     }
3023
3024     if((DDSD->ddsCaps.dwCaps & (DDSCAPS_FLIP | DDSCAPS_PRIMARYSURFACE)) == (DDSCAPS_FLIP | DDSCAPS_PRIMARYSURFACE) &&
3025        !(This->cooperative_level & DDSCL_EXCLUSIVE))
3026     {
3027         TRACE("(%p): Attempt to create a flipable primary surface without DDSCL_EXCLUSIVE set\n", This);
3028         *Surf = NULL;
3029         LeaveCriticalSection(&ddraw_cs);
3030         return DDERR_NOEXCLUSIVEMODE;
3031     }
3032
3033     if(DDSD->ddsCaps.dwCaps & (DDSCAPS_FRONTBUFFER | DDSCAPS_BACKBUFFER)) {
3034         WARN("Application tried to create an explicit front or back buffer\n");
3035         LeaveCriticalSection(&ddraw_cs);
3036         return DDERR_INVALIDCAPS;
3037     }
3038
3039     if((DDSD->ddsCaps.dwCaps & sysvidmem) == sysvidmem)
3040     {
3041         /* This is a special switch in ddrawex.dll, but not allowed in ddraw.dll */
3042         WARN("Application tries to put the surface in both system and video memory\n");
3043         LeaveCriticalSection(&ddraw_cs);
3044         *Surf = NULL;
3045         return DDERR_INVALIDCAPS;
3046     }
3047
3048     /* Check cube maps but only if the size includes them */
3049     if (DDSD->dwSize >= sizeof(DDSURFACEDESC2))
3050     {
3051         if(DDSD->ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP_ALLFACES &&
3052            !(DDSD->ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP))
3053         {
3054             WARN("Cube map faces requested without cube map flag\n");
3055             LeaveCriticalSection(&ddraw_cs);
3056             return DDERR_INVALIDCAPS;
3057         }
3058         if(DDSD->ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP &&
3059            (DDSD->ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP_ALLFACES) == 0)
3060         {
3061             WARN("Cube map without faces requested\n");
3062             LeaveCriticalSection(&ddraw_cs);
3063             return DDERR_INVALIDPARAMS;
3064         }
3065
3066         /* Quick tests confirm those can be created, but we don't do that yet */
3067         if(DDSD->ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP &&
3068            (DDSD->ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP_ALLFACES) != DDSCAPS2_CUBEMAP_ALLFACES)
3069         {
3070             FIXME("Partial cube maps not supported yet\n");
3071         }
3072     }
3073
3074     /* According to the msdn this flag is ignored by CreateSurface */
3075     if (DDSD->dwSize >= sizeof(DDSURFACEDESC2))
3076         DDSD->ddsCaps.dwCaps2 &= ~DDSCAPS2_MIPMAPSUBLEVEL;
3077
3078     /* Modify some flags */
3079     memset(&desc2, 0, sizeof(desc2));
3080     desc2.dwSize = sizeof(desc2);   /* For the struct copy */
3081     DD_STRUCT_COPY_BYSIZE(&desc2, DDSD);
3082     desc2.dwSize = sizeof(desc2);   /* To override a possibly smaller size */
3083     desc2.u4.ddpfPixelFormat.dwSize=sizeof(DDPIXELFORMAT); /* Just to be sure */
3084
3085     /* Get the video mode from WineD3D - we will need it */
3086     hr = IWineD3DDevice_GetDisplayMode(This->wineD3DDevice,
3087                                        0, /* Swapchain 0 */
3088                                        &Mode);
3089     if(FAILED(hr))
3090     {
3091         ERR("Failed to read display mode from wined3d\n");
3092         switch(This->orig_bpp)
3093         {
3094             case 8:
3095                 Mode.Format = WINED3DFMT_P8_UINT;
3096                 break;
3097
3098             case 15:
3099                 Mode.Format = WINED3DFMT_B5G5R5X1_UNORM;
3100                 break;
3101
3102             case 16:
3103                 Mode.Format = WINED3DFMT_B5G6R5_UNORM;
3104                 break;
3105
3106             case 24:
3107                 Mode.Format = WINED3DFMT_B8G8R8_UNORM;
3108                 break;
3109
3110             case 32:
3111                 Mode.Format = WINED3DFMT_B8G8R8X8_UNORM;
3112                 break;
3113         }
3114         Mode.Width = This->orig_width;
3115         Mode.Height = This->orig_height;
3116     }
3117
3118     /* No pixelformat given? Use the current screen format */
3119     if(!(desc2.dwFlags & DDSD_PIXELFORMAT))
3120     {
3121         desc2.dwFlags |= DDSD_PIXELFORMAT;
3122         desc2.u4.ddpfPixelFormat.dwSize=sizeof(DDPIXELFORMAT);
3123
3124         /* Wait: It could be a Z buffer */
3125         if(desc2.ddsCaps.dwCaps & DDSCAPS_ZBUFFER)
3126         {
3127             switch(desc2.u2.dwMipMapCount) /* Who had this glorious idea? */
3128             {
3129                 case 15:
3130                     PixelFormat_WineD3DtoDD(&desc2.u4.ddpfPixelFormat, WINED3DFMT_S1_UINT_D15_UNORM);
3131                     break;
3132                 case 16:
3133                     PixelFormat_WineD3DtoDD(&desc2.u4.ddpfPixelFormat, WINED3DFMT_D16_UNORM);
3134                     break;
3135                 case 24:
3136                     PixelFormat_WineD3DtoDD(&desc2.u4.ddpfPixelFormat, WINED3DFMT_X8D24_UNORM);
3137                     break;
3138                 case 32:
3139                     PixelFormat_WineD3DtoDD(&desc2.u4.ddpfPixelFormat, WINED3DFMT_D32_UNORM);
3140                     break;
3141                 default:
3142                     ERR("Unknown Z buffer bit depth\n");
3143             }
3144         }
3145         else
3146         {
3147             PixelFormat_WineD3DtoDD(&desc2.u4.ddpfPixelFormat, Mode.Format);
3148         }
3149     }
3150
3151     /* No Width or no Height? Use the original screen size
3152      */
3153     if(!(desc2.dwFlags & DDSD_WIDTH) ||
3154        !(desc2.dwFlags & DDSD_HEIGHT) )
3155     {
3156         /* Invalid for non-render targets */
3157         if(!(desc2.ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE))
3158         {
3159             WARN("Creating a non-Primary surface without Width or Height info, returning DDERR_INVALIDPARAMS\n");
3160             *Surf = NULL;
3161             LeaveCriticalSection(&ddraw_cs);
3162             return DDERR_INVALIDPARAMS;
3163         }
3164
3165         desc2.dwFlags |= DDSD_WIDTH | DDSD_HEIGHT;
3166         desc2.dwWidth = Mode.Width;
3167         desc2.dwHeight = Mode.Height;
3168     }
3169
3170     /* Mipmap count fixes */
3171     if(desc2.ddsCaps.dwCaps & DDSCAPS_MIPMAP)
3172     {
3173         if(desc2.ddsCaps.dwCaps & DDSCAPS_COMPLEX)
3174         {
3175             if(desc2.dwFlags & DDSD_MIPMAPCOUNT)
3176             {
3177                 /* Mipmap count is given, should not be 0 */
3178                 if( desc2.u2.dwMipMapCount == 0 )
3179                 {
3180                     LeaveCriticalSection(&ddraw_cs);
3181                     return DDERR_INVALIDPARAMS;
3182                 }
3183             }
3184             else
3185             {
3186                 /* Undocumented feature: Create sublevels until
3187                  * either the width or the height is 1
3188                  */
3189                 DWORD min = desc2.dwWidth < desc2.dwHeight ?
3190                             desc2.dwWidth : desc2.dwHeight;
3191                 desc2.u2.dwMipMapCount = 0;
3192                 while( min )
3193                 {
3194                     desc2.u2.dwMipMapCount += 1;
3195                     min >>= 1;
3196                 }
3197             }
3198         }
3199         else
3200         {
3201             /* Not-complex mipmap -> Mipmapcount = 1 */
3202             desc2.u2.dwMipMapCount = 1;
3203         }
3204         extra_surfaces = desc2.u2.dwMipMapCount - 1;
3205
3206         /* There's a mipmap count in the created surface in any case */
3207         desc2.dwFlags |= DDSD_MIPMAPCOUNT;
3208     }
3209     /* If no mipmap is given, the texture has only one level */
3210
3211     /* The first surface is a front buffer, the back buffer is created afterwards */
3212     if( (desc2.dwFlags & DDSD_CAPS) && (desc2.ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE) )
3213     {
3214         desc2.ddsCaps.dwCaps |= DDSCAPS_FRONTBUFFER;
3215     }
3216
3217     /* The root surface in a cube map is positive x */
3218     if(desc2.ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP)
3219     {
3220         desc2.ddsCaps.dwCaps2 &= ~DDSCAPS2_CUBEMAP_ALLFACES;
3221         desc2.ddsCaps.dwCaps2 |=  DDSCAPS2_CUBEMAP_POSITIVEX;
3222     }
3223
3224     /* Create the first surface */
3225     hr = ddraw_create_surface(This, &desc2, &object, 0);
3226     if( hr != DD_OK)
3227     {
3228         ERR("ddraw_create_surface failed, hr %#x.\n", hr);
3229         LeaveCriticalSection(&ddraw_cs);
3230         return hr;
3231     }
3232     object->is_complex_root = TRUE;
3233
3234     *Surf = (IDirectDrawSurface7 *)object;
3235
3236     /* Create Additional surfaces if necessary
3237      * This applies to Primary surfaces which have a back buffer count
3238      * set, but not to mipmap textures. In case of Mipmap textures,
3239      * wineD3D takes care of the creation of additional surfaces
3240      */
3241     if(DDSD->dwFlags & DDSD_BACKBUFFERCOUNT)
3242     {
3243         extra_surfaces = DDSD->dwBackBufferCount;
3244         desc2.ddsCaps.dwCaps &= ~DDSCAPS_FRONTBUFFER; /* It's not a front buffer */
3245         desc2.ddsCaps.dwCaps |= DDSCAPS_BACKBUFFER;
3246         desc2.dwBackBufferCount = 0;
3247     }
3248
3249     hr = DD_OK;
3250     if(desc2.ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP)
3251     {
3252         desc2.ddsCaps.dwCaps2 &= ~DDSCAPS2_CUBEMAP_ALLFACES;
3253         desc2.ddsCaps.dwCaps2 |=  DDSCAPS2_CUBEMAP_NEGATIVEZ;
3254         hr |= CreateAdditionalSurfaces(This, object, extra_surfaces + 1, desc2, TRUE);
3255         desc2.ddsCaps.dwCaps2 &= ~DDSCAPS2_CUBEMAP_NEGATIVEZ;
3256         desc2.ddsCaps.dwCaps2 |=  DDSCAPS2_CUBEMAP_POSITIVEZ;
3257         hr |= CreateAdditionalSurfaces(This, object, extra_surfaces + 1, desc2, TRUE);
3258         desc2.ddsCaps.dwCaps2 &= ~DDSCAPS2_CUBEMAP_POSITIVEZ;
3259         desc2.ddsCaps.dwCaps2 |=  DDSCAPS2_CUBEMAP_NEGATIVEY;
3260         hr |= CreateAdditionalSurfaces(This, object, extra_surfaces + 1, desc2, TRUE);
3261         desc2.ddsCaps.dwCaps2 &= ~DDSCAPS2_CUBEMAP_NEGATIVEY;
3262         desc2.ddsCaps.dwCaps2 |=  DDSCAPS2_CUBEMAP_POSITIVEY;
3263         hr |= CreateAdditionalSurfaces(This, object, extra_surfaces + 1, desc2, TRUE);
3264         desc2.ddsCaps.dwCaps2 &= ~DDSCAPS2_CUBEMAP_POSITIVEY;
3265         desc2.ddsCaps.dwCaps2 |=  DDSCAPS2_CUBEMAP_NEGATIVEX;
3266         hr |= CreateAdditionalSurfaces(This, object, extra_surfaces + 1, desc2, TRUE);
3267         desc2.ddsCaps.dwCaps2 &= ~DDSCAPS2_CUBEMAP_NEGATIVEX;
3268         desc2.ddsCaps.dwCaps2 |=  DDSCAPS2_CUBEMAP_POSITIVEX;
3269     }
3270
3271     hr |= CreateAdditionalSurfaces(This, object, extra_surfaces, desc2, FALSE);
3272     if(hr != DD_OK)
3273     {
3274         /* This destroys and possibly created surfaces too */
3275         IDirectDrawSurface_Release((IDirectDrawSurface7 *)object);
3276         LeaveCriticalSection(&ddraw_cs);
3277         return hr;
3278     }
3279
3280     /* If the implementation is OpenGL and there's no d3ddevice, attach a d3ddevice
3281      * But attach the d3ddevice only if the currently created surface was
3282      * a primary surface (2D app in 3D mode) or a 3DDEVICE surface (3D app)
3283      * The only case I can think of where this doesn't apply is when a
3284      * 2D app was configured by the user to run with OpenGL and it didn't create
3285      * the render target as first surface. In this case the render target creation
3286      * will cause the 3D init.
3287      */
3288     if( (This->ImplType == SURFACE_OPENGL) && !(This->d3d_initialized) &&
3289         desc2.ddsCaps.dwCaps & (DDSCAPS_PRIMARYSURFACE | DDSCAPS_3DDEVICE) )
3290     {
3291         IDirectDrawSurfaceImpl *target = object, *surface;
3292         struct list *entry;
3293
3294         /* Search for the primary to use as render target */
3295         LIST_FOR_EACH(entry, &This->surface_list)
3296         {
3297             surface = LIST_ENTRY(entry, IDirectDrawSurfaceImpl, surface_list_entry);
3298             if((surface->surface_desc.ddsCaps.dwCaps & (DDSCAPS_PRIMARYSURFACE | DDSCAPS_FRONTBUFFER)) ==
3299                (DDSCAPS_PRIMARYSURFACE | DDSCAPS_FRONTBUFFER))
3300             {
3301                 /* found */
3302                 target = surface;
3303                 TRACE("Using primary %p as render target\n", target);
3304                 break;
3305             }
3306         }
3307
3308         TRACE("(%p) Attaching a D3DDevice, rendertarget = %p\n", This, target);
3309         hr = ddraw_attach_d3d_device(This, target);
3310         if (hr != D3D_OK)
3311         {
3312             IDirectDrawSurfaceImpl *release_surf;
3313             ERR("ddraw_attach_d3d_device failed, hr %#x\n", hr);
3314             *Surf = NULL;
3315
3316             /* The before created surface structures are in an incomplete state here.
3317              * WineD3D holds the reference on the IParents, and it released them on the failure
3318              * already. So the regular release method implementation would fail on the attempt
3319              * to destroy either the IParents or the swapchain. So free the surface here.
3320              * The surface structure here is a list, not a tree, because onscreen targets
3321              * cannot be cube textures
3322              */
3323             while(object)
3324             {
3325                 release_surf = object;
3326                 object = object->complex_array[0];
3327                 ddraw_surface_destroy(release_surf);
3328             }
3329             LeaveCriticalSection(&ddraw_cs);
3330             return hr;
3331         }
3332     }
3333     else if(!(This->d3d_initialized) && desc2.ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE)
3334     {
3335         ddraw_create_gdi_swapchain(This, object);
3336     }
3337
3338     /* Addref the ddraw interface to keep an reference for each surface */
3339     IDirectDraw7_AddRef(iface);
3340     object->ifaceToRelease = (IUnknown *) iface;
3341
3342     /* Create a WineD3DTexture if a texture was requested */
3343     if(desc2.ddsCaps.dwCaps & DDSCAPS_TEXTURE)
3344     {
3345         UINT levels;
3346         WINED3DFORMAT Format;
3347         WINED3DPOOL Pool = WINED3DPOOL_DEFAULT;
3348
3349         This->tex_root = object;
3350
3351         if(desc2.ddsCaps.dwCaps & DDSCAPS_MIPMAP)
3352         {
3353             /* a mipmap is created, create enough levels */
3354             levels = desc2.u2.dwMipMapCount;
3355         }
3356         else
3357         {
3358             /* No mipmap is created, create one level */
3359             levels = 1;
3360         }
3361
3362         /* DDSCAPS_SYSTEMMEMORY textures are in WINED3DPOOL_SYSTEMMEM */
3363         if(DDSD->ddsCaps.dwCaps & DDSCAPS_SYSTEMMEMORY)
3364         {
3365             Pool = WINED3DPOOL_SYSTEMMEM;
3366         }
3367         /* Should I forward the MANAGED cap to the managed pool ? */
3368
3369         /* Get the format. It's set already by CreateNewSurface */
3370         Format = PixelFormat_DD2WineD3D(&object->surface_desc.u4.ddpfPixelFormat);
3371
3372         /* The surfaces are already created, the callback only
3373          * passes the IWineD3DSurface to WineD3D
3374          */
3375         if(desc2.ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP)
3376         {
3377             hr = IWineD3DDevice_CreateCubeTexture(This->wineD3DDevice, DDSD->dwWidth /* Edgelength */,
3378                     levels, 0 /* usage */, Format, Pool, (IWineD3DCubeTexture **)&object->wineD3DTexture,
3379                     (IUnknown *)object, &ddraw_null_wined3d_parent_ops);
3380         }
3381         else
3382         {
3383             hr = IWineD3DDevice_CreateTexture(This->wineD3DDevice, DDSD->dwWidth, DDSD->dwHeight, levels,
3384                     0 /* usage */, Format, Pool, (IWineD3DTexture **)&object->wineD3DTexture,
3385                     (IUnknown *)object, &ddraw_null_wined3d_parent_ops);
3386         }
3387         This->tex_root = NULL;
3388     }
3389
3390     LeaveCriticalSection(&ddraw_cs);
3391     return hr;
3392 }
3393
3394 static HRESULT WINAPI ddraw4_CreateSurface(IDirectDraw4 *iface,
3395         DDSURFACEDESC2 *surface_desc, IDirectDrawSurface4 **surface, IUnknown *outer_unknown)
3396 {
3397     IDirectDrawImpl *ddraw = ddraw_from_ddraw4(iface);
3398     IDirectDrawSurfaceImpl *impl;
3399     HRESULT hr;
3400
3401     TRACE("iface %p, surface_desc %p, surface %p, outer_unknown %p.\n",
3402             iface, surface_desc, surface, outer_unknown);
3403
3404     hr = ddraw7_CreateSurface((IDirectDraw7 *)ddraw, surface_desc, (IDirectDrawSurface7 **)surface, outer_unknown);
3405     impl = (IDirectDrawSurfaceImpl *)*surface;
3406     if (SUCCEEDED(hr) && impl)
3407     {
3408         ddraw_set_surface_version(impl, 4);
3409         IDirectDraw7_Release((IDirectDraw7 *)ddraw);
3410         IDirectDraw4_AddRef(iface);
3411         impl->ifaceToRelease = (IUnknown *)iface;
3412     }
3413
3414     return hr;
3415 }
3416
3417 static HRESULT WINAPI ddraw3_CreateSurface(IDirectDraw3 *iface,
3418         DDSURFACEDESC *surface_desc, IDirectDrawSurface **surface, IUnknown *outer_unknown)
3419 {
3420     IDirectDrawImpl *ddraw = ddraw_from_ddraw3(iface);
3421     IDirectDrawSurface7 *surface7;
3422     IDirectDrawSurfaceImpl *impl;
3423     HRESULT hr;
3424
3425     TRACE("iface %p, surface_desc %p, surface %p, outer_unknown %p.\n",
3426             iface, surface_desc, surface, outer_unknown);
3427
3428     hr = ddraw7_CreateSurface((IDirectDraw7 *)ddraw, (DDSURFACEDESC2 *)surface_desc, &surface7, outer_unknown);
3429     if (FAILED(hr))
3430     {
3431         *surface = NULL;
3432         return hr;
3433     }
3434
3435     impl = (IDirectDrawSurfaceImpl *)surface7;
3436     *surface = (IDirectDrawSurface *)&impl->IDirectDrawSurface3_vtbl;
3437     ddraw_set_surface_version(impl, 3);
3438     IDirectDraw7_Release((IDirectDraw7 *)ddraw);
3439     IDirectDraw3_AddRef(iface);
3440     impl->ifaceToRelease = (IUnknown *)iface;
3441
3442     return hr;
3443 }
3444
3445 static HRESULT WINAPI ddraw2_CreateSurface(IDirectDraw2 *iface,
3446         DDSURFACEDESC *surface_desc, IDirectDrawSurface **surface, IUnknown *outer_unknown)
3447 {
3448     IDirectDrawImpl *ddraw = ddraw_from_ddraw2(iface);
3449     IDirectDrawSurface7 *surface7;
3450     IDirectDrawSurfaceImpl *impl;
3451     HRESULT hr;
3452
3453     TRACE("iface %p, surface_desc %p, surface %p, outer_unknown %p.\n",
3454             iface, surface_desc, surface, outer_unknown);
3455
3456     hr = ddraw7_CreateSurface((IDirectDraw7 *)ddraw, (DDSURFACEDESC2 *)surface_desc, &surface7, outer_unknown);
3457     if (FAILED(hr))
3458     {
3459         *surface = NULL;
3460         return hr;
3461     }
3462
3463     impl = (IDirectDrawSurfaceImpl *)surface7;
3464     *surface = (IDirectDrawSurface *)&impl->IDirectDrawSurface3_vtbl;
3465     ddraw_set_surface_version(impl, 2);
3466     IDirectDraw7_Release((IDirectDraw7 *)ddraw);
3467     impl->ifaceToRelease = NULL;
3468
3469     return hr;
3470 }
3471
3472 static HRESULT WINAPI ddraw1_CreateSurface(IDirectDraw *iface,
3473         DDSURFACEDESC *surface_desc, IDirectDrawSurface **surface, IUnknown *outer_unknown)
3474 {
3475     IDirectDrawImpl *ddraw = ddraw_from_ddraw1(iface);
3476     IDirectDrawSurface7 *surface7;
3477     IDirectDrawSurfaceImpl *impl;
3478     HRESULT hr;
3479
3480     TRACE("iface %p, surface_desc %p, surface %p, outer_unknown %p.\n",
3481             iface, surface_desc, surface, outer_unknown);
3482
3483     /* Remove front buffer flag, this causes failure in v7, and its added to normal
3484      * primaries anyway. */
3485     surface_desc->ddsCaps.dwCaps &= ~DDSCAPS_FRONTBUFFER;
3486     hr = ddraw7_CreateSurface((IDirectDraw7 *)ddraw, (DDSURFACEDESC2 *)surface_desc, &surface7, outer_unknown);
3487     if (FAILED(hr))
3488     {
3489         *surface = NULL;
3490         return hr;
3491     }
3492
3493     impl = (IDirectDrawSurfaceImpl *)surface7;
3494     *surface = (IDirectDrawSurface *)&impl->IDirectDrawSurface3_vtbl;
3495     ddraw_set_surface_version(impl, 1);
3496     IDirectDraw7_Release((IDirectDraw7 *)ddraw);
3497     impl->ifaceToRelease = NULL;
3498
3499     return hr;
3500 }
3501
3502 #define DDENUMSURFACES_SEARCHTYPE (DDENUMSURFACES_CANBECREATED|DDENUMSURFACES_DOESEXIST)
3503 #define DDENUMSURFACES_MATCHTYPE (DDENUMSURFACES_ALL|DDENUMSURFACES_MATCH|DDENUMSURFACES_NOMATCH)
3504
3505 static BOOL
3506 Main_DirectDraw_DDPIXELFORMAT_Match(const DDPIXELFORMAT *requested,
3507                                     const DDPIXELFORMAT *provided)
3508 {
3509     /* Some flags must be present in both or neither for a match. */
3510     static const DWORD must_match = DDPF_PALETTEINDEXED1 | DDPF_PALETTEINDEXED2
3511         | DDPF_PALETTEINDEXED4 | DDPF_PALETTEINDEXED8 | DDPF_FOURCC
3512         | DDPF_ZBUFFER | DDPF_STENCILBUFFER;
3513
3514     if ((requested->dwFlags & provided->dwFlags) != requested->dwFlags)
3515         return FALSE;
3516
3517     if ((requested->dwFlags & must_match) != (provided->dwFlags & must_match))
3518         return FALSE;
3519
3520     if (requested->dwFlags & DDPF_FOURCC)
3521         if (requested->dwFourCC != provided->dwFourCC)
3522             return FALSE;
3523
3524     if (requested->dwFlags & (DDPF_RGB|DDPF_YUV|DDPF_ZBUFFER|DDPF_ALPHA
3525                               |DDPF_LUMINANCE|DDPF_BUMPDUDV))
3526         if (requested->u1.dwRGBBitCount != provided->u1.dwRGBBitCount)
3527             return FALSE;
3528
3529     if (requested->dwFlags & (DDPF_RGB|DDPF_YUV|DDPF_STENCILBUFFER
3530                               |DDPF_LUMINANCE|DDPF_BUMPDUDV))
3531         if (requested->u2.dwRBitMask != provided->u2.dwRBitMask)
3532             return FALSE;
3533
3534     if (requested->dwFlags & (DDPF_RGB|DDPF_YUV|DDPF_ZBUFFER|DDPF_BUMPDUDV))
3535         if (requested->u3.dwGBitMask != provided->u3.dwGBitMask)
3536             return FALSE;
3537
3538     /* I could be wrong about the bumpmapping. MSDN docs are vague. */
3539     if (requested->dwFlags & (DDPF_RGB|DDPF_YUV|DDPF_STENCILBUFFER
3540                               |DDPF_BUMPDUDV))
3541         if (requested->u4.dwBBitMask != provided->u4.dwBBitMask)
3542             return FALSE;
3543
3544     if (requested->dwFlags & (DDPF_ALPHAPIXELS|DDPF_ZPIXELS))
3545         if (requested->u5.dwRGBAlphaBitMask != provided->u5.dwRGBAlphaBitMask)
3546             return FALSE;
3547
3548     return TRUE;
3549 }
3550
3551 static BOOL ddraw_match_surface_desc(const DDSURFACEDESC2 *requested, const DDSURFACEDESC2 *provided)
3552 {
3553     struct compare_info
3554     {
3555         DWORD flag;
3556         ptrdiff_t offset;
3557         size_t size;
3558     };
3559
3560 #define CMP(FLAG, FIELD)                                \
3561         { DDSD_##FLAG, offsetof(DDSURFACEDESC2, FIELD), \
3562           sizeof(((DDSURFACEDESC2 *)(NULL))->FIELD) }
3563
3564     static const struct compare_info compare[] =
3565     {
3566         CMP(ALPHABITDEPTH, dwAlphaBitDepth),
3567         CMP(BACKBUFFERCOUNT, dwBackBufferCount),
3568         CMP(CAPS, ddsCaps),
3569         CMP(CKDESTBLT, ddckCKDestBlt),
3570         CMP(CKDESTOVERLAY, u3 /* ddckCKDestOverlay */),
3571         CMP(CKSRCBLT, ddckCKSrcBlt),
3572         CMP(CKSRCOVERLAY, ddckCKSrcOverlay),
3573         CMP(HEIGHT, dwHeight),
3574         CMP(LINEARSIZE, u1 /* dwLinearSize */),
3575         CMP(LPSURFACE, lpSurface),
3576         CMP(MIPMAPCOUNT, u2 /* dwMipMapCount */),
3577         CMP(PITCH, u1 /* lPitch */),
3578         /* PIXELFORMAT: manual */
3579         CMP(REFRESHRATE, u2 /* dwRefreshRate */),
3580         CMP(TEXTURESTAGE, dwTextureStage),
3581         CMP(WIDTH, dwWidth),
3582         /* ZBUFFERBITDEPTH: "obsolete" */
3583     };
3584
3585 #undef CMP
3586
3587     unsigned int i;
3588
3589     if ((requested->dwFlags & provided->dwFlags) != requested->dwFlags)
3590         return FALSE;
3591
3592     for (i=0; i < sizeof(compare)/sizeof(compare[0]); i++)
3593     {
3594         if (requested->dwFlags & compare[i].flag
3595             && memcmp((const char *)provided + compare[i].offset,
3596                       (const char *)requested + compare[i].offset,
3597                       compare[i].size) != 0)
3598             return FALSE;
3599     }
3600
3601     if (requested->dwFlags & DDSD_PIXELFORMAT)
3602     {
3603         if (!Main_DirectDraw_DDPIXELFORMAT_Match(&requested->u4.ddpfPixelFormat,
3604                                                 &provided->u4.ddpfPixelFormat))
3605             return FALSE;
3606     }
3607
3608     return TRUE;
3609 }
3610
3611 #undef DDENUMSURFACES_SEARCHTYPE
3612 #undef DDENUMSURFACES_MATCHTYPE
3613
3614 struct surfacescallback_context
3615 {
3616     LPDDENUMSURFACESCALLBACK func;
3617     void *context;
3618 };
3619
3620 static HRESULT CALLBACK EnumSurfacesCallbackThunk(IDirectDrawSurface7 *surface,
3621         DDSURFACEDESC2 *surface_desc, void *context)
3622 {
3623     struct surfacescallback_context *cbcontext = context;
3624
3625     return cbcontext->func((IDirectDrawSurface *)&((IDirectDrawSurfaceImpl *)surface)->IDirectDrawSurface3_vtbl,
3626             (DDSURFACEDESC *)surface_desc, cbcontext->context);
3627 }
3628
3629 /*****************************************************************************
3630  * IDirectDraw7::EnumSurfaces
3631  *
3632  * Loops through all surfaces attached to this device and calls the
3633  * application callback. This can't be relayed to WineD3DDevice,
3634  * because some WineD3DSurfaces' parents are IParent objects
3635  *
3636  * Params:
3637  *  Flags: Some filtering flags. See IDirectDrawImpl_EnumSurfacesCallback
3638  *  DDSD: Description to filter for
3639  *  Context: Application-provided pointer, it's passed unmodified to the
3640  *           Callback function
3641  *  Callback: Address to call for each surface
3642  *
3643  * Returns:
3644  *  DDERR_INVALIDPARAMS if the callback is NULL
3645  *  DD_OK on success
3646  *
3647  *****************************************************************************/
3648 static HRESULT WINAPI ddraw7_EnumSurfaces(IDirectDraw7 *iface, DWORD Flags,
3649         DDSURFACEDESC2 *DDSD, void *Context, LPDDENUMSURFACESCALLBACK7 Callback)
3650 {
3651     /* The surface enumeration is handled by WineDDraw,
3652      * because it keeps track of all surfaces attached to
3653      * it. The filtering is done by our callback function,
3654      * because WineDDraw doesn't handle ddraw-like surface
3655      * caps structures
3656      */
3657     IDirectDrawImpl *This = (IDirectDrawImpl *)iface;
3658     IDirectDrawSurfaceImpl *surf;
3659     BOOL all, nomatch;
3660     DDSURFACEDESC2 desc;
3661     struct list *entry, *entry2;
3662
3663     all = Flags & DDENUMSURFACES_ALL;
3664     nomatch = Flags & DDENUMSURFACES_NOMATCH;
3665
3666     TRACE("(%p)->(%x,%p,%p,%p)\n", This, Flags, DDSD, Context, Callback);
3667     EnterCriticalSection(&ddraw_cs);
3668
3669     if(!Callback)
3670     {
3671         LeaveCriticalSection(&ddraw_cs);
3672         return DDERR_INVALIDPARAMS;
3673     }
3674
3675     /* Use the _SAFE enumeration, the app may destroy enumerated surfaces */
3676     LIST_FOR_EACH_SAFE(entry, entry2, &This->surface_list)
3677     {
3678         surf = LIST_ENTRY(entry, IDirectDrawSurfaceImpl, surface_list_entry);
3679         if (all || (nomatch != ddraw_match_surface_desc(DDSD, &surf->surface_desc)))
3680         {
3681             desc = surf->surface_desc;
3682             IDirectDrawSurface7_AddRef((IDirectDrawSurface7 *)surf);
3683             if (Callback((IDirectDrawSurface7 *)surf, &desc, Context) != DDENUMRET_OK)
3684             {
3685                 LeaveCriticalSection(&ddraw_cs);
3686                 return DD_OK;
3687             }
3688         }
3689     }
3690     LeaveCriticalSection(&ddraw_cs);
3691     return DD_OK;
3692 }
3693
3694 static HRESULT WINAPI ddraw4_EnumSurfaces(IDirectDraw4 *iface, DWORD flags,
3695         DDSURFACEDESC2 *surface_desc, void *context, LPDDENUMSURFACESCALLBACK2 callback)
3696 {
3697     TRACE("iface %p, flags %#x, surface_desc %p, context %p, callback %p.\n",
3698             iface, flags, surface_desc, context, callback);
3699
3700     return ddraw7_EnumSurfaces((IDirectDraw7 *)ddraw_from_ddraw4(iface),
3701             flags, surface_desc, context, (LPDDENUMSURFACESCALLBACK7)callback);
3702 }
3703
3704 static HRESULT WINAPI ddraw3_EnumSurfaces(IDirectDraw3 *iface, DWORD flags,
3705         DDSURFACEDESC *surface_desc, void *context, LPDDENUMSURFACESCALLBACK callback)
3706 {
3707     struct surfacescallback_context cbcontext;
3708
3709     TRACE("iface %p, flags %#x, surface_desc %p, context %p, callback %p.\n",
3710             iface, flags, surface_desc, context, callback);
3711
3712     cbcontext.func = callback;
3713     cbcontext.context = context;
3714
3715     return ddraw7_EnumSurfaces((IDirectDraw7 *)ddraw_from_ddraw3(iface), flags,
3716             (DDSURFACEDESC2 *)surface_desc, &cbcontext, EnumSurfacesCallbackThunk);
3717 }
3718
3719 static HRESULT WINAPI ddraw2_EnumSurfaces(IDirectDraw2 *iface, DWORD flags,
3720         DDSURFACEDESC *surface_desc, void *context, LPDDENUMSURFACESCALLBACK callback)
3721 {
3722     struct surfacescallback_context cbcontext;
3723
3724     TRACE("iface %p, flags %#x, surface_desc %p, context %p, callback %p.\n",
3725             iface, flags, surface_desc, context, callback);
3726
3727     cbcontext.func = callback;
3728     cbcontext.context = context;
3729
3730     return ddraw7_EnumSurfaces((IDirectDraw7 *)ddraw_from_ddraw2(iface), flags,
3731             (DDSURFACEDESC2 *)surface_desc, &cbcontext, EnumSurfacesCallbackThunk);
3732 }
3733
3734 static HRESULT WINAPI ddraw1_EnumSurfaces(IDirectDraw *iface, DWORD flags,
3735         DDSURFACEDESC *surface_desc, void *context, LPDDENUMSURFACESCALLBACK callback)
3736 {
3737     struct surfacescallback_context cbcontext;
3738
3739     TRACE("iface %p, flags %#x, surface_desc %p, context %p, callback %p.\n",
3740             iface, flags, surface_desc, context, callback);
3741
3742     cbcontext.func = callback;
3743     cbcontext.context = context;
3744
3745     return ddraw7_EnumSurfaces((IDirectDraw7 *)ddraw_from_ddraw1(iface), flags,
3746             (DDSURFACEDESC2 *)surface_desc, &cbcontext, EnumSurfacesCallbackThunk);
3747 }
3748
3749 /*****************************************************************************
3750  * DirectDrawCreateClipper (DDRAW.@)
3751  *
3752  * Creates a new IDirectDrawClipper object.
3753  *
3754  * Params:
3755  *  Clipper: Address to write the interface pointer to
3756  *  UnkOuter: For aggregation support, which ddraw doesn't have. Has to be
3757  *            NULL
3758  *
3759  * Returns:
3760  *  CLASS_E_NOAGGREGATION if UnkOuter != NULL
3761  *  E_OUTOFMEMORY if allocating the object failed
3762  *
3763  *****************************************************************************/
3764 HRESULT WINAPI
3765 DirectDrawCreateClipper(DWORD Flags,
3766                         LPDIRECTDRAWCLIPPER *Clipper,
3767                         IUnknown *UnkOuter)
3768 {
3769     IDirectDrawClipperImpl* object;
3770     TRACE("(%08x,%p,%p)\n", Flags, Clipper, UnkOuter);
3771
3772     EnterCriticalSection(&ddraw_cs);
3773     if (UnkOuter != NULL)
3774     {
3775         LeaveCriticalSection(&ddraw_cs);
3776         return CLASS_E_NOAGGREGATION;
3777     }
3778
3779     if (!LoadWineD3D())
3780     {
3781         LeaveCriticalSection(&ddraw_cs);
3782         return DDERR_NODIRECTDRAWSUPPORT;
3783     }
3784
3785     object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
3786                      sizeof(IDirectDrawClipperImpl));
3787     if (object == NULL)
3788     {
3789         LeaveCriticalSection(&ddraw_cs);
3790         return E_OUTOFMEMORY;
3791     }
3792
3793     object->lpVtbl = &IDirectDrawClipper_Vtbl;
3794     object->ref = 1;
3795     object->wineD3DClipper = pWineDirect3DCreateClipper((IUnknown *) object);
3796     if(!object->wineD3DClipper)
3797     {
3798         HeapFree(GetProcessHeap(), 0, object);
3799         LeaveCriticalSection(&ddraw_cs);
3800         return E_OUTOFMEMORY;
3801     }
3802
3803     *Clipper = (IDirectDrawClipper *) object;
3804     LeaveCriticalSection(&ddraw_cs);
3805     return DD_OK;
3806 }
3807
3808 /*****************************************************************************
3809  * IDirectDraw7::CreateClipper
3810  *
3811  * Creates a DDraw clipper. See DirectDrawCreateClipper for details
3812  *
3813  *****************************************************************************/
3814 static HRESULT WINAPI ddraw7_CreateClipper(IDirectDraw7 *iface, DWORD Flags,
3815         IDirectDrawClipper **Clipper, IUnknown *UnkOuter)
3816 {
3817     IDirectDrawImpl *This = (IDirectDrawImpl *)iface;
3818     TRACE("(%p)->(%x,%p,%p)\n", This, Flags, Clipper, UnkOuter);
3819     return DirectDrawCreateClipper(Flags, Clipper, UnkOuter);
3820 }
3821
3822 static HRESULT WINAPI ddraw4_CreateClipper(IDirectDraw4 *iface,
3823         DWORD flags, IDirectDrawClipper **clipper, IUnknown *outer_unknown)
3824 {
3825     TRACE("iface %p, flags %#x, clipper %p, outer_unknown %p.\n",
3826             iface, flags, clipper, outer_unknown);
3827
3828     return ddraw7_CreateClipper((IDirectDraw7 *)ddraw_from_ddraw4(iface), flags, clipper, outer_unknown);
3829 }
3830
3831 static HRESULT WINAPI ddraw3_CreateClipper(IDirectDraw3 *iface,
3832         DWORD flags, IDirectDrawClipper **clipper, IUnknown *outer_unknown)
3833 {
3834     TRACE("iface %p, flags %#x, clipper %p, outer_unknown %p.\n",
3835             iface, flags, clipper, outer_unknown);
3836
3837     return ddraw7_CreateClipper((IDirectDraw7 *)ddraw_from_ddraw3(iface), flags, clipper, outer_unknown);
3838 }
3839
3840 static HRESULT WINAPI ddraw2_CreateClipper(IDirectDraw2 *iface,
3841         DWORD flags, IDirectDrawClipper **clipper, IUnknown *outer_unknown)
3842 {
3843     TRACE("iface %p, flags %#x, clipper %p, outer_unknown %p.\n",
3844             iface, flags, clipper, outer_unknown);
3845
3846     return ddraw7_CreateClipper((IDirectDraw7 *)ddraw_from_ddraw2(iface), flags, clipper, outer_unknown);
3847 }
3848
3849 static HRESULT WINAPI ddraw1_CreateClipper(IDirectDraw *iface,
3850         DWORD flags, IDirectDrawClipper **clipper, IUnknown *outer_unknown)
3851 {
3852     TRACE("iface %p, flags %#x, clipper %p, outer_unknown %p.\n",
3853             iface, flags, clipper, outer_unknown);
3854
3855     return ddraw7_CreateClipper((IDirectDraw7 *)ddraw_from_ddraw1(iface), flags, clipper, outer_unknown);
3856 }
3857
3858 /*****************************************************************************
3859  * IDirectDraw7::CreatePalette
3860  *
3861  * Creates a new IDirectDrawPalette object
3862  *
3863  * Params:
3864  *  Flags: The flags for the new clipper
3865  *  ColorTable: Color table to assign to the new clipper
3866  *  Palette: Address to write the interface pointer to
3867  *  UnkOuter: For aggregation support, which ddraw doesn't have. Has to be
3868  *            NULL
3869  *
3870  * Returns:
3871  *  CLASS_E_NOAGGREGATION if UnkOuter != NULL
3872  *  E_OUTOFMEMORY if allocating the object failed
3873  *
3874  *****************************************************************************/
3875 static HRESULT WINAPI ddraw7_CreatePalette(IDirectDraw7 *iface, DWORD Flags,
3876         PALETTEENTRY *ColorTable, IDirectDrawPalette **Palette, IUnknown *pUnkOuter)
3877 {
3878     IDirectDrawImpl *This = (IDirectDrawImpl *)iface;
3879     IDirectDrawPaletteImpl *object;
3880     HRESULT hr = DDERR_GENERIC;
3881     TRACE("(%p)->(%x,%p,%p,%p)\n", This, Flags, ColorTable, Palette, pUnkOuter);
3882
3883     EnterCriticalSection(&ddraw_cs);
3884     if(pUnkOuter != NULL)
3885     {
3886         WARN("pUnkOuter is %p, returning CLASS_E_NOAGGREGATION\n", pUnkOuter);
3887         LeaveCriticalSection(&ddraw_cs);
3888         return CLASS_E_NOAGGREGATION;
3889     }
3890
3891     /* The refcount test shows that a cooplevel is required for this */
3892     if(!This->cooperative_level)
3893     {
3894         WARN("No cooperative level set, returning DDERR_NOCOOPERATIVELEVELSET\n");
3895         LeaveCriticalSection(&ddraw_cs);
3896         return DDERR_NOCOOPERATIVELEVELSET;
3897     }
3898
3899     object = HeapAlloc(GetProcessHeap(), 0, sizeof(IDirectDrawPaletteImpl));
3900     if(!object)
3901     {
3902         ERR("Out of memory when allocating memory for a palette implementation\n");
3903         LeaveCriticalSection(&ddraw_cs);
3904         return E_OUTOFMEMORY;
3905     }
3906
3907     object->lpVtbl = &IDirectDrawPalette_Vtbl;
3908     object->ref = 1;
3909
3910     hr = IWineD3DDevice_CreatePalette(This->wineD3DDevice, Flags,
3911             ColorTable, &object->wineD3DPalette, (IUnknown *)object);
3912     if(hr != DD_OK)
3913     {
3914         HeapFree(GetProcessHeap(), 0, object);
3915         LeaveCriticalSection(&ddraw_cs);
3916         return hr;
3917     }
3918
3919     IDirectDraw7_AddRef(iface);
3920     object->ifaceToRelease = (IUnknown *) iface;
3921     *Palette = (IDirectDrawPalette *)object;
3922     LeaveCriticalSection(&ddraw_cs);
3923     return DD_OK;
3924 }
3925
3926 static HRESULT WINAPI ddraw4_CreatePalette(IDirectDraw4 *iface, DWORD flags,
3927         PALETTEENTRY *entries, IDirectDrawPalette **palette, IUnknown *outer_unknown)
3928 {
3929     IDirectDrawImpl *ddraw = ddraw_from_ddraw4(iface);
3930     HRESULT hr;
3931
3932     TRACE("iface %p, flags %#x, entries %p, palette %p, outer_unknown %p.\n",
3933             iface, flags, entries, palette, outer_unknown);
3934
3935     hr = ddraw7_CreatePalette((IDirectDraw7 *)ddraw, flags, entries, palette, outer_unknown);
3936     if (SUCCEEDED(hr) && *palette)
3937     {
3938         IDirectDrawPaletteImpl *impl = (IDirectDrawPaletteImpl *)*palette;
3939         IDirectDraw7_Release((IDirectDraw7 *)ddraw);
3940         IDirectDraw4_AddRef(iface);
3941         impl->ifaceToRelease = (IUnknown *)iface;
3942     }
3943     return hr;
3944 }
3945
3946 static HRESULT WINAPI ddraw3_CreatePalette(IDirectDraw3 *iface, DWORD flags,
3947         PALETTEENTRY *entries, IDirectDrawPalette **palette, IUnknown *outer_unknown)
3948 {
3949     IDirectDrawImpl *ddraw = ddraw_from_ddraw3(iface);
3950     HRESULT hr;
3951
3952     TRACE("iface %p, flags %#x, entries %p, palette %p, outer_unknown %p.\n",
3953             iface, flags, entries, palette, outer_unknown);
3954
3955     hr = ddraw7_CreatePalette((IDirectDraw7 *)ddraw, flags, entries, palette, outer_unknown);
3956     if (SUCCEEDED(hr) && *palette)
3957     {
3958         IDirectDrawPaletteImpl *impl = (IDirectDrawPaletteImpl *)*palette;
3959         IDirectDraw7_Release((IDirectDraw7 *)ddraw);
3960         IDirectDraw4_AddRef(iface);
3961         impl->ifaceToRelease = (IUnknown *)iface;
3962     }
3963
3964     return hr;
3965 }
3966
3967 static HRESULT WINAPI ddraw2_CreatePalette(IDirectDraw2 *iface, DWORD flags,
3968         PALETTEENTRY *entries, IDirectDrawPalette **palette, IUnknown *outer_unknown)
3969 {
3970     IDirectDrawImpl *ddraw = ddraw_from_ddraw2(iface);
3971     HRESULT hr;
3972
3973     TRACE("iface %p, flags %#x, entries %p, palette %p, outer_unknown %p.\n",
3974             iface, flags, entries, palette, outer_unknown);
3975
3976     hr = ddraw7_CreatePalette((IDirectDraw7 *)ddraw, flags, entries, palette, outer_unknown);
3977     if (SUCCEEDED(hr) && *palette)
3978     {
3979         IDirectDrawPaletteImpl *impl = (IDirectDrawPaletteImpl *)*palette;
3980         IDirectDraw7_Release((IDirectDraw7 *)ddraw);
3981         impl->ifaceToRelease = NULL;
3982     }
3983
3984     return hr;
3985 }
3986
3987 static HRESULT WINAPI ddraw1_CreatePalette(IDirectDraw *iface, DWORD flags,
3988         PALETTEENTRY *entries, IDirectDrawPalette **palette, IUnknown *outer_unknown)
3989 {
3990     IDirectDrawImpl *ddraw = ddraw_from_ddraw1(iface);
3991     HRESULT hr;
3992
3993     TRACE("iface %p, flags %#x, entries %p, palette %p, outer_unknown %p.\n",
3994             iface, flags, entries, palette, outer_unknown);
3995
3996     hr = ddraw7_CreatePalette((IDirectDraw7 *)ddraw, flags, entries, palette, outer_unknown);
3997     if (SUCCEEDED(hr) && *palette)
3998     {
3999         IDirectDrawPaletteImpl *impl = (IDirectDrawPaletteImpl *)*palette;
4000         IDirectDraw7_Release((IDirectDraw7 *)ddraw);
4001         impl->ifaceToRelease = NULL;
4002     }
4003
4004     return hr;
4005 }
4006
4007 /*****************************************************************************
4008  * IDirectDraw7::DuplicateSurface
4009  *
4010  * Duplicates a surface. The surface memory points to the same memory as
4011  * the original surface, and it's released when the last surface referencing
4012  * it is released. I guess that's beyond Wine's surface management right now
4013  * (Idea: create a new DDraw surface with the same WineD3DSurface. I need a
4014  * test application to implement this)
4015  *
4016  * Params:
4017  *  Src: Address of the source surface
4018  *  Dest: Address to write the new surface pointer to
4019  *
4020  * Returns:
4021  *  See IDirectDraw7::CreateSurface
4022  *
4023  *****************************************************************************/
4024 static HRESULT WINAPI ddraw7_DuplicateSurface(IDirectDraw7 *iface,
4025         IDirectDrawSurface7 *Src, IDirectDrawSurface7 **Dest)
4026 {
4027     IDirectDrawImpl *This = (IDirectDrawImpl *)iface;
4028     IDirectDrawSurfaceImpl *Surf = (IDirectDrawSurfaceImpl *)Src;
4029
4030     FIXME("(%p)->(%p,%p)\n", This, Surf, Dest);
4031
4032     /* For now, simply create a new, independent surface */
4033     return IDirectDraw7_CreateSurface(iface,
4034                                       &Surf->surface_desc,
4035                                       Dest,
4036                                       NULL);
4037 }
4038
4039 static HRESULT WINAPI ddraw4_DuplicateSurface(IDirectDraw4 *iface,
4040         IDirectDrawSurface4 *src, IDirectDrawSurface4 **dst)
4041 {
4042     TRACE("iface %p, src %p, dst %p.\n", iface, src, dst);
4043
4044     return ddraw7_DuplicateSurface((IDirectDraw7 *)ddraw_from_ddraw4(iface),
4045             (IDirectDrawSurface7 *)src, (IDirectDrawSurface7 **)dst);
4046 }
4047
4048 static HRESULT WINAPI ddraw3_DuplicateSurface(IDirectDraw3 *iface,
4049         IDirectDrawSurface *src, IDirectDrawSurface **dst)
4050 {
4051     IDirectDrawSurface7 *src7, *dst7;
4052     HRESULT hr;
4053
4054     TRACE("iface %p, src %p, dst %p.\n", iface, src, dst);
4055     src7 = (IDirectDrawSurface7 *)surface_from_surface3((IDirectDrawSurface3 *)src);
4056     hr = ddraw7_DuplicateSurface((IDirectDraw7 *)ddraw_from_ddraw3(iface), src7, &dst7);
4057     if (!SUCCEEDED(hr))
4058         return hr;
4059     *dst = (IDirectDrawSurface *)&((IDirectDrawSurfaceImpl *)dst7)->IDirectDrawSurface3_vtbl;
4060     return hr;
4061 }
4062
4063 static HRESULT WINAPI ddraw2_DuplicateSurface(IDirectDraw2 *iface,
4064         IDirectDrawSurface *src, IDirectDrawSurface **dst)
4065 {
4066     IDirectDrawSurface7 *src7, *dst7;
4067     HRESULT hr;
4068
4069     TRACE("iface %p, src %p, dst %p.\n", iface, src, dst);
4070     src7 = (IDirectDrawSurface7 *)surface_from_surface3((IDirectDrawSurface3 *)src);
4071     hr = ddraw7_DuplicateSurface((IDirectDraw7 *)ddraw_from_ddraw2(iface), src7, &dst7);
4072     if (!SUCCEEDED(hr))
4073         return hr;
4074     *dst = (IDirectDrawSurface *)&((IDirectDrawSurfaceImpl *)dst7)->IDirectDrawSurface3_vtbl;
4075     return hr;
4076 }
4077
4078 static HRESULT WINAPI ddraw1_DuplicateSurface(IDirectDraw *iface,
4079         IDirectDrawSurface *src, IDirectDrawSurface **dst)
4080 {
4081     IDirectDrawSurface7 *src7, *dst7;
4082     HRESULT hr;
4083
4084     TRACE("iface %p, src %p, dst %p.\n", iface, src, dst);
4085     src7 = (IDirectDrawSurface7 *)surface_from_surface3((IDirectDrawSurface3 *)src);
4086     hr = ddraw7_DuplicateSurface((IDirectDraw7 *)ddraw_from_ddraw1(iface), src7, &dst7);
4087     if (!SUCCEEDED(hr))
4088         return hr;
4089     *dst = (IDirectDrawSurface *)&((IDirectDrawSurfaceImpl *)dst7)->IDirectDrawSurface3_vtbl;
4090     return hr;
4091 }
4092
4093 /*****************************************************************************
4094  * IDirectDraw7 VTable
4095  *****************************************************************************/
4096 const IDirectDraw7Vtbl IDirectDraw7_Vtbl =
4097 {
4098     /* IUnknown */
4099     ddraw7_QueryInterface,
4100     ddraw7_AddRef,
4101     ddraw7_Release,
4102     /* IDirectDraw */
4103     ddraw7_Compact,
4104     ddraw7_CreateClipper,
4105     ddraw7_CreatePalette,
4106     ddraw7_CreateSurface,
4107     ddraw7_DuplicateSurface,
4108     ddraw7_EnumDisplayModes,
4109     ddraw7_EnumSurfaces,
4110     ddraw7_FlipToGDISurface,
4111     ddraw7_GetCaps,
4112     ddraw7_GetDisplayMode,
4113     ddraw7_GetFourCCCodes,
4114     ddraw7_GetGDISurface,
4115     ddraw7_GetMonitorFrequency,
4116     ddraw7_GetScanLine,
4117     ddraw7_GetVerticalBlankStatus,
4118     ddraw7_Initialize,
4119     ddraw7_RestoreDisplayMode,
4120     ddraw7_SetCooperativeLevel,
4121     ddraw7_SetDisplayMode,
4122     ddraw7_WaitForVerticalBlank,
4123     /* IDirectDraw2 */
4124     ddraw7_GetAvailableVidMem,
4125     /* IDirectDraw3 */
4126     ddraw7_GetSurfaceFromDC,
4127     /* IDirectDraw4 */
4128     ddraw7_RestoreAllSurfaces,
4129     ddraw7_TestCooperativeLevel,
4130     ddraw7_GetDeviceIdentifier,
4131     /* IDirectDraw7 */
4132     ddraw7_StartModeTest,
4133     ddraw7_EvaluateMode
4134 };
4135
4136 const struct IDirectDraw4Vtbl IDirectDraw4_Vtbl =
4137 {
4138     /* IUnknown */
4139     ddraw4_QueryInterface,
4140     ddraw4_AddRef,
4141     ddraw4_Release,
4142     /* IDirectDraw */
4143     ddraw4_Compact,
4144     ddraw4_CreateClipper,
4145     ddraw4_CreatePalette,
4146     ddraw4_CreateSurface,
4147     ddraw4_DuplicateSurface,
4148     ddraw4_EnumDisplayModes,
4149     ddraw4_EnumSurfaces,
4150     ddraw4_FlipToGDISurface,
4151     ddraw4_GetCaps,
4152     ddraw4_GetDisplayMode,
4153     ddraw4_GetFourCCCodes,
4154     ddraw4_GetGDISurface,
4155     ddraw4_GetMonitorFrequency,
4156     ddraw4_GetScanLine,
4157     ddraw4_GetVerticalBlankStatus,
4158     ddraw4_Initialize,
4159     ddraw4_RestoreDisplayMode,
4160     ddraw4_SetCooperativeLevel,
4161     ddraw4_SetDisplayMode,
4162     ddraw4_WaitForVerticalBlank,
4163     /* IDirectDraw2 */
4164     ddraw4_GetAvailableVidMem,
4165     /* IDirectDraw3 */
4166     ddraw4_GetSurfaceFromDC,
4167     /* IDirectDraw4 */
4168     ddraw4_RestoreAllSurfaces,
4169     ddraw4_TestCooperativeLevel,
4170     ddraw4_GetDeviceIdentifier,
4171 };
4172
4173 const struct IDirectDraw3Vtbl IDirectDraw3_Vtbl =
4174 {
4175     /* IUnknown */
4176     ddraw3_QueryInterface,
4177     ddraw3_AddRef,
4178     ddraw3_Release,
4179     /* IDirectDraw */
4180     ddraw3_Compact,
4181     ddraw3_CreateClipper,
4182     ddraw3_CreatePalette,
4183     ddraw3_CreateSurface,
4184     ddraw3_DuplicateSurface,
4185     ddraw3_EnumDisplayModes,
4186     ddraw3_EnumSurfaces,
4187     ddraw3_FlipToGDISurface,
4188     ddraw3_GetCaps,
4189     ddraw3_GetDisplayMode,
4190     ddraw3_GetFourCCCodes,
4191     ddraw3_GetGDISurface,
4192     ddraw3_GetMonitorFrequency,
4193     ddraw3_GetScanLine,
4194     ddraw3_GetVerticalBlankStatus,
4195     ddraw3_Initialize,
4196     ddraw3_RestoreDisplayMode,
4197     ddraw3_SetCooperativeLevel,
4198     ddraw3_SetDisplayMode,
4199     ddraw3_WaitForVerticalBlank,
4200     /* IDirectDraw2 */
4201     ddraw3_GetAvailableVidMem,
4202     /* IDirectDraw3 */
4203     ddraw3_GetSurfaceFromDC,
4204 };
4205
4206 const struct IDirectDraw2Vtbl IDirectDraw2_Vtbl =
4207 {
4208     /* IUnknown */
4209     ddraw2_QueryInterface,
4210     ddraw2_AddRef,
4211     ddraw2_Release,
4212     /* IDirectDraw */
4213     ddraw2_Compact,
4214     ddraw2_CreateClipper,
4215     ddraw2_CreatePalette,
4216     ddraw2_CreateSurface,
4217     ddraw2_DuplicateSurface,
4218     ddraw2_EnumDisplayModes,
4219     ddraw2_EnumSurfaces,
4220     ddraw2_FlipToGDISurface,
4221     ddraw2_GetCaps,
4222     ddraw2_GetDisplayMode,
4223     ddraw2_GetFourCCCodes,
4224     ddraw2_GetGDISurface,
4225     ddraw2_GetMonitorFrequency,
4226     ddraw2_GetScanLine,
4227     ddraw2_GetVerticalBlankStatus,
4228     ddraw2_Initialize,
4229     ddraw2_RestoreDisplayMode,
4230     ddraw2_SetCooperativeLevel,
4231     ddraw2_SetDisplayMode,
4232     ddraw2_WaitForVerticalBlank,
4233     /* IDirectDraw2 */
4234     ddraw2_GetAvailableVidMem,
4235 };
4236
4237 const struct IDirectDrawVtbl IDirectDraw1_Vtbl =
4238 {
4239     /* IUnknown */
4240     ddraw1_QueryInterface,
4241     ddraw1_AddRef,
4242     ddraw1_Release,
4243     /* IDirectDraw */
4244     ddraw1_Compact,
4245     ddraw1_CreateClipper,
4246     ddraw1_CreatePalette,
4247     ddraw1_CreateSurface,
4248     ddraw1_DuplicateSurface,
4249     ddraw1_EnumDisplayModes,
4250     ddraw1_EnumSurfaces,
4251     ddraw1_FlipToGDISurface,
4252     ddraw1_GetCaps,
4253     ddraw1_GetDisplayMode,
4254     ddraw1_GetFourCCCodes,
4255     ddraw1_GetGDISurface,
4256     ddraw1_GetMonitorFrequency,
4257     ddraw1_GetScanLine,
4258     ddraw1_GetVerticalBlankStatus,
4259     ddraw1_Initialize,
4260     ddraw1_RestoreDisplayMode,
4261     ddraw1_SetCooperativeLevel,
4262     ddraw1_SetDisplayMode,
4263     ddraw1_WaitForVerticalBlank,
4264 };
4265
4266 /*****************************************************************************
4267  * ddraw_find_decl
4268  *
4269  * Finds the WineD3D vertex declaration for a specific fvf, and creates one
4270  * if none was found.
4271  *
4272  * This function is in ddraw.c and the DDraw object space because D3D7
4273  * vertex buffers are created using the IDirect3D interface to the ddraw
4274  * object, so they can be valid across D3D devices(theoretically. The ddraw
4275  * object also owns the wined3d device
4276  *
4277  * Parameters:
4278  *  This: Device
4279  *  fvf: Fvf to find the decl for
4280  *
4281  * Returns:
4282  *  NULL in case of an error, the IWineD3DVertexDeclaration interface for the
4283  *  fvf otherwise.
4284  *
4285  *****************************************************************************/
4286 IWineD3DVertexDeclaration *ddraw_find_decl(IDirectDrawImpl *This, DWORD fvf)
4287 {
4288     HRESULT hr;
4289     IWineD3DVertexDeclaration* pDecl = NULL;
4290     int p, low, high; /* deliberately signed */
4291     struct FvfToDecl *convertedDecls = This->decls;
4292
4293     TRACE("Searching for declaration for fvf %08x... ", fvf);
4294
4295     low = 0;
4296     high = This->numConvertedDecls - 1;
4297     while(low <= high) {
4298         p = (low + high) >> 1;
4299         TRACE("%d ", p);
4300         if(convertedDecls[p].fvf == fvf) {
4301             TRACE("found %p\n", convertedDecls[p].decl);
4302             return convertedDecls[p].decl;
4303         } else if(convertedDecls[p].fvf < fvf) {
4304             low = p + 1;
4305         } else {
4306             high = p - 1;
4307         }
4308     }
4309     TRACE("not found. Creating and inserting at position %d.\n", low);
4310
4311     hr = IWineD3DDevice_CreateVertexDeclarationFromFVF(This->wineD3DDevice, &pDecl,
4312             (IUnknown *)This, &ddraw_null_wined3d_parent_ops, fvf);
4313     if (hr != S_OK) return NULL;
4314
4315     if(This->declArraySize == This->numConvertedDecls) {
4316         int grow = max(This->declArraySize / 2, 8);
4317         convertedDecls = HeapReAlloc(GetProcessHeap(), 0, convertedDecls,
4318                                      sizeof(convertedDecls[0]) * (This->numConvertedDecls + grow));
4319         if(!convertedDecls) {
4320             /* This will destroy it */
4321             IWineD3DVertexDeclaration_Release(pDecl);
4322             return NULL;
4323         }
4324         This->decls = convertedDecls;
4325         This->declArraySize += grow;
4326     }
4327
4328     memmove(convertedDecls + low + 1, convertedDecls + low, sizeof(convertedDecls[0]) * (This->numConvertedDecls - low));
4329     convertedDecls[low].decl = pDecl;
4330     convertedDecls[low].fvf = fvf;
4331     This->numConvertedDecls++;
4332
4333     TRACE("Returning %p. %d decls in array\n", pDecl, This->numConvertedDecls);
4334     return pDecl;
4335 }
4336
4337 /* IWineD3DDeviceParent IUnknown methods */
4338
4339 static inline struct IDirectDrawImpl *ddraw_from_device_parent(IWineD3DDeviceParent *iface)
4340 {
4341     return (struct IDirectDrawImpl *)((char*)iface - FIELD_OFFSET(struct IDirectDrawImpl, device_parent_vtbl));
4342 }
4343
4344 static HRESULT STDMETHODCALLTYPE device_parent_QueryInterface(IWineD3DDeviceParent *iface, REFIID riid, void **object)
4345 {
4346     struct IDirectDrawImpl *This = ddraw_from_device_parent(iface);
4347     return ddraw7_QueryInterface((IDirectDraw7 *)This, riid, object);
4348 }
4349
4350 static ULONG STDMETHODCALLTYPE device_parent_AddRef(IWineD3DDeviceParent *iface)
4351 {
4352     struct IDirectDrawImpl *This = ddraw_from_device_parent(iface);
4353     return ddraw7_AddRef((IDirectDraw7 *)This);
4354 }
4355
4356 static ULONG STDMETHODCALLTYPE device_parent_Release(IWineD3DDeviceParent *iface)
4357 {
4358     struct IDirectDrawImpl *This = ddraw_from_device_parent(iface);
4359     return ddraw7_Release((IDirectDraw7 *)This);
4360 }
4361
4362 /* IWineD3DDeviceParent methods */
4363
4364 static void STDMETHODCALLTYPE device_parent_WineD3DDeviceCreated(IWineD3DDeviceParent *iface, IWineD3DDevice *device)
4365 {
4366     TRACE("iface %p, device %p\n", iface, device);
4367 }
4368
4369 static HRESULT STDMETHODCALLTYPE device_parent_CreateSurface(IWineD3DDeviceParent *iface,
4370         IUnknown *superior, UINT width, UINT height, WINED3DFORMAT format, DWORD usage,
4371         WINED3DPOOL pool, UINT level, WINED3DCUBEMAP_FACES face, IWineD3DSurface **surface)
4372 {
4373     struct IDirectDrawImpl *This = ddraw_from_device_parent(iface);
4374     IDirectDrawSurfaceImpl *surf = NULL;
4375     UINT i = 0;
4376     DDSCAPS2 searchcaps = This->tex_root->surface_desc.ddsCaps;
4377
4378     TRACE("iface %p, superior %p, width %u, height %u, format %#x, usage %#x,\n"
4379             "\tpool %#x, level %u, face %u, surface %p\n",
4380             iface, superior, width, height, format, usage, pool, level, face, surface);
4381
4382     searchcaps.dwCaps2 &= ~DDSCAPS2_CUBEMAP_ALLFACES;
4383     switch(face)
4384     {
4385         case WINED3DCUBEMAP_FACE_POSITIVE_X:
4386             TRACE("Asked for positive x\n");
4387             if (searchcaps.dwCaps2 & DDSCAPS2_CUBEMAP)
4388             {
4389                 searchcaps.dwCaps2 |= DDSCAPS2_CUBEMAP_POSITIVEX;
4390             }
4391             surf = This->tex_root; break;
4392         case WINED3DCUBEMAP_FACE_NEGATIVE_X:
4393             TRACE("Asked for negative x\n");
4394             searchcaps.dwCaps2 |= DDSCAPS2_CUBEMAP_NEGATIVEX; break;
4395         case WINED3DCUBEMAP_FACE_POSITIVE_Y:
4396             TRACE("Asked for positive y\n");
4397             searchcaps.dwCaps2 |= DDSCAPS2_CUBEMAP_POSITIVEY; break;
4398         case WINED3DCUBEMAP_FACE_NEGATIVE_Y:
4399             TRACE("Asked for negative y\n");
4400             searchcaps.dwCaps2 |= DDSCAPS2_CUBEMAP_NEGATIVEY; break;
4401         case WINED3DCUBEMAP_FACE_POSITIVE_Z:
4402             TRACE("Asked for positive z\n");
4403             searchcaps.dwCaps2 |= DDSCAPS2_CUBEMAP_POSITIVEZ; break;
4404         case WINED3DCUBEMAP_FACE_NEGATIVE_Z:
4405             TRACE("Asked for negative z\n");
4406             searchcaps.dwCaps2 |= DDSCAPS2_CUBEMAP_NEGATIVEZ; break;
4407         default: {ERR("Unexpected cube face\n");} /* Stupid compiler */
4408     }
4409
4410     if (!surf)
4411     {
4412         IDirectDrawSurface7 *attached;
4413         IDirectDrawSurface7_GetAttachedSurface((IDirectDrawSurface7 *)This->tex_root, &searchcaps, &attached);
4414         surf = (IDirectDrawSurfaceImpl *)attached;
4415         IDirectDrawSurface7_Release(attached);
4416     }
4417     if (!surf) ERR("root search surface not found\n");
4418
4419     /* Find the wanted mipmap. There are enough mipmaps in the chain */
4420     while (i < level)
4421     {
4422         IDirectDrawSurface7 *attached;
4423         IDirectDrawSurface7_GetAttachedSurface((IDirectDrawSurface7 *)surf, &searchcaps, &attached);
4424         if(!attached) ERR("Surface not found\n");
4425         surf = (IDirectDrawSurfaceImpl *)attached;
4426         IDirectDrawSurface7_Release(attached);
4427         ++i;
4428     }
4429
4430     /* Return the surface */
4431     *surface = surf->WineD3DSurface;
4432     IWineD3DSurface_AddRef(*surface);
4433
4434     TRACE("Returning wineD3DSurface %p, it belongs to surface %p\n", *surface, surf);
4435
4436     return D3D_OK;
4437 }
4438
4439 static HRESULT WINAPI findRenderTarget(IDirectDrawSurface7 *surface, DDSURFACEDESC2 *surface_desc, void *ctx)
4440 {
4441     IDirectDrawSurfaceImpl *s = (IDirectDrawSurfaceImpl *)surface;
4442     IDirectDrawSurfaceImpl **target = ctx;
4443
4444     if (!s->isRenderTarget)
4445     {
4446         *target = s;
4447         IDirectDrawSurface7_Release(surface);
4448         return DDENUMRET_CANCEL;
4449     }
4450
4451     /* Recurse into the surface tree */
4452     IDirectDrawSurface7_EnumAttachedSurfaces(surface, ctx, findRenderTarget);
4453
4454     IDirectDrawSurface7_Release(surface);
4455     if (*target) return DDENUMRET_CANCEL;
4456
4457     return DDENUMRET_OK;
4458 }
4459
4460 static HRESULT STDMETHODCALLTYPE device_parent_CreateRenderTarget(IWineD3DDeviceParent *iface,
4461         IUnknown *superior, UINT width, UINT height, WINED3DFORMAT format, WINED3DMULTISAMPLE_TYPE multisample_type,
4462         DWORD multisample_quality, BOOL lockable, IWineD3DSurface **surface)
4463 {
4464     struct IDirectDrawImpl *This = ddraw_from_device_parent(iface);
4465     IDirectDrawSurfaceImpl *d3d_surface = This->d3d_target;
4466     IDirectDrawSurfaceImpl *target = NULL;
4467
4468     TRACE("iface %p, superior %p, width %u, height %u, format %#x, multisample_type %#x,\n"
4469             "\tmultisample_quality %u, lockable %u, surface %p\n",
4470             iface, superior, width, height, format, multisample_type, multisample_quality, lockable, surface);
4471
4472     if (d3d_surface->isRenderTarget)
4473     {
4474         IDirectDrawSurface7_EnumAttachedSurfaces((IDirectDrawSurface7 *)d3d_surface, &target, findRenderTarget);
4475     }
4476     else
4477     {
4478         target = d3d_surface;
4479     }
4480
4481     if (!target)
4482     {
4483         target = This->d3d_target;
4484         ERR(" (%p) : No DirectDrawSurface found to create the back buffer. Using the front buffer as back buffer. Uncertain consequences\n", This);
4485     }
4486
4487     /* TODO: Return failure if the dimensions do not match, but this shouldn't happen */
4488
4489     *surface = target->WineD3DSurface;
4490     IWineD3DSurface_AddRef(*surface);
4491     target->isRenderTarget = TRUE;
4492
4493     TRACE("Returning wineD3DSurface %p, it belongs to surface %p\n", *surface, d3d_surface);
4494
4495     return D3D_OK;
4496 }
4497
4498 static HRESULT STDMETHODCALLTYPE device_parent_CreateDepthStencilSurface(IWineD3DDeviceParent *iface,
4499         IUnknown *superior, UINT width, UINT height, WINED3DFORMAT format, WINED3DMULTISAMPLE_TYPE multisample_type,
4500         DWORD multisample_quality, BOOL discard, IWineD3DSurface **surface)
4501 {
4502     struct IDirectDrawImpl *This = ddraw_from_device_parent(iface);
4503     IDirectDrawSurfaceImpl *ddraw_surface;
4504     DDSURFACEDESC2 ddsd;
4505     HRESULT hr;
4506
4507     TRACE("iface %p, superior %p, width %u, height %u, format %#x, multisample_type %#x,\n"
4508             "\tmultisample_quality %u, discard %u, surface %p\n",
4509             iface, superior, width, height, format, multisample_type, multisample_quality, discard, surface);
4510
4511     *surface = NULL;
4512
4513     /* Create a DirectDraw surface */
4514     memset(&ddsd, 0, sizeof(ddsd));
4515     ddsd.dwSize = sizeof(ddsd);
4516     ddsd.u4.ddpfPixelFormat.dwSize = sizeof(DDPIXELFORMAT);
4517     ddsd.dwFlags = DDSD_PIXELFORMAT | DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS;
4518     ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
4519     ddsd.dwHeight = height;
4520     ddsd.dwWidth = width;
4521     if (format)
4522     {
4523         PixelFormat_WineD3DtoDD(&ddsd.u4.ddpfPixelFormat, format);
4524     }
4525     else
4526     {
4527         ddsd.dwFlags ^= DDSD_PIXELFORMAT;
4528     }
4529
4530     This->depthstencil = TRUE;
4531     hr = IDirectDraw7_CreateSurface((IDirectDraw7 *)This, &ddsd, (IDirectDrawSurface7 **)&ddraw_surface, NULL);
4532     This->depthstencil = FALSE;
4533     if(FAILED(hr))
4534     {
4535         ERR(" (%p) Creating a DepthStencil Surface failed, result = %x\n", This, hr);
4536         return hr;
4537     }
4538
4539     *surface = ddraw_surface->WineD3DSurface;
4540     IWineD3DSurface_AddRef(*surface);
4541     IDirectDrawSurface7_Release((IDirectDrawSurface7 *)ddraw_surface);
4542
4543     return D3D_OK;
4544 }
4545
4546 static HRESULT STDMETHODCALLTYPE device_parent_CreateVolume(IWineD3DDeviceParent *iface,
4547         IUnknown *superior, UINT width, UINT height, UINT depth, WINED3DFORMAT format,
4548         WINED3DPOOL pool, DWORD usage, IWineD3DVolume **volume)
4549 {
4550     TRACE("iface %p, superior %p, width %u, height %u, depth %u, format %#x, pool %#x, usage %#x, volume %p\n",
4551                 iface, superior, width, height, depth, format, pool, usage, volume);
4552
4553     ERR("Not implemented!\n");
4554
4555     return E_NOTIMPL;
4556 }
4557
4558 static HRESULT STDMETHODCALLTYPE device_parent_CreateSwapChain(IWineD3DDeviceParent *iface,
4559         WINED3DPRESENT_PARAMETERS *present_parameters, IWineD3DSwapChain **swapchain)
4560 {
4561     struct IDirectDrawImpl *This = ddraw_from_device_parent(iface);
4562     IDirectDrawSurfaceImpl *iterator;
4563     IParentImpl *object;
4564     HRESULT hr;
4565
4566     TRACE("iface %p, present_parameters %p, swapchain %p\n", iface, present_parameters, swapchain);
4567
4568     object = HeapAlloc(GetProcessHeap(),  HEAP_ZERO_MEMORY, sizeof(IParentImpl));
4569     if (!object)
4570     {
4571         FIXME("Allocation of memory failed\n");
4572         *swapchain = NULL;
4573         return DDERR_OUTOFVIDEOMEMORY;
4574     }
4575
4576     object->lpVtbl = &IParent_Vtbl;
4577     object->ref = 1;
4578
4579     hr = IWineD3DDevice_CreateSwapChain(This->wineD3DDevice, present_parameters,
4580             swapchain, (IUnknown *)object, This->ImplType);
4581     if (FAILED(hr))
4582     {
4583         FIXME("(%p) CreateSwapChain failed, returning %#x\n", iface, hr);
4584         HeapFree(GetProcessHeap(), 0 , object);
4585         *swapchain = NULL;
4586         return hr;
4587     }
4588
4589     object->child = (IUnknown *)*swapchain;
4590     This->d3d_target->wineD3DSwapChain = *swapchain;
4591     iterator = This->d3d_target->complex_array[0];
4592     while (iterator)
4593     {
4594         iterator->wineD3DSwapChain = *swapchain;
4595         iterator = iterator->complex_array[0];
4596     }
4597
4598     return hr;
4599 }
4600
4601 const IWineD3DDeviceParentVtbl ddraw_wined3d_device_parent_vtbl =
4602 {
4603     /* IUnknown methods */
4604     device_parent_QueryInterface,
4605     device_parent_AddRef,
4606     device_parent_Release,
4607     /* IWineD3DDeviceParent methods */
4608     device_parent_WineD3DDeviceCreated,
4609     device_parent_CreateSurface,
4610     device_parent_CreateRenderTarget,
4611     device_parent_CreateDepthStencilSurface,
4612     device_parent_CreateVolume,
4613     device_parent_CreateSwapChain,
4614 };