ReactOS 0.4.16-dev-588-gf07ea94
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#ifdef __REACTOS__
1151#endif
1152 }
1153
1155
1157
1158 switch (hr)
1159 {
1161 default: return hr;
1162 }
1163}
1164
1167{
1168 struct ddraw *ddraw = impl_from_IDirectDraw4(iface);
1169
1170 TRACE("iface %p, width %u, height %u, bpp %u, refresh_rate %u, flags %#x.\n",
1171 iface, width, height, bpp, refresh_rate, flags);
1172
1174}
1175
1176static HRESULT WINAPI ddraw2_SetDisplayMode(IDirectDraw2 *iface,
1177 DWORD width, DWORD height, DWORD bpp, DWORD refresh_rate, DWORD flags)
1178{
1179 struct ddraw *ddraw = impl_from_IDirectDraw2(iface);
1180
1181 TRACE("iface %p, width %u, height %u, bpp %u, refresh_rate %u, flags %#x.\n",
1182 iface, width, height, bpp, refresh_rate, flags);
1183
1185}
1186
1188{
1189 struct ddraw *ddraw = impl_from_IDirectDraw(iface);
1190
1191 TRACE("iface %p, width %u, height %u, bpp %u.\n", iface, width, height, bpp);
1192
1194}
1195
1197{
1198 memset(caps1, 0, sizeof(*caps1));
1199 caps1->dwSize = sizeof(*caps1);
1200 caps1->dwFlags = D3DDD_COLORMODEL
1211 caps1->dcmColorModel = D3DCOLOR_RGB;
1212 caps1->dwDevCaps = caps7->dwDevCaps;
1213 caps1->dtcTransformCaps.dwSize = sizeof(caps1->dtcTransformCaps);
1215 caps1->bClipping = TRUE;
1216 caps1->dlcLightingCaps.dwSize = sizeof(caps1->dlcLightingCaps);
1223 caps1->dpcLineCaps = caps7->dpcLineCaps;
1224 caps1->dpcTriCaps = caps7->dpcTriCaps;
1227 caps1->dwMaxBufferSize = 0;
1228 caps1->dwMaxVertexCount = 65536;
1229 caps1->dwMinTextureWidth = caps7->dwMinTextureWidth;
1230 caps1->dwMinTextureHeight = caps7->dwMinTextureHeight;
1231 caps1->dwMaxTextureWidth = caps7->dwMaxTextureWidth;
1232 caps1->dwMaxTextureHeight = caps7->dwMaxTextureHeight;
1233 caps1->dwMinStippleWidth = 1;
1234 caps1->dwMinStippleHeight = 1;
1235 caps1->dwMaxStippleWidth = 32;
1236 caps1->dwMaxStippleHeight = 32;
1237 caps1->dwMaxTextureRepeat = caps7->dwMaxTextureRepeat;
1239 caps1->dwMaxAnisotropy = caps7->dwMaxAnisotropy;
1240 caps1->dvGuardBandLeft = caps7->dvGuardBandLeft;
1241 caps1->dvGuardBandTop = caps7->dvGuardBandTop;
1242 caps1->dvGuardBandRight = caps7->dvGuardBandRight;
1243 caps1->dvGuardBandBottom = caps7->dvGuardBandBottom;
1244 caps1->dvExtentsAdjust = caps7->dvExtentsAdjust;
1245 caps1->dwStencilCaps = caps7->dwStencilCaps;
1246 caps1->dwFVFCaps = caps7->dwFVFCaps;
1247 caps1->dwTextureOpCaps = caps7->dwTextureOpCaps;
1250}
1251
1253{
1254 WINED3DCAPS wined3d_caps;
1255 HRESULT hr;
1256
1257 TRACE("ddraw %p, caps %p.\n", ddraw, caps);
1258
1259 memset(&wined3d_caps, 0, sizeof(wined3d_caps));
1260
1264 if (FAILED(hr))
1265 {
1266 WARN("Failed to get device caps, hr %#x.\n", hr);
1267 return hr;
1268 }
1269
1270 caps->dwDevCaps = wined3d_caps.DevCaps;
1271 caps->dpcLineCaps.dwMiscCaps = wined3d_caps.PrimitiveMiscCaps;
1272 caps->dpcLineCaps.dwRasterCaps = wined3d_caps.RasterCaps;
1273 caps->dpcLineCaps.dwZCmpCaps = wined3d_caps.ZCmpCaps;
1274 caps->dpcLineCaps.dwSrcBlendCaps = wined3d_caps.SrcBlendCaps;
1275 caps->dpcLineCaps.dwDestBlendCaps = wined3d_caps.DestBlendCaps;
1276 caps->dpcLineCaps.dwAlphaCmpCaps = wined3d_caps.AlphaCmpCaps;
1277 caps->dpcLineCaps.dwShadeCaps = wined3d_caps.ShadeCaps;
1278 caps->dpcLineCaps.dwTextureCaps = wined3d_caps.TextureCaps;
1281
1282 caps->dwMaxTextureWidth = wined3d_caps.MaxTextureWidth;
1283 caps->dwMaxTextureHeight = wined3d_caps.MaxTextureHeight;
1284
1285 caps->dwMaxTextureRepeat = wined3d_caps.MaxTextureRepeat;
1287 caps->dwMaxAnisotropy = wined3d_caps.MaxAnisotropy;
1288 caps->dvMaxVertexW = wined3d_caps.MaxVertexW;
1289
1290 caps->dvGuardBandLeft = wined3d_caps.GuardBandLeft;
1291 caps->dvGuardBandTop = wined3d_caps.GuardBandTop;
1292 caps->dvGuardBandRight = wined3d_caps.GuardBandRight;
1293 caps->dvGuardBandBottom = wined3d_caps.GuardBandBottom;
1294
1295 caps->dvExtentsAdjust = wined3d_caps.ExtentsAdjust;
1296 caps->dwStencilCaps = wined3d_caps.StencilCaps;
1297
1298 caps->dwFVFCaps = wined3d_caps.FVFCaps;
1299 caps->dwTextureOpCaps = wined3d_caps.TextureOpCaps;
1300
1301 caps->dwVertexProcessingCaps = wined3d_caps.VertexProcessingCaps;
1302 caps->dwMaxActiveLights = wined3d_caps.MaxActiveLights;
1303
1304 /* Remove all non-d3d7 caps */
1305 caps->dwDevCaps &= (
1313
1314 caps->dwStencilCaps &= (
1318
1319 /* FVF caps ?*/
1320
1321 caps->dwTextureOpCaps &= (
1330
1331 caps->dwVertexProcessingCaps &= (
1334
1335 caps->dpcLineCaps.dwMiscCaps &= (
1339
1340 caps->dpcLineCaps.dwRasterCaps &= (
1349
1350 caps->dpcLineCaps.dwZCmpCaps &= (
1354
1355 caps->dpcLineCaps.dwSrcBlendCaps &= (
1361
1362 caps->dpcLineCaps.dwDestBlendCaps &= (
1368
1369 caps->dpcLineCaps.dwAlphaCmpCaps &= (
1373
1374 caps->dpcLineCaps.dwShadeCaps &= (
1382
1383 caps->dpcLineCaps.dwTextureCaps &= (
1388
1396
1400
1402 {
1403 /* DirectX7 always has the np2 flag set, no matter what the card
1404 * supports. Some old games (Rollcage) check the caps incorrectly.
1405 * If wined3d supports nonpow2 textures it also has np2 conditional
1406 * support. */
1408 }
1409
1410 /* Fill the missing members, and do some fixup */
1411 caps->dpcLineCaps.dwSize = sizeof(caps->dpcLineCaps);
1420 caps->dpcLineCaps.dwStippleWidth = 32;
1421 caps->dpcLineCaps.dwStippleHeight = 32;
1422 /* Use the same for the TriCaps */
1423 caps->dpcTriCaps = caps->dpcLineCaps;
1424
1427 caps->dwMinTextureWidth = 1;
1428 caps->dwMinTextureHeight = 1;
1429
1430 /* Convert DWORDs safely to WORDs */
1431 caps->wMaxTextureBlendStages = min(wined3d_caps.MaxTextureBlendStages, 0xffff);
1432 caps->wMaxSimultaneousTextures = min(wined3d_caps.MaxSimultaneousTextures, 0xffff);
1434 caps->wMaxVertexBlendMatrices = min(wined3d_caps.MaxVertexBlendMatrices, 0xffff);
1435
1436 caps->deviceGUID = IID_IDirect3DTnLHalDevice;
1437
1438 caps->dwReserved1 = 0;
1439 caps->dwReserved2 = 0;
1440 caps->dwReserved3 = 0;
1441 caps->dwReserved4 = 0;
1442
1443 return DD_OK;
1444}
1445
1447{
1448 DDCAPS *caps = ctx;
1449
1450 switch (format->u1.dwZBufferBitDepth)
1451 {
1452 case 8:
1453 caps->dwZBufferBitDepths |= DDBD_8;
1454 break;
1455 case 16:
1456 caps->dwZBufferBitDepths |= DDBD_16;
1457 break;
1458 case 24:
1459 caps->dwZBufferBitDepths |= DDBD_24;
1460 break;
1461 case 32:
1462 caps->dwZBufferBitDepths |= DDBD_32;
1463 break;
1464 }
1465 return D3DENUMRET_OK;
1466}
1467
1468/*****************************************************************************
1469 * IDirectDraw7::GetCaps
1470 *
1471 * Returns the drives capabilities
1472 *
1473 * Used for version 1, 2, 4 and 7
1474 *
1475 * Params:
1476 * DriverCaps: Structure to write the Hardware accelerated caps to
1477 * HelCaps: Structure to write the emulation caps to
1478 *
1479 * Returns
1480 * This implementation returns DD_OK only
1481 *
1482 *****************************************************************************/
1483static HRESULT WINAPI ddraw7_GetCaps(IDirectDraw7 *iface, DDCAPS *DriverCaps, DDCAPS *HELCaps)
1484{
1485 struct ddraw *ddraw = impl_from_IDirectDraw7(iface);
1486 DDCAPS caps;
1487 WINED3DCAPS winecaps;
1488 HRESULT hr;
1489 DDSCAPS2 ddscaps = {0, 0, 0, {0}};
1490
1491 TRACE("iface %p, driver_caps %p, hel_caps %p.\n", iface, DriverCaps, HELCaps);
1492
1493 /* One structure must be != NULL */
1494 if (!DriverCaps && !HELCaps)
1495 {
1496 WARN("Invalid parameters.\n");
1497 return DDERR_INVALIDPARAMS;
1498 }
1499
1500 memset(&caps, 0, sizeof(caps));
1501 memset(&winecaps, 0, sizeof(winecaps));
1502 caps.dwSize = sizeof(caps);
1503
1506 if (FAILED(hr))
1507 {
1508 WARN("Failed to get device caps, %#x.\n", hr);
1510 return hr;
1511 }
1512
1513 hr = IDirectDraw7_GetAvailableVidMem(iface, &ddscaps, &caps.dwVidMemTotal, &caps.dwVidMemFree);
1514 if (FAILED(hr))
1515 {
1516 WARN("IDirectDraw7::GetAvailableVidMem failed\n");
1518 return hr;
1519 }
1520
1521 hr = IDirectDraw7_GetFourCCCodes(iface, &caps.dwNumFourCCCodes, NULL);
1523 if (FAILED(hr))
1524 {
1525 WARN("IDirectDraw7::GetFourCCCodes failed\n");
1526 return hr;
1527 }
1528
1529 caps.dwCaps = winecaps.ddraw_caps.caps;
1530 caps.dwCaps2 = winecaps.ddraw_caps.caps2;
1531 caps.dwCKeyCaps = winecaps.ddraw_caps.color_key_caps;
1532 caps.dwFXCaps = winecaps.ddraw_caps.fx_caps;
1533 caps.dwPalCaps = DDPCAPS_8BIT | DDPCAPS_PRIMARYSURFACE;
1534 caps.ddsCaps.dwCaps = winecaps.ddraw_caps.dds_caps;
1535 caps.dwSVBCaps = winecaps.ddraw_caps.svb_caps;
1536 caps.dwSVBCKeyCaps = winecaps.ddraw_caps.svb_color_key_caps;
1537 caps.dwSVBFXCaps = winecaps.ddraw_caps.svb_fx_caps;
1538 caps.dwVSBCaps = winecaps.ddraw_caps.vsb_caps;
1539 caps.dwVSBCKeyCaps = winecaps.ddraw_caps.vsb_color_key_caps;
1540 caps.dwVSBFXCaps = winecaps.ddraw_caps.vsb_fx_caps;
1541 caps.dwSSBCaps = winecaps.ddraw_caps.ssb_caps;
1542 caps.dwSSBCKeyCaps = winecaps.ddraw_caps.ssb_color_key_caps;
1543 caps.dwSSBFXCaps = winecaps.ddraw_caps.ssb_fx_caps;
1544
1545 caps.dwCaps |= DDCAPS_ALIGNSTRIDE;
1546 caps.dwAlignStrideAlign = DDRAW_STRIDE_ALIGNMENT;
1547
1548 caps.ddsOldCaps.dwCaps = caps.ddsCaps.dwCaps;
1549
1550 IDirect3D7_EnumZBufferFormats(&ddraw->IDirect3D7_iface, &IID_IDirect3DHALDevice, enum_zbuffer, &caps);
1551
1552 if(DriverCaps)
1553 {
1554 DD_STRUCT_COPY_BYSIZE(DriverCaps, &caps);
1555 if (TRACE_ON(ddraw))
1556 {
1557 TRACE("Driver Caps :\n");
1558 DDRAW_dump_DDCAPS(DriverCaps);
1559 }
1560
1561 }
1562 if(HELCaps)
1563 {
1564 DD_STRUCT_COPY_BYSIZE(HELCaps, &caps);
1565 if (TRACE_ON(ddraw))
1566 {
1567 TRACE("HEL Caps :\n");
1568 DDRAW_dump_DDCAPS(HELCaps);
1569 }
1570 }
1571
1572 return DD_OK;
1573}
1574
1575static HRESULT WINAPI ddraw4_GetCaps(IDirectDraw4 *iface, DDCAPS *driver_caps, DDCAPS *hel_caps)
1576{
1577 struct ddraw *ddraw = impl_from_IDirectDraw4(iface);
1578
1579 TRACE("iface %p, driver_caps %p, hel_caps %p.\n", iface, driver_caps, hel_caps);
1580
1581 return ddraw7_GetCaps(&ddraw->IDirectDraw7_iface, driver_caps, hel_caps);
1582}
1583
1584static HRESULT WINAPI ddraw2_GetCaps(IDirectDraw2 *iface, DDCAPS *driver_caps, DDCAPS *hel_caps)
1585{
1586 struct ddraw *ddraw = impl_from_IDirectDraw2(iface);
1587
1588 TRACE("iface %p, driver_caps %p, hel_caps %p.\n", iface, driver_caps, hel_caps);
1589
1590 return ddraw7_GetCaps(&ddraw->IDirectDraw7_iface, driver_caps, hel_caps);
1591}
1592
1593static HRESULT WINAPI ddraw1_GetCaps(IDirectDraw *iface, DDCAPS *driver_caps, DDCAPS *hel_caps)
1594{
1595 struct ddraw *ddraw = impl_from_IDirectDraw(iface);
1596
1597 TRACE("iface %p, driver_caps %p, hel_caps %p.\n", iface, driver_caps, hel_caps);
1598
1599 return ddraw7_GetCaps(&ddraw->IDirectDraw7_iface, driver_caps, hel_caps);
1600}
1601
1602/*****************************************************************************
1603 * IDirectDraw7::Compact
1604 *
1605 * No idea what it does, MSDN says it's not implemented.
1606 *
1607 * Returns
1608 * DD_OK, but this is unchecked
1609 *
1610 *****************************************************************************/
1612{
1613 TRACE("iface %p.\n", iface);
1614
1615 return DD_OK;
1616}
1617
1618static HRESULT WINAPI ddraw4_Compact(IDirectDraw4 *iface)
1619{
1620 struct ddraw *ddraw = impl_from_IDirectDraw4(iface);
1621
1622 TRACE("iface %p.\n", iface);
1623
1625}
1626
1627static HRESULT WINAPI ddraw2_Compact(IDirectDraw2 *iface)
1628{
1629 struct ddraw *ddraw = impl_from_IDirectDraw2(iface);
1630
1631 TRACE("iface %p.\n", iface);
1632
1634}
1635
1636static HRESULT WINAPI ddraw1_Compact(IDirectDraw *iface)
1637{
1638 struct ddraw *ddraw = impl_from_IDirectDraw(iface);
1639
1640 TRACE("iface %p.\n", iface);
1641
1643}
1644
1645/*****************************************************************************
1646 * IDirectDraw7::GetDisplayMode
1647 *
1648 * Returns information about the current display mode
1649 *
1650 * Exists in versions 1, 2, 4 and 7
1651 *
1652 * Params:
1653 * DDSD: Address of a surface description structure to write the info to
1654 *
1655 * Returns
1656 * DD_OK
1657 *
1658 *****************************************************************************/
1660{
1661 struct ddraw *ddraw = impl_from_IDirectDraw7(iface);
1663 HRESULT hr;
1664
1665 TRACE("iface %p, surface_desc %p.\n", iface, DDSD);
1666
1667 /* This seems sane */
1668 if (!DDSD || (DDSD->dwSize != sizeof(DDSURFACEDESC) && DDSD->dwSize != sizeof(DDSURFACEDESC2)))
1669 return DDERR_INVALIDPARAMS;
1670
1672
1674 {
1675 ERR("Failed to get display mode, hr %#x.\n", hr);
1677 return hr;
1678 }
1679
1680 memset(DDSD, 0, DDSD->dwSize);
1681 DDSD->dwSize = sizeof(*DDSD);
1683 DDSD->dwWidth = mode.width;
1684 DDSD->dwHeight = mode.height;
1685 DDSD->u2.dwRefreshRate = 60;
1686 DDSD->ddsCaps.dwCaps = 0;
1687 DDSD->u4.ddpfPixelFormat.dwSize = sizeof(DDSD->u4.ddpfPixelFormat);
1689 DDSD->u1.lPitch = mode.width * DDSD->u4.ddpfPixelFormat.u1.dwRGBBitCount / 8;
1690
1691 if(TRACE_ON(ddraw))
1692 {
1693 TRACE("Returning surface desc :\n");
1695 }
1696
1698
1699 return DD_OK;
1700}
1701
1702static HRESULT WINAPI ddraw4_GetDisplayMode(IDirectDraw4 *iface, DDSURFACEDESC2 *surface_desc)
1703{
1704 struct ddraw *ddraw = impl_from_IDirectDraw4(iface);
1705
1706 TRACE("iface %p, surface_desc %p.\n", iface, surface_desc);
1707
1708 return ddraw7_GetDisplayMode(&ddraw->IDirectDraw7_iface, surface_desc);
1709}
1710
1711static HRESULT WINAPI ddraw2_GetDisplayMode(IDirectDraw2 *iface, DDSURFACEDESC *surface_desc)
1712{
1713 struct ddraw *ddraw = impl_from_IDirectDraw2(iface);
1714 HRESULT hr;
1715
1716 TRACE("iface %p, surface_desc %p.\n", iface, surface_desc);
1717
1719 if (SUCCEEDED(hr)) surface_desc->dwSize = sizeof(*surface_desc);
1720 return hr;
1721}
1722
1723static HRESULT WINAPI ddraw1_GetDisplayMode(IDirectDraw *iface, DDSURFACEDESC *surface_desc)
1724{
1725 struct ddraw *ddraw = impl_from_IDirectDraw(iface);
1726 HRESULT hr;
1727
1728 TRACE("iface %p, surface_desc %p.\n", iface, surface_desc);
1729
1731 if (SUCCEEDED(hr)) surface_desc->dwSize = sizeof(*surface_desc);
1732 return hr;
1733}
1734
1735/*****************************************************************************
1736 * IDirectDraw7::GetFourCCCodes
1737 *
1738 * Returns an array of supported FourCC codes.
1739 *
1740 * Exists in versions 1, 2, 4 and 7
1741 *
1742 * Params:
1743 * NumCodes: Contains the number of Codes that Codes can carry. Returns the number
1744 * of enumerated codes
1745 * Codes: Pointer to an array of DWORDs where the supported codes are written
1746 * to
1747 *
1748 * Returns
1749 * Always returns DD_OK, as it's a stub for now
1750 *
1751 *****************************************************************************/
1753{
1754 struct ddraw *ddraw = impl_from_IDirectDraw7(iface);
1755 static const enum wined3d_format_id formats[] =
1756 {
1760 };
1762 DWORD count = 0, i, outsize;
1763 HRESULT hr;
1764
1765 TRACE("iface %p, codes_count %p, codes %p.\n", iface, NumCodes, Codes);
1766
1768 {
1769 ERR("Failed to get display mode, hr %#x.\n", hr);
1770 return hr;
1771 }
1772
1773 outsize = NumCodes && Codes ? *NumCodes : 0;
1774
1775 for (i = 0; i < ARRAY_SIZE(formats); ++i)
1776 {
1778 mode.format_id, 0, WINED3D_RTYPE_TEXTURE_2D, formats[i])))
1779 {
1780 if (count < outsize)
1781 Codes[count] = formats[i];
1782 ++count;
1783 }
1784 }
1785 if(NumCodes) {
1786 TRACE("Returning %u FourCC codes\n", count);
1787 *NumCodes = count;
1788 }
1789
1790 return DD_OK;
1791}
1792
1793static HRESULT WINAPI ddraw4_GetFourCCCodes(IDirectDraw4 *iface, DWORD *codes_count, DWORD *codes)
1794{
1795 struct ddraw *ddraw = impl_from_IDirectDraw4(iface);
1796
1797 TRACE("iface %p, codes_count %p, codes %p.\n", iface, codes_count, codes);
1798
1799 return ddraw7_GetFourCCCodes(&ddraw->IDirectDraw7_iface, codes_count, codes);
1800}
1801
1802static HRESULT WINAPI ddraw2_GetFourCCCodes(IDirectDraw2 *iface, DWORD *codes_count, DWORD *codes)
1803{
1804 struct ddraw *ddraw = impl_from_IDirectDraw2(iface);
1805
1806 TRACE("iface %p, codes_count %p, codes %p.\n", iface, codes_count, codes);
1807
1808 return ddraw7_GetFourCCCodes(&ddraw->IDirectDraw7_iface, codes_count, codes);
1809}
1810
1811static HRESULT WINAPI ddraw1_GetFourCCCodes(IDirectDraw *iface, DWORD *codes_count, DWORD *codes)
1812{
1813 struct ddraw *ddraw = impl_from_IDirectDraw(iface);
1814
1815 TRACE("iface %p, codes_count %p, codes %p.\n", iface, codes_count, codes);
1816
1817 return ddraw7_GetFourCCCodes(&ddraw->IDirectDraw7_iface, codes_count, codes);
1818}
1819
1821{
1822 struct ddraw *ddraw = impl_from_IDirectDraw7(iface);
1824 HRESULT hr;
1825
1826 TRACE("iface %p, frequency %p.\n", iface, frequency);
1827
1831 if (FAILED(hr))
1832 {
1833 WARN("Failed to get display mode, hr %#x.\n", hr);
1834 return hr;
1835 }
1836
1837 *frequency = mode.refresh_rate;
1838
1839 return DD_OK;
1840}
1841
1843{
1844 struct ddraw *ddraw = impl_from_IDirectDraw4(iface);
1845
1846 TRACE("iface %p, frequency %p.\n", iface, frequency);
1847
1849}
1850
1852{
1853 struct ddraw *ddraw = impl_from_IDirectDraw2(iface);
1854
1855 TRACE("iface %p, frequency %p.\n", iface, frequency);
1856
1858}
1859
1861{
1862 struct ddraw *ddraw = impl_from_IDirectDraw(iface);
1863
1864 TRACE("iface %p, frequency %p.\n", iface, frequency);
1865
1867}
1868
1870{
1871 struct ddraw *ddraw = impl_from_IDirectDraw7(iface);
1872 struct wined3d_raster_status raster_status;
1873 HRESULT hr;
1874
1875 TRACE("iface %p, status %p.\n", iface, status);
1876
1877 if(!status)
1878 return DDERR_INVALIDPARAMS;
1879
1883 if (FAILED(hr))
1884 {
1885 WARN("Failed to get raster status, hr %#x.\n", hr);
1886 return hr;
1887 }
1888
1889 *status = raster_status.in_vblank;
1890
1891 return DD_OK;
1892}
1893
1895{
1896 struct ddraw *ddraw = impl_from_IDirectDraw4(iface);
1897
1898 TRACE("iface %p, status %p.\n", iface, status);
1899
1901}
1902
1904{
1905 struct ddraw *ddraw = impl_from_IDirectDraw2(iface);
1906
1907 TRACE("iface %p, status %p.\n", iface, status);
1908
1910}
1911
1913{
1914 struct ddraw *ddraw = impl_from_IDirectDraw(iface);
1915
1916 TRACE("iface %p, status %p.\n", iface, status);
1917
1919}
1920
1921/*****************************************************************************
1922 * IDirectDraw7::GetAvailableVidMem
1923 *
1924 * Returns the total and free video memory
1925 *
1926 * Params:
1927 * caps: Specifies the memory type asked for
1928 * total: Pointer to a DWORD to be filled with the total memory
1929 * free: Pointer to a DWORD to be filled with the free memory
1930 *
1931 * Returns
1932 * DD_OK on success
1933 * DDERR_INVALIDPARAMS if free and total are NULL
1934 *
1935 *****************************************************************************/
1937 DWORD *free)
1938{
1939 unsigned int framebuffer_size, total_vidmem, free_vidmem;
1940 struct ddraw *ddraw = impl_from_IDirectDraw7(iface);
1942 HRESULT hr = DD_OK;
1943
1944 TRACE("iface %p, caps %p, total %p, free %p.\n", iface, caps, total, free);
1945
1946 if (!total && !free)
1947 return DDERR_INVALIDPARAMS;
1948
1949 if (TRACE_ON(ddraw))
1950 {
1951 TRACE("Asked for memory with description: ");
1952 DDRAW_dump_DDSCAPS2(caps);
1953 }
1955
1956 /* Todo: System memory vs local video memory vs non-local video memory
1957 * The MSDN also mentions differences between texture memory and other
1958 * resources, but that's not important
1959 */
1960
1961 /* Some applications (e.g. 3DMark 2000) assume that the reported amount of
1962 * video memory doesn't include the memory used by the default framebuffer.
1963 */
1965 {
1966 WARN("Failed to get display mode, hr %#x.\n", hr);
1968 return hr;
1969 }
1971 mode.format_id, mode.width);
1972 framebuffer_size *= mode.height;
1973
1974 if (free)
1975 {
1977 *free = framebuffer_size > free_vidmem ? 0 : free_vidmem - framebuffer_size;
1978 TRACE("Free video memory %#x.\n", *free);
1979 }
1980
1981 if (total)
1982 {
1983 struct wined3d_adapter_identifier desc = {0};
1984
1986 total_vidmem = min(UINT_MAX, desc.video_memory);
1987 *total = framebuffer_size > total_vidmem ? 0 : total_vidmem - framebuffer_size;
1988 TRACE("Total video memory %#x.\n", *total);
1989 }
1990
1992
1993 return hr;
1994}
1995
1996static HRESULT WINAPI ddraw4_GetAvailableVidMem(IDirectDraw4 *iface,
1997 DDSCAPS2 *caps, DWORD *total, DWORD *free)
1998{
1999 struct ddraw *ddraw = impl_from_IDirectDraw4(iface);
2000
2001 TRACE("iface %p, caps %p, total %p, free %p.\n", iface, caps, total, free);
2002
2004}
2005
2006static HRESULT WINAPI ddraw2_GetAvailableVidMem(IDirectDraw2 *iface,
2007 DDSCAPS *caps, DWORD *total, DWORD *free)
2008{
2009 struct ddraw *ddraw = impl_from_IDirectDraw2(iface);
2010 DDSCAPS2 caps2;
2011
2012 TRACE("iface %p, caps %p, total %p, free %p.\n", iface, caps, total, free);
2013
2014 DDRAW_Convert_DDSCAPS_1_To_2(caps, &caps2);
2016}
2017
2018/*****************************************************************************
2019 * IDirectDraw7::Initialize
2020 *
2021 * Initializes a DirectDraw interface.
2022 *
2023 * Params:
2024 * GUID: Interface identifier. Well, don't know what this is really good
2025 * for
2026 *
2027 * Returns
2028 * Returns DD_OK on the first call,
2029 * DDERR_ALREADYINITIALIZED on repeated calls
2030 *
2031 *****************************************************************************/
2033{
2034 struct ddraw *ddraw = impl_from_IDirectDraw7(iface);
2035
2036 TRACE("iface %p, guid %s.\n", iface, debugstr_guid(guid));
2037
2040
2041 /* FIXME: To properly take the GUID into account we should call
2042 * ddraw_init() here instead of in DDRAW_Create(). */
2043 if (guid)
2044 FIXME("Ignoring guid %s.\n", debugstr_guid(guid));
2045
2047 return DD_OK;
2048}
2049
2050static HRESULT WINAPI ddraw4_Initialize(IDirectDraw4 *iface, GUID *guid)
2051{
2052 struct ddraw *ddraw = impl_from_IDirectDraw4(iface);
2053
2054 TRACE("iface %p, guid %s.\n", iface, debugstr_guid(guid));
2055
2057}
2058
2059static HRESULT WINAPI ddraw2_Initialize(IDirectDraw2 *iface, GUID *guid)
2060{
2061 struct ddraw *ddraw = impl_from_IDirectDraw2(iface);
2062
2063 TRACE("iface %p, guid %s.\n", iface, debugstr_guid(guid));
2064
2066}
2067
2068static HRESULT WINAPI ddraw1_Initialize(IDirectDraw *iface, GUID *guid)
2069{
2070 struct ddraw *ddraw = impl_from_IDirectDraw(iface);
2071
2072 TRACE("iface %p, guid %s.\n", iface, debugstr_guid(guid));
2073
2075}
2076
2077static HRESULT WINAPI d3d1_Initialize(IDirect3D *iface, REFIID riid)
2078{
2079 TRACE("iface %p, riid %s.\n", iface, debugstr_guid(riid));
2080
2082}
2083
2084/*****************************************************************************
2085 * IDirectDraw7::FlipToGDISurface
2086 *
2087 * "Makes the surface that the GDI writes to the primary surface"
2088 * Looks like some windows specific thing we don't have to care about.
2089 * According to MSDN it permits GDI dialog boxes in FULLSCREEN mode. Good to
2090 * show error boxes ;)
2091 * Well, just return DD_OK.
2092 *
2093 * Returns:
2094 * Always returns DD_OK
2095 *
2096 *****************************************************************************/
2098{
2099 struct ddraw *ddraw = impl_from_IDirectDraw7(iface);
2100 IDirectDrawSurface7 *gdi_surface;
2101 struct ddraw_surface *gdi_impl;
2102 HRESULT hr;
2103
2104 TRACE("iface %p.\n", iface);
2105
2107
2108 if (FAILED(hr = IDirectDraw7_GetGDISurface(iface, &gdi_surface)))
2109 {
2110 WARN("Failed to retrieve GDI surface, hr %#x.\n", hr);
2112 return hr;
2113 }
2114
2115 gdi_impl = impl_from_IDirectDrawSurface7(gdi_surface);
2117 hr = DD_OK;
2118 else
2119 hr = IDirectDrawSurface7_Flip(&ddraw->primary->IDirectDrawSurface7_iface, gdi_surface, DDFLIP_WAIT);
2120 IDirectDrawSurface7_Release(gdi_surface);
2121
2123
2124 return hr;
2125}
2126
2127static HRESULT WINAPI ddraw4_FlipToGDISurface(IDirectDraw4 *iface)
2128{
2129 struct ddraw *ddraw = impl_from_IDirectDraw4(iface);
2130
2131 TRACE("iface %p.\n", iface);
2132
2134}
2135
2136static HRESULT WINAPI ddraw2_FlipToGDISurface(IDirectDraw2 *iface)
2137{
2138 struct ddraw *ddraw = impl_from_IDirectDraw2(iface);
2139
2140 TRACE("iface %p.\n", iface);
2141
2143}
2144
2145static HRESULT WINAPI ddraw1_FlipToGDISurface(IDirectDraw *iface)
2146{
2147 struct ddraw *ddraw = impl_from_IDirectDraw(iface);
2148
2149 TRACE("iface %p.\n", iface);
2150
2152}
2153
2154/*****************************************************************************
2155 * IDirectDraw7::WaitForVerticalBlank
2156 *
2157 * This method allows applications to get in sync with the vertical blank
2158 * interval.
2159 * The wormhole demo in the DirectX 7 sdk uses this call, and it doesn't
2160 * redraw the screen, most likely because of this stub
2161 *
2162 * Parameters:
2163 * Flags: one of DDWAITVB_BLOCKBEGIN, DDWAITVB_BLOCKBEGINEVENT
2164 * or DDWAITVB_BLOCKEND
2165 * h: Not used, according to MSDN
2166 *
2167 * Returns:
2168 * Always returns DD_OK
2169 *
2170 *****************************************************************************/
2172{
2173 static BOOL hide;
2174
2175 TRACE("iface %p, flags %#x, event %p.\n", iface, Flags, event);
2176
2177 /* This function is called often, so print the fixme only once */
2178 if(!hide)
2179 {
2180 FIXME("iface %p, flags %#x, event %p stub!\n", iface, Flags, event);
2181 hide = TRUE;
2182 }
2183
2184 /* MSDN says DDWAITVB_BLOCKBEGINEVENT is not supported */
2186 return DDERR_UNSUPPORTED; /* unchecked */
2187
2188 return DD_OK;
2189}
2190
2192{
2193 struct ddraw *ddraw = impl_from_IDirectDraw4(iface);
2194
2195 TRACE("iface %p, flags %#x, event %p.\n", iface, flags, event);
2196
2198}
2199
2201{
2202 struct ddraw *ddraw = impl_from_IDirectDraw2(iface);
2203
2204 TRACE("iface %p, flags %#x, event %p.\n", iface, flags, event);
2205
2207}
2208
2210{
2211 struct ddraw *ddraw = impl_from_IDirectDraw(iface);
2212
2213 TRACE("iface %p, flags %#x, event %p.\n", iface, flags, event);
2214
2216}
2217
2219{
2220 struct ddraw *ddraw = impl_from_IDirectDraw7(iface);
2221 struct wined3d_raster_status raster_status;
2222 HRESULT hr;
2223
2224 TRACE("iface %p, line %p.\n", iface, Scanline);
2225
2229 if (FAILED(hr))
2230 {
2231 WARN("Failed to get raster status, hr %#x.\n", hr);
2232 return hr;
2233 }
2234
2235 *Scanline = raster_status.scan_line;
2236
2237 if (raster_status.in_vblank)
2239
2240 return DD_OK;
2241}
2242
2243static HRESULT WINAPI ddraw4_GetScanLine(IDirectDraw4 *iface, DWORD *line)
2244{
2245 struct ddraw *ddraw = impl_from_IDirectDraw4(iface);
2246
2247 TRACE("iface %p, line %p.\n", iface, line);
2248
2250}
2251
2252static HRESULT WINAPI ddraw2_GetScanLine(IDirectDraw2 *iface, DWORD *line)
2253{
2254 struct ddraw *ddraw = impl_from_IDirectDraw2(iface);
2255
2256 TRACE("iface %p, line %p.\n", iface, line);
2257
2259}
2260
2261static HRESULT WINAPI ddraw1_GetScanLine(IDirectDraw *iface, DWORD *line)
2262{
2263 struct ddraw *ddraw = impl_from_IDirectDraw(iface);
2264
2265 TRACE("iface %p, line %p.\n", iface, line);
2266
2268}
2269
2271{
2272 struct ddraw *ddraw = impl_from_IDirectDraw7(iface);
2273
2274 TRACE("iface %p.\n", iface);
2275
2277}
2278
2279static HRESULT WINAPI ddraw4_TestCooperativeLevel(IDirectDraw4 *iface)
2280{
2281 struct ddraw *ddraw = impl_from_IDirectDraw4(iface);
2282
2283 TRACE("iface %p.\n", iface);
2284
2286}
2287
2288/*****************************************************************************
2289 * IDirectDraw7::GetGDISurface
2290 *
2291 * Returns the surface that GDI is treating as the primary surface.
2292 * For Wine this is the front buffer
2293 *
2294 * Params:
2295 * GDISurface: Address to write the surface pointer to
2296 *
2297 * Returns:
2298 * DD_OK if the surface was found
2299 * DDERR_NOTFOUND if the GDI surface wasn't found
2300 *
2301 *****************************************************************************/
2303{
2304 struct ddraw *ddraw = impl_from_IDirectDraw7(iface);
2305
2306 TRACE("iface %p, surface %p.\n", iface, GDISurface);
2307
2309
2310 if (!(*GDISurface = &ddraw->primary->IDirectDrawSurface7_iface))
2311 {
2312 WARN("Primary not created yet.\n");
2314 return DDERR_NOTFOUND;
2315 }
2316 IDirectDrawSurface7_AddRef(*GDISurface);
2317
2319
2320 return DD_OK;
2321}
2322
2323static HRESULT WINAPI ddraw4_GetGDISurface(IDirectDraw4 *iface, IDirectDrawSurface4 **surface)
2324{
2325 struct ddraw *ddraw = impl_from_IDirectDraw4(iface);
2326 struct ddraw_surface *surface_impl;
2327 IDirectDrawSurface7 *surface7;
2328 HRESULT hr;
2329
2330 TRACE("iface %p, surface %p.\n", iface, surface);
2331
2333 if (FAILED(hr))
2334 {
2335 *surface = NULL;
2336 return hr;
2337 }
2338 surface_impl = impl_from_IDirectDrawSurface7(surface7);
2339 *surface = &surface_impl->IDirectDrawSurface4_iface;
2340 IDirectDrawSurface4_AddRef(*surface);
2341 IDirectDrawSurface7_Release(surface7);
2342
2343 return hr;
2344}
2345
2346static HRESULT WINAPI ddraw2_GetGDISurface(IDirectDraw2 *iface, IDirectDrawSurface **surface)
2347{
2348 struct ddraw *ddraw = impl_from_IDirectDraw2(iface);
2349 struct ddraw_surface *surface_impl;
2350 IDirectDrawSurface7 *surface7;
2351 HRESULT hr;
2352
2353 TRACE("iface %p, surface %p.\n", iface, surface);
2354
2356 if (FAILED(hr))
2357 {
2358 *surface = NULL;
2359 return hr;
2360 }
2361 surface_impl = impl_from_IDirectDrawSurface7(surface7);
2362 *surface = &surface_impl->IDirectDrawSurface_iface;
2363 IDirectDrawSurface_AddRef(*surface);
2364 IDirectDrawSurface7_Release(surface7);
2365
2366 return hr;
2367}
2368
2369static HRESULT WINAPI ddraw1_GetGDISurface(IDirectDraw *iface, IDirectDrawSurface **surface)
2370{
2371 struct ddraw *ddraw = impl_from_IDirectDraw(iface);
2372 struct ddraw_surface *surface_impl;
2373 IDirectDrawSurface7 *surface7;
2374 HRESULT hr;
2375
2376 TRACE("iface %p, surface %p.\n", iface, surface);
2377
2379 if (FAILED(hr))
2380 {
2381 *surface = NULL;
2382 return hr;
2383 }
2384 surface_impl = impl_from_IDirectDrawSurface7(surface7);
2385 *surface = &surface_impl->IDirectDrawSurface_iface;
2386 IDirectDrawSurface_AddRef(*surface);
2387 IDirectDrawSurface7_Release(surface7);
2388
2389 return hr;
2390}
2391
2393{
2395 void *context;
2396};
2397
2399{
2400 struct displaymodescallback_context *cbcontext = context;
2402
2403 DDSD2_to_DDSD(surface_desc, &desc);
2404 return cbcontext->func(&desc, cbcontext->context);
2405}
2406
2407/*****************************************************************************
2408 * IDirectDraw7::EnumDisplayModes
2409 *
2410 * Enumerates the supported Display modes. The modes can be filtered with
2411 * the DDSD parameter.
2412 *
2413 * Params:
2414 * Flags: can be DDEDM_REFRESHRATES and DDEDM_STANDARDVGAMODES. For old ddraw
2415 * versions (3 and older?) this is reserved and must be 0.
2416 * DDSD: Surface description to filter the modes
2417 * Context: Pointer passed back to the callback function
2418 * cb: Application-provided callback function
2419 *
2420 * Returns:
2421 * DD_OK on success
2422 * DDERR_INVALIDPARAMS if the callback wasn't set
2423 *
2424 *****************************************************************************/
2427{
2428 struct ddraw *ddraw = impl_from_IDirectDraw7(iface);
2429 struct wined3d_display_mode *enum_modes = NULL;
2431 unsigned int modenum, fmt;
2432 DDSURFACEDESC2 callback_sd;
2433 unsigned enum_mode_count = 0, enum_mode_array_size = 16;
2435
2436 static const enum wined3d_format_id checkFormatList[] =
2437 {
2441 };
2442
2443 TRACE("iface %p, flags %#x, surface_desc %p, context %p, callback %p.\n",
2444 iface, Flags, DDSD, Context, cb);
2445
2446 if (!cb)
2447 return DDERR_INVALIDPARAMS;
2448
2449 if (!(enum_modes = heap_alloc(enum_mode_array_size * sizeof(*enum_modes))))
2450 return DDERR_OUTOFMEMORY;
2451
2453
2454 pixelformat.dwSize = sizeof(pixelformat);
2455 for(fmt = 0; fmt < ARRAY_SIZE(checkFormatList); fmt++)
2456 {
2457 modenum = 0;
2460 {
2461 BOOL found = FALSE;
2462 unsigned i;
2463
2465 if (DDSD)
2466 {
2467 if (DDSD->dwFlags & DDSD_WIDTH && mode.width != DDSD->dwWidth)
2468 continue;
2469 if (DDSD->dwFlags & DDSD_HEIGHT && mode.height != DDSD->dwHeight)
2470 continue;
2471 if (DDSD->dwFlags & DDSD_REFRESHRATE && mode.refresh_rate != DDSD->u2.dwRefreshRate)
2472 continue;
2473 if (DDSD->dwFlags & DDSD_PIXELFORMAT
2474 && pixelformat.u1.dwRGBBitCount != DDSD->u4.ddpfPixelFormat.u1.dwRGBBitCount)
2475 continue;
2476 }
2477
2478 /* DX docs state EnumDisplayMode should return only unique modes */
2479 for (i = 0; i < enum_mode_count; i++)
2480 {
2481 if (enum_modes[i].width == mode.width && enum_modes[i].height == mode.height
2482 && enum_modes[i].format_id == mode.format_id
2483 && (enum_modes[i].refresh_rate == mode.refresh_rate || !(Flags & DDEDM_REFRESHRATES)))
2484 {
2485 found = TRUE;
2486 break;
2487 }
2488 }
2489 if(found) continue;
2490
2491 memset(&callback_sd, 0, sizeof(callback_sd));
2492 callback_sd.dwSize = sizeof(callback_sd);
2493 callback_sd.u4.ddpfPixelFormat.dwSize = sizeof(DDPIXELFORMAT);
2494
2497 callback_sd.u2.dwRefreshRate = mode.refresh_rate;
2498
2499 callback_sd.dwWidth = mode.width;
2500 callback_sd.dwHeight = mode.height;
2501
2502 callback_sd.u4.ddpfPixelFormat=pixelformat;
2503
2504 /* Calc pitch and DWORD align like MSDN says */
2505 callback_sd.u1.lPitch = (callback_sd.u4.ddpfPixelFormat.u1.dwRGBBitCount / 8) * mode.width;
2506 callback_sd.u1.lPitch = (callback_sd.u1.lPitch + 3) & ~3;
2507
2508 TRACE("Enumerating %dx%dx%d @%d\n", callback_sd.dwWidth, callback_sd.dwHeight, callback_sd.u4.ddpfPixelFormat.u1.dwRGBBitCount,
2509 callback_sd.u2.dwRefreshRate);
2510
2511 if(cb(&callback_sd, Context) == DDENUMRET_CANCEL)
2512 {
2513 TRACE("Application asked to terminate the enumeration\n");
2514 heap_free(enum_modes);
2516 return DD_OK;
2517 }
2518
2519 if (enum_mode_count == enum_mode_array_size)
2520 {
2521 struct wined3d_display_mode *new_enum_modes;
2522
2523 enum_mode_array_size *= 2;
2524 if (!(new_enum_modes = heap_realloc(enum_modes, enum_mode_array_size * sizeof(*new_enum_modes))))
2525 {
2526 heap_free(enum_modes);
2528 return DDERR_OUTOFMEMORY;
2529 }
2530
2531 enum_modes = new_enum_modes;
2532 }
2533 enum_modes[enum_mode_count++] = mode;
2534 }
2535 }
2536
2537 TRACE("End of enumeration\n");
2538 heap_free(enum_modes);
2540
2541 return DD_OK;
2542}
2543
2546{
2547 struct ddraw *ddraw = impl_from_IDirectDraw4(iface);
2548
2549 TRACE("iface %p, flags %#x, surface_desc %p, context %p, callback %p.\n",
2550 iface, flags, surface_desc, context, callback);
2551
2553}
2554
2557{
2558 struct ddraw *ddraw = impl_from_IDirectDraw2(iface);
2559 struct displaymodescallback_context cbcontext;
2560 DDSURFACEDESC2 surface_desc2;
2561
2562 TRACE("iface %p, flags %#x, surface_desc %p, context %p, callback %p.\n",
2563 iface, flags, surface_desc, context, callback);
2564
2565 cbcontext.func = callback;
2566 cbcontext.context = context;
2567
2568 if (surface_desc) DDSD_to_DDSD2(surface_desc, &surface_desc2);
2570 surface_desc ? &surface_desc2 : NULL, &cbcontext, EnumDisplayModesCallbackThunk);
2571}
2572
2575{
2576 struct ddraw *ddraw = impl_from_IDirectDraw(iface);
2577 struct displaymodescallback_context cbcontext;
2578 DDSURFACEDESC2 surface_desc2;
2579
2580 TRACE("iface %p, flags %#x, surface_desc %p, context %p, callback %p.\n",
2581 iface, flags, surface_desc, context, callback);
2582
2583 cbcontext.func = callback;
2584 cbcontext.context = context;
2585
2586 if (surface_desc) DDSD_to_DDSD2(surface_desc, &surface_desc2);
2588 surface_desc ? &surface_desc2 : NULL, &cbcontext, EnumDisplayModesCallbackThunk);
2589}
2590
2591/*****************************************************************************
2592 * IDirectDraw7::EvaluateMode
2593 *
2594 * Used with IDirectDraw7::StartModeTest to test video modes.
2595 * EvaluateMode is used to pass or fail a mode, and continue with the next
2596 * mode
2597 *
2598 * Params:
2599 * Flags: DDEM_MODEPASSED or DDEM_MODEFAILED
2600 * Timeout: Returns the amount of seconds left before the mode would have
2601 * been failed automatically
2602 *
2603 * Returns:
2604 * This implementation always DD_OK, because it's a stub
2605 *
2606 *****************************************************************************/
2608{
2609 FIXME("iface %p, flags %#x, timeout %p stub!\n", iface, Flags, Timeout);
2610
2611 /* When implementing this, implement it in WineD3D */
2612
2613 return DD_OK;
2614}
2615
2616/*****************************************************************************
2617 * IDirectDraw7::GetDeviceIdentifier
2618 *
2619 * Returns the device identifier, which gives information about the driver
2620 * Our device identifier is defined at the beginning of this file.
2621 *
2622 * Params:
2623 * DDDI: Address for the returned structure
2624 * Flags: Can be DDGDI_GETHOSTIDENTIFIER
2625 *
2626 * Returns:
2627 * On success it returns DD_OK
2628 * DDERR_INVALIDPARAMS if DDDI is NULL
2629 *
2630 *****************************************************************************/
2633{
2634 struct ddraw *ddraw = impl_from_IDirectDraw7(iface);
2635 struct wined3d_adapter_identifier adapter_id;
2636 HRESULT hr = S_OK;
2637
2638 TRACE("iface %p, device_identifier %p, flags %#x.\n", iface, DDDI, Flags);
2639
2640 if (!DDDI)
2641 return DDERR_INVALIDPARAMS;
2642
2644 {
2645 /* The DDGDI_GETHOSTIDENTIFIER returns the information about the 2D
2646 * host adapter, if there's a secondary 3D adapter. This doesn't apply
2647 * to any modern hardware, nor is it interesting for Wine, so ignore it.
2648 * Size of DDDEVICEIDENTIFIER2 may be aligned to 8 bytes and thus 4
2649 * bytes too long. So only copy the relevant part of the structure
2650 */
2651
2653 return DD_OK;
2654 }
2655
2656 /* Drakan: Order of the Flame expects accurate D3D device information from ddraw */
2657 adapter_id.driver = DDDI->szDriver;
2658 adapter_id.driver_size = sizeof(DDDI->szDriver);
2659 adapter_id.description = DDDI->szDescription;
2660 adapter_id.description_size = sizeof(DDDI->szDescription);
2661 adapter_id.device_name_size = 0;
2665 if (FAILED(hr)) return hr;
2666
2667 DDDI->liDriverVersion = adapter_id.driver_version;
2668 DDDI->dwVendorId = adapter_id.vendor_id;
2669 DDDI->dwDeviceId = adapter_id.device_id;
2670 DDDI->dwSubSysId = adapter_id.subsystem_id;
2671 DDDI->dwRevision = adapter_id.revision;
2672 DDDI->guidDeviceIdentifier = adapter_id.device_identifier;
2673 DDDI->dwWHQLLevel = adapter_id.whql_level;
2674 return DD_OK;
2675}
2676
2677static HRESULT WINAPI ddraw4_GetDeviceIdentifier(IDirectDraw4 *iface,
2678 DDDEVICEIDENTIFIER *identifier, DWORD flags)
2679{
2680 struct ddraw *ddraw = impl_from_IDirectDraw4(iface);
2681 DDDEVICEIDENTIFIER2 identifier2;
2682 HRESULT hr;
2683
2684 TRACE("iface %p, identifier %p, flags %#x.\n", iface, identifier, flags);
2685
2687 DDRAW_Convert_DDDEVICEIDENTIFIER_2_To_1(&identifier2, identifier);
2688
2689 return hr;
2690}
2691
2692/*****************************************************************************
2693 * IDirectDraw7::GetSurfaceFromDC
2694 *
2695 * Returns the Surface for a GDI device context handle.
2696 * Is this related to IDirectDrawSurface::GetDC ???
2697 *
2698 * Params:
2699 * hdc: hdc to return the surface for
2700 * Surface: Address to write the surface pointer to
2701 *
2702 * Returns:
2703 * Always returns DD_OK because it's a stub
2704 *
2705 *****************************************************************************/
2707 HDC dc, IDirectDrawSurface7 **surface)
2708{
2709 struct ddraw *ddraw = impl_from_IDirectDraw7(iface);
2710 struct ddraw_surface *surface_impl;
2711
2712 TRACE("iface %p, dc %p, surface %p.\n", iface, dc, surface);
2713
2714 if (!surface)
2715 return E_INVALIDARG;
2716
2717 if (!dc)
2718 goto done;
2719
2722 {
2723 if (surface_impl->dc != dc)
2724 continue;
2725
2726 TRACE("Found surface %p for dc %p.\n", surface_impl, dc);
2727 *surface = &surface_impl->IDirectDrawSurface7_iface;
2728 IDirectDrawSurface7_AddRef(*surface);
2730 return DD_OK;
2731 }
2733
2734done:
2735 TRACE("No surface found for dc %p.\n", dc);
2736 *surface = NULL;
2737 return DDERR_NOTFOUND;
2738}
2739
2740static HRESULT WINAPI ddraw4_GetSurfaceFromDC(IDirectDraw4 *iface, HDC dc,
2741 IDirectDrawSurface4 **surface)
2742{
2743 struct ddraw *ddraw = impl_from_IDirectDraw4(iface);
2744 struct ddraw_surface *surface_impl;
2745 IDirectDrawSurface7 *surface7;
2746 HRESULT hr;
2747
2748 TRACE("iface %p, dc %p, surface %p.\n", iface, dc, surface);
2749
2750 if (!surface) return E_INVALIDARG;
2751
2753 if (FAILED(hr))
2754 {
2755 *surface = NULL;
2756 return hr;
2757 }
2758 surface_impl = impl_from_IDirectDrawSurface7(surface7);
2759 /* Tests say this is true */
2760 *surface = (IDirectDrawSurface4 *)&surface_impl->IDirectDrawSurface_iface;
2761 IDirectDrawSurface_AddRef(&surface_impl->IDirectDrawSurface_iface);
2762 IDirectDrawSurface7_Release(surface7);
2763
2764 return hr;
2765}
2766
2768{
2769 IDirectDrawSurface_Restore(surface);
2770 IDirectDrawSurface_Release(surface);
2771
2772 return DDENUMRET_OK;
2773}
2774
2776{
2777 TRACE("iface %p.\n", iface);
2778
2779 return IDirectDraw7_EnumSurfaces(iface, DDENUMSURFACES_ALL | DDENUMSURFACES_DOESEXIST,
2781}
2782
2783static HRESULT WINAPI ddraw4_RestoreAllSurfaces(IDirectDraw4 *iface)
2784{
2785 struct ddraw *ddraw = impl_from_IDirectDraw4(iface);
2786
2787 TRACE("iface %p.\n", iface);
2788
2790}
2791
2792/*****************************************************************************
2793 * IDirectDraw7::StartModeTest
2794 *
2795 * Tests the specified video modes to update the system registry with
2796 * refresh rate information. StartModeTest starts the mode test,
2797 * EvaluateMode is used to fail or pass a mode. If EvaluateMode
2798 * isn't called within 15 seconds, the mode is failed automatically
2799 *
2800 * As refresh rates are handled by the X server, I don't think this
2801 * Method is important
2802 *
2803 * Params:
2804 * Modes: An array of mode specifications
2805 * NumModes: The number of modes in Modes
2806 * Flags: Some flags...
2807 *
2808 * Returns:
2809 * Returns DDERR_TESTFINISHED if flags contains DDSMT_ISTESTREQUIRED,
2810 * if no modes are passed, DDERR_INVALIDPARAMS is returned,
2811 * otherwise DD_OK
2812 *
2813 *****************************************************************************/
2815{
2816 FIXME("iface %p, modes %p, mode_count %u, flags %#x partial stub!\n",
2817 iface, Modes, NumModes, Flags);
2818
2819 /* This looks sane */
2820 if( (!Modes) || (NumModes == 0) ) return DDERR_INVALIDPARAMS;
2821
2822 /* DDSMT_ISTESTREQUIRED asks if a mode test is necessary.
2823 * As it is not, DDERR_TESTFINISHED is returned
2824 * (hopefully that's correct
2825 *
2826 if(Flags & DDSMT_ISTESTREQUIRED) return DDERR_TESTFINISHED;
2827 * well, that value doesn't (yet) exist in the wine headers, so ignore it
2828 */
2829
2830 return DD_OK;
2831}
2832
2834 IDirectDrawSurface7 **surface, IUnknown *outer_unknown)
2835{
2836 struct ddraw *ddraw = impl_from_IDirectDraw7(iface);
2837 struct ddraw_surface *impl;
2838 HRESULT hr;
2839
2840 TRACE("iface %p, surface_desc %p, surface %p, outer_unknown %p.\n",
2841 iface, surface_desc, surface, outer_unknown);
2842
2844
2846 {
2847 WARN("Cooperative level not set.\n");
2850 }
2851
2852 if(surface_desc == NULL || surface_desc->dwSize != sizeof(DDSURFACEDESC2))
2853 {
2854 WARN("Application supplied invalid surface descriptor\n");
2856 return DDERR_INVALIDPARAMS;
2857 }
2858
2859 __TRY
2860 {
2861 *surface = NULL;
2862 }
2864 {
2865 WARN("Surface pointer %p is invalid.\n", surface);
2867 return DDERR_INVALIDPARAMS;
2868 }
2869 __ENDTRY;
2870
2872 {
2873 if (TRACE_ON(ddraw))
2874 {
2875 TRACE(" (%p) Requesting surface desc :\n", iface);
2877 }
2878
2879 WARN("Application tried to create an explicit front or back buffer\n");
2881 return DDERR_INVALIDCAPS;
2882 }
2883
2884 hr = ddraw_surface_create(ddraw, surface_desc, &impl, outer_unknown, 7);
2886 if (FAILED(hr))
2887 return hr;
2888
2889 *surface = &impl->IDirectDrawSurface7_iface;
2890 IDirectDraw7_AddRef(iface);
2891 impl->ifaceToRelease = (IUnknown *)iface;
2892
2893 return hr;
2894}
2895
2896static HRESULT WINAPI ddraw4_CreateSurface(IDirectDraw4 *iface,
2897 DDSURFACEDESC2 *surface_desc, IDirectDrawSurface4 **surface, IUnknown *outer_unknown)
2898{
2899 struct ddraw *ddraw = impl_from_IDirectDraw4(iface);
2900 struct ddraw_surface *impl;
2901 HRESULT hr;
2902
2903 TRACE("iface %p, surface_desc %p, surface %p, outer_unknown %p.\n",
2904 iface, surface_desc, surface, outer_unknown);
2905
2907
2909 {
2910 WARN("Cooperative level not set.\n");
2913 }
2914
2915 if(surface_desc == NULL || surface_desc->dwSize != sizeof(DDSURFACEDESC2))
2916 {
2917 WARN("Application supplied invalid surface descriptor\n");
2919 return DDERR_INVALIDPARAMS;
2920 }
2921
2922 __TRY
2923 {
2924 *surface = NULL;
2925 }
2927 {
2928 WARN("Surface pointer %p is invalid.\n", surface);
2930 return DDERR_INVALIDPARAMS;
2931 }
2932 __ENDTRY;
2933
2935 {
2936 if (TRACE_ON(ddraw))
2937 {
2938 TRACE(" (%p) Requesting surface desc :\n", iface);
2940 }
2941
2942 WARN("Application tried to create an explicit front or back buffer\n");
2944 return DDERR_INVALIDCAPS;
2945 }
2946
2947 hr = ddraw_surface_create(ddraw, surface_desc, &impl, outer_unknown, 4);
2949 if (FAILED(hr))
2950 return hr;
2951
2952 *surface = &impl->IDirectDrawSurface4_iface;
2953 IDirectDraw4_AddRef(iface);
2954 impl->ifaceToRelease = (IUnknown *)iface;
2955
2956 return hr;
2957}
2958
2959static HRESULT WINAPI ddraw2_CreateSurface(IDirectDraw2 *iface,
2960 DDSURFACEDESC *surface_desc, IDirectDrawSurface **surface, IUnknown *outer_unknown)
2961{
2962 struct ddraw *ddraw = impl_from_IDirectDraw2(iface);
2963 struct ddraw_surface *impl;
2964 HRESULT hr;
2965 DDSURFACEDESC2 surface_desc2;
2966
2967 TRACE("iface %p, surface_desc %p, surface %p, outer_unknown %p.\n",
2968 iface, surface_desc, surface, outer_unknown);
2969
2971
2973 {
2974 WARN("Cooperative level not set.\n");
2977 }
2978
2979 if(surface_desc == NULL || surface_desc->dwSize != sizeof(DDSURFACEDESC))
2980 {
2981 WARN("Application supplied invalid surface descriptor\n");
2983 return DDERR_INVALIDPARAMS;
2984 }
2985
2986 __TRY
2987 {
2988 *surface = NULL;
2989 }
2991 {
2992 WARN("Surface pointer %p is invalid.\n", surface);
2994 return DDERR_INVALIDPARAMS;
2995 }
2996 __ENDTRY;
2997
2998 DDSD_to_DDSD2(surface_desc, &surface_desc2);
3000 {
3001 if (TRACE_ON(ddraw))
3002 {
3003 TRACE(" (%p) Requesting surface desc :\n", iface);
3005 }
3006
3007 WARN("Application tried to create an explicit front or back buffer\n");
3009 return DDERR_INVALIDCAPS;
3010 }
3011
3012 hr = ddraw_surface_create(ddraw, &surface_desc2, &impl, outer_unknown, 2);
3014 if (FAILED(hr))
3015 return hr;
3016
3017 *surface = &impl->IDirectDrawSurface_iface;
3018 impl->ifaceToRelease = NULL;
3019
3020 return hr;
3021}
3022
3023static HRESULT WINAPI ddraw1_CreateSurface(IDirectDraw *iface,
3024 DDSURFACEDESC *surface_desc, IDirectDrawSurface **surface, IUnknown *outer_unknown)
3025{
3026 struct ddraw *ddraw = impl_from_IDirectDraw(iface);
3027 struct ddraw_surface *impl;
3028 HRESULT hr;
3029 DDSURFACEDESC2 surface_desc2;
3030
3031 TRACE("iface %p, surface_desc %p, surface %p, outer_unknown %p.\n",
3032 iface, surface_desc, surface, outer_unknown);
3033
3035
3037 {
3038 WARN("Cooperative level not set.\n");
3041 }
3042
3043 if(surface_desc == NULL || surface_desc->dwSize != sizeof(DDSURFACEDESC))
3044 {
3045 WARN("Application supplied invalid surface descriptor\n");
3047 return DDERR_INVALIDPARAMS;
3048 }
3049
3050 __TRY
3051 {
3052 *surface = NULL;
3053 }
3055 {
3056 WARN("Surface pointer %p is invalid.\n", surface);
3058 return DDERR_INVALIDPARAMS;
3059 }
3060 __ENDTRY;
3061
3066 {
3067 WARN("Application tried to create an explicit front or back buffer.\n");
3069 return DDERR_INVALIDCAPS;
3070 }
3071
3072 DDSD_to_DDSD2(surface_desc, &surface_desc2);
3073 hr = ddraw_surface_create(ddraw, &surface_desc2, &impl, outer_unknown, 1);
3075 if (FAILED(hr))
3076 return hr;
3077
3078 *surface = &impl->IDirectDrawSurface_iface;
3079 impl->ifaceToRelease = NULL;
3080
3081 return hr;
3082}
3083
3084static BOOL
3086 const DDPIXELFORMAT *provided)
3087{
3088 /* Some flags must be present in both or neither for a match. */
3089 static const DWORD must_match = DDPF_PALETTEINDEXED1 | DDPF_PALETTEINDEXED2
3092
3093 if ((requested->dwFlags & provided->dwFlags) != requested->dwFlags)
3094 return FALSE;
3095
3096 if ((requested->dwFlags & must_match) != (provided->dwFlags & must_match))
3097 return FALSE;
3098
3099 if (requested->dwFlags & DDPF_FOURCC)
3100 if (requested->dwFourCC != provided->dwFourCC)
3101 return FALSE;
3102
3105 if (requested->u1.dwRGBBitCount != provided->u1.dwRGBBitCount)
3106 return FALSE;
3107
3110 if (requested->u2.dwRBitMask != provided->u2.dwRBitMask)
3111 return FALSE;
3112
3114 if (requested->u3.dwGBitMask != provided->u3.dwGBitMask)
3115 return FALSE;
3116
3117 /* I could be wrong about the bumpmapping. MSDN docs are vague. */
3119 |DDPF_BUMPDUDV))
3120 if (requested->u4.dwBBitMask != provided->u4.dwBBitMask)
3121 return FALSE;
3122
3123 if (requested->dwFlags & (DDPF_ALPHAPIXELS|DDPF_ZPIXELS))
3124 if (requested->u5.dwRGBAlphaBitMask != provided->u5.dwRGBAlphaBitMask)
3125 return FALSE;
3126
3127 return TRUE;
3128}
3129
3130static BOOL ddraw_match_surface_desc(const DDSURFACEDESC2 *requested, const DDSURFACEDESC2 *provided)
3131{
3132 struct compare_info
3133 {
3134 DWORD flag;
3136 size_t size;
3137 };
3138
3139#define CMP(FLAG, FIELD) \
3140 { DDSD_##FLAG, offsetof(DDSURFACEDESC2, FIELD), \
3141 sizeof(((DDSURFACEDESC2 *)(NULL))->FIELD) }
3142
3143 static const struct compare_info compare[] =
3144 {
3145 CMP(ALPHABITDEPTH, dwAlphaBitDepth),
3146 CMP(BACKBUFFERCOUNT, u5.dwBackBufferCount),
3147 CMP(CAPS, ddsCaps),
3148 CMP(CKDESTBLT, ddckCKDestBlt),
3149 CMP(CKDESTOVERLAY, u3 /* ddckCKDestOverlay */),
3150 CMP(CKSRCBLT, ddckCKSrcBlt),
3151 CMP(CKSRCOVERLAY, ddckCKSrcOverlay),
3153 CMP(LINEARSIZE, u1 /* dwLinearSize */),
3154 CMP(LPSURFACE, lpSurface),
3155 CMP(MIPMAPCOUNT, u2 /* dwMipMapCount */),
3156 CMP(PITCH, u1 /* lPitch */),
3157 /* PIXELFORMAT: manual */
3158 CMP(REFRESHRATE, u2 /* dwRefreshRate */),
3159 CMP(TEXTURESTAGE, dwTextureStage),
3160 CMP(WIDTH, dwWidth),
3161 /* ZBUFFERBITDEPTH: "obsolete" */
3162 };
3163
3164#undef CMP
3165
3166 unsigned int i;
3167
3168 if ((requested->dwFlags & provided->dwFlags) != requested->dwFlags)
3169 return FALSE;
3170
3171 for (i=0; i < ARRAY_SIZE(compare); i++)
3172 {
3173 if (requested->dwFlags & compare[i].flag
3174 && memcmp((const char *)provided + compare[i].offset,
3175 (const char *)requested + compare[i].offset,
3176 compare[i].size) != 0)
3177 return FALSE;
3178 }
3179
3180 if (requested->dwFlags & DDSD_PIXELFORMAT)
3181 {
3183 &provided->u4.ddpfPixelFormat))
3184 return FALSE;
3185 }
3186
3187 return TRUE;
3188}
3189
3191{
3193 void *context;
3194};
3195
3197{
3199 void *context;
3200};
3201
3203 DDSURFACEDESC2 *surface_desc, void *context)
3204{
3205 struct ddraw_surface *surface_impl = impl_from_IDirectDrawSurface7(surface);
3206 struct surfacescallback2_context *cbcontext = context;
3207
3208 IDirectDrawSurface4_AddRef(&surface_impl->IDirectDrawSurface4_iface);
3209 IDirectDrawSurface7_Release(surface);
3210
3211 return cbcontext->func(&surface_impl->IDirectDrawSurface4_iface,
3212 surface_desc, cbcontext->context);
3213}
3214
3216 DDSURFACEDESC2 *surface_desc, void *context)
3217{
3218 struct ddraw_surface *surface_impl = impl_from_IDirectDrawSurface7(surface);
3219 struct surfacescallback_context *cbcontext = context;
3220
3221 IDirectDrawSurface_AddRef(&surface_impl->IDirectDrawSurface_iface);
3222 IDirectDrawSurface7_Release(surface);
3223
3224 return cbcontext->func(&surface_impl->IDirectDrawSurface_iface,
3225 (DDSURFACEDESC *)surface_desc, cbcontext->context);
3226}
3227
3228/*****************************************************************************
3229 * IDirectDraw7::EnumSurfaces
3230 *
3231 * Loops through all surfaces attached to this device and calls the
3232 * application callback. This can't be relayed to WineD3DDevice,
3233 * because some WineD3DSurfaces' parents are IParent objects
3234 *
3235 * Params:
3236 * Flags: Some filtering flags. See IDirectDrawImpl_EnumSurfacesCallback
3237 * DDSD: Description to filter for
3238 * Context: Application-provided pointer, it's passed unmodified to the
3239 * Callback function
3240 * Callback: Address to call for each surface
3241 *
3242 * Returns:
3243 * DDERR_INVALIDPARAMS if the callback is NULL
3244 * DD_OK on success
3245 *
3246 *****************************************************************************/
3249{
3250 struct ddraw *ddraw = impl_from_IDirectDraw7(iface);
3251 struct ddraw_surface *surf;
3253
3254 TRACE("iface %p, flags %#x, surface_desc %p, context %p, callback %p.\n",
3255 iface, Flags, DDSD, Context, Callback);
3256
3257 if (!Callback)
3258 return DDERR_INVALIDPARAMS;
3259
3261 {
3262 IDirectDrawSurface7 *surface;
3263 DDSURFACEDESC2 testdesc;
3264 HRESULT hr;
3265
3266 if (match_flags != DDENUMSURFACES_MATCH)
3267 return DDERR_INVALIDPARAMS;
3268
3269 if (!DDSD)
3270 return DDERR_INVALIDPARAMS;
3271
3272 memcpy(&testdesc, DDSD, sizeof(testdesc));
3273 if (!(testdesc.dwFlags & DDSD_WIDTH))
3274 {
3275 testdesc.dwFlags |= DDSD_WIDTH;
3276 testdesc.dwWidth = 512;
3277 }
3278 if (!(testdesc.dwFlags & DDSD_HEIGHT))
3279 {
3280 testdesc.dwFlags |= DDSD_HEIGHT;
3281 testdesc.dwHeight = 512;
3282 }
3283
3284 hr = IDirectDraw7_CreateSurface(iface, &testdesc, &surface, NULL);
3285 if (SUCCEEDED(hr))
3286 {
3289 IDirectDrawSurface7_Release(surface);
3290 }
3291 else
3292 ERR("Failed to create surface, hr %#x.\n", hr);
3293 }
3295 {
3296 BOOL all, nomatch;
3298 struct list *entry, *entry2;
3299
3300 /* a combination of match flags is not allowed */
3301 if (match_flags != 0 &&
3302 match_flags != DDENUMSURFACES_ALL &&
3303 match_flags != DDENUMSURFACES_MATCH &&
3304 match_flags != DDENUMSURFACES_NOMATCH)
3305 return DDERR_INVALIDPARAMS;
3306
3307 all = (Flags & DDENUMSURFACES_ALL) != 0;
3308 nomatch = (Flags & DDENUMSURFACES_NOMATCH) != 0;
3309
3310 if (!all && !DDSD)
3311 return DDERR_INVALIDPARAMS;
3312
3314
3315 /* Use the _SAFE enumeration, the app may destroy enumerated surfaces */
3317 {
3318 surf = LIST_ENTRY(entry, struct ddraw_surface, surface_list_entry);
3319
3320 if (!surf->iface_count)
3321 {
3322 WARN("Not enumerating surface %p because it doesn't have any references.\n", surf);
3323 continue;
3324 }
3325
3326 if (all || (nomatch != ddraw_match_surface_desc(DDSD, &surf->surface_desc)))
3327 {
3328 TRACE("Enumerating surface %p.\n", surf);
3329 desc = surf->surface_desc;
3330 IDirectDrawSurface7_AddRef(&surf->IDirectDrawSurface7_iface);
3332 {
3334 return DD_OK;
3335 }
3336 }
3337 }
3338
3340 }
3341 else
3342 return DDERR_INVALIDPARAMS;
3343
3344 return DD_OK;
3345}
3346
3347static HRESULT WINAPI ddraw4_EnumSurfaces(IDirectDraw4 *iface, DWORD flags,
3349{
3350 struct ddraw *ddraw = impl_from_IDirectDraw4(iface);
3351 struct surfacescallback2_context cbcontext;
3352
3353 TRACE("iface %p, flags %#x, surface_desc %p, context %p, callback %p.\n",
3354 iface, flags, surface_desc, context, callback);
3355
3356 cbcontext.func = callback;
3357 cbcontext.context = context;
3358
3359 return ddraw7_EnumSurfaces(&ddraw->IDirectDraw7_iface, flags, surface_desc,
3360 &cbcontext, EnumSurfacesCallback2Thunk);
3361}
3362
3363static HRESULT WINAPI ddraw2_EnumSurfaces(IDirectDraw2 *iface, DWORD flags,
3365{
3366 struct ddraw *ddraw = impl_from_IDirectDraw2(iface);
3367 struct surfacescallback_context cbcontext;
3368 DDSURFACEDESC2 surface_desc2;
3369
3370 TRACE("iface %p, flags %#x, surface_desc %p, context %p, callback %p.\n",
3371 iface, flags, surface_desc, context, callback);
3372
3373 cbcontext.func = callback;
3374 cbcontext.context = context;
3375
3376 if (surface_desc) DDSD_to_DDSD2(surface_desc, &surface_desc2);
3378 surface_desc ? &surface_desc2 : NULL, &cbcontext, EnumSurfacesCallbackThunk);
3379}
3380
3381static HRESULT WINAPI ddraw1_EnumSurfaces(IDirectDraw *iface, DWORD flags,
3383{
3384 struct ddraw *ddraw = impl_from_IDirectDraw(iface);
3385 struct surfacescallback_context cbcontext;
3386 DDSURFACEDESC2 surface_desc2;
3387
3388 TRACE("iface %p, flags %#x, surface_desc %p, context %p, callback %p.\n",
3389 iface, flags, surface_desc, context, callback);
3390
3391 cbcontext.func = callback;
3392 cbcontext.context = context;
3393
3394 if (surface_desc) DDSD_to_DDSD2(surface_desc, &surface_desc2);
3396 surface_desc ? &surface_desc2 : NULL, &cbcontext, EnumSurfacesCallbackThunk);
3397}
3398
3399/*****************************************************************************
3400 * DirectDrawCreateClipper (DDRAW.@)
3401 *
3402 * Creates a new IDirectDrawClipper object.
3403 *
3404 * Params:
3405 * Clipper: Address to write the interface pointer to
3406 * UnkOuter: For aggregation support, which ddraw doesn't have. Has to be
3407 * NULL
3408 *
3409 * Returns:
3410 * CLASS_E_NOAGGREGATION if UnkOuter != NULL
3411 * E_OUTOFMEMORY if allocating the object failed
3412 *
3413 *****************************************************************************/
3414HRESULT WINAPI DirectDrawCreateClipper(DWORD flags, IDirectDrawClipper **clipper, IUnknown *outer_unknown)
3415{
3416 struct ddraw_clipper *object;
3417 HRESULT hr;
3418
3419 TRACE("flags %#x, clipper %p, outer_unknown %p.\n",
3420 flags, clipper, outer_unknown);
3421
3422 if (outer_unknown)
3423 return CLASS_E_NOAGGREGATION;
3424
3426
3427 if (!(object = heap_alloc_zero(sizeof(*object))))
3428 {
3430 return E_OUTOFMEMORY;
3431 }
3432
3433 hr = ddraw_clipper_init(object);
3434 if (FAILED(hr))
3435 {
3436 WARN("Failed to initialize clipper, hr %#x.\n", hr);
3437 heap_free(object);
3439 return hr;
3440 }
3441
3442 TRACE("Created clipper %p.\n", object);
3443 *clipper = &object->IDirectDrawClipper_iface;
3445
3446 return DD_OK;
3447}
3448
3449/*****************************************************************************
3450 * IDirectDraw7::CreateClipper
3451 *
3452 * Creates a DDraw clipper. See DirectDrawCreateClipper for details
3453 *
3454 *****************************************************************************/
3456 IDirectDrawClipper **Clipper, IUnknown *UnkOuter)
3457{
3458 TRACE("iface %p, flags %#x, clipper %p, outer_unknown %p.\n",
3459 iface, Flags, Clipper, UnkOuter);
3460
3461 return DirectDrawCreateClipper(Flags, Clipper, UnkOuter);
3462}
3463
3464static HRESULT WINAPI ddraw4_CreateClipper(IDirectDraw4 *iface, DWORD flags,
3465 IDirectDrawClipper **clipper, IUnknown *outer_unknown)
3466{
3467 struct ddraw *ddraw = impl_from_IDirectDraw4(iface);
3468
3469 TRACE("iface %p, flags %#x, clipper %p, outer_unknown %p.\n",
3470 iface, flags, clipper, outer_unknown);
3471
3472 return ddraw7_CreateClipper(&ddraw->IDirectDraw7_iface, flags, clipper, outer_unknown);
3473}
3474
3475static HRESULT WINAPI ddraw2_CreateClipper(IDirectDraw2 *iface,
3476 DWORD flags, IDirectDrawClipper **clipper, IUnknown *outer_unknown)
3477{
3478 struct ddraw *ddraw = impl_from_IDirectDraw2(iface);
3479
3480 TRACE("iface %p, flags %#x, clipper %p, outer_unknown %p.\n",
3481 iface, flags, clipper, outer_unknown);
3482
3483 return ddraw7_CreateClipper(&ddraw->IDirectDraw7_iface, flags, clipper, outer_unknown);
3484}
3485
3486static HRESULT WINAPI ddraw1_CreateClipper(IDirectDraw *iface,
3487 DWORD flags, IDirectDrawClipper **clipper, IUnknown *outer_unknown)
3488{
3489 struct ddraw *ddraw = impl_from_IDirectDraw(iface);
3490
3491 TRACE("iface %p, flags %#x, clipper %p, outer_unknown %p.\n",
3492 iface, flags, clipper, outer_unknown);
3493
3494 return ddraw7_CreateClipper(&ddraw->IDirectDraw7_iface, flags, clipper, outer_unknown);
3495}
3496
3497/*****************************************************************************
3498 * IDirectDraw7::CreatePalette
3499 *
3500 * Creates a new IDirectDrawPalette object
3501 *
3502 * Params:
3503 * Flags: The flags for the new clipper
3504 * ColorTable: Color table to assign to the new clipper
3505 * Palette: Address to write the interface pointer to
3506 * UnkOuter: For aggregation support, which ddraw doesn't have. Has to be
3507 * NULL
3508 *
3509 * Returns:
3510 * CLASS_E_NOAGGREGATION if UnkOuter != NULL
3511 * E_OUTOFMEMORY if allocating the object failed
3512 *
3513 *****************************************************************************/
3515 PALETTEENTRY *ColorTable, IDirectDrawPalette **Palette, IUnknown *pUnkOuter)
3516{
3517 struct ddraw *ddraw = impl_from_IDirectDraw7(iface);
3518 struct ddraw_palette *object;
3519 HRESULT hr;
3520
3521 TRACE("iface %p, flags %#x, color_table %p, palette %p, outer_unknown %p.\n",
3522 iface, Flags, ColorTable, Palette, pUnkOuter);
3523
3524 if (pUnkOuter)
3525 return CLASS_E_NOAGGREGATION;
3526
3528
3529 /* The refcount test shows that a cooplevel is required for this */
3531 {
3532 WARN("No cooperative level set, returning DDERR_NOCOOPERATIVELEVELSET\n");
3535 }
3536
3537 if (!(object = heap_alloc(sizeof(*object))))
3538 {
3539 ERR("Out of memory when allocating memory for a palette implementation\n");
3541 return E_OUTOFMEMORY;
3542 }
3543
3544 hr = ddraw_palette_init(object, ddraw, Flags, ColorTable);
3545 if (FAILED(hr))
3546 {
3547 WARN("Failed to initialize palette, hr %#x.\n", hr);
3548 heap_free(object);
3550 return hr;
3551 }
3552
3553 TRACE("Created palette %p.\n", object);
3554 *Palette = &object->IDirectDrawPalette_iface;
3556
3557 return DD_OK;
3558}
3559
3560static HRESULT WINAPI ddraw4_CreatePalette(IDirectDraw4 *iface, DWORD flags, PALETTEENTRY *entries,
3561 IDirectDrawPalette **palette, IUnknown *outer_unknown)
3562{
3563 struct ddraw *ddraw = impl_from_IDirectDraw4(iface);
3564 HRESULT hr;
3565
3566 TRACE("iface %p, flags %#x, entries %p, palette %p, outer_unknown %p.\n",
3567 iface, flags, entries, palette, outer_unknown);
3568
3569 hr = ddraw7_CreatePalette(&ddraw->IDirectDraw7_iface, flags, entries, palette, outer_unknown);
3570 if (SUCCEEDED(hr) && *palette)
3571 {
3573 IDirectDraw7_Release(&ddraw->IDirectDraw7_iface);
3574 IDirectDraw4_AddRef(iface);
3575 impl->ifaceToRelease = (IUnknown *)iface;
3576 }
3577 return hr;
3578}
3579
3580static HRESULT WINAPI ddraw2_CreatePalette(IDirectDraw2 *iface, DWORD flags,
3581 PALETTEENTRY *entries, IDirectDrawPalette **palette, IUnknown *outer_unknown)
3582{
3583 struct ddraw *ddraw = impl_from_IDirectDraw2(iface);
3584 HRESULT hr;
3585
3586 TRACE("iface %p, flags %#x, entries %p, palette %p, outer_unknown %p.\n",
3587 iface, flags, entries, palette, outer_unknown);
3588
3589 hr = ddraw7_CreatePalette(&ddraw->IDirectDraw7_iface, flags, entries, palette, outer_unknown);
3590 if (SUCCEEDED(hr) && *palette)
3591 {
3593 IDirectDraw7_Release(&ddraw->IDirectDraw7_iface);
3594 impl->ifaceToRelease = NULL;
3595 }
3596
3597 return hr;
3598}
3599
3600static HRESULT WINAPI ddraw1_CreatePalette(IDirectDraw *iface, DWORD flags,
3601 PALETTEENTRY *entries, IDirectDrawPalette **palette, IUnknown *outer_unknown)
3602{
3603 struct ddraw *ddraw = impl_from_IDirectDraw(iface);
3604 HRESULT hr;
3605
3606 TRACE("iface %p, flags %#x, entries %p, palette %p, outer_unknown %p.\n",
3607 iface, flags, entries, palette, outer_unknown);
3608
3609 hr = ddraw7_CreatePalette(&ddraw->IDirectDraw7_iface, flags, entries, palette, outer_unknown);
3610 if (SUCCEEDED(hr) && *palette)
3611 {
3613 IDirectDraw7_Release(&ddraw->IDirectDraw7_iface);
3614 impl->ifaceToRelease = NULL;
3615 }
3616
3617 return hr;
3618}
3619
3620/*****************************************************************************
3621 * IDirectDraw7::DuplicateSurface
3622 *
3623 * Duplicates a surface. The surface memory points to the same memory as
3624 * the original surface, and it's released when the last surface referencing
3625 * it is released. I guess that's beyond Wine's surface management right now
3626 * (Idea: create a new DDraw surface with the same WineD3DSurface. I need a
3627 * test application to implement this)
3628 *
3629 * Params:
3630 * Src: Address of the source surface
3631 * Dest: Address to write the new surface pointer to
3632 *
3633 * Returns:
3634 * See IDirectDraw7::CreateSurface
3635 *
3636 *****************************************************************************/
3639{
3640 struct ddraw_surface *src_surface = unsafe_impl_from_IDirectDrawSurface7(Src);
3641
3642 FIXME("iface %p, src %p, dst %p partial stub!\n", iface, Src, Dest);
3643
3644 /* For now, simply create a new, independent surface */
3645 return IDirectDraw7_CreateSurface(iface, &src_surface->surface_desc, Dest, NULL);
3646}
3647
3648static HRESULT WINAPI ddraw4_DuplicateSurface(IDirectDraw4 *iface, IDirectDrawSurface4 *src,
3649 IDirectDrawSurface4 **dst)
3650{
3652 struct ddraw *ddraw = impl_from_IDirectDraw4(iface);
3653 struct ddraw_surface *dst_impl;
3654 IDirectDrawSurface7 *dst7;
3655 HRESULT hr;
3656
3657 TRACE("iface %p, src %p, dst %p.\n", iface, src, dst);
3658
3660 src_impl ? &src_impl->IDirectDrawSurface7_iface : NULL, &dst7);
3661 if (FAILED(hr))
3662 {
3663 *dst = NULL;
3664 return hr;
3665 }
3666 dst_impl = impl_from_IDirectDrawSurface7(dst7);
3667 *dst = &dst_impl->IDirectDrawSurface4_iface;
3668 IDirectDrawSurface4_AddRef(*dst);
3669 IDirectDrawSurface7_Release(dst7);
3670
3671 return hr;
3672}
3673
3674static HRESULT WINAPI ddraw2_DuplicateSurface(IDirectDraw2 *iface,
3675 IDirectDrawSurface *src, IDirectDrawSurface **dst)
3676{
3678 struct ddraw *ddraw = impl_from_IDirectDraw2(iface);
3679 struct ddraw_surface *dst_impl;
3680 IDirectDrawSurface7 *dst7;
3681 HRESULT hr;
3682
3683 TRACE("iface %p, src %p, dst %p.\n", iface, src, dst);
3684
3686 src_impl ? &src_impl->IDirectDrawSurface7_iface : NULL, &dst7);
3687 if (FAILED(hr))
3688 return hr;
3689 dst_impl = impl_from_IDirectDrawSurface7(dst7);
3690 *dst = &dst_impl->IDirectDrawSurface_iface;
3691 IDirectDrawSurface_AddRef(*dst);
3692 IDirectDrawSurface7_Release(dst7);
3693
3694 return hr;
3695}
3696
3697static HRESULT WINAPI ddraw1_DuplicateSurface(IDirectDraw *iface, IDirectDrawSurface *src,
3698 IDirectDrawSurface **dst)
3699{
3701 struct ddraw *ddraw = impl_from_IDirectDraw(iface);
3702 struct ddraw_surface *dst_impl;
3703 IDirectDrawSurface7 *dst7;
3704 HRESULT hr;
3705
3706 TRACE("iface %p, src %p, dst %p.\n", iface, src, dst);
3707
3709 src_impl ? &src_impl->IDirectDrawSurface7_iface : NULL, &dst7);
3710 if (FAILED(hr))
3711 return hr;
3712 dst_impl = impl_from_IDirectDrawSurface7(dst7);
3713 *dst = &dst_impl->IDirectDrawSurface_iface;
3714 IDirectDrawSurface_AddRef(*dst);
3715 IDirectDrawSurface7_Release(dst7);
3716
3717 return hr;
3718}
3719
3720/*****************************************************************************
3721 * IDirect3D7::EnumDevices
3722 *
3723 * The EnumDevices method for IDirect3D7. It enumerates all supported
3724 * D3D7 devices. Currently the T&L, HAL and RGB devices are enumerated.
3725 *
3726 * Params:
3727 * callback: Function to call for each enumerated device
3728 * context: Pointer to pass back to the app
3729 *
3730 * Returns:
3731 * D3D_OK, or the return value of the GetCaps call
3732 *
3733 *****************************************************************************/
3735{
3736 struct ddraw *ddraw = impl_from_IDirect3D7(iface);
3737 D3DDEVICEDESC7 device_desc7;
3738 DWORD dev_caps;
3739 HRESULT hr;
3740 size_t i;
3741
3742 TRACE("iface %p, callback %p, context %p.\n", iface, callback, context);
3743
3744 if (!callback)
3745 return DDERR_INVALIDPARAMS;
3746
3748
3749 if (FAILED(hr = ddraw_get_d3dcaps(ddraw, &device_desc7)))
3750 {
3752 return hr;
3753 }
3754
3755 dev_caps = device_desc7.dwDevCaps;
3756
3757 for (i = 0; i < ARRAY_SIZE(device_list7); i++)
3758 {
3759 HRESULT ret;
3760
3761 device_desc7.deviceGUID = *device_list7[i].device_guid;
3762 device_desc7.dwDevCaps = dev_caps & ~device_list7[i].remove_caps;
3763
3764 ret = callback(device_list7[i].interface_name, device_list7[i].device_name, &device_desc7, context);
3765 if (ret != DDENUMRET_OK)
3766 {
3767 TRACE("Application cancelled the enumeration.\n");
3769 return D3D_OK;
3770 }
3771 }
3772
3773 TRACE("End of enumeration.\n");
3774
3776
3777 return D3D_OK;
3778}
3779
3780/*****************************************************************************
3781 * IDirect3D3::EnumDevices
3782 *
3783 * Enumerates all supported Direct3DDevice interfaces. This is the
3784 * implementation for Direct3D 1 to Direc3D 3, Version 7 has its own.
3785 *
3786 * Versions 1, 2 and 3
3787 *
3788 * Params:
3789 * callback: Application-provided routine to call for each enumerated device
3790 * Context: Pointer to pass to the callback
3791 *
3792 * Returns:
3793 * D3D_OK on success,
3794 * The result of IDirect3DImpl_GetCaps if it failed
3795 *
3796 *****************************************************************************/
3798{
3799 static CHAR wined3d_description[] = "Wine D3DDevice using WineD3D and OpenGL";
3800
3801 struct ddraw *ddraw = impl_from_IDirect3D3(iface);
3802 D3DDEVICEDESC device_desc1, hal_desc, hel_desc;
3803 D3DDEVICEDESC7 device_desc7;
3804 HRESULT hr;
3805
3806 /* Some games (Motoracer 2 demo) have the bad idea to modify the device
3807 * name string. Let's put the string in a sufficiently sized array in
3808 * writable memory. */
3809 char device_name[50];
3810 strcpy(device_name,"Direct3D HEL");
3811
3812 TRACE("iface %p, callback %p, context %p.\n", iface, callback, context);
3813
3814 if (!callback)
3815 return DDERR_INVALIDPARAMS;
3816
3818
3819 if (FAILED(hr = ddraw_get_d3dcaps(ddraw, &device_desc7)))
3820 {
3822 return hr;
3823 }
3824 ddraw_d3dcaps1_from_7(&device_desc1, &device_desc7);
3825
3826 /* Do I have to enumerate the reference id? Note from old d3d7:
3827 * "It seems that enumerating the reference IID on Direct3D 1 games
3828 * (AvP / Motoracer2) breaks them". So do not enumerate this iid in V1
3829 *
3830 * There's a registry key HKLM\Software\Microsoft\Direct3D\Drivers,
3831 * EnumReference which enables / disables enumerating the reference
3832 * rasterizer. It's a DWORD, 0 means disabled, 2 means enabled. The
3833 * enablerefrast.reg and disablerefrast.reg files in the DirectX 7.0 sdk
3834 * demo directory suggest this.
3835 *
3836 * Some games(GTA 2) seem to use the second enumerated device, so I have
3837 * to enumerate at least 2 devices. So enumerate the reference device to
3838 * have 2 devices.
3839 *
3840 * Other games (Rollcage) tell emulation and hal device apart by certain
3841 * flags. Rollcage expects D3DPTEXTURECAPS_POW2 to be set (yeah, it is a
3842 * limitation flag), and it refuses all devices that have the perspective
3843 * flag set. This way it refuses the emulation device, and HAL devices
3844 * never have POW2 unset in d3d7 on windows. */
3845 if (ddraw->d3dversion != 1)
3846 {
3847 static CHAR reference_description[] = "RGB Direct3D emulation";
3848
3849 TRACE("Enumerating WineD3D D3DDevice interface.\n");
3850 hal_desc = device_desc1;
3851 hel_desc = device_desc1;
3852 /* The rgb device has the pow2 flag set in the hel caps, but not in the hal caps. */
3857 /* RGB, RAMP and MMX devices have a HAL dcmColorModel of 0 */
3858 hal_desc.dcmColorModel = 0;
3859 /* RGB, RAMP and MMX devices cannot report HAL hardware flags */
3860 hal_desc.dwFlags = 0;
3861
3862 hr = callback((GUID *)&IID_IDirect3DRGBDevice, reference_description,
3863 device_name, &hal_desc, &hel_desc, context);
3864 if (hr != D3DENUMRET_OK)
3865 {
3866 TRACE("Application cancelled the enumeration.\n");
3868 return D3D_OK;
3869 }
3870 }
3871
3872 strcpy(device_name,"Direct3D HAL");
3873
3874 TRACE("Enumerating HAL Direct3D device.\n");
3875 hal_desc = device_desc1;
3876 hel_desc = device_desc1;
3877
3878 /* The hal device does not have the pow2 flag set in hel, but in hal. */
3883 /* HAL devices have a HEL dcmColorModel of 0 */
3884 hel_desc.dcmColorModel = 0;
3885
3886 hr = callback((GUID *)&IID_IDirect3DHALDevice, wined3d_description,
3887 device_name, &hal_desc, &hel_desc, context);
3888 if (hr != D3DENUMRET_OK)
3889 {
3890 TRACE("Application cancelled the enumeration.\n");
3892 return D3D_OK;
3893 }
3894
3895 TRACE("End of enumeration.\n");
3896
3898
3899 return D3D_OK;
3900}
3901
3903{
3904 struct ddraw *ddraw = impl_from_IDirect3D2(iface);
3905
3906 TRACE("iface %p, callback %p, context %p.\n", iface, callback, context);
3907
3909}
3910
3912{
3913 struct ddraw *ddraw = impl_from_IDirect3D(iface);
3914
3915 TRACE("iface %p, callback %p, context %p.\n", iface, callback, context);
3916
3918}
3919
3920/*****************************************************************************
3921 * IDirect3D3::CreateLight
3922 *
3923 * Creates an IDirect3DLight interface. This interface is used in
3924 * Direct3D3 or earlier for lighting. In Direct3D7 it has been replaced
3925 * by the DIRECT3DLIGHT7 structure. Wine's Direct3DLight implementation
3926 * uses the IDirect3DDevice7 interface with D3D7 lights.
3927 *
3928 * Versions 1, 2 and 3
3929 *
3930 * Params:
3931 * light: Address to store the new interface pointer
3932 * outer_unknown: Basically for aggregation, but ddraw doesn't support it.
3933 * Must be NULL
3934 *
3935 * Returns:
3936 * D3D_OK on success
3937 * DDERR_OUTOFMEMORY if memory allocation failed
3938 * CLASS_E_NOAGGREGATION if outer_unknown != NULL
3939 *
3940 *****************************************************************************/
3941static HRESULT WINAPI d3d3_CreateLight(IDirect3D3 *iface, IDirect3DLight **light,
3942 IUnknown *outer_unknown)
3943{
3944 struct ddraw *ddraw = impl_from_IDirect3D3(iface);
3945 struct d3d_light *object;
3946
3947 TRACE("iface %p, light %p, outer_unknown %p.\n", iface, light, outer_unknown);
3948
3949 if (outer_unknown)
3950 return CLASS_E_NOAGGREGATION;
3951
3952 if (!(object = heap_alloc_zero(sizeof(*object))))
3953 {
3954 ERR("Failed to allocate light memory.\n");
3955 return DDERR_OUTOFMEMORY;
3956 }
3957
3958 d3d_light_init(object, ddraw);
3959
3960 TRACE("Created light %p.\n", object);
3961 *light = &object->IDirect3DLight_iface;
3962
3963 return D3D_OK;
3964}
3965
3966static HRESULT WINAPI d3d2_CreateLight(IDirect3D2 *iface, IDirect3DLight **light, IUnknown *outer_unknown)
3967{
3968 struct ddraw *ddraw = impl_from_IDirect3D2(iface);
3969
3970 TRACE("iface %p, light %p, outer_unknown %p.\n", iface, light, outer_unknown);
3971
3972 return d3d3_CreateLight(&ddraw->IDirect3D3_iface, light, outer_unknown);
3973}
3974
3975static HRESULT WINAPI d3d1_CreateLight(IDirect3D *iface, IDirect3DLight **light, IUnknown *outer_unknown)
3976{
3977 struct ddraw *ddraw = impl_from_IDirect3D(iface);
3978
3979 TRACE("iface %p, light %p, outer_unknown %p.\n", iface, light, outer_unknown);
3980
3981 return d3d3_CreateLight(&ddraw->IDirect3D3_iface, light, outer_unknown);
3982}
3983
3984/*****************************************************************************
3985 * IDirect3D3::CreateMaterial
3986 *
3987 * Creates an IDirect3DMaterial interface. This interface is used by Direct3D3
3988 * and older versions. The IDirect3DMaterial implementation wraps its
3989 * functionality to IDirect3DDevice7::SetMaterial and friends.
3990 *
3991 * Versions 1, 2 and 3
3992 *
3993 * Params:
3994 * material: Address to store the new interface's pointer to
3995 * outer_unknown: Basically for aggregation, but ddraw doesn't support it.
3996 * Must be NULL
3997 *
3998 * Returns:
3999 * D3D_OK on success
4000 * DDERR_OUTOFMEMORY if memory allocation failed
4001 * CLASS_E_NOAGGREGATION if outer_unknown != NULL
4002 *
4003 *****************************************************************************/
4004static HRESULT WINAPI d3d3_CreateMaterial(IDirect3D3 *iface, IDirect3DMaterial3 **material,
4005 IUnknown *outer_unknown)
4006{
4007 struct ddraw *ddraw = impl_from_IDirect3D3(iface);
4008 struct d3d_material *object;
4009
4010 TRACE("iface %p, material %p, outer_unknown %p.\n", iface, material, outer_unknown);
4011
4012 if (outer_unknown) return CLASS_E_NOAGGREGATION;
4013
4014 object = d3d_material_create(ddraw);
4015 if (!object)
4016 {
4017 ERR("Failed to allocate material memory.\n");
4018 return DDERR_OUTOFMEMORY;
4019 }
4020
4021 TRACE("Created material %p.\n", object);
4022 *material = &object->IDirect3DMaterial3_iface;
4023
4024 return D3D_OK;
4025}
4026
4027static HRESULT WINAPI d3d2_CreateMaterial(IDirect3D2 *iface, IDirect3DMaterial2 **material,
4028 IUnknown *outer_unknown)
4029{
4030 struct ddraw *ddraw = impl_from_IDirect3D2(iface);
4031