ddraw: Return DDERR_INVALIDPARAMS for 0 width / height surface creation.
[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     if (!desc2.dwWidth || !desc2.dwHeight)
3073     {
3074         LeaveCriticalSection(&ddraw_cs);
3075         return DDERR_INVALIDPARAMS;
3076     }
3077
3078     /* Mipmap count fixes */
3079     if(desc2.ddsCaps.dwCaps & DDSCAPS_MIPMAP)
3080     {
3081         if(desc2.ddsCaps.dwCaps & DDSCAPS_COMPLEX)
3082         {
3083             if(desc2.dwFlags & DDSD_MIPMAPCOUNT)
3084             {
3085                 /* Mipmap count is given, should not be 0 */
3086                 if( desc2.u2.dwMipMapCount == 0 )
3087                 {
3088                     LeaveCriticalSection(&ddraw_cs);
3089                     return DDERR_INVALIDPARAMS;
3090                 }
3091             }
3092             else
3093             {
3094                 /* Undocumented feature: Create sublevels until
3095                  * either the width or the height is 1
3096                  */
3097                 DWORD min = desc2.dwWidth < desc2.dwHeight ?
3098                             desc2.dwWidth : desc2.dwHeight;
3099                 desc2.u2.dwMipMapCount = 0;
3100                 while( min )
3101                 {
3102                     desc2.u2.dwMipMapCount += 1;
3103                     min >>= 1;
3104                 }
3105             }
3106         }
3107         else
3108         {
3109             /* Not-complex mipmap -> Mipmapcount = 1 */
3110             desc2.u2.dwMipMapCount = 1;
3111         }
3112         extra_surfaces = desc2.u2.dwMipMapCount - 1;
3113
3114         /* There's a mipmap count in the created surface in any case */
3115         desc2.dwFlags |= DDSD_MIPMAPCOUNT;
3116     }
3117     /* If no mipmap is given, the texture has only one level */
3118
3119     /* The first surface is a front buffer, the back buffer is created afterwards */
3120     if( (desc2.dwFlags & DDSD_CAPS) && (desc2.ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE) )
3121     {
3122         desc2.ddsCaps.dwCaps |= DDSCAPS_FRONTBUFFER;
3123     }
3124
3125     /* The root surface in a cube map is positive x */
3126     if(desc2.ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP)
3127     {
3128         desc2.ddsCaps.dwCaps2 &= ~DDSCAPS2_CUBEMAP_ALLFACES;
3129         desc2.ddsCaps.dwCaps2 |=  DDSCAPS2_CUBEMAP_POSITIVEX;
3130     }
3131
3132     /* Create the first surface */
3133     hr = ddraw_create_surface(This, &desc2, &object, 0);
3134     if (FAILED(hr))
3135     {
3136         WARN("ddraw_create_surface failed, hr %#x.\n", hr);
3137         LeaveCriticalSection(&ddraw_cs);
3138         return hr;
3139     }
3140     object->is_complex_root = TRUE;
3141
3142     *Surf = (IDirectDrawSurface7 *)object;
3143
3144     /* Create Additional surfaces if necessary
3145      * This applies to Primary surfaces which have a back buffer count
3146      * set, but not to mipmap textures. In case of Mipmap textures,
3147      * wineD3D takes care of the creation of additional surfaces
3148      */
3149     if(DDSD->dwFlags & DDSD_BACKBUFFERCOUNT)
3150     {
3151         extra_surfaces = DDSD->dwBackBufferCount;
3152         desc2.ddsCaps.dwCaps &= ~DDSCAPS_FRONTBUFFER; /* It's not a front buffer */
3153         desc2.ddsCaps.dwCaps |= DDSCAPS_BACKBUFFER;
3154         desc2.dwBackBufferCount = 0;
3155     }
3156
3157     hr = DD_OK;
3158     if(desc2.ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP)
3159     {
3160         desc2.ddsCaps.dwCaps2 &= ~DDSCAPS2_CUBEMAP_ALLFACES;
3161         desc2.ddsCaps.dwCaps2 |=  DDSCAPS2_CUBEMAP_NEGATIVEZ;
3162         hr |= CreateAdditionalSurfaces(This, object, extra_surfaces + 1, desc2, TRUE);
3163         desc2.ddsCaps.dwCaps2 &= ~DDSCAPS2_CUBEMAP_NEGATIVEZ;
3164         desc2.ddsCaps.dwCaps2 |=  DDSCAPS2_CUBEMAP_POSITIVEZ;
3165         hr |= CreateAdditionalSurfaces(This, object, extra_surfaces + 1, desc2, TRUE);
3166         desc2.ddsCaps.dwCaps2 &= ~DDSCAPS2_CUBEMAP_POSITIVEZ;
3167         desc2.ddsCaps.dwCaps2 |=  DDSCAPS2_CUBEMAP_NEGATIVEY;
3168         hr |= CreateAdditionalSurfaces(This, object, extra_surfaces + 1, desc2, TRUE);
3169         desc2.ddsCaps.dwCaps2 &= ~DDSCAPS2_CUBEMAP_NEGATIVEY;
3170         desc2.ddsCaps.dwCaps2 |=  DDSCAPS2_CUBEMAP_POSITIVEY;
3171         hr |= CreateAdditionalSurfaces(This, object, extra_surfaces + 1, desc2, TRUE);
3172         desc2.ddsCaps.dwCaps2 &= ~DDSCAPS2_CUBEMAP_POSITIVEY;
3173         desc2.ddsCaps.dwCaps2 |=  DDSCAPS2_CUBEMAP_NEGATIVEX;
3174         hr |= CreateAdditionalSurfaces(This, object, extra_surfaces + 1, desc2, TRUE);
3175         desc2.ddsCaps.dwCaps2 &= ~DDSCAPS2_CUBEMAP_NEGATIVEX;
3176         desc2.ddsCaps.dwCaps2 |=  DDSCAPS2_CUBEMAP_POSITIVEX;
3177     }
3178
3179     hr |= CreateAdditionalSurfaces(This, object, extra_surfaces, desc2, FALSE);
3180     if(hr != DD_OK)
3181     {
3182         /* This destroys and possibly created surfaces too */
3183         IDirectDrawSurface_Release((IDirectDrawSurface7 *)object);
3184         LeaveCriticalSection(&ddraw_cs);
3185         return hr;
3186     }
3187
3188     /* If the implementation is OpenGL and there's no d3ddevice, attach a d3ddevice
3189      * But attach the d3ddevice only if the currently created surface was
3190      * a primary surface (2D app in 3D mode) or a 3DDEVICE surface (3D app)
3191      * The only case I can think of where this doesn't apply is when a
3192      * 2D app was configured by the user to run with OpenGL and it didn't create
3193      * the render target as first surface. In this case the render target creation
3194      * will cause the 3D init.
3195      */
3196     if( (This->ImplType == SURFACE_OPENGL) && !(This->d3d_initialized) &&
3197         desc2.ddsCaps.dwCaps & (DDSCAPS_PRIMARYSURFACE | DDSCAPS_3DDEVICE) )
3198     {
3199         IDirectDrawSurfaceImpl *target = object, *surface;
3200         struct list *entry;
3201
3202         /* Search for the primary to use as render target */
3203         LIST_FOR_EACH(entry, &This->surface_list)
3204         {
3205             surface = LIST_ENTRY(entry, IDirectDrawSurfaceImpl, surface_list_entry);
3206             if((surface->surface_desc.ddsCaps.dwCaps & (DDSCAPS_PRIMARYSURFACE | DDSCAPS_FRONTBUFFER)) ==
3207                (DDSCAPS_PRIMARYSURFACE | DDSCAPS_FRONTBUFFER))
3208             {
3209                 /* found */
3210                 target = surface;
3211                 TRACE("Using primary %p as render target\n", target);
3212                 break;
3213             }
3214         }
3215
3216         TRACE("(%p) Attaching a D3DDevice, rendertarget = %p\n", This, target);
3217         hr = ddraw_attach_d3d_device(This, target);
3218         if (hr != D3D_OK)
3219         {
3220             IDirectDrawSurfaceImpl *release_surf;
3221             ERR("ddraw_attach_d3d_device failed, hr %#x\n", hr);
3222             *Surf = NULL;
3223
3224             /* The before created surface structures are in an incomplete state here.
3225              * WineD3D holds the reference on the IParents, and it released them on the failure
3226              * already. So the regular release method implementation would fail on the attempt
3227              * to destroy either the IParents or the swapchain. So free the surface here.
3228              * The surface structure here is a list, not a tree, because onscreen targets
3229              * cannot be cube textures
3230              */
3231             while(object)
3232             {
3233                 release_surf = object;
3234                 object = object->complex_array[0];
3235                 ddraw_surface_destroy(release_surf);
3236             }
3237             LeaveCriticalSection(&ddraw_cs);
3238             return hr;
3239         }
3240     }
3241     else if(!(This->d3d_initialized) && desc2.ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE)
3242     {
3243         ddraw_create_gdi_swapchain(This, object);
3244     }
3245
3246     /* Addref the ddraw interface to keep an reference for each surface */
3247     IDirectDraw7_AddRef(iface);
3248     object->ifaceToRelease = (IUnknown *) iface;
3249
3250     /* Create a WineD3DTexture if a texture was requested */
3251     if(desc2.ddsCaps.dwCaps & DDSCAPS_TEXTURE)
3252     {
3253         enum wined3d_format_id Format;
3254         UINT levels;
3255         WINED3DPOOL Pool = WINED3DPOOL_DEFAULT;
3256
3257         This->tex_root = object;
3258
3259         if(desc2.ddsCaps.dwCaps & DDSCAPS_MIPMAP)
3260         {
3261             /* a mipmap is created, create enough levels */
3262             levels = desc2.u2.dwMipMapCount;
3263         }
3264         else
3265         {
3266             /* No mipmap is created, create one level */
3267             levels = 1;
3268         }
3269
3270         /* DDSCAPS_SYSTEMMEMORY textures are in WINED3DPOOL_SYSTEMMEM */
3271         if(DDSD->ddsCaps.dwCaps & DDSCAPS_SYSTEMMEMORY)
3272         {
3273             Pool = WINED3DPOOL_SYSTEMMEM;
3274         }
3275         /* Should I forward the MANAGED cap to the managed pool ? */
3276
3277         /* Get the format. It's set already by CreateNewSurface */
3278         Format = PixelFormat_DD2WineD3D(&object->surface_desc.u4.ddpfPixelFormat);
3279
3280         /* The surfaces are already created, the callback only
3281          * passes the IWineD3DSurface to WineD3D
3282          */
3283         if(desc2.ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP)
3284         {
3285             hr = IWineD3DDevice_CreateCubeTexture(This->wineD3DDevice, DDSD->dwWidth /* Edgelength */, levels,
3286                     0 /* usage */, Format, Pool, object, &ddraw_null_wined3d_parent_ops,
3287                     (IWineD3DCubeTexture **)&object->wineD3DTexture);
3288         }
3289         else
3290         {
3291             hr = IWineD3DDevice_CreateTexture(This->wineD3DDevice, DDSD->dwWidth, DDSD->dwHeight, levels,
3292                     0 /* usage */, Format, Pool, object, &ddraw_null_wined3d_parent_ops,
3293                     (IWineD3DTexture **)&object->wineD3DTexture);
3294         }
3295         This->tex_root = NULL;
3296     }
3297
3298     LeaveCriticalSection(&ddraw_cs);
3299     return hr;
3300 }
3301
3302 static HRESULT WINAPI ddraw7_CreateSurface(IDirectDraw7 *iface,
3303         DDSURFACEDESC2 *surface_desc, IDirectDrawSurface7 **surface, IUnknown *outer_unknown)
3304 {
3305     TRACE("iface %p, surface_desc %p, surface %p, outer_unknown %p.\n",
3306             iface, surface_desc, surface, outer_unknown);
3307
3308     if(surface_desc == NULL || surface_desc->dwSize != sizeof(DDSURFACEDESC2))
3309     {
3310         WARN("Application supplied invalid surface descriptor\n");
3311         return DDERR_INVALIDPARAMS;
3312     }
3313
3314     if(surface_desc->ddsCaps.dwCaps & (DDSCAPS_FRONTBUFFER | DDSCAPS_BACKBUFFER))
3315     {
3316         if (TRACE_ON(ddraw))
3317         {
3318             TRACE(" (%p) Requesting surface desc :\n", iface);
3319             DDRAW_dump_surface_desc(surface_desc);
3320         }
3321
3322         WARN("Application tried to create an explicit front or back buffer\n");
3323         return DDERR_INVALIDCAPS;
3324     }
3325
3326     return CreateSurface(iface, surface_desc, surface, outer_unknown);
3327 }
3328
3329 static HRESULT WINAPI ddraw4_CreateSurface(IDirectDraw4 *iface,
3330         DDSURFACEDESC2 *surface_desc, IDirectDrawSurface4 **surface, IUnknown *outer_unknown)
3331 {
3332     IDirectDrawImpl *ddraw = ddraw_from_ddraw4(iface);
3333     IDirectDrawSurfaceImpl *impl;
3334     HRESULT hr;
3335
3336     TRACE("iface %p, surface_desc %p, surface %p, outer_unknown %p.\n",
3337             iface, surface_desc, surface, outer_unknown);
3338
3339     if(surface_desc == NULL || surface_desc->dwSize != sizeof(DDSURFACEDESC2))
3340     {
3341         WARN("Application supplied invalid surface descriptor\n");
3342         return DDERR_INVALIDPARAMS;
3343     }
3344
3345     if(surface_desc->ddsCaps.dwCaps & (DDSCAPS_FRONTBUFFER | DDSCAPS_BACKBUFFER))
3346     {
3347         if (TRACE_ON(ddraw))
3348         {
3349             TRACE(" (%p) Requesting surface desc :\n", iface);
3350             DDRAW_dump_surface_desc(surface_desc);
3351         }
3352
3353         WARN("Application tried to create an explicit front or back buffer\n");
3354         return DDERR_INVALIDCAPS;
3355     }
3356
3357     hr = CreateSurface((IDirectDraw7 *)ddraw, surface_desc, (IDirectDrawSurface7 **)surface, outer_unknown);
3358     impl = (IDirectDrawSurfaceImpl *)*surface;
3359     if (SUCCEEDED(hr) && impl)
3360     {
3361         ddraw_set_surface_version(impl, 4);
3362         IDirectDraw7_Release((IDirectDraw7 *)ddraw);
3363         IDirectDraw4_AddRef(iface);
3364         impl->ifaceToRelease = (IUnknown *)iface;
3365     }
3366
3367     return hr;
3368 }
3369
3370 static HRESULT WINAPI ddraw3_CreateSurface(IDirectDraw3 *iface,
3371         DDSURFACEDESC *surface_desc, IDirectDrawSurface **surface, IUnknown *outer_unknown)
3372 {
3373     IDirectDrawImpl *ddraw = ddraw_from_ddraw3(iface);
3374     IDirectDrawSurface7 *surface7;
3375     IDirectDrawSurfaceImpl *impl;
3376     HRESULT hr;
3377
3378     TRACE("iface %p, surface_desc %p, surface %p, outer_unknown %p.\n",
3379             iface, surface_desc, surface, outer_unknown);
3380
3381     if(surface_desc == NULL || surface_desc->dwSize != sizeof(DDSURFACEDESC))
3382     {
3383         WARN("Application supplied invalid surface descriptor\n");
3384         return DDERR_INVALIDPARAMS;
3385     }
3386
3387     if(surface_desc->ddsCaps.dwCaps & (DDSCAPS_FRONTBUFFER | DDSCAPS_BACKBUFFER))
3388     {
3389         if (TRACE_ON(ddraw))
3390         {
3391             TRACE(" (%p) Requesting surface desc :\n", iface);
3392             DDRAW_dump_surface_desc((LPDDSURFACEDESC2)surface_desc);
3393         }
3394
3395         WARN("Application tried to create an explicit front or back buffer\n");
3396         return DDERR_INVALIDCAPS;
3397     }
3398
3399     hr = CreateSurface((IDirectDraw7 *)ddraw, (DDSURFACEDESC2 *)surface_desc, &surface7, outer_unknown);
3400     if (FAILED(hr))
3401     {
3402         *surface = NULL;
3403         return hr;
3404     }
3405
3406     impl = (IDirectDrawSurfaceImpl *)surface7;
3407     *surface = (IDirectDrawSurface *)&impl->IDirectDrawSurface3_vtbl;
3408     ddraw_set_surface_version(impl, 3);
3409     IDirectDraw7_Release((IDirectDraw7 *)ddraw);
3410     IDirectDraw3_AddRef(iface);
3411     impl->ifaceToRelease = (IUnknown *)iface;
3412
3413     return hr;
3414 }
3415
3416 static HRESULT WINAPI ddraw2_CreateSurface(IDirectDraw2 *iface,
3417         DDSURFACEDESC *surface_desc, IDirectDrawSurface **surface, IUnknown *outer_unknown)
3418 {
3419     IDirectDrawImpl *ddraw = ddraw_from_ddraw2(iface);
3420     IDirectDrawSurface7 *surface7;
3421     IDirectDrawSurfaceImpl *impl;
3422     HRESULT hr;
3423
3424     TRACE("iface %p, surface_desc %p, surface %p, outer_unknown %p.\n",
3425             iface, surface_desc, surface, outer_unknown);
3426
3427     if(surface_desc == NULL || surface_desc->dwSize != sizeof(DDSURFACEDESC))
3428     {
3429         WARN("Application supplied invalid surface descriptor\n");
3430         return DDERR_INVALIDPARAMS;
3431     }
3432
3433     if(surface_desc->ddsCaps.dwCaps & (DDSCAPS_FRONTBUFFER | DDSCAPS_BACKBUFFER))
3434     {
3435         if (TRACE_ON(ddraw))
3436         {
3437             TRACE(" (%p) Requesting surface desc :\n", iface);
3438             DDRAW_dump_surface_desc((LPDDSURFACEDESC2)surface_desc);
3439         }
3440
3441         WARN("Application tried to create an explicit front or back buffer\n");
3442         return DDERR_INVALIDCAPS;
3443     }
3444
3445     hr = CreateSurface((IDirectDraw7 *)ddraw, (DDSURFACEDESC2 *)surface_desc, &surface7, outer_unknown);
3446     if (FAILED(hr))
3447     {
3448         *surface = NULL;
3449         return hr;
3450     }
3451
3452     impl = (IDirectDrawSurfaceImpl *)surface7;
3453     *surface = (IDirectDrawSurface *)&impl->IDirectDrawSurface3_vtbl;
3454     ddraw_set_surface_version(impl, 2);
3455     IDirectDraw7_Release((IDirectDraw7 *)ddraw);
3456     impl->ifaceToRelease = NULL;
3457
3458     return hr;
3459 }
3460
3461 static HRESULT WINAPI ddraw1_CreateSurface(IDirectDraw *iface,
3462         DDSURFACEDESC *surface_desc, IDirectDrawSurface **surface, IUnknown *outer_unknown)
3463 {
3464     IDirectDrawImpl *ddraw = ddraw_from_ddraw1(iface);
3465     IDirectDrawSurface7 *surface7;
3466     IDirectDrawSurfaceImpl *impl;
3467     HRESULT hr;
3468
3469     TRACE("iface %p, surface_desc %p, surface %p, outer_unknown %p.\n",
3470             iface, surface_desc, surface, outer_unknown);
3471
3472     if(surface_desc == NULL || surface_desc->dwSize != sizeof(DDSURFACEDESC))
3473     {
3474         WARN("Application supplied invalid surface descriptor\n");
3475         return DDERR_INVALIDPARAMS;
3476     }
3477
3478     /* Remove front buffer flag, this causes failure in v7, and its added to normal
3479      * primaries anyway. */
3480     surface_desc->ddsCaps.dwCaps &= ~DDSCAPS_FRONTBUFFER;
3481     hr = CreateSurface((IDirectDraw7 *)ddraw, (DDSURFACEDESC2 *)surface_desc, &surface7, outer_unknown);
3482     if (FAILED(hr))
3483     {
3484         *surface = NULL;
3485         return hr;
3486     }
3487
3488     impl = (IDirectDrawSurfaceImpl *)surface7;
3489     *surface = (IDirectDrawSurface *)&impl->IDirectDrawSurface3_vtbl;
3490     ddraw_set_surface_version(impl, 1);
3491     IDirectDraw7_Release((IDirectDraw7 *)ddraw);
3492     impl->ifaceToRelease = NULL;
3493
3494     return hr;
3495 }
3496
3497 #define DDENUMSURFACES_SEARCHTYPE (DDENUMSURFACES_CANBECREATED|DDENUMSURFACES_DOESEXIST)
3498 #define DDENUMSURFACES_MATCHTYPE (DDENUMSURFACES_ALL|DDENUMSURFACES_MATCH|DDENUMSURFACES_NOMATCH)
3499
3500 static BOOL
3501 Main_DirectDraw_DDPIXELFORMAT_Match(const DDPIXELFORMAT *requested,
3502                                     const DDPIXELFORMAT *provided)
3503 {
3504     /* Some flags must be present in both or neither for a match. */
3505     static const DWORD must_match = DDPF_PALETTEINDEXED1 | DDPF_PALETTEINDEXED2
3506         | DDPF_PALETTEINDEXED4 | DDPF_PALETTEINDEXED8 | DDPF_FOURCC
3507         | DDPF_ZBUFFER | DDPF_STENCILBUFFER;
3508
3509     if ((requested->dwFlags & provided->dwFlags) != requested->dwFlags)
3510         return FALSE;
3511
3512     if ((requested->dwFlags & must_match) != (provided->dwFlags & must_match))
3513         return FALSE;
3514
3515     if (requested->dwFlags & DDPF_FOURCC)
3516         if (requested->dwFourCC != provided->dwFourCC)
3517             return FALSE;
3518
3519     if (requested->dwFlags & (DDPF_RGB|DDPF_YUV|DDPF_ZBUFFER|DDPF_ALPHA
3520                               |DDPF_LUMINANCE|DDPF_BUMPDUDV))
3521         if (requested->u1.dwRGBBitCount != provided->u1.dwRGBBitCount)
3522             return FALSE;
3523
3524     if (requested->dwFlags & (DDPF_RGB|DDPF_YUV|DDPF_STENCILBUFFER
3525                               |DDPF_LUMINANCE|DDPF_BUMPDUDV))
3526         if (requested->u2.dwRBitMask != provided->u2.dwRBitMask)
3527             return FALSE;
3528
3529     if (requested->dwFlags & (DDPF_RGB|DDPF_YUV|DDPF_ZBUFFER|DDPF_BUMPDUDV))
3530         if (requested->u3.dwGBitMask != provided->u3.dwGBitMask)
3531             return FALSE;
3532
3533     /* I could be wrong about the bumpmapping. MSDN docs are vague. */
3534     if (requested->dwFlags & (DDPF_RGB|DDPF_YUV|DDPF_STENCILBUFFER
3535                               |DDPF_BUMPDUDV))
3536         if (requested->u4.dwBBitMask != provided->u4.dwBBitMask)
3537             return FALSE;
3538
3539     if (requested->dwFlags & (DDPF_ALPHAPIXELS|DDPF_ZPIXELS))
3540         if (requested->u5.dwRGBAlphaBitMask != provided->u5.dwRGBAlphaBitMask)
3541             return FALSE;
3542
3543     return TRUE;
3544 }
3545
3546 static BOOL ddraw_match_surface_desc(const DDSURFACEDESC2 *requested, const DDSURFACEDESC2 *provided)
3547 {
3548     struct compare_info
3549     {
3550         DWORD flag;
3551         ptrdiff_t offset;
3552         size_t size;
3553     };
3554
3555 #define CMP(FLAG, FIELD)                                \
3556         { DDSD_##FLAG, offsetof(DDSURFACEDESC2, FIELD), \
3557           sizeof(((DDSURFACEDESC2 *)(NULL))->FIELD) }
3558
3559     static const struct compare_info compare[] =
3560     {
3561         CMP(ALPHABITDEPTH, dwAlphaBitDepth),
3562         CMP(BACKBUFFERCOUNT, dwBackBufferCount),
3563         CMP(CAPS, ddsCaps),
3564         CMP(CKDESTBLT, ddckCKDestBlt),
3565         CMP(CKDESTOVERLAY, u3 /* ddckCKDestOverlay */),
3566         CMP(CKSRCBLT, ddckCKSrcBlt),
3567         CMP(CKSRCOVERLAY, ddckCKSrcOverlay),
3568         CMP(HEIGHT, dwHeight),
3569         CMP(LINEARSIZE, u1 /* dwLinearSize */),
3570         CMP(LPSURFACE, lpSurface),
3571         CMP(MIPMAPCOUNT, u2 /* dwMipMapCount */),
3572         CMP(PITCH, u1 /* lPitch */),
3573         /* PIXELFORMAT: manual */
3574         CMP(REFRESHRATE, u2 /* dwRefreshRate */),
3575         CMP(TEXTURESTAGE, dwTextureStage),
3576         CMP(WIDTH, dwWidth),
3577         /* ZBUFFERBITDEPTH: "obsolete" */
3578     };
3579
3580 #undef CMP
3581
3582     unsigned int i;
3583
3584     if ((requested->dwFlags & provided->dwFlags) != requested->dwFlags)
3585         return FALSE;
3586
3587     for (i=0; i < sizeof(compare)/sizeof(compare[0]); i++)
3588     {
3589         if (requested->dwFlags & compare[i].flag
3590             && memcmp((const char *)provided + compare[i].offset,
3591                       (const char *)requested + compare[i].offset,
3592                       compare[i].size) != 0)
3593             return FALSE;
3594     }
3595
3596     if (requested->dwFlags & DDSD_PIXELFORMAT)
3597     {
3598         if (!Main_DirectDraw_DDPIXELFORMAT_Match(&requested->u4.ddpfPixelFormat,
3599                                                 &provided->u4.ddpfPixelFormat))
3600             return FALSE;
3601     }
3602
3603     return TRUE;
3604 }
3605
3606 #undef DDENUMSURFACES_SEARCHTYPE
3607 #undef DDENUMSURFACES_MATCHTYPE
3608
3609 struct surfacescallback_context
3610 {
3611     LPDDENUMSURFACESCALLBACK func;
3612     void *context;
3613 };
3614
3615 static HRESULT CALLBACK EnumSurfacesCallbackThunk(IDirectDrawSurface7 *surface,
3616         DDSURFACEDESC2 *surface_desc, void *context)
3617 {
3618     struct surfacescallback_context *cbcontext = context;
3619
3620     return cbcontext->func((IDirectDrawSurface *)&((IDirectDrawSurfaceImpl *)surface)->IDirectDrawSurface3_vtbl,
3621             (DDSURFACEDESC *)surface_desc, cbcontext->context);
3622 }
3623
3624 /*****************************************************************************
3625  * IDirectDraw7::EnumSurfaces
3626  *
3627  * Loops through all surfaces attached to this device and calls the
3628  * application callback. This can't be relayed to WineD3DDevice,
3629  * because some WineD3DSurfaces' parents are IParent objects
3630  *
3631  * Params:
3632  *  Flags: Some filtering flags. See IDirectDrawImpl_EnumSurfacesCallback
3633  *  DDSD: Description to filter for
3634  *  Context: Application-provided pointer, it's passed unmodified to the
3635  *           Callback function
3636  *  Callback: Address to call for each surface
3637  *
3638  * Returns:
3639  *  DDERR_INVALIDPARAMS if the callback is NULL
3640  *  DD_OK on success
3641  *
3642  *****************************************************************************/
3643 static HRESULT WINAPI ddraw7_EnumSurfaces(IDirectDraw7 *iface, DWORD Flags,
3644         DDSURFACEDESC2 *DDSD, void *Context, LPDDENUMSURFACESCALLBACK7 Callback)
3645 {
3646     /* The surface enumeration is handled by WineDDraw,
3647      * because it keeps track of all surfaces attached to
3648      * it. The filtering is done by our callback function,
3649      * because WineDDraw doesn't handle ddraw-like surface
3650      * caps structures
3651      */
3652     IDirectDrawImpl *This = (IDirectDrawImpl *)iface;
3653     IDirectDrawSurfaceImpl *surf;
3654     BOOL all, nomatch;
3655     DDSURFACEDESC2 desc;
3656     struct list *entry, *entry2;
3657
3658     TRACE("iface %p, flags %#x, surface_desc %p, context %p, callback %p.\n",
3659             iface, Flags, DDSD, Context, Callback);
3660
3661     all = Flags & DDENUMSURFACES_ALL;
3662     nomatch = Flags & DDENUMSURFACES_NOMATCH;
3663
3664     EnterCriticalSection(&ddraw_cs);
3665
3666     if(!Callback)
3667     {
3668         LeaveCriticalSection(&ddraw_cs);
3669         return DDERR_INVALIDPARAMS;
3670     }
3671
3672     /* Use the _SAFE enumeration, the app may destroy enumerated surfaces */
3673     LIST_FOR_EACH_SAFE(entry, entry2, &This->surface_list)
3674     {
3675         surf = LIST_ENTRY(entry, IDirectDrawSurfaceImpl, surface_list_entry);
3676         if (all || (nomatch != ddraw_match_surface_desc(DDSD, &surf->surface_desc)))
3677         {
3678             desc = surf->surface_desc;
3679             IDirectDrawSurface7_AddRef((IDirectDrawSurface7 *)surf);
3680             if (Callback((IDirectDrawSurface7 *)surf, &desc, Context) != DDENUMRET_OK)
3681             {
3682                 LeaveCriticalSection(&ddraw_cs);
3683                 return DD_OK;
3684             }
3685         }
3686     }
3687     LeaveCriticalSection(&ddraw_cs);
3688     return DD_OK;
3689 }
3690
3691 static HRESULT WINAPI ddraw4_EnumSurfaces(IDirectDraw4 *iface, DWORD flags,
3692         DDSURFACEDESC2 *surface_desc, void *context, LPDDENUMSURFACESCALLBACK2 callback)
3693 {
3694     TRACE("iface %p, flags %#x, surface_desc %p, context %p, callback %p.\n",
3695             iface, flags, surface_desc, context, callback);
3696
3697     return ddraw7_EnumSurfaces((IDirectDraw7 *)ddraw_from_ddraw4(iface),
3698             flags, surface_desc, context, (LPDDENUMSURFACESCALLBACK7)callback);
3699 }
3700
3701 static HRESULT WINAPI ddraw3_EnumSurfaces(IDirectDraw3 *iface, DWORD flags,
3702         DDSURFACEDESC *surface_desc, void *context, LPDDENUMSURFACESCALLBACK callback)
3703 {
3704     struct surfacescallback_context cbcontext;
3705
3706     TRACE("iface %p, flags %#x, surface_desc %p, context %p, callback %p.\n",
3707             iface, flags, surface_desc, context, callback);
3708
3709     cbcontext.func = callback;
3710     cbcontext.context = context;
3711
3712     return ddraw7_EnumSurfaces((IDirectDraw7 *)ddraw_from_ddraw3(iface), flags,
3713             (DDSURFACEDESC2 *)surface_desc, &cbcontext, EnumSurfacesCallbackThunk);
3714 }
3715
3716 static HRESULT WINAPI ddraw2_EnumSurfaces(IDirectDraw2 *iface, DWORD flags,
3717         DDSURFACEDESC *surface_desc, void *context, LPDDENUMSURFACESCALLBACK callback)
3718 {
3719     struct surfacescallback_context cbcontext;
3720
3721     TRACE("iface %p, flags %#x, surface_desc %p, context %p, callback %p.\n",
3722             iface, flags, surface_desc, context, callback);
3723
3724     cbcontext.func = callback;
3725     cbcontext.context = context;
3726
3727     return ddraw7_EnumSurfaces((IDirectDraw7 *)ddraw_from_ddraw2(iface), flags,
3728             (DDSURFACEDESC2 *)surface_desc, &cbcontext, EnumSurfacesCallbackThunk);
3729 }
3730
3731 static HRESULT WINAPI ddraw1_EnumSurfaces(IDirectDraw *iface, DWORD flags,
3732         DDSURFACEDESC *surface_desc, void *context, LPDDENUMSURFACESCALLBACK callback)
3733 {
3734     struct surfacescallback_context cbcontext;
3735
3736     TRACE("iface %p, flags %#x, surface_desc %p, context %p, callback %p.\n",
3737             iface, flags, surface_desc, context, callback);
3738
3739     cbcontext.func = callback;
3740     cbcontext.context = context;
3741
3742     return ddraw7_EnumSurfaces((IDirectDraw7 *)ddraw_from_ddraw1(iface), flags,
3743             (DDSURFACEDESC2 *)surface_desc, &cbcontext, EnumSurfacesCallbackThunk);
3744 }
3745
3746 /*****************************************************************************
3747  * DirectDrawCreateClipper (DDRAW.@)
3748  *
3749  * Creates a new IDirectDrawClipper object.
3750  *
3751  * Params:
3752  *  Clipper: Address to write the interface pointer to
3753  *  UnkOuter: For aggregation support, which ddraw doesn't have. Has to be
3754  *            NULL
3755  *
3756  * Returns:
3757  *  CLASS_E_NOAGGREGATION if UnkOuter != NULL
3758  *  E_OUTOFMEMORY if allocating the object failed
3759  *
3760  *****************************************************************************/
3761 HRESULT WINAPI
3762 DirectDrawCreateClipper(DWORD Flags,
3763                         LPDIRECTDRAWCLIPPER *Clipper,
3764                         IUnknown *UnkOuter)
3765 {
3766     IDirectDrawClipperImpl* object;
3767     HRESULT hr;
3768
3769     TRACE("flags %#x, clipper %p, outer_unknown %p.\n",
3770             Flags, Clipper, UnkOuter);
3771
3772     EnterCriticalSection(&ddraw_cs);
3773     if (UnkOuter != NULL)
3774     {
3775         LeaveCriticalSection(&ddraw_cs);
3776         return CLASS_E_NOAGGREGATION;
3777     }
3778
3779     if (!LoadWineD3D())
3780     {
3781         LeaveCriticalSection(&ddraw_cs);
3782         return DDERR_NODIRECTDRAWSUPPORT;
3783     }
3784
3785     object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
3786                      sizeof(IDirectDrawClipperImpl));
3787     if (object == NULL)
3788     {
3789         LeaveCriticalSection(&ddraw_cs);
3790         return E_OUTOFMEMORY;
3791     }
3792
3793     hr = ddraw_clipper_init(object);
3794     if (FAILED(hr))
3795     {
3796         WARN("Failed to initialize clipper, hr %#x.\n", hr);
3797         HeapFree(GetProcessHeap(), 0, object);
3798         LeaveCriticalSection(&ddraw_cs);
3799         return hr;
3800     }
3801
3802     TRACE("Created clipper %p.\n", object);
3803     *Clipper = (IDirectDrawClipper *) object;
3804     LeaveCriticalSection(&ddraw_cs);
3805     return DD_OK;
3806 }
3807
3808 /*****************************************************************************
3809  * IDirectDraw7::CreateClipper
3810  *
3811  * Creates a DDraw clipper. See DirectDrawCreateClipper for details
3812  *
3813  *****************************************************************************/
3814 static HRESULT WINAPI ddraw7_CreateClipper(IDirectDraw7 *iface, DWORD Flags,
3815         IDirectDrawClipper **Clipper, IUnknown *UnkOuter)
3816 {
3817     TRACE("iface %p, flags %#x, clipper %p, outer_unknown %p.\n",
3818             iface, Flags, Clipper, UnkOuter);
3819
3820     return DirectDrawCreateClipper(Flags, Clipper, UnkOuter);
3821 }
3822
3823 static HRESULT WINAPI ddraw4_CreateClipper(IDirectDraw4 *iface,
3824         DWORD flags, IDirectDrawClipper **clipper, IUnknown *outer_unknown)
3825 {
3826     TRACE("iface %p, flags %#x, clipper %p, outer_unknown %p.\n",
3827             iface, flags, clipper, outer_unknown);
3828
3829     return ddraw7_CreateClipper((IDirectDraw7 *)ddraw_from_ddraw4(iface), flags, clipper, outer_unknown);
3830 }
3831
3832 static HRESULT WINAPI ddraw3_CreateClipper(IDirectDraw3 *iface,
3833         DWORD flags, IDirectDrawClipper **clipper, IUnknown *outer_unknown)
3834 {
3835     TRACE("iface %p, flags %#x, clipper %p, outer_unknown %p.\n",
3836             iface, flags, clipper, outer_unknown);
3837
3838     return ddraw7_CreateClipper((IDirectDraw7 *)ddraw_from_ddraw3(iface), flags, clipper, outer_unknown);
3839 }
3840
3841 static HRESULT WINAPI ddraw2_CreateClipper(IDirectDraw2 *iface,
3842         DWORD flags, IDirectDrawClipper **clipper, IUnknown *outer_unknown)
3843 {
3844     TRACE("iface %p, flags %#x, clipper %p, outer_unknown %p.\n",
3845             iface, flags, clipper, outer_unknown);
3846
3847     return ddraw7_CreateClipper((IDirectDraw7 *)ddraw_from_ddraw2(iface), flags, clipper, outer_unknown);
3848 }
3849
3850 static HRESULT WINAPI ddraw1_CreateClipper(IDirectDraw *iface,
3851         DWORD flags, IDirectDrawClipper **clipper, IUnknown *outer_unknown)
3852 {
3853     TRACE("iface %p, flags %#x, clipper %p, outer_unknown %p.\n",
3854             iface, flags, clipper, outer_unknown);
3855
3856     return ddraw7_CreateClipper((IDirectDraw7 *)ddraw_from_ddraw1(iface), flags, clipper, outer_unknown);
3857 }
3858
3859 /*****************************************************************************
3860  * IDirectDraw7::CreatePalette
3861  *
3862  * Creates a new IDirectDrawPalette object
3863  *
3864  * Params:
3865  *  Flags: The flags for the new clipper
3866  *  ColorTable: Color table to assign to the new clipper
3867  *  Palette: Address to write the interface pointer to
3868  *  UnkOuter: For aggregation support, which ddraw doesn't have. Has to be
3869  *            NULL
3870  *
3871  * Returns:
3872  *  CLASS_E_NOAGGREGATION if UnkOuter != NULL
3873  *  E_OUTOFMEMORY if allocating the object failed
3874  *
3875  *****************************************************************************/
3876 static HRESULT WINAPI ddraw7_CreatePalette(IDirectDraw7 *iface, DWORD Flags,
3877         PALETTEENTRY *ColorTable, IDirectDrawPalette **Palette, IUnknown *pUnkOuter)
3878 {
3879     IDirectDrawImpl *This = (IDirectDrawImpl *)iface;
3880     IDirectDrawPaletteImpl *object;
3881     HRESULT hr;
3882
3883     TRACE("iface %p, flags %#x, color_table %p, palette %p, outer_unknown %p.\n",
3884             iface, Flags, ColorTable, Palette, pUnkOuter);
3885
3886     EnterCriticalSection(&ddraw_cs);
3887     if(pUnkOuter != NULL)
3888     {
3889         WARN("pUnkOuter is %p, returning CLASS_E_NOAGGREGATION\n", pUnkOuter);
3890         LeaveCriticalSection(&ddraw_cs);
3891         return CLASS_E_NOAGGREGATION;
3892     }
3893
3894     /* The refcount test shows that a cooplevel is required for this */
3895     if(!This->cooperative_level)
3896     {
3897         WARN("No cooperative level set, returning DDERR_NOCOOPERATIVELEVELSET\n");
3898         LeaveCriticalSection(&ddraw_cs);
3899         return DDERR_NOCOOPERATIVELEVELSET;
3900     }
3901
3902     object = HeapAlloc(GetProcessHeap(), 0, sizeof(IDirectDrawPaletteImpl));
3903     if(!object)
3904     {
3905         ERR("Out of memory when allocating memory for a palette implementation\n");
3906         LeaveCriticalSection(&ddraw_cs);
3907         return E_OUTOFMEMORY;
3908     }
3909
3910     hr = ddraw_palette_init(object, This, Flags, ColorTable);
3911     if (FAILED(hr))
3912     {
3913         WARN("Failed to initialize palette, hr %#x.\n", hr);
3914         HeapFree(GetProcessHeap(), 0, object);
3915         LeaveCriticalSection(&ddraw_cs);
3916         return hr;
3917     }
3918
3919     TRACE("Created palette %p.\n", object);
3920     *Palette = (IDirectDrawPalette *)object;
3921     LeaveCriticalSection(&ddraw_cs);
3922     return DD_OK;
3923 }
3924
3925 static HRESULT WINAPI ddraw4_CreatePalette(IDirectDraw4 *iface, DWORD flags,
3926         PALETTEENTRY *entries, IDirectDrawPalette **palette, IUnknown *outer_unknown)
3927 {
3928     IDirectDrawImpl *ddraw = ddraw_from_ddraw4(iface);
3929     HRESULT hr;
3930
3931     TRACE("iface %p, flags %#x, entries %p, palette %p, outer_unknown %p.\n",
3932             iface, flags, entries, palette, outer_unknown);
3933
3934     hr = ddraw7_CreatePalette((IDirectDraw7 *)ddraw, flags, entries, palette, outer_unknown);
3935     if (SUCCEEDED(hr) && *palette)
3936     {
3937         IDirectDrawPaletteImpl *impl = (IDirectDrawPaletteImpl *)*palette;
3938         IDirectDraw7_Release((IDirectDraw7 *)ddraw);
3939         IDirectDraw4_AddRef(iface);
3940         impl->ifaceToRelease = (IUnknown *)iface;
3941     }
3942     return hr;
3943 }
3944
3945 static HRESULT WINAPI ddraw3_CreatePalette(IDirectDraw3 *iface, DWORD flags,
3946         PALETTEENTRY *entries, IDirectDrawPalette **palette, IUnknown *outer_unknown)
3947 {
3948     IDirectDrawImpl *ddraw = ddraw_from_ddraw3(iface);
3949     HRESULT hr;
3950
3951     TRACE("iface %p, flags %#x, entries %p, palette %p, outer_unknown %p.\n",
3952             iface, flags, entries, palette, outer_unknown);
3953
3954     hr = ddraw7_CreatePalette((IDirectDraw7 *)ddraw, flags, entries, palette, outer_unknown);
3955     if (SUCCEEDED(hr) && *palette)
3956     {
3957         IDirectDrawPaletteImpl *impl = (IDirectDrawPaletteImpl *)*palette;
3958         IDirectDraw7_Release((IDirectDraw7 *)ddraw);
3959         IDirectDraw4_AddRef(iface);
3960         impl->ifaceToRelease = (IUnknown *)iface;
3961     }
3962
3963     return hr;
3964 }
3965
3966 static HRESULT WINAPI ddraw2_CreatePalette(IDirectDraw2 *iface, DWORD flags,
3967         PALETTEENTRY *entries, IDirectDrawPalette **palette, IUnknown *outer_unknown)
3968 {
3969     IDirectDrawImpl *ddraw = ddraw_from_ddraw2(iface);
3970     HRESULT hr;
3971
3972     TRACE("iface %p, flags %#x, entries %p, palette %p, outer_unknown %p.\n",
3973             iface, flags, entries, palette, outer_unknown);
3974
3975     hr = ddraw7_CreatePalette((IDirectDraw7 *)ddraw, flags, entries, palette, outer_unknown);
3976     if (SUCCEEDED(hr) && *palette)
3977     {
3978         IDirectDrawPaletteImpl *impl = (IDirectDrawPaletteImpl *)*palette;
3979         IDirectDraw7_Release((IDirectDraw7 *)ddraw);
3980         impl->ifaceToRelease = NULL;
3981     }
3982
3983     return hr;
3984 }
3985
3986 static HRESULT WINAPI ddraw1_CreatePalette(IDirectDraw *iface, DWORD flags,
3987         PALETTEENTRY *entries, IDirectDrawPalette **palette, IUnknown *outer_unknown)
3988 {
3989     IDirectDrawImpl *ddraw = ddraw_from_ddraw1(iface);
3990     HRESULT hr;
3991
3992     TRACE("iface %p, flags %#x, entries %p, palette %p, outer_unknown %p.\n",
3993             iface, flags, entries, palette, outer_unknown);
3994
3995     hr = ddraw7_CreatePalette((IDirectDraw7 *)ddraw, flags, entries, palette, outer_unknown);
3996     if (SUCCEEDED(hr) && *palette)
3997     {
3998         IDirectDrawPaletteImpl *impl = (IDirectDrawPaletteImpl *)*palette;
3999         IDirectDraw7_Release((IDirectDraw7 *)ddraw);
4000         impl->ifaceToRelease = NULL;
4001     }
4002
4003     return hr;
4004 }
4005
4006 /*****************************************************************************
4007  * IDirectDraw7::DuplicateSurface
4008  *
4009  * Duplicates a surface. The surface memory points to the same memory as
4010  * the original surface, and it's released when the last surface referencing
4011  * it is released. I guess that's beyond Wine's surface management right now
4012  * (Idea: create a new DDraw surface with the same WineD3DSurface. I need a
4013  * test application to implement this)
4014  *
4015  * Params:
4016  *  Src: Address of the source surface
4017  *  Dest: Address to write the new surface pointer to
4018  *
4019  * Returns:
4020  *  See IDirectDraw7::CreateSurface
4021  *
4022  *****************************************************************************/
4023 static HRESULT WINAPI ddraw7_DuplicateSurface(IDirectDraw7 *iface,
4024         IDirectDrawSurface7 *Src, IDirectDrawSurface7 **Dest)
4025 {
4026     IDirectDrawSurfaceImpl *Surf = (IDirectDrawSurfaceImpl *)Src;
4027
4028     FIXME("iface %p, src %p, dst %p partial stub!\n", iface, Src, Dest);
4029
4030     /* For now, simply create a new, independent surface */
4031     return IDirectDraw7_CreateSurface(iface,
4032                                       &Surf->surface_desc,
4033                                       Dest,
4034                                       NULL);
4035 }
4036
4037 static HRESULT WINAPI ddraw4_DuplicateSurface(IDirectDraw4 *iface,
4038         IDirectDrawSurface4 *src, IDirectDrawSurface4 **dst)
4039 {
4040     TRACE("iface %p, src %p, dst %p.\n", iface, src, dst);
4041
4042     return ddraw7_DuplicateSurface((IDirectDraw7 *)ddraw_from_ddraw4(iface),
4043             (IDirectDrawSurface7 *)src, (IDirectDrawSurface7 **)dst);
4044 }
4045
4046 static HRESULT WINAPI ddraw3_DuplicateSurface(IDirectDraw3 *iface,
4047         IDirectDrawSurface *src, IDirectDrawSurface **dst)
4048 {
4049     IDirectDrawSurface7 *src7, *dst7;
4050     HRESULT hr;
4051
4052     TRACE("iface %p, src %p, dst %p.\n", iface, src, dst);
4053     src7 = (IDirectDrawSurface7 *)surface_from_surface3((IDirectDrawSurface3 *)src);
4054     hr = ddraw7_DuplicateSurface((IDirectDraw7 *)ddraw_from_ddraw3(iface), src7, &dst7);
4055     if (FAILED(hr))
4056         return hr;
4057     *dst = (IDirectDrawSurface *)&((IDirectDrawSurfaceImpl *)dst7)->IDirectDrawSurface3_vtbl;
4058     return hr;
4059 }
4060
4061 static HRESULT WINAPI ddraw2_DuplicateSurface(IDirectDraw2 *iface,
4062         IDirectDrawSurface *src, IDirectDrawSurface **dst)
4063 {
4064     IDirectDrawSurface7 *src7, *dst7;
4065     HRESULT hr;
4066
4067     TRACE("iface %p, src %p, dst %p.\n", iface, src, dst);
4068     src7 = (IDirectDrawSurface7 *)surface_from_surface3((IDirectDrawSurface3 *)src);
4069     hr = ddraw7_DuplicateSurface((IDirectDraw7 *)ddraw_from_ddraw2(iface), src7, &dst7);
4070     if (FAILED(hr))
4071         return hr;
4072     *dst = (IDirectDrawSurface *)&((IDirectDrawSurfaceImpl *)dst7)->IDirectDrawSurface3_vtbl;
4073     return hr;
4074 }
4075
4076 static HRESULT WINAPI ddraw1_DuplicateSurface(IDirectDraw *iface,
4077         IDirectDrawSurface *src, IDirectDrawSurface **dst)
4078 {
4079     IDirectDrawSurface7 *src7, *dst7;
4080     HRESULT hr;
4081
4082     TRACE("iface %p, src %p, dst %p.\n", iface, src, dst);
4083     src7 = (IDirectDrawSurface7 *)surface_from_surface3((IDirectDrawSurface3 *)src);
4084     hr = ddraw7_DuplicateSurface((IDirectDraw7 *)ddraw_from_ddraw1(iface), src7, &dst7);
4085     if (FAILED(hr))
4086         return hr;
4087     *dst = (IDirectDrawSurface *)&((IDirectDrawSurfaceImpl *)dst7)->IDirectDrawSurface3_vtbl;
4088     return hr;
4089 }
4090
4091 /*****************************************************************************
4092  * IDirect3D7::EnumDevices
4093  *
4094  * The EnumDevices method for IDirect3D7. It enumerates all supported
4095  * D3D7 devices. Currently the T&L, HAL and RGB devices are enumerated.
4096  *
4097  * Params:
4098  *  callback: Function to call for each enumerated device
4099  *  context: Pointer to pass back to the app
4100  *
4101  * Returns:
4102  *  D3D_OK, or the return value of the GetCaps call
4103  *
4104  *****************************************************************************/
4105 static HRESULT WINAPI d3d7_EnumDevices(IDirect3D7 *iface, LPD3DENUMDEVICESCALLBACK7 callback, void *context)
4106 {
4107     char interface_name_tnl[] = "WINE Direct3D7 Hardware Transform and Lighting acceleration using WineD3D";
4108     char device_name_tnl[] = "Wine D3D7 T&L HAL";
4109     char interface_name_hal[] = "WINE Direct3D7 Hardware acceleration using WineD3D";
4110     char device_name_hal[] = "Wine D3D7 HAL";
4111     char interface_name_rgb[] = "WINE Direct3D7 RGB Software Emulation using WineD3D";
4112     char device_name_rgb[] = "Wine D3D7 RGB";
4113
4114     IDirectDrawImpl *ddraw = ddraw_from_d3d7(iface);
4115     D3DDEVICEDESC7 device_desc7;
4116     D3DDEVICEDESC device_desc1;
4117     HRESULT hr;
4118
4119     TRACE("iface %p, callback %p, context %p.\n", iface, callback, context);
4120
4121     EnterCriticalSection(&ddraw_cs);
4122
4123     hr = IDirect3DImpl_GetCaps(ddraw->wineD3D, &device_desc1, &device_desc7);
4124     if (hr != D3D_OK)
4125     {
4126         LeaveCriticalSection(&ddraw_cs);
4127         return hr;
4128     }
4129     callback(interface_name_tnl, device_name_tnl, &device_desc7, context);
4130
4131     device_desc7.deviceGUID = IID_IDirect3DHALDevice;
4132     callback(interface_name_hal, device_name_hal, &device_desc7, context);
4133
4134     device_desc7.deviceGUID = IID_IDirect3DRGBDevice;
4135     callback(interface_name_rgb, device_name_rgb, &device_desc7, context);
4136
4137     TRACE("End of enumeration.\n");
4138
4139     LeaveCriticalSection(&ddraw_cs);
4140
4141     return D3D_OK;
4142 }
4143
4144 /*****************************************************************************
4145  * IDirect3D3::EnumDevices
4146  *
4147  * Enumerates all supported Direct3DDevice interfaces. This is the
4148  * implementation for Direct3D 1 to Direc3D 3, Version 7 has its own.
4149  *
4150  * Version 1, 2 and 3
4151  *
4152  * Params:
4153  *  callback: Application-provided routine to call for each enumerated device
4154  *  Context: Pointer to pass to the callback
4155  *
4156  * Returns:
4157  *  D3D_OK on success,
4158  *  The result of IDirect3DImpl_GetCaps if it failed
4159  *
4160  *****************************************************************************/
4161 static HRESULT WINAPI d3d3_EnumDevices(IDirect3D3 *iface, LPD3DENUMDEVICESCALLBACK callback, void *context)
4162 {
4163     static CHAR wined3d_description[] = "Wine D3DDevice using WineD3D and OpenGL";
4164
4165     IDirectDrawImpl *ddraw = ddraw_from_d3d3(iface);
4166     D3DDEVICEDESC device_desc1, hal_desc, hel_desc;
4167     D3DDEVICEDESC7 device_desc7;
4168     HRESULT hr;
4169
4170     /* Some games (Motoracer 2 demo) have the bad idea to modify the device
4171      * name string. Let's put the string in a sufficiently sized array in
4172      * writable memory. */
4173     char device_name[50];
4174     strcpy(device_name,"Direct3D HEL");
4175
4176     TRACE("iface %p, callback %p, context %p.\n", iface, callback, context);
4177
4178     EnterCriticalSection(&ddraw_cs);
4179
4180     hr = IDirect3DImpl_GetCaps(ddraw->wineD3D, &device_desc1, &device_desc7);
4181     if (hr != D3D_OK)
4182     {
4183         LeaveCriticalSection(&ddraw_cs);
4184         return hr;
4185     }
4186
4187     /* Do I have to enumerate the reference id? Note from old d3d7:
4188      * "It seems that enumerating the reference IID on Direct3D 1 games
4189      * (AvP / Motoracer2) breaks them". So do not enumerate this iid in V1
4190      *
4191      * There's a registry key HKLM\Software\Microsoft\Direct3D\Drivers,
4192      * EnumReference which enables / disables enumerating the reference
4193      * rasterizer. It's a DWORD, 0 means disabled, 2 means enabled. The
4194      * enablerefrast.reg and disablerefrast.reg files in the DirectX 7.0 sdk
4195      * demo directory suggest this.
4196      *
4197      * Some games(GTA 2) seem to use the second enumerated device, so I have
4198      * to enumerate at least 2 devices. So enumerate the reference device to
4199      * have 2 devices.
4200      *
4201      * Other games (Rollcage) tell emulation and hal device apart by certain
4202      * flags. Rollcage expects D3DPTEXTURECAPS_POW2 to be set (yeah, it is a
4203      * limitation flag), and it refuses all devices that have the perspective
4204      * flag set. This way it refuses the emulation device, and HAL devices
4205      * never have POW2 unset in d3d7 on windows. */
4206     if (ddraw->d3dversion != 1)
4207     {
4208         static CHAR reference_description[] = "RGB Direct3D emulation";
4209
4210         TRACE("Enumerating WineD3D D3DDevice interface.\n");
4211         hal_desc = device_desc1;
4212         hel_desc = device_desc1;
4213         /* The rgb device has the pow2 flag set in the hel caps, but not in the hal caps. */
4214         hal_desc.dpcLineCaps.dwTextureCaps &= ~(D3DPTEXTURECAPS_POW2
4215                 | D3DPTEXTURECAPS_NONPOW2CONDITIONAL | D3DPTEXTURECAPS_PERSPECTIVE);
4216         hal_desc.dpcTriCaps.dwTextureCaps &= ~(D3DPTEXTURECAPS_POW2
4217                 | D3DPTEXTURECAPS_NONPOW2CONDITIONAL | D3DPTEXTURECAPS_PERSPECTIVE);
4218         hr = callback((GUID *)&IID_IDirect3DRGBDevice, reference_description,
4219                 device_name, &hal_desc, &hel_desc, context);
4220         if (hr != D3DENUMRET_OK)
4221         {
4222             TRACE("Application cancelled the enumeration.\n");
4223             LeaveCriticalSection(&ddraw_cs);
4224             return D3D_OK;
4225         }
4226     }
4227
4228     strcpy(device_name,"Direct3D HAL");
4229
4230     TRACE("Enumerating HAL Direct3D device.\n");
4231     hal_desc = device_desc1;
4232     hel_desc = device_desc1;
4233     /* The hal device does not have the pow2 flag set in hel, but in hal. */
4234     hel_desc.dpcLineCaps.dwTextureCaps &= ~(D3DPTEXTURECAPS_POW2
4235             | D3DPTEXTURECAPS_NONPOW2CONDITIONAL | D3DPTEXTURECAPS_PERSPECTIVE);
4236     hel_desc.dpcTriCaps.dwTextureCaps &= ~(D3DPTEXTURECAPS_POW2
4237             | D3DPTEXTURECAPS_NONPOW2CONDITIONAL | D3DPTEXTURECAPS_PERSPECTIVE);
4238     hr = callback((GUID *)&IID_IDirect3DHALDevice, wined3d_description,
4239             device_name, &hal_desc, &hel_desc, context);
4240     if (hr != D3DENUMRET_OK)
4241     {
4242         TRACE("Application cancelled the enumeration.\n");
4243         LeaveCriticalSection(&ddraw_cs);
4244         return D3D_OK;
4245     }
4246
4247     TRACE("End of enumeration.\n");
4248
4249     LeaveCriticalSection(&ddraw_cs);
4250     return D3D_OK;
4251 }
4252
4253 static HRESULT WINAPI d3d2_EnumDevices(IDirect3D2 *iface, LPD3DENUMDEVICESCALLBACK callback, void *context)
4254 {
4255     TRACE("iface %p, callback %p, context %p.\n", iface, callback, context);
4256
4257     return d3d3_EnumDevices((IDirect3D3 *)&ddraw_from_d3d2(iface)->IDirect3D3_vtbl, callback, context);
4258 }
4259
4260 static HRESULT WINAPI d3d1_EnumDevices(IDirect3D *iface, LPD3DENUMDEVICESCALLBACK callback, void *context)
4261 {
4262     TRACE("iface %p, callback %p, context %p.\n", iface, callback, context);
4263
4264     return d3d3_EnumDevices((IDirect3D3 *)&ddraw_from_d3d1(iface)->IDirect3D3_vtbl, callback, context);
4265 }
4266
4267 /*****************************************************************************
4268  * IDirect3D3::CreateLight
4269  *
4270  * Creates an IDirect3DLight interface. This interface is used in
4271  * Direct3D3 or earlier for lighting. In Direct3D7 it has been replaced
4272  * by the DIRECT3DLIGHT7 structure. Wine's Direct3DLight implementation
4273  * uses the IDirect3DDevice7 interface with D3D7 lights.
4274  *
4275  * Version 1, 2 and 3
4276  *
4277  * Params:
4278  *  light: Address to store the new interface pointer
4279  *  outer_unknown: Basically for aggregation, but ddraw doesn't support it.
4280  *                 Must be NULL
4281  *
4282  * Returns:
4283  *  D3D_OK on success
4284  *  DDERR_OUTOFMEMORY if memory allocation failed
4285  *  CLASS_E_NOAGGREGATION if outer_unknown != NULL
4286  *
4287  *****************************************************************************/
4288 static HRESULT WINAPI d3d3_CreateLight(IDirect3D3 *iface, IDirect3DLight **light, IUnknown *outer_unknown)
4289 {
4290     IDirect3DLightImpl *object;
4291
4292     TRACE("iface %p, light %p, outer_unknown %p.\n", iface, light, outer_unknown);
4293
4294     if (outer_unknown) return CLASS_E_NOAGGREGATION;
4295
4296     object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*object));
4297     if (!object)
4298     {
4299         ERR("Failed to allocate light memory.\n");
4300         return DDERR_OUTOFMEMORY;
4301     }
4302
4303     d3d_light_init(object, ddraw_from_d3d3(iface));
4304
4305     TRACE("Created light %p.\n", object);
4306     *light = (IDirect3DLight *)object;
4307
4308     return D3D_OK;
4309 }
4310
4311 static HRESULT WINAPI d3d2_CreateLight(IDirect3D2 *iface, IDirect3DLight **light, IUnknown *outer_unknown)
4312 {
4313     TRACE("iface %p, light %p, outer_unknown %p.\n", iface, light, outer_unknown);
4314
4315     return d3d3_CreateLight((IDirect3D3 *)&ddraw_from_d3d2(iface)->IDirect3D3_vtbl, light, outer_unknown);
4316 }
4317
4318 static HRESULT WINAPI d3d1_CreateLight(IDirect3D *iface, IDirect3DLight **light, IUnknown *outer_unknown)
4319 {
4320     TRACE("iface %p, light %p, outer_unknown %p.\n", iface, light, outer_unknown);
4321
4322     return d3d3_CreateLight((IDirect3D3 *)&ddraw_from_d3d1(iface)->IDirect3D3_vtbl, light, outer_unknown);
4323 }
4324
4325 /*****************************************************************************
4326  * IDirect3D3::CreateMaterial
4327  *
4328  * Creates an IDirect3DMaterial interface. This interface is used by Direct3D3
4329  * and older versions. The IDirect3DMaterial implementation wraps its
4330  * functionality to IDirect3DDevice7::SetMaterial and friends.
4331  *
4332  * Version 1, 2 and 3
4333  *
4334  * Params:
4335  *  material: Address to store the new interface's pointer to
4336  *  outer_unknown: Basically for aggregation, but ddraw doesn't support it.
4337  *                 Must be NULL
4338  *
4339  * Returns:
4340  *  D3D_OK on success
4341  *  DDERR_OUTOFMEMORY if memory allocation failed
4342  *  CLASS_E_NOAGGREGATION if outer_unknown != NULL
4343  *
4344  *****************************************************************************/
4345 static HRESULT WINAPI d3d3_CreateMaterial(IDirect3D3 *iface, IDirect3DMaterial3 **material, IUnknown *outer_unknown)
4346 {
4347     IDirect3DMaterialImpl *object;
4348
4349     TRACE("iface %p, material %p, outer_unknown %p.\n", iface, material, outer_unknown);
4350
4351     if (outer_unknown) return CLASS_E_NOAGGREGATION;
4352
4353     object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*object));
4354     if (!object)
4355     {
4356         ERR("Failed to allocate material memory.\n");
4357         return DDERR_OUTOFMEMORY;
4358     }
4359
4360     d3d_material_init(object, ddraw_from_d3d3(iface));
4361
4362     TRACE("Created material %p.\n", object);
4363     *material = (IDirect3DMaterial3 *)object;
4364
4365     return D3D_OK;
4366 }
4367
4368 static HRESULT WINAPI d3d2_CreateMaterial(IDirect3D2 *iface, IDirect3DMaterial2 **material, IUnknown *outer_unknown)
4369 {
4370     IDirect3DMaterial3 *material3;
4371     HRESULT hr;
4372
4373     TRACE("iface %p, material %p, outer_unknown %p.\n", iface, material, outer_unknown);
4374
4375     hr = d3d3_CreateMaterial((IDirect3D3 *)&ddraw_from_d3d2(iface)->IDirect3D3_vtbl, &material3, outer_unknown);
4376     *material = material3 ? (IDirect3DMaterial2 *)&((IDirect3DMaterialImpl *)material3)->IDirect3DMaterial2_vtbl : NULL;
4377
4378     TRACE("Returning material %p.\n", *material);
4379
4380     return hr;
4381 }
4382
4383 static HRESULT WINAPI d3d1_CreateMaterial(IDirect3D *iface, IDirect3DMaterial **material, IUnknown *outer_unknown)
4384 {
4385     IDirect3DMaterial3 *material3;
4386     HRESULT hr;
4387
4388     TRACE("iface %p, material %p, outer_unknown %p.\n", iface, material, outer_unknown);
4389
4390     hr = d3d3_CreateMaterial((IDirect3D3 *)&ddraw_from_d3d1(iface)->IDirect3D3_vtbl, &material3, outer_unknown);
4391     *material = material3 ? (IDirect3DMaterial *)&((IDirect3DMaterialImpl *)material3)->IDirect3DMaterial_vtbl : NULL;
4392
4393     TRACE("Returning material %p.\n", *material);
4394
4395     return hr;
4396 }
4397
4398 /*****************************************************************************
4399  * IDirect3D3::CreateViewport
4400  *
4401  * Creates an IDirect3DViewport interface. This interface is used
4402  * by Direct3D and earlier versions for Viewport management. In Direct3D7
4403  * it has been replaced by a viewport structure and
4404  * IDirect3DDevice7::*Viewport. Wine's IDirect3DViewport implementation
4405  * uses the IDirect3DDevice7 methods for its functionality
4406  *
4407  * Params:
4408  *  Viewport: Address to store the new interface pointer
4409  *  outer_unknown: Basically for aggregation, but ddraw doesn't support it.
4410  *                 Must be NULL
4411  *
4412  * Returns:
4413  *  D3D_OK on success
4414  *  DDERR_OUTOFMEMORY if memory allocation failed
4415  *  CLASS_E_NOAGGREGATION if outer_unknown != NULL
4416  *
4417  *****************************************************************************/
4418 static HRESULT WINAPI d3d3_CreateViewport(IDirect3D3 *iface, IDirect3DViewport3 **viewport, IUnknown *outer_unknown)
4419 {
4420     IDirect3DViewportImpl *object;
4421
4422     TRACE("iface %p, viewport %p, outer_unknown %p.\n", iface, viewport, outer_unknown);
4423
4424     if (outer_unknown) return CLASS_E_NOAGGREGATION;
4425
4426     object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*object));
4427     if (!object)
4428     {
4429         ERR("Failed to allocate viewport memory.\n");
4430         return DDERR_OUTOFMEMORY;
4431     }
4432
4433     d3d_viewport_init(object, ddraw_from_d3d3(iface));
4434
4435     TRACE("Created viewport %p.\n", object);
4436     *viewport = (IDirect3DViewport3 *)object;
4437
4438     return D3D_OK;
4439 }
4440
4441 static HRESULT WINAPI d3d2_CreateViewport(IDirect3D2 *iface, IDirect3DViewport2 **viewport, IUnknown *outer_unknown)
4442 {
4443     TRACE("iface %p, viewport %p, outer_unknown %p.\n", iface, viewport, outer_unknown);
4444
4445     return d3d3_CreateViewport((IDirect3D3 *)&ddraw_from_d3d2(iface)->IDirect3D3_vtbl,
4446             (IDirect3DViewport3 **)viewport, outer_unknown);
4447 }
4448
4449 static HRESULT WINAPI d3d1_CreateViewport(IDirect3D *iface, IDirect3DViewport **viewport, IUnknown *outer_unknown)
4450 {
4451     TRACE("iface %p, viewport %p, outer_unknown %p.\n", iface, viewport, outer_unknown);
4452
4453     return d3d3_CreateViewport((IDirect3D3 *)&ddraw_from_d3d1(iface)->IDirect3D3_vtbl,
4454             (IDirect3DViewport3 **)viewport, outer_unknown);
4455 }
4456
4457 /*****************************************************************************
4458  * IDirect3D3::FindDevice
4459  *
4460  * This method finds a device with the requested properties and returns a
4461  * device description
4462  *
4463  * Verion 1, 2 and 3
4464  * Params:
4465  *  fds: Describes the requested device characteristics
4466  *  fdr: Returns the device description
4467  *
4468  * Returns:
4469  *  D3D_OK on success
4470  *  DDERR_INVALIDPARAMS if no device was found
4471  *
4472  *****************************************************************************/
4473 static HRESULT WINAPI d3d3_FindDevice(IDirect3D3 *iface, D3DFINDDEVICESEARCH *fds, D3DFINDDEVICERESULT *fdr)
4474 {
4475     IDirectDrawImpl *ddraw = ddraw_from_d3d3(iface);
4476     D3DDEVICEDESC7 desc7;
4477     D3DDEVICEDESC desc1;
4478     HRESULT hr;
4479
4480     TRACE("iface %p, fds %p, fdr %p.\n", iface, fds, fdr);
4481
4482     if (!fds || !fdr) return DDERR_INVALIDPARAMS;
4483
4484     if (fds->dwSize != sizeof(D3DFINDDEVICESEARCH)
4485             || fdr->dwSize != sizeof(D3DFINDDEVICERESULT))
4486         return DDERR_INVALIDPARAMS;
4487
4488     if ((fds->dwFlags & D3DFDS_COLORMODEL)
4489             && fds->dcmColorModel != D3DCOLOR_RGB)
4490     {
4491         WARN("Trying to request a non-RGB D3D color model. Not supported.\n");
4492         return DDERR_INVALIDPARAMS; /* No real idea what to return here :-) */
4493     }
4494
4495     if (fds->dwFlags & D3DFDS_GUID)
4496     {
4497         TRACE("Trying to match guid %s.\n", debugstr_guid(&(fds->guid)));
4498         if (!IsEqualGUID(&IID_D3DDEVICE_WineD3D, &fds->guid)
4499                 && !IsEqualGUID(&IID_IDirect3DHALDevice, &fds->guid)
4500                 && !IsEqualGUID(&IID_IDirect3DRGBDevice, &fds->guid))
4501         {
4502             WARN("No match for this GUID.\n");
4503             return DDERR_NOTFOUND;
4504         }
4505     }
4506
4507     /* Get the caps */
4508     hr = IDirect3DImpl_GetCaps(ddraw->wineD3D, &desc1, &desc7);
4509     if (hr != D3D_OK) return hr;
4510
4511     /* Now return our own GUID */
4512     fdr->guid = IID_D3DDEVICE_WineD3D;
4513     fdr->ddHwDesc = desc1;
4514     fdr->ddSwDesc = desc1;
4515
4516     TRACE("Returning Wine's wined3d device with (undumped) capabilities.\n");
4517
4518     return D3D_OK;
4519 }
4520
4521 static HRESULT WINAPI d3d2_FindDevice(IDirect3D2 *iface, D3DFINDDEVICESEARCH *fds, D3DFINDDEVICERESULT *fdr)
4522 {
4523     TRACE("iface %p, fds %p, fdr %p.\n", iface, fds, fdr);
4524
4525     return d3d3_FindDevice((IDirect3D3 *)&ddraw_from_d3d2(iface)->IDirect3D3_vtbl, fds, fdr);
4526 }
4527
4528 static HRESULT WINAPI d3d1_FindDevice(IDirect3D *iface, D3DFINDDEVICESEARCH *fds, D3DFINDDEVICERESULT *fdr)
4529 {
4530     TRACE("iface %p, fds %p, fdr %p.\n", iface, fds, fdr);
4531
4532     return d3d3_FindDevice((IDirect3D3 *)&ddraw_from_d3d1(iface)->IDirect3D3_vtbl, fds, fdr);
4533 }
4534
4535 /*****************************************************************************
4536  * IDirect3D7::CreateDevice
4537  *
4538  * Creates an IDirect3DDevice7 interface.
4539  *
4540  * Version 2, 3 and 7. IDirect3DDevice 1 interfaces are interfaces to
4541  * DirectDraw surfaces and are created with
4542  * IDirectDrawSurface::QueryInterface. This method uses CreateDevice to
4543  * create the device object and QueryInterfaces for IDirect3DDevice
4544  *
4545  * Params:
4546  *  refiid: IID of the device to create
4547  *  Surface: Initial rendertarget
4548  *  Device: Address to return the interface pointer
4549  *
4550  * Returns:
4551  *  D3D_OK on success
4552  *  DDERR_OUTOFMEMORY if memory allocation failed
4553  *  DDERR_INVALIDPARAMS if a device exists already
4554  *
4555  *****************************************************************************/
4556 static HRESULT WINAPI d3d7_CreateDevice(IDirect3D7 *iface, REFCLSID riid,
4557         IDirectDrawSurface7 *surface, IDirect3DDevice7 **device)
4558 {
4559     IDirectDrawSurfaceImpl *target = (IDirectDrawSurfaceImpl *)surface;
4560     IDirectDrawImpl *ddraw = ddraw_from_d3d7(iface);
4561     IDirect3DDeviceImpl *object;
4562     HRESULT hr;
4563
4564     TRACE("iface %p, riid %s, surface %p, device %p.\n", iface, debugstr_guid(riid), surface, device);
4565
4566     EnterCriticalSection(&ddraw_cs);
4567     *device = NULL;
4568
4569     /* Fail device creation if non-opengl surfaces are used. */
4570     if (ddraw->ImplType != SURFACE_OPENGL)
4571     {
4572         ERR("The application wants to create a Direct3D device, but non-opengl surfaces are set in the registry.\n");
4573         ERR("Please set the surface implementation to opengl or autodetection to allow 3D rendering.\n");
4574
4575         /* We only hit this path if a default surface is set in the registry. Incorrect autodetection
4576          * is caught in CreateSurface or QueryInterface. */
4577         LeaveCriticalSection(&ddraw_cs);
4578         return DDERR_NO3D;
4579     }
4580
4581     if (ddraw->d3ddevice)
4582     {
4583         FIXME("Only one Direct3D device per DirectDraw object supported.\n");
4584         LeaveCriticalSection(&ddraw_cs);
4585         return DDERR_INVALIDPARAMS;
4586     }
4587
4588     object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*object));
4589     if (!object)
4590     {
4591         ERR("Failed to allocate device memory.\n");
4592         LeaveCriticalSection(&ddraw_cs);
4593         return DDERR_OUTOFMEMORY;
4594     }
4595
4596     hr = d3d_device_init(object, ddraw, target);
4597     if (FAILED(hr))
4598     {
4599         WARN("Failed to initialize device, hr %#x.\n", hr);
4600         HeapFree(GetProcessHeap(), 0, object);
4601         LeaveCriticalSection(&ddraw_cs);
4602         return hr;
4603     }
4604
4605     TRACE("Created device %p.\n", object);
4606     *device = (IDirect3DDevice7 *)object;
4607
4608     LeaveCriticalSection(&ddraw_cs);
4609     return D3D_OK;
4610 }
4611
4612 static HRESULT WINAPI d3d3_CreateDevice(IDirect3D3 *iface, REFCLSID riid,
4613         IDirectDrawSurface4 *surface, IDirect3DDevice3 **device, IUnknown *outer_unknown)
4614 {
4615     HRESULT hr;
4616
4617     TRACE("iface %p, riid %s, surface %p, device %p, outer_unknown %p.\n",
4618             iface, debugstr_guid(riid), surface, device, outer_unknown);
4619
4620     if (outer_unknown) return CLASS_E_NOAGGREGATION;
4621
4622     hr = d3d7_CreateDevice((IDirect3D7 *)&ddraw_from_d3d3(iface)->IDirect3D7_vtbl, riid,
4623             (IDirectDrawSurface7 *)surface, (IDirect3DDevice7 **)device);
4624     if (*device) *device = (IDirect3DDevice3 *)&((IDirect3DDeviceImpl *)*device)->IDirect3DDevice3_vtbl;
4625
4626     return hr;
4627 }
4628
4629 static HRESULT WINAPI d3d2_CreateDevice(IDirect3D2 *iface, REFCLSID riid,
4630         IDirectDrawSurface *surface, IDirect3DDevice2 **device)
4631 {
4632     HRESULT hr;
4633
4634     TRACE("iface %p, riid %s, surface %p, device %p.\n",
4635             iface, debugstr_guid(riid), surface, device);
4636
4637     hr = d3d7_CreateDevice((IDirect3D7 *)&ddraw_from_d3d2(iface)->IDirect3D7_vtbl, riid,
4638             surface ? (IDirectDrawSurface7 *)surface_from_surface3((IDirectDrawSurface3 *)surface) : NULL,
4639             (IDirect3DDevice7 **)device);
4640     if (*device) *device = (IDirect3DDevice2 *)&((IDirect3DDeviceImpl *)*device)->IDirect3DDevice2_vtbl;
4641
4642     return hr;
4643 }
4644
4645 /*****************************************************************************
4646  * IDirect3D7::CreateVertexBuffer
4647  *
4648  * Creates a new vertex buffer object and returns a IDirect3DVertexBuffer7
4649  * interface.
4650  *
4651  * Version 3 and 7
4652  *
4653  * Params:
4654  *  desc: Requested Vertex buffer properties
4655  *  vertex_buffer: Address to return the interface pointer at
4656  *  flags: Some flags, should be 0
4657  *
4658  * Returns
4659  *  D3D_OK on success
4660  *  DDERR_OUTOFMEMORY if memory allocation failed
4661  *  The return value of IWineD3DDevice::CreateVertexBuffer if this call fails
4662  *  DDERR_INVALIDPARAMS if desc or vertex_buffer are NULL
4663  *
4664  *****************************************************************************/
4665 static HRESULT WINAPI d3d7_CreateVertexBuffer(IDirect3D7 *iface, D3DVERTEXBUFFERDESC *desc,
4666         IDirect3DVertexBuffer7 **vertex_buffer, DWORD flags)
4667 {
4668     IDirect3DVertexBufferImpl *object;
4669     HRESULT hr;
4670
4671     TRACE("iface %p, desc %p, vertex_buffer %p, flags %#x.\n",
4672             iface, desc, vertex_buffer, flags);
4673
4674     if (!vertex_buffer || !desc) return DDERR_INVALIDPARAMS;
4675
4676     TRACE("Vertex buffer description:\n");
4677     TRACE("    dwSize %u\n", desc->dwSize);
4678     TRACE("    dwCaps %#x\n", desc->dwCaps);
4679     TRACE("    FVF %#x\n", desc->dwFVF);
4680     TRACE("    dwNumVertices %u\n", desc->dwNumVertices);
4681
4682     /* Now create the vertex buffer */
4683     object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*object));
4684     if (!object)
4685     {
4686         ERR("Failed to allocate vertex buffer memory.\n");
4687         return DDERR_OUTOFMEMORY;
4688     }
4689
4690     hr = d3d_vertex_buffer_init(object, ddraw_from_d3d7(iface), desc);
4691     if (FAILED(hr))
4692     {
4693         WARN("Failed to initialize vertex buffer, hr %#x.\n", hr);
4694         HeapFree(GetProcessHeap(), 0, object);
4695         return hr;
4696     }
4697
4698     TRACE("Created vertex buffer %p.\n", object);
4699     *vertex_buffer = (IDirect3DVertexBuffer7 *)object;
4700
4701     return D3D_OK;
4702 }
4703
4704 static HRESULT WINAPI d3d3_CreateVertexBuffer(IDirect3D3 *iface, D3DVERTEXBUFFERDESC *desc,
4705         IDirect3DVertexBuffer **vertex_buffer, DWORD flags, IUnknown *outer_unknown)
4706 {
4707     IDirectDrawImpl *This = ddraw_from_d3d3(iface);
4708     HRESULT hr;
4709
4710     TRACE("iface %p, desc %p, vertex_buffer %p, flags %#x, outer_unknown %p.\n",
4711             iface, desc, vertex_buffer, flags, outer_unknown);
4712
4713     if (outer_unknown) return CLASS_E_NOAGGREGATION;
4714
4715     hr = d3d7_CreateVertexBuffer((IDirect3D7 *)&This->IDirect3D7_vtbl,
4716             desc, (IDirect3DVertexBuffer7 **)vertex_buffer, flags);
4717     if (*vertex_buffer)
4718         *vertex_buffer = (IDirect3DVertexBuffer *)&((IDirect3DVertexBufferImpl *)*vertex_buffer)->IDirect3DVertexBuffer_vtbl;
4719
4720     return hr;
4721 }
4722
4723 /*****************************************************************************
4724  * IDirect3D7::EnumZBufferFormats
4725  *
4726  * Enumerates all supported Z buffer pixel formats
4727  *
4728  * Version 3 and 7
4729  *
4730  * Params:
4731  *  device_iid:
4732  *  callback: callback to call for each pixel format
4733  *  context: Pointer to pass back to the callback
4734  *
4735  * Returns:
4736  *  D3D_OK on success
4737  *  DDERR_INVALIDPARAMS if callback is NULL
4738  *  For details, see IWineD3DDevice::EnumZBufferFormats
4739  *
4740  *****************************************************************************/
4741 static HRESULT WINAPI d3d7_EnumZBufferFormats(IDirect3D7 *iface, REFCLSID device_iid,
4742         LPD3DENUMPIXELFORMATSCALLBACK callback, void *context)
4743 {
4744     IDirectDrawImpl *ddraw = ddraw_from_d3d7(iface);
4745     WINED3DDISPLAYMODE d3ddm;
4746     WINED3DDEVTYPE type;
4747     unsigned int i;
4748     HRESULT hr;
4749
4750     /* Order matters. Specifically, BattleZone II (full version) expects the
4751      * 16-bit depth formats to be listed before the 24 and 32 ones. */
4752     static const enum wined3d_format_id formats[] =
4753     {
4754         WINED3DFMT_S1_UINT_D15_UNORM,
4755         WINED3DFMT_D16_UNORM,
4756         WINED3DFMT_X8D24_UNORM,
4757         WINED3DFMT_S4X4_UINT_D24_UNORM,
4758         WINED3DFMT_D24_UNORM_S8_UINT,
4759         WINED3DFMT_D32_UNORM,
4760     };
4761
4762     TRACE("iface %p, device_iid %s, callback %p, context %p.\n",
4763             iface, debugstr_guid(device_iid), callback, context);
4764
4765     if (!callback) return DDERR_INVALIDPARAMS;
4766
4767     if (IsEqualGUID(device_iid, &IID_IDirect3DHALDevice)
4768             || IsEqualGUID(device_iid, &IID_IDirect3DTnLHalDevice)
4769             || IsEqualGUID(device_iid, &IID_D3DDEVICE_WineD3D))
4770     {
4771         TRACE("Asked for HAL device.\n");
4772         type = WINED3DDEVTYPE_HAL;
4773     }
4774     else if (IsEqualGUID(device_iid, &IID_IDirect3DRGBDevice)
4775             || IsEqualGUID(device_iid, &IID_IDirect3DMMXDevice))
4776     {
4777         TRACE("Asked for SW device.\n");
4778         type = WINED3DDEVTYPE_SW;
4779     }
4780     else if (IsEqualGUID(device_iid, &IID_IDirect3DRefDevice))
4781     {
4782         TRACE("Asked for REF device.\n");
4783         type = WINED3DDEVTYPE_REF;
4784     }
4785     else if (IsEqualGUID(device_iid, &IID_IDirect3DNullDevice))
4786     {
4787         TRACE("Asked for NULLREF device.\n");
4788         type = WINED3DDEVTYPE_NULLREF;
4789     }
4790     else
4791     {
4792         FIXME("Unexpected device GUID %s.\n", debugstr_guid(device_iid));
4793         type = WINED3DDEVTYPE_HAL;
4794     }
4795
4796     EnterCriticalSection(&ddraw_cs);
4797     /* We need an adapter format from somewhere to please wined3d and WGL.
4798      * Use the current display mode. So far all cards offer the same depth
4799      * stencil format for all modes, but if some do not and applications do
4800      * not like that we'll have to find some workaround, like iterating over
4801      * all imaginable formats and collecting all the depth stencil formats we
4802      * can get. */
4803     hr = IWineD3DDevice_GetDisplayMode(ddraw->wineD3DDevice, 0, &d3ddm);
4804
4805     for (i = 0; i < (sizeof(formats) / sizeof(*formats)); ++i)
4806     {
4807         hr = IWineD3D_CheckDeviceFormat(ddraw->wineD3D, WINED3DADAPTER_DEFAULT, type, d3ddm.Format,
4808                 WINED3DUSAGE_DEPTHSTENCIL, WINED3DRTYPE_SURFACE, formats[i], SURFACE_OPENGL);
4809         if (SUCCEEDED(hr))
4810         {
4811             DDPIXELFORMAT pformat;
4812
4813             memset(&pformat, 0, sizeof(pformat));
4814             pformat.dwSize = sizeof(pformat);
4815             PixelFormat_WineD3DtoDD(&pformat, formats[i]);
4816
4817             TRACE("Enumerating wined3d format %#x.\n", formats[i]);
4818             hr = callback(&pformat, context);
4819             if (hr != DDENUMRET_OK)
4820             {
4821                 TRACE("Format enumeration cancelled by application.\n");
4822                 LeaveCriticalSection(&ddraw_cs);
4823                 return D3D_OK;
4824             }
4825         }
4826     }
4827     TRACE("End of enumeration.\n");
4828
4829     LeaveCriticalSection(&ddraw_cs);
4830     return D3D_OK;
4831 }
4832
4833 static HRESULT WINAPI d3d3_EnumZBufferFormats(IDirect3D3 *iface, REFCLSID device_iid,
4834         LPD3DENUMPIXELFORMATSCALLBACK callback, void *context)
4835 {
4836     TRACE("iface %p, device_iid %s, callback %p, context %p.\n",
4837             iface, debugstr_guid(device_iid), callback, context);
4838
4839     return d3d7_EnumZBufferFormats((IDirect3D7 *)&ddraw_from_d3d3(iface)->IDirect3D7_vtbl,
4840             device_iid, callback, context);
4841 }
4842
4843 /*****************************************************************************
4844  * IDirect3D7::EvictManagedTextures
4845  *
4846  * Removes all managed textures (=surfaces with DDSCAPS2_TEXTUREMANAGE or
4847  * DDSCAPS2_D3DTEXTUREMANAGE caps) to be removed from video memory.
4848  *
4849  * Version 3 and 7
4850  *
4851  * Returns:
4852  *  D3D_OK, because it's a stub
4853  *
4854  *****************************************************************************/
4855 static HRESULT WINAPI d3d7_EvictManagedTextures(IDirect3D7 *iface)
4856 {
4857     FIXME("iface %p stub!\n", iface);
4858
4859     /* TODO: Just enumerate resources using IWineD3DDevice_EnumResources(),
4860      * then unload surfaces / textures. */
4861
4862     return D3D_OK;
4863 }
4864
4865 static HRESULT WINAPI d3d3_EvictManagedTextures(IDirect3D3 *iface)
4866 {
4867     TRACE("iface %p.\n", iface);
4868
4869     return d3d7_EvictManagedTextures((IDirect3D7 *)&ddraw_from_d3d3(iface)->IDirect3D7_vtbl);
4870 }
4871
4872 /*****************************************************************************
4873  * IDirect3DImpl_GetCaps
4874  *
4875  * This function retrieves the device caps from wined3d
4876  * and converts it into a D3D7 and D3D - D3D3 structure
4877  * This is a helper function called from various places in ddraw
4878  *
4879  * Params:
4880  *  wined3d: The interface to get the caps from
4881  *  desc1: Old D3D <3 structure to fill (needed)
4882  *  desc7: D3D7 device desc structure to fill (needed)
4883  *
4884  * Returns
4885  *  D3D_OK on success, or the return value of IWineD3D::GetCaps
4886  *
4887  *****************************************************************************/
4888 HRESULT IDirect3DImpl_GetCaps(IWineD3D *wined3d, D3DDEVICEDESC *desc1, D3DDEVICEDESC7 *desc7)
4889 {
4890     WINED3DCAPS wined3d_caps;
4891     HRESULT hr;
4892
4893     TRACE("wined3d %p, desc1 %p, desc7 %p.\n", wined3d, desc1, desc7);
4894
4895     memset(&wined3d_caps, 0, sizeof(wined3d_caps));
4896
4897     EnterCriticalSection(&ddraw_cs);
4898     hr = IWineD3D_GetDeviceCaps(wined3d, 0, WINED3DDEVTYPE_HAL, &wined3d_caps);
4899     LeaveCriticalSection(&ddraw_cs);
4900     if (FAILED(hr))
4901     {
4902         WARN("Failed to get device caps, hr %#x.\n", hr);
4903         return hr;
4904     }
4905
4906     /* Copy the results into the d3d7 and d3d3 structures */
4907     desc7->dwDevCaps = wined3d_caps.DevCaps;
4908     desc7->dpcLineCaps.dwMiscCaps = wined3d_caps.PrimitiveMiscCaps;
4909     desc7->dpcLineCaps.dwRasterCaps = wined3d_caps.RasterCaps;
4910     desc7->dpcLineCaps.dwZCmpCaps = wined3d_caps.ZCmpCaps;
4911     desc7->dpcLineCaps.dwSrcBlendCaps = wined3d_caps.SrcBlendCaps;
4912     desc7->dpcLineCaps.dwDestBlendCaps = wined3d_caps.DestBlendCaps;
4913     desc7->dpcLineCaps.dwAlphaCmpCaps = wined3d_caps.AlphaCmpCaps;
4914     desc7->dpcLineCaps.dwShadeCaps = wined3d_caps.ShadeCaps;
4915     desc7->dpcLineCaps.dwTextureCaps = wined3d_caps.TextureCaps;
4916     desc7->dpcLineCaps.dwTextureFilterCaps = wined3d_caps.TextureFilterCaps;
4917     desc7->dpcLineCaps.dwTextureAddressCaps = wined3d_caps.TextureAddressCaps;
4918
4919     desc7->dwMaxTextureWidth = wined3d_caps.MaxTextureWidth;
4920     desc7->dwMaxTextureHeight = wined3d_caps.MaxTextureHeight;
4921
4922     desc7->dwMaxTextureRepeat = wined3d_caps.MaxTextureRepeat;
4923     desc7->dwMaxTextureAspectRatio = wined3d_caps.MaxTextureAspectRatio;
4924     desc7->dwMaxAnisotropy = wined3d_caps.MaxAnisotropy;
4925     desc7->dvMaxVertexW = wined3d_caps.MaxVertexW;
4926
4927     desc7->dvGuardBandLeft = wined3d_caps.GuardBandLeft;
4928     desc7->dvGuardBandTop = wined3d_caps.GuardBandTop;
4929     desc7->dvGuardBandRight = wined3d_caps.GuardBandRight;
4930     desc7->dvGuardBandBottom = wined3d_caps.GuardBandBottom;
4931
4932     desc7->dvExtentsAdjust = wined3d_caps.ExtentsAdjust;
4933     desc7->dwStencilCaps = wined3d_caps.StencilCaps;
4934
4935     desc7->dwFVFCaps = wined3d_caps.FVFCaps;
4936     desc7->dwTextureOpCaps = wined3d_caps.TextureOpCaps;
4937
4938     desc7->dwVertexProcessingCaps = wined3d_caps.VertexProcessingCaps;
4939     desc7->dwMaxActiveLights = wined3d_caps.MaxActiveLights;
4940
4941     /* Remove all non-d3d7 caps */
4942     desc7->dwDevCaps &= (
4943         D3DDEVCAPS_FLOATTLVERTEX         | D3DDEVCAPS_SORTINCREASINGZ          | D3DDEVCAPS_SORTDECREASINGZ          |
4944         D3DDEVCAPS_SORTEXACT             | D3DDEVCAPS_EXECUTESYSTEMMEMORY      | D3DDEVCAPS_EXECUTEVIDEOMEMORY       |
4945         D3DDEVCAPS_TLVERTEXSYSTEMMEMORY  | D3DDEVCAPS_TLVERTEXVIDEOMEMORY      | D3DDEVCAPS_TEXTURESYSTEMMEMORY      |
4946         D3DDEVCAPS_TEXTUREVIDEOMEMORY    | D3DDEVCAPS_DRAWPRIMTLVERTEX         | D3DDEVCAPS_CANRENDERAFTERFLIP       |
4947         D3DDEVCAPS_TEXTURENONLOCALVIDMEM | D3DDEVCAPS_DRAWPRIMITIVES2          | D3DDEVCAPS_SEPARATETEXTUREMEMORIES  |
4948         D3DDEVCAPS_DRAWPRIMITIVES2EX     | D3DDEVCAPS_HWTRANSFORMANDLIGHT      | D3DDEVCAPS_CANBLTSYSTONONLOCAL      |
4949         D3DDEVCAPS_HWRASTERIZATION);
4950
4951     desc7->dwStencilCaps &= (
4952         D3DSTENCILCAPS_KEEP              | D3DSTENCILCAPS_ZERO                 | D3DSTENCILCAPS_REPLACE              |
4953         D3DSTENCILCAPS_INCRSAT           | D3DSTENCILCAPS_DECRSAT              | D3DSTENCILCAPS_INVERT               |
4954         D3DSTENCILCAPS_INCR              | D3DSTENCILCAPS_DECR);
4955
4956     /* FVF caps ?*/
4957
4958     desc7->dwTextureOpCaps &= (
4959         D3DTEXOPCAPS_DISABLE             | D3DTEXOPCAPS_SELECTARG1             | D3DTEXOPCAPS_SELECTARG2             |
4960         D3DTEXOPCAPS_MODULATE            | D3DTEXOPCAPS_MODULATE2X             | D3DTEXOPCAPS_MODULATE4X             |
4961         D3DTEXOPCAPS_ADD                 | D3DTEXOPCAPS_ADDSIGNED              | D3DTEXOPCAPS_ADDSIGNED2X            |
4962         D3DTEXOPCAPS_SUBTRACT            | D3DTEXOPCAPS_ADDSMOOTH              | D3DTEXOPCAPS_BLENDTEXTUREALPHA      |
4963         D3DTEXOPCAPS_BLENDFACTORALPHA    | D3DTEXOPCAPS_BLENDTEXTUREALPHAPM    | D3DTEXOPCAPS_BLENDCURRENTALPHA      |
4964         D3DTEXOPCAPS_PREMODULATE         | D3DTEXOPCAPS_MODULATEALPHA_ADDCOLOR | D3DTEXOPCAPS_MODULATECOLOR_ADDALPHA |
4965         D3DTEXOPCAPS_MODULATEINVALPHA_ADDCOLOR | D3DTEXOPCAPS_MODULATEINVCOLOR_ADDALPHA | D3DTEXOPCAPS_BUMPENVMAP    |
4966         D3DTEXOPCAPS_BUMPENVMAPLUMINANCE | D3DTEXOPCAPS_DOTPRODUCT3);
4967
4968     desc7->dwVertexProcessingCaps &= (
4969         D3DVTXPCAPS_TEXGEN               | D3DVTXPCAPS_MATERIALSOURCE7         | D3DVTXPCAPS_VERTEXFOG               |
4970         D3DVTXPCAPS_DIRECTIONALLIGHTS    | D3DVTXPCAPS_POSITIONALLIGHTS        | D3DVTXPCAPS_LOCALVIEWER);
4971
4972     desc7->dpcLineCaps.dwMiscCaps &= (
4973         D3DPMISCCAPS_MASKPLANES          | D3DPMISCCAPS_MASKZ                  | D3DPMISCCAPS_LINEPATTERNREP         |
4974         D3DPMISCCAPS_CONFORMANT          | D3DPMISCCAPS_CULLNONE               | D3DPMISCCAPS_CULLCW                 |
4975         D3DPMISCCAPS_CULLCCW);
4976
4977     desc7->dpcLineCaps.dwRasterCaps &= (
4978         D3DPRASTERCAPS_DITHER            | D3DPRASTERCAPS_ROP2                 | D3DPRASTERCAPS_XOR                  |
4979         D3DPRASTERCAPS_PAT               | D3DPRASTERCAPS_ZTEST                | D3DPRASTERCAPS_SUBPIXEL             |
4980         D3DPRASTERCAPS_SUBPIXELX         | D3DPRASTERCAPS_FOGVERTEX            | D3DPRASTERCAPS_FOGTABLE             |
4981         D3DPRASTERCAPS_STIPPLE           | D3DPRASTERCAPS_ANTIALIASSORTDEPENDENT | D3DPRASTERCAPS_ANTIALIASSORTINDEPENDENT |
4982         D3DPRASTERCAPS_ANTIALIASEDGES    | D3DPRASTERCAPS_MIPMAPLODBIAS        | D3DPRASTERCAPS_ZBIAS                |
4983         D3DPRASTERCAPS_ZBUFFERLESSHSR    | D3DPRASTERCAPS_FOGRANGE             | D3DPRASTERCAPS_ANISOTROPY           |
4984         D3DPRASTERCAPS_WBUFFER           | D3DPRASTERCAPS_TRANSLUCENTSORTINDEPENDENT | D3DPRASTERCAPS_WFOG           |
4985         D3DPRASTERCAPS_ZFOG);
4986
4987     desc7->dpcLineCaps.dwZCmpCaps &= (
4988         D3DPCMPCAPS_NEVER                | D3DPCMPCAPS_LESS                    | D3DPCMPCAPS_EQUAL                   |
4989         D3DPCMPCAPS_LESSEQUAL            | D3DPCMPCAPS_GREATER                 | D3DPCMPCAPS_NOTEQUAL                |
4990         D3DPCMPCAPS_GREATEREQUAL         | D3DPCMPCAPS_ALWAYS);
4991
4992     desc7->dpcLineCaps.dwSrcBlendCaps &= (
4993         D3DPBLENDCAPS_ZERO               | D3DPBLENDCAPS_ONE                   | D3DPBLENDCAPS_SRCCOLOR              |
4994         D3DPBLENDCAPS_INVSRCCOLOR        | D3DPBLENDCAPS_SRCALPHA              | D3DPBLENDCAPS_INVSRCALPHA           |
4995         D3DPBLENDCAPS_DESTALPHA          | D3DPBLENDCAPS_INVDESTALPHA          | D3DPBLENDCAPS_DESTCOLOR             |
4996         D3DPBLENDCAPS_INVDESTCOLOR       | D3DPBLENDCAPS_SRCALPHASAT           | D3DPBLENDCAPS_BOTHSRCALPHA          |
4997         D3DPBLENDCAPS_BOTHINVSRCALPHA);
4998
4999     desc7->dpcLineCaps.dwDestBlendCaps &= (
5000         D3DPBLENDCAPS_ZERO               | D3DPBLENDCAPS_ONE                   | D3DPBLENDCAPS_SRCCOLOR              |
5001         D3DPBLENDCAPS_INVSRCCOLOR        | D3DPBLENDCAPS_SRCALPHA              | D3DPBLENDCAPS_INVSRCALPHA           |
5002         D3DPBLENDCAPS_DESTALPHA          | D3DPBLENDCAPS_INVDESTALPHA          | D3DPBLENDCAPS_DESTCOLOR             |
5003         D3DPBLENDCAPS_INVDESTCOLOR       | D3DPBLENDCAPS_SRCALPHASAT           | D3DPBLENDCAPS_BOTHSRCALPHA          |
5004         D3DPBLENDCAPS_BOTHINVSRCALPHA);
5005
5006     desc7->dpcLineCaps.dwAlphaCmpCaps &= (
5007         D3DPCMPCAPS_NEVER                | D3DPCMPCAPS_LESS                    | D3DPCMPCAPS_EQUAL                   |
5008         D3DPCMPCAPS_LESSEQUAL            | D3DPCMPCAPS_GREATER                 | D3DPCMPCAPS_NOTEQUAL                |
5009         D3DPCMPCAPS_GREATEREQUAL         | D3DPCMPCAPS_ALWAYS);
5010
5011     desc7->dpcLineCaps.dwShadeCaps &= (
5012         D3DPSHADECAPS_COLORFLATMONO      | D3DPSHADECAPS_COLORFLATRGB          | D3DPSHADECAPS_COLORGOURAUDMONO      |
5013         D3DPSHADECAPS_COLORGOURAUDRGB    | D3DPSHADECAPS_COLORPHONGMONO        | D3DPSHADECAPS_COLORPHONGRGB         |
5014         D3DPSHADECAPS_SPECULARFLATMONO   | D3DPSHADECAPS_SPECULARFLATRGB       | D3DPSHADECAPS_SPECULARGOURAUDMONO   |
5015         D3DPSHADECAPS_SPECULARGOURAUDRGB | D3DPSHADECAPS_SPECULARPHONGMONO     | D3DPSHADECAPS_SPECULARPHONGRGB      |
5016         D3DPSHADECAPS_ALPHAFLATBLEND     | D3DPSHADECAPS_ALPHAFLATSTIPPLED     | D3DPSHADECAPS_ALPHAGOURAUDBLEND     |
5017         D3DPSHADECAPS_ALPHAGOURAUDSTIPPLED | D3DPSHADECAPS_ALPHAPHONGBLEND     | D3DPSHADECAPS_ALPHAPHONGSTIPPLED    |
5018         D3DPSHADECAPS_FOGFLAT            | D3DPSHADECAPS_FOGGOURAUD            | D3DPSHADECAPS_FOGPHONG);
5019
5020     desc7->dpcLineCaps.dwTextureCaps &= (
5021         D3DPTEXTURECAPS_PERSPECTIVE      | D3DPTEXTURECAPS_POW2                | D3DPTEXTURECAPS_ALPHA               |
5022         D3DPTEXTURECAPS_TRANSPARENCY     | D3DPTEXTURECAPS_BORDER              | D3DPTEXTURECAPS_SQUAREONLY          |
5023         D3DPTEXTURECAPS_TEXREPEATNOTSCALEDBYSIZE | D3DPTEXTURECAPS_ALPHAPALETTE| D3DPTEXTURECAPS_NONPOW2CONDITIONAL  |
5024         D3DPTEXTURECAPS_PROJECTED        | D3DPTEXTURECAPS_CUBEMAP             | D3DPTEXTURECAPS_COLORKEYBLEND);
5025
5026     desc7->dpcLineCaps.dwTextureFilterCaps &= (
5027         D3DPTFILTERCAPS_NEAREST          | D3DPTFILTERCAPS_LINEAR              | D3DPTFILTERCAPS_MIPNEAREST          |
5028         D3DPTFILTERCAPS_MIPLINEAR        | D3DPTFILTERCAPS_LINEARMIPNEAREST    | D3DPTFILTERCAPS_LINEARMIPLINEAR     |
5029         D3DPTFILTERCAPS_MINFPOINT        | D3DPTFILTERCAPS_MINFLINEAR          | D3DPTFILTERCAPS_MINFANISOTROPIC     |
5030         D3DPTFILTERCAPS_MIPFPOINT        | D3DPTFILTERCAPS_MIPFLINEAR          | D3DPTFILTERCAPS_MAGFPOINT           |
5031         D3DPTFILTERCAPS_MAGFLINEAR       | D3DPTFILTERCAPS_MAGFANISOTROPIC     | D3DPTFILTERCAPS_MAGFAFLATCUBIC      |
5032         D3DPTFILTERCAPS_MAGFGAUSSIANCUBIC);
5033
5034     desc7->dpcLineCaps.dwTextureBlendCaps &= (
5035         D3DPTBLENDCAPS_DECAL             | D3DPTBLENDCAPS_MODULATE             | D3DPTBLENDCAPS_DECALALPHA           |
5036         D3DPTBLENDCAPS_MODULATEALPHA     | D3DPTBLENDCAPS_DECALMASK            | D3DPTBLENDCAPS_MODULATEMASK         |
5037         D3DPTBLENDCAPS_COPY              | D3DPTBLENDCAPS_ADD);
5038
5039     desc7->dpcLineCaps.dwTextureAddressCaps &= (
5040         D3DPTADDRESSCAPS_WRAP            | D3DPTADDRESSCAPS_MIRROR             | D3DPTADDRESSCAPS_CLAMP              |
5041         D3DPTADDRESSCAPS_BORDER          | D3DPTADDRESSCAPS_INDEPENDENTUV);
5042
5043     if (!(desc7->dpcLineCaps.dwTextureCaps & D3DPTEXTURECAPS_POW2))
5044     {
5045         /* DirectX7 always has the np2 flag set, no matter what the card
5046          * supports. Some old games (Rollcage) check the caps incorrectly.
5047          * If wined3d supports nonpow2 textures it also has np2 conditional
5048          * support. */
5049         desc7->dpcLineCaps.dwTextureCaps |= D3DPTEXTURECAPS_POW2 | D3DPTEXTURECAPS_NONPOW2CONDITIONAL;
5050     }
5051
5052     /* Fill the missing members, and do some fixup */
5053     desc7->dpcLineCaps.dwSize = sizeof(desc7->dpcLineCaps);
5054     desc7->dpcLineCaps.dwTextureBlendCaps = D3DPTBLENDCAPS_ADD | D3DPTBLENDCAPS_MODULATEMASK |
5055                                             D3DPTBLENDCAPS_COPY | D3DPTBLENDCAPS_DECAL |
5056                                             D3DPTBLENDCAPS_DECALALPHA | D3DPTBLENDCAPS_DECALMASK |
5057                                             D3DPTBLENDCAPS_MODULATE | D3DPTBLENDCAPS_MODULATEALPHA;
5058     desc7->dpcLineCaps.dwStippleWidth = 32;
5059     desc7->dpcLineCaps.dwStippleHeight = 32;
5060     /* Use the same for the TriCaps */
5061     desc7->dpcTriCaps = desc7->dpcLineCaps;
5062
5063     desc7->dwDeviceRenderBitDepth = DDBD_16 | DDBD_24 | DDBD_32;
5064     desc7->dwDeviceZBufferBitDepth = DDBD_16 | DDBD_24;
5065     desc7->dwMinTextureWidth = 1;
5066     desc7->dwMinTextureHeight = 1;
5067
5068     /* Convert DWORDs safely to WORDs */
5069     if (wined3d_caps.MaxTextureBlendStages > 0xffff) desc7->wMaxTextureBlendStages = 0xffff;
5070     else desc7->wMaxTextureBlendStages = (WORD)wined3d_caps.MaxTextureBlendStages;
5071     if (wined3d_caps.MaxSimultaneousTextures > 0xffff) desc7->wMaxSimultaneousTextures = 0xffff;
5072     else desc7->wMaxSimultaneousTextures = (WORD)wined3d_caps.MaxSimultaneousTextures;
5073
5074     if (wined3d_caps.MaxUserClipPlanes > 0xffff) desc7->wMaxUserClipPlanes = 0xffff;
5075     else desc7->wMaxUserClipPlanes = (WORD)wined3d_caps.MaxUserClipPlanes;
5076     if (wined3d_caps.MaxVertexBlendMatrices > 0xffff) desc7->wMaxVertexBlendMatrices = 0xffff;
5077     else desc7->wMaxVertexBlendMatrices = (WORD)wined3d_caps.MaxVertexBlendMatrices;
5078
5079     desc7->deviceGUID = IID_IDirect3DTnLHalDevice;
5080
5081     desc7->dwReserved1 = 0;
5082     desc7->dwReserved2 = 0;
5083     desc7->dwReserved3 = 0;
5084     desc7->dwReserved4 = 0;
5085
5086     /* Fill the old structure */
5087     memset(desc1, 0, sizeof(*desc1));
5088     desc1->dwSize = sizeof(D3DDEVICEDESC);
5089     desc1->dwFlags = D3DDD_COLORMODEL
5090             | D3DDD_DEVCAPS
5091             | D3DDD_TRANSFORMCAPS
5092             | D3DDD_BCLIPPING
5093             | D3DDD_LIGHTINGCAPS
5094             | D3DDD_LINECAPS
5095             | D3DDD_TRICAPS
5096             | D3DDD_DEVICERENDERBITDEPTH
5097             | D3DDD_DEVICEZBUFFERBITDEPTH
5098             | D3DDD_MAXBUFFERSIZE
5099             | D3DDD_MAXVERTEXCOUNT;
5100
5101     desc1->dcmColorModel = D3DCOLOR_RGB;
5102     desc1->dwDevCaps = desc7->dwDevCaps;
5103     desc1->dtcTransformCaps.dwSize = sizeof(D3DTRANSFORMCAPS);
5104     desc1->dtcTransformCaps.dwCaps = D3DTRANSFORMCAPS_CLIP;
5105     desc1->bClipping = TRUE;
5106     desc1->dlcLightingCaps.dwSize = sizeof(D3DLIGHTINGCAPS);
5107     desc1->dlcLightingCaps.dwCaps = D3DLIGHTCAPS_DIRECTIONAL
5108             | D3DLIGHTCAPS_PARALLELPOINT
5109             | D3DLIGHTCAPS_POINT
5110             | D3DLIGHTCAPS_SPOT;
5111
5112     desc1->dlcLightingCaps.dwLightingModel = D3DLIGHTINGMODEL_RGB;
5113     desc1->dlcLightingCaps.dwNumLights = desc7->dwMaxActiveLights;
5114
5115     desc1->dpcLineCaps.dwSize = sizeof(D3DPRIMCAPS);
5116     desc1->dpcLineCaps.dwMiscCaps = desc7->dpcLineCaps.dwMiscCaps;
5117     desc1->dpcLineCaps.dwRasterCaps = desc7->dpcLineCaps.dwRasterCaps;
5118     desc1->dpcLineCaps.dwZCmpCaps = desc7->dpcLineCaps.dwZCmpCaps;
5119     desc1->dpcLineCaps.dwSrcBlendCaps = desc7->dpcLineCaps.dwSrcBlendCaps;
5120     desc1->dpcLineCaps.dwDestBlendCaps = desc7->dpcLineCaps.dwDestBlendCaps;
5121     desc1->dpcLineCaps.dwShadeCaps = desc7->dpcLineCaps.dwShadeCaps;
5122     desc1->dpcLineCaps.dwTextureCaps = desc7->dpcLineCaps.dwTextureCaps;
5123     desc1->dpcLineCaps.dwTextureFilterCaps = desc7->dpcLineCaps.dwTextureFilterCaps;
5124     desc1->dpcLineCaps.dwTextureBlendCaps = desc7->dpcLineCaps.dwTextureBlendCaps;
5125     desc1->dpcLineCaps.dwTextureAddressCaps = desc7->dpcLineCaps.dwTextureAddressCaps;
5126     desc1->dpcLineCaps.dwStippleWidth = desc7->dpcLineCaps.dwStippleWidth;
5127     desc1->dpcLineCaps.dwAlphaCmpCaps = desc7->dpcLineCaps.dwAlphaCmpCaps;
5128
5129     desc1->dpcTriCaps.dwSize = sizeof(D3DPRIMCAPS);
5130     desc1->dpcTriCaps.dwMiscCaps = desc7->dpcTriCaps.dwMiscCaps;
5131     desc1->dpcTriCaps.dwRasterCaps = desc7->dpcTriCaps.dwRasterCaps;
5132     desc1->dpcTriCaps.dwZCmpCaps = desc7->dpcTriCaps.dwZCmpCaps;
5133     desc1->dpcTriCaps.dwSrcBlendCaps = desc7->dpcTriCaps.dwSrcBlendCaps;
5134     desc1->dpcTriCaps.dwDestBlendCaps = desc7->dpcTriCaps.dwDestBlendCaps;
5135     desc1->dpcTriCaps.dwShadeCaps = desc7->dpcTriCaps.dwShadeCaps;
5136     desc1->dpcTriCaps.dwTextureCaps = desc7->dpcTriCaps.dwTextureCaps;
5137     desc1->dpcTriCaps.dwTextureFilterCaps = desc7->dpcTriCaps.dwTextureFilterCaps;
5138     desc1->dpcTriCaps.dwTextureBlendCaps = desc7->dpcTriCaps.dwTextureBlendCaps;
5139     desc1->dpcTriCaps.dwTextureAddressCaps = desc7->dpcTriCaps.dwTextureAddressCaps;
5140     desc1->dpcTriCaps.dwStippleWidth = desc7->dpcTriCaps.dwStippleWidth;
5141     desc1->dpcTriCaps.dwAlphaCmpCaps = desc7->dpcTriCaps.dwAlphaCmpCaps;
5142
5143     desc1->dwDeviceRenderBitDepth = desc7->dwDeviceRenderBitDepth;
5144     desc1->dwDeviceZBufferBitDepth = desc7->dwDeviceZBufferBitDepth;
5145     desc1->dwMaxBufferSize = 0;
5146     desc1->dwMaxVertexCount = 65536;
5147     desc1->dwMinTextureWidth  = desc7->dwMinTextureWidth;
5148     desc1->dwMinTextureHeight = desc7->dwMinTextureHeight;
5149     desc1->dwMaxTextureWidth  = desc7->dwMaxTextureWidth;
5150     desc1->dwMaxTextureHeight = desc7->dwMaxTextureHeight;
5151     desc1->dwMinStippleWidth  = 1;
5152     desc1->dwMinStippleHeight = 1;
5153     desc1->dwMaxStippleWidth  = 32;
5154     desc1->dwMaxStippleHeight = 32;
5155     desc1->dwMaxTextureRepeat = desc7->dwMaxTextureRepeat;
5156     desc1->dwMaxTextureAspectRatio = desc7->dwMaxTextureAspectRatio;
5157     desc1->dwMaxAnisotropy = desc7->dwMaxAnisotropy;
5158     desc1->dvGuardBandLeft = desc7->dvGuardBandLeft;
5159     desc1->dvGuardBandRight = desc7->dvGuardBandRight;
5160     desc1->dvGuardBandTop = desc7->dvGuardBandTop;
5161     desc1->dvGuardBandBottom = desc7->dvGuardBandBottom;
5162     desc1->dvExtentsAdjust = desc7->dvExtentsAdjust;
5163     desc1->dwStencilCaps = desc7->dwStencilCaps;
5164     desc1->dwFVFCaps = desc7->dwFVFCaps;
5165     desc1->dwTextureOpCaps = desc7->dwTextureOpCaps;
5166     desc1->wMaxTextureBlendStages = desc7->wMaxTextureBlendStages;
5167     desc1->wMaxSimultaneousTextures = desc7->wMaxSimultaneousTextures;
5168
5169     return DD_OK;
5170 }
5171
5172 /*****************************************************************************
5173  * IDirectDraw7 VTable
5174  *****************************************************************************/
5175 static const struct IDirectDraw7Vtbl ddraw7_vtbl =
5176 {
5177     /* IUnknown */
5178     ddraw7_QueryInterface,
5179     ddraw7_AddRef,
5180     ddraw7_Release,
5181     /* IDirectDraw */
5182     ddraw7_Compact,
5183     ddraw7_CreateClipper,
5184     ddraw7_CreatePalette,
5185     ddraw7_CreateSurface,
5186     ddraw7_DuplicateSurface,
5187     ddraw7_EnumDisplayModes,
5188     ddraw7_EnumSurfaces,
5189     ddraw7_FlipToGDISurface,
5190     ddraw7_GetCaps,
5191     ddraw7_GetDisplayMode,
5192     ddraw7_GetFourCCCodes,
5193     ddraw7_GetGDISurface,
5194     ddraw7_GetMonitorFrequency,
5195     ddraw7_GetScanLine,
5196     ddraw7_GetVerticalBlankStatus,
5197     ddraw7_Initialize,
5198     ddraw7_RestoreDisplayMode,
5199     ddraw7_SetCooperativeLevel,
5200     ddraw7_SetDisplayMode,
5201     ddraw7_WaitForVerticalBlank,
5202     /* IDirectDraw2 */
5203     ddraw7_GetAvailableVidMem,
5204     /* IDirectDraw3 */
5205     ddraw7_GetSurfaceFromDC,
5206     /* IDirectDraw4 */
5207     ddraw7_RestoreAllSurfaces,
5208     ddraw7_TestCooperativeLevel,
5209     ddraw7_GetDeviceIdentifier,
5210     /* IDirectDraw7 */
5211     ddraw7_StartModeTest,
5212     ddraw7_EvaluateMode
5213 };
5214
5215 static const struct IDirectDraw4Vtbl ddraw4_vtbl =
5216 {
5217     /* IUnknown */
5218     ddraw4_QueryInterface,
5219     ddraw4_AddRef,
5220     ddraw4_Release,
5221     /* IDirectDraw */
5222     ddraw4_Compact,
5223     ddraw4_CreateClipper,
5224     ddraw4_CreatePalette,
5225     ddraw4_CreateSurface,
5226     ddraw4_DuplicateSurface,
5227     ddraw4_EnumDisplayModes,
5228     ddraw4_EnumSurfaces,
5229     ddraw4_FlipToGDISurface,
5230     ddraw4_GetCaps,
5231     ddraw4_GetDisplayMode,
5232     ddraw4_GetFourCCCodes,
5233     ddraw4_GetGDISurface,
5234     ddraw4_GetMonitorFrequency,
5235     ddraw4_GetScanLine,
5236     ddraw4_GetVerticalBlankStatus,
5237     ddraw4_Initialize,
5238     ddraw4_RestoreDisplayMode,
5239     ddraw4_SetCooperativeLevel,
5240     ddraw4_SetDisplayMode,
5241     ddraw4_WaitForVerticalBlank,
5242     /* IDirectDraw2 */
5243     ddraw4_GetAvailableVidMem,
5244     /* IDirectDraw3 */
5245     ddraw4_GetSurfaceFromDC,
5246     /* IDirectDraw4 */
5247     ddraw4_RestoreAllSurfaces,
5248     ddraw4_TestCooperativeLevel,
5249     ddraw4_GetDeviceIdentifier,
5250 };
5251
5252 static const struct IDirectDraw3Vtbl ddraw3_vtbl =
5253 {
5254     /* IUnknown */
5255     ddraw3_QueryInterface,
5256     ddraw3_AddRef,
5257     ddraw3_Release,
5258     /* IDirectDraw */
5259     ddraw3_Compact,
5260     ddraw3_CreateClipper,
5261     ddraw3_CreatePalette,
5262     ddraw3_CreateSurface,
5263     ddraw3_DuplicateSurface,
5264     ddraw3_EnumDisplayModes,
5265     ddraw3_EnumSurfaces,
5266     ddraw3_FlipToGDISurface,
5267     ddraw3_GetCaps,
5268     ddraw3_GetDisplayMode,
5269     ddraw3_GetFourCCCodes,
5270     ddraw3_GetGDISurface,
5271     ddraw3_GetMonitorFrequency,
5272     ddraw3_GetScanLine,
5273     ddraw3_GetVerticalBlankStatus,
5274     ddraw3_Initialize,
5275     ddraw3_RestoreDisplayMode,
5276     ddraw3_SetCooperativeLevel,
5277     ddraw3_SetDisplayMode,
5278     ddraw3_WaitForVerticalBlank,
5279     /* IDirectDraw2 */
5280     ddraw3_GetAvailableVidMem,
5281     /* IDirectDraw3 */
5282     ddraw3_GetSurfaceFromDC,
5283 };
5284
5285 static const struct IDirectDraw2Vtbl ddraw2_vtbl =
5286 {
5287     /* IUnknown */
5288     ddraw2_QueryInterface,
5289     ddraw2_AddRef,
5290     ddraw2_Release,
5291     /* IDirectDraw */
5292     ddraw2_Compact,
5293     ddraw2_CreateClipper,
5294     ddraw2_CreatePalette,
5295     ddraw2_CreateSurface,
5296     ddraw2_DuplicateSurface,
5297     ddraw2_EnumDisplayModes,
5298     ddraw2_EnumSurfaces,
5299     ddraw2_FlipToGDISurface,
5300     ddraw2_GetCaps,
5301     ddraw2_GetDisplayMode,
5302     ddraw2_GetFourCCCodes,
5303     ddraw2_GetGDISurface,
5304     ddraw2_GetMonitorFrequency,
5305     ddraw2_GetScanLine,
5306     ddraw2_GetVerticalBlankStatus,
5307     ddraw2_Initialize,
5308     ddraw2_RestoreDisplayMode,
5309     ddraw2_SetCooperativeLevel,
5310     ddraw2_SetDisplayMode,
5311     ddraw2_WaitForVerticalBlank,
5312     /* IDirectDraw2 */
5313     ddraw2_GetAvailableVidMem,
5314 };
5315
5316 static const struct IDirectDrawVtbl ddraw1_vtbl =
5317 {
5318     /* IUnknown */
5319     ddraw1_QueryInterface,
5320     ddraw1_AddRef,
5321     ddraw1_Release,
5322     /* IDirectDraw */
5323     ddraw1_Compact,
5324     ddraw1_CreateClipper,
5325     ddraw1_CreatePalette,
5326     ddraw1_CreateSurface,
5327     ddraw1_DuplicateSurface,
5328     ddraw1_EnumDisplayModes,
5329     ddraw1_EnumSurfaces,
5330     ddraw1_FlipToGDISurface,
5331     ddraw1_GetCaps,
5332     ddraw1_GetDisplayMode,
5333     ddraw1_GetFourCCCodes,
5334     ddraw1_GetGDISurface,
5335     ddraw1_GetMonitorFrequency,
5336     ddraw1_GetScanLine,
5337     ddraw1_GetVerticalBlankStatus,
5338     ddraw1_Initialize,
5339     ddraw1_RestoreDisplayMode,
5340     ddraw1_SetCooperativeLevel,
5341     ddraw1_SetDisplayMode,
5342     ddraw1_WaitForVerticalBlank,
5343 };
5344
5345 static const struct IDirect3D7Vtbl d3d7_vtbl =
5346 {
5347     /* IUnknown methods */
5348     d3d7_QueryInterface,
5349     d3d7_AddRef,
5350     d3d7_Release,
5351     /* IDirect3D7 methods */
5352     d3d7_EnumDevices,
5353     d3d7_CreateDevice,
5354     d3d7_CreateVertexBuffer,
5355     d3d7_EnumZBufferFormats,
5356     d3d7_EvictManagedTextures
5357 };
5358
5359 static const struct IDirect3D3Vtbl d3d3_vtbl =
5360 {
5361     /* IUnknown methods */
5362     d3d3_QueryInterface,
5363     d3d3_AddRef,
5364     d3d3_Release,
5365     /* IDirect3D3 methods */
5366     d3d3_EnumDevices,
5367     d3d3_CreateLight,
5368     d3d3_CreateMaterial,
5369     d3d3_CreateViewport,
5370     d3d3_FindDevice,
5371     d3d3_CreateDevice,
5372     d3d3_CreateVertexBuffer,
5373     d3d3_EnumZBufferFormats,
5374     d3d3_EvictManagedTextures
5375 };
5376
5377 static const struct IDirect3D2Vtbl d3d2_vtbl =
5378 {
5379     /* IUnknown methods */
5380     d3d2_QueryInterface,
5381     d3d2_AddRef,
5382     d3d2_Release,
5383     /* IDirect3D2 methods */
5384     d3d2_EnumDevices,
5385     d3d2_CreateLight,
5386     d3d2_CreateMaterial,
5387     d3d2_CreateViewport,
5388     d3d2_FindDevice,
5389     d3d2_CreateDevice
5390 };
5391
5392 static const struct IDirect3DVtbl d3d1_vtbl =
5393 {
5394     /* IUnknown methods */
5395     d3d1_QueryInterface,
5396     d3d1_AddRef,
5397     d3d1_Release,
5398     /* IDirect3D methods */
5399     d3d1_Initialize,
5400     d3d1_EnumDevices,
5401     d3d1_CreateLight,
5402     d3d1_CreateMaterial,
5403     d3d1_CreateViewport,
5404     d3d1_FindDevice
5405 };
5406
5407 /*****************************************************************************
5408  * ddraw_find_decl
5409  *
5410  * Finds the WineD3D vertex declaration for a specific fvf, and creates one
5411  * if none was found.
5412  *
5413  * This function is in ddraw.c and the DDraw object space because D3D7
5414  * vertex buffers are created using the IDirect3D interface to the ddraw
5415  * object, so they can be valid across D3D devices(theoretically. The ddraw
5416  * object also owns the wined3d device
5417  *
5418  * Parameters:
5419  *  This: Device
5420  *  fvf: Fvf to find the decl for
5421  *
5422  * Returns:
5423  *  NULL in case of an error, the IWineD3DVertexDeclaration interface for the
5424  *  fvf otherwise.
5425  *
5426  *****************************************************************************/
5427 IWineD3DVertexDeclaration *ddraw_find_decl(IDirectDrawImpl *This, DWORD fvf)
5428 {
5429     HRESULT hr;
5430     IWineD3DVertexDeclaration* pDecl = NULL;
5431     int p, low, high; /* deliberately signed */
5432     struct FvfToDecl *convertedDecls = This->decls;
5433
5434     TRACE("Searching for declaration for fvf %08x... ", fvf);
5435
5436     low = 0;
5437     high = This->numConvertedDecls - 1;
5438     while(low <= high) {
5439         p = (low + high) >> 1;
5440         TRACE("%d ", p);
5441         if(convertedDecls[p].fvf == fvf) {
5442             TRACE("found %p\n", convertedDecls[p].decl);
5443             return convertedDecls[p].decl;
5444         } else if(convertedDecls[p].fvf < fvf) {
5445             low = p + 1;
5446         } else {
5447             high = p - 1;
5448         }
5449     }
5450     TRACE("not found. Creating and inserting at position %d.\n", low);
5451
5452     hr = IWineD3DDevice_CreateVertexDeclarationFromFVF(This->wineD3DDevice,
5453             fvf, This, &ddraw_null_wined3d_parent_ops, &pDecl);
5454     if (hr != S_OK) return NULL;
5455
5456     if(This->declArraySize == This->numConvertedDecls) {
5457         int grow = max(This->declArraySize / 2, 8);
5458         convertedDecls = HeapReAlloc(GetProcessHeap(), 0, convertedDecls,
5459                                      sizeof(convertedDecls[0]) * (This->numConvertedDecls + grow));
5460         if(!convertedDecls) {
5461             /* This will destroy it */
5462             IWineD3DVertexDeclaration_Release(pDecl);
5463             return NULL;
5464         }
5465         This->decls = convertedDecls;
5466         This->declArraySize += grow;
5467     }
5468
5469     memmove(convertedDecls + low + 1, convertedDecls + low, sizeof(convertedDecls[0]) * (This->numConvertedDecls - low));
5470     convertedDecls[low].decl = pDecl;
5471     convertedDecls[low].fvf = fvf;
5472     This->numConvertedDecls++;
5473
5474     TRACE("Returning %p. %d decls in array\n", pDecl, This->numConvertedDecls);
5475     return pDecl;
5476 }
5477
5478 /* IWineD3DDeviceParent IUnknown methods */
5479
5480 static inline struct IDirectDrawImpl *ddraw_from_device_parent(IWineD3DDeviceParent *iface)
5481 {
5482     return (struct IDirectDrawImpl *)((char*)iface - FIELD_OFFSET(struct IDirectDrawImpl, device_parent_vtbl));
5483 }
5484
5485 static HRESULT STDMETHODCALLTYPE device_parent_QueryInterface(IWineD3DDeviceParent *iface, REFIID riid, void **object)
5486 {
5487     struct IDirectDrawImpl *This = ddraw_from_device_parent(iface);
5488     return ddraw7_QueryInterface((IDirectDraw7 *)This, riid, object);
5489 }
5490
5491 static ULONG STDMETHODCALLTYPE device_parent_AddRef(IWineD3DDeviceParent *iface)
5492 {
5493     struct IDirectDrawImpl *This = ddraw_from_device_parent(iface);
5494     return ddraw7_AddRef((IDirectDraw7 *)This);
5495 }
5496
5497 static ULONG STDMETHODCALLTYPE device_parent_Release(IWineD3DDeviceParent *iface)
5498 {
5499     struct IDirectDrawImpl *This = ddraw_from_device_parent(iface);
5500     return ddraw7_Release((IDirectDraw7 *)This);
5501 }
5502
5503 /* IWineD3DDeviceParent methods */
5504
5505 static void STDMETHODCALLTYPE device_parent_WineD3DDeviceCreated(IWineD3DDeviceParent *iface, IWineD3DDevice *device)
5506 {
5507     TRACE("iface %p, device %p\n", iface, device);
5508 }
5509
5510 static HRESULT STDMETHODCALLTYPE device_parent_CreateSurface(IWineD3DDeviceParent *iface,
5511         IUnknown *superior, UINT width, UINT height, enum wined3d_format_id format, DWORD usage,
5512         WINED3DPOOL pool, UINT level, WINED3DCUBEMAP_FACES face, IWineD3DSurface **surface)
5513 {
5514     struct IDirectDrawImpl *This = ddraw_from_device_parent(iface);
5515     IDirectDrawSurfaceImpl *surf = NULL;
5516     UINT i = 0;
5517     DDSCAPS2 searchcaps = This->tex_root->surface_desc.ddsCaps;
5518
5519     TRACE("iface %p, superior %p, width %u, height %u, format %#x, usage %#x,\n"
5520             "\tpool %#x, level %u, face %u, surface %p\n",
5521             iface, superior, width, height, format, usage, pool, level, face, surface);
5522
5523     searchcaps.dwCaps2 &= ~DDSCAPS2_CUBEMAP_ALLFACES;
5524     switch(face)
5525     {
5526         case WINED3DCUBEMAP_FACE_POSITIVE_X:
5527             TRACE("Asked for positive x\n");
5528             if (searchcaps.dwCaps2 & DDSCAPS2_CUBEMAP)
5529             {
5530                 searchcaps.dwCaps2 |= DDSCAPS2_CUBEMAP_POSITIVEX;
5531             }
5532             surf = This->tex_root; break;
5533         case WINED3DCUBEMAP_FACE_NEGATIVE_X:
5534             TRACE("Asked for negative x\n");
5535             searchcaps.dwCaps2 |= DDSCAPS2_CUBEMAP_NEGATIVEX; break;
5536         case WINED3DCUBEMAP_FACE_POSITIVE_Y:
5537             TRACE("Asked for positive y\n");
5538             searchcaps.dwCaps2 |= DDSCAPS2_CUBEMAP_POSITIVEY; break;
5539         case WINED3DCUBEMAP_FACE_NEGATIVE_Y:
5540             TRACE("Asked for negative y\n");
5541             searchcaps.dwCaps2 |= DDSCAPS2_CUBEMAP_NEGATIVEY; break;
5542         case WINED3DCUBEMAP_FACE_POSITIVE_Z:
5543             TRACE("Asked for positive z\n");
5544             searchcaps.dwCaps2 |= DDSCAPS2_CUBEMAP_POSITIVEZ; break;
5545         case WINED3DCUBEMAP_FACE_NEGATIVE_Z:
5546             TRACE("Asked for negative z\n");
5547             searchcaps.dwCaps2 |= DDSCAPS2_CUBEMAP_NEGATIVEZ; break;
5548         default: {ERR("Unexpected cube face\n");} /* Stupid compiler */
5549     }
5550
5551     if (!surf)
5552     {
5553         IDirectDrawSurface7 *attached;
5554         IDirectDrawSurface7_GetAttachedSurface((IDirectDrawSurface7 *)This->tex_root, &searchcaps, &attached);
5555         surf = (IDirectDrawSurfaceImpl *)attached;
5556         IDirectDrawSurface7_Release(attached);
5557     }
5558     if (!surf) ERR("root search surface not found\n");
5559
5560     /* Find the wanted mipmap. There are enough mipmaps in the chain */
5561     while (i < level)
5562     {
5563         IDirectDrawSurface7 *attached;
5564         IDirectDrawSurface7_GetAttachedSurface((IDirectDrawSurface7 *)surf, &searchcaps, &attached);
5565         if(!attached) ERR("Surface not found\n");
5566         surf = (IDirectDrawSurfaceImpl *)attached;
5567         IDirectDrawSurface7_Release(attached);
5568         ++i;
5569     }
5570
5571     /* Return the surface */
5572     *surface = surf->WineD3DSurface;
5573     IWineD3DSurface_AddRef(*surface);
5574
5575     TRACE("Returning wineD3DSurface %p, it belongs to surface %p\n", *surface, surf);
5576
5577     return D3D_OK;
5578 }
5579
5580 static HRESULT WINAPI findRenderTarget(IDirectDrawSurface7 *surface, DDSURFACEDESC2 *surface_desc, void *ctx)
5581 {
5582     IDirectDrawSurfaceImpl *s = (IDirectDrawSurfaceImpl *)surface;
5583     IDirectDrawSurfaceImpl **target = ctx;
5584
5585     if (!s->isRenderTarget)
5586     {
5587         *target = s;
5588         IDirectDrawSurface7_Release(surface);
5589         return DDENUMRET_CANCEL;
5590     }
5591
5592     /* Recurse into the surface tree */
5593     IDirectDrawSurface7_EnumAttachedSurfaces(surface, ctx, findRenderTarget);
5594
5595     IDirectDrawSurface7_Release(surface);
5596     if (*target) return DDENUMRET_CANCEL;
5597
5598     return DDENUMRET_OK;
5599 }
5600
5601 static HRESULT STDMETHODCALLTYPE device_parent_CreateRenderTarget(IWineD3DDeviceParent *iface,
5602         IUnknown *superior, UINT width, UINT height, enum wined3d_format_id format,
5603         WINED3DMULTISAMPLE_TYPE multisample_type, DWORD multisample_quality, BOOL lockable,
5604         IWineD3DSurface **surface)
5605 {
5606     struct IDirectDrawImpl *This = ddraw_from_device_parent(iface);
5607     IDirectDrawSurfaceImpl *d3d_surface = This->d3d_target;
5608     IDirectDrawSurfaceImpl *target = NULL;
5609
5610     TRACE("iface %p, superior %p, width %u, height %u, format %#x, multisample_type %#x,\n"
5611             "\tmultisample_quality %u, lockable %u, surface %p\n",
5612             iface, superior, width, height, format, multisample_type, multisample_quality, lockable, surface);
5613
5614     if (d3d_surface->isRenderTarget)
5615     {
5616         IDirectDrawSurface7_EnumAttachedSurfaces((IDirectDrawSurface7 *)d3d_surface, &target, findRenderTarget);
5617     }
5618     else
5619     {
5620         target = d3d_surface;
5621     }
5622
5623     if (!target)
5624     {
5625         target = This->d3d_target;
5626         ERR(" (%p) : No DirectDrawSurface found to create the back buffer. Using the front buffer as back buffer. Uncertain consequences\n", This);
5627     }
5628
5629     /* TODO: Return failure if the dimensions do not match, but this shouldn't happen */
5630
5631     *surface = target->WineD3DSurface;
5632     IWineD3DSurface_AddRef(*surface);
5633     target->isRenderTarget = TRUE;
5634
5635     TRACE("Returning wineD3DSurface %p, it belongs to surface %p\n", *surface, d3d_surface);
5636
5637     return D3D_OK;
5638 }
5639
5640 static HRESULT STDMETHODCALLTYPE device_parent_CreateDepthStencilSurface(IWineD3DDeviceParent *iface,
5641         UINT width, UINT height, enum wined3d_format_id format, WINED3DMULTISAMPLE_TYPE multisample_type,
5642         DWORD multisample_quality, BOOL discard, IWineD3DSurface **surface)
5643 {
5644     struct IDirectDrawImpl *This = ddraw_from_device_parent(iface);
5645     IDirectDrawSurfaceImpl *ddraw_surface;
5646     DDSURFACEDESC2 ddsd;
5647     HRESULT hr;
5648
5649     TRACE("iface %p, width %u, height %u, format %#x, multisample_type %#x,\n"
5650             "\tmultisample_quality %u, discard %u, surface %p\n",
5651             iface, width, height, format, multisample_type, multisample_quality, discard, surface);
5652
5653     *surface = NULL;
5654
5655     /* Create a DirectDraw surface */
5656     memset(&ddsd, 0, sizeof(ddsd));
5657     ddsd.dwSize = sizeof(ddsd);
5658     ddsd.u4.ddpfPixelFormat.dwSize = sizeof(DDPIXELFORMAT);
5659     ddsd.dwFlags = DDSD_PIXELFORMAT | DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS;
5660     ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
5661     ddsd.dwHeight = height;
5662     ddsd.dwWidth = width;
5663     if (format)
5664     {
5665         PixelFormat_WineD3DtoDD(&ddsd.u4.ddpfPixelFormat, format);
5666     }
5667     else
5668     {
5669         ddsd.dwFlags ^= DDSD_PIXELFORMAT;
5670     }
5671
5672     This->depthstencil = TRUE;
5673     hr = IDirectDraw7_CreateSurface((IDirectDraw7 *)This, &ddsd, (IDirectDrawSurface7 **)&ddraw_surface, NULL);
5674     This->depthstencil = FALSE;
5675     if(FAILED(hr))
5676     {
5677         ERR(" (%p) Creating a DepthStencil Surface failed, result = %x\n", This, hr);
5678         return hr;
5679     }
5680
5681     *surface = ddraw_surface->WineD3DSurface;
5682     IWineD3DSurface_AddRef(*surface);
5683     IDirectDrawSurface7_Release((IDirectDrawSurface7 *)ddraw_surface);
5684
5685     return D3D_OK;
5686 }
5687
5688 static HRESULT STDMETHODCALLTYPE device_parent_CreateVolume(IWineD3DDeviceParent *iface,
5689         IUnknown *superior, UINT width, UINT height, UINT depth, enum wined3d_format_id format,
5690         WINED3DPOOL pool, DWORD usage, IWineD3DVolume **volume)
5691 {
5692     TRACE("iface %p, superior %p, width %u, height %u, depth %u, format %#x, pool %#x, usage %#x, volume %p\n",
5693                 iface, superior, width, height, depth, format, pool, usage, volume);
5694
5695     ERR("Not implemented!\n");
5696
5697     return E_NOTIMPL;
5698 }
5699
5700 static HRESULT STDMETHODCALLTYPE device_parent_CreateSwapChain(IWineD3DDeviceParent *iface,
5701         WINED3DPRESENT_PARAMETERS *present_parameters, IWineD3DSwapChain **swapchain)
5702 {
5703     struct IDirectDrawImpl *This = ddraw_from_device_parent(iface);
5704     IDirectDrawSurfaceImpl *iterator;
5705     IParentImpl *object;
5706     HRESULT hr;
5707
5708     TRACE("iface %p, present_parameters %p, swapchain %p\n", iface, present_parameters, swapchain);
5709
5710     object = HeapAlloc(GetProcessHeap(),  HEAP_ZERO_MEMORY, sizeof(IParentImpl));
5711     if (!object)
5712     {
5713         FIXME("Allocation of memory failed\n");
5714         *swapchain = NULL;
5715         return DDERR_OUTOFVIDEOMEMORY;
5716     }
5717
5718     ddraw_parent_init(object);
5719
5720     hr = IWineD3DDevice_CreateSwapChain(This->wineD3DDevice, present_parameters,
5721             This->ImplType, object, swapchain);
5722     if (FAILED(hr))
5723     {
5724         FIXME("(%p) CreateSwapChain failed, returning %#x\n", iface, hr);
5725         HeapFree(GetProcessHeap(), 0 , object);
5726         *swapchain = NULL;
5727         return hr;
5728     }
5729
5730     object->child = (IUnknown *)*swapchain;
5731     This->d3d_target->wineD3DSwapChain = *swapchain;
5732     iterator = This->d3d_target->complex_array[0];
5733     while (iterator)
5734     {
5735         iterator->wineD3DSwapChain = *swapchain;
5736         iterator = iterator->complex_array[0];
5737     }
5738
5739     return hr;
5740 }
5741
5742 static const IWineD3DDeviceParentVtbl ddraw_wined3d_device_parent_vtbl =
5743 {
5744     /* IUnknown methods */
5745     device_parent_QueryInterface,
5746     device_parent_AddRef,
5747     device_parent_Release,
5748     /* IWineD3DDeviceParent methods */
5749     device_parent_WineD3DDeviceCreated,
5750     device_parent_CreateSurface,
5751     device_parent_CreateRenderTarget,
5752     device_parent_CreateDepthStencilSurface,
5753     device_parent_CreateVolume,
5754     device_parent_CreateSwapChain,
5755 };
5756
5757 HRESULT ddraw_init(IDirectDrawImpl *ddraw, WINED3DDEVTYPE device_type)
5758 {
5759     HRESULT hr;
5760     HDC hDC;
5761
5762     ddraw->lpVtbl = &ddraw7_vtbl;
5763     ddraw->IDirectDraw_vtbl = &ddraw1_vtbl;
5764     ddraw->IDirectDraw2_vtbl = &ddraw2_vtbl;
5765     ddraw->IDirectDraw3_vtbl = &ddraw3_vtbl;
5766     ddraw->IDirectDraw4_vtbl = &ddraw4_vtbl;
5767     ddraw->IDirect3D_vtbl = &d3d1_vtbl;
5768     ddraw->IDirect3D2_vtbl = &d3d2_vtbl;
5769     ddraw->IDirect3D3_vtbl = &d3d3_vtbl;
5770     ddraw->IDirect3D7_vtbl = &d3d7_vtbl;
5771     ddraw->device_parent_vtbl = &ddraw_wined3d_device_parent_vtbl;
5772     ddraw->numIfaces = 1;
5773     ddraw->ref7 = 1;
5774
5775     /* See comments in IDirectDrawImpl_CreateNewSurface for a description of
5776      * this field. */
5777     ddraw->ImplType = DefaultSurfaceType;
5778
5779     /* Get the current screen settings. */
5780     hDC = GetDC(0);
5781     ddraw->orig_bpp = GetDeviceCaps(hDC, BITSPIXEL) * GetDeviceCaps(hDC, PLANES);
5782     ReleaseDC(0, hDC);
5783     ddraw->orig_width = GetSystemMetrics(SM_CXSCREEN);
5784     ddraw->orig_height = GetSystemMetrics(SM_CYSCREEN);
5785
5786     if (!LoadWineD3D())
5787     {
5788         ERR("Failed to load wined3d - broken OpenGL setup?\n");
5789         return DDERR_NODIRECTDRAWSUPPORT;
5790     }
5791
5792     ddraw->wineD3D = pWineDirect3DCreate(7, (IUnknown *)ddraw);
5793     if (!ddraw->wineD3D)
5794     {
5795         WARN("Failed to create a wined3d object.\n");
5796         return E_OUTOFMEMORY;
5797     }
5798
5799     hr = IWineD3D_CreateDevice(ddraw->wineD3D, WINED3DADAPTER_DEFAULT, device_type, NULL, 0,
5800             (IWineD3DDeviceParent *)&ddraw->device_parent_vtbl, &ddraw->wineD3DDevice);
5801     if (FAILED(hr))
5802     {
5803         WARN("Failed to create a wined3d device, hr %#x.\n", hr);
5804         IWineD3D_Release(ddraw->wineD3D);
5805         return hr;
5806     }
5807
5808     /* Get the amount of video memory */
5809     ddraw->total_vidmem = IWineD3DDevice_GetAvailableTextureMem(ddraw->wineD3DDevice);
5810
5811     list_init(&ddraw->surface_list);
5812
5813     return DD_OK;
5814 }