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