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.
 
 
 
 
 
 

1952 lines
48 KiB

/*==========================================================================
*
* Copyright (C) 1994-1995 Microsoft Corporation. All Rights Reserved.
*
* File: ddraw.c
* Content: DirectDraw object support
* History:
* Date By Reason
* ==== == ======
* 25-dec-94 craige initial implementation
* 13-jan-95 craige re-worked to updated spec + ongoing work
* 21-jan-95 craige made 32-bit + ongoing work
* 31-jan-95 craige and even more ongoing work...
* 21-feb-95 craige disconnect anyone who forgot to do it themselves
* 27-feb-95 craige new sync. macros
* 01-mar-95 craige flags to Get/SetExclusiveMode
* 03-mar-95 craige DuplicateSurface
* 08-mar-95 craige GetFourCCCodes, FreeAllSurfaces, GarbageCollect
* 19-mar-95 craige use HRESULTs
* 20-mar-95 craige new CSECT work
* 26-mar-95 craige driver wide color keys for overlays
* 28-mar-95 craige added FlipToGDISurface; removed Get/SetColorKey
* 01-apr-95 craige happy fun joy updated header file
* 06-apr-95 craige fill in free video memory
* 13-apr-95 craige EricEng's little contribution to our being late
* 15-apr-95 craige implement FlipToGDISurface
* 06-may-95 craige use driver-level csects only
* 14-may-95 craige disable CTRL_ALT_DEL if exclusive fullscreen
* 19-may-95 craige check DDSEMO_ALLOWREBOOT before disabling CAD
* 22-may-95 craige use MemAlloc16 for sel. allocation
* 23-may-95 craige have GetCaps return HEL caps
* 28-may-95 craige implement FreeAllSurfaces; unicode support;
* HAL cleanup: entry for GetScanLine
* 05-jun-95 craige removed GetVersion, FreeAllSurfaces, DefWindowProc;
* change GarbageCollect to Compact
* 07-jun-95 craige added StartExclusiveMode
* 12-jun-95 craige new process list stuff
* 16-jun-95 craige removed fpVidMemOrig
* 17-jun-95 craige new surface structure
* 18-jun-95 craige new DuplicateSurface code
* 20-jun-95 craige need to check fpVidMemOrig for deciding to flip
* 24-jun-95 craige don't hide/show cursor - up to app
* 25-jun-95 craige pay attention to DDCKEY_COLORSPACE; allow NULL ckey;
* one ddraw mutex
* 26-jun-95 craige reorganized surface structure
* 27-jun-95 craige return num of 4cc codes if NULL array specified.
* 28-jun-95 craige ENTER_DDRAW at very start of fns
* 30-jun-95 kylej use GetProcessPrimary instead of lpPrimarySurface,
* invalid all primaries when starting exclusive mode
* 30-jun-95 craige turn off all hot keys
* 01-jul-95 craige require fullscreen for excl. mode
* 03-jul-95 craige YEEHAW: new driver struct; SEH
* 05-jul-95 craige added internal FlipToGDISurface
* 06-jul-95 craige added Initialize
* 08-jul-95 craige added FindProcessDDObject
* 08-jul-95 kylej Handle exclusive mode palettes correctly
* 09-jul-95 craige SetExclusiveMode->SetCooperativeLevel;
* flush all service when exclusive mode set;
* check style for SetCooperativeLevel
* 16-jul-95 craige hook hwnd always
* 17-jul-95 craige return unsupported from GetMonitorFrequency if not avail
* 20-jul-95 craige don't set palette unless palettized
* 22-jul-95 craige bug 230 - unsupported starting modes
* 01-aug-95 craige bug 286 - GetCaps should fail if both parms NULL
* 13-aug-95 craige new parms to flip
* 13-aug-95 toddla added DDSCL_DONTHOOKHWND
* 20-aug-95 toddla added DDSCL_ALLOWMODEX
* 21-aug-95 craige mode X support
* 25-aug-95 craige bug 671
* 26-aug-95 craige bug 717
* 26-aug-95 craige bug 738
* 04-sep-95 craige bug 895: toggle GetVerticalBlankStatus result in emul.
* 22-sep-95 craige bug 1275: return # of 4cc codes copied
* 15-nov-95 jeffno Initial NT changes: ifdef out all but last routine
* 27-nov-95 colinmc new member to return the available vram of a given
* type (defined by DDSCAPS).
* 10-dec-95 colinmc added execute buffer support
* 18-dec-95 colinmc additional surface caps checking for
* GetAvailableVidMem member
* 26-dec-95 craige implement DD_Initialize
* 02-jan-96 kylej handle new interface structures
* 26-jan-96 jeffno Teensy change in DoneExclusiveMode: bug when only 1 mode avail.
* 14-feb-96 kylej Allow NULL hwnd for non-exclusive SetCooperativeLevel
* 05-mar-96 colinmc Bug 11928: Fixed DuplicateSurface problem caused by
* failing to initialize the back pointer to the
* DirectDraw object
* 13-mar-96 craige Bug 7528: hw that doesn't have modex
* 22-mar-96 colinmc Bug 13316: uninitialized interfaces
* 10-apr-96 colinmc Bug 16903: HEL uses obsolete FindProcessDDObject
* 13-apr-96 colinmc Bug 17736: No driver notification of flip to GDI
* 14-apr-96 colinmc Bug 16855: Can't pass NULL to initialize
* 03-may-96 kylej Bug 19125: Preserve V1 SetCooperativeLevel behaviour
* 27-may-96 colinmc Bug 24465: SetCooperativeLevel(..., DDSCL_NORMAL)
* needs to ensure we are looking at the GDI surface
*
***************************************************************************/
#include "ddrawpr.h"
/*
* Caps bits that we don't allow to be specified when asking for
* available video memory. These are bits which don't effect the
* allocation of the surface in a vram heap.
*/
#define AVAILVIDMEM_BADSCAPS (DDSCAPS_BACKBUFFER | \
DDSCAPS_FRONTBUFFER | \
DDSCAPS_COMPLEX | \
DDSCAPS_FLIP | \
DDSCAPS_OWNDC | \
DDSCAPS_PALETTE | \
DDSCAPS_SYSTEMMEMORY | \
DDSCAPS_VISIBLE | \
DDSCAPS_WRITEONLY)
#undef DPF_MODNAME
#define DPF_MODNAME "GetVerticalBlankStatus"
#if defined(WIN95) || defined(NT_FIX)
__inline static BOOL IN_VBLANK( void )
{
BOOL rc;
_asm
{
xor eax,eax
mov dx,03dah ;status reg. port on color card
in al,dx ;read the status
and al,8 ;test whether beam is currently in retrace
mov rc,eax
}
return rc;
}
#define IN_DISPLAY() (!IN_VBLANK())
#endif
/*
* DD_GetVerticalBlankStatus
*/
HRESULT DDAPI DD_GetVerticalBlankStatus(
LPDIRECTDRAW lpDD,
LPBOOL lpbIsInVB )
{
LPDDRAWI_DIRECTDRAW_INT this_int;
LPDDRAWI_DIRECTDRAW_LCL this_lcl;
LPDDRAWI_DIRECTDRAW_GBL this;
LPDDHAL_WAITFORVERTICALBLANK wfvbhalfn;
LPDDHAL_WAITFORVERTICALBLANK wfvbfn;
ENTER_DDRAW();
TRY
{
this_int = (LPDDRAWI_DIRECTDRAW_INT) lpDD;
if( !VALID_DIRECTDRAW_PTR( this_int ) )
{
LEAVE_DDRAW();
return DDERR_INVALIDOBJECT;
}
this_lcl = this_int->lpLcl;
this = this_lcl->lpGbl;
if( !VALID_BOOL_PTR( lpbIsInVB ) )
{
DPF_ERR( "Invalid BOOL pointer" );
LEAVE_DDRAW();
return DDERR_INVALIDPARAMS;
}
}
EXCEPT( EXCEPTION_EXECUTE_HANDLER )
{
DPF_ERR( "Exception encountered validating parameters" );
LEAVE_DDRAW();
return DDERR_INVALIDPARAMS;
}
/*
* ask the driver test the VB status
*/
#pragma message( REMIND( "Need HEL WaitForVerticalBlank (for NT too!)" ))
#if defined (WIN95) || defined ( NT_FIX )
if( this->dwFlags & DDRAWI_MODEX )
{
*lpbIsInVB = FALSE;
if( IN_VBLANK() )
{
*lpbIsInVB = TRUE;
}
LEAVE_DDRAW();
return DD_OK;
}
else
#endif
{
wfvbfn = this_lcl->lpDDCB->HALDD.WaitForVerticalBlank;
wfvbhalfn = this_lcl->lpDDCB->cbDDCallbacks.WaitForVerticalBlank;
if( wfvbhalfn != NULL )
{
DDHAL_WAITFORVERTICALBLANKDATA wfvbd;
DWORD rc;
wfvbd.WaitForVerticalBlank = wfvbhalfn;
wfvbd.lpDD = this;
wfvbd.dwFlags = DDWAITVB_I_TESTVB;
wfvbd.hEvent = 0;
DOHALCALL( WaitForVerticalBlank, wfvbfn, wfvbd, rc, FALSE );
if( rc == DDHAL_DRIVER_HANDLED )
{
*lpbIsInVB = wfvbd.bIsInVB;
LEAVE_DDRAW();
return wfvbd.ddRVal;
}
}
}
/*
* no hardware support, so just pretend it works
*/
{
static BOOL bLast=FALSE;
*lpbIsInVB = bLast;
bLast = !bLast;
}
LEAVE_DDRAW();
return DD_OK;
} /* DD_GetVerticalBlankStatus */
#undef DPF_MODNAME
#define DPF_MODNAME "GetScanLine"
/*
* DD_GetScanLine
*/
HRESULT DDAPI DD_GetScanLine(
LPDIRECTDRAW lpDD,
LPDWORD lpdwScanLine )
{
LPDDRAWI_DIRECTDRAW_INT this_int;
LPDDRAWI_DIRECTDRAW_LCL this_lcl;
LPDDRAWI_DIRECTDRAW_GBL this;
LPDDHAL_GETSCANLINE gslhalfn;
LPDDHAL_GETSCANLINE gslfn;
ENTER_DDRAW();
TRY
{
this_int = (LPDDRAWI_DIRECTDRAW_INT) lpDD;
if( !VALID_DIRECTDRAW_PTR( this_int ) )
{
LEAVE_DDRAW();
return DDERR_INVALIDOBJECT;
}
this_lcl = this_int->lpLcl;
this = this_lcl->lpGbl;
if( !VALID_DWORD_PTR( lpdwScanLine ) )
{
DPF_ERR( "Invalid scan line pointer" );
LEAVE_DDRAW();
return DDERR_INVALIDPARAMS;
}
}
EXCEPT( EXCEPTION_EXECUTE_HANDLER )
{
DPF_ERR( "Exception encountered validating parameters" );
LEAVE_DDRAW();
return DDERR_INVALIDPARAMS;
}
/*
* ask the driver to get the current scanline
*/
#pragma message( REMIND( "Need HEL GetScanLine" ))
gslfn = this_lcl->lpDDCB->HALDD.GetScanLine;
gslhalfn = this_lcl->lpDDCB->cbDDCallbacks.GetScanLine;
if( gslhalfn != NULL )
{
DDHAL_GETSCANLINEDATA gsld;
DWORD rc;
gsld.GetScanLine = gslhalfn;
gsld.lpDD = this;
DOHALCALL( GetScanLine, gslfn, gsld, rc, FALSE );
if( rc == DDHAL_DRIVER_HANDLED )
{
*lpdwScanLine = gsld.dwScanLine;
LEAVE_DDRAW();
return gsld.ddRVal;
}
}
*lpdwScanLine = 0;
LEAVE_DDRAW();
return DDERR_UNSUPPORTED;
} /* DD_GetScanLine */
#undef DPF_MODNAME
#define DPF_MODNAME "GetCaps"
/*
* DD_GetCaps
*
* Retrieve all driver capabilites
*/
HRESULT DDAPI DD_GetCaps(
LPDIRECTDRAW lpDD,
LPDDCAPS lpDDDriverCaps,
LPDDCAPS lpDDHELCaps )
{
LPDDRAWI_DIRECTDRAW_INT this_int;
LPDDRAWI_DIRECTDRAW_LCL this_lcl;
LPDDRAWI_DIRECTDRAW_GBL this;
DWORD freevm;
int i;
DWORD dwSize;
ENTER_DDRAW();
TRY
{
this_int = (LPDDRAWI_DIRECTDRAW_INT) lpDD;
if( !VALID_DIRECTDRAW_PTR( this_int ) )
{
LEAVE_DDRAW();
return DDERR_INVALIDOBJECT;
}
this_lcl = this_int->lpLcl;
this = this_lcl->lpGbl;
if( (lpDDDriverCaps == NULL) && (lpDDHELCaps == NULL) )
{
DPF_ERR( "Must specify at least one of driver or emulation caps" );
LEAVE_DDRAW();
return DDERR_INVALIDPARAMS;
}
if( lpDDDriverCaps != NULL )
{
if( !VALID_DDCAPS_PTR( lpDDDriverCaps ) )
{
DPF_ERR( "Invalid driver caps pointer" );
LEAVE_DDRAW();
return DDERR_INVALIDPARAMS;
}
}
if( lpDDHELCaps != NULL )
{
if( !VALID_DDCAPS_PTR( lpDDHELCaps ) )
{
DPF_ERR( "Invalid hel caps pointer" );
LEAVE_DDRAW();
return DDERR_INVALIDPARAMS;
}
}
}
EXCEPT( EXCEPTION_EXECUTE_HANDLER )
{
DPF_ERR( "Exception encountered validating parameters" );
LEAVE_DDRAW();
return DDERR_INVALIDPARAMS;
}
/*
* fill in caps fields
*/
if( lpDDDriverCaps != NULL )
{
dwSize = lpDDDriverCaps->dwSize;
memcpy( lpDDDriverCaps, &(this->ddCaps), lpDDDriverCaps->dwSize );
lpDDDriverCaps->dwSize = dwSize;
/*
* Execute buffers are invisible to the user level API
* so mask that caps bit off.
*/
lpDDDriverCaps->ddsCaps.dwCaps &= ~DDSCAPS_EXECUTEBUFFER;
/*
* get amount of free video memory
*/
freevm = 0;
for( i=0;i<(int)this->vmiData.dwNumHeaps;i++ )
{
freevm += VidMemAmountFree( this->vmiData.pvmList[i].lpHeap );
}
lpDDDriverCaps->dwVidMemFree = freevm;
}
/*
* fill in hel caps
*/
if( lpDDHELCaps != NULL )
{
dwSize = lpDDHELCaps->dwSize;
memcpy( lpDDHELCaps, &(this->ddHELCaps), lpDDHELCaps->dwSize );
lpDDHELCaps->dwSize = dwSize;
/*
* Again, execute buffers are invisible to the user level API
* so mask that caps bit off.
*/
lpDDHELCaps->ddsCaps.dwCaps &= ~DDSCAPS_EXECUTEBUFFER;
lpDDHELCaps->dwVidMemFree = 0;
}
LEAVE_DDRAW();
return DD_OK;
} /* DD_GetCaps */
// Get/SetColorKey removed...
#if 0
#undef DPF_MODNAME
#define DPF_MODNAME "GetColorKey"
/*
* DD_GetColorKey
*
* get the current driver-wide chroma key
*/
HRESULT DDAPI DD_GetColorKey(
LPDIRECTDRAW lpDD,
DWORD dwFlags,
LPDDCOLORKEY lpDDColorKey )
{
LPDDRAWI_DIRECTDRAW this;
DWORD ckcaps;
ENTER_DDRAW();
this = (LPDDRAWI_DIRECTDRAW) lpDD;
if( !VALID_DIRECTDRAW_PTR( this ) )
{
LEAVE_DDRAW();
return DDERR_INVALIDOBJECT;
}
if( !VALID_DDCOLORKEY_PTR( lpDDColorKey ) )
{
DPF_ERR( "Invalid color key pointer" );
LEAVE_DDRAW();
return DDERR_INVALIDPARAMS;
}
if( dwFlags & (DDCKEY_SRCOVERLAY| DDCKEY_SRCBLT) )
{
DPF_ERR( "Driver wide color key for blt not supported" );
LEAVE_DDRAW();
return DDERR_UNSUPPORTED;
}
/*
* do we even support a color key
*/
if( !(this->ddsCaps.dwCaps & DDSCAPS_COLORKEY) )
{
LEAVE_DDRAW();
return DDERR_UNSUPPORTED;
}
ckcaps = this->ddsCaps.dwCKeyCaps;
/*
* get key for DESTOVERLAY
*/
if( dwFlags & DDCKEY_DESTOVERLAY )
{
if( dwFlags & (DDCKEY_SRCOVERLAY) )
{
DPF_ERR( "Invalid Flags with DESTOVERLAY" );
LEAVE_DDRAW();
return DDERR_INVALIDPARAMS;
}
if( !(ckcaps & DDCKEYCAPS_DESTOVERLAYDRIVERWIDE) )
{
LEAVE_DDRAW();
return DDERR_UNSUPPORTED;
}
if( !(this->dwFlags & DDRAWI_HASCKEYDESTOVERLAY) )
{
LEAVE_DDRAW();
return DDERR_NOCLRKEY;
}
*lpDDColorKey = this->ddckCKDestOverlay;
}
/*
* get key for SRCOVERLAY
*/
else if( dwFlags & DDCKEY_SRCOVERLAY )
{
if( !(this->ddsCaps.dwCaps & DDSCAPS_OVERLAY ) )
{
DPF_ERR( "DESTOVERLAY specified for a non-overlay surface" );
LEAVE_DDRAW();
return DDERR_INVALIDOBJECT;
}
if( !(ckcaps & DDCKEYCAPS_SRCOVERLAYDRIVERWIDE) )
{
LEAVE_DDRAW();
return DDERR_UNSUPPORTED;
}
if( !(this->dwFlags & DDRAWI_HASCKEYSRCOVERLAY) )
{
LEAVE_DDRAW();
return DDERR_NOCLRKEY;
}
*lpDDColorKey = this->ddckCKSrcOverlay;
}
/*
* flags are no good
*/
else
{
DPF_ERR( "Invalid Flags" );
LEAVE_DDRAW();
return DDERR_INVALIDPARAMS;
}
LEAVE_DDRAW();
return DD_OK;
} /* DD_GetColorKey */
#undef DPF_MODNAME
#define DPF_MODNAME "SetColorKey"
/*
* DD_SetColorKey
*
* set the driver-wide chroma key
*/
HRESULT DDAPI DD_SetColorKey(
LPDIRECTDRAW lpDD,
DWORD dwFlags,
LPDDCOLORKEY lpDDColorKey )
{
LPDDRAWI_DIRECTDRAW this;
HRESULT ddrval;
DWORD sflags;
BOOL halonly;
BOOL helonly;
DDCOLORKEY ddck;
ENTER_DDRAW();
this = (LPDDRAWI_DIRECTDRAW) lpDD;
if( !VALID_DIRECTDRAW_PTR( this ) )
{
LEAVE_DDRAW();
return DDERR_INVALIDOBJECT;
}
if( lpDDColorKey != NULL )
{
if( !VALID_DDCOLORKEY_PTR( lpDDColorKey ) )
{
DPF_ERR( "Invaid colorkey pointer" );
LEAVE_DDRAW();
return DDERR_INVALIDPARAMS;
}
}
/*
* do we even support a color key?
*/
if( !(this->ddsBothCaps.dwCaps & DDSCAPS_COLORKEY) )
{
if( this->ddsCaps.dwCaps & DDSCAPS_COLORKEY )
{
halonly = TRUE;
}
else if( this->ddsHELCaps.dwCaps & DDSCAPS_COLORKEY )
{
helonly = TRUE;
}
else
{
LEAVE_DDRAW();
return DDERR_UNSUPPORTED;
}
}
else
{
helonly = FALSE;
halonly = FALSE;
}
/*
* check for color space
*/
if( lpDDColorKey != NULL )
{
ddck = *lpDDColorKey;
if( !(dwFlags & DDCKEY_COLORSPACE) )
{
ddck.dwColorSpaceHighValue = ddck.dwColorSpaceLowValue;
}
lpDDColorKey = &ddck;
/*
* check the color key
*/
ddrval = CheckColorKey( dwFlags, this, lpDDColorKey, &sflags,
halonly, helonly );
if( ddrval != DD_OK )
{
LEAVE_DDRAW();
return ddrval;
}
}
/*
* Overlay dest. key
*/
if( dwFlags & DDCKEY_DESTOVERLAY )
{
if( lpDDColorKey == NULL )
{
this->dwFlags &= ~DDRAWI_HASCKEYDESTOVERLAY;
}
else
{
this->ddckCKDestOverlay = *lpDDColorKey;
this->dwFlags |= DDRAWI_HASCKEYDESTOVERLAY;
}
/*
* Overlay src. key
*/
}
else if( dwFlags & DDCKEY_SRCOVERLAY )
{
if( lpDDColorKey == NULL )
{
this->dwFlags &= ~DDRAWI_HASCKEYSRCOVERLAY;
}
else
{
this->ddckCKSrcOverlay = *lpDDColorKey;
this->dwFlags |= DDRAWI_HASCKEYSRCOVERLAY;
}
}
/*
* add in extra flags
*/
this->dwFlags |= sflags;
LEAVE_DDRAW();
return DD_OK;
} /* DD_SetColorKey */
#endif
#undef DPF_MODNAME
#define DPF_MODNAME "WaitForVerticalBlank"
/*
* ModeX_WaitForVerticalBlank
*/
static void ModeX_WaitForVerticalBlank( DWORD dwFlags )
{
#if defined (WIN95) || defined ( NT_FIX )
switch( dwFlags )
{
case DDWAITVB_BLOCKBEGIN:
/*
* if blockbegin is requested we wait until the vertical retrace
* is over, and then wait for the display period to end.
*/
while(IN_VBLANK());
while(IN_DISPLAY());
break;
case DDWAITVB_BLOCKEND:
/*
* if blockend is requested we wait for the vblank interval to end.
*/
if( IN_VBLANK() )
{
while( IN_VBLANK() );
}
else
{
while(IN_DISPLAY());
while(IN_VBLANK());
}
break;
}
#endif
} /* ModeX_WaitForVerticalBlank */
/*
* DD_WaitForVerticalBlank
*/
HRESULT DDAPI DD_WaitForVerticalBlank(
LPDIRECTDRAW lpDD,
DWORD dwFlags,
HANDLE hEvent )
{
LPDDRAWI_DIRECTDRAW_INT this_int;
LPDDRAWI_DIRECTDRAW_LCL this_lcl;
LPDDRAWI_DIRECTDRAW_GBL this;
LPDDHAL_WAITFORVERTICALBLANK wfvbhalfn;
LPDDHAL_WAITFORVERTICALBLANK wfvbfn;
ENTER_DDRAW();
TRY
{
this_int = (LPDDRAWI_DIRECTDRAW_INT) lpDD;
if( !VALID_DIRECTDRAW_PTR( this_int ) )
{
LEAVE_DDRAW();
return DDERR_INVALIDOBJECT;
}
this_lcl = this_int->lpLcl;
this = this_lcl->lpGbl;
if( (dwFlags & DDWAITVB_BLOCKBEGINEVENT) || (hEvent != NULL) )
{
DPF_ERR( "Event's not currently supported" );
LEAVE_DDRAW();
return DDERR_UNSUPPORTED;
}
if( (dwFlags != DDWAITVB_BLOCKBEGIN) && (dwFlags != DDWAITVB_BLOCKEND) )
{
DPF_ERR( "Invalid dwFlags" );
LEAVE_DDRAW();
return DDERR_INVALIDPARAMS;
}
}
EXCEPT( EXCEPTION_EXECUTE_HANDLER )
{
DPF_ERR( "Exception encountered validating parameters" );
LEAVE_DDRAW();
return DDERR_INVALIDPARAMS;
}
/*
* ask the driver to wait for the vertical blank
*/
if( this->dwFlags & DDRAWI_MODEX )
{
ModeX_WaitForVerticalBlank( dwFlags );
}
else
{
#pragma message( REMIND( "Need HEL WaitForVerticalBlank" ))
wfvbfn = this_lcl->lpDDCB->HALDD.WaitForVerticalBlank;
wfvbhalfn = this_lcl->lpDDCB->cbDDCallbacks.WaitForVerticalBlank;
if( wfvbhalfn != NULL )
{
DDHAL_WAITFORVERTICALBLANKDATA wfvbd;
DWORD rc;
wfvbd.WaitForVerticalBlank = wfvbhalfn;
wfvbd.lpDD = this;
wfvbd.dwFlags = dwFlags;
wfvbd.hEvent = (DWORD) hEvent;
DOHALCALL( WaitForVerticalBlank, wfvbfn, wfvbd, rc, FALSE );
if( rc == DDHAL_DRIVER_HANDLED )
{
LEAVE_DDRAW();
return wfvbd.ddRVal;
}
}
}
LEAVE_DDRAW();
return DDERR_UNSUPPORTED;
} /* DD_WaitForVerticalBlank */
#undef DPF_MODNAME
#define DPF_MODNAME "GetMonitorFrequency"
/*
* DD_GetMonitorFrequency
*/
HRESULT DDAPI DD_GetMonitorFrequency(
LPDIRECTDRAW lpDD,
LPDWORD lpdwFrequency)
{
LPDDRAWI_DIRECTDRAW_INT this_int;
LPDDRAWI_DIRECTDRAW_LCL this_lcl;
LPDDRAWI_DIRECTDRAW_GBL this;
ENTER_DDRAW();
TRY
{
this_int = (LPDDRAWI_DIRECTDRAW_INT) lpDD;
if( !VALID_DIRECTDRAW_PTR( this_int ) )
{
LEAVE_DDRAW();
return DDERR_INVALIDOBJECT;
}
this_lcl = this_int->lpLcl;
this = this_lcl->lpGbl;
if( !VALID_DWORD_PTR( lpdwFrequency ) )
{
DPF_ERR( "Invalid frequency pointer" );
LEAVE_DDRAW();
return DDERR_INVALIDPARAMS;
}
if( this->dwMonitorFrequency == 0 )
{
LEAVE_DDRAW();
return DDERR_UNSUPPORTED;
}
*lpdwFrequency = this->dwMonitorFrequency;
}
EXCEPT( EXCEPTION_EXECUTE_HANDLER )
{
DPF_ERR( "Exception encountered validating parameters" );
LEAVE_DDRAW();
return DDERR_INVALIDPARAMS;
}
LEAVE_DDRAW();
return DD_OK;
} /* DD_GetMonitorFrequency */
/*
* DoneExclusiveMode
*/
void DoneExclusiveMode( LPDDRAWI_DIRECTDRAW_LCL pdrv_lcl )
{
LPDDRAWI_DIRECTDRAW_GBL pdrv;
DDHAL_SETEXCLUSIVEMODEDATA semd;
LPDDHAL_SETEXCLUSIVEMODE semfn;
LPDDHAL_SETEXCLUSIVEMODE semhalfn;
HRESULT rc;
DPF( 1, "DoneExclusiveMode" );
pdrv = pdrv_lcl->lpGbl;
if( (pdrv->dwFlags & DDRAWI_FULLSCREEN) &&
(pdrv->dwFlags & DDRAWI_DISPLAYDRV) )
{
DPF( 1, "Enabling error mode, hotkeys" );
SetErrorMode( pdrv_lcl->dwErrorMode );
// #ifdef WIN95
{
BOOL old;
SystemParametersInfo( SPI_SCREENSAVERRUNNING, FALSE, &old, 0 );
}
// #endif
}
pdrv->dwFlags &= ~(DDRAWI_FULLSCREEN);
/*
* Driver is no longer flipped to GDI surface.
* NOTE: This does not mean its not showing the GDI surface just that
* its no longer showing the GDI surface as a result of a FlipToGDISurface
*/
pdrv->dwFlags &= ~(DDRAWI_FLIPPEDTOGDI);
// restore the GDI palette
// we let GDI do this by calling SetSystemPaletteUse() this will send
// the right (ie what GDI thinks...) colors down to the device
// this also flushes GDIs palette xlat cache.
if( pdrv->dwModeIndex != DDUNSUPPORTEDMODE && NULL != pdrv->lpModeInfo)
{
if( pdrv->lpModeInfo[ pdrv->dwModeIndex ].wFlags & DDMODEINFO_PALETTIZED )
{
HDC hdc;
hdc = GetDC(NULL);
SetSystemPaletteUse(hdc, SYSPAL_STATIC);
DPF(7,"SetSystemPaletteUse STATICS ON (DoneExclusiveMode)");
if (pdrv_lcl->lpPrimary)//if we have a primary
{
if (pdrv_lcl->lpPrimary->lpLcl->lpDDPalette) //if that primary has a palette
{
pdrv_lcl->lpPrimary->lpLcl->lpDDPalette->lpLcl->lpGbl->dwFlags &= ~DDRAWIPAL_EXCLUSIVE;
DPF(7,"Setting non-exclusive for palette %08x",pdrv_lcl->lpPrimary->lpLcl->lpDDPalette->lpLcl);
}
}
ReleaseDC(NULL, hdc);
}
#ifdef WINNT
// this fixes DOS Box colors on NT. We need to do this even in non-
// palettized modes.
PostMessage(HWND_BROADCAST, WM_PALETTECHANGED, (WPARAM)pdrv_lcl->hWnd, 0);
#endif
}
/*
* Restore the display mode in case it was changed while
* in exclusive mode.
* Only do this if we are not adhering to the v1 behaviour
*/
if( !(pdrv_lcl->dwLocalFlags & DDRAWILCL_V1SCLBEHAVIOUR) )
{
RestoreDisplayMode( pdrv_lcl, TRUE );
}
/*
* Notify the driver that we are leaving exclusive mode.
* NOTE: This is a HAL only call - the HEL does not get to
* see it.
* NOTE: We don't allow the driver to fail this call. This is
* a notification callback only.
*/
semfn = pdrv_lcl->lpDDCB->HALDD.SetExclusiveMode;
semhalfn = pdrv_lcl->lpDDCB->cbDDCallbacks.SetExclusiveMode;
if( NULL != semhalfn )
{
semd.SetExclusiveMode = semhalfn;
semd.lpDD = pdrv;
semd.dwEnterExcl = FALSE;
semd.dwReserved = 0UL;
DOHALCALL( SetExclusiveMode, semfn, semd, rc, FALSE );
DDASSERT( ( DDHAL_DRIVER_HANDLED == rc ) && ( !FAILED( semd.ddRVal ) ) );
}
pdrv->lpExclusiveOwner = NULL;
} /* DoneExclusiveMode */
/*
* StartExclusiveMode
*/
void StartExclusiveMode( LPDDRAWI_DIRECTDRAW_LCL pdrv_lcl, DWORD dwFlags, DWORD pid )
{
LPDDRAWI_DIRECTDRAW_GBL pdrv;
DDHAL_SETEXCLUSIVEMODEDATA semd;
LPDDHAL_SETEXCLUSIVEMODE semfn;
LPDDHAL_SETEXCLUSIVEMODE semhalfn;
HRESULT rc;
DPF( 1, "StartExclusiveMode" );
pdrv = pdrv_lcl->lpGbl;
pdrv->lpExclusiveOwner = pdrv_lcl;
if( (pdrv->dwFlags & DDRAWI_FULLSCREEN) &&
(pdrv->dwFlags & DDRAWI_DISPLAYDRV) )
{
pdrv_lcl->dwErrorMode = SetErrorMode( SEM_NOGPFAULTERRORBOX | SEM_FAILCRITICALERRORS | SEM_NOOPENFILEERRORBOX );
// #ifdef WIN95
{
BOOL old;
SystemParametersInfo( SPI_SCREENSAVERRUNNING, TRUE, &old, 0 );
#ifdef WIN95
if( dwFlags & DDSCL_ALLOWREBOOT )
{
/*
* re-enable reboot after SPI_SCREENSAVERRUNNING, it disables it
*/
DD16_EnableReboot( TRUE );
}
#endif
}
// #endif
}
/*
* invalidate all primary surfaces. This includes the primary surface
* for the current process if it was created before exclusive mode was
* entered.
*
* we must invalidate ALL surfaces in case the app doesn't switch the
* mode. - craige 7/9/95
*/
InvalidateAllSurfaces( pdrv );
/*
* Notify the driver that we are entering exclusive mode.
* NOTE: This is a HAL only call - the HEL does not get to
* see it.
* NOTE: We don't allow the driver to fail this call. This is
* a notification callback only.
*/
semfn = pdrv_lcl->lpDDCB->HALDD.SetExclusiveMode;
semhalfn = pdrv_lcl->lpDDCB->cbDDCallbacks.SetExclusiveMode;
if( NULL != semhalfn )
{
semd.SetExclusiveMode = semhalfn;
semd.lpDD = pdrv;
semd.dwEnterExcl = TRUE;
semd.dwReserved = 0UL;
DOHALCALL( SetExclusiveMode, semfn, semd, rc, FALSE );
DDASSERT( ( DDHAL_DRIVER_HANDLED == rc ) && ( !FAILED( semd.ddRVal ) ) );
}
} /* StartExclusiveMode */
#undef DPF_MODNAME
#define DPF_MODNAME "SetCooperativeLevel"
/*
* DD_SetCooperativeLevel
*/
HRESULT DDAPI DD_SetCooperativeLevel(
LPDIRECTDRAW lpDD,
HWND hWnd,
DWORD dwFlags )
{
LPDDRAWI_DIRECTDRAW_INT this_int;
LPDDRAWI_DIRECTDRAW_LCL this_lcl;
LPDDRAWI_DIRECTDRAW_GBL this;
DWORD pid;
HRESULT ddrval;
DWORD style;
HWND old_hwnd;
ENTER_DDRAW();
TRY
{
this_int = (LPDDRAWI_DIRECTDRAW_INT) lpDD;
if( !VALID_DIRECTDRAW_PTR( this_int ) )
{
LEAVE_DDRAW();
return DDERR_INVALIDOBJECT;
}
this_lcl = this_int->lpLcl;
this = this_lcl->lpGbl;
if( dwFlags & ~DDSCL_VALID )
{
DPF_ERR( "Invalid flags specified" );
LEAVE_DDRAW();
return DDERR_INVALIDPARAMS;
}
if( !(dwFlags & (DDSCL_EXCLUSIVE|DDSCL_NORMAL) ) )
{
DPF_ERR( "Must specify one of EXCLUSIVE or NORMAL" );
LEAVE_DDRAW();
return DDERR_INVALIDPARAMS;
}
if( (dwFlags & DDSCL_EXCLUSIVE) && !(dwFlags & DDSCL_FULLSCREEN) )
{
DPF_ERR( "Must specify fullscreen for exclusive mode" );
LEAVE_DDRAW();
return DDERR_INVALIDPARAMS;
}
if( (dwFlags & DDSCL_ALLOWMODEX) && !(dwFlags & DDSCL_FULLSCREEN) )
{
DPF_ERR( "Must specify fullscreen for modex" );
LEAVE_DDRAW();
return DDERR_INVALIDPARAMS;
}
if( (hWnd != NULL) && !IsWindow( hWnd ) )
{
DPF_ERR( "Hwnd passed is not a valid window" );
LEAVE_DDRAW();
return DDERR_INVALIDPARAMS;
}
if( (dwFlags & DDSCL_DONTHOOKHWND) && (dwFlags & DDSCL_EXCLUSIVE) )
{
DPF_ERR( "we must hook the window in exclusive mode" );
LEAVE_DDRAW();
return DDERR_INVALIDPARAMS;
}
if( dwFlags & DDSCL_EXCLUSIVE )
{
if( NULL == hWnd )
{
DPF_ERR( "Hwnd must be specified for exclusive mode" );
LEAVE_DDRAW();
return DDERR_INVALIDPARAMS;
}
if( (GetWindowLong(hWnd, GWL_STYLE) & WS_CHILD) )
{
DPF_ERR( "Hwnd must be a top level window" );
LEAVE_DDRAW();
return DDERR_INVALIDPARAMS;
}
}
pid = GETCURRPID();
if( dwFlags & DDSCL_EXCLUSIVE )
{
if( (this->lpExclusiveOwner != NULL) &&
(this->lpExclusiveOwner != this_lcl) )
{
DPF_ERR( "another app is already in exclusive mode" );
LEAVE_DDRAW();
return DDERR_EXCLUSIVEMODEALREADYSET;
}
}
}
EXCEPT( EXCEPTION_EXECUTE_HANDLER )
{
DPF_ERR( "Exception encountered validating parameters" );
LEAVE_DDRAW();
return DDERR_INVALIDPARAMS;
}
/*
* In v1, we allowed an app to set the mode while in exclusive mode but
* we didn't restore the mode if the app lost exclusive mode. We have
* changed this behaviour in v2 to cause the display mode to be restored
* when exclusive mode is lost. If the v1 SetCooperativeLevel is ever
* called then we revert back to the v1 behaviour to avoid breaking
* existing apps.
*/
if( this_int->lpVtbl == &ddCallbacks )
{
// This is the V1 SetCooperativeLevel
this_lcl->dwLocalFlags |= DDRAWILCL_V1SCLBEHAVIOUR;
}
/*
* don't dork with dialogs, this is a hack for DDTEST and DDCAPS
*/
if( NULL != hWnd )
{
style = GetWindowLong(hWnd, GWL_STYLE);
if ((style & WS_CAPTION) == WS_DLGFRAME)
{
DPF( 1, "setting DDSCL_NOWINDOWCHANGES for caller" );
dwFlags |= DDSCL_NOWINDOWCHANGES;
}
}
// Save the hwnd in the local object for later reference
old_hwnd = (HWND)this_lcl->hWnd;
(HWND) this_lcl->hWnd = hWnd;
/*
* allow modex modes?
*/
if( (dwFlags & DDSCL_ALLOWMODEX) &&
!( this->dwFlags & DDRAWI_MODEXILLEGAL ) )
{
DPF( 4, "*********** ALLOWING MODE X MODES" );
this_lcl->dwLocalFlags |= DDRAWILCL_ALLOWMODEX;
}
else
{
DPF( 4, "*********** NOT!! ALLOWING MODE X MODES" );
this_lcl->dwLocalFlags &= ~DDRAWILCL_ALLOWMODEX;
}
/*
* exclusive mode?
*/
if( dwFlags & DDSCL_EXCLUSIVE )
{
if( dwFlags & DDSCL_FULLSCREEN )
{
this->dwFlags |= DDRAWI_FULLSCREEN;
this_lcl->dwLocalFlags |= DDRAWILCL_ISFULLSCREEN;
}
// Only hook if exclusive mode requested
if( !(dwFlags & DDSCL_DONTHOOKHWND) )
{
ddrval = SetAppHWnd( this_lcl, hWnd, dwFlags );
if( ddrval != DD_OK )
{
DPF( 1, "Could not hook HWND!" );
LEAVE_DDRAW();
return ddrval;
}
this_lcl->dwLocalFlags |= DDRAWILCL_HOOKEDHWND;
}
if( this->lpExclusiveOwner != this_lcl)
{
StartExclusiveMode( this_lcl, dwFlags, pid );
this_lcl->dwLocalFlags |= DDRAWILCL_ACTIVEYES;
this_lcl->dwLocalFlags &=~DDRAWILCL_ACTIVENO;
SetForegroundWindow(hWnd);
this_lcl->dwLocalFlags |= DDRAWILCL_HASEXCLUSIVEMODE;
}
}
/*
* no, must be regular
*/
else
{
if( this_lcl->dwLocalFlags & DDRAWILCL_HASEXCLUSIVEMODE )
{
/*
* If we are leaving exclusive mode ensure we are
* looking at the GDI surface.
*/
DD_FlipToGDISurface( lpDD );
DoneExclusiveMode( this_lcl );
this_lcl->dwLocalFlags &= ~(DDRAWILCL_ISFULLSCREEN |
DDRAWILCL_ALLOWMODEX |
DDRAWILCL_HASEXCLUSIVEMODE);
// Lost exclusive mode, need to remove window hook?
if( this_lcl->dwLocalFlags & DDRAWILCL_HOOKEDHWND )
{
ddrval = SetAppHWnd( this_lcl, NULL, dwFlags );
if( ddrval != DD_OK )
{
DPF( 1, "Could not unhook HWND!" );
LEAVE_DDRAW();
return ddrval;
}
this_lcl->dwLocalFlags &= ~DDRAWILCL_HOOKEDHWND;
}
/*
* make the window non-topmost
*/
if (!(dwFlags & DDSCL_NOWINDOWCHANGES) && (IsWindow(old_hwnd)))
{
SetWindowPos(old_hwnd, HWND_NOTOPMOST,
0, 0, 0, 0, SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE);
}
}
}
// Allow other DD objects to be created now.
this_lcl->dwLocalFlags |= DDRAWILCL_SETCOOPCALLED;
LEAVE_DDRAW();
return DD_OK;
} /* DD_SetCooperativeLevel */
#undef DPF_MODNAME
#define DPF_MODNAME "DuplicateSurface"
/*
* DD_DuplicateSurface
*
* Create a duplicate surface from an existing one.
* The surface will have the same properties and point to the same
* video memory.
*/
HRESULT DDAPI DD_DuplicateSurface(
LPDIRECTDRAW lpDD,
LPDIRECTDRAWSURFACE lpDDSurface,
LPDIRECTDRAWSURFACE FAR *lplpDupDDSurface )
{
LPDDRAWI_DIRECTDRAW_INT this_int;
LPDDRAWI_DIRECTDRAW_LCL this_lcl;
LPDDRAWI_DIRECTDRAW_GBL this;
LPDDRAWI_DDRAWSURFACE_LCL orig_surf_lcl;
LPDDRAWI_DDRAWSURFACE_LCL new_surf_lcl;
LPDDRAWI_DDRAWSURFACE_INT orig_surf_int;
LPDDRAWI_DDRAWSURFACE_INT new_surf_int;
ENTER_DDRAW();
TRY
{
this_int = (LPDDRAWI_DIRECTDRAW_INT) lpDD;
if( !VALID_DIRECTDRAW_PTR( this_int ) )
{
LEAVE_DDRAW();
return DDERR_INVALIDOBJECT;
}
this_lcl = this_int->lpLcl;
this = this_lcl->lpGbl;
orig_surf_int = (LPDDRAWI_DDRAWSURFACE_INT) lpDDSurface;
if( !VALID_DIRECTDRAWSURFACE_PTR( orig_surf_int ) )
{
LEAVE_DDRAW();
return DDERR_INVALIDOBJECT;
}
orig_surf_lcl = orig_surf_int->lpLcl;
if( SURFACE_LOST( orig_surf_lcl ) )
{
LEAVE_DDRAW();
return DDERR_SURFACELOST;
}
if( !VALID_PTR_PTR( lplpDupDDSurface ) )
{
DPF_ERR( "Invalid dup surface pointer" );
LEAVE_DDRAW();
return DDERR_INVALIDPARAMS;
}
*lplpDupDDSurface = NULL;
/*
* make sure we can duplicate this baby
*/
if( orig_surf_lcl->ddsCaps.dwCaps & (DDSCAPS_PRIMARYSURFACE) )
{
DPF_ERR( "Can't duplicate primary surface" );
LEAVE_DDRAW();
return DDERR_CANTDUPLICATE;
}
if( orig_surf_lcl->dwFlags & (DDRAWISURF_IMPLICITCREATE) )
{
DPF_ERR( "Can't duplicate implicitly created surfaces" );
LEAVE_DDRAW();
return DDERR_CANTDUPLICATE;
}
}
EXCEPT( EXCEPTION_EXECUTE_HANDLER )
{
DPF_ERR( "Exception encountered validating parameters" );
LEAVE_DDRAW();
return DDERR_INVALIDPARAMS;
}
/*
* go make ourselves a new interface for this surface...
*/
new_surf_lcl = NewSurfaceLocal( orig_surf_lcl, orig_surf_int->lpVtbl );
if( NULL == new_surf_lcl )
{
LEAVE_DDRAW();
return DDERR_OUTOFMEMORY;
}
/*
* NewSurfaceLocal does not initialize the lpDD_lcl field of the
* local surface object's lpSurfMore data structure. Need to do
* this here as it is needed by Release.
*/
new_surf_lcl->lpSurfMore->lpDD_lcl = this_lcl;
new_surf_lcl->lpSurfMore->lpDD_int = this_int;
new_surf_int = NewSurfaceInterface( new_surf_lcl, orig_surf_int->lpVtbl );
if( new_surf_int == NULL )
{
MemFree(new_surf_lcl);
LEAVE_DDRAW();
return DDERR_OUTOFMEMORY;
}
DD_Surface_AddRef( (LPDIRECTDRAWSURFACE)new_surf_int );
if( new_surf_lcl->ddsCaps.dwCaps & DDSCAPS_OVERLAY )
{
new_surf_lcl->dbnOverlayNode.object = new_surf_lcl;
new_surf_lcl->dbnOverlayNode.object_int = new_surf_int;
}
LEAVE_DDRAW();
*lplpDupDDSurface = (LPDIRECTDRAWSURFACE) new_surf_int;
return DD_OK;
} /* DD_DuplicateSurface */
#undef DPF_MODNAME
#define DPF_MODNAME "GetGDISurface"
/*
* DD_GetGDISurface
*
* Get the current surface associated with GDI
*/
HRESULT DDAPI DD_GetGDISurface(
LPDIRECTDRAW lpDD,
LPDIRECTDRAWSURFACE FAR *lplpGDIDDSurface )
{
LPDDRAWI_DIRECTDRAW_INT this_int;
LPDDRAWI_DIRECTDRAW_LCL this_lcl;
LPDDRAWI_DIRECTDRAW_GBL this;
LPDDRAWI_DDRAWSURFACE_INT psurf_int;
LPDDRAWI_DDRAWSURFACE_LCL psurf_lcl;
LPDDRAWI_DDRAWSURFACE_GBL psurf;
LPDDRAWI_DDRAWSURFACE_INT next_int;
LPDDRAWI_DDRAWSURFACE_LCL next_lcl;
LPDDRAWI_DDRAWSURFACE_GBL next;
ENTER_DDRAW();
TRY
{
this_int = (LPDDRAWI_DIRECTDRAW_INT) lpDD;
if( !VALID_DIRECTDRAW_PTR( this_int ) )
{
LEAVE_DDRAW();
return DDERR_INVALIDOBJECT;
}
this_lcl = this_int->lpLcl;
this = this_lcl->lpGbl;
if( !VALID_PTR_PTR( lplpGDIDDSurface ) )
{
DPF_ERR( "Invalid gdi surface pointer" );
LEAVE_DDRAW();
return DDERR_INVALIDPARAMS;
}
*lplpGDIDDSurface = NULL;
}
EXCEPT( EXCEPTION_EXECUTE_HANDLER )
{
DPF_ERR( "Exception encountered validating parameters" );
LEAVE_DDRAW();
return DDERR_INVALIDPARAMS;
}
/*
* go find the surface. start at the primary, look at all attached...
*/
psurf_int = this_lcl->lpPrimary;
if( psurf_int != NULL )
{
psurf_lcl = psurf_int->lpLcl;
psurf = psurf_lcl->lpGbl;
if( !(psurf->dwGlobalFlags & DDRAWISURFGBL_ISGDISURFACE) ) //psurf->fpVidMem != this->fpPrimaryOrig )
{
next_int = FindAttachedFlip( psurf_int );
if( next_int != psurf_int )
{
next_lcl = next_int->lpLcl;
next = next_lcl->lpGbl;
do
{
if( next->dwGlobalFlags & DDRAWISURFGBL_ISGDISURFACE ) //next->fpVidMem == this->fpPrimaryOrig )
{
DD_Surface_AddRef( (LPDIRECTDRAWSURFACE) next_int );
*lplpGDIDDSurface = (LPDIRECTDRAWSURFACE) next_int;
LEAVE_DDRAW();
return DD_OK;
}
next_int = FindAttachedFlip( next_int );
} while( next_int != psurf_int );
}
DPF_ERR( "Not found" );
}
else
{
DD_Surface_AddRef( (LPDIRECTDRAWSURFACE) psurf_int );
*lplpGDIDDSurface = (LPDIRECTDRAWSURFACE) psurf_int;
LEAVE_DDRAW();
return DD_OK;
}
}
else
{
DPF_ERR( "No Primary Surface" );
}
LEAVE_DDRAW();
return DDERR_NOTFOUND;
} /* DD_GetGDISurface */
#undef DPF_MODNAME
#define DPF_MODNAME "FlipToGDISurface"
/*
* FlipToGDISurface
*/
HRESULT FlipToGDISurface( LPDDRAWI_DIRECTDRAW_LCL pdrv_lcl,
LPDDRAWI_DDRAWSURFACE_INT psurf_int) //, FLATPTR fpprim )
{
LPDDRAWI_DIRECTDRAW_GBL pdrv;
LPDDRAWI_DDRAWSURFACE_LCL psurf_lcl;
LPDDRAWI_DDRAWSURFACE_INT attached_int;
DDHAL_FLIPTOGDISURFACEDATA ftgsd;
LPDDHAL_FLIPTOGDISURFACE ftgsfn;
LPDDHAL_FLIPTOGDISURFACE ftgshalfn;
HRESULT ddrval;
pdrv = pdrv_lcl->lpGbl;
psurf_lcl = psurf_int->lpLcl;
if( psurf_lcl->ddsCaps.dwCaps & DDSCAPS_SYSTEMMEMORY )
return DD_OK;
/*
* Notify the driver that we are about to flip to GDI
* surface.
* NOTE: This is a HAL only call - it means nothing to the
* HEL.
* NOTE: If the driver handles this call then we do not
* attempt to do the actual flip. This is to support cards
* which do not have GDI surfaces. If the driver does not
* handle the call we will continue on and do the flip.
*/
ftgsfn = pdrv_lcl->lpDDCB->HALDD.FlipToGDISurface;
ftgshalfn = pdrv_lcl->lpDDCB->cbDDCallbacks.FlipToGDISurface;
if( NULL != ftgshalfn )
{
ftgsd.FlipToGDISurface = ftgshalfn;
ftgsd.lpDD = pdrv;
ftgsd.dwToGDI = TRUE;
ftgsd.dwReserved = 0UL;
DOHALCALL( FlipToGDISurface, ftgsfn, ftgsd, ddrval, FALSE );
if( DDHAL_DRIVER_HANDLED == ddrval )
{
if( !FAILED( ftgsd.ddRVal ) )
{
/*
* The driver is not showing the GDI surface as a
* result of a flip to GDI operation.
*/
pdrv->dwFlags |= DDRAWI_FLIPPEDTOGDI;
DPF( 4, "Driver handled FlipToGDISurface" );
return ftgsd.ddRVal;
}
else
{
DPF_ERR( "Driver failed FlipToGDISurface" );
return ftgsd.ddRVal;
}
}
}
/*
* No HAL entry point. If this is not a GDI driver we will
* fail the call with NOGDI.
*/
if( ( NULL == ftgshalfn ) && !( pdrv->dwFlags & DDRAWI_DISPLAYDRV ) )
{
DPF( 0, "Not a GDI driver" );
return DDERR_NOGDI;
}
/*
* Driver did not handle FlipToGDISurface so do the default action
* (the actual flip).
*
* go find our partner in the attachment list
*/
attached_int = FindAttachedFlip( psurf_int );
if( attached_int == NULL )
{
return DDERR_NOTFOUND;
}
while( attached_int != psurf_int )
{
if( attached_int->lpLcl->lpGbl->dwGlobalFlags & DDRAWISURFGBL_ISGDISURFACE) //->lpGbl->fpVidMem == fpprim )
{
break;
}
attached_int = FindAttachedFlip( attached_int );
}
/*
* flip between the two buddies
*/
ddrval = DD_Surface_Flip( (LPDIRECTDRAWSURFACE) psurf_int,
(LPDIRECTDRAWSURFACE) attached_int, DDFLIP_WAIT );
if( ddrval != DD_OK )
{
DPF_ERR( "Couldn't do the flip!" );
DPF( 1, "Error = %08lx (%ld)", ddrval, LOWORD( ddrval ) );
}
/*
* The driver is now showing the GDI surface as a result of a
* FlipToGDISurface operation.
*/
pdrv->dwFlags |= DDRAWI_FLIPPEDTOGDI;
return ddrval;
} /* FlipToGDISurface */
/*
* DD_FlipToGDISurface
*
* Get the current surface associated with GDI
*/
HRESULT DDAPI DD_FlipToGDISurface( LPDIRECTDRAW lpDD )
{
LPDDRAWI_DIRECTDRAW_INT this_int;
LPDDRAWI_DIRECTDRAW_LCL this_lcl;
LPDDRAWI_DIRECTDRAW_GBL this;
LPDDRAWI_DDRAWSURFACE_INT psurf_int;
LPDDRAWI_DDRAWSURFACE_LCL psurf_lcl;
LPDDRAWI_DDRAWSURFACE_GBL psurf;
HRESULT ddrval;
// FLATPTR fpprim;
ENTER_DDRAW();
TRY
{
this_int = (LPDDRAWI_DIRECTDRAW_INT) lpDD;
if( !VALID_DIRECTDRAW_PTR( this_int ) )
{
LEAVE_DDRAW();
return DDERR_INVALIDOBJECT;
}
this_lcl = this_int->lpLcl;
this = this_lcl->lpGbl;
}
EXCEPT( EXCEPTION_EXECUTE_HANDLER )
{
DPF_ERR( "Exception encountered validating parameters" );
LEAVE_DDRAW();
return DDERR_INVALIDPARAMS;
}
psurf_int = this_lcl->lpPrimary;
if( psurf_int == NULL )
{
DPF_ERR( "No Primary Surface" );
LEAVE_DDRAW();
return DDERR_NOTFOUND;
}
psurf_lcl = psurf_int->lpLcl;
psurf = psurf_lcl->lpGbl;
if( !(psurf_lcl->ddsCaps.dwCaps & DDSCAPS_FLIP) )
{
DPF_ERR( "Primary surface isn't flippable" );
LEAVE_DDRAW();
return DDERR_NOTFLIPPABLE;
}
/*
* only do the flip if needed of course
*/
// fpprim = this->fpPrimaryOrig;
ddrval = DD_OK;
if( !(psurf->dwGlobalFlags & DDRAWISURFGBL_ISGDISURFACE)) //->fpVidMem != fpprim )
ddrval = FlipToGDISurface( this_lcl, psurf_int); //, fpprim );
LEAVE_DDRAW();
return ddrval;
} /* DD_FlipToGDISurface */
#undef DPF_MODNAME
#define DPF_MODNAME "GetFourCCCodes"
/*
* DD_GetFourCCCodes
*/
HRESULT DDAPI DD_GetFourCCCodes(
LPDIRECTDRAW lpDD,
DWORD FAR *lpNumCodes,
DWORD FAR *lpCodes )
{
LPDDRAWI_DIRECTDRAW_INT this_int;
LPDDRAWI_DIRECTDRAW_LCL this_lcl;
LPDDRAWI_DIRECTDRAW_GBL this;
int numcodes;
int i;
ENTER_DDRAW();
TRY
{
this_int = (LPDDRAWI_DIRECTDRAW_INT) lpDD;
if( !VALID_DIRECTDRAW_PTR( this_int ) )
{
LEAVE_DDRAW();
return DDERR_INVALIDOBJECT;
}
this_lcl = this_int->lpLcl;
this = this_lcl->lpGbl;
if( !VALID_DWORD_PTR( lpNumCodes ) )
{
DPF_ERR( "Invalid number of codes pointer" );
LEAVE_DDRAW();
return DDERR_INVALIDPARAMS;
}
if( (*lpNumCodes > 0) && (lpCodes != NULL) )
{
if( !VALID_DWORD_ARRAY( lpCodes, *lpNumCodes ) )
{
DPF_ERR( "Invalid array of codes" );
LEAVE_DDRAW();
return DDERR_INVALIDPARAMS;
}
}
if( lpCodes == NULL )
{
*lpNumCodes = this->dwNumFourCC;
}
else
{
numcodes = min( *lpNumCodes, this->dwNumFourCC );
*lpNumCodes = numcodes;
for( i=0;i<numcodes;i++ )
{
lpCodes[i] = this->lpdwFourCC[i];
}
}
}
EXCEPT( EXCEPTION_EXECUTE_HANDLER )
{
DPF_ERR( "Exception encountered validating parameters" );
LEAVE_DDRAW();
return DDERR_INVALIDPARAMS;
}
LEAVE_DDRAW();
return DD_OK;
} /* DD_GetFourCCCodes */
#undef DPF_MODNAME
#define DPF_MODNAME "Compact"
/*
* DD_Compact
*/
HRESULT DDAPI DD_Compact( LPDIRECTDRAW lpDD )
{
LPDDRAWI_DIRECTDRAW_INT this_int;
LPDDRAWI_DIRECTDRAW_LCL this_lcl;
LPDDRAWI_DIRECTDRAW_GBL this;
ENTER_DDRAW();
TRY
{
this_int = (LPDDRAWI_DIRECTDRAW_INT) lpDD;
if( !VALID_DIRECTDRAW_PTR( this_int ) )
{
LEAVE_DDRAW();
return DDERR_INVALIDOBJECT;
}
this_lcl = this_int->lpLcl;
this = this_lcl->lpGbl;
if( this->lpExclusiveOwner != this_lcl )
{
LEAVE_DDRAW();
return DDERR_NOEXCLUSIVEMODE;
}
}
EXCEPT( EXCEPTION_EXECUTE_HANDLER )
{
DPF_ERR( "Exception encountered validating parameters" );
LEAVE_DDRAW();
return DDERR_INVALIDPARAMS;
}
#pragma message( REMIND( "Compact not implemented in Rev 1" ) )
LEAVE_DDRAW();
return DD_OK;
}/* DD_Compact */
#undef DPF_MODNAME
#define DPF_MODNAME "GetAvailableVidMem"
/*
* DD_GetAvailableVidMem
*/
HRESULT DDAPI DD_GetAvailableVidMem( LPDIRECTDRAW lpDD, LPDDSCAPS lpDDSCaps, LPDWORD lpdwTotal, LPDWORD lpdwFree )
{
LPDDRAWI_DIRECTDRAW_INT this_int;
LPDDRAWI_DIRECTDRAW_LCL this_lcl;
LPDDRAWI_DIRECTDRAW_GBL this;
LPVIDMEM pvm;
int i;
DWORD dwFree;
ENTER_DDRAW();
TRY
{
this_int = (LPDDRAWI_DIRECTDRAW_INT) lpDD;
if( !VALID_DIRECTDRAW_PTR( this_int ) )
{
LEAVE_DDRAW();
return DDERR_INVALIDOBJECT;
}
this_lcl = this_int->lpLcl;
this = this_lcl->lpGbl;
/*
* This call only considers vram so if running in emulation
* only there really is no point.
*/
if( this->dwFlags & DDRAWI_NOHARDWARE )
{
DPF_ERR( "No video memory - running emulation only" );
LEAVE_DDRAW();
return DDERR_NODIRECTDRAWHW;
}
if( !VALID_DDSCAPS_PTR( lpDDSCaps ) )
{
LEAVE_DDRAW();
return DDERR_INVALIDPARAMS;
}
/*
* Check for generically bogus caps.
*/
if( lpDDSCaps->dwCaps & ~DDSCAPS_VALID )
{
DPF_ERR( "Invalid surface caps specified" );
LEAVE_DDRAW();
return DDERR_INVALIDCAPS;
}
/*
* !!! NOTE: Consider using the capability checking code
* of CreateSurface here to ensure no silly bit combinations
* are passed in.
*/
if( lpDDSCaps->dwCaps & AVAILVIDMEM_BADSCAPS )
{
DPF_ERR( "Invalid surface capability bits specified" );
LEAVE_DDRAW();
return DDERR_INVALIDPARAMS;
}
/*
* The caller can pass NULL for lpdwTotal or lpdwFree if
* they are not interested in that info. However, they
* can't pass NULL for both (that would be silly).
*/
if( ( lpdwTotal == NULL ) && ( lpdwFree == NULL ) )
{
DPF_ERR( "Can't specify NULL for both total and free memory" );
LEAVE_DDRAW();
return DDERR_INVALIDPARAMS;
}
if( ( lpdwTotal != NULL ) && !VALID_DWORD_PTR( lpdwTotal ) )
{
LEAVE_DDRAW();
return DDERR_INVALIDPARAMS;
}
if( ( lpdwFree != NULL ) && !VALID_DWORD_PTR( lpdwFree ) )
{
LEAVE_DDRAW();
return DDERR_INVALIDPARAMS;
}
}
EXCEPT( EXCEPTION_EXECUTE_HANDLER )
{
DPF_ERR( "Exception encountered validating parameters" );
LEAVE_DDRAW();
return DDERR_INVALIDPARAMS;
}
dwFree = 0UL;
if( lpdwTotal != NULL )
{
*lpdwTotal = 0UL;
}
for( i=0;i<(int)this->vmiData.dwNumHeaps;i++ )
{
pvm = &this->vmiData.pvmList[i];
/*
* We use ddsCapsAlt as we wish to return the total amount
* of memory of the given type it is possible to allocate
* regardless of whether is is desirable to allocate that
* type of memory from a given heap or not.
*/
if( (lpDDSCaps->dwCaps & pvm->ddsCapsAlt.dwCaps) == 0 )
{
dwFree += VidMemAmountFree( pvm->lpHeap );
if( lpdwTotal != NULL )
{
*lpdwTotal += VidMemAmountAllocated( pvm->lpHeap );
}
}
}
if( lpdwFree != NULL )
{
*lpdwFree = dwFree;
}
if( lpdwTotal != NULL )
{
*lpdwTotal += dwFree;
}
LEAVE_DDRAW();
return DD_OK;
} /* DD_GetAvailableVidMem */
#undef DPF_MODNAME
#define DPF_MODNAME "Initialize"
/*
* DD_Initialize
*
* Initialize a DirectDraw object that was created via the class factory
*/
HRESULT DDAPI DD_Initialize( LPDIRECTDRAW lpDD, GUID FAR * lpGUID )
{
LPDDRAWI_DIRECTDRAW_INT this_int;
LPDDRAWI_DIRECTDRAW_LCL this_lcl;
HRESULT hr;
LPDIRECTDRAW tmplpdd;
LPVOID lpOldCallbacks;
ENTER_DDRAW();
DPF( 2, "****** DirectDraw::Initialize( 0x%08lx ) ******", lpGUID );
TRY
{
this_int = (LPDDRAWI_DIRECTDRAW_INT) lpDD;
if( !VALID_DIRECTDRAW_PTR( this_int ) )
{
LEAVE_DDRAW();
return DDERR_INVALIDOBJECT;
}
this_lcl = this_int->lpLcl;
if( this_lcl->lpGbl != NULL )
{
DPF_ERR( "Already initialized." );
LEAVE_DDRAW();
return DDERR_ALREADYINITIALIZED;
}
}
EXCEPT( EXCEPTION_EXECUTE_HANDLER )
{
DPF_ERR( "Exception encountered validating parameters" );
LEAVE_DDRAW();
return DDERR_INVALIDPARAMS;
}
/*
* If the object is uninitialized put the real vtable in place.
*/
lpOldCallbacks = NULL;
if( this_int->lpVtbl == &ddUninitCallbacks )
{
lpOldCallbacks = this_int->lpVtbl;
this_int->lpVtbl = &ddCallbacks;
}
else if( this_int->lpVtbl == &dd2UninitCallbacks )
{
lpOldCallbacks = this_int->lpVtbl;
this_int->lpVtbl = &dd2Callbacks;
}
hr = InternalDirectDrawCreate( (GUID *)lpGUID, &tmplpdd, NULL, this_int );
if( FAILED( hr ) && ( lpOldCallbacks != NULL ) )
{
/*
* As initialization has failed put the vtable back the way it was
* before.
*/
this_int->lpVtbl = lpOldCallbacks;
}
LEAVE_DDRAW();
return hr;
} /* DD_Initialize */