ddraw: Add a separate function for ddraw initialization.
[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 "ddraw_private.h"
27
28 WINE_DEFAULT_DEBUG_CHANNEL(ddraw);
29
30 /* Device identifier. Don't relay it to WineD3D */
31 static const DDDEVICEIDENTIFIER2 deviceidentifier =
32 {
33     "display",
34     "DirectDraw HAL",
35     { { 0x00010001, 0x00010001 } },
36     0, 0, 0, 0,
37     /* a8373c10-7ac4-4deb-849a-009844d08b2d */
38     {0xa8373c10,0x7ac4,0x4deb, {0x84,0x9a,0x00,0x98,0x44,0xd0,0x8b,0x2d}},
39     0
40 };
41
42 static void STDMETHODCALLTYPE ddraw_null_wined3d_object_destroyed(void *parent) {}
43
44 const struct wined3d_parent_ops ddraw_null_wined3d_parent_ops =
45 {
46     ddraw_null_wined3d_object_destroyed,
47 };
48
49 static inline IDirectDrawImpl *ddraw_from_ddraw1(IDirectDraw *iface)
50 {
51     return (IDirectDrawImpl *)((char*)iface - FIELD_OFFSET(IDirectDrawImpl, IDirectDraw_vtbl));
52 }
53
54 static inline IDirectDrawImpl *ddraw_from_ddraw2(IDirectDraw2 *iface)
55 {
56     return (IDirectDrawImpl *)((char*)iface - FIELD_OFFSET(IDirectDrawImpl, IDirectDraw2_vtbl));
57 }
58
59 static inline IDirectDrawImpl *ddraw_from_ddraw3(IDirectDraw3 *iface)
60 {
61     return (IDirectDrawImpl *)((char*)iface - FIELD_OFFSET(IDirectDrawImpl, IDirectDraw3_vtbl));
62 }
63
64 static inline IDirectDrawImpl *ddraw_from_ddraw4(IDirectDraw4 *iface)
65 {
66     return (IDirectDrawImpl *)((char*)iface - FIELD_OFFSET(IDirectDrawImpl, IDirectDraw4_vtbl));
67 }
68
69 /*****************************************************************************
70  * IUnknown Methods
71  *****************************************************************************/
72
73 /*****************************************************************************
74  * IDirectDraw7::QueryInterface
75  *
76  * Queries different interfaces of the DirectDraw object. It can return
77  * IDirectDraw interfaces in version 1, 2, 4 and 7, and IDirect3D interfaces
78  * in version 1, 2, 3 and 7. An IDirect3DDevice can be created with this
79  * method.
80  * The returned interface is AddRef()-ed before it's returned
81  *
82  * Used for version 1, 2, 4 and 7
83  *
84  * Params:
85  *  refiid: Interface ID asked for
86  *  obj: Used to return the interface pointer
87  *
88  * Returns:
89  *  S_OK if an interface was found
90  *  E_NOINTERFACE if the requested interface wasn't found
91  *
92  *****************************************************************************/
93 static HRESULT WINAPI ddraw7_QueryInterface(IDirectDraw7 *iface, REFIID refiid, void **obj)
94 {
95     IDirectDrawImpl *This = (IDirectDrawImpl *)iface;
96
97     TRACE("(%p)->(%s,%p)\n", This, debugstr_guid(refiid), obj);
98
99     /* Can change surface impl type */
100     EnterCriticalSection(&ddraw_cs);
101
102     /* According to COM docs, if the QueryInterface fails, obj should be set to NULL */
103     *obj = NULL;
104
105     if(!refiid)
106     {
107         LeaveCriticalSection(&ddraw_cs);
108         return DDERR_INVALIDPARAMS;
109     }
110
111     /* Check DirectDraw Interfaces */
112     if ( IsEqualGUID( &IID_IUnknown, refiid ) ||
113          IsEqualGUID( &IID_IDirectDraw7, refiid ) )
114     {
115         *obj = This;
116         TRACE("(%p) Returning IDirectDraw7 interface at %p\n", This, *obj);
117     }
118     else if ( IsEqualGUID( &IID_IDirectDraw4, refiid ) )
119     {
120         *obj = &This->IDirectDraw4_vtbl;
121         TRACE("(%p) Returning IDirectDraw4 interface at %p\n", This, *obj);
122     }
123     else if ( IsEqualGUID( &IID_IDirectDraw3, refiid ) )
124     {
125         /* This Interface exists in ddrawex.dll, it is implemented in a wrapper */
126         WARN("IDirectDraw3 is not valid in ddraw.dll\n");
127         *obj = NULL;
128         LeaveCriticalSection(&ddraw_cs);
129         return E_NOINTERFACE;
130     }
131     else if ( IsEqualGUID( &IID_IDirectDraw2, refiid ) )
132     {
133         *obj = &This->IDirectDraw2_vtbl;
134         TRACE("(%p) Returning IDirectDraw2 interface at %p\n", This, *obj);
135     }
136     else if ( IsEqualGUID( &IID_IDirectDraw, refiid ) )
137     {
138         *obj = &This->IDirectDraw_vtbl;
139         TRACE("(%p) Returning IDirectDraw interface at %p\n", This, *obj);
140     }
141
142     /* Direct3D
143      * The refcount unit test revealed that an IDirect3D7 interface can only be queried
144      * from a DirectDraw object that was created as an IDirectDraw7 interface. No idea
145      * who had this idea and why. The older interfaces can query and IDirect3D version
146      * because they are all created as IDirectDraw(1). This isn't really crucial behavior,
147      * and messy to implement with the common creation function, so it has been left out here.
148      */
149     else if ( IsEqualGUID( &IID_IDirect3D  , refiid ) ||
150               IsEqualGUID( &IID_IDirect3D2 , refiid ) ||
151               IsEqualGUID( &IID_IDirect3D3 , refiid ) ||
152               IsEqualGUID( &IID_IDirect3D7 , refiid ) )
153     {
154         /* Check the surface implementation */
155         if(This->ImplType == SURFACE_UNKNOWN)
156         {
157             /* Apps may create the IDirect3D Interface before the primary surface.
158              * set the surface implementation */
159             This->ImplType = SURFACE_OPENGL;
160             TRACE("(%p) Choosing OpenGL surfaces because a Direct3D interface was requested\n", This);
161         }
162         else if(This->ImplType != SURFACE_OPENGL && DefaultSurfaceType == SURFACE_UNKNOWN)
163         {
164             ERR("(%p) The App is requesting a D3D device, but a non-OpenGL surface type was choosen. Prepare for trouble!\n", This);
165             ERR(" (%p) You may want to contact wine-devel for help\n", This);
166             /* Should I assert(0) here??? */
167         }
168         else if(This->ImplType != SURFACE_OPENGL)
169         {
170             WARN("The app requests a Direct3D interface, but non-opengl surfaces where set in winecfg\n");
171             /* Do not abort here, only reject 3D Device creation */
172         }
173
174         if ( IsEqualGUID( &IID_IDirect3D  , refiid ) )
175         {
176             This->d3dversion = 1;
177             *obj = &This->IDirect3D_vtbl;
178             TRACE(" returning Direct3D interface at %p.\n", *obj);
179         }
180         else if ( IsEqualGUID( &IID_IDirect3D2  , refiid ) )
181         {
182             This->d3dversion = 2;
183             *obj = &This->IDirect3D2_vtbl;
184             TRACE(" returning Direct3D2 interface at %p.\n", *obj);
185         }
186         else if ( IsEqualGUID( &IID_IDirect3D3  , refiid ) )
187         {
188             This->d3dversion = 3;
189             *obj = &This->IDirect3D3_vtbl;
190             TRACE(" returning Direct3D3 interface at %p.\n", *obj);
191         }
192         else if(IsEqualGUID( &IID_IDirect3D7  , refiid ))
193         {
194             This->d3dversion = 7;
195             *obj = &This->IDirect3D7_vtbl;
196             TRACE(" returning Direct3D7 interface at %p.\n", *obj);
197         }
198     }
199     else if (IsEqualGUID(refiid, &IID_IWineD3DDeviceParent))
200     {
201         *obj = &This->device_parent_vtbl;
202     }
203
204     /* Unknown interface */
205     else
206     {
207         ERR("(%p)->(%s, %p): No interface found\n", This, debugstr_guid(refiid), obj);
208         LeaveCriticalSection(&ddraw_cs);
209         return E_NOINTERFACE;
210     }
211
212     IUnknown_AddRef( (IUnknown *) *obj );
213     LeaveCriticalSection(&ddraw_cs);
214     return S_OK;
215 }
216
217 static HRESULT WINAPI ddraw4_QueryInterface(IDirectDraw4 *iface, REFIID riid, void **object)
218 {
219     TRACE("iface %p, riid %s, object %p.\n", iface, debugstr_guid(riid), object);
220
221     return ddraw7_QueryInterface((IDirectDraw7 *)ddraw_from_ddraw4(iface), riid, object);
222 }
223
224 static HRESULT WINAPI ddraw3_QueryInterface(IDirectDraw3 *iface, REFIID riid, void **object)
225 {
226     TRACE("iface %p, riid %s, object %p.\n", iface, debugstr_guid(riid), object);
227
228     return ddraw7_QueryInterface((IDirectDraw7 *)ddraw_from_ddraw3(iface), riid, object);
229 }
230
231 static HRESULT WINAPI ddraw2_QueryInterface(IDirectDraw2 *iface, REFIID riid, void **object)
232 {
233     TRACE("iface %p, riid %s, object %p.\n", iface, debugstr_guid(riid), object);
234
235     return ddraw7_QueryInterface((IDirectDraw7 *)ddraw_from_ddraw2(iface), riid, object);
236 }
237
238 static HRESULT WINAPI ddraw1_QueryInterface(IDirectDraw *iface, REFIID riid, void **object)
239 {
240     TRACE("iface %p, riid %s, object %p.\n", iface, debugstr_guid(riid), object);
241
242     return ddraw7_QueryInterface((IDirectDraw7 *)ddraw_from_ddraw1(iface), riid, object);
243 }
244
245 static HRESULT WINAPI d3d7_QueryInterface(IDirect3D7 *iface, REFIID riid, void **object)
246 {
247     TRACE("iface %p, riid %s, object %p.\n", iface, debugstr_guid(riid), object);
248
249     return ddraw7_QueryInterface((IDirectDraw7 *)ddraw_from_d3d7(iface), riid, object);
250 }
251
252 static HRESULT WINAPI d3d3_QueryInterface(IDirect3D3 *iface, REFIID riid, void **object)
253 {
254     TRACE("iface %p, riid %s, object %p.\n", iface, debugstr_guid(riid), object);
255
256     return ddraw7_QueryInterface((IDirectDraw7 *)ddraw_from_d3d3(iface), riid, object);
257 }
258
259 static HRESULT WINAPI d3d2_QueryInterface(IDirect3D2 *iface, REFIID riid, void **object)
260 {
261     TRACE("iface %p, riid %s, object %p.\n", iface, debugstr_guid(riid), object);
262
263     return ddraw7_QueryInterface((IDirectDraw7 *)ddraw_from_d3d2(iface), riid, object);
264 }
265
266 static HRESULT WINAPI d3d1_QueryInterface(IDirect3D *iface, REFIID riid, void **object)
267 {
268     TRACE("iface %p, riid %s, object %p.\n", iface, debugstr_guid(riid), object);
269
270     return ddraw7_QueryInterface((IDirectDraw7 *)ddraw_from_d3d1(iface), riid, object);
271 }
272
273 /*****************************************************************************
274  * IDirectDraw7::AddRef
275  *
276  * Increases the interfaces refcount, basically
277  *
278  * DDraw refcounting is a bit tricky. The different DirectDraw interface
279  * versions have individual refcounts, but the IDirect3D interfaces do not.
280  * All interfaces are from one object, that means calling QueryInterface on an
281  * IDirectDraw7 interface for an IDirectDraw4 interface does not create a new
282  * IDirectDrawImpl object.
283  *
284  * That means all AddRef and Release implementations of IDirectDrawX work
285  * with their own counter, and IDirect3DX::AddRef thunk to IDirectDraw (1),
286  * except of IDirect3D7 which thunks to IDirectDraw7
287  *
288  * Returns: The new refcount
289  *
290  *****************************************************************************/
291 static ULONG WINAPI ddraw7_AddRef(IDirectDraw7 *iface)
292 {
293     IDirectDrawImpl *This = (IDirectDrawImpl *)iface;
294     ULONG ref = InterlockedIncrement(&This->ref7);
295
296     TRACE("(%p) : incrementing IDirectDraw7 refcount from %u.\n", This, ref -1);
297
298     if(ref == 1) InterlockedIncrement(&This->numIfaces);
299
300     return ref;
301 }
302
303 static ULONG WINAPI ddraw4_AddRef(IDirectDraw4 *iface)
304 {
305     IDirectDrawImpl *ddraw = ddraw_from_ddraw4(iface);
306     ULONG ref = InterlockedIncrement(&ddraw->ref4);
307
308     TRACE("%p increasing refcount to %u.\n", ddraw, ref);
309
310     if (ref == 1) InterlockedIncrement(&ddraw->numIfaces);
311
312     return ref;
313 }
314
315 static ULONG WINAPI ddraw3_AddRef(IDirectDraw3 *iface)
316 {
317     IDirectDrawImpl *ddraw = ddraw_from_ddraw3(iface);
318     ULONG ref = InterlockedIncrement(&ddraw->ref3);
319
320     TRACE("%p increasing refcount to %u.\n", ddraw, ref);
321
322     if (ref == 1) InterlockedIncrement(&ddraw->numIfaces);
323
324     return ref;
325 }
326
327 static ULONG WINAPI ddraw2_AddRef(IDirectDraw2 *iface)
328 {
329     IDirectDrawImpl *ddraw = ddraw_from_ddraw2(iface);
330     ULONG ref = InterlockedIncrement(&ddraw->ref2);
331
332     TRACE("%p increasing refcount to %u.\n", ddraw, ref);
333
334     if (ref == 1) InterlockedIncrement(&ddraw->numIfaces);
335
336     return ref;
337 }
338
339 static ULONG WINAPI ddraw1_AddRef(IDirectDraw *iface)
340 {
341     IDirectDrawImpl *ddraw = ddraw_from_ddraw1(iface);
342     ULONG ref = InterlockedIncrement(&ddraw->ref1);
343
344     TRACE("%p increasing refcount to %u.\n", ddraw, ref);
345
346     if (ref == 1) InterlockedIncrement(&ddraw->numIfaces);
347
348     return ref;
349 }
350
351 static ULONG WINAPI d3d7_AddRef(IDirect3D7 *iface)
352 {
353     TRACE("iface %p.\n", iface);
354
355     return ddraw7_AddRef((IDirectDraw7 *)ddraw_from_d3d7(iface));
356 }
357
358 static ULONG WINAPI d3d3_AddRef(IDirect3D3 *iface)
359 {
360     TRACE("iface %p.\n", iface);
361
362     return ddraw1_AddRef((IDirectDraw *)&ddraw_from_d3d3(iface)->IDirectDraw_vtbl);
363 }
364
365 static ULONG WINAPI d3d2_AddRef(IDirect3D2 *iface)
366 {
367     TRACE("iface %p.\n", iface);
368
369     return ddraw1_AddRef((IDirectDraw *)&ddraw_from_d3d2(iface)->IDirectDraw_vtbl);
370 }
371
372 static ULONG WINAPI d3d1_AddRef(IDirect3D *iface)
373 {
374     TRACE("iface %p.\n", iface);
375
376     return ddraw1_AddRef((IDirectDraw *)&ddraw_from_d3d1(iface)->IDirectDraw_vtbl);
377 }
378
379 /*****************************************************************************
380  * ddraw_destroy
381  *
382  * Destroys a ddraw object if all refcounts are 0. This is to share code
383  * between the IDirectDrawX::Release functions
384  *
385  * Params:
386  *  This: DirectDraw object to destroy
387  *
388  *****************************************************************************/
389 static void ddraw_destroy(IDirectDrawImpl *This)
390 {
391     IDirectDraw7_SetCooperativeLevel((IDirectDraw7 *)This, NULL, DDSCL_NORMAL);
392     IDirectDraw7_RestoreDisplayMode((IDirectDraw7 *)This);
393
394     /* Destroy the device window if we created one */
395     if(This->devicewindow != 0)
396     {
397         TRACE(" (%p) Destroying the device window %p\n", This, This->devicewindow);
398         DestroyWindow(This->devicewindow);
399         This->devicewindow = 0;
400     }
401
402     EnterCriticalSection(&ddraw_cs);
403     list_remove(&This->ddraw_list_entry);
404     LeaveCriticalSection(&ddraw_cs);
405
406     /* Release the attached WineD3D stuff */
407     IWineD3DDevice_Release(This->wineD3DDevice);
408     IWineD3D_Release(This->wineD3D);
409
410     /* Now free the object */
411     HeapFree(GetProcessHeap(), 0, This);
412 }
413
414 /*****************************************************************************
415  * IDirectDraw7::Release
416  *
417  * Decreases the refcount. If the refcount falls to 0, the object is destroyed
418  *
419  * Returns: The new refcount
420  *****************************************************************************/
421 static ULONG WINAPI ddraw7_Release(IDirectDraw7 *iface)
422 {
423     IDirectDrawImpl *This = (IDirectDrawImpl *)iface;
424     ULONG ref = InterlockedDecrement(&This->ref7);
425
426     TRACE("(%p)->() decrementing IDirectDraw7 refcount from %u.\n", This, ref +1);
427
428     if (!ref && !InterlockedDecrement(&This->numIfaces))
429         ddraw_destroy(This);
430
431     return ref;
432 }
433
434 static ULONG WINAPI ddraw4_Release(IDirectDraw4 *iface)
435 {
436     IDirectDrawImpl *ddraw = ddraw_from_ddraw4(iface);
437     ULONG ref = InterlockedDecrement(&ddraw->ref4);
438
439     TRACE("%p decreasing refcount to %u.\n", ddraw, ref);
440
441     if (!ref && !InterlockedDecrement(&ddraw->numIfaces))
442         ddraw_destroy(ddraw);
443
444     return ref;
445 }
446
447 static ULONG WINAPI ddraw3_Release(IDirectDraw3 *iface)
448 {
449     IDirectDrawImpl *ddraw = ddraw_from_ddraw3(iface);
450     ULONG ref = InterlockedDecrement(&ddraw->ref3);
451
452     TRACE("%p decreasing refcount to %u.\n", ddraw, ref);
453
454     if (!ref && !InterlockedDecrement(&ddraw->numIfaces))
455         ddraw_destroy(ddraw);
456
457     return ref;
458 }
459
460 static ULONG WINAPI ddraw2_Release(IDirectDraw2 *iface)
461 {
462     IDirectDrawImpl *ddraw = ddraw_from_ddraw2(iface);
463     ULONG ref = InterlockedDecrement(&ddraw->ref2);
464
465     TRACE("%p decreasing refcount to %u.\n", ddraw, ref);
466
467     if (!ref && !InterlockedDecrement(&ddraw->numIfaces))
468         ddraw_destroy(ddraw);
469
470     return ref;
471 }
472
473 static ULONG WINAPI ddraw1_Release(IDirectDraw *iface)
474 {
475     IDirectDrawImpl *ddraw = ddraw_from_ddraw1(iface);
476     ULONG ref = InterlockedDecrement(&ddraw->ref1);
477
478     TRACE("%p decreasing refcount to %u.\n", ddraw, ref);
479
480     if (!ref && !InterlockedDecrement(&ddraw->numIfaces))
481         ddraw_destroy(ddraw);
482
483     return ref;
484 }
485
486 static ULONG WINAPI d3d7_Release(IDirect3D7 *iface)
487 {
488     TRACE("iface %p.\n", iface);
489
490     return ddraw7_Release((IDirectDraw7 *)ddraw_from_d3d7(iface));
491 }
492
493 static ULONG WINAPI d3d3_Release(IDirect3D3 *iface)
494 {
495     TRACE("iface %p.\n", iface);
496
497     return ddraw1_Release((IDirectDraw *)&ddraw_from_d3d3(iface)->IDirectDraw_vtbl);
498 }
499
500 static ULONG WINAPI d3d2_Release(IDirect3D2 *iface)
501 {
502     TRACE("iface %p.\n", iface);
503
504     return ddraw1_Release((IDirectDraw *)&ddraw_from_d3d2(iface)->IDirectDraw_vtbl);
505 }
506
507 static ULONG WINAPI d3d1_Release(IDirect3D *iface)
508 {
509     TRACE("iface %p.\n", iface);
510
511     return ddraw1_Release((IDirectDraw *)&ddraw_from_d3d1(iface)->IDirectDraw_vtbl);
512 }
513
514 /*****************************************************************************
515  * IDirectDraw methods
516  *****************************************************************************/
517
518 /*****************************************************************************
519  * IDirectDraw7::SetCooperativeLevel
520  *
521  * Sets the cooperative level for the DirectDraw object, and the window
522  * assigned to it. The cooperative level determines the general behavior
523  * of the DirectDraw application
524  *
525  * Warning: This is quite tricky, as it's not really documented which
526  * cooperative levels can be combined with each other. If a game fails
527  * after this function, try to check the cooperative levels passed on
528  * Windows, and if it returns something different.
529  *
530  * If you think that this function caused the failure because it writes a
531  * fixme, be sure to run again with a +ddraw trace.
532  *
533  * What is known about cooperative levels (See the ddraw modes test):
534  * DDSCL_EXCLUSIVE and DDSCL_FULLSCREEN must be used with each other
535  * DDSCL_NORMAL is not compatible with DDSCL_EXCLUSIVE or DDSCL_FULLSCREEN
536  * DDSCL_SETFOCUSWINDOW can be passed only in DDSCL_NORMAL mode, but after that
537  * DDSCL_FULLSCREEN can be activated
538  * DDSCL_SETFOCUSWINDOW may only be used with DDSCL_NOWINDOWCHANGES
539  *
540  * Handled flags: DDSCL_NORMAL, DDSCL_FULLSCREEN, DDSCL_EXCLUSIVE,
541  *                DDSCL_SETFOCUSWINDOW (partially),
542  *                DDSCL_MULTITHREADED (work in progress)
543  *
544  * Unhandled flags, which should be implemented
545  *  DDSCL_SETDEVICEWINDOW: Sets a window specially used for rendering (I don't
546  *  expect any difference to a normal window for wine)
547  *  DDSCL_CREATEDEVICEWINDOW: Tells ddraw to create its own window for
548  *  rendering (Possible test case: Half-Life)
549  *
550  * Unsure about these: DDSCL_FPUSETUP DDSCL_FPURESERVE
551  *
552  * These don't seem very important for wine:
553  *  DDSCL_ALLOWREBOOT, DDSCL_NOWINDOWCHANGES, DDSCL_ALLOWMODEX
554  *
555  * Returns:
556  *  DD_OK if the cooperative level was set successfully
557  *  DDERR_INVALIDPARAMS if the passed cooperative level combination is invalid
558  *  DDERR_HWNDALREADYSET if DDSCL_SETFOCUSWINDOW is passed in exclusive mode
559  *   (Probably others too, have to investigate)
560  *
561  *****************************************************************************/
562 static HRESULT WINAPI ddraw7_SetCooperativeLevel(IDirectDraw7 *iface, HWND hwnd, DWORD cooplevel)
563 {
564     IDirectDrawImpl *This = (IDirectDrawImpl *)iface;
565     HWND window;
566
567     TRACE("(%p)->(%p,%08x)\n",This,hwnd,cooplevel);
568     DDRAW_dump_cooperativelevel(cooplevel);
569
570     EnterCriticalSection(&ddraw_cs);
571
572     /* Get the old window */
573     window = This->dest_window;
574
575     /* Tests suggest that we need one of them: */
576     if(!(cooplevel & (DDSCL_SETFOCUSWINDOW |
577                       DDSCL_NORMAL         |
578                       DDSCL_EXCLUSIVE      )))
579     {
580         TRACE("Incorrect cooplevel flags, returning DDERR_INVALIDPARAMS\n");
581         LeaveCriticalSection(&ddraw_cs);
582         return DDERR_INVALIDPARAMS;
583     }
584
585     /* Handle those levels first which set various hwnds */
586     if(cooplevel & DDSCL_SETFOCUSWINDOW)
587     {
588         /* This isn't compatible with a lot of flags */
589         if(cooplevel & ( DDSCL_MULTITHREADED   |
590                          DDSCL_FPUSETUP        |
591                          DDSCL_FPUPRESERVE     |
592                          DDSCL_ALLOWREBOOT     |
593                          DDSCL_ALLOWMODEX      |
594                          DDSCL_SETDEVICEWINDOW |
595                          DDSCL_NORMAL          |
596                          DDSCL_EXCLUSIVE       |
597                          DDSCL_FULLSCREEN      ) )
598         {
599             TRACE("Called with incompatible flags, returning DDERR_INVALIDPARAMS\n");
600             LeaveCriticalSection(&ddraw_cs);
601             return DDERR_INVALIDPARAMS;
602         }
603         else if( (This->cooperative_level & DDSCL_FULLSCREEN) && window)
604         {
605             TRACE("Setting DDSCL_SETFOCUSWINDOW with an already set window, returning DDERR_HWNDALREADYSET\n");
606             LeaveCriticalSection(&ddraw_cs);
607             return DDERR_HWNDALREADYSET;
608         }
609
610         This->focuswindow = hwnd;
611         /* Won't use the hwnd param for anything else */
612         hwnd = NULL;
613
614         /* Use the focus window for drawing too */
615         This->dest_window = This->focuswindow;
616
617         /* Destroy the device window, if we have one */
618         if(This->devicewindow)
619         {
620             DestroyWindow(This->devicewindow);
621             This->devicewindow = NULL;
622         }
623     }
624     /* DDSCL_NORMAL or DDSCL_FULLSCREEN | DDSCL_EXCLUSIVE */
625     if(cooplevel & DDSCL_NORMAL)
626     {
627         /* Can't coexist with fullscreen or exclusive */
628         if(cooplevel & (DDSCL_FULLSCREEN | DDSCL_EXCLUSIVE) )
629         {
630             TRACE("(%p) DDSCL_NORMAL is not compative with DDSCL_FULLSCREEN or DDSCL_EXCLUSIVE\n", This);
631             LeaveCriticalSection(&ddraw_cs);
632             return DDERR_INVALIDPARAMS;
633         }
634
635         /* Switching from fullscreen? */
636         if(This->cooperative_level & DDSCL_FULLSCREEN)
637         {
638             This->cooperative_level &= ~DDSCL_FULLSCREEN;
639             This->cooperative_level &= ~DDSCL_EXCLUSIVE;
640             This->cooperative_level &= ~DDSCL_ALLOWMODEX;
641
642             IWineD3DDevice_ReleaseFocusWindow(This->wineD3DDevice);
643         }
644
645         /* Don't override focus windows or private device windows */
646         if( hwnd &&
647             !(This->focuswindow) &&
648             !(This->devicewindow) &&
649             (hwnd != window) )
650         {
651             This->dest_window = hwnd;
652         }
653     }
654     else if(cooplevel & DDSCL_FULLSCREEN)
655     {
656         /* Needs DDSCL_EXCLUSIVE */
657         if(!(cooplevel & DDSCL_EXCLUSIVE) )
658         {
659             TRACE("(%p) DDSCL_FULLSCREEN needs DDSCL_EXCLUSIVE\n", This);
660             LeaveCriticalSection(&ddraw_cs);
661             return DDERR_INVALIDPARAMS;
662         }
663         /* Need a HWND
664         if(hwnd == 0)
665         {
666             TRACE("(%p) DDSCL_FULLSCREEN needs a HWND\n", This);
667             return DDERR_INVALIDPARAMS;
668         }
669         */
670
671         This->cooperative_level &= ~DDSCL_NORMAL;
672
673         /* Don't override focus windows or private device windows */
674         if( hwnd &&
675             !(This->focuswindow) &&
676             !(This->devicewindow) &&
677             (hwnd != window) )
678         {
679             HRESULT hr = IWineD3DDevice_AcquireFocusWindow(This->wineD3DDevice, hwnd);
680             if (FAILED(hr))
681             {
682                 ERR("Failed to acquire focus window, hr %#x.\n", hr);
683                 LeaveCriticalSection(&ddraw_cs);
684                 return hr;
685             }
686             This->dest_window = hwnd;
687         }
688     }
689     else if(cooplevel & DDSCL_EXCLUSIVE)
690     {
691         TRACE("(%p) DDSCL_EXCLUSIVE needs DDSCL_FULLSCREEN\n", This);
692         LeaveCriticalSection(&ddraw_cs);
693         return DDERR_INVALIDPARAMS;
694     }
695
696     if(cooplevel & DDSCL_CREATEDEVICEWINDOW)
697     {
698         /* Don't create a device window if a focus window is set */
699         if( !(This->focuswindow) )
700         {
701             HWND devicewindow = CreateWindowExA(0, DDRAW_WINDOW_CLASS_NAME, "DDraw device window",
702                     WS_POPUP, 0, 0, GetSystemMetrics(SM_CXSCREEN), GetSystemMetrics(SM_CYSCREEN),
703                     NULL, NULL, NULL, NULL);
704             if (!devicewindow)
705             {
706                 ERR("Failed to create window, last error %#x.\n", GetLastError());
707                 LeaveCriticalSection(&ddraw_cs);
708                 return E_FAIL;
709             }
710
711             ShowWindow(devicewindow, SW_SHOW);   /* Just to be sure */
712             TRACE("(%p) Created a DDraw device window. HWND=%p\n", This, devicewindow);
713
714             This->devicewindow = devicewindow;
715             This->dest_window = devicewindow;
716         }
717     }
718
719     if(cooplevel & DDSCL_MULTITHREADED && !(This->cooperative_level & DDSCL_MULTITHREADED))
720     {
721         /* Enable thread safety in wined3d */
722         IWineD3DDevice_SetMultithreaded(This->wineD3DDevice);
723     }
724
725     /* Unhandled flags */
726     if(cooplevel & DDSCL_ALLOWREBOOT)
727         WARN("(%p) Unhandled flag DDSCL_ALLOWREBOOT, harmless\n", This);
728     if(cooplevel & DDSCL_ALLOWMODEX)
729         WARN("(%p) Unhandled flag DDSCL_ALLOWMODEX, harmless\n", This);
730     if(cooplevel & DDSCL_FPUSETUP)
731         WARN("(%p) Unhandled flag DDSCL_FPUSETUP, harmless\n", This);
732
733     /* Store the cooperative_level */
734     This->cooperative_level |= cooplevel;
735     TRACE("SetCooperativeLevel retuning DD_OK\n");
736     LeaveCriticalSection(&ddraw_cs);
737     return DD_OK;
738 }
739
740 static HRESULT WINAPI ddraw4_SetCooperativeLevel(IDirectDraw4 *iface, HWND window, DWORD flags)
741 {
742     TRACE("iface %p, window %p, flags %#x.\n", iface, window, flags);
743
744     return ddraw7_SetCooperativeLevel((IDirectDraw7 *)ddraw_from_ddraw4(iface), window, flags);
745 }
746
747 static HRESULT WINAPI ddraw3_SetCooperativeLevel(IDirectDraw3 *iface, HWND window, DWORD flags)
748 {
749     TRACE("iface %p, window %p, flags %#x.\n", iface, window, flags);
750
751     return ddraw7_SetCooperativeLevel((IDirectDraw7 *)ddraw_from_ddraw3(iface), window, flags);
752 }
753
754 static HRESULT WINAPI ddraw2_SetCooperativeLevel(IDirectDraw2 *iface, HWND window, DWORD flags)
755 {
756     TRACE("iface %p, window %p, flags %#x.\n", iface, window, flags);
757
758     return ddraw7_SetCooperativeLevel((IDirectDraw7 *)ddraw_from_ddraw2(iface), window, flags);
759 }
760
761 static HRESULT WINAPI ddraw1_SetCooperativeLevel(IDirectDraw *iface, HWND window, DWORD flags)
762 {
763     TRACE("iface %p, window %p, flags %#x.\n", iface, window, flags);
764
765     return ddraw7_SetCooperativeLevel((IDirectDraw7 *)ddraw_from_ddraw1(iface), window, flags);
766 }
767
768 /*****************************************************************************
769  *
770  * Helper function for SetDisplayMode and RestoreDisplayMode
771  *
772  * Implements DirectDraw's SetDisplayMode, but ignores the value of
773  * ForceRefreshRate, since it is already handled by
774  * ddraw7_SetDisplayMode.  RestoreDisplayMode can use this function
775  * without worrying that ForceRefreshRate will override the refresh rate.  For
776  * argument and return value documentation, see
777  * ddraw7_SetDisplayMode.
778  *
779  *****************************************************************************/
780 static HRESULT ddraw_set_display_mode(IDirectDraw7 *iface, DWORD Width, DWORD Height,
781         DWORD BPP, DWORD RefreshRate, DWORD Flags)
782 {
783     IDirectDrawImpl *This = (IDirectDrawImpl *)iface;
784     WINED3DDISPLAYMODE Mode;
785     HRESULT hr;
786     TRACE("(%p)->(%d,%d,%d,%d,%x): Relay!\n", This, Width, Height, BPP, RefreshRate, Flags);
787
788     EnterCriticalSection(&ddraw_cs);
789     if( !Width || !Height )
790     {
791         ERR("Width=%d, Height=%d, what to do?\n", Width, Height);
792         /* It looks like Need for Speed Porsche Unleashed expects DD_OK here */
793         LeaveCriticalSection(&ddraw_cs);
794         return DD_OK;
795     }
796
797     /* Check the exclusive mode
798     if(!(This->cooperative_level & DDSCL_EXCLUSIVE))
799         return DDERR_NOEXCLUSIVEMODE;
800      * This is WRONG. Don't know if the SDK is completely
801      * wrong and if there are any conditions when DDERR_NOEXCLUSIVE
802      * is returned, but Half-Life 1.1.1.1 (Steam version)
803      * depends on this
804      */
805
806     Mode.Width = Width;
807     Mode.Height = Height;
808     Mode.RefreshRate = RefreshRate;
809     switch(BPP)
810     {
811         case 8:  Mode.Format = WINED3DFMT_P8_UINT;          break;
812         case 15: Mode.Format = WINED3DFMT_B5G5R5X1_UNORM;   break;
813         case 16: Mode.Format = WINED3DFMT_B5G6R5_UNORM;     break;
814         case 24: Mode.Format = WINED3DFMT_B8G8R8_UNORM;     break;
815         case 32: Mode.Format = WINED3DFMT_B8G8R8X8_UNORM;   break;
816     }
817
818     /* TODO: The possible return values from msdn suggest that
819      * the screen mode can't be changed if a surface is locked
820      * or some drawing is in progress
821      */
822
823     /* TODO: Lose the primary surface */
824     hr = IWineD3DDevice_SetDisplayMode(This->wineD3DDevice,
825                                        0, /* First swapchain */
826                                        &Mode);
827     LeaveCriticalSection(&ddraw_cs);
828     switch(hr)
829     {
830         case WINED3DERR_NOTAVAILABLE:       return DDERR_UNSUPPORTED;
831         default:                            return hr;
832     }
833 }
834
835 /*****************************************************************************
836  * IDirectDraw7::SetDisplayMode
837  *
838  * Sets the display screen resolution, color depth and refresh frequency
839  * when in fullscreen mode (in theory).
840  * Possible return values listed in the SDK suggest that this method fails
841  * when not in fullscreen mode, but this is wrong. Windows 2000 happily sets
842  * the display mode in DDSCL_NORMAL mode without an hwnd specified.
843  * It seems to be valid to pass 0 for With and Height, this has to be tested
844  * It could mean that the current video mode should be left as-is. (But why
845  * call it then?)
846  *
847  * Params:
848  *  Height, Width: Screen dimension
849  *  BPP: Color depth in Bits per pixel
850  *  Refreshrate: Screen refresh rate
851  *  Flags: Other stuff
852  *
853  * Returns
854  *  DD_OK on success
855  *
856  *****************************************************************************/
857 static HRESULT WINAPI ddraw7_SetDisplayMode(IDirectDraw7 *iface, DWORD Width, DWORD Height,
858         DWORD BPP, DWORD RefreshRate, DWORD Flags)
859 {
860     if (force_refresh_rate != 0)
861     {
862         TRACE("ForceRefreshRate overriding passed-in refresh rate (%d Hz) to %d Hz\n", RefreshRate, force_refresh_rate);
863         RefreshRate = force_refresh_rate;
864     }
865
866     return ddraw_set_display_mode(iface, Width, Height, BPP, RefreshRate, Flags);
867 }
868
869 static HRESULT WINAPI ddraw4_SetDisplayMode(IDirectDraw4 *iface,
870         DWORD width, DWORD height, DWORD bpp, DWORD refresh_rate, DWORD flags)
871 {
872     TRACE("iface %p, width %u, height %u, bpp %u, refresh_rate %u, flags %#x.\n",
873             iface, width, height, bpp, refresh_rate, flags);
874
875     return ddraw7_SetDisplayMode((IDirectDraw7 *)ddraw_from_ddraw4(iface),
876             width, height, bpp, refresh_rate, flags);
877 }
878
879 static HRESULT WINAPI ddraw3_SetDisplayMode(IDirectDraw3 *iface,
880         DWORD width, DWORD height, DWORD bpp, DWORD refresh_rate, DWORD flags)
881 {
882     TRACE("iface %p, width %u, height %u, bpp %u, refresh_rate %u, flags %#x.\n",
883             iface, width, height, bpp, refresh_rate, flags);
884
885     return ddraw7_SetDisplayMode((IDirectDraw7 *)ddraw_from_ddraw3(iface),
886             width, height, bpp, refresh_rate, flags);
887 }
888
889 static HRESULT WINAPI ddraw2_SetDisplayMode(IDirectDraw2 *iface,
890         DWORD width, DWORD height, DWORD bpp, DWORD refresh_rate, DWORD flags)
891 {
892     TRACE("iface %p, width %u, height %u, bpp %u, refresh_rate %u, flags %#x.\n",
893             iface, width, height, bpp, refresh_rate, flags);
894
895     return ddraw7_SetDisplayMode((IDirectDraw7 *)ddraw_from_ddraw2(iface),
896             width, height, bpp, refresh_rate, flags);
897 }
898
899 static HRESULT WINAPI ddraw1_SetDisplayMode(IDirectDraw *iface, DWORD width, DWORD height, DWORD bpp)
900 {
901     TRACE("iface %p, width %u, height %u, bpp %u.\n", iface, width, height, bpp);
902
903     return ddraw7_SetDisplayMode((IDirectDraw7 *)ddraw_from_ddraw1(iface), width, height, bpp, 0, 0);
904 }
905
906 /*****************************************************************************
907  * IDirectDraw7::RestoreDisplayMode
908  *
909  * Restores the display mode to what it was at creation time. Basically.
910  *
911  * A problem arises when there are 2 DirectDraw objects using the same hwnd:
912  *  -> DD_1 finds the screen at 1400x1050x32 when created, sets it to 640x480x16
913  *  -> DD_2 is created, finds the screen at 640x480x16, sets it to 1024x768x32
914  *  -> DD_1 is released. The screen should be left at 1024x768x32.
915  *  -> DD_2 is released. The screen should be set to 1400x1050x32
916  * This case is unhandled right now, but Empire Earth does it this way.
917  * (But perhaps there is something in SetCooperativeLevel to prevent this)
918  *
919  * The msdn says that this method resets the display mode to what it was before
920  * SetDisplayMode was called. What if SetDisplayModes is called 2 times??
921  *
922  * Returns
923  *  DD_OK on success
924  *  DDERR_NOEXCLUSIVE mode if the device isn't in fullscreen mode
925  *
926  *****************************************************************************/
927 static HRESULT WINAPI ddraw7_RestoreDisplayMode(IDirectDraw7 *iface)
928 {
929     IDirectDrawImpl *This = (IDirectDrawImpl *)iface;
930     TRACE("(%p)\n", This);
931
932     return ddraw_set_display_mode(iface, This->orig_width, This->orig_height, This->orig_bpp, 0, 0);
933 }
934
935 static HRESULT WINAPI ddraw4_RestoreDisplayMode(IDirectDraw4 *iface)
936 {
937     TRACE("iface %p.\n", iface);
938
939     return ddraw7_RestoreDisplayMode((IDirectDraw7 *)ddraw_from_ddraw4(iface));
940 }
941
942 static HRESULT WINAPI ddraw3_RestoreDisplayMode(IDirectDraw3 *iface)
943 {
944     TRACE("iface %p.\n", iface);
945
946     return ddraw7_RestoreDisplayMode((IDirectDraw7 *)ddraw_from_ddraw3(iface));
947 }
948
949 static HRESULT WINAPI ddraw2_RestoreDisplayMode(IDirectDraw2 *iface)
950 {
951     TRACE("iface %p.\n", iface);
952
953     return ddraw7_RestoreDisplayMode((IDirectDraw7 *)ddraw_from_ddraw2(iface));
954 }
955
956 static HRESULT WINAPI ddraw1_RestoreDisplayMode(IDirectDraw *iface)
957 {
958     TRACE("iface %p.\n", iface);
959
960     return ddraw7_RestoreDisplayMode((IDirectDraw7 *)ddraw_from_ddraw1(iface));
961 }
962
963 /*****************************************************************************
964  * IDirectDraw7::GetCaps
965  *
966  * Returns the drives capabilities
967  *
968  * Used for version 1, 2, 4 and 7
969  *
970  * Params:
971  *  DriverCaps: Structure to write the Hardware accelerated caps to
972  *  HelCaps: Structure to write the emulation caps to
973  *
974  * Returns
975  *  This implementation returns DD_OK only
976  *
977  *****************************************************************************/
978 static HRESULT WINAPI ddraw7_GetCaps(IDirectDraw7 *iface, DDCAPS *DriverCaps, DDCAPS *HELCaps)
979 {
980     IDirectDrawImpl *This = (IDirectDrawImpl *)iface;
981     DDCAPS caps;
982     WINED3DCAPS winecaps;
983     HRESULT hr;
984     DDSCAPS2 ddscaps = {0, 0, 0, 0};
985     TRACE("(%p)->(%p,%p)\n", This, DriverCaps, HELCaps);
986
987     /* One structure must be != NULL */
988     if( (!DriverCaps) && (!HELCaps) )
989     {
990         ERR("(%p) Invalid params to ddraw7_GetCaps\n", This);
991         return DDERR_INVALIDPARAMS;
992     }
993
994     memset(&caps, 0, sizeof(caps));
995     memset(&winecaps, 0, sizeof(winecaps));
996     caps.dwSize = sizeof(caps);
997     EnterCriticalSection(&ddraw_cs);
998     hr = IWineD3DDevice_GetDeviceCaps(This->wineD3DDevice, &winecaps);
999     if(FAILED(hr)) {
1000         WARN("IWineD3DDevice::GetDeviceCaps failed\n");
1001         LeaveCriticalSection(&ddraw_cs);
1002         return hr;
1003     }
1004
1005     hr = IDirectDraw7_GetAvailableVidMem(iface, &ddscaps, &caps.dwVidMemTotal, &caps.dwVidMemFree);
1006     LeaveCriticalSection(&ddraw_cs);
1007     if(FAILED(hr)) {
1008         WARN("IDirectDraw7::GetAvailableVidMem failed\n");
1009         return hr;
1010     }
1011
1012     caps.dwCaps = winecaps.DirectDrawCaps.Caps;
1013     caps.dwCaps2 = winecaps.DirectDrawCaps.Caps2;
1014     caps.dwCKeyCaps = winecaps.DirectDrawCaps.CKeyCaps;
1015     caps.dwFXCaps = winecaps.DirectDrawCaps.FXCaps;
1016     caps.dwPalCaps = winecaps.DirectDrawCaps.PalCaps;
1017     caps.ddsCaps.dwCaps = winecaps.DirectDrawCaps.ddsCaps;
1018     caps.dwSVBCaps = winecaps.DirectDrawCaps.SVBCaps;
1019     caps.dwSVBCKeyCaps = winecaps.DirectDrawCaps.SVBCKeyCaps;
1020     caps.dwSVBFXCaps = winecaps.DirectDrawCaps.SVBFXCaps;
1021     caps.dwVSBCaps = winecaps.DirectDrawCaps.VSBCaps;
1022     caps.dwVSBCKeyCaps = winecaps.DirectDrawCaps.VSBCKeyCaps;
1023     caps.dwVSBFXCaps = winecaps.DirectDrawCaps.VSBFXCaps;
1024     caps.dwSSBCaps = winecaps.DirectDrawCaps.SSBCaps;
1025     caps.dwSSBCKeyCaps = winecaps.DirectDrawCaps.SSBCKeyCaps;
1026     caps.dwSSBFXCaps = winecaps.DirectDrawCaps.SSBFXCaps;
1027
1028     /* Even if WineD3D supports 3D rendering, remove the cap if ddraw is configured
1029      * not to use it
1030      */
1031     if(DefaultSurfaceType == SURFACE_GDI) {
1032         caps.dwCaps &= ~DDCAPS_3D;
1033         caps.ddsCaps.dwCaps &= ~(DDSCAPS_3DDEVICE | DDSCAPS_MIPMAP | DDSCAPS_TEXTURE | DDSCAPS_ZBUFFER);
1034     }
1035     if(winecaps.DirectDrawCaps.StrideAlign != 0) {
1036         caps.dwCaps |= DDCAPS_ALIGNSTRIDE;
1037         caps.dwAlignStrideAlign = winecaps.DirectDrawCaps.StrideAlign;
1038     }
1039
1040     if(DriverCaps)
1041     {
1042         DD_STRUCT_COPY_BYSIZE(DriverCaps, &caps);
1043         if (TRACE_ON(ddraw))
1044         {
1045             TRACE("Driver Caps :\n");
1046             DDRAW_dump_DDCAPS(DriverCaps);
1047         }
1048
1049     }
1050     if(HELCaps)
1051     {
1052         DD_STRUCT_COPY_BYSIZE(HELCaps, &caps);
1053         if (TRACE_ON(ddraw))
1054         {
1055             TRACE("HEL Caps :\n");
1056             DDRAW_dump_DDCAPS(HELCaps);
1057         }
1058     }
1059
1060     return DD_OK;
1061 }
1062
1063 static HRESULT WINAPI ddraw4_GetCaps(IDirectDraw4 *iface, DDCAPS *driver_caps, DDCAPS *hel_caps)
1064 {
1065     TRACE("iface %p, driver_caps %p, hel_caps %p.\n", iface, driver_caps, hel_caps);
1066
1067     return ddraw7_GetCaps((IDirectDraw7 *)ddraw_from_ddraw4(iface), driver_caps, hel_caps);
1068 }
1069
1070 static HRESULT WINAPI ddraw3_GetCaps(IDirectDraw3 *iface, DDCAPS *driver_caps, DDCAPS *hel_caps)
1071 {
1072     TRACE("iface %p, driver_caps %p, hel_caps %p.\n", iface, driver_caps, hel_caps);
1073
1074     return ddraw7_GetCaps((IDirectDraw7 *)ddraw_from_ddraw3(iface), driver_caps, hel_caps);
1075 }
1076
1077 static HRESULT WINAPI ddraw2_GetCaps(IDirectDraw2 *iface, DDCAPS *driver_caps, DDCAPS *hel_caps)
1078 {
1079     TRACE("iface %p, driver_caps %p, hel_caps %p.\n", iface, driver_caps, hel_caps);
1080
1081     return ddraw7_GetCaps((IDirectDraw7 *)ddraw_from_ddraw2(iface), driver_caps, hel_caps);
1082 }
1083
1084 static HRESULT WINAPI ddraw1_GetCaps(IDirectDraw *iface, DDCAPS *driver_caps, DDCAPS *hel_caps)
1085 {
1086     TRACE("iface %p, driver_caps %p, hel_caps %p.\n", iface, driver_caps, hel_caps);
1087
1088     return ddraw7_GetCaps((IDirectDraw7 *)ddraw_from_ddraw1(iface), driver_caps, hel_caps);
1089 }
1090
1091 /*****************************************************************************
1092  * IDirectDraw7::Compact
1093  *
1094  * No idea what it does, MSDN says it's not implemented.
1095  *
1096  * Returns
1097  *  DD_OK, but this is unchecked
1098  *
1099  *****************************************************************************/
1100 static HRESULT WINAPI ddraw7_Compact(IDirectDraw7 *iface)
1101 {
1102     IDirectDrawImpl *This = (IDirectDrawImpl *)iface;
1103     TRACE("(%p)\n", This);
1104
1105     return DD_OK;
1106 }
1107
1108 static HRESULT WINAPI ddraw4_Compact(IDirectDraw4 *iface)
1109 {
1110     TRACE("iface %p.\n", iface);
1111
1112     return ddraw7_Compact((IDirectDraw7 *)ddraw_from_ddraw4(iface));
1113 }
1114
1115 static HRESULT WINAPI ddraw3_Compact(IDirectDraw3 *iface)
1116 {
1117     TRACE("iface %p.\n", iface);
1118
1119     return ddraw7_Compact((IDirectDraw7 *)ddraw_from_ddraw3(iface));
1120 }
1121
1122 static HRESULT WINAPI ddraw2_Compact(IDirectDraw2 *iface)
1123 {
1124     TRACE("iface %p.\n", iface);
1125
1126     return ddraw7_Compact((IDirectDraw7 *)ddraw_from_ddraw2(iface));
1127 }
1128
1129 static HRESULT WINAPI ddraw1_Compact(IDirectDraw *iface)
1130 {
1131     TRACE("iface %p.\n", iface);
1132
1133     return ddraw7_Compact((IDirectDraw7 *)ddraw_from_ddraw1(iface));
1134 }
1135
1136 /*****************************************************************************
1137  * IDirectDraw7::GetDisplayMode
1138  *
1139  * Returns information about the current display mode
1140  *
1141  * Exists in Version 1, 2, 4 and 7
1142  *
1143  * Params:
1144  *  DDSD: Address of a surface description structure to write the info to
1145  *
1146  * Returns
1147  *  DD_OK
1148  *
1149  *****************************************************************************/
1150 static HRESULT WINAPI ddraw7_GetDisplayMode(IDirectDraw7 *iface, DDSURFACEDESC2 *DDSD)
1151 {
1152     IDirectDrawImpl *This = (IDirectDrawImpl *)iface;
1153     HRESULT hr;
1154     WINED3DDISPLAYMODE Mode;
1155     DWORD Size;
1156     TRACE("(%p)->(%p): Relay\n", This, DDSD);
1157
1158     EnterCriticalSection(&ddraw_cs);
1159     /* This seems sane */
1160     if (!DDSD)
1161     {
1162         LeaveCriticalSection(&ddraw_cs);
1163         return DDERR_INVALIDPARAMS;
1164     }
1165
1166     /* The necessary members of LPDDSURFACEDESC and LPDDSURFACEDESC2 are equal,
1167      * so one method can be used for all versions (Hopefully)
1168      */
1169     hr = IWineD3DDevice_GetDisplayMode(This->wineD3DDevice,
1170                                       0 /* swapchain 0 */,
1171                                       &Mode);
1172     if( hr != D3D_OK )
1173     {
1174         ERR(" (%p) IWineD3DDevice::GetDisplayMode returned %08x\n", This, hr);
1175         LeaveCriticalSection(&ddraw_cs);
1176         return hr;
1177     }
1178
1179     Size = DDSD->dwSize;
1180     memset(DDSD, 0, Size);
1181
1182     DDSD->dwSize = Size;
1183     DDSD->dwFlags |= DDSD_HEIGHT | DDSD_WIDTH | DDSD_PIXELFORMAT | DDSD_PITCH | DDSD_REFRESHRATE;
1184     DDSD->dwWidth = Mode.Width;
1185     DDSD->dwHeight = Mode.Height;
1186     DDSD->u2.dwRefreshRate = 60;
1187     DDSD->ddsCaps.dwCaps = 0;
1188     DDSD->u4.ddpfPixelFormat.dwSize = sizeof(DDSD->u4.ddpfPixelFormat);
1189     PixelFormat_WineD3DtoDD(&DDSD->u4.ddpfPixelFormat, Mode.Format);
1190     DDSD->u1.lPitch = Mode.Width * DDSD->u4.ddpfPixelFormat.u1.dwRGBBitCount / 8;
1191
1192     if(TRACE_ON(ddraw))
1193     {
1194         TRACE("Returning surface desc :\n");
1195         DDRAW_dump_surface_desc(DDSD);
1196     }
1197
1198     LeaveCriticalSection(&ddraw_cs);
1199     return DD_OK;
1200 }
1201
1202 static HRESULT WINAPI ddraw4_GetDisplayMode(IDirectDraw4 *iface, DDSURFACEDESC2 *surface_desc)
1203 {
1204     TRACE("iface %p, surface_desc %p.\n", iface, surface_desc);
1205
1206     return ddraw7_GetDisplayMode((IDirectDraw7 *)ddraw_from_ddraw4(iface), surface_desc);
1207 }
1208
1209 static HRESULT WINAPI ddraw3_GetDisplayMode(IDirectDraw3 *iface, DDSURFACEDESC *surface_desc)
1210 {
1211     TRACE("iface %p, surface_desc %p.\n", iface, surface_desc);
1212
1213     return ddraw7_GetDisplayMode((IDirectDraw7 *)ddraw_from_ddraw3(iface), (DDSURFACEDESC2 *)surface_desc);
1214 }
1215
1216 static HRESULT WINAPI ddraw2_GetDisplayMode(IDirectDraw2 *iface, DDSURFACEDESC *surface_desc)
1217 {
1218     TRACE("iface %p, surface_desc %p.\n", iface, surface_desc);
1219
1220     return ddraw7_GetDisplayMode((IDirectDraw7 *)ddraw_from_ddraw2(iface), (DDSURFACEDESC2 *)surface_desc);
1221 }
1222
1223 static HRESULT WINAPI ddraw1_GetDisplayMode(IDirectDraw *iface, DDSURFACEDESC *surface_desc)
1224 {
1225     TRACE("iface %p, surface_desc %p.\n", iface, surface_desc);
1226
1227     return ddraw7_GetDisplayMode((IDirectDraw7 *)ddraw_from_ddraw1(iface), (DDSURFACEDESC2 *)surface_desc);
1228 }
1229
1230 /*****************************************************************************
1231  * IDirectDraw7::GetFourCCCodes
1232  *
1233  * Returns an array of supported FourCC codes.
1234  *
1235  * Exists in Version 1, 2, 4 and 7
1236  *
1237  * Params:
1238  *  NumCodes: Contains the number of Codes that Codes can carry. Returns the number
1239  *            of enumerated codes
1240  *  Codes: Pointer to an array of DWORDs where the supported codes are written
1241  *         to
1242  *
1243  * Returns
1244  *  Always returns DD_OK, as it's a stub for now
1245  *
1246  *****************************************************************************/
1247 static HRESULT WINAPI ddraw7_GetFourCCCodes(IDirectDraw7 *iface, DWORD *NumCodes, DWORD *Codes)
1248 {
1249     IDirectDrawImpl *This = (IDirectDrawImpl *)iface;
1250     WINED3DFORMAT formats[] = {
1251         WINED3DFMT_YUY2, WINED3DFMT_UYVY, WINED3DFMT_YV12,
1252         WINED3DFMT_DXT1, WINED3DFMT_DXT2, WINED3DFMT_DXT3, WINED3DFMT_DXT4, WINED3DFMT_DXT5,
1253         WINED3DFMT_ATI2N, WINED3DFMT_NVHU, WINED3DFMT_NVHS
1254     };
1255     DWORD count = 0, i, outsize;
1256     HRESULT hr;
1257     WINED3DDISPLAYMODE d3ddm;
1258     WINED3DSURFTYPE type = This->ImplType;
1259     TRACE("(%p)->(%p, %p)\n", This, NumCodes, Codes);
1260
1261     IWineD3DDevice_GetDisplayMode(This->wineD3DDevice,
1262                                   0 /* swapchain 0 */,
1263                                   &d3ddm);
1264
1265     outsize = NumCodes && Codes ? *NumCodes : 0;
1266
1267     if(type == SURFACE_UNKNOWN) type = SURFACE_GDI;
1268
1269     for(i = 0; i < (sizeof(formats) / sizeof(formats[0])); i++) {
1270         hr = IWineD3D_CheckDeviceFormat(This->wineD3D,
1271                                         WINED3DADAPTER_DEFAULT,
1272                                         WINED3DDEVTYPE_HAL,
1273                                         d3ddm.Format /* AdapterFormat */,
1274                                         0 /* usage */,
1275                                         WINED3DRTYPE_SURFACE,
1276                                         formats[i],
1277                                         type);
1278         if(SUCCEEDED(hr)) {
1279             if(count < outsize) {
1280                 Codes[count] = formats[i];
1281             }
1282             count++;
1283         }
1284     }
1285     if(NumCodes) {
1286         TRACE("Returning %u FourCC codes\n", count);
1287         *NumCodes = count;
1288     }
1289
1290     return DD_OK;
1291 }
1292
1293 static HRESULT WINAPI ddraw4_GetFourCCCodes(IDirectDraw4 *iface, DWORD *codes_count, DWORD *codes)
1294 {
1295     TRACE("iface %p, codes_count %p, codes %p.\n", iface, codes_count, codes);
1296
1297     return ddraw7_GetFourCCCodes((IDirectDraw7 *)ddraw_from_ddraw4(iface), codes_count, codes);
1298 }
1299
1300 static HRESULT WINAPI ddraw3_GetFourCCCodes(IDirectDraw3 *iface, DWORD *codes_count, DWORD *codes)
1301 {
1302     TRACE("iface %p, codes_count %p, codes %p.\n", iface, codes_count, codes);
1303
1304     return ddraw7_GetFourCCCodes((IDirectDraw7 *)ddraw_from_ddraw3(iface), codes_count, codes);
1305 }
1306
1307 static HRESULT WINAPI ddraw2_GetFourCCCodes(IDirectDraw2 *iface, DWORD *codes_count, DWORD *codes)
1308 {
1309     TRACE("iface %p, codes_count %p, codes %p.\n", iface, codes_count, codes);
1310
1311     return ddraw7_GetFourCCCodes((IDirectDraw7 *)ddraw_from_ddraw2(iface), codes_count, codes);
1312 }
1313
1314 static HRESULT WINAPI ddraw1_GetFourCCCodes(IDirectDraw *iface, DWORD *codes_count, DWORD *codes)
1315 {
1316     TRACE("iface %p, codes_count %p, codes %p.\n", iface, codes_count, codes);
1317
1318     return ddraw7_GetFourCCCodes((IDirectDraw7 *)ddraw_from_ddraw1(iface), codes_count, codes);
1319 }
1320
1321 /*****************************************************************************
1322  * IDirectDraw7::GetMonitorFrequency
1323  *
1324  * Returns the monitor's frequency
1325  *
1326  * Exists in Version 1, 2, 4 and 7
1327  *
1328  * Params:
1329  *  Freq: Pointer to a DWORD to write the frequency to
1330  *
1331  * Returns
1332  *  Always returns DD_OK
1333  *
1334  *****************************************************************************/
1335 static HRESULT WINAPI ddraw7_GetMonitorFrequency(IDirectDraw7 *iface, DWORD *Freq)
1336 {
1337     IDirectDrawImpl *This = (IDirectDrawImpl *)iface;
1338     TRACE("(%p)->(%p)\n", This, Freq);
1339
1340     /* Ideally this should be in WineD3D, as it concerns the screen setup,
1341      * but for now this should make the games happy
1342      */
1343     *Freq = 60;
1344     return DD_OK;
1345 }
1346
1347 static HRESULT WINAPI ddraw4_GetMonitorFrequency(IDirectDraw4 *iface, DWORD *frequency)
1348 {
1349     TRACE("iface %p, frequency %p.\n", iface, frequency);
1350
1351     return ddraw7_GetMonitorFrequency((IDirectDraw7 *)ddraw_from_ddraw4(iface), frequency);
1352 }
1353
1354 static HRESULT WINAPI ddraw3_GetMonitorFrequency(IDirectDraw3 *iface, DWORD *frequency)
1355 {
1356     TRACE("iface %p, frequency %p.\n", iface, frequency);
1357
1358     return ddraw7_GetMonitorFrequency((IDirectDraw7 *)ddraw_from_ddraw3(iface), frequency);
1359 }
1360
1361 static HRESULT WINAPI ddraw2_GetMonitorFrequency(IDirectDraw2 *iface, DWORD *frequency)
1362 {
1363     TRACE("iface %p, frequency %p.\n", iface, frequency);
1364
1365     return ddraw7_GetMonitorFrequency((IDirectDraw7 *)ddraw_from_ddraw2(iface), frequency);
1366 }
1367
1368 static HRESULT WINAPI ddraw1_GetMonitorFrequency(IDirectDraw *iface, DWORD *frequency)
1369 {
1370     TRACE("iface %p, frequency %p.\n", iface, frequency);
1371
1372     return ddraw7_GetMonitorFrequency((IDirectDraw7 *)ddraw_from_ddraw1(iface), frequency);
1373 }
1374
1375 /*****************************************************************************
1376  * IDirectDraw7::GetVerticalBlankStatus
1377  *
1378  * Returns the Vertical blank status of the monitor. This should be in WineD3D
1379  * too basically, but as it's a semi stub, I didn't create a function there
1380  *
1381  * Params:
1382  *  status: Pointer to a BOOL to be filled with the vertical blank status
1383  *
1384  * Returns
1385  *  DD_OK on success
1386  *  DDERR_INVALIDPARAMS if status is NULL
1387  *
1388  *****************************************************************************/
1389 static HRESULT WINAPI ddraw7_GetVerticalBlankStatus(IDirectDraw7 *iface, BOOL *status)
1390 {
1391     IDirectDrawImpl *This = (IDirectDrawImpl *)iface;
1392     TRACE("(%p)->(%p)\n", This, status);
1393
1394     /* This looks sane, the MSDN suggests it too */
1395     EnterCriticalSection(&ddraw_cs);
1396     if(!status)
1397     {
1398         LeaveCriticalSection(&ddraw_cs);
1399         return DDERR_INVALIDPARAMS;
1400     }
1401
1402     *status = This->fake_vblank;
1403     This->fake_vblank = !This->fake_vblank;
1404     LeaveCriticalSection(&ddraw_cs);
1405     return DD_OK;
1406 }
1407
1408 static HRESULT WINAPI ddraw4_GetVerticalBlankStatus(IDirectDraw4 *iface, BOOL *status)
1409 {
1410     TRACE("iface %p, status %p.\n", iface, status);
1411
1412     return ddraw7_GetVerticalBlankStatus((IDirectDraw7 *)ddraw_from_ddraw4(iface), status);
1413 }
1414
1415 static HRESULT WINAPI ddraw3_GetVerticalBlankStatus(IDirectDraw3 *iface, BOOL *status)
1416 {
1417     TRACE("iface %p, status %p.\n", iface, status);
1418
1419     return ddraw7_GetVerticalBlankStatus((IDirectDraw7 *)ddraw_from_ddraw3(iface), status);
1420 }
1421
1422 static HRESULT WINAPI ddraw2_GetVerticalBlankStatus(IDirectDraw2 *iface, BOOL *status)
1423 {
1424     TRACE("iface %p, status %p.\n", iface, status);
1425
1426     return ddraw7_GetVerticalBlankStatus((IDirectDraw7 *)ddraw_from_ddraw2(iface), status);
1427 }
1428
1429 static HRESULT WINAPI ddraw1_GetVerticalBlankStatus(IDirectDraw *iface, BOOL *status)
1430 {
1431     TRACE("iface %p, status %p.\n", iface, status);
1432
1433     return ddraw7_GetVerticalBlankStatus((IDirectDraw7 *)ddraw_from_ddraw1(iface), status);
1434 }
1435
1436 /*****************************************************************************
1437  * IDirectDraw7::GetAvailableVidMem
1438  *
1439  * Returns the total and free video memory
1440  *
1441  * Params:
1442  *  Caps: Specifies the memory type asked for
1443  *  total: Pointer to a DWORD to be filled with the total memory
1444  *  free: Pointer to a DWORD to be filled with the free memory
1445  *
1446  * Returns
1447  *  DD_OK on success
1448  *  DDERR_INVALIDPARAMS of free and total are NULL
1449  *
1450  *****************************************************************************/
1451 static HRESULT WINAPI ddraw7_GetAvailableVidMem(IDirectDraw7 *iface, DDSCAPS2 *Caps, DWORD *total, DWORD *free)
1452 {
1453     IDirectDrawImpl *This = (IDirectDrawImpl *)iface;
1454     TRACE("(%p)->(%p, %p, %p)\n", This, Caps, total, free);
1455
1456     if(TRACE_ON(ddraw))
1457     {
1458         TRACE("(%p) Asked for memory with description: ", This);
1459         DDRAW_dump_DDSCAPS2(Caps);
1460     }
1461     EnterCriticalSection(&ddraw_cs);
1462
1463     /* Todo: System memory vs local video memory vs non-local video memory
1464      * The MSDN also mentions differences between texture memory and other
1465      * resources, but that's not important
1466      */
1467
1468     if( (!total) && (!free) )
1469     {
1470         LeaveCriticalSection(&ddraw_cs);
1471         return DDERR_INVALIDPARAMS;
1472     }
1473
1474     if(total) *total = This->total_vidmem;
1475     if(free) *free = IWineD3DDevice_GetAvailableTextureMem(This->wineD3DDevice);
1476
1477     LeaveCriticalSection(&ddraw_cs);
1478     return DD_OK;
1479 }
1480
1481 static HRESULT WINAPI ddraw4_GetAvailableVidMem(IDirectDraw4 *iface,
1482         DDSCAPS2 *caps, DWORD *total, DWORD *free)
1483 {
1484     TRACE("iface %p, caps %p, total %p, free %p.\n", iface, caps, total, free);
1485
1486     return ddraw7_GetAvailableVidMem((IDirectDraw7 *)ddraw_from_ddraw4(iface), caps, total, free);
1487 }
1488
1489 static HRESULT WINAPI ddraw3_GetAvailableVidMem(IDirectDraw3 *iface,
1490         DDSCAPS *caps, DWORD *total, DWORD *free)
1491 {
1492     DDSCAPS2 caps2;
1493
1494     TRACE("iface %p, caps %p, total %p, free %p.\n", iface, caps, total, free);
1495
1496     DDRAW_Convert_DDSCAPS_1_To_2(caps, &caps2);
1497     return ddraw7_GetAvailableVidMem((IDirectDraw7 *)ddraw_from_ddraw3(iface), &caps2, total, free);
1498 }
1499
1500 static HRESULT WINAPI ddraw2_GetAvailableVidMem(IDirectDraw2 *iface,
1501         DDSCAPS *caps, DWORD *total, DWORD *free)
1502 {
1503     DDSCAPS2 caps2;
1504
1505     TRACE("iface %p, caps %p, total %p, free %p.\n", iface, caps, total, free);
1506
1507     DDRAW_Convert_DDSCAPS_1_To_2(caps, &caps2);
1508     return ddraw7_GetAvailableVidMem((IDirectDraw7 *)ddraw_from_ddraw2(iface), &caps2, total, free);
1509 }
1510
1511 /*****************************************************************************
1512  * IDirectDraw7::Initialize
1513  *
1514  * Initializes a DirectDraw interface.
1515  *
1516  * Params:
1517  *  GUID: Interface identifier. Well, don't know what this is really good
1518  *   for
1519  *
1520  * Returns
1521  *  Returns DD_OK on the first call,
1522  *  DDERR_ALREADYINITIALIZED on repeated calls
1523  *
1524  *****************************************************************************/
1525 static HRESULT WINAPI ddraw7_Initialize(IDirectDraw7 *iface, GUID *Guid)
1526 {
1527     IDirectDrawImpl *This = (IDirectDrawImpl *)iface;
1528     TRACE("(%p)->(%s): No-op\n", This, debugstr_guid(Guid));
1529
1530     if(This->initialized)
1531     {
1532         return DDERR_ALREADYINITIALIZED;
1533     }
1534     else
1535     {
1536         return DD_OK;
1537     }
1538 }
1539
1540 static HRESULT WINAPI ddraw4_Initialize(IDirectDraw4 *iface, GUID *guid)
1541 {
1542     TRACE("iface %p, guid %s.\n", iface, debugstr_guid(guid));
1543
1544     return ddraw7_Initialize((IDirectDraw7 *)ddraw_from_ddraw4(iface), guid);
1545 }
1546
1547 static HRESULT WINAPI ddraw3_Initialize(IDirectDraw3 *iface, GUID *guid)
1548 {
1549     TRACE("iface %p, guid %s.\n", iface, debugstr_guid(guid));
1550
1551     return ddraw7_Initialize((IDirectDraw7 *)ddraw_from_ddraw3(iface), guid);
1552 }
1553
1554 static HRESULT WINAPI ddraw2_Initialize(IDirectDraw2 *iface, GUID *guid)
1555 {
1556     TRACE("iface %p, guid %s.\n", iface, debugstr_guid(guid));
1557
1558     return ddraw7_Initialize((IDirectDraw7 *)ddraw_from_ddraw2(iface), guid);
1559 }
1560
1561 static HRESULT WINAPI ddraw1_Initialize(IDirectDraw *iface, GUID *guid)
1562 {
1563     TRACE("iface %p, guid %s.\n", iface, debugstr_guid(guid));
1564
1565     return ddraw7_Initialize((IDirectDraw7 *)ddraw_from_ddraw1(iface), guid);
1566 }
1567
1568 static HRESULT WINAPI d3d1_Initialize(IDirect3D *iface, REFIID riid)
1569 {
1570     TRACE("iface %p, riid %s.\n", iface, debugstr_guid(riid));
1571
1572     return D3D_OK;
1573 }
1574
1575 /*****************************************************************************
1576  * IDirectDraw7::FlipToGDISurface
1577  *
1578  * "Makes the surface that the GDI writes to the primary surface"
1579  * Looks like some windows specific thing we don't have to care about.
1580  * According to MSDN it permits GDI dialog boxes in FULLSCREEN mode. Good to
1581  * show error boxes ;)
1582  * Well, just return DD_OK.
1583  *
1584  * Returns:
1585  *  Always returns DD_OK
1586  *
1587  *****************************************************************************/
1588 static HRESULT WINAPI ddraw7_FlipToGDISurface(IDirectDraw7 *iface)
1589 {
1590     IDirectDrawImpl *This = (IDirectDrawImpl *)iface;
1591     TRACE("(%p)\n", This);
1592
1593     return DD_OK;
1594 }
1595
1596 static HRESULT WINAPI ddraw4_FlipToGDISurface(IDirectDraw4 *iface)
1597 {
1598     TRACE("iface %p.\n", iface);
1599
1600     return ddraw7_FlipToGDISurface((IDirectDraw7 *)ddraw_from_ddraw4(iface));
1601 }
1602
1603 static HRESULT WINAPI ddraw3_FlipToGDISurface(IDirectDraw3 *iface)
1604 {
1605     TRACE("iface %p.\n", iface);
1606
1607     return ddraw7_FlipToGDISurface((IDirectDraw7 *)ddraw_from_ddraw3(iface));
1608 }
1609
1610 static HRESULT WINAPI ddraw2_FlipToGDISurface(IDirectDraw2 *iface)
1611 {
1612     TRACE("iface %p.\n", iface);
1613
1614     return ddraw7_FlipToGDISurface((IDirectDraw7 *)ddraw_from_ddraw2(iface));
1615 }
1616
1617 static HRESULT WINAPI ddraw1_FlipToGDISurface(IDirectDraw *iface)
1618 {
1619     TRACE("iface %p.\n", iface);
1620
1621     return ddraw7_FlipToGDISurface((IDirectDraw7 *)ddraw_from_ddraw1(iface));
1622 }
1623
1624 /*****************************************************************************
1625  * IDirectDraw7::WaitForVerticalBlank
1626  *
1627  * This method allows applications to get in sync with the vertical blank
1628  * interval.
1629  * The wormhole demo in the DirectX 7 sdk uses this call, and it doesn't
1630  * redraw the screen, most likely because of this stub
1631  *
1632  * Parameters:
1633  *  Flags: one of DDWAITVB_BLOCKBEGIN, DDWAITVB_BLOCKBEGINEVENT
1634  *         or DDWAITVB_BLOCKEND
1635  *  h: Not used, according to MSDN
1636  *
1637  * Returns:
1638  *  Always returns DD_OK
1639  *
1640  *****************************************************************************/
1641 static HRESULT WINAPI ddraw7_WaitForVerticalBlank(IDirectDraw7 *iface, DWORD Flags, HANDLE h)
1642 {
1643     IDirectDrawImpl *This = (IDirectDrawImpl *)iface;
1644     static BOOL hide = FALSE;
1645
1646     /* This function is called often, so print the fixme only once */
1647     if(!hide)
1648     {
1649         FIXME("(%p)->(%x,%p): Stub\n", This, Flags, h);
1650         hide = TRUE;
1651     }
1652
1653     /* MSDN says DDWAITVB_BLOCKBEGINEVENT is not supported */
1654     if(Flags & DDWAITVB_BLOCKBEGINEVENT)
1655         return DDERR_UNSUPPORTED; /* unchecked */
1656
1657     return DD_OK;
1658 }
1659
1660 static HRESULT WINAPI ddraw4_WaitForVerticalBlank(IDirectDraw4 *iface, DWORD flags, HANDLE event)
1661 {
1662     TRACE("iface %p, flags %#x, event %p.\n", iface, flags, event);
1663
1664     return ddraw7_WaitForVerticalBlank((IDirectDraw7 *)ddraw_from_ddraw4(iface), flags, event);
1665 }
1666
1667 static HRESULT WINAPI ddraw3_WaitForVerticalBlank(IDirectDraw3 *iface, DWORD flags, HANDLE event)
1668 {
1669     TRACE("iface %p, flags %#x, event %p.\n", iface, flags, event);
1670
1671     return ddraw7_WaitForVerticalBlank((IDirectDraw7 *)ddraw_from_ddraw3(iface), flags, event);
1672 }
1673
1674 static HRESULT WINAPI ddraw2_WaitForVerticalBlank(IDirectDraw2 *iface, DWORD flags, HANDLE event)
1675 {
1676     TRACE("iface %p, flags %#x, event %p.\n", iface, flags, event);
1677
1678     return ddraw7_WaitForVerticalBlank((IDirectDraw7 *)ddraw_from_ddraw2(iface), flags, event);
1679 }
1680
1681 static HRESULT WINAPI ddraw1_WaitForVerticalBlank(IDirectDraw *iface, DWORD flags, HANDLE event)
1682 {
1683     TRACE("iface %p, flags %#x, event %p.\n", iface, flags, event);
1684
1685     return ddraw7_WaitForVerticalBlank((IDirectDraw7 *)ddraw_from_ddraw1(iface), flags, event);
1686 }
1687
1688 /*****************************************************************************
1689  * IDirectDraw7::GetScanLine
1690  *
1691  * Returns the scan line that is being drawn on the monitor
1692  *
1693  * Parameters:
1694  *  Scanline: Address to write the scan line value to
1695  *
1696  * Returns:
1697  *  Always returns DD_OK
1698  *
1699  *****************************************************************************/
1700 static HRESULT WINAPI ddraw7_GetScanLine(IDirectDraw7 *iface, DWORD *Scanline)
1701 {
1702     IDirectDrawImpl *This = (IDirectDrawImpl *)iface;
1703     static BOOL hide = FALSE;
1704     WINED3DDISPLAYMODE Mode;
1705
1706     /* This function is called often, so print the fixme only once */
1707     EnterCriticalSection(&ddraw_cs);
1708     if(!hide)
1709     {
1710         FIXME("(%p)->(%p): Semi-Stub\n", This, Scanline);
1711         hide = TRUE;
1712     }
1713
1714     IWineD3DDevice_GetDisplayMode(This->wineD3DDevice,
1715                                   0,
1716                                   &Mode);
1717
1718     /* Fake the line sweeping of the monitor */
1719     /* FIXME: We should synchronize with a source to keep the refresh rate */
1720     *Scanline = This->cur_scanline++;
1721     /* Assume 20 scan lines in the vertical blank */
1722     if (This->cur_scanline >= Mode.Height + 20)
1723         This->cur_scanline = 0;
1724
1725     LeaveCriticalSection(&ddraw_cs);
1726     return DD_OK;
1727 }
1728
1729 static HRESULT WINAPI ddraw4_GetScanLine(IDirectDraw4 *iface, DWORD *line)
1730 {
1731     TRACE("iface %p, line %p.\n", iface, line);
1732
1733     return ddraw7_GetScanLine((IDirectDraw7 *)ddraw_from_ddraw4(iface), line);
1734 }
1735
1736 static HRESULT WINAPI ddraw3_GetScanLine(IDirectDraw3 *iface, DWORD *line)
1737 {
1738     TRACE("iface %p, line %p.\n", iface, line);
1739
1740     return ddraw7_GetScanLine((IDirectDraw7 *)ddraw_from_ddraw3(iface), line);
1741 }
1742
1743 static HRESULT WINAPI ddraw2_GetScanLine(IDirectDraw2 *iface, DWORD *line)
1744 {
1745     TRACE("iface %p, line %p.\n", iface, line);
1746
1747     return ddraw7_GetScanLine((IDirectDraw7 *)ddraw_from_ddraw2(iface), line);
1748 }
1749
1750 static HRESULT WINAPI ddraw1_GetScanLine(IDirectDraw *iface, DWORD *line)
1751 {
1752     TRACE("iface %p, line %p.\n", iface, line);
1753
1754     return ddraw7_GetScanLine((IDirectDraw7 *)ddraw_from_ddraw1(iface), line);
1755 }
1756
1757 /*****************************************************************************
1758  * IDirectDraw7::TestCooperativeLevel
1759  *
1760  * Informs the application about the state of the video adapter, depending
1761  * on the cooperative level
1762  *
1763  * Returns:
1764  *  DD_OK if the device is in a sane state
1765  *  DDERR_NOEXCLUSIVEMODE or DDERR_EXCLUSIVEMODEALREADYSET
1766  *  if the state is not correct(See below)
1767  *
1768  *****************************************************************************/
1769 static HRESULT WINAPI ddraw7_TestCooperativeLevel(IDirectDraw7 *iface)
1770 {
1771     TRACE("iface %p.\n", iface);
1772
1773     return DD_OK;
1774 }
1775
1776 static HRESULT WINAPI ddraw4_TestCooperativeLevel(IDirectDraw4 *iface)
1777 {
1778     TRACE("iface %p.\n", iface);
1779
1780     return ddraw7_TestCooperativeLevel((IDirectDraw7 *)ddraw_from_ddraw4(iface));
1781 }
1782
1783 /*****************************************************************************
1784  * IDirectDraw7::GetGDISurface
1785  *
1786  * Returns the surface that GDI is treating as the primary surface.
1787  * For Wine this is the front buffer
1788  *
1789  * Params:
1790  *  GDISurface: Address to write the surface pointer to
1791  *
1792  * Returns:
1793  *  DD_OK if the surface was found
1794  *  DDERR_NOTFOUND if the GDI surface wasn't found
1795  *
1796  *****************************************************************************/
1797 static HRESULT WINAPI ddraw7_GetGDISurface(IDirectDraw7 *iface, IDirectDrawSurface7 **GDISurface)
1798 {
1799     IDirectDrawImpl *This = (IDirectDrawImpl *)iface;
1800     IWineD3DSurface *Surf;
1801     IDirectDrawSurface7 *ddsurf;
1802     HRESULT hr;
1803     DDSCAPS2 ddsCaps;
1804     TRACE("(%p)->(%p)\n", This, GDISurface);
1805
1806     /* Get the back buffer from the wineD3DDevice and search its
1807      * attached surfaces for the front buffer
1808      */
1809     EnterCriticalSection(&ddraw_cs);
1810     hr = IWineD3DDevice_GetBackBuffer(This->wineD3DDevice,
1811                                       0, /* SwapChain */
1812                                       0, /* first back buffer*/
1813                                       WINED3DBACKBUFFER_TYPE_MONO,
1814                                       &Surf);
1815
1816     if( (hr != D3D_OK) ||
1817         (!Surf) )
1818     {
1819         ERR("IWineD3DDevice::GetBackBuffer failed\n");
1820         LeaveCriticalSection(&ddraw_cs);
1821         return DDERR_NOTFOUND;
1822     }
1823
1824     /* GetBackBuffer AddRef()ed the surface, release it */
1825     IWineD3DSurface_Release(Surf);
1826
1827     IWineD3DSurface_GetParent(Surf,
1828                               (IUnknown **) &ddsurf);
1829     IDirectDrawSurface7_Release(ddsurf);  /* For the GetParent */
1830
1831     /* Find the front buffer */
1832     ddsCaps.dwCaps = DDSCAPS_FRONTBUFFER;
1833     hr = IDirectDrawSurface7_GetAttachedSurface(ddsurf,
1834                                                 &ddsCaps,
1835                                                 GDISurface);
1836     if(hr != DD_OK)
1837     {
1838         ERR("IDirectDrawSurface7::GetAttachedSurface failed, hr = %x\n", hr);
1839     }
1840
1841     /* The AddRef is OK this time */
1842     LeaveCriticalSection(&ddraw_cs);
1843     return hr;
1844 }
1845
1846 static HRESULT WINAPI ddraw4_GetGDISurface(IDirectDraw4 *iface, IDirectDrawSurface4 **surface)
1847 {
1848     TRACE("iface %p, surface %p.\n", iface, surface);
1849
1850     return ddraw7_GetGDISurface((IDirectDraw7 *)ddraw_from_ddraw4(iface), (IDirectDrawSurface7 **)surface);
1851 }
1852
1853 static HRESULT WINAPI ddraw3_GetGDISurface(IDirectDraw3 *iface, IDirectDrawSurface **surface)
1854 {
1855     IDirectDrawSurface7 *surface7;
1856     HRESULT hr;
1857
1858     TRACE("iface %p, surface %p.\n", iface, surface);
1859
1860     hr = ddraw7_GetGDISurface((IDirectDraw7 *)ddraw_from_ddraw3(iface), &surface7);
1861     *surface = surface7 ? (IDirectDrawSurface *)&((IDirectDrawSurfaceImpl *)surface7)->IDirectDrawSurface3_vtbl : NULL;
1862
1863     return hr;
1864 }
1865
1866 static HRESULT WINAPI ddraw2_GetGDISurface(IDirectDraw2 *iface, IDirectDrawSurface **surface)
1867 {
1868     IDirectDrawSurface7 *surface7;
1869     HRESULT hr;
1870
1871     TRACE("iface %p, surface %p.\n", iface, surface);
1872
1873     hr = ddraw7_GetGDISurface((IDirectDraw7 *)ddraw_from_ddraw2(iface), &surface7);
1874     *surface = surface7 ? (IDirectDrawSurface *)&((IDirectDrawSurfaceImpl *)surface7)->IDirectDrawSurface3_vtbl : NULL;
1875
1876     return hr;
1877 }
1878
1879 static HRESULT WINAPI ddraw1_GetGDISurface(IDirectDraw *iface, IDirectDrawSurface **surface)
1880 {
1881     IDirectDrawSurface7 *surface7;
1882     HRESULT hr;
1883
1884     TRACE("iface %p, surface %p.\n", iface, surface);
1885
1886     hr = ddraw7_GetGDISurface((IDirectDraw7 *)ddraw_from_ddraw1(iface), &surface7);
1887     *surface = surface7 ? (IDirectDrawSurface *)&((IDirectDrawSurfaceImpl *)surface7)->IDirectDrawSurface3_vtbl : NULL;
1888
1889     return hr;
1890 }
1891
1892 struct displaymodescallback_context
1893 {
1894     LPDDENUMMODESCALLBACK func;
1895     void *context;
1896 };
1897
1898 static HRESULT CALLBACK EnumDisplayModesCallbackThunk(DDSURFACEDESC2 *surface_desc, void *context)
1899 {
1900     struct displaymodescallback_context *cbcontext = context;
1901     DDSURFACEDESC desc;
1902
1903     memcpy(&desc, surface_desc, sizeof(desc));
1904     desc.dwSize = sizeof(desc);
1905
1906     return cbcontext->func(&desc, cbcontext->context);
1907 }
1908
1909 /*****************************************************************************
1910  * IDirectDraw7::EnumDisplayModes
1911  *
1912  * Enumerates the supported Display modes. The modes can be filtered with
1913  * the DDSD parameter.
1914  *
1915  * Params:
1916  *  Flags: can be DDEDM_REFRESHRATES and DDEDM_STANDARDVGAMODES
1917  *  DDSD: Surface description to filter the modes
1918  *  Context: Pointer passed back to the callback function
1919  *  cb: Application-provided callback function
1920  *
1921  * Returns:
1922  *  DD_OK on success
1923  *  DDERR_INVALIDPARAMS if the callback wasn't set
1924  *
1925  *****************************************************************************/
1926 static HRESULT WINAPI ddraw7_EnumDisplayModes(IDirectDraw7 *iface, DWORD Flags,
1927         DDSURFACEDESC2 *DDSD, void *Context, LPDDENUMMODESCALLBACK2 cb)
1928 {
1929     IDirectDrawImpl *This = (IDirectDrawImpl *)iface;
1930     unsigned int modenum, fmt;
1931     WINED3DFORMAT pixelformat = WINED3DFMT_UNKNOWN;
1932     WINED3DDISPLAYMODE mode;
1933     DDSURFACEDESC2 callback_sd;
1934     WINED3DDISPLAYMODE *enum_modes = NULL;
1935     unsigned enum_mode_count = 0, enum_mode_array_size = 0;
1936
1937     WINED3DFORMAT checkFormatList[] =
1938     {
1939         WINED3DFMT_B8G8R8X8_UNORM,
1940         WINED3DFMT_B5G6R5_UNORM,
1941         WINED3DFMT_P8_UINT,
1942     };
1943
1944     TRACE("(%p)->(%p,%p,%p): Relay\n", This, DDSD, Context, cb);
1945
1946     EnterCriticalSection(&ddraw_cs);
1947     /* This looks sane */
1948     if(!cb)
1949     {
1950         LeaveCriticalSection(&ddraw_cs);
1951         return DDERR_INVALIDPARAMS;
1952     }
1953
1954     if(DDSD)
1955     {
1956         if ((DDSD->dwFlags & DDSD_PIXELFORMAT) && (DDSD->u4.ddpfPixelFormat.dwFlags & DDPF_RGB) )
1957             pixelformat = PixelFormat_DD2WineD3D(&DDSD->u4.ddpfPixelFormat);
1958     }
1959
1960     if(!(Flags & DDEDM_REFRESHRATES))
1961     {
1962         enum_mode_array_size = 16;
1963         enum_modes = HeapAlloc(GetProcessHeap(), 0, sizeof(WINED3DDISPLAYMODE) * enum_mode_array_size);
1964         if (!enum_modes)
1965         {
1966             ERR("Out of memory\n");
1967             LeaveCriticalSection(&ddraw_cs);
1968             return DDERR_OUTOFMEMORY;
1969         }
1970     }
1971
1972     for(fmt = 0; fmt < (sizeof(checkFormatList) / sizeof(checkFormatList[0])); fmt++)
1973     {
1974         if(pixelformat != WINED3DFMT_UNKNOWN && checkFormatList[fmt] != pixelformat)
1975         {
1976             continue;
1977         }
1978
1979         modenum = 0;
1980         while(IWineD3D_EnumAdapterModes(This->wineD3D,
1981                                         WINED3DADAPTER_DEFAULT,
1982                                         checkFormatList[fmt],
1983                                         modenum++,
1984                                         &mode) == WINED3D_OK)
1985         {
1986             if(DDSD)
1987             {
1988                 if(DDSD->dwFlags & DDSD_WIDTH && mode.Width != DDSD->dwWidth) continue;
1989                 if(DDSD->dwFlags & DDSD_HEIGHT && mode.Height != DDSD->dwHeight) continue;
1990             }
1991
1992             if(!(Flags & DDEDM_REFRESHRATES))
1993             {
1994                 /* DX docs state EnumDisplayMode should return only unique modes. If DDEDM_REFRESHRATES is not set, refresh
1995                  * rate doesn't matter when determining if the mode is unique. So modes only differing in refresh rate have
1996                  * to be reduced to a single unique result in such case.
1997                  */
1998                 BOOL found = FALSE;
1999                 unsigned i;
2000
2001                 for (i = 0; i < enum_mode_count; i++)
2002                 {
2003                     if(enum_modes[i].Width == mode.Width && enum_modes[i].Height == mode.Height &&
2004                        enum_modes[i].Format == mode.Format)
2005                     {
2006                         found = TRUE;
2007                         break;
2008                     }
2009                 }
2010
2011                 if(found) continue;
2012             }
2013
2014             memset(&callback_sd, 0, sizeof(callback_sd));
2015             callback_sd.dwSize = sizeof(callback_sd);
2016             callback_sd.u4.ddpfPixelFormat.dwSize = sizeof(DDPIXELFORMAT);
2017
2018             callback_sd.dwFlags = DDSD_HEIGHT|DDSD_WIDTH|DDSD_PIXELFORMAT|DDSD_PITCH;
2019             if(Flags & DDEDM_REFRESHRATES)
2020             {
2021                 callback_sd.dwFlags |= DDSD_REFRESHRATE;
2022                 callback_sd.u2.dwRefreshRate = mode.RefreshRate;
2023             }
2024
2025             callback_sd.dwWidth = mode.Width;
2026             callback_sd.dwHeight = mode.Height;
2027
2028             PixelFormat_WineD3DtoDD(&callback_sd.u4.ddpfPixelFormat, mode.Format);
2029
2030             /* Calc pitch and DWORD align like MSDN says */
2031             callback_sd.u1.lPitch = (callback_sd.u4.ddpfPixelFormat.u1.dwRGBBitCount / 8) * mode.Width;
2032             callback_sd.u1.lPitch = (callback_sd.u1.lPitch + 3) & ~3;
2033
2034             TRACE("Enumerating %dx%dx%d @%d\n", callback_sd.dwWidth, callback_sd.dwHeight, callback_sd.u4.ddpfPixelFormat.u1.dwRGBBitCount,
2035               callback_sd.u2.dwRefreshRate);
2036
2037             if(cb(&callback_sd, Context) == DDENUMRET_CANCEL)
2038             {
2039                 TRACE("Application asked to terminate the enumeration\n");
2040                 HeapFree(GetProcessHeap(), 0, enum_modes);
2041                 LeaveCriticalSection(&ddraw_cs);
2042                 return DD_OK;
2043             }
2044
2045             if(!(Flags & DDEDM_REFRESHRATES))
2046             {
2047                 if (enum_mode_count == enum_mode_array_size)
2048                 {
2049                     WINED3DDISPLAYMODE *new_enum_modes;
2050
2051                     enum_mode_array_size *= 2;
2052                     new_enum_modes = HeapReAlloc(GetProcessHeap(), 0, enum_modes, sizeof(WINED3DDISPLAYMODE) * enum_mode_array_size);
2053
2054                     if (!new_enum_modes)
2055                     {
2056                         ERR("Out of memory\n");
2057                         HeapFree(GetProcessHeap(), 0, enum_modes);
2058                         LeaveCriticalSection(&ddraw_cs);
2059                         return DDERR_OUTOFMEMORY;
2060                     }
2061
2062                     enum_modes = new_enum_modes;
2063                 }
2064
2065                 enum_modes[enum_mode_count++] = mode;
2066             }
2067         }
2068     }
2069
2070     TRACE("End of enumeration\n");
2071     HeapFree(GetProcessHeap(), 0, enum_modes);
2072     LeaveCriticalSection(&ddraw_cs);
2073     return DD_OK;
2074 }
2075
2076 static HRESULT WINAPI ddraw4_EnumDisplayModes(IDirectDraw4 *iface, DWORD flags,
2077         DDSURFACEDESC2 *surface_desc, void *context, LPDDENUMMODESCALLBACK2 callback)
2078 {
2079     TRACE("iface %p, flags %#x, surface_desc %p, context %p, callback %p.\n",
2080             iface, flags, surface_desc, context, callback);
2081
2082     return ddraw7_EnumDisplayModes((IDirectDraw7 *)ddraw_from_ddraw4(iface), flags,
2083             surface_desc, context, callback);
2084 }
2085
2086 static HRESULT WINAPI ddraw3_EnumDisplayModes(IDirectDraw3 *iface, DWORD flags,
2087         DDSURFACEDESC *surface_desc, void *context, LPDDENUMMODESCALLBACK callback)
2088 {
2089     struct displaymodescallback_context cbcontext;
2090
2091     TRACE("iface %p, flags %#x, surface_desc %p, context %p, callback %p.\n",
2092             iface, flags, surface_desc, context, callback);
2093
2094     cbcontext.func = callback;
2095     cbcontext.context = context;
2096
2097     return ddraw7_EnumDisplayModes((IDirectDraw7 *)ddraw_from_ddraw3(iface), flags,
2098             (DDSURFACEDESC2 *)surface_desc, &cbcontext, EnumDisplayModesCallbackThunk);
2099 }
2100
2101 static HRESULT WINAPI ddraw2_EnumDisplayModes(IDirectDraw2 *iface, DWORD flags,
2102         DDSURFACEDESC *surface_desc, void *context, LPDDENUMMODESCALLBACK callback)
2103 {
2104     struct displaymodescallback_context cbcontext;
2105
2106     TRACE("iface %p, flags %#x, surface_desc %p, context %p, callback %p.\n",
2107             iface, flags, surface_desc, context, callback);
2108
2109     cbcontext.func = callback;
2110     cbcontext.context = context;
2111
2112     return ddraw7_EnumDisplayModes((IDirectDraw7 *)ddraw_from_ddraw2(iface), flags,
2113             (DDSURFACEDESC2 *)surface_desc, &cbcontext, EnumDisplayModesCallbackThunk);
2114 }
2115
2116 static HRESULT WINAPI ddraw1_EnumDisplayModes(IDirectDraw *iface, DWORD flags,
2117         DDSURFACEDESC *surface_desc, void *context, LPDDENUMMODESCALLBACK callback)
2118 {
2119     struct displaymodescallback_context cbcontext;
2120
2121     TRACE("iface %p, flags %#x, surface_desc %p, context %p, callback %p.\n",
2122             iface, flags, surface_desc, context, callback);
2123
2124     cbcontext.func = callback;
2125     cbcontext.context = context;
2126
2127     return ddraw7_EnumDisplayModes((IDirectDraw7 *)ddraw_from_ddraw1(iface), flags,
2128             (DDSURFACEDESC2 *)surface_desc, &cbcontext, EnumDisplayModesCallbackThunk);
2129 }
2130
2131 /*****************************************************************************
2132  * IDirectDraw7::EvaluateMode
2133  *
2134  * Used with IDirectDraw7::StartModeTest to test video modes.
2135  * EvaluateMode is used to pass or fail a mode, and continue with the next
2136  * mode
2137  *
2138  * Params:
2139  *  Flags: DDEM_MODEPASSED or DDEM_MODEFAILED
2140  *  Timeout: Returns the amount of seconds left before the mode would have
2141  *           been failed automatically
2142  *
2143  * Returns:
2144  *  This implementation always DD_OK, because it's a stub
2145  *
2146  *****************************************************************************/
2147 static HRESULT WINAPI ddraw7_EvaluateMode(IDirectDraw7 *iface, DWORD Flags, DWORD *Timeout)
2148 {
2149     IDirectDrawImpl *This = (IDirectDrawImpl *)iface;
2150     FIXME("(%p)->(%d,%p): Stub!\n", This, Flags, Timeout);
2151
2152     /* When implementing this, implement it in WineD3D */
2153
2154     return DD_OK;
2155 }
2156
2157 /*****************************************************************************
2158  * IDirectDraw7::GetDeviceIdentifier
2159  *
2160  * Returns the device identifier, which gives information about the driver
2161  * Our device identifier is defined at the beginning of this file.
2162  *
2163  * Params:
2164  *  DDDI: Address for the returned structure
2165  *  Flags: Can be DDGDI_GETHOSTIDENTIFIER
2166  *
2167  * Returns:
2168  *  On success it returns DD_OK
2169  *  DDERR_INVALIDPARAMS if DDDI is NULL
2170  *
2171  *****************************************************************************/
2172 static HRESULT WINAPI ddraw7_GetDeviceIdentifier(IDirectDraw7 *iface,
2173         DDDEVICEIDENTIFIER2 *DDDI, DWORD Flags)
2174 {
2175     IDirectDrawImpl *This = (IDirectDrawImpl *)iface;
2176     TRACE("(%p)->(%p,%08x)\n", This, DDDI, Flags);
2177
2178     if(!DDDI)
2179         return DDERR_INVALIDPARAMS;
2180
2181     /* The DDGDI_GETHOSTIDENTIFIER returns the information about the 2D
2182      * host adapter, if there's a secondary 3D adapter. This doesn't apply
2183      * to any modern hardware, nor is it interesting for Wine, so ignore it.
2184      * Size of DDDEVICEIDENTIFIER2 may be aligned to 8 bytes and thus 4
2185      * bytes too long. So only copy the relevant part of the structure
2186      */
2187
2188     memcpy(DDDI, &deviceidentifier, FIELD_OFFSET(DDDEVICEIDENTIFIER2, dwWHQLLevel) + sizeof(DWORD));
2189     return DD_OK;
2190 }
2191
2192 static HRESULT WINAPI ddraw4_GetDeviceIdentifier(IDirectDraw4 *iface,
2193         DDDEVICEIDENTIFIER *identifier, DWORD flags)
2194 {
2195     DDDEVICEIDENTIFIER2 identifier2;
2196     HRESULT hr;
2197
2198     TRACE("iface %p, identifier %p, flags %#x.\n", iface, identifier, flags);
2199
2200     hr = ddraw7_GetDeviceIdentifier((IDirectDraw7 *)ddraw_from_ddraw4(iface), &identifier2, flags);
2201     DDRAW_Convert_DDDEVICEIDENTIFIER_2_To_1(&identifier2, identifier);
2202
2203     return hr;
2204 }
2205
2206 /*****************************************************************************
2207  * IDirectDraw7::GetSurfaceFromDC
2208  *
2209  * Returns the Surface for a GDI device context handle.
2210  * Is this related to IDirectDrawSurface::GetDC ???
2211  *
2212  * Params:
2213  *  hdc: hdc to return the surface for
2214  *  Surface: Address to write the surface pointer to
2215  *
2216  * Returns:
2217  *  Always returns DD_OK because it's a stub
2218  *
2219  *****************************************************************************/
2220 static HRESULT WINAPI ddraw7_GetSurfaceFromDC(IDirectDraw7 *iface, HDC hdc, IDirectDrawSurface7 **Surface)
2221 {
2222     IDirectDrawImpl *This = (IDirectDrawImpl *)iface;
2223     IWineD3DSurface *wined3d_surface;
2224     HRESULT hr;
2225
2226     TRACE("iface %p, dc %p, surface %p.\n", iface, hdc, Surface);
2227
2228     if (!Surface) return E_INVALIDARG;
2229
2230     hr = IWineD3DDevice_GetSurfaceFromDC(This->wineD3DDevice, hdc, &wined3d_surface);
2231     if (FAILED(hr))
2232     {
2233         TRACE("No surface found for dc %p.\n", hdc);
2234         *Surface = NULL;
2235         return DDERR_NOTFOUND;
2236     }
2237
2238     IWineD3DSurface_GetParent(wined3d_surface, (IUnknown **)Surface);
2239     TRACE("Returning surface %p.\n", Surface);
2240     return DD_OK;
2241 }
2242
2243 static HRESULT WINAPI ddraw4_GetSurfaceFromDC(IDirectDraw4 *iface, HDC dc, IDirectDrawSurface4 **surface)
2244 {
2245     IDirectDrawSurface7 *surface7;
2246     HRESULT hr;
2247
2248     TRACE("iface %p, dc %p, surface %p.\n", iface, dc, surface);
2249
2250     if (!surface) return E_INVALIDARG;
2251
2252     hr = ddraw7_GetSurfaceFromDC((IDirectDraw7 *)ddraw_from_ddraw4(iface), dc, &surface7);
2253     *surface = surface7 ? (IDirectDrawSurface4 *)&((IDirectDrawSurfaceImpl *)surface7)->IDirectDrawSurface3_vtbl : NULL;
2254
2255     return hr;
2256 }
2257
2258 static HRESULT WINAPI ddraw3_GetSurfaceFromDC(IDirectDraw3 *iface, HDC dc, IDirectDrawSurface **surface)
2259 {
2260     TRACE("iface %p, dc %p, surface %p.\n", iface, dc, surface);
2261
2262     return ddraw7_GetSurfaceFromDC((IDirectDraw7 *)ddraw_from_ddraw3(iface),
2263             dc, (IDirectDrawSurface7 **)surface);
2264 }
2265
2266 /*****************************************************************************
2267  * IDirectDraw7::RestoreAllSurfaces
2268  *
2269  * Calls the restore method of all surfaces
2270  *
2271  * Params:
2272  *
2273  * Returns:
2274  *  Always returns DD_OK because it's a stub
2275  *
2276  *****************************************************************************/
2277 static HRESULT WINAPI ddraw7_RestoreAllSurfaces(IDirectDraw7 *iface)
2278 {
2279     IDirectDrawImpl *This = (IDirectDrawImpl *)iface;
2280     FIXME("(%p): Stub\n", This);
2281
2282     /* This isn't hard to implement: Enumerate all WineD3D surfaces,
2283      * get their parent and call their restore method. Do not implement
2284      * it in WineD3D, as restoring a surface means re-creating the
2285      * WineD3DDSurface
2286      */
2287     return DD_OK;
2288 }
2289
2290 static HRESULT WINAPI ddraw4_RestoreAllSurfaces(IDirectDraw4 *iface)
2291 {
2292     TRACE("iface %p.\n", iface);
2293
2294     return ddraw7_RestoreAllSurfaces((IDirectDraw7 *)ddraw_from_ddraw4(iface));
2295 }
2296
2297 /*****************************************************************************
2298  * IDirectDraw7::StartModeTest
2299  *
2300  * Tests the specified video modes to update the system registry with
2301  * refresh rate information. StartModeTest starts the mode test,
2302  * EvaluateMode is used to fail or pass a mode. If EvaluateMode
2303  * isn't called within 15 seconds, the mode is failed automatically
2304  *
2305  * As refresh rates are handled by the X server, I don't think this
2306  * Method is important
2307  *
2308  * Params:
2309  *  Modes: An array of mode specifications
2310  *  NumModes: The number of modes in Modes
2311  *  Flags: Some flags...
2312  *
2313  * Returns:
2314  *  Returns DDERR_TESTFINISHED if flags contains DDSMT_ISTESTREQUIRED,
2315  *  if no modes are passed, DDERR_INVALIDPARAMS is returned,
2316  *  otherwise DD_OK
2317  *
2318  *****************************************************************************/
2319 static HRESULT WINAPI ddraw7_StartModeTest(IDirectDraw7 *iface, SIZE *Modes, DWORD NumModes, DWORD Flags)
2320 {
2321     IDirectDrawImpl *This = (IDirectDrawImpl *)iface;
2322     WARN("(%p)->(%p, %d, %x): Semi-Stub, most likely harmless\n", This, Modes, NumModes, Flags);
2323
2324     /* This looks sane */
2325     if( (!Modes) || (NumModes == 0) ) return DDERR_INVALIDPARAMS;
2326
2327     /* DDSMT_ISTESTREQUIRED asks if a mode test is necessary.
2328      * As it is not, DDERR_TESTFINISHED is returned
2329      * (hopefully that's correct
2330      *
2331     if(Flags & DDSMT_ISTESTREQUIRED) return DDERR_TESTFINISHED;
2332      * well, that value doesn't (yet) exist in the wine headers, so ignore it
2333      */
2334
2335     return DD_OK;
2336 }
2337
2338 /*****************************************************************************
2339  * ddraw_recreate_surfaces_cb
2340  *
2341  * Enumeration callback for ddraw_recreate_surface.
2342  * It re-recreates the WineD3DSurface. It's pretty straightforward
2343  *
2344  *****************************************************************************/
2345 HRESULT WINAPI ddraw_recreate_surfaces_cb(IDirectDrawSurface7 *surf, DDSURFACEDESC2 *desc, void *Context)
2346 {
2347     IDirectDrawSurfaceImpl *surfImpl = (IDirectDrawSurfaceImpl *)surf;
2348     IDirectDrawImpl *This = surfImpl->ddraw;
2349     IUnknown *Parent;
2350     IWineD3DSurface *wineD3DSurface;
2351     IWineD3DSwapChain *swapchain;
2352     HRESULT hr;
2353     IWineD3DClipper *clipper = NULL;
2354
2355     WINED3DSURFACE_DESC     Desc;
2356     WINED3DFORMAT           Format;
2357     DWORD                   Usage;
2358     WINED3DPOOL             Pool;
2359
2360     WINED3DMULTISAMPLE_TYPE MultiSampleType;
2361     DWORD                   MultiSampleQuality;
2362     UINT                    Width;
2363     UINT                    Height;
2364
2365     TRACE("(%p): Enumerated Surface %p\n", This, surfImpl);
2366
2367     /* For the enumeration */
2368     IDirectDrawSurface7_Release(surf);
2369
2370     if(surfImpl->ImplType == This->ImplType) return DDENUMRET_OK; /* Continue */
2371
2372     /* Get the objects */
2373     swapchain = surfImpl->wineD3DSwapChain;
2374     surfImpl->wineD3DSwapChain = NULL;
2375     wineD3DSurface = surfImpl->WineD3DSurface;
2376
2377     /* get the clipper */
2378     IWineD3DSurface_GetClipper(wineD3DSurface, &clipper);
2379
2380     /* Get the surface properties */
2381     hr = IWineD3DSurface_GetDesc(wineD3DSurface, &Desc);
2382     if(hr != D3D_OK) return hr;
2383
2384     Format = Desc.format;
2385     Usage = Desc.usage;
2386     Pool = Desc.pool;
2387     MultiSampleType = Desc.multisample_type;
2388     MultiSampleQuality = Desc.multisample_quality;
2389     Width = Desc.width;
2390     Height = Desc.height;
2391
2392     IWineD3DSurface_GetParent(wineD3DSurface, &Parent);
2393
2394     /* Create the new surface */
2395     hr = IWineD3DDevice_CreateSurface(This->wineD3DDevice, Width, Height, Format,
2396             TRUE /* Lockable */, FALSE /* Discard */, surfImpl->mipmap_level, &surfImpl->WineD3DSurface, Usage, Pool,
2397             MultiSampleType, MultiSampleQuality, This->ImplType, Parent, &ddraw_null_wined3d_parent_ops);
2398     IUnknown_Release(Parent);
2399     if (FAILED(hr))
2400     {
2401         surfImpl->WineD3DSurface = wineD3DSurface;
2402         return hr;
2403     }
2404
2405     IWineD3DSurface_SetClipper(surfImpl->WineD3DSurface, clipper);
2406
2407     /* TODO: Copy the surface content, except for render targets */
2408
2409     /* If there's a swapchain, it owns the wined3d surfaces. So Destroy
2410      * the swapchain
2411      */
2412     if(swapchain) {
2413         /* The backbuffers have the swapchain set as well, but the primary
2414          * owns it and destroys it
2415          */
2416         if(surfImpl->surface_desc.ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE) {
2417             IWineD3DDevice_UninitGDI(This->wineD3DDevice, D3D7CB_DestroySwapChain);
2418         }
2419         surfImpl->isRenderTarget = FALSE;
2420     } else {
2421         if(IWineD3DSurface_Release(wineD3DSurface) == 0)
2422             TRACE("Surface released successful, next surface\n");
2423         else
2424             ERR("Something's still holding the old WineD3DSurface\n");
2425     }
2426
2427     surfImpl->ImplType = This->ImplType;
2428
2429     if(clipper)
2430     {
2431         IWineD3DClipper_Release(clipper);
2432     }
2433     return DDENUMRET_OK;
2434 }
2435
2436 /*****************************************************************************
2437  * ddraw_recreate_surfaces
2438  *
2439  * A function, that converts all wineD3DSurfaces to the new implementation type
2440  * It enumerates all surfaces with IWineD3DDevice::EnumSurfaces, creates a
2441  * new WineD3DSurface, copies the content and releases the old surface
2442  *
2443  *****************************************************************************/
2444 static HRESULT ddraw_recreate_surfaces(IDirectDrawImpl *This)
2445 {
2446     DDSURFACEDESC2 desc;
2447     TRACE("(%p): Switch to implementation %d\n", This, This->ImplType);
2448
2449     if(This->ImplType != SURFACE_OPENGL && This->d3d_initialized)
2450     {
2451         /* Should happen almost never */
2452         FIXME("(%p) Switching to non-opengl surfaces with d3d started. Is this a bug?\n", This);
2453         /* Shutdown d3d */
2454         IWineD3DDevice_Uninit3D(This->wineD3DDevice, D3D7CB_DestroySwapChain);
2455     }
2456     /* Contrary: D3D starting is handled by the caller, because it knows the render target */
2457
2458     memset(&desc, 0, sizeof(desc));
2459     desc.dwSize = sizeof(desc);
2460
2461     return IDirectDraw7_EnumSurfaces((IDirectDraw7 *)This, 0, &desc, This, ddraw_recreate_surfaces_cb);
2462 }
2463
2464 ULONG WINAPI D3D7CB_DestroySwapChain(IWineD3DSwapChain *pSwapChain) {
2465     IUnknown* swapChainParent;
2466     TRACE("(%p) call back\n", pSwapChain);
2467
2468     IWineD3DSwapChain_GetParent(pSwapChain, &swapChainParent);
2469     IUnknown_Release(swapChainParent);
2470     return IUnknown_Release(swapChainParent);
2471 }
2472
2473 /*****************************************************************************
2474  * ddraw_create_surface
2475  *
2476  * A helper function for IDirectDraw7::CreateSurface. It creates a new surface
2477  * with the passed parameters.
2478  *
2479  * Params:
2480  *  DDSD: Description of the surface to create
2481  *  Surf: Address to store the interface pointer at
2482  *
2483  * Returns:
2484  *  DD_OK on success
2485  *
2486  *****************************************************************************/
2487 static HRESULT ddraw_create_surface(IDirectDrawImpl *This, DDSURFACEDESC2 *pDDSD,
2488         IDirectDrawSurfaceImpl **ppSurf, UINT level)
2489 {
2490     HRESULT hr;
2491     UINT Width, Height;
2492     WINED3DFORMAT Format = WINED3DFMT_UNKNOWN;
2493     DWORD Usage = 0;
2494     WINED3DSURFTYPE ImplType = This->ImplType;
2495     WINED3DSURFACE_DESC Desc;
2496     WINED3DPOOL Pool = WINED3DPOOL_DEFAULT;
2497
2498     if (TRACE_ON(ddraw))
2499     {
2500         TRACE(" (%p) Requesting surface desc :\n", This);
2501         DDRAW_dump_surface_desc(pDDSD);
2502     }
2503
2504     /* Select the surface type, if it wasn't choosen yet */
2505     if(ImplType == SURFACE_UNKNOWN)
2506     {
2507         /* Use GL Surfaces if a D3DDEVICE Surface is requested */
2508         if(pDDSD->ddsCaps.dwCaps & DDSCAPS_3DDEVICE)
2509         {
2510             TRACE("(%p) Choosing GL surfaces because a 3DDEVICE Surface was requested\n", This);
2511             ImplType = SURFACE_OPENGL;
2512         }
2513
2514         /* Otherwise use GDI surfaces for now */
2515         else
2516         {
2517             TRACE("(%p) Choosing GDI surfaces for 2D rendering\n", This);
2518             ImplType = SURFACE_GDI;
2519         }
2520
2521         /* Policy if all surface implementations are available:
2522          * First, check if a default type was set with winecfg. If not,
2523          * try Xrender surfaces, and use them if they work. Next, check if
2524          * accelerated OpenGL is available, and use GL surfaces in this
2525          * case. If all else fails, use GDI surfaces. If a 3DDEVICE surface
2526          * was created, always use OpenGL surfaces.
2527          *
2528          * (Note: Xrender surfaces are not implemented for now, the
2529          * unaccelerated implementation uses GDI to render in Software)
2530          */
2531
2532         /* Store the type. If it needs to be changed, all WineD3DSurfaces have to
2533          * be re-created. This could be done with IDirectDrawSurface7::Restore
2534          */
2535         This->ImplType = ImplType;
2536     }
2537     else
2538     {
2539         if ((pDDSD->ddsCaps.dwCaps & DDSCAPS_3DDEVICE)
2540                 && (This->ImplType != SURFACE_OPENGL)
2541                 && DefaultSurfaceType == SURFACE_UNKNOWN)
2542         {
2543             /* We have to change to OpenGL,
2544              * and re-create all WineD3DSurfaces
2545              */
2546             ImplType = SURFACE_OPENGL;
2547             This->ImplType = ImplType;
2548             TRACE("(%p) Re-creating all surfaces\n", This);
2549             ddraw_recreate_surfaces(This);
2550             TRACE("(%p) Done recreating all surfaces\n", This);
2551         }
2552         else if(This->ImplType != SURFACE_OPENGL && pDDSD->ddsCaps.dwCaps & DDSCAPS_3DDEVICE)
2553         {
2554             WARN("The application requests a 3D capable surface, but a non-opengl surface was set in the registry\n");
2555             /* Do not fail surface creation, only fail 3D device creation */
2556         }
2557     }
2558
2559     if (!(pDDSD->ddsCaps.dwCaps & (DDSCAPS_VIDEOMEMORY | DDSCAPS_SYSTEMMEMORY)) &&
2560         !((pDDSD->ddsCaps.dwCaps & DDSCAPS_TEXTURE) && (pDDSD->ddsCaps.dwCaps2 & DDSCAPS2_TEXTUREMANAGE)) )
2561     {
2562         /* Tests show surfaces without memory flags get these flags added right after creation. */
2563         pDDSD->ddsCaps.dwCaps |= DDSCAPS_LOCALVIDMEM | DDSCAPS_VIDEOMEMORY;
2564     }
2565     /* Get the correct wined3d usage */
2566     if (pDDSD->ddsCaps.dwCaps & (DDSCAPS_PRIMARYSURFACE |
2567                                  DDSCAPS_3DDEVICE       ) )
2568     {
2569         Usage |= WINED3DUSAGE_RENDERTARGET;
2570
2571         pDDSD->ddsCaps.dwCaps |= DDSCAPS_VISIBLE;
2572     }
2573     if (pDDSD->ddsCaps.dwCaps & (DDSCAPS_OVERLAY))
2574     {
2575         Usage |= WINED3DUSAGE_OVERLAY;
2576     }
2577     if(This->depthstencil || (pDDSD->ddsCaps.dwCaps & DDSCAPS_ZBUFFER) )
2578     {
2579         /* The depth stencil creation callback sets this flag.
2580          * Set the WineD3D usage to let it know that it's a depth
2581          * Stencil surface.
2582          */
2583         Usage |= WINED3DUSAGE_DEPTHSTENCIL;
2584     }
2585     if(pDDSD->ddsCaps.dwCaps & DDSCAPS_SYSTEMMEMORY)
2586     {
2587         Pool = WINED3DPOOL_SYSTEMMEM;
2588     }
2589     else if(pDDSD->ddsCaps.dwCaps2 & DDSCAPS2_TEXTUREMANAGE)
2590     {
2591         Pool = WINED3DPOOL_MANAGED;
2592         /* Managed textures have the system memory flag set */
2593         pDDSD->ddsCaps.dwCaps |= DDSCAPS_SYSTEMMEMORY;
2594     }
2595     else if(pDDSD->ddsCaps.dwCaps & DDSCAPS_VIDEOMEMORY)
2596     {
2597         /* Videomemory adds localvidmem, this is mutually exclusive with systemmemory
2598          * and texturemanage
2599          */
2600         pDDSD->ddsCaps.dwCaps |= DDSCAPS_LOCALVIDMEM;
2601     }
2602
2603     Format = PixelFormat_DD2WineD3D(&pDDSD->u4.ddpfPixelFormat);
2604     if(Format == WINED3DFMT_UNKNOWN)
2605     {
2606         ERR("Unsupported / Unknown pixelformat\n");
2607         return DDERR_INVALIDPIXELFORMAT;
2608     }
2609
2610     /* Create the Surface object */
2611     *ppSurf = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDirectDrawSurfaceImpl));
2612     if(!*ppSurf)
2613     {
2614         ERR("(%p) Error allocating memory for a surface\n", This);
2615         return DDERR_OUTOFVIDEOMEMORY;
2616     }
2617     (*ppSurf)->lpVtbl = &IDirectDrawSurface7_Vtbl;
2618     (*ppSurf)->IDirectDrawSurface3_vtbl = &IDirectDrawSurface3_Vtbl;
2619     (*ppSurf)->IDirectDrawGammaControl_vtbl = &IDirectDrawGammaControl_Vtbl;
2620     (*ppSurf)->IDirect3DTexture2_vtbl = &IDirect3DTexture2_Vtbl;
2621     (*ppSurf)->IDirect3DTexture_vtbl = &IDirect3DTexture1_Vtbl;
2622     (*ppSurf)->ref = 1;
2623     (*ppSurf)->version = 7;
2624     TRACE("%p->version = %d\n", (*ppSurf), (*ppSurf)->version);
2625     (*ppSurf)->ddraw = This;
2626     (*ppSurf)->surface_desc.dwSize = sizeof(DDSURFACEDESC2);
2627     (*ppSurf)->surface_desc.u4.ddpfPixelFormat.dwSize = sizeof(DDPIXELFORMAT);
2628     DD_STRUCT_COPY_BYSIZE(&(*ppSurf)->surface_desc, pDDSD);
2629
2630     /* Surface attachments */
2631     (*ppSurf)->next_attached = NULL;
2632     (*ppSurf)->first_attached = *ppSurf;
2633
2634     /* Needed to re-create the surface on an implementation change */
2635     (*ppSurf)->ImplType = ImplType;
2636
2637     /* For D3DDevice creation */
2638     (*ppSurf)->isRenderTarget = FALSE;
2639
2640     /* A trace message for debugging */
2641     TRACE("(%p) Created IDirectDrawSurface implementation structure at %p\n", This, *ppSurf);
2642
2643     /* Now create the WineD3D Surface */
2644     hr = IWineD3DDevice_CreateSurface(This->wineD3DDevice, pDDSD->dwWidth, pDDSD->dwHeight, Format,
2645             TRUE /* Lockable */, FALSE /* Discard */, level, &(*ppSurf)->WineD3DSurface,
2646             Usage, Pool, WINED3DMULTISAMPLE_NONE, 0 /* MultiSampleQuality */, ImplType,
2647             (IUnknown *)*ppSurf, &ddraw_null_wined3d_parent_ops);
2648
2649     if(hr != D3D_OK)
2650     {
2651         ERR("IWineD3DDevice::CreateSurface failed. hr = %08x\n", hr);
2652         return hr;
2653     }
2654
2655     /* Increase the surface counter, and attach the surface */
2656     InterlockedIncrement(&This->surfaces);
2657     list_add_head(&This->surface_list, &(*ppSurf)->surface_list_entry);
2658
2659     /* Here we could store all created surfaces in the DirectDrawImpl structure,
2660      * But this could also be delegated to WineDDraw, as it keeps track of all its
2661      * resources. Not implemented for now, as there are more important things ;)
2662      */
2663
2664     /* Get the pixel format of the WineD3DSurface and store it.
2665      * Don't use the Format choosen above, WineD3D might have
2666      * changed it
2667      */
2668     (*ppSurf)->surface_desc.dwFlags |= DDSD_PIXELFORMAT;
2669     hr = IWineD3DSurface_GetDesc((*ppSurf)->WineD3DSurface, &Desc);
2670     if(hr != D3D_OK)
2671     {
2672         ERR("IWineD3DSurface::GetDesc failed\n");
2673         IDirectDrawSurface7_Release( (IDirectDrawSurface7 *) *ppSurf);
2674         return hr;
2675     }
2676
2677     Format = Desc.format;
2678     Width = Desc.width;
2679     Height = Desc.height;
2680
2681     if(Format == WINED3DFMT_UNKNOWN)
2682     {
2683         FIXME("IWineD3DSurface::GetDesc returned WINED3DFMT_UNKNOWN\n");
2684     }
2685     PixelFormat_WineD3DtoDD( &(*ppSurf)->surface_desc.u4.ddpfPixelFormat, Format);
2686
2687     /* Anno 1602 stores the pitch right after surface creation, so make sure it's there.
2688      * I can't LockRect() the surface here because if OpenGL surfaces are in use, the
2689      * WineD3DDevice might not be usable for 3D yet, so an extra method was created.
2690      * TODO: Test other fourcc formats
2691      */
2692     if(Format == WINED3DFMT_DXT1 || Format == WINED3DFMT_DXT2 || Format == WINED3DFMT_DXT3 ||
2693        Format == WINED3DFMT_DXT4 || Format == WINED3DFMT_DXT5)
2694     {
2695         (*ppSurf)->surface_desc.dwFlags |= DDSD_LINEARSIZE;
2696         if(Format == WINED3DFMT_DXT1)
2697         {
2698             (*ppSurf)->surface_desc.u1.dwLinearSize = max(4, Width) * max(4, Height) / 2;
2699         }
2700         else
2701         {
2702             (*ppSurf)->surface_desc.u1.dwLinearSize = max(4, Width) * max(4, Height);
2703         }
2704     }
2705     else
2706     {
2707         (*ppSurf)->surface_desc.dwFlags |= DDSD_PITCH;
2708         (*ppSurf)->surface_desc.u1.lPitch = IWineD3DSurface_GetPitch((*ppSurf)->WineD3DSurface);
2709     }
2710
2711     /* Application passed a color key? Set it! */
2712     if(pDDSD->dwFlags & DDSD_CKDESTOVERLAY)
2713     {
2714         IWineD3DSurface_SetColorKey((*ppSurf)->WineD3DSurface,
2715                                     DDCKEY_DESTOVERLAY,
2716                                     (WINEDDCOLORKEY *) &pDDSD->u3.ddckCKDestOverlay);
2717     }
2718     if(pDDSD->dwFlags & DDSD_CKDESTBLT)
2719     {
2720         IWineD3DSurface_SetColorKey((*ppSurf)->WineD3DSurface,
2721                                     DDCKEY_DESTBLT,
2722                                     (WINEDDCOLORKEY *) &pDDSD->ddckCKDestBlt);
2723     }
2724     if(pDDSD->dwFlags & DDSD_CKSRCOVERLAY)
2725     {
2726         IWineD3DSurface_SetColorKey((*ppSurf)->WineD3DSurface,
2727                                     DDCKEY_SRCOVERLAY,
2728                                     (WINEDDCOLORKEY *) &pDDSD->ddckCKSrcOverlay);
2729     }
2730     if(pDDSD->dwFlags & DDSD_CKSRCBLT)
2731     {
2732         IWineD3DSurface_SetColorKey((*ppSurf)->WineD3DSurface,
2733                                     DDCKEY_SRCBLT,
2734                                     (WINEDDCOLORKEY *) &pDDSD->ddckCKSrcBlt);
2735     }
2736     if ( pDDSD->dwFlags & DDSD_LPSURFACE)
2737     {
2738         hr = IWineD3DSurface_SetMem((*ppSurf)->WineD3DSurface, pDDSD->lpSurface);
2739         if(hr != WINED3D_OK)
2740         {
2741             /* No need for a trace here, wined3d does that for us */
2742             IDirectDrawSurface7_Release((IDirectDrawSurface7 *)*ppSurf);
2743             return hr;
2744         }
2745     }
2746
2747     return DD_OK;
2748 }
2749 /*****************************************************************************
2750  * CreateAdditionalSurfaces
2751  *
2752  * Creates a new mipmap chain.
2753  *
2754  * Params:
2755  *  root: Root surface to attach the newly created chain to
2756  *  count: number of surfaces to create
2757  *  DDSD: Description of the surface. Intentionally not a pointer to avoid side
2758  *        effects on the caller
2759  *  CubeFaceRoot: Whether the new surface is a root of a cube map face. This
2760  *                creates an additional surface without the mipmapping flags
2761  *
2762  *****************************************************************************/
2763 static HRESULT
2764 CreateAdditionalSurfaces(IDirectDrawImpl *This,
2765                          IDirectDrawSurfaceImpl *root,
2766                          UINT count,
2767                          DDSURFACEDESC2 DDSD,
2768                          BOOL CubeFaceRoot)
2769 {
2770     UINT i, j, level = 0;
2771     HRESULT hr;
2772     IDirectDrawSurfaceImpl *last = root;
2773
2774     for(i = 0; i < count; i++)
2775     {
2776         IDirectDrawSurfaceImpl *object2 = NULL;
2777
2778         /* increase the mipmap level, but only if a mipmap is created
2779          * In this case, also halve the size
2780          */
2781         if(DDSD.ddsCaps.dwCaps & DDSCAPS_MIPMAP && !CubeFaceRoot)
2782         {
2783             level++;
2784             if(DDSD.dwWidth > 1) DDSD.dwWidth /= 2;
2785             if(DDSD.dwHeight > 1) DDSD.dwHeight /= 2;
2786             /* Set the mipmap sublevel flag according to msdn */
2787             DDSD.ddsCaps.dwCaps2 |= DDSCAPS2_MIPMAPSUBLEVEL;
2788         }
2789         else
2790         {
2791             DDSD.ddsCaps.dwCaps2 &= ~DDSCAPS2_MIPMAPSUBLEVEL;
2792         }
2793         CubeFaceRoot = FALSE;
2794
2795         hr = ddraw_create_surface(This, &DDSD, &object2, level);
2796         if(hr != DD_OK)
2797         {
2798             return hr;
2799         }
2800
2801         /* Add the new surface to the complex attachment array */
2802         for(j = 0; j < MAX_COMPLEX_ATTACHED; j++)
2803         {
2804             if(last->complex_array[j]) continue;
2805             last->complex_array[j] = object2;
2806             break;
2807         }
2808         last = object2;
2809
2810         /* Remove the (possible) back buffer cap from the new surface description,
2811          * because only one surface in the flipping chain is a back buffer, one
2812          * is a front buffer, the others are just primary surfaces.
2813          */
2814         DDSD.ddsCaps.dwCaps &= ~DDSCAPS_BACKBUFFER;
2815     }
2816     return DD_OK;
2817 }
2818
2819 /* Must set all attached surfaces (e.g. mipmaps) versions as well */
2820 static void ddraw_set_surface_version(IDirectDrawSurfaceImpl *surface, UINT version)
2821 {
2822     unsigned int i;
2823
2824     TRACE("surface %p, version %u -> %u.\n", surface, surface->version, version);
2825
2826     surface->version = version;
2827     for (i = 0; i < MAX_COMPLEX_ATTACHED; ++i)
2828     {
2829         if (!surface->complex_array[i]) break;
2830         ddraw_set_surface_version(surface->complex_array[i], version);
2831     }
2832     while ((surface = surface->next_attached))
2833     {
2834         ddraw_set_surface_version(surface, version);
2835     }
2836 }
2837
2838 /*****************************************************************************
2839  * ddraw_attach_d3d_device
2840  *
2841  * Initializes the D3D capabilities of WineD3D
2842  *
2843  * Params:
2844  *  primary: The primary surface for D3D
2845  *
2846  * Returns
2847  *  DD_OK on success,
2848  *  DDERR_* otherwise
2849  *
2850  *****************************************************************************/
2851 static HRESULT ddraw_attach_d3d_device(IDirectDrawImpl *ddraw, IDirectDrawSurfaceImpl *primary)
2852 {
2853     WINED3DPRESENT_PARAMETERS localParameters;
2854     HWND window = ddraw->dest_window;
2855     HRESULT hr;
2856
2857     TRACE("ddraw %p, primary %p.\n", ddraw, primary);
2858
2859     if (!window || window == GetDesktopWindow())
2860     {
2861         window = CreateWindowExA(0, DDRAW_WINDOW_CLASS_NAME, "Hidden D3D Window",
2862                 WS_DISABLED, 0, 0, GetSystemMetrics(SM_CXSCREEN), GetSystemMetrics(SM_CYSCREEN),
2863                 NULL, NULL, NULL, NULL);
2864         if (!window)
2865         {
2866             ERR("Failed to create window, last error %#x.\n", GetLastError());
2867             return E_FAIL;
2868         }
2869
2870         ShowWindow(window, SW_HIDE);   /* Just to be sure */
2871         WARN("No window for the Direct3DDevice, created hidden window %p.\n", window);
2872     }
2873     else
2874     {
2875         TRACE("Using existing window %p for Direct3D rendering.\n", window);
2876     }
2877     ddraw->d3d_window = window;
2878
2879     /* Store the future Render Target surface */
2880     ddraw->d3d_target = primary;
2881
2882     /* Use the surface description for the device parameters, not the device
2883      * settings. The application might render to an offscreen surface. */
2884     localParameters.BackBufferWidth = primary->surface_desc.dwWidth;
2885     localParameters.BackBufferHeight = primary->surface_desc.dwHeight;
2886     localParameters.BackBufferFormat = PixelFormat_DD2WineD3D(&primary->surface_desc.u4.ddpfPixelFormat);
2887     localParameters.BackBufferCount = (primary->surface_desc.dwFlags & DDSD_BACKBUFFERCOUNT)
2888             ? primary->surface_desc.dwBackBufferCount : 0;
2889     localParameters.MultiSampleType = WINED3DMULTISAMPLE_NONE;
2890     localParameters.MultiSampleQuality = 0;
2891     localParameters.SwapEffect = WINED3DSWAPEFFECT_COPY;
2892     localParameters.hDeviceWindow = window;
2893     localParameters.Windowed = !(ddraw->cooperative_level & DDSCL_FULLSCREEN);
2894     localParameters.EnableAutoDepthStencil = TRUE;
2895     localParameters.AutoDepthStencilFormat = WINED3DFMT_D16_UNORM;
2896     localParameters.Flags = 0;
2897     localParameters.FullScreen_RefreshRateInHz = WINED3DPRESENT_RATE_DEFAULT;
2898     localParameters.PresentationInterval = WINED3DPRESENT_INTERVAL_DEFAULT;
2899
2900     /* Set this NOW, otherwise creating the depth stencil surface will cause a
2901      * recursive loop until ram or emulated video memory is full. */
2902     ddraw->d3d_initialized = TRUE;
2903     hr = IWineD3DDevice_Init3D(ddraw->wineD3DDevice, &localParameters);
2904     if (FAILED(hr))
2905     {
2906         ddraw->d3d_target = NULL;
2907         ddraw->d3d_initialized = FALSE;
2908         return hr;
2909     }
2910
2911     ddraw->declArraySize = 2;
2912     ddraw->decls = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*ddraw->decls) * ddraw->declArraySize);
2913     if (!ddraw->decls)
2914     {
2915         ERR("Error allocating an array for the converted vertex decls.\n");
2916         ddraw->declArraySize = 0;
2917         hr = IWineD3DDevice_Uninit3D(ddraw->wineD3DDevice, D3D7CB_DestroySwapChain);
2918         return E_OUTOFMEMORY;
2919     }
2920
2921     TRACE("Successfully initialized 3D.\n");
2922
2923     return DD_OK;
2924 }
2925
2926 static HRESULT ddraw_create_gdi_swapchain(IDirectDrawImpl *ddraw, IDirectDrawSurfaceImpl *primary)
2927 {
2928     WINED3DPRESENT_PARAMETERS presentation_parameters;
2929     HWND window;
2930     HRESULT hr;
2931
2932     window = ddraw->dest_window;
2933
2934     memset(&presentation_parameters, 0, sizeof(presentation_parameters));
2935
2936     /* Use the surface description for the device parameters, not the device
2937      * settings. The application might render to an offscreen surface. */
2938     presentation_parameters.BackBufferWidth = primary->surface_desc.dwWidth;
2939     presentation_parameters.BackBufferHeight = primary->surface_desc.dwHeight;
2940     presentation_parameters.BackBufferFormat = PixelFormat_DD2WineD3D(&primary->surface_desc.u4.ddpfPixelFormat);
2941     presentation_parameters.BackBufferCount = (primary->surface_desc.dwFlags & DDSD_BACKBUFFERCOUNT)
2942             ? primary->surface_desc.dwBackBufferCount : 0;
2943     presentation_parameters.MultiSampleType = WINED3DMULTISAMPLE_NONE;
2944     presentation_parameters.MultiSampleQuality = 0;
2945     presentation_parameters.SwapEffect = WINED3DSWAPEFFECT_FLIP;
2946     presentation_parameters.hDeviceWindow = window;
2947     presentation_parameters.Windowed = !(ddraw->cooperative_level & DDSCL_FULLSCREEN);
2948     presentation_parameters.EnableAutoDepthStencil = FALSE; /* Not on GDI swapchains */
2949     presentation_parameters.AutoDepthStencilFormat = 0;
2950     presentation_parameters.Flags = 0;
2951     presentation_parameters.FullScreen_RefreshRateInHz = WINED3DPRESENT_RATE_DEFAULT;
2952     presentation_parameters.PresentationInterval = WINED3DPRESENT_INTERVAL_DEFAULT;
2953
2954     ddraw->d3d_target = primary;
2955     hr = IWineD3DDevice_InitGDI(ddraw->wineD3DDevice, &presentation_parameters);
2956     ddraw->d3d_target = NULL;
2957     if (FAILED(hr))
2958     {
2959         WARN("Failed to initialize GDI ddraw implementation, hr %#x.\n", hr);
2960         primary->wineD3DSwapChain = NULL;
2961     }
2962
2963     return hr;
2964 }
2965
2966 /*****************************************************************************
2967  * IDirectDraw7::CreateSurface
2968  *
2969  * Creates a new IDirectDrawSurface object and returns its interface.
2970  *
2971  * The surface connections with wined3d are a bit tricky. Basically it works
2972  * like this:
2973  *
2974  * |------------------------|               |-----------------|
2975  * | DDraw surface          |               | WineD3DSurface  |
2976  * |                        |               |                 |
2977  * |        WineD3DSurface  |-------------->|                 |
2978  * |        Child           |<------------->| Parent          |
2979  * |------------------------|               |-----------------|
2980  *
2981  * The DDraw surface is the parent of the wined3d surface, and it releases
2982  * the WineD3DSurface when the ddraw surface is destroyed.
2983  *
2984  * However, for all surfaces which can be in a container in WineD3D,
2985  * we have to do this. These surfaces are usually complex surfaces,
2986  * so this concerns primary surfaces with a front and a back buffer,
2987  * and textures.
2988  *
2989  * |------------------------|               |-----------------|
2990  * | DDraw surface          |               | Container       |
2991  * |                        |               |                 |
2992  * |                  Child |<------------->| Parent          |
2993  * |                Texture |<------------->|                 |
2994  * |         WineD3DSurface |<----|         |          Levels |<--|
2995  * | Complex connection     |     |         |                 |   |
2996  * |------------------------|     |         |-----------------|   |
2997  *  ^                             |                               |
2998  *  |                             |                               |
2999  *  |                             |                               |
3000  *  |    |------------------|     |         |-----------------|   |
3001  *  |    | IParent          |     |-------->| WineD3DSurface  |   |
3002  *  |    |                  |               |                 |   |
3003  *  |    |            Child |<------------->| Parent          |   |
3004  *  |    |                  |               |       Container |<--|
3005  *  |    |------------------|               |-----------------|   |
3006  *  |                                                             |
3007  *  |   |----------------------|                                  |
3008  *  |   | DDraw surface 2      |                                  |
3009  *  |   |                      |                                  |
3010  *  |<->| Complex root   Child |                                  |
3011  *  |   |              Texture |                                  |
3012  *  |   |       WineD3DSurface |<----|                            |
3013  *  |   |----------------------|     |                            |
3014  *  |                                |                            |
3015  *  |    |---------------------|     |      |-----------------|   |
3016  *  |    | IParent             |     |----->| WineD3DSurface  |   |
3017  *  |    |                     |            |                 |   |
3018  *  |    |               Child |<---------->| Parent          |   |
3019  *  |    |---------------------|            |       Container |<--|
3020  *  |                                       |-----------------|   |
3021  *  |                                                             |
3022  *  |             ---More surfaces can follow---                  |
3023  *
3024  * The reason is that the IWineD3DSwapchain(render target container)
3025  * and the IWineD3DTexure(Texture container) release the parents
3026  * of their surface's children, but by releasing the complex root
3027  * the surfaces which are complexly attached to it are destroyed
3028  * too. See IDirectDrawSurface::Release for a more detailed
3029  * explanation.
3030  *
3031  * Params:
3032  *  DDSD: Description of the surface to create
3033  *  Surf: Address to store the interface pointer at
3034  *  UnkOuter: Basically for aggregation support, but ddraw doesn't support
3035  *            aggregation, so it has to be NULL
3036  *
3037  * Returns:
3038  *  DD_OK on success
3039  *  CLASS_E_NOAGGREGATION if UnkOuter != NULL
3040  *  DDERR_* if an error occurs
3041  *
3042  *****************************************************************************/
3043 static HRESULT WINAPI ddraw7_CreateSurface(IDirectDraw7 *iface,
3044         DDSURFACEDESC2 *DDSD, IDirectDrawSurface7 **Surf, IUnknown *UnkOuter)
3045 {
3046     IDirectDrawImpl *This = (IDirectDrawImpl *)iface;
3047     IDirectDrawSurfaceImpl *object = NULL;
3048     HRESULT hr;
3049     LONG extra_surfaces = 0;
3050     DDSURFACEDESC2 desc2;
3051     WINED3DDISPLAYMODE Mode;
3052     const DWORD sysvidmem = DDSCAPS_VIDEOMEMORY | DDSCAPS_SYSTEMMEMORY;
3053
3054     TRACE("(%p)->(%p,%p,%p)\n", This, DDSD, Surf, UnkOuter);
3055
3056     /* Some checks before we start */
3057     if (TRACE_ON(ddraw))
3058     {
3059         TRACE(" (%p) Requesting surface desc :\n", This);
3060         DDRAW_dump_surface_desc(DDSD);
3061     }
3062     EnterCriticalSection(&ddraw_cs);
3063
3064     if (UnkOuter != NULL)
3065     {
3066         FIXME("(%p) : outer != NULL?\n", This);
3067         LeaveCriticalSection(&ddraw_cs);
3068         return CLASS_E_NOAGGREGATION; /* unchecked */
3069     }
3070
3071     if (Surf == NULL)
3072     {
3073         FIXME("(%p) You want to get back a surface? Don't give NULL ptrs!\n", This);
3074         LeaveCriticalSection(&ddraw_cs);
3075         return E_POINTER; /* unchecked */
3076     }
3077
3078     if (!(DDSD->dwFlags & DDSD_CAPS))
3079     {
3080         /* DVIDEO.DLL does forget the DDSD_CAPS flag ... *sigh* */
3081         DDSD->dwFlags |= DDSD_CAPS;
3082     }
3083
3084     if (DDSD->ddsCaps.dwCaps & DDSCAPS_ALLOCONLOAD)
3085     {
3086         /* If the surface is of the 'alloconload' type, ignore the LPSURFACE field */
3087         DDSD->dwFlags &= ~DDSD_LPSURFACE;
3088     }
3089
3090     if ((DDSD->dwFlags & DDSD_LPSURFACE) && (DDSD->lpSurface == NULL))
3091     {
3092         /* Frank Herbert's Dune specifies a null pointer for the surface, ignore the LPSURFACE field */
3093         WARN("(%p) Null surface pointer specified, ignore it!\n", This);
3094         DDSD->dwFlags &= ~DDSD_LPSURFACE;
3095     }
3096
3097     if((DDSD->ddsCaps.dwCaps & (DDSCAPS_FLIP | DDSCAPS_PRIMARYSURFACE)) == (DDSCAPS_FLIP | DDSCAPS_PRIMARYSURFACE) &&
3098        !(This->cooperative_level & DDSCL_EXCLUSIVE))
3099     {
3100         TRACE("(%p): Attempt to create a flipable primary surface without DDSCL_EXCLUSIVE set\n", This);
3101         *Surf = NULL;
3102         LeaveCriticalSection(&ddraw_cs);
3103         return DDERR_NOEXCLUSIVEMODE;
3104     }
3105
3106     if(DDSD->ddsCaps.dwCaps & (DDSCAPS_FRONTBUFFER | DDSCAPS_BACKBUFFER)) {
3107         WARN("Application tried to create an explicit front or back buffer\n");
3108         LeaveCriticalSection(&ddraw_cs);
3109         return DDERR_INVALIDCAPS;
3110     }
3111
3112     if((DDSD->ddsCaps.dwCaps & sysvidmem) == sysvidmem)
3113     {
3114         /* This is a special switch in ddrawex.dll, but not allowed in ddraw.dll */
3115         WARN("Application tries to put the surface in both system and video memory\n");
3116         LeaveCriticalSection(&ddraw_cs);
3117         *Surf = NULL;
3118         return DDERR_INVALIDCAPS;
3119     }
3120
3121     /* Check cube maps but only if the size includes them */
3122     if (DDSD->dwSize >= sizeof(DDSURFACEDESC2))
3123     {
3124         if(DDSD->ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP_ALLFACES &&
3125            !(DDSD->ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP))
3126         {
3127             WARN("Cube map faces requested without cube map flag\n");
3128             LeaveCriticalSection(&ddraw_cs);
3129             return DDERR_INVALIDCAPS;
3130         }
3131         if(DDSD->ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP &&
3132            (DDSD->ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP_ALLFACES) == 0)
3133         {
3134             WARN("Cube map without faces requested\n");
3135             LeaveCriticalSection(&ddraw_cs);
3136             return DDERR_INVALIDPARAMS;
3137         }
3138
3139         /* Quick tests confirm those can be created, but we don't do that yet */
3140         if(DDSD->ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP &&
3141            (DDSD->ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP_ALLFACES) != DDSCAPS2_CUBEMAP_ALLFACES)
3142         {
3143             FIXME("Partial cube maps not supported yet\n");
3144         }
3145     }
3146
3147     /* According to the msdn this flag is ignored by CreateSurface */
3148     if (DDSD->dwSize >= sizeof(DDSURFACEDESC2))
3149         DDSD->ddsCaps.dwCaps2 &= ~DDSCAPS2_MIPMAPSUBLEVEL;
3150
3151     /* Modify some flags */
3152     memset(&desc2, 0, sizeof(desc2));
3153     desc2.dwSize = sizeof(desc2);   /* For the struct copy */
3154     DD_STRUCT_COPY_BYSIZE(&desc2, DDSD);
3155     desc2.dwSize = sizeof(desc2);   /* To override a possibly smaller size */
3156     desc2.u4.ddpfPixelFormat.dwSize=sizeof(DDPIXELFORMAT); /* Just to be sure */
3157
3158     /* Get the video mode from WineD3D - we will need it */
3159     hr = IWineD3DDevice_GetDisplayMode(This->wineD3DDevice,
3160                                        0, /* Swapchain 0 */
3161                                        &Mode);
3162     if(FAILED(hr))
3163     {
3164         ERR("Failed to read display mode from wined3d\n");
3165         switch(This->orig_bpp)
3166         {
3167             case 8:
3168                 Mode.Format = WINED3DFMT_P8_UINT;
3169                 break;
3170
3171             case 15:
3172                 Mode.Format = WINED3DFMT_B5G5R5X1_UNORM;
3173                 break;
3174
3175             case 16:
3176                 Mode.Format = WINED3DFMT_B5G6R5_UNORM;
3177                 break;
3178
3179             case 24:
3180                 Mode.Format = WINED3DFMT_B8G8R8_UNORM;
3181                 break;
3182
3183             case 32:
3184                 Mode.Format = WINED3DFMT_B8G8R8X8_UNORM;
3185                 break;
3186         }
3187         Mode.Width = This->orig_width;
3188         Mode.Height = This->orig_height;
3189     }
3190
3191     /* No pixelformat given? Use the current screen format */
3192     if(!(desc2.dwFlags & DDSD_PIXELFORMAT))
3193     {
3194         desc2.dwFlags |= DDSD_PIXELFORMAT;
3195         desc2.u4.ddpfPixelFormat.dwSize=sizeof(DDPIXELFORMAT);
3196
3197         /* Wait: It could be a Z buffer */
3198         if(desc2.ddsCaps.dwCaps & DDSCAPS_ZBUFFER)
3199         {
3200             switch(desc2.u2.dwMipMapCount) /* Who had this glorious idea? */
3201             {
3202                 case 15:
3203                     PixelFormat_WineD3DtoDD(&desc2.u4.ddpfPixelFormat, WINED3DFMT_S1_UINT_D15_UNORM);
3204                     break;
3205                 case 16:
3206                     PixelFormat_WineD3DtoDD(&desc2.u4.ddpfPixelFormat, WINED3DFMT_D16_UNORM);
3207                     break;
3208                 case 24:
3209                     PixelFormat_WineD3DtoDD(&desc2.u4.ddpfPixelFormat, WINED3DFMT_X8D24_UNORM);
3210                     break;
3211                 case 32:
3212                     PixelFormat_WineD3DtoDD(&desc2.u4.ddpfPixelFormat, WINED3DFMT_D32_UNORM);
3213                     break;
3214                 default:
3215                     ERR("Unknown Z buffer bit depth\n");
3216             }
3217         }
3218         else
3219         {
3220             PixelFormat_WineD3DtoDD(&desc2.u4.ddpfPixelFormat, Mode.Format);
3221         }
3222     }
3223
3224     /* No Width or no Height? Use the original screen size
3225      */
3226     if(!(desc2.dwFlags & DDSD_WIDTH) ||
3227        !(desc2.dwFlags & DDSD_HEIGHT) )
3228     {
3229         /* Invalid for non-render targets */
3230         if(!(desc2.ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE))
3231         {
3232             WARN("Creating a non-Primary surface without Width or Height info, returning DDERR_INVALIDPARAMS\n");
3233             *Surf = NULL;
3234             LeaveCriticalSection(&ddraw_cs);
3235             return DDERR_INVALIDPARAMS;
3236         }
3237
3238         desc2.dwFlags |= DDSD_WIDTH | DDSD_HEIGHT;
3239         desc2.dwWidth = Mode.Width;
3240         desc2.dwHeight = Mode.Height;
3241     }
3242
3243     /* Mipmap count fixes */
3244     if(desc2.ddsCaps.dwCaps & DDSCAPS_MIPMAP)
3245     {
3246         if(desc2.ddsCaps.dwCaps & DDSCAPS_COMPLEX)
3247         {
3248             if(desc2.dwFlags & DDSD_MIPMAPCOUNT)
3249             {
3250                 /* Mipmap count is given, should not be 0 */
3251                 if( desc2.u2.dwMipMapCount == 0 )
3252                 {
3253                     LeaveCriticalSection(&ddraw_cs);
3254                     return DDERR_INVALIDPARAMS;
3255                 }
3256             }
3257             else
3258             {
3259                 /* Undocumented feature: Create sublevels until
3260                  * either the width or the height is 1
3261                  */
3262                 DWORD min = desc2.dwWidth < desc2.dwHeight ?
3263                             desc2.dwWidth : desc2.dwHeight;
3264                 desc2.u2.dwMipMapCount = 0;
3265                 while( min )
3266                 {
3267                     desc2.u2.dwMipMapCount += 1;
3268                     min >>= 1;
3269                 }
3270             }
3271         }
3272         else
3273         {
3274             /* Not-complex mipmap -> Mipmapcount = 1 */
3275             desc2.u2.dwMipMapCount = 1;
3276         }
3277         extra_surfaces = desc2.u2.dwMipMapCount - 1;
3278
3279         /* There's a mipmap count in the created surface in any case */
3280         desc2.dwFlags |= DDSD_MIPMAPCOUNT;
3281     }
3282     /* If no mipmap is given, the texture has only one level */
3283
3284     /* The first surface is a front buffer, the back buffer is created afterwards */
3285     if( (desc2.dwFlags & DDSD_CAPS) && (desc2.ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE) )
3286     {
3287         desc2.ddsCaps.dwCaps |= DDSCAPS_FRONTBUFFER;
3288     }
3289
3290     /* The root surface in a cube map is positive x */
3291     if(desc2.ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP)
3292     {
3293         desc2.ddsCaps.dwCaps2 &= ~DDSCAPS2_CUBEMAP_ALLFACES;
3294         desc2.ddsCaps.dwCaps2 |=  DDSCAPS2_CUBEMAP_POSITIVEX;
3295     }
3296
3297     /* Create the first surface */
3298     hr = ddraw_create_surface(This, &desc2, &object, 0);
3299     if( hr != DD_OK)
3300     {
3301         ERR("ddraw_create_surface failed, hr %#x.\n", hr);
3302         LeaveCriticalSection(&ddraw_cs);
3303         return hr;
3304     }
3305     object->is_complex_root = TRUE;
3306
3307     *Surf = (IDirectDrawSurface7 *)object;
3308
3309     /* Create Additional surfaces if necessary
3310      * This applies to Primary surfaces which have a back buffer count
3311      * set, but not to mipmap textures. In case of Mipmap textures,
3312      * wineD3D takes care of the creation of additional surfaces
3313      */
3314     if(DDSD->dwFlags & DDSD_BACKBUFFERCOUNT)
3315     {
3316         extra_surfaces = DDSD->dwBackBufferCount;
3317         desc2.ddsCaps.dwCaps &= ~DDSCAPS_FRONTBUFFER; /* It's not a front buffer */
3318         desc2.ddsCaps.dwCaps |= DDSCAPS_BACKBUFFER;
3319         desc2.dwBackBufferCount = 0;
3320     }
3321
3322     hr = DD_OK;
3323     if(desc2.ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP)
3324     {
3325         desc2.ddsCaps.dwCaps2 &= ~DDSCAPS2_CUBEMAP_ALLFACES;
3326         desc2.ddsCaps.dwCaps2 |=  DDSCAPS2_CUBEMAP_NEGATIVEZ;
3327         hr |= CreateAdditionalSurfaces(This, object, extra_surfaces + 1, desc2, TRUE);
3328         desc2.ddsCaps.dwCaps2 &= ~DDSCAPS2_CUBEMAP_NEGATIVEZ;
3329         desc2.ddsCaps.dwCaps2 |=  DDSCAPS2_CUBEMAP_POSITIVEZ;
3330         hr |= CreateAdditionalSurfaces(This, object, extra_surfaces + 1, desc2, TRUE);
3331         desc2.ddsCaps.dwCaps2 &= ~DDSCAPS2_CUBEMAP_POSITIVEZ;
3332         desc2.ddsCaps.dwCaps2 |=  DDSCAPS2_CUBEMAP_NEGATIVEY;
3333         hr |= CreateAdditionalSurfaces(This, object, extra_surfaces + 1, desc2, TRUE);
3334         desc2.ddsCaps.dwCaps2 &= ~DDSCAPS2_CUBEMAP_NEGATIVEY;
3335         desc2.ddsCaps.dwCaps2 |=  DDSCAPS2_CUBEMAP_POSITIVEY;
3336         hr |= CreateAdditionalSurfaces(This, object, extra_surfaces + 1, desc2, TRUE);
3337         desc2.ddsCaps.dwCaps2 &= ~DDSCAPS2_CUBEMAP_POSITIVEY;
3338         desc2.ddsCaps.dwCaps2 |=  DDSCAPS2_CUBEMAP_NEGATIVEX;
3339         hr |= CreateAdditionalSurfaces(This, object, extra_surfaces + 1, desc2, TRUE);
3340         desc2.ddsCaps.dwCaps2 &= ~DDSCAPS2_CUBEMAP_NEGATIVEX;
3341         desc2.ddsCaps.dwCaps2 |=  DDSCAPS2_CUBEMAP_POSITIVEX;
3342     }
3343
3344     hr |= CreateAdditionalSurfaces(This, object, extra_surfaces, desc2, FALSE);
3345     if(hr != DD_OK)
3346     {
3347         /* This destroys and possibly created surfaces too */
3348         IDirectDrawSurface_Release((IDirectDrawSurface7 *)object);
3349         LeaveCriticalSection(&ddraw_cs);
3350         return hr;
3351     }
3352
3353     /* If the implementation is OpenGL and there's no d3ddevice, attach a d3ddevice
3354      * But attach the d3ddevice only if the currently created surface was
3355      * a primary surface (2D app in 3D mode) or a 3DDEVICE surface (3D app)
3356      * The only case I can think of where this doesn't apply is when a
3357      * 2D app was configured by the user to run with OpenGL and it didn't create
3358      * the render target as first surface. In this case the render target creation
3359      * will cause the 3D init.
3360      */
3361     if( (This->ImplType == SURFACE_OPENGL) && !(This->d3d_initialized) &&
3362         desc2.ddsCaps.dwCaps & (DDSCAPS_PRIMARYSURFACE | DDSCAPS_3DDEVICE) )
3363     {
3364         IDirectDrawSurfaceImpl *target = object, *surface;
3365         struct list *entry;
3366
3367         /* Search for the primary to use as render target */
3368         LIST_FOR_EACH(entry, &This->surface_list)
3369         {
3370             surface = LIST_ENTRY(entry, IDirectDrawSurfaceImpl, surface_list_entry);
3371             if((surface->surface_desc.ddsCaps.dwCaps & (DDSCAPS_PRIMARYSURFACE | DDSCAPS_FRONTBUFFER)) ==
3372                (DDSCAPS_PRIMARYSURFACE | DDSCAPS_FRONTBUFFER))
3373             {
3374                 /* found */
3375                 target = surface;
3376                 TRACE("Using primary %p as render target\n", target);
3377                 break;
3378             }
3379         }
3380
3381         TRACE("(%p) Attaching a D3DDevice, rendertarget = %p\n", This, target);
3382         hr = ddraw_attach_d3d_device(This, target);
3383         if (hr != D3D_OK)
3384         {
3385             IDirectDrawSurfaceImpl *release_surf;
3386             ERR("ddraw_attach_d3d_device failed, hr %#x\n", hr);
3387             *Surf = NULL;
3388
3389             /* The before created surface structures are in an incomplete state here.
3390              * WineD3D holds the reference on the IParents, and it released them on the failure
3391              * already. So the regular release method implementation would fail on the attempt
3392              * to destroy either the IParents or the swapchain. So free the surface here.
3393              * The surface structure here is a list, not a tree, because onscreen targets
3394              * cannot be cube textures
3395              */
3396             while(object)
3397             {
3398                 release_surf = object;
3399                 object = object->complex_array[0];
3400                 ddraw_surface_destroy(release_surf);
3401             }
3402             LeaveCriticalSection(&ddraw_cs);
3403             return hr;
3404         }
3405     }
3406     else if(!(This->d3d_initialized) && desc2.ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE)
3407     {
3408         ddraw_create_gdi_swapchain(This, object);
3409     }
3410
3411     /* Addref the ddraw interface to keep an reference for each surface */
3412     IDirectDraw7_AddRef(iface);
3413     object->ifaceToRelease = (IUnknown *) iface;
3414
3415     /* Create a WineD3DTexture if a texture was requested */
3416     if(desc2.ddsCaps.dwCaps & DDSCAPS_TEXTURE)
3417     {
3418         UINT levels;
3419         WINED3DFORMAT Format;
3420         WINED3DPOOL Pool = WINED3DPOOL_DEFAULT;
3421
3422         This->tex_root = object;
3423
3424         if(desc2.ddsCaps.dwCaps & DDSCAPS_MIPMAP)
3425         {
3426             /* a mipmap is created, create enough levels */
3427             levels = desc2.u2.dwMipMapCount;
3428         }
3429         else
3430         {
3431             /* No mipmap is created, create one level */
3432             levels = 1;
3433         }
3434
3435         /* DDSCAPS_SYSTEMMEMORY textures are in WINED3DPOOL_SYSTEMMEM */
3436         if(DDSD->ddsCaps.dwCaps & DDSCAPS_SYSTEMMEMORY)
3437         {
3438             Pool = WINED3DPOOL_SYSTEMMEM;
3439         }
3440         /* Should I forward the MANAGED cap to the managed pool ? */
3441
3442         /* Get the format. It's set already by CreateNewSurface */
3443         Format = PixelFormat_DD2WineD3D(&object->surface_desc.u4.ddpfPixelFormat);
3444
3445         /* The surfaces are already created, the callback only
3446          * passes the IWineD3DSurface to WineD3D
3447          */
3448         if(desc2.ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP)
3449         {
3450             hr = IWineD3DDevice_CreateCubeTexture(This->wineD3DDevice, DDSD->dwWidth /* Edgelength */,
3451                     levels, 0 /* usage */, Format, Pool, (IWineD3DCubeTexture **)&object->wineD3DTexture,
3452                     (IUnknown *)object, &ddraw_null_wined3d_parent_ops);
3453         }
3454         else
3455         {
3456             hr = IWineD3DDevice_CreateTexture(This->wineD3DDevice, DDSD->dwWidth, DDSD->dwHeight, levels,
3457                     0 /* usage */, Format, Pool, (IWineD3DTexture **)&object->wineD3DTexture,
3458                     (IUnknown *)object, &ddraw_null_wined3d_parent_ops);
3459         }
3460         This->tex_root = NULL;
3461     }
3462
3463     LeaveCriticalSection(&ddraw_cs);
3464     return hr;
3465 }
3466
3467 static HRESULT WINAPI ddraw4_CreateSurface(IDirectDraw4 *iface,
3468         DDSURFACEDESC2 *surface_desc, IDirectDrawSurface4 **surface, IUnknown *outer_unknown)
3469 {
3470     IDirectDrawImpl *ddraw = ddraw_from_ddraw4(iface);
3471     IDirectDrawSurfaceImpl *impl;
3472     HRESULT hr;
3473
3474     TRACE("iface %p, surface_desc %p, surface %p, outer_unknown %p.\n",
3475             iface, surface_desc, surface, outer_unknown);
3476
3477     hr = ddraw7_CreateSurface((IDirectDraw7 *)ddraw, surface_desc, (IDirectDrawSurface7 **)surface, outer_unknown);
3478     impl = (IDirectDrawSurfaceImpl *)*surface;
3479     if (SUCCEEDED(hr) && impl)
3480     {
3481         ddraw_set_surface_version(impl, 4);
3482         IDirectDraw7_Release((IDirectDraw7 *)ddraw);
3483         IDirectDraw4_AddRef(iface);
3484         impl->ifaceToRelease = (IUnknown *)iface;
3485     }
3486
3487     return hr;
3488 }
3489
3490 static HRESULT WINAPI ddraw3_CreateSurface(IDirectDraw3 *iface,
3491         DDSURFACEDESC *surface_desc, IDirectDrawSurface **surface, IUnknown *outer_unknown)
3492 {
3493     IDirectDrawImpl *ddraw = ddraw_from_ddraw3(iface);
3494     IDirectDrawSurface7 *surface7;
3495     IDirectDrawSurfaceImpl *impl;
3496     HRESULT hr;
3497
3498     TRACE("iface %p, surface_desc %p, surface %p, outer_unknown %p.\n",
3499             iface, surface_desc, surface, outer_unknown);
3500
3501     hr = ddraw7_CreateSurface((IDirectDraw7 *)ddraw, (DDSURFACEDESC2 *)surface_desc, &surface7, outer_unknown);
3502     if (FAILED(hr))
3503     {
3504         *surface = NULL;
3505         return hr;
3506     }
3507
3508     impl = (IDirectDrawSurfaceImpl *)surface7;
3509     *surface = (IDirectDrawSurface *)&impl->IDirectDrawSurface3_vtbl;
3510     ddraw_set_surface_version(impl, 3);
3511     IDirectDraw7_Release((IDirectDraw7 *)ddraw);
3512     IDirectDraw3_AddRef(iface);
3513     impl->ifaceToRelease = (IUnknown *)iface;
3514
3515     return hr;
3516 }
3517
3518 static HRESULT WINAPI ddraw2_CreateSurface(IDirectDraw2 *iface,
3519         DDSURFACEDESC *surface_desc, IDirectDrawSurface **surface, IUnknown *outer_unknown)
3520 {
3521     IDirectDrawImpl *ddraw = ddraw_from_ddraw2(iface);
3522     IDirectDrawSurface7 *surface7;
3523     IDirectDrawSurfaceImpl *impl;
3524     HRESULT hr;
3525
3526     TRACE("iface %p, surface_desc %p, surface %p, outer_unknown %p.\n",
3527             iface, surface_desc, surface, outer_unknown);
3528
3529     hr = ddraw7_CreateSurface((IDirectDraw7 *)ddraw, (DDSURFACEDESC2 *)surface_desc, &surface7, outer_unknown);
3530     if (FAILED(hr))
3531     {
3532         *surface = NULL;
3533         return hr;
3534     }
3535
3536     impl = (IDirectDrawSurfaceImpl *)surface7;
3537     *surface = (IDirectDrawSurface *)&impl->IDirectDrawSurface3_vtbl;
3538     ddraw_set_surface_version(impl, 2);
3539     IDirectDraw7_Release((IDirectDraw7 *)ddraw);
3540     impl->ifaceToRelease = NULL;
3541
3542     return hr;
3543 }
3544
3545 static HRESULT WINAPI ddraw1_CreateSurface(IDirectDraw *iface,
3546         DDSURFACEDESC *surface_desc, IDirectDrawSurface **surface, IUnknown *outer_unknown)
3547 {
3548     IDirectDrawImpl *ddraw = ddraw_from_ddraw1(iface);
3549     IDirectDrawSurface7 *surface7;
3550     IDirectDrawSurfaceImpl *impl;
3551     HRESULT hr;
3552
3553     TRACE("iface %p, surface_desc %p, surface %p, outer_unknown %p.\n",
3554             iface, surface_desc, surface, outer_unknown);
3555
3556     /* Remove front buffer flag, this causes failure in v7, and its added to normal
3557      * primaries anyway. */
3558     surface_desc->ddsCaps.dwCaps &= ~DDSCAPS_FRONTBUFFER;
3559     hr = ddraw7_CreateSurface((IDirectDraw7 *)ddraw, (DDSURFACEDESC2 *)surface_desc, &surface7, outer_unknown);
3560     if (FAILED(hr))
3561     {
3562         *surface = NULL;
3563         return hr;
3564     }
3565
3566     impl = (IDirectDrawSurfaceImpl *)surface7;
3567     *surface = (IDirectDrawSurface *)&impl->IDirectDrawSurface3_vtbl;
3568     ddraw_set_surface_version(impl, 1);
3569     IDirectDraw7_Release((IDirectDraw7 *)ddraw);
3570     impl->ifaceToRelease = NULL;
3571
3572     return hr;
3573 }
3574
3575 #define DDENUMSURFACES_SEARCHTYPE (DDENUMSURFACES_CANBECREATED|DDENUMSURFACES_DOESEXIST)
3576 #define DDENUMSURFACES_MATCHTYPE (DDENUMSURFACES_ALL|DDENUMSURFACES_MATCH|DDENUMSURFACES_NOMATCH)
3577
3578 static BOOL
3579 Main_DirectDraw_DDPIXELFORMAT_Match(const DDPIXELFORMAT *requested,
3580                                     const DDPIXELFORMAT *provided)
3581 {
3582     /* Some flags must be present in both or neither for a match. */
3583     static const DWORD must_match = DDPF_PALETTEINDEXED1 | DDPF_PALETTEINDEXED2
3584         | DDPF_PALETTEINDEXED4 | DDPF_PALETTEINDEXED8 | DDPF_FOURCC
3585         | DDPF_ZBUFFER | DDPF_STENCILBUFFER;
3586
3587     if ((requested->dwFlags & provided->dwFlags) != requested->dwFlags)
3588         return FALSE;
3589
3590     if ((requested->dwFlags & must_match) != (provided->dwFlags & must_match))
3591         return FALSE;
3592
3593     if (requested->dwFlags & DDPF_FOURCC)
3594         if (requested->dwFourCC != provided->dwFourCC)
3595             return FALSE;
3596
3597     if (requested->dwFlags & (DDPF_RGB|DDPF_YUV|DDPF_ZBUFFER|DDPF_ALPHA
3598                               |DDPF_LUMINANCE|DDPF_BUMPDUDV))
3599         if (requested->u1.dwRGBBitCount != provided->u1.dwRGBBitCount)
3600             return FALSE;
3601
3602     if (requested->dwFlags & (DDPF_RGB|DDPF_YUV|DDPF_STENCILBUFFER
3603                               |DDPF_LUMINANCE|DDPF_BUMPDUDV))
3604         if (requested->u2.dwRBitMask != provided->u2.dwRBitMask)
3605             return FALSE;
3606
3607     if (requested->dwFlags & (DDPF_RGB|DDPF_YUV|DDPF_ZBUFFER|DDPF_BUMPDUDV))
3608         if (requested->u3.dwGBitMask != provided->u3.dwGBitMask)
3609             return FALSE;
3610
3611     /* I could be wrong about the bumpmapping. MSDN docs are vague. */
3612     if (requested->dwFlags & (DDPF_RGB|DDPF_YUV|DDPF_STENCILBUFFER
3613                               |DDPF_BUMPDUDV))
3614         if (requested->u4.dwBBitMask != provided->u4.dwBBitMask)
3615             return FALSE;
3616
3617     if (requested->dwFlags & (DDPF_ALPHAPIXELS|DDPF_ZPIXELS))
3618         if (requested->u5.dwRGBAlphaBitMask != provided->u5.dwRGBAlphaBitMask)
3619             return FALSE;
3620
3621     return TRUE;
3622 }
3623
3624 static BOOL ddraw_match_surface_desc(const DDSURFACEDESC2 *requested, const DDSURFACEDESC2 *provided)
3625 {
3626     struct compare_info
3627     {
3628         DWORD flag;
3629         ptrdiff_t offset;
3630         size_t size;
3631     };
3632
3633 #define CMP(FLAG, FIELD)                                \
3634         { DDSD_##FLAG, offsetof(DDSURFACEDESC2, FIELD), \
3635           sizeof(((DDSURFACEDESC2 *)(NULL))->FIELD) }
3636
3637     static const struct compare_info compare[] =
3638     {
3639         CMP(ALPHABITDEPTH, dwAlphaBitDepth),
3640         CMP(BACKBUFFERCOUNT, dwBackBufferCount),
3641         CMP(CAPS, ddsCaps),
3642         CMP(CKDESTBLT, ddckCKDestBlt),
3643         CMP(CKDESTOVERLAY, u3 /* ddckCKDestOverlay */),
3644         CMP(CKSRCBLT, ddckCKSrcBlt),
3645         CMP(CKSRCOVERLAY, ddckCKSrcOverlay),
3646         CMP(HEIGHT, dwHeight),
3647         CMP(LINEARSIZE, u1 /* dwLinearSize */),
3648         CMP(LPSURFACE, lpSurface),
3649         CMP(MIPMAPCOUNT, u2 /* dwMipMapCount */),
3650         CMP(PITCH, u1 /* lPitch */),
3651         /* PIXELFORMAT: manual */
3652         CMP(REFRESHRATE, u2 /* dwRefreshRate */),
3653         CMP(TEXTURESTAGE, dwTextureStage),
3654         CMP(WIDTH, dwWidth),
3655         /* ZBUFFERBITDEPTH: "obsolete" */
3656     };
3657
3658 #undef CMP
3659
3660     unsigned int i;
3661
3662     if ((requested->dwFlags & provided->dwFlags) != requested->dwFlags)
3663         return FALSE;
3664
3665     for (i=0; i < sizeof(compare)/sizeof(compare[0]); i++)
3666     {
3667         if (requested->dwFlags & compare[i].flag
3668             && memcmp((const char *)provided + compare[i].offset,
3669                       (const char *)requested + compare[i].offset,
3670                       compare[i].size) != 0)
3671             return FALSE;
3672     }
3673
3674     if (requested->dwFlags & DDSD_PIXELFORMAT)
3675     {
3676         if (!Main_DirectDraw_DDPIXELFORMAT_Match(&requested->u4.ddpfPixelFormat,
3677                                                 &provided->u4.ddpfPixelFormat))
3678             return FALSE;
3679     }
3680
3681     return TRUE;
3682 }
3683
3684 #undef DDENUMSURFACES_SEARCHTYPE
3685 #undef DDENUMSURFACES_MATCHTYPE
3686
3687 struct surfacescallback_context
3688 {
3689     LPDDENUMSURFACESCALLBACK func;
3690     void *context;
3691 };
3692
3693 static HRESULT CALLBACK EnumSurfacesCallbackThunk(IDirectDrawSurface7 *surface,
3694         DDSURFACEDESC2 *surface_desc, void *context)
3695 {
3696     struct surfacescallback_context *cbcontext = context;
3697
3698     return cbcontext->func((IDirectDrawSurface *)&((IDirectDrawSurfaceImpl *)surface)->IDirectDrawSurface3_vtbl,
3699             (DDSURFACEDESC *)surface_desc, cbcontext->context);
3700 }
3701
3702 /*****************************************************************************
3703  * IDirectDraw7::EnumSurfaces
3704  *
3705  * Loops through all surfaces attached to this device and calls the
3706  * application callback. This can't be relayed to WineD3DDevice,
3707  * because some WineD3DSurfaces' parents are IParent objects
3708  *
3709  * Params:
3710  *  Flags: Some filtering flags. See IDirectDrawImpl_EnumSurfacesCallback
3711  *  DDSD: Description to filter for
3712  *  Context: Application-provided pointer, it's passed unmodified to the
3713  *           Callback function
3714  *  Callback: Address to call for each surface
3715  *
3716  * Returns:
3717  *  DDERR_INVALIDPARAMS if the callback is NULL
3718  *  DD_OK on success
3719  *
3720  *****************************************************************************/
3721 static HRESULT WINAPI ddraw7_EnumSurfaces(IDirectDraw7 *iface, DWORD Flags,
3722         DDSURFACEDESC2 *DDSD, void *Context, LPDDENUMSURFACESCALLBACK7 Callback)
3723 {
3724     /* The surface enumeration is handled by WineDDraw,
3725      * because it keeps track of all surfaces attached to
3726      * it. The filtering is done by our callback function,
3727      * because WineDDraw doesn't handle ddraw-like surface
3728      * caps structures
3729      */
3730     IDirectDrawImpl *This = (IDirectDrawImpl *)iface;
3731     IDirectDrawSurfaceImpl *surf;
3732     BOOL all, nomatch;
3733     DDSURFACEDESC2 desc;
3734     struct list *entry, *entry2;
3735
3736     all = Flags & DDENUMSURFACES_ALL;
3737     nomatch = Flags & DDENUMSURFACES_NOMATCH;
3738
3739     TRACE("(%p)->(%x,%p,%p,%p)\n", This, Flags, DDSD, Context, Callback);
3740     EnterCriticalSection(&ddraw_cs);
3741
3742     if(!Callback)
3743     {
3744         LeaveCriticalSection(&ddraw_cs);
3745         return DDERR_INVALIDPARAMS;
3746     }
3747
3748     /* Use the _SAFE enumeration, the app may destroy enumerated surfaces */
3749     LIST_FOR_EACH_SAFE(entry, entry2, &This->surface_list)
3750     {
3751         surf = LIST_ENTRY(entry, IDirectDrawSurfaceImpl, surface_list_entry);
3752         if (all || (nomatch != ddraw_match_surface_desc(DDSD, &surf->surface_desc)))
3753         {
3754             desc = surf->surface_desc;
3755             IDirectDrawSurface7_AddRef((IDirectDrawSurface7 *)surf);
3756             if (Callback((IDirectDrawSurface7 *)surf, &desc, Context) != DDENUMRET_OK)
3757             {
3758                 LeaveCriticalSection(&ddraw_cs);
3759                 return DD_OK;
3760             }
3761         }
3762     }
3763     LeaveCriticalSection(&ddraw_cs);
3764     return DD_OK;
3765 }
3766
3767 static HRESULT WINAPI ddraw4_EnumSurfaces(IDirectDraw4 *iface, DWORD flags,
3768         DDSURFACEDESC2 *surface_desc, void *context, LPDDENUMSURFACESCALLBACK2 callback)
3769 {
3770     TRACE("iface %p, flags %#x, surface_desc %p, context %p, callback %p.\n",
3771             iface, flags, surface_desc, context, callback);
3772
3773     return ddraw7_EnumSurfaces((IDirectDraw7 *)ddraw_from_ddraw4(iface),
3774             flags, surface_desc, context, (LPDDENUMSURFACESCALLBACK7)callback);
3775 }
3776
3777 static HRESULT WINAPI ddraw3_EnumSurfaces(IDirectDraw3 *iface, DWORD flags,
3778         DDSURFACEDESC *surface_desc, void *context, LPDDENUMSURFACESCALLBACK callback)
3779 {
3780     struct surfacescallback_context cbcontext;
3781
3782     TRACE("iface %p, flags %#x, surface_desc %p, context %p, callback %p.\n",
3783             iface, flags, surface_desc, context, callback);
3784
3785     cbcontext.func = callback;
3786     cbcontext.context = context;
3787
3788     return ddraw7_EnumSurfaces((IDirectDraw7 *)ddraw_from_ddraw3(iface), flags,
3789             (DDSURFACEDESC2 *)surface_desc, &cbcontext, EnumSurfacesCallbackThunk);
3790 }
3791
3792 static HRESULT WINAPI ddraw2_EnumSurfaces(IDirectDraw2 *iface, DWORD flags,
3793         DDSURFACEDESC *surface_desc, void *context, LPDDENUMSURFACESCALLBACK callback)
3794 {
3795     struct surfacescallback_context cbcontext;
3796
3797     TRACE("iface %p, flags %#x, surface_desc %p, context %p, callback %p.\n",
3798             iface, flags, surface_desc, context, callback);
3799
3800     cbcontext.func = callback;
3801     cbcontext.context = context;
3802
3803     return ddraw7_EnumSurfaces((IDirectDraw7 *)ddraw_from_ddraw2(iface), flags,
3804             (DDSURFACEDESC2 *)surface_desc, &cbcontext, EnumSurfacesCallbackThunk);
3805 }
3806
3807 static HRESULT WINAPI ddraw1_EnumSurfaces(IDirectDraw *iface, DWORD flags,
3808         DDSURFACEDESC *surface_desc, void *context, LPDDENUMSURFACESCALLBACK callback)
3809 {
3810     struct surfacescallback_context cbcontext;
3811
3812     TRACE("iface %p, flags %#x, surface_desc %p, context %p, callback %p.\n",
3813             iface, flags, surface_desc, context, callback);
3814
3815     cbcontext.func = callback;
3816     cbcontext.context = context;
3817
3818     return ddraw7_EnumSurfaces((IDirectDraw7 *)ddraw_from_ddraw1(iface), flags,
3819             (DDSURFACEDESC2 *)surface_desc, &cbcontext, EnumSurfacesCallbackThunk);
3820 }
3821
3822 /*****************************************************************************
3823  * DirectDrawCreateClipper (DDRAW.@)
3824  *
3825  * Creates a new IDirectDrawClipper object.
3826  *
3827  * Params:
3828  *  Clipper: Address to write the interface pointer to
3829  *  UnkOuter: For aggregation support, which ddraw doesn't have. Has to be
3830  *            NULL
3831  *
3832  * Returns:
3833  *  CLASS_E_NOAGGREGATION if UnkOuter != NULL
3834  *  E_OUTOFMEMORY if allocating the object failed
3835  *
3836  *****************************************************************************/
3837 HRESULT WINAPI
3838 DirectDrawCreateClipper(DWORD Flags,
3839                         LPDIRECTDRAWCLIPPER *Clipper,
3840                         IUnknown *UnkOuter)
3841 {
3842     IDirectDrawClipperImpl* object;
3843     HRESULT hr;
3844
3845     TRACE("(%08x,%p,%p)\n", Flags, Clipper, UnkOuter);
3846
3847     EnterCriticalSection(&ddraw_cs);
3848     if (UnkOuter != NULL)
3849     {
3850         LeaveCriticalSection(&ddraw_cs);
3851         return CLASS_E_NOAGGREGATION;
3852     }
3853
3854     if (!LoadWineD3D())
3855     {
3856         LeaveCriticalSection(&ddraw_cs);
3857         return DDERR_NODIRECTDRAWSUPPORT;
3858     }
3859
3860     object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
3861                      sizeof(IDirectDrawClipperImpl));
3862     if (object == NULL)
3863     {
3864         LeaveCriticalSection(&ddraw_cs);
3865         return E_OUTOFMEMORY;
3866     }
3867
3868     hr = ddraw_clipper_init(object);
3869     if (FAILED(hr))
3870     {
3871         WARN("Failed to initialize clipper, hr %#x.\n", hr);
3872         HeapFree(GetProcessHeap(), 0, object);
3873         LeaveCriticalSection(&ddraw_cs);
3874         return hr;
3875     }
3876
3877     TRACE("Created clipper %p.\n", object);
3878     *Clipper = (IDirectDrawClipper *) object;
3879     LeaveCriticalSection(&ddraw_cs);
3880     return DD_OK;
3881 }
3882
3883 /*****************************************************************************
3884  * IDirectDraw7::CreateClipper
3885  *
3886  * Creates a DDraw clipper. See DirectDrawCreateClipper for details
3887  *
3888  *****************************************************************************/
3889 static HRESULT WINAPI ddraw7_CreateClipper(IDirectDraw7 *iface, DWORD Flags,
3890         IDirectDrawClipper **Clipper, IUnknown *UnkOuter)
3891 {
3892     IDirectDrawImpl *This = (IDirectDrawImpl *)iface;
3893     TRACE("(%p)->(%x,%p,%p)\n", This, Flags, Clipper, UnkOuter);
3894     return DirectDrawCreateClipper(Flags, Clipper, UnkOuter);
3895 }
3896
3897 static HRESULT WINAPI ddraw4_CreateClipper(IDirectDraw4 *iface,
3898         DWORD flags, IDirectDrawClipper **clipper, IUnknown *outer_unknown)
3899 {
3900     TRACE("iface %p, flags %#x, clipper %p, outer_unknown %p.\n",
3901             iface, flags, clipper, outer_unknown);
3902
3903     return ddraw7_CreateClipper((IDirectDraw7 *)ddraw_from_ddraw4(iface), flags, clipper, outer_unknown);
3904 }
3905
3906 static HRESULT WINAPI ddraw3_CreateClipper(IDirectDraw3 *iface,
3907         DWORD flags, IDirectDrawClipper **clipper, IUnknown *outer_unknown)
3908 {
3909     TRACE("iface %p, flags %#x, clipper %p, outer_unknown %p.\n",
3910             iface, flags, clipper, outer_unknown);
3911
3912     return ddraw7_CreateClipper((IDirectDraw7 *)ddraw_from_ddraw3(iface), flags, clipper, outer_unknown);
3913 }
3914
3915 static HRESULT WINAPI ddraw2_CreateClipper(IDirectDraw2 *iface,
3916         DWORD flags, IDirectDrawClipper **clipper, IUnknown *outer_unknown)
3917 {
3918     TRACE("iface %p, flags %#x, clipper %p, outer_unknown %p.\n",
3919             iface, flags, clipper, outer_unknown);
3920
3921     return ddraw7_CreateClipper((IDirectDraw7 *)ddraw_from_ddraw2(iface), flags, clipper, outer_unknown);
3922 }
3923
3924 static HRESULT WINAPI ddraw1_CreateClipper(IDirectDraw *iface,
3925         DWORD flags, IDirectDrawClipper **clipper, IUnknown *outer_unknown)
3926 {
3927     TRACE("iface %p, flags %#x, clipper %p, outer_unknown %p.\n",
3928             iface, flags, clipper, outer_unknown);
3929
3930     return ddraw7_CreateClipper((IDirectDraw7 *)ddraw_from_ddraw1(iface), flags, clipper, outer_unknown);
3931 }
3932
3933 /*****************************************************************************
3934  * IDirectDraw7::CreatePalette
3935  *
3936  * Creates a new IDirectDrawPalette object
3937  *
3938  * Params:
3939  *  Flags: The flags for the new clipper
3940  *  ColorTable: Color table to assign to the new clipper
3941  *  Palette: Address to write the interface pointer to
3942  *  UnkOuter: For aggregation support, which ddraw doesn't have. Has to be
3943  *            NULL
3944  *
3945  * Returns:
3946  *  CLASS_E_NOAGGREGATION if UnkOuter != NULL
3947  *  E_OUTOFMEMORY if allocating the object failed
3948  *
3949  *****************************************************************************/
3950 static HRESULT WINAPI ddraw7_CreatePalette(IDirectDraw7 *iface, DWORD Flags,
3951         PALETTEENTRY *ColorTable, IDirectDrawPalette **Palette, IUnknown *pUnkOuter)
3952 {
3953     IDirectDrawImpl *This = (IDirectDrawImpl *)iface;
3954     IDirectDrawPaletteImpl *object;
3955     HRESULT hr;
3956
3957     TRACE("(%p)->(%x,%p,%p,%p)\n", This, Flags, ColorTable, Palette, pUnkOuter);
3958
3959     EnterCriticalSection(&ddraw_cs);
3960     if(pUnkOuter != NULL)
3961     {
3962         WARN("pUnkOuter is %p, returning CLASS_E_NOAGGREGATION\n", pUnkOuter);
3963         LeaveCriticalSection(&ddraw_cs);
3964         return CLASS_E_NOAGGREGATION;
3965     }
3966
3967     /* The refcount test shows that a cooplevel is required for this */
3968     if(!This->cooperative_level)
3969     {
3970         WARN("No cooperative level set, returning DDERR_NOCOOPERATIVELEVELSET\n");
3971         LeaveCriticalSection(&ddraw_cs);
3972         return DDERR_NOCOOPERATIVELEVELSET;
3973     }
3974
3975     object = HeapAlloc(GetProcessHeap(), 0, sizeof(IDirectDrawPaletteImpl));
3976     if(!object)
3977     {
3978         ERR("Out of memory when allocating memory for a palette implementation\n");
3979         LeaveCriticalSection(&ddraw_cs);
3980         return E_OUTOFMEMORY;
3981     }
3982
3983     hr = ddraw_palette_init(object, This, Flags, ColorTable);
3984     if (FAILED(hr))
3985     {
3986         WARN("Failed to initialize palette, hr %#x.\n", hr);
3987         HeapFree(GetProcessHeap(), 0, object);
3988         LeaveCriticalSection(&ddraw_cs);
3989         return hr;
3990     }
3991
3992     TRACE("Created palette %p.\n", object);
3993     *Palette = (IDirectDrawPalette *)object;
3994     LeaveCriticalSection(&ddraw_cs);
3995     return DD_OK;
3996 }
3997
3998 static HRESULT WINAPI ddraw4_CreatePalette(IDirectDraw4 *iface, DWORD flags,
3999         PALETTEENTRY *entries, IDirectDrawPalette **palette, IUnknown *outer_unknown)
4000 {
4001     IDirectDrawImpl *ddraw = ddraw_from_ddraw4(iface);
4002     HRESULT hr;
4003
4004     TRACE("iface %p, flags %#x, entries %p, palette %p, outer_unknown %p.\n",
4005             iface, flags, entries, palette, outer_unknown);
4006
4007     hr = ddraw7_CreatePalette((IDirectDraw7 *)ddraw, flags, entries, palette, outer_unknown);
4008     if (SUCCEEDED(hr) && *palette)
4009     {
4010         IDirectDrawPaletteImpl *impl = (IDirectDrawPaletteImpl *)*palette;
4011         IDirectDraw7_Release((IDirectDraw7 *)ddraw);
4012         IDirectDraw4_AddRef(iface);
4013         impl->ifaceToRelease = (IUnknown *)iface;
4014     }
4015     return hr;
4016 }
4017
4018 static HRESULT WINAPI ddraw3_CreatePalette(IDirectDraw3 *iface, DWORD flags,
4019         PALETTEENTRY *entries, IDirectDrawPalette **palette, IUnknown *outer_unknown)
4020 {
4021     IDirectDrawImpl *ddraw = ddraw_from_ddraw3(iface);
4022     HRESULT hr;
4023
4024     TRACE("iface %p, flags %#x, entries %p, palette %p, outer_unknown %p.\n",
4025             iface, flags, entries, palette, outer_unknown);
4026
4027     hr = ddraw7_CreatePalette((IDirectDraw7 *)ddraw, flags, entries, palette, outer_unknown);
4028     if (SUCCEEDED(hr) && *palette)
4029     {
4030         IDirectDrawPaletteImpl *impl = (IDirectDrawPaletteImpl *)*palette;
4031         IDirectDraw7_Release((IDirectDraw7 *)ddraw);
4032         IDirectDraw4_AddRef(iface);
4033         impl->ifaceToRelease = (IUnknown *)iface;
4034     }
4035
4036     return hr;
4037 }
4038
4039 static HRESULT WINAPI ddraw2_CreatePalette(IDirectDraw2 *iface, DWORD flags,
4040         PALETTEENTRY *entries, IDirectDrawPalette **palette, IUnknown *outer_unknown)
4041 {
4042     IDirectDrawImpl *ddraw = ddraw_from_ddraw2(iface);
4043     HRESULT hr;
4044
4045     TRACE("iface %p, flags %#x, entries %p, palette %p, outer_unknown %p.\n",
4046             iface, flags, entries, palette, outer_unknown);
4047
4048     hr = ddraw7_CreatePalette((IDirectDraw7 *)ddraw, flags, entries, palette, outer_unknown);
4049     if (SUCCEEDED(hr) && *palette)
4050     {
4051         IDirectDrawPaletteImpl *impl = (IDirectDrawPaletteImpl *)*palette;
4052         IDirectDraw7_Release((IDirectDraw7 *)ddraw);
4053         impl->ifaceToRelease = NULL;
4054     }
4055
4056     return hr;
4057 }
4058
4059 static HRESULT WINAPI ddraw1_CreatePalette(IDirectDraw *iface, DWORD flags,
4060         PALETTEENTRY *entries, IDirectDrawPalette **palette, IUnknown *outer_unknown)
4061 {
4062     IDirectDrawImpl *ddraw = ddraw_from_ddraw1(iface);
4063     HRESULT hr;
4064
4065     TRACE("iface %p, flags %#x, entries %p, palette %p, outer_unknown %p.\n",
4066             iface, flags, entries, palette, outer_unknown);
4067
4068     hr = ddraw7_CreatePalette((IDirectDraw7 *)ddraw, flags, entries, palette, outer_unknown);
4069     if (SUCCEEDED(hr) && *palette)
4070     {
4071         IDirectDrawPaletteImpl *impl = (IDirectDrawPaletteImpl *)*palette;
4072         IDirectDraw7_Release((IDirectDraw7 *)ddraw);
4073         impl->ifaceToRelease = NULL;
4074     }
4075
4076     return hr;
4077 }
4078
4079 /*****************************************************************************
4080  * IDirectDraw7::DuplicateSurface
4081  *
4082  * Duplicates a surface. The surface memory points to the same memory as
4083  * the original surface, and it's released when the last surface referencing
4084  * it is released. I guess that's beyond Wine's surface management right now
4085  * (Idea: create a new DDraw surface with the same WineD3DSurface. I need a
4086  * test application to implement this)
4087  *
4088  * Params:
4089  *  Src: Address of the source surface
4090  *  Dest: Address to write the new surface pointer to
4091  *
4092  * Returns:
4093  *  See IDirectDraw7::CreateSurface
4094  *
4095  *****************************************************************************/
4096 static HRESULT WINAPI ddraw7_DuplicateSurface(IDirectDraw7 *iface,
4097         IDirectDrawSurface7 *Src, IDirectDrawSurface7 **Dest)
4098 {
4099     IDirectDrawImpl *This = (IDirectDrawImpl *)iface;
4100     IDirectDrawSurfaceImpl *Surf = (IDirectDrawSurfaceImpl *)Src;
4101
4102     FIXME("(%p)->(%p,%p)\n", This, Surf, Dest);
4103
4104     /* For now, simply create a new, independent surface */
4105     return IDirectDraw7_CreateSurface(iface,
4106                                       &Surf->surface_desc,
4107                                       Dest,
4108                                       NULL);
4109 }
4110
4111 static HRESULT WINAPI ddraw4_DuplicateSurface(IDirectDraw4 *iface,
4112         IDirectDrawSurface4 *src, IDirectDrawSurface4 **dst)
4113 {
4114     TRACE("iface %p, src %p, dst %p.\n", iface, src, dst);
4115
4116     return ddraw7_DuplicateSurface((IDirectDraw7 *)ddraw_from_ddraw4(iface),
4117             (IDirectDrawSurface7 *)src, (IDirectDrawSurface7 **)dst);
4118 }
4119
4120 static HRESULT WINAPI ddraw3_DuplicateSurface(IDirectDraw3 *iface,
4121         IDirectDrawSurface *src, IDirectDrawSurface **dst)
4122 {
4123     IDirectDrawSurface7 *src7, *dst7;
4124     HRESULT hr;
4125
4126     TRACE("iface %p, src %p, dst %p.\n", iface, src, dst);
4127     src7 = (IDirectDrawSurface7 *)surface_from_surface3((IDirectDrawSurface3 *)src);
4128     hr = ddraw7_DuplicateSurface((IDirectDraw7 *)ddraw_from_ddraw3(iface), src7, &dst7);
4129     if (FAILED(hr))
4130         return hr;
4131     *dst = (IDirectDrawSurface *)&((IDirectDrawSurfaceImpl *)dst7)->IDirectDrawSurface3_vtbl;
4132     return hr;
4133 }
4134
4135 static HRESULT WINAPI ddraw2_DuplicateSurface(IDirectDraw2 *iface,
4136         IDirectDrawSurface *src, IDirectDrawSurface **dst)
4137 {
4138     IDirectDrawSurface7 *src7, *dst7;
4139     HRESULT hr;
4140
4141     TRACE("iface %p, src %p, dst %p.\n", iface, src, dst);
4142     src7 = (IDirectDrawSurface7 *)surface_from_surface3((IDirectDrawSurface3 *)src);
4143     hr = ddraw7_DuplicateSurface((IDirectDraw7 *)ddraw_from_ddraw2(iface), src7, &dst7);
4144     if (FAILED(hr))
4145         return hr;
4146     *dst = (IDirectDrawSurface *)&((IDirectDrawSurfaceImpl *)dst7)->IDirectDrawSurface3_vtbl;
4147     return hr;
4148 }
4149
4150 static HRESULT WINAPI ddraw1_DuplicateSurface(IDirectDraw *iface,
4151         IDirectDrawSurface *src, IDirectDrawSurface **dst)
4152 {
4153     IDirectDrawSurface7 *src7, *dst7;
4154     HRESULT hr;
4155
4156     TRACE("iface %p, src %p, dst %p.\n", iface, src, dst);
4157     src7 = (IDirectDrawSurface7 *)surface_from_surface3((IDirectDrawSurface3 *)src);
4158     hr = ddraw7_DuplicateSurface((IDirectDraw7 *)ddraw_from_ddraw1(iface), src7, &dst7);
4159     if (FAILED(hr))
4160         return hr;
4161     *dst = (IDirectDrawSurface *)&((IDirectDrawSurfaceImpl *)dst7)->IDirectDrawSurface3_vtbl;
4162     return hr;
4163 }
4164
4165 /*****************************************************************************
4166  * IDirect3D7::EnumDevices
4167  *
4168  * The EnumDevices method for IDirect3D7. It enumerates all supported
4169  * D3D7 devices. Currently the T&L, HAL and RGB devices are enumerated.
4170  *
4171  * Params:
4172  *  callback: Function to call for each enumerated device
4173  *  context: Pointer to pass back to the app
4174  *
4175  * Returns:
4176  *  D3D_OK, or the return value of the GetCaps call
4177  *
4178  *****************************************************************************/
4179 static HRESULT WINAPI d3d7_EnumDevices(IDirect3D7 *iface, LPD3DENUMDEVICESCALLBACK7 callback, void *context)
4180 {
4181     char interface_name_tnl[] = "WINE Direct3D7 Hardware Transform and Lighting acceleration using WineD3D";
4182     char device_name_tnl[] = "Wine D3D7 T&L HAL";
4183     char interface_name_hal[] = "WINE Direct3D7 Hardware acceleration using WineD3D";
4184     char device_name_hal[] = "Wine D3D7 HAL";
4185     char interface_name_rgb[] = "WINE Direct3D7 RGB Software Emulation using WineD3D";
4186     char device_name_rgb[] = "Wine D3D7 RGB";
4187
4188     IDirectDrawImpl *ddraw = ddraw_from_d3d7(iface);
4189     D3DDEVICEDESC7 device_desc7;
4190     D3DDEVICEDESC device_desc1;
4191     HRESULT hr;
4192
4193     TRACE("iface %p, callback %p, context %p.\n", iface, callback, context);
4194
4195     EnterCriticalSection(&ddraw_cs);
4196
4197     hr = IDirect3DImpl_GetCaps(ddraw->wineD3D, &device_desc1, &device_desc7);
4198     if (hr != D3D_OK)
4199     {
4200         LeaveCriticalSection(&ddraw_cs);
4201         return hr;
4202     }
4203     callback(interface_name_tnl, device_name_tnl, &device_desc7, context);
4204
4205     device_desc7.deviceGUID = IID_IDirect3DHALDevice;
4206     callback(interface_name_hal, device_name_hal, &device_desc7, context);
4207
4208     device_desc7.deviceGUID = IID_IDirect3DRGBDevice;
4209     callback(interface_name_rgb, device_name_rgb, &device_desc7, context);
4210
4211     TRACE("End of enumeration.\n");
4212
4213     LeaveCriticalSection(&ddraw_cs);
4214
4215     return D3D_OK;
4216 }
4217
4218 /*****************************************************************************
4219  * IDirect3D3::EnumDevices
4220  *
4221  * Enumerates all supported Direct3DDevice interfaces. This is the
4222  * implementation for Direct3D 1 to Direc3D 3, Version 7 has its own.
4223  *
4224  * Version 1, 2 and 3
4225  *
4226  * Params:
4227  *  callback: Application-provided routine to call for each enumerated device
4228  *  Context: Pointer to pass to the callback
4229  *
4230  * Returns:
4231  *  D3D_OK on success,
4232  *  The result of IDirect3DImpl_GetCaps if it failed
4233  *
4234  *****************************************************************************/
4235 static HRESULT WINAPI d3d3_EnumDevices(IDirect3D3 *iface, LPD3DENUMDEVICESCALLBACK callback, void *context)
4236 {
4237     static CHAR wined3d_description[] = "Wine D3DDevice using WineD3D and OpenGL";
4238
4239     IDirectDrawImpl *ddraw = ddraw_from_d3d3(iface);
4240     D3DDEVICEDESC device_desc1, hal_desc, hel_desc;
4241     D3DDEVICEDESC7 device_desc7;
4242     HRESULT hr;
4243
4244     /* Some games (Motoracer 2 demo) have the bad idea to modify the device
4245      * name string. Let's put the string in a sufficiently sized array in
4246      * writable memory. */
4247     char device_name[50];
4248     strcpy(device_name,"Direct3D HEL");
4249
4250     TRACE("iface %p, callback %p, context %p.\n", iface, callback, context);
4251
4252     EnterCriticalSection(&ddraw_cs);
4253
4254     hr = IDirect3DImpl_GetCaps(ddraw->wineD3D, &device_desc1, &device_desc7);
4255     if (hr != D3D_OK)
4256     {
4257         LeaveCriticalSection(&ddraw_cs);
4258         return hr;
4259     }
4260
4261     /* Do I have to enumerate the reference id? Note from old d3d7:
4262      * "It seems that enumerating the reference IID on Direct3D 1 games
4263      * (AvP / Motoracer2) breaks them". So do not enumerate this iid in V1
4264      *
4265      * There's a registry key HKLM\Software\Microsoft\Direct3D\Drivers,
4266      * EnumReference which enables / disables enumerating the reference
4267      * rasterizer. It's a DWORD, 0 means disabled, 2 means enabled. The
4268      * enablerefrast.reg and disablerefrast.reg files in the DirectX 7.0 sdk
4269      * demo directory suggest this.
4270      *
4271      * Some games(GTA 2) seem to use the second enumerated device, so I have
4272      * to enumerate at least 2 devices. So enumerate the reference device to
4273      * have 2 devices.
4274      *
4275      * Other games (Rollcage) tell emulation and hal device apart by certain
4276      * flags. Rollcage expects D3DPTEXTURECAPS_POW2 to be set (yeah, it is a
4277      * limitation flag), and it refuses all devices that have the perspective
4278      * flag set. This way it refuses the emulation device, and HAL devices
4279      * never have POW2 unset in d3d7 on windows. */
4280     if (ddraw->d3dversion != 1)
4281     {
4282         static CHAR reference_description[] = "RGB Direct3D emulation";
4283
4284         TRACE("Enumerating WineD3D D3DDevice interface.\n");
4285         hal_desc = device_desc1;
4286         hel_desc = device_desc1;
4287         /* The rgb device has the pow2 flag set in the hel caps, but not in the hal caps. */
4288         hal_desc.dpcLineCaps.dwTextureCaps &= ~(D3DPTEXTURECAPS_POW2
4289                 | D3DPTEXTURECAPS_NONPOW2CONDITIONAL | D3DPTEXTURECAPS_PERSPECTIVE);
4290         hal_desc.dpcTriCaps.dwTextureCaps &= ~(D3DPTEXTURECAPS_POW2
4291                 | D3DPTEXTURECAPS_NONPOW2CONDITIONAL | D3DPTEXTURECAPS_PERSPECTIVE);
4292         hr = callback((GUID *)&IID_IDirect3DRGBDevice, reference_description,
4293                 device_name, &hal_desc, &hel_desc, context);
4294         if (hr != D3DENUMRET_OK)
4295         {
4296             TRACE("Application cancelled the enumeration.\n");
4297             LeaveCriticalSection(&ddraw_cs);
4298             return D3D_OK;
4299         }
4300     }
4301
4302     strcpy(device_name,"Direct3D HAL");
4303
4304     TRACE("Enumerating HAL Direct3D device.\n");
4305     hal_desc = device_desc1;
4306     hel_desc = device_desc1;
4307     /* The hal device does not have the pow2 flag set in hel, but in hal. */
4308     hel_desc.dpcLineCaps.dwTextureCaps &= ~(D3DPTEXTURECAPS_POW2
4309             | D3DPTEXTURECAPS_NONPOW2CONDITIONAL | D3DPTEXTURECAPS_PERSPECTIVE);
4310     hel_desc.dpcTriCaps.dwTextureCaps &= ~(D3DPTEXTURECAPS_POW2
4311             | D3DPTEXTURECAPS_NONPOW2CONDITIONAL | D3DPTEXTURECAPS_PERSPECTIVE);
4312     hr = callback((GUID *)&IID_IDirect3DHALDevice, wined3d_description,
4313             device_name, &hal_desc, &hel_desc, context);
4314     if (hr != D3DENUMRET_OK)
4315     {
4316         TRACE("Application cancelled the enumeration.\n");
4317         LeaveCriticalSection(&ddraw_cs);
4318         return D3D_OK;
4319     }
4320
4321     TRACE("End of enumeration.\n");
4322
4323     LeaveCriticalSection(&ddraw_cs);
4324     return D3D_OK;
4325 }
4326
4327 static HRESULT WINAPI d3d2_EnumDevices(IDirect3D2 *iface, LPD3DENUMDEVICESCALLBACK callback, void *context)
4328 {
4329     TRACE("iface %p, callback %p, context %p.\n", iface, callback, context);
4330
4331     return d3d3_EnumDevices((IDirect3D3 *)&ddraw_from_d3d2(iface)->IDirect3D3_vtbl, callback, context);
4332 }
4333
4334 static HRESULT WINAPI d3d1_EnumDevices(IDirect3D *iface, LPD3DENUMDEVICESCALLBACK callback, void *context)
4335 {
4336     TRACE("iface %p, callback %p, context %p.\n", iface, callback, context);
4337
4338     return d3d3_EnumDevices((IDirect3D3 *)&ddraw_from_d3d1(iface)->IDirect3D3_vtbl, callback, context);
4339 }
4340
4341 /*****************************************************************************
4342  * IDirect3D3::CreateLight
4343  *
4344  * Creates an IDirect3DLight interface. This interface is used in
4345  * Direct3D3 or earlier for lighting. In Direct3D7 it has been replaced
4346  * by the DIRECT3DLIGHT7 structure. Wine's Direct3DLight implementation
4347  * uses the IDirect3DDevice7 interface with D3D7 lights.
4348  *
4349  * Version 1, 2 and 3
4350  *
4351  * Params:
4352  *  light: Address to store the new interface pointer
4353  *  outer_unknown: Basically for aggregation, but ddraw doesn't support it.
4354  *                 Must be NULL
4355  *
4356  * Returns:
4357  *  D3D_OK on success
4358  *  DDERR_OUTOFMEMORY if memory allocation failed
4359  *  CLASS_E_NOAGGREGATION if outer_unknown != NULL
4360  *
4361  *****************************************************************************/
4362 static HRESULT WINAPI d3d3_CreateLight(IDirect3D3 *iface, IDirect3DLight **light, IUnknown *outer_unknown)
4363 {
4364     IDirect3DLightImpl *object;
4365
4366     TRACE("iface %p, light %p, outer_unknown %p.\n", iface, light, outer_unknown);
4367
4368     if (outer_unknown) return CLASS_E_NOAGGREGATION;
4369
4370     object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*object));
4371     if (!object)
4372     {
4373         ERR("Failed to allocate light memory.\n");
4374         return DDERR_OUTOFMEMORY;
4375     }
4376
4377     d3d_light_init(object, ddraw_from_d3d3(iface));
4378
4379     TRACE("Created light %p.\n", object);
4380     *light = (IDirect3DLight *)object;
4381
4382     return D3D_OK;
4383 }
4384
4385 static HRESULT WINAPI d3d2_CreateLight(IDirect3D2 *iface, IDirect3DLight **light, IUnknown *outer_unknown)
4386 {
4387     TRACE("iface %p, light %p, outer_unknown %p.\n", iface, light, outer_unknown);
4388
4389     return d3d3_CreateLight((IDirect3D3 *)&ddraw_from_d3d2(iface)->IDirect3D3_vtbl, light, outer_unknown);
4390 }
4391
4392 static HRESULT WINAPI d3d1_CreateLight(IDirect3D *iface, IDirect3DLight **light, IUnknown *outer_unknown)
4393 {
4394     TRACE("iface %p, light %p, outer_unknown %p.\n", iface, light, outer_unknown);
4395
4396     return d3d3_CreateLight((IDirect3D3 *)&ddraw_from_d3d1(iface)->IDirect3D3_vtbl, light, outer_unknown);
4397 }
4398
4399 /*****************************************************************************
4400  * IDirect3D3::CreateMaterial
4401  *
4402  * Creates an IDirect3DMaterial interface. This interface is used by Direct3D3
4403  * and older versions. The IDirect3DMaterial implementation wraps its
4404  * functionality to IDirect3DDevice7::SetMaterial and friends.
4405  *
4406  * Version 1, 2 and 3
4407  *
4408  * Params:
4409  *  material: Address to store the new interface's pointer to
4410  *  outer_unknown: Basically for aggregation, but ddraw doesn't support it.
4411  *                 Must be NULL
4412  *
4413  * Returns:
4414  *  D3D_OK on success
4415  *  DDERR_OUTOFMEMORY if memory allocation failed
4416  *  CLASS_E_NOAGGREGATION if outer_unknown != NULL
4417  *
4418  *****************************************************************************/
4419 static HRESULT WINAPI d3d3_CreateMaterial(IDirect3D3 *iface, IDirect3DMaterial3 **material, IUnknown *outer_unknown)
4420 {
4421     IDirect3DMaterialImpl *object;
4422
4423     TRACE("iface %p, material %p, outer_unknown %p.\n", iface, material, outer_unknown);
4424
4425     if (outer_unknown) return CLASS_E_NOAGGREGATION;
4426
4427     object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*object));
4428     if (!object)
4429     {
4430         ERR("Failed to allocate material memory.\n");
4431         return DDERR_OUTOFMEMORY;
4432     }
4433
4434     d3d_material_init(object, ddraw_from_d3d3(iface));
4435
4436     TRACE("Created material %p.\n", object);
4437     *material = (IDirect3DMaterial3 *)object;
4438
4439     return D3D_OK;
4440 }
4441
4442 static HRESULT WINAPI d3d2_CreateMaterial(IDirect3D2 *iface, IDirect3DMaterial2 **material, IUnknown *outer_unknown)
4443 {
4444     IDirect3DMaterial3 *material3;
4445     HRESULT hr;
4446
4447     TRACE("iface %p, material %p, outer_unknown %p.\n", iface, material, outer_unknown);
4448
4449     hr = d3d3_CreateMaterial((IDirect3D3 *)&ddraw_from_d3d2(iface)->IDirect3D3_vtbl, &material3, outer_unknown);
4450     *material = material3 ? (IDirect3DMaterial2 *)&((IDirect3DMaterialImpl *)material3)->IDirect3DMaterial2_vtbl : NULL;
4451
4452     TRACE("Returning material %p.\n", *material);
4453
4454     return hr;
4455 }
4456
4457 static HRESULT WINAPI d3d1_CreateMaterial(IDirect3D *iface, IDirect3DMaterial **material, IUnknown *outer_unknown)
4458 {
4459     IDirect3DMaterial3 *material3;
4460     HRESULT hr;
4461
4462     TRACE("iface %p, material %p, outer_unknown %p.\n", iface, material, outer_unknown);
4463
4464     hr = d3d3_CreateMaterial((IDirect3D3 *)&ddraw_from_d3d1(iface)->IDirect3D3_vtbl, &material3, outer_unknown);
4465     *material = material3 ? (IDirect3DMaterial *)&((IDirect3DMaterialImpl *)material3)->IDirect3DMaterial_vtbl : NULL;
4466
4467     TRACE("Returning material %p.\n", *material);
4468
4469     return hr;
4470 }
4471
4472 /*****************************************************************************
4473  * IDirect3D3::CreateViewport
4474  *
4475  * Creates an IDirect3DViewport interface. This interface is used
4476  * by Direct3D and earlier versions for Viewport management. In Direct3D7
4477  * it has been replaced by a viewport structure and
4478  * IDirect3DDevice7::*Viewport. Wine's IDirect3DViewport implementation
4479  * uses the IDirect3DDevice7 methods for its functionality
4480  *
4481  * Params:
4482  *  Viewport: Address to store the new interface pointer
4483  *  outer_unknown: Basically for aggregation, but ddraw doesn't support it.
4484  *                 Must be NULL
4485  *
4486  * Returns:
4487  *  D3D_OK on success
4488  *  DDERR_OUTOFMEMORY if memory allocation failed
4489  *  CLASS_E_NOAGGREGATION if outer_unknown != NULL
4490  *
4491  *****************************************************************************/
4492 static HRESULT WINAPI d3d3_CreateViewport(IDirect3D3 *iface, IDirect3DViewport3 **viewport, IUnknown *outer_unknown)
4493 {
4494     IDirect3DViewportImpl *object;
4495
4496     TRACE("iface %p, viewport %p, outer_unknown %p.\n", iface, viewport, outer_unknown);
4497
4498     if (outer_unknown) return CLASS_E_NOAGGREGATION;
4499
4500     object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*object));
4501     if (!object)
4502     {
4503         ERR("Failed to allocate viewport memory.\n");
4504         return DDERR_OUTOFMEMORY;
4505     }
4506
4507     d3d_viewport_init(object, ddraw_from_d3d3(iface));
4508
4509     TRACE("Created viewport %p.\n", object);
4510     *viewport = (IDirect3DViewport3 *)object;
4511
4512     return D3D_OK;
4513 }
4514
4515 static HRESULT WINAPI d3d2_CreateViewport(IDirect3D2 *iface, IDirect3DViewport2 **viewport, IUnknown *outer_unknown)
4516 {
4517     TRACE("iface %p, viewport %p, outer_unknown %p.\n", iface, viewport, outer_unknown);
4518
4519     return d3d3_CreateViewport((IDirect3D3 *)&ddraw_from_d3d2(iface)->IDirect3D3_vtbl,
4520             (IDirect3DViewport3 **)viewport, outer_unknown);
4521 }
4522
4523 static HRESULT WINAPI d3d1_CreateViewport(IDirect3D *iface, IDirect3DViewport **viewport, IUnknown *outer_unknown)
4524 {
4525     TRACE("iface %p, viewport %p, outer_unknown %p.\n", iface, viewport, outer_unknown);
4526
4527     return d3d3_CreateViewport((IDirect3D3 *)&ddraw_from_d3d1(iface)->IDirect3D3_vtbl,
4528             (IDirect3DViewport3 **)viewport, outer_unknown);
4529 }
4530
4531 /*****************************************************************************
4532  * IDirect3D3::FindDevice
4533  *
4534  * This method finds a device with the requested properties and returns a
4535  * device description
4536  *
4537  * Verion 1, 2 and 3
4538  * Params:
4539  *  fds: Describes the requested device characteristics
4540  *  fdr: Returns the device description
4541  *
4542  * Returns:
4543  *  D3D_OK on success
4544  *  DDERR_INVALIDPARAMS if no device was found
4545  *
4546  *****************************************************************************/
4547 static HRESULT WINAPI d3d3_FindDevice(IDirect3D3 *iface, D3DFINDDEVICESEARCH *fds, D3DFINDDEVICERESULT *fdr)
4548 {
4549     IDirectDrawImpl *ddraw = ddraw_from_d3d3(iface);
4550     D3DDEVICEDESC7 desc7;
4551     D3DDEVICEDESC desc1;
4552     HRESULT hr;
4553
4554     TRACE("iface %p, fds %p, fdr %p.\n", iface, fds, fdr);
4555
4556     if (!fds || !fdr) return DDERR_INVALIDPARAMS;
4557
4558     if (fds->dwSize != sizeof(D3DFINDDEVICESEARCH)
4559             || fdr->dwSize != sizeof(D3DFINDDEVICERESULT))
4560         return DDERR_INVALIDPARAMS;
4561
4562     if ((fds->dwFlags & D3DFDS_COLORMODEL)
4563             && fds->dcmColorModel != D3DCOLOR_RGB)
4564     {
4565         WARN("Trying to request a non-RGB D3D color model. Not supported.\n");
4566         return DDERR_INVALIDPARAMS; /* No real idea what to return here :-) */
4567     }
4568
4569     if (fds->dwFlags & D3DFDS_GUID)
4570     {
4571         TRACE("Trying to match guid %s.\n", debugstr_guid(&(fds->guid)));
4572         if (!IsEqualGUID(&IID_D3DDEVICE_WineD3D, &fds->guid)
4573                 && !IsEqualGUID(&IID_IDirect3DHALDevice, &fds->guid)
4574                 && !IsEqualGUID(&IID_IDirect3DRGBDevice, &fds->guid))
4575         {
4576             WARN("No match for this GUID.\n");
4577             return DDERR_NOTFOUND;
4578         }
4579     }
4580
4581     /* Get the caps */
4582     hr = IDirect3DImpl_GetCaps(ddraw->wineD3D, &desc1, &desc7);
4583     if (hr != D3D_OK) return hr;
4584
4585     /* Now return our own GUID */
4586     fdr->guid = IID_D3DDEVICE_WineD3D;
4587     fdr->ddHwDesc = desc1;
4588     fdr->ddSwDesc = desc1;
4589
4590     TRACE("Returning Wine's wined3d device with (undumped) capabilities.\n");
4591
4592     return D3D_OK;
4593 }
4594
4595 static HRESULT WINAPI d3d2_FindDevice(IDirect3D2 *iface, D3DFINDDEVICESEARCH *fds, D3DFINDDEVICERESULT *fdr)
4596 {
4597     TRACE("iface %p, fds %p, fdr %p.\n", iface, fds, fdr);
4598
4599     return d3d3_FindDevice((IDirect3D3 *)&ddraw_from_d3d2(iface)->IDirect3D3_vtbl, fds, fdr);
4600 }
4601
4602 static HRESULT WINAPI d3d1_FindDevice(IDirect3D *iface, D3DFINDDEVICESEARCH *fds, D3DFINDDEVICERESULT *fdr)
4603 {
4604     TRACE("iface %p, fds %p, fdr %p.\n", iface, fds, fdr);
4605
4606     return d3d3_FindDevice((IDirect3D3 *)&ddraw_from_d3d1(iface)->IDirect3D3_vtbl, fds, fdr);
4607 }
4608
4609 /*****************************************************************************
4610  * IDirect3D7::CreateDevice
4611  *
4612  * Creates an IDirect3DDevice7 interface.
4613  *
4614  * Version 2, 3 and 7. IDirect3DDevice 1 interfaces are interfaces to
4615  * DirectDraw surfaces and are created with
4616  * IDirectDrawSurface::QueryInterface. This method uses CreateDevice to
4617  * create the device object and QueryInterfaces for IDirect3DDevice
4618  *
4619  * Params:
4620  *  refiid: IID of the device to create
4621  *  Surface: Initial rendertarget
4622  *  Device: Address to return the interface pointer
4623  *
4624  * Returns:
4625  *  D3D_OK on success
4626  *  DDERR_OUTOFMEMORY if memory allocation failed
4627  *  DDERR_INVALIDPARAMS if a device exists already
4628  *
4629  *****************************************************************************/
4630 static HRESULT WINAPI d3d7_CreateDevice(IDirect3D7 *iface, REFCLSID riid,
4631         IDirectDrawSurface7 *surface, IDirect3DDevice7 **device)
4632 {
4633     IDirectDrawSurfaceImpl *target = (IDirectDrawSurfaceImpl *)surface;
4634     IDirectDrawImpl *ddraw = ddraw_from_d3d7(iface);
4635     IDirect3DDeviceImpl *object;
4636     HRESULT hr;
4637
4638     TRACE("iface %p, riid %s, surface %p, device %p.\n", iface, debugstr_guid(riid), surface, device);
4639
4640     EnterCriticalSection(&ddraw_cs);
4641     *device = NULL;
4642
4643     /* Fail device creation if non-opengl surfaces are used. */
4644     if (ddraw->ImplType != SURFACE_OPENGL)
4645     {
4646         ERR("The application wants to create a Direct3D device, but non-opengl surfaces are set in the registry.\n");
4647         ERR("Please set the surface implementation to opengl or autodetection to allow 3D rendering.\n");
4648
4649         /* We only hit this path if a default surface is set in the registry. Incorrect autodetection
4650          * is caught in CreateSurface or QueryInterface. */
4651         LeaveCriticalSection(&ddraw_cs);
4652         return DDERR_NO3D;
4653     }
4654
4655     if (ddraw->d3ddevice)
4656     {
4657         FIXME("Only one Direct3D device per DirectDraw object supported.\n");
4658         LeaveCriticalSection(&ddraw_cs);
4659         return DDERR_INVALIDPARAMS;
4660     }
4661
4662     object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*object));
4663     if (!object)
4664     {
4665         ERR("Failed to allocate device memory.\n");
4666         LeaveCriticalSection(&ddraw_cs);
4667         return DDERR_OUTOFMEMORY;
4668     }
4669
4670     hr = d3d_device_init(object, ddraw, target);
4671     if (FAILED(hr))
4672     {
4673         WARN("Failed to initialize device, hr %#x.\n", hr);
4674         HeapFree(GetProcessHeap(), 0, object);
4675         LeaveCriticalSection(&ddraw_cs);
4676         return hr;
4677     }
4678
4679     TRACE("Created device %p.\n", object);
4680     *device = (IDirect3DDevice7 *)object;
4681
4682     LeaveCriticalSection(&ddraw_cs);
4683     return D3D_OK;
4684 }
4685
4686 static HRESULT WINAPI d3d3_CreateDevice(IDirect3D3 *iface, REFCLSID riid,
4687         IDirectDrawSurface4 *surface, IDirect3DDevice3 **device, IUnknown *outer_unknown)
4688 {
4689     HRESULT hr;
4690
4691     TRACE("iface %p, riid %s, surface %p, device %p, outer_unknown %p.\n",
4692             iface, debugstr_guid(riid), surface, device, outer_unknown);
4693
4694     if (outer_unknown) return CLASS_E_NOAGGREGATION;
4695
4696     hr = d3d7_CreateDevice((IDirect3D7 *)&ddraw_from_d3d3(iface)->IDirect3D7_vtbl, riid,
4697             (IDirectDrawSurface7 *)surface, (IDirect3DDevice7 **)device);
4698     if (*device) *device = (IDirect3DDevice3 *)&((IDirect3DDeviceImpl *)*device)->IDirect3DDevice3_vtbl;
4699
4700     return hr;
4701 }
4702
4703 static HRESULT WINAPI d3d2_CreateDevice(IDirect3D2 *iface, REFCLSID riid,
4704         IDirectDrawSurface *surface, IDirect3DDevice2 **device)
4705 {
4706     HRESULT hr;
4707
4708     TRACE("iface %p, riid %s, surface %p, device %p.\n",
4709             iface, debugstr_guid(riid), surface, device);
4710
4711     hr = d3d7_CreateDevice((IDirect3D7 *)&ddraw_from_d3d2(iface)->IDirect3D7_vtbl, riid,
4712             surface ? (IDirectDrawSurface7 *)surface_from_surface3((IDirectDrawSurface3 *)surface) : NULL,
4713             (IDirect3DDevice7 **)device);
4714     if (*device) *device = (IDirect3DDevice2 *)&((IDirect3DDeviceImpl *)*device)->IDirect3DDevice2_vtbl;
4715
4716     return hr;
4717 }
4718
4719 /*****************************************************************************
4720  * IDirect3D7::CreateVertexBuffer
4721  *
4722  * Creates a new vertex buffer object and returns a IDirect3DVertexBuffer7
4723  * interface.
4724  *
4725  * Version 3 and 7
4726  *
4727  * Params:
4728  *  desc: Requested Vertex buffer properties
4729  *  vertex_buffer: Address to return the interface pointer at
4730  *  flags: Some flags, should be 0
4731  *
4732  * Returns
4733  *  D3D_OK on success
4734  *  DDERR_OUTOFMEMORY if memory allocation failed
4735  *  The return value of IWineD3DDevice::CreateVertexBuffer if this call fails
4736  *  DDERR_INVALIDPARAMS if desc or vertex_buffer are NULL
4737  *
4738  *****************************************************************************/
4739 static HRESULT WINAPI d3d7_CreateVertexBuffer(IDirect3D7 *iface, D3DVERTEXBUFFERDESC *desc,
4740         IDirect3DVertexBuffer7 **vertex_buffer, DWORD flags)
4741 {
4742     IDirect3DVertexBufferImpl *object;
4743     HRESULT hr;
4744
4745     TRACE("iface %p, desc %p, vertex_buffer %p, flags %#x.\n",
4746             iface, desc, vertex_buffer, flags);
4747
4748     if (!vertex_buffer || !desc) return DDERR_INVALIDPARAMS;
4749
4750     TRACE("Vertex buffer description:\n");
4751     TRACE("    dwSize %u\n", desc->dwSize);
4752     TRACE("    dwCaps %#x\n", desc->dwCaps);
4753     TRACE("    FVF %#x\n", desc->dwFVF);
4754     TRACE("    dwNumVertices %u\n", desc->dwNumVertices);
4755
4756     /* Now create the vertex buffer */
4757     object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*object));
4758     if (!object)
4759     {
4760         ERR("Failed to allocate vertex buffer memory.\n");
4761         return DDERR_OUTOFMEMORY;
4762     }
4763
4764     hr = d3d_vertex_buffer_init(object, ddraw_from_d3d7(iface), desc);
4765     if (FAILED(hr))
4766     {
4767         WARN("Failed to initialize vertex buffer, hr %#x.\n", hr);
4768         HeapFree(GetProcessHeap(), 0, object);
4769         return hr;
4770     }
4771
4772     TRACE("Created vertex buffer %p.\n", object);
4773     *vertex_buffer = (IDirect3DVertexBuffer7 *)object;
4774
4775     return D3D_OK;
4776 }
4777
4778 static HRESULT WINAPI d3d3_CreateVertexBuffer(IDirect3D3 *iface, D3DVERTEXBUFFERDESC *desc,
4779         IDirect3DVertexBuffer **vertex_buffer, DWORD flags, IUnknown *outer_unknown)
4780 {
4781     IDirectDrawImpl *This = ddraw_from_d3d3(iface);
4782     HRESULT hr;
4783
4784     TRACE("iface %p, desc %p, vertex_buffer %p, flags %#x, outer_unknown %p.\n",
4785             iface, desc, vertex_buffer, flags, outer_unknown);
4786
4787     if (outer_unknown) return CLASS_E_NOAGGREGATION;
4788
4789     hr = d3d7_CreateVertexBuffer((IDirect3D7 *)&This->IDirect3D7_vtbl,
4790             desc, (IDirect3DVertexBuffer7 **)vertex_buffer, flags);
4791     if (*vertex_buffer)
4792         *vertex_buffer = (IDirect3DVertexBuffer *)&((IDirect3DVertexBufferImpl *)*vertex_buffer)->IDirect3DVertexBuffer_vtbl;
4793
4794     return hr;
4795 }
4796
4797 /*****************************************************************************
4798  * IDirect3D7::EnumZBufferFormats
4799  *
4800  * Enumerates all supported Z buffer pixel formats
4801  *
4802  * Version 3 and 7
4803  *
4804  * Params:
4805  *  device_iid:
4806  *  callback: callback to call for each pixel format
4807  *  context: Pointer to pass back to the callback
4808  *
4809  * Returns:
4810  *  D3D_OK on success
4811  *  DDERR_INVALIDPARAMS if callback is NULL
4812  *  For details, see IWineD3DDevice::EnumZBufferFormats
4813  *
4814  *****************************************************************************/
4815 static HRESULT WINAPI d3d7_EnumZBufferFormats(IDirect3D7 *iface, REFCLSID device_iid,
4816         LPD3DENUMPIXELFORMATSCALLBACK callback, void *context)
4817 {
4818     IDirectDrawImpl *ddraw = ddraw_from_d3d7(iface);
4819     WINED3DDISPLAYMODE d3ddm;
4820     WINED3DDEVTYPE type;
4821     unsigned int i;
4822     HRESULT hr;
4823
4824     /* Order matters. Specifically, BattleZone II (full version) expects the
4825      * 16-bit depth formats to be listed before the 24 and 32 ones. */
4826     static const WINED3DFORMAT formats[] =
4827     {
4828         WINED3DFMT_S1_UINT_D15_UNORM,
4829         WINED3DFMT_D16_UNORM,
4830         WINED3DFMT_X8D24_UNORM,
4831         WINED3DFMT_S4X4_UINT_D24_UNORM,
4832         WINED3DFMT_D24_UNORM_S8_UINT,
4833         WINED3DFMT_D32_UNORM,
4834     };
4835
4836     TRACE("iface %p, device_iid %s, callback %p, context %p.\n",
4837             iface, debugstr_guid(device_iid), callback, context);
4838
4839     if (!callback) return DDERR_INVALIDPARAMS;
4840
4841     if (IsEqualGUID(device_iid, &IID_IDirect3DHALDevice)
4842             || IsEqualGUID(device_iid, &IID_IDirect3DTnLHalDevice)
4843             || IsEqualGUID(device_iid, &IID_D3DDEVICE_WineD3D))
4844     {
4845         TRACE("Asked for HAL device.\n");
4846         type = WINED3DDEVTYPE_HAL;
4847     }
4848     else if (IsEqualGUID(device_iid, &IID_IDirect3DRGBDevice)
4849             || IsEqualGUID(device_iid, &IID_IDirect3DMMXDevice))
4850     {
4851         TRACE("Asked for SW device.\n");
4852         type = WINED3DDEVTYPE_SW;
4853     }
4854     else if (IsEqualGUID(device_iid, &IID_IDirect3DRefDevice))
4855     {
4856         TRACE("Asked for REF device.\n");
4857         type = WINED3DDEVTYPE_REF;
4858     }
4859     else if (IsEqualGUID(device_iid, &IID_IDirect3DNullDevice))
4860     {
4861         TRACE("Asked for NULLREF device.\n");
4862         type = WINED3DDEVTYPE_NULLREF;
4863     }
4864     else
4865     {
4866         FIXME("Unexpected device GUID %s.\n", debugstr_guid(device_iid));
4867         type = WINED3DDEVTYPE_HAL;
4868     }
4869
4870     EnterCriticalSection(&ddraw_cs);
4871     /* We need an adapter format from somewhere to please wined3d and WGL.
4872      * Use the current display mode. So far all cards offer the same depth
4873      * stencil format for all modes, but if some do not and applications do
4874      * not like that we'll have to find some workaround, like iterating over
4875      * all imaginable formats and collecting all the depth stencil formats we
4876      * can get. */
4877     hr = IWineD3DDevice_GetDisplayMode(ddraw->wineD3DDevice, 0, &d3ddm);
4878
4879     for (i = 0; i < (sizeof(formats) / sizeof(*formats)); ++i)
4880     {
4881         hr = IWineD3D_CheckDeviceFormat(ddraw->wineD3D, WINED3DADAPTER_DEFAULT, type, d3ddm.Format,
4882                 WINED3DUSAGE_DEPTHSTENCIL, WINED3DRTYPE_SURFACE, formats[i], SURFACE_OPENGL);
4883         if (SUCCEEDED(hr))
4884         {
4885             DDPIXELFORMAT pformat;
4886
4887             memset(&pformat, 0, sizeof(pformat));
4888             pformat.dwSize = sizeof(pformat);
4889             PixelFormat_WineD3DtoDD(&pformat, formats[i]);
4890
4891             TRACE("Enumerating wined3d format %#x.\n", formats[i]);
4892             hr = callback(&pformat, context);
4893             if (hr != DDENUMRET_OK)
4894             {
4895                 TRACE("Format enumeration cancelled by application.\n");
4896                 LeaveCriticalSection(&ddraw_cs);
4897                 return D3D_OK;
4898             }
4899         }
4900     }
4901     TRACE("End of enumeration.\n");
4902
4903     LeaveCriticalSection(&ddraw_cs);
4904     return D3D_OK;
4905 }
4906
4907 static HRESULT WINAPI d3d3_EnumZBufferFormats(IDirect3D3 *iface, REFCLSID device_iid,
4908         LPD3DENUMPIXELFORMATSCALLBACK callback, void *context)
4909 {
4910     TRACE("iface %p, device_iid %s, callback %p, context %p.\n",
4911             iface, debugstr_guid(device_iid), callback, context);
4912
4913     return d3d7_EnumZBufferFormats((IDirect3D7 *)&ddraw_from_d3d3(iface)->IDirect3D7_vtbl,
4914             device_iid, callback, context);
4915 }
4916
4917 /*****************************************************************************
4918  * IDirect3D7::EvictManagedTextures
4919  *
4920  * Removes all managed textures (=surfaces with DDSCAPS2_TEXTUREMANAGE or
4921  * DDSCAPS2_D3DTEXTUREMANAGE caps) to be removed from video memory.
4922  *
4923  * Version 3 and 7
4924  *
4925  * Returns:
4926  *  D3D_OK, because it's a stub
4927  *
4928  *****************************************************************************/
4929 static HRESULT WINAPI d3d7_EvictManagedTextures(IDirect3D7 *iface)
4930 {
4931     FIXME("iface %p stub!\n", iface);
4932
4933     /* TODO: Just enumerate resources using IWineD3DDevice_EnumResources(),
4934      * then unload surfaces / textures. */
4935
4936     return D3D_OK;
4937 }
4938
4939 static HRESULT WINAPI d3d3_EvictManagedTextures(IDirect3D3 *iface)
4940 {
4941     TRACE("iface %p.\n", iface);
4942
4943     return d3d7_EvictManagedTextures((IDirect3D7 *)&ddraw_from_d3d3(iface)->IDirect3D7_vtbl);
4944 }
4945
4946 /*****************************************************************************
4947  * IDirect3DImpl_GetCaps
4948  *
4949  * This function retrieves the device caps from wined3d
4950  * and converts it into a D3D7 and D3D - D3D3 structure
4951  * This is a helper function called from various places in ddraw
4952  *
4953  * Params:
4954  *  wined3d: The interface to get the caps from
4955  *  desc1: Old D3D <3 structure to fill (needed)
4956  *  desc7: D3D7 device desc structure to fill (needed)
4957  *
4958  * Returns
4959  *  D3D_OK on success, or the return value of IWineD3D::GetCaps
4960  *
4961  *****************************************************************************/
4962 HRESULT IDirect3DImpl_GetCaps(IWineD3D *wined3d, D3DDEVICEDESC *desc1, D3DDEVICEDESC7 *desc7)
4963 {
4964     WINED3DCAPS wined3d_caps;
4965     HRESULT hr;
4966
4967     TRACE("wined3d %p, desc1 %p, desc7 %p.\n", wined3d, desc1, desc7);
4968
4969     memset(&wined3d_caps, 0, sizeof(wined3d_caps));
4970
4971     EnterCriticalSection(&ddraw_cs);
4972     hr = IWineD3D_GetDeviceCaps(wined3d, 0, WINED3DDEVTYPE_HAL, &wined3d_caps);
4973     LeaveCriticalSection(&ddraw_cs);
4974     if (FAILED(hr))
4975     {
4976         WARN("Failed to get device caps, hr %#x.\n", hr);
4977         return hr;
4978     }
4979
4980     /* Copy the results into the d3d7 and d3d3 structures */
4981     desc7->dwDevCaps = wined3d_caps.DevCaps;
4982     desc7->dpcLineCaps.dwMiscCaps = wined3d_caps.PrimitiveMiscCaps;
4983     desc7->dpcLineCaps.dwRasterCaps = wined3d_caps.RasterCaps;
4984     desc7->dpcLineCaps.dwZCmpCaps = wined3d_caps.ZCmpCaps;
4985     desc7->dpcLineCaps.dwSrcBlendCaps = wined3d_caps.SrcBlendCaps;
4986     desc7->dpcLineCaps.dwDestBlendCaps = wined3d_caps.DestBlendCaps;
4987     desc7->dpcLineCaps.dwAlphaCmpCaps = wined3d_caps.AlphaCmpCaps;
4988     desc7->dpcLineCaps.dwShadeCaps = wined3d_caps.ShadeCaps;
4989     desc7->dpcLineCaps.dwTextureCaps = wined3d_caps.TextureCaps;
4990     desc7->dpcLineCaps.dwTextureFilterCaps = wined3d_caps.TextureFilterCaps;
4991     desc7->dpcLineCaps.dwTextureAddressCaps = wined3d_caps.TextureAddressCaps;
4992
4993     desc7->dwMaxTextureWidth = wined3d_caps.MaxTextureWidth;
4994     desc7->dwMaxTextureHeight = wined3d_caps.MaxTextureHeight;
4995
4996     desc7->dwMaxTextureRepeat = wined3d_caps.MaxTextureRepeat;
4997     desc7->dwMaxTextureAspectRatio = wined3d_caps.MaxTextureAspectRatio;
4998     desc7->dwMaxAnisotropy = wined3d_caps.MaxAnisotropy;
4999     desc7->dvMaxVertexW = wined3d_caps.MaxVertexW;
5000
5001     desc7->dvGuardBandLeft = wined3d_caps.GuardBandLeft;
5002     desc7->dvGuardBandTop = wined3d_caps.GuardBandTop;
5003     desc7->dvGuardBandRight = wined3d_caps.GuardBandRight;
5004     desc7->dvGuardBandBottom = wined3d_caps.GuardBandBottom;
5005
5006     desc7->dvExtentsAdjust = wined3d_caps.ExtentsAdjust;
5007     desc7->dwStencilCaps = wined3d_caps.StencilCaps;
5008
5009     desc7->dwFVFCaps = wined3d_caps.FVFCaps;
5010     desc7->dwTextureOpCaps = wined3d_caps.TextureOpCaps;
5011
5012     desc7->dwVertexProcessingCaps = wined3d_caps.VertexProcessingCaps;
5013     desc7->dwMaxActiveLights = wined3d_caps.MaxActiveLights;
5014
5015     /* Remove all non-d3d7 caps */
5016     desc7->dwDevCaps &= (
5017         D3DDEVCAPS_FLOATTLVERTEX         | D3DDEVCAPS_SORTINCREASINGZ          | D3DDEVCAPS_SORTDECREASINGZ          |
5018         D3DDEVCAPS_SORTEXACT             | D3DDEVCAPS_EXECUTESYSTEMMEMORY      | D3DDEVCAPS_EXECUTEVIDEOMEMORY       |
5019         D3DDEVCAPS_TLVERTEXSYSTEMMEMORY  | D3DDEVCAPS_TLVERTEXVIDEOMEMORY      | D3DDEVCAPS_TEXTURESYSTEMMEMORY      |
5020         D3DDEVCAPS_TEXTUREVIDEOMEMORY    | D3DDEVCAPS_DRAWPRIMTLVERTEX         | D3DDEVCAPS_CANRENDERAFTERFLIP       |
5021         D3DDEVCAPS_TEXTURENONLOCALVIDMEM | D3DDEVCAPS_DRAWPRIMITIVES2          | D3DDEVCAPS_SEPARATETEXTUREMEMORIES  |
5022         D3DDEVCAPS_DRAWPRIMITIVES2EX     | D3DDEVCAPS_HWTRANSFORMANDLIGHT      | D3DDEVCAPS_CANBLTSYSTONONLOCAL      |
5023         D3DDEVCAPS_HWRASTERIZATION);
5024
5025     desc7->dwStencilCaps &= (
5026         D3DSTENCILCAPS_KEEP              | D3DSTENCILCAPS_ZERO                 | D3DSTENCILCAPS_REPLACE              |
5027         D3DSTENCILCAPS_INCRSAT           | D3DSTENCILCAPS_DECRSAT              | D3DSTENCILCAPS_INVERT               |
5028         D3DSTENCILCAPS_INCR              | D3DSTENCILCAPS_DECR);
5029
5030     /* FVF caps ?*/
5031
5032     desc7->dwTextureOpCaps &= (
5033         D3DTEXOPCAPS_DISABLE             | D3DTEXOPCAPS_SELECTARG1             | D3DTEXOPCAPS_SELECTARG2             |
5034         D3DTEXOPCAPS_MODULATE            | D3DTEXOPCAPS_MODULATE2X             | D3DTEXOPCAPS_MODULATE4X             |
5035         D3DTEXOPCAPS_ADD                 | D3DTEXOPCAPS_ADDSIGNED              | D3DTEXOPCAPS_ADDSIGNED2X            |
5036         D3DTEXOPCAPS_SUBTRACT            | D3DTEXOPCAPS_ADDSMOOTH              | D3DTEXOPCAPS_BLENDTEXTUREALPHA      |
5037         D3DTEXOPCAPS_BLENDFACTORALPHA    | D3DTEXOPCAPS_BLENDTEXTUREALPHAPM    | D3DTEXOPCAPS_BLENDCURRENTALPHA      |
5038         D3DTEXOPCAPS_PREMODULATE         | D3DTEXOPCAPS_MODULATEALPHA_ADDCOLOR | D3DTEXOPCAPS_MODULATECOLOR_ADDALPHA |
5039         D3DTEXOPCAPS_MODULATEINVALPHA_ADDCOLOR | D3DTEXOPCAPS_MODULATEINVCOLOR_ADDALPHA | D3DTEXOPCAPS_BUMPENVMAP    |
5040         D3DTEXOPCAPS_BUMPENVMAPLUMINANCE | D3DTEXOPCAPS_DOTPRODUCT3);
5041
5042     desc7->dwVertexProcessingCaps &= (
5043         D3DVTXPCAPS_TEXGEN               | D3DVTXPCAPS_MATERIALSOURCE7         | D3DVTXPCAPS_VERTEXFOG               |
5044         D3DVTXPCAPS_DIRECTIONALLIGHTS    | D3DVTXPCAPS_POSITIONALLIGHTS        | D3DVTXPCAPS_LOCALVIEWER);
5045
5046     desc7->dpcLineCaps.dwMiscCaps &= (
5047         D3DPMISCCAPS_MASKPLANES          | D3DPMISCCAPS_MASKZ                  | D3DPMISCCAPS_LINEPATTERNREP         |
5048         D3DPMISCCAPS_CONFORMANT          | D3DPMISCCAPS_CULLNONE               | D3DPMISCCAPS_CULLCW                 |
5049         D3DPMISCCAPS_CULLCCW);
5050
5051     desc7->dpcLineCaps.dwRasterCaps &= (
5052         D3DPRASTERCAPS_DITHER            | D3DPRASTERCAPS_ROP2                 | D3DPRASTERCAPS_XOR                  |
5053         D3DPRASTERCAPS_PAT               | D3DPRASTERCAPS_ZTEST                | D3DPRASTERCAPS_SUBPIXEL             |
5054         D3DPRASTERCAPS_SUBPIXELX         | D3DPRASTERCAPS_FOGVERTEX            | D3DPRASTERCAPS_FOGTABLE             |
5055         D3DPRASTERCAPS_STIPPLE           | D3DPRASTERCAPS_ANTIALIASSORTDEPENDENT | D3DPRASTERCAPS_ANTIALIASSORTINDEPENDENT |
5056         D3DPRASTERCAPS_ANTIALIASEDGES    | D3DPRASTERCAPS_MIPMAPLODBIAS        | D3DPRASTERCAPS_ZBIAS                |
5057         D3DPRASTERCAPS_ZBUFFERLESSHSR    | D3DPRASTERCAPS_FOGRANGE             | D3DPRASTERCAPS_ANISOTROPY           |
5058         D3DPRASTERCAPS_WBUFFER           | D3DPRASTERCAPS_TRANSLUCENTSORTINDEPENDENT | D3DPRASTERCAPS_WFOG           |
5059         D3DPRASTERCAPS_ZFOG);
5060
5061     desc7->dpcLineCaps.dwZCmpCaps &= (
5062         D3DPCMPCAPS_NEVER                | D3DPCMPCAPS_LESS                    | D3DPCMPCAPS_EQUAL                   |
5063         D3DPCMPCAPS_LESSEQUAL            | D3DPCMPCAPS_GREATER                 | D3DPCMPCAPS_NOTEQUAL                |
5064         D3DPCMPCAPS_GREATEREQUAL         | D3DPCMPCAPS_ALWAYS);
5065
5066     desc7->dpcLineCaps.dwSrcBlendCaps &= (
5067         D3DPBLENDCAPS_ZERO               | D3DPBLENDCAPS_ONE                   | D3DPBLENDCAPS_SRCCOLOR              |
5068         D3DPBLENDCAPS_INVSRCCOLOR        | D3DPBLENDCAPS_SRCALPHA              | D3DPBLENDCAPS_INVSRCALPHA           |
5069         D3DPBLENDCAPS_DESTALPHA          | D3DPBLENDCAPS_INVDESTALPHA          | D3DPBLENDCAPS_DESTCOLOR             |
5070         D3DPBLENDCAPS_INVDESTCOLOR       | D3DPBLENDCAPS_SRCALPHASAT           | D3DPBLENDCAPS_BOTHSRCALPHA          |
5071         D3DPBLENDCAPS_BOTHINVSRCALPHA);
5072
5073     desc7->dpcLineCaps.dwDestBlendCaps &= (
5074         D3DPBLENDCAPS_ZERO               | D3DPBLENDCAPS_ONE                   | D3DPBLENDCAPS_SRCCOLOR              |
5075         D3DPBLENDCAPS_INVSRCCOLOR        | D3DPBLENDCAPS_SRCALPHA              | D3DPBLENDCAPS_INVSRCALPHA           |
5076         D3DPBLENDCAPS_DESTALPHA          | D3DPBLENDCAPS_INVDESTALPHA          | D3DPBLENDCAPS_DESTCOLOR             |
5077         D3DPBLENDCAPS_INVDESTCOLOR       | D3DPBLENDCAPS_SRCALPHASAT           | D3DPBLENDCAPS_BOTHSRCALPHA          |
5078         D3DPBLENDCAPS_BOTHINVSRCALPHA);
5079
5080     desc7->dpcLineCaps.dwAlphaCmpCaps &= (
5081         D3DPCMPCAPS_NEVER                | D3DPCMPCAPS_LESS                    | D3DPCMPCAPS_EQUAL                   |
5082         D3DPCMPCAPS_LESSEQUAL            | D3DPCMPCAPS_GREATER                 | D3DPCMPCAPS_NOTEQUAL                |
5083         D3DPCMPCAPS_GREATEREQUAL         | D3DPCMPCAPS_ALWAYS);
5084
5085     desc7->dpcLineCaps.dwShadeCaps &= (
5086         D3DPSHADECAPS_COLORFLATMONO      | D3DPSHADECAPS_COLORFLATRGB          | D3DPSHADECAPS_COLORGOURAUDMONO      |
5087         D3DPSHADECAPS_COLORGOURAUDRGB    | D3DPSHADECAPS_COLORPHONGMONO        | D3DPSHADECAPS_COLORPHONGRGB         |
5088         D3DPSHADECAPS_SPECULARFLATMONO   | D3DPSHADECAPS_SPECULARFLATRGB       | D3DPSHADECAPS_SPECULARGOURAUDMONO   |
5089         D3DPSHADECAPS_SPECULARGOURAUDRGB | D3DPSHADECAPS_SPECULARPHONGMONO     | D3DPSHADECAPS_SPECULARPHONGRGB      |
5090         D3DPSHADECAPS_ALPHAFLATBLEND     | D3DPSHADECAPS_ALPHAFLATSTIPPLED     | D3DPSHADECAPS_ALPHAGOURAUDBLEND     |
5091         D3DPSHADECAPS_ALPHAGOURAUDSTIPPLED | D3DPSHADECAPS_ALPHAPHONGBLEND     | D3DPSHADECAPS_ALPHAPHONGSTIPPLED    |
5092         D3DPSHADECAPS_FOGFLAT            | D3DPSHADECAPS_FOGGOURAUD            | D3DPSHADECAPS_FOGPHONG);
5093
5094     desc7->dpcLineCaps.dwTextureCaps &= (
5095         D3DPTEXTURECAPS_PERSPECTIVE      | D3DPTEXTURECAPS_POW2                | D3DPTEXTURECAPS_ALPHA               |
5096         D3DPTEXTURECAPS_TRANSPARENCY     | D3DPTEXTURECAPS_BORDER              | D3DPTEXTURECAPS_SQUAREONLY          |
5097         D3DPTEXTURECAPS_TEXREPEATNOTSCALEDBYSIZE | D3DPTEXTURECAPS_ALPHAPALETTE| D3DPTEXTURECAPS_NONPOW2CONDITIONAL  |
5098         D3DPTEXTURECAPS_PROJECTED        | D3DPTEXTURECAPS_CUBEMAP             | D3DPTEXTURECAPS_COLORKEYBLEND);
5099
5100     desc7->dpcLineCaps.dwTextureFilterCaps &= (
5101         D3DPTFILTERCAPS_NEAREST          | D3DPTFILTERCAPS_LINEAR              | D3DPTFILTERCAPS_MIPNEAREST          |
5102         D3DPTFILTERCAPS_MIPLINEAR        | D3DPTFILTERCAPS_LINEARMIPNEAREST    | D3DPTFILTERCAPS_LINEARMIPLINEAR     |
5103         D3DPTFILTERCAPS_MINFPOINT        | D3DPTFILTERCAPS_MINFLINEAR          | D3DPTFILTERCAPS_MINFANISOTROPIC     |
5104         D3DPTFILTERCAPS_MIPFPOINT        | D3DPTFILTERCAPS_MIPFLINEAR          | D3DPTFILTERCAPS_MAGFPOINT           |
5105         D3DPTFILTERCAPS_MAGFLINEAR       | D3DPTFILTERCAPS_MAGFANISOTROPIC     | D3DPTFILTERCAPS_MAGFAFLATCUBIC      |
5106         D3DPTFILTERCAPS_MAGFGAUSSIANCUBIC);
5107
5108     desc7->dpcLineCaps.dwTextureBlendCaps &= (
5109         D3DPTBLENDCAPS_DECAL             | D3DPTBLENDCAPS_MODULATE             | D3DPTBLENDCAPS_DECALALPHA           |
5110         D3DPTBLENDCAPS_MODULATEALPHA     | D3DPTBLENDCAPS_DECALMASK            | D3DPTBLENDCAPS_MODULATEMASK         |
5111         D3DPTBLENDCAPS_COPY              | D3DPTBLENDCAPS_ADD);
5112
5113     desc7->dpcLineCaps.dwTextureAddressCaps &= (
5114         D3DPTADDRESSCAPS_WRAP            | D3DPTADDRESSCAPS_MIRROR             | D3DPTADDRESSCAPS_CLAMP              |
5115         D3DPTADDRESSCAPS_BORDER          | D3DPTADDRESSCAPS_INDEPENDENTUV);
5116
5117     if (!(desc7->dpcLineCaps.dwTextureCaps & D3DPTEXTURECAPS_POW2))
5118     {
5119         /* DirectX7 always has the np2 flag set, no matter what the card
5120          * supports. Some old games (Rollcage) check the caps incorrectly.
5121          * If wined3d supports nonpow2 textures it also has np2 conditional
5122          * support. */
5123         desc7->dpcLineCaps.dwTextureCaps |= D3DPTEXTURECAPS_POW2 | D3DPTEXTURECAPS_NONPOW2CONDITIONAL;
5124     }
5125
5126     /* Fill the missing members, and do some fixup */
5127     desc7->dpcLineCaps.dwSize = sizeof(desc7->dpcLineCaps);
5128     desc7->dpcLineCaps.dwTextureBlendCaps = D3DPTBLENDCAPS_ADD | D3DPTBLENDCAPS_MODULATEMASK |
5129                                             D3DPTBLENDCAPS_COPY | D3DPTBLENDCAPS_DECAL |
5130                                             D3DPTBLENDCAPS_DECALALPHA | D3DPTBLENDCAPS_DECALMASK |
5131                                             D3DPTBLENDCAPS_MODULATE | D3DPTBLENDCAPS_MODULATEALPHA;
5132     desc7->dpcLineCaps.dwStippleWidth = 32;
5133     desc7->dpcLineCaps.dwStippleHeight = 32;
5134     /* Use the same for the TriCaps */
5135     desc7->dpcTriCaps = desc7->dpcLineCaps;
5136
5137     desc7->dwDeviceRenderBitDepth = DDBD_16 | DDBD_24 | DDBD_32;
5138     desc7->dwDeviceZBufferBitDepth = DDBD_16 | DDBD_24;
5139     desc7->dwMinTextureWidth = 1;
5140     desc7->dwMinTextureHeight = 1;
5141
5142     /* Convert DWORDs safely to WORDs */
5143     if (wined3d_caps.MaxTextureBlendStages > 0xffff) desc7->wMaxTextureBlendStages = 0xffff;
5144     else desc7->wMaxTextureBlendStages = (WORD)wined3d_caps.MaxTextureBlendStages;
5145     if (wined3d_caps.MaxSimultaneousTextures > 0xffff) desc7->wMaxSimultaneousTextures = 0xffff;
5146     else desc7->wMaxSimultaneousTextures = (WORD)wined3d_caps.MaxSimultaneousTextures;
5147
5148     if (wined3d_caps.MaxUserClipPlanes > 0xffff) desc7->wMaxUserClipPlanes = 0xffff;
5149     else desc7->wMaxUserClipPlanes = (WORD)wined3d_caps.MaxUserClipPlanes;
5150     if (wined3d_caps.MaxVertexBlendMatrices > 0xffff) desc7->wMaxVertexBlendMatrices = 0xffff;
5151     else desc7->wMaxVertexBlendMatrices = (WORD)wined3d_caps.MaxVertexBlendMatrices;
5152
5153     desc7->deviceGUID = IID_IDirect3DTnLHalDevice;
5154
5155     desc7->dwReserved1 = 0;
5156     desc7->dwReserved2 = 0;
5157     desc7->dwReserved3 = 0;
5158     desc7->dwReserved4 = 0;
5159
5160     /* Fill the old structure */
5161     memset(desc1, 0, sizeof(desc1));
5162     desc1->dwSize = sizeof(D3DDEVICEDESC);
5163     desc1->dwFlags = D3DDD_COLORMODEL
5164             | D3DDD_DEVCAPS
5165             | D3DDD_TRANSFORMCAPS
5166             | D3DDD_BCLIPPING
5167             | D3DDD_LIGHTINGCAPS
5168             | D3DDD_LINECAPS
5169             | D3DDD_TRICAPS
5170             | D3DDD_DEVICERENDERBITDEPTH
5171             | D3DDD_DEVICEZBUFFERBITDEPTH
5172             | D3DDD_MAXBUFFERSIZE
5173             | D3DDD_MAXVERTEXCOUNT;
5174
5175     desc1->dcmColorModel = D3DCOLOR_RGB;
5176     desc1->dwDevCaps = desc7->dwDevCaps;
5177     desc1->dtcTransformCaps.dwSize = sizeof(D3DTRANSFORMCAPS);
5178     desc1->dtcTransformCaps.dwCaps = D3DTRANSFORMCAPS_CLIP;
5179     desc1->bClipping = TRUE;
5180     desc1->dlcLightingCaps.dwSize = sizeof(D3DLIGHTINGCAPS);
5181     desc1->dlcLightingCaps.dwCaps = D3DLIGHTCAPS_DIRECTIONAL
5182             | D3DLIGHTCAPS_PARALLELPOINT
5183             | D3DLIGHTCAPS_POINT
5184             | D3DLIGHTCAPS_SPOT;
5185
5186     desc1->dlcLightingCaps.dwLightingModel = D3DLIGHTINGMODEL_RGB;
5187     desc1->dlcLightingCaps.dwNumLights = desc7->dwMaxActiveLights;
5188
5189     desc1->dpcLineCaps.dwSize = sizeof(D3DPRIMCAPS);
5190     desc1->dpcLineCaps.dwMiscCaps = desc7->dpcLineCaps.dwMiscCaps;
5191     desc1->dpcLineCaps.dwRasterCaps = desc7->dpcLineCaps.dwRasterCaps;
5192     desc1->dpcLineCaps.dwZCmpCaps = desc7->dpcLineCaps.dwZCmpCaps;
5193     desc1->dpcLineCaps.dwSrcBlendCaps = desc7->dpcLineCaps.dwSrcBlendCaps;
5194     desc1->dpcLineCaps.dwDestBlendCaps = desc7->dpcLineCaps.dwDestBlendCaps;
5195     desc1->dpcLineCaps.dwShadeCaps = desc7->dpcLineCaps.dwShadeCaps;
5196     desc1->dpcLineCaps.dwTextureCaps = desc7->dpcLineCaps.dwTextureCaps;
5197     desc1->dpcLineCaps.dwTextureFilterCaps = desc7->dpcLineCaps.dwTextureFilterCaps;
5198     desc1->dpcLineCaps.dwTextureBlendCaps = desc7->dpcLineCaps.dwTextureBlendCaps;
5199     desc1->dpcLineCaps.dwTextureAddressCaps = desc7->dpcLineCaps.dwTextureAddressCaps;
5200     desc1->dpcLineCaps.dwStippleWidth = desc7->dpcLineCaps.dwStippleWidth;
5201     desc1->dpcLineCaps.dwAlphaCmpCaps = desc7->dpcLineCaps.dwAlphaCmpCaps;
5202
5203     desc1->dpcTriCaps.dwSize = sizeof(D3DPRIMCAPS);
5204     desc1->dpcTriCaps.dwMiscCaps = desc7->dpcTriCaps.dwMiscCaps;
5205     desc1->dpcTriCaps.dwRasterCaps = desc7->dpcTriCaps.dwRasterCaps;
5206     desc1->dpcTriCaps.dwZCmpCaps = desc7->dpcTriCaps.dwZCmpCaps;
5207     desc1->dpcTriCaps.dwSrcBlendCaps = desc7->dpcTriCaps.dwSrcBlendCaps;
5208     desc1->dpcTriCaps.dwDestBlendCaps = desc7->dpcTriCaps.dwDestBlendCaps;
5209     desc1->dpcTriCaps.dwShadeCaps = desc7->dpcTriCaps.dwShadeCaps;
5210     desc1->dpcTriCaps.dwTextureCaps = desc7->dpcTriCaps.dwTextureCaps;
5211     desc1->dpcTriCaps.dwTextureFilterCaps = desc7->dpcTriCaps.dwTextureFilterCaps;
5212     desc1->dpcTriCaps.dwTextureBlendCaps = desc7->dpcTriCaps.dwTextureBlendCaps;
5213     desc1->dpcTriCaps.dwTextureAddressCaps = desc7->dpcTriCaps.dwTextureAddressCaps;
5214     desc1->dpcTriCaps.dwStippleWidth = desc7->dpcTriCaps.dwStippleWidth;
5215     desc1->dpcTriCaps.dwAlphaCmpCaps = desc7->dpcTriCaps.dwAlphaCmpCaps;
5216
5217     desc1->dwDeviceRenderBitDepth = desc7->dwDeviceRenderBitDepth;
5218     desc1->dwDeviceZBufferBitDepth = desc7->dwDeviceZBufferBitDepth;
5219     desc1->dwMaxBufferSize = 0;
5220     desc1->dwMaxVertexCount = 65536;
5221     desc1->dwMinTextureWidth  = desc7->dwMinTextureWidth;
5222     desc1->dwMinTextureHeight = desc7->dwMinTextureHeight;
5223     desc1->dwMaxTextureWidth  = desc7->dwMaxTextureWidth;
5224     desc1->dwMaxTextureHeight = desc7->dwMaxTextureHeight;
5225     desc1->dwMinStippleWidth  = 1;
5226     desc1->dwMinStippleHeight = 1;
5227     desc1->dwMaxStippleWidth  = 32;
5228     desc1->dwMaxStippleHeight = 32;
5229     desc1->dwMaxTextureRepeat = desc7->dwMaxTextureRepeat;
5230     desc1->dwMaxTextureAspectRatio = desc7->dwMaxTextureAspectRatio;
5231     desc1->dwMaxAnisotropy = desc7->dwMaxAnisotropy;
5232     desc1->dvGuardBandLeft = desc7->dvGuardBandLeft;
5233     desc1->dvGuardBandRight = desc7->dvGuardBandRight;
5234     desc1->dvGuardBandTop = desc7->dvGuardBandTop;
5235     desc1->dvGuardBandBottom = desc7->dvGuardBandBottom;
5236     desc1->dvExtentsAdjust = desc7->dvExtentsAdjust;
5237     desc1->dwStencilCaps = desc7->dwStencilCaps;
5238     desc1->dwFVFCaps = desc7->dwFVFCaps;
5239     desc1->dwTextureOpCaps = desc7->dwTextureOpCaps;
5240     desc1->wMaxTextureBlendStages = desc7->wMaxTextureBlendStages;
5241     desc1->wMaxSimultaneousTextures = desc7->wMaxSimultaneousTextures;
5242
5243     return DD_OK;
5244 }
5245
5246 /*****************************************************************************
5247  * IDirectDraw7 VTable
5248  *****************************************************************************/
5249 static const struct IDirectDraw7Vtbl ddraw7_vtbl =
5250 {
5251     /* IUnknown */
5252     ddraw7_QueryInterface,
5253     ddraw7_AddRef,
5254     ddraw7_Release,
5255     /* IDirectDraw */
5256     ddraw7_Compact,
5257     ddraw7_CreateClipper,
5258     ddraw7_CreatePalette,
5259     ddraw7_CreateSurface,
5260     ddraw7_DuplicateSurface,
5261     ddraw7_EnumDisplayModes,
5262     ddraw7_EnumSurfaces,
5263     ddraw7_FlipToGDISurface,
5264     ddraw7_GetCaps,
5265     ddraw7_GetDisplayMode,
5266     ddraw7_GetFourCCCodes,
5267     ddraw7_GetGDISurface,
5268     ddraw7_GetMonitorFrequency,
5269     ddraw7_GetScanLine,
5270     ddraw7_GetVerticalBlankStatus,
5271     ddraw7_Initialize,
5272     ddraw7_RestoreDisplayMode,
5273     ddraw7_SetCooperativeLevel,
5274     ddraw7_SetDisplayMode,
5275     ddraw7_WaitForVerticalBlank,
5276     /* IDirectDraw2 */
5277     ddraw7_GetAvailableVidMem,
5278     /* IDirectDraw3 */
5279     ddraw7_GetSurfaceFromDC,
5280     /* IDirectDraw4 */
5281     ddraw7_RestoreAllSurfaces,
5282     ddraw7_TestCooperativeLevel,
5283     ddraw7_GetDeviceIdentifier,
5284     /* IDirectDraw7 */
5285     ddraw7_StartModeTest,
5286     ddraw7_EvaluateMode
5287 };
5288
5289 static const struct IDirectDraw4Vtbl ddraw4_vtbl =
5290 {
5291     /* IUnknown */
5292     ddraw4_QueryInterface,
5293     ddraw4_AddRef,
5294     ddraw4_Release,
5295     /* IDirectDraw */
5296     ddraw4_Compact,
5297     ddraw4_CreateClipper,
5298     ddraw4_CreatePalette,
5299     ddraw4_CreateSurface,
5300     ddraw4_DuplicateSurface,
5301     ddraw4_EnumDisplayModes,
5302     ddraw4_EnumSurfaces,
5303     ddraw4_FlipToGDISurface,
5304     ddraw4_GetCaps,
5305     ddraw4_GetDisplayMode,
5306     ddraw4_GetFourCCCodes,
5307     ddraw4_GetGDISurface,
5308     ddraw4_GetMonitorFrequency,
5309     ddraw4_GetScanLine,
5310     ddraw4_GetVerticalBlankStatus,
5311     ddraw4_Initialize,
5312     ddraw4_RestoreDisplayMode,
5313     ddraw4_SetCooperativeLevel,
5314     ddraw4_SetDisplayMode,
5315     ddraw4_WaitForVerticalBlank,
5316     /* IDirectDraw2 */
5317     ddraw4_GetAvailableVidMem,
5318     /* IDirectDraw3 */
5319     ddraw4_GetSurfaceFromDC,
5320     /* IDirectDraw4 */
5321     ddraw4_RestoreAllSurfaces,
5322     ddraw4_TestCooperativeLevel,
5323     ddraw4_GetDeviceIdentifier,
5324 };
5325
5326 static const struct IDirectDraw3Vtbl ddraw3_vtbl =
5327 {
5328     /* IUnknown */
5329     ddraw3_QueryInterface,
5330     ddraw3_AddRef,
5331     ddraw3_Release,
5332     /* IDirectDraw */
5333     ddraw3_Compact,
5334     ddraw3_CreateClipper,
5335     ddraw3_CreatePalette,
5336     ddraw3_CreateSurface,
5337     ddraw3_DuplicateSurface,
5338     ddraw3_EnumDisplayModes,
5339     ddraw3_EnumSurfaces,
5340     ddraw3_FlipToGDISurface,
5341     ddraw3_GetCaps,
5342     ddraw3_GetDisplayMode,
5343     ddraw3_GetFourCCCodes,
5344     ddraw3_GetGDISurface,
5345     ddraw3_GetMonitorFrequency,
5346     ddraw3_GetScanLine,
5347     ddraw3_GetVerticalBlankStatus,
5348     ddraw3_Initialize,
5349     ddraw3_RestoreDisplayMode,
5350     ddraw3_SetCooperativeLevel,
5351     ddraw3_SetDisplayMode,
5352     ddraw3_WaitForVerticalBlank,
5353     /* IDirectDraw2 */
5354     ddraw3_GetAvailableVidMem,
5355     /* IDirectDraw3 */
5356     ddraw3_GetSurfaceFromDC,
5357 };
5358
5359 static const struct IDirectDraw2Vtbl ddraw2_vtbl =
5360 {
5361     /* IUnknown */
5362     ddraw2_QueryInterface,
5363     ddraw2_AddRef,
5364     ddraw2_Release,
5365     /* IDirectDraw */
5366     ddraw2_Compact,
5367     ddraw2_CreateClipper,
5368     ddraw2_CreatePalette,
5369     ddraw2_CreateSurface,
5370     ddraw2_DuplicateSurface,
5371     ddraw2_EnumDisplayModes,
5372     ddraw2_EnumSurfaces,
5373     ddraw2_FlipToGDISurface,
5374     ddraw2_GetCaps,
5375     ddraw2_GetDisplayMode,
5376     ddraw2_GetFourCCCodes,
5377     ddraw2_GetGDISurface,
5378     ddraw2_GetMonitorFrequency,
5379     ddraw2_GetScanLine,
5380     ddraw2_GetVerticalBlankStatus,
5381     ddraw2_Initialize,
5382     ddraw2_RestoreDisplayMode,
5383     ddraw2_SetCooperativeLevel,
5384     ddraw2_SetDisplayMode,
5385     ddraw2_WaitForVerticalBlank,
5386     /* IDirectDraw2 */
5387     ddraw2_GetAvailableVidMem,
5388 };
5389
5390 static const struct IDirectDrawVtbl ddraw1_vtbl =
5391 {
5392     /* IUnknown */
5393     ddraw1_QueryInterface,
5394     ddraw1_AddRef,
5395     ddraw1_Release,
5396     /* IDirectDraw */
5397     ddraw1_Compact,
5398     ddraw1_CreateClipper,
5399     ddraw1_CreatePalette,
5400     ddraw1_CreateSurface,
5401     ddraw1_DuplicateSurface,
5402     ddraw1_EnumDisplayModes,
5403     ddraw1_EnumSurfaces,
5404     ddraw1_FlipToGDISurface,
5405     ddraw1_GetCaps,
5406     ddraw1_GetDisplayMode,
5407     ddraw1_GetFourCCCodes,
5408     ddraw1_GetGDISurface,
5409     ddraw1_GetMonitorFrequency,
5410     ddraw1_GetScanLine,
5411     ddraw1_GetVerticalBlankStatus,
5412     ddraw1_Initialize,
5413     ddraw1_RestoreDisplayMode,
5414     ddraw1_SetCooperativeLevel,
5415     ddraw1_SetDisplayMode,
5416     ddraw1_WaitForVerticalBlank,
5417 };
5418
5419 static const struct IDirect3D7Vtbl d3d7_vtbl =
5420 {
5421     /* IUnknown methods */
5422     d3d7_QueryInterface,
5423     d3d7_AddRef,
5424     d3d7_Release,
5425     /* IDirect3D7 methods */
5426     d3d7_EnumDevices,
5427     d3d7_CreateDevice,
5428     d3d7_CreateVertexBuffer,
5429     d3d7_EnumZBufferFormats,
5430     d3d7_EvictManagedTextures
5431 };
5432
5433 static const struct IDirect3D3Vtbl d3d3_vtbl =
5434 {
5435     /* IUnknown methods */
5436     d3d3_QueryInterface,
5437     d3d3_AddRef,
5438     d3d3_Release,
5439     /* IDirect3D3 methods */
5440     d3d3_EnumDevices,
5441     d3d3_CreateLight,
5442     d3d3_CreateMaterial,
5443     d3d3_CreateViewport,
5444     d3d3_FindDevice,
5445     d3d3_CreateDevice,
5446     d3d3_CreateVertexBuffer,
5447     d3d3_EnumZBufferFormats,
5448     d3d3_EvictManagedTextures
5449 };
5450
5451 static const struct IDirect3D2Vtbl d3d2_vtbl =
5452 {
5453     /* IUnknown methods */
5454     d3d2_QueryInterface,
5455     d3d2_AddRef,
5456     d3d2_Release,
5457     /* IDirect3D2 methods */
5458     d3d2_EnumDevices,
5459     d3d2_CreateLight,
5460     d3d2_CreateMaterial,
5461     d3d2_CreateViewport,
5462     d3d2_FindDevice,
5463     d3d2_CreateDevice
5464 };
5465
5466 static const struct IDirect3DVtbl d3d1_vtbl =
5467 {
5468     /* IUnknown methods */
5469     d3d1_QueryInterface,
5470     d3d1_AddRef,
5471     d3d1_Release,
5472     /* IDirect3D methods */
5473     d3d1_Initialize,
5474     d3d1_EnumDevices,
5475     d3d1_CreateLight,
5476     d3d1_CreateMaterial,
5477     d3d1_CreateViewport,
5478     d3d1_FindDevice
5479 };
5480
5481 /*****************************************************************************
5482  * ddraw_find_decl
5483  *
5484  * Finds the WineD3D vertex declaration for a specific fvf, and creates one
5485  * if none was found.
5486  *
5487  * This function is in ddraw.c and the DDraw object space because D3D7
5488  * vertex buffers are created using the IDirect3D interface to the ddraw
5489  * object, so they can be valid across D3D devices(theoretically. The ddraw
5490  * object also owns the wined3d device
5491  *
5492  * Parameters:
5493  *  This: Device
5494  *  fvf: Fvf to find the decl for
5495  *
5496  * Returns:
5497  *  NULL in case of an error, the IWineD3DVertexDeclaration interface for the
5498  *  fvf otherwise.
5499  *
5500  *****************************************************************************/
5501 IWineD3DVertexDeclaration *ddraw_find_decl(IDirectDrawImpl *This, DWORD fvf)
5502 {
5503     HRESULT hr;
5504     IWineD3DVertexDeclaration* pDecl = NULL;
5505     int p, low, high; /* deliberately signed */
5506     struct FvfToDecl *convertedDecls = This->decls;
5507
5508     TRACE("Searching for declaration for fvf %08x... ", fvf);
5509
5510     low = 0;
5511     high = This->numConvertedDecls - 1;
5512     while(low <= high) {
5513         p = (low + high) >> 1;
5514         TRACE("%d ", p);
5515         if(convertedDecls[p].fvf == fvf) {
5516             TRACE("found %p\n", convertedDecls[p].decl);
5517             return convertedDecls[p].decl;
5518         } else if(convertedDecls[p].fvf < fvf) {
5519             low = p + 1;
5520         } else {
5521             high = p - 1;
5522         }
5523     }
5524     TRACE("not found. Creating and inserting at position %d.\n", low);
5525
5526     hr = IWineD3DDevice_CreateVertexDeclarationFromFVF(This->wineD3DDevice, &pDecl,
5527             (IUnknown *)This, &ddraw_null_wined3d_parent_ops, fvf);
5528     if (hr != S_OK) return NULL;
5529
5530     if(This->declArraySize == This->numConvertedDecls) {
5531         int grow = max(This->declArraySize / 2, 8);
5532         convertedDecls = HeapReAlloc(GetProcessHeap(), 0, convertedDecls,
5533                                      sizeof(convertedDecls[0]) * (This->numConvertedDecls + grow));
5534         if(!convertedDecls) {
5535             /* This will destroy it */
5536             IWineD3DVertexDeclaration_Release(pDecl);
5537             return NULL;
5538         }
5539         This->decls = convertedDecls;
5540         This->declArraySize += grow;
5541     }
5542
5543     memmove(convertedDecls + low + 1, convertedDecls + low, sizeof(convertedDecls[0]) * (This->numConvertedDecls - low));
5544     convertedDecls[low].decl = pDecl;
5545     convertedDecls[low].fvf = fvf;
5546     This->numConvertedDecls++;
5547
5548     TRACE("Returning %p. %d decls in array\n", pDecl, This->numConvertedDecls);
5549     return pDecl;
5550 }
5551
5552 /* IWineD3DDeviceParent IUnknown methods */
5553
5554 static inline struct IDirectDrawImpl *ddraw_from_device_parent(IWineD3DDeviceParent *iface)
5555 {
5556     return (struct IDirectDrawImpl *)((char*)iface - FIELD_OFFSET(struct IDirectDrawImpl, device_parent_vtbl));
5557 }
5558
5559 static HRESULT STDMETHODCALLTYPE device_parent_QueryInterface(IWineD3DDeviceParent *iface, REFIID riid, void **object)
5560 {
5561     struct IDirectDrawImpl *This = ddraw_from_device_parent(iface);
5562     return ddraw7_QueryInterface((IDirectDraw7 *)This, riid, object);
5563 }
5564
5565 static ULONG STDMETHODCALLTYPE device_parent_AddRef(IWineD3DDeviceParent *iface)
5566 {
5567     struct IDirectDrawImpl *This = ddraw_from_device_parent(iface);
5568     return ddraw7_AddRef((IDirectDraw7 *)This);
5569 }
5570
5571 static ULONG STDMETHODCALLTYPE device_parent_Release(IWineD3DDeviceParent *iface)
5572 {
5573     struct IDirectDrawImpl *This = ddraw_from_device_parent(iface);
5574     return ddraw7_Release((IDirectDraw7 *)This);
5575 }
5576
5577 /* IWineD3DDeviceParent methods */
5578
5579 static void STDMETHODCALLTYPE device_parent_WineD3DDeviceCreated(IWineD3DDeviceParent *iface, IWineD3DDevice *device)
5580 {
5581     TRACE("iface %p, device %p\n", iface, device);
5582 }
5583
5584 static HRESULT STDMETHODCALLTYPE device_parent_CreateSurface(IWineD3DDeviceParent *iface,
5585         IUnknown *superior, UINT width, UINT height, WINED3DFORMAT format, DWORD usage,
5586         WINED3DPOOL pool, UINT level, WINED3DCUBEMAP_FACES face, IWineD3DSurface **surface)
5587 {
5588     struct IDirectDrawImpl *This = ddraw_from_device_parent(iface);
5589     IDirectDrawSurfaceImpl *surf = NULL;
5590     UINT i = 0;
5591     DDSCAPS2 searchcaps = This->tex_root->surface_desc.ddsCaps;
5592
5593     TRACE("iface %p, superior %p, width %u, height %u, format %#x, usage %#x,\n"
5594             "\tpool %#x, level %u, face %u, surface %p\n",
5595             iface, superior, width, height, format, usage, pool, level, face, surface);
5596
5597     searchcaps.dwCaps2 &= ~DDSCAPS2_CUBEMAP_ALLFACES;
5598     switch(face)
5599     {
5600         case WINED3DCUBEMAP_FACE_POSITIVE_X:
5601             TRACE("Asked for positive x\n");
5602             if (searchcaps.dwCaps2 & DDSCAPS2_CUBEMAP)
5603             {
5604                 searchcaps.dwCaps2 |= DDSCAPS2_CUBEMAP_POSITIVEX;
5605             }
5606             surf = This->tex_root; break;
5607         case WINED3DCUBEMAP_FACE_NEGATIVE_X:
5608             TRACE("Asked for negative x\n");
5609             searchcaps.dwCaps2 |= DDSCAPS2_CUBEMAP_NEGATIVEX; break;
5610         case WINED3DCUBEMAP_FACE_POSITIVE_Y:
5611             TRACE("Asked for positive y\n");
5612             searchcaps.dwCaps2 |= DDSCAPS2_CUBEMAP_POSITIVEY; break;
5613         case WINED3DCUBEMAP_FACE_NEGATIVE_Y:
5614             TRACE("Asked for negative y\n");
5615             searchcaps.dwCaps2 |= DDSCAPS2_CUBEMAP_NEGATIVEY; break;
5616         case WINED3DCUBEMAP_FACE_POSITIVE_Z:
5617             TRACE("Asked for positive z\n");
5618             searchcaps.dwCaps2 |= DDSCAPS2_CUBEMAP_POSITIVEZ; break;
5619         case WINED3DCUBEMAP_FACE_NEGATIVE_Z:
5620             TRACE("Asked for negative z\n");
5621             searchcaps.dwCaps2 |= DDSCAPS2_CUBEMAP_NEGATIVEZ; break;
5622         default: {ERR("Unexpected cube face\n");} /* Stupid compiler */
5623     }
5624
5625     if (!surf)
5626     {
5627         IDirectDrawSurface7 *attached;
5628         IDirectDrawSurface7_GetAttachedSurface((IDirectDrawSurface7 *)This->tex_root, &searchcaps, &attached);
5629         surf = (IDirectDrawSurfaceImpl *)attached;
5630         IDirectDrawSurface7_Release(attached);
5631     }
5632     if (!surf) ERR("root search surface not found\n");
5633
5634     /* Find the wanted mipmap. There are enough mipmaps in the chain */
5635     while (i < level)
5636     {
5637         IDirectDrawSurface7 *attached;
5638         IDirectDrawSurface7_GetAttachedSurface((IDirectDrawSurface7 *)surf, &searchcaps, &attached);
5639         if(!attached) ERR("Surface not found\n");
5640         surf = (IDirectDrawSurfaceImpl *)attached;
5641         IDirectDrawSurface7_Release(attached);
5642         ++i;
5643     }
5644
5645     /* Return the surface */
5646     *surface = surf->WineD3DSurface;
5647     IWineD3DSurface_AddRef(*surface);
5648
5649     TRACE("Returning wineD3DSurface %p, it belongs to surface %p\n", *surface, surf);
5650
5651     return D3D_OK;
5652 }
5653
5654 static HRESULT WINAPI findRenderTarget(IDirectDrawSurface7 *surface, DDSURFACEDESC2 *surface_desc, void *ctx)
5655 {
5656     IDirectDrawSurfaceImpl *s = (IDirectDrawSurfaceImpl *)surface;
5657     IDirectDrawSurfaceImpl **target = ctx;
5658
5659     if (!s->isRenderTarget)
5660     {
5661         *target = s;
5662         IDirectDrawSurface7_Release(surface);
5663         return DDENUMRET_CANCEL;
5664     }
5665
5666     /* Recurse into the surface tree */
5667     IDirectDrawSurface7_EnumAttachedSurfaces(surface, ctx, findRenderTarget);
5668
5669     IDirectDrawSurface7_Release(surface);
5670     if (*target) return DDENUMRET_CANCEL;
5671
5672     return DDENUMRET_OK;
5673 }
5674
5675 static HRESULT STDMETHODCALLTYPE device_parent_CreateRenderTarget(IWineD3DDeviceParent *iface,
5676         IUnknown *superior, UINT width, UINT height, WINED3DFORMAT format, WINED3DMULTISAMPLE_TYPE multisample_type,
5677         DWORD multisample_quality, BOOL lockable, IWineD3DSurface **surface)
5678 {
5679     struct IDirectDrawImpl *This = ddraw_from_device_parent(iface);
5680     IDirectDrawSurfaceImpl *d3d_surface = This->d3d_target;
5681     IDirectDrawSurfaceImpl *target = NULL;
5682
5683     TRACE("iface %p, superior %p, width %u, height %u, format %#x, multisample_type %#x,\n"
5684             "\tmultisample_quality %u, lockable %u, surface %p\n",
5685             iface, superior, width, height, format, multisample_type, multisample_quality, lockable, surface);
5686
5687     if (d3d_surface->isRenderTarget)
5688     {
5689         IDirectDrawSurface7_EnumAttachedSurfaces((IDirectDrawSurface7 *)d3d_surface, &target, findRenderTarget);
5690     }
5691     else
5692     {
5693         target = d3d_surface;
5694     }
5695
5696     if (!target)
5697     {
5698         target = This->d3d_target;
5699         ERR(" (%p) : No DirectDrawSurface found to create the back buffer. Using the front buffer as back buffer. Uncertain consequences\n", This);
5700     }
5701
5702     /* TODO: Return failure if the dimensions do not match, but this shouldn't happen */
5703
5704     *surface = target->WineD3DSurface;
5705     IWineD3DSurface_AddRef(*surface);
5706     target->isRenderTarget = TRUE;
5707
5708     TRACE("Returning wineD3DSurface %p, it belongs to surface %p\n", *surface, d3d_surface);
5709
5710     return D3D_OK;
5711 }
5712
5713 static HRESULT STDMETHODCALLTYPE device_parent_CreateDepthStencilSurface(IWineD3DDeviceParent *iface,
5714         IUnknown *superior, UINT width, UINT height, WINED3DFORMAT format, WINED3DMULTISAMPLE_TYPE multisample_type,
5715         DWORD multisample_quality, BOOL discard, IWineD3DSurface **surface)
5716 {
5717     struct IDirectDrawImpl *This = ddraw_from_device_parent(iface);
5718     IDirectDrawSurfaceImpl *ddraw_surface;
5719     DDSURFACEDESC2 ddsd;
5720     HRESULT hr;
5721
5722     TRACE("iface %p, superior %p, width %u, height %u, format %#x, multisample_type %#x,\n"
5723             "\tmultisample_quality %u, discard %u, surface %p\n",
5724             iface, superior, width, height, format, multisample_type, multisample_quality, discard, surface);
5725
5726     *surface = NULL;
5727
5728     /* Create a DirectDraw surface */
5729     memset(&ddsd, 0, sizeof(ddsd));
5730     ddsd.dwSize = sizeof(ddsd);
5731     ddsd.u4.ddpfPixelFormat.dwSize = sizeof(DDPIXELFORMAT);
5732     ddsd.dwFlags = DDSD_PIXELFORMAT | DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS;
5733     ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
5734     ddsd.dwHeight = height;
5735     ddsd.dwWidth = width;
5736     if (format)
5737     {
5738         PixelFormat_WineD3DtoDD(&ddsd.u4.ddpfPixelFormat, format);
5739     }
5740     else
5741     {
5742         ddsd.dwFlags ^= DDSD_PIXELFORMAT;
5743     }
5744
5745     This->depthstencil = TRUE;
5746     hr = IDirectDraw7_CreateSurface((IDirectDraw7 *)This, &ddsd, (IDirectDrawSurface7 **)&ddraw_surface, NULL);
5747     This->depthstencil = FALSE;
5748     if(FAILED(hr))
5749     {
5750         ERR(" (%p) Creating a DepthStencil Surface failed, result = %x\n", This, hr);
5751         return hr;
5752     }
5753
5754     *surface = ddraw_surface->WineD3DSurface;
5755     IWineD3DSurface_AddRef(*surface);
5756     IDirectDrawSurface7_Release((IDirectDrawSurface7 *)ddraw_surface);
5757
5758     return D3D_OK;
5759 }
5760
5761 static HRESULT STDMETHODCALLTYPE device_parent_CreateVolume(IWineD3DDeviceParent *iface,
5762         IUnknown *superior, UINT width, UINT height, UINT depth, WINED3DFORMAT format,
5763         WINED3DPOOL pool, DWORD usage, IWineD3DVolume **volume)
5764 {
5765     TRACE("iface %p, superior %p, width %u, height %u, depth %u, format %#x, pool %#x, usage %#x, volume %p\n",
5766                 iface, superior, width, height, depth, format, pool, usage, volume);
5767
5768     ERR("Not implemented!\n");
5769
5770     return E_NOTIMPL;
5771 }
5772
5773 static HRESULT STDMETHODCALLTYPE device_parent_CreateSwapChain(IWineD3DDeviceParent *iface,
5774         WINED3DPRESENT_PARAMETERS *present_parameters, IWineD3DSwapChain **swapchain)
5775 {
5776     struct IDirectDrawImpl *This = ddraw_from_device_parent(iface);
5777     IDirectDrawSurfaceImpl *iterator;
5778     IParentImpl *object;
5779     HRESULT hr;
5780
5781     TRACE("iface %p, present_parameters %p, swapchain %p\n", iface, present_parameters, swapchain);
5782
5783     object = HeapAlloc(GetProcessHeap(),  HEAP_ZERO_MEMORY, sizeof(IParentImpl));
5784     if (!object)
5785     {
5786         FIXME("Allocation of memory failed\n");
5787         *swapchain = NULL;
5788         return DDERR_OUTOFVIDEOMEMORY;
5789     }
5790
5791     ddraw_parent_init(object);
5792
5793     hr = IWineD3DDevice_CreateSwapChain(This->wineD3DDevice, present_parameters,
5794             swapchain, (IUnknown *)object, This->ImplType);
5795     if (FAILED(hr))
5796     {
5797         FIXME("(%p) CreateSwapChain failed, returning %#x\n", iface, hr);
5798         HeapFree(GetProcessHeap(), 0 , object);
5799         *swapchain = NULL;
5800         return hr;
5801     }
5802
5803     object->child = (IUnknown *)*swapchain;
5804     This->d3d_target->wineD3DSwapChain = *swapchain;
5805     iterator = This->d3d_target->complex_array[0];
5806     while (iterator)
5807     {
5808         iterator->wineD3DSwapChain = *swapchain;
5809         iterator = iterator->complex_array[0];
5810     }
5811
5812     return hr;
5813 }
5814
5815 static const IWineD3DDeviceParentVtbl ddraw_wined3d_device_parent_vtbl =
5816 {
5817     /* IUnknown methods */
5818     device_parent_QueryInterface,
5819     device_parent_AddRef,
5820     device_parent_Release,
5821     /* IWineD3DDeviceParent methods */
5822     device_parent_WineD3DDeviceCreated,
5823     device_parent_CreateSurface,
5824     device_parent_CreateRenderTarget,
5825     device_parent_CreateDepthStencilSurface,
5826     device_parent_CreateVolume,
5827     device_parent_CreateSwapChain,
5828 };
5829
5830 HRESULT ddraw_init(IDirectDrawImpl *ddraw, WINED3DDEVTYPE device_type)
5831 {
5832     HRESULT hr;
5833     HDC hDC;
5834
5835     ddraw->lpVtbl = &ddraw7_vtbl;
5836     ddraw->IDirectDraw_vtbl = &ddraw1_vtbl;
5837     ddraw->IDirectDraw2_vtbl = &ddraw2_vtbl;
5838     ddraw->IDirectDraw3_vtbl = &ddraw3_vtbl;
5839     ddraw->IDirectDraw4_vtbl = &ddraw4_vtbl;
5840     ddraw->IDirect3D_vtbl = &d3d1_vtbl;
5841     ddraw->IDirect3D2_vtbl = &d3d2_vtbl;
5842     ddraw->IDirect3D3_vtbl = &d3d3_vtbl;
5843     ddraw->IDirect3D7_vtbl = &d3d7_vtbl;
5844     ddraw->device_parent_vtbl = &ddraw_wined3d_device_parent_vtbl;
5845     ddraw->numIfaces = 1;
5846     ddraw->ref7 = 1;
5847
5848     /* See comments in IDirectDrawImpl_CreateNewSurface for a description of
5849      * this field. */
5850     ddraw->ImplType = DefaultSurfaceType;
5851
5852     /* Get the current screen settings. */
5853     hDC = GetDC(0);
5854     ddraw->orig_bpp = GetDeviceCaps(hDC, BITSPIXEL) * GetDeviceCaps(hDC, PLANES);
5855     ReleaseDC(0, hDC);
5856     ddraw->orig_width = GetSystemMetrics(SM_CXSCREEN);
5857     ddraw->orig_height = GetSystemMetrics(SM_CYSCREEN);
5858
5859     if (!LoadWineD3D())
5860     {
5861         ERR("Failed to load wined3d - broken OpenGL setup?\n");
5862         return DDERR_NODIRECTDRAWSUPPORT;
5863     }
5864
5865     ddraw->wineD3D = pWineDirect3DCreate(7, (IUnknown *)ddraw);
5866     if (!ddraw->wineD3D)
5867     {
5868         WARN("Failed to create a wined3d object.\n");
5869         return E_OUTOFMEMORY;
5870     }
5871
5872     hr = IWineD3D_CreateDevice(ddraw->wineD3D, WINED3DADAPTER_DEFAULT, device_type, NULL, 0, (IUnknown *)ddraw,
5873             (IWineD3DDeviceParent *)&ddraw->device_parent_vtbl, &ddraw->wineD3DDevice);
5874     if (FAILED(hr))
5875     {
5876         WARN("Failed to create a wined3d device, hr %#x.\n", hr);
5877         IWineD3D_Release(ddraw->wineD3D);
5878         return hr;
5879     }
5880
5881     /* Get the amount of video memory */
5882     ddraw->total_vidmem = IWineD3DDevice_GetAvailableTextureMem(ddraw->wineD3DDevice);
5883
5884     list_init(&ddraw->surface_list);
5885
5886     return DD_OK;
5887 }