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"
32 #define NONAMELESSUNION
38 #include "wine/exception.h"
43 #include "ddraw_private.h"
44 #include "wine/debug.h"
46 WINE_DEFAULT_DEBUG_CHANNEL(ddraw
);
48 /* Device identifier. Don't relay it to WineD3D */
49 static const DDDEVICEIDENTIFIER2 deviceidentifier
=
53 { { 0x00010001, 0x00010001 } },
55 /* a8373c10-7ac4-4deb-849a-009844d08b2d */
56 {0xa8373c10,0x7ac4,0x4deb, {0x84,0x9a,0x00,0x98,0x44,0xd0,0x8b,0x2d}},
60 static void STDMETHODCALLTYPE
ddraw_null_wined3d_object_destroyed(void *parent
) {}
62 const struct wined3d_parent_ops ddraw_null_wined3d_parent_ops
=
64 ddraw_null_wined3d_object_destroyed
,
67 static inline IDirectDrawImpl
*ddraw_from_ddraw1(IDirectDraw
*iface
)
69 return (IDirectDrawImpl
*)((char*)iface
- FIELD_OFFSET(IDirectDrawImpl
, IDirectDraw_vtbl
));
72 static inline IDirectDrawImpl
*ddraw_from_ddraw2(IDirectDraw2
*iface
)
74 return (IDirectDrawImpl
*)((char*)iface
- FIELD_OFFSET(IDirectDrawImpl
, IDirectDraw2_vtbl
));
77 static inline IDirectDrawImpl
*ddraw_from_ddraw3(IDirectDraw3
*iface
)
79 return (IDirectDrawImpl
*)((char*)iface
- FIELD_OFFSET(IDirectDrawImpl
, IDirectDraw3_vtbl
));
82 static inline IDirectDrawImpl
*ddraw_from_ddraw4(IDirectDraw4
*iface
)
84 return (IDirectDrawImpl
*)((char*)iface
- FIELD_OFFSET(IDirectDrawImpl
, IDirectDraw4_vtbl
));
87 /*****************************************************************************
89 *****************************************************************************/
91 /*****************************************************************************
92 * IDirectDraw7::QueryInterface
94 * Queries different interfaces of the DirectDraw object. It can return
95 * IDirectDraw interfaces in version 1, 2, 4 and 7, and IDirect3D interfaces
96 * in version 1, 2, 3 and 7. An IDirect3DDevice can be created with this
98 * The returned interface is AddRef()-ed before it's returned
100 * Used for version 1, 2, 4 and 7
103 * refiid: Interface ID asked for
104 * obj: Used to return the interface pointer
107 * S_OK if an interface was found
108 * E_NOINTERFACE if the requested interface wasn't found
110 *****************************************************************************/
111 static HRESULT WINAPI
ddraw7_QueryInterface(IDirectDraw7
*iface
, REFIID refiid
, void **obj
)
113 IDirectDrawImpl
*This
= (IDirectDrawImpl
*)iface
;
115 TRACE("(%p)->(%s,%p)\n", This
, debugstr_guid(refiid
), obj
);
117 /* Can change surface impl type */
118 EnterCriticalSection(&ddraw_cs
);
120 /* According to COM docs, if the QueryInterface fails, obj should be set to NULL */
125 LeaveCriticalSection(&ddraw_cs
);
126 return DDERR_INVALIDPARAMS
;
129 /* Check DirectDraw Interfaces */
130 if ( IsEqualGUID( &IID_IUnknown
, refiid
) ||
131 IsEqualGUID( &IID_IDirectDraw7
, refiid
) )
134 TRACE("(%p) Returning IDirectDraw7 interface at %p\n", This
, *obj
);
136 else if ( IsEqualGUID( &IID_IDirectDraw4
, refiid
) )
138 *obj
= &This
->IDirectDraw4_vtbl
;
139 TRACE("(%p) Returning IDirectDraw4 interface at %p\n", This
, *obj
);
141 else if ( IsEqualGUID( &IID_IDirectDraw3
, refiid
) )
143 /* This Interface exists in ddrawex.dll, it is implemented in a wrapper */
144 WARN("IDirectDraw3 is not valid in ddraw.dll\n");
146 LeaveCriticalSection(&ddraw_cs
);
147 return E_NOINTERFACE
;
149 else if ( IsEqualGUID( &IID_IDirectDraw2
, refiid
) )
151 *obj
= &This
->IDirectDraw2_vtbl
;
152 TRACE("(%p) Returning IDirectDraw2 interface at %p\n", This
, *obj
);
154 else if ( IsEqualGUID( &IID_IDirectDraw
, refiid
) )
156 *obj
= &This
->IDirectDraw_vtbl
;
157 TRACE("(%p) Returning IDirectDraw interface at %p\n", This
, *obj
);
161 * The refcount unit test revealed that an IDirect3D7 interface can only be queried
162 * from a DirectDraw object that was created as an IDirectDraw7 interface. No idea
163 * who had this idea and why. The older interfaces can query and IDirect3D version
164 * because they are all created as IDirectDraw(1). This isn't really crucial behavior,
165 * and messy to implement with the common creation function, so it has been left out here.
167 else if ( IsEqualGUID( &IID_IDirect3D
, refiid
) ||
168 IsEqualGUID( &IID_IDirect3D2
, refiid
) ||
169 IsEqualGUID( &IID_IDirect3D3
, refiid
) ||
170 IsEqualGUID( &IID_IDirect3D7
, refiid
) )
172 /* Check the surface implementation */
173 if(This
->ImplType
== SURFACE_UNKNOWN
)
175 /* Apps may create the IDirect3D Interface before the primary surface.
176 * set the surface implementation */
177 This
->ImplType
= SURFACE_OPENGL
;
178 TRACE("(%p) Choosing OpenGL surfaces because a Direct3D interface was requested\n", This
);
180 else if(This
->ImplType
!= SURFACE_OPENGL
&& DefaultSurfaceType
== SURFACE_UNKNOWN
)
182 ERR("(%p) The App is requesting a D3D device, but a non-OpenGL surface type was choosen. Prepare for trouble!\n", This
);
183 ERR(" (%p) You may want to contact wine-devel for help\n", This
);
184 /* Should I assert(0) here??? */
186 else if(This
->ImplType
!= SURFACE_OPENGL
)
188 WARN("The app requests a Direct3D interface, but non-opengl surfaces where set in winecfg\n");
189 /* Do not abort here, only reject 3D Device creation */
192 if ( IsEqualGUID( &IID_IDirect3D
, refiid
) )
194 This
->d3dversion
= 1;
195 *obj
= &This
->IDirect3D_vtbl
;
196 TRACE(" returning Direct3D interface at %p.\n", *obj
);
198 else if ( IsEqualGUID( &IID_IDirect3D2
, refiid
) )
200 This
->d3dversion
= 2;
201 *obj
= &This
->IDirect3D2_vtbl
;
202 TRACE(" returning Direct3D2 interface at %p.\n", *obj
);
204 else if ( IsEqualGUID( &IID_IDirect3D3
, refiid
) )
206 This
->d3dversion
= 3;
207 *obj
= &This
->IDirect3D3_vtbl
;
208 TRACE(" returning Direct3D3 interface at %p.\n", *obj
);
210 else if(IsEqualGUID( &IID_IDirect3D7
, refiid
))
212 This
->d3dversion
= 7;
213 *obj
= &This
->IDirect3D7_vtbl
;
214 TRACE(" returning Direct3D7 interface at %p.\n", *obj
);
217 else if (IsEqualGUID(refiid
, &IID_IWineD3DDeviceParent
))
219 *obj
= &This
->device_parent_vtbl
;
222 /* Unknown interface */
225 ERR("(%p)->(%s, %p): No interface found\n", This
, debugstr_guid(refiid
), obj
);
226 LeaveCriticalSection(&ddraw_cs
);
227 return E_NOINTERFACE
;
230 IUnknown_AddRef( (IUnknown
*) *obj
);
231 LeaveCriticalSection(&ddraw_cs
);
235 static HRESULT WINAPI
ddraw4_QueryInterface(IDirectDraw4
*iface
, REFIID riid
, void **object
)
237 TRACE("iface %p, riid %s, object %p.\n", iface
, debugstr_guid(riid
), object
);
239 return ddraw7_QueryInterface((IDirectDraw7
*)ddraw_from_ddraw4(iface
), riid
, object
);
242 static HRESULT WINAPI
ddraw3_QueryInterface(IDirectDraw3
*iface
, REFIID riid
, void **object
)
244 TRACE("iface %p, riid %s, object %p.\n", iface
, debugstr_guid(riid
), object
);
246 return ddraw7_QueryInterface((IDirectDraw7
*)ddraw_from_ddraw3(iface
), riid
, object
);
249 static HRESULT WINAPI
ddraw2_QueryInterface(IDirectDraw2
*iface
, REFIID riid
, void **object
)
251 TRACE("iface %p, riid %s, object %p.\n", iface
, debugstr_guid(riid
), object
);
253 return ddraw7_QueryInterface((IDirectDraw7
*)ddraw_from_ddraw2(iface
), riid
, object
);
256 static HRESULT WINAPI
ddraw1_QueryInterface(IDirectDraw
*iface
, REFIID riid
, void **object
)
258 TRACE("iface %p, riid %s, object %p.\n", iface
, debugstr_guid(riid
), object
);
260 return ddraw7_QueryInterface((IDirectDraw7
*)ddraw_from_ddraw1(iface
), riid
, object
);
263 /*****************************************************************************
264 * IDirectDraw7::AddRef
266 * Increases the interfaces refcount, basically
268 * DDraw refcounting is a bit tricky. The different DirectDraw interface
269 * versions have individual refcounts, but the IDirect3D interfaces do not.
270 * All interfaces are from one object, that means calling QueryInterface on an
271 * IDirectDraw7 interface for an IDirectDraw4 interface does not create a new
272 * IDirectDrawImpl object.
274 * That means all AddRef and Release implementations of IDirectDrawX work
275 * with their own counter, and IDirect3DX::AddRef thunk to IDirectDraw (1),
276 * except of IDirect3D7 which thunks to IDirectDraw7
278 * Returns: The new refcount
280 *****************************************************************************/
281 static ULONG WINAPI
ddraw7_AddRef(IDirectDraw7
*iface
)
283 IDirectDrawImpl
*This
= (IDirectDrawImpl
*)iface
;
284 ULONG ref
= InterlockedIncrement(&This
->ref7
);
286 TRACE("(%p) : incrementing IDirectDraw7 refcount from %u.\n", This
, ref
-1);
288 if(ref
== 1) InterlockedIncrement(&This
->numIfaces
);
293 static ULONG WINAPI
ddraw4_AddRef(IDirectDraw4
*iface
)
295 IDirectDrawImpl
*ddraw
= ddraw_from_ddraw4(iface
);
296 ULONG ref
= InterlockedIncrement(&ddraw
->ref4
);
298 TRACE("%p increasing refcount to %u.\n", ddraw
, ref
);
300 if (ref
== 1) InterlockedIncrement(&ddraw
->numIfaces
);
305 static ULONG WINAPI
ddraw3_AddRef(IDirectDraw3
*iface
)
307 IDirectDrawImpl
*ddraw
= ddraw_from_ddraw3(iface
);
308 ULONG ref
= InterlockedIncrement(&ddraw
->ref3
);
310 TRACE("%p increasing refcount to %u.\n", ddraw
, ref
);
312 if (ref
== 1) InterlockedIncrement(&ddraw
->numIfaces
);
317 static ULONG WINAPI
ddraw2_AddRef(IDirectDraw2
*iface
)
319 IDirectDrawImpl
*ddraw
= ddraw_from_ddraw2(iface
);
320 ULONG ref
= InterlockedIncrement(&ddraw
->ref2
);
322 TRACE("%p increasing refcount to %u.\n", ddraw
, ref
);
324 if (ref
== 1) InterlockedIncrement(&ddraw
->numIfaces
);
329 static ULONG WINAPI
ddraw1_AddRef(IDirectDraw
*iface
)
331 IDirectDrawImpl
*ddraw
= ddraw_from_ddraw1(iface
);
332 ULONG ref
= InterlockedIncrement(&ddraw
->ref1
);
334 TRACE("%p increasing refcount to %u.\n", ddraw
, ref
);
336 if (ref
== 1) InterlockedIncrement(&ddraw
->numIfaces
);
341 /*****************************************************************************
344 * Destroys a ddraw object if all refcounts are 0. This is to share code
345 * between the IDirectDrawX::Release functions
348 * This: DirectDraw object to destroy
350 *****************************************************************************/
351 static void ddraw_destroy(IDirectDrawImpl
*This
)
353 IDirectDraw7_SetCooperativeLevel((IDirectDraw7
*)This
, NULL
, DDSCL_NORMAL
);
354 IDirectDraw7_RestoreDisplayMode((IDirectDraw7
*)This
);
356 /* Destroy the device window if we created one */
357 if(This
->devicewindow
!= 0)
359 TRACE(" (%p) Destroying the device window %p\n", This
, This
->devicewindow
);
360 DestroyWindow(This
->devicewindow
);
361 This
->devicewindow
= 0;
364 EnterCriticalSection(&ddraw_cs
);
365 list_remove(&This
->ddraw_list_entry
);
366 LeaveCriticalSection(&ddraw_cs
);
368 /* Release the attached WineD3D stuff */
369 IWineD3DDevice_Release(This
->wineD3DDevice
);
370 IWineD3D_Release(This
->wineD3D
);
372 /* Now free the object */
373 HeapFree(GetProcessHeap(), 0, This
);
376 /*****************************************************************************
377 * IDirectDraw7::Release
379 * Decreases the refcount. If the refcount falls to 0, the object is destroyed
381 * Returns: The new refcount
382 *****************************************************************************/
383 static ULONG WINAPI
ddraw7_Release(IDirectDraw7
*iface
)
385 IDirectDrawImpl
*This
= (IDirectDrawImpl
*)iface
;
386 ULONG ref
= InterlockedDecrement(&This
->ref7
);
388 TRACE("(%p)->() decrementing IDirectDraw7 refcount from %u.\n", This
, ref
+1);
390 if (!ref
&& !InterlockedDecrement(&This
->numIfaces
))
396 static ULONG WINAPI
ddraw4_Release(IDirectDraw4
*iface
)
398 IDirectDrawImpl
*ddraw
= ddraw_from_ddraw4(iface
);
399 ULONG ref
= InterlockedDecrement(&ddraw
->ref4
);
401 TRACE("%p decreasing refcount to %u.\n", ddraw
, ref
);
403 if (!ref
&& !InterlockedDecrement(&ddraw
->numIfaces
))
404 ddraw_destroy(ddraw
);
409 static ULONG WINAPI
ddraw3_Release(IDirectDraw3
*iface
)
411 IDirectDrawImpl
*ddraw
= ddraw_from_ddraw3(iface
);
412 ULONG ref
= InterlockedDecrement(&ddraw
->ref3
);
414 TRACE("%p decreasing refcount to %u.\n", ddraw
, ref
);
416 if (!ref
&& !InterlockedDecrement(&ddraw
->numIfaces
))
417 ddraw_destroy(ddraw
);
422 static ULONG WINAPI
ddraw2_Release(IDirectDraw2
*iface
)
424 IDirectDrawImpl
*ddraw
= ddraw_from_ddraw2(iface
);
425 ULONG ref
= InterlockedDecrement(&ddraw
->ref2
);
427 TRACE("%p decreasing refcount to %u.\n", ddraw
, ref
);
429 if (!ref
&& !InterlockedDecrement(&ddraw
->numIfaces
))
430 ddraw_destroy(ddraw
);
435 static ULONG WINAPI
ddraw1_Release(IDirectDraw
*iface
)
437 IDirectDrawImpl
*ddraw
= ddraw_from_ddraw1(iface
);
438 ULONG ref
= InterlockedDecrement(&ddraw
->ref1
);
440 TRACE("%p decreasing refcount to %u.\n", ddraw
, ref
);
442 if (!ref
&& !InterlockedDecrement(&ddraw
->numIfaces
))
443 ddraw_destroy(ddraw
);
448 /*****************************************************************************
449 * IDirectDraw methods
450 *****************************************************************************/
452 /*****************************************************************************
453 * IDirectDraw7::SetCooperativeLevel
455 * Sets the cooperative level for the DirectDraw object, and the window
456 * assigned to it. The cooperative level determines the general behavior
457 * of the DirectDraw application
459 * Warning: This is quite tricky, as it's not really documented which
460 * cooperative levels can be combined with each other. If a game fails
461 * after this function, try to check the cooperative levels passed on
462 * Windows, and if it returns something different.
464 * If you think that this function caused the failure because it writes a
465 * fixme, be sure to run again with a +ddraw trace.
467 * What is known about cooperative levels (See the ddraw modes test):
468 * DDSCL_EXCLUSIVE and DDSCL_FULLSCREEN must be used with each other
469 * DDSCL_NORMAL is not compatible with DDSCL_EXCLUSIVE or DDSCL_FULLSCREEN
470 * DDSCL_SETFOCUSWINDOW can be passed only in DDSCL_NORMAL mode, but after that
471 * DDSCL_FULLSCREEN can be activated
472 * DDSCL_SETFOCUSWINDOW may only be used with DDSCL_NOWINDOWCHANGES
474 * Handled flags: DDSCL_NORMAL, DDSCL_FULLSCREEN, DDSCL_EXCLUSIVE,
475 * DDSCL_SETFOCUSWINDOW (partially),
476 * DDSCL_MULTITHREADED (work in progress)
478 * Unhandled flags, which should be implemented
479 * DDSCL_SETDEVICEWINDOW: Sets a window specially used for rendering (I don't
480 * expect any difference to a normal window for wine)
481 * DDSCL_CREATEDEVICEWINDOW: Tells ddraw to create its own window for
482 * rendering (Possible test case: Half-Life)
484 * Unsure about these: DDSCL_FPUSETUP DDSCL_FPURESERVE
486 * These don't seem very important for wine:
487 * DDSCL_ALLOWREBOOT, DDSCL_NOWINDOWCHANGES, DDSCL_ALLOWMODEX
490 * DD_OK if the cooperative level was set successfully
491 * DDERR_INVALIDPARAMS if the passed cooperative level combination is invalid
492 * DDERR_HWNDALREADYSET if DDSCL_SETFOCUSWINDOW is passed in exclusive mode
493 * (Probably others too, have to investigate)
495 *****************************************************************************/
496 static HRESULT WINAPI
ddraw7_SetCooperativeLevel(IDirectDraw7
*iface
, HWND hwnd
, DWORD cooplevel
)
498 IDirectDrawImpl
*This
= (IDirectDrawImpl
*)iface
;
501 TRACE("(%p)->(%p,%08x)\n",This
,hwnd
,cooplevel
);
502 DDRAW_dump_cooperativelevel(cooplevel
);
504 EnterCriticalSection(&ddraw_cs
);
506 /* Get the old window */
507 window
= This
->dest_window
;
509 /* Tests suggest that we need one of them: */
510 if(!(cooplevel
& (DDSCL_SETFOCUSWINDOW
|
514 TRACE("Incorrect cooplevel flags, returning DDERR_INVALIDPARAMS\n");
515 LeaveCriticalSection(&ddraw_cs
);
516 return DDERR_INVALIDPARAMS
;
519 /* Handle those levels first which set various hwnds */
520 if(cooplevel
& DDSCL_SETFOCUSWINDOW
)
522 /* This isn't compatible with a lot of flags */
523 if(cooplevel
& ( DDSCL_MULTITHREADED
|
528 DDSCL_SETDEVICEWINDOW
|
533 TRACE("Called with incompatible flags, returning DDERR_INVALIDPARAMS\n");
534 LeaveCriticalSection(&ddraw_cs
);
535 return DDERR_INVALIDPARAMS
;
537 else if( (This
->cooperative_level
& DDSCL_FULLSCREEN
) && window
)
539 TRACE("Setting DDSCL_SETFOCUSWINDOW with an already set window, returning DDERR_HWNDALREADYSET\n");
540 LeaveCriticalSection(&ddraw_cs
);
541 return DDERR_HWNDALREADYSET
;
544 This
->focuswindow
= hwnd
;
545 /* Won't use the hwnd param for anything else */
548 /* Use the focus window for drawing too */
549 This
->dest_window
= This
->focuswindow
;
551 /* Destroy the device window, if we have one */
552 if(This
->devicewindow
)
554 DestroyWindow(This
->devicewindow
);
555 This
->devicewindow
= NULL
;
558 /* DDSCL_NORMAL or DDSCL_FULLSCREEN | DDSCL_EXCLUSIVE */
559 if(cooplevel
& DDSCL_NORMAL
)
561 /* Can't coexist with fullscreen or exclusive */
562 if(cooplevel
& (DDSCL_FULLSCREEN
| DDSCL_EXCLUSIVE
) )
564 TRACE("(%p) DDSCL_NORMAL is not compative with DDSCL_FULLSCREEN or DDSCL_EXCLUSIVE\n", This
);
565 LeaveCriticalSection(&ddraw_cs
);
566 return DDERR_INVALIDPARAMS
;
569 /* Switching from fullscreen? */
570 if(This
->cooperative_level
& DDSCL_FULLSCREEN
)
572 This
->cooperative_level
&= ~DDSCL_FULLSCREEN
;
573 This
->cooperative_level
&= ~DDSCL_EXCLUSIVE
;
574 This
->cooperative_level
&= ~DDSCL_ALLOWMODEX
;
576 IWineD3DDevice_ReleaseFocusWindow(This
->wineD3DDevice
);
579 /* Don't override focus windows or private device windows */
581 !(This
->focuswindow
) &&
582 !(This
->devicewindow
) &&
585 This
->dest_window
= hwnd
;
588 else if(cooplevel
& DDSCL_FULLSCREEN
)
590 /* Needs DDSCL_EXCLUSIVE */
591 if(!(cooplevel
& DDSCL_EXCLUSIVE
) )
593 TRACE("(%p) DDSCL_FULLSCREEN needs DDSCL_EXCLUSIVE\n", This
);
594 LeaveCriticalSection(&ddraw_cs
);
595 return DDERR_INVALIDPARAMS
;
600 TRACE("(%p) DDSCL_FULLSCREEN needs a HWND\n", This);
601 return DDERR_INVALIDPARAMS;
605 This
->cooperative_level
&= ~DDSCL_NORMAL
;
607 /* Don't override focus windows or private device windows */
609 !(This
->focuswindow
) &&
610 !(This
->devicewindow
) &&
613 HRESULT hr
= IWineD3DDevice_AcquireFocusWindow(This
->wineD3DDevice
, hwnd
);
616 ERR("Failed to acquire focus window, hr %#x.\n", hr
);
617 LeaveCriticalSection(&ddraw_cs
);
620 This
->dest_window
= hwnd
;
623 else if(cooplevel
& DDSCL_EXCLUSIVE
)
625 TRACE("(%p) DDSCL_EXCLUSIVE needs DDSCL_FULLSCREEN\n", This
);
626 LeaveCriticalSection(&ddraw_cs
);
627 return DDERR_INVALIDPARAMS
;
630 if(cooplevel
& DDSCL_CREATEDEVICEWINDOW
)
632 /* Don't create a device window if a focus window is set */
633 if( !(This
->focuswindow
) )
635 HWND devicewindow
= CreateWindowExA(0, DDRAW_WINDOW_CLASS_NAME
, "DDraw device window",
636 WS_POPUP
, 0, 0, GetSystemMetrics(SM_CXSCREEN
), GetSystemMetrics(SM_CYSCREEN
),
637 NULL
, NULL
, NULL
, NULL
);
640 ERR("Failed to create window, last error %#x.\n", GetLastError());
641 LeaveCriticalSection(&ddraw_cs
);
645 ShowWindow(devicewindow
, SW_SHOW
); /* Just to be sure */
646 TRACE("(%p) Created a DDraw device window. HWND=%p\n", This
, devicewindow
);
648 This
->devicewindow
= devicewindow
;
649 This
->dest_window
= devicewindow
;
653 if(cooplevel
& DDSCL_MULTITHREADED
&& !(This
->cooperative_level
& DDSCL_MULTITHREADED
))
655 /* Enable thread safety in wined3d */
656 IWineD3DDevice_SetMultithreaded(This
->wineD3DDevice
);
659 /* Unhandled flags */
660 if(cooplevel
& DDSCL_ALLOWREBOOT
)
661 WARN("(%p) Unhandled flag DDSCL_ALLOWREBOOT, harmless\n", This
);
662 if(cooplevel
& DDSCL_ALLOWMODEX
)
663 WARN("(%p) Unhandled flag DDSCL_ALLOWMODEX, harmless\n", This
);
664 if(cooplevel
& DDSCL_FPUSETUP
)
665 WARN("(%p) Unhandled flag DDSCL_FPUSETUP, harmless\n", This
);
667 /* Store the cooperative_level */
668 This
->cooperative_level
|= cooplevel
;
669 TRACE("SetCooperativeLevel retuning DD_OK\n");
670 LeaveCriticalSection(&ddraw_cs
);
674 static HRESULT WINAPI
ddraw4_SetCooperativeLevel(IDirectDraw4
*iface
, HWND window
, DWORD flags
)
676 TRACE("iface %p, window %p, flags %#x.\n", iface
, window
, flags
);
678 return ddraw7_SetCooperativeLevel((IDirectDraw7
*)ddraw_from_ddraw4(iface
), window
, flags
);
681 static HRESULT WINAPI
ddraw3_SetCooperativeLevel(IDirectDraw3
*iface
, HWND window
, DWORD flags
)
683 TRACE("iface %p, window %p, flags %#x.\n", iface
, window
, flags
);
685 return ddraw7_SetCooperativeLevel((IDirectDraw7
*)ddraw_from_ddraw3(iface
), window
, flags
);
688 static HRESULT WINAPI
ddraw2_SetCooperativeLevel(IDirectDraw2
*iface
, HWND window
, DWORD flags
)
690 TRACE("iface %p, window %p, flags %#x.\n", iface
, window
, flags
);
692 return ddraw7_SetCooperativeLevel((IDirectDraw7
*)ddraw_from_ddraw2(iface
), window
, flags
);
695 static HRESULT WINAPI
ddraw1_SetCooperativeLevel(IDirectDraw
*iface
, HWND window
, DWORD flags
)
697 TRACE("iface %p, window %p, flags %#x.\n", iface
, window
, flags
);
699 return ddraw7_SetCooperativeLevel((IDirectDraw7
*)ddraw_from_ddraw1(iface
), window
, flags
);
702 /*****************************************************************************
704 * Helper function for SetDisplayMode and RestoreDisplayMode
706 * Implements DirectDraw's SetDisplayMode, but ignores the value of
707 * ForceRefreshRate, since it is already handled by
708 * ddraw7_SetDisplayMode. RestoreDisplayMode can use this function
709 * without worrying that ForceRefreshRate will override the refresh rate. For
710 * argument and return value documentation, see
711 * ddraw7_SetDisplayMode.
713 *****************************************************************************/
714 static HRESULT
ddraw_set_display_mode(IDirectDraw7
*iface
, DWORD Width
, DWORD Height
,
715 DWORD BPP
, DWORD RefreshRate
, DWORD Flags
)
717 IDirectDrawImpl
*This
= (IDirectDrawImpl
*)iface
;
718 WINED3DDISPLAYMODE Mode
;
720 TRACE("(%p)->(%d,%d,%d,%d,%x): Relay!\n", This
, Width
, Height
, BPP
, RefreshRate
, Flags
);
722 EnterCriticalSection(&ddraw_cs
);
723 if( !Width
|| !Height
)
725 ERR("Width=%d, Height=%d, what to do?\n", Width
, Height
);
726 /* It looks like Need for Speed Porsche Unleashed expects DD_OK here */
727 LeaveCriticalSection(&ddraw_cs
);
731 /* Check the exclusive mode
732 if(!(This->cooperative_level & DDSCL_EXCLUSIVE))
733 return DDERR_NOEXCLUSIVEMODE;
734 * This is WRONG. Don't know if the SDK is completely
735 * wrong and if there are any conditions when DDERR_NOEXCLUSIVE
736 * is returned, but Half-Life 1.1.1.1 (Steam version)
741 Mode
.Height
= Height
;
742 Mode
.RefreshRate
= RefreshRate
;
745 case 8: Mode
.Format
= WINED3DFMT_P8_UINT
; break;
746 case 15: Mode
.Format
= WINED3DFMT_B5G5R5X1_UNORM
; break;
747 case 16: Mode
.Format
= WINED3DFMT_B5G6R5_UNORM
; break;
748 case 24: Mode
.Format
= WINED3DFMT_B8G8R8_UNORM
; break;
749 case 32: Mode
.Format
= WINED3DFMT_B8G8R8X8_UNORM
; break;
752 /* TODO: The possible return values from msdn suggest that
753 * the screen mode can't be changed if a surface is locked
754 * or some drawing is in progress
757 /* TODO: Lose the primary surface */
758 hr
= IWineD3DDevice_SetDisplayMode(This
->wineD3DDevice
,
759 0, /* First swapchain */
761 LeaveCriticalSection(&ddraw_cs
);
764 case WINED3DERR_NOTAVAILABLE
: return DDERR_UNSUPPORTED
;
769 /*****************************************************************************
770 * IDirectDraw7::SetDisplayMode
772 * Sets the display screen resolution, color depth and refresh frequency
773 * when in fullscreen mode (in theory).
774 * Possible return values listed in the SDK suggest that this method fails
775 * when not in fullscreen mode, but this is wrong. Windows 2000 happily sets
776 * the display mode in DDSCL_NORMAL mode without an hwnd specified.
777 * It seems to be valid to pass 0 for With and Height, this has to be tested
778 * It could mean that the current video mode should be left as-is. (But why
782 * Height, Width: Screen dimension
783 * BPP: Color depth in Bits per pixel
784 * Refreshrate: Screen refresh rate
790 *****************************************************************************/
791 static HRESULT WINAPI
ddraw7_SetDisplayMode(IDirectDraw7
*iface
, DWORD Width
, DWORD Height
,
792 DWORD BPP
, DWORD RefreshRate
, DWORD Flags
)
794 if (force_refresh_rate
!= 0)
796 TRACE("ForceRefreshRate overriding passed-in refresh rate (%d Hz) to %d Hz\n", RefreshRate
, force_refresh_rate
);
797 RefreshRate
= force_refresh_rate
;
800 return ddraw_set_display_mode(iface
, Width
, Height
, BPP
, RefreshRate
, Flags
);
803 static HRESULT WINAPI
ddraw4_SetDisplayMode(IDirectDraw4
*iface
,
804 DWORD width
, DWORD height
, DWORD bpp
, DWORD refresh_rate
, DWORD flags
)
806 TRACE("iface %p, width %u, height %u, bpp %u, refresh_rate %u, flags %#x.\n",
807 iface
, width
, height
, bpp
, refresh_rate
, flags
);
809 return ddraw7_SetDisplayMode((IDirectDraw7
*)ddraw_from_ddraw4(iface
),
810 width
, height
, bpp
, refresh_rate
, flags
);
813 static HRESULT WINAPI
ddraw3_SetDisplayMode(IDirectDraw3
*iface
,
814 DWORD width
, DWORD height
, DWORD bpp
, DWORD refresh_rate
, DWORD flags
)
816 TRACE("iface %p, width %u, height %u, bpp %u, refresh_rate %u, flags %#x.\n",
817 iface
, width
, height
, bpp
, refresh_rate
, flags
);
819 return ddraw7_SetDisplayMode((IDirectDraw7
*)ddraw_from_ddraw3(iface
),
820 width
, height
, bpp
, refresh_rate
, flags
);
823 static HRESULT WINAPI
ddraw2_SetDisplayMode(IDirectDraw2
*iface
,
824 DWORD width
, DWORD height
, DWORD bpp
, DWORD refresh_rate
, DWORD flags
)
826 TRACE("iface %p, width %u, height %u, bpp %u, refresh_rate %u, flags %#x.\n",
827 iface
, width
, height
, bpp
, refresh_rate
, flags
);
829 return ddraw7_SetDisplayMode((IDirectDraw7
*)ddraw_from_ddraw2(iface
),
830 width
, height
, bpp
, refresh_rate
, flags
);
833 static HRESULT WINAPI
ddraw1_SetDisplayMode(IDirectDraw
*iface
, DWORD width
, DWORD height
, DWORD bpp
)
835 TRACE("iface %p, width %u, height %u, bpp %u.\n", iface
, width
, height
, bpp
);
837 return ddraw7_SetDisplayMode((IDirectDraw7
*)ddraw_from_ddraw1(iface
), width
, height
, bpp
, 0, 0);
840 /*****************************************************************************
841 * IDirectDraw7::RestoreDisplayMode
843 * Restores the display mode to what it was at creation time. Basically.
845 * A problem arises when there are 2 DirectDraw objects using the same hwnd:
846 * -> DD_1 finds the screen at 1400x1050x32 when created, sets it to 640x480x16
847 * -> DD_2 is created, finds the screen at 640x480x16, sets it to 1024x768x32
848 * -> DD_1 is released. The screen should be left at 1024x768x32.
849 * -> DD_2 is released. The screen should be set to 1400x1050x32
850 * This case is unhandled right now, but Empire Earth does it this way.
851 * (But perhaps there is something in SetCooperativeLevel to prevent this)
853 * The msdn says that this method resets the display mode to what it was before
854 * SetDisplayMode was called. What if SetDisplayModes is called 2 times??
858 * DDERR_NOEXCLUSIVE mode if the device isn't in fullscreen mode
860 *****************************************************************************/
861 static HRESULT WINAPI
ddraw7_RestoreDisplayMode(IDirectDraw7
*iface
)
863 IDirectDrawImpl
*This
= (IDirectDrawImpl
*)iface
;
864 TRACE("(%p)\n", This
);
866 return ddraw_set_display_mode(iface
, This
->orig_width
, This
->orig_height
, This
->orig_bpp
, 0, 0);
869 static HRESULT WINAPI
ddraw4_RestoreDisplayMode(IDirectDraw4
*iface
)
871 TRACE("iface %p.\n", iface
);
873 return ddraw7_RestoreDisplayMode((IDirectDraw7
*)ddraw_from_ddraw4(iface
));
876 static HRESULT WINAPI
ddraw3_RestoreDisplayMode(IDirectDraw3
*iface
)
878 TRACE("iface %p.\n", iface
);
880 return ddraw7_RestoreDisplayMode((IDirectDraw7
*)ddraw_from_ddraw3(iface
));
883 static HRESULT WINAPI
ddraw2_RestoreDisplayMode(IDirectDraw2
*iface
)
885 TRACE("iface %p.\n", iface
);
887 return ddraw7_RestoreDisplayMode((IDirectDraw7
*)ddraw_from_ddraw2(iface
));
890 static HRESULT WINAPI
ddraw1_RestoreDisplayMode(IDirectDraw
*iface
)
892 TRACE("iface %p.\n", iface
);
894 return ddraw7_RestoreDisplayMode((IDirectDraw7
*)ddraw_from_ddraw1(iface
));
897 /*****************************************************************************
898 * IDirectDraw7::GetCaps
900 * Returns the drives capabilities
902 * Used for version 1, 2, 4 and 7
905 * DriverCaps: Structure to write the Hardware accelerated caps to
906 * HelCaps: Structure to write the emulation caps to
909 * This implementation returns DD_OK only
911 *****************************************************************************/
912 static HRESULT WINAPI
ddraw7_GetCaps(IDirectDraw7
*iface
, DDCAPS
*DriverCaps
, DDCAPS
*HELCaps
)
914 IDirectDrawImpl
*This
= (IDirectDrawImpl
*)iface
;
916 WINED3DCAPS winecaps
;
918 DDSCAPS2 ddscaps
= {0, 0, 0, 0};
919 TRACE("(%p)->(%p,%p)\n", This
, DriverCaps
, HELCaps
);
921 /* One structure must be != NULL */
922 if( (!DriverCaps
) && (!HELCaps
) )
924 ERR("(%p) Invalid params to ddraw7_GetCaps\n", This
);
925 return DDERR_INVALIDPARAMS
;
928 memset(&caps
, 0, sizeof(caps
));
929 memset(&winecaps
, 0, sizeof(winecaps
));
930 caps
.dwSize
= sizeof(caps
);
931 EnterCriticalSection(&ddraw_cs
);
932 hr
= IWineD3DDevice_GetDeviceCaps(This
->wineD3DDevice
, &winecaps
);
934 WARN("IWineD3DDevice::GetDeviceCaps failed\n");
935 LeaveCriticalSection(&ddraw_cs
);
939 hr
= IDirectDraw7_GetAvailableVidMem(iface
, &ddscaps
, &caps
.dwVidMemTotal
, &caps
.dwVidMemFree
);
940 LeaveCriticalSection(&ddraw_cs
);
942 WARN("IDirectDraw7::GetAvailableVidMem failed\n");
946 caps
.dwCaps
= winecaps
.DirectDrawCaps
.Caps
;
947 caps
.dwCaps2
= winecaps
.DirectDrawCaps
.Caps2
;
948 caps
.dwCKeyCaps
= winecaps
.DirectDrawCaps
.CKeyCaps
;
949 caps
.dwFXCaps
= winecaps
.DirectDrawCaps
.FXCaps
;
950 caps
.dwPalCaps
= winecaps
.DirectDrawCaps
.PalCaps
;
951 caps
.ddsCaps
.dwCaps
= winecaps
.DirectDrawCaps
.ddsCaps
;
952 caps
.dwSVBCaps
= winecaps
.DirectDrawCaps
.SVBCaps
;
953 caps
.dwSVBCKeyCaps
= winecaps
.DirectDrawCaps
.SVBCKeyCaps
;
954 caps
.dwSVBFXCaps
= winecaps
.DirectDrawCaps
.SVBFXCaps
;
955 caps
.dwVSBCaps
= winecaps
.DirectDrawCaps
.VSBCaps
;
956 caps
.dwVSBCKeyCaps
= winecaps
.DirectDrawCaps
.VSBCKeyCaps
;
957 caps
.dwVSBFXCaps
= winecaps
.DirectDrawCaps
.VSBFXCaps
;
958 caps
.dwSSBCaps
= winecaps
.DirectDrawCaps
.SSBCaps
;
959 caps
.dwSSBCKeyCaps
= winecaps
.DirectDrawCaps
.SSBCKeyCaps
;
960 caps
.dwSSBFXCaps
= winecaps
.DirectDrawCaps
.SSBFXCaps
;
962 /* Even if WineD3D supports 3D rendering, remove the cap if ddraw is configured
965 if(DefaultSurfaceType
== SURFACE_GDI
) {
966 caps
.dwCaps
&= ~DDCAPS_3D
;
967 caps
.ddsCaps
.dwCaps
&= ~(DDSCAPS_3DDEVICE
| DDSCAPS_MIPMAP
| DDSCAPS_TEXTURE
| DDSCAPS_ZBUFFER
);
969 if(winecaps
.DirectDrawCaps
.StrideAlign
!= 0) {
970 caps
.dwCaps
|= DDCAPS_ALIGNSTRIDE
;
971 caps
.dwAlignStrideAlign
= winecaps
.DirectDrawCaps
.StrideAlign
;
976 DD_STRUCT_COPY_BYSIZE(DriverCaps
, &caps
);
979 TRACE("Driver Caps :\n");
980 DDRAW_dump_DDCAPS(DriverCaps
);
986 DD_STRUCT_COPY_BYSIZE(HELCaps
, &caps
);
989 TRACE("HEL Caps :\n");
990 DDRAW_dump_DDCAPS(HELCaps
);
997 static HRESULT WINAPI
ddraw4_GetCaps(IDirectDraw4
*iface
, DDCAPS
*driver_caps
, DDCAPS
*hel_caps
)
999 TRACE("iface %p, driver_caps %p, hel_caps %p.\n", iface
, driver_caps
, hel_caps
);
1001 return ddraw7_GetCaps((IDirectDraw7
*)ddraw_from_ddraw4(iface
), driver_caps
, hel_caps
);
1004 static HRESULT WINAPI
ddraw3_GetCaps(IDirectDraw3
*iface
, DDCAPS
*driver_caps
, DDCAPS
*hel_caps
)
1006 TRACE("iface %p, driver_caps %p, hel_caps %p.\n", iface
, driver_caps
, hel_caps
);
1008 return ddraw7_GetCaps((IDirectDraw7
*)ddraw_from_ddraw3(iface
), driver_caps
, hel_caps
);
1011 static HRESULT WINAPI
ddraw2_GetCaps(IDirectDraw2
*iface
, DDCAPS
*driver_caps
, DDCAPS
*hel_caps
)
1013 TRACE("iface %p, driver_caps %p, hel_caps %p.\n", iface
, driver_caps
, hel_caps
);
1015 return ddraw7_GetCaps((IDirectDraw7
*)ddraw_from_ddraw2(iface
), driver_caps
, hel_caps
);
1018 static HRESULT WINAPI
ddraw1_GetCaps(IDirectDraw
*iface
, DDCAPS
*driver_caps
, DDCAPS
*hel_caps
)
1020 TRACE("iface %p, driver_caps %p, hel_caps %p.\n", iface
, driver_caps
, hel_caps
);
1022 return ddraw7_GetCaps((IDirectDraw7
*)ddraw_from_ddraw1(iface
), driver_caps
, hel_caps
);
1025 /*****************************************************************************
1026 * IDirectDraw7::Compact
1028 * No idea what it does, MSDN says it's not implemented.
1031 * DD_OK, but this is unchecked
1033 *****************************************************************************/
1034 static HRESULT WINAPI
ddraw7_Compact(IDirectDraw7
*iface
)
1036 IDirectDrawImpl
*This
= (IDirectDrawImpl
*)iface
;
1037 TRACE("(%p)\n", This
);
1042 static HRESULT WINAPI
ddraw4_Compact(IDirectDraw4
*iface
)
1044 TRACE("iface %p.\n", iface
);
1046 return ddraw7_Compact((IDirectDraw7
*)ddraw_from_ddraw4(iface
));
1049 static HRESULT WINAPI
ddraw3_Compact(IDirectDraw3
*iface
)
1051 TRACE("iface %p.\n", iface
);
1053 return ddraw7_Compact((IDirectDraw7
*)ddraw_from_ddraw3(iface
));
1056 static HRESULT WINAPI
ddraw2_Compact(IDirectDraw2
*iface
)
1058 TRACE("iface %p.\n", iface
);
1060 return ddraw7_Compact((IDirectDraw7
*)ddraw_from_ddraw2(iface
));
1063 static HRESULT WINAPI
ddraw1_Compact(IDirectDraw
*iface
)
1065 TRACE("iface %p.\n", iface
);
1067 return ddraw7_Compact((IDirectDraw7
*)ddraw_from_ddraw1(iface
));
1070 /*****************************************************************************
1071 * IDirectDraw7::GetDisplayMode
1073 * Returns information about the current display mode
1075 * Exists in Version 1, 2, 4 and 7
1078 * DDSD: Address of a surface description structure to write the info to
1083 *****************************************************************************/
1084 static HRESULT WINAPI
ddraw7_GetDisplayMode(IDirectDraw7
*iface
, DDSURFACEDESC2
*DDSD
)
1086 IDirectDrawImpl
*This
= (IDirectDrawImpl
*)iface
;
1088 WINED3DDISPLAYMODE Mode
;
1090 TRACE("(%p)->(%p): Relay\n", This
, DDSD
);
1092 EnterCriticalSection(&ddraw_cs
);
1093 /* This seems sane */
1096 LeaveCriticalSection(&ddraw_cs
);
1097 return DDERR_INVALIDPARAMS
;
1100 /* The necessary members of LPDDSURFACEDESC and LPDDSURFACEDESC2 are equal,
1101 * so one method can be used for all versions (Hopefully)
1103 hr
= IWineD3DDevice_GetDisplayMode(This
->wineD3DDevice
,
1104 0 /* swapchain 0 */,
1108 ERR(" (%p) IWineD3DDevice::GetDisplayMode returned %08x\n", This
, hr
);
1109 LeaveCriticalSection(&ddraw_cs
);
1113 Size
= DDSD
->dwSize
;
1114 memset(DDSD
, 0, Size
);
1116 DDSD
->dwSize
= Size
;
1117 DDSD
->dwFlags
|= DDSD_HEIGHT
| DDSD_WIDTH
| DDSD_PIXELFORMAT
| DDSD_PITCH
| DDSD_REFRESHRATE
;
1118 DDSD
->dwWidth
= Mode
.Width
;
1119 DDSD
->dwHeight
= Mode
.Height
;
1120 DDSD
->u2
.dwRefreshRate
= 60;
1121 DDSD
->ddsCaps
.dwCaps
= 0;
1122 DDSD
->u4
.ddpfPixelFormat
.dwSize
= sizeof(DDSD
->u4
.ddpfPixelFormat
);
1123 PixelFormat_WineD3DtoDD(&DDSD
->u4
.ddpfPixelFormat
, Mode
.Format
);
1124 DDSD
->u1
.lPitch
= Mode
.Width
* DDSD
->u4
.ddpfPixelFormat
.u1
.dwRGBBitCount
/ 8;
1128 TRACE("Returning surface desc :\n");
1129 DDRAW_dump_surface_desc(DDSD
);
1132 LeaveCriticalSection(&ddraw_cs
);
1136 static HRESULT WINAPI
ddraw4_GetDisplayMode(IDirectDraw4
*iface
, DDSURFACEDESC2
*surface_desc
)
1138 TRACE("iface %p, surface_desc %p.\n", iface
, surface_desc
);
1140 return ddraw7_GetDisplayMode((IDirectDraw7
*)ddraw_from_ddraw4(iface
), surface_desc
);
1143 static HRESULT WINAPI
ddraw3_GetDisplayMode(IDirectDraw3
*iface
, DDSURFACEDESC
*surface_desc
)
1145 TRACE("iface %p, surface_desc %p.\n", iface
, surface_desc
);
1147 return ddraw7_GetDisplayMode((IDirectDraw7
*)ddraw_from_ddraw3(iface
), (DDSURFACEDESC2
*)surface_desc
);
1150 static HRESULT WINAPI
ddraw2_GetDisplayMode(IDirectDraw2
*iface
, DDSURFACEDESC
*surface_desc
)
1152 TRACE("iface %p, surface_desc %p.\n", iface
, surface_desc
);
1154 return ddraw7_GetDisplayMode((IDirectDraw7
*)ddraw_from_ddraw2(iface
), (DDSURFACEDESC2
*)surface_desc
);
1157 static HRESULT WINAPI
ddraw1_GetDisplayMode(IDirectDraw
*iface
, DDSURFACEDESC
*surface_desc
)
1159 TRACE("iface %p, surface_desc %p.\n", iface
, surface_desc
);
1161 return ddraw7_GetDisplayMode((IDirectDraw7
*)ddraw_from_ddraw1(iface
), (DDSURFACEDESC2
*)surface_desc
);
1164 /*****************************************************************************
1165 * IDirectDraw7::GetFourCCCodes
1167 * Returns an array of supported FourCC codes.
1169 * Exists in Version 1, 2, 4 and 7
1172 * NumCodes: Contains the number of Codes that Codes can carry. Returns the number
1173 * of enumerated codes
1174 * Codes: Pointer to an array of DWORDs where the supported codes are written
1178 * Always returns DD_OK, as it's a stub for now
1180 *****************************************************************************/
1181 static HRESULT WINAPI
ddraw7_GetFourCCCodes(IDirectDraw7
*iface
, DWORD
*NumCodes
, DWORD
*Codes
)
1183 IDirectDrawImpl
*This
= (IDirectDrawImpl
*)iface
;
1184 WINED3DFORMAT formats
[] = {
1185 WINED3DFMT_YUY2
, WINED3DFMT_UYVY
, WINED3DFMT_YV12
,
1186 WINED3DFMT_DXT1
, WINED3DFMT_DXT2
, WINED3DFMT_DXT3
, WINED3DFMT_DXT4
, WINED3DFMT_DXT5
,
1187 WINED3DFMT_ATI2N
, WINED3DFMT_NVHU
, WINED3DFMT_NVHS
1189 DWORD count
= 0, i
, outsize
;
1191 WINED3DDISPLAYMODE d3ddm
;
1192 WINED3DSURFTYPE type
= This
->ImplType
;
1193 TRACE("(%p)->(%p, %p)\n", This
, NumCodes
, Codes
);
1195 IWineD3DDevice_GetDisplayMode(This
->wineD3DDevice
,
1196 0 /* swapchain 0 */,
1199 outsize
= NumCodes
&& Codes
? *NumCodes
: 0;
1201 if(type
== SURFACE_UNKNOWN
) type
= SURFACE_GDI
;
1203 for(i
= 0; i
< (sizeof(formats
) / sizeof(formats
[0])); i
++) {
1204 hr
= IWineD3D_CheckDeviceFormat(This
->wineD3D
,
1205 WINED3DADAPTER_DEFAULT
,
1207 d3ddm
.Format
/* AdapterFormat */,
1209 WINED3DRTYPE_SURFACE
,
1213 if(count
< outsize
) {
1214 Codes
[count
] = formats
[i
];
1220 TRACE("Returning %u FourCC codes\n", count
);
1227 static HRESULT WINAPI
ddraw4_GetFourCCCodes(IDirectDraw4
*iface
, DWORD
*codes_count
, DWORD
*codes
)
1229 TRACE("iface %p, codes_count %p, codes %p.\n", iface
, codes_count
, codes
);
1231 return ddraw7_GetFourCCCodes((IDirectDraw7
*)ddraw_from_ddraw4(iface
), codes_count
, codes
);
1234 static HRESULT WINAPI
ddraw3_GetFourCCCodes(IDirectDraw3
*iface
, DWORD
*codes_count
, DWORD
*codes
)
1236 TRACE("iface %p, codes_count %p, codes %p.\n", iface
, codes_count
, codes
);
1238 return ddraw7_GetFourCCCodes((IDirectDraw7
*)ddraw_from_ddraw3(iface
), codes_count
, codes
);
1241 static HRESULT WINAPI
ddraw2_GetFourCCCodes(IDirectDraw2
*iface
, DWORD
*codes_count
, DWORD
*codes
)
1243 TRACE("iface %p, codes_count %p, codes %p.\n", iface
, codes_count
, codes
);
1245 return ddraw7_GetFourCCCodes((IDirectDraw7
*)ddraw_from_ddraw2(iface
), codes_count
, codes
);
1248 static HRESULT WINAPI
ddraw1_GetFourCCCodes(IDirectDraw
*iface
, DWORD
*codes_count
, DWORD
*codes
)
1250 TRACE("iface %p, codes_count %p, codes %p.\n", iface
, codes_count
, codes
);
1252 return ddraw7_GetFourCCCodes((IDirectDraw7
*)ddraw_from_ddraw1(iface
), codes_count
, codes
);
1255 /*****************************************************************************
1256 * IDirectDraw7::GetMonitorFrequency
1258 * Returns the monitor's frequency
1260 * Exists in Version 1, 2, 4 and 7
1263 * Freq: Pointer to a DWORD to write the frequency to
1266 * Always returns DD_OK
1268 *****************************************************************************/
1269 static HRESULT WINAPI
ddraw7_GetMonitorFrequency(IDirectDraw7
*iface
, DWORD
*Freq
)
1271 IDirectDrawImpl
*This
= (IDirectDrawImpl
*)iface
;
1272 TRACE("(%p)->(%p)\n", This
, Freq
);
1274 /* Ideally this should be in WineD3D, as it concerns the screen setup,
1275 * but for now this should make the games happy
1281 static HRESULT WINAPI
ddraw4_GetMonitorFrequency(IDirectDraw4
*iface
, DWORD
*frequency
)
1283 TRACE("iface %p, frequency %p.\n", iface
, frequency
);
1285 return ddraw7_GetMonitorFrequency((IDirectDraw7
*)ddraw_from_ddraw4(iface
), frequency
);
1288 static HRESULT WINAPI
ddraw3_GetMonitorFrequency(IDirectDraw3
*iface
, DWORD
*frequency
)
1290 TRACE("iface %p, frequency %p.\n", iface
, frequency
);
1292 return ddraw7_GetMonitorFrequency((IDirectDraw7
*)ddraw_from_ddraw3(iface
), frequency
);
1295 static HRESULT WINAPI
ddraw2_GetMonitorFrequency(IDirectDraw2
*iface
, DWORD
*frequency
)
1297 TRACE("iface %p, frequency %p.\n", iface
, frequency
);
1299 return ddraw7_GetMonitorFrequency((IDirectDraw7
*)ddraw_from_ddraw2(iface
), frequency
);
1302 static HRESULT WINAPI
ddraw1_GetMonitorFrequency(IDirectDraw
*iface
, DWORD
*frequency
)
1304 TRACE("iface %p, frequency %p.\n", iface
, frequency
);
1306 return ddraw7_GetMonitorFrequency((IDirectDraw7
*)ddraw_from_ddraw1(iface
), frequency
);
1309 /*****************************************************************************
1310 * IDirectDraw7::GetVerticalBlankStatus
1312 * Returns the Vertical blank status of the monitor. This should be in WineD3D
1313 * too basically, but as it's a semi stub, I didn't create a function there
1316 * status: Pointer to a BOOL to be filled with the vertical blank status
1320 * DDERR_INVALIDPARAMS if status is NULL
1322 *****************************************************************************/
1323 static HRESULT WINAPI
ddraw7_GetVerticalBlankStatus(IDirectDraw7
*iface
, BOOL
*status
)
1325 IDirectDrawImpl
*This
= (IDirectDrawImpl
*)iface
;
1326 TRACE("(%p)->(%p)\n", This
, status
);
1328 /* This looks sane, the MSDN suggests it too */
1329 EnterCriticalSection(&ddraw_cs
);
1332 LeaveCriticalSection(&ddraw_cs
);
1333 return DDERR_INVALIDPARAMS
;
1336 *status
= This
->fake_vblank
;
1337 This
->fake_vblank
= !This
->fake_vblank
;
1338 LeaveCriticalSection(&ddraw_cs
);
1342 static HRESULT WINAPI
ddraw4_GetVerticalBlankStatus(IDirectDraw4
*iface
, BOOL
*status
)
1344 TRACE("iface %p, status %p.\n", iface
, status
);
1346 return ddraw7_GetVerticalBlankStatus((IDirectDraw7
*)ddraw_from_ddraw4(iface
), status
);
1349 static HRESULT WINAPI
ddraw3_GetVerticalBlankStatus(IDirectDraw3
*iface
, BOOL
*status
)
1351 TRACE("iface %p, status %p.\n", iface
, status
);
1353 return ddraw7_GetVerticalBlankStatus((IDirectDraw7
*)ddraw_from_ddraw3(iface
), status
);
1356 static HRESULT WINAPI
ddraw2_GetVerticalBlankStatus(IDirectDraw2
*iface
, BOOL
*status
)
1358 TRACE("iface %p, status %p.\n", iface
, status
);
1360 return ddraw7_GetVerticalBlankStatus((IDirectDraw7
*)ddraw_from_ddraw2(iface
), status
);
1363 static HRESULT WINAPI
ddraw1_GetVerticalBlankStatus(IDirectDraw
*iface
, BOOL
*status
)
1365 TRACE("iface %p, status %p.\n", iface
, status
);
1367 return ddraw7_GetVerticalBlankStatus((IDirectDraw7
*)ddraw_from_ddraw1(iface
), status
);
1370 /*****************************************************************************
1371 * IDirectDraw7::GetAvailableVidMem
1373 * Returns the total and free video memory
1376 * Caps: Specifies the memory type asked for
1377 * total: Pointer to a DWORD to be filled with the total memory
1378 * free: Pointer to a DWORD to be filled with the free memory
1382 * DDERR_INVALIDPARAMS of free and total are NULL
1384 *****************************************************************************/
1385 static HRESULT WINAPI
ddraw7_GetAvailableVidMem(IDirectDraw7
*iface
, DDSCAPS2
*Caps
, DWORD
*total
, DWORD
*free
)
1387 IDirectDrawImpl
*This
= (IDirectDrawImpl
*)iface
;
1388 TRACE("(%p)->(%p, %p, %p)\n", This
, Caps
, total
, free
);
1392 TRACE("(%p) Asked for memory with description: ", This
);
1393 DDRAW_dump_DDSCAPS2(Caps
);
1395 EnterCriticalSection(&ddraw_cs
);
1397 /* Todo: System memory vs local video memory vs non-local video memory
1398 * The MSDN also mentions differences between texture memory and other
1399 * resources, but that's not important
1402 if( (!total
) && (!free
) )
1404 LeaveCriticalSection(&ddraw_cs
);
1405 return DDERR_INVALIDPARAMS
;
1408 if(total
) *total
= This
->total_vidmem
;
1409 if(free
) *free
= IWineD3DDevice_GetAvailableTextureMem(This
->wineD3DDevice
);
1411 LeaveCriticalSection(&ddraw_cs
);
1415 static HRESULT WINAPI
ddraw4_GetAvailableVidMem(IDirectDraw4
*iface
,
1416 DDSCAPS2
*caps
, DWORD
*total
, DWORD
*free
)
1418 TRACE("iface %p, caps %p, total %p, free %p.\n", iface
, caps
, total
, free
);
1420 return ddraw7_GetAvailableVidMem((IDirectDraw7
*)ddraw_from_ddraw4(iface
), caps
, total
, free
);
1423 static HRESULT WINAPI
ddraw3_GetAvailableVidMem(IDirectDraw3
*iface
,
1424 DDSCAPS
*caps
, DWORD
*total
, DWORD
*free
)
1428 TRACE("iface %p, caps %p, total %p, free %p.\n", iface
, caps
, total
, free
);
1430 DDRAW_Convert_DDSCAPS_1_To_2(caps
, &caps2
);
1431 return ddraw7_GetAvailableVidMem((IDirectDraw7
*)ddraw_from_ddraw3(iface
), &caps2
, total
, free
);
1434 static HRESULT WINAPI
ddraw2_GetAvailableVidMem(IDirectDraw2
*iface
,
1435 DDSCAPS
*caps
, DWORD
*total
, DWORD
*free
)
1439 TRACE("iface %p, caps %p, total %p, free %p.\n", iface
, caps
, total
, free
);
1441 DDRAW_Convert_DDSCAPS_1_To_2(caps
, &caps2
);
1442 return ddraw7_GetAvailableVidMem((IDirectDraw7
*)ddraw_from_ddraw2(iface
), &caps2
, total
, free
);
1445 /*****************************************************************************
1446 * IDirectDraw7::Initialize
1448 * Initializes a DirectDraw interface.
1451 * GUID: Interface identifier. Well, don't know what this is really good
1455 * Returns DD_OK on the first call,
1456 * DDERR_ALREADYINITIALIZED on repeated calls
1458 *****************************************************************************/
1459 static HRESULT WINAPI
ddraw7_Initialize(IDirectDraw7
*iface
, GUID
*Guid
)
1461 IDirectDrawImpl
*This
= (IDirectDrawImpl
*)iface
;
1462 TRACE("(%p)->(%s): No-op\n", This
, debugstr_guid(Guid
));
1464 if(This
->initialized
)
1466 return DDERR_ALREADYINITIALIZED
;
1474 static HRESULT WINAPI
ddraw4_Initialize(IDirectDraw4
*iface
, GUID
*guid
)
1476 TRACE("iface %p, guid %s.\n", iface
, debugstr_guid(guid
));
1478 return ddraw7_Initialize((IDirectDraw7
*)ddraw_from_ddraw4(iface
), guid
);
1481 static HRESULT WINAPI
ddraw3_Initialize(IDirectDraw3
*iface
, GUID
*guid
)
1483 TRACE("iface %p, guid %s.\n", iface
, debugstr_guid(guid
));
1485 return ddraw7_Initialize((IDirectDraw7
*)ddraw_from_ddraw3(iface
), guid
);
1488 static HRESULT WINAPI
ddraw2_Initialize(IDirectDraw2
*iface
, GUID
*guid
)
1490 TRACE("iface %p, guid %s.\n", iface
, debugstr_guid(guid
));
1492 return ddraw7_Initialize((IDirectDraw7
*)ddraw_from_ddraw2(iface
), guid
);
1495 static HRESULT WINAPI
ddraw1_Initialize(IDirectDraw
*iface
, GUID
*guid
)
1497 TRACE("iface %p, guid %s.\n", iface
, debugstr_guid(guid
));
1499 return ddraw7_Initialize((IDirectDraw7
*)ddraw_from_ddraw1(iface
), guid
);
1502 /*****************************************************************************
1503 * IDirectDraw7::FlipToGDISurface
1505 * "Makes the surface that the GDI writes to the primary surface"
1506 * Looks like some windows specific thing we don't have to care about.
1507 * According to MSDN it permits GDI dialog boxes in FULLSCREEN mode. Good to
1508 * show error boxes ;)
1509 * Well, just return DD_OK.
1512 * Always returns DD_OK
1514 *****************************************************************************/
1515 static HRESULT WINAPI
ddraw7_FlipToGDISurface(IDirectDraw7
*iface
)
1517 IDirectDrawImpl
*This
= (IDirectDrawImpl
*)iface
;
1518 TRACE("(%p)\n", This
);
1523 static HRESULT WINAPI
ddraw4_FlipToGDISurface(IDirectDraw4
*iface
)
1525 TRACE("iface %p.\n", iface
);
1527 return ddraw7_FlipToGDISurface((IDirectDraw7
*)ddraw_from_ddraw4(iface
));
1530 static HRESULT WINAPI
ddraw3_FlipToGDISurface(IDirectDraw3
*iface
)
1532 TRACE("iface %p.\n", iface
);
1534 return ddraw7_FlipToGDISurface((IDirectDraw7
*)ddraw_from_ddraw3(iface
));
1537 static HRESULT WINAPI
ddraw2_FlipToGDISurface(IDirectDraw2
*iface
)
1539 TRACE("iface %p.\n", iface
);
1541 return ddraw7_FlipToGDISurface((IDirectDraw7
*)ddraw_from_ddraw2(iface
));
1544 static HRESULT WINAPI
ddraw1_FlipToGDISurface(IDirectDraw
*iface
)
1546 TRACE("iface %p.\n", iface
);
1548 return ddraw7_FlipToGDISurface((IDirectDraw7
*)ddraw_from_ddraw1(iface
));
1551 /*****************************************************************************
1552 * IDirectDraw7::WaitForVerticalBlank
1554 * This method allows applications to get in sync with the vertical blank
1556 * The wormhole demo in the DirectX 7 sdk uses this call, and it doesn't
1557 * redraw the screen, most likely because of this stub
1560 * Flags: one of DDWAITVB_BLOCKBEGIN, DDWAITVB_BLOCKBEGINEVENT
1561 * or DDWAITVB_BLOCKEND
1562 * h: Not used, according to MSDN
1565 * Always returns DD_OK
1567 *****************************************************************************/
1568 static HRESULT WINAPI
ddraw7_WaitForVerticalBlank(IDirectDraw7
*iface
, DWORD Flags
, HANDLE h
)
1570 IDirectDrawImpl
*This
= (IDirectDrawImpl
*)iface
;
1571 static BOOL hide
= FALSE
;
1573 /* This function is called often, so print the fixme only once */
1576 FIXME("(%p)->(%x,%p): Stub\n", This
, Flags
, h
);
1580 /* MSDN says DDWAITVB_BLOCKBEGINEVENT is not supported */
1581 if(Flags
& DDWAITVB_BLOCKBEGINEVENT
)
1582 return DDERR_UNSUPPORTED
; /* unchecked */
1587 static HRESULT WINAPI
ddraw4_WaitForVerticalBlank(IDirectDraw4
*iface
, DWORD flags
, HANDLE event
)
1589 TRACE("iface %p, flags %#x, event %p.\n", iface
, flags
, event
);
1591 return ddraw7_WaitForVerticalBlank((IDirectDraw7
*)ddraw_from_ddraw4(iface
), flags
, event
);
1594 static HRESULT WINAPI
ddraw3_WaitForVerticalBlank(IDirectDraw3
*iface
, DWORD flags
, HANDLE event
)
1596 TRACE("iface %p, flags %#x, event %p.\n", iface
, flags
, event
);
1598 return ddraw7_WaitForVerticalBlank((IDirectDraw7
*)ddraw_from_ddraw3(iface
), flags
, event
);
1601 static HRESULT WINAPI
ddraw2_WaitForVerticalBlank(IDirectDraw2
*iface
, DWORD flags
, HANDLE event
)
1603 TRACE("iface %p, flags %#x, event %p.\n", iface
, flags
, event
);
1605 return ddraw7_WaitForVerticalBlank((IDirectDraw7
*)ddraw_from_ddraw2(iface
), flags
, event
);
1608 static HRESULT WINAPI
ddraw1_WaitForVerticalBlank(IDirectDraw
*iface
, DWORD flags
, HANDLE event
)
1610 TRACE("iface %p, flags %#x, event %p.\n", iface
, flags
, event
);
1612 return ddraw7_WaitForVerticalBlank((IDirectDraw7
*)ddraw_from_ddraw1(iface
), flags
, event
);
1615 /*****************************************************************************
1616 * IDirectDraw7::GetScanLine
1618 * Returns the scan line that is being drawn on the monitor
1621 * Scanline: Address to write the scan line value to
1624 * Always returns DD_OK
1626 *****************************************************************************/
1627 static HRESULT WINAPI
ddraw7_GetScanLine(IDirectDraw7
*iface
, DWORD
*Scanline
)
1629 IDirectDrawImpl
*This
= (IDirectDrawImpl
*)iface
;
1630 static BOOL hide
= FALSE
;
1631 WINED3DDISPLAYMODE Mode
;
1633 /* This function is called often, so print the fixme only once */
1634 EnterCriticalSection(&ddraw_cs
);
1637 FIXME("(%p)->(%p): Semi-Stub\n", This
, Scanline
);
1641 IWineD3DDevice_GetDisplayMode(This
->wineD3DDevice
,
1645 /* Fake the line sweeping of the monitor */
1646 /* FIXME: We should synchronize with a source to keep the refresh rate */
1647 *Scanline
= This
->cur_scanline
++;
1648 /* Assume 20 scan lines in the vertical blank */
1649 if (This
->cur_scanline
>= Mode
.Height
+ 20)
1650 This
->cur_scanline
= 0;
1652 LeaveCriticalSection(&ddraw_cs
);
1656 static HRESULT WINAPI
ddraw4_GetScanLine(IDirectDraw4
*iface
, DWORD
*line
)
1658 TRACE("iface %p, line %p.\n", iface
, line
);
1660 return ddraw7_GetScanLine((IDirectDraw7
*)ddraw_from_ddraw4(iface
), line
);
1663 static HRESULT WINAPI
ddraw3_GetScanLine(IDirectDraw3
*iface
, DWORD
*line
)
1665 TRACE("iface %p, line %p.\n", iface
, line
);
1667 return ddraw7_GetScanLine((IDirectDraw7
*)ddraw_from_ddraw3(iface
), line
);
1670 static HRESULT WINAPI
ddraw2_GetScanLine(IDirectDraw2
*iface
, DWORD
*line
)
1672 TRACE("iface %p, line %p.\n", iface
, line
);
1674 return ddraw7_GetScanLine((IDirectDraw7
*)ddraw_from_ddraw2(iface
), line
);
1677 static HRESULT WINAPI
ddraw1_GetScanLine(IDirectDraw
*iface
, DWORD
*line
)
1679 TRACE("iface %p, line %p.\n", iface
, line
);
1681 return ddraw7_GetScanLine((IDirectDraw7
*)ddraw_from_ddraw1(iface
), line
);
1684 /*****************************************************************************
1685 * IDirectDraw7::TestCooperativeLevel
1687 * Informs the application about the state of the video adapter, depending
1688 * on the cooperative level
1691 * DD_OK if the device is in a sane state
1692 * DDERR_NOEXCLUSIVEMODE or DDERR_EXCLUSIVEMODEALREADYSET
1693 * if the state is not correct(See below)
1695 *****************************************************************************/
1696 static HRESULT WINAPI
ddraw7_TestCooperativeLevel(IDirectDraw7
*iface
)
1698 TRACE("iface %p.\n", iface
);
1703 static HRESULT WINAPI
ddraw4_TestCooperativeLevel(IDirectDraw4
*iface
)
1705 TRACE("iface %p.\n", iface
);
1707 return ddraw7_TestCooperativeLevel((IDirectDraw7
*)ddraw_from_ddraw4(iface
));
1710 /*****************************************************************************
1711 * IDirectDraw7::GetGDISurface
1713 * Returns the surface that GDI is treating as the primary surface.
1714 * For Wine this is the front buffer
1717 * GDISurface: Address to write the surface pointer to
1720 * DD_OK if the surface was found
1721 * DDERR_NOTFOUND if the GDI surface wasn't found
1723 *****************************************************************************/
1724 static HRESULT WINAPI
ddraw7_GetGDISurface(IDirectDraw7
*iface
, IDirectDrawSurface7
**GDISurface
)
1726 IDirectDrawImpl
*This
= (IDirectDrawImpl
*)iface
;
1727 IWineD3DSurface
*Surf
;
1728 IDirectDrawSurface7
*ddsurf
;
1731 TRACE("(%p)->(%p)\n", This
, GDISurface
);
1733 /* Get the back buffer from the wineD3DDevice and search its
1734 * attached surfaces for the front buffer
1736 EnterCriticalSection(&ddraw_cs
);
1737 hr
= IWineD3DDevice_GetBackBuffer(This
->wineD3DDevice
,
1739 0, /* first back buffer*/
1740 WINED3DBACKBUFFER_TYPE_MONO
,
1743 if( (hr
!= D3D_OK
) ||
1746 ERR("IWineD3DDevice::GetBackBuffer failed\n");
1747 LeaveCriticalSection(&ddraw_cs
);
1748 return DDERR_NOTFOUND
;
1751 /* GetBackBuffer AddRef()ed the surface, release it */
1752 IWineD3DSurface_Release(Surf
);
1754 IWineD3DSurface_GetParent(Surf
,
1755 (IUnknown
**) &ddsurf
);
1756 IDirectDrawSurface7_Release(ddsurf
); /* For the GetParent */
1758 /* Find the front buffer */
1759 ddsCaps
.dwCaps
= DDSCAPS_FRONTBUFFER
;
1760 hr
= IDirectDrawSurface7_GetAttachedSurface(ddsurf
,
1765 ERR("IDirectDrawSurface7::GetAttachedSurface failed, hr = %x\n", hr
);
1768 /* The AddRef is OK this time */
1769 LeaveCriticalSection(&ddraw_cs
);
1773 static HRESULT WINAPI
ddraw4_GetGDISurface(IDirectDraw4
*iface
, IDirectDrawSurface4
**surface
)
1775 TRACE("iface %p, surface %p.\n", iface
, surface
);
1777 return ddraw7_GetGDISurface((IDirectDraw7
*)ddraw_from_ddraw4(iface
), (IDirectDrawSurface7
**)surface
);
1780 static HRESULT WINAPI
ddraw3_GetGDISurface(IDirectDraw3
*iface
, IDirectDrawSurface
**surface
)
1782 IDirectDrawSurface7
*surface7
;
1785 TRACE("iface %p, surface %p.\n", iface
, surface
);
1787 hr
= ddraw7_GetGDISurface((IDirectDraw7
*)ddraw_from_ddraw3(iface
), &surface7
);
1788 *surface
= surface7
? (IDirectDrawSurface
*)&((IDirectDrawSurfaceImpl
*)surface7
)->IDirectDrawSurface3_vtbl
: NULL
;
1793 static HRESULT WINAPI
ddraw2_GetGDISurface(IDirectDraw2
*iface
, IDirectDrawSurface
**surface
)
1795 IDirectDrawSurface7
*surface7
;
1798 TRACE("iface %p, surface %p.\n", iface
, surface
);
1800 hr
= ddraw7_GetGDISurface((IDirectDraw7
*)ddraw_from_ddraw2(iface
), &surface7
);
1801 *surface
= surface7
? (IDirectDrawSurface
*)&((IDirectDrawSurfaceImpl
*)surface7
)->IDirectDrawSurface3_vtbl
: NULL
;
1806 static HRESULT WINAPI
ddraw1_GetGDISurface(IDirectDraw
*iface
, IDirectDrawSurface
**surface
)
1808 IDirectDrawSurface7
*surface7
;
1811 TRACE("iface %p, surface %p.\n", iface
, surface
);
1813 hr
= ddraw7_GetGDISurface((IDirectDraw7
*)ddraw_from_ddraw1(iface
), &surface7
);
1814 *surface
= surface7
? (IDirectDrawSurface
*)&((IDirectDrawSurfaceImpl
*)surface7
)->IDirectDrawSurface3_vtbl
: NULL
;
1819 struct displaymodescallback_context
1821 LPDDENUMMODESCALLBACK func
;
1825 static HRESULT CALLBACK
EnumDisplayModesCallbackThunk(DDSURFACEDESC2
*surface_desc
, void *context
)
1827 struct displaymodescallback_context
*cbcontext
= context
;
1830 memcpy(&desc
, surface_desc
, sizeof(desc
));
1831 desc
.dwSize
= sizeof(desc
);
1833 return cbcontext
->func(&desc
, cbcontext
->context
);
1836 /*****************************************************************************
1837 * IDirectDraw7::EnumDisplayModes
1839 * Enumerates the supported Display modes. The modes can be filtered with
1840 * the DDSD parameter.
1843 * Flags: can be DDEDM_REFRESHRATES and DDEDM_STANDARDVGAMODES
1844 * DDSD: Surface description to filter the modes
1845 * Context: Pointer passed back to the callback function
1846 * cb: Application-provided callback function
1850 * DDERR_INVALIDPARAMS if the callback wasn't set
1852 *****************************************************************************/
1853 static HRESULT WINAPI
ddraw7_EnumDisplayModes(IDirectDraw7
*iface
, DWORD Flags
,
1854 DDSURFACEDESC2
*DDSD
, void *Context
, LPDDENUMMODESCALLBACK2 cb
)
1856 IDirectDrawImpl
*This
= (IDirectDrawImpl
*)iface
;
1857 unsigned int modenum
, fmt
;
1858 WINED3DFORMAT pixelformat
= WINED3DFMT_UNKNOWN
;
1859 WINED3DDISPLAYMODE mode
;
1860 DDSURFACEDESC2 callback_sd
;
1861 WINED3DDISPLAYMODE
*enum_modes
= NULL
;
1862 unsigned enum_mode_count
= 0, enum_mode_array_size
= 0;
1864 WINED3DFORMAT checkFormatList
[] =
1866 WINED3DFMT_B8G8R8X8_UNORM
,
1867 WINED3DFMT_B5G6R5_UNORM
,
1871 TRACE("(%p)->(%p,%p,%p): Relay\n", This
, DDSD
, Context
, cb
);
1873 EnterCriticalSection(&ddraw_cs
);
1874 /* This looks sane */
1877 LeaveCriticalSection(&ddraw_cs
);
1878 return DDERR_INVALIDPARAMS
;
1883 if ((DDSD
->dwFlags
& DDSD_PIXELFORMAT
) && (DDSD
->u4
.ddpfPixelFormat
.dwFlags
& DDPF_RGB
) )
1884 pixelformat
= PixelFormat_DD2WineD3D(&DDSD
->u4
.ddpfPixelFormat
);
1887 if(!(Flags
& DDEDM_REFRESHRATES
))
1889 enum_mode_array_size
= 16;
1890 enum_modes
= HeapAlloc(GetProcessHeap(), 0, sizeof(WINED3DDISPLAYMODE
) * enum_mode_array_size
);
1893 ERR("Out of memory\n");
1894 LeaveCriticalSection(&ddraw_cs
);
1895 return DDERR_OUTOFMEMORY
;
1899 for(fmt
= 0; fmt
< (sizeof(checkFormatList
) / sizeof(checkFormatList
[0])); fmt
++)
1901 if(pixelformat
!= WINED3DFMT_UNKNOWN
&& checkFormatList
[fmt
] != pixelformat
)
1907 while(IWineD3D_EnumAdapterModes(This
->wineD3D
,
1908 WINED3DADAPTER_DEFAULT
,
1909 checkFormatList
[fmt
],
1911 &mode
) == WINED3D_OK
)
1915 if(DDSD
->dwFlags
& DDSD_WIDTH
&& mode
.Width
!= DDSD
->dwWidth
) continue;
1916 if(DDSD
->dwFlags
& DDSD_HEIGHT
&& mode
.Height
!= DDSD
->dwHeight
) continue;
1919 if(!(Flags
& DDEDM_REFRESHRATES
))
1921 /* DX docs state EnumDisplayMode should return only unique modes. If DDEDM_REFRESHRATES is not set, refresh
1922 * rate doesn't matter when determining if the mode is unique. So modes only differing in refresh rate have
1923 * to be reduced to a single unique result in such case.
1928 for (i
= 0; i
< enum_mode_count
; i
++)
1930 if(enum_modes
[i
].Width
== mode
.Width
&& enum_modes
[i
].Height
== mode
.Height
&&
1931 enum_modes
[i
].Format
== mode
.Format
)
1941 memset(&callback_sd
, 0, sizeof(callback_sd
));
1942 callback_sd
.dwSize
= sizeof(callback_sd
);
1943 callback_sd
.u4
.ddpfPixelFormat
.dwSize
= sizeof(DDPIXELFORMAT
);
1945 callback_sd
.dwFlags
= DDSD_HEIGHT
|DDSD_WIDTH
|DDSD_PIXELFORMAT
|DDSD_PITCH
;
1946 if(Flags
& DDEDM_REFRESHRATES
)
1948 callback_sd
.dwFlags
|= DDSD_REFRESHRATE
;
1949 callback_sd
.u2
.dwRefreshRate
= mode
.RefreshRate
;
1952 callback_sd
.dwWidth
= mode
.Width
;
1953 callback_sd
.dwHeight
= mode
.Height
;
1955 PixelFormat_WineD3DtoDD(&callback_sd
.u4
.ddpfPixelFormat
, mode
.Format
);
1957 /* Calc pitch and DWORD align like MSDN says */
1958 callback_sd
.u1
.lPitch
= (callback_sd
.u4
.ddpfPixelFormat
.u1
.dwRGBBitCount
/ 8) * mode
.Width
;
1959 callback_sd
.u1
.lPitch
= (callback_sd
.u1
.lPitch
+ 3) & ~3;
1961 TRACE("Enumerating %dx%dx%d @%d\n", callback_sd
.dwWidth
, callback_sd
.dwHeight
, callback_sd
.u4
.ddpfPixelFormat
.u1
.dwRGBBitCount
,
1962 callback_sd
.u2
.dwRefreshRate
);
1964 if(cb(&callback_sd
, Context
) == DDENUMRET_CANCEL
)
1966 TRACE("Application asked to terminate the enumeration\n");
1967 HeapFree(GetProcessHeap(), 0, enum_modes
);
1968 LeaveCriticalSection(&ddraw_cs
);
1972 if(!(Flags
& DDEDM_REFRESHRATES
))
1974 if (enum_mode_count
== enum_mode_array_size
)
1976 WINED3DDISPLAYMODE
*new_enum_modes
;
1978 enum_mode_array_size
*= 2;
1979 new_enum_modes
= HeapReAlloc(GetProcessHeap(), 0, enum_modes
, sizeof(WINED3DDISPLAYMODE
) * enum_mode_array_size
);
1981 if (!new_enum_modes
)
1983 ERR("Out of memory\n");
1984 HeapFree(GetProcessHeap(), 0, enum_modes
);
1985 LeaveCriticalSection(&ddraw_cs
);
1986 return DDERR_OUTOFMEMORY
;
1989 enum_modes
= new_enum_modes
;
1992 enum_modes
[enum_mode_count
++] = mode
;
1997 TRACE("End of enumeration\n");
1998 HeapFree(GetProcessHeap(), 0, enum_modes
);
1999 LeaveCriticalSection(&ddraw_cs
);
2003 static HRESULT WINAPI
ddraw4_EnumDisplayModes(IDirectDraw4
*iface
, DWORD flags
,
2004 DDSURFACEDESC2
*surface_desc
, void *context
, LPDDENUMMODESCALLBACK2 callback
)
2006 TRACE("iface %p, flags %#x, surface_desc %p, context %p, callback %p.\n",
2007 iface
, flags
, surface_desc
, context
, callback
);
2009 return ddraw7_EnumDisplayModes((IDirectDraw7
*)ddraw_from_ddraw4(iface
), flags
,
2010 surface_desc
, context
, callback
);
2013 static HRESULT WINAPI
ddraw3_EnumDisplayModes(IDirectDraw3
*iface
, DWORD flags
,
2014 DDSURFACEDESC
*surface_desc
, void *context
, LPDDENUMMODESCALLBACK callback
)
2016 struct displaymodescallback_context cbcontext
;
2018 TRACE("iface %p, flags %#x, surface_desc %p, context %p, callback %p.\n",
2019 iface
, flags
, surface_desc
, context
, callback
);
2021 cbcontext
.func
= callback
;
2022 cbcontext
.context
= context
;
2024 return ddraw7_EnumDisplayModes((IDirectDraw7
*)ddraw_from_ddraw3(iface
), flags
,
2025 (DDSURFACEDESC2
*)surface_desc
, &cbcontext
, EnumDisplayModesCallbackThunk
);
2028 static HRESULT WINAPI
ddraw2_EnumDisplayModes(IDirectDraw2
*iface
, DWORD flags
,
2029 DDSURFACEDESC
*surface_desc
, void *context
, LPDDENUMMODESCALLBACK callback
)
2031 struct displaymodescallback_context cbcontext
;
2033 TRACE("iface %p, flags %#x, surface_desc %p, context %p, callback %p.\n",
2034 iface
, flags
, surface_desc
, context
, callback
);
2036 cbcontext
.func
= callback
;
2037 cbcontext
.context
= context
;
2039 return ddraw7_EnumDisplayModes((IDirectDraw7
*)ddraw_from_ddraw2(iface
), flags
,
2040 (DDSURFACEDESC2
*)surface_desc
, &cbcontext
, EnumDisplayModesCallbackThunk
);
2043 static HRESULT WINAPI
ddraw1_EnumDisplayModes(IDirectDraw
*iface
, DWORD flags
,
2044 DDSURFACEDESC
*surface_desc
, void *context
, LPDDENUMMODESCALLBACK callback
)
2046 struct displaymodescallback_context cbcontext
;
2048 TRACE("iface %p, flags %#x, surface_desc %p, context %p, callback %p.\n",
2049 iface
, flags
, surface_desc
, context
, callback
);
2051 cbcontext
.func
= callback
;
2052 cbcontext
.context
= context
;
2054 return ddraw7_EnumDisplayModes((IDirectDraw7
*)ddraw_from_ddraw1(iface
), flags
,
2055 (DDSURFACEDESC2
*)surface_desc
, &cbcontext
, EnumDisplayModesCallbackThunk
);
2058 /*****************************************************************************
2059 * IDirectDraw7::EvaluateMode
2061 * Used with IDirectDraw7::StartModeTest to test video modes.
2062 * EvaluateMode is used to pass or fail a mode, and continue with the next
2066 * Flags: DDEM_MODEPASSED or DDEM_MODEFAILED
2067 * Timeout: Returns the amount of seconds left before the mode would have
2068 * been failed automatically
2071 * This implementation always DD_OK, because it's a stub
2073 *****************************************************************************/
2074 static HRESULT WINAPI
ddraw7_EvaluateMode(IDirectDraw7
*iface
, DWORD Flags
, DWORD
*Timeout
)
2076 IDirectDrawImpl
*This
= (IDirectDrawImpl
*)iface
;
2077 FIXME("(%p)->(%d,%p): Stub!\n", This
, Flags
, Timeout
);
2079 /* When implementing this, implement it in WineD3D */
2084 /*****************************************************************************
2085 * IDirectDraw7::GetDeviceIdentifier
2087 * Returns the device identifier, which gives information about the driver
2088 * Our device identifier is defined at the beginning of this file.
2091 * DDDI: Address for the returned structure
2092 * Flags: Can be DDGDI_GETHOSTIDENTIFIER
2095 * On success it returns DD_OK
2096 * DDERR_INVALIDPARAMS if DDDI is NULL
2098 *****************************************************************************/
2099 static HRESULT WINAPI
ddraw7_GetDeviceIdentifier(IDirectDraw7
*iface
,
2100 DDDEVICEIDENTIFIER2
*DDDI
, DWORD Flags
)
2102 IDirectDrawImpl
*This
= (IDirectDrawImpl
*)iface
;
2103 TRACE("(%p)->(%p,%08x)\n", This
, DDDI
, Flags
);
2106 return DDERR_INVALIDPARAMS
;
2108 /* The DDGDI_GETHOSTIDENTIFIER returns the information about the 2D
2109 * host adapter, if there's a secondary 3D adapter. This doesn't apply
2110 * to any modern hardware, nor is it interesting for Wine, so ignore it.
2111 * Size of DDDEVICEIDENTIFIER2 may be aligned to 8 bytes and thus 4
2112 * bytes too long. So only copy the relevant part of the structure
2115 memcpy(DDDI
, &deviceidentifier
, FIELD_OFFSET(DDDEVICEIDENTIFIER2
, dwWHQLLevel
) + sizeof(DWORD
));
2119 static HRESULT WINAPI
ddraw4_GetDeviceIdentifier(IDirectDraw4
*iface
,
2120 DDDEVICEIDENTIFIER
*identifier
, DWORD flags
)
2122 DDDEVICEIDENTIFIER2 identifier2
;
2125 TRACE("iface %p, identifier %p, flags %#x.\n", iface
, identifier
, flags
);
2127 hr
= ddraw7_GetDeviceIdentifier((IDirectDraw7
*)ddraw_from_ddraw4(iface
), &identifier2
, flags
);
2128 DDRAW_Convert_DDDEVICEIDENTIFIER_2_To_1(&identifier2
, identifier
);
2133 /*****************************************************************************
2134 * IDirectDraw7::GetSurfaceFromDC
2136 * Returns the Surface for a GDI device context handle.
2137 * Is this related to IDirectDrawSurface::GetDC ???
2140 * hdc: hdc to return the surface for
2141 * Surface: Address to write the surface pointer to
2144 * Always returns DD_OK because it's a stub
2146 *****************************************************************************/
2147 static HRESULT WINAPI
ddraw7_GetSurfaceFromDC(IDirectDraw7
*iface
, HDC hdc
, IDirectDrawSurface7
**Surface
)
2149 IDirectDrawImpl
*This
= (IDirectDrawImpl
*)iface
;
2150 IWineD3DSurface
*wined3d_surface
;
2153 TRACE("iface %p, dc %p, surface %p.\n", iface
, hdc
, Surface
);
2155 if (!Surface
) return E_INVALIDARG
;
2157 hr
= IWineD3DDevice_GetSurfaceFromDC(This
->wineD3DDevice
, hdc
, &wined3d_surface
);
2160 TRACE("No surface found for dc %p.\n", hdc
);
2162 return DDERR_NOTFOUND
;
2165 IWineD3DSurface_GetParent(wined3d_surface
, (IUnknown
**)Surface
);
2166 TRACE("Returning surface %p.\n", Surface
);
2170 static HRESULT WINAPI
ddraw4_GetSurfaceFromDC(IDirectDraw4
*iface
, HDC dc
, IDirectDrawSurface4
**surface
)
2172 IDirectDrawSurface7
*surface7
;
2175 TRACE("iface %p, dc %p, surface %p.\n", iface
, dc
, surface
);
2177 if (!surface
) return E_INVALIDARG
;
2179 hr
= ddraw7_GetSurfaceFromDC((IDirectDraw7
*)ddraw_from_ddraw4(iface
), dc
, &surface7
);
2180 *surface
= surface7
? (IDirectDrawSurface4
*)&((IDirectDrawSurfaceImpl
*)surface7
)->IDirectDrawSurface3_vtbl
: NULL
;
2185 static HRESULT WINAPI
ddraw3_GetSurfaceFromDC(IDirectDraw3
*iface
, HDC dc
, IDirectDrawSurface
**surface
)
2187 TRACE("iface %p, dc %p, surface %p.\n", iface
, dc
, surface
);
2189 return ddraw7_GetSurfaceFromDC((IDirectDraw7
*)ddraw_from_ddraw3(iface
),
2190 dc
, (IDirectDrawSurface7
**)surface
);
2193 /*****************************************************************************
2194 * IDirectDraw7::RestoreAllSurfaces
2196 * Calls the restore method of all surfaces
2201 * Always returns DD_OK because it's a stub
2203 *****************************************************************************/
2204 static HRESULT WINAPI
ddraw7_RestoreAllSurfaces(IDirectDraw7
*iface
)
2206 IDirectDrawImpl
*This
= (IDirectDrawImpl
*)iface
;
2207 FIXME("(%p): Stub\n", This
);
2209 /* This isn't hard to implement: Enumerate all WineD3D surfaces,
2210 * get their parent and call their restore method. Do not implement
2211 * it in WineD3D, as restoring a surface means re-creating the
2217 static HRESULT WINAPI
ddraw4_RestoreAllSurfaces(IDirectDraw4
*iface
)
2219 TRACE("iface %p.\n", iface
);
2221 return ddraw7_RestoreAllSurfaces((IDirectDraw7
*)ddraw_from_ddraw4(iface
));
2224 /*****************************************************************************
2225 * IDirectDraw7::StartModeTest
2227 * Tests the specified video modes to update the system registry with
2228 * refresh rate information. StartModeTest starts the mode test,
2229 * EvaluateMode is used to fail or pass a mode. If EvaluateMode
2230 * isn't called within 15 seconds, the mode is failed automatically
2232 * As refresh rates are handled by the X server, I don't think this
2233 * Method is important
2236 * Modes: An array of mode specifications
2237 * NumModes: The number of modes in Modes
2238 * Flags: Some flags...
2241 * Returns DDERR_TESTFINISHED if flags contains DDSMT_ISTESTREQUIRED,
2242 * if no modes are passed, DDERR_INVALIDPARAMS is returned,
2245 *****************************************************************************/
2246 static HRESULT WINAPI
ddraw7_StartModeTest(IDirectDraw7
*iface
, SIZE
*Modes
, DWORD NumModes
, DWORD Flags
)
2248 IDirectDrawImpl
*This
= (IDirectDrawImpl
*)iface
;
2249 WARN("(%p)->(%p, %d, %x): Semi-Stub, most likely harmless\n", This
, Modes
, NumModes
, Flags
);
2251 /* This looks sane */
2252 if( (!Modes
) || (NumModes
== 0) ) return DDERR_INVALIDPARAMS
;
2254 /* DDSMT_ISTESTREQUIRED asks if a mode test is necessary.
2255 * As it is not, DDERR_TESTFINISHED is returned
2256 * (hopefully that's correct
2258 if(Flags & DDSMT_ISTESTREQUIRED) return DDERR_TESTFINISHED;
2259 * well, that value doesn't (yet) exist in the wine headers, so ignore it
2265 /*****************************************************************************
2266 * ddraw_recreate_surfaces_cb
2268 * Enumeration callback for ddraw_recreate_surface.
2269 * It re-recreates the WineD3DSurface. It's pretty straightforward
2271 *****************************************************************************/
2272 HRESULT WINAPI
ddraw_recreate_surfaces_cb(IDirectDrawSurface7
*surf
, DDSURFACEDESC2
*desc
, void *Context
)
2274 IDirectDrawSurfaceImpl
*surfImpl
= (IDirectDrawSurfaceImpl
*)surf
;
2275 IDirectDrawImpl
*This
= surfImpl
->ddraw
;
2277 IWineD3DSurface
*wineD3DSurface
;
2278 IWineD3DSwapChain
*swapchain
;
2280 IWineD3DClipper
*clipper
= NULL
;
2282 WINED3DSURFACE_DESC Desc
;
2283 WINED3DFORMAT Format
;
2287 WINED3DMULTISAMPLE_TYPE MultiSampleType
;
2288 DWORD MultiSampleQuality
;
2292 TRACE("(%p): Enumerated Surface %p\n", This
, surfImpl
);
2294 /* For the enumeration */
2295 IDirectDrawSurface7_Release(surf
);
2297 if(surfImpl
->ImplType
== This
->ImplType
) return DDENUMRET_OK
; /* Continue */
2299 /* Get the objects */
2300 swapchain
= surfImpl
->wineD3DSwapChain
;
2301 surfImpl
->wineD3DSwapChain
= NULL
;
2302 wineD3DSurface
= surfImpl
->WineD3DSurface
;
2304 /* get the clipper */
2305 IWineD3DSurface_GetClipper(wineD3DSurface
, &clipper
);
2307 /* Get the surface properties */
2308 hr
= IWineD3DSurface_GetDesc(wineD3DSurface
, &Desc
);
2309 if(hr
!= D3D_OK
) return hr
;
2311 Format
= Desc
.format
;
2314 MultiSampleType
= Desc
.multisample_type
;
2315 MultiSampleQuality
= Desc
.multisample_quality
;
2317 Height
= Desc
.height
;
2319 IWineD3DSurface_GetParent(wineD3DSurface
, &Parent
);
2321 /* Create the new surface */
2322 hr
= IWineD3DDevice_CreateSurface(This
->wineD3DDevice
, Width
, Height
, Format
,
2323 TRUE
/* Lockable */, FALSE
/* Discard */, surfImpl
->mipmap_level
, &surfImpl
->WineD3DSurface
, Usage
, Pool
,
2324 MultiSampleType
, MultiSampleQuality
, This
->ImplType
, Parent
, &ddraw_null_wined3d_parent_ops
);
2325 IUnknown_Release(Parent
);
2328 surfImpl
->WineD3DSurface
= wineD3DSurface
;
2332 IWineD3DSurface_SetClipper(surfImpl
->WineD3DSurface
, clipper
);
2334 /* TODO: Copy the surface content, except for render targets */
2336 /* If there's a swapchain, it owns the wined3d surfaces. So Destroy
2340 /* The backbuffers have the swapchain set as well, but the primary
2341 * owns it and destroys it
2343 if(surfImpl
->surface_desc
.ddsCaps
.dwCaps
& DDSCAPS_PRIMARYSURFACE
) {
2344 IWineD3DDevice_UninitGDI(This
->wineD3DDevice
, D3D7CB_DestroySwapChain
);
2346 surfImpl
->isRenderTarget
= FALSE
;
2348 if(IWineD3DSurface_Release(wineD3DSurface
) == 0)
2349 TRACE("Surface released successful, next surface\n");
2351 ERR("Something's still holding the old WineD3DSurface\n");
2354 surfImpl
->ImplType
= This
->ImplType
;
2358 IWineD3DClipper_Release(clipper
);
2360 return DDENUMRET_OK
;
2363 /*****************************************************************************
2364 * ddraw_recreate_surfaces
2366 * A function, that converts all wineD3DSurfaces to the new implementation type
2367 * It enumerates all surfaces with IWineD3DDevice::EnumSurfaces, creates a
2368 * new WineD3DSurface, copies the content and releases the old surface
2370 *****************************************************************************/
2371 static HRESULT
ddraw_recreate_surfaces(IDirectDrawImpl
*This
)
2373 DDSURFACEDESC2 desc
;
2374 TRACE("(%p): Switch to implementation %d\n", This
, This
->ImplType
);
2376 if(This
->ImplType
!= SURFACE_OPENGL
&& This
->d3d_initialized
)
2378 /* Should happen almost never */
2379 FIXME("(%p) Switching to non-opengl surfaces with d3d started. Is this a bug?\n", This
);
2381 IWineD3DDevice_Uninit3D(This
->wineD3DDevice
, D3D7CB_DestroySwapChain
);
2383 /* Contrary: D3D starting is handled by the caller, because it knows the render target */
2385 memset(&desc
, 0, sizeof(desc
));
2386 desc
.dwSize
= sizeof(desc
);
2388 return IDirectDraw7_EnumSurfaces((IDirectDraw7
*)This
, 0, &desc
, This
, ddraw_recreate_surfaces_cb
);
2391 ULONG WINAPI
D3D7CB_DestroySwapChain(IWineD3DSwapChain
*pSwapChain
) {
2392 IUnknown
* swapChainParent
;
2393 TRACE("(%p) call back\n", pSwapChain
);
2395 IWineD3DSwapChain_GetParent(pSwapChain
, &swapChainParent
);
2396 IUnknown_Release(swapChainParent
);
2397 return IUnknown_Release(swapChainParent
);
2400 /*****************************************************************************
2401 * ddraw_create_surface
2403 * A helper function for IDirectDraw7::CreateSurface. It creates a new surface
2404 * with the passed parameters.
2407 * DDSD: Description of the surface to create
2408 * Surf: Address to store the interface pointer at
2413 *****************************************************************************/
2414 static HRESULT
ddraw_create_surface(IDirectDrawImpl
*This
, DDSURFACEDESC2
*pDDSD
,
2415 IDirectDrawSurfaceImpl
**ppSurf
, UINT level
)
2419 WINED3DFORMAT Format
= WINED3DFMT_UNKNOWN
;
2421 WINED3DSURFTYPE ImplType
= This
->ImplType
;
2422 WINED3DSURFACE_DESC Desc
;
2423 WINED3DPOOL Pool
= WINED3DPOOL_DEFAULT
;
2425 if (TRACE_ON(ddraw
))
2427 TRACE(" (%p) Requesting surface desc :\n", This
);
2428 DDRAW_dump_surface_desc(pDDSD
);
2431 /* Select the surface type, if it wasn't choosen yet */
2432 if(ImplType
== SURFACE_UNKNOWN
)
2434 /* Use GL Surfaces if a D3DDEVICE Surface is requested */
2435 if(pDDSD
->ddsCaps
.dwCaps
& DDSCAPS_3DDEVICE
)
2437 TRACE("(%p) Choosing GL surfaces because a 3DDEVICE Surface was requested\n", This
);
2438 ImplType
= SURFACE_OPENGL
;
2441 /* Otherwise use GDI surfaces for now */
2444 TRACE("(%p) Choosing GDI surfaces for 2D rendering\n", This
);
2445 ImplType
= SURFACE_GDI
;
2448 /* Policy if all surface implementations are available:
2449 * First, check if a default type was set with winecfg. If not,
2450 * try Xrender surfaces, and use them if they work. Next, check if
2451 * accelerated OpenGL is available, and use GL surfaces in this
2452 * case. If all else fails, use GDI surfaces. If a 3DDEVICE surface
2453 * was created, always use OpenGL surfaces.
2455 * (Note: Xrender surfaces are not implemented for now, the
2456 * unaccelerated implementation uses GDI to render in Software)
2459 /* Store the type. If it needs to be changed, all WineD3DSurfaces have to
2460 * be re-created. This could be done with IDirectDrawSurface7::Restore
2462 This
->ImplType
= ImplType
;
2466 if ((pDDSD
->ddsCaps
.dwCaps
& DDSCAPS_3DDEVICE
)
2467 && (This
->ImplType
!= SURFACE_OPENGL
)
2468 && DefaultSurfaceType
== SURFACE_UNKNOWN
)
2470 /* We have to change to OpenGL,
2471 * and re-create all WineD3DSurfaces
2473 ImplType
= SURFACE_OPENGL
;
2474 This
->ImplType
= ImplType
;
2475 TRACE("(%p) Re-creating all surfaces\n", This
);
2476 ddraw_recreate_surfaces(This
);
2477 TRACE("(%p) Done recreating all surfaces\n", This
);
2479 else if(This
->ImplType
!= SURFACE_OPENGL
&& pDDSD
->ddsCaps
.dwCaps
& DDSCAPS_3DDEVICE
)
2481 WARN("The application requests a 3D capable surface, but a non-opengl surface was set in the registry\n");
2482 /* Do not fail surface creation, only fail 3D device creation */
2486 if (!(pDDSD
->ddsCaps
.dwCaps
& (DDSCAPS_VIDEOMEMORY
| DDSCAPS_SYSTEMMEMORY
)) &&
2487 !((pDDSD
->ddsCaps
.dwCaps
& DDSCAPS_TEXTURE
) && (pDDSD
->ddsCaps
.dwCaps2
& DDSCAPS2_TEXTUREMANAGE
)) )
2489 /* Tests show surfaces without memory flags get these flags added right after creation. */
2490 pDDSD
->ddsCaps
.dwCaps
|= DDSCAPS_LOCALVIDMEM
| DDSCAPS_VIDEOMEMORY
;
2492 /* Get the correct wined3d usage */
2493 if (pDDSD
->ddsCaps
.dwCaps
& (DDSCAPS_PRIMARYSURFACE
|
2494 DDSCAPS_3DDEVICE
) )
2496 Usage
|= WINED3DUSAGE_RENDERTARGET
;
2498 pDDSD
->ddsCaps
.dwCaps
|= DDSCAPS_VISIBLE
;
2500 if (pDDSD
->ddsCaps
.dwCaps
& (DDSCAPS_OVERLAY
))
2502 Usage
|= WINED3DUSAGE_OVERLAY
;
2504 if(This
->depthstencil
|| (pDDSD
->ddsCaps
.dwCaps
& DDSCAPS_ZBUFFER
) )
2506 /* The depth stencil creation callback sets this flag.
2507 * Set the WineD3D usage to let it know that it's a depth
2510 Usage
|= WINED3DUSAGE_DEPTHSTENCIL
;
2512 if(pDDSD
->ddsCaps
.dwCaps
& DDSCAPS_SYSTEMMEMORY
)
2514 Pool
= WINED3DPOOL_SYSTEMMEM
;
2516 else if(pDDSD
->ddsCaps
.dwCaps2
& DDSCAPS2_TEXTUREMANAGE
)
2518 Pool
= WINED3DPOOL_MANAGED
;
2519 /* Managed textures have the system memory flag set */
2520 pDDSD
->ddsCaps
.dwCaps
|= DDSCAPS_SYSTEMMEMORY
;
2522 else if(pDDSD
->ddsCaps
.dwCaps
& DDSCAPS_VIDEOMEMORY
)
2524 /* Videomemory adds localvidmem, this is mutually exclusive with systemmemory
2527 pDDSD
->ddsCaps
.dwCaps
|= DDSCAPS_LOCALVIDMEM
;
2530 Format
= PixelFormat_DD2WineD3D(&pDDSD
->u4
.ddpfPixelFormat
);
2531 if(Format
== WINED3DFMT_UNKNOWN
)
2533 ERR("Unsupported / Unknown pixelformat\n");
2534 return DDERR_INVALIDPIXELFORMAT
;
2537 /* Create the Surface object */
2538 *ppSurf
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(IDirectDrawSurfaceImpl
));
2541 ERR("(%p) Error allocating memory for a surface\n", This
);
2542 return DDERR_OUTOFVIDEOMEMORY
;
2544 (*ppSurf
)->lpVtbl
= &IDirectDrawSurface7_Vtbl
;
2545 (*ppSurf
)->IDirectDrawSurface3_vtbl
= &IDirectDrawSurface3_Vtbl
;
2546 (*ppSurf
)->IDirectDrawGammaControl_vtbl
= &IDirectDrawGammaControl_Vtbl
;
2547 (*ppSurf
)->IDirect3DTexture2_vtbl
= &IDirect3DTexture2_Vtbl
;
2548 (*ppSurf
)->IDirect3DTexture_vtbl
= &IDirect3DTexture1_Vtbl
;
2550 (*ppSurf
)->version
= 7;
2551 TRACE("%p->version = %d\n", (*ppSurf
), (*ppSurf
)->version
);
2552 (*ppSurf
)->ddraw
= This
;
2553 (*ppSurf
)->surface_desc
.dwSize
= sizeof(DDSURFACEDESC2
);
2554 (*ppSurf
)->surface_desc
.u4
.ddpfPixelFormat
.dwSize
= sizeof(DDPIXELFORMAT
);
2555 DD_STRUCT_COPY_BYSIZE(&(*ppSurf
)->surface_desc
, pDDSD
);
2557 /* Surface attachments */
2558 (*ppSurf
)->next_attached
= NULL
;
2559 (*ppSurf
)->first_attached
= *ppSurf
;
2561 /* Needed to re-create the surface on an implementation change */
2562 (*ppSurf
)->ImplType
= ImplType
;
2564 /* For D3DDevice creation */
2565 (*ppSurf
)->isRenderTarget
= FALSE
;
2567 /* A trace message for debugging */
2568 TRACE("(%p) Created IDirectDrawSurface implementation structure at %p\n", This
, *ppSurf
);
2570 /* Now create the WineD3D Surface */
2571 hr
= IWineD3DDevice_CreateSurface(This
->wineD3DDevice
, pDDSD
->dwWidth
, pDDSD
->dwHeight
, Format
,
2572 TRUE
/* Lockable */, FALSE
/* Discard */, level
, &(*ppSurf
)->WineD3DSurface
,
2573 Usage
, Pool
, WINED3DMULTISAMPLE_NONE
, 0 /* MultiSampleQuality */, ImplType
,
2574 (IUnknown
*)*ppSurf
, &ddraw_null_wined3d_parent_ops
);
2578 ERR("IWineD3DDevice::CreateSurface failed. hr = %08x\n", hr
);
2582 /* Increase the surface counter, and attach the surface */
2583 InterlockedIncrement(&This
->surfaces
);
2584 list_add_head(&This
->surface_list
, &(*ppSurf
)->surface_list_entry
);
2586 /* Here we could store all created surfaces in the DirectDrawImpl structure,
2587 * But this could also be delegated to WineDDraw, as it keeps track of all its
2588 * resources. Not implemented for now, as there are more important things ;)
2591 /* Get the pixel format of the WineD3DSurface and store it.
2592 * Don't use the Format choosen above, WineD3D might have
2595 (*ppSurf
)->surface_desc
.dwFlags
|= DDSD_PIXELFORMAT
;
2596 hr
= IWineD3DSurface_GetDesc((*ppSurf
)->WineD3DSurface
, &Desc
);
2599 ERR("IWineD3DSurface::GetDesc failed\n");
2600 IDirectDrawSurface7_Release( (IDirectDrawSurface7
*) *ppSurf
);
2604 Format
= Desc
.format
;
2606 Height
= Desc
.height
;
2608 if(Format
== WINED3DFMT_UNKNOWN
)
2610 FIXME("IWineD3DSurface::GetDesc returned WINED3DFMT_UNKNOWN\n");
2612 PixelFormat_WineD3DtoDD( &(*ppSurf
)->surface_desc
.u4
.ddpfPixelFormat
, Format
);
2614 /* Anno 1602 stores the pitch right after surface creation, so make sure it's there.
2615 * I can't LockRect() the surface here because if OpenGL surfaces are in use, the
2616 * WineD3DDevice might not be usable for 3D yet, so an extra method was created.
2617 * TODO: Test other fourcc formats
2619 if(Format
== WINED3DFMT_DXT1
|| Format
== WINED3DFMT_DXT2
|| Format
== WINED3DFMT_DXT3
||
2620 Format
== WINED3DFMT_DXT4
|| Format
== WINED3DFMT_DXT5
)
2622 (*ppSurf
)->surface_desc
.dwFlags
|= DDSD_LINEARSIZE
;
2623 if(Format
== WINED3DFMT_DXT1
)
2625 (*ppSurf
)->surface_desc
.u1
.dwLinearSize
= max(4, Width
) * max(4, Height
) / 2;
2629 (*ppSurf
)->surface_desc
.u1
.dwLinearSize
= max(4, Width
) * max(4, Height
);
2634 (*ppSurf
)->surface_desc
.dwFlags
|= DDSD_PITCH
;
2635 (*ppSurf
)->surface_desc
.u1
.lPitch
= IWineD3DSurface_GetPitch((*ppSurf
)->WineD3DSurface
);
2638 /* Application passed a color key? Set it! */
2639 if(pDDSD
->dwFlags
& DDSD_CKDESTOVERLAY
)
2641 IWineD3DSurface_SetColorKey((*ppSurf
)->WineD3DSurface
,
2643 (WINEDDCOLORKEY
*) &pDDSD
->u3
.ddckCKDestOverlay
);
2645 if(pDDSD
->dwFlags
& DDSD_CKDESTBLT
)
2647 IWineD3DSurface_SetColorKey((*ppSurf
)->WineD3DSurface
,
2649 (WINEDDCOLORKEY
*) &pDDSD
->ddckCKDestBlt
);
2651 if(pDDSD
->dwFlags
& DDSD_CKSRCOVERLAY
)
2653 IWineD3DSurface_SetColorKey((*ppSurf
)->WineD3DSurface
,
2655 (WINEDDCOLORKEY
*) &pDDSD
->ddckCKSrcOverlay
);
2657 if(pDDSD
->dwFlags
& DDSD_CKSRCBLT
)
2659 IWineD3DSurface_SetColorKey((*ppSurf
)->WineD3DSurface
,
2661 (WINEDDCOLORKEY
*) &pDDSD
->ddckCKSrcBlt
);
2663 if ( pDDSD
->dwFlags
& DDSD_LPSURFACE
)
2665 hr
= IWineD3DSurface_SetMem((*ppSurf
)->WineD3DSurface
, pDDSD
->lpSurface
);
2666 if(hr
!= WINED3D_OK
)
2668 /* No need for a trace here, wined3d does that for us */
2669 IDirectDrawSurface7_Release((IDirectDrawSurface7
*)*ppSurf
);
2676 /*****************************************************************************
2677 * CreateAdditionalSurfaces
2679 * Creates a new mipmap chain.
2682 * root: Root surface to attach the newly created chain to
2683 * count: number of surfaces to create
2684 * DDSD: Description of the surface. Intentionally not a pointer to avoid side
2685 * effects on the caller
2686 * CubeFaceRoot: Whether the new surface is a root of a cube map face. This
2687 * creates an additional surface without the mipmapping flags
2689 *****************************************************************************/
2691 CreateAdditionalSurfaces(IDirectDrawImpl
*This
,
2692 IDirectDrawSurfaceImpl
*root
,
2694 DDSURFACEDESC2 DDSD
,
2697 UINT i
, j
, level
= 0;
2699 IDirectDrawSurfaceImpl
*last
= root
;
2701 for(i
= 0; i
< count
; i
++)
2703 IDirectDrawSurfaceImpl
*object2
= NULL
;
2705 /* increase the mipmap level, but only if a mipmap is created
2706 * In this case, also halve the size
2708 if(DDSD
.ddsCaps
.dwCaps
& DDSCAPS_MIPMAP
&& !CubeFaceRoot
)
2711 if(DDSD
.dwWidth
> 1) DDSD
.dwWidth
/= 2;
2712 if(DDSD
.dwHeight
> 1) DDSD
.dwHeight
/= 2;
2713 /* Set the mipmap sublevel flag according to msdn */
2714 DDSD
.ddsCaps
.dwCaps2
|= DDSCAPS2_MIPMAPSUBLEVEL
;
2718 DDSD
.ddsCaps
.dwCaps2
&= ~DDSCAPS2_MIPMAPSUBLEVEL
;
2720 CubeFaceRoot
= FALSE
;
2722 hr
= ddraw_create_surface(This
, &DDSD
, &object2
, level
);
2728 /* Add the new surface to the complex attachment array */
2729 for(j
= 0; j
< MAX_COMPLEX_ATTACHED
; j
++)
2731 if(last
->complex_array
[j
]) continue;
2732 last
->complex_array
[j
] = object2
;
2737 /* Remove the (possible) back buffer cap from the new surface description,
2738 * because only one surface in the flipping chain is a back buffer, one
2739 * is a front buffer, the others are just primary surfaces.
2741 DDSD
.ddsCaps
.dwCaps
&= ~DDSCAPS_BACKBUFFER
;
2746 /* Must set all attached surfaces (e.g. mipmaps) versions as well */
2747 static void ddraw_set_surface_version(IDirectDrawSurfaceImpl
*surface
, UINT version
)
2751 TRACE("surface %p, version %u -> %u.\n", surface
, surface
->version
, version
);
2753 surface
->version
= version
;
2754 for (i
= 0; i
< MAX_COMPLEX_ATTACHED
; ++i
)
2756 if (!surface
->complex_array
[i
]) break;
2757 ddraw_set_surface_version(surface
->complex_array
[i
], version
);
2759 while ((surface
= surface
->next_attached
))
2761 ddraw_set_surface_version(surface
, version
);
2765 /*****************************************************************************
2766 * ddraw_attach_d3d_device
2768 * Initializes the D3D capabilities of WineD3D
2771 * primary: The primary surface for D3D
2777 *****************************************************************************/
2778 static HRESULT
ddraw_attach_d3d_device(IDirectDrawImpl
*ddraw
, IDirectDrawSurfaceImpl
*primary
)
2780 WINED3DPRESENT_PARAMETERS localParameters
;
2781 HWND window
= ddraw
->dest_window
;
2784 TRACE("ddraw %p, primary %p.\n", ddraw
, primary
);
2786 if (!window
|| window
== GetDesktopWindow())
2788 window
= CreateWindowExA(0, DDRAW_WINDOW_CLASS_NAME
, "Hidden D3D Window",
2789 WS_DISABLED
, 0, 0, GetSystemMetrics(SM_CXSCREEN
), GetSystemMetrics(SM_CYSCREEN
),
2790 NULL
, NULL
, NULL
, NULL
);
2793 ERR("Failed to create window, last error %#x.\n", GetLastError());
2797 ShowWindow(window
, SW_HIDE
); /* Just to be sure */
2798 WARN("No window for the Direct3DDevice, created hidden window %p.\n", window
);
2802 TRACE("Using existing window %p for Direct3D rendering.\n", window
);
2804 ddraw
->d3d_window
= window
;
2806 /* Store the future Render Target surface */
2807 ddraw
->d3d_target
= primary
;
2809 /* Use the surface description for the device parameters, not the device
2810 * settings. The application might render to an offscreen surface. */
2811 localParameters
.BackBufferWidth
= primary
->surface_desc
.dwWidth
;
2812 localParameters
.BackBufferHeight
= primary
->surface_desc
.dwHeight
;
2813 localParameters
.BackBufferFormat
= PixelFormat_DD2WineD3D(&primary
->surface_desc
.u4
.ddpfPixelFormat
);
2814 localParameters
.BackBufferCount
= (primary
->surface_desc
.dwFlags
& DDSD_BACKBUFFERCOUNT
)
2815 ? primary
->surface_desc
.dwBackBufferCount
: 0;
2816 localParameters
.MultiSampleType
= WINED3DMULTISAMPLE_NONE
;
2817 localParameters
.MultiSampleQuality
= 0;
2818 localParameters
.SwapEffect
= WINED3DSWAPEFFECT_COPY
;
2819 localParameters
.hDeviceWindow
= window
;
2820 localParameters
.Windowed
= !(ddraw
->cooperative_level
& DDSCL_FULLSCREEN
);
2821 localParameters
.EnableAutoDepthStencil
= TRUE
;
2822 localParameters
.AutoDepthStencilFormat
= WINED3DFMT_D16_UNORM
;
2823 localParameters
.Flags
= 0;
2824 localParameters
.FullScreen_RefreshRateInHz
= WINED3DPRESENT_RATE_DEFAULT
;
2825 localParameters
.PresentationInterval
= WINED3DPRESENT_INTERVAL_DEFAULT
;
2827 /* Set this NOW, otherwise creating the depth stencil surface will cause a
2828 * recursive loop until ram or emulated video memory is full. */
2829 ddraw
->d3d_initialized
= TRUE
;
2830 hr
= IWineD3DDevice_Init3D(ddraw
->wineD3DDevice
, &localParameters
);
2833 ddraw
->d3d_target
= NULL
;
2834 ddraw
->d3d_initialized
= FALSE
;
2838 ddraw
->declArraySize
= 2;
2839 ddraw
->decls
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(*ddraw
->decls
) * ddraw
->declArraySize
);
2842 ERR("Error allocating an array for the converted vertex decls.\n");
2843 ddraw
->declArraySize
= 0;
2844 hr
= IWineD3DDevice_Uninit3D(ddraw
->wineD3DDevice
, D3D7CB_DestroySwapChain
);
2845 return E_OUTOFMEMORY
;
2848 TRACE("Successfully initialized 3D.\n");
2853 static HRESULT
ddraw_create_gdi_swapchain(IDirectDrawImpl
*ddraw
, IDirectDrawSurfaceImpl
*primary
)
2855 WINED3DPRESENT_PARAMETERS presentation_parameters
;
2859 window
= ddraw
->dest_window
;
2861 memset(&presentation_parameters
, 0, sizeof(presentation_parameters
));
2863 /* Use the surface description for the device parameters, not the device
2864 * settings. The application might render to an offscreen surface. */
2865 presentation_parameters
.BackBufferWidth
= primary
->surface_desc
.dwWidth
;
2866 presentation_parameters
.BackBufferHeight
= primary
->surface_desc
.dwHeight
;
2867 presentation_parameters
.BackBufferFormat
= PixelFormat_DD2WineD3D(&primary
->surface_desc
.u4
.ddpfPixelFormat
);
2868 presentation_parameters
.BackBufferCount
= (primary
->surface_desc
.dwFlags
& DDSD_BACKBUFFERCOUNT
)
2869 ? primary
->surface_desc
.dwBackBufferCount
: 0;
2870 presentation_parameters
.MultiSampleType
= WINED3DMULTISAMPLE_NONE
;
2871 presentation_parameters
.MultiSampleQuality
= 0;
2872 presentation_parameters
.SwapEffect
= WINED3DSWAPEFFECT_FLIP
;
2873 presentation_parameters
.hDeviceWindow
= window
;
2874 presentation_parameters
.Windowed
= !(ddraw
->cooperative_level
& DDSCL_FULLSCREEN
);
2875 presentation_parameters
.EnableAutoDepthStencil
= FALSE
; /* Not on GDI swapchains */
2876 presentation_parameters
.AutoDepthStencilFormat
= 0;
2877 presentation_parameters
.Flags
= 0;
2878 presentation_parameters
.FullScreen_RefreshRateInHz
= WINED3DPRESENT_RATE_DEFAULT
;
2879 presentation_parameters
.PresentationInterval
= WINED3DPRESENT_INTERVAL_DEFAULT
;
2881 ddraw
->d3d_target
= primary
;
2882 hr
= IWineD3DDevice_InitGDI(ddraw
->wineD3DDevice
, &presentation_parameters
);
2883 ddraw
->d3d_target
= NULL
;
2886 WARN("Failed to initialize GDI ddraw implementation, hr %#x.\n", hr
);
2887 primary
->wineD3DSwapChain
= NULL
;
2893 /*****************************************************************************
2894 * IDirectDraw7::CreateSurface
2896 * Creates a new IDirectDrawSurface object and returns its interface.
2898 * The surface connections with wined3d are a bit tricky. Basically it works
2901 * |------------------------| |-----------------|
2902 * | DDraw surface | | WineD3DSurface |
2904 * | WineD3DSurface |-------------->| |
2905 * | Child |<------------->| Parent |
2906 * |------------------------| |-----------------|
2908 * The DDraw surface is the parent of the wined3d surface, and it releases
2909 * the WineD3DSurface when the ddraw surface is destroyed.
2911 * However, for all surfaces which can be in a container in WineD3D,
2912 * we have to do this. These surfaces are usually complex surfaces,
2913 * so this concerns primary surfaces with a front and a back buffer,
2916 * |------------------------| |-----------------|
2917 * | DDraw surface | | Container |
2919 * | Child |<------------->| Parent |
2920 * | Texture |<------------->| |
2921 * | WineD3DSurface |<----| | Levels |<--|
2922 * | Complex connection | | | | |
2923 * |------------------------| | |-----------------| |
2927 * | |------------------| | |-----------------| |
2928 * | | IParent | |-------->| WineD3DSurface | |
2930 * | | Child |<------------->| Parent | |
2931 * | | | | Container |<--|
2932 * | |------------------| |-----------------| |
2934 * | |----------------------| |
2935 * | | DDraw surface 2 | |
2937 * |<->| Complex root Child | |
2939 * | | WineD3DSurface |<----| |
2940 * | |----------------------| | |
2942 * | |---------------------| | |-----------------| |
2943 * | | IParent | |----->| WineD3DSurface | |
2945 * | | Child |<---------->| Parent | |
2946 * | |---------------------| | Container |<--|
2947 * | |-----------------| |
2949 * | ---More surfaces can follow--- |
2951 * The reason is that the IWineD3DSwapchain(render target container)
2952 * and the IWineD3DTexure(Texture container) release the parents
2953 * of their surface's children, but by releasing the complex root
2954 * the surfaces which are complexly attached to it are destroyed
2955 * too. See IDirectDrawSurface::Release for a more detailed
2959 * DDSD: Description of the surface to create
2960 * Surf: Address to store the interface pointer at
2961 * UnkOuter: Basically for aggregation support, but ddraw doesn't support
2962 * aggregation, so it has to be NULL
2966 * CLASS_E_NOAGGREGATION if UnkOuter != NULL
2967 * DDERR_* if an error occurs
2969 *****************************************************************************/
2970 static HRESULT WINAPI
ddraw7_CreateSurface(IDirectDraw7
*iface
,
2971 DDSURFACEDESC2
*DDSD
, IDirectDrawSurface7
**Surf
, IUnknown
*UnkOuter
)
2973 IDirectDrawImpl
*This
= (IDirectDrawImpl
*)iface
;
2974 IDirectDrawSurfaceImpl
*object
= NULL
;
2976 LONG extra_surfaces
= 0;
2977 DDSURFACEDESC2 desc2
;
2978 WINED3DDISPLAYMODE Mode
;
2979 const DWORD sysvidmem
= DDSCAPS_VIDEOMEMORY
| DDSCAPS_SYSTEMMEMORY
;
2981 TRACE("(%p)->(%p,%p,%p)\n", This
, DDSD
, Surf
, UnkOuter
);
2983 /* Some checks before we start */
2984 if (TRACE_ON(ddraw
))
2986 TRACE(" (%p) Requesting surface desc :\n", This
);
2987 DDRAW_dump_surface_desc(DDSD
);
2989 EnterCriticalSection(&ddraw_cs
);
2991 if (UnkOuter
!= NULL
)
2993 FIXME("(%p) : outer != NULL?\n", This
);
2994 LeaveCriticalSection(&ddraw_cs
);
2995 return CLASS_E_NOAGGREGATION
; /* unchecked */
3000 FIXME("(%p) You want to get back a surface? Don't give NULL ptrs!\n", This
);
3001 LeaveCriticalSection(&ddraw_cs
);
3002 return E_POINTER
; /* unchecked */
3005 if (!(DDSD
->dwFlags
& DDSD_CAPS
))
3007 /* DVIDEO.DLL does forget the DDSD_CAPS flag ... *sigh* */
3008 DDSD
->dwFlags
|= DDSD_CAPS
;
3011 if (DDSD
->ddsCaps
.dwCaps
& DDSCAPS_ALLOCONLOAD
)
3013 /* If the surface is of the 'alloconload' type, ignore the LPSURFACE field */
3014 DDSD
->dwFlags
&= ~DDSD_LPSURFACE
;
3017 if ((DDSD
->dwFlags
& DDSD_LPSURFACE
) && (DDSD
->lpSurface
== NULL
))
3019 /* Frank Herbert's Dune specifies a null pointer for the surface, ignore the LPSURFACE field */
3020 WARN("(%p) Null surface pointer specified, ignore it!\n", This
);
3021 DDSD
->dwFlags
&= ~DDSD_LPSURFACE
;
3024 if((DDSD
->ddsCaps
.dwCaps
& (DDSCAPS_FLIP
| DDSCAPS_PRIMARYSURFACE
)) == (DDSCAPS_FLIP
| DDSCAPS_PRIMARYSURFACE
) &&
3025 !(This
->cooperative_level
& DDSCL_EXCLUSIVE
))
3027 TRACE("(%p): Attempt to create a flipable primary surface without DDSCL_EXCLUSIVE set\n", This
);
3029 LeaveCriticalSection(&ddraw_cs
);
3030 return DDERR_NOEXCLUSIVEMODE
;
3033 if(DDSD
->ddsCaps
.dwCaps
& (DDSCAPS_FRONTBUFFER
| DDSCAPS_BACKBUFFER
)) {
3034 WARN("Application tried to create an explicit front or back buffer\n");
3035 LeaveCriticalSection(&ddraw_cs
);
3036 return DDERR_INVALIDCAPS
;
3039 if((DDSD
->ddsCaps
.dwCaps
& sysvidmem
) == sysvidmem
)
3041 /* This is a special switch in ddrawex.dll, but not allowed in ddraw.dll */
3042 WARN("Application tries to put the surface in both system and video memory\n");
3043 LeaveCriticalSection(&ddraw_cs
);
3045 return DDERR_INVALIDCAPS
;
3048 /* Check cube maps but only if the size includes them */
3049 if (DDSD
->dwSize
>= sizeof(DDSURFACEDESC2
))
3051 if(DDSD
->ddsCaps
.dwCaps2
& DDSCAPS2_CUBEMAP_ALLFACES
&&
3052 !(DDSD
->ddsCaps
.dwCaps2
& DDSCAPS2_CUBEMAP
))
3054 WARN("Cube map faces requested without cube map flag\n");
3055 LeaveCriticalSection(&ddraw_cs
);
3056 return DDERR_INVALIDCAPS
;
3058 if(DDSD
->ddsCaps
.dwCaps2
& DDSCAPS2_CUBEMAP
&&
3059 (DDSD
->ddsCaps
.dwCaps2
& DDSCAPS2_CUBEMAP_ALLFACES
) == 0)
3061 WARN("Cube map without faces requested\n");
3062 LeaveCriticalSection(&ddraw_cs
);
3063 return DDERR_INVALIDPARAMS
;
3066 /* Quick tests confirm those can be created, but we don't do that yet */
3067 if(DDSD
->ddsCaps
.dwCaps2
& DDSCAPS2_CUBEMAP
&&
3068 (DDSD
->ddsCaps
.dwCaps2
& DDSCAPS2_CUBEMAP_ALLFACES
) != DDSCAPS2_CUBEMAP_ALLFACES
)
3070 FIXME("Partial cube maps not supported yet\n");
3074 /* According to the msdn this flag is ignored by CreateSurface */
3075 if (DDSD
->dwSize
>= sizeof(DDSURFACEDESC2
))
3076 DDSD
->ddsCaps
.dwCaps2
&= ~DDSCAPS2_MIPMAPSUBLEVEL
;
3078 /* Modify some flags */
3079 memset(&desc2
, 0, sizeof(desc2
));
3080 desc2
.dwSize
= sizeof(desc2
); /* For the struct copy */
3081 DD_STRUCT_COPY_BYSIZE(&desc2
, DDSD
);
3082 desc2
.dwSize
= sizeof(desc2
); /* To override a possibly smaller size */
3083 desc2
.u4
.ddpfPixelFormat
.dwSize
=sizeof(DDPIXELFORMAT
); /* Just to be sure */
3085 /* Get the video mode from WineD3D - we will need it */
3086 hr
= IWineD3DDevice_GetDisplayMode(This
->wineD3DDevice
,
3087 0, /* Swapchain 0 */
3091 ERR("Failed to read display mode from wined3d\n");
3092 switch(This
->orig_bpp
)
3095 Mode
.Format
= WINED3DFMT_P8_UINT
;
3099 Mode
.Format
= WINED3DFMT_B5G5R5X1_UNORM
;
3103 Mode
.Format
= WINED3DFMT_B5G6R5_UNORM
;
3107 Mode
.Format
= WINED3DFMT_B8G8R8_UNORM
;
3111 Mode
.Format
= WINED3DFMT_B8G8R8X8_UNORM
;
3114 Mode
.Width
= This
->orig_width
;
3115 Mode
.Height
= This
->orig_height
;
3118 /* No pixelformat given? Use the current screen format */
3119 if(!(desc2
.dwFlags
& DDSD_PIXELFORMAT
))
3121 desc2
.dwFlags
|= DDSD_PIXELFORMAT
;
3122 desc2
.u4
.ddpfPixelFormat
.dwSize
=sizeof(DDPIXELFORMAT
);
3124 /* Wait: It could be a Z buffer */
3125 if(desc2
.ddsCaps
.dwCaps
& DDSCAPS_ZBUFFER
)
3127 switch(desc2
.u2
.dwMipMapCount
) /* Who had this glorious idea? */
3130 PixelFormat_WineD3DtoDD(&desc2
.u4
.ddpfPixelFormat
, WINED3DFMT_S1_UINT_D15_UNORM
);
3133 PixelFormat_WineD3DtoDD(&desc2
.u4
.ddpfPixelFormat
, WINED3DFMT_D16_UNORM
);
3136 PixelFormat_WineD3DtoDD(&desc2
.u4
.ddpfPixelFormat
, WINED3DFMT_X8D24_UNORM
);
3139 PixelFormat_WineD3DtoDD(&desc2
.u4
.ddpfPixelFormat
, WINED3DFMT_D32_UNORM
);
3142 ERR("Unknown Z buffer bit depth\n");
3147 PixelFormat_WineD3DtoDD(&desc2
.u4
.ddpfPixelFormat
, Mode
.Format
);
3151 /* No Width or no Height? Use the original screen size
3153 if(!(desc2
.dwFlags
& DDSD_WIDTH
) ||
3154 !(desc2
.dwFlags
& DDSD_HEIGHT
) )
3156 /* Invalid for non-render targets */
3157 if(!(desc2
.ddsCaps
.dwCaps
& DDSCAPS_PRIMARYSURFACE
))
3159 WARN("Creating a non-Primary surface without Width or Height info, returning DDERR_INVALIDPARAMS\n");
3161 LeaveCriticalSection(&ddraw_cs
);
3162 return DDERR_INVALIDPARAMS
;
3165 desc2
.dwFlags
|= DDSD_WIDTH
| DDSD_HEIGHT
;
3166 desc2
.dwWidth
= Mode
.Width
;
3167 desc2
.dwHeight
= Mode
.Height
;
3170 /* Mipmap count fixes */
3171 if(desc2
.ddsCaps
.dwCaps
& DDSCAPS_MIPMAP
)
3173 if(desc2
.ddsCaps
.dwCaps
& DDSCAPS_COMPLEX
)
3175 if(desc2
.dwFlags
& DDSD_MIPMAPCOUNT
)
3177 /* Mipmap count is given, should not be 0 */
3178 if( desc2
.u2
.dwMipMapCount
== 0 )
3180 LeaveCriticalSection(&ddraw_cs
);
3181 return DDERR_INVALIDPARAMS
;
3186 /* Undocumented feature: Create sublevels until
3187 * either the width or the height is 1
3189 DWORD min
= desc2
.dwWidth
< desc2
.dwHeight
?
3190 desc2
.dwWidth
: desc2
.dwHeight
;
3191 desc2
.u2
.dwMipMapCount
= 0;
3194 desc2
.u2
.dwMipMapCount
+= 1;
3201 /* Not-complex mipmap -> Mipmapcount = 1 */
3202 desc2
.u2
.dwMipMapCount
= 1;
3204 extra_surfaces
= desc2
.u2
.dwMipMapCount
- 1;
3206 /* There's a mipmap count in the created surface in any case */
3207 desc2
.dwFlags
|= DDSD_MIPMAPCOUNT
;
3209 /* If no mipmap is given, the texture has only one level */
3211 /* The first surface is a front buffer, the back buffer is created afterwards */
3212 if( (desc2
.dwFlags
& DDSD_CAPS
) && (desc2
.ddsCaps
.dwCaps
& DDSCAPS_PRIMARYSURFACE
) )
3214 desc2
.ddsCaps
.dwCaps
|= DDSCAPS_FRONTBUFFER
;
3217 /* The root surface in a cube map is positive x */
3218 if(desc2
.ddsCaps
.dwCaps2
& DDSCAPS2_CUBEMAP
)
3220 desc2
.ddsCaps
.dwCaps2
&= ~DDSCAPS2_CUBEMAP_ALLFACES
;
3221 desc2
.ddsCaps
.dwCaps2
|= DDSCAPS2_CUBEMAP_POSITIVEX
;
3224 /* Create the first surface */
3225 hr
= ddraw_create_surface(This
, &desc2
, &object
, 0);
3228 ERR("ddraw_create_surface failed, hr %#x.\n", hr
);
3229 LeaveCriticalSection(&ddraw_cs
);
3232 object
->is_complex_root
= TRUE
;
3234 *Surf
= (IDirectDrawSurface7
*)object
;
3236 /* Create Additional surfaces if necessary
3237 * This applies to Primary surfaces which have a back buffer count
3238 * set, but not to mipmap textures. In case of Mipmap textures,
3239 * wineD3D takes care of the creation of additional surfaces
3241 if(DDSD
->dwFlags
& DDSD_BACKBUFFERCOUNT
)
3243 extra_surfaces
= DDSD
->dwBackBufferCount
;
3244 desc2
.ddsCaps
.dwCaps
&= ~DDSCAPS_FRONTBUFFER
; /* It's not a front buffer */
3245 desc2
.ddsCaps
.dwCaps
|= DDSCAPS_BACKBUFFER
;
3246 desc2
.dwBackBufferCount
= 0;
3250 if(desc2
.ddsCaps
.dwCaps2
& DDSCAPS2_CUBEMAP
)
3252 desc2
.ddsCaps
.dwCaps2
&= ~DDSCAPS2_CUBEMAP_ALLFACES
;
3253 desc2
.ddsCaps
.dwCaps2
|= DDSCAPS2_CUBEMAP_NEGATIVEZ
;
3254 hr
|= CreateAdditionalSurfaces(This
, object
, extra_surfaces
+ 1, desc2
, TRUE
);
3255 desc2
.ddsCaps
.dwCaps2
&= ~DDSCAPS2_CUBEMAP_NEGATIVEZ
;
3256 desc2
.ddsCaps
.dwCaps2
|= DDSCAPS2_CUBEMAP_POSITIVEZ
;
3257 hr
|= CreateAdditionalSurfaces(This
, object
, extra_surfaces
+ 1, desc2
, TRUE
);
3258 desc2
.ddsCaps
.dwCaps2
&= ~DDSCAPS2_CUBEMAP_POSITIVEZ
;
3259 desc2
.ddsCaps
.dwCaps2
|= DDSCAPS2_CUBEMAP_NEGATIVEY
;
3260 hr
|= CreateAdditionalSurfaces(This
, object
, extra_surfaces
+ 1, desc2
, TRUE
);
3261 desc2
.ddsCaps
.dwCaps2
&= ~DDSCAPS2_CUBEMAP_NEGATIVEY
;
3262 desc2
.ddsCaps
.dwCaps2
|= DDSCAPS2_CUBEMAP_POSITIVEY
;
3263 hr
|= CreateAdditionalSurfaces(This
, object
, extra_surfaces
+ 1, desc2
, TRUE
);
3264 desc2
.ddsCaps
.dwCaps2
&= ~DDSCAPS2_CUBEMAP_POSITIVEY
;
3265 desc2
.ddsCaps
.dwCaps2
|= DDSCAPS2_CUBEMAP_NEGATIVEX
;
3266 hr
|= CreateAdditionalSurfaces(This
, object
, extra_surfaces
+ 1, desc2
, TRUE
);
3267 desc2
.ddsCaps
.dwCaps2
&= ~DDSCAPS2_CUBEMAP_NEGATIVEX
;
3268 desc2
.ddsCaps
.dwCaps2
|= DDSCAPS2_CUBEMAP_POSITIVEX
;
3271 hr
|= CreateAdditionalSurfaces(This
, object
, extra_surfaces
, desc2
, FALSE
);
3274 /* This destroys and possibly created surfaces too */
3275 IDirectDrawSurface_Release((IDirectDrawSurface7
*)object
);
3276 LeaveCriticalSection(&ddraw_cs
);
3280 /* If the implementation is OpenGL and there's no d3ddevice, attach a d3ddevice
3281 * But attach the d3ddevice only if the currently created surface was
3282 * a primary surface (2D app in 3D mode) or a 3DDEVICE surface (3D app)
3283 * The only case I can think of where this doesn't apply is when a
3284 * 2D app was configured by the user to run with OpenGL and it didn't create
3285 * the render target as first surface. In this case the render target creation
3286 * will cause the 3D init.
3288 if( (This
->ImplType
== SURFACE_OPENGL
) && !(This
->d3d_initialized
) &&
3289 desc2
.ddsCaps
.dwCaps
& (DDSCAPS_PRIMARYSURFACE
| DDSCAPS_3DDEVICE
) )
3291 IDirectDrawSurfaceImpl
*target
= object
, *surface
;
3294 /* Search for the primary to use as render target */
3295 LIST_FOR_EACH(entry
, &This
->surface_list
)
3297 surface
= LIST_ENTRY(entry
, IDirectDrawSurfaceImpl
, surface_list_entry
);
3298 if((surface
->surface_desc
.ddsCaps
.dwCaps
& (DDSCAPS_PRIMARYSURFACE
| DDSCAPS_FRONTBUFFER
)) ==
3299 (DDSCAPS_PRIMARYSURFACE
| DDSCAPS_FRONTBUFFER
))
3303 TRACE("Using primary %p as render target\n", target
);
3308 TRACE("(%p) Attaching a D3DDevice, rendertarget = %p\n", This
, target
);
3309 hr
= ddraw_attach_d3d_device(This
, target
);
3312 IDirectDrawSurfaceImpl
*release_surf
;
3313 ERR("ddraw_attach_d3d_device failed, hr %#x\n", hr
);
3316 /* The before created surface structures are in an incomplete state here.
3317 * WineD3D holds the reference on the IParents, and it released them on the failure
3318 * already. So the regular release method implementation would fail on the attempt
3319 * to destroy either the IParents or the swapchain. So free the surface here.
3320 * The surface structure here is a list, not a tree, because onscreen targets
3321 * cannot be cube textures
3325 release_surf
= object
;
3326 object
= object
->complex_array
[0];
3327 ddraw_surface_destroy(release_surf
);
3329 LeaveCriticalSection(&ddraw_cs
);
3333 else if(!(This
->d3d_initialized
) && desc2
.ddsCaps
.dwCaps
& DDSCAPS_PRIMARYSURFACE
)
3335 ddraw_create_gdi_swapchain(This
, object
);
3338 /* Addref the ddraw interface to keep an reference for each surface */
3339 IDirectDraw7_AddRef(iface
);
3340 object
->ifaceToRelease
= (IUnknown
*) iface
;
3342 /* Create a WineD3DTexture if a texture was requested */
3343 if(desc2
.ddsCaps
.dwCaps
& DDSCAPS_TEXTURE
)
3346 WINED3DFORMAT Format
;
3347 WINED3DPOOL Pool
= WINED3DPOOL_DEFAULT
;
3349 This
->tex_root
= object
;
3351 if(desc2
.ddsCaps
.dwCaps
& DDSCAPS_MIPMAP
)
3353 /* a mipmap is created, create enough levels */
3354 levels
= desc2
.u2
.dwMipMapCount
;
3358 /* No mipmap is created, create one level */
3362 /* DDSCAPS_SYSTEMMEMORY textures are in WINED3DPOOL_SYSTEMMEM */
3363 if(DDSD
->ddsCaps
.dwCaps
& DDSCAPS_SYSTEMMEMORY
)
3365 Pool
= WINED3DPOOL_SYSTEMMEM
;
3367 /* Should I forward the MANAGED cap to the managed pool ? */
3369 /* Get the format. It's set already by CreateNewSurface */
3370 Format
= PixelFormat_DD2WineD3D(&object
->surface_desc
.u4
.ddpfPixelFormat
);
3372 /* The surfaces are already created, the callback only
3373 * passes the IWineD3DSurface to WineD3D
3375 if(desc2
.ddsCaps
.dwCaps2
& DDSCAPS2_CUBEMAP
)
3377 hr
= IWineD3DDevice_CreateCubeTexture(This
->wineD3DDevice
, DDSD
->dwWidth
/* Edgelength */,
3378 levels
, 0 /* usage */, Format
, Pool
, (IWineD3DCubeTexture
**)&object
->wineD3DTexture
,
3379 (IUnknown
*)object
, &ddraw_null_wined3d_parent_ops
);
3383 hr
= IWineD3DDevice_CreateTexture(This
->wineD3DDevice
, DDSD
->dwWidth
, DDSD
->dwHeight
, levels
,
3384 0 /* usage */, Format
, Pool
, (IWineD3DTexture
**)&object
->wineD3DTexture
,
3385 (IUnknown
*)object
, &ddraw_null_wined3d_parent_ops
);
3387 This
->tex_root
= NULL
;
3390 LeaveCriticalSection(&ddraw_cs
);
3394 static HRESULT WINAPI
ddraw4_CreateSurface(IDirectDraw4
*iface
,
3395 DDSURFACEDESC2
*surface_desc
, IDirectDrawSurface4
**surface
, IUnknown
*outer_unknown
)
3397 IDirectDrawImpl
*ddraw
= ddraw_from_ddraw4(iface
);
3398 IDirectDrawSurfaceImpl
*impl
;
3401 TRACE("iface %p, surface_desc %p, surface %p, outer_unknown %p.\n",
3402 iface
, surface_desc
, surface
, outer_unknown
);
3404 hr
= ddraw7_CreateSurface((IDirectDraw7
*)ddraw
, surface_desc
, (IDirectDrawSurface7
**)surface
, outer_unknown
);
3405 impl
= (IDirectDrawSurfaceImpl
*)*surface
;
3406 if (SUCCEEDED(hr
) && impl
)
3408 ddraw_set_surface_version(impl
, 4);
3409 IDirectDraw7_Release((IDirectDraw7
*)ddraw
);
3410 IDirectDraw4_AddRef(iface
);
3411 impl
->ifaceToRelease
= (IUnknown
*)iface
;
3417 static HRESULT WINAPI
ddraw3_CreateSurface(IDirectDraw3
*iface
,
3418 DDSURFACEDESC
*surface_desc
, IDirectDrawSurface
**surface
, IUnknown
*outer_unknown
)
3420 IDirectDrawImpl
*ddraw
= ddraw_from_ddraw3(iface
);
3421 IDirectDrawSurface7
*surface7
;
3422 IDirectDrawSurfaceImpl
*impl
;
3425 TRACE("iface %p, surface_desc %p, surface %p, outer_unknown %p.\n",
3426 iface
, surface_desc
, surface
, outer_unknown
);
3428 hr
= ddraw7_CreateSurface((IDirectDraw7
*)ddraw
, (DDSURFACEDESC2
*)surface_desc
, &surface7
, outer_unknown
);
3435 impl
= (IDirectDrawSurfaceImpl
*)surface7
;
3436 *surface
= (IDirectDrawSurface
*)&impl
->IDirectDrawSurface3_vtbl
;
3437 ddraw_set_surface_version(impl
, 3);
3438 IDirectDraw7_Release((IDirectDraw7
*)ddraw
);
3439 IDirectDraw3_AddRef(iface
);
3440 impl
->ifaceToRelease
= (IUnknown
*)iface
;
3445 static HRESULT WINAPI
ddraw2_CreateSurface(IDirectDraw2
*iface
,
3446 DDSURFACEDESC
*surface_desc
, IDirectDrawSurface
**surface
, IUnknown
*outer_unknown
)
3448 IDirectDrawImpl
*ddraw
= ddraw_from_ddraw2(iface
);
3449 IDirectDrawSurface7
*surface7
;
3450 IDirectDrawSurfaceImpl
*impl
;
3453 TRACE("iface %p, surface_desc %p, surface %p, outer_unknown %p.\n",
3454 iface
, surface_desc
, surface
, outer_unknown
);
3456 hr
= ddraw7_CreateSurface((IDirectDraw7
*)ddraw
, (DDSURFACEDESC2
*)surface_desc
, &surface7
, outer_unknown
);
3463 impl
= (IDirectDrawSurfaceImpl
*)surface7
;
3464 *surface
= (IDirectDrawSurface
*)&impl
->IDirectDrawSurface3_vtbl
;
3465 ddraw_set_surface_version(impl
, 2);
3466 IDirectDraw7_Release((IDirectDraw7
*)ddraw
);
3467 impl
->ifaceToRelease
= NULL
;
3472 static HRESULT WINAPI
ddraw1_CreateSurface(IDirectDraw
*iface
,
3473 DDSURFACEDESC
*surface_desc
, IDirectDrawSurface
**surface
, IUnknown
*outer_unknown
)
3475 IDirectDrawImpl
*ddraw
= ddraw_from_ddraw1(iface
);
3476 IDirectDrawSurface7
*surface7
;
3477 IDirectDrawSurfaceImpl
*impl
;
3480 TRACE("iface %p, surface_desc %p, surface %p, outer_unknown %p.\n",
3481 iface
, surface_desc
, surface
, outer_unknown
);
3483 /* Remove front buffer flag, this causes failure in v7, and its added to normal
3484 * primaries anyway. */
3485 surface_desc
->ddsCaps
.dwCaps
&= ~DDSCAPS_FRONTBUFFER
;
3486 hr
= ddraw7_CreateSurface((IDirectDraw7
*)ddraw
, (DDSURFACEDESC2
*)surface_desc
, &surface7
, outer_unknown
);
3493 impl
= (IDirectDrawSurfaceImpl
*)surface7
;
3494 *surface
= (IDirectDrawSurface
*)&impl
->IDirectDrawSurface3_vtbl
;
3495 ddraw_set_surface_version(impl
, 1);
3496 IDirectDraw7_Release((IDirectDraw7
*)ddraw
);
3497 impl
->ifaceToRelease
= NULL
;
3502 #define DDENUMSURFACES_SEARCHTYPE (DDENUMSURFACES_CANBECREATED|DDENUMSURFACES_DOESEXIST)
3503 #define DDENUMSURFACES_MATCHTYPE (DDENUMSURFACES_ALL|DDENUMSURFACES_MATCH|DDENUMSURFACES_NOMATCH)
3506 Main_DirectDraw_DDPIXELFORMAT_Match(const DDPIXELFORMAT
*requested
,
3507 const DDPIXELFORMAT
*provided
)
3509 /* Some flags must be present in both or neither for a match. */
3510 static const DWORD must_match
= DDPF_PALETTEINDEXED1
| DDPF_PALETTEINDEXED2
3511 | DDPF_PALETTEINDEXED4
| DDPF_PALETTEINDEXED8
| DDPF_FOURCC
3512 | DDPF_ZBUFFER
| DDPF_STENCILBUFFER
;
3514 if ((requested
->dwFlags
& provided
->dwFlags
) != requested
->dwFlags
)
3517 if ((requested
->dwFlags
& must_match
) != (provided
->dwFlags
& must_match
))
3520 if (requested
->dwFlags
& DDPF_FOURCC
)
3521 if (requested
->dwFourCC
!= provided
->dwFourCC
)
3524 if (requested
->dwFlags
& (DDPF_RGB
|DDPF_YUV
|DDPF_ZBUFFER
|DDPF_ALPHA
3525 |DDPF_LUMINANCE
|DDPF_BUMPDUDV
))
3526 if (requested
->u1
.dwRGBBitCount
!= provided
->u1
.dwRGBBitCount
)
3529 if (requested
->dwFlags
& (DDPF_RGB
|DDPF_YUV
|DDPF_STENCILBUFFER
3530 |DDPF_LUMINANCE
|DDPF_BUMPDUDV
))
3531 if (requested
->u2
.dwRBitMask
!= provided
->u2
.dwRBitMask
)
3534 if (requested
->dwFlags
& (DDPF_RGB
|DDPF_YUV
|DDPF_ZBUFFER
|DDPF_BUMPDUDV
))
3535 if (requested
->u3
.dwGBitMask
!= provided
->u3
.dwGBitMask
)
3538 /* I could be wrong about the bumpmapping. MSDN docs are vague. */
3539 if (requested
->dwFlags
& (DDPF_RGB
|DDPF_YUV
|DDPF_STENCILBUFFER
3541 if (requested
->u4
.dwBBitMask
!= provided
->u4
.dwBBitMask
)
3544 if (requested
->dwFlags
& (DDPF_ALPHAPIXELS
|DDPF_ZPIXELS
))
3545 if (requested
->u5
.dwRGBAlphaBitMask
!= provided
->u5
.dwRGBAlphaBitMask
)
3551 static BOOL
ddraw_match_surface_desc(const DDSURFACEDESC2
*requested
, const DDSURFACEDESC2
*provided
)
3560 #define CMP(FLAG, FIELD) \
3561 { DDSD_##FLAG, offsetof(DDSURFACEDESC2, FIELD), \
3562 sizeof(((DDSURFACEDESC2 *)(NULL))->FIELD) }
3564 static const struct compare_info compare
[] =
3566 CMP(ALPHABITDEPTH
, dwAlphaBitDepth
),
3567 CMP(BACKBUFFERCOUNT
, dwBackBufferCount
),
3569 CMP(CKDESTBLT
, ddckCKDestBlt
),
3570 CMP(CKDESTOVERLAY
, u3
/* ddckCKDestOverlay */),
3571 CMP(CKSRCBLT
, ddckCKSrcBlt
),
3572 CMP(CKSRCOVERLAY
, ddckCKSrcOverlay
),
3573 CMP(HEIGHT
, dwHeight
),
3574 CMP(LINEARSIZE
, u1
/* dwLinearSize */),
3575 CMP(LPSURFACE
, lpSurface
),
3576 CMP(MIPMAPCOUNT
, u2
/* dwMipMapCount */),
3577 CMP(PITCH
, u1
/* lPitch */),
3578 /* PIXELFORMAT: manual */
3579 CMP(REFRESHRATE
, u2
/* dwRefreshRate */),
3580 CMP(TEXTURESTAGE
, dwTextureStage
),
3581 CMP(WIDTH
, dwWidth
),
3582 /* ZBUFFERBITDEPTH: "obsolete" */
3589 if ((requested
->dwFlags
& provided
->dwFlags
) != requested
->dwFlags
)
3592 for (i
=0; i
< sizeof(compare
)/sizeof(compare
[0]); i
++)
3594 if (requested
->dwFlags
& compare
[i
].flag
3595 && memcmp((const char *)provided
+ compare
[i
].offset
,
3596 (const char *)requested
+ compare
[i
].offset
,
3597 compare
[i
].size
) != 0)
3601 if (requested
->dwFlags
& DDSD_PIXELFORMAT
)
3603 if (!Main_DirectDraw_DDPIXELFORMAT_Match(&requested
->u4
.ddpfPixelFormat
,
3604 &provided
->u4
.ddpfPixelFormat
))
3611 #undef DDENUMSURFACES_SEARCHTYPE
3612 #undef DDENUMSURFACES_MATCHTYPE
3614 struct surfacescallback_context
3616 LPDDENUMSURFACESCALLBACK func
;
3620 static HRESULT CALLBACK
EnumSurfacesCallbackThunk(IDirectDrawSurface7
*surface
,
3621 DDSURFACEDESC2
*surface_desc
, void *context
)
3623 struct surfacescallback_context
*cbcontext
= context
;
3625 return cbcontext
->func((IDirectDrawSurface
*)&((IDirectDrawSurfaceImpl
*)surface
)->IDirectDrawSurface3_vtbl
,
3626 (DDSURFACEDESC
*)surface_desc
, cbcontext
->context
);
3629 /*****************************************************************************
3630 * IDirectDraw7::EnumSurfaces
3632 * Loops through all surfaces attached to this device and calls the
3633 * application callback. This can't be relayed to WineD3DDevice,
3634 * because some WineD3DSurfaces' parents are IParent objects
3637 * Flags: Some filtering flags. See IDirectDrawImpl_EnumSurfacesCallback
3638 * DDSD: Description to filter for
3639 * Context: Application-provided pointer, it's passed unmodified to the
3641 * Callback: Address to call for each surface
3644 * DDERR_INVALIDPARAMS if the callback is NULL
3647 *****************************************************************************/
3648 static HRESULT WINAPI
ddraw7_EnumSurfaces(IDirectDraw7
*iface
, DWORD Flags
,
3649 DDSURFACEDESC2
*DDSD
, void *Context
, LPDDENUMSURFACESCALLBACK7 Callback
)
3651 /* The surface enumeration is handled by WineDDraw,
3652 * because it keeps track of all surfaces attached to
3653 * it. The filtering is done by our callback function,
3654 * because WineDDraw doesn't handle ddraw-like surface
3657 IDirectDrawImpl
*This
= (IDirectDrawImpl
*)iface
;
3658 IDirectDrawSurfaceImpl
*surf
;
3660 DDSURFACEDESC2 desc
;
3661 struct list
*entry
, *entry2
;
3663 all
= Flags
& DDENUMSURFACES_ALL
;
3664 nomatch
= Flags
& DDENUMSURFACES_NOMATCH
;
3666 TRACE("(%p)->(%x,%p,%p,%p)\n", This
, Flags
, DDSD
, Context
, Callback
);
3667 EnterCriticalSection(&ddraw_cs
);
3671 LeaveCriticalSection(&ddraw_cs
);
3672 return DDERR_INVALIDPARAMS
;
3675 /* Use the _SAFE enumeration, the app may destroy enumerated surfaces */
3676 LIST_FOR_EACH_SAFE(entry
, entry2
, &This
->surface_list
)
3678 surf
= LIST_ENTRY(entry
, IDirectDrawSurfaceImpl
, surface_list_entry
);
3679 if (all
|| (nomatch
!= ddraw_match_surface_desc(DDSD
, &surf
->surface_desc
)))
3681 desc
= surf
->surface_desc
;
3682 IDirectDrawSurface7_AddRef((IDirectDrawSurface7
*)surf
);
3683 if (Callback((IDirectDrawSurface7
*)surf
, &desc
, Context
) != DDENUMRET_OK
)
3685 LeaveCriticalSection(&ddraw_cs
);
3690 LeaveCriticalSection(&ddraw_cs
);
3694 static HRESULT WINAPI
ddraw4_EnumSurfaces(IDirectDraw4
*iface
, DWORD flags
,
3695 DDSURFACEDESC2
*surface_desc
, void *context
, LPDDENUMSURFACESCALLBACK2 callback
)
3697 TRACE("iface %p, flags %#x, surface_desc %p, context %p, callback %p.\n",
3698 iface
, flags
, surface_desc
, context
, callback
);
3700 return ddraw7_EnumSurfaces((IDirectDraw7
*)ddraw_from_ddraw4(iface
),
3701 flags
, surface_desc
, context
, (LPDDENUMSURFACESCALLBACK7
)callback
);
3704 static HRESULT WINAPI
ddraw3_EnumSurfaces(IDirectDraw3
*iface
, DWORD flags
,
3705 DDSURFACEDESC
*surface_desc
, void *context
, LPDDENUMSURFACESCALLBACK callback
)
3707 struct surfacescallback_context cbcontext
;
3709 TRACE("iface %p, flags %#x, surface_desc %p, context %p, callback %p.\n",
3710 iface
, flags
, surface_desc
, context
, callback
);
3712 cbcontext
.func
= callback
;
3713 cbcontext
.context
= context
;
3715 return ddraw7_EnumSurfaces((IDirectDraw7
*)ddraw_from_ddraw3(iface
), flags
,
3716 (DDSURFACEDESC2
*)surface_desc
, &cbcontext
, EnumSurfacesCallbackThunk
);
3719 static HRESULT WINAPI
ddraw2_EnumSurfaces(IDirectDraw2
*iface
, DWORD flags
,
3720 DDSURFACEDESC
*surface_desc
, void *context
, LPDDENUMSURFACESCALLBACK callback
)
3722 struct surfacescallback_context cbcontext
;
3724 TRACE("iface %p, flags %#x, surface_desc %p, context %p, callback %p.\n",
3725 iface
, flags
, surface_desc
, context
, callback
);
3727 cbcontext
.func
= callback
;
3728 cbcontext
.context
= context
;
3730 return ddraw7_EnumSurfaces((IDirectDraw7
*)ddraw_from_ddraw2(iface
), flags
,
3731 (DDSURFACEDESC2
*)surface_desc
, &cbcontext
, EnumSurfacesCallbackThunk
);
3734 static HRESULT WINAPI
ddraw1_EnumSurfaces(IDirectDraw
*iface
, DWORD flags
,
3735 DDSURFACEDESC
*surface_desc
, void *context
, LPDDENUMSURFACESCALLBACK callback
)
3737 struct surfacescallback_context cbcontext
;
3739 TRACE("iface %p, flags %#x, surface_desc %p, context %p, callback %p.\n",
3740 iface
, flags
, surface_desc
, context
, callback
);
3742 cbcontext
.func
= callback
;
3743 cbcontext
.context
= context
;
3745 return ddraw7_EnumSurfaces((IDirectDraw7
*)ddraw_from_ddraw1(iface
), flags
,
3746 (DDSURFACEDESC2
*)surface_desc
, &cbcontext
, EnumSurfacesCallbackThunk
);
3749 /*****************************************************************************
3750 * DirectDrawCreateClipper (DDRAW.@)
3752 * Creates a new IDirectDrawClipper object.
3755 * Clipper: Address to write the interface pointer to
3756 * UnkOuter: For aggregation support, which ddraw doesn't have. Has to be
3760 * CLASS_E_NOAGGREGATION if UnkOuter != NULL
3761 * E_OUTOFMEMORY if allocating the object failed
3763 *****************************************************************************/
3765 DirectDrawCreateClipper(DWORD Flags
,
3766 LPDIRECTDRAWCLIPPER
*Clipper
,
3769 IDirectDrawClipperImpl
* object
;
3770 TRACE("(%08x,%p,%p)\n", Flags
, Clipper
, UnkOuter
);
3772 EnterCriticalSection(&ddraw_cs
);
3773 if (UnkOuter
!= NULL
)
3775 LeaveCriticalSection(&ddraw_cs
);
3776 return CLASS_E_NOAGGREGATION
;
3781 LeaveCriticalSection(&ddraw_cs
);
3782 return DDERR_NODIRECTDRAWSUPPORT
;
3785 object
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,
3786 sizeof(IDirectDrawClipperImpl
));
3789 LeaveCriticalSection(&ddraw_cs
);
3790 return E_OUTOFMEMORY
;
3793 object
->lpVtbl
= &IDirectDrawClipper_Vtbl
;
3795 object
->wineD3DClipper
= pWineDirect3DCreateClipper((IUnknown
*) object
);
3796 if(!object
->wineD3DClipper
)
3798 HeapFree(GetProcessHeap(), 0, object
);
3799 LeaveCriticalSection(&ddraw_cs
);
3800 return E_OUTOFMEMORY
;
3803 *Clipper
= (IDirectDrawClipper
*) object
;
3804 LeaveCriticalSection(&ddraw_cs
);
3808 /*****************************************************************************
3809 * IDirectDraw7::CreateClipper
3811 * Creates a DDraw clipper. See DirectDrawCreateClipper for details
3813 *****************************************************************************/
3814 static HRESULT WINAPI
ddraw7_CreateClipper(IDirectDraw7
*iface
, DWORD Flags
,
3815 IDirectDrawClipper
**Clipper
, IUnknown
*UnkOuter
)
3817 IDirectDrawImpl
*This
= (IDirectDrawImpl
*)iface
;
3818 TRACE("(%p)->(%x,%p,%p)\n", This
, Flags
, Clipper
, UnkOuter
);
3819 return DirectDrawCreateClipper(Flags
, Clipper
, UnkOuter
);
3822 static HRESULT WINAPI
ddraw4_CreateClipper(IDirectDraw4
*iface
,
3823 DWORD flags
, IDirectDrawClipper
**clipper
, IUnknown
*outer_unknown
)
3825 TRACE("iface %p, flags %#x, clipper %p, outer_unknown %p.\n",
3826 iface
, flags
, clipper
, outer_unknown
);
3828 return ddraw7_CreateClipper((IDirectDraw7
*)ddraw_from_ddraw4(iface
), flags
, clipper
, outer_unknown
);
3831 static HRESULT WINAPI
ddraw3_CreateClipper(IDirectDraw3
*iface
,
3832 DWORD flags
, IDirectDrawClipper
**clipper
, IUnknown
*outer_unknown
)
3834 TRACE("iface %p, flags %#x, clipper %p, outer_unknown %p.\n",
3835 iface
, flags
, clipper
, outer_unknown
);
3837 return ddraw7_CreateClipper((IDirectDraw7
*)ddraw_from_ddraw3(iface
), flags
, clipper
, outer_unknown
);
3840 static HRESULT WINAPI
ddraw2_CreateClipper(IDirectDraw2
*iface
,
3841 DWORD flags
, IDirectDrawClipper
**clipper
, IUnknown
*outer_unknown
)
3843 TRACE("iface %p, flags %#x, clipper %p, outer_unknown %p.\n",
3844 iface
, flags
, clipper
, outer_unknown
);
3846 return ddraw7_CreateClipper((IDirectDraw7
*)ddraw_from_ddraw2(iface
), flags
, clipper
, outer_unknown
);
3849 static HRESULT WINAPI
ddraw1_CreateClipper(IDirectDraw
*iface
,
3850 DWORD flags
, IDirectDrawClipper
**clipper
, IUnknown
*outer_unknown
)
3852 TRACE("iface %p, flags %#x, clipper %p, outer_unknown %p.\n",
3853 iface
, flags
, clipper
, outer_unknown
);
3855 return ddraw7_CreateClipper((IDirectDraw7
*)ddraw_from_ddraw1(iface
), flags
, clipper
, outer_unknown
);
3858 /*****************************************************************************
3859 * IDirectDraw7::CreatePalette
3861 * Creates a new IDirectDrawPalette object
3864 * Flags: The flags for the new clipper
3865 * ColorTable: Color table to assign to the new clipper
3866 * Palette: Address to write the interface pointer to
3867 * UnkOuter: For aggregation support, which ddraw doesn't have. Has to be
3871 * CLASS_E_NOAGGREGATION if UnkOuter != NULL
3872 * E_OUTOFMEMORY if allocating the object failed
3874 *****************************************************************************/
3875 static HRESULT WINAPI
ddraw7_CreatePalette(IDirectDraw7
*iface
, DWORD Flags
,
3876 PALETTEENTRY
*ColorTable
, IDirectDrawPalette
**Palette
, IUnknown
*pUnkOuter
)
3878 IDirectDrawImpl
*This
= (IDirectDrawImpl
*)iface
;
3879 IDirectDrawPaletteImpl
*object
;
3880 HRESULT hr
= DDERR_GENERIC
;
3881 TRACE("(%p)->(%x,%p,%p,%p)\n", This
, Flags
, ColorTable
, Palette
, pUnkOuter
);
3883 EnterCriticalSection(&ddraw_cs
);
3884 if(pUnkOuter
!= NULL
)
3886 WARN("pUnkOuter is %p, returning CLASS_E_NOAGGREGATION\n", pUnkOuter
);
3887 LeaveCriticalSection(&ddraw_cs
);
3888 return CLASS_E_NOAGGREGATION
;
3891 /* The refcount test shows that a cooplevel is required for this */
3892 if(!This
->cooperative_level
)
3894 WARN("No cooperative level set, returning DDERR_NOCOOPERATIVELEVELSET\n");
3895 LeaveCriticalSection(&ddraw_cs
);
3896 return DDERR_NOCOOPERATIVELEVELSET
;
3899 object
= HeapAlloc(GetProcessHeap(), 0, sizeof(IDirectDrawPaletteImpl
));
3902 ERR("Out of memory when allocating memory for a palette implementation\n");
3903 LeaveCriticalSection(&ddraw_cs
);
3904 return E_OUTOFMEMORY
;
3907 object
->lpVtbl
= &IDirectDrawPalette_Vtbl
;
3910 hr
= IWineD3DDevice_CreatePalette(This
->wineD3DDevice
, Flags
,
3911 ColorTable
, &object
->wineD3DPalette
, (IUnknown
*)object
);
3914 HeapFree(GetProcessHeap(), 0, object
);
3915 LeaveCriticalSection(&ddraw_cs
);
3919 IDirectDraw7_AddRef(iface
);
3920 object
->ifaceToRelease
= (IUnknown
*) iface
;
3921 *Palette
= (IDirectDrawPalette
*)object
;
3922 LeaveCriticalSection(&ddraw_cs
);
3926 static HRESULT WINAPI
ddraw4_CreatePalette(IDirectDraw4
*iface
, DWORD flags
,
3927 PALETTEENTRY
*entries
, IDirectDrawPalette
**palette
, IUnknown
*outer_unknown
)
3929 IDirectDrawImpl
*ddraw
= ddraw_from_ddraw4(iface
);
3932 TRACE("iface %p, flags %#x, entries %p, palette %p, outer_unknown %p.\n",
3933 iface
, flags
, entries
, palette
, outer_unknown
);
3935 hr
= ddraw7_CreatePalette((IDirectDraw7
*)ddraw
, flags
, entries
, palette
, outer_unknown
);
3936 if (SUCCEEDED(hr
) && *palette
)
3938 IDirectDrawPaletteImpl
*impl
= (IDirectDrawPaletteImpl
*)*palette
;
3939 IDirectDraw7_Release((IDirectDraw7
*)ddraw
);
3940 IDirectDraw4_AddRef(iface
);
3941 impl
->ifaceToRelease
= (IUnknown
*)iface
;
3946 static HRESULT WINAPI
ddraw3_CreatePalette(IDirectDraw3
*iface
, DWORD flags
,
3947 PALETTEENTRY
*entries
, IDirectDrawPalette
**palette
, IUnknown
*outer_unknown
)
3949 IDirectDrawImpl
*ddraw
= ddraw_from_ddraw3(iface
);
3952 TRACE("iface %p, flags %#x, entries %p, palette %p, outer_unknown %p.\n",
3953 iface
, flags
, entries
, palette
, outer_unknown
);
3955 hr
= ddraw7_CreatePalette((IDirectDraw7
*)ddraw
, flags
, entries
, palette
, outer_unknown
);
3956 if (SUCCEEDED(hr
) && *palette
)
3958 IDirectDrawPaletteImpl
*impl
= (IDirectDrawPaletteImpl
*)*palette
;
3959 IDirectDraw7_Release((IDirectDraw7
*)ddraw
);
3960 IDirectDraw4_AddRef(iface
);
3961 impl
->ifaceToRelease
= (IUnknown
*)iface
;
3967 static HRESULT WINAPI
ddraw2_CreatePalette(IDirectDraw2
*iface
, DWORD flags
,
3968 PALETTEENTRY
*entries
, IDirectDrawPalette
**palette
, IUnknown
*outer_unknown
)
3970 IDirectDrawImpl
*ddraw
= ddraw_from_ddraw2(iface
);
3973 TRACE("iface %p, flags %#x, entries %p, palette %p, outer_unknown %p.\n",
3974 iface
, flags
, entries
, palette
, outer_unknown
);
3976 hr
= ddraw7_CreatePalette((IDirectDraw7
*)ddraw
, flags
, entries
, palette
, outer_unknown
);
3977 if (SUCCEEDED(hr
) && *palette
)
3979 IDirectDrawPaletteImpl
*impl
= (IDirectDrawPaletteImpl
*)*palette
;
3980 IDirectDraw7_Release((IDirectDraw7
*)ddraw
);
3981 impl
->ifaceToRelease
= NULL
;
3987 static HRESULT WINAPI
ddraw1_CreatePalette(IDirectDraw
*iface
, DWORD flags
,
3988 PALETTEENTRY
*entries
, IDirectDrawPalette
**palette
, IUnknown
*outer_unknown
)
3990 IDirectDrawImpl
*ddraw
= ddraw_from_ddraw1(iface
);
3993 TRACE("iface %p, flags %#x, entries %p, palette %p, outer_unknown %p.\n",
3994 iface
, flags
, entries
, palette
, outer_unknown
);
3996 hr
= ddraw7_CreatePalette((IDirectDraw7
*)ddraw
, flags
, entries
, palette
, outer_unknown
);
3997 if (SUCCEEDED(hr
) && *palette
)
3999 IDirectDrawPaletteImpl
*impl
= (IDirectDrawPaletteImpl
*)*palette
;
4000 IDirectDraw7_Release((IDirectDraw7
*)ddraw
);
4001 impl
->ifaceToRelease
= NULL
;
4007 /*****************************************************************************
4008 * IDirectDraw7::DuplicateSurface
4010 * Duplicates a surface. The surface memory points to the same memory as
4011 * the original surface, and it's released when the last surface referencing
4012 * it is released. I guess that's beyond Wine's surface management right now
4013 * (Idea: create a new DDraw surface with the same WineD3DSurface. I need a
4014 * test application to implement this)
4017 * Src: Address of the source surface
4018 * Dest: Address to write the new surface pointer to
4021 * See IDirectDraw7::CreateSurface
4023 *****************************************************************************/
4024 static HRESULT WINAPI
ddraw7_DuplicateSurface(IDirectDraw7
*iface
,
4025 IDirectDrawSurface7
*Src
, IDirectDrawSurface7
**Dest
)
4027 IDirectDrawImpl
*This
= (IDirectDrawImpl
*)iface
;
4028 IDirectDrawSurfaceImpl
*Surf
= (IDirectDrawSurfaceImpl
*)Src
;
4030 FIXME("(%p)->(%p,%p)\n", This
, Surf
, Dest
);
4032 /* For now, simply create a new, independent surface */
4033 return IDirectDraw7_CreateSurface(iface
,
4034 &Surf
->surface_desc
,
4039 static HRESULT WINAPI
ddraw4_DuplicateSurface(IDirectDraw4
*iface
,
4040 IDirectDrawSurface4
*src
, IDirectDrawSurface4
**dst
)
4042 TRACE("iface %p, src %p, dst %p.\n", iface
, src
, dst
);
4044 return ddraw7_DuplicateSurface((IDirectDraw7
*)ddraw_from_ddraw4(iface
),
4045 (IDirectDrawSurface7
*)src
, (IDirectDrawSurface7
**)dst
);
4048 static HRESULT WINAPI
ddraw3_DuplicateSurface(IDirectDraw3
*iface
,
4049 IDirectDrawSurface
*src
, IDirectDrawSurface
**dst
)
4051 IDirectDrawSurface7
*src7
, *dst7
;
4054 TRACE("iface %p, src %p, dst %p.\n", iface
, src
, dst
);
4056 src7
= src
? (IDirectDrawSurface7
*)surface_from_surface3((IDirectDrawSurface3
*)src
) : NULL
;
4057 hr
= ddraw7_DuplicateSurface((IDirectDraw7
*)ddraw_from_ddraw3(iface
), src7
, &dst7
);
4058 *dst
= dst7
? (IDirectDrawSurface
*)&((IDirectDrawSurfaceImpl
*)dst7
)->IDirectDrawSurface3_vtbl
: NULL
;
4063 static HRESULT WINAPI
ddraw2_DuplicateSurface(IDirectDraw2
*iface
,
4064 IDirectDrawSurface
*src
, IDirectDrawSurface
**dst
)
4066 IDirectDrawSurface7
*src7
, *dst7
;
4069 TRACE("iface %p, src %p, dst %p.\n", iface
, src
, dst
);
4071 src7
= src
? (IDirectDrawSurface7
*)surface_from_surface3((IDirectDrawSurface3
*)src
) : NULL
;
4072 hr
= ddraw7_DuplicateSurface((IDirectDraw7
*)ddraw_from_ddraw2(iface
), src7
, &dst7
);
4073 *dst
= dst7
? (IDirectDrawSurface
*)&((IDirectDrawSurfaceImpl
*)dst7
)->IDirectDrawSurface3_vtbl
: NULL
;
4078 static HRESULT WINAPI
ddraw1_DuplicateSurface(IDirectDraw
*iface
,
4079 IDirectDrawSurface
*src
, IDirectDrawSurface
**dst
)
4081 IDirectDrawSurface7
*src7
, *dst7
;
4084 TRACE("iface %p, src %p, dst %p.\n", iface
, src
, dst
);
4086 src7
= src
? (IDirectDrawSurface7
*)surface_from_surface3((IDirectDrawSurface3
*)src
) : NULL
;
4087 hr
= ddraw7_DuplicateSurface((IDirectDraw7
*)ddraw_from_ddraw1(iface
), src7
, &dst7
);
4088 *dst
= dst7
? (IDirectDrawSurface
*)&((IDirectDrawSurfaceImpl
*)dst7
)->IDirectDrawSurface3_vtbl
: NULL
;
4093 /*****************************************************************************
4094 * IDirectDraw7 VTable
4095 *****************************************************************************/
4096 const IDirectDraw7Vtbl IDirectDraw7_Vtbl
=
4099 ddraw7_QueryInterface
,
4104 ddraw7_CreateClipper
,
4105 ddraw7_CreatePalette
,
4106 ddraw7_CreateSurface
,
4107 ddraw7_DuplicateSurface
,
4108 ddraw7_EnumDisplayModes
,
4109 ddraw7_EnumSurfaces
,
4110 ddraw7_FlipToGDISurface
,
4112 ddraw7_GetDisplayMode
,
4113 ddraw7_GetFourCCCodes
,
4114 ddraw7_GetGDISurface
,
4115 ddraw7_GetMonitorFrequency
,
4117 ddraw7_GetVerticalBlankStatus
,
4119 ddraw7_RestoreDisplayMode
,
4120 ddraw7_SetCooperativeLevel
,
4121 ddraw7_SetDisplayMode
,
4122 ddraw7_WaitForVerticalBlank
,
4124 ddraw7_GetAvailableVidMem
,
4126 ddraw7_GetSurfaceFromDC
,
4128 ddraw7_RestoreAllSurfaces
,
4129 ddraw7_TestCooperativeLevel
,
4130 ddraw7_GetDeviceIdentifier
,
4132 ddraw7_StartModeTest
,
4136 const struct IDirectDraw4Vtbl IDirectDraw4_Vtbl
=
4139 ddraw4_QueryInterface
,
4144 ddraw4_CreateClipper
,
4145 ddraw4_CreatePalette
,
4146 ddraw4_CreateSurface
,
4147 ddraw4_DuplicateSurface
,
4148 ddraw4_EnumDisplayModes
,
4149 ddraw4_EnumSurfaces
,
4150 ddraw4_FlipToGDISurface
,
4152 ddraw4_GetDisplayMode
,
4153 ddraw4_GetFourCCCodes
,
4154 ddraw4_GetGDISurface
,
4155 ddraw4_GetMonitorFrequency
,
4157 ddraw4_GetVerticalBlankStatus
,
4159 ddraw4_RestoreDisplayMode
,
4160 ddraw4_SetCooperativeLevel
,
4161 ddraw4_SetDisplayMode
,
4162 ddraw4_WaitForVerticalBlank
,
4164 ddraw4_GetAvailableVidMem
,
4166 ddraw4_GetSurfaceFromDC
,
4168 ddraw4_RestoreAllSurfaces
,
4169 ddraw4_TestCooperativeLevel
,
4170 ddraw4_GetDeviceIdentifier
,
4173 const struct IDirectDraw3Vtbl IDirectDraw3_Vtbl
=
4176 ddraw3_QueryInterface
,
4181 ddraw3_CreateClipper
,
4182 ddraw3_CreatePalette
,
4183 ddraw3_CreateSurface
,
4184 ddraw3_DuplicateSurface
,
4185 ddraw3_EnumDisplayModes
,
4186 ddraw3_EnumSurfaces
,
4187 ddraw3_FlipToGDISurface
,
4189 ddraw3_GetDisplayMode
,
4190 ddraw3_GetFourCCCodes
,
4191 ddraw3_GetGDISurface
,
4192 ddraw3_GetMonitorFrequency
,
4194 ddraw3_GetVerticalBlankStatus
,
4196 ddraw3_RestoreDisplayMode
,
4197 ddraw3_SetCooperativeLevel
,
4198 ddraw3_SetDisplayMode
,
4199 ddraw3_WaitForVerticalBlank
,
4201 ddraw3_GetAvailableVidMem
,
4203 ddraw3_GetSurfaceFromDC
,
4206 const struct IDirectDraw2Vtbl IDirectDraw2_Vtbl
=
4209 ddraw2_QueryInterface
,
4214 ddraw2_CreateClipper
,
4215 ddraw2_CreatePalette
,
4216 ddraw2_CreateSurface
,
4217 ddraw2_DuplicateSurface
,
4218 ddraw2_EnumDisplayModes
,
4219 ddraw2_EnumSurfaces
,
4220 ddraw2_FlipToGDISurface
,
4222 ddraw2_GetDisplayMode
,
4223 ddraw2_GetFourCCCodes
,
4224 ddraw2_GetGDISurface
,
4225 ddraw2_GetMonitorFrequency
,
4227 ddraw2_GetVerticalBlankStatus
,
4229 ddraw2_RestoreDisplayMode
,
4230 ddraw2_SetCooperativeLevel
,
4231 ddraw2_SetDisplayMode
,
4232 ddraw2_WaitForVerticalBlank
,
4234 ddraw2_GetAvailableVidMem
,
4237 const struct IDirectDrawVtbl IDirectDraw1_Vtbl
=
4240 ddraw1_QueryInterface
,
4245 ddraw1_CreateClipper
,
4246 ddraw1_CreatePalette
,
4247 ddraw1_CreateSurface
,
4248 ddraw1_DuplicateSurface
,
4249 ddraw1_EnumDisplayModes
,
4250 ddraw1_EnumSurfaces
,
4251 ddraw1_FlipToGDISurface
,
4253 ddraw1_GetDisplayMode
,
4254 ddraw1_GetFourCCCodes
,
4255 ddraw1_GetGDISurface
,
4256 ddraw1_GetMonitorFrequency
,
4258 ddraw1_GetVerticalBlankStatus
,
4260 ddraw1_RestoreDisplayMode
,
4261 ddraw1_SetCooperativeLevel
,
4262 ddraw1_SetDisplayMode
,
4263 ddraw1_WaitForVerticalBlank
,
4266 /*****************************************************************************
4269 * Finds the WineD3D vertex declaration for a specific fvf, and creates one
4270 * if none was found.
4272 * This function is in ddraw.c and the DDraw object space because D3D7
4273 * vertex buffers are created using the IDirect3D interface to the ddraw
4274 * object, so they can be valid across D3D devices(theoretically. The ddraw
4275 * object also owns the wined3d device
4279 * fvf: Fvf to find the decl for
4282 * NULL in case of an error, the IWineD3DVertexDeclaration interface for the
4285 *****************************************************************************/
4286 IWineD3DVertexDeclaration
*ddraw_find_decl(IDirectDrawImpl
*This
, DWORD fvf
)
4289 IWineD3DVertexDeclaration
* pDecl
= NULL
;
4290 int p
, low
, high
; /* deliberately signed */
4291 struct FvfToDecl
*convertedDecls
= This
->decls
;
4293 TRACE("Searching for declaration for fvf %08x... ", fvf
);
4296 high
= This
->numConvertedDecls
- 1;
4297 while(low
<= high
) {
4298 p
= (low
+ high
) >> 1;
4300 if(convertedDecls
[p
].fvf
== fvf
) {
4301 TRACE("found %p\n", convertedDecls
[p
].decl
);
4302 return convertedDecls
[p
].decl
;
4303 } else if(convertedDecls
[p
].fvf
< fvf
) {
4309 TRACE("not found. Creating and inserting at position %d.\n", low
);
4311 hr
= IWineD3DDevice_CreateVertexDeclarationFromFVF(This
->wineD3DDevice
, &pDecl
,
4312 (IUnknown
*)This
, &ddraw_null_wined3d_parent_ops
, fvf
);
4313 if (hr
!= S_OK
) return NULL
;
4315 if(This
->declArraySize
== This
->numConvertedDecls
) {
4316 int grow
= max(This
->declArraySize
/ 2, 8);
4317 convertedDecls
= HeapReAlloc(GetProcessHeap(), 0, convertedDecls
,
4318 sizeof(convertedDecls
[0]) * (This
->numConvertedDecls
+ grow
));
4319 if(!convertedDecls
) {
4320 /* This will destroy it */
4321 IWineD3DVertexDeclaration_Release(pDecl
);
4324 This
->decls
= convertedDecls
;
4325 This
->declArraySize
+= grow
;
4328 memmove(convertedDecls
+ low
+ 1, convertedDecls
+ low
, sizeof(convertedDecls
[0]) * (This
->numConvertedDecls
- low
));
4329 convertedDecls
[low
].decl
= pDecl
;
4330 convertedDecls
[low
].fvf
= fvf
;
4331 This
->numConvertedDecls
++;
4333 TRACE("Returning %p. %d decls in array\n", pDecl
, This
->numConvertedDecls
);
4337 /* IWineD3DDeviceParent IUnknown methods */
4339 static inline struct IDirectDrawImpl
*ddraw_from_device_parent(IWineD3DDeviceParent
*iface
)
4341 return (struct IDirectDrawImpl
*)((char*)iface
- FIELD_OFFSET(struct IDirectDrawImpl
, device_parent_vtbl
));
4344 static HRESULT STDMETHODCALLTYPE
device_parent_QueryInterface(IWineD3DDeviceParent
*iface
, REFIID riid
, void **object
)
4346 struct IDirectDrawImpl
*This
= ddraw_from_device_parent(iface
);
4347 return ddraw7_QueryInterface((IDirectDraw7
*)This
, riid
, object
);
4350 static ULONG STDMETHODCALLTYPE
device_parent_AddRef(IWineD3DDeviceParent
*iface
)
4352 struct IDirectDrawImpl
*This
= ddraw_from_device_parent(iface
);
4353 return ddraw7_AddRef((IDirectDraw7
*)This
);
4356 static ULONG STDMETHODCALLTYPE
device_parent_Release(IWineD3DDeviceParent
*iface
)
4358 struct IDirectDrawImpl
*This
= ddraw_from_device_parent(iface
);
4359 return ddraw7_Release((IDirectDraw7
*)This
);
4362 /* IWineD3DDeviceParent methods */
4364 static void STDMETHODCALLTYPE
device_parent_WineD3DDeviceCreated(IWineD3DDeviceParent
*iface
, IWineD3DDevice
*device
)
4366 TRACE("iface %p, device %p\n", iface
, device
);
4369 static HRESULT STDMETHODCALLTYPE
device_parent_CreateSurface(IWineD3DDeviceParent
*iface
,
4370 IUnknown
*superior
, UINT width
, UINT height
, WINED3DFORMAT format
, DWORD usage
,
4371 WINED3DPOOL pool
, UINT level
, WINED3DCUBEMAP_FACES face
, IWineD3DSurface
**surface
)
4373 struct IDirectDrawImpl
*This
= ddraw_from_device_parent(iface
);
4374 IDirectDrawSurfaceImpl
*surf
= NULL
;
4376 DDSCAPS2 searchcaps
= This
->tex_root
->surface_desc
.ddsCaps
;
4378 TRACE("iface %p, superior %p, width %u, height %u, format %#x, usage %#x,\n"
4379 "\tpool %#x, level %u, face %u, surface %p\n",
4380 iface
, superior
, width
, height
, format
, usage
, pool
, level
, face
, surface
);
4382 searchcaps
.dwCaps2
&= ~DDSCAPS2_CUBEMAP_ALLFACES
;
4385 case WINED3DCUBEMAP_FACE_POSITIVE_X
:
4386 TRACE("Asked for positive x\n");
4387 if (searchcaps
.dwCaps2
& DDSCAPS2_CUBEMAP
)
4389 searchcaps
.dwCaps2
|= DDSCAPS2_CUBEMAP_POSITIVEX
;
4391 surf
= This
->tex_root
; break;
4392 case WINED3DCUBEMAP_FACE_NEGATIVE_X
:
4393 TRACE("Asked for negative x\n");
4394 searchcaps
.dwCaps2
|= DDSCAPS2_CUBEMAP_NEGATIVEX
; break;
4395 case WINED3DCUBEMAP_FACE_POSITIVE_Y
:
4396 TRACE("Asked for positive y\n");
4397 searchcaps
.dwCaps2
|= DDSCAPS2_CUBEMAP_POSITIVEY
; break;
4398 case WINED3DCUBEMAP_FACE_NEGATIVE_Y
:
4399 TRACE("Asked for negative y\n");
4400 searchcaps
.dwCaps2
|= DDSCAPS2_CUBEMAP_NEGATIVEY
; break;
4401 case WINED3DCUBEMAP_FACE_POSITIVE_Z
:
4402 TRACE("Asked for positive z\n");
4403 searchcaps
.dwCaps2
|= DDSCAPS2_CUBEMAP_POSITIVEZ
; break;
4404 case WINED3DCUBEMAP_FACE_NEGATIVE_Z
:
4405 TRACE("Asked for negative z\n");
4406 searchcaps
.dwCaps2
|= DDSCAPS2_CUBEMAP_NEGATIVEZ
; break;
4407 default: {ERR("Unexpected cube face\n");} /* Stupid compiler */
4412 IDirectDrawSurface7
*attached
;
4413 IDirectDrawSurface7_GetAttachedSurface((IDirectDrawSurface7
*)This
->tex_root
, &searchcaps
, &attached
);
4414 surf
= (IDirectDrawSurfaceImpl
*)attached
;
4415 IDirectDrawSurface7_Release(attached
);
4417 if (!surf
) ERR("root search surface not found\n");
4419 /* Find the wanted mipmap. There are enough mipmaps in the chain */
4422 IDirectDrawSurface7
*attached
;
4423 IDirectDrawSurface7_GetAttachedSurface((IDirectDrawSurface7
*)surf
, &searchcaps
, &attached
);
4424 if(!attached
) ERR("Surface not found\n");
4425 surf
= (IDirectDrawSurfaceImpl
*)attached
;
4426 IDirectDrawSurface7_Release(attached
);
4430 /* Return the surface */
4431 *surface
= surf
->WineD3DSurface
;
4432 IWineD3DSurface_AddRef(*surface
);
4434 TRACE("Returning wineD3DSurface %p, it belongs to surface %p\n", *surface
, surf
);
4439 static HRESULT WINAPI
findRenderTarget(IDirectDrawSurface7
*surface
, DDSURFACEDESC2
*surface_desc
, void *ctx
)
4441 IDirectDrawSurfaceImpl
*s
= (IDirectDrawSurfaceImpl
*)surface
;
4442 IDirectDrawSurfaceImpl
**target
= ctx
;
4444 if (!s
->isRenderTarget
)
4447 IDirectDrawSurface7_Release(surface
);
4448 return DDENUMRET_CANCEL
;
4451 /* Recurse into the surface tree */
4452 IDirectDrawSurface7_EnumAttachedSurfaces(surface
, ctx
, findRenderTarget
);
4454 IDirectDrawSurface7_Release(surface
);
4455 if (*target
) return DDENUMRET_CANCEL
;
4457 return DDENUMRET_OK
;
4460 static HRESULT STDMETHODCALLTYPE
device_parent_CreateRenderTarget(IWineD3DDeviceParent
*iface
,
4461 IUnknown
*superior
, UINT width
, UINT height
, WINED3DFORMAT format
, WINED3DMULTISAMPLE_TYPE multisample_type
,
4462 DWORD multisample_quality
, BOOL lockable
, IWineD3DSurface
**surface
)
4464 struct IDirectDrawImpl
*This
= ddraw_from_device_parent(iface
);
4465 IDirectDrawSurfaceImpl
*d3d_surface
= This
->d3d_target
;
4466 IDirectDrawSurfaceImpl
*target
= NULL
;
4468 TRACE("iface %p, superior %p, width %u, height %u, format %#x, multisample_type %#x,\n"
4469 "\tmultisample_quality %u, lockable %u, surface %p\n",
4470 iface
, superior
, width
, height
, format
, multisample_type
, multisample_quality
, lockable
, surface
);
4472 if (d3d_surface
->isRenderTarget
)
4474 IDirectDrawSurface7_EnumAttachedSurfaces((IDirectDrawSurface7
*)d3d_surface
, &target
, findRenderTarget
);
4478 target
= d3d_surface
;
4483 target
= This
->d3d_target
;
4484 ERR(" (%p) : No DirectDrawSurface found to create the back buffer. Using the front buffer as back buffer. Uncertain consequences\n", This
);
4487 /* TODO: Return failure if the dimensions do not match, but this shouldn't happen */
4489 *surface
= target
->WineD3DSurface
;
4490 IWineD3DSurface_AddRef(*surface
);
4491 target
->isRenderTarget
= TRUE
;
4493 TRACE("Returning wineD3DSurface %p, it belongs to surface %p\n", *surface
, d3d_surface
);
4498 static HRESULT STDMETHODCALLTYPE
device_parent_CreateDepthStencilSurface(IWineD3DDeviceParent
*iface
,
4499 IUnknown
*superior
, UINT width
, UINT height
, WINED3DFORMAT format
, WINED3DMULTISAMPLE_TYPE multisample_type
,
4500 DWORD multisample_quality
, BOOL discard
, IWineD3DSurface
**surface
)
4502 struct IDirectDrawImpl
*This
= ddraw_from_device_parent(iface
);
4503 IDirectDrawSurfaceImpl
*ddraw_surface
;
4504 DDSURFACEDESC2 ddsd
;
4507 TRACE("iface %p, superior %p, width %u, height %u, format %#x, multisample_type %#x,\n"
4508 "\tmultisample_quality %u, discard %u, surface %p\n",
4509 iface
, superior
, width
, height
, format
, multisample_type
, multisample_quality
, discard
, surface
);
4513 /* Create a DirectDraw surface */
4514 memset(&ddsd
, 0, sizeof(ddsd
));
4515 ddsd
.dwSize
= sizeof(ddsd
);
4516 ddsd
.u4
.ddpfPixelFormat
.dwSize
= sizeof(DDPIXELFORMAT
);
4517 ddsd
.dwFlags
= DDSD_PIXELFORMAT
| DDSD_WIDTH
| DDSD_HEIGHT
| DDSD_CAPS
;
4518 ddsd
.ddsCaps
.dwCaps
= DDSCAPS_OFFSCREENPLAIN
;
4519 ddsd
.dwHeight
= height
;
4520 ddsd
.dwWidth
= width
;
4523 PixelFormat_WineD3DtoDD(&ddsd
.u4
.ddpfPixelFormat
, format
);
4527 ddsd
.dwFlags
^= DDSD_PIXELFORMAT
;
4530 This
->depthstencil
= TRUE
;
4531 hr
= IDirectDraw7_CreateSurface((IDirectDraw7
*)This
, &ddsd
, (IDirectDrawSurface7
**)&ddraw_surface
, NULL
);
4532 This
->depthstencil
= FALSE
;
4535 ERR(" (%p) Creating a DepthStencil Surface failed, result = %x\n", This
, hr
);
4539 *surface
= ddraw_surface
->WineD3DSurface
;
4540 IWineD3DSurface_AddRef(*surface
);
4541 IDirectDrawSurface7_Release((IDirectDrawSurface7
*)ddraw_surface
);
4546 static HRESULT STDMETHODCALLTYPE
device_parent_CreateVolume(IWineD3DDeviceParent
*iface
,
4547 IUnknown
*superior
, UINT width
, UINT height
, UINT depth
, WINED3DFORMAT format
,
4548 WINED3DPOOL pool
, DWORD usage
, IWineD3DVolume
**volume
)
4550 TRACE("iface %p, superior %p, width %u, height %u, depth %u, format %#x, pool %#x, usage %#x, volume %p\n",
4551 iface
, superior
, width
, height
, depth
, format
, pool
, usage
, volume
);
4553 ERR("Not implemented!\n");
4558 static HRESULT STDMETHODCALLTYPE
device_parent_CreateSwapChain(IWineD3DDeviceParent
*iface
,
4559 WINED3DPRESENT_PARAMETERS
*present_parameters
, IWineD3DSwapChain
**swapchain
)
4561 struct IDirectDrawImpl
*This
= ddraw_from_device_parent(iface
);
4562 IDirectDrawSurfaceImpl
*iterator
;
4563 IParentImpl
*object
;
4566 TRACE("iface %p, present_parameters %p, swapchain %p\n", iface
, present_parameters
, swapchain
);
4568 object
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(IParentImpl
));
4571 FIXME("Allocation of memory failed\n");
4573 return DDERR_OUTOFVIDEOMEMORY
;
4576 object
->lpVtbl
= &IParent_Vtbl
;
4579 hr
= IWineD3DDevice_CreateSwapChain(This
->wineD3DDevice
, present_parameters
,
4580 swapchain
, (IUnknown
*)object
, This
->ImplType
);
4583 FIXME("(%p) CreateSwapChain failed, returning %#x\n", iface
, hr
);
4584 HeapFree(GetProcessHeap(), 0 , object
);
4589 object
->child
= (IUnknown
*)*swapchain
;
4590 This
->d3d_target
->wineD3DSwapChain
= *swapchain
;
4591 iterator
= This
->d3d_target
->complex_array
[0];
4594 iterator
->wineD3DSwapChain
= *swapchain
;
4595 iterator
= iterator
->complex_array
[0];
4601 const IWineD3DDeviceParentVtbl ddraw_wined3d_device_parent_vtbl
=
4603 /* IUnknown methods */
4604 device_parent_QueryInterface
,
4605 device_parent_AddRef
,
4606 device_parent_Release
,
4607 /* IWineD3DDeviceParent methods */
4608 device_parent_WineD3DDeviceCreated
,
4609 device_parent_CreateSurface
,
4610 device_parent_CreateRenderTarget
,
4611 device_parent_CreateDepthStencilSurface
,
4612 device_parent_CreateVolume
,
4613 device_parent_CreateSwapChain
,