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