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"
35 #include "ddraw/main.h"
36 #include "ddraw/user.h"
37 #include "ddraw/hal.h"
38 #include "dclipper/main.h"
39 #include "dpalette/main.h"
40 #include "dpalette/hal.h"
41 #include "dsurface/main.h"
42 #include "dsurface/dib.h"
43 #include "dsurface/user.h"
44 #include "dsurface/hal.h"
46 WINE_DEFAULT_DEBUG_CHANNEL(ddraw
);
48 static IDirectDraw7Vtbl HAL_DirectDraw_VTable
;
50 static DDVERSIONDATA hal_version
;
51 static DD32BITDRIVERDATA hal_driverdata
;
52 static HINSTANCE hal_instance
;
54 static const DDDEVICEIDENTIFIER2 hal_device
=
58 { { 0x00010001, 0x00010001 } },
60 /* 40c1b248-9d7d-4a29-b7d7-4cd8109f3d5d */
61 {0x40c1b248,0x9d7d,0x4a29,{0xd7,0xb7,0x4c,0xd8,0x10,0x9f,0x3d,0x5d}},
65 HRESULT
HAL_DirectDraw_Create(const GUID
* pGUID
, LPDIRECTDRAW7
* pIface
,
66 IUnknown
* pUnkOuter
, BOOL ex
);
67 HRESULT
HAL_DirectDraw_Initialize(IDirectDrawImpl
*, const GUID
*);
69 static const ddraw_driver hal_driver
=
72 100, /* we prefer the HAL */
73 HAL_DirectDraw_Create
,
74 HAL_DirectDraw_Initialize
77 static DDHAL_CALLBACKS dd_cbs
;
78 static DDRAWI_DIRECTDRAW_GBL dd_gbl
;
80 static D3DHAL_GLOBALDRIVERDATA d3d_hal_data
;
81 static D3DHAL_D3DEXTENDEDCAPS d3d_hal_extcaps
;
82 static D3DHAL_CALLBACKS d3d_hal_cbs1
;
83 static D3DHAL_CALLBACKS2 d3d_hal_cbs2
;
85 /* in real windoze, these entry points are 16-bit, but we can work in 32-bit */
86 static BOOL WINAPI
set_hal_info(LPDDHALINFO lpDDHalInfo
, BOOL reset
)
88 dd_cbs
.HALDD
= *lpDDHalInfo
->lpDDCallbacks
;
89 dd_cbs
.HALDDSurface
= *lpDDHalInfo
->lpDDSurfaceCallbacks
;
90 dd_cbs
.HALDDPalette
= *lpDDHalInfo
->lpDDPaletteCallbacks
;
91 if (lpDDHalInfo
->lpDDExeBufCallbacks
)
92 dd_cbs
.HALDDExeBuf
= *lpDDHalInfo
->lpDDExeBufCallbacks
;
94 dd_gbl
.lpDDCBtmp
= &dd_cbs
;
96 dd_gbl
.ddCaps
= lpDDHalInfo
->ddCaps
;
97 dd_gbl
.dwMonitorFrequency
= lpDDHalInfo
->dwMonitorFrequency
;
98 dd_gbl
.vmiData
= lpDDHalInfo
->vmiData
;
99 dd_gbl
.dwModeIndex
= lpDDHalInfo
->dwModeIndex
;
100 dd_gbl
.dwNumFourCC
= lpDDHalInfo
->ddCaps
.dwNumFourCCCodes
;
101 dd_gbl
.lpdwFourCC
= lpDDHalInfo
->lpdwFourCC
;
102 dd_gbl
.dwNumModes
= lpDDHalInfo
->dwNumModes
;
103 dd_gbl
.lpModeInfo
= lpDDHalInfo
->lpModeInfo
;
105 dd_gbl
.dwPDevice
= (DWORD
)lpDDHalInfo
->lpPDevice
;
106 dd_gbl
.hInstance
= lpDDHalInfo
->hInstance
;
108 if (lpDDHalInfo
->lpD3DGlobalDriverData
)
109 memcpy(&d3d_hal_data
, (LPVOID
)lpDDHalInfo
->lpD3DGlobalDriverData
, sizeof(D3DDEVICEDESC_V1
));
111 memset(&d3d_hal_data
, 0, sizeof(D3DDEVICEDESC_V1
));
112 dd_gbl
.lpD3DGlobalDriverData
= (ULONG_PTR
)&d3d_hal_data
;
114 if (lpDDHalInfo
->lpD3DHALCallbacks
)
115 memcpy(&d3d_hal_cbs1
, (LPVOID
)lpDDHalInfo
->lpD3DHALCallbacks
, sizeof(D3DHAL_CALLBACKS
));
117 memset(&d3d_hal_cbs1
, 0, sizeof(D3DDEVICEDESC_V1
));
118 dd_gbl
.lpD3DHALCallbacks
= (ULONG_PTR
)&d3d_hal_cbs1
;
120 if (lpDDHalInfo
->dwFlags
& DDHALINFO_GETDRIVERINFOSET
) {
121 DDHAL_GETDRIVERINFODATA data
;
122 data
.dwSize
= sizeof(DDHAL_GETDRIVERINFODATA
);
123 data
.dwFlags
= 0; /* ? */
124 data
.dwContext
= hal_driverdata
.dwContext
; /* ? */
126 data
.guidInfo
= GUID_D3DExtendedCaps
;
127 data
.dwExpectedSize
= sizeof(D3DHAL_D3DEXTENDEDCAPS
);
128 data
.lpvData
= &d3d_hal_extcaps
;
129 data
.dwActualSize
= 0;
131 lpDDHalInfo
->GetDriverInfo(&data
);
132 d3d_hal_extcaps
.dwSize
= data
.dwActualSize
;
133 dd_gbl
.lpD3DExtendedCaps
= (ULONG_PTR
)&d3d_hal_extcaps
;
135 data
.guidInfo
= GUID_D3DCallbacks2
;
136 data
.dwExpectedSize
= sizeof(D3DHAL_CALLBACKS2
);
137 data
.lpvData
= &d3d_hal_cbs2
;
138 data
.dwActualSize
= 0;
140 lpDDHalInfo
->GetDriverInfo(&data
);
141 d3d_hal_cbs2
.dwSize
= data
.dwActualSize
;
142 dd_gbl
.lpD3DHALCallbacks2
= (ULONG_PTR
)&d3d_hal_cbs2
;
145 if( opengl_initialized
&&
146 (d3d_hal_data
.hwCaps
.dwFlags
& D3DDD_WINE_OPENGL_DEVICE
) ) {
147 /*GL_DirectDraw_Init(&dd_gbl);*/
153 static DDHALDDRAWFNS hal_funcs
= {
154 sizeof(DDHALDDRAWFNS
),
156 NULL
, /* VidMemAlloc */
157 NULL
/* VidMemFree */
160 /* Called from DllInit, which is synchronised so there are no threading
162 static BOOL
initialize(void)
165 INT ncmd
= DCICOMMAND
;
167 HDC dc
= CreateDCA("DISPLAY", NULL
, NULL
, NULL
);
168 INT ver
= Escape(dc
, QUERYESCSUPPORT
, sizeof(ncmd
), (LPVOID
)&ncmd
, NULL
);
169 if (ver
!= DD_HAL_VERSION
) {
171 TRACE("DirectDraw HAL not available\n");
174 cmd
.dwVersion
= DD_VERSION
;
177 /* the DDNEWCALLBACKFNS is supposed to give the 16-bit driver entry points
178 * in ddraw16.dll, but since Wine doesn't have or use 16-bit display drivers,
179 * we'll just work in 32-bit, who'll notice... */
180 cmd
.dwCommand
= DDNEWCALLBACKFNS
;
181 cmd
.dwParam1
= (DWORD
)&hal_funcs
;
182 ExtEscape(dc
, DCICOMMAND
, sizeof(cmd
), (LPVOID
)&cmd
, 0, NULL
);
184 /* next, exchange version information */
185 cmd
.dwCommand
= DDVERSIONINFO
;
186 cmd
.dwParam1
= DD_RUNTIME_VERSION
; /* not sure what should *really* go here */
187 ExtEscape(dc
, DCICOMMAND
, sizeof(cmd
), (LPVOID
)&cmd
, sizeof(hal_version
), (LPVOID
)&hal_version
);
189 /* get 32-bit driver data (dll name and entry point) */
190 cmd
.dwCommand
= DDGET32BITDRIVERNAME
;
191 ExtEscape(dc
, DCICOMMAND
, sizeof(cmd
), (LPVOID
)&cmd
, sizeof(hal_driverdata
), (LPVOID
)&hal_driverdata
);
192 /* we're supposed to load the DLL in hal_driverdata.szName, then GetProcAddress
193 * the hal_driverdata.szEntryPoint, and call it with hal_driverdata.dwContext
194 * as a parameter... but since this is only more remains from the 16-bit world,
197 /* finally, initialize the driver object */
198 cmd
.dwCommand
= DDCREATEDRIVEROBJECT
;
199 ret
= ExtEscape(dc
, DCICOMMAND
, sizeof(cmd
), (LPVOID
)&cmd
, sizeof(hal_instance
), (LPVOID
)&hal_instance
);
201 /* the driver should have called our set_hal_info now */
202 if (!dd_gbl
.lpDDCBtmp
) ret
= FALSE
;
208 TRACE("%s DirectDraw HAL\n", ret
? "enabling" : "disabling");
213 static void cleanup(void)
215 DDHAL_DESTROYDRIVERDATA data
;
218 data
.DestroyDriver
= dd_cbs
.HALDD
.DestroyDriver
;
219 data
.DestroyDriver(&data
);
222 static DWORD
choose_mode(DWORD dwWidth
, DWORD dwHeight
, DWORD dwBPP
,
223 DWORD dwRefreshRate
, DWORD dwFlags
)
228 if (!dd_gbl
.dwNumModes
) return 0;
230 /* let's support HALs that cannot switch depths (XVidMode),
231 * these should return dwBPP == 0 for all their resolutions */
232 #define BPP_MATCH(dd, bpp) ((!(dd)) || ((dd) == bpp))
234 /* FIXME: we should try to match the refresh rate too */
236 /* Choose the smallest mode that is large enough. */
237 for (i
=0; i
< dd_gbl
.dwNumModes
; i
++)
239 if (dd_gbl
.lpModeInfo
[i
].dwWidth
>= dwWidth
&&
240 dd_gbl
.lpModeInfo
[i
].dwHeight
>= dwHeight
&&
241 BPP_MATCH(dd_gbl
.lpModeInfo
[i
].dwBPP
, dwBPP
))
243 if (best
== -1) best
= i
;
246 if (dd_gbl
.lpModeInfo
[i
].dwWidth
< dd_gbl
.lpModeInfo
[best
].dwWidth
||
247 dd_gbl
.lpModeInfo
[i
].dwHeight
< dd_gbl
.lpModeInfo
[best
].dwHeight
)
255 TRACE("all modes too small\n");
256 /* ok, let's use the largest */
258 for (i
=0; i
< dd_gbl
.dwNumModes
; i
++)
260 if (BPP_MATCH(dd_gbl
.lpModeInfo
[i
].dwBPP
, dwBPP
))
262 if (best
== -1) best
= i
;
265 if (dd_gbl
.lpModeInfo
[i
].dwWidth
> dd_gbl
.lpModeInfo
[best
].dwWidth
||
266 dd_gbl
.lpModeInfo
[i
].dwHeight
> dd_gbl
.lpModeInfo
[best
].dwHeight
)
276 ERR("requested color depth (%ld) not available, try reconfiguring X server\n", dwBPP
);
277 return dd_gbl
.dwModeIndex
;
280 TRACE("using mode %d\n", best
);
285 static HRESULT
set_mode(IDirectDrawImpl
*This
, DWORD dwMode
)
289 if (dwMode
!= dd_gbl
.dwModeIndex
)
291 DDHAL_SETMODEDATA data
;
293 data
.dwModeIndex
= dwMode
;
295 data
.SetMode
= dd_cbs
.HALDD
.SetMode
;
297 data
.useRefreshRate
= FALSE
;
302 dd_gbl
.dwModeIndex
= dwMode
;
307 static HRESULT
set_exclusive_mode(IDirectDrawImpl
*This
, DWORD dwEnterExcl
)
309 DDHAL_SETEXCLUSIVEMODEDATA data
;
312 data
.dwEnterExcl
= dwEnterExcl
;
315 data
.SetExclusiveMode
= dd_cbs
.HALDD
.SetExclusiveMode
;
316 if (data
.SetExclusiveMode
)
317 data
.SetExclusiveMode(&data
);
321 BOOL
DDRAW_HAL_Init(HINSTANCE hInstDLL
, DWORD fdwReason
, LPVOID lpv
)
323 if (fdwReason
== DLL_PROCESS_ATTACH
)
326 DDRAW_register_driver(&hal_driver
);
328 else if (fdwReason
== DLL_PROCESS_DETACH
)
336 /* Not called from the vtable. */
337 HRESULT
HAL_DirectDraw_Construct(IDirectDrawImpl
*This
, BOOL ex
)
341 TRACE("(%p,%d)\n", This
, ex
);
343 hr
= User_DirectDraw_Construct(This
, ex
);
344 if (FAILED(hr
)) return hr
;
346 This
->local
.lpGbl
= &dd_gbl
;
348 This
->final_release
= HAL_DirectDraw_final_release
;
349 This
->set_exclusive_mode
= set_exclusive_mode
;
351 This
->create_palette
= HAL_DirectDrawPalette_Create
;
353 This
->create_primary
= HAL_DirectDraw_create_primary
;
354 This
->create_backbuffer
= HAL_DirectDraw_create_backbuffer
;
355 This
->create_texture
= HAL_DirectDraw_create_texture
;
357 ICOM_INIT_INTERFACE(This
, IDirectDraw7
, HAL_DirectDraw_VTable
);
360 This
->caps
.dwCaps
|= dd_gbl
.ddCaps
.dwCaps
;
361 This
->caps
.dwCaps2
|= dd_gbl
.ddCaps
.dwCaps2
;
362 This
->caps
.dwCKeyCaps
|= dd_gbl
.ddCaps
.dwCKeyCaps
;
363 This
->caps
.dwFXCaps
|= dd_gbl
.ddCaps
.dwFXCaps
;
364 This
->caps
.dwPalCaps
|= dd_gbl
.ddCaps
.dwPalCaps
;
365 /* FIXME: merge more caps */
366 This
->caps
.ddsCaps
.dwCaps
|= dd_gbl
.ddCaps
.ddsCaps
.dwCaps
;
367 This
->caps
.ddsCaps
.dwCaps2
|= dd_gbl
.ddsCapsMore
.dwCaps2
;
368 This
->caps
.ddsCaps
.dwCaps3
|= dd_gbl
.ddsCapsMore
.dwCaps3
;
369 This
->caps
.ddsCaps
.dwCaps4
|= dd_gbl
.ddsCapsMore
.dwCaps4
;
370 This
->caps
.ddsOldCaps
.dwCaps
= This
->caps
.ddsCaps
.dwCaps
;
375 /* This function is called from DirectDrawCreate(Ex) on the most-derived
376 * class to start construction.
377 * Not called from the vtable. */
378 HRESULT
HAL_DirectDraw_Create(const GUID
* pGUID
, LPDIRECTDRAW7
* pIface
,
379 IUnknown
* pUnkOuter
, BOOL ex
)
382 IDirectDrawImpl
* This
;
386 assert(pUnkOuter
== NULL
);
388 This
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,
389 sizeof(IDirectDrawImpl
)
390 + sizeof(HAL_DirectDrawImpl
));
391 if (This
== NULL
) return E_OUTOFMEMORY
;
393 /* Note that this relation does *not* hold true if the DD object was
394 * CoCreateInstanced then Initialized. */
395 This
->private = (HAL_DirectDrawImpl
*)(This
+1);
397 /* Initialize the DDCAPS structure */
398 This
->caps
.dwSize
= sizeof(This
->caps
);
400 hr
= HAL_DirectDraw_Construct(This
, ex
);
402 HeapFree(GetProcessHeap(), 0, This
);
404 *pIface
= ICOM_INTERFACE(This
, IDirectDraw7
);
409 /* This function is called from Uninit_DirectDraw_Initialize on the
410 * most-derived-class to start initialization.
411 * Not called from the vtable. */
412 HRESULT
HAL_DirectDraw_Initialize(IDirectDrawImpl
*This
, const GUID
* guid
)
418 This
->private = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,
419 sizeof(HAL_DirectDrawImpl
));
420 if (This
->private == NULL
) return E_OUTOFMEMORY
;
422 /* Initialize the DDCAPS structure */
423 This
->caps
.dwSize
= sizeof(This
->caps
);
425 hr
= HAL_DirectDraw_Construct(This
, TRUE
); /* XXX ex? */
428 HeapFree(GetProcessHeap(), 0, This
->private);
435 /* Called from an internal function pointer. */
436 void HAL_DirectDraw_final_release(IDirectDrawImpl
*This
)
438 if (dd_gbl
.dwFlags
& DDRAWI_MODECHANGED
) set_mode(This
, dd_gbl
.dwModeIndexOrig
);
439 User_DirectDraw_final_release(This
);
442 HRESULT
HAL_DirectDraw_create_primary(IDirectDrawImpl
* This
,
443 const DDSURFACEDESC2
* pDDSD
,
444 LPDIRECTDRAWSURFACE7
* ppSurf
,
447 if (This
->cooperative_level
& DDSCL_EXCLUSIVE
)
448 return HAL_DirectDrawSurface_Create(This
, pDDSD
, ppSurf
, pUnkOuter
);
450 return User_DirectDrawSurface_Create(This
, pDDSD
, ppSurf
, pUnkOuter
);
453 HRESULT
HAL_DirectDraw_create_backbuffer(IDirectDrawImpl
* This
,
454 const DDSURFACEDESC2
* pDDSD
,
455 LPDIRECTDRAWSURFACE7
* ppSurf
,
457 IDirectDrawSurfaceImpl
* primary
)
459 if (This
->cooperative_level
& DDSCL_EXCLUSIVE
)
460 return HAL_DirectDrawSurface_Create(This
, pDDSD
, ppSurf
, pUnkOuter
);
462 return User_DirectDrawSurface_Create(This
, pDDSD
, ppSurf
, pUnkOuter
);
465 HRESULT
HAL_DirectDraw_create_texture(IDirectDrawImpl
* This
,
466 const DDSURFACEDESC2
* pDDSD
,
467 LPDIRECTDRAWSURFACE7
* ppSurf
,
471 return HAL_DirectDrawSurface_Create(This
, pDDSD
, ppSurf
, pOuter
);
475 HAL_DirectDraw_GetDeviceIdentifier(LPDIRECTDRAW7 iface
,
476 LPDDDEVICEIDENTIFIER2 pDDDI
,
484 HAL_DirectDraw_RestoreDisplayMode(LPDIRECTDRAW7 iface
)
486 ICOM_THIS(IDirectDrawImpl
, iface
);
489 TRACE("(%p)\n", iface
);
491 if (!(dd_gbl
.dwFlags
& DDRAWI_MODECHANGED
)) return DD_OK
;
493 hr
= Main_DirectDraw_RestoreDisplayMode(iface
);
495 hr
= set_mode(This
, dd_gbl
.dwModeIndexOrig
);
496 if (SUCCEEDED(hr
)) dd_gbl
.dwFlags
&= ~DDRAWI_MODECHANGED
;
503 HAL_DirectDraw_SetDisplayMode(LPDIRECTDRAW7 iface
, DWORD dwWidth
,
504 DWORD dwHeight
, DWORD dwBPP
,
505 DWORD dwRefreshRate
, DWORD dwFlags
)
507 ICOM_THIS(IDirectDrawImpl
, iface
);
511 TRACE("(%p)->(%ldx%ldx%ld,%ld Hz,%08lx)\n",This
,dwWidth
,dwHeight
,dwBPP
,dwRefreshRate
,dwFlags
);
512 hr
= User_DirectDraw_SetDisplayMode(iface
, dwWidth
, dwHeight
, dwBPP
,
513 dwRefreshRate
, dwFlags
);
516 if (!(dd_gbl
.dwFlags
& DDRAWI_MODECHANGED
)) dd_gbl
.dwModeIndexOrig
= dd_gbl
.dwModeIndex
;
517 hr
= set_mode(This
, choose_mode(dwWidth
, dwHeight
, dwBPP
, dwRefreshRate
, dwFlags
));
518 if (SUCCEEDED(hr
)) dd_gbl
.dwFlags
|= DDRAWI_MODECHANGED
;
525 HAL_DirectDraw_GetFourCCCodes(LPDIRECTDRAW7 iface
, LPDWORD pNumCodes
,
529 ICOM_THIS(IDirectDrawImpl
,iface
);
531 *pNumCodes
=dd_gbl
.dwNumFourCC
;
532 if (pCodes
&& dd_gbl
.dwNumFourCC
)
533 memcpy(pCodes
,dd_gbl
.lpdwFourCC
,sizeof(pCodes
[0])*dd_gbl
.dwNumFourCC
);
534 FIXME("(%p,%p,%p)\n",This
,pNumCodes
,pCodes
);
535 if (dd_gbl
.dwNumFourCC
) {
536 if (pCodes
&& FIXME_ON(ddraw
)) {
537 FIXME("returning: ");
538 for (i
=0;i
<dd_gbl
.dwNumFourCC
;i
++) {
540 ((LPBYTE
)(pCodes
+i
))[0],
541 ((LPBYTE
)(pCodes
+i
))[1],
542 ((LPBYTE
)(pCodes
+i
))[2],
543 ((LPBYTE
)(pCodes
+i
))[3]
553 static IDirectDraw7Vtbl HAL_DirectDraw_VTable
=
555 Main_DirectDraw_QueryInterface
,
556 Main_DirectDraw_AddRef
,
557 Main_DirectDraw_Release
,
558 Main_DirectDraw_Compact
,
559 Main_DirectDraw_CreateClipper
,
560 Main_DirectDraw_CreatePalette
,
561 Main_DirectDraw_CreateSurface
,
562 Main_DirectDraw_DuplicateSurface
,
563 User_DirectDraw_EnumDisplayModes
,
564 Main_DirectDraw_EnumSurfaces
,
565 Main_DirectDraw_FlipToGDISurface
,
566 Main_DirectDraw_GetCaps
,
567 Main_DirectDraw_GetDisplayMode
,
568 HAL_DirectDraw_GetFourCCCodes
,
569 Main_DirectDraw_GetGDISurface
,
570 Main_DirectDraw_GetMonitorFrequency
,
571 Main_DirectDraw_GetScanLine
,
572 Main_DirectDraw_GetVerticalBlankStatus
,
573 Main_DirectDraw_Initialize
,
574 HAL_DirectDraw_RestoreDisplayMode
,
575 Main_DirectDraw_SetCooperativeLevel
,
576 HAL_DirectDraw_SetDisplayMode
,
577 Main_DirectDraw_WaitForVerticalBlank
,
578 Main_DirectDraw_GetAvailableVidMem
,
579 Main_DirectDraw_GetSurfaceFromDC
,
580 Main_DirectDraw_RestoreAllSurfaces
,
581 Main_DirectDraw_TestCooperativeLevel
,
582 HAL_DirectDraw_GetDeviceIdentifier
,
583 Main_DirectDraw_StartModeTest
,
584 Main_DirectDraw_EvaluateMode