ReactOS 0.4.15-dev-8614-gbc76250
ddraw.c
Go to the documentation of this file.
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
32
33static const struct ddraw *exclusive_ddraw;
35
36/* Device identifier. Don't relay it to WineD3D */
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
48static struct enum_device_entry
49{
50 char interface_name[100];
51 char device_name[100];
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,
78 },
79};
80
82
84{
86};
87
88static inline struct ddraw *impl_from_IDirectDraw(IDirectDraw *iface)
89{
90 return CONTAINING_RECORD(iface, struct ddraw, IDirectDraw_iface);
91}
92
93static inline struct ddraw *impl_from_IDirectDraw2(IDirectDraw2 *iface)
94{
95 return CONTAINING_RECORD(iface, struct ddraw, IDirectDraw2_iface);
96}
97
98static inline struct ddraw *impl_from_IDirectDraw4(IDirectDraw4 *iface)
99{
100 return CONTAINING_RECORD(iface, struct ddraw, IDirectDraw4_iface);
101}
102
103static inline struct ddraw *impl_from_IDirectDraw7(IDirectDraw7 *iface)
104{
105 return CONTAINING_RECORD(iface, struct ddraw, IDirectDraw7_iface);
106}
107
108static inline struct ddraw *impl_from_IDirect3D(IDirect3D *iface)
109{
110 return CONTAINING_RECORD(iface, struct ddraw, IDirect3D_iface);
111}
112
113static inline struct ddraw *impl_from_IDirect3D2(IDirect3D2 *iface)
114{
115 return CONTAINING_RECORD(iface, struct ddraw, IDirect3D2_iface);
116}
117
118static inline struct ddraw *impl_from_IDirect3D3(IDirect3D3 *iface)
119{
120 return CONTAINING_RECORD(iface, struct ddraw, IDirect3D3_iface);
121}
122
123static inline struct ddraw *impl_from_IDirect3D7(IDirect3D7 *iface)
124{
125 return CONTAINING_RECORD(iface, struct ddraw, IDirect3D7_iface);
126}
127
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)
148 {
150 TRACE("Returning IDirectDraw7 interface %p.\n", *out);
151 }
152 else if (IsEqualGUID(&IID_IDirectDraw4, riid))
153 {
155 TRACE("Returning IDirectDraw4 interface %p.\n", *out);
156 }
157 else if (IsEqualGUID(&IID_IDirectDraw2, riid))
158 {
160 TRACE("Returning IDirectDraw2 interface %p.\n", *out);
161 }
162 else if (IsEqualGUID(&IID_IDirectDraw, riid))
163 {
165 TRACE("Returning IDirectDraw interface %p.\n", *out);
166 }
167 else if (IsEqualGUID(&IID_IDirect3D7, riid))
168 {
169 ddraw->d3dversion = 7;
171 TRACE("Returning Direct3D7 interface %p.\n", *out);
172 }
173 else if (IsEqualGUID(&IID_IDirect3D3, riid))
174 {
175 ddraw->d3dversion = 3;
177 TRACE("Returning Direct3D3 interface %p.\n", *out);
178 }
179 else if (IsEqualGUID(&IID_IDirect3D2, riid))
180 {
181 ddraw->d3dversion = 2;
183 TRACE("Returning Direct3D2 interface %p.\n", *out);
184 }
185 else if (IsEqualGUID(&IID_IDirect3D, riid))
186 {
187 ddraw->d3dversion = 1;
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
203static 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
210}
211
212static 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
219}
220
221static 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
228}
229
230static 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
237}
238
239static 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
246}
247
248static 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
255}
256
257static 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
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 *****************************************************************************/
285{
286 struct ddraw *This = impl_from_IDirectDraw7(iface);
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
296static ULONG WINAPI ddraw4_AddRef(IDirectDraw4 *iface)
297{
298 struct ddraw *This = impl_from_IDirectDraw4(iface);
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
308static ULONG WINAPI ddraw2_AddRef(IDirectDraw2 *iface)
309{
310 struct ddraw *This = impl_from_IDirectDraw2(iface);
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
320static ULONG WINAPI ddraw1_AddRef(IDirectDraw *iface)
321{
322 struct ddraw *This = impl_from_IDirectDraw(iface);
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
332static 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
341static 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
350static 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
359static 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
369{
370 TRACE("Destroying the swapchain.\n");
371
374
375 if (!(ddraw->flags & DDRAW_NO3D))
376 {
377 UINT i;
378
379 for (i = 0; i < ddraw->numConvertedDecls; ++i)
380 {
382 }
385
387 {
388 ERR("Failed to uninit 3D.\n");
389 }
390 else
391 {
392 /* Free the d3d window if one was created. */
394 {
395 TRACE("Destroying the hidden render window %p.\n", ddraw->d3d_window);
397 ddraw->d3d_window = 0;
398 }
399 }
400
401 ddraw->flags &= ~DDRAW_D3D_INITIALIZED;
402 }
403 else
404 {
406 }
407
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 *****************************************************************************/
423static 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
437 list_remove(&This->ddraw_list_entry);
439
440 if (This->wined3d_swapchain)
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 */
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 *****************************************************************************/
460{
461 struct ddraw *This = impl_from_IDirectDraw7(iface);
463
464 TRACE("%p decreasing refcount to %u.\n", This, ref);
465
466 if (!ref && !InterlockedDecrement(&This->numIfaces))
468
469 return ref;
470}
471
472static ULONG WINAPI ddraw4_Release(IDirectDraw4 *iface)
473{
474 struct ddraw *This = impl_from_IDirectDraw4(iface);
476
477 TRACE("%p decreasing refcount to %u.\n", This, ref);
478
479 if (!ref && !InterlockedDecrement(&This->numIfaces))
481
482 return ref;
483}
484
485static ULONG WINAPI ddraw2_Release(IDirectDraw2 *iface)
486{
487 struct ddraw *This = impl_from_IDirectDraw2(iface);
489
490 TRACE("%p decreasing refcount to %u.\n", This, ref);
491
492 if (!ref && !InterlockedDecrement(&This->numIfaces))
494
495 return ref;
496}
497
498static ULONG WINAPI ddraw1_Release(IDirectDraw *iface)
499{
500 struct ddraw *This = impl_from_IDirectDraw(iface);
502
503 TRACE("%p decreasing refcount to %u.\n", This, ref);
504
505 if (!ref && !InterlockedDecrement(&This->numIfaces))
507
508 return ref;
509}
510
511static 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
520static 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
529static 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
538static 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
552{
553 /* FIXME: This looks wrong, exclusive mode should imply a destination
554 * window. */
556 {
557 TRACE("Setting DDSCL_SETFOCUSWINDOW with an already set window, returning DDERR_HWNDALREADYSET.\n");
559 }
560
562
563 return DD_OK;
564}
565
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",
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 }
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. */
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;
612 return E_OUTOFMEMORY;
613 }
614
615 TRACE("Successfully initialized 3D.\n");
616
617 return DD_OK;
618}
619
621{
622 struct wined3d_swapchain_desc swapchain_desc;
625
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;
637 swapchain_desc.swap_effect = WINED3D_SWAP_EFFECT_COPY;
638 swapchain_desc.device_window = window;
639 swapchain_desc.windowed = windowed;
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
654 {
655 ERR("Failed to get swapchain.\n");
656 return DDERR_INVALIDPARAMS;
657 }
658
661
662 if (ddraw->primary && ddraw->primary->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 *****************************************************************************/
679{
680 struct ddraw *ddraw = impl_from_IDirectDraw7(iface);
681 HRESULT hr;
682
683 TRACE("iface %p.\n", iface);
684
686
688 {
690 return DD_OK;
691 }
692
694 {
697 }
698
700 ddraw->flags &= ~DDRAW_RESTORE_MODE;
701
703
705
706 return hr;
707}
708
709static HRESULT WINAPI ddraw4_RestoreDisplayMode(IDirectDraw4 *iface)
710{
711 struct ddraw *ddraw = impl_from_IDirectDraw4(iface);
712
713 TRACE("iface %p.\n", iface);
714
716}
717
718static HRESULT WINAPI ddraw2_RestoreDisplayMode(IDirectDraw2 *iface)
719{
720 struct ddraw *ddraw = impl_from_IDirectDraw2(iface);
721
722 TRACE("iface %p.\n", iface);
723
725}
726
727static HRESULT WINAPI ddraw1_RestoreDisplayMode(IDirectDraw *iface)
728{
729 struct ddraw *ddraw = impl_from_IDirectDraw(iface);
730
731 TRACE("iface %p.\n", iface);
732
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 *****************************************************************************/
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);
789
791
793 {
794 WARN("Recursive call, returning DD_OK.\n");
795 hr = DD_OK;
796 goto done;
797 }
799
800 /* Tests suggest that we need one of them: */
801 if(!(cooplevel & (DDSCL_SETFOCUSWINDOW |
804 {
805 TRACE("Incorrect cooplevel flags, returning DDERR_INVALIDPARAMS\n");
807 goto done;
808 }
809
810 if ((cooplevel & DDSCL_CREATEDEVICEWINDOW) && !(cooplevel & DDSCL_EXCLUSIVE))
811 {
812 WARN("DDSCL_CREATEDEVICEWINDOW requires DDSCL_EXCLUSIVE.\n");
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
830 {
831 WARN("Called with incompatible flags, returning DDERR_INVALIDPARAMS.\n");
833 goto done;
834 }
835
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");
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");
857 goto done;
858 }
859
860 device_window = CreateWindowExA(0, DDRAW_WINDOW_CLASS_NAME, "DirectDrawDeviceWnd",
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. */
876 ddraw->devicewindow = device_window;
877
878 if (cooplevel & DDSCL_SETFOCUSWINDOW)
879 {
880 if (!window)
881 {
883 goto done;
884 }
885
887 goto done;
888 }
889
890 window = device_window;
891 }
892 }
893 else
894 {
899 }
900
902 {
905
906 if (cooplevel & DDSCL_FULLSCREEN)
907 {
908 struct wined3d_display_mode display_mode;
909
912 display_mode.width, display_mode.height);
913 }
914 }
915
916 if ((cooplevel & DDSCL_EXCLUSIVE) && exclusive_window != window)
917 {
920 }
921
924
926 {
927 if (!(ddraw->flags & DDRAW_NO3D))
928 {
929 restore_state = TRUE;
930
932 {
933 ERR("Failed to create stateblock, hr %#x.\n", hr);
934 goto done;
935 }
936
937 wined3d_stateblock_capture(stateblock);
939 /* Rendering to ddraw->wined3d_frontbuffer. */
941 rtv = NULL;
942 else if (rtv)
944
947 }
948
950 }
951
953 ERR("Failed to create swapchain, hr %#x.\n", hr);
954
955 if (restore_state)
956 {
957 if (dsv)
958 {
961 }
962
963 if (rtv)
964 {
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 {
977 if (FAILED(hr))
978 ERR("RestoreDisplayMode failed\n");
979 }
980
982 && (window != ddraw->dest_window || !(cooplevel & DDSCL_EXCLUSIVE)))
984
985 if ((cooplevel & DDSCL_EXCLUSIVE)
987 {
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)
1006 else if (exclusive_ddraw == ddraw)
1008
1009 /* Store the cooperative_level */
1010 ddraw->cooperative_level = cooplevel;
1012
1013 TRACE("SetCooperativeLevel returning DD_OK\n");
1014 hr = DD_OK;
1015done:
1016 ddraw->flags &= ~DDRAW_SCL_RECURSIVE;
1018
1019 return hr;
1020}
1021
1023{
1024 struct ddraw *ddraw = impl_from_IDirectDraw7(iface);
1025
1026 TRACE("iface %p, window %p, flags %#x.\n", iface, window, flags);
1027
1029}
1030
1032{
1033 struct ddraw *ddraw = impl_from_IDirectDraw4(iface);
1034
1035 TRACE("iface %p, window %p, flags %#x.\n", iface, window, flags);
1036
1038}
1039
1041{
1042 struct ddraw *ddraw = impl_from_IDirectDraw2(iface);
1043
1044 TRACE("iface %p, window %p, flags %#x.\n", iface, window, flags);
1045
1047}
1048
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
1057 if (SUCCEEDED(hr))
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 *****************************************************************************/
1085 DWORD bpp, DWORD refresh_rate, DWORD flags)
1086{
1087 struct ddraw *ddraw = impl_from_IDirectDraw7(iface);
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",
1100 }
1101
1103
1105 {
1107 return DDERR_NOEXCLUSIVEMODE;
1108 }
1109
1110 if (!width || !height)
1111 {
1112 /* It looks like Need for Speed Porsche Unleashed expects DD_OK here. */
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. */
1136 {
1137 if (ddraw->primary)
1138 {
1139 DDSURFACEDESC2 *surface_desc = &ddraw->primary->surface_desc;
1140
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 }
1148 }
1149
1151
1153
1154 switch (hr)
1155 {
1157 default: return hr;
1158 }
1159}
1160
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
1170}
1171
1172static 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
1181}
1182
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
1190}
1191
1193{
1194 memset(caps1, 0, sizeof(*caps1));
1195 caps1->dwSize = sizeof(*caps1);
1196 caps1->dwFlags = D3DDD_COLORMODEL
1207 caps1->dcmColorModel = D3DCOLOR_RGB;
1208 caps1->dwDevCaps = caps7->dwDevCaps;
1209 caps1->dtcTransformCaps.dwSize = sizeof(caps1->dtcTransformCaps);
1211 caps1->bClipping = TRUE;
1212 caps1->dlcLightingCaps.dwSize = sizeof(caps1->dlcLightingCaps);
1219 caps1->dpcLineCaps = caps7->dpcLineCaps;
1220 caps1->dpcTriCaps = caps7->dpcTriCaps;
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;
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;
1246}
1247
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
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;
1277
1278 caps->dwMaxTextureWidth = wined3d_caps.MaxTextureWidth;
1279 caps->dwMaxTextureHeight = wined3d_caps.MaxTextureHeight;
1280
1281 caps->dwMaxTextureRepeat = wined3d_caps.MaxTextureRepeat;
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 &= (
1309
1310 caps->dwStencilCaps &= (
1314
1315 /* FVF caps ?*/
1316
1317 caps->dwTextureOpCaps &= (
1326
1327 caps->dwVertexProcessingCaps &= (
1330
1331 caps->dpcLineCaps.dwMiscCaps &= (
1335
1336 caps->dpcLineCaps.dwRasterCaps &= (
1345
1346 caps->dpcLineCaps.dwZCmpCaps &= (
1350
1351 caps->dpcLineCaps.dwSrcBlendCaps &= (
1357
1358 caps->dpcLineCaps.dwDestBlendCaps &= (
1364
1365 caps->dpcLineCaps.dwAlphaCmpCaps &= (
1369
1370 caps->dpcLineCaps.dwShadeCaps &= (
1378
1379 caps->dpcLineCaps.dwTextureCaps &= (
1384
1392
1396
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. */
1404 }
1405
1406 /* Fill the missing members, and do some fixup */
1407 caps->dpcLineCaps.dwSize = sizeof(caps->dpcLineCaps);
1416 caps->dpcLineCaps.dwStippleWidth = 32;
1417 caps->dpcLineCaps.dwStippleHeight = 32;
1418 /* Use the same for the TriCaps */
1419 caps->dpcTriCaps = caps->dpcLineCaps;
1420
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);
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
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 *****************************************************************************/
1479static 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
1502 if (FAILED(hr))
1503 {
1504 WARN("Failed to get device caps, %#x.\n", hr);
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");
1514 return hr;
1515 }
1516
1517 hr = IDirectDraw7_GetFourCCCodes(iface, &caps.dwNumFourCCCodes, NULL);
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
1571static 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
1580static 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
1589static 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 *****************************************************************************/
1608{
1609 TRACE("iface %p.\n", iface);
1610
1611 return DD_OK;
1612}
1613
1614static HRESULT WINAPI ddraw4_Compact(IDirectDraw4 *iface)
1615{
1616 struct ddraw *ddraw = impl_from_IDirectDraw4(iface);
1617
1618 TRACE("iface %p.\n", iface);
1619
1621}
1622
1623static HRESULT WINAPI ddraw2_Compact(IDirectDraw2 *iface)
1624{
1625 struct ddraw *ddraw = impl_from_IDirectDraw2(iface);
1626
1627 TRACE("iface %p.\n", iface);
1628
1630}
1631
1632static HRESULT WINAPI ddraw1_Compact(IDirectDraw *iface)
1633{
1634 struct ddraw *ddraw = impl_from_IDirectDraw(iface);
1635
1636 TRACE("iface %p.\n", iface);
1637
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 *****************************************************************************/
1656{
1657 struct ddraw *ddraw = impl_from_IDirectDraw7(iface);
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
1668
1670 {
1671 ERR("Failed to get display mode, hr %#x.\n", hr);
1673 return hr;
1674 }
1675
1676 memset(DDSD, 0, DDSD->dwSize);
1677 DDSD->dwSize = sizeof(*DDSD);
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);
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");
1691 }
1692
1694
1695 return DD_OK;
1696}
1697
1698static 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
1707static 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
1715 if (SUCCEEDED(hr)) surface_desc->dwSize = sizeof(*surface_desc);
1716 return hr;
1717}
1718
1719static 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
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 *****************************************************************************/
1749{
1750 struct ddraw *ddraw = impl_from_IDirectDraw7(iface);
1751 static const enum wined3d_format_id formats[] =
1752 {
1756 };
1758 DWORD count = 0, i, outsize;
1759 HRESULT hr;
1760
1761 TRACE("iface %p, codes_count %p, codes %p.\n", iface, NumCodes, Codes);
1762
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 {
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
1789static 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
1798static 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
1807static 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
1817{
1818 struct ddraw *ddraw = impl_from_IDirectDraw7(iface);
1820 HRESULT hr;
1821
1822 TRACE("iface %p, frequency %p.\n", iface, frequency);
1823
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
1839{
1840 struct ddraw *ddraw = impl_from_IDirectDraw4(iface);
1841
1842 TRACE("iface %p, frequency %p.\n", iface, frequency);
1843
1845}
1846
1848{
1849 struct ddraw *ddraw = impl_from_IDirectDraw2(iface);
1850
1851 TRACE("iface %p, frequency %p.\n", iface, frequency);
1852
1854}
1855
1857{
1858 struct ddraw *ddraw = impl_from_IDirectDraw(iface);
1859
1860 TRACE("iface %p, frequency %p.\n", iface, frequency);
1861
1863}
1864
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
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
1891{
1892 struct ddraw *ddraw = impl_from_IDirectDraw4(iface);
1893
1894 TRACE("iface %p, status %p.\n", iface, status);
1895
1897}
1898
1900{
1901 struct ddraw *ddraw = impl_from_IDirectDraw2(iface);
1902
1903 TRACE("iface %p, status %p.\n", iface, status);
1904
1906}
1907
1909{
1910 struct ddraw *ddraw = impl_from_IDirectDraw(iface);
1911
1912 TRACE("iface %p, status %p.\n", iface, status);
1913
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 *****************************************************************************/
1933 DWORD *free)
1934{
1935 unsigned int framebuffer_size, total_vidmem, free_vidmem;
1936 struct ddraw *ddraw = impl_from_IDirectDraw7(iface);
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 }
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 */
1961 {
1962 WARN("Failed to get display mode, hr %#x.\n", hr);
1964 return hr;
1965 }
1967 mode.format_id, mode.width);
1968 framebuffer_size *= mode.height;
1969
1970 if (free)
1971 {
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
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
1988
1989 return hr;
1990}
1991
1992static 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
2000}
2001
2002static 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);
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 *****************************************************************************/
2029{
2030 struct ddraw *ddraw = impl_from_IDirectDraw7(iface);
2031
2032 TRACE("iface %p, guid %s.\n", iface, debugstr_guid(guid));
2033
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
2043 return DD_OK;
2044}
2045
2046static 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
2053}
2054
2055static 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
2062}
2063
2064static 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
2071}
2072
2073static HRESULT WINAPI d3d1_Initialize(IDirect3D *iface, REFIID riid)
2074{
2075 TRACE("iface %p, riid %s.\n", iface, debugstr_guid(riid));
2076
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 *****************************************************************************/
2094{
2095 struct ddraw *ddraw = impl_from_IDirectDraw7(iface);
2096 IDirectDrawSurface7 *gdi_surface;
2097 struct ddraw_surface *gdi_impl;
2098 HRESULT hr;
2099
2100 TRACE("iface %p.\n", iface);
2101
2103
2104 if (FAILED(hr = IDirectDraw7_GetGDISurface(iface, &gdi_surface)))
2105 {
2106 WARN("Failed to retrieve GDI surface, hr %#x.\n", hr);
2108 return hr;
2109 }
2110
2111 gdi_impl = impl_from_IDirectDrawSurface7(gdi_surface);
2113 hr = DD_OK;
2114 else
2115 hr = IDirectDrawSurface7_Flip(&ddraw->primary->IDirectDrawSurface7_iface, gdi_surface, DDFLIP_WAIT);
2116 IDirectDrawSurface7_Release(gdi_surface);
2117
2119
2120 return hr;
2121}
2122
2123static HRESULT WINAPI ddraw4_FlipToGDISurface(IDirectDraw4 *iface)
2124{
2125 struct ddraw *ddraw = impl_from_IDirectDraw4(iface);
2126
2127 TRACE("iface %p.\n", iface);
2128
2130}
2131
2132static HRESULT WINAPI ddraw2_FlipToGDISurface(IDirectDraw2 *iface)
2133{
2134 struct ddraw *ddraw = impl_from_IDirectDraw2(iface);
2135
2136 TRACE("iface %p.\n", iface);
2137
2139}
2140
2141static HRESULT WINAPI ddraw1_FlipToGDISurface(IDirectDraw *iface)
2142{
2143 struct ddraw *ddraw = impl_from_IDirectDraw(iface);
2144
2145 TRACE("iface %p.\n", iface);
2146
2148}
2149
2150/*****************************************************************************
2151 * IDirectDraw7::WaitForVerticalBlank
2152 *
2153 * This method allows applications to get in sync with the vertical blank
2154 * interval.
2155 * The wormhole demo in the DirectX 7 sdk uses this call, and it doesn't
2156 * redraw the screen, most likely because of this stub
2157 *
2158 * Parameters:
2159 * Flags: one of DDWAITVB_BLOCKBEGIN, DDWAITVB_BLOCKBEGINEVENT
2160 * or DDWAITVB_BLOCKEND
2161 * h: Not used, according to MSDN
2162 *
2163 * Returns:
2164 * Always returns DD_OK
2165 *
2166 *****************************************************************************/
2168{
2169 static BOOL hide;
2170
2171 TRACE("iface %p, flags %#x, event %p.\n", iface, Flags, event);
2172
2173 /* This function is called often, so print the fixme only once */
2174 if(!hide)
2175 {
2176 FIXME("iface %p, flags %#x, event %p stub!\n", iface, Flags, event);
2177 hide = TRUE;
2178 }
2179
2180 /* MSDN says DDWAITVB_BLOCKBEGINEVENT is not supported */
2182 return DDERR_UNSUPPORTED; /* unchecked */
2183
2184 return DD_OK;
2185}
2186
2188{
2189 struct ddraw *ddraw = impl_from_IDirectDraw4(iface);
2190
2191 TRACE("iface %p, flags %#x, event %p.\n", iface, flags, event);
2192
2194}
2195
2197{
2198 struct ddraw *ddraw = impl_from_IDirectDraw2(iface);
2199
2200 TRACE("iface %p, flags %#x, event %p.\n", iface, flags, event);
2201
2203}
2204
2206{
2207 struct ddraw *ddraw = impl_from_IDirectDraw(iface);
2208
2209 TRACE("iface %p, flags %#x, event %p.\n", iface, flags, event);
2210
2212}
2213
2215{
2216 struct ddraw *ddraw = impl_from_IDirectDraw7(iface);
2217 struct wined3d_raster_status raster_status;
2218 HRESULT hr;
2219
2220 TRACE("iface %p, line %p.\n", iface, Scanline);
2221
2225 if (FAILED(hr))
2226 {
2227 WARN("Failed to get raster status, hr %#x.\n", hr);
2228 return hr;
2229 }
2230
2231 *Scanline = raster_status.scan_line;
2232
2233 if (raster_status.in_vblank)
2235
2236 return DD_OK;
2237}
2238
2239static HRESULT WINAPI ddraw4_GetScanLine(IDirectDraw4 *iface, DWORD *line)
2240{
2241 struct ddraw *ddraw = impl_from_IDirectDraw4(iface);
2242
2243 TRACE("iface %p, line %p.\n", iface, line);
2244
2246}
2247
2248static HRESULT WINAPI ddraw2_GetScanLine(IDirectDraw2 *iface, DWORD *line)
2249{
2250 struct ddraw *ddraw = impl_from_IDirectDraw2(iface);
2251
2252 TRACE("iface %p, line %p.\n", iface, line);
2253
2255}
2256
2257static HRESULT WINAPI ddraw1_GetScanLine(IDirectDraw *iface, DWORD *line)
2258{
2259 struct ddraw *ddraw = impl_from_IDirectDraw(iface);
2260
2261 TRACE("iface %p, line %p.\n", iface, line);
2262
2264}
2265
2267{
2268 struct ddraw *ddraw = impl_from_IDirectDraw7(iface);
2269
2270 TRACE("iface %p.\n", iface);
2271
2273}
2274
2275static HRESULT WINAPI ddraw4_TestCooperativeLevel(IDirectDraw4 *iface)
2276{
2277 struct ddraw *ddraw = impl_from_IDirectDraw4(iface);
2278
2279 TRACE("iface %p.\n", iface);
2280
2282}
2283
2284/*****************************************************************************
2285 * IDirectDraw7::GetGDISurface
2286 *
2287 * Returns the surface that GDI is treating as the primary surface.
2288 * For Wine this is the front buffer
2289 *
2290 * Params:
2291 * GDISurface: Address to write the surface pointer to
2292 *
2293 * Returns:
2294 * DD_OK if the surface was found
2295 * DDERR_NOTFOUND if the GDI surface wasn't found
2296 *
2297 *****************************************************************************/
2299{
2300 struct ddraw *ddraw = impl_from_IDirectDraw7(iface);
2301
2302 TRACE("iface %p, surface %p.\n", iface, GDISurface);
2303
2305
2306 if (!(*GDISurface = &ddraw->primary->IDirectDrawSurface7_iface))
2307 {
2308 WARN("Primary not created yet.\n");
2310 return DDERR_NOTFOUND;
2311 }
2312 IDirectDrawSurface7_AddRef(*GDISurface);
2313
2315
2316 return DD_OK;
2317}
2318
2319static HRESULT WINAPI ddraw4_GetGDISurface(IDirectDraw4 *iface, IDirectDrawSurface4 **surface)
2320{
2321 struct ddraw *ddraw = impl_from_IDirectDraw4(iface);
2322 struct ddraw_surface *surface_impl;
2323 IDirectDrawSurface7 *surface7;
2324 HRESULT hr;
2325
2326 TRACE("iface %p, surface %p.\n", iface, surface);
2327
2329 if (FAILED(hr))
2330 {
2331 *surface = NULL;
2332 return hr;
2333 }
2334 surface_impl = impl_from_IDirectDrawSurface7(surface7);
2335 *surface = &surface_impl->IDirectDrawSurface4_iface;
2336 IDirectDrawSurface4_AddRef(*surface);
2337 IDirectDrawSurface7_Release(surface7);
2338
2339 return hr;
2340}
2341
2342static HRESULT WINAPI ddraw2_GetGDISurface(IDirectDraw2 *iface, IDirectDrawSurface **surface)
2343{
2344 struct ddraw *ddraw = impl_from_IDirectDraw2(iface);
2345 struct ddraw_surface *surface_impl;
2346 IDirectDrawSurface7 *surface7;
2347 HRESULT hr;
2348
2349 TRACE("iface %p, surface %p.\n", iface, surface);
2350
2352 if (FAILED(hr))
2353 {
2354 *surface = NULL;
2355 return hr;
2356 }
2357 surface_impl = impl_from_IDirectDrawSurface7(surface7);
2358 *surface = &surface_impl->IDirectDrawSurface_iface;
2359 IDirectDrawSurface_AddRef(*surface);
2360 IDirectDrawSurface7_Release(surface7);
2361
2362 return hr;
2363}
2364
2365static HRESULT WINAPI ddraw1_GetGDISurface(IDirectDraw *iface, IDirectDrawSurface **surface)
2366{
2367 struct ddraw *ddraw = impl_from_IDirectDraw(iface);
2368 struct ddraw_surface *surface_impl;
2369 IDirectDrawSurface7 *surface7;
2370 HRESULT hr;
2371
2372 TRACE("iface %p, surface %p.\n", iface, surface);
2373
2375 if (FAILED(hr))
2376 {
2377 *surface = NULL;
2378 return hr;
2379 }
2380 surface_impl = impl_from_IDirectDrawSurface7(surface7);
2381 *surface = &surface_impl->IDirectDrawSurface_iface;
2382 IDirectDrawSurface_AddRef(*surface);
2383 IDirectDrawSurface7_Release(surface7);
2384
2385 return hr;
2386}
2387
2389{
2391 void *context;
2392};
2393
2395{
2396 struct displaymodescallback_context *cbcontext = context;
2398
2399 DDSD2_to_DDSD(surface_desc, &desc);
2400 return cbcontext->func(&desc, cbcontext->context);
2401}
2402
2403/*****************************************************************************
2404 * IDirectDraw7::EnumDisplayModes
2405 *
2406 * Enumerates the supported Display modes. The modes can be filtered with
2407 * the DDSD parameter.
2408 *
2409 * Params:
2410 * Flags: can be DDEDM_REFRESHRATES and DDEDM_STANDARDVGAMODES. For old ddraw
2411 * versions (3 and older?) this is reserved and must be 0.
2412 * DDSD: Surface description to filter the modes
2413 * Context: Pointer passed back to the callback function
2414 * cb: Application-provided callback function
2415 *
2416 * Returns:
2417 * DD_OK on success
2418 * DDERR_INVALIDPARAMS if the callback wasn't set
2419 *
2420 *****************************************************************************/
2423{
2424 struct ddraw *ddraw = impl_from_IDirectDraw7(iface);
2425 struct wined3d_display_mode *enum_modes = NULL;
2427 unsigned int modenum, fmt;
2428 DDSURFACEDESC2 callback_sd;
2429 unsigned enum_mode_count = 0, enum_mode_array_size = 16;
2431
2432 static const enum wined3d_format_id checkFormatList[] =
2433 {
2437 };
2438
2439 TRACE("iface %p, flags %#x, surface_desc %p, context %p, callback %p.\n",
2440 iface, Flags, DDSD, Context, cb);
2441
2442 if (!cb)
2443 return DDERR_INVALIDPARAMS;
2444
2445 if (!(enum_modes = heap_alloc(enum_mode_array_size * sizeof(*enum_modes))))
2446 return DDERR_OUTOFMEMORY;
2447
2449
2450 pixelformat.dwSize = sizeof(pixelformat);
2451 for(fmt = 0; fmt < ARRAY_SIZE(checkFormatList); fmt++)
2452 {
2453 modenum = 0;
2456 {
2457 BOOL found = FALSE;
2458 unsigned i;
2459
2461 if (DDSD)
2462 {
2463 if (DDSD->dwFlags & DDSD_WIDTH && mode.width != DDSD->dwWidth)
2464 continue;
2465 if (DDSD->dwFlags & DDSD_HEIGHT && mode.height != DDSD->dwHeight)
2466 continue;
2467 if (DDSD->dwFlags & DDSD_REFRESHRATE && mode.refresh_rate != DDSD->u2.dwRefreshRate)
2468 continue;
2469 if (DDSD->dwFlags & DDSD_PIXELFORMAT
2470 && pixelformat.u1.dwRGBBitCount != DDSD->u4.ddpfPixelFormat.u1.dwRGBBitCount)
2471 continue;
2472 }
2473
2474 /* DX docs state EnumDisplayMode should return only unique modes */
2475 for (i = 0; i < enum_mode_count; i++)
2476 {
2477 if (enum_modes[i].width == mode.width && enum_modes[i].height == mode.height
2478 && enum_modes[i].format_id == mode.format_id
2479 && (enum_modes[i].refresh_rate == mode.refresh_rate || !(Flags & DDEDM_REFRESHRATES)))
2480 {
2481 found = TRUE;
2482 break;
2483 }
2484 }
2485 if(found) continue;
2486
2487 memset(&callback_sd, 0, sizeof(callback_sd));
2488 callback_sd.dwSize = sizeof(callback_sd);
2489 callback_sd.u4.ddpfPixelFormat.dwSize = sizeof(DDPIXELFORMAT);
2490
2493 callback_sd.u2.dwRefreshRate = mode.refresh_rate;
2494
2495 callback_sd.dwWidth = mode.width;
2496 callback_sd.dwHeight = mode.height;
2497
2498 callback_sd.u4.ddpfPixelFormat=pixelformat;
2499
2500 /* Calc pitch and DWORD align like MSDN says */
2501 callback_sd.u1.lPitch = (callback_sd.u4.ddpfPixelFormat.u1.dwRGBBitCount / 8) * mode.width;
2502 callback_sd.u1.lPitch = (callback_sd.u1.lPitch + 3) & ~3;
2503
2504 TRACE("Enumerating %dx%dx%d @%d\n", callback_sd.dwWidth, callback_sd.dwHeight, callback_sd.u4.ddpfPixelFormat.u1.dwRGBBitCount,
2505 callback_sd.u2.dwRefreshRate);
2506
2507 if(cb(&callback_sd, Context) == DDENUMRET_CANCEL)
2508 {
2509 TRACE("Application asked to terminate the enumeration\n");
2510 heap_free(enum_modes);
2512 return DD_OK;
2513 }
2514
2515 if (enum_mode_count == enum_mode_array_size)
2516 {
2517 struct wined3d_display_mode *new_enum_modes;
2518
2519 enum_mode_array_size *= 2;
2520 if (!(new_enum_modes = heap_realloc(enum_modes, enum_mode_array_size * sizeof(*new_enum_modes))))
2521 {
2522 heap_free(enum_modes);
2524 return DDERR_OUTOFMEMORY;
2525 }
2526
2527 enum_modes = new_enum_modes;
2528 }
2529 enum_modes[enum_mode_count++] = mode;
2530 }
2531 }
2532
2533 TRACE("End of enumeration\n");
2534 heap_free(enum_modes);
2536
2537 return DD_OK;
2538}
2539
2542{
2543 struct ddraw *ddraw = impl_from_IDirectDraw4(iface);
2544
2545 TRACE("iface %p, flags %#x, surface_desc %p, context %p, callback %p.\n",
2546 iface, flags, surface_desc, context, callback);
2547
2549}
2550
2553{
2554 struct ddraw *ddraw = impl_from_IDirectDraw2(iface);
2555 struct displaymodescallback_context cbcontext;
2556 DDSURFACEDESC2 surface_desc2;
2557
2558 TRACE("iface %p, flags %#x, surface_desc %p, context %p, callback %p.\n",
2559 iface, flags, surface_desc, context, callback);
2560
2561 cbcontext.func = callback;
2562 cbcontext.context = context;
2563
2564 if (surface_desc) DDSD_to_DDSD2(surface_desc, &surface_desc2);
2566 surface_desc ? &surface_desc2 : NULL, &cbcontext, EnumDisplayModesCallbackThunk);
2567}
2568
2571{
2572 struct ddraw *ddraw = impl_from_IDirectDraw(iface);
2573 struct displaymodescallback_context cbcontext;
2574 DDSURFACEDESC2 surface_desc2;
2575
2576 TRACE("iface %p, flags %#x, surface_desc %p, context %p, callback %p.\n",
2577 iface, flags, surface_desc, context, callback);
2578
2579 cbcontext.func = callback;
2580 cbcontext.context = context;
2581
2582 if (surface_desc) DDSD_to_DDSD2(surface_desc, &surface_desc2);
2584 surface_desc ? &surface_desc2 : NULL, &cbcontext, EnumDisplayModesCallbackThunk);
2585}
2586
2587/*****************************************************************************
2588 * IDirectDraw7::EvaluateMode
2589 *
2590 * Used with IDirectDraw7::StartModeTest to test video modes.
2591 * EvaluateMode is used to pass or fail a mode, and continue with the next
2592 * mode
2593 *
2594 * Params:
2595 * Flags: DDEM_MODEPASSED or DDEM_MODEFAILED
2596 * Timeout: Returns the amount of seconds left before the mode would have
2597 * been failed automatically
2598 *
2599 * Returns:
2600 * This implementation always DD_OK, because it's a stub
2601 *
2602 *****************************************************************************/
2604{
2605 FIXME("iface %p, flags %#x, timeout %p stub!\n", iface, Flags, Timeout);
2606
2607 /* When implementing this, implement it in WineD3D */
2608
2609 return DD_OK;
2610}
2611
2612/*****************************************************************************
2613 * IDirectDraw7::GetDeviceIdentifier
2614 *
2615 * Returns the device identifier, which gives information about the driver
2616 * Our device identifier is defined at the beginning of this file.
2617 *
2618 * Params:
2619 * DDDI: Address for the returned structure
2620 * Flags: Can be DDGDI_GETHOSTIDENTIFIER
2621 *
2622 * Returns:
2623 * On success it returns DD_OK
2624 * DDERR_INVALIDPARAMS if DDDI is NULL
2625 *
2626 *****************************************************************************/
2629{
2630 struct ddraw *ddraw = impl_from_IDirectDraw7(iface);
2631 struct wined3d_adapter_identifier adapter_id;
2632 HRESULT hr = S_OK;
2633
2634 TRACE("iface %p, device_identifier %p, flags %#x.\n", iface, DDDI, Flags);
2635
2636 if (!DDDI)
2637 return DDERR_INVALIDPARAMS;
2638
2640 {
2641 /* The DDGDI_GETHOSTIDENTIFIER returns the information about the 2D
2642 * host adapter, if there's a secondary 3D adapter. This doesn't apply
2643 * to any modern hardware, nor is it interesting for Wine, so ignore it.
2644 * Size of DDDEVICEIDENTIFIER2 may be aligned to 8 bytes and thus 4
2645 * bytes too long. So only copy the relevant part of the structure
2646 */
2647
2649 return DD_OK;
2650 }
2651
2652 /* Drakan: Order of the Flame expects accurate D3D device information from ddraw */
2653 adapter_id.driver = DDDI->szDriver;
2654 adapter_id.driver_size = sizeof(DDDI->szDriver);
2655 adapter_id.description = DDDI->szDescription;
2656 adapter_id.description_size = sizeof(DDDI->szDescription);
2657 adapter_id.device_name_size = 0;
2661 if (FAILED(hr)) return hr;
2662
2663 DDDI->liDriverVersion = adapter_id.driver_version;
2664 DDDI->dwVendorId = adapter_id.vendor_id;
2665 DDDI->dwDeviceId = adapter_id.device_id;
2666 DDDI->dwSubSysId = adapter_id.subsystem_id;
2667 DDDI->dwRevision = adapter_id.revision;
2668 DDDI->guidDeviceIdentifier = adapter_id.device_identifier;
2669 DDDI->dwWHQLLevel = adapter_id.whql_level;
2670 return DD_OK;
2671}
2672
2673static HRESULT WINAPI ddraw4_GetDeviceIdentifier(IDirectDraw4 *iface,
2674 DDDEVICEIDENTIFIER *identifier, DWORD flags)
2675{
2676 struct ddraw *ddraw = impl_from_IDirectDraw4(iface);
2677 DDDEVICEIDENTIFIER2 identifier2;
2678 HRESULT hr;
2679
2680 TRACE("iface %p, identifier %p, flags %#x.\n", iface, identifier, flags);
2681
2683 DDRAW_Convert_DDDEVICEIDENTIFIER_2_To_1(&identifier2, identifier);
2684
2685 return hr;
2686}
2687
2688/*****************************************************************************
2689 * IDirectDraw7::GetSurfaceFromDC
2690 *
2691 * Returns the Surface for a GDI device context handle.
2692 * Is this related to IDirectDrawSurface::GetDC ???
2693 *
2694 * Params:
2695 * hdc: hdc to return the surface for
2696 * Surface: Address to write the surface pointer to
2697 *
2698 * Returns:
2699 * Always returns DD_OK because it's a stub
2700 *
2701 *****************************************************************************/
2703 HDC dc, IDirectDrawSurface7 **surface)
2704{
2705 struct ddraw *ddraw = impl_from_IDirectDraw7(iface);
2706 struct ddraw_surface *surface_impl;
2707
2708 TRACE("iface %p, dc %p, surface %p.\n", iface, dc, surface);
2709
2710 if (!surface)
2711 return E_INVALIDARG;
2712
2713 if (!dc)
2714 goto done;
2715
2718 {
2719 if (surface_impl->dc != dc)
2720 continue;
2721
2722 TRACE("Found surface %p for dc %p.\n", surface_impl, dc);
2723 *surface = &surface_impl->IDirectDrawSurface7_iface;
2724 IDirectDrawSurface7_AddRef(*surface);
2726 return DD_OK;
2727 }
2729
2730done:
2731 TRACE("No surface found for dc %p.\n", dc);
2732 *surface = NULL;
2733 return DDERR_NOTFOUND;
2734}
2735
2736static HRESULT WINAPI ddraw4_GetSurfaceFromDC(IDirectDraw4 *iface, HDC dc,
2737 IDirectDrawSurface4 **surface)
2738{
2739 struct ddraw *ddraw = impl_from_IDirectDraw4(iface);
2740 struct ddraw_surface *surface_impl;
2741 IDirectDrawSurface7 *surface7;
2742 HRESULT hr;
2743
2744 TRACE("iface %p, dc %p, surface %p.\n", iface, dc, surface);
2745
2746 if (!surface) return E_INVALIDARG;
2747
2749 if (FAILED(hr))
2750 {
2751 *surface = NULL;
2752 return hr;
2753 }
2754 surface_impl = impl_from_IDirectDrawSurface7(surface7);
2755 /* Tests say this is true */
2756 *surface = (IDirectDrawSurface4 *)&surface_impl->IDirectDrawSurface_iface;
2757 IDirectDrawSurface_AddRef(&surface_impl->IDirectDrawSurface_iface);
2758 IDirectDrawSurface7_Release(surface7);
2759
2760 return hr;
2761}
2762
2764{
2765 IDirectDrawSurface_Restore(surface);
2766 IDirectDrawSurface_Release(surface);
2767
2768 return DDENUMRET_OK;
2769}
2770
2772{
2773 TRACE("iface %p.\n", iface);
2774
2775 return IDirectDraw7_EnumSurfaces(iface, DDENUMSURFACES_ALL | DDENUMSURFACES_DOESEXIST,
2777}
2778
2779static HRESULT WINAPI ddraw4_RestoreAllSurfaces(IDirectDraw4 *iface)
2780{
2781 struct ddraw *ddraw = impl_from_IDirectDraw4(iface);
2782
2783 TRACE("iface %p.\n", iface);
2784
2786}
2787
2788/*****************************************************************************
2789 * IDirectDraw7::StartModeTest
2790 *
2791 * Tests the specified video modes to update the system registry with
2792 * refresh rate information. StartModeTest starts the mode test,
2793 * EvaluateMode is used to fail or pass a mode. If EvaluateMode
2794 * isn't called within 15 seconds, the mode is failed automatically
2795 *
2796 * As refresh rates are handled by the X server, I don't think this
2797 * Method is important
2798 *
2799 * Params:
2800 * Modes: An array of mode specifications
2801 * NumModes: The number of modes in Modes
2802 * Flags: Some flags...
2803 *
2804 * Returns:
2805 * Returns DDERR_TESTFINISHED if flags contains DDSMT_ISTESTREQUIRED,
2806 * if no modes are passed, DDERR_INVALIDPARAMS is returned,
2807 * otherwise DD_OK
2808 *
2809 *****************************************************************************/
2811{
2812 FIXME("iface %p, modes %p, mode_count %u, flags %#x partial stub!\n",
2813 iface, Modes, NumModes, Flags);
2814
2815 /* This looks sane */
2816 if( (!Modes) || (NumModes == 0) ) return DDERR_INVALIDPARAMS;
2817
2818 /* DDSMT_ISTESTREQUIRED asks if a mode test is necessary.
2819 * As it is not, DDERR_TESTFINISHED is returned
2820 * (hopefully that's correct
2821 *
2822 if(Flags & DDSMT_ISTESTREQUIRED) return DDERR_TESTFINISHED;
2823 * well, that value doesn't (yet) exist in the wine headers, so ignore it
2824 */
2825
2826 return DD_OK;
2827}
2828
2830 IDirectDrawSurface7 **surface, IUnknown *outer_unknown)
2831{
2832 struct ddraw *ddraw = impl_from_IDirectDraw7(iface);
2833 struct ddraw_surface *impl;
2834 HRESULT hr;
2835
2836 TRACE("iface %p, surface_desc %p, surface %p, outer_unknown %p.\n",
2837 iface, surface_desc, surface, outer_unknown);
2838
2840
2842 {
2843 WARN("Cooperative level not set.\n");
2846 }
2847
2848 if(surface_desc == NULL || surface_desc->dwSize != sizeof(DDSURFACEDESC2))
2849 {
2850 WARN("Application supplied invalid surface descriptor\n");
2852 return DDERR_INVALIDPARAMS;
2853 }
2854
2855 __TRY
2856 {
2857 *surface = NULL;
2858 }
2860 {
2861 WARN("Surface pointer %p is invalid.\n", surface);
2863 return DDERR_INVALIDPARAMS;
2864 }
2865 __ENDTRY;
2866
2868 {
2869 if (TRACE_ON(ddraw))
2870 {
2871 TRACE(" (%p) Requesting surface desc :\n", iface);
2873 }
2874
2875 WARN("Application tried to create an explicit front or back buffer\n");
2877 return DDERR_INVALIDCAPS;
2878 }
2879
2880 hr = ddraw_surface_create(ddraw, surface_desc, &impl, outer_unknown, 7);
2882 if (FAILED(hr))
2883 return hr;
2884
2885 *surface = &impl->IDirectDrawSurface7_iface;
2886 IDirectDraw7_AddRef(iface);
2887 impl->ifaceToRelease = (IUnknown *)iface;
2888
2889 return hr;
2890}
2891
2892static HRESULT WINAPI ddraw4_CreateSurface(IDirectDraw4 *iface,
2893 DDSURFACEDESC2 *surface_desc, IDirectDrawSurface4 **surface, IUnknown *outer_unknown)
2894{
2895 struct ddraw *ddraw = impl_from_IDirectDraw4(iface);
2896 struct ddraw_surface *impl;
2897 HRESULT hr;
2898
2899 TRACE("iface %p, surface_desc %p, surface %p, outer_unknown %p.\n",
2900 iface, surface_desc, surface, outer_unknown);
2901
2903
2905 {
2906 WARN("Cooperative level not set.\n");
2909 }
2910
2911 if(surface_desc == NULL || surface_desc->dwSize != sizeof(DDSURFACEDESC2))
2912 {
2913 WARN("Application supplied invalid surface descriptor\n");
2915 return DDERR_INVALIDPARAMS;
2916 }
2917
2918 __TRY
2919 {
2920 *surface = NULL;
2921 }
2923 {
2924 WARN("Surface pointer %p is invalid.\n", surface);
2926 return DDERR_INVALIDPARAMS;
2927 }
2928 __ENDTRY;
2929
2931 {
2932 if (TRACE_ON(ddraw))
2933 {
2934 TRACE(" (%p) Requesting surface desc :\n", iface);
2936 }
2937
2938 WARN("Application tried to create an explicit front or back buffer\n");
2940 return DDERR_INVALIDCAPS;
2941 }
2942
2943 hr = ddraw_surface_create(ddraw, surface_desc, &impl, outer_unknown, 4);
2945 if (FAILED(hr))
2946 return hr;
2947
2948 *surface = &impl->IDirectDrawSurface4_iface;
2949 IDirectDraw4_AddRef(iface);
2950 impl->ifaceToRelease = (IUnknown *)iface;
2951
2952 return hr;
2953}
2954
2955static HRESULT WINAPI ddraw2_CreateSurface(IDirectDraw2 *iface,
2956 DDSURFACEDESC *surface_desc, IDirectDrawSurface **surface, IUnknown *outer_unknown)
2957{
2958 struct ddraw *ddraw = impl_from_IDirectDraw2(iface);
2959 struct ddraw_surface *impl;
2960 HRESULT hr;
2961 DDSURFACEDESC2 surface_desc2;
2962
2963 TRACE("iface %p, surface_desc %p, surface %p, outer_unknown %p.\n",
2964 iface, surface_desc, surface, outer_unknown);
2965
2967
2969 {
2970 WARN("Cooperative level not set.\n");
2973 }
2974
2975 if(surface_desc == NULL || surface_desc->dwSize != sizeof(DDSURFACEDESC))
2976 {
2977 WARN("Application supplied invalid surface descriptor\n");
2979 return DDERR_INVALIDPARAMS;
2980 }
2981
2982 __TRY
2983 {
2984 *surface = NULL;
2985 }
2987 {
2988 WARN("Surface pointer %p is invalid.\n", surface);
2990 return DDERR_INVALIDPARAMS;
2991 }
2992 __ENDTRY;
2993
2994 DDSD_to_DDSD2(surface_desc, &surface_desc2);
2996 {
2997 if (TRACE_ON(ddraw))
2998 {
2999 TRACE(" (%p) Requesting surface desc :\n", iface);
3001 }
3002
3003 WARN("Application tried to create an explicit front or back buffer\n");
3005 return DDERR_INVALIDCAPS;
3006 }
3007
3008 hr = ddraw_surface_create(ddraw, &surface_desc2, &impl, outer_unknown, 2);
3010 if (FAILED(hr))
3011 return hr;
3012
3013 *surface = &impl->IDirectDrawSurface_iface;
3014 impl->ifaceToRelease = NULL;
3015
3016 return hr;
3017}
3018
3019static HRESULT WINAPI ddraw1_CreateSurface(IDirectDraw *iface,
3020 DDSURFACEDESC *surface_desc, IDirectDrawSurface **surface, IUnknown *outer_unknown)
3021{
3022 struct ddraw *ddraw = impl_from_IDirectDraw(iface);
3023 struct ddraw_surface *impl;
3024 HRESULT hr;
3025 DDSURFACEDESC2 surface_desc2;
3026
3027 TRACE("iface %p, surface_desc %p, surface %p, outer_unknown %p.\n",
3028 iface, surface_desc, surface, outer_unknown);
3029
3031
3033 {
3034 WARN("Cooperative level not set.\n");
3037 }
3038
3039 if(surface_desc == NULL || surface_desc->dwSize != sizeof(DDSURFACEDESC))
3040 {
3041 WARN("Application supplied invalid surface descriptor\n");
3043 return DDERR_INVALIDPARAMS;
3044 }
3045
3046 __TRY
3047 {
3048 *surface = NULL;
3049 }
3051 {
3052 WARN("Surface pointer %p is invalid.\n", surface);
3054 return DDERR_INVALIDPARAMS;
3055 }
3056 __ENDTRY;
3057
3062 {
3063 WARN("Application tried to create an explicit front or back buffer.\n");
3065 return DDERR_INVALIDCAPS;
3066 }
3067
3068 DDSD_to_DDSD2(surface_desc, &surface_desc2);
3069 hr = ddraw_surface_create(ddraw, &surface_desc2, &impl, outer_unknown, 1);
3071 if (FAILED(hr))
3072 return hr;
3073
3074 *surface = &impl->IDirectDrawSurface_iface;
3075 impl->ifaceToRelease = NULL;
3076
3077 return hr;
3078}
3079
3080static BOOL
3082 const DDPIXELFORMAT *provided)
3083{
3084 /* Some flags must be present in both or neither for a match. */
3085 static const DWORD must_match = DDPF_PALETTEINDEXED1 | DDPF_PALETTEINDEXED2
3088
3089 if ((requested->dwFlags & provided->dwFlags) != requested->dwFlags)
3090 return FALSE;
3091
3092 if ((requested->dwFlags & must_match) != (provided->dwFlags & must_match))
3093 return FALSE;
3094
3095 if (requested->dwFlags & DDPF_FOURCC)
3096 if (requested->dwFourCC != provided->dwFourCC)
3097 return FALSE;
3098
3101 if (requested->u1.dwRGBBitCount != provided->u1.dwRGBBitCount)
3102 return FALSE;
3103
3106 if (requested->u2.dwRBitMask != provided->u2.dwRBitMask)
3107 return FALSE;
3108
3110 if (requested->u3.dwGBitMask != provided->u3.dwGBitMask)
3111 return FALSE;
3112
3113 /* I could be wrong about the bumpmapping. MSDN docs are vague. */
3115 |DDPF_BUMPDUDV))
3116 if (requested->u4.dwBBitMask != provided->u4.dwBBitMask)
3117 return FALSE;
3118
3119 if (requested->dwFlags & (DDPF_ALPHAPIXELS|DDPF_ZPIXELS))
3120 if (requested->u5.dwRGBAlphaBitMask != provided->u5.dwRGBAlphaBitMask)
3121 return FALSE;
3122
3123 return TRUE;
3124}
3125
3126static BOOL ddraw_match_surface_desc(const DDSURFACEDESC2 *requested, const DDSURFACEDESC2 *provided)
3127{
3128 struct compare_info
3129 {
3130 DWORD flag;
3132 size_t size;
3133 };
3134
3135#define CMP(FLAG, FIELD) \
3136 { DDSD_##FLAG, offsetof(DDSURFACEDESC2, FIELD), \
3137 sizeof(((DDSURFACEDESC2 *)(NULL))->FIELD) }
3138
3139 static const struct compare_info compare[] =
3140 {
3141 CMP(ALPHABITDEPTH, dwAlphaBitDepth),
3142 CMP(BACKBUFFERCOUNT, u5.dwBackBufferCount),
3143 CMP(CAPS, ddsCaps),
3144 CMP(CKDESTBLT, ddckCKDestBlt),
3145 CMP(CKDESTOVERLAY, u3 /* ddckCKDestOverlay */),
3146 CMP(CKSRCBLT, ddckCKSrcBlt),
3147 CMP(CKSRCOVERLAY, ddckCKSrcOverlay),
3149 CMP(LINEARSIZE, u1 /* dwLinearSize */),
3150 CMP(LPSURFACE, lpSurface),
3151 CMP(MIPMAPCOUNT, u2 /* dwMipMapCount */),
3152 CMP(PITCH, u1 /* lPitch */),
3153 /* PIXELFORMAT: manual */
3154 CMP(REFRESHRATE, u2 /* dwRefreshRate */),
3155 CMP(TEXTURESTAGE, dwTextureStage),
3156 CMP(WIDTH, dwWidth),
3157 /* ZBUFFERBITDEPTH: "obsolete" */
3158 };
3159
3160#undef CMP
3161
3162 unsigned int i;
3163
3164 if ((requested->dwFlags & provided->dwFlags) != requested->dwFlags)
3165 return FALSE;
3166
3167 for (i=0; i < ARRAY_SIZE(compare); i++)
3168 {
3169 if (requested->dwFlags & compare[i].flag
3170 && memcmp((const char *)provided + compare[i].offset,
3171 (const char *)requested + compare[i].offset,
3172 compare[i].size) != 0)
3173 return FALSE;
3174 }
3175
3176 if (requested->dwFlags & DDSD_PIXELFORMAT)
3177 {
3179 &provided->u4.ddpfPixelFormat))
3180 return FALSE;
3181 }
3182
3183 return TRUE;
3184}
3185
3187{
3189 void *context;
3190};
3191
3193{
3195 void *context;
3196};
3197
3199 DDSURFACEDESC2 *surface_desc, void *context)
3200{
3201 struct ddraw_surface *surface_impl = impl_from_IDirectDrawSurface7(surface);
3202 struct surfacescallback2_context *cbcontext = context;
3203
3204 IDirectDrawSurface4_AddRef(&surface_impl->IDirectDrawSurface4_iface);
3205 IDirectDrawSurface7_Release(surface);
3206
3207 return cbcontext->func(&surface_impl->IDirectDrawSurface4_iface,
3208 surface_desc, cbcontext->context);
3209}
3210
3212 DDSURFACEDESC2 *surface_desc, void *context)
3213{
3214 struct ddraw_surface *surface_impl = impl_from_IDirectDrawSurface7(surface);
3215 struct surfacescallback_context *cbcontext = context;
3216
3217 IDirectDrawSurface_AddRef(&surface_impl->IDirectDrawSurface_iface);
3218 IDirectDrawSurface7_Release(surface);
3219
3220 return cbcontext->func(&surface_impl->IDirectDrawSurface_iface,
3221 (DDSURFACEDESC *)surface_desc, cbcontext->context);
3222}
3223
3224/*****************************************************************************
3225 * IDirectDraw7::EnumSurfaces
3226 *
3227 * Loops through all surfaces attached to this device and calls the
3228 * application callback. This can't be relayed to WineD3DDevice,
3229 * because some WineD3DSurfaces' parents are IParent objects
3230 *
3231 * Params:
3232 * Flags: Some filtering flags. See IDirectDrawImpl_EnumSurfacesCallback
3233 * DDSD: Description to filter for
3234 * Context: Application-provided pointer, it's passed unmodified to the
3235 * Callback function
3236 * Callback: Address to call for each surface
3237 *
3238 * Returns:
3239 * DDERR_INVALIDPARAMS if the callback is NULL
3240 * DD_OK on success
3241 *
3242 *****************************************************************************/
3245{
3246 struct ddraw *ddraw = impl_from_IDirectDraw7(iface);
3247 struct ddraw_surface *surf;
3249
3250 TRACE("iface %p, flags %#x, surface_desc %p, context %p, callback %p.\n",
3251 iface, Flags, DDSD, Context, Callback);
3252
3253 if (!Callback)
3254 return DDERR_INVALIDPARAMS;
3255
3257 {
3258 IDirectDrawSurface7 *surface;
3259 DDSURFACEDESC2 testdesc;
3260 HRESULT hr;
3261
3262 if (match_flags != DDENUMSURFACES_MATCH)
3263 return DDERR_INVALIDPARAMS;
3264
3265 if (!DDSD)
3266 return DDERR_INVALIDPARAMS;
3267
3268 memcpy(&testdesc, DDSD, sizeof(testdesc));
3269 if (!(testdesc.dwFlags & DDSD_WIDTH))
3270 {
3271 testdesc.dwFlags |= DDSD_WIDTH;
3272 testdesc.dwWidth = 512;
3273 }
3274 if (!(testdesc.dwFlags & DDSD_HEIGHT))
3275 {
3276 testdesc.dwFlags |= DDSD_HEIGHT;
3277 testdesc.dwHeight = 512;
3278 }
3279
3280 hr = IDirectDraw7_CreateSurface(iface, &testdesc, &surface, NULL);
3281 if (SUCCEEDED(hr))
3282 {
3285 IDirectDrawSurface7_Release(surface);
3286 }
3287 else
3288 ERR("Failed to create surface, hr %#x.\n", hr);
3289 }
3291 {
3292 BOOL all, nomatch;
3294 struct list *entry, *entry2;
3295
3296 /* a combination of match flags is not allowed */
3297 if (match_flags != 0 &&
3298 match_flags != DDENUMSURFACES_ALL &&
3299 match_flags != DDENUMSURFACES_MATCH &&
3300 match_flags != DDENUMSURFACES_NOMATCH)
3301 return DDERR_INVALIDPARAMS;
3302
3303 all = (Flags & DDENUMSURFACES_ALL) != 0;
3304 nomatch = (Flags & DDENUMSURFACES_NOMATCH) != 0;
3305
3306 if (!all && !DDSD)
3307 return DDERR_INVALIDPARAMS;
3308
3310
3311 /* Use the _SAFE enumeration, the app may destroy enumerated surfaces */
3313 {
3314 surf = LIST_ENTRY(entry, struct ddraw_surface, surface_list_entry);
3315
3316 if (!surf->iface_count)
3317 {
3318 WARN("Not enumerating surface %p because it doesn't have any references.\n", surf);
3319 continue;
3320 }
3321
3322 if (all || (nomatch != ddraw_match_surface_desc(DDSD, &surf->surface_desc)))
3323 {
3324 TRACE("Enumerating surface %p.\n", surf);
3325 desc = surf->surface_desc;
3326 IDirectDrawSurface7_AddRef(&surf->IDirectDrawSurface7_iface);
3328 {
3330 return DD_OK;
3331 }
3332 }
3333 }
3334
3336 }
3337 else
3338 return DDERR_INVALIDPARAMS;
3339
3340 return DD_OK;
3341}
3342
3343static HRESULT WINAPI ddraw4_EnumSurfaces(IDirectDraw4 *iface, DWORD flags,
3345{
3346 struct ddraw *ddraw = impl_from_IDirectDraw4(iface);
3347 struct surfacescallback2_context cbcontext;
3348
3349 TRACE("iface %p, flags %#x, surface_desc %p, context %p, callback %p.\n",
3350 iface, flags, surface_desc, context, callback);
3351
3352 cbcontext.func = callback;
3353 cbcontext.context = context;
3354
3355 return ddraw7_EnumSurfaces(&ddraw->IDirectDraw7_iface, flags, surface_desc,
3356 &cbcontext, EnumSurfacesCallback2Thunk);
3357}
3358
3359static HRESULT WINAPI ddraw2_EnumSurfaces(IDirectDraw2 *iface, DWORD flags,
3361{
3362 struct ddraw *ddraw = impl_from_IDirectDraw2(iface);
3363 struct surfacescallback_context cbcontext;
3364 DDSURFACEDESC2 surface_desc2;
3365
3366 TRACE("iface %p, flags %#x, surface_desc %p, context %p, callback %p.\n",
3367 iface, flags, surface_desc, context, callback);
3368
3369 cbcontext.func = callback;
3370 cbcontext.context = context;
3371
3372 if (surface_desc) DDSD_to_DDSD2(surface_desc, &surface_desc2);
3374 surface_desc ? &surface_desc2 : NULL, &cbcontext, EnumSurfacesCallbackThunk);
3375}
3376
3377static HRESULT WINAPI ddraw1_EnumSurfaces(IDirectDraw *iface, DWORD flags,
3379{
3380 struct ddraw *ddraw = impl_from_IDirectDraw(iface);
3381 struct surfacescallback_context cbcontext;
3382 DDSURFACEDESC2 surface_desc2;
3383
3384 TRACE("iface %p, flags %#x, surface_desc %p, context %p, callback %p.\n",
3385 iface, flags, surface_desc, context, callback);
3386
3387 cbcontext.func = callback;
3388 cbcontext.context = context;
3389
3390 if (surface_desc) DDSD_to_DDSD2(surface_desc, &surface_desc2);
3392 surface_desc ? &surface_desc2 : NULL, &cbcontext, EnumSurfacesCallbackThunk);
3393}
3394
3395/*****************************************************************************
3396 * DirectDrawCreateClipper (DDRAW.@)
3397 *
3398 * Creates a new IDirectDrawClipper object.
3399 *
3400 * Params:
3401 * Clipper: Address to write the interface pointer to
3402 * UnkOuter: For aggregation support, which ddraw doesn't have. Has to be
3403 * NULL
3404 *
3405 * Returns:
3406 * CLASS_E_NOAGGREGATION if UnkOuter != NULL
3407 * E_OUTOFMEMORY if allocating the object failed
3408 *
3409 *****************************************************************************/
3410HRESULT WINAPI DirectDrawCreateClipper(DWORD flags, IDirectDrawClipper **clipper, IUnknown *outer_unknown)
3411{
3412 struct ddraw_clipper *object;
3413 HRESULT hr;
3414
3415 TRACE("flags %#x, clipper %p, outer_unknown %p.\n",
3416 flags, clipper, outer_unknown);
3417
3418 if (outer_unknown)
3419 return CLASS_E_NOAGGREGATION;
3420
3422
3423 if (!(object = heap_alloc_zero(sizeof(*object))))
3424 {
3426 return E_OUTOFMEMORY;
3427 }
3428
3429 hr = ddraw_clipper_init(object);
3430 if (FAILED(hr))
3431 {
3432 WARN("Failed to initialize clipper, hr %#x.\n", hr);
3433 heap_free(object);
3435 return hr;
3436 }
3437
3438 TRACE("Created clipper %p.\n", object);
3439 *clipper = &object->IDirectDrawClipper_iface;
3441
3442 return DD_OK;
3443}
3444
3445/*****************************************************************************
3446 * IDirectDraw7::CreateClipper
3447 *
3448 * Creates a DDraw clipper. See DirectDrawCreateClipper for details
3449 *
3450 *****************************************************************************/
3452 IDirectDrawClipper **Clipper, IUnknown *UnkOuter)
3453{
3454 TRACE("iface %p, flags %#x, clipper %p, outer_unknown %p.\n",
3455 iface, Flags, Clipper, UnkOuter);
3456
3457 return DirectDrawCreateClipper(Flags, Clipper, UnkOuter);
3458}
3459
3460static HRESULT WINAPI ddraw4_CreateClipper(IDirectDraw4 *iface, DWORD flags,
3461 IDirectDrawClipper **clipper, IUnknown *outer_unknown)
3462{
3463 struct ddraw *ddraw = impl_from_IDirectDraw4(iface);
3464
3465 TRACE("iface %p, flags %#x, clipper %p, outer_unknown %p.\n",
3466 iface, flags, clipper, outer_unknown);
3467
3468 return ddraw7_CreateClipper(&ddraw->IDirectDraw7_iface, flags, clipper, outer_unknown);
3469}
3470
3471static HRESULT WINAPI ddraw2_CreateClipper(IDirectDraw2 *iface,
3472 DWORD flags, IDirectDrawClipper **clipper, IUnknown *outer_unknown)
3473{
3474 struct ddraw *ddraw = impl_from_IDirectDraw2(iface);
3475
3476 TRACE("iface %p, flags %#x, clipper %p, outer_unknown %p.\n",
3477 iface, flags, clipper, outer_unknown);
3478
3479 return ddraw7_CreateClipper(&ddraw->IDirectDraw7_iface, flags, clipper, outer_unknown);
3480}
3481
3482static HRESULT WINAPI ddraw1_CreateClipper(IDirectDraw *iface,
3483 DWORD flags, IDirectDrawClipper **clipper, IUnknown *outer_unknown)
3484{
3485 struct ddraw *ddraw = impl_from_IDirectDraw(iface);
3486
3487 TRACE("iface %p, flags %#x, clipper %p, outer_unknown %p.\n",
3488 iface, flags, clipper, outer_unknown);
3489
3490 return ddraw7_CreateClipper(&ddraw->IDirectDraw7_iface, flags, clipper, outer_unknown);
3491}
3492
3493/*****************************************************************************
3494 * IDirectDraw7::CreatePalette
3495 *
3496 * Creates a new IDirectDrawPalette object
3497 *
3498 * Params:
3499 * Flags: The flags for the new clipper
3500 * ColorTable: Color table to assign to the new clipper
3501 * Palette: Address to write the interface pointer to
3502 * UnkOuter: For aggregation support, which ddraw doesn't have. Has to be
3503 * NULL
3504 *
3505 * Returns:
3506 * CLASS_E_NOAGGREGATION if UnkOuter != NULL
3507 * E_OUTOFMEMORY if allocating the object failed
3508 *
3509 *****************************************************************************/
3511 PALETTEENTRY *ColorTable, IDirectDrawPalette **Palette, IUnknown *pUnkOuter)
3512{
3513 struct ddraw *ddraw = impl_from_IDirectDraw7(iface);
3514 struct ddraw_palette *object;
3515 HRESULT hr;
3516
3517 TRACE("iface %p, flags %#x, color_table %p, palette %p, outer_unknown %p.\n",
3518 iface, Flags, ColorTable, Palette, pUnkOuter);
3519
3520 if (pUnkOuter)
3521 return CLASS_E_NOAGGREGATION;
3522
3524
3525 /* The refcount test shows that a cooplevel is required for this */
3527 {
3528 WARN("No cooperative level set, returning DDERR_NOCOOPERATIVELEVELSET\n");
3531 }
3532
3533 if (!(object = heap_alloc(sizeof(*object))))
3534 {
3535 ERR("Out of memory when allocating memory for a palette implementation\n");
3537 return E_OUTOFMEMORY;
3538 }
3539
3540 hr = ddraw_palette_init(object, ddraw, Flags, ColorTable);
3541 if (FAILED(hr))
3542 {
3543 WARN("Failed to initialize palette, hr %#x.\n", hr);
3544 heap_free(object);
3546 return hr;
3547 }
3548
3549 TRACE("Created palette %p.\n", object);
3550 *Palette = &object->IDirectDrawPalette_iface;
3552
3553 return DD_OK;
3554}
3555
3556static HRESULT WINAPI ddraw4_CreatePalette(IDirectDraw4 *iface, DWORD flags, PALETTEENTRY *entries,
3557 IDirectDrawPalette **palette, IUnknown *outer_unknown)
3558{
3559 struct ddraw *ddraw = impl_from_IDirectDraw4(iface);
3560 HRESULT hr;
3561
3562 TRACE("iface %p, flags %#x, entries %p, palette %p, outer_unknown %p.\n",
3563 iface, flags, entries, palette, outer_unknown);
3564
3565 hr = ddraw7_CreatePalette(&ddraw->IDirectDraw7_iface, flags, entries, palette, outer_unknown);
3566 if (SUCCEEDED(hr) && *palette)
3567 {
3569 IDirectDraw7_Release(&ddraw->IDirectDraw7_iface);
3570 IDirectDraw4_AddRef(iface);
3571 impl->ifaceToRelease = (IUnknown *)iface;
3572 }
3573 return hr;
3574}
3575
3576static HRESULT WINAPI ddraw2_CreatePalette(IDirectDraw2 *iface, DWORD flags,
3577 PALETTEENTRY *entries, IDirectDrawPalette **palette, IUnknown *outer_unknown)
3578{
3579 struct ddraw *ddraw = impl_from_IDirectDraw2(iface);
3580 HRESULT hr;
3581
3582 TRACE("iface %p, flags %#x, entries %p, palette %p, outer_unknown %p.\n",
3583 iface, flags, entries, palette, outer_unknown);
3584
3585 hr = ddraw7_CreatePalette(&ddraw->IDirectDraw7_iface, flags, entries, palette, outer_unknown);
3586 if (SUCCEEDED(hr) && *palette)
3587 {
3589 IDirectDraw7_Release(&ddraw->IDirectDraw7_iface);
3590 impl->ifaceToRelease = NULL;
3591 }
3592
3593 return hr;
3594}
3595
3596static HRESULT WINAPI ddraw1_CreatePalette(IDirectDraw *iface, DWORD flags,
3597 PALETTEENTRY *entries, IDirectDrawPalette **palette, IUnknown *outer_unknown)
3598{
3599 struct ddraw *ddraw = impl_from_IDirectDraw(iface);
3600 HRESULT hr;
3601
3602 TRACE("iface %p, flags %#x, entries %p, palette %p, outer_unknown %p.\n",
3603 iface, flags, entries, palette, outer_unknown);
3604
3605 hr = ddraw7_CreatePalette(&ddraw->IDirectDraw7_iface, flags, entries, palette, outer_unknown);
3606 if (SUCCEEDED(hr) && *palette)
3607 {
3609 IDirectDraw7_Release(&ddraw->IDirectDraw7_iface);
3610 impl->ifaceToRelease = NULL;
3611 }
3612
3613 return hr;
3614}
3615
3616/*****************************************************************************
3617 * IDirectDraw7::DuplicateSurface
3618 *
3619 * Duplicates a surface. The surface memory points to the same memory as
3620 * the original surface, and it's released when the last surface referencing
3621 * it is released. I guess that's beyond Wine's surface management right now
3622 * (Idea: create a new DDraw surface with the same WineD3DSurface. I need a
3623 * test application to implement this)
3624 *
3625 * Params:
3626 * Src: Address of the source surface
3627 * Dest: Address to write the new surface pointer to
3628 *
3629 * Returns:
3630 * See IDirectDraw7::CreateSurface
3631 *
3632 *****************************************************************************/
3635{
3636 struct ddraw_surface *src_surface = unsafe_impl_from_IDirectDrawSurface7(Src);
3637
3638 FIXME("iface %p, src %p, dst %p partial stub!\n", iface, Src, Dest);
3639
3640 /* For now, simply create a new, independent surface */
3641 return IDirectDraw7_CreateSurface(iface, &src_surface->surface_desc, Dest, NULL);
3642}
3643
3644static HRESULT WINAPI ddraw4_DuplicateSurface(IDirectDraw4 *iface, IDirectDrawSurface4 *src,
3645 IDirectDrawSurface4 **dst)
3646{
3648 struct ddraw *ddraw = impl_from_IDirectDraw4(iface);
3649 struct ddraw_surface *dst_impl;
3650 IDirectDrawSurface7 *dst7;
3651 HRESULT hr;
3652
3653 TRACE("iface %p, src %p, dst %p.\n", iface, src, dst);
3654
3656 src_impl ? &src_impl->IDirectDrawSurface7_iface : NULL, &dst7);
3657 if (FAILED(hr))
3658 {
3659 *dst = NULL;
3660 return hr;
3661 }
3662 dst_impl = impl_from_IDirectDrawSurface7(dst7);
3663 *dst = &dst_impl->IDirectDrawSurface4_iface;
3664 IDirectDrawSurface4_AddRef(*dst);
3665 IDirectDrawSurface7_Release(dst7);
3666
3667 return hr;
3668}
3669
3670static HRESULT WINAPI ddraw2_DuplicateSurface(IDirectDraw2 *iface,
3671 IDirectDrawSurface *src, IDirectDrawSurface **dst)
3672{
3674 struct ddraw *ddraw = impl_from_IDirectDraw2(iface);
3675 struct ddraw_surface *dst_impl;
3676 IDirectDrawSurface7 *dst7;
3677 HRESULT hr;
3678
3679 TRACE("iface %p, src %p, dst %p.\n", iface, src, dst);
3680
3682 src_impl ? &src_impl->IDirectDrawSurface7_iface : NULL, &dst7);
3683 if (FAILED(hr))
3684 return hr;
3685 dst_impl = impl_from_IDirectDrawSurface7(dst7);
3686 *dst = &dst_impl->IDirectDrawSurface_iface;
3687 IDirectDrawSurface_AddRef(*dst);
3688 IDirectDrawSurface7_Release(dst7);
3689
3690 return hr;
3691}
3692
3693static HRESULT WINAPI ddraw1_DuplicateSurface(IDirectDraw *iface, IDirectDrawSurface *src,
3694 IDirectDrawSurface **dst)
3695{
3697 struct ddraw *ddraw = impl_from_IDirectDraw(iface);
3698 struct ddraw_surface *dst_impl;
3699 IDirectDrawSurface7 *dst7;
3700 HRESULT hr;
3701
3702 TRACE("iface %p, src %p, dst %p.\n", iface, src, dst);
3703
3705 src_impl ? &src_impl->IDirectDrawSurface7_iface : NULL, &dst7);
3706 if (FAILED(hr))
3707 return hr;
3708 dst_impl = impl_from_IDirectDrawSurface7(dst7);
3709 *dst = &dst_impl->IDirectDrawSurface_iface;
3710 IDirectDrawSurface_AddRef(*dst);
3711 IDirectDrawSurface7_Release(dst7);
3712
3713 return hr;
3714}
3715
3716/*****************************************************************************
3717 * IDirect3D7::EnumDevices
3718 *
3719 * The EnumDevices method for IDirect3D7. It enumerates all supported
3720 * D3D7 devices. Currently the T&L, HAL and RGB devices are enumerated.
3721 *
3722 * Params:
3723 * callback: Function to call for each enumerated device
3724 * context: Pointer to pass back to the app
3725 *
3726 * Returns:
3727 * D3D_OK, or the return value of the GetCaps call
3728 *
3729 *****************************************************************************/
3731{
3732 struct ddraw *ddraw = impl_from_IDirect3D7(iface);
3733 D3DDEVICEDESC7 device_desc7;
3734 DWORD dev_caps;
3735 HRESULT hr;
3736 size_t i;
3737
3738 TRACE("iface %p, callback %p, context %p.\n", iface, callback, context);
3739
3740 if (!callback)
3741 return DDERR_INVALIDPARAMS;
3742
3744
3745 if (FAILED(hr = ddraw_get_d3dcaps(ddraw, &device_desc7)))
3746 {
3748 return hr;
3749 }
3750
3751 dev_caps = device_desc7.dwDevCaps;
3752
3753 for (i = 0; i < ARRAY_SIZE(device_list7); i++)
3754 {
3755 HRESULT ret;
3756
3757 device_desc7.deviceGUID = *device_list7[i].device_guid;
3758 device_desc7.dwDevCaps = dev_caps & ~device_list7[i].remove_caps;
3759
3760 ret = callback(device_list7[i].interface_name, device_list7[i].device_name, &device_desc7, context);
3761 if (ret != DDENUMRET_OK)
3762 {
3763 TRACE("Application cancelled the enumeration.\n");
3765 return D3D_OK;
3766 }
3767 }
3768
3769 TRACE("End of enumeration.\n");
3770
3772
3773 return D3D_OK;
3774}
3775
3776/*****************************************************************************
3777 * IDirect3D3::EnumDevices
3778 *
3779 * Enumerates all supported Direct3DDevice interfaces. This is the
3780 * implementation for Direct3D 1 to Direc3D 3, Version 7 has its own.
3781 *
3782 * Versions 1, 2 and 3
3783 *
3784 * Params:
3785 * callback: Application-provided routine to call for each enumerated device
3786 * Context: Pointer to pass to the callback
3787 *
3788 * Returns:
3789 * D3D_OK on success,
3790 * The result of IDirect3DImpl_GetCaps if it failed
3791 *
3792 *****************************************************************************/
3794{
3795 static CHAR wined3d_description[] = "Wine D3DDevice using WineD3D and OpenGL";
3796
3797 struct ddraw *ddraw = impl_from_IDirect3D3(iface);
3798 D3DDEVICEDESC device_desc1, hal_desc, hel_desc;
3799 D3DDEVICEDESC7 device_desc7;
3800 HRESULT hr;
3801
3802 /* Some games (Motoracer 2 demo) have the bad idea to modify the device
3803 * name string. Let's put the string in a sufficiently sized array in
3804 * writable memory. */
3805 char device_name[50];
3806 strcpy(device_name,"Direct3D HEL");
3807
3808 TRACE("iface %p, callback %p, context %p.\n", iface, callback, context);
3809
3810 if (!callback)
3811 return DDERR_INVALIDPARAMS;
3812
3814
3815 if (FAILED(hr = ddraw_get_d3dcaps(ddraw, &device_desc7)))
3816 {
3818 return hr;
3819 }
3820 ddraw_d3dcaps1_from_7(&device_desc1, &device_desc7);
3821
3822 /* Do I have to enumerate the reference id? Note from old d3d7:
3823 * "It seems that enumerating the reference IID on Direct3D 1 games
3824 * (AvP / Motoracer2) breaks them". So do not enumerate this iid in V1
3825 *
3826 * There's a registry key HKLM\Software\Microsoft\Direct3D\Drivers,
3827 * EnumReference which enables / disables enumerating the reference
3828 * rasterizer. It's a DWORD, 0 means disabled, 2 means enabled. The
3829 * enablerefrast.reg and disablerefrast.reg files in the DirectX 7.0 sdk
3830 * demo directory suggest this.
3831 *
3832 * Some games(GTA 2) seem to use the second enumerated device, so I have
3833 * to enumerate at least 2 devices. So enumerate the reference device to
3834 * have 2 devices.
3835 *
3836 * Other games (Rollcage) tell emulation and hal device apart by certain
3837 * flags. Rollcage expects D3DPTEXTURECAPS_POW2 to be set (yeah, it is a
3838 * limitation flag), and it refuses all devices that have the perspective
3839 * flag set. This way it refuses the emulation device, and HAL devices
3840 * never have POW2 unset in d3d7 on windows. */
3841 if (ddraw->d3dversion != 1)
3842 {
3843 static CHAR reference_description[] = "RGB Direct3D emulation";
3844
3845 TRACE("Enumerating WineD3D D3DDevice interface.\n");
3846 hal_desc = device_desc1;
3847 hel_desc = device_desc1;
3848 /* The rgb device has the pow2 flag set in the hel caps, but not in the hal caps. */
3853 /* RGB, RAMP and MMX devices have a HAL dcmColorModel of 0 */
3854 hal_desc.dcmColorModel = 0;
3855 /* RGB, RAMP and MMX devices cannot report HAL hardware flags */
3856 hal_desc.dwFlags = 0;
3857
3858 hr = callback((GUID *)&IID_IDirect3DRGBDevice, reference_description,
3859 device_name, &hal_desc, &hel_desc, context);
3860 if (hr != D3DENUMRET_OK)
3861 {
3862 TRACE("Application cancelled the enumeration.\n");
3864 return D3D_OK;
3865 }
3866 }
3867
3868 strcpy(device_name,"Direct3D HAL");
3869
3870 TRACE("Enumerating HAL Direct3D device.\n");
3871 hal_desc = device_desc1;
3872 hel_desc = device_desc1;
3873
3874 /* The hal device does not have the pow2 flag set in hel, but in hal. */
3879 /* HAL devices have a HEL dcmColorModel of 0 */
3880 hel_desc.dcmColorModel = 0;
3881
3882 hr = callback((GUID *)&IID_IDirect3DHALDevice, wined3d_description,
3883 device_name, &hal_desc, &hel_desc, context);
3884 if (hr != D3DENUMRET_OK)
3885 {
3886 TRACE("Application cancelled the enumeration.\n");
3888 return D3D_OK;
3889 }
3890
3891 TRACE("End of enumeration.\n");
3892
3894
3895 return D3D_OK;
3896}
3897
3899{
3900 struct ddraw *ddraw = impl_from_IDirect3D2(iface);
3901
3902 TRACE("iface %p, callback %p, context %p.\n", iface, callback, context);
3903
3905}
3906
3908{
3909 struct ddraw *ddraw = impl_from_IDirect3D(iface);
3910
3911 TRACE("iface %p, callback %p, context %p.\n", iface, callback, context);
3912
3914}
3915
3916/*****************************************************************************
3917 * IDirect3D3::CreateLight
3918 *
3919 * Creates an IDirect3DLight interface. This interface is used in
3920 * Direct3D3 or earlier for lighting. In Direct3D7 it has been replaced
3921 * by the DIRECT3DLIGHT7 structure. Wine's Direct3DLight implementation
3922 * uses the IDirect3DDevice7 interface with D3D7 lights.
3923 *
3924 * Versions 1, 2 and 3
3925 *
3926 * Params:
3927 * light: Address to store the new interface pointer
3928 * outer_unknown: Basically for aggregation, but ddraw doesn't support it.
3929 * Must be NULL
3930 *
3931 * Returns:
3932 * D3D_OK on success
3933 * DDERR_OUTOFMEMORY if memory allocation failed
3934 * CLASS_E_NOAGGREGATION if outer_unknown != NULL
3935 *
3936 *****************************************************************************/
3937static HRESULT WINAPI d3d3_CreateLight(IDirect3D3 *iface, IDirect3DLight **light,
3938 IUnknown *outer_unknown)
3939{
3940 struct ddraw *ddraw = impl_from_IDirect3D3(iface);
3941 struct d3d_light *object;
3942
3943 TRACE("iface %p, light %p, outer_unknown %p.\n", iface, light, outer_unknown);
3944
3945 if (outer_unknown)
3946 return CLASS_E_NOAGGREGATION;
3947
3948 if (!(object = heap_alloc_zero(sizeof(*object))))
3949 {
3950 ERR("Failed to allocate light memory.\n");
3951 return DDERR_OUTOFMEMORY;
3952 }
3953
3954 d3d_light_init(object, ddraw);
3955
3956 TRACE("Created light %p.\n", object);
3957 *light = &object->IDirect3DLight_iface;
3958
3959 return D3D_OK;
3960}
3961
3962static HRESULT WINAPI d3d2_CreateLight(IDirect3D2 *iface, IDirect3DLight **light, IUnknown *outer_unknown)
3963{
3964 struct ddraw *ddraw = impl_from_IDirect3D2(iface);
3965
3966 TRACE("iface %p, light %p, outer_unknown %p.\n", iface, light, outer_unknown);
3967
3968 return d3d3_CreateLight(&ddraw->IDirect3D3_iface, light, outer_unknown);
3969}
3970
3971static HRESULT WINAPI d3d1_CreateLight(IDirect3D *iface, IDirect3DLight **light, IUnknown *outer_unknown)
3972{
3973 struct ddraw *ddraw = impl_from_IDirect3D(iface);
3974
3975 TRACE("iface %p, light %p, outer_unknown %p.\n", iface, light, outer_unknown);
3976
3977 return d3d3_CreateLight(&ddraw->IDirect3D3_iface, light, outer_unknown);
3978}
3979
3980/*****************************************************************************
3981 * IDirect3D3::CreateMaterial
3982 *
3983 * Creates an IDirect3DMaterial interface. This interface is used by Direct3D3
3984 * and older versions. The IDirect3DMaterial implementation wraps its
3985 * functionality to IDirect3DDevice7::SetMaterial and friends.
3986 *
3987 * Versions 1, 2 and 3
3988 *
3989 * Params:
3990 * material: Address to store the new interface's pointer to
3991 * outer_unknown: Basically for aggregation, but ddraw doesn't support it.
3992 * Must be NULL
3993 *
3994 * Returns:
3995 * D3D_OK on success
3996 * DDERR_OUTOFMEMORY if memory allocation failed
3997 * CLASS_E_NOAGGREGATION if outer_unknown != NULL
3998 *
3999 *****************************************************************************/
4000static HRESULT WINAPI d3d3_CreateMaterial(IDirect3D3 *iface, IDirect3DMaterial3 **material,
4001 IUnknown *outer_unknown)
4002{
4003 struct ddraw *ddraw = impl_from_IDirect3D3(iface);
4004 struct d3d_material *object;
4005
4006 TRACE("iface %p, material %p, outer_unknown %p.\n", iface, material, outer_unknown);
4007
4008 if (outer_unknown) return CLASS_E_NOAGGREGATION;
4009
4010 object = d3d_material_create(ddraw);
4011 if (!object)
4012 {
4013 ERR("Failed to allocate material memory.\n");
4014 return DDERR_OUTOFMEMORY;
4015 }
4016
4017 TRACE("Created material %p.\n", object);
4018 *material = &object->IDirect3DMaterial3_iface;
4019
4020 return D3D_OK;
4021}
4022
4023static HRESULT WINAPI d3d2_CreateMaterial(IDirect3D2 *iface, IDirect3DMaterial2 **material,
4024 IUnknown *outer_unknown)
4025{
4026 struct ddraw *ddraw = impl_from_IDirect3D2(iface);
4027 struct d3d_material *object;
4028
4029 TRACE("iface %p, material %p, outer_unknown %p.\n", iface, material, outer_unknown);
4030
4031 object = d3d_material_create(ddraw);
4032 if (!object)
4033 {
4034