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.
3888 lines
132 KiB
3888 lines
132 KiB
/******************************Module*Header*******************************\
|
|
* Module Name: dxapi.cxx
|
|
*
|
|
* Contains the public kernel-mode APIs for DirectX.
|
|
*
|
|
* All of the stuff that has to happen at raised IRQL happens here, because
|
|
* win32k is entirely pageable.
|
|
*
|
|
* Created: 11-Apr-1997
|
|
* Author: J. Andrew Goossen [andrewgo]
|
|
*
|
|
* Copyright (c) 1997 Microsoft Corporation
|
|
*
|
|
\**************************************************************************/
|
|
|
|
#include "precomp.hxx"
|
|
|
|
#if DBG
|
|
#define RIPDX(x) { KdPrint((x)); DbgBreakPoint();}
|
|
#define ASSERTDX(x, y) if (!(x)) RIPDX(y)
|
|
#else
|
|
#define RIPDX(x)
|
|
#define ASSERTDX(x, y)
|
|
#endif
|
|
|
|
extern "C" {
|
|
|
|
VOID
|
|
APIENTRY
|
|
DxIrqCallBack(
|
|
DX_IRQDATA* pIrqData
|
|
);
|
|
|
|
NTSTATUS
|
|
DriverEntry(
|
|
PDRIVER_OBJECT DriverObject,
|
|
PUNICODE_STRING RegistryPath
|
|
);
|
|
|
|
VOID
|
|
APIENTRY
|
|
DxGetVersionNumber(
|
|
DWORD dwNotUsed,
|
|
DDGETVERSIONNUMBER* pGetVersionNumber
|
|
);
|
|
|
|
BOOL
|
|
bDxModifyPassiveEventList(
|
|
EDD_DXDIRECTDRAW* peDxDirectDraw,
|
|
BOOL bAdd,
|
|
DWORD dwEvent,
|
|
LPDD_NOTIFYCALLBACK pfnCallBack,
|
|
PVOID pContext
|
|
);
|
|
|
|
DWORD
|
|
dwDxRegisterEvent(
|
|
DDREGISTERCALLBACK* pRegisterEvent,
|
|
BOOL bRegister
|
|
);
|
|
|
|
VOID
|
|
APIENTRY
|
|
DxRegisterEvent(
|
|
DDREGISTERCALLBACK* pRegisterEvent,
|
|
DWORD* pdwRet
|
|
);
|
|
|
|
VOID
|
|
APIENTRY
|
|
DxUnregisterEvent(
|
|
DDREGISTERCALLBACK* pRegisterEvent,
|
|
DWORD* pdwRet
|
|
);
|
|
|
|
VOID
|
|
APIENTRY
|
|
DxOpenDirectDraw(
|
|
DDOPENDIRECTDRAWIN* pOpenDirectDrawIn,
|
|
DDOPENDIRECTDRAWOUT* pOpenDirectDrawOut
|
|
);
|
|
|
|
VOID
|
|
APIENTRY
|
|
DxApiInitialize(
|
|
PFNDXAPIOPENDIRECTDRAW pfnOpenDirectDraw,
|
|
PFNDXAPIOPENVIDEOPORT pfnOpenVideoPort,
|
|
PFNDXAPIOPENSURFACE pfnOpenSurface,
|
|
PFNDXAPICLOSEHANDLE pfnCloseHandle,
|
|
PFNDXAPIGETKERNELCAPS pfnGetKernelCaps,
|
|
PFNDXAPIOPENCAPTUREDEVICE pfnOpenCaptureDevice,
|
|
PFNDXAPILOCKDEVICE pfnLockDevice,
|
|
PFNDXAPIUNLOCKDEVICE pfnUnlockDevice
|
|
);
|
|
|
|
DWORD
|
|
APIENTRY
|
|
DxApi(
|
|
DWORD iFunction,
|
|
VOID* pInBuffer,
|
|
DWORD cInBuffer,
|
|
VOID* pOutBuffer,
|
|
DWORD cOutBuffer
|
|
);
|
|
|
|
VOID
|
|
APIENTRY
|
|
DxAutoflipDpc(
|
|
DWORD dwEvent,
|
|
PVOID pContext,
|
|
DWORD dwParam1,
|
|
DWORD dwParam2
|
|
);
|
|
|
|
VOID
|
|
APIENTRY
|
|
DxAutoflipUpdate(
|
|
EDD_DXVIDEOPORT* peDxVideoPort,
|
|
EDD_DXSURFACE** apeDxSurfaceVideo,
|
|
ULONG cSurfacesVideo,
|
|
EDD_DXSURFACE** apeDxSurfaceVbi,
|
|
ULONG cSurfacesVbi
|
|
);
|
|
|
|
VOID
|
|
APIENTRY
|
|
DxLoseObject(
|
|
VOID* pvObject,
|
|
LOTYPE loType
|
|
);
|
|
|
|
VOID
|
|
APIENTRY
|
|
DxEnableIRQ(
|
|
EDD_DXVIDEOPORT* peDxVideoPort,
|
|
BOOL bEnable
|
|
);
|
|
|
|
VOID
|
|
APIENTRY
|
|
DxUpdateCapture(
|
|
EDD_DXVIDEOPORT* peDxVideoPort,
|
|
EDD_DXCAPTURE* peDxCapture,
|
|
BOOL bRemove
|
|
);
|
|
|
|
DWORD
|
|
APIENTRY
|
|
DxApiGetVersion(
|
|
VOID
|
|
);
|
|
|
|
}; // end "extern "C"
|
|
|
|
|
|
// Marke whatever we can as pageable:
|
|
|
|
#if defined(ALLOC_PRAGMA)
|
|
#pragma alloc_text(PAGE,DriverEntry)
|
|
#pragma alloc_text(PAGE,DxGetVersionNumber)
|
|
#pragma alloc_text(PAGE,bDxModifyPassiveEventList)
|
|
#pragma alloc_text(PAGE,dwDxRegisterEvent)
|
|
#pragma alloc_text(PAGE,DxRegisterEvent)
|
|
#pragma alloc_text(PAGE,DxUnregisterEvent)
|
|
#pragma alloc_text(PAGE,DxOpenDirectDraw)
|
|
#pragma alloc_text(PAGE,DxApiInitialize)
|
|
#pragma alloc_text(PAGE,DxApiGetVersion)
|
|
#endif
|
|
|
|
PFNDXAPIOPENDIRECTDRAW gpfnOpenDirectDraw;
|
|
PFNDXAPILOCKDEVICE gpfnLockDevice;
|
|
PFNDXAPIUNLOCKDEVICE gpfnUnlockDevice;
|
|
|
|
/***************************************************************************\
|
|
* NTSTATUS DriverEntry
|
|
*
|
|
* This routine is never actually called, but we need it to link.
|
|
*
|
|
\***************************************************************************/
|
|
|
|
extern "C"
|
|
NTSTATUS
|
|
DriverEntry(
|
|
PDRIVER_OBJECT DriverObject,
|
|
PUNICODE_STRING RegistryPath
|
|
)
|
|
{
|
|
return(STATUS_SUCCESS);
|
|
}
|
|
|
|
/******************************Public*Routine******************************\
|
|
* DWORD DxGetVersionNumber
|
|
*
|
|
* 14-Apr-1997 -by- J. Andrew Goossen [andrewgo]
|
|
* Wrote it.
|
|
\**************************************************************************/
|
|
|
|
VOID
|
|
APIENTRY
|
|
DxGetVersionNumber(
|
|
DWORD dwNotUsed,
|
|
DDGETVERSIONNUMBER* pGetVersionNumber
|
|
)
|
|
{
|
|
ASSERTDX(KeGetCurrentIrql() == PASSIVE_LEVEL,
|
|
"DxGetVersionNumber: Call only at passive level (it's not pageable)");
|
|
|
|
pGetVersionNumber->dwMajorVersion = DXAPI_MAJORVERSION;
|
|
pGetVersionNumber->dwMinorVersion = DXAPI_MINORVERSION;
|
|
pGetVersionNumber->ddRVal = DD_OK;
|
|
}
|
|
|
|
/******************************Public*Routine******************************\
|
|
* VOID DxGetFieldNumber
|
|
*
|
|
* 14-Apr-1997 -by- J. Andrew Goossen [andrewgo]
|
|
* Wrote it.
|
|
\**************************************************************************/
|
|
|
|
VOID
|
|
APIENTRY
|
|
DxGetFieldNumber(
|
|
DDGETFIELDNUMIN* pGetFieldNumIn,
|
|
DDGETFIELDNUMOUT* pGetFieldNumOut
|
|
)
|
|
{
|
|
DXOBJ* pDxObjDirectDraw;
|
|
DXOBJ* pDxObjVideoPort;
|
|
EDD_DXDIRECTDRAW* peDxDirectDraw;
|
|
EDD_DXVIDEOPORT* peDxVideoPort;
|
|
|
|
pGetFieldNumOut->ddRVal = DDERR_INVALIDPARAMS;
|
|
if (pGetFieldNumIn == NULL)
|
|
{
|
|
return;
|
|
}
|
|
|
|
pDxObjDirectDraw = (DXOBJ*) pGetFieldNumIn->hDirectDraw;
|
|
if (pDxObjDirectDraw != NULL)
|
|
{
|
|
peDxDirectDraw = pDxObjDirectDraw->peDxDirectDraw;
|
|
|
|
pDxObjVideoPort = (DXOBJ*) pGetFieldNumIn->hVideoPort;
|
|
if (pDxObjVideoPort != NULL)
|
|
{
|
|
peDxVideoPort = pDxObjVideoPort->peDxVideoPort;
|
|
|
|
ASSERTDX(pDxObjDirectDraw->iDxType == DXT_DIRECTDRAW,
|
|
"Invalid DirectDraw object");
|
|
ASSERTDX(pDxObjVideoPort->iDxType == DXT_VIDEOPORT,
|
|
"Invalid VideoPort object");
|
|
ASSERTDX(peDxDirectDraw == peDxVideoPort->peDxDirectDraw,
|
|
"VideoPort and DirectDraw objects don't match");
|
|
|
|
if (peDxVideoPort->peDxDirectDraw->dwIRQCaps & DDIRQ_VPORT0_VSYNC )
|
|
{
|
|
pGetFieldNumOut->dwFieldNum = peDxVideoPort->dwCurrentField;
|
|
pGetFieldNumOut->ddRVal = DD_OK;
|
|
}
|
|
else
|
|
{
|
|
KdPrint(("DxGetFieldNumber: Device doesn't support an interrupt\n"));
|
|
pGetFieldNumOut->ddRVal = DDERR_UNSUPPORTED;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/******************************Public*Routine******************************\
|
|
* VOID DxSetFieldNumber
|
|
*
|
|
* 14-Apr-1997 -by- J. Andrew Goossen [andrewgo]
|
|
* Wrote it.
|
|
\**************************************************************************/
|
|
|
|
VOID
|
|
APIENTRY
|
|
DxSetFieldNumber(
|
|
DDSETFIELDNUM* pSetFieldNum,
|
|
DWORD* pdwRet
|
|
)
|
|
{
|
|
DXOBJ* pDxObjDirectDraw;
|
|
DXOBJ* pDxObjVideoPort;
|
|
EDD_DXDIRECTDRAW* peDxDirectDraw;
|
|
EDD_DXVIDEOPORT* peDxVideoPort;
|
|
|
|
*pdwRet = DDERR_INVALIDPARAMS;
|
|
if (pSetFieldNum == NULL)
|
|
{
|
|
return;
|
|
}
|
|
|
|
pDxObjDirectDraw = (DXOBJ*) pSetFieldNum->hDirectDraw;
|
|
if (pDxObjDirectDraw != NULL)
|
|
{
|
|
peDxDirectDraw = pDxObjDirectDraw->peDxDirectDraw;
|
|
|
|
pDxObjVideoPort = (DXOBJ*) pSetFieldNum->hVideoPort;
|
|
if (pDxObjVideoPort != NULL)
|
|
{
|
|
peDxVideoPort = pDxObjVideoPort->peDxVideoPort;
|
|
|
|
ASSERTDX(pDxObjDirectDraw->iDxType == DXT_DIRECTDRAW,
|
|
"Invalid DirectDraw object");
|
|
ASSERTDX(pDxObjVideoPort->iDxType == DXT_VIDEOPORT,
|
|
"Invalid VideoPort object");
|
|
ASSERTDX(peDxDirectDraw == peDxVideoPort->peDxDirectDraw,
|
|
"VideoPort and DirectDraw objects don't match");
|
|
|
|
if (peDxVideoPort->peDxDirectDraw->dwIRQCaps & DDIRQ_VPORT0_VSYNC )
|
|
{
|
|
peDxVideoPort->dwCurrentField = pSetFieldNum->dwFieldNum;
|
|
*pdwRet = DD_OK;
|
|
}
|
|
else
|
|
{
|
|
KdPrint(("DxSetFieldNumber: Device doesn't support an interrupt\n"));
|
|
*pdwRet = DDERR_UNSUPPORTED;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/******************************Public*Routine******************************\
|
|
* VOID DxSetSkipPattern
|
|
*
|
|
* 14-Apr-1997 -by- J. Andrew Goossen [andrewgo]
|
|
* Wrote it.
|
|
\**************************************************************************/
|
|
|
|
VOID
|
|
APIENTRY
|
|
DxSetSkipPattern(
|
|
DDSETSKIPFIELD* pSetSkipPattern,
|
|
DWORD* pdwRet
|
|
)
|
|
{
|
|
DXOBJ* pDxObjDirectDraw;
|
|
DXOBJ* pDxObjVideoPort;
|
|
EDD_DXDIRECTDRAW* peDxDirectDraw;
|
|
EDD_DXVIDEOPORT* peDxVideoPort;
|
|
KIRQL OldIrql;
|
|
DWORD dwStartField;
|
|
|
|
*pdwRet = DDERR_INVALIDPARAMS;
|
|
if (pSetSkipPattern == NULL)
|
|
{
|
|
return;
|
|
}
|
|
|
|
pDxObjDirectDraw = (DXOBJ*) pSetSkipPattern->hDirectDraw;
|
|
if (pDxObjDirectDraw != NULL)
|
|
{
|
|
peDxDirectDraw = pDxObjDirectDraw->peDxDirectDraw;
|
|
|
|
pDxObjVideoPort = (DXOBJ*) pSetSkipPattern->hVideoPort;
|
|
if (pDxObjVideoPort != NULL)
|
|
{
|
|
peDxVideoPort = pDxObjVideoPort->peDxVideoPort;
|
|
|
|
ASSERTDX(pDxObjDirectDraw->iDxType == DXT_DIRECTDRAW,
|
|
"Invalid DirectDraw object");
|
|
ASSERTDX(pDxObjVideoPort->iDxType == DXT_VIDEOPORT,
|
|
"Invalid VideoPort object");
|
|
ASSERTDX(peDxDirectDraw == peDxVideoPort->peDxDirectDraw,
|
|
"VideoPort and DirectDraw objects don't match");
|
|
|
|
// Acquire the spinlock while we muck around
|
|
|
|
KeAcquireSpinLock(&peDxDirectDraw->SpinLock, &OldIrql);
|
|
|
|
// We assume that we are called during the VSYNC callback notification
|
|
// so all that we do is store the value and do the actual skipping
|
|
// during the AutoflipDpc call.
|
|
|
|
dwStartField = pSetSkipPattern->dwStartField;
|
|
if( peDxVideoPort->flFlags & DD_DXVIDEOPORT_FLAG_SKIP_SET )
|
|
{
|
|
if( peDxVideoPort->dwFieldToSkip > dwStartField )
|
|
{
|
|
peDxVideoPort->dwNextFieldToSkip = peDxVideoPort->dwFieldToSkip;
|
|
peDxVideoPort->dwFieldToSkip = dwStartField;
|
|
peDxVideoPort->flFlags |= DD_DXVIDEOPORT_FLAG_NEXT_SKIP_SET;
|
|
}
|
|
else if ( dwStartField != peDxVideoPort->dwFieldToSkip )
|
|
{
|
|
peDxVideoPort->dwFieldToSkip = dwStartField;
|
|
peDxVideoPort->flFlags |= DD_DXVIDEOPORT_FLAG_NEXT_SKIP_SET;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
peDxVideoPort->dwFieldToSkip = dwStartField;
|
|
peDxVideoPort->flFlags |= DD_DXVIDEOPORT_FLAG_SKIP_SET;
|
|
}
|
|
|
|
KeReleaseSpinLock(&peDxDirectDraw->SpinLock, OldIrql);
|
|
|
|
*pdwRet = DX_OK;
|
|
}
|
|
}
|
|
}
|
|
|
|
/******************************Public*Routine******************************\
|
|
* VOID EffectStateChange
|
|
*
|
|
* 09-Jan-1998 -by- Scott MacDonald [smac]
|
|
* Wrote it.
|
|
\**************************************************************************/
|
|
|
|
VOID EffectStateChange( EDD_DXVIDEOPORT* peDxVideoPort,
|
|
EDD_DXSURFACE* peDxSurface, DWORD dwNewState )
|
|
{
|
|
EDD_DXDIRECTDRAW* peDxDirectDraw;
|
|
DDSETSTATEININFO ddStateInInfo;
|
|
DDSETSTATEOUTINFO ddStateOutInfo;
|
|
DWORD dwOldFlags;
|
|
DWORD dwOldVPFlags;
|
|
DWORD ddRVal;
|
|
DWORD i;
|
|
DWORD dwRet;
|
|
|
|
dwOldVPFlags = 0;
|
|
if( peDxVideoPort != NULL )
|
|
{
|
|
peDxVideoPort->dwSetStateState = 0;
|
|
peDxSurface = peDxVideoPort->apeDxSurfaceVideo[0];
|
|
dwOldVPFlags = peDxVideoPort->dwVPFlags;
|
|
if( dwNewState & DDSTATE_SKIPEVENFIELDS )
|
|
{
|
|
peDxVideoPort->dwVPFlags |= DDVP_SKIPEVENFIELDS;
|
|
}
|
|
else
|
|
{
|
|
peDxVideoPort->dwVPFlags &= ~DDVP_SKIPEVENFIELDS;
|
|
}
|
|
}
|
|
|
|
if( peDxSurface != NULL )
|
|
{
|
|
dwOldFlags = peDxSurface->dwOverlayFlags;
|
|
if( dwNewState & DDSTATE_BOB )
|
|
{
|
|
peDxSurface->dwOverlayFlags |= DDOVER_BOB;
|
|
}
|
|
else if( dwNewState & ( DDSTATE_WEAVE | DDSTATE_SKIPEVENFIELDS ) )
|
|
{
|
|
peDxSurface->dwOverlayFlags &= ~DDOVER_BOB;
|
|
}
|
|
|
|
peDxDirectDraw = peDxSurface->peDxDirectDraw;
|
|
|
|
ddStateInInfo.lpSurfaceData = peDxSurface;
|
|
ddStateInInfo.lpVideoPortData = peDxVideoPort;
|
|
ddStateOutInfo.bSoftwareAutoflip = 0;
|
|
|
|
dwRet = DDERR_UNSUPPORTED;
|
|
if (peDxDirectDraw->DxApiInterface.DxSetState != NULL)
|
|
{
|
|
dwRet = peDxDirectDraw->DxApiInterface.DxSetState(
|
|
peDxDirectDraw->HwDeviceExtension,
|
|
&ddStateInInfo,
|
|
&ddStateOutInfo);
|
|
}
|
|
if( dwRet != DD_OK )
|
|
{
|
|
peDxSurface->dwOverlayFlags = dwOldFlags;
|
|
if( peDxVideoPort != NULL )
|
|
{
|
|
peDxVideoPort->dwVPFlags = dwOldVPFlags;
|
|
}
|
|
}
|
|
peDxSurface->flFlags |= DD_DXSURFACE_FLAG_STATE_SET;
|
|
if( peDxVideoPort != NULL )
|
|
{
|
|
if( peDxSurface->dwOverlayFlags & DDOVER_BOB )
|
|
{
|
|
peDxVideoPort->flFlags |= DD_DXVIDEOPORT_FLAG_BOB;
|
|
}
|
|
else
|
|
{
|
|
peDxVideoPort->flFlags &= ~DD_DXVIDEOPORT_FLAG_BOB;
|
|
}
|
|
|
|
// Do they want to switch from hardware autoflipping to
|
|
// software autoflipping?
|
|
|
|
if( ( ddStateOutInfo.bSoftwareAutoflip ) &&
|
|
( peDxVideoPort->dwVPFlags & DDVP_AUTOFLIP ) &&
|
|
!( peDxVideoPort->flFlags & (DD_DXVIDEOPORT_FLAG_AUTOFLIP|DD_DXVIDEOPORT_FLAG_AUTOFLIP_VBI)))
|
|
{
|
|
if( peDxVideoPort->cAutoflipVideo > 0 )
|
|
{
|
|
peDxVideoPort->flFlags |= DD_DXVIDEOPORT_FLAG_AUTOFLIP;
|
|
}
|
|
if( peDxVideoPort->cAutoflipVbi > 0 )
|
|
{
|
|
peDxVideoPort->flFlags |= DD_DXVIDEOPORT_FLAG_AUTOFLIP_VBI;
|
|
}
|
|
if( ddStateOutInfo.dwSurfaceIndex >= peDxVideoPort->cAutoflipVideo )
|
|
{
|
|
peDxVideoPort->iCurrentVideo = 0;
|
|
}
|
|
else
|
|
{
|
|
peDxVideoPort->iCurrentVideo = ddStateOutInfo.dwSurfaceIndex;
|
|
}
|
|
if( ddStateOutInfo.dwVBISurfaceIndex >= peDxVideoPort->cAutoflipVbi )
|
|
{
|
|
peDxVideoPort->iCurrentVbi = 0;
|
|
}
|
|
else
|
|
{
|
|
peDxVideoPort->iCurrentVbi = ddStateOutInfo.dwVBISurfaceIndex;
|
|
}
|
|
}
|
|
|
|
for( i = 0; i < peDxVideoPort->iCurrentVideo; i++ )
|
|
{
|
|
peDxSurface = peDxVideoPort->apeDxSurfaceVideo[i];
|
|
peDxSurface->flFlags &= ~(DD_DXSURFACE_FLAG_STATE_BOB|DD_DXSURFACE_FLAG_STATE_WEAVE);
|
|
if( dwNewState & DDSTATE_BOB )
|
|
{
|
|
peDxSurface->dwOverlayFlags |= DDOVER_BOB;
|
|
peDxSurface->flFlags |= DD_DXSURFACE_FLAG_STATE_BOB;
|
|
}
|
|
else if( dwNewState & ( DDSTATE_WEAVE | DDSTATE_SKIPEVENFIELDS ) )
|
|
{
|
|
peDxSurface->dwOverlayFlags &= ~DDOVER_BOB;
|
|
if( dwNewState == DDSTATE_WEAVE )
|
|
{
|
|
peDxSurface->flFlags |= DD_DXSURFACE_FLAG_STATE_WEAVE;
|
|
}
|
|
}
|
|
peDxSurface->flFlags |= DD_DXSURFACE_FLAG_STATE_SET;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/******************************Public*Routine******************************\
|
|
* VOID DxGetSurfaceState
|
|
*
|
|
* 14-Apr-1997 -by- J. Andrew Goossen [andrewgo]
|
|
* Wrote it.
|
|
\**************************************************************************/
|
|
|
|
VOID
|
|
APIENTRY
|
|
DxGetSurfaceState(
|
|
DDGETSURFACESTATEIN* pGetSurfaceStateIn,
|
|
DDGETSURFACESTATEOUT* pGetSurfaceStateOut
|
|
)
|
|
{
|
|
DXOBJ* pDxObjDirectDraw;
|
|
DXOBJ* pDxObjSurface;
|
|
EDD_DXDIRECTDRAW* peDxDirectDraw;
|
|
EDD_DXVIDEOPORT* peDxVideoPort;
|
|
EDD_DXSURFACE* peDxSurface;
|
|
|
|
pGetSurfaceStateOut->ddRVal = DDERR_INVALIDPARAMS;
|
|
if (pGetSurfaceStateIn == NULL)
|
|
{
|
|
return;
|
|
}
|
|
|
|
pDxObjDirectDraw = (DXOBJ*) pGetSurfaceStateIn->hDirectDraw;
|
|
pDxObjSurface = (DXOBJ*) pGetSurfaceStateIn->hSurface;
|
|
|
|
if ((pDxObjDirectDraw != NULL) &&
|
|
(pDxObjSurface != NULL))
|
|
{
|
|
peDxDirectDraw = pDxObjDirectDraw->peDxDirectDraw;
|
|
peDxSurface = pDxObjSurface->peDxSurface;
|
|
|
|
ASSERTDX(pDxObjDirectDraw->iDxType == DXT_DIRECTDRAW,
|
|
"Invalid DirectDraw object");
|
|
ASSERTDX(pDxObjSurface->iDxType == DXT_SURFACE,
|
|
"Invalid Surface object");
|
|
ASSERTDX(peDxDirectDraw == peDxSurface->peDxDirectDraw,
|
|
"Surface and DirectDraw objects don't match");
|
|
ASSERTDX(peDxSurface->ddsCaps & DDSCAPS_OVERLAY,
|
|
"Surface is not an overlay surface");
|
|
|
|
// Fill in the available caps
|
|
|
|
pGetSurfaceStateOut->dwStateCaps = 0;
|
|
pGetSurfaceStateOut->dwStateStatus = 0;
|
|
peDxVideoPort = peDxSurface->peDxVideoPort;
|
|
|
|
// If the DDOVER_OVERRIDEBOBWEAVE flag was set, the status is equal
|
|
// to the caps.
|
|
|
|
if( peDxSurface->dwOverlayFlags & DDOVER_OVERRIDEBOBWEAVE )
|
|
{
|
|
if( peDxSurface->dwOverlayFlags & DDOVER_BOB )
|
|
{
|
|
pGetSurfaceStateOut->dwStateStatus |= DDSTATE_BOB;
|
|
pGetSurfaceStateOut->dwStateCaps |= DDSTATE_BOB;
|
|
}
|
|
else if( ( peDxVideoPort != NULL ) &&
|
|
( peDxVideoPort->dwVPFlags & (DDVP_SKIPEVENFIELDS|DDVP_SKIPODDFIELDS) ) )
|
|
{
|
|
pGetSurfaceStateOut->dwStateStatus |= DDSTATE_SKIPEVENFIELDS;
|
|
pGetSurfaceStateOut->dwStateCaps |= DDSTATE_SKIPEVENFIELDS;
|
|
}
|
|
else if( ( peDxVideoPort != NULL ) &&
|
|
( peDxVideoPort->dwVPFlags & DDVP_INTERLEAVE ) )
|
|
{
|
|
pGetSurfaceStateOut->dwStateStatus |= DDSTATE_WEAVE;
|
|
pGetSurfaceStateOut->dwStateCaps |= DDSTATE_WEAVE;
|
|
}
|
|
else if( ( peDxVideoPort == NULL ) &&
|
|
( peDxSurface->dwOverlayFlags & DDOVER_INTERLEAVED ) )
|
|
{
|
|
pGetSurfaceStateOut->dwStateStatus |= DDSTATE_WEAVE;
|
|
pGetSurfaceStateOut->dwStateCaps |= DDSTATE_WEAVE;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// The status is different from the caps
|
|
|
|
if( ( peDxVideoPort != NULL ) &&
|
|
( peDxVideoPort->dwVPFlags & (DDVP_SKIPEVENFIELDS|DDVP_SKIPODDFIELDS) ) )
|
|
{
|
|
pGetSurfaceStateOut->dwStateStatus |= DDSTATE_SKIPEVENFIELDS;
|
|
}
|
|
else if( peDxSurface->dwOverlayFlags & DDOVER_BOB )
|
|
{
|
|
pGetSurfaceStateOut->dwStateStatus |= DDSTATE_BOB;
|
|
}
|
|
|
|
if( ( ( peDxVideoPort != NULL ) &&
|
|
( peDxVideoPort->dwVPFlags & DDVP_INTERLEAVE ) ) ||
|
|
( ( peDxVideoPort == NULL ) &&
|
|
( peDxSurface->dwOverlayFlags & DDOVER_INTERLEAVED ) ) )
|
|
{
|
|
pGetSurfaceStateOut->dwStateCaps |= DDSTATE_WEAVE;
|
|
if( peDxSurface->flFlags & DD_DXSURFACE_FLAG_CAN_BOB_INTERLEAVED )
|
|
{
|
|
pGetSurfaceStateOut->dwStateCaps |= DDSTATE_BOB;
|
|
}
|
|
if( pGetSurfaceStateOut->dwStateStatus == 0 )
|
|
{
|
|
pGetSurfaceStateOut->dwStateStatus |= DDSTATE_WEAVE;
|
|
}
|
|
}
|
|
else if( peDxSurface->flFlags & DD_DXSURFACE_FLAG_CAN_BOB_NONINTERLEAVED )
|
|
{
|
|
pGetSurfaceStateOut->dwStateCaps |= DDSTATE_BOB;
|
|
}
|
|
if( peDxVideoPort != NULL )
|
|
{
|
|
pGetSurfaceStateOut->dwStateCaps |= DDSTATE_SKIPEVENFIELDS;
|
|
}
|
|
}
|
|
|
|
// Notify the client that the state was explicity set by a
|
|
// kernel mode client.
|
|
|
|
if( peDxSurface->flFlags & DD_DXSURFACE_FLAG_STATE_SET )
|
|
{
|
|
pGetSurfaceStateOut->dwStateStatus |= DDSTATE_EXPLICITLY_SET;
|
|
}
|
|
|
|
// Tell if software autoflipping vs. hardware autofliping. This
|
|
// is mostly for DDraw's benefit.
|
|
|
|
if( ( peDxVideoPort != NULL ) && ( peDxVideoPort->bSoftwareAutoflip ) )
|
|
{
|
|
pGetSurfaceStateOut->dwStateStatus |= DDSTATE_SOFTWARE_AUTOFLIP;
|
|
}
|
|
|
|
pGetSurfaceStateOut->ddRVal = DD_OK;
|
|
}
|
|
}
|
|
|
|
/******************************Public*Routine******************************\
|
|
* VOID DxSetSurfaceState
|
|
*
|
|
* 14-Apr-1997 -by- J. Andrew Goossen [andrewgo]
|
|
* Wrote it.
|
|
\**************************************************************************/
|
|
|
|
VOID
|
|
APIENTRY
|
|
DxSetSurfaceState(
|
|
DDSETSURFACESTATE* pSetSurfaceState,
|
|
DWORD* pdwRet
|
|
)
|
|
{
|
|
DWORD dwState;
|
|
DXOBJ* pDxObjDirectDraw;
|
|
DXOBJ* pDxObjSurface;
|
|
EDD_DXDIRECTDRAW* peDxDirectDraw;
|
|
EDD_DXVIDEOPORT* peDxVideoPort;
|
|
EDD_DXSURFACE* peDxSurface;
|
|
DDGETSURFACESTATEIN GetSurfaceStateIn;
|
|
DDGETSURFACESTATEOUT GetSurfaceStateOut;
|
|
DDSETSTATEININFO SetStateInInfo;
|
|
DDSETSTATEOUTINFO SetStateOutInfo;
|
|
DWORD iCurrentVideo;
|
|
KIRQL OldIrql;
|
|
DWORD dwRet;
|
|
DWORD dwVPFlags;
|
|
|
|
*pdwRet = dwRet = DDERR_INVALIDPARAMS;
|
|
if (pSetSurfaceState == NULL)
|
|
{
|
|
return;
|
|
}
|
|
|
|
pDxObjDirectDraw = (DXOBJ*) pSetSurfaceState->hDirectDraw;
|
|
pDxObjSurface = (DXOBJ*) pSetSurfaceState->hSurface;
|
|
if ((pDxObjDirectDraw != NULL) &&
|
|
(pDxObjSurface != NULL))
|
|
{
|
|
peDxDirectDraw = pDxObjDirectDraw->peDxDirectDraw;
|
|
peDxSurface = pDxObjSurface->peDxSurface;
|
|
|
|
GetSurfaceStateIn.hDirectDraw = pSetSurfaceState->hDirectDraw;
|
|
GetSurfaceStateIn.hSurface = pSetSurfaceState->hSurface;
|
|
|
|
DxGetSurfaceState(&GetSurfaceStateIn, &GetSurfaceStateOut);
|
|
|
|
ASSERTDX(GetSurfaceStateOut.ddRVal == DD_OK,
|
|
"DxSetSurfaceState: Didn't expect failure from DxGetSurfaceState");
|
|
|
|
dwState = pSetSurfaceState->dwState;
|
|
|
|
// Get the video port if one is associated with the surface
|
|
|
|
if( peDxSurface->peDxVideoPort == NULL )
|
|
{
|
|
peDxVideoPort = NULL;
|
|
dwVPFlags = 0;
|
|
}
|
|
else
|
|
{
|
|
peDxVideoPort = peDxSurface->peDxVideoPort;
|
|
dwVPFlags = peDxVideoPort->dwVPFlags;
|
|
}
|
|
|
|
if ((dwState != DDSTATE_BOB) &&
|
|
(dwState != DDSTATE_WEAVE) &&
|
|
(dwState != DDSTATE_SKIPEVENFIELDS))
|
|
{
|
|
RIPDX("DxSetSurfaceState: Invalid dwState flags");
|
|
}
|
|
else if ((dwState & GetSurfaceStateOut.dwStateCaps) != dwState)
|
|
{
|
|
RIPDX("DxSetSurfaceState: State not supported");
|
|
}
|
|
else if ((dwState == DDSTATE_SKIPEVENFIELDS) && (peDxVideoPort == NULL ))
|
|
{
|
|
RIPDX("DxSetSurfaceState: Surface not attached to video port");
|
|
}
|
|
else if (((dwState & DDSTATE_BOB) &&
|
|
(peDxSurface->dwOverlayFlags & DDOVER_BOB)) ||
|
|
((dwState & DDSTATE_WEAVE) &&
|
|
!(peDxSurface->dwOverlayFlags & DDOVER_BOB) &&
|
|
!(dwVPFlags & (DDVP_SKIPEVENFIELDS|DDVP_SKIPODDFIELDS))) ||
|
|
((dwState & DDSTATE_SKIPEVENFIELDS ) &&
|
|
(dwVPFlags & (DDVP_SKIPEVENFIELDS|DDVP_SKIPODDFIELDS))))
|
|
{
|
|
// Don't do nothin, it's already in the requested state.
|
|
|
|
dwRet = DD_OK;
|
|
}
|
|
else if (peDxDirectDraw->DxApiInterface.DxSetState != NULL)
|
|
{
|
|
// Acquire the spinlock while we muck around in the 'dwSetStateState'
|
|
// and 'dwSetStateField' members, which are accessed by the videoport
|
|
// DPC.
|
|
|
|
KeAcquireSpinLock(&peDxDirectDraw->SpinLock, &OldIrql);
|
|
|
|
if ((peDxDirectDraw->bLost) ||
|
|
((peDxVideoPort != NULL) && (peDxVideoPort->bLost)) ||
|
|
(peDxSurface->bLost))
|
|
{
|
|
KdPrint(("DxSetSurfaceState: Objects are lost\n"));
|
|
dwRet = DDERR_SURFACELOST;
|
|
}
|
|
|
|
// If they want it to happen for the next field or we are not
|
|
// using a video port, call the mini port now; otherwise, we'll let
|
|
// the IRQ logoic handle this later.
|
|
|
|
else if ((pSetSurfaceState->dwStartField == 0) ||
|
|
(peDxVideoPort == NULL) ||
|
|
!(peDxVideoPort->bSoftwareAutoflip))
|
|
{
|
|
EffectStateChange( peDxVideoPort, peDxSurface, dwState );
|
|
}
|
|
else
|
|
{
|
|
peDxVideoPort->dwSetStateState = dwState;
|
|
peDxVideoPort->dwSetStateField = pSetSurfaceState->dwStartField;
|
|
peDxVideoPort->flFlags |= DD_DXVIDEOPORT_FLAG_NEW_STATE;
|
|
}
|
|
|
|
KeReleaseSpinLock(&peDxDirectDraw->SpinLock, OldIrql);
|
|
|
|
dwRet = DD_OK;
|
|
}
|
|
|
|
if (peDxDirectDraw->DxApiInterface.DxSetState == NULL)
|
|
{
|
|
dwRet = DDERR_UNSUPPORTED;
|
|
}
|
|
|
|
*pdwRet = dwRet;
|
|
}
|
|
}
|
|
|
|
/******************************Public*Routine******************************\
|
|
* VOID DxLock
|
|
*
|
|
* 14-Apr-1997 -by- J. Andrew Goossen [andrewgo]
|
|
* Wrote it.
|
|
\**************************************************************************/
|
|
|
|
VOID
|
|
APIENTRY
|
|
DxLock(
|
|
DDLOCKIN* pLockIn,
|
|
DDLOCKOUT* pLockOut
|
|
)
|
|
{
|
|
DWORD dwRet;
|
|
DXOBJ* pDxObjDirectDraw;
|
|
DXOBJ* pDxObjSurface;
|
|
EDD_DXDIRECTDRAW* peDxDirectDraw;
|
|
EDD_DXSURFACE* peDxSurface;
|
|
DDLOCKININFO LockInInfo;
|
|
DDLOCKOUTINFO LockOutInfo;
|
|
KIRQL OldIrql;
|
|
|
|
pLockOut->ddRVal = DDERR_INVALIDPARAMS;
|
|
if (pLockIn == NULL)
|
|
{
|
|
return;
|
|
}
|
|
|
|
dwRet = DD_OK;
|
|
|
|
pDxObjDirectDraw = (DXOBJ*) pLockIn->hDirectDraw;
|
|
pDxObjSurface = (DXOBJ*) pLockIn->hSurface;
|
|
if ((pDxObjDirectDraw != NULL) &&
|
|
(pDxObjSurface != NULL))
|
|
{
|
|
peDxDirectDraw = pDxObjDirectDraw->peDxDirectDraw;
|
|
peDxSurface = pDxObjSurface->peDxSurface;
|
|
|
|
ASSERTDX(peDxDirectDraw == peDxSurface->peDxDirectDraw,
|
|
"Surface and DirectDraw objects don't match");
|
|
ASSERTDX(pDxObjDirectDraw->iDxType == DXT_DIRECTDRAW,
|
|
"Invalid DirectDraw object");
|
|
ASSERTDX(pDxObjSurface->iDxType == DXT_SURFACE,
|
|
"Invalid surface object");
|
|
|
|
LockInInfo.lpSurfaceData = peDxSurface;
|
|
LockOutInfo.dwSurfacePtr = peDxSurface->fpLockPtr;
|
|
|
|
// The display driver can set 'fpLockPtr' to NULL in its SyncSurfaceData
|
|
// routine if it doesn't want to support a DXAPI lock.
|
|
|
|
if (peDxSurface->fpLockPtr == NULL)
|
|
{
|
|
KdPrint(("DxLock: Video miniport doesn't support lock on this surface\n"));
|
|
dwRet = DDERR_UNSUPPORTED;
|
|
}
|
|
else
|
|
{
|
|
// NOTE: The miniport should not wait for accelerator complete!
|
|
|
|
if (peDxDirectDraw->DxApiInterface.DxLock)
|
|
{
|
|
KeAcquireSpinLock(&peDxDirectDraw->SpinLock, &OldIrql);
|
|
|
|
if ((peDxDirectDraw->bLost) || (peDxSurface->bLost))
|
|
{
|
|
KdPrint(("DxLock: Objects are lost\n"));
|
|
dwRet = DDERR_SURFACELOST;
|
|
}
|
|
else
|
|
{
|
|
dwRet = peDxDirectDraw->DxApiInterface.DxLock(
|
|
peDxDirectDraw->HwDeviceExtension,
|
|
&LockInInfo,
|
|
&LockOutInfo);
|
|
}
|
|
|
|
KeReleaseSpinLock(&peDxDirectDraw->SpinLock, OldIrql);
|
|
|
|
if (dwRet != DD_OK)
|
|
{
|
|
KdPrint(("DxLock: Driver failed call\n"));
|
|
|
|
// Pass the return code on down...
|
|
}
|
|
}
|
|
|
|
pLockOut->lpSurface = (LPVOID) LockOutInfo.dwSurfacePtr;
|
|
|
|
pLockOut->dwSurfHeight = peDxSurface->dwHeight;
|
|
pLockOut->dwSurfWidth = peDxSurface->dwWidth;
|
|
pLockOut->lSurfPitch = peDxSurface->lPitch;
|
|
pLockOut->SurfaceCaps = peDxSurface->ddsCaps;
|
|
pLockOut->dwFormatFlags = peDxSurface->dwFormatFlags;
|
|
pLockOut->dwFormatFourCC = peDxSurface->dwFormatFourCC;
|
|
pLockOut->dwFormatBitCount = peDxSurface->dwFormatBitCount;
|
|
pLockOut->dwRBitMask = peDxSurface->dwRBitMask;
|
|
pLockOut->dwGBitMask = peDxSurface->dwGBitMask;
|
|
pLockOut->dwBBitMask = peDxSurface->dwBBitMask;
|
|
}
|
|
|
|
pLockOut->ddRVal = dwRet;
|
|
}
|
|
}
|
|
|
|
/******************************Public*Routine******************************\
|
|
* VOID DxFlipOverlay
|
|
*
|
|
* 14-Apr-1997 -by- J. Andrew Goossen [andrewgo]
|
|
* Wrote it.
|
|
\**************************************************************************/
|
|
|
|
VOID
|
|
APIENTRY
|
|
DxFlipOverlay(
|
|
DDFLIPOVERLAY* pFlipOverlay,
|
|
DWORD* pdwRet
|
|
)
|
|
{
|
|
DWORD dwRet;
|
|
DXOBJ* pDxObjDirectDraw;
|
|
DXOBJ* pDxObjTarget;
|
|
DXOBJ* pDxObjCurrent;
|
|
EDD_DXDIRECTDRAW* peDxDirectDraw;
|
|
EDD_DXSURFACE* peDxTarget;
|
|
EDD_DXSURFACE* peDxCurrent;
|
|
DDFLIPOVERLAYINFO FlipOverlayInfo;
|
|
KIRQL OldIrql;
|
|
|
|
*pdwRet = DDERR_INVALIDPARAMS;
|
|
if (pFlipOverlay == NULL)
|
|
{
|
|
return;
|
|
}
|
|
|
|
dwRet = DDERR_UNSUPPORTED; // Assume failure
|
|
|
|
pDxObjDirectDraw = (DXOBJ*) pFlipOverlay->hDirectDraw;
|
|
pDxObjTarget = (DXOBJ*) pFlipOverlay->hTargetSurface;
|
|
pDxObjCurrent = (DXOBJ*) pFlipOverlay->hCurrentSurface;
|
|
|
|
if ((pDxObjDirectDraw != NULL) &&
|
|
(pDxObjTarget != NULL) &&
|
|
(pDxObjCurrent != NULL))
|
|
{
|
|
peDxDirectDraw = pDxObjDirectDraw->peDxDirectDraw;
|
|
peDxTarget = pDxObjTarget->peDxSurface;
|
|
peDxCurrent = pDxObjCurrent->peDxSurface;
|
|
|
|
ASSERTDX(pDxObjDirectDraw->iDxType == DXT_DIRECTDRAW,
|
|
"Invalid DirectDraw object");
|
|
ASSERTDX(pDxObjTarget->iDxType == DXT_SURFACE,
|
|
"Invalid target object");
|
|
ASSERTDX(pDxObjCurrent->iDxType == DXT_SURFACE,
|
|
"Invalid current object");
|
|
ASSERTDX((peDxDirectDraw == peDxTarget->peDxDirectDraw) &&
|
|
(peDxDirectDraw == peDxCurrent->peDxDirectDraw),
|
|
"Surface and DirectDraw objects don't match");
|
|
ASSERTDX((peDxCurrent->dwWidth == peDxTarget->dwWidth) &&
|
|
(peDxCurrent->dwHeight == peDxTarget->dwHeight),
|
|
"Surfaces are different sizes");
|
|
|
|
if (!(peDxCurrent->ddsCaps & DDSCAPS_OVERLAY) ||
|
|
(peDxCurrent->dwOverlayFlags & DDOVER_AUTOFLIP))
|
|
{
|
|
RIPDX("Invalid current overlay status");
|
|
}
|
|
else if (!(peDxTarget->ddsCaps & DDSCAPS_OVERLAY) ||
|
|
(peDxTarget->dwOverlayFlags & DDOVER_AUTOFLIP))
|
|
{
|
|
RIPDX("Invalid target overlay status");
|
|
}
|
|
else
|
|
{
|
|
FlipOverlayInfo.lpCurrentSurface = peDxCurrent;
|
|
FlipOverlayInfo.lpTargetSurface = peDxTarget;
|
|
FlipOverlayInfo.dwFlags = pFlipOverlay->dwFlags;
|
|
|
|
if (peDxDirectDraw->DxApiInterface.DxFlipOverlay)
|
|
{
|
|
KeAcquireSpinLock(&peDxDirectDraw->SpinLock, &OldIrql);
|
|
|
|
if ((peDxDirectDraw->bLost) ||
|
|
(peDxTarget->bLost) ||
|
|
(peDxCurrent->bLost))
|
|
{
|
|
KdPrint(("DxFlipOverlay: Objects are lost\n"));
|
|
dwRet = DDERR_SURFACELOST;
|
|
}
|
|
else
|
|
{
|
|
dwRet = peDxDirectDraw->DxApiInterface.DxFlipOverlay(
|
|
peDxDirectDraw->HwDeviceExtension,
|
|
&FlipOverlayInfo,
|
|
NULL);
|
|
}
|
|
|
|
KeReleaseSpinLock(&peDxDirectDraw->SpinLock, OldIrql);
|
|
}
|
|
|
|
if (dwRet != DD_OK)
|
|
{
|
|
KdPrint(("DxFlipOverlay: Driver failed call\n"));
|
|
}
|
|
}
|
|
|
|
*pdwRet = dwRet;
|
|
}
|
|
}
|
|
|
|
/******************************Public*Routine******************************\
|
|
* VOID DxFlipVideoPort
|
|
*
|
|
* 14-Apr-1997 -by- J. Andrew Goossen [andrewgo]
|
|
* Wrote it.
|
|
\**************************************************************************/
|
|
|
|
VOID
|
|
APIENTRY
|
|
DxFlipVideoPort(
|
|
DDFLIPVIDEOPORT* pFlipVideoPort,
|
|
DWORD* pdwRet
|
|
)
|
|
{
|
|
DWORD dwRet;
|
|
DXOBJ* pDxObjDirectDraw;
|
|
DXOBJ* pDxObjVideoPort;
|
|
DXOBJ* pDxObjTarget;
|
|
DXOBJ* pDxObjCurrent;
|
|
EDD_DXDIRECTDRAW* peDxDirectDraw;
|
|
EDD_DXVIDEOPORT* peDxVideoPort;
|
|
EDD_DXSURFACE* peDxTarget;
|
|
EDD_DXSURFACE* peDxCurrent;
|
|
DDFLIPVIDEOPORTINFO FlipVideoPortInfo;
|
|
KIRQL OldIrql;
|
|
|
|
*pdwRet = DDERR_INVALIDPARAMS;
|
|
if (pFlipVideoPort == NULL)
|
|
{
|
|
return;
|
|
}
|
|
|
|
dwRet = DDERR_UNSUPPORTED; // Assume failure
|
|
|
|
pDxObjDirectDraw = (DXOBJ*) pFlipVideoPort->hDirectDraw;
|
|
pDxObjVideoPort = (DXOBJ*) pFlipVideoPort->hVideoPort;
|
|
pDxObjTarget = (DXOBJ*) pFlipVideoPort->hTargetSurface;
|
|
pDxObjCurrent = (DXOBJ*) pFlipVideoPort->hCurrentSurface;
|
|
|
|
if ((pDxObjDirectDraw != NULL) &&
|
|
(pDxObjVideoPort != NULL) &&
|
|
(pDxObjTarget != NULL) &&
|
|
(pDxObjCurrent != NULL))
|
|
{
|
|
peDxDirectDraw = pDxObjDirectDraw->peDxDirectDraw;
|
|
peDxVideoPort = pDxObjVideoPort->peDxVideoPort;
|
|
peDxTarget = pDxObjTarget->peDxSurface;
|
|
peDxCurrent = pDxObjCurrent->peDxSurface;
|
|
|
|
ASSERTDX(pDxObjDirectDraw->iDxType == DXT_DIRECTDRAW,
|
|
"Invalid DirectDraw object");
|
|
ASSERTDX(pDxObjVideoPort->iDxType == DXT_VIDEOPORT,
|
|
"Invalid VideoPort object");
|
|
ASSERTDX(pDxObjTarget->iDxType == DXT_SURFACE,
|
|
"Invalid target object");
|
|
ASSERTDX(pDxObjCurrent->iDxType == DXT_SURFACE,
|
|
"Invalid current object");
|
|
ASSERTDX((peDxDirectDraw == peDxTarget->peDxDirectDraw) &&
|
|
(peDxDirectDraw == peDxCurrent->peDxDirectDraw) &&
|
|
(peDxDirectDraw == peDxVideoPort->peDxDirectDraw),
|
|
"Surface, VideoPort, and DirectDraw objects don't match");
|
|
ASSERTDX((peDxCurrent->dwWidth == peDxTarget->dwWidth) &&
|
|
(peDxCurrent->dwHeight == peDxTarget->dwHeight),
|
|
"Surfaces are different sizes");
|
|
ASSERTDX((pFlipVideoPort->dwFlags == DDVPFLIP_VIDEO) ||
|
|
(pFlipVideoPort->dwFlags == DDVPFLIP_VBI),
|
|
"Invalid flags");
|
|
ASSERTDX(!(peDxVideoPort->dwVPFlags & DDVP_AUTOFLIP),
|
|
"Flip not available while autoflipping");
|
|
|
|
FlipVideoPortInfo.lpVideoPortData = peDxVideoPort;
|
|
FlipVideoPortInfo.lpCurrentSurface = peDxCurrent;
|
|
FlipVideoPortInfo.lpTargetSurface = peDxTarget;
|
|
FlipVideoPortInfo.dwFlipVPFlags = pFlipVideoPort->dwFlags;
|
|
|
|
if (peDxDirectDraw->DxApiInterface.DxFlipVideoPort)
|
|
{
|
|
KeAcquireSpinLock(&peDxDirectDraw->SpinLock, &OldIrql);
|
|
|
|
if ((peDxDirectDraw->bLost) ||
|
|
(peDxVideoPort->bLost) ||
|
|
(peDxTarget->bLost) ||
|
|
(peDxCurrent->bLost))
|
|
{
|
|
KdPrint(("DxFlipVideoPort: Objects are lost\n"));
|
|
dwRet = DDERR_SURFACELOST;
|
|
}
|
|
else
|
|
{
|
|
dwRet = peDxDirectDraw->DxApiInterface.DxFlipVideoPort(
|
|
peDxDirectDraw->HwDeviceExtension,
|
|
&FlipVideoPortInfo,
|
|
NULL);
|
|
}
|
|
peDxCurrent->peDxVideoPort = NULL;
|
|
peDxTarget->peDxVideoPort = peDxVideoPort;
|
|
|
|
KeReleaseSpinLock(&peDxDirectDraw->SpinLock, OldIrql);
|
|
}
|
|
|
|
if (dwRet != DD_OK)
|
|
{
|
|
KdPrint(("DxFlipVideoPort: Driver failed call\n"));
|
|
}
|
|
|
|
*pdwRet = dwRet;
|
|
}
|
|
}
|
|
|
|
/******************************Public*Routine******************************\
|
|
* VOID DxGetCurrentAutoflip
|
|
*
|
|
* 14-Apr-1997 -by- J. Andrew Goossen [andrewgo]
|
|
* Wrote it.
|
|
\**************************************************************************/
|
|
|
|
VOID
|
|
APIENTRY
|
|
DxGetCurrentAutoflip(
|
|
DDGETAUTOFLIPIN* pGetCurrentAutoflipIn,
|
|
DDGETAUTOFLIPOUT* pGetCurrentAutoflipOut
|
|
)
|
|
{
|
|
DWORD dwRet;
|
|
DXOBJ* pDxObjDirectDraw;
|
|
DXOBJ* pDxObjVideoPort;
|
|
DXOBJ* pDxObjTarget;
|
|
DXOBJ* pDxObjCurrent;
|
|
EDD_DXDIRECTDRAW* peDxDirectDraw;
|
|
EDD_DXVIDEOPORT* peDxVideoPort;
|
|
EDD_DXSURFACE* peDxTarget;
|
|
EDD_DXSURFACE* peDxCurrent;
|
|
DDGETPOLARITYININFO GetPolarityInInfo;
|
|
DDGETPOLARITYOUTINFO GetPolarityOutInfo;
|
|
DDGETCURRENTAUTOFLIPININFO GetCurrentAutoflipInInfo;
|
|
DDGETCURRENTAUTOFLIPOUTINFO GetCurrentAutoflipOutInfo;
|
|
KIRQL OldIrql;
|
|
DWORD dwVideo;
|
|
DWORD dwVBI;
|
|
BOOL bFlipping;
|
|
|
|
pGetCurrentAutoflipOut->ddRVal = DDERR_INVALIDPARAMS;
|
|
if (pGetCurrentAutoflipIn == NULL)
|
|
{
|
|
return;
|
|
}
|
|
|
|
dwRet = DDERR_UNSUPPORTED; // Assume failure
|
|
|
|
pDxObjDirectDraw = (DXOBJ*) pGetCurrentAutoflipIn->hDirectDraw;
|
|
pDxObjVideoPort = (DXOBJ*) pGetCurrentAutoflipIn->hVideoPort;
|
|
if ((pDxObjDirectDraw != NULL) &&
|
|
(pDxObjVideoPort != NULL))
|
|
{
|
|
peDxDirectDraw = pDxObjDirectDraw->peDxDirectDraw;
|
|
peDxVideoPort = pDxObjVideoPort->peDxVideoPort;
|
|
|
|
ASSERTDX(pDxObjDirectDraw->iDxType == DXT_DIRECTDRAW,
|
|
"Invalid DirectDraw object");
|
|
ASSERTDX(pDxObjVideoPort->iDxType == DXT_VIDEOPORT,
|
|
"Invalid VideoPort object");
|
|
ASSERTDX(peDxDirectDraw == peDxVideoPort->peDxDirectDraw,
|
|
"Surface, VideoPort, and DirectDraw objects don't match");
|
|
ASSERTDX(peDxVideoPort->dwVPFlags & DDVP_AUTOFLIP,
|
|
"Not currently autoflipping");
|
|
|
|
GetPolarityInInfo.lpVideoPortData = peDxVideoPort;
|
|
|
|
KeAcquireSpinLock(&peDxDirectDraw->SpinLock, &OldIrql);
|
|
|
|
if ((peDxDirectDraw->bLost) ||
|
|
(peDxVideoPort->bLost))
|
|
{
|
|
KdPrint(("DxGetCurrentAutoflip: Objects are lost\n"));
|
|
dwRet = DDERR_SURFACELOST;
|
|
}
|
|
else
|
|
{
|
|
dwRet = DDERR_UNSUPPORTED;
|
|
if (peDxDirectDraw->DxApiInterface.DxGetPolarity)
|
|
{
|
|
dwRet = peDxDirectDraw->DxApiInterface.DxGetPolarity(
|
|
peDxDirectDraw->HwDeviceExtension,
|
|
&GetPolarityInInfo,
|
|
&GetPolarityOutInfo);
|
|
}
|
|
|
|
if (dwRet != DD_OK)
|
|
{
|
|
KdPrint(("DxGetCurrentAutoflip: Driver failed GetPolarity\n"));
|
|
}
|
|
else
|
|
{
|
|
// Determine which field is currently receiving the data. If they
|
|
// are software autoflipping, I can do that myself; otherwise, I
|
|
// have to call the HAL
|
|
//
|
|
// When software autoflipping, there is an issue that if this
|
|
// function is called between the time that the IRQ occured
|
|
// and the time that the DPC ran, this function would return
|
|
// the wrong surface. Since fixing this requires that we do all
|
|
// of the work at IRQ time (bad), we can probably assume that
|
|
// this will always be the case since anybody using this
|
|
// function would be calling it during the IRQ callback. We
|
|
// will therefore work around it.
|
|
|
|
dwVideo = (DWORD) -1;
|
|
dwVBI = (DWORD) -1;
|
|
|
|
if( peDxVideoPort->flFlags & DD_DXVIDEOPORT_FLAG_AUTOFLIP )
|
|
{
|
|
dwVideo = peDxVideoPort->iCurrentVideo;
|
|
bFlipping = TRUE;
|
|
if( ( peDxVideoPort->flFlags & DD_DXVIDEOPORT_FLAG_SKIP_SET ) &&
|
|
( peDxVideoPort->dwFieldToSkip == 1 ) )
|
|
{
|
|
bFlipping = FALSE;
|
|
}
|
|
else if( !( peDxVideoPort->flFlags & DD_DXVIDEOPORT_FLAG_SKIPPED_LAST ) &&
|
|
( peDxVideoPort->dwVPFlags & DDVP_INTERLEAVE ) &&
|
|
!( peDxVideoPort->flFlags & DD_DXVIDEOPORT_FLAG_FLIP_NEXT ) )
|
|
{
|
|
bFlipping = FALSE;
|
|
}
|
|
if( bFlipping )
|
|
{
|
|
if( ++dwVideo >= peDxVideoPort->cAutoflipVideo )
|
|
{
|
|
dwVideo = 0;
|
|
}
|
|
}
|
|
}
|
|
|
|
if( peDxVideoPort->flFlags & DD_DXVIDEOPORT_FLAG_AUTOFLIP_VBI )
|
|
{
|
|
dwVBI = peDxVideoPort->iCurrentVbi;
|
|
if( ( peDxVideoPort->flFlags & DD_DXVIDEOPORT_FLAG_VBI_INTERLEAVED ) &&
|
|
!( peDxVideoPort->flFlags & DD_DXVIDEOPORT_FLAG_FLIP_NEXT_VBI ) )
|
|
{
|
|
if( ++dwVBI >= peDxVideoPort->cAutoflipVbi )
|
|
{
|
|
dwVBI = 0;
|
|
}
|
|
}
|
|
}
|
|
|
|
if( ( dwVideo == (DWORD) -1 ) && ( dwVBI == (DWORD) -1 ) )
|
|
{
|
|
GetCurrentAutoflipInInfo.lpVideoPortData = peDxVideoPort;
|
|
GetCurrentAutoflipOutInfo.dwSurfaceIndex = 0;
|
|
GetCurrentAutoflipOutInfo.dwVBISurfaceIndex = 0;
|
|
if (peDxDirectDraw->DxApiInterface.DxGetCurrentAutoflip)
|
|
{
|
|
dwRet = peDxDirectDraw->DxApiInterface.DxGetCurrentAutoflip(
|
|
peDxDirectDraw->HwDeviceExtension,
|
|
&GetCurrentAutoflipInInfo,
|
|
&GetCurrentAutoflipOutInfo);
|
|
}
|
|
dwVideo = GetCurrentAutoflipOutInfo.dwSurfaceIndex;
|
|
dwVBI = GetCurrentAutoflipOutInfo.dwVBISurfaceIndex;
|
|
}
|
|
|
|
pGetCurrentAutoflipOut->hVideoSurface = NULL;
|
|
pGetCurrentAutoflipOut->hVBISurface = NULL;
|
|
if( ( peDxVideoPort->cAutoflipVideo > 0 ) && ( dwVideo != (DWORD) -1 ) )
|
|
{
|
|
pGetCurrentAutoflipOut->hVideoSurface =
|
|
peDxVideoPort->apeDxSurfaceVideo[dwVideo];
|
|
}
|
|
if( ( peDxVideoPort->cAutoflipVbi > 0 ) && ( dwVBI != (DWORD) -1 ) )
|
|
{
|
|
pGetCurrentAutoflipOut->hVBISurface =
|
|
peDxVideoPort->apeDxSurfaceVbi[dwVBI];
|
|
}
|
|
pGetCurrentAutoflipOut->bPolarity = GetPolarityOutInfo.bPolarity;
|
|
}
|
|
}
|
|
|
|
KeReleaseSpinLock(&peDxDirectDraw->SpinLock, OldIrql);
|
|
|
|
pGetCurrentAutoflipOut->ddRVal = dwRet;
|
|
}
|
|
}
|
|
|
|
/******************************Public*Routine******************************\
|
|
* VOID DxGetPreviousAutoflip
|
|
*
|
|
* 14-Apr-1997 -by- J. Andrew Goossen [andrewgo]
|
|
* Wrote it.
|
|
\**************************************************************************/
|
|
|
|
VOID
|
|
APIENTRY
|
|
DxGetPreviousAutoflip(
|
|
DDGETAUTOFLIPIN* pGetPreviousAutoflipIn,
|
|
DDGETAUTOFLIPOUT* pGetPreviousAutoflipOut
|
|
)
|
|
{
|
|
DWORD dwRet;
|
|
DXOBJ* pDxObjDirectDraw;
|
|
DXOBJ* pDxObjVideoPort;
|
|
DXOBJ* pDxObjTarget;
|
|
DXOBJ* pDxObjCurrent;
|
|
EDD_DXDIRECTDRAW* peDxDirectDraw;
|
|
EDD_DXVIDEOPORT* peDxVideoPort;
|
|
EDD_DXSURFACE* peDxTarget;
|
|
EDD_DXSURFACE* peDxPrevious;
|
|
DDGETPOLARITYININFO GetPolarityInInfo;
|
|
DDGETPOLARITYOUTINFO GetPolarityOutInfo;
|
|
DDGETPREVIOUSAUTOFLIPININFO GetPreviousAutoflipInInfo;
|
|
DDGETPREVIOUSAUTOFLIPOUTINFO GetPreviousAutoflipOutInfo;
|
|
KIRQL OldIrql;
|
|
DWORD dwVideo;
|
|
DWORD dwVBI;
|
|
|
|
pGetPreviousAutoflipOut->ddRVal = DDERR_INVALIDPARAMS;
|
|
if (pGetPreviousAutoflipIn == NULL)
|
|
{
|
|
return;
|
|
}
|
|
|
|
|
|
dwRet = DDERR_UNSUPPORTED; // Assume failure
|
|
|
|
pDxObjDirectDraw = (DXOBJ*) pGetPreviousAutoflipIn->hDirectDraw;
|
|
pDxObjVideoPort = (DXOBJ*) pGetPreviousAutoflipIn->hVideoPort;
|
|
if ((pDxObjDirectDraw != NULL) &&
|
|
(pDxObjVideoPort != NULL))
|
|
{
|
|
peDxDirectDraw = pDxObjDirectDraw->peDxDirectDraw;
|
|
peDxVideoPort = pDxObjVideoPort->peDxVideoPort;
|
|
|
|
ASSERTDX(pDxObjDirectDraw->iDxType == DXT_DIRECTDRAW,
|
|
"Invalid DirectDraw object");
|
|
ASSERTDX(pDxObjVideoPort->iDxType == DXT_VIDEOPORT,
|
|
"Invalid VideoPort object");
|
|
ASSERTDX(peDxDirectDraw == peDxVideoPort->peDxDirectDraw,
|
|
"Surface, VideoPort, and DirectDraw objects don't match");
|
|
ASSERTDX(peDxVideoPort->dwVPFlags & DDVP_AUTOFLIP,
|
|
"Not currently autoflipping");
|
|
|
|
GetPolarityInInfo.lpVideoPortData = peDxVideoPort;
|
|
|
|
KeAcquireSpinLock(&peDxDirectDraw->SpinLock, &OldIrql);
|
|
|
|
if ((peDxDirectDraw->bLost) ||
|
|
(peDxVideoPort->bLost))
|
|
{
|
|
KdPrint(("DxGetPreviousAutoflip: Objects are lost\n"));
|
|
dwRet = DDERR_SURFACELOST;
|
|
}
|
|
else
|
|
{
|
|
dwRet = DDERR_UNSUPPORTED;
|
|
if (peDxDirectDraw->DxApiInterface.DxGetPolarity)
|
|
{
|
|
dwRet = peDxDirectDraw->DxApiInterface.DxGetPolarity(
|
|
peDxDirectDraw->HwDeviceExtension,
|
|
&GetPolarityInInfo,
|
|
&GetPolarityOutInfo);
|
|
}
|
|
|
|
if (dwRet != DD_OK)
|
|
{
|
|
KdPrint(("DxGetPreviousAutoflip: Driver failed GetPolarity\n"));
|
|
}
|
|
else
|
|
{
|
|
// Determine which field is currently receiving the data. If they
|
|
// are software autoflipping, I can do that myself; otherwise, I
|
|
// have to call the HAL
|
|
//
|
|
// This is complicated by the facts that:
|
|
// 1) Skipping may be enabled.
|
|
// 3) When interleaving, they flip every other field, but its not
|
|
// guarenteed that the flip always occurs between the even and the
|
|
// odd fields.
|
|
//
|
|
// When software autoflipping, there is an issue that if this
|
|
// function is called between the time that the IRQ occured
|
|
// and the time that the DPC ran, this function would return
|
|
// the wrong surface. Since fixing this requires that we do all
|
|
// of the work at IRQ time (bad), we can probably assume that
|
|
// this will always be the case since anybody using this
|
|
// function would be calling it during the IRQ callback. We
|
|
// will therefore work around it.
|
|
|
|
dwVideo = (DWORD) -1;
|
|
dwVBI = (DWORD) -1;
|
|
if( peDxVideoPort->flFlags & DD_DXVIDEOPORT_FLAG_AUTOFLIP )
|
|
{
|
|
dwVideo = peDxVideoPort->iCurrentVideo;
|
|
}
|
|
if( peDxVideoPort->flFlags & DD_DXVIDEOPORT_FLAG_AUTOFLIP_VBI )
|
|
{
|
|
dwVBI = peDxVideoPort->iCurrentVbi;
|
|
}
|
|
if( ( dwVideo == (DWORD) -1 ) && ( dwVBI == (DWORD) -1 ) )
|
|
{
|
|
GetPreviousAutoflipInInfo.lpVideoPortData = peDxVideoPort;
|
|
GetPreviousAutoflipOutInfo.dwSurfaceIndex = 0;
|
|
GetPreviousAutoflipOutInfo.dwVBISurfaceIndex = 0;
|
|
if (peDxDirectDraw->DxApiInterface.DxGetPreviousAutoflip)
|
|
{
|
|
dwRet = peDxDirectDraw->DxApiInterface.DxGetPreviousAutoflip(
|
|
peDxDirectDraw->HwDeviceExtension,
|
|
&GetPreviousAutoflipInInfo,
|
|
&GetPreviousAutoflipOutInfo);
|
|
}
|
|
dwVideo = GetPreviousAutoflipOutInfo.dwSurfaceIndex;
|
|
dwVBI = GetPreviousAutoflipOutInfo.dwVBISurfaceIndex;
|
|
}
|
|
|
|
pGetPreviousAutoflipOut->hVideoSurface = NULL;
|
|
pGetPreviousAutoflipOut->hVBISurface = NULL;
|
|
if( ( peDxVideoPort->cAutoflipVideo > 0 ) && ( dwVideo != (DWORD) -1 ) )
|
|
{
|
|
pGetPreviousAutoflipOut->hVideoSurface =
|
|
peDxVideoPort->apeDxSurfaceVideo[dwVideo];
|
|
}
|
|
if( ( peDxVideoPort->cAutoflipVbi > 0 ) && ( dwVBI != (DWORD) -1 ) )
|
|
{
|
|
pGetPreviousAutoflipOut->hVBISurface =
|
|
peDxVideoPort->apeDxSurfaceVbi[dwVBI];
|
|
}
|
|
pGetPreviousAutoflipOut->bPolarity =
|
|
( GetPolarityOutInfo.bPolarity == FALSE ); // invert
|
|
}
|
|
}
|
|
|
|
KeReleaseSpinLock(&peDxDirectDraw->SpinLock, OldIrql);
|
|
|
|
pGetPreviousAutoflipOut->ddRVal = dwRet;
|
|
}
|
|
}
|
|
|
|
/******************************Public*Routine******************************\
|
|
* BOOL bDxModifyPassiveEventList
|
|
*
|
|
* 14-Apr-1997 -by- J. Andrew Goossen [andrewgo]
|
|
* Wrote it.
|
|
\**************************************************************************/
|
|
|
|
BOOL
|
|
bDxModifyPassiveEventList(
|
|
EDD_DXDIRECTDRAW* peDxDirectDraw,
|
|
BOOL bAdd, // TRUE to add, FALSE to delete
|
|
DWORD dwEvent,
|
|
LPDD_NOTIFYCALLBACK pfnCallBack,
|
|
PVOID pContext
|
|
)
|
|
{
|
|
BOOL bRet;
|
|
DXAPI_EVENT* pDxEvent;
|
|
DXAPI_EVENT* pDxEvent_New;
|
|
DXAPI_EVENT* pDxEvent_Previous;
|
|
KIRQL OldIrql;
|
|
|
|
bRet = FALSE; // Assume failure
|
|
|
|
ASSERTDX(KeGetCurrentIrql() == PASSIVE_LEVEL, "Expected passive level");
|
|
ASSERTDX((bAdd == FALSE) || (bAdd == TRUE), "Bad boolean");
|
|
|
|
if (bAdd)
|
|
{
|
|
pDxEvent_New = (DXAPI_EVENT*) ExAllocatePoolWithTag(PagedPool,
|
|
sizeof(*pDxEvent),
|
|
'eddG');
|
|
|
|
if (pDxEvent_New == NULL)
|
|
return(FALSE);
|
|
|
|
RtlZeroMemory(pDxEvent_New, sizeof(*pDxEvent_New));
|
|
}
|
|
|
|
// We must synchronize additions or deletions to the passive-level
|
|
// event list via our devlock.
|
|
|
|
ASSERTDX(gpfnLockDevice, "bDxModifyPassiveEventList: gpfnLockDevice is NULL");
|
|
gpfnLockDevice(peDxDirectDraw->hdev);
|
|
|
|
if (peDxDirectDraw->bLost)
|
|
{
|
|
KdPrint(("bDxModifyPassiveEventList: Object is lost\n"));
|
|
}
|
|
else
|
|
{
|
|
// First, try to find this event in the list:
|
|
|
|
pDxEvent_Previous = NULL;
|
|
|
|
for (pDxEvent = peDxDirectDraw->pDxEvent_PassiveList;
|
|
pDxEvent != NULL;
|
|
pDxEvent = pDxEvent->pDxEvent_Next)
|
|
{
|
|
if ((pDxEvent->dwEvent == dwEvent) &&
|
|
(pDxEvent->pfnCallBack == pfnCallBack) &&
|
|
(pDxEvent->pContext == pContext))
|
|
{
|
|
break;
|
|
}
|
|
|
|
pDxEvent_Previous = pDxEvent;
|
|
}
|
|
|
|
// It's a failure when:
|
|
//
|
|
// 1) If adding, the same event is already in the list;
|
|
// 2) If deleting, the event is not in the list.
|
|
|
|
if ((bAdd) == (pDxEvent == NULL))
|
|
{
|
|
if (bAdd)
|
|
{
|
|
// Add the event.
|
|
|
|
pDxEvent_New->peDxDirectDraw = peDxDirectDraw;
|
|
pDxEvent_New->dwEvent = dwEvent;
|
|
pDxEvent_New->dwIrqFlag = 0;
|
|
pDxEvent_New->pfnCallBack = pfnCallBack;
|
|
pDxEvent_New->pContext = pContext;
|
|
pDxEvent_New->pDxEvent_Next = peDxDirectDraw->pDxEvent_PassiveList;
|
|
|
|
peDxDirectDraw->pDxEvent_PassiveList = pDxEvent_New;
|
|
|
|
bRet = TRUE;
|
|
}
|
|
else
|
|
{
|
|
// Delete the event.
|
|
|
|
if (pDxEvent_Previous == NULL)
|
|
{
|
|
ASSERTDX(peDxDirectDraw->pDxEvent_PassiveList == pDxEvent,
|
|
"Deletion code is confused");
|
|
|
|
peDxDirectDraw->pDxEvent_PassiveList = pDxEvent->pDxEvent_Next;
|
|
}
|
|
else
|
|
{
|
|
pDxEvent_Previous->pDxEvent_Next = pDxEvent->pDxEvent_Next;
|
|
}
|
|
|
|
bRet = TRUE;
|
|
}
|
|
}
|
|
}
|
|
|
|
ASSERTDX(gpfnUnlockDevice, "bDxModifyPassiveEventList: gpfnUnlockDevice is NULL");
|
|
gpfnUnlockDevice(peDxDirectDraw->hdev);
|
|
|
|
if (bAdd) // Add case
|
|
{
|
|
if (!bRet)
|
|
{
|
|
// Add failed, so free the new node we allocated up front:
|
|
|
|
ExFreePool(pDxEvent_New);
|
|
|
|
RIPDX("DD_DXAPI_REGISTER_EVENT: Event was already registered");
|
|
}
|
|
}
|
|
else // Remove case
|
|
{
|
|
if (bRet)
|
|
{
|
|
// Delete succeeded, so free the old node:
|
|
|
|
ExFreePool(pDxEvent);
|
|
}
|
|
else
|
|
{
|
|
KdPrint(("DD_DXAPI_UNREGISTEREVENT: Couldn't find an event registered with those\n"));
|
|
KdPrint(("same parameters, so the unregister failed.\n"));
|
|
RIPDX("This will probably cause a leak of non-paged memory!");
|
|
}
|
|
}
|
|
|
|
return(bRet);
|
|
}
|
|
|
|
/******************************Public*Routine******************************\
|
|
* BOOL bDxModifyDispatchEventList
|
|
*
|
|
* 14-Apr-1997 -by- J. Andrew Goossen [andrewgo]
|
|
* Wrote it.
|
|
\**************************************************************************/
|
|
|
|
BOOL
|
|
bDxModifyDispatchEventList(
|
|
EDD_DXDIRECTDRAW* peDxDirectDraw,
|
|
EDD_DXVIDEOPORT* peDxVideoPort,
|
|
BOOL bAdd, // TRUE to add, FALSE to delete
|
|
DWORD dwEvent,
|
|
DWORD dwIrqFlag,
|
|
LPDD_NOTIFYCALLBACK pfnCallBack,
|
|
PVOID pContext,
|
|
DWORD dwListEntry
|
|
)
|
|
{
|
|
BOOL bRet;
|
|
DXAPI_EVENT* pDxEvent;
|
|
DXAPI_EVENT* pDxEvent_New;
|
|
DXAPI_EVENT* pDxEvent_Previous;
|
|
KIRQL OldIrql;
|
|
|
|
bRet = FALSE; // Assume failure
|
|
|
|
ASSERTDX(KeGetCurrentIrql() == PASSIVE_LEVEL, "Expected passive level");
|
|
ASSERTDX((bAdd == FALSE) || (bAdd == TRUE), "Bad boolean");
|
|
|
|
// The event list is traversed at dispatch-level, so needs
|
|
// to be allocated non-paged.
|
|
|
|
if (bAdd)
|
|
{
|
|
pDxEvent_New = (DXAPI_EVENT*) ExAllocatePoolWithTag(NonPagedPool,
|
|
sizeof(*pDxEvent),
|
|
'eddG');
|
|
if (pDxEvent_New == NULL)
|
|
return(FALSE);
|
|
|
|
RtlZeroMemory(pDxEvent_New, sizeof(*pDxEvent_New));
|
|
}
|
|
|
|
// We must synchronize additions or deletions to the dispatch-level
|
|
// event list via our spin lock. Note that this spinlock (of course)
|
|
// raises our IRQL level, which means we can't touch any pageable code!
|
|
|
|
KeAcquireSpinLock(&peDxDirectDraw->SpinLock, &OldIrql);
|
|
|
|
if ((peDxDirectDraw->bLost) ||
|
|
((peDxVideoPort != NULL) && (peDxVideoPort->bLost)))
|
|
{
|
|
KdPrint(("bDxModifyDispatchEventList: Objects are lost\n"));
|
|
}
|
|
else
|
|
{
|
|
// First, try to find this event in the list:
|
|
|
|
pDxEvent_Previous = NULL;
|
|
|
|
for (pDxEvent = peDxDirectDraw->pDxEvent_DispatchList[dwListEntry];
|
|
pDxEvent != NULL;
|
|
pDxEvent = pDxEvent->pDxEvent_Next)
|
|
{
|
|
if ((pDxEvent->dwEvent == dwEvent) &&
|
|
(pDxEvent->dwIrqFlag == dwIrqFlag) &&
|
|
(pDxEvent->pfnCallBack == pfnCallBack) &&
|
|
(pDxEvent->pContext == pContext))
|
|
{
|
|
break;
|
|
}
|
|
|
|
pDxEvent_Previous = pDxEvent;
|
|
}
|
|
|
|
// It's a failure when:
|
|
//
|
|
// 1) If adding, the same event is already in the list;
|
|
// 2) If deleting, the event is not in the list.
|
|
|
|
if ((bAdd) == (pDxEvent == NULL))
|
|
{
|
|
if (bAdd)
|
|
{
|
|
// Add the event.
|
|
|
|
pDxEvent_New->peDxDirectDraw = peDxVideoPort->peDxDirectDraw;
|
|
pDxEvent_New->peDxVideoPort = peDxVideoPort;
|
|
pDxEvent_New->dwEvent = dwEvent;
|
|
pDxEvent_New->dwIrqFlag = dwIrqFlag;
|
|
pDxEvent_New->pfnCallBack = pfnCallBack;
|
|
pDxEvent_New->pContext = pContext;
|
|
pDxEvent_New->pDxEvent_Next = peDxDirectDraw->pDxEvent_DispatchList[dwListEntry];
|
|
|
|
peDxDirectDraw->pDxEvent_DispatchList[dwListEntry] = pDxEvent_New;
|
|
|
|
bRet = TRUE;
|
|
}
|
|
else
|
|
{
|
|
// Delete the event.
|
|
|
|
if (pDxEvent_Previous == NULL)
|
|
{
|
|
ASSERTDX(peDxDirectDraw->pDxEvent_DispatchList[dwListEntry] == pDxEvent,
|
|
"Deletion code is confused");
|
|
|
|
peDxDirectDraw->pDxEvent_DispatchList[dwListEntry]
|
|
= pDxEvent->pDxEvent_Next;
|
|
}
|
|
else
|
|
{
|
|
pDxEvent_Previous->pDxEvent_Next = pDxEvent->pDxEvent_Next;
|
|
}
|
|
|
|
bRet = TRUE;
|
|
}
|
|
}
|
|
}
|
|
|
|
KeReleaseSpinLock(&peDxDirectDraw->SpinLock, OldIrql);
|
|
|
|
if (bAdd) // Add case
|
|
{
|
|
if (!bRet)
|
|
{
|
|
// Add failed, so free the new node we allocated up front:
|
|
|
|
ExFreePool(pDxEvent_New);
|
|
}
|
|
}
|
|
else // Remove case
|
|
{
|
|
if (bRet)
|
|
{
|
|
// Delete succeeded, so free the old node:
|
|
|
|
ExFreePool(pDxEvent);
|
|
}
|
|
else
|
|
{
|
|
KdPrint(("DD_DXAPI_UNREGISTEREVENT: Couldn't find an event registered with those\n"));
|
|
KdPrint(("same parameters, so the unregister failed.\n"));
|
|
RIPDX("This will probably cause a leak of non-paged memory!");
|
|
}
|
|
}
|
|
|
|
return(bRet);
|
|
}
|
|
|
|
/******************************Public*Routine******************************\
|
|
* VOID vDxEnableInterrupts
|
|
*
|
|
* NOTE: Drivers may not fail DxEnableIrq.
|
|
*
|
|
* 14-Apr-1997 -by- J. Andrew Goossen [andrewgo]
|
|
* Wrote it.
|
|
\**************************************************************************/
|
|
|
|
VOID
|
|
vDxEnableInterrupts(
|
|
EDD_DXDIRECTDRAW* peDxDirectDraw,
|
|
DWORD dwLine
|
|
)
|
|
{
|
|
DWORD dwIRQSources = 0;
|
|
KIRQL OldIrql;
|
|
DXAPI_EVENT* pDxEvent;
|
|
DDENABLEIRQINFO EnableIrqInfo;
|
|
DWORD dwRet;
|
|
DWORD i;
|
|
|
|
ASSERTDX(KeGetCurrentIrql() == PASSIVE_LEVEL, "Expected passive level");
|
|
ASSERTDX(peDxDirectDraw->DxApiInterface.DxEnableIrq != NULL,
|
|
"DxEnableIrq must be hooked if supporting interrupts.");
|
|
|
|
// We acquire both the devlock and the spinlock to ensure that no other
|
|
// activity in the driver is occurring while interrupts are enabled.
|
|
//
|
|
// The motivation for acquiring both (the spinlock could have been
|
|
// sufficient) is that we want to allow drivers to touch the CRTC
|
|
// registers in their interrupt enable routine (typically, both the
|
|
// display driver and the enable interrupt routine use CRTC registers,
|
|
// the usage of which must be synchronized).
|
|
|
|
ASSERTDX(gpfnLockDevice, "vDxEnableInterrupts: gpfnLockDevice is NULL");
|
|
gpfnLockDevice(peDxDirectDraw->hdev);
|
|
|
|
KeAcquireSpinLock(&peDxDirectDraw->SpinLock, &OldIrql);
|
|
|
|
// Compute the interrupts that are to be enabled by traversing the
|
|
// active event list:
|
|
|
|
for( i = 0; i < NUM_DISPATCH_LISTS; i++ )
|
|
{
|
|
for (pDxEvent = peDxDirectDraw->pDxEvent_DispatchList[i];
|
|
pDxEvent != NULL;
|
|
pDxEvent = pDxEvent->pDxEvent_Next)
|
|
{
|
|
dwIRQSources |= pDxEvent->dwIrqFlag;
|
|
}
|
|
}
|
|
|
|
EnableIrqInfo.dwIRQSources = dwIRQSources;
|
|
EnableIrqInfo.dwLine = dwLine;
|
|
EnableIrqInfo.IRQCallback = DxIrqCallBack;
|
|
EnableIrqInfo.lpIRQData = &peDxDirectDraw->IrqData;
|
|
|
|
dwRet = peDxDirectDraw->DxApiInterface.DxEnableIrq(
|
|
peDxDirectDraw->HwDeviceExtension,
|
|
&EnableIrqInfo,
|
|
NULL);
|
|
|
|
KeReleaseSpinLock(&peDxDirectDraw->SpinLock, OldIrql);
|
|
|
|
ASSERTDX(gpfnUnlockDevice, "vDxEnableInterrupts: gpfnUnlockDevice is NULL");
|
|
gpfnUnlockDevice(peDxDirectDraw->hdev);
|
|
|
|
ASSERTDX(dwRet == DD_OK, "vDxEnableInterrupts: Driver failed DxEnableIrq");
|
|
}
|
|
|
|
/******************************Public*Routine******************************\
|
|
* DWORD dwDxRegisterEvent
|
|
*
|
|
* 14-Apr-1997 -by- J. Andrew Goossen [andrewgo]
|
|
* Wrote it.
|
|
\**************************************************************************/
|
|
|
|
DWORD
|
|
dwDxRegisterEvent(
|
|
DDREGISTERCALLBACK* pRegisterEvent,
|
|
BOOL bRegister // TRUE if register, FALSE if unregister
|
|
)
|
|
{
|
|
DWORD dwRet;
|
|
DXOBJ* pDxObjDirectDraw;
|
|
DXOBJ* pDxObjVideoPort;
|
|
EDD_DXDIRECTDRAW* peDxDirectDraw;
|
|
EDD_DXVIDEOPORT* peDxVideoPort;
|
|
DWORD dwEvent;
|
|
DWORD dwIrqFlag;
|
|
BOOL bPassiveEvent;
|
|
BOOL bDispatchEvent;
|
|
DWORD dwLine;
|
|
|
|
dwRet = DDERR_GENERIC; // Assume failure
|
|
|
|
// Passive level is required because we have to acquire the devlock
|
|
// for the RESCHANGE and DOSBOX notifications.
|
|
|
|
ASSERTDX(KeGetCurrentIrql() == PASSIVE_LEVEL, "Expected passive level");
|
|
ASSERTDX(pRegisterEvent->pfnCallback != NULL, "Null callback specified");
|
|
ASSERTDX(pRegisterEvent->hDirectDraw != NULL, "Null hDirectDraw specified");
|
|
|
|
pDxObjDirectDraw = (DXOBJ*) pRegisterEvent->hDirectDraw;
|
|
if (pDxObjDirectDraw != NULL)
|
|
{
|
|
peDxDirectDraw = pDxObjDirectDraw->peDxDirectDraw;
|
|
|
|
// Note that we don't support the hooking of DDEVENT_CLOSEDIRECTDRAW,
|
|
// DDEVENT_CLOSESURFACE, or DDEVENT_CLOSEVIDEOPORT because those are
|
|
// always explictly registered with the object open call. If multiple
|
|
// clients want object close notification, they should each open their
|
|
// own object instances.
|
|
|
|
dwEvent = pRegisterEvent->dwEvents;
|
|
|
|
// Memphis doesn't bother checking to verify that 'dwParam1' and
|
|
// 'dwParam2' are zero when unused, so we won't either.
|
|
|
|
bPassiveEvent = FALSE;
|
|
bDispatchEvent = FALSE;
|
|
peDxVideoPort = NULL;
|
|
dwLine = 0;
|
|
dwIrqFlag = 0;
|
|
|
|
switch (dwEvent)
|
|
{
|
|
case DDEVENT_VP_VSYNC:
|
|
case DDEVENT_VP_LINE:
|
|
|
|
ASSERTDX(pRegisterEvent->dwParam1 != NULL,
|
|
"dwParam1 should be videoport handle");
|
|
|
|
pDxObjVideoPort = (DXOBJ*) pRegisterEvent->dwParam1;
|
|
if (pDxObjVideoPort != NULL)
|
|
{
|
|
peDxVideoPort = pDxObjVideoPort->peDxVideoPort;
|
|
|
|
ASSERTDX(pDxObjVideoPort->iDxType == DXT_VIDEOPORT,
|
|
"dwParam1 should be videoport handle");
|
|
|
|
if (dwEvent == DDEVENT_VP_LINE)
|
|
{
|
|
dwIrqFlag = DDIRQ_VPORT0_LINE; // We're going to shift this...
|
|
|
|
// We make it so that the 'dwLine' parameter is non-zero only
|
|
// when the event is registered, not unregistered,
|
|
|
|
dwLine = (bRegister) ? (DWORD) pRegisterEvent->dwParam2 : 0;
|
|
}
|
|
else
|
|
{
|
|
dwIrqFlag = DDIRQ_VPORT0_VSYNC; // We're going to shift this...
|
|
}
|
|
|
|
dwIrqFlag <<= (2 * peDxVideoPort->dwVideoPortID);
|
|
|
|
bDispatchEvent = TRUE;
|
|
}
|
|
break;
|
|
|
|
case DDEVENT_DISPLAY_VSYNC:
|
|
|
|
dwIrqFlag = DDIRQ_DISPLAY_VSYNC;
|
|
bDispatchEvent = TRUE;
|
|
break;
|
|
|
|
case DDEVENT_PRERESCHANGE:
|
|
case DDEVENT_POSTRESCHANGE:
|
|
case DDEVENT_PREDOSBOX:
|
|
case DDEVENT_POSTDOSBOX:
|
|
|
|
bPassiveEvent = TRUE;
|
|
break;
|
|
|
|
default:
|
|
|
|
KdPrint(("dwDxRegisterEvent: Invalid dwEvents specified\n"));
|
|
dwRet = DDERR_UNSUPPORTED;
|
|
break;
|
|
}
|
|
|
|
if (bPassiveEvent)
|
|
{
|
|
if (bDxModifyPassiveEventList(peDxDirectDraw,
|
|
bRegister,
|
|
dwEvent,
|
|
pRegisterEvent->pfnCallback,
|
|
pRegisterEvent->pContext))
|
|
{
|
|
dwRet = DD_OK;
|
|
}
|
|
}
|
|
else if (bDispatchEvent)
|
|
{
|
|
// First, verify that the requested interrupt is supported:
|
|
|
|
if (!(peDxDirectDraw->dwIRQCaps & dwIrqFlag))
|
|
{
|
|
KdPrint(("dwDxRegisterEvent: Interrupt not supported by driver.\n"));
|
|
dwRet = DDERR_UNSUPPORTED;
|
|
}
|
|
else
|
|
{
|
|
if (bDxModifyDispatchEventList(peDxDirectDraw,
|
|
peDxVideoPort,
|
|
bRegister,
|
|
dwEvent,
|
|
dwIrqFlag,
|
|
pRegisterEvent->pfnCallback,
|
|
pRegisterEvent->pContext,
|
|
CLIENT_DISPATCH_LIST))
|
|
{
|
|
vDxEnableInterrupts(peDxDirectDraw, dwLine);
|
|
dwRet = DD_OK;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return(dwRet);
|
|
}
|
|
|
|
/******************************Public*Routine******************************\
|
|
* VOID DxRegisterEvent
|
|
*
|
|
* 14-Apr-1997 -by- J. Andrew Goossen [andrewgo]
|
|
* Wrote it.
|
|
\**************************************************************************/
|
|
|
|
VOID
|
|
APIENTRY
|
|
DxRegisterEvent(
|
|
DDREGISTERCALLBACK* pRegisterEvent,
|
|
DWORD* pdwRet
|
|
)
|
|
{
|
|
if (pRegisterEvent == NULL)
|
|
{
|
|
*pdwRet = DDERR_INVALIDPARAMS;
|
|
}
|
|
else
|
|
{
|
|
*pdwRet = dwDxRegisterEvent(pRegisterEvent, TRUE);
|
|
}
|
|
}
|
|
|
|
/******************************Public*Routine******************************\
|
|
* VOID DxUnregisterEvent
|
|
*
|
|
* 14-Apr-1997 -by- J. Andrew Goossen [andrewgo]
|
|
* Wrote it.
|
|
\**************************************************************************/
|
|
|
|
VOID
|
|
APIENTRY
|
|
DxUnregisterEvent(
|
|
DDREGISTERCALLBACK* pRegisterEvent,
|
|
DWORD* pdwRet
|
|
)
|
|
{
|
|
if (pRegisterEvent == NULL)
|
|
{
|
|
*pdwRet = DDERR_INVALIDPARAMS;
|
|
}
|
|
else
|
|
{
|
|
*pdwRet = dwDxRegisterEvent(pRegisterEvent, FALSE);
|
|
}
|
|
}
|
|
|
|
/******************************Public*Routine******************************\
|
|
* VOID DxGetPolarity
|
|
*
|
|
* 14-Apr-1997 -by- J. Andrew Goossen [andrewgo]
|
|
* Wrote it.
|
|
\**************************************************************************/
|
|
|
|
VOID
|
|
APIENTRY
|
|
DxGetPolarity(
|
|
DDGETPOLARITYIN* pGetPolarityIn,
|
|
DDGETPOLARITYOUT* pGetPolarityOut
|
|
)
|
|
{
|
|
DWORD dwRet;
|
|
DXOBJ* pDxObjDirectDraw;
|
|
DXOBJ* pDxObjVideoPort;
|
|
DXOBJ* pDxObjTarget;
|
|
DXOBJ* pDxObjCurrent;
|
|
EDD_DXDIRECTDRAW* peDxDirectDraw;
|
|
EDD_DXVIDEOPORT* peDxVideoPort;
|
|
DDGETPOLARITYININFO GetPolarityInInfo;
|
|
DDGETPOLARITYOUTINFO GetPolarityOutInfo;
|
|
KIRQL OldIrql;
|
|
|
|
pGetPolarityOut->ddRVal = DDERR_INVALIDPARAMS;
|
|
if (pGetPolarityIn == NULL)
|
|
{
|
|
return;
|
|
}
|
|
|
|
dwRet = DDERR_UNSUPPORTED; // Assume failure
|
|
|
|
pDxObjDirectDraw = (DXOBJ*) pGetPolarityIn->hDirectDraw;
|
|
pDxObjVideoPort = (DXOBJ*) pGetPolarityIn->hVideoPort;
|
|
if ((pDxObjDirectDraw != NULL) &&
|
|
(pDxObjVideoPort != NULL))
|
|
{
|
|
peDxDirectDraw = pDxObjDirectDraw->peDxDirectDraw;
|
|
peDxVideoPort = pDxObjVideoPort->peDxVideoPort;
|
|
|
|
ASSERTDX(pDxObjDirectDraw->iDxType == DXT_DIRECTDRAW,
|
|
"Invalid DirectDraw object");
|
|
ASSERTDX(pDxObjVideoPort->iDxType == DXT_VIDEOPORT,
|
|
"Invalid VideoPort object");
|
|
ASSERTDX(peDxDirectDraw == peDxVideoPort->peDxDirectDraw,
|
|
"Surface, VideoPort, and DirectDraw objects don't match");
|
|
|
|
GetPolarityInInfo.lpVideoPortData = peDxVideoPort;
|
|
GetPolarityOutInfo.bPolarity = 0;
|
|
|
|
KeAcquireSpinLock(&peDxDirectDraw->SpinLock, &OldIrql);
|
|
|
|
if ((peDxDirectDraw->bLost) ||
|
|
(peDxVideoPort->bLost))
|
|
{
|
|
KdPrint(("DxGetPolarity: Objects are lost\n"));
|
|
dwRet = DDERR_SURFACELOST;
|
|
}
|
|
else
|
|
{
|
|
if (peDxDirectDraw->DxApiInterface.DxGetPolarity)
|
|
{
|
|
dwRet = peDxDirectDraw->DxApiInterface.DxGetPolarity(
|
|
peDxDirectDraw->HwDeviceExtension,
|
|
&GetPolarityInInfo,
|
|
&GetPolarityOutInfo);
|
|
}
|
|
}
|
|
|
|
KeReleaseSpinLock(&peDxDirectDraw->SpinLock, OldIrql);
|
|
|
|
pGetPolarityOut->ddRVal = dwRet;
|
|
pGetPolarityOut->bPolarity = GetPolarityOutInfo.bPolarity;
|
|
}
|
|
}
|
|
|
|
/******************************Public*Routine******************************\
|
|
* VOID DxAddVpCaptureBuffer
|
|
*
|
|
* 01-Nov-1997 -by- smac
|
|
* Wrote it.
|
|
\**************************************************************************/
|
|
|
|
VOID
|
|
APIENTRY
|
|
DxAddVpCaptureBuffer(
|
|
DDADDVPCAPTUREBUFF* pAddCaptureBuff,
|
|
DWORD* pdwRet
|
|
)
|
|
{
|
|
DXOBJ* pDxObjCapture;
|
|
EDD_DXCAPTURE* peDxCapture;
|
|
EDD_DXVIDEOPORT* peDxVideoPort;
|
|
EDD_DXDIRECTDRAW* peDxDirectDraw;
|
|
DWORD dwTop;
|
|
KIRQL OldIrql;
|
|
|
|
*pdwRet = DDERR_INVALIDPARAMS;
|
|
if (pAddCaptureBuff == NULL)
|
|
{
|
|
return;
|
|
}
|
|
|
|
pDxObjCapture = (DXOBJ*) pAddCaptureBuff->hCapture;
|
|
if (pDxObjCapture != NULL)
|
|
{
|
|
peDxCapture = pDxObjCapture->peDxCapture;
|
|
|
|
ASSERTDX(pDxObjCapture->iDxType == DXT_CAPTURE,
|
|
"Invalid Capture object");
|
|
ASSERTDX(pAddCaptureBuff->pKEvent != NULL,
|
|
"No KEvent specified");
|
|
ASSERTDX(pAddCaptureBuff->pMDL != NULL,
|
|
"No MDL specified");
|
|
ASSERTDX((pAddCaptureBuff->dwFlags != 0 ) &&
|
|
!(pAddCaptureBuff->dwFlags & ~(DDADDBUFF_SYSTEMMEMORY|DDADDBUFF_NONLOCALVIDMEM|DDADDBUFF_INVERT)),
|
|
"Invalid flags specified");
|
|
ASSERTDX(pAddCaptureBuff->lpBuffInfo != NULL,
|
|
"lpBuffInfo not specified");
|
|
|
|
*pdwRet = DDERR_INVALIDOBJECT;
|
|
peDxVideoPort = peDxCapture->peDxVideoPort;
|
|
if( peDxVideoPort != NULL )
|
|
{
|
|
peDxDirectDraw = peDxVideoPort->peDxDirectDraw;
|
|
|
|
KeAcquireSpinLock(&peDxDirectDraw->SpinLock, &OldIrql);
|
|
|
|
if( !( peDxVideoPort->bLost ) &&
|
|
!( peDxCapture->bLost ) )
|
|
{
|
|
// Is the queue full?
|
|
|
|
dwTop = peDxCapture->dwTop;
|
|
if( ( peDxCapture->CaptureQueue[dwTop].flFlags & DD_DXCAPTUREBUFF_FLAG_IN_USE ) ||
|
|
!( peDxVideoPort->flFlags & DD_DXVIDEOPORT_FLAG_ON ) )
|
|
{
|
|
*pdwRet = DDERR_CURRENTLYNOTAVAIL;
|
|
}
|
|
else
|
|
{
|
|
// Save the new buffer in the queque
|
|
|
|
peDxCapture->CaptureQueue[dwTop].dwClientFlags =
|
|
pAddCaptureBuff->dwFlags;
|
|
peDxCapture->CaptureQueue[dwTop].pBuffMDL =
|
|
pAddCaptureBuff->pMDL;
|
|
peDxCapture->CaptureQueue[dwTop].pBuffKEvent =
|
|
pAddCaptureBuff->pKEvent;
|
|
peDxCapture->CaptureQueue[dwTop].lpBuffInfo =
|
|
(PVOID) pAddCaptureBuff->lpBuffInfo;
|
|
peDxCapture->CaptureQueue[dwTop].flFlags = DD_DXCAPTUREBUFF_FLAG_IN_USE;
|
|
peDxVideoPort->flFlags |= DD_DXVIDEOPORT_FLAG_CAPTURING;
|
|
|
|
if( ++(peDxCapture->dwTop) >= DXCAPTURE_MAX_CAPTURE_BUFFS )
|
|
{
|
|
peDxCapture->dwTop = 0;
|
|
}
|
|
*pdwRet = DD_OK;
|
|
}
|
|
}
|
|
KeReleaseSpinLock(&peDxDirectDraw->SpinLock, OldIrql);
|
|
}
|
|
}
|
|
}
|
|
|
|
/******************************Public*Routine******************************\
|
|
* VOID DxInternalFlushVpCaptureBuffs
|
|
*
|
|
* 12-Apr-1999 -by- smac
|
|
* Wrote it.
|
|
\**************************************************************************/
|
|
|
|
VOID
|
|
APIENTRY
|
|
DxInternalFlushVpCaptureBuffs(
|
|
EDD_DXDIRECTDRAW* peDxDirectDraw,
|
|
EDD_DXVIDEOPORT* peDxVideoPort,
|
|
EDD_DXCAPTURE* peDxCapture
|
|
)
|
|
{
|
|
DDTRANSFERININFO ddTransferIn;
|
|
DDTRANSFEROUTINFO ddTransferOut;
|
|
LPDDCAPBUFFINFO lpBuffInfo;
|
|
DWORD i;
|
|
|
|
// Turn off all video port capture if nobody else is capturing
|
|
|
|
if( peDxVideoPort->peDxCapture && ( peDxCapture->peDxCaptureNext == NULL ) )
|
|
{
|
|
peDxVideoPort->flFlags &= ~DD_DXVIDEOPORT_FLAG_CAPTURING;
|
|
}
|
|
|
|
// If a buffer is in the queue and the busmaster has not yet been
|
|
// initiated, clear it now so we don't do it. If the busmaster has
|
|
// already been initiated, we will tell the miniport to stop it now.
|
|
|
|
peDxCapture->dwTop = peDxCapture->dwBottom = 0;
|
|
for( i = 0; i < DXCAPTURE_MAX_CAPTURE_BUFFS; i++ )
|
|
{
|
|
if( peDxCapture->CaptureQueue[i].flFlags & DD_DXCAPTUREBUFF_FLAG_IN_USE )
|
|
{
|
|
if( peDxCapture->CaptureQueue[i].flFlags & DD_DXCAPTUREBUFF_FLAG_WAITING )
|
|
{
|
|
ddTransferIn.dwStartLine = 0;
|
|
ddTransferIn.dwEndLine = 0;
|
|
ddTransferIn.dwTransferFlags = DDTRANSFER_CANCEL;
|
|
ddTransferIn.lpDestMDL = NULL;
|
|
ddTransferIn.lpSurfaceData = NULL;
|
|
ddTransferIn.dwTransferID = ((ULONG_PTR)peDxCapture & ~0xf) + i;
|
|
|
|
if (peDxDirectDraw->DxApiInterface.DxTransfer)
|
|
{
|
|
peDxDirectDraw->DxApiInterface.DxTransfer(
|
|
peDxDirectDraw->HwDeviceExtension,
|
|
&ddTransferIn,
|
|
&ddTransferOut);
|
|
}
|
|
|
|
peDxCapture->CaptureQueue[i].peDxSurface->flFlags
|
|
&= ~DD_DXSURFACE_FLAG_TRANSFER;
|
|
}
|
|
|
|
lpBuffInfo = (LPDDCAPBUFFINFO) peDxCapture->CaptureQueue[i].lpBuffInfo;
|
|
lpBuffInfo->bPolarity = 0;
|
|
lpBuffInfo->dwFieldNumber = 0;
|
|
lpBuffInfo->ddRVal = (DWORD) DDERR_GENERIC;
|
|
peDxCapture->CaptureQueue[i].flFlags = 0;
|
|
|
|
KeSetEvent( peDxCapture->CaptureQueue[i].pBuffKEvent, 0, 0 );
|
|
}
|
|
}
|
|
}
|
|
|
|
/******************************Public*Routine******************************\
|
|
* VOID DxFlushVpCaptureBuffs
|
|
*
|
|
* 01-Nov-1997 -by- smac
|
|
* Wrote it.
|
|
\**************************************************************************/
|
|
|
|
VOID
|
|
APIENTRY
|
|
DxFlushVpCaptureBuffs(
|
|
DWORD** hCapture,
|
|
DWORD* pdwRet
|
|
)
|
|
{
|
|
DXOBJ* pDxObjCapture;
|
|
EDD_DXCAPTURE* peDxCapture;
|
|
EDD_DXVIDEOPORT* peDxVideoPort;
|
|
EDD_DXDIRECTDRAW* peDxDirectDraw;
|
|
KIRQL OldIrql;
|
|
|
|
*pdwRet = DDERR_INVALIDPARAMS;
|
|
if (hCapture == NULL)
|
|
{
|
|
return;
|
|
}
|
|
|
|
ASSERTDX(KeGetCurrentIrql() <= DISPATCH_LEVEL,
|
|
"DxFlushCaptureBuffs: Call less than or equl to DISPATCH_LEVEL (it accesses the dispatch table)");
|
|
|
|
pDxObjCapture = (DXOBJ*) (*hCapture);
|
|
if (pDxObjCapture != NULL)
|
|
{
|
|
peDxCapture = pDxObjCapture->peDxCapture;
|
|
peDxVideoPort = peDxCapture->peDxVideoPort;
|
|
peDxDirectDraw = peDxVideoPort->peDxDirectDraw;
|
|
|
|
KeAcquireSpinLock(&peDxDirectDraw->SpinLock, &OldIrql);
|
|
|
|
DxInternalFlushVpCaptureBuffs( peDxDirectDraw, peDxVideoPort, peDxCapture );
|
|
|
|
KeReleaseSpinLock(&peDxDirectDraw->SpinLock, OldIrql);
|
|
|
|
*pdwRet = DD_OK;
|
|
}
|
|
}
|
|
|
|
/******************************Public*Routine******************************\
|
|
* VOID DxIrqCallBack
|
|
*
|
|
* This routine is called by the miniport at interrupt time to notify us
|
|
* of interrupt-based events. We simply queue a DPC to handle the request
|
|
* at the more appropriate dispatch level, instead of interrupt level that
|
|
* we're currently at.
|
|
*
|
|
* 14-Apr-1997 -by- J. Andrew Goossen [andrewgo]
|
|
* Wrote it.
|
|
\**************************************************************************/
|
|
|
|
VOID
|
|
APIENTRY
|
|
DxIrqCallBack(
|
|
DX_IRQDATA* pIrqData
|
|
)
|
|
{
|
|
EDD_DXDIRECTDRAW* peDxDirectDraw;
|
|
|
|
// We always tell the miniport to call us back with the pointer to
|
|
// &peDxDirectDraw->IrqData, so we can get back to the original
|
|
// peDxDirectDraw by subtracting the offset. If we ever need to
|
|
// change this in the future, we can simply add a field to DX_IRQDATA
|
|
// to point to the context:
|
|
|
|
peDxDirectDraw = (EDD_DXDIRECTDRAW*)
|
|
((BYTE*) pIrqData - offsetof(EDD_DXDIRECTDRAW, IrqData));
|
|
|
|
// It's okay if KeInsertQueueDpc fails because the same DPC for a
|
|
// previous interrupt is still queued -- the miniport always ORs
|
|
// its interrupt flags into pIrqData->dwIrqflags.
|
|
|
|
KeInsertQueueDpc(&peDxDirectDraw->EventDpc, pIrqData, NULL);
|
|
}
|
|
|
|
/******************************Public*Routine******************************\
|
|
* VOID DxGetIrqFlags
|
|
*
|
|
* Out interrupt processing code runs at DPC level, and can be interrupt
|
|
* by an ISR. Consequently, when we look at the interrupt status, we
|
|
* must synchronize with the ISR. This is accomplished by having
|
|
* VideoPortSynchronizeExecution (which does a KeSynchronizeExecution)
|
|
* call-back to this routine.
|
|
*
|
|
* All we do here is copy the flags to the device extension (actually,
|
|
* we use the EDD_DXDIRECTDRAW which is allocated one-to-one with the
|
|
* device extension).
|
|
*
|
|
* 14-Apr-1997 -by- J. Andrew Goossen [andrewgo]
|
|
* Wrote it.
|
|
\**************************************************************************/
|
|
|
|
BOOLEAN
|
|
DxGetIrqFlags(
|
|
PVOID pvContext
|
|
)
|
|
{
|
|
EDD_DXDIRECTDRAW* peDxDirectDraw;
|
|
|
|
peDxDirectDraw = (EDD_DXDIRECTDRAW*) pvContext;
|
|
|
|
// Copy the flags to a safe place:
|
|
|
|
peDxDirectDraw->dwSynchedIrqFlags = peDxDirectDraw->IrqData.dwIrqFlags;
|
|
|
|
// We have to zero the current flags because the miniport always ORs
|
|
// its flags in:
|
|
|
|
peDxDirectDraw->IrqData.dwIrqFlags = 0;
|
|
|
|
return(TRUE);
|
|
}
|
|
|
|
/******************************Public*Routine******************************\
|
|
* VOID DxEventDpc
|
|
*
|
|
* This routine does all the work of handling interrupt notification
|
|
* from the miniport. It makes the synchronous call-backs to anyone
|
|
* who has hooked the particular event.
|
|
*
|
|
* Note that to be synchronous we're making the call-backs at dispatch
|
|
* level. So if a callee doesn't require a truly synchronous notification,
|
|
* they should do nothing but kick off an event.
|
|
*
|
|
* 14-Apr-1997 -by- J. Andrew Goossen [andrewgo]
|
|
* Wrote it.
|
|
\**************************************************************************/
|
|
|
|
// We can't call KeSynchronizeExecution directly, because we don't
|
|
// have the device's interrupt object. Videoport.sys does, however.
|
|
// Unfortunately, 'video.h', which is used to access the videoport.sys
|
|
// routines, was never intended to be mixed with GDI and USER header
|
|
// files (among other problems, there are conflicts in the PEVENT and
|
|
// PVIDEO_POWER_MANAGEMENT structures). So we define what prototypes
|
|
// we need here:
|
|
|
|
extern "C" {
|
|
|
|
typedef enum VIDEO_SYNCHRONIZE_PRIORITY {
|
|
VpLowPriority,
|
|
VpMediumPriority,
|
|
VpHighPriority
|
|
} VIDEO_SYNCHRONIZE_PRIORITY, *PVIDEO_SYNCHRONIZE_PRIORITY;
|
|
|
|
typedef
|
|
BOOLEAN
|
|
(*PMINIPORT_SYNCHRONIZE_ROUTINE)(
|
|
PVOID Context
|
|
);
|
|
|
|
VOID
|
|
VideoPortSynchronizeExecution(
|
|
PVOID HwDeviceExtension,
|
|
VIDEO_SYNCHRONIZE_PRIORITY Priority,
|
|
PMINIPORT_SYNCHRONIZE_ROUTINE synchronizeRoutine,
|
|
PVOID Context
|
|
);
|
|
|
|
};
|
|
|
|
VOID
|
|
DxEventDpc(
|
|
PKDPC pDpc,
|
|
PVOID pvContext,
|
|
PVOID pvArgument1,
|
|
PVOID pvArgument2
|
|
)
|
|
{
|
|
EDD_DXDIRECTDRAW* peDxDirectDraw;
|
|
DX_IRQDATA* pIrqData;
|
|
DXAPI_EVENT* pDxEvent;
|
|
DWORD dwIrqFlags;
|
|
DWORD i;
|
|
|
|
pIrqData = (DX_IRQDATA*) pvArgument1;
|
|
peDxDirectDraw = (EDD_DXDIRECTDRAW*) pvContext;
|
|
|
|
// The ISR can be triggered even while we're processing the DPC for
|
|
// its previous interrupt. Consequently, we have to access the
|
|
// interrupt flags in a routine that is synchronized to the ISR
|
|
// routine.
|
|
//
|
|
// Note that we don't call KeSynchronizeExecution directly, because
|
|
// we don't have the device's interrupt object.
|
|
|
|
VideoPortSynchronizeExecution(peDxDirectDraw->HwDeviceExtension,
|
|
VpMediumPriority,
|
|
DxGetIrqFlags,
|
|
peDxDirectDraw);
|
|
|
|
dwIrqFlags = peDxDirectDraw->dwSynchedIrqFlags;
|
|
|
|
// We must acquire a spinlock while traversing the event list to
|
|
// protect against simultaneous modifications to the list.
|
|
|
|
KeAcquireSpinLockAtDpcLevel(&peDxDirectDraw->SpinLock);
|
|
|
|
// We call the callbacks registered by the client before we
|
|
// call the ones that we registered so we give the client a chance
|
|
// to skip fields before we execute our skip logic. This is why
|
|
// we keep two dispatch lists.
|
|
|
|
for (i = 0; i < NUM_DISPATCH_LISTS; i++)
|
|
{
|
|
for (pDxEvent = peDxDirectDraw->pDxEvent_DispatchList[i];
|
|
pDxEvent != NULL;
|
|
pDxEvent = pDxEvent->pDxEvent_Next)
|
|
{
|
|
if (pDxEvent->dwIrqFlag & dwIrqFlags)
|
|
{
|
|
pDxEvent->pfnCallBack(pDxEvent->dwEvent, pDxEvent->pContext, 0, 0);
|
|
}
|
|
}
|
|
}
|
|
|
|
// If it was a busmaster IRQ, take care of them as well
|
|
|
|
if (dwIrqFlags & DDIRQ_BUSMASTER)
|
|
{
|
|
for (pDxEvent = peDxDirectDraw->pDxEvent_CaptureList;
|
|
pDxEvent != NULL;
|
|
pDxEvent = pDxEvent->pDxEvent_Next)
|
|
{
|
|
pDxEvent->pfnCallBack(pDxEvent->dwEvent, pDxEvent->pContext, 0, 0);
|
|
}
|
|
}
|
|
|
|
KeReleaseSpinLockFromDpcLevel(&peDxDirectDraw->SpinLock);
|
|
}
|
|
|
|
/******************************Public*Routine******************************\
|
|
* VOID vDxFlip
|
|
*
|
|
* Assumes the spinlock is held.
|
|
*
|
|
* 14-Apr-1997 -by- J. Andrew Goossen [andrewgo]
|
|
* Wrote it.
|
|
\**************************************************************************/
|
|
|
|
VOID
|
|
vDxFlip(
|
|
EDD_DXVIDEOPORT* peDxVideoPort,
|
|
DWORD dwFlags
|
|
)
|
|
{
|
|
EDD_DXDIRECTDRAW* peDxDirectDraw;
|
|
DWORD iOldVideo;
|
|
DWORD iOldVbi;
|
|
DWORD iOldOverlay;
|
|
DWORD iNewVideo;
|
|
DWORD iNewVbi;
|
|
DWORD iNewOverlay;
|
|
DDFLIPVIDEOPORTINFO FlipVideoPortInfo;
|
|
DDFLIPOVERLAYINFO FlipOverlayInfo;
|
|
DWORD dwRet;
|
|
DWORD dwTemp;
|
|
|
|
ASSERTDX(KeGetCurrentIrql() == DISPATCH_LEVEL, "Expected held spinlock");
|
|
|
|
peDxDirectDraw = peDxVideoPort->peDxDirectDraw;
|
|
|
|
if( dwFlags == DDVPFLIP_VBI )
|
|
{
|
|
if (peDxVideoPort->cAutoflipVbi != 0)
|
|
{
|
|
// Flip videoport VBI surface:
|
|
|
|
iOldVbi = peDxVideoPort->iCurrentVbi;
|
|
iNewVbi = iOldVbi + 1;
|
|
if (iNewVbi >= peDxVideoPort->cAutoflipVbi)
|
|
iNewVbi = 0;
|
|
peDxVideoPort->iCurrentVbi = iNewVbi;
|
|
|
|
FlipVideoPortInfo.lpVideoPortData
|
|
= peDxVideoPort;
|
|
FlipVideoPortInfo.lpCurrentSurface
|
|
= peDxVideoPort->apeDxSurfaceVbi[iOldVbi];
|
|
FlipVideoPortInfo.lpTargetSurface
|
|
= peDxVideoPort->apeDxSurfaceVbi[iNewVbi];
|
|
FlipVideoPortInfo.dwFlipVPFlags = DDVPFLIP_VBI;
|
|
|
|
if (peDxDirectDraw->DxApiInterface.DxFlipVideoPort)
|
|
{
|
|
dwRet = peDxDirectDraw->DxApiInterface.DxFlipVideoPort(
|
|
peDxDirectDraw->HwDeviceExtension,
|
|
&FlipVideoPortInfo,
|
|
NULL);
|
|
}
|
|
}
|
|
}
|
|
|
|
else if( dwFlags == DDVPFLIP_VIDEO )
|
|
{
|
|
if (peDxVideoPort->cAutoflipVideo != 0)
|
|
{
|
|
// Flip videoport video surface:
|
|
|
|
iOldVideo = peDxVideoPort->iCurrentVideo;
|
|
iNewVideo = iOldVideo + 1;
|
|
if (iNewVideo >= peDxVideoPort->cAutoflipVideo)
|
|
iNewVideo = 0;
|
|
peDxVideoPort->iCurrentVideo = iNewVideo;
|
|
|
|
FlipVideoPortInfo.lpVideoPortData
|
|
= peDxVideoPort;
|
|
FlipVideoPortInfo.lpCurrentSurface
|
|
= peDxVideoPort->apeDxSurfaceVideo[iOldVideo];
|
|
FlipVideoPortInfo.lpTargetSurface
|
|
= peDxVideoPort->apeDxSurfaceVideo[iNewVideo];
|
|
FlipVideoPortInfo.dwFlipVPFlags
|
|
= DDVPFLIP_VIDEO;
|
|
|
|
if (peDxDirectDraw->DxApiInterface.DxFlipVideoPort)
|
|
{
|
|
dwRet = peDxDirectDraw->DxApiInterface.DxFlipVideoPort(
|
|
peDxDirectDraw->HwDeviceExtension,
|
|
&FlipVideoPortInfo,
|
|
NULL);
|
|
}
|
|
|
|
// Flip overlay surface:
|
|
|
|
if( ( peDxVideoPort->apeDxSurfaceVideo[0] != NULL ) &&
|
|
( peDxVideoPort->apeDxSurfaceVideo[0]->ddsCaps & DDSCAPS_OVERLAY ) &&
|
|
( ( peDxVideoPort->apeDxSurfaceVideo[0]->dwOverlayFlags & DDOVER_AUTOFLIP ) ||
|
|
( peDxVideoPort->bSoftwareAutoflip ) ) )
|
|
{
|
|
// If there are two surfaces, flip to the opposite surface. If
|
|
// there are more than two surfaces, flip to dwNumAutoflip - 2.
|
|
|
|
dwTemp = 1;
|
|
if( peDxVideoPort->cAutoflipVideo != 2 )
|
|
{
|
|
dwTemp++;
|
|
}
|
|
dwTemp = peDxVideoPort->iCurrentVideo +
|
|
peDxVideoPort->cAutoflipVideo - dwTemp;
|
|
if( dwTemp >= peDxVideoPort->cAutoflipVideo )
|
|
{
|
|
dwTemp -= peDxVideoPort->cAutoflipVideo;
|
|
}
|
|
|
|
FlipOverlayInfo.lpTargetSurface
|
|
= peDxVideoPort->apeDxSurfaceVideo[dwTemp];
|
|
if( dwTemp == 0 )
|
|
{
|
|
dwTemp = peDxVideoPort->cAutoflipVideo;
|
|
}
|
|
FlipOverlayInfo.lpCurrentSurface
|
|
= peDxVideoPort->apeDxSurfaceVideo[--dwTemp];
|
|
FlipOverlayInfo.dwFlags = 0;
|
|
|
|
if (peDxDirectDraw->DxApiInterface.DxFlipOverlay)
|
|
{
|
|
dwRet = peDxDirectDraw->DxApiInterface.DxFlipOverlay(
|
|
peDxDirectDraw->HwDeviceExtension,
|
|
&FlipOverlayInfo,
|
|
NULL);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/******************************Public*Routine******************************\
|
|
* VOID vDxBob
|
|
*
|
|
* Assumes the spinlock is held.
|
|
*
|
|
* 14-Apr-1997 -by- J. Andrew Goossen [andrewgo]
|
|
* Wrote it.
|
|
\**************************************************************************/
|
|
|
|
VOID
|
|
vDxBob(
|
|
EDD_DXVIDEOPORT* peDxVideoPort
|
|
)
|
|
{
|
|
EDD_DXDIRECTDRAW* peDxDirectDraw;
|
|
DDBOBNEXTFIELDINFO BobNextFieldInfo;
|
|
DWORD dwRet;
|
|
DWORD dwTemp;
|
|
|
|
ASSERTDX(KeGetCurrentIrql() == DISPATCH_LEVEL, "Expected held spinlock");
|
|
|
|
peDxDirectDraw = peDxVideoPort->peDxDirectDraw;
|
|
|
|
// Get the current surface handle. This is tricky because
|
|
// dwCurrentBuffer tells us which surface the video port is
|
|
// writting to - not which surface has the overlay. Therefore,
|
|
// we re-create the algorithm used in DoFlip to get the surface.
|
|
|
|
if( peDxVideoPort->flFlags & DD_DXVIDEOPORT_FLAG_AUTOFLIP )
|
|
{
|
|
dwTemp = 1;
|
|
if( peDxVideoPort->cAutoflipVideo != 2 )
|
|
{
|
|
dwTemp++;
|
|
}
|
|
dwTemp = peDxVideoPort->iCurrentVideo +
|
|
peDxVideoPort->cAutoflipVideo - dwTemp;
|
|
if( dwTemp >= peDxVideoPort->cAutoflipVideo )
|
|
{
|
|
dwTemp -= peDxVideoPort->cAutoflipVideo;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
dwTemp = 0;
|
|
}
|
|
|
|
BobNextFieldInfo.lpSurface = peDxVideoPort->apeDxSurfaceVideo[dwTemp];
|
|
|
|
if (peDxDirectDraw->DxApiInterface.DxBobNextField)
|
|
{
|
|
dwRet = peDxDirectDraw->DxApiInterface.DxBobNextField(
|
|
peDxDirectDraw->HwDeviceExtension,
|
|
&BobNextFieldInfo,
|
|
NULL);
|
|
}
|
|
}
|
|
|
|
/******************************Public*Routine******************************\
|
|
* VOID vDxSkip
|
|
*
|
|
* Assumes the spinlock is held.
|
|
*
|
|
* 14-Apr-1997 -by- J. Andrew Goossen [andrewgo]
|
|
* Wrote it.
|
|
\**************************************************************************/
|
|
|
|
VOID
|
|
vDxSkip(
|
|
EDD_DXVIDEOPORT* peDxVideoPort,
|
|
DWORD dwFlags
|
|
)
|
|
{
|
|
EDD_DXDIRECTDRAW* peDxDirectDraw;
|
|
DDSKIPNEXTFIELDINFO SkipNextFieldInfo;
|
|
DWORD dwRet;
|
|
|
|
ASSERTDX(KeGetCurrentIrql() == DISPATCH_LEVEL, "Expected held spinlock");
|
|
|
|
peDxDirectDraw = peDxVideoPort->peDxDirectDraw;
|
|
|
|
if (peDxDirectDraw->DxApiInterface.DxSkipNextField)
|
|
{
|
|
SkipNextFieldInfo.lpVideoPortData = peDxVideoPort;
|
|
SkipNextFieldInfo.dwSkipFlags = dwFlags;
|
|
|
|
dwRet = peDxDirectDraw->DxApiInterface.DxSkipNextField(
|
|
peDxDirectDraw->HwDeviceExtension,
|
|
&SkipNextFieldInfo,
|
|
NULL);
|
|
}
|
|
}
|
|
|
|
/******************************Public*Routine******************************\
|
|
* VOID IRQCapture
|
|
*
|
|
* This routine initiates video/VBI capture based on a video port VSYNC.
|
|
*
|
|
* NOTE: The spinlock is already held.
|
|
*
|
|
* 10-Jan-1998 -by- Scott MacDonald [smac]
|
|
* Wrote it.
|
|
\**************************************************************************/
|
|
|
|
VOID IRQCapture(
|
|
EDD_DXVIDEOPORT* peDxVideoPort,
|
|
EDD_DXDIRECTDRAW* peDxDirectDraw
|
|
)
|
|
{
|
|
DDGETCURRENTAUTOFLIPININFO ddAutoflipInInfo;
|
|
DDGETCURRENTAUTOFLIPOUTINFO ddAutoflipOutInfo;
|
|
EDD_DXCAPTURE* peDxCapture;
|
|
LPDDCAPBUFFINFO lpBuffInfo;
|
|
DXCAPTUREBUFF* lpBuff;
|
|
DDTRANSFERININFO ddTransferIn;
|
|
DDTRANSFEROUTINFO ddTransferOut;
|
|
ULONGLONG ullTimeStamp;
|
|
PULONGLONG pullTemp;
|
|
ULONGLONG rate;
|
|
DWORD dwVBIIndex;
|
|
DWORD dwVideoIndex;
|
|
BOOL bStarved = TRUE;
|
|
DWORD ddRVal;
|
|
|
|
// Get the current time stamp
|
|
|
|
ullTimeStamp = (ULONGLONG)KeQueryPerformanceCounter((PLARGE_INTEGER)&rate).QuadPart;
|
|
ullTimeStamp = (ullTimeStamp & 0xFFFFFFFF00000000) / rate * 10000000 +
|
|
(ullTimeStamp & 0xFFFFFFFF) * 10000000 / rate;
|
|
|
|
// If either the VBI or video is being hardware autoflipped, figure out
|
|
// the correct buffers.
|
|
|
|
dwVBIIndex = 0;
|
|
dwVideoIndex = 0;
|
|
if( ( ( peDxVideoPort->cAutoflipVbi > 1 ) &&
|
|
!( peDxVideoPort->flFlags & DD_DXVIDEOPORT_FLAG_AUTOFLIP_VBI ) ) ||
|
|
( ( peDxVideoPort->cAutoflipVideo > 1 ) &&
|
|
!( peDxVideoPort->flFlags & DD_DXVIDEOPORT_FLAG_AUTOFLIP ) ) )
|
|
{
|
|
ddAutoflipInInfo.lpVideoPortData = peDxVideoPort;
|
|
ddAutoflipOutInfo.dwSurfaceIndex = 0;
|
|
if (peDxDirectDraw->DxApiInterface.DxGetCurrentAutoflip)
|
|
{
|
|
ddRVal = peDxDirectDraw->DxApiInterface.DxGetCurrentAutoflip(
|
|
peDxDirectDraw->HwDeviceExtension,
|
|
&ddAutoflipInInfo,
|
|
&ddAutoflipOutInfo);
|
|
}
|
|
if( peDxVideoPort->cAutoflipVideo > 0 )
|
|
{
|
|
dwVideoIndex = ddAutoflipOutInfo.dwSurfaceIndex;
|
|
if( dwVideoIndex-- == 0 )
|
|
{
|
|
dwVideoIndex = peDxVideoPort->cAutoflipVideo - 1;
|
|
}
|
|
}
|
|
if( peDxVideoPort->cAutoflipVbi > 0 )
|
|
{
|
|
dwVBIIndex = ddAutoflipOutInfo.dwVBISurfaceIndex;
|
|
if( dwVBIIndex-- == 0 )
|
|
{
|
|
dwVBIIndex = peDxVideoPort->cAutoflipVbi - 1;
|
|
}
|
|
}
|
|
}
|
|
|
|
// Which is the surface containing the most recent VBI data?
|
|
|
|
if( ( peDxVideoPort->cAutoflipVbi > 0 ) &&
|
|
( peDxVideoPort->flFlags & DD_DXVIDEOPORT_FLAG_AUTOFLIP_VBI ) )
|
|
{
|
|
dwVBIIndex = peDxVideoPort->iCurrentVbi;
|
|
if( dwVBIIndex-- == 0 )
|
|
{
|
|
dwVBIIndex = peDxVideoPort->cAutoflipVbi - 1;
|
|
}
|
|
}
|
|
|
|
// Which is the surface containing the most recent video data?
|
|
|
|
if( ( peDxVideoPort->cAutoflipVideo > 0 ) &&
|
|
( peDxVideoPort->flFlags & DD_DXVIDEOPORT_FLAG_AUTOFLIP ) )
|
|
{
|
|
dwVideoIndex = peDxVideoPort->iCurrentVideo;
|
|
if( dwVideoIndex-- == 0 )
|
|
{
|
|
dwVideoIndex = peDxVideoPort->cAutoflipVideo - 1;
|
|
}
|
|
}
|
|
|
|
// Look at each capture device to determine if it has to do a busmaster
|
|
// or not
|
|
|
|
peDxCapture = peDxVideoPort->peDxCapture;
|
|
while( peDxCapture != NULL )
|
|
{
|
|
if( ( peDxCapture->CaptureQueue[peDxCapture->dwBottom].flFlags & DD_DXCAPTUREBUFF_FLAG_IN_USE ) &&
|
|
!( peDxCapture->CaptureQueue[peDxCapture->dwBottom].flFlags & DD_DXCAPTUREBUFF_FLAG_WAITING ) )
|
|
{
|
|
bStarved = FALSE;
|
|
|
|
if( peDxCapture->dwCaptureCountDown-- == 1 )
|
|
{
|
|
peDxCapture->dwCaptureCountDown = peDxCapture->dwCaptureEveryNFields;
|
|
lpBuff = &(peDxCapture->CaptureQueue[peDxCapture->dwBottom]);
|
|
|
|
// Fill in the buffer info
|
|
|
|
lpBuffInfo = (LPDDCAPBUFFINFO) lpBuff->lpBuffInfo;
|
|
lpBuffInfo->dwFieldNumber = peDxVideoPort->dwCurrentField;
|
|
pullTemp = (PULONGLONG) &(lpBuffInfo->liTimeStamp);
|
|
*pullTemp = ullTimeStamp;
|
|
|
|
// Tell mini port to do the transfer
|
|
|
|
ddTransferIn.dwStartLine = peDxCapture->dwStartLine;
|
|
ddTransferIn.dwEndLine = peDxCapture->dwEndLine;
|
|
ddTransferIn.dwTransferFlags = lpBuff->dwClientFlags;
|
|
if( peDxVideoPort->flFlags & DD_DXVIDEOPORT_FLAG_HALFLINES )
|
|
{
|
|
ddTransferIn.dwTransferFlags |= DDTRANSFER_HALFLINES;
|
|
}
|
|
ddTransferIn.lpDestMDL = lpBuff->pBuffMDL;
|
|
if( peDxCapture->flFlags & DD_DXCAPTURE_FLAG_VIDEO )
|
|
{
|
|
ddTransferIn.lpSurfaceData = peDxVideoPort->apeDxSurfaceVideo[dwVideoIndex];
|
|
}
|
|
else
|
|
{
|
|
ddTransferIn.lpSurfaceData = peDxVideoPort->apeDxSurfaceVbi[dwVBIIndex];
|
|
}
|
|
|
|
if (ddTransferIn.lpSurfaceData)
|
|
{
|
|
ddTransferIn.dwTransferID = (ULONG_PTR) peDxCapture;
|
|
ddTransferIn.dwTransferID &= ~0xf;
|
|
ddTransferIn.dwTransferID |= peDxCapture->dwBottom;
|
|
|
|
ddRVal = DDERR_UNSUPPORTED;
|
|
if (peDxDirectDraw->DxApiInterface.DxTransfer)
|
|
{
|
|
ddRVal = peDxDirectDraw->DxApiInterface.DxTransfer(
|
|
peDxDirectDraw->HwDeviceExtension,
|
|
&ddTransferIn,
|
|
&ddTransferOut);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
ddRVal = DDERR_INVALIDPARAMS;
|
|
}
|
|
|
|
lpBuffInfo->ddRVal = ddRVal;
|
|
if( ddRVal != DD_OK )
|
|
{
|
|
// Set the KEvent now
|
|
|
|
KeSetEvent( lpBuff->pBuffKEvent, 0, 0 );
|
|
lpBuff->flFlags = 0;
|
|
lpBuff->pBuffKEvent = 0;
|
|
}
|
|
else
|
|
{
|
|
// Mark the lucky surface as doing a transfer
|
|
|
|
lpBuffInfo->bPolarity = ddTransferOut.dwBufferPolarity;
|
|
lpBuff->peDxSurface = (EDD_DXSURFACE*) ddTransferIn.lpSurfaceData;
|
|
lpBuff->peDxSurface->flFlags |= DD_DXSURFACE_FLAG_TRANSFER;
|
|
lpBuff->flFlags |= DD_DXCAPTUREBUFF_FLAG_WAITING;
|
|
}
|
|
|
|
// Next time use the next buffer
|
|
|
|
if( ++( peDxCapture->dwBottom ) >= DXCAPTURE_MAX_CAPTURE_BUFFS )
|
|
{
|
|
peDxCapture->dwBottom = 0;
|
|
}
|
|
}
|
|
}
|
|
peDxCapture = peDxCapture->peDxCaptureNext;
|
|
}
|
|
|
|
if( bStarved )
|
|
{
|
|
peDxVideoPort->flFlags &= ~DD_DXVIDEOPORT_FLAG_CAPTURING;
|
|
}
|
|
}
|
|
|
|
/******************************Public*Routine******************************\
|
|
* VOID DxAutoflipDpc
|
|
*
|
|
* This routine handles 'software autoflipping' and is called at dispatch
|
|
* level when the miniport's videoport interrupt is triggered. This routine
|
|
* can't be kept in 'win32k.sys' because it needs to be non-pageable.
|
|
*
|
|
* NOTE: The spinlock is already held.
|
|
*
|
|
* 14-Apr-1997 -by- J. Andrew Goossen [andrewgo]
|
|
* Wrote it.
|
|
\**************************************************************************/
|
|
|
|
VOID
|
|
APIENTRY
|
|
DxAutoflipDpc(
|
|
DWORD dwEvent,
|
|
PVOID pContext,
|
|
DWORD dwParam1,
|
|
DWORD dwParam2
|
|
)
|
|
{
|
|
EDD_DXDIRECTDRAW* peDxDirectDraw;
|
|
EDD_DXVIDEOPORT* peDxVideoPort;
|
|
DWORD dwCurrentField;
|
|
BOOL bAdjustFirstWeave;
|
|
BOOL bSkipped;
|
|
BOOL bFlipped;
|
|
|
|
ASSERTDX(KeGetCurrentIrql() == DISPATCH_LEVEL, "Expected dispath level");
|
|
ASSERTDX(dwEvent == DDEVENT_VP_VSYNC, "Expected VP_VSYNC event");
|
|
|
|
peDxVideoPort = (EDD_DXVIDEOPORT*) pContext;
|
|
peDxDirectDraw = peDxVideoPort->peDxDirectDraw;
|
|
|
|
// If capturing, do it now
|
|
|
|
if( ( peDxVideoPort->flFlags & DD_DXVIDEOPORT_FLAG_CAPTURING ) &&
|
|
( peDxVideoPort->flFlags & DD_DXVIDEOPORT_FLAG_ON ) )
|
|
{
|
|
IRQCapture(peDxVideoPort, peDxDirectDraw);
|
|
}
|
|
|
|
// Do we need to notify user mode that a vsync occurred?
|
|
|
|
if ((peDxVideoPort->pNotifyEvent != NULL) &&
|
|
(peDxVideoPort->pNotifyBuffer != NULL) &&
|
|
(1 == InterlockedExchange( &peDxVideoPort->pNotifyBuffer->lDone, 0 ) ) )
|
|
{
|
|
DDGETCURRENTAUTOFLIPININFO ddAutoflipInInfo;
|
|
DDGETCURRENTAUTOFLIPOUTINFO ddAutoflipOutInfo;
|
|
|
|
ULONGLONG ullTimeStamp;
|
|
ULONGLONG rate;
|
|
UINT dwVideoIndex;
|
|
|
|
// Fill in the buffer
|
|
|
|
peDxVideoPort->pNotifyBuffer->lField = -1;
|
|
if ( peDxDirectDraw->DxApiInterface.DxGetPolarity )
|
|
{
|
|
DDGETPOLARITYININFO ddPolarityInInfo;
|
|
DDGETPOLARITYOUTINFO ddPolarityOutInfo;
|
|
ddPolarityInInfo.lpVideoPortData = peDxVideoPort;
|
|
peDxDirectDraw->DxApiInterface.DxGetPolarity( peDxDirectDraw->HwDeviceExtension,
|
|
&ddPolarityInInfo, &ddPolarityOutInfo );
|
|
peDxVideoPort->pNotifyBuffer->lField = ddPolarityOutInfo.bPolarity ? 1 : 0;
|
|
}
|
|
|
|
dwVideoIndex = 0;
|
|
if (peDxVideoPort->cAutoflipVideo > 1 )
|
|
{
|
|
if (peDxVideoPort->flFlags & DD_DXVIDEOPORT_FLAG_AUTOFLIP)
|
|
{
|
|
dwVideoIndex = peDxVideoPort->iCurrentVideo;
|
|
}
|
|
else
|
|
{
|
|
ddAutoflipInInfo.lpVideoPortData = peDxVideoPort;
|
|
ddAutoflipOutInfo.dwSurfaceIndex = 0;
|
|
if (peDxDirectDraw->DxApiInterface.DxGetCurrentAutoflip)
|
|
{
|
|
peDxDirectDraw->DxApiInterface.DxGetCurrentAutoflip(
|
|
peDxDirectDraw->HwDeviceExtension,
|
|
&ddAutoflipInInfo,
|
|
&ddAutoflipOutInfo);
|
|
}
|
|
dwVideoIndex = ddAutoflipOutInfo.dwSurfaceIndex;
|
|
}
|
|
if( dwVideoIndex-- == 0 )
|
|
{
|
|
dwVideoIndex = peDxVideoPort->cAutoflipVideo - 1;
|
|
}
|
|
}
|
|
peDxVideoPort->pNotifyBuffer->dwSurfaceIndex = dwVideoIndex;
|
|
|
|
ullTimeStamp = (ULONGLONG)KeQueryPerformanceCounter((PLARGE_INTEGER)&rate).QuadPart;
|
|
ullTimeStamp = (ullTimeStamp & 0xFFFFFFFF00000000) / rate * 10000000 +
|
|
(ullTimeStamp & 0xFFFFFFFF) * 10000000 / rate;
|
|
*((ULONGLONG*)&(peDxVideoPort->pNotifyBuffer->ApproximateTimeStamp)) = ullTimeStamp;
|
|
|
|
KeSetEvent (peDxVideoPort->pNotifyEvent, IO_NO_INCREMENT, FALSE);
|
|
}
|
|
|
|
// Note that it is okay to modify 'dwCurrentField' outside of a spinlock,
|
|
// as the only other routine that modifies it is 'DxSetFieldNumber' and
|
|
// it always does an atomic write.
|
|
|
|
dwCurrentField = InterlockedIncrement((LONG*) &peDxVideoPort->dwCurrentField);
|
|
|
|
// Check for posted state changes
|
|
|
|
bAdjustFirstWeave = FALSE;
|
|
if( peDxVideoPort->flFlags & DD_DXVIDEOPORT_FLAG_NEW_STATE )
|
|
{
|
|
if( peDxVideoPort->dwSetStateField-- == 0 )
|
|
{
|
|
peDxVideoPort->flFlags &= ~DD_DXVIDEOPORT_FLAG_NEW_STATE;
|
|
|
|
// If we'll be weaving, we need to make sure that
|
|
// we only flip at the beginning of a frame and not
|
|
// during the middle. We assume that we're told to
|
|
// star weaving at the beginning of the frame.
|
|
|
|
if( ( peDxVideoPort->dwSetStateState & DDSTATE_WEAVE ) &&
|
|
!( peDxVideoPort->flFlags & DD_DXVIDEOPORT_FLAG_FLIP_NEXT ) )
|
|
{
|
|
bAdjustFirstWeave = TRUE;
|
|
peDxVideoPort->flFlags |= DD_DXVIDEOPORT_FLAG_FLIP_NEXT;
|
|
}
|
|
EffectStateChange( peDxVideoPort, NULL, peDxVideoPort->dwSetStateState );
|
|
}
|
|
}
|
|
|
|
// Check the skip logic
|
|
|
|
bSkipped = FALSE;
|
|
if( peDxVideoPort->flFlags & DD_DXVIDEOPORT_FLAG_SKIP_SET )
|
|
{
|
|
if( peDxVideoPort->dwFieldToSkip-- == 0 )
|
|
{
|
|
// Tell the MiniPort to skip the next field
|
|
|
|
vDxSkip( peDxVideoPort, DDSKIP_SKIPNEXT );
|
|
peDxVideoPort->flFlags |= DD_DXVIDEOPORT_FLAG_SKIPPED_LAST;
|
|
bSkipped = TRUE;
|
|
|
|
if( peDxVideoPort->flFlags & DD_DXVIDEOPORT_FLAG_NEXT_SKIP_SET )
|
|
{
|
|
peDxVideoPort->dwFieldToSkip = peDxVideoPort->dwNextFieldToSkip;
|
|
peDxVideoPort->flFlags &= ~DD_DXVIDEOPORT_FLAG_NEXT_SKIP_SET;
|
|
}
|
|
else
|
|
{
|
|
peDxVideoPort->flFlags &= ~DD_DXVIDEOPORT_FLAG_SKIP_SET;
|
|
}
|
|
}
|
|
else if( peDxVideoPort->flFlags & DD_DXVIDEOPORT_FLAG_NEXT_SKIP_SET )
|
|
{
|
|
peDxVideoPort->dwNextFieldToSkip--;
|
|
}
|
|
}
|
|
if( ( peDxVideoPort->flFlags & DD_DXVIDEOPORT_FLAG_SKIPPED_LAST ) && !bSkipped )
|
|
{
|
|
// Tell the MiniPort to un-skip the next field
|
|
|
|
vDxSkip( peDxVideoPort, DDSKIP_ENABLENEXT );
|
|
peDxVideoPort->flFlags &= ~DD_DXVIDEOPORT_FLAG_SKIPPED_LAST;
|
|
|
|
// This next part is a hack.We keep track of which fields
|
|
// to flip on in weave mode during the ISR, but what if we
|
|
// happen to miss an IRQ (due to DOS box, etc.)? We can't
|
|
// use to polarity to re-sync because field skipping screws
|
|
// that up, so this code assume that the repeat field will
|
|
// always be the last field of a frame and so the following
|
|
// field will be the first field. This will make it re-sync
|
|
// if we ever miss an IRQ.
|
|
|
|
peDxVideoPort->flFlags |= DD_DXVIDEOPORT_FLAG_FLIP_NEXT;
|
|
}
|
|
|
|
// Now do all of the autoflipping
|
|
|
|
if( peDxVideoPort->flFlags & (DD_DXVIDEOPORT_FLAG_AUTOFLIP|
|
|
DD_DXVIDEOPORT_FLAG_AUTOFLIP_VBI|DD_DXVIDEOPORT_FLAG_BOB ) )
|
|
{
|
|
// Check for autoflipping the VBI surface in which case we
|
|
// don't care about the skip logic
|
|
|
|
if( peDxVideoPort->flFlags & DD_DXVIDEOPORT_FLAG_AUTOFLIP_VBI )
|
|
{
|
|
if( peDxVideoPort->flFlags & DD_DXVIDEOPORT_FLAG_VBI_INTERLEAVED )
|
|
{
|
|
if( peDxVideoPort->flFlags & DD_DXVIDEOPORT_FLAG_FLIP_NEXT_VBI )
|
|
{
|
|
peDxVideoPort->flFlags &= ~DD_DXVIDEOPORT_FLAG_FLIP_NEXT_VBI;
|
|
vDxFlip( peDxVideoPort, DDVPFLIP_VBI );
|
|
}
|
|
else
|
|
{
|
|
peDxVideoPort->flFlags |= DD_DXVIDEOPORT_FLAG_FLIP_NEXT_VBI;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
peDxVideoPort->flFlags &= ~DD_DXVIDEOPORT_FLAG_FLIP_NEXT_VBI;
|
|
vDxFlip( peDxVideoPort, DDVPFLIP_VBI );
|
|
}
|
|
}
|
|
|
|
// Autoflip the vhe video if we are not skipping this field
|
|
|
|
if( !bSkipped )
|
|
{
|
|
bFlipped = FALSE;
|
|
if( peDxVideoPort->flFlags & DD_DXVIDEOPORT_FLAG_AUTOFLIP )
|
|
{
|
|
if( peDxVideoPort->dwVPFlags & DDVP_INTERLEAVE )
|
|
{
|
|
if( peDxVideoPort->flFlags & DD_DXVIDEOPORT_FLAG_FLIP_NEXT )
|
|
{
|
|
peDxVideoPort->flFlags &= ~DD_DXVIDEOPORT_FLAG_FLIP_NEXT;
|
|
if( !bAdjustFirstWeave )
|
|
{
|
|
vDxFlip( peDxVideoPort, DDVPFLIP_VIDEO );
|
|
bFlipped = TRUE;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
peDxVideoPort->flFlags |= DD_DXVIDEOPORT_FLAG_FLIP_NEXT;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
vDxFlip( peDxVideoPort, DDVPFLIP_VIDEO );
|
|
bFlipped = TRUE;
|
|
peDxVideoPort->flFlags &= ~DD_DXVIDEOPORT_FLAG_FLIP_NEXT;
|
|
}
|
|
}
|
|
|
|
// They may be bobbing even when not autoflipping
|
|
// (they may have one interleaved buffer that they
|
|
// use for bob - technically this is not a flip since
|
|
// only one surface is involved).
|
|
|
|
if( ( peDxVideoPort->flFlags & DD_DXVIDEOPORT_FLAG_BOB ) &&
|
|
!bFlipped )
|
|
{
|
|
vDxBob( peDxVideoPort );
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/******************************Public*Routine******************************\
|
|
* VOID DxBusmasterDpc
|
|
*
|
|
* This routine handles the video capture and is called when one of
|
|
* the buffers is filled. It figures out which one and then sets the
|
|
* compeletion event for that buffer.
|
|
*
|
|
* NOTE: The spinlock is already held.
|
|
*
|
|
* 10-Jan-1998 -by- Scott MacDonald [smac]
|
|
* Wrote it.
|
|
\**************************************************************************/
|
|
|
|
VOID
|
|
APIENTRY
|
|
DxBusmasterDpc(
|
|
DWORD dwEvent,
|
|
PVOID pContext,
|
|
DWORD dwParam1,
|
|
DWORD dwParam2
|
|
)
|
|
{
|
|
DDGETTRANSFERSTATUSOUTINFO ddGetTransferStatus;
|
|
EDD_DXVIDEOPORT* peDxVideoPort;
|
|
EDD_DXDIRECTDRAW* peDxDirectDraw;
|
|
EDD_DXCAPTURE* peDxCapture;
|
|
DWORD ddRVal;
|
|
ULONG_PTR dwTempId;
|
|
DWORD dwTempIndex;
|
|
|
|
// Call the miniport to get the transfer ID of the completed busmaster
|
|
|
|
ddRVal = DDERR_UNSUPPORTED;
|
|
peDxVideoPort = (EDD_DXVIDEOPORT*) pContext;
|
|
peDxDirectDraw = peDxVideoPort->peDxDirectDraw;
|
|
if (peDxDirectDraw->DxApiInterface.DxGetTransferStatus)
|
|
{
|
|
ddRVal = peDxDirectDraw->DxApiInterface.DxGetTransferStatus(
|
|
peDxDirectDraw->HwDeviceExtension,
|
|
NULL,
|
|
&ddGetTransferStatus);
|
|
}
|
|
if( ddRVal == DD_OK )
|
|
{
|
|
// Find the capture object. It may not even be associated with this
|
|
// video port if multiple vidoe ports exist in the system.
|
|
|
|
dwTempId = ddGetTransferStatus.dwTransferID & ~0xf;
|
|
peDxCapture = peDxVideoPort->peDxCapture;
|
|
while (peDxCapture && (((ULONG_PTR)peDxCapture & ~0xf) != dwTempId))
|
|
{
|
|
peDxCapture = peDxCapture->peDxCaptureNext;
|
|
}
|
|
|
|
if (peDxCapture != NULL)
|
|
{
|
|
// We've found the capture object
|
|
|
|
dwTempIndex = (DWORD)(ddGetTransferStatus.dwTransferID & 0xf);
|
|
if (peDxCapture->CaptureQueue[dwTempIndex].flFlags & DD_DXCAPTUREBUFF_FLAG_WAITING )
|
|
{
|
|
peDxCapture->CaptureQueue[dwTempIndex].flFlags = 0;
|
|
KeSetEvent(peDxCapture->CaptureQueue[dwTempIndex].pBuffKEvent, 0, 0);
|
|
}
|
|
|
|
// Mark the lucky surface as being done w/ the transfer
|
|
|
|
peDxCapture->CaptureQueue[dwTempIndex].peDxSurface->flFlags
|
|
&= ~DD_DXSURFACE_FLAG_TRANSFER;
|
|
peDxCapture->CaptureQueue[dwTempIndex].peDxSurface = NULL;
|
|
}
|
|
}
|
|
}
|
|
|
|
/******************************Public*Routine******************************\
|
|
* VOID DxAutoflipUpdate
|
|
*
|
|
* This routine handles 'software autoflipping' and is called at dispatch
|
|
* level when the miniport's videoport interrupt is triggered. This routine
|
|
* can't be kept in 'win32k.sys' because it needs to be non-pageable.
|
|
*
|
|
* 14-Apr-1997 -by- J. Andrew Goossen [andrewgo]
|
|
* Wrote it.
|
|
\**************************************************************************/
|
|
|
|
VOID
|
|
APIENTRY
|
|
DxAutoflipUpdate(
|
|
EDD_DXVIDEOPORT* peDxVideoPort,
|
|
EDD_DXSURFACE** apeDxSurfaceVideo,
|
|
ULONG cSurfacesVideo,
|
|
EDD_DXSURFACE** apeDxSurfaceVbi,
|
|
ULONG cSurfacesVbi
|
|
)
|
|
{
|
|
KIRQL OldIrql;
|
|
ULONG i;
|
|
|
|
KeAcquireSpinLock(&peDxVideoPort->peDxDirectDraw->SpinLock, &OldIrql);
|
|
|
|
peDxVideoPort->cAutoflipVideo = cSurfacesVideo;
|
|
for (i = 0; i < cSurfacesVideo; i++)
|
|
{
|
|
peDxVideoPort->apeDxSurfaceVideo[i] = apeDxSurfaceVideo[i];
|
|
peDxVideoPort->apeDxSurfaceVideo[i]->peDxVideoPort = peDxVideoPort;
|
|
}
|
|
peDxVideoPort->cAutoflipVbi = cSurfacesVbi;
|
|
for (i = 0; i < cSurfacesVbi; i++)
|
|
{
|
|
peDxVideoPort->apeDxSurfaceVbi[i] = apeDxSurfaceVbi[i];
|
|
peDxVideoPort->apeDxSurfaceVbi[i]->peDxVideoPort = peDxVideoPort;
|
|
}
|
|
|
|
KeReleaseSpinLock(&peDxVideoPort->peDxDirectDraw->SpinLock, OldIrql);
|
|
}
|
|
|
|
/******************************Public*Routine******************************\
|
|
* VOID DxLoseObject
|
|
*
|
|
* 14-Apr-1997 -by- J. Andrew Goossen [andrewgo]
|
|
* Wrote it.
|
|
\**************************************************************************/
|
|
|
|
VOID
|
|
APIENTRY
|
|
DxLoseObject(
|
|
VOID* pvObject,
|
|
LOTYPE loType
|
|
)
|
|
{
|
|
KIRQL OldIrql;
|
|
EDD_DXDIRECTDRAW* peDxDirectDraw;
|
|
EDD_DXVIDEOPORT* peDxVideoPort;
|
|
EDD_DXSURFACE* peDxSurface;
|
|
EDD_DXCAPTURE* peDxCapture;
|
|
DXAPI_EVENT* pDxEvent;
|
|
DDENABLEIRQINFO EnableIrqInfo;
|
|
DWORD dwRet;
|
|
|
|
switch (loType)
|
|
{
|
|
case LO_DIRECTDRAW:
|
|
peDxDirectDraw = (EDD_DXDIRECTDRAW*) pvObject;
|
|
|
|
peDxDirectDraw->peDirectDrawGlobal->peDxDirectDraw = NULL; // Passive
|
|
|
|
KeAcquireSpinLock(&peDxDirectDraw->SpinLock, &OldIrql);
|
|
|
|
peDxDirectDraw->bLost = TRUE;
|
|
peDxDirectDraw->peDirectDrawGlobal = NULL;
|
|
|
|
if (peDxDirectDraw->DxApiInterface.DxEnableIrq)
|
|
{
|
|
// Make sure all IRQs are disabled
|
|
|
|
EnableIrqInfo.dwIRQSources = 0;
|
|
EnableIrqInfo.dwLine = 0;
|
|
EnableIrqInfo.IRQCallback = NULL;
|
|
EnableIrqInfo.lpIRQData = NULL;
|
|
|
|
peDxDirectDraw->DxApiInterface.DxEnableIrq(
|
|
peDxDirectDraw->HwDeviceExtension,
|
|
&EnableIrqInfo,
|
|
NULL);
|
|
}
|
|
|
|
KeReleaseSpinLock(&peDxDirectDraw->SpinLock, OldIrql);
|
|
break;
|
|
|
|
case LO_VIDEOPORT:
|
|
peDxVideoPort = (EDD_DXVIDEOPORT*) pvObject;
|
|
peDxDirectDraw = peDxVideoPort->peDxDirectDraw;
|
|
|
|
peDxVideoPort->peVideoPort->peDxVideoPort = NULL; // Passive
|
|
|
|
KeAcquireSpinLock(&peDxDirectDraw->SpinLock, &OldIrql);
|
|
|
|
peDxVideoPort->bLost = TRUE;
|
|
peDxVideoPort->peVideoPort = NULL;
|
|
peDxVideoPort->peDxCapture = NULL;
|
|
|
|
KeReleaseSpinLock(&peDxDirectDraw->SpinLock, OldIrql);
|
|
break;
|
|
|
|
case LO_SURFACE:
|
|
peDxSurface = (EDD_DXSURFACE*) pvObject;
|
|
peDxDirectDraw = peDxSurface->peDxDirectDraw;
|
|
|
|
peDxSurface->peSurface->peDxSurface = NULL; // Passive
|
|
|
|
KeAcquireSpinLock(&peDxDirectDraw->SpinLock, &OldIrql);
|
|
|
|
peDxSurface->bLost = TRUE;
|
|
peDxSurface->peSurface = NULL;
|
|
peDxSurface->peDxVideoPort = NULL;
|
|
|
|
KeReleaseSpinLock(&peDxDirectDraw->SpinLock, OldIrql);
|
|
break;
|
|
|
|
case LO_CAPTURE:
|
|
peDxCapture = (EDD_DXCAPTURE*) pvObject;
|
|
peDxVideoPort = peDxCapture->peDxVideoPort;
|
|
if( peDxVideoPort != NULL )
|
|
{
|
|
peDxDirectDraw = peDxVideoPort->peDxDirectDraw;
|
|
|
|
KeAcquireSpinLock(&peDxDirectDraw->SpinLock, &OldIrql);
|
|
|
|
// First flush the capture buffers
|
|
|
|
DxInternalFlushVpCaptureBuffs( peDxDirectDraw, peDxVideoPort, peDxCapture );
|
|
|
|
// Disassociate the capture object from the video port
|
|
|
|
peDxCapture->peDxVideoPort = NULL;
|
|
peDxCapture->bLost = TRUE;
|
|
if( peDxVideoPort->peDxCapture == peDxCapture )
|
|
{
|
|
peDxVideoPort->peDxCapture = peDxCapture->peDxCaptureNext;
|
|
}
|
|
else
|
|
{
|
|
EDD_DXCAPTURE* peDxTemp;
|
|
|
|
for( peDxTemp = peDxVideoPort->peDxCapture;
|
|
( peDxTemp != NULL ) &&
|
|
( peDxTemp->peDxCaptureNext != peDxCapture );
|
|
peDxTemp = peDxTemp->peDxCaptureNext );
|
|
if( peDxTemp != NULL )
|
|
{
|
|
peDxTemp->peDxCaptureNext = peDxCapture->peDxCaptureNext;
|
|
}
|
|
else
|
|
{
|
|
RIPDX("Capture object not in video port list");
|
|
}
|
|
}
|
|
|
|
// If there are no more capture objects associated with the
|
|
// video port, remove the video port from the capture list.
|
|
|
|
pDxEvent = NULL;
|
|
if( peDxVideoPort->peDxCapture == NULL )
|
|
{
|
|
if( peDxDirectDraw->pDxEvent_CaptureList->peDxVideoPort == peDxVideoPort )
|
|
{
|
|
pDxEvent = peDxDirectDraw->pDxEvent_CaptureList;
|
|
peDxDirectDraw->pDxEvent_CaptureList = pDxEvent->pDxEvent_Next;
|
|
}
|
|
else
|
|
{
|
|
for( pDxEvent = peDxDirectDraw->pDxEvent_CaptureList;
|
|
(pDxEvent != NULL) &&
|
|
(pDxEvent->pDxEvent_Next->peDxVideoPort != peDxVideoPort);
|
|
pDxEvent = pDxEvent->pDxEvent_Next );
|
|
if( pDxEvent != NULL )
|
|
{
|
|
pDxEvent->pDxEvent_Next =
|
|
pDxEvent->pDxEvent_Next->pDxEvent_Next;
|
|
pDxEvent = pDxEvent->pDxEvent_Next;
|
|
}
|
|
}
|
|
}
|
|
|
|
KeReleaseSpinLock(&peDxDirectDraw->SpinLock, OldIrql);
|
|
|
|
if( pDxEvent != NULL )
|
|
{
|
|
ExFreePool(pDxEvent);
|
|
}
|
|
}
|
|
break;
|
|
|
|
default:
|
|
RIPDX("Unexpected type");
|
|
}
|
|
}
|
|
|
|
/******************************Public*Routine******************************\
|
|
* VOID DxUpdateCapture
|
|
*
|
|
* This routine inserts capture devices intot he list handling off of the
|
|
* video port. Since this list is walked at DPC level, we need to
|
|
* synchronize this with the DPC.
|
|
*
|
|
* 10-Jan-1997 -by- Scott MacDonald [smac]
|
|
* Wrote it.
|
|
\**************************************************************************/
|
|
|
|
VOID
|
|
APIENTRY
|
|
DxUpdateCapture(
|
|
EDD_DXVIDEOPORT* peDxVideoPort,
|
|
EDD_DXCAPTURE* peDxCapture,
|
|
BOOL bRemove
|
|
)
|
|
{
|
|
KIRQL OldIrql;
|
|
EDD_DXCAPTURE* peDxTemp;
|
|
EDD_DXDIRECTDRAW* peDxDirectDraw;
|
|
DXAPI_EVENT* pDxEvent_New;
|
|
DXAPI_EVENT* pDxEvent_Temp = NULL;
|
|
DWORD dwRet;
|
|
|
|
// If adding to the list, also an event to the capture list so we
|
|
// can get the busmaster complete notification. Allocate the
|
|
// memory for this now.
|
|
|
|
peDxDirectDraw = peDxVideoPort->peDxDirectDraw;
|
|
if( !bRemove )
|
|
{
|
|
pDxEvent_New = (DXAPI_EVENT*) ExAllocatePoolWithTag(NonPagedPool,
|
|
sizeof(*pDxEvent_New),
|
|
'eddG');
|
|
if (pDxEvent_New == NULL)
|
|
return;
|
|
|
|
RtlZeroMemory(pDxEvent_New, sizeof(*pDxEvent_New));
|
|
pDxEvent_New->peDxDirectDraw = peDxDirectDraw;
|
|
pDxEvent_New->peDxVideoPort = peDxVideoPort;
|
|
pDxEvent_New->pfnCallBack = (LPDD_NOTIFYCALLBACK) DxBusmasterDpc;
|
|
pDxEvent_New->pContext = peDxVideoPort;
|
|
}
|
|
|
|
KeAcquireSpinLock(&peDxVideoPort->peDxDirectDraw->SpinLock, &OldIrql);
|
|
|
|
if( bRemove )
|
|
{
|
|
// First flush the capture buffers
|
|
|
|
DxInternalFlushVpCaptureBuffs( peDxDirectDraw, peDxVideoPort, peDxCapture );
|
|
|
|
// Disassociate the capture object with the video port
|
|
|
|
if( peDxVideoPort->peDxCapture == peDxCapture )
|
|
{
|
|
peDxVideoPort->peDxCapture = peDxCapture->peDxCaptureNext;
|
|
}
|
|
else
|
|
{
|
|
for( peDxTemp = peDxVideoPort->peDxCapture;
|
|
( peDxTemp != NULL ) &&
|
|
( peDxTemp->peDxCaptureNext != peDxCapture );
|
|
peDxTemp = peDxTemp->peDxCaptureNext );
|
|
if( peDxTemp != NULL )
|
|
{
|
|
peDxTemp->peDxCaptureNext = peDxCapture->peDxCaptureNext;
|
|
}
|
|
}
|
|
peDxCapture->peDxVideoPort = NULL;
|
|
|
|
// If there are no more capture objects associated with the
|
|
// video port, remove the video port from the capture list.
|
|
|
|
if( peDxVideoPort->peDxCapture == NULL )
|
|
{
|
|
pDxEvent_Temp = NULL;
|
|
if( peDxDirectDraw->pDxEvent_CaptureList->peDxVideoPort == peDxVideoPort )
|
|
{
|
|
pDxEvent_Temp = peDxDirectDraw->pDxEvent_CaptureList;
|
|
peDxDirectDraw->pDxEvent_CaptureList = pDxEvent_Temp->pDxEvent_Next;
|
|
}
|
|
else
|
|
{
|
|
for( pDxEvent_Temp = peDxDirectDraw->pDxEvent_CaptureList;
|
|
(pDxEvent_Temp != NULL) &&
|
|
(pDxEvent_Temp->pDxEvent_Next->peDxVideoPort != NULL);
|
|
pDxEvent_Temp = pDxEvent_Temp->pDxEvent_Next );
|
|
if( pDxEvent_Temp != NULL )
|
|
{
|
|
pDxEvent_Temp->pDxEvent_Next =
|
|
pDxEvent_Temp->pDxEvent_Next->pDxEvent_Next;
|
|
pDxEvent_Temp = pDxEvent_Temp->pDxEvent_Next;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// Associate the capture object with the video port
|
|
|
|
peDxCapture->peDxCaptureNext = peDxVideoPort->peDxCapture;
|
|
peDxVideoPort->peDxCapture = peDxCapture;
|
|
|
|
// Add an event to the capture list so we can get the busmaster
|
|
// complete notification. First check to see if it's already in
|
|
// in the list.
|
|
|
|
for (pDxEvent_Temp = peDxDirectDraw->pDxEvent_CaptureList;
|
|
pDxEvent_Temp != NULL;
|
|
pDxEvent_Temp = pDxEvent_Temp->pDxEvent_Next)
|
|
{
|
|
if (pDxEvent_Temp->peDxVideoPort == peDxVideoPort)
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
if( pDxEvent_Temp == NULL )
|
|
{
|
|
// Not already in list - add it
|
|
|
|
pDxEvent_New->pDxEvent_Next = peDxDirectDraw->pDxEvent_CaptureList;
|
|
peDxDirectDraw->pDxEvent_CaptureList = pDxEvent_New;
|
|
}
|
|
}
|
|
|
|
KeReleaseSpinLock(&peDxVideoPort->peDxDirectDraw->SpinLock, OldIrql);
|
|
|
|
if( bRemove && ( pDxEvent_Temp != NULL ) )
|
|
{
|
|
ExFreePool(pDxEvent_Temp);
|
|
}
|
|
else if( pDxEvent_Temp != NULL )
|
|
{
|
|
ExFreePool(pDxEvent_New);
|
|
}
|
|
}
|
|
|
|
/******************************Public*Routine******************************\
|
|
* DWORD DxOpenDirectDraw
|
|
*
|
|
* 14-Apr-1997 -by- J. Andrew Goossen [andrewgo]
|
|
* Wrote it.
|
|
\**************************************************************************/
|
|
|
|
VOID
|
|
APIENTRY
|
|
DxOpenDirectDraw(
|
|
DDOPENDIRECTDRAWIN* pOpenDirectDrawIn,
|
|
DDOPENDIRECTDRAWOUT* pOpenDirectDrawOut
|
|
)
|
|
{
|
|
pOpenDirectDrawOut->ddRVal = DDERR_UNSUPPORTED;
|
|
if (pOpenDirectDrawIn != NULL)
|
|
{
|
|
if (gpfnOpenDirectDraw != NULL)
|
|
{
|
|
gpfnOpenDirectDraw(pOpenDirectDrawIn,
|
|
pOpenDirectDrawOut,
|
|
DxEventDpc,
|
|
DXAPI_PRIVATE_VERSION_NUMBER);
|
|
}
|
|
}
|
|
}
|
|
|
|
/******************************Public*Routine******************************\
|
|
* VOID DxEnableIRQ
|
|
*
|
|
* This routine enables/disables the video port VSYNC IRQ and is
|
|
* is called at dispatch level.
|
|
*
|
|
* 17-Oct-1997 -by- smac
|
|
* Wrote it.
|
|
\**************************************************************************/
|
|
|
|
VOID
|
|
APIENTRY
|
|
DxEnableIRQ(
|
|
EDD_DXVIDEOPORT* peDxVideoPort,
|
|
BOOL bEnable
|
|
)
|
|
{
|
|
EDD_DXDIRECTDRAW* peDxDirectDraw;
|
|
EDD_DIRECTDRAW_GLOBAL* peDirectDrawGlobal;
|
|
DWORD dwBit;
|
|
|
|
peDxDirectDraw = peDxVideoPort->peDxDirectDraw;
|
|
peDirectDrawGlobal = peDxDirectDraw->peDirectDrawGlobal;
|
|
dwBit = DDIRQ_VPORT0_VSYNC << ( peDxVideoPort->dwVideoPortID * 2);
|
|
|
|
/*
|
|
* Don't enable or disable of the IRQ isn't supported
|
|
*/
|
|
if( ( peDirectDrawGlobal != NULL ) &&
|
|
( peDirectDrawGlobal->DDKernelCaps.dwIRQCaps & dwBit ) )
|
|
{
|
|
if( bEnable )
|
|
{
|
|
if( !( peDxVideoPort->flFlags & DD_DXVIDEOPORT_FLAG_REGISTERED_IRQ ) )
|
|
{
|
|
bDxModifyDispatchEventList(peDxDirectDraw,
|
|
peDxVideoPort,
|
|
bEnable,
|
|
DDEVENT_VP_VSYNC,
|
|
dwBit,
|
|
(LPDD_NOTIFYCALLBACK) DxAutoflipDpc,
|
|
(PVOID)peDxVideoPort,
|
|
INTERNAL_DISPATCH_LIST);
|
|
peDxVideoPort->flFlags |= DD_DXVIDEOPORT_FLAG_REGISTERED_IRQ;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if( peDxVideoPort->flFlags & DD_DXVIDEOPORT_FLAG_REGISTERED_IRQ )
|
|
{
|
|
bDxModifyDispatchEventList(peDxDirectDraw,
|
|
peDxVideoPort,
|
|
bEnable,
|
|
DDEVENT_VP_VSYNC,
|
|
dwBit,
|
|
(LPDD_NOTIFYCALLBACK) DxAutoflipDpc,
|
|
(PVOID)peDxVideoPort,
|
|
INTERNAL_DISPATCH_LIST);
|
|
peDxVideoPort->flFlags &= ~DD_DXVIDEOPORT_FLAG_REGISTERED_IRQ;
|
|
}
|
|
}
|
|
vDxEnableInterrupts( peDxDirectDraw, 0 );
|
|
}
|
|
}
|
|
|
|
/******************************Public*Routine******************************\
|
|
* DxApi
|
|
*
|
|
* Single entry point for all DXAPI.SYS public functionality.
|
|
*
|
|
* 14-Apr-1997 -by- J. Andrew Goossen [andrewgo]
|
|
* Wrote it.
|
|
\**************************************************************************/
|
|
|
|
typedef VOID (APIENTRY* PDX_FUNCTION)(VOID*, VOID*);
|
|
|
|
typedef struct _DXAPI_ENTRY_POINT {
|
|
PDX_FUNCTION pfn;
|
|
DWORD cInBuffer;
|
|
DWORD cOutBuffer;
|
|
BOOLEAN bMapProcess;
|
|
} DXAPI_ENTRY_POINT;
|
|
|
|
#define DX(fn, structin, structout, boolean) \
|
|
(PDX_FUNCTION) fn, structin, sizeof(structout), boolean
|
|
|
|
DXAPI_ENTRY_POINT gDxApiEntryPoint[] = {
|
|
DX(DxGetVersionNumber, 0, DDGETVERSIONNUMBER, FALSE ), // 0
|
|
DX(NULL, sizeof(DDCLOSEHANDLE), DWORD, TRUE ), // 1
|
|
DX(DxOpenDirectDraw, sizeof(DDOPENDIRECTDRAWIN), DDOPENDIRECTDRAWOUT, FALSE ), // 2
|
|
DX(NULL, sizeof(DDOPENSURFACEIN), DDOPENSURFACEOUT, TRUE ), // 3
|
|
DX(NULL, sizeof(DDOPENVIDEOPORTIN), DDOPENVIDEOPORTOUT, TRUE ), // 4
|
|
DX(NULL, sizeof(DWORD), DDGETKERNELCAPSOUT, TRUE ), // 5
|
|
DX(DxGetFieldNumber, sizeof(DDGETFIELDNUMIN), DDGETFIELDNUMOUT, FALSE ), // 6
|
|
DX(DxSetFieldNumber, sizeof(DDSETFIELDNUM), DWORD, FALSE ), // 7
|
|
DX(DxSetSkipPattern, sizeof(DDSETSKIPFIELD), DWORD, FALSE ), // 8
|
|
DX(DxGetSurfaceState, sizeof(DDGETSURFACESTATEIN), DDGETSURFACESTATEOUT, FALSE ), // 9
|
|
DX(DxSetSurfaceState, sizeof(DDSETSURFACESTATE), DWORD, FALSE ), // 10
|
|
DX(DxLock, sizeof(DDLOCKIN), DDLOCKOUT, FALSE ), // 11
|
|
DX(DxFlipOverlay, sizeof(DDFLIPOVERLAY), DWORD, FALSE ), // 12
|
|
DX(DxFlipVideoPort, sizeof(DDFLIPVIDEOPORT), DWORD, FALSE ), // 13
|
|
DX(DxGetCurrentAutoflip, sizeof(DDGETAUTOFLIPIN), DDGETAUTOFLIPOUT, FALSE ), // 14
|
|
DX(DxGetPreviousAutoflip, sizeof(DDGETAUTOFLIPIN), DDGETAUTOFLIPOUT, FALSE ), // 15
|
|
DX(DxRegisterEvent, sizeof(DDREGISTERCALLBACK), DWORD, FALSE ), // 16
|
|
DX(DxUnregisterEvent, sizeof(DDREGISTERCALLBACK), DWORD, FALSE ), // 17
|
|
DX(DxGetPolarity, sizeof(DDGETPOLARITYIN), DDGETPOLARITYOUT, FALSE ), // 18
|
|
DX(NULL, sizeof(DDOPENVPCAPTUREDEVICEIN),DDOPENVPCAPTUREDEVICEOUT, TRUE ), // 19
|
|
DX(DxAddVpCaptureBuffer, sizeof(DDADDVPCAPTUREBUFF), DWORD, FALSE ), // 20
|
|
DX(DxFlushVpCaptureBuffs, sizeof(DWORD), DWORD, FALSE ), // 21
|
|
};
|
|
|
|
DWORD
|
|
APIENTRY
|
|
DxApi(
|
|
DWORD iFunction,
|
|
VOID* pInBuffer,
|
|
DWORD cInBuffer,
|
|
VOID* pOutBuffer,
|
|
DWORD cOutBuffer
|
|
)
|
|
{
|
|
DWORD dwRet;
|
|
BOOL bProcessAttached = FALSE;
|
|
|
|
dwRet = 0;
|
|
|
|
iFunction -= DD_FIRST_DXAPI;
|
|
|
|
if ((iFunction >= sizeof(gDxApiEntryPoint) / sizeof(DXAPI_ENTRY_POINT)) ||
|
|
(gDxApiEntryPoint[iFunction].pfn == NULL))
|
|
{
|
|
KdPrint(("DxApi: Invalid function\n"));
|
|
}
|
|
else if ((cInBuffer < gDxApiEntryPoint[iFunction].cInBuffer) ||
|
|
(cOutBuffer < gDxApiEntryPoint[iFunction].cOutBuffer))
|
|
{
|
|
KdPrint(("DxApi: Input or output buffer too small\n"));
|
|
}
|
|
else if (pOutBuffer == NULL)
|
|
{
|
|
KdPrint(("DxApi: Invalid output buffer specified\n"));
|
|
}
|
|
else
|
|
{
|
|
if (gDxApiEntryPoint[iFunction].bMapProcess)
|
|
{
|
|
PEPROCESS pepSession;
|
|
|
|
switch (iFunction)
|
|
{
|
|
case (DD_DXAPI_CLOSEHANDLE - DD_FIRST_DXAPI):
|
|
case (DD_DXAPI_OPENSURFACE - DD_FIRST_DXAPI):
|
|
case (DD_DXAPI_OPENVIDEOPORT - DD_FIRST_DXAPI):
|
|
case (DD_DXAPI_OPENVPCAPTUREDEVICE - DD_FIRST_DXAPI):
|
|
|
|
// pInBuffer is a pointer to a structure that has
|
|
// a pointer to DXOBJ as its first element.
|
|
|
|
pepSession = ((DXOBJ *)(*(HANDLE *)pInBuffer))->pepSession;
|
|
break;
|
|
|
|
case (DD_DXAPI_GETKERNELCAPS - DD_FIRST_DXAPI):
|
|
|
|
// pInBuffer is a pointer to DXOBJ.
|
|
|
|
pepSession = ((DXOBJ *)pInBuffer)->pepSession;
|
|
break;
|
|
|
|
default:
|
|
return (dwRet);
|
|
}
|
|
|
|
if (!KeIsAttachedProcess())
|
|
{
|
|
KeAttachProcess(PsGetProcessPcb(pepSession));
|
|
bProcessAttached = TRUE;
|
|
}
|
|
}
|
|
|
|
// The return value is the size of the output buffer:
|
|
|
|
dwRet = gDxApiEntryPoint[iFunction].cOutBuffer;
|
|
|
|
// Call the actual routine:
|
|
|
|
gDxApiEntryPoint[iFunction].pfn(pInBuffer, pOutBuffer);
|
|
|
|
if (bProcessAttached)
|
|
{
|
|
KeDetachProcess();
|
|
}
|
|
}
|
|
|
|
return(dwRet);
|
|
}
|
|
|
|
/******************************Public*Routine******************************\
|
|
* VOID DxApiInitialize
|
|
*
|
|
* Called by win32k.sys to initialize dxapi.sys state.
|
|
*
|
|
* 14-Apr-1997 -by- J. Andrew Goossen [andrewgo]
|
|
* Wrote it.
|
|
\**************************************************************************/
|
|
|
|
VOID
|
|
APIENTRY
|
|
DxApiInitialize(
|
|
PFNDXAPIOPENDIRECTDRAW pfnOpenDirectDraw,
|
|
PFNDXAPIOPENVIDEOPORT pfnOpenVideoPort,
|
|
PFNDXAPIOPENSURFACE pfnOpenSurface,
|
|
PFNDXAPICLOSEHANDLE pfnCloseHandle,
|
|
PFNDXAPIGETKERNELCAPS pfnGetKernelCaps,
|
|
PFNDXAPIOPENCAPTUREDEVICE pfnOpenCaptureDevice,
|
|
PFNDXAPILOCKDEVICE pfnLockDevice,
|
|
PFNDXAPIUNLOCKDEVICE pfnUnlockDevice
|
|
)
|
|
{
|
|
gpfnOpenDirectDraw = pfnOpenDirectDraw;
|
|
gpfnLockDevice = pfnLockDevice;
|
|
gpfnUnlockDevice = pfnUnlockDevice;
|
|
|
|
gDxApiEntryPoint[DD_DXAPI_OPENVIDEOPORT - DD_FIRST_DXAPI].pfn
|
|
= (PDX_FUNCTION) pfnOpenVideoPort;
|
|
|
|
gDxApiEntryPoint[DD_DXAPI_OPENSURFACE - DD_FIRST_DXAPI].pfn
|
|
= (PDX_FUNCTION) pfnOpenSurface;
|
|
|
|
gDxApiEntryPoint[DD_DXAPI_CLOSEHANDLE - DD_FIRST_DXAPI].pfn
|
|
= (PDX_FUNCTION) pfnCloseHandle;
|
|
|
|
gDxApiEntryPoint[DD_DXAPI_GETKERNELCAPS - DD_FIRST_DXAPI].pfn
|
|
= (PDX_FUNCTION) pfnGetKernelCaps;
|
|
|
|
gDxApiEntryPoint[DD_DXAPI_OPENVPCAPTUREDEVICE - DD_FIRST_DXAPI].pfn
|
|
= (PDX_FUNCTION) pfnOpenCaptureDevice;
|
|
}
|
|
|
|
/******************************Public*Routine******************************\
|
|
* ULONG DxApiGetVersion
|
|
*
|
|
* The original Memphis DXAPI had this entry point and although it doesn't
|
|
* do anything usefull, some drivers called it so we have to support it
|
|
* for those drivers to load. It does not return a real version number
|
|
* because the original incorrectly returned the DSOUND version 4.02,
|
|
* which has no correlation to the DxApi version number. If we return the
|
|
* real version, however, we risk breaking drivers.
|
|
*
|
|
* 16-Apr-1998 -by- Scott MacDonald [smac]
|
|
* Wrote it.
|
|
\**************************************************************************/
|
|
|
|
ULONG
|
|
APIENTRY
|
|
DxApiGetVersion(
|
|
VOID
|
|
)
|
|
{
|
|
return( 0x402 );
|
|
}
|
|
|