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