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