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