Leaked source code of windows server 2003
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.
 
 
 
 
 
 

4061 lines
135 KiB

/******************************Module*Header*******************************\
* Module Name: dvpe.cxx
*
* Contains all of GDI's private VideoPort APIs.
*
* Note that for videoport support, WIN32K.SYS and DXAPI.SYS are closely
* linked. DXAPI.SYS provides two services:
*
* 1. It handles the "software autoflipping" support for the videoports,
* where the CPU handles the videoport field-done interrupt to
* flip the overlay and do "bob" and "weave" for better video
* quality.
* 2. It provides the public DirectDraw entry points that are callable
* by other kernel-mode WDM drivers (there is a corresponding DXAPI.SYS
* module on Memphis/Win95 that exposes the same interface).
*
* All of the non-paged code for videoports has to go into DXAPI.SYS since
* WIN32K.SYS is marked entirely as pageable. WIN32K.SYS handles some
* functionality on behalf of DXAPI.SYS, such as object opens and closes,
* since only WIN32K.SYS can access GDI's handle table.
*
* Created: 17-Oct-1996
* Author: Lingyun Wang [LingyunW]
*
* Copyright (c) 1996-1999 Microsoft Corporation
*
\**************************************************************************/
#include "precomp.hxx"
extern PEPROCESS gpepSession;
VOID
vDdDxApiFreeDirectDraw(
DXOBJ* pDxObj,
BOOL bDoCallBack
);
/////////////////////////////////////////////////////////////////////////
// DXAPI concerns:
//
// - Document that call-back may not occur in context of same process
// - Refuse to open surface, videoport objects while full-screen
// Keep DirectDraw open so that POSTFULLSCREEN and DOSBOX can be honored
// - See InitKernelInterface for init restrictions
// - Flush DMA buffer before mode changes?
// - Invalidate dxapi data after mode change?
// - Right now, DirectDraw DXAPI objects have to be closed last
/////////////////////////////////////////////////////////////////////////
// VPE concerns:
//
// - Make sure VideoPort's not duplicated on same device
// - Document that display driver cannot use pool-allocated memory for
// dwReserved fields on Synchronize calls
// - Close DxVideoPort objects on full-screen switch?
// No, to support hardware that can DMA even while full-screen!
// Okay, but what about mode changes? There's no way they'll not
// be able to drop frames
// - Never close DxDirectDraw objects?
/*****************************Private*Routine******************************\
* ULONG vDdNullCallBack
*
* The DXAPI register routines require a close call-back routine to notify
* the client that the object is going away. Since we're really DirectDraw,
* we already know when the object is going away; hence, this routine doesn't
* need to do anything.
*
* 14-Apr-1997 -by- J. Andrew Goossen [andrewgo]
* Wrote it.
\**************************************************************************/
ULONG
vDdNullCallBack(
DWORD dwFlags,
PVOID pContext,
DWORD dwParam1,
DWORD dwParam2
)
{
return 0;
}
/*****************************Private*Routine******************************\
* VOID vDdUnloadDxApiImage
*
* This routine performs the actual unload of DXAPI.SYS.
*
* 28-Oct-1997 -by- smac
* Wrote it.
\**************************************************************************/
VOID
vDdUnloadDxApiImage(
EDD_DIRECTDRAW_GLOBAL* peDirectDrawGlobal
)
{
EDD_VIDEOPORT* peVideoPort;
EDD_VIDEOPORT* peVideoPortNext;
EDD_SURFACE* peSurface;
EDD_DIRECTDRAW_LOCAL* peDirectDrawLocal;
DD_ASSERTDEVLOCK(peDirectDrawGlobal);
// Notify clients that the resources are lost and clean up
for (peDirectDrawLocal = peDirectDrawGlobal->peDirectDrawLocalList;
peDirectDrawLocal != NULL;
peDirectDrawLocal = peDirectDrawLocal->peDirectDrawLocalNext)
{
// If any video port still exist (which should not be the case)
// delete all of the video port objects since the video port assumes
// that DXAPI.SYS is loaded.
for (peVideoPort = peDirectDrawLocal->peVideoPort_DdList;
peVideoPort != NULL;
peVideoPort = peVideoPortNext)
{
// Don't reference peVideoPort after it's been deleted!
peVideoPortNext = peVideoPort->peVideoPort_DdNext;
bDdDeleteVideoPortObject(peVideoPort->hGet(), NULL);
}
// If a surface still has a client using it, shut it down.
peSurface = peDirectDrawLocal->peSurface_Enum(NULL);
while (peSurface)
{
if (peSurface->hSurface != NULL)
{
vDdDxApiFreeSurface( (DXOBJ*) peSurface->hSurface, FALSE );
peSurface->hSurface = NULL;
}
if( peSurface->peDxSurface != NULL )
{
vDdLoseDxObjects( peDirectDrawGlobal,
peSurface->peDxSurface->pDxObj_List,
(PVOID) peSurface->peDxSurface,
LO_SURFACE );
}
peSurface = peDirectDrawLocal->peSurface_Enum(peSurface);
}
}
if (peDirectDrawGlobal->hDirectDraw != NULL)
{
vDdDxApiFreeDirectDraw( (DXOBJ*) peDirectDrawGlobal->hDirectDraw, FALSE );
}
if( peDirectDrawGlobal->peDxDirectDraw != NULL )
{
vDdLoseDxObjects( peDirectDrawGlobal,
peDirectDrawGlobal->peDxDirectDraw->pDxObj_List,
(PVOID) peDirectDrawGlobal->peDxDirectDraw,
LO_DIRECTDRAW );
}
EngUnloadImage(peDirectDrawGlobal->hDxApi);
//
// Free the memory associate with the module
//
peDirectDrawGlobal->hDxApi = NULL;
peDirectDrawGlobal->dwDxApiRefCnt = 0;
}
/*****************************Private*Routine******************************\
* BOOL bDdLoadDxApi
*
* This routine loads up DXAPI.SYS and allocates the non-paged DXAPI
* structures.
*
* Returns: FALSE only if a DXAPI resource could not be allocated.
*
* 14-Apr-1997 -by- J. Andrew Goossen [andrewgo]
* Wrote it.
* 16-Oct-1977 -by- smac
* Broke it out into a separate function.
\**************************************************************************/
BOOL
bDdLoadDxApi(
EDD_DIRECTDRAW_LOCAL* peDirectDrawLocal
)
{
EDD_DIRECTDRAW_GLOBAL* peDirectDrawGlobal;
HANDLE hDxApi;
PFNDXAPIINITIALIZE pfnDxApiInitialize;
DDOPENDIRECTDRAWIN OpenDirectDrawIn;
DDOPENDIRECTDRAWOUT OpenDirectDrawOut;
DWORD dwRet;
DD_ASSERTDEVLOCK(peDirectDrawLocal->peDirectDrawGlobal);
peDirectDrawGlobal = peDirectDrawLocal->peDirectDrawGlobal;
/*
* Don't load if it's already loaded
*/
if (peDirectDrawGlobal->hDxApi == NULL)
{
ASSERTGDI((peDirectDrawGlobal->hDirectDraw == NULL) &&
(peDirectDrawGlobal->hDxApi == NULL),
"Expected NULL hDirectDraw and hDxApi");
BOOL loaded;
hDxApi = DxEngLoadImage(L"drivers\\dxapi.sys",FALSE);
if (hDxApi)
{
peDirectDrawGlobal->hDxApi = hDxApi;
peDirectDrawGlobal->pfnDxApi = (LPDXAPI)
EngFindImageProcAddress(hDxApi, "_DxApi");
peDirectDrawGlobal->pfnAutoflipUpdate = (PFNAUTOFLIPUPDATE)
EngFindImageProcAddress(hDxApi, "_DxAutoflipUpdate");
peDirectDrawGlobal->pfnLoseObject = (PFNLOSEOBJECT)
EngFindImageProcAddress(hDxApi, "_DxLoseObject");
pfnDxApiInitialize = (PFNDXAPIINITIALIZE)
EngFindImageProcAddress(hDxApi, "_DxApiInitialize");
peDirectDrawGlobal->pfnEnableIRQ = (PFNENABLEIRQ)
EngFindImageProcAddress(hDxApi, "_DxEnableIRQ");
peDirectDrawGlobal->pfnUpdateCapture = (PFNUPDATECAPTURE)
EngFindImageProcAddress(hDxApi, "_DxUpdateCapture");
ASSERTGDI(peDirectDrawGlobal->pfnDxApi != NULL,
"Couldn't find DxApi'");
ASSERTGDI(peDirectDrawGlobal->pfnAutoflipUpdate != NULL,
"Couldn't find DxAutoflipUpdate");
ASSERTGDI(peDirectDrawGlobal->pfnLoseObject != NULL,
"Couldn't find DxLoseObject");
ASSERTGDI(peDirectDrawGlobal->pfnEnableIRQ != NULL,
"Couldn't find DxEnableIRQ");
ASSERTGDI(peDirectDrawGlobal->pfnUpdateCapture != NULL,
"Couldn't find DxUpdateCapture");
ASSERTGDI(pfnDxApiInitialize != NULL,
"Couldn't find DxApiInitialize");
// By explicitly passing dxapi.sys its private win32k.sys
// entry points, we don't have to export them from win32k.sys,
// thus preventing any drivers from using those entry points
// for their own nefarious purposes.
pfnDxApiInitialize(DdDxApiOpenDirectDraw,
DdDxApiOpenVideoPort,
DdDxApiOpenSurface,
DdDxApiCloseHandle,
DdDxApiGetKernelCaps,
DdDxApiOpenCaptureDevice,
DdDxApiLockDevice,
DdDxApiUnlockDevice);
// EngLoadImage always makes the entire driver pageable, but
// DXAPI.SYS handles the DPC for the videoport interrupt and
// so cannot be entirely pageable. Consequently, we reset
// the paging now:
MmResetDriverPaging(pfnDxApiInitialize);
// Now open the DXAPI version of DirectDraw:
OpenDirectDrawIn.pfnDirectDrawClose = vDdNullCallBack;
OpenDirectDrawIn.pContext = NULL;
OpenDirectDrawIn.dwDirectDrawHandle
= (ULONG_PTR) peDirectDrawLocal->hGet();
peDirectDrawGlobal->pfnDxApi(DD_DXAPI_OPENDIRECTDRAW,
&OpenDirectDrawIn,
sizeof(OpenDirectDrawIn),
&OpenDirectDrawOut,
sizeof(OpenDirectDrawOut));
if (OpenDirectDrawOut.ddRVal == DD_OK)
{
// Success!
peDirectDrawGlobal->hDirectDraw = OpenDirectDrawOut.hDirectDraw;
}
peDirectDrawGlobal->dwDxApiRefCnt = 1;
}
else
{
WARNING("bDdLoadDxApi: Couldn't load dxapi.sys\n");
return(FALSE);
}
}
else
{
peDirectDrawGlobal->dwDxApiRefCnt++;
}
return(TRUE);
}
/*****************************Private*Routine******************************\
* VOID vDdUnloadDxApi
*
* This routine unloads DXAPI.SYS
*
* 22-Oct-1997 -by- smac
\**************************************************************************/
VOID
vDdUnloadDxApi(
EDD_DIRECTDRAW_GLOBAL* peDirectDrawGlobal
)
{
DDCLOSEHANDLE CloseHandle;
DWORD dwRet;
if ((peDirectDrawGlobal->hDxApi != NULL) &&
(peDirectDrawGlobal->dwDxApiRefCnt > 0 ))
{
if( --peDirectDrawGlobal->dwDxApiRefCnt == 0 )
{
if (peDirectDrawGlobal->hDirectDraw != NULL)
{
CloseHandle.hHandle = peDirectDrawGlobal->hDirectDraw;
peDirectDrawGlobal->pfnDxApi(DD_DXAPI_CLOSEHANDLE,
&CloseHandle,
sizeof(CloseHandle),
&dwRet,
sizeof(dwRet));
ASSERTGDI(dwRet == DD_OK, "Unexpected failure from close");
peDirectDrawGlobal->hDirectDraw = NULL;
}
vDdUnloadDxApiImage( peDirectDrawGlobal );
}
}
}
/*****************************Private*Routine******************************\
* BOOL bDdEnableSoftwareAutoflipping
*
* This routine loads up DXAPI.SYS, allocates the non-paged DXAPI structures
* required for software autoflipping, and enables the videoport interrupt.
*
* Returns: FALSE only if a DXAPI resource could not be allocated. May
* return TRUE even if the interrupt hasn't been successfully
* enabled (because I expect that interrupts will be usable
* on the majority of systems that support videoports, and this
* simplifies other code by allowing it to assume that all the
* DXAPI structures have been allocated).
*
* 14-Apr-1997 -by- J. Andrew Goossen [andrewgo]
* Wrote it.
\**************************************************************************/
BOOL
bDdEnableSoftwareAutoflipping(
EDD_DIRECTDRAW_LOCAL* peDirectDrawLocal,
EDD_VIDEOPORT* peVideoPort,
DWORD dwVideoPortID,
BOOL bFirst
)
{
EDD_DIRECTDRAW_GLOBAL* peDirectDrawGlobal;
HANDLE hDxApi;
PFNDXAPIINITIALIZE pfnDxApiInitialize;
DDOPENDIRECTDRAWIN OpenDirectDrawIn;
DDOPENDIRECTDRAWOUT OpenDirectDrawOut;
DDOPENVIDEOPORTIN OpenVideoPortIn;
DDOPENVIDEOPORTOUT OpenVideoPortOut;
DWORD dwRet;
UNICODE_STRING UnicodeString;
DD_ASSERTDEVLOCK(peVideoPort->peDirectDrawGlobal);
peDirectDrawGlobal = peVideoPort->peDirectDrawGlobal;
// Create a DXAPI DirectDraw object, which we'll need for software
// autoflipping.
if (bFirst)
{
bDdLoadDxApi( peDirectDrawLocal );
}
if (peDirectDrawGlobal->hDirectDraw != NULL)
{
ASSERTGDI(peVideoPort->hVideoPort == NULL, "Expected NULL hVideoPort");
OpenVideoPortIn.hDirectDraw = peDirectDrawGlobal->hDirectDraw;
OpenVideoPortIn.pfnVideoPortClose = vDdNullCallBack;
OpenVideoPortIn.pContext = NULL;
OpenVideoPortIn.dwVideoPortHandle = dwVideoPortID;
peDirectDrawGlobal->pfnDxApi(DD_DXAPI_OPENVIDEOPORT,
&OpenVideoPortIn,
sizeof(OpenVideoPortIn),
&OpenVideoPortOut,
sizeof(OpenVideoPortOut));
if (OpenVideoPortOut.ddRVal == DD_OK)
{
peVideoPort->hVideoPort = OpenVideoPortOut.hVideoPort;
return(TRUE);
}
}
return(FALSE);
}
/******************************Public*Routine******************************\
* VOID vDdNotifyEvent
*
* This routine calls back to all registered DXAPI clients when a particular
* event (like mode change notification) occurs.
*
* 14-Apr-1997 -by- J. Andrew Goossen [andrewgo]
* Wrote it.
\**************************************************************************/
VOID
vDdNotifyEvent(
EDD_DIRECTDRAW_GLOBAL* peDirectDrawGlobal,
DWORD dwEvent
)
{
EDD_DXDIRECTDRAW* peDxDirectDraw;
DXAPI_EVENT* pDxEvent;
peDxDirectDraw = peDirectDrawGlobal->peDxDirectDraw;
if (peDxDirectDraw != NULL)
{
DD_ASSERTDEVLOCK(peDirectDrawGlobal);
for (pDxEvent = peDxDirectDraw->pDxEvent_PassiveList;
pDxEvent != NULL;
pDxEvent = pDxEvent->pDxEvent_Next)
{
if (pDxEvent->dwEvent == dwEvent)
{
pDxEvent->pfnCallBack(pDxEvent->dwEvent,pDxEvent->pContext, 0, 0);
}
}
}
}
/******************************Public*Routine******************************\
* DXAPI_OBJECT* pDdDxObjHandleAllocate
*
* 14-Apr-1997 -by- J. Andrew Goossen [andrewgo]
* Wrote it.
\**************************************************************************/
DXOBJ*
pDdDxObjHandleAllocate(
DXTYPE iDxType,
LPDD_NOTIFYCALLBACK pfnClose,
DWORD dwEvent,
PVOID pvContext
)
{
DXOBJ* pDxObj;
ASSERTGDI(pfnClose != NULL,
"pDdDxObjHandleAllocate: DXAPI client must supply Close function");
pDxObj = (DXOBJ*) PALLOCNONPAGED(sizeof(*pDxObj),'xxdG');
if (pDxObj != NULL)
{
pDxObj->iDxType = iDxType;
pDxObj->pfnClose = pfnClose;
pDxObj->pContext = pvContext;
pDxObj->dwEvent = dwEvent;
pDxObj->pDxObj_Next = NULL;
pDxObj->dwFlags = 0;
pDxObj->pepSession = gpepSession;
}
return(pDxObj);
}
// Should be macro for free build.
PVOID
pDdDxObjDataAllocate(
ULONG cj,
ULONG tag
)
{
return (PALLOCNONPAGED(cj,tag));
}
VOID
vDdDxObjFree(
PVOID pvDxObj
)
{
VFREEMEM(pvDxObj);
}
/******************************Public*Routine******************************\
* VOID vDdQueryMiniportDxApiSupport
*
* 14-Apr-1997 -by- J. Andrew Goossen [andrewgo]
* Wrote it.
\**************************************************************************/
VOID
vDdQueryMiniportDxApiSupport(
EDD_DIRECTDRAW_GLOBAL* peDirectDrawGlobal
)
{
BOOL bMiniportSupport;
// Assume failure.
bMiniportSupport = FALSE;
if (bDdIoQueryInterface(peDirectDrawGlobal,
&GUID_DxApi,
sizeof(DXAPI_INTERFACE),
DXAPI_HALVERSION,
(INTERFACE *)&peDirectDrawGlobal->DxApiInterface))
{
ASSERTGDI((peDirectDrawGlobal->DxApiInterface.
InterfaceReference == NULL) &&
(peDirectDrawGlobal->DxApiInterface.
InterfaceDereference == NULL),
"Miniport shouldn't modify InterfaceReference/Dereference");
// Assert some stuff about hooked entry points?
peDirectDrawGlobal->HwDeviceExtension
= peDirectDrawGlobal->DxApiInterface.Context;
bMiniportSupport = TRUE;
}
// Even if the miniport doesn't support DXAPI accelerations, we still
// allow DXAPI to work (the DXAPI Lock call doesn't require that the
// miniport support DXAPI, for example).
if (!bMiniportSupport)
{
// Zero out any capabilities:
RtlZeroMemory(&peDirectDrawGlobal->DxApiInterface,
sizeof(peDirectDrawGlobal->DxApiInterface));
}
}
/******************************Public*Routine******************************\
* DWORD vDdSynchronizeSurface
*
* Updates the EDD_DXSURFACE structure using the master EDD_SURFACE
* structure, with some help from the driver.
*
* Analagous to Win95's SyncKernelSurface routine.
*
* This routine lets a driver use fields from the larger, pageable version
* of the DD_SURFACE_* structures used by the display driver to set
* fields in the smaller, non-pageable version of the corresponding
* DDSURFACEDATA structure used by the miniport.
*
* NOTE: The display driver may NOT use the reserved fields to point to
* allocated memory, for two reasons:
*
* 1. We don't call them when the surfaces is freed, so they'd
* lose memory;
* 2. We only let display drivers allocate paged memory, which
* they can't use in the miniport since they'll be at raised
* IRQL when we call them.
*
* 14-Apr-1997 -by- J. Andrew Goossen [andrewgo]
* Wrote it.
\**************************************************************************/
VOID
vDdSynchronizeSurface(
EDD_SURFACE* peSurface
)
{
EDD_DXSURFACE* peDxSurface;
EDD_DIRECTDRAW_GLOBAL* peDirectDrawGlobal;
DD_SYNCSURFACEDATA SyncSurfaceData;
peDirectDrawGlobal = peSurface->peDirectDrawGlobal;
peDxSurface = peSurface->peDxSurface;
if (peDxSurface != NULL)
{
RtlZeroMemory(&SyncSurfaceData, sizeof(SyncSurfaceData));
SyncSurfaceData.lpDD = peDirectDrawGlobal;
SyncSurfaceData.lpDDSurface = peSurface;
SyncSurfaceData.dwSurfaceOffset = (DWORD) peSurface->fpVidMem;
SyncSurfaceData.fpLockPtr = peSurface->fpVidMem
+ (FLATPTR) peDirectDrawGlobal->HalInfo.vmiData.pvPrimary;
SyncSurfaceData.lPitch = peSurface->lPitch;
EDD_DEVLOCK eDevLock(peDirectDrawGlobal);
// Call the driver to let it fill in the rest of the values:
if ((!peDirectDrawGlobal->bSuspended) &&
(peDirectDrawGlobal->DxApiCallBacks.SyncSurfaceData))
{
peDirectDrawGlobal->
DxApiCallBacks.SyncSurfaceData(&SyncSurfaceData);
}
// Fields updated by the driver:
peDxSurface->dwSurfaceOffset = SyncSurfaceData.dwSurfaceOffset;
peDxSurface->fpLockPtr = SyncSurfaceData.fpLockPtr;
peDxSurface->lPitch = SyncSurfaceData.lPitch;
peDxSurface->dwOverlayOffset = SyncSurfaceData.dwOverlayOffset;
peDxSurface->dwDriverReserved1 = SyncSurfaceData.dwDriverReserved1;
peDxSurface->dwDriverReserved2 = SyncSurfaceData.dwDriverReserved2;
peDxSurface->dwDriverReserved3 = SyncSurfaceData.dwDriverReserved3;
peDxSurface->dwDriverReserved4 = SyncSurfaceData.dwDriverReserved4;
// Fields taken straight from the surface structure:
peDxSurface->ddsCaps = peSurface->ddsCaps.dwCaps;
peDxSurface->dwWidth = peSurface->wWidth;
peDxSurface->dwHeight = peSurface->wHeight;
peDxSurface->dwOverlayFlags = peSurface->dwOverlayFlags;
peDxSurface->dwFormatFlags = peSurface->ddpfSurface.dwFlags;
peDxSurface->dwFormatFourCC = peSurface->ddpfSurface.dwFourCC;
peDxSurface->dwFormatBitCount = peSurface->ddpfSurface.dwRGBBitCount;
peDxSurface->dwRBitMask = peSurface->ddpfSurface.dwRBitMask;
peDxSurface->dwGBitMask = peSurface->ddpfSurface.dwGBitMask;
peDxSurface->dwBBitMask = peSurface->ddpfSurface.dwBBitMask;
peDxSurface->dwOverlaySrcWidth = peSurface->dwOverlaySrcWidth;
peDxSurface->dwOverlaySrcHeight = peSurface->dwOverlaySrcHeight;
peDxSurface->dwOverlayDestWidth = peSurface->dwOverlayDestWidth;
peDxSurface->dwOverlayDestHeight = peSurface->dwOverlayDestHeight;
}
}
/******************************Public*Routine******************************\
* DWORD vDdSynchronizeVideoPort
*
* Updates the EDD_DXVIDEOPORT structure using the master EDD_VIDEOPORT
* structure, with some help from the driver.
*
* Analagous to Win95's SyncKernelVideoPort routine.
*
* This routine lets a driver use fields from the larger, pageable version
* of the DD_VIDEOPORT_LOCAL structure used by the display driver to set
* fields in the smaller, non-pageable version of the corresponding
* DDVIDEOPORTDATA structure used by the miniport.
*
* 14-Apr-1997 -by- J. Andrew Goossen [andrewgo]
* Wrote it.
\**************************************************************************/
VOID
vDdSynchronizeVideoPort(
EDD_VIDEOPORT* peVideoPort
)
{
EDD_DXVIDEOPORT* peDxVideoPort;
EDD_DIRECTDRAW_GLOBAL* peDirectDrawGlobal;
DD_SYNCVIDEOPORTDATA SyncVideoPortData;
peDirectDrawGlobal = peVideoPort->peDirectDrawGlobal;
peDxVideoPort = peVideoPort->peDxVideoPort;
if (peDxVideoPort != NULL)
{
RtlZeroMemory(&SyncVideoPortData, sizeof(SyncVideoPortData));
SyncVideoPortData.lpDD = peDirectDrawGlobal;
SyncVideoPortData.lpVideoPort = peVideoPort;
SyncVideoPortData.dwVBIHeight = peVideoPort->ddvpInfo.dwVBIHeight;
if (peVideoPort->ddvpInfo.dwVPFlags & DDVP_PRESCALE)
{
SyncVideoPortData.dwHeight = peVideoPort->ddvpInfo.dwPrescaleHeight;
}
else if (peVideoPort->ddvpInfo.dwVPFlags & DDVP_CROP)
{
SyncVideoPortData.dwHeight = peVideoPort->ddvpInfo.rCrop.bottom -
peVideoPort->ddvpInfo.rCrop.top;
}
else
{
SyncVideoPortData.dwHeight = peVideoPort->ddvpDesc.dwFieldHeight;
}
if (peVideoPort->ddvpInfo.dwVPFlags & DDVP_INTERLEAVE)
{
SyncVideoPortData.dwHeight *= 2;
}
EDD_DEVLOCK eDevLock(peDirectDrawGlobal);
// Call the driver to let it fill in the rest of the values:
if ((peDirectDrawGlobal->bSuspended) &&
(peDirectDrawGlobal->DxApiCallBacks.SyncVideoPortData))
{
peDirectDrawGlobal->
DxApiCallBacks.SyncVideoPortData(&SyncVideoPortData);
}
// Fields updated by the driver:
peDxVideoPort->dwOriginOffset = SyncVideoPortData.dwOriginOffset;
peDxVideoPort->dwHeight = SyncVideoPortData.dwHeight;
peDxVideoPort->dwVBIHeight = SyncVideoPortData.dwVBIHeight;
peDxVideoPort->dwDriverReserved1 = SyncVideoPortData.dwDriverReserved1;
peDxVideoPort->dwDriverReserved2 = SyncVideoPortData.dwDriverReserved2;
peDxVideoPort->dwDriverReserved3 = SyncVideoPortData.dwDriverReserved3;
// Fields taken straight from the videoport structure:
peDxVideoPort->dwVideoPortId = peVideoPort->ddvpDesc.dwVideoPortID;
peDxVideoPort->dwVPFlags = peVideoPort->ddvpInfo.dwVPFlags;
if( ( peDxVideoPort->dwVBIHeight > 0 ) &&
( peDxVideoPort->dwVPFlags & DDVP_INTERLEAVE ) &&
!( peDxVideoPort->dwVPFlags & DDVP_VBINOINTERLEAVE ) )
{
peDxVideoPort->flFlags |= DD_DXVIDEOPORT_FLAG_VBI_INTERLEAVED;
}
else
{
peDxVideoPort->flFlags &= ~DD_DXVIDEOPORT_FLAG_VBI_INTERLEAVED;
}
}
}
/******************************Public*Routine******************************\
* HANDLE hDdOpenDxApiSurface
*
* Opens a DXAPI representation of a surface
*
* 20-Oct-1997 -by- smac
* Wrote it.
\**************************************************************************/
HANDLE
hDdOpenDxApiSurface(
EDD_SURFACE* peSurface
)
{
DDOPENSURFACEIN OpenSurfaceIn;
DDOPENSURFACEOUT OpenSurfaceOut;
HANDLE hHandle;
hHandle = NULL;
// Allocate a DXAPI object:
OpenSurfaceIn.hDirectDraw = peSurface->peDirectDrawGlobal->hDirectDraw;
OpenSurfaceIn.dwSurfaceHandle = (ULONG_PTR) peSurface->hGet();
OpenSurfaceIn.pfnSurfaceClose = vDdNullCallBack;
peSurface->peDirectDrawGlobal->pfnDxApi(DD_DXAPI_OPENSURFACE,
&OpenSurfaceIn,
sizeof(OpenSurfaceIn),
&OpenSurfaceOut,
sizeof(OpenSurfaceOut));
if( ( OpenSurfaceOut.ddRVal == DD_OK ) &&
( OpenSurfaceOut.hSurface != NULL ) )
{
hHandle = OpenSurfaceOut.hSurface;
vDdSynchronizeSurface( peSurface );
}
return hHandle;
}
/******************************Public*Routine******************************\
* HANDLE hDdCloseDxApiSurface
*
* Closes a DXAPI representation of a surface
*
* 21-Oct-1997 -by- smac
* Wrote it.
\**************************************************************************/
VOID
vDdCloseDxApiSurface(
EDD_SURFACE* peSurface
)
{
DDCLOSEHANDLE CloseHandle;
DWORD dwRet;
CloseHandle.hHandle = peSurface->hSurface;
peSurface->peDirectDrawGlobal->pfnDxApi(DD_DXAPI_CLOSEHANDLE,
&CloseHandle,
sizeof(CloseHandle),
&dwRet,
sizeof(dwRet));
ASSERTGDI(dwRet == DD_OK, "Expected DD_OK");
peSurface->hSurface = NULL;
}
/******************************Public*Routine******************************\
* BOOL bDdUpdateLinksAndSynchronize
*
* A bidirectional link is maintained between a videoport and its active
* surfaces:
*
* 1. From each surface to the active videoport;
* 2. From the videoport to each of its active surfaces.
*
* This routine does all the maintaining of those links, automatically
* removing links from surfaces that are no longer used, and informing
* the software autoflipper of the change.
*
* 14-Apr-1997 -by- J. Andrew Goossen [andrewgo]
* Wrote it.
\**************************************************************************/
BOOL
bDdUpdateLinksAndSynchronize(
EDD_VIDEOPORT* peVideoPort,
BOOL bNewVideo, // FALSE if 'video' parameters should
EDD_SURFACE** apeNewVideo, // be ignored and current video state
ULONG cAutoflipVideo, // should remain unchanged
BOOL bNewVbi, // FALSE if 'VBI' parameters should
EDD_SURFACE** apeNewVbi, // be ignored and current VBI state
ULONG cAutoflipVbi // should remain unchanged
)
{
EDD_DIRECTDRAW_GLOBAL* peDirectDrawGlobal;
EDD_DXVIDEOPORT* peDxVideoPort;
// EDD_SURFACE* apeTempVideo[MAX_AUTOFLIP_BUFFERS];
// EDD_SURFACE* apeTempVbi[MAX_AUTOFLIP_BUFFERS];
EDD_DXSURFACE* apeDxNewVideo[MAX_AUTOFLIP_BUFFERS];
EDD_DXSURFACE* apeDxNewVbi[MAX_AUTOFLIP_BUFFERS];
ULONG i;
BOOL bOk;
peDirectDrawGlobal = peVideoPort->peDirectDrawGlobal;
peDxVideoPort = peVideoPort->peDxVideoPort;
if (peDxVideoPort == NULL)
return(TRUE);
DD_ASSERTDEVLOCK(peDirectDrawGlobal);
// First, check to make sure the surfaces have been opened
bOk = TRUE;
for (i = 0; i < cAutoflipVideo; i++)
{
if( ( apeNewVideo[i] == NULL ) ||
( apeNewVideo[i]->hSurface == NULL ) )
{
bOk = FALSE;
}
}
for (i = 0; i < cAutoflipVbi; i++)
{
if( ( apeNewVbi[i] == NULL ) ||
( apeNewVbi[i]->hSurface == NULL ) )
{
bOk = FALSE;
}
}
if (!bOk)
{
return(FALSE);
}
// Remove the videoport links from the old surfaces, and stash a copy
// of the list for later:
for (i = 0; i < peVideoPort->cAutoflipVideo; i++)
{
peVideoPort->apeSurfaceVideo[i]->lpVideoPort = NULL;
if( peVideoPort->apeSurfaceVideo[i]->peDxSurface != NULL )
{
peVideoPort->apeSurfaceVideo[i]->peDxSurface->peDxVideoPort = NULL;
}
}
for (i = 0; i < peVideoPort->cAutoflipVbi; i++)
{
peVideoPort->apeSurfaceVbi[i]->lpVideoPort = NULL;
if( peVideoPort->apeSurfaceVbi[i]->peDxSurface != NULL )
{
peVideoPort->apeSurfaceVbi[i]->peDxSurface->peDxVideoPort = NULL;
}
}
// Now add the links to the new surfaces:
for (i = 0; i < cAutoflipVideo; i++)
{
peVideoPort->apeSurfaceVideo[i] = apeNewVideo[i];
apeNewVideo[i]->lpVideoPort = peVideoPort;
apeDxNewVideo[i] = apeNewVideo[i]->peDxSurface;
}
for (i = 0; i < cAutoflipVbi; i++)
{
peVideoPort->apeSurfaceVbi[i] = apeNewVbi[i];
apeNewVbi[i]->lpVideoPort = peVideoPort;
apeDxNewVbi[i] = apeNewVbi[i]->peDxSurface;
}
// Now modify the autoflip buffers, being careful to synchronize with
// the software-autoflip DPC. Note that this does stuff like sets
// peDxVideoPort->cAutoflipVbi.
peDirectDrawGlobal->pfnAutoflipUpdate(peDxVideoPort,
apeDxNewVideo,
cAutoflipVideo,
apeDxNewVbi,
cAutoflipVbi);
peVideoPort->cAutoflipVideo = cAutoflipVideo;
peVideoPort->cAutoflipVbi = cAutoflipVbi;
// Finally, Update some last public fields in the videoport structure:
peVideoPort->dwNumAutoflip = cAutoflipVideo;
peVideoPort->dwNumVBIAutoflip = cAutoflipVbi;
peVideoPort->lpSurface = (cAutoflipVideo == 0) ? NULL : apeNewVideo[0];
peVideoPort->lpVBISurface = (cAutoflipVbi == 0) ? NULL : apeNewVbi[0];
return(TRUE);
}
/******************************Public*Routine******************************\
* VOID vDdDxApiFreeDirectDraw
*
* 14-Apr-1997 -by- J. Andrew Goossen [andrewgo]
* Wrote it.
\**************************************************************************/
VOID
vDdDxApiFreeDirectDraw(
DXOBJ* pDxObj,
BOOL bDoCallBack
)
{
EDD_DXDIRECTDRAW* peDxDirectDraw;
DXOBJ* pDxTmp;
ASSERTGDI(pDxObj->iDxType == DXT_DIRECTDRAW, "Invalid object");
peDxDirectDraw = pDxObj->peDxDirectDraw;
EDD_DEVLOCK eDevLock(peDxDirectDraw->hdev);
if (bDoCallBack)
{
pDxObj->pfnClose(pDxObj->dwEvent,pDxObj->pContext, 0, 0);
}
// Remove this DXOBJ instance from the list hanging off the DXAPI object:
if (peDxDirectDraw->pDxObj_List == pDxObj)
{
peDxDirectDraw->pDxObj_List = pDxObj->pDxObj_Next;
}
else
{
for (pDxTmp = peDxDirectDraw->pDxObj_List;
pDxTmp->pDxObj_Next != pDxObj;
pDxTmp = pDxTmp->pDxObj_Next)
{
ASSERTGDI(pDxTmp->iDxType == DXT_DIRECTDRAW, "Unexpected type");
ASSERTGDI(pDxTmp->pDxObj_Next != NULL, "Couldn't find node");
}
pDxTmp->pDxObj_Next = pDxObj->pDxObj_Next;
}
// Free the DXOBJ instance:
pDxObj->iDxType = DXT_INVALID;
vDdDxObjFree(pDxObj);
// If there are no more DXOBJ instances of the DirectDraw DXAPI object,
// we can free the non-paged DXAPI part of the DirectDraw structure:
if (peDxDirectDraw->pDxObj_List == NULL)
{
if ((peDxDirectDraw->pDxEvent_PassiveList != NULL) ||
(peDxDirectDraw->pDxEvent_DispatchList[CLIENT_DISPATCH_LIST] != NULL))
{
KdPrint(("vDdDxApiFreeDirectDraw: A kernel-mode DXAPI client didn't unregister all\n"));
KdPrint((" its events when it received CLOSE call-backs. This will cause at\n"));
KdPrint((" best a memory leak and at worst a crash!\n"));
RIP("The DXAPI client must be fixed.");
}
if (peDxDirectDraw->peDirectDrawGlobal != NULL)
{
peDxDirectDraw->peDirectDrawGlobal->peDxDirectDraw = NULL;
}
vDdDxObjFree(peDxDirectDraw);
}
}
/******************************Public*Routine******************************\
* VOID vDdDxApiFreeVideoPort
*
* 14-Apr-1997 -by- J. Andrew Goossen [andrewgo]
* Wrote it.
\**************************************************************************/
VOID
vDdDxApiFreeVideoPort(
DXOBJ* pDxObj,
BOOL bDoCallBack
)
{
EDD_DXDIRECTDRAW* peDxDirectDraw;
EDD_DXVIDEOPORT* peDxVideoPort;
DXOBJ* pDxObjTmp;
DXAPI_EVENT* pDxEventTmp;
ASSERTGDI(pDxObj->iDxType == DXT_VIDEOPORT, "Invalid object");
peDxVideoPort = pDxObj->peDxVideoPort;
peDxDirectDraw = peDxVideoPort->peDxDirectDraw;
EDD_DEVLOCK eDevLock(peDxDirectDraw->hdev);
if (bDoCallBack)
{
pDxObj->pfnClose(pDxObj->dwEvent, pDxObj->pContext, 0, 0);
}
// Remove this DXOBJ instance from the list hanging off the DXAPI object:
if (peDxVideoPort->pDxObj_List == pDxObj)
{
peDxVideoPort->pDxObj_List = pDxObj->pDxObj_Next;
}
else
{
for (pDxObjTmp = peDxVideoPort->pDxObj_List;
pDxObjTmp->pDxObj_Next != pDxObj;
pDxObjTmp = pDxObjTmp->pDxObj_Next)
{
ASSERTGDI(pDxObjTmp->iDxType == DXT_VIDEOPORT, "Unexpected type");
ASSERTGDI(pDxObjTmp->pDxObj_Next != NULL, "Couldn't find node");
}
pDxObjTmp->pDxObj_Next = pDxObj->pDxObj_Next;
}
// Free the notification event if one is present
if (peDxVideoPort->pNotifyEvent != NULL)
{
PKEVENT pTemp = NULL;
HANDLE hEvent = peDxVideoPort->pNotifyEventHandle;
NTSTATUS Status;
peDxVideoPort->pNotifyEvent = NULL;
peDxVideoPort->pNotifyEventHandle = NULL;
// Make sure that the handle hasn't been freed by the OS already
Status = ObReferenceObjectByHandle( hEvent,
0,
0,
KernelMode,
(PVOID *) &pTemp,
NULL );
if ((pTemp != NULL) && (Status != STATUS_INVALID_HANDLE))
{
ObDereferenceObject(pTemp);
ZwClose (hEvent);
}
// Un-page lock memory
peDxVideoPort->pNotifyBuffer = NULL;
if (peDxVideoPort->pNotifyMdl != NULL)
{
MmUnlockPages (peDxVideoPort->pNotifyMdl);
IoFreeMdl (peDxVideoPort->pNotifyMdl);
peDxVideoPort->pNotifyMdl = NULL;
}
}
// Free the DXOBJ instance:
pDxObj->iDxType = DXT_INVALID;
vDdDxObjFree(pDxObj);
// If there are no more DXOBJ instances of the VideoPort DXAPI object,
// we can free the non-paged DXAPI part of the VideoPort structure:
if (peDxVideoPort->pDxObj_List == NULL)
{
ASSERTGDI(peDxDirectDraw != NULL, "Unexpected NULL peDxDirectDraw");
for (pDxEventTmp = peDxDirectDraw->pDxEvent_DispatchList[CLIENT_DISPATCH_LIST];
pDxEventTmp != NULL;
pDxEventTmp = pDxEventTmp->pDxEvent_Next)
{
if (pDxEventTmp->peDxVideoPort == peDxVideoPort)
{
KdPrint(("vDdDxApiFreeVideoPort: A kernel-mode DXAPI client didn't unregister all\n"));
KdPrint((" its videoport events when it received CLOSE call-backs. This will\n"));
KdPrint((" cause at best a memory leak and at worst a crash!\n"));
RIP("The DXAPI client must be fixed.");
}
}
if (peDxVideoPort->peVideoPort != NULL)
{
// If we are actually freeing the video port, we need to lose
// any capture objects that are associated with it
while( peDxVideoPort->peDxCapture != NULL )
{
vDdLoseDxObjects( peDxDirectDraw->peDirectDrawGlobal,
peDxVideoPort->peDxCapture->pDxObj_List,
(PVOID) peDxVideoPort->peDxCapture,
LO_CAPTURE );
}
peDxVideoPort->peVideoPort->peDxVideoPort = NULL;
}
vDdDxObjFree(peDxVideoPort);
}
}
/******************************Public*Routine******************************\
* VOID vDdDxApiFreeCapture
*
* 10-Apr-1998 -by- Scott MacDonald [smac]
* Wrote it.
\**************************************************************************/
VOID
vDdDxApiFreeCapture(
DXOBJ* pDxObj,
BOOL bDoCallBack
)
{
EDD_DXCAPTURE* peDxCapture;
EDD_DXVIDEOPORT* peDxVideoPort;
ASSERTGDI(pDxObj->iDxType == DXT_CAPTURE, "Invalid object");
peDxCapture = pDxObj->peDxCapture;
peDxVideoPort = peDxCapture->peDxVideoPort;
if (bDoCallBack)
{
pDxObj->pfnClose(pDxObj->dwEvent, pDxObj->pContext, 0, 0);
}
// Free the DXOBJ instance:
pDxObj->iDxType = DXT_INVALID;
vDdDxObjFree(pDxObj);
// Unassociate the capture object from the video port. Since this
// must be synchronized with the DPC, we need to call DxApi to do this.
if( peDxVideoPort != NULL )
{
EDD_DXDIRECTDRAW* peDxDirectDraw;
EDD_DIRECTDRAW_GLOBAL* peDirectDrawGlobal;
peDxDirectDraw = peDxVideoPort->peDxDirectDraw;
EDD_DEVLOCK eDevLock(peDxDirectDraw->hdev);
peDirectDrawGlobal = peDxDirectDraw->peDirectDrawGlobal;
peDirectDrawGlobal->pfnUpdateCapture( peDxVideoPort,
peDxCapture, TRUE );
}
vDdDxObjFree(peDxCapture);
}
/******************************Public*Routine******************************\
* VOID vDdDxApiFreeSurface
*
* 14-Apr-1997 -by- J. Andrew Goossen [andrewgo]
* Wrote it.
\**************************************************************************/
VOID
vDdDxApiFreeSurface(
DXOBJ* pDxObj,
BOOL bDoCallBack
)
{
EDD_DXSURFACE* peDxSurface;
EDD_DXDIRECTDRAW* peDxDirectDraw;
DXOBJ* pDxTmp;
ASSERTGDI(pDxObj->iDxType == DXT_SURFACE, "Invalid object");
peDxSurface = pDxObj->peDxSurface;
peDxDirectDraw = peDxSurface->peDxDirectDraw;
EDD_DEVLOCK eDevLock(peDxDirectDraw->hdev);
if (bDoCallBack)
{
pDxObj->pfnClose(pDxObj->dwEvent, pDxObj->pContext, 0, 0);
}
// Remove this DXOBJ instance from the list hanging off the DXAPI object:
if (peDxSurface->pDxObj_List == pDxObj)
{
peDxSurface->pDxObj_List = pDxObj->pDxObj_Next;
}
else
{
for (pDxTmp = peDxSurface->pDxObj_List;
pDxTmp->pDxObj_Next != pDxObj;
pDxTmp = pDxTmp->pDxObj_Next)
{
ASSERTGDI(pDxTmp->iDxType == DXT_SURFACE, "Unexpected type");
ASSERTGDI(pDxTmp->pDxObj_Next != NULL, "Couldn't find node");
}
pDxTmp->pDxObj_Next = pDxObj->pDxObj_Next;
}
// Free the DXOBJ instance:
pDxObj->iDxType = DXT_INVALID;
vDdDxObjFree(pDxObj);
// If there are no more DXOBJ instances of the Surface DXAPI object,
// we can free the non-paged DXAPI part of the Surface structure:
if (peDxSurface->pDxObj_List == NULL)
{
if (peDxSurface->peSurface != NULL)
{
peDxSurface->peSurface->peDxSurface = NULL;
}
vDdDxObjFree(peDxSurface);
}
}
/******************************Public*Routine******************************\
* VOID vDdStopVideoPort
*
* Makes an emergency stop of the videoport.
*
* 16-Feb-1997 -by- J. Andrew Goossen [andrewgo]
* Wrote it.
\**************************************************************************/
VOID
vDdStopVideoPort(
EDD_VIDEOPORT* peVideoPort
)
{
EDD_DXVIDEOPORT* peDxVideoPort;
DD_UPDATEVPORTDATA UpdateVPortData;
EDD_DIRECTDRAW_GLOBAL* peDirectDrawGlobal;
BOOL b;
peDirectDrawGlobal = peVideoPort->peDirectDrawGlobal;
peDxVideoPort = peVideoPort->peDxVideoPort;
// Stop the videoport itself:
UpdateVPortData.lpDD = peDirectDrawGlobal;
UpdateVPortData.lpVideoPort = peVideoPort;
UpdateVPortData.lplpDDVBISurface = NULL;
UpdateVPortData.lplpDDSurface = NULL;
UpdateVPortData.lpVideoInfo = NULL;
UpdateVPortData.dwNumAutoflip = 0;
UpdateVPortData.dwFlags = DDRAWI_VPORTSTOP;
EDD_DEVLOCK eDevlock(peDirectDrawGlobal);
ASSERTGDI(peDirectDrawGlobal->VideoPortCallBacks.UpdateVideoPort != NULL,
"Videoport object shouldn't have been created if UpdateVideoPort NULL");
// Disable video port VSYNC IRQ
if (peDxVideoPort != NULL)
{
// Shut down software autoflipping (the autoflipping routine peeks
// at these values, so this is sufficient):
peDxVideoPort->bSoftwareAutoflip = FALSE;
peDxVideoPort->flFlags &= ~(DD_DXVIDEOPORT_FLAG_AUTOFLIP|DD_DXVIDEOPORT_FLAG_AUTOFLIP_VBI);
peDxVideoPort->bSkip = FALSE;
peDxVideoPort->dwSetStateField = 0;
if (peDxVideoPort->flFlags & DD_DXVIDEOPORT_FLAG_ON)
{
peDxVideoPort->flFlags &= ~DD_DXVIDEOPORT_FLAG_ON;
peDirectDrawGlobal->pfnEnableIRQ(peDxVideoPort, FALSE );
}
}
if (!peDirectDrawGlobal->bSuspended &&
(peDirectDrawGlobal->VideoPortCallBacks.UpdateVideoPort != NULL))
{
peDirectDrawGlobal->VideoPortCallBacks.UpdateVideoPort(&UpdateVPortData);
}
// Update the links to reflect the fact that no surface is a
// destination for this videoport anymore:
b = bDdUpdateLinksAndSynchronize(peVideoPort, TRUE, NULL, 0, TRUE, NULL, 0);
ASSERTGDI(b, "vDdStopVideoPort: Shouldn't fail bDdUpdateLinkAndSynchronize");
}
/******************************Public*Routine******************************\
* VOID LoseDxObjects
*
* Notifies all clients using the resource that it can't be used anymore.
* It also notifies DXAPI.SYS that the resource is unusable.
*
* 04-Nov-1997 -by- smac
* Wrote it.
\**************************************************************************/
VOID
vDdLoseDxObjects(
EDD_DIRECTDRAW_GLOBAL* peDirectDrawGlobal,
DXOBJ* pDxObj,
PVOID pDxThing,
DWORD dwType
)
{
if( pDxObj != NULL )
{
while( pDxObj != NULL )
{
pDxObj->pfnClose(pDxObj->dwEvent, pDxObj->pContext, 0, 0);
pDxObj = pDxObj->pDxObj_Next;
}
peDirectDrawGlobal->pfnLoseObject( pDxThing, (LOTYPE) dwType );
}
}
/******************************Public*Routine******************************\
* BOOL bDdDeleteVideoPortObject
*
* Deletes a kernel-mode representation of the videoport object.
*
* 16-Feb-1997 -by- J. Andrew Goossen [andrewgo]
* Wrote it.
\**************************************************************************/
BOOL
bDdDeleteVideoPortObject(
HANDLE hVideoPort,
DWORD* pdwRet // For returning driver return code, may be NULL
)
{
BOOL bRet;
DWORD dwRet;
EDD_DXVIDEOPORT* peDxVideoPort;
EDD_VIDEOPORT* peVideoPort;
EDD_VIDEOPORT* peTmp;
VOID* pvRemove;
EDD_DIRECTDRAW_GLOBAL* peDirectDrawGlobal;
EDD_DIRECTDRAW_LOCAL* peDirectDrawLocal;
DD_DESTROYVPORTDATA DestroyVPortData;
DXOBJ* pDxObj;
DXOBJ* pDxObjNext;
bRet = FALSE;
dwRet = DDHAL_DRIVER_HANDLED;
peVideoPort = (EDD_VIDEOPORT*) DdHmgLock((HDD_OBJ) hVideoPort, DD_VIDEOPORT_TYPE, FALSE);
if (peVideoPort != NULL)
{
peDirectDrawGlobal = peVideoPort->peDirectDrawGlobal;
// Make sure the videoport has been turned off:
vDdStopVideoPort(peVideoPort);
// If there are any capture objects associated witht he video port,
// lose them now
peDxVideoPort = peVideoPort->peDxVideoPort;
while( peDxVideoPort && (peDxVideoPort->peDxCapture != NULL) )
{
vDdLoseDxObjects( peDirectDrawGlobal,
peDxVideoPort->peDxCapture->pDxObj_List,
(PVOID) peDxVideoPort->peDxCapture,
LO_CAPTURE );
}
// Free the DXAPI instance of the videoport object
if (peVideoPort->hVideoPort != NULL)
{
vDdDxApiFreeVideoPort( (DXOBJ*) peVideoPort->hVideoPort, FALSE);
peVideoPort->hVideoPort = NULL;
peDxVideoPort = peVideoPort->peDxVideoPort;
}
// Notify clients that their open objects are lost
if (peDxVideoPort) {
vDdLoseDxObjects( peDirectDrawGlobal,
peDxVideoPort->pDxObj_List,
(PVOID) peDxVideoPort,
LO_VIDEOPORT );
}
pvRemove = DdHmgRemoveObject((HDD_OBJ) hVideoPort,
DdHmgQueryLock((HDD_OBJ) hVideoPort),
0,
TRUE,
DD_VIDEOPORT_TYPE);
ASSERTGDI(pvRemove != NULL, "Outstanding surfaces locks");
// Hold the devlock while we call the driver and while we muck
// around in the videoport list:
EDD_DEVLOCK eDevlock(peDirectDrawGlobal);
if (peVideoPort->fl & DD_VIDEOPORT_FLAG_DRIVER_CREATED)
{
// Call the driver if it created the object:
if (peDirectDrawGlobal->VideoPortCallBacks.DestroyVideoPort)
{
DestroyVPortData.lpDD = peDirectDrawGlobal;
DestroyVPortData.lpVideoPort = peVideoPort;
DestroyVPortData.ddRVal = DDERR_GENERIC;
dwRet = peDirectDrawGlobal->
VideoPortCallBacks.DestroyVideoPort(&DestroyVPortData);
}
}
// Remove from the videoport linked-list:
peDirectDrawLocal = peVideoPort->peDirectDrawLocal;
if (peDirectDrawLocal->peVideoPort_DdList == peVideoPort)
{
peDirectDrawLocal->peVideoPort_DdList
= peVideoPort->peVideoPort_DdNext;
}
else
{
for (peTmp = peDirectDrawLocal->peVideoPort_DdList;
peTmp->peVideoPort_DdNext != peVideoPort;
peTmp = peTmp->peVideoPort_DdNext)
;
peTmp->peVideoPort_DdNext = peVideoPort->peVideoPort_DdNext;
}
// Unload DXAPI.SYS if no other video port is using it
if (peDirectDrawLocal->peVideoPort_DdList == NULL)
{
vDdUnloadDxApi( peDirectDrawGlobal );
}
// We're all done with this object, so free the memory and
// leave:
DdFreeObject(peVideoPort, DD_VIDEOPORT_TYPE);
bRet = TRUE;
}
else
{
WARNING1("bDdDeleteVideoPortObject: Bad handle or object was busy\n");
}
if (pdwRet != NULL)
{
*pdwRet = dwRet;
}
return(bRet);
}
/******************************Public*Routine******************************\
* DWORD DdDxApiOpenDirectDraw
*
* 14-Apr-1997 -by- J. Andrew Goossen [andrewgo]
* Wrote it.
\**************************************************************************/
VOID
APIENTRY
DdDxApiOpenDirectDraw(
DDOPENDIRECTDRAWIN* pOpenDirectDrawIn,
DDOPENDIRECTDRAWOUT* pOpenDirectDrawOut,
PKDEFERRED_ROUTINE pfnEventDpc,
ULONG DxApiPrivateVersionNumber
)
{
HANDLE hDirectDraw;
EDD_LOCK_DIRECTDRAW eLockDirectDraw;
EDD_DIRECTDRAW_LOCAL* peDirectDrawLocal;
EDD_DIRECTDRAW_GLOBAL* peDirectDrawGlobal;
DXOBJ* pDxObj;
EDD_DXDIRECTDRAW* peDxDirectDraw;
ASSERTGDI(KeGetCurrentIrql() == PASSIVE_LEVEL,
"DdDxApiOpenDirectDraw: Callable only at passive level (it's not pageable)");
hDirectDraw = 0; // Assume failure
// We use the private version number to ensure consistency between
// win32k.sys and dxapi.sys. Since dxapi.sys is dynamically loaded,
// I am worried about a scenario where a service pack is applied that
// updates both dxapi.sys and win32k.sys -- if the machine isn't
// rebooted, the old win32k.sys will remain loaded but the new dxapi.sys
// may be loaded, possibly causing a crash.
peDirectDrawLocal
= eLockDirectDraw.peLock((HANDLE) pOpenDirectDrawIn->dwDirectDrawHandle);
if ((peDirectDrawLocal != NULL) ||
(DxApiPrivateVersionNumber != DXAPI_PRIVATE_VERSION_NUMBER))
{
peDirectDrawGlobal = peDirectDrawLocal->peDirectDrawGlobal;
pDxObj = pDdDxObjHandleAllocate(DXT_DIRECTDRAW,
pOpenDirectDrawIn->pfnDirectDrawClose,
DDNOTIFY_CLOSEDIRECTDRAW,
pOpenDirectDrawIn->pContext);
if (pDxObj != NULL)
{
// Among other things, enforce synchronization while we muck
// around in the global DirectDraw object:
EDD_DEVLOCK eDevLock(peDirectDrawGlobal);
peDxDirectDraw = peDirectDrawGlobal->peDxDirectDraw;
if (peDxDirectDraw != NULL)
{
// Just add this object to the list hanging off the DirectDraw
// object:
pDxObj->peDxDirectDraw = peDxDirectDraw;
pDxObj->pDxObj_Next = peDxDirectDraw->pDxObj_List;
peDxDirectDraw->pDxObj_List = pDxObj;
// Success!
hDirectDraw = (HANDLE) pDxObj;
}
else
{
peDxDirectDraw = (EDD_DXDIRECTDRAW*) pDdDxObjDataAllocate(
sizeof(*peDxDirectDraw),
'dxdG');
if (peDxDirectDraw)
{
RtlZeroMemory(peDxDirectDraw, sizeof(*peDxDirectDraw));
pDxObj->peDxDirectDraw = peDxDirectDraw;
// We need to access some capabilities at raised IRQL,
// so copy those from the paged 'peDirectDrawGlobal'
// to the non-paged 'peDxDirectDraw' now:
peDxDirectDraw->DxApiInterface
= peDirectDrawGlobal->DxApiInterface;
peDxDirectDraw->HwDeviceExtension
= peDirectDrawGlobal->HwDeviceExtension;
peDxDirectDraw->dwIRQCaps
= peDirectDrawGlobal->DDKernelCaps.dwIRQCaps;
peDxDirectDraw->peDirectDrawGlobal
= peDirectDrawGlobal;
peDxDirectDraw->hdev
= peDirectDrawGlobal->hdev;
peDirectDrawGlobal->peDxDirectDraw = peDxDirectDraw;
peDxDirectDraw->pDxObj_List = pDxObj;
// Initialize our kernel structures use for interrupts
// and handling raised IRQL callers.
KeInitializeDpc(&peDxDirectDraw->EventDpc,
pfnEventDpc,
peDxDirectDraw);
KeInitializeSpinLock(&peDxDirectDraw->SpinLock);
// Success!
hDirectDraw = (HANDLE) pDxObj;
}
}
if (!hDirectDraw)
{
vDdDxObjFree(pDxObj);
}
}
}
else
{
WARNING("DdDxApiOpenDirectDraw: Invalid dwDirectDrawHandle, failing\n");
}
pOpenDirectDrawOut->hDirectDraw = hDirectDraw;
pOpenDirectDrawOut->ddRVal = (hDirectDraw != NULL) ? DD_OK : DDERR_GENERIC;
}
/******************************Public*Routine******************************\
* DWORD DdDxApiOpenVideoPort
*
* This routine lets a driver use fields from the larger, pageable version
* of the DD_SURFACE_* structures used by the display driver to set
* fields in the smaller, non-pageable version of the corresponding
* DDSURFACEDATA structure used by the miniport.
*
* 14-Apr-1997 -by- J. Andrew Goossen [andrewgo]
* Wrote it.
\**************************************************************************/
VOID
APIENTRY
DdDxApiOpenVideoPort(
DDOPENVIDEOPORTIN* pOpenVideoPortIn,
DDOPENVIDEOPORTOUT* pOpenVideoPortOut
)
{
HANDLE hVideoPort;
DXOBJ* pDxObjDirectDraw;
DXOBJ* pDxObj;
EDD_DXDIRECTDRAW* peDxDirectDraw;
EDD_DXVIDEOPORT* peDxVideoPort;
EDD_DIRECTDRAW_GLOBAL* peDirectDrawGlobal;
EDD_LOCK_VIDEOPORT eLockVideoPort;
EDD_VIDEOPORT* peVideoPort;
BOOL bFound;
EDD_DIRECTDRAW_LOCAL* peTempDirectDrawLocal;
EDD_VIDEOPORT* peTempVideoPort;
ASSERTGDI(KeGetCurrentIrql() == PASSIVE_LEVEL,
"DdDxApiOpenVideoPort: Callable only at passive level (it's not pageable)");
hVideoPort = 0; // Assume failure
pDxObjDirectDraw = (DXOBJ*) pOpenVideoPortIn->hDirectDraw;
ASSERTGDI((pDxObjDirectDraw != NULL) &&
(pDxObjDirectDraw->iDxType == DXT_DIRECTDRAW),
"DdDxApiOpenVideoPort: Invalid hDirectDraw, we're about to crash");
peDxDirectDraw = pDxObjDirectDraw->peDxDirectDraw;
// Among other things, enforce synchronization while we muck around
// in the DirectDraw object:
EDD_DEVLOCK eDevLock(peDxDirectDraw->hdev);
if (!peDxDirectDraw->bLost)
{
peDirectDrawGlobal = peDxDirectDraw->peDirectDrawGlobal;
// We need to get a handle to the video port, so we need to
// go looking for it.
bFound = FALSE;
peTempDirectDrawLocal = peDirectDrawGlobal->peDirectDrawLocalList;
while( ( peTempDirectDrawLocal != NULL ) && !bFound )
{
peTempVideoPort = peTempDirectDrawLocal->peVideoPort_DdList;
while( peTempVideoPort != NULL )
{
if( peTempVideoPort->ddvpDesc.dwVideoPortID == pOpenVideoPortIn->dwVideoPortHandle )
{
bFound = TRUE;
break;
}
peTempVideoPort = peTempVideoPort->peVideoPort_DdNext;
}
peTempDirectDrawLocal = peTempDirectDrawLocal->peDirectDrawLocalNext;
}
if( bFound )
{
peVideoPort = eLockVideoPort.peLock(
(HANDLE) peTempVideoPort->hGet());
if ((peVideoPort != NULL) &&
(peVideoPort->peDirectDrawGlobal == peDirectDrawGlobal))
{
pDxObj = pDdDxObjHandleAllocate(DXT_VIDEOPORT,
pOpenVideoPortIn->pfnVideoPortClose,
DDNOTIFY_CLOSEVIDEOPORT,
pOpenVideoPortIn->pContext);
if (pDxObj != NULL)
{
peDxVideoPort = peVideoPort->peDxVideoPort;
if (peDxVideoPort != NULL)
{
// Just add this object to the list hanging off the
// surface object:
pDxObj->peDxVideoPort = peDxVideoPort;
pDxObj->pDxObj_Next = peDxVideoPort->pDxObj_List;
peDxVideoPort->pDxObj_List = pDxObj;
// Success!
hVideoPort = (HANDLE) pDxObj;
}
else
{
peDxVideoPort = (EDD_DXVIDEOPORT*) pDdDxObjDataAllocate(
sizeof(*peDxVideoPort),
'sxdG');
if (peDxVideoPort)
{
RtlZeroMemory(peDxVideoPort, sizeof(*peDxVideoPort));
pDxObj->peDxVideoPort = peDxVideoPort;
peVideoPort->peDxVideoPort = peDxVideoPort;
peDxVideoPort->pDxObj_List = pDxObj;
peDxVideoPort->peVideoPort = peVideoPort;
peDxVideoPort->peDxDirectDraw = peDxDirectDraw;
peDxVideoPort->iCurrentVideo = 1;
peDxVideoPort->dwVideoPortID
= peVideoPort->ddvpDesc.dwVideoPortID;
vDdSynchronizeVideoPort(peVideoPort);
// Success!
hVideoPort = (HANDLE) pDxObj;
}
}
if (!hVideoPort)
{
vDdDxObjFree(pDxObj);
}
}
}
else
{
WARNING("DdDxApiOpenVideoPort: Invalid dwSurfaceHandle, failing.\n");
}
}
else
{
WARNING("DdDxApiOpenVideoPort: Invalid dwSurfaceHandle, failing.\n");
}
}
else
{
WARNING("DdDxApiOpenVideoPort: DirectDraw object is lost");
}
pOpenVideoPortOut->hVideoPort = hVideoPort;
pOpenVideoPortOut->ddRVal = (hVideoPort != NULL) ? DD_OK : DDERR_GENERIC;
}
/******************************Public*Routine******************************\
* DWORD DdDxApiOpenSurface
*
* 14-Apr-1997 -by- J. Andrew Goossen [andrewgo]
* Wrote it.
\**************************************************************************/
VOID
APIENTRY
DdDxApiOpenSurface(
DDOPENSURFACEIN* pOpenSurfaceIn,
DDOPENSURFACEOUT* pOpenSurfaceOut
)
{
HANDLE hSurface;
DXOBJ* pDxObjDirectDraw;
DXOBJ* pDxObj;
EDD_DXDIRECTDRAW* peDxDirectDraw;
EDD_DXSURFACE* peDxSurface;
EDD_DIRECTDRAW_GLOBAL* peDirectDrawGlobal;
EDD_LOCK_SURFACE eLockSurface;
EDD_SURFACE* peSurface;
ASSERTGDI(KeGetCurrentIrql() == PASSIVE_LEVEL,
"DdDxApiOpenSurface: Callable only at passive level (it's not pageable)");
hSurface = 0; // Assume failure
pDxObjDirectDraw = (DXOBJ*) pOpenSurfaceIn->hDirectDraw;
ASSERTGDI((pDxObjDirectDraw != NULL) &&
(pDxObjDirectDraw->iDxType == DXT_DIRECTDRAW),
"DdDxApiOpenSurface: Invalid hDirectDraw, we're about to crash");
peDxDirectDraw = pDxObjDirectDraw->peDxDirectDraw;
// Among other things, enforce synchronization while we muck around
// in the DirectDraw object:
EDD_DEVLOCK eDevLock(peDxDirectDraw->hdev);
if (!peDxDirectDraw->bLost)
{
peDirectDrawGlobal = peDxDirectDraw->peDirectDrawGlobal;
peSurface = eLockSurface.peLock((HANDLE) pOpenSurfaceIn->dwSurfaceHandle);
if ((peSurface != NULL) &&
(peSurface->peDirectDrawGlobal == peDirectDrawGlobal))
{
pDxObj = pDdDxObjHandleAllocate(DXT_SURFACE,
pOpenSurfaceIn->pfnSurfaceClose,
DDNOTIFY_CLOSESURFACE,
pOpenSurfaceIn->pContext);
if (pDxObj != NULL)
{
peDxSurface = peSurface->peDxSurface;
if (peDxSurface != NULL)
{
// Just add this object to the list hanging off the
// surface object:
pDxObj->peDxSurface = peDxSurface;
pDxObj->pDxObj_Next = peDxSurface->pDxObj_List;
peDxSurface->pDxObj_List = pDxObj;
// Success!
hSurface = (HANDLE) pDxObj;
}
else
{
peDxSurface = (EDD_DXSURFACE*) pDdDxObjDataAllocate(
sizeof(*peDxSurface),
'sxdG');
if (peDxSurface)
{
RtlZeroMemory(peDxSurface, sizeof(*peDxSurface));
pDxObj->peDxSurface = peDxSurface;
peSurface->peDxSurface = peDxSurface;
peDxSurface->pDxObj_List = pDxObj;
peDxSurface->peSurface = peSurface;
peDxSurface->peDxDirectDraw = peDxDirectDraw;
if( peDirectDrawGlobal->HalInfo.ddCaps.dwCaps2 &
DDCAPS2_CANBOBINTERLEAVED )
{
peDxSurface->flFlags |= DD_DXSURFACE_FLAG_CAN_BOB_INTERLEAVED;
}
if( peDirectDrawGlobal->HalInfo.ddCaps.dwCaps2 &
DDCAPS2_CANBOBNONINTERLEAVED )
{
peDxSurface->flFlags |= DD_DXSURFACE_FLAG_CAN_BOB_NONINTERLEAVED;
}
// Success!
hSurface = (HANDLE) pDxObj;
}
}
vDdSynchronizeSurface(peSurface);
if (!hSurface)
{
vDdDxObjFree(pDxObj);
}
}
}
else
{
WARNING("DdDxApiOpenSurface: Invalid dwSurfaceHandle, failing.\n");
}
}
else
{
WARNING("DdDxApiOpenSurface: DirectDraw object lost\n");
}
pOpenSurfaceOut->hSurface = hSurface;
pOpenSurfaceOut->ddRVal = (hSurface != NULL) ? DD_OK : DDERR_GENERIC;
}
/******************************Public*Routine******************************\
* DWORD DdDxApiCloseHandle
*
* 14-Apr-1997 -by- J. Andrew Goossen [andrewgo]
* Wrote it.
\**************************************************************************/
VOID
APIENTRY
DdDxApiCloseHandle(
DDCLOSEHANDLE* pCloseHandle,
DWORD* pdwRet
)
{
DXOBJ* pDxObj = (DXOBJ*) pCloseHandle->hHandle;
ASSERTGDI(KeGetCurrentIrql() == PASSIVE_LEVEL,
"DdDxApiCloseHandle: Callable only at passive level (it's not pageable)");
ASSERTGDI(pCloseHandle->hHandle != NULL,
"DdDxApiCloseHandle: Trying to close NULL handle");
switch(pDxObj->iDxType)
{
case DXT_DIRECTDRAW:
vDdDxApiFreeDirectDraw(pDxObj, TRUE);
break;
case DXT_VIDEOPORT:
vDdDxApiFreeVideoPort(pDxObj, FALSE);
break;
case DXT_SURFACE:
vDdDxApiFreeSurface(pDxObj, FALSE);
break;
case DXT_CAPTURE:
vDdDxApiFreeCapture(pDxObj, FALSE);
break;
case DXT_INVALID:
RIP("DdDxApiCloseHandle: Invalid surface. Same handle probably closed twice");
break;
default:
RIP("DdDxApiCloseHandle: Invalid surface.");
break;
}
*pdwRet = DD_OK;
}
/******************************Public*Routine******************************\
* DWORD DdDxApiOpenCaptureDevice
*
* 01-Nov-1997 -by- smac
* Wrote it.
\**************************************************************************/
VOID
APIENTRY
DdDxApiOpenCaptureDevice(
DDOPENVPCAPTUREDEVICEIN* pOpenCaptureDeviceIn,
DDOPENVPCAPTUREDEVICEOUT* pOpenCaptureDeviceOut
)
{
HANDLE hCaptureDevice;
DXOBJ* pDxObjDirectDraw;
DXOBJ* pDxObjVideoPort;
DXOBJ* pDxObj;
EDD_DXDIRECTDRAW* peDxDirectDraw;
EDD_DXVIDEOPORT* peDxVideoPort;
EDD_DXCAPTURE* peDxCapture;
EDD_DIRECTDRAW_GLOBAL* peDirectDrawGlobal;
DWORD dwRet;
ASSERTGDI(KeGetCurrentIrql() == PASSIVE_LEVEL,
"DdDxApiOpenVideoPort: Callable only at passive level (it's not pageable)");
hCaptureDevice = 0; // Assume failure
pDxObjDirectDraw = (DXOBJ*) pOpenCaptureDeviceIn->hDirectDraw;
pDxObjVideoPort = (DXOBJ*) pOpenCaptureDeviceIn->hVideoPort;
ASSERTGDI((pDxObjDirectDraw != NULL) &&
(pDxObjDirectDraw->iDxType == DXT_DIRECTDRAW),
"DdDxApiOpenCaptureDevice: Invalid hDirectDraw, we're about to crash");
ASSERTGDI((pDxObjVideoPort != NULL) &&
(pDxObjVideoPort->iDxType == DXT_VIDEOPORT),
"DdDxApiOpenCaptureDevice: Invalid hVideoPort, we're about to crash");
peDxDirectDraw = pDxObjDirectDraw->peDxDirectDraw;
peDxVideoPort = pDxObjVideoPort->peDxVideoPort;
ASSERTGDI((pOpenCaptureDeviceIn->dwFlags == DDOPENCAPTURE_VIDEO) ||
(pOpenCaptureDeviceIn->dwFlags == DDOPENCAPTURE_VBI),
"DdDxApiOpenCaptureDevice: Invalid flags specified");
ASSERTGDI((pOpenCaptureDeviceIn->dwCaptureEveryNFields != 0),
"DdDxApiOpenCaptureDevice: Invalid dwCaptureEveryNFields specified");
ASSERTGDI((pOpenCaptureDeviceIn->pfnCaptureClose != 0),
"DdDxApiOpenCaptureDevice: Invalid pfnCaptureClose specified");
// Among other things, enforce synchronization while we muck around
// in the DirectDraw object:
EDD_DEVLOCK eDevLock(peDxDirectDraw->hdev);
dwRet = DDERR_INVALIDPARAMS;
if ((!peDxDirectDraw->bLost) &&
(!peDxVideoPort->bLost))
{
// Only do this if the device actually supports capturing
dwRet = DDERR_CURRENTLYNOTAVAIL;
peDirectDrawGlobal = peDxDirectDraw->peDirectDrawGlobal;
if ((peDirectDrawGlobal->DDKernelCaps.dwCaps &
(DDKERNELCAPS_CAPTURE_SYSMEM|DDKERNELCAPS_CAPTURE_NONLOCALVIDMEM)) &&
(peDxDirectDraw->DxApiInterface.DxTransfer != NULL))
{
#if 0 // fix bug 169385
// See capturing target is matched.
if (((pOpenCaptureDeviceIn->dwFlags & DDOPENCAPTURE_VBI) &&
(peDxVideoPort->cAutoflipVbi > 0)) ||
((pOpenCaptureDeviceIn->dwFlags & DDOPENCAPTURE_VIDEO) &&
(peDxVideoPort->cAutoflipVideo > 0)))
{
#endif
// Allocate the object. We only allow one handle per object.
dwRet = DDERR_OUTOFMEMORY;
pDxObj = pDdDxObjHandleAllocate(DXT_CAPTURE,
pOpenCaptureDeviceIn->pfnCaptureClose,
DDNOTIFY_CLOSECAPTURE,
pOpenCaptureDeviceIn->pContext);
if (pDxObj != NULL)
{
peDxCapture = (EDD_DXCAPTURE*) pDdDxObjDataAllocate(
sizeof(*peDxCapture),
'sxdG');
if (peDxCapture)
{
RtlZeroMemory(peDxCapture, sizeof(*peDxCapture));
pDxObj->peDxCapture = peDxCapture;
peDxCapture->pDxObj_List = pDxObj;
peDxCapture->peDxVideoPort = peDxVideoPort;
peDxCapture->dwStartLine = pOpenCaptureDeviceIn->dwStartLine;
peDxCapture->dwEndLine = pOpenCaptureDeviceIn->dwEndLine;
peDxCapture->dwCaptureCountDown = 1;
peDxCapture->dwCaptureEveryNFields =
pOpenCaptureDeviceIn->dwCaptureEveryNFields;
if (pOpenCaptureDeviceIn->dwFlags & DDOPENCAPTURE_VBI )
{
peDxCapture->flFlags = DD_DXCAPTURE_FLAG_VBI;
}
else
{
peDxCapture->flFlags = DD_DXCAPTURE_FLAG_VIDEO;
}
// Now we need to put the capture object into the list
// of active capture objects, but since this list is
// walked at DPC time, we need to call DxApi to do this.
peDirectDrawGlobal->pfnUpdateCapture( peDxVideoPort,
peDxCapture, FALSE );
// Success!
hCaptureDevice = (HANDLE) pDxObj;
dwRet = DD_OK;
}
if (!hCaptureDevice)
{
vDdDxObjFree(pDxObj);
}
}
#if 0 // fix bug 169385
}
else
{
WARNING("DdDxApiOpenCaptureDevice: VideoPort doesn't have surface requested by driver.\n");
}
#endif
}
else
{
WARNING("DdDxApiOpenCaptureDevice: Device does not support capture, failing.\n");
}
}
else
{
WARNING("DdDxApiOpenCaptureDevice: DirectDraw or VideoPort object is not valid, failing.\n");
}
pOpenCaptureDeviceOut->hCapture = hCaptureDevice;
pOpenCaptureDeviceOut->ddRVal = dwRet;
}
/******************************Public*Routine******************************\
* DWORD DdDxApiGetKernelCaps
*
* 01-Nov-1997 -by- smac
* Wrote it.
\**************************************************************************/
VOID
APIENTRY
DdDxApiGetKernelCaps(
HANDLE hDirectDraw,
DDGETKERNELCAPSOUT* pGetKernelCaps
)
{
DXOBJ* pDxObjDirectDraw;
EDD_DXDIRECTDRAW* peDxDirectDraw;
EDD_DIRECTDRAW_GLOBAL* peDirectDrawGlobal;
ASSERTGDI(KeGetCurrentIrql() == PASSIVE_LEVEL,
"DdDxApiGetKernelCaps: Callable only at passive level (it's not pageable)");
pDxObjDirectDraw = (DXOBJ*) hDirectDraw;
ASSERTGDI((pDxObjDirectDraw != NULL) &&
(pDxObjDirectDraw->iDxType == DXT_DIRECTDRAW),
"DdDxApiGetKernelCaps: Invalid hDirectDraw, we're about to crash");
peDxDirectDraw = pDxObjDirectDraw->peDxDirectDraw;
// Among other things, enforce synchronization while we muck around
// in the DirectDraw object:
EDD_DEVLOCK eDevLock(peDxDirectDraw->hdev);
if (!peDxDirectDraw->bLost)
{
peDirectDrawGlobal = peDxDirectDraw->peDirectDrawGlobal;
pGetKernelCaps->ddRVal = DD_OK;
pGetKernelCaps->dwCaps = peDirectDrawGlobal->DDKernelCaps.dwCaps;
pGetKernelCaps->dwIRQCaps = peDirectDrawGlobal->DDKernelCaps.dwIRQCaps;
}
else
{
pGetKernelCaps->ddRVal = DXERR_OUTOFCAPS;
pGetKernelCaps->dwCaps = 0;
pGetKernelCaps->dwIRQCaps = 0;
}
}
/******************************Public*Routine******************************\
* VOID DdDxApiLockDevice
*
* 05-Jun-1998 -by- agodfrey
\**************************************************************************/
VOID
APIENTRY
DdDxApiLockDevice(
HDEV hdev
)
{
DxEngLockHdev(hdev);
}
/******************************Public*Routine******************************\
* VOID DdDxApiUnlockDevice
*
* 05-Jun-1998 -by- agodfrey
\**************************************************************************/
VOID
APIENTRY
DdDxApiUnlockDevice(
HDEV hdev
)
{
DxEngUnlockHdev(hdev);
}
/******************************Public*Routine******************************\
* DWORD DxDvpCanCreateVideoPort
*
* Queries the driver to determine whether it can support a DirectDraw
* videoPort.
*
* 3-Oct-1996 -by- Lingyun Wang [lingyunw]
* Wrote it.
\**************************************************************************/
DWORD
APIENTRY
DxDvpCanCreateVideoPort(
HANDLE hDirectDraw,
PDD_CANCREATEVPORTDATA puCanCreateVPortData
)
{
DWORD dwRet;
DD_CANCREATEVPORTDATA CanCreateVideoPort;
DDVIDEOPORTDESC VideoPortDescription;
__try
{
CanCreateVideoPort
= ProbeAndReadStructure(puCanCreateVPortData,
DD_CANCREATEVPORTDATA);
VideoPortDescription
= ProbeAndReadStructure(CanCreateVideoPort.lpDDVideoPortDesc,
DDVIDEOPORTDESC);
}
__except(EXCEPTION_EXECUTE_HANDLER)
{
return(DDHAL_DRIVER_NOTHANDLED);
}
dwRet = DDHAL_DRIVER_NOTHANDLED;
CanCreateVideoPort.ddRVal = DDERR_GENERIC;
EDD_DIRECTDRAW_LOCAL* peDirectDrawLocal;
EDD_LOCK_DIRECTDRAW eLockDirectDraw;
EDD_DIRECTDRAW_GLOBAL* peDirectDrawGlobal;
peDirectDrawLocal = eLockDirectDraw.peLock(hDirectDraw);
// For now, do now enable VPE on Terminal Server due to problems
// loading DXAPI.SYS into session space vs. non-session space
{
if (peDirectDrawLocal != NULL)
{
peDirectDrawGlobal = peDirectDrawLocal->peDirectDrawGlobal;
CanCreateVideoPort.lpDD = peDirectDrawGlobal;
CanCreateVideoPort.lpDDVideoPortDesc = &VideoPortDescription;
EDD_DEVLOCK eDevlock(peDirectDrawGlobal);
if ((!peDirectDrawGlobal->bSuspended) &&
(peDirectDrawGlobal->VideoPortCallBacks.CanCreateVideoPort))
{
dwRet = peDirectDrawGlobal->
VideoPortCallBacks.CanCreateVideoPort(&CanCreateVideoPort);
}
}
else
{
WARNING("DxDvpCanCreateSurface: Invalid object\n");
}
}
// We have to wrap this in another try-except because the user-mode
// memory containing the input may have been deallocated by now:
__try
{
ProbeAndWriteRVal(&puCanCreateVPortData->ddRVal,
CanCreateVideoPort.ddRVal);
}
__except(EXCEPTION_EXECUTE_HANDLER)
{
}
return(dwRet);
}
/*****************************Private*Routine******************************\
* HANDLE DxDvpCreateVideoPort
*
* Notifies the HAL after a video port is created.
*
* This is an optional call for the driver, but we always have to 'hook'
* this call from user-mode DirectDraw.
*
* Question: A user-mode application could have absolute garbage in
* lpDDVideoPortDesc and get it by the driver, because the
* driver would only be monitoring for invalid data in its
* CanCreateVideoPort call. So should we call the driver's
* CanCreateVideoPort here in this routine before calling
* CreateVideoPort?
*
* History:
* 2-Oct-1996 -by- Lingyun Wang [lingyunw]
* Wrote it.
\**************************************************************************/
HANDLE
APIENTRY
DxDvpCreateVideoPort(
HANDLE hDirectDraw,
PDD_CREATEVPORTDATA puCreateVPortData
)
{
HANDLE hRet;
DWORD dwRet;
DD_CREATEVPORTDATA CreateVPortData;
DDVIDEOPORTDESC VideoPortDescription;
BOOL bFirst;
__try
{
CreateVPortData =
ProbeAndReadStructure(puCreateVPortData,
DD_CREATEVPORTDATA);
VideoPortDescription
= ProbeAndReadStructure(CreateVPortData.lpDDVideoPortDesc,
DDVIDEOPORTDESC);
}
__except(EXCEPTION_EXECUTE_HANDLER)
{
return(DDHAL_DRIVER_NOTHANDLED);
}
hRet = 0;
CreateVPortData.ddRVal = DDERR_GENERIC;
EDD_DIRECTDRAW_LOCAL* peDirectDrawLocal;
EDD_DIRECTDRAW_GLOBAL* peDirectDrawGlobal;
EDD_LOCK_DIRECTDRAW eLockDirectDraw;
EDD_VIDEOPORT* peVideoPort;
// The two items below where triple bang comments are are somewhat cryptic.
//
// 1. Ensure that not more than one VideoPort created
// 2. Scott allows CanCreateVideoPort and CreateVideoPort to be optional
peDirectDrawLocal = eLockDirectDraw.peLock(hDirectDraw);
// For now, enable VPE on Terminal Server due to conflicts loading in
// session space vs. non-session sapce.
{
if (peDirectDrawLocal != NULL)
{
peDirectDrawGlobal = peDirectDrawLocal->peDirectDrawGlobal;
// Here we do the minimal validations checks to ensure that bad
// parameters won't crash NT. We're not more strict than
// checking for stuff that will crash us, as the user-mode part
// of DirectDraw handles that.
if (VideoPortDescription.dwVideoPortID <
peDirectDrawGlobal->HalInfo.ddCaps.dwMaxVideoPorts)
{
// Check for the case where a video port has been created for
// VBI or video and we are now creating the other one, in which
// case we use the existing video port.
peVideoPort = peDirectDrawLocal->peVideoPort_DdList;
while ((peVideoPort != NULL) &&
(peVideoPort->ddvpDesc.dwVideoPortID != VideoPortDescription.dwVideoPortID))
{
peVideoPort = peVideoPort->peVideoPort_DdNext;
}
if (peVideoPort != NULL)
{
peVideoPort->ddvpDesc = VideoPortDescription;
CreateVPortData.ddRVal = DD_OK;
hRet = peVideoPort->hGet();
}
else
{
peVideoPort = (EDD_VIDEOPORT*) DdHmgAlloc(sizeof(EDD_VIDEOPORT),
DD_VIDEOPORT_TYPE,
HMGR_ALLOC_LOCK);
if (peVideoPort)
{
// Private data:
peVideoPort->peDirectDrawGlobal = peDirectDrawGlobal;
peVideoPort->peDirectDrawLocal = peDirectDrawLocal;
// Public data:
peVideoPort->lpDD = peDirectDrawGlobal;
peVideoPort->ddvpDesc = VideoPortDescription;
// Hold devlock for driver call and for bDdEnableSoftware
// Autoflipping.
EDD_DEVLOCK eDevlock(peDirectDrawGlobal);
// Add this videoport to the list hanging off the
// DirectDrawLocal object allocated for this process:
bFirst = peDirectDrawLocal->peVideoPort_DdList == NULL;
peVideoPort->peVideoPort_DdNext
= peDirectDrawLocal->peVideoPort_DdList;
peDirectDrawLocal->peVideoPort_DdList
= peVideoPort;
// Now call the driver to create its version:
CreateVPortData.lpDD = peDirectDrawGlobal;
CreateVPortData.lpDDVideoPortDesc = &VideoPortDescription;
CreateVPortData.lpVideoPort = peVideoPort;
CreateVPortData.ddRVal = DDERR_GENERIC;
dwRet = DDHAL_DRIVER_NOTHANDLED; // Call is optional
if ((!peDirectDrawGlobal->bSuspended) &&
(peDirectDrawGlobal->VideoPortCallBacks.CreateVideoPort))
{
dwRet = peDirectDrawGlobal->
VideoPortCallBacks.CreateVideoPort(&CreateVPortData);
}
if ((dwRet == DDHAL_DRIVER_NOTHANDLED) ||
(CreateVPortData.ddRVal == DD_OK))
{
CreateVPortData.ddRVal = DD_OK;
peVideoPort->fl |= DD_VIDEOPORT_FLAG_DRIVER_CREATED;
}
else
{
WARNING("DxDvpCreateVideoPort: Driver failed call\n");
}
if ((CreateVPortData.ddRVal == DD_OK) &&
(bDdEnableSoftwareAutoflipping(peDirectDrawLocal,
peVideoPort,
VideoPortDescription.dwVideoPortID,
bFirst)))
{
// Success!
hRet = peVideoPort->hGet();
DEC_EXCLUSIVE_REF_CNT( peVideoPort );
}
else
{
bDdDeleteVideoPortObject(peVideoPort->hGet(), NULL);
CreateVPortData.ddRVal = DDERR_GENERIC;
}
}
}
}
else
{
WARNING("DxDvpCreateVideoPort: Bad parameters\n");
}
}
else
{
WARNING("DxDvpCreateVideoPort: Invalid object\n");
}
}
// We have to wrap this in another try-except because the user-mode
// memory containing the input may have been deallocated by now:
__try
{
ProbeAndWriteRVal(&puCreateVPortData->ddRVal, CreateVPortData.ddRVal);
}
__except(EXCEPTION_EXECUTE_HANDLER)
{
}
// Note that the user-mode stub always returns DDHAL_DRIVER_HANDLED
// to DirectDraw.
return(hRet);
}
/*****************************Private*Routine******************************\
* DWORD DxDvpDestroyVideoPort
*
* Notifies the HAL when the video port is destroyed.
*
* History:
* 2-Oct-1996 -by- Lingyun Wang [lingyunw]
* Wrote it.
\**************************************************************************/
DWORD
APIENTRY
DxDvpDestroyVideoPort(
HANDLE hVideoPort,
PDD_DESTROYVPORTDATA puDestroyVPortData
)
{
DWORD dwRet;
bDdDeleteVideoPortObject(hVideoPort, &dwRet);
__try
{
ProbeAndWriteRVal(&puDestroyVPortData->ddRVal, DD_OK);
}
__except(EXCEPTION_EXECUTE_HANDLER)
{
}
return(dwRet);
}
/*****************************Private*Routine******************************\
* DWORD DxDvpFlipVideoPort
*
* Performs the physical flip, causing the video port to start writing data
* to the new surface. This does not affect the actual display of this data.
*
* History:
* 2-Oct-1996 -by- Lingyun Wang [lingyunw]
* Wrote it.
\**************************************************************************/
DWORD
APIENTRY
DxDvpFlipVideoPort(
HANDLE hVideoPort,
HANDLE hDDSurfaceCurrent,
HANDLE hDDSurfaceTarget,
PDD_FLIPVPORTDATA puFlipVPortData
)
{
DWORD dwRet;
DD_FLIPVPORTDATA FlipVPortData;
dwRet = DDHAL_DRIVER_NOTHANDLED;
FlipVPortData.ddRVal = DDERR_GENERIC;
EDD_VIDEOPORT* peVideoPort;
EDD_LOCK_VIDEOPORT eLockVideoPort;
EDD_DIRECTDRAW_GLOBAL* peDirectDrawGlobal;
// 1. Make sure they're videoport surfaces, and compatible, not system surfaces?
// 2. Make sure not software autoflipping?
peVideoPort = eLockVideoPort.peLock(hVideoPort);
if (peVideoPort != NULL)
{
peDirectDrawGlobal = peVideoPort->peDirectDrawGlobal;
if (peDirectDrawGlobal->VideoPortCallBacks.FlipVideoPort)
{
EDD_SURFACE* peSurfaceCurrent;
EDD_SURFACE* peSurfaceTarget;
EDD_LOCK_SURFACE eLockSurfaceCurrent;
EDD_LOCK_SURFACE eLockSurfaceTarget;
peSurfaceCurrent = eLockSurfaceCurrent.peLock(hDDSurfaceCurrent);
peSurfaceTarget = eLockSurfaceTarget.peLock(hDDSurfaceTarget);
if ((peSurfaceCurrent != NULL) &&
(peSurfaceTarget != NULL) &&
(peSurfaceCurrent->peDirectDrawGlobal == peDirectDrawGlobal) &&
(peSurfaceCurrent->peDirectDrawLocal
== peSurfaceTarget->peDirectDrawLocal))
{
FlipVPortData.lpDD = peDirectDrawGlobal;
FlipVPortData.lpVideoPort = peVideoPort;
FlipVPortData.lpSurfCurr = peSurfaceCurrent;
FlipVPortData.lpSurfTarg = peSurfaceTarget;
{
EDD_DEVLOCK eDevlock(peDirectDrawGlobal);
if ((!peDirectDrawGlobal->bSuspended) &&
(peDirectDrawGlobal->VideoPortCallBacks.FlipVideoPort))
{
dwRet = peDirectDrawGlobal->VideoPortCallBacks.
FlipVideoPort(&FlipVPortData);
}
}
if ((dwRet == DDHAL_DRIVER_HANDLED) &&
(FlipVPortData.ddRVal == DD_OK))
{
peVideoPort->lpSurface = peSurfaceTarget;
}
}
else
{
WARNING("DxDvpFlipVPort: Invalid source or target surface\n");
}
}
else
{
WARNING("DxDvpFlipVPort: Driver doesn't hook call\n");
}
}
else
{
WARNING("DxDvpFlipVPort: Invalid object\n");
}
__try
{
ProbeAndWriteRVal(&puFlipVPortData->ddRVal, FlipVPortData.ddRVal);
}
__except(EXCEPTION_EXECUTE_HANDLER)
{
}
return(dwRet);
}
/*****************************Private*Routine******************************\
* DWORD DxGetVideoPortBandwidth
*
* Informs the client of bandwidth requirements for any specified format,
* allowing them to better chose a format and to understand its limitations.
* This information can only be given after the video port object is created
* because the information in the DDVIDEOPORTDESC structure is required before
* accurate bandwidth information can be supplied.
*
* History:
* 2-Oct-1996 -by- Lingyun Wang [lingyunw]
* Wrote it.
\**************************************************************************/
DWORD
APIENTRY
DxDvpGetVideoPortBandwidth(
HANDLE hVideoPort,
PDD_GETVPORTBANDWIDTHDATA puGetVPortBandwidthData
)
{
DWORD dwRet;
DD_GETVPORTBANDWIDTHDATA GetVPortBandwidthData;
LPDDPIXELFORMAT pddpfFormat;
DDPIXELFORMAT ddpfFormat;
DDVIDEOPORTBANDWIDTH Bandwidth;
LPDDVIDEOPORTBANDWIDTH puBandwidth;
__try
{
GetVPortBandwidthData = ProbeAndReadStructure(puGetVPortBandwidthData,
DD_GETVPORTBANDWIDTHDATA);
ddpfFormat = ProbeAndReadStructure(GetVPortBandwidthData.lpddpfFormat,
DDPIXELFORMAT);
puBandwidth = GetVPortBandwidthData.lpBandwidth;
Bandwidth = ProbeAndReadStructure(puBandwidth,DDVIDEOPORTBANDWIDTH);
}
__except(EXCEPTION_EXECUTE_HANDLER)
{
return(DDHAL_DRIVER_NOTHANDLED);
}
dwRet = DDHAL_DRIVER_NOTHANDLED;
GetVPortBandwidthData.ddRVal = DDERR_GENERIC;
EDD_VIDEOPORT* peVideoPort;
EDD_LOCK_VIDEOPORT eLockVideoPort;
EDD_DIRECTDRAW_GLOBAL* peDirectDrawGlobal;
peVideoPort = eLockVideoPort.peLock(hVideoPort);
if (peVideoPort != NULL)
{
peDirectDrawGlobal = peVideoPort->peDirectDrawGlobal;
if (peDirectDrawGlobal->VideoPortCallBacks.GetVideoPortBandwidth)
{
GetVPortBandwidthData.lpDD = peDirectDrawGlobal;
GetVPortBandwidthData.lpVideoPort = peVideoPort;
GetVPortBandwidthData.lpBandwidth = &Bandwidth;
GetVPortBandwidthData.lpddpfFormat = &ddpfFormat;
EDD_DEVLOCK eDevlock(peDirectDrawGlobal);
if ((!peDirectDrawGlobal->bSuspended) &&
(peDirectDrawGlobal->VideoPortCallBacks.GetVideoPortBandwidth))
{
dwRet = peDirectDrawGlobal->VideoPortCallBacks.
GetVideoPortBandwidth(&GetVPortBandwidthData);
}
}
else
{
WARNING("DxDvpGetVPortBandwidthData: Driver doesn't hook call\n");
}
}
else
{
WARNING("DxDvpGetVPortBandwidthData: Invalid object\n");
}
// We have to wrap this in another try-except because the user-mode
// memory containing the input may have been deallocated by now:
__try
{
ProbeAndWriteStructure(puBandwidth, Bandwidth, DDVIDEOPORTBANDWIDTH);
ProbeAndWriteRVal(&puGetVPortBandwidthData->ddRVal,
GetVPortBandwidthData.ddRVal);
}
__except(EXCEPTION_EXECUTE_HANDLER)
{
}
return(dwRet);
}
/*****************************Private*Routine******************************\
* DWORD DxDvpGetVideoPortField
*
* Sets bField to TRUE if the current field is the even field of an
* interlaced signal. Otherwise, bField is set to FALSE.
*
* History:
* 2-Oct-1996 -by- Lingyun Wang [lingyunw]
* Wrote it.
\**************************************************************************/
DWORD
APIENTRY
DxDvpGetVideoPortField(
HANDLE hVideoPort,
PDD_GETVPORTFIELDDATA puGetVPortFieldData
)
{
DWORD dwRet;
DD_GETVPORTFIELDDATA GetVPortFieldData;
__try
{
GetVPortFieldData = ProbeAndReadStructure(puGetVPortFieldData,
DD_GETVPORTFIELDDATA);
}
__except(EXCEPTION_EXECUTE_HANDLER)
{
return(DDHAL_DRIVER_NOTHANDLED);
}
dwRet = DDHAL_DRIVER_NOTHANDLED;
GetVPortFieldData.ddRVal = DDERR_GENERIC;
EDD_VIDEOPORT* peVideoPort;
EDD_LOCK_VIDEOPORT eLockVideoPort;
EDD_DIRECTDRAW_GLOBAL* peDirectDrawGlobal;
peVideoPort = eLockVideoPort.peLock(hVideoPort);
if (peVideoPort != NULL)
{
peDirectDrawGlobal = peVideoPort->peDirectDrawGlobal;
GetVPortFieldData.lpDD = peDirectDrawGlobal;
GetVPortFieldData.lpVideoPort = peVideoPort;
EDD_DEVLOCK eDevlock(peDirectDrawGlobal);
if ((!peDirectDrawGlobal->bSuspended) &&
(peDirectDrawGlobal->VideoPortCallBacks.GetVideoPortField))
{
dwRet = peDirectDrawGlobal->
VideoPortCallBacks.GetVideoPortField(&GetVPortFieldData);
}
}
else
{
WARNING("DxDvpCanGetVPortFieldData: Invalid object\n");
}
// We have to wrap this in another try-except because the user-mode
// memory containing the input may have been deallocated by now:
__try
{
ProbeAndWriteRVal(&puGetVPortFieldData->ddRVal,
GetVPortFieldData.ddRVal);
ProbeAndWriteStructure(&puGetVPortFieldData->bField,
GetVPortFieldData.bField,
BOOL);
}
__except(EXCEPTION_EXECUTE_HANDLER)
{
}
return(dwRet);
}
/*****************************Private*Routine******************************\
* DWORD DxDvpGetVideoPortFlipStatus
*
* Returns DDERR_WASSTILLDRAWING if a video VSYNC has not occurred since the
* flip was performed on the specified surface. This function allows DDRAW.DLL
* to fail locks on a surface that was recently flipped from so the HAL doesn't
* have to account for this.
*
* History:
* 2-Oct-1996 -by- Lingyun Wang [lingyunw]
* Wrote it.
\**************************************************************************/
DWORD
APIENTRY
DxDvpGetVideoPortFlipStatus(
HANDLE hDirectDraw,
PDD_GETVPORTFLIPSTATUSDATA puGetVPortFlipStatusData
)
{
DWORD dwRet;
DD_GETVPORTFLIPSTATUSDATA GetVPortFlipStatusData;
__try
{
GetVPortFlipStatusData = ProbeAndReadStructure(puGetVPortFlipStatusData,
DD_GETVPORTFLIPSTATUSDATA);
}
__except(EXCEPTION_EXECUTE_HANDLER)
{
return(DDHAL_DRIVER_NOTHANDLED);
}
dwRet = DDHAL_DRIVER_NOTHANDLED;
GetVPortFlipStatusData.ddRVal = DDERR_GENERIC;
EDD_DIRECTDRAW_LOCAL* peDirectDrawLocal;
EDD_LOCK_DIRECTDRAW eLockDirectDraw;
EDD_DIRECTDRAW_GLOBAL* peDirectDrawGlobal;
peDirectDrawLocal = eLockDirectDraw.peLock(hDirectDraw);
if (peDirectDrawLocal != NULL)
{
peDirectDrawGlobal = peDirectDrawLocal->peDirectDrawGlobal;
GetVPortFlipStatusData.lpDD = peDirectDrawGlobal;
EDD_DEVLOCK eDevlock(peDirectDrawGlobal);
if ((!peDirectDrawGlobal->bSuspended) &&
(peDirectDrawGlobal->VideoPortCallBacks.GetVideoPortFlipStatus))
{
dwRet = peDirectDrawGlobal->
VideoPortCallBacks.GetVideoPortFlipStatus(
&GetVPortFlipStatusData);
}
}
else
{
WARNING("DxDvpCanGetVPortFlipStatusData: Invalid object\n");
}
// We have to wrap this in another try-except because the user-mode
// memory containing the input may have been deallocated by now:
__try
{
ProbeAndWriteRVal(&puGetVPortFlipStatusData->ddRVal,
GetVPortFlipStatusData.ddRVal);
}
__except(EXCEPTION_EXECUTE_HANDLER)
{
}
return(dwRet);
}
/*****************************Private*Routine******************************\
* DWORD DxDvpGetVideoPortInputFormats
*
* Fills in the specified array with all of the formats that the video port
* can accept and puts that number in dwNumFormats. If lpddpfFormats is NULL,
* it only fills in dwNumFormats with the number of formats that it can support.
* This function is needed because the supported formats may vary depending on
* the electrical connection of the video port.
*
* History:
* 2-Oct-1996 -by- Lingyun Wang [lingyunw]
* Wrote it.
\**************************************************************************/
DWORD
APIENTRY
DxDvpGetVideoPortInputFormats(
HANDLE hVideoPort,
PDD_GETVPORTINPUTFORMATDATA puGetVPortInputFormatData
)
{
DWORD dwRet;
DD_GETVPORTINPUTFORMATDATA GetVPortInputFormatData;
LPDDPIXELFORMAT puFormat;
ULONG cjFormat;
HANDLE hSecure;
__try
{
GetVPortInputFormatData
= ProbeAndReadStructure(puGetVPortInputFormatData,
DD_GETVPORTINPUTFORMATDATA);
puFormat = GetVPortInputFormatData.lpddpfFormat;
}
__except(EXCEPTION_EXECUTE_HANDLER)
{
return(DDHAL_DRIVER_NOTHANDLED);
}
dwRet = DDHAL_DRIVER_NOTHANDLED;
GetVPortInputFormatData.ddRVal = DDERR_GENERIC;
EDD_VIDEOPORT* peVideoPort;
EDD_LOCK_VIDEOPORT eLockVideoPort;
EDD_DIRECTDRAW_GLOBAL* peDirectDrawGlobal;
peVideoPort = eLockVideoPort.peLock(hVideoPort);
if (peVideoPort != NULL)
{
peDirectDrawGlobal = peVideoPort->peDirectDrawGlobal;
GetVPortInputFormatData.lpDD = peDirectDrawGlobal;
GetVPortInputFormatData.lpVideoPort = peVideoPort;
GetVPortInputFormatData.lpddpfFormat = NULL;
EDD_DEVLOCK eDevlock(peDirectDrawGlobal);
if ((!peDirectDrawGlobal->bSuspended) &&
(peDirectDrawGlobal->VideoPortCallBacks.GetVideoPortInputFormats))
{
dwRet = peDirectDrawGlobal->VideoPortCallBacks.
GetVideoPortInputFormats(&GetVPortInputFormatData);
cjFormat = GetVPortInputFormatData.dwNumFormats
* sizeof(DDPIXELFORMAT);
if ((dwRet == DDHAL_DRIVER_HANDLED) &&
(GetVPortInputFormatData.ddRVal == DD_OK) &&
(cjFormat > 0) &&
(puFormat != NULL) &&
!BALLOC_OVERFLOW1(GetVPortInputFormatData.dwNumFormats, DDPIXELFORMAT))
{
GetVPortInputFormatData.ddRVal = DDERR_GENERIC;
hSecure = 0;
__try
{
ProbeForWrite(puFormat, cjFormat, sizeof(UCHAR));
hSecure = MmSecureVirtualMemory(puFormat,
cjFormat,
PAGE_READWRITE);
}
__except(EXCEPTION_EXECUTE_HANDLER)
{
}
if (hSecure)
{
GetVPortInputFormatData.lpddpfFormat = puFormat;
dwRet = peDirectDrawGlobal->VideoPortCallBacks.
GetVideoPortInputFormats(&GetVPortInputFormatData);
MmUnsecureVirtualMemory(hSecure);
}
else
{
WARNING("DxDvpGetVideoPortInputFormats: Bad destination buffer\n");
}
}
}
}
else
{
WARNING("DxDvpGetVPortInputFormatData: Invalid object\n");
}
// We have to wrap this in another try-except because the user-mode
// memory containing the input may have been deallocated by now:
__try
{
ProbeAndWriteRVal(&puGetVPortInputFormatData->ddRVal,
GetVPortInputFormatData.ddRVal);
ProbeAndWriteUlong(&puGetVPortInputFormatData->dwNumFormats,
GetVPortInputFormatData.dwNumFormats);
}
__except(EXCEPTION_EXECUTE_HANDLER)
{
}
return(dwRet);
}
/*****************************Private*Routine******************************\
* DWORD DxDvpGetVideoPortOutputFormats
*
* Fills in the specified array with all of the formats that can be written
* to the frame buffer based on the specified input format and puts that
* number in dwNumFormats. If lpddpfOutputFormats is NULL, it only fills
* in dwNumFormats with the number of formats that can be written to the
* frame buffer.
*
* History:
* 2-Oct-1996 -by- Lingyun Wang [lingyunw]
* Wrote it.
\**************************************************************************/
DWORD
APIENTRY
DxDvpGetVideoPortOutputFormats(
HANDLE hVideoPort,
PDD_GETVPORTOUTPUTFORMATDATA puGetVPortOutputFormatData
)
{
DWORD dwRet;
DD_GETVPORTOUTPUTFORMATDATA GetVPortOutputFormatData;
LPDDPIXELFORMAT puOutputFormats;
DDPIXELFORMAT ddpfInputFormat;
ULONG cjFormat;
HANDLE hSecure;
__try
{
GetVPortOutputFormatData
= ProbeAndReadStructure(puGetVPortOutputFormatData,
DD_GETVPORTOUTPUTFORMATDATA);
ddpfInputFormat
= ProbeAndReadStructure(GetVPortOutputFormatData.lpddpfInputFormat,
DDPIXELFORMAT);
puOutputFormats = GetVPortOutputFormatData.lpddpfOutputFormats;
}
__except(EXCEPTION_EXECUTE_HANDLER)
{
return(DDHAL_DRIVER_NOTHANDLED);
}
dwRet = DDHAL_DRIVER_NOTHANDLED;
GetVPortOutputFormatData.ddRVal = DDERR_GENERIC;
EDD_VIDEOPORT* peVideoPort;
EDD_LOCK_VIDEOPORT eLockVideoPort;
EDD_DIRECTDRAW_GLOBAL* peDirectDrawGlobal;
peVideoPort = eLockVideoPort.peLock(hVideoPort);
if (peVideoPort != NULL)
{
peDirectDrawGlobal = peVideoPort->peDirectDrawGlobal;
GetVPortOutputFormatData.lpDD = peDirectDrawGlobal;
GetVPortOutputFormatData.lpVideoPort = peVideoPort;
GetVPortOutputFormatData.lpddpfInputFormat = &ddpfInputFormat;
GetVPortOutputFormatData.lpddpfOutputFormats = NULL;
EDD_DEVLOCK eDevlock(peDirectDrawGlobal);
if ((!peDirectDrawGlobal->bSuspended) &&
(peDirectDrawGlobal->VideoPortCallBacks.GetVideoPortOutputFormats))
{
dwRet = peDirectDrawGlobal->VideoPortCallBacks.
GetVideoPortOutputFormats(&GetVPortOutputFormatData);
cjFormat = GetVPortOutputFormatData.dwNumFormats
* sizeof(DDPIXELFORMAT);
if ((dwRet == DDHAL_DRIVER_HANDLED) &&
(GetVPortOutputFormatData.ddRVal == DD_OK) &&
(cjFormat > 0) &&
(puOutputFormats != NULL) &&
!BALLOC_OVERFLOW1(GetVPortOutputFormatData.dwNumFormats, DDPIXELFORMAT))
{
GetVPortOutputFormatData.ddRVal = DDERR_GENERIC;
hSecure = 0;
__try
{
ProbeForWrite(puOutputFormats,
cjFormat,
sizeof(UCHAR));
hSecure = MmSecureVirtualMemory(puOutputFormats,
cjFormat,
PAGE_READWRITE);
}
__except(EXCEPTION_EXECUTE_HANDLER)
{
}
if (hSecure)
{
GetVPortOutputFormatData.lpddpfOutputFormats
= puOutputFormats;
dwRet = peDirectDrawGlobal->VideoPortCallBacks.
GetVideoPortOutputFormats(&GetVPortOutputFormatData);
MmUnsecureVirtualMemory(hSecure);
}
else
{
WARNING("DxDvpGetVideoPortOutputFormats: Bad destination buffer\n");
}
}
}
}
else
{
WARNING("DxDvpGetVPortOutputFormatData: Invalid object\n");
}
// We have to wrap this in another try-except because the user-mode
// memory containing the input may have been deallocated by now:
__try
{
ProbeAndWriteRVal(&puGetVPortOutputFormatData->ddRVal,
GetVPortOutputFormatData.ddRVal);
ProbeAndWriteUlong(&puGetVPortOutputFormatData->dwNumFormats,
GetVPortOutputFormatData.dwNumFormats);
}
__except(EXCEPTION_EXECUTE_HANDLER)
{
}
return(dwRet);
}
/*****************************Private*Routine******************************\
* DWORD DxGetVideoPortLine
*
* Returns the current line counter of the video port.
*
* This function is only required if the driver sets the DDVPCAPS_READBACKLINE
* flag.
*
* History:
* 2-Oct-1996 -by- Lingyun Wang [lingyunw]
* Wrote it.
\**************************************************************************/
DWORD
APIENTRY
DxDvpGetVideoPortLine(
HANDLE hVideoPort,
PDD_GETVPORTLINEDATA puGetVPortLineData
)
{
DWORD dwRet;
DD_GETVPORTLINEDATA GetVPortLineData;
dwRet = DDHAL_DRIVER_NOTHANDLED;
GetVPortLineData.ddRVal = DDERR_GENERIC;
EDD_VIDEOPORT* peVideoPort;
EDD_LOCK_VIDEOPORT eLockVideoPort;
EDD_DIRECTDRAW_GLOBAL* peDirectDrawGlobal;
peVideoPort = eLockVideoPort.peLock(hVideoPort);
if (peVideoPort != NULL)
{
peDirectDrawGlobal = peVideoPort->peDirectDrawGlobal;
GetVPortLineData.lpDD = peDirectDrawGlobal;
GetVPortLineData.lpVideoPort = peVideoPort;
EDD_DEVLOCK eDevlock(peDirectDrawGlobal);
if ((!peDirectDrawGlobal->bSuspended) &&
(peDirectDrawGlobal->VideoPortCallBacks.GetVideoPortLine))
{
dwRet = peDirectDrawGlobal->
VideoPortCallBacks.GetVideoPortLine(&GetVPortLineData);
}
}
else
{
WARNING("DxDvpGetVPortLineData: Invalid object\n");
}
__try
{
ProbeAndWriteStructure(puGetVPortLineData,
GetVPortLineData,
DD_GETVPORTLINEDATA);
}
__except(EXCEPTION_EXECUTE_HANDLER)
{
}
return(dwRet);
}
/*****************************Private*Routine******************************\
* DWORD DxGetVideoPortConnectInfo
*
* Fills in the specified array with all of the connection combinations
* supported by the specified video port and puts that number in dwNumEntries.
* If lpConnect is NULL, it only fills in dwNumEntries with the number of
* DDVIDEOPORTCONNECT entries supported.
*
* History:
* 2-Oct-1996 -by- Lingyun Wang [lingyunw]
* Wrote it.
\**************************************************************************/
DWORD
APIENTRY
DxDvpGetVideoPortConnectInfo(
HANDLE hDirectDraw,
PDD_GETVPORTCONNECTDATA puGetVPortConnectData
)
{
DWORD dwRet;
DD_GETVPORTCONNECTDATA GetVPortConnectData;
DDVIDEOPORTCONNECT* puConnect;
ULONG cjConnect;
HANDLE hSecure;
__try
{
GetVPortConnectData = ProbeAndReadStructure(puGetVPortConnectData,
DD_GETVPORTCONNECTDATA);
puConnect = GetVPortConnectData.lpConnect;
}
__except(EXCEPTION_EXECUTE_HANDLER)
{
return(DDHAL_DRIVER_NOTHANDLED);
}
dwRet = DDHAL_DRIVER_NOTHANDLED;
GetVPortConnectData.ddRVal = DDERR_GENERIC;
EDD_DIRECTDRAW_LOCAL* peDirectDrawLocal;
EDD_LOCK_DIRECTDRAW eLockDirectDraw;
EDD_DIRECTDRAW_GLOBAL* peDirectDrawGlobal;
peDirectDrawLocal = eLockDirectDraw.peLock(hDirectDraw);
if (peDirectDrawLocal != NULL)
{
peDirectDrawGlobal = peDirectDrawLocal->peDirectDrawGlobal;
GetVPortConnectData.lpDD = peDirectDrawGlobal;
GetVPortConnectData.lpConnect = NULL;
EDD_DEVLOCK eDevlock(peDirectDrawGlobal);
if ((!peDirectDrawGlobal->bSuspended) &&
(peDirectDrawGlobal->VideoPortCallBacks.GetVideoPortConnectInfo))
{
dwRet = peDirectDrawGlobal->
VideoPortCallBacks.GetVideoPortConnectInfo(
&GetVPortConnectData);
cjConnect = GetVPortConnectData.dwNumEntries
* sizeof(DDVIDEOPORTCONNECT);
if ((dwRet == DDHAL_DRIVER_HANDLED) &&
(GetVPortConnectData.ddRVal == DD_OK) &&
(cjConnect > 0) &&
(puConnect != NULL) &&
!BALLOC_OVERFLOW1(GetVPortConnectData.dwNumEntries, DDVIDEOPORTCONNECT))
{
GetVPortConnectData.ddRVal = DDERR_GENERIC;
hSecure = 0;
__try
{
ProbeForWrite(puConnect, cjConnect, sizeof(UCHAR));
hSecure = MmSecureVirtualMemory(puConnect,
cjConnect,
PAGE_READWRITE);
}
__except(EXCEPTION_EXECUTE_HANDLER)
{
}
if (hSecure)
{
GetVPortConnectData.lpConnect = puConnect;
dwRet = peDirectDrawGlobal->VideoPortCallBacks.
GetVideoPortConnectInfo(&GetVPortConnectData);
MmUnsecureVirtualMemory(hSecure);
}
else
{
WARNING("DxDvpGetVideoPortConnectInfo: Bad destination buffer\n");
}
}
}
}
else
{
WARNING("DxDvpGetVPortConnectData: Invalid object\n");
}
// We have to wrap this in another try-except because the user-mode
// memory containing the input may have been deallocated by now:
__try
{
ProbeAndWriteRVal(&puGetVPortConnectData->ddRVal,
GetVPortConnectData.ddRVal);
ProbeAndWriteUlong(&puGetVPortConnectData->dwNumEntries,
GetVPortConnectData.dwNumEntries);
}
__except(EXCEPTION_EXECUTE_HANDLER)
{
}
return(dwRet);
}
/*****************************Private*Routine******************************\
* DxDvpGetVideoSignalStatus
*
* If the video port is receiving a good signal, the HAL should set dwStatus
* to DDVPSQ_SIGNALOK; otherwise, it should set dwStatus to DDVPSQ_NOSIGNAL.
*
*History:
* 2-Oct-1996 -by- Lingyun Wang [lingyunw]
* Wrote it.
\**************************************************************************/
DWORD
APIENTRY
DxDvpGetVideoSignalStatus(
HANDLE hVideoPort,
PDD_GETVPORTSIGNALDATA puGetVPortSignalData
)
{
DWORD dwRet;
DD_GETVPORTSIGNALDATA GetVPortSignalData;
dwRet = DDHAL_DRIVER_NOTHANDLED;
GetVPortSignalData.ddRVal = DDERR_GENERIC;
EDD_VIDEOPORT* peVideoPort;
EDD_LOCK_VIDEOPORT eLockVideoPort;
EDD_DIRECTDRAW_GLOBAL* peDirectDrawGlobal;
peVideoPort = eLockVideoPort.peLock(hVideoPort);
if (peVideoPort != NULL)
{
peDirectDrawGlobal = peVideoPort->peDirectDrawGlobal;
GetVPortSignalData.lpDD = peDirectDrawGlobal;
GetVPortSignalData.lpVideoPort = peVideoPort;
EDD_DEVLOCK eDevlock(peDirectDrawGlobal);
if ((!peDirectDrawGlobal->bSuspended) &&
(peDirectDrawGlobal->VideoPortCallBacks.GetVideoSignalStatus))
{
dwRet = peDirectDrawGlobal->
VideoPortCallBacks.GetVideoSignalStatus(&GetVPortSignalData);
}
}
else
{
WARNING("DxDvpGetVPortSignalData: Invalid object\n");
}
__try
{
ProbeAndWriteStructure(puGetVPortSignalData,
GetVPortSignalData,
DD_GETVPORTSIGNALDATA);
}
__except(EXCEPTION_EXECUTE_HANDLER)
{
}
return(dwRet);
}
/*****************************Private*Routine******************************\
* DWORD DxDvpUpdateVideoPort
*
* Starts, stops, and changes the video port. dwFlags can contain either
* DDRAWI_VPORTSTART, DDRAWI_VPORTSTOP, or DDRAWI_VPORTUPDATE. To accommodate
* auto-flipping, lplpDDSurface and lplpDDVBISurface point to an array of
* surface structures rather than to a single structure. If autoflipping is
* requested, the dwNumAutoflip field contains the number of surfaces in the
* list.
*
* History:
* 2-Oct-1996 -by- Lingyun Wang [lingyunw]
* Wrote it.
\**************************************************************************/
DWORD
APIENTRY
DxDvpUpdateVideoPort(
HANDLE hVideoPort,
HANDLE* phSurfaceVideo,
HANDLE* phSurfaceVbi,
PDD_UPDATEVPORTDATA puUpdateVPortData
)
{
DWORD dwRet;
DD_UPDATEVPORTDATA UpdateVPortData;
DDVIDEOPORTINFO VideoPortInfo;
DDPIXELFORMAT ddpfInputFormat;
DDPIXELFORMAT ddpfVBIInputFormat;
DDPIXELFORMAT ddpfVBIOutputFormat;
HANDLE ahSurfaceVideo[MAX_AUTOFLIP_BUFFERS];
HANDLE ahSurfaceVbi[MAX_AUTOFLIP_BUFFERS];
EDD_SURFACE* apeSurfaceVideo[MAX_AUTOFLIP_BUFFERS];
EDD_SURFACE* apeSurfaceVbi[MAX_AUTOFLIP_BUFFERS];
DD_SURFACE_INT* apDDSurfaceVideo[MAX_AUTOFLIP_BUFFERS];
DD_SURFACE_INT* apDDSurfaceVbi[MAX_AUTOFLIP_BUFFERS];
ULONG cAutoflipVideo;
ULONG cAutoflipVbi;
EDD_DXVIDEOPORT* peDxVideoPort;
__try
{
UpdateVPortData = ProbeAndReadStructure(puUpdateVPortData,
DD_UPDATEVPORTDATA);
// Handle VideoPortInfo structure:
if (UpdateVPortData.dwFlags != DDRAWI_VPORTSTOP)
{
VideoPortInfo = ProbeAndReadStructure(UpdateVPortData.lpVideoInfo,
DDVIDEOPORTINFO);
if (VideoPortInfo.lpddpfInputFormat != NULL)
{
ddpfInputFormat
= ProbeAndReadStructure(VideoPortInfo.lpddpfInputFormat,
DDPIXELFORMAT);
VideoPortInfo.lpddpfInputFormat = &ddpfInputFormat;
}
if (VideoPortInfo.dwVBIHeight > 0)
{
if (VideoPortInfo.lpddpfVBIInputFormat != NULL)
{
ddpfVBIInputFormat
= ProbeAndReadStructure(VideoPortInfo.lpddpfVBIInputFormat,
DDPIXELFORMAT);
VideoPortInfo.lpddpfVBIInputFormat = &ddpfVBIInputFormat;
}
if (VideoPortInfo.lpddpfVBIOutputFormat != NULL)
{
ddpfVBIOutputFormat
= ProbeAndReadStructure(VideoPortInfo.lpddpfVBIOutputFormat,
DDPIXELFORMAT);
VideoPortInfo.lpddpfVBIOutputFormat = &ddpfVBIOutputFormat;
}
}
else
{
VideoPortInfo.lpddpfVBIInputFormat = NULL;
VideoPortInfo.lpddpfVBIOutputFormat = NULL;
}
}
// Handle arrays of surfaces:
cAutoflipVbi = 0;
cAutoflipVideo = 0;
if (UpdateVPortData.dwFlags != DDRAWI_VPORTSTOP)
{
cAutoflipVideo = min(UpdateVPortData.dwNumAutoflip, MAX_AUTOFLIP_BUFFERS);
if ((cAutoflipVideo == 0) && (UpdateVPortData.lplpDDSurface != NULL))
{
cAutoflipVideo = 1;
}
cAutoflipVbi = min(UpdateVPortData.dwNumVBIAutoflip, MAX_AUTOFLIP_BUFFERS);
if ((cAutoflipVbi == 0) && (UpdateVPortData.lplpDDVBISurface != NULL))
{
cAutoflipVbi = 1;
}
}
if (cAutoflipVideo)
{
ProbeForRead(phSurfaceVideo,
cAutoflipVideo * sizeof(HANDLE),
sizeof(HANDLE));
RtlCopyMemory(ahSurfaceVideo,
phSurfaceVideo,
cAutoflipVideo * sizeof(HANDLE));
}
if (cAutoflipVbi)
{
ProbeForRead(phSurfaceVbi,
cAutoflipVbi * sizeof(HANDLE),
sizeof(HANDLE));
RtlCopyMemory(ahSurfaceVbi,
phSurfaceVbi,
cAutoflipVbi * sizeof(HANDLE));
}
}
__except(EXCEPTION_EXECUTE_HANDLER)
{
return(DDHAL_DRIVER_NOTHANDLED);
}
dwRet = DDHAL_DRIVER_NOTHANDLED;
UpdateVPortData.ddRVal = DDERR_GENERIC;
EDD_VIDEOPORT* peVideoPort;
EDD_LOCK_VIDEOPORT eLockVideoPort;
EDD_DIRECTDRAW_GLOBAL* peDirectDrawGlobal;
ULONG i;
EDD_SURFACE* peSurface;
BOOL bUpdateOK = TRUE;
peVideoPort = eLockVideoPort.peLock(hVideoPort);
if (peVideoPort != NULL)
{
peDxVideoPort = peVideoPort->peDxVideoPort;
peDirectDrawGlobal = peVideoPort->peDirectDrawGlobal;
// Lock all the surfaces. Note that bDdUpdateLinksAndSynchronize
// will check for failure of DdHmgLock (the pointer will be NULL):
for (i = 0; i < cAutoflipVideo; i++)
{
apeSurfaceVideo[i] = (EDD_SURFACE*)
DdHmgLock((HDD_OBJ) ahSurfaceVideo[i], DD_SURFACE_TYPE, FALSE);
}
for (i = 0; i < cAutoflipVbi; i++)
{
apeSurfaceVbi[i] = (EDD_SURFACE*)
DdHmgLock((HDD_OBJ) ahSurfaceVbi[i], DD_SURFACE_TYPE, FALSE);
}
EDD_DEVLOCK eDevlock(peDirectDrawGlobal);
if ((!peDirectDrawGlobal->bSuspended) &&
(peDirectDrawGlobal->VideoPortCallBacks.UpdateVideoPort) &&
(bUpdateOK = bDdUpdateLinksAndSynchronize(
peVideoPort,
TRUE, // Update video
apeSurfaceVideo,
cAutoflipVideo,
TRUE, // Update VBI
apeSurfaceVbi,
cAutoflipVbi)))
{
UpdateVPortData.lpDD = peDirectDrawGlobal;
UpdateVPortData.lpVideoPort = peVideoPort;
UpdateVPortData.lplpDDSurface = NULL;
UpdateVPortData.lplpDDVBISurface = NULL;
UpdateVPortData.dwNumAutoflip = cAutoflipVideo;
UpdateVPortData.dwNumVBIAutoflip = cAutoflipVbi;
UpdateVPortData.lpVideoInfo
= (UpdateVPortData.dwFlags == DDRAWI_VPORTSTOP)
? NULL
: &VideoPortInfo;
if (cAutoflipVideo != 0)
{
for (i = 0; i < cAutoflipVideo; i++)
{
apDDSurfaceVideo[i] = apeSurfaceVideo[i];
}
UpdateVPortData.lplpDDSurface = apDDSurfaceVideo;
}
if (cAutoflipVbi != 0)
{
for (i = 0; i < cAutoflipVbi; i++)
{
apDDSurfaceVbi[i] = apeSurfaceVbi[i];
}
UpdateVPortData.lplpDDVBISurface = apDDSurfaceVbi;
}
// Turn off software autoflipping if necessary:
if (UpdateVPortData.dwFlags == DDRAWI_VPORTSTOP)
{
peDxVideoPort->bSoftwareAutoflip = FALSE;
peDxVideoPort->flFlags &= ~(DD_DXVIDEOPORT_FLAG_AUTOFLIP|DD_DXVIDEOPORT_FLAG_AUTOFLIP_VBI);
// Disable the video port VSYNC IRQ now
if( peDxVideoPort->flFlags & DD_DXVIDEOPORT_FLAG_ON )
{
peDxVideoPort->flFlags &= ~DD_DXVIDEOPORT_FLAG_ON;
peDirectDrawGlobal->pfnEnableIRQ(peDxVideoPort, FALSE );
}
}
// We don't allow switching back to hardware once software
// autoflipping has started (for various reasons, among
// them being how do we synchronize -- the hardware would
// start autoflipping before we could turn off the software
// autoflipping).
if (peDxVideoPort->bSoftwareAutoflip)
{
VideoPortInfo.dwVPFlags &= ~DDVP_AUTOFLIP;
}
// Make the HAL call:
dwRet = peDirectDrawGlobal->
VideoPortCallBacks.UpdateVideoPort(&UpdateVPortData);
// If we failed due to a request for hardware autoflipping,
// try again with software autoflipping.
if ((dwRet == DDHAL_DRIVER_HANDLED) &&
(UpdateVPortData.ddRVal != DD_OK) &&
(peDirectDrawGlobal->DDKernelCaps.dwCaps & DDKERNELCAPS_AUTOFLIP))
{
VideoPortInfo.dwVPFlags &= ~DDVP_AUTOFLIP;
dwRet = peDirectDrawGlobal->
VideoPortCallBacks.UpdateVideoPort(&UpdateVPortData);
if ((dwRet == DDHAL_DRIVER_HANDLED) &&
(UpdateVPortData.ddRVal == DD_OK))
{
KdPrint(("DxDvpUpdateVideoPort: Software autoflipping\n"));
peDxVideoPort->bSoftwareAutoflip = TRUE;
UpdateVPortData.ddRVal = DD_OK;
}
}
if ((UpdateVPortData.ddRVal == DD_OK) &&
peDxVideoPort->bSoftwareAutoflip)
{
if( cAutoflipVideo > 0 )
{
peDxVideoPort->flFlags |= DD_DXVIDEOPORT_FLAG_AUTOFLIP;
}
if( cAutoflipVbi > 0 )
{
peDxVideoPort->flFlags |= DD_DXVIDEOPORT_FLAG_AUTOFLIP_VBI;
}
}
}
if (!bUpdateOK)
{
WARNING("DxDvpUpdateVideoPort: failed on bDdUpdateLinksAndSynchronize");
}
if ((dwRet == DDHAL_DRIVER_HANDLED) &&
(UpdateVPortData.ddRVal == DD_OK))
{
// Success!
peVideoPort->dwNumAutoflip = cAutoflipVideo;
peVideoPort->dwNumVBIAutoflip = cAutoflipVbi;
if (UpdateVPortData.dwFlags != DDRAWI_VPORTSTOP)
{
peVideoPort->ddvpInfo = VideoPortInfo;
if (VideoPortInfo.lpddpfInputFormat != NULL)
{
peVideoPort->ddvpInfo.lpddpfInputFormat
= &peVideoPort->ddpfInputFormat;
peVideoPort->ddpfInputFormat = ddpfInputFormat;
}
else
{
peVideoPort->ddvpInfo.lpddpfInputFormat = NULL;
}
}
}
// Update various DXAPI state to reflect the changes:
vDdSynchronizeVideoPort(peVideoPort);
// If it wasn't previously on, enable the video port VSYNC IRQ now
//
// if bDdUpdateLinksAndSynchronize failed, don't enable.
if( (bUpdateOK) &&
(UpdateVPortData.dwFlags != DDRAWI_VPORTSTOP) &&
!(peDxVideoPort->flFlags & DD_DXVIDEOPORT_FLAG_ON) )
{
peDxVideoPort->flFlags |= DD_DXVIDEOPORT_FLAG_ON;
peDirectDrawGlobal->pfnEnableIRQ(peDxVideoPort, TRUE );
}
// Unlock the memory that I've locked
for (i = 0; i < cAutoflipVideo; i++)
{
if( apeSurfaceVideo[i] != NULL )
DEC_EXCLUSIVE_REF_CNT( apeSurfaceVideo[i] );
}
for (i = 0; i < cAutoflipVbi; i++)
{
if( apeSurfaceVbi[i] != NULL )
DEC_EXCLUSIVE_REF_CNT( apeSurfaceVbi[i] );
}
}
else
{
WARNING("DxDvpUpdateVPortData: Invalid object\n");
}
// We have to wrap this in another try-except because the user-mode
// memory containing the input may have been deallocated by now:
__try
{
ProbeAndWriteRVal(&puUpdateVPortData->ddRVal, UpdateVPortData.ddRVal);
}
__except(EXCEPTION_EXECUTE_HANDLER)
{
}
return(dwRet);
}
/*****************************Private*Routine******************************\
* DWORD DxDvpWaitForVideoPortSync
*
* Returns at the beginning or end of either the video VSYNC or the specified
* line. If the sync does not occur before the number of milliseconds
* specified in dwTimeOut has elapsed, the HAL should return
* DDERR_VIDEONOTACTIVE.
*
* History:
* 2-Oct-1996 -by- Lingyun Wang [lingyunw]
* Wrote it.
\**************************************************************************/
DWORD
APIENTRY
DxDvpWaitForVideoPortSync(
HANDLE hVideoPort,
PDD_WAITFORVPORTSYNCDATA puWaitForVPortSyncData
)
{
DWORD dwRet;
DD_WAITFORVPORTSYNCDATA WaitForVPortSyncData;
__try
{
WaitForVPortSyncData = ProbeAndReadStructure(puWaitForVPortSyncData,
DD_WAITFORVPORTSYNCDATA);
}
__except(EXCEPTION_EXECUTE_HANDLER)
{
return(DDHAL_DRIVER_NOTHANDLED);
}
dwRet = DDHAL_DRIVER_NOTHANDLED;
WaitForVPortSyncData.ddRVal = DDERR_GENERIC;
EDD_VIDEOPORT* peVideoPort;
EDD_LOCK_VIDEOPORT eLockVideoPort;
EDD_DIRECTDRAW_GLOBAL* peDirectDrawGlobal;
peVideoPort = eLockVideoPort.peLock(hVideoPort);
if (peVideoPort != NULL)
{
peDirectDrawGlobal = peVideoPort->peDirectDrawGlobal;
WaitForVPortSyncData.lpDD = peDirectDrawGlobal;
WaitForVPortSyncData.lpVideoPort = peVideoPort;
// Cap the number of milliseconds to wait to something reasonable:
if (WaitForVPortSyncData.dwTimeOut
> 6 * peVideoPort->ddvpDesc.dwMicrosecondsPerField)
{
WaitForVPortSyncData.dwTimeOut
= 6 * peVideoPort->ddvpDesc.dwMicrosecondsPerField;
}
EDD_DEVLOCK eDevlock(peDirectDrawGlobal);
if ((!peDirectDrawGlobal->bSuspended) &&
(peDirectDrawGlobal->VideoPortCallBacks.WaitForVideoPortSync))
{
dwRet = peDirectDrawGlobal->VideoPortCallBacks.
WaitForVideoPortSync(&WaitForVPortSyncData);
}
}
else
{
WARNING("DxDvpWaitForVPortSyncData: Invalid object\n");
}
// We have to wrap this in another try-except because the user-mode
// memory containing the input may have been deallocated by now:
__try
{
ProbeAndWriteRVal(&puWaitForVPortSyncData->ddRVal,
WaitForVPortSyncData.ddRVal);
}
__except(EXCEPTION_EXECUTE_HANDLER)
{
}
return(dwRet);
}
/*****************************Private*Routine******************************\
* DWORD DxDvpColorControl
*
* Gets or sets the current color controls associated with the video port.
*
* History:
* 2-Oct-1996 -by- Lingyun Wang [lingyunw]
* Wrote it.
\**************************************************************************/
DWORD
APIENTRY
DxDvpColorControl(
HANDLE hVideoPort,
PDD_VPORTCOLORDATA puVPortColorData
)
{
DWORD dwRet;
DD_VPORTCOLORDATA VPortColorData;
DDCOLORCONTROL ColorData;
__try
{
VPortColorData = ProbeAndReadStructure(puVPortColorData,
DD_VPORTCOLORDATA);
ColorData = ProbeAndReadStructure(VPortColorData.lpColorData,
DDCOLORCONTROL);
}
__except(EXCEPTION_EXECUTE_HANDLER)
{
return(DDHAL_DRIVER_NOTHANDLED);
}
dwRet = DDHAL_DRIVER_NOTHANDLED;
VPortColorData.ddRVal = DDERR_GENERIC;
EDD_VIDEOPORT* peVideoPort;
EDD_LOCK_VIDEOPORT eLockVideoPort;
EDD_DIRECTDRAW_GLOBAL* peDirectDrawGlobal;
peVideoPort = eLockVideoPort.peLock(hVideoPort);
if (peVideoPort != NULL)
{
peDirectDrawGlobal = peVideoPort->peDirectDrawGlobal;
VPortColorData.lpDD = peDirectDrawGlobal;
VPortColorData.lpVideoPort = peVideoPort;
VPortColorData.lpColorData = &ColorData;
EDD_DEVLOCK eDevlock(peDirectDrawGlobal);
if ((!peDirectDrawGlobal->bSuspended) &&
(peDirectDrawGlobal->VideoPortCallBacks.ColorControl))
{
dwRet = peDirectDrawGlobal->
VideoPortCallBacks.ColorControl(&VPortColorData);
}
}
else
{
WARNING("DxDvpColorControl: Invalid object\n");
}
// We have to wrap this in another try-except because the user-mode
// memory containing the input may have been deallocated by now:
__try
{
ProbeAndWriteRVal(&puVPortColorData->ddRVal, VPortColorData.ddRVal);
}
__except(EXCEPTION_EXECUTE_HANDLER)
{
}
return(dwRet);
}
/*****************************Private*Routine******************************\
* DWORD DxDvpAcquireNotification
*
* Sets up the user mode notification of video port vsyncs.
*
* History:
* 10-Oct-2000 -Scott MacDonald [smac]
* Wrote it.
\**************************************************************************/
DWORD
APIENTRY
DxDvpAcquireNotification(
HANDLE hVideoPort,
HANDLE * phEvent,
LPDDVIDEOPORTNOTIFY pNotify
)
{
PKEVENT pEvent = NULL;
EDD_VIDEOPORT* peVideoPort;
EDD_LOCK_VIDEOPORT eLockVideoPort;
EDD_DIRECTDRAW_GLOBAL* peDirectDrawGlobal;
PMDL mdl;
LPDDVIDEOPORTNOTIFY pLockedBuffer;
__try
{
ProbeAndWriteHandle(phEvent, NULL);
}
__except(EXCEPTION_EXECUTE_HANDLER)
{
return DDHAL_DRIVER_NOTHANDLED;
}
// First check the caps to see if this device even supports a vport IRQ
peVideoPort = eLockVideoPort.peLock(hVideoPort);
if ((peVideoPort != NULL) &&
(peVideoPort->peDxVideoPort->pNotifyEvent == NULL))
{
peDirectDrawGlobal = peVideoPort->peDirectDrawGlobal;
if (peDirectDrawGlobal->DDKernelCaps.dwIRQCaps & DDIRQ_VPORT0_VSYNC )
{
// Now setup the buffer so it can be accessed at DPC level
mdl = IoAllocateMdl(pNotify,
sizeof(DDVIDEOPORTNOTIFY),
FALSE,
FALSE,
NULL);
if (mdl != NULL)
{
__try
{
MmProbeAndLockPages (mdl,
KernelMode,
IoWriteAccess);
}
__except(EXCEPTION_EXECUTE_HANDLER)
{
IoFreeMdl (mdl);
mdl = NULL;
}
}
if (mdl != NULL)
{
pLockedBuffer = (LPDDVIDEOPORTNOTIFY)
MmGetSystemAddressForMdlSafe (mdl,
NormalPagePriority);
if (pLockedBuffer == NULL)
{
MmUnlockPages (mdl);
IoFreeMdl (mdl);
}
else
{
// Now set up the event that we trigger
HANDLE h = NULL;
ZwCreateEvent( &h,
EVENT_ALL_ACCESS,
NULL,
SynchronizationEvent,
FALSE );
if (h != NULL)
{
(VOID) ObReferenceObjectByHandle( h,
0,
0,
KernelMode,
(PVOID *) &pEvent,
NULL );
}
if (pEvent != NULL)
{
ObDereferenceObject(pEvent);
peVideoPort->peDxVideoPort->pNotifyBuffer = pLockedBuffer;
peVideoPort->peDxVideoPort->pNotifyMdl = mdl;
peVideoPort->peDxVideoPort->pNotifyEvent = pEvent;
peVideoPort->peDxVideoPort->pNotifyEventHandle = h;
__try
{
ProbeAndWriteHandle(phEvent, h);
}
__except(EXCEPTION_EXECUTE_HANDLER)
{
}
}
else
{
MmUnlockPages (mdl);
IoFreeMdl (mdl);
}
}
// force software autoflipping
peVideoPort->peDxVideoPort->bSoftwareAutoflip = TRUE;
}
}
}
return 0;
}
/*****************************Private*Routine******************************\
* DWORD DxDvpReleaseNotification
*
* Stops up the user mode notification of video port vsyncs.
*
* History:
* 10-Oct-2000 -Scott MacDonald [smac]
* Wrote it.
\**************************************************************************/
DWORD
APIENTRY
DxDvpReleaseNotification(
HANDLE hVideoPort,
HANDLE pEvent
)
{
EDD_VIDEOPORT* peVideoPort;
EDD_LOCK_VIDEOPORT eLockVideoPort;
peVideoPort = eLockVideoPort.peLock(hVideoPort);
if ((peVideoPort != NULL) &&
(peVideoPort->peDxVideoPort->pNotifyEventHandle == pEvent) &&
(pEvent != NULL))
{
PKEVENT pTemp = NULL;
NTSTATUS Status;
peVideoPort->peDxVideoPort->pNotifyEvent = NULL;
peVideoPort->peDxVideoPort->pNotifyEventHandle = NULL;
// Make sure that the handle hasn't been freed by the OS already
Status = ObReferenceObjectByHandle( pEvent,
0,
0,
KernelMode,
(PVOID *) &pTemp,
NULL );
if ((pTemp != NULL) && (Status != STATUS_INVALID_HANDLE))
{
ObDereferenceObject(pTemp);
ZwClose (pEvent);
}
peVideoPort->peDxVideoPort->pNotifyBuffer = NULL;
if (peVideoPort->peDxVideoPort->pNotifyMdl != NULL)
{
MmUnlockPages (peVideoPort->peDxVideoPort->pNotifyMdl);
IoFreeMdl (peVideoPort->peDxVideoPort->pNotifyMdl);
peVideoPort->peDxVideoPort->pNotifyMdl = NULL;
}
}
return 0;
}