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