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.
 
 
 
 
 
 

5818 lines
151 KiB

/*==========================================================================
* Copyright (C) 1996 Microsoft Corporation. All Rights Reserved.
*
* File: ddvp.c
* Content: DirectDrawVideoPort
* History:
* Date By Reason
* ==== == ======
* 11-jun-96 scottm created
* 29-jan-97 smac Various API changes and bug fixes
* 31-jan-97 colinmc Bug 5457: Fixed problem with new aliased (no-Win16
* lock) and multiple AMovie clips playing on old cards.
* 03-mar-97 smac Added kernel mode interface and fixed some bugs
*
***************************************************************************/
#include "ddrawpr.h"
#ifdef WINNT
#include "ddrawgdi.h"
#include "ddkmmini.h"
#include "ddkmapi.h"
#else
#include "ddkmmini.h"
#include "ddkmapip.h"
#endif
#define DPF_MODNAME "DirectDrawVideoPort"
#define MAX_VP_FORMATS 25
#define MAX_VIDEO_PORTS 10
DDPIXELFORMAT ddpfVPFormats[MAX_VP_FORMATS];
BOOL bInEnumCallback = FALSE;
HRESULT InternalUpdateVideo( LPDDRAWI_DDVIDEOPORT_INT, LPDDVIDEOPORTINFO );
HRESULT InternalStartVideo( LPDDRAWI_DDVIDEOPORT_INT, LPDDVIDEOPORTINFO );
LPDDPIXELFORMAT GetSurfaceFormat( LPDDRAWI_DDRAWSURFACE_LCL );
HRESULT CreateVideoPortNotify( LPDDRAWI_DDVIDEOPORT_INT, LPDIRECTDRAWVIDEOPORTNOTIFY *lplpVPNotify );
/*
* This function 1) updates the surfaces in the chain so they know they
* are no longer receiving video port data and 2) releases any implicitly
* created kernel handles.
*/
VOID ReleaseVPESurfaces( LPDDRAWI_DDRAWSURFACE_INT surf_int, BOOL bRelease )
{
LPDDRAWI_DDRAWSURFACE_INT surf_first;
DDASSERT( surf_int != NULL );
surf_first = surf_int;
do
{
if( bRelease &&
( surf_int->lpLcl->lpGbl->dwGlobalFlags & DDRAWISURFGBL_IMPLICITHANDLE ) )
{
InternalReleaseKernelSurfaceHandle( surf_int->lpLcl, FALSE );
surf_int->lpLcl->lpGbl->dwGlobalFlags &= ~DDRAWISURFGBL_IMPLICITHANDLE;
}
surf_int->lpLcl->lpSurfMore->lpVideoPort = NULL;
surf_int = FindAttachedFlip( surf_int );
} while( ( surf_int != NULL ) && ( surf_int->lpLcl != surf_first->lpLcl ) );
}
/*
* This function 1) updates the surfaces in the chain so they know they
* are receiving video port data and 2) implicitly creates kernel handles
* for each surface if one does not already exist so ring 0 can perform
* software autoflipping or software bobbing.
*/
DWORD PrepareVPESurfaces( LPDDRAWI_DDRAWSURFACE_INT surf_int,
LPDDRAWI_DDVIDEOPORT_LCL lpVideoPort, BOOL bAutoflipping )
{
LPDDRAWI_DDRAWSURFACE_GBL_MORE lpSurfGblMore;
LPDDRAWI_DDRAWSURFACE_INT surf_first;
ULONG_PTR dwHandle;
DWORD ddRVal;
DDASSERT( surf_int != NULL );
surf_first = surf_int;
do
{
/*
* Create a kernel handle if one doesn't already exist
*/
if( bAutoflipping )
{
surf_int->lpLcl->lpSurfMore->lpVideoPort = lpVideoPort;
}
lpSurfGblMore = GET_LPDDRAWSURFACE_GBL_MORE( surf_int->lpLcl->lpGbl );
if( ( lpSurfGblMore->hKernelSurface == 0 ) &&
!( lpVideoPort->dwFlags & DDRAWIVPORT_NOKERNELHANDLES ) )
{
ddRVal = InternalCreateKernelSurfaceHandle( surf_int->lpLcl, &dwHandle );
if( ddRVal == DD_OK )
{
surf_int->lpLcl->lpGbl->dwGlobalFlags |= DDRAWISURFGBL_IMPLICITHANDLE;
}
else
{
/*
* This is not a catastrophic failure, but it will stop us
* from software autoflipping.
*/
lpVideoPort->dwFlags |= DDRAWIVPORT_NOKERNELHANDLES;
}
}
surf_int = FindAttachedFlip( surf_int );
} while( ( surf_int != NULL ) && ( surf_int->lpLcl != surf_first->lpLcl ) );
if( !bAutoflipping )
{
surf_first->lpLcl->lpSurfMore->lpVideoPort = lpVideoPort;
}
return DD_OK;
}
/*
* GetVideoPortFromSurface
*
* Returns the video port associated with the surface. The video
* port can be anywhere in the surface list.
*/
LPDDRAWI_DDVIDEOPORT_LCL GetVideoPortFromSurface( LPDDRAWI_DDRAWSURFACE_INT surf_int )
{
LPDDRAWI_DDRAWSURFACE_INT surf_first;
LPDDRAWI_DDVIDEOPORT_LCL lpVp;
/*
* Is it associated with video port? If not explicitly, is another
* surface in the chain explicitly associated?
*/
lpVp = surf_int->lpLcl->lpSurfMore->lpVideoPort;
if( lpVp == NULL )
{
surf_first = surf_int;
do
{
surf_int = FindAttachedFlip( surf_int );
if( surf_int != NULL )
{
lpVp = surf_int->lpLcl->lpSurfMore->lpVideoPort;
}
}
while( ( surf_int != NULL ) && ( lpVp == NULL ) && ( surf_int->lpLcl != surf_first->lpLcl ) );
}
return lpVp;
}
/*
* Determines if the specified overlay surface can support autoflipping
* Return: 0 = Not valid, 1 = software only, 2 = hardware autoflipping
*/
DWORD IsValidAutoFlipSurface( LPDDRAWI_DDRAWSURFACE_INT lpSurface_int )
{
LPDDRAWI_DDRAWSURFACE_INT lpFirstSurf;
LPDDRAWI_DDRAWSURFACE_INT lpSurf;
LPDDRAWI_DDVIDEOPORT_LCL lpVp;
BOOL bFound;
/*
* Is it associated with video port?
*/
lpVp = GetVideoPortFromSurface( lpSurface_int );
if( lpVp == NULL )
{
return IVAS_NOAUTOFLIPPING;
}
/*
* Is the video port autoflipping? If not, then neither can the overlay.
*/
if( !( lpVp->ddvpInfo.dwVPFlags & DDVP_AUTOFLIP ) )
{
return IVAS_NOAUTOFLIPPING;
}
/*
* It's still possible that VBI is autoflipping, but not the regular
* video (which applies to the overlay).
*/
if( lpVp->dwNumAutoflip == 0 )
{
return IVAS_NOAUTOFLIPPING;
}
lpSurf = lpFirstSurf = lpVp->lpSurface;
bFound = FALSE;
if( lpFirstSurf != NULL )
{
do
{
if( lpSurf->lpLcl == lpSurface_int->lpLcl )
{
bFound = TRUE;
}
lpSurf = FindAttachedFlip( lpSurf );
} while( !bFound && ( lpSurf != NULL) && ( lpSurf->lpLcl != lpFirstSurf->lpLcl ) );
}
if( !bFound )
{
return IVAS_NOAUTOFLIPPING;
}
/*
* If the video port is software autoflipping, then the overlay must
* as well.
*/
if( lpVp->dwFlags & DDRAWIVPORT_SOFTWARE_AUTOFLIP )
{
return IVAS_SOFTWAREAUTOFLIPPING;
}
return IVAS_HARDWAREAUTOFLIPPING;
}
/*
* Notifies the video port that the overlay will only allow software
* autoflipping
*/
VOID RequireSoftwareAutoflip( LPDDRAWI_DDRAWSURFACE_INT lpSurface_int )
{
LPDDRAWI_DDVIDEOPORT_LCL lpVideoPort;
lpVideoPort = GetVideoPortFromSurface( lpSurface_int );
if( lpVideoPort != NULL )
{
lpVideoPort->dwFlags |= DDRAWIVPORT_SOFTWARE_AUTOFLIP;
/*
* If they are already hardware autoflipping, make them switch
* to software.
*/
if( lpVideoPort->dwFlags & DDRAWIVPORT_ON )
{
LPDDRAWI_DDVIDEOPORT_INT lpVp_int;
/*
* The next function requires a DDVIDEOPORT_INT and all we
* have is a DDVIDEOPORT_LCL, so we need to search for it.
*/
lpVp_int = lpSurface_int->lpLcl->lpSurfMore->lpDD_lcl->lpGbl->dvpList;
while( lpVp_int != NULL )
{
if( ( lpVp_int->lpLcl == lpVideoPort ) &&
!( lpVp_int->dwFlags & DDVPCREATE_NOTIFY ) )
{
InternalUpdateVideo( lpVp_int,
&( lpVp_int->lpLcl->ddvpInfo) );
}
lpVp_int = lpVp_int->lpLink;
}
}
}
}
/*
* Determines if the overlay must be bobbed using software or whether
* it should try software.
*/
BOOL MustSoftwareBob( LPDDRAWI_DDRAWSURFACE_INT lpSurface_int )
{
LPDDRAWI_DDVIDEOPORT_LCL lpVp;
/*
* Is it associated with video port?
*/
lpVp = GetVideoPortFromSurface( lpSurface_int );
if( lpVp == NULL )
{
return TRUE;
}
/*
* If the video port is software autoflipping or software bobbing,
* then the overlay must as well.
*/
if( ( lpVp->dwFlags & DDRAWIVPORT_SOFTWARE_AUTOFLIP ) ||
( lpVp->dwFlags & DDRAWIVPORT_SOFTWARE_BOB ) )
{
return TRUE;
}
return FALSE;
}
/*
* Notifies the video port that the overlay will only allow software
* bobbing
*/
VOID RequireSoftwareBob( LPDDRAWI_DDRAWSURFACE_INT lpSurface_int )
{
LPDDRAWI_DDVIDEOPORT_LCL lpVideoPort;
lpVideoPort = GetVideoPortFromSurface( lpSurface_int );
if( lpVideoPort != NULL )
{
lpVideoPort->dwFlags |= DDRAWIVPORT_SOFTWARE_BOB;
/*
* If they are already hardware autoflipping, make them switch
* to software.
*/
if( ( lpVideoPort->dwFlags & DDRAWIVPORT_ON ) &&
( lpVideoPort->dwNumAutoflip > 0 ) &&
!( lpVideoPort->dwFlags & DDRAWIVPORT_SOFTWARE_AUTOFLIP ) )
{
LPDDRAWI_DDVIDEOPORT_INT lpVp_int;
/*
* The next function requires a DDVIDEOPORT_INT and all we
* have is a DDVIDEOPORT_LCL, so we need to search for it.
*/
lpVp_int = lpSurface_int->lpLcl->lpSurfMore->lpDD_lcl->lpGbl->dvpList;
while( lpVp_int != NULL )
{
if( ( lpVp_int->lpLcl == lpVideoPort ) &&
!( lpVp_int->dwFlags & DDVPCREATE_NOTIFY ) )
{
InternalUpdateVideo( lpVp_int,
&( lpVp_int->lpLcl->ddvpInfo) );
}
lpVp_int = lpVp_int->lpLink;
}
}
}
}
#ifdef WIN95
/*
* OverrideOverlay
*
* Checks to see if there is a chance that the kernel mode interface
* has changed the state from bob to weave or visa versa, or if it's
* cahnged from hardware autoflipping to software autoflipping. If the
* chance exists, it calls down to ring 0 to get the state and if
* it's changed, changes the overlay parameters accordingly.
*/
VOID OverrideOverlay( LPDDRAWI_DDRAWSURFACE_INT surf_int,
LPDWORD lpdwFlags )
{
LPDDRAWI_DDRAWSURFACE_GBL_MORE lpSurfGblMore;
LPDDRAWI_DDRAWSURFACE_MORE lpSurfMore;
LPDDRAWI_DDVIDEOPORT_LCL lpVp;
DWORD dwStateFlags;
/*
* Ring 0 can change the state, so we need to call down to it.
*/
lpSurfMore = surf_int->lpLcl->lpSurfMore;
lpSurfGblMore = GET_LPDDRAWSURFACE_GBL_MORE( surf_int->lpLcl->lpGbl );
if( lpSurfGblMore->hKernelSurface != 0 )
{
dwStateFlags = 0;
GetKernelSurfaceState( surf_int->lpLcl, &dwStateFlags );
if( dwStateFlags & DDSTATE_EXPLICITLY_SET )
{
if( ( dwStateFlags & DDSTATE_BOB ) &&
!( *lpdwFlags & DDOVER_BOB ) )
{
// Switch from weave to bob
*lpdwFlags |= DDOVER_BOB;
}
else if( ( dwStateFlags & DDSTATE_WEAVE ) &&
( *lpdwFlags & DDOVER_BOB ) )
{
// Switch from bob to weave
*lpdwFlags &= ~DDOVER_BOB;
}
else if( ( dwStateFlags & DDSTATE_SKIPEVENFIELDS ) &&
( *lpdwFlags & DDOVER_BOB ) )
{
// Switch from bob to weave
*lpdwFlags &= ~DDOVER_BOB;
}
}
lpVp = GetVideoPortFromSurface( surf_int );
if( ( dwStateFlags & DDSTATE_SOFTWARE_AUTOFLIP ) &&
( lpVp != NULL ) &&
( lpVp->ddvpInfo.dwVPFlags & DDVP_AUTOFLIP ) &&
!( lpVp->dwFlags & DDRAWIVPORT_SOFTWARE_AUTOFLIP ) )
{
RequireSoftwareAutoflip( surf_int );
}
}
}
/*
* OverrideVideoPort
*
* Checks to see if there is a chance that the kernel mode interface
* has changed the state from bob/weave to field skipping or visa versa.
* If the chance exists, it calls down to ring 0 to get the state and if
* it's changed, changes the overlay parameters accordingly.
*/
VOID OverrideVideoPort( LPDDRAWI_DDRAWSURFACE_INT surf_int,
LPDWORD lpdwFlags )
{
LPDDRAWI_DDRAWSURFACE_GBL_MORE lpSurfGblMore;
LPDDRAWI_DDRAWSURFACE_MORE lpSurfMore;
DWORD dwStateFlags;
/*
* Ring 0 can change the state, so we need to call down to it.
*/
lpSurfMore = surf_int->lpLcl->lpSurfMore;
lpSurfGblMore = GET_LPDDRAWSURFACE_GBL_MORE( surf_int->lpLcl->lpGbl );
if( lpSurfGblMore->hKernelSurface != 0 )
{
dwStateFlags = 0;
GetKernelSurfaceState( surf_int->lpLcl, &dwStateFlags );
if( dwStateFlags & DDSTATE_EXPLICITLY_SET )
{
if( ( dwStateFlags & DDSTATE_SKIPEVENFIELDS ) &&
!( *lpdwFlags & DDVP_SKIPODDFIELDS ) )
{
// Switch from bob to weave
*lpdwFlags &= ~DDVP_INTERLEAVE;
*lpdwFlags |= DDVP_SKIPEVENFIELDS;
}
}
}
}
#endif
/*
* UpdateInterleavedFlags
*
* We want to track whether the surface data came from a vidoe port or not
* and if it did, was it interleaved. This is important so we can
* automatically set the DDOVER_INTERLEAVED flag while using the video port.
*/
VOID UpdateInterleavedFlags( LPDDRAWI_DDVIDEOPORT_LCL this_lcl, DWORD dwVPFlags )
{
LPDDRAWI_DDRAWSURFACE_INT surf_first;
LPDDRAWI_DDRAWSURFACE_INT surf_temp;
/*
* Since the interleaved flag is only used for calling UpdateOverlay,
* we only need to handle this for the regular video.
*/
surf_temp = this_lcl->lpSurface;
if( surf_temp == NULL )
{
return;
}
/*
* If autoflipping, update every surface in the chain.
*/
if( ( dwVPFlags & DDVP_AUTOFLIP ) && ( this_lcl->dwNumAutoflip > 0 ) )
{
surf_first = surf_temp;
do
{
surf_temp->lpLcl->lpGbl->dwGlobalFlags |= DDRAWISURFGBL_VPORTDATA;
if( dwVPFlags & DDVP_INTERLEAVE )
{
surf_temp->lpLcl->lpGbl->dwGlobalFlags |= DDRAWISURFGBL_VPORTINTERLEAVED;
}
else
{
surf_temp->lpLcl->lpGbl->dwGlobalFlags &= ~DDRAWISURFGBL_VPORTINTERLEAVED;
}
surf_temp = FindAttachedFlip( surf_temp );
} while( ( surf_temp != NULL ) && ( surf_temp->lpLcl != surf_first->lpLcl ) );
}
else
{
surf_temp->lpLcl->lpGbl->dwGlobalFlags |= DDRAWISURFGBL_VPORTDATA;
if( dwVPFlags & DDVP_INTERLEAVE )
{
surf_temp->lpLcl->lpGbl->dwGlobalFlags |= DDRAWISURFGBL_VPORTINTERLEAVED;
}
else
{
surf_temp->lpLcl->lpGbl->dwGlobalFlags &= ~DDRAWISURFGBL_VPORTINTERLEAVED;
}
}
}
/*
* InternalVideoPortFlip
*
* This fucntion acts differntly based on whether the flip is occurring
* based on an overlay flip or whether an explicit flip was specified.
*/
HRESULT InternalVideoPortFlip( LPDDRAWI_DDVIDEOPORT_LCL this_lcl,
LPDDRAWI_DDRAWSURFACE_INT next_int,
BOOL bExplicit )
{
LPDDRAWI_DDRAWSURFACE_LCL next_lcl;
LPDDHALVPORTCB_FLIP pfn;
DDHAL_FLIPVPORTDATA FlipData;
DWORD rc;
/*
* surfaces must be in video memory
*/
next_lcl = next_int->lpLcl;
if( next_lcl->ddsCaps.dwCaps & DDSCAPS_SYSTEMMEMORY)
{
if ( !( this_lcl->lpDD->lpGbl->lpDDVideoPortCaps[this_lcl->ddvpDesc.dwVideoPortID].dwCaps &
DDVPCAPS_SYSTEMMEMORY ) )
{
DPF_ERR( "Surface must be in video memory" );
return DDERR_INVALIDPARAMS;
}
if( next_lcl->lpSurfMore->dwPageLockCount == 0 )
{
DPF_ERR( "Surface must be page locked" );
return DDERR_INVALIDPARAMS;
}
}
/*
* surfaces must have the VIDEOPORT attribute
*/
if( !( next_lcl->ddsCaps.dwCaps & DDSCAPS_VIDEOPORT ) )
{
DPF_ERR( "Surface must have the DDSCAPS_VIDEOPORT attribute" );
return DDERR_INVALIDPARAMS;
}
/*
* Tell the HAL to perform the flip
*/
pfn = this_lcl->lpDD->lpDDCB->HALDDVideoPort.FlipVideoPort;
if( pfn != NULL )
{
FlipData.lpDD = this_lcl->lpDD;
FlipData.lpVideoPort = this_lcl;
FlipData.lpSurfCurr = this_lcl->lpSurface->lpLcl;
FlipData.lpSurfTarg = next_lcl;
DOHALCALL( FlipVideoPort, pfn, FlipData, rc, 0 );
if( DDHAL_DRIVER_HANDLED != rc )
{
return DDERR_UNSUPPORTED;
}
else if( DD_OK != FlipData.ddRVal )
{
return FlipData.ddRVal;
}
}
else
{
return DDERR_UNSUPPORTED;
}
/*
* Update the surfaces so they know which one is connected to the
* video port.
*/
if( bExplicit )
{
if( this_lcl->lpSurface != NULL )
{
this_lcl->lpSurface->lpLcl->lpSurfMore->lpVideoPort = NULL;
}
next_int->lpLcl->lpSurfMore->lpVideoPort = this_lcl;
this_lcl->lpSurface = next_int;
}
UpdateInterleavedFlags( this_lcl, this_lcl->ddvpInfo.dwVPFlags );
this_lcl->fpLastFlip = next_int->lpLcl->lpGbl->fpVidMem;
return DD_OK;
}
/*
* FlipVideoPortToN
*
* This flips the video port to the next N surface. If N is 1, it flips it
* to the next surface, etc.
*/
HRESULT FlipVideoPortToN( LPDDRAWI_DDVIDEOPORT_LCL this_lcl, DWORD dwSkipNum )
{
LPDDRAWI_DDRAWSURFACE_INT surf_int;
DWORD i;
/*
* Get the target surface. We can eliminate a lot of error checking
* since this function is called from DD_Surface_Flip which already
* performs the same error checking.
*/
surf_int = this_lcl->lpSurface;
for( i = 0; i < dwSkipNum; i++ )
{
surf_int = FindAttachedFlip( surf_int );
}
if (surf_int == NULL)
{
// Better to do this instead of faulting.
DPF_ERR("Couldn't find Nth flipping surface.");
return DDERR_INVALIDPARAMS;
}
return InternalVideoPortFlip( this_lcl, surf_int, 0 );
}
/*
* FlipVideoPortSurface
*
* Called when flipping a surface that is fed by a video port. This searches
* for each videoport associated with the surface and flips the video port.
*/
DWORD FlipVideoPortSurface( LPDDRAWI_DDRAWSURFACE_INT surf_int, DWORD dwNumSkipped )
{
LPDDRAWI_DDRAWSURFACE_INT surf_first;
LPDDRAWI_DIRECTDRAW_GBL lpDD_Gbl;
LPDDRAWI_DDVIDEOPORT_INT lpVp;
LPDDRAWI_DDRAWSURFACE_INT lpSurface;
BOOL bFound;
DWORD rc;
lpDD_Gbl = surf_int->lpLcl->lpSurfMore->lpDD_lcl->lpGbl;
lpVp = lpDD_Gbl->dvpList;
while( lpVp != NULL )
{
bFound = FALSE;
if( ( lpVp->lpLcl->lpSurface != NULL ) &&
!( lpVp->lpLcl->ddvpInfo.dwVPFlags & DDVP_AUTOFLIP ) &&
!( lpVp->dwFlags & DDVPCREATE_NOTIFY ) )
{
surf_first = lpSurface = lpVp->lpLcl->lpSurface;
do
{
if( lpSurface == surf_int )
{
rc = FlipVideoPortToN( lpVp->lpLcl, dwNumSkipped );
bFound = TRUE;
}
lpSurface = FindAttachedFlip( lpSurface );
} while( ( lpSurface != NULL ) && ( lpSurface->lpLcl != surf_first->lpLcl ) );
}
lpVp = lpVp->lpLink;
}
return DD_OK;
}
/*
* IndepenantVBIPossible
*
* Returns TRUE if the specified caps determine it is possible to manage the
* VBI stream completely independant of the video stream.
*/
BOOL IndependantVBIPossible( LPDDVIDEOPORTCAPS lpCaps )
{
if( ( lpCaps->dwCaps & ( DDVPCAPS_VBISURFACE|DDVPCAPS_OVERSAMPLEDVBI ) ) !=
( DDVPCAPS_VBISURFACE | DDVPCAPS_OVERSAMPLEDVBI ) )
{
return FALSE;
}
if( ( lpCaps->dwFX & ( DDVPFX_VBINOSCALE | DDVPFX_IGNOREVBIXCROP |
DDVPFX_VBINOINTERLEAVE ) ) != ( DDVPFX_VBINOSCALE |
DDVPFX_IGNOREVBIXCROP | DDVPFX_VBINOINTERLEAVE ) )
{
return FALSE;
}
return TRUE;
}
/*
* DDVPC_EnumVideoPorts
*/
HRESULT DDAPI DDVPC_EnumVideoPorts(
LPDDVIDEOPORTCONTAINER lpDVP,
DWORD dwReserved,
LPDDVIDEOPORTCAPS lpCaps,
LPVOID lpContext,
LPDDENUMVIDEOCALLBACK lpEnumCallback )
{
LPDDRAWI_DIRECTDRAW_INT this_int;
LPDDRAWI_DIRECTDRAW_LCL this_lcl;
LPDDVIDEOPORTCAPS lpHALCaps;
DWORD rc;
DWORD dwMaxVideoPorts;
DWORD flags;
DWORD i;
BOOL bEnumThisOne;
ENTER_DDRAW();
DPF(2,A,"ENTERAPI: DDVPC_EnumVideoPorts");
/*
* Don't allow access to this function if called from within the
* the EnumVideoPort callback.
*/
if( bInEnumCallback )
{
DPF_ERR ( "This function cannot be called from within the EnumVideoPort callback!");
LEAVE_DDRAW();
return DDERR_CURRENTLYNOTAVAIL;
}
/*
* validate parameters
*/
TRY
{
this_int = (LPDDRAWI_DIRECTDRAW_INT) lpDVP;
if( !VALID_DIRECTDRAW_PTR( this_int ) )
{
DPF_ERR( "Invalid video port container specified" );
LEAVE_DDRAW();
return DDERR_INVALIDOBJECT;
}
this_lcl = this_int->lpLcl;
if( !VALIDEX_CODE_PTR( lpEnumCallback ) )
{
DPF_ERR( "Invalid callback routine" );
LEAVE_DDRAW();
return DDERR_INVALIDPARAMS;
}
if( NULL == lpCaps )
{
/*
* If a NULL description is defined, we will assume that they
* want to enum everything.
*/
flags = 0;
}
else
{
if( !VALID_DDVIDEOPORTCAPS_PTR( lpCaps ) )
{
DPF_ERR( "Invalid DDVIDEOPORTCAPS specified" );
LEAVE_DDRAW();
return DDERR_INVALIDPARAMS;
}
flags = lpCaps->dwFlags;
/*
* check height/width
*/
if( ((flags & DDVPD_HEIGHT) && !(flags & DDVPD_WIDTH)) ||
(!(flags & DDVPD_HEIGHT) && (flags & DDVPD_WIDTH)) )
{
DPF_ERR( "Specify both height & width in video port desc" );
LEAVE_DDRAW();
return DDERR_INVALIDPARAMS;
}
if( lpCaps->dwVideoPortID >= this_lcl->lpGbl->ddCaps.dwMaxVideoPorts )
{
DPF_ERR( "Invalid video port ID specified" );
LEAVE_DDRAW();
return DDERR_INVALIDPARAMS;
}
}
if( NULL == this_lcl->lpGbl->lpDDVideoPortCaps )
{
DPF_ERR( "Driver failed query for video port caps" );
LEAVE_DDRAW();
return DDERR_UNSUPPORTED;
}
for( i = 0; i < this_lcl->lpGbl->ddCaps.dwMaxVideoPorts; i++ )
{
lpHALCaps = &(this_lcl->lpGbl->lpDDVideoPortCaps[i]);
if( !VALID_DDVIDEOPORTCAPS_PTR( lpHALCaps ) )
{
DPF_ERR( "Driver returned invalid DDVIDEOPORTCAPS" );
LEAVE_DDRAW();
return DDERR_UNSUPPORTED;
}
}
}
EXCEPT( EXCEPTION_EXECUTE_HANDLER )
{
DPF_ERR( "Exception encountered validating parameters" );
LEAVE_DDRAW();
return DDERR_INVALIDPARAMS;
}
/*
* Look at each video port and match it with the input description.
*/
dwMaxVideoPorts = this_lcl->lpGbl->ddCaps.dwMaxVideoPorts;
lpHALCaps = this_lcl->lpGbl->lpDDVideoPortCaps;
for (i = 0; i < dwMaxVideoPorts; i++)
{
bEnumThisOne = TRUE;
if( flags & DDVPD_WIDTH )
{
if( lpCaps->dwMaxWidth > lpHALCaps->dwMaxWidth )
bEnumThisOne = FALSE;
}
if( flags & DDVPD_HEIGHT )
{
if( lpCaps->dwMaxHeight > lpHALCaps->dwMaxHeight )
bEnumThisOne = FALSE;
}
if( flags & DDVPD_ID )
{
if( lpCaps->dwVideoPortID != lpHALCaps->dwVideoPortID )
bEnumThisOne = FALSE;
}
if( flags & DDVPD_CAPS )
{
/*
* Simple check to make sure no caps were specified that are
* not returned by the HAL.
*/
if ( (lpCaps->dwCaps & lpHALCaps->dwCaps) != lpCaps->dwCaps )
bEnumThisOne = FALSE;
}
if( flags & DDVPD_FX )
{
/*
* Simple check to make sure no FX were specified that are
* not returned by the HAL.
*/
if ( (lpCaps->dwFX & lpHALCaps->dwFX) != lpCaps->dwFX )
bEnumThisOne = FALSE;
}
if ( TRUE == bEnumThisOne )
{
/*
* Don't trust the drivers to set this bit correctly (especially
* since we are adding it so late)
*/
if( IndependantVBIPossible( lpHALCaps ) )
{
lpHALCaps->dwCaps |= DDVPCAPS_VBIANDVIDEOINDEPENDENT;
}
else
{
lpHALCaps->dwCaps &= ~DDVPCAPS_VBIANDVIDEOINDEPENDENT;
}
/*
* We added the dwNumPrefferedAutoflip for Memphis, so some
* old drivers might not report this correctly. For that reason,
* we will attempt to fill in a valid value.
*/
if( !( lpHALCaps->dwFlags & DDVPD_PREFERREDAUTOFLIP ) )
{
/*
* The driver did not set this, so we should force the
* value to 3.
*/
lpHALCaps->dwNumPreferredAutoflip = 3;
lpHALCaps->dwFlags |= DDVPD_PREFERREDAUTOFLIP;
}
if( lpHALCaps->dwNumPreferredAutoflip > lpHALCaps->dwNumAutoFlipSurfaces )
{
lpHALCaps->dwNumPreferredAutoflip = lpHALCaps->dwNumAutoFlipSurfaces;
}
bInEnumCallback = TRUE;
rc = lpEnumCallback( lpHALCaps, lpContext );
bInEnumCallback = FALSE;
if( rc == 0 )
{
break;
}
}
lpHALCaps++;
}
LEAVE_DDRAW();
return DD_OK;
} /* DDVPC_EnumVideoPorts */
/*
* DDVPC_GetVideoPortConnectInfo
*/
HRESULT DDAPI DDVPC_GetVideoPortConnectInfo(
LPDDVIDEOPORTCONTAINER lpDVP,
DWORD dwVideoPortID,
LPDWORD lpdwNumEntries,
LPDDVIDEOPORTCONNECT lpConnect )
{
LPDDHALVPORTCB_GETVPORTCONNECT pfn;
LPDDRAWI_DIRECTDRAW_INT this_int;
LPDDRAWI_DIRECTDRAW_LCL this_lcl;
LPDDVIDEOPORTCONNECT lpTemp;
DDHAL_GETVPORTCONNECTDATA GetGuidData;
DWORD rc;
DWORD i;
ENTER_DDRAW();
DPF(2,A,"ENTERAPI: DDVPC_GetVideoPortConnectInfo");
/*
* Don't allow access to this function if called from within the
* the EnumVideoPort callback.
*/
if( bInEnumCallback )
{
DPF_ERR ( "This function cannot be called from within the EnumVideoPort callback!");
LEAVE_DDRAW();
return DDERR_CURRENTLYNOTAVAIL;
}
/*
* Validate parameters
*/
TRY
{
this_int = (LPDDRAWI_DIRECTDRAW_INT) lpDVP;
if( !VALID_DIRECTDRAW_PTR( this_int ) )
{
DPF_ERR ( "DDVPC_GetVideoPortConnectInfo: Invalid DirectDraw ptr");
LEAVE_DDRAW();
return DDERR_INVALIDOBJECT;
}
this_lcl = this_int->lpLcl;
#ifdef WINNT
// Update DDraw handle in driver GBL object.
this_lcl->lpGbl->hDD = this_lcl->hDD;
#endif
if( dwVideoPortID >= this_lcl->lpGbl->ddCaps.dwMaxVideoPorts )
{
DPF_ERR ( "DDVPC_GetVideoPortConnectInfo: invalid port ID");
LEAVE_DDRAW();
return DDERR_INVALIDPARAMS;
}
if( (lpdwNumEntries == NULL) || !VALID_BYTE_ARRAY( lpdwNumEntries, sizeof( LPVOID ) ) )
{
DPF_ERR ( "DDVPC_GetVideoPortConnectInfo: numentries not valid");
LEAVE_DDRAW();
return DDERR_INVALIDPARAMS;
}
if( NULL != lpConnect )
{
if( 0 == *lpdwNumEntries )
{
DPF_ERR ( "DDVPC_GetVideoPortConnectInfo: numentries not valid");
LEAVE_DDRAW();
return DDERR_INVALIDPARAMS;
}
if( !VALID_BYTE_ARRAY( lpConnect, *lpdwNumEntries * sizeof( DDVIDEOPORTCONNECT ) ) )
{
DPF_ERR ( "DDVPC_GetVideoPortConnectInfo: invalid array passed in");
LEAVE_DDRAW();
return DDERR_INVALIDPARAMS;
}
}
}
EXCEPT( EXCEPTION_EXECUTE_HANDLER )
{
DPF_ERR( "Exception encountered validating parameters" );
LEAVE_DDRAW();
return DDERR_EXCEPTION;
}
pfn = this_int->lpLcl->lpDDCB->HALDDVideoPort.GetVideoPortConnectInfo;
if( pfn != NULL )
{
/*
* Get the number of GUIDs
*/
GetGuidData.lpDD = this_int->lpLcl;
GetGuidData.dwPortId = dwVideoPortID;
GetGuidData.lpConnect = NULL;
DOHALCALL( GetVideoPortConnectInfo, pfn, GetGuidData, rc, 0 );
if( DDHAL_DRIVER_HANDLED != rc )
{
LEAVE_DDRAW();
return GetGuidData.ddRVal;
}
else if( DD_OK != GetGuidData.ddRVal )
{
LEAVE_DDRAW();
return GetGuidData.ddRVal;
}
if( NULL == lpConnect )
{
*lpdwNumEntries = GetGuidData.dwNumEntries;
}
else
{
/*
* Make sure we have enough room for GUIDs
*/
if( GetGuidData.dwNumEntries > *lpdwNumEntries )
{
lpTemp = (LPDDVIDEOPORTCONNECT) MemAlloc(
sizeof( DDVIDEOPORTCONNECT ) * GetGuidData.dwNumEntries );
GetGuidData.lpConnect = lpTemp;
}
else
{
GetGuidData.lpConnect = lpConnect;
}
DOHALCALL( GetVideoPortConnectInfo, pfn, GetGuidData, rc, 0 );
if( DDHAL_DRIVER_HANDLED != rc )
{
LEAVE_DDRAW();
return DDERR_UNSUPPORTED;
}
else if( DD_OK != GetGuidData.ddRVal )
{
LEAVE_DDRAW();
return GetGuidData.ddRVal;
}
/*
* Make sure the reserved fields are set to 0
*/
for( i = 0; i < *lpdwNumEntries; i++ )
{
GetGuidData.lpConnect[i].dwReserved1 = 0;
}
if( GetGuidData.lpConnect != lpConnect )
{
memcpy( lpConnect, lpTemp,
sizeof( DDVIDEOPORTCONNECT ) * *lpdwNumEntries );
MemFree( lpTemp );
LEAVE_DDRAW();
return DDERR_MOREDATA;
}
else
{
*lpdwNumEntries = GetGuidData.dwNumEntries;
}
}
}
else
{
LEAVE_DDRAW();
return DDERR_UNSUPPORTED;
}
LEAVE_DDRAW();
return DD_OK;
} /* DDVPC_GetVideoPortConnectInfo */
/*
* DDVPC_QueryVideoPortStatus
*/
HRESULT DDAPI DDVPC_QueryVideoPortStatus(
LPDDVIDEOPORTCONTAINER lpDVP,
DWORD dwVideoPortID,
LPDDVIDEOPORTSTATUS lpStatus )
{
LPDDRAWI_DIRECTDRAW_INT this_int;
LPDDRAWI_DIRECTDRAW_LCL this_lcl;
LPDDRAWI_DIRECTDRAW_GBL this;
LPDDRAWI_DDVIDEOPORT_INT lpVP_int;
ENTER_DDRAW();
DPF(2,A,"ENTERAPI: DDVPC_QueryVideoPortStatus");
/*
* Don't allow access to this function if called from within the
* the EnumVideoPort callback.
*/
if( bInEnumCallback )
{
DPF_ERR ( "This function cannot be called from within the EnumVideoPort callback!");
LEAVE_DDRAW();
return DDERR_CURRENTLYNOTAVAIL;
}
/*
* Validate parameters
*/
TRY
{
this_int = (LPDDRAWI_DIRECTDRAW_INT) lpDVP;
if( !VALID_DIRECTDRAW_PTR( this_int ) )
{
LEAVE_DDRAW();
return DDERR_INVALIDOBJECT;
}
this_lcl = this_int->lpLcl;
this = this_lcl->lpGbl;
if( ( lpStatus == NULL ) || !VALID_DDVIDEOPORTSTATUS_PTR( lpStatus ) )
{
DPF_ERR ( "DDVPC_QueryVideoPortStatus: Invalid DDVIDEOPORTSTATUS ptr");
LEAVE_DDRAW();
return DDERR_INVALIDOBJECT;
}
memset( lpStatus, 0, sizeof( DDVIDEOPORTSTATUS ) );
lpStatus->dwSize = sizeof( DDVIDEOPORTSTATUS );
if( dwVideoPortID >= this->ddCaps.dwMaxVideoPorts )
{
DPF_ERR ( "DDVPC_QueryVideoPortStatus: Invalid Video Port ID specified");
LEAVE_DDRAW();
return DDERR_INVALIDPARAMS;
}
}
EXCEPT( EXCEPTION_EXECUTE_HANDLER )
{
DPF_ERR( "Exception encountered validating parameters" );
LEAVE_DDRAW();
return DDERR_EXCEPTION;
}
/*
* Search the list of video ports to see if anybody's using this one
*/
lpVP_int = this->dvpList;
while( lpVP_int != NULL )
{
if( ( lpVP_int->lpLcl->ddvpDesc.dwVideoPortID == dwVideoPortID ) &&
!( lpVP_int->dwFlags & DDVPCREATE_NOTIFY ) )
{
/*
* One does exist - return info about it
*/
lpStatus->bInUse = TRUE;
memcpy( &(lpStatus->VideoPortType),
&(lpVP_int->lpLcl->ddvpDesc.VideoPortType),
sizeof( DDVIDEOPORTCONNECT ) );
lpStatus->dwFlags |= lpVP_int->dwFlags;
}
lpVP_int = lpVP_int->lpLink;
}
if( ( lpStatus->dwFlags & DDVPCREATE_VBIONLY ) &&
( lpStatus->dwFlags & DDVPCREATE_VIDEOONLY ) )
{
lpStatus->dwFlags = 0;
}
LEAVE_DDRAW();
return DD_OK;
} /* DDVPC_QueryVideoPortStatus */
/*
* InsertVideoPortInList
*/
VOID InsertVideoPortInList( LPDDRAWI_DIRECTDRAW_GBL lpGbl, LPDDRAWI_DDVIDEOPORT_INT lpNew )
{
if( NULL == lpGbl->dvpList )
{
lpGbl->dvpList = lpNew;
}
else
{
LPDDRAWI_DDVIDEOPORT_INT lpTemp;
lpTemp = lpGbl->dvpList;
while( NULL != lpTemp->lpLink )
{
lpTemp = lpTemp->lpLink;
}
lpTemp->lpLink = lpNew;
}
}
/*
* IncrementRefCounts
*
* Used to increment the reference count of all surfaces that could
* receive data from the video port, insuring that a surface isn't released
* while we are using it.
*/
VOID IncrementRefCounts( LPDDRAWI_DDRAWSURFACE_INT surf_int )
{
LPDDRAWI_DDRAWSURFACE_INT surf_first;
surf_first = surf_int;
do
{
DD_Surface_AddRef( (LPDIRECTDRAWSURFACE) surf_int );
surf_int = FindAttachedFlip( surf_int );
} while( ( surf_int != NULL ) && ( surf_int->lpLcl != surf_first->lpLcl ) );
}
/*
* DecrementRefCounts
*
* Used to decrement the reference count of all surfaces that were previously
* AddRefed because they were using the video port.
*/
VOID DecrementRefCounts( LPDDRAWI_DDRAWSURFACE_INT surf_int )
{
LPDDRAWI_DDRAWSURFACE_INT *lpSurfList;
LPDDRAWI_DDRAWSURFACE_INT surf_first;
DWORD dwCnt;
DWORD i;
/*
* We cannot simply walk the chain, releasing each surface as we go
* because if the ref cnt goes to zero, the chain goes away and we
* cannot get to the next surface becasue the current interface is
* unusable. For this reason, we cnt how many explicit surfaces are
* in the chain, allocate a buffer to store all of them, and then
* release them without walking the chain.
*
* We do not release the implicitly created surfaces since 1) DirectDraw
* ignores this anyway and 2) they are immediately released when
* releasing their explicit surface, so touching them can be dangerous.
*/
dwCnt = 0;
surf_first = surf_int;
do
{
if( !( surf_int->lpLcl->dwFlags & DDRAWISURF_IMPLICITCREATE ) )
{
dwCnt++;
}
surf_int = FindAttachedFlip( surf_int );
} while( ( surf_int != NULL ) && ( surf_int->lpLcl != surf_first->lpLcl ) );
lpSurfList = (LPDDRAWI_DDRAWSURFACE_INT *) MemAlloc( dwCnt *
sizeof( surf_first ) );
if( lpSurfList == NULL )
{
return;
}
/*
* Now put the surfaces in the list
*/
i = 0;
surf_int = surf_first;
do
{
if( !( surf_int->lpLcl->dwFlags & DDRAWISURF_IMPLICITCREATE ) )
{
lpSurfList[i++] = surf_int;
}
surf_int = FindAttachedFlip( surf_int );
} while( ( surf_int != NULL ) && ( surf_int->lpLcl != surf_first->lpLcl ) );
/*
* Now release them
*/
for( i = 0; i < dwCnt; i++ )
{
DD_Surface_Release( (LPDIRECTDRAWSURFACE) lpSurfList[i] );
}
MemFree( lpSurfList );
}
/*
* MergeVPDescriptions
*
* This function takes two DDVIDEOPORTDESC structures (one for VBI and one
* for video) and merges them into a single structure. If only one is
* passed, it does a memcpy.
*/
VOID MergeVPDescriptions( LPDDVIDEOPORTDESC lpOutDesc,
LPDDVIDEOPORTDESC lpInDesc, LPDDRAWI_DDVIDEOPORT_INT lpOtherInt )
{
memcpy( lpOutDesc, lpInDesc, sizeof( DDVIDEOPORTDESC ) );
if( lpOtherInt != NULL )
{
if( lpOtherInt->dwFlags & DDVPCREATE_VIDEOONLY )
{
lpOutDesc->dwFieldWidth = lpOtherInt->lpLcl->ddvpDesc.dwFieldWidth;
}
else
{
lpOutDesc->dwVBIWidth = lpOtherInt->lpLcl->ddvpDesc.dwVBIWidth;
}
if( lpOtherInt->lpLcl->ddvpDesc.dwFieldHeight > lpOutDesc->dwFieldHeight )
{
lpOutDesc->dwFieldHeight = lpOtherInt->lpLcl->ddvpDesc.dwFieldHeight;
}
if( lpOtherInt->lpLcl->ddvpDesc.dwMicrosecondsPerField >
lpOutDesc->dwMicrosecondsPerField )
{
lpOutDesc->dwMicrosecondsPerField =
lpOtherInt->lpLcl->ddvpDesc.dwMicrosecondsPerField;
}
if( lpOtherInt->lpLcl->ddvpDesc.dwMaxPixelsPerSecond >
lpOutDesc->dwMaxPixelsPerSecond )
{
lpOutDesc->dwMaxPixelsPerSecond =
lpOtherInt->lpLcl->ddvpDesc.dwMaxPixelsPerSecond;
}
}
}
/*
* MergeVPInfo
*
* This function takes two DDVIDEOPORTINFO structures (one for VBI and one
* for video) and merges them into a single structure.
*/
HRESULT MergeVPInfo( LPDDRAWI_DDVIDEOPORT_LCL lpVP, LPDDVIDEOPORTINFO lpVBIInfo,
LPDDVIDEOPORTINFO lpVideoInfo, LPDDVIDEOPORTINFO lpOutInfo )
{
/*
* First, handle the case where only one interface is on. Also, we
* require that the following be true for VBI/Video-only video ports:
* 1) They both must set the dwVBIHeight.
* 2) Neither one can crop the area immediately adjacent to the other.
*/
if( lpVBIInfo == NULL )
{
if( lpVideoInfo->dwVBIHeight == 0 )
{
DPF_ERR( "Video-only video port failed to set dwVBIHeight" );
return DDERR_INVALIDPARAMS;
}
memcpy( lpOutInfo, lpVideoInfo, sizeof( DDVIDEOPORTINFO ) );
if( lpVideoInfo->dwVPFlags & DDVP_CROP )
{
if( lpVideoInfo->rCrop.top > (int) lpVideoInfo->dwVBIHeight )
{
DPF_ERR( "rCrop.top > dwVBIHeight on video-only video port" );
return DDERR_INVALIDPARAMS;
}
lpOutInfo->rCrop.top = lpVideoInfo->dwVBIHeight;
}
else
{
lpOutInfo->dwVPFlags |= DDVP_CROP;
lpOutInfo->rCrop.top = lpVideoInfo->dwVBIHeight;
lpOutInfo->rCrop.left = 0;
lpOutInfo->rCrop.right = lpVP->lpVideoDesc->dwFieldWidth;
lpOutInfo->rCrop.bottom = lpVP->lpVideoDesc->dwFieldHeight;
}
}
else if( lpVideoInfo == NULL )
{
if( lpVBIInfo->dwVBIHeight == 0 )
{
DPF_ERR( "VBI-only video port failed to set dwVBIHeight" );
return DDERR_INVALIDPARAMS;
}
memcpy( lpOutInfo, lpVBIInfo, sizeof( DDVIDEOPORTINFO ) );
if( lpVBIInfo->dwVPFlags & DDVP_CROP )
{
if( lpVBIInfo->rCrop.bottom < (int) lpVBIInfo->dwVBIHeight )
{
DPF_ERR( "rCrop.bottom < dwVBIHeight on VBI-only video port" );
return DDERR_INVALIDPARAMS;
}
lpOutInfo->rCrop.bottom = lpVBIInfo->dwVBIHeight;
}
else
{
lpOutInfo->dwVPFlags |= DDVP_CROP;
lpOutInfo->rCrop.top = 0;
lpOutInfo->rCrop.bottom = lpVBIInfo->dwVBIHeight;
lpOutInfo->rCrop.left = 0;
lpOutInfo->rCrop.right = lpVP->lpVBIDesc->dwVBIWidth;
}
}
/*
* Now handle the case where both are on and we have to truly merge them.
*/
else
{
memset( lpOutInfo, 0, sizeof( DDVIDEOPORTINFO ) );
lpOutInfo->dwSize = sizeof( DDVIDEOPORTINFO );
lpOutInfo->dwOriginX = lpVideoInfo->dwOriginX;
lpOutInfo->dwOriginY = lpVideoInfo->dwOriginY;
lpOutInfo->dwVPFlags = lpVideoInfo->dwVPFlags | lpVBIInfo->dwVPFlags;
lpOutInfo->dwVBIHeight = lpVBIInfo->dwVBIHeight;
/*
* Fix up the cropping.
*/
if( lpOutInfo->dwVPFlags & DDVP_CROP )
{
if( ( lpVBIInfo->dwVPFlags & DDVP_CROP ) &&
( lpVBIInfo->rCrop.bottom < (int) lpVBIInfo->dwVBIHeight ) )
{
DPF_ERR( "rCrop.bottom < dwVBIHeight on VBI-only video port" );
return DDERR_INVALIDPARAMS;
}
if( ( lpVideoInfo->dwVPFlags & DDVP_CROP ) &&
( lpVideoInfo->rCrop.top > (int) lpVideoInfo->dwVBIHeight ) )
{
DPF_ERR( "rCrop.top > dwVBIHeight on video-only video port" );
return DDERR_INVALIDPARAMS;
}
lpOutInfo->dwVPFlags |= DDVP_IGNOREVBIXCROP;
if( lpVBIInfo->dwVPFlags & DDVP_CROP )
{
lpOutInfo->rCrop.top = lpVBIInfo->rCrop.top;
}
else
{
lpOutInfo->rCrop.top = 0;
}
if( lpVideoInfo->dwVPFlags & DDVP_CROP )
{
lpOutInfo->rCrop.bottom = lpVideoInfo->rCrop.bottom;
lpOutInfo->rCrop.left = lpVideoInfo->rCrop.left;
lpOutInfo->rCrop.right = lpVideoInfo->rCrop.right;
}
else
{
lpOutInfo->rCrop.bottom = lpVP->lpVideoDesc->dwFieldHeight;
lpOutInfo->rCrop.left = 0;
lpOutInfo->rCrop.right = lpVP->lpVideoDesc->dwFieldWidth;
}
}
else if( lpVP->ddvpDesc.dwFieldHeight > lpVP->lpVideoDesc->dwFieldHeight )
{
lpOutInfo->dwVPFlags |= DDVP_CROP;
lpOutInfo->rCrop.top = 0;
lpOutInfo->rCrop.bottom = lpVP->lpVideoDesc->dwFieldHeight;
lpOutInfo->rCrop.left = 0;
lpOutInfo->rCrop.right = lpVP->lpVideoDesc->dwFieldWidth;
}
/*
* Handle pre-scaling. Assume that VBI video ports are not allowed
* to prescale.
*/
if( lpVBIInfo->dwVPFlags & DDVP_PRESCALE )
{
DPF_ERR( "VBI-only video port set DDVP_PRESCALE" );
return DDERR_INVALIDPARAMS;
}
else if( lpVideoInfo->dwVPFlags & DDVP_PRESCALE )
{
lpOutInfo->dwPrescaleWidth = lpVideoInfo->dwPrescaleWidth;
lpOutInfo->dwPrescaleHeight = lpVideoInfo->dwPrescaleHeight;
}
lpOutInfo->lpddpfInputFormat = lpVideoInfo->lpddpfInputFormat;
lpOutInfo->lpddpfVBIInputFormat = lpVBIInfo->lpddpfVBIInputFormat;
lpOutInfo->lpddpfVBIOutputFormat = lpVBIInfo->lpddpfVBIOutputFormat;
}
return DD_OK;
}
/*
* DDVPC_CreateVideoPort
*/
HRESULT DDAPI DDVPC_CreateVideoPort(
LPDDVIDEOPORTCONTAINER lpDVP,
DWORD dwClientFlags,
LPDDVIDEOPORTDESC lpDesc,
LPDIRECTDRAWVIDEOPORT FAR *lplpDDVideoPort,
IUnknown FAR *pUnkOuter )
{
DDVIDEOPORTDESC ddTempDesc;
LPDDRAWI_DIRECTDRAW_INT this_int;
LPDDRAWI_DIRECTDRAW_LCL this_lcl;
LPDDRAWI_DIRECTDRAW_GBL this;
LPDDRAWI_DDVIDEOPORT_INT lpVPInt;
LPDDRAWI_DDVIDEOPORT_INT lpEven;
LPDDRAWI_DDVIDEOPORT_INT lpOdd;
LPDDRAWI_DDVIDEOPORT_INT lpOtherInt = NULL;
LPDDVIDEOPORTCAPS lpAvailCaps;
LPDDHALVPORTCB_CANCREATEVIDEOPORT ccvppfn;
LPDDHALVPORTCB_CREATEVIDEOPORT cvppfn;
LPDDRAWI_DDVIDEOPORT_INT new_int;
LPDDRAWI_DDVIDEOPORT_LCL new_lcl;
DWORD dwAvailCaps;
DWORD dwConnectFlags;
DWORD rc;
if( pUnkOuter != NULL )
{
return CLASS_E_NOAGGREGATION;
}
ENTER_DDRAW();
DPF(2,A,"ENTERAPI: DDVPC_CreateVideoPort");
/*
* Don't allow access to this function if called from within the
* the EnumVideoPort callback.
*/
if( bInEnumCallback )
{
DPF_ERR ( "This function cannot be called from within the EnumVideoPort callback!");
LEAVE_DDRAW();
return DDERR_CURRENTLYNOTAVAIL;
}
/*
* Validate parameters
*/
TRY
{
this_int = (LPDDRAWI_DIRECTDRAW_INT) lpDVP;
if( !VALID_DIRECTDRAW_PTR( this_int ) )
{
LEAVE_DDRAW();
return DDERR_INVALIDOBJECT;
}
this_lcl = this_int->lpLcl;
this = this_lcl->lpGbl;
#ifdef WINNT
// Update DDraw handle in driver GBL object.
this->hDD = this_lcl->hDD;
#endif
if( dwClientFlags & ~( DDVPCREATE_VBIONLY|DDVPCREATE_VIDEOONLY) )
{
DPF_ERR( "Invalid flags specified" );
LEAVE_DDRAW();
return DDERR_INVALIDPARAMS;
}
if( dwClientFlags == ( DDVPCREATE_VBIONLY | DDVPCREATE_VIDEOONLY ) )
{
/*
* SPecifying boht flags is the same as specifying neither
*/
dwClientFlags = 0;
}
if( ( NULL == lpDesc ) || !VALID_DDVIDEOPORTDESC_PTR( lpDesc ) )
{
LEAVE_DDRAW();
return DDERR_INVALIDPARAMS;
}
if( ( NULL == lplpDDVideoPort ) || !VALID_PTR_PTR( lplpDDVideoPort ) )
{
LEAVE_DDRAW();
return DDERR_INVALIDPARAMS;
}
if( NULL == this->lpDDVideoPortCaps )
{
LEAVE_DDRAW();
return DDERR_UNSUPPORTED;
}
if( lpDesc->dwVideoPortID >= this->ddCaps.dwMaxVideoPorts )
{
LEAVE_DDRAW();
return DDERR_INVALIDPARAMS;
}
if( ( lpDesc->VideoPortType.dwReserved1 != 0 ) ||
( lpDesc->dwReserved1 != 0 ) ||
( lpDesc->dwReserved2 != 0 ) ||
( lpDesc->dwReserved3 != 0 ) )
{
DPF_ERR( "Reserved field not set to zero" );
LEAVE_DDRAW();
return DDERR_INVALIDPARAMS;
}
lpAvailCaps = &(this->lpDDVideoPortCaps[lpDesc->dwVideoPortID]);
if( !VALID_DDVIDEOPORTCAPS_PTR( lpAvailCaps ) )
{
LEAVE_DDRAW();
return DDERR_UNSUPPORTED;
}
if( ( dwClientFlags & DDVPCREATE_VBIONLY ) &&
!IndependantVBIPossible( lpAvailCaps ) )
{
DPF_ERR( "DDVPCREATE_VBIONLY is not supported" );
LEAVE_DDRAW();
return DDERR_UNSUPPORTED;
}
}
EXCEPT( EXCEPTION_EXECUTE_HANDLER )
{
DPF_ERR( "Exception encountered validating parameters" );
LEAVE_DDRAW();
return DDERR_EXCEPTION;
}
if( this_lcl->dwProcessId != GetCurrentProcessId() )
{
DPF_ERR( "Process does not have access to object" );
LEAVE_DDRAW();
return DDERR_INVALIDPARAMS;
}
/*
* Is the requested video port available?
*/
lpVPInt = this->dvpList;
lpEven = lpOdd = NULL;
while( NULL != lpVPInt )
{
if( ( lpVPInt->lpLcl->ddvpDesc.dwVideoPortID == lpDesc->dwVideoPortID ) &&
!( lpVPInt->dwFlags & DDVPCREATE_NOTIFY ) )
{
if( lpVPInt->lpLcl->ddvpDesc.VideoPortType.dwFlags &
DDVPCONNECT_SHAREEVEN )
{
lpEven = lpVPInt;
}
else if( lpVPInt->lpLcl->ddvpDesc.VideoPortType.dwFlags &
DDVPCONNECT_SHAREODD )
{
lpOdd = lpVPInt;
}
else if( !dwClientFlags || !(lpVPInt->dwFlags) ||
( dwClientFlags & lpVPInt->dwFlags ) )
{
lpEven = lpOdd = lpVPInt;
}
else
{
/*
* Video has been opened for VBI/Video only use. Remember
* the other interface because we will need it shortly.
*/
lpOtherInt = lpVPInt;
}
}
lpVPInt = lpVPInt->lpLink;
}
if( ( NULL != lpEven ) && ( NULL != lpOdd ) )
{
DPF_ERR( "video port already in use" );
LEAVE_DDRAW();
return DDERR_OUTOFCAPS;
}
/*
* Get the caps of the specified video port
*/
dwAvailCaps = lpAvailCaps->dwCaps;
dwConnectFlags = lpDesc->VideoPortType.dwFlags;
if( NULL != lpEven )
{
dwAvailCaps &= ~( DDVPCAPS_NONINTERLACED |
DDVPCAPS_SKIPEVENFIELDS | DDVPCAPS_SKIPODDFIELDS );
if( dwConnectFlags & DDVPCONNECT_SHAREEVEN )
{
DPF_ERR( "Even field already used" );
LEAVE_DDRAW();
return DDERR_INVALIDCAPS;
}
}
else if( NULL != lpOdd )
{
dwAvailCaps &= ~( DDVPCAPS_NONINTERLACED |
DDVPCAPS_SKIPEVENFIELDS | DDVPCAPS_SKIPODDFIELDS );
if( dwConnectFlags & DDVPCONNECT_SHAREODD )
{
DPF_ERR( "Odd field already used" );
LEAVE_DDRAW();
return DDERR_INVALIDCAPS;
}
}
else if( dwClientFlags )
{
dwAvailCaps &= ~( DDVPCAPS_SKIPEVENFIELDS | DDVPCAPS_SKIPODDFIELDS );
}
/*
* Check for incompatible flags/caps
*/
if( ( dwConnectFlags & DDVPCONNECT_INTERLACED ) &&
!( dwAvailCaps & DDVPCAPS_INTERLACED ) )
{
DPF_ERR( "DDVPCONNECT_INTERLACED not supported" );
LEAVE_DDRAW();
return DDERR_INVALIDCAPS;
}
if( !( dwConnectFlags & DDVPCONNECT_INTERLACED ) &&
!( dwAvailCaps & DDVPCAPS_NONINTERLACED ) )
{
DPF_ERR( "Non interlaced is not supported" );
LEAVE_DDRAW();
return DDERR_INVALIDCAPS;
}
if( ( dwConnectFlags &
(DDVPCONNECT_SHAREEVEN|DDVPCONNECT_SHAREODD) ) &&
!( dwAvailCaps & DDVPCAPS_SHAREABLE ) )
{
DPF_ERR( "DDVPCONNECT_SHAREEVEN/SHAREODD not supported" );
LEAVE_DDRAW();
return DDERR_INVALIDCAPS;
}
if( !( dwConnectFlags & DDVPCONNECT_INTERLACED ) )
{
if( dwConnectFlags & ( DDVPCONNECT_SHAREEVEN |
DDVPCONNECT_SHAREODD ) )
{
DPF_ERR( "cap invalid with non-interlaced video" );
LEAVE_DDRAW();
return DDERR_INVALIDCAPS;
}
}
if( ( dwConnectFlags & DDVPCONNECT_SHAREEVEN ) &&
( dwConnectFlags & DDVPCONNECT_SHAREODD ) )
{
DPF_ERR( "shareeven and share odd are mutually exclusive" );
LEAVE_DDRAW();
return DDERR_INVALIDCAPS;
}
if( ( ( NULL != lpEven ) && !( dwConnectFlags & DDVPCONNECT_SHAREODD ) ) ||
( ( NULL != lpOdd ) && !( dwConnectFlags & DDVPCONNECT_SHAREEVEN ) ) )
{
DPF_ERR( "specifed video port must be shared" );
LEAVE_DDRAW();
return DDERR_INVALIDCAPS;
}
if( lpAvailCaps->dwMaxWidth < lpDesc->dwFieldWidth )
{
DPF_ERR( "specified width is too large" );
LEAVE_DDRAW();
return DDERR_INVALIDPARAMS;
}
if( lpAvailCaps->dwMaxHeight < lpDesc->dwFieldHeight )
{
DPF_ERR( "specified height is too large" );
LEAVE_DDRAW();
return DDERR_INVALIDPARAMS;
}
if( lpDesc->dwMicrosecondsPerField == 0 )
{
DPF_ERR( "Microseconds/field not specified" );
LEAVE_DDRAW();
return DDERR_INVALIDPARAMS;
}
if( lpDesc->dwMaxPixelsPerSecond == 0 )
{
DPF_ERR( "Max pixels per second not specified" );
LEAVE_DDRAW();
return DDERR_INVALIDPARAMS;
}
if( NULL != lpEven )
{
if( !( ( IsEqualIID( &(lpDesc->VideoPortType.guidTypeID),
&(lpOdd->lpLcl->ddvpDesc.VideoPortType.guidTypeID) ) ) &&
( lpDesc->VideoPortType.dwPortWidth ==
lpOdd->lpLcl->ddvpDesc.VideoPortType.dwPortWidth ) &&
( ( lpDesc->VideoPortType.dwFlags & lpOdd->lpLcl->ddvpDesc.VideoPortType.dwFlags )
== lpDesc->VideoPortType.dwFlags ) ) )
{
DPF_ERR( "invalid GUID specified" );
LEAVE_DDRAW();
return DDERR_INVALIDPARAMS;
}
}
else if( NULL != lpOdd )
{
if( !( ( IsEqualIID( &(lpDesc->VideoPortType.guidTypeID),
&(lpEven->lpLcl->ddvpDesc.VideoPortType.guidTypeID) ) ) &&
( lpDesc->VideoPortType.dwPortWidth ==
lpEven->lpLcl->ddvpDesc.VideoPortType.dwPortWidth ) &&
( ( lpDesc->VideoPortType.dwFlags & lpEven->lpLcl->ddvpDesc.VideoPortType.dwFlags )
== lpDesc->VideoPortType.dwFlags ) ) )
{
DPF_ERR( "invalid GUID specified" );
LEAVE_DDRAW();
return DDERR_INVALIDPARAMS;
}
}
else if( NULL != lpOtherInt )
{
/*
* Since they are both sharing the exact same connection, fail
* unless the connections are identical.
*/
if( lpDesc->VideoPortType.dwPortWidth !=
lpOtherInt->lpLcl->ddvpDesc.VideoPortType.dwPortWidth )
{
DPF_ERR( "connection info must match other interface" );
LEAVE_DDRAW();
return DDERR_INVALIDPARAMS;
}
if( lpDesc->VideoPortType.dwFlags !=
lpOtherInt->lpLcl->ddvpDesc.VideoPortType.dwFlags )
{
DPF_ERR( "connection info must match other interface" );
LEAVE_DDRAW();
return DDERR_INVALIDPARAMS;
}
if( !IsEqualIID( &(lpDesc->VideoPortType.guidTypeID),
&(lpOtherInt->lpLcl->ddvpDesc.VideoPortType.guidTypeID) ) )
{
DPF_ERR( "connection info must match other interface" );
LEAVE_DDRAW();
return DDERR_INVALIDPARAMS;
}
}
else
{
LPDDVIDEOPORTCONNECT lpConnect;
DWORD dwNumEntries;
DWORD i;
DWORD rc;
/*
* Verify that the connection can be supported.
*/
rc = DDVPC_GetVideoPortConnectInfo( lpDVP,
lpDesc->dwVideoPortID, &dwNumEntries, NULL );
if( rc != DD_OK )
{
LEAVE_DDRAW();
return DDERR_INVALIDPARAMS;
}
lpConnect = (LPDDVIDEOPORTCONNECT) MemAlloc(
sizeof( DDVIDEOPORTCONNECT ) * dwNumEntries );
if( NULL == lpConnect )
{
LEAVE_DDRAW();
return DDERR_OUTOFMEMORY;
}
rc = DDVPC_GetVideoPortConnectInfo( lpDVP,
lpDesc->dwVideoPortID, &dwNumEntries, lpConnect );
if( rc != DD_OK )
{
LEAVE_DDRAW();
return DDERR_INVALIDPARAMS;
}
for (i = 0; i < dwNumEntries; i++)
{
if( ( IsEqualIID( &(lpDesc->VideoPortType.guidTypeID),
&(lpConnect[i].guidTypeID) ) ) &&
( lpDesc->VideoPortType.dwPortWidth ==
lpConnect[i].dwPortWidth ) )
{
break;
}
}
MemFree( lpConnect );
if ( i == dwNumEntries )
{
DPF_ERR( "invalid GUID specified" );
LEAVE_DDRAW();
return DDERR_INVALIDPARAMS;
}
}
/*
* Turn merge the description of the multiple interfaces into one.
*/
MergeVPDescriptions( &ddTempDesc, lpDesc, lpOtherInt );
/*
* Things look good so far. Lets call the HAL and see if they
* can handle it.
*/
ccvppfn = this_lcl->lpDDCB->HALDDVideoPort.CanCreateVideoPort;
if( NULL != ccvppfn )
{
DDHAL_CANCREATEVPORTDATA CanCreateData;
CanCreateData.lpDD = this_lcl;
CanCreateData.lpDDVideoPortDesc = &ddTempDesc;
DOHALCALL( CanCreateVideoPort, ccvppfn, CanCreateData, rc, 0 );
if( ( DDHAL_DRIVER_HANDLED == rc ) && (DD_OK != CanCreateData.ddRVal ) )
{
LEAVE_DDRAW();
return CanCreateData.ddRVal;
}
}
/*
* Allocate the sucker(s)
*/
new_int = MemAlloc( sizeof( DDRAWI_DDVIDEOPORT_INT ) );
if( NULL == new_int )
{
LEAVE_DDRAW();
return DDERR_OUTOFMEMORY;
}
new_int->lpVtbl = (LPVOID)&ddVideoPortCallbacks;
new_int->dwFlags = dwClientFlags;
if( lpOtherInt != NULL )
{
new_lcl = lpOtherInt->lpLcl;
}
else
{
new_lcl = MemAlloc( sizeof( DDRAWI_DDVIDEOPORT_LCL ) +
( 2 * sizeof( DDPIXELFORMAT ) ) );
if( NULL == new_lcl )
{
LEAVE_DDRAW();
return DDERR_OUTOFMEMORY;
}
new_lcl->lpDD = this_lcl;
new_lcl->lpSurface = NULL;
new_lcl->lpVBISurface = NULL;
}
if( dwClientFlags & DDVPCREATE_VBIONLY )
{
new_lcl->dwVBIProcessID = GetCurrentProcessId();
}
else
{
new_lcl->dwProcessID = GetCurrentProcessId();
}
new_int->lpLcl = new_lcl;
memcpy( &(new_lcl->ddvpDesc), &ddTempDesc, sizeof( DDVIDEOPORTDESC ));
/*
* If this is a VBI/VIDEOONLY interface, save the original description
* for future use.
*/
if( dwClientFlags & DDVPCREATE_VBIONLY )
{
new_lcl->lpVBIDesc = MemAlloc( sizeof( DDVIDEOPORTDESC ) );
if( NULL == new_lcl->lpVBIDesc )
{
LEAVE_DDRAW();
return DDERR_OUTOFMEMORY;
}
memcpy( new_lcl->lpVBIDesc, lpDesc, sizeof( DDVIDEOPORTDESC ));
}
else if( dwClientFlags & DDVPCREATE_VIDEOONLY )
{
new_lcl->lpVideoDesc = MemAlloc( sizeof( DDVIDEOPORTDESC ) );
if( NULL == new_lcl->lpVideoDesc )
{
LEAVE_DDRAW();
return DDERR_OUTOFMEMORY;
}
memcpy( new_lcl->lpVideoDesc, lpDesc, sizeof( DDVIDEOPORTDESC ));
}
/*
* Notify the HAL that we created it
*/
cvppfn = this_lcl->lpDDCB->HALDDVideoPort.CreateVideoPort;
if( NULL != cvppfn )
{
DDHAL_CREATEVPORTDATA CreateData;
CreateData.lpDD = this_lcl;
CreateData.lpDDVideoPortDesc = &ddTempDesc;
CreateData.lpVideoPort = new_lcl;
DOHALCALL( CreateVideoPort, cvppfn, CreateData, rc, 0 );
if( ( DDHAL_DRIVER_HANDLED == rc ) && (DD_OK != CreateData.ddRVal ) )
{
LEAVE_DDRAW();
return CreateData.ddRVal;
}
}
InsertVideoPortInList( this, new_int );
DD_VP_AddRef( (LPDIRECTDRAWVIDEOPORT )new_int );
*lplpDDVideoPort = (LPDIRECTDRAWVIDEOPORT) new_int;
/*
* Notify kernel mode of we created the video port
*/
#ifdef WIN95
if( lpOtherInt == NULL )
{
UpdateKernelVideoPort( new_lcl, DDKMVP_CREATE );
}
#endif
LEAVE_DDRAW();
return DD_OK;
} /* DDVPC_CreateVideoPort */
/*
* DD_VP_AddRef
*/
DWORD DDAPI DD_VP_AddRef( LPDIRECTDRAWVIDEOPORT lpDVP )
{
LPDDRAWI_DDVIDEOPORT_INT this_int;
LPDDRAWI_DDVIDEOPORT_LCL this_lcl;
ENTER_DDRAW();
DPF(2,A,"ENTERAPI: DD_VP_AddRef");
/*
* Don't allow access to this function if called from within the
* the EnumVideoPort callback.
*/
if( bInEnumCallback )
{
DPF_ERR ( "This function cannot be called from within the EnumVideoPort callback!");
LEAVE_DDRAW();
return 0;
}
DPF( 5, "DD_VP_AddRef, pid=%08lx, obj=%08lx", GETCURRPID(), lpDVP );
TRY
{
this_int = (LPDDRAWI_DDVIDEOPORT_INT) lpDVP;
if( !VALID_DDVIDEOPORT_PTR( this_int ) )
{
LEAVE_DDRAW();
return 0;
}
this_lcl = this_int->lpLcl;
}
EXCEPT( EXCEPTION_EXECUTE_HANDLER )
{
DPF_ERR( "Exception encountered validating parameters" );
LEAVE_DDRAW();
return 0;
}
/*
* bump refcnt
*/
this_lcl->dwRefCnt++;
this_int->dwIntRefCnt++;
LEAVE_DDRAW();
return this_int->dwIntRefCnt;
} /* DD_VP_AddRef */
/*
* DD_VP_QueryInterface
*/
HRESULT DDAPI DD_VP_QueryInterface(LPDIRECTDRAWVIDEOPORT lpDVP, REFIID riid, LPVOID FAR * ppvObj )
{
LPDDRAWI_DDVIDEOPORT_INT this_int;
LPDDRAWI_DDVIDEOPORT_LCL this_lcl;
ENTER_DDRAW();
DPF(2,A,"ENTERAPI: DD_VP_QueryInterface");
/*
* Don't allow access to this function if called from within the
* the EnumVideoPort callback.
*/
if( bInEnumCallback )
{
DPF_ERR ( "This function cannot be called from within the EnumVideoPort callback!");
LEAVE_DDRAW();
return DDERR_CURRENTLYNOTAVAIL;
}
/*
* validate parms
*/
TRY
{
this_int = (LPDDRAWI_DDVIDEOPORT_INT) lpDVP;
if( !VALID_DDVIDEOPORT_PTR( this_int ) )
{
DPF_ERR( "Invalid videoport pointer" );
LEAVE_DDRAW();
return DDERR_INVALIDOBJECT;
}
this_lcl = this_int->lpLcl;
if( !VALID_PTR_PTR( ppvObj ) )
{
DPF_ERR( "Invalid videoport interface pointer" );
LEAVE_DDRAW();
return DDERR_INVALIDPARAMS;
}
*ppvObj = NULL;
if( !VALIDEX_IID_PTR( riid ) )
{
DPF_ERR( "Invalid IID pointer" );
LEAVE_DDRAW();
return DDERR_INVALIDPARAMS;
}
}
EXCEPT( EXCEPTION_EXECUTE_HANDLER )
{
DPF_ERR( "Exception encountered validating parameters" );
LEAVE_DDRAW();
return DDERR_INVALIDPARAMS;
}
/*
* asking for IUnknown?
*/
if( IsEqualIID(riid, &IID_IUnknown) ||
IsEqualIID(riid, &IID_IDirectDrawVideoPort) )
{
/*
* Our IUnknown interface is the same as our V1
* interface. We must always return the V1 interface
* if IUnknown is requested.
*/
*ppvObj = (LPVOID) this_int;
DD_VP_AddRef( *ppvObj );
LEAVE_DDRAW();
return DD_OK;
}
else if( IsEqualIID(riid, &IID_IDirectDrawVideoPortNotify) )
{
HRESULT ret;
ret = CreateVideoPortNotify (this_int, (LPDIRECTDRAWVIDEOPORTNOTIFY*)ppvObj);
LEAVE_DDRAW();
return ret;
}
DPF_ERR( "IID not understood by DirectDraw" );
LEAVE_DDRAW();
return E_NOINTERFACE;
} /* DD_VP_QueryInterface */
/*
* DD_VP_Release
*/
DWORD DDAPI DD_VP_Release(LPDIRECTDRAWVIDEOPORT lpDVP )
{
LPDDRAWI_DDVIDEOPORT_INT this_int;
LPDDRAWI_DDVIDEOPORT_LCL this_lcl;
LPDDRAWI_DIRECTDRAW_GBL pdrv;
LPDDHALVPORTCB_DESTROYVPORT pfn;
DWORD dwIntRefCnt;
DWORD rc;
ENTER_DDRAW();
DPF(2,A,"ENTERAPI: DD_VP_Release");
/*
* Don't allow access to this function if called from within the
* the EnumVideoPort callback.
*/
if( bInEnumCallback )
{
DPF_ERR ( "This function cannot be called from within the EnumVideoPort callback!");
LEAVE_DDRAW();
return 0;
}
TRY
{
this_int = (LPDDRAWI_DDVIDEOPORT_INT) lpDVP;
if( !VALID_DDVIDEOPORT_PTR( this_int ) )
{
DPF_ERR( "Invalid videoport pointer" );
LEAVE_DDRAW();
return 0;
}
this_lcl = this_int->lpLcl;
pdrv = this_lcl->lpDD->lpGbl;
}
EXCEPT( EXCEPTION_EXECUTE_HANDLER )
{
DPF_ERR( "Exception encountered validating parameters" );
LEAVE_DDRAW();
return 0;
}
/*
* decrement the reference count. if it hits zero, free the surface
*/
this_lcl->dwRefCnt--;
this_int->dwIntRefCnt--;
DPF( 5, "DD_VP_Release, Reference Count: Local = %ld Int = %ld",
this_lcl->dwRefCnt, this_int->dwIntRefCnt );
/*
* interface at zero?
*/
dwIntRefCnt = this_int->dwIntRefCnt;
if( dwIntRefCnt == 0 )
{
LPDDRAWI_DDVIDEOPORT_INT curr_int;
LPDDRAWI_DDVIDEOPORT_INT last_int;
/*
* remove videoport from list
*/
curr_int = pdrv->dvpList;
last_int = NULL;
while( curr_int != this_int )
{
last_int = curr_int;
curr_int = curr_int->lpLink;
if( curr_int == NULL )
{
DPF_ERR( "VideoPort not in list!" );
LEAVE_DDRAW();
return 0;
}
}
if( last_int == NULL )
{
pdrv->dvpList = pdrv->dvpList->lpLink;
}
else
{
last_int->lpLink = curr_int->lpLink;
}
/*
* Decrement the surface reference counts and clean things up
*/
if( !( this_int->dwFlags & DDVPCREATE_NOTIFY ) )
{
DD_VP_StopVideo( (LPDIRECTDRAWVIDEOPORT) this_int );
this_lcl->dwFlags &= ~DDRAWIVPORT_ON;
if( this_int->dwFlags & DDVPCREATE_VBIONLY )
{
if( this_lcl->lpVBISurface != NULL )
{
DecrementRefCounts( this_lcl->lpVBISurface );
this_lcl->lpVBISurface = NULL;
}
if( this_lcl->lpVBIDesc != NULL )
{
MemFree( this_lcl->lpVBIDesc );
this_lcl->lpVBIDesc = NULL;
}
if( this_lcl->lpVBIInfo != NULL )
{
MemFree( this_lcl->lpVBIInfo );
this_lcl->lpVBIInfo = NULL;
}
this_lcl->dwVBIProcessID = 0;
}
else if( this_int->dwFlags & DDVPCREATE_VIDEOONLY )
{
if( this_lcl->lpSurface != NULL )
{
DecrementRefCounts( this_lcl->lpSurface );
this_lcl->lpSurface = NULL;
}
if( this_lcl->lpVideoDesc != NULL )
{
MemFree( this_lcl->lpVideoDesc );
this_lcl->lpVideoDesc = NULL;
}
if( this_lcl->lpVideoInfo != NULL )
{
MemFree( this_lcl->lpVideoInfo );
this_lcl->lpVideoInfo = NULL;
}
this_lcl->dwProcessID = 0;
}
else
{
if( this_lcl->lpSurface != NULL )
{
DecrementRefCounts( this_lcl->lpSurface );
}
if( this_lcl->lpVBISurface != NULL )
{
DecrementRefCounts( this_lcl->lpVBISurface );
}
this_lcl->dwProcessID = 0;
}
}
else
{
this_lcl->lpVPNotify = NULL;
}
/*
* just in case someone comes back in with this pointer, set
* an invalid vtbl & data ptr.
*/
this_int->lpVtbl = NULL;
this_int->lpLcl = NULL;
MemFree( this_int );
}
/*
* local object at zero?
*/
if( this_lcl->dwRefCnt == 0 )
{
/*
* turn off the videoport hardware
*/
if( this_lcl->dwFlags & DDRAWIVPORT_ON )
{
DD_VP_StopVideo( lpDVP );
}
#ifdef WIN95
UpdateKernelVideoPort( this_lcl, DDKMVP_RELEASE );
#endif
/*
* Notify the HAL
*/
pfn = this_lcl->lpDD->lpDDCB->HALDDVideoPort.DestroyVideoPort;
if( NULL != pfn )
{
DDHAL_DESTROYVPORTDATA DestroyVportData;
DestroyVportData.lpDD = this_lcl->lpDD;
DestroyVportData.lpVideoPort = this_lcl;
DOHALCALL( DestroyVideoPort, pfn, DestroyVportData, rc, 0 );
if( ( DDHAL_DRIVER_HANDLED == rc ) && ( DD_OK != DestroyVportData.ddRVal ) )
{
LEAVE_DDRAW();
return DestroyVportData.ddRVal;
}
}
MemFree( this_lcl->lpFlipInts );
MemFree( this_lcl );
}
LEAVE_DDRAW();
return dwIntRefCnt;
}
/*
* DD_VP_SetTargetSurface
*/
HRESULT DDAPI DD_VP_SetTargetSurface(LPDIRECTDRAWVIDEOPORT lpDVP, LPDIRECTDRAWSURFACE lpSurface, DWORD dwFlags )
{
LPDDRAWI_DDRAWSURFACE_INT surf_first;
LPDDRAWI_DDVIDEOPORT_INT this_int;
LPDDRAWI_DDVIDEOPORT_LCL this_lcl;
LPDDRAWI_DDRAWSURFACE_INT surf_int;
LPDDRAWI_DDRAWSURFACE_LCL surf_lcl;
LPDDRAWI_DDRAWSURFACE_INT lpTemp;
LPDDRAWI_DDRAWSURFACE_INT lpPrevious;
BOOL bWasOn;
DWORD ddRVal;
ENTER_DDRAW();
DPF(2,A,"ENTERAPI: DD_VP_SetTargetSurface");
/*
* Don't allow access to this function if called from within the
* the EnumVideoPort callback.
*/
if( bInEnumCallback )
{
DPF_ERR ( "This function cannot be called from within the EnumVideoPort callback!");
LEAVE_DDRAW();
return DDERR_CURRENTLYNOTAVAIL;
}
/*
* Validate parameters
*/
TRY
{
this_int = (LPDDRAWI_DDVIDEOPORT_INT) lpDVP;
if( !VALID_DDVIDEOPORT_PTR( this_int ) )
{
LEAVE_DDRAW();
return DDERR_INVALIDOBJECT;
}
this_lcl = this_int->lpLcl;
surf_int = (LPDDRAWI_DDRAWSURFACE_INT) lpSurface;
if( ( NULL == lpSurface ) || !VALID_DIRECTDRAWSURFACE_PTR( surf_int ) )
{
LEAVE_DDRAW();
return DDERR_INVALIDOBJECT;
}
surf_lcl = surf_int->lpLcl;
/*
* Make sure the surface and video port belong to the same device.
*/
if (surf_lcl->lpSurfMore->lpDD_lcl->lpGbl != this_lcl->lpDD->lpGbl)
{
DPF_ERR("Video port and Surface must belong to the same device");
LEAVE_DDRAW();
return DDERR_DEVICEDOESNTOWNSURFACE;
}
if( this_int->dwFlags & DDVPCREATE_VBIONLY )
{
if( dwFlags & DDVPTARGET_VIDEO )
{
DPF_ERR( "DDVPTARGET_VIDEO specified on a VBI-only video port" );
LEAVE_DDRAW();
return DDERR_INVALIDPARAMS;
}
dwFlags |= DDVPTARGET_VBI;
}
else if( this_int->dwFlags & DDVPCREATE_VIDEOONLY )
{
if( dwFlags & DDVPTARGET_VBI )
{
DPF_ERR( "DDVPTARGET_VBI specified on a video-only video port" );
LEAVE_DDRAW();
return DDERR_INVALIDPARAMS;
}
dwFlags |= DDVPTARGET_VIDEO;
}
}
EXCEPT( EXCEPTION_EXECUTE_HANDLER )
{
DPF_ERR( "Exception encountered validating parameters" );
LEAVE_DDRAW();
return DDERR_EXCEPTION;
}
/*
* Surface must have the video port flag set
*/
if( !( surf_lcl->ddsCaps.dwCaps & DDSCAPS_VIDEOPORT ) )
{
DPF_ERR( "Specified surface doesnt have DDSCAPS_VIDEOPORT set" );
LEAVE_DDRAW();
return DDERR_INVALIDPARAMS;
}
/*
* Can surface live in system memory?
*/
if( surf_lcl->ddsCaps.dwCaps & DDSCAPS_SYSTEMMEMORY )
{
if( !( this_lcl->lpDD->lpGbl->lpDDVideoPortCaps[this_lcl->ddvpDesc.dwVideoPortID].dwCaps &
DDVPCAPS_SYSTEMMEMORY ) )
{
DPF_ERR( "Video port surface must live in video memory" );
LEAVE_DDRAW();
return DDERR_INVALIDPARAMS;
}
if( surf_lcl->lpSurfMore->dwPageLockCount == 0 )
{
DPF_ERR( "Surface must be page locked" );
LEAVE_DDRAW();
return DDERR_INVALIDPARAMS;
}
}
/*
* If another surface in the chain is attached to a different video
* port, fail now.
*/
surf_first = surf_int;
do
{
if( ( surf_int->lpLcl->lpSurfMore->lpVideoPort != NULL ) &&
( surf_int->lpLcl->lpSurfMore->lpVideoPort != this_lcl ) )
{
LEAVE_DDRAW();
return DDERR_INVALIDPARAMS;
}
surf_int = FindAttachedFlip( surf_int );
} while( ( surf_int != NULL ) && ( surf_int->lpLcl != surf_first->lpLcl ) );
surf_int = surf_first;
/*
* If the video was on, we need to temporarily turn it off. Otherwise,
* we could lose our kernel surfaces while they are still in use.
*/
bWasOn = FALSE;
if( this_int->dwFlags & DDVPCREATE_VBIONLY )
{
if( this_lcl->lpVBIInfo != NULL )
{
bWasOn = TRUE;
}
}
else if( this_int->dwFlags & DDVPCREATE_VIDEOONLY )
{
if( this_lcl->lpVideoInfo != NULL )
{
bWasOn = TRUE;
}
}
else if( this_lcl->dwFlags & DDRAWIVPORT_ON )
{
bWasOn = TRUE;
}
if( bWasOn )
{
DD_VP_StopVideo( lpDVP );
}
if( dwFlags & DDVPTARGET_VIDEO )
{
/*
* Set the new surface
*/
lpPrevious = this_lcl->lpSurface;
lpTemp = (LPDDRAWI_DDRAWSURFACE_INT) this_lcl->lpSurface;
this_lcl->lpSurface = surf_int;
IncrementRefCounts( surf_int );
}
else if( dwFlags & DDVPTARGET_VBI )
{
if( this_lcl->lpDD->lpGbl->lpDDVideoPortCaps[this_lcl->ddvpDesc.dwVideoPortID].dwCaps & DDVPCAPS_VBISURFACE )
{
/*
* Set the new surface
*/
lpPrevious = this_lcl->lpVBISurface;
lpTemp = (LPDDRAWI_DDRAWSURFACE_INT) this_lcl->lpVBISurface;
this_lcl->lpVBISurface = surf_int;
IncrementRefCounts( surf_int );
}
else
{
DPF_ERR( "device does not support attaching VBI surfaces" );
LEAVE_DDRAW();
return DDERR_INVALIDCAPS;
}
}
else
{
LEAVE_DDRAW();
return DDERR_INVALIDPARAMS;
}
/*
* If the video port is already on, we should tell the hardware
* to make this change.
*/
if( bWasOn )
{
if( this_int->dwFlags & DDVPCREATE_VBIONLY )
{
ddRVal = DD_VP_StartVideo( lpDVP, this_lcl->lpVBIInfo );
}
else if( this_int->dwFlags & DDVPCREATE_VIDEOONLY )
{
ddRVal = DD_VP_StartVideo( lpDVP, this_lcl->lpVideoInfo );
}
else
{
ddRVal = DD_VP_StartVideo( lpDVP, &(this_lcl->ddvpInfo) );
}
if( ddRVal != DD_OK )
{
// Restore the old surface
DD_VP_SetTargetSurface( lpDVP,
(LPDIRECTDRAWSURFACE) lpTemp, dwFlags );
if( lpTemp != NULL )
{
DecrementRefCounts( lpTemp );
}
LEAVE_DDRAW();
return ddRVal;
}
}
/*
* Decrement the ref counts of the previously attached surfaces. We
* wait until now so we don't inadvertantly blast data to a surface that
* has just been released.
*/
if( lpPrevious != NULL )
{
DecrementRefCounts( lpPrevious );
}
LEAVE_DDRAW();
return DD_OK;
}
/*
* DD_VP_Flip
*/
HRESULT DDAPI DD_VP_Flip(LPDIRECTDRAWVIDEOPORT lpDVP, LPDIRECTDRAWSURFACE lpSurface, DWORD dwFlags )
{
LPDDRAWI_DDRAWSURFACE_LCL surf_lcl;
LPDDRAWI_DDRAWSURFACE_INT surf_int;
LPDDRAWI_DDRAWSURFACE_GBL surf;
LPDDRAWI_DDRAWSURFACE_INT surf_dest_int;
LPDDRAWI_DDRAWSURFACE_LCL surf_dest_lcl;
LPDDRAWI_DIRECTDRAW_LCL pdrv_lcl;
LPDDRAWI_DIRECTDRAW_GBL pdrv;
LPDDRAWI_DDVIDEOPORT_INT this_int;
LPDDRAWI_DDVIDEOPORT_LCL this_lcl;
LPDDRAWI_DDRAWSURFACE_INT next_save_int;
LPDDRAWI_DDRAWSURFACE_INT next_int;
BOOL found_dest;
DWORD rc;
ENTER_DDRAW();
DPF(2,A,"ENTERAPI: DD_VP_Flip");
/*
* Don't allow access to this function if called from within the
* the EnumVideoPort callback.
*/
if( bInEnumCallback )
{
DPF_ERR ( "This function cannot be called from within the EnumVideoPort callback!");
LEAVE_DDRAW();
return DDERR_CURRENTLYNOTAVAIL;
}
TRY
{
this_int = (LPDDRAWI_DDVIDEOPORT_INT) lpDVP;
if( !VALID_DDVIDEOPORT_PTR( this_int ) )
{
LEAVE_DDRAW();
return DDERR_INVALIDOBJECT;
}
this_lcl = this_int->lpLcl;
if( this_lcl->ddvpInfo.dwVPFlags & DDVP_AUTOFLIP )
{
DPF_ERR( "cannot manually flip while autoflipping is enabled" );
LEAVE_DDRAW();
return DDERR_NOTFLIPPABLE;
}
surf_dest_int = (LPDDRAWI_DDRAWSURFACE_INT) lpSurface;
if( NULL != surf_dest_int )
{
if( !VALID_DIRECTDRAWSURFACE_PTR( surf_dest_int ) )
{
LEAVE_DDRAW();
return DDERR_INVALIDOBJECT;
}
surf_dest_lcl = surf_dest_int->lpLcl;
if( SURFACE_LOST( surf_dest_lcl ) )
{
LEAVE_DDRAW();
return DDERR_SURFACELOST;
}
}
else
{
surf_dest_lcl = NULL;
}
if( dwFlags & DDVPFLIP_VBI )
{
surf_int = this_lcl->lpVBISurface;
}
else
{
surf_int = this_lcl->lpSurface;
}
if( surf_int == NULL )
{
DPF_ERR( "SetTargetSurface not yet called" );
LEAVE_DDRAW();
return DDERR_INVALIDPARAMS;
}
surf_lcl = surf_int->lpLcl;
if( NULL == surf_lcl )
{
LEAVE_DDRAW();
return DDERR_SURFACENOTATTACHED;
}
else if( SURFACE_LOST( surf_lcl ) )
{
LEAVE_DDRAW();
return DDERR_SURFACELOST;
}
surf = surf_lcl->lpGbl;
/*
* device busy?
*/
pdrv_lcl = surf_lcl->lpSurfMore->lpDD_lcl;
pdrv = pdrv_lcl->lpGbl;
#ifdef USE_ALIAS
if( pdrv->dwBusyDueToAliasedLock > 0 )
{
/*
* Aliased locks (the ones that don't take the Win16 lock) don't
* set the busy bit either (it can't or USER get's very confused).
* However, we must prevent blits happening via DirectDraw as
* otherwise we get into the old host talking to VRAM while
* blitter does at the same time. Bad. So fail if there is an
* outstanding aliased lock just as if the BUST bit had been
* set.
*/
DPF_ERR( "Graphics adapter is busy (due to a DirectDraw lock)" );
LEAVE_DDRAW();
return DDERR_SURFACEBUSY;
}
#endif /* USE_ALIAS */
if( *(pdrv->lpwPDeviceFlags) & BUSY )
{
DPF( 0, "BUSY - Flip" );
LEAVE_DDRAW()
return DDERR_SURFACEBUSY;
}
/*
* make sure that it's OK to flip this surface
*/
if( !(surf_lcl->ddsCaps.dwCaps & DDSCAPS_FLIP) )
{
LEAVE_DDRAW();
return DDERR_NOTFLIPPABLE;
}
if( surf->dwUsageCount > 0 )
{
DPF_ERR( "Can't flip because surface is locked" );
LEAVE_DDRAW();
return DDERR_SURFACEBUSY;
}
}
EXCEPT( EXCEPTION_EXECUTE_HANDLER )
{
DPF_ERR( "Exception encountered validating parameters" );
LEAVE_DDRAW();
return DDERR_INVALIDPARAMS;
}
/*
* make sure no surfaces are in use
*/
found_dest = FALSE;
next_save_int = next_int = FindAttachedFlip( surf_int );
if( next_int == NULL )
{
LEAVE_DDRAW();
return DDERR_NOTFLIPPABLE; // ACKACK: real error?
}
do
{
if( SURFACE_LOST( next_int->lpLcl ) )
{
DPF_ERR( "Can't flip - back buffer is lost" );
LEAVE_DDRAW();
return DDERR_SURFACELOST;
}
if( next_int->lpLcl->lpGbl->dwUsageCount != 0 )
{
LEAVE_DDRAW();
return DDERR_SURFACEBUSY;
}
if( surf_dest_int->lpLcl == next_int->lpLcl )
{
found_dest = TRUE;
}
next_int = FindAttachedFlip( next_int );
} while( next_int->lpLcl != surf_lcl );
/*
* see if we can use the specified destination
*/
if( surf_dest_int != NULL )
{
if( !found_dest )
{
DPF_ERR( "Destination not part of flipping chain!" );
LEAVE_DDRAW();
return DDERR_NOTFLIPPABLE; // ACKACK: real error?
}
next_save_int = surf_dest_int;
}
/*
* found the linked surface we want to flip to
*/
next_int = next_save_int;
rc = InternalVideoPortFlip( this_lcl, next_int, 1 );
LEAVE_DDRAW();
return (HRESULT)rc;
}
/*
* InternalGetBandwidth
*/
HRESULT InternalGetBandwidth( LPDDRAWI_DDVIDEOPORT_LCL this_lcl,
LPDDPIXELFORMAT lpf, DWORD dwWidth, DWORD dwHeight, DWORD dwFlags,
LPDDVIDEOPORTBANDWIDTH lpBandwidth )
{
LPDDHALVPORTCB_GETBANDWIDTH pfn;
DDHAL_GETVPORTBANDWIDTHDATA GetBandwidthData;
DWORD rc;
lpBandwidth->dwCaps = 0;
lpBandwidth->dwOverlay = (DWORD) -1;
lpBandwidth->dwColorkey = (DWORD) -1;
lpBandwidth->dwYInterpolate = (DWORD) -1;
lpBandwidth->dwYInterpAndColorkey = (DWORD) -1;
pfn = this_lcl->lpDD->lpDDCB->HALDDVideoPort.GetVideoPortBandwidth;
if( pfn != NULL )
{
/*
* Call the HAL
*/
GetBandwidthData.lpDD = this_lcl->lpDD;
GetBandwidthData.lpVideoPort = this_lcl;
GetBandwidthData.lpddpfFormat = lpf;
GetBandwidthData.dwWidth = dwWidth;
GetBandwidthData.dwHeight = dwHeight;
GetBandwidthData.lpBandwidth = lpBandwidth;
GetBandwidthData.dwFlags = dwFlags;
DOHALCALL( GetVideoPortBandwidthInfo, pfn, GetBandwidthData, rc, 0 );
if( DDHAL_DRIVER_HANDLED != rc )
{
return DDERR_UNSUPPORTED;
}
else if( DD_OK != GetBandwidthData.ddRVal )
{
return GetBandwidthData.ddRVal;
}
lpBandwidth->dwReserved1 = 0;
lpBandwidth->dwReserved2 = 0;
}
else
{
return DDERR_UNSUPPORTED;
}
return DD_OK;
}
/*
* DD_VP_GetBandwidth
*/
HRESULT DDAPI DD_VP_GetBandwidth(LPDIRECTDRAWVIDEOPORT lpDVP,
LPDDPIXELFORMAT lpf, DWORD dwWidth, DWORD dwHeight, DWORD dwFlags,
LPDDVIDEOPORTBANDWIDTH lpBandwidth )
{
LPDDRAWI_DDVIDEOPORT_INT this_int;
LPDDRAWI_DDVIDEOPORT_LCL this_lcl;
DWORD rc;
ENTER_DDRAW();
DPF(2,A,"ENTERAPI: DD_VP_Getbandwidth");
/*
* Don't allow access to this function if called from within the
* the EnumVideoPort callback.
*/
if( bInEnumCallback )
{
DPF_ERR ( "This function cannot be called from within the EnumVideoPort callback!");
LEAVE_DDRAW();
return DDERR_CURRENTLYNOTAVAIL;
}
/*
* Validate parameters
*/
TRY
{
this_int = (LPDDRAWI_DDVIDEOPORT_INT) lpDVP;
if( !VALID_DDVIDEOPORT_PTR( this_int ) )
{
LEAVE_DDRAW();
return DDERR_INVALIDOBJECT;
}
this_lcl = this_int->lpLcl;
if( (lpf == NULL) || !VALID_DDPIXELFORMAT_PTR( lpf ) )
{
DPF_ERR( "Invalid LPDDPIXELFORMAT specified" );
LEAVE_DDRAW();
return DDERR_INVALIDPARAMS;
}
if( (lpBandwidth == NULL) || !VALID_DDVIDEOPORTBANDWIDTH_PTR( lpBandwidth ) )
{
DPF_ERR( "Invalid LPDDVIDEOPORTBANDWIDTH specified" );
LEAVE_DDRAW();
return DDERR_INVALIDPARAMS;
}
if( ( ( dwHeight == 0 ) || ( dwWidth == 0 ) ) &&
!( dwFlags & DDVPB_TYPE ) )
{
DPF_ERR( "Width and Height must be specified" );
LEAVE_DDRAW();
return DDERR_INVALIDPARAMS;
}
if( ( dwFlags & DDVPB_VIDEOPORT ) && ( dwFlags & DDVPB_OVERLAY ) )
{
DPF_ERR( "Mutually exclusive flags specified" );
LEAVE_DDRAW();
return DDERR_INVALIDPARAMS;
}
if( dwFlags & DDVPB_VIDEOPORT )
{
if( !( this_lcl->lpDD->lpGbl->lpDDVideoPortCaps[this_lcl->ddvpDesc.dwVideoPortID].dwFX &
( DDVPFX_PRESTRETCHX | DDVPFX_PRESTRETCHY |
DDVPFX_PRESTRETCHXN | DDVPFX_PRESTRETCHYN ) ) )
{
if( ( dwWidth > this_lcl->ddvpDesc.dwFieldWidth ) ||
( dwHeight > this_lcl->ddvpDesc.dwFieldHeight ) )
{
DPF_ERR( "Invalid Width/Height specified" );
LEAVE_DDRAW();
return DDERR_INVALIDPARAMS;
}
}
}
}
EXCEPT( EXCEPTION_EXECUTE_HANDLER )
{
DPF_ERR( "Exception encountered validating parameters" );
LEAVE_DDRAW();
return DDERR_EXCEPTION;
}
rc = InternalGetBandwidth( this_lcl, lpf, dwWidth, dwHeight,
dwFlags, lpBandwidth );
LEAVE_DDRAW();
return rc;
}
/*
* DD_VP_GetInputFormats
*/
HRESULT DDAPI DD_VP_GetInputFormats(LPDIRECTDRAWVIDEOPORT lpDVP, LPDWORD lpdwNum, LPDDPIXELFORMAT lpf, DWORD dwFlags )
{
LPDDHALVPORTCB_GETINPUTFORMATS pfn;
LPDDRAWI_DDVIDEOPORT_INT this_int;
LPDDRAWI_DDVIDEOPORT_LCL this_lcl;
LPDDPIXELFORMAT lpTemp = NULL;
DDHAL_GETVPORTINPUTFORMATDATA GetFormatData;
DWORD rc;
ENTER_DDRAW();
DPF(2,A,"ENTERAPI: DD_VP_GetInputFormats");
/*
* Don't allow access to this function if called from within the
* the EnumVideoPort callback.
*/
if( bInEnumCallback )
{
DPF_ERR ( "This function cannot be called from within the EnumVideoPort callback!");
LEAVE_DDRAW();
return DDERR_CURRENTLYNOTAVAIL;
}
/*
* Validate parameters
*/
TRY
{
this_int = (LPDDRAWI_DDVIDEOPORT_INT) lpDVP;
if( !VALID_DDVIDEOPORT_PTR( this_int ) )
{
LEAVE_DDRAW();
return DDERR_INVALIDOBJECT;
}
this_lcl = this_int->lpLcl;
if( (lpdwNum == NULL) || !VALID_BYTE_ARRAY( lpdwNum, sizeof( LPVOID ) ) )
{
LEAVE_DDRAW();
return DDERR_INVALIDPARAMS;
}
if( NULL != lpf )
{
if( 0 == *lpdwNum )
{
LEAVE_DDRAW();
return DDERR_INVALIDPARAMS;
}
if( !VALID_BYTE_ARRAY( lpf, *lpdwNum * sizeof( DDPIXELFORMAT ) ) )
{
LEAVE_DDRAW();
return DDERR_INVALIDPARAMS;
}
}
if( ( dwFlags == 0 ) ||
( dwFlags & ~(DDVPFORMAT_VIDEO|DDVPFORMAT_VBI|DDVPFORMAT_NOFAIL) ) )
{
LEAVE_DDRAW();
return DDERR_INVALIDPARAMS;
}
if( ( this_int->dwFlags & DDVPCREATE_VBIONLY ) &&
!( dwFlags & DDVPFORMAT_NOFAIL ) )
{
if( dwFlags & DDVPFORMAT_VIDEO )
{
DPF_ERR( "DDVPFORMAT_VIDEO specified on a VBI-only video port" );
LEAVE_DDRAW();
return DDERR_INVALIDPARAMS;
}
dwFlags |= DDVPFORMAT_VBI;
}
else if( ( this_int->dwFlags & DDVPCREATE_VIDEOONLY ) &&
!( dwFlags & DDVPFORMAT_NOFAIL ) )
{
if( dwFlags & DDVPFORMAT_VBI )
{
DPF_ERR( "DDVPFORMAT_VBI specified on a video-only video port" );
LEAVE_DDRAW();
return DDERR_INVALIDPARAMS;
}
dwFlags |= DDVPFORMAT_VIDEO;
}
}
EXCEPT( EXCEPTION_EXECUTE_HANDLER )
{
DPF_ERR( "Exception encountered validating parameters" );
LEAVE_DDRAW();
return DDERR_EXCEPTION;
}
pfn = this_lcl->lpDD->lpDDCB->HALDDVideoPort.GetVideoPortInputFormats;
if( pfn != NULL )
{
/*
* Get the number of formats
*/
GetFormatData.lpDD = this_lcl->lpDD;
GetFormatData.dwFlags = dwFlags;
GetFormatData.lpVideoPort = this_lcl;
GetFormatData.lpddpfFormat = NULL;
DOHALCALL( GetVideoPortInputFormats, pfn, GetFormatData, rc, 0 );
if( DDHAL_DRIVER_HANDLED != rc )
{
LEAVE_DDRAW();
return GetFormatData.ddRVal;
}
else if( DD_OK != GetFormatData.ddRVal )
{
LEAVE_DDRAW();
return GetFormatData.ddRVal;
}
if( NULL == lpf )
{
*lpdwNum = GetFormatData.dwNumFormats;
}
else
{
/*
* Make sure we have enough room for formats
*/
if( GetFormatData.dwNumFormats > *lpdwNum )
{
lpTemp = (LPDDPIXELFORMAT) MemAlloc( sizeof( DDPIXELFORMAT ) *
GetFormatData.dwNumFormats );
GetFormatData.lpddpfFormat = lpTemp;
}
else
{
GetFormatData.lpddpfFormat = lpf;
}
DOHALCALL( GetVideoPortInputFormats, pfn, GetFormatData, rc, 0 );
if( DDHAL_DRIVER_HANDLED != rc )
{
MemFree( lpTemp );
LEAVE_DDRAW();
return DDERR_UNSUPPORTED;
}
else if( DD_OK != GetFormatData.ddRVal )
{
MemFree( lpTemp );
LEAVE_DDRAW();
return GetFormatData.ddRVal;
}
if( GetFormatData.lpddpfFormat != lpf )
{
memcpy( lpf, lpTemp, sizeof( DDPIXELFORMAT ) * *lpdwNum );
MemFree( lpTemp );
LEAVE_DDRAW();
return DDERR_MOREDATA;
}
else
{
*lpdwNum = GetFormatData.dwNumFormats;
}
}
}
else
{
LEAVE_DDRAW();
return DDERR_UNSUPPORTED;
}
LEAVE_DDRAW();
return DD_OK;
}
/*
* DD_VP_GetOutputFormats
*/
HRESULT DDAPI DD_VP_GetOutputFormats(LPDIRECTDRAWVIDEOPORT lpDVP, LPDDPIXELFORMAT lpddpfInput, LPDWORD lpdwNum, LPDDPIXELFORMAT lpddpfOutput, DWORD dwFlags )
{
LPDDHALVPORTCB_GETOUTPUTFORMATS pfn;
LPDDRAWI_DDVIDEOPORT_INT this_int;
LPDDRAWI_DDVIDEOPORT_LCL this_lcl;
LPDDPIXELFORMAT lpTemp = NULL;
DDHAL_GETVPORTOUTPUTFORMATDATA GetFormatData;
DWORD rc;
ENTER_DDRAW();
DPF(2,A,"ENTERAPI: DD_VP_GetOutputFormats");
/*
* Don't allow access to this function if called from within the
* the EnumVideoPort callback.
*/
if( bInEnumCallback )
{
DPF_ERR ( "This function cannot be called from within the EnumVideoPort callback!");
LEAVE_DDRAW();
return DDERR_CURRENTLYNOTAVAIL;
}
/*
* Validate parameters
*/
TRY
{
this_int = (LPDDRAWI_DDVIDEOPORT_INT) lpDVP;
if( !VALID_DDVIDEOPORT_PTR( this_int ) )
{
LEAVE_DDRAW();
return DDERR_INVALIDOBJECT;
}
this_lcl = this_int->lpLcl;
if( !VALID_DDPIXELFORMAT_PTR( lpddpfInput ) )
{
LEAVE_DDRAW();
return DDERR_INVALIDPARAMS;
}
if( (lpdwNum == NULL) || !VALID_BYTE_ARRAY( lpdwNum, sizeof( LPVOID ) ) )
{
LEAVE_DDRAW();
return DDERR_INVALIDPARAMS;
}
if( NULL != lpddpfOutput )
{
if( 0 == *lpdwNum )
{
LEAVE_DDRAW();
return DDERR_INVALIDPARAMS;
}
if( !VALID_BYTE_ARRAY( lpddpfOutput, *lpdwNum * sizeof( DDPIXELFORMAT ) ) )
{
LEAVE_DDRAW();
return DDERR_INVALIDPARAMS;
}
}
if( ( dwFlags == 0 ) ||
( dwFlags & ~(DDVPFORMAT_VIDEO|DDVPFORMAT_VBI|DDVPFORMAT_NOFAIL) ) )
{
LEAVE_DDRAW();
return DDERR_INVALIDPARAMS;
}
if( ( this_int->dwFlags & DDVPCREATE_VBIONLY ) &&
!( dwFlags & DDVPFORMAT_NOFAIL ) )
{
if( dwFlags & DDVPFORMAT_VIDEO )
{
DPF_ERR( "DDVPFORMAT_VIDEO specified on a VBI-only video port" );
LEAVE_DDRAW();
return DDERR_INVALIDPARAMS;
}
dwFlags |= DDVPFORMAT_VBI;
}
else if( ( this_int->dwFlags & DDVPCREATE_VIDEOONLY ) &&
!( dwFlags & DDVPFORMAT_NOFAIL ) )
{
if( dwFlags & DDVPFORMAT_VBI )
{
DPF_ERR( "DDVPFORMAT_VBI specified on a video-only video port" );
LEAVE_DDRAW();
return DDERR_INVALIDPARAMS;
}
dwFlags |= DDVPFORMAT_VIDEO;
}
}
EXCEPT( EXCEPTION_EXECUTE_HANDLER )
{
DPF_ERR( "Exception encountered validating parameters" );
LEAVE_DDRAW();
return DDERR_EXCEPTION;
}
pfn = this_lcl->lpDD->lpDDCB->HALDDVideoPort.GetVideoPortOutputFormats;
if( pfn != NULL )
{
/*
* Get the number of formats
*/
GetFormatData.lpDD = this_lcl->lpDD;
GetFormatData.dwFlags = dwFlags;
GetFormatData.lpVideoPort = this_lcl;
GetFormatData.lpddpfInputFormat = lpddpfInput;
GetFormatData.lpddpfOutputFormats = NULL;
DOHALCALL( GetVideoPortOutputFormats, pfn, GetFormatData, rc, 0 );
if( DDHAL_DRIVER_HANDLED != rc )
{
LEAVE_DDRAW();
return DDERR_UNSUPPORTED;
}
else if( DD_OK != GetFormatData.ddRVal )
{
LEAVE_DDRAW();
return GetFormatData.ddRVal;
}
if( NULL == lpddpfOutput )
{
*lpdwNum = GetFormatData.dwNumFormats;
}
else
{
/*
* Make sure we have enough room for formats
*/
if( GetFormatData.dwNumFormats > *lpdwNum )
{
lpTemp = (LPDDPIXELFORMAT) MemAlloc( sizeof( DDPIXELFORMAT ) *
GetFormatData.dwNumFormats );
GetFormatData.lpddpfOutputFormats = lpTemp;
}
else
{
GetFormatData.lpddpfOutputFormats = lpddpfOutput;
}
DOHALCALL( GetVideoPortOutputFormats, pfn, GetFormatData, rc, 0 );
if( DDHAL_DRIVER_HANDLED != rc )
{
MemFree( lpTemp );
LEAVE_DDRAW();
return DDERR_UNSUPPORTED;
}
else if( DD_OK != GetFormatData.ddRVal )
{
MemFree( lpTemp );
LEAVE_DDRAW();
return GetFormatData.ddRVal;
}
if( GetFormatData.lpddpfOutputFormats != lpddpfOutput )
{
memcpy( lpddpfOutput, lpTemp, sizeof( DDPIXELFORMAT ) * *lpdwNum );
MemFree( lpTemp );
LEAVE_DDRAW();
return DDERR_MOREDATA;
}
else
{
*lpdwNum = GetFormatData.dwNumFormats;
}
}
}
else
{
LEAVE_DDRAW();
return DDERR_UNSUPPORTED;
}
LEAVE_DDRAW();
return DD_OK;
}
/*
* DD_VP_GetField
*/
HRESULT DDAPI DD_VP_GetField(LPDIRECTDRAWVIDEOPORT lpDVP, LPBOOL lpField )
{
LPDDHALVPORTCB_GETFIELD pfn;
LPDDRAWI_DDVIDEOPORT_INT this_int;
LPDDRAWI_DDVIDEOPORT_LCL this_lcl;
DWORD rc;
DDHAL_GETVPORTFIELDDATA GetFieldData;
ENTER_DDRAW();
DPF(2,A,"ENTERAPI: DD_VP_GetField");
/*
* Don't allow access to this function if called from within the
* the EnumVideoPort callback.
*/
if( bInEnumCallback )
{
DPF_ERR ( "This function cannot be called from within the EnumVideoPort callback!");
LEAVE_DDRAW();
return DDERR_CURRENTLYNOTAVAIL;
}
/*
* Validate parameters
*/
TRY
{
this_int = (LPDDRAWI_DDVIDEOPORT_INT) lpDVP;
if( !VALID_DDVIDEOPORT_PTR( this_int ) )
{
LEAVE_DDRAW();
return DDERR_INVALIDOBJECT;
}
this_lcl = this_int->lpLcl;
if( (NULL == lpField ) || !VALID_BOOL_PTR( lpField ) )
{
LEAVE_DDRAW();
return DDERR_INVALIDPARAMS;
}
}
EXCEPT( EXCEPTION_EXECUTE_HANDLER )
{
DPF_ERR( "Exception encountered validating parameters" );
LEAVE_DDRAW();
return DDERR_EXCEPTION;
}
pfn = this_lcl->lpDD->lpDDCB->HALDDVideoPort.GetVideoPortField;
if( pfn != NULL )
{
GetFieldData.lpDD = this_lcl->lpDD;
GetFieldData.lpVideoPort = this_lcl;
GetFieldData.bField = 0;
DOHALCALL( GetVideoPortField, pfn, GetFieldData, rc, 0 );
if( DDHAL_DRIVER_HANDLED != rc )
{
LEAVE_DDRAW();
return DDERR_UNSUPPORTED;
}
else if( DD_OK != GetFieldData.ddRVal )
{
LEAVE_DDRAW();
return GetFieldData.ddRVal;
}
*lpField = GetFieldData.bField;
}
else
{
LEAVE_DDRAW();
return DDERR_UNSUPPORTED;
}
LEAVE_DDRAW();
return DD_OK;
}
/*
* DD_VP_GetLine
*/
HRESULT DDAPI DD_VP_GetLine(LPDIRECTDRAWVIDEOPORT lpDVP, LPDWORD lpdwLine )
{
LPDDHALVPORTCB_GETLINE pfn;
LPDDRAWI_DDVIDEOPORT_INT this_int;
LPDDRAWI_DDVIDEOPORT_LCL this_lcl;
DWORD rc;
DDHAL_GETVPORTLINEDATA GetLineData;
ENTER_DDRAW();
DPF(2,A,"ENTERAPI: DD_VP_GetLine");
/*
* Don't allow access to this function if called from within the
* the EnumVideoPort callback.
*/
if( bInEnumCallback )
{
DPF_ERR ( "This function cannot be called from within the EnumVideoPort callback!");
LEAVE_DDRAW();
return DDERR_CURRENTLYNOTAVAIL;
}
/*
* Validate parameters
*/
TRY
{
this_int = (LPDDRAWI_DDVIDEOPORT_INT) lpDVP;
if( !VALID_DDVIDEOPORT_PTR( this_int ) )
{
LEAVE_DDRAW();
return DDERR_INVALIDOBJECT;
}
this_lcl = this_int->lpLcl;
if( (NULL == lpdwLine ) || !VALID_DWORD_PTR( lpdwLine ) )
{
LEAVE_DDRAW();
return DDERR_INVALIDPARAMS;
}
}
EXCEPT( EXCEPTION_EXECUTE_HANDLER )
{
DPF_ERR( "Exception encountered validating parameters" );
LEAVE_DDRAW();
return DDERR_EXCEPTION;
}
pfn = this_lcl->lpDD->lpDDCB->HALDDVideoPort.GetVideoPortLine;
if( pfn != NULL )
{
GetLineData.lpDD = this_lcl->lpDD;
GetLineData.lpVideoPort = this_lcl;
GetLineData.dwLine = 0;
DOHALCALL( GetVideoPortLine, pfn, GetLineData, rc, 0 );
if( DDHAL_DRIVER_HANDLED != rc )
{
LEAVE_DDRAW();
return DDERR_UNSUPPORTED;
}
else if( DD_OK != GetLineData.ddRVal )
{
LEAVE_DDRAW();
return GetLineData.ddRVal;
}
*lpdwLine = GetLineData.dwLine;
}
else
{
LEAVE_DDRAW();
return DDERR_UNSUPPORTED;
}
LEAVE_DDRAW();
return DD_OK;
}
/*
* ValidateVideoInfo
*/
HRESULT ValidateVideoInfo(LPDDRAWI_DDVIDEOPORT_INT this_int,
LPDDVIDEOPORTINFO lpInfo, LPDWORD lpNumAutoFlip, LPDWORD lpNumVBIAutoFlip )
{
LPDDRAWI_DDVIDEOPORT_LCL this_lcl;
LPDDPIXELFORMAT lpOutputFormat;
LPDDRAWI_DDRAWSURFACE_LCL surf_lcl = NULL;
DWORD rc;
DWORD dwAvailCaps;
DWORD dwAvailFX;
DWORD dwConnectFlags;
DWORD dwVPFlags;
DWORD dwNum;
DWORD i;
this_lcl = this_int->lpLcl;
*lpNumAutoFlip = 0;
*lpNumVBIAutoFlip = 0;
/*
* Check for invalid caps
*/
dwAvailCaps = this_lcl->lpDD->lpGbl->lpDDVideoPortCaps[this_lcl->ddvpDesc.dwVideoPortID].dwCaps;
dwAvailFX = this_lcl->lpDD->lpGbl->lpDDVideoPortCaps[this_lcl->ddvpDesc.dwVideoPortID].dwFX;
dwConnectFlags = this_lcl->ddvpDesc.VideoPortType.dwFlags;
dwVPFlags = lpInfo->dwVPFlags;
if( ( dwVPFlags & DDVP_AUTOFLIP ) && !( dwAvailCaps & DDVPCAPS_AUTOFLIP ) )
{
DPF_ERR( "Invalid autoflip capability specified" );
return DDERR_INVALIDCAPS;
}
if( ( dwVPFlags & DDVP_INTERLEAVE ) && (
!( dwConnectFlags & DDVPCONNECT_INTERLACED ) ||
( dwConnectFlags & DDVPCONNECT_SHAREEVEN ) ||
( dwConnectFlags & DDVPCONNECT_SHAREODD ) ||
!( dwAvailFX & DDVPFX_INTERLEAVE ) ||
( dwVPFlags & DDVP_SKIPODDFIELDS ) ||
( dwVPFlags & DDVP_SKIPEVENFIELDS ) ) )
{
DPF_ERR( "Invalid interleave capability specified" );
return DDERR_INVALIDCAPS;
}
if( ( dwVPFlags & DDVP_MIRRORLEFTRIGHT ) && !( dwAvailFX & DDVPFX_MIRRORLEFTRIGHT ) )
{
DPF_ERR( "Invalid mirror left/right capability specified" );
return DDERR_INVALIDCAPS;
}
if( ( dwVPFlags & DDVP_MIRRORUPDOWN ) && !( dwAvailFX & DDVPFX_MIRRORUPDOWN ) )
{
DPF_ERR( "Invalid mirror up/down capability specified" );
return DDERR_INVALIDCAPS;
}
if( ( dwVPFlags & DDVP_SKIPEVENFIELDS ) && (
!( dwConnectFlags & DDVPCONNECT_INTERLACED ) ||
( dwConnectFlags & DDVPCONNECT_SHAREEVEN ) ||
( dwConnectFlags & DDVPCONNECT_SHAREODD ) ||
!( dwAvailCaps & DDVPCAPS_SKIPEVENFIELDS ) ||
( dwVPFlags & DDVP_SKIPODDFIELDS ) ) )
{
DPF_ERR( "Invalid skipevenfields capability specified" );
return DDERR_INVALIDCAPS;
}
if( ( dwVPFlags & DDVP_SKIPODDFIELDS ) && (
!( dwConnectFlags & DDVPCONNECT_INTERLACED ) ||
( dwConnectFlags & DDVPCONNECT_SHAREEVEN ) ||
( dwConnectFlags & DDVPCONNECT_SHAREODD ) ||
!( dwAvailCaps & DDVPCAPS_SKIPODDFIELDS ) ) )
{
DPF_ERR( "Invalid skipoddfields capability specified" );
return DDERR_INVALIDCAPS;
}
if( ( dwVPFlags & DDVP_VBINOSCALE ) && !( dwAvailFX & DDVPFX_VBINOSCALE ) )
{
DPF_ERR( "Invalid VBI no-scale capability specified" );
return DDERR_INVALIDCAPS;
}
if( ( dwVPFlags & ( DDVP_VBICONVERT | DDVP_VBINOSCALE ) ) ||
( NULL != this_lcl->lpVBISurface ) )
{
if( ( lpInfo->dwVBIHeight == 0 ) ||
( lpInfo->dwVBIHeight >= this_lcl->ddvpDesc.dwFieldHeight ) )
{
DPF_ERR( "Invalid dwVBIHeight specified" );
return DDERR_INVALIDPARAMS;
}
if( ( dwVPFlags & DDVP_CROP ) &&
( lpInfo->rCrop.top > (int) lpInfo->dwVBIHeight ) )
{
DPF_ERR( "Invalid dwVBIHeight specified" );
return DDERR_INVALIDPARAMS;
}
}
if( dwVPFlags & DDVP_CROP )
{
if( lpInfo->rCrop.bottom > (int) this_lcl->ddvpDesc.dwFieldHeight )
{
DPF_ERR( "Invalid cropping rectangle specified" );
return DDERR_SURFACENOTATTACHED;
}
if( !( dwAvailFX & ( DDVPFX_CROPY | DDVPFX_CROPTOPDATA ) ) && (
(lpInfo->rCrop.bottom - lpInfo->rCrop.top ) !=
(int) this_lcl->ddvpDesc.dwFieldHeight ) )
{
DPF_ERR( "Invalid cropping rectangle specified" );
return DDERR_SURFACENOTATTACHED;
}
if( lpInfo->rCrop.top >= (int) lpInfo->dwVBIHeight )
{
lpInfo->dwVBIHeight = 0;
}
/*
* Only do the extensive field width/height checking if the video
* region is involved
*/
if( lpInfo->rCrop.bottom > (int) lpInfo->dwVBIHeight )
{
if( lpInfo->rCrop.right > (int) this_lcl->ddvpDesc.dwFieldWidth )
{
DPF_ERR( "Invalid cropping rectangle specified" );
return DDERR_SURFACENOTATTACHED;
}
if( !( dwAvailFX & DDVPFX_CROPX ) && (
(lpInfo->rCrop.right - lpInfo->rCrop.left ) !=
(int) this_lcl->ddvpDesc.dwFieldWidth ) )
{
DPF_ERR( "Invalid cropping rectangle specified" );
return DDERR_SURFACENOTATTACHED;
}
if( ( ( lpInfo->rCrop.right - lpInfo->rCrop.left ) ==
(int) this_lcl->ddvpDesc.dwFieldWidth ) &&
( ( lpInfo->rCrop.bottom - lpInfo->rCrop.top ) ==
(int) this_lcl->ddvpDesc.dwFieldHeight ) )
{
dwVPFlags &= ~DDVP_CROP;
lpInfo->dwVPFlags &= ~DDVP_CROP;
}
}
}
if( dwVPFlags & DDVP_PRESCALE )
{
DWORD dwPreWidth;
DWORD dwPreHeight;
if( dwVPFlags & DDVP_CROP )
{
dwPreWidth = lpInfo->rCrop.right - lpInfo->rCrop.left;
dwPreHeight = lpInfo->rCrop.bottom - lpInfo->rCrop.top;
}
else
{
dwPreWidth = this_lcl->ddvpDesc.dwFieldWidth;
dwPreHeight = this_lcl->ddvpDesc.dwFieldHeight;
}
if( lpInfo->dwPrescaleWidth > dwPreWidth )
{
if( !( dwAvailFX & DDVPFX_PRESTRETCHX ) &&
!( ( dwAvailFX & DDVPFX_PRESTRETCHXN ) &&
( lpInfo->dwPrescaleWidth % dwPreWidth ) ) )
{
DPF_ERR( "Invalid stretch specified" );
return DDERR_INVALIDPARAMS;
}
}
if( lpInfo->dwPrescaleHeight > dwPreHeight )
{
if( !( dwAvailFX & DDVPFX_PRESTRETCHY ) &&
!( ( dwAvailFX & DDVPFX_PRESTRETCHYN ) &&
( lpInfo->dwPrescaleHeight % dwPreHeight ) ) )
{
DPF_ERR( "Invalid stretch specified" );
return DDERR_INVALIDPARAMS;
}
}
if( lpInfo->dwPrescaleWidth < dwPreWidth )
{
if( !( dwAvailFX & DDVPFX_PRESHRINKX ) &&
!( dwAvailFX & DDVPFX_PRESHRINKXS ) &&
!( dwAvailFX & DDVPFX_PRESHRINKXB ) )
{
DPF_ERR( "Invalid shrink specified" );
return DDERR_INVALIDPARAMS;
}
}
if( lpInfo->dwPrescaleHeight < dwPreHeight )
{
if( !( dwAvailFX & DDVPFX_PRESHRINKY ) &&
!( dwAvailFX & DDVPFX_PRESHRINKYS ) &&
!( dwAvailFX & DDVPFX_PRESHRINKYB ) )
{
DPF_ERR( "Invalid shrink specified" );
return DDERR_INVALIDPARAMS;
}
}
if( ( lpInfo->dwPrescaleWidth == dwPreWidth ) &&
( lpInfo->dwPrescaleHeight == dwPreHeight ) )
{
dwVPFlags &= ~DDVP_PRESCALE;
lpInfo->dwVPFlags &= ~DDVP_PRESCALE;
}
}
if( dwVPFlags & DDVP_VBINOINTERLEAVE )
{
if( !( dwAvailFX & DDVPFX_VBINOINTERLEAVE ) )
{
DPF_ERR( "Device does not support DDVP_VBINOINTERLEAVE" );
return DDERR_INVALIDPARAMS;
}
if( this_lcl->lpVBISurface == NULL )
{
DPF_ERR( "DDVP_VBINOINTERLEAVE only valid when using a separate VBI surface" );
return DDERR_INVALIDPARAMS;
}
}
if( dwVPFlags & DDVP_HARDWAREDEINTERLACE )
{
if( !( dwAvailCaps & DDVPCAPS_HARDWAREDEINTERLACE ) )
{
DPF_ERR( "DDVP_HARDWAREDEINTERLACE not supported by this device" );
return DDERR_INVALIDPARAMS;
}
if( ( this_lcl->lpSurface != NULL ) &&
!( this_lcl->lpSurface->lpLcl->lpSurfMore->ddsCapsEx.dwCaps2 &
DDSCAPS2_RESERVED4 ) )
{
DPF_ERR( "DDSCAPS2_RESERVED4 not set on target surface" );
return DDERR_INVALIDPARAMS;
}
if( ( this_lcl->lpVBISurface != NULL ) &&
!( this_lcl->lpVBISurface->lpLcl->lpSurfMore->ddsCapsEx.dwCaps2 &
DDSCAPS2_RESERVED4 ) )
{
DPF_ERR( "DDSCAPS2_RESERVED4 not set on target surface" );
return DDERR_INVALIDPARAMS;
}
if( dwVPFlags & DDVP_AUTOFLIP )
{
DPF_ERR( "DDVP_HARDWAREDEINTERLACE not valid with DDVP_AUTOFLIP" );
return DDERR_INVALIDPARAMS;
}
}
/*
* Fail if neither a VBI or regular surface is attached
*/
if( ( NULL == this_lcl->lpSurface ) && ( NULL == this_lcl->lpVBISurface ) )
{
DPF_ERR( "No surfaces are attached to the video port" );
return DDERR_INVALIDPARAMS;
}
/*
* Validate the regular video data
*/
if( ( NULL != this_lcl->lpSurface ) &&
( this_int->lpLcl->dwFlags & DDRAWIVPORT_VIDEOON ) )
{
DWORD dwVidWidth;
DWORD dwVidHeight;
/*
* Validate the input format
*/
dwNum = MAX_VP_FORMATS;
rc = DD_VP_GetInputFormats( (LPDIRECTDRAWVIDEOPORT) this_int,
&dwNum, ddpfVPFormats, DDVPFORMAT_VIDEO | DDVPFORMAT_NOFAIL );
if( ( rc != DD_OK ) && ( rc != DDERR_MOREDATA ) )
{
DPF_ERR( "Invalid input format specified" );
return DDERR_INVALIDPIXELFORMAT;
}
i = 0;
while( ( i < dwNum ) && IsDifferentPixelFormat( &(ddpfVPFormats[i]),
lpInfo->lpddpfInputFormat ) )
{
i++;
}
if( i == dwNum )
{
DPF_ERR( "Invalid input format specified" );
return DDERR_INVALIDPIXELFORMAT;
}
/*
* Validate the output format
*/
dwNum = MAX_VP_FORMATS;
rc = DD_VP_GetOutputFormats( (LPDIRECTDRAWVIDEOPORT) this_int,
lpInfo->lpddpfInputFormat, &dwNum, ddpfVPFormats,
DDVPFORMAT_VIDEO | DDVPFORMAT_NOFAIL );
if( ( rc != DD_OK ) && ( rc != DDERR_MOREDATA ) )
{
DPF_ERR( "Invalid output format specified" );
return DDERR_INVALIDPIXELFORMAT;
}
i = 0;
surf_lcl = this_lcl->lpSurface->lpLcl;
lpOutputFormat = GetSurfaceFormat( surf_lcl );
if( ( IsDifferentPixelFormat( lpInfo->lpddpfInputFormat,
lpOutputFormat ) ) && !( dwVPFlags |= DDVP_CONVERT ) )
{
DPF_ERR( "Invalid output format specified" );
return DDERR_INVALIDPIXELFORMAT;
}
while( ( i < dwNum ) && IsDifferentPixelFormat( &(ddpfVPFormats[i]),
lpOutputFormat ) )
{
i++;
}
if( i == dwNum )
{
DPF_ERR( "Invalid output format specified" );
return DDERR_INVALIDPIXELFORMAT;
}
/*
* Make sure the video fits within the attached surface
*/
if( SURFACE_LOST( surf_lcl ) )
{
DPF_ERR( "Target surface is lost" );
return DDERR_SURFACELOST;
}
if( dwVPFlags & DDVP_PRESCALE )
{
dwVidWidth = lpInfo->dwPrescaleWidth;
dwVidHeight = lpInfo->dwPrescaleHeight;
}
else if( dwVPFlags & DDVP_CROP )
{
dwVidWidth = lpInfo->rCrop.right - lpInfo->rCrop.left;
dwVidHeight = lpInfo->rCrop.bottom - lpInfo->rCrop.top;
}
else
{
dwVidWidth = this_lcl->ddvpDesc.dwFieldWidth;
dwVidHeight = this_lcl->ddvpDesc.dwFieldHeight;
}
if( ( lpInfo->dwVBIHeight > 0 ) &&
( this_lcl->dwFlags & DDRAWIVPORT_VBION ) &&
( NULL != this_lcl->lpVBISurface ) )
{
dwVidHeight -= lpInfo->dwVBIHeight;
}
if( dwVPFlags & DDVP_INTERLEAVE )
{
dwVidHeight *= 2;
}
if( lpInfo->dwOriginX + dwVidWidth > (DWORD) surf_lcl->lpGbl->wWidth )
{
DPF_ERR( "surface is not wide enough to hold the videoport data" );
return DDERR_TOOBIGWIDTH;
}
if( lpInfo->dwOriginY + dwVidHeight > (DWORD) surf_lcl->lpGbl->wHeight )
{
DPF_ERR( "surface is not tall enough to hold the videoport data" );
return DDERR_TOOBIGHEIGHT;
}
}
else if( this_lcl->dwFlags & DDRAWIVPORT_VIDEOON )
{
DPF_ERR( "Video surface not specified" );
return DDERR_INVALIDPARAMS;
}
/*
* Validate the VBI formats.
*/
if( ( lpInfo->dwVBIHeight > 0 ) &&
( this_int->lpLcl->dwFlags & DDRAWIVPORT_VBION ) )
{
if( lpInfo->lpddpfVBIInputFormat == NULL )
{
DPF_ERR( "VBI input format not specified" );
return DDERR_INVALIDPIXELFORMAT;
}
}
/*
* Unless they want to convert the format, we don't do very much
* error checking.
*/
if( dwVPFlags & DDVP_VBICONVERT )
{
if( !( dwAvailFX & DDVPFX_VBICONVERT ) )
{
DPF_ERR( "device cannot convert the VBI data" );
return DDERR_INVALIDCAPS;
}
/*
* Validate the VBI input format
*/
dwNum = MAX_VP_FORMATS;
rc = DD_VP_GetInputFormats( (LPDIRECTDRAWVIDEOPORT) this_int,
&dwNum, ddpfVPFormats, DDVPFORMAT_VBI | DDVPFORMAT_NOFAIL );
if( ( rc != DD_OK ) && ( rc != DDERR_MOREDATA ) )
{
DPF_ERR( "Invalid input VBI format specified" );
return DDERR_INVALIDPIXELFORMAT;
}
i = 0;
while( ( i < dwNum ) && IsDifferentPixelFormat( &(ddpfVPFormats[i]),
lpInfo->lpddpfVBIInputFormat ) )
{
i++;
}
if( i == dwNum )
{
DPF_ERR( "Invalid VBI input format specified" );
return DDERR_INVALIDPIXELFORMAT;
}
/*
* Validate the VBI output format
*/
if( lpInfo->lpddpfVBIOutputFormat == NULL )
{
DPF_ERR( "VBI output format not specified" );
return DDERR_INVALIDPIXELFORMAT;
}
dwNum = MAX_VP_FORMATS;
rc = DD_VP_GetOutputFormats( (LPDIRECTDRAWVIDEOPORT) this_int,
lpInfo->lpddpfVBIInputFormat, &dwNum, ddpfVPFormats,
DDVPFORMAT_VBI | DDVPFORMAT_NOFAIL );
if( ( rc != DD_OK ) && ( rc != DDERR_MOREDATA ) )
{
DPF_ERR( "Invalid output format specified" );
return DDERR_INVALIDPIXELFORMAT;
}
i = 0;
while( ( i < dwNum ) && IsDifferentPixelFormat( &(ddpfVPFormats[i]),
lpInfo->lpddpfVBIOutputFormat ) )
{
i++;
}
if( i == dwNum )
{
DPF_ERR( "Invalid VBI output format specified" );
return DDERR_INVALIDPIXELFORMAT;
}
}
/*
* Validate the VBI surface
*/
if( ( lpInfo->dwVBIHeight > 0 ) &&
( this_int->lpLcl->dwFlags & DDRAWIVPORT_VBION ) )
{
DWORD dwVBIBytes;
DWORD dwSurfaceBytes = 0;
DWORD dwVBIHeight;
/*
* Determine the height of the VBI data
*/
dwVBIHeight = lpInfo->dwVBIHeight;
if( dwVPFlags & DDVP_CROP )
{
if( lpInfo->rCrop.top < (int) lpInfo->dwVBIHeight )
{
dwVBIHeight -= lpInfo->rCrop.top;
if( lpInfo->rCrop.bottom < (int) lpInfo->dwVBIHeight )
{
dwVBIHeight -= (lpInfo->dwVBIHeight - (DWORD)lpInfo->rCrop.bottom);
}
}
else
{
dwVBIHeight = 0;
}
}
if( ( dwVPFlags & DDVP_INTERLEAVE ) &&
!( dwVPFlags & DDVP_VBINOINTERLEAVE ) )
{
dwVBIHeight *= 2;
}
/*
* Make sure that the data will fit in the surface
*/
if( ( dwVPFlags & DDVP_VBINOSCALE ) ||
!( dwVPFlags & DDVP_PRESCALE ) )
{
dwVBIBytes = this_lcl->ddvpDesc.dwVBIWidth;
}
else
{
dwVBIBytes = lpInfo->dwPrescaleWidth;
}
if( dwVPFlags & DDVP_VBICONVERT )
{
lpOutputFormat = lpInfo->lpddpfVBIOutputFormat;
}
else
{
lpOutputFormat = lpInfo->lpddpfVBIInputFormat;
}
if( lpOutputFormat->dwRGBBitCount )
{
dwVBIBytes *= lpOutputFormat->dwRGBBitCount;
dwVBIBytes /= 8;
}
else
{
dwVBIBytes *= 2;
}
if( NULL != this_lcl->lpVBISurface )
{
if( SURFACE_LOST( this_lcl->lpVBISurface->lpLcl ) )
{
DPF_ERR( "Target VBI surface is lost" );
return DDERR_SURFACELOST;
}
dwSurfaceBytes = (DWORD) this_lcl->lpVBISurface->lpLcl->lpGbl->wWidth;
if( this_lcl->lpVBISurface->lpLcl->dwFlags & DDRAWISURF_HASPIXELFORMAT )
{
dwSurfaceBytes *= this_lcl->lpVBISurface->lpLcl->lpGbl->ddpfSurface.dwRGBBitCount;
}
else
{
dwSurfaceBytes *= this_lcl->lpDD->lpGbl->vmiData.ddpfDisplay.dwRGBBitCount;
}
if( dwVBIHeight > (DWORD) this_lcl->lpVBISurface->lpLcl->lpGbl->wHeight )
{
DPF_ERR( "VBI surface is not tall enough to hold the VBI data" );
return DDERR_TOOBIGHEIGHT;
}
}
else if( NULL != surf_lcl )
{
dwSurfaceBytes = (DWORD) surf_lcl->lpGbl->wWidth;
if( surf_lcl->dwFlags & DDRAWISURF_HASPIXELFORMAT )
{
dwSurfaceBytes *= surf_lcl->lpGbl->ddpfSurface.dwRGBBitCount;
}
else
{
dwSurfaceBytes *= this_lcl->lpDD->lpGbl->vmiData.ddpfDisplay.dwRGBBitCount;
}
if( dwVBIHeight > (DWORD) this_lcl->lpSurface->lpLcl->lpGbl->wHeight )
{
DPF_ERR( "Surface is not tall enough to hold the VBI data" );
return DDERR_TOOBIGHEIGHT;
}
}
dwSurfaceBytes /= 8;
if( dwSurfaceBytes == 0 )
{
DPF_ERR( "No VBI/Video surface is attached to hold VBI data" );
return DDERR_INVALIDPARAMS;
}
if( dwVBIBytes > dwSurfaceBytes )
{
DPF_ERR( "VBI surface is not wide enough to hold the VBI data" );
return DDERR_TOOBIGWIDTH;
}
}
/*
* Validate the autoflip parameters
*/
if( dwVPFlags & DDVP_AUTOFLIP )
{
LPDDRAWI_DDRAWSURFACE_INT surf_first;
LPDDRAWI_DDRAWSURFACE_INT surf_int;
/*
* Count how many regular surfaces there are
*/
if( ( NULL != this_lcl->lpSurface ) &&
( this_int->lpLcl->dwFlags & DDRAWIVPORT_VIDEOON ) )
{
surf_first = surf_int = this_lcl->lpSurface;
do
{
(*lpNumAutoFlip)++;
surf_int = FindAttachedFlip( surf_int );
} while( ( surf_int != NULL ) && ( surf_int->lpLcl != surf_first->lpLcl ) );
if( *lpNumAutoFlip == 1 )
{
*lpNumAutoFlip = 0;
}
}
/*
* Count how many VBI surfaces there are
*/
if( ( NULL != this_lcl->lpVBISurface ) &&
( this_int->lpLcl->dwFlags & DDRAWIVPORT_VBION ) )
{
surf_first = surf_int = this_lcl->lpVBISurface;
do
{
(*lpNumVBIAutoFlip)++;
surf_int = FindAttachedFlip( surf_int );
} while( ( surf_int != NULL ) && ( surf_int->lpLcl != surf_first->lpLcl ) );
if( *lpNumVBIAutoFlip == 1 )
{
*lpNumVBIAutoFlip = 0;
}
}
/*
* It's an error if neither one has sufficient surfaces to autoflip
*/
if( ( *lpNumAutoFlip == 0 ) && ( *lpNumVBIAutoFlip == 0 ) )
{
DPF_ERR( "no autoflip surfaces are attached" );
return DDERR_INVALIDPARAMS;
}
}
return DD_OK;
}
/*
* FillFlipArray
*/
DWORD FillFlipArray( LPDDRAWI_DDRAWSURFACE_INT *lpArray,
LPDDRAWI_DDRAWSURFACE_INT lpStart, LPDWORD lpdwCnt )
{
LPDDRAWI_DDRAWSURFACE_INT surf_first;
*lpdwCnt = 0;
surf_first = lpStart;
do
{
if( SURFACE_LOST( lpStart->lpLcl ) )
{
DPF_ERR( "Autoflip surface is lost" );
return (DWORD) DDERR_SURFACELOST;
}
(*lpdwCnt)++;
*lpArray++ = lpStart;
lpStart = FindAttachedFlip( lpStart );
} while( ( lpStart != NULL ) && ( lpStart->lpLcl != surf_first->lpLcl ) );
return DD_OK;
}
/*
* InternalStartVideo
*/
HRESULT InternalStartVideo(LPDDRAWI_DDVIDEOPORT_INT this_int,
LPDDVIDEOPORTINFO lpInfo )
{
LPDDHALVPORTCB_UPDATE pfn;
LPDDRAWI_DDVIDEOPORT_LCL this_lcl;
DDHAL_UPDATEVPORTDATA UpdateData;
DDVIDEOPORTBANDWIDTH Bandwidth;
LPDDRAWI_DDRAWSURFACE_INT *lpTempFlipInts;
LPDDVIDEOPORTCAPS lpAvailCaps;
DWORD dwTempNumAutoFlip;
DWORD dwTempNumVBIAutoFlip;
DWORD rc;
DWORD dwNumAutoFlip;
DWORD dwNumVBIAutoFlip;
DWORD dwTemp;
/*
* Validate the input parameters
*/
rc = ValidateVideoInfo( this_int, lpInfo, &dwNumAutoFlip, &dwNumVBIAutoFlip );
if( DD_OK != rc )
{
return rc;
}
this_lcl = this_int->lpLcl;
lpAvailCaps = &(this_lcl->lpDD->lpGbl->lpDDVideoPortCaps[this_lcl->ddvpDesc.dwVideoPortID]);
/*
* Setup the autoflip surfaces
*/
lpTempFlipInts = NULL;
if( lpInfo->dwVPFlags & DDVP_AUTOFLIP )
{
DWORD dwCnt;
lpTempFlipInts = this_lcl->lpFlipInts;
this_lcl->lpFlipInts = MemAlloc( sizeof( LPDDRAWI_DDRAWSURFACE_INT ) *
( dwNumAutoFlip + dwNumVBIAutoFlip ) );
if( NULL == this_lcl->lpFlipInts )
{
DPF_ERR( "insufficient memory" );
this_lcl->lpFlipInts = lpTempFlipInts;
return DDERR_OUTOFMEMORY;
}
/*
* Now put the surface INTs into the array.
*/
if( dwNumAutoFlip )
{
rc = FillFlipArray( this_lcl->lpFlipInts, this_lcl->lpSurface, &dwCnt );
if( rc != DD_OK )
{
MemFree( this_lcl->lpFlipInts );
this_lcl->lpFlipInts = lpTempFlipInts;
return rc;
}
DDASSERT( dwCnt == dwNumAutoFlip );
if( dwNumAutoFlip > lpAvailCaps->dwNumAutoFlipSurfaces )
{
DPF_ERR( "Too many autoflip surfaces" );
MemFree( this_lcl->lpFlipInts );
this_lcl->lpFlipInts = lpTempFlipInts;
return DDERR_INVALIDPARAMS;
}
}
/*
* Now put the VBI surface INTs into the array.
*/
if( dwNumVBIAutoFlip )
{
rc = FillFlipArray( &(this_lcl->lpFlipInts[dwNumAutoFlip]),
this_lcl->lpVBISurface, &dwCnt );
if( rc != DD_OK )
{
MemFree( this_lcl->lpFlipInts );
this_lcl->lpFlipInts = lpTempFlipInts;
return rc;
}
DDASSERT( dwCnt == dwNumVBIAutoFlip );
if( dwNumVBIAutoFlip > lpAvailCaps->dwNumVBIAutoFlipSurfaces )
{
DPF_ERR( "Too many VBI autoflip surfaces" );
MemFree( this_lcl->lpFlipInts );
return DDERR_INVALIDPARAMS;
}
}
}
dwTempNumAutoFlip = this_lcl->dwNumAutoflip;
dwTempNumVBIAutoFlip = this_lcl->dwNumVBIAutoflip;
this_lcl->dwNumAutoflip = dwNumAutoFlip;
this_lcl->dwNumVBIAutoflip = dwNumVBIAutoFlip;
/*
* The kernel interface may have switched from hardware autoflipping
* to software autoflipping w/o us knowing. We need to check for
* this.
*/
#ifdef WIN95
if( ( lpInfo->dwVPFlags & DDVP_AUTOFLIP ) &&
( this_lcl->dwFlags & DDRAWIVPORT_SOFTWARE_AUTOFLIP ) &&
( ( this_lcl->lpSurface != NULL ) || ( this_lcl->lpVBISurface != NULL ) ) )
{
DWORD dwState;
dwState = 0;
if( this_lcl->dwFlags & DDRAWIVPORT_VIDEOON )
{
GetKernelSurfaceState( this_lcl->lpSurface->lpLcl, &dwState );
}
else
{
GetKernelSurfaceState( this_lcl->lpVBISurface->lpLcl, &dwState );
}
if( dwState & DDSTATE_SOFTWARE_AUTOFLIP )
{
this_lcl->dwFlags |= DDRAWIVPORT_SOFTWARE_AUTOFLIP;
}
}
#endif
pfn = this_lcl->lpDD->lpDDCB->HALDDVideoPort.UpdateVideoPort;
if( pfn != NULL )
{
/*
* Call the HAL
*/
memset( &UpdateData, 0, sizeof( UpdateData ) );
UpdateData.lpDD = this_lcl->lpDD;
UpdateData.lpVideoPort = this_lcl;
UpdateData.lpVideoInfo = lpInfo;
UpdateData.dwFlags = DDRAWI_VPORTSTART;
if( dwNumAutoFlip && ( this_lcl->dwFlags & DDRAWIVPORT_VIDEOON ) )
{
UpdateData.lplpDDSurface = this_lcl->lpFlipInts;
UpdateData.dwNumAutoflip = dwNumAutoFlip;
}
else if( this_lcl->lpSurface && ( this_lcl->dwFlags & DDRAWIVPORT_VIDEOON ) )
{
UpdateData.lplpDDSurface = &(this_lcl->lpSurface);
}
else
{
UpdateData.lplpDDSurface = NULL;
}
if( dwNumVBIAutoFlip && ( this_lcl->dwFlags & DDRAWIVPORT_VBION ) )
{
UpdateData.lplpDDVBISurface =
&(this_lcl->lpFlipInts[this_lcl->dwNumAutoflip]);
UpdateData.dwNumVBIAutoflip = dwNumVBIAutoFlip;
}
else if( this_lcl->lpVBISurface && ( this_lcl->dwFlags & DDRAWIVPORT_VBION ) )
{
UpdateData.lplpDDVBISurface = &(this_lcl->lpVBISurface);
}
else
{
UpdateData.lplpDDVBISurface = NULL;
}
dwTemp = lpInfo->dwVPFlags;
if( this_lcl->dwFlags & DDRAWIVPORT_SOFTWARE_AUTOFLIP )
{
lpInfo->dwVPFlags &= ~DDVP_AUTOFLIP;
}
/*
* Before we call the HAL, create the implicit kernel surfaces if
* needed and update the list. A failure here will tell us whether
* software autoflip, etc. is an option.
*/
if( ( this_lcl->lpSurface != NULL ) &&
( this_lcl->dwFlags & DDRAWIVPORT_VIDEOON ) )
{
ReleaseVPESurfaces( this_lcl->lpSurface, FALSE );
PrepareVPESurfaces( this_lcl->lpSurface, this_lcl,
dwNumAutoFlip > 0 );
}
if( ( this_lcl->lpVBISurface != NULL ) &&
( this_lcl->dwFlags & DDRAWIVPORT_VBION ) )
{
ReleaseVPESurfaces( this_lcl->lpVBISurface, FALSE );
PrepareVPESurfaces( this_lcl->lpVBISurface, this_lcl,
dwNumVBIAutoFlip > 0 );
}
#ifdef WIN95
if( this_lcl->lpSurface != NULL )
{
OverrideVideoPort( this_lcl->lpSurface, &(lpInfo->dwVPFlags) );
}
#endif
DOHALCALL( UpdateVideoPort, pfn, UpdateData, rc, 0 );
if( DDHAL_DRIVER_HANDLED != rc )
{
lpInfo->dwVPFlags = dwTemp;
if( lpInfo->dwVPFlags & DDVP_AUTOFLIP )
{
MemFree( this_lcl->lpFlipInts );
this_lcl->lpFlipInts = lpTempFlipInts;
this_lcl->dwNumAutoflip = dwTempNumAutoFlip;
this_lcl->dwNumVBIAutoflip = dwTempNumVBIAutoFlip;
}
return DDERR_UNSUPPORTED;
}
else if( DD_OK != UpdateData.ddRVal )
{
/*
* If we failed due to hardware autoflipping, try again w/o
*/
#ifdef WIN95
if( ( lpInfo->dwVPFlags & DDVP_AUTOFLIP ) &&
CanSoftwareAutoflip( this_lcl ) )
{
lpInfo->dwVPFlags &= ~DDVP_AUTOFLIP;
DOHALCALL( UpdateVideoPort, pfn, UpdateData, rc, 0 );
if( ( DDHAL_DRIVER_HANDLED != rc ) ||
( DD_OK != UpdateData.ddRVal ) )
{
lpInfo->dwVPFlags = dwTemp;
MemFree( this_lcl->lpFlipInts );
this_lcl->lpFlipInts = lpTempFlipInts;
this_lcl->dwNumAutoflip = dwTempNumAutoFlip;
this_lcl->dwNumVBIAutoflip = dwTempNumVBIAutoFlip;
return UpdateData.ddRVal;
}
this_lcl->dwFlags |= DDRAWIVPORT_SOFTWARE_AUTOFLIP;
}
else
{
#endif
lpInfo->dwVPFlags = dwTemp;
if( lpInfo->dwVPFlags & DDVP_AUTOFLIP )
{
MemFree( this_lcl->lpFlipInts );
this_lcl->lpFlipInts = lpTempFlipInts;
this_lcl->dwNumAutoflip = dwTempNumAutoFlip;
this_lcl->dwNumVBIAutoflip = dwTempNumVBIAutoFlip;
}
return UpdateData.ddRVal;
#ifdef WIN95
}
#endif
}
MemFree( lpTempFlipInts );
lpTempFlipInts = NULL;
lpInfo->dwVPFlags = dwTemp;
UpdateInterleavedFlags( this_lcl, lpInfo->dwVPFlags );
this_lcl->dwFlags |= DDRAWIVPORT_ON;
memcpy( &(this_lcl->ddvpInfo), lpInfo, sizeof( DDVIDEOPORTINFO ) );
if( NULL != lpInfo->lpddpfInputFormat )
{
this_lcl->ddvpInfo.lpddpfInputFormat = (LPDDPIXELFORMAT)
((LPBYTE)this_lcl +
sizeof( DDRAWI_DDVIDEOPORT_LCL ) );
memcpy( this_lcl->ddvpInfo.lpddpfInputFormat,
lpInfo->lpddpfInputFormat, sizeof( DDPIXELFORMAT ) );
}
/*
* Determine if this can be colorkeyed and interpolated at
* the same time.
*/
if( NULL != lpInfo->lpddpfInputFormat )
{
memset( &Bandwidth, 0, sizeof( Bandwidth ) );
Bandwidth.dwSize = sizeof( Bandwidth );
InternalGetBandwidth( this_lcl, lpInfo->lpddpfInputFormat,
0, 0, DDVPB_TYPE, &Bandwidth );
if( Bandwidth.dwCaps & DDVPBCAPS_SOURCE )
{
if( InternalGetBandwidth( this_lcl, lpInfo->lpddpfInputFormat,
this_lcl->ddvpDesc.dwFieldWidth,
this_lcl->ddvpDesc.dwFieldHeight,
DDVPB_OVERLAY,
&Bandwidth ) == DD_OK )
{
if( Bandwidth.dwYInterpAndColorkey ==
Bandwidth.dwYInterpolate )
{
this_lcl->dwFlags |= DDRAWIVPORT_COLORKEYANDINTERP;
}
}
}
else
{
if( InternalGetBandwidth( this_lcl, lpInfo->lpddpfInputFormat,
this_lcl->ddvpDesc.dwFieldWidth,
this_lcl->ddvpDesc.dwFieldHeight,
DDVPB_VIDEOPORT,
&Bandwidth ) == DD_OK )
{
if( Bandwidth.dwYInterpAndColorkey <= 2000 )
{
this_lcl->dwFlags |= DDRAWIVPORT_COLORKEYANDINTERP;
}
}
}
}
}
else
{
this_lcl->dwNumAutoflip = dwTempNumAutoFlip;
this_lcl->dwNumVBIAutoflip = dwTempNumVBIAutoFlip;
if( lpInfo->dwVPFlags & DDVP_AUTOFLIP )
{
MemFree( this_lcl->lpFlipInts );
this_lcl->lpFlipInts = lpTempFlipInts;
}
return DDERR_UNSUPPORTED;
}
/*
* Notify kernel mode of the change
*/
#ifdef WIN95
UpdateKernelVideoPort( this_lcl, DDKMVP_UPDATE );
#endif
return DD_OK;
}
/*
* InternalStopVideo
*/
HRESULT InternalStopVideo( LPDDRAWI_DDVIDEOPORT_INT this_int )
{
LPDDHALVPORTCB_UPDATE pfn;
LPDDRAWI_DDVIDEOPORT_LCL this_lcl;
DDHAL_UPDATEVPORTDATA UpdateData;
DWORD dwTemp2;
DWORD dwTemp;
DWORD rc;
this_lcl = this_int->lpLcl;
if( !( this_lcl->dwFlags & DDRAWIVPORT_ON ) )
{
// VPORT is not on
return DD_OK;
}
/*
* Notify kernel mode of the change
*/
dwTemp2 = this_lcl->dwFlags;
this_lcl->dwFlags &= ~DDRAWIVPORT_ON;
dwTemp = this_lcl->ddvpInfo.dwVPFlags;
this_lcl->ddvpInfo.dwVPFlags &= ~DDVP_AUTOFLIP;
this_lcl->dwNumAutoflip = 0;
this_lcl->dwNumVBIAutoflip = 0;
#ifdef WIN95
UpdateKernelVideoPort( this_lcl, DDKMVP_UPDATE );
#endif
this_lcl->ddvpInfo.dwVPFlags = dwTemp;
this_lcl->dwFlags = dwTemp2;
pfn = this_lcl->lpDD->lpDDCB->HALDDVideoPort.UpdateVideoPort;
if( pfn != NULL )
{
/*
* Call the HAL
*/
memset( &UpdateData, 0, sizeof( UpdateData ) );
UpdateData.lpDD = this_lcl->lpDD;
UpdateData.lpVideoPort = this_lcl;
UpdateData.lpVideoInfo = &(this_lcl->ddvpInfo);
UpdateData.dwFlags = DDRAWI_VPORTSTOP;
UpdateData.dwNumAutoflip = 0;
UpdateData.dwNumVBIAutoflip = 0;
UpdateData.lplpDDSurface = NULL;
dwTemp = this_lcl->ddvpInfo.dwVPFlags;
this_lcl->ddvpInfo.dwVPFlags &= ~DDVP_AUTOFLIP;
DOHALCALL( UpdateVideoPort, pfn, UpdateData, rc, 0 );
if( DDHAL_DRIVER_HANDLED != rc )
{
this_lcl->ddvpInfo.dwVPFlags = dwTemp;
return DDERR_UNSUPPORTED;
}
else if( DD_OK != UpdateData.ddRVal )
{
this_lcl->ddvpInfo.dwVPFlags = dwTemp;
return UpdateData.ddRVal;
}
this_lcl->dwFlags &= ~DDRAWIVPORT_ON;
this_lcl->ddvpInfo.dwVPFlags = dwTemp;
}
else
{
return DDERR_UNSUPPORTED;
}
/*
* Update the surfaces and release implicit kernel handles.
*/
if( this_lcl->lpSurface != NULL )
{
ReleaseVPESurfaces( this_lcl->lpSurface, TRUE );
}
if( this_lcl->lpVBISurface != NULL )
{
ReleaseVPESurfaces( this_lcl->lpVBISurface, TRUE );
}
return DD_OK;
}
/*
* InternalUpdateVideo
*/
HRESULT InternalUpdateVideo(LPDDRAWI_DDVIDEOPORT_INT this_int,
LPDDVIDEOPORTINFO lpInfo )
{
LPDDHALVPORTCB_UPDATE pfn;
LPDDRAWI_DDVIDEOPORT_LCL this_lcl;
DDHAL_UPDATEVPORTDATA UpdateData;
LPDDRAWI_DDRAWSURFACE_INT *lpTempFlipInts;
LPDDVIDEOPORTCAPS lpAvailCaps;
DWORD dwTempNumAutoFlip;
DWORD dwTempNumVBIAutoFlip;
DWORD rc;
DWORD dwNumAutoFlip;
DWORD dwNumVBIAutoFlip;
DWORD dwTemp;
/*
* Validate the input parameters
*/
rc = ValidateVideoInfo( this_int, lpInfo, &dwNumAutoFlip, &dwNumVBIAutoFlip );
if( DD_OK != rc )
{
return rc;
}
this_lcl = this_int->lpLcl;
lpAvailCaps = &(this_lcl->lpDD->lpGbl->lpDDVideoPortCaps[this_lcl->ddvpDesc.dwVideoPortID]);
if( !( this_lcl->dwFlags & DDRAWIVPORT_ON ) )
{
// VPORT is not on - nothing to update
return DD_OK;
}
/*
* Setup the autoflip surfaces
*/
lpTempFlipInts = NULL;
if( lpInfo->dwVPFlags & DDVP_AUTOFLIP )
{
DWORD dwCnt;
lpTempFlipInts = this_lcl->lpFlipInts;
this_lcl->lpFlipInts = MemAlloc( sizeof( LPDDRAWI_DDRAWSURFACE_INT ) *
( dwNumAutoFlip + dwNumVBIAutoFlip ) );
if( NULL == this_lcl->lpFlipInts )
{
DPF_ERR( "insufficient memory" );
this_lcl->lpFlipInts = lpTempFlipInts;
return DDERR_OUTOFMEMORY;
}
/*
* Now put the surface INTs into the array.
*/
if( dwNumAutoFlip )
{
rc = FillFlipArray( this_lcl->lpFlipInts, this_lcl->lpSurface, &dwCnt );
if( rc != DD_OK )
{
MemFree( this_lcl->lpFlipInts );
this_lcl->lpFlipInts = lpTempFlipInts;
return rc;
}
DDASSERT( dwCnt == dwNumAutoFlip );
if( dwNumAutoFlip > lpAvailCaps->dwNumAutoFlipSurfaces )
{
DPF_ERR( "Too many autoflip surfaces" );
MemFree( this_lcl->lpFlipInts );
this_lcl->lpFlipInts = lpTempFlipInts;
return DDERR_INVALIDPARAMS;
}
}
/*
* Now put the VBI surface INTs into the array.
*/
if( dwNumVBIAutoFlip )
{
rc = FillFlipArray( &(this_lcl->lpFlipInts[dwNumAutoFlip]),
this_lcl->lpVBISurface, &dwCnt );
if( rc != DD_OK )
{
MemFree( this_lcl->lpFlipInts );
this_lcl->lpFlipInts = lpTempFlipInts;
return rc;
}
DDASSERT( dwCnt == dwNumVBIAutoFlip );
if( dwNumVBIAutoFlip > lpAvailCaps->dwNumVBIAutoFlipSurfaces )
{
DPF_ERR( "Too many VBI autoflip surfaces" );
MemFree( this_lcl->lpFlipInts );
return DDERR_INVALIDPARAMS;
}
}
}
dwTempNumAutoFlip = this_lcl->dwNumAutoflip;
dwTempNumVBIAutoFlip = this_lcl->dwNumVBIAutoflip;
this_lcl->dwNumAutoflip = dwNumAutoFlip;
this_lcl->dwNumVBIAutoflip = dwNumVBIAutoFlip;
/*
* The kernel interface may have switched from hardware autoflipping
* to software autoflipping w/o us knowing. We need to check for
* this.
*/
#ifdef WIN95
if( ( lpInfo->dwVPFlags & DDVP_AUTOFLIP ) &&
( this_lcl->dwFlags & DDRAWIVPORT_SOFTWARE_AUTOFLIP ) &&
( ( this_lcl->lpSurface != NULL ) || ( this_lcl->lpVBISurface != NULL ) ) )
{
DWORD dwState;
dwState = 0;
if( this_lcl->dwFlags & DDRAWIVPORT_VIDEOON )
{
GetKernelSurfaceState( this_lcl->lpSurface->lpLcl, &dwState );
}
else
{
GetKernelSurfaceState( this_lcl->lpVBISurface->lpLcl, &dwState );
}
if( dwState & DDSTATE_SOFTWARE_AUTOFLIP )
{
this_lcl->dwFlags |= DDRAWIVPORT_SOFTWARE_AUTOFLIP;
}
}
#endif
pfn = this_lcl->lpDD->lpDDCB->HALDDVideoPort.UpdateVideoPort;
if( pfn != NULL )
{
/*
* Call the HAL
*/
memset( &UpdateData, 0, sizeof( UpdateData ) );
UpdateData.lpDD = this_lcl->lpDD;
UpdateData.lpVideoPort = this_lcl;
UpdateData.lpVideoInfo = lpInfo;
UpdateData.dwFlags = DDRAWI_VPORTSTART;
if( dwNumAutoFlip && ( this_lcl->dwFlags & DDRAWIVPORT_VIDEOON ) )
{
UpdateData.lplpDDSurface = this_lcl->lpFlipInts;
UpdateData.dwNumAutoflip = dwNumAutoFlip;
}
else if( this_lcl->lpSurface && ( this_lcl->dwFlags & DDRAWIVPORT_VIDEOON ) )
{
UpdateData.lplpDDSurface = &(this_lcl->lpSurface);
}
else
{
UpdateData.lplpDDSurface = NULL;
}
if( dwNumVBIAutoFlip && ( this_lcl->dwFlags & DDRAWIVPORT_VBION ) )
{
UpdateData.lplpDDVBISurface =
&(this_lcl->lpFlipInts[this_lcl->dwNumAutoflip]);
UpdateData.dwNumVBIAutoflip = dwNumVBIAutoFlip;
}
else if( this_lcl->lpVBISurface && ( this_lcl->dwFlags & DDRAWIVPORT_VBION ) )
{
UpdateData.lplpDDVBISurface = &(this_lcl->lpVBISurface);
}
else
{
UpdateData.lplpDDVBISurface = NULL;
}
dwTemp = lpInfo->dwVPFlags;
if( this_lcl->dwFlags & DDRAWIVPORT_SOFTWARE_AUTOFLIP )
{
lpInfo->dwVPFlags &= ~DDVP_AUTOFLIP;
}
#ifdef WIN95
if( this_lcl->lpSurface != NULL )
{
OverrideVideoPort( this_lcl->lpSurface, &(lpInfo->dwVPFlags) );
}
#endif
DOHALCALL( UpdateVideoPort, pfn, UpdateData, rc, 0 );
if( DDHAL_DRIVER_HANDLED != rc )
{
lpInfo->dwVPFlags = dwTemp;
if( lpInfo->dwVPFlags & DDVP_AUTOFLIP )
{
MemFree( this_lcl->lpFlipInts );
this_lcl->lpFlipInts = lpTempFlipInts;
this_lcl->dwNumAutoflip = dwTempNumAutoFlip;
this_lcl->dwNumVBIAutoflip = dwTempNumVBIAutoFlip;
}
return DDERR_UNSUPPORTED;
}
else if( DD_OK != UpdateData.ddRVal )
{
/*
* If we failed due to hardware autoflipping, try again w/o
*/
if( ( lpInfo->dwVPFlags & DDVP_AUTOFLIP ) ||
CanSoftwareAutoflip( this_lcl ) )
{
lpInfo->dwVPFlags &= ~DDVP_AUTOFLIP;
DOHALCALL( UpdateVideoPort, pfn, UpdateData, rc, 0 );
if( ( DDHAL_DRIVER_HANDLED != rc ) &&
( DD_OK != UpdateData.ddRVal ) )
{
lpInfo->dwVPFlags = dwTemp;
MemFree( this_lcl->lpFlipInts );
this_lcl->lpFlipInts = lpTempFlipInts;
this_lcl->dwNumAutoflip = dwTempNumAutoFlip;
this_lcl->dwNumVBIAutoflip = dwTempNumVBIAutoFlip;
return UpdateData.ddRVal;
}
this_lcl->dwFlags |= DDRAWIVPORT_SOFTWARE_AUTOFLIP;
}
else
{
lpInfo->dwVPFlags = dwTemp;
if( lpInfo->dwVPFlags & DDVP_AUTOFLIP )
{
MemFree( this_lcl->lpFlipInts );
this_lcl->lpFlipInts = lpTempFlipInts;
this_lcl->dwNumAutoflip = dwTempNumAutoFlip;
this_lcl->dwNumVBIAutoflip = dwTempNumVBIAutoFlip;
}
return UpdateData.ddRVal;
}
}
MemFree( lpTempFlipInts );
lpTempFlipInts = NULL;
lpInfo->dwVPFlags = dwTemp;
/*
* If they are changing to or from autoflipping, we need to update
* the surfaces.
*/
if( ( dwNumAutoFlip > dwTempNumAutoFlip ) &&
( this_lcl->dwFlags & DDRAWIVPORT_VIDEOON ) )
{
DDASSERT( this_lcl->lpSurface != NULL );
PrepareVPESurfaces( this_lcl->lpSurface, this_lcl, TRUE );
}
if( ( dwNumVBIAutoFlip > dwTempNumVBIAutoFlip ) &&
( this_lcl->dwFlags & DDRAWIVPORT_VBION ) )
{
DDASSERT( this_lcl->lpVBISurface != NULL );
PrepareVPESurfaces( this_lcl->lpVBISurface, this_lcl, TRUE );
}
if( ( dwNumAutoFlip < dwTempNumAutoFlip ) &&
( this_lcl->dwFlags & DDRAWIVPORT_VIDEOON ) )
{
DDASSERT( this_lcl->lpSurface != NULL );
ReleaseVPESurfaces( this_lcl->lpSurface, FALSE );
PrepareVPESurfaces( this_lcl->lpSurface, this_lcl, FALSE );
}
if( ( dwNumVBIAutoFlip < dwTempNumVBIAutoFlip ) &&
( this_lcl->dwFlags & DDRAWIVPORT_VBION ) )
{
DDASSERT( this_lcl->lpVBISurface != NULL );
ReleaseVPESurfaces( this_lcl->lpVBISurface, FALSE );
PrepareVPESurfaces( this_lcl->lpVBISurface, this_lcl, FALSE );
}
UpdateInterleavedFlags( this_lcl, lpInfo->dwVPFlags );
memcpy( &(this_lcl->ddvpInfo), lpInfo, sizeof( DDVIDEOPORTINFO ) );
if( NULL != lpInfo->lpddpfInputFormat )
{
this_lcl->ddvpInfo.lpddpfInputFormat = (LPDDPIXELFORMAT)
((LPBYTE)this_lcl +
sizeof( DDRAWI_DDVIDEOPORT_LCL ) );
memcpy( this_lcl->ddvpInfo.lpddpfInputFormat,
lpInfo->lpddpfInputFormat, sizeof( DDPIXELFORMAT ) );
}
}
else
{
this_lcl->dwNumAutoflip = dwTempNumAutoFlip;
this_lcl->dwNumVBIAutoflip = dwTempNumVBIAutoFlip;
if( lpInfo->dwVPFlags & DDVP_AUTOFLIP )
{
MemFree( this_lcl->lpFlipInts );
this_lcl->lpFlipInts = lpTempFlipInts;
}
return DDERR_UNSUPPORTED;
}
/*
* Notify kernel mode of the change
*/
#ifdef WIN95
UpdateKernelVideoPort( this_lcl, DDKMVP_UPDATE );
#endif
return DD_OK;
}
/*
* DD_VP_StartVideo
*/
HRESULT DDAPI DD_VP_StartVideo(LPDIRECTDRAWVIDEOPORT lpDVP, LPDDVIDEOPORTINFO lpInfo )
{
LPDDRAWI_DDVIDEOPORT_INT this_int;
DDVIDEOPORTINFO TempInfo;
DWORD dwTempFlags;
DWORD rc;
ENTER_DDRAW();
DPF(2,A,"ENTERAPI: DD_VP_StartVideo");
/*
* Don't allow access to this function if called from within the
* the EnumVideoPort callback.
*/
if( bInEnumCallback )
{
DPF_ERR ( "This function cannot be called from within the EnumVideoPort callback!");
LEAVE_DDRAW();
return DDERR_CURRENTLYNOTAVAIL;
}
/*
* Validate parameters
*/
TRY
{
this_int = (LPDDRAWI_DDVIDEOPORT_INT) lpDVP;
if( !VALID_DDVIDEOPORT_PTR( this_int ) )
{
LEAVE_DDRAW();
return DDERR_INVALIDOBJECT;
}
if( (NULL == lpInfo) || !VALID_DDVIDEOPORTINFO_PTR( lpInfo ) )
{
LEAVE_DDRAW();
return DDERR_INVALIDPARAMS;
}
if( ( lpInfo->dwReserved1 != 0 ) ||
( lpInfo->dwReserved2 != 0 ) )
{
DPF_ERR( "Reserved field not set to zero" );
LEAVE_DDRAW();
return DDERR_INVALIDPARAMS;
}
if( this_int->dwFlags & DDVPCREATE_VBIONLY )
{
if( (NULL == lpInfo->lpddpfVBIInputFormat) ||
!VALID_DDPIXELFORMAT_PTR( lpInfo->lpddpfVBIInputFormat ) )
{
LEAVE_DDRAW();
return DDERR_INVALIDPARAMS;
}
}
else if( (NULL == lpInfo->lpddpfInputFormat) ||
!VALID_DDPIXELFORMAT_PTR( lpInfo->lpddpfInputFormat ) )
{
LEAVE_DDRAW();
return DDERR_INVALIDPARAMS;
}
}
EXCEPT( EXCEPTION_EXECUTE_HANDLER )
{
DPF_ERR( "Exception encountered validating parameters" );
LEAVE_DDRAW();
return DDERR_EXCEPTION;
}
dwTempFlags = this_int->lpLcl->dwFlags;
if( this_int->dwFlags )
{
rc = MergeVPInfo( this_int->lpLcl,
this_int->dwFlags & DDVPCREATE_VBIONLY ? lpInfo : this_int->lpLcl->lpVBIInfo,
this_int->dwFlags & DDVPCREATE_VIDEOONLY ? lpInfo : this_int->lpLcl->lpVideoInfo,
&TempInfo );
if( rc == DD_OK )
{
if( this_int->dwFlags & DDVPCREATE_VBIONLY )
{
this_int->lpLcl->dwFlags |= DDRAWIVPORT_VBION;
}
else
{
this_int->lpLcl->dwFlags |= DDRAWIVPORT_VIDEOON;
}
rc = InternalStartVideo( this_int, &TempInfo );
}
}
else
{
this_int->lpLcl->dwFlags |= DDRAWIVPORT_VIDEOON | DDRAWIVPORT_VBION;
rc = InternalStartVideo( this_int, lpInfo );
}
if( ( rc == DD_OK ) && this_int->dwFlags )
{
/*
* Save the original info
*/
if( this_int->dwFlags & DDVPCREATE_VBIONLY )
{
if( this_int->lpLcl->lpVBIInfo == NULL )
{
this_int->lpLcl->lpVBIInfo = MemAlloc( sizeof( TempInfo ) +
( 2 * sizeof( DDPIXELFORMAT)) );
}
if( this_int->lpLcl->lpVBIInfo != NULL )
{
memcpy( this_int->lpLcl->lpVBIInfo, lpInfo, sizeof( TempInfo ) );
this_int->lpLcl->lpVBIInfo->lpddpfVBIInputFormat = (LPDDPIXELFORMAT)
((LPBYTE)this_int->lpLcl->lpVBIInfo + sizeof( DDVIDEOPORTINFO ));
this_int->lpLcl->lpVBIInfo->lpddpfVBIOutputFormat = (LPDDPIXELFORMAT)
((LPBYTE)this_int->lpLcl->lpVBIInfo + sizeof( DDVIDEOPORTINFO ) +
sizeof( DDPIXELFORMAT ) );
memcpy( this_int->lpLcl->lpVBIInfo->lpddpfVBIInputFormat,
lpInfo->lpddpfVBIInputFormat, sizeof( DDPIXELFORMAT ) );
if( lpInfo->lpddpfVBIOutputFormat != NULL )
{
memcpy( this_int->lpLcl->lpVBIInfo->lpddpfVBIOutputFormat,
lpInfo->lpddpfVBIOutputFormat, sizeof( DDPIXELFORMAT ) );
}
}
}
else if( this_int->dwFlags & DDVPCREATE_VIDEOONLY )
{
if( this_int->lpLcl->lpVideoInfo == NULL )
{
this_int->lpLcl->lpVideoInfo = MemAlloc( sizeof( TempInfo ) );
}
if( this_int->lpLcl->lpVideoInfo != NULL )
{
memcpy( this_int->lpLcl->lpVideoInfo, lpInfo, sizeof( TempInfo ) );
this_int->lpLcl->lpVideoInfo->lpddpfInputFormat =
this_int->lpLcl->ddvpInfo.lpddpfInputFormat;
}
}
}
else if( rc != DD_OK )
{
this_int->lpLcl->dwFlags = dwTempFlags;
}
LEAVE_DDRAW();
return rc;
}
/*
* DD_VP_StopVideo
*/
HRESULT DDAPI DD_VP_StopVideo(LPDIRECTDRAWVIDEOPORT lpDVP )
{
LPDDRAWI_DDVIDEOPORT_INT this_int;
LPDDRAWI_DDVIDEOPORT_LCL this_lcl;
DDVIDEOPORTINFO TempInfo;
BOOL bChanged;
DWORD rc = DD_OK;
ENTER_DDRAW();
DPF(2,A,"ENTERAPI: DD_VP_StopVideo");
/*
* Don't allow access to this function if called from within the
* the EnumVideoPort callback.
*/
if( bInEnumCallback )
{
DPF_ERR ( "This function cannot be called from within the EnumVideoPort callback!");
LEAVE_DDRAW();
return DDERR_CURRENTLYNOTAVAIL;
}
/*
* Validate parameters
*/
TRY
{
this_int = (LPDDRAWI_DDVIDEOPORT_INT) lpDVP;
if( !VALID_DDVIDEOPORT_PTR( this_int ) )
{
LEAVE_DDRAW();
return DDERR_INVALIDOBJECT;
}
this_lcl = this_int->lpLcl;
}
EXCEPT( EXCEPTION_EXECUTE_HANDLER )
{
DPF_ERR( "Exception encountered validating parameters" );
LEAVE_DDRAW();
return DDERR_EXCEPTION;
}
/*
* Three special things are done for VBI/Video-only video ports:
* 1. Remove the lpVBI/VideoInfo reference so we know we are no
* longer on.
* 2. If the other interface is running, instead of stoping the
* video stream, we simply crop it out so the other stream can
* continue un-interrupted.
* 3. Release the kernel handles.
*/
if( this_int->dwFlags )
{
bChanged = FALSE;
if( this_int->dwFlags & DDVPCREATE_VBIONLY )
{
if( this_lcl->lpVBIInfo != NULL )
{
MemFree( this_lcl->lpVBIInfo );
this_lcl->lpVBIInfo = NULL;
bChanged = TRUE;
}
if( this_lcl->lpVBISurface != NULL )
{
ReleaseVPESurfaces( this_lcl->lpVBISurface, TRUE );
}
this_lcl->dwFlags &= ~DDRAWIVPORT_VBION;
}
else if( this_int->dwFlags & DDVPCREATE_VIDEOONLY )
{
if( this_lcl->lpVideoInfo != NULL )
{
MemFree( this_lcl->lpVideoInfo );
this_lcl->lpVideoInfo = NULL;
bChanged = TRUE;
}
if( this_lcl->lpSurface != NULL )
{
ReleaseVPESurfaces( this_lcl->lpSurface, TRUE );
}
this_lcl->dwFlags &= ~DDRAWIVPORT_VIDEOON;
}
if( bChanged && ( ( this_lcl->lpVideoInfo != NULL ) ||
( this_lcl->lpVBIInfo != NULL ) ) )
{
rc = MergeVPInfo( this_lcl,
this_lcl->lpVBIInfo,
this_lcl->lpVideoInfo,
&TempInfo );
if( rc == DD_OK )
{
rc = InternalUpdateVideo( this_int, &TempInfo );
}
}
else if( bChanged )
{
rc = InternalStopVideo( this_int );
}
}
else
{
this_lcl->dwFlags &= ~( DDRAWIVPORT_VIDEOON | DDRAWIVPORT_VBION );
rc = InternalStopVideo( this_int );
}
LEAVE_DDRAW();
return rc;
}
/*
* DD_VP_UpdateVideo
*/
HRESULT DDAPI DD_VP_UpdateVideo(LPDIRECTDRAWVIDEOPORT lpDVP, LPDDVIDEOPORTINFO lpInfo )
{
LPDDRAWI_DDVIDEOPORT_INT this_int;
DDVIDEOPORTINFO TempInfo;
DWORD rc;
ENTER_DDRAW();
DPF(2,A,"ENTERAPI: DD_VP_UpdateVideo");
/*
* Don't allow access to this function if called from within the
* the EnumVideoPort callback.
*/
if( bInEnumCallback )
{
DPF_ERR ( "This function cannot be called from within the EnumVideoPort callback!");
LEAVE_DDRAW();
return DDERR_CURRENTLYNOTAVAIL;
}
/*
* Validate parameters
*/
TRY
{
this_int = (LPDDRAWI_DDVIDEOPORT_INT) lpDVP;
if( !VALID_DDVIDEOPORT_PTR( this_int ) )
{
LEAVE_DDRAW();
return DDERR_INVALIDOBJECT;
}
if( (NULL == lpInfo) || !VALID_DDVIDEOPORTINFO_PTR( lpInfo ) )
{
LEAVE_DDRAW();
return DDERR_INVALIDPARAMS;
}
if( ( lpInfo->dwReserved1 != 0 ) ||
( lpInfo->dwReserved2 != 0 ) )
{
DPF_ERR( "Reserved field not set to zero" );
LEAVE_DDRAW();
return DDERR_INVALIDPARAMS;
}
if( this_int->dwFlags & DDVPCREATE_VBIONLY )
{
if( (NULL == lpInfo->lpddpfVBIInputFormat) ||
!VALID_DDPIXELFORMAT_PTR( lpInfo->lpddpfVBIInputFormat ) )
{
LEAVE_DDRAW();
return DDERR_INVALIDPARAMS;
}
}
else if( (NULL == lpInfo->lpddpfInputFormat) ||
!VALID_DDPIXELFORMAT_PTR( lpInfo->lpddpfInputFormat ) )
{
LEAVE_DDRAW();
return DDERR_INVALIDPARAMS;
}
}
EXCEPT( EXCEPTION_EXECUTE_HANDLER )
{
DPF_ERR( "Exception encountered validating parameters" );
LEAVE_DDRAW();
return DDERR_EXCEPTION;
}
if( this_int->dwFlags )
{
rc = MergeVPInfo( this_int->lpLcl,
this_int->dwFlags & DDVPCREATE_VBIONLY ? lpInfo : this_int->lpLcl->lpVBIInfo,
this_int->dwFlags & DDVPCREATE_VIDEOONLY ? lpInfo : this_int->lpLcl->lpVideoInfo,
&TempInfo );
if( rc == DD_OK )
{
rc = InternalUpdateVideo( this_int, &TempInfo );
}
}
else
{
rc = InternalUpdateVideo( this_int, lpInfo );
}
if( ( rc == DD_OK ) && this_int->dwFlags )
{
/*
* Save the original info
*/
if( this_int->dwFlags & DDVPCREATE_VBIONLY )
{
if( this_int->lpLcl->lpVBIInfo != NULL )
{
memcpy( this_int->lpLcl->lpVBIInfo, lpInfo, sizeof( TempInfo ) );
this_int->lpLcl->lpVBIInfo->lpddpfVBIInputFormat = (LPDDPIXELFORMAT)
((LPBYTE)this_int->lpLcl->lpVBIInfo + sizeof( DDVIDEOPORTINFO ));
this_int->lpLcl->lpVBIInfo->lpddpfVBIOutputFormat = (LPDDPIXELFORMAT)
((LPBYTE)this_int->lpLcl->lpVBIInfo + sizeof( DDVIDEOPORTINFO ) +
sizeof( DDPIXELFORMAT ) );
memcpy( this_int->lpLcl->lpVBIInfo->lpddpfVBIInputFormat,
lpInfo->lpddpfVBIInputFormat, sizeof( DDPIXELFORMAT ) );
if( lpInfo->lpddpfVBIOutputFormat != NULL )
{
memcpy( this_int->lpLcl->lpVBIInfo->lpddpfVBIOutputFormat,
lpInfo->lpddpfVBIOutputFormat, sizeof( DDPIXELFORMAT ) );
}
}
}
else if( this_int->dwFlags & DDVPCREATE_VIDEOONLY )
{
if( this_int->lpLcl->lpVideoInfo != NULL )
{
memcpy( this_int->lpLcl->lpVideoInfo, lpInfo, sizeof( TempInfo ) );
this_int->lpLcl->lpVideoInfo->lpddpfInputFormat =
this_int->lpLcl->ddvpInfo.lpddpfInputFormat;
}
}
}
LEAVE_DDRAW();
return rc;
}
/*
* DD_VP_WaitForSync
*/
HRESULT DDAPI DD_VP_WaitForSync(LPDIRECTDRAWVIDEOPORT lpDVP, DWORD dwFlags, DWORD dwLine, DWORD dwTimeOut )
{
LPDDHALVPORTCB_WAITFORSYNC pfn;
LPDDRAWI_DDVIDEOPORT_INT this_int;
LPDDRAWI_DDVIDEOPORT_LCL this_lcl;
DWORD rc;
DDHAL_WAITFORVPORTSYNCDATA WaitSyncData;
ENTER_DDRAW();
DPF(2,A,"ENTERAPI: DD_VP_WaitForSync");
/*
* Don't allow access to this function if called from within the
* the EnumVideoPort callback.
*/
if( bInEnumCallback )
{
DPF_ERR ( "This function cannot be called from within the EnumVideoPort callback!");
LEAVE_DDRAW();
return DDERR_CURRENTLYNOTAVAIL;
}
/*
* Validate parameters
*/
TRY
{
this_int = (LPDDRAWI_DDVIDEOPORT_INT) lpDVP;
if( !VALID_DDVIDEOPORT_PTR( this_int ) )
{
LEAVE_DDRAW();
return DDERR_INVALIDOBJECT;
}
this_lcl = this_int->lpLcl;
}
EXCEPT( EXCEPTION_EXECUTE_HANDLER )
{
DPF_ERR( "Exception encountered validating parameters" );
LEAVE_DDRAW();
return DDERR_EXCEPTION;
}
if( !dwFlags || ( dwFlags > 3 ) )
{
LEAVE_DDRAW();
return DDERR_INVALIDPARAMS;
}
pfn = this_lcl->lpDD->lpDDCB->HALDDVideoPort.WaitForVideoPortSync;
if( pfn != NULL )
{
WaitSyncData.lpDD = this_lcl->lpDD;
WaitSyncData.lpVideoPort = this_lcl;
WaitSyncData.dwFlags = dwFlags;
WaitSyncData.dwLine = dwLine;
if( dwTimeOut != 0 )
{
WaitSyncData.dwTimeOut = dwTimeOut;
}
else
{
WaitSyncData.dwTimeOut = this_lcl->ddvpDesc.dwMicrosecondsPerField * 3;
}
DOHALCALL( WaitForVideoPortSync, pfn, WaitSyncData, rc, 0 );
if( DDHAL_DRIVER_HANDLED != rc )
{
LEAVE_DDRAW();
return DDERR_UNSUPPORTED;
}
}
else
{
LEAVE_DDRAW();
return DDERR_UNSUPPORTED;
}
LEAVE_DDRAW();
return WaitSyncData.ddRVal;
}
/*
* DD_VP_GetSignalStatus
*/
HRESULT DDAPI DD_VP_GetSignalStatus(LPDIRECTDRAWVIDEOPORT lpDVP, LPDWORD lpdwStatus )
{
LPDDHALVPORTCB_GETSIGNALSTATUS pfn;
LPDDRAWI_DDVIDEOPORT_INT this_int;
LPDDRAWI_DDVIDEOPORT_LCL this_lcl;
DDHAL_GETVPORTSIGNALDATA GetSignalData;
DWORD rc;
ENTER_DDRAW();
DPF(2,A,"ENTERAPI: DD_VP_GetSignalStatus");
/*
* Don't allow access to this function if called from within the
* the EnumVideoPort callback.
*/
if( bInEnumCallback )
{
DPF_ERR ( "This function cannot be called from within the EnumVideoPort callback!");
LEAVE_DDRAW();
return DDERR_CURRENTLYNOTAVAIL;
}
/*
* Validate parameters
*/
TRY
{
this_int = (LPDDRAWI_DDVIDEOPORT_INT) lpDVP;
if( !VALID_DDVIDEOPORT_PTR( this_int ) )
{
LEAVE_DDRAW();
return DDERR_INVALIDOBJECT;
}
this_lcl = this_int->lpLcl;
if( (NULL == lpdwStatus ) || !VALID_DWORD_PTR( lpdwStatus ) )
{
LEAVE_DDRAW();
return DDERR_INVALIDPARAMS;
}
}
EXCEPT( EXCEPTION_EXECUTE_HANDLER )
{
DPF_ERR( "Exception encountered validating parameters" );
LEAVE_DDRAW();
return DDERR_EXCEPTION;
}
pfn = this_lcl->lpDD->lpDDCB->HALDDVideoPort.GetVideoSignalStatus;
if( pfn != NULL )
{
/*
* Call the HAL
*/
GetSignalData.lpDD = this_lcl->lpDD;
GetSignalData.lpVideoPort = this_lcl;
GetSignalData.dwStatus = DDVPSQ_NOSIGNAL; // Let the HAL tell us otherwise
DOHALCALL( GetVideoSignalStatus, pfn, GetSignalData, rc, 0 );
if( DDHAL_DRIVER_HANDLED != rc )
{
LEAVE_DDRAW();
return DDERR_UNSUPPORTED;
}
else if( DD_OK != GetSignalData.ddRVal )
{
LEAVE_DDRAW();
return GetSignalData.ddRVal;
}
}
else
{
LEAVE_DDRAW();
return DDERR_UNSUPPORTED;
}
*lpdwStatus = GetSignalData.dwStatus;
LEAVE_DDRAW();
return DD_OK;
}
/*
* DD_VP_GetColorControls
*/
HRESULT DDAPI DD_VP_GetColorControls(LPDIRECTDRAWVIDEOPORT lpDVP, LPDDCOLORCONTROL lpColor )
{
LPDDHALVPORTCB_COLORCONTROL pfn;
LPDDRAWI_DDVIDEOPORT_INT this_int;
LPDDRAWI_DDVIDEOPORT_LCL this_lcl;
DDHAL_VPORTCOLORDATA ColorData;
DWORD rc;
ENTER_DDRAW();
DPF(2,A,"ENTERAPI: DD_VP_GetColorControls");
/*
* Don't allow access to this function if called from within the
* the EnumVideoPort callback.
*/
if( bInEnumCallback )
{
DPF_ERR ( "This function cannot be called from within the EnumVideoPort callback!");
LEAVE_DDRAW();
return DDERR_CURRENTLYNOTAVAIL;
}
/*
* Validate parameters
*/
TRY
{
this_int = (LPDDRAWI_DDVIDEOPORT_INT) lpDVP;
if( !VALID_DDVIDEOPORT_PTR( this_int ) )
{
LEAVE_DDRAW();
return DDERR_INVALIDOBJECT;
}
this_lcl = this_int->lpLcl;
if( (NULL == lpColor ) || !VALID_DDCOLORCONTROL_PTR( lpColor ) )
{
LEAVE_DDRAW();
return DDERR_INVALIDPARAMS;
}
if( this_int->dwFlags & DDVPCREATE_VBIONLY )
{
DPF_ERR( "Unable to set color controls on a VBI-only video port" );
LEAVE_DDRAW();
return DDERR_UNSUPPORTED;
}
}
EXCEPT( EXCEPTION_EXECUTE_HANDLER )
{
DPF_ERR( "Exception encountered validating parameters" );
LEAVE_DDRAW();
return DDERR_EXCEPTION;
}
pfn = this_lcl->lpDD->lpDDCB->HALDDVideoPort.ColorControl;
if( pfn != NULL )
{
/*
* Call the HAL
*/
ColorData.lpDD = this_lcl->lpDD;
ColorData.lpVideoPort = this_lcl;
ColorData.dwFlags = DDRAWI_VPORTGETCOLOR;
ColorData.lpColorData = lpColor;
DOHALCALL( VideoColorControl, pfn, ColorData, rc, 0 );
if( DDHAL_DRIVER_HANDLED != rc )
{
LEAVE_DDRAW();
return DDERR_UNSUPPORTED;
}
else if( DD_OK != ColorData.ddRVal )
{
LEAVE_DDRAW();
return ColorData.ddRVal;
}
}
else
{
LEAVE_DDRAW();
return DDERR_UNSUPPORTED;
}
LEAVE_DDRAW();
return DD_OK;
}
/*
* DD_VP_SetColorControls
*/
HRESULT DDAPI DD_VP_SetColorControls(LPDIRECTDRAWVIDEOPORT lpDVP, LPDDCOLORCONTROL lpColor )
{
LPDDHALVPORTCB_COLORCONTROL pfn;
LPDDRAWI_DDVIDEOPORT_INT this_int;
LPDDRAWI_DDVIDEOPORT_LCL this_lcl;
DDHAL_VPORTCOLORDATA ColorData;
DWORD rc;
ENTER_DDRAW();
DPF(2,A,"ENTERAPI: DD_VP_SetColorControls");
/*
* Don't allow access to this function if called from within the
* the EnumVideoPort callback.
*/
if( bInEnumCallback )
{
DPF_ERR ( "This function cannot be called from within the EnumVideoPort callback!");
LEAVE_DDRAW();
return DDERR_CURRENTLYNOTAVAIL;
}
/*
* Validate parameters
*/
TRY
{
this_int = (LPDDRAWI_DDVIDEOPORT_INT) lpDVP;
if( !VALID_DDVIDEOPORT_PTR( this_int ) )
{
LEAVE_DDRAW();
return DDERR_INVALIDOBJECT;
}
this_lcl = this_int->lpLcl;
if( (NULL == lpColor ) || !VALID_DDCOLORCONTROL_PTR( lpColor ) )
{
LEAVE_DDRAW();
return DDERR_INVALIDPARAMS;
}
if( this_int->dwFlags & DDVPCREATE_VBIONLY )
{
DPF_ERR( "Unable to set color controls on a VBI-only video port" );
LEAVE_DDRAW();
return DDERR_UNSUPPORTED;
}
}
EXCEPT( EXCEPTION_EXECUTE_HANDLER )
{
DPF_ERR( "Exception encountered validating parameters" );
LEAVE_DDRAW();
return DDERR_EXCEPTION;
}
pfn = this_lcl->lpDD->lpDDCB->HALDDVideoPort.ColorControl;
if( pfn != NULL )
{
/*
* Call the HAL
*/
ColorData.lpDD = this_lcl->lpDD;
ColorData.lpVideoPort = this_lcl;
ColorData.dwFlags = DDRAWI_VPORTSETCOLOR;
ColorData.lpColorData = lpColor;
DOHALCALL( VideoColorControl, pfn, ColorData, rc, 0 );
if( DDHAL_DRIVER_HANDLED != rc )
{
LEAVE_DDRAW();
return DDERR_UNSUPPORTED;
}
else if( DD_OK != ColorData.ddRVal )
{
LEAVE_DDRAW();
return ColorData.ddRVal;
}
}
else
{
LEAVE_DDRAW();
return DDERR_UNSUPPORTED;
}
LEAVE_DDRAW();
return DD_OK;
}
/*
* GetSurfaceFormat
*
* Fills in the DDPIXELFORMAT structure with the surface's format
*/
LPDDPIXELFORMAT GetSurfaceFormat( LPDDRAWI_DDRAWSURFACE_LCL surf_lcl )
{
if( surf_lcl->dwFlags & DDRAWISURF_HASPIXELFORMAT )
{
return &(surf_lcl->lpGbl->ddpfSurface);
}
else
{
return &(surf_lcl->lpSurfMore->lpDD_lcl->lpGbl->vmiData.ddpfDisplay);
}
return NULL;
}
/*
* CreateVideoPortNotify
*/
HRESULT CreateVideoPortNotify( LPDDRAWI_DDVIDEOPORT_INT lpDDVPInt, LPDIRECTDRAWVIDEOPORTNOTIFY *lplpVPNotify )
{
#ifdef WINNT
OSVERSIONINFOEX osvi;
DWORDLONG dwlConditionMask = 0;
LPDDRAWI_DDVIDEOPORT_INT lpInt;
#endif
*lplpVPNotify = NULL;
#ifdef WIN95
// This is available on Win9X
return DDERR_UNSUPPORTED;
#else
// This is only available on whistler
ZeroMemory(&osvi, sizeof(OSVERSIONINFOEX));
osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX);
osvi.dwMajorVersion = 5;
osvi.dwMinorVersion = 1;
VER_SET_CONDITION( dwlConditionMask, VER_MAJORVERSION,
VER_GREATER_EQUAL );
VER_SET_CONDITION( dwlConditionMask, VER_MINORVERSION,
VER_GREATER_EQUAL );
if (!VerifyVersionInfo(&osvi, VER_MAJORVERSION|VER_MINORVERSION, dwlConditionMask))
{
return DDERR_UNSUPPORTED;
}
// Only one notification interface can be active at any time for a single
// video port
if (lpDDVPInt->lpLcl->lpVPNotify != NULL)
{
DPF_ERR("A IDirectDrawVideoPortNotify interface already exists for this video port");
return DDERR_CURRENTLYNOTAVAIL;
}
lpInt = MemAlloc(sizeof(DDRAWI_DDVIDEOPORT_INT));
if (lpInt == NULL)
{
return DDERR_OUTOFMEMORY;
}
lpInt->lpVtbl = (LPVOID)&ddVideoPortNotifyCallbacks;
lpInt->lpLcl = lpDDVPInt->lpLcl;
lpInt->dwFlags = DDVPCREATE_NOTIFY | lpDDVPInt->dwFlags;
DD_VP_AddRef( (LPDIRECTDRAWVIDEOPORT )lpInt );
*lplpVPNotify = (LPDIRECTDRAWVIDEOPORTNOTIFY) lpInt;
lpInt->lpLink = lpDDVPInt->lpLcl->lpDD->lpGbl->dvpList;
lpDDVPInt->lpLcl->lpDD->lpGbl->dvpList = lpInt;
#endif
return DD_OK;
}
/*
* DDAPI DD_VP_Notify_AcquireNotification
*/
HRESULT DDAPI DD_VP_Notify_AcquireNotification( LPDIRECTDRAWVIDEOPORTNOTIFY lpNotify, HANDLE* pEvent, LPDDVIDEOPORTNOTIFY pBuffer )
{
LPDDRAWI_DDVIDEOPORT_INT this_int;
LPDDRAWI_DDVIDEOPORT_LCL this_lcl;
HRESULT rc;
ENTER_DDRAW();
DPF(2,A,"ENTERAPI: DD_VP_Notify_AcquireNotification");
/*
* Validate parameters
*/
TRY
{
this_int = (LPDDRAWI_DDVIDEOPORT_INT) lpNotify;
if( !VALID_DDVIDEOPORT_PTR( this_int ) )
{
LEAVE_DDRAW();
return DDERR_INVALIDOBJECT;
}
this_lcl = this_int->lpLcl;
if( (pBuffer == NULL) || !VALID_DDVIDEOPORTNOTIFY_PTR( pBuffer ) )
{
DPF_ERR( "Invalid LPDDVIDEOPORTNOTIFY specified" );
LEAVE_DDRAW();
return DDERR_INVALIDPARAMS;
}
if( (pEvent == NULL) || !VALID_HANDLE_PTR( pEvent ) )
{
DPF_ERR( "Invalid event handle ptr specified" );
LEAVE_DDRAW();
return DDERR_INVALIDPARAMS;
}
}
EXCEPT( EXCEPTION_EXECUTE_HANDLER )
{
DPF_ERR( "Exception encountered validating parameters" );
LEAVE_DDRAW();
return DDERR_EXCEPTION;
}
*pEvent = NULL;
rc = DDERR_UNSUPPORTED;
#ifdef WINNT
this_lcl->lpDD->lpGbl->lpDDCBtmp->HALDDVPE2.AcquireNotification(this_lcl, pEvent, pBuffer);
if (*pEvent != NULL)
{
rc = DD_OK;
}
#endif
LEAVE_DDRAW();
return rc;
}
/*
* DDAPI DD_VP_Notify_AcquireNotification
*/
HRESULT DDAPI DD_VP_Notify_ReleaseNotification( LPDIRECTDRAWVIDEOPORTNOTIFY lpNotify, HANDLE pEvent )
{
LPDDRAWI_DDVIDEOPORT_INT this_int;
LPDDRAWI_DDVIDEOPORT_LCL this_lcl;
ENTER_DDRAW();
DPF(2,A,"ENTERAPI: DD_VP_Notify_ReleaseNotification");
/*
* Validate parameters
*/
TRY
{
this_int = (LPDDRAWI_DDVIDEOPORT_INT) lpNotify;
if( !VALID_DDVIDEOPORT_PTR( this_int ) )
{
LEAVE_DDRAW();
return DDERR_INVALIDOBJECT;
}
this_lcl = this_int->lpLcl;
}
EXCEPT( EXCEPTION_EXECUTE_HANDLER )
{
DPF_ERR( "Exception encountered validating parameters" );
LEAVE_DDRAW();
return DDERR_EXCEPTION;
}
#ifdef WINNT
this_lcl->lpDD->lpGbl->lpDDCBtmp->HALDDVPE2.ReleaseNotification(this_lcl, pEvent);
#endif
LEAVE_DDRAW();
return DD_OK;
}
/*
* ProcessVideoPortCleanup
*
* A process is done, clean up any videoports that it may have locked.
*
* NOTE: we enter with a lock taken on the DIRECTDRAW object.
*/
void ProcessVideoPortCleanup( LPDDRAWI_DIRECTDRAW_GBL pdrv, DWORD pid, LPDDRAWI_DIRECTDRAW_LCL pdrv_lcl )
{
LPDDRAWI_DDVIDEOPORT_INT pvport_int;
LPDDRAWI_DDVIDEOPORT_LCL pvport_lcl;
LPDDRAWI_DDVIDEOPORT_INT pvpnext_int;
DWORD rcnt;
ULONG rc;
DWORD vp_id;
/*
* run through all videoports owned by the driver object, and find ones
* that have been accessed by this process. If the pdrv_lcl parameter
* is non-null, only delete videoports created by that local driver object.
*/
pvport_int = pdrv->dvpList;
DPF( 4, "ProcessVideoPortCleanup" );
while( pvport_int != NULL )
{
pvport_lcl = pvport_int->lpLcl;
pvpnext_int = pvport_int->lpLink;
rc = 1;
if( pvport_int->dwFlags & DDVPCREATE_VBIONLY )
{
vp_id = pvport_lcl->dwVBIProcessID;
}
else
{
vp_id = pvport_lcl->dwProcessID;
}
if( ( vp_id == pid ) &&
( (NULL == pdrv_lcl) || (pvport_lcl->lpDD == pdrv_lcl) ) )
{
/*
* release the references by this process
*/
rcnt = pvport_int->dwIntRefCnt;
DPF( 5, "Process %08lx had %ld accesses to videoport %08lx", pid, rcnt, pvport_int );
while( rcnt > 0 )
{
DD_VP_Release( (LPDIRECTDRAWVIDEOPORT) pvport_int );
pvpnext_int = pdrv->dvpList;
if( rc == 0 )
{
break;
}
rcnt--;
}
}
else
{
DPF( 5, "Process %08lx had no accesses to videoport %08lx", pid, pvport_int );
}
pvport_int = pvpnext_int;
}
DPF( 4, "Leaving ProcessVideoPortCleanup");
} /* ProcessVideoPortCleanup */