mirror of https://github.com/lianthony/NT4.0
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
1952 lines
48 KiB
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 */
|
|
|