Windows NT 4.0 source code leak
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.
 
 
 
 
 
 

1696 lines
40 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
*
***************************************************************************/
#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,
BOOL emulate )
{
DWORD caps;
DWORD basecaps;
BOOL fail;
DWORD dwMinStretch;
DWORD dwMaxStretch;
fail = FALSE;
if( emulate )
{
basecaps = pdrv->ddHELCaps.dwCaps;
caps = pdrv->ddHELCaps.dwFXCaps;
dwMinStretch = pdrv->ddHELCaps.dwMinOverlayStretch;
dwMaxStretch = pdrv->ddHELCaps.dwMaxOverlayStretch;
}
else
{
basecaps = pdrv->ddCaps.dwCaps;
caps = pdrv->ddCaps.dwFXCaps;
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_LCL this_src_lcl,
LPDDRAWI_DDRAWSURFACE_LCL this_dest_lcl,
LPDDHAL_UPDATEOVERLAYDATA puod,
LPDDOVERLAYFX lpDDOverlayFX,
BOOL emulate )
{
DWORD basecaps;
DWORD baseckeycaps;
DWORD dwFlags;
dwFlags= * lpdwFlags;
if( emulate )
{
basecaps = pdrv->ddHELCaps.dwCaps;
baseckeycaps = pdrv->ddHELCaps.dwCKeyCaps;
}
else
{
basecaps = pdrv->ddCaps.dwCaps;
baseckeycaps = pdrv->ddCaps.dwCKeyCaps;
}
/*
* 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)
/*
* 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 */
/*
* 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;
ENTER_DDRAW();
/*
* 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;
}
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;
}
/*
* 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, rdest );
lpDestRect = &rdest;
}
if( lpSrcRect == NULL )
{
MAKE_SURF_RECT( this_src, rsrc );
lpSrcRect = &rsrc;
}
/*
* 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,
emulation );
if( ddrval != DD_OK )
{
LEAVE_DDRAW();
return ddrval;
}
}
/*
* 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_lcl,
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;
}
/*
* 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
*/
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;
DOHALCALL( UpdateOverlay, uofn, uod, rc, emulation );
// 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 )
{
/*
* store the destination rect for later use
*/
this_src_lcl->rcOverlayDest.left = uod.rDest.left;
this_src_lcl->rcOverlayDest.top = uod.rDest.top;
this_src_lcl->rcOverlayDest.right = uod.rDest.right;
this_src_lcl->rcOverlayDest.bottom = uod.rDest.bottom;
/*
* 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 );
}
}
LEAVE_DDRAW();
return uod.ddRVal;
}
}
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();
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( lplXPos ) )
{
LEAVE_DDRAW();
return DDERR_INVALIDPARAMS;
}
*lplXPos = 0;
if( SURFACE_LOST( this_lcl ) )
{
LEAVE_DDRAW();
return DDERR_SURFACELOST;
}
pdrv = this->lpDD;
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;
*lplXPos = 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();
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;
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;
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;
}
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;
ENTER_DDRAW();
/*
* 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;
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;
}
// 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_int == psurf_ref_int )
{
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.
*/
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) );
}
}
LEAVE_DDRAW();
return DD_OK;
} /* 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;
DDSURFACEDESC ddsd;
DWORD rc;
ENTER_DDRAW();
/*
* 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( dwFlags == DDENUMOVERLAYZ_FRONTTOBACK )
{
pdbn = pRoot->next;
while(pdbn != pRoot)
{
FillDDSurfaceDesc( pdbn->object, &ddsd );
DD_Surface_AddRef( (LPDIRECTDRAWSURFACE)(pdbn->object_int));
rc = lpfnCallback( (LPDIRECTDRAWSURFACE)(pdbn->object_int), &ddsd, lpContext );
if( rc == 0)
{
break;
}
pdbn = pdbn->next;
}
}
else if( dwFlags == DDENUMOVERLAYZ_BACKTOFRONT )
{
pdbn = pRoot->prev;
while(pdbn != pRoot)
{
FillDDSurfaceDesc( pdbn->object,&ddsd );
DD_Surface_AddRef( (LPDIRECTDRAWSURFACE)(pdbn->object_int));
rc = lpfnCallback( (LPDIRECTDRAWSURFACE)(pdbn->object_int), &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();
/*
* 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( !(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;
}
}
} /* 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();
/*
* 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;
}
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, uod.rDest );
uod.lpDDSrcSurface = this_lcl;
MAKE_SURF_RECT( this, 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 */