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.
 
 
 
 
 
 

3255 lines
86 KiB

/*==========================================================================
*
* Copyright (C) 1994-1995 Microsoft Corporation. All Rights Reserved.
*
* File: ddsblt.c
* Content: DirectDraw Surface support for blt
* History:
* Date By Reason
* ==== == ======
* 24-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
* 21-feb-95 craige work work work
* 27-feb-95 craige new sync. macros
* 08-mar-95 craige new stretch flags
* 11-mar-95 craige take Win16 lock on Win95 before calling 32-bit fns
* 15-mar-95 craige HEL integration
* 19-mar-95 craige use HRESULTs
* 29-mar-95 craige make colorfill work
* 01-apr-95 craige happy fun joy updated header file
* 03-apr-95 craige off by one when rect specified; need to validate
* rectangles against surfaces
* 12-apr-95 craige pulled out clipped stretching code optimization for now
* 15-apr-95 craige can't allow source surface with colorfill; don't
* allow < 0 left, top coords
* 06-may-95 craige use driver-level csects only
* 11-jun-95 craige check for locked surface before blt
* 21-jun-95 kylej lock non-emulated surfaces before calling HEL blt
* 21-jun-95 craige clipping changes
* 24-jun-95 kylej move video memory source surfaces to system memory
* if there is no hardware blt support.
* 25-jun-95 craige one ddraw mutex
* 26-jun-95 craige reorganized surface structure
* 27-jun-95 craige use clipper to do clipping; started BltBatch;
* moved CheckBltStretching back in
* 28-jun-95 craige ENTER_DDRAW at very start of fns; disabled alpha & Z blt
* 04-jul-95 craige YEEHAW: new driver struct; SEH
* 05-jul-95 kylej debugged clipping code and added clipped stretched blts
* 07-jul-95 craige added test for BUSY
* 07-jul-95 kylej replace inline code with call to XformRect
* 08-jul-95 craige BltFast: need to use HEL if src or dest is in
* system memory!
* 09-jul-95 craige hasvram flag in MoveToSystemMemory; handle loss
* of color key resource after blt
* 10-jul-95 kylej added mirroring caps checks in Blt
* 13-jul-95 craige ENTER_DDRAW is now the win16 lock
* 16-jul-95 craige check DDRAWISURF_HELCB
* 27-jul-95 craige check for color fill support in hardware!
* 31-jul-95 craige check Lock calls for WASSTILLDRAWING;
* test for valid flags
* 01-aug-95 craige hold win16 early to keep busy bit test valid
* 01-aug-95 toddla added DD16_Exclude and DD16_Unexclude
* 04-aug-95 craige use InternalLock/Unlock
* 06-aug-95 craige do DD16_Exclude before lock, unexclude after unlock
* 10-aug-95 toddla added DDBLT_WAIT and DDBLTFAST_WAIT flags
* 12-aug-95 craige use_full_lock parm for MoveToSystemMemory and
* ChangeToSoftwareColorKey
* 23-aug-95 craige wasn't unlocking surfaces or unexcluding cursor on
* a few error conditions
* 16-sep-95 craige bug 1175: set return code if NULL clip list
* 02-jan-96 kylej handle new interface structures
* 04-jan-96 colinmc added DDBLT_DEPTHFILL for clearing Z-buffers
* 01-feb-96 jeffno NT: pass user-mode ptrs to vram surfaces to HEL
* in Blt and BltFast
* 12-feb-96 colinmc Surface lost flag moved from global to local object
* 29-feb-96 kylej Enable System->Video bltting
* 03-mar-96 colinmc Fixed a couple of nasty bugs causing blts to system
* memory to be done by hardware
* 21-mar-96 colinmc Bug 14011: Insufficient parameter validation on
* BltFast
* 26-mar-96 jeffno Handle visrgn changes under NT
* 20-apr-96 colinmc Fixed problem with releasePageLocks spinning on
* busy bit
* 23-apr-96 kylej Bug 10196: Added check for software dest blt
* 17-may-96 craige bug 21499: perf problems with BltFast
* 14-jun-96 kylej NT Bug 38227: Internal lock was not correctly reporting
* when the visrgn had changed.
*
***************************************************************************/
#include "ddrawpr.h"
#define DONE_BUSY() \
(*pdflags) &= ~BUSY; \
#define LEAVE_BOTH_NOBUSY() \
{ if(pdflags)\
(*pdflags) &= ~BUSY; \
} \
LEAVE_BOTH();
#define DONE_LOCKS() \
if( dest_lock_taken ) \
{ \
InternalUnlock( this_dest_lcl,NULL,0 ); \
dest_lock_taken = FALSE; \
} \
if( src_lock_taken && this_src_lcl) \
{ \
InternalUnlock( this_src_lcl,NULL,0 ); \
src_lock_taken = FALSE; \
}
#undef DPF_MODNAME
#define DPF_MODNAME "BltFast"
// turns off SEH for bltfast
#define FASTFAST
typedef struct _bltcaps
{
LPDWORD dwCaps;
LPDWORD dwFXCaps;
LPDWORD dwCKeyCaps;
LPDWORD dwRops;
LPDWORD dwHELCaps;
LPDWORD dwHELFXCaps;
LPDWORD dwHELCKeyCaps;
LPDWORD dwHELRops;
LPDWORD dwBothCaps;
LPDWORD dwBothFXCaps;
LPDWORD dwBothCKeyCaps;
LPDWORD dwBothRops;
BOOL bPageLockRequired;
BOOL bDestPageLocked;
BOOL bSrcPageLocked;
BOOL bNeedToUnlock;
} BLTCAPS, *LPBLTCAPS;
void initBltCaps( DWORD dwDstCaps, DWORD dwSrcCaps, LPDDRAWI_DIRECTDRAW_GBL pdrv, LPBLTCAPS lpbc, LPBOOL helonly )
{
if( !(pdrv->ddCaps.dwCaps & DDCAPS_CANBLTSYSMEM) )
{
if( (dwSrcCaps & DDSCAPS_SYSTEMMEMORY) || (dwDstCaps & DDSCAPS_SYSTEMMEMORY) )
{
*helonly = TRUE;
}
}
if( ( (dwSrcCaps & DDSCAPS_VIDEOMEMORY) && (dwDstCaps & DDSCAPS_VIDEOMEMORY) ) ||
!( pdrv->ddCaps.dwCaps & DDCAPS_CANBLTSYSMEM ) )
{
lpbc->dwCaps = &(pdrv->ddCaps.dwCaps);
lpbc->dwFXCaps = &(pdrv->ddCaps.dwFXCaps);
lpbc->dwCKeyCaps = &(pdrv->ddCaps.dwCKeyCaps);
lpbc->dwRops = pdrv->ddCaps.dwRops;
lpbc->dwHELCaps = &(pdrv->ddHELCaps.dwCaps);
lpbc->dwHELFXCaps = &(pdrv->ddHELCaps.dwFXCaps);
lpbc->dwHELCKeyCaps = &(pdrv->ddHELCaps.dwCKeyCaps);
lpbc->dwHELRops = pdrv->ddHELCaps.dwRops;
lpbc->dwBothCaps = &(pdrv->ddBothCaps.dwCaps);
lpbc->dwBothFXCaps = &(pdrv->ddBothCaps.dwFXCaps);
lpbc->dwBothCKeyCaps = &(pdrv->ddBothCaps.dwCKeyCaps);
lpbc->dwBothRops = pdrv->ddBothCaps.dwRops;
lpbc->bPageLockRequired = FALSE;
}
else if( (dwSrcCaps & DDSCAPS_SYSTEMMEMORY) && (dwDstCaps & DDSCAPS_VIDEOMEMORY) )
{
lpbc->dwCaps = &(pdrv->ddCaps.dwSVBCaps);
lpbc->dwFXCaps = &(pdrv->ddCaps.dwSVBFXCaps);
lpbc->dwCKeyCaps = &(pdrv->ddCaps.dwSVBCKeyCaps);
lpbc->dwRops = pdrv->ddCaps.dwSVBRops;
lpbc->dwHELCaps = &(pdrv->ddHELCaps.dwSVBCaps);
lpbc->dwHELFXCaps = &(pdrv->ddHELCaps.dwSVBFXCaps);
lpbc->dwHELCKeyCaps = &(pdrv->ddHELCaps.dwSVBCKeyCaps);
lpbc->dwHELRops = pdrv->ddHELCaps.dwSVBRops;
lpbc->dwBothCaps = &(pdrv->ddBothCaps.dwSVBCaps);
lpbc->dwBothFXCaps = &(pdrv->ddBothCaps.dwSVBFXCaps);
lpbc->dwBothCKeyCaps = &(pdrv->ddBothCaps.dwSVBCKeyCaps);
lpbc->dwBothRops = pdrv->ddBothCaps.dwSVBRops;
lpbc->bPageLockRequired = TRUE;
}
else if( (dwSrcCaps & DDSCAPS_VIDEOMEMORY) && (dwDstCaps & DDSCAPS_SYSTEMMEMORY) )
{
lpbc->dwCaps = &(pdrv->ddCaps.dwVSBCaps);
lpbc->dwFXCaps = &(pdrv->ddCaps.dwVSBFXCaps);
lpbc->dwCKeyCaps = &(pdrv->ddCaps.dwVSBCKeyCaps);
lpbc->dwRops = pdrv->ddCaps.dwVSBRops;
lpbc->dwHELCaps = &(pdrv->ddHELCaps.dwVSBCaps);
lpbc->dwHELFXCaps = &(pdrv->ddHELCaps.dwVSBFXCaps);
lpbc->dwHELCKeyCaps = &(pdrv->ddHELCaps.dwVSBCKeyCaps);
lpbc->dwHELRops = pdrv->ddHELCaps.dwVSBRops;
lpbc->dwBothCaps = &(pdrv->ddBothCaps.dwVSBCaps);
lpbc->dwBothFXCaps = &(pdrv->ddBothCaps.dwVSBFXCaps);
lpbc->dwBothCKeyCaps = &(pdrv->ddBothCaps.dwVSBCKeyCaps);
lpbc->dwBothRops = pdrv->ddBothCaps.dwVSBRops;
lpbc->bPageLockRequired = TRUE;
}
else if( (dwSrcCaps & DDSCAPS_SYSTEMMEMORY) && (dwDstCaps & DDSCAPS_SYSTEMMEMORY) )
{
lpbc->dwCaps = &(pdrv->ddCaps.dwSSBCaps);
lpbc->dwFXCaps = &(pdrv->ddCaps.dwSSBFXCaps);
lpbc->dwCKeyCaps = &(pdrv->ddCaps.dwSSBCKeyCaps);
lpbc->dwRops = pdrv->ddCaps.dwSSBRops;
lpbc->dwHELCaps = &(pdrv->ddHELCaps.dwSSBCaps);
lpbc->dwHELFXCaps = &(pdrv->ddHELCaps.dwSSBFXCaps);
lpbc->dwHELCKeyCaps = &(pdrv->ddHELCaps.dwSSBCKeyCaps);
lpbc->dwHELRops = pdrv->ddHELCaps.dwSSBRops;
lpbc->dwBothCaps = &(pdrv->ddBothCaps.dwSSBCaps);
lpbc->dwBothFXCaps = &(pdrv->ddBothCaps.dwSSBFXCaps);
lpbc->dwBothCKeyCaps = &(pdrv->ddBothCaps.dwSSBCKeyCaps);
lpbc->dwBothRops = pdrv->ddBothCaps.dwSSBRops;
lpbc->bPageLockRequired = TRUE;
}
lpbc->bNeedToUnlock = FALSE;
}
__inline void initBltCapsFast(
DWORD dwDstCaps,
DWORD dwSrcCaps,
LPDDRAWI_DIRECTDRAW_GBL pdrv,
LPBLTCAPS lpbc )
{
if( ( (dwSrcCaps & DDSCAPS_VIDEOMEMORY) && (dwDstCaps & DDSCAPS_VIDEOMEMORY) ) ||
!( pdrv->ddCaps.dwCaps & DDCAPS_CANBLTSYSMEM ) )
{
lpbc->dwCaps = &(pdrv->ddCaps.dwCaps);
lpbc->dwHELCaps = &(pdrv->ddHELCaps.dwCaps);
lpbc->dwBothCaps = &(pdrv->ddBothCaps.dwCaps);
lpbc->bPageLockRequired = FALSE;
}
else if( (dwSrcCaps & DDSCAPS_SYSTEMMEMORY) && (dwDstCaps & DDSCAPS_VIDEOMEMORY) )
{
lpbc->dwCaps = &(pdrv->ddCaps.dwSVBCaps);
lpbc->dwHELCaps = &(pdrv->ddHELCaps.dwSVBCaps);
lpbc->dwBothCaps = &(pdrv->ddBothCaps.dwSVBCaps);
lpbc->bPageLockRequired = TRUE;
}
else if( (dwSrcCaps & DDSCAPS_VIDEOMEMORY) && (dwDstCaps & DDSCAPS_SYSTEMMEMORY) )
{
lpbc->dwCaps = &(pdrv->ddCaps.dwVSBCaps);
lpbc->dwHELCaps = &(pdrv->ddHELCaps.dwVSBCaps);
lpbc->dwBothCaps = &(pdrv->ddBothCaps.dwVSBCaps);
lpbc->bPageLockRequired = TRUE;
}
else if( (dwSrcCaps & DDSCAPS_SYSTEMMEMORY) && (dwDstCaps & DDSCAPS_SYSTEMMEMORY) )
{
lpbc->dwCaps = &(pdrv->ddCaps.dwSSBCaps);
lpbc->dwHELCaps = &(pdrv->ddHELCaps.dwSSBCaps);
lpbc->dwBothCaps = &(pdrv->ddBothCaps.dwSSBCaps);
lpbc->bPageLockRequired = TRUE;
}
lpbc->bNeedToUnlock = FALSE;
}
void releasePageLocks( LPBLTCAPS lpbc, LPDDRAWI_DDRAWSURFACE_INT this_dest_int,
LPDDRAWI_DDRAWSURFACE_INT this_src_int )
{
while( DD_Surface_GetBltStatus( (LPDIRECTDRAWSURFACE)this_dest_int, DDGBS_ISBLTDONE ) != DD_OK )
;
if( lpbc->bDestPageLocked )
DD_Surface_PageUnlock( (LPDIRECTDRAWSURFACE)this_dest_int, 0 );
if( lpbc->bSrcPageLocked )
DD_Surface_PageUnlock( (LPDIRECTDRAWSURFACE)this_src_int, 0 );
}
/*
* DD_Surface_BltFast
*
* Bit Blt from one surface to another FAST
*/
HRESULT DDAPI DD_Surface_BltFast(
LPDIRECTDRAWSURFACE lpDDDestSurface,
DWORD dwX,
DWORD dwY,
LPDIRECTDRAWSURFACE lpDDSrcSurface,
LPRECT lpSrcRect,
DWORD dwTrans )
{
LPDDRAWI_DIRECTDRAW_LCL pdrv_lcl;
LPDDRAWI_DIRECTDRAW_GBL pdrv;
LPDDRAWI_DDRAWSURFACE_INT this_src_int;
LPDDRAWI_DDRAWSURFACE_INT this_dest_int;
LPDDRAWI_DDRAWSURFACE_LCL this_src_lcl;
LPDDRAWI_DDRAWSURFACE_LCL this_dest_lcl;
LPDDRAWI_DDRAWSURFACE_GBL this_src;
LPDDRAWI_DDRAWSURFACE_GBL this_dest;
DDHAL_BLTDATA bd;
DWORD rc;
LPDDHALSURFCB_BLT bltfn;
BOOL halonly;
BOOL helonly;
int src_height;
int src_width;
BOOL dest_lock_taken=FALSE;
BOOL src_lock_taken=FALSE;
LPVOID dest_bits;
LPVOID src_bits;
HRESULT ddrval;
BLTCAPS bc;
LPBLTCAPS lpbc = &bc;
LPWORD pdflags=0;
ENTER_BOTH();
/*
* prepare parameters. An exception here is considered a bad parameter
*/
#ifndef FASTFAST
TRY
#endif
{
this_dest_int = (LPDDRAWI_DDRAWSURFACE_INT) lpDDDestSurface;
if( !VALID_DIRECTDRAWSURFACE_PTR( this_dest_int ) )
{
LEAVE_BOTH()
return DDERR_INVALIDOBJECT;
}
this_dest_lcl = this_dest_int->lpLcl;
this_dest = this_dest_lcl->lpGbl;
if( SURFACE_LOST( this_dest_lcl ) )
{
DPF( 1, "Destination (%08lx) is lost", this_dest_int );
LEAVE_BOTH();
return DDERR_SURFACELOST;
}
this_src_int = (LPDDRAWI_DDRAWSURFACE_INT) lpDDSrcSurface;
if( !VALID_DIRECTDRAWSURFACE_PTR( this_src_int ) )
{
LEAVE_BOTH();
return DDERR_INVALIDOBJECT;
}
this_src_lcl = this_src_int->lpLcl;
this_src = this_src_lcl->lpGbl;
if( SURFACE_LOST( this_src_lcl ) )
{
DPF( 1, "Source (%08lx) is lost", this_src_int );
LEAVE_BOTH();
return DDERR_SURFACELOST;
}
if( lpSrcRect != NULL )
{
if( !VALID_RECT_PTR( lpSrcRect ) )
{
LEAVE_BOTH()
return DDERR_INVALIDPARAMS;
}
}
if( dwTrans & ~DDBLTFAST_VALID )
{
DPF_ERR( "Invalid flags") ;
LEAVE_BOTH();
return DDERR_INVALIDPARAMS;
}
pdrv = this_dest->lpDD;
pdrv_lcl = this_dest_lcl->lpSurfMore->lpDD_lcl;
// Test and set the busy bit. If it was already set, bail.
{
BOOL isbusy = 0;
pdflags = pdrv->lpwPDeviceFlags;
#ifdef WIN95
_asm
{
mov eax, pdflags
bts word ptr [eax], BUSY_BIT
adc byte ptr isbusy,0
}
#else
isbusy -= (InterlockedExchange((LPDWORD)pdflags,
*((LPDWORD)pdflags) | (1<<BUSY_BIT) ) == (1<<BUSY_BIT) );
#endif
if( isbusy )
{
DPF( 3, "BUSY - BltFast" );
LEAVE_BOTH();
return DDERR_SURFACEBUSY;
}
}
RESTART_BLTFAST:
/*
* is either surface locked?
*/
if( this_src->dwUsageCount > 0 || this_dest->dwUsageCount > 0 )
{
DPF_ERR( "Surface is locked" );
LEAVE_BOTH_NOBUSY()
return DDERR_SURFACEBUSY;
}
// no restrictions yet
halonly = FALSE;
helonly = FALSE;
// initialize the blit caps according to the surface types
initBltCapsFast( this_dest_lcl->ddsCaps.dwCaps, this_src_lcl->ddsCaps.dwCaps, pdrv, lpbc );
if( !( pdrv->ddCaps.dwCaps & DDCAPS_CANBLTSYSMEM ) &&
( ( this_dest_lcl->ddsCaps.dwCaps & DDSCAPS_SYSTEMMEMORY ) ||
( this_src_lcl->ddsCaps.dwCaps & DDSCAPS_SYSTEMMEMORY ) ) )
{
helonly = TRUE;
}
/*
* check for HEL composition buffer
*/
if( (this_dest_lcl->dwFlags & DDRAWISURF_HELCB) ||
(this_src_lcl->dwFlags & DDRAWISURF_HELCB) )
{
helonly = TRUE;
}
/*
* does the driver even allow bltting?
*/
if( !(*(lpbc->dwBothCaps) & DDCAPS_BLT) )
{
BOOL fail;
fail = FALSE;
GETFAILCODEBLT( *(lpbc->dwCaps),
*(lpbc->dwHELCaps),
halonly,
helonly,
DDCAPS_BLT );
if( fail )
{
DPF_ERR( "Blt not supported" );
LEAVE_BOTH_NOBUSY()
return DDERR_NOBLTHW;
}
}
/*
* get src rectangle
*/
if( lpSrcRect == NULL )
{
MAKE_SURF_RECT( this_src, bd.rSrc );
src_height = this_src->wHeight;
src_width = this_src->wWidth;
}
else
{
bd.rSrc = *(LPRECTL)lpSrcRect;
src_height = (bd.rSrc.bottom-bd.rSrc.top);
if( (src_height <= 0) ||
((DWORD) bd.rSrc.bottom > (DWORD) this_src->wHeight) )
{
DPF( 2, "Invalid Height: %ld, top=%ld, bottom=%ld, srcHeight=%ld",
src_height, bd.rSrc.top, bd.rSrc.bottom, this_src->wHeight );
LEAVE_BOTH_NOBUSY()
return DDERR_INVALIDRECT;
}
src_width = (bd.rSrc.right-bd.rSrc.left);
if( (src_width <= 0) ||
((DWORD) bd.rSrc.right > (DWORD) this_src->wWidth) )
{
DPF( 2, "Invalid Width: %ld, right=%ld, left=%ld, srcWidth=%ld",
src_width, bd.rSrc.right, bd.rSrc.left, this_src->wWidth );
LEAVE_BOTH_NOBUSY()
return DDERR_INVALIDRECT;
}
}
/*
* Ensure the destination offsets are valid.
*/
if( dwX >= this_dest->wWidth )
{
DPF( 0, "Invalid destination x offset %ld", dwX );
LEAVE_BOTH_NOBUSY()
return DDERR_INVALIDRECT;
}
if( dwY >= this_dest->wHeight )
{
DPF( 0, "Invalid destination y offset %ld", dwY );
LEAVE_BOTH_NOBUSY()
return DDERR_INVALIDRECT;
}
/*
* get destination rectangle
*/
bd.rDest.top = dwY;
bd.rDest.left = dwX;
bd.rDest.bottom = dwY + (DWORD) src_height;
if( (DWORD) bd.rDest.bottom > (DWORD) this_dest->wHeight )
{
DPF_ERR( "Invalid dest height" );
LEAVE_BOTH_NOBUSY()
return DDERR_INVALIDRECT;
}
bd.rDest.right = dwX + (DWORD) src_width;
if( (DWORD) bd.rDest.right > (DWORD) this_dest->wWidth )
{
DPF_ERR( "Invalid dest width" );
LEAVE_BOTH_NOBUSY()
return DDERR_INVALIDRECT;
}
/*
* transparent?
*/
switch( dwTrans & DDBLTFAST_COLORKEY_MASK )
{
case DDBLTFAST_NOCOLORKEY:
bd.dwFlags = DDBLT_ROP;
break;
case DDBLTFAST_SRCCOLORKEY:
if( !(this_src_lcl->dwFlags & DDRAWISURF_HASCKEYSRCBLT) )
{
DPF_ERR( "No colorkey on source" );
LEAVE_BOTH_NOBUSY()
return DDERR_INVALIDPARAMS;
}
if( this_src_lcl->dwFlags & DDRAWISURF_SW_CKEYSRCBLT )
{
if( halonly )
{
DPF_ERR( "Cannot do transparent blt!" );
LEAVE_BOTH_NOBUSY()
return DDERR_INVALIDPARAMS;
}
helonly = TRUE;
}
if( this_src_lcl->dwFlags & DDRAWISURF_HW_CKEYSRCBLT )
{
if( helonly )
{
DPF_ERR( "Cannot do transparent blt!" );
LEAVE_BOTH_NOBUSY()
return DDERR_INVALIDPARAMS;
}
halonly = TRUE;
}
bd.bltFX.ddckSrcColorkey = this_src_lcl->ddckCKSrcBlt;
bd.dwFlags = DDBLT_ROP | DDBLT_KEYSRCOVERRIDE;
break;
case DDBLTFAST_DESTCOLORKEY:
if( !(this_dest_lcl->dwFlags & DDRAWISURF_HASCKEYDESTBLT) )
{
DPF_ERR( "No colorkey on dest" );
LEAVE_BOTH_NOBUSY()
return DDERR_INVALIDPARAMS;
}
if( this_dest_lcl->dwFlags & DDRAWISURF_SW_CKEYDESTBLT )
{
if( halonly )
{
DPF_ERR( "Cannot do transparent blt!" );
LEAVE_BOTH_NOBUSY()
return DDERR_UNSUPPORTED;
}
helonly = TRUE;
}
if( this_dest_lcl->dwFlags & DDRAWISURF_HW_CKEYDESTBLT )
{
if( helonly )
{
DPF_ERR( "Cannot do transparent blt!" );
LEAVE_BOTH_NOBUSY()
return DDERR_UNSUPPORTED;
}
halonly = TRUE;
}
bd.bltFX.ddckDestColorkey = this_dest_lcl->ddckCKDestBlt;
bd.dwFlags = DDBLT_ROP | DDBLT_KEYDESTOVERRIDE;
break;
}
}
#ifndef FASTFAST
EXCEPT( EXCEPTION_EXECUTE_HANDLER )
{
DPF_ERR( "Exception encountered validating parameters" );
LEAVE_BOTH_NOBUSY()
return DDERR_INVALIDPARAMS;
}
#endif
/*
* do the blt
*/
#ifndef FASTFAST
TRY
#endif
{
bd.bltFX.dwROP = SRCCOPY;
bd.lpDDDestSurface = this_dest_lcl;
bd.lpDDSrcSurface = this_src_lcl;
if( helonly && halonly )
{
DPF_ERR( "BLT not supported in software or hardware" );
LEAVE_BOTH_NOBUSY()
return DDERR_NOBLTHW;
}
// Did the mode change since ENTER_DDRAW?
#ifdef WINNT
if ( DdQueryDisplaySettingsUniqueness() != uDisplaySettingsUnique )
{
// mode changed, don't do the blt
DPF_ERR( "Mode changed between ENTER_DDRAW and HAL call" );
LEAVE_BOTH_NOBUSY()
return DDERR_SURFACELOST;
}
#endif
if( helonly ) // must be HEL call
{
DPF( 4, "Software FastBlt");
bltfn = pdrv_lcl->lpDDCB->HELDDSurface.Blt;
// take locks on vram surfaces
if( ( this_dest_lcl->ddsCaps.dwCaps & DDSCAPS_SYSTEMMEMORY ) == 0)
{
while( 1 )
{
ddrval = InternalLock( this_dest_lcl, &dest_bits, NULL, 0);
if( ddrval == DD_OK )
{
#ifdef WINNT
this_dest->fpVidMem = (FLATPTR) dest_bits;
#endif
break;
}
if( ddrval == DDERR_WASSTILLDRAWING )
{
continue;
}
LEAVE_BOTH_NOBUSY()
return ddrval;
}
dest_lock_taken = TRUE;
}
else
{
dest_lock_taken = FALSE;
}
if( (lpDDSrcSurface != lpDDDestSurface) &&
( ( this_src_lcl->ddsCaps.dwCaps & DDSCAPS_SYSTEMMEMORY ) == 0) )
{
if( MoveToSystemMemory( this_src_int, TRUE, FALSE ) == DD_OK )
{
src_lock_taken = FALSE;
}
else
{
while( 1 )
{
ddrval = InternalLock( this_src_lcl, &src_bits, NULL, 0);
if( ddrval == DD_OK )
{
#ifdef WINNT
this_src->fpVidMem = (FLATPTR) src_bits;
#endif
break;
}
if( ddrval == DDERR_WASSTILLDRAWING )
{
continue;
}
if( dest_lock_taken )
{
InternalUnlock( this_dest_lcl, NULL, 0 );
}
LEAVE_BOTH_NOBUSY()
return ddrval;
}
src_lock_taken = TRUE;
}
}
else
{
src_lock_taken = FALSE;
}
}
else
{
DPF( 4, "Hardware FastBlt");
bltfn = pdrv_lcl->lpDDCB->HALDDSurface.Blt;
bd.Blt = pdrv_lcl->lpDDCB->cbDDSurfaceCallbacks.Blt;
if( lpbc->bPageLockRequired )
{
/*
* Make sure the surfaces are pagelocked
*/
if( (this_dest_lcl->lpSurfMore->dwPageLockCount == 0) &&
(this_dest_lcl->ddsCaps.dwCaps & DDSCAPS_SYSTEMMEMORY) )
{
DD_Surface_PageLock( (LPDIRECTDRAWSURFACE)this_dest_int, 0 );
lpbc->bDestPageLocked = TRUE;
lpbc->bNeedToUnlock = TRUE;
}
else
{
lpbc->bDestPageLocked = FALSE;
}
if( (this_src_lcl->lpSurfMore->dwPageLockCount == 0) &&
(this_src_lcl->ddsCaps.dwCaps & DDSCAPS_SYSTEMMEMORY) )
{
DD_Surface_PageLock( (LPDIRECTDRAWSURFACE)this_src_int, 0 );
lpbc->bSrcPageLocked = TRUE;
lpbc->bNeedToUnlock = TRUE;
}
else
{
lpbc->bSrcPageLocked = FALSE;
}
}
}
bd.lpDD = pdrv;
bd.bltFX.dwSize = sizeof( bd.bltFX );
if( this_dest_lcl->lpDDClipper == NULL )
{
bd.IsClipped = FALSE; // no clipping in BltFast
try_again:
DOHALCALL_NOWIN16( Blt, bltfn, bd, rc, helonly );
#ifdef WINNT
DDASSERT( ! (rc == DDHAL_DRIVER_HANDLED && bd.ddRVal == DDERR_VISRGNCHANGED) );
#endif
if ( (dwTrans & DDBLTFAST_WAIT) &&
rc == DDHAL_DRIVER_HANDLED &&
bd.ddRVal == DDERR_WASSTILLDRAWING )
{
DPF(4, "Waiting...");
goto try_again;
}
DPF(4,"Driver returned %08x",bd.ddRVal);
}
else
{
DPF_ERR( "Can't clip in BltFast" );
bd.ddRVal = DDERR_BLTFASTCANTCLIP;
}
if( helonly )
{
DONE_LOCKS();
}
if( rc != DDHAL_DRIVER_HANDLED )
{
/*
* did the driver run out of hardware color key resources?
*/
if( (rc == DDHAL_DRIVER_NOCKEYHW) &&
((dwTrans & DDBLTFAST_COLORKEY_MASK) == DDBLTFAST_SRCCOLORKEY) )
{
ddrval = ChangeToSoftwareColorKey( this_src_int, FALSE );
if( ddrval == DD_OK )
{
halonly = FALSE;
helonly = FALSE;
goto RESTART_BLTFAST;
}
else
{
bd.ddRVal = DDERR_NOCOLORKEYHW;
}
}
else
{
bd.ddRVal = DDERR_UNSUPPORTED;
}
}
/*
* NOTE: We cannot use LEAVE_BOTH_NOBUSY in this scenario as
* releasePageLocks() calls GetBltStatus() to ensure that blts
* are finished before releasing the page locks. Therefore,
* the busy bit must be cleared before this function is called.
* However, we can't release the critical section until after
* releasePageLocks() finishes so we have to split the
* functionality.
*/
DONE_BUSY();
if( lpbc->bNeedToUnlock )
releasePageLocks( lpbc, this_dest_int, this_src_int );
LEAVE_BOTH();
return bd.ddRVal;
}
#ifndef FASTFAST
EXCEPT( EXCEPTION_EXECUTE_HANDLER )
{
DPF_ERR( "Exception encountered processing blt" );
DONE_LOCKS();
DONE_BUSY();
if( lpbc->bNeedToUnlock )
releasePageLocks( lpbc, this_dest_int, this_src_int );
LEAVE_BOTH();
return DDERR_EXCEPTION;
}
#endif
} /* DD_Surface_BltFast */
#undef DPF_MODNAME
#define DPF_MODNAME "Blt"
/*
* ROP table
*
* tells which ROPS require pattern surfaces and/or source surfaces
*/
static char cROPTable[] = {
0, // 00 0 BLACKNESS
ROP_HAS_SOURCEPATTERN, // 01 DPSoon
ROP_HAS_SOURCEPATTERN, // 02 DPSona
ROP_HAS_SOURCEPATTERN, // 03 PSon
ROP_HAS_SOURCEPATTERN, // 04 SDPona
ROP_HAS_PATTERN, // 05 DPon
ROP_HAS_SOURCEPATTERN, // 06 PDSxnon
ROP_HAS_SOURCEPATTERN, // 07 PDSaon
ROP_HAS_SOURCEPATTERN, // 08 SDPnaa
ROP_HAS_SOURCEPATTERN, // 09 PDSxon
ROP_HAS_PATTERN, // 0A DPna
ROP_HAS_SOURCEPATTERN, // 0B PSDnaon
ROP_HAS_SOURCEPATTERN, // 0C SPna
ROP_HAS_SOURCEPATTERN, // 0D PDSnaon
ROP_HAS_SOURCEPATTERN, // 0E PDSonon
ROP_HAS_PATTERN, // 0F Pn
ROP_HAS_SOURCEPATTERN, // 10 PDSona
ROP_HAS_SOURCE, // 11 DSon NOTSRCERASE
ROP_HAS_SOURCEPATTERN, // 12 SDPxnon
ROP_HAS_SOURCEPATTERN, // 13 SDPaon
ROP_HAS_SOURCEPATTERN, // 14 DPSxnon
ROP_HAS_SOURCEPATTERN, // 15 DPSaon
ROP_HAS_SOURCEPATTERN, // 16 PSDPSanaxx
ROP_HAS_SOURCEPATTERN, // 17 SSPxDSxaxn
ROP_HAS_SOURCEPATTERN, // 18 SPxPDxa
ROP_HAS_SOURCEPATTERN, // 19 SDPSanaxn
ROP_HAS_SOURCEPATTERN, // 1A PDSPaox
ROP_HAS_SOURCEPATTERN, // 1B SDPSxaxn
ROP_HAS_SOURCEPATTERN, // 1C PSDPaox
ROP_HAS_SOURCEPATTERN, // 1D DSPDxaxn
ROP_HAS_SOURCEPATTERN, // 1E PDSox
ROP_HAS_SOURCEPATTERN, // 1F PDSoan
ROP_HAS_SOURCEPATTERN, // 20 DPSnaa
ROP_HAS_SOURCEPATTERN, // 21 SDPxon
ROP_HAS_SOURCE, // 22 DSna
ROP_HAS_SOURCEPATTERN, // 23 SPDnaon
ROP_HAS_SOURCEPATTERN, // 24 SPxDSxa
ROP_HAS_SOURCEPATTERN, // 25 PDSPanaxn
ROP_HAS_SOURCEPATTERN, // 26 SDPSaox
ROP_HAS_SOURCEPATTERN, // 27 SDPSxnox
ROP_HAS_SOURCEPATTERN, // 28 DPSxa
ROP_HAS_SOURCEPATTERN, // 29 PSDPSaoxxn
ROP_HAS_SOURCEPATTERN, // 2A DPSana
ROP_HAS_SOURCEPATTERN, // 2B SSPxPDxaxn
ROP_HAS_SOURCEPATTERN, // 2C SPDSoax
ROP_HAS_SOURCEPATTERN, // 2D PSDnox
ROP_HAS_SOURCEPATTERN, // 2E PSDPxox
ROP_HAS_SOURCEPATTERN, // 2F PSDnoan
ROP_HAS_SOURCEPATTERN, // 30 PSna
ROP_HAS_SOURCEPATTERN, // 31 SDPnaon
ROP_HAS_SOURCEPATTERN, // 32 SDPSoox
ROP_HAS_SOURCE, // 33 Sn NOTSRCCOPY
ROP_HAS_SOURCEPATTERN, // 34 SPDSaox
ROP_HAS_SOURCEPATTERN, // 35 SPDSxnox
ROP_HAS_SOURCEPATTERN, // 36 SDPox
ROP_HAS_SOURCEPATTERN, // 37 SDPoan
ROP_HAS_SOURCEPATTERN, // 38 PSDPoax
ROP_HAS_SOURCEPATTERN, // 39 SPDnox
ROP_HAS_SOURCEPATTERN, // 3A SPDSxox
ROP_HAS_SOURCEPATTERN, // 3B SPDnoan
ROP_HAS_SOURCEPATTERN, // 3C PSx
ROP_HAS_SOURCEPATTERN, // 3D SPDSonox
ROP_HAS_SOURCEPATTERN, // 3E SPDSnaox
ROP_HAS_SOURCEPATTERN, // 3F PSan
ROP_HAS_SOURCEPATTERN, // 40 PSDnaa
ROP_HAS_SOURCEPATTERN, // 41 DPSxon
ROP_HAS_SOURCEPATTERN, // 42 SDxPDxa
ROP_HAS_SOURCEPATTERN, // 43 SPDSanaxn
ROP_HAS_SOURCE, // 44 SDna SRCERASE
ROP_HAS_SOURCEPATTERN, // 45 DPSnaon
ROP_HAS_SOURCEPATTERN, // 46 DSPDaox
ROP_HAS_SOURCEPATTERN, // 47 PSDPxaxn
ROP_HAS_SOURCEPATTERN, // 48 SDPxa
ROP_HAS_SOURCEPATTERN, // 49 PDSPDaoxxn
ROP_HAS_SOURCEPATTERN, // 4A DPSDoax
ROP_HAS_SOURCEPATTERN, // 4B PDSnox
ROP_HAS_SOURCEPATTERN, // 4C SDPana
ROP_HAS_SOURCEPATTERN, // 4D SSPxDSxoxn
ROP_HAS_SOURCEPATTERN, // 4E PDSPxox
ROP_HAS_SOURCEPATTERN, // 4F PDSnoan
ROP_HAS_PATTERN, // 50 PDna
ROP_HAS_SOURCEPATTERN, // 51 DSPnaon
ROP_HAS_SOURCEPATTERN, // 52 DPSDaox
ROP_HAS_SOURCEPATTERN, // 53 SPDSxaxn
ROP_HAS_SOURCEPATTERN, // 54 DPSonon
0, // 55 Dn DSTINVERT
ROP_HAS_SOURCEPATTERN, // 56 DPSox
ROP_HAS_SOURCEPATTERN, // 57 DPSoan
ROP_HAS_SOURCEPATTERN, // 58 PDSPoax
ROP_HAS_SOURCEPATTERN, // 59 DPSnox
ROP_HAS_PATTERN, // 5A DPx PATINVERT
ROP_HAS_SOURCEPATTERN, // 5B DPSDonox
ROP_HAS_SOURCEPATTERN, // 5C DPSDxox
ROP_HAS_SOURCEPATTERN, // 5D DPSnoan
ROP_HAS_SOURCEPATTERN, // 5E DPSDnaox
ROP_HAS_PATTERN, // 5F DPan
ROP_HAS_SOURCEPATTERN, // 60 PDSxa
ROP_HAS_SOURCEPATTERN, // 61 DSPDSaoxxn
ROP_HAS_SOURCEPATTERN, // 62 DSPDoax
ROP_HAS_SOURCEPATTERN, // 63 SDPnox
ROP_HAS_SOURCEPATTERN, // 64 SDPSoax
ROP_HAS_SOURCEPATTERN, // 65 DSPnox
ROP_HAS_SOURCE, // 66 DSx SRCINVERT
ROP_HAS_SOURCEPATTERN, // 67 SDPSonox
ROP_HAS_SOURCEPATTERN, // 68 DSPDSonoxxn
ROP_HAS_SOURCEPATTERN, // 69 PDSxxn
ROP_HAS_SOURCEPATTERN, // 6A DPSax
ROP_HAS_SOURCEPATTERN, // 6B PSDPSoaxxn
ROP_HAS_SOURCEPATTERN, // 6C SDPax
ROP_HAS_SOURCEPATTERN, // 6D PDSPDoaxxn
ROP_HAS_SOURCEPATTERN, // 6E SDPSnoax
ROP_HAS_SOURCEPATTERN, // 6F PDSxnan
ROP_HAS_SOURCEPATTERN, // 70 PDSana
ROP_HAS_SOURCEPATTERN, // 71 SSDxPDxaxn
ROP_HAS_SOURCEPATTERN, // 72 SDPSxox
ROP_HAS_SOURCEPATTERN, // 73 SDPnoan
ROP_HAS_SOURCEPATTERN, // 74 DSPDxox
ROP_HAS_SOURCEPATTERN, // 75 DSPnoan
ROP_HAS_SOURCEPATTERN, // 76 SDPSnaox
ROP_HAS_SOURCE, // 77 DSan
ROP_HAS_SOURCEPATTERN, // 78 PDSax
ROP_HAS_SOURCEPATTERN, // 79 DSPDSoaxxn
ROP_HAS_SOURCEPATTERN, // 7A DPSDnoax
ROP_HAS_SOURCEPATTERN, // 7B SDPxnan
ROP_HAS_SOURCEPATTERN, // 7C SPDSnoax
ROP_HAS_SOURCEPATTERN, // 7D DPSxnan
ROP_HAS_SOURCEPATTERN, // 7E SPxDSxo
ROP_HAS_SOURCEPATTERN, // 7F DPSaan
ROP_HAS_SOURCEPATTERN, // 80 DPSaa
ROP_HAS_SOURCEPATTERN, // 81 SPxDSxon
ROP_HAS_SOURCEPATTERN, // 82 DPSxna
ROP_HAS_SOURCEPATTERN, // 83 SPDSnoaxn
ROP_HAS_SOURCEPATTERN, // 84 SDPxna
ROP_HAS_SOURCEPATTERN, // 85 PDSPnoaxn
ROP_HAS_SOURCEPATTERN, // 86 DSPDSoaxx
ROP_HAS_SOURCEPATTERN, // 87 PDSaxn
ROP_HAS_SOURCE, // 88 DSa SRCAND
ROP_HAS_SOURCEPATTERN, // 89 SDPSnaoxn
ROP_HAS_SOURCEPATTERN, // 8A DSPnoa
ROP_HAS_SOURCEPATTERN, // 8B DSPDxoxn
ROP_HAS_SOURCEPATTERN, // 8C SDPnoa
ROP_HAS_SOURCEPATTERN, // 8D SDPSxoxn
ROP_HAS_SOURCEPATTERN, // 8E SSDxPDxax
ROP_HAS_SOURCEPATTERN, // 8F PDSanan
ROP_HAS_SOURCEPATTERN, // 90 PDSxna
ROP_HAS_SOURCEPATTERN, // 91 SDPSnoaxn
ROP_HAS_SOURCEPATTERN, // 92 DPSDPoaxx
ROP_HAS_SOURCEPATTERN, // 93 SPDaxn
ROP_HAS_SOURCEPATTERN, // 94 PSDPSoaxx
ROP_HAS_SOURCEPATTERN, // 95 DPSaxn
ROP_HAS_SOURCEPATTERN, // 96 DPSxx
ROP_HAS_SOURCEPATTERN, // 97 PSDPSonoxx
ROP_HAS_SOURCEPATTERN, // 98 SDPSonoxn
ROP_HAS_SOURCE, // 99 DSxn
ROP_HAS_SOURCEPATTERN, // 9A DPSnax
ROP_HAS_SOURCEPATTERN, // 9B SDPSoaxn
ROP_HAS_SOURCEPATTERN, // 9C SPDnax
ROP_HAS_SOURCEPATTERN, // 9D DSPDoaxn
ROP_HAS_SOURCEPATTERN, // 9E DSPDSaoxx
ROP_HAS_SOURCEPATTERN, // 9F PDSxan
ROP_HAS_PATTERN, // A0 DPa
ROP_HAS_SOURCEPATTERN, // A1 PDSPnaoxn
ROP_HAS_SOURCEPATTERN, // A2 DPSnoa
ROP_HAS_SOURCEPATTERN, // A3 DPSDxoxn
ROP_HAS_SOURCEPATTERN, // A4 PDSPonoxn
ROP_HAS_PATTERN, // A5 PDxn
ROP_HAS_SOURCEPATTERN, // A6 DSPnax
ROP_HAS_SOURCEPATTERN, // A7 PDSPoaxn
ROP_HAS_SOURCEPATTERN, // A8 DPSoa
ROP_HAS_SOURCEPATTERN, // A9 DPSoxn
0, // AA D
ROP_HAS_SOURCEPATTERN, // AB DPSono
ROP_HAS_SOURCEPATTERN, // AC SPDSxax
ROP_HAS_SOURCEPATTERN, // AD DPSDaoxn
ROP_HAS_SOURCEPATTERN, // AE DSPnao
ROP_HAS_PATTERN, // AF DPno
ROP_HAS_SOURCEPATTERN, // B0 PDSnoa
ROP_HAS_SOURCEPATTERN, // B1 PDSPxoxn
ROP_HAS_SOURCEPATTERN, // B2 SSPxDSxox
ROP_HAS_SOURCEPATTERN, // B3 SDPanan
ROP_HAS_SOURCEPATTERN, // B4 PSDnax
ROP_HAS_SOURCEPATTERN, // B5 DPSDoaxn
ROP_HAS_SOURCEPATTERN, // B6 DPSDPaoxx
ROP_HAS_SOURCEPATTERN, // B7 SDPxan
ROP_HAS_SOURCEPATTERN, // B8 PSDPxax
ROP_HAS_SOURCEPATTERN, // B9 DSPDaoxn
ROP_HAS_SOURCEPATTERN, // BA DPSnao
ROP_HAS_SOURCE, // BB DSno MERGEPAINT
ROP_HAS_SOURCEPATTERN, // BC SPDSanax
ROP_HAS_SOURCEPATTERN, // BD SDxPDxan
ROP_HAS_SOURCEPATTERN, // BE DPSxo
ROP_HAS_SOURCEPATTERN, // BF DPSano MERGECOPY
ROP_HAS_SOURCEPATTERN, // C0 PSa
ROP_HAS_SOURCEPATTERN, // C1 SPDSnaoxn
ROP_HAS_SOURCEPATTERN, // C2 SPDSonoxn
ROP_HAS_SOURCEPATTERN, // C3 PSxn
ROP_HAS_SOURCEPATTERN, // C4 SPDnoa
ROP_HAS_SOURCEPATTERN, // C5 SPDSxoxn
ROP_HAS_SOURCEPATTERN, // C6 SDPnax
ROP_HAS_SOURCEPATTERN, // C7 PSDPoaxn
ROP_HAS_SOURCEPATTERN, // C8 SDPoa
ROP_HAS_SOURCEPATTERN, // C9 SPDoxn
ROP_HAS_SOURCEPATTERN, // CA DPSDxax
ROP_HAS_SOURCEPATTERN, // CB SPDSaoxn
ROP_HAS_SOURCE, // CC S SRCCOPY
ROP_HAS_SOURCEPATTERN, // CD SDPono
ROP_HAS_SOURCEPATTERN, // CE SDPnao
ROP_HAS_SOURCEPATTERN, // CF SPno
ROP_HAS_SOURCEPATTERN, // D0 PSDnoa
ROP_HAS_SOURCEPATTERN, // D1 PSDPxoxn
ROP_HAS_SOURCEPATTERN, // D2 PDSnax
ROP_HAS_SOURCEPATTERN, // D3 SPDSoaxn
ROP_HAS_SOURCEPATTERN, // D4 SSPxPDxax
ROP_HAS_SOURCEPATTERN, // D5 DPSanan
ROP_HAS_SOURCEPATTERN, // D6 PSDPSaoxx
ROP_HAS_SOURCEPATTERN, // D7 DPSxan
ROP_HAS_SOURCEPATTERN, // D8 PDSPxax
ROP_HAS_SOURCEPATTERN, // D9 SDPSaoxn
ROP_HAS_SOURCEPATTERN, // DA DPSDanax
ROP_HAS_SOURCEPATTERN, // DB SPxDSxan
ROP_HAS_SOURCEPATTERN, // DC SPDnao
ROP_HAS_SOURCE, // DD SDno
ROP_HAS_SOURCEPATTERN, // DE SDPxo
ROP_HAS_SOURCEPATTERN, // DF SDPano
ROP_HAS_SOURCEPATTERN, // E0 PDSoa
ROP_HAS_SOURCEPATTERN, // E1 PDSoxn
ROP_HAS_SOURCEPATTERN, // E2 DSPDxax
ROP_HAS_SOURCEPATTERN, // E3 PSDPaoxn
ROP_HAS_SOURCEPATTERN, // E4 SDPSxax
ROP_HAS_SOURCEPATTERN, // E5 PDSPaoxn
ROP_HAS_SOURCEPATTERN, // E6 SDPSanax
ROP_HAS_SOURCEPATTERN, // E7 SPxPDxan
ROP_HAS_SOURCEPATTERN, // E8 SSPxDSxax
ROP_HAS_SOURCEPATTERN, // E9 DSPDSanaxxn
ROP_HAS_SOURCEPATTERN, // EA DPSao
ROP_HAS_SOURCEPATTERN, // EB DPSxno
ROP_HAS_SOURCEPATTERN, // EC SDPao
ROP_HAS_SOURCEPATTERN, // ED SDPxno
ROP_HAS_SOURCE, // EE DSo SRCPAINT
ROP_HAS_SOURCEPATTERN, // EF SDPnoo
ROP_HAS_PATTERN, // F0 P PATCOPY
ROP_HAS_SOURCEPATTERN, // F1 PDSono
ROP_HAS_SOURCEPATTERN, // F2 PDSnao
ROP_HAS_SOURCEPATTERN, // F3 PSno
ROP_HAS_SOURCEPATTERN, // F4 PSDnao
ROP_HAS_PATTERN, // F5 PDno
ROP_HAS_SOURCEPATTERN, // F6 PDSxo
ROP_HAS_SOURCEPATTERN, // F7 PDSano
ROP_HAS_SOURCEPATTERN, // F8 PDSao
ROP_HAS_SOURCEPATTERN, // F9 PDSxno
ROP_HAS_PATTERN, // FA DPo
ROP_HAS_SOURCEPATTERN, // FB DPSnoo PATPAINT
ROP_HAS_SOURCEPATTERN, // FC PSo
ROP_HAS_SOURCEPATTERN, // FD PSDnoo
ROP_HAS_SOURCEPATTERN, // FE DPSoo
0 // FF 1 WHITENESS
};
/*
* checkBltStretching
*
* check and see if we can stretch or not
*/
HRESULT checkBltStretching(
LPBLTCAPS lpbc,
LPSPECIAL_BLT_DATA psbd )
{
DWORD caps;
BOOL fail;
fail = FALSE;
/*
* can we even stretch at all?
*/
if( !(*(lpbc->dwBothCaps) & DDCAPS_BLTSTRETCH))
{
GETFAILCODEBLT( *(lpbc->dwCaps),
*(lpbc->dwHELCaps),
psbd->halonly,
psbd->helonly,
DDCAPS_BLTSTRETCH );
if( fail )
{
return DDERR_NOSTRETCHHW;
}
}
if (psbd->helonly)
caps = *(lpbc->dwHELFXCaps);
else
caps = *(lpbc->dwFXCaps);
/*
* verify height
*/
if( psbd->src_height != psbd->dest_height )
{
if( psbd->src_height > psbd->dest_height )
{
/*
* can we shrink Y arbitrarily?
*/
if( !(caps & (DDFXCAPS_BLTSHRINKY) ) )
{
/*
* see if this is a non-integer shrink
*/
if( (psbd->src_height % psbd->dest_height) != 0 )
{
GETFAILCODEBLT( *(lpbc->dwFXCaps),
*(lpbc->dwHELFXCaps),
psbd->halonly,
psbd->helonly,
DDFXCAPS_BLTSHRINKY );
if( fail )
{
return DDERR_NOSTRETCHHW;
}
/*
* see if we can integer shrink
*/
}
else if( !(caps & DDFXCAPS_BLTSHRINKYN) )
{
GETFAILCODEBLT( *(lpbc->dwFXCaps),
*(lpbc->dwHELFXCaps),
psbd->halonly,
psbd->helonly,
DDFXCAPS_BLTSHRINKYN );
if( fail )
{
return DDERR_NOSTRETCHHW;
}
}
}
}
else
{
if( !(caps & DDFXCAPS_BLTSTRETCHY) )
{
/*
* see if this is a non-integer stretch
*/
if( (psbd->dest_height % psbd->src_height) != 0 )
{
GETFAILCODEBLT( *(lpbc->dwFXCaps),
*(lpbc->dwHELFXCaps),
psbd->halonly,
psbd->helonly,
DDFXCAPS_BLTSTRETCHY );
if( fail )
{
return DDERR_NOSTRETCHHW;
}
/*
* see if we can integer stretch
*/
}
else if( !(caps & DDFXCAPS_BLTSTRETCHYN) )
{
GETFAILCODEBLT( *(lpbc->dwFXCaps),
*(lpbc->dwHELFXCaps),
psbd->halonly,
psbd->helonly,
DDFXCAPS_BLTSTRETCHYN );
if( fail )
{
return DDERR_NOSTRETCHHW;
}
}
}
}
}
/*
* verify width
*/
if( psbd->src_width != psbd->dest_width )
{
if( psbd->src_width > psbd->dest_width )
{
if( !(caps & DDFXCAPS_BLTSHRINKX) )
{
/*
* see if this is a non-integer shrink
*/
if( (psbd->src_width % psbd->dest_width) != 0 )
{
GETFAILCODEBLT( *(lpbc->dwFXCaps),
*(lpbc->dwHELFXCaps),
psbd->halonly,
psbd->helonly,
DDFXCAPS_BLTSHRINKX );
if( fail )
{
return DDERR_NOSTRETCHHW;
}
/*
* see if we can integer shrink
*/
}
else if( !(caps & DDFXCAPS_BLTSHRINKXN) )
{
GETFAILCODEBLT( *(lpbc->dwFXCaps),
*(lpbc->dwHELFXCaps),
psbd->halonly,
psbd->helonly,
DDFXCAPS_BLTSHRINKXN );
if( fail )
{
return DDERR_NOSTRETCHHW;
}
}
}
}
else
{
if( !(caps & DDFXCAPS_BLTSTRETCHX) )
{
/*
* see if this is a non-integer stretch
*/
if( (psbd->dest_width % psbd->src_width) != 0 )
{
GETFAILCODEBLT( *(lpbc->dwFXCaps),
*(lpbc->dwHELFXCaps),
psbd->halonly,
psbd->helonly,
DDFXCAPS_BLTSTRETCHX );
if( fail )
{
return DDERR_NOSTRETCHHW;
}
}
if( !(caps & DDFXCAPS_BLTSTRETCHXN) )
{
GETFAILCODEBLT( *(lpbc->dwFXCaps),
*(lpbc->dwHELFXCaps),
psbd->halonly,
psbd->helonly,
DDFXCAPS_BLTSTRETCHXN );
if( fail )
{
return DDERR_NOSTRETCHHW;
}
}
}
}
}
return DD_OK;
} /* checkBltStretching */
/*
* FindAttached
*
* find an attached surface with particular caps
*/
LPDDRAWI_DDRAWSURFACE_LCL FindAttached( LPDDRAWI_DDRAWSURFACE_LCL ptr_lcl, DWORD caps )
{
LPATTACHLIST pal;
LPDDRAWI_DDRAWSURFACE_LCL psurf_lcl;
pal = ptr_lcl->lpAttachList;
while( pal != NULL )
{
psurf_lcl = pal->lpAttached;
if( psurf_lcl->ddsCaps.dwCaps & caps )
{
return psurf_lcl;
}
pal = pal->lpLink;
}
return NULL;
} /* FindAttached */
#if defined(WIN95)
#define DONE_EXCLUDE() \
if( this_dest_lcl->lpDDClipper != NULL ) \
{ \
if ( (pdrv->dwFlags & DDRAWI_DISPLAYDRV) && pdrv->dwPDevice && \
!(*pdrv->lpwPDeviceFlags & HARDWARECURSOR)) \
{ \
DD16_Unexclude(pdrv->dwPDevice); \
} \
}
#elif defined(WINNT)
#define DONE_EXCLUDE() ;
#endif
/*
* DD_Surface_Blt
*
* Bit Blt from one surface to another
*/
HRESULT DDAPI DD_Surface_Blt(
LPDIRECTDRAWSURFACE lpDDDestSurface,
LPRECT lpDestRect,
LPDIRECTDRAWSURFACE lpDDSrcSurface,
LPRECT lpSrcRect,
DWORD dwFlags,
LPDDBLTFX lpDDBltFX )
{
DWORD rc;
DWORD rop;
LPDDRAWI_DDRAWSURFACE_LCL psurf_lcl;
LPDDRAWI_DDRAWSURFACE_INT psurf_int;
LPDDRAWI_DDRAWSURFACE_LCL this_src_lcl;
LPDDRAWI_DDRAWSURFACE_LCL this_dest_lcl;
LPDDRAWI_DDRAWSURFACE_GBL this_src;
LPDDRAWI_DDRAWSURFACE_GBL this_dest;
LPDDRAWI_DDRAWSURFACE_INT this_src_int;
LPDDRAWI_DDRAWSURFACE_INT this_dest_int;
BOOL need_pat;
SPECIAL_BLT_DATA sbd;
BOOL stretch_blt;
LPDDRAWI_DIRECTDRAW_LCL pdrv_lcl;
LPDDRAWI_DIRECTDRAW_GBL pdrv;
DDHAL_BLTDATA bd;
BOOL fail;
BOOL dest_lock_taken=FALSE;
BOOL src_lock_taken=FALSE;
LPVOID dest_bits;
LPVOID src_bits;
HRESULT ddrval;
BLTCAPS bc;
LPBLTCAPS lpbc=&bc;
LPWORD pdflags=0;
ENTER_BOTH();
TRY
{
/*
* validate surface ptrs
*/
this_dest_int = (LPDDRAWI_DDRAWSURFACE_INT) lpDDDestSurface;
this_src_int = (LPDDRAWI_DDRAWSURFACE_INT) lpDDSrcSurface;
if( !VALID_DIRECTDRAWSURFACE_PTR( this_dest_int ) )
{
DPF_ERR( "Invalid dest specified") ;
LEAVE_BOTH();
return DDERR_INVALIDOBJECT;
}
this_dest_lcl = this_dest_int->lpLcl;
this_dest = this_dest_lcl->lpGbl;
if( SURFACE_LOST( this_dest_lcl ) )
{
DPF_ERR( "Dest lost") ;
LEAVE_BOTH();
return DDERR_SURFACELOST;
}
if( this_src_int != NULL )
{
if( !VALID_DIRECTDRAWSURFACE_PTR( this_src_int ) )
{
DPF_ERR( "Invalid source specified" );
LEAVE_BOTH();
return DDERR_INVALIDOBJECT;
}
this_src_lcl = this_src_int->lpLcl;
this_src = this_src_lcl->lpGbl;
if( SURFACE_LOST( this_src_lcl ) )
{
DPF_ERR( "Src lost") ;
LEAVE_BOTH();
return DDERR_SURFACELOST;
}
}
else
{
this_src_lcl = NULL;
this_src = NULL;
}
if( dwFlags & ~DDBLT_VALID )
{
DPF_ERR( "Invalid flags") ;
LEAVE_BOTH();
return DDERR_INVALIDPARAMS;
}
pdrv = this_dest->lpDD;
pdrv_lcl = this_dest_lcl->lpSurfMore->lpDD_lcl;
}
EXCEPT( EXCEPTION_EXECUTE_HANDLER )
{
DPF_ERR( "Exception encountered validating parameters" );
LEAVE_BOTH();
return DDERR_INVALIDPARAMS;
}
// Test and set the busy bit. If it was already set, bail.
{
BOOL isbusy = 0;
pdflags = pdrv->lpwPDeviceFlags;
#ifdef WIN95
_asm
{
mov eax, pdflags
bts word ptr [eax], BUSY_BIT
adc byte ptr isbusy,0
}
#else
isbusy -= (InterlockedExchange((LPDWORD)pdflags,
*((LPDWORD)pdflags) | (1<<BUSY_BIT) ) == (1<<BUSY_BIT) );
#endif
if( isbusy )
{
DPF( 3, "BUSY - Blt" );
LEAVE_BOTH();
return DDERR_SURFACEBUSY;
}
}
RESTART_BLT:
TRY
{
/*
* is either surface locked?
*/
if( (this_dest->dwUsageCount > 0) ||
((this_src != NULL) && (this_src->dwUsageCount > 0)) )
{
DPF_ERR( "Surface is locked" );
LEAVE_BOTH_NOBUSY();
return DDERR_SURFACEBUSY;
}
sbd.halonly = FALSE;
sbd.helonly = FALSE;
if( this_src != NULL )
{
// initialize the blit caps according to the surface types
initBltCaps( this_dest_lcl->ddsCaps.dwCaps, this_src_lcl->ddsCaps.dwCaps, pdrv, lpbc, &(sbd.helonly) );
}
else
{
// no source surface, use vram->vram caps and determine hal or hel
// based on system memory status of destination surface
initBltCaps( DDSCAPS_VIDEOMEMORY, DDSCAPS_VIDEOMEMORY, pdrv, lpbc, &sbd.helonly );
if( this_dest_lcl->ddsCaps.dwCaps & DDSCAPS_SYSTEMMEMORY )
{
sbd.helonly = TRUE;
}
}
fail = FALSE;
/*
* can we really blt?
*/
if( !(*(lpbc->dwBothCaps) & DDCAPS_BLT) )
{
if( *(lpbc->dwCaps) & DDCAPS_BLT )
{
sbd.halonly = TRUE;
}
else if( *(lpbc->dwHELCaps) & DDCAPS_BLT )
{
sbd.helonly = TRUE;
}
else
{
DPF_ERR( "Driver does not support Blt" );
LEAVE_BOTH_NOBUSY();
return DDERR_NOBLTHW;
}
}
/*
* check for HEL composition buffer
*/
if( (this_dest_lcl->dwFlags & DDRAWISURF_HELCB) ||
((this_src_lcl != NULL) && (this_src_lcl->dwFlags & DDRAWISURF_HELCB)) )
{
sbd.helonly = TRUE;
}
bd.lpDD = pdrv;
/*
* make sure BltFX struct is OK
*/
bd.bltFX.dwSize = sizeof( bd.bltFX );
if( lpDDBltFX != NULL )
{
if( !VALID_DDBLTFX_PTR( lpDDBltFX ) )
{
DPF_ERR( "Invalid BLTFX specified" );
LEAVE_BOTH_NOBUSY();
return DDERR_INVALIDPARAMS;
}
}
else
{
if( dwFlags & ( DDBLT_ALPHASRCCONSTOVERRIDE |
DDBLT_ALPHADESTCONSTOVERRIDE |
DDBLT_ALPHASRCSURFACEOVERRIDE |
DDBLT_ALPHADESTSURFACEOVERRIDE |
DDBLT_COLORFILL |
DDBLT_DDFX |
DDBLT_DDROPS |
DDBLT_DEPTHFILL |
DDBLT_KEYDESTOVERRIDE |
DDBLT_KEYSRCOVERRIDE |
DDBLT_ROP |
DDBLT_ROTATIONANGLE |
DDBLT_ZBUFFERDESTCONSTOVERRIDE |
DDBLT_ZBUFFERDESTOVERRIDE |
DDBLT_ZBUFFERSRCCONSTOVERRIDE |
DDBLT_ZBUFFERSRCOVERRIDE ) )
{
DPF_ERR( "BltFX required but not specified" );
LEAVE_BOTH_NOBUSY();
return DDERR_INVALIDPARAMS;
}
}
/*
* make sure flags & associated bd.bltFX are specified OK
*/
need_pat = FALSE;
if( dwFlags & ~DDBLT_WAIT )
{
/*
* isolate lower use tests together
*/
if( dwFlags & (DDBLT_KEYSRCOVERRIDE|
DDBLT_KEYDESTOVERRIDE|
DDBLT_KEYSRC |
DDBLT_KEYDEST ) )
{
#pragma message( REMIND( "Alpha turned off in Rev 1" ) )
#if 0
/*
* verify ALPHA
*/
if( dwFlags & DDBLT_ANYALPHA )
{
BOOL no_alpha;
no_alpha = TRUE;
// check to see if alpha is supported
if( !(*(lpbc->dwBothCaps) & DDCAPS_ALPHA) )
{
GETFAILCODEBLT( *(lpbc->dwCaps),
*(lpbc->dwHELCaps),
sbd.halonly,
sbd.helonly,
DDCAPS_ALPHA );
if( fail )
{
DPF_ERR( "Alpha blt requested, not supported" );
LEAVE_BOTH_NOBUSY();
return DDERR_NOALPHAHW;
}
}
/*
* dest alpha
*/
if( dwFlags & DDBLT_ALPHADEST )
{
if( dwFlags & ( DDBLT_ALPHADESTCONSTOVERRIDE |
DDBLT_ALPHADESTSURFACEOVERRIDE) )
{
DPF_ERR( "ALPHADEST and other alpha dests specified" );
LEAVE_BOTH_NOBUSY();
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" );
LEAVE_BOTH_NOBUSY();
return DDERR_INVALIDPARAMS;
}
dwFlags &= ~DDBLT_ALPHADEST;
dwFlags |= DDBLT_ALPHADESTSURFACEOVERRIDE;
bd.bltFX.lpDDSAlphaDest = (LPDIRECTDRAWSURFACE) psurf_lcl;
no_alpha = FALSE;
// check to see if alpha surfaces are supported
if( !(*(lpbc->dwBothCaps) & DDFXCAPS_ALPHASURFACES) )
{
GETFAILCODEBLT( *(lpbc->dwFXCaps),
*(lpbc->dwHELFXCaps),
sbd.halonly,
sbd.helonly,
DDFXCAPS_ALPHASURFACES );
if( fail )
{
DPF_ERR( "AlphaDest surface requested, not supported" );
LEAVE_BOTH_NOBUSY();
return DDERR_NOALPHAHW;
}
}
}
else if( dwFlags & DDBLT_ALPHADESTCONSTOVERRIDE )
{
if( dwFlags & ( DDBLT_ALPHADESTSURFACEOVERRIDE ))
{
DPF_ERR( "ALPHADESTCONSTOVERRIDE and other alpha sources specified" );
LEAVE_BOTH_NOBUSY();
return DDERR_INVALIDPARAMS;
}
bd.bltFX.dwConstAlphaDest = lpDDBltFX->dwConstAlphaDest;
no_alpha = FALSE;
}
else if( dwFlags & DDBLT_ALPHADESTSURFACEOVERRIDE )
{
psurf_lcl = (LPDDRAWI_DDRAWSURFACE_LCL) lpDDBltFX->lpDDSAlphaDest;
if( !VALID_DIRECTDRAWSURFACE_PTR( psurf_lcl ) )
{
DPF_ERR( "ALPHASURFACEOVERRIDE requires surface ptr" );
LEAVE_BOTH_NOBUSY();
return DDERR_INVALIDPARAMS;
}
if( SURFACE_LOST( psurf_lcl ) )
{
LEAVE_BOTH_NOBUSY();
return DDERR_SURFACELOST;
}
bd.bltFX.lpDDSAlphaDest = (LPDIRECTDRAWSURFACE) psurf_lcl;
no_alpha = FALSE;
// check to see if alpha surfaces are supported
if( !(*(lpbc->dwBothCaps) & DDFXCAPS_ALPHASURFACES) )
{
GETFAILCODEBLT( *(lpbc->dwFXCaps),
*(lpbc->dwHELFXCaps),
sbd.halonly,
sbd.helonly,
DDFXCAPS_ALPHASURFACES );
if( fail )
{
DPF_ERR( "AlphaDestOvr surface requested, not supported" );
LEAVE_BOTH_NOBUSY();
return DDERR_NOALPHAHW;
}
}
}
/*
* source alpha
*/
if( dwFlags & DDBLT_ALPHASRC )
{
if( dwFlags & (DDBLT_ALPHASRCCONSTOVERRIDE|
DDBLT_ALPHASRCSURFACEOVERRIDE) )
{
DPF_ERR( "ALPHASRC and other alpha sources specified" );
LEAVE_BOTH_NOBUSY();
return DDERR_INVALIDPARAMS;
}
if( this_src == NULL )
{
DPF_ERR( "ALPHASRC requires a source surface" );
LEAVE_BOTH_NOBUSY();
return DDERR_INVALIDPARAMS;
}
psurf_lcl = FindAttached( this_src_lcl, DDSCAPS_ALPHA );
if( psurf_lcl == NULL )
{
DPF_ERR( "ALPHASRC requires an attached alpha to the src" );
LEAVE_BOTH_NOBUSY();
return DDERR_INVALIDPARAMS;
}
dwFlags &= ~DDBLT_ALPHASRC;
dwFlags |= DDBLT_ALPHASRCSURFACEOVERRIDE;
bd.bltFX.lpDDSAlphaSrc = (LPDIRECTDRAWSURFACE) psurf_lcl;
no_alpha = FALSE;
// check to see if alpha surfaces are supported
if( !(*(lpbc->dwBothCaps) & DDFXCAPS_ALPHASURFACES) )
{
GETFAILCODEBLT( *(lpbc->dwFXCaps),
*(lpbc->dwHELFXCaps),
sbd.halonly,
sbd.helonly,
DDFXCAPS_ALPHASURFACES );
if( fail )
{
DPF_ERR( "AlphaSrc surface requested, not supported" );
LEAVE_BOTH_NOBUSY();
return DDERR_NOALPHAHW;
}
}
}
else if( dwFlags & DDBLT_ALPHASRCCONSTOVERRIDE )
{
if( dwFlags & ( DDBLT_ALPHASRCSURFACEOVERRIDE ))
{
DPF_ERR( "ALPHASRCCONSTOVERRIDE and other alpha sources specified" );
LEAVE_BOTH_NOBUSY();
return DDERR_INVALIDPARAMS;
}
bd.bltFX.dwConstAlphaSrc = lpDDBltFX->dwConstAlphaSrc;
no_alpha = FALSE;
}
else if( dwFlags & DDBLT_ALPHASRCSURFACEOVERRIDE )
{
psurf_int = (LPDDRAWI_DDRAWSURFACE_INT) lpDDBltFX->lpDDSAlphaSrc;
if( !VALID_DIRECTDRAWSURFACE_PTR( psurf_int ) )
{
DPF_ERR( "ALPHASURFACEOVERRIDE requires surface ptr" );
LEAVE_BOTH_NOBUSY();
return DDERR_INVALIDPARAMS;
}
psurf_lcl = psurf_int->lpLcl;
if( SURFACE_LOST( psurf_lcl ) )
{
LEAVE_BOTH_NOBUSY();
return DDERR_SURFACELOST;
}
bd.bltFX.lpDDSAlphaSrc = (LPDIRECTDRAWSURFACE) psurf_lcl;
no_alpha = FALSE;
// check to see if alpha surfaces are supported
if( !(*(lpbc->dwBothCaps) & DDFXCAPS_ALPHASURFACES) )
{
GETFAILCODEBLT( *(lpbc->dwFXCaps),
*(lpbc->dwHELFXCaps),
sbd.halonly,
sbd.helonly,
DDFXCAPS_ALPHASURFACES );
if( fail )
{
DPF_ERR( "AlphaSrcOvr surface requested, not supported" );
LEAVE_BOTH_NOBUSY();
return DDERR_NOALPHAHW;
}
}
}
if( no_alpha )
{
DPF_ERR( "ALPHA specified with no alpha surface to use" );
LEAVE_BOTH_NOBUSY();
return DDERR_INVALIDPARAMS;
}
}
#endif
#pragma message( REMIND( "Z blts turned off in Rev 1" ) )
#if 0
/*
* verify Z Buffer
*/
if( dwFlags & DDBLT_ZBUFFER )
{
if( this_src_lcl == NULL )
{
DPF_ERR( "ZBUFFER specified, but no source data" );
LEAVE_BOTH_NOBUSY();
return DDERR_INVALIDPARAMS;
}
// check to see if the driver supports zbuffer blts
if( !(*(lpbc->dwBothCaps) & DDCAPS_ZBLTS) )
{
GETFAILCODEBLT( *(lpbc->dwCaps),
*(lpbc->dwHELCaps),
sbd.halonly,
sbd.helonly,
DDCAPS_ZBLTS );
if( fail )
{
DPF_ERR( "ZBuffer blt requested, not supported" );
LEAVE_BOTH_NOBUSY();
return DDERR_NOZBUFFERHW;
}
}
bd.bltFX.dwZBufferOpCode = lpDDBltFX->dwZBufferOpCode;
if( dwFlags & DDBLT_ZBUFFERCONSTDESTOVERRIDE )
{
if( dwFlags & (DDBLT_ZBUFFERDESTOVERRIDE) )
{
DPF_ERR( "ZBUFFERCONSTDESTOVERRIDE and z surface specified" );
LEAVE_BOTH_NOBUSY();
return DDERR_INVALIDPARAMS;
}
bd.bltFX.dwConstZDest = lpDDBltFX->dwConstZDest;
}
else if( dwFlags & DDBLT_ZBUFFERDESTOVERRIDE )
{
psurf_int = (LPDDRAWI_DDRAWSURFACE_INT) lpDDBltFX->lpDDSZBufferDest;
if( !VALID_DIRECTDRAWSURFACE_PTR( psurf_int ) )
{
DPF_ERR( "ZBUFFERSURFACEDESTOVERRIDE requires surface ptr" );
LEAVE_BOTH_NOBUSY();
return DDERR_INVALIDPARAMS;
}
psurf_lcl = psurf_int->lpLcl;
if( SURFACE_LOST( psurf_lcl ) )
{
LEAVE_BOTH_NOBUSY();
return DDERR_SURFACELOST;
}
bd.bltFX.lpDDSZBufferDest = (LPDIRECTDRAWSURFACE) psurf_lcl;
}
else
{
psurf_lcl = FindAttached( this_dest_lcl, DDSCAPS_ZBUFFER );
if( psurf_lcl == NULL )
{
DPF_ERR( "ZBUFFER requires an attached Z to dest" );
LEAVE_BOTH_NOBUSY();
return DDERR_INVALIDPARAMS;
}
dwFlags |= DDBLT_ZBUFFERDESTOVERRIDE;
bd.bltFX.lpDDSZBufferDest = (LPDIRECTDRAWSURFACE) psurf_lcl;
}
if( dwFlags & DDBLT_ZBUFFERCONSTSRCOVERRIDE )
{
if( dwFlags & (DDBLT_ZBUFFERSRCOVERRIDE) )
{
DPF_ERR( "ZBUFFERCONSTSRCOVERRIDE and z surface specified" );
LEAVE_BOTH_NOBUSY();
return DDERR_INVALIDPARAMS;
}
bd.bltFX.dwConstZSrc = lpDDBltFX->dwConstZSrc;
} else if( dwFlags & DDBLT_ZBUFFERSRCOVERRIDE )
{
psurf_int = (LPDDRAWI_DDRAWSURFACE_INT) lpDDBltFX->lpDDSZBufferSrc;
if( !VALID_DIRECTDRAWSURFACE_PTR( psurf_int ) )
{
DPF_ERR( "ZBUFFERSURFACESRCOVERRIDE requires surface ptr" );
LEAVE_BOTH_NOBUSY();
return DDERR_INVALIDPARAMS;
}
psurf_lcl = psurf_int->lpLcl
if( SURFACE_LOST( psurf_lcl ) )
{
LEAVE_BOTH_NOBUSY();
return DDERR_SURFACELOST;
}
bd.bltFX.lpDDSZBufferSrc = (LPDIRECTDRAWSURFACE) psurf_lcl;
}
else
{
psurf_lcl = FindAttached( this_src_lcl, DDSCAPS_ZBUFFER );
if( psurf_lcl == NULL )
{
DPF_ERR( "ZBUFFER requires an attached Z to src" );
LEAVE_BOTH_NOBUSY();
return DDERR_INVALIDPARAMS;
}
dwFlags |= DDBLT_ZBUFFERSRCOVERRIDE;
bd.bltFX.lpDDSZBufferSrc = (LPDIRECTDRAWSURFACE) psurf_lcl;
}
}
#endif
/*
* verify color key overrides
*/
if( dwFlags & (DDBLT_KEYSRCOVERRIDE|DDBLT_KEYDESTOVERRIDE) )
{
// see if the driver supports color key blts
if( !(*(lpbc->dwBothCaps) & DDCAPS_COLORKEY) )
{
GETFAILCODEBLT( *(lpbc->dwCaps),
*(lpbc->dwHELCaps),
sbd.halonly,
sbd.helonly,
DDCAPS_COLORKEY );
if( fail )
{
DPF_ERR( "KEYOVERRIDE specified, not supported" );
LEAVE_BOTH_NOBUSY();
return DDERR_NOCOLORKEYHW;
}
}
if( dwFlags & DDBLT_KEYSRCOVERRIDE )
{
if( !(*(lpbc->dwBothCKeyCaps) & DDCKEYCAPS_SRCBLT) )
{
GETFAILCODEBLT( *(lpbc->dwCKeyCaps),
*(lpbc->dwHELCKeyCaps),
sbd.halonly,
sbd.helonly,
DDCKEYCAPS_SRCBLT );
if( fail )
{
DPF_ERR( "KEYSRCOVERRIDE specified, not supported" );
LEAVE_BOTH_NOBUSY();
return DDERR_NOCOLORKEYHW;
}
}
bd.bltFX.ddckSrcColorkey = lpDDBltFX->ddckSrcColorkey;
}
if( dwFlags & DDBLT_KEYDESTOVERRIDE )
{
if( !(*(lpbc->dwBothCKeyCaps) & DDCKEYCAPS_DESTBLT) )
{
GETFAILCODEBLT( *(lpbc->dwCKeyCaps),
*(lpbc->dwHELCKeyCaps),
sbd.halonly,
sbd.helonly,
DDCKEYCAPS_DESTBLT );
if( fail )
{
DPF_ERR( "KEYDESTOVERRIDE specified, not supported" );
LEAVE_BOTH_NOBUSY();
return DDERR_NOCOLORKEYHW;
}
}
bd.bltFX.ddckDestColorkey = lpDDBltFX->ddckDestColorkey;
}
}
/*
* verify src color key
*/
if( dwFlags & DDBLT_KEYSRC )
{
if( this_src == NULL )
{
DPF_ERR( "KEYSRC specified, but no source data" );
LEAVE_BOTH_NOBUSY();
return DDERR_INVALIDOBJECT;
}
if( dwFlags & DDBLT_KEYSRCOVERRIDE )
{
DPF_ERR( "KEYSRC specified with KEYSRCOVERRIDE" );
LEAVE_BOTH_NOBUSY();
return DDERR_INVALIDPARAMS;
}
if( !(this_src_lcl->dwFlags & DDRAWISURF_HASCKEYSRCBLT) )
{
DPF_ERR( "KEYSRC specified, but no color key" );
DPF( 1, "srcFlags = %08lx", this_src_lcl->dwFlags );
LEAVE_BOTH_NOBUSY();
return DDERR_INVALIDPARAMS;
}
// make sure we can do this
if( !(*(lpbc->dwBothCKeyCaps) & DDCKEYCAPS_SRCBLT) )
{
GETFAILCODEBLT( *(lpbc->dwCKeyCaps),
*(lpbc->dwHELCKeyCaps),
sbd.halonly,
sbd.helonly,
DDCKEYCAPS_SRCBLT );
if( fail )
{
DPF_ERR( "KEYSRC specified, not supported" );
LEAVE_BOTH_NOBUSY();
return DDERR_NOCOLORKEYHW;
}
}
bd.bltFX.ddckSrcColorkey = this_src_lcl->ddckCKSrcBlt;
dwFlags &= ~DDBLT_KEYSRC;
dwFlags |= DDBLT_KEYSRCOVERRIDE;
}
/*
* verify dest color key
*/
if( dwFlags & DDBLT_KEYDEST )
{
if( dwFlags & DDBLT_KEYDESTOVERRIDE )
{
DPF_ERR( "KEYDEST specified with KEYDESTOVERRIDE" );
LEAVE_BOTH_NOBUSY();
return DDERR_INVALIDPARAMS;
}
if( !(this_dest_lcl->dwFlags & DDRAWISURF_HASCKEYDESTBLT) )
{
DPF_ERR( "KEYDEST specified, but no color key" );
LEAVE_BOTH_NOBUSY();
return DDERR_INVALIDPARAMS;
}
// make sure we can do this
if( !(*(lpbc->dwBothCKeyCaps) & DDCKEYCAPS_DESTBLT) )
{
GETFAILCODEBLT( *(lpbc->dwCKeyCaps),
*(lpbc->dwHELCKeyCaps),
sbd.halonly,
sbd.helonly,
DDCKEYCAPS_DESTBLT );
if( fail )
{
DPF_ERR( "KEYDEST specified, not supported" );
LEAVE_BOTH_NOBUSY();
return DDERR_NOCOLORKEYHW;
}
}
bd.bltFX.ddckDestColorkey = this_src_lcl->ddckCKDestBlt;
dwFlags &= ~DDBLT_KEYDEST;
dwFlags |= DDBLT_KEYDESTOVERRIDE;
}
}
/*
* verify various flags
*/
if( !(dwFlags &(DDBLT_ROP |
DDBLT_COLORFILL |
DDBLT_DDROPS |
DDBLT_DEPTHFILL |
DDBLT_ROTATIONANGLE |
DDBLT_DDFX) ) )
{
if( this_src == NULL )
{
DPF_ERR( "Need a source for blt" );
LEAVE_BOTH_NOBUSY();
return DDERR_INVALIDPARAMS;
}
dwFlags |= DDBLT_ROP;
bd.bltFX.dwROP = SRCCOPY;
}
/*
* verify ROP
*/
else if( dwFlags & DDBLT_ROP )
{
DWORD idx;
DWORD bit;
if( dwFlags & (DDBLT_DDFX |
DDBLT_COLORFILL|
DDBLT_DEPTHFILL|
DDBLT_ROTATIONANGLE|
DDBLT_DDROPS))
{
DPF_ERR( "Invalid flags specified with ROP" );
LEAVE_BOTH_NOBUSY();
return DDERR_INVALIDPARAMS;
}
bd.bltFX.dwROP = lpDDBltFX->dwROP;
rop = (DWORD) LOBYTE( HIWORD( bd.bltFX.dwROP ) );
idx = rop/32;
bit = 1 << (rop % 32 );
DPF( 4, "Trying ROP %d, idx=%d, bit=%08lx", rop, idx, bit );
/*
* see if both HEL & HAL support the ROP
*/
if( !(lpbc->dwBothRops[idx] & bit ) )
{
GETFAILCODEBLT( lpbc->dwRops[idx],
lpbc->dwHELRops[idx],
sbd.halonly,
sbd.helonly,
bit );
if( fail )
{
DPF_ERR( "ROP not supported" );
LEAVE_BOTH_NOBUSY();
return DDERR_NORASTEROPHW;
}
}
bd.dwROPFlags = cROPTable[ rop ];
if( bd.dwROPFlags & ROP_HAS_SOURCE )
{
if( this_src == NULL )
{
DPF_ERR( "ROP required a surface" );
LEAVE_BOTH_NOBUSY();
return DDERR_INVALIDPARAMS;
}
}
if( bd.dwROPFlags & ROP_HAS_PATTERN )
{
need_pat = TRUE;
}
}
/*
* verify COLORFILL
*/
else if( dwFlags & DDBLT_COLORFILL )
{
if( this_src != NULL )
{
DPF_ERR( "COLORFILL specified along with source surface" );
LEAVE_BOTH_NOBUSY();
return DDERR_INVALIDPARAMS;
}
/*
* You cannot use COLORFILL to clear Z-buffers anymore. You must
* explicitly use DEPTHFILL. Disallow Z-buffer destinations.
*/
if( this_dest_lcl->ddsCaps.dwCaps & DDSCAPS_ZBUFFER )
{
DPF_ERR( "Z-Buffer cannot be target of a color fill blt" );
LEAVE_BOTH_NOBUSY();
return DDERR_INVALIDPARAMS;
}
if( !(*(lpbc->dwBothCaps) & DDCAPS_BLTCOLORFILL) )
{
GETFAILCODEBLT( *(lpbc->dwCaps),
*(lpbc->dwHELCaps),
sbd.halonly,
sbd.helonly,
DDCAPS_BLTCOLORFILL );
if( fail )
{
DPF_ERR( "COLORFILL specified, not supported" );
LEAVE_BOTH_NOBUSY();
return DDERR_UNSUPPORTED;
}
}
bd.bltFX.dwFillColor = lpDDBltFX->dwFillColor;
}
/*
* verify DEPTHFILL
*/
else if( dwFlags & DDBLT_DEPTHFILL )
{
if( this_src != NULL )
{
DPF_ERR( "DEPTHFILL specified along with source surface" );
LEAVE_BOTH_NOBUSY();
return DDERR_INVALIDPARAMS;
}
/*
* Ensure the destination is a z-buffer.
*/
if( !( this_dest_lcl->ddsCaps.dwCaps & DDSCAPS_ZBUFFER ) )
{
DPF_ERR( "DEPTHFILL specified but destination is not a Z-buffer" );
LEAVE_BOTH_NOBUSY();
return DDERR_INVALIDPARAMS;
}
if( !(*(lpbc->dwBothCaps) & DDCAPS_BLTDEPTHFILL) )
{
GETFAILCODEBLT( *(lpbc->dwCaps),
*(lpbc->dwHELCaps),
sbd.halonly,
sbd.helonly,
DDCAPS_BLTDEPTHFILL );
if( fail )
{
DPF_ERR( "DEPTHFILL specified, not supported" );
LEAVE_BOTH_NOBUSY();
return DDERR_UNSUPPORTED;
}
}
bd.bltFX.dwFillDepth = lpDDBltFX->dwFillDepth;
}
/*
* verify DDROPS
*/
else if( dwFlags & DDBLT_DDROPS )
{
if( dwFlags & (DDBLT_DDFX |
DDBLT_COLORFILL|
DDBLT_DEPTHFILL|
DDBLT_ROTATIONANGLE) )
{
DPF_ERR( "Invalid flags specified with DDROPS" );
LEAVE_BOTH_NOBUSY();
return DDERR_INVALIDPARAMS;
}
bd.bltFX.dwDDROP = lpDDBltFX->dwDDROP;
DPF_ERR( "DDROPS unsupported" );
LEAVE_BOTH_NOBUSY();
return DDERR_NODDROPSHW;
}
/*
* verify DDFX
*/
else if( dwFlags & DDBLT_DDFX )
{
if( dwFlags & (DDBLT_COLORFILL |
DDBLT_DEPTHFILL |
DDBLT_ROTATIONANGLE) )
{
DPF_ERR( "Invalid flags specified with DDFX" );
LEAVE_BOTH_NOBUSY();
return DDERR_INVALIDPARAMS;
}
if( lpDDBltFX->dwDDFX & ( DDBLTFX_ARITHSTRETCHY ) )
{
DPF_ERR( "DDBLTFX_ARITHSTRETCHY unsupported" );
LEAVE_BOTH_NOBUSY();
return DDERR_NOSTRETCHHW;
}
if( lpDDBltFX->dwDDFX & ( DDBLTFX_MIRRORLEFTRIGHT ) )
{
GETFAILCODEBLT( *(lpbc->dwFXCaps),
*(lpbc->dwHELFXCaps),
sbd.halonly,
sbd.helonly,
DDFXCAPS_BLTMIRRORLEFTRIGHT );
if( fail )
{
DPF_ERR( "Mirroring along vertical axis not supported" );
LEAVE_BOTH_NOBUSY();
return DDERR_NOMIRRORHW;
}
}
if( lpDDBltFX->dwDDFX & ( DDBLTFX_MIRRORUPDOWN ) )
{
GETFAILCODEBLT( *(lpbc->dwFXCaps),
*(lpbc->dwHELFXCaps),
sbd.halonly,
sbd.helonly,
DDFXCAPS_BLTMIRRORUPDOWN );
if( fail )
{
DPF_ERR( "Mirroring along horizontal axis not supported" );
LEAVE_BOTH_NOBUSY();
return DDERR_NOMIRRORHW;
}
}
bd.bltFX.dwDDFX = lpDDBltFX->dwDDFX;
dwFlags |= DDBLT_ROP;
bd.bltFX.dwROP = SRCCOPY;
/*
* verify ROTATIONANGLE
*/
}
else if( dwFlags & DDBLT_ROTATIONANGLE )
{
if( dwFlags & (DDBLT_COLORFILL | DDBLT_DEPTHFILL) )
{
DPF_ERR( "Invalid flags specified with ROTATIONANGLE" );
LEAVE_BOTH_NOBUSY();
return DDERR_INVALIDPARAMS;
}
bd.bltFX.dwRotationAngle = lpDDBltFX->dwRotationAngle;
DPF_ERR( "ROTATIONANGLE unsupported" );
LEAVE_BOTH_NOBUSY();
return DDERR_NOROTATIONHW;
/*
* you should have told me SOMETHING!
*/
}
else
{
DPF_ERR( "no blt type specified!" );
LEAVE_BOTH_NOBUSY();
return DDERR_INVALIDPARAMS;
}
/*
* no flags, we are doing a generic SRCCOPY
*/
}
else
{
if( this_src == NULL )
{
DPF_ERR( "Need a source for blt" );
LEAVE_BOTH_NOBUSY();
return DDERR_INVALIDPARAMS;
}
dwFlags |= DDBLT_ROP;
bd.bltFX.dwROP = SRCCOPY;
}
/*
* verify pattern
*/
if( need_pat )
{
psurf_int = (LPDDRAWI_DDRAWSURFACE_INT) lpDDBltFX->lpDDSPattern;
if( !VALID_DIRECTDRAWSURFACE_PTR( psurf_int ) )
{
DPF_ERR( "Invalid pattern surface specified" );
LEAVE_BOTH_NOBUSY();
return DDERR_INVALIDOBJECT;
}
psurf_lcl = psurf_int->lpLcl;
bd.bltFX.lpDDSPattern = (LPDIRECTDRAWSURFACE) psurf_lcl;
if( SURFACE_LOST( psurf_lcl ) )
{
LEAVE_BOTH_NOBUSY();
return DDERR_SURFACELOST;
}
#pragma message( REMIND( "What about general (non-8x8) patterns?" ))
if( psurf_lcl->lpGbl->wHeight != 8 || psurf_lcl->lpGbl->wWidth != 8 )
{
DPF_ERR( "Pattern surface must be 8 by 8" );
LEAVE_BOTH_NOBUSY();
return DDERR_INVALIDPARAMS;
}
dwFlags |= DDBLT_PRIVATE_ALIASPATTERN;
}
/*
* make sure dest rect is OK
*/
if( lpDestRect != NULL )
{
if( !VALID_RECT_PTR( lpDestRect ) )
{
DPF_ERR( "Invalid dest rect specified" );
LEAVE_BOTH_NOBUSY();
return DDERR_INVALIDRECT;
}
bd.rDest = *(LPRECTL)lpDestRect;
}
else
{
MAKE_SURF_RECT( this_dest, bd.rDest );
}
/*
* make sure src rect is OK
*/
if( lpSrcRect != NULL )
{
if( !VALID_RECT_PTR( lpSrcRect ) )
{
DPF_ERR( "Invalid src rect specified" );
LEAVE_BOTH_NOBUSY();
return DDERR_INVALIDRECT;
}
bd.rSrc = *(LPRECTL)lpSrcRect;
}
else
{
if( this_src != NULL )
{
MAKE_SURF_RECT( this_src, bd.rSrc );
}
}
/*
* get dimensions & check them
*/
stretch_blt = FALSE;
sbd.dest_height = bd.rDest.bottom - bd.rDest.top;
sbd.dest_width = bd.rDest.right - bd.rDest.left;
if( ((int)sbd.dest_height <= 0) || ((int)sbd.dest_width <= 0) ||
( (this_dest_lcl->lpDDClipper == NULL) &&
( ((int)bd.rDest.top < 0) || ((int)bd.rDest.left < 0) ||
((DWORD) bd.rDest.bottom > (DWORD) this_dest->wHeight) ||
((DWORD) bd.rDest.right > (DWORD) this_dest->wWidth) ) ) )
{
DPF_ERR( "Invalid destination dimensions" );
LEAVE_BOTH_NOBUSY();
return DDERR_INVALIDRECT;
}
if( this_src != NULL )
{
sbd.src_height = bd.rSrc.bottom - bd.rSrc.top;
sbd.src_width = bd.rSrc.right - bd.rSrc.left;
if( ((int)sbd.src_height <= 0) || ((int)sbd.src_width <= 0) ||
((int)bd.rSrc.top < 0) || ((int)bd.rSrc.left < 0) ||
((DWORD) bd.rSrc.bottom > (DWORD) this_src->wHeight) ||
((DWORD) bd.rSrc.right > (DWORD) this_src->wWidth) )
{
DPF_ERR( "Invalid source dimensions" );
LEAVE_BOTH_NOBUSY();
return DDERR_INVALIDRECT;
}
/*
* verify stretching...
*
*/
if( sbd.src_height != sbd.dest_height || sbd.src_width != sbd.dest_width )
{
HRESULT ddrval;
ddrval = checkBltStretching( lpbc, &sbd );
if( ddrval != DD_OK )
{
DPF_ERR( "Failed checkBltStretching" );
LEAVE_BOTH_NOBUSY();
return ddrval;
}
stretch_blt = TRUE;
}
}
}
EXCEPT( EXCEPTION_EXECUTE_HANDLER )
{
DPF_ERR( "Exception encountered validating parameters" );
LEAVE_BOTH_NOBUSY();
return DDERR_INVALIDPARAMS;
}
/*
* now shovel the data...
*/
TRY
{
/*
* final bits of blt data
*/
bd.lpDDDestSurface = this_dest_lcl;
bd.lpDDSrcSurface = this_src_lcl;
bd.dwFlags = dwFlags;
/*
* Set up for a HAL or a HEL call
*/
if( pdrv_lcl->lpDDCB->HALDDSurface.Blt == NULL )
{
sbd.helonly = TRUE;
}
if( sbd.helonly && sbd.halonly )
{
DPF_ERR( "BLT not supported in software or hardware" );
LEAVE_BOTH_NOBUSY();
return DDERR_NOBLTHW;
}
// Did the mode change since ENTER_DDRAW?
#ifdef WINNT
if ( DdQueryDisplaySettingsUniqueness() != uDisplaySettingsUnique )
{
// mode changed, don't do the blt
DPF_ERR( "Mode changed between ENTER_DDRAW and HAL call" );
LEAVE_BOTH_NOBUSY()
return DDERR_SURFACELOST;
}
#endif
/*
* Some drivers (like S3) do stuff in their BeginAccess call
* that screws up stuff that they did in their DDHAL Lock Call.
*
* Exclusion needs to happen BEFORE the lock call to prevent this.
*
*/
#if defined(WIN95)
if( this_dest_lcl->lpDDClipper != NULL )
{
/*
* exclude the mouse cursor.
*
* we only need to do this for the windows display driver
*
* we only need to do this if we are blting to or from the
* primary surface.
*
* we only do this in the clipping case, we figure if the
* app cares enough to not scribble all over other windows
* he also cares enough to not to wipe out the cursor.
*
* we only need to do this if the driver is using a
* software cursor.
*
* NOTE
* we should check and only do this on the primary?
* we should make sure the clipper is window based?
* we should check for the source being the primary?
*
*/
if ( (pdrv->dwFlags & DDRAWI_DISPLAYDRV) && pdrv->dwPDevice &&
!(*pdrv->lpwPDeviceFlags & HARDWARECURSOR))
{
if ( lpDDDestSurface == lpDDSrcSurface )
{
RECTL rcl;
UnionRect((RECT*)&rcl, (RECT*)&bd.rDest, (RECT*)&bd.rSrc);
DD16_Exclude(pdrv->dwPDevice, &rcl);
}
else
{
DD16_Exclude(pdrv->dwPDevice, &bd.rDest);
}
}
}
#endif
if( !sbd.helonly ) // must not be HEL call
{
DPF( 4, "Hardware Blt");
sbd.bltfn = pdrv_lcl->lpDDCB->HALDDSurface.Blt;
bd.Blt = pdrv_lcl->lpDDCB->cbDDSurfaceCallbacks.Blt;
dest_lock_taken = FALSE;
src_lock_taken = FALSE;
if( lpbc->bPageLockRequired )
{
/*
* Make sure the surfaces are pagelocked
*/
if( (this_dest_lcl->lpSurfMore->dwPageLockCount == 0) &&
(this_dest_lcl->ddsCaps.dwCaps & DDSCAPS_SYSTEMMEMORY) )
{
DD_Surface_PageLock( (LPDIRECTDRAWSURFACE)this_dest_int, 0 );
lpbc->bDestPageLocked = TRUE;
lpbc->bNeedToUnlock = TRUE;
}
else
{
lpbc->bDestPageLocked = FALSE;
}
if( this_src_lcl && (this_src_lcl->lpSurfMore->dwPageLockCount == 0) &&
(this_src_lcl->ddsCaps.dwCaps & DDSCAPS_SYSTEMMEMORY) )
{
DD_Surface_PageLock( (LPDIRECTDRAWSURFACE)this_src_int, 0 );
lpbc->bSrcPageLocked = TRUE;
lpbc->bNeedToUnlock = TRUE;
}
else
{
lpbc->bSrcPageLocked = FALSE;
}
}
}
/*
* Blt the unclipped case
*/
if( this_dest_lcl->lpDDClipper == NULL )
{
bd.IsClipped = FALSE; // no clipping
// if hel only, check and take locks on video mem surfaces.
if( sbd.helonly )
{
sbd.bltfn = pdrv_lcl->lpDDCB->HELDDSurface.Blt;
/*
* take locks on vram surfaces
*/
if( !(this_dest_lcl->ddsCaps.dwCaps & DDSCAPS_SYSTEMMEMORY) )
{
while( 1 )
{
ddrval = InternalLock( this_dest_lcl, &dest_bits , NULL, 0);
if( ddrval == DD_OK )
{
#ifdef WINNT
this_dest->fpVidMem = (FLATPTR) dest_bits;
#endif
break;
}
if( ddrval == DDERR_WASSTILLDRAWING )
{
continue;
}
DONE_EXCLUDE();
(*pdflags) &= ~BUSY;
LEAVE_BOTH();
return ddrval;
}
dest_lock_taken = TRUE;
}
else
{
dest_lock_taken = FALSE;
}
if( ( this_src != NULL) && (lpDDSrcSurface != lpDDDestSurface) &&
( ( this_src_lcl->ddsCaps.dwCaps & DDSCAPS_SYSTEMMEMORY ) == 0) )
{
while( 1 )
{
ddrval = InternalLock( this_src_lcl, &src_bits, NULL, 0);
if( ddrval == DD_OK )
{
#ifdef WINNT
this_src->fpVidMem = (FLATPTR) src_bits;
#endif
break;
}
if( ddrval == DDERR_WASSTILLDRAWING )
{
continue;
}
if( dest_lock_taken )
{
InternalUnlock( this_dest_lcl,NULL,0 );
dest_lock_taken=FALSE;
}
DONE_EXCLUDE();
(*pdflags) &= ~BUSY;
LEAVE_BOTH();
return ddrval;
}
src_lock_taken = TRUE;
}
else
{
src_lock_taken = FALSE;
}
}
try_again:
DOHALCALL_NOWIN16( Blt, sbd.bltfn, bd, rc, sbd.helonly );
#ifdef WINNT
DDASSERT( ! (rc == DDHAL_DRIVER_HANDLED && bd.ddRVal == DDERR_VISRGNCHANGED) );
#endif
if ( (dwFlags & DDBLT_WAIT) &&
rc == DDHAL_DRIVER_HANDLED &&
bd.ddRVal == DDERR_WASSTILLDRAWING )
{
DPF(4, "Waiting.....");
goto try_again;
}
}
else
{
/*
* Blt when the destination is clipped
*/
DWORD cnt;
DWORD total;
LPRECT prect;
DWORD size;
LPRGNDATA prd=(LPRGNDATA)0;
int x_offset;
int y_offset;
DWORD scale_x;
DWORD scale_y;
bd.rOrigSrc = bd.rSrc;
bd.rOrigDest = bd.rDest;
#ifdef WINNT
get_clipping_info:
#endif
bd.IsClipped = TRUE; // yes, we are clipping
/*
* get the clip list
*/
ddrval = DD_Clipper_GetClipList( (LPDIRECTDRAWCLIPPER) this_dest_lcl->lpSurfMore->lpDDIClipper,
(LPRECT)&bd.rOrigDest, NULL, &size );
if( ddrval != DD_OK )
{
DPF_ERR( "GetClipList FAILED" );
DONE_LOCKS();
DONE_EXCLUDE();
LEAVE_BOTH_NOBUSY();
return ddrval;
}
if ( size <= sizeof(RGNDATA) )
{
DPF( 4, "Totally clipped");
rc = DDHAL_DRIVER_HANDLED;
bd.ddRVal = DD_OK;
goto null_clip_rgn;
}
MemFree(prd); //in case we re-got the clipping list
prd = MemAlloc( size );
if( prd == NULL )
{
DONE_LOCKS();
DONE_EXCLUDE();
LEAVE_BOTH_NOBUSY();
return DDERR_OUTOFMEMORY;
}
ddrval = DD_Clipper_GetClipList( (LPDIRECTDRAWCLIPPER) this_dest_lcl->lpSurfMore->lpDDIClipper,
(LPRECT)&bd.rOrigDest, prd, &size );
if( ddrval != DD_OK )
{
#ifdef WINNT
if( ddrval == DDERR_REGIONTOOSMALL )
{
// the visrgn changed between the first and second calls to GetClipList.
// try again.
MemFree(prd);
prd = NULL;
goto get_clipping_info;
}
#endif
DPF_ERR( "GetClipList FAILED" );
MemFree( prd );
DONE_LOCKS();
DONE_EXCLUDE();
LEAVE_BOTH_NOBUSY();
return ddrval;
}
total = prd->rdh.nCount;
DPF( 4, "total vis rects = %ld", total );
prect = (LPRECT) &prd->Buffer[0];
rc = DDHAL_DRIVER_HANDLED;
bd.ddRVal = DD_OK;
// if hel only, check and take locks on video mem surfaces.
if( sbd.helonly )
{
sbd.bltfn = pdrv_lcl->lpDDCB->HELDDSurface.Blt;
/*
* take locks on vram surfaces
*/
if( !(this_dest_lcl->ddsCaps.dwCaps & DDSCAPS_SYSTEMMEMORY) )
{
while( 1 )
{
DPF(5,"locking1");
ddrval = InternalLock( this_dest_lcl, &dest_bits , NULL, DDLOCK_FAILONVISRGNCHANGED);
#ifdef WINNT
if (ddrval == DDERR_VISRGNCHANGED)
{
DDASSERT (this_dest_lcl->lpDDClipper);
DDASSERT (this_dest_lcl->lpDDClipper->lpGbl);
DdResetVisrgn(this_dest_lcl,(HWND) (this_dest_lcl->lpDDClipper->lpGbl->hWnd) );
DPF(5,"Surface %08x:NT Kernel reports clipping changed. Resetting hwnd %08x, retrying",this_dest_lcl,this_dest_lcl->lpDDClipper->lpGbl->hWnd);
DONE_LOCKS(); //should do nothing... here for ortho
goto get_clipping_info;
}
#endif
if( ddrval == DD_OK )
{
#ifdef WINNT
this_dest->fpVidMem = (FLATPTR) dest_bits;
#endif
break;
}
if( ddrval == DDERR_WASSTILLDRAWING )
{
continue;
}
DONE_LOCKS();
DONE_EXCLUDE();
(*pdflags) &= ~BUSY;
LEAVE_BOTH();
return ddrval;
}
dest_lock_taken = TRUE;
}
else
{
dest_lock_taken = FALSE;
}
if( ( this_src != NULL) && (lpDDSrcSurface != lpDDDestSurface) &&
( ( this_src_lcl->ddsCaps.dwCaps & DDSCAPS_SYSTEMMEMORY ) == 0) )
{
while( 1 )
{
DPF(5,"locking2");
ddrval = InternalLock( this_src_lcl, &src_bits , NULL, DDLOCK_FAILONVISRGNCHANGED);
#ifdef WINNT
if (ddrval == DDERR_VISRGNCHANGED)
{
DDASSERT (this_dest_lcl->lpDDClipper);
DDASSERT (this_dest_lcl->lpDDClipper->lpGbl);
DdResetVisrgn(this_dest_lcl,(HWND) (this_dest_lcl->lpDDClipper->lpGbl->hWnd) );
DPF(5,"Surface %08x:NT Kernel reports clipping changed. Resetting hwnd %08x, retrying",this_dest_lcl,this_dest_lcl->lpDDClipper->lpGbl->hWnd);
DONE_LOCKS();
goto get_clipping_info;
}
#endif
if( ddrval == DD_OK )
{
#ifdef WINNT
this_src->fpVidMem = (FLATPTR) src_bits;
#endif
break;
}
if( ddrval == DDERR_WASSTILLDRAWING )
{
continue;
}
DONE_LOCKS();
DONE_EXCLUDE();
(*pdflags) &= ~BUSY;
LEAVE_BOTH();
return ddrval;
}
src_lock_taken = TRUE;
}
else
{
src_lock_taken = FALSE;
}
}
/*
* See if the driver wants to do the clipping
*/
if( (stretch_blt && (*(lpbc->dwCaps) & DDCAPS_CANCLIPSTRETCHED)) ||
(!stretch_blt && (*(lpbc->dwCaps) & DDCAPS_CANCLIP)) )
{
// The driver will do the clipping
bd.dwRectCnt = total;
bd.prDestRects = prect;
/*
* pass the whole mess off to the driver
*/
drvclip_try_again:
DOHALCALL_NOWIN16( Blt, sbd.bltfn, bd, rc, sbd.helonly );
if( rc == DDHAL_DRIVER_HANDLED )
{
#ifdef WINNT
if (bd.ddRVal == DDERR_VISRGNCHANGED)
{
DONE_LOCKS();
DDASSERT (this_dest_lcl->lpDDClipper);
DDASSERT (this_dest_lcl->lpDDClipper->lpGbl);
DdResetVisrgn(this_dest_lcl,(HWND) (this_dest_lcl->lpDDClipper->lpGbl->hWnd) );
DPF(5,"Surface %08x:NT Kernel reports clipping changed. Resetting hwnd %08x, retrying",this_dest_lcl,this_dest_lcl->lpDDClipper->lpGbl->hWnd);
goto get_clipping_info;
}
#endif
if ( (dwFlags & DDBLT_WAIT) &&
bd.ddRVal == DDERR_WASSTILLDRAWING )
{
DPF(4, "Waiting.....");
goto drvclip_try_again;
}
}
}
else
{
// We will do the clipping
bd.dwRectCnt =1;
bd.prDestRects = (LPVOID)&(bd.rDest);
// precalculate a couple of variables
if( !stretch_blt )
{
x_offset = bd.rSrc.left - bd.rDest.left;
y_offset = bd.rSrc.top - bd.rDest.top;
}
else
{
// scale_x and scale_y are fixed point variables scaled
// 16.16 (16 integer bits and 16 fractional bits)
scale_x = ((bd.rSrc.right - bd.rSrc.left) << 16) /
(bd.rDest.right - bd.rDest.left);
scale_y = ((bd.rSrc.bottom - bd.rSrc.top) << 16) /
(bd.rDest.bottom - bd.rDest.top);
}
/*
* traverse the visible rect list and send each piece to
* the driver to blit.
*/
for( cnt=0;cnt<total;cnt++ )
{
/*
* find out where on the src rect we need to get
* the data from.
*/
if( !stretch_blt )
{
// no stretch
// one-to-one mapping from source to destination
bd.rDest.left = prect->left;
bd.rDest.right = prect->right;
bd.rDest.top = prect->top;
bd.rDest.bottom = prect->bottom;
bd.rSrc.left = bd.rDest.left + x_offset;
bd.rSrc.right = bd.rDest.right + x_offset;
bd.rSrc.top = bd.rDest.top + y_offset;
bd.rSrc.bottom = bd.rDest.bottom + y_offset;
}
else
{
// stretching
// linear mapping from source to destination
bd.rDest.left = prect->left;
bd.rDest.right = prect->right;
bd.rDest.top = prect->top;
bd.rDest.bottom = prect->bottom;
// calculate the source rect which transforms to the
// dest rect
XformRect( (RECT *)&(bd.rOrigSrc), (RECT *)&(bd.rOrigDest), (RECT *)prect,
(RECT *)&(bd.rSrc), scale_x, scale_y );
}
/*
* blt this little piece
*/
clip_try_again:
DOHALCALL_NOWIN16( Blt, sbd.bltfn, bd, rc, sbd.helonly );
if( rc == DDHAL_DRIVER_HANDLED )
{
#ifdef WINNT
if (bd.ddRVal == DDERR_VISRGNCHANGED)
{
DONE_LOCKS();
DDASSERT (this_dest_lcl->lpDDClipper);
DDASSERT (this_dest_lcl->lpDDClipper->lpGbl);
DdResetVisrgn(this_dest_lcl,(HWND) (this_dest_lcl->lpDDClipper->lpGbl->hWnd) );
DPF(5,"Surface %08x:NT Kernel reports clipping changed. Resetting hwnd %08x, retrying",this_dest_lcl,this_dest_lcl->lpDDClipper->lpGbl->hWnd);
goto get_clipping_info;
}
#endif
if ( (dwFlags & DDBLT_WAIT) &&
bd.ddRVal == DDERR_WASSTILLDRAWING )
{
DPF(4, "Waiting.....");
goto clip_try_again;
}
if( bd.ddRVal != DD_OK )
{
break;
}
}
/*
* next clipping rect
*/
prect++;
}
}
MemFree( prd );
null_clip_rgn:
;
}
DONE_LOCKS();
/*
* Exclusion needs to happen after unlock call
*/
DONE_EXCLUDE();
if( rc != DDHAL_DRIVER_HANDLED )
{
/*
* did the driver run out of hardware color key resources?
*/
if( (rc == DDHAL_DRIVER_NOCKEYHW) && (dwFlags & DDBLT_KEYSRCOVERRIDE) )
{
ddrval = ChangeToSoftwareColorKey( this_src_int, FALSE );
if( ddrval == DD_OK )
{
sbd.halonly = FALSE;
sbd.helonly = FALSE;
goto RESTART_BLT;
}
else
{
bd.ddRVal = DDERR_NOCOLORKEYHW;
}
}
else
{
bd.ddRVal = DDERR_UNSUPPORTED;
}
}
/*
* NOTE: We cannot use LEAVE_BOTH_NOBUSY in this scenario as
* releasePageLocks() calls GetBltStatus() to ensure that blts
* are finished before releasing the page locks. Therefore,
* the busy bit must be cleared before this function is called.
* However, we can't release the critical section until after
* releasePageLocks() finishes so we have to split the
* functionality.
*/
DONE_BUSY();
if( lpbc->bNeedToUnlock )
releasePageLocks( lpbc, this_dest_int, this_src_int );
LEAVE_BOTH();
return bd.ddRVal;
}
EXCEPT( EXCEPTION_EXECUTE_HANDLER )
{
DPF_ERR( "Exception encountered doing blt" );
DONE_LOCKS();
DONE_EXCLUDE();
DONE_BUSY();
if( lpbc->bNeedToUnlock )
releasePageLocks( lpbc, this_dest_int, this_src_int );
LEAVE_BOTH();
return DDERR_EXCEPTION;
}
} /* DD_Surface_Blt */
#undef DPF_MODNAME
#define DPF_MODNAME "BltBatch"
/*
* DD_Surface_BltBatch
*
* BitBlt a whole pile of surfaces
*/
HRESULT DDAPI DD_Surface_BltBatch(
LPDIRECTDRAWSURFACE lpDDDestSurface,
LPDDBLTBATCH lpDDBltBatch,
DWORD dwCount,
DWORD dwFlags )
{
LPDDRAWI_DDRAWSURFACE_LCL this_src_lcl;
LPDDRAWI_DDRAWSURFACE_LCL this_dest_lcl;
LPDDRAWI_DDRAWSURFACE_INT this_src_int;
LPDDRAWI_DDRAWSURFACE_INT this_dest_int;
HRESULT ddrval;
int i;
ENTER_BOTH();
/*
* validate surface ptrs
*/
this_dest_int = (LPDDRAWI_DDRAWSURFACE_INT) lpDDDestSurface;
if( !VALID_DIRECTDRAWSURFACE_PTR( this_dest_int ) )
{
DPF_ERR( "Invalid dest specified") ;
LEAVE_BOTH();
return DDERR_INVALIDOBJECT;
}
this_dest_lcl = this_dest_int->lpLcl;
if( SURFACE_LOST( this_dest_lcl ) )
{
DPF_ERR( "Dest lost") ;
LEAVE_BOTH();
return DDERR_SURFACELOST;
}
if( this_dest_lcl->lpGbl->dwUsageCount > 0 )
{
DPF( 1, "Dest surface %08lx is still locked", this_dest_int );
LEAVE_BOTH();
return DDERR_SURFACEBUSY;
}
/*
* validate BltBatch ptr
*/
if( !VALID_DDBLTBATCH_PTR( lpDDBltBatch ) )
{
DPF( 1, "Invalid Blt batch ptr" );
LEAVE_BOTH();
return DDERR_INVALIDPARAMS;
}
/*
* validate blt batch params
*/
for( i=0;i<(int)dwCount;i++ )
{
/*
* validate dest rect
*/
if( lpDDBltBatch[i].lprDest != NULL )
{
if( !VALID_RECT_PTR(lpDDBltBatch[i].lprDest) )
{
DPF( 1, "dest rectangle invalid, entry %d", i );
LEAVE_BOTH();
return DDERR_INVALIDRECT;
}
}
/*
* validate source surface
*/
this_src_int = (LPDDRAWI_DDRAWSURFACE_INT)lpDDBltBatch[i].lpDDSSrc;
if( this_src_int != NULL )
{
if( !VALID_DIRECTDRAWSURFACE_PTR( this_src_int ) )
{
DPF( 1, "Invalid source specified, entry %d", i );
LEAVE_BOTH();
return DDERR_INVALIDOBJECT;
}
this_src_lcl = this_src_int->lpLcl;
if( SURFACE_LOST( this_src_lcl ) )
{
DPF( 1, "Src lost, entry %d", i) ;
LEAVE_BOTH();
return DDERR_SURFACELOST;
}
if( this_src_lcl->lpGbl->dwUsageCount > 0 )
{
DPF( 2, "Source surface %08lx is still locked, entry %d", this_src_int, i );
LEAVE_BOTH();
return DDERR_SURFACEBUSY;
}
}
/*
* validate src rect
*/
if( lpDDBltBatch[i].lprSrc != NULL )
{
if( !VALID_RECT_PTR(lpDDBltBatch[i].lprSrc) )
{
DPF( 1, "src rectangle invalid, entry %d", i );
LEAVE_BOTH();
return DDERR_INVALIDRECT;
}
}
/*
* validate bltfx ptr
*/
if( lpDDBltBatch[i].lpDDBltFx != NULL )
{
if( !VALID_DDBLTFX_PTR( lpDDBltBatch[i].lpDDBltFx ) )
{
DPF( 1, "Invalid BLTFX specified, entry %d", i );
LEAVE_BOTH();
return DDERR_INVALIDPARAMS;
}
}
else
{
if( lpDDBltBatch[i].dwFlags
& ( DDBLT_ALPHASRCCONSTOVERRIDE |
DDBLT_ALPHADESTCONSTOVERRIDE |
DDBLT_ALPHASRCSURFACEOVERRIDE |
DDBLT_ALPHADESTSURFACEOVERRIDE |
DDBLT_COLORFILL |
DDBLT_DDFX |
DDBLT_DDROPS |
DDBLT_DEPTHFILL |
DDBLT_KEYDESTOVERRIDE |
DDBLT_KEYSRCOVERRIDE |
DDBLT_ROP |
DDBLT_ROTATIONANGLE |
DDBLT_ZBUFFERDESTCONSTOVERRIDE |
DDBLT_ZBUFFERDESTOVERRIDE |
DDBLT_ZBUFFERSRCCONSTOVERRIDE |
DDBLT_ZBUFFERSRCOVERRIDE ) )
{
DPF( 1, "BltFX required but not specified, entry %d", i );
LEAVE_BOTH();
return DDERR_INVALIDPARAMS;
}
}
}
ddrval = DDERR_UNSUPPORTED;
for( i=0;i<(int)dwCount;i++ )
{
#if 0
while( 1 )
{
ddrval = doBlt( this_dest_lcl,
lpDDBltBatch[i].lprDest,
lpDDBltBatch[i].lpDDSSrc,
lpDDBltBatch[i].lprSrc,
lpDDBltBatch[i].dwFlags,
lpDDBltBatch[i].lpDDBltFX );
if( ddrval != DDERR_WASSTILLDRAWING )
{
break;
}
}
#endif
if( ddrval != DD_OK )
{
break;
}
}
LEAVE_BOTH();
return ddrval;
} /* BltBatch */
/*
* XformRect
*
* Transform a clipped rect in destination space to the corresponding clipped
* rect in src space. So, if we're stretching from src to dest, this yields
* the unstretched clipping rect in src space.
*
* PARAMETERS:
* prcSrc - unclipped rect in the source space
* prcDest - unclipped rect in the destination space
* prcClippedDest - the rect we want to transform
* prcClippedSrc - the resulting rect in the source space. return value.
* scale_x - 16.16 fixed point src/dest width ratio
* scale_y - 16.16 fixed point src/dest height ratio
*
* DESCRIPTION:
* Given an rect in source space and a rect in destination space, and a
* clipped rectangle in the destination space (prcClippedDest), return
* the rectangle in the source space (prcClippedSrc) that maps to
* prcClippedDest.
*
* Use 16.16 fixed point math for more accuracy. (Shift left, do math,
* shift back (w/ round))
*
* RETURNS:
* DD_OK always. prcClippedSrc is the mapped rectangle.
*
*/
HRESULT XformRect(RECT * prcSrc, RECT * prcDest, RECT * prcClippedDest,
RECT * prcClippedSrc, DWORD scale_x, DWORD scale_y)
{
/*
* This first calculation is done with fixed point arithmetic (16.16).
* The result is converted to (32.0) below. Scale back into source space
*/
prcClippedSrc->left = (prcClippedDest->left - prcDest->left) * scale_x;
prcClippedSrc->right = (prcClippedDest->right - prcDest->left) * scale_x;
prcClippedSrc->top = (prcClippedDest->top - prcDest->top) * scale_y;
prcClippedSrc->bottom = (prcClippedDest->bottom - prcDest->top) * scale_y;
/*
* now round (adding 0x8000 rounds) and translate (offset by the
* src offset)
*/
prcClippedSrc->left = (((DWORD)prcClippedSrc->left + 0x8000) >> 16) + prcSrc->left;
prcClippedSrc->right = (((DWORD)prcClippedSrc->right + 0x8000) >> 16) + prcSrc->left;
prcClippedSrc->top = (((DWORD)prcClippedSrc->top + 0x8000) >> 16) + prcSrc->top;
prcClippedSrc->bottom = (((DWORD)prcClippedSrc->bottom + 0x8000) >> 16) + prcSrc->top;
/*
* Check for zero-sized source rect dimensions and bump if necessary
*/
if (prcClippedSrc->left == prcClippedSrc->right)
{
if (prcClippedSrc->right == prcSrc->right)
{
(prcClippedSrc->left)--;
}
else
{
(prcClippedSrc->right)++;
}
}
if (prcClippedSrc->top == prcClippedSrc->bottom)
{
if (prcClippedSrc->bottom == prcSrc->bottom)
{
(prcClippedSrc->top)--;
}
else
{
(prcClippedSrc->bottom)++;
}
}
return DD_OK;
} /* XformRect */