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
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License as published by the Free Software Foundation; either
11 * version 2.1 of the License, or (at your option) any later version.
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with this library; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
24 #include "wine/port.h"
26 #include "ddraw_private.h"
28 WINE_DEFAULT_DEBUG_CHANNEL(ddraw);
30 /* Device identifier. Don't relay it to WineD3D */
31 static const DDDEVICEIDENTIFIER2 deviceidentifier =
35 { { 0x00010001, 0x00010001 } },
37 /* a8373c10-7ac4-4deb-849a-009844d08b2d */
38 {0xa8373c10,0x7ac4,0x4deb, {0x84,0x9a,0x00,0x98,0x44,0xd0,0x8b,0x2d}},
42 static void STDMETHODCALLTYPE ddraw_null_wined3d_object_destroyed(void *parent) {}
44 const struct wined3d_parent_ops ddraw_null_wined3d_parent_ops =
46 ddraw_null_wined3d_object_destroyed,
49 static inline IDirectDrawImpl *impl_from_IDirectDraw(IDirectDraw *iface)
51 return CONTAINING_RECORD(iface, IDirectDrawImpl, IDirectDraw_iface);
54 static inline IDirectDrawImpl *impl_from_IDirectDraw2(IDirectDraw2 *iface)
56 return CONTAINING_RECORD(iface, IDirectDrawImpl, IDirectDraw2_iface);
59 static inline IDirectDrawImpl *impl_from_IDirectDraw3(IDirectDraw3 *iface)
61 return CONTAINING_RECORD(iface, IDirectDrawImpl, IDirectDraw3_iface);
64 static inline IDirectDrawImpl *impl_from_IDirectDraw4(IDirectDraw4 *iface)
66 return CONTAINING_RECORD(iface, IDirectDrawImpl, IDirectDraw4_iface);
69 static inline IDirectDrawImpl *impl_from_IDirectDraw7(IDirectDraw7 *iface)
71 return CONTAINING_RECORD(iface, IDirectDrawImpl, IDirectDraw7_iface);
74 static inline IDirectDrawImpl *impl_from_IDirect3D(IDirect3D *iface)
76 return CONTAINING_RECORD(iface, IDirectDrawImpl, IDirect3D_iface);
79 static inline IDirectDrawImpl *impl_from_IDirect3D2(IDirect3D2 *iface)
81 return CONTAINING_RECORD(iface, IDirectDrawImpl, IDirect3D2_iface);
84 static inline IDirectDrawImpl *impl_from_IDirect3D3(IDirect3D3 *iface)
86 return CONTAINING_RECORD(iface, IDirectDrawImpl, IDirect3D3_iface);
89 static inline IDirectDrawImpl *impl_from_IDirect3D7(IDirect3D7 *iface)
91 return CONTAINING_RECORD(iface, IDirectDrawImpl, IDirect3D7_iface);
94 /*****************************************************************************
96 *****************************************************************************/
98 /*****************************************************************************
99 * IDirectDraw7::QueryInterface
101 * Queries different interfaces of the DirectDraw object. It can return
102 * IDirectDraw interfaces in version 1, 2, 4 and 7, and IDirect3D interfaces
103 * in version 1, 2, 3 and 7. An IDirect3DDevice can be created with this
105 * The returned interface is AddRef()-ed before it's returned
107 * Used for version 1, 2, 4 and 7
110 * refiid: Interface ID asked for
111 * obj: Used to return the interface pointer
114 * S_OK if an interface was found
115 * E_NOINTERFACE if the requested interface wasn't found
117 *****************************************************************************/
118 static HRESULT WINAPI ddraw7_QueryInterface(IDirectDraw7 *iface, REFIID refiid, void **obj)
120 IDirectDrawImpl *This = impl_from_IDirectDraw7(iface);
122 TRACE("iface %p, riid %s, object %p.\n", iface, debugstr_guid(refiid), obj);
124 /* Can change surface impl type */
125 EnterCriticalSection(&ddraw_cs);
127 /* According to COM docs, if the QueryInterface fails, obj should be set to NULL */
132 LeaveCriticalSection(&ddraw_cs);
133 return DDERR_INVALIDPARAMS;
136 /* Check DirectDraw Interfaces */
137 if ( IsEqualGUID( &IID_IUnknown, refiid ) ||
138 IsEqualGUID( &IID_IDirectDraw7, refiid ) )
141 TRACE("(%p) Returning IDirectDraw7 interface at %p\n", This, *obj);
143 else if ( IsEqualGUID( &IID_IDirectDraw4, refiid ) )
145 *obj = &This->IDirectDraw4_iface;
146 TRACE("(%p) Returning IDirectDraw4 interface at %p\n", This, *obj);
148 else if ( IsEqualGUID( &IID_IDirectDraw3, refiid ) )
150 /* This Interface exists in ddrawex.dll, it is implemented in a wrapper */
151 WARN("IDirectDraw3 is not valid in ddraw.dll\n");
153 LeaveCriticalSection(&ddraw_cs);
154 return E_NOINTERFACE;
156 else if ( IsEqualGUID( &IID_IDirectDraw2, refiid ) )
158 *obj = &This->IDirectDraw2_iface;
159 TRACE("(%p) Returning IDirectDraw2 interface at %p\n", This, *obj);
161 else if ( IsEqualGUID( &IID_IDirectDraw, refiid ) )
163 *obj = &This->IDirectDraw_iface;
164 TRACE("(%p) Returning IDirectDraw interface at %p\n", This, *obj);
168 * The refcount unit test revealed that an IDirect3D7 interface can only be queried
169 * from a DirectDraw object that was created as an IDirectDraw7 interface. No idea
170 * who had this idea and why. The older interfaces can query and IDirect3D version
171 * because they are all created as IDirectDraw(1). This isn't really crucial behavior,
172 * and messy to implement with the common creation function, so it has been left out here.
174 else if ( IsEqualGUID( &IID_IDirect3D , refiid ) ||
175 IsEqualGUID( &IID_IDirect3D2 , refiid ) ||
176 IsEqualGUID( &IID_IDirect3D3 , refiid ) ||
177 IsEqualGUID( &IID_IDirect3D7 , refiid ) )
179 /* Check the surface implementation */
180 if(This->ImplType == SURFACE_UNKNOWN)
182 /* Apps may create the IDirect3D Interface before the primary surface.
183 * set the surface implementation */
184 This->ImplType = SURFACE_OPENGL;
185 TRACE("(%p) Choosing OpenGL surfaces because a Direct3D interface was requested\n", This);
187 else if(This->ImplType != SURFACE_OPENGL && DefaultSurfaceType == SURFACE_UNKNOWN)
189 ERR("(%p) The App is requesting a D3D device, but a non-OpenGL surface type was choosen. Prepare for trouble!\n", This);
190 ERR(" (%p) You may want to contact wine-devel for help\n", This);
191 /* Should I assert(0) here??? */
193 else if(This->ImplType != SURFACE_OPENGL)
195 WARN("The app requests a Direct3D interface, but non-opengl surfaces where set in winecfg\n");
196 /* Do not abort here, only reject 3D Device creation */
199 if ( IsEqualGUID( &IID_IDirect3D , refiid ) )
201 This->d3dversion = 1;
202 *obj = &This->IDirect3D_iface;
203 TRACE(" returning Direct3D interface at %p.\n", *obj);
205 else if ( IsEqualGUID( &IID_IDirect3D2 , refiid ) )
207 This->d3dversion = 2;
208 *obj = &This->IDirect3D2_iface;
209 TRACE(" returning Direct3D2 interface at %p.\n", *obj);
211 else if ( IsEqualGUID( &IID_IDirect3D3 , refiid ) )
213 This->d3dversion = 3;
214 *obj = &This->IDirect3D3_iface;
215 TRACE(" returning Direct3D3 interface at %p.\n", *obj);
217 else if(IsEqualGUID( &IID_IDirect3D7 , refiid ))
219 This->d3dversion = 7;
220 *obj = &This->IDirect3D7_iface;
221 TRACE(" returning Direct3D7 interface at %p.\n", *obj);
224 else if (IsEqualGUID(refiid, &IID_IWineD3DDeviceParent))
226 *obj = &This->device_parent_vtbl;
229 /* Unknown interface */
232 ERR("(%p)->(%s, %p): No interface found\n", This, debugstr_guid(refiid), obj);
233 LeaveCriticalSection(&ddraw_cs);
234 return E_NOINTERFACE;
237 IUnknown_AddRef( (IUnknown *) *obj );
238 LeaveCriticalSection(&ddraw_cs);
242 static HRESULT WINAPI ddraw4_QueryInterface(IDirectDraw4 *iface, REFIID riid, void **object)
244 IDirectDrawImpl *This = impl_from_IDirectDraw4(iface);
246 TRACE("iface %p, riid %s, object %p.\n", iface, debugstr_guid(riid), object);
248 return ddraw7_QueryInterface(&This->IDirectDraw7_iface, riid, object);
251 static HRESULT WINAPI ddraw3_QueryInterface(IDirectDraw3 *iface, REFIID riid, void **object)
253 IDirectDrawImpl *This = impl_from_IDirectDraw3(iface);
255 TRACE("iface %p, riid %s, object %p.\n", iface, debugstr_guid(riid), object);
257 return ddraw7_QueryInterface(&This->IDirectDraw7_iface, riid, object);
260 static HRESULT WINAPI ddraw2_QueryInterface(IDirectDraw2 *iface, REFIID riid, void **object)
262 IDirectDrawImpl *This = impl_from_IDirectDraw2(iface);
264 TRACE("iface %p, riid %s, object %p.\n", iface, debugstr_guid(riid), object);
266 return ddraw7_QueryInterface(&This->IDirectDraw7_iface, riid, object);
269 static HRESULT WINAPI ddraw1_QueryInterface(IDirectDraw *iface, REFIID riid, void **object)
271 IDirectDrawImpl *This = impl_from_IDirectDraw(iface);
273 TRACE("iface %p, riid %s, object %p.\n", iface, debugstr_guid(riid), object);
275 return ddraw7_QueryInterface(&This->IDirectDraw7_iface, riid, object);
278 static HRESULT WINAPI d3d7_QueryInterface(IDirect3D7 *iface, REFIID riid, void **object)
280 IDirectDrawImpl *This = impl_from_IDirect3D7(iface);
282 TRACE("iface %p, riid %s, object %p.\n", iface, debugstr_guid(riid), object);
284 return ddraw7_QueryInterface(&This->IDirectDraw7_iface, riid, object);
287 static HRESULT WINAPI d3d3_QueryInterface(IDirect3D3 *iface, REFIID riid, void **object)
289 IDirectDrawImpl *This = impl_from_IDirect3D3(iface);
291 TRACE("iface %p, riid %s, object %p.\n", iface, debugstr_guid(riid), object);
293 return ddraw7_QueryInterface(&This->IDirectDraw7_iface, riid, object);
296 static HRESULT WINAPI d3d2_QueryInterface(IDirect3D2 *iface, REFIID riid, void **object)
298 IDirectDrawImpl *This = impl_from_IDirect3D2(iface);
300 TRACE("iface %p, riid %s, object %p.\n", iface, debugstr_guid(riid), object);
302 return ddraw7_QueryInterface(&This->IDirectDraw7_iface, riid, object);
305 static HRESULT WINAPI d3d1_QueryInterface(IDirect3D *iface, REFIID riid, void **object)
307 IDirectDrawImpl *This = impl_from_IDirect3D(iface);
309 TRACE("iface %p, riid %s, object %p.\n", iface, debugstr_guid(riid), object);
311 return ddraw7_QueryInterface(&This->IDirectDraw7_iface, riid, object);
314 /*****************************************************************************
315 * IDirectDraw7::AddRef
317 * Increases the interfaces refcount, basically
319 * DDraw refcounting is a bit tricky. The different DirectDraw interface
320 * versions have individual refcounts, but the IDirect3D interfaces do not.
321 * All interfaces are from one object, that means calling QueryInterface on an
322 * IDirectDraw7 interface for an IDirectDraw4 interface does not create a new
323 * IDirectDrawImpl object.
325 * That means all AddRef and Release implementations of IDirectDrawX work
326 * with their own counter, and IDirect3DX::AddRef thunk to IDirectDraw (1),
327 * except of IDirect3D7 which thunks to IDirectDraw7
329 * Returns: The new refcount
331 *****************************************************************************/
332 static ULONG WINAPI ddraw7_AddRef(IDirectDraw7 *iface)
334 IDirectDrawImpl *This = impl_from_IDirectDraw7(iface);
335 ULONG ref = InterlockedIncrement(&This->ref7);
337 TRACE("%p increasing refcount to %u.\n", This, ref);
339 if(ref == 1) InterlockedIncrement(&This->numIfaces);
344 static ULONG WINAPI ddraw4_AddRef(IDirectDraw4 *iface)
346 IDirectDrawImpl *This = impl_from_IDirectDraw4(iface);
347 ULONG ref = InterlockedIncrement(&This->ref4);
349 TRACE("%p increasing refcount to %u.\n", This, ref);
351 if (ref == 1) InterlockedIncrement(&This->numIfaces);
356 static ULONG WINAPI ddraw3_AddRef(IDirectDraw3 *iface)
358 IDirectDrawImpl *This = impl_from_IDirectDraw3(iface);
359 ULONG ref = InterlockedIncrement(&This->ref3);
361 TRACE("%p increasing refcount to %u.\n", This, ref);
363 if (ref == 1) InterlockedIncrement(&This->numIfaces);
368 static ULONG WINAPI ddraw2_AddRef(IDirectDraw2 *iface)
370 IDirectDrawImpl *This = impl_from_IDirectDraw2(iface);
371 ULONG ref = InterlockedIncrement(&This->ref2);
373 TRACE("%p increasing refcount to %u.\n", This, ref);
375 if (ref == 1) InterlockedIncrement(&This->numIfaces);
380 static ULONG WINAPI ddraw1_AddRef(IDirectDraw *iface)
382 IDirectDrawImpl *This = impl_from_IDirectDraw(iface);
383 ULONG ref = InterlockedIncrement(&This->ref1);
385 TRACE("%p increasing refcount to %u.\n", This, ref);
387 if (ref == 1) InterlockedIncrement(&This->numIfaces);
392 static ULONG WINAPI d3d7_AddRef(IDirect3D7 *iface)
394 IDirectDrawImpl *This = impl_from_IDirect3D7(iface);
396 TRACE("iface %p.\n", iface);
398 return ddraw7_AddRef(&This->IDirectDraw7_iface);
401 static ULONG WINAPI d3d3_AddRef(IDirect3D3 *iface)
403 IDirectDrawImpl *This = impl_from_IDirect3D3(iface);
405 TRACE("iface %p.\n", iface);
407 return ddraw1_AddRef(&This->IDirectDraw_iface);
410 static ULONG WINAPI d3d2_AddRef(IDirect3D2 *iface)
412 IDirectDrawImpl *This = impl_from_IDirect3D2(iface);
414 TRACE("iface %p.\n", iface);
416 return ddraw1_AddRef(&This->IDirectDraw_iface);
419 static ULONG WINAPI d3d1_AddRef(IDirect3D *iface)
421 IDirectDrawImpl *This = impl_from_IDirect3D(iface);
423 TRACE("iface %p.\n", iface);
425 return ddraw1_AddRef(&This->IDirectDraw_iface);
428 /*****************************************************************************
431 * Destroys a ddraw object if all refcounts are 0. This is to share code
432 * between the IDirectDrawX::Release functions
435 * This: DirectDraw object to destroy
437 *****************************************************************************/
438 static void ddraw_destroy(IDirectDrawImpl *This)
440 IDirectDraw7_SetCooperativeLevel(&This->IDirectDraw7_iface, NULL, DDSCL_NORMAL);
441 IDirectDraw7_RestoreDisplayMode(&This->IDirectDraw7_iface);
443 /* Destroy the device window if we created one */
444 if(This->devicewindow != 0)
446 TRACE(" (%p) Destroying the device window %p\n", This, This->devicewindow);
447 DestroyWindow(This->devicewindow);
448 This->devicewindow = 0;
451 EnterCriticalSection(&ddraw_cs);
452 list_remove(&This->ddraw_list_entry);
453 LeaveCriticalSection(&ddraw_cs);
455 /* Release the attached WineD3D stuff */
456 IWineD3DDevice_Release(This->wineD3DDevice);
457 wined3d_decref(This->wineD3D);
459 /* Now free the object */
460 HeapFree(GetProcessHeap(), 0, This);
463 /*****************************************************************************
464 * IDirectDraw7::Release
466 * Decreases the refcount. If the refcount falls to 0, the object is destroyed
468 * Returns: The new refcount
469 *****************************************************************************/
470 static ULONG WINAPI ddraw7_Release(IDirectDraw7 *iface)
472 IDirectDrawImpl *This = impl_from_IDirectDraw7(iface);
473 ULONG ref = InterlockedDecrement(&This->ref7);
475 TRACE("%p decreasing refcount to %u.\n", This, ref);
477 if (!ref && !InterlockedDecrement(&This->numIfaces))
483 static ULONG WINAPI ddraw4_Release(IDirectDraw4 *iface)
485 IDirectDrawImpl *This = impl_from_IDirectDraw4(iface);
486 ULONG ref = InterlockedDecrement(&This->ref4);
488 TRACE("%p decreasing refcount to %u.\n", This, ref);
490 if (!ref && !InterlockedDecrement(&This->numIfaces))
496 static ULONG WINAPI ddraw3_Release(IDirectDraw3 *iface)
498 IDirectDrawImpl *This = impl_from_IDirectDraw3(iface);
499 ULONG ref = InterlockedDecrement(&This->ref3);
501 TRACE("%p decreasing refcount to %u.\n", This, ref);
503 if (!ref && !InterlockedDecrement(&This->numIfaces))
509 static ULONG WINAPI ddraw2_Release(IDirectDraw2 *iface)
511 IDirectDrawImpl *This = impl_from_IDirectDraw2(iface);
512 ULONG ref = InterlockedDecrement(&This->ref2);
514 TRACE("%p decreasing refcount to %u.\n", This, ref);
516 if (!ref && !InterlockedDecrement(&This->numIfaces))
522 static ULONG WINAPI ddraw1_Release(IDirectDraw *iface)
524 IDirectDrawImpl *This = impl_from_IDirectDraw(iface);
525 ULONG ref = InterlockedDecrement(&This->ref1);
527 TRACE("%p decreasing refcount to %u.\n", This, ref);
529 if (!ref && !InterlockedDecrement(&This->numIfaces))
535 static ULONG WINAPI d3d7_Release(IDirect3D7 *iface)
537 IDirectDrawImpl *This = impl_from_IDirect3D7(iface);
539 TRACE("iface %p.\n", iface);
541 return ddraw7_Release(&This->IDirectDraw7_iface);
544 static ULONG WINAPI d3d3_Release(IDirect3D3 *iface)
546 IDirectDrawImpl *This = impl_from_IDirect3D3(iface);
548 TRACE("iface %p.\n", iface);
550 return ddraw1_Release(&This->IDirectDraw_iface);
553 static ULONG WINAPI d3d2_Release(IDirect3D2 *iface)
555 IDirectDrawImpl *This = impl_from_IDirect3D2(iface);
557 TRACE("iface %p.\n", iface);
559 return ddraw1_Release(&This->IDirectDraw_iface);
562 static ULONG WINAPI d3d1_Release(IDirect3D *iface)
564 IDirectDrawImpl *This = impl_from_IDirect3D(iface);
566 TRACE("iface %p.\n", iface);
568 return ddraw1_Release(&This->IDirectDraw_iface);
571 /*****************************************************************************
572 * IDirectDraw methods
573 *****************************************************************************/
575 /*****************************************************************************
576 * IDirectDraw7::SetCooperativeLevel
578 * Sets the cooperative level for the DirectDraw object, and the window
579 * assigned to it. The cooperative level determines the general behavior
580 * of the DirectDraw application
582 * Warning: This is quite tricky, as it's not really documented which
583 * cooperative levels can be combined with each other. If a game fails
584 * after this function, try to check the cooperative levels passed on
585 * Windows, and if it returns something different.
587 * If you think that this function caused the failure because it writes a
588 * fixme, be sure to run again with a +ddraw trace.
590 * What is known about cooperative levels (See the ddraw modes test):
591 * DDSCL_EXCLUSIVE and DDSCL_FULLSCREEN must be used with each other
592 * DDSCL_NORMAL is not compatible with DDSCL_EXCLUSIVE or DDSCL_FULLSCREEN
593 * DDSCL_SETFOCUSWINDOW can be passed only in DDSCL_NORMAL mode, but after that
594 * DDSCL_FULLSCREEN can be activated
595 * DDSCL_SETFOCUSWINDOW may only be used with DDSCL_NOWINDOWCHANGES
597 * Handled flags: DDSCL_NORMAL, DDSCL_FULLSCREEN, DDSCL_EXCLUSIVE,
598 * DDSCL_SETFOCUSWINDOW (partially),
599 * DDSCL_MULTITHREADED (work in progress)
601 * Unhandled flags, which should be implemented
602 * DDSCL_SETDEVICEWINDOW: Sets a window specially used for rendering (I don't
603 * expect any difference to a normal window for wine)
604 * DDSCL_CREATEDEVICEWINDOW: Tells ddraw to create its own window for
605 * rendering (Possible test case: Half-Life)
607 * Unsure about these: DDSCL_FPUSETUP DDSCL_FPURESERVE
609 * These don't seem very important for wine:
610 * DDSCL_ALLOWREBOOT, DDSCL_NOWINDOWCHANGES, DDSCL_ALLOWMODEX
613 * DD_OK if the cooperative level was set successfully
614 * DDERR_INVALIDPARAMS if the passed cooperative level combination is invalid
615 * DDERR_HWNDALREADYSET if DDSCL_SETFOCUSWINDOW is passed in exclusive mode
616 * (Probably others too, have to investigate)
618 *****************************************************************************/
619 static HRESULT WINAPI ddraw7_SetCooperativeLevel(IDirectDraw7 *iface, HWND hwnd, DWORD cooplevel)
621 IDirectDrawImpl *This = impl_from_IDirectDraw7(iface);
624 TRACE("iface %p, window %p, flags %#x.\n", iface, hwnd, cooplevel);
625 DDRAW_dump_cooperativelevel(cooplevel);
627 EnterCriticalSection(&ddraw_cs);
629 /* Get the old window */
630 window = This->dest_window;
632 /* Tests suggest that we need one of them: */
633 if(!(cooplevel & (DDSCL_SETFOCUSWINDOW |
637 TRACE("Incorrect cooplevel flags, returning DDERR_INVALIDPARAMS\n");
638 LeaveCriticalSection(&ddraw_cs);
639 return DDERR_INVALIDPARAMS;
642 /* Handle those levels first which set various hwnds */
643 if(cooplevel & DDSCL_SETFOCUSWINDOW)
645 /* This isn't compatible with a lot of flags */
646 if(cooplevel & ( DDSCL_MULTITHREADED |
647 DDSCL_CREATEDEVICEWINDOW |
652 DDSCL_SETDEVICEWINDOW |
657 TRACE("Called with incompatible flags, returning DDERR_INVALIDPARAMS\n");
658 LeaveCriticalSection(&ddraw_cs);
659 return DDERR_INVALIDPARAMS;
662 if( (This->cooperative_level & DDSCL_EXCLUSIVE) && window )
664 TRACE("Setting DDSCL_SETFOCUSWINDOW with an already set window, returning DDERR_HWNDALREADYSET\n");
665 LeaveCriticalSection(&ddraw_cs);
666 return DDERR_HWNDALREADYSET;
669 This->focuswindow = hwnd;
670 /* Won't use the hwnd param for anything else */
673 /* Use the focus window for drawing too */
674 This->dest_window = This->focuswindow;
676 /* Destroy the device window, if we have one */
677 if(This->devicewindow)
679 DestroyWindow(This->devicewindow);
680 This->devicewindow = NULL;
683 LeaveCriticalSection(&ddraw_cs);
687 if(cooplevel & DDSCL_EXCLUSIVE)
689 if( !(cooplevel & DDSCL_FULLSCREEN) || !hwnd )
691 TRACE("(%p) DDSCL_EXCLUSIVE needs DDSCL_FULLSCREEN and a window\n", This);
692 LeaveCriticalSection(&ddraw_cs);
693 return DDERR_INVALIDPARAMS;
696 else if( !(cooplevel & DDSCL_NORMAL) )
698 TRACE("(%p) SetCooperativeLevel needs at least SetFocusWindow or Exclusive or Normal mode\n", This);
699 LeaveCriticalSection(&ddraw_cs);
700 return DDERR_INVALIDPARAMS;
703 if ((This->cooperative_level & DDSCL_EXCLUSIVE)
704 && (hwnd != window || !(cooplevel & DDSCL_EXCLUSIVE)))
705 IWineD3DDevice_ReleaseFocusWindow(This->wineD3DDevice);
707 if ((cooplevel & DDSCL_FULLSCREEN) != (This->cooperative_level & DDSCL_FULLSCREEN) || hwnd != window)
709 if (This->cooperative_level & DDSCL_FULLSCREEN)
711 IWineD3DDevice_RestoreFullscreenWindow(This->wineD3DDevice, window);
713 if (cooplevel & DDSCL_FULLSCREEN)
715 WINED3DDISPLAYMODE display_mode;
717 wined3d_get_adapter_display_mode(This->wineD3D, WINED3DADAPTER_DEFAULT, &display_mode);
718 IWineD3DDevice_SetupFullscreenWindow(This->wineD3DDevice, hwnd, display_mode.Width, display_mode.Height);
722 if ((cooplevel & DDSCL_EXCLUSIVE)
723 && (hwnd != window || !(This->cooperative_level & DDSCL_EXCLUSIVE)))
725 HRESULT hr = IWineD3DDevice_AcquireFocusWindow(This->wineD3DDevice, hwnd);
728 ERR("Failed to acquire focus window, hr %#x.\n", hr);
729 LeaveCriticalSection(&ddraw_cs);
734 /* Don't override focus windows or private device windows */
735 if (hwnd && !This->focuswindow && !This->devicewindow && (hwnd != window))
736 This->dest_window = hwnd;
738 if(cooplevel & DDSCL_CREATEDEVICEWINDOW)
740 /* Don't create a device window if a focus window is set */
741 if( !(This->focuswindow) )
743 HWND devicewindow = CreateWindowExA(0, DDRAW_WINDOW_CLASS_NAME, "DDraw device window",
744 WS_POPUP, 0, 0, GetSystemMetrics(SM_CXSCREEN), GetSystemMetrics(SM_CYSCREEN),
745 NULL, NULL, NULL, NULL);
748 ERR("Failed to create window, last error %#x.\n", GetLastError());
749 LeaveCriticalSection(&ddraw_cs);
753 ShowWindow(devicewindow, SW_SHOW); /* Just to be sure */
754 TRACE("(%p) Created a DDraw device window. HWND=%p\n", This, devicewindow);
756 This->devicewindow = devicewindow;
757 This->dest_window = devicewindow;
761 if(cooplevel & DDSCL_MULTITHREADED && !(This->cooperative_level & DDSCL_MULTITHREADED))
763 /* Enable thread safety in wined3d */
764 IWineD3DDevice_SetMultithreaded(This->wineD3DDevice);
767 /* Unhandled flags */
768 if(cooplevel & DDSCL_ALLOWREBOOT)
769 WARN("(%p) Unhandled flag DDSCL_ALLOWREBOOT, harmless\n", This);
770 if(cooplevel & DDSCL_ALLOWMODEX)
771 WARN("(%p) Unhandled flag DDSCL_ALLOWMODEX, harmless\n", This);
772 if(cooplevel & DDSCL_FPUSETUP)
773 WARN("(%p) Unhandled flag DDSCL_FPUSETUP, harmless\n", This);
775 /* Store the cooperative_level */
776 This->cooperative_level = cooplevel;
777 TRACE("SetCooperativeLevel retuning DD_OK\n");
778 LeaveCriticalSection(&ddraw_cs);
782 static HRESULT WINAPI ddraw4_SetCooperativeLevel(IDirectDraw4 *iface, HWND window, DWORD flags)
784 IDirectDrawImpl *This = impl_from_IDirectDraw4(iface);
786 TRACE("iface %p, window %p, flags %#x.\n", iface, window, flags);
788 return ddraw7_SetCooperativeLevel(&This->IDirectDraw7_iface, window, flags);
791 static HRESULT WINAPI ddraw3_SetCooperativeLevel(IDirectDraw3 *iface, HWND window, DWORD flags)
793 IDirectDrawImpl *This = impl_from_IDirectDraw3(iface);
795 TRACE("iface %p, window %p, flags %#x.\n", iface, window, flags);
797 return ddraw7_SetCooperativeLevel(&This->IDirectDraw7_iface, window, flags);
800 static HRESULT WINAPI ddraw2_SetCooperativeLevel(IDirectDraw2 *iface, HWND window, DWORD flags)
802 IDirectDrawImpl *This = impl_from_IDirectDraw2(iface);
804 TRACE("iface %p, window %p, flags %#x.\n", iface, window, flags);
806 return ddraw7_SetCooperativeLevel(&This->IDirectDraw7_iface, window, flags);
809 static HRESULT WINAPI ddraw1_SetCooperativeLevel(IDirectDraw *iface, HWND window, DWORD flags)
811 IDirectDrawImpl *This = impl_from_IDirectDraw(iface);
813 TRACE("iface %p, window %p, flags %#x.\n", iface, window, flags);
815 return ddraw7_SetCooperativeLevel(&This->IDirectDraw7_iface, window, flags);
818 /*****************************************************************************
820 * Helper function for SetDisplayMode and RestoreDisplayMode
822 * Implements DirectDraw's SetDisplayMode, but ignores the value of
823 * ForceRefreshRate, since it is already handled by
824 * ddraw7_SetDisplayMode. RestoreDisplayMode can use this function
825 * without worrying that ForceRefreshRate will override the refresh rate. For
826 * argument and return value documentation, see
827 * ddraw7_SetDisplayMode.
829 *****************************************************************************/
830 static HRESULT ddraw_set_display_mode(IDirectDrawImpl *ddraw, DWORD Width, DWORD Height,
831 DWORD BPP, DWORD RefreshRate, DWORD Flags)
833 enum wined3d_format_id format;
834 WINED3DDISPLAYMODE Mode;
837 TRACE("ddraw %p, width %u, height %u, bpp %u, refresh_rate %u, flags %#x.\n", ddraw, Width,
838 Height, BPP, RefreshRate, Flags);
840 EnterCriticalSection(&ddraw_cs);
841 if( !Width || !Height )
843 ERR("Width %u, Height %u, what to do?\n", Width, Height);
844 /* It looks like Need for Speed Porsche Unleashed expects DD_OK here */
845 LeaveCriticalSection(&ddraw_cs);
851 case 8: format = WINED3DFMT_P8_UINT; break;
852 case 15: format = WINED3DFMT_B5G5R5X1_UNORM; break;
853 case 16: format = WINED3DFMT_B5G6R5_UNORM; break;
854 case 24: format = WINED3DFMT_B8G8R8_UNORM; break;
855 case 32: format = WINED3DFMT_B8G8R8X8_UNORM; break;
856 default: format = WINED3DFMT_UNKNOWN; break;
859 if (FAILED(hr = IWineD3DDevice_GetDisplayMode(ddraw->wineD3DDevice, 0, &Mode)))
861 ERR("Failed to get current display mode, hr %#x.\n", hr);
863 else if (Mode.Width == Width
864 && Mode.Height == Height
865 && Mode.Format == format
866 && Mode.RefreshRate == RefreshRate)
868 TRACE("Skipping redundant mode setting call.\n");
869 LeaveCriticalSection(&ddraw_cs);
873 /* Check the exclusive mode
874 if(!(ddraw->cooperative_level & DDSCL_EXCLUSIVE))
875 return DDERR_NOEXCLUSIVEMODE;
876 * This is WRONG. Don't know if the SDK is completely
877 * wrong and if there are any conditions when DDERR_NOEXCLUSIVE
878 * is returned, but Half-Life 1.1.1.1 (Steam version)
883 Mode.Height = Height;
884 Mode.RefreshRate = RefreshRate;
885 Mode.Format = format;
887 /* TODO: The possible return values from msdn suggest that
888 * the screen mode can't be changed if a surface is locked
889 * or some drawing is in progress
892 /* TODO: Lose the primary surface */
893 hr = IWineD3DDevice_SetDisplayMode(ddraw->wineD3DDevice, 0, &Mode);
894 IWineD3DDevice_RestoreFullscreenWindow(ddraw->wineD3DDevice, ddraw->dest_window);
895 IWineD3DDevice_SetupFullscreenWindow(ddraw->wineD3DDevice, ddraw->dest_window, Width, Height);
896 LeaveCriticalSection(&ddraw_cs);
899 case WINED3DERR_NOTAVAILABLE: return DDERR_UNSUPPORTED;
904 /*****************************************************************************
905 * IDirectDraw7::SetDisplayMode
907 * Sets the display screen resolution, color depth and refresh frequency
908 * when in fullscreen mode (in theory).
909 * Possible return values listed in the SDK suggest that this method fails
910 * when not in fullscreen mode, but this is wrong. Windows 2000 happily sets
911 * the display mode in DDSCL_NORMAL mode without an hwnd specified.
912 * It seems to be valid to pass 0 for With and Height, this has to be tested
913 * It could mean that the current video mode should be left as-is. (But why
917 * Height, Width: Screen dimension
918 * BPP: Color depth in Bits per pixel
919 * Refreshrate: Screen refresh rate
925 *****************************************************************************/
926 static HRESULT WINAPI ddraw7_SetDisplayMode(IDirectDraw7 *iface, DWORD Width, DWORD Height,
927 DWORD BPP, DWORD RefreshRate, DWORD Flags)
929 IDirectDrawImpl *This = impl_from_IDirectDraw7(iface);
931 TRACE("iface %p, width %u, height %u, bpp %u, refresh_rate %u, flags %#x.\n",
932 iface, Width, Height, BPP, RefreshRate, Flags);
934 if (force_refresh_rate != 0)
936 TRACE("ForceRefreshRate overriding passed-in refresh rate (%u Hz) to %u Hz\n",
937 RefreshRate, force_refresh_rate);
938 RefreshRate = force_refresh_rate;
941 return ddraw_set_display_mode(This, Width, Height, BPP, RefreshRate, Flags);
944 static HRESULT WINAPI ddraw4_SetDisplayMode(IDirectDraw4 *iface, DWORD width, DWORD height,
945 DWORD bpp, DWORD refresh_rate, DWORD flags)
947 IDirectDrawImpl *This = impl_from_IDirectDraw4(iface);
949 TRACE("iface %p, width %u, height %u, bpp %u, refresh_rate %u, flags %#x.\n",
950 iface, width, height, bpp, refresh_rate, flags);
952 return ddraw7_SetDisplayMode(&This->IDirectDraw7_iface, width, height, bpp, refresh_rate, flags);
955 static HRESULT WINAPI ddraw3_SetDisplayMode(IDirectDraw3 *iface, DWORD width, DWORD height,
956 DWORD bpp, DWORD refresh_rate, DWORD flags)
958 IDirectDrawImpl *This = impl_from_IDirectDraw3(iface);
960 TRACE("iface %p, width %u, height %u, bpp %u, refresh_rate %u, flags %#x.\n",
961 iface, width, height, bpp, refresh_rate, flags);
963 return ddraw7_SetDisplayMode(&This->IDirectDraw7_iface, width, height, bpp, refresh_rate, flags);
966 static HRESULT WINAPI ddraw2_SetDisplayMode(IDirectDraw2 *iface,
967 DWORD width, DWORD height, DWORD bpp, DWORD refresh_rate, DWORD flags)
969 IDirectDrawImpl *This = impl_from_IDirectDraw2(iface);
971 TRACE("iface %p, width %u, height %u, bpp %u, refresh_rate %u, flags %#x.\n",
972 iface, width, height, bpp, refresh_rate, flags);
974 return ddraw7_SetDisplayMode(&This->IDirectDraw7_iface, width, height, bpp, refresh_rate, flags);
977 static HRESULT WINAPI ddraw1_SetDisplayMode(IDirectDraw *iface, DWORD width, DWORD height, DWORD bpp)
979 IDirectDrawImpl *This = impl_from_IDirectDraw(iface);
981 TRACE("iface %p, width %u, height %u, bpp %u.\n", iface, width, height, bpp);
983 return ddraw7_SetDisplayMode(&This->IDirectDraw7_iface, width, height, bpp, 0, 0);
986 /*****************************************************************************
987 * IDirectDraw7::RestoreDisplayMode
989 * Restores the display mode to what it was at creation time. Basically.
991 * A problem arises when there are 2 DirectDraw objects using the same hwnd:
992 * -> DD_1 finds the screen at 1400x1050x32 when created, sets it to 640x480x16
993 * -> DD_2 is created, finds the screen at 640x480x16, sets it to 1024x768x32
994 * -> DD_1 is released. The screen should be left at 1024x768x32.
995 * -> DD_2 is released. The screen should be set to 1400x1050x32
996 * This case is unhandled right now, but Empire Earth does it this way.
997 * (But perhaps there is something in SetCooperativeLevel to prevent this)
999 * The msdn says that this method resets the display mode to what it was before
1000 * SetDisplayMode was called. What if SetDisplayModes is called 2 times??
1004 * DDERR_NOEXCLUSIVE mode if the device isn't in fullscreen mode
1006 *****************************************************************************/
1007 static HRESULT WINAPI ddraw7_RestoreDisplayMode(IDirectDraw7 *iface)
1009 IDirectDrawImpl *This = impl_from_IDirectDraw7(iface);
1011 TRACE("iface %p.\n", iface);
1013 return ddraw_set_display_mode(This, This->orig_width, This->orig_height, This->orig_bpp, 0, 0);
1016 static HRESULT WINAPI ddraw4_RestoreDisplayMode(IDirectDraw4 *iface)
1018 IDirectDrawImpl *This = impl_from_IDirectDraw4(iface);
1020 TRACE("iface %p.\n", iface);
1022 return ddraw7_RestoreDisplayMode(&This->IDirectDraw7_iface);
1025 static HRESULT WINAPI ddraw3_RestoreDisplayMode(IDirectDraw3 *iface)
1027 IDirectDrawImpl *This = impl_from_IDirectDraw3(iface);
1029 TRACE("iface %p.\n", iface);
1031 return ddraw7_RestoreDisplayMode(&This->IDirectDraw7_iface);
1034 static HRESULT WINAPI ddraw2_RestoreDisplayMode(IDirectDraw2 *iface)
1036 IDirectDrawImpl *This = impl_from_IDirectDraw2(iface);
1038 TRACE("iface %p.\n", iface);
1040 return ddraw7_RestoreDisplayMode(&This->IDirectDraw7_iface);
1043 static HRESULT WINAPI ddraw1_RestoreDisplayMode(IDirectDraw *iface)
1045 IDirectDrawImpl *This = impl_from_IDirectDraw(iface);
1047 TRACE("iface %p.\n", iface);
1049 return ddraw7_RestoreDisplayMode(&This->IDirectDraw7_iface);
1052 /*****************************************************************************
1053 * IDirectDraw7::GetCaps
1055 * Returns the drives capabilities
1057 * Used for version 1, 2, 4 and 7
1060 * DriverCaps: Structure to write the Hardware accelerated caps to
1061 * HelCaps: Structure to write the emulation caps to
1064 * This implementation returns DD_OK only
1066 *****************************************************************************/
1067 static HRESULT WINAPI ddraw7_GetCaps(IDirectDraw7 *iface, DDCAPS *DriverCaps, DDCAPS *HELCaps)
1069 IDirectDrawImpl *This = impl_from_IDirectDraw7(iface);
1071 WINED3DCAPS winecaps;
1073 DDSCAPS2 ddscaps = {0, 0, 0, 0};
1075 TRACE("iface %p, driver_caps %p, hel_caps %p.\n", iface, DriverCaps, HELCaps);
1077 /* One structure must be != NULL */
1078 if( (!DriverCaps) && (!HELCaps) )
1080 ERR("(%p) Invalid params to ddraw7_GetCaps\n", This);
1081 return DDERR_INVALIDPARAMS;
1084 memset(&caps, 0, sizeof(caps));
1085 memset(&winecaps, 0, sizeof(winecaps));
1086 caps.dwSize = sizeof(caps);
1087 EnterCriticalSection(&ddraw_cs);
1088 hr = IWineD3DDevice_GetDeviceCaps(This->wineD3DDevice, &winecaps);
1090 WARN("IWineD3DDevice::GetDeviceCaps failed\n");
1091 LeaveCriticalSection(&ddraw_cs);
1095 hr = IDirectDraw7_GetAvailableVidMem(iface, &ddscaps, &caps.dwVidMemTotal, &caps.dwVidMemFree);
1096 LeaveCriticalSection(&ddraw_cs);
1098 WARN("IDirectDraw7::GetAvailableVidMem failed\n");
1102 caps.dwCaps = winecaps.DirectDrawCaps.Caps;
1103 caps.dwCaps2 = winecaps.DirectDrawCaps.Caps2;
1104 caps.dwCKeyCaps = winecaps.DirectDrawCaps.CKeyCaps;
1105 caps.dwFXCaps = winecaps.DirectDrawCaps.FXCaps;
1106 caps.dwPalCaps = winecaps.DirectDrawCaps.PalCaps;
1107 caps.ddsCaps.dwCaps = winecaps.DirectDrawCaps.ddsCaps;
1108 caps.dwSVBCaps = winecaps.DirectDrawCaps.SVBCaps;
1109 caps.dwSVBCKeyCaps = winecaps.DirectDrawCaps.SVBCKeyCaps;
1110 caps.dwSVBFXCaps = winecaps.DirectDrawCaps.SVBFXCaps;
1111 caps.dwVSBCaps = winecaps.DirectDrawCaps.VSBCaps;
1112 caps.dwVSBCKeyCaps = winecaps.DirectDrawCaps.VSBCKeyCaps;
1113 caps.dwVSBFXCaps = winecaps.DirectDrawCaps.VSBFXCaps;
1114 caps.dwSSBCaps = winecaps.DirectDrawCaps.SSBCaps;
1115 caps.dwSSBCKeyCaps = winecaps.DirectDrawCaps.SSBCKeyCaps;
1116 caps.dwSSBFXCaps = winecaps.DirectDrawCaps.SSBFXCaps;
1118 /* Even if WineD3D supports 3D rendering, remove the cap if ddraw is configured
1121 if(DefaultSurfaceType == SURFACE_GDI) {
1122 caps.dwCaps &= ~DDCAPS_3D;
1123 caps.ddsCaps.dwCaps &= ~(DDSCAPS_3DDEVICE | DDSCAPS_MIPMAP | DDSCAPS_TEXTURE | DDSCAPS_ZBUFFER);
1125 if(winecaps.DirectDrawCaps.StrideAlign != 0) {
1126 caps.dwCaps |= DDCAPS_ALIGNSTRIDE;
1127 caps.dwAlignStrideAlign = winecaps.DirectDrawCaps.StrideAlign;
1132 DD_STRUCT_COPY_BYSIZE(DriverCaps, &caps);
1133 if (TRACE_ON(ddraw))
1135 TRACE("Driver Caps :\n");
1136 DDRAW_dump_DDCAPS(DriverCaps);
1142 DD_STRUCT_COPY_BYSIZE(HELCaps, &caps);
1143 if (TRACE_ON(ddraw))
1145 TRACE("HEL Caps :\n");
1146 DDRAW_dump_DDCAPS(HELCaps);
1153 static HRESULT WINAPI ddraw4_GetCaps(IDirectDraw4 *iface, DDCAPS *driver_caps, DDCAPS *hel_caps)
1155 IDirectDrawImpl *This = impl_from_IDirectDraw4(iface);
1157 TRACE("iface %p, driver_caps %p, hel_caps %p.\n", iface, driver_caps, hel_caps);
1159 return ddraw7_GetCaps(&This->IDirectDraw7_iface, driver_caps, hel_caps);
1162 static HRESULT WINAPI ddraw3_GetCaps(IDirectDraw3 *iface, DDCAPS *driver_caps, DDCAPS *hel_caps)
1164 IDirectDrawImpl *This = impl_from_IDirectDraw3(iface);
1166 TRACE("iface %p, driver_caps %p, hel_caps %p.\n", iface, driver_caps, hel_caps);
1168 return ddraw7_GetCaps(&This->IDirectDraw7_iface, driver_caps, hel_caps);
1171 static HRESULT WINAPI ddraw2_GetCaps(IDirectDraw2 *iface, DDCAPS *driver_caps, DDCAPS *hel_caps)
1173 IDirectDrawImpl *This = impl_from_IDirectDraw2(iface);
1175 TRACE("iface %p, driver_caps %p, hel_caps %p.\n", iface, driver_caps, hel_caps);
1177 return ddraw7_GetCaps(&This->IDirectDraw7_iface, driver_caps, hel_caps);
1180 static HRESULT WINAPI ddraw1_GetCaps(IDirectDraw *iface, DDCAPS *driver_caps, DDCAPS *hel_caps)
1182 IDirectDrawImpl *This = impl_from_IDirectDraw(iface);
1184 TRACE("iface %p, driver_caps %p, hel_caps %p.\n", iface, driver_caps, hel_caps);
1186 return ddraw7_GetCaps(&This->IDirectDraw7_iface, driver_caps, hel_caps);
1189 /*****************************************************************************
1190 * IDirectDraw7::Compact
1192 * No idea what it does, MSDN says it's not implemented.
1195 * DD_OK, but this is unchecked
1197 *****************************************************************************/
1198 static HRESULT WINAPI ddraw7_Compact(IDirectDraw7 *iface)
1200 TRACE("iface %p.\n", iface);
1205 static HRESULT WINAPI ddraw4_Compact(IDirectDraw4 *iface)
1207 IDirectDrawImpl *This = impl_from_IDirectDraw4(iface);
1209 TRACE("iface %p.\n", iface);
1211 return ddraw7_Compact(&This->IDirectDraw7_iface);
1214 static HRESULT WINAPI ddraw3_Compact(IDirectDraw3 *iface)
1216 IDirectDrawImpl *This = impl_from_IDirectDraw3(iface);
1218 TRACE("iface %p.\n", iface);
1220 return ddraw7_Compact(&This->IDirectDraw7_iface);
1223 static HRESULT WINAPI ddraw2_Compact(IDirectDraw2 *iface)
1225 IDirectDrawImpl *This = impl_from_IDirectDraw2(iface);
1227 TRACE("iface %p.\n", iface);
1229 return ddraw7_Compact(&This->IDirectDraw7_iface);
1232 static HRESULT WINAPI ddraw1_Compact(IDirectDraw *iface)
1234 IDirectDrawImpl *This = impl_from_IDirectDraw(iface);
1236 TRACE("iface %p.\n", iface);
1238 return ddraw7_Compact(&This->IDirectDraw7_iface);
1241 /*****************************************************************************
1242 * IDirectDraw7::GetDisplayMode
1244 * Returns information about the current display mode
1246 * Exists in Version 1, 2, 4 and 7
1249 * DDSD: Address of a surface description structure to write the info to
1254 *****************************************************************************/
1255 static HRESULT WINAPI ddraw7_GetDisplayMode(IDirectDraw7 *iface, DDSURFACEDESC2 *DDSD)
1257 IDirectDrawImpl *This = impl_from_IDirectDraw7(iface);
1259 WINED3DDISPLAYMODE Mode;
1262 TRACE("iface %p, surface_desc %p.\n", iface, DDSD);
1264 EnterCriticalSection(&ddraw_cs);
1265 /* This seems sane */
1268 LeaveCriticalSection(&ddraw_cs);
1269 return DDERR_INVALIDPARAMS;
1272 /* The necessary members of LPDDSURFACEDESC and LPDDSURFACEDESC2 are equal,
1273 * so one method can be used for all versions (Hopefully)
1275 hr = IWineD3DDevice_GetDisplayMode(This->wineD3DDevice,
1276 0 /* swapchain 0 */,
1280 ERR(" (%p) IWineD3DDevice::GetDisplayMode returned %08x\n", This, hr);
1281 LeaveCriticalSection(&ddraw_cs);
1285 Size = DDSD->dwSize;
1286 memset(DDSD, 0, Size);
1288 DDSD->dwSize = Size;
1289 DDSD->dwFlags |= DDSD_HEIGHT | DDSD_WIDTH | DDSD_PIXELFORMAT | DDSD_PITCH | DDSD_REFRESHRATE;
1290 DDSD->dwWidth = Mode.Width;
1291 DDSD->dwHeight = Mode.Height;
1292 DDSD->u2.dwRefreshRate = 60;
1293 DDSD->ddsCaps.dwCaps = 0;
1294 DDSD->u4.ddpfPixelFormat.dwSize = sizeof(DDSD->u4.ddpfPixelFormat);
1295 PixelFormat_WineD3DtoDD(&DDSD->u4.ddpfPixelFormat, Mode.Format);
1296 DDSD->u1.lPitch = Mode.Width * DDSD->u4.ddpfPixelFormat.u1.dwRGBBitCount / 8;
1300 TRACE("Returning surface desc :\n");
1301 DDRAW_dump_surface_desc(DDSD);
1304 LeaveCriticalSection(&ddraw_cs);
1308 static HRESULT WINAPI ddraw4_GetDisplayMode(IDirectDraw4 *iface, DDSURFACEDESC2 *surface_desc)
1310 IDirectDrawImpl *This = impl_from_IDirectDraw4(iface);
1312 TRACE("iface %p, surface_desc %p.\n", iface, surface_desc);
1314 return ddraw7_GetDisplayMode(&This->IDirectDraw7_iface, surface_desc);
1317 static HRESULT WINAPI ddraw3_GetDisplayMode(IDirectDraw3 *iface, DDSURFACEDESC *surface_desc)
1319 IDirectDrawImpl *This = impl_from_IDirectDraw3(iface);
1321 TRACE("iface %p, surface_desc %p.\n", iface, surface_desc);
1323 return ddraw7_GetDisplayMode(&This->IDirectDraw7_iface, (DDSURFACEDESC2 *)surface_desc);
1326 static HRESULT WINAPI ddraw2_GetDisplayMode(IDirectDraw2 *iface, DDSURFACEDESC *surface_desc)
1328 IDirectDrawImpl *This = impl_from_IDirectDraw2(iface);
1330 TRACE("iface %p, surface_desc %p.\n", iface, surface_desc);
1332 return ddraw7_GetDisplayMode(&This->IDirectDraw7_iface, (DDSURFACEDESC2 *)surface_desc);
1335 static HRESULT WINAPI ddraw1_GetDisplayMode(IDirectDraw *iface, DDSURFACEDESC *surface_desc)
1337 IDirectDrawImpl *This = impl_from_IDirectDraw(iface);
1339 TRACE("iface %p, surface_desc %p.\n", iface, surface_desc);
1341 return ddraw7_GetDisplayMode(&This->IDirectDraw7_iface, (DDSURFACEDESC2 *)surface_desc);
1344 /*****************************************************************************
1345 * IDirectDraw7::GetFourCCCodes
1347 * Returns an array of supported FourCC codes.
1349 * Exists in Version 1, 2, 4 and 7
1352 * NumCodes: Contains the number of Codes that Codes can carry. Returns the number
1353 * of enumerated codes
1354 * Codes: Pointer to an array of DWORDs where the supported codes are written
1358 * Always returns DD_OK, as it's a stub for now
1360 *****************************************************************************/
1361 static HRESULT WINAPI ddraw7_GetFourCCCodes(IDirectDraw7 *iface, DWORD *NumCodes, DWORD *Codes)
1363 IDirectDrawImpl *This = impl_from_IDirectDraw7(iface);
1364 static const enum wined3d_format_id formats[] =
1366 WINED3DFMT_YUY2, WINED3DFMT_UYVY, WINED3DFMT_YV12,
1367 WINED3DFMT_DXT1, WINED3DFMT_DXT2, WINED3DFMT_DXT3, WINED3DFMT_DXT4, WINED3DFMT_DXT5,
1368 WINED3DFMT_ATI2N, WINED3DFMT_NVHU, WINED3DFMT_NVHS
1370 DWORD count = 0, i, outsize;
1372 WINED3DDISPLAYMODE d3ddm;
1373 WINED3DSURFTYPE type = This->ImplType;
1375 TRACE("iface %p, codes_count %p, codes %p.\n", iface, NumCodes, Codes);
1377 IWineD3DDevice_GetDisplayMode(This->wineD3DDevice,
1378 0 /* swapchain 0 */,
1381 outsize = NumCodes && Codes ? *NumCodes : 0;
1383 if(type == SURFACE_UNKNOWN) type = SURFACE_GDI;
1385 for (i = 0; i < (sizeof(formats) / sizeof(formats[0])); ++i)
1387 hr = wined3d_check_device_format(This->wineD3D, WINED3DADAPTER_DEFAULT, WINED3DDEVTYPE_HAL,
1388 d3ddm.Format, 0, WINED3DRTYPE_SURFACE, formats[i], type);
1391 if (count < outsize)
1392 Codes[count] = formats[i];
1397 TRACE("Returning %u FourCC codes\n", count);
1404 static HRESULT WINAPI ddraw4_GetFourCCCodes(IDirectDraw4 *iface, DWORD *codes_count, DWORD *codes)
1406 IDirectDrawImpl *This = impl_from_IDirectDraw4(iface);
1408 TRACE("iface %p, codes_count %p, codes %p.\n", iface, codes_count, codes);
1410 return ddraw7_GetFourCCCodes(&This->IDirectDraw7_iface, codes_count, codes);
1413 static HRESULT WINAPI ddraw3_GetFourCCCodes(IDirectDraw3 *iface, DWORD *codes_count, DWORD *codes)
1415 IDirectDrawImpl *This = impl_from_IDirectDraw3(iface);
1417 TRACE("iface %p, codes_count %p, codes %p.\n", iface, codes_count, codes);
1419 return ddraw7_GetFourCCCodes(&This->IDirectDraw7_iface, codes_count, codes);
1422 static HRESULT WINAPI ddraw2_GetFourCCCodes(IDirectDraw2 *iface, DWORD *codes_count, DWORD *codes)
1424 IDirectDrawImpl *This = impl_from_IDirectDraw2(iface);
1426 TRACE("iface %p, codes_count %p, codes %p.\n", iface, codes_count, codes);
1428 return ddraw7_GetFourCCCodes(&This->IDirectDraw7_iface, codes_count, codes);
1431 static HRESULT WINAPI ddraw1_GetFourCCCodes(IDirectDraw *iface, DWORD *codes_count, DWORD *codes)
1433 IDirectDrawImpl *This = impl_from_IDirectDraw(iface);
1435 TRACE("iface %p, codes_count %p, codes %p.\n", iface, codes_count, codes);
1437 return ddraw7_GetFourCCCodes(&This->IDirectDraw7_iface, codes_count, codes);
1440 /*****************************************************************************
1441 * IDirectDraw7::GetMonitorFrequency
1443 * Returns the monitor's frequency
1445 * Exists in Version 1, 2, 4 and 7
1448 * Freq: Pointer to a DWORD to write the frequency to
1451 * Always returns DD_OK
1453 *****************************************************************************/
1454 static HRESULT WINAPI ddraw7_GetMonitorFrequency(IDirectDraw7 *iface, DWORD *Freq)
1456 FIXME("iface %p, frequency %p stub!\n", iface, Freq);
1458 /* Ideally this should be in WineD3D, as it concerns the screen setup,
1459 * but for now this should make the games happy
1465 static HRESULT WINAPI ddraw4_GetMonitorFrequency(IDirectDraw4 *iface, DWORD *frequency)
1467 IDirectDrawImpl *This = impl_from_IDirectDraw4(iface);
1469 TRACE("iface %p, frequency %p.\n", iface, frequency);
1471 return ddraw7_GetMonitorFrequency(&This->IDirectDraw7_iface, frequency);
1474 static HRESULT WINAPI ddraw3_GetMonitorFrequency(IDirectDraw3 *iface, DWORD *frequency)
1476 IDirectDrawImpl *This = impl_from_IDirectDraw3(iface);
1478 TRACE("iface %p, frequency %p.\n", iface, frequency);
1480 return ddraw7_GetMonitorFrequency(&This->IDirectDraw7_iface, frequency);
1483 static HRESULT WINAPI ddraw2_GetMonitorFrequency(IDirectDraw2 *iface, DWORD *frequency)
1485 IDirectDrawImpl *This = impl_from_IDirectDraw2(iface);
1487 TRACE("iface %p, frequency %p.\n", iface, frequency);
1489 return ddraw7_GetMonitorFrequency(&This->IDirectDraw7_iface, frequency);
1492 static HRESULT WINAPI ddraw1_GetMonitorFrequency(IDirectDraw *iface, DWORD *frequency)
1494 IDirectDrawImpl *This = impl_from_IDirectDraw(iface);
1496 TRACE("iface %p, frequency %p.\n", iface, frequency);
1498 return ddraw7_GetMonitorFrequency(&This->IDirectDraw7_iface, frequency);
1501 /*****************************************************************************
1502 * IDirectDraw7::GetVerticalBlankStatus
1504 * Returns the Vertical blank status of the monitor. This should be in WineD3D
1505 * too basically, but as it's a semi stub, I didn't create a function there
1508 * status: Pointer to a BOOL to be filled with the vertical blank status
1512 * DDERR_INVALIDPARAMS if status is NULL
1514 *****************************************************************************/
1515 static HRESULT WINAPI ddraw7_GetVerticalBlankStatus(IDirectDraw7 *iface, BOOL *status)
1517 IDirectDrawImpl *This = impl_from_IDirectDraw7(iface);
1519 TRACE("iface %p, status %p.\n", iface, status);
1521 /* This looks sane, the MSDN suggests it too */
1522 EnterCriticalSection(&ddraw_cs);
1525 LeaveCriticalSection(&ddraw_cs);
1526 return DDERR_INVALIDPARAMS;
1529 *status = This->fake_vblank;
1530 This->fake_vblank = !This->fake_vblank;
1531 LeaveCriticalSection(&ddraw_cs);
1535 static HRESULT WINAPI ddraw4_GetVerticalBlankStatus(IDirectDraw4 *iface, BOOL *status)
1537 IDirectDrawImpl *This = impl_from_IDirectDraw4(iface);
1539 TRACE("iface %p, status %p.\n", iface, status);
1541 return ddraw7_GetVerticalBlankStatus(&This->IDirectDraw7_iface, status);
1544 static HRESULT WINAPI ddraw3_GetVerticalBlankStatus(IDirectDraw3 *iface, BOOL *status)
1546 IDirectDrawImpl *This = impl_from_IDirectDraw3(iface);
1548 TRACE("iface %p, status %p.\n", iface, status);
1550 return ddraw7_GetVerticalBlankStatus(&This->IDirectDraw7_iface, status);
1553 static HRESULT WINAPI ddraw2_GetVerticalBlankStatus(IDirectDraw2 *iface, BOOL *status)
1555 IDirectDrawImpl *This = impl_from_IDirectDraw2(iface);
1557 TRACE("iface %p, status %p.\n", iface, status);
1559 return ddraw7_GetVerticalBlankStatus(&This->IDirectDraw7_iface, status);
1562 static HRESULT WINAPI ddraw1_GetVerticalBlankStatus(IDirectDraw *iface, BOOL *status)
1564 IDirectDrawImpl *This = impl_from_IDirectDraw(iface);
1566 TRACE("iface %p, status %p.\n", iface, status);
1568 return ddraw7_GetVerticalBlankStatus(&This->IDirectDraw7_iface, status);
1571 /*****************************************************************************
1572 * IDirectDraw7::GetAvailableVidMem
1574 * Returns the total and free video memory
1577 * Caps: Specifies the memory type asked for
1578 * total: Pointer to a DWORD to be filled with the total memory
1579 * free: Pointer to a DWORD to be filled with the free memory
1583 * DDERR_INVALIDPARAMS of free and total are NULL
1585 *****************************************************************************/
1586 static HRESULT WINAPI ddraw7_GetAvailableVidMem(IDirectDraw7 *iface, DDSCAPS2 *Caps, DWORD *total,
1589 IDirectDrawImpl *This = impl_from_IDirectDraw7(iface);
1591 TRACE("iface %p, caps %p, total %p, free %p.\n", iface, Caps, total, free);
1595 TRACE("(%p) Asked for memory with description: ", This);
1596 DDRAW_dump_DDSCAPS2(Caps);
1598 EnterCriticalSection(&ddraw_cs);
1600 /* Todo: System memory vs local video memory vs non-local video memory
1601 * The MSDN also mentions differences between texture memory and other
1602 * resources, but that's not important
1605 if( (!total) && (!free) )
1607 LeaveCriticalSection(&ddraw_cs);
1608 return DDERR_INVALIDPARAMS;
1611 if(total) *total = This->total_vidmem;
1612 if(free) *free = IWineD3DDevice_GetAvailableTextureMem(This->wineD3DDevice);
1614 LeaveCriticalSection(&ddraw_cs);
1618 static HRESULT WINAPI ddraw4_GetAvailableVidMem(IDirectDraw4 *iface,
1619 DDSCAPS2 *caps, DWORD *total, DWORD *free)
1621 IDirectDrawImpl *This = impl_from_IDirectDraw4(iface);
1623 TRACE("iface %p, caps %p, total %p, free %p.\n", iface, caps, total, free);
1625 return ddraw7_GetAvailableVidMem(&This->IDirectDraw7_iface, caps, total, free);
1628 static HRESULT WINAPI ddraw3_GetAvailableVidMem(IDirectDraw3 *iface, DDSCAPS *caps, DWORD *total,
1631 IDirectDrawImpl *This = impl_from_IDirectDraw3(iface);
1634 TRACE("iface %p, caps %p, total %p, free %p.\n", iface, caps, total, free);
1636 DDRAW_Convert_DDSCAPS_1_To_2(caps, &caps2);
1637 return ddraw7_GetAvailableVidMem(&This->IDirectDraw7_iface, &caps2, total, free);
1640 static HRESULT WINAPI ddraw2_GetAvailableVidMem(IDirectDraw2 *iface,
1641 DDSCAPS *caps, DWORD *total, DWORD *free)
1643 IDirectDrawImpl *This = impl_from_IDirectDraw2(iface);
1646 TRACE("iface %p, caps %p, total %p, free %p.\n", iface, caps, total, free);
1648 DDRAW_Convert_DDSCAPS_1_To_2(caps, &caps2);
1649 return ddraw7_GetAvailableVidMem(&This->IDirectDraw7_iface, &caps2, total, free);
1652 /*****************************************************************************
1653 * IDirectDraw7::Initialize
1655 * Initializes a DirectDraw interface.
1658 * GUID: Interface identifier. Well, don't know what this is really good
1662 * Returns DD_OK on the first call,
1663 * DDERR_ALREADYINITIALIZED on repeated calls
1665 *****************************************************************************/
1666 static HRESULT WINAPI ddraw7_Initialize(IDirectDraw7 *iface, GUID *Guid)
1668 IDirectDrawImpl *This = impl_from_IDirectDraw7(iface);
1670 TRACE("iface %p, guid %s.\n", iface, debugstr_guid(Guid));
1672 if(This->initialized)
1674 return DDERR_ALREADYINITIALIZED;
1682 static HRESULT WINAPI ddraw4_Initialize(IDirectDraw4 *iface, GUID *guid)
1684 IDirectDrawImpl *This = impl_from_IDirectDraw4(iface);
1686 TRACE("iface %p, guid %s.\n", iface, debugstr_guid(guid));
1688 return ddraw7_Initialize(&This->IDirectDraw7_iface, guid);
1691 static HRESULT WINAPI ddraw3_Initialize(IDirectDraw3 *iface, GUID *guid)
1693 IDirectDrawImpl *This = impl_from_IDirectDraw3(iface);
1695 TRACE("iface %p, guid %s.\n", iface, debugstr_guid(guid));
1697 return ddraw7_Initialize(&This->IDirectDraw7_iface, guid);
1700 static HRESULT WINAPI ddraw2_Initialize(IDirectDraw2 *iface, GUID *guid)
1702 IDirectDrawImpl *This = impl_from_IDirectDraw2(iface);
1704 TRACE("iface %p, guid %s.\n", iface, debugstr_guid(guid));
1706 return ddraw7_Initialize(&This->IDirectDraw7_iface, guid);
1709 static HRESULT WINAPI ddraw1_Initialize(IDirectDraw *iface, GUID *guid)
1711 IDirectDrawImpl *This = impl_from_IDirectDraw(iface);
1713 TRACE("iface %p, guid %s.\n", iface, debugstr_guid(guid));
1715 return ddraw7_Initialize(&This->IDirectDraw7_iface, guid);
1718 static HRESULT WINAPI d3d1_Initialize(IDirect3D *iface, REFIID riid)
1720 TRACE("iface %p, riid %s.\n", iface, debugstr_guid(riid));
1725 /*****************************************************************************
1726 * IDirectDraw7::FlipToGDISurface
1728 * "Makes the surface that the GDI writes to the primary surface"
1729 * Looks like some windows specific thing we don't have to care about.
1730 * According to MSDN it permits GDI dialog boxes in FULLSCREEN mode. Good to
1731 * show error boxes ;)
1732 * Well, just return DD_OK.
1735 * Always returns DD_OK
1737 *****************************************************************************/
1738 static HRESULT WINAPI ddraw7_FlipToGDISurface(IDirectDraw7 *iface)
1740 FIXME("iface %p stub!\n", iface);
1745 static HRESULT WINAPI ddraw4_FlipToGDISurface(IDirectDraw4 *iface)
1747 IDirectDrawImpl *This = impl_from_IDirectDraw4(iface);
1749 TRACE("iface %p.\n", iface);
1751 return ddraw7_FlipToGDISurface(&This->IDirectDraw7_iface);
1754 static HRESULT WINAPI ddraw3_FlipToGDISurface(IDirectDraw3 *iface)
1756 IDirectDrawImpl *This = impl_from_IDirectDraw3(iface);
1758 TRACE("iface %p.\n", iface);
1760 return ddraw7_FlipToGDISurface(&This->IDirectDraw7_iface);
1763 static HRESULT WINAPI ddraw2_FlipToGDISurface(IDirectDraw2 *iface)
1765 IDirectDrawImpl *This = impl_from_IDirectDraw2(iface);
1767 TRACE("iface %p.\n", iface);
1769 return ddraw7_FlipToGDISurface(&This->IDirectDraw7_iface);
1772 static HRESULT WINAPI ddraw1_FlipToGDISurface(IDirectDraw *iface)
1774 IDirectDrawImpl *This = impl_from_IDirectDraw(iface);
1776 TRACE("iface %p.\n", iface);
1778 return ddraw7_FlipToGDISurface(&This->IDirectDraw7_iface);
1781 /*****************************************************************************
1782 * IDirectDraw7::WaitForVerticalBlank
1784 * This method allows applications to get in sync with the vertical blank
1786 * The wormhole demo in the DirectX 7 sdk uses this call, and it doesn't
1787 * redraw the screen, most likely because of this stub
1790 * Flags: one of DDWAITVB_BLOCKBEGIN, DDWAITVB_BLOCKBEGINEVENT
1791 * or DDWAITVB_BLOCKEND
1792 * h: Not used, according to MSDN
1795 * Always returns DD_OK
1797 *****************************************************************************/
1798 static HRESULT WINAPI ddraw7_WaitForVerticalBlank(IDirectDraw7 *iface, DWORD Flags, HANDLE event)
1802 TRACE("iface %p, flags %#x, event %p.\n", iface, Flags, event);
1804 /* This function is called often, so print the fixme only once */
1807 FIXME("iface %p, flags %#x, event %p stub!\n", iface, Flags, event);
1811 /* MSDN says DDWAITVB_BLOCKBEGINEVENT is not supported */
1812 if(Flags & DDWAITVB_BLOCKBEGINEVENT)
1813 return DDERR_UNSUPPORTED; /* unchecked */
1818 static HRESULT WINAPI ddraw4_WaitForVerticalBlank(IDirectDraw4 *iface, DWORD flags, HANDLE event)
1820 IDirectDrawImpl *This = impl_from_IDirectDraw4(iface);
1822 TRACE("iface %p, flags %#x, event %p.\n", iface, flags, event);
1824 return ddraw7_WaitForVerticalBlank(&This->IDirectDraw7_iface, flags, event);
1827 static HRESULT WINAPI ddraw3_WaitForVerticalBlank(IDirectDraw3 *iface, DWORD flags, HANDLE event)
1829 IDirectDrawImpl *This = impl_from_IDirectDraw3(iface);
1831 TRACE("iface %p, flags %#x, event %p.\n", iface, flags, event);
1833 return ddraw7_WaitForVerticalBlank(&This->IDirectDraw7_iface, flags, event);
1836 static HRESULT WINAPI ddraw2_WaitForVerticalBlank(IDirectDraw2 *iface, DWORD flags, HANDLE event)
1838 IDirectDrawImpl *This = impl_from_IDirectDraw2(iface);
1840 TRACE("iface %p, flags %#x, event %p.\n", iface, flags, event);
1842 return ddraw7_WaitForVerticalBlank(&This->IDirectDraw7_iface, flags, event);
1845 static HRESULT WINAPI ddraw1_WaitForVerticalBlank(IDirectDraw *iface, DWORD flags, HANDLE event)
1847 IDirectDrawImpl *This = impl_from_IDirectDraw(iface);
1849 TRACE("iface %p, flags %#x, event %p.\n", iface, flags, event);
1851 return ddraw7_WaitForVerticalBlank(&This->IDirectDraw7_iface, flags, event);
1854 /*****************************************************************************
1855 * IDirectDraw7::GetScanLine
1857 * Returns the scan line that is being drawn on the monitor
1860 * Scanline: Address to write the scan line value to
1863 * Always returns DD_OK
1865 *****************************************************************************/
1866 static HRESULT WINAPI ddraw7_GetScanLine(IDirectDraw7 *iface, DWORD *Scanline)
1868 IDirectDrawImpl *This = impl_from_IDirectDraw7(iface);
1869 static BOOL hide = FALSE;
1870 WINED3DDISPLAYMODE Mode;
1872 TRACE("iface %p, line %p.\n", iface, Scanline);
1874 /* This function is called often, so print the fixme only once */
1875 EnterCriticalSection(&ddraw_cs);
1878 FIXME("iface %p, line %p partial stub!\n", iface, Scanline);
1882 IWineD3DDevice_GetDisplayMode(This->wineD3DDevice,
1886 /* Fake the line sweeping of the monitor */
1887 /* FIXME: We should synchronize with a source to keep the refresh rate */
1888 *Scanline = This->cur_scanline++;
1889 /* Assume 20 scan lines in the vertical blank */
1890 if (This->cur_scanline >= Mode.Height + 20)
1891 This->cur_scanline = 0;
1893 LeaveCriticalSection(&ddraw_cs);
1897 static HRESULT WINAPI ddraw4_GetScanLine(IDirectDraw4 *iface, DWORD *line)
1899 IDirectDrawImpl *This = impl_from_IDirectDraw4(iface);
1901 TRACE("iface %p, line %p.\n", iface, line);
1903 return ddraw7_GetScanLine(&This->IDirectDraw7_iface, line);
1906 static HRESULT WINAPI ddraw3_GetScanLine(IDirectDraw3 *iface, DWORD *line)
1908 IDirectDrawImpl *This = impl_from_IDirectDraw3(iface);
1910 TRACE("iface %p, line %p.\n", iface, line);
1912 return ddraw7_GetScanLine(&This->IDirectDraw7_iface, line);
1915 static HRESULT WINAPI ddraw2_GetScanLine(IDirectDraw2 *iface, DWORD *line)
1917 IDirectDrawImpl *This = impl_from_IDirectDraw2(iface);
1919 TRACE("iface %p, line %p.\n", iface, line);
1921 return ddraw7_GetScanLine(&This->IDirectDraw7_iface, line);
1924 static HRESULT WINAPI ddraw1_GetScanLine(IDirectDraw *iface, DWORD *line)
1926 IDirectDrawImpl *This = impl_from_IDirectDraw(iface);
1928 TRACE("iface %p, line %p.\n", iface, line);
1930 return ddraw7_GetScanLine(&This->IDirectDraw7_iface, line);
1933 /*****************************************************************************
1934 * IDirectDraw7::TestCooperativeLevel
1936 * Informs the application about the state of the video adapter, depending
1937 * on the cooperative level
1940 * DD_OK if the device is in a sane state
1941 * DDERR_NOEXCLUSIVEMODE or DDERR_EXCLUSIVEMODEALREADYSET
1942 * if the state is not correct(See below)
1944 *****************************************************************************/
1945 static HRESULT WINAPI ddraw7_TestCooperativeLevel(IDirectDraw7 *iface)
1947 TRACE("iface %p.\n", iface);
1952 static HRESULT WINAPI ddraw4_TestCooperativeLevel(IDirectDraw4 *iface)
1954 IDirectDrawImpl *This = impl_from_IDirectDraw4(iface);
1956 TRACE("iface %p.\n", iface);
1958 return ddraw7_TestCooperativeLevel(&This->IDirectDraw7_iface);
1961 /*****************************************************************************
1962 * IDirectDraw7::GetGDISurface
1964 * Returns the surface that GDI is treating as the primary surface.
1965 * For Wine this is the front buffer
1968 * GDISurface: Address to write the surface pointer to
1971 * DD_OK if the surface was found
1972 * DDERR_NOTFOUND if the GDI surface wasn't found
1974 *****************************************************************************/
1975 static HRESULT WINAPI ddraw7_GetGDISurface(IDirectDraw7 *iface, IDirectDrawSurface7 **GDISurface)
1977 IDirectDrawImpl *This = impl_from_IDirectDraw7(iface);
1978 struct wined3d_surface *wined3d_surface;
1979 IDirectDrawSurface7 *ddsurf;
1983 TRACE("iface %p, surface %p.\n", iface, GDISurface);
1985 /* Get the back buffer from the wineD3DDevice and search its
1986 * attached surfaces for the front buffer
1988 EnterCriticalSection(&ddraw_cs);
1989 hr = IWineD3DDevice_GetBackBuffer(This->wineD3DDevice,
1990 0, 0, WINED3DBACKBUFFER_TYPE_MONO, &wined3d_surface);
1991 if (FAILED(hr) || !wined3d_surface)
1993 ERR("IWineD3DDevice::GetBackBuffer failed\n");
1994 LeaveCriticalSection(&ddraw_cs);
1995 return DDERR_NOTFOUND;
1998 ddsurf = wined3d_surface_get_parent(wined3d_surface);
1999 wined3d_surface_decref(wined3d_surface);
2001 /* Find the front buffer */
2002 ddsCaps.dwCaps = DDSCAPS_FRONTBUFFER;
2003 hr = IDirectDrawSurface7_GetAttachedSurface(ddsurf,
2008 ERR("IDirectDrawSurface7::GetAttachedSurface failed, hr = %x\n", hr);
2011 /* The AddRef is OK this time */
2012 LeaveCriticalSection(&ddraw_cs);
2016 static HRESULT WINAPI ddraw4_GetGDISurface(IDirectDraw4 *iface, IDirectDrawSurface4 **surface)
2018 IDirectDrawImpl *This = impl_from_IDirectDraw4(iface);
2020 TRACE("iface %p, surface %p.\n", iface, surface);
2022 return ddraw7_GetGDISurface(&This->IDirectDraw7_iface, (IDirectDrawSurface7 **)surface);
2025 static HRESULT WINAPI ddraw3_GetGDISurface(IDirectDraw3 *iface, IDirectDrawSurface **surface)
2027 IDirectDrawImpl *This = impl_from_IDirectDraw3(iface);
2028 IDirectDrawSurface7 *surface7;
2031 TRACE("iface %p, surface %p.\n", iface, surface);
2033 hr = ddraw7_GetGDISurface(&This->IDirectDraw7_iface, &surface7);
2034 *surface = surface7 ? (IDirectDrawSurface *)&((IDirectDrawSurfaceImpl *)surface7)->IDirectDrawSurface3_vtbl : NULL;
2039 static HRESULT WINAPI ddraw2_GetGDISurface(IDirectDraw2 *iface, IDirectDrawSurface **surface)
2041 IDirectDrawImpl *This = impl_from_IDirectDraw2(iface);
2042 IDirectDrawSurface7 *surface7;
2045 TRACE("iface %p, surface %p.\n", iface, surface);
2047 hr = ddraw7_GetGDISurface(&This->IDirectDraw7_iface, &surface7);
2048 *surface = surface7 ? (IDirectDrawSurface *)&((IDirectDrawSurfaceImpl *)surface7)->IDirectDrawSurface3_vtbl : NULL;
2053 static HRESULT WINAPI ddraw1_GetGDISurface(IDirectDraw *iface, IDirectDrawSurface **surface)
2055 IDirectDrawImpl *This = impl_from_IDirectDraw(iface);
2056 IDirectDrawSurface7 *surface7;
2059 TRACE("iface %p, surface %p.\n", iface, surface);
2061 hr = ddraw7_GetGDISurface(&This->IDirectDraw7_iface, &surface7);
2062 *surface = surface7 ? (IDirectDrawSurface *)&((IDirectDrawSurfaceImpl *)surface7)->IDirectDrawSurface3_vtbl : NULL;
2067 struct displaymodescallback_context
2069 LPDDENUMMODESCALLBACK func;
2073 static HRESULT CALLBACK EnumDisplayModesCallbackThunk(DDSURFACEDESC2 *surface_desc, void *context)
2075 struct displaymodescallback_context *cbcontext = context;
2078 memcpy(&desc, surface_desc, sizeof(desc));
2079 desc.dwSize = sizeof(desc);
2081 return cbcontext->func(&desc, cbcontext->context);
2084 /*****************************************************************************
2085 * IDirectDraw7::EnumDisplayModes
2087 * Enumerates the supported Display modes. The modes can be filtered with
2088 * the DDSD parameter.
2091 * Flags: can be DDEDM_REFRESHRATES and DDEDM_STANDARDVGAMODES. For old ddraw
2092 * versions (3 and older?) this is reserved and must be 0.
2093 * DDSD: Surface description to filter the modes
2094 * Context: Pointer passed back to the callback function
2095 * cb: Application-provided callback function
2099 * DDERR_INVALIDPARAMS if the callback wasn't set
2101 *****************************************************************************/
2102 static HRESULT WINAPI ddraw7_EnumDisplayModes(IDirectDraw7 *iface, DWORD Flags,
2103 DDSURFACEDESC2 *DDSD, void *Context, LPDDENUMMODESCALLBACK2 cb)
2105 IDirectDrawImpl *This = impl_from_IDirectDraw7(iface);
2106 unsigned int modenum, fmt;
2107 WINED3DDISPLAYMODE mode;
2108 DDSURFACEDESC2 callback_sd;
2109 WINED3DDISPLAYMODE *enum_modes = NULL;
2110 unsigned enum_mode_count = 0, enum_mode_array_size = 0;
2111 DDPIXELFORMAT pixelformat;
2113 static const enum wined3d_format_id checkFormatList[] =
2115 WINED3DFMT_B8G8R8X8_UNORM,
2116 WINED3DFMT_B5G6R5_UNORM,
2120 TRACE("iface %p, flags %#x, surface_desc %p, context %p, callback %p.\n",
2121 iface, Flags, DDSD, Context, cb);
2123 EnterCriticalSection(&ddraw_cs);
2124 /* This looks sane */
2127 LeaveCriticalSection(&ddraw_cs);
2128 return DDERR_INVALIDPARAMS;
2131 if(!(Flags & DDEDM_REFRESHRATES))
2133 enum_mode_array_size = 16;
2134 enum_modes = HeapAlloc(GetProcessHeap(), 0, sizeof(WINED3DDISPLAYMODE) * enum_mode_array_size);
2137 ERR("Out of memory\n");
2138 LeaveCriticalSection(&ddraw_cs);
2139 return DDERR_OUTOFMEMORY;
2143 pixelformat.dwSize = sizeof(pixelformat);
2144 for(fmt = 0; fmt < (sizeof(checkFormatList) / sizeof(checkFormatList[0])); fmt++)
2147 while (wined3d_enum_adapter_modes(This->wineD3D, WINED3DADAPTER_DEFAULT,
2148 checkFormatList[fmt], modenum++, &mode) == WINED3D_OK)
2150 PixelFormat_WineD3DtoDD(&pixelformat, mode.Format);
2153 if(DDSD->dwFlags & DDSD_WIDTH && mode.Width != DDSD->dwWidth) continue;
2154 if(DDSD->dwFlags & DDSD_HEIGHT && mode.Height != DDSD->dwHeight) continue;
2155 if(DDSD->dwFlags & DDSD_REFRESHRATE && mode.RefreshRate != DDSD->u2.dwRefreshRate) continue;
2156 if (DDSD->dwFlags & DDSD_PIXELFORMAT &&
2157 pixelformat.u1.dwRGBBitCount != DDSD->u4.ddpfPixelFormat.u1.dwRGBBitCount) continue;
2160 if(!(Flags & DDEDM_REFRESHRATES))
2162 /* DX docs state EnumDisplayMode should return only unique modes. If DDEDM_REFRESHRATES is not set, refresh
2163 * rate doesn't matter when determining if the mode is unique. So modes only differing in refresh rate have
2164 * to be reduced to a single unique result in such case.
2169 for (i = 0; i < enum_mode_count; i++)
2171 if(enum_modes[i].Width == mode.Width && enum_modes[i].Height == mode.Height &&
2172 enum_modes[i].Format == mode.Format)
2182 memset(&callback_sd, 0, sizeof(callback_sd));
2183 callback_sd.dwSize = sizeof(callback_sd);
2184 callback_sd.u4.ddpfPixelFormat.dwSize = sizeof(DDPIXELFORMAT);
2186 callback_sd.dwFlags = DDSD_HEIGHT|DDSD_WIDTH|DDSD_PIXELFORMAT|DDSD_PITCH|DDSD_REFRESHRATE;
2187 if(Flags & DDEDM_REFRESHRATES)
2189 callback_sd.u2.dwRefreshRate = mode.RefreshRate;
2192 callback_sd.dwWidth = mode.Width;
2193 callback_sd.dwHeight = mode.Height;
2195 callback_sd.u4.ddpfPixelFormat=pixelformat;
2197 /* Calc pitch and DWORD align like MSDN says */
2198 callback_sd.u1.lPitch = (callback_sd.u4.ddpfPixelFormat.u1.dwRGBBitCount / 8) * mode.Width;
2199 callback_sd.u1.lPitch = (callback_sd.u1.lPitch + 3) & ~3;
2201 TRACE("Enumerating %dx%dx%d @%d\n", callback_sd.dwWidth, callback_sd.dwHeight, callback_sd.u4.ddpfPixelFormat.u1.dwRGBBitCount,
2202 callback_sd.u2.dwRefreshRate);
2204 if(cb(&callback_sd, Context) == DDENUMRET_CANCEL)
2206 TRACE("Application asked to terminate the enumeration\n");
2207 HeapFree(GetProcessHeap(), 0, enum_modes);
2208 LeaveCriticalSection(&ddraw_cs);
2212 if(!(Flags & DDEDM_REFRESHRATES))
2214 if (enum_mode_count == enum_mode_array_size)
2216 WINED3DDISPLAYMODE *new_enum_modes;
2218 enum_mode_array_size *= 2;
2219 new_enum_modes = HeapReAlloc(GetProcessHeap(), 0, enum_modes, sizeof(WINED3DDISPLAYMODE) * enum_mode_array_size);
2221 if (!new_enum_modes)
2223 ERR("Out of memory\n");
2224 HeapFree(GetProcessHeap(), 0, enum_modes);
2225 LeaveCriticalSection(&ddraw_cs);
2226 return DDERR_OUTOFMEMORY;
2229 enum_modes = new_enum_modes;
2232 enum_modes[enum_mode_count++] = mode;
2237 TRACE("End of enumeration\n");
2238 HeapFree(GetProcessHeap(), 0, enum_modes);
2239 LeaveCriticalSection(&ddraw_cs);
2243 static HRESULT WINAPI ddraw4_EnumDisplayModes(IDirectDraw4 *iface, DWORD flags,
2244 DDSURFACEDESC2 *surface_desc, void *context, LPDDENUMMODESCALLBACK2 callback)
2246 IDirectDrawImpl *This = impl_from_IDirectDraw4(iface);
2248 TRACE("iface %p, flags %#x, surface_desc %p, context %p, callback %p.\n",
2249 iface, flags, surface_desc, context, callback);
2251 return ddraw7_EnumDisplayModes(&This->IDirectDraw7_iface, flags, surface_desc, context, callback);
2254 static HRESULT WINAPI ddraw3_EnumDisplayModes(IDirectDraw3 *iface, DWORD flags,
2255 DDSURFACEDESC *surface_desc, void *context, LPDDENUMMODESCALLBACK callback)
2257 IDirectDrawImpl *This = impl_from_IDirectDraw3(iface);
2258 struct displaymodescallback_context cbcontext;
2260 TRACE("iface %p, flags %#x, surface_desc %p, context %p, callback %p.\n",
2261 iface, flags, surface_desc, context, callback);
2263 cbcontext.func = callback;
2264 cbcontext.context = context;
2266 return ddraw7_EnumDisplayModes(&This->IDirectDraw7_iface, flags, (DDSURFACEDESC2 *)surface_desc,
2267 &cbcontext, EnumDisplayModesCallbackThunk);
2270 static HRESULT WINAPI ddraw2_EnumDisplayModes(IDirectDraw2 *iface, DWORD flags,
2271 DDSURFACEDESC *surface_desc, void *context, LPDDENUMMODESCALLBACK callback)
2273 IDirectDrawImpl *This = impl_from_IDirectDraw2(iface);
2274 struct displaymodescallback_context cbcontext;
2276 TRACE("iface %p, flags %#x, surface_desc %p, context %p, callback %p.\n",
2277 iface, flags, surface_desc, context, callback);
2279 cbcontext.func = callback;
2280 cbcontext.context = context;
2282 return ddraw7_EnumDisplayModes(&This->IDirectDraw7_iface, flags, (DDSURFACEDESC2 *)surface_desc,
2283 &cbcontext, EnumDisplayModesCallbackThunk);
2286 static HRESULT WINAPI ddraw1_EnumDisplayModes(IDirectDraw *iface, DWORD flags,
2287 DDSURFACEDESC *surface_desc, void *context, LPDDENUMMODESCALLBACK callback)
2289 IDirectDrawImpl *This = impl_from_IDirectDraw(iface);
2290 struct displaymodescallback_context cbcontext;
2292 TRACE("iface %p, flags %#x, surface_desc %p, context %p, callback %p.\n",
2293 iface, flags, surface_desc, context, callback);
2295 cbcontext.func = callback;
2296 cbcontext.context = context;
2298 return ddraw7_EnumDisplayModes(&This->IDirectDraw7_iface, flags, (DDSURFACEDESC2 *)surface_desc,
2299 &cbcontext, EnumDisplayModesCallbackThunk);
2302 /*****************************************************************************
2303 * IDirectDraw7::EvaluateMode
2305 * Used with IDirectDraw7::StartModeTest to test video modes.
2306 * EvaluateMode is used to pass or fail a mode, and continue with the next
2310 * Flags: DDEM_MODEPASSED or DDEM_MODEFAILED
2311 * Timeout: Returns the amount of seconds left before the mode would have
2312 * been failed automatically
2315 * This implementation always DD_OK, because it's a stub
2317 *****************************************************************************/
2318 static HRESULT WINAPI ddraw7_EvaluateMode(IDirectDraw7 *iface, DWORD Flags, DWORD *Timeout)
2320 FIXME("iface %p, flags %#x, timeout %p stub!\n", iface, Flags, Timeout);
2322 /* When implementing this, implement it in WineD3D */
2327 /*****************************************************************************
2328 * IDirectDraw7::GetDeviceIdentifier
2330 * Returns the device identifier, which gives information about the driver
2331 * Our device identifier is defined at the beginning of this file.
2334 * DDDI: Address for the returned structure
2335 * Flags: Can be DDGDI_GETHOSTIDENTIFIER
2338 * On success it returns DD_OK
2339 * DDERR_INVALIDPARAMS if DDDI is NULL
2341 *****************************************************************************/
2342 static HRESULT WINAPI ddraw7_GetDeviceIdentifier(IDirectDraw7 *iface,
2343 DDDEVICEIDENTIFIER2 *DDDI, DWORD Flags)
2345 TRACE("iface %p, device_identifier %p, flags %#x.\n", iface, DDDI, Flags);
2348 return DDERR_INVALIDPARAMS;
2350 /* The DDGDI_GETHOSTIDENTIFIER returns the information about the 2D
2351 * host adapter, if there's a secondary 3D adapter. This doesn't apply
2352 * to any modern hardware, nor is it interesting for Wine, so ignore it.
2353 * Size of DDDEVICEIDENTIFIER2 may be aligned to 8 bytes and thus 4
2354 * bytes too long. So only copy the relevant part of the structure
2357 memcpy(DDDI, &deviceidentifier, FIELD_OFFSET(DDDEVICEIDENTIFIER2, dwWHQLLevel) + sizeof(DWORD));
2361 static HRESULT WINAPI ddraw4_GetDeviceIdentifier(IDirectDraw4 *iface,
2362 DDDEVICEIDENTIFIER *identifier, DWORD flags)
2364 IDirectDrawImpl *This = impl_from_IDirectDraw4(iface);
2365 DDDEVICEIDENTIFIER2 identifier2;
2368 TRACE("iface %p, identifier %p, flags %#x.\n", iface, identifier, flags);
2370 hr = ddraw7_GetDeviceIdentifier(&This->IDirectDraw7_iface, &identifier2, flags);
2371 DDRAW_Convert_DDDEVICEIDENTIFIER_2_To_1(&identifier2, identifier);
2376 /*****************************************************************************
2377 * IDirectDraw7::GetSurfaceFromDC
2379 * Returns the Surface for a GDI device context handle.
2380 * Is this related to IDirectDrawSurface::GetDC ???
2383 * hdc: hdc to return the surface for
2384 * Surface: Address to write the surface pointer to
2387 * Always returns DD_OK because it's a stub
2389 *****************************************************************************/
2390 static HRESULT WINAPI ddraw7_GetSurfaceFromDC(IDirectDraw7 *iface, HDC hdc,
2391 IDirectDrawSurface7 **Surface)
2393 IDirectDrawImpl *This = impl_from_IDirectDraw7(iface);
2394 struct wined3d_surface *wined3d_surface;
2397 TRACE("iface %p, dc %p, surface %p.\n", iface, hdc, Surface);
2399 if (!Surface) return E_INVALIDARG;
2401 hr = IWineD3DDevice_GetSurfaceFromDC(This->wineD3DDevice, hdc, &wined3d_surface);
2404 TRACE("No surface found for dc %p.\n", hdc);
2406 return DDERR_NOTFOUND;
2409 *Surface = wined3d_surface_get_parent(wined3d_surface);
2410 IDirectDrawSurface7_AddRef(*Surface);
2411 TRACE("Returning surface %p.\n", Surface);
2415 static HRESULT WINAPI ddraw4_GetSurfaceFromDC(IDirectDraw4 *iface, HDC dc,
2416 IDirectDrawSurface4 **surface)
2418 IDirectDrawImpl *This = impl_from_IDirectDraw4(iface);
2419 IDirectDrawSurface7 *surface7;
2422 TRACE("iface %p, dc %p, surface %p.\n", iface, dc, surface);
2424 if (!surface) return E_INVALIDARG;
2426 hr = ddraw7_GetSurfaceFromDC(&This->IDirectDraw7_iface, dc, &surface7);
2427 *surface = surface7 ? (IDirectDrawSurface4 *)&((IDirectDrawSurfaceImpl *)surface7)->IDirectDrawSurface3_vtbl : NULL;
2432 static HRESULT WINAPI ddraw3_GetSurfaceFromDC(IDirectDraw3 *iface, HDC dc,
2433 IDirectDrawSurface **surface)
2435 IDirectDrawImpl *This = impl_from_IDirectDraw3(iface);
2437 TRACE("iface %p, dc %p, surface %p.\n", iface, dc, surface);
2439 return ddraw7_GetSurfaceFromDC(&This->IDirectDraw7_iface, dc, (IDirectDrawSurface7 **)surface);
2442 /*****************************************************************************
2443 * IDirectDraw7::RestoreAllSurfaces
2445 * Calls the restore method of all surfaces
2450 * Always returns DD_OK because it's a stub
2452 *****************************************************************************/
2453 static HRESULT WINAPI ddraw7_RestoreAllSurfaces(IDirectDraw7 *iface)
2455 FIXME("iface %p stub!\n", iface);
2457 /* This isn't hard to implement: Enumerate all WineD3D surfaces,
2458 * get their parent and call their restore method. Do not implement
2459 * it in WineD3D, as restoring a surface means re-creating the
2465 static HRESULT WINAPI ddraw4_RestoreAllSurfaces(IDirectDraw4 *iface)
2467 IDirectDrawImpl *This = impl_from_IDirectDraw4(iface);
2469 TRACE("iface %p.\n", iface);
2471 return ddraw7_RestoreAllSurfaces(&This->IDirectDraw7_iface);
2474 /*****************************************************************************
2475 * IDirectDraw7::StartModeTest
2477 * Tests the specified video modes to update the system registry with
2478 * refresh rate information. StartModeTest starts the mode test,
2479 * EvaluateMode is used to fail or pass a mode. If EvaluateMode
2480 * isn't called within 15 seconds, the mode is failed automatically
2482 * As refresh rates are handled by the X server, I don't think this
2483 * Method is important
2486 * Modes: An array of mode specifications
2487 * NumModes: The number of modes in Modes
2488 * Flags: Some flags...
2491 * Returns DDERR_TESTFINISHED if flags contains DDSMT_ISTESTREQUIRED,
2492 * if no modes are passed, DDERR_INVALIDPARAMS is returned,
2495 *****************************************************************************/
2496 static HRESULT WINAPI ddraw7_StartModeTest(IDirectDraw7 *iface, SIZE *Modes, DWORD NumModes, DWORD Flags)
2498 FIXME("iface %p, modes %p, mode_count %u, flags %#x partial stub!\n",
2499 iface, Modes, NumModes, Flags);
2501 /* This looks sane */
2502 if( (!Modes) || (NumModes == 0) ) return DDERR_INVALIDPARAMS;
2504 /* DDSMT_ISTESTREQUIRED asks if a mode test is necessary.
2505 * As it is not, DDERR_TESTFINISHED is returned
2506 * (hopefully that's correct
2508 if(Flags & DDSMT_ISTESTREQUIRED) return DDERR_TESTFINISHED;
2509 * well, that value doesn't (yet) exist in the wine headers, so ignore it
2515 /*****************************************************************************
2516 * ddraw_recreate_surfaces_cb
2518 * Enumeration callback for ddraw_recreate_surface.
2519 * It re-recreates the WineD3DSurface. It's pretty straightforward
2521 *****************************************************************************/
2522 HRESULT WINAPI ddraw_recreate_surfaces_cb(IDirectDrawSurface7 *surf, DDSURFACEDESC2 *desc, void *Context)
2524 IDirectDrawSurfaceImpl *surfImpl = (IDirectDrawSurfaceImpl *)surf;
2525 struct wined3d_resource_desc wined3d_desc;
2526 struct wined3d_resource *wined3d_resource;
2527 IDirectDrawImpl *This = surfImpl->ddraw;
2528 struct wined3d_surface *wined3d_surface;
2529 struct wined3d_swapchain *swapchain;
2530 struct wined3d_clipper *clipper;
2534 TRACE("surface %p, surface_desc %p, context %p.\n",
2535 surf, desc, Context);
2537 /* For the enumeration */
2538 IDirectDrawSurface7_Release(surf);
2540 if(surfImpl->ImplType == This->ImplType) return DDENUMRET_OK; /* Continue */
2542 /* Get the objects */
2543 swapchain = surfImpl->wined3d_swapchain;
2544 surfImpl->wined3d_swapchain = NULL;
2545 wined3d_surface = surfImpl->wined3d_surface;
2547 /* get the clipper */
2548 clipper = wined3d_surface_get_clipper(wined3d_surface);
2550 /* Get the surface properties */
2551 wined3d_resource = wined3d_surface_get_resource(wined3d_surface);
2552 wined3d_resource_get_desc(wined3d_resource, &wined3d_desc);
2554 parent = wined3d_surface_get_parent(wined3d_surface);
2555 hr = wined3d_surface_create(This->wineD3DDevice, wined3d_desc.width, wined3d_desc.height,
2556 wined3d_desc.format, TRUE, FALSE, surfImpl->mipmap_level, wined3d_desc.usage, wined3d_desc.pool,
2557 wined3d_desc.multisample_type, wined3d_desc.multisample_quality, This->ImplType,
2558 parent, &ddraw_surface_wined3d_parent_ops, &surfImpl->wined3d_surface);
2561 surfImpl->wined3d_surface = wined3d_surface;
2565 wined3d_surface_set_clipper(surfImpl->wined3d_surface, clipper);
2567 /* TODO: Copy the surface content, except for render targets */
2569 /* If there's a swapchain, it owns the wined3d surfaces. So Destroy
2574 /* The backbuffers have the swapchain set as well, but the primary
2575 * owns it and destroys it. */
2576 if (surfImpl->surface_desc.ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE)
2577 IWineD3DDevice_UninitGDI(This->wineD3DDevice);
2578 surfImpl->isRenderTarget = FALSE;
2582 if (!wined3d_surface_decref(wined3d_surface))
2583 TRACE("Surface released successful, next surface\n");
2585 ERR("Something's still holding the old WineD3DSurface\n");
2588 surfImpl->ImplType = This->ImplType;
2590 return DDENUMRET_OK;
2593 /*****************************************************************************
2594 * ddraw_recreate_surfaces
2596 * A function, that converts all wineD3DSurfaces to the new implementation type
2597 * It enumerates all surfaces with IWineD3DDevice::EnumSurfaces, creates a
2598 * new WineD3DSurface, copies the content and releases the old surface
2600 *****************************************************************************/
2601 static HRESULT ddraw_recreate_surfaces(IDirectDrawImpl *This)
2603 DDSURFACEDESC2 desc;
2604 TRACE("(%p): Switch to implementation %d\n", This, This->ImplType);
2606 if(This->ImplType != SURFACE_OPENGL && This->d3d_initialized)
2608 /* Should happen almost never */
2609 FIXME("(%p) Switching to non-opengl surfaces with d3d started. Is this a bug?\n", This);
2611 IWineD3DDevice_Uninit3D(This->wineD3DDevice);
2613 /* Contrary: D3D starting is handled by the caller, because it knows the render target */
2615 memset(&desc, 0, sizeof(desc));
2616 desc.dwSize = sizeof(desc);
2618 return IDirectDraw7_EnumSurfaces(&This->IDirectDraw7_iface, 0, &desc, This,
2619 ddraw_recreate_surfaces_cb);
2622 /*****************************************************************************
2623 * ddraw_create_surface
2625 * A helper function for IDirectDraw7::CreateSurface. It creates a new surface
2626 * with the passed parameters.
2629 * DDSD: Description of the surface to create
2630 * Surf: Address to store the interface pointer at
2635 *****************************************************************************/
2636 static HRESULT ddraw_create_surface(IDirectDrawImpl *This, DDSURFACEDESC2 *pDDSD,
2637 IDirectDrawSurfaceImpl **ppSurf, UINT level)
2639 WINED3DSURFTYPE ImplType = This->ImplType;
2642 TRACE("ddraw %p, surface_desc %p, surface %p, level %u.\n",
2643 This, pDDSD, ppSurf, level);
2645 if (TRACE_ON(ddraw))
2647 TRACE(" (%p) Requesting surface desc :\n", This);
2648 DDRAW_dump_surface_desc(pDDSD);
2651 /* Select the surface type, if it wasn't choosen yet */
2652 if(ImplType == SURFACE_UNKNOWN)
2654 /* Use GL Surfaces if a D3DDEVICE Surface is requested */
2655 if(pDDSD->ddsCaps.dwCaps & DDSCAPS_3DDEVICE)
2657 TRACE("(%p) Choosing GL surfaces because a 3DDEVICE Surface was requested\n", This);
2658 ImplType = SURFACE_OPENGL;
2661 /* Otherwise use GDI surfaces for now */
2664 TRACE("(%p) Choosing GDI surfaces for 2D rendering\n", This);
2665 ImplType = SURFACE_GDI;
2668 /* Policy if all surface implementations are available:
2669 * First, check if a default type was set with winecfg. If not,
2670 * try Xrender surfaces, and use them if they work. Next, check if
2671 * accelerated OpenGL is available, and use GL surfaces in this
2672 * case. If all else fails, use GDI surfaces. If a 3DDEVICE surface
2673 * was created, always use OpenGL surfaces.
2675 * (Note: Xrender surfaces are not implemented for now, the
2676 * unaccelerated implementation uses GDI to render in Software)
2679 /* Store the type. If it needs to be changed, all WineD3DSurfaces have to
2680 * be re-created. This could be done with IDirectDrawSurface7::Restore
2682 This->ImplType = ImplType;
2686 if ((pDDSD->ddsCaps.dwCaps & DDSCAPS_3DDEVICE)
2687 && (This->ImplType != SURFACE_OPENGL)
2688 && DefaultSurfaceType == SURFACE_UNKNOWN)
2690 /* We have to change to OpenGL,
2691 * and re-create all WineD3DSurfaces
2693 ImplType = SURFACE_OPENGL;
2694 This->ImplType = ImplType;
2695 TRACE("(%p) Re-creating all surfaces\n", This);
2696 ddraw_recreate_surfaces(This);
2697 TRACE("(%p) Done recreating all surfaces\n", This);
2699 else if(This->ImplType != SURFACE_OPENGL && pDDSD->ddsCaps.dwCaps & DDSCAPS_3DDEVICE)
2701 WARN("The application requests a 3D capable surface, but a non-opengl surface was set in the registry\n");
2702 /* Do not fail surface creation, only fail 3D device creation */
2706 /* Create the Surface object */
2707 *ppSurf = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDirectDrawSurfaceImpl));
2710 ERR("(%p) Error allocating memory for a surface\n", This);
2711 return DDERR_OUTOFVIDEOMEMORY;
2714 hr = ddraw_surface_init(*ppSurf, This, pDDSD, level, ImplType);
2717 WARN("Failed to initialize surface, hr %#x.\n", hr);
2718 HeapFree(GetProcessHeap(), 0, *ppSurf);
2722 /* Increase the surface counter, and attach the surface */
2723 InterlockedIncrement(&This->surfaces);
2724 list_add_head(&This->surface_list, &(*ppSurf)->surface_list_entry);
2726 TRACE("Created surface %p.\n", *ppSurf);
2730 /*****************************************************************************
2731 * CreateAdditionalSurfaces
2733 * Creates a new mipmap chain.
2736 * root: Root surface to attach the newly created chain to
2737 * count: number of surfaces to create
2738 * DDSD: Description of the surface. Intentionally not a pointer to avoid side
2739 * effects on the caller
2740 * CubeFaceRoot: Whether the new surface is a root of a cube map face. This
2741 * creates an additional surface without the mipmapping flags
2743 *****************************************************************************/
2745 CreateAdditionalSurfaces(IDirectDrawImpl *This,
2746 IDirectDrawSurfaceImpl *root,
2748 DDSURFACEDESC2 DDSD,
2751 UINT i, j, level = 0;
2753 IDirectDrawSurfaceImpl *last = root;
2755 for(i = 0; i < count; i++)
2757 IDirectDrawSurfaceImpl *object2 = NULL;
2759 /* increase the mipmap level, but only if a mipmap is created
2760 * In this case, also halve the size
2762 if(DDSD.ddsCaps.dwCaps & DDSCAPS_MIPMAP && !CubeFaceRoot)
2765 if(DDSD.dwWidth > 1) DDSD.dwWidth /= 2;
2766 if(DDSD.dwHeight > 1) DDSD.dwHeight /= 2;
2767 /* Set the mipmap sublevel flag according to msdn */
2768 DDSD.ddsCaps.dwCaps2 |= DDSCAPS2_MIPMAPSUBLEVEL;
2772 DDSD.ddsCaps.dwCaps2 &= ~DDSCAPS2_MIPMAPSUBLEVEL;
2774 CubeFaceRoot = FALSE;
2776 hr = ddraw_create_surface(This, &DDSD, &object2, level);
2782 /* Add the new surface to the complex attachment array */
2783 for(j = 0; j < MAX_COMPLEX_ATTACHED; j++)
2785 if(last->complex_array[j]) continue;
2786 last->complex_array[j] = object2;
2791 /* Remove the (possible) back buffer cap from the new surface description,
2792 * because only one surface in the flipping chain is a back buffer, one
2793 * is a front buffer, the others are just primary surfaces.
2795 DDSD.ddsCaps.dwCaps &= ~DDSCAPS_BACKBUFFER;
2800 /* Must set all attached surfaces (e.g. mipmaps) versions as well */
2801 static void ddraw_set_surface_version(IDirectDrawSurfaceImpl *surface, UINT version)
2805 TRACE("surface %p, version %u -> %u.\n", surface, surface->version, version);
2807 surface->version = version;
2808 for (i = 0; i < MAX_COMPLEX_ATTACHED; ++i)
2810 if (!surface->complex_array[i]) break;
2811 ddraw_set_surface_version(surface->complex_array[i], version);
2813 while ((surface = surface->next_attached))
2815 ddraw_set_surface_version(surface, version);
2819 /*****************************************************************************
2820 * ddraw_attach_d3d_device
2822 * Initializes the D3D capabilities of WineD3D
2825 * primary: The primary surface for D3D
2831 *****************************************************************************/
2832 static HRESULT ddraw_attach_d3d_device(IDirectDrawImpl *ddraw, IDirectDrawSurfaceImpl *primary)
2834 WINED3DPRESENT_PARAMETERS localParameters;
2835 HWND window = ddraw->dest_window;
2838 TRACE("ddraw %p, primary %p.\n", ddraw, primary);
2840 if (!window || window == GetDesktopWindow())
2842 window = CreateWindowExA(0, DDRAW_WINDOW_CLASS_NAME, "Hidden D3D Window",
2843 WS_DISABLED, 0, 0, GetSystemMetrics(SM_CXSCREEN), GetSystemMetrics(SM_CYSCREEN),
2844 NULL, NULL, NULL, NULL);
2847 ERR("Failed to create window, last error %#x.\n", GetLastError());
2851 ShowWindow(window, SW_HIDE); /* Just to be sure */
2852 WARN("No window for the Direct3DDevice, created hidden window %p.\n", window);
2856 TRACE("Using existing window %p for Direct3D rendering.\n", window);
2858 ddraw->d3d_window = window;
2860 /* Store the future Render Target surface */
2861 ddraw->d3d_target = primary;
2863 /* Use the surface description for the device parameters, not the device
2864 * settings. The application might render to an offscreen surface. */
2865 localParameters.BackBufferWidth = primary->surface_desc.dwWidth;
2866 localParameters.BackBufferHeight = primary->surface_desc.dwHeight;
2867 localParameters.BackBufferFormat = PixelFormat_DD2WineD3D(&primary->surface_desc.u4.ddpfPixelFormat);
2868 localParameters.BackBufferCount = (primary->surface_desc.dwFlags & DDSD_BACKBUFFERCOUNT)
2869 ? primary->surface_desc.dwBackBufferCount : 0;
2870 localParameters.MultiSampleType = WINED3DMULTISAMPLE_NONE;
2871 localParameters.MultiSampleQuality = 0;
2872 localParameters.SwapEffect = WINED3DSWAPEFFECT_COPY;
2873 localParameters.hDeviceWindow = window;
2874 localParameters.Windowed = !(ddraw->cooperative_level & DDSCL_FULLSCREEN);
2875 localParameters.EnableAutoDepthStencil = TRUE;
2876 localParameters.AutoDepthStencilFormat = WINED3DFMT_D16_UNORM;
2877 localParameters.Flags = 0;
2878 localParameters.FullScreen_RefreshRateInHz = WINED3DPRESENT_RATE_DEFAULT;
2879 localParameters.PresentationInterval = WINED3DPRESENT_INTERVAL_DEFAULT;
2880 localParameters.AutoRestoreDisplayMode = FALSE;
2882 /* Set this NOW, otherwise creating the depth stencil surface will cause a
2883 * recursive loop until ram or emulated video memory is full. */
2884 ddraw->d3d_initialized = TRUE;
2885 hr = IWineD3DDevice_Init3D(ddraw->wineD3DDevice, &localParameters);
2888 ddraw->d3d_target = NULL;
2889 ddraw->d3d_initialized = FALSE;
2893 ddraw->declArraySize = 2;
2894 ddraw->decls = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*ddraw->decls) * ddraw->declArraySize);
2897 ERR("Error allocating an array for the converted vertex decls.\n");
2898 ddraw->declArraySize = 0;
2899 hr = IWineD3DDevice_Uninit3D(ddraw->wineD3DDevice);
2900 return E_OUTOFMEMORY;
2903 TRACE("Successfully initialized 3D.\n");
2908 static HRESULT ddraw_create_gdi_swapchain(IDirectDrawImpl *ddraw, IDirectDrawSurfaceImpl *primary)
2910 WINED3DPRESENT_PARAMETERS presentation_parameters;
2914 window = ddraw->dest_window;
2916 memset(&presentation_parameters, 0, sizeof(presentation_parameters));
2918 /* Use the surface description for the device parameters, not the device
2919 * settings. The application might render to an offscreen surface. */
2920 presentation_parameters.BackBufferWidth = primary->surface_desc.dwWidth;
2921 presentation_parameters.BackBufferHeight = primary->surface_desc.dwHeight;
2922 presentation_parameters.BackBufferFormat = PixelFormat_DD2WineD3D(&primary->surface_desc.u4.ddpfPixelFormat);
2923 presentation_parameters.BackBufferCount = (primary->surface_desc.dwFlags & DDSD_BACKBUFFERCOUNT)
2924 ? primary->surface_desc.dwBackBufferCount : 0;
2925 presentation_parameters.MultiSampleType = WINED3DMULTISAMPLE_NONE;
2926 presentation_parameters.MultiSampleQuality = 0;
2927 presentation_parameters.SwapEffect = WINED3DSWAPEFFECT_FLIP;
2928 presentation_parameters.hDeviceWindow = window;
2929 presentation_parameters.Windowed = !(ddraw->cooperative_level & DDSCL_FULLSCREEN);
2930 presentation_parameters.EnableAutoDepthStencil = FALSE; /* Not on GDI swapchains */
2931 presentation_parameters.AutoDepthStencilFormat = 0;
2932 presentation_parameters.Flags = 0;
2933 presentation_parameters.FullScreen_RefreshRateInHz = WINED3DPRESENT_RATE_DEFAULT;
2934 presentation_parameters.PresentationInterval = WINED3DPRESENT_INTERVAL_DEFAULT;
2935 presentation_parameters.AutoRestoreDisplayMode = FALSE;
2937 ddraw->d3d_target = primary;
2938 hr = IWineD3DDevice_InitGDI(ddraw->wineD3DDevice, &presentation_parameters);
2939 ddraw->d3d_target = NULL;
2942 WARN("Failed to initialize GDI ddraw implementation, hr %#x.\n", hr);
2943 primary->wined3d_swapchain = NULL;
2949 /*****************************************************************************
2950 * IDirectDraw7::CreateSurface
2952 * Creates a new IDirectDrawSurface object and returns its interface.
2954 * The surface connections with wined3d are a bit tricky. Basically it works
2957 * |------------------------| |-----------------|
2958 * | DDraw surface | | WineD3DSurface |
2960 * | WineD3DSurface |-------------->| |
2961 * | Child |<------------->| Parent |
2962 * |------------------------| |-----------------|
2964 * The DDraw surface is the parent of the wined3d surface, and it releases
2965 * the WineD3DSurface when the ddraw surface is destroyed.
2967 * However, for all surfaces which can be in a container in WineD3D,
2968 * we have to do this. These surfaces are usually complex surfaces,
2969 * so this concerns primary surfaces with a front and a back buffer,
2972 * |------------------------| |-----------------|
2973 * | DDraw surface | | Container |
2975 * | Child |<------------->| Parent |
2976 * | Texture |<------------->| |
2977 * | WineD3DSurface |<----| | Levels |<--|
2978 * | Complex connection | | | | |
2979 * |------------------------| | |-----------------| |
2983 * | |------------------| | |-----------------| |
2984 * | | IParent | |-------->| WineD3DSurface | |
2986 * | | Child |<------------->| Parent | |
2987 * | | | | Container |<--|
2988 * | |------------------| |-----------------| |
2990 * | |----------------------| |
2991 * | | DDraw surface 2 | |
2993 * |<->| Complex root Child | |
2995 * | | WineD3DSurface |<----| |
2996 * | |----------------------| | |
2998 * | |---------------------| | |-----------------| |
2999 * | | IParent | |----->| WineD3DSurface | |
3001 * | | Child |<---------->| Parent | |
3002 * | |---------------------| | Container |<--|
3003 * | |-----------------| |
3005 * | ---More surfaces can follow--- |
3007 * The reason is that the IWineD3DSwapchain(render target container)
3008 * and the IWineD3DTexure(Texture container) release the parents
3009 * of their surface's children, but by releasing the complex root
3010 * the surfaces which are complexly attached to it are destroyed
3011 * too. See IDirectDrawSurface::Release for a more detailed
3015 * DDSD: Description of the surface to create
3016 * Surf: Address to store the interface pointer at
3017 * UnkOuter: Basically for aggregation support, but ddraw doesn't support
3018 * aggregation, so it has to be NULL
3022 * CLASS_E_NOAGGREGATION if UnkOuter != NULL
3023 * DDERR_* if an error occurs
3025 *****************************************************************************/
3026 static HRESULT CreateSurface(IDirectDrawImpl *ddraw, DDSURFACEDESC2 *DDSD,
3027 IDirectDrawSurface7 **Surf, IUnknown *UnkOuter)
3029 IDirectDrawSurfaceImpl *object = NULL;
3031 LONG extra_surfaces = 0;
3032 DDSURFACEDESC2 desc2;
3033 WINED3DDISPLAYMODE Mode;
3034 const DWORD sysvidmem = DDSCAPS_VIDEOMEMORY | DDSCAPS_SYSTEMMEMORY;
3036 TRACE("ddraw %p, surface_desc %p, surface %p, outer_unknown %p.\n", ddraw, DDSD, Surf, UnkOuter);
3038 /* Some checks before we start */
3039 if (TRACE_ON(ddraw))
3041 TRACE(" (%p) Requesting surface desc :\n", ddraw);
3042 DDRAW_dump_surface_desc(DDSD);
3044 EnterCriticalSection(&ddraw_cs);
3046 if (UnkOuter != NULL)
3048 FIXME("(%p) : outer != NULL?\n", ddraw);
3049 LeaveCriticalSection(&ddraw_cs);
3050 return CLASS_E_NOAGGREGATION; /* unchecked */
3055 FIXME("(%p) You want to get back a surface? Don't give NULL ptrs!\n", ddraw);
3056 LeaveCriticalSection(&ddraw_cs);
3057 return E_POINTER; /* unchecked */
3060 if (!(DDSD->dwFlags & DDSD_CAPS))
3062 /* DVIDEO.DLL does forget the DDSD_CAPS flag ... *sigh* */
3063 DDSD->dwFlags |= DDSD_CAPS;
3066 if (DDSD->ddsCaps.dwCaps & DDSCAPS_ALLOCONLOAD)
3068 /* If the surface is of the 'alloconload' type, ignore the LPSURFACE field */
3069 DDSD->dwFlags &= ~DDSD_LPSURFACE;
3072 if ((DDSD->dwFlags & DDSD_LPSURFACE) && (DDSD->lpSurface == NULL))
3074 /* Frank Herbert's Dune specifies a null pointer for the surface, ignore the LPSURFACE field */
3075 WARN("(%p) Null surface pointer specified, ignore it!\n", ddraw);
3076 DDSD->dwFlags &= ~DDSD_LPSURFACE;
3079 if((DDSD->ddsCaps.dwCaps & (DDSCAPS_FLIP | DDSCAPS_PRIMARYSURFACE)) == (DDSCAPS_FLIP | DDSCAPS_PRIMARYSURFACE) &&
3080 !(ddraw->cooperative_level & DDSCL_EXCLUSIVE))
3082 TRACE("(%p): Attempt to create a flipable primary surface without DDSCL_EXCLUSIVE set\n",
3085 LeaveCriticalSection(&ddraw_cs);
3086 return DDERR_NOEXCLUSIVEMODE;
3089 if((DDSD->ddsCaps.dwCaps & (DDSCAPS_BACKBUFFER | DDSCAPS_PRIMARYSURFACE)) == (DDSCAPS_BACKBUFFER | DDSCAPS_PRIMARYSURFACE))
3091 WARN("Application wanted to create back buffer primary surface\n");
3092 LeaveCriticalSection(&ddraw_cs);
3093 return DDERR_INVALIDCAPS;
3096 if((DDSD->ddsCaps.dwCaps & sysvidmem) == sysvidmem)
3098 /* This is a special switch in ddrawex.dll, but not allowed in ddraw.dll */
3099 WARN("Application tries to put the surface in both system and video memory\n");
3100 LeaveCriticalSection(&ddraw_cs);
3102 return DDERR_INVALIDCAPS;
3105 /* Check cube maps but only if the size includes them */
3106 if (DDSD->dwSize >= sizeof(DDSURFACEDESC2))
3108 if(DDSD->ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP_ALLFACES &&
3109 !(DDSD->ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP))
3111 WARN("Cube map faces requested without cube map flag\n");
3112 LeaveCriticalSection(&ddraw_cs);
3113 return DDERR_INVALIDCAPS;
3115 if(DDSD->ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP &&
3116 (DDSD->ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP_ALLFACES) == 0)
3118 WARN("Cube map without faces requested\n");
3119 LeaveCriticalSection(&ddraw_cs);
3120 return DDERR_INVALIDPARAMS;
3123 /* Quick tests confirm those can be created, but we don't do that yet */
3124 if(DDSD->ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP &&
3125 (DDSD->ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP_ALLFACES) != DDSCAPS2_CUBEMAP_ALLFACES)
3127 FIXME("Partial cube maps not supported yet\n");
3131 /* According to the msdn this flag is ignored by CreateSurface */
3132 if (DDSD->dwSize >= sizeof(DDSURFACEDESC2))
3133 DDSD->ddsCaps.dwCaps2 &= ~DDSCAPS2_MIPMAPSUBLEVEL;
3135 /* Modify some flags */
3136 memset(&desc2, 0, sizeof(desc2));
3137 desc2.dwSize = sizeof(desc2); /* For the struct copy */
3138 DD_STRUCT_COPY_BYSIZE(&desc2, DDSD);
3139 desc2.dwSize = sizeof(desc2); /* To override a possibly smaller size */
3140 desc2.u4.ddpfPixelFormat.dwSize=sizeof(DDPIXELFORMAT); /* Just to be sure */
3142 /* Get the video mode from WineD3D - we will need it */
3143 hr = IWineD3DDevice_GetDisplayMode(ddraw->wineD3DDevice, 0, &Mode);
3146 ERR("Failed to read display mode from wined3d\n");
3147 switch(ddraw->orig_bpp)
3150 Mode.Format = WINED3DFMT_P8_UINT;
3154 Mode.Format = WINED3DFMT_B5G5R5X1_UNORM;
3158 Mode.Format = WINED3DFMT_B5G6R5_UNORM;
3162 Mode.Format = WINED3DFMT_B8G8R8_UNORM;
3166 Mode.Format = WINED3DFMT_B8G8R8X8_UNORM;
3169 Mode.Width = ddraw->orig_width;
3170 Mode.Height = ddraw->orig_height;
3173 /* No pixelformat given? Use the current screen format */
3174 if(!(desc2.dwFlags & DDSD_PIXELFORMAT))
3176 desc2.dwFlags |= DDSD_PIXELFORMAT;
3177 desc2.u4.ddpfPixelFormat.dwSize=sizeof(DDPIXELFORMAT);
3179 /* Wait: It could be a Z buffer */
3180 if(desc2.ddsCaps.dwCaps & DDSCAPS_ZBUFFER)
3182 switch(desc2.u2.dwMipMapCount) /* Who had this glorious idea? */
3185 PixelFormat_WineD3DtoDD(&desc2.u4.ddpfPixelFormat, WINED3DFMT_S1_UINT_D15_UNORM);
3188 PixelFormat_WineD3DtoDD(&desc2.u4.ddpfPixelFormat, WINED3DFMT_D16_UNORM);
3191 PixelFormat_WineD3DtoDD(&desc2.u4.ddpfPixelFormat, WINED3DFMT_X8D24_UNORM);
3194 PixelFormat_WineD3DtoDD(&desc2.u4.ddpfPixelFormat, WINED3DFMT_D32_UNORM);
3197 ERR("Unknown Z buffer bit depth\n");
3202 PixelFormat_WineD3DtoDD(&desc2.u4.ddpfPixelFormat, Mode.Format);
3206 /* No Width or no Height? Use the original screen size
3208 if(!(desc2.dwFlags & DDSD_WIDTH) ||
3209 !(desc2.dwFlags & DDSD_HEIGHT) )
3211 /* Invalid for non-render targets */
3212 if(!(desc2.ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE))
3214 WARN("Creating a non-Primary surface without Width or Height info, returning DDERR_INVALIDPARAMS\n");
3216 LeaveCriticalSection(&ddraw_cs);
3217 return DDERR_INVALIDPARAMS;
3220 desc2.dwFlags |= DDSD_WIDTH | DDSD_HEIGHT;
3221 desc2.dwWidth = Mode.Width;
3222 desc2.dwHeight = Mode.Height;
3225 if (!desc2.dwWidth || !desc2.dwHeight)
3227 LeaveCriticalSection(&ddraw_cs);
3228 return DDERR_INVALIDPARAMS;
3231 /* Mipmap count fixes */
3232 if(desc2.ddsCaps.dwCaps & DDSCAPS_MIPMAP)
3234 if(desc2.ddsCaps.dwCaps & DDSCAPS_COMPLEX)
3236 if(desc2.dwFlags & DDSD_MIPMAPCOUNT)
3238 /* Mipmap count is given, should not be 0 */
3239 if( desc2.u2.dwMipMapCount == 0 )
3241 LeaveCriticalSection(&ddraw_cs);
3242 return DDERR_INVALIDPARAMS;
3247 /* Undocumented feature: Create sublevels until
3248 * either the width or the height is 1
3250 DWORD min = desc2.dwWidth < desc2.dwHeight ?
3251 desc2.dwWidth : desc2.dwHeight;
3252 desc2.u2.dwMipMapCount = 0;
3255 desc2.u2.dwMipMapCount += 1;
3262 /* Not-complex mipmap -> Mipmapcount = 1 */
3263 desc2.u2.dwMipMapCount = 1;
3265 extra_surfaces = desc2.u2.dwMipMapCount - 1;
3267 /* There's a mipmap count in the created surface in any case */
3268 desc2.dwFlags |= DDSD_MIPMAPCOUNT;
3270 /* If no mipmap is given, the texture has only one level */
3272 /* The first surface is a front buffer, the back buffer is created afterwards */
3273 if( (desc2.dwFlags & DDSD_CAPS) && (desc2.ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE) )
3275 desc2.ddsCaps.dwCaps |= DDSCAPS_FRONTBUFFER;
3278 /* The root surface in a cube map is positive x */
3279 if(desc2.ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP)
3281 desc2.ddsCaps.dwCaps2 &= ~DDSCAPS2_CUBEMAP_ALLFACES;
3282 desc2.ddsCaps.dwCaps2 |= DDSCAPS2_CUBEMAP_POSITIVEX;
3285 /* Create the first surface */
3286 hr = ddraw_create_surface(ddraw, &desc2, &object, 0);
3289 WARN("ddraw_create_surface failed, hr %#x.\n", hr);
3290 LeaveCriticalSection(&ddraw_cs);
3293 object->is_complex_root = TRUE;
3295 *Surf = (IDirectDrawSurface7 *)object;
3297 /* Create Additional surfaces if necessary
3298 * This applies to Primary surfaces which have a back buffer count
3299 * set, but not to mipmap textures. In case of Mipmap textures,
3300 * wineD3D takes care of the creation of additional surfaces
3302 if(DDSD->dwFlags & DDSD_BACKBUFFERCOUNT)
3304 extra_surfaces = DDSD->dwBackBufferCount;
3305 desc2.ddsCaps.dwCaps &= ~DDSCAPS_FRONTBUFFER; /* It's not a front buffer */
3306 desc2.ddsCaps.dwCaps |= DDSCAPS_BACKBUFFER;
3307 desc2.dwBackBufferCount = 0;
3311 if(desc2.ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP)
3313 desc2.ddsCaps.dwCaps2 &= ~DDSCAPS2_CUBEMAP_ALLFACES;
3314 desc2.ddsCaps.dwCaps2 |= DDSCAPS2_CUBEMAP_NEGATIVEZ;
3315 hr |= CreateAdditionalSurfaces(ddraw, object, extra_surfaces + 1, desc2, TRUE);
3316 desc2.ddsCaps.dwCaps2 &= ~DDSCAPS2_CUBEMAP_NEGATIVEZ;
3317 desc2.ddsCaps.dwCaps2 |= DDSCAPS2_CUBEMAP_POSITIVEZ;
3318 hr |= CreateAdditionalSurfaces(ddraw, object, extra_surfaces + 1, desc2, TRUE);
3319 desc2.ddsCaps.dwCaps2 &= ~DDSCAPS2_CUBEMAP_POSITIVEZ;
3320 desc2.ddsCaps.dwCaps2 |= DDSCAPS2_CUBEMAP_NEGATIVEY;
3321 hr |= CreateAdditionalSurfaces(ddraw, object, extra_surfaces + 1, desc2, TRUE);
3322 desc2.ddsCaps.dwCaps2 &= ~DDSCAPS2_CUBEMAP_NEGATIVEY;
3323 desc2.ddsCaps.dwCaps2 |= DDSCAPS2_CUBEMAP_POSITIVEY;
3324 hr |= CreateAdditionalSurfaces(ddraw, object, extra_surfaces + 1, desc2, TRUE);
3325 desc2.ddsCaps.dwCaps2 &= ~DDSCAPS2_CUBEMAP_POSITIVEY;
3326 desc2.ddsCaps.dwCaps2 |= DDSCAPS2_CUBEMAP_NEGATIVEX;
3327 hr |= CreateAdditionalSurfaces(ddraw, object, extra_surfaces + 1, desc2, TRUE);
3328 desc2.ddsCaps.dwCaps2 &= ~DDSCAPS2_CUBEMAP_NEGATIVEX;
3329 desc2.ddsCaps.dwCaps2 |= DDSCAPS2_CUBEMAP_POSITIVEX;
3332 hr |= CreateAdditionalSurfaces(ddraw, object, extra_surfaces, desc2, FALSE);
3335 /* This destroys and possibly created surfaces too */
3336 IDirectDrawSurface_Release((IDirectDrawSurface7 *)object);
3337 LeaveCriticalSection(&ddraw_cs);
3341 /* If the implementation is OpenGL and there's no d3ddevice, attach a d3ddevice
3342 * But attach the d3ddevice only if the currently created surface was
3343 * a primary surface (2D app in 3D mode) or a 3DDEVICE surface (3D app)
3344 * The only case I can think of where this doesn't apply is when a
3345 * 2D app was configured by the user to run with OpenGL and it didn't create
3346 * the render target as first surface. In this case the render target creation
3347 * will cause the 3D init.
3349 if( (ddraw->ImplType == SURFACE_OPENGL) && !(ddraw->d3d_initialized) &&
3350 desc2.ddsCaps.dwCaps & (DDSCAPS_PRIMARYSURFACE | DDSCAPS_3DDEVICE) )
3352 IDirectDrawSurfaceImpl *target = object, *surface;
3355 /* Search for the primary to use as render target */
3356 LIST_FOR_EACH(entry, &ddraw->surface_list)
3358 surface = LIST_ENTRY(entry, IDirectDrawSurfaceImpl, surface_list_entry);
3359 if((surface->surface_desc.ddsCaps.dwCaps & (DDSCAPS_PRIMARYSURFACE | DDSCAPS_FRONTBUFFER)) ==
3360 (DDSCAPS_PRIMARYSURFACE | DDSCAPS_FRONTBUFFER))
3364 TRACE("Using primary %p as render target\n", target);
3369 TRACE("(%p) Attaching a D3DDevice, rendertarget = %p\n", ddraw, target);
3370 hr = ddraw_attach_d3d_device(ddraw, target);
3373 IDirectDrawSurfaceImpl *release_surf;
3374 ERR("ddraw_attach_d3d_device failed, hr %#x\n", hr);
3377 /* The before created surface structures are in an incomplete state here.
3378 * WineD3D holds the reference on the IParents, and it released them on the failure
3379 * already. So the regular release method implementation would fail on the attempt
3380 * to destroy either the IParents or the swapchain. So free the surface here.
3381 * The surface structure here is a list, not a tree, because onscreen targets
3382 * cannot be cube textures
3386 release_surf = object;
3387 object = object->complex_array[0];
3388 ddraw_surface_destroy(release_surf);
3390 LeaveCriticalSection(&ddraw_cs);
3394 else if(!(ddraw->d3d_initialized) && desc2.ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE)
3396 ddraw_create_gdi_swapchain(ddraw, object);
3399 /* Addref the ddraw interface to keep an reference for each surface */
3400 IDirectDraw7_AddRef(&ddraw->IDirectDraw7_iface);
3401 object->ifaceToRelease = (IUnknown *)&ddraw->IDirectDraw7_iface;
3403 /* Create a WineD3DTexture if a texture was requested */
3404 if (desc2.ddsCaps.dwCaps & DDSCAPS_TEXTURE)
3406 ddraw->tex_root = object;
3407 ddraw_surface_create_texture(object);
3408 ddraw->tex_root = NULL;
3411 LeaveCriticalSection(&ddraw_cs);
3415 static HRESULT WINAPI ddraw7_CreateSurface(IDirectDraw7 *iface, DDSURFACEDESC2 *surface_desc,
3416 IDirectDrawSurface7 **surface, IUnknown *outer_unknown)
3418 IDirectDrawImpl *This = impl_from_IDirectDraw7(iface);
3420 TRACE("iface %p, surface_desc %p, surface %p, outer_unknown %p.\n",
3421 iface, surface_desc, surface, outer_unknown);
3423 if(surface_desc == NULL || surface_desc->dwSize != sizeof(DDSURFACEDESC2))
3425 WARN("Application supplied invalid surface descriptor\n");
3426 return DDERR_INVALIDPARAMS;
3429 if(surface_desc->ddsCaps.dwCaps & (DDSCAPS_FRONTBUFFER | DDSCAPS_BACKBUFFER))
3431 if (TRACE_ON(ddraw))
3433 TRACE(" (%p) Requesting surface desc :\n", iface);
3434 DDRAW_dump_surface_desc(surface_desc);
3437 WARN("Application tried to create an explicit front or back buffer\n");
3438 return DDERR_INVALIDCAPS;
3441 return CreateSurface(This, surface_desc, surface, outer_unknown);
3444 static HRESULT WINAPI ddraw4_CreateSurface(IDirectDraw4 *iface,
3445 DDSURFACEDESC2 *surface_desc, IDirectDrawSurface4 **surface, IUnknown *outer_unknown)
3447 IDirectDrawImpl *This = impl_from_IDirectDraw4(iface);
3448 IDirectDrawSurfaceImpl *impl;
3451 TRACE("iface %p, surface_desc %p, surface %p, outer_unknown %p.\n",
3452 iface, surface_desc, surface, outer_unknown);
3454 if(surface_desc == NULL || surface_desc->dwSize != sizeof(DDSURFACEDESC2))
3456 WARN("Application supplied invalid surface descriptor\n");
3457 return DDERR_INVALIDPARAMS;
3460 if(surface_desc->ddsCaps.dwCaps & (DDSCAPS_FRONTBUFFER | DDSCAPS_BACKBUFFER))
3462 if (TRACE_ON(ddraw))
3464 TRACE(" (%p) Requesting surface desc :\n", iface);
3465 DDRAW_dump_surface_desc(surface_desc);
3468 WARN("Application tried to create an explicit front or back buffer\n");
3469 return DDERR_INVALIDCAPS;
3472 hr = CreateSurface(This, surface_desc, (IDirectDrawSurface7 **)surface, outer_unknown);
3473 impl = (IDirectDrawSurfaceImpl *)*surface;
3474 if (SUCCEEDED(hr) && impl)
3476 ddraw_set_surface_version(impl, 4);
3477 IDirectDraw7_Release(&This->IDirectDraw7_iface);
3478 IDirectDraw4_AddRef(iface);
3479 impl->ifaceToRelease = (IUnknown *)iface;
3485 static HRESULT WINAPI ddraw3_CreateSurface(IDirectDraw3 *iface, DDSURFACEDESC *surface_desc,
3486 IDirectDrawSurface **surface, IUnknown *outer_unknown)
3488 IDirectDrawImpl *This = impl_from_IDirectDraw3(iface);
3489 IDirectDrawSurface7 *surface7;
3490 IDirectDrawSurfaceImpl *impl;
3493 TRACE("iface %p, surface_desc %p, surface %p, outer_unknown %p.\n",
3494 iface, surface_desc, surface, outer_unknown);
3496 if(surface_desc == NULL || surface_desc->dwSize != sizeof(DDSURFACEDESC))
3498 WARN("Application supplied invalid surface descriptor\n");
3499 return DDERR_INVALIDPARAMS;
3502 if(surface_desc->ddsCaps.dwCaps & (DDSCAPS_FRONTBUFFER | DDSCAPS_BACKBUFFER))
3504 if (TRACE_ON(ddraw))
3506 TRACE(" (%p) Requesting surface desc :\n", iface);
3507 DDRAW_dump_surface_desc((LPDDSURFACEDESC2)surface_desc);
3510 WARN("Application tried to create an explicit front or back buffer\n");
3511 return DDERR_INVALIDCAPS;
3514 hr = CreateSurface(This, (DDSURFACEDESC2 *)surface_desc, &surface7, outer_unknown);
3521 impl = (IDirectDrawSurfaceImpl *)surface7;
3522 *surface = (IDirectDrawSurface *)&impl->IDirectDrawSurface3_vtbl;
3523 ddraw_set_surface_version(impl, 3);
3524 IDirectDraw7_Release(&This->IDirectDraw7_iface);
3525 IDirectDraw3_AddRef(iface);
3526 impl->ifaceToRelease = (IUnknown *)iface;
3531 static HRESULT WINAPI ddraw2_CreateSurface(IDirectDraw2 *iface,
3532 DDSURFACEDESC *surface_desc, IDirectDrawSurface **surface, IUnknown *outer_unknown)
3534 IDirectDrawImpl *This = impl_from_IDirectDraw2(iface);
3535 IDirectDrawSurface7 *surface7;
3536 IDirectDrawSurfaceImpl *impl;
3539 TRACE("iface %p, surface_desc %p, surface %p, outer_unknown %p.\n",
3540 iface, surface_desc, surface, outer_unknown);
3542 if(surface_desc == NULL || surface_desc->dwSize != sizeof(DDSURFACEDESC))
3544 WARN("Application supplied invalid surface descriptor\n");
3545 return DDERR_INVALIDPARAMS;
3548 if(surface_desc->ddsCaps.dwCaps & (DDSCAPS_FRONTBUFFER | DDSCAPS_BACKBUFFER))
3550 if (TRACE_ON(ddraw))
3552 TRACE(" (%p) Requesting surface desc :\n", iface);
3553 DDRAW_dump_surface_desc((LPDDSURFACEDESC2)surface_desc);
3556 WARN("Application tried to create an explicit front or back buffer\n");
3557 return DDERR_INVALIDCAPS;
3560 hr = CreateSurface(This, (DDSURFACEDESC2 *)surface_desc, &surface7, outer_unknown);
3567 impl = (IDirectDrawSurfaceImpl *)surface7;
3568 *surface = (IDirectDrawSurface *)&impl->IDirectDrawSurface3_vtbl;
3569 ddraw_set_surface_version(impl, 2);
3570 IDirectDraw7_Release(&This->IDirectDraw7_iface);
3571 impl->ifaceToRelease = NULL;
3576 static HRESULT WINAPI ddraw1_CreateSurface(IDirectDraw *iface,
3577 DDSURFACEDESC *surface_desc, IDirectDrawSurface **surface, IUnknown *outer_unknown)
3579 IDirectDrawImpl *This = impl_from_IDirectDraw(iface);
3580 IDirectDrawSurface7 *surface7;
3581 IDirectDrawSurfaceImpl *impl;
3584 TRACE("iface %p, surface_desc %p, surface %p, outer_unknown %p.\n",
3585 iface, surface_desc, surface, outer_unknown);
3587 if(surface_desc == NULL || surface_desc->dwSize != sizeof(DDSURFACEDESC))
3589 WARN("Application supplied invalid surface descriptor\n");
3590 return DDERR_INVALIDPARAMS;
3593 /* Remove front buffer flag, this causes failure in v7, and its added to normal
3594 * primaries anyway. */
3595 surface_desc->ddsCaps.dwCaps &= ~DDSCAPS_FRONTBUFFER;
3596 hr = CreateSurface(This, (DDSURFACEDESC2 *)surface_desc, &surface7, outer_unknown);
3603 impl = (IDirectDrawSurfaceImpl *)surface7;
3604 *surface = (IDirectDrawSurface *)&impl->IDirectDrawSurface3_vtbl;
3605 ddraw_set_surface_version(impl, 1);
3606 IDirectDraw7_Release(&This->IDirectDraw7_iface);
3607 impl->ifaceToRelease = NULL;
3612 #define DDENUMSURFACES_SEARCHTYPE (DDENUMSURFACES_CANBECREATED|DDENUMSURFACES_DOESEXIST)
3613 #define DDENUMSURFACES_MATCHTYPE (DDENUMSURFACES_ALL|DDENUMSURFACES_MATCH|DDENUMSURFACES_NOMATCH)
3616 Main_DirectDraw_DDPIXELFORMAT_Match(const DDPIXELFORMAT *requested,
3617 const DDPIXELFORMAT *provided)
3619 /* Some flags must be present in both or neither for a match. */
3620 static const DWORD must_match = DDPF_PALETTEINDEXED1 | DDPF_PALETTEINDEXED2
3621 | DDPF_PALETTEINDEXED4 | DDPF_PALETTEINDEXED8 | DDPF_FOURCC
3622 | DDPF_ZBUFFER | DDPF_STENCILBUFFER;
3624 if ((requested->dwFlags & provided->dwFlags) != requested->dwFlags)
3627 if ((requested->dwFlags & must_match) != (provided->dwFlags & must_match))
3630 if (requested->dwFlags & DDPF_FOURCC)
3631 if (requested->dwFourCC != provided->dwFourCC)
3634 if (requested->dwFlags & (DDPF_RGB|DDPF_YUV|DDPF_ZBUFFER|DDPF_ALPHA
3635 |DDPF_LUMINANCE|DDPF_BUMPDUDV))
3636 if (requested->u1.dwRGBBitCount != provided->u1.dwRGBBitCount)
3639 if (requested->dwFlags & (DDPF_RGB|DDPF_YUV|DDPF_STENCILBUFFER
3640 |DDPF_LUMINANCE|DDPF_BUMPDUDV))
3641 if (requested->u2.dwRBitMask != provided->u2.dwRBitMask)
3644 if (requested->dwFlags & (DDPF_RGB|DDPF_YUV|DDPF_ZBUFFER|DDPF_BUMPDUDV))
3645 if (requested->u3.dwGBitMask != provided->u3.dwGBitMask)
3648 /* I could be wrong about the bumpmapping. MSDN docs are vague. */
3649 if (requested->dwFlags & (DDPF_RGB|DDPF_YUV|DDPF_STENCILBUFFER
3651 if (requested->u4.dwBBitMask != provided->u4.dwBBitMask)
3654 if (requested->dwFlags & (DDPF_ALPHAPIXELS|DDPF_ZPIXELS))
3655 if (requested->u5.dwRGBAlphaBitMask != provided->u5.dwRGBAlphaBitMask)
3661 static BOOL ddraw_match_surface_desc(const DDSURFACEDESC2 *requested, const DDSURFACEDESC2 *provided)
3670 #define CMP(FLAG, FIELD) \
3671 { DDSD_##FLAG, offsetof(DDSURFACEDESC2, FIELD), \
3672 sizeof(((DDSURFACEDESC2 *)(NULL))->FIELD) }
3674 static const struct compare_info compare[] =
3676 CMP(ALPHABITDEPTH, dwAlphaBitDepth),
3677 CMP(BACKBUFFERCOUNT, dwBackBufferCount),
3679 CMP(CKDESTBLT, ddckCKDestBlt),
3680 CMP(CKDESTOVERLAY, u3 /* ddckCKDestOverlay */),
3681 CMP(CKSRCBLT, ddckCKSrcBlt),
3682 CMP(CKSRCOVERLAY, ddckCKSrcOverlay),
3683 CMP(HEIGHT, dwHeight),
3684 CMP(LINEARSIZE, u1 /* dwLinearSize */),
3685 CMP(LPSURFACE, lpSurface),
3686 CMP(MIPMAPCOUNT, u2 /* dwMipMapCount */),
3687 CMP(PITCH, u1 /* lPitch */),
3688 /* PIXELFORMAT: manual */
3689 CMP(REFRESHRATE, u2 /* dwRefreshRate */),
3690 CMP(TEXTURESTAGE, dwTextureStage),
3691 CMP(WIDTH, dwWidth),
3692 /* ZBUFFERBITDEPTH: "obsolete" */
3699 if ((requested->dwFlags & provided->dwFlags) != requested->dwFlags)
3702 for (i=0; i < sizeof(compare)/sizeof(compare[0]); i++)
3704 if (requested->dwFlags & compare[i].flag
3705 && memcmp((const char *)provided + compare[i].offset,
3706 (const char *)requested + compare[i].offset,
3707 compare[i].size) != 0)
3711 if (requested->dwFlags & DDSD_PIXELFORMAT)
3713 if (!Main_DirectDraw_DDPIXELFORMAT_Match(&requested->u4.ddpfPixelFormat,
3714 &provided->u4.ddpfPixelFormat))
3721 #undef DDENUMSURFACES_SEARCHTYPE
3722 #undef DDENUMSURFACES_MATCHTYPE
3724 struct surfacescallback_context
3726 LPDDENUMSURFACESCALLBACK func;
3730 static HRESULT CALLBACK EnumSurfacesCallbackThunk(IDirectDrawSurface7 *surface,
3731 DDSURFACEDESC2 *surface_desc, void *context)
3733 struct surfacescallback_context *cbcontext = context;
3735 return cbcontext->func((IDirectDrawSurface *)&((IDirectDrawSurfaceImpl *)surface)->IDirectDrawSurface3_vtbl,
3736 (DDSURFACEDESC *)surface_desc, cbcontext->context);
3739 /*****************************************************************************
3740 * IDirectDraw7::EnumSurfaces
3742 * Loops through all surfaces attached to this device and calls the
3743 * application callback. This can't be relayed to WineD3DDevice,
3744 * because some WineD3DSurfaces' parents are IParent objects
3747 * Flags: Some filtering flags. See IDirectDrawImpl_EnumSurfacesCallback
3748 * DDSD: Description to filter for
3749 * Context: Application-provided pointer, it's passed unmodified to the
3751 * Callback: Address to call for each surface
3754 * DDERR_INVALIDPARAMS if the callback is NULL
3757 *****************************************************************************/
3758 static HRESULT WINAPI ddraw7_EnumSurfaces(IDirectDraw7 *iface, DWORD Flags,
3759 DDSURFACEDESC2 *DDSD, void *Context, LPDDENUMSURFACESCALLBACK7 Callback)
3761 /* The surface enumeration is handled by WineDDraw,
3762 * because it keeps track of all surfaces attached to
3763 * it. The filtering is done by our callback function,
3764 * because WineDDraw doesn't handle ddraw-like surface
3767 IDirectDrawImpl *This = impl_from_IDirectDraw7(iface);
3768 IDirectDrawSurfaceImpl *surf;
3770 DDSURFACEDESC2 desc;
3771 struct list *entry, *entry2;
3773 TRACE("iface %p, flags %#x, surface_desc %p, context %p, callback %p.\n",
3774 iface, Flags, DDSD, Context, Callback);
3776 all = Flags & DDENUMSURFACES_ALL;
3777 nomatch = Flags & DDENUMSURFACES_NOMATCH;
3779 EnterCriticalSection(&ddraw_cs);
3783 LeaveCriticalSection(&ddraw_cs);
3784 return DDERR_INVALIDPARAMS;
3787 /* Use the _SAFE enumeration, the app may destroy enumerated surfaces */
3788 LIST_FOR_EACH_SAFE(entry, entry2, &This->surface_list)
3790 surf = LIST_ENTRY(entry, IDirectDrawSurfaceImpl, surface_list_entry);
3791 if (all || (nomatch != ddraw_match_surface_desc(DDSD, &surf->surface_desc)))
3793 desc = surf->surface_desc;
3794 IDirectDrawSurface7_AddRef((IDirectDrawSurface7 *)surf);
3795 if (Callback((IDirectDrawSurface7 *)surf, &desc, Context) != DDENUMRET_OK)
3797 LeaveCriticalSection(&ddraw_cs);
3802 LeaveCriticalSection(&ddraw_cs);
3806 static HRESULT WINAPI ddraw4_EnumSurfaces(IDirectDraw4 *iface, DWORD flags,
3807 DDSURFACEDESC2 *surface_desc, void *context, LPDDENUMSURFACESCALLBACK2 callback)
3809 IDirectDrawImpl *This = impl_from_IDirectDraw4(iface);
3811 TRACE("iface %p, flags %#x, surface_desc %p, context %p, callback %p.\n",
3812 iface, flags, surface_desc, context, callback);
3814 return ddraw7_EnumSurfaces(&This->IDirectDraw7_iface, flags, surface_desc, context,
3815 (LPDDENUMSURFACESCALLBACK7)callback);
3818 static HRESULT WINAPI ddraw3_EnumSurfaces(IDirectDraw3 *iface, DWORD flags,
3819 DDSURFACEDESC *surface_desc, void *context, LPDDENUMSURFACESCALLBACK callback)
3821 IDirectDrawImpl *This = impl_from_IDirectDraw3(iface);
3822 struct surfacescallback_context cbcontext;
3824 TRACE("iface %p, flags %#x, surface_desc %p, context %p, callback %p.\n",
3825 iface, flags, surface_desc, context, callback);
3827 cbcontext.func = callback;
3828 cbcontext.context = context;
3830 return ddraw7_EnumSurfaces(&This->IDirectDraw7_iface, flags, (DDSURFACEDESC2 *)surface_desc,
3831 &cbcontext, EnumSurfacesCallbackThunk);
3834 static HRESULT WINAPI ddraw2_EnumSurfaces(IDirectDraw2 *iface, DWORD flags,
3835 DDSURFACEDESC *surface_desc, void *context, LPDDENUMSURFACESCALLBACK callback)
3837 IDirectDrawImpl *This = impl_from_IDirectDraw2(iface);
3838 struct surfacescallback_context cbcontext;
3840 TRACE("iface %p, flags %#x, surface_desc %p, context %p, callback %p.\n",
3841 iface, flags, surface_desc, context, callback);
3843 cbcontext.func = callback;
3844 cbcontext.context = context;
3846 return ddraw7_EnumSurfaces(&This->IDirectDraw7_iface, flags, (DDSURFACEDESC2 *)surface_desc,
3847 &cbcontext, EnumSurfacesCallbackThunk);
3850 static HRESULT WINAPI ddraw1_EnumSurfaces(IDirectDraw *iface, DWORD flags,
3851 DDSURFACEDESC *surface_desc, void *context, LPDDENUMSURFACESCALLBACK callback)
3853 IDirectDrawImpl *This = impl_from_IDirectDraw(iface);
3854 struct surfacescallback_context cbcontext;
3856 TRACE("iface %p, flags %#x, surface_desc %p, context %p, callback %p.\n",
3857 iface, flags, surface_desc, context, callback);
3859 cbcontext.func = callback;
3860 cbcontext.context = context;
3862 return ddraw7_EnumSurfaces(&This->IDirectDraw7_iface, flags, (DDSURFACEDESC2 *)surface_desc,
3863 &cbcontext, EnumSurfacesCallbackThunk);
3866 /*****************************************************************************
3867 * DirectDrawCreateClipper (DDRAW.@)
3869 * Creates a new IDirectDrawClipper object.
3872 * Clipper: Address to write the interface pointer to
3873 * UnkOuter: For aggregation support, which ddraw doesn't have. Has to be
3877 * CLASS_E_NOAGGREGATION if UnkOuter != NULL
3878 * E_OUTOFMEMORY if allocating the object failed
3880 *****************************************************************************/
3882 DirectDrawCreateClipper(DWORD Flags,
3883 LPDIRECTDRAWCLIPPER *Clipper,
3886 IDirectDrawClipperImpl* object;
3889 TRACE("flags %#x, clipper %p, outer_unknown %p.\n",
3890 Flags, Clipper, UnkOuter);
3892 EnterCriticalSection(&ddraw_cs);
3893 if (UnkOuter != NULL)
3895 LeaveCriticalSection(&ddraw_cs);
3896 return CLASS_E_NOAGGREGATION;
3899 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
3900 sizeof(IDirectDrawClipperImpl));
3903 LeaveCriticalSection(&ddraw_cs);
3904 return E_OUTOFMEMORY;
3907 hr = ddraw_clipper_init(object);
3910 WARN("Failed to initialize clipper, hr %#x.\n", hr);
3911 HeapFree(GetProcessHeap(), 0, object);
3912 LeaveCriticalSection(&ddraw_cs);
3916 TRACE("Created clipper %p.\n", object);
3917 *Clipper = (IDirectDrawClipper *) object;
3918 LeaveCriticalSection(&ddraw_cs);
3922 /*****************************************************************************
3923 * IDirectDraw7::CreateClipper
3925 * Creates a DDraw clipper. See DirectDrawCreateClipper for details
3927 *****************************************************************************/
3928 static HRESULT WINAPI ddraw7_CreateClipper(IDirectDraw7 *iface, DWORD Flags,
3929 IDirectDrawClipper **Clipper, IUnknown *UnkOuter)
3931 TRACE("iface %p, flags %#x, clipper %p, outer_unknown %p.\n",
3932 iface, Flags, Clipper, UnkOuter);
3934 return DirectDrawCreateClipper(Flags, Clipper, UnkOuter);
3937 static HRESULT WINAPI ddraw4_CreateClipper(IDirectDraw4 *iface, DWORD flags,
3938 IDirectDrawClipper **clipper, IUnknown *outer_unknown)
3940 IDirectDrawImpl *This = impl_from_IDirectDraw4(iface);
3942 TRACE("iface %p, flags %#x, clipper %p, outer_unknown %p.\n",
3943 iface, flags, clipper, outer_unknown);
3945 return ddraw7_CreateClipper(&This->IDirectDraw7_iface, flags, clipper, outer_unknown);
3948 static HRESULT WINAPI ddraw3_CreateClipper(IDirectDraw3 *iface, DWORD flags,
3949 IDirectDrawClipper **clipper, IUnknown *outer_unknown)
3951 IDirectDrawImpl *This = impl_from_IDirectDraw3(iface);
3953 TRACE("iface %p, flags %#x, clipper %p, outer_unknown %p.\n",
3954 iface, flags, clipper, outer_unknown);
3956 return ddraw7_CreateClipper(&This->IDirectDraw7_iface, flags, clipper, outer_unknown);
3959 static HRESULT WINAPI ddraw2_CreateClipper(IDirectDraw2 *iface,
3960 DWORD flags, IDirectDrawClipper **clipper, IUnknown *outer_unknown)
3962 IDirectDrawImpl *This = impl_from_IDirectDraw2(iface);
3964 TRACE("iface %p, flags %#x, clipper %p, outer_unknown %p.\n",
3965 iface, flags, clipper, outer_unknown);
3967 return ddraw7_CreateClipper(&This->IDirectDraw7_iface, flags, clipper, outer_unknown);
3970 static HRESULT WINAPI ddraw1_CreateClipper(IDirectDraw *iface,
3971 DWORD flags, IDirectDrawClipper **clipper, IUnknown *outer_unknown)
3973 IDirectDrawImpl *This = impl_from_IDirectDraw(iface);
3975 TRACE("iface %p, flags %#x, clipper %p, outer_unknown %p.\n",
3976 iface, flags, clipper, outer_unknown);
3978 return ddraw7_CreateClipper(&This->IDirectDraw7_iface, flags, clipper, outer_unknown);
3981 /*****************************************************************************
3982 * IDirectDraw7::CreatePalette
3984 * Creates a new IDirectDrawPalette object
3987 * Flags: The flags for the new clipper
3988 * ColorTable: Color table to assign to the new clipper
3989 * Palette: Address to write the interface pointer to
3990 * UnkOuter: For aggregation support, which ddraw doesn't have. Has to be
3994 * CLASS_E_NOAGGREGATION if UnkOuter != NULL
3995 * E_OUTOFMEMORY if allocating the object failed
3997 *****************************************************************************/
3998 static HRESULT WINAPI ddraw7_CreatePalette(IDirectDraw7 *iface, DWORD Flags,
3999 PALETTEENTRY *ColorTable, IDirectDrawPalette **Palette, IUnknown *pUnkOuter)
4001 IDirectDrawImpl *This = impl_from_IDirectDraw7(iface);
4002 IDirectDrawPaletteImpl *object;
4005 TRACE("iface %p, flags %#x, color_table %p, palette %p, outer_unknown %p.\n",
4006 iface, Flags, ColorTable, Palette, pUnkOuter);
4008 EnterCriticalSection(&ddraw_cs);
4009 if(pUnkOuter != NULL)
4011 WARN("pUnkOuter is %p, returning CLASS_E_NOAGGREGATION\n", pUnkOuter);
4012 LeaveCriticalSection(&ddraw_cs);
4013 return CLASS_E_NOAGGREGATION;
4016 /* The refcount test shows that a cooplevel is required for this */
4017 if(!This->cooperative_level)
4019 WARN("No cooperative level set, returning DDERR_NOCOOPERATIVELEVELSET\n");
4020 LeaveCriticalSection(&ddraw_cs);
4021 return DDERR_NOCOOPERATIVELEVELSET;
4024 object = HeapAlloc(GetProcessHeap(), 0, sizeof(IDirectDrawPaletteImpl));
4027 ERR("Out of memory when allocating memory for a palette implementation\n");
4028 LeaveCriticalSection(&ddraw_cs);
4029 return E_OUTOFMEMORY;
4032 hr = ddraw_palette_init(object, This, Flags, ColorTable);
4035 WARN("Failed to initialize palette, hr %#x.\n", hr);
4036 HeapFree(GetProcessHeap(), 0, object);
4037 LeaveCriticalSection(&ddraw_cs);
4041 TRACE("Created palette %p.\n", object);
4042 *Palette = (IDirectDrawPalette *)object;
4043 LeaveCriticalSection(&ddraw_cs);
4047 static HRESULT WINAPI ddraw4_CreatePalette(IDirectDraw4 *iface, DWORD flags, PALETTEENTRY *entries,
4048 IDirectDrawPalette **palette, IUnknown *outer_unknown)
4050 IDirectDrawImpl *This = impl_from_IDirectDraw4(iface);
4053 TRACE("iface %p, flags %#x, entries %p, palette %p, outer_unknown %p.\n",
4054 iface, flags, entries, palette, outer_unknown);
4056 hr = ddraw7_CreatePalette(&This->IDirectDraw7_iface, flags, entries, palette, outer_unknown);
4057 if (SUCCEEDED(hr) && *palette)
4059 IDirectDrawPaletteImpl *impl = (IDirectDrawPaletteImpl *)*palette;
4060 IDirectDraw7_Release(&This->IDirectDraw7_iface);
4061 IDirectDraw4_AddRef(iface);
4062 impl->ifaceToRelease = (IUnknown *)iface;
4067 static HRESULT WINAPI ddraw3_CreatePalette(IDirectDraw3 *iface, DWORD flags,
4068 PALETTEENTRY *entries, IDirectDrawPalette **palette, IUnknown *outer_unknown)
4070 IDirectDrawImpl *This = impl_from_IDirectDraw3(iface);
4073 TRACE("iface %p, flags %#x, entries %p, palette %p, outer_unknown %p.\n",
4074 iface, flags, entries, palette, outer_unknown);
4076 hr = ddraw7_CreatePalette(&This->IDirectDraw7_iface, flags, entries, palette, outer_unknown);
4077 if (SUCCEEDED(hr) && *palette)
4079 IDirectDrawPaletteImpl *impl = (IDirectDrawPaletteImpl *)*palette;
4080 IDirectDraw7_Release(&This->IDirectDraw7_iface);
4081 IDirectDraw4_AddRef(iface);
4082 impl->ifaceToRelease = (IUnknown *)iface;
4088 static HRESULT WINAPI ddraw2_CreatePalette(IDirectDraw2 *iface, DWORD flags,
4089 PALETTEENTRY *entries, IDirectDrawPalette **palette, IUnknown *outer_unknown)
4091 IDirectDrawImpl *This = impl_from_IDirectDraw2(iface);
4094 TRACE("iface %p, flags %#x, entries %p, palette %p, outer_unknown %p.\n",
4095 iface, flags, entries, palette, outer_unknown);
4097 hr = ddraw7_CreatePalette(&This->IDirectDraw7_iface, flags, entries, palette, outer_unknown);
4098 if (SUCCEEDED(hr) && *palette)
4100 IDirectDrawPaletteImpl *impl = (IDirectDrawPaletteImpl *)*palette;
4101 IDirectDraw7_Release(&This->IDirectDraw7_iface);
4102 impl->ifaceToRelease = NULL;
4108 static HRESULT WINAPI ddraw1_CreatePalette(IDirectDraw *iface, DWORD flags,
4109 PALETTEENTRY *entries, IDirectDrawPalette **palette, IUnknown *outer_unknown)
4111 IDirectDrawImpl *This = impl_from_IDirectDraw(iface);
4114 TRACE("iface %p, flags %#x, entries %p, palette %p, outer_unknown %p.\n",
4115 iface, flags, entries, palette, outer_unknown);
4117 hr = ddraw7_CreatePalette(&This->IDirectDraw7_iface, flags, entries, palette, outer_unknown);
4118 if (SUCCEEDED(hr) && *palette)
4120 IDirectDrawPaletteImpl *impl = (IDirectDrawPaletteImpl *)*palette;
4121 IDirectDraw7_Release(&This->IDirectDraw7_iface);
4122 impl->ifaceToRelease = NULL;
4128 /*****************************************************************************
4129 * IDirectDraw7::DuplicateSurface
4131 * Duplicates a surface. The surface memory points to the same memory as
4132 * the original surface, and it's released when the last surface referencing
4133 * it is released. I guess that's beyond Wine's surface management right now
4134 * (Idea: create a new DDraw surface with the same WineD3DSurface. I need a
4135 * test application to implement this)
4138 * Src: Address of the source surface
4139 * Dest: Address to write the new surface pointer to
4142 * See IDirectDraw7::CreateSurface
4144 *****************************************************************************/
4145 static HRESULT WINAPI ddraw7_DuplicateSurface(IDirectDraw7 *iface,
4146 IDirectDrawSurface7 *Src, IDirectDrawSurface7 **Dest)
4148 IDirectDrawSurfaceImpl *Surf = (IDirectDrawSurfaceImpl *)Src;
4150 FIXME("iface %p, src %p, dst %p partial stub!\n", iface, Src, Dest);
4152 /* For now, simply create a new, independent surface */
4153 return IDirectDraw7_CreateSurface(iface,
4154 &Surf->surface_desc,
4159 static HRESULT WINAPI ddraw4_DuplicateSurface(IDirectDraw4 *iface, IDirectDrawSurface4 *src,
4160 IDirectDrawSurface4 **dst)
4162 IDirectDrawImpl *This = impl_from_IDirectDraw4(iface);
4164 TRACE("iface %p, src %p, dst %p.\n", iface, src, dst);
4166 return ddraw7_DuplicateSurface(&This->IDirectDraw7_iface, (IDirectDrawSurface7 *)src,
4167 (IDirectDrawSurface7 **)dst);
4170 static HRESULT WINAPI ddraw3_DuplicateSurface(IDirectDraw3 *iface, IDirectDrawSurface *src,
4171 IDirectDrawSurface **dst)
4173 IDirectDrawImpl *This = impl_from_IDirectDraw3(iface);
4174 IDirectDrawSurface7 *src7, *dst7;
4177 TRACE("iface %p, src %p, dst %p.\n", iface, src, dst);
4178 src7 = (IDirectDrawSurface7 *)surface_from_surface3((IDirectDrawSurface3 *)src);
4179 hr = ddraw7_DuplicateSurface(&This->IDirectDraw7_iface, src7, &dst7);
4182 *dst = (IDirectDrawSurface *)&((IDirectDrawSurfaceImpl *)dst7)->IDirectDrawSurface3_vtbl;
4186 static HRESULT WINAPI ddraw2_DuplicateSurface(IDirectDraw2 *iface,
4187 IDirectDrawSurface *src, IDirectDrawSurface **dst)
4189 IDirectDrawImpl *This = impl_from_IDirectDraw2(iface);
4190 IDirectDrawSurface7 *src7, *dst7;
4193 TRACE("iface %p, src %p, dst %p.\n", iface, src, dst);
4194 src7 = (IDirectDrawSurface7 *)surface_from_surface3((IDirectDrawSurface3 *)src);
4195 hr = ddraw7_DuplicateSurface(&This->IDirectDraw7_iface, src7, &dst7);
4198 *dst = (IDirectDrawSurface *)&((IDirectDrawSurfaceImpl *)dst7)->IDirectDrawSurface3_vtbl;
4202 static HRESULT WINAPI ddraw1_DuplicateSurface(IDirectDraw *iface, IDirectDrawSurface *src,
4203 IDirectDrawSurface **dst)
4205 IDirectDrawImpl *This = impl_from_IDirectDraw(iface);
4206 IDirectDrawSurface7 *src7, *dst7;
4209 TRACE("iface %p, src %p, dst %p.\n", iface, src, dst);
4210 src7 = (IDirectDrawSurface7 *)surface_from_surface3((IDirectDrawSurface3 *)src);
4211 hr = ddraw7_DuplicateSurface(&This->IDirectDraw7_iface, src7, &dst7);
4214 *dst = (IDirectDrawSurface *)&((IDirectDrawSurfaceImpl *)dst7)->IDirectDrawSurface3_vtbl;
4218 /*****************************************************************************
4219 * IDirect3D7::EnumDevices
4221 * The EnumDevices method for IDirect3D7. It enumerates all supported
4222 * D3D7 devices. Currently the T&L, HAL and RGB devices are enumerated.
4225 * callback: Function to call for each enumerated device
4226 * context: Pointer to pass back to the app
4229 * D3D_OK, or the return value of the GetCaps call
4231 *****************************************************************************/
4232 static HRESULT WINAPI d3d7_EnumDevices(IDirect3D7 *iface, LPD3DENUMDEVICESCALLBACK7 callback, void *context)
4234 char interface_name_tnl[] = "WINE Direct3D7 Hardware Transform and Lighting acceleration using WineD3D";
4235 char device_name_tnl[] = "Wine D3D7 T&L HAL";
4236 char interface_name_hal[] = "WINE Direct3D7 Hardware acceleration using WineD3D";
4237 char device_name_hal[] = "Wine D3D7 HAL";
4238 char interface_name_rgb[] = "WINE Direct3D7 RGB Software Emulation using WineD3D";
4239 char device_name_rgb[] = "Wine D3D7 RGB";
4241 IDirectDrawImpl *This = impl_from_IDirect3D7(iface);
4242 D3DDEVICEDESC7 device_desc7;
4243 D3DDEVICEDESC device_desc1;
4246 TRACE("iface %p, callback %p, context %p.\n", iface, callback, context);
4248 EnterCriticalSection(&ddraw_cs);
4250 hr = IDirect3DImpl_GetCaps(This->wineD3D, &device_desc1, &device_desc7);
4253 LeaveCriticalSection(&ddraw_cs);
4256 callback(interface_name_tnl, device_name_tnl, &device_desc7, context);
4258 device_desc7.deviceGUID = IID_IDirect3DHALDevice;
4259 callback(interface_name_hal, device_name_hal, &device_desc7, context);
4261 device_desc7.deviceGUID = IID_IDirect3DRGBDevice;
4262 callback(interface_name_rgb, device_name_rgb, &device_desc7, context);
4264 TRACE("End of enumeration.\n");
4266 LeaveCriticalSection(&ddraw_cs);
4271 /*****************************************************************************
4272 * IDirect3D3::EnumDevices
4274 * Enumerates all supported Direct3DDevice interfaces. This is the
4275 * implementation for Direct3D 1 to Direc3D 3, Version 7 has its own.
4277 * Version 1, 2 and 3
4280 * callback: Application-provided routine to call for each enumerated device
4281 * Context: Pointer to pass to the callback
4284 * D3D_OK on success,
4285 * The result of IDirect3DImpl_GetCaps if it failed
4287 *****************************************************************************/
4288 static HRESULT WINAPI d3d3_EnumDevices(IDirect3D3 *iface, LPD3DENUMDEVICESCALLBACK callback, void *context)
4290 static CHAR wined3d_description[] = "Wine D3DDevice using WineD3D and OpenGL";
4292 IDirectDrawImpl *This = impl_from_IDirect3D3(iface);
4293 D3DDEVICEDESC device_desc1, hal_desc, hel_desc;
4294 D3DDEVICEDESC7 device_desc7;
4297 /* Some games (Motoracer 2 demo) have the bad idea to modify the device
4298 * name string. Let's put the string in a sufficiently sized array in
4299 * writable memory. */
4300 char device_name[50];
4301 strcpy(device_name,"Direct3D HEL");
4303 TRACE("iface %p, callback %p, context %p.\n", iface, callback, context);
4305 EnterCriticalSection(&ddraw_cs);
4307 hr = IDirect3DImpl_GetCaps(This->wineD3D, &device_desc1, &device_desc7);
4310 LeaveCriticalSection(&ddraw_cs);
4314 /* Do I have to enumerate the reference id? Note from old d3d7:
4315 * "It seems that enumerating the reference IID on Direct3D 1 games
4316 * (AvP / Motoracer2) breaks them". So do not enumerate this iid in V1
4318 * There's a registry key HKLM\Software\Microsoft\Direct3D\Drivers,
4319 * EnumReference which enables / disables enumerating the reference
4320 * rasterizer. It's a DWORD, 0 means disabled, 2 means enabled. The
4321 * enablerefrast.reg and disablerefrast.reg files in the DirectX 7.0 sdk
4322 * demo directory suggest this.
4324 * Some games(GTA 2) seem to use the second enumerated device, so I have
4325 * to enumerate at least 2 devices. So enumerate the reference device to
4328 * Other games (Rollcage) tell emulation and hal device apart by certain
4329 * flags. Rollcage expects D3DPTEXTURECAPS_POW2 to be set (yeah, it is a
4330 * limitation flag), and it refuses all devices that have the perspective
4331 * flag set. This way it refuses the emulation device, and HAL devices
4332 * never have POW2 unset in d3d7 on windows. */
4333 if (This->d3dversion != 1)
4335 static CHAR reference_description[] = "RGB Direct3D emulation";
4337 TRACE("Enumerating WineD3D D3DDevice interface.\n");
4338 hal_desc = device_desc1;
4339 hel_desc = device_desc1;
4340 /* The rgb device has the pow2 flag set in the hel caps, but not in the hal caps. */
4341 hal_desc.dpcLineCaps.dwTextureCaps &= ~(D3DPTEXTURECAPS_POW2
4342 | D3DPTEXTURECAPS_NONPOW2CONDITIONAL | D3DPTEXTURECAPS_PERSPECTIVE);
4343 hal_desc.dpcTriCaps.dwTextureCaps &= ~(D3DPTEXTURECAPS_POW2
4344 | D3DPTEXTURECAPS_NONPOW2CONDITIONAL | D3DPTEXTURECAPS_PERSPECTIVE);
4345 hr = callback((GUID *)&IID_IDirect3DRGBDevice, reference_description,
4346 device_name, &hal_desc, &hel_desc, context);
4347 if (hr != D3DENUMRET_OK)
4349 TRACE("Application cancelled the enumeration.\n");
4350 LeaveCriticalSection(&ddraw_cs);
4355 strcpy(device_name,"Direct3D HAL");
4357 TRACE("Enumerating HAL Direct3D device.\n");
4358 hal_desc = device_desc1;
4359 hel_desc = device_desc1;
4360 /* The hal device does not have the pow2 flag set in hel, but in hal. */
4361 hel_desc.dpcLineCaps.dwTextureCaps &= ~(D3DPTEXTURECAPS_POW2
4362 | D3DPTEXTURECAPS_NONPOW2CONDITIONAL | D3DPTEXTURECAPS_PERSPECTIVE);
4363 hel_desc.dpcTriCaps.dwTextureCaps &= ~(D3DPTEXTURECAPS_POW2
4364 | D3DPTEXTURECAPS_NONPOW2CONDITIONAL | D3DPTEXTURECAPS_PERSPECTIVE);
4365 hr = callback((GUID *)&IID_IDirect3DHALDevice, wined3d_description,
4366 device_name, &hal_desc, &hel_desc, context);
4367 if (hr != D3DENUMRET_OK)
4369 TRACE("Application cancelled the enumeration.\n");
4370 LeaveCriticalSection(&ddraw_cs);
4374 TRACE("End of enumeration.\n");
4376 LeaveCriticalSection(&ddraw_cs);
4380 static HRESULT WINAPI d3d2_EnumDevices(IDirect3D2 *iface, LPD3DENUMDEVICESCALLBACK callback, void *context)
4382 IDirectDrawImpl *This = impl_from_IDirect3D2(iface);
4384 TRACE("iface %p, callback %p, context %p.\n", iface, callback, context);
4386 return d3d3_EnumDevices(&This->IDirect3D3_iface, callback, context);
4389 static HRESULT WINAPI d3d1_EnumDevices(IDirect3D *iface, LPD3DENUMDEVICESCALLBACK callback, void *context)
4391 IDirectDrawImpl *This = impl_from_IDirect3D(iface);
4393 TRACE("iface %p, callback %p, context %p.\n", iface, callback, context);
4395 return d3d3_EnumDevices(&This->IDirect3D3_iface, callback, context);
4398 /*****************************************************************************
4399 * IDirect3D3::CreateLight
4401 * Creates an IDirect3DLight interface. This interface is used in
4402 * Direct3D3 or earlier for lighting. In Direct3D7 it has been replaced
4403 * by the DIRECT3DLIGHT7 structure. Wine's Direct3DLight implementation
4404 * uses the IDirect3DDevice7 interface with D3D7 lights.
4406 * Version 1, 2 and 3
4409 * light: Address to store the new interface pointer
4410 * outer_unknown: Basically for aggregation, but ddraw doesn't support it.
4415 * DDERR_OUTOFMEMORY if memory allocation failed
4416 * CLASS_E_NOAGGREGATION if outer_unknown != NULL
4418 *****************************************************************************/
4419 static HRESULT WINAPI d3d3_CreateLight(IDirect3D3 *iface, IDirect3DLight **light,
4420 IUnknown *outer_unknown)
4422 IDirectDrawImpl *This = impl_from_IDirect3D3(iface);
4423 IDirect3DLightImpl *object;
4425 TRACE("iface %p, light %p, outer_unknown %p.\n", iface, light, outer_unknown);
4427 if (outer_unknown) return CLASS_E_NOAGGREGATION;
4429 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*object));
4432 ERR("Failed to allocate light memory.\n");
4433 return DDERR_OUTOFMEMORY;
4436 d3d_light_init(object, This);
4438 TRACE("Created light %p.\n", object);
4439 *light = (IDirect3DLight *)object;
4444 static HRESULT WINAPI d3d2_CreateLight(IDirect3D2 *iface, IDirect3DLight **light, IUnknown *outer_unknown)
4446 IDirectDrawImpl *This = impl_from_IDirect3D2(iface);
4448 TRACE("iface %p, light %p, outer_unknown %p.\n", iface, light, outer_unknown);
4450 return d3d3_CreateLight(&This->IDirect3D3_iface, light, outer_unknown);
4453 static HRESULT WINAPI d3d1_CreateLight(IDirect3D *iface, IDirect3DLight **light, IUnknown *outer_unknown)
4455 IDirectDrawImpl *This = impl_from_IDirect3D(iface);
4457 TRACE("iface %p, light %p, outer_unknown %p.\n", iface, light, outer_unknown);
4459 return d3d3_CreateLight(&This->IDirect3D3_iface, light, outer_unknown);
4462 /*****************************************************************************
4463 * IDirect3D3::CreateMaterial
4465 * Creates an IDirect3DMaterial interface. This interface is used by Direct3D3
4466 * and older versions. The IDirect3DMaterial implementation wraps its
4467 * functionality to IDirect3DDevice7::SetMaterial and friends.
4469 * Version 1, 2 and 3
4472 * material: Address to store the new interface's pointer to
4473 * outer_unknown: Basically for aggregation, but ddraw doesn't support it.
4478 * DDERR_OUTOFMEMORY if memory allocation failed
4479 * CLASS_E_NOAGGREGATION if outer_unknown != NULL
4481 *****************************************************************************/
4482 static HRESULT WINAPI d3d3_CreateMaterial(IDirect3D3 *iface, IDirect3DMaterial3 **material,
4483 IUnknown *outer_unknown)
4485 IDirectDrawImpl *This = impl_from_IDirect3D3(iface);
4486 IDirect3DMaterialImpl *object;
4488 TRACE("iface %p, material %p, outer_unknown %p.\n", iface, material, outer_unknown);
4490 if (outer_unknown) return CLASS_E_NOAGGREGATION;
4492 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*object));
4495 ERR("Failed to allocate material memory.\n");
4496 return DDERR_OUTOFMEMORY;
4499 d3d_material_init(object, This);
4501 TRACE("Created material %p.\n", object);
4502 *material = (IDirect3DMaterial3 *)object;
4507 static HRESULT WINAPI d3d2_CreateMaterial(IDirect3D2 *iface, IDirect3DMaterial2 **material, IUnknown *outer_unknown)
4509 IDirectDrawImpl *This = impl_from_IDirect3D2(iface);
4510 IDirect3DMaterial3 *material3;
4513 TRACE("iface %p, material %p, outer_unknown %p.\n", iface, material, outer_unknown);
4515 hr = d3d3_CreateMaterial(&This->IDirect3D3_iface, &material3, outer_unknown);
4516 *material = material3 ? (IDirect3DMaterial2 *)&((IDirect3DMaterialImpl *)material3)->IDirect3DMaterial2_vtbl : NULL;
4518 TRACE("Returning material %p.\n", *material);
4523 static HRESULT WINAPI d3d1_CreateMaterial(IDirect3D *iface, IDirect3DMaterial **material, IUnknown *outer_unknown)
4525 IDirect3DMaterial3 *material3;
4528 IDirectDrawImpl *This = impl_from_IDirect3D(iface);
4530 TRACE("iface %p, material %p, outer_unknown %p.\n", iface, material, outer_unknown);
4532 hr = d3d3_CreateMaterial(&This->IDirect3D3_iface, &material3, outer_unknown);
4533 *material = material3 ? (IDirect3DMaterial *)&((IDirect3DMaterialImpl *)material3)->IDirect3DMaterial_vtbl : NULL;
4535 TRACE("Returning material %p.\n", *material);
4540 /*****************************************************************************
4541 * IDirect3D3::CreateViewport
4543 * Creates an IDirect3DViewport interface. This interface is used
4544 * by Direct3D and earlier versions for Viewport management. In Direct3D7
4545 * it has been replaced by a viewport structure and
4546 * IDirect3DDevice7::*Viewport. Wine's IDirect3DViewport implementation
4547 * uses the IDirect3DDevice7 methods for its functionality
4550 * Viewport: Address to store the new interface pointer
4551 * outer_unknown: Basically for aggregation, but ddraw doesn't support it.
4556 * DDERR_OUTOFMEMORY if memory allocation failed
4557 * CLASS_E_NOAGGREGATION if outer_unknown != NULL
4559 *****************************************************************************/
4560 static HRESULT WINAPI d3d3_CreateViewport(IDirect3D3 *iface, IDirect3DViewport3 **viewport,
4561 IUnknown *outer_unknown)
4563 IDirectDrawImpl *This = impl_from_IDirect3D3(iface);
4564 IDirect3DViewportImpl *object;
4566 TRACE("iface %p, viewport %p, outer_unknown %p.\n", iface, viewport, outer_unknown);
4568 if (outer_unknown) return CLASS_E_NOAGGREGATION;
4570 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*object));
4573 ERR("Failed to allocate viewport memory.\n");
4574 return DDERR_OUTOFMEMORY;
4577 d3d_viewport_init(object, This);
4579 TRACE("Created viewport %p.\n", object);
4580 *viewport = (IDirect3DViewport3 *)object;
4585 static HRESULT WINAPI d3d2_CreateViewport(IDirect3D2 *iface, IDirect3DViewport2 **viewport, IUnknown *outer_unknown)
4587 IDirectDrawImpl *This = impl_from_IDirect3D2(iface);
4589 TRACE("iface %p, viewport %p, outer_unknown %p.\n", iface, viewport, outer_unknown);
4591 return d3d3_CreateViewport(&This->IDirect3D3_iface, (IDirect3DViewport3 **)viewport,
4595 static HRESULT WINAPI d3d1_CreateViewport(IDirect3D *iface, IDirect3DViewport **viewport, IUnknown *outer_unknown)
4597 IDirectDrawImpl *This = impl_from_IDirect3D(iface);
4599 TRACE("iface %p, viewport %p, outer_unknown %p.\n", iface, viewport, outer_unknown);
4601 return d3d3_CreateViewport(&This->IDirect3D3_iface, (IDirect3DViewport3 **)viewport,
4605 /*****************************************************************************
4606 * IDirect3D3::FindDevice
4608 * This method finds a device with the requested properties and returns a
4609 * device description
4613 * fds: Describes the requested device characteristics
4614 * fdr: Returns the device description
4618 * DDERR_INVALIDPARAMS if no device was found
4620 *****************************************************************************/
4621 static HRESULT WINAPI d3d3_FindDevice(IDirect3D3 *iface, D3DFINDDEVICESEARCH *fds, D3DFINDDEVICERESULT *fdr)
4623 IDirectDrawImpl *This = impl_from_IDirect3D3(iface);
4624 D3DDEVICEDESC7 desc7;
4625 D3DDEVICEDESC desc1;
4628 TRACE("iface %p, fds %p, fdr %p.\n", iface, fds, fdr);
4630 if (!fds || !fdr) return DDERR_INVALIDPARAMS;
4632 if (fds->dwSize != sizeof(D3DFINDDEVICESEARCH)
4633 || fdr->dwSize != sizeof(D3DFINDDEVICERESULT))
4634 return DDERR_INVALIDPARAMS;
4636 if ((fds->dwFlags & D3DFDS_COLORMODEL)
4637 && fds->dcmColorModel != D3DCOLOR_RGB)
4639 WARN("Trying to request a non-RGB D3D color model. Not supported.\n");
4640 return DDERR_INVALIDPARAMS; /* No real idea what to return here :-) */
4643 if (fds->dwFlags & D3DFDS_GUID)
4645 TRACE("Trying to match guid %s.\n", debugstr_guid(&(fds->guid)));
4646 if (!IsEqualGUID(&IID_D3DDEVICE_WineD3D, &fds->guid)
4647 && !IsEqualGUID(&IID_IDirect3DHALDevice, &fds->guid)
4648 && !IsEqualGUID(&IID_IDirect3DRGBDevice, &fds->guid))
4650 WARN("No match for this GUID.\n");
4651 return DDERR_NOTFOUND;
4656 hr = IDirect3DImpl_GetCaps(This->wineD3D, &desc1, &desc7);
4657 if (hr != D3D_OK) return hr;
4659 /* Now return our own GUID */
4660 fdr->guid = IID_D3DDEVICE_WineD3D;
4661 fdr->ddHwDesc = desc1;
4662 fdr->ddSwDesc = desc1;
4664 TRACE("Returning Wine's wined3d device with (undumped) capabilities.\n");
4669 static HRESULT WINAPI d3d2_FindDevice(IDirect3D2 *iface, D3DFINDDEVICESEARCH *fds, D3DFINDDEVICERESULT *fdr)
4671 IDirectDrawImpl *This = impl_from_IDirect3D2(iface);
4673 TRACE("iface %p, fds %p, fdr %p.\n", iface, fds, fdr);
4675 return d3d3_FindDevice(&This->IDirect3D3_iface, fds, fdr);
4678 static HRESULT WINAPI d3d1_FindDevice(IDirect3D *iface, D3DFINDDEVICESEARCH *fds, D3DFINDDEVICERESULT *fdr)
4680 IDirectDrawImpl *This = impl_from_IDirect3D(iface);
4682 TRACE("iface %p, fds %p, fdr %p.\n", iface, fds, fdr);
4684 return d3d3_FindDevice(&This->IDirect3D3_iface, fds, fdr);
4687 /*****************************************************************************
4688 * IDirect3D7::CreateDevice
4690 * Creates an IDirect3DDevice7 interface.
4692 * Version 2, 3 and 7. IDirect3DDevice 1 interfaces are interfaces to
4693 * DirectDraw surfaces and are created with
4694 * IDirectDrawSurface::QueryInterface. This method uses CreateDevice to
4695 * create the device object and QueryInterfaces for IDirect3DDevice
4698 * refiid: IID of the device to create
4699 * Surface: Initial rendertarget
4700 * Device: Address to return the interface pointer
4704 * DDERR_OUTOFMEMORY if memory allocation failed
4705 * DDERR_INVALIDPARAMS if a device exists already
4707 *****************************************************************************/
4708 static HRESULT WINAPI d3d7_CreateDevice(IDirect3D7 *iface, REFCLSID riid,
4709 IDirectDrawSurface7 *surface, IDirect3DDevice7 **device)
4711 IDirectDrawSurfaceImpl *target = (IDirectDrawSurfaceImpl *)surface;
4712 IDirectDrawImpl *This = impl_from_IDirect3D7(iface);
4713 IDirect3DDeviceImpl *object;
4716 TRACE("iface %p, riid %s, surface %p, device %p.\n", iface, debugstr_guid(riid), surface, device);
4718 EnterCriticalSection(&ddraw_cs);
4721 /* Fail device creation if non-opengl surfaces are used. */
4722 if (This->ImplType != SURFACE_OPENGL)
4724 ERR("The application wants to create a Direct3D device, but non-opengl surfaces are set in the registry.\n");
4725 ERR("Please set the surface implementation to opengl or autodetection to allow 3D rendering.\n");
4727 /* We only hit this path if a default surface is set in the registry. Incorrect autodetection
4728 * is caught in CreateSurface or QueryInterface. */
4729 LeaveCriticalSection(&ddraw_cs);
4733 if (This->d3ddevice)
4735 FIXME("Only one Direct3D device per DirectDraw object supported.\n");
4736 LeaveCriticalSection(&ddraw_cs);
4737 return DDERR_INVALIDPARAMS;
4740 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*object));
4743 ERR("Failed to allocate device memory.\n");
4744 LeaveCriticalSection(&ddraw_cs);
4745 return DDERR_OUTOFMEMORY;
4748 hr = d3d_device_init(object, This, target);
4751 WARN("Failed to initialize device, hr %#x.\n", hr);
4752 HeapFree(GetProcessHeap(), 0, object);
4753 LeaveCriticalSection(&ddraw_cs);
4757 TRACE("Created device %p.\n", object);
4758 *device = (IDirect3DDevice7 *)object;
4760 LeaveCriticalSection(&ddraw_cs);
4764 static HRESULT WINAPI d3d3_CreateDevice(IDirect3D3 *iface, REFCLSID riid,
4765 IDirectDrawSurface4 *surface, IDirect3DDevice3 **device, IUnknown *outer_unknown)
4767 IDirectDrawImpl *This = impl_from_IDirect3D3(iface);
4770 TRACE("iface %p, riid %s, surface %p, device %p, outer_unknown %p.\n",
4771 iface, debugstr_guid(riid), surface, device, outer_unknown);
4773 if (outer_unknown) return CLASS_E_NOAGGREGATION;
4775 hr = d3d7_CreateDevice(&This->IDirect3D7_iface, riid, (IDirectDrawSurface7 *)surface,
4776 (IDirect3DDevice7 **)device);
4777 if (*device) *device = (IDirect3DDevice3 *)&((IDirect3DDeviceImpl *)*device)->IDirect3DDevice3_vtbl;
4782 static HRESULT WINAPI d3d2_CreateDevice(IDirect3D2 *iface, REFCLSID riid,
4783 IDirectDrawSurface *surface, IDirect3DDevice2 **device)
4785 IDirectDrawImpl *This = impl_from_IDirect3D2(iface);
4788 TRACE("iface %p, riid %s, surface %p, device %p.\n",
4789 iface, debugstr_guid(riid), surface, device);
4791 hr = d3d7_CreateDevice(&This->IDirect3D7_iface, riid,
4792 surface ? (IDirectDrawSurface7 *)surface_from_surface3((IDirectDrawSurface3 *)surface) : NULL,
4793 (IDirect3DDevice7 **)device);
4794 if (*device) *device = (IDirect3DDevice2 *)&((IDirect3DDeviceImpl *)*device)->IDirect3DDevice2_vtbl;
4799 /*****************************************************************************
4800 * IDirect3D7::CreateVertexBuffer
4802 * Creates a new vertex buffer object and returns a IDirect3DVertexBuffer7
4808 * desc: Requested Vertex buffer properties
4809 * vertex_buffer: Address to return the interface pointer at
4810 * flags: Some flags, should be 0
4814 * DDERR_OUTOFMEMORY if memory allocation failed
4815 * The return value of IWineD3DDevice::CreateVertexBuffer if this call fails
4816 * DDERR_INVALIDPARAMS if desc or vertex_buffer are NULL
4818 *****************************************************************************/
4819 static HRESULT WINAPI d3d7_CreateVertexBuffer(IDirect3D7 *iface, D3DVERTEXBUFFERDESC *desc,
4820 IDirect3DVertexBuffer7 **vertex_buffer, DWORD flags)
4822 IDirectDrawImpl *This = impl_from_IDirect3D7(iface);
4823 IDirect3DVertexBufferImpl *object;
4826 TRACE("iface %p, desc %p, vertex_buffer %p, flags %#x.\n",
4827 iface, desc, vertex_buffer, flags);
4829 if (!vertex_buffer || !desc) return DDERR_INVALIDPARAMS;
4831 TRACE("Vertex buffer description:\n");
4832 TRACE(" dwSize %u\n", desc->dwSize);
4833 TRACE(" dwCaps %#x\n", desc->dwCaps);
4834 TRACE(" FVF %#x\n", desc->dwFVF);
4835 TRACE(" dwNumVertices %u\n", desc->dwNumVertices);
4837 /* Now create the vertex buffer */
4838 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*object));
4841 ERR("Failed to allocate vertex buffer memory.\n");
4842 return DDERR_OUTOFMEMORY;
4845 hr = d3d_vertex_buffer_init(object, This, desc);
4848 WARN("Failed to initialize vertex buffer, hr %#x.\n", hr);
4849 HeapFree(GetProcessHeap(), 0, object);
4853 TRACE("Created vertex buffer %p.\n", object);
4854 *vertex_buffer = (IDirect3DVertexBuffer7 *)object;
4859 static HRESULT WINAPI d3d3_CreateVertexBuffer(IDirect3D3 *iface, D3DVERTEXBUFFERDESC *desc,
4860 IDirect3DVertexBuffer **vertex_buffer, DWORD flags, IUnknown *outer_unknown)
4862 IDirectDrawImpl *This = impl_from_IDirect3D3(iface);
4865 TRACE("iface %p, desc %p, vertex_buffer %p, flags %#x, outer_unknown %p.\n",
4866 iface, desc, vertex_buffer, flags, outer_unknown);
4868 if (outer_unknown) return CLASS_E_NOAGGREGATION;
4870 hr = d3d7_CreateVertexBuffer(&This->IDirect3D7_iface, desc,
4871 (IDirect3DVertexBuffer7 **)vertex_buffer, flags);
4873 *vertex_buffer = (IDirect3DVertexBuffer *)&((IDirect3DVertexBufferImpl *)*vertex_buffer)->IDirect3DVertexBuffer_vtbl;
4878 /*****************************************************************************
4879 * IDirect3D7::EnumZBufferFormats
4881 * Enumerates all supported Z buffer pixel formats
4887 * callback: callback to call for each pixel format
4888 * context: Pointer to pass back to the callback
4892 * DDERR_INVALIDPARAMS if callback is NULL
4893 * For details, see IWineD3DDevice::EnumZBufferFormats
4895 *****************************************************************************/
4896 static HRESULT WINAPI d3d7_EnumZBufferFormats(IDirect3D7 *iface, REFCLSID device_iid,
4897 LPD3DENUMPIXELFORMATSCALLBACK callback, void *context)
4899 IDirectDrawImpl *This = impl_from_IDirect3D7(iface);
4900 WINED3DDISPLAYMODE d3ddm;
4901 WINED3DDEVTYPE type;
4905 /* Order matters. Specifically, BattleZone II (full version) expects the
4906 * 16-bit depth formats to be listed before the 24 and 32 ones. */
4907 static const enum wined3d_format_id formats[] =
4909 WINED3DFMT_S1_UINT_D15_UNORM,
4910 WINED3DFMT_D16_UNORM,
4911 WINED3DFMT_X8D24_UNORM,
4912 WINED3DFMT_S4X4_UINT_D24_UNORM,
4913 WINED3DFMT_D24_UNORM_S8_UINT,
4914 WINED3DFMT_D32_UNORM,
4917 TRACE("iface %p, device_iid %s, callback %p, context %p.\n",
4918 iface, debugstr_guid(device_iid), callback, context);
4920 if (!callback) return DDERR_INVALIDPARAMS;
4922 if (IsEqualGUID(device_iid, &IID_IDirect3DHALDevice)
4923 || IsEqualGUID(device_iid, &IID_IDirect3DTnLHalDevice)
4924 || IsEqualGUID(device_iid, &IID_D3DDEVICE_WineD3D))
4926 TRACE("Asked for HAL device.\n");
4927 type = WINED3DDEVTYPE_HAL;
4929 else if (IsEqualGUID(device_iid, &IID_IDirect3DRGBDevice)
4930 || IsEqualGUID(device_iid, &IID_IDirect3DMMXDevice))
4932 TRACE("Asked for SW device.\n");
4933 type = WINED3DDEVTYPE_SW;
4935 else if (IsEqualGUID(device_iid, &IID_IDirect3DRefDevice))
4937 TRACE("Asked for REF device.\n");
4938 type = WINED3DDEVTYPE_REF;
4940 else if (IsEqualGUID(device_iid, &IID_IDirect3DNullDevice))
4942 TRACE("Asked for NULLREF device.\n");
4943 type = WINED3DDEVTYPE_NULLREF;
4947 FIXME("Unexpected device GUID %s.\n", debugstr_guid(device_iid));
4948 type = WINED3DDEVTYPE_HAL;
4951 EnterCriticalSection(&ddraw_cs);
4952 /* We need an adapter format from somewhere to please wined3d and WGL.
4953 * Use the current display mode. So far all cards offer the same depth
4954 * stencil format for all modes, but if some do not and applications do
4955 * not like that we'll have to find some workaround, like iterating over
4956 * all imaginable formats and collecting all the depth stencil formats we
4958 hr = IWineD3DDevice_GetDisplayMode(This->wineD3DDevice, 0, &d3ddm);
4960 for (i = 0; i < (sizeof(formats) / sizeof(*formats)); ++i)
4962 hr = wined3d_check_device_format(This->wineD3D, WINED3DADAPTER_DEFAULT, type, d3ddm.Format,
4963 WINED3DUSAGE_DEPTHSTENCIL, WINED3DRTYPE_SURFACE, formats[i], SURFACE_OPENGL);
4966 DDPIXELFORMAT pformat;
4968 memset(&pformat, 0, sizeof(pformat));
4969 pformat.dwSize = sizeof(pformat);
4970 PixelFormat_WineD3DtoDD(&pformat, formats[i]);
4972 TRACE("Enumerating wined3d format %#x.\n", formats[i]);
4973 hr = callback(&pformat, context);
4974 if (hr != DDENUMRET_OK)
4976 TRACE("Format enumeration cancelled by application.\n");
4977 LeaveCriticalSection(&ddraw_cs);
4982 TRACE("End of enumeration.\n");
4984 LeaveCriticalSection(&ddraw_cs);
4988 static HRESULT WINAPI d3d3_EnumZBufferFormats(IDirect3D3 *iface, REFCLSID device_iid,
4989 LPD3DENUMPIXELFORMATSCALLBACK callback, void *context)
4991 IDirectDrawImpl *This = impl_from_IDirect3D3(iface);
4993 TRACE("iface %p, device_iid %s, callback %p, context %p.\n",
4994 iface, debugstr_guid(device_iid), callback, context);
4996 return d3d7_EnumZBufferFormats(&This->IDirect3D7_iface, device_iid, callback, context);
4999 /*****************************************************************************
5000 * IDirect3D7::EvictManagedTextures
5002 * Removes all managed textures (=surfaces with DDSCAPS2_TEXTUREMANAGE or
5003 * DDSCAPS2_D3DTEXTUREMANAGE caps) to be removed from video memory.
5008 * D3D_OK, because it's a stub
5010 *****************************************************************************/
5011 static HRESULT WINAPI d3d7_EvictManagedTextures(IDirect3D7 *iface)
5013 FIXME("iface %p stub!\n", iface);
5015 /* TODO: Just enumerate resources using IWineD3DDevice_EnumResources(),
5016 * then unload surfaces / textures. */
5021 static HRESULT WINAPI d3d3_EvictManagedTextures(IDirect3D3 *iface)
5023 IDirectDrawImpl *This = impl_from_IDirect3D3(iface);
5025 TRACE("iface %p.\n", iface);
5027 return d3d7_EvictManagedTextures(&This->IDirect3D7_iface);
5030 /*****************************************************************************
5031 * IDirect3DImpl_GetCaps
5033 * This function retrieves the device caps from wined3d
5034 * and converts it into a D3D7 and D3D - D3D3 structure
5035 * This is a helper function called from various places in ddraw
5038 * wined3d: The interface to get the caps from
5039 * desc1: Old D3D <3 structure to fill (needed)
5040 * desc7: D3D7 device desc structure to fill (needed)
5043 * D3D_OK on success, or the return value of IWineD3D::GetCaps
5045 *****************************************************************************/
5046 HRESULT IDirect3DImpl_GetCaps(const struct wined3d *wined3d, D3DDEVICEDESC *desc1, D3DDEVICEDESC7 *desc7)
5048 WINED3DCAPS wined3d_caps;
5051 TRACE("wined3d %p, desc1 %p, desc7 %p.\n", wined3d, desc1, desc7);
5053 memset(&wined3d_caps, 0, sizeof(wined3d_caps));
5055 EnterCriticalSection(&ddraw_cs);
5056 hr = wined3d_get_device_caps(wined3d, 0, WINED3DDEVTYPE_HAL, &wined3d_caps);
5057 LeaveCriticalSection(&ddraw_cs);
5060 WARN("Failed to get device caps, hr %#x.\n", hr);
5064 /* Copy the results into the d3d7 and d3d3 structures */
5065 desc7->dwDevCaps = wined3d_caps.DevCaps;
5066 desc7->dpcLineCaps.dwMiscCaps = wined3d_caps.PrimitiveMiscCaps;
5067 desc7->dpcLineCaps.dwRasterCaps = wined3d_caps.RasterCaps;
5068 desc7->dpcLineCaps.dwZCmpCaps = wined3d_caps.ZCmpCaps;
5069 desc7->dpcLineCaps.dwSrcBlendCaps = wined3d_caps.SrcBlendCaps;
5070 desc7->dpcLineCaps.dwDestBlendCaps = wined3d_caps.DestBlendCaps;
5071 desc7->dpcLineCaps.dwAlphaCmpCaps = wined3d_caps.AlphaCmpCaps;
5072 desc7->dpcLineCaps.dwShadeCaps = wined3d_caps.ShadeCaps;
5073 desc7->dpcLineCaps.dwTextureCaps = wined3d_caps.TextureCaps;
5074 desc7->dpcLineCaps.dwTextureFilterCaps = wined3d_caps.TextureFilterCaps;
5075 desc7->dpcLineCaps.dwTextureAddressCaps = wined3d_caps.TextureAddressCaps;
5077 desc7->dwMaxTextureWidth = wined3d_caps.MaxTextureWidth;
5078 desc7->dwMaxTextureHeight = wined3d_caps.MaxTextureHeight;
5080 desc7->dwMaxTextureRepeat = wined3d_caps.MaxTextureRepeat;
5081 desc7->dwMaxTextureAspectRatio = wined3d_caps.MaxTextureAspectRatio;
5082 desc7->dwMaxAnisotropy = wined3d_caps.MaxAnisotropy;
5083 desc7->dvMaxVertexW = wined3d_caps.MaxVertexW;
5085 desc7->dvGuardBandLeft = wined3d_caps.GuardBandLeft;
5086 desc7->dvGuardBandTop = wined3d_caps.GuardBandTop;
5087 desc7->dvGuardBandRight = wined3d_caps.GuardBandRight;
5088 desc7->dvGuardBandBottom = wined3d_caps.GuardBandBottom;
5090 desc7->dvExtentsAdjust = wined3d_caps.ExtentsAdjust;
5091 desc7->dwStencilCaps = wined3d_caps.StencilCaps;
5093 desc7->dwFVFCaps = wined3d_caps.FVFCaps;
5094 desc7->dwTextureOpCaps = wined3d_caps.TextureOpCaps;
5096 desc7->dwVertexProcessingCaps = wined3d_caps.VertexProcessingCaps;
5097 desc7->dwMaxActiveLights = wined3d_caps.MaxActiveLights;
5099 /* Remove all non-d3d7 caps */
5100 desc7->dwDevCaps &= (
5101 D3DDEVCAPS_FLOATTLVERTEX | D3DDEVCAPS_SORTINCREASINGZ | D3DDEVCAPS_SORTDECREASINGZ |
5102 D3DDEVCAPS_SORTEXACT | D3DDEVCAPS_EXECUTESYSTEMMEMORY | D3DDEVCAPS_EXECUTEVIDEOMEMORY |
5103 D3DDEVCAPS_TLVERTEXSYSTEMMEMORY | D3DDEVCAPS_TLVERTEXVIDEOMEMORY | D3DDEVCAPS_TEXTURESYSTEMMEMORY |
5104 D3DDEVCAPS_TEXTUREVIDEOMEMORY | D3DDEVCAPS_DRAWPRIMTLVERTEX | D3DDEVCAPS_CANRENDERAFTERFLIP |
5105 D3DDEVCAPS_TEXTURENONLOCALVIDMEM | D3DDEVCAPS_DRAWPRIMITIVES2 | D3DDEVCAPS_SEPARATETEXTUREMEMORIES |
5106 D3DDEVCAPS_DRAWPRIMITIVES2EX | D3DDEVCAPS_HWTRANSFORMANDLIGHT | D3DDEVCAPS_CANBLTSYSTONONLOCAL |
5107 D3DDEVCAPS_HWRASTERIZATION);
5109 desc7->dwStencilCaps &= (
5110 D3DSTENCILCAPS_KEEP | D3DSTENCILCAPS_ZERO | D3DSTENCILCAPS_REPLACE |
5111 D3DSTENCILCAPS_INCRSAT | D3DSTENCILCAPS_DECRSAT | D3DSTENCILCAPS_INVERT |
5112 D3DSTENCILCAPS_INCR | D3DSTENCILCAPS_DECR);
5116 desc7->dwTextureOpCaps &= (
5117 D3DTEXOPCAPS_DISABLE | D3DTEXOPCAPS_SELECTARG1 | D3DTEXOPCAPS_SELECTARG2 |
5118 D3DTEXOPCAPS_MODULATE | D3DTEXOPCAPS_MODULATE2X | D3DTEXOPCAPS_MODULATE4X |
5119 D3DTEXOPCAPS_ADD | D3DTEXOPCAPS_ADDSIGNED | D3DTEXOPCAPS_ADDSIGNED2X |
5120 D3DTEXOPCAPS_SUBTRACT | D3DTEXOPCAPS_ADDSMOOTH | D3DTEXOPCAPS_BLENDTEXTUREALPHA |
5121 D3DTEXOPCAPS_BLENDFACTORALPHA | D3DTEXOPCAPS_BLENDTEXTUREALPHAPM | D3DTEXOPCAPS_BLENDCURRENTALPHA |
5122 D3DTEXOPCAPS_PREMODULATE | D3DTEXOPCAPS_MODULATEALPHA_ADDCOLOR | D3DTEXOPCAPS_MODULATECOLOR_ADDALPHA |
5123 D3DTEXOPCAPS_MODULATEINVALPHA_ADDCOLOR | D3DTEXOPCAPS_MODULATEINVCOLOR_ADDALPHA | D3DTEXOPCAPS_BUMPENVMAP |
5124 D3DTEXOPCAPS_BUMPENVMAPLUMINANCE | D3DTEXOPCAPS_DOTPRODUCT3);
5126 desc7->dwVertexProcessingCaps &= (
5127 D3DVTXPCAPS_TEXGEN | D3DVTXPCAPS_MATERIALSOURCE7 | D3DVTXPCAPS_VERTEXFOG |
5128 D3DVTXPCAPS_DIRECTIONALLIGHTS | D3DVTXPCAPS_POSITIONALLIGHTS | D3DVTXPCAPS_LOCALVIEWER);
5130 desc7->dpcLineCaps.dwMiscCaps &= (
5131 D3DPMISCCAPS_MASKPLANES | D3DPMISCCAPS_MASKZ | D3DPMISCCAPS_LINEPATTERNREP |
5132 D3DPMISCCAPS_CONFORMANT | D3DPMISCCAPS_CULLNONE | D3DPMISCCAPS_CULLCW |
5133 D3DPMISCCAPS_CULLCCW);
5135 desc7->dpcLineCaps.dwRasterCaps &= (
5136 D3DPRASTERCAPS_DITHER | D3DPRASTERCAPS_ROP2 | D3DPRASTERCAPS_XOR |
5137 D3DPRASTERCAPS_PAT | D3DPRASTERCAPS_ZTEST | D3DPRASTERCAPS_SUBPIXEL |
5138 D3DPRASTERCAPS_SUBPIXELX | D3DPRASTERCAPS_FOGVERTEX | D3DPRASTERCAPS_FOGTABLE |
5139 D3DPRASTERCAPS_STIPPLE | D3DPRASTERCAPS_ANTIALIASSORTDEPENDENT | D3DPRASTERCAPS_ANTIALIASSORTINDEPENDENT |
5140 D3DPRASTERCAPS_ANTIALIASEDGES | D3DPRASTERCAPS_MIPMAPLODBIAS | D3DPRASTERCAPS_ZBIAS |
5141 D3DPRASTERCAPS_ZBUFFERLESSHSR | D3DPRASTERCAPS_FOGRANGE | D3DPRASTERCAPS_ANISOTROPY |
5142 D3DPRASTERCAPS_WBUFFER | D3DPRASTERCAPS_TRANSLUCENTSORTINDEPENDENT | D3DPRASTERCAPS_WFOG |
5143 D3DPRASTERCAPS_ZFOG);
5145 desc7->dpcLineCaps.dwZCmpCaps &= (
5146 D3DPCMPCAPS_NEVER | D3DPCMPCAPS_LESS | D3DPCMPCAPS_EQUAL |
5147 D3DPCMPCAPS_LESSEQUAL | D3DPCMPCAPS_GREATER | D3DPCMPCAPS_NOTEQUAL |
5148 D3DPCMPCAPS_GREATEREQUAL | D3DPCMPCAPS_ALWAYS);
5150 desc7->dpcLineCaps.dwSrcBlendCaps &= (
5151 D3DPBLENDCAPS_ZERO | D3DPBLENDCAPS_ONE | D3DPBLENDCAPS_SRCCOLOR |
5152 D3DPBLENDCAPS_INVSRCCOLOR | D3DPBLENDCAPS_SRCALPHA | D3DPBLENDCAPS_INVSRCALPHA |
5153 D3DPBLENDCAPS_DESTALPHA | D3DPBLENDCAPS_INVDESTALPHA | D3DPBLENDCAPS_DESTCOLOR |
5154 D3DPBLENDCAPS_INVDESTCOLOR | D3DPBLENDCAPS_SRCALPHASAT | D3DPBLENDCAPS_BOTHSRCALPHA |
5155 D3DPBLENDCAPS_BOTHINVSRCALPHA);
5157 desc7->dpcLineCaps.dwDestBlendCaps &= (
5158 D3DPBLENDCAPS_ZERO | D3DPBLENDCAPS_ONE | D3DPBLENDCAPS_SRCCOLOR |
5159 D3DPBLENDCAPS_INVSRCCOLOR | D3DPBLENDCAPS_SRCALPHA | D3DPBLENDCAPS_INVSRCALPHA |
5160 D3DPBLENDCAPS_DESTALPHA | D3DPBLENDCAPS_INVDESTALPHA | D3DPBLENDCAPS_DESTCOLOR |
5161 D3DPBLENDCAPS_INVDESTCOLOR | D3DPBLENDCAPS_SRCALPHASAT | D3DPBLENDCAPS_BOTHSRCALPHA |
5162 D3DPBLENDCAPS_BOTHINVSRCALPHA);
5164 desc7->dpcLineCaps.dwAlphaCmpCaps &= (
5165 D3DPCMPCAPS_NEVER | D3DPCMPCAPS_LESS | D3DPCMPCAPS_EQUAL |
5166 D3DPCMPCAPS_LESSEQUAL | D3DPCMPCAPS_GREATER | D3DPCMPCAPS_NOTEQUAL |
5167 D3DPCMPCAPS_GREATEREQUAL | D3DPCMPCAPS_ALWAYS);
5169 desc7->dpcLineCaps.dwShadeCaps &= (
5170 D3DPSHADECAPS_COLORFLATMONO | D3DPSHADECAPS_COLORFLATRGB | D3DPSHADECAPS_COLORGOURAUDMONO |
5171 D3DPSHADECAPS_COLORGOURAUDRGB | D3DPSHADECAPS_COLORPHONGMONO | D3DPSHADECAPS_COLORPHONGRGB |
5172 D3DPSHADECAPS_SPECULARFLATMONO | D3DPSHADECAPS_SPECULARFLATRGB | D3DPSHADECAPS_SPECULARGOURAUDMONO |
5173 D3DPSHADECAPS_SPECULARGOURAUDRGB | D3DPSHADECAPS_SPECULARPHONGMONO | D3DPSHADECAPS_SPECULARPHONGRGB |
5174 D3DPSHADECAPS_ALPHAFLATBLEND | D3DPSHADECAPS_ALPHAFLATSTIPPLED | D3DPSHADECAPS_ALPHAGOURAUDBLEND |
5175 D3DPSHADECAPS_ALPHAGOURAUDSTIPPLED | D3DPSHADECAPS_ALPHAPHONGBLEND | D3DPSHADECAPS_ALPHAPHONGSTIPPLED |
5176 D3DPSHADECAPS_FOGFLAT | D3DPSHADECAPS_FOGGOURAUD | D3DPSHADECAPS_FOGPHONG);
5178 desc7->dpcLineCaps.dwTextureCaps &= (
5179 D3DPTEXTURECAPS_PERSPECTIVE | D3DPTEXTURECAPS_POW2 | D3DPTEXTURECAPS_ALPHA |
5180 D3DPTEXTURECAPS_TRANSPARENCY | D3DPTEXTURECAPS_BORDER | D3DPTEXTURECAPS_SQUAREONLY |
5181 D3DPTEXTURECAPS_TEXREPEATNOTSCALEDBYSIZE | D3DPTEXTURECAPS_ALPHAPALETTE| D3DPTEXTURECAPS_NONPOW2CONDITIONAL |
5182 D3DPTEXTURECAPS_PROJECTED | D3DPTEXTURECAPS_CUBEMAP | D3DPTEXTURECAPS_COLORKEYBLEND);
5184 desc7->dpcLineCaps.dwTextureFilterCaps &= (
5185 D3DPTFILTERCAPS_NEAREST | D3DPTFILTERCAPS_LINEAR | D3DPTFILTERCAPS_MIPNEAREST |
5186 D3DPTFILTERCAPS_MIPLINEAR | D3DPTFILTERCAPS_LINEARMIPNEAREST | D3DPTFILTERCAPS_LINEARMIPLINEAR |
5187 D3DPTFILTERCAPS_MINFPOINT | D3DPTFILTERCAPS_MINFLINEAR | D3DPTFILTERCAPS_MINFANISOTROPIC |
5188 D3DPTFILTERCAPS_MIPFPOINT | D3DPTFILTERCAPS_MIPFLINEAR | D3DPTFILTERCAPS_MAGFPOINT |
5189 D3DPTFILTERCAPS_MAGFLINEAR | D3DPTFILTERCAPS_MAGFANISOTROPIC | D3DPTFILTERCAPS_MAGFAFLATCUBIC |
5190 D3DPTFILTERCAPS_MAGFGAUSSIANCUBIC);
5192 desc7->dpcLineCaps.dwTextureBlendCaps &= (
5193 D3DPTBLENDCAPS_DECAL | D3DPTBLENDCAPS_MODULATE | D3DPTBLENDCAPS_DECALALPHA |
5194 D3DPTBLENDCAPS_MODULATEALPHA | D3DPTBLENDCAPS_DECALMASK | D3DPTBLENDCAPS_MODULATEMASK |
5195 D3DPTBLENDCAPS_COPY | D3DPTBLENDCAPS_ADD);
5197 desc7->dpcLineCaps.dwTextureAddressCaps &= (
5198 D3DPTADDRESSCAPS_WRAP | D3DPTADDRESSCAPS_MIRROR | D3DPTADDRESSCAPS_CLAMP |
5199 D3DPTADDRESSCAPS_BORDER | D3DPTADDRESSCAPS_INDEPENDENTUV);
5201 if (!(desc7->dpcLineCaps.dwTextureCaps & D3DPTEXTURECAPS_POW2))
5203 /* DirectX7 always has the np2 flag set, no matter what the card
5204 * supports. Some old games (Rollcage) check the caps incorrectly.
5205 * If wined3d supports nonpow2 textures it also has np2 conditional
5207 desc7->dpcLineCaps.dwTextureCaps |= D3DPTEXTURECAPS_POW2 | D3DPTEXTURECAPS_NONPOW2CONDITIONAL;
5210 /* Fill the missing members, and do some fixup */
5211 desc7->dpcLineCaps.dwSize = sizeof(desc7->dpcLineCaps);
5212 desc7->dpcLineCaps.dwTextureBlendCaps = D3DPTBLENDCAPS_ADD | D3DPTBLENDCAPS_MODULATEMASK |
5213 D3DPTBLENDCAPS_COPY | D3DPTBLENDCAPS_DECAL |
5214 D3DPTBLENDCAPS_DECALALPHA | D3DPTBLENDCAPS_DECALMASK |
5215 D3DPTBLENDCAPS_MODULATE | D3DPTBLENDCAPS_MODULATEALPHA;
5216 desc7->dpcLineCaps.dwStippleWidth = 32;
5217 desc7->dpcLineCaps.dwStippleHeight = 32;
5218 /* Use the same for the TriCaps */
5219 desc7->dpcTriCaps = desc7->dpcLineCaps;
5221 desc7->dwDeviceRenderBitDepth = DDBD_16 | DDBD_24 | DDBD_32;
5222 desc7->dwDeviceZBufferBitDepth = DDBD_16 | DDBD_24;
5223 desc7->dwMinTextureWidth = 1;
5224 desc7->dwMinTextureHeight = 1;
5226 /* Convert DWORDs safely to WORDs */
5227 if (wined3d_caps.MaxTextureBlendStages > 0xffff) desc7->wMaxTextureBlendStages = 0xffff;
5228 else desc7->wMaxTextureBlendStages = (WORD)wined3d_caps.MaxTextureBlendStages;
5229 if (wined3d_caps.MaxSimultaneousTextures > 0xffff) desc7->wMaxSimultaneousTextures = 0xffff;
5230 else desc7->wMaxSimultaneousTextures = (WORD)wined3d_caps.MaxSimultaneousTextures;
5232 if (wined3d_caps.MaxUserClipPlanes > 0xffff) desc7->wMaxUserClipPlanes = 0xffff;
5233 else desc7->wMaxUserClipPlanes = (WORD)wined3d_caps.MaxUserClipPlanes;
5234 if (wined3d_caps.MaxVertexBlendMatrices > 0xffff) desc7->wMaxVertexBlendMatrices = 0xffff;
5235 else desc7->wMaxVertexBlendMatrices = (WORD)wined3d_caps.MaxVertexBlendMatrices;
5237 desc7->deviceGUID = IID_IDirect3DTnLHalDevice;
5239 desc7->dwReserved1 = 0;
5240 desc7->dwReserved2 = 0;
5241 desc7->dwReserved3 = 0;
5242 desc7->dwReserved4 = 0;
5244 /* Fill the old structure */
5245 memset(desc1, 0, sizeof(*desc1));
5246 desc1->dwSize = sizeof(D3DDEVICEDESC);
5247 desc1->dwFlags = D3DDD_COLORMODEL
5249 | D3DDD_TRANSFORMCAPS
5251 | D3DDD_LIGHTINGCAPS
5254 | D3DDD_DEVICERENDERBITDEPTH
5255 | D3DDD_DEVICEZBUFFERBITDEPTH
5256 | D3DDD_MAXBUFFERSIZE
5257 | D3DDD_MAXVERTEXCOUNT;
5259 desc1->dcmColorModel = D3DCOLOR_RGB;
5260 desc1->dwDevCaps = desc7->dwDevCaps;
5261 desc1->dtcTransformCaps.dwSize = sizeof(D3DTRANSFORMCAPS);
5262 desc1->dtcTransformCaps.dwCaps = D3DTRANSFORMCAPS_CLIP;
5263 desc1->bClipping = TRUE;
5264 desc1->dlcLightingCaps.dwSize = sizeof(D3DLIGHTINGCAPS);
5265 desc1->dlcLightingCaps.dwCaps = D3DLIGHTCAPS_DIRECTIONAL
5266 | D3DLIGHTCAPS_PARALLELPOINT
5267 | D3DLIGHTCAPS_POINT
5268 | D3DLIGHTCAPS_SPOT;
5270 desc1->dlcLightingCaps.dwLightingModel = D3DLIGHTINGMODEL_RGB;
5271 desc1->dlcLightingCaps.dwNumLights = desc7->dwMaxActiveLights;
5273 desc1->dpcLineCaps.dwSize = sizeof(D3DPRIMCAPS);
5274 desc1->dpcLineCaps.dwMiscCaps = desc7->dpcLineCaps.dwMiscCaps;
5275 desc1->dpcLineCaps.dwRasterCaps = desc7->dpcLineCaps.dwRasterCaps;
5276 desc1->dpcLineCaps.dwZCmpCaps = desc7->dpcLineCaps.dwZCmpCaps;
5277 desc1->dpcLineCaps.dwSrcBlendCaps = desc7->dpcLineCaps.dwSrcBlendCaps;
5278 desc1->dpcLineCaps.dwDestBlendCaps = desc7->dpcLineCaps.dwDestBlendCaps;
5279 desc1->dpcLineCaps.dwShadeCaps = desc7->dpcLineCaps.dwShadeCaps;
5280 desc1->dpcLineCaps.dwTextureCaps = desc7->dpcLineCaps.dwTextureCaps;
5281 desc1->dpcLineCaps.dwTextureFilterCaps = desc7->dpcLineCaps.dwTextureFilterCaps;
5282 desc1->dpcLineCaps.dwTextureBlendCaps = desc7->dpcLineCaps.dwTextureBlendCaps;
5283 desc1->dpcLineCaps.dwTextureAddressCaps = desc7->dpcLineCaps.dwTextureAddressCaps;
5284 desc1->dpcLineCaps.dwStippleWidth = desc7->dpcLineCaps.dwStippleWidth;
5285 desc1->dpcLineCaps.dwAlphaCmpCaps = desc7->dpcLineCaps.dwAlphaCmpCaps;
5287 desc1->dpcTriCaps.dwSize = sizeof(D3DPRIMCAPS);
5288 desc1->dpcTriCaps.dwMiscCaps = desc7->dpcTriCaps.dwMiscCaps;
5289 desc1->dpcTriCaps.dwRasterCaps = desc7->dpcTriCaps.dwRasterCaps;
5290 desc1->dpcTriCaps.dwZCmpCaps = desc7->dpcTriCaps.dwZCmpCaps;
5291 desc1->dpcTriCaps.dwSrcBlendCaps = desc7->dpcTriCaps.dwSrcBlendCaps;
5292 desc1->dpcTriCaps.dwDestBlendCaps = desc7->dpcTriCaps.dwDestBlendCaps;
5293 desc1->dpcTriCaps.dwShadeCaps = desc7->dpcTriCaps.dwShadeCaps;
5294 desc1->dpcTriCaps.dwTextureCaps = desc7->dpcTriCaps.dwTextureCaps;
5295 desc1->dpcTriCaps.dwTextureFilterCaps = desc7->dpcTriCaps.dwTextureFilterCaps;
5296 desc1->dpcTriCaps.dwTextureBlendCaps = desc7->dpcTriCaps.dwTextureBlendCaps;
5297 desc1->dpcTriCaps.dwTextureAddressCaps = desc7->dpcTriCaps.dwTextureAddressCaps;
5298 desc1->dpcTriCaps.dwStippleWidth = desc7->dpcTriCaps.dwStippleWidth;
5299 desc1->dpcTriCaps.dwAlphaCmpCaps = desc7->dpcTriCaps.dwAlphaCmpCaps;
5301 desc1->dwDeviceRenderBitDepth = desc7->dwDeviceRenderBitDepth;
5302 desc1->dwDeviceZBufferBitDepth = desc7->dwDeviceZBufferBitDepth;
5303 desc1->dwMaxBufferSize = 0;
5304 desc1->dwMaxVertexCount = 65536;
5305 desc1->dwMinTextureWidth = desc7->dwMinTextureWidth;
5306 desc1->dwMinTextureHeight = desc7->dwMinTextureHeight;
5307 desc1->dwMaxTextureWidth = desc7->dwMaxTextureWidth;
5308 desc1->dwMaxTextureHeight = desc7->dwMaxTextureHeight;
5309 desc1->dwMinStippleWidth = 1;
5310 desc1->dwMinStippleHeight = 1;
5311 desc1->dwMaxStippleWidth = 32;
5312 desc1->dwMaxStippleHeight = 32;
5313 desc1->dwMaxTextureRepeat = desc7->dwMaxTextureRepeat;
5314 desc1->dwMaxTextureAspectRatio = desc7->dwMaxTextureAspectRatio;
5315 desc1->dwMaxAnisotropy = desc7->dwMaxAnisotropy;
5316 desc1->dvGuardBandLeft = desc7->dvGuardBandLeft;
5317 desc1->dvGuardBandRight = desc7->dvGuardBandRight;
5318 desc1->dvGuardBandTop = desc7->dvGuardBandTop;
5319 desc1->dvGuardBandBottom = desc7->dvGuardBandBottom;
5320 desc1->dvExtentsAdjust = desc7->dvExtentsAdjust;
5321 desc1->dwStencilCaps = desc7->dwStencilCaps;
5322 desc1->dwFVFCaps = desc7->dwFVFCaps;
5323 desc1->dwTextureOpCaps = desc7->dwTextureOpCaps;
5324 desc1->wMaxTextureBlendStages = desc7->wMaxTextureBlendStages;
5325 desc1->wMaxSimultaneousTextures = desc7->wMaxSimultaneousTextures;
5330 /*****************************************************************************
5331 * IDirectDraw7 VTable
5332 *****************************************************************************/
5333 static const struct IDirectDraw7Vtbl ddraw7_vtbl =
5336 ddraw7_QueryInterface,
5341 ddraw7_CreateClipper,
5342 ddraw7_CreatePalette,
5343 ddraw7_CreateSurface,
5344 ddraw7_DuplicateSurface,
5345 ddraw7_EnumDisplayModes,
5346 ddraw7_EnumSurfaces,
5347 ddraw7_FlipToGDISurface,
5349 ddraw7_GetDisplayMode,
5350 ddraw7_GetFourCCCodes,
5351 ddraw7_GetGDISurface,
5352 ddraw7_GetMonitorFrequency,
5354 ddraw7_GetVerticalBlankStatus,
5356 ddraw7_RestoreDisplayMode,
5357 ddraw7_SetCooperativeLevel,
5358 ddraw7_SetDisplayMode,
5359 ddraw7_WaitForVerticalBlank,
5361 ddraw7_GetAvailableVidMem,
5363 ddraw7_GetSurfaceFromDC,
5365 ddraw7_RestoreAllSurfaces,
5366 ddraw7_TestCooperativeLevel,
5367 ddraw7_GetDeviceIdentifier,
5369 ddraw7_StartModeTest,
5373 static const struct IDirectDraw4Vtbl ddraw4_vtbl =
5376 ddraw4_QueryInterface,
5381 ddraw4_CreateClipper,
5382 ddraw4_CreatePalette,
5383 ddraw4_CreateSurface,
5384 ddraw4_DuplicateSurface,
5385 ddraw4_EnumDisplayModes,
5386 ddraw4_EnumSurfaces,
5387 ddraw4_FlipToGDISurface,
5389 ddraw4_GetDisplayMode,
5390 ddraw4_GetFourCCCodes,
5391 ddraw4_GetGDISurface,
5392 ddraw4_GetMonitorFrequency,
5394 ddraw4_GetVerticalBlankStatus,
5396 ddraw4_RestoreDisplayMode,
5397 ddraw4_SetCooperativeLevel,
5398 ddraw4_SetDisplayMode,
5399 ddraw4_WaitForVerticalBlank,
5401 ddraw4_GetAvailableVidMem,
5403 ddraw4_GetSurfaceFromDC,
5405 ddraw4_RestoreAllSurfaces,
5406 ddraw4_TestCooperativeLevel,
5407 ddraw4_GetDeviceIdentifier,
5410 static const struct IDirectDraw3Vtbl ddraw3_vtbl =
5413 ddraw3_QueryInterface,
5418 ddraw3_CreateClipper,
5419 ddraw3_CreatePalette,
5420 ddraw3_CreateSurface,
5421 ddraw3_DuplicateSurface,
5422 ddraw3_EnumDisplayModes,
5423 ddraw3_EnumSurfaces,
5424 ddraw3_FlipToGDISurface,
5426 ddraw3_GetDisplayMode,
5427 ddraw3_GetFourCCCodes,
5428 ddraw3_GetGDISurface,
5429 ddraw3_GetMonitorFrequency,
5431 ddraw3_GetVerticalBlankStatus,
5433 ddraw3_RestoreDisplayMode,
5434 ddraw3_SetCooperativeLevel,
5435 ddraw3_SetDisplayMode,
5436 ddraw3_WaitForVerticalBlank,
5438 ddraw3_GetAvailableVidMem,
5440 ddraw3_GetSurfaceFromDC,
5443 static const struct IDirectDraw2Vtbl ddraw2_vtbl =
5446 ddraw2_QueryInterface,
5451 ddraw2_CreateClipper,
5452 ddraw2_CreatePalette,
5453 ddraw2_CreateSurface,
5454 ddraw2_DuplicateSurface,
5455 ddraw2_EnumDisplayModes,
5456 ddraw2_EnumSurfaces,
5457 ddraw2_FlipToGDISurface,
5459 ddraw2_GetDisplayMode,
5460 ddraw2_GetFourCCCodes,
5461 ddraw2_GetGDISurface,
5462 ddraw2_GetMonitorFrequency,
5464 ddraw2_GetVerticalBlankStatus,
5466 ddraw2_RestoreDisplayMode,
5467 ddraw2_SetCooperativeLevel,
5468 ddraw2_SetDisplayMode,
5469 ddraw2_WaitForVerticalBlank,
5471 ddraw2_GetAvailableVidMem,
5474 static const struct IDirectDrawVtbl ddraw1_vtbl =
5477 ddraw1_QueryInterface,
5482 ddraw1_CreateClipper,
5483 ddraw1_CreatePalette,
5484 ddraw1_CreateSurface,
5485 ddraw1_DuplicateSurface,
5486 ddraw1_EnumDisplayModes,
5487 ddraw1_EnumSurfaces,
5488 ddraw1_FlipToGDISurface,
5490 ddraw1_GetDisplayMode,
5491 ddraw1_GetFourCCCodes,
5492 ddraw1_GetGDISurface,
5493 ddraw1_GetMonitorFrequency,
5495 ddraw1_GetVerticalBlankStatus,
5497 ddraw1_RestoreDisplayMode,
5498 ddraw1_SetCooperativeLevel,
5499 ddraw1_SetDisplayMode,
5500 ddraw1_WaitForVerticalBlank,
5503 static const struct IDirect3D7Vtbl d3d7_vtbl =
5505 /* IUnknown methods */
5506 d3d7_QueryInterface,
5509 /* IDirect3D7 methods */
5512 d3d7_CreateVertexBuffer,
5513 d3d7_EnumZBufferFormats,
5514 d3d7_EvictManagedTextures
5517 static const struct IDirect3D3Vtbl d3d3_vtbl =
5519 /* IUnknown methods */
5520 d3d3_QueryInterface,
5523 /* IDirect3D3 methods */
5526 d3d3_CreateMaterial,
5527 d3d3_CreateViewport,
5530 d3d3_CreateVertexBuffer,
5531 d3d3_EnumZBufferFormats,
5532 d3d3_EvictManagedTextures
5535 static const struct IDirect3D2Vtbl d3d2_vtbl =
5537 /* IUnknown methods */
5538 d3d2_QueryInterface,
5541 /* IDirect3D2 methods */
5544 d3d2_CreateMaterial,
5545 d3d2_CreateViewport,
5550 static const struct IDirect3DVtbl d3d1_vtbl =
5552 /* IUnknown methods */
5553 d3d1_QueryInterface,
5556 /* IDirect3D methods */
5560 d3d1_CreateMaterial,
5561 d3d1_CreateViewport,
5565 /*****************************************************************************
5568 * Finds the WineD3D vertex declaration for a specific fvf, and creates one
5569 * if none was found.
5571 * This function is in ddraw.c and the DDraw object space because D3D7
5572 * vertex buffers are created using the IDirect3D interface to the ddraw
5573 * object, so they can be valid across D3D devices(theoretically. The ddraw
5574 * object also owns the wined3d device
5578 * fvf: Fvf to find the decl for
5581 * NULL in case of an error, the vertex declaration for the FVF otherwise.
5583 *****************************************************************************/
5584 struct wined3d_vertex_declaration *ddraw_find_decl(IDirectDrawImpl *This, DWORD fvf)
5586 struct wined3d_vertex_declaration *pDecl = NULL;
5588 int p, low, high; /* deliberately signed */
5589 struct FvfToDecl *convertedDecls = This->decls;
5591 TRACE("Searching for declaration for fvf %08x... ", fvf);
5594 high = This->numConvertedDecls - 1;
5595 while(low <= high) {
5596 p = (low + high) >> 1;
5598 if(convertedDecls[p].fvf == fvf) {
5599 TRACE("found %p\n", convertedDecls[p].decl);
5600 return convertedDecls[p].decl;
5601 } else if(convertedDecls[p].fvf < fvf) {
5607 TRACE("not found. Creating and inserting at position %d.\n", low);
5609 hr = wined3d_vertex_declaration_create_from_fvf(This->wineD3DDevice,
5610 fvf, This, &ddraw_null_wined3d_parent_ops, &pDecl);
5611 if (hr != S_OK) return NULL;
5613 if(This->declArraySize == This->numConvertedDecls) {
5614 int grow = max(This->declArraySize / 2, 8);
5615 convertedDecls = HeapReAlloc(GetProcessHeap(), 0, convertedDecls,
5616 sizeof(convertedDecls[0]) * (This->numConvertedDecls + grow));
5617 if (!convertedDecls)
5619 wined3d_vertex_declaration_decref(pDecl);
5622 This->decls = convertedDecls;
5623 This->declArraySize += grow;
5626 memmove(convertedDecls + low + 1, convertedDecls + low, sizeof(convertedDecls[0]) * (This->numConvertedDecls - low));
5627 convertedDecls[low].decl = pDecl;
5628 convertedDecls[low].fvf = fvf;
5629 This->numConvertedDecls++;
5631 TRACE("Returning %p. %d decls in array\n", pDecl, This->numConvertedDecls);
5635 /* IWineD3DDeviceParent IUnknown methods */
5637 static inline struct IDirectDrawImpl *ddraw_from_device_parent(IWineD3DDeviceParent *iface)
5639 return (struct IDirectDrawImpl *)((char*)iface - FIELD_OFFSET(struct IDirectDrawImpl, device_parent_vtbl));
5642 static HRESULT STDMETHODCALLTYPE device_parent_QueryInterface(IWineD3DDeviceParent *iface, REFIID riid, void **object)
5644 struct IDirectDrawImpl *This = ddraw_from_device_parent(iface);
5645 return ddraw7_QueryInterface(&This->IDirectDraw7_iface, riid, object);
5648 static ULONG STDMETHODCALLTYPE device_parent_AddRef(IWineD3DDeviceParent *iface)
5650 struct IDirectDrawImpl *This = ddraw_from_device_parent(iface);
5651 return ddraw7_AddRef(&This->IDirectDraw7_iface);
5654 static ULONG STDMETHODCALLTYPE device_parent_Release(IWineD3DDeviceParent *iface)
5656 struct IDirectDrawImpl *This = ddraw_from_device_parent(iface);
5657 return ddraw7_Release(&This->IDirectDraw7_iface);
5660 /* IWineD3DDeviceParent methods */
5662 static void STDMETHODCALLTYPE device_parent_WineD3DDeviceCreated(IWineD3DDeviceParent *iface, IWineD3DDevice *device)
5664 TRACE("iface %p, device %p\n", iface, device);
5667 static HRESULT STDMETHODCALLTYPE device_parent_CreateSurface(IWineD3DDeviceParent *iface,
5668 void *container_parent, UINT width, UINT height, enum wined3d_format_id format, DWORD usage,
5669 WINED3DPOOL pool, UINT level, WINED3DCUBEMAP_FACES face, struct wined3d_surface **surface)
5671 struct IDirectDrawImpl *This = ddraw_from_device_parent(iface);
5672 IDirectDrawSurfaceImpl *surf = NULL;
5674 DDSCAPS2 searchcaps = This->tex_root->surface_desc.ddsCaps;
5676 TRACE("iface %p, container_parent %p, width %u, height %u, format %#x, usage %#x,\n"
5677 "\tpool %#x, level %u, face %u, surface %p\n",
5678 iface, container_parent, width, height, format, usage, pool, level, face, surface);
5680 searchcaps.dwCaps2 &= ~DDSCAPS2_CUBEMAP_ALLFACES;
5683 case WINED3DCUBEMAP_FACE_POSITIVE_X:
5684 TRACE("Asked for positive x\n");
5685 if (searchcaps.dwCaps2 & DDSCAPS2_CUBEMAP)
5687 searchcaps.dwCaps2 |= DDSCAPS2_CUBEMAP_POSITIVEX;
5689 surf = This->tex_root; break;
5690 case WINED3DCUBEMAP_FACE_NEGATIVE_X:
5691 TRACE("Asked for negative x\n");
5692 searchcaps.dwCaps2 |= DDSCAPS2_CUBEMAP_NEGATIVEX; break;
5693 case WINED3DCUBEMAP_FACE_POSITIVE_Y:
5694 TRACE("Asked for positive y\n");
5695 searchcaps.dwCaps2 |= DDSCAPS2_CUBEMAP_POSITIVEY; break;
5696 case WINED3DCUBEMAP_FACE_NEGATIVE_Y:
5697 TRACE("Asked for negative y\n");
5698 searchcaps.dwCaps2 |= DDSCAPS2_CUBEMAP_NEGATIVEY; break;
5699 case WINED3DCUBEMAP_FACE_POSITIVE_Z:
5700 TRACE("Asked for positive z\n");
5701 searchcaps.dwCaps2 |= DDSCAPS2_CUBEMAP_POSITIVEZ; break;
5702 case WINED3DCUBEMAP_FACE_NEGATIVE_Z:
5703 TRACE("Asked for negative z\n");
5704 searchcaps.dwCaps2 |= DDSCAPS2_CUBEMAP_NEGATIVEZ; break;
5705 default: {ERR("Unexpected cube face\n");} /* Stupid compiler */
5710 IDirectDrawSurface7 *attached;
5711 IDirectDrawSurface7_GetAttachedSurface((IDirectDrawSurface7 *)This->tex_root, &searchcaps, &attached);
5712 surf = (IDirectDrawSurfaceImpl *)attached;
5713 IDirectDrawSurface7_Release(attached);
5715 if (!surf) ERR("root search surface not found\n");
5717 /* Find the wanted mipmap. There are enough mipmaps in the chain */
5720 IDirectDrawSurface7 *attached;
5721 IDirectDrawSurface7_GetAttachedSurface((IDirectDrawSurface7 *)surf, &searchcaps, &attached);
5722 if(!attached) ERR("Surface not found\n");
5723 surf = (IDirectDrawSurfaceImpl *)attached;
5724 IDirectDrawSurface7_Release(attached);
5728 /* Return the surface */
5729 *surface = surf->wined3d_surface;
5730 wined3d_surface_incref(*surface);
5732 TRACE("Returning wineD3DSurface %p, it belongs to surface %p\n", *surface, surf);
5737 static HRESULT WINAPI findRenderTarget(IDirectDrawSurface7 *surface, DDSURFACEDESC2 *surface_desc, void *ctx)
5739 IDirectDrawSurfaceImpl *s = (IDirectDrawSurfaceImpl *)surface;
5740 IDirectDrawSurfaceImpl **target = ctx;
5742 if (!s->isRenderTarget)
5745 IDirectDrawSurface7_Release(surface);
5746 return DDENUMRET_CANCEL;
5749 /* Recurse into the surface tree */
5750 IDirectDrawSurface7_EnumAttachedSurfaces(surface, ctx, findRenderTarget);
5752 IDirectDrawSurface7_Release(surface);
5753 if (*target) return DDENUMRET_CANCEL;
5755 return DDENUMRET_OK;
5758 static HRESULT STDMETHODCALLTYPE device_parent_CreateRenderTarget(IWineD3DDeviceParent *iface,
5759 void *container_parent, UINT width, UINT height, enum wined3d_format_id format,
5760 WINED3DMULTISAMPLE_TYPE multisample_type, DWORD multisample_quality, BOOL lockable,
5761 struct wined3d_surface **surface)
5763 struct IDirectDrawImpl *This = ddraw_from_device_parent(iface);
5764 IDirectDrawSurfaceImpl *d3d_surface = This->d3d_target;
5765 IDirectDrawSurfaceImpl *target = NULL;
5767 TRACE("iface %p, container_parent %p, width %u, height %u, format %#x, multisample_type %#x,\n"
5768 "\tmultisample_quality %u, lockable %u, surface %p\n",
5769 iface, container_parent, width, height, format, multisample_type, multisample_quality, lockable, surface);
5771 if (d3d_surface->isRenderTarget)
5773 IDirectDrawSurface7_EnumAttachedSurfaces((IDirectDrawSurface7 *)d3d_surface, &target, findRenderTarget);
5777 target = d3d_surface;
5782 target = This->d3d_target;
5783 ERR(" (%p) : No DirectDrawSurface found to create the back buffer. Using the front buffer as back buffer. Uncertain consequences\n", This);
5786 /* TODO: Return failure if the dimensions do not match, but this shouldn't happen */
5788 *surface = target->wined3d_surface;
5789 wined3d_surface_incref(*surface);
5790 target->isRenderTarget = TRUE;
5792 TRACE("Returning wineD3DSurface %p, it belongs to surface %p\n", *surface, d3d_surface);
5797 static HRESULT STDMETHODCALLTYPE device_parent_CreateDepthStencilSurface(IWineD3DDeviceParent *iface,
5798 UINT width, UINT height, enum wined3d_format_id format, WINED3DMULTISAMPLE_TYPE multisample_type,
5799 DWORD multisample_quality, BOOL discard, struct wined3d_surface **surface)
5801 struct IDirectDrawImpl *This = ddraw_from_device_parent(iface);
5802 IDirectDrawSurfaceImpl *ddraw_surface;
5803 DDSURFACEDESC2 ddsd;
5806 TRACE("iface %p, width %u, height %u, format %#x, multisample_type %#x,\n"
5807 "\tmultisample_quality %u, discard %u, surface %p\n",
5808 iface, width, height, format, multisample_type, multisample_quality, discard, surface);
5812 /* Create a DirectDraw surface */
5813 memset(&ddsd, 0, sizeof(ddsd));
5814 ddsd.dwSize = sizeof(ddsd);
5815 ddsd.u4.ddpfPixelFormat.dwSize = sizeof(DDPIXELFORMAT);
5816 ddsd.dwFlags = DDSD_PIXELFORMAT | DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS;
5817 ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
5818 ddsd.dwHeight = height;
5819 ddsd.dwWidth = width;
5822 PixelFormat_WineD3DtoDD(&ddsd.u4.ddpfPixelFormat, format);
5826 ddsd.dwFlags ^= DDSD_PIXELFORMAT;
5829 This->depthstencil = TRUE;
5830 hr = IDirectDraw7_CreateSurface(&This->IDirectDraw7_iface, &ddsd,
5831 (IDirectDrawSurface7 **)&ddraw_surface, NULL);
5832 This->depthstencil = FALSE;
5835 ERR(" (%p) Creating a DepthStencil Surface failed, result = %x\n", This, hr);
5839 *surface = ddraw_surface->wined3d_surface;
5840 wined3d_surface_incref(*surface);
5841 IDirectDrawSurface7_Release((IDirectDrawSurface7 *)ddraw_surface);
5846 static HRESULT STDMETHODCALLTYPE device_parent_CreateVolume(IWineD3DDeviceParent *iface,
5847 void *container_parent, UINT width, UINT height, UINT depth, enum wined3d_format_id format,
5848 WINED3DPOOL pool, DWORD usage, struct wined3d_volume **volume)
5850 TRACE("iface %p, container_parent %p, width %u, height %u, depth %u, format %#x, pool %#x, usage %#x, volume %p\n",
5851 iface, container_parent, width, height, depth, format, pool, usage, volume);
5853 ERR("Not implemented!\n");
5858 static HRESULT STDMETHODCALLTYPE device_parent_CreateSwapChain(IWineD3DDeviceParent *iface,
5859 WINED3DPRESENT_PARAMETERS *present_parameters, struct wined3d_swapchain **swapchain)
5861 struct IDirectDrawImpl *This = ddraw_from_device_parent(iface);
5862 IDirectDrawSurfaceImpl *iterator;
5865 TRACE("iface %p, present_parameters %p, swapchain %p\n", iface, present_parameters, swapchain);
5867 hr = wined3d_swapchain_create(This->wineD3DDevice, present_parameters,
5868 This->ImplType, NULL, &ddraw_null_wined3d_parent_ops, swapchain);
5871 FIXME("(%p) CreateSwapChain failed, returning %#x\n", iface, hr);
5876 This->d3d_target->wined3d_swapchain = *swapchain;
5877 iterator = This->d3d_target->complex_array[0];
5880 iterator->wined3d_swapchain = *swapchain;
5881 iterator = iterator->complex_array[0];
5887 static const IWineD3DDeviceParentVtbl ddraw_wined3d_device_parent_vtbl =
5889 /* IUnknown methods */
5890 device_parent_QueryInterface,
5891 device_parent_AddRef,
5892 device_parent_Release,
5893 /* IWineD3DDeviceParent methods */
5894 device_parent_WineD3DDeviceCreated,
5895 device_parent_CreateSurface,
5896 device_parent_CreateRenderTarget,
5897 device_parent_CreateDepthStencilSurface,
5898 device_parent_CreateVolume,
5899 device_parent_CreateSwapChain,
5902 HRESULT ddraw_init(IDirectDrawImpl *ddraw, WINED3DDEVTYPE device_type)
5907 ddraw->IDirectDraw7_iface.lpVtbl = &ddraw7_vtbl;
5908 ddraw->IDirectDraw_iface.lpVtbl = &ddraw1_vtbl;
5909 ddraw->IDirectDraw2_iface.lpVtbl = &ddraw2_vtbl;
5910 ddraw->IDirectDraw3_iface.lpVtbl = &ddraw3_vtbl;
5911 ddraw->IDirectDraw4_iface.lpVtbl = &ddraw4_vtbl;
5912 ddraw->IDirect3D_iface.lpVtbl = &d3d1_vtbl;
5913 ddraw->IDirect3D2_iface.lpVtbl = &d3d2_vtbl;
5914 ddraw->IDirect3D3_iface.lpVtbl = &d3d3_vtbl;
5915 ddraw->IDirect3D7_iface.lpVtbl = &d3d7_vtbl;
5916 ddraw->device_parent_vtbl = &ddraw_wined3d_device_parent_vtbl;
5917 ddraw->numIfaces = 1;
5920 /* See comments in IDirectDrawImpl_CreateNewSurface for a description of
5922 ddraw->ImplType = DefaultSurfaceType;
5924 /* Get the current screen settings. */
5926 ddraw->orig_bpp = GetDeviceCaps(hDC, BITSPIXEL) * GetDeviceCaps(hDC, PLANES);
5928 ddraw->orig_width = GetSystemMetrics(SM_CXSCREEN);
5929 ddraw->orig_height = GetSystemMetrics(SM_CYSCREEN);
5931 ddraw->wineD3D = wined3d_create(7, &ddraw->IDirectDraw7_iface);
5932 if (!ddraw->wineD3D)
5934 WARN("Failed to create a wined3d object.\n");
5935 return E_OUTOFMEMORY;
5938 hr = wined3d_device_create(ddraw->wineD3D, WINED3DADAPTER_DEFAULT, device_type, NULL, 0,
5939 (IWineD3DDeviceParent *)&ddraw->device_parent_vtbl, &ddraw->wineD3DDevice);
5942 WARN("Failed to create a wined3d device, hr %#x.\n", hr);
5943 wined3d_decref(ddraw->wineD3D);
5947 /* Get the amount of video memory */
5948 ddraw->total_vidmem = IWineD3DDevice_GetAvailableTextureMem(ddraw->wineD3DDevice);
5950 list_init(&ddraw->surface_list);