comctl32/imagelist: Use proper color format for merged image lists.
[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 == DDRAW_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 == DDRAW_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 != DDRAW_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
1210      * configured not to use it. */
1211     if (DefaultSurfaceType == DDRAW_SURFACE_TYPE_GDI)
1212     {
1213         caps.dwCaps &= ~DDCAPS_3D;
1214         caps.ddsCaps.dwCaps &= ~(DDSCAPS_3DDEVICE | DDSCAPS_MIPMAP | DDSCAPS_TEXTURE | DDSCAPS_ZBUFFER);
1215     }
1216     if (winecaps.ddraw_caps.stride_align)
1217     {
1218         caps.dwCaps |= DDCAPS_ALIGNSTRIDE;
1219         caps.dwAlignStrideAlign = winecaps.ddraw_caps.stride_align;
1220     }
1221
1222     if(DriverCaps)
1223     {
1224         DD_STRUCT_COPY_BYSIZE(DriverCaps, &caps);
1225         if (TRACE_ON(ddraw))
1226         {
1227             TRACE("Driver Caps :\n");
1228             DDRAW_dump_DDCAPS(DriverCaps);
1229         }
1230
1231     }
1232     if(HELCaps)
1233     {
1234         DD_STRUCT_COPY_BYSIZE(HELCaps, &caps);
1235         if (TRACE_ON(ddraw))
1236         {
1237             TRACE("HEL Caps :\n");
1238             DDRAW_dump_DDCAPS(HELCaps);
1239         }
1240     }
1241
1242     return DD_OK;
1243 }
1244
1245 static HRESULT WINAPI ddraw4_GetCaps(IDirectDraw4 *iface, DDCAPS *driver_caps, DDCAPS *hel_caps)
1246 {
1247     struct ddraw *ddraw = impl_from_IDirectDraw4(iface);
1248
1249     TRACE("iface %p, driver_caps %p, hel_caps %p.\n", iface, driver_caps, hel_caps);
1250
1251     return ddraw7_GetCaps(&ddraw->IDirectDraw7_iface, driver_caps, hel_caps);
1252 }
1253
1254 static HRESULT WINAPI ddraw2_GetCaps(IDirectDraw2 *iface, DDCAPS *driver_caps, DDCAPS *hel_caps)
1255 {
1256     struct ddraw *ddraw = impl_from_IDirectDraw2(iface);
1257
1258     TRACE("iface %p, driver_caps %p, hel_caps %p.\n", iface, driver_caps, hel_caps);
1259
1260     return ddraw7_GetCaps(&ddraw->IDirectDraw7_iface, driver_caps, hel_caps);
1261 }
1262
1263 static HRESULT WINAPI ddraw1_GetCaps(IDirectDraw *iface, DDCAPS *driver_caps, DDCAPS *hel_caps)
1264 {
1265     struct ddraw *ddraw = impl_from_IDirectDraw(iface);
1266
1267     TRACE("iface %p, driver_caps %p, hel_caps %p.\n", iface, driver_caps, hel_caps);
1268
1269     return ddraw7_GetCaps(&ddraw->IDirectDraw7_iface, driver_caps, hel_caps);
1270 }
1271
1272 /*****************************************************************************
1273  * IDirectDraw7::Compact
1274  *
1275  * No idea what it does, MSDN says it's not implemented.
1276  *
1277  * Returns
1278  *  DD_OK, but this is unchecked
1279  *
1280  *****************************************************************************/
1281 static HRESULT WINAPI ddraw7_Compact(IDirectDraw7 *iface)
1282 {
1283     TRACE("iface %p.\n", iface);
1284
1285     return DD_OK;
1286 }
1287
1288 static HRESULT WINAPI ddraw4_Compact(IDirectDraw4 *iface)
1289 {
1290     struct ddraw *ddraw = impl_from_IDirectDraw4(iface);
1291
1292     TRACE("iface %p.\n", iface);
1293
1294     return ddraw7_Compact(&ddraw->IDirectDraw7_iface);
1295 }
1296
1297 static HRESULT WINAPI ddraw2_Compact(IDirectDraw2 *iface)
1298 {
1299     struct ddraw *ddraw = impl_from_IDirectDraw2(iface);
1300
1301     TRACE("iface %p.\n", iface);
1302
1303     return ddraw7_Compact(&ddraw->IDirectDraw7_iface);
1304 }
1305
1306 static HRESULT WINAPI ddraw1_Compact(IDirectDraw *iface)
1307 {
1308     struct ddraw *ddraw = impl_from_IDirectDraw(iface);
1309
1310     TRACE("iface %p.\n", iface);
1311
1312     return ddraw7_Compact(&ddraw->IDirectDraw7_iface);
1313 }
1314
1315 /*****************************************************************************
1316  * IDirectDraw7::GetDisplayMode
1317  *
1318  * Returns information about the current display mode
1319  *
1320  * Exists in Version 1, 2, 4 and 7
1321  *
1322  * Params:
1323  *  DDSD: Address of a surface description structure to write the info to
1324  *
1325  * Returns
1326  *  DD_OK
1327  *
1328  *****************************************************************************/
1329 static HRESULT WINAPI ddraw7_GetDisplayMode(IDirectDraw7 *iface, DDSURFACEDESC2 *DDSD)
1330 {
1331     struct ddraw *ddraw = impl_from_IDirectDraw7(iface);
1332     struct wined3d_display_mode mode;
1333     HRESULT hr;
1334     DWORD Size;
1335
1336     TRACE("iface %p, surface_desc %p.\n", iface, DDSD);
1337
1338     wined3d_mutex_lock();
1339     /* This seems sane */
1340     if (!DDSD)
1341     {
1342         wined3d_mutex_unlock();
1343         return DDERR_INVALIDPARAMS;
1344     }
1345
1346     if (FAILED(hr = wined3d_get_adapter_display_mode(ddraw->wined3d, WINED3DADAPTER_DEFAULT, &mode, NULL)))
1347     {
1348         ERR("Failed to get display mode, hr %#x.\n", hr);
1349         wined3d_mutex_unlock();
1350         return hr;
1351     }
1352
1353     Size = DDSD->dwSize;
1354     memset(DDSD, 0, Size);
1355
1356     DDSD->dwSize = Size;
1357     DDSD->dwFlags |= DDSD_HEIGHT | DDSD_WIDTH | DDSD_PIXELFORMAT | DDSD_PITCH | DDSD_REFRESHRATE;
1358     DDSD->dwWidth = mode.width;
1359     DDSD->dwHeight = mode.height;
1360     DDSD->u2.dwRefreshRate = 60;
1361     DDSD->ddsCaps.dwCaps = 0;
1362     DDSD->u4.ddpfPixelFormat.dwSize = sizeof(DDSD->u4.ddpfPixelFormat);
1363     PixelFormat_WineD3DtoDD(&DDSD->u4.ddpfPixelFormat, mode.format_id);
1364     DDSD->u1.lPitch = mode.width * DDSD->u4.ddpfPixelFormat.u1.dwRGBBitCount / 8;
1365
1366     if(TRACE_ON(ddraw))
1367     {
1368         TRACE("Returning surface desc :\n");
1369         DDRAW_dump_surface_desc(DDSD);
1370     }
1371
1372     wined3d_mutex_unlock();
1373
1374     return DD_OK;
1375 }
1376
1377 static HRESULT WINAPI ddraw4_GetDisplayMode(IDirectDraw4 *iface, DDSURFACEDESC2 *surface_desc)
1378 {
1379     struct ddraw *ddraw = impl_from_IDirectDraw4(iface);
1380
1381     TRACE("iface %p, surface_desc %p.\n", iface, surface_desc);
1382
1383     return ddraw7_GetDisplayMode(&ddraw->IDirectDraw7_iface, surface_desc);
1384 }
1385
1386 static HRESULT WINAPI ddraw2_GetDisplayMode(IDirectDraw2 *iface, DDSURFACEDESC *surface_desc)
1387 {
1388     struct ddraw *ddraw = impl_from_IDirectDraw2(iface);
1389
1390     TRACE("iface %p, surface_desc %p.\n", iface, surface_desc);
1391
1392     /* FIXME: Test sizes, properly convert surface_desc */
1393     return ddraw7_GetDisplayMode(&ddraw->IDirectDraw7_iface, (DDSURFACEDESC2 *)surface_desc);
1394 }
1395
1396 static HRESULT WINAPI ddraw1_GetDisplayMode(IDirectDraw *iface, DDSURFACEDESC *surface_desc)
1397 {
1398     struct ddraw *ddraw = impl_from_IDirectDraw(iface);
1399
1400     TRACE("iface %p, surface_desc %p.\n", iface, surface_desc);
1401
1402     /* FIXME: Test sizes, properly convert surface_desc */
1403     return ddraw7_GetDisplayMode(&ddraw->IDirectDraw7_iface, (DDSURFACEDESC2 *)surface_desc);
1404 }
1405
1406 /*****************************************************************************
1407  * IDirectDraw7::GetFourCCCodes
1408  *
1409  * Returns an array of supported FourCC codes.
1410  *
1411  * Exists in Version 1, 2, 4 and 7
1412  *
1413  * Params:
1414  *  NumCodes: Contains the number of Codes that Codes can carry. Returns the number
1415  *            of enumerated codes
1416  *  Codes: Pointer to an array of DWORDs where the supported codes are written
1417  *         to
1418  *
1419  * Returns
1420  *  Always returns DD_OK, as it's a stub for now
1421  *
1422  *****************************************************************************/
1423 static HRESULT WINAPI ddraw7_GetFourCCCodes(IDirectDraw7 *iface, DWORD *NumCodes, DWORD *Codes)
1424 {
1425     struct ddraw *ddraw = impl_from_IDirectDraw7(iface);
1426     static const enum wined3d_format_id formats[] =
1427     {
1428         WINED3DFMT_YUY2, WINED3DFMT_UYVY, WINED3DFMT_YV12,
1429         WINED3DFMT_DXT1, WINED3DFMT_DXT2, WINED3DFMT_DXT3, WINED3DFMT_DXT4, WINED3DFMT_DXT5,
1430         WINED3DFMT_ATI2N, WINED3DFMT_NVHU, WINED3DFMT_NVHS
1431     };
1432     struct wined3d_display_mode mode;
1433     DWORD count = 0, i, outsize;
1434     HRESULT hr;
1435
1436     TRACE("iface %p, codes_count %p, codes %p.\n", iface, NumCodes, Codes);
1437
1438     if (FAILED(hr = wined3d_get_adapter_display_mode(ddraw->wined3d, WINED3DADAPTER_DEFAULT, &mode, NULL)))
1439     {
1440         ERR("Failed to get display mode, hr %#x.\n", hr);
1441         return hr;
1442     }
1443
1444     outsize = NumCodes && Codes ? *NumCodes : 0;
1445
1446     for (i = 0; i < (sizeof(formats) / sizeof(formats[0])); ++i)
1447     {
1448         if (SUCCEEDED(wined3d_check_device_format(ddraw->wined3d, WINED3DADAPTER_DEFAULT, WINED3D_DEVICE_TYPE_HAL,
1449                 mode.format_id, 0, WINED3D_RTYPE_SURFACE, formats[i])))
1450         {
1451             if (count < outsize)
1452                 Codes[count] = formats[i];
1453             ++count;
1454         }
1455     }
1456     if(NumCodes) {
1457         TRACE("Returning %u FourCC codes\n", count);
1458         *NumCodes = count;
1459     }
1460
1461     return DD_OK;
1462 }
1463
1464 static HRESULT WINAPI ddraw4_GetFourCCCodes(IDirectDraw4 *iface, DWORD *codes_count, DWORD *codes)
1465 {
1466     struct ddraw *ddraw = impl_from_IDirectDraw4(iface);
1467
1468     TRACE("iface %p, codes_count %p, codes %p.\n", iface, codes_count, codes);
1469
1470     return ddraw7_GetFourCCCodes(&ddraw->IDirectDraw7_iface, codes_count, codes);
1471 }
1472
1473 static HRESULT WINAPI ddraw2_GetFourCCCodes(IDirectDraw2 *iface, DWORD *codes_count, DWORD *codes)
1474 {
1475     struct ddraw *ddraw = impl_from_IDirectDraw2(iface);
1476
1477     TRACE("iface %p, codes_count %p, codes %p.\n", iface, codes_count, codes);
1478
1479     return ddraw7_GetFourCCCodes(&ddraw->IDirectDraw7_iface, codes_count, codes);
1480 }
1481
1482 static HRESULT WINAPI ddraw1_GetFourCCCodes(IDirectDraw *iface, DWORD *codes_count, DWORD *codes)
1483 {
1484     struct ddraw *ddraw = impl_from_IDirectDraw(iface);
1485
1486     TRACE("iface %p, codes_count %p, codes %p.\n", iface, codes_count, codes);
1487
1488     return ddraw7_GetFourCCCodes(&ddraw->IDirectDraw7_iface, codes_count, codes);
1489 }
1490
1491 static HRESULT WINAPI ddraw7_GetMonitorFrequency(IDirectDraw7 *iface, DWORD *frequency)
1492 {
1493     struct ddraw *ddraw = impl_from_IDirectDraw7(iface);
1494     struct wined3d_display_mode mode;
1495     HRESULT hr;
1496
1497     TRACE("iface %p, frequency %p.\n", iface, frequency);
1498
1499     wined3d_mutex_lock();
1500     hr = wined3d_get_adapter_display_mode(ddraw->wined3d, WINED3DADAPTER_DEFAULT, &mode, NULL);
1501     wined3d_mutex_unlock();
1502     if (FAILED(hr))
1503     {
1504         WARN("Failed to get display mode, hr %#x.\n", hr);
1505         return hr;
1506     }
1507
1508     *frequency = mode.refresh_rate;
1509
1510     return DD_OK;
1511 }
1512
1513 static HRESULT WINAPI ddraw4_GetMonitorFrequency(IDirectDraw4 *iface, DWORD *frequency)
1514 {
1515     struct ddraw *ddraw = impl_from_IDirectDraw4(iface);
1516
1517     TRACE("iface %p, frequency %p.\n", iface, frequency);
1518
1519     return ddraw7_GetMonitorFrequency(&ddraw->IDirectDraw7_iface, frequency);
1520 }
1521
1522 static HRESULT WINAPI ddraw2_GetMonitorFrequency(IDirectDraw2 *iface, DWORD *frequency)
1523 {
1524     struct ddraw *ddraw = impl_from_IDirectDraw2(iface);
1525
1526     TRACE("iface %p, frequency %p.\n", iface, frequency);
1527
1528     return ddraw7_GetMonitorFrequency(&ddraw->IDirectDraw7_iface, frequency);
1529 }
1530
1531 static HRESULT WINAPI ddraw1_GetMonitorFrequency(IDirectDraw *iface, DWORD *frequency)
1532 {
1533     struct ddraw *ddraw = impl_from_IDirectDraw(iface);
1534
1535     TRACE("iface %p, frequency %p.\n", iface, frequency);
1536
1537     return ddraw7_GetMonitorFrequency(&ddraw->IDirectDraw7_iface, frequency);
1538 }
1539
1540 static HRESULT WINAPI ddraw7_GetVerticalBlankStatus(IDirectDraw7 *iface, BOOL *status)
1541 {
1542     struct ddraw *ddraw = impl_from_IDirectDraw7(iface);
1543     struct wined3d_raster_status raster_status;
1544     HRESULT hr;
1545
1546     TRACE("iface %p, status %p.\n", iface, status);
1547
1548     if(!status)
1549         return DDERR_INVALIDPARAMS;
1550
1551     wined3d_mutex_lock();
1552     hr = wined3d_get_adapter_raster_status(ddraw->wined3d, WINED3DADAPTER_DEFAULT, &raster_status);
1553     wined3d_mutex_unlock();
1554     if (FAILED(hr))
1555     {
1556         WARN("Failed to get raster status, hr %#x.\n", hr);
1557         return hr;
1558     }
1559
1560     *status = raster_status.in_vblank;
1561
1562     return DD_OK;
1563 }
1564
1565 static HRESULT WINAPI ddraw4_GetVerticalBlankStatus(IDirectDraw4 *iface, BOOL *status)
1566 {
1567     struct ddraw *ddraw = impl_from_IDirectDraw4(iface);
1568
1569     TRACE("iface %p, status %p.\n", iface, status);
1570
1571     return ddraw7_GetVerticalBlankStatus(&ddraw->IDirectDraw7_iface, status);
1572 }
1573
1574 static HRESULT WINAPI ddraw2_GetVerticalBlankStatus(IDirectDraw2 *iface, BOOL *status)
1575 {
1576     struct ddraw *ddraw = impl_from_IDirectDraw2(iface);
1577
1578     TRACE("iface %p, status %p.\n", iface, status);
1579
1580     return ddraw7_GetVerticalBlankStatus(&ddraw->IDirectDraw7_iface, status);
1581 }
1582
1583 static HRESULT WINAPI ddraw1_GetVerticalBlankStatus(IDirectDraw *iface, BOOL *status)
1584 {
1585     struct ddraw *ddraw = impl_from_IDirectDraw(iface);
1586
1587     TRACE("iface %p, status %p.\n", iface, status);
1588
1589     return ddraw7_GetVerticalBlankStatus(&ddraw->IDirectDraw7_iface, status);
1590 }
1591
1592 /*****************************************************************************
1593  * IDirectDraw7::GetAvailableVidMem
1594  *
1595  * Returns the total and free video memory
1596  *
1597  * Params:
1598  *  Caps: Specifies the memory type asked for
1599  *  total: Pointer to a DWORD to be filled with the total memory
1600  *  free: Pointer to a DWORD to be filled with the free memory
1601  *
1602  * Returns
1603  *  DD_OK on success
1604  *  DDERR_INVALIDPARAMS of free and total are NULL
1605  *
1606  *****************************************************************************/
1607 static HRESULT WINAPI ddraw7_GetAvailableVidMem(IDirectDraw7 *iface, DDSCAPS2 *Caps, DWORD *total,
1608         DWORD *free)
1609 {
1610     struct ddraw *ddraw = impl_from_IDirectDraw7(iface);
1611     HRESULT hr = DD_OK;
1612
1613     TRACE("iface %p, caps %p, total %p, free %p.\n", iface, Caps, total, free);
1614
1615     if (TRACE_ON(ddraw))
1616     {
1617         TRACE("Asked for memory with description: ");
1618         DDRAW_dump_DDSCAPS2(Caps);
1619     }
1620     wined3d_mutex_lock();
1621
1622     /* Todo: System memory vs local video memory vs non-local video memory
1623      * The MSDN also mentions differences between texture memory and other
1624      * resources, but that's not important
1625      */
1626
1627     if( (!total) && (!free) )
1628     {
1629         wined3d_mutex_unlock();
1630         return DDERR_INVALIDPARAMS;
1631     }
1632
1633     if (free)
1634         *free = wined3d_device_get_available_texture_mem(ddraw->wined3d_device);
1635     if (total)
1636     {
1637         struct wined3d_adapter_identifier desc = {0};
1638
1639         hr = wined3d_get_adapter_identifier(ddraw->wined3d, WINED3DADAPTER_DEFAULT, 0, &desc);
1640         *total = desc.video_memory;
1641     }
1642
1643     wined3d_mutex_unlock();
1644
1645     return hr;
1646 }
1647
1648 static HRESULT WINAPI ddraw4_GetAvailableVidMem(IDirectDraw4 *iface,
1649         DDSCAPS2 *caps, DWORD *total, DWORD *free)
1650 {
1651     struct ddraw *ddraw = impl_from_IDirectDraw4(iface);
1652
1653     TRACE("iface %p, caps %p, total %p, free %p.\n", iface, caps, total, free);
1654
1655     return ddraw7_GetAvailableVidMem(&ddraw->IDirectDraw7_iface, caps, total, free);
1656 }
1657
1658 static HRESULT WINAPI ddraw2_GetAvailableVidMem(IDirectDraw2 *iface,
1659         DDSCAPS *caps, DWORD *total, DWORD *free)
1660 {
1661     struct ddraw *ddraw = impl_from_IDirectDraw2(iface);
1662     DDSCAPS2 caps2;
1663
1664     TRACE("iface %p, caps %p, total %p, free %p.\n", iface, caps, total, free);
1665
1666     DDRAW_Convert_DDSCAPS_1_To_2(caps, &caps2);
1667     return ddraw7_GetAvailableVidMem(&ddraw->IDirectDraw7_iface, &caps2, total, free);
1668 }
1669
1670 /*****************************************************************************
1671  * IDirectDraw7::Initialize
1672  *
1673  * Initializes a DirectDraw interface.
1674  *
1675  * Params:
1676  *  GUID: Interface identifier. Well, don't know what this is really good
1677  *   for
1678  *
1679  * Returns
1680  *  Returns DD_OK on the first call,
1681  *  DDERR_ALREADYINITIALIZED on repeated calls
1682  *
1683  *****************************************************************************/
1684 static HRESULT WINAPI ddraw7_Initialize(IDirectDraw7 *iface, GUID *guid)
1685 {
1686     struct ddraw *ddraw = impl_from_IDirectDraw7(iface);
1687
1688     TRACE("iface %p, guid %s.\n", iface, debugstr_guid(guid));
1689
1690     if (ddraw->initialized)
1691         return DDERR_ALREADYINITIALIZED;
1692
1693     /* FIXME: To properly take the GUID into account we should call
1694      * ddraw_init() here instead of in DDRAW_Create(). */
1695     if (guid)
1696         FIXME("Ignoring guid %s.\n", debugstr_guid(guid));
1697
1698     ddraw->initialized = TRUE;
1699     return DD_OK;
1700 }
1701
1702 static HRESULT WINAPI ddraw4_Initialize(IDirectDraw4 *iface, GUID *guid)
1703 {
1704     struct ddraw *ddraw = impl_from_IDirectDraw4(iface);
1705
1706     TRACE("iface %p, guid %s.\n", iface, debugstr_guid(guid));
1707
1708     return ddraw7_Initialize(&ddraw->IDirectDraw7_iface, guid);
1709 }
1710
1711 static HRESULT WINAPI ddraw2_Initialize(IDirectDraw2 *iface, GUID *guid)
1712 {
1713     struct ddraw *ddraw = impl_from_IDirectDraw2(iface);
1714
1715     TRACE("iface %p, guid %s.\n", iface, debugstr_guid(guid));
1716
1717     return ddraw7_Initialize(&ddraw->IDirectDraw7_iface, guid);
1718 }
1719
1720 static HRESULT WINAPI ddraw1_Initialize(IDirectDraw *iface, GUID *guid)
1721 {
1722     struct ddraw *ddraw = impl_from_IDirectDraw(iface);
1723
1724     TRACE("iface %p, guid %s.\n", iface, debugstr_guid(guid));
1725
1726     return ddraw7_Initialize(&ddraw->IDirectDraw7_iface, guid);
1727 }
1728
1729 static HRESULT WINAPI d3d1_Initialize(IDirect3D *iface, REFIID riid)
1730 {
1731     TRACE("iface %p, riid %s.\n", iface, debugstr_guid(riid));
1732
1733     return DDERR_ALREADYINITIALIZED;
1734 }
1735
1736 /*****************************************************************************
1737  * IDirectDraw7::FlipToGDISurface
1738  *
1739  * "Makes the surface that the GDI writes to the primary surface"
1740  * Looks like some windows specific thing we don't have to care about.
1741  * According to MSDN it permits GDI dialog boxes in FULLSCREEN mode. Good to
1742  * show error boxes ;)
1743  * Well, just return DD_OK.
1744  *
1745  * Returns:
1746  *  Always returns DD_OK
1747  *
1748  *****************************************************************************/
1749 static HRESULT WINAPI ddraw7_FlipToGDISurface(IDirectDraw7 *iface)
1750 {
1751     FIXME("iface %p stub!\n", iface);
1752
1753     return DD_OK;
1754 }
1755
1756 static HRESULT WINAPI ddraw4_FlipToGDISurface(IDirectDraw4 *iface)
1757 {
1758     struct ddraw *ddraw = impl_from_IDirectDraw4(iface);
1759
1760     TRACE("iface %p.\n", iface);
1761
1762     return ddraw7_FlipToGDISurface(&ddraw->IDirectDraw7_iface);
1763 }
1764
1765 static HRESULT WINAPI ddraw2_FlipToGDISurface(IDirectDraw2 *iface)
1766 {
1767     struct ddraw *ddraw = impl_from_IDirectDraw2(iface);
1768
1769     TRACE("iface %p.\n", iface);
1770
1771     return ddraw7_FlipToGDISurface(&ddraw->IDirectDraw7_iface);
1772 }
1773
1774 static HRESULT WINAPI ddraw1_FlipToGDISurface(IDirectDraw *iface)
1775 {
1776     struct ddraw *ddraw = impl_from_IDirectDraw(iface);
1777
1778     TRACE("iface %p.\n", iface);
1779
1780     return ddraw7_FlipToGDISurface(&ddraw->IDirectDraw7_iface);
1781 }
1782
1783 /*****************************************************************************
1784  * IDirectDraw7::WaitForVerticalBlank
1785  *
1786  * This method allows applications to get in sync with the vertical blank
1787  * interval.
1788  * The wormhole demo in the DirectX 7 sdk uses this call, and it doesn't
1789  * redraw the screen, most likely because of this stub
1790  *
1791  * Parameters:
1792  *  Flags: one of DDWAITVB_BLOCKBEGIN, DDWAITVB_BLOCKBEGINEVENT
1793  *         or DDWAITVB_BLOCKEND
1794  *  h: Not used, according to MSDN
1795  *
1796  * Returns:
1797  *  Always returns DD_OK
1798  *
1799  *****************************************************************************/
1800 static HRESULT WINAPI ddraw7_WaitForVerticalBlank(IDirectDraw7 *iface, DWORD Flags, HANDLE event)
1801 {
1802     static BOOL hide;
1803
1804     TRACE("iface %p, flags %#x, event %p.\n", iface, Flags, event);
1805
1806     /* This function is called often, so print the fixme only once */
1807     if(!hide)
1808     {
1809         FIXME("iface %p, flags %#x, event %p stub!\n", iface, Flags, event);
1810         hide = TRUE;
1811     }
1812
1813     /* MSDN says DDWAITVB_BLOCKBEGINEVENT is not supported */
1814     if(Flags & DDWAITVB_BLOCKBEGINEVENT)
1815         return DDERR_UNSUPPORTED; /* unchecked */
1816
1817     return DD_OK;
1818 }
1819
1820 static HRESULT WINAPI ddraw4_WaitForVerticalBlank(IDirectDraw4 *iface, DWORD flags, HANDLE event)
1821 {
1822     struct ddraw *ddraw = impl_from_IDirectDraw4(iface);
1823
1824     TRACE("iface %p, flags %#x, event %p.\n", iface, flags, event);
1825
1826     return ddraw7_WaitForVerticalBlank(&ddraw->IDirectDraw7_iface, flags, event);
1827 }
1828
1829 static HRESULT WINAPI ddraw2_WaitForVerticalBlank(IDirectDraw2 *iface, DWORD flags, HANDLE event)
1830 {
1831     struct ddraw *ddraw = impl_from_IDirectDraw2(iface);
1832
1833     TRACE("iface %p, flags %#x, event %p.\n", iface, flags, event);
1834
1835     return ddraw7_WaitForVerticalBlank(&ddraw->IDirectDraw7_iface, flags, event);
1836 }
1837
1838 static HRESULT WINAPI ddraw1_WaitForVerticalBlank(IDirectDraw *iface, DWORD flags, HANDLE event)
1839 {
1840     struct ddraw *ddraw = impl_from_IDirectDraw(iface);
1841
1842     TRACE("iface %p, flags %#x, event %p.\n", iface, flags, event);
1843
1844     return ddraw7_WaitForVerticalBlank(&ddraw->IDirectDraw7_iface, flags, event);
1845 }
1846
1847 static HRESULT WINAPI ddraw7_GetScanLine(IDirectDraw7 *iface, DWORD *Scanline)
1848 {
1849     struct ddraw *ddraw = impl_from_IDirectDraw7(iface);
1850     struct wined3d_raster_status raster_status;
1851     HRESULT hr;
1852
1853     TRACE("iface %p, line %p.\n", iface, Scanline);
1854
1855     wined3d_mutex_lock();
1856     hr = wined3d_get_adapter_raster_status(ddraw->wined3d, WINED3DADAPTER_DEFAULT, &raster_status);
1857     wined3d_mutex_unlock();
1858     if (FAILED(hr))
1859     {
1860         WARN("Failed to get raster status, hr %#x.\n", hr);
1861         return hr;
1862     }
1863
1864     *Scanline = raster_status.scan_line;
1865
1866     if (raster_status.in_vblank)
1867         return DDERR_VERTICALBLANKINPROGRESS;
1868
1869     return DD_OK;
1870 }
1871
1872 static HRESULT WINAPI ddraw4_GetScanLine(IDirectDraw4 *iface, DWORD *line)
1873 {
1874     struct ddraw *ddraw = impl_from_IDirectDraw4(iface);
1875
1876     TRACE("iface %p, line %p.\n", iface, line);
1877
1878     return ddraw7_GetScanLine(&ddraw->IDirectDraw7_iface, line);
1879 }
1880
1881 static HRESULT WINAPI ddraw2_GetScanLine(IDirectDraw2 *iface, DWORD *line)
1882 {
1883     struct ddraw *ddraw = impl_from_IDirectDraw2(iface);
1884
1885     TRACE("iface %p, line %p.\n", iface, line);
1886
1887     return ddraw7_GetScanLine(&ddraw->IDirectDraw7_iface, line);
1888 }
1889
1890 static HRESULT WINAPI ddraw1_GetScanLine(IDirectDraw *iface, DWORD *line)
1891 {
1892     struct ddraw *ddraw = impl_from_IDirectDraw(iface);
1893
1894     TRACE("iface %p, line %p.\n", iface, line);
1895
1896     return ddraw7_GetScanLine(&ddraw->IDirectDraw7_iface, line);
1897 }
1898
1899 /*****************************************************************************
1900  * IDirectDraw7::TestCooperativeLevel
1901  *
1902  * Informs the application about the state of the video adapter, depending
1903  * on the cooperative level
1904  *
1905  * Returns:
1906  *  DD_OK if the device is in a sane state
1907  *  DDERR_NOEXCLUSIVEMODE or DDERR_EXCLUSIVEMODEALREADYSET
1908  *  if the state is not correct(See below)
1909  *
1910  *****************************************************************************/
1911 static HRESULT WINAPI ddraw7_TestCooperativeLevel(IDirectDraw7 *iface)
1912 {
1913     TRACE("iface %p.\n", iface);
1914
1915     return DD_OK;
1916 }
1917
1918 static HRESULT WINAPI ddraw4_TestCooperativeLevel(IDirectDraw4 *iface)
1919 {
1920     struct ddraw *ddraw = impl_from_IDirectDraw4(iface);
1921
1922     TRACE("iface %p.\n", iface);
1923
1924     return ddraw7_TestCooperativeLevel(&ddraw->IDirectDraw7_iface);
1925 }
1926
1927 /*****************************************************************************
1928  * IDirectDraw7::GetGDISurface
1929  *
1930  * Returns the surface that GDI is treating as the primary surface.
1931  * For Wine this is the front buffer
1932  *
1933  * Params:
1934  *  GDISurface: Address to write the surface pointer to
1935  *
1936  * Returns:
1937  *  DD_OK if the surface was found
1938  *  DDERR_NOTFOUND if the GDI surface wasn't found
1939  *
1940  *****************************************************************************/
1941 static HRESULT WINAPI ddraw7_GetGDISurface(IDirectDraw7 *iface, IDirectDrawSurface7 **GDISurface)
1942 {
1943     struct ddraw *ddraw = impl_from_IDirectDraw7(iface);
1944
1945     TRACE("iface %p, surface %p.\n", iface, GDISurface);
1946
1947     wined3d_mutex_lock();
1948
1949     if (!(*GDISurface = &ddraw->primary->IDirectDrawSurface7_iface))
1950     {
1951         WARN("Primary not created yet.\n");
1952         wined3d_mutex_unlock();
1953         return DDERR_NOTFOUND;
1954     }
1955     IDirectDrawSurface7_AddRef(*GDISurface);
1956
1957     wined3d_mutex_unlock();
1958
1959     return DD_OK;
1960 }
1961
1962 static HRESULT WINAPI ddraw4_GetGDISurface(IDirectDraw4 *iface, IDirectDrawSurface4 **surface)
1963 {
1964     struct ddraw *ddraw = impl_from_IDirectDraw4(iface);
1965     struct ddraw_surface *surface_impl;
1966     IDirectDrawSurface7 *surface7;
1967     HRESULT hr;
1968
1969     TRACE("iface %p, surface %p.\n", iface, surface);
1970
1971     hr = ddraw7_GetGDISurface(&ddraw->IDirectDraw7_iface, &surface7);
1972     if (FAILED(hr))
1973     {
1974         *surface = NULL;
1975         return hr;
1976     }
1977     surface_impl = impl_from_IDirectDrawSurface7(surface7);
1978     *surface = &surface_impl->IDirectDrawSurface4_iface;
1979     IDirectDrawSurface4_AddRef(*surface);
1980     IDirectDrawSurface7_Release(surface7);
1981
1982     return hr;
1983 }
1984
1985 static HRESULT WINAPI ddraw2_GetGDISurface(IDirectDraw2 *iface, IDirectDrawSurface **surface)
1986 {
1987     struct ddraw *ddraw = impl_from_IDirectDraw2(iface);
1988     struct ddraw_surface *surface_impl;
1989     IDirectDrawSurface7 *surface7;
1990     HRESULT hr;
1991
1992     TRACE("iface %p, surface %p.\n", iface, surface);
1993
1994     hr = ddraw7_GetGDISurface(&ddraw->IDirectDraw7_iface, &surface7);
1995     if (FAILED(hr))
1996     {
1997         *surface = NULL;
1998         return hr;
1999     }
2000     surface_impl = impl_from_IDirectDrawSurface7(surface7);
2001     *surface = &surface_impl->IDirectDrawSurface_iface;
2002     IDirectDrawSurface_AddRef(*surface);
2003     IDirectDrawSurface7_Release(surface7);
2004
2005     return hr;
2006 }
2007
2008 static HRESULT WINAPI ddraw1_GetGDISurface(IDirectDraw *iface, IDirectDrawSurface **surface)
2009 {
2010     struct ddraw *ddraw = impl_from_IDirectDraw(iface);
2011     struct ddraw_surface *surface_impl;
2012     IDirectDrawSurface7 *surface7;
2013     HRESULT hr;
2014
2015     TRACE("iface %p, surface %p.\n", iface, surface);
2016
2017     hr = ddraw7_GetGDISurface(&ddraw->IDirectDraw7_iface, &surface7);
2018     if (FAILED(hr))
2019     {
2020         *surface = NULL;
2021         return hr;
2022     }
2023     surface_impl = impl_from_IDirectDrawSurface7(surface7);
2024     *surface = &surface_impl->IDirectDrawSurface_iface;
2025     IDirectDrawSurface_AddRef(*surface);
2026     IDirectDrawSurface7_Release(surface7);
2027
2028     return hr;
2029 }
2030
2031 struct displaymodescallback_context
2032 {
2033     LPDDENUMMODESCALLBACK func;
2034     void *context;
2035 };
2036
2037 static HRESULT CALLBACK EnumDisplayModesCallbackThunk(DDSURFACEDESC2 *surface_desc, void *context)
2038 {
2039     struct displaymodescallback_context *cbcontext = context;
2040     DDSURFACEDESC desc;
2041
2042     DDSD2_to_DDSD(surface_desc, &desc);
2043     return cbcontext->func(&desc, cbcontext->context);
2044 }
2045
2046 /*****************************************************************************
2047  * IDirectDraw7::EnumDisplayModes
2048  *
2049  * Enumerates the supported Display modes. The modes can be filtered with
2050  * the DDSD parameter.
2051  *
2052  * Params:
2053  *  Flags: can be DDEDM_REFRESHRATES and DDEDM_STANDARDVGAMODES. For old ddraw
2054  *         versions (3 and older?) this is reserved and must be 0.
2055  *  DDSD: Surface description to filter the modes
2056  *  Context: Pointer passed back to the callback function
2057  *  cb: Application-provided callback function
2058  *
2059  * Returns:
2060  *  DD_OK on success
2061  *  DDERR_INVALIDPARAMS if the callback wasn't set
2062  *
2063  *****************************************************************************/
2064 static HRESULT WINAPI ddraw7_EnumDisplayModes(IDirectDraw7 *iface, DWORD Flags,
2065         DDSURFACEDESC2 *DDSD, void *Context, LPDDENUMMODESCALLBACK2 cb)
2066 {
2067     struct ddraw *ddraw = impl_from_IDirectDraw7(iface);
2068     struct wined3d_display_mode *enum_modes = NULL;
2069     struct wined3d_display_mode mode;
2070     unsigned int modenum, fmt;
2071     DDSURFACEDESC2 callback_sd;
2072     unsigned enum_mode_count = 0, enum_mode_array_size = 0;
2073     DDPIXELFORMAT pixelformat;
2074
2075     static const enum wined3d_format_id checkFormatList[] =
2076     {
2077         WINED3DFMT_B8G8R8X8_UNORM,
2078         WINED3DFMT_B5G6R5_UNORM,
2079         WINED3DFMT_P8_UINT,
2080     };
2081
2082     TRACE("iface %p, flags %#x, surface_desc %p, context %p, callback %p.\n",
2083             iface, Flags, DDSD, Context, cb);
2084
2085     if (!cb)
2086         return DDERR_INVALIDPARAMS;
2087
2088     wined3d_mutex_lock();
2089     if(!(Flags & DDEDM_REFRESHRATES))
2090     {
2091         enum_mode_array_size = 16;
2092         enum_modes = HeapAlloc(GetProcessHeap(), 0, sizeof(*enum_modes) * enum_mode_array_size);
2093         if (!enum_modes)
2094         {
2095             ERR("Out of memory\n");
2096             wined3d_mutex_unlock();
2097             return DDERR_OUTOFMEMORY;
2098         }
2099     }
2100
2101     pixelformat.dwSize = sizeof(pixelformat);
2102     for(fmt = 0; fmt < (sizeof(checkFormatList) / sizeof(checkFormatList[0])); fmt++)
2103     {
2104         modenum = 0;
2105         while (wined3d_enum_adapter_modes(ddraw->wined3d, WINED3DADAPTER_DEFAULT, checkFormatList[fmt],
2106                 WINED3D_SCANLINE_ORDERING_UNKNOWN, modenum++, &mode) == WINED3D_OK)
2107         {
2108             PixelFormat_WineD3DtoDD(&pixelformat, mode.format_id);
2109             if (DDSD)
2110             {
2111                 if (DDSD->dwFlags & DDSD_WIDTH && mode.width != DDSD->dwWidth)
2112                     continue;
2113                 if (DDSD->dwFlags & DDSD_HEIGHT && mode.height != DDSD->dwHeight)
2114                     continue;
2115                 if (DDSD->dwFlags & DDSD_REFRESHRATE && mode.refresh_rate != DDSD->u2.dwRefreshRate)
2116                     continue;
2117                 if (DDSD->dwFlags & DDSD_PIXELFORMAT
2118                         && pixelformat.u1.dwRGBBitCount != DDSD->u4.ddpfPixelFormat.u1.dwRGBBitCount)
2119                     continue;
2120             }
2121
2122             if(!(Flags & DDEDM_REFRESHRATES))
2123             {
2124                 /* DX docs state EnumDisplayMode should return only unique modes. If DDEDM_REFRESHRATES is not set, refresh
2125                  * rate doesn't matter when determining if the mode is unique. So modes only differing in refresh rate have
2126                  * to be reduced to a single unique result in such case.
2127                  */
2128                 BOOL found = FALSE;
2129                 unsigned i;
2130
2131                 for (i = 0; i < enum_mode_count; i++)
2132                 {
2133                     if (enum_modes[i].width == mode.width && enum_modes[i].height == mode.height
2134                             && enum_modes[i].format_id == mode.format_id)
2135                     {
2136                         found = TRUE;
2137                         break;
2138                     }
2139                 }
2140
2141                 if(found) continue;
2142             }
2143
2144             memset(&callback_sd, 0, sizeof(callback_sd));
2145             callback_sd.dwSize = sizeof(callback_sd);
2146             callback_sd.u4.ddpfPixelFormat.dwSize = sizeof(DDPIXELFORMAT);
2147
2148             callback_sd.dwFlags = DDSD_HEIGHT|DDSD_WIDTH|DDSD_PIXELFORMAT|DDSD_PITCH|DDSD_REFRESHRATE;
2149             if (Flags & DDEDM_REFRESHRATES)
2150                 callback_sd.u2.dwRefreshRate = mode.refresh_rate;
2151
2152             callback_sd.dwWidth = mode.width;
2153             callback_sd.dwHeight = mode.height;
2154
2155             callback_sd.u4.ddpfPixelFormat=pixelformat;
2156
2157             /* Calc pitch and DWORD align like MSDN says */
2158             callback_sd.u1.lPitch = (callback_sd.u4.ddpfPixelFormat.u1.dwRGBBitCount / 8) * mode.width;
2159             callback_sd.u1.lPitch = (callback_sd.u1.lPitch + 3) & ~3;
2160
2161             TRACE("Enumerating %dx%dx%d @%d\n", callback_sd.dwWidth, callback_sd.dwHeight, callback_sd.u4.ddpfPixelFormat.u1.dwRGBBitCount,
2162               callback_sd.u2.dwRefreshRate);
2163
2164             if(cb(&callback_sd, Context) == DDENUMRET_CANCEL)
2165             {
2166                 TRACE("Application asked to terminate the enumeration\n");
2167                 HeapFree(GetProcessHeap(), 0, enum_modes);
2168                 wined3d_mutex_unlock();
2169                 return DD_OK;
2170             }
2171
2172             if(!(Flags & DDEDM_REFRESHRATES))
2173             {
2174                 if (enum_mode_count == enum_mode_array_size)
2175                 {
2176                     struct wined3d_display_mode *new_enum_modes;
2177
2178                     enum_mode_array_size *= 2;
2179                     new_enum_modes = HeapReAlloc(GetProcessHeap(), 0, enum_modes,
2180                             sizeof(*new_enum_modes) * enum_mode_array_size);
2181                     if (!new_enum_modes)
2182                     {
2183                         ERR("Out of memory\n");
2184                         HeapFree(GetProcessHeap(), 0, enum_modes);
2185                         wined3d_mutex_unlock();
2186                         return DDERR_OUTOFMEMORY;
2187                     }
2188
2189                     enum_modes = new_enum_modes;
2190                 }
2191
2192                 enum_modes[enum_mode_count++] = mode;
2193             }
2194         }
2195     }
2196
2197     TRACE("End of enumeration\n");
2198     HeapFree(GetProcessHeap(), 0, enum_modes);
2199     wined3d_mutex_unlock();
2200
2201     return DD_OK;
2202 }
2203
2204 static HRESULT WINAPI ddraw4_EnumDisplayModes(IDirectDraw4 *iface, DWORD flags,
2205         DDSURFACEDESC2 *surface_desc, void *context, LPDDENUMMODESCALLBACK2 callback)
2206 {
2207     struct ddraw *ddraw = impl_from_IDirectDraw4(iface);
2208
2209     TRACE("iface %p, flags %#x, surface_desc %p, context %p, callback %p.\n",
2210             iface, flags, surface_desc, context, callback);
2211
2212     return ddraw7_EnumDisplayModes(&ddraw->IDirectDraw7_iface, flags, surface_desc, context, callback);
2213 }
2214
2215 static HRESULT WINAPI ddraw2_EnumDisplayModes(IDirectDraw2 *iface, DWORD flags,
2216         DDSURFACEDESC *surface_desc, void *context, LPDDENUMMODESCALLBACK callback)
2217 {
2218     struct ddraw *ddraw = impl_from_IDirectDraw2(iface);
2219     struct displaymodescallback_context cbcontext;
2220     DDSURFACEDESC2 surface_desc2;
2221
2222     TRACE("iface %p, flags %#x, surface_desc %p, context %p, callback %p.\n",
2223             iface, flags, surface_desc, context, callback);
2224
2225     cbcontext.func = callback;
2226     cbcontext.context = context;
2227
2228     if (surface_desc) DDSD_to_DDSD2(surface_desc, &surface_desc2);
2229     return ddraw7_EnumDisplayModes(&ddraw->IDirectDraw7_iface, flags,
2230             surface_desc ? &surface_desc2 : NULL, &cbcontext, EnumDisplayModesCallbackThunk);
2231 }
2232
2233 static HRESULT WINAPI ddraw1_EnumDisplayModes(IDirectDraw *iface, DWORD flags,
2234         DDSURFACEDESC *surface_desc, void *context, LPDDENUMMODESCALLBACK callback)
2235 {
2236     struct ddraw *ddraw = impl_from_IDirectDraw(iface);
2237     struct displaymodescallback_context cbcontext;
2238     DDSURFACEDESC2 surface_desc2;
2239
2240     TRACE("iface %p, flags %#x, surface_desc %p, context %p, callback %p.\n",
2241             iface, flags, surface_desc, context, callback);
2242
2243     cbcontext.func = callback;
2244     cbcontext.context = context;
2245
2246     if (surface_desc) DDSD_to_DDSD2(surface_desc, &surface_desc2);
2247     return ddraw7_EnumDisplayModes(&ddraw->IDirectDraw7_iface, flags,
2248             surface_desc ? &surface_desc2 : NULL, &cbcontext, EnumDisplayModesCallbackThunk);
2249 }
2250
2251 /*****************************************************************************
2252  * IDirectDraw7::EvaluateMode
2253  *
2254  * Used with IDirectDraw7::StartModeTest to test video modes.
2255  * EvaluateMode is used to pass or fail a mode, and continue with the next
2256  * mode
2257  *
2258  * Params:
2259  *  Flags: DDEM_MODEPASSED or DDEM_MODEFAILED
2260  *  Timeout: Returns the amount of seconds left before the mode would have
2261  *           been failed automatically
2262  *
2263  * Returns:
2264  *  This implementation always DD_OK, because it's a stub
2265  *
2266  *****************************************************************************/
2267 static HRESULT WINAPI ddraw7_EvaluateMode(IDirectDraw7 *iface, DWORD Flags, DWORD *Timeout)
2268 {
2269     FIXME("iface %p, flags %#x, timeout %p stub!\n", iface, Flags, Timeout);
2270
2271     /* When implementing this, implement it in WineD3D */
2272
2273     return DD_OK;
2274 }
2275
2276 /*****************************************************************************
2277  * IDirectDraw7::GetDeviceIdentifier
2278  *
2279  * Returns the device identifier, which gives information about the driver
2280  * Our device identifier is defined at the beginning of this file.
2281  *
2282  * Params:
2283  *  DDDI: Address for the returned structure
2284  *  Flags: Can be DDGDI_GETHOSTIDENTIFIER
2285  *
2286  * Returns:
2287  *  On success it returns DD_OK
2288  *  DDERR_INVALIDPARAMS if DDDI is NULL
2289  *
2290  *****************************************************************************/
2291 static HRESULT WINAPI ddraw7_GetDeviceIdentifier(IDirectDraw7 *iface,
2292         DDDEVICEIDENTIFIER2 *DDDI, DWORD Flags)
2293 {
2294     TRACE("iface %p, device_identifier %p, flags %#x.\n", iface, DDDI, Flags);
2295
2296     if(!DDDI)
2297         return DDERR_INVALIDPARAMS;
2298
2299     /* The DDGDI_GETHOSTIDENTIFIER returns the information about the 2D
2300      * host adapter, if there's a secondary 3D adapter. This doesn't apply
2301      * to any modern hardware, nor is it interesting for Wine, so ignore it.
2302      * Size of DDDEVICEIDENTIFIER2 may be aligned to 8 bytes and thus 4
2303      * bytes too long. So only copy the relevant part of the structure
2304      */
2305
2306     memcpy(DDDI, &deviceidentifier, FIELD_OFFSET(DDDEVICEIDENTIFIER2, dwWHQLLevel) + sizeof(DWORD));
2307     return DD_OK;
2308 }
2309
2310 static HRESULT WINAPI ddraw4_GetDeviceIdentifier(IDirectDraw4 *iface,
2311         DDDEVICEIDENTIFIER *identifier, DWORD flags)
2312 {
2313     struct ddraw *ddraw = impl_from_IDirectDraw4(iface);
2314     DDDEVICEIDENTIFIER2 identifier2;
2315     HRESULT hr;
2316
2317     TRACE("iface %p, identifier %p, flags %#x.\n", iface, identifier, flags);
2318
2319     hr = ddraw7_GetDeviceIdentifier(&ddraw->IDirectDraw7_iface, &identifier2, flags);
2320     DDRAW_Convert_DDDEVICEIDENTIFIER_2_To_1(&identifier2, identifier);
2321
2322     return hr;
2323 }
2324
2325 /*****************************************************************************
2326  * IDirectDraw7::GetSurfaceFromDC
2327  *
2328  * Returns the Surface for a GDI device context handle.
2329  * Is this related to IDirectDrawSurface::GetDC ???
2330  *
2331  * Params:
2332  *  hdc: hdc to return the surface for
2333  *  Surface: Address to write the surface pointer to
2334  *
2335  * Returns:
2336  *  Always returns DD_OK because it's a stub
2337  *
2338  *****************************************************************************/
2339 static HRESULT WINAPI ddraw7_GetSurfaceFromDC(IDirectDraw7 *iface, HDC hdc,
2340         IDirectDrawSurface7 **Surface)
2341 {
2342     struct ddraw *ddraw = impl_from_IDirectDraw7(iface);
2343     struct wined3d_surface *wined3d_surface;
2344     struct ddraw_surface *surface_impl;
2345
2346     TRACE("iface %p, dc %p, surface %p.\n", iface, hdc, Surface);
2347
2348     if (!Surface) return E_INVALIDARG;
2349
2350     if (!(wined3d_surface = wined3d_device_get_surface_from_dc(ddraw->wined3d_device, hdc)))
2351     {
2352         TRACE("No surface found for dc %p.\n", hdc);
2353         *Surface = NULL;
2354         return DDERR_NOTFOUND;
2355     }
2356
2357     surface_impl = wined3d_surface_get_parent(wined3d_surface);
2358     *Surface = &surface_impl->IDirectDrawSurface7_iface;
2359     IDirectDrawSurface7_AddRef(*Surface);
2360     TRACE("Returning surface %p.\n", Surface);
2361     return DD_OK;
2362 }
2363
2364 static HRESULT WINAPI ddraw4_GetSurfaceFromDC(IDirectDraw4 *iface, HDC dc,
2365         IDirectDrawSurface4 **surface)
2366 {
2367     struct ddraw *ddraw = impl_from_IDirectDraw4(iface);
2368     struct ddraw_surface *surface_impl;
2369     IDirectDrawSurface7 *surface7;
2370     HRESULT hr;
2371
2372     TRACE("iface %p, dc %p, surface %p.\n", iface, dc, surface);
2373
2374     if (!surface) return E_INVALIDARG;
2375
2376     hr = ddraw7_GetSurfaceFromDC(&ddraw->IDirectDraw7_iface, dc, &surface7);
2377     if (FAILED(hr))
2378     {
2379         *surface = NULL;
2380         return hr;
2381     }
2382     surface_impl = impl_from_IDirectDrawSurface7(surface7);
2383     /* Tests say this is true */
2384     *surface = (IDirectDrawSurface4 *)&surface_impl->IDirectDrawSurface_iface;
2385     IDirectDrawSurface_AddRef(&surface_impl->IDirectDrawSurface_iface);
2386     IDirectDrawSurface7_Release(surface7);
2387
2388     return hr;
2389 }
2390
2391 /*****************************************************************************
2392  * IDirectDraw7::RestoreAllSurfaces
2393  *
2394  * Calls the restore method of all surfaces
2395  *
2396  * Params:
2397  *
2398  * Returns:
2399  *  Always returns DD_OK because it's a stub
2400  *
2401  *****************************************************************************/
2402 static HRESULT WINAPI ddraw7_RestoreAllSurfaces(IDirectDraw7 *iface)
2403 {
2404     FIXME("iface %p stub!\n", iface);
2405
2406     /* This isn't hard to implement: Enumerate all WineD3D surfaces,
2407      * get their parent and call their restore method. Do not implement
2408      * it in WineD3D, as restoring a surface means re-creating the
2409      * WineD3DDSurface
2410      */
2411     return DD_OK;
2412 }
2413
2414 static HRESULT WINAPI ddraw4_RestoreAllSurfaces(IDirectDraw4 *iface)
2415 {
2416     struct ddraw *ddraw = impl_from_IDirectDraw4(iface);
2417
2418     TRACE("iface %p.\n", iface);
2419
2420     return ddraw7_RestoreAllSurfaces(&ddraw->IDirectDraw7_iface);
2421 }
2422
2423 /*****************************************************************************
2424  * IDirectDraw7::StartModeTest
2425  *
2426  * Tests the specified video modes to update the system registry with
2427  * refresh rate information. StartModeTest starts the mode test,
2428  * EvaluateMode is used to fail or pass a mode. If EvaluateMode
2429  * isn't called within 15 seconds, the mode is failed automatically
2430  *
2431  * As refresh rates are handled by the X server, I don't think this
2432  * Method is important
2433  *
2434  * Params:
2435  *  Modes: An array of mode specifications
2436  *  NumModes: The number of modes in Modes
2437  *  Flags: Some flags...
2438  *
2439  * Returns:
2440  *  Returns DDERR_TESTFINISHED if flags contains DDSMT_ISTESTREQUIRED,
2441  *  if no modes are passed, DDERR_INVALIDPARAMS is returned,
2442  *  otherwise DD_OK
2443  *
2444  *****************************************************************************/
2445 static HRESULT WINAPI ddraw7_StartModeTest(IDirectDraw7 *iface, SIZE *Modes, DWORD NumModes, DWORD Flags)
2446 {
2447     FIXME("iface %p, modes %p, mode_count %u, flags %#x partial stub!\n",
2448             iface, Modes, NumModes, Flags);
2449
2450     /* This looks sane */
2451     if( (!Modes) || (NumModes == 0) ) return DDERR_INVALIDPARAMS;
2452
2453     /* DDSMT_ISTESTREQUIRED asks if a mode test is necessary.
2454      * As it is not, DDERR_TESTFINISHED is returned
2455      * (hopefully that's correct
2456      *
2457     if(Flags & DDSMT_ISTESTREQUIRED) return DDERR_TESTFINISHED;
2458      * well, that value doesn't (yet) exist in the wine headers, so ignore it
2459      */
2460
2461     return DD_OK;
2462 }
2463
2464 /*****************************************************************************
2465  * ddraw_create_surface
2466  *
2467  * A helper function for IDirectDraw7::CreateSurface. It creates a new surface
2468  * with the passed parameters.
2469  *
2470  * Params:
2471  *  DDSD: Description of the surface to create
2472  *  Surf: Address to store the interface pointer at
2473  *
2474  * Returns:
2475  *  DD_OK on success
2476  *
2477  *****************************************************************************/
2478 static HRESULT ddraw_create_surface(struct ddraw *ddraw, DDSURFACEDESC2 *pDDSD,
2479         struct ddraw_surface **surface, UINT version)
2480 {
2481     HRESULT hr;
2482
2483     TRACE("ddraw %p, surface_desc %p, surface %p.\n", ddraw, pDDSD, surface);
2484
2485     if (TRACE_ON(ddraw))
2486     {
2487         TRACE("Requesting surface desc:\n");
2488         DDRAW_dump_surface_desc(pDDSD);
2489     }
2490
2491     if ((pDDSD->ddsCaps.dwCaps & DDSCAPS_3DDEVICE) && DefaultSurfaceType != DDRAW_SURFACE_TYPE_OPENGL)
2492     {
2493         WARN("The application requests a 3D capable surface, but a non-OpenGL surface type was set in the registry.\n");
2494         /* Do not fail surface creation, only fail 3D device creation. */
2495     }
2496
2497     /* Create the Surface object */
2498     *surface = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(**surface));
2499     if (!*surface)
2500     {
2501         ERR("Failed to allocate surface memory.\n");
2502         return DDERR_OUTOFVIDEOMEMORY;
2503     }
2504
2505     if (FAILED(hr = ddraw_surface_init(*surface, ddraw, pDDSD, version)))
2506     {
2507         WARN("Failed to initialize surface, hr %#x.\n", hr);
2508         HeapFree(GetProcessHeap(), 0, *surface);
2509         return hr;
2510     }
2511
2512     /* Increase the surface counter, and attach the surface */
2513     list_add_head(&ddraw->surface_list, &(*surface)->surface_list_entry);
2514
2515     TRACE("Created surface %p.\n", *surface);
2516
2517     return DD_OK;
2518 }
2519
2520 static HRESULT CDECL ddraw_reset_enum_callback(struct wined3d_resource *resource)
2521 {
2522     return DD_OK;
2523 }
2524
2525 /*****************************************************************************
2526  * IDirectDraw7::CreateSurface
2527  *
2528  * Creates a new IDirectDrawSurface object and returns its interface.
2529  *
2530  * The surface connections with wined3d are a bit tricky. Basically it works
2531  * like this:
2532  *
2533  * |------------------------|               |-----------------|
2534  * | DDraw surface          |               | WineD3DSurface  |
2535  * |                        |               |                 |
2536  * |        WineD3DSurface  |-------------->|                 |
2537  * |        Child           |<------------->| Parent          |
2538  * |------------------------|               |-----------------|
2539  *
2540  * The DDraw surface is the parent of the wined3d surface, and it releases
2541  * the WineD3DSurface when the ddraw surface is destroyed.
2542  *
2543  * However, for all surfaces which can be in a container in WineD3D,
2544  * we have to do this. These surfaces are usually complex surfaces,
2545  * so this concerns primary surfaces with a front and a back buffer,
2546  * and textures.
2547  *
2548  * |------------------------|               |-----------------|
2549  * | DDraw surface          |               | Container       |
2550  * |                        |               |                 |
2551  * |                  Child |<------------->| Parent          |
2552  * |                Texture |<------------->|                 |
2553  * |         WineD3DSurface |<----|         |          Levels |<--|
2554  * | Complex connection     |     |         |                 |   |
2555  * |------------------------|     |         |-----------------|   |
2556  *  ^                             |                               |
2557  *  |                             |                               |
2558  *  |                             |                               |
2559  *  |    |------------------|     |         |-----------------|   |
2560  *  |    | IParent          |     |-------->| WineD3DSurface  |   |
2561  *  |    |                  |               |                 |   |
2562  *  |    |            Child |<------------->| Parent          |   |
2563  *  |    |                  |               |       Container |<--|
2564  *  |    |------------------|               |-----------------|   |
2565  *  |                                                             |
2566  *  |   |----------------------|                                  |
2567  *  |   | DDraw surface 2      |                                  |
2568  *  |   |                      |                                  |
2569  *  |<->| Complex root   Child |                                  |
2570  *  |   |              Texture |                                  |
2571  *  |   |       WineD3DSurface |<----|                            |
2572  *  |   |----------------------|     |                            |
2573  *  |                                |                            |
2574  *  |    |---------------------|     |      |-----------------|   |
2575  *  |    | IParent             |     |----->| WineD3DSurface  |   |
2576  *  |    |                     |            |                 |   |
2577  *  |    |               Child |<---------->| Parent          |   |
2578  *  |    |---------------------|            |       Container |<--|
2579  *  |                                       |-----------------|   |
2580  *  |                                                             |
2581  *  |             ---More surfaces can follow---                  |
2582  *
2583  * The reason is that the IWineD3DSwapchain(render target container)
2584  * and the IWineD3DTexure(Texture container) release the parents
2585  * of their surface's children, but by releasing the complex root
2586  * the surfaces which are complexly attached to it are destroyed
2587  * too. See IDirectDrawSurface::Release for a more detailed
2588  * explanation.
2589  *
2590  * Params:
2591  *  DDSD: Description of the surface to create
2592  *  Surf: Address to store the interface pointer at
2593  *  UnkOuter: Basically for aggregation support, but ddraw doesn't support
2594  *            aggregation, so it has to be NULL
2595  *
2596  * Returns:
2597  *  DD_OK on success
2598  *  CLASS_E_NOAGGREGATION if UnkOuter != NULL
2599  *  DDERR_* if an error occurs
2600  *
2601  *****************************************************************************/
2602 static HRESULT CreateSurface(struct ddraw *ddraw, DDSURFACEDESC2 *DDSD,
2603         struct ddraw_surface **surface, IUnknown *UnkOuter, UINT version)
2604 {
2605     struct ddraw_surface *object = NULL;
2606     struct wined3d_display_mode mode;
2607     HRESULT hr;
2608     DDSURFACEDESC2 desc2;
2609     const DWORD sysvidmem = DDSCAPS_VIDEOMEMORY | DDSCAPS_SYSTEMMEMORY;
2610
2611     TRACE("ddraw %p, surface_desc %p, surface %p, outer_unknown %p.\n", ddraw, DDSD, surface, UnkOuter);
2612
2613     /* Some checks before we start */
2614     if (TRACE_ON(ddraw))
2615     {
2616         TRACE(" (%p) Requesting surface desc :\n", ddraw);
2617         DDRAW_dump_surface_desc(DDSD);
2618     }
2619
2620     if (UnkOuter != NULL)
2621     {
2622         FIXME("(%p) : outer != NULL?\n", ddraw);
2623         return CLASS_E_NOAGGREGATION; /* unchecked */
2624     }
2625
2626     if (!surface)
2627     {
2628         FIXME("(%p) You want to get back a surface? Don't give NULL ptrs!\n", ddraw);
2629         return E_POINTER; /* unchecked */
2630     }
2631
2632     if (!(DDSD->dwFlags & DDSD_CAPS))
2633     {
2634         /* DVIDEO.DLL does forget the DDSD_CAPS flag ... *sigh* */
2635         DDSD->dwFlags |= DDSD_CAPS;
2636     }
2637
2638     if (DDSD->ddsCaps.dwCaps & DDSCAPS_ALLOCONLOAD)
2639     {
2640         /* If the surface is of the 'alloconload' type, ignore the LPSURFACE field */
2641         DDSD->dwFlags &= ~DDSD_LPSURFACE;
2642     }
2643
2644     if ((DDSD->dwFlags & DDSD_LPSURFACE) && (DDSD->lpSurface == NULL))
2645     {
2646         /* Frank Herbert's Dune specifies a null pointer for the surface, ignore the LPSURFACE field */
2647         WARN("(%p) Null surface pointer specified, ignore it!\n", ddraw);
2648         DDSD->dwFlags &= ~DDSD_LPSURFACE;
2649     }
2650
2651     if((DDSD->ddsCaps.dwCaps & (DDSCAPS_FLIP | DDSCAPS_PRIMARYSURFACE)) == (DDSCAPS_FLIP | DDSCAPS_PRIMARYSURFACE) &&
2652        !(ddraw->cooperative_level & DDSCL_EXCLUSIVE))
2653     {
2654         TRACE("(%p): Attempt to create a flipable primary surface without DDSCL_EXCLUSIVE set\n",
2655                 ddraw);
2656         *surface = NULL;
2657         return DDERR_NOEXCLUSIVEMODE;
2658     }
2659
2660     if((DDSD->ddsCaps.dwCaps & (DDSCAPS_BACKBUFFER | DDSCAPS_PRIMARYSURFACE)) == (DDSCAPS_BACKBUFFER | DDSCAPS_PRIMARYSURFACE))
2661     {
2662         WARN("Application wanted to create back buffer primary surface\n");
2663         return DDERR_INVALIDCAPS;
2664     }
2665
2666     if((DDSD->ddsCaps.dwCaps & sysvidmem) == sysvidmem)
2667     {
2668         /* This is a special switch in ddrawex.dll, but not allowed in ddraw.dll */
2669         WARN("Application tries to put the surface in both system and video memory\n");
2670         *surface = NULL;
2671         return DDERR_INVALIDCAPS;
2672     }
2673
2674     /* Check cube maps but only if the size includes them */
2675     if (DDSD->dwSize >= sizeof(DDSURFACEDESC2))
2676     {
2677         if(DDSD->ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP_ALLFACES &&
2678            !(DDSD->ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP))
2679         {
2680             WARN("Cube map faces requested without cube map flag\n");
2681             return DDERR_INVALIDCAPS;
2682         }
2683         if(DDSD->ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP &&
2684            (DDSD->ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP_ALLFACES) == 0)
2685         {
2686             WARN("Cube map without faces requested\n");
2687             return DDERR_INVALIDPARAMS;
2688         }
2689
2690         /* Quick tests confirm those can be created, but we don't do that yet */
2691         if(DDSD->ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP &&
2692            (DDSD->ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP_ALLFACES) != DDSCAPS2_CUBEMAP_ALLFACES)
2693         {
2694             FIXME("Partial cube maps not supported yet\n");
2695         }
2696     }
2697
2698     /* According to the msdn this flag is ignored by CreateSurface */
2699     if (DDSD->dwSize >= sizeof(DDSURFACEDESC2))
2700         DDSD->ddsCaps.dwCaps2 &= ~DDSCAPS2_MIPMAPSUBLEVEL;
2701
2702     /* Modify some flags */
2703     copy_to_surfacedesc2(&desc2, DDSD);
2704     desc2.u4.ddpfPixelFormat.dwSize=sizeof(DDPIXELFORMAT); /* Just to be sure */
2705
2706     if (FAILED(hr = wined3d_get_adapter_display_mode(ddraw->wined3d, WINED3DADAPTER_DEFAULT, &mode, NULL)))
2707     {
2708         ERR("Failed to get display mode, hr %#x.\n", hr);
2709         return hr;
2710     }
2711
2712     /* No pixelformat given? Use the current screen format */
2713     if(!(desc2.dwFlags & DDSD_PIXELFORMAT))
2714     {
2715         desc2.dwFlags |= DDSD_PIXELFORMAT;
2716         desc2.u4.ddpfPixelFormat.dwSize=sizeof(DDPIXELFORMAT);
2717
2718         PixelFormat_WineD3DtoDD(&desc2.u4.ddpfPixelFormat, mode.format_id);
2719     }
2720
2721     /* No Width or no Height? Use the original screen size
2722      */
2723     if(!(desc2.dwFlags & DDSD_WIDTH) ||
2724        !(desc2.dwFlags & DDSD_HEIGHT) )
2725     {
2726         /* Invalid for non-render targets */
2727         if(!(desc2.ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE))
2728         {
2729             WARN("Creating a non-Primary surface without Width or Height info, returning DDERR_INVALIDPARAMS\n");
2730             *surface = NULL;
2731             return DDERR_INVALIDPARAMS;
2732         }
2733
2734         desc2.dwFlags |= DDSD_WIDTH | DDSD_HEIGHT;
2735         desc2.dwWidth = mode.width;
2736         desc2.dwHeight = mode.height;
2737     }
2738
2739     if (!desc2.dwWidth || !desc2.dwHeight)
2740         return DDERR_INVALIDPARAMS;
2741
2742     /* Mipmap count fixes */
2743     if(desc2.ddsCaps.dwCaps & DDSCAPS_MIPMAP)
2744     {
2745         if(desc2.ddsCaps.dwCaps & DDSCAPS_COMPLEX)
2746         {
2747             if(desc2.dwFlags & DDSD_MIPMAPCOUNT)
2748             {
2749                 /* Mipmap count is given, should not be 0 */
2750                 if( desc2.u2.dwMipMapCount == 0 )
2751                     return DDERR_INVALIDPARAMS;
2752             }
2753             else
2754             {
2755                 /* Undocumented feature: Create sublevels until
2756                  * either the width or the height is 1
2757                  */
2758                 DWORD min = desc2.dwWidth < desc2.dwHeight ?
2759                             desc2.dwWidth : desc2.dwHeight;
2760                 desc2.u2.dwMipMapCount = 0;
2761                 while( min )
2762                 {
2763                     desc2.u2.dwMipMapCount += 1;
2764                     min >>= 1;
2765                 }
2766             }
2767         }
2768         else
2769         {
2770             /* Not-complex mipmap -> Mipmapcount = 1 */
2771             desc2.u2.dwMipMapCount = 1;
2772         }
2773
2774         /* There's a mipmap count in the created surface in any case */
2775         desc2.dwFlags |= DDSD_MIPMAPCOUNT;
2776     }
2777     /* If no mipmap is given, the texture has only one level */
2778
2779     /* The first surface is a front buffer, the back buffer is created afterwards */
2780     if( (desc2.dwFlags & DDSD_CAPS) && (desc2.ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE) )
2781     {
2782         desc2.ddsCaps.dwCaps |= DDSCAPS_FRONTBUFFER;
2783     }
2784
2785     /* The root surface in a cube map is positive x */
2786     if(desc2.ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP)
2787     {
2788         desc2.ddsCaps.dwCaps2 &= ~DDSCAPS2_CUBEMAP_ALLFACES;
2789         desc2.ddsCaps.dwCaps2 |=  DDSCAPS2_CUBEMAP_POSITIVEX;
2790     }
2791
2792     if ((desc2.ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE) && (ddraw->cooperative_level & DDSCL_EXCLUSIVE))
2793     {
2794         struct wined3d_swapchain_desc swapchain_desc;
2795
2796         wined3d_swapchain_get_desc(ddraw->wined3d_swapchain, &swapchain_desc);
2797         swapchain_desc.backbuffer_width = mode.width;
2798         swapchain_desc.backbuffer_height = mode.height;
2799         swapchain_desc.backbuffer_format = mode.format_id;
2800
2801         hr = wined3d_device_reset(ddraw->wined3d_device,
2802                 &swapchain_desc, NULL, ddraw_reset_enum_callback, TRUE);
2803         if (FAILED(hr))
2804         {
2805             ERR("Failed to reset device.\n");
2806             return hr;
2807         }
2808     }
2809
2810     /* Create the first surface */
2811     if (FAILED(hr = ddraw_create_surface(ddraw, &desc2, &object, version)))
2812     {
2813         WARN("ddraw_create_surface failed, hr %#x.\n", hr);
2814         return hr;
2815     }
2816     object->is_complex_root = TRUE;
2817
2818     *surface = object;
2819
2820     /* Create Additional surfaces if necessary
2821      * This applies to Primary surfaces which have a back buffer count
2822      * set, but not to mipmap textures. In case of Mipmap textures,
2823      * wineD3D takes care of the creation of additional surfaces
2824      */
2825     if(DDSD->dwFlags & DDSD_BACKBUFFERCOUNT)
2826     {
2827         struct ddraw_surface *last = object;
2828         UINT i;
2829
2830         desc2.ddsCaps.dwCaps &= ~DDSCAPS_FRONTBUFFER; /* It's not a front buffer */
2831         desc2.ddsCaps.dwCaps |= DDSCAPS_BACKBUFFER;
2832         desc2.dwBackBufferCount = 0;
2833
2834         for (i = 0; i < DDSD->dwBackBufferCount; ++i)
2835         {
2836             struct ddraw_surface *object2 = NULL;
2837
2838             if (FAILED(hr = ddraw_create_surface(ddraw, &desc2, &object2, version)))
2839             {
2840                 if (version == 7)
2841                     IDirectDrawSurface7_Release(&object->IDirectDrawSurface7_iface);
2842                 else if (version == 4)
2843                     IDirectDrawSurface4_Release(&object->IDirectDrawSurface4_iface);
2844                 else
2845                     IDirectDrawSurface_Release(&object->IDirectDrawSurface_iface);
2846
2847                 return hr;
2848             }
2849
2850             /* Add the new surface to the complex attachment array. */
2851             last->complex_array[0] = object2;
2852             last = object2;
2853
2854             /* Remove the (possible) back buffer cap from the new surface
2855              * description, because only one surface in the flipping chain is a
2856              * back buffer, one is a front buffer, the others are just primary
2857              * surfaces. */
2858             desc2.ddsCaps.dwCaps &= ~DDSCAPS_BACKBUFFER;
2859         }
2860     }
2861
2862     if (desc2.ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE)
2863         ddraw->primary = object;
2864
2865     /* Create a WineD3DTexture if a texture was requested */
2866     if (desc2.ddsCaps.dwCaps & DDSCAPS_TEXTURE)
2867         ddraw_surface_create_texture(object);
2868
2869     return hr;
2870 }
2871
2872 static HRESULT WINAPI ddraw7_CreateSurface(IDirectDraw7 *iface, DDSURFACEDESC2 *surface_desc,
2873         IDirectDrawSurface7 **surface, IUnknown *outer_unknown)
2874 {
2875     struct ddraw *ddraw = impl_from_IDirectDraw7(iface);
2876     struct ddraw_surface *impl;
2877     HRESULT hr;
2878
2879     TRACE("iface %p, surface_desc %p, surface %p, outer_unknown %p.\n",
2880             iface, surface_desc, surface, outer_unknown);
2881
2882     wined3d_mutex_lock();
2883
2884     if (!(ddraw->cooperative_level & (DDSCL_NORMAL | DDSCL_EXCLUSIVE)))
2885     {
2886         WARN("Cooperative level not set.\n");
2887         wined3d_mutex_unlock();
2888         return DDERR_NOCOOPERATIVELEVELSET;
2889     }
2890
2891     if(surface_desc == NULL || surface_desc->dwSize != sizeof(DDSURFACEDESC2))
2892     {
2893         WARN("Application supplied invalid surface descriptor\n");
2894         wined3d_mutex_unlock();
2895         return DDERR_INVALIDPARAMS;
2896     }
2897
2898     if(surface_desc->ddsCaps.dwCaps & (DDSCAPS_FRONTBUFFER | DDSCAPS_BACKBUFFER))
2899     {
2900         if (TRACE_ON(ddraw))
2901         {
2902             TRACE(" (%p) Requesting surface desc :\n", iface);
2903             DDRAW_dump_surface_desc(surface_desc);
2904         }
2905
2906         WARN("Application tried to create an explicit front or back buffer\n");
2907         wined3d_mutex_unlock();
2908         return DDERR_INVALIDCAPS;
2909     }
2910
2911     hr = CreateSurface(ddraw, surface_desc, &impl, outer_unknown, 7);
2912     wined3d_mutex_unlock();
2913     if (FAILED(hr))
2914     {
2915         *surface = NULL;
2916         return hr;
2917     }
2918
2919     *surface = &impl->IDirectDrawSurface7_iface;
2920     IDirectDraw7_AddRef(iface);
2921     impl->ifaceToRelease = (IUnknown *)iface;
2922
2923     return hr;
2924 }
2925
2926 static HRESULT WINAPI ddraw4_CreateSurface(IDirectDraw4 *iface,
2927         DDSURFACEDESC2 *surface_desc, IDirectDrawSurface4 **surface, IUnknown *outer_unknown)
2928 {
2929     struct ddraw *ddraw = impl_from_IDirectDraw4(iface);
2930     struct ddraw_surface *impl;
2931     HRESULT hr;
2932
2933     TRACE("iface %p, surface_desc %p, surface %p, outer_unknown %p.\n",
2934             iface, surface_desc, surface, outer_unknown);
2935
2936     wined3d_mutex_lock();
2937
2938     if (!(ddraw->cooperative_level & (DDSCL_NORMAL | DDSCL_EXCLUSIVE)))
2939     {
2940         WARN("Cooperative level not set.\n");
2941         wined3d_mutex_unlock();
2942         return DDERR_NOCOOPERATIVELEVELSET;
2943     }
2944
2945     if(surface_desc == NULL || surface_desc->dwSize != sizeof(DDSURFACEDESC2))
2946     {
2947         WARN("Application supplied invalid surface descriptor\n");
2948         wined3d_mutex_unlock();
2949         return DDERR_INVALIDPARAMS;
2950     }
2951
2952     if(surface_desc->ddsCaps.dwCaps & (DDSCAPS_FRONTBUFFER | DDSCAPS_BACKBUFFER))
2953     {
2954         if (TRACE_ON(ddraw))
2955         {
2956             TRACE(" (%p) Requesting surface desc :\n", iface);
2957             DDRAW_dump_surface_desc(surface_desc);
2958         }
2959
2960         WARN("Application tried to create an explicit front or back buffer\n");
2961         wined3d_mutex_unlock();
2962         return DDERR_INVALIDCAPS;
2963     }
2964
2965     hr = CreateSurface(ddraw, surface_desc, &impl, outer_unknown, 4);
2966     wined3d_mutex_unlock();
2967     if (FAILED(hr))
2968     {
2969         *surface = NULL;
2970         return hr;
2971     }
2972
2973     *surface = &impl->IDirectDrawSurface4_iface;
2974     IDirectDraw4_AddRef(iface);
2975     impl->ifaceToRelease = (IUnknown *)iface;
2976
2977     return hr;
2978 }
2979
2980 static HRESULT WINAPI ddraw2_CreateSurface(IDirectDraw2 *iface,
2981         DDSURFACEDESC *surface_desc, IDirectDrawSurface **surface, IUnknown *outer_unknown)
2982 {
2983     struct ddraw *ddraw = impl_from_IDirectDraw2(iface);
2984     struct ddraw_surface *impl;
2985     HRESULT hr;
2986     DDSURFACEDESC2 surface_desc2;
2987
2988     TRACE("iface %p, surface_desc %p, surface %p, outer_unknown %p.\n",
2989             iface, surface_desc, surface, outer_unknown);
2990
2991     wined3d_mutex_lock();
2992
2993     if (!(ddraw->cooperative_level & (DDSCL_NORMAL | DDSCL_EXCLUSIVE)))
2994     {
2995         WARN("Cooperative level not set.\n");
2996         wined3d_mutex_unlock();
2997         return DDERR_NOCOOPERATIVELEVELSET;
2998     }
2999
3000     if(surface_desc == NULL || surface_desc->dwSize != sizeof(DDSURFACEDESC))
3001     {
3002         WARN("Application supplied invalid surface descriptor\n");
3003         wined3d_mutex_unlock();
3004         return DDERR_INVALIDPARAMS;
3005     }
3006
3007     DDSD_to_DDSD2(surface_desc, &surface_desc2);
3008     if(surface_desc->ddsCaps.dwCaps & (DDSCAPS_FRONTBUFFER | DDSCAPS_BACKBUFFER))
3009     {
3010         if (TRACE_ON(ddraw))
3011         {
3012             TRACE(" (%p) Requesting surface desc :\n", iface);
3013             DDRAW_dump_surface_desc((DDSURFACEDESC2 *)surface_desc);
3014         }
3015
3016         WARN("Application tried to create an explicit front or back buffer\n");
3017         wined3d_mutex_unlock();
3018         return DDERR_INVALIDCAPS;
3019     }
3020
3021     hr = CreateSurface(ddraw, &surface_desc2, &impl, outer_unknown, 2);
3022     wined3d_mutex_unlock();
3023     if (FAILED(hr))
3024     {
3025         *surface = NULL;
3026         return hr;
3027     }
3028
3029     *surface = &impl->IDirectDrawSurface_iface;
3030     impl->ifaceToRelease = NULL;
3031
3032     return hr;
3033 }
3034
3035 static HRESULT WINAPI ddraw1_CreateSurface(IDirectDraw *iface,
3036         DDSURFACEDESC *surface_desc, IDirectDrawSurface **surface, IUnknown *outer_unknown)
3037 {
3038     struct ddraw *ddraw = impl_from_IDirectDraw(iface);
3039     struct ddraw_surface *impl;
3040     HRESULT hr;
3041     DDSURFACEDESC2 surface_desc2;
3042
3043     TRACE("iface %p, surface_desc %p, surface %p, outer_unknown %p.\n",
3044             iface, surface_desc, surface, outer_unknown);
3045
3046     wined3d_mutex_lock();
3047
3048     if (!(ddraw->cooperative_level & (DDSCL_NORMAL | DDSCL_EXCLUSIVE)))
3049     {
3050         WARN("Cooperative level not set.\n");
3051         wined3d_mutex_unlock();
3052         return DDERR_NOCOOPERATIVELEVELSET;
3053     }
3054
3055     if(surface_desc == NULL || surface_desc->dwSize != sizeof(DDSURFACEDESC))
3056     {
3057         WARN("Application supplied invalid surface descriptor\n");
3058         wined3d_mutex_unlock();
3059         return DDERR_INVALIDPARAMS;
3060     }
3061
3062     /* Remove front buffer flag, this causes failure in v7, and its added to normal
3063      * primaries anyway. */
3064     surface_desc->ddsCaps.dwCaps &= ~DDSCAPS_FRONTBUFFER;
3065     DDSD_to_DDSD2(surface_desc, &surface_desc2);
3066     hr = CreateSurface(ddraw, &surface_desc2, &impl, outer_unknown, 1);
3067     wined3d_mutex_unlock();
3068     if (FAILED(hr))
3069     {
3070         *surface = NULL;
3071         return hr;
3072     }
3073
3074     *surface = &impl->IDirectDrawSurface_iface;
3075     impl->ifaceToRelease = NULL;
3076
3077     return hr;
3078 }
3079
3080 #define DDENUMSURFACES_SEARCHTYPE (DDENUMSURFACES_CANBECREATED|DDENUMSURFACES_DOESEXIST)
3081 #define DDENUMSURFACES_MATCHTYPE (DDENUMSURFACES_ALL|DDENUMSURFACES_MATCH|DDENUMSURFACES_NOMATCH)
3082
3083 static BOOL
3084 Main_DirectDraw_DDPIXELFORMAT_Match(const DDPIXELFORMAT *requested,
3085                                     const DDPIXELFORMAT *provided)
3086 {
3087     /* Some flags must be present in both or neither for a match. */
3088     static const DWORD must_match = DDPF_PALETTEINDEXED1 | DDPF_PALETTEINDEXED2
3089         | DDPF_PALETTEINDEXED4 | DDPF_PALETTEINDEXED8 | DDPF_FOURCC
3090         | DDPF_ZBUFFER | DDPF_STENCILBUFFER;
3091
3092     if ((requested->dwFlags & provided->dwFlags) != requested->dwFlags)
3093         return FALSE;
3094
3095     if ((requested->dwFlags & must_match) != (provided->dwFlags & must_match))
3096         return FALSE;
3097
3098     if (requested->dwFlags & DDPF_FOURCC)
3099         if (requested->dwFourCC != provided->dwFourCC)
3100             return FALSE;
3101
3102     if (requested->dwFlags & (DDPF_RGB|DDPF_YUV|DDPF_ZBUFFER|DDPF_ALPHA
3103                               |DDPF_LUMINANCE|DDPF_BUMPDUDV))
3104         if (requested->u1.dwRGBBitCount != provided->u1.dwRGBBitCount)
3105             return FALSE;
3106
3107     if (requested->dwFlags & (DDPF_RGB|DDPF_YUV|DDPF_STENCILBUFFER
3108                               |DDPF_LUMINANCE|DDPF_BUMPDUDV))
3109         if (requested->u2.dwRBitMask != provided->u2.dwRBitMask)
3110             return FALSE;
3111
3112     if (requested->dwFlags & (DDPF_RGB|DDPF_YUV|DDPF_ZBUFFER|DDPF_BUMPDUDV))
3113         if (requested->u3.dwGBitMask != provided->u3.dwGBitMask)
3114             return FALSE;
3115
3116     /* I could be wrong about the bumpmapping. MSDN docs are vague. */
3117     if (requested->dwFlags & (DDPF_RGB|DDPF_YUV|DDPF_STENCILBUFFER
3118                               |DDPF_BUMPDUDV))
3119         if (requested->u4.dwBBitMask != provided->u4.dwBBitMask)
3120             return FALSE;
3121
3122     if (requested->dwFlags & (DDPF_ALPHAPIXELS|DDPF_ZPIXELS))
3123         if (requested->u5.dwRGBAlphaBitMask != provided->u5.dwRGBAlphaBitMask)
3124             return FALSE;
3125
3126     return TRUE;
3127 }
3128
3129 static BOOL ddraw_match_surface_desc(const DDSURFACEDESC2 *requested, const DDSURFACEDESC2 *provided)
3130 {
3131     struct compare_info
3132     {
3133         DWORD flag;
3134         ptrdiff_t offset;
3135         size_t size;
3136     };
3137
3138 #define CMP(FLAG, FIELD)                                \
3139         { DDSD_##FLAG, offsetof(DDSURFACEDESC2, FIELD), \
3140           sizeof(((DDSURFACEDESC2 *)(NULL))->FIELD) }
3141
3142     static const struct compare_info compare[] =
3143     {
3144         CMP(ALPHABITDEPTH, dwAlphaBitDepth),
3145         CMP(BACKBUFFERCOUNT, dwBackBufferCount),
3146         CMP(CAPS, ddsCaps),
3147         CMP(CKDESTBLT, ddckCKDestBlt),
3148         CMP(CKDESTOVERLAY, u3 /* ddckCKDestOverlay */),
3149         CMP(CKSRCBLT, ddckCKSrcBlt),
3150         CMP(CKSRCOVERLAY, ddckCKSrcOverlay),
3151         CMP(HEIGHT, dwHeight),
3152         CMP(LINEARSIZE, u1 /* dwLinearSize */),
3153         CMP(LPSURFACE, lpSurface),
3154         CMP(MIPMAPCOUNT, u2 /* dwMipMapCount */),
3155         CMP(PITCH, u1 /* lPitch */),
3156         /* PIXELFORMAT: manual */
3157         CMP(REFRESHRATE, u2 /* dwRefreshRate */),
3158         CMP(TEXTURESTAGE, dwTextureStage),
3159         CMP(WIDTH, dwWidth),
3160         /* ZBUFFERBITDEPTH: "obsolete" */
3161     };
3162
3163 #undef CMP
3164
3165     unsigned int i;
3166
3167     if ((requested->dwFlags & provided->dwFlags) != requested->dwFlags)
3168         return FALSE;
3169
3170     for (i=0; i < sizeof(compare)/sizeof(compare[0]); i++)
3171     {
3172         if (requested->dwFlags & compare[i].flag
3173             && memcmp((const char *)provided + compare[i].offset,
3174                       (const char *)requested + compare[i].offset,
3175                       compare[i].size) != 0)
3176             return FALSE;
3177     }
3178
3179     if (requested->dwFlags & DDSD_PIXELFORMAT)
3180     {
3181         if (!Main_DirectDraw_DDPIXELFORMAT_Match(&requested->u4.ddpfPixelFormat,
3182                                                 &provided->u4.ddpfPixelFormat))
3183             return FALSE;
3184     }
3185
3186     return TRUE;
3187 }
3188
3189 #undef DDENUMSURFACES_SEARCHTYPE
3190 #undef DDENUMSURFACES_MATCHTYPE
3191
3192 struct surfacescallback2_context
3193 {
3194     LPDDENUMSURFACESCALLBACK2 func;
3195     void *context;
3196 };
3197
3198 struct surfacescallback_context
3199 {
3200     LPDDENUMSURFACESCALLBACK func;
3201     void *context;
3202 };
3203
3204 static HRESULT CALLBACK EnumSurfacesCallback2Thunk(IDirectDrawSurface7 *surface,
3205         DDSURFACEDESC2 *surface_desc, void *context)
3206 {
3207     struct ddraw_surface *surface_impl = impl_from_IDirectDrawSurface7(surface);
3208     struct surfacescallback2_context *cbcontext = context;
3209
3210     IDirectDrawSurface4_AddRef(&surface_impl->IDirectDrawSurface4_iface);
3211     IDirectDrawSurface7_Release(surface);
3212
3213     return cbcontext->func(&surface_impl->IDirectDrawSurface4_iface,
3214             surface_desc, cbcontext->context);
3215 }
3216
3217 static HRESULT CALLBACK EnumSurfacesCallbackThunk(IDirectDrawSurface7 *surface,
3218         DDSURFACEDESC2 *surface_desc, void *context)
3219 {
3220     struct ddraw_surface *surface_impl = impl_from_IDirectDrawSurface7(surface);
3221     struct surfacescallback_context *cbcontext = context;
3222
3223     IDirectDrawSurface_AddRef(&surface_impl->IDirectDrawSurface_iface);
3224     IDirectDrawSurface7_Release(surface);
3225
3226     return cbcontext->func(&surface_impl->IDirectDrawSurface_iface,
3227             (DDSURFACEDESC *)surface_desc, cbcontext->context);
3228 }
3229
3230 /*****************************************************************************
3231  * IDirectDraw7::EnumSurfaces
3232  *
3233  * Loops through all surfaces attached to this device and calls the
3234  * application callback. This can't be relayed to WineD3DDevice,
3235  * because some WineD3DSurfaces' parents are IParent objects
3236  *
3237  * Params:
3238  *  Flags: Some filtering flags. See IDirectDrawImpl_EnumSurfacesCallback
3239  *  DDSD: Description to filter for
3240  *  Context: Application-provided pointer, it's passed unmodified to the
3241  *           Callback function
3242  *  Callback: Address to call for each surface
3243  *
3244  * Returns:
3245  *  DDERR_INVALIDPARAMS if the callback is NULL
3246  *  DD_OK on success
3247  *
3248  *****************************************************************************/
3249 static HRESULT WINAPI ddraw7_EnumSurfaces(IDirectDraw7 *iface, DWORD Flags,
3250         DDSURFACEDESC2 *DDSD, void *Context, LPDDENUMSURFACESCALLBACK7 Callback)
3251 {
3252     struct ddraw *ddraw = impl_from_IDirectDraw7(iface);
3253     struct ddraw_surface *surf;
3254     BOOL all, nomatch;
3255     DDSURFACEDESC2 desc;
3256     struct list *entry, *entry2;
3257
3258     TRACE("iface %p, flags %#x, surface_desc %p, context %p, callback %p.\n",
3259             iface, Flags, DDSD, Context, Callback);
3260
3261     all = Flags & DDENUMSURFACES_ALL;
3262     nomatch = Flags & DDENUMSURFACES_NOMATCH;
3263
3264     if (!Callback)
3265         return DDERR_INVALIDPARAMS;
3266
3267     wined3d_mutex_lock();
3268
3269     /* Use the _SAFE enumeration, the app may destroy enumerated surfaces */
3270     LIST_FOR_EACH_SAFE(entry, entry2, &ddraw->surface_list)
3271     {
3272         surf = LIST_ENTRY(entry, struct ddraw_surface, surface_list_entry);
3273
3274         if (!surf->iface_count)
3275         {
3276             WARN("Not enumerating surface %p because it doesn't have any references.\n", surf);
3277             continue;
3278         }
3279
3280         if (all || (nomatch != ddraw_match_surface_desc(DDSD, &surf->surface_desc)))
3281         {
3282             TRACE("Enumerating surface %p.\n", surf);
3283             desc = surf->surface_desc;
3284             IDirectDrawSurface7_AddRef(&surf->IDirectDrawSurface7_iface);
3285             if (Callback(&surf->IDirectDrawSurface7_iface, &desc, Context) != DDENUMRET_OK)
3286             {
3287                 wined3d_mutex_unlock();
3288                 return DD_OK;
3289             }
3290         }
3291     }
3292
3293     wined3d_mutex_unlock();
3294
3295     return DD_OK;
3296 }
3297
3298 static HRESULT WINAPI ddraw4_EnumSurfaces(IDirectDraw4 *iface, DWORD flags,
3299         DDSURFACEDESC2 *surface_desc, void *context, LPDDENUMSURFACESCALLBACK2 callback)
3300 {
3301     struct ddraw *ddraw = impl_from_IDirectDraw4(iface);
3302     struct surfacescallback2_context cbcontext;
3303
3304     TRACE("iface %p, flags %#x, surface_desc %p, context %p, callback %p.\n",
3305             iface, flags, surface_desc, context, callback);
3306
3307     cbcontext.func = callback;
3308     cbcontext.context = context;
3309
3310     return ddraw7_EnumSurfaces(&ddraw->IDirectDraw7_iface, flags, surface_desc,
3311             &cbcontext, EnumSurfacesCallback2Thunk);
3312 }
3313
3314 static HRESULT WINAPI ddraw2_EnumSurfaces(IDirectDraw2 *iface, DWORD flags,
3315         DDSURFACEDESC *surface_desc, void *context, LPDDENUMSURFACESCALLBACK callback)
3316 {
3317     struct ddraw *ddraw = impl_from_IDirectDraw2(iface);
3318     struct surfacescallback_context cbcontext;
3319     DDSURFACEDESC2 surface_desc2;
3320
3321     TRACE("iface %p, flags %#x, surface_desc %p, context %p, callback %p.\n",
3322             iface, flags, surface_desc, context, callback);
3323
3324     cbcontext.func = callback;
3325     cbcontext.context = context;
3326
3327     if (surface_desc) DDSD_to_DDSD2(surface_desc, &surface_desc2);
3328     return ddraw7_EnumSurfaces(&ddraw->IDirectDraw7_iface, flags,
3329             surface_desc ? &surface_desc2 : NULL, &cbcontext, EnumSurfacesCallbackThunk);
3330 }
3331
3332 static HRESULT WINAPI ddraw1_EnumSurfaces(IDirectDraw *iface, DWORD flags,
3333         DDSURFACEDESC *surface_desc, void *context, LPDDENUMSURFACESCALLBACK callback)
3334 {
3335     struct ddraw *ddraw = impl_from_IDirectDraw(iface);
3336     struct surfacescallback_context cbcontext;
3337     DDSURFACEDESC2 surface_desc2;
3338
3339     TRACE("iface %p, flags %#x, surface_desc %p, context %p, callback %p.\n",
3340             iface, flags, surface_desc, context, callback);
3341
3342     cbcontext.func = callback;
3343     cbcontext.context = context;
3344
3345     if (surface_desc) DDSD_to_DDSD2(surface_desc, &surface_desc2);
3346     return ddraw7_EnumSurfaces(&ddraw->IDirectDraw7_iface, flags,
3347             surface_desc ? &surface_desc2 : NULL, &cbcontext, EnumSurfacesCallbackThunk);
3348 }
3349
3350 /*****************************************************************************
3351  * DirectDrawCreateClipper (DDRAW.@)
3352  *
3353  * Creates a new IDirectDrawClipper object.
3354  *
3355  * Params:
3356  *  Clipper: Address to write the interface pointer to
3357  *  UnkOuter: For aggregation support, which ddraw doesn't have. Has to be
3358  *            NULL
3359  *
3360  * Returns:
3361  *  CLASS_E_NOAGGREGATION if UnkOuter != NULL
3362  *  E_OUTOFMEMORY if allocating the object failed
3363  *
3364  *****************************************************************************/
3365 HRESULT WINAPI DirectDrawCreateClipper(DWORD flags, IDirectDrawClipper **clipper, IUnknown *outer_unknown)
3366 {
3367     struct ddraw_clipper *object;
3368     HRESULT hr;
3369
3370     TRACE("flags %#x, clipper %p, outer_unknown %p.\n",
3371             flags, clipper, outer_unknown);
3372
3373     if (outer_unknown)
3374         return CLASS_E_NOAGGREGATION;
3375
3376     wined3d_mutex_lock();
3377
3378     object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*object));
3379     if (!object)
3380     {
3381         wined3d_mutex_unlock();
3382         return E_OUTOFMEMORY;
3383     }
3384
3385     hr = ddraw_clipper_init(object);
3386     if (FAILED(hr))
3387     {
3388         WARN("Failed to initialize clipper, hr %#x.\n", hr);
3389         HeapFree(GetProcessHeap(), 0, object);
3390         wined3d_mutex_unlock();
3391         return hr;
3392     }
3393
3394     TRACE("Created clipper %p.\n", object);
3395     *clipper = &object->IDirectDrawClipper_iface;
3396     wined3d_mutex_unlock();
3397
3398     return DD_OK;
3399 }
3400
3401 /*****************************************************************************
3402  * IDirectDraw7::CreateClipper
3403  *
3404  * Creates a DDraw clipper. See DirectDrawCreateClipper for details
3405  *
3406  *****************************************************************************/
3407 static HRESULT WINAPI ddraw7_CreateClipper(IDirectDraw7 *iface, DWORD Flags,
3408         IDirectDrawClipper **Clipper, IUnknown *UnkOuter)
3409 {
3410     TRACE("iface %p, flags %#x, clipper %p, outer_unknown %p.\n",
3411             iface, Flags, Clipper, UnkOuter);
3412
3413     return DirectDrawCreateClipper(Flags, Clipper, UnkOuter);
3414 }
3415
3416 static HRESULT WINAPI ddraw4_CreateClipper(IDirectDraw4 *iface, DWORD flags,
3417         IDirectDrawClipper **clipper, IUnknown *outer_unknown)
3418 {
3419     struct ddraw *ddraw = impl_from_IDirectDraw4(iface);
3420
3421     TRACE("iface %p, flags %#x, clipper %p, outer_unknown %p.\n",
3422             iface, flags, clipper, outer_unknown);
3423
3424     return ddraw7_CreateClipper(&ddraw->IDirectDraw7_iface, flags, clipper, outer_unknown);
3425 }
3426
3427 static HRESULT WINAPI ddraw2_CreateClipper(IDirectDraw2 *iface,
3428         DWORD flags, IDirectDrawClipper **clipper, IUnknown *outer_unknown)
3429 {
3430     struct ddraw *ddraw = impl_from_IDirectDraw2(iface);
3431
3432     TRACE("iface %p, flags %#x, clipper %p, outer_unknown %p.\n",
3433             iface, flags, clipper, outer_unknown);
3434
3435     return ddraw7_CreateClipper(&ddraw->IDirectDraw7_iface, flags, clipper, outer_unknown);
3436 }
3437
3438 static HRESULT WINAPI ddraw1_CreateClipper(IDirectDraw *iface,
3439         DWORD flags, IDirectDrawClipper **clipper, IUnknown *outer_unknown)
3440 {
3441     struct ddraw *ddraw = impl_from_IDirectDraw(iface);
3442
3443     TRACE("iface %p, flags %#x, clipper %p, outer_unknown %p.\n",
3444             iface, flags, clipper, outer_unknown);
3445
3446     return ddraw7_CreateClipper(&ddraw->IDirectDraw7_iface, flags, clipper, outer_unknown);
3447 }
3448
3449 /*****************************************************************************
3450  * IDirectDraw7::CreatePalette
3451  *
3452  * Creates a new IDirectDrawPalette object
3453  *
3454  * Params:
3455  *  Flags: The flags for the new clipper
3456  *  ColorTable: Color table to assign to the new clipper
3457  *  Palette: Address to write the interface pointer to
3458  *  UnkOuter: For aggregation support, which ddraw doesn't have. Has to be
3459  *            NULL
3460  *
3461  * Returns:
3462  *  CLASS_E_NOAGGREGATION if UnkOuter != NULL
3463  *  E_OUTOFMEMORY if allocating the object failed
3464  *
3465  *****************************************************************************/
3466 static HRESULT WINAPI ddraw7_CreatePalette(IDirectDraw7 *iface, DWORD Flags,
3467         PALETTEENTRY *ColorTable, IDirectDrawPalette **Palette, IUnknown *pUnkOuter)
3468 {
3469     struct ddraw *ddraw = impl_from_IDirectDraw7(iface);
3470     struct ddraw_palette *object;
3471     HRESULT hr;
3472
3473     TRACE("iface %p, flags %#x, color_table %p, palette %p, outer_unknown %p.\n",
3474             iface, Flags, ColorTable, Palette, pUnkOuter);
3475
3476     if (pUnkOuter)
3477         return CLASS_E_NOAGGREGATION;
3478
3479     wined3d_mutex_lock();
3480
3481     /* The refcount test shows that a cooplevel is required for this */
3482     if (!ddraw->cooperative_level)
3483     {
3484         WARN("No cooperative level set, returning DDERR_NOCOOPERATIVELEVELSET\n");
3485         wined3d_mutex_unlock();
3486         return DDERR_NOCOOPERATIVELEVELSET;
3487     }
3488
3489     object = HeapAlloc(GetProcessHeap(), 0, sizeof(*object));
3490     if (!object)
3491     {
3492         ERR("Out of memory when allocating memory for a palette implementation\n");
3493         wined3d_mutex_unlock();
3494         return E_OUTOFMEMORY;
3495     }
3496
3497     hr = ddraw_palette_init(object, ddraw, Flags, ColorTable);
3498     if (FAILED(hr))
3499     {
3500         WARN("Failed to initialize palette, hr %#x.\n", hr);
3501         HeapFree(GetProcessHeap(), 0, object);
3502         wined3d_mutex_unlock();
3503         return hr;
3504     }
3505
3506     TRACE("Created palette %p.\n", object);
3507     *Palette = &object->IDirectDrawPalette_iface;
3508     wined3d_mutex_unlock();
3509
3510     return DD_OK;
3511 }
3512
3513 static HRESULT WINAPI ddraw4_CreatePalette(IDirectDraw4 *iface, DWORD flags, PALETTEENTRY *entries,
3514         IDirectDrawPalette **palette, IUnknown *outer_unknown)
3515 {
3516     struct ddraw *ddraw = impl_from_IDirectDraw4(iface);
3517     HRESULT hr;
3518
3519     TRACE("iface %p, flags %#x, entries %p, palette %p, outer_unknown %p.\n",
3520             iface, flags, entries, palette, outer_unknown);
3521
3522     hr = ddraw7_CreatePalette(&ddraw->IDirectDraw7_iface, flags, entries, palette, outer_unknown);
3523     if (SUCCEEDED(hr) && *palette)
3524     {
3525         struct ddraw_palette *impl = impl_from_IDirectDrawPalette(*palette);
3526         IDirectDraw7_Release(&ddraw->IDirectDraw7_iface);
3527         IDirectDraw4_AddRef(iface);
3528         impl->ifaceToRelease = (IUnknown *)iface;
3529     }
3530     return hr;
3531 }
3532
3533 static HRESULT WINAPI ddraw2_CreatePalette(IDirectDraw2 *iface, DWORD flags,
3534         PALETTEENTRY *entries, IDirectDrawPalette **palette, IUnknown *outer_unknown)
3535 {
3536     struct ddraw *ddraw = impl_from_IDirectDraw2(iface);
3537     HRESULT hr;
3538
3539     TRACE("iface %p, flags %#x, entries %p, palette %p, outer_unknown %p.\n",
3540             iface, flags, entries, palette, outer_unknown);
3541
3542     hr = ddraw7_CreatePalette(&ddraw->IDirectDraw7_iface, flags, entries, palette, outer_unknown);
3543     if (SUCCEEDED(hr) && *palette)
3544     {
3545         struct ddraw_palette *impl = impl_from_IDirectDrawPalette(*palette);
3546         IDirectDraw7_Release(&ddraw->IDirectDraw7_iface);
3547         impl->ifaceToRelease = NULL;
3548     }
3549
3550     return hr;
3551 }
3552
3553 static HRESULT WINAPI ddraw1_CreatePalette(IDirectDraw *iface, DWORD flags,
3554         PALETTEENTRY *entries, IDirectDrawPalette **palette, IUnknown *outer_unknown)
3555 {
3556     struct ddraw *ddraw = impl_from_IDirectDraw(iface);
3557     HRESULT hr;
3558
3559     TRACE("iface %p, flags %#x, entries %p, palette %p, outer_unknown %p.\n",
3560             iface, flags, entries, palette, outer_unknown);
3561
3562     hr = ddraw7_CreatePalette(&ddraw->IDirectDraw7_iface, flags, entries, palette, outer_unknown);
3563     if (SUCCEEDED(hr) && *palette)
3564     {
3565         struct ddraw_palette *impl = impl_from_IDirectDrawPalette(*palette);
3566         IDirectDraw7_Release(&ddraw->IDirectDraw7_iface);
3567         impl->ifaceToRelease = NULL;
3568     }
3569
3570     return hr;
3571 }
3572
3573 /*****************************************************************************
3574  * IDirectDraw7::DuplicateSurface
3575  *
3576  * Duplicates a surface. The surface memory points to the same memory as
3577  * the original surface, and it's released when the last surface referencing
3578  * it is released. I guess that's beyond Wine's surface management right now
3579  * (Idea: create a new DDraw surface with the same WineD3DSurface. I need a
3580  * test application to implement this)
3581  *
3582  * Params:
3583  *  Src: Address of the source surface
3584  *  Dest: Address to write the new surface pointer to
3585  *
3586  * Returns:
3587  *  See IDirectDraw7::CreateSurface
3588  *
3589  *****************************************************************************/
3590 static HRESULT WINAPI ddraw7_DuplicateSurface(IDirectDraw7 *iface,
3591         IDirectDrawSurface7 *Src, IDirectDrawSurface7 **Dest)
3592 {
3593     struct ddraw_surface *src_surface = unsafe_impl_from_IDirectDrawSurface7(Src);
3594
3595     FIXME("iface %p, src %p, dst %p partial stub!\n", iface, Src, Dest);
3596
3597     /* For now, simply create a new, independent surface */
3598     return IDirectDraw7_CreateSurface(iface, &src_surface->surface_desc, Dest, NULL);
3599 }
3600
3601 static HRESULT WINAPI ddraw4_DuplicateSurface(IDirectDraw4 *iface, IDirectDrawSurface4 *src,
3602         IDirectDrawSurface4 **dst)
3603 {
3604     struct ddraw_surface *src_impl = unsafe_impl_from_IDirectDrawSurface4(src);
3605     struct ddraw *ddraw = impl_from_IDirectDraw4(iface);
3606     struct ddraw_surface *dst_impl;
3607     IDirectDrawSurface7 *dst7;
3608     HRESULT hr;
3609
3610     TRACE("iface %p, src %p, dst %p.\n", iface, src, dst);
3611
3612     hr = ddraw7_DuplicateSurface(&ddraw->IDirectDraw7_iface,
3613             src_impl ? &src_impl->IDirectDrawSurface7_iface : NULL, &dst7);
3614     if (FAILED(hr))
3615     {
3616         *dst = NULL;
3617         return hr;
3618     }
3619     dst_impl = impl_from_IDirectDrawSurface7(dst7);
3620     *dst = &dst_impl->IDirectDrawSurface4_iface;
3621     IDirectDrawSurface4_AddRef(*dst);
3622     IDirectDrawSurface7_Release(dst7);
3623
3624     return hr;
3625 }
3626
3627 static HRESULT WINAPI ddraw2_DuplicateSurface(IDirectDraw2 *iface,
3628         IDirectDrawSurface *src, IDirectDrawSurface **dst)
3629 {
3630     struct ddraw_surface *src_impl = unsafe_impl_from_IDirectDrawSurface(src);
3631     struct ddraw *ddraw = impl_from_IDirectDraw2(iface);
3632     struct ddraw_surface *dst_impl;
3633     IDirectDrawSurface7 *dst7;
3634     HRESULT hr;
3635
3636     TRACE("iface %p, src %p, dst %p.\n", iface, src, dst);
3637
3638     hr = ddraw7_DuplicateSurface(&ddraw->IDirectDraw7_iface,
3639             src_impl ? &src_impl->IDirectDrawSurface7_iface : NULL, &dst7);
3640     if (FAILED(hr))
3641         return hr;
3642     dst_impl = impl_from_IDirectDrawSurface7(dst7);
3643     *dst = &dst_impl->IDirectDrawSurface_iface;
3644     IDirectDrawSurface_AddRef(*dst);
3645     IDirectDrawSurface7_Release(dst7);
3646
3647     return hr;
3648 }
3649
3650 static HRESULT WINAPI ddraw1_DuplicateSurface(IDirectDraw *iface, IDirectDrawSurface *src,
3651         IDirectDrawSurface **dst)
3652 {
3653     struct ddraw_surface *src_impl = unsafe_impl_from_IDirectDrawSurface(src);
3654     struct ddraw *ddraw = impl_from_IDirectDraw(iface);
3655     struct ddraw_surface *dst_impl;
3656     IDirectDrawSurface7 *dst7;
3657     HRESULT hr;
3658
3659     TRACE("iface %p, src %p, dst %p.\n", iface, src, dst);
3660
3661     hr = ddraw7_DuplicateSurface(&ddraw->IDirectDraw7_iface,
3662             src_impl ? &src_impl->IDirectDrawSurface7_iface : NULL, &dst7);
3663     if (FAILED(hr))
3664         return hr;
3665     dst_impl = impl_from_IDirectDrawSurface7(dst7);
3666     *dst = &dst_impl->IDirectDrawSurface_iface;
3667     IDirectDrawSurface_AddRef(*dst);
3668     IDirectDrawSurface7_Release(dst7);
3669
3670     return hr;
3671 }
3672
3673 /*****************************************************************************
3674  * IDirect3D7::EnumDevices
3675  *
3676  * The EnumDevices method for IDirect3D7. It enumerates all supported
3677  * D3D7 devices. Currently the T&L, HAL and RGB devices are enumerated.
3678  *
3679  * Params:
3680  *  callback: Function to call for each enumerated device
3681  *  context: Pointer to pass back to the app
3682  *
3683  * Returns:
3684  *  D3D_OK, or the return value of the GetCaps call
3685  *
3686  *****************************************************************************/
3687 static HRESULT WINAPI d3d7_EnumDevices(IDirect3D7 *iface, LPD3DENUMDEVICESCALLBACK7 callback, void *context)
3688 {
3689     struct ddraw *ddraw = impl_from_IDirect3D7(iface);
3690     D3DDEVICEDESC7 device_desc7;
3691     D3DDEVICEDESC device_desc1;
3692     HRESULT hr;
3693     size_t i;
3694
3695     TRACE("iface %p, callback %p, context %p.\n", iface, callback, context);
3696
3697     if (!callback)
3698         return DDERR_INVALIDPARAMS;
3699
3700     wined3d_mutex_lock();
3701
3702     hr = IDirect3DImpl_GetCaps(ddraw->wined3d, &device_desc1, &device_desc7);
3703     if (hr != D3D_OK)
3704     {
3705         wined3d_mutex_unlock();
3706         return hr;
3707     }
3708
3709     for (i = 0; i < sizeof(device_list7)/sizeof(device_list7[0]); i++)
3710     {
3711         HRESULT ret;
3712
3713         device_desc7.deviceGUID = *device_list7[i].device_guid;
3714         ret = callback(device_list7[i].interface_name, device_list7[i].device_name, &device_desc7, context);
3715         if (ret != DDENUMRET_OK)
3716         {
3717             TRACE("Application cancelled the enumeration.\n");
3718             wined3d_mutex_unlock();
3719             return D3D_OK;
3720         }
3721     }
3722
3723     TRACE("End of enumeration.\n");
3724
3725     wined3d_mutex_unlock();
3726
3727     return D3D_OK;
3728 }
3729
3730 /*****************************************************************************
3731  * IDirect3D3::EnumDevices
3732  *
3733  * Enumerates all supported Direct3DDevice interfaces. This is the
3734  * implementation for Direct3D 1 to Direc3D 3, Version 7 has its own.
3735  *
3736  * Version 1, 2 and 3
3737  *
3738  * Params:
3739  *  callback: Application-provided routine to call for each enumerated device
3740  *  Context: Pointer to pass to the callback
3741  *
3742  * Returns:
3743  *  D3D_OK on success,
3744  *  The result of IDirect3DImpl_GetCaps if it failed
3745  *
3746  *****************************************************************************/
3747 static HRESULT WINAPI d3d3_EnumDevices(IDirect3D3 *iface, LPD3DENUMDEVICESCALLBACK callback, void *context)
3748 {
3749     static CHAR wined3d_description[] = "Wine D3DDevice using WineD3D and OpenGL";
3750
3751     struct ddraw *ddraw = impl_from_IDirect3D3(iface);
3752     D3DDEVICEDESC device_desc1, hal_desc, hel_desc;
3753     D3DDEVICEDESC7 device_desc7;
3754     HRESULT hr;
3755
3756     /* Some games (Motoracer 2 demo) have the bad idea to modify the device
3757      * name string. Let's put the string in a sufficiently sized array in
3758      * writable memory. */
3759     char device_name[50];
3760     strcpy(device_name,"Direct3D HEL");
3761
3762     TRACE("iface %p, callback %p, context %p.\n", iface, callback, context);
3763
3764     if (!callback)
3765         return DDERR_INVALIDPARAMS;
3766
3767     wined3d_mutex_lock();
3768
3769     hr = IDirect3DImpl_GetCaps(ddraw->wined3d, &device_desc1, &device_desc7);
3770     if (hr != D3D_OK)
3771     {
3772         wined3d_mutex_unlock();
3773         return hr;
3774     }
3775
3776     /* Do I have to enumerate the reference id? Note from old d3d7:
3777      * "It seems that enumerating the reference IID on Direct3D 1 games
3778      * (AvP / Motoracer2) breaks them". So do not enumerate this iid in V1
3779      *
3780      * There's a registry key HKLM\Software\Microsoft\Direct3D\Drivers,
3781      * EnumReference which enables / disables enumerating the reference
3782      * rasterizer. It's a DWORD, 0 means disabled, 2 means enabled. The
3783      * enablerefrast.reg and disablerefrast.reg files in the DirectX 7.0 sdk
3784      * demo directory suggest this.
3785      *
3786      * Some games(GTA 2) seem to use the second enumerated device, so I have
3787      * to enumerate at least 2 devices. So enumerate the reference device to
3788      * have 2 devices.
3789      *
3790      * Other games (Rollcage) tell emulation and hal device apart by certain
3791      * flags. Rollcage expects D3DPTEXTURECAPS_POW2 to be set (yeah, it is a
3792      * limitation flag), and it refuses all devices that have the perspective
3793      * flag set. This way it refuses the emulation device, and HAL devices
3794      * never have POW2 unset in d3d7 on windows. */
3795     if (ddraw->d3dversion != 1)
3796     {
3797         static CHAR reference_description[] = "RGB Direct3D emulation";
3798
3799         TRACE("Enumerating WineD3D D3DDevice interface.\n");
3800         hal_desc = device_desc1;
3801         hel_desc = device_desc1;
3802         /* The rgb device has the pow2 flag set in the hel caps, but not in the hal caps. */
3803         hal_desc.dpcLineCaps.dwTextureCaps &= ~(D3DPTEXTURECAPS_POW2
3804                 | D3DPTEXTURECAPS_NONPOW2CONDITIONAL | D3DPTEXTURECAPS_PERSPECTIVE);
3805         hal_desc.dpcTriCaps.dwTextureCaps &= ~(D3DPTEXTURECAPS_POW2
3806                 | D3DPTEXTURECAPS_NONPOW2CONDITIONAL | D3DPTEXTURECAPS_PERSPECTIVE);
3807         /* RGB, RAMP and MMX devices have a HAL dcmColorModel of 0 */
3808         hal_desc.dcmColorModel = 0;
3809
3810         hr = callback((GUID *)&IID_IDirect3DRGBDevice, reference_description,
3811                 device_name, &hal_desc, &hel_desc, context);
3812         if (hr != D3DENUMRET_OK)
3813         {
3814             TRACE("Application cancelled the enumeration.\n");
3815             wined3d_mutex_unlock();
3816             return D3D_OK;
3817         }
3818     }
3819
3820     strcpy(device_name,"Direct3D HAL");
3821
3822     TRACE("Enumerating HAL Direct3D device.\n");
3823     hal_desc = device_desc1;
3824     hel_desc = device_desc1;
3825
3826     /* The hal device does not have the pow2 flag set in hel, but in hal. */
3827     hel_desc.dpcLineCaps.dwTextureCaps &= ~(D3DPTEXTURECAPS_POW2
3828             | D3DPTEXTURECAPS_NONPOW2CONDITIONAL | D3DPTEXTURECAPS_PERSPECTIVE);
3829     hel_desc.dpcTriCaps.dwTextureCaps &= ~(D3DPTEXTURECAPS_POW2
3830             | D3DPTEXTURECAPS_NONPOW2CONDITIONAL | D3DPTEXTURECAPS_PERSPECTIVE);
3831     /* HAL devices have a HEL dcmColorModel of 0 */
3832     hel_desc.dcmColorModel = 0;
3833
3834     hr = callback((GUID *)&IID_IDirect3DHALDevice, wined3d_description,
3835             device_name, &hal_desc, &hel_desc, context);
3836     if (hr != D3DENUMRET_OK)
3837     {
3838         TRACE("Application cancelled the enumeration.\n");
3839         wined3d_mutex_unlock();
3840         return D3D_OK;
3841     }
3842
3843     TRACE("End of enumeration.\n");
3844
3845     wined3d_mutex_unlock();
3846
3847     return D3D_OK;
3848 }
3849
3850 static HRESULT WINAPI d3d2_EnumDevices(IDirect3D2 *iface, LPD3DENUMDEVICESCALLBACK callback, void *context)
3851 {
3852     struct ddraw *ddraw = impl_from_IDirect3D2(iface);
3853
3854     TRACE("iface %p, callback %p, context %p.\n", iface, callback, context);
3855
3856     return d3d3_EnumDevices(&ddraw->IDirect3D3_iface, callback, context);
3857 }
3858
3859 static HRESULT WINAPI d3d1_EnumDevices(IDirect3D *iface, LPD3DENUMDEVICESCALLBACK callback, void *context)
3860 {
3861     struct ddraw *ddraw = impl_from_IDirect3D(iface);
3862
3863     TRACE("iface %p, callback %p, context %p.\n", iface, callback, context);
3864
3865     return d3d3_EnumDevices(&ddraw->IDirect3D3_iface, callback, context);
3866 }
3867
3868 /*****************************************************************************
3869  * IDirect3D3::CreateLight
3870  *
3871  * Creates an IDirect3DLight interface. This interface is used in
3872  * Direct3D3 or earlier for lighting. In Direct3D7 it has been replaced
3873  * by the DIRECT3DLIGHT7 structure. Wine's Direct3DLight implementation
3874  * uses the IDirect3DDevice7 interface with D3D7 lights.
3875  *
3876  * Version 1, 2 and 3
3877  *
3878  * Params:
3879  *  light: Address to store the new interface pointer
3880  *  outer_unknown: Basically for aggregation, but ddraw doesn't support it.
3881  *                 Must be NULL
3882  *
3883  * Returns:
3884  *  D3D_OK on success
3885  *  DDERR_OUTOFMEMORY if memory allocation failed
3886  *  CLASS_E_NOAGGREGATION if outer_unknown != NULL
3887  *
3888  *****************************************************************************/
3889 static HRESULT WINAPI d3d3_CreateLight(IDirect3D3 *iface, IDirect3DLight **light,
3890         IUnknown *outer_unknown)
3891 {
3892     struct ddraw *ddraw = impl_from_IDirect3D3(iface);
3893     struct d3d_light *object;
3894
3895     TRACE("iface %p, light %p, outer_unknown %p.\n", iface, light, outer_unknown);
3896
3897     if (outer_unknown) return CLASS_E_NOAGGREGATION;
3898
3899     object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*object));
3900     if (!object)
3901     {
3902         ERR("Failed to allocate light memory.\n");
3903         return DDERR_OUTOFMEMORY;
3904     }
3905
3906     d3d_light_init(object, ddraw);
3907
3908     TRACE("Created light %p.\n", object);
3909     *light = &object->IDirect3DLight_iface;
3910
3911     return D3D_OK;
3912 }
3913
3914 static HRESULT WINAPI d3d2_CreateLight(IDirect3D2 *iface, IDirect3DLight **light, IUnknown *outer_unknown)
3915 {
3916     struct ddraw *ddraw = impl_from_IDirect3D2(iface);
3917
3918     TRACE("iface %p, light %p, outer_unknown %p.\n", iface, light, outer_unknown);
3919
3920     return d3d3_CreateLight(&ddraw->IDirect3D3_iface, light, outer_unknown);
3921 }
3922
3923 static HRESULT WINAPI d3d1_CreateLight(IDirect3D *iface, IDirect3DLight **light, IUnknown *outer_unknown)
3924 {
3925     struct ddraw *ddraw = impl_from_IDirect3D(iface);
3926
3927     TRACE("iface %p, light %p, outer_unknown %p.\n", iface, light, outer_unknown);
3928
3929     return d3d3_CreateLight(&ddraw->IDirect3D3_iface, light, outer_unknown);
3930 }
3931
3932 /*****************************************************************************
3933  * IDirect3D3::CreateMaterial
3934  *
3935  * Creates an IDirect3DMaterial interface. This interface is used by Direct3D3
3936  * and older versions. The IDirect3DMaterial implementation wraps its
3937  * functionality to IDirect3DDevice7::SetMaterial and friends.
3938  *
3939  * Version 1, 2 and 3
3940  *
3941  * Params:
3942  *  material: Address to store the new interface's pointer to
3943  *  outer_unknown: Basically for aggregation, but ddraw doesn't support it.
3944  *                 Must be NULL
3945  *
3946  * Returns:
3947  *  D3D_OK on success
3948  *  DDERR_OUTOFMEMORY if memory allocation failed
3949  *  CLASS_E_NOAGGREGATION if outer_unknown != NULL
3950  *
3951  *****************************************************************************/
3952 static HRESULT WINAPI d3d3_CreateMaterial(IDirect3D3 *iface, IDirect3DMaterial3 **material,
3953         IUnknown *outer_unknown)
3954 {
3955     struct ddraw *ddraw = impl_from_IDirect3D3(iface);
3956     struct d3d_material *object;
3957
3958     TRACE("iface %p, material %p, outer_unknown %p.\n", iface, material, outer_unknown);
3959
3960     if (outer_unknown) return CLASS_E_NOAGGREGATION;
3961
3962     object = d3d_material_create(ddraw);
3963     if (!object)
3964     {
3965         ERR("Failed to allocate material memory.\n");
3966         return DDERR_OUTOFMEMORY;
3967     }
3968
3969     TRACE("Created material %p.\n", object);
3970     *material = &object->IDirect3DMaterial3_iface;
3971
3972     return D3D_OK;
3973 }
3974
3975 static HRESULT WINAPI d3d2_CreateMaterial(IDirect3D2 *iface, IDirect3DMaterial2 **material,
3976         IUnknown *outer_unknown)
3977 {
3978     struct ddraw *ddraw = impl_from_IDirect3D2(iface);
3979     struct d3d_material *object;
3980
3981     TRACE("iface %p, material %p, outer_unknown %p.\n", iface, material, outer_unknown);
3982
3983     object = d3d_material_create(ddraw);
3984     if (!object)
3985     {
3986         ERR("Failed to allocate material memory.\n");
3987         return DDERR_OUTOFMEMORY;
3988     }
3989
3990     TRACE("Created material %p.\n", object);
3991     *material = &object->IDirect3DMaterial2_iface;
3992
3993     return D3D_OK;
3994 }
3995
3996 static HRESULT WINAPI d3d1_CreateMaterial(IDirect3D *iface, IDirect3DMaterial **material,
3997         IUnknown *outer_unknown)
3998 {
3999     struct ddraw *ddraw = impl_from_IDirect3D(iface);
4000     struct d3d_material *object;
4001
4002     TRACE("iface %p, material %p, outer_unknown %p.\n", iface, material, outer_unknown);
4003
4004     object = d3d_material_create(ddraw);
4005     if (!object)
4006     {
4007         ERR("Failed to allocate material memory.\n");
4008         return DDERR_OUTOFMEMORY;
4009     }
4010
4011     TRACE("Created material %p.\n", object);
4012     *material = &object->IDirect3DMaterial_iface;
4013
4014     return D3D_OK;
4015 }
4016
4017 /*****************************************************************************
4018  * IDirect3D3::CreateViewport
4019  *
4020  * Creates an IDirect3DViewport interface. This interface is used
4021  * by Direct3D and earlier versions for Viewport management. In Direct3D7
4022  * it has been replaced by a viewport structure and
4023  * IDirect3DDevice7::*Viewport. Wine's IDirect3DViewport implementation
4024  * uses the IDirect3DDevice7 methods for its functionality
4025  *
4026  * Params:
4027  *  Viewport: Address to store the new interface pointer
4028  *  outer_unknown: Basically for aggregation, but ddraw doesn't support it.
4029  *                 Must be NULL
4030  *
4031  * Returns:
4032  *  D3D_OK on success
4033  *  DDERR_OUTOFMEMORY if memory allocation failed
4034  *  CLASS_E_NOAGGREGATION if outer_unknown != NULL
4035  *
4036  *****************************************************************************/
4037 static HRESULT WINAPI d3d3_CreateViewport(IDirect3D3 *iface, IDirect3DViewport3 **viewport,
4038         IUnknown *outer_unknown)
4039 {
4040     struct ddraw *ddraw = impl_from_IDirect3D3(iface);
4041     struct d3d_viewport *object;
4042
4043     TRACE("iface %p, viewport %p, outer_unknown %p.\n", iface, viewport, outer_unknown);
4044
4045     if (outer_unknown) return CLASS_E_NOAGGREGATION;
4046
4047     object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*object));
4048     if (!object)
4049     {
4050         ERR("Failed to allocate viewport memory.\n");
4051         return DDERR_OUTOFMEMORY;
4052     }
4053
4054     d3d_viewport_init(object, ddraw);
4055
4056     TRACE("Created viewport %p.\n", object);
4057     *viewport = &object->IDirect3DViewport3_iface;
4058
4059     return D3D_OK;
4060 }
4061
4062 static HRESULT WINAPI d3d2_CreateViewport(IDirect3D2 *iface, IDirect3DViewport2 **viewport, IUnknown *outer_unknown)
4063 {
4064     struct ddraw *ddraw = impl_from_IDirect3D2(iface);
4065
4066     TRACE("iface %p, viewport %p, outer_unknown %p.\n", iface, viewport, outer_unknown);
4067
4068     return d3d3_CreateViewport(&ddraw->IDirect3D3_iface, (IDirect3DViewport3 **)viewport,
4069             outer_unknown);
4070 }
4071
4072 static HRESULT WINAPI d3d1_CreateViewport(IDirect3D *iface, IDirect3DViewport **viewport, IUnknown *outer_unknown)
4073 {
4074     struct ddraw *ddraw = impl_from_IDirect3D(iface);
4075
4076     TRACE("iface %p, viewport %p, outer_unknown %p.\n", iface, viewport, outer_unknown);
4077
4078     return d3d3_CreateViewport(&ddraw->IDirect3D3_iface, (IDirect3DViewport3 **)viewport,
4079             outer_unknown);
4080 }
4081
4082 /*****************************************************************************
4083  * IDirect3D3::FindDevice
4084  *
4085  * This method finds a device with the requested properties and returns a
4086  * device description
4087  *
4088  * Verion 1, 2 and 3
4089  * Params:
4090  *  fds: Describes the requested device characteristics
4091  *  fdr: Returns the device description
4092  *
4093  * Returns:
4094  *  D3D_OK on success
4095  *  DDERR_INVALIDPARAMS if no device was found
4096  *
4097  *****************************************************************************/
4098 static HRESULT WINAPI d3d3_FindDevice(IDirect3D3 *iface, D3DFINDDEVICESEARCH *fds, D3DFINDDEVICERESULT *fdr)
4099 {
4100     struct ddraw *ddraw = impl_from_IDirect3D3(iface);
4101     D3DDEVICEDESC7 desc7;
4102     D3DDEVICEDESC desc1;
4103     HRESULT hr;
4104
4105     TRACE("iface %p, fds %p, fdr %p.\n", iface, fds, fdr);
4106
4107     if (!fds || !fdr) return DDERR_INVALIDPARAMS;
4108
4109     if (fds->dwSize != sizeof(D3DFINDDEVICESEARCH)
4110             || fdr->dwSize != sizeof(D3DFINDDEVICERESULT))
4111         return DDERR_INVALIDPARAMS;
4112
4113     if ((fds->dwFlags & D3DFDS_COLORMODEL)
4114             && fds->dcmColorModel != D3DCOLOR_RGB)
4115     {
4116         WARN("Trying to request a non-RGB D3D color model. Not supported.\n");
4117         return DDERR_INVALIDPARAMS; /* No real idea what to return here :-) */
4118     }
4119
4120     if (fds->dwFlags & D3DFDS_GUID)
4121     {
4122         TRACE("Trying to match guid %s.\n", debugstr_guid(&(fds->guid)));
4123         if (!IsEqualGUID(&IID_D3DDEVICE_WineD3D, &fds->guid)
4124                 && !IsEqualGUID(&IID_IDirect3DHALDevice, &fds->guid)
4125                 && !IsEqualGUID(&IID_IDirect3DRGBDevice, &fds->guid))
4126         {
4127             WARN("No match for this GUID.\n");
4128             return DDERR_NOTFOUND;
4129         }
4130     }
4131
4132     /* Get the caps */
4133     hr = IDirect3DImpl_GetCaps(ddraw->wined3d, &desc1, &desc7);
4134     if (hr != D3D_OK) return hr;
4135
4136     /* Now return our own GUID */
4137     fdr->guid = IID_D3DDEVICE_WineD3D;
4138     fdr->ddHwDesc = desc1;
4139     fdr->ddSwDesc = desc1;
4140
4141     TRACE("Returning Wine's wined3d device with (undumped) capabilities.\n");
4142
4143     return D3D_OK;
4144 }
4145
4146 static HRESULT WINAPI d3d2_FindDevice(IDirect3D2 *iface, D3DFINDDEVICESEARCH *fds, D3DFINDDEVICERESULT *fdr)
4147 {
4148     struct ddraw *ddraw = impl_from_IDirect3D2(iface);
4149
4150     TRACE("iface %p, fds %p, fdr %p.\n", iface, fds, fdr);
4151
4152     return d3d3_FindDevice(&ddraw->IDirect3D3_iface, fds, fdr);
4153 }
4154
4155 static HRESULT WINAPI d3d1_FindDevice(IDirect3D *iface, D3DFINDDEVICESEARCH *fds, D3DFINDDEVICERESULT *fdr)
4156 {
4157     struct ddraw *ddraw = impl_from_IDirect3D(iface);
4158
4159     TRACE("iface %p, fds %p, fdr %p.\n", iface, fds, fdr);
4160
4161     return d3d3_FindDevice(&ddraw->IDirect3D3_iface, fds, fdr);
4162 }
4163
4164 /*****************************************************************************
4165  * IDirect3D7::CreateDevice
4166  *
4167  * Creates an IDirect3DDevice7 interface.
4168  *
4169  * Version 2, 3 and 7. IDirect3DDevice 1 interfaces are interfaces to
4170  * DirectDraw surfaces and are created with
4171  * IDirectDrawSurface::QueryInterface. This method uses CreateDevice to
4172  * create the device object and QueryInterfaces for IDirect3DDevice
4173  *
4174  * Params:
4175  *  refiid: IID of the device to create
4176  *  Surface: Initial rendertarget
4177  *  Device: Address to return the interface pointer
4178  *
4179  * Returns:
4180  *  D3D_OK on success
4181  *  DDERR_OUTOFMEMORY if memory allocation failed
4182  *  DDERR_INVALIDPARAMS if a device exists already
4183  *
4184  *****************************************************************************/
4185 static HRESULT WINAPI d3d7_CreateDevice(IDirect3D7 *iface, REFCLSID riid,
4186         IDirectDrawSurface7 *surface, IDirect3DDevice7 **device)
4187 {
4188     struct ddraw_surface *target = unsafe_impl_from_IDirectDrawSurface7(surface);
4189     struct ddraw *ddraw = impl_from_IDirect3D7(iface);
4190     struct d3d_device *object;
4191     HRESULT hr;
4192
4193     TRACE("iface %p, riid %s, surface %p, device %p.\n", iface, debugstr_guid(riid), surface, device);
4194
4195     wined3d_mutex_lock();
4196     hr = d3d_device_create(ddraw, target, 7, &object, NULL);
4197     if (SUCCEEDED(hr))
4198         *device = &object->IDirect3DDevice7_iface;
4199     else
4200     {
4201         WARN("Failed to create device, hr %#x.\n", hr);
4202         *device = NULL;
4203     }
4204     wined3d_mutex_unlock();
4205
4206     return hr;
4207 }
4208
4209 static HRESULT WINAPI d3d3_CreateDevice(IDirect3D3 *iface, REFCLSID riid,
4210         IDirectDrawSurface4 *surface, IDirect3DDevice3 **device, IUnknown *outer_unknown)
4211 {
4212     struct ddraw_surface *surface_impl = unsafe_impl_from_IDirectDrawSurface4(surface);
4213     struct ddraw *ddraw = impl_from_IDirect3D3(iface);
4214     struct d3d_device *device_impl;
4215     HRESULT hr;
4216
4217     TRACE("iface %p, riid %s, surface %p, device %p, outer_unknown %p.\n",
4218             iface, debugstr_guid(riid), surface, device, outer_unknown);
4219
4220     if (outer_unknown)
4221         return CLASS_E_NOAGGREGATION;
4222
4223     wined3d_mutex_lock();
4224     hr = d3d_device_create(ddraw, surface_impl, 3, &device_impl, NULL);
4225     if (SUCCEEDED(hr))
4226         *device = &device_impl->IDirect3DDevice3_iface;
4227     else
4228     {
4229         WARN("Failed to create device, hr %#x.\n", hr);
4230         *device = NULL;
4231     }
4232     wined3d_mutex_unlock();
4233
4234     return hr;
4235 }
4236
4237 static HRESULT WINAPI d3d2_CreateDevice(IDirect3D2 *iface, REFCLSID riid,
4238         IDirectDrawSurface *surface, IDirect3DDevice2 **device)
4239 {
4240     struct ddraw_surface *surface_impl = unsafe_impl_from_IDirectDrawSurface(surface);
4241     struct ddraw *ddraw = impl_from_IDirect3D2(iface);
4242     struct d3d_device *device_impl;
4243     HRESULT hr;
4244
4245     TRACE("iface %p, riid %s, surface %p, device %p.\n",
4246             iface, debugstr_guid(riid), surface, device);
4247
4248     wined3d_mutex_lock();
4249     hr = d3d_device_create(ddraw, surface_impl, 2, &device_impl, NULL);
4250     if (SUCCEEDED(hr))
4251         *device = &device_impl->IDirect3DDevice2_iface;
4252     else
4253     {
4254         WARN("Failed to create device, hr %#x.\n", hr);
4255         *device = NULL;
4256     }
4257     wined3d_mutex_unlock();
4258
4259     return hr;
4260 }
4261
4262 /*****************************************************************************
4263  * IDirect3D7::CreateVertexBuffer
4264  *
4265  * Creates a new vertex buffer object and returns a IDirect3DVertexBuffer7
4266  * interface.
4267  *
4268  * Version 3 and 7
4269  *
4270  * Params:
4271  *  desc: Requested Vertex buffer properties
4272  *  vertex_buffer: Address to return the interface pointer at
4273  *  flags: Some flags, should be 0
4274  *
4275  * Returns
4276  *  D3D_OK on success
4277  *  DDERR_OUTOFMEMORY if memory allocation failed
4278  *  The return value of IWineD3DDevice::CreateVertexBuffer if this call fails
4279  *  DDERR_INVALIDPARAMS if desc or vertex_buffer are NULL
4280  *
4281  *****************************************************************************/
4282 static HRESULT WINAPI d3d7_CreateVertexBuffer(IDirect3D7 *iface, D3DVERTEXBUFFERDESC *desc,
4283         IDirect3DVertexBuffer7 **vertex_buffer, DWORD flags)
4284 {
4285     struct ddraw *ddraw = impl_from_IDirect3D7(iface);
4286     struct d3d_vertex_buffer *object;
4287     HRESULT hr;
4288
4289     TRACE("iface %p, desc %p, vertex_buffer %p, flags %#x.\n",
4290             iface, desc, vertex_buffer, flags);
4291
4292     if (!vertex_buffer || !desc) return DDERR_INVALIDPARAMS;
4293
4294     hr = d3d_vertex_buffer_create(&object, ddraw, desc);
4295     if (hr == D3D_OK)
4296     {
4297         TRACE("Created vertex buffer %p.\n", object);
4298         *vertex_buffer = &object->IDirect3DVertexBuffer7_iface;
4299     }
4300     else
4301         WARN("Failed to create vertex buffer, hr %#x.\n", hr);
4302
4303     return hr;
4304 }
4305
4306 static HRESULT WINAPI d3d3_CreateVertexBuffer(IDirect3D3 *iface, D3DVERTEXBUFFERDESC *desc,
4307         IDirect3DVertexBuffer **vertex_buffer, DWORD flags, IUnknown *outer_unknown)
4308 {
4309     struct ddraw *ddraw = impl_from_IDirect3D3(iface);
4310     struct d3d_vertex_buffer *object;
4311     HRESULT hr;
4312
4313     TRACE("iface %p, desc %p, vertex_buffer %p, flags %#x, outer_unknown %p.\n",
4314             iface, desc, vertex_buffer, flags, outer_unknown);
4315
4316     if (outer_unknown)
4317         return CLASS_E_NOAGGREGATION;
4318     if (!vertex_buffer || !desc)
4319         return DDERR_INVALIDPARAMS;
4320
4321     hr = d3d_vertex_buffer_create(&object, ddraw, desc);
4322     if (hr == D3D_OK)
4323     {
4324         TRACE("Created vertex buffer %p.\n", object);
4325         *vertex_buffer = &object->IDirect3DVertexBuffer_iface;
4326     }
4327     else
4328         WARN("Failed to create vertex buffer, hr %#x.\n", hr);
4329
4330     return hr;
4331 }
4332
4333 /*****************************************************************************
4334  * IDirect3D7::EnumZBufferFormats
4335  *
4336  * Enumerates all supported Z buffer pixel formats
4337  *
4338  * Version 3 and 7
4339  *
4340  * Params:
4341  *  device_iid:
4342  *  callback: callback to call for each pixel format
4343  *  context: Pointer to pass back to the callback
4344  *
4345  * Returns:
4346  *  D3D_OK on success
4347  *  DDERR_INVALIDPARAMS if callback is NULL
4348  *  For details, see IWineD3DDevice::EnumZBufferFormats
4349  *
4350  *****************************************************************************/
4351 static HRESULT WINAPI d3d7_EnumZBufferFormats(IDirect3D7 *iface, REFCLSID device_iid,
4352         LPD3DENUMPIXELFORMATSCALLBACK callback, void *context)
4353 {
4354     struct ddraw *ddraw = impl_from_IDirect3D7(iface);
4355     struct wined3d_display_mode mode;
4356     enum wined3d_device_type type;
4357     unsigned int i;
4358     HRESULT hr;
4359
4360     /* Order matters. Specifically, BattleZone II (full version) expects the
4361      * 16-bit depth formats to be listed before the 24 and 32 ones. */
4362     static const enum wined3d_format_id formats[] =
4363     {
4364         WINED3DFMT_S1_UINT_D15_UNORM,
4365         WINED3DFMT_D16_UNORM,
4366         WINED3DFMT_X8D24_UNORM,
4367         WINED3DFMT_S4X4_UINT_D24_UNORM,
4368         WINED3DFMT_D24_UNORM_S8_UINT,
4369         WINED3DFMT_D32_UNORM,
4370     };
4371
4372     TRACE("iface %p, device_iid %s, callback %p, context %p.\n",
4373             iface, debugstr_guid(device_iid), callback, context);
4374
4375     if (!callback) return DDERR_INVALIDPARAMS;
4376
4377     if (IsEqualGUID(device_iid, &IID_IDirect3DHALDevice)
4378             || IsEqualGUID(device_iid, &IID_IDirect3DTnLHalDevice)
4379             || IsEqualGUID(device_iid, &IID_D3DDEVICE_WineD3D))
4380     {
4381         TRACE("Asked for HAL device.\n");
4382         type = WINED3D_DEVICE_TYPE_HAL;
4383     }
4384     else if (IsEqualGUID(device_iid, &IID_IDirect3DRGBDevice)
4385             || IsEqualGUID(device_iid, &IID_IDirect3DMMXDevice))
4386     {
4387         TRACE("Asked for SW device.\n");
4388         type = WINED3D_DEVICE_TYPE_SW;
4389     }
4390     else if (IsEqualGUID(device_iid, &IID_IDirect3DRefDevice))
4391     {
4392         TRACE("Asked for REF device.\n");
4393         type = WINED3D_DEVICE_TYPE_REF;
4394     }
4395     else if (IsEqualGUID(device_iid, &IID_IDirect3DNullDevice))
4396     {
4397         TRACE("Asked for NULLREF device.\n");
4398         type = WINED3D_DEVICE_TYPE_NULLREF;
4399     }
4400     else
4401     {
4402         FIXME("Unexpected device GUID %s.\n", debugstr_guid(device_iid));
4403         type = WINED3D_DEVICE_TYPE_HAL;
4404     }
4405
4406     wined3d_mutex_lock();
4407     /* We need an adapter format from somewhere to please wined3d and WGL.
4408      * Use the current display mode. So far all cards offer the same depth
4409      * stencil format for all modes, but if some do not and applications do
4410      * not like that we'll have to find some workaround, like iterating over
4411      * all imaginable formats and collecting all the depth stencil formats we
4412      * can get. */
4413     if (FAILED(hr = wined3d_get_adapter_display_mode(ddraw->wined3d, WINED3DADAPTER_DEFAULT, &mode, NULL)))
4414     {
4415         ERR("Failed to get display mode, hr %#x.\n", hr);
4416         wined3d_mutex_unlock();
4417         return hr;
4418     }
4419
4420     for (i = 0; i < (sizeof(formats) / sizeof(*formats)); ++i)
4421     {
4422         if (SUCCEEDED(wined3d_check_device_format(ddraw->wined3d, WINED3DADAPTER_DEFAULT, type, mode.format_id,
4423                 WINED3DUSAGE_DEPTHSTENCIL, WINED3D_RTYPE_SURFACE, formats[i])))
4424         {
4425             DDPIXELFORMAT pformat;
4426
4427             memset(&pformat, 0, sizeof(pformat));
4428             pformat.dwSize = sizeof(pformat);
4429             PixelFormat_WineD3DtoDD(&pformat, formats[i]);
4430
4431             TRACE("Enumerating wined3d format %#x.\n", formats[i]);
4432             hr = callback(&pformat, context);
4433             if (hr != DDENUMRET_OK)
4434             {
4435                 TRACE("Format enumeration cancelled by application.\n");
4436                 wined3d_mutex_unlock();
4437                 return D3D_OK;
4438             }
4439         }
4440     }
4441
4442     /* Historically some windows drivers used dwZBufferBitDepth=24 for WINED3DFMT_X8D24_UNORM,
4443      * while others used dwZBufferBitDepth=32. In either case the pitch matches a 32 bits per
4444      * pixel format, so we use dwZBufferBitDepth=32. Some games expect 24. Windows Vista and
4445      * newer enumerate both versions, so we do the same(bug 22434) */
4446     if (SUCCEEDED(wined3d_check_device_format(ddraw->wined3d, WINED3DADAPTER_DEFAULT, type, mode.format_id,
4447             WINED3DUSAGE_DEPTHSTENCIL, WINED3D_RTYPE_SURFACE, WINED3DFMT_X8D24_UNORM)))
4448     {
4449         DDPIXELFORMAT x8d24 =
4450         {
4451             sizeof(x8d24), DDPF_ZBUFFER, 0,
4452             {24}, {0x00000000}, {0x00ffffff}, {0x00000000}
4453         };
4454         TRACE("Enumerating WINED3DFMT_X8D24_UNORM, dwZBufferBitDepth=24 version\n");
4455         callback(&x8d24, context);
4456     }
4457
4458     TRACE("End of enumeration.\n");
4459
4460     wined3d_mutex_unlock();
4461
4462     return D3D_OK;
4463 }
4464
4465 static HRESULT WINAPI d3d3_EnumZBufferFormats(IDirect3D3 *iface, REFCLSID device_iid,
4466         LPD3DENUMPIXELFORMATSCALLBACK callback, void *context)
4467 {
4468     struct ddraw *ddraw = impl_from_IDirect3D3(iface);
4469
4470     TRACE("iface %p, device_iid %s, callback %p, context %p.\n",
4471             iface, debugstr_guid(device_iid), callback, context);
4472
4473     return d3d7_EnumZBufferFormats(&ddraw->IDirect3D7_iface, device_iid, callback, context);
4474 }
4475
4476 /*****************************************************************************
4477  * IDirect3D7::EvictManagedTextures
4478  *
4479  * Removes all managed textures (=surfaces with DDSCAPS2_TEXTUREMANAGE or
4480  * DDSCAPS2_D3DTEXTUREMANAGE caps) to be removed from video memory.
4481  *
4482  * Version 3 and 7
4483  *
4484  * Returns:
4485  *  D3D_OK, because it's a stub
4486  *
4487  *****************************************************************************/
4488 static HRESULT WINAPI d3d7_EvictManagedTextures(IDirect3D7 *iface)
4489 {
4490     struct ddraw *ddraw = impl_from_IDirect3D7(iface);
4491
4492     TRACE("iface %p!\n", iface);
4493
4494     wined3d_mutex_lock();
4495     if (ddraw->d3d_initialized)
4496         wined3d_device_evict_managed_resources(ddraw->wined3d_device);
4497     wined3d_mutex_unlock();
4498
4499     return D3D_OK;
4500 }
4501
4502 static HRESULT WINAPI d3d3_EvictManagedTextures(IDirect3D3 *iface)
4503 {
4504     struct ddraw *ddraw = impl_from_IDirect3D3(iface);
4505
4506     TRACE("iface %p.\n", iface);
4507
4508     return d3d7_EvictManagedTextures(&ddraw->IDirect3D7_iface);
4509 }
4510
4511 /*****************************************************************************
4512  * IDirect3DImpl_GetCaps
4513  *
4514  * This function retrieves the device caps from wined3d
4515  * and converts it into a D3D7 and D3D - D3D3 structure
4516  * This is a helper function called from various places in ddraw
4517  *
4518  * Params:
4519  *  wined3d: The interface to get the caps from
4520  *  desc1: Old D3D <3 structure to fill (needed)
4521  *  desc7: D3D7 device desc structure to fill (needed)
4522  *
4523  * Returns
4524  *  D3D_OK on success, or the return value of IWineD3D::GetCaps
4525  *
4526  *****************************************************************************/
4527 HRESULT IDirect3DImpl_GetCaps(const struct wined3d *wined3d, D3DDEVICEDESC *desc1, D3DDEVICEDESC7 *desc7)
4528 {
4529     WINED3DCAPS wined3d_caps;
4530     HRESULT hr;
4531
4532     TRACE("wined3d %p, desc1 %p, desc7 %p.\n", wined3d, desc1, desc7);
4533
4534     memset(&wined3d_caps, 0, sizeof(wined3d_caps));
4535
4536     wined3d_mutex_lock();
4537     hr = wined3d_get_device_caps(wined3d, 0, WINED3D_DEVICE_TYPE_HAL, &wined3d_caps);
4538     wined3d_mutex_unlock();
4539     if (FAILED(hr))
4540     {
4541         WARN("Failed to get device caps, hr %#x.\n", hr);
4542         return hr;
4543     }
4544
4545     /* Copy the results into the d3d7 and d3d3 structures */
4546     desc7->dwDevCaps = wined3d_caps.DevCaps;
4547     desc7->dpcLineCaps.dwMiscCaps = wined3d_caps.PrimitiveMiscCaps;
4548     desc7->dpcLineCaps.dwRasterCaps = wined3d_caps.RasterCaps;
4549     desc7->dpcLineCaps.dwZCmpCaps = wined3d_caps.ZCmpCaps;
4550     desc7->dpcLineCaps.dwSrcBlendCaps = wined3d_caps.SrcBlendCaps;
4551     desc7->dpcLineCaps.dwDestBlendCaps = wined3d_caps.DestBlendCaps;
4552     desc7->dpcLineCaps.dwAlphaCmpCaps = wined3d_caps.AlphaCmpCaps;
4553     desc7->dpcLineCaps.dwShadeCaps = wined3d_caps.ShadeCaps;
4554     desc7->dpcLineCaps.dwTextureCaps = wined3d_caps.TextureCaps;
4555     desc7->dpcLineCaps.dwTextureFilterCaps = wined3d_caps.TextureFilterCaps;
4556     desc7->dpcLineCaps.dwTextureAddressCaps = wined3d_caps.TextureAddressCaps;
4557
4558     desc7->dwMaxTextureWidth = wined3d_caps.MaxTextureWidth;
4559     desc7->dwMaxTextureHeight = wined3d_caps.MaxTextureHeight;
4560
4561     desc7->dwMaxTextureRepeat = wined3d_caps.MaxTextureRepeat;
4562     desc7->dwMaxTextureAspectRatio = wined3d_caps.MaxTextureAspectRatio;
4563     desc7->dwMaxAnisotropy = wined3d_caps.MaxAnisotropy;
4564     desc7->dvMaxVertexW = wined3d_caps.MaxVertexW;
4565
4566     desc7->dvGuardBandLeft = wined3d_caps.GuardBandLeft;
4567     desc7->dvGuardBandTop = wined3d_caps.GuardBandTop;
4568     desc7->dvGuardBandRight = wined3d_caps.GuardBandRight;
4569     desc7->dvGuardBandBottom = wined3d_caps.GuardBandBottom;
4570
4571     desc7->dvExtentsAdjust = wined3d_caps.ExtentsAdjust;
4572     desc7->dwStencilCaps = wined3d_caps.StencilCaps;
4573
4574     desc7->dwFVFCaps = wined3d_caps.FVFCaps;
4575     desc7->dwTextureOpCaps = wined3d_caps.TextureOpCaps;
4576
4577     desc7->dwVertexProcessingCaps = wined3d_caps.VertexProcessingCaps;
4578     desc7->dwMaxActiveLights = wined3d_caps.MaxActiveLights;
4579
4580     /* Remove all non-d3d7 caps */
4581     desc7->dwDevCaps &= (
4582         D3DDEVCAPS_FLOATTLVERTEX         | D3DDEVCAPS_SORTINCREASINGZ          | D3DDEVCAPS_SORTDECREASINGZ          |
4583         D3DDEVCAPS_SORTEXACT             | D3DDEVCAPS_EXECUTESYSTEMMEMORY      | D3DDEVCAPS_EXECUTEVIDEOMEMORY       |
4584         D3DDEVCAPS_TLVERTEXSYSTEMMEMORY  | D3DDEVCAPS_TLVERTEXVIDEOMEMORY      | D3DDEVCAPS_TEXTURESYSTEMMEMORY      |
4585         D3DDEVCAPS_TEXTUREVIDEOMEMORY    | D3DDEVCAPS_DRAWPRIMTLVERTEX         | D3DDEVCAPS_CANRENDERAFTERFLIP       |
4586         D3DDEVCAPS_TEXTURENONLOCALVIDMEM | D3DDEVCAPS_DRAWPRIMITIVES2          | D3DDEVCAPS_SEPARATETEXTUREMEMORIES  |
4587         D3DDEVCAPS_DRAWPRIMITIVES2EX     | D3DDEVCAPS_HWTRANSFORMANDLIGHT      | D3DDEVCAPS_CANBLTSYSTONONLOCAL      |
4588         D3DDEVCAPS_HWRASTERIZATION);
4589
4590     desc7->dwStencilCaps &= (
4591         D3DSTENCILCAPS_KEEP              | D3DSTENCILCAPS_ZERO                 | D3DSTENCILCAPS_REPLACE              |
4592         D3DSTENCILCAPS_INCRSAT           | D3DSTENCILCAPS_DECRSAT              | D3DSTENCILCAPS_INVERT               |
4593         D3DSTENCILCAPS_INCR              | D3DSTENCILCAPS_DECR);
4594
4595     /* FVF caps ?*/
4596
4597     desc7->dwTextureOpCaps &= (
4598         D3DTEXOPCAPS_DISABLE             | D3DTEXOPCAPS_SELECTARG1             | D3DTEXOPCAPS_SELECTARG2             |
4599         D3DTEXOPCAPS_MODULATE            | D3DTEXOPCAPS_MODULATE2X             | D3DTEXOPCAPS_MODULATE4X             |
4600         D3DTEXOPCAPS_ADD                 | D3DTEXOPCAPS_ADDSIGNED              | D3DTEXOPCAPS_ADDSIGNED2X            |
4601         D3DTEXOPCAPS_SUBTRACT            | D3DTEXOPCAPS_ADDSMOOTH              | D3DTEXOPCAPS_BLENDTEXTUREALPHA      |
4602         D3DTEXOPCAPS_BLENDFACTORALPHA    | D3DTEXOPCAPS_BLENDTEXTUREALPHAPM    | D3DTEXOPCAPS_BLENDCURRENTALPHA      |
4603         D3DTEXOPCAPS_PREMODULATE         | D3DTEXOPCAPS_MODULATEALPHA_ADDCOLOR | D3DTEXOPCAPS_MODULATECOLOR_ADDALPHA |
4604         D3DTEXOPCAPS_MODULATEINVALPHA_ADDCOLOR | D3DTEXOPCAPS_MODULATEINVCOLOR_ADDALPHA | D3DTEXOPCAPS_BUMPENVMAP    |
4605         D3DTEXOPCAPS_BUMPENVMAPLUMINANCE | D3DTEXOPCAPS_DOTPRODUCT3);
4606
4607     desc7->dwVertexProcessingCaps &= (
4608         D3DVTXPCAPS_TEXGEN               | D3DVTXPCAPS_MATERIALSOURCE7         | D3DVTXPCAPS_VERTEXFOG               |
4609         D3DVTXPCAPS_DIRECTIONALLIGHTS    | D3DVTXPCAPS_POSITIONALLIGHTS        | D3DVTXPCAPS_LOCALVIEWER);
4610
4611     desc7->dpcLineCaps.dwMiscCaps &= (
4612         D3DPMISCCAPS_MASKPLANES          | D3DPMISCCAPS_MASKZ                  | D3DPMISCCAPS_LINEPATTERNREP         |
4613         D3DPMISCCAPS_CONFORMANT          | D3DPMISCCAPS_CULLNONE               | D3DPMISCCAPS_CULLCW                 |
4614         D3DPMISCCAPS_CULLCCW);
4615
4616     desc7->dpcLineCaps.dwRasterCaps &= (
4617         D3DPRASTERCAPS_DITHER            | D3DPRASTERCAPS_ROP2                 | D3DPRASTERCAPS_XOR                  |
4618         D3DPRASTERCAPS_PAT               | D3DPRASTERCAPS_ZTEST                | D3DPRASTERCAPS_SUBPIXEL             |
4619         D3DPRASTERCAPS_SUBPIXELX         | D3DPRASTERCAPS_FOGVERTEX            | D3DPRASTERCAPS_FOGTABLE             |
4620         D3DPRASTERCAPS_STIPPLE           | D3DPRASTERCAPS_ANTIALIASSORTDEPENDENT | D3DPRASTERCAPS_ANTIALIASSORTINDEPENDENT |
4621         D3DPRASTERCAPS_ANTIALIASEDGES    | D3DPRASTERCAPS_MIPMAPLODBIAS        | D3DPRASTERCAPS_ZBIAS                |
4622         D3DPRASTERCAPS_ZBUFFERLESSHSR    | D3DPRASTERCAPS_FOGRANGE             | D3DPRASTERCAPS_ANISOTROPY           |
4623         D3DPRASTERCAPS_WBUFFER           | D3DPRASTERCAPS_TRANSLUCENTSORTINDEPENDENT | D3DPRASTERCAPS_WFOG           |
4624         D3DPRASTERCAPS_ZFOG);
4625
4626     desc7->dpcLineCaps.dwZCmpCaps &= (
4627         D3DPCMPCAPS_NEVER                | D3DPCMPCAPS_LESS                    | D3DPCMPCAPS_EQUAL                   |
4628         D3DPCMPCAPS_LESSEQUAL            | D3DPCMPCAPS_GREATER                 | D3DPCMPCAPS_NOTEQUAL                |
4629         D3DPCMPCAPS_GREATEREQUAL         | D3DPCMPCAPS_ALWAYS);
4630
4631     desc7->dpcLineCaps.dwSrcBlendCaps &= (
4632         D3DPBLENDCAPS_ZERO               | D3DPBLENDCAPS_ONE                   | D3DPBLENDCAPS_SRCCOLOR              |
4633         D3DPBLENDCAPS_INVSRCCOLOR        | D3DPBLENDCAPS_SRCALPHA              | D3DPBLENDCAPS_INVSRCALPHA           |
4634         D3DPBLENDCAPS_DESTALPHA          | D3DPBLENDCAPS_INVDESTALPHA          | D3DPBLENDCAPS_DESTCOLOR             |
4635         D3DPBLENDCAPS_INVDESTCOLOR       | D3DPBLENDCAPS_SRCALPHASAT           | D3DPBLENDCAPS_BOTHSRCALPHA          |
4636         D3DPBLENDCAPS_BOTHINVSRCALPHA);
4637
4638     desc7->dpcLineCaps.dwDestBlendCaps &= (
4639         D3DPBLENDCAPS_ZERO               | D3DPBLENDCAPS_ONE                   | D3DPBLENDCAPS_SRCCOLOR              |
4640         D3DPBLENDCAPS_INVSRCCOLOR        | D3DPBLENDCAPS_SRCALPHA              | D3DPBLENDCAPS_INVSRCALPHA           |
4641         D3DPBLENDCAPS_DESTALPHA          | D3DPBLENDCAPS_INVDESTALPHA          | D3DPBLENDCAPS_DESTCOLOR             |
4642         D3DPBLENDCAPS_INVDESTCOLOR       | D3DPBLENDCAPS_SRCALPHASAT           | D3DPBLENDCAPS_BOTHSRCALPHA          |
4643         D3DPBLENDCAPS_BOTHINVSRCALPHA);
4644
4645     desc7->dpcLineCaps.dwAlphaCmpCaps &= (
4646         D3DPCMPCAPS_NEVER                | D3DPCMPCAPS_LESS                    | D3DPCMPCAPS_EQUAL                   |
4647         D3DPCMPCAPS_LESSEQUAL            | D3DPCMPCAPS_GREATER                 | D3DPCMPCAPS_NOTEQUAL                |
4648         D3DPCMPCAPS_GREATEREQUAL         | D3DPCMPCAPS_ALWAYS);
4649
4650     desc7->dpcLineCaps.dwShadeCaps &= (
4651         D3DPSHADECAPS_COLORFLATMONO      | D3DPSHADECAPS_COLORFLATRGB          | D3DPSHADECAPS_COLORGOURAUDMONO      |
4652         D3DPSHADECAPS_COLORGOURAUDRGB    | D3DPSHADECAPS_COLORPHONGMONO        | D3DPSHADECAPS_COLORPHONGRGB         |
4653         D3DPSHADECAPS_SPECULARFLATMONO   | D3DPSHADECAPS_SPECULARFLATRGB       | D3DPSHADECAPS_SPECULARGOURAUDMONO   |
4654         D3DPSHADECAPS_SPECULARGOURAUDRGB | D3DPSHADECAPS_SPECULARPHONGMONO     | D3DPSHADECAPS_SPECULARPHONGRGB      |
4655         D3DPSHADECAPS_ALPHAFLATBLEND     | D3DPSHADECAPS_ALPHAFLATSTIPPLED     | D3DPSHADECAPS_ALPHAGOURAUDBLEND     |
4656         D3DPSHADECAPS_ALPHAGOURAUDSTIPPLED | D3DPSHADECAPS_ALPHAPHONGBLEND     | D3DPSHADECAPS_ALPHAPHONGSTIPPLED    |
4657         D3DPSHADECAPS_FOGFLAT            | D3DPSHADECAPS_FOGGOURAUD            | D3DPSHADECAPS_FOGPHONG);
4658
4659     desc7->dpcLineCaps.dwTextureCaps &= (
4660         D3DPTEXTURECAPS_PERSPECTIVE      | D3DPTEXTURECAPS_POW2                | D3DPTEXTURECAPS_ALPHA               |
4661         D3DPTEXTURECAPS_TRANSPARENCY     | D3DPTEXTURECAPS_BORDER              | D3DPTEXTURECAPS_SQUAREONLY          |
4662         D3DPTEXTURECAPS_TEXREPEATNOTSCALEDBYSIZE | D3DPTEXTURECAPS_ALPHAPALETTE| D3DPTEXTURECAPS_NONPOW2CONDITIONAL  |
4663         D3DPTEXTURECAPS_PROJECTED        | D3DPTEXTURECAPS_CUBEMAP             | D3DPTEXTURECAPS_COLORKEYBLEND);
4664
4665     desc7->dpcLineCaps.dwTextureFilterCaps &= (
4666         D3DPTFILTERCAPS_NEAREST          | D3DPTFILTERCAPS_LINEAR              | D3DPTFILTERCAPS_MIPNEAREST          |
4667         D3DPTFILTERCAPS_MIPLINEAR        | D3DPTFILTERCAPS_LINEARMIPNEAREST    | D3DPTFILTERCAPS_LINEARMIPLINEAR     |
4668         D3DPTFILTERCAPS_MINFPOINT        | D3DPTFILTERCAPS_MINFLINEAR          | D3DPTFILTERCAPS_MINFANISOTROPIC     |
4669         D3DPTFILTERCAPS_MIPFPOINT        | D3DPTFILTERCAPS_MIPFLINEAR          | D3DPTFILTERCAPS_MAGFPOINT           |
4670         D3DPTFILTERCAPS_MAGFLINEAR       | D3DPTFILTERCAPS_MAGFANISOTROPIC     | D3DPTFILTERCAPS_MAGFAFLATCUBIC      |
4671         D3DPTFILTERCAPS_MAGFGAUSSIANCUBIC);
4672
4673     desc7->dpcLineCaps.dwTextureAddressCaps &= (
4674         D3DPTADDRESSCAPS_WRAP            | D3DPTADDRESSCAPS_MIRROR             | D3DPTADDRESSCAPS_CLAMP              |
4675         D3DPTADDRESSCAPS_BORDER          | D3DPTADDRESSCAPS_INDEPENDENTUV);
4676
4677     if (!(desc7->dpcLineCaps.dwTextureCaps & D3DPTEXTURECAPS_POW2))
4678     {
4679         /* DirectX7 always has the np2 flag set, no matter what the card
4680          * supports. Some old games (Rollcage) check the caps incorrectly.
4681          * If wined3d supports nonpow2 textures it also has np2 conditional
4682          * support. */
4683         desc7->dpcLineCaps.dwTextureCaps |= D3DPTEXTURECAPS_POW2 | D3DPTEXTURECAPS_NONPOW2CONDITIONAL;
4684     }
4685
4686     /* Fill the missing members, and do some fixup */
4687     desc7->dpcLineCaps.dwSize = sizeof(desc7->dpcLineCaps);
4688     desc7->dpcLineCaps.dwTextureBlendCaps = D3DPTBLENDCAPS_ADD | D3DPTBLENDCAPS_MODULATEMASK |
4689                                             D3DPTBLENDCAPS_COPY | D3DPTBLENDCAPS_DECAL |
4690                                             D3DPTBLENDCAPS_DECALALPHA | D3DPTBLENDCAPS_DECALMASK |
4691                                             D3DPTBLENDCAPS_MODULATE | D3DPTBLENDCAPS_MODULATEALPHA;
4692     desc7->dpcLineCaps.dwStippleWidth = 32;
4693     desc7->dpcLineCaps.dwStippleHeight = 32;
4694     /* Use the same for the TriCaps */
4695     desc7->dpcTriCaps = desc7->dpcLineCaps;
4696
4697     desc7->dwDeviceRenderBitDepth = DDBD_16 | DDBD_24 | DDBD_32;
4698     desc7->dwDeviceZBufferBitDepth = DDBD_16 | DDBD_24;
4699     desc7->dwMinTextureWidth = 1;
4700     desc7->dwMinTextureHeight = 1;
4701
4702     /* Convert DWORDs safely to WORDs */
4703     if (wined3d_caps.MaxTextureBlendStages > 0xffff) desc7->wMaxTextureBlendStages = 0xffff;
4704     else desc7->wMaxTextureBlendStages = (WORD)wined3d_caps.MaxTextureBlendStages;
4705     if (wined3d_caps.MaxSimultaneousTextures > 0xffff) desc7->wMaxSimultaneousTextures = 0xffff;
4706     else desc7->wMaxSimultaneousTextures = (WORD)wined3d_caps.MaxSimultaneousTextures;
4707
4708     if (wined3d_caps.MaxUserClipPlanes > 0xffff) desc7->wMaxUserClipPlanes = 0xffff;
4709     else desc7->wMaxUserClipPlanes = (WORD)wined3d_caps.MaxUserClipPlanes;
4710     if (wined3d_caps.MaxVertexBlendMatrices > 0xffff) desc7->wMaxVertexBlendMatrices = 0xffff;
4711     else desc7->wMaxVertexBlendMatrices = (WORD)wined3d_caps.MaxVertexBlendMatrices;
4712
4713     desc7->deviceGUID = IID_IDirect3DTnLHalDevice;
4714
4715     desc7->dwReserved1 = 0;
4716     desc7->dwReserved2 = 0;
4717     desc7->dwReserved3 = 0;
4718     desc7->dwReserved4 = 0;
4719
4720     /* Fill the old structure */
4721     memset(desc1, 0, sizeof(*desc1));
4722     desc1->dwSize = sizeof(D3DDEVICEDESC);
4723     desc1->dwFlags = D3DDD_COLORMODEL
4724             | D3DDD_DEVCAPS
4725             | D3DDD_TRANSFORMCAPS
4726             | D3DDD_BCLIPPING
4727             | D3DDD_LIGHTINGCAPS
4728             | D3DDD_LINECAPS
4729             | D3DDD_TRICAPS
4730             | D3DDD_DEVICERENDERBITDEPTH
4731             | D3DDD_DEVICEZBUFFERBITDEPTH
4732             | D3DDD_MAXBUFFERSIZE
4733             | D3DDD_MAXVERTEXCOUNT;
4734
4735     desc1->dcmColorModel = D3DCOLOR_RGB;
4736     desc1->dwDevCaps = desc7->dwDevCaps;
4737     desc1->dtcTransformCaps.dwSize = sizeof(D3DTRANSFORMCAPS);
4738     desc1->dtcTransformCaps.dwCaps = D3DTRANSFORMCAPS_CLIP;
4739     desc1->bClipping = TRUE;
4740     desc1->dlcLightingCaps.dwSize = sizeof(D3DLIGHTINGCAPS);
4741     desc1->dlcLightingCaps.dwCaps = D3DLIGHTCAPS_DIRECTIONAL
4742             | D3DLIGHTCAPS_PARALLELPOINT
4743             | D3DLIGHTCAPS_POINT
4744             | D3DLIGHTCAPS_SPOT;
4745
4746     desc1->dlcLightingCaps.dwLightingModel = D3DLIGHTINGMODEL_RGB;
4747     desc1->dlcLightingCaps.dwNumLights = desc7->dwMaxActiveLights;
4748
4749     desc1->dpcLineCaps.dwSize = sizeof(D3DPRIMCAPS);
4750     desc1->dpcLineCaps.dwMiscCaps = desc7->dpcLineCaps.dwMiscCaps;
4751     desc1->dpcLineCaps.dwRasterCaps = desc7->dpcLineCaps.dwRasterCaps;
4752     desc1->dpcLineCaps.dwZCmpCaps = desc7->dpcLineCaps.dwZCmpCaps;
4753     desc1->dpcLineCaps.dwSrcBlendCaps = desc7->dpcLineCaps.dwSrcBlendCaps;
4754     desc1->dpcLineCaps.dwDestBlendCaps = desc7->dpcLineCaps.dwDestBlendCaps;
4755     desc1->dpcLineCaps.dwShadeCaps = desc7->dpcLineCaps.dwShadeCaps;
4756     desc1->dpcLineCaps.dwTextureCaps = desc7->dpcLineCaps.dwTextureCaps;
4757     desc1->dpcLineCaps.dwTextureFilterCaps = desc7->dpcLineCaps.dwTextureFilterCaps;
4758     desc1->dpcLineCaps.dwTextureBlendCaps = desc7->dpcLineCaps.dwTextureBlendCaps;
4759     desc1->dpcLineCaps.dwTextureAddressCaps = desc7->dpcLineCaps.dwTextureAddressCaps;
4760     desc1->dpcLineCaps.dwStippleWidth = desc7->dpcLineCaps.dwStippleWidth;
4761     desc1->dpcLineCaps.dwAlphaCmpCaps = desc7->dpcLineCaps.dwAlphaCmpCaps;
4762
4763     desc1->dpcTriCaps.dwSize = sizeof(D3DPRIMCAPS);
4764     desc1->dpcTriCaps.dwMiscCaps = desc7->dpcTriCaps.dwMiscCaps;
4765     desc1->dpcTriCaps.dwRasterCaps = desc7->dpcTriCaps.dwRasterCaps;
4766     desc1->dpcTriCaps.dwZCmpCaps = desc7->dpcTriCaps.dwZCmpCaps;
4767     desc1->dpcTriCaps.dwSrcBlendCaps = desc7->dpcTriCaps.dwSrcBlendCaps;
4768     desc1->dpcTriCaps.dwDestBlendCaps = desc7->dpcTriCaps.dwDestBlendCaps;
4769     desc1->dpcTriCaps.dwShadeCaps = desc7->dpcTriCaps.dwShadeCaps;
4770     desc1->dpcTriCaps.dwTextureCaps = desc7->dpcTriCaps.dwTextureCaps;
4771     desc1->dpcTriCaps.dwTextureFilterCaps = desc7->dpcTriCaps.dwTextureFilterCaps;
4772     desc1->dpcTriCaps.dwTextureBlendCaps = desc7->dpcTriCaps.dwTextureBlendCaps;
4773     desc1->dpcTriCaps.dwTextureAddressCaps = desc7->dpcTriCaps.dwTextureAddressCaps;
4774     desc1->dpcTriCaps.dwStippleWidth = desc7->dpcTriCaps.dwStippleWidth;
4775     desc1->dpcTriCaps.dwAlphaCmpCaps = desc7->dpcTriCaps.dwAlphaCmpCaps;
4776
4777     desc1->dwDeviceRenderBitDepth = desc7->dwDeviceRenderBitDepth;
4778     desc1->dwDeviceZBufferBitDepth = desc7->dwDeviceZBufferBitDepth;
4779     desc1->dwMaxBufferSize = 0;
4780     desc1->dwMaxVertexCount = 65536;
4781     desc1->dwMinTextureWidth  = desc7->dwMinTextureWidth;
4782     desc1->dwMinTextureHeight = desc7->dwMinTextureHeight;
4783     desc1->dwMaxTextureWidth  = desc7->dwMaxTextureWidth;
4784     desc1->dwMaxTextureHeight = desc7->dwMaxTextureHeight;
4785     desc1->dwMinStippleWidth  = 1;
4786     desc1->dwMinStippleHeight = 1;
4787     desc1->dwMaxStippleWidth  = 32;
4788     desc1->dwMaxStippleHeight = 32;
4789     desc1->dwMaxTextureRepeat = desc7->dwMaxTextureRepeat;
4790     desc1->dwMaxTextureAspectRatio = desc7->dwMaxTextureAspectRatio;
4791     desc1->dwMaxAnisotropy = desc7->dwMaxAnisotropy;
4792     desc1->dvGuardBandLeft = desc7->dvGuardBandLeft;
4793     desc1->dvGuardBandRight = desc7->dvGuardBandRight;
4794     desc1->dvGuardBandTop = desc7->dvGuardBandTop;
4795     desc1->dvGuardBandBottom = desc7->dvGuardBandBottom;
4796     desc1->dvExtentsAdjust = desc7->dvExtentsAdjust;
4797     desc1->dwStencilCaps = desc7->dwStencilCaps;
4798     desc1->dwFVFCaps = desc7->dwFVFCaps;
4799     desc1->dwTextureOpCaps = desc7->dwTextureOpCaps;
4800     desc1->wMaxTextureBlendStages = desc7->wMaxTextureBlendStages;
4801     desc1->wMaxSimultaneousTextures = desc7->wMaxSimultaneousTextures;
4802
4803     return DD_OK;
4804 }
4805
4806 /*****************************************************************************
4807  * IDirectDraw7 VTable
4808  *****************************************************************************/
4809 static const struct IDirectDraw7Vtbl ddraw7_vtbl =
4810 {
4811     /* IUnknown */
4812     ddraw7_QueryInterface,
4813     ddraw7_AddRef,
4814     ddraw7_Release,
4815     /* IDirectDraw */
4816     ddraw7_Compact,
4817     ddraw7_CreateClipper,
4818     ddraw7_CreatePalette,
4819     ddraw7_CreateSurface,
4820     ddraw7_DuplicateSurface,
4821     ddraw7_EnumDisplayModes,
4822     ddraw7_EnumSurfaces,
4823     ddraw7_FlipToGDISurface,
4824     ddraw7_GetCaps,
4825     ddraw7_GetDisplayMode,
4826     ddraw7_GetFourCCCodes,
4827     ddraw7_GetGDISurface,
4828     ddraw7_GetMonitorFrequency,
4829     ddraw7_GetScanLine,
4830     ddraw7_GetVerticalBlankStatus,
4831     ddraw7_Initialize,
4832     ddraw7_RestoreDisplayMode,
4833     ddraw7_SetCooperativeLevel,
4834     ddraw7_SetDisplayMode,
4835     ddraw7_WaitForVerticalBlank,
4836     /* IDirectDraw2 */
4837     ddraw7_GetAvailableVidMem,
4838     /* IDirectDraw3 */
4839     ddraw7_GetSurfaceFromDC,
4840     /* IDirectDraw4 */
4841     ddraw7_RestoreAllSurfaces,
4842     ddraw7_TestCooperativeLevel,
4843     ddraw7_GetDeviceIdentifier,
4844     /* IDirectDraw7 */
4845     ddraw7_StartModeTest,
4846     ddraw7_EvaluateMode
4847 };
4848
4849 static const struct IDirectDraw4Vtbl ddraw4_vtbl =
4850 {
4851     /* IUnknown */
4852     ddraw4_QueryInterface,
4853     ddraw4_AddRef,
4854     ddraw4_Release,
4855     /* IDirectDraw */
4856     ddraw4_Compact,
4857     ddraw4_CreateClipper,
4858     ddraw4_CreatePalette,
4859     ddraw4_CreateSurface,
4860     ddraw4_DuplicateSurface,
4861     ddraw4_EnumDisplayModes,
4862     ddraw4_EnumSurfaces,
4863     ddraw4_FlipToGDISurface,
4864     ddraw4_GetCaps,
4865     ddraw4_GetDisplayMode,
4866     ddraw4_GetFourCCCodes,
4867     ddraw4_GetGDISurface,
4868     ddraw4_GetMonitorFrequency,
4869     ddraw4_GetScanLine,
4870     ddraw4_GetVerticalBlankStatus,
4871     ddraw4_Initialize,
4872     ddraw4_RestoreDisplayMode,
4873     ddraw4_SetCooperativeLevel,
4874     ddraw4_SetDisplayMode,
4875     ddraw4_WaitForVerticalBlank,
4876     /* IDirectDraw2 */
4877     ddraw4_GetAvailableVidMem,
4878     /* IDirectDraw3 */
4879     ddraw4_GetSurfaceFromDC,
4880     /* IDirectDraw4 */
4881     ddraw4_RestoreAllSurfaces,
4882     ddraw4_TestCooperativeLevel,
4883     ddraw4_GetDeviceIdentifier,
4884 };
4885
4886 static const struct IDirectDraw2Vtbl ddraw2_vtbl =
4887 {
4888     /* IUnknown */
4889     ddraw2_QueryInterface,
4890     ddraw2_AddRef,
4891     ddraw2_Release,
4892     /* IDirectDraw */
4893     ddraw2_Compact,
4894     ddraw2_CreateClipper,
4895     ddraw2_CreatePalette,
4896     ddraw2_CreateSurface,
4897     ddraw2_DuplicateSurface,
4898     ddraw2_EnumDisplayModes,
4899     ddraw2_EnumSurfaces,
4900     ddraw2_FlipToGDISurface,
4901     ddraw2_GetCaps,
4902     ddraw2_GetDisplayMode,
4903     ddraw2_GetFourCCCodes,
4904     ddraw2_GetGDISurface,
4905     ddraw2_GetMonitorFrequency,
4906     ddraw2_GetScanLine,
4907     ddraw2_GetVerticalBlankStatus,
4908     ddraw2_Initialize,
4909     ddraw2_RestoreDisplayMode,
4910     ddraw2_SetCooperativeLevel,
4911     ddraw2_SetDisplayMode,
4912     ddraw2_WaitForVerticalBlank,
4913     /* IDirectDraw2 */
4914     ddraw2_GetAvailableVidMem,
4915 };
4916
4917 static const struct IDirectDrawVtbl ddraw1_vtbl =
4918 {
4919     /* IUnknown */
4920     ddraw1_QueryInterface,
4921     ddraw1_AddRef,
4922     ddraw1_Release,
4923     /* IDirectDraw */
4924     ddraw1_Compact,
4925     ddraw1_CreateClipper,
4926     ddraw1_CreatePalette,
4927     ddraw1_CreateSurface,
4928     ddraw1_DuplicateSurface,
4929     ddraw1_EnumDisplayModes,
4930     ddraw1_EnumSurfaces,
4931     ddraw1_FlipToGDISurface,
4932     ddraw1_GetCaps,
4933     ddraw1_GetDisplayMode,
4934     ddraw1_GetFourCCCodes,
4935     ddraw1_GetGDISurface,
4936     ddraw1_GetMonitorFrequency,
4937     ddraw1_GetScanLine,
4938     ddraw1_GetVerticalBlankStatus,
4939     ddraw1_Initialize,
4940     ddraw1_RestoreDisplayMode,
4941     ddraw1_SetCooperativeLevel,
4942     ddraw1_SetDisplayMode,
4943     ddraw1_WaitForVerticalBlank,
4944 };
4945
4946 static const struct IDirect3D7Vtbl d3d7_vtbl =
4947 {
4948     /* IUnknown methods */
4949     d3d7_QueryInterface,
4950     d3d7_AddRef,
4951     d3d7_Release,
4952     /* IDirect3D7 methods */
4953     d3d7_EnumDevices,
4954     d3d7_CreateDevice,
4955     d3d7_CreateVertexBuffer,
4956     d3d7_EnumZBufferFormats,
4957     d3d7_EvictManagedTextures
4958 };
4959
4960 static const struct IDirect3D3Vtbl d3d3_vtbl =
4961 {
4962     /* IUnknown methods */
4963     d3d3_QueryInterface,
4964     d3d3_AddRef,
4965     d3d3_Release,
4966     /* IDirect3D3 methods */
4967     d3d3_EnumDevices,
4968     d3d3_CreateLight,
4969     d3d3_CreateMaterial,
4970     d3d3_CreateViewport,
4971     d3d3_FindDevice,
4972     d3d3_CreateDevice,
4973     d3d3_CreateVertexBuffer,
4974     d3d3_EnumZBufferFormats,
4975     d3d3_EvictManagedTextures
4976 };
4977
4978 static const struct IDirect3D2Vtbl d3d2_vtbl =
4979 {
4980     /* IUnknown methods */
4981     d3d2_QueryInterface,
4982     d3d2_AddRef,
4983     d3d2_Release,
4984     /* IDirect3D2 methods */
4985     d3d2_EnumDevices,
4986     d3d2_CreateLight,
4987     d3d2_CreateMaterial,
4988     d3d2_CreateViewport,
4989     d3d2_FindDevice,
4990     d3d2_CreateDevice
4991 };
4992
4993 static const struct IDirect3DVtbl d3d1_vtbl =
4994 {
4995     /* IUnknown methods */
4996     d3d1_QueryInterface,
4997     d3d1_AddRef,
4998     d3d1_Release,
4999     /* IDirect3D methods */
5000     d3d1_Initialize,
5001     d3d1_EnumDevices,
5002     d3d1_CreateLight,
5003     d3d1_CreateMaterial,
5004     d3d1_CreateViewport,
5005     d3d1_FindDevice
5006 };
5007
5008 /*****************************************************************************
5009  * ddraw_find_decl
5010  *
5011  * Finds the WineD3D vertex declaration for a specific fvf, and creates one
5012  * if none was found.
5013  *
5014  * This function is in ddraw.c and the DDraw object space because D3D7
5015  * vertex buffers are created using the IDirect3D interface to the ddraw
5016  * object, so they can be valid across D3D devices(theoretically. The ddraw
5017  * object also owns the wined3d device
5018  *
5019  * Parameters:
5020  *  This: Device
5021  *  fvf: Fvf to find the decl for
5022  *
5023  * Returns:
5024  *  NULL in case of an error, the vertex declaration for the FVF otherwise.
5025  *
5026  *****************************************************************************/
5027 struct wined3d_vertex_declaration *ddraw_find_decl(struct ddraw *This, DWORD fvf)
5028 {
5029     struct wined3d_vertex_declaration *pDecl = NULL;
5030     HRESULT hr;
5031     int p, low, high; /* deliberately signed */
5032     struct FvfToDecl *convertedDecls = This->decls;
5033
5034     TRACE("Searching for declaration for fvf %08x... ", fvf);
5035
5036     low = 0;
5037     high = This->numConvertedDecls - 1;
5038     while(low <= high) {
5039         p = (low + high) >> 1;
5040         TRACE("%d ", p);
5041         if(convertedDecls[p].fvf == fvf) {
5042             TRACE("found %p\n", convertedDecls[p].decl);
5043             return convertedDecls[p].decl;
5044         } else if(convertedDecls[p].fvf < fvf) {
5045             low = p + 1;
5046         } else {
5047             high = p - 1;
5048         }
5049     }
5050     TRACE("not found. Creating and inserting at position %d.\n", low);
5051
5052     hr = wined3d_vertex_declaration_create_from_fvf(This->wined3d_device,
5053             fvf, This, &ddraw_null_wined3d_parent_ops, &pDecl);
5054     if (hr != S_OK) return NULL;
5055
5056     if(This->declArraySize == This->numConvertedDecls) {
5057         int grow = max(This->declArraySize / 2, 8);
5058         convertedDecls = HeapReAlloc(GetProcessHeap(), 0, convertedDecls,
5059                                      sizeof(convertedDecls[0]) * (This->numConvertedDecls + grow));
5060         if (!convertedDecls)
5061         {
5062             wined3d_vertex_declaration_decref(pDecl);
5063             return NULL;
5064         }
5065         This->decls = convertedDecls;
5066         This->declArraySize += grow;
5067     }
5068
5069     memmove(convertedDecls + low + 1, convertedDecls + low, sizeof(convertedDecls[0]) * (This->numConvertedDecls - low));
5070     convertedDecls[low].decl = pDecl;
5071     convertedDecls[low].fvf = fvf;
5072     This->numConvertedDecls++;
5073
5074     TRACE("Returning %p. %d decls in array\n", pDecl, This->numConvertedDecls);
5075     return pDecl;
5076 }
5077
5078 static inline struct ddraw *ddraw_from_device_parent(struct wined3d_device_parent *device_parent)
5079 {
5080     return CONTAINING_RECORD(device_parent, struct ddraw, device_parent);
5081 }
5082
5083 static void CDECL device_parent_wined3d_device_created(struct wined3d_device_parent *device_parent,
5084         struct wined3d_device *device)
5085 {
5086     TRACE("device_parent %p, device %p.\n", device_parent, device);
5087 }
5088
5089 /* This is run from device_process_message() in wined3d, we can't take the
5090  * wined3d mutex. */
5091 static void CDECL device_parent_mode_changed(struct wined3d_device_parent *device_parent)
5092 {
5093     struct ddraw *ddraw = ddraw_from_device_parent(device_parent);
5094     MONITORINFO monitor_info;
5095     HMONITOR monitor;
5096     RECT *r;
5097
5098     TRACE("device_parent %p.\n", device_parent);
5099
5100     if (!(ddraw->cooperative_level & DDSCL_EXCLUSIVE) || !ddraw->swapchain_window)
5101     {
5102         TRACE("Nothing to resize.\n");
5103         return;
5104     }
5105
5106     monitor = MonitorFromWindow(ddraw->swapchain_window, MONITOR_DEFAULTTOPRIMARY);
5107     monitor_info.cbSize = sizeof(monitor_info);
5108     if (!GetMonitorInfoW(monitor, &monitor_info))
5109     {
5110         ERR("Failed to get monitor info.\n");
5111         return;
5112     }
5113
5114     r = &monitor_info.rcMonitor;
5115     TRACE("Resizing window %p to %s.\n", ddraw->swapchain_window, wine_dbgstr_rect(r));
5116
5117     if (!SetWindowPos(ddraw->swapchain_window, HWND_TOP, r->left, r->top,
5118                       r->right - r->left, r->bottom - r->top, SWP_SHOWWINDOW | SWP_NOACTIVATE))
5119         ERR("Failed to resize window.\n");
5120 }
5121
5122 static HRESULT CDECL device_parent_create_texture_surface(struct wined3d_device_parent *device_parent,
5123         void *container_parent, UINT width, UINT height, enum wined3d_format_id format, DWORD usage,
5124         enum wined3d_pool pool, UINT sub_resource_idx, struct wined3d_surface **surface)
5125 {
5126     struct ddraw *ddraw = ddraw_from_device_parent(device_parent);
5127     struct ddraw_surface *tex_root = container_parent;
5128     DDSURFACEDESC2 desc = tex_root->surface_desc;
5129     struct ddraw_surface *ddraw_surface;
5130     HRESULT hr;
5131
5132     TRACE("device_parent %p, container_parent %p, width %u, height %u, format %#x, usage %#x,\n"
5133             "\tpool %#x, sub_resource_idx %u, surface %p.\n",
5134             device_parent, container_parent, width, height, format, usage, pool, sub_resource_idx, surface);
5135
5136     /* The ddraw root surface is created before the wined3d texture. */
5137     if (!sub_resource_idx)
5138     {
5139         ddraw_surface = tex_root;
5140         goto done;
5141     }
5142
5143     desc.dwWidth = width;
5144     desc.dwHeight = height;
5145
5146     /* FIXME: Validate that format, usage, pool, etc. really make sense. */
5147     if (FAILED(hr = ddraw_create_surface(ddraw, &desc, &ddraw_surface, tex_root->version)))
5148         return hr;
5149
5150 done:
5151     *surface = ddraw_surface->wined3d_surface;
5152     wined3d_surface_incref(*surface);
5153
5154     return DD_OK;
5155 }
5156
5157 static void STDMETHODCALLTYPE ddraw_frontbuffer_destroyed(void *parent)
5158 {
5159     struct ddraw *ddraw = parent;
5160     ddraw->wined3d_frontbuffer = NULL;
5161 }
5162
5163 static const struct wined3d_parent_ops ddraw_frontbuffer_parent_ops =
5164 {
5165     ddraw_frontbuffer_destroyed,
5166 };
5167
5168 static HRESULT CDECL device_parent_create_swapchain_surface(struct wined3d_device_parent *device_parent,
5169         void *container_parent, UINT width, UINT height, enum wined3d_format_id format_id, DWORD usage,
5170         enum wined3d_multisample_type multisample_type, DWORD multisample_quality, struct wined3d_surface **surface)
5171 {
5172     struct ddraw *ddraw = ddraw_from_device_parent(device_parent);
5173     HRESULT hr;
5174
5175     TRACE("device_parent %p, container_parent %p, width %u, height %u, format_id %#x, usage %#x,\n"
5176             "\tmultisample_type %#x, multisample_quality %u, surface %p.\n",
5177             device_parent, container_parent, width, height, format_id, usage,
5178             multisample_type, multisample_quality, surface);
5179
5180     if (ddraw->wined3d_frontbuffer)
5181     {
5182         ERR("Frontbuffer already created.\n");
5183         return E_FAIL;
5184     }
5185
5186     if (SUCCEEDED(hr = wined3d_surface_create(ddraw->wined3d_device, width, height, format_id, usage,
5187             WINED3D_POOL_DEFAULT, multisample_type, multisample_quality, WINED3D_SURFACE_MAPPABLE,
5188             ddraw, &ddraw_frontbuffer_parent_ops, surface)))
5189         ddraw->wined3d_frontbuffer = *surface;
5190
5191     return hr;
5192 }
5193
5194 static HRESULT CDECL device_parent_create_volume(struct wined3d_device_parent *device_parent,
5195         void *container_parent, UINT width, UINT height, UINT depth, enum wined3d_format_id format,
5196         enum wined3d_pool pool, DWORD usage, struct wined3d_volume **volume)
5197 {
5198     TRACE("device_parent %p, container_parent %p, width %u, height %u, depth %u, "
5199             "format %#x, pool %#x, usage %#x, volume %p.\n",
5200             device_parent, container_parent, width, height, depth,
5201             format, pool, usage, volume);
5202
5203     ERR("Not implemented!\n");
5204
5205     return E_NOTIMPL;
5206 }
5207
5208 static HRESULT CDECL device_parent_create_swapchain(struct wined3d_device_parent *device_parent,
5209         struct wined3d_swapchain_desc *desc, struct wined3d_swapchain **swapchain)
5210 {
5211     struct ddraw *ddraw = ddraw_from_device_parent(device_parent);
5212     HRESULT hr;
5213
5214     TRACE("device_parent %p, desc %p, swapchain %p.\n", device_parent, desc, swapchain);
5215
5216     if (ddraw->wined3d_swapchain)
5217     {
5218         ERR("Swapchain already created.\n");
5219         return E_FAIL;
5220     }
5221
5222     if (FAILED(hr = wined3d_swapchain_create(ddraw->wined3d_device, desc, NULL,
5223             &ddraw_null_wined3d_parent_ops, swapchain)))
5224         WARN("Failed to create swapchain, hr %#x.\n", hr);
5225
5226     return hr;
5227 }
5228
5229 static const struct wined3d_device_parent_ops ddraw_wined3d_device_parent_ops =
5230 {
5231     device_parent_wined3d_device_created,
5232     device_parent_mode_changed,
5233     device_parent_create_swapchain_surface,
5234     device_parent_create_texture_surface,
5235     device_parent_create_volume,
5236     device_parent_create_swapchain,
5237 };
5238
5239 HRESULT ddraw_init(struct ddraw *ddraw, enum wined3d_device_type device_type)
5240 {
5241     DWORD flags;
5242     HRESULT hr;
5243
5244     ddraw->IDirectDraw7_iface.lpVtbl = &ddraw7_vtbl;
5245     ddraw->IDirectDraw_iface.lpVtbl = &ddraw1_vtbl;
5246     ddraw->IDirectDraw2_iface.lpVtbl = &ddraw2_vtbl;
5247     ddraw->IDirectDraw4_iface.lpVtbl = &ddraw4_vtbl;
5248     ddraw->IDirect3D_iface.lpVtbl = &d3d1_vtbl;
5249     ddraw->IDirect3D2_iface.lpVtbl = &d3d2_vtbl;
5250     ddraw->IDirect3D3_iface.lpVtbl = &d3d3_vtbl;
5251     ddraw->IDirect3D7_iface.lpVtbl = &d3d7_vtbl;
5252     ddraw->device_parent.ops = &ddraw_wined3d_device_parent_ops;
5253     ddraw->numIfaces = 1;
5254     ddraw->ref7 = 1;
5255
5256     flags = WINED3D_LEGACY_DEPTH_BIAS;
5257     if (DefaultSurfaceType != DDRAW_SURFACE_TYPE_OPENGL)
5258         flags |= WINED3D_NO3D;
5259
5260     if (!(ddraw->wined3d = wined3d_create(7, flags)))
5261     {
5262         if ((flags & WINED3D_NO3D) || !(ddraw->wined3d = wined3d_create(7, flags | WINED3D_NO3D)))
5263         {
5264             WARN("Failed to create a wined3d object.\n");
5265             return E_FAIL;
5266         }
5267
5268         WARN("Created a wined3d object without 3D support.\n");
5269         DefaultSurfaceType = DDRAW_SURFACE_TYPE_GDI;
5270     }
5271
5272     hr = wined3d_device_create(ddraw->wined3d, WINED3DADAPTER_DEFAULT, device_type,
5273             NULL, 0, 8, &ddraw->device_parent, &ddraw->wined3d_device);
5274     if (FAILED(hr))
5275     {
5276         WARN("Failed to create a wined3d device, hr %#x.\n", hr);
5277         wined3d_decref(ddraw->wined3d);
5278         return hr;
5279     }
5280
5281     list_init(&ddraw->surface_list);
5282
5283     return DD_OK;
5284 }