1 /* DirectDraw Base Functions
3 * Copyright 1997-1999 Marcus Meissner
4 * Copyright 1998 Lionel Ulmer
5 * Copyright 2000-2001 TransGaming Technologies Inc.
6 * Copyright 2006 Stefan Dösinger
8 * This file contains the (internal) driver registration functions,
9 * driver enumeration APIs and DirectDraw creation functions.
11 * This library is free software; you can redistribute it and/or
12 * modify it under the terms of the GNU Lesser General Public
13 * License as published by the Free Software Foundation; either
14 * version 2.1 of the License, or (at your option) any later version.
16 * This library is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19 * Lesser General Public License for more details.
21 * You should have received a copy of the GNU Lesser General Public
22 * License along with this library; if not, write to the Free Software
23 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
27 #include "wine/port.h"
28 #include "wine/debug.h"
42 #include "wine/exception.h"
49 #include "ddraw_private.h"
51 WINE_DEFAULT_DEBUG_CHANNEL(ddraw
);
53 /* The configured default surface */
54 WINED3DSURFTYPE DefaultSurfaceType
= SURFACE_UNKNOWN
;
56 /***********************************************************************
58 * Helper function for DirectDrawCreate and friends
59 * Creates a new DDraw interface with the given REFIID
61 * Interfaces that can be created:
62 * IDirectDraw, IDirectDraw2, IDirectDraw4, IDirectDraw7
63 * IDirect3D, IDirect3D2, IDirect3D3, IDirect3D7. (Does Windows return
64 * IDirect3D interfaces?)
67 * guid: ID of the requested driver, NULL for the default driver.
68 * The GUID can be queried with DirectDrawEnumerate(Ex)A/W
69 * DD: Used to return the pointer to the created object
70 * UnkOuter: For aggregation, which is unsupported. Must be NULL
71 * iid: requested version ID.
74 * DD_OK if the Interface was created successfully
75 * CLASS_E_NOAGGREGATION if UnkOuter is not NULL
76 * E_OUTOFMEMORY if some allocation failed
78 ***********************************************************************/
80 DDRAW_Create(GUID
*guid
,
85 IDirectDrawImpl
*This
= NULL
;
87 IWineD3D
*wineD3D
= NULL
;
88 IWineD3DDevice
*wineD3DDevice
= NULL
;
90 WINED3DDEVTYPE devicetype
;
92 TRACE("(%s,%p,%p)\n", debugstr_guid(guid
), DD
, UnkOuter
);
94 /* We don't care about this guids. Well, there's no special guid anyway
97 if (guid
== (GUID
*) DDCREATE_EMULATIONONLY
)
99 /* Use the reference device id. This doesn't actually change anything,
100 * WineD3D always uses OpenGL for D3D rendering. One could make it request
103 devicetype
= WINED3DDEVTYPE_REF
;
105 else if(guid
== (GUID
*) DDCREATE_HARDWAREONLY
)
107 devicetype
= WINED3DDEVTYPE_HAL
;
114 /* DDraw doesn't support aggregation, according to msdn */
115 if (UnkOuter
!= NULL
)
116 return CLASS_E_NOAGGREGATION
;
118 /* DirectDraw creation comes here */
119 This
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(IDirectDrawImpl
));
122 ERR("Out of memory when creating DirectDraw\n");
123 return E_OUTOFMEMORY
;
127 * IDirectDraw and IDirect3D are the same object,
128 * QueryInterface is used to get other interfaces.
130 ICOM_INIT_INTERFACE(This
, IDirectDraw
, IDirectDraw1_Vtbl
);
131 ICOM_INIT_INTERFACE(This
, IDirectDraw2
, IDirectDraw2_Vtbl
);
132 ICOM_INIT_INTERFACE(This
, IDirectDraw4
, IDirectDraw4_Vtbl
);
133 ICOM_INIT_INTERFACE(This
, IDirectDraw7
, IDirectDraw7_Vtbl
);
134 ICOM_INIT_INTERFACE(This
, IDirect3D
, IDirect3D1_Vtbl
);
135 ICOM_INIT_INTERFACE(This
, IDirect3D2
, IDirect3D2_Vtbl
);
136 ICOM_INIT_INTERFACE(This
, IDirect3D3
, IDirect3D3_Vtbl
);
137 ICOM_INIT_INTERFACE(This
, IDirect3D7
, IDirect3D7_Vtbl
);
139 /* See comments in IDirectDrawImpl_CreateNewSurface for a description
141 * Read from a registry key, should add a winecfg option later
143 This
->ImplType
= DefaultSurfaceType
;
145 /* Get the current screen settings */
146 hDC
= CreateDCA("DISPLAY", NULL
, NULL
, NULL
);
147 This
->orig_bpp
= GetDeviceCaps(hDC
, BITSPIXEL
) * GetDeviceCaps(hDC
, PLANES
);
149 This
->orig_width
= GetSystemMetrics(SM_CXSCREEN
);
150 This
->orig_height
= GetSystemMetrics(SM_CYSCREEN
);
152 /* Initialize WineD3D
154 * All Rendering (2D and 3D) is relayed to WineD3D,
155 * but DirectDraw specific management, like DDSURFACEDESC and DDPIXELFORMAT
156 * structure handling is handled in this lib.
158 wineD3D
= WineDirect3DCreate(0 /* SDKVersion */, 7 /* DXVersion */, (IUnknown
*) This
/* Parent */);
161 ERR("Failed to initialise WineD3D\n");
165 This
->wineD3D
= wineD3D
;
166 TRACE("WineD3D created at %p\n", wineD3D
);
168 /* Initialized member...
170 * It is set to false at creation time, and set to true in
171 * IDirectDraw7::Initialize. Its sole purpose is to return DD_OK on
172 * initialize only once
174 This
->initialized
= FALSE
;
176 /* Initialize WineD3DDevice
178 * It is used for screen setup, surface and palette creation
179 * When a Direct3DDevice7 is created, the D3D capabilities of WineD3D are
182 hr
= IWineD3D_CreateDevice(wineD3D
,
183 0 /*D3D_ADAPTER_DEFAULT*/,
185 NULL
, /* FocusWindow, don't know yet */
186 0, /* BehaviorFlags */
188 (IUnknown
*) ICOM_INTERFACE(This
, IDirectDraw7
));
191 ERR("Failed to create a wineD3DDevice, result = %lx\n", hr
);
194 This
->wineD3DDevice
= wineD3DDevice
;
195 TRACE("wineD3DDevice created at %p\n", This
->wineD3DDevice
);
197 /* Register the window class
199 * It is used to create a hidden window for D3D
200 * rendering, if the application didn't pass one.
201 * It can also be used for Creating a device window
202 * from SetCooperativeLevel
204 * The name: DDRAW_<address>. The classname is
205 * 32 bit long, so a 64 bit address will fit nicely
206 * (Will this be compiled for 64 bit anyway?)
209 sprintf(This
->classname
, "DDRAW_%p", This
);
211 memset(&This
->wnd_class
, 0, sizeof(This
->wnd_class
));
212 This
->wnd_class
.style
= CS_HREDRAW
| CS_VREDRAW
;
213 This
->wnd_class
.lpfnWndProc
= DefWindowProcA
;
214 This
->wnd_class
.cbClsExtra
= 0;
215 This
->wnd_class
.cbWndExtra
= 0;
216 This
->wnd_class
.hInstance
= GetModuleHandleA(0);
217 This
->wnd_class
.hIcon
= 0;
218 This
->wnd_class
.hCursor
= 0;
219 This
->wnd_class
.hbrBackground
= (HBRUSH
) GetStockObject(BLACK_BRUSH
);
220 This
->wnd_class
.lpszMenuName
= NULL
;
221 This
->wnd_class
.lpszClassName
= This
->classname
;
222 if(!RegisterClassA(&This
->wnd_class
))
224 ERR("RegisterClassA failed!\n");
228 /* Get the amount of video memory */
229 This
->total_vidmem
= IWineD3DDevice_GetAvailableTextureMem(This
->wineD3DDevice
);
231 /* Initialize the caps */
232 This
->caps
.dwSize
= sizeof(This
->caps
);
233 #define BLIT_CAPS (DDCAPS_BLT | DDCAPS_BLTCOLORFILL | DDCAPS_BLTDEPTHFILL \
234 | DDCAPS_BLTSTRETCH | DDCAPS_CANBLTSYSMEM | DDCAPS_CANCLIP \
235 | DDCAPS_CANCLIPSTRETCHED | DDCAPS_COLORKEY \
236 | DDCAPS_COLORKEYHWASSIST | DDCAPS_OVERLAY | DDCAPS_OVERLAYSTRETCH |DDCAPS_ALIGNBOUNDARYSRC )
237 #define CKEY_CAPS (DDCKEYCAPS_DESTBLT | DDCKEYCAPS_SRCBLT)
238 #define FX_CAPS (DDFXCAPS_BLTALPHA | DDFXCAPS_BLTMIRRORLEFTRIGHT \
239 | DDFXCAPS_BLTMIRRORUPDOWN | DDFXCAPS_BLTROTATION90 \
240 | DDFXCAPS_BLTSHRINKX | DDFXCAPS_BLTSHRINKXN \
241 | DDFXCAPS_BLTSHRINKY | DDFXCAPS_BLTSHRINKXN \
242 | DDFXCAPS_BLTSTRETCHX | DDFXCAPS_BLTSTRETCHXN \
243 | DDFXCAPS_BLTSTRETCHY | DDFXCAPS_BLTSTRETCHYN)
244 This
->caps
.dwCaps
|= DDCAPS_GDI
| DDCAPS_PALETTE
| BLIT_CAPS
;
246 This
->caps
.dwCaps2
|= DDCAPS2_CERTIFIED
| DDCAPS2_NOPAGELOCKREQUIRED
|
247 DDCAPS2_PRIMARYGAMMA
| DDCAPS2_WIDESURFACES
|
248 DDCAPS2_CANRENDERWINDOWED
;
249 This
->caps
.dwCKeyCaps
|= CKEY_CAPS
;
250 This
->caps
.dwFXCaps
|= FX_CAPS
;
251 This
->caps
.dwPalCaps
|= DDPCAPS_8BIT
| DDPCAPS_PRIMARYSURFACE
;
252 This
->caps
.dwVidMemTotal
= This
->total_vidmem
;
253 This
->caps
.dwVidMemFree
= This
->total_vidmem
;
254 This
->caps
.dwSVBCaps
|= BLIT_CAPS
;
255 This
->caps
.dwSVBCKeyCaps
|= CKEY_CAPS
;
256 This
->caps
.dwSVBFXCaps
|= FX_CAPS
;
257 This
->caps
.dwVSBCaps
|= BLIT_CAPS
;
258 This
->caps
.dwVSBCKeyCaps
|= CKEY_CAPS
;
259 This
->caps
.dwVSBFXCaps
|= FX_CAPS
;
260 This
->caps
.dwSSBCaps
|= BLIT_CAPS
;
261 This
->caps
.dwSSBCKeyCaps
|= CKEY_CAPS
;
262 This
->caps
.dwSSBFXCaps
|= FX_CAPS
;
263 This
->caps
.ddsCaps
.dwCaps
|= DDSCAPS_ALPHA
| DDSCAPS_BACKBUFFER
|
264 DDSCAPS_FLIP
| DDSCAPS_FRONTBUFFER
|
265 DDSCAPS_OFFSCREENPLAIN
| DDSCAPS_PALETTE
|
266 DDSCAPS_PRIMARYSURFACE
| DDSCAPS_SYSTEMMEMORY
|
267 DDSCAPS_VIDEOMEMORY
| DDSCAPS_VISIBLE
;
268 /* Hacks for D3D code */
269 /* TODO: Check if WineD3D has 3D enabled
270 Need opengl surfaces or auto for 3D
272 if(This
->ImplType
== 0 || This
->ImplType
== SURFACE_OPENGL
)
274 This
->caps
.dwCaps
|= DDCAPS_3D
;
275 This
->caps
.ddsCaps
.dwCaps
|= DDSCAPS_3DDEVICE
| DDSCAPS_MIPMAP
| DDSCAPS_TEXTURE
| DDSCAPS_ZBUFFER
;
277 This
->caps
.ddsOldCaps
.dwCaps
= This
->caps
.ddsCaps
.dwCaps
;
283 /* Add the object to the ddraw cleanup list */
284 This
->next
= ddraw_list
;
287 /* Call QueryInterface to get the pointer to the requested interface. This also initializes
288 * The required refcount
290 hr
= IDirectDraw7_QueryInterface( ICOM_INTERFACE(This
, IDirectDraw7
), iid
, DD
);
291 if(SUCCEEDED(hr
)) return DD_OK
;
294 /* Let's hope we never need this ;) */
295 if(wineD3DDevice
) IWineD3DDevice_Release(wineD3DDevice
);
296 if(wineD3D
) IWineD3D_Release(wineD3D
);
297 if(This
) HeapFree(GetProcessHeap(), 0, This
);
301 /***********************************************************************
302 * DirectDrawCreate (DDRAW.@)
304 * Creates legacy DirectDraw Interfaces. Can't create IDirectDraw7
305 * interfaces in theory
307 * Arguments, return values: See DDRAW_Create
309 ***********************************************************************/
311 DirectDrawCreate(GUID
*GUID
,
315 TRACE("(%s,%p,%p)\n", debugstr_guid(GUID
), DD
, UnkOuter
);
317 return DDRAW_Create(GUID
, (void **) DD
, UnkOuter
, &IID_IDirectDraw
);
320 /***********************************************************************
321 * DirectDrawCreateEx (DDRAW.@)
323 * Only creates new IDirectDraw7 interfaces, supposed to fail if legacy
324 * interfaces are requested.
326 * Arguments, return values: See DDRAW_Create
328 ***********************************************************************/
330 DirectDrawCreateEx(GUID
*GUID
,
335 TRACE("(%s,%p,%s,%p)\n", debugstr_guid(GUID
), DD
, debugstr_guid(iid
), UnkOuter
);
337 if (!IsEqualGUID(iid
, &IID_IDirectDraw7
))
338 return DDERR_INVALIDPARAMS
;
340 return DDRAW_Create(GUID
, DD
, UnkOuter
, iid
);
343 /***********************************************************************
344 * DirectDrawEnumerateA (DDRAW.@)
346 * Enumerates legacy ddraw drivers, ascii version. We only have one
347 * driver, which relays to WineD3D. If we were sufficiently cool,
348 * we could offer various interfaces, which use a different default surface
349 * implementation, but I think it's better to offer this choice in
350 * winecfg, because some apps use the default driver, so we would need
351 * a winecfg option anyway, and there shouldn't be 2 ways to set one setting
354 * Callback: Callback function from the app
355 * Context: Argument to the call back.
359 * E_INVALIDARG if the Callback caused a page fault
362 ***********************************************************************/
364 DirectDrawEnumerateA(LPDDENUMCALLBACKA Callback
,
369 TRACE(" Enumerating default DirectDraw HAL interface\n");
370 /* We only have one driver */
373 stop
= !Callback(NULL
, "DirectDraw HAL", "display", Context
);
381 TRACE(" End of enumeration\n");
385 /***********************************************************************
386 * DirectDrawEnumerateExA (DDRAW.@)
388 * Enumerates DirectDraw7 drivers, ascii version. See
389 * the comments above DirectDrawEnumerateA for more details.
391 * The Flag member is not supported right now.
393 ***********************************************************************/
395 DirectDrawEnumerateExA(LPDDENUMCALLBACKEXA Callback
,
400 TRACE("Enumerating default DirectDraw HAL interface\n");
402 /* We only have one driver by now */
405 /* QuickTime expects the description "DirectDraw HAL" */
406 stop
= !Callback(NULL
, "DirectDraw HAL", "display", Context
, 0);
414 TRACE("End of enumeration\n");
418 /***********************************************************************
419 * DirectDrawEnumerateW (DDRAW.@)
421 * Enumerates legacy drivers, unicode version. See
422 * the comments above DirectDrawEnumerateA for more details.
424 * The Flag member is not supported right now.
426 ***********************************************************************/
428 /***********************************************************************
429 * DirectDrawEnumerateExW (DDRAW.@)
431 * Enumerates DirectDraw7 drivers, unicode version. See
432 * the comments above DirectDrawEnumerateA for more details.
434 * The Flag member is not supported right now.
436 ***********************************************************************/
438 /***********************************************************************
439 * Classfactory implementation.
440 ***********************************************************************/
442 /***********************************************************************
443 * CF_CreateDirectDraw
445 * DDraw creation function for the class factory
448 * UnkOuter: Set to NULL
449 * iid: ID of the wanted interface
450 * obj: Address to pass the interface pointer back
453 * DD_OK / DDERR*, see DDRAW_Create
455 ***********************************************************************/
457 CF_CreateDirectDraw(IUnknown
* UnkOuter
, REFIID iid
,
462 TRACE("(%p,%s,%p)\n", UnkOuter
, debugstr_guid(iid
), obj
);
464 hr
= DDRAW_Create(NULL
, obj
, UnkOuter
, iid
);
468 /***********************************************************************
469 * CF_CreateDirectDraw
471 * Clipper creation function for the class factory
474 * UnkOuter: Set to NULL
475 * iid: ID of the wanted interface
476 * obj: Address to pass the interface pointer back
479 * DD_OK / DDERR*, see DDRAW_Create
481 ***********************************************************************/
483 CF_CreateDirectDrawClipper(IUnknown
* UnkOuter
, REFIID riid
,
487 IDirectDrawClipper
*Clip
;
489 hr
= DirectDrawCreateClipper(0, &Clip
, UnkOuter
);
490 if (hr
!= DD_OK
) return hr
;
492 hr
= IDirectDrawClipper_QueryInterface(Clip
, riid
, obj
);
493 IDirectDrawClipper_Release(Clip
);
497 static const struct object_creation_info object_creation
[] =
499 { &CLSID_DirectDraw
, CF_CreateDirectDraw
},
500 { &CLSID_DirectDraw7
, CF_CreateDirectDraw
},
501 { &CLSID_DirectDrawClipper
, CF_CreateDirectDrawClipper
}
504 /*******************************************************************************
505 * IDirectDrawClassFactory::QueryInterface
507 * QueryInterface for the class factory
510 * riid Reference to identifier of queried interface
511 * ppv Address to return the interface pointer at
515 * Failure: E_NOINTERFACE
517 *******************************************************************************/
518 static HRESULT WINAPI
519 IDirectDrawClassFactoryImpl_QueryInterface(IClassFactory
*iface
,
523 ICOM_THIS_FROM(IClassFactoryImpl
, IClassFactory
, iface
);
525 TRACE("(%p)->(%s,%p)\n", This
, debugstr_guid(riid
), obj
);
527 if (IsEqualGUID(riid
, &IID_IUnknown
)
528 || IsEqualGUID(riid
, &IID_IClassFactory
))
530 IClassFactory_AddRef(iface
);
535 WARN("(%p)->(%s,%p),not found\n",This
,debugstr_guid(riid
),obj
);
536 return E_NOINTERFACE
;
539 /*******************************************************************************
540 * IDirectDrawClassFactory::AddRef
542 * AddRef for the class factory
547 *******************************************************************************/
549 IDirectDrawClassFactoryImpl_AddRef(IClassFactory
*iface
)
551 ICOM_THIS_FROM(IClassFactoryImpl
, IClassFactory
, iface
);
552 ULONG ref
= InterlockedIncrement(&This
->ref
);
554 TRACE("(%p)->() incrementing from %ld.\n", This
, ref
- 1);
559 /*******************************************************************************
560 * IDirectDrawClassFactory::Release
562 * Release for the class factory. If the refcount falls to 0, the object
568 *******************************************************************************/
570 IDirectDrawClassFactoryImpl_Release(IClassFactory
*iface
)
572 ICOM_THIS_FROM(IClassFactoryImpl
, IClassFactory
, iface
);
573 ULONG ref
= InterlockedDecrement(&This
->ref
);
574 TRACE("(%p)->() decrementing from %ld.\n", This
, ref
+1);
577 HeapFree(GetProcessHeap(), 0, This
);
583 /*******************************************************************************
584 * IDirectDrawClassFactory::CreateInstance
586 * What is this? Seems to create DirectDraw objects...
589 * The ususal things???
594 *******************************************************************************/
595 static HRESULT WINAPI
596 IDirectDrawClassFactoryImpl_CreateInstance(IClassFactory
*iface
,
601 ICOM_THIS_FROM(IClassFactoryImpl
, IClassFactory
, iface
);
603 TRACE("(%p)->(%p,%s,%p)\n",This
,UnkOuter
,debugstr_guid(riid
),obj
);
605 return This
->pfnCreateInstance(UnkOuter
, riid
, obj
);
608 /*******************************************************************************
609 * IDirectDrawClassFactory::LockServer
617 * S_OK, because it's a stub
619 *******************************************************************************/
620 static HRESULT WINAPI
621 IDirectDrawClassFactoryImpl_LockServer(IClassFactory
*iface
,BOOL dolock
)
623 ICOM_THIS_FROM(IClassFactoryImpl
, IClassFactory
, iface
);
624 FIXME("(%p)->(%d),stub!\n",This
,dolock
);
628 /*******************************************************************************
629 * The class factory VTable
630 *******************************************************************************/
631 static const IClassFactoryVtbl IClassFactory_Vtbl
=
633 IDirectDrawClassFactoryImpl_QueryInterface
,
634 IDirectDrawClassFactoryImpl_AddRef
,
635 IDirectDrawClassFactoryImpl_Release
,
636 IDirectDrawClassFactoryImpl_CreateInstance
,
637 IDirectDrawClassFactoryImpl_LockServer
640 /*******************************************************************************
641 * DllGetClassObject [DDRAW.@]
642 * Retrieves class object from a DLL object
645 * Docs say returns STDAPI
648 * rclsid [I] CLSID for the class object
649 * riid [I] Reference to identifier of interface for class object
650 * ppv [O] Address of variable to receive interface pointer for riid
654 * Failure: CLASS_E_CLASSNOTAVAILABLE, E_OUTOFMEMORY, E_INVALIDARG,
657 HRESULT WINAPI
DllGetClassObject(REFCLSID rclsid
, REFIID riid
, LPVOID
*ppv
)
660 IClassFactoryImpl
*factory
;
662 TRACE("(%s,%s,%p)\n", debugstr_guid(rclsid
), debugstr_guid(riid
), ppv
);
664 if ( !IsEqualGUID( &IID_IClassFactory
, riid
)
665 && ! IsEqualGUID( &IID_IUnknown
, riid
) )
666 return E_NOINTERFACE
;
668 for (i
=0; i
< sizeof(object_creation
)/sizeof(object_creation
[0]); i
++)
670 if (IsEqualGUID(object_creation
[i
].clsid
, rclsid
))
674 if (i
== sizeof(object_creation
)/sizeof(object_creation
[0]))
676 FIXME("%s: no class found.\n", debugstr_guid(rclsid
));
677 return CLASS_E_CLASSNOTAVAILABLE
;
680 factory
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(*factory
));
681 if (factory
== NULL
) return E_OUTOFMEMORY
;
683 ICOM_INIT_INTERFACE(factory
, IClassFactory
, IClassFactory_Vtbl
);
686 factory
->pfnCreateInstance
= object_creation
[i
].pfnCreateInstance
;
688 *ppv
= ICOM_INTERFACE(factory
, IClassFactory
);
693 /*******************************************************************************
694 * DllCanUnloadNow [DDRAW.@] Determines whether the DLL is in use.
700 HRESULT WINAPI
DllCanUnloadNow(void)
702 FIXME("(void): stub\n");
706 /*******************************************************************************
709 * Callback function for the EnumSurfaces call in DllMain.
710 * Dumps some surface info and releases the surface
713 * surf: The enumerated surface
714 * desc: it's description
715 * context: Pointer to the ddraw impl
719 *******************************************************************************/
720 static HRESULT WINAPI
721 DestroyCallback(IDirectDrawSurface7
*surf
,
722 DDSURFACEDESC2
*desc
,
725 IDirectDrawSurfaceImpl
*Impl
= ICOM_OBJECT(IDirectDrawSurfaceImpl
, IDirectDrawSurface7
, surf
);
726 IDirectDrawImpl
*ddraw
= (IDirectDrawImpl
*) context
;
729 ref
= IDirectDrawSurface7_Release(surf
); /* For the EnumSurfaces */
730 WARN("Surface %p has an reference count of %ld\n", Impl
, ref
);
732 /* Skip surfaces which are attached somewhere or which are
733 * part of a complex compound. They will get released when destroying
736 if( (Impl
->first_complex
!= Impl
) || (Impl
->first_attached
!= Impl
) )
738 /* Skip our depth stencil surface, it will be released with the render target */
739 if( Impl
== ddraw
->DepthStencilBuffer
)
742 /* Destroy the surface */
743 while(ref
) ref
= IDirectDrawSurface7_Release(surf
);
748 /***********************************************************************
751 * Reads a config key from the registry. Taken from WineD3D
753 ***********************************************************************/
754 inline static DWORD
get_config_key(HKEY defkey
, HKEY appkey
, const char* name
, char* buffer
, DWORD size
)
756 if (0 != appkey
&& !RegQueryValueExA( appkey
, name
, 0, NULL
, (LPBYTE
) buffer
, &size
)) return 0;
757 if (0 != defkey
&& !RegQueryValueExA( defkey
, name
, 0, NULL
, (LPBYTE
) buffer
, &size
)) return 0;
758 return ERROR_FILE_NOT_FOUND
;
761 /***********************************************************************
764 * Could be used to register DirectDraw drivers, if we have more than
765 * one. Also used to destroy any objects left at unload if the
766 * app didn't release them properly(Gothic 2, Diablo 2, Moto racer, ...)
768 ***********************************************************************/
770 DllMain(HINSTANCE hInstDLL
,
774 static LONG counter
= 0;
776 TRACE("(%p,%lx,%p)\n", hInstDLL
, Reason
, lpv
);
777 if (Reason
== DLL_PROCESS_ATTACH
)
779 char buffer
[MAX_PATH
+10];
780 DWORD size
= sizeof(buffer
);
785 /* @@ Wine registry key: HKCU\Software\Wine\Direct3D */
786 if ( RegOpenKeyA( HKEY_CURRENT_USER
, "Software\\Wine\\Direct3D", &hkey
) ) hkey
= 0;
788 len
= GetModuleFileNameA( 0, buffer
, MAX_PATH
);
789 if (len
&& len
< MAX_PATH
)
792 /* @@ Wine registry key: HKCU\Software\Wine\AppDefaults\app.exe\Direct3D */
793 if (!RegOpenKeyA( HKEY_CURRENT_USER
, "Software\\Wine\\AppDefaults", &tmpkey
))
795 char *p
, *appname
= buffer
;
796 if ((p
= strrchr( appname
, '/' ))) appname
= p
+ 1;
797 if ((p
= strrchr( appname
, '\\' ))) appname
= p
+ 1;
798 strcat( appname
, "\\Direct3D" );
799 TRACE("appname = [%s]\n", appname
);
800 if (RegOpenKeyA( tmpkey
, appname
, &appkey
)) appkey
= 0;
801 RegCloseKey( tmpkey
);
805 if ( 0 != hkey
|| 0 != appkey
)
807 if ( !get_config_key( hkey
, appkey
, "DirectDrawRenderer", buffer
, size
) )
809 if (!strcmp(buffer
,"gdi"))
811 TRACE("Defaulting to GDI surfaces\n");
812 DefaultSurfaceType
= SURFACE_GDI
;
814 else if (!strcmp(buffer
,"opengl"))
816 TRACE("Defaulting to opengl surfaces\n");
817 DefaultSurfaceType
= SURFACE_OPENGL
;
821 ERR("Unknown default surface type. Supported are:\n gdi, opengl");
826 DisableThreadLibraryCalls(hInstDLL
);
827 TRACE("Attach counter: %ld\n", InterlockedIncrement(&counter
));
829 else if (Reason
== DLL_PROCESS_DETACH
)
831 TRACE("Attach counter: %ld\n", InterlockedDecrement(&counter
));
837 IDirectDrawImpl
*ddraw
;
838 WARN("There are still existing DirectDraw interfaces. Wine bug or buggy application?\n");
840 for(ddraw
= ddraw_list
; ddraw
; ddraw
= ddraw
->next
)
846 WARN("DDraw %p has a refcount of %ld\n", ddraw
, ddraw
->ref7
+ ddraw
->ref4
+ ddraw
->ref2
+ ddraw
->ref1
);
848 /* Add references to each interface to avoid freeing them unexpectadely */
849 IDirectDraw_AddRef(ICOM_INTERFACE(ddraw
, IDirectDraw
));
850 IDirectDraw2_AddRef(ICOM_INTERFACE(ddraw
, IDirectDraw2
));
851 IDirectDraw4_AddRef(ICOM_INTERFACE(ddraw
, IDirectDraw4
));
852 IDirectDraw7_AddRef(ICOM_INTERFACE(ddraw
, IDirectDraw7
));
854 /* Does a D3D device exist? Destroy it
855 * TODO: Destroy all Vertex buffers, Lights, Materials
856 * and execture buffers too
860 WARN("DDraw %p has d3ddevice %p attached\n", ddraw
, ddraw
->d3ddevice
);
861 while(IDirect3DDevice7_Release(ICOM_INTERFACE(ddraw
->d3ddevice
, IDirect3DDevice7
)));
864 /* Try to release the objects
865 * Do an EnumSurfaces to find any hanging surfaces
867 memset(&desc
, 0, sizeof(desc
));
868 desc
.dwSize
= sizeof(desc
);
869 for(i
= 0; i
<= 1; i
++)
871 hr
= IDirectDraw7_EnumSurfaces(ICOM_INTERFACE(ddraw
, IDirectDraw7
),
877 ERR("(%p) EnumSurfaces failed, prepare for trouble\n", ddraw
);
880 /* Check the surface count */
881 if(ddraw
->surfaces
> 0)
882 ERR("DDraw %p still has %ld surfaces attached\n", ddraw
, ddraw
->surfaces
);
884 /* Release all hanging references to destroy the objects. This
885 * restores the screen mode too
887 while(IDirectDraw_Release(ICOM_INTERFACE(ddraw
, IDirectDraw
)));
888 while(IDirectDraw2_Release(ICOM_INTERFACE(ddraw
, IDirectDraw2
)));
889 while(IDirectDraw4_Release(ICOM_INTERFACE(ddraw
, IDirectDraw4
)));
890 while(IDirectDraw7_Release(ICOM_INTERFACE(ddraw
, IDirectDraw7
)));