You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
1531 lines
41 KiB
1531 lines
41 KiB
/*==========================================================================
|
|
* Copyright (C) 1997 Microsoft Corporation. All Rights Reserved.
|
|
*
|
|
* File: ddkernel.c
|
|
* Content: APIs for getting the kernel mode handles for
|
|
* DirectDraw and the surfaces
|
|
* History:
|
|
* Date By Reason
|
|
* ==== == ======
|
|
* 09-jan-97 smac created
|
|
*
|
|
***************************************************************************/
|
|
#include "ddrawpr.h"
|
|
#ifdef WINNT
|
|
#include "ddrawgdi.h"
|
|
#include "ddkmmini.h"
|
|
#include "ddkmapi.h"
|
|
#else
|
|
#include "minivdd.h"
|
|
#include "ddkmmini.h"
|
|
#include "ddkmapip.h"
|
|
#endif
|
|
#define DPF_MODNAME "DirectDrawVideoPort"
|
|
|
|
#define DISPLAY_STR "display"
|
|
|
|
extern char g_szPrimaryDisplay[]; // usually \\.\Display1 on Win98
|
|
|
|
#if WIN95
|
|
/*
|
|
* IsWindows98
|
|
*/
|
|
BOOL IsWindows98( VOID )
|
|
{
|
|
OSVERSIONINFO osVer;
|
|
|
|
osVer.dwOSVersionInfoSize = sizeof( osVer );
|
|
osVer.dwMinorVersion = 0;
|
|
GetVersionEx( &osVer );
|
|
|
|
return( ( osVer.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS ) &&
|
|
( osVer.dwMinorVersion > 0 ) );
|
|
}
|
|
|
|
|
|
/*
|
|
* SyncKernelSurface
|
|
*
|
|
* Initializes the buffer with the kernel surface info and then gives
|
|
* it to the HAL so they can make whatever modifications are neccesary
|
|
* and to fill in the dwDriverReserved fields with their internal state
|
|
* data.
|
|
*/
|
|
HRESULT SyncKernelSurface( LPDDRAWI_DDRAWSURFACE_LCL lpSurface,
|
|
LPDDKMSURFACEINFO lpddkmSurfaceInfo )
|
|
{
|
|
LPDDRAWI_DDRAWSURFACE_GBL_MORE lpSurfGblMore;
|
|
DDHAL_SYNCSURFACEDATA HALSurfaceData;
|
|
LPDDHALKERNELCB_SYNCSURFACE pfn;
|
|
LPDDPIXELFORMAT lpddpfFormat;
|
|
DWORD rc;
|
|
|
|
/*
|
|
* Determine the default data the best that we can
|
|
*/
|
|
memset( &HALSurfaceData, 0, sizeof( HALSurfaceData ) );
|
|
HALSurfaceData.dwSize = sizeof( HALSurfaceData );
|
|
HALSurfaceData.lpDD = lpSurface->lpSurfMore->lpDD_lcl;
|
|
HALSurfaceData.lpDDSurface = lpSurface;
|
|
HALSurfaceData.dwSurfaceOffset = 0;
|
|
HALSurfaceData.fpLockPtr = lpSurface->lpGbl->fpVidMem;
|
|
HALSurfaceData.lPitch = (DWORD) lpSurface->lpGbl->lPitch;
|
|
HALSurfaceData.dwOverlayOffset = 0;
|
|
if( lpSurface->ddsCaps.dwCaps & DDSCAPS_OVERLAY )
|
|
{
|
|
HALSurfaceData.dwOverlaySrcWidth =
|
|
lpSurface->rcOverlaySrc.right -
|
|
lpSurface->rcOverlaySrc.left;
|
|
HALSurfaceData.dwOverlaySrcHeight =
|
|
lpSurface->rcOverlaySrc.bottom -
|
|
lpSurface->rcOverlaySrc.top;
|
|
HALSurfaceData.dwOverlayDestWidth =
|
|
lpSurface->rcOverlayDest.right -
|
|
lpSurface->rcOverlayDest.left;
|
|
HALSurfaceData.dwOverlayDestHeight =
|
|
lpSurface->rcOverlayDest.bottom -
|
|
lpSurface->rcOverlayDest.top;
|
|
}
|
|
else
|
|
{
|
|
HALSurfaceData.dwOverlaySrcWidth = 0;
|
|
HALSurfaceData.dwOverlaySrcHeight = 0;
|
|
HALSurfaceData.dwOverlayDestWidth = 0;
|
|
HALSurfaceData.dwOverlayDestHeight = 0;
|
|
}
|
|
|
|
/*
|
|
* Now call the HAL and have it fill in the rest of the values
|
|
*/
|
|
pfn = lpSurface->lpSurfMore->lpDD_lcl->lpDDCB->HALDDKernel.SyncSurfaceData;
|
|
if( pfn != NULL )
|
|
{
|
|
DOHALCALL( SyncSurfaceData, pfn, HALSurfaceData, rc, 0 );
|
|
if( DDHAL_DRIVER_HANDLED != rc )
|
|
{
|
|
return DDERR_UNSUPPORTED;
|
|
}
|
|
else if( DD_OK != HALSurfaceData.ddRVal )
|
|
{
|
|
return (HRESULT)rc;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
return DDERR_UNSUPPORTED;
|
|
}
|
|
|
|
/*
|
|
* Now put all of the data into a structure that the VDD can understand
|
|
*/
|
|
lpddkmSurfaceInfo->ddsCaps = lpSurface->ddsCaps.dwCaps;
|
|
lpddkmSurfaceInfo->dwSurfaceOffset = HALSurfaceData.dwSurfaceOffset;
|
|
lpddkmSurfaceInfo->fpLockPtr = HALSurfaceData.fpLockPtr;
|
|
lpddkmSurfaceInfo->dwWidth = (DWORD) lpSurface->lpGbl->wWidth;
|
|
lpddkmSurfaceInfo->dwHeight = (DWORD) lpSurface->lpGbl->wHeight;
|
|
lpddkmSurfaceInfo->lPitch = HALSurfaceData.lPitch;
|
|
lpddkmSurfaceInfo->dwOverlayFlags = lpSurface->lpSurfMore->dwOverlayFlags;
|
|
lpddkmSurfaceInfo->dwOverlayOffset = HALSurfaceData.dwOverlayOffset;
|
|
lpddkmSurfaceInfo->dwOverlaySrcWidth = HALSurfaceData.dwOverlaySrcWidth;
|
|
lpddkmSurfaceInfo->dwOverlaySrcHeight = HALSurfaceData.dwOverlaySrcHeight;
|
|
lpddkmSurfaceInfo->dwOverlayDestWidth = HALSurfaceData.dwOverlayDestWidth;
|
|
lpddkmSurfaceInfo->dwOverlayDestHeight = HALSurfaceData.dwOverlayDestHeight;
|
|
lpddkmSurfaceInfo->dwDriverReserved1 = HALSurfaceData.dwDriverReserved1;
|
|
lpddkmSurfaceInfo->dwDriverReserved2 = HALSurfaceData.dwDriverReserved2;
|
|
lpddkmSurfaceInfo->dwDriverReserved3 = HALSurfaceData.dwDriverReserved3;
|
|
if( lpSurface->lpSurfMore->lpVideoPort == NULL )
|
|
{
|
|
lpddkmSurfaceInfo->dwVideoPortId = (DWORD)-1;
|
|
}
|
|
else
|
|
{
|
|
lpddkmSurfaceInfo->dwVideoPortId =
|
|
lpSurface->lpSurfMore->lpVideoPort->ddvpDesc.dwVideoPortID;
|
|
}
|
|
lpSurfGblMore = GET_LPDDRAWSURFACE_GBL_MORE( lpSurface->lpGbl );
|
|
lpddkmSurfaceInfo->dwPhysicalPageTable = lpSurfGblMore->dwPhysicalPageTable;
|
|
lpddkmSurfaceInfo->pPageTable = (DWORD)lpSurfGblMore->pPageTable;
|
|
lpddkmSurfaceInfo->cPages = lpSurfGblMore->cPages;
|
|
GET_PIXEL_FORMAT( lpSurface, lpSurface->lpGbl, lpddpfFormat );
|
|
if( lpddpfFormat != NULL )
|
|
{
|
|
lpddkmSurfaceInfo->dwFormatFlags = lpddpfFormat->dwFlags;
|
|
lpddkmSurfaceInfo->dwFormatFourCC = lpddpfFormat->dwFourCC;
|
|
lpddkmSurfaceInfo->dwFormatBitCount = lpddpfFormat->dwRGBBitCount;
|
|
lpddkmSurfaceInfo->dwRBitMask = lpddpfFormat->dwRBitMask;
|
|
lpddkmSurfaceInfo->dwGBitMask = lpddpfFormat->dwGBitMask;
|
|
lpddkmSurfaceInfo->dwBBitMask = lpddpfFormat->dwBBitMask;
|
|
}
|
|
|
|
return DD_OK;
|
|
}
|
|
|
|
|
|
/*
|
|
* SyncKernelVideoPort
|
|
*
|
|
* Initializes the buffer with the kernel video port info and then gives
|
|
* it to the HAL so they can make whatever modifications are neccesary
|
|
* and to fill in the dwDriverReserved fields with their internal state
|
|
* data.
|
|
*/
|
|
HRESULT SyncKernelVideoPort( LPDDRAWI_DDVIDEOPORT_LCL lpVideoPort,
|
|
LPDDKMVIDEOPORTINFO lpddkmVideoPortInfo )
|
|
{
|
|
LPDDHALKERNELCB_SYNCVIDEOPORT pfn;
|
|
DDHAL_SYNCVIDEOPORTDATA HALVideoPortData;
|
|
DWORD rc;
|
|
|
|
/*
|
|
* Determine the default data the best that we can
|
|
*/
|
|
memset( &HALVideoPortData, 0, sizeof( HALVideoPortData ) );
|
|
HALVideoPortData.dwSize = sizeof( HALVideoPortData );
|
|
HALVideoPortData.lpDD = lpVideoPort->lpDD;
|
|
HALVideoPortData.lpVideoPort = lpVideoPort;
|
|
HALVideoPortData.dwOriginOffset = 0;
|
|
if( lpVideoPort->ddvpInfo.dwVPFlags & DDVP_PRESCALE )
|
|
{
|
|
HALVideoPortData.dwHeight = lpVideoPort->ddvpInfo.dwPrescaleHeight;
|
|
}
|
|
else if( lpVideoPort->ddvpInfo.dwVPFlags & DDVP_CROP )
|
|
{
|
|
HALVideoPortData.dwHeight = lpVideoPort->ddvpInfo.rCrop.bottom -
|
|
lpVideoPort->ddvpInfo.rCrop.top;
|
|
}
|
|
else
|
|
{
|
|
HALVideoPortData.dwHeight = lpVideoPort->ddvpDesc.dwFieldHeight;
|
|
}
|
|
if( lpVideoPort->ddvpInfo.dwVPFlags & DDVP_INTERLEAVE )
|
|
{
|
|
HALVideoPortData.dwHeight *= 2;
|
|
}
|
|
HALVideoPortData.dwVBIHeight = lpVideoPort->ddvpInfo.dwVBIHeight;
|
|
|
|
/*
|
|
* Now call the HAL and have it fill in the rest of the values
|
|
*/
|
|
pfn = lpVideoPort->lpDD->lpDDCB->HALDDKernel.SyncVideoPortData;
|
|
if( pfn != NULL )
|
|
{
|
|
DOHALCALL( SyncVideoPortData, pfn, HALVideoPortData, rc, 0 );
|
|
if( DDHAL_DRIVER_HANDLED != rc )
|
|
{
|
|
return DDERR_UNSUPPORTED;
|
|
}
|
|
else if( DD_OK != HALVideoPortData.ddRVal )
|
|
{
|
|
return (HRESULT)rc;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
return DDERR_UNSUPPORTED;
|
|
}
|
|
|
|
/*
|
|
* Now put all of the data into a structure that the VDD can understand
|
|
*/
|
|
lpddkmVideoPortInfo->dwOriginOffset = HALVideoPortData.dwOriginOffset;
|
|
lpddkmVideoPortInfo->dwHeight = HALVideoPortData.dwHeight;
|
|
lpddkmVideoPortInfo->dwVBIHeight = HALVideoPortData.dwVBIHeight;
|
|
lpddkmVideoPortInfo->dwDriverReserved1 = HALVideoPortData.dwDriverReserved1;
|
|
lpddkmVideoPortInfo->dwDriverReserved2 = HALVideoPortData.dwDriverReserved2;
|
|
lpddkmVideoPortInfo->dwDriverReserved3 = HALVideoPortData.dwDriverReserved3;
|
|
|
|
return DD_OK;
|
|
}
|
|
|
|
|
|
/*
|
|
* UpdateKernelSurface
|
|
*/
|
|
HRESULT UpdateKernelSurface( LPDDRAWI_DDRAWSURFACE_LCL lpSurface )
|
|
{
|
|
LPDDRAWI_DDRAWSURFACE_GBL_MORE lpSurfGblMore;
|
|
HANDLE hDeviceHandle;
|
|
DWORD ddRVal;
|
|
|
|
if( !IsKernelInterfaceSupported( lpSurface->lpSurfMore->lpDD_lcl ) )
|
|
{
|
|
return DDERR_UNSUPPORTED;
|
|
}
|
|
|
|
lpSurfGblMore = GET_LPDDRAWSURFACE_GBL_MORE( lpSurface->lpGbl );
|
|
if( lpSurfGblMore->hKernelSurface == 0 )
|
|
{
|
|
return DDERR_GENERIC;
|
|
}
|
|
else
|
|
{
|
|
DDKMSURFACEUPDATE ddkmSurfaceInfo;
|
|
DWORD dwReturned;
|
|
|
|
hDeviceHandle = GETDDVXDHANDLE( lpSurface->lpSurfMore->lpDD_lcl );
|
|
if( INVALID_HANDLE_VALUE == hDeviceHandle )
|
|
{
|
|
return DDERR_UNSUPPORTED;
|
|
}
|
|
|
|
/*
|
|
* Get/sync the surface info
|
|
*/
|
|
ddRVal = SyncKernelSurface( lpSurface, &(ddkmSurfaceInfo.si) );
|
|
if( ddRVal != DD_OK )
|
|
{
|
|
DPF( 0, "Unable to sync surface data with HAL" );
|
|
return ddRVal;
|
|
}
|
|
|
|
/*
|
|
* Get the handle from the VDD
|
|
*/
|
|
ddkmSurfaceInfo.dwDirectDrawHandle =
|
|
lpSurface->lpSurfMore->lpDD_lcl->lpGbl->hKernelHandle;
|
|
ddkmSurfaceInfo.dwSurfaceHandle =
|
|
lpSurfGblMore->hKernelSurface;
|
|
ddRVal = (DWORD) DDERR_GENERIC;
|
|
DeviceIoControl( hDeviceHandle,
|
|
DD_DXAPI_UPDATE_SURFACE_INFO,
|
|
&ddkmSurfaceInfo,
|
|
sizeof( ddkmSurfaceInfo ),
|
|
&ddRVal,
|
|
sizeof( ddRVal ),
|
|
&dwReturned,
|
|
NULL);
|
|
if( ddRVal != DD_OK )
|
|
{
|
|
DPF( 0, "Unable to update the surface info" );
|
|
return DDERR_UNSUPPORTED;
|
|
}
|
|
}
|
|
|
|
return DD_OK;
|
|
}
|
|
|
|
|
|
/*
|
|
* GetKernelSurfaceState
|
|
*/
|
|
HRESULT GetKernelSurfaceState( LPDDRAWI_DDRAWSURFACE_LCL lpSurf, LPDWORD lpdwStateFlags )
|
|
{
|
|
DDGETSURFACESTATEIN ddStateInput;
|
|
DDGETSURFACESTATEOUT ddStateOutput;
|
|
LPDDRAWI_DDRAWSURFACE_GBL_MORE lpSurfGblMore;
|
|
HANDLE hDeviceHandle;
|
|
DWORD dwReturned;
|
|
|
|
*lpdwStateFlags = 0;
|
|
if( !IsKernelInterfaceSupported( lpSurf->lpSurfMore->lpDD_lcl ) )
|
|
{
|
|
return DDERR_UNSUPPORTED;
|
|
}
|
|
|
|
hDeviceHandle = GETDDVXDHANDLE( lpSurf->lpSurfMore->lpDD_lcl );
|
|
if( INVALID_HANDLE_VALUE == hDeviceHandle )
|
|
{
|
|
return DDERR_UNSUPPORTED;
|
|
}
|
|
|
|
/*
|
|
* Send the new info down to the VDD
|
|
*/
|
|
lpSurfGblMore = GET_LPDDRAWSURFACE_GBL_MORE( lpSurf->lpGbl );
|
|
ddStateInput.hDirectDraw = (HANDLE)
|
|
(lpSurf->lpSurfMore->lpDD_lcl->lpGbl->hKernelHandle);
|
|
ddStateInput.hSurface = (HANDLE)
|
|
(lpSurfGblMore->hKernelSurface);
|
|
ddStateOutput.ddRVal = (DWORD) DDERR_GENERIC;
|
|
DeviceIoControl( hDeviceHandle,
|
|
DD_DXAPI_PRIVATE_GET_SURFACE_STATE,
|
|
&ddStateInput,
|
|
sizeof( ddStateInput ),
|
|
&ddStateOutput,
|
|
sizeof( ddStateOutput ),
|
|
&dwReturned,
|
|
NULL);
|
|
if( ddStateOutput.ddRVal != DD_OK )
|
|
{
|
|
DPF( 0, "Unable to get the surface state" );
|
|
return DDERR_UNSUPPORTED;
|
|
}
|
|
*lpdwStateFlags = ddStateOutput.dwStateStatus;
|
|
|
|
return DD_OK;
|
|
}
|
|
|
|
/*
|
|
* SetKernelDOSBoxEvent
|
|
*/
|
|
HRESULT SetKernelDOSBoxEvent( LPDDRAWI_DIRECTDRAW_LCL lpDD )
|
|
{
|
|
DDSETDOSBOXEVENT ddDOSBox;
|
|
DWORD dwReturned;
|
|
DWORD ddRVal;
|
|
|
|
ddDOSBox.dwDirectDrawHandle = lpDD->lpGbl->hKernelHandle;
|
|
ddDOSBox.dwDOSBoxEvent = lpDD->lpGbl->dwDOSBoxEvent;
|
|
ddRVal = (DWORD) DDERR_GENERIC;
|
|
DeviceIoControl( (HANDLE)lpDD->hDDVxd,
|
|
DD_DXAPI_SET_DOS_BOX_EVENT,
|
|
&ddDOSBox,
|
|
sizeof( ddDOSBox ),
|
|
&ddRVal,
|
|
sizeof( ddRVal ),
|
|
&dwReturned,
|
|
NULL);
|
|
|
|
return DD_OK;
|
|
}
|
|
|
|
|
|
/*
|
|
* UpdateKernelVideoPort
|
|
*
|
|
* On NT, this same stuff is done in kernel mode as part of the
|
|
* UpdateVideo call, so it doesn't have to do it again here.
|
|
*/
|
|
HRESULT UpdateKernelVideoPort( LPDDRAWI_DDVIDEOPORT_LCL lpVideoPort, DWORD dwFlags )
|
|
{
|
|
LPDDRAWI_DDRAWSURFACE_GBL_MORE lpSurfGblMore;
|
|
LPDDRAWI_DDRAWSURFACE_LCL lpSurf;
|
|
DDKMVIDEOPORTINFO ddkmVideoPortInfo;
|
|
HANDLE hDeviceHandle;
|
|
DWORD dwReturned;
|
|
DWORD ddRVal;
|
|
DWORD dwIRQ;
|
|
DWORD i;
|
|
|
|
if( ( lpVideoPort->lpDD->lpGbl->lpDDKernelCaps == NULL ) ||
|
|
( lpVideoPort->lpDD->lpGbl->hKernelHandle == (DWORD)NULL ) )
|
|
{
|
|
return DDERR_UNSUPPORTED;
|
|
}
|
|
|
|
hDeviceHandle = GETDDVXDHANDLE( lpVideoPort->lpDD );
|
|
if( INVALID_HANDLE_VALUE == hDeviceHandle )
|
|
{
|
|
return DDERR_UNSUPPORTED;
|
|
}
|
|
|
|
/*
|
|
* Start filling in the info
|
|
*/
|
|
memset( &ddkmVideoPortInfo, 0, sizeof( DDKMVIDEOPORTINFO ) );
|
|
ddkmVideoPortInfo.dwDirectDrawHandle =
|
|
lpVideoPort->lpDD->lpGbl->hKernelHandle;
|
|
ddkmVideoPortInfo.dwVideoPortId = lpVideoPort->ddvpDesc.dwVideoPortID;
|
|
ddkmVideoPortInfo.dwVPFlags = lpVideoPort->ddvpInfo.dwVPFlags;
|
|
ddkmVideoPortInfo.dwFlags = dwFlags;
|
|
if( lpVideoPort->dwFlags & DDRAWIVPORT_ON )
|
|
{
|
|
ddkmVideoPortInfo.dwFlags |= DDKMVP_ON;
|
|
}
|
|
if( dwFlags != DDKMVP_RELEASE )
|
|
{
|
|
if( ( lpVideoPort->dwFlags & DDRAWIVPORT_SOFTWARE_AUTOFLIP ) &&
|
|
( lpVideoPort->ddvpInfo.dwVPFlags & DDVP_AUTOFLIP ) )
|
|
{
|
|
if( lpVideoPort->dwNumAutoflip > 0 )
|
|
{
|
|
ddkmVideoPortInfo.dwFlags |= DDKMVP_AUTOFLIP;
|
|
}
|
|
if( lpVideoPort->dwNumVBIAutoflip > 0 )
|
|
{
|
|
ddkmVideoPortInfo.dwFlags |= DDKMVP_AUTOFLIP_VBI;
|
|
}
|
|
}
|
|
ddkmVideoPortInfo.dwNumAutoflipping = lpVideoPort->dwNumAutoflip;
|
|
ddkmVideoPortInfo.dwNumVBIAutoflipping = lpVideoPort->dwNumVBIAutoflip;
|
|
|
|
/*
|
|
* Fill in surface handles for the regular video
|
|
*/
|
|
if( lpVideoPort->lpSurface != NULL )
|
|
{
|
|
if( lpVideoPort->dwNumAutoflip > 0 )
|
|
{
|
|
for( i = 0; i < lpVideoPort->dwNumAutoflip; i++ )
|
|
{
|
|
lpSurf = lpVideoPort->lpFlipInts[i]->lpLcl;
|
|
DDASSERT( lpSurf != NULL );
|
|
lpSurfGblMore = GET_LPDDRAWSURFACE_GBL_MORE( lpSurf->lpGbl );
|
|
ddkmVideoPortInfo.dwSurfaceHandle[i] =
|
|
lpSurfGblMore->hKernelSurface;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
lpSurf = lpVideoPort->lpSurface->lpLcl;
|
|
lpSurfGblMore = GET_LPDDRAWSURFACE_GBL_MORE( lpSurf->lpGbl );
|
|
ddkmVideoPortInfo.dwSurfaceHandle[0] =
|
|
lpSurfGblMore->hKernelSurface;
|
|
}
|
|
}
|
|
|
|
/*
|
|
* Fill in surface handles for the VBI data
|
|
*/
|
|
if( lpVideoPort->lpVBISurface != NULL )
|
|
{
|
|
if( lpVideoPort->dwNumVBIAutoflip > 0 )
|
|
{
|
|
DWORD dwCnt = 0;
|
|
|
|
for( i = lpVideoPort->dwNumAutoflip;
|
|
i < (lpVideoPort->dwNumVBIAutoflip + lpVideoPort->dwNumAutoflip);
|
|
i++ )
|
|
{
|
|
lpSurf = lpVideoPort->lpFlipInts[i]->lpLcl;
|
|
DDASSERT( lpSurf != NULL );
|
|
lpSurfGblMore = GET_LPDDRAWSURFACE_GBL_MORE( lpSurf->lpGbl );
|
|
ddkmVideoPortInfo.dwVBISurfaceHandle[dwCnt++] =
|
|
lpSurfGblMore->hKernelSurface;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
lpSurf = lpVideoPort->lpVBISurface->lpLcl;
|
|
lpSurfGblMore = GET_LPDDRAWSURFACE_GBL_MORE( lpSurf->lpGbl );
|
|
ddkmVideoPortInfo.dwVBISurfaceHandle[0] =
|
|
lpSurfGblMore->hKernelSurface;
|
|
}
|
|
}
|
|
|
|
/*
|
|
* Sync with the HAL
|
|
*/
|
|
if( dwFlags == DDKMVP_UPDATE )
|
|
{
|
|
/*
|
|
* Get/sync the surface info
|
|
*/
|
|
ddRVal = SyncKernelVideoPort( lpVideoPort, &ddkmVideoPortInfo );
|
|
if( ddRVal != DD_OK )
|
|
{
|
|
DPF( 0, "Unable to sync video port data with HAL" );
|
|
return ddRVal;
|
|
}
|
|
}
|
|
|
|
/*
|
|
* Does this support an IRQ?
|
|
*/
|
|
dwIRQ = DDIRQ_VPORT0_VSYNC;
|
|
dwIRQ <<= ( lpVideoPort->ddvpDesc.dwVideoPortID * 2 );
|
|
if( !( lpVideoPort->lpDD->lpGbl->lpDDKernelCaps->dwIRQCaps &
|
|
dwIRQ ) )
|
|
{
|
|
ddkmVideoPortInfo.dwFlags |= DDKMVP_NOIRQ;
|
|
}
|
|
if( !( lpVideoPort->lpDD->lpGbl->lpDDKernelCaps->dwCaps &
|
|
DDKERNELCAPS_SKIPFIELDS ) )
|
|
{
|
|
ddkmVideoPortInfo.dwFlags |= DDKMVP_NOSKIP;
|
|
}
|
|
}
|
|
|
|
/*
|
|
* Notify DDVXD if the even field is shifted down by one line
|
|
* due to half lines. This is really only an issue when capturing.
|
|
*/
|
|
if( lpVideoPort->ddvpDesc.VideoPortType.dwFlags & DDVPCONNECT_HALFLINE )
|
|
{
|
|
ddkmVideoPortInfo.dwFlags |= DDKMVP_HALFLINES;
|
|
}
|
|
|
|
/*
|
|
* Send the new info down to the VDD
|
|
*/
|
|
ddRVal = (DWORD) DDERR_GENERIC;
|
|
DeviceIoControl( hDeviceHandle,
|
|
DD_DXAPI_UPDATE_VP_INFO,
|
|
&ddkmVideoPortInfo,
|
|
sizeof( ddkmVideoPortInfo ),
|
|
&ddRVal,
|
|
sizeof( ddRVal ),
|
|
&dwReturned,
|
|
NULL);
|
|
if( ddRVal != DD_OK )
|
|
{
|
|
DPF( 0, "Unable to update the video port info" );
|
|
return DDERR_UNSUPPORTED;
|
|
}
|
|
|
|
return DD_OK;
|
|
}
|
|
|
|
/*
|
|
* EnableAutoflip
|
|
*/
|
|
VOID EnableAutoflip( LPDDRAWI_DDVIDEOPORT_LCL lpVideoPort, BOOL bEnable )
|
|
{
|
|
DDENABLEAUTOFLIP ddkmEnableAutoflip;
|
|
HANDLE hDeviceHandle;
|
|
DWORD dwReturned;
|
|
DWORD ddRVal;
|
|
|
|
if( lpVideoPort == NULL )
|
|
{
|
|
return;
|
|
}
|
|
|
|
#ifdef WIN95
|
|
if( !IsWindows98() )
|
|
{
|
|
return;
|
|
}
|
|
#endif
|
|
|
|
hDeviceHandle = GETDDVXDHANDLE( lpVideoPort->lpDD );
|
|
if( INVALID_HANDLE_VALUE == hDeviceHandle )
|
|
{
|
|
return;
|
|
}
|
|
|
|
/*
|
|
* Start filling in the info
|
|
*/
|
|
memset( &ddkmEnableAutoflip, 0, sizeof( DDENABLEAUTOFLIP ) );
|
|
ddkmEnableAutoflip.dwDirectDrawHandle =
|
|
lpVideoPort->lpDD->lpGbl->hKernelHandle;
|
|
ddkmEnableAutoflip.dwVideoPortId = lpVideoPort->ddvpDesc.dwVideoPortID;
|
|
ddkmEnableAutoflip.bEnableAutoflip = bEnable;
|
|
ddRVal = (DWORD) DDERR_GENERIC;
|
|
DeviceIoControl( hDeviceHandle,
|
|
DD_DXAPI_ENABLE_AUTOFLIP,
|
|
&ddkmEnableAutoflip,
|
|
sizeof( ddkmEnableAutoflip ),
|
|
&ddRVal,
|
|
sizeof( ddRVal ),
|
|
&dwReturned,
|
|
NULL);
|
|
}
|
|
|
|
|
|
/*
|
|
* MungeAutoflipCaps
|
|
*/
|
|
void MungeAutoflipCaps( LPDDRAWI_DIRECTDRAW_GBL pdrv )
|
|
{
|
|
LPDDVIDEOPORTCAPS lpVideoPortCaps;
|
|
DWORD i;
|
|
|
|
if( ( pdrv->hKernelHandle != (DWORD) NULL ) &&
|
|
( pdrv->lpDDVideoPortCaps != NULL ) &&
|
|
( pdrv->lpDDKernelCaps != NULL ) &&
|
|
( pdrv->lpDDKernelCaps->dwCaps & DDKERNELCAPS_AUTOFLIP ) )
|
|
{
|
|
/*
|
|
* Software autoflipping is supported, so set the autoflip
|
|
* capabilities to the max.
|
|
*/
|
|
for( i = 0; i < pdrv->ddCaps.dwMaxVideoPorts; i++ )
|
|
{
|
|
lpVideoPortCaps = &(pdrv->lpDDVideoPortCaps[i]);
|
|
if( ( lpVideoPortCaps != NULL ) &&
|
|
VALID_DDVIDEOPORTCAPS_PTR( lpVideoPortCaps ) )
|
|
{
|
|
lpVideoPortCaps->dwCaps |= DDVPCAPS_AUTOFLIP;
|
|
lpVideoPortCaps->dwNumAutoFlipSurfaces = MAX_AUTOFLIP;
|
|
if( lpVideoPortCaps->dwCaps & DDVPCAPS_VBISURFACE )
|
|
{
|
|
lpVideoPortCaps->dwNumVBIAutoFlipSurfaces = MAX_AUTOFLIP;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
#endif
|
|
|
|
|
|
/*
|
|
* InternalReleaseKernelHandle
|
|
*/
|
|
HRESULT InternalReleaseKernelSurfaceHandle( LPDDRAWI_DDRAWSURFACE_LCL lpSurface, BOOL bLosingSurface )
|
|
{
|
|
LPDDRAWI_DDRAWSURFACE_GBL_MORE lpSurfGblMore;
|
|
HANDLE hDeviceHandle;
|
|
DWORD dwReturned;
|
|
DWORD ddRVal;
|
|
#ifdef WIN95
|
|
DDRELEASEHANDLE ddRelease;
|
|
#endif
|
|
|
|
#ifdef WIN95
|
|
if( lpSurface->lpSurfMore->lpDD_lcl->lpGbl->hKernelHandle == (DWORD) NULL )
|
|
{
|
|
return DD_OK;
|
|
}
|
|
|
|
hDeviceHandle = GETDDVXDHANDLE( lpSurface->lpSurfMore->lpDD_lcl );
|
|
if( INVALID_HANDLE_VALUE == hDeviceHandle )
|
|
{
|
|
return DDERR_UNSUPPORTED;
|
|
}
|
|
#endif
|
|
|
|
lpSurfGblMore = GET_LPDDRAWSURFACE_GBL_MORE( lpSurface->lpGbl );
|
|
if( lpSurfGblMore->hKernelSurface == 0 )
|
|
{
|
|
return DD_OK;
|
|
}
|
|
|
|
/*
|
|
* Check the ref count to make sure it's time to release this surface
|
|
*/
|
|
if( bLosingSurface )
|
|
{
|
|
lpSurfGblMore->dwKernelRefCnt = 0;
|
|
}
|
|
else if( lpSurfGblMore->dwKernelRefCnt > 0 )
|
|
{
|
|
if( --(lpSurfGblMore->dwKernelRefCnt) > 0 )
|
|
{
|
|
return DD_OK;
|
|
}
|
|
}
|
|
|
|
#if WIN95
|
|
|
|
/*
|
|
* Tell the VDD to release the surface
|
|
*/
|
|
ddRelease.dwDirectDrawHandle =
|
|
lpSurface->lpSurfMore->lpDD_lcl->lpGbl->hKernelHandle;
|
|
ddRelease.hSurface = lpSurfGblMore->hKernelSurface;
|
|
ddRVal = (DWORD) DDERR_GENERIC;
|
|
|
|
DeviceIoControl( hDeviceHandle,
|
|
DD_DXAPI_RELEASE_SURFACE_HANDLE,
|
|
&ddRelease,
|
|
sizeof( ddRelease ),
|
|
&ddRVal,
|
|
sizeof( ddRVal ),
|
|
&dwReturned,
|
|
NULL);
|
|
if( ddRVal != DD_OK )
|
|
{
|
|
DPF_ERR( "Unable to release the surface handle in the VDD" );
|
|
return (HRESULT)ddRVal;
|
|
}
|
|
|
|
#else
|
|
{
|
|
LPDDRAWI_DIRECTDRAW_LCL pdrv_lcl = lpSurface->lpSurfMore->lpDD_lcl;
|
|
LPDDRAWI_DIRECTDRAW_GBL pdrv = pdrv_lcl->lpGbl;
|
|
|
|
// Update DDraw handle in driver GBL object before calling DdGetDxHandle.
|
|
pdrv->hDD = pdrv_lcl->hDD;
|
|
DdGetDxHandle( NULL, lpSurface, TRUE );
|
|
}
|
|
|
|
#endif
|
|
|
|
lpSurfGblMore->hKernelSurface = 0;
|
|
|
|
return DD_OK;
|
|
}
|
|
|
|
|
|
/*
|
|
* InternalCreateKernelSurfaceHandle
|
|
*/
|
|
HRESULT InternalCreateKernelSurfaceHandle( LPDDRAWI_DDRAWSURFACE_LCL lpSurface,
|
|
PULONG_PTR lpHandle )
|
|
{
|
|
LPDDRAWI_DDRAWSURFACE_GBL_MORE lpSurfGblMore;
|
|
HANDLE hDeviceHandle;
|
|
DWORD ddRVal;
|
|
|
|
*lpHandle = 0;
|
|
if( !IsKernelInterfaceSupported( lpSurface->lpSurfMore->lpDD_lcl ) )
|
|
{
|
|
return DDERR_UNSUPPORTED;
|
|
}
|
|
|
|
lpSurfGblMore = GET_LPDDRAWSURFACE_GBL_MORE( lpSurface->lpGbl );
|
|
if( lpSurfGblMore->hKernelSurface != 0 )
|
|
{
|
|
*lpHandle = lpSurfGblMore->hKernelSurface;
|
|
lpSurfGblMore->dwKernelRefCnt++;
|
|
}
|
|
else
|
|
{
|
|
#if WIN95
|
|
DDKMSURFACEINFO ddkmSurfaceInfo;
|
|
DDGETSURFACEHANDLE ddkmGetSurfaceHandle;
|
|
DWORD dwReturned;
|
|
|
|
hDeviceHandle = GETDDVXDHANDLE( lpSurface->lpSurfMore->lpDD_lcl );
|
|
if( INVALID_HANDLE_VALUE == hDeviceHandle )
|
|
{
|
|
return DDERR_UNSUPPORTED;
|
|
}
|
|
|
|
/*
|
|
* Get/sync the surface info
|
|
*/
|
|
ddRVal = SyncKernelSurface( lpSurface, &ddkmSurfaceInfo );
|
|
if( ddRVal != DD_OK )
|
|
{
|
|
DPF( 0, "Unable to sync surface data with HAL" );
|
|
return ddRVal;
|
|
}
|
|
|
|
/*
|
|
* Get the handle from DDRAW.VXD
|
|
*/
|
|
ddkmSurfaceInfo.dwDirectDrawHandle =
|
|
lpSurface->lpSurfMore->lpDD_lcl->lpGbl->hKernelHandle;
|
|
ddkmGetSurfaceHandle.ddRVal = (DWORD) DDERR_GENERIC;
|
|
ddkmGetSurfaceHandle.hSurface = 0;
|
|
DeviceIoControl( hDeviceHandle,
|
|
DD_DXAPI_GET_SURFACE_HANDLE,
|
|
&ddkmSurfaceInfo,
|
|
sizeof( ddkmSurfaceInfo ),
|
|
&ddkmGetSurfaceHandle,
|
|
sizeof( ddkmGetSurfaceHandle ),
|
|
&dwReturned,
|
|
NULL);
|
|
if( ( ddkmGetSurfaceHandle.ddRVal != DD_OK ) ||
|
|
( ddkmGetSurfaceHandle.hSurface == 0 ) )
|
|
{
|
|
DPF( 0, "Unable to get surface handle from the VDD" );
|
|
return DDERR_UNSUPPORTED;
|
|
}
|
|
*lpHandle = lpSurfGblMore->hKernelSurface =
|
|
ddkmGetSurfaceHandle.hSurface;
|
|
|
|
#else
|
|
|
|
*lpHandle = (ULONG_PTR) DdGetDxHandle( NULL, lpSurface, 0 );
|
|
if( *lpHandle == 0 )
|
|
{
|
|
return DDERR_GENERIC;
|
|
}
|
|
lpSurfGblMore->hKernelSurface = *lpHandle;
|
|
|
|
#endif
|
|
|
|
lpSurfGblMore->dwKernelRefCnt = 1;
|
|
}
|
|
|
|
return DD_OK;
|
|
}
|
|
|
|
|
|
/*
|
|
* InitKernelInterface
|
|
*/
|
|
|
|
#ifdef WINNT
|
|
#ifndef MAX_AUTOFLIP
|
|
#define MAX_AUTOFLIP 10
|
|
#endif
|
|
#endif
|
|
|
|
HRESULT InitKernelInterface( LPDDRAWI_DIRECTDRAW_LCL lpDD )
|
|
{
|
|
#ifdef WIN95
|
|
VDD_IOCTL_SET_NOTIFY_INPUT vddNotify;
|
|
DDINITDEVICEIN ddInput;
|
|
DDINITDEVICEOUT ddOutput;
|
|
DDSETKERNELCAPS ddSetCaps;
|
|
#endif
|
|
LPDDKERNELCAPS lpKernelCaps;
|
|
HANDLE hDeviceHandle;
|
|
DWORD dwReturned;
|
|
DWORD ddRVal;
|
|
DWORD dwTemp;
|
|
BYTE szDisplayName[MAX_DRIVER_NAME];
|
|
|
|
#ifdef WIN95
|
|
|
|
/*
|
|
* Don't do anything unles we're Windows98 or later
|
|
*/
|
|
if( !IsWindows98() )
|
|
{
|
|
return DDERR_UNSUPPORTED;
|
|
}
|
|
|
|
/*
|
|
* Get the name of the VDD device to open
|
|
* This is a hack to do some temporary work on Win95
|
|
*/
|
|
lstrcpy( szDisplayName, lpDD->lpGbl->cDriverName );
|
|
if( _stricmp( szDisplayName, DISPLAY_STR ) == 0 )
|
|
{
|
|
lstrcpy( szDisplayName, g_szPrimaryDisplay );
|
|
}
|
|
|
|
/*
|
|
* Open the VDD for communication
|
|
*/
|
|
lpDD->lpGbl->hKernelHandle = 0;
|
|
hDeviceHandle = CreateFile( szDisplayName,
|
|
GENERIC_WRITE,
|
|
FILE_SHARE_WRITE,
|
|
NULL,
|
|
OPEN_EXISTING,
|
|
FILE_ATTRIBUTE_NORMAL | FILE_FLAG_GLOBAL_HANDLE,
|
|
NULL);
|
|
if( INVALID_HANDLE_VALUE == hDeviceHandle )
|
|
{
|
|
DPF( 0, "Unable to open the VDD" );
|
|
return DDERR_UNSUPPORTED;
|
|
}
|
|
|
|
/*
|
|
* Get the function table from the mini VDD
|
|
*/
|
|
memset( &ddInput, 0, sizeof( ddInput ) );
|
|
DeviceIoControl( hDeviceHandle,
|
|
VDD_IOCTL_GET_DDHAL,
|
|
&dwTemp,
|
|
sizeof( DWORD ),
|
|
&(ddInput.MiniVDDTable),
|
|
sizeof( DDMINIVDDTABLE ),
|
|
&dwReturned,
|
|
NULL);
|
|
|
|
/*
|
|
* Send the new info down to DDRAW.VXD
|
|
*/
|
|
lpKernelCaps = lpDD->lpGbl->lpDDKernelCaps;
|
|
if( lpKernelCaps != NULL )
|
|
{
|
|
ddInput.dwMaxVideoPorts = lpDD->lpGbl->ddCaps.dwMaxVideoPorts;
|
|
if( lpDD->lpGbl->ddCaps.dwCaps2 & DDCAPS2_CANBOBINTERLEAVED )
|
|
{
|
|
ddInput.dwDeviceFlags |= DDKMDF_CAN_BOB_INTERLEAVED;
|
|
}
|
|
if( lpDD->lpGbl->ddCaps.dwCaps2 & DDCAPS2_CANBOBNONINTERLEAVED )
|
|
{
|
|
ddInput.dwDeviceFlags |= DDKMDF_CAN_BOB_NONINTERLEAVED;
|
|
}
|
|
if( !( lpKernelCaps->dwCaps & DDKERNELCAPS_SETSTATE ) )
|
|
{
|
|
ddInput.dwDeviceFlags |= DDKMDF_NOSTATE;
|
|
}
|
|
}
|
|
ddOutput.ddRVal = (DWORD) DDERR_GENERIC;
|
|
DeviceIoControl( (HANDLE)lpDD->hDDVxd,
|
|
DD_DXAPI_INIT_DEVICE,
|
|
&ddInput,
|
|
sizeof( ddInput ),
|
|
&ddOutput,
|
|
sizeof( ddOutput ),
|
|
&dwReturned,
|
|
NULL);
|
|
if( ddOutput.ddRVal != DD_OK )
|
|
{
|
|
DPF( 0, "Unable to initialize the kernel data" );
|
|
CloseHandle( hDeviceHandle );
|
|
return DDERR_UNSUPPORTED;
|
|
}
|
|
|
|
/*
|
|
* If unable to allocate the IRQ, disable functionality that depends
|
|
* on it.
|
|
*/
|
|
if( lpKernelCaps != NULL )
|
|
{
|
|
if( !ddOutput.bHaveIRQ )
|
|
{
|
|
DPF( 1, "Unable to allocate IRQ - disabling some kernel mode functionality" );
|
|
lpKernelCaps->dwIRQCaps = 0;
|
|
}
|
|
|
|
/*
|
|
* Disable kernel mode caps for which functions are not available
|
|
*/
|
|
if( ( ddInput.MiniVDDTable.vddGetIRQInfo == NULL ) ||
|
|
( ddInput.MiniVDDTable.vddEnableIRQ == NULL ) )
|
|
{
|
|
// Can't to any IRQ stuff w/o these functions
|
|
DPF( 1, "vddGet/EnableIRQ not supported - overriding dwIRQCaps" );
|
|
lpKernelCaps->dwIRQCaps = 0;
|
|
}
|
|
if( ddInput.MiniVDDTable.vddSetState == NULL )
|
|
{
|
|
DPF( 1, "vddSetState not supported - overriding DDKERNELCAPS_SETSTATE" );
|
|
lpKernelCaps->dwCaps &= ~DDKERNELCAPS_SETSTATE;
|
|
}
|
|
if( ddInput.MiniVDDTable.vddLock == NULL )
|
|
{
|
|
DPF( 1, "vddLock not supported - overriding DDKERNELCAPS_LOCK" );
|
|
lpKernelCaps->dwCaps &= ~DDKERNELCAPS_LOCK;
|
|
}
|
|
if( ddInput.MiniVDDTable.vddSkipNextField == NULL )
|
|
{
|
|
DPF( 1, "vddSkipNextField not supported - overriding DDKERNELCAPS_SKIPFIELDS" );
|
|
lpKernelCaps->dwCaps &= ~DDKERNELCAPS_SKIPFIELDS;
|
|
}
|
|
if( ddInput.MiniVDDTable.vddFlipOverlay == NULL )
|
|
{
|
|
DPF( 1, "vddFlipOverlay not supported - overriding DDKERNELCAPS_FLIPOVERLAY" );
|
|
lpKernelCaps->dwCaps &= ~DDKERNELCAPS_FLIPOVERLAY;
|
|
}
|
|
if( ddInput.MiniVDDTable.vddFlipVideoPort == NULL )
|
|
{
|
|
DPF( 1, "vddFlipVideoPort not supported - overriding DDKERNELCAPS_FLIPVIDEOPORT" );
|
|
lpKernelCaps->dwCaps &= ~DDKERNELCAPS_FLIPVIDEOPORT;
|
|
}
|
|
if( ddInput.MiniVDDTable.vddGetPolarity == NULL )
|
|
{
|
|
DPF( 1, "vddGetFieldPolarity not supported - overriding DDKERNELCAPS_FIELDPOLARITY" );
|
|
lpKernelCaps->dwCaps &= ~DDKERNELCAPS_FIELDPOLARITY;
|
|
}
|
|
if( ( ddInput.MiniVDDTable.vddTransfer == NULL ) ||
|
|
( ddInput.MiniVDDTable.vddGetTransferStatus == NULL ) )
|
|
{
|
|
DPF( 1, "vddTransfer/GetTransferStatus not supported - overriding DDKERNELCAPS_CAPTURE_NONLOCALVIDMEM/SYSMEM" );
|
|
lpKernelCaps->dwCaps &= ~DDKERNELCAPS_CAPTURE_NONLOCALVIDMEM;
|
|
lpKernelCaps->dwCaps &= ~DDKERNELCAPS_CAPTURE_SYSMEM;
|
|
lpKernelCaps->dwCaps &= ~DDKERNELCAPS_CAPTURE_INVERTED;
|
|
}
|
|
if( ( ddInput.MiniVDDTable.vddBobNextField == NULL ) &&
|
|
( lpDD->lpGbl->ddCaps.dwCaps2 & DDCAPS2_CANBOBINTERLEAVED ) )
|
|
{
|
|
DPF( 1, "vddBobNextField not supported - overriding DDKERNELCAPS_AUTOFLIP" );
|
|
lpKernelCaps->dwCaps &= ~DDKERNELCAPS_AUTOFLIP;
|
|
}
|
|
if( ( ddInput.MiniVDDTable.vddFlipOverlay == NULL ) ||
|
|
( ddInput.MiniVDDTable.vddFlipVideoPort == NULL ) )
|
|
{
|
|
DPF( 1, "vddFlipOverlay/VideoPort not supported - overriding DDKERNELCAPS_AUTOFLIP" );
|
|
lpKernelCaps->dwCaps &= ~DDKERNELCAPS_AUTOFLIP;
|
|
}
|
|
if( !( lpKernelCaps->dwIRQCaps & DDIRQ_VPORT0_VSYNC ) )
|
|
{
|
|
DPF( 1, "DDIRQ_VPORT0_VSYNC not set - overriding DDKERNELCAPS_AUTOFLIP" );
|
|
lpKernelCaps->dwCaps &= ~( DDKERNELCAPS_AUTOFLIP | DDKERNELCAPS_SETSTATE );
|
|
}
|
|
if( !( lpKernelCaps->dwCaps & DDKERNELCAPS_AUTOFLIP ) )
|
|
{
|
|
DPF( 1, "DDKERNELCAPS_AUTOFLIP not set - overriding DDKERNELCAPS_SKIPFIELDS" );
|
|
lpKernelCaps->dwCaps &= ~DDKERNELCAPS_SKIPFIELDS;
|
|
}
|
|
|
|
/*
|
|
* Notify DDVXD of the updated caps
|
|
*/
|
|
ddSetCaps.dwDirectDrawHandle = ddOutput.dwDirectDrawHandle;
|
|
ddSetCaps.dwCaps = lpKernelCaps->dwCaps;
|
|
ddSetCaps.dwIRQCaps = lpKernelCaps->dwIRQCaps;
|
|
ddRVal = (DWORD) DDERR_GENERIC;
|
|
DeviceIoControl( (HANDLE)lpDD->hDDVxd,
|
|
DD_DXAPI_SET_KERNEL_CAPS,
|
|
&ddSetCaps,
|
|
sizeof( ddSetCaps ),
|
|
&ddRVal,
|
|
sizeof( ddRVal ),
|
|
&dwReturned,
|
|
NULL);
|
|
if( ddRVal != DD_OK )
|
|
{
|
|
DPF( 0, "Unable to initialize the kernel data" );
|
|
CloseHandle( hDeviceHandle );
|
|
return DDERR_UNSUPPORTED;
|
|
}
|
|
}
|
|
|
|
|
|
/*
|
|
* Tell the VDD to notify us of dos box and res change events.
|
|
*/
|
|
vddNotify.NotifyMask = VDD_NOTIFY_START_MODE_CHANGE |
|
|
VDD_NOTIFY_END_MODE_CHANGE | VDD_NOTIFY_ENABLE | VDD_NOTIFY_DISABLE;
|
|
vddNotify.NotifyType = VDD_NOTIFY_TYPE_CALLBACK;
|
|
vddNotify.NotifyProc = ddOutput.pfnNotifyProc;
|
|
vddNotify.NotifyData = ddOutput.dwDirectDrawHandle;
|
|
DeviceIoControl( hDeviceHandle,
|
|
VDD_IOCTL_SET_NOTIFY,
|
|
&vddNotify,
|
|
sizeof( vddNotify ),
|
|
&dwTemp,
|
|
sizeof( dwTemp ),
|
|
&dwReturned,
|
|
NULL);
|
|
CloseHandle( hDeviceHandle );
|
|
|
|
lpDD->lpGbl->hKernelHandle = ddOutput.dwDirectDrawHandle;
|
|
lpDD->lpGbl->pfnNotifyProc = ddOutput.pfnNotifyProc;
|
|
|
|
/*
|
|
* Everything worked. If they can support software autoflipping,
|
|
* we'll update the video port caps structure accordingly.
|
|
*/
|
|
MungeAutoflipCaps( lpDD->lpGbl );
|
|
|
|
#else
|
|
|
|
/*
|
|
* Can we software autoflip? If so, we'll update the video
|
|
* port caps structure accordingly.
|
|
*/
|
|
lpKernelCaps = lpDD->lpGbl->lpDDKernelCaps;
|
|
if( ( lpKernelCaps != NULL ) &&
|
|
( lpKernelCaps->dwCaps & DDKERNELCAPS_AUTOFLIP ) &&
|
|
( lpDD->lpGbl->lpDDVideoPortCaps != NULL ) )
|
|
{
|
|
LPDDVIDEOPORTCAPS lpVideoPortCaps;
|
|
DWORD i;
|
|
|
|
for( i = 0; i < lpDD->lpGbl->ddCaps.dwMaxVideoPorts; i++ )
|
|
{
|
|
lpVideoPortCaps = &(lpDD->lpGbl->lpDDVideoPortCaps[i]);
|
|
if( ( lpVideoPortCaps != NULL ) &&
|
|
VALID_DDVIDEOPORTCAPS_PTR( lpVideoPortCaps ) )
|
|
{
|
|
lpVideoPortCaps->dwCaps |= DDVPCAPS_AUTOFLIP;
|
|
lpVideoPortCaps->dwNumAutoFlipSurfaces = MAX_AUTOFLIP;
|
|
if( lpVideoPortCaps->dwCaps & DDVPCAPS_VBISURFACE )
|
|
{
|
|
lpVideoPortCaps->dwNumVBIAutoFlipSurfaces = MAX_AUTOFLIP;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
#endif
|
|
|
|
return DD_OK;
|
|
}
|
|
|
|
|
|
/*
|
|
* ReleaseKernelInterface
|
|
*/
|
|
HRESULT ReleaseKernelInterface( LPDDRAWI_DIRECTDRAW_LCL lpDD )
|
|
{
|
|
HANDLE hDDVxd;
|
|
HANDLE hVDD;
|
|
DWORD dwTemp;
|
|
DWORD dwReturned;
|
|
BYTE szDisplayName[MAX_DRIVER_NAME];
|
|
|
|
/*
|
|
* Do nothing if no interface has been created.
|
|
*/
|
|
if( lpDD->lpGbl->hKernelHandle == 0 )
|
|
{
|
|
return DD_OK;
|
|
}
|
|
|
|
#if WIN95
|
|
|
|
/*
|
|
* Tell the VDD to stop notifying us of DOS box and res change events.
|
|
*/
|
|
if( lpDD->lpGbl->pfnNotifyProc != 0 )
|
|
{
|
|
/*
|
|
* Get the name of the VDD device to open
|
|
*/
|
|
lstrcpy( szDisplayName, lpDD->lpGbl->cDriverName );
|
|
if( _stricmp( szDisplayName, DISPLAY_STR ) == 0 )
|
|
{
|
|
lstrcpy( szDisplayName, g_szPrimaryDisplay );
|
|
}
|
|
|
|
hVDD = CreateFile( szDisplayName,
|
|
GENERIC_WRITE,
|
|
FILE_SHARE_WRITE,
|
|
NULL,
|
|
OPEN_EXISTING,
|
|
FILE_ATTRIBUTE_NORMAL | FILE_FLAG_GLOBAL_HANDLE,
|
|
NULL);
|
|
if( hVDD != INVALID_HANDLE_VALUE )
|
|
{
|
|
VDD_IOCTL_SET_NOTIFY_INPUT vddNotify;
|
|
|
|
vddNotify.NotifyMask = 0;
|
|
vddNotify.NotifyType = VDD_NOTIFY_TYPE_CALLBACK;
|
|
vddNotify.NotifyProc = lpDD->lpGbl->pfnNotifyProc;
|
|
vddNotify.NotifyData = lpDD->lpGbl->hKernelHandle;
|
|
DeviceIoControl( hVDD,
|
|
VDD_IOCTL_SET_NOTIFY,
|
|
&vddNotify,
|
|
sizeof( vddNotify ),
|
|
&dwTemp,
|
|
sizeof( dwTemp ),
|
|
&dwReturned,
|
|
NULL);
|
|
CloseHandle( hVDD );
|
|
}
|
|
}
|
|
|
|
/*
|
|
* Need to decide which VXD handle to use. If we are executing
|
|
* on a DDHELP thread use the helper's VXD handle.
|
|
*/
|
|
hDDVxd = ( ( GetCurrentProcessId() != GETCURRPID() ) ? hHelperDDVxd : (HANDLE)lpDD->hDDVxd );
|
|
dwTemp = lpDD->lpGbl->hKernelHandle;
|
|
if( ( hDDVxd != NULL ) && ( dwTemp != 0 ) )
|
|
{
|
|
DeviceIoControl( hDDVxd,
|
|
DD_DXAPI_RELEASE_DEVICE,
|
|
&dwTemp,
|
|
sizeof( DWORD ),
|
|
&dwTemp,
|
|
sizeof( DWORD ),
|
|
&dwReturned,
|
|
NULL);
|
|
}
|
|
|
|
#else
|
|
|
|
DdGetDxHandle( lpDD, NULL, TRUE );
|
|
|
|
#endif
|
|
|
|
return DD_OK;
|
|
}
|
|
|
|
|
|
/*
|
|
* Determines if software autoflipping is an option.
|
|
*/
|
|
BOOL CanSoftwareAutoflip( LPDDRAWI_DDVIDEOPORT_LCL lpVideoPort )
|
|
{
|
|
DWORD dwIRQ;
|
|
|
|
#if WIN95
|
|
|
|
/*
|
|
* Fail if the ring 0 interface is not present
|
|
*/
|
|
if( ( lpVideoPort == NULL ) ||
|
|
( !IsKernelInterfaceSupported( lpVideoPort->lpDD ) ) ||
|
|
( lpVideoPort->lpDD->lpGbl->hKernelHandle == (DWORD) 0 ) ||
|
|
( lpVideoPort->dwFlags & DDRAWIVPORT_NOKERNELHANDLES ) )
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
/*
|
|
* Check the ring 0 caps to see if autoflipping is available
|
|
*/
|
|
if( ( lpVideoPort->lpDD->lpGbl->lpDDKernelCaps == NULL ) ||
|
|
!( lpVideoPort->lpDD->lpGbl->lpDDKernelCaps->dwCaps &
|
|
DDKERNELCAPS_AUTOFLIP ) )
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
/*
|
|
* Check to make sure an IRQ is available for this video port
|
|
*/
|
|
dwIRQ = DDIRQ_VPORT0_VSYNC;
|
|
dwIRQ <<= ( lpVideoPort->ddvpDesc.dwVideoPortID * 2 );
|
|
if( !( lpVideoPort->lpDD->lpGbl->lpDDKernelCaps->dwIRQCaps & dwIRQ ) )
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
#else
|
|
|
|
/*
|
|
* Check the ring 0 caps to see if autoflipping is available
|
|
*/
|
|
if( (lpVideoPort == NULL ) ||
|
|
( lpVideoPort->lpDD->lpGbl->lpDDKernelCaps == NULL ) ||
|
|
!( lpVideoPort->lpDD->lpGbl->lpDDKernelCaps->dwCaps &
|
|
DDKERNELCAPS_AUTOFLIP ) )
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
/*
|
|
* Check to make sure an IRQ is available for this video port
|
|
*/
|
|
dwIRQ = DDIRQ_VPORT0_VSYNC;
|
|
dwIRQ <<= ( lpVideoPort->ddvpDesc.dwVideoPortID * 2 );
|
|
if( !( lpVideoPort->lpDD->lpGbl->lpDDKernelCaps->dwIRQCaps & dwIRQ ) )
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
#endif
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
/*
|
|
* DD_Kernel_GetCaps
|
|
*/
|
|
HRESULT DDAPI DD_Kernel_GetCaps(LPDIRECTDRAWKERNEL lpDDK, LPDDKERNELCAPS lpCaps )
|
|
{
|
|
LPDDRAWI_DIRECTDRAW_INT this_int;
|
|
LPDDRAWI_DIRECTDRAW_GBL this;
|
|
|
|
ENTER_DDRAW();
|
|
|
|
DPF(2,A,"ENTERAPI: DD_Kernel_GetCaps");
|
|
|
|
TRY
|
|
{
|
|
this_int = (LPDDRAWI_DIRECTDRAW_INT) lpDDK;
|
|
if( !VALID_DIRECTDRAW_PTR( this_int ) )
|
|
{
|
|
LEAVE_DDRAW();
|
|
return DDERR_INVALIDOBJECT;
|
|
}
|
|
this = this_int->lpLcl->lpGbl;
|
|
if( !VALID_DDKERNELCAPS_PTR( lpCaps ) )
|
|
{
|
|
DPF( 0, "Invalid DDKERNELCAPS ptr" );
|
|
LEAVE_DDRAW();
|
|
return DDERR_INVALIDPARAMS;
|
|
}
|
|
if( !IsKernelInterfaceSupported( this_int->lpLcl ) )
|
|
{
|
|
DPF( 0, "Device does not support kernel interface" );
|
|
LEAVE_DDRAW();
|
|
return DDERR_UNSUPPORTED;
|
|
}
|
|
}
|
|
EXCEPT( EXCEPTION_EXECUTE_HANDLER )
|
|
{
|
|
DPF_ERR( "Exception encountered validating parameters" );
|
|
LEAVE_DDRAW();
|
|
return DDERR_EXCEPTION;
|
|
}
|
|
|
|
memcpy( lpCaps, this->lpDDKernelCaps, sizeof( DDKERNELCAPS ));
|
|
lpCaps->dwSize = sizeof( DDKERNELCAPS );
|
|
|
|
LEAVE_DDRAW();
|
|
return DD_OK;
|
|
}
|
|
|
|
|
|
/*
|
|
* DD_Kernel_GetKernelHandle
|
|
*/
|
|
HRESULT DDAPI DD_Kernel_GetKernelHandle(LPDIRECTDRAWKERNEL lpDDK, PULONG_PTR lpHandle )
|
|
{
|
|
LPDDRAWI_DIRECTDRAW_INT this_int;
|
|
LPDDRAWI_DIRECTDRAW_GBL this;
|
|
|
|
ENTER_DDRAW();
|
|
|
|
DPF(2,A,"ENTERAPI: DD_Kernel_GetKernelHandle");
|
|
|
|
TRY
|
|
{
|
|
this_int = (LPDDRAWI_DIRECTDRAW_INT) lpDDK;
|
|
if( !VALID_DIRECTDRAW_PTR( this_int ) )
|
|
{
|
|
LEAVE_DDRAW();
|
|
return DDERR_INVALIDOBJECT;
|
|
}
|
|
this = this_int->lpLcl->lpGbl;
|
|
if( !VALID_DWORD_PTR( lpHandle ) )
|
|
{
|
|
DPF( 0, "Invalid handle ptr" );
|
|
LEAVE_DDRAW();
|
|
return DDERR_INVALIDPARAMS;
|
|
}
|
|
if( !IsKernelInterfaceSupported( this_int->lpLcl ) )
|
|
{
|
|
DPF( 0, "Device does not support kernel interface" );
|
|
LEAVE_DDRAW();
|
|
return DDERR_UNSUPPORTED;
|
|
}
|
|
}
|
|
EXCEPT( EXCEPTION_EXECUTE_HANDLER )
|
|
{
|
|
DPF_ERR( "Exception encountered validating parameters" );
|
|
LEAVE_DDRAW();
|
|
return DDERR_EXCEPTION;
|
|
}
|
|
|
|
#ifdef WINNT
|
|
this->hKernelHandle = (ULONG_PTR) DdGetDxHandle( this_int->lpLcl, NULL, FALSE );
|
|
if( this->hKernelHandle == 0 )
|
|
{
|
|
DPF( 0, "Kernel failed GetDxHandle" );
|
|
LEAVE_DDRAW();
|
|
return DDERR_GENERIC;
|
|
}
|
|
#endif
|
|
*lpHandle = this->hKernelHandle;
|
|
|
|
LEAVE_DDRAW();
|
|
return DD_OK;
|
|
}
|
|
|
|
|
|
/*
|
|
* DD_Kernel_ReleaseKernelHandle
|
|
*
|
|
* Does nothing - should it?
|
|
*/
|
|
HRESULT DDAPI DD_Kernel_ReleaseKernelHandle(LPDIRECTDRAWKERNEL lpDDK )
|
|
{
|
|
LPDDRAWI_DIRECTDRAW_INT this_int;
|
|
LPDDRAWI_DIRECTDRAW_GBL this;
|
|
|
|
ENTER_DDRAW();
|
|
|
|
DPF(2,A,"ENTERAPI: DD_Kernel_ReleaseKernelHandle");
|
|
|
|
TRY
|
|
{
|
|
this_int = (LPDDRAWI_DIRECTDRAW_INT) lpDDK;
|
|
if( !VALID_DIRECTDRAW_PTR( this_int ) )
|
|
{
|
|
LEAVE_DDRAW();
|
|
return DDERR_INVALIDOBJECT;
|
|
}
|
|
this = this_int->lpLcl->lpGbl;
|
|
if( !IsKernelInterfaceSupported( this_int->lpLcl ) )
|
|
{
|
|
DPF( 0, "Device does not support kernel interface" );
|
|
LEAVE_DDRAW();
|
|
return DDERR_UNSUPPORTED;
|
|
}
|
|
}
|
|
EXCEPT( EXCEPTION_EXECUTE_HANDLER )
|
|
{
|
|
DPF_ERR( "Exception encountered validating parameters" );
|
|
LEAVE_DDRAW();
|
|
return DDERR_EXCEPTION;
|
|
}
|
|
|
|
#ifdef WINNT
|
|
ReleaseKernelInterface( this_int->lpLcl );
|
|
#endif
|
|
|
|
LEAVE_DDRAW();
|
|
return DD_OK;
|
|
}
|
|
|
|
|
|
/*
|
|
* DD_SurfaceKernel_GetKernelHandle
|
|
*/
|
|
HRESULT DDAPI DD_SurfaceKernel_GetKernelHandle(LPDIRECTDRAWSURFACEKERNEL lpDDK,
|
|
PULONG_PTR lpHandle )
|
|
{
|
|
LPDDRAWI_DDRAWSURFACE_INT this_int;
|
|
DWORD ddRVal;
|
|
|
|
ENTER_DDRAW();
|
|
|
|
DPF(2,A,"ENTERAPI: DD_SurfaceKernel_GetKernelHandle");
|
|
|
|
TRY
|
|
{
|
|
this_int = (LPDDRAWI_DDRAWSURFACE_INT) lpDDK;
|
|
if( !VALID_DIRECTDRAWSURFACE_PTR( this_int ) )
|
|
{
|
|
LEAVE_DDRAW();
|
|
return DDERR_INVALIDOBJECT;
|
|
}
|
|
if( !VALID_DWORD_PTR( lpHandle ) )
|
|
{
|
|
DPF( 0, "Invalid handle ptr" );
|
|
LEAVE_DDRAW();
|
|
return DDERR_INVALIDPARAMS;
|
|
}
|
|
if( !IsKernelInterfaceSupported( this_int->lpLcl->lpSurfMore->lpDD_lcl ) )
|
|
{
|
|
DPF( 0, "Device does not support kernel interface" );
|
|
LEAVE_DDRAW();
|
|
return DDERR_UNSUPPORTED;
|
|
}
|
|
}
|
|
EXCEPT( EXCEPTION_EXECUTE_HANDLER )
|
|
{
|
|
DPF_ERR( "Exception encountered validating parameters" );
|
|
LEAVE_DDRAW();
|
|
return DDERR_EXCEPTION;
|
|
}
|
|
|
|
ddRVal = InternalCreateKernelSurfaceHandle( this_int->lpLcl, lpHandle );
|
|
|
|
LEAVE_DDRAW();
|
|
return ddRVal;
|
|
}
|
|
|
|
|
|
/*
|
|
* DD_SurfaceKernel_ReleaseKernelHandle
|
|
*/
|
|
HRESULT DDAPI DD_SurfaceKernel_ReleaseKernelHandle(LPDIRECTDRAWSURFACEKERNEL lpDDK )
|
|
{
|
|
LPDDRAWI_DDRAWSURFACE_INT this_int;
|
|
LPDDRAWI_DDRAWSURFACE_GBL this;
|
|
LPDDRAWI_DDRAWSURFACE_GBL_MORE lpSurfGblMore;
|
|
DWORD ddRVal;
|
|
|
|
ENTER_DDRAW();
|
|
|
|
DPF(2,A,"ENTERAPI: DD_SurfaceKernel_ReleaseKernelHandle");
|
|
|
|
TRY
|
|
{
|
|
this_int = (LPDDRAWI_DDRAWSURFACE_INT) lpDDK;
|
|
if( !VALID_DIRECTDRAWSURFACE_PTR( this_int ) )
|
|
{
|
|
LEAVE_DDRAW();
|
|
return DDERR_INVALIDOBJECT;
|
|
}
|
|
this = this_int->lpLcl->lpGbl;
|
|
lpSurfGblMore = GET_LPDDRAWSURFACE_GBL_MORE( this );
|
|
if( lpSurfGblMore->hKernelSurface == 0 )
|
|
{
|
|
DPF_ERR( "Kernel handle has already been released" );
|
|
LEAVE_DDRAW();
|
|
return DD_OK;
|
|
}
|
|
if( this_int->lpLcl->lpSurfMore->lpDD_lcl->lpGbl->hKernelHandle == (DWORD) 0 )
|
|
{
|
|
DPF( 0, "Device does not support kernel interface" );
|
|
LEAVE_DDRAW();
|
|
return DDERR_UNSUPPORTED;
|
|
}
|
|
}
|
|
EXCEPT( EXCEPTION_EXECUTE_HANDLER )
|
|
{
|
|
DPF_ERR( "Exception encountered validating parameters" );
|
|
LEAVE_DDRAW();
|
|
return DDERR_EXCEPTION;
|
|
}
|
|
|
|
ddRVal = InternalReleaseKernelSurfaceHandle( this_int->lpLcl, FALSE );
|
|
|
|
LEAVE_DDRAW();
|
|
return ddRVal;
|
|
}
|
|
|
|
|
|
/*
|
|
* IsKernelInterfaceSupported
|
|
*/
|
|
BOOL IsKernelInterfaceSupported( LPDDRAWI_DIRECTDRAW_LCL lpDD )
|
|
{
|
|
#ifdef WIN95
|
|
if( ( lpDD->lpGbl->hKernelHandle == (DWORD) NULL ) ||
|
|
( lpDD->lpGbl->lpDDKernelCaps == NULL ) ||
|
|
( lpDD->lpDDCB->HALDDKernel.SyncSurfaceData == NULL ) )
|
|
{
|
|
return FALSE;
|
|
}
|
|
#else
|
|
if( ( lpDD->lpGbl->lpDDKernelCaps == NULL ) ||
|
|
( lpDD->lpGbl->lpDDKernelCaps->dwCaps == 0 ) )
|
|
{
|
|
return FALSE;
|
|
}
|
|
#endif
|
|
|
|
return TRUE;
|
|
}
|