mirror of https://github.com/lianthony/NT4.0
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
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 */
|