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.
2517 lines
69 KiB
2517 lines
69 KiB
/*==========================================================================
|
|
*
|
|
* Copyright (C) 1994-1995 Microsoft Corporation. All Rights Reserved.
|
|
*
|
|
* File: ddsover.c
|
|
* Content: DirectDraw Surface overlay support:
|
|
* UpdateOverlay
|
|
* History:
|
|
* Date By Reason
|
|
* ==== == ======
|
|
* 27-jan-95 craige split out of ddsurf.c, enhanced
|
|
* 31-jan-95 craige and even more ongoing work...
|
|
* 03-feb-95 craige performance tuning, ongoing work
|
|
* 27-feb-95 craige new sync. macros
|
|
* 08-mar-95 craige new APIs: GetOverlayPosition, GetOverlayZOrder
|
|
* SetOverlayZOrder, SetOverlayPosition
|
|
* 19-mar-95 craige use HRESULTs
|
|
* 01-apr-95 craige happy fun joy updated header file
|
|
* 03-apr-95 craige made update overlay work again
|
|
* 06-may-95 craige use driver-level csects only
|
|
* 14-may-95 craige cleaned out obsolete junk
|
|
* 15-may-95 kylej deleted GetOverlayZOrder, SetOverlayZOrder,
|
|
* InsertOverlayZOrder. Added UpdateOverlayZOrder
|
|
* and EnumOverlayZOrders.
|
|
* 17-jun-95 craige new surface structure
|
|
* 25-jun-95 craige one ddraw mutex
|
|
* 26-jun-95 craige reorganized surface structure
|
|
* 28-jun-95 craige ENTER_DDRAW at very start of fns; tweaks in UpdateOverlay;
|
|
* verify stretching; disabled alpha
|
|
* 30-jun-95 craige small bug fixes; verify rectangle alignment
|
|
* 04-jul-95 craige YEEHAW: new driver struct; SEH
|
|
* 10-jul-95 craige support Get/SetOverlayPosition
|
|
* 10-jul-95 kylej mirroring caps and flags
|
|
* 13-jul-95 craige changed Get/SetOverlayPosition to use LONG
|
|
* 31-jul-95 craige validate flags
|
|
* 19-aug-95 davidmay don't check rectangles when hiding overlay
|
|
* 10-dec-95 colinmc added execute buffer support
|
|
* 02-jan-96 kylej handle new interface structs
|
|
* 12-feb-96 colinmc surface lost flag moved from global to local object
|
|
* 23-apr-96 kylej use dwMinOverlayStretch and dwMaxOverlayStretch
|
|
* validate that entire dest rect is in overlayed surface
|
|
* 29-jan-97 smac Removed old ring 0 code
|
|
* 03-mar-97 smac Added kernel mode interface
|
|
* 19-nov-98 jvanaken Overlays with alpha blending
|
|
*
|
|
***************************************************************************/
|
|
#include "ddrawpr.h"
|
|
|
|
#undef DPF_MODNAME
|
|
#define DPF_MODNAME "UpdateOverlay"
|
|
|
|
/*
|
|
* checkOverlayStretching
|
|
*
|
|
* check and see if we can stretch or not
|
|
*/
|
|
HRESULT checkOverlayStretching(
|
|
LPDDRAWI_DIRECTDRAW_GBL pdrv,
|
|
DWORD dest_height,
|
|
DWORD dest_width,
|
|
DWORD src_height,
|
|
DWORD src_width,
|
|
DWORD src_caps,
|
|
BOOL emulate )
|
|
{
|
|
DWORD caps;
|
|
DWORD basecaps;
|
|
BOOL fail;
|
|
DWORD dwMinStretch;
|
|
DWORD dwMaxStretch;
|
|
|
|
fail = FALSE;
|
|
|
|
if( emulate )
|
|
{
|
|
basecaps = pdrv->ddHELCaps.dwCaps;
|
|
caps = pdrv->ddHELCaps.dwFXCaps;
|
|
if( src_caps & DDSCAPS_LIVEVIDEO )
|
|
{
|
|
dwMinStretch = pdrv->ddHELCaps.dwMinLiveVideoStretch;
|
|
dwMaxStretch = pdrv->ddHELCaps.dwMaxLiveVideoStretch;
|
|
}
|
|
else if( src_caps & DDSCAPS_HWCODEC )
|
|
{
|
|
dwMinStretch = pdrv->ddHELCaps.dwMinHwCodecStretch;
|
|
dwMaxStretch = pdrv->ddHELCaps.dwMaxHwCodecStretch;
|
|
}
|
|
else
|
|
{
|
|
dwMinStretch = pdrv->ddHELCaps.dwMinOverlayStretch;
|
|
dwMaxStretch = pdrv->ddHELCaps.dwMaxOverlayStretch;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
basecaps = pdrv->ddCaps.dwCaps;
|
|
caps = pdrv->ddCaps.dwFXCaps;
|
|
if( src_caps & DDSCAPS_LIVEVIDEO )
|
|
{
|
|
dwMinStretch = pdrv->ddCaps.dwMinLiveVideoStretch;
|
|
dwMaxStretch = pdrv->ddCaps.dwMaxLiveVideoStretch;
|
|
}
|
|
else if( src_caps & DDSCAPS_HWCODEC )
|
|
{
|
|
dwMinStretch = pdrv->ddCaps.dwMinHwCodecStretch;
|
|
dwMaxStretch = pdrv->ddCaps.dwMaxHwCodecStretch;
|
|
}
|
|
else
|
|
{
|
|
dwMinStretch = pdrv->ddCaps.dwMinOverlayStretch;
|
|
dwMaxStretch = pdrv->ddCaps.dwMaxOverlayStretch;
|
|
}
|
|
}
|
|
|
|
/*
|
|
* Check against dwMinOverlayStretch
|
|
*/
|
|
if( src_width*dwMinStretch > dest_width*1000 )
|
|
{
|
|
return DDERR_INVALIDPARAMS;
|
|
}
|
|
|
|
/*
|
|
* Check against dwMaxOverlayStretch
|
|
*/
|
|
if( (dwMaxStretch != 0) && (src_width*dwMaxStretch < dest_width*1000) )
|
|
{
|
|
return DDERR_INVALIDPARAMS;
|
|
}
|
|
|
|
|
|
if( (src_height == dest_height) && (src_width == dest_width) )
|
|
{
|
|
// not stretching.
|
|
return DD_OK;
|
|
}
|
|
|
|
/*
|
|
* If we are here, we must be trying to stretch.
|
|
* can we even stretch at all?
|
|
*/
|
|
if( !(basecaps & DDCAPS_OVERLAYSTRETCH))
|
|
{
|
|
return DDERR_NOSTRETCHHW;
|
|
}
|
|
|
|
/*
|
|
* verify height
|
|
*/
|
|
if( src_height != dest_height )
|
|
{
|
|
if( src_height > dest_height )
|
|
{
|
|
/*
|
|
* can we shrink Y arbitrarily?
|
|
*/
|
|
if( !(caps & DDFXCAPS_OVERLAYSHRINKY) )
|
|
{
|
|
/*
|
|
* see if this is a non-integer shrink
|
|
*/
|
|
if( (src_height % dest_height) != 0 )
|
|
{
|
|
return DDERR_NOSTRETCHHW;
|
|
/*
|
|
* see if we can integer shrink
|
|
*/
|
|
}
|
|
else if( !(caps & DDFXCAPS_OVERLAYSHRINKYN) )
|
|
{
|
|
return DDERR_NOSTRETCHHW;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if( !(caps & DDFXCAPS_OVERLAYSTRETCHY) )
|
|
{
|
|
/*
|
|
* see if this is a non-integer stretch
|
|
*/
|
|
if( (dest_height % src_height) != 0 )
|
|
{
|
|
return DDERR_NOSTRETCHHW;
|
|
/*
|
|
* see if we can integer stretch
|
|
*/
|
|
}
|
|
else if( !(caps & DDFXCAPS_OVERLAYSTRETCHYN) )
|
|
{
|
|
return DDERR_NOSTRETCHHW;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/*
|
|
* verify width
|
|
*/
|
|
if( src_width != dest_width )
|
|
{
|
|
if( src_width > dest_width )
|
|
{
|
|
if( !(caps & DDFXCAPS_OVERLAYSHRINKX) )
|
|
{
|
|
/*
|
|
* see if this is a non-integer shrink
|
|
*/
|
|
if( (src_width % dest_width) != 0 )
|
|
{
|
|
return DDERR_NOSTRETCHHW;
|
|
/*
|
|
* see if we can integer shrink
|
|
*/
|
|
}
|
|
else if( !(caps & DDFXCAPS_OVERLAYSHRINKXN) )
|
|
{
|
|
return DDERR_NOSTRETCHHW;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if( !(caps & DDFXCAPS_OVERLAYSTRETCHX) )
|
|
{
|
|
/*
|
|
* see if this is a non-integer stretch
|
|
*/
|
|
if( (dest_width % src_width) != 0 )
|
|
{
|
|
return DDERR_NOSTRETCHHW;
|
|
}
|
|
if( !(caps & DDFXCAPS_OVERLAYSTRETCHXN) )
|
|
{
|
|
return DDERR_NOSTRETCHHW;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return DD_OK;
|
|
|
|
} /* checkOverlayStretching */
|
|
|
|
/*
|
|
* checkOverlayFlags
|
|
*/
|
|
static HRESULT checkOverlayFlags(
|
|
LPDDRAWI_DIRECTDRAW_GBL pdrv,
|
|
LPDWORD lpdwFlags,
|
|
LPDDRAWI_DDRAWSURFACE_INT this_src_int,
|
|
LPDDRAWI_DDRAWSURFACE_LCL this_dest_lcl,
|
|
LPDDHAL_UPDATEOVERLAYDATA puod,
|
|
LPDDOVERLAYFX lpDDOverlayFX,
|
|
BOOL emulate )
|
|
{
|
|
LPDDRAWI_DDRAWSURFACE_LCL this_src_lcl;
|
|
DWORD basecaps;
|
|
DWORD baseckeycaps;
|
|
DWORD dwFlags;
|
|
|
|
this_src_lcl = this_src_int->lpLcl;
|
|
dwFlags= * lpdwFlags;
|
|
|
|
if( emulate )
|
|
{
|
|
basecaps = pdrv->ddHELCaps.dwCaps;
|
|
baseckeycaps = pdrv->ddHELCaps.dwCKeyCaps;
|
|
}
|
|
else
|
|
{
|
|
basecaps = pdrv->ddCaps.dwCaps;
|
|
baseckeycaps = pdrv->ddCaps.dwCKeyCaps;
|
|
}
|
|
|
|
/*
|
|
* Handle auto-flipping
|
|
*/
|
|
if( dwFlags & DDOVER_AUTOFLIP )
|
|
{
|
|
DWORD rc;
|
|
|
|
rc = IsValidAutoFlipSurface( this_src_int );
|
|
if( rc == IVAS_NOAUTOFLIPPING )
|
|
{
|
|
DPF_ERR( "AUTOFLIPPING not valid" );
|
|
return DDERR_INVALIDPARAMS;
|
|
}
|
|
else if( rc == IVAS_SOFTWAREAUTOFLIPPING )
|
|
{
|
|
/*
|
|
* Software autoflipping only
|
|
*/
|
|
this_src_lcl->lpGbl->dwGlobalFlags |= DDRAWISURFGBL_SOFTWAREAUTOFLIP;
|
|
}
|
|
}
|
|
|
|
/*
|
|
* Handle bob
|
|
*/
|
|
if( dwFlags & DDOVER_BOB )
|
|
{
|
|
/*
|
|
* Fail if bob caps not specified
|
|
*/
|
|
if( dwFlags & DDOVER_INTERLEAVED )
|
|
{
|
|
if( !( pdrv->ddCaps.dwCaps2 & DDCAPS2_CANBOBINTERLEAVED ) )
|
|
{
|
|
DPF_ERR( "Device doesn't support DDOVER_BOB while interleaved!" );
|
|
return DDERR_INVALIDPARAMS;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if( !( pdrv->ddCaps.dwCaps2 & DDCAPS2_CANBOBNONINTERLEAVED ) )
|
|
{
|
|
DPF_ERR( "Device doesn't support DDOVER_BOB!" );
|
|
return DDERR_INVALIDPARAMS;
|
|
}
|
|
}
|
|
|
|
/*
|
|
* Is the surface fed by a video port?
|
|
*/
|
|
if( ( this_src_lcl->ddsCaps.dwCaps & DDSCAPS_VIDEOPORT ) &&
|
|
( this_src_lcl->lpSurfMore->lpVideoPort != NULL ) )
|
|
{
|
|
/*
|
|
* Yes - fail (at least for DX5) if they are bobbing and not
|
|
* autofliiping. This is because this support is broken in DX5.
|
|
*/
|
|
if( !( dwFlags & ( DDOVER_AUTOFLIP | DDOVER_INTERLEAVED ) ) )
|
|
{
|
|
DPF_ERR( "DDOVER_BOB specified without autoflip or interleaved!" );
|
|
return DDERR_INVALIDPARAMS;
|
|
}
|
|
if( MustSoftwareBob( this_src_int ) )
|
|
{
|
|
dwFlags &= ~DDOVER_BOBHARDWARE;
|
|
}
|
|
else
|
|
{
|
|
dwFlags |= DDOVER_BOBHARDWARE;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
/*
|
|
* Don't allow non-VPE clients to use bob unless the
|
|
* driver can handle it.
|
|
*/
|
|
if( !( pdrv->ddCaps.dwCaps2 & DDCAPS2_CANFLIPODDEVEN ) )
|
|
{
|
|
DPF_ERR( "Device does not support DDCAPS2_CANFLIPODDEVEN" );
|
|
return DDERR_INVALIDPARAMS;
|
|
}
|
|
if( dwFlags & DDOVER_BOBHARDWARE )
|
|
{
|
|
DPF_ERR( "DDOVER_BOBHARDWARE only valid when used with a video port" );
|
|
return DDERR_INVALIDPARAMS;
|
|
}
|
|
}
|
|
}
|
|
else if( dwFlags & DDOVER_BOBHARDWARE )
|
|
{
|
|
DPF_ERR( "DDOVER_BOBHARDWARE specified w/o DDOVER_BOB" );
|
|
return DDERR_INVALIDPARAMS;
|
|
}
|
|
|
|
/*
|
|
* ALPHA DISABLED FOR REV 1
|
|
*/
|
|
#pragma message( REMIND( "Alpha disabled for rev 1" ) )
|
|
#ifdef USE_ALPHA
|
|
/*
|
|
* verify alpha
|
|
*/
|
|
if( dwFlags & DDOVER_ANYALPHA )
|
|
{
|
|
/*
|
|
* dest
|
|
*/
|
|
if( dwFlags & DDOVER_ALPHADEST )
|
|
{
|
|
if( dwFlags & (DDOVER_ALPHASRC |
|
|
DDOVER_ALPHADESTCONSTOVERRIDE |
|
|
DDOVER_ALPHADESTSURFACEOVERRIDE) )
|
|
{
|
|
DPF_ERR( "ALPHADEST and other alpha sources specified" );
|
|
return DDERR_INVALIDPARAMS;
|
|
}
|
|
psurf_lcl = FindAttached( this_dest_lcl, DDSCAPS_ALPHA );
|
|
if( psurf_lcl == NULL )
|
|
{
|
|
DPF_ERR( "ALPHADEST requires an attached alpha to the dest" );
|
|
return DDERR_INVALIDPARAMS;
|
|
}
|
|
psurf = psurf_lcl->lpGbl;
|
|
dwFlags &= ~DDOVER_ALPHADEST;
|
|
dwFlags |= DDOVER_ALPHADESTSURFACEOVERRIDE;
|
|
puod->overlayFX.lpDDSAlphaDest = (LPDIRECTDRAWSURFACE) psurf;
|
|
}
|
|
else if( dwFlags & DDOVER_ALPHADESTCONSTOVERRIDE )
|
|
{
|
|
if( dwFlags & ( DDOVER_ALPHADESTSURFACEOVERRIDE) )
|
|
{
|
|
DPF_ERR( "ALPHADESTCONSTOVERRIDE and other alpha sources specified" );
|
|
return DDERR_INVALIDPARAMS;
|
|
}
|
|
puod->overlayFX.dwConstAlphaDestBitDepth =
|
|
lpDDOverlayFX->dwConstAlphaDestBitDepth;
|
|
puod->overlayFX.dwConstAlphaDest = lpDDOverlayFX->dwConstAlphaDest;
|
|
}
|
|
else if( dwFlags & DDOVER_ALPHADESTSURFACEOVERRIDE )
|
|
{
|
|
psurf_lcl = (LPDDRAWI_DDRAWSURFACE_LCL) lpDDOverlayFX->lpDDSAlphaDest;
|
|
if( !VALID_DIRECTDRAWSURFACE_PTR( psurf_lcl ) )
|
|
{
|
|
DPF_ERR( "ALPHASURFACEOVERRIDE requires surface ptr" );
|
|
return DDERR_INVALIDPARAMS;
|
|
}
|
|
psurf = psurf_lcl->lpGbl;
|
|
if( SURFACE_LOST( psurf_lcl ) )
|
|
{
|
|
return DDERR_SURFACELOST;
|
|
}
|
|
puod->overlayFX.lpDDSAlphaDest = (LPDIRECTDRAWSURFACE) psurf;
|
|
}
|
|
|
|
/*
|
|
* source
|
|
*/
|
|
if( dwFlags & DDOVER_ALPHASRC )
|
|
{
|
|
if( dwFlags & (DDOVER_ALPHASRC |
|
|
DDOVER_ALPHASRCCONSTOVERRIDE |
|
|
DDOVER_ALPHASRCSURFACEOVERRIDE) )
|
|
{
|
|
DPF_ERR( "ALPHASRC and other alpha sources specified" );
|
|
return DDERR_INVALIDPARAMS;
|
|
}
|
|
psurf_lcl = FindAttached( this_dest_lcl, DDSCAPS_ALPHA );
|
|
if( psurf_lcl == NULL )
|
|
{
|
|
DPF_ERR( "ALPHASRC requires an attached alpha to the dest" );
|
|
return DDERR_INVALIDPARAMS;
|
|
}
|
|
psurf = psurf_lcl->lpGbl;
|
|
dwFlags &= ~DDOVER_ALPHASRC;
|
|
dwFlags |= DDOVER_ALPHASRCSURFACEOVERRIDE;
|
|
puod->overlayFX.lpDDSAlphaSrc = (LPDIRECTDRAWSURFACE) psurf;
|
|
}
|
|
else if( dwFlags & DDOVER_ALPHASRCCONSTOVERRIDE )
|
|
{
|
|
if( dwFlags & ( DDOVER_ALPHASRCSURFACEOVERRIDE) )
|
|
{
|
|
DPF_ERR( "ALPHASRCCONSTOVERRIDE and other alpha sources specified" );
|
|
return DDERR_INVALIDPARAMS;
|
|
}
|
|
puod->overlayFX.dwConstAlphaSrcBitDepth =
|
|
lpDDOverlayFX->dwConstAlphaSrcBitDepth;
|
|
puod->overlayFX.dwConstAlphaSrc = lpDDOverlayFX->dwConstAlphaSrc;
|
|
}
|
|
else if( dwFlags & DDOVER_ALPHASRCSURFACEOVERRIDE )
|
|
{
|
|
psurf_lcl = (LPDDRAWI_DDRAWSURFACE_LCL) lpDDOverlayFX->lpDDSAlphaSrc;
|
|
if( !VALID_DIRECTDRAWSURFACE_PTR( psurf_lcl ) )
|
|
{
|
|
DPF_ERR( "ALPHASURFACEOVERRIDE requires surface ptr" );
|
|
return DDERR_INVALIDPARAMS;
|
|
}
|
|
psurf = psurf_lcl->lpGbl;
|
|
if( SURFACE_LOST( psurf_lcl ) )
|
|
{
|
|
return DDERR_SURFACELOST;
|
|
}
|
|
puod->overlayFX.lpDDSAlphaSrc = (LPDIRECTDRAWSURFACE) psurf;
|
|
}
|
|
}
|
|
#endif
|
|
|
|
/*
|
|
* verify color key overrides
|
|
*/
|
|
if( dwFlags & (DDOVER_KEYSRCOVERRIDE|DDOVER_KEYDESTOVERRIDE) )
|
|
{
|
|
if( !(basecaps & DDCAPS_COLORKEY) )
|
|
{
|
|
DPF_ERR( "KEYOVERRIDE specified, colorkey not supported" );
|
|
return DDERR_NOCOLORKEYHW;
|
|
}
|
|
if( dwFlags & DDOVER_KEYSRCOVERRIDE )
|
|
{
|
|
if( !(baseckeycaps & DDCKEYCAPS_SRCOVERLAY) )
|
|
{
|
|
DPF_ERR( "KEYSRCOVERRIDE specified, not supported" );
|
|
return DDERR_NOCOLORKEYHW;
|
|
}
|
|
puod->overlayFX.dckSrcColorkey = lpDDOverlayFX->dckSrcColorkey;
|
|
}
|
|
if( dwFlags & DDOVER_KEYDESTOVERRIDE )
|
|
{
|
|
if( !(baseckeycaps & DDCKEYCAPS_DESTOVERLAY) )
|
|
{
|
|
DPF_ERR( "KEYDESTOVERRIDE specified, not supported" );
|
|
return DDERR_NOCOLORKEYHW;
|
|
}
|
|
puod->overlayFX.dckDestColorkey = lpDDOverlayFX->dckDestColorkey;
|
|
}
|
|
}
|
|
|
|
/*
|
|
* verify src color key
|
|
*/
|
|
if( dwFlags & DDOVER_KEYSRC )
|
|
{
|
|
if( dwFlags & DDOVER_KEYSRCOVERRIDE )
|
|
{
|
|
DPF_ERR( "KEYSRC specified with KEYSRCOVERRIDE" );
|
|
return DDERR_INVALIDPARAMS;
|
|
}
|
|
if( !(this_src_lcl->dwFlags & DDRAWISURF_HASCKEYSRCOVERLAY) )
|
|
{
|
|
DPF_ERR( "KEYSRC specified, but no color key" );
|
|
return DDERR_INVALIDPARAMS;
|
|
}
|
|
puod->overlayFX.dckSrcColorkey = this_src_lcl->ddckCKSrcOverlay;
|
|
dwFlags &= ~DDOVER_KEYSRC;
|
|
dwFlags |= DDOVER_KEYSRCOVERRIDE;
|
|
}
|
|
|
|
/*
|
|
* verify dest color key
|
|
*/
|
|
if( dwFlags & DDOVER_KEYDEST )
|
|
{
|
|
if( dwFlags & DDOVER_KEYDESTOVERRIDE )
|
|
{
|
|
DPF_ERR( "KEYDEST specified with KEYDESTOVERRIDE" );
|
|
return DDERR_INVALIDPARAMS;
|
|
}
|
|
if( !(this_dest_lcl->dwFlags & DDRAWISURF_HASCKEYDESTOVERLAY) )
|
|
{
|
|
DPF_ERR( "KEYDEST specified, but no color key" );
|
|
return DDERR_INVALIDPARAMS;
|
|
}
|
|
puod->overlayFX.dckDestColorkey = this_dest_lcl->ddckCKDestOverlay;
|
|
dwFlags &= ~DDOVER_KEYDEST;
|
|
dwFlags |= DDOVER_KEYDESTOVERRIDE;
|
|
}
|
|
|
|
*lpdwFlags = dwFlags;
|
|
return DD_OK;
|
|
|
|
} /* checkOverlayFlags */
|
|
|
|
/*
|
|
* flags we need to call checkOverlayFlags for
|
|
*/
|
|
#define FLAGS_TO_CHECK \
|
|
(DDOVER_KEYSRCOVERRIDE| DDOVER_KEYDESTOVERRIDE | \
|
|
DDOVER_KEYSRC | DDOVER_KEYDEST | DDOVER_OVERRIDEBOBWEAVE | \
|
|
DDOVER_AUTOFLIP | DDOVER_BOB )
|
|
|
|
|
|
/*
|
|
* Return a pointer to the DDPIXELFORMAT structure that
|
|
* describes the specified surface's pixel format.
|
|
*/
|
|
static DWORD getPixelFormatFlags(LPDDRAWI_DDRAWSURFACE_LCL surf_lcl)
|
|
{
|
|
if (surf_lcl->dwFlags & DDRAWISURF_HASPIXELFORMAT)
|
|
{
|
|
// surface contains explicitly defined pixel format
|
|
return surf_lcl->lpGbl->ddpfSurface.dwFlags;
|
|
}
|
|
|
|
// surface's pixel format is implicit -- same as primary's
|
|
return surf_lcl->lpSurfMore->lpDD_lcl->lpGbl->vmiData.ddpfDisplay.dwFlags;
|
|
|
|
} /* getPixelFormatFlags */
|
|
|
|
#if 0
|
|
/*
|
|
* checkOverlayAlpha -- See if we can do specified alpha-blending operation.
|
|
*/
|
|
static HRESULT checkOverlayAlpha(
|
|
LPDDRAWI_DIRECTDRAW_GBL pdrv,
|
|
LPDWORD lpdwFlags,
|
|
LPDDRAWI_DDRAWSURFACE_LCL src_surf_lcl,
|
|
LPDDHAL_UPDATEOVERLAYDATA puod,
|
|
LPDDOVERLAYFX lpDDOverlayFX,
|
|
BOOL emulate )
|
|
{
|
|
DDARGB argb = { 255, 255, 255, 255 };
|
|
DWORD fxcaps = 0;
|
|
DWORD alphacaps = 0;
|
|
DWORD pfflags = getPixelFormatFlags(src_surf_lcl);
|
|
DWORD dwFlags = *lpdwFlags;
|
|
|
|
if( emulate )
|
|
{
|
|
fxcaps = pdrv->ddHELCaps.dwFXCaps;
|
|
if (pdrv->lpddHELMoreCaps)
|
|
{
|
|
alphacaps = pdrv->lpddHELMoreCaps->dwAlphaCaps;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
fxcaps = pdrv->ddCaps.dwFXCaps;
|
|
if (pdrv->lpddMoreCaps)
|
|
{
|
|
alphacaps = pdrv->lpddMoreCaps->dwAlphaCaps;
|
|
}
|
|
}
|
|
|
|
// Is any type of alpha blending required for this overlay?
|
|
if (!(pfflags & DDPF_ALPHAPIXELS) && !(dwFlags & DDOVER_ARGBSCALEFACTORS))
|
|
{
|
|
return DD_OK; // no alpha blending is needed
|
|
}
|
|
|
|
// Yes, verify that the driver supports alpha blending.
|
|
if (!(fxcaps & DDFXCAPS_OVERLAYALPHA))
|
|
{
|
|
DPF_ERR("Driver can't do alpha blending on overlays");
|
|
return DDERR_NOALPHAHW;
|
|
}
|
|
|
|
// Is dest color keying also enabled for this overlay?
|
|
if ((dwFlags & (DDOVER_KEYDEST | DDOVER_KEYDESTOVERRIDE)) &&
|
|
!(alphacaps &DDALPHACAPS_OVERLAYALPHAANDKEYDEST))
|
|
{
|
|
DPF_ERR("Driver can't do alpha blending and dest color key on same overlay");
|
|
return DDERR_UNSUPPORTED;
|
|
}
|
|
|
|
// Get ARGB scaling factors from DDOVERLAYFX structure.
|
|
*(LPDWORD)&argb = ~0; // default = ARGB scaling disabled (all ones)
|
|
if (dwFlags & DDOVER_ARGBSCALEFACTORS)
|
|
{
|
|
if( !(*lpdwFlags & DDOVER_DDFX) )
|
|
{
|
|
DPF_ERR("Must specify DDOVER_DDFX with DDOVER_ARGBSCALEFACTORS");
|
|
return DDERR_INVALIDPARAMS;
|
|
}
|
|
argb = lpDDOverlayFX->ddargbScaleFactors; // ARGB scaling enabled
|
|
}
|
|
|
|
// Does the source surface have an alpha channel?
|
|
if (pfflags & DDPF_ALPHAPIXELS)
|
|
{
|
|
/*
|
|
* Yes, verify that the driver can handle an alpha channel.
|
|
* (This check is a bit redundant since the driver has already blessed
|
|
* the format of this overlay surface by allowing it to be created.)
|
|
*/
|
|
if (!(alphacaps & DDALPHACAPS_OVERLAYALPHAPIXELS))
|
|
{
|
|
DPF_ERR("Driver can't handle source surface's alpha channel");
|
|
return DDERR_NOALPHAHW;
|
|
}
|
|
|
|
// Ignore source color key flags if source has alpha channel.
|
|
if (dwFlags & (DDOVER_KEYSRC | DDOVER_KEYSRCOVERRIDE))
|
|
{
|
|
*lpdwFlags &= ~(DDOVER_KEYSRC | DDOVER_KEYSRCOVERRIDE);
|
|
}
|
|
|
|
/*
|
|
* Are we asking the driver to handle both ARGB scaling and
|
|
* an alpha channel when it can't do both at the same time?
|
|
*/
|
|
if (*(LPDWORD)&argb != ~0 &&
|
|
!(alphacaps & DDALPHACAPS_OVERLAYALPHAANDARGBSCALING))
|
|
{
|
|
if (!(dwFlags & DDOVER_DEGRADEARGBSCALING))
|
|
{
|
|
DPF_ERR("Driver can't handle alpha channel and ARGB scaling at same time");
|
|
return DDERR_INVALIDPARAMS;
|
|
}
|
|
// We're allowed to degrade ARGB scaling, so turn it off.
|
|
*(LPDWORD)&argb = ~0;
|
|
}
|
|
|
|
/*
|
|
* Are color components in pixel format premultiplied by the
|
|
* alpha component or not? In either case, verify that the
|
|
* driver supports the specified alpha format.
|
|
*/
|
|
if (pfflags & DDPF_ALPHAPREMULT)
|
|
{
|
|
// Source pixel format uses premultiplied alpha.
|
|
if (!(alphacaps & DDALPHACAPS_OVERLAYPREMULT))
|
|
{
|
|
DPF_ERR("No driver support for premultiplied alpha");
|
|
return DDERR_NOALPHAHW;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// Source pixel format uses NON-premultiplied alpha.
|
|
if (!(alphacaps & DDALPHACAPS_OVERLAYNONPREMULT))
|
|
{
|
|
DPF_ERR("No driver support for non-premultiplied alpha");
|
|
return DDERR_NOALPHAHW;
|
|
}
|
|
|
|
/*
|
|
* We allow only one-factor ARGB scaling with a source surface
|
|
* that has a non-premultiplied alpha pixel format.
|
|
* The following code enforces this rule.
|
|
*/
|
|
if (*(LPDWORD)&argb != ~0)
|
|
{
|
|
// ARGB scaling is enabled. Check for one-factor scaling.
|
|
DWORD val = 0x01010101UL*argb.alpha;
|
|
|
|
if (*(LPDWORD)&argb != val)
|
|
{
|
|
// Uh-oh. This is NOT one-factor ARGB scaling.
|
|
if (!(dwFlags & DDABLT_DEGRADEARGBSCALING))
|
|
{
|
|
DPF_ERR("Can't do 2- or 4-mult ARGB scaling if source has non-premultiplied alpha");
|
|
return DDERR_INVALIDPARAMS;
|
|
}
|
|
// We're allowed to degrade to one-factor scaling.
|
|
*(LPDWORD)&argb = val;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// Is ARGB scaling is enabled?
|
|
if (*(LPDWORD)&argb != ~0UL)
|
|
{
|
|
// Yes, ARGB scaling is enabled. Is DEGRADESCALEFACTORS flag set?
|
|
if (dwFlags & DDOVER_DEGRADEARGBSCALING)
|
|
{
|
|
/*
|
|
* Yes, if necessary, we are permitted to degrade the ARGB
|
|
* scaling factors to values the driver can handle.
|
|
*/
|
|
if (!(alphacaps & (DDALPHACAPS_OVERLAYARGBSCALE1F |
|
|
DDALPHACAPS_OVERLAYARGBSCALE2F |
|
|
DDALPHACAPS_OVERLAYARGBSCALE4F)))
|
|
{
|
|
/*
|
|
* Driver can't do any kind of ARGB scaling at all, so just
|
|
* disable ARGB scaling by setting all four factors to 255.
|
|
*/
|
|
*(LPDWORD)&argb = ~0UL;
|
|
}
|
|
else if (!(alphacaps & (DDALPHACAPS_OVERLAYARGBSCALE2F |
|
|
DDALPHACAPS_OVERLAYARGBSCALE4F)))
|
|
{
|
|
/*
|
|
* The driver can do only one-factor ARGB scaling, so set the
|
|
* three color factors to the same value as the alpha factor.
|
|
*/
|
|
*(LPDWORD)&argb = 0x01010101UL*argb.alpha;
|
|
}
|
|
else if (!(alphacaps & DDALPHACAPS_OVERLAYARGBSCALE4F))
|
|
{
|
|
/*
|
|
* Driver can do only 2-factor ARGB scaling, so make sure
|
|
* all three color factors are set to the same value.
|
|
*/
|
|
if ((argb.red != argb.green) || (argb.red != argb.blue))
|
|
{
|
|
/*
|
|
* Set all three color factors to value "fact", which is the
|
|
* weighted average of their specified values (Fr,Fg,Fb):
|
|
* fact = .299*Fr + .587*Fg + .114*Fb
|
|
*/
|
|
DWORD fact = 19595UL*argb.red + 38470UL*argb.green +
|
|
7471UL*argb.blue;
|
|
|
|
argb.red =
|
|
argb.green =
|
|
argb.blue = (BYTE)(fact >> 16);
|
|
}
|
|
}
|
|
/*
|
|
* Does driver use saturated arithmetic to do alpha blending?
|
|
*/
|
|
if (!(alphacaps & DDALPHACAPS_OVERLAYSATURATE))
|
|
{
|
|
/*
|
|
* The driver can't do saturated arithmetic, so ensure that none
|
|
* of the color factors exceeds the value of the alpha factor.
|
|
*/
|
|
if (argb.red > argb.alpha)
|
|
{
|
|
argb.red = argb.alpha;
|
|
}
|
|
if (argb.green > argb.alpha)
|
|
{
|
|
argb.green = argb.alpha;
|
|
}
|
|
if (argb.blue > argb.alpha)
|
|
{
|
|
argb.blue = argb.alpha;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
/*
|
|
* We are not permitted to degrade the ARGB scaling factors, so if
|
|
* the driver can't handle them as specified, the call must fail.
|
|
* We permit a color factor to be larger than the alpha factor
|
|
* only if the hardware uses saturated arithmetic. (Otherwise, we
|
|
* would risk integer overflow when we calculate the color values.)
|
|
*/
|
|
if (!(alphacaps & DDALPHACAPS_OVERLAYSATURATE) &&
|
|
((argb.red > argb.alpha) || (argb.green > argb.alpha) ||
|
|
(argb.blue > argb.alpha)))
|
|
{
|
|
DPF_ERR("Driver can't handle specified ARGB scaling factors");
|
|
return DDERR_NOALPHAHW;
|
|
}
|
|
|
|
// Can the driver handle any ARGB scaling at all?
|
|
if (!(alphacaps & (DDALPHACAPS_OVERLAYARGBSCALE1F |
|
|
DDALPHACAPS_OVERLAYARGBSCALE2F |
|
|
DDALPHACAPS_OVERLAYARGBSCALE4F)))
|
|
{
|
|
DPF_ERR("Driver can't handle any ARGB scaling at all");
|
|
return DDERR_NOALPHAHW;
|
|
}
|
|
|
|
if ((argb.red != argb.green) || (argb.red != argb.blue))
|
|
{
|
|
/*
|
|
* Driver must be capable of doing 4-factor ARGB scaling.
|
|
*/
|
|
if (!(alphacaps & DDALPHACAPS_OVERLAYARGBSCALE4F))
|
|
{
|
|
DPF_ERR("Driver can't handle 4-factor ARGB scaling");
|
|
return DDERR_NOALPHAHW;
|
|
}
|
|
}
|
|
else if (argb.red != argb.alpha)
|
|
{
|
|
/*
|
|
* Driver must be capable of doing 2-factor ARGB scaling.
|
|
*/
|
|
if (!(alphacaps & (DDALPHACAPS_OVERLAYARGBSCALE2F |
|
|
DDALPHACAPS_OVERLAYARGBSCALE4F)))
|
|
{
|
|
DPF_ERR("Driver can't handle 2-factor ARGB scaling");
|
|
return DDERR_NOALPHAHW;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
// Save any modifications made to values of ARGB scaling factors.
|
|
puod->overlayFX.ddargbScaleFactors = argb;
|
|
return DD_OK;
|
|
|
|
} /* checkOverlayAlpha */
|
|
#endif
|
|
|
|
/*
|
|
* checkOverlayEmulation
|
|
*/
|
|
__inline HRESULT checkOverlayEmulation(
|
|
LPDDRAWI_DIRECTDRAW_GBL pdrv,
|
|
LPDDRAWI_DDRAWSURFACE_LCL this_src_lcl,
|
|
LPDDRAWI_DDRAWSURFACE_LCL this_dest_lcl,
|
|
LPBOOL pemulation )
|
|
{
|
|
/*
|
|
* check if emulated or hardware
|
|
*/
|
|
if( (this_dest_lcl->ddsCaps.dwCaps & DDSCAPS_SYSTEMMEMORY) ||
|
|
(this_src_lcl->ddsCaps.dwCaps & DDSCAPS_SYSTEMMEMORY ) )
|
|
{
|
|
if( !(pdrv->ddHELCaps.dwCaps & DDCAPS_OVERLAY) )
|
|
{
|
|
DPF_ERR( "can't emulate overlays" );
|
|
return DDERR_UNSUPPORTED;
|
|
}
|
|
*pemulation = TRUE;
|
|
}
|
|
/*
|
|
* hardware overlays
|
|
*/
|
|
else
|
|
{
|
|
if( !(pdrv->ddCaps.dwCaps & DDCAPS_OVERLAY) )
|
|
{
|
|
DPF_ERR( "no hardware overlay support" );
|
|
return DDERR_NOOVERLAYHW;
|
|
}
|
|
*pemulation = FALSE;
|
|
}
|
|
return DD_OK;
|
|
|
|
} /* checkOverlayEmulation */
|
|
|
|
#ifdef WIN95
|
|
/*
|
|
* WillCauseOverlayArtifacts
|
|
*
|
|
* There is a latency between the time Update overlay is called and all of
|
|
* the kernel mode surfaces structures are updated. If UpdateOverlay
|
|
* updates the src pointer and an autoflip occurs before the kernel surface
|
|
* data gets updated, it will cause a very visble jump. This function tries
|
|
* to determine when this is the case so we can work around it by temporarily
|
|
* disabling the video.
|
|
*/
|
|
BOOL WillCauseOverlayArtifacts( LPDDRAWI_DDRAWSURFACE_LCL this_src_lcl,
|
|
LPDDHAL_UPDATEOVERLAYDATA lpHALData )
|
|
{
|
|
if( ( this_src_lcl->ddsCaps.dwCaps & DDSCAPS_VISIBLE ) &&
|
|
!( lpHALData->dwFlags & DDOVER_HIDE ) &&
|
|
( ( lpHALData->rSrc.left != this_src_lcl->rcOverlaySrc.left ) ||
|
|
( lpHALData->rSrc.top != this_src_lcl->rcOverlaySrc.top ) ) )
|
|
{
|
|
return TRUE;
|
|
}
|
|
return FALSE;
|
|
}
|
|
#endif
|
|
|
|
/*
|
|
* DD_Surface_UpdateOverlay
|
|
*/
|
|
HRESULT DDAPI DD_Surface_UpdateOverlay(
|
|
LPDIRECTDRAWSURFACE lpDDSrcSurface,
|
|
LPRECT lpSrcRect,
|
|
LPDIRECTDRAWSURFACE lpDDDestSurface,
|
|
LPRECT lpDestRect,
|
|
DWORD dwFlags,
|
|
LPDDOVERLAYFX lpDDOverlayFX )
|
|
{
|
|
DWORD rc;
|
|
DDHAL_UPDATEOVERLAYDATA uod;
|
|
LPDDRAWI_DDRAWSURFACE_INT this_src_int;
|
|
LPDDRAWI_DDRAWSURFACE_LCL this_src_lcl;
|
|
LPDDRAWI_DDRAWSURFACE_GBL this_src;
|
|
LPDDRAWI_DDRAWSURFACE_INT this_dest_int;
|
|
LPDDRAWI_DDRAWSURFACE_LCL this_dest_lcl;
|
|
LPDDRAWI_DDRAWSURFACE_GBL this_dest;
|
|
LPDDRAWI_DIRECTDRAW_LCL pdrv_lcl;
|
|
LPDDRAWI_DIRECTDRAW_GBL pdrv;
|
|
RECT rsrc;
|
|
RECT rdest;
|
|
BOOL emulation;
|
|
DWORD dest_width;
|
|
DWORD dest_height;
|
|
DWORD src_width;
|
|
DWORD src_height;
|
|
LPDDHALSURFCB_UPDATEOVERLAY uohalfn;
|
|
LPDDHALSURFCB_UPDATEOVERLAY uofn;
|
|
HRESULT ddrval;
|
|
#ifdef WIN95
|
|
BOOL bAutoflipDisabled;
|
|
#endif
|
|
|
|
ENTER_DDRAW();
|
|
|
|
DPF(2,A,"ENTERAPI: DD_Surface_UpdateOverlay");
|
|
|
|
/*
|
|
* validate parameters
|
|
*/
|
|
TRY
|
|
{
|
|
this_src_int = (LPDDRAWI_DDRAWSURFACE_INT) lpDDSrcSurface;
|
|
if( !VALID_DIRECTDRAWSURFACE_PTR( this_src_int ) )
|
|
{
|
|
LEAVE_DDRAW();
|
|
return DDERR_INVALIDOBJECT;
|
|
}
|
|
this_src_lcl = this_src_int->lpLcl;
|
|
this_src = this_src_lcl->lpGbl;
|
|
if( SURFACE_LOST( this_src_lcl ) )
|
|
{
|
|
LEAVE_DDRAW();
|
|
return DDERR_SURFACELOST;
|
|
}
|
|
this_dest_int = (LPDDRAWI_DDRAWSURFACE_INT) lpDDDestSurface;
|
|
if( !VALID_DIRECTDRAWSURFACE_PTR( this_dest_int ) )
|
|
{
|
|
LEAVE_DDRAW();
|
|
return DDERR_INVALIDOBJECT;
|
|
}
|
|
this_dest_lcl = this_dest_int->lpLcl;
|
|
this_dest = this_dest_lcl->lpGbl;
|
|
if( SURFACE_LOST( this_dest_lcl ) )
|
|
{
|
|
LEAVE_DDRAW();
|
|
return DDERR_SURFACELOST;
|
|
}
|
|
|
|
//
|
|
// For now, if either surface is optimized, quit
|
|
//
|
|
if ((this_src_lcl->ddsCaps.dwCaps & DDSCAPS_OPTIMIZED) ||
|
|
(this_dest_lcl->ddsCaps.dwCaps & DDSCAPS_OPTIMIZED))
|
|
{
|
|
DPF_ERR( "It is an optimized surface" );
|
|
LEAVE_DDRAW();
|
|
return DDERR_ISOPTIMIZEDSURFACE;
|
|
}
|
|
|
|
if( dwFlags & ~DDOVER_VALID )
|
|
{
|
|
DPF_ERR( "invalid flags" );
|
|
LEAVE_DDRAW();
|
|
return DDERR_INVALIDPARAMS;
|
|
}
|
|
|
|
if( lpDestRect != NULL )
|
|
{
|
|
if( !VALID_RECT_PTR( lpDestRect ) )
|
|
{
|
|
DPF_ERR( "invalid dest rect" );
|
|
LEAVE_DDRAW();
|
|
return DDERR_INVALIDRECT;
|
|
}
|
|
}
|
|
|
|
if( lpSrcRect != NULL )
|
|
{
|
|
if( !VALID_RECT_PTR( lpSrcRect ) )
|
|
{
|
|
DPF_ERR( "invalid src rect" );
|
|
LEAVE_DDRAW();
|
|
return DDERR_INVALIDRECT;
|
|
}
|
|
}
|
|
if( lpDDOverlayFX != NULL )
|
|
{
|
|
if( !VALID_DDOVERLAYFX_PTR( lpDDOverlayFX ) )
|
|
{
|
|
DPF_ERR( "invalid overlayfx" );
|
|
LEAVE_DDRAW();
|
|
return DDERR_INVALIDPARAMS;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if( dwFlags & DDOVER_DDFX )
|
|
{
|
|
DPF_ERR( "DDOVER_DDFX requires valid DDOverlayFX structure" );
|
|
LEAVE_DDRAW();
|
|
return DDERR_INVALIDPARAMS;
|
|
}
|
|
}
|
|
|
|
pdrv_lcl = this_dest_lcl->lpSurfMore->lpDD_lcl;
|
|
pdrv = pdrv_lcl->lpGbl;
|
|
|
|
/*
|
|
* make sure the source surface is an overlay surface
|
|
*/
|
|
if( !(this_src_lcl->ddsCaps.dwCaps & DDSCAPS_OVERLAY) )
|
|
{
|
|
DPF_ERR( "Source is not an overlay surface" );
|
|
LEAVE_DDRAW();
|
|
return DDERR_NOTAOVERLAYSURFACE;
|
|
}
|
|
|
|
/*
|
|
* make sure the destination is not an execute buffer
|
|
*/
|
|
if( this_dest_lcl->ddsCaps.dwCaps & DDSCAPS_EXECUTEBUFFER )
|
|
{
|
|
DPF_ERR( "Invalid surface type: cannot overlay" );
|
|
LEAVE_DDRAW();
|
|
return DDERR_INVALIDSURFACETYPE;
|
|
}
|
|
|
|
/*
|
|
* Make sure that both surfaces belong to the same device.
|
|
*/
|
|
if (this_src_lcl->lpSurfMore->lpDD_lcl->lpGbl != this_dest_lcl->lpSurfMore->lpDD_lcl->lpGbl)
|
|
{
|
|
DPF_ERR("Source and Destination surface must belong to the same device");
|
|
LEAVE_DDRAW();
|
|
return DDERR_DEVICEDOESNTOWNSURFACE;
|
|
}
|
|
|
|
/*
|
|
* check if emulated or not
|
|
*/
|
|
ddrval = checkOverlayEmulation( pdrv, this_src_lcl, this_dest_lcl, &emulation );
|
|
if( ddrval != DD_OK )
|
|
{
|
|
LEAVE_DDRAW();
|
|
return ddrval;
|
|
}
|
|
#ifdef TOOMUCHOVERLAYVALIDATION
|
|
/*
|
|
* check if showing/hiding
|
|
*/
|
|
if( dwFlags & DDOVER_SHOW )
|
|
{
|
|
if( this_src_lcl->ddsCaps.dwCaps & DDSCAPS_VISIBLE )
|
|
{
|
|
DPF_ERR( "Overlay already shown" );
|
|
LEAVE_DDRAW();
|
|
return DDERR_GENERIC;
|
|
}
|
|
}
|
|
else if ( dwFlags & DDOVER_HIDE )
|
|
{
|
|
if( !(this_src_lcl->ddsCaps.dwCaps & DDSCAPS_VISIBLE) )
|
|
{
|
|
DPF_ERR( "Overlay already hidden" );
|
|
LEAVE_DDRAW();
|
|
return DDERR_GENERIC;
|
|
}
|
|
}
|
|
#endif
|
|
|
|
/*
|
|
* set new rectangles if needed
|
|
*/
|
|
if( lpDestRect == NULL )
|
|
{
|
|
MAKE_SURF_RECT( this_dest, this_dest_lcl, rdest );
|
|
lpDestRect = &rdest;
|
|
}
|
|
if( lpSrcRect == NULL )
|
|
{
|
|
MAKE_SURF_RECT( this_src, this_src_lcl, rsrc );
|
|
lpSrcRect = &rsrc;
|
|
}
|
|
|
|
/*
|
|
* Check if ring 0 interface is overriding what the client
|
|
* tells us to do
|
|
*/
|
|
#ifdef WIN95
|
|
if( !( dwFlags & DDOVER_HIDE) )
|
|
{
|
|
OverrideOverlay( this_src_int, &dwFlags );
|
|
}
|
|
#endif
|
|
|
|
/*
|
|
* validate the rectangle dimensions
|
|
*/
|
|
dest_height = lpDestRect->bottom - lpDestRect->top;
|
|
dest_width = lpDestRect->right - lpDestRect->left;
|
|
if( ((int)dest_height <= 0) || ((int)dest_width <= 0) ||
|
|
((int)lpDestRect->top < 0) || ((int)lpDestRect->left < 0) ||
|
|
((DWORD) lpDestRect->bottom > (DWORD) this_dest->wHeight) ||
|
|
((DWORD) lpDestRect->right > (DWORD) this_dest->wWidth) )
|
|
{
|
|
DPF_ERR( "Invalid destination rect dimensions" );
|
|
LEAVE_DDRAW();
|
|
return DDERR_INVALIDRECT;
|
|
}
|
|
|
|
src_height = lpSrcRect->bottom - lpSrcRect->top;
|
|
src_width = lpSrcRect->right - lpSrcRect->left;
|
|
if( ((int)src_height <= 0) || ((int)src_width <= 0) ||
|
|
((int)lpSrcRect->top < 0) || ((int)lpSrcRect->left < 0) ||
|
|
((DWORD) lpSrcRect->bottom > (DWORD) this_src->wHeight) ||
|
|
((DWORD) lpSrcRect->right > (DWORD) this_src->wWidth) )
|
|
{
|
|
DPF_ERR( "Invalid source rect dimensions" );
|
|
LEAVE_DDRAW();
|
|
return DDERR_INVALIDRECT;
|
|
}
|
|
|
|
/*
|
|
* validate alignment
|
|
*/
|
|
if( !emulation )
|
|
{
|
|
if( pdrv->ddCaps.dwCaps & (DDCAPS_ALIGNBOUNDARYDEST |
|
|
DDCAPS_ALIGNSIZEDEST |
|
|
DDCAPS_ALIGNBOUNDARYSRC |
|
|
DDCAPS_ALIGNSIZESRC) )
|
|
{
|
|
if( pdrv->ddCaps.dwCaps & DDCAPS_ALIGNBOUNDARYDEST )
|
|
{
|
|
#if 0
|
|
/* GEE: I don't believe this code should be here
|
|
* only test alignment on width on height
|
|
*/
|
|
if( (lpDestRect->top % pdrv->ddCaps.dwAlignBoundaryDest) != 0 )
|
|
{
|
|
DPF_ERR( "Destination top is not aligned correctly" );
|
|
LEAVE_DDRAW();
|
|
return DDERR_YALIGN;
|
|
}
|
|
#endif
|
|
if( (lpDestRect->left % pdrv->ddCaps.dwAlignBoundaryDest) != 0 )
|
|
{
|
|
DPF_ERR( "Destination left is not aligned correctly" );
|
|
LEAVE_DDRAW();
|
|
return DDERR_XALIGN;
|
|
}
|
|
}
|
|
|
|
if( pdrv->ddCaps.dwCaps & DDCAPS_ALIGNBOUNDARYSRC )
|
|
{
|
|
#if 0
|
|
/* GEE: I don't believe this code should be here
|
|
* only test alignment on width on height
|
|
*/
|
|
if( (lpSrcRect->top % pdrv->ddCaps.dwAlignBoundarySrc) != 0 )
|
|
{
|
|
DPF_ERR( "Source top is not aligned correctly" );
|
|
LEAVE_DDRAW();
|
|
return DDERR_YALIGN;
|
|
}
|
|
#endif
|
|
if( (lpSrcRect->left % pdrv->ddCaps.dwAlignBoundarySrc) != 0 )
|
|
{
|
|
DPF_ERR( "Source left is not aligned correctly" );
|
|
LEAVE_DDRAW();
|
|
return DDERR_XALIGN;
|
|
}
|
|
}
|
|
|
|
if( pdrv->ddCaps.dwCaps & DDCAPS_ALIGNSIZEDEST )
|
|
{
|
|
if( (dest_width % pdrv->ddCaps.dwAlignSizeDest) != 0 )
|
|
{
|
|
DPF_ERR( "Destination width is not aligned correctly" );
|
|
LEAVE_DDRAW();
|
|
return DDERR_XALIGN;
|
|
}
|
|
#if 0
|
|
/* GEE: I don't believe this code should be here
|
|
* only test alignment for x axis
|
|
*/
|
|
if( (dest_height % pdrv->ddCaps.dwAlignSizeDest) != 0 )
|
|
{
|
|
DPF_ERR( "Destination height is not aligned correctly" );
|
|
LEAVE_DDRAW();
|
|
return DDERR_HEIGHTALIGN;
|
|
}
|
|
#endif
|
|
}
|
|
|
|
if( pdrv->ddCaps.dwCaps & DDCAPS_ALIGNSIZESRC )
|
|
{
|
|
if( (src_width % pdrv->ddCaps.dwAlignSizeSrc) != 0 )
|
|
{
|
|
DPF_ERR( "Source width is not aligned correctly" );
|
|
LEAVE_DDRAW();
|
|
return DDERR_XALIGN;
|
|
}
|
|
#if 0
|
|
/* GEE: I don't believe this code should be here
|
|
* only test alignment for x axis
|
|
*/
|
|
if( (src_height % pdrv->ddCaps.dwAlignSizeSrc) != 0 )
|
|
{
|
|
DPF_ERR( "Source height is not aligned correctly" );
|
|
LEAVE_DDRAW();
|
|
return DDERR_HEIGHTALIGN;
|
|
}
|
|
#endif
|
|
}
|
|
}
|
|
}
|
|
|
|
/*
|
|
* validate if stretching
|
|
*/
|
|
if( !( dwFlags & DDOVER_HIDE) )
|
|
{
|
|
ddrval = checkOverlayStretching( pdrv,
|
|
dest_height,
|
|
dest_width,
|
|
src_height,
|
|
src_width,
|
|
this_src_lcl->ddsCaps.dwCaps,
|
|
emulation );
|
|
if( ddrval != DD_OK )
|
|
{
|
|
LEAVE_DDRAW();
|
|
return ddrval;
|
|
}
|
|
}
|
|
|
|
/*
|
|
* If the surface has recieved data from a video port, we will
|
|
* set/clear the DDOVER_INTERLEAVED flag accordingly. This
|
|
* makes life a little easier on the HAL.
|
|
*/
|
|
if( ( this_src_lcl->ddsCaps.dwCaps & DDSCAPS_VIDEOPORT ) &&
|
|
( this_src_lcl->lpGbl->dwGlobalFlags & DDRAWISURFGBL_VPORTDATA ) )
|
|
{
|
|
if( this_src_lcl->lpGbl->dwGlobalFlags & DDRAWISURFGBL_VPORTINTERLEAVED )
|
|
{
|
|
dwFlags |= DDOVER_INTERLEAVED;
|
|
}
|
|
else
|
|
{
|
|
dwFlags &= ~DDOVER_INTERLEAVED;
|
|
}
|
|
}
|
|
|
|
#if 0
|
|
/*
|
|
* If any kind of alpha blending is requested, make sure the specified
|
|
* alpha parameters are correct and that the driver supports alpha blending.
|
|
* If source has alpha channel, this call clears source color-key flags.
|
|
*/
|
|
ddrval = checkOverlayAlpha( pdrv,
|
|
&dwFlags,
|
|
this_src_lcl,
|
|
&uod,
|
|
lpDDOverlayFX,
|
|
emulation );
|
|
if( ddrval != DD_OK )
|
|
{
|
|
LEAVE_DDRAW();
|
|
return ddrval;
|
|
}
|
|
#endif
|
|
/*
|
|
* any flags at all? if not, blow the whole thing off...
|
|
*/
|
|
uod.overlayFX.dwSize = sizeof( DDOVERLAYFX );
|
|
if( dwFlags & FLAGS_TO_CHECK )
|
|
{
|
|
ddrval = checkOverlayFlags( pdrv,
|
|
&dwFlags,
|
|
this_src_int,
|
|
this_dest_lcl,
|
|
&uod,
|
|
lpDDOverlayFX,
|
|
emulation );
|
|
if( ddrval != DD_OK )
|
|
{
|
|
LEAVE_DDRAW();
|
|
return ddrval;
|
|
}
|
|
}
|
|
|
|
// check for overlay mirroring capability
|
|
if( dwFlags & DDOVER_DDFX )
|
|
{
|
|
if( lpDDOverlayFX->dwDDFX & DDOVERFX_MIRRORLEFTRIGHT )
|
|
{
|
|
if( !( pdrv->ddBothCaps.dwFXCaps & DDFXCAPS_OVERLAYMIRRORLEFTRIGHT ) )
|
|
{
|
|
if( pdrv->ddHELCaps.dwFXCaps & DDFXCAPS_OVERLAYMIRRORLEFTRIGHT )
|
|
{
|
|
emulation = TRUE;
|
|
}
|
|
}
|
|
}
|
|
if( lpDDOverlayFX->dwDDFX & DDOVERFX_MIRRORUPDOWN )
|
|
{
|
|
if( !( pdrv->ddBothCaps.dwFXCaps & DDFXCAPS_OVERLAYMIRRORUPDOWN ) )
|
|
{
|
|
if( pdrv->ddHELCaps.dwFXCaps & DDFXCAPS_OVERLAYMIRRORUPDOWN )
|
|
{
|
|
emulation = TRUE;
|
|
}
|
|
}
|
|
}
|
|
uod.overlayFX.dwDDFX = lpDDOverlayFX->dwDDFX;
|
|
// deinterlacing is a hint - if not supported by hardware, mask it off
|
|
if ( lpDDOverlayFX->dwDDFX & DDOVERFX_DEINTERLACE )
|
|
{
|
|
if ( !( pdrv->ddCaps.dwFXCaps & DDFXCAPS_OVERLAYDEINTERLACE ) )
|
|
{
|
|
uod.overlayFX.dwDDFX &= ~DDOVERFX_DEINTERLACE;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
/*
|
|
* pick fns to use
|
|
*/
|
|
if( emulation )
|
|
{
|
|
uofn = pdrv_lcl->lpDDCB->HELDDSurface.UpdateOverlay;
|
|
uohalfn = uofn;
|
|
}
|
|
else
|
|
{
|
|
uofn = pdrv_lcl->lpDDCB->HALDDSurface.UpdateOverlay;
|
|
uohalfn = pdrv_lcl->lpDDCB->cbDDSurfaceCallbacks.UpdateOverlay;
|
|
}
|
|
|
|
}
|
|
EXCEPT( EXCEPTION_EXECUTE_HANDLER )
|
|
{
|
|
DPF_ERR( "Exception encountered validating parameters" );
|
|
LEAVE_DDRAW();
|
|
return DDERR_INVALIDPARAMS;
|
|
}
|
|
|
|
/*
|
|
* call the driver
|
|
*/
|
|
#ifdef WIN95
|
|
bAutoflipDisabled = FALSE;
|
|
#endif
|
|
if( uohalfn != NULL )
|
|
{
|
|
BOOL original_visible;
|
|
|
|
// Set the visible flag according to the show and hide bits
|
|
// If the HAL call fails, restore the visible bit to its original
|
|
// state. The HEL uses the DDSCAPS_VISIBLE bit to determine
|
|
// whether or not to display the overlay.
|
|
if( this_src_lcl->ddsCaps.dwCaps & DDSCAPS_VISIBLE )
|
|
{
|
|
original_visible = TRUE;
|
|
}
|
|
else
|
|
{
|
|
original_visible = FALSE;
|
|
}
|
|
if( dwFlags & DDOVER_SHOW )
|
|
{
|
|
this_src_lcl->ddsCaps.dwCaps |= DDSCAPS_VISIBLE;
|
|
}
|
|
else if ( dwFlags & DDOVER_HIDE )
|
|
{
|
|
this_src_lcl->ddsCaps.dwCaps &= ~DDSCAPS_VISIBLE;
|
|
}
|
|
|
|
|
|
uod.UpdateOverlay = uohalfn;
|
|
uod.lpDD = pdrv;
|
|
uod.lpDDSrcSurface = this_src_lcl;
|
|
uod.lpDDDestSurface = this_dest_lcl;
|
|
uod.rDest = *(LPRECTL) lpDestRect;
|
|
uod.rSrc = *(LPRECTL) lpSrcRect;
|
|
uod.dwFlags = dwFlags;
|
|
if( this_src->dwGlobalFlags & DDRAWISURFGBL_SOFTWAREAUTOFLIP )
|
|
{
|
|
uod.dwFlags &= ~( DDOVER_AUTOFLIP | DDOVER_BOBHARDWARE );
|
|
#ifdef WIN95
|
|
if( WillCauseOverlayArtifacts( this_src_lcl, &uod ) )
|
|
{
|
|
// Eliminate artifacts by temporarily freezing the video
|
|
EnableAutoflip( GetVideoPortFromSurface( this_src_int ), FALSE );
|
|
bAutoflipDisabled = TRUE;
|
|
}
|
|
#endif
|
|
}
|
|
|
|
/*
|
|
* Don't call the HAL if we're in a DOS box (the busy bit will be set),
|
|
* but we also cant fail or this might cause a regression.
|
|
*/
|
|
#ifdef WIN95
|
|
if( ( *(pdrv->lpwPDeviceFlags) & BUSY ) &&
|
|
( pdrv->dwSurfaceLockCount == 0) ) // Don't fail if it's busy due to a lock
|
|
{
|
|
rc = DDHAL_DRIVER_HANDLED;
|
|
uod.ddRVal = DD_OK;
|
|
}
|
|
else
|
|
#endif
|
|
{
|
|
#ifndef WINNT
|
|
// Hack to work around s3 driver bug: it crushes the dest surface's
|
|
// dwReserved1 with the src pointer!!!
|
|
UINT_PTR dwTemp = uod.lpDDDestSurface->lpGbl->dwReserved1;
|
|
#endif
|
|
DOHALCALL( UpdateOverlay, uofn, uod, rc, emulation );
|
|
#ifndef WINNT
|
|
// Note the STB video rage 2 driver trashes uod.lpDDDestSurface and
|
|
// uod.lpDDSrcSurface pointers, so we must check the driver name first.
|
|
if (((*(LPWORD)(&pdrv->dd32BitDriverData.szName)) == ((WORD)'S' + (((WORD)'3')<<8))) &&
|
|
(uod.lpDDDestSurface->lpGbl->dwReserved1 != dwTemp) &&
|
|
(uod.lpDDDestSurface->lpGbl->dwReserved1 == (UINT_PTR)uod.lpDDSrcSurface))
|
|
{
|
|
uod.lpDDDestSurface->lpGbl->dwReserved1 = dwTemp;
|
|
}
|
|
#endif
|
|
}
|
|
|
|
/*
|
|
* If it failed due to hardware autoflipping or bobbing interleaved
|
|
* data using a video port, try again w/o
|
|
*/
|
|
if( ( rc == DDHAL_DRIVER_HANDLED ) &&
|
|
( uod.ddRVal != DD_OK ) && ( ( uod.dwFlags & DDOVER_AUTOFLIP ) ||
|
|
( uod.dwFlags & DDOVER_BOBHARDWARE ) ) &&
|
|
CanSoftwareAutoflip( GetVideoPortFromSurface( this_src_int ) ) )
|
|
{
|
|
uod.dwFlags &= ~( DDOVER_AUTOFLIP | DDOVER_BOBHARDWARE );
|
|
DOHALCALL( UpdateOverlay, uofn, uod, rc, emulation );
|
|
if( ( rc == DDHAL_DRIVER_HANDLED ) &&
|
|
( uod.ddRVal == DD_OK ) )
|
|
{
|
|
if( dwFlags & DDOVER_AUTOFLIP )
|
|
{
|
|
this_src_lcl->lpGbl->dwGlobalFlags |= DDRAWISURFGBL_SOFTWAREAUTOFLIP;
|
|
RequireSoftwareAutoflip( this_src_int );
|
|
}
|
|
if( dwFlags & DDOVER_BOBHARDWARE )
|
|
{
|
|
RequireSoftwareBob( this_src_int );
|
|
}
|
|
}
|
|
}
|
|
|
|
// if the HAL call failed, restore the visible bit
|
|
if( ( rc != DDHAL_DRIVER_HANDLED ) || ( uod.ddRVal != DD_OK ) )
|
|
{
|
|
if( original_visible )
|
|
{
|
|
this_src_lcl->ddsCaps.dwCaps |= DDSCAPS_VISIBLE;
|
|
}
|
|
else
|
|
{
|
|
this_src_lcl->ddsCaps.dwCaps &= ~DDSCAPS_VISIBLE;
|
|
}
|
|
}
|
|
|
|
if( rc == DDHAL_DRIVER_HANDLED )
|
|
{
|
|
if( uod.ddRVal == DD_OK )
|
|
{
|
|
LPDDRAWI_DDRAWSURFACE_INT surf_first;
|
|
LPDDRAWI_DDRAWSURFACE_INT surf_temp;
|
|
|
|
/*
|
|
* Store this info for later use. If the surface is part
|
|
* of a chain, store this data for each of the surfaces in
|
|
* the chain.
|
|
*/
|
|
surf_first = surf_temp = this_src_int;
|
|
do
|
|
{
|
|
surf_temp->lpLcl->lOverlayX = uod.rDest.left;
|
|
surf_temp->lpLcl->lOverlayY = uod.rDest.top;
|
|
surf_temp->lpLcl->rcOverlayDest.left = uod.rDest.left;
|
|
surf_temp->lpLcl->rcOverlayDest.top = uod.rDest.top;
|
|
surf_temp->lpLcl->rcOverlayDest.right = uod.rDest.right;
|
|
surf_temp->lpLcl->rcOverlayDest.bottom = uod.rDest.bottom;
|
|
surf_temp->lpLcl->rcOverlaySrc.left = uod.rSrc.left;
|
|
surf_temp->lpLcl->rcOverlaySrc.top = uod.rSrc.top;
|
|
surf_temp->lpLcl->rcOverlaySrc.right = uod.rSrc.right;
|
|
surf_temp->lpLcl->rcOverlaySrc.bottom = uod.rSrc.bottom;
|
|
surf_temp->lpLcl->lpSurfMore->dwOverlayFlags = dwFlags;
|
|
if( dwFlags & DDOVER_DDFX )
|
|
{
|
|
if( surf_temp->lpLcl->lpSurfMore->lpddOverlayFX == NULL )
|
|
{
|
|
surf_temp->lpLcl->lpSurfMore->lpddOverlayFX =
|
|
(LPDDOVERLAYFX) MemAlloc( sizeof( DDOVERLAYFX ) );
|
|
}
|
|
if( surf_temp->lpLcl->lpSurfMore->lpddOverlayFX != NULL )
|
|
{
|
|
memcpy( surf_temp->lpLcl->lpSurfMore->lpddOverlayFX,
|
|
lpDDOverlayFX, sizeof( DDOVERLAYFX) );
|
|
}
|
|
}
|
|
#ifdef WIN95
|
|
UpdateKernelSurface( surf_temp->lpLcl );
|
|
#endif
|
|
surf_temp = FindAttachedFlip( surf_temp );
|
|
} while( ( surf_temp != NULL ) && ( surf_temp->lpLcl != surf_first->lpLcl ) );
|
|
|
|
/*
|
|
* update refcnt if this is a new surface we are overlaying
|
|
*/
|
|
if( this_src_lcl->lpSurfaceOverlaying != this_dest_int )
|
|
{
|
|
if(this_src_lcl->lpSurfaceOverlaying != NULL)
|
|
{
|
|
/*
|
|
* This overlay was previously overlaying another surface.
|
|
*/
|
|
DD_Surface_Release(
|
|
(LPDIRECTDRAWSURFACE)(this_src_lcl->lpSurfaceOverlaying) );
|
|
}
|
|
this_src_lcl->lpSurfaceOverlaying = this_dest_int;
|
|
|
|
/*
|
|
* addref overlayed surface so that it won't be destroyed until
|
|
* all surfaces which overlay it are destroyed.
|
|
*/
|
|
DD_Surface_AddRef( (LPDIRECTDRAWSURFACE) this_dest_int );
|
|
}
|
|
}
|
|
#ifdef WIN95
|
|
if( bAutoflipDisabled )
|
|
{
|
|
EnableAutoflip( GetVideoPortFromSurface( this_src_int ), TRUE );
|
|
}
|
|
#endif
|
|
LEAVE_DDRAW();
|
|
return uod.ddRVal;
|
|
}
|
|
#ifdef WIN95
|
|
if( bAutoflipDisabled )
|
|
{
|
|
EnableAutoflip( GetVideoPortFromSurface( this_src_int ), TRUE );
|
|
}
|
|
#endif
|
|
}
|
|
LEAVE_DDRAW();
|
|
return DDERR_UNSUPPORTED;
|
|
|
|
} /* DD_Surface_UpdateOverlay */
|
|
|
|
|
|
#undef DPF_MODNAME
|
|
#define DPF_MODNAME "GetOverlayPosition"
|
|
|
|
/*
|
|
* DD_Surface_GetOverlayPosition
|
|
*/
|
|
HRESULT DDAPI DD_Surface_GetOverlayPosition(
|
|
LPDIRECTDRAWSURFACE lpDDSurface,
|
|
LPLONG lplXPos,
|
|
LPLONG lplYPos)
|
|
{
|
|
LPDDRAWI_DIRECTDRAW_GBL pdrv;
|
|
LPDDRAWI_DDRAWSURFACE_INT this_int;
|
|
LPDDRAWI_DDRAWSURFACE_LCL this_lcl;
|
|
LPDDRAWI_DDRAWSURFACE_GBL this;
|
|
|
|
ENTER_DDRAW();
|
|
|
|
DPF(2,A,"ENTERAPI: DD_Surface_GetOverlayPosition");
|
|
|
|
TRY
|
|
{
|
|
this_int = (LPDDRAWI_DDRAWSURFACE_INT) lpDDSurface;
|
|
if( !VALID_DIRECTDRAWSURFACE_PTR( this_int ) )
|
|
{
|
|
LEAVE_DDRAW();
|
|
return DDERR_INVALIDOBJECT;
|
|
}
|
|
this_lcl = this_int->lpLcl;
|
|
this = this_lcl->lpGbl;
|
|
if( !VALID_DWORD_PTR( lplXPos ) )
|
|
{
|
|
LEAVE_DDRAW();
|
|
return DDERR_INVALIDPARAMS;
|
|
}
|
|
*lplXPos = 0;
|
|
if( !VALID_DWORD_PTR( lplYPos ) )
|
|
{
|
|
LEAVE_DDRAW();
|
|
return DDERR_INVALIDPARAMS;
|
|
}
|
|
*lplYPos = 0;
|
|
if( SURFACE_LOST( this_lcl ) )
|
|
{
|
|
LEAVE_DDRAW();
|
|
return DDERR_SURFACELOST;
|
|
}
|
|
pdrv = this->lpDD;
|
|
|
|
//
|
|
// For now, if the current surface is optimized, quit
|
|
//
|
|
if (this_lcl->ddsCaps.dwCaps & DDSCAPS_OPTIMIZED)
|
|
{
|
|
DPF_ERR( "It is an optimized surface" );
|
|
LEAVE_DDRAW();
|
|
return DDERR_ISOPTIMIZEDSURFACE;
|
|
}
|
|
|
|
if( !(this_lcl->ddsCaps.dwCaps & DDSCAPS_OVERLAY) )
|
|
{
|
|
DPF_ERR( "Surface is not an overlay surface" );
|
|
LEAVE_DDRAW();
|
|
return DDERR_NOTAOVERLAYSURFACE;
|
|
}
|
|
if( !(this_lcl->ddsCaps.dwCaps & DDSCAPS_VISIBLE) )
|
|
{
|
|
DPF_ERR( "Overlay surface is not visible" );
|
|
LEAVE_DDRAW();
|
|
return DDERR_OVERLAYNOTVISIBLE;
|
|
}
|
|
|
|
if( this_lcl->lpSurfaceOverlaying == NULL )
|
|
{
|
|
DPF_ERR( "Overlay not activated" );
|
|
LEAVE_DDRAW();
|
|
return DDERR_NOOVERLAYDEST;
|
|
}
|
|
|
|
}
|
|
EXCEPT( EXCEPTION_EXECUTE_HANDLER )
|
|
{
|
|
DPF_ERR( "Exception encountered validating parameters" );
|
|
LEAVE_DDRAW();
|
|
return DDERR_INVALIDPARAMS;
|
|
}
|
|
*lplXPos = this_lcl->lOverlayX;
|
|
*lplYPos = this_lcl->lOverlayY;
|
|
|
|
LEAVE_DDRAW();
|
|
return DD_OK;
|
|
|
|
} /* DD_Surface_GetOverlayPosition */
|
|
|
|
#undef DPF_MODNAME
|
|
#define DPF_MODNAME "SetOverlayPosition"
|
|
|
|
/*
|
|
* DD_Surface_SetOverlayPosition
|
|
*/
|
|
HRESULT DDAPI DD_Surface_SetOverlayPosition(
|
|
LPDIRECTDRAWSURFACE lpDDSurface,
|
|
LONG lXPos,
|
|
LONG lYPos)
|
|
{
|
|
LPDDRAWI_DIRECTDRAW_LCL pdrv_lcl;
|
|
LPDDRAWI_DIRECTDRAW_GBL pdrv;
|
|
LPDDRAWI_DDRAWSURFACE_INT psurfover_int;
|
|
LPDDRAWI_DDRAWSURFACE_LCL psurfover_lcl;
|
|
LPDDRAWI_DDRAWSURFACE_INT this_int;
|
|
LPDDRAWI_DDRAWSURFACE_LCL this_lcl;
|
|
LPDDRAWI_DDRAWSURFACE_GBL this;
|
|
BOOL emulation;
|
|
LPDDHALSURFCB_SETOVERLAYPOSITION sophalfn;
|
|
LPDDHALSURFCB_SETOVERLAYPOSITION sopfn;
|
|
DDHAL_SETOVERLAYPOSITIONDATA sopd;
|
|
HRESULT ddrval;
|
|
DWORD rc;
|
|
|
|
ENTER_DDRAW();
|
|
|
|
DPF(2,A,"ENTERAPI: DD_Surface_SetOverlayPosition");
|
|
|
|
TRY
|
|
{
|
|
this_int = (LPDDRAWI_DDRAWSURFACE_INT) lpDDSurface;
|
|
if( !VALID_DIRECTDRAWSURFACE_PTR( this_int ) )
|
|
{
|
|
LEAVE_DDRAW();
|
|
return DDERR_INVALIDOBJECT;
|
|
}
|
|
this_lcl = this_int->lpLcl;
|
|
this = this_lcl->lpGbl;
|
|
if( SURFACE_LOST( this_lcl ) )
|
|
{
|
|
LEAVE_DDRAW();
|
|
return DDERR_SURFACELOST;
|
|
}
|
|
pdrv_lcl = this_lcl->lpSurfMore->lpDD_lcl;
|
|
pdrv = pdrv_lcl->lpGbl;
|
|
|
|
//
|
|
// For now, if the current surface is optimized, quit
|
|
//
|
|
if (this_lcl->ddsCaps.dwCaps & DDSCAPS_OPTIMIZED)
|
|
{
|
|
DPF_ERR( "It is an optimized surface" );
|
|
LEAVE_DDRAW();
|
|
return DDERR_ISOPTIMIZEDSURFACE;
|
|
}
|
|
|
|
if( !(this_lcl->ddsCaps.dwCaps & DDSCAPS_OVERLAY) )
|
|
{
|
|
DPF_ERR( "Surface is not an overlay surface" );
|
|
LEAVE_DDRAW();
|
|
return DDERR_NOTAOVERLAYSURFACE;
|
|
}
|
|
|
|
if( !(this_lcl->ddsCaps.dwCaps & DDSCAPS_VISIBLE) )
|
|
{
|
|
DPF_ERR( "Overlay surface is not visible" );
|
|
LEAVE_DDRAW();
|
|
return DDERR_OVERLAYNOTVISIBLE;
|
|
}
|
|
|
|
psurfover_int = this_lcl->lpSurfaceOverlaying;
|
|
if( psurfover_int == NULL )
|
|
{
|
|
DPF_ERR( "Overlay not activated" );
|
|
LEAVE_DDRAW();
|
|
return DDERR_NOOVERLAYDEST;
|
|
}
|
|
|
|
psurfover_lcl = psurfover_int->lpLcl;
|
|
if( (lYPos > (LONG) psurfover_lcl->lpGbl->wHeight -
|
|
(this_lcl->rcOverlayDest.bottom - this_lcl->rcOverlayDest.top)) ||
|
|
(lXPos > (LONG) psurfover_lcl->lpGbl->wWidth -
|
|
(this_lcl->rcOverlayDest.right - this_lcl->rcOverlayDest.left) ) ||
|
|
(lYPos < 0) ||
|
|
(lXPos < 0) )
|
|
{
|
|
DPF_ERR( "Invalid overlay position" );
|
|
LEAVE_DDRAW();
|
|
return DDERR_INVALIDPOSITION;
|
|
}
|
|
}
|
|
EXCEPT( EXCEPTION_EXECUTE_HANDLER )
|
|
{
|
|
DPF_ERR( "Exception encountered validating parameters" );
|
|
LEAVE_DDRAW();
|
|
return DDERR_INVALIDPARAMS;
|
|
}
|
|
|
|
/*
|
|
* check if emulated or not
|
|
*/
|
|
ddrval = checkOverlayEmulation( pdrv, this_lcl, psurfover_lcl, &emulation );
|
|
if( ddrval != DD_OK )
|
|
{
|
|
LEAVE_DDRAW();
|
|
return ddrval;
|
|
}
|
|
|
|
/*
|
|
* pick fns to use
|
|
*/
|
|
if( emulation )
|
|
{
|
|
sopfn = pdrv_lcl->lpDDCB->HELDDSurface.SetOverlayPosition;
|
|
sophalfn = sopfn;
|
|
}
|
|
else
|
|
{
|
|
sopfn = pdrv_lcl->lpDDCB->HALDDSurface.SetOverlayPosition;
|
|
sophalfn = pdrv_lcl->lpDDCB->cbDDSurfaceCallbacks.SetOverlayPosition;
|
|
}
|
|
|
|
/*
|
|
* call the driver
|
|
*/
|
|
if( sophalfn != NULL )
|
|
{
|
|
sopd.SetOverlayPosition = sophalfn;
|
|
sopd.lpDD = pdrv;
|
|
sopd.lpDDSrcSurface = this_lcl;
|
|
sopd.lpDDDestSurface = psurfover_lcl;
|
|
sopd.lXPos = lXPos;
|
|
sopd.lYPos = lYPos;
|
|
|
|
/*
|
|
* Don't call the HAL if we're in a DOS box (the busy bit will be set),
|
|
* but we also cant fail or this might cause a regression.
|
|
*/
|
|
#if WIN95
|
|
if( *(pdrv->lpwPDeviceFlags) & BUSY )
|
|
{
|
|
rc = DDHAL_DRIVER_HANDLED;
|
|
sopd.ddRVal = DD_OK;
|
|
}
|
|
else
|
|
#endif
|
|
{
|
|
DOHALCALL( SetOverlayPosition, sopfn, sopd, rc, emulation );
|
|
}
|
|
|
|
if( rc == DDHAL_DRIVER_HANDLED )
|
|
{
|
|
LEAVE_DDRAW();
|
|
if( sopd.ddRVal == DD_OK )
|
|
{
|
|
this_lcl->lOverlayX = lXPos;
|
|
this_lcl->lOverlayY = lYPos;
|
|
this_lcl->rcOverlayDest.right =
|
|
( this_lcl->rcOverlayDest.right -
|
|
this_lcl->rcOverlayDest.left ) + lXPos;
|
|
this_lcl->rcOverlayDest.left = lXPos;
|
|
this_lcl->rcOverlayDest.bottom =
|
|
( this_lcl->rcOverlayDest.bottom -
|
|
this_lcl->rcOverlayDest.top ) + lYPos;
|
|
this_lcl->rcOverlayDest.top = lYPos;
|
|
}
|
|
return sopd.ddRVal;
|
|
}
|
|
}
|
|
|
|
LEAVE_DDRAW();
|
|
return DDERR_UNSUPPORTED;
|
|
|
|
} /* DD_Surface_SetOverlayPosition */
|
|
|
|
#undef DPF_MODNAME
|
|
#define DPF_MODNAME "UpdateOverlayZOrder"
|
|
|
|
/*
|
|
* DD_Surface_UpdateOverlayZOrder
|
|
*/
|
|
HRESULT DDAPI DD_Surface_UpdateOverlayZOrder(
|
|
LPDIRECTDRAWSURFACE lpDDSurface,
|
|
DWORD dwFlags,
|
|
LPDIRECTDRAWSURFACE lpDDSReference)
|
|
{
|
|
LPDDRAWI_DIRECTDRAW_GBL pdrv;
|
|
LPDDRAWI_DDRAWSURFACE_INT this_int;
|
|
LPDDRAWI_DDRAWSURFACE_LCL this_lcl;
|
|
LPDDRAWI_DDRAWSURFACE_GBL this;
|
|
LPDDRAWI_DDRAWSURFACE_INT psurf_ref_int;
|
|
LPDDRAWI_DDRAWSURFACE_LCL psurf_ref_lcl;
|
|
LPDDRAWI_DDRAWSURFACE_GBL psurf_ref;
|
|
LPDBLNODE pdbnNode;
|
|
LPDBLNODE pdbnRef;
|
|
DWORD ddrval;
|
|
|
|
ENTER_DDRAW();
|
|
|
|
DPF(2,A,"ENTERAPI: DD_Surface_UpdateOverlayZOrder");
|
|
|
|
/*
|
|
* validate parameters
|
|
*/
|
|
TRY
|
|
{
|
|
this_int = (LPDDRAWI_DDRAWSURFACE_INT) lpDDSurface;
|
|
|
|
if( !VALID_DIRECTDRAWSURFACE_PTR( this_int ) )
|
|
{
|
|
LEAVE_DDRAW();
|
|
return DDERR_INVALIDOBJECT;
|
|
}
|
|
this_lcl = this_int->lpLcl;
|
|
this = this_lcl->lpGbl;
|
|
|
|
pdrv = this->lpDD;
|
|
|
|
//
|
|
// For now, if the current surface is optimized, quit
|
|
//
|
|
if (this_lcl->ddsCaps.dwCaps & DDSCAPS_OPTIMIZED)
|
|
{
|
|
DPF_ERR( "It is an optimized surface" );
|
|
LEAVE_DDRAW();
|
|
return DDERR_ISOPTIMIZEDSURFACE;
|
|
}
|
|
|
|
if( !(this_lcl->ddsCaps.dwCaps & DDSCAPS_OVERLAY) )
|
|
{
|
|
DPF_ERR( "Surface is not an overlay surface" );
|
|
LEAVE_DDRAW();
|
|
return DDERR_NOTAOVERLAYSURFACE;
|
|
}
|
|
|
|
switch(dwFlags)
|
|
{
|
|
case DDOVERZ_SENDTOFRONT:
|
|
pdbnNode = &(this_lcl->dbnOverlayNode);
|
|
// the reference node is the root
|
|
pdbnRef = &(this->lpDD->dbnOverlayRoot);
|
|
// Delete surface from current position
|
|
pdbnNode->prev->next = pdbnNode->next;
|
|
pdbnNode->next->prev = pdbnNode->prev;
|
|
// insert this node after the root node
|
|
pdbnNode->next = pdbnRef->next;
|
|
pdbnNode->prev = pdbnRef;
|
|
pdbnRef->next = pdbnNode;
|
|
pdbnNode->next->prev = pdbnNode;
|
|
break;
|
|
|
|
case DDOVERZ_SENDTOBACK:
|
|
pdbnNode = &(this_lcl->dbnOverlayNode);
|
|
// the reference node is the root
|
|
pdbnRef = &(this->lpDD->dbnOverlayRoot);
|
|
// Delete surface from current position
|
|
pdbnNode->prev->next = pdbnNode->next;
|
|
pdbnNode->next->prev = pdbnNode->prev;
|
|
// insert this node before the root node
|
|
pdbnNode->next = pdbnRef;
|
|
pdbnNode->prev = pdbnRef->prev;
|
|
pdbnRef->prev = pdbnNode;
|
|
pdbnNode->prev->next = pdbnNode;
|
|
break;
|
|
|
|
case DDOVERZ_MOVEFORWARD:
|
|
pdbnNode = &(this_lcl->dbnOverlayNode);
|
|
// the reference node is the previous node
|
|
pdbnRef = pdbnNode->prev;
|
|
if(pdbnRef != &(this->lpDD->dbnOverlayRoot)) // node already first?
|
|
{
|
|
// move node forward one position by inserting before ref node
|
|
// Delete surface from current position
|
|
pdbnNode->prev->next = pdbnNode->next;
|
|
pdbnNode->next->prev = pdbnNode->prev;
|
|
// insert this node before the ref node
|
|
pdbnNode->next = pdbnRef;
|
|
pdbnNode->prev = pdbnRef->prev;
|
|
pdbnRef->prev = pdbnNode;
|
|
pdbnNode->prev->next = pdbnNode;
|
|
}
|
|
break;
|
|
|
|
case DDOVERZ_MOVEBACKWARD:
|
|
pdbnNode = &(this_lcl->dbnOverlayNode);
|
|
// the reference node is the next node
|
|
pdbnRef = pdbnNode->next;
|
|
if(pdbnRef != &(this->lpDD->dbnOverlayRoot)) // node already last?
|
|
{
|
|
// move node backward one position by inserting after ref node
|
|
// Delete surface from current position
|
|
pdbnNode->prev->next = pdbnNode->next;
|
|
pdbnNode->next->prev = pdbnNode->prev;
|
|
// insert this node after the reference node
|
|
pdbnNode->next = pdbnRef->next;
|
|
pdbnNode->prev = pdbnRef;
|
|
pdbnRef->next = pdbnNode;
|
|
pdbnNode->next->prev = pdbnNode;
|
|
}
|
|
break;
|
|
|
|
case DDOVERZ_INSERTINBACKOF:
|
|
case DDOVERZ_INSERTINFRONTOF:
|
|
psurf_ref_int = (LPDDRAWI_DDRAWSURFACE_INT) lpDDSReference;
|
|
if( !VALID_DIRECTDRAWSURFACE_PTR( psurf_ref_int ) )
|
|
{
|
|
DPF_ERR( "Invalid reference surface ptr" );
|
|
LEAVE_DDRAW();
|
|
return DDERR_INVALIDOBJECT;
|
|
}
|
|
psurf_ref_lcl = psurf_ref_int->lpLcl;
|
|
psurf_ref = psurf_ref_lcl->lpGbl;
|
|
if( !(psurf_ref_lcl->ddsCaps.dwCaps & DDSCAPS_OVERLAY) )
|
|
{
|
|
DPF_ERR( "reference surface is not an overlay" );
|
|
LEAVE_DDRAW();
|
|
return DDERR_NOTAOVERLAYSURFACE;
|
|
}
|
|
if (this_lcl->lpSurfMore->lpDD_lcl->lpGbl != psurf_ref_lcl->lpSurfMore->lpDD_lcl->lpGbl)
|
|
{
|
|
DPF_ERR("Surfaces must belong to the same device");
|
|
LEAVE_DDRAW();
|
|
return DDERR_DEVICEDOESNTOWNSURFACE;
|
|
}
|
|
|
|
// Search for the reference surface in the Z Order list
|
|
pdbnNode = &(this->lpDD->dbnOverlayRoot); // pdbnNode points to root
|
|
for(pdbnRef=pdbnNode->next;
|
|
pdbnRef != pdbnNode;
|
|
pdbnRef = pdbnRef->next )
|
|
{
|
|
if( pdbnRef->object == psurf_ref_lcl )
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
if(pdbnRef == pdbnNode) // didn't find the reference node
|
|
{
|
|
DPF_ERR( "Reference Surface not in Z Order list" );
|
|
LEAVE_DDRAW();
|
|
return DDERR_INVALIDPARAMS;
|
|
}
|
|
|
|
pdbnNode = &(this_lcl->dbnOverlayNode); // pdbnNode points to this node
|
|
// Delete this surface from its current position
|
|
pdbnNode->prev->next = pdbnNode->next;
|
|
pdbnNode->next->prev = pdbnNode->prev;
|
|
if(dwFlags == DDOVERZ_INSERTINFRONTOF)
|
|
{
|
|
// insert this node before the ref node
|
|
pdbnNode->next = pdbnRef;
|
|
pdbnNode->prev = pdbnRef->prev;
|
|
pdbnRef->prev = pdbnNode;
|
|
pdbnNode->prev->next = pdbnNode;
|
|
}
|
|
else
|
|
{
|
|
// insert this node after the ref node
|
|
pdbnNode->next = pdbnRef->next;
|
|
pdbnNode->prev = pdbnRef;
|
|
pdbnRef->next = pdbnNode;
|
|
pdbnNode->next->prev = pdbnNode;
|
|
}
|
|
break;
|
|
|
|
default:
|
|
DPF_ERR( "Invalid dwFlags in UpdateOverlayZOrder" );
|
|
LEAVE_DDRAW();
|
|
return DDERR_INVALIDPARAMS;
|
|
}
|
|
}
|
|
EXCEPT( EXCEPTION_EXECUTE_HANDLER )
|
|
{
|
|
DPF_ERR( "Exception encountered validating parameters" );
|
|
LEAVE_DDRAW();
|
|
return DDERR_INVALIDPARAMS;
|
|
}
|
|
|
|
/*
|
|
* If this surface is overlaying an emulated surface, we must notify
|
|
* the HEL that it needs to eventually update the part of the surface
|
|
* touched by this overlay.
|
|
*/
|
|
ddrval = DD_OK;
|
|
if( this_lcl->lpSurfaceOverlaying != NULL )
|
|
{
|
|
/*
|
|
* We have a pointer to the surface being overlayed, check to
|
|
* see if it is being emulated.
|
|
*/
|
|
if( this_lcl->lpSurfaceOverlaying->lpLcl->ddsCaps.dwCaps & DDSCAPS_SYSTEMMEMORY )
|
|
{
|
|
/*
|
|
* Mark the destination region of this overlay as dirty.
|
|
*/
|
|
DD_Surface_AddOverlayDirtyRect(
|
|
(LPDIRECTDRAWSURFACE)(this_lcl->lpSurfaceOverlaying),
|
|
&(this_lcl->rcOverlayDest) );
|
|
}
|
|
|
|
/*
|
|
* If the overlay is on, call down to the HAL
|
|
*/
|
|
if( this_lcl->ddsCaps.dwCaps & DDSCAPS_VISIBLE )
|
|
{
|
|
if( ( this_lcl->lpSurfMore->dwOverlayFlags & DDOVER_DDFX ) &&
|
|
( this_lcl->lpSurfMore->lpddOverlayFX != NULL ) )
|
|
{
|
|
ddrval = DD_Surface_UpdateOverlay(
|
|
(LPDIRECTDRAWSURFACE) this_int,
|
|
&(this_lcl->rcOverlaySrc),
|
|
(LPDIRECTDRAWSURFACE) this_lcl->lpSurfaceOverlaying,
|
|
&(this_lcl->rcOverlayDest),
|
|
this_lcl->lpSurfMore->dwOverlayFlags,
|
|
this_lcl->lpSurfMore->lpddOverlayFX );
|
|
}
|
|
else
|
|
{
|
|
ddrval = DD_Surface_UpdateOverlay(
|
|
(LPDIRECTDRAWSURFACE) this_int,
|
|
&(this_lcl->rcOverlaySrc),
|
|
(LPDIRECTDRAWSURFACE) this_lcl->lpSurfaceOverlaying,
|
|
&(this_lcl->rcOverlayDest),
|
|
this_lcl->lpSurfMore->dwOverlayFlags,
|
|
NULL );
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
LEAVE_DDRAW();
|
|
return ddrval;
|
|
|
|
} /* DD_Surface_UpdateOverlayZOrder */
|
|
|
|
#undef DPF_MODNAME
|
|
#define DPF_MODNAME "EnumOverlayZOrders"
|
|
|
|
/*
|
|
* DD_Surface_EnumOverlayZOrders
|
|
*/
|
|
HRESULT DDAPI DD_Surface_EnumOverlayZOrders(
|
|
LPDIRECTDRAWSURFACE lpDDSurface,
|
|
DWORD dwFlags,
|
|
LPVOID lpContext,
|
|
LPDDENUMSURFACESCALLBACK lpfnCallback)
|
|
{
|
|
LPDDRAWI_DIRECTDRAW_GBL pdrv;
|
|
LPDDRAWI_DDRAWSURFACE_INT this_int;
|
|
LPDDRAWI_DDRAWSURFACE_LCL this_lcl;
|
|
LPDDRAWI_DDRAWSURFACE_GBL this;
|
|
LPDBLNODE pRoot;
|
|
LPDBLNODE pdbn;
|
|
DDSURFACEDESC2 ddsd;
|
|
DWORD rc;
|
|
|
|
ENTER_DDRAW();
|
|
|
|
DPF(2,A,"ENTERAPI: DD_Surface_EnumOverlayZOrders");
|
|
|
|
/*
|
|
* validate parameters
|
|
*/
|
|
TRY
|
|
{
|
|
this_int = (LPDDRAWI_DDRAWSURFACE_INT) lpDDSurface;
|
|
|
|
if( !VALID_DIRECTDRAWSURFACE_PTR( this_int ) )
|
|
{
|
|
LEAVE_DDRAW();
|
|
return DDERR_INVALIDOBJECT;
|
|
}
|
|
this_lcl = this_int->lpLcl;
|
|
|
|
if( !VALIDEX_CODE_PTR( lpfnCallback ) )
|
|
{
|
|
DPF_ERR( "Invalid callback routine" );
|
|
LEAVE_DDRAW();
|
|
return DDERR_INVALIDPARAMS;
|
|
}
|
|
this = this_lcl->lpGbl;
|
|
pdrv = this->lpDD;
|
|
|
|
pRoot = &(pdrv->dbnOverlayRoot); // save address of root node
|
|
}
|
|
EXCEPT( EXCEPTION_EXECUTE_HANDLER )
|
|
{
|
|
DPF_ERR( "Exception encountered validating parameters" );
|
|
LEAVE_DDRAW();
|
|
return DDERR_INVALIDPARAMS;
|
|
}
|
|
|
|
//
|
|
// If the current surface is optimized, quit
|
|
//
|
|
if (this_lcl->ddsCaps.dwCaps & DDSCAPS_OPTIMIZED)
|
|
{
|
|
DPF_ERR( "It is an optimized surface" );
|
|
LEAVE_DDRAW();
|
|
return DDERR_ISOPTIMIZEDSURFACE;
|
|
}
|
|
|
|
if( dwFlags == DDENUMOVERLAYZ_FRONTTOBACK )
|
|
{
|
|
pdbn = pRoot->next;
|
|
while(pdbn != pRoot)
|
|
{
|
|
LPDIRECTDRAWSURFACE7 intReturned = (LPDIRECTDRAWSURFACE7) pdbn->object_int;
|
|
|
|
FillDDSurfaceDesc2( pdbn->object, &ddsd );
|
|
if (LOWERTHANSURFACE4(this_int))
|
|
{
|
|
ddsd.dwSize = sizeof(DDSURFACEDESC);
|
|
DD_Surface_QueryInterface( (LPDIRECTDRAWSURFACE) intReturned, & IID_IDirectDrawSurface, (void**) & intReturned );
|
|
}
|
|
else if (this_int->lpVtbl == &ddSurface4Callbacks)
|
|
{
|
|
DD_Surface_QueryInterface( (LPDIRECTDRAWSURFACE) intReturned, & IID_IDirectDrawSurface4, (void**) & intReturned );
|
|
}
|
|
else
|
|
{
|
|
DD_Surface_QueryInterface( (LPDIRECTDRAWSURFACE) intReturned, & IID_IDirectDrawSurface7, (void**) & intReturned );
|
|
}
|
|
|
|
rc = lpfnCallback( (LPDIRECTDRAWSURFACE)intReturned, (LPDDSURFACEDESC) &ddsd, lpContext );
|
|
if( rc == 0)
|
|
{
|
|
break;
|
|
}
|
|
pdbn = pdbn->next;
|
|
}
|
|
}
|
|
else if( dwFlags == DDENUMOVERLAYZ_BACKTOFRONT )
|
|
{
|
|
pdbn = pRoot->prev;
|
|
while(pdbn != pRoot)
|
|
{
|
|
LPDIRECTDRAWSURFACE7 intReturned = (LPDIRECTDRAWSURFACE7) pdbn->object_int;
|
|
|
|
FillDDSurfaceDesc2( pdbn->object, &ddsd );
|
|
if (LOWERTHANSURFACE4(this_int))
|
|
{
|
|
ddsd.dwSize = sizeof(DDSURFACEDESC);
|
|
DD_Surface_QueryInterface( (LPDIRECTDRAWSURFACE) intReturned, & IID_IDirectDrawSurface, (void**) & intReturned );
|
|
}
|
|
else if (this_int->lpVtbl == &ddSurface4Callbacks)
|
|
{
|
|
DD_Surface_QueryInterface( (LPDIRECTDRAWSURFACE) intReturned, & IID_IDirectDrawSurface4, (void**) & intReturned );
|
|
}
|
|
else
|
|
{
|
|
DD_Surface_QueryInterface( (LPDIRECTDRAWSURFACE) intReturned, & IID_IDirectDrawSurface7, (void**) & intReturned );
|
|
}
|
|
|
|
rc = lpfnCallback( (LPDIRECTDRAWSURFACE)intReturned, (LPDDSURFACEDESC) &ddsd, lpContext );
|
|
if( rc == 0)
|
|
{
|
|
break;
|
|
}
|
|
pdbn = pdbn->prev;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
DPF_ERR( "Invalid dwFlags in EnumOverlayZOrders" );
|
|
LEAVE_DDRAW();
|
|
return DDERR_INVALIDPARAMS;
|
|
}
|
|
|
|
LEAVE_DDRAW();
|
|
return DD_OK;
|
|
|
|
} /* DD_Surface_EnumOverlayZOrders */
|
|
|
|
#undef DPF_MODNAME
|
|
#define DPF_MODNAME "AddOverlayDirtyRect"
|
|
|
|
/*
|
|
* DD_Surface_AddOverlayDirtyRect
|
|
*/
|
|
HRESULT DDAPI DD_Surface_AddOverlayDirtyRect(
|
|
LPDIRECTDRAWSURFACE lpDDSurface,
|
|
LPRECT lpRect )
|
|
{
|
|
LPDDRAWI_DIRECTDRAW_LCL pdrv_lcl;
|
|
LPDDRAWI_DDRAWSURFACE_INT this_int;
|
|
LPDDRAWI_DDRAWSURFACE_LCL this_lcl;
|
|
LPDDRAWI_DDRAWSURFACE_GBL this;
|
|
DDHAL_UPDATEOVERLAYDATA uod;
|
|
DWORD rc;
|
|
|
|
ENTER_DDRAW();
|
|
|
|
DPF(2,A,"ENTERAPI: DD_Surface_AddOverlayDirtyRect");
|
|
|
|
/*
|
|
* validate parameters
|
|
*/
|
|
TRY
|
|
{
|
|
this_int = (LPDDRAWI_DDRAWSURFACE_INT) lpDDSurface;
|
|
|
|
if( !VALID_DIRECTDRAWSURFACE_PTR( this_int ) )
|
|
{
|
|
LEAVE_DDRAW();
|
|
return DDERR_INVALIDOBJECT;
|
|
}
|
|
this_lcl = this_int->lpLcl;
|
|
|
|
if( this_lcl->ddsCaps.dwCaps & DDSCAPS_EXECUTEBUFFER )
|
|
{
|
|
DPF_ERR( "Invalid surface type: does not support overlays" );
|
|
LEAVE_DDRAW();
|
|
return DDERR_INVALIDSURFACETYPE;
|
|
}
|
|
|
|
if( !VALID_RECT_PTR( lpRect ) )
|
|
{
|
|
DPF_ERR( "invalid Rect" );
|
|
LEAVE_DDRAW();
|
|
return DDERR_INVALIDPARAMS;
|
|
}
|
|
|
|
this = this_lcl->lpGbl;
|
|
pdrv_lcl = this_lcl->lpSurfMore->lpDD_lcl;
|
|
|
|
/*
|
|
* make sure rectangle is OK
|
|
*/
|
|
if( (lpRect->left < 0) ||
|
|
(lpRect->top < 0) ||
|
|
(lpRect->left > lpRect->right) ||
|
|
(lpRect->top > lpRect->bottom) ||
|
|
(lpRect->bottom > (int) (DWORD) this->wHeight) ||
|
|
(lpRect->right > (int) (DWORD) this->wWidth) )
|
|
{
|
|
DPF_ERR( "invalid Rect" );
|
|
LEAVE_DDRAW();
|
|
return DDERR_INVALIDPARAMS;
|
|
}
|
|
|
|
}
|
|
EXCEPT( EXCEPTION_EXECUTE_HANDLER )
|
|
{
|
|
DPF_ERR( "Exception encountered validating parameters" );
|
|
LEAVE_DDRAW();
|
|
return DDERR_INVALIDPARAMS;
|
|
}
|
|
|
|
//
|
|
// If the current surface is optimized, quit
|
|
//
|
|
if (this_lcl->ddsCaps.dwCaps & DDSCAPS_OPTIMIZED)
|
|
{
|
|
DPF_ERR( "It is an optimized surface" );
|
|
LEAVE_DDRAW();
|
|
return DDERR_ISOPTIMIZEDSURFACE;
|
|
}
|
|
|
|
if( !(this_lcl->ddsCaps.dwCaps & DDSCAPS_SYSTEMMEMORY) )
|
|
{
|
|
// If this surface is not emulated, there is nothing to be done.
|
|
LEAVE_DDRAW();
|
|
return DD_OK;
|
|
}
|
|
else
|
|
{
|
|
if( pdrv_lcl->lpDDCB->HELDDSurface.UpdateOverlay == NULL )
|
|
{
|
|
LEAVE_DDRAW();
|
|
return DDERR_UNSUPPORTED;
|
|
}
|
|
|
|
uod.overlayFX.dwSize = sizeof( DDOVERLAYFX );
|
|
uod.lpDD = this->lpDD;
|
|
uod.lpDDDestSurface = this_lcl;
|
|
uod.rDest = *(LPRECTL) lpRect;
|
|
uod.lpDDSrcSurface = this_lcl;
|
|
uod.rSrc = *(LPRECTL) lpRect;
|
|
uod.dwFlags = DDOVER_ADDDIRTYRECT;
|
|
rc = pdrv_lcl->lpDDCB->HELDDSurface.UpdateOverlay( &uod );
|
|
|
|
if( rc == DDHAL_DRIVER_HANDLED )
|
|
{
|
|
if( uod.ddRVal == DD_OK )
|
|
{
|
|
DPF( 2, "Added dirty rect to surface = %08lx", this );
|
|
}
|
|
LEAVE_DDRAW();
|
|
return uod.ddRVal;
|
|
}
|
|
else
|
|
{
|
|
LEAVE_DDRAW();
|
|
return DDERR_INVALIDPARAMS;
|
|
}
|
|
}
|
|
|
|
} /* DD_Surface_AddOverlayDirtyRect */
|
|
|
|
#undef DPF_MODNAME
|
|
#define DPF_MODNAME "UpdateOverlayDisplay"
|
|
|
|
/*
|
|
* DD_Surface_UpdateOverlayDisplay
|
|
*/
|
|
HRESULT DDAPI DD_Surface_UpdateOverlayDisplay(
|
|
LPDIRECTDRAWSURFACE lpDDSurface,
|
|
DWORD dwFlags )
|
|
{
|
|
LPDDRAWI_DIRECTDRAW_LCL pdrv_lcl;
|
|
LPDDRAWI_DDRAWSURFACE_INT this_int;
|
|
LPDDRAWI_DDRAWSURFACE_LCL this_lcl;
|
|
LPDDRAWI_DDRAWSURFACE_GBL this;
|
|
DDHAL_UPDATEOVERLAYDATA uod;
|
|
DWORD rc;
|
|
|
|
ENTER_DDRAW();
|
|
|
|
DPF(2,A,"ENTERAPI: DD_Surface_UpdateOverlayDisplay");
|
|
|
|
/*
|
|
* validate parameters
|
|
*/
|
|
TRY
|
|
{
|
|
this_int = (LPDDRAWI_DDRAWSURFACE_INT) lpDDSurface;
|
|
|
|
if( !VALID_DIRECTDRAWSURFACE_PTR( this_int ) )
|
|
{
|
|
LEAVE_DDRAW();
|
|
return DDERR_INVALIDOBJECT;
|
|
}
|
|
this_lcl = this_int->lpLcl;
|
|
|
|
if( dwFlags & ~(DDOVER_REFRESHDIRTYRECTS | DDOVER_REFRESHALL) )
|
|
{
|
|
LEAVE_DDRAW();
|
|
return DDERR_INVALIDPARAMS;
|
|
}
|
|
|
|
this = this_lcl->lpGbl;
|
|
pdrv_lcl = this_lcl->lpSurfMore->lpDD_lcl;
|
|
|
|
if( this_lcl->ddsCaps.dwCaps & DDSCAPS_EXECUTEBUFFER )
|
|
{
|
|
DPF_ERR( "Invalid surface type: does not support overlays" );
|
|
LEAVE_DDRAW();
|
|
return DDERR_INVALIDSURFACETYPE;
|
|
}
|
|
|
|
//
|
|
// For now, if the current surface is optimized, quit
|
|
//
|
|
if (this_lcl->ddsCaps.dwCaps & DDSCAPS_OPTIMIZED)
|
|
{
|
|
DPF_ERR( "It is an optimized surface" );
|
|
LEAVE_DDRAW();
|
|
return DDERR_ISOPTIMIZEDSURFACE;
|
|
}
|
|
|
|
if( !(this_lcl->ddsCaps.dwCaps & DDSCAPS_SYSTEMMEMORY) )
|
|
{
|
|
// If this surface is not emulated, there is nothing to be done.
|
|
LEAVE_DDRAW();
|
|
return DD_OK;
|
|
}
|
|
|
|
if( pdrv_lcl->lpDDCB->HELDDSurface.UpdateOverlay == NULL )
|
|
{
|
|
LEAVE_DDRAW();
|
|
return DDERR_UNSUPPORTED;
|
|
}
|
|
|
|
uod.overlayFX.dwSize = sizeof( DDOVERLAYFX );
|
|
uod.lpDD = this->lpDD;
|
|
uod.lpDDDestSurface = this_lcl;
|
|
MAKE_SURF_RECT( this, this_lcl, uod.rDest );
|
|
uod.lpDDSrcSurface = this_lcl;
|
|
MAKE_SURF_RECT( this, this_lcl, uod.rSrc );
|
|
uod.dwFlags = dwFlags;
|
|
}
|
|
EXCEPT( EXCEPTION_EXECUTE_HANDLER )
|
|
{
|
|
DPF_ERR( "Exception encountered validating parameters" );
|
|
LEAVE_DDRAW();
|
|
return DDERR_INVALIDPARAMS;
|
|
}
|
|
|
|
/*
|
|
* invoke the HEL
|
|
*/
|
|
rc = pdrv_lcl->lpDDCB->HELDDSurface.UpdateOverlay( &uod );
|
|
|
|
if( rc == DDHAL_DRIVER_HANDLED )
|
|
{
|
|
if( uod.ddRVal == DD_OK )
|
|
{
|
|
DPF( 2, "Refreshed overlayed surface = %08lx", this );
|
|
}
|
|
LEAVE_DDRAW();
|
|
return uod.ddRVal;
|
|
}
|
|
|
|
LEAVE_DDRAW();
|
|
return DDERR_UNSUPPORTED;
|
|
|
|
} /* DD_Surface_UpdateOverlayDisplay */
|