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.
 
 
 
 
 
 

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 */