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