1 /* DirectDraw HAL driver
3 * Copyright 2001 TransGaming Technologies Inc.
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
8 * version 2.1 of the License, or (at your option) any later version.
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this library; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
26 #include "wine/debug.h"
34 #include "ddraw_private.h"
36 WINE_DEFAULT_DEBUG_CHANNEL(ddraw
);
38 static const IDirectDraw7Vtbl HAL_DirectDraw_VTable
;
40 static DDVERSIONDATA hal_version
;
41 static DD32BITDRIVERDATA hal_driverdata
;
42 static HINSTANCE hal_instance
;
44 static const DDDEVICEIDENTIFIER2 hal_device
=
48 { { 0x00010001, 0x00010001 } },
50 /* 40c1b248-9d7d-4a29-b7d7-4cd8109f3d5d */
51 {0x40c1b248,0x9d7d,0x4a29,{0xd7,0xb7,0x4c,0xd8,0x10,0x9f,0x3d,0x5d}},
55 HRESULT
HAL_DirectDraw_Create(const GUID
* pGUID
, LPDIRECTDRAW7
* pIface
,
56 IUnknown
* pUnkOuter
, BOOL ex
);
57 HRESULT
HAL_DirectDraw_Initialize(IDirectDrawImpl
*, const GUID
*);
59 static const ddraw_driver hal_driver
=
62 100, /* we prefer the HAL */
63 HAL_DirectDraw_Create
,
64 HAL_DirectDraw_Initialize
67 static DDHAL_CALLBACKS dd_cbs
;
68 static DDRAWI_DIRECTDRAW_GBL dd_gbl
;
70 static D3DHAL_GLOBALDRIVERDATA d3d_hal_data
;
71 static D3DHAL_D3DEXTENDEDCAPS d3d_hal_extcaps
;
72 static D3DHAL_CALLBACKS d3d_hal_cbs1
;
73 static D3DHAL_CALLBACKS2 d3d_hal_cbs2
;
75 /* in real windoze, these entry points are 16-bit, but we can work in 32-bit */
76 static BOOL WINAPI
set_hal_info(LPDDHALINFO lpDDHalInfo
, BOOL reset
)
78 dd_cbs
.HALDD
= *lpDDHalInfo
->lpDDCallbacks
;
79 dd_cbs
.HALDDSurface
= *lpDDHalInfo
->lpDDSurfaceCallbacks
;
80 dd_cbs
.HALDDPalette
= *lpDDHalInfo
->lpDDPaletteCallbacks
;
81 if (lpDDHalInfo
->lpDDExeBufCallbacks
)
82 dd_cbs
.HALDDExeBuf
= *lpDDHalInfo
->lpDDExeBufCallbacks
;
84 dd_gbl
.lpDDCBtmp
= &dd_cbs
;
86 dd_gbl
.ddCaps
= lpDDHalInfo
->ddCaps
;
87 dd_gbl
.dwMonitorFrequency
= lpDDHalInfo
->dwMonitorFrequency
;
88 dd_gbl
.vmiData
= lpDDHalInfo
->vmiData
;
89 dd_gbl
.dwModeIndex
= lpDDHalInfo
->dwModeIndex
;
90 dd_gbl
.dwNumFourCC
= lpDDHalInfo
->ddCaps
.dwNumFourCCCodes
;
91 dd_gbl
.lpdwFourCC
= lpDDHalInfo
->lpdwFourCC
;
92 dd_gbl
.dwNumModes
= lpDDHalInfo
->dwNumModes
;
93 dd_gbl
.lpModeInfo
= lpDDHalInfo
->lpModeInfo
;
95 dd_gbl
.dwPDevice
= (DWORD
)lpDDHalInfo
->lpPDevice
;
96 dd_gbl
.hInstance
= lpDDHalInfo
->hInstance
;
98 if (lpDDHalInfo
->lpD3DGlobalDriverData
)
99 memcpy(&d3d_hal_data
, (LPVOID
)lpDDHalInfo
->lpD3DGlobalDriverData
, sizeof(D3DDEVICEDESC_V1
));
101 memset(&d3d_hal_data
, 0, sizeof(D3DDEVICEDESC_V1
));
102 dd_gbl
.lpD3DGlobalDriverData
= (ULONG_PTR
)&d3d_hal_data
;
104 if (lpDDHalInfo
->lpD3DHALCallbacks
)
105 memcpy(&d3d_hal_cbs1
, (LPVOID
)lpDDHalInfo
->lpD3DHALCallbacks
, sizeof(D3DHAL_CALLBACKS
));
107 memset(&d3d_hal_cbs1
, 0, sizeof(D3DHAL_CALLBACKS
));
108 dd_gbl
.lpD3DHALCallbacks
= (ULONG_PTR
)&d3d_hal_cbs1
;
110 if (lpDDHalInfo
->dwFlags
& DDHALINFO_GETDRIVERINFOSET
) {
111 DDHAL_GETDRIVERINFODATA data
;
112 data
.dwSize
= sizeof(DDHAL_GETDRIVERINFODATA
);
113 data
.dwFlags
= 0; /* ? */
114 data
.dwContext
= hal_driverdata
.dwContext
; /* ? */
116 data
.guidInfo
= GUID_D3DExtendedCaps
;
117 data
.dwExpectedSize
= sizeof(D3DHAL_D3DEXTENDEDCAPS
);
118 data
.lpvData
= &d3d_hal_extcaps
;
119 data
.dwActualSize
= 0;
121 lpDDHalInfo
->GetDriverInfo(&data
);
122 d3d_hal_extcaps
.dwSize
= data
.dwActualSize
;
123 dd_gbl
.lpD3DExtendedCaps
= (ULONG_PTR
)&d3d_hal_extcaps
;
125 data
.guidInfo
= GUID_D3DCallbacks2
;
126 data
.dwExpectedSize
= sizeof(D3DHAL_CALLBACKS2
);
127 data
.lpvData
= &d3d_hal_cbs2
;
128 data
.dwActualSize
= 0;
130 lpDDHalInfo
->GetDriverInfo(&data
);
131 d3d_hal_cbs2
.dwSize
= data
.dwActualSize
;
132 dd_gbl
.lpD3DHALCallbacks2
= (ULONG_PTR
)&d3d_hal_cbs2
;
135 if( opengl_initialized
&&
136 (d3d_hal_data
.hwCaps
.dwFlags
& D3DDD_WINE_OPENGL_DEVICE
) ) {
137 /*GL_DirectDraw_Init(&dd_gbl);*/
143 static DDHALDDRAWFNS hal_funcs
= {
144 sizeof(DDHALDDRAWFNS
),
146 NULL
, /* VidMemAlloc */
147 NULL
/* VidMemFree */
150 /* Called from DllInit, which is synchronised so there are no threading
152 static BOOL
initialize(void)
155 INT ncmd
= DCICOMMAND
;
157 HDC dc
= CreateDCA("DISPLAY", NULL
, NULL
, NULL
);
158 INT ver
= Escape(dc
, QUERYESCSUPPORT
, sizeof(ncmd
), (LPVOID
)&ncmd
, NULL
);
159 if (ver
!= DD_HAL_VERSION
) {
161 TRACE("DirectDraw HAL not available\n");
164 cmd
.dwVersion
= DD_VERSION
;
167 /* the DDNEWCALLBACKFNS is supposed to give the 16-bit driver entry points
168 * in ddraw16.dll, but since Wine doesn't have or use 16-bit display drivers,
169 * we'll just work in 32-bit, who'll notice... */
170 cmd
.dwCommand
= DDNEWCALLBACKFNS
;
171 cmd
.dwParam1
= (DWORD
)&hal_funcs
;
172 ExtEscape(dc
, DCICOMMAND
, sizeof(cmd
), (LPVOID
)&cmd
, 0, NULL
);
174 /* next, exchange version information */
175 cmd
.dwCommand
= DDVERSIONINFO
;
176 cmd
.dwParam1
= DD_RUNTIME_VERSION
; /* not sure what should *really* go here */
177 ExtEscape(dc
, DCICOMMAND
, sizeof(cmd
), (LPVOID
)&cmd
, sizeof(hal_version
), (LPVOID
)&hal_version
);
179 /* get 32-bit driver data (dll name and entry point) */
180 cmd
.dwCommand
= DDGET32BITDRIVERNAME
;
181 ExtEscape(dc
, DCICOMMAND
, sizeof(cmd
), (LPVOID
)&cmd
, sizeof(hal_driverdata
), (LPVOID
)&hal_driverdata
);
182 /* we're supposed to load the DLL in hal_driverdata.szName, then GetProcAddress
183 * the hal_driverdata.szEntryPoint, and call it with hal_driverdata.dwContext
184 * as a parameter... but since this is only more remains from the 16-bit world,
187 /* finally, initialize the driver object */
188 cmd
.dwCommand
= DDCREATEDRIVEROBJECT
;
189 ret
= ExtEscape(dc
, DCICOMMAND
, sizeof(cmd
), (LPVOID
)&cmd
, sizeof(hal_instance
), (LPVOID
)&hal_instance
);
191 /* the driver should have called our set_hal_info now */
192 if (!dd_gbl
.lpDDCBtmp
) ret
= FALSE
;
198 TRACE("%s DirectDraw HAL\n", ret
? "enabling" : "disabling");
203 static void cleanup(void)
205 DDHAL_DESTROYDRIVERDATA data
;
207 if (!dd_cbs
.HALDD
.DestroyDriver
) return;
211 data
.DestroyDriver
= dd_cbs
.HALDD
.DestroyDriver
;
212 data
.DestroyDriver(&data
);
215 static DWORD
choose_mode(DWORD dwWidth
, DWORD dwHeight
, DWORD dwBPP
,
216 DWORD dwRefreshRate
, DWORD dwFlags
)
221 if (!dd_gbl
.dwNumModes
) return 0;
223 /* let's support HALs that cannot switch depths (XVidMode),
224 * these should return dwBPP == 0 for all their resolutions */
225 #define BPP_MATCH(dd, bpp) ((!(dd)) || ((dd) == bpp))
227 /* FIXME: we should try to match the refresh rate too */
229 /* Choose the smallest mode that is large enough. */
230 for (i
=0; i
< dd_gbl
.dwNumModes
; i
++)
232 if (dd_gbl
.lpModeInfo
[i
].dwWidth
>= dwWidth
&&
233 dd_gbl
.lpModeInfo
[i
].dwHeight
>= dwHeight
&&
234 BPP_MATCH(dd_gbl
.lpModeInfo
[i
].dwBPP
, dwBPP
))
236 if (best
== -1) best
= i
;
239 if (dd_gbl
.lpModeInfo
[i
].dwWidth
< dd_gbl
.lpModeInfo
[best
].dwWidth
||
240 dd_gbl
.lpModeInfo
[i
].dwHeight
< dd_gbl
.lpModeInfo
[best
].dwHeight
)
248 TRACE("all modes too small\n");
249 /* ok, let's use the largest */
251 for (i
=0; i
< dd_gbl
.dwNumModes
; i
++)
253 if (BPP_MATCH(dd_gbl
.lpModeInfo
[i
].dwBPP
, dwBPP
))
255 if (best
== -1) best
= i
;
258 if (dd_gbl
.lpModeInfo
[i
].dwWidth
> dd_gbl
.lpModeInfo
[best
].dwWidth
||
259 dd_gbl
.lpModeInfo
[i
].dwHeight
> dd_gbl
.lpModeInfo
[best
].dwHeight
)
269 ERR("requested color depth (%ld) not available, try reconfiguring X server\n", dwBPP
);
270 return dd_gbl
.dwModeIndex
;
273 TRACE("using mode %d\n", best
);
278 static HRESULT
set_mode(IDirectDrawImpl
*This
, DWORD dwMode
)
282 if (dwMode
!= dd_gbl
.dwModeIndex
)
284 DDHAL_SETMODEDATA data
;
286 data
.dwModeIndex
= dwMode
;
288 data
.SetMode
= dd_cbs
.HALDD
.SetMode
;
290 data
.useRefreshRate
= FALSE
;
295 dd_gbl
.dwModeIndex
= dwMode
;
300 static HRESULT
set_exclusive_mode(IDirectDrawImpl
*This
, DWORD dwEnterExcl
)
302 DDHAL_SETEXCLUSIVEMODEDATA data
;
305 data
.dwEnterExcl
= dwEnterExcl
;
308 data
.SetExclusiveMode
= dd_cbs
.HALDD
.SetExclusiveMode
;
309 if (data
.SetExclusiveMode
)
310 data
.SetExclusiveMode(&data
);
314 BOOL
DDRAW_HAL_Init(HINSTANCE hInstDLL
, DWORD fdwReason
, LPVOID lpv
)
316 if (fdwReason
== DLL_PROCESS_ATTACH
)
319 DDRAW_register_driver(&hal_driver
);
321 else if (fdwReason
== DLL_PROCESS_DETACH
)
329 /* Not called from the vtable. */
330 HRESULT
HAL_DirectDraw_Construct(IDirectDrawImpl
*This
, BOOL ex
)
334 TRACE("(%p,%d)\n", This
, ex
);
336 hr
= User_DirectDraw_Construct(This
, ex
);
337 if (FAILED(hr
)) return hr
;
339 This
->local
.lpGbl
= &dd_gbl
;
341 This
->final_release
= HAL_DirectDraw_final_release
;
342 This
->set_exclusive_mode
= set_exclusive_mode
;
344 This
->create_palette
= HAL_DirectDrawPalette_Create
;
346 This
->create_primary
= HAL_DirectDraw_create_primary
;
347 This
->create_backbuffer
= HAL_DirectDraw_create_backbuffer
;
348 This
->create_texture
= HAL_DirectDraw_create_texture
;
350 ICOM_INIT_INTERFACE(This
, IDirectDraw7
, HAL_DirectDraw_VTable
);
353 This
->caps
.dwCaps
|= dd_gbl
.ddCaps
.dwCaps
;
354 This
->caps
.dwCaps2
|= dd_gbl
.ddCaps
.dwCaps2
;
355 This
->caps
.dwCKeyCaps
|= dd_gbl
.ddCaps
.dwCKeyCaps
;
356 This
->caps
.dwFXCaps
|= dd_gbl
.ddCaps
.dwFXCaps
;
357 This
->caps
.dwPalCaps
|= dd_gbl
.ddCaps
.dwPalCaps
;
358 /* FIXME: merge more caps */
359 This
->caps
.ddsCaps
.dwCaps
|= dd_gbl
.ddCaps
.ddsCaps
.dwCaps
;
360 This
->caps
.ddsCaps
.dwCaps2
|= dd_gbl
.ddsCapsMore
.dwCaps2
;
361 This
->caps
.ddsCaps
.dwCaps3
|= dd_gbl
.ddsCapsMore
.dwCaps3
;
362 This
->caps
.ddsCaps
.dwCaps4
|= dd_gbl
.ddsCapsMore
.dwCaps4
;
363 This
->caps
.ddsOldCaps
.dwCaps
= This
->caps
.ddsCaps
.dwCaps
;
368 /* This function is called from DirectDrawCreate(Ex) on the most-derived
369 * class to start construction.
370 * Not called from the vtable. */
371 HRESULT
HAL_DirectDraw_Create(const GUID
* pGUID
, LPDIRECTDRAW7
* pIface
,
372 IUnknown
* pUnkOuter
, BOOL ex
)
375 IDirectDrawImpl
* This
;
379 assert(pUnkOuter
== NULL
);
381 This
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,
382 sizeof(IDirectDrawImpl
)
383 + sizeof(HAL_DirectDrawImpl
));
384 if (This
== NULL
) return E_OUTOFMEMORY
;
386 /* Note that this relation does *not* hold true if the DD object was
387 * CoCreateInstanced then Initialized. */
388 This
->private = (HAL_DirectDrawImpl
*)(This
+1);
390 /* Initialize the DDCAPS structure */
391 This
->caps
.dwSize
= sizeof(This
->caps
);
393 hr
= HAL_DirectDraw_Construct(This
, ex
);
395 HeapFree(GetProcessHeap(), 0, This
);
397 *pIface
= ICOM_INTERFACE(This
, IDirectDraw7
);
402 /* This function is called from Uninit_DirectDraw_Initialize on the
403 * most-derived-class to start initialization.
404 * Not called from the vtable. */
405 HRESULT
HAL_DirectDraw_Initialize(IDirectDrawImpl
*This
, const GUID
* guid
)
411 This
->private = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,
412 sizeof(HAL_DirectDrawImpl
));
413 if (This
->private == NULL
) return E_OUTOFMEMORY
;
415 /* Initialize the DDCAPS structure */
416 This
->caps
.dwSize
= sizeof(This
->caps
);
418 hr
= HAL_DirectDraw_Construct(This
, TRUE
); /* XXX ex? */
421 HeapFree(GetProcessHeap(), 0, This
->private);
428 /* Called from an internal function pointer. */
429 void HAL_DirectDraw_final_release(IDirectDrawImpl
*This
)
431 if (dd_gbl
.dwFlags
& DDRAWI_MODECHANGED
) set_mode(This
, dd_gbl
.dwModeIndexOrig
);
432 User_DirectDraw_final_release(This
);
435 HRESULT
HAL_DirectDraw_create_primary(IDirectDrawImpl
* This
,
436 const DDSURFACEDESC2
* pDDSD
,
437 LPDIRECTDRAWSURFACE7
* ppSurf
,
440 if (This
->cooperative_level
& DDSCL_EXCLUSIVE
)
441 return HAL_DirectDrawSurface_Create(This
, pDDSD
, ppSurf
, pUnkOuter
);
443 return User_DirectDrawSurface_Create(This
, pDDSD
, ppSurf
, pUnkOuter
);
446 HRESULT
HAL_DirectDraw_create_backbuffer(IDirectDrawImpl
* This
,
447 const DDSURFACEDESC2
* pDDSD
,
448 LPDIRECTDRAWSURFACE7
* ppSurf
,
450 IDirectDrawSurfaceImpl
* primary
)
452 if (This
->cooperative_level
& DDSCL_EXCLUSIVE
)
453 return HAL_DirectDrawSurface_Create(This
, pDDSD
, ppSurf
, pUnkOuter
);
455 return User_DirectDrawSurface_Create(This
, pDDSD
, ppSurf
, pUnkOuter
);
458 HRESULT
HAL_DirectDraw_create_texture(IDirectDrawImpl
* This
,
459 const DDSURFACEDESC2
* pDDSD
,
460 LPDIRECTDRAWSURFACE7
* ppSurf
,
464 return HAL_DirectDrawSurface_Create(This
, pDDSD
, ppSurf
, pOuter
);
468 HAL_DirectDraw_GetDeviceIdentifier(LPDIRECTDRAW7 iface
,
469 LPDDDEVICEIDENTIFIER2 pDDDI
,
477 HAL_DirectDraw_RestoreDisplayMode(LPDIRECTDRAW7 iface
)
479 IDirectDrawImpl
*This
= (IDirectDrawImpl
*)iface
;
482 TRACE("(%p)\n", iface
);
484 if (!(dd_gbl
.dwFlags
& DDRAWI_MODECHANGED
)) return DD_OK
;
486 hr
= Main_DirectDraw_RestoreDisplayMode(iface
);
488 hr
= set_mode(This
, dd_gbl
.dwModeIndexOrig
);
489 if (SUCCEEDED(hr
)) dd_gbl
.dwFlags
&= ~DDRAWI_MODECHANGED
;
496 HAL_DirectDraw_SetDisplayMode(LPDIRECTDRAW7 iface
, DWORD dwWidth
,
497 DWORD dwHeight
, DWORD dwBPP
,
498 DWORD dwRefreshRate
, DWORD dwFlags
)
500 IDirectDrawImpl
*This
= (IDirectDrawImpl
*)iface
;
504 TRACE("(%p)->(%ldx%ldx%ld,%ld Hz,%08lx)\n",This
,dwWidth
,dwHeight
,dwBPP
,dwRefreshRate
,dwFlags
);
505 hr
= User_DirectDraw_SetDisplayMode(iface
, dwWidth
, dwHeight
, dwBPP
,
506 dwRefreshRate
, dwFlags
);
509 if (!(dd_gbl
.dwFlags
& DDRAWI_MODECHANGED
)) dd_gbl
.dwModeIndexOrig
= dd_gbl
.dwModeIndex
;
510 hr
= set_mode(This
, choose_mode(dwWidth
, dwHeight
, dwBPP
, dwRefreshRate
, dwFlags
));
511 if (SUCCEEDED(hr
)) dd_gbl
.dwFlags
|= DDRAWI_MODECHANGED
;
518 HAL_DirectDraw_GetFourCCCodes(LPDIRECTDRAW7 iface
, LPDWORD pNumCodes
,
522 IDirectDrawImpl
*This
= (IDirectDrawImpl
*)iface
;
524 *pNumCodes
=dd_gbl
.dwNumFourCC
;
525 if (pCodes
&& dd_gbl
.dwNumFourCC
)
526 memcpy(pCodes
,dd_gbl
.lpdwFourCC
,sizeof(pCodes
[0])*dd_gbl
.dwNumFourCC
);
527 FIXME("(%p,%p,%p)\n",This
,pNumCodes
,pCodes
);
528 if (dd_gbl
.dwNumFourCC
) {
529 if (pCodes
&& FIXME_ON(ddraw
)) {
530 FIXME("returning: ");
531 for (i
=0;i
<dd_gbl
.dwNumFourCC
;i
++) {
533 ((LPBYTE
)(pCodes
+i
))[0],
534 ((LPBYTE
)(pCodes
+i
))[1],
535 ((LPBYTE
)(pCodes
+i
))[2],
536 ((LPBYTE
)(pCodes
+i
))[3]
546 static const IDirectDraw7Vtbl HAL_DirectDraw_VTable
=
548 Main_DirectDraw_QueryInterface
,
549 Main_DirectDraw_AddRef
,
550 Main_DirectDraw_Release
,
551 Main_DirectDraw_Compact
,
552 Main_DirectDraw_CreateClipper
,
553 Main_DirectDraw_CreatePalette
,
554 Main_DirectDraw_CreateSurface
,
555 Main_DirectDraw_DuplicateSurface
,
556 User_DirectDraw_EnumDisplayModes
,
557 Main_DirectDraw_EnumSurfaces
,
558 Main_DirectDraw_FlipToGDISurface
,
559 Main_DirectDraw_GetCaps
,
560 Main_DirectDraw_GetDisplayMode
,
561 HAL_DirectDraw_GetFourCCCodes
,
562 Main_DirectDraw_GetGDISurface
,
563 Main_DirectDraw_GetMonitorFrequency
,
564 Main_DirectDraw_GetScanLine
,
565 Main_DirectDraw_GetVerticalBlankStatus
,
566 Main_DirectDraw_Initialize
,
567 HAL_DirectDraw_RestoreDisplayMode
,
568 Main_DirectDraw_SetCooperativeLevel
,
569 HAL_DirectDraw_SetDisplayMode
,
570 Main_DirectDraw_WaitForVerticalBlank
,
571 Main_DirectDraw_GetAvailableVidMem
,
572 Main_DirectDraw_GetSurfaceFromDC
,
573 Main_DirectDraw_RestoreAllSurfaces
,
574 Main_DirectDraw_TestCooperativeLevel
,
575 HAL_DirectDraw_GetDeviceIdentifier
,
576 Main_DirectDraw_StartModeTest
,
577 Main_DirectDraw_EvaluateMode