Release 9.12.
[wine.git] / dlls / ddraw / ddraw.c
blob5cea4677439757e07c527421573ecd22e3a11595
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
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.
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.
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
24 #include "ddraw_private.h"
25 #include "ddrawi.h"
26 #include "d3dhal.h"
28 #include "wine/exception.h"
30 WINE_DEFAULT_DEBUG_CHANNEL(ddraw);
32 static const struct ddraw *exclusive_ddraw;
33 static HWND exclusive_window;
35 /* Device identifier. Don't relay it to WineD3D */
36 static const DDDEVICEIDENTIFIER2 deviceidentifier =
38 "vga.dll", /* default 2D driver */
39 "DirectDraw HAL",
40 { { 0x00010001, 0x00010001 } },
41 0, 0, 0, 0,
42 /* a8373c10-7ac4-4deb-849a-009844d08b2d */
43 {0xa8373c10,0x7ac4,0x4deb, {0x84,0x9a,0x00,0x98,0x44,0xd0,0x8b,0x2d}},
47 static struct enum_device_entry
49 char interface_name[100];
50 char device_name[100];
51 const GUID *device_guid;
52 DWORD unsupported_caps;
53 } device_list7[] =
55 /* T&L HAL device */
57 "WINE Direct3D7 Hardware Transform and Lighting acceleration using WineD3D",
58 "Wine D3D7 T&L HAL",
59 &IID_IDirect3DTnLHalDevice,
63 /* HAL device */
65 "WINE Direct3D7 Hardware acceleration using WineD3D",
66 "Direct3D HAL",
67 &IID_IDirect3DHALDevice,
68 D3DDEVCAPS_HWTRANSFORMANDLIGHT,
71 /* RGB device */
73 "WINE Direct3D7 RGB Software Emulation using WineD3D",
74 "Wine D3D7 RGB",
75 &IID_IDirect3DRGBDevice,
76 D3DDEVCAPS_HWTRANSFORMANDLIGHT | D3DDEVCAPS_DRAWPRIMITIVES2EX | D3DDEVCAPS_HWRASTERIZATION,
80 static void STDMETHODCALLTYPE ddraw_null_wined3d_object_destroyed(void *parent) {}
82 const struct wined3d_parent_ops ddraw_null_wined3d_parent_ops =
84 ddraw_null_wined3d_object_destroyed,
87 static void CDECL ddraw_swapchain_windowed_state_changed(struct wined3d_swapchain_state_parent *parent,
88 BOOL windowed)
90 TRACE("parent %p, windowed %d.\n", parent, windowed);
93 static const struct wined3d_swapchain_state_parent_ops ddraw_swapchain_state_parent_ops =
95 ddraw_swapchain_windowed_state_changed,
98 static inline struct ddraw *impl_from_IDirectDraw(IDirectDraw *iface)
100 return CONTAINING_RECORD(iface, struct ddraw, IDirectDraw_iface);
103 static inline struct ddraw *impl_from_IDirectDraw2(IDirectDraw2 *iface)
105 return CONTAINING_RECORD(iface, struct ddraw, IDirectDraw2_iface);
108 static inline struct ddraw *impl_from_IDirectDraw4(IDirectDraw4 *iface)
110 return CONTAINING_RECORD(iface, struct ddraw, IDirectDraw4_iface);
113 static inline struct ddraw *impl_from_IDirectDraw7(IDirectDraw7 *iface)
115 return CONTAINING_RECORD(iface, struct ddraw, IDirectDraw7_iface);
118 static inline struct ddraw *impl_from_IDirect3D(IDirect3D *iface)
120 return CONTAINING_RECORD(iface, struct ddraw, IDirect3D_iface);
123 static inline struct ddraw *impl_from_IDirect3D2(IDirect3D2 *iface)
125 return CONTAINING_RECORD(iface, struct ddraw, IDirect3D2_iface);
128 static inline struct ddraw *impl_from_IDirect3D3(IDirect3D3 *iface)
130 return CONTAINING_RECORD(iface, struct ddraw, IDirect3D3_iface);
133 static inline struct ddraw *impl_from_IDirect3D7(IDirect3D7 *iface)
135 return CONTAINING_RECORD(iface, struct ddraw, IDirect3D7_iface);
138 static HRESULT WINAPI ddraw7_QueryInterface(IDirectDraw7 *iface, REFIID riid, void **out)
140 struct ddraw *ddraw = impl_from_IDirectDraw7(iface);
142 TRACE("iface %p, riid %s, out %p.\n", iface, debugstr_guid(riid), out);
144 if (!riid)
146 *out = NULL;
147 return DDERR_INVALIDPARAMS;
150 /* The refcount unit test revealed that an IDirect3D7 interface can only
151 * be queried from a DirectDraw object that was created as an IDirectDraw7
152 * interface. The older interfaces can query any IDirect3D version except
153 * 7, because they are all initially created as IDirectDraw. This isn't
154 * really crucial behavior, and messy to implement with the common
155 * creation function, so it has been left out here. */
156 if (IsEqualGUID(&IID_IDirectDraw7, riid)
157 || IsEqualGUID(&IID_IUnknown, riid))
159 *out = &ddraw->IDirectDraw7_iface;
160 TRACE("Returning IDirectDraw7 interface %p.\n", *out);
162 else if (IsEqualGUID(&IID_IDirectDraw4, riid))
164 *out = &ddraw->IDirectDraw4_iface;
165 TRACE("Returning IDirectDraw4 interface %p.\n", *out);
167 else if (IsEqualGUID(&IID_IDirectDraw2, riid))
169 *out = &ddraw->IDirectDraw2_iface;
170 TRACE("Returning IDirectDraw2 interface %p.\n", *out);
172 else if (IsEqualGUID(&IID_IDirectDraw, riid))
174 *out = &ddraw->IDirectDraw_iface;
175 TRACE("Returning IDirectDraw interface %p.\n", *out);
177 else if (IsEqualGUID(&IID_IDirect3D7, riid))
179 ddraw->d3dversion = 7;
180 *out = &ddraw->IDirect3D7_iface;
181 TRACE("Returning Direct3D7 interface %p.\n", *out);
183 else if (IsEqualGUID(&IID_IDirect3D3, riid))
185 ddraw->d3dversion = 3;
186 *out = &ddraw->IDirect3D3_iface;
187 TRACE("Returning Direct3D3 interface %p.\n", *out);
189 else if (IsEqualGUID(&IID_IDirect3D2, riid))
191 ddraw->d3dversion = 2;
192 *out = &ddraw->IDirect3D2_iface;
193 TRACE("Returning Direct3D2 interface %p.\n", *out);
195 else if (IsEqualGUID(&IID_IDirect3D, riid))
197 ddraw->d3dversion = 1;
198 *out = &ddraw->IDirect3D_iface;
199 TRACE("Returning Direct3D interface %p.\n", *out);
201 /* Unknown interface */
202 else
204 WARN("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(riid));
205 *out = NULL;
206 return E_NOINTERFACE;
209 IUnknown_AddRef((IUnknown *)*out);
210 return S_OK;
213 static HRESULT WINAPI ddraw4_QueryInterface(IDirectDraw4 *iface, REFIID riid, void **object)
215 struct ddraw *ddraw = impl_from_IDirectDraw4(iface);
217 TRACE("iface %p, riid %s, object %p.\n", iface, debugstr_guid(riid), object);
219 return ddraw7_QueryInterface(&ddraw->IDirectDraw7_iface, riid, object);
222 static HRESULT WINAPI ddraw2_QueryInterface(IDirectDraw2 *iface, REFIID riid, void **object)
224 struct ddraw *ddraw = impl_from_IDirectDraw2(iface);
226 TRACE("iface %p, riid %s, object %p.\n", iface, debugstr_guid(riid), object);
228 return ddraw7_QueryInterface(&ddraw->IDirectDraw7_iface, riid, object);
231 static HRESULT WINAPI ddraw1_QueryInterface(IDirectDraw *iface, REFIID riid, void **object)
233 struct ddraw *ddraw = impl_from_IDirectDraw(iface);
235 TRACE("iface %p, riid %s, object %p.\n", iface, debugstr_guid(riid), object);
237 return ddraw7_QueryInterface(&ddraw->IDirectDraw7_iface, riid, object);
240 static HRESULT WINAPI d3d7_QueryInterface(IDirect3D7 *iface, REFIID riid, void **object)
242 struct ddraw *ddraw = impl_from_IDirect3D7(iface);
244 TRACE("iface %p, riid %s, object %p.\n", iface, debugstr_guid(riid), object);
246 return ddraw7_QueryInterface(&ddraw->IDirectDraw7_iface, riid, object);
249 static HRESULT WINAPI d3d3_QueryInterface(IDirect3D3 *iface, REFIID riid, void **object)
251 struct ddraw *ddraw = impl_from_IDirect3D3(iface);
253 TRACE("iface %p, riid %s, object %p.\n", iface, debugstr_guid(riid), object);
255 return ddraw7_QueryInterface(&ddraw->IDirectDraw7_iface, riid, object);
258 static HRESULT WINAPI d3d2_QueryInterface(IDirect3D2 *iface, REFIID riid, void **object)
260 struct ddraw *ddraw = impl_from_IDirect3D2(iface);
262 TRACE("iface %p, riid %s, object %p.\n", iface, debugstr_guid(riid), object);
264 return ddraw7_QueryInterface(&ddraw->IDirectDraw7_iface, riid, object);
267 static HRESULT WINAPI d3d1_QueryInterface(IDirect3D *iface, REFIID riid, void **object)
269 struct ddraw *ddraw = impl_from_IDirect3D(iface);
271 TRACE("iface %p, riid %s, object %p.\n", iface, debugstr_guid(riid), object);
273 return ddraw7_QueryInterface(&ddraw->IDirectDraw7_iface, riid, object);
276 /*****************************************************************************
277 * IDirectDraw7::AddRef
279 * Increases the interfaces refcount, basically
281 * DDraw refcounting is a bit tricky. The different DirectDraw interface
282 * versions have individual refcounts, but the IDirect3D interfaces do not.
283 * All interfaces are from one object, that means calling QueryInterface on an
284 * IDirectDraw7 interface for an IDirectDraw4 interface does not create a new
285 * ddraw object.
287 * That means all AddRef and Release implementations of IDirectDrawX work
288 * with their own counter, and IDirect3DX::AddRef thunk to IDirectDraw (1),
289 * except of IDirect3D7 which thunks to IDirectDraw7
291 * Returns: The new refcount
293 *****************************************************************************/
294 static ULONG WINAPI ddraw7_AddRef(IDirectDraw7 *iface)
296 struct ddraw *This = impl_from_IDirectDraw7(iface);
297 ULONG ref = InterlockedIncrement(&This->ref7);
299 TRACE("%p increasing refcount to %lu.\n", This, ref);
301 if(ref == 1) InterlockedIncrement(&This->numIfaces);
303 return ref;
306 static ULONG WINAPI ddraw4_AddRef(IDirectDraw4 *iface)
308 struct ddraw *This = impl_from_IDirectDraw4(iface);
309 ULONG ref = InterlockedIncrement(&This->ref4);
311 TRACE("%p increasing refcount to %lu.\n", This, ref);
313 if (ref == 1) InterlockedIncrement(&This->numIfaces);
315 return ref;
318 static ULONG WINAPI ddraw2_AddRef(IDirectDraw2 *iface)
320 struct ddraw *This = impl_from_IDirectDraw2(iface);
321 ULONG ref = InterlockedIncrement(&This->ref2);
323 TRACE("%p increasing refcount to %lu.\n", This, ref);
325 if (ref == 1) InterlockedIncrement(&This->numIfaces);
327 return ref;
330 static ULONG WINAPI ddraw1_AddRef(IDirectDraw *iface)
332 struct ddraw *This = impl_from_IDirectDraw(iface);
333 ULONG ref = InterlockedIncrement(&This->ref1);
335 TRACE("%p increasing refcount to %lu.\n", This, ref);
337 if (ref == 1) InterlockedIncrement(&This->numIfaces);
339 return ref;
342 static ULONG WINAPI d3d7_AddRef(IDirect3D7 *iface)
344 struct ddraw *This = impl_from_IDirect3D7(iface);
346 TRACE("iface %p.\n", iface);
348 return ddraw7_AddRef(&This->IDirectDraw7_iface);
351 static ULONG WINAPI d3d3_AddRef(IDirect3D3 *iface)
353 struct ddraw *This = impl_from_IDirect3D3(iface);
355 TRACE("iface %p.\n", iface);
357 return ddraw1_AddRef(&This->IDirectDraw_iface);
360 static ULONG WINAPI d3d2_AddRef(IDirect3D2 *iface)
362 struct ddraw *This = impl_from_IDirect3D2(iface);
364 TRACE("iface %p.\n", iface);
366 return ddraw1_AddRef(&This->IDirectDraw_iface);
369 static ULONG WINAPI d3d1_AddRef(IDirect3D *iface)
371 struct ddraw *This = impl_from_IDirect3D(iface);
373 TRACE("iface %p.\n", iface);
375 return ddraw1_AddRef(&This->IDirectDraw_iface);
378 static void ddraw_destroy_swapchain(struct ddraw *ddraw)
380 unsigned int i;
382 TRACE("Destroying the swapchain.\n");
384 wined3d_swapchain_decref(ddraw->wined3d_swapchain);
386 for (i = 0; i < ddraw->numConvertedDecls; ++i)
388 wined3d_vertex_declaration_decref(ddraw->decls[i].decl);
390 free(ddraw->decls);
391 ddraw->numConvertedDecls = 0;
393 wined3d_swapchain_decref(ddraw->wined3d_swapchain);
394 ddraw->wined3d_swapchain = NULL;
396 /* Free the d3d window if one was created. */
397 if (ddraw->d3d_window && ddraw->d3d_window != ddraw->dest_window)
399 TRACE("Destroying the hidden render window %p.\n", ddraw->d3d_window);
400 DestroyWindow(ddraw->d3d_window);
401 ddraw->d3d_window = 0;
404 ddraw->flags &= ~DDRAW_D3D_INITIALIZED;
406 ddraw_set_swapchain_window(ddraw, NULL);
408 TRACE("Swapchain destroyed.\n");
411 /*****************************************************************************
412 * ddraw_destroy
414 * Destroys a ddraw object if all refcounts are 0. This is to share code
415 * between the IDirectDrawX::Release functions
417 * Params:
418 * This: DirectDraw object to destroy
420 *****************************************************************************/
421 static void ddraw_destroy(struct ddraw *This)
423 struct d3d_device *device;
424 IDirectDraw7_SetCooperativeLevel(&This->IDirectDraw7_iface, NULL, DDSCL_NORMAL);
425 IDirectDraw7_RestoreDisplayMode(&This->IDirectDraw7_iface);
427 /* Destroy the device window if we created one */
428 if(This->devicewindow != 0)
430 TRACE(" (%p) Destroying the device window %p\n", This, This->devicewindow);
431 DestroyWindow(This->devicewindow);
432 This->devicewindow = 0;
435 wined3d_mutex_lock();
436 list_remove(&This->ddraw_list_entry);
437 wined3d_mutex_unlock();
439 if (This->wined3d_swapchain)
440 ddraw_destroy_swapchain(This);
441 wined3d_device_decref(This->wined3d_device);
442 wined3d_decref(This->wined3d);
444 LIST_FOR_EACH_ENTRY(device, &This->d3ddevice_list, struct d3d_device, ddraw_entry)
446 device->ddraw = NULL;
449 /* Now free the object */
450 free(This);
453 /*****************************************************************************
454 * IDirectDraw7::Release
456 * Decreases the refcount. If the refcount falls to 0, the object is destroyed
458 * Returns: The new refcount
459 *****************************************************************************/
460 static ULONG WINAPI ddraw7_Release(IDirectDraw7 *iface)
462 struct ddraw *This = impl_from_IDirectDraw7(iface);
463 ULONG ref = InterlockedDecrement(&This->ref7);
465 TRACE("%p decreasing refcount to %lu.\n", This, ref);
467 if (!ref && !InterlockedDecrement(&This->numIfaces))
468 ddraw_destroy(This);
470 return ref;
473 static ULONG WINAPI ddraw4_Release(IDirectDraw4 *iface)
475 struct ddraw *This = impl_from_IDirectDraw4(iface);
476 ULONG ref = InterlockedDecrement(&This->ref4);
478 TRACE("%p decreasing refcount to %lu.\n", This, ref);
480 if (!ref && !InterlockedDecrement(&This->numIfaces))
481 ddraw_destroy(This);
483 return ref;
486 static ULONG WINAPI ddraw2_Release(IDirectDraw2 *iface)
488 struct ddraw *This = impl_from_IDirectDraw2(iface);
489 ULONG ref = InterlockedDecrement(&This->ref2);
491 TRACE("%p decreasing refcount to %lu.\n", This, ref);
493 if (!ref && !InterlockedDecrement(&This->numIfaces))
494 ddraw_destroy(This);
496 return ref;
499 static ULONG WINAPI ddraw1_Release(IDirectDraw *iface)
501 struct ddraw *This = impl_from_IDirectDraw(iface);
502 ULONG ref = InterlockedDecrement(&This->ref1);
504 TRACE("%p decreasing refcount to %lu.\n", This, ref);
506 if (!ref && !InterlockedDecrement(&This->numIfaces))
507 ddraw_destroy(This);
509 return ref;
512 static ULONG WINAPI d3d7_Release(IDirect3D7 *iface)
514 struct ddraw *This = impl_from_IDirect3D7(iface);
516 TRACE("iface %p.\n", iface);
518 return ddraw7_Release(&This->IDirectDraw7_iface);
521 static ULONG WINAPI d3d3_Release(IDirect3D3 *iface)
523 struct ddraw *This = impl_from_IDirect3D3(iface);
525 TRACE("iface %p.\n", iface);
527 return ddraw1_Release(&This->IDirectDraw_iface);
530 static ULONG WINAPI d3d2_Release(IDirect3D2 *iface)
532 struct ddraw *This = impl_from_IDirect3D2(iface);
534 TRACE("iface %p.\n", iface);
536 return ddraw1_Release(&This->IDirectDraw_iface);
539 static ULONG WINAPI d3d1_Release(IDirect3D *iface)
541 struct ddraw *This = impl_from_IDirect3D(iface);
543 TRACE("iface %p.\n", iface);
545 return ddraw1_Release(&This->IDirectDraw_iface);
548 /*****************************************************************************
549 * IDirectDraw methods
550 *****************************************************************************/
552 static HRESULT ddraw_set_focus_window(struct ddraw *ddraw, HWND window)
554 /* FIXME: This looks wrong, exclusive mode should imply a destination
555 * window. */
556 if ((ddraw->cooperative_level & DDSCL_EXCLUSIVE) && ddraw->dest_window)
558 TRACE("Setting DDSCL_SETFOCUSWINDOW with an already set window, returning DDERR_HWNDALREADYSET.\n");
559 return DDERR_HWNDALREADYSET;
562 ddraw->focuswindow = window;
564 return DD_OK;
567 static HRESULT ddraw_attach_d3d_device(struct ddraw *ddraw, HWND window,
568 DWORD cooplevel, struct wined3d_swapchain **wined3d_swapchain)
570 struct wined3d_swapchain_desc swapchain_desc;
571 struct wined3d_display_mode mode;
572 HRESULT hr;
574 TRACE("ddraw %p.\n", ddraw);
576 if (FAILED(hr = wined3d_output_get_display_mode(ddraw->wined3d_output, &mode, NULL)))
578 ERR("Failed to get display mode.\n");
579 return hr;
582 memset(&swapchain_desc, 0, sizeof(swapchain_desc));
583 swapchain_desc.output = ddraw->wined3d_output;
584 swapchain_desc.backbuffer_width = mode.width;
585 swapchain_desc.backbuffer_height = mode.height;
586 swapchain_desc.backbuffer_format = mode.format_id;
587 swapchain_desc.backbuffer_bind_flags = 0;
588 swapchain_desc.backbuffer_count = 1;
589 swapchain_desc.swap_effect = WINED3D_SWAP_EFFECT_DISCARD;
590 swapchain_desc.device_window = window;
591 swapchain_desc.windowed = !(cooplevel & DDSCL_FULLSCREEN);
592 swapchain_desc.flags = DDRAW_WINED3D_SWAPCHAIN_FLAGS;
594 if ((cooplevel & DDSCL_NOWINDOWCHANGES) || window != GetForegroundWindow())
595 swapchain_desc.flags |= WINED3D_SWAPCHAIN_NO_WINDOW_CHANGES;
597 if (ddraw->flags & DDRAW_NO3D)
598 return wined3d_swapchain_create(ddraw->wined3d_device, &swapchain_desc,
599 &ddraw->state_parent, NULL, &ddraw_null_wined3d_parent_ops, wined3d_swapchain);
601 if (!window || window == GetDesktopWindow())
603 window = CreateWindowExA(0, DDRAW_WINDOW_CLASS_NAME, "Hidden D3D Window",
604 WS_DISABLED, 0, 0, GetSystemMetrics(SM_CXSCREEN), GetSystemMetrics(SM_CYSCREEN),
605 NULL, NULL, NULL, NULL);
606 if (!window)
608 ERR("Failed to create window, last error %#lx.\n", GetLastError());
609 return E_FAIL;
612 ShowWindow(window, SW_HIDE); /* Just to be sure */
613 WARN("No window for the Direct3DDevice, created hidden window %p.\n", window);
615 swapchain_desc.device_window = window;
617 else
619 TRACE("Using existing window %p for Direct3D rendering.\n", window);
621 ddraw->d3d_window = window;
623 /* Set this NOW, otherwise creating the depth stencil surface will cause a
624 * recursive loop until ram or emulated video memory is full. */
625 ddraw->flags |= DDRAW_D3D_INITIALIZED;
626 if (FAILED(hr = wined3d_swapchain_create(ddraw->wined3d_device, &swapchain_desc,
627 &ddraw->state_parent, NULL, &ddraw_null_wined3d_parent_ops, wined3d_swapchain)))
629 ddraw->flags &= ~DDRAW_D3D_INITIALIZED;
630 DestroyWindow(window);
631 ddraw->d3d_window = NULL;
632 return hr;
635 ddraw->declArraySize = 2;
636 if (!(ddraw->decls = calloc(ddraw->declArraySize, sizeof(*ddraw->decls))))
638 ERR("Error allocating an array for the converted vertex decls.\n");
639 ddraw->declArraySize = 0;
640 wined3d_swapchain_decref(*wined3d_swapchain);
641 DestroyWindow(window);
642 ddraw->d3d_window = NULL;
643 return E_OUTOFMEMORY;
646 TRACE("Successfully initialized 3D.\n");
648 return DD_OK;
651 static HRESULT ddraw_create_swapchain(struct ddraw *ddraw, HWND window, DWORD cooplevel)
653 HRESULT hr;
655 if (ddraw->wined3d_swapchain)
657 ERR("Swapchain already created.\n");
658 return E_FAIL;
661 if (FAILED(hr = ddraw_attach_d3d_device(ddraw, window, cooplevel, &ddraw->wined3d_swapchain)))
663 ERR("Failed to create swapchain, hr %#lx.\n", hr);
664 return hr;
666 wined3d_swapchain_incref(ddraw->wined3d_swapchain);
668 ddraw_set_swapchain_window(ddraw, window);
670 if (ddraw->primary && ddraw->primary->palette)
671 wined3d_swapchain_set_palette(ddraw->wined3d_swapchain, ddraw->primary->palette->wined3d_palette);
673 return DD_OK;
676 /*****************************************************************************
677 * IDirectDraw7::RestoreDisplayMode
679 * Restores the display mode to what it was at creation time. Basically.
681 * Returns
682 * DD_OK on success
683 * DDERR_NOEXCLUSIVE mode if the device isn't in fullscreen mode
685 *****************************************************************************/
686 static HRESULT WINAPI ddraw7_RestoreDisplayMode(IDirectDraw7 *iface)
688 struct ddraw *ddraw = impl_from_IDirectDraw7(iface);
689 struct wined3d_display_mode mode;
690 RECT clip_rect;
691 HRESULT hr;
693 TRACE("iface %p.\n", iface);
695 wined3d_mutex_lock();
697 if (!(ddraw->flags & DDRAW_RESTORE_MODE))
699 wined3d_mutex_unlock();
700 return DD_OK;
703 if (exclusive_ddraw && exclusive_ddraw != ddraw)
705 wined3d_mutex_unlock();
706 return DDERR_NOEXCLUSIVEMODE;
709 if (SUCCEEDED(hr = wined3d_restore_display_modes(ddraw->wined3d)))
711 ddraw->flags &= ~DDRAW_RESTORE_MODE;
712 if (ddraw->cooperative_level & DDSCL_EXCLUSIVE &&
713 SUCCEEDED(hr = wined3d_output_get_display_mode(ddraw->wined3d_output, &mode, NULL)))
715 SetRect(&clip_rect, 0, 0, mode.width, mode.height);
716 ClipCursor(&clip_rect);
720 InterlockedCompareExchange(&ddraw->device_state, DDRAW_DEVICE_STATE_NOT_RESTORED, DDRAW_DEVICE_STATE_OK);
722 wined3d_mutex_unlock();
724 return hr;
727 static HRESULT WINAPI ddraw4_RestoreDisplayMode(IDirectDraw4 *iface)
729 struct ddraw *ddraw = impl_from_IDirectDraw4(iface);
731 TRACE("iface %p.\n", iface);
733 return ddraw7_RestoreDisplayMode(&ddraw->IDirectDraw7_iface);
736 static HRESULT WINAPI ddraw2_RestoreDisplayMode(IDirectDraw2 *iface)
738 struct ddraw *ddraw = impl_from_IDirectDraw2(iface);
740 TRACE("iface %p.\n", iface);
742 return ddraw7_RestoreDisplayMode(&ddraw->IDirectDraw7_iface);
745 static HRESULT WINAPI ddraw1_RestoreDisplayMode(IDirectDraw *iface)
747 struct ddraw *ddraw = impl_from_IDirectDraw(iface);
749 TRACE("iface %p.\n", iface);
751 return ddraw7_RestoreDisplayMode(&ddraw->IDirectDraw7_iface);
754 /*****************************************************************************
755 * IDirectDraw7::SetCooperativeLevel
757 * Sets the cooperative level for the DirectDraw object, and the window
758 * assigned to it. The cooperative level determines the general behavior
759 * of the DirectDraw application
761 * Warning: This is quite tricky, as it's not really documented which
762 * cooperative levels can be combined with each other. If a game fails
763 * after this function, try to check the cooperative levels passed on
764 * Windows, and if it returns something different.
766 * If you think that this function caused the failure because it writes a
767 * fixme, be sure to run again with a +ddraw trace.
769 * What is known about cooperative levels (See the ddraw modes test):
770 * DDSCL_EXCLUSIVE requires DDSCL_FULLSCREEN.
771 * DDSCL_NORMAL is not compatible with DDSCL_EXCLUSIVE.
772 * Unlike what msdn claims, DDSCL_NORMAL | DDSCL_FULLSCREEN is allowed.
773 * DDSCL_SETFOCUSWINDOW can be passed only in DDSCL_NORMAL mode, but after that
774 * DDSCL_EXCLUSIVE can be activated.
775 * DDSCL_SETFOCUSWINDOW may only be used with DDSCL_NOWINDOWCHANGES or
776 * DDSCL_CREATEDEVICEWINDOW.
778 * Handled flags: DDSCL_NORMAL, DDSCL_FULLSCREEN, DDSCL_EXCLUSIVE,
779 * DDSCL_CREATEDEVICEWINDOW, DDSCL_SETDEVICEWINDOW
780 * DDSCL_SETFOCUSWINDOW (partially),
781 * DDSCL_MULTITHREADED (work in progress)
782 * DDSCL_FPUPRESERVE (see device.c)
784 * Unsure about this: DDSCL_FPUSETUP
786 * These don't seem very important for wine:
787 * DDSCL_ALLOWREBOOT, DDSCL_ALLOWMODEX
789 * Returns:
790 * DD_OK if the cooperative level was set successfully
791 * DDERR_INVALIDPARAMS if the passed cooperative level combination is invalid
792 * DDERR_HWNDALREADYSET if DDSCL_SETFOCUSWINDOW is passed in exclusive mode
793 * (Probably others too, have to investigate)
795 *****************************************************************************/
796 static HRESULT ddraw_set_cooperative_level(struct ddraw *ddraw, HWND window,
797 DWORD cooplevel, BOOL restore_mode_on_normal)
799 BOOL restore_state = FALSE;
800 struct d3d_device *device;
801 RECT clip_rect;
802 HRESULT hr;
804 TRACE("ddraw %p, window %p, flags %#lx, restore_mode_on_normal %x.\n", ddraw, window, cooplevel,
805 restore_mode_on_normal);
806 DDRAW_dump_cooperativelevel(cooplevel);
808 wined3d_mutex_lock();
810 if (ddraw->flags & DDRAW_SCL_RECURSIVE)
812 WARN("Recursive call, returning DD_OK.\n");
813 hr = DD_OK;
814 goto done;
816 ddraw->flags |= DDRAW_SCL_RECURSIVE;
818 /* Tests suggest that we need one of them: */
819 if(!(cooplevel & (DDSCL_SETFOCUSWINDOW |
820 DDSCL_NORMAL |
821 DDSCL_EXCLUSIVE )))
823 TRACE("Incorrect cooplevel flags, returning DDERR_INVALIDPARAMS\n");
824 hr = DDERR_INVALIDPARAMS;
825 goto done;
828 if ((cooplevel & DDSCL_CREATEDEVICEWINDOW) && !(cooplevel & DDSCL_EXCLUSIVE))
830 WARN("DDSCL_CREATEDEVICEWINDOW requires DDSCL_EXCLUSIVE.\n");
831 hr = DDERR_INVALIDPARAMS;
832 goto done;
835 /* Handle those levels first which set various hwnds */
836 if ((cooplevel & DDSCL_SETFOCUSWINDOW) && !(cooplevel & DDSCL_CREATEDEVICEWINDOW))
838 /* This isn't compatible with a lot of flags */
839 if (cooplevel & (DDSCL_MULTITHREADED
840 | DDSCL_FPUSETUP
841 | DDSCL_FPUPRESERVE
842 | DDSCL_ALLOWREBOOT
843 | DDSCL_ALLOWMODEX
844 | DDSCL_SETDEVICEWINDOW
845 | DDSCL_NORMAL
846 | DDSCL_EXCLUSIVE
847 | DDSCL_FULLSCREEN))
849 WARN("Called with incompatible flags, returning DDERR_INVALIDPARAMS.\n");
850 hr = DDERR_INVALIDPARAMS;
851 goto done;
854 hr = ddraw_set_focus_window(ddraw, window);
855 goto done;
858 if (cooplevel & DDSCL_EXCLUSIVE)
860 if (!(cooplevel & DDSCL_FULLSCREEN) || !(window || (cooplevel & DDSCL_CREATEDEVICEWINDOW)))
862 WARN("DDSCL_EXCLUSIVE requires DDSCL_FULLSCREEN and a window.\n");
863 hr = DDERR_INVALIDPARAMS;
864 goto done;
867 if (cooplevel & DDSCL_CREATEDEVICEWINDOW)
869 HWND device_window;
871 if (!ddraw->focuswindow && !(cooplevel & DDSCL_SETFOCUSWINDOW))
873 WARN("No focus window set.\n");
874 hr = DDERR_NOFOCUSWINDOW;
875 goto done;
878 device_window = CreateWindowExA(0, DDRAW_WINDOW_CLASS_NAME, "DirectDrawDeviceWnd",
879 WS_POPUP, 0, 0, GetSystemMetrics(SM_CXSCREEN), GetSystemMetrics(SM_CYSCREEN),
880 NULL, NULL, NULL, NULL);
881 if (!device_window)
883 ERR("Failed to create window, last error %#lx.\n", GetLastError());
884 hr = E_FAIL;
885 goto done;
888 ShowWindow(device_window, SW_SHOW);
889 TRACE("Created a device window %p.\n", device_window);
891 /* Native apparently leaks the created device window if setting the
892 * focus window below fails. */
893 ddraw->cooperative_level |= DDSCL_CREATEDEVICEWINDOW;
894 ddraw->devicewindow = device_window;
896 if (cooplevel & DDSCL_SETFOCUSWINDOW)
898 if (!window)
900 hr = DDERR_NOHWND;
901 goto done;
904 if (FAILED(hr = ddraw_set_focus_window(ddraw, window)))
905 goto done;
908 window = device_window;
911 else
913 if (ddraw->cooperative_level & DDSCL_CREATEDEVICEWINDOW)
914 DestroyWindow(ddraw->devicewindow);
915 ddraw->devicewindow = NULL;
916 ddraw->focuswindow = NULL;
919 if ((cooplevel & DDSCL_EXCLUSIVE) && exclusive_window != window)
921 ddraw->device_state = DDRAW_DEVICE_STATE_NOT_RESTORED;
922 exclusive_window = window;
925 if (cooplevel & DDSCL_MULTITHREADED && !(ddraw->cooperative_level & DDSCL_MULTITHREADED))
926 wined3d_device_set_multithreaded(ddraw->wined3d_device);
928 if (ddraw->wined3d_swapchain)
930 if (!(ddraw->flags & DDRAW_NO3D))
932 restore_state = TRUE;
934 LIST_FOR_EACH_ENTRY(device, &ddraw->d3ddevice_list, struct d3d_device, ddraw_entry)
936 if (FAILED(hr = wined3d_stateblock_create(ddraw->wined3d_device,
937 device->state, WINED3D_SBT_ALL, &device->saved_state)))
939 struct list *entry;
941 ERR("Failed to create stateblock, hr %#lx.\n", hr);
942 entry = &device->ddraw_entry;
943 while ((entry = list_prev(&ddraw->d3ddevice_list, entry)))
945 device = LIST_ENTRY(entry, struct d3d_device, ddraw_entry);
946 wined3d_stateblock_decref(device->saved_state);
947 device->saved_state = NULL;
949 goto done;
954 ddraw_destroy_swapchain(ddraw);
957 if (FAILED(hr = ddraw_create_swapchain(ddraw, window, cooplevel)))
958 ERR("Failed to create swapchain, hr %#lx.\n", hr);
960 if (restore_state)
962 LIST_FOR_EACH_ENTRY(device, &ddraw->d3ddevice_list, struct d3d_device, ddraw_entry)
964 wined3d_stateblock_apply(device->saved_state, device->state);
965 wined3d_stateblock_decref(device->saved_state);
966 device->saved_state = NULL;
970 if (!(cooplevel & DDSCL_EXCLUSIVE) && (ddraw->cooperative_level & DDSCL_EXCLUSIVE))
972 /* When going from exclusive mode to normal, ddraw removes the
973 topmost bit unless the DDSCL_NOWINDOWCHANGES flag is set in
974 this call that sets it to normal, not in the old coop level. */
975 if (!(cooplevel & DDSCL_NOWINDOWCHANGES))
976 SetWindowPos(window, HWND_NOTOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE);
978 if (restore_mode_on_normal && FAILED(ddraw7_RestoreDisplayMode(&ddraw->IDirectDraw7_iface)))
979 ERR("RestoreDisplayMode failed\n");
980 ClipCursor(NULL);
983 if ((ddraw->cooperative_level & DDSCL_EXCLUSIVE)
984 && (window != ddraw->dest_window || !(cooplevel & DDSCL_EXCLUSIVE)))
985 wined3d_device_release_focus_window(ddraw->wined3d_device);
987 if ((cooplevel & DDSCL_EXCLUSIVE)
988 && (window != ddraw->dest_window || !(ddraw->cooperative_level & DDSCL_EXCLUSIVE)))
990 hr = wined3d_device_acquire_focus_window(ddraw->wined3d_device, window);
991 if (FAILED(hr))
993 ERR("Failed to acquire focus window, hr %#lx.\n", hr);
994 goto done;
998 if (cooplevel & DDSCL_EXCLUSIVE)
1000 SetRect(&clip_rect, 0, 0, GetSystemMetrics(SM_CXSCREEN), GetSystemMetrics(SM_CYSCREEN));
1001 ClipCursor(&clip_rect);
1004 /* Unhandled flags */
1005 if (cooplevel & DDSCL_ALLOWREBOOT)
1006 WARN("Unhandled flag DDSCL_ALLOWREBOOT, harmless\n");
1007 if (cooplevel & DDSCL_ALLOWMODEX)
1008 WARN("Unhandled flag DDSCL_ALLOWMODEX, harmless\n");
1009 if (cooplevel & DDSCL_FPUSETUP)
1010 WARN("Unhandled flag DDSCL_FPUSETUP, harmless\n");
1012 if (cooplevel & DDSCL_EXCLUSIVE)
1013 exclusive_ddraw = ddraw;
1014 else if (exclusive_ddraw == ddraw)
1015 exclusive_ddraw = NULL;
1017 /* Store the cooperative_level */
1018 ddraw->cooperative_level = cooplevel;
1019 ddraw->dest_window = window;
1021 TRACE("SetCooperativeLevel returning DD_OK\n");
1022 hr = DD_OK;
1023 done:
1024 ddraw->flags &= ~DDRAW_SCL_RECURSIVE;
1025 wined3d_mutex_unlock();
1027 return hr;
1030 static HRESULT WINAPI ddraw7_SetCooperativeLevel(IDirectDraw7 *iface, HWND window, DWORD flags)
1032 struct ddraw *ddraw = impl_from_IDirectDraw7(iface);
1034 TRACE("iface %p, window %p, flags %#lx.\n", iface, window, flags);
1036 return ddraw_set_cooperative_level(ddraw, window, flags, !(ddraw->flags & DDRAW_SCL_DDRAW1));
1039 static HRESULT WINAPI ddraw4_SetCooperativeLevel(IDirectDraw4 *iface, HWND window, DWORD flags)
1041 struct ddraw *ddraw = impl_from_IDirectDraw4(iface);
1043 TRACE("iface %p, window %p, flags %#lx.\n", iface, window, flags);
1045 return ddraw_set_cooperative_level(ddraw, window, flags, !(ddraw->flags & DDRAW_SCL_DDRAW1));
1048 static HRESULT WINAPI ddraw2_SetCooperativeLevel(IDirectDraw2 *iface, HWND window, DWORD flags)
1050 struct ddraw *ddraw = impl_from_IDirectDraw2(iface);
1052 TRACE("iface %p, window %p, flags %#lx.\n", iface, window, flags);
1054 return ddraw_set_cooperative_level(ddraw, window, flags, !(ddraw->flags & DDRAW_SCL_DDRAW1));
1057 static HRESULT WINAPI ddraw1_SetCooperativeLevel(IDirectDraw *iface, HWND window, DWORD flags)
1059 struct ddraw *ddraw = impl_from_IDirectDraw(iface);
1060 HRESULT hr;
1062 TRACE("iface %p, window %p, flags %#lx.\n", iface, window, flags);
1064 hr = ddraw_set_cooperative_level(ddraw, window, flags, FALSE);
1065 if (SUCCEEDED(hr))
1066 ddraw->flags |= DDRAW_SCL_DDRAW1;
1067 return hr;
1070 /*****************************************************************************
1071 * IDirectDraw7::SetDisplayMode
1073 * Sets the display screen resolution, color depth and refresh frequency
1074 * when in fullscreen mode (in theory).
1075 * Possible return values listed in the SDK suggest that this method fails
1076 * when not in fullscreen mode, but this is wrong. Windows 2000 happily sets
1077 * the display mode in DDSCL_NORMAL mode without an hwnd specified.
1078 * It seems to be valid to pass 0 for With and Height, this has to be tested
1079 * It could mean that the current video mode should be left as-is. (But why
1080 * call it then?)
1082 * Params:
1083 * Height, Width: Screen dimension
1084 * BPP: Color depth in Bits per pixel
1085 * Refreshrate: Screen refresh rate
1086 * Flags: Other stuff
1088 * Returns
1089 * DD_OK on success
1091 *****************************************************************************/
1092 static HRESULT WINAPI ddraw7_SetDisplayMode(IDirectDraw7 *iface, DWORD width, DWORD height,
1093 DWORD bpp, DWORD refresh_rate, DWORD flags)
1095 struct ddraw *ddraw = impl_from_IDirectDraw7(iface);
1096 struct wined3d_display_mode mode;
1097 enum wined3d_format_id format;
1098 RECT clip_rect;
1099 HRESULT hr;
1101 TRACE("iface %p, width %lu, height %lu, bpp %lu, refresh_rate %lu, flags %#lx.\n",
1102 iface, width, height, bpp, refresh_rate, flags);
1104 if (force_refresh_rate != 0)
1106 TRACE("ForceRefreshRate overriding passed-in refresh rate (%lu Hz) to %lu Hz\n",
1107 refresh_rate, force_refresh_rate);
1108 refresh_rate = force_refresh_rate;
1111 wined3d_mutex_lock();
1113 if (exclusive_ddraw && exclusive_ddraw != ddraw)
1115 wined3d_mutex_unlock();
1116 return DDERR_NOEXCLUSIVEMODE;
1119 if (!width || !height)
1121 /* It looks like Need for Speed Porsche Unleashed expects DD_OK here. */
1122 wined3d_mutex_unlock();
1123 return DD_OK;
1126 switch (bpp)
1128 case 8: format = WINED3DFMT_P8_UINT; break;
1129 case 15: format = WINED3DFMT_B5G5R5X1_UNORM; break;
1130 case 16: format = WINED3DFMT_B5G6R5_UNORM; break;
1131 case 24: format = WINED3DFMT_B8G8R8_UNORM; break;
1132 case 32: format = WINED3DFMT_B8G8R8X8_UNORM; break;
1133 default: format = WINED3DFMT_UNKNOWN; break;
1136 mode.width = width;
1137 mode.height = height;
1138 mode.refresh_rate = refresh_rate;
1139 mode.format_id = format;
1140 mode.scanline_ordering = WINED3D_SCANLINE_ORDERING_UNKNOWN;
1142 /* TODO: The possible return values from msdn suggest that the screen mode
1143 * can't be changed if a surface is locked or some drawing is in progress. */
1144 if (SUCCEEDED(hr = wined3d_output_set_display_mode(ddraw->wined3d_output, &mode)))
1146 if (ddraw->primary)
1148 DDSURFACEDESC2 *surface_desc = &ddraw->primary->surface_desc;
1150 if (FAILED(hr = wined3d_swapchain_resize_buffers(ddraw->wined3d_swapchain, 0,
1151 surface_desc->dwWidth, surface_desc->dwHeight, mode.format_id, WINED3D_MULTISAMPLE_NONE, 0)))
1152 ERR("Failed to resize buffers, hr %#lx.\n", hr);
1153 else
1154 ddrawformat_from_wined3dformat(&ddraw->primary->surface_desc.ddpfPixelFormat, mode.format_id);
1156 ddraw->flags |= DDRAW_RESTORE_MODE;
1158 if (ddraw->cooperative_level & DDSCL_EXCLUSIVE)
1160 SetRect(&clip_rect, 0, 0, width, height);
1161 ClipCursor(&clip_rect);
1165 InterlockedCompareExchange(&ddraw->device_state, DDRAW_DEVICE_STATE_NOT_RESTORED, DDRAW_DEVICE_STATE_OK);
1167 wined3d_mutex_unlock();
1169 return hr_ddraw_from_wined3d(hr);
1172 static HRESULT WINAPI ddraw4_SetDisplayMode(IDirectDraw4 *iface, DWORD width, DWORD height,
1173 DWORD bpp, DWORD refresh_rate, DWORD flags)
1175 struct ddraw *ddraw = impl_from_IDirectDraw4(iface);
1177 TRACE("iface %p, width %lu, height %lu, bpp %lu, refresh_rate %lu, flags %#lx.\n",
1178 iface, width, height, bpp, refresh_rate, flags);
1180 return ddraw7_SetDisplayMode(&ddraw->IDirectDraw7_iface, width, height, bpp, refresh_rate, flags);
1183 static HRESULT WINAPI ddraw2_SetDisplayMode(IDirectDraw2 *iface,
1184 DWORD width, DWORD height, DWORD bpp, DWORD refresh_rate, DWORD flags)
1186 struct ddraw *ddraw = impl_from_IDirectDraw2(iface);
1188 TRACE("iface %p, width %lu, height %lu, bpp %lu, refresh_rate %lu, flags %#lx.\n",
1189 iface, width, height, bpp, refresh_rate, flags);
1191 return ddraw7_SetDisplayMode(&ddraw->IDirectDraw7_iface, width, height, bpp, refresh_rate, flags);
1194 static HRESULT WINAPI ddraw1_SetDisplayMode(IDirectDraw *iface, DWORD width, DWORD height, DWORD bpp)
1196 struct ddraw *ddraw = impl_from_IDirectDraw(iface);
1198 TRACE("iface %p, width %lu, height %lu, bpp %lu.\n", iface, width, height, bpp);
1200 return ddraw7_SetDisplayMode(&ddraw->IDirectDraw7_iface, width, height, bpp, 0, 0);
1203 void ddraw_d3dcaps1_from_7(D3DDEVICEDESC *caps1, D3DDEVICEDESC7 *caps7)
1205 memset(caps1, 0, sizeof(*caps1));
1206 caps1->dwSize = sizeof(*caps1);
1207 caps1->dwFlags = D3DDD_COLORMODEL
1208 | D3DDD_DEVCAPS
1209 | D3DDD_TRANSFORMCAPS
1210 | D3DDD_BCLIPPING
1211 | D3DDD_LIGHTINGCAPS
1212 | D3DDD_LINECAPS
1213 | D3DDD_TRICAPS
1214 | D3DDD_DEVICERENDERBITDEPTH
1215 | D3DDD_DEVICEZBUFFERBITDEPTH
1216 | D3DDD_MAXBUFFERSIZE
1217 | D3DDD_MAXVERTEXCOUNT;
1218 caps1->dcmColorModel = D3DCOLOR_RGB;
1219 caps1->dwDevCaps = caps7->dwDevCaps;
1220 caps1->dtcTransformCaps.dwSize = sizeof(caps1->dtcTransformCaps);
1221 caps1->dtcTransformCaps.dwCaps = D3DTRANSFORMCAPS_CLIP;
1222 caps1->bClipping = TRUE;
1223 caps1->dlcLightingCaps.dwSize = sizeof(caps1->dlcLightingCaps);
1224 caps1->dlcLightingCaps.dwCaps = D3DLIGHTCAPS_DIRECTIONAL
1225 | D3DLIGHTCAPS_PARALLELPOINT
1226 | D3DLIGHTCAPS_POINT
1227 | D3DLIGHTCAPS_SPOT;
1228 caps1->dlcLightingCaps.dwLightingModel = D3DLIGHTINGMODEL_RGB;
1229 caps1->dlcLightingCaps.dwNumLights = caps7->dwMaxActiveLights;
1230 caps1->dpcLineCaps = caps7->dpcLineCaps;
1231 caps1->dpcTriCaps = caps7->dpcTriCaps;
1232 caps1->dwDeviceRenderBitDepth = caps7->dwDeviceRenderBitDepth;
1233 caps1->dwDeviceZBufferBitDepth = caps7->dwDeviceZBufferBitDepth;
1234 caps1->dwMaxBufferSize = 0;
1235 caps1->dwMaxVertexCount = 65536;
1236 caps1->dwMinTextureWidth = caps7->dwMinTextureWidth;
1237 caps1->dwMinTextureHeight = caps7->dwMinTextureHeight;
1238 caps1->dwMaxTextureWidth = caps7->dwMaxTextureWidth;
1239 caps1->dwMaxTextureHeight = caps7->dwMaxTextureHeight;
1240 caps1->dwMinStippleWidth = 1;
1241 caps1->dwMinStippleHeight = 1;
1242 caps1->dwMaxStippleWidth = 32;
1243 caps1->dwMaxStippleHeight = 32;
1244 caps1->dwMaxTextureRepeat = caps7->dwMaxTextureRepeat;
1245 caps1->dwMaxTextureAspectRatio = caps7->dwMaxTextureAspectRatio;
1246 caps1->dwMaxAnisotropy = caps7->dwMaxAnisotropy;
1247 caps1->dvGuardBandLeft = caps7->dvGuardBandLeft;
1248 caps1->dvGuardBandTop = caps7->dvGuardBandTop;
1249 caps1->dvGuardBandRight = caps7->dvGuardBandRight;
1250 caps1->dvGuardBandBottom = caps7->dvGuardBandBottom;
1251 caps1->dvExtentsAdjust = caps7->dvExtentsAdjust;
1252 caps1->dwStencilCaps = caps7->dwStencilCaps;
1253 caps1->dwFVFCaps = caps7->dwFVFCaps;
1254 caps1->dwTextureOpCaps = caps7->dwTextureOpCaps;
1255 caps1->wMaxTextureBlendStages = caps7->wMaxTextureBlendStages;
1256 caps1->wMaxSimultaneousTextures = caps7->wMaxSimultaneousTextures;
1259 HRESULT ddraw_get_d3dcaps(const struct ddraw *ddraw, D3DDEVICEDESC7 *caps)
1261 struct wined3d_caps wined3d_caps;
1262 HRESULT hr;
1264 TRACE("ddraw %p, caps %p.\n", ddraw, caps);
1266 memset(&wined3d_caps, 0, sizeof(wined3d_caps));
1268 wined3d_mutex_lock();
1269 hr = wined3d_get_device_caps(ddraw->wined3d_adapter, WINED3D_DEVICE_TYPE_HAL, &wined3d_caps);
1270 wined3d_mutex_unlock();
1271 if (FAILED(hr))
1273 WARN("Failed to get device caps, hr %#lx.\n", hr);
1274 return hr;
1277 caps->dwDevCaps = wined3d_caps.DevCaps;
1278 caps->dpcLineCaps.dwMiscCaps = wined3d_caps.PrimitiveMiscCaps;
1279 caps->dpcLineCaps.dwRasterCaps = wined3d_caps.RasterCaps;
1280 caps->dpcLineCaps.dwZCmpCaps = wined3d_caps.ZCmpCaps;
1281 caps->dpcLineCaps.dwSrcBlendCaps = wined3d_caps.SrcBlendCaps;
1282 caps->dpcLineCaps.dwDestBlendCaps = wined3d_caps.DestBlendCaps;
1283 caps->dpcLineCaps.dwAlphaCmpCaps = wined3d_caps.AlphaCmpCaps;
1284 caps->dpcLineCaps.dwShadeCaps = wined3d_caps.ShadeCaps;
1285 caps->dpcLineCaps.dwTextureCaps = wined3d_caps.TextureCaps;
1286 caps->dpcLineCaps.dwTextureFilterCaps = wined3d_caps.TextureFilterCaps;
1287 caps->dpcLineCaps.dwTextureAddressCaps = wined3d_caps.TextureAddressCaps;
1289 caps->dwMaxTextureWidth = wined3d_caps.MaxTextureWidth;
1290 caps->dwMaxTextureHeight = wined3d_caps.MaxTextureHeight;
1292 caps->dwMaxTextureRepeat = wined3d_caps.MaxTextureRepeat;
1293 caps->dwMaxTextureAspectRatio = wined3d_caps.MaxTextureAspectRatio;
1294 caps->dwMaxAnisotropy = wined3d_caps.MaxAnisotropy;
1295 caps->dvMaxVertexW = wined3d_caps.MaxVertexW;
1297 caps->dvGuardBandLeft = wined3d_caps.GuardBandLeft;
1298 caps->dvGuardBandTop = wined3d_caps.GuardBandTop;
1299 caps->dvGuardBandRight = wined3d_caps.GuardBandRight;
1300 caps->dvGuardBandBottom = wined3d_caps.GuardBandBottom;
1302 caps->dvExtentsAdjust = wined3d_caps.ExtentsAdjust;
1303 caps->dwStencilCaps = wined3d_caps.StencilCaps;
1305 caps->dwFVFCaps = wined3d_caps.FVFCaps;
1306 caps->dwTextureOpCaps = wined3d_caps.TextureOpCaps;
1308 caps->dwVertexProcessingCaps = wined3d_caps.VertexProcessingCaps;
1309 caps->dwMaxActiveLights = wined3d_caps.MaxActiveLights;
1311 /* Remove all non-d3d7 caps */
1312 caps->dwDevCaps &= (
1313 D3DDEVCAPS_FLOATTLVERTEX | D3DDEVCAPS_SORTINCREASINGZ | D3DDEVCAPS_SORTDECREASINGZ |
1314 D3DDEVCAPS_SORTEXACT | D3DDEVCAPS_EXECUTESYSTEMMEMORY | D3DDEVCAPS_EXECUTEVIDEOMEMORY |
1315 D3DDEVCAPS_TLVERTEXSYSTEMMEMORY | D3DDEVCAPS_TLVERTEXVIDEOMEMORY | D3DDEVCAPS_TEXTURESYSTEMMEMORY |
1316 D3DDEVCAPS_TEXTUREVIDEOMEMORY | D3DDEVCAPS_DRAWPRIMTLVERTEX | D3DDEVCAPS_CANRENDERAFTERFLIP |
1317 D3DDEVCAPS_TEXTURENONLOCALVIDMEM | D3DDEVCAPS_DRAWPRIMITIVES2 | D3DDEVCAPS_SEPARATETEXTUREMEMORIES |
1318 D3DDEVCAPS_DRAWPRIMITIVES2EX | D3DDEVCAPS_HWTRANSFORMANDLIGHT | D3DDEVCAPS_CANBLTSYSTONONLOCAL |
1319 D3DDEVCAPS_HWRASTERIZATION);
1321 caps->dwStencilCaps &= (
1322 D3DSTENCILCAPS_KEEP | D3DSTENCILCAPS_ZERO | D3DSTENCILCAPS_REPLACE |
1323 D3DSTENCILCAPS_INCRSAT | D3DSTENCILCAPS_DECRSAT | D3DSTENCILCAPS_INVERT |
1324 D3DSTENCILCAPS_INCR | D3DSTENCILCAPS_DECR);
1326 /* FVF caps ?*/
1328 caps->dwTextureOpCaps &= (
1329 D3DTEXOPCAPS_DISABLE | D3DTEXOPCAPS_SELECTARG1 | D3DTEXOPCAPS_SELECTARG2 |
1330 D3DTEXOPCAPS_MODULATE | D3DTEXOPCAPS_MODULATE2X | D3DTEXOPCAPS_MODULATE4X |
1331 D3DTEXOPCAPS_ADD | D3DTEXOPCAPS_ADDSIGNED | D3DTEXOPCAPS_ADDSIGNED2X |
1332 D3DTEXOPCAPS_SUBTRACT | D3DTEXOPCAPS_ADDSMOOTH | D3DTEXOPCAPS_BLENDTEXTUREALPHA |
1333 D3DTEXOPCAPS_BLENDFACTORALPHA | D3DTEXOPCAPS_BLENDTEXTUREALPHAPM | D3DTEXOPCAPS_BLENDCURRENTALPHA |
1334 D3DTEXOPCAPS_PREMODULATE | D3DTEXOPCAPS_MODULATEALPHA_ADDCOLOR | D3DTEXOPCAPS_MODULATECOLOR_ADDALPHA |
1335 D3DTEXOPCAPS_MODULATEINVALPHA_ADDCOLOR | D3DTEXOPCAPS_MODULATEINVCOLOR_ADDALPHA | D3DTEXOPCAPS_BUMPENVMAP |
1336 D3DTEXOPCAPS_BUMPENVMAPLUMINANCE | D3DTEXOPCAPS_DOTPRODUCT3);
1338 caps->dwVertexProcessingCaps &= (
1339 D3DVTXPCAPS_TEXGEN | D3DVTXPCAPS_MATERIALSOURCE7 | D3DVTXPCAPS_VERTEXFOG |
1340 D3DVTXPCAPS_DIRECTIONALLIGHTS | D3DVTXPCAPS_POSITIONALLIGHTS | D3DVTXPCAPS_LOCALVIEWER);
1342 caps->dpcLineCaps.dwMiscCaps &= (
1343 D3DPMISCCAPS_MASKPLANES | D3DPMISCCAPS_MASKZ | D3DPMISCCAPS_LINEPATTERNREP |
1344 D3DPMISCCAPS_CONFORMANT | D3DPMISCCAPS_CULLNONE | D3DPMISCCAPS_CULLCW |
1345 D3DPMISCCAPS_CULLCCW);
1347 caps->dpcLineCaps.dwRasterCaps &= (
1348 D3DPRASTERCAPS_DITHER | D3DPRASTERCAPS_ROP2 | D3DPRASTERCAPS_XOR |
1349 D3DPRASTERCAPS_PAT | D3DPRASTERCAPS_ZTEST | D3DPRASTERCAPS_SUBPIXEL |
1350 D3DPRASTERCAPS_SUBPIXELX | D3DPRASTERCAPS_FOGVERTEX | D3DPRASTERCAPS_FOGTABLE |
1351 D3DPRASTERCAPS_STIPPLE | D3DPRASTERCAPS_ANTIALIASSORTDEPENDENT | D3DPRASTERCAPS_ANTIALIASSORTINDEPENDENT |
1352 D3DPRASTERCAPS_ANTIALIASEDGES | D3DPRASTERCAPS_MIPMAPLODBIAS |
1353 D3DPRASTERCAPS_ZBUFFERLESSHSR | D3DPRASTERCAPS_FOGRANGE | D3DPRASTERCAPS_ANISOTROPY |
1354 D3DPRASTERCAPS_WBUFFER | D3DPRASTERCAPS_TRANSLUCENTSORTINDEPENDENT | D3DPRASTERCAPS_WFOG |
1355 D3DPRASTERCAPS_ZFOG | WINED3DPRASTERCAPS_DEPTHBIAS);
1356 if (caps->dpcLineCaps.dwRasterCaps & WINED3DPRASTERCAPS_DEPTHBIAS)
1357 caps->dpcLineCaps.dwRasterCaps = (caps->dpcLineCaps.dwRasterCaps | D3DPRASTERCAPS_ZBIAS)
1358 & ~WINED3DPRASTERCAPS_DEPTHBIAS;
1359 if (wined3d_caps.LineCaps & WINED3DLINECAPS_ANTIALIAS)
1360 caps->dpcLineCaps.dwRasterCaps |= D3DPRASTERCAPS_ANTIALIASEDGES;
1362 caps->dpcLineCaps.dwZCmpCaps &= (
1363 D3DPCMPCAPS_NEVER | D3DPCMPCAPS_LESS | D3DPCMPCAPS_EQUAL |
1364 D3DPCMPCAPS_LESSEQUAL | D3DPCMPCAPS_GREATER | D3DPCMPCAPS_NOTEQUAL |
1365 D3DPCMPCAPS_GREATEREQUAL | D3DPCMPCAPS_ALWAYS);
1367 caps->dpcLineCaps.dwSrcBlendCaps &= (
1368 D3DPBLENDCAPS_ZERO | D3DPBLENDCAPS_ONE | D3DPBLENDCAPS_SRCCOLOR |
1369 D3DPBLENDCAPS_INVSRCCOLOR | D3DPBLENDCAPS_SRCALPHA | D3DPBLENDCAPS_INVSRCALPHA |
1370 D3DPBLENDCAPS_DESTALPHA | D3DPBLENDCAPS_INVDESTALPHA | D3DPBLENDCAPS_DESTCOLOR |
1371 D3DPBLENDCAPS_INVDESTCOLOR | D3DPBLENDCAPS_SRCALPHASAT | D3DPBLENDCAPS_BOTHSRCALPHA |
1372 D3DPBLENDCAPS_BOTHINVSRCALPHA);
1374 caps->dpcLineCaps.dwDestBlendCaps &= (
1375 D3DPBLENDCAPS_ZERO | D3DPBLENDCAPS_ONE | D3DPBLENDCAPS_SRCCOLOR |
1376 D3DPBLENDCAPS_INVSRCCOLOR | D3DPBLENDCAPS_SRCALPHA | D3DPBLENDCAPS_INVSRCALPHA |
1377 D3DPBLENDCAPS_DESTALPHA | D3DPBLENDCAPS_INVDESTALPHA | D3DPBLENDCAPS_DESTCOLOR |
1378 D3DPBLENDCAPS_INVDESTCOLOR | D3DPBLENDCAPS_SRCALPHASAT | D3DPBLENDCAPS_BOTHSRCALPHA |
1379 D3DPBLENDCAPS_BOTHINVSRCALPHA);
1381 caps->dpcLineCaps.dwAlphaCmpCaps &= (
1382 D3DPCMPCAPS_NEVER | D3DPCMPCAPS_LESS | D3DPCMPCAPS_EQUAL |
1383 D3DPCMPCAPS_LESSEQUAL | D3DPCMPCAPS_GREATER | D3DPCMPCAPS_NOTEQUAL |
1384 D3DPCMPCAPS_GREATEREQUAL | D3DPCMPCAPS_ALWAYS);
1386 caps->dpcLineCaps.dwShadeCaps &= (
1387 D3DPSHADECAPS_COLORFLATMONO | D3DPSHADECAPS_COLORFLATRGB | D3DPSHADECAPS_COLORGOURAUDMONO |
1388 D3DPSHADECAPS_COLORGOURAUDRGB | D3DPSHADECAPS_COLORPHONGMONO | D3DPSHADECAPS_COLORPHONGRGB |
1389 D3DPSHADECAPS_SPECULARFLATMONO | D3DPSHADECAPS_SPECULARFLATRGB | D3DPSHADECAPS_SPECULARGOURAUDMONO |
1390 D3DPSHADECAPS_SPECULARGOURAUDRGB | D3DPSHADECAPS_SPECULARPHONGMONO | D3DPSHADECAPS_SPECULARPHONGRGB |
1391 D3DPSHADECAPS_ALPHAFLATBLEND | D3DPSHADECAPS_ALPHAFLATSTIPPLED | D3DPSHADECAPS_ALPHAGOURAUDBLEND |
1392 D3DPSHADECAPS_ALPHAGOURAUDSTIPPLED | D3DPSHADECAPS_ALPHAPHONGBLEND | D3DPSHADECAPS_ALPHAPHONGSTIPPLED |
1393 D3DPSHADECAPS_FOGFLAT | D3DPSHADECAPS_FOGGOURAUD | D3DPSHADECAPS_FOGPHONG);
1395 caps->dpcLineCaps.dwTextureCaps &= (
1396 D3DPTEXTURECAPS_PERSPECTIVE | D3DPTEXTURECAPS_POW2 | D3DPTEXTURECAPS_ALPHA |
1397 D3DPTEXTURECAPS_TRANSPARENCY | D3DPTEXTURECAPS_BORDER | D3DPTEXTURECAPS_SQUAREONLY |
1398 D3DPTEXTURECAPS_TEXREPEATNOTSCALEDBYSIZE | D3DPTEXTURECAPS_ALPHAPALETTE| D3DPTEXTURECAPS_NONPOW2CONDITIONAL |
1399 D3DPTEXTURECAPS_PROJECTED | D3DPTEXTURECAPS_CUBEMAP | D3DPTEXTURECAPS_COLORKEYBLEND);
1401 caps->dpcLineCaps.dwTextureFilterCaps &= (
1402 D3DPTFILTERCAPS_NEAREST | D3DPTFILTERCAPS_LINEAR | D3DPTFILTERCAPS_MIPNEAREST |
1403 D3DPTFILTERCAPS_MIPLINEAR | D3DPTFILTERCAPS_LINEARMIPNEAREST | D3DPTFILTERCAPS_LINEARMIPLINEAR |
1404 D3DPTFILTERCAPS_MINFPOINT | D3DPTFILTERCAPS_MINFLINEAR | D3DPTFILTERCAPS_MINFANISOTROPIC |
1405 D3DPTFILTERCAPS_MIPFPOINT | D3DPTFILTERCAPS_MIPFLINEAR | D3DPTFILTERCAPS_MAGFPOINT |
1406 D3DPTFILTERCAPS_MAGFLINEAR | D3DPTFILTERCAPS_MAGFANISOTROPIC | D3DPTFILTERCAPS_MAGFAFLATCUBIC |
1407 D3DPTFILTERCAPS_MAGFGAUSSIANCUBIC);
1409 caps->dpcLineCaps.dwTextureAddressCaps &= (
1410 D3DPTADDRESSCAPS_WRAP | D3DPTADDRESSCAPS_MIRROR | D3DPTADDRESSCAPS_CLAMP |
1411 D3DPTADDRESSCAPS_BORDER | D3DPTADDRESSCAPS_INDEPENDENTUV);
1413 if (!(caps->dpcLineCaps.dwTextureCaps & D3DPTEXTURECAPS_POW2))
1415 /* DirectX7 always has the np2 flag set, no matter what the card
1416 * supports. Some old games (Rollcage) check the caps incorrectly.
1417 * If wined3d supports nonpow2 textures it also has np2 conditional
1418 * support. */
1419 caps->dpcLineCaps.dwTextureCaps |= D3DPTEXTURECAPS_POW2 | D3DPTEXTURECAPS_NONPOW2CONDITIONAL;
1422 /* Fill the missing members, and do some fixup */
1423 caps->dpcLineCaps.dwSize = sizeof(caps->dpcLineCaps);
1424 caps->dpcLineCaps.dwTextureBlendCaps = D3DPTBLENDCAPS_ADD
1425 | D3DPTBLENDCAPS_MODULATEMASK
1426 | D3DPTBLENDCAPS_COPY
1427 | D3DPTBLENDCAPS_DECAL
1428 | D3DPTBLENDCAPS_DECALALPHA
1429 | D3DPTBLENDCAPS_DECALMASK
1430 | D3DPTBLENDCAPS_MODULATE
1431 | D3DPTBLENDCAPS_MODULATEALPHA;
1432 caps->dpcLineCaps.dwStippleWidth = 32;
1433 caps->dpcLineCaps.dwStippleHeight = 32;
1434 /* Use the same for the TriCaps */
1435 caps->dpcTriCaps = caps->dpcLineCaps;
1437 caps->dwDeviceRenderBitDepth = DDBD_16 | DDBD_24 | DDBD_32;
1438 caps->dwDeviceZBufferBitDepth = DDBD_16 | DDBD_24;
1439 caps->dwMinTextureWidth = 1;
1440 caps->dwMinTextureHeight = 1;
1442 /* Convert DWORDs safely to WORDs */
1443 caps->wMaxTextureBlendStages = min(wined3d_caps.MaxTextureBlendStages, 0xffff);
1444 caps->wMaxSimultaneousTextures = min(wined3d_caps.MaxSimultaneousTextures, 0xffff);
1445 caps->wMaxUserClipPlanes = min(wined3d_caps.MaxUserClipPlanes, D3DMAXUSERCLIPPLANES);
1446 caps->wMaxVertexBlendMatrices = min(wined3d_caps.MaxVertexBlendMatrices, 0xffff);
1448 caps->deviceGUID = IID_IDirect3DTnLHalDevice;
1450 caps->dwReserved1 = 0;
1451 caps->dwReserved2 = 0;
1452 caps->dwReserved3 = 0;
1453 caps->dwReserved4 = 0;
1455 return DD_OK;
1458 /*****************************************************************************
1459 * IDirectDraw7::GetCaps
1461 * Returns the drives capabilities
1463 * Used for version 1, 2, 4 and 7
1465 * Params:
1466 * DriverCaps: Structure to write the Hardware accelerated caps to
1467 * HelCaps: Structure to write the emulation caps to
1469 * Returns
1470 * This implementation returns DD_OK only
1472 *****************************************************************************/
1473 static HRESULT WINAPI ddraw7_GetCaps(IDirectDraw7 *iface, DDCAPS *DriverCaps, DDCAPS *HELCaps)
1475 struct ddraw *ddraw = impl_from_IDirectDraw7(iface);
1476 DDSCAPS2 ddscaps = {0, 0, 0, {0}};
1477 struct wined3d_caps winecaps;
1478 DDCAPS caps;
1479 HRESULT hr;
1481 TRACE("iface %p, driver_caps %p, hel_caps %p.\n", iface, DriverCaps, HELCaps);
1483 /* One structure must be != NULL */
1484 if (!DriverCaps && !HELCaps)
1486 WARN("Invalid parameters.\n");
1487 return DDERR_INVALIDPARAMS;
1490 memset(&caps, 0, sizeof(caps));
1491 memset(&winecaps, 0, sizeof(winecaps));
1492 caps.dwSize = sizeof(caps);
1494 wined3d_mutex_lock();
1495 hr = wined3d_device_get_device_caps(ddraw->wined3d_device, &winecaps);
1496 if (FAILED(hr))
1498 WARN("Failed to get device caps, %#lx.\n", hr);
1499 wined3d_mutex_unlock();
1500 return hr;
1503 hr = IDirectDraw7_GetAvailableVidMem(iface, &ddscaps, &caps.dwVidMemTotal, &caps.dwVidMemFree);
1504 if (FAILED(hr))
1506 WARN("IDirectDraw7::GetAvailableVidMem failed\n");
1507 wined3d_mutex_unlock();
1508 return hr;
1511 hr = IDirectDraw7_GetFourCCCodes(iface, &caps.dwNumFourCCCodes, NULL);
1512 wined3d_mutex_unlock();
1513 if (FAILED(hr))
1515 WARN("IDirectDraw7::GetFourCCCodes failed\n");
1516 return hr;
1519 caps.dwCaps = winecaps.ddraw_caps.caps;
1520 caps.dwCaps2 = winecaps.ddraw_caps.caps2;
1521 caps.dwCKeyCaps = winecaps.ddraw_caps.color_key_caps;
1522 caps.dwFXCaps = winecaps.ddraw_caps.fx_caps;
1523 caps.dwPalCaps = DDPCAPS_8BIT | DDPCAPS_PRIMARYSURFACE;
1524 caps.ddsCaps.dwCaps = winecaps.ddraw_caps.dds_caps;
1525 caps.dwSVBCaps = winecaps.ddraw_caps.svb_caps;
1526 caps.dwSVBCKeyCaps = winecaps.ddraw_caps.svb_color_key_caps;
1527 caps.dwSVBFXCaps = winecaps.ddraw_caps.svb_fx_caps;
1528 caps.dwVSBCaps = winecaps.ddraw_caps.vsb_caps;
1529 caps.dwVSBCKeyCaps = winecaps.ddraw_caps.vsb_color_key_caps;
1530 caps.dwVSBFXCaps = winecaps.ddraw_caps.vsb_fx_caps;
1531 caps.dwSSBCaps = winecaps.ddraw_caps.ssb_caps;
1532 caps.dwSSBCKeyCaps = winecaps.ddraw_caps.ssb_color_key_caps;
1533 caps.dwSSBFXCaps = winecaps.ddraw_caps.ssb_fx_caps;
1535 caps.dwCaps |= DDCAPS_ALIGNSTRIDE;
1536 caps.dwAlignStrideAlign = DDRAW_STRIDE_ALIGNMENT;
1538 caps.ddsOldCaps.dwCaps = caps.ddsCaps.dwCaps;
1540 if(DriverCaps)
1542 DD_STRUCT_COPY_BYSIZE(DriverCaps, &caps);
1543 if (TRACE_ON(ddraw))
1545 TRACE("Driver Caps :\n");
1546 DDRAW_dump_DDCAPS(DriverCaps);
1550 if(HELCaps)
1552 DD_STRUCT_COPY_BYSIZE(HELCaps, &caps);
1553 if (TRACE_ON(ddraw))
1555 TRACE("HEL Caps :\n");
1556 DDRAW_dump_DDCAPS(HELCaps);
1560 return DD_OK;
1563 static HRESULT WINAPI ddraw4_GetCaps(IDirectDraw4 *iface, DDCAPS *driver_caps, DDCAPS *hel_caps)
1565 struct ddraw *ddraw = impl_from_IDirectDraw4(iface);
1567 TRACE("iface %p, driver_caps %p, hel_caps %p.\n", iface, driver_caps, hel_caps);
1569 return ddraw7_GetCaps(&ddraw->IDirectDraw7_iface, driver_caps, hel_caps);
1572 static HRESULT WINAPI ddraw2_GetCaps(IDirectDraw2 *iface, DDCAPS *driver_caps, DDCAPS *hel_caps)
1574 struct ddraw *ddraw = impl_from_IDirectDraw2(iface);
1576 TRACE("iface %p, driver_caps %p, hel_caps %p.\n", iface, driver_caps, hel_caps);
1578 return ddraw7_GetCaps(&ddraw->IDirectDraw7_iface, driver_caps, hel_caps);
1581 static HRESULT WINAPI ddraw1_GetCaps(IDirectDraw *iface, DDCAPS *driver_caps, DDCAPS *hel_caps)
1583 struct ddraw *ddraw = impl_from_IDirectDraw(iface);
1585 TRACE("iface %p, driver_caps %p, hel_caps %p.\n", iface, driver_caps, hel_caps);
1587 return ddraw7_GetCaps(&ddraw->IDirectDraw7_iface, driver_caps, hel_caps);
1590 /*****************************************************************************
1591 * IDirectDraw7::Compact
1593 * No idea what it does, MSDN says it's not implemented.
1595 * Returns
1596 * DD_OK, but this is unchecked
1598 *****************************************************************************/
1599 static HRESULT WINAPI ddraw7_Compact(IDirectDraw7 *iface)
1601 TRACE("iface %p.\n", iface);
1603 return DD_OK;
1606 static HRESULT WINAPI ddraw4_Compact(IDirectDraw4 *iface)
1608 struct ddraw *ddraw = impl_from_IDirectDraw4(iface);
1610 TRACE("iface %p.\n", iface);
1612 return ddraw7_Compact(&ddraw->IDirectDraw7_iface);
1615 static HRESULT WINAPI ddraw2_Compact(IDirectDraw2 *iface)
1617 struct ddraw *ddraw = impl_from_IDirectDraw2(iface);
1619 TRACE("iface %p.\n", iface);
1621 return ddraw7_Compact(&ddraw->IDirectDraw7_iface);
1624 static HRESULT WINAPI ddraw1_Compact(IDirectDraw *iface)
1626 struct ddraw *ddraw = impl_from_IDirectDraw(iface);
1628 TRACE("iface %p.\n", iface);
1630 return ddraw7_Compact(&ddraw->IDirectDraw7_iface);
1633 /*****************************************************************************
1634 * IDirectDraw7::GetDisplayMode
1636 * Returns information about the current display mode
1638 * Exists in versions 1, 2, 4 and 7
1640 * Params:
1641 * DDSD: Address of a surface description structure to write the info to
1643 * Returns
1644 * DD_OK
1646 *****************************************************************************/
1647 static HRESULT WINAPI ddraw7_GetDisplayMode(IDirectDraw7 *iface, DDSURFACEDESC2 *DDSD)
1649 struct ddraw *ddraw = impl_from_IDirectDraw7(iface);
1650 struct wined3d_display_mode mode;
1651 HRESULT hr;
1653 TRACE("iface %p, surface_desc %p.\n", iface, DDSD);
1655 /* This seems sane */
1656 if (!DDSD || (DDSD->dwSize != sizeof(DDSURFACEDESC) && DDSD->dwSize != sizeof(DDSURFACEDESC2)))
1657 return DDERR_INVALIDPARAMS;
1659 wined3d_mutex_lock();
1661 if (FAILED(hr = wined3d_output_get_display_mode(ddraw->wined3d_output, &mode, NULL)))
1663 ERR("Failed to get display mode, hr %#lx.\n", hr);
1664 wined3d_mutex_unlock();
1665 return hr;
1668 memset(DDSD, 0, DDSD->dwSize);
1669 DDSD->dwSize = sizeof(*DDSD);
1670 DDSD->dwFlags = DDSD_HEIGHT | DDSD_WIDTH | DDSD_PIXELFORMAT | DDSD_PITCH | DDSD_REFRESHRATE;
1671 DDSD->dwWidth = mode.width;
1672 DDSD->dwHeight = mode.height;
1673 DDSD->dwRefreshRate = mode.refresh_rate;
1674 DDSD->ddpfPixelFormat.dwSize = sizeof(DDSD->ddpfPixelFormat);
1675 ddrawformat_from_wined3dformat(&DDSD->ddpfPixelFormat, mode.format_id);
1676 DDSD->lPitch = mode.width * DDSD->ddpfPixelFormat.dwRGBBitCount / 8;
1678 if(TRACE_ON(ddraw))
1680 TRACE("Returning surface desc :\n");
1681 DDRAW_dump_surface_desc(DDSD);
1684 wined3d_mutex_unlock();
1686 return DD_OK;
1689 static HRESULT WINAPI ddraw4_GetDisplayMode(IDirectDraw4 *iface, DDSURFACEDESC2 *surface_desc)
1691 struct ddraw *ddraw = impl_from_IDirectDraw4(iface);
1693 TRACE("iface %p, surface_desc %p.\n", iface, surface_desc);
1695 return ddraw7_GetDisplayMode(&ddraw->IDirectDraw7_iface, surface_desc);
1698 static HRESULT WINAPI ddraw2_GetDisplayMode(IDirectDraw2 *iface, DDSURFACEDESC *surface_desc)
1700 struct ddraw *ddraw = impl_from_IDirectDraw2(iface);
1701 HRESULT hr;
1703 TRACE("iface %p, surface_desc %p.\n", iface, surface_desc);
1705 hr = ddraw7_GetDisplayMode(&ddraw->IDirectDraw7_iface, (DDSURFACEDESC2 *)surface_desc);
1706 if (SUCCEEDED(hr)) surface_desc->dwSize = sizeof(*surface_desc);
1707 return hr;
1710 static HRESULT WINAPI ddraw1_GetDisplayMode(IDirectDraw *iface, DDSURFACEDESC *surface_desc)
1712 struct ddraw *ddraw = impl_from_IDirectDraw(iface);
1713 HRESULT hr;
1715 TRACE("iface %p, surface_desc %p.\n", iface, surface_desc);
1717 hr = ddraw7_GetDisplayMode(&ddraw->IDirectDraw7_iface, (DDSURFACEDESC2 *)surface_desc);
1718 if (SUCCEEDED(hr)) surface_desc->dwSize = sizeof(*surface_desc);
1719 return hr;
1722 /*****************************************************************************
1723 * IDirectDraw7::GetFourCCCodes
1725 * Returns an array of supported FourCC codes.
1727 * Exists in versions 1, 2, 4 and 7
1729 * Params:
1730 * NumCodes: Contains the number of Codes that Codes can carry. Returns the number
1731 * of enumerated codes
1732 * Codes: Pointer to an array of DWORDs where the supported codes are written
1733 * to
1735 * Returns
1736 * Always returns DD_OK, as it's a stub for now
1738 *****************************************************************************/
1739 static HRESULT WINAPI ddraw7_GetFourCCCodes(IDirectDraw7 *iface, DWORD *NumCodes, DWORD *Codes)
1741 struct ddraw *ddraw = impl_from_IDirectDraw7(iface);
1742 static const enum wined3d_format_id formats[] =
1744 WINED3DFMT_YUY2, WINED3DFMT_UYVY, WINED3DFMT_YV12,
1745 WINED3DFMT_DXT1, WINED3DFMT_DXT2, WINED3DFMT_DXT3, WINED3DFMT_DXT4, WINED3DFMT_DXT5,
1746 WINED3DFMT_ATI2N, WINED3DFMT_NVHU, WINED3DFMT_NVHS
1748 struct wined3d_display_mode mode;
1749 DWORD count = 0, i, outsize;
1750 HRESULT hr;
1752 TRACE("iface %p, codes_count %p, codes %p.\n", iface, NumCodes, Codes);
1754 if (FAILED(hr = wined3d_output_get_display_mode(ddraw->wined3d_output, &mode, NULL)))
1756 ERR("Failed to get display mode, hr %#lx.\n", hr);
1757 return hr;
1760 outsize = NumCodes && Codes ? *NumCodes : 0;
1762 for (i = 0; i < ARRAY_SIZE(formats); ++i)
1764 if (SUCCEEDED(wined3d_check_device_format(ddraw->wined3d, ddraw->wined3d_adapter, WINED3D_DEVICE_TYPE_HAL,
1765 mode.format_id, 0, 0, WINED3D_RTYPE_TEXTURE_2D, formats[i])))
1767 if (count < outsize)
1768 Codes[count] = formats[i];
1769 ++count;
1772 if(NumCodes) {
1773 TRACE("Returning %lu FourCC codes\n", count);
1774 *NumCodes = count;
1777 return DD_OK;
1780 static HRESULT WINAPI ddraw4_GetFourCCCodes(IDirectDraw4 *iface, DWORD *codes_count, DWORD *codes)
1782 struct ddraw *ddraw = impl_from_IDirectDraw4(iface);
1784 TRACE("iface %p, codes_count %p, codes %p.\n", iface, codes_count, codes);
1786 return ddraw7_GetFourCCCodes(&ddraw->IDirectDraw7_iface, codes_count, codes);
1789 static HRESULT WINAPI ddraw2_GetFourCCCodes(IDirectDraw2 *iface, DWORD *codes_count, DWORD *codes)
1791 struct ddraw *ddraw = impl_from_IDirectDraw2(iface);
1793 TRACE("iface %p, codes_count %p, codes %p.\n", iface, codes_count, codes);
1795 return ddraw7_GetFourCCCodes(&ddraw->IDirectDraw7_iface, codes_count, codes);
1798 static HRESULT WINAPI ddraw1_GetFourCCCodes(IDirectDraw *iface, DWORD *codes_count, DWORD *codes)
1800 struct ddraw *ddraw = impl_from_IDirectDraw(iface);
1802 TRACE("iface %p, codes_count %p, codes %p.\n", iface, codes_count, codes);
1804 return ddraw7_GetFourCCCodes(&ddraw->IDirectDraw7_iface, codes_count, codes);
1807 static HRESULT WINAPI ddraw7_GetMonitorFrequency(IDirectDraw7 *iface, DWORD *frequency)
1809 struct ddraw *ddraw = impl_from_IDirectDraw7(iface);
1810 struct wined3d_display_mode mode;
1811 HRESULT hr;
1813 TRACE("iface %p, frequency %p.\n", iface, frequency);
1815 wined3d_mutex_lock();
1816 hr = wined3d_output_get_display_mode(ddraw->wined3d_output, &mode, NULL);
1817 wined3d_mutex_unlock();
1818 if (FAILED(hr))
1820 WARN("Failed to get display mode, hr %#lx.\n", hr);
1821 return hr;
1824 *frequency = mode.refresh_rate;
1826 return DD_OK;
1829 static HRESULT WINAPI ddraw4_GetMonitorFrequency(IDirectDraw4 *iface, DWORD *frequency)
1831 struct ddraw *ddraw = impl_from_IDirectDraw4(iface);
1833 TRACE("iface %p, frequency %p.\n", iface, frequency);
1835 return ddraw7_GetMonitorFrequency(&ddraw->IDirectDraw7_iface, frequency);
1838 static HRESULT WINAPI ddraw2_GetMonitorFrequency(IDirectDraw2 *iface, DWORD *frequency)
1840 struct ddraw *ddraw = impl_from_IDirectDraw2(iface);
1842 TRACE("iface %p, frequency %p.\n", iface, frequency);
1844 return ddraw7_GetMonitorFrequency(&ddraw->IDirectDraw7_iface, frequency);
1847 static HRESULT WINAPI ddraw1_GetMonitorFrequency(IDirectDraw *iface, DWORD *frequency)
1849 struct ddraw *ddraw = impl_from_IDirectDraw(iface);
1851 TRACE("iface %p, frequency %p.\n", iface, frequency);
1853 return ddraw7_GetMonitorFrequency(&ddraw->IDirectDraw7_iface, frequency);
1856 static HRESULT WINAPI ddraw7_GetVerticalBlankStatus(IDirectDraw7 *iface, BOOL *status)
1858 struct ddraw *ddraw = impl_from_IDirectDraw7(iface);
1859 struct wined3d_raster_status raster_status;
1860 HRESULT hr;
1862 TRACE("iface %p, status %p.\n", iface, status);
1864 if(!status)
1865 return DDERR_INVALIDPARAMS;
1867 wined3d_mutex_lock();
1868 hr = wined3d_output_get_raster_status(ddraw->wined3d_output, &raster_status);
1869 wined3d_mutex_unlock();
1870 if (FAILED(hr))
1872 WARN("Failed to get raster status, hr %#lx.\n", hr);
1873 return hr;
1876 *status = raster_status.in_vblank;
1878 return DD_OK;
1881 static HRESULT WINAPI ddraw4_GetVerticalBlankStatus(IDirectDraw4 *iface, BOOL *status)
1883 struct ddraw *ddraw = impl_from_IDirectDraw4(iface);
1885 TRACE("iface %p, status %p.\n", iface, status);
1887 return ddraw7_GetVerticalBlankStatus(&ddraw->IDirectDraw7_iface, status);
1890 static HRESULT WINAPI ddraw2_GetVerticalBlankStatus(IDirectDraw2 *iface, BOOL *status)
1892 struct ddraw *ddraw = impl_from_IDirectDraw2(iface);
1894 TRACE("iface %p, status %p.\n", iface, status);
1896 return ddraw7_GetVerticalBlankStatus(&ddraw->IDirectDraw7_iface, status);
1899 static HRESULT WINAPI ddraw1_GetVerticalBlankStatus(IDirectDraw *iface, BOOL *status)
1901 struct ddraw *ddraw = impl_from_IDirectDraw(iface);
1903 TRACE("iface %p, status %p.\n", iface, status);
1905 return ddraw7_GetVerticalBlankStatus(&ddraw->IDirectDraw7_iface, status);
1908 /*****************************************************************************
1909 * IDirectDraw7::GetAvailableVidMem
1911 * Returns the total and free video memory
1913 * Params:
1914 * caps: Specifies the memory type asked for
1915 * total: Pointer to a DWORD to be filled with the total memory
1916 * free: Pointer to a DWORD to be filled with the free memory
1918 * Returns
1919 * DD_OK on success
1920 * DDERR_INVALIDPARAMS if free and total are NULL
1922 *****************************************************************************/
1923 static HRESULT WINAPI ddraw7_GetAvailableVidMem(IDirectDraw7 *iface, DDSCAPS2 *caps, DWORD *total,
1924 DWORD *free)
1926 unsigned int framebuffer_size, total_vidmem, free_vidmem;
1927 struct ddraw *ddraw = impl_from_IDirectDraw7(iface);
1928 struct wined3d_display_mode mode;
1929 HRESULT hr = DD_OK;
1931 TRACE("iface %p, caps %p, total %p, free %p.\n", iface, caps, total, free);
1933 if (!total && !free)
1934 return DDERR_INVALIDPARAMS;
1936 if (TRACE_ON(ddraw))
1938 TRACE("Asked for memory with description: ");
1939 DDRAW_dump_DDSCAPS2(caps);
1941 wined3d_mutex_lock();
1943 /* Todo: System memory vs local video memory vs non-local video memory
1944 * The MSDN also mentions differences between texture memory and other
1945 * resources, but that's not important
1948 /* Some applications (e.g. 3DMark 2000) assume that the reported amount of
1949 * video memory doesn't include the memory used by the default framebuffer.
1951 if (FAILED(hr = wined3d_output_get_display_mode(ddraw->wined3d_output, &mode, NULL)))
1953 WARN("Failed to get display mode, hr %#lx.\n", hr);
1954 wined3d_mutex_unlock();
1955 return hr;
1957 framebuffer_size = wined3d_calculate_format_pitch(ddraw->wined3d_adapter,
1958 mode.format_id, mode.width);
1959 framebuffer_size *= mode.height;
1961 if (free)
1963 free_vidmem = wined3d_device_get_available_texture_mem(ddraw->wined3d_device);
1964 *free = framebuffer_size > free_vidmem ? 0 : free_vidmem - framebuffer_size;
1965 TRACE("Free video memory %#lx.\n", *free);
1968 if (total)
1970 struct wined3d_adapter_identifier desc = {0};
1972 hr = wined3d_adapter_get_identifier(ddraw->wined3d_adapter, 0, &desc);
1973 total_vidmem = min(UINT_MAX, desc.video_memory);
1974 *total = framebuffer_size > total_vidmem ? 0 : total_vidmem - framebuffer_size;
1975 TRACE("Total video memory %#lx.\n", *total);
1978 wined3d_mutex_unlock();
1980 return hr;
1983 static HRESULT WINAPI ddraw4_GetAvailableVidMem(IDirectDraw4 *iface,
1984 DDSCAPS2 *caps, DWORD *total, DWORD *free)
1986 struct ddraw *ddraw = impl_from_IDirectDraw4(iface);
1988 TRACE("iface %p, caps %p, total %p, free %p.\n", iface, caps, total, free);
1990 return ddraw7_GetAvailableVidMem(&ddraw->IDirectDraw7_iface, caps, total, free);
1993 static HRESULT WINAPI ddraw2_GetAvailableVidMem(IDirectDraw2 *iface,
1994 DDSCAPS *caps, DWORD *total, DWORD *free)
1996 struct ddraw *ddraw = impl_from_IDirectDraw2(iface);
1997 DDSCAPS2 caps2;
1999 TRACE("iface %p, caps %p, total %p, free %p.\n", iface, caps, total, free);
2001 DDRAW_Convert_DDSCAPS_1_To_2(caps, &caps2);
2002 return ddraw7_GetAvailableVidMem(&ddraw->IDirectDraw7_iface, &caps2, total, free);
2005 /*****************************************************************************
2006 * IDirectDraw7::Initialize
2008 * Initializes a DirectDraw interface.
2010 * Params:
2011 * GUID: Interface identifier. Well, don't know what this is really good
2012 * for
2014 * Returns
2015 * Returns DD_OK on the first call,
2016 * DDERR_ALREADYINITIALIZED on repeated calls
2018 *****************************************************************************/
2019 static HRESULT WINAPI ddraw7_Initialize(IDirectDraw7 *iface, GUID *guid)
2021 struct ddraw *ddraw = impl_from_IDirectDraw7(iface);
2023 TRACE("iface %p, guid %s.\n", iface, debugstr_guid(guid));
2025 if (ddraw->flags & DDRAW_INITIALIZED)
2026 return DDERR_ALREADYINITIALIZED;
2028 /* FIXME: To properly take the GUID into account we should call
2029 * ddraw_init() here instead of in DDRAW_Create(). */
2030 if (guid)
2031 FIXME("Ignoring guid %s.\n", debugstr_guid(guid));
2033 ddraw->flags |= DDRAW_INITIALIZED;
2034 return DD_OK;
2037 static HRESULT WINAPI ddraw4_Initialize(IDirectDraw4 *iface, GUID *guid)
2039 struct ddraw *ddraw = impl_from_IDirectDraw4(iface);
2041 TRACE("iface %p, guid %s.\n", iface, debugstr_guid(guid));
2043 return ddraw7_Initialize(&ddraw->IDirectDraw7_iface, guid);
2046 static HRESULT WINAPI ddraw2_Initialize(IDirectDraw2 *iface, GUID *guid)
2048 struct ddraw *ddraw = impl_from_IDirectDraw2(iface);
2050 TRACE("iface %p, guid %s.\n", iface, debugstr_guid(guid));
2052 return ddraw7_Initialize(&ddraw->IDirectDraw7_iface, guid);
2055 static HRESULT WINAPI ddraw1_Initialize(IDirectDraw *iface, GUID *guid)
2057 struct ddraw *ddraw = impl_from_IDirectDraw(iface);
2059 TRACE("iface %p, guid %s.\n", iface, debugstr_guid(guid));
2061 return ddraw7_Initialize(&ddraw->IDirectDraw7_iface, guid);
2064 static HRESULT WINAPI d3d1_Initialize(IDirect3D *iface, REFIID riid)
2066 TRACE("iface %p, riid %s.\n", iface, debugstr_guid(riid));
2068 return DDERR_ALREADYINITIALIZED;
2071 /*****************************************************************************
2072 * IDirectDraw7::FlipToGDISurface
2074 * "Makes the surface that the GDI writes to the primary surface"
2075 * Looks like some windows specific thing we don't have to care about.
2076 * According to MSDN it permits GDI dialog boxes in FULLSCREEN mode. Good to
2077 * show error boxes ;)
2078 * Well, just return DD_OK.
2080 * Returns:
2081 * Always returns DD_OK
2083 *****************************************************************************/
2084 static HRESULT WINAPI ddraw7_FlipToGDISurface(IDirectDraw7 *iface)
2086 struct ddraw *ddraw = impl_from_IDirectDraw7(iface);
2087 IDirectDrawSurface7 *gdi_surface;
2088 struct ddraw_surface *gdi_impl;
2089 HRESULT hr;
2091 TRACE("iface %p.\n", iface);
2093 wined3d_mutex_lock();
2095 if (FAILED(hr = IDirectDraw7_GetGDISurface(iface, &gdi_surface)))
2097 WARN("Failed to retrieve GDI surface, hr %#lx.\n", hr);
2098 wined3d_mutex_unlock();
2099 return hr;
2102 gdi_impl = impl_from_IDirectDrawSurface7(gdi_surface);
2103 if (gdi_impl->surface_desc.ddsCaps.dwCaps & DDSCAPS_FRONTBUFFER)
2104 hr = DD_OK;
2105 else
2106 hr = IDirectDrawSurface7_Flip(&ddraw->primary->IDirectDrawSurface7_iface, gdi_surface, DDFLIP_WAIT);
2107 IDirectDrawSurface7_Release(gdi_surface);
2109 wined3d_mutex_unlock();
2111 return hr;
2114 static HRESULT WINAPI ddraw4_FlipToGDISurface(IDirectDraw4 *iface)
2116 struct ddraw *ddraw = impl_from_IDirectDraw4(iface);
2118 TRACE("iface %p.\n", iface);
2120 return ddraw7_FlipToGDISurface(&ddraw->IDirectDraw7_iface);
2123 static HRESULT WINAPI ddraw2_FlipToGDISurface(IDirectDraw2 *iface)
2125 struct ddraw *ddraw = impl_from_IDirectDraw2(iface);
2127 TRACE("iface %p.\n", iface);
2129 return ddraw7_FlipToGDISurface(&ddraw->IDirectDraw7_iface);
2132 static HRESULT WINAPI ddraw1_FlipToGDISurface(IDirectDraw *iface)
2134 struct ddraw *ddraw = impl_from_IDirectDraw(iface);
2136 TRACE("iface %p.\n", iface);
2138 return ddraw7_FlipToGDISurface(&ddraw->IDirectDraw7_iface);
2141 /*****************************************************************************
2142 * IDirectDraw7::WaitForVerticalBlank
2144 * This method allows applications to get in sync with the vertical blank
2145 * interval.
2146 * The wormhole demo in the DirectX 7 sdk uses this call, and it doesn't
2147 * redraw the screen, most likely because of this stub
2149 * Parameters:
2150 * Flags: one of DDWAITVB_BLOCKBEGIN, DDWAITVB_BLOCKBEGINEVENT
2151 * or DDWAITVB_BLOCKEND
2152 * h: Not used, according to MSDN
2154 * Returns:
2155 * Always returns DD_OK
2157 *****************************************************************************/
2158 static HRESULT WINAPI ddraw7_WaitForVerticalBlank(IDirectDraw7 *iface, DWORD Flags, HANDLE event)
2160 static BOOL hide;
2162 TRACE("iface %p, flags %#lx, event %p.\n", iface, Flags, event);
2164 /* This function is called often, so print the fixme only once */
2165 if(!hide)
2167 FIXME("iface %p, flags %#lx, event %p stub!\n", iface, Flags, event);
2168 hide = TRUE;
2171 /* MSDN says DDWAITVB_BLOCKBEGINEVENT is not supported */
2172 if(Flags & DDWAITVB_BLOCKBEGINEVENT)
2173 return DDERR_UNSUPPORTED; /* unchecked */
2175 return DD_OK;
2178 static HRESULT WINAPI ddraw4_WaitForVerticalBlank(IDirectDraw4 *iface, DWORD flags, HANDLE event)
2180 struct ddraw *ddraw = impl_from_IDirectDraw4(iface);
2182 TRACE("iface %p, flags %#lx, event %p.\n", iface, flags, event);
2184 return ddraw7_WaitForVerticalBlank(&ddraw->IDirectDraw7_iface, flags, event);
2187 static HRESULT WINAPI ddraw2_WaitForVerticalBlank(IDirectDraw2 *iface, DWORD flags, HANDLE event)
2189 struct ddraw *ddraw = impl_from_IDirectDraw2(iface);
2191 TRACE("iface %p, flags %#lx, event %p.\n", iface, flags, event);
2193 return ddraw7_WaitForVerticalBlank(&ddraw->IDirectDraw7_iface, flags, event);
2196 static HRESULT WINAPI ddraw1_WaitForVerticalBlank(IDirectDraw *iface, DWORD flags, HANDLE event)
2198 struct ddraw *ddraw = impl_from_IDirectDraw(iface);
2200 TRACE("iface %p, flags %#lx, event %p.\n", iface, flags, event);
2202 return ddraw7_WaitForVerticalBlank(&ddraw->IDirectDraw7_iface, flags, event);
2205 static HRESULT WINAPI ddraw7_GetScanLine(IDirectDraw7 *iface, DWORD *Scanline)
2207 struct ddraw *ddraw = impl_from_IDirectDraw7(iface);
2208 struct wined3d_raster_status raster_status;
2209 HRESULT hr;
2211 TRACE("iface %p, line %p.\n", iface, Scanline);
2213 wined3d_mutex_lock();
2214 hr = wined3d_output_get_raster_status(ddraw->wined3d_output, &raster_status);
2215 wined3d_mutex_unlock();
2216 if (FAILED(hr))
2218 WARN("Failed to get raster status, hr %#lx.\n", hr);
2219 return hr;
2222 *Scanline = raster_status.scan_line;
2224 if (raster_status.in_vblank)
2225 return DDERR_VERTICALBLANKINPROGRESS;
2227 return DD_OK;
2230 static HRESULT WINAPI ddraw4_GetScanLine(IDirectDraw4 *iface, DWORD *line)
2232 struct ddraw *ddraw = impl_from_IDirectDraw4(iface);
2234 TRACE("iface %p, line %p.\n", iface, line);
2236 return ddraw7_GetScanLine(&ddraw->IDirectDraw7_iface, line);
2239 static HRESULT WINAPI ddraw2_GetScanLine(IDirectDraw2 *iface, DWORD *line)
2241 struct ddraw *ddraw = impl_from_IDirectDraw2(iface);
2243 TRACE("iface %p, line %p.\n", iface, line);
2245 return ddraw7_GetScanLine(&ddraw->IDirectDraw7_iface, line);
2248 static HRESULT WINAPI ddraw1_GetScanLine(IDirectDraw *iface, DWORD *line)
2250 struct ddraw *ddraw = impl_from_IDirectDraw(iface);
2252 TRACE("iface %p, line %p.\n", iface, line);
2254 return ddraw7_GetScanLine(&ddraw->IDirectDraw7_iface, line);
2257 static HRESULT WINAPI ddraw7_TestCooperativeLevel(IDirectDraw7 *iface)
2259 struct ddraw *ddraw = impl_from_IDirectDraw7(iface);
2261 TRACE("iface %p.\n", iface);
2263 return ddraw->device_state == DDRAW_DEVICE_STATE_LOST ? DDERR_NOEXCLUSIVEMODE : DD_OK;
2266 static HRESULT WINAPI ddraw4_TestCooperativeLevel(IDirectDraw4 *iface)
2268 struct ddraw *ddraw = impl_from_IDirectDraw4(iface);
2270 TRACE("iface %p.\n", iface);
2272 return ddraw7_TestCooperativeLevel(&ddraw->IDirectDraw7_iface);
2275 /*****************************************************************************
2276 * IDirectDraw7::GetGDISurface
2278 * Returns the surface that GDI is treating as the primary surface.
2279 * For Wine this is the front buffer
2281 * Params:
2282 * GDISurface: Address to write the surface pointer to
2284 * Returns:
2285 * DD_OK if the surface was found
2286 * DDERR_NOTFOUND if the GDI surface wasn't found
2288 *****************************************************************************/
2289 static HRESULT WINAPI ddraw7_GetGDISurface(IDirectDraw7 *iface, IDirectDrawSurface7 **surface)
2291 struct ddraw *ddraw = impl_from_IDirectDraw7(iface);
2292 struct ddraw_surface *ddraw_surface;
2294 TRACE("iface %p, surface %p.\n", iface, surface);
2296 wined3d_mutex_lock();
2298 if (!ddraw->gdi_surface || !(ddraw_surface = wined3d_texture_get_sub_resource_parent(ddraw->gdi_surface, 0)))
2300 WARN("GDI surface not available.\n");
2301 *surface = NULL;
2302 wined3d_mutex_unlock();
2303 return DDERR_NOTFOUND;
2305 *surface = &ddraw_surface->IDirectDrawSurface7_iface;
2306 IDirectDrawSurface7_AddRef(*surface);
2308 wined3d_mutex_unlock();
2310 return DD_OK;
2313 static HRESULT WINAPI ddraw4_GetGDISurface(IDirectDraw4 *iface, IDirectDrawSurface4 **surface)
2315 struct ddraw *ddraw = impl_from_IDirectDraw4(iface);
2316 struct ddraw_surface *surface_impl;
2317 IDirectDrawSurface7 *surface7;
2318 HRESULT hr;
2320 TRACE("iface %p, surface %p.\n", iface, surface);
2322 hr = ddraw7_GetGDISurface(&ddraw->IDirectDraw7_iface, &surface7);
2323 if (FAILED(hr))
2325 *surface = NULL;
2326 return hr;
2328 surface_impl = impl_from_IDirectDrawSurface7(surface7);
2329 *surface = &surface_impl->IDirectDrawSurface4_iface;
2330 IDirectDrawSurface4_AddRef(*surface);
2331 IDirectDrawSurface7_Release(surface7);
2333 return hr;
2336 static HRESULT WINAPI ddraw2_GetGDISurface(IDirectDraw2 *iface, IDirectDrawSurface **surface)
2338 struct ddraw *ddraw = impl_from_IDirectDraw2(iface);
2339 struct ddraw_surface *surface_impl;
2340 IDirectDrawSurface7 *surface7;
2341 HRESULT hr;
2343 TRACE("iface %p, surface %p.\n", iface, surface);
2345 hr = ddraw7_GetGDISurface(&ddraw->IDirectDraw7_iface, &surface7);
2346 if (FAILED(hr))
2348 *surface = NULL;
2349 return hr;
2351 surface_impl = impl_from_IDirectDrawSurface7(surface7);
2352 *surface = &surface_impl->IDirectDrawSurface_iface;
2353 IDirectDrawSurface_AddRef(*surface);
2354 IDirectDrawSurface7_Release(surface7);
2356 return hr;
2359 static HRESULT WINAPI ddraw1_GetGDISurface(IDirectDraw *iface, IDirectDrawSurface **surface)
2361 struct ddraw *ddraw = impl_from_IDirectDraw(iface);
2362 struct ddraw_surface *surface_impl;
2363 IDirectDrawSurface7 *surface7;
2364 HRESULT hr;
2366 TRACE("iface %p, surface %p.\n", iface, surface);
2368 hr = ddraw7_GetGDISurface(&ddraw->IDirectDraw7_iface, &surface7);
2369 if (FAILED(hr))
2371 *surface = NULL;
2372 return hr;
2374 surface_impl = impl_from_IDirectDrawSurface7(surface7);
2375 *surface = &surface_impl->IDirectDrawSurface_iface;
2376 IDirectDrawSurface_AddRef(*surface);
2377 IDirectDrawSurface7_Release(surface7);
2379 return hr;
2382 struct displaymodescallback_context
2384 LPDDENUMMODESCALLBACK func;
2385 void *context;
2388 static HRESULT CALLBACK EnumDisplayModesCallbackThunk(DDSURFACEDESC2 *surface_desc, void *context)
2390 struct displaymodescallback_context *cbcontext = context;
2391 DDSURFACEDESC desc;
2393 DDSD2_to_DDSD(surface_desc, &desc);
2394 return cbcontext->func(&desc, cbcontext->context);
2397 /*****************************************************************************
2398 * IDirectDraw7::EnumDisplayModes
2400 * Enumerates the supported Display modes. The modes can be filtered with
2401 * the DDSD parameter.
2403 * Params:
2404 * Flags: can be DDEDM_REFRESHRATES and DDEDM_STANDARDVGAMODES. For old ddraw
2405 * versions (3 and older?) this is reserved and must be 0.
2406 * DDSD: Surface description to filter the modes
2407 * Context: Pointer passed back to the callback function
2408 * cb: Application-provided callback function
2410 * Returns:
2411 * DD_OK on success
2412 * DDERR_INVALIDPARAMS if the callback wasn't set
2414 *****************************************************************************/
2415 static HRESULT WINAPI ddraw7_EnumDisplayModes(IDirectDraw7 *iface, DWORD Flags,
2416 DDSURFACEDESC2 *DDSD, void *Context, LPDDENUMMODESCALLBACK2 cb)
2418 struct ddraw *ddraw = impl_from_IDirectDraw7(iface);
2419 struct wined3d_display_mode *enum_modes = NULL;
2420 struct wined3d_display_mode mode;
2421 unsigned int modenum, fmt;
2422 DDSURFACEDESC2 callback_sd;
2423 unsigned enum_mode_count = 0, enum_mode_array_size = 16;
2424 DDPIXELFORMAT pixelformat;
2426 static const enum wined3d_format_id checkFormatList[] =
2428 WINED3DFMT_B8G8R8X8_UNORM,
2429 WINED3DFMT_B5G6R5_UNORM,
2430 WINED3DFMT_P8_UINT,
2433 TRACE("iface %p, flags %#lx, surface_desc %p, context %p, callback %p.\n",
2434 iface, Flags, DDSD, Context, cb);
2436 if (!cb)
2437 return DDERR_INVALIDPARAMS;
2439 if (!(enum_modes = malloc(enum_mode_array_size * sizeof(*enum_modes))))
2440 return DDERR_OUTOFMEMORY;
2442 wined3d_mutex_lock();
2444 pixelformat.dwSize = sizeof(pixelformat);
2445 for(fmt = 0; fmt < ARRAY_SIZE(checkFormatList); fmt++)
2447 modenum = 0;
2448 while (wined3d_output_get_mode(ddraw->wined3d_output, checkFormatList[fmt],
2449 WINED3D_SCANLINE_ORDERING_UNKNOWN, modenum++, &mode, false) == WINED3D_OK)
2451 BOOL found = FALSE;
2452 unsigned i;
2454 ddrawformat_from_wined3dformat(&pixelformat, mode.format_id);
2455 if (DDSD)
2457 if (DDSD->dwFlags & DDSD_WIDTH && mode.width != DDSD->dwWidth)
2458 continue;
2459 if (DDSD->dwFlags & DDSD_HEIGHT && mode.height != DDSD->dwHeight)
2460 continue;
2461 if (DDSD->dwFlags & DDSD_REFRESHRATE && mode.refresh_rate != DDSD->dwRefreshRate)
2462 continue;
2463 if (DDSD->dwFlags & DDSD_PIXELFORMAT
2464 && pixelformat.dwRGBBitCount != DDSD->ddpfPixelFormat.dwRGBBitCount)
2465 continue;
2468 /* DX docs state EnumDisplayMode should return only unique modes */
2469 for (i = 0; i < enum_mode_count; i++)
2471 if (enum_modes[i].width == mode.width && enum_modes[i].height == mode.height
2472 && enum_modes[i].format_id == mode.format_id
2473 && (enum_modes[i].refresh_rate == mode.refresh_rate || !(Flags & DDEDM_REFRESHRATES)))
2475 found = TRUE;
2476 break;
2479 if(found) continue;
2481 memset(&callback_sd, 0, sizeof(callback_sd));
2482 callback_sd.dwSize = sizeof(callback_sd);
2483 callback_sd.ddpfPixelFormat.dwSize = sizeof(DDPIXELFORMAT);
2485 callback_sd.dwFlags = DDSD_HEIGHT|DDSD_WIDTH|DDSD_PIXELFORMAT|DDSD_PITCH|DDSD_REFRESHRATE;
2486 if (Flags & DDEDM_REFRESHRATES)
2487 callback_sd.dwRefreshRate = mode.refresh_rate;
2489 callback_sd.dwWidth = mode.width;
2490 callback_sd.dwHeight = mode.height;
2492 callback_sd.ddpfPixelFormat=pixelformat;
2494 /* Calc pitch and DWORD align like MSDN says */
2495 callback_sd.lPitch = (callback_sd.ddpfPixelFormat.dwRGBBitCount / 8) * mode.width;
2496 callback_sd.lPitch = (callback_sd.lPitch + 3) & ~3;
2498 TRACE("Enumerating %lux%lux%lu @%lu\n", callback_sd.dwWidth, callback_sd.dwHeight, callback_sd.ddpfPixelFormat.dwRGBBitCount,
2499 callback_sd.dwRefreshRate);
2501 if(cb(&callback_sd, Context) == DDENUMRET_CANCEL)
2503 TRACE("Application asked to terminate the enumeration\n");
2504 free(enum_modes);
2505 wined3d_mutex_unlock();
2506 return DD_OK;
2509 if (enum_mode_count == enum_mode_array_size)
2511 struct wined3d_display_mode *new_enum_modes;
2513 enum_mode_array_size *= 2;
2514 if (!(new_enum_modes = realloc(enum_modes, enum_mode_array_size * sizeof(*new_enum_modes))))
2516 free(enum_modes);
2517 wined3d_mutex_unlock();
2518 return DDERR_OUTOFMEMORY;
2521 enum_modes = new_enum_modes;
2523 enum_modes[enum_mode_count++] = mode;
2527 TRACE("End of enumeration\n");
2528 free(enum_modes);
2529 wined3d_mutex_unlock();
2531 return DD_OK;
2534 static HRESULT WINAPI ddraw4_EnumDisplayModes(IDirectDraw4 *iface, DWORD flags,
2535 DDSURFACEDESC2 *surface_desc, void *context, LPDDENUMMODESCALLBACK2 callback)
2537 struct ddraw *ddraw = impl_from_IDirectDraw4(iface);
2539 TRACE("iface %p, flags %#lx, surface_desc %p, context %p, callback %p.\n",
2540 iface, flags, surface_desc, context, callback);
2542 return ddraw7_EnumDisplayModes(&ddraw->IDirectDraw7_iface, flags, surface_desc, context, callback);
2545 static HRESULT WINAPI ddraw2_EnumDisplayModes(IDirectDraw2 *iface, DWORD flags,
2546 DDSURFACEDESC *surface_desc, void *context, LPDDENUMMODESCALLBACK callback)
2548 struct ddraw *ddraw = impl_from_IDirectDraw2(iface);
2549 struct displaymodescallback_context cbcontext;
2550 DDSURFACEDESC2 surface_desc2;
2552 TRACE("iface %p, flags %#lx, surface_desc %p, context %p, callback %p.\n",
2553 iface, flags, surface_desc, context, callback);
2555 cbcontext.func = callback;
2556 cbcontext.context = context;
2558 if (surface_desc) DDSD_to_DDSD2(surface_desc, &surface_desc2);
2559 return ddraw7_EnumDisplayModes(&ddraw->IDirectDraw7_iface, flags,
2560 surface_desc ? &surface_desc2 : NULL, &cbcontext, EnumDisplayModesCallbackThunk);
2563 static HRESULT WINAPI ddraw1_EnumDisplayModes(IDirectDraw *iface, DWORD flags,
2564 DDSURFACEDESC *surface_desc, void *context, LPDDENUMMODESCALLBACK callback)
2566 struct ddraw *ddraw = impl_from_IDirectDraw(iface);
2567 struct displaymodescallback_context cbcontext;
2568 DDSURFACEDESC2 surface_desc2;
2570 TRACE("iface %p, flags %#lx, surface_desc %p, context %p, callback %p.\n",
2571 iface, flags, surface_desc, context, callback);
2573 cbcontext.func = callback;
2574 cbcontext.context = context;
2576 if (surface_desc) DDSD_to_DDSD2(surface_desc, &surface_desc2);
2577 return ddraw7_EnumDisplayModes(&ddraw->IDirectDraw7_iface, flags,
2578 surface_desc ? &surface_desc2 : NULL, &cbcontext, EnumDisplayModesCallbackThunk);
2581 /*****************************************************************************
2582 * IDirectDraw7::EvaluateMode
2584 * Used with IDirectDraw7::StartModeTest to test video modes.
2585 * EvaluateMode is used to pass or fail a mode, and continue with the next
2586 * mode
2588 * Params:
2589 * Flags: DDEM_MODEPASSED or DDEM_MODEFAILED
2590 * Timeout: Returns the amount of seconds left before the mode would have
2591 * been failed automatically
2593 * Returns:
2594 * This implementation always DD_OK, because it's a stub
2596 *****************************************************************************/
2597 static HRESULT WINAPI ddraw7_EvaluateMode(IDirectDraw7 *iface, DWORD Flags, DWORD *Timeout)
2599 FIXME("iface %p, flags %#lx, timeout %p stub!\n", iface, Flags, Timeout);
2601 /* When implementing this, implement it in WineD3D */
2603 return DD_OK;
2606 /*****************************************************************************
2607 * IDirectDraw7::GetDeviceIdentifier
2609 * Returns the device identifier, which gives information about the driver
2610 * Our device identifier is defined at the beginning of this file.
2612 * Params:
2613 * DDDI: Address for the returned structure
2614 * Flags: Can be DDGDI_GETHOSTIDENTIFIER
2616 * Returns:
2617 * On success it returns DD_OK
2618 * DDERR_INVALIDPARAMS if DDDI is NULL
2620 *****************************************************************************/
2621 static HRESULT WINAPI ddraw7_GetDeviceIdentifier(IDirectDraw7 *iface,
2622 DDDEVICEIDENTIFIER2 *DDDI, DWORD Flags)
2624 struct ddraw *ddraw = impl_from_IDirectDraw7(iface);
2625 struct wined3d_adapter_identifier adapter_id;
2626 HRESULT hr = S_OK;
2628 TRACE("iface %p, device_identifier %p, flags %#lx.\n", iface, DDDI, Flags);
2630 if (!DDDI)
2631 return DDERR_INVALIDPARAMS;
2633 if (Flags & DDGDI_GETHOSTIDENTIFIER)
2635 /* The DDGDI_GETHOSTIDENTIFIER returns the information about the 2D
2636 * host adapter, if there's a secondary 3D adapter. This doesn't apply
2637 * to any modern hardware, nor is it interesting for Wine, so ignore it.
2638 * Size of DDDEVICEIDENTIFIER2 may be aligned to 8 bytes and thus 4
2639 * bytes too long. So only copy the relevant part of the structure
2642 memcpy(DDDI, &deviceidentifier, FIELD_OFFSET(DDDEVICEIDENTIFIER2, dwWHQLLevel) + sizeof(DWORD));
2643 return DD_OK;
2646 /* Drakan: Order of the Flame expects accurate D3D device information from ddraw */
2647 adapter_id.driver = DDDI->szDriver;
2648 adapter_id.driver_size = sizeof(DDDI->szDriver);
2649 adapter_id.description = DDDI->szDescription;
2650 adapter_id.description_size = sizeof(DDDI->szDescription);
2651 wined3d_mutex_lock();
2652 hr = wined3d_adapter_get_identifier(ddraw->wined3d_adapter, WINED3DENUM_WHQL_LEVEL, &adapter_id);
2653 wined3d_mutex_unlock();
2654 if (FAILED(hr)) return hr;
2656 DDDI->liDriverVersion = adapter_id.driver_version;
2657 DDDI->dwVendorId = adapter_id.vendor_id;
2658 DDDI->dwDeviceId = adapter_id.device_id;
2659 DDDI->dwSubSysId = adapter_id.subsystem_id;
2660 DDDI->dwRevision = adapter_id.revision;
2661 DDDI->guidDeviceIdentifier = adapter_id.device_identifier;
2662 DDDI->dwWHQLLevel = adapter_id.whql_level;
2663 return DD_OK;
2666 static HRESULT WINAPI ddraw4_GetDeviceIdentifier(IDirectDraw4 *iface,
2667 DDDEVICEIDENTIFIER *identifier, DWORD flags)
2669 struct ddraw *ddraw = impl_from_IDirectDraw4(iface);
2670 DDDEVICEIDENTIFIER2 identifier2;
2671 HRESULT hr;
2673 TRACE("iface %p, identifier %p, flags %#lx.\n", iface, identifier, flags);
2675 hr = ddraw7_GetDeviceIdentifier(&ddraw->IDirectDraw7_iface, &identifier2, flags);
2676 DDRAW_Convert_DDDEVICEIDENTIFIER_2_To_1(&identifier2, identifier);
2678 return hr;
2681 /*****************************************************************************
2682 * IDirectDraw7::GetSurfaceFromDC
2684 * Returns the Surface for a GDI device context handle.
2685 * Is this related to IDirectDrawSurface::GetDC ???
2687 * Params:
2688 * hdc: hdc to return the surface for
2689 * Surface: Address to write the surface pointer to
2691 * Returns:
2692 * Always returns DD_OK because it's a stub
2694 *****************************************************************************/
2695 static HRESULT WINAPI ddraw7_GetSurfaceFromDC(IDirectDraw7 *iface,
2696 HDC dc, IDirectDrawSurface7 **surface)
2698 struct ddraw *ddraw = impl_from_IDirectDraw7(iface);
2699 struct ddraw_surface *surface_impl;
2701 TRACE("iface %p, dc %p, surface %p.\n", iface, dc, surface);
2703 if (!surface)
2704 return E_INVALIDARG;
2706 if (!dc)
2707 goto done;
2709 wined3d_mutex_lock();
2710 LIST_FOR_EACH_ENTRY(surface_impl, &ddraw->surface_list, struct ddraw_surface, surface_list_entry)
2712 if (surface_impl->dc != dc)
2713 continue;
2715 TRACE("Found surface %p for dc %p.\n", surface_impl, dc);
2716 *surface = &surface_impl->IDirectDrawSurface7_iface;
2717 IDirectDrawSurface7_AddRef(*surface);
2718 wined3d_mutex_unlock();
2719 return DD_OK;
2721 wined3d_mutex_unlock();
2723 done:
2724 TRACE("No surface found for dc %p.\n", dc);
2725 *surface = NULL;
2726 return DDERR_NOTFOUND;
2729 static HRESULT WINAPI ddraw4_GetSurfaceFromDC(IDirectDraw4 *iface, HDC dc,
2730 IDirectDrawSurface4 **surface)
2732 struct ddraw *ddraw = impl_from_IDirectDraw4(iface);
2733 struct ddraw_surface *surface_impl;
2734 IDirectDrawSurface7 *surface7;
2735 HRESULT hr;
2737 TRACE("iface %p, dc %p, surface %p.\n", iface, dc, surface);
2739 if (!surface) return E_INVALIDARG;
2741 hr = ddraw7_GetSurfaceFromDC(&ddraw->IDirectDraw7_iface, dc, &surface7);
2742 if (FAILED(hr))
2744 *surface = NULL;
2745 return hr;
2747 surface_impl = impl_from_IDirectDrawSurface7(surface7);
2748 /* Tests say this is true */
2749 *surface = (IDirectDrawSurface4 *)&surface_impl->IDirectDrawSurface_iface;
2750 IDirectDrawSurface_AddRef(&surface_impl->IDirectDrawSurface_iface);
2751 IDirectDrawSurface7_Release(surface7);
2753 return hr;
2756 static HRESULT CALLBACK restore_callback(IDirectDrawSurface7 *surface, DDSURFACEDESC2 *desc, void *context)
2758 IDirectDrawSurface_Restore(surface);
2759 IDirectDrawSurface_Release(surface);
2761 return DDENUMRET_OK;
2764 static HRESULT WINAPI ddraw7_RestoreAllSurfaces(IDirectDraw7 *iface)
2766 TRACE("iface %p.\n", iface);
2768 return IDirectDraw7_EnumSurfaces(iface, DDENUMSURFACES_ALL | DDENUMSURFACES_DOESEXIST,
2769 NULL, NULL, restore_callback);
2772 static HRESULT WINAPI ddraw4_RestoreAllSurfaces(IDirectDraw4 *iface)
2774 struct ddraw *ddraw = impl_from_IDirectDraw4(iface);
2776 TRACE("iface %p.\n", iface);
2778 return ddraw7_RestoreAllSurfaces(&ddraw->IDirectDraw7_iface);
2781 /*****************************************************************************
2782 * IDirectDraw7::StartModeTest
2784 * Tests the specified video modes to update the system registry with
2785 * refresh rate information. StartModeTest starts the mode test,
2786 * EvaluateMode is used to fail or pass a mode. If EvaluateMode
2787 * isn't called within 15 seconds, the mode is failed automatically
2789 * As refresh rates are handled by the X server, I don't think this
2790 * Method is important
2792 * Params:
2793 * Modes: An array of mode specifications
2794 * NumModes: The number of modes in Modes
2795 * Flags: Some flags...
2797 * Returns:
2798 * Returns DDERR_TESTFINISHED if flags contains DDSMT_ISTESTREQUIRED,
2799 * if no modes are passed, DDERR_INVALIDPARAMS is returned,
2800 * otherwise DD_OK
2802 *****************************************************************************/
2803 static HRESULT WINAPI ddraw7_StartModeTest(IDirectDraw7 *iface, SIZE *Modes, DWORD NumModes, DWORD Flags)
2805 FIXME("iface %p, modes %p, mode_count %lu, flags %#lx partial stub!\n",
2806 iface, Modes, NumModes, Flags);
2808 /* This looks sane */
2809 if( (!Modes) || (NumModes == 0) ) return DDERR_INVALIDPARAMS;
2811 /* DDSMT_ISTESTREQUIRED asks if a mode test is necessary.
2812 * As it is not, DDERR_TESTFINISHED is returned
2813 * (hopefully that's correct
2815 if(Flags & DDSMT_ISTESTREQUIRED) return DDERR_TESTFINISHED;
2816 * well, that value doesn't (yet) exist in the wine headers, so ignore it
2819 return DD_OK;
2822 static HRESULT WINAPI ddraw7_CreateSurface(IDirectDraw7 *iface, DDSURFACEDESC2 *surface_desc,
2823 IDirectDrawSurface7 **surface, IUnknown *outer_unknown)
2825 struct ddraw *ddraw = impl_from_IDirectDraw7(iface);
2826 struct ddraw_surface *impl;
2827 HRESULT hr;
2829 TRACE("iface %p, surface_desc %p, surface %p, outer_unknown %p.\n",
2830 iface, surface_desc, surface, outer_unknown);
2832 wined3d_mutex_lock();
2834 if (!(ddraw->cooperative_level & (DDSCL_NORMAL | DDSCL_EXCLUSIVE)))
2836 WARN("Cooperative level not set.\n");
2837 wined3d_mutex_unlock();
2838 return DDERR_NOCOOPERATIVELEVELSET;
2841 if(surface_desc == NULL || surface_desc->dwSize != sizeof(DDSURFACEDESC2))
2843 WARN("Application supplied invalid surface descriptor\n");
2844 wined3d_mutex_unlock();
2845 return DDERR_INVALIDPARAMS;
2848 __TRY
2850 *surface = NULL;
2852 __EXCEPT_PAGE_FAULT
2854 WARN("Surface pointer %p is invalid.\n", surface);
2855 wined3d_mutex_unlock();
2856 return DDERR_INVALIDPARAMS;
2858 __ENDTRY;
2860 if(surface_desc->ddsCaps.dwCaps & (DDSCAPS_FRONTBUFFER | DDSCAPS_BACKBUFFER))
2862 if (TRACE_ON(ddraw))
2864 TRACE(" (%p) Requesting surface desc :\n", iface);
2865 DDRAW_dump_surface_desc(surface_desc);
2868 WARN("Application tried to create an explicit front or back buffer\n");
2869 wined3d_mutex_unlock();
2870 return DDERR_INVALIDCAPS;
2873 hr = ddraw_surface_create(ddraw, surface_desc, &impl, outer_unknown, 7);
2874 wined3d_mutex_unlock();
2875 if (FAILED(hr))
2876 return hr;
2878 *surface = &impl->IDirectDrawSurface7_iface;
2879 IDirectDraw7_AddRef(iface);
2880 impl->ifaceToRelease = (IUnknown *)iface;
2882 return hr;
2885 static HRESULT WINAPI ddraw4_CreateSurface(IDirectDraw4 *iface,
2886 DDSURFACEDESC2 *surface_desc, IDirectDrawSurface4 **surface, IUnknown *outer_unknown)
2888 struct ddraw *ddraw = impl_from_IDirectDraw4(iface);
2889 struct ddraw_surface *impl;
2890 HRESULT hr;
2892 TRACE("iface %p, surface_desc %p, surface %p, outer_unknown %p.\n",
2893 iface, surface_desc, surface, outer_unknown);
2895 wined3d_mutex_lock();
2897 if (!(ddraw->cooperative_level & (DDSCL_NORMAL | DDSCL_EXCLUSIVE)))
2899 WARN("Cooperative level not set.\n");
2900 wined3d_mutex_unlock();
2901 return DDERR_NOCOOPERATIVELEVELSET;
2904 if(surface_desc == NULL || surface_desc->dwSize != sizeof(DDSURFACEDESC2))
2906 WARN("Application supplied invalid surface descriptor\n");
2907 wined3d_mutex_unlock();
2908 return DDERR_INVALIDPARAMS;
2911 __TRY
2913 *surface = NULL;
2915 __EXCEPT_PAGE_FAULT
2917 WARN("Surface pointer %p is invalid.\n", surface);
2918 wined3d_mutex_unlock();
2919 return DDERR_INVALIDPARAMS;
2921 __ENDTRY;
2923 if(surface_desc->ddsCaps.dwCaps & (DDSCAPS_FRONTBUFFER | DDSCAPS_BACKBUFFER))
2925 if (TRACE_ON(ddraw))
2927 TRACE(" (%p) Requesting surface desc :\n", iface);
2928 DDRAW_dump_surface_desc(surface_desc);
2931 WARN("Application tried to create an explicit front or back buffer\n");
2932 wined3d_mutex_unlock();
2933 return DDERR_INVALIDCAPS;
2936 hr = ddraw_surface_create(ddraw, surface_desc, &impl, outer_unknown, 4);
2937 wined3d_mutex_unlock();
2938 if (FAILED(hr))
2939 return hr;
2941 *surface = &impl->IDirectDrawSurface4_iface;
2942 IDirectDraw4_AddRef(iface);
2943 impl->ifaceToRelease = (IUnknown *)iface;
2945 return hr;
2948 static HRESULT WINAPI ddraw2_CreateSurface(IDirectDraw2 *iface,
2949 DDSURFACEDESC *surface_desc, IDirectDrawSurface **surface, IUnknown *outer_unknown)
2951 struct ddraw *ddraw = impl_from_IDirectDraw2(iface);
2952 struct ddraw_surface *impl;
2953 HRESULT hr;
2954 DDSURFACEDESC2 surface_desc2;
2956 TRACE("iface %p, surface_desc %p, surface %p, outer_unknown %p.\n",
2957 iface, surface_desc, surface, outer_unknown);
2959 wined3d_mutex_lock();
2961 if (!(ddraw->cooperative_level & (DDSCL_NORMAL | DDSCL_EXCLUSIVE)))
2963 WARN("Cooperative level not set.\n");
2964 wined3d_mutex_unlock();
2965 return DDERR_NOCOOPERATIVELEVELSET;
2968 if(surface_desc == NULL || surface_desc->dwSize != sizeof(DDSURFACEDESC))
2970 WARN("Application supplied invalid surface descriptor\n");
2971 wined3d_mutex_unlock();
2972 return DDERR_INVALIDPARAMS;
2975 __TRY
2977 *surface = NULL;
2979 __EXCEPT_PAGE_FAULT
2981 WARN("Surface pointer %p is invalid.\n", surface);
2982 wined3d_mutex_unlock();
2983 return DDERR_INVALIDPARAMS;
2985 __ENDTRY;
2987 DDSD_to_DDSD2(surface_desc, &surface_desc2);
2988 if(surface_desc->ddsCaps.dwCaps & (DDSCAPS_FRONTBUFFER | DDSCAPS_BACKBUFFER))
2990 if (TRACE_ON(ddraw))
2992 TRACE(" (%p) Requesting surface desc :\n", iface);
2993 DDRAW_dump_surface_desc((DDSURFACEDESC2 *)surface_desc);
2996 WARN("Application tried to create an explicit front or back buffer\n");
2997 wined3d_mutex_unlock();
2998 return DDERR_INVALIDCAPS;
3001 hr = ddraw_surface_create(ddraw, &surface_desc2, &impl, outer_unknown, 2);
3002 wined3d_mutex_unlock();
3003 if (FAILED(hr))
3004 return hr;
3006 *surface = &impl->IDirectDrawSurface_iface;
3007 impl->ifaceToRelease = NULL;
3009 return hr;
3012 static HRESULT WINAPI ddraw1_CreateSurface(IDirectDraw *iface,
3013 DDSURFACEDESC *surface_desc, IDirectDrawSurface **surface, IUnknown *outer_unknown)
3015 struct ddraw *ddraw = impl_from_IDirectDraw(iface);
3016 struct ddraw_surface *impl;
3017 HRESULT hr;
3018 DDSURFACEDESC2 surface_desc2;
3020 TRACE("iface %p, surface_desc %p, surface %p, outer_unknown %p.\n",
3021 iface, surface_desc, surface, outer_unknown);
3023 wined3d_mutex_lock();
3025 if (!(ddraw->cooperative_level & (DDSCL_NORMAL | DDSCL_EXCLUSIVE)))
3027 WARN("Cooperative level not set.\n");
3028 wined3d_mutex_unlock();
3029 return DDERR_NOCOOPERATIVELEVELSET;
3032 if(surface_desc == NULL || surface_desc->dwSize != sizeof(DDSURFACEDESC))
3034 WARN("Application supplied invalid surface descriptor\n");
3035 wined3d_mutex_unlock();
3036 return DDERR_INVALIDPARAMS;
3039 __TRY
3041 *surface = NULL;
3043 __EXCEPT_PAGE_FAULT
3045 WARN("Surface pointer %p is invalid.\n", surface);
3046 wined3d_mutex_unlock();
3047 return DDERR_INVALIDPARAMS;
3049 __ENDTRY;
3051 if ((surface_desc->ddsCaps.dwCaps & (DDSCAPS_PRIMARYSURFACE | DDSCAPS_BACKBUFFER))
3052 == (DDSCAPS_PRIMARYSURFACE | DDSCAPS_BACKBUFFER)
3053 || (surface_desc->ddsCaps.dwCaps & (DDSCAPS_FLIP | DDSCAPS_FRONTBUFFER))
3054 == ((DDSCAPS_FLIP | DDSCAPS_FRONTBUFFER)))
3056 WARN("Application tried to create an explicit front or back buffer.\n");
3057 wined3d_mutex_unlock();
3058 return DDERR_INVALIDCAPS;
3061 DDSD_to_DDSD2(surface_desc, &surface_desc2);
3062 hr = ddraw_surface_create(ddraw, &surface_desc2, &impl, outer_unknown, 1);
3063 wined3d_mutex_unlock();
3064 if (FAILED(hr))
3065 return hr;
3067 *surface = &impl->IDirectDrawSurface_iface;
3068 impl->ifaceToRelease = NULL;
3070 return hr;
3073 static BOOL
3074 Main_DirectDraw_DDPIXELFORMAT_Match(const DDPIXELFORMAT *requested,
3075 const DDPIXELFORMAT *provided)
3077 /* Some flags must be present in both or neither for a match. */
3078 static const DWORD must_match = DDPF_PALETTEINDEXED1 | DDPF_PALETTEINDEXED2
3079 | DDPF_PALETTEINDEXED4 | DDPF_PALETTEINDEXED8 | DDPF_FOURCC
3080 | DDPF_ZBUFFER | DDPF_STENCILBUFFER;
3082 if ((requested->dwFlags & provided->dwFlags) != requested->dwFlags)
3083 return FALSE;
3085 if ((requested->dwFlags & must_match) != (provided->dwFlags & must_match))
3086 return FALSE;
3088 if (requested->dwFlags & DDPF_FOURCC)
3089 if (requested->dwFourCC != provided->dwFourCC)
3090 return FALSE;
3092 if (requested->dwFlags & (DDPF_RGB|DDPF_YUV|DDPF_ZBUFFER|DDPF_ALPHA
3093 |DDPF_LUMINANCE|DDPF_BUMPDUDV))
3094 if (requested->dwRGBBitCount != provided->dwRGBBitCount)
3095 return FALSE;
3097 if (requested->dwFlags & (DDPF_RGB|DDPF_YUV|DDPF_STENCILBUFFER
3098 |DDPF_LUMINANCE|DDPF_BUMPDUDV))
3099 if (requested->dwRBitMask != provided->dwRBitMask)
3100 return FALSE;
3102 if (requested->dwFlags & (DDPF_RGB|DDPF_YUV|DDPF_ZBUFFER|DDPF_BUMPDUDV))
3103 if (requested->dwGBitMask != provided->dwGBitMask)
3104 return FALSE;
3106 /* I could be wrong about the bumpmapping. MSDN docs are vague. */
3107 if (requested->dwFlags & (DDPF_RGB|DDPF_YUV|DDPF_STENCILBUFFER
3108 |DDPF_BUMPDUDV))
3109 if (requested->dwBBitMask != provided->dwBBitMask)
3110 return FALSE;
3112 if (requested->dwFlags & (DDPF_ALPHAPIXELS|DDPF_ZPIXELS))
3113 if (requested->dwRGBAlphaBitMask != provided->dwRGBAlphaBitMask)
3114 return FALSE;
3116 return TRUE;
3119 static BOOL ddraw_match_surface_desc(const DDSURFACEDESC2 *requested, const DDSURFACEDESC2 *provided)
3121 struct compare_info
3123 DWORD flag;
3124 ptrdiff_t offset;
3125 size_t size;
3128 #define CMP(FLAG, FIELD) \
3129 { DDSD_##FLAG, offsetof(DDSURFACEDESC2, FIELD), \
3130 sizeof(((DDSURFACEDESC2 *)(NULL))->FIELD) }
3132 static const struct compare_info compare[] =
3134 CMP(ALPHABITDEPTH, dwAlphaBitDepth),
3135 CMP(BACKBUFFERCOUNT, dwBackBufferCount),
3136 CMP(CAPS, ddsCaps),
3137 CMP(CKDESTBLT, ddckCKDestBlt),
3138 CMP(CKDESTOVERLAY, ddckCKDestOverlay),
3139 CMP(CKSRCBLT, ddckCKSrcBlt),
3140 CMP(CKSRCOVERLAY, ddckCKSrcOverlay),
3141 CMP(HEIGHT, dwHeight),
3142 CMP(LINEARSIZE, dwLinearSize),
3143 CMP(LPSURFACE, lpSurface),
3144 CMP(MIPMAPCOUNT, dwMipMapCount),
3145 CMP(PITCH, lPitch),
3146 /* PIXELFORMAT: manual */
3147 CMP(REFRESHRATE, dwRefreshRate),
3148 CMP(TEXTURESTAGE, dwTextureStage),
3149 CMP(WIDTH, dwWidth),
3150 /* ZBUFFERBITDEPTH: "obsolete" */
3153 #undef CMP
3155 unsigned int i;
3157 if ((requested->dwFlags & provided->dwFlags) != requested->dwFlags)
3158 return FALSE;
3160 for (i=0; i < ARRAY_SIZE(compare); i++)
3162 if (requested->dwFlags & compare[i].flag
3163 && memcmp((const char *)provided + compare[i].offset,
3164 (const char *)requested + compare[i].offset,
3165 compare[i].size) != 0)
3166 return FALSE;
3169 if (requested->dwFlags & DDSD_PIXELFORMAT)
3171 if (!Main_DirectDraw_DDPIXELFORMAT_Match(&requested->ddpfPixelFormat,
3172 &provided->ddpfPixelFormat))
3173 return FALSE;
3176 return TRUE;
3179 struct surfacescallback2_context
3181 LPDDENUMSURFACESCALLBACK2 func;
3182 void *context;
3185 struct surfacescallback_context
3187 LPDDENUMSURFACESCALLBACK func;
3188 void *context;
3191 static HRESULT CALLBACK EnumSurfacesCallback2Thunk(IDirectDrawSurface7 *surface,
3192 DDSURFACEDESC2 *surface_desc, void *context)
3194 struct ddraw_surface *surface_impl = impl_from_IDirectDrawSurface7(surface);
3195 struct surfacescallback2_context *cbcontext = context;
3197 if (!surface)
3198 return cbcontext->func(NULL, surface_desc, cbcontext->context);
3200 IDirectDrawSurface4_AddRef(&surface_impl->IDirectDrawSurface4_iface);
3201 IDirectDrawSurface7_Release(surface);
3203 return cbcontext->func(&surface_impl->IDirectDrawSurface4_iface,
3204 surface_desc, cbcontext->context);
3207 static HRESULT CALLBACK EnumSurfacesCallbackThunk(IDirectDrawSurface7 *surface,
3208 DDSURFACEDESC2 *surface_desc, void *context)
3210 struct ddraw_surface *surface_impl = impl_from_IDirectDrawSurface7(surface);
3211 struct surfacescallback_context *cbcontext = context;
3213 if (!surface)
3214 return cbcontext->func(NULL, (DDSURFACEDESC *)surface_desc, cbcontext->context);
3216 IDirectDrawSurface_AddRef(&surface_impl->IDirectDrawSurface_iface);
3217 IDirectDrawSurface7_Release(surface);
3219 return cbcontext->func(&surface_impl->IDirectDrawSurface_iface,
3220 (DDSURFACEDESC *)surface_desc, cbcontext->context);
3223 struct enum_surface_mode_params
3225 IDirectDraw7 *ddraw;
3226 const DDSURFACEDESC2 *desc;
3227 LPDDENUMSURFACESCALLBACK7 callback;
3228 void *context;
3231 static HRESULT CALLBACK enum_surface_mode_callback(DDSURFACEDESC2 *surface_desc, void *context)
3233 const struct enum_surface_mode_params *params = context;
3234 DDSURFACEDESC2 desc = *params->desc;
3235 IDirectDrawSurface7 *surface;
3237 desc.dwFlags |= DDSD_WIDTH | DDSD_HEIGHT | DDSD_PITCH | DDSD_PIXELFORMAT;
3238 desc.dwWidth = surface_desc->dwWidth;
3239 desc.dwHeight = surface_desc->dwHeight;
3240 desc.lPitch = surface_desc->lPitch;
3241 desc.ddpfPixelFormat = surface_desc->ddpfPixelFormat;
3243 if (SUCCEEDED(ddraw7_CreateSurface(params->ddraw, &desc, &surface, NULL)))
3245 IDirectDrawSurface7_Release(surface);
3246 return params->callback(NULL, &desc, params->context);
3248 return DDENUMRET_OK;
3251 /*****************************************************************************
3252 * IDirectDraw7::EnumSurfaces
3254 * Loops through all surfaces attached to this device and calls the
3255 * application callback. This can't be relayed to WineD3DDevice,
3256 * because some WineD3DSurfaces' parents are IParent objects
3258 * Params:
3259 * Flags: Some filtering flags. See IDirectDrawImpl_EnumSurfacesCallback
3260 * DDSD: Description to filter for
3261 * Context: Application-provided pointer, it's passed unmodified to the
3262 * Callback function
3263 * Callback: Address to call for each surface
3265 * Returns:
3266 * DDERR_INVALIDPARAMS if the callback is NULL
3267 * DD_OK on success
3269 *****************************************************************************/
3270 static HRESULT WINAPI ddraw7_EnumSurfaces(IDirectDraw7 *iface, DWORD flags,
3271 DDSURFACEDESC2 *surface_desc, void *context, LPDDENUMSURFACESCALLBACK7 callback)
3273 struct ddraw *ddraw = impl_from_IDirectDraw7(iface);
3274 HRESULT hr = DD_OK;
3276 TRACE("iface %p, flags %#lx, surface_desc %p, context %p, callback %p.\n",
3277 iface, flags, surface_desc, context, callback);
3279 if (!callback)
3280 return DDERR_INVALIDPARAMS;
3282 if (flags & DDENUMSURFACES_CANBECREATED)
3284 IDirectDrawSurface7 *surface;
3286 if ((flags & (DDENUMSURFACES_ALL | DDENUMSURFACES_MATCH | DDENUMSURFACES_NOMATCH)) != DDENUMSURFACES_MATCH)
3287 return DDERR_INVALIDPARAMS;
3289 wined3d_mutex_lock();
3291 if (surface_desc->dwFlags & (DDSD_WIDTH | DDSD_HEIGHT))
3293 if (SUCCEEDED(ddraw7_CreateSurface(iface, surface_desc, &surface, NULL)))
3295 struct ddraw_surface *surface_impl = impl_from_IDirectDrawSurface7(surface);
3296 callback(NULL, &surface_impl->surface_desc, context);
3297 IDirectDrawSurface7_Release(surface);
3300 else
3302 DDSURFACEDESC2 desc =
3304 .dwSize = sizeof(desc),
3305 .dwFlags = DDSD_PIXELFORMAT,
3306 .ddpfPixelFormat.dwSize = sizeof(DDPIXELFORMAT),
3308 struct enum_surface_mode_params params =
3310 .ddraw = iface,
3311 .desc = surface_desc,
3312 .callback = callback,
3313 .context = context,
3315 struct wined3d_display_mode mode;
3317 if (FAILED(hr = wined3d_output_get_display_mode(ddraw->wined3d_output, &mode, NULL)))
3319 ERR("Failed to get display mode, hr %#lx.\n", hr);
3320 wined3d_mutex_unlock();
3321 return hr_ddraw_from_wined3d(hr);
3324 ddrawformat_from_wined3dformat(&desc.ddpfPixelFormat, mode.format_id);
3325 hr = ddraw7_EnumDisplayModes(iface, 0, &desc, &params, enum_surface_mode_callback);
3328 wined3d_mutex_unlock();
3330 else if (flags & DDENUMSURFACES_DOESEXIST)
3332 struct ddraw_surface *surface, *cursor;
3333 BOOL nomatch = !!(flags & DDENUMSURFACES_NOMATCH);
3335 wined3d_mutex_lock();
3337 /* Use the safe enumeration, as the callback may destroy surfaces. */
3338 LIST_FOR_EACH_ENTRY_SAFE(surface, cursor, &ddraw->surface_list, struct ddraw_surface, surface_list_entry)
3340 if (!surface->iface_count)
3342 WARN("Not enumerating surface %p because it doesn't have any references.\n", surface);
3343 continue;
3346 if ((flags & DDENUMSURFACES_ALL)
3347 || nomatch != ddraw_match_surface_desc(surface_desc, &surface->surface_desc))
3349 DDSURFACEDESC2 desc = surface->surface_desc;
3351 TRACE("Enumerating surface %p.\n", surface);
3352 IDirectDrawSurface7_AddRef(&surface->IDirectDrawSurface7_iface);
3353 if (callback(&surface->IDirectDrawSurface7_iface, &desc, context) != DDENUMRET_OK)
3354 break;
3358 wined3d_mutex_unlock();
3360 else
3362 return DDERR_INVALIDPARAMS;
3365 return hr;
3368 static HRESULT WINAPI ddraw4_EnumSurfaces(IDirectDraw4 *iface, DWORD flags,
3369 DDSURFACEDESC2 *surface_desc, void *context, LPDDENUMSURFACESCALLBACK2 callback)
3371 struct ddraw *ddraw = impl_from_IDirectDraw4(iface);
3372 struct surfacescallback2_context cbcontext;
3374 TRACE("iface %p, flags %#lx, surface_desc %p, context %p, callback %p.\n",
3375 iface, flags, surface_desc, context, callback);
3377 cbcontext.func = callback;
3378 cbcontext.context = context;
3380 return ddraw7_EnumSurfaces(&ddraw->IDirectDraw7_iface, flags, surface_desc,
3381 &cbcontext, EnumSurfacesCallback2Thunk);
3384 static HRESULT WINAPI ddraw2_EnumSurfaces(IDirectDraw2 *iface, DWORD flags,
3385 DDSURFACEDESC *surface_desc, void *context, LPDDENUMSURFACESCALLBACK callback)
3387 struct ddraw *ddraw = impl_from_IDirectDraw2(iface);
3388 struct surfacescallback_context cbcontext;
3389 DDSURFACEDESC2 surface_desc2;
3391 TRACE("iface %p, flags %#lx, surface_desc %p, context %p, callback %p.\n",
3392 iface, flags, surface_desc, context, callback);
3394 cbcontext.func = callback;
3395 cbcontext.context = context;
3397 if (surface_desc) DDSD_to_DDSD2(surface_desc, &surface_desc2);
3398 return ddraw7_EnumSurfaces(&ddraw->IDirectDraw7_iface, flags,
3399 surface_desc ? &surface_desc2 : NULL, &cbcontext, EnumSurfacesCallbackThunk);
3402 static HRESULT WINAPI ddraw1_EnumSurfaces(IDirectDraw *iface, DWORD flags,
3403 DDSURFACEDESC *surface_desc, void *context, LPDDENUMSURFACESCALLBACK callback)
3405 struct ddraw *ddraw = impl_from_IDirectDraw(iface);
3406 struct surfacescallback_context cbcontext;
3407 DDSURFACEDESC2 surface_desc2;
3409 TRACE("iface %p, flags %#lx, surface_desc %p, context %p, callback %p.\n",
3410 iface, flags, surface_desc, context, callback);
3412 cbcontext.func = callback;
3413 cbcontext.context = context;
3415 if (surface_desc) DDSD_to_DDSD2(surface_desc, &surface_desc2);
3416 return ddraw7_EnumSurfaces(&ddraw->IDirectDraw7_iface, flags,
3417 surface_desc ? &surface_desc2 : NULL, &cbcontext, EnumSurfacesCallbackThunk);
3420 /*****************************************************************************
3421 * DirectDrawCreateClipper (DDRAW.@)
3423 * Creates a new IDirectDrawClipper object.
3425 * Params:
3426 * Clipper: Address to write the interface pointer to
3427 * UnkOuter: For aggregation support, which ddraw doesn't have. Has to be
3428 * NULL
3430 * Returns:
3431 * CLASS_E_NOAGGREGATION if UnkOuter != NULL
3432 * E_OUTOFMEMORY if allocating the object failed
3434 *****************************************************************************/
3435 HRESULT WINAPI DirectDrawCreateClipper(DWORD flags, IDirectDrawClipper **clipper, IUnknown *outer_unknown)
3437 struct ddraw_clipper *object;
3438 HRESULT hr;
3440 TRACE("flags %#lx, clipper %p, outer_unknown %p.\n",
3441 flags, clipper, outer_unknown);
3443 if (outer_unknown)
3444 return CLASS_E_NOAGGREGATION;
3446 wined3d_mutex_lock();
3448 if (!(object = calloc(1, sizeof(*object))))
3450 wined3d_mutex_unlock();
3451 return E_OUTOFMEMORY;
3454 hr = ddraw_clipper_init(object);
3455 if (FAILED(hr))
3457 WARN("Failed to initialize clipper, hr %#lx.\n", hr);
3458 free(object);
3459 wined3d_mutex_unlock();
3460 return hr;
3463 TRACE("Created clipper %p.\n", object);
3464 *clipper = &object->IDirectDrawClipper_iface;
3465 wined3d_mutex_unlock();
3467 return DD_OK;
3470 /*****************************************************************************
3471 * IDirectDraw7::CreateClipper
3473 * Creates a DDraw clipper. See DirectDrawCreateClipper for details
3475 *****************************************************************************/
3476 static HRESULT WINAPI ddraw7_CreateClipper(IDirectDraw7 *iface, DWORD Flags,
3477 IDirectDrawClipper **Clipper, IUnknown *UnkOuter)
3479 TRACE("iface %p, flags %#lx, clipper %p, outer_unknown %p.\n",
3480 iface, Flags, Clipper, UnkOuter);
3482 return DirectDrawCreateClipper(Flags, Clipper, UnkOuter);
3485 static HRESULT WINAPI ddraw4_CreateClipper(IDirectDraw4 *iface, DWORD flags,
3486 IDirectDrawClipper **clipper, IUnknown *outer_unknown)
3488 struct ddraw *ddraw = impl_from_IDirectDraw4(iface);
3490 TRACE("iface %p, flags %#lx, clipper %p, outer_unknown %p.\n",
3491 iface, flags, clipper, outer_unknown);
3493 return ddraw7_CreateClipper(&ddraw->IDirectDraw7_iface, flags, clipper, outer_unknown);
3496 static HRESULT WINAPI ddraw2_CreateClipper(IDirectDraw2 *iface,
3497 DWORD flags, IDirectDrawClipper **clipper, IUnknown *outer_unknown)
3499 struct ddraw *ddraw = impl_from_IDirectDraw2(iface);
3501 TRACE("iface %p, flags %#lx, clipper %p, outer_unknown %p.\n",
3502 iface, flags, clipper, outer_unknown);
3504 return ddraw7_CreateClipper(&ddraw->IDirectDraw7_iface, flags, clipper, outer_unknown);
3507 static HRESULT WINAPI ddraw1_CreateClipper(IDirectDraw *iface,
3508 DWORD flags, IDirectDrawClipper **clipper, IUnknown *outer_unknown)
3510 struct ddraw *ddraw = impl_from_IDirectDraw(iface);
3512 TRACE("iface %p, flags %#lx, clipper %p, outer_unknown %p.\n",
3513 iface, flags, clipper, outer_unknown);
3515 return ddraw7_CreateClipper(&ddraw->IDirectDraw7_iface, flags, clipper, outer_unknown);
3518 /*****************************************************************************
3519 * IDirectDraw7::CreatePalette
3521 * Creates a new IDirectDrawPalette object
3523 * Params:
3524 * Flags: The flags for the new clipper
3525 * ColorTable: Color table to assign to the new clipper
3526 * Palette: Address to write the interface pointer to
3527 * UnkOuter: For aggregation support, which ddraw doesn't have. Has to be
3528 * NULL
3530 * Returns:
3531 * CLASS_E_NOAGGREGATION if UnkOuter != NULL
3532 * E_OUTOFMEMORY if allocating the object failed
3534 *****************************************************************************/
3535 static HRESULT WINAPI ddraw7_CreatePalette(IDirectDraw7 *iface, DWORD Flags,
3536 PALETTEENTRY *ColorTable, IDirectDrawPalette **Palette, IUnknown *pUnkOuter)
3538 struct ddraw *ddraw = impl_from_IDirectDraw7(iface);
3539 struct ddraw_palette *object;
3540 HRESULT hr;
3542 TRACE("iface %p, flags %#lx, color_table %p, palette %p, outer_unknown %p.\n",
3543 iface, Flags, ColorTable, Palette, pUnkOuter);
3545 if (pUnkOuter)
3546 return CLASS_E_NOAGGREGATION;
3548 wined3d_mutex_lock();
3550 /* The refcount test shows that a cooplevel is required for this */
3551 if (!ddraw->cooperative_level)
3553 WARN("No cooperative level set, returning DDERR_NOCOOPERATIVELEVELSET\n");
3554 wined3d_mutex_unlock();
3555 return DDERR_NOCOOPERATIVELEVELSET;
3558 if (!(object = malloc(sizeof(*object))))
3560 ERR("Out of memory when allocating memory for a palette implementation\n");
3561 wined3d_mutex_unlock();
3562 return E_OUTOFMEMORY;
3565 hr = ddraw_palette_init(object, ddraw, Flags, ColorTable);
3566 if (FAILED(hr))
3568 WARN("Failed to initialize palette, hr %#lx.\n", hr);
3569 free(object);
3570 wined3d_mutex_unlock();
3571 return hr;
3574 TRACE("Created palette %p.\n", object);
3575 *Palette = &object->IDirectDrawPalette_iface;
3576 wined3d_mutex_unlock();
3578 return DD_OK;
3581 static HRESULT WINAPI ddraw4_CreatePalette(IDirectDraw4 *iface, DWORD flags, PALETTEENTRY *entries,
3582 IDirectDrawPalette **palette, IUnknown *outer_unknown)
3584 struct ddraw *ddraw = impl_from_IDirectDraw4(iface);
3585 HRESULT hr;
3587 TRACE("iface %p, flags %#lx, entries %p, palette %p, outer_unknown %p.\n",
3588 iface, flags, entries, palette, outer_unknown);
3590 hr = ddraw7_CreatePalette(&ddraw->IDirectDraw7_iface, flags, entries, palette, outer_unknown);
3591 if (SUCCEEDED(hr) && *palette)
3593 struct ddraw_palette *impl = impl_from_IDirectDrawPalette(*palette);
3594 IDirectDraw7_Release(&ddraw->IDirectDraw7_iface);
3595 IDirectDraw4_AddRef(iface);
3596 impl->ifaceToRelease = (IUnknown *)iface;
3598 return hr;
3601 static HRESULT WINAPI ddraw2_CreatePalette(IDirectDraw2 *iface, DWORD flags,
3602 PALETTEENTRY *entries, IDirectDrawPalette **palette, IUnknown *outer_unknown)
3604 struct ddraw *ddraw = impl_from_IDirectDraw2(iface);
3605 HRESULT hr;
3607 TRACE("iface %p, flags %#lx, entries %p, palette %p, outer_unknown %p.\n",
3608 iface, flags, entries, palette, outer_unknown);
3610 hr = ddraw7_CreatePalette(&ddraw->IDirectDraw7_iface, flags, entries, palette, outer_unknown);
3611 if (SUCCEEDED(hr) && *palette)
3613 struct ddraw_palette *impl = impl_from_IDirectDrawPalette(*palette);
3614 IDirectDraw7_Release(&ddraw->IDirectDraw7_iface);
3615 impl->ifaceToRelease = NULL;
3618 return hr;
3621 static HRESULT WINAPI ddraw1_CreatePalette(IDirectDraw *iface, DWORD flags,
3622 PALETTEENTRY *entries, IDirectDrawPalette **palette, IUnknown *outer_unknown)
3624 struct ddraw *ddraw = impl_from_IDirectDraw(iface);
3625 HRESULT hr;
3627 TRACE("iface %p, flags %#lx, entries %p, palette %p, outer_unknown %p.\n",
3628 iface, flags, entries, palette, outer_unknown);
3630 hr = ddraw7_CreatePalette(&ddraw->IDirectDraw7_iface, flags, entries, palette, outer_unknown);
3631 if (SUCCEEDED(hr) && *palette)
3633 struct ddraw_palette *impl = impl_from_IDirectDrawPalette(*palette);
3634 IDirectDraw7_Release(&ddraw->IDirectDraw7_iface);
3635 impl->ifaceToRelease = NULL;
3638 return hr;
3641 /*****************************************************************************
3642 * IDirectDraw7::DuplicateSurface
3644 * Duplicates a surface. The surface memory points to the same memory as
3645 * the original surface, and it's released when the last surface referencing
3646 * it is released. I guess that's beyond Wine's surface management right now
3647 * (Idea: create a new DDraw surface with the same WineD3DSurface. I need a
3648 * test application to implement this)
3650 * Params:
3651 * Src: Address of the source surface
3652 * Dest: Address to write the new surface pointer to
3654 * Returns:
3655 * See IDirectDraw7::CreateSurface
3657 *****************************************************************************/
3658 static HRESULT WINAPI ddraw7_DuplicateSurface(IDirectDraw7 *iface,
3659 IDirectDrawSurface7 *Src, IDirectDrawSurface7 **Dest)
3661 struct ddraw_surface *src_surface = unsafe_impl_from_IDirectDrawSurface7(Src);
3663 FIXME("iface %p, src %p, dst %p partial stub!\n", iface, Src, Dest);
3665 /* For now, simply create a new, independent surface */
3666 return IDirectDraw7_CreateSurface(iface, &src_surface->surface_desc, Dest, NULL);
3669 static HRESULT WINAPI ddraw4_DuplicateSurface(IDirectDraw4 *iface, IDirectDrawSurface4 *src,
3670 IDirectDrawSurface4 **dst)
3672 struct ddraw_surface *src_impl = unsafe_impl_from_IDirectDrawSurface4(src);
3673 struct ddraw *ddraw = impl_from_IDirectDraw4(iface);
3674 struct ddraw_surface *dst_impl;
3675 IDirectDrawSurface7 *dst7;
3676 HRESULT hr;
3678 TRACE("iface %p, src %p, dst %p.\n", iface, src, dst);
3680 hr = ddraw7_DuplicateSurface(&ddraw->IDirectDraw7_iface,
3681 src_impl ? &src_impl->IDirectDrawSurface7_iface : NULL, &dst7);
3682 if (FAILED(hr))
3684 *dst = NULL;
3685 return hr;
3687 dst_impl = impl_from_IDirectDrawSurface7(dst7);
3688 *dst = &dst_impl->IDirectDrawSurface4_iface;
3689 IDirectDrawSurface4_AddRef(*dst);
3690 IDirectDrawSurface7_Release(dst7);
3692 return hr;
3695 static HRESULT WINAPI ddraw2_DuplicateSurface(IDirectDraw2 *iface,
3696 IDirectDrawSurface *src, IDirectDrawSurface **dst)
3698 struct ddraw_surface *src_impl = unsafe_impl_from_IDirectDrawSurface(src);
3699 struct ddraw *ddraw = impl_from_IDirectDraw2(iface);
3700 struct ddraw_surface *dst_impl;
3701 IDirectDrawSurface7 *dst7;
3702 HRESULT hr;
3704 TRACE("iface %p, src %p, dst %p.\n", iface, src, dst);
3706 hr = ddraw7_DuplicateSurface(&ddraw->IDirectDraw7_iface,
3707 src_impl ? &src_impl->IDirectDrawSurface7_iface : NULL, &dst7);
3708 if (FAILED(hr))
3709 return hr;
3710 dst_impl = impl_from_IDirectDrawSurface7(dst7);
3711 *dst = &dst_impl->IDirectDrawSurface_iface;
3712 IDirectDrawSurface_AddRef(*dst);
3713 IDirectDrawSurface7_Release(dst7);
3715 return hr;
3718 static HRESULT WINAPI ddraw1_DuplicateSurface(IDirectDraw *iface, IDirectDrawSurface *src,
3719 IDirectDrawSurface **dst)
3721 struct ddraw_surface *src_impl = unsafe_impl_from_IDirectDrawSurface(src);
3722 struct ddraw *ddraw = impl_from_IDirectDraw(iface);
3723 struct ddraw_surface *dst_impl;
3724 IDirectDrawSurface7 *dst7;
3725 HRESULT hr;
3727 TRACE("iface %p, src %p, dst %p.\n", iface, src, dst);
3729 hr = ddraw7_DuplicateSurface(&ddraw->IDirectDraw7_iface,
3730 src_impl ? &src_impl->IDirectDrawSurface7_iface : NULL, &dst7);
3731 if (FAILED(hr))
3732 return hr;
3733 dst_impl = impl_from_IDirectDrawSurface7(dst7);
3734 *dst = &dst_impl->IDirectDrawSurface_iface;
3735 IDirectDrawSurface_AddRef(*dst);
3736 IDirectDrawSurface7_Release(dst7);
3738 return hr;
3741 /*****************************************************************************
3742 * IDirect3D7::EnumDevices
3744 * The EnumDevices method for IDirect3D7. It enumerates all supported
3745 * D3D7 devices. Currently the T&L, HAL and RGB devices are enumerated.
3747 * Params:
3748 * callback: Function to call for each enumerated device
3749 * context: Pointer to pass back to the app
3751 * Returns:
3752 * D3D_OK, or the return value of the GetCaps call
3754 *****************************************************************************/
3755 static HRESULT WINAPI d3d7_EnumDevices(IDirect3D7 *iface, LPD3DENUMDEVICESCALLBACK7 callback, void *context)
3757 struct ddraw *ddraw = impl_from_IDirect3D7(iface);
3758 D3DDEVICEDESC7 device_desc7;
3759 DWORD dev_caps;
3760 HRESULT hr;
3761 size_t i;
3763 TRACE("iface %p, callback %p, context %p.\n", iface, callback, context);
3765 if (!callback)
3766 return DDERR_INVALIDPARAMS;
3768 wined3d_mutex_lock();
3770 if (FAILED(hr = ddraw_get_d3dcaps(ddraw, &device_desc7)))
3772 wined3d_mutex_unlock();
3773 return hr;
3775 dev_caps = device_desc7.dwDevCaps;
3777 for (i = 0; i < ARRAY_SIZE(device_list7); i++)
3779 HRESULT ret;
3781 device_desc7.deviceGUID = *device_list7[i].device_guid;
3782 device_desc7.dwDevCaps = dev_caps & ~device_list7[i].unsupported_caps;
3783 ret = callback(device_list7[i].interface_name, device_list7[i].device_name, &device_desc7, context);
3784 if (ret != DDENUMRET_OK)
3786 TRACE("Application cancelled the enumeration.\n");
3787 wined3d_mutex_unlock();
3788 return D3D_OK;
3792 TRACE("End of enumeration.\n");
3794 wined3d_mutex_unlock();
3796 return D3D_OK;
3799 /*****************************************************************************
3800 * IDirect3D3::EnumDevices
3802 * Enumerates all supported Direct3DDevice interfaces. This is the
3803 * implementation for Direct3D 1 to Direc3D 3, Version 7 has its own.
3805 * Versions 1, 2 and 3
3807 * Params:
3808 * callback: Application-provided routine to call for each enumerated device
3809 * Context: Pointer to pass to the callback
3811 * Returns:
3812 * D3D_OK on success,
3813 * The result of IDirect3DImpl_GetCaps if it failed
3815 *****************************************************************************/
3816 static HRESULT WINAPI d3d3_EnumDevices(IDirect3D3 *iface, LPD3DENUMDEVICESCALLBACK callback, void *context)
3818 static CHAR wined3d_description[] = "Wine D3DDevice using WineD3D and OpenGL";
3820 struct ddraw *ddraw = impl_from_IDirect3D3(iface);
3821 D3DDEVICEDESC device_desc1, hal_desc, hel_desc;
3822 D3DDEVICEDESC7 device_desc7;
3823 HRESULT hr;
3825 /* Some games (Motoracer 2 demo) have the bad idea to modify the device
3826 * name string. Let's put the string in a sufficiently sized array in
3827 * writable memory. */
3828 char device_name[50];
3829 strcpy(device_name,"Direct3D HEL");
3831 TRACE("iface %p, callback %p, context %p.\n", iface, callback, context);
3833 if (!callback)
3834 return DDERR_INVALIDPARAMS;
3836 wined3d_mutex_lock();
3838 if (FAILED(hr = ddraw_get_d3dcaps(ddraw, &device_desc7)))
3840 wined3d_mutex_unlock();
3841 return hr;
3843 ddraw_d3dcaps1_from_7(&device_desc1, &device_desc7);
3845 /* Do I have to enumerate the reference id? Note from old d3d7:
3846 * "It seems that enumerating the reference IID on Direct3D 1 games
3847 * (AvP / Motoracer2) breaks them". So do not enumerate this iid in V1
3849 * There's a registry key HKLM\Software\Microsoft\Direct3D\Drivers,
3850 * EnumReference which enables / disables enumerating the reference
3851 * rasterizer. It's a DWORD, 0 means disabled, 2 means enabled. The
3852 * enablerefrast.reg and disablerefrast.reg files in the DirectX 7.0 sdk
3853 * demo directory suggest this.
3855 * Some games(GTA 2) seem to use the second enumerated device, so I have
3856 * to enumerate at least 2 devices. So enumerate the reference device to
3857 * have 2 devices.
3859 * Other games (Rollcage) tell emulation and hal device apart by certain
3860 * flags. Rollcage expects D3DPTEXTURECAPS_POW2 to be set (yeah, it is a
3861 * limitation flag), and it refuses all devices that have the perspective
3862 * flag set. This way it refuses the emulation device, and HAL devices
3863 * never have POW2 unset in d3d7 on windows. */
3864 if (ddraw->d3dversion != 1)
3866 /* Tomb Raider 3 overwrites the reference device description buffer
3867 * with its own custom string. Reserve some extra space in the array
3868 * to avoid a buffer overrun. */
3869 static CHAR reference_description[64] = "RGB Direct3D emulation";
3871 TRACE("Enumerating WineD3D D3DDevice interface.\n");
3872 hal_desc = device_desc1;
3873 hel_desc = device_desc1;
3874 /* The rgb device has the pow2 flag set in the hel caps, but not in the hal caps. */
3875 hal_desc.dpcLineCaps.dwTextureCaps &= ~(D3DPTEXTURECAPS_POW2
3876 | D3DPTEXTURECAPS_NONPOW2CONDITIONAL | D3DPTEXTURECAPS_PERSPECTIVE);
3877 hal_desc.dpcTriCaps.dwTextureCaps &= ~(D3DPTEXTURECAPS_POW2
3878 | D3DPTEXTURECAPS_NONPOW2CONDITIONAL | D3DPTEXTURECAPS_PERSPECTIVE);
3879 /* RGB, RAMP and MMX devices have a HAL dcmColorModel of 0 */
3880 hal_desc.dcmColorModel = 0;
3881 /* RGB, RAMP and MMX devices cannot report HAL hardware flags */
3882 hal_desc.dwFlags = 0;
3883 /* RGB, REF, RAMP and MMX devices don't report hardware transform and lighting capability */
3884 hal_desc.dwDevCaps &= ~(D3DDEVCAPS_HWTRANSFORMANDLIGHT | D3DDEVCAPS_DRAWPRIMITIVES2EX | D3DDEVCAPS_HWRASTERIZATION);
3885 hel_desc.dwDevCaps &= ~(D3DDEVCAPS_HWTRANSFORMANDLIGHT | D3DDEVCAPS_DRAWPRIMITIVES2EX | D3DDEVCAPS_HWRASTERIZATION);
3887 hr = callback((GUID *)&IID_IDirect3DRGBDevice, reference_description,
3888 device_name, &hal_desc, &hel_desc, context);
3889 if (hr != D3DENUMRET_OK)
3891 TRACE("Application cancelled the enumeration.\n");
3892 wined3d_mutex_unlock();
3893 return D3D_OK;
3897 strcpy(device_name,"Direct3D HAL");
3899 TRACE("Enumerating HAL Direct3D device.\n");
3900 hal_desc = device_desc1;
3901 hel_desc = device_desc1;
3903 /* The hal device does not have the pow2 flag set in hel, but in hal. */
3904 hel_desc.dpcLineCaps.dwTextureCaps &= ~(D3DPTEXTURECAPS_POW2
3905 | D3DPTEXTURECAPS_NONPOW2CONDITIONAL | D3DPTEXTURECAPS_PERSPECTIVE);
3906 hel_desc.dpcTriCaps.dwTextureCaps &= ~(D3DPTEXTURECAPS_POW2
3907 | D3DPTEXTURECAPS_NONPOW2CONDITIONAL | D3DPTEXTURECAPS_PERSPECTIVE);
3908 /* HAL devices have a HEL dcmColorModel of 0 */
3909 hel_desc.dcmColorModel = 0;
3910 /* HAL devices report hardware transform and lighting capability, but not in hel */
3911 hel_desc.dwDevCaps &= ~(D3DDEVCAPS_HWTRANSFORMANDLIGHT | D3DDEVCAPS_DRAWPRIMITIVES2EX);
3913 hr = callback((GUID *)&IID_IDirect3DHALDevice, wined3d_description,
3914 device_name, &hal_desc, &hel_desc, context);
3915 if (hr != D3DENUMRET_OK)
3917 TRACE("Application cancelled the enumeration.\n");
3918 wined3d_mutex_unlock();
3919 return D3D_OK;
3922 TRACE("End of enumeration.\n");
3924 wined3d_mutex_unlock();
3926 return D3D_OK;
3929 static HRESULT WINAPI d3d2_EnumDevices(IDirect3D2 *iface, LPD3DENUMDEVICESCALLBACK callback, void *context)
3931 struct ddraw *ddraw = impl_from_IDirect3D2(iface);
3933 TRACE("iface %p, callback %p, context %p.\n", iface, callback, context);
3935 return d3d3_EnumDevices(&ddraw->IDirect3D3_iface, callback, context);
3938 static HRESULT WINAPI d3d1_EnumDevices(IDirect3D *iface, LPD3DENUMDEVICESCALLBACK callback, void *context)
3940 struct ddraw *ddraw = impl_from_IDirect3D(iface);
3942 TRACE("iface %p, callback %p, context %p.\n", iface, callback, context);
3944 return d3d3_EnumDevices(&ddraw->IDirect3D3_iface, callback, context);
3947 /*****************************************************************************
3948 * IDirect3D3::CreateLight
3950 * Creates an IDirect3DLight interface. This interface is used in
3951 * Direct3D3 or earlier for lighting. In Direct3D7 it has been replaced
3952 * by the DIRECT3DLIGHT7 structure. Wine's Direct3DLight implementation
3953 * uses the IDirect3DDevice7 interface with D3D7 lights.
3955 * Versions 1, 2 and 3
3957 * Params:
3958 * light: Address to store the new interface pointer
3959 * outer_unknown: Basically for aggregation, but ddraw doesn't support it.
3960 * Must be NULL
3962 * Returns:
3963 * D3D_OK on success
3964 * DDERR_OUTOFMEMORY if memory allocation failed
3965 * CLASS_E_NOAGGREGATION if outer_unknown != NULL
3967 *****************************************************************************/
3968 static HRESULT WINAPI d3d3_CreateLight(IDirect3D3 *iface, IDirect3DLight **light,
3969 IUnknown *outer_unknown)
3971 struct ddraw *ddraw = impl_from_IDirect3D3(iface);
3972 struct d3d_light *object;
3974 TRACE("iface %p, light %p, outer_unknown %p.\n", iface, light, outer_unknown);
3976 if (outer_unknown)
3977 return CLASS_E_NOAGGREGATION;
3979 if (!(object = calloc(1, sizeof(*object))))
3981 ERR("Failed to allocate light memory.\n");
3982 return DDERR_OUTOFMEMORY;
3985 d3d_light_init(object, ddraw);
3987 TRACE("Created light %p.\n", object);
3988 *light = &object->IDirect3DLight_iface;
3990 return D3D_OK;
3993 static HRESULT WINAPI d3d2_CreateLight(IDirect3D2 *iface, IDirect3DLight **light, IUnknown *outer_unknown)
3995 struct ddraw *ddraw = impl_from_IDirect3D2(iface);
3997 TRACE("iface %p, light %p, outer_unknown %p.\n", iface, light, outer_unknown);
3999 return d3d3_CreateLight(&ddraw->IDirect3D3_iface, light, outer_unknown);
4002 static HRESULT WINAPI d3d1_CreateLight(IDirect3D *iface, IDirect3DLight **light, IUnknown *outer_unknown)
4004 struct ddraw *ddraw = impl_from_IDirect3D(iface);
4006 TRACE("iface %p, light %p, outer_unknown %p.\n", iface, light, outer_unknown);
4008 return d3d3_CreateLight(&ddraw->IDirect3D3_iface, light, outer_unknown);
4011 /*****************************************************************************
4012 * IDirect3D3::CreateMaterial
4014 * Creates an IDirect3DMaterial interface. This interface is used by Direct3D3
4015 * and older versions. The IDirect3DMaterial implementation wraps its
4016 * functionality to IDirect3DDevice7::SetMaterial and friends.
4018 * Versions 1, 2 and 3
4020 * Params:
4021 * material: Address to store the new interface's pointer to
4022 * outer_unknown: Basically for aggregation, but ddraw doesn't support it.
4023 * Must be NULL
4025 * Returns:
4026 * D3D_OK on success
4027 * DDERR_OUTOFMEMORY if memory allocation failed
4028 * CLASS_E_NOAGGREGATION if outer_unknown != NULL
4030 *****************************************************************************/
4031 static HRESULT WINAPI d3d3_CreateMaterial(IDirect3D3 *iface, IDirect3DMaterial3 **material,
4032 IUnknown *outer_unknown)
4034 struct ddraw *ddraw = impl_from_IDirect3D3(iface);
4035 struct d3d_material *object;
4037 TRACE("iface %p, material %p, outer_unknown %p.\n", iface, material, outer_unknown);
4039 if (outer_unknown) return CLASS_E_NOAGGREGATION;
4041 object = d3d_material_create(ddraw);
4042 if (!object)
4044 ERR("Failed to allocate material memory.\n");
4045 return DDERR_OUTOFMEMORY;
4048 TRACE("Created material %p.\n", object);
4049 *material = &object->IDirect3DMaterial3_iface;
4051 return D3D_OK;
4054 static HRESULT WINAPI d3d2_CreateMaterial(IDirect3D2 *iface, IDirect3DMaterial2 **material,
4055 IUnknown *outer_unknown)
4057 struct ddraw *ddraw = impl_from_IDirect3D2(iface);
4058 struct d3d_material *object;
4060 TRACE("iface %p, material %p, outer_unknown %p.\n", iface, material, outer_unknown);
4062 object = d3d_material_create(ddraw);
4063 if (!object)
4065 ERR("Failed to allocate material memory.\n");
4066 return DDERR_OUTOFMEMORY;
4069 TRACE("Created material %p.\n", object);
4070 *material = &object->IDirect3DMaterial2_iface;
4072 return D3D_OK;
4075 static HRESULT WINAPI d3d1_CreateMaterial(IDirect3D *iface, IDirect3DMaterial **material,
4076 IUnknown *outer_unknown)
4078 struct ddraw *ddraw = impl_from_IDirect3D(iface);
4079 struct d3d_material *object;
4081 TRACE("iface %p, material %p, outer_unknown %p.\n", iface, material, outer_unknown);
4083 object = d3d_material_create(ddraw);
4084 if (!object)
4086 ERR("Failed to allocate material memory.\n");
4087 return DDERR_OUTOFMEMORY;
4090 TRACE("Created material %p.\n", object);
4091 *material = &object->IDirect3DMaterial_iface;
4093 return D3D_OK;
4096 /*****************************************************************************
4097 * IDirect3D3::CreateViewport
4099 * Creates an IDirect3DViewport interface. This interface is used
4100 * by Direct3D and earlier versions for Viewport management. In Direct3D7
4101 * it has been replaced by a viewport structure and
4102 * IDirect3DDevice7::*Viewport. Wine's IDirect3DViewport implementation
4103 * uses the IDirect3DDevice7 methods for its functionality
4105 * Params:
4106 * Viewport: Address to store the new interface pointer
4107 * outer_unknown: Basically for aggregation, but ddraw doesn't support it.
4108 * Must be NULL
4110 * Returns:
4111 * D3D_OK on success
4112 * DDERR_OUTOFMEMORY if memory allocation failed
4113 * CLASS_E_NOAGGREGATION if outer_unknown != NULL
4115 *****************************************************************************/
4116 static HRESULT WINAPI d3d3_CreateViewport(IDirect3D3 *iface, IDirect3DViewport3 **viewport,
4117 IUnknown *outer_unknown)
4119 struct ddraw *ddraw = impl_from_IDirect3D3(iface);
4120 struct d3d_viewport *object;
4122 TRACE("iface %p, viewport %p, outer_unknown %p.\n", iface, viewport, outer_unknown);
4124 if (outer_unknown) return CLASS_E_NOAGGREGATION;
4126 if (!(object = calloc(1, sizeof(*object))))
4128 ERR("Failed to allocate viewport memory.\n");
4129 return DDERR_OUTOFMEMORY;
4132 d3d_viewport_init(object, ddraw);
4134 TRACE("Created viewport %p.\n", object);
4135 *viewport = &object->IDirect3DViewport3_iface;
4137 return D3D_OK;
4140 static HRESULT WINAPI d3d2_CreateViewport(IDirect3D2 *iface, IDirect3DViewport2 **viewport, IUnknown *outer_unknown)
4142 struct ddraw *ddraw = impl_from_IDirect3D2(iface);
4144 TRACE("iface %p, viewport %p, outer_unknown %p.\n", iface, viewport, outer_unknown);
4146 return d3d3_CreateViewport(&ddraw->IDirect3D3_iface, (IDirect3DViewport3 **)viewport,
4147 outer_unknown);
4150 static HRESULT WINAPI d3d1_CreateViewport(IDirect3D *iface, IDirect3DViewport **viewport, IUnknown *outer_unknown)
4152 struct ddraw *ddraw = impl_from_IDirect3D(iface);
4154 TRACE("iface %p, viewport %p, outer_unknown %p.\n", iface, viewport, outer_unknown);
4156 return d3d3_CreateViewport(&ddraw->IDirect3D3_iface, (IDirect3DViewport3 **)viewport,
4157 outer_unknown);
4160 static HRESULT ddraw_find_device(struct ddraw *ddraw, const D3DFINDDEVICESEARCH *fds, D3DFINDDEVICERESULT *fdr,
4161 unsigned int guid_count, const GUID * const *guids, DWORD device_desc_size)
4163 struct ddraw_find_device_result_v1
4165 DWORD size;
4166 GUID guid;
4167 D3DDEVICEDESC_V1 hw_desc;
4168 D3DDEVICEDESC_V1 sw_desc;
4169 } *fdr1;
4170 struct ddraw_find_device_result_v2
4172 DWORD size;
4173 GUID guid;
4174 D3DDEVICEDESC_V2 hw_desc;
4175 D3DDEVICEDESC_V2 sw_desc;
4176 } *fdr2;
4177 D3DDEVICEDESC7 desc7;
4178 D3DDEVICEDESC desc1;
4179 unsigned int i;
4180 HRESULT hr;
4182 TRACE("ddraw %p, fds %p, fdr %p, guid_count %u, guids %p, device_desc_size %lu.\n",
4183 ddraw, fds, fdr, guid_count, guids, device_desc_size);
4185 if (!fds || !fdr)
4186 return DDERR_INVALIDPARAMS;
4188 if (fds->dwSize != sizeof(*fds))
4190 WARN("Got invalid search structure size %lu.\n", fds->dwSize);
4191 return DDERR_INVALIDPARAMS;
4194 if (fdr->dwSize != sizeof(*fdr) && fdr->dwSize != sizeof(*fdr2) && fdr->dwSize != sizeof(*fdr1))
4196 WARN("Got invalid result structure size %lu.\n", fdr->dwSize);
4197 return DDERR_INVALIDPARAMS;
4200 if (fds->dwFlags & D3DFDS_COLORMODEL)
4201 WARN("Ignoring colour model %#lx.\n", fds->dcmColorModel);
4203 if (fds->dwFlags & D3DFDS_GUID)
4205 BOOL found = FALSE;
4207 TRACE("Trying to match GUID %s.\n", debugstr_guid(&fds->guid));
4209 if ((ddraw->flags & DDRAW_NO3D) && IsEqualGUID(&fds->guid, &IID_IDirect3DHALDevice))
4211 WARN("HAL device not available without 3D support.\n");
4212 return DDERR_NOTFOUND;
4215 for (i = 0; i < guid_count; ++i)
4217 if (IsEqualGUID(guids[i], &fds->guid))
4219 found = TRUE;
4220 break;
4224 if (!found)
4226 WARN("Failed to match GUID %s.\n", debugstr_guid(&fds->guid));
4227 return DDERR_NOTFOUND;
4231 /* Get the caps */
4232 if (FAILED(hr = ddraw_get_d3dcaps(ddraw, &desc7)))
4233 return hr;
4235 /* Now return our own GUID */
4236 ddraw_d3dcaps1_from_7(&desc1, &desc7);
4237 fdr->guid = IID_D3DDEVICE_WineD3D;
4239 /* Note that "device_desc_size" doesn't necessarily have any relation to
4240 * the actual structure size. However, this matches the behaviour of
4241 * Windows since at least Windows 2000. */
4242 if (fdr->dwSize == sizeof(*fdr1))
4244 fdr1 = (struct ddraw_find_device_result_v1 *)fdr;
4245 memcpy(&fdr1->hw_desc, &desc1, sizeof(fdr1->hw_desc));
4246 fdr1->hw_desc.dwSize = device_desc_size;
4247 memcpy(&fdr1->sw_desc, &desc1, sizeof(fdr1->sw_desc));
4248 fdr1->sw_desc.dwSize = device_desc_size;
4250 else if (fdr->dwSize == sizeof(*fdr2))
4252 fdr2 = (struct ddraw_find_device_result_v2 *)fdr;
4253 memcpy(&fdr2->hw_desc, &desc1, sizeof(fdr2->hw_desc));
4254 fdr2->hw_desc.dwSize = device_desc_size;
4255 memcpy(&fdr2->sw_desc, &desc1, sizeof(fdr2->sw_desc));
4256 fdr2->sw_desc.dwSize = device_desc_size;
4258 else
4260 fdr->ddHwDesc = desc1;
4261 fdr->ddHwDesc.dwSize = device_desc_size;
4262 fdr->ddSwDesc = desc1;
4263 fdr->ddSwDesc.dwSize = device_desc_size;
4266 TRACE("Returning Wine's wined3d device with (undumped) capabilities.\n");
4268 return D3D_OK;
4271 static HRESULT WINAPI d3d3_FindDevice(IDirect3D3 *iface, D3DFINDDEVICESEARCH *fds, D3DFINDDEVICERESULT *fdr)
4273 struct ddraw *ddraw = impl_from_IDirect3D3(iface);
4274 static const GUID * const guids[] =
4276 &IID_D3DDEVICE_WineD3D,
4277 &IID_IDirect3DHALDevice,
4278 &IID_IDirect3DRGBDevice,
4281 TRACE("iface %p, fds %p, fdr %p.\n", iface, fds, fdr);
4283 return ddraw_find_device(ddraw, fds, fdr, ARRAY_SIZE(guids), guids, sizeof(D3DDEVICEDESC_V3));
4286 static HRESULT WINAPI d3d2_FindDevice(IDirect3D2 *iface, D3DFINDDEVICESEARCH *fds, D3DFINDDEVICERESULT *fdr)
4288 struct ddraw *ddraw = impl_from_IDirect3D2(iface);
4289 static const GUID * const guids[] =
4291 &IID_D3DDEVICE_WineD3D,
4292 &IID_IDirect3DHALDevice,
4293 &IID_IDirect3DMMXDevice,
4294 &IID_IDirect3DRGBDevice,
4295 &IID_IDirect3DRampDevice,
4298 TRACE("iface %p, fds %p, fdr %p.\n", iface, fds, fdr);
4300 return ddraw_find_device(ddraw, fds, fdr, ARRAY_SIZE(guids), guids, sizeof(D3DDEVICEDESC_V2));
4303 static HRESULT WINAPI d3d1_FindDevice(IDirect3D *iface, D3DFINDDEVICESEARCH *fds, D3DFINDDEVICERESULT *fdr)
4305 struct ddraw *ddraw = impl_from_IDirect3D(iface);
4306 static const GUID * const guids[] =
4308 &IID_D3DDEVICE_WineD3D,
4309 &IID_IDirect3DHALDevice,
4310 &IID_IDirect3DRGBDevice,
4311 &IID_IDirect3DRampDevice,
4314 TRACE("iface %p, fds %p, fdr %p.\n", iface, fds, fdr);
4316 return ddraw_find_device(ddraw, fds, fdr, ARRAY_SIZE(guids), guids, sizeof(D3DDEVICEDESC_V1));
4319 /*****************************************************************************
4320 * IDirect3D7::CreateDevice
4322 * Creates an IDirect3DDevice7 interface.
4324 * Versions 2, 3 and 7. IDirect3DDevice 1 interfaces are interfaces to
4325 * DirectDraw surfaces and are created with
4326 * IDirectDrawSurface::QueryInterface. This method uses CreateDevice to
4327 * create the device object and QueryInterfaces for IDirect3DDevice
4329 * Params:
4330 * refiid: IID of the device to create
4331 * Surface: Initial rendertarget
4332 * Device: Address to return the interface pointer
4334 * Returns:
4335 * D3D_OK on success
4336 * DDERR_OUTOFMEMORY if memory allocation failed
4337 * DDERR_INVALIDPARAMS if a device exists already
4339 *****************************************************************************/
4340 static HRESULT WINAPI d3d7_CreateDevice(IDirect3D7 *iface, REFCLSID riid,
4341 IDirectDrawSurface7 *surface, IDirect3DDevice7 **device)
4343 struct ddraw_surface *target = unsafe_impl_from_IDirectDrawSurface7(surface);
4344 struct ddraw *ddraw = impl_from_IDirect3D7(iface);
4345 struct d3d_device *object;
4346 HRESULT hr;
4348 TRACE("iface %p, riid %s, surface %p, device %p.\n", iface, debugstr_guid(riid), surface, device);
4350 wined3d_mutex_lock();
4351 if (SUCCEEDED(hr = d3d_device_create(ddraw, riid, target, (IUnknown *)surface, 7, &object, NULL)))
4353 *device = &object->IDirect3DDevice7_iface;
4355 else
4357 WARN("Failed to create device, hr %#lx.\n", hr);
4358 *device = NULL;
4360 wined3d_mutex_unlock();
4362 return hr;
4365 static HRESULT WINAPI d3d3_CreateDevice(IDirect3D3 *iface, REFCLSID riid,
4366 IDirectDrawSurface4 *surface, IDirect3DDevice3 **device, IUnknown *outer_unknown)
4368 struct ddraw_surface *surface_impl = unsafe_impl_from_IDirectDrawSurface4(surface);
4369 struct ddraw *ddraw = impl_from_IDirect3D3(iface);
4370 struct d3d_device *device_impl;
4371 HRESULT hr;
4373 TRACE("iface %p, riid %s, surface %p, device %p, outer_unknown %p.\n",
4374 iface, debugstr_guid(riid), surface, device, outer_unknown);
4376 if (outer_unknown)
4377 return CLASS_E_NOAGGREGATION;
4379 wined3d_mutex_lock();
4380 if (SUCCEEDED(hr = d3d_device_create(ddraw, riid, surface_impl, (IUnknown *)surface, 3, &device_impl, NULL)))
4382 *device = &device_impl->IDirect3DDevice3_iface;
4384 else
4386 WARN("Failed to create device, hr %#lx.\n", hr);
4387 *device = NULL;
4389 wined3d_mutex_unlock();
4391 return hr;
4394 static HRESULT WINAPI d3d2_CreateDevice(IDirect3D2 *iface, REFCLSID riid,
4395 IDirectDrawSurface *surface, IDirect3DDevice2 **device)
4397 struct ddraw_surface *surface_impl = unsafe_impl_from_IDirectDrawSurface(surface);
4398 struct ddraw *ddraw = impl_from_IDirect3D2(iface);
4399 struct d3d_device *device_impl;
4400 HRESULT hr;
4402 TRACE("iface %p, riid %s, surface %p, device %p.\n",
4403 iface, debugstr_guid(riid), surface, device);
4405 wined3d_mutex_lock();
4406 if (SUCCEEDED(hr = d3d_device_create(ddraw, riid, surface_impl, (IUnknown *)surface, 2, &device_impl, NULL)))
4408 *device = &device_impl->IDirect3DDevice2_iface;
4410 else
4412 WARN("Failed to create device, hr %#lx.\n", hr);
4413 *device = NULL;
4415 wined3d_mutex_unlock();
4417 return hr;
4420 /*****************************************************************************
4421 * IDirect3D7::CreateVertexBuffer
4423 * Creates a new vertex buffer object and returns a IDirect3DVertexBuffer7
4424 * interface.
4426 * Versions 3 and 7
4428 * Params:
4429 * desc: Requested Vertex buffer properties
4430 * vertex_buffer: Address to return the interface pointer at
4431 * flags: Some flags, should be 0
4433 * Returns
4434 * D3D_OK on success
4435 * DDERR_OUTOFMEMORY if memory allocation failed
4436 * DDERR_INVALIDPARAMS if desc or vertex_buffer is NULL
4438 *****************************************************************************/
4439 static HRESULT WINAPI d3d7_CreateVertexBuffer(IDirect3D7 *iface, D3DVERTEXBUFFERDESC *desc,
4440 IDirect3DVertexBuffer7 **vertex_buffer, DWORD flags)
4442 struct ddraw *ddraw = impl_from_IDirect3D7(iface);
4443 struct d3d_vertex_buffer *object;
4444 HRESULT hr;
4446 TRACE("iface %p, desc %p, vertex_buffer %p, flags %#lx.\n",
4447 iface, desc, vertex_buffer, flags);
4449 if (!vertex_buffer || !desc) return DDERR_INVALIDPARAMS;
4451 hr = d3d_vertex_buffer_create(&object, ddraw, desc);
4452 if (hr == D3D_OK)
4454 TRACE("Created vertex buffer %p.\n", object);
4455 *vertex_buffer = &object->IDirect3DVertexBuffer7_iface;
4457 else
4458 WARN("Failed to create vertex buffer, hr %#lx.\n", hr);
4460 return hr;
4463 static HRESULT WINAPI d3d3_CreateVertexBuffer(IDirect3D3 *iface, D3DVERTEXBUFFERDESC *desc,
4464 IDirect3DVertexBuffer **vertex_buffer, DWORD flags, IUnknown *outer_unknown)
4466 struct ddraw *ddraw = impl_from_IDirect3D3(iface);
4467 struct d3d_vertex_buffer *object;
4468 HRESULT hr;
4470 TRACE("iface %p, desc %p, vertex_buffer %p, flags %#lx, outer_unknown %p.\n",
4471 iface, desc, vertex_buffer, flags, outer_unknown);
4473 if (outer_unknown)
4474 return CLASS_E_NOAGGREGATION;
4475 if (!vertex_buffer || !desc)
4476 return DDERR_INVALIDPARAMS;
4478 hr = d3d_vertex_buffer_create(&object, ddraw, desc);
4479 if (hr == D3D_OK)
4481 TRACE("Created vertex buffer %p.\n", object);
4482 *vertex_buffer = (IDirect3DVertexBuffer *)&object->IDirect3DVertexBuffer7_iface;
4484 else
4485 WARN("Failed to create vertex buffer, hr %#lx.\n", hr);
4487 return hr;
4490 /*****************************************************************************
4491 * IDirect3D7::EnumZBufferFormats
4493 * Enumerates all supported Z buffer pixel formats
4495 * Versions 3 and 7
4497 * Params:
4498 * device_iid:
4499 * callback: callback to call for each pixel format
4500 * context: Pointer to pass back to the callback
4502 * Returns:
4503 * D3D_OK on success
4504 * DDERR_INVALIDPARAMS if callback is NULL
4506 *****************************************************************************/
4507 static HRESULT WINAPI d3d7_EnumZBufferFormats(IDirect3D7 *iface, REFCLSID device_iid,
4508 LPD3DENUMPIXELFORMATSCALLBACK callback, void *context)
4510 struct ddraw *ddraw = impl_from_IDirect3D7(iface);
4511 struct wined3d_display_mode mode;
4512 enum wined3d_device_type type;
4513 unsigned int i;
4514 HRESULT hr;
4516 /* Order matters. Specifically, BattleZone II (full version) expects the
4517 * 16-bit depth formats to be listed before the 24 and 32 ones. */
4518 static const enum wined3d_format_id formats[] =
4520 WINED3DFMT_S1_UINT_D15_UNORM,
4521 WINED3DFMT_D16_UNORM,
4522 WINED3DFMT_X8D24_UNORM,
4523 WINED3DFMT_S4X4_UINT_D24_UNORM,
4524 WINED3DFMT_D24_UNORM_S8_UINT,
4525 WINED3DFMT_D32_UNORM,
4528 TRACE("iface %p, device_iid %s, callback %p, context %p.\n",
4529 iface, debugstr_guid(device_iid), callback, context);
4531 if (!callback) return DDERR_INVALIDPARAMS;
4533 if (IsEqualGUID(device_iid, &IID_IDirect3DHALDevice)
4534 || IsEqualGUID(device_iid, &IID_IDirect3DTnLHalDevice)
4535 || IsEqualGUID(device_iid, &IID_D3DDEVICE_WineD3D))
4537 TRACE("Asked for HAL device.\n");
4538 type = WINED3D_DEVICE_TYPE_HAL;
4540 else if (IsEqualGUID(device_iid, &IID_IDirect3DRGBDevice)
4541 || IsEqualGUID(device_iid, &IID_IDirect3DMMXDevice))
4543 TRACE("Asked for SW device.\n");
4544 type = WINED3D_DEVICE_TYPE_SW;
4546 else if (IsEqualGUID(device_iid, &IID_IDirect3DRefDevice))
4548 TRACE("Asked for REF device.\n");
4549 type = WINED3D_DEVICE_TYPE_REF;
4551 else if (IsEqualGUID(device_iid, &IID_IDirect3DNullDevice))
4553 TRACE("Asked for NULLREF device.\n");
4554 type = WINED3D_DEVICE_TYPE_NULLREF;
4556 else
4558 FIXME("Unexpected device GUID %s.\n", debugstr_guid(device_iid));
4559 type = WINED3D_DEVICE_TYPE_HAL;
4562 wined3d_mutex_lock();
4563 /* We need an adapter format from somewhere to please wined3d and WGL.
4564 * Use the current display mode. So far all cards offer the same depth
4565 * stencil format for all modes, but if some do not and applications do
4566 * not like that we'll have to find some workaround, like iterating over
4567 * all imaginable formats and collecting all the depth stencil formats we
4568 * can get. */
4569 if (FAILED(hr = wined3d_output_get_display_mode(ddraw->wined3d_output, &mode, NULL)))
4571 ERR("Failed to get display mode, hr %#lx.\n", hr);
4572 wined3d_mutex_unlock();
4573 return hr;
4576 for (i = 0; i < ARRAY_SIZE(formats); ++i)
4578 if (SUCCEEDED(wined3d_check_device_format(ddraw->wined3d, ddraw->wined3d_adapter, type,
4579 mode.format_id, 0, WINED3D_BIND_DEPTH_STENCIL, WINED3D_RTYPE_TEXTURE_2D, formats[i])))
4581 DDPIXELFORMAT pformat;
4583 memset(&pformat, 0, sizeof(pformat));
4584 pformat.dwSize = sizeof(pformat);
4585 ddrawformat_from_wined3dformat(&pformat, formats[i]);
4587 TRACE("Enumerating wined3d format %#x.\n", formats[i]);
4588 hr = callback(&pformat, context);
4589 if (hr != DDENUMRET_OK)
4591 TRACE("Format enumeration cancelled by application.\n");
4592 wined3d_mutex_unlock();
4593 return D3D_OK;
4598 /* Historically some windows drivers used dwZBufferBitDepth=24 for WINED3DFMT_X8D24_UNORM,
4599 * while others used dwZBufferBitDepth=32. In either case the pitch matches a 32 bits per
4600 * pixel format, so we use dwZBufferBitDepth=32. Some games expect 24. Windows Vista and
4601 * newer enumerate both versions, so we do the same(bug 22434) */
4602 if (SUCCEEDED(wined3d_check_device_format(ddraw->wined3d, ddraw->wined3d_adapter, type, mode.format_id,
4603 0, WINED3D_BIND_DEPTH_STENCIL, WINED3D_RTYPE_TEXTURE_2D, WINED3DFMT_X8D24_UNORM)))
4605 DDPIXELFORMAT x8d24 =
4607 sizeof(x8d24), DDPF_ZBUFFER, 0,
4608 {24}, {0x00000000}, {0x00ffffff}, {0x00000000}
4610 TRACE("Enumerating WINED3DFMT_X8D24_UNORM, dwZBufferBitDepth=24 version\n");
4611 callback(&x8d24, context);
4614 TRACE("End of enumeration.\n");
4616 wined3d_mutex_unlock();
4618 return D3D_OK;
4621 static HRESULT WINAPI d3d3_EnumZBufferFormats(IDirect3D3 *iface, REFCLSID device_iid,
4622 LPD3DENUMPIXELFORMATSCALLBACK callback, void *context)
4624 struct ddraw *ddraw = impl_from_IDirect3D3(iface);
4626 TRACE("iface %p, device_iid %s, callback %p, context %p.\n",
4627 iface, debugstr_guid(device_iid), callback, context);
4629 return d3d7_EnumZBufferFormats(&ddraw->IDirect3D7_iface, device_iid, callback, context);
4632 /*****************************************************************************
4633 * IDirect3D7::EvictManagedTextures
4635 * Removes all managed textures (=surfaces with DDSCAPS2_TEXTUREMANAGE or
4636 * DDSCAPS2_D3DTEXTUREMANAGE caps) to be removed from video memory.
4638 * Versions 3 and 7
4640 * Returns:
4641 * D3D_OK, because it's a stub
4643 *****************************************************************************/
4644 static HRESULT WINAPI d3d7_EvictManagedTextures(IDirect3D7 *iface)
4646 struct ddraw *ddraw = impl_from_IDirect3D7(iface);
4648 TRACE("iface %p!\n", iface);
4650 wined3d_mutex_lock();
4651 if (ddraw->flags & DDRAW_D3D_INITIALIZED)
4652 wined3d_device_evict_managed_resources(ddraw->wined3d_device);
4653 wined3d_mutex_unlock();
4655 return D3D_OK;
4658 static HRESULT WINAPI d3d3_EvictManagedTextures(IDirect3D3 *iface)
4660 struct ddraw *ddraw = impl_from_IDirect3D3(iface);
4662 TRACE("iface %p.\n", iface);
4664 return d3d7_EvictManagedTextures(&ddraw->IDirect3D7_iface);
4667 /*****************************************************************************
4668 * IDirectDraw7 VTable
4669 *****************************************************************************/
4670 static const struct IDirectDraw7Vtbl ddraw7_vtbl =
4672 /* IUnknown */
4673 ddraw7_QueryInterface,
4674 ddraw7_AddRef,
4675 ddraw7_Release,
4676 /* IDirectDraw */
4677 ddraw7_Compact,
4678 ddraw7_CreateClipper,
4679 ddraw7_CreatePalette,
4680 ddraw7_CreateSurface,
4681 ddraw7_DuplicateSurface,
4682 ddraw7_EnumDisplayModes,
4683 ddraw7_EnumSurfaces,
4684 ddraw7_FlipToGDISurface,
4685 ddraw7_GetCaps,
4686 ddraw7_GetDisplayMode,
4687 ddraw7_GetFourCCCodes,
4688 ddraw7_GetGDISurface,
4689 ddraw7_GetMonitorFrequency,
4690 ddraw7_GetScanLine,
4691 ddraw7_GetVerticalBlankStatus,
4692 ddraw7_Initialize,
4693 ddraw7_RestoreDisplayMode,
4694 ddraw7_SetCooperativeLevel,
4695 ddraw7_SetDisplayMode,
4696 ddraw7_WaitForVerticalBlank,
4697 /* IDirectDraw2 */
4698 ddraw7_GetAvailableVidMem,
4699 /* IDirectDraw3 */
4700 ddraw7_GetSurfaceFromDC,
4701 /* IDirectDraw4 */
4702 ddraw7_RestoreAllSurfaces,
4703 ddraw7_TestCooperativeLevel,
4704 ddraw7_GetDeviceIdentifier,
4705 /* IDirectDraw7 */
4706 ddraw7_StartModeTest,
4707 ddraw7_EvaluateMode
4710 static const struct IDirectDraw4Vtbl ddraw4_vtbl =
4712 /* IUnknown */
4713 ddraw4_QueryInterface,
4714 ddraw4_AddRef,
4715 ddraw4_Release,
4716 /* IDirectDraw */
4717 ddraw4_Compact,
4718 ddraw4_CreateClipper,
4719 ddraw4_CreatePalette,
4720 ddraw4_CreateSurface,
4721 ddraw4_DuplicateSurface,
4722 ddraw4_EnumDisplayModes,
4723 ddraw4_EnumSurfaces,
4724 ddraw4_FlipToGDISurface,
4725 ddraw4_GetCaps,
4726 ddraw4_GetDisplayMode,
4727 ddraw4_GetFourCCCodes,
4728 ddraw4_GetGDISurface,
4729 ddraw4_GetMonitorFrequency,
4730 ddraw4_GetScanLine,
4731 ddraw4_GetVerticalBlankStatus,
4732 ddraw4_Initialize,
4733 ddraw4_RestoreDisplayMode,
4734 ddraw4_SetCooperativeLevel,
4735 ddraw4_SetDisplayMode,
4736 ddraw4_WaitForVerticalBlank,
4737 /* IDirectDraw2 */
4738 ddraw4_GetAvailableVidMem,
4739 /* IDirectDraw3 */
4740 ddraw4_GetSurfaceFromDC,
4741 /* IDirectDraw4 */
4742 ddraw4_RestoreAllSurfaces,
4743 ddraw4_TestCooperativeLevel,
4744 ddraw4_GetDeviceIdentifier,
4747 static const struct IDirectDraw2Vtbl ddraw2_vtbl =
4749 /* IUnknown */
4750 ddraw2_QueryInterface,
4751 ddraw2_AddRef,
4752 ddraw2_Release,
4753 /* IDirectDraw */
4754 ddraw2_Compact,
4755 ddraw2_CreateClipper,
4756 ddraw2_CreatePalette,
4757 ddraw2_CreateSurface,
4758 ddraw2_DuplicateSurface,
4759 ddraw2_EnumDisplayModes,
4760 ddraw2_EnumSurfaces,
4761 ddraw2_FlipToGDISurface,
4762 ddraw2_GetCaps,
4763 ddraw2_GetDisplayMode,
4764 ddraw2_GetFourCCCodes,
4765 ddraw2_GetGDISurface,
4766 ddraw2_GetMonitorFrequency,
4767 ddraw2_GetScanLine,
4768 ddraw2_GetVerticalBlankStatus,
4769 ddraw2_Initialize,
4770 ddraw2_RestoreDisplayMode,
4771 ddraw2_SetCooperativeLevel,
4772 ddraw2_SetDisplayMode,
4773 ddraw2_WaitForVerticalBlank,
4774 /* IDirectDraw2 */
4775 ddraw2_GetAvailableVidMem,
4778 /* Bad Mojo Redux expects this vtbl to be writable. */
4779 static struct IDirectDrawVtbl ddraw1_vtbl =
4781 /* IUnknown */
4782 ddraw1_QueryInterface,
4783 ddraw1_AddRef,
4784 ddraw1_Release,
4785 /* IDirectDraw */
4786 ddraw1_Compact,
4787 ddraw1_CreateClipper,
4788 ddraw1_CreatePalette,
4789 ddraw1_CreateSurface,
4790 ddraw1_DuplicateSurface,
4791 ddraw1_EnumDisplayModes,
4792 ddraw1_EnumSurfaces,
4793 ddraw1_FlipToGDISurface,
4794 ddraw1_GetCaps,
4795 ddraw1_GetDisplayMode,
4796 ddraw1_GetFourCCCodes,
4797 ddraw1_GetGDISurface,
4798 ddraw1_GetMonitorFrequency,
4799 ddraw1_GetScanLine,
4800 ddraw1_GetVerticalBlankStatus,
4801 ddraw1_Initialize,
4802 ddraw1_RestoreDisplayMode,
4803 ddraw1_SetCooperativeLevel,
4804 ddraw1_SetDisplayMode,
4805 ddraw1_WaitForVerticalBlank,
4808 static const struct IDirect3D7Vtbl d3d7_vtbl =
4810 /* IUnknown methods */
4811 d3d7_QueryInterface,
4812 d3d7_AddRef,
4813 d3d7_Release,
4814 /* IDirect3D7 methods */
4815 d3d7_EnumDevices,
4816 d3d7_CreateDevice,
4817 d3d7_CreateVertexBuffer,
4818 d3d7_EnumZBufferFormats,
4819 d3d7_EvictManagedTextures
4822 static const struct IDirect3D3Vtbl d3d3_vtbl =
4824 /* IUnknown methods */
4825 d3d3_QueryInterface,
4826 d3d3_AddRef,
4827 d3d3_Release,
4828 /* IDirect3D3 methods */
4829 d3d3_EnumDevices,
4830 d3d3_CreateLight,
4831 d3d3_CreateMaterial,
4832 d3d3_CreateViewport,
4833 d3d3_FindDevice,
4834 d3d3_CreateDevice,
4835 d3d3_CreateVertexBuffer,
4836 d3d3_EnumZBufferFormats,
4837 d3d3_EvictManagedTextures
4840 static const struct IDirect3D2Vtbl d3d2_vtbl =
4842 /* IUnknown methods */
4843 d3d2_QueryInterface,
4844 d3d2_AddRef,
4845 d3d2_Release,
4846 /* IDirect3D2 methods */
4847 d3d2_EnumDevices,
4848 d3d2_CreateLight,
4849 d3d2_CreateMaterial,
4850 d3d2_CreateViewport,
4851 d3d2_FindDevice,
4852 d3d2_CreateDevice
4855 static const struct IDirect3DVtbl d3d1_vtbl =
4857 /* IUnknown methods */
4858 d3d1_QueryInterface,
4859 d3d1_AddRef,
4860 d3d1_Release,
4861 /* IDirect3D methods */
4862 d3d1_Initialize,
4863 d3d1_EnumDevices,
4864 d3d1_CreateLight,
4865 d3d1_CreateMaterial,
4866 d3d1_CreateViewport,
4867 d3d1_FindDevice
4870 /*****************************************************************************
4871 * ddraw_find_decl
4873 * Finds the WineD3D vertex declaration for a specific fvf, and creates one
4874 * if none was found.
4876 * This function is in ddraw.c and the DDraw object space because D3D7
4877 * vertex buffers are created using the IDirect3D interface to the ddraw
4878 * object, so they can be valid across D3D devices(theoretically. The ddraw
4879 * object also owns the wined3d device
4881 * Parameters:
4882 * This: Device
4883 * fvf: Fvf to find the decl for
4885 * Returns:
4886 * NULL in case of an error, the vertex declaration for the FVF otherwise.
4888 *****************************************************************************/
4889 struct wined3d_vertex_declaration *ddraw_find_decl(struct ddraw *This, DWORD fvf)
4891 struct wined3d_vertex_declaration *pDecl = NULL;
4892 HRESULT hr;
4893 int p, low, high; /* deliberately signed */
4894 struct FvfToDecl *convertedDecls = This->decls;
4896 TRACE("Searching for declaration for fvf %08lx... ", fvf);
4898 low = 0;
4899 high = This->numConvertedDecls - 1;
4900 while(low <= high) {
4901 p = (low + high) >> 1;
4902 TRACE("%d ", p);
4903 if(convertedDecls[p].fvf == fvf) {
4904 TRACE("found %p\n", convertedDecls[p].decl);
4905 return convertedDecls[p].decl;
4906 } else if(convertedDecls[p].fvf < fvf) {
4907 low = p + 1;
4908 } else {
4909 high = p - 1;
4912 TRACE("not found. Creating and inserting at position %d.\n", low);
4914 hr = wined3d_vertex_declaration_create_from_fvf(This->wined3d_device,
4915 fvf, This, &ddraw_null_wined3d_parent_ops, &pDecl);
4916 if (hr != S_OK) return NULL;
4918 if (This->declArraySize == This->numConvertedDecls)
4920 unsigned int grow = max(This->declArraySize / 2, 8);
4922 if (!(convertedDecls = realloc(convertedDecls,
4923 (This->numConvertedDecls + grow) * sizeof(*convertedDecls))))
4925 wined3d_vertex_declaration_decref(pDecl);
4926 return NULL;
4928 This->decls = convertedDecls;
4929 This->declArraySize += grow;
4932 memmove(convertedDecls + low + 1, convertedDecls + low, sizeof(convertedDecls[0]) * (This->numConvertedDecls - low));
4933 convertedDecls[low].decl = pDecl;
4934 convertedDecls[low].fvf = fvf;
4935 This->numConvertedDecls++;
4937 TRACE("Returning %p. %d decls in array\n", pDecl, This->numConvertedDecls);
4938 return pDecl;
4941 static inline struct ddraw *ddraw_from_device_parent(struct wined3d_device_parent *device_parent)
4943 return CONTAINING_RECORD(device_parent, struct ddraw, device_parent);
4946 static void CDECL device_parent_wined3d_device_created(struct wined3d_device_parent *device_parent,
4947 struct wined3d_device *device)
4949 TRACE("device_parent %p, device %p.\n", device_parent, device);
4952 /* This is run from device_process_message() in wined3d, we can't take the
4953 * wined3d mutex. */
4954 /* FIXME: We only get mode change notifications in exclusive mode, but we
4955 * should mark surfaces as lost on mode changes in DDSCL_NORMAL mode as well. */
4956 static void CDECL device_parent_mode_changed(struct wined3d_device_parent *device_parent)
4958 struct ddraw *ddraw = ddraw_from_device_parent(device_parent);
4959 struct wined3d_output_desc output_desc;
4960 RECT *r;
4962 TRACE("device_parent %p.\n", device_parent);
4964 if (!(ddraw->cooperative_level & DDSCL_EXCLUSIVE) || !ddraw->swapchain_window)
4966 TRACE("Nothing to resize.\n");
4967 return;
4970 if (FAILED(wined3d_output_get_desc(ddraw->wined3d_output, &output_desc)))
4972 ERR("Failed to get output description.\n");
4973 return;
4976 r = &output_desc.desktop_rect;
4977 TRACE("Resizing window %p to %s.\n", ddraw->swapchain_window, wine_dbgstr_rect(r));
4979 if (!SetWindowPos(ddraw->swapchain_window, HWND_TOP, r->left, r->top,
4980 r->right - r->left, r->bottom - r->top, SWP_SHOWWINDOW | SWP_NOACTIVATE))
4981 ERR("Failed to resize window.\n");
4983 InterlockedCompareExchange(&ddraw->device_state, DDRAW_DEVICE_STATE_NOT_RESTORED, DDRAW_DEVICE_STATE_OK);
4986 static void CDECL device_parent_activate(struct wined3d_device_parent *device_parent, BOOL activate)
4988 struct ddraw *ddraw = ddraw_from_device_parent(device_parent);
4990 TRACE("device_parent %p, activate %#x.\n", device_parent, activate);
4992 if (!activate)
4994 ddraw->device_state = DDRAW_DEVICE_STATE_LOST;
4995 exclusive_window = NULL;
4997 else
4999 InterlockedCompareExchange(&ddraw->device_state, DDRAW_DEVICE_STATE_NOT_RESTORED, DDRAW_DEVICE_STATE_LOST);
5003 void ddraw_update_lost_surfaces(struct ddraw *ddraw)
5005 struct ddraw_surface *surface;
5007 /* Railroad Tycoon 2 tries to restore surfaces from within a
5008 * WM_QUERYNEWPALETTE message handler and expects it to succeed. We
5009 * haven't received the WM_ACTIVATEAPP message by that point, so the
5010 * device state is still DDRAW_DEVICE_STATE_LOST, even though we are in
5011 * the foreground. */
5012 if (ddraw->device_state == DDRAW_DEVICE_STATE_LOST)
5014 HWND window = ddraw->focuswindow ? ddraw->focuswindow : ddraw->dest_window;
5016 if (window && GetForegroundWindow() == window)
5017 ddraw->device_state = DDRAW_DEVICE_STATE_NOT_RESTORED;
5020 if (ddraw->device_state != DDRAW_DEVICE_STATE_NOT_RESTORED)
5021 return;
5023 LIST_FOR_EACH_ENTRY(surface, &ddraw->surface_list, struct ddraw_surface, surface_list_entry)
5025 surface->is_lost = ddraw_surface_can_be_lost(surface);
5027 ddraw->device_state = DDRAW_DEVICE_STATE_OK;
5030 static HRESULT CDECL device_parent_texture_sub_resource_created(struct wined3d_device_parent *device_parent,
5031 enum wined3d_resource_type type, struct wined3d_texture *wined3d_texture, unsigned int sub_resource_idx,
5032 void **parent, const struct wined3d_parent_ops **parent_ops)
5034 TRACE("device_parent %p, type %#x, wined3d_texture %p, sub_resource_idx %u, parent %p, parent_ops %p.\n",
5035 device_parent, type, wined3d_texture, sub_resource_idx, parent, parent_ops);
5037 *parent = NULL;
5038 *parent_ops = &ddraw_null_wined3d_parent_ops;
5040 return DD_OK;
5043 static const struct wined3d_device_parent_ops ddraw_wined3d_device_parent_ops =
5045 device_parent_wined3d_device_created,
5046 device_parent_mode_changed,
5047 device_parent_activate,
5048 device_parent_texture_sub_resource_created,
5051 HRESULT ddraw_init(struct ddraw *ddraw, DWORD flags, enum wined3d_device_type device_type)
5053 struct wined3d_caps caps;
5054 HRESULT hr;
5056 static const enum wined3d_feature_level feature_levels[] =
5058 WINED3D_FEATURE_LEVEL_7,
5059 WINED3D_FEATURE_LEVEL_6,
5060 WINED3D_FEATURE_LEVEL_5,
5063 ddraw->IDirectDraw7_iface.lpVtbl = &ddraw7_vtbl;
5064 ddraw->IDirectDraw_iface.lpVtbl = &ddraw1_vtbl;
5065 ddraw->IDirectDraw2_iface.lpVtbl = &ddraw2_vtbl;
5066 ddraw->IDirectDraw4_iface.lpVtbl = &ddraw4_vtbl;
5067 ddraw->IDirect3D_iface.lpVtbl = &d3d1_vtbl;
5068 ddraw->IDirect3D2_iface.lpVtbl = &d3d2_vtbl;
5069 ddraw->IDirect3D3_iface.lpVtbl = &d3d3_vtbl;
5070 ddraw->IDirect3D7_iface.lpVtbl = &d3d7_vtbl;
5071 ddraw->device_parent.ops = &ddraw_wined3d_device_parent_ops;
5072 ddraw->state_parent.ops = &ddraw_swapchain_state_parent_ops;
5073 ddraw->numIfaces = 1;
5074 ddraw->ref7 = 1;
5076 flags |= DDRAW_WINED3D_FLAGS;
5077 if (!(ddraw->wined3d = wined3d_create(flags)))
5079 flags |= WINED3D_NO3D;
5080 if (!(ddraw->wined3d = wined3d_create(flags)))
5082 WARN("Failed to create a wined3d object.\n");
5083 return E_FAIL;
5087 if (!(ddraw->wined3d_adapter = wined3d_get_adapter(ddraw->wined3d, WINED3DADAPTER_DEFAULT)))
5089 WARN("Failed to get the default wined3d adapter.\n");
5090 wined3d_decref(ddraw->wined3d);
5091 return E_FAIL;
5094 if (!(ddraw->wined3d_output = wined3d_adapter_get_output(ddraw->wined3d_adapter, 0)))
5096 WARN("Failed to get the default wined3d output.\n");
5097 wined3d_decref(ddraw->wined3d);
5098 return E_FAIL;
5101 if (FAILED(hr = wined3d_get_device_caps(ddraw->wined3d_adapter, device_type, &caps)))
5103 ERR("Failed to get device caps, hr %#lx.\n", hr);
5104 wined3d_decref(ddraw->wined3d);
5105 return E_FAIL;
5108 if (!(caps.ddraw_caps.caps & WINEDDCAPS_3D))
5110 WARN("Created a wined3d object without 3D support.\n");
5111 ddraw->flags |= DDRAW_NO3D;
5114 if (FAILED(hr = wined3d_device_create(ddraw->wined3d, ddraw->wined3d_adapter, device_type,
5115 NULL, 0, DDRAW_STRIDE_ALIGNMENT, feature_levels, ARRAY_SIZE(feature_levels),
5116 &ddraw->device_parent, &ddraw->wined3d_device)))
5118 WARN("Failed to create a wined3d device, hr %#lx.\n", hr);
5119 wined3d_decref(ddraw->wined3d);
5120 return hr;
5122 ddraw->immediate_context = wined3d_device_get_immediate_context(ddraw->wined3d_device);
5124 list_init(&ddraw->surface_list);
5125 list_init(&ddraw->d3ddevice_list);
5126 return DD_OK;