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