Leaked source code of windows server 2003
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.
 
 
 
 
 
 

3096 lines
102 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
* 01-oct-96 ketand Use GetAvailDriverMemory to free/total vidmem estimates
* 12-oct-96 colinmc Improvements to Win16 locking code to reduce virtual
* memory usage
* 21-jan-97 ketand Deleted unused Get/SetColorKey. Put existing DDraw windowed
* apps into emulation on multi-mon systems.
* 30-jan-97 colinmc Work item 4125: Need time bomb for final
* 29-jan-97 jeffno Mode13 support. Just debugging changes.
* 07-feb-97 ketand Fix Multi-Mon when running EMULATION_ONLY and going full-screen
* 08-mar-97 colinmc Support for DMA model AGP parts
* 24-mar-97 jeffno Optimized Surfaces
* 30-sep-97 jeffno IDirectDraw4
*
***************************************************************************/
#include "ddrawpr.h"
#include "dx8priv.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)
extern BYTE szDeviceWndClass[];
extern LRESULT WINAPI DeviceWindowProc( HWND, UINT, WPARAM, LPARAM );
#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();
/* Removed because too many: DPF(2,A,"ENTERAPI: DD_GetVerticalBlankStatus"); */
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;
#ifdef WINNT
// Update DDraw handle in driver GBL object.
this->hDD = this_lcl->hDD;
#endif //WINNT
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();
DPF(2,A,"ENTERAPI: DD_GetScanLine");
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;
#ifdef WINNT
// Update DDraw handle in driver GBL object.
this->hDD = this_lcl->hDD;
#endif //WINNT
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 "BuildDDCAPS"
/*
* Build a fullsized, API visible DDCAPS structure from the multiple internal
* caps structures in the global driver object.
*/
static void BuildDDCAPS( LPDDCAPS lpddcaps, LPDDRAWI_DIRECTDRAW_GBL pdrv, BOOL bHEL )
{
LPDDCORECAPS lpddcorecaps;
LPDDNONLOCALVIDMEMCAPS lpddnlvcaps;
LPDDMORECAPS lpddmorecaps;
LPDDSCAPSEX lpddsExCaps;
DDASSERT( NULL != lpddcaps );
DDASSERT( NULL != pdrv );
lpddcorecaps = ( bHEL ? &( pdrv->ddHELCaps ) : &( pdrv->ddCaps ) );
lpddnlvcaps = ( bHEL ? pdrv->lpddNLVHELCaps : pdrv->lpddNLVCaps );
lpddmorecaps = ( bHEL ? pdrv->lpddHELMoreCaps : pdrv->lpddMoreCaps );
lpddsExCaps = ( bHEL ? &pdrv->ddsHELCapsMore : &pdrv->ddsCapsMore );
memset( lpddcaps, 0, sizeof( DDCAPS ) );
memcpy( lpddcaps, lpddcorecaps, sizeof( DDCORECAPS ) );
if( NULL != lpddnlvcaps )
{
lpddcaps->dwNLVBCaps = lpddnlvcaps->dwNLVBCaps;
lpddcaps->dwNLVBCaps2 = lpddnlvcaps->dwNLVBCaps2;
lpddcaps->dwNLVBCKeyCaps = lpddnlvcaps->dwNLVBCKeyCaps;
lpddcaps->dwNLVBFXCaps = lpddnlvcaps->dwNLVBFXCaps;
memcpy( &( lpddcaps->dwNLVBRops[0] ), &( lpddnlvcaps->dwNLVBRops[0] ), DD_ROP_SPACE * sizeof( DWORD ) );
}
lpddcaps->ddsCaps.dwCaps = lpddcorecaps->ddsCaps.dwCaps;
memcpy(&lpddcaps->ddsCaps.ddsCapsEx, lpddsExCaps, sizeof(lpddcaps->ddsCaps.ddsCapsEx) );
if (lpddmorecaps != NULL)
{
#ifdef POSTPONED2
lpddcaps->dwAlphaCaps = lpddmorecaps->dwAlphaCaps;
lpddcaps->dwSVBAlphaCaps = lpddmorecaps->dwSVBAlphaCaps;
lpddcaps->dwVSBAlphaCaps = lpddmorecaps->dwVSBAlphaCaps;
lpddcaps->dwSSBAlphaCaps = lpddmorecaps->dwSSBAlphaCaps;
lpddcaps->dwFilterCaps = lpddmorecaps->dwFilterCaps;
lpddcaps->dwSVBFilterCaps = lpddmorecaps->dwSVBFilterCaps;
lpddcaps->dwVSBFilterCaps = lpddmorecaps->dwVSBFilterCaps;
lpddcaps->dwSSBFilterCaps = lpddmorecaps->dwSSBFilterCaps;
lpddcaps->dwTransformCaps = lpddmorecaps->dwTransformCaps;
lpddcaps->dwSVBTransformCaps = lpddmorecaps->dwSVBTransformCaps;
lpddcaps->dwVSBTransformCaps = lpddmorecaps->dwVSBTransformCaps;
lpddcaps->dwSSBTransformCaps = lpddmorecaps->dwSSBTransformCaps;
lpddcaps->dwBltAffineMinifyLimit = lpddmorecaps->dwBltAffineMinifyLimit;
lpddcaps->dwOverlayAffineMinifyLimit = lpddmorecaps->dwOverlayAffineMinifyLimit;
#endif //POSTPONED2
}
lpddcaps->dwSize = sizeof( DDCAPS );
} /* BuildDDCAPS */
#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 dwSize;
DDCAPS ddcaps;
DDSCAPS ddscaps;
ENTER_DDRAW();
DPF(2,A,"ENTERAPI: DD_GetCaps");
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)
{
/*
* We now have to assemble the final, API visible caps from multiple
* sub-components scattered through the driver object. To make the size
* computation simple we just build a full, API sized DDCAPS and then
* just copy the appropritate portion of it. Cheesy in that involves an
* extra copy of the data but very simple. This should not be performance
* critical code to start with.
*/
BuildDDCAPS( &ddcaps, this, FALSE );
dwSize = lpDDDriverCaps->dwSize;
ZeroMemory( lpDDDriverCaps, dwSize);
memcpy( lpDDDriverCaps, &ddcaps, dwSize );
lpDDDriverCaps->dwSize = dwSize;
/*
* Execute buffers are invisible to the user level API
* so mask that caps bit off.
*/
if (dwSize >= sizeof(DDCAPS))
{
/*
* Only mask off the extended caps if they were queried for.
*/
lpDDDriverCaps->ddsCaps.dwCaps &= ~DDSCAPS_EXECUTEBUFFER;
}
lpDDDriverCaps->ddsOldCaps.dwCaps &= ~DDSCAPS_EXECUTEBUFFER;
/*
* get amount of free video memory
* Yes, I know I'm ignoring the return code. This is a conscious choice not to engender any
* regression risks by changing return codes.
*/
ZeroMemory(&ddscaps,sizeof(ddscaps));
ddscaps.dwCaps = DDSCAPS_VIDEOMEMORY;
DD_GetAvailableVidMem( lpDD, &ddscaps, &lpDDDriverCaps->dwVidMemTotal, &lpDDDriverCaps->dwVidMemFree );
}
/*
* fill in hel caps
*/
if( lpDDHELCaps != NULL )
{
/*
* We now have to assemble the final, API visible caps from multiple
* sub-components scattered through the driver object. To make the size
* computation simple we just build a full, API sized DDCAPS and then
* just copy the appropritate portion of it. Cheesy in that involves an
* extra copy of the data but very simple. This should not be performance
* critical code to start with.
*/
BuildDDCAPS( &ddcaps, this, TRUE );
dwSize = lpDDHELCaps->dwSize;
ZeroMemory( lpDDHELCaps, dwSize);
memcpy( lpDDHELCaps, &ddcaps, dwSize );
lpDDHELCaps->dwSize = dwSize;
/*
* Again, execute buffers are invisible to the user level API
* so mask that caps bit off.
*/
if (dwSize >= sizeof(DDCAPS))
{
/*
* Only mask off the extended caps if they were queried for.
*/
lpDDHELCaps->ddsCaps.dwCaps &= ~DDSCAPS_EXECUTEBUFFER;
}
lpDDHELCaps->ddsOldCaps.dwCaps &= ~DDSCAPS_EXECUTEBUFFER;
lpDDHELCaps->dwVidMemFree = 0;
}
LEAVE_DDRAW();
return DD_OK;
} /* DD_GetCaps */
#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();
DPF(2,A,"ENTERAPI: DD_WaitForVerticalBlank");
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;
#ifdef WINNT
// Update DDraw handle in driver GBL object.
this->hDD = this_lcl->hDD;
#endif //WINNT
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 = (ULONG_PTR) 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();
DPF(2,A,"ENTERAPI: DD_GetMonitorFrequency");
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 */
DWORD gdwSetIME = 0;
/*
* DoneExclusiveMode
*/
void DoneExclusiveMode( LPDDRAWI_DIRECTDRAW_LCL pdrv_lcl )
{
LPDDRAWI_DIRECTDRAW_GBL pdrv;
DDHAL_SETEXCLUSIVEMODEDATA semd;
LPDDHAL_SETEXCLUSIVEMODE semfn;
LPDDHAL_SETEXCLUSIVEMODE semhalfn;
HRESULT rc;
DPF( 4, "DoneExclusiveMode" );
pdrv = pdrv_lcl->lpGbl;
if( (pdrv->dwFlags & DDRAWI_FULLSCREEN) &&
(pdrv->dwFlags & DDRAWI_DISPLAYDRV) )
{
DPF( 4, "Enabling error mode, hotkeys" );
SetErrorMode( pdrv_lcl->dwErrorMode );
if( !( pdrv_lcl->dwAppHackFlags & DDRAW_APPCOMPAT_SCREENSAVER ) )
{
BOOL old;
SystemParametersInfo( SPI_SCREENSAVERRUNNING, FALSE, &old, 0 );
}
#ifdef WINNT
// Restore cursor shadow coming out of fullscreen
SystemParametersInfo( SPI_SETCURSORSHADOW, 0, (LPVOID)ULongToPtr(pdrv_lcl->dwCursorShadow), 0 );
#endif
// Restore reactive menus coming out of fullscreen:
SystemParametersInfo( SPI_SETHOTTRACKING, 0, (LPVOID)ULongToPtr(pdrv_lcl->dwHotTracking), 0 );
InterlockedExchange(&gdwSetIME, pdrv_lcl->dwIMEState + 1);
}
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.
#ifdef WIN95
if( pdrv->dwModeIndex != DDUNSUPPORTEDMODE && NULL != pdrv->lpModeInfo)
#else
if (NULL != pdrv->lpModeInfo)
#endif
{
if( pdrv->lpModeInfo[ pdrv->dwModeIndex ].wFlags & DDMODEINFO_PALETTIZED )
{
HDC hdc;
if( pdrv->cMonitors > 1 )
{
SetSystemPaletteUse( (HDC) (pdrv_lcl->hDC), SYSPAL_STATIC);
DPF(4,"SetSystemPaletteUse STATICS ON (DoneExclusiveMode)");
}
else
{
hdc = GetDC(NULL);
SetSystemPaletteUse(hdc, SYSPAL_STATIC);
DPF(4,"SetSystemPaletteUse STATICS ON (DoneExclusiveMode)");
ReleaseDC(NULL, hdc);
}
// if we have a primary
if (pdrv_lcl->lpPrimary)
{
if (pdrv_lcl->lpPrimary->lpLcl->lpDDPalette) //if that primary has a palette
{
pdrv_lcl->lpPrimary->lpLcl->lpDDPalette->lpLcl->lpGbl->dwFlags &= ~DDRAWIPAL_EXCLUSIVE;
DPF(5,"Setting non-exclusive for palette %08x",pdrv_lcl->lpPrimary->lpLcl->lpDDPalette->lpLcl);
}
}
}
#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 );
}
/*
* If the primary has a gamma ramp associated w/ it, set it now
*/
if( ( pdrv_lcl->lpPrimary != NULL ) &&
( pdrv_lcl->lpPrimary->lpLcl->lpSurfMore->lpOriginalGammaRamp != NULL ) )
{
RestoreGamma( pdrv_lcl->lpPrimary->lpLcl, pdrv_lcl );
}
/*
* 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 );
//
// This assert has fired and confused many devs. Seems like the 3dfx and the pvr both
// bounce us a failure code. It's clearly not serving its original purpose of making
// driver devs return an ok code, so let's yank it.
//
//DDASSERT( ( DDHAL_DRIVER_HANDLED == rc ) && ( !FAILED( semd.ddRVal ) ) );
}
pdrv->lpExclusiveOwner = NULL;
/*
* changes to lpExclusiveOwner can only be made while the exclusive mode mutex is owned by this process
*/
RELEASE_EXCLUSIVEMODE_MUTEX;
ClipTheCursor(pdrv_lcl, NULL);
// If we are going into window'ed mode and we are
// emulated then we might need to turn on the VirtualDesktop flag.
// We don't do this for 3Dfx, and we don't do this if the app
// has chosen a monitor explicitly.
if( ( pdrv->cMonitors > 1 ) &&
(pdrv->dwFlags & DDRAWI_DISPLAYDRV) )
{
pdrv->dwFlags |= DDRAWI_VIRTUALDESKTOP;
// We need to update our device rect
UpdateRectFromDevice( pdrv );
}
} /* 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;
DWORD dwWaitResult;
HRESULT rc;
DPF( 4, "StartExclusiveMode" );
pdrv = pdrv_lcl->lpGbl;
#if _WIN32_WINNT >= 0x0501
{
//Turn off ghosting for any exclusive-mode app
//(Whistler onwards only)
typedef void (WINAPI *PFN_NOGHOST)( void );
HINSTANCE hInst = NULL;
hInst = LoadLibrary( "user32.dll" );
if( hInst )
{
PFN_NOGHOST pfnNoGhost = NULL;
pfnNoGhost = (PFN_NOGHOST)GetProcAddress( (HMODULE)hInst, "DisableProcessWindowsGhosting" );
if( pfnNoGhost )
{
pfnNoGhost();
}
FreeLibrary( hInst );
}
}
#endif // _WIN32_WINNT >= 0x0501
/*
* Preceeding code should have taken this mutex already.
*/
#if defined(WINNT) && defined(DEBUG)
dwWaitResult = WaitForSingleObject(hExclusiveModeMutex, 0);
DDASSERT(dwWaitResult == WAIT_OBJECT_0);
ReleaseMutex(hExclusiveModeMutex);
#endif
pdrv->lpExclusiveOwner = pdrv_lcl;
if( (pdrv->dwFlags & DDRAWI_FULLSCREEN) &&
(pdrv->dwFlags & DDRAWI_DISPLAYDRV) )
{
pdrv_lcl->dwErrorMode = SetErrorMode( SEM_NOGPFAULTERRORBOX | SEM_FAILCRITICALERRORS | SEM_NOOPENFILEERRORBOX );
{
BOOL old;
/*
* Don't send kepyboard events while the screen saver is running
* or else USER gets confused
*/
if( !( pdrv_lcl->dwAppHackFlags & DDRAW_APPCOMPAT_SCREENSAVER ) )
{
#ifdef WIN95
// If the user has just switched to us, and then quickly
// switched away from us, we may be in the Alt+Tab switch box.
// If we are, then we need to get out of it or the user will
// be forced to reboot the system. So we check to see if the
// Alt key is down, and if so, force it up. Hacking is fun.
if (GetAsyncKeyState(VK_MENU) & 0x80000000)
{
keybd_event(VK_MENU, 0, KEYEVENTF_KEYUP, 0);
}
#endif
SystemParametersInfo( SPI_SCREENSAVERRUNNING, TRUE, &old, 0 );
}
#ifdef WINNT
// Save current cursor shadow setting
SystemParametersInfo( SPI_GETCURSORSHADOW, 0, (LPVOID) &(pdrv_lcl->dwCursorShadow), 0 );
SystemParametersInfo( SPI_SETCURSORSHADOW, 0, 0, 0 );
#endif
// Save current hot-tracking setting
SystemParametersInfo( SPI_GETHOTTRACKING, 0, (LPVOID) &(pdrv_lcl->dwHotTracking), 0 );
SystemParametersInfo( SPI_GETSHOWIMEUI, 0, (LPVOID) &(pdrv_lcl->dwIMEState), 0 );
//And turn it off as we go into exclusive mode
SystemParametersInfo( SPI_SETHOTTRACKING, 0, 0, 0 );
InterlockedExchange(&gdwSetIME, FALSE + 1);
#ifdef WIN95
if( dwFlags & DDSCL_ALLOWREBOOT )
{
/*
* re-enable reboot after SPI_SCREENSAVERRUNNING, it disables it
*/
DD16_EnableReboot( TRUE );
}
#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, (HANDLE) pdrv_lcl->hDDVxd, TRUE );
/*
* If the primary has a gamma ramp associated w/ it, set it now
*/
if( ( pdrv_lcl->lpPrimary != NULL ) &&
( pdrv_lcl->lpPrimary->lpLcl->lpSurfMore->lpGammaRamp != NULL ) )
{
SetGamma( pdrv_lcl->lpPrimary->lpLcl, pdrv_lcl );
}
/*
* 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 );
//
// This assert has fired and confused many devs. Seems like the 3dfx and the pvr both
// bounce us a failure code. It's clearly not serving its original purpose of making
// driver devs return an ok code, so let's yank it.
//
//DDASSERT( ( DDHAL_DRIVER_HANDLED == rc ) && ( !FAILED( semd.ddRVal ) ) );
}
// If we are going into fullscreen mode
// Then we might need to turn off the VirtualDesktop flag
if( pdrv->cMonitors > 1 )
{
pdrv->dwFlags &= ~DDRAWI_VIRTUALDESKTOP;
// We need to update our device rect
UpdateRectFromDevice( pdrv );
}
} /* 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 pdrv_lcl;
LPDDRAWI_DIRECTDRAW_LCL this_lcl;
LPDDRAWI_DIRECTDRAW_GBL this;
DWORD pid;
HRESULT ddrval;
DWORD style;
HWND old_hwnd;
HWND hTemp;
BOOL excl_exists;
BOOL is_excl;
ENTER_DDRAW();
DPF(2,A,"ENTERAPI: DD_SetCooperativeLevel");
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_FPUSETUP) && (dwFlags & DDSCL_FPUPRESERVE))
{
DPF_ERR( "Only one DDSCL_FPU* flag can be specified" );
LEAVE_DDRAW();
return DDERR_INVALIDPARAMS;
}
/*
* If the device isn't attached to the desktop, we don't want
* to mess w/ it's window because we'll get it wrong.
*/
if( !( this->dwFlags & DDRAWI_ATTACHEDTODESKTOP ) )
{
dwFlags |= DDSCL_NOWINDOWCHANGES;
}
if( !(dwFlags & (DDSCL_EXCLUSIVE|DDSCL_NORMAL) ) &&
!(dwFlags & DDSCL_SETFOCUSWINDOW ) )
{
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_SETFOCUSWINDOW )
{
if( !( dwFlags & DDSCL_CREATEDEVICEWINDOW) &&
( dwFlags & ~(DDSCL_SETFOCUSWINDOW | DDSCL_ALLOWMODEX
| DDSCL_DX8APP | DDSCL_NOWINDOWCHANGES) ) )
{
DPF_ERR( "Flags invalid with DDSCL_SETFOCUSWINDOW" );
LEAVE_DDRAW();
return DDERR_INVALIDPARAMS;
}
if( this_lcl->dwLocalFlags & DDRAWILCL_HASEXCLUSIVEMODE )
{
DPF_ERR( "Cannot reset focus window while exclusive mode is owned" );
LEAVE_DDRAW();
return DDERR_HWNDALREADYSET;
}
}
if( dwFlags & DDSCL_SETDEVICEWINDOW )
{
if( dwFlags & (DDSCL_SETFOCUSWINDOW | DDSCL_CREATEDEVICEWINDOW) )
{
DPF_ERR( "Flags invalid with DDSCL_SETDEVICEWINDOW" );
LEAVE_DDRAW();
return DDERR_INVALIDPARAMS;
}
if( hWnd != NULL )
{
if( this_lcl->hFocusWnd == 0 )
{
DPF_ERR( "Focus window has not been set" );
LEAVE_DDRAW();
return DDERR_NOFOCUSWINDOW;
}
}
}
if( ( dwFlags & DDSCL_CREATEDEVICEWINDOW ) &&
( this_lcl->hWnd != 0 ) &&
!( this_lcl->dwLocalFlags & DDRAWILCL_CREATEDWINDOW ) )
{
DPF_ERR( "HWND already set - DDSCL_CREATEDEVICEWINDOW flag not valid" );
LEAVE_DDRAW();
return DDERR_INVALIDPARAMS;
}
if( ( dwFlags & DDSCL_CREATEDEVICEWINDOW ) &&
!( dwFlags & DDSCL_EXCLUSIVE ) )
{
DPF_ERR( "DDSCL_CREATEDEVICEWINDOW only valid with DDSCL_EXCLUSIVE" );
LEAVE_DDRAW();
return DDERR_INVALIDPARAMS;
}
if( ( dwFlags & DDSCL_CREATEDEVICEWINDOW ) &&
( this_lcl->hWnd == 0 ) )
{
if( !( dwFlags & DDSCL_SETFOCUSWINDOW ) )
{
if( hWnd != NULL )
{
DPF_ERR( "hWnd specified with DDSCL_CREATEDEVICEWINDOW" );
LEAVE_DDRAW();
return DDERR_INVALIDPARAMS;
}
if( this_lcl->hFocusWnd == 0 )
{
DPF_ERR( "Focus window has not been set" );
LEAVE_DDRAW();
return DDERR_NOFOCUSWINDOW;
}
}
}
if( ( dwFlags & DDSCL_EXCLUSIVE ) &&
!( dwFlags & DDSCL_CREATEDEVICEWINDOW ) )
{
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();
}
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 mess with dialogs, this is a hack for DDTEST and DDCAPS.
* Don't do this if the app specified the
* SETDEVICEWINDOW/CREATEDEVICEWINDOW flags.
*/
if( ( NULL != hWnd ) &&
!( dwFlags & (DDSCL_SETDEVICEWINDOW|DDSCL_CREATEDEVICEWINDOW) ) )
{
style = GetWindowLong(hWnd, GWL_STYLE);
if ((style & WS_CAPTION) == WS_DLGFRAME)
{
DPF( 2, "setting DDSCL_NOWINDOWCHANGES for caller" );
dwFlags |= DDSCL_NOWINDOWCHANGES;
}
}
if( dwFlags & DDSCL_EXCLUSIVE )
{
/*
* This is one of exactly two cases where we keep the exclusive mode mutex (the other is
* in dddefwp, wherein we are activated by alt-tab). We have to be careful to release the
* mutex properly in failure modes.
*/
if( !( dwFlags & DDSCL_SETFOCUSWINDOW ) )
{
hTemp = (HWND) this_lcl->hFocusWnd;
}
else
{
hTemp = hWnd;
}
CheckExclusiveMode(this_lcl, &excl_exists, &is_excl, TRUE, hTemp, TRUE );
if( (excl_exists) &&
(!is_excl) )
{
if( ( dwFlags & DDSCL_CREATEDEVICEWINDOW ) &&
( this_lcl->hWnd == 0 ) &&
( hWnd ) )
{
DestroyWindow(hWnd);
}
LEAVE_DDRAW();
return DDERR_EXCLUSIVEMODEALREADYSET;
}
}
/*
* If we are only setting the focus window, save it now
*/
if( dwFlags & DDSCL_SETFOCUSWINDOW )
{
this_lcl->hFocusWnd = (ULONG_PTR) hWnd;
if( ( this_lcl->hWnd != 0 ) &&
( this_lcl->dwLocalFlags & DDRAWILCL_CREATEDWINDOW ) &&
IsWindow( (HWND) this_lcl->hWnd ) )
{
SetWindowLongPtr( (HWND) this_lcl->hWnd, 0, (LONG_PTR) hWnd );
}
if( !( dwFlags & DDSCL_CREATEDEVICEWINDOW ) )
{
if (dwFlags & DDSCL_MULTITHREADED)
this_lcl->dwLocalFlags |= DDRAWILCL_MULTITHREADED;
if (dwFlags & DDSCL_FPUSETUP)
this_lcl->dwLocalFlags |= DDRAWILCL_FPUSETUP;
if (dwFlags & DDSCL_FPUPRESERVE)
this_lcl->dwLocalFlags |= DDRAWILCL_FPUPRESERVE;
/*
* It's ok to always release the mutex here, because the only way we can get here is if we just took
* exclusive mode, i.e. we didn't already have exclusive mode before this SetCoop call was made.
*/
if( dwFlags & DDSCL_EXCLUSIVE )
{
RELEASE_EXCLUSIVEMODE_MUTEX;
}
LEAVE_DDRAW();
return DD_OK;
}
}
/*
* Create the window now if we need to
*/
if( ( dwFlags & DDSCL_CREATEDEVICEWINDOW ) &&
( this_lcl->hWnd == 0 ) )
{
WNDCLASS cls;
if( !GetClassInfo( hModule, szDeviceWndClass, &cls ) )
{
cls.lpszClassName = szDeviceWndClass;
cls.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH);
cls.hInstance = hModule;
cls.hIcon = NULL;
cls.hCursor = NULL;
cls.lpszMenuName = NULL;
cls.style = CS_DBLCLKS;
cls.lpfnWndProc = DeviceWindowProc;
cls.cbWndExtra = sizeof( INT_PTR );
cls.cbClsExtra = 0;
if( RegisterClass(&cls) == 0 )
{
DPF_ERR( "RegisterClass failed" );
RELEASE_EXCLUSIVEMODE_MUTEX;
LEAVE_DDRAW();
return DDERR_GENERIC;
}
}
hWnd = CreateWindow(
szDeviceWndClass,
szDeviceWndClass,
WS_OVERLAPPED|WS_POPUP|WS_VISIBLE,
this->rectDevice.left,
this->rectDevice.top,
this->rectDevice.right - this->rectDevice.left,
this->rectDevice.bottom - this->rectDevice.top,
(HWND)this_lcl->hFocusWnd, NULL,
hModule,
(LPVOID) (this_lcl->hFocusWnd) );
if( hWnd == NULL )
{
DPF_ERR( "Unable to create the device window" );
RELEASE_EXCLUSIVEMODE_MUTEX;
LEAVE_DDRAW();
return DDERR_INVALIDPARAMS;
}
}
// Destroy the old window if we created it ourselves
if( ( hWnd != (HWND) this_lcl->hWnd ) &&
IsWindow( (HWND) this_lcl->hWnd ) &&
( this_lcl->dwLocalFlags & DDRAWILCL_CREATEDWINDOW ) )
{
DestroyWindow( (HWND) this_lcl->hWnd );
this_lcl->hWnd = 0;
this_lcl->dwLocalFlags &= ~DDRAWILCL_CREATEDWINDOW;
}
// Save the hwnd in the local object for later reference
old_hwnd = (HWND)this_lcl->hWnd;
if( dwFlags & (DDSCL_SETDEVICEWINDOW | DDSCL_CREATEDEVICEWINDOW) )
{
(HWND) this_lcl->hWnd = hWnd;
if( dwFlags & DDSCL_CREATEDEVICEWINDOW )
{
this_lcl->dwLocalFlags |= DDRAWILCL_CREATEDWINDOW;
}
}
else
{
(HWND) this_lcl->hWnd = hWnd;
(HWND) this_lcl->hFocusWnd = hWnd;
}
/*
* allow modex modes?
*/
if( (dwFlags & DDSCL_ALLOWMODEX) &&
!( this->dwFlags & DDRAWI_MODEXILLEGAL ) )
{
DPF( 2, "*********** ALLOWING MODE X AND VGA MODES" );
this_lcl->dwLocalFlags |= DDRAWILCL_ALLOWMODEX;
}
else
{
DPF( 2, "*********** NOT!! ALLOWING MODE X AND VGA 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!" );
//We don't release the exclusive mode mutex here, because we are already committed to owning
//it by the lines just above.
LEAVE_DDRAW();
return ddrval;
}
this_lcl->dwLocalFlags |= DDRAWILCL_HOOKEDHWND;
}
if( !is_excl )
{
StartExclusiveMode( this_lcl, dwFlags, pid );
this_lcl->dwLocalFlags |= DDRAWILCL_ACTIVEYES;
this_lcl->dwLocalFlags &=~DDRAWILCL_ACTIVENO;
if( hWnd != NULL )
{
extern void InternalSetForegroundWindow(HWND hWnd);
InternalSetForegroundWindow(hWnd);
}
this_lcl->dwLocalFlags |= DDRAWILCL_HASEXCLUSIVEMODE;
ClipTheCursor(this_lcl, &(this->rectDevice));
}
}
/*
* 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!" );
//No need to release excl mutex here, since DoneExclusiveMode does it.
LEAVE_DDRAW();
HIDESHOW_IME(); //Show/hide the IME OUTSIDE of the ddraw critsect.
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);
}
}
// If we are going into window'ed mode and we are
// emulated then we might need to turn on the VirtualDesktop flag.
// We don't do this for 3Dfx, and we don't do this if the app
// has chosen a monitor explicitly.
if( ( this->cMonitors > 1 ) &&
(this->dwFlags & DDRAWI_DISPLAYDRV) )
{
this->dwFlags |= DDRAWI_VIRTUALDESKTOP;
// We need to update our device rect
UpdateRectFromDevice( this );
}
}
// Allow other DD objects to be created now.
this_lcl->dwLocalFlags |= DDRAWILCL_SETCOOPCALLED;
if (dwFlags & DDSCL_MULTITHREADED)
this_lcl->dwLocalFlags |= DDRAWILCL_MULTITHREADED;
if (dwFlags & DDSCL_FPUSETUP)
this_lcl->dwLocalFlags |= DDRAWILCL_FPUSETUP;
if (dwFlags & DDSCL_FPUPRESERVE)
this_lcl->dwLocalFlags |= DDRAWILCL_FPUPRESERVE;
LEAVE_DDRAW();
HIDESHOW_IME(); //Show/hide the IME OUTSIDE of the ddraw critsect.
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();
DPF(2,A,"ENTERAPI: DD_DuplicateSurface");
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();
DPF(2,A,"ENTERAPI: DD_GetGDISurface");
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 != NULL && next_int != psurf_int )
{
next_lcl = next_int->lpLcl;
next = next_lcl->lpGbl;
do
{
if( next->dwGlobalFlags & DDRAWISURFGBL_ISGDISURFACE ) //next->fpVidMem == this->fpPrimaryOrig )
{
/*
* DirectDraw's COM behavior has changed with IDD4:
* IDD4 returns IDDSurface4 and IDD5 returns IDDSurface7.
* Create the new surface interface object only if we need to.
*/
if ( !LOWERTHANDDRAW4(this_int) )
{
// This is IDD4 or above. Assume IDD4 initially:
LPVOID pddSurfCB = &ddSurface4Callbacks;
if (this_int->lpVtbl == &dd7Callbacks)
{
// This is IDD7, so we must return IDDSurface7.
pddSurfCB = &ddSurface7Callbacks;
}
if (next_int->lpVtbl != pddSurfCB)
{
// Need to make IDDSurface? level match IDD? level.
next_int = NewSurfaceInterface( next_lcl, pddSurfCB );
}
}
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
{
/*
* DirectDraw's COM behavior has changed with IDD4:
* IDD4 returns IDDSurface4 and IDD7 returns IDDSurface7.
* Create the new surface interface object only if we need to.
*/
if ( !LOWERTHANDDRAW4(this_int) )
{
// This is IDD4 or above. Assume IDD4 initially:
LPVOID pddSurfCB = &ddSurface4Callbacks;
if (this_int->lpVtbl == &dd7Callbacks)
{
// This is IDD7, so we must return IDDSurface7.
pddSurfCB = &ddSurface7Callbacks;
}
if (psurf_int->lpVtbl != pddSurfCB)
{
// Need to make IDDSurface? level match IDD? level.
psurf_int = NewSurfaceInterface( psurf_lcl, pddSurfCB );
}
}
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;
}
}
}
/*
* We used to only call this function if the flip was actaully needed,
* but 3DFX requested that we always call them, so now this fucntion
* is always called. If we make it this far, it's not a 3DFX and we don't
* need to do anything more if the GDI surface is already visible.
*/
if( psurf_lcl->lpGbl->dwGlobalFlags & DDRAWISURFGBL_ISGDISURFACE)
{
return DD_OK;
}
/*
* 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( 5, "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();
DPF(2,A,"ENTERAPI: DD_FlipToGDISurface");
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(2, "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;
}
/*
* Always call FlipToGDISurface because it benefits 3DFX
*/
// fpprim = this->fpPrimaryOrig;
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();
DPF(2,A,"ENTERAPI: DD_GetFourCCCodes");
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();
DPF(2,A,"ENTERAPI: DD_Compact");
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;
DDSCAPS2 ddscaps2 = {0,0,0,0};
HRESULT hr=DD_OK;
ENTER_DDRAW();
DPF(2,A,"ENTERAPI: DD_GetAvailableVidMem");
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;
}
ddscaps2.dwCaps = lpDDSCaps->dwCaps;
}
EXCEPT( EXCEPTION_EXECUTE_HANDLER )
{
DPF_ERR( "Invalid DDSCAPS pointer" );
LEAVE_DDRAW();
return DDERR_INVALIDPARAMS;
}
hr = DD_GetAvailableVidMem4(lpDD, & ddscaps2, lpdwTotal, lpdwFree);
LEAVE_DDRAW();
return hr;
}
HRESULT DDAPI DD_GetAvailableVidMem4( LPDIRECTDRAW lpDD, LPDDSCAPS2 lpDDSCaps, LPDWORD lpdwTotal, LPDWORD lpdwFree )
{
LPDDRAWI_DIRECTDRAW_INT this_int;
LPDDRAWI_DIRECTDRAW_LCL this_lcl;
LPDDRAWI_DIRECTDRAW_GBL this;
DWORD dwLocalFree;
DWORD dwNonLocalFree;
DWORD dwLocalTotal;
DWORD dwNonLocalTotal;
#ifndef WINNT
LPVIDMEM pvm;
int i;
#endif
LPDDHAL_GETAVAILDRIVERMEMORY gadmfn;
ENTER_DDRAW();
DPF(2,A,"ENTERAPI: DD_GetAvailableVidMem4");
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;
#ifdef WINNT
// Update DDraw handle in driver GBL object.
this->hDD = this_lcl->hDD;
#endif //WINNT
/*
* 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_DDSCAPS2_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;
}
if( lpDDSCaps->dwCaps2 & ~DDSCAPS2_VALID )
{
DPF_ERR( "Invalid surface caps2 specified" );
LEAVE_DDRAW();
return DDERR_INVALIDCAPS;
}
if( lpDDSCaps->dwCaps3 & ~DDSCAPS3_VALID )
{
DPF_ERR( "Invalid surface caps3 specified" );
LEAVE_DDRAW();
return DDERR_INVALIDCAPS;
}
if( lpDDSCaps->dwCaps4 & ~DDSCAPS4_VALID )
{
DPF_ERR( "Invalid surface caps4 specified" );
LEAVE_DDRAW();
return DDERR_INVALIDCAPS;
}
/*
* !!! NOTE: Consider using the capability checking code
* of CreateSurface here to ensure no strange 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.
*/
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;
}
// Initialize values
dwLocalFree = 0UL;
dwNonLocalFree = 0UL;
dwLocalTotal = 0UL;
dwNonLocalTotal = 0UL;
if( lpdwTotal != NULL )
{
*lpdwTotal = 0UL;
}
if( lpdwFree != NULL )
{
*lpdwFree = 0UL;
}
DPF(5,"GetAvailableVidmem called for:");
DPF_STRUCT(5,V,DDSCAPS2,lpDDSCaps);
#ifndef WINNT
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.
* We need to keep a separate count of what's in nonlocal,
* since we may need to cap that amount to respect the commit policy.
*/
if( (lpDDSCaps->dwCaps & pvm->ddsCapsAlt.dwCaps) == 0 )
{
if ( pvm->dwFlags & VIDMEM_ISNONLOCAL )
{
DPF(5,V,"Heap number %d adds %08x (%d) free bytes of nonlocal",i,VidMemAmountFree( pvm->lpHeap ),VidMemAmountFree( pvm->lpHeap ));
DPF(5,V,"Heap number %d adds %08x (%d) allocated bytes of nonlocal",i,VidMemAmountAllocated( pvm->lpHeap ),VidMemAmountAllocated( pvm->lpHeap ));
dwNonLocalFree += VidMemAmountFree( pvm->lpHeap );
dwNonLocalTotal += VidMemAmountAllocated( pvm->lpHeap );
}
else
{
DPF(5,V,"Heap number %d adds %08x free bytes of local",i,VidMemAmountFree( pvm->lpHeap ));
DPF(5,V,"Heap number %d adds %08x (%d) allocated bytes of local",i,VidMemAmountAllocated( pvm->lpHeap ),VidMemAmountAllocated( pvm->lpHeap ));
dwLocalFree += VidMemAmountFree( pvm->lpHeap );
dwLocalTotal += VidMemAmountAllocated( pvm->lpHeap );
}
}
}
dwLocalTotal += dwLocalFree;
dwNonLocalTotal += dwNonLocalFree;
#endif //not WINNT
// Try asking the driver
gadmfn = this_lcl->lpDDCB->HALDDMiscellaneous.GetAvailDriverMemory;
/*
* Only ask the driver about nonlocal vidmem if it understands the concept.
*/
if( (gadmfn != NULL) &&
(((lpDDSCaps->dwCaps & DDSCAPS_NONLOCALVIDMEM) == 0) || (this->ddCaps.dwCaps2 & DDCAPS2_NONLOCALVIDMEM))
)
{
DDHAL_GETAVAILDRIVERMEMORYDATA gadmd;
DWORD rc;
DDASSERT( VALIDEX_CODE_PTR( gadmfn ) );
gadmd.lpDD = this;
gadmd.DDSCaps.dwCaps = lpDDSCaps->dwCaps;
gadmd.ddsCapsEx = lpDDSCaps->ddsCapsEx;
DOHALCALL( GetAvailDriverMemory, gadmfn, gadmd, rc, FALSE );
if( rc == DDHAL_DRIVER_HANDLED )
{
if( lpDDSCaps->dwCaps & DDSCAPS_NONLOCALVIDMEM )
{
DPF(5,V,"Driver adds %08x private free nonlocal bytes",gadmd.dwFree);
DPF(5,V,"Driver adds %08x private total nonlocal bytes",gadmd.dwTotal);
dwNonLocalFree += gadmd.dwFree;
dwNonLocalTotal += gadmd.dwTotal;
}
else
{
DPF(5,V,"Driver adds %08x (%d) private free local bytes",gadmd.dwFree,gadmd.dwFree);
DPF(5,V,"Driver adds %08x (%d) private total local bytes",gadmd.dwTotal,gadmd.dwTotal);
dwLocalFree += gadmd.dwFree;
dwLocalTotal += gadmd.dwTotal;
}
}
else
{
DPF_ERR( "GetAvailDriverMemory failed!" );
}
}
if( lpdwFree != NULL )
{
*lpdwFree = dwLocalFree;
if (lpDDSCaps->dwCaps & DDSCAPS_NONLOCALVIDMEM)
{
//report nonlocal if it was asked for
*lpdwFree += dwNonLocalFree;
}
else if ( ((this->ddCaps.dwCaps2 & DDCAPS2_NONLOCALVIDMEMCAPS) == 0) ||
((this_lcl->lpGbl->lpD3DGlobalDriverData) &&
(this_lcl->lpGbl->lpD3DGlobalDriverData->hwCaps.dwDevCaps & D3DDEVCAPS_TEXTURENONLOCALVIDMEM ) &&
(lpDDSCaps->dwCaps & DDSCAPS_TEXTURE) )
)
{
//If nonlocal wasn't asked for, then report it only if it's either execute model, or the app is asking
//for textures, and the part can texture nonlocal
*lpdwFree += dwNonLocalFree;
}
}
if( lpdwTotal != NULL )
{
*lpdwTotal = dwLocalTotal;
if (lpDDSCaps->dwCaps & DDSCAPS_NONLOCALVIDMEM)
{
//report nonlocal if it was asked for
*lpdwTotal += dwNonLocalTotal;
}
else if ( ((this->ddCaps.dwCaps2 & DDCAPS2_NONLOCALVIDMEMCAPS) == 0) ||
((this_lcl->lpGbl->lpD3DGlobalDriverData) &&
(this_lcl->lpGbl->lpD3DGlobalDriverData->hwCaps.dwDevCaps & D3DDEVCAPS_TEXTURENONLOCALVIDMEM ) &&
(lpDDSCaps->dwCaps & DDSCAPS_TEXTURE) )
)
{
//If nonlocal wasn't asked for, then report it only if it's either execute model, or the app is asking
//for textures, and the part can texture nonlocal
*lpdwTotal += dwNonLocalTotal;
}
}
LEAVE_DDRAW();
return DD_OK;
} /* DD_GetAvailableVidMem */
#undef DPF_MODNAME
#define DPF_MODNAME "DD_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;
IUnknown *lpOldIUnknown=NULL;
BOOL bDX7=FALSE;
ENTER_DDRAW();
DPF(2,A,"ENTERAPI: DD_Initialize");
/* DPF_ENTERAPI(lpDD); */
DPF( 5, "****** 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;
}
else if( this_int->lpVtbl == &dd4UninitCallbacks )
{
lpOldCallbacks = this_int->lpVtbl;
this_int->lpVtbl = &dd4Callbacks;
}
else if( this_int->lpVtbl == &dd7UninitCallbacks )
{
lpOldCallbacks = this_int->lpVtbl;
this_int->lpVtbl = &dd7Callbacks;
bDX7=TRUE;
}
/*
* Note that a call to Initialize off of the uninitnondelegatingiunknown vtbl
* is not possible, since the Initialize method doesn't exist in that interface
*/
#ifdef POSTPONED
/*
* Also need to fix up the owning unknown to point to the initialized non delegating unknown
* This is the non-aggregated case. In the aggregated case, the owning IUnknown will
* not have our vtable, and we also don't need to mess with it.
*/
lpOldIUnknown = this_int->lpLcl->pUnkOuter;
if (this_int->lpLcl->pUnkOuter == (IUnknown*) &UninitNonDelegatingIUnknownInterface )
{
this_int->lpLcl->pUnkOuter = (IUnknown*) &NonDelegatingIUnknownInterface;
}
#endif
hr = InternalDirectDrawCreate( (GUID *)lpGUID, &tmplpdd, this_int, bDX7 ? DDRAWILCL_DIRECTDRAW7 : 0UL, NULL );
if( FAILED( hr ) && ( lpOldCallbacks != NULL ) )
{
/*
* As initialization has failed put the vtable and the owner back the way it was
* before.
*/
this_int->lpVtbl = lpOldCallbacks;
#ifdef POSTPONED
this_int->lpLcl->pUnkOuter = lpOldIUnknown;
#endif
}
LEAVE_DDRAW();
return hr;
} /* DD_Initialize */
#ifdef WINNT
BOOL IsWinlogonThread (void)
{
BOOL fResult = FALSE;
DWORD dwLengthNeeded;
TCHAR szThreadDesktopName[256];
if (GetUserObjectInformation(GetThreadDesktop(GetCurrentThreadId()),
UOI_NAME,
szThreadDesktopName,
sizeof(szThreadDesktopName),
&dwLengthNeeded))
{
fResult = (BOOL)(lstrcmpi(szThreadDesktopName, TEXT("winlogon")) == 0);
if (fResult)
DPF(0,"Is winlogon thread");
}
return fResult;
}
#endif
BOOL DesktopIsVisible()
{
#ifdef WINNT
BOOL retval=FALSE;
HDC hdc = GetDC(NULL);
if (hdc)
{
HRGN hrgn = CreateRectRgn(0, 0, 0, 0);
if (hrgn)
{
if (GetRandomRgn(hdc, hrgn, SYSRGN) == 1)
{
RECT rect;
retval = (BOOL) (GetRgnBox(hrgn, &rect) != NULLREGION);
if (!retval)
{
if (IsWinlogonThread())
{
//We must be on winlogon's process... so desktop IS visible...
retval = TRUE;
}
}
}
DeleteObject(hrgn);
}
ReleaseDC(NULL, hdc);
}
return retval;
#else
return TRUE;
#endif
}
HRESULT DDAPI DD_TestCooperativeLevel(LPDIRECTDRAW lpDD)
{
LPDDRAWI_DIRECTDRAW_INT this_int;
LPDDRAWI_DIRECTDRAW_LCL this_lcl;
LPDDRAWI_DIRECTDRAW_GBL this;
HRESULT hr;
BOOL has_excl;
BOOL excl_exists;
ENTER_DDRAW();
DPF(2,A,"ENTERAPI: DD_TestCooperativeLevel");
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 we're in a fullscreen DOS box, we need to let them know that
* they don't have it and that they can't get it.
*/
if( *(this->lpwPDeviceFlags) & BUSY )
{
if ( this_lcl->dwLocalFlags & DDRAWILCL_HASEXCLUSIVEMODE )
{
hr = DDERR_NOEXCLUSIVEMODE;
}
else
{
hr = DDERR_EXCLUSIVEMODEALREADYSET;
}
LEAVE_DDRAW();
return hr;
}
}
EXCEPT( EXCEPTION_EXECUTE_HANDLER )
{
DPF_ERR( "Exception encountered validating parameters" );
LEAVE_DDRAW();
return DDERR_INVALIDPARAMS;
}
CheckExclusiveMode(this_lcl, &excl_exists, &has_excl, FALSE, NULL, FALSE);
if ( this_lcl->dwLocalFlags & DDRAWILCL_HASEXCLUSIVEMODE )
{
/*
* Either the app has exclusive mode or it does not
*/
if ( has_excl && DesktopIsVisible() )
{
hr = DD_OK;
}
else
{
hr = DDERR_NOEXCLUSIVEMODE;
}
}
else
{
if ( excl_exists || !DesktopIsVisible() )
{
hr = DDERR_EXCLUSIVEMODEALREADYSET;
}
else
{
#ifdef WIN95
if ( this->dwModeIndex == this_lcl->dwPreferredMode )
#else
if (EQUAL_DISPLAYMODE(this->dmiCurrent, this_lcl->dmiPreferred))
#endif
{
hr = DD_OK;
}
else
{
hr = DDERR_WRONGMODE;
}
}
}
LEAVE_DDRAW();
return hr;
} /* DD_TestCooperativeLevel */
#ifdef DEBUG
/*
* These are the DPF structure dumpers.
* If you want to dump a structure, add a function with the prototype
* void DUMP_<structure-name> (DWORD level, DWORD topic, LP<structure-name> lpStruct);
*
*/
/*
* Dump a DDPIXELFORMAT
*/
void DUMP_DDPIXELFORMAT (DWORD level, DWORD topic, LPDDPIXELFORMAT lpDDPF)
{
if (!lpDDPF)
{
DPF(level,topic," DDPIXELFORMAT NULL");
return;
}
DPF(level,topic,"Flags:");
if (lpDDPF->dwFlags & DDPF_ALPHAPIXELS )
DPF(level,topic," DDPF_ALPHAPIXELS");
if (lpDDPF->dwFlags & DDPF_ALPHA )
DPF(level,topic," DDPF_ALPHA ");
if (lpDDPF->dwFlags & DDPF_FOURCC )
DPF(level,topic," DDPF_FOURCC = %08x",lpDDPF->dwFourCC);
if (lpDDPF->dwFlags & DDPF_PALETTEINDEXED4 )
DPF(level,topic," DDPF_PALETTEINDEXED4 ");
if (lpDDPF->dwFlags & DDPF_PALETTEINDEXEDTO8)
DPF(level,topic," DDPF_PALETTEINDEXEDTO8");
if (lpDDPF->dwFlags & DDPF_PALETTEINDEXED8 )
DPF(level,topic," DDPF_PALETTEINDEXED8 ");
if (lpDDPF->dwFlags & DDPF_RGB )
DPF(level,topic," DDPF_RGB ");
if (lpDDPF->dwFlags & DDPF_COMPRESSED )
DPF(level,topic," DDPF_COMPRESSED ");
if (lpDDPF->dwFlags & DDPF_RGBTOYUV )
DPF(level,topic," DDPF_RGBTOYUV ");
if (lpDDPF->dwFlags & DDPF_YUV )
DPF(level,topic," DDPF_YUV ");
if (lpDDPF->dwFlags & DDPF_ZBUFFER )
DPF(level,topic," DDPF_ZBUFFER ");
if (lpDDPF->dwFlags & DDPF_PALETTEINDEXED1 )
DPF(level,topic," DDPF_PALETTEINDEXED1 ");
if (lpDDPF->dwFlags & DDPF_PALETTEINDEXED2 )
DPF(level,topic," DDPF_PALETTEINDEXED2 ");
if (lpDDPF->dwFlags & DDPF_ZPIXELS )
DPF(level,topic," DDPF_ZPIXELS ");
if (lpDDPF->dwFlags & DDPF_STENCILBUFFER )
DPF(level,topic," DDPF_STENCILBUFFER ");
DPF(level,topic," BitCount:%d",lpDDPF->dwRGBBitCount);
DPF(level,topic," Bitmasks: R/Y/StencDepth:%08x, G/U/ZMask:%08x, B/V/StencMask:%08x, Alpha/Z:%08x",
lpDDPF->dwRBitMask,
lpDDPF->dwGBitMask,
lpDDPF->dwBBitMask,
lpDDPF->dwRGBAlphaBitMask);
}
/*
* Dump a ddscaps
*/
void DUMP_DDSCAPS (DWORD level, DWORD topic, LPDDSCAPS lpDDSC)
{
if (!lpDDSC)
{
DPF(level,topic," DDSCAPS NULL");
return;
}
if (lpDDSC->dwCaps & DDSCAPS_ALPHA)
DPF(level,topic," DDSCAPS_ALPHA");
if (lpDDSC->dwCaps & DDSCAPS_BACKBUFFER)
DPF(level,topic," DDSCAPS_BACKBUFFER");
if (lpDDSC->dwCaps & DDSCAPS_COMPLEX)
DPF(level,topic," DDSCAPS_COMPLEX");
if (lpDDSC->dwCaps & DDSCAPS_FLIP)
DPF(level,topic," DDSCAPS_FLIP");
if (lpDDSC->dwCaps & DDSCAPS_FRONTBUFFER)
DPF(level,topic," DDSCAPS_FRONTBUFFER");
if (lpDDSC->dwCaps & DDSCAPS_OFFSCREENPLAIN)
DPF(level,topic," DDSCAPS_OFFSCREENPLAIN");
if (lpDDSC->dwCaps & DDSCAPS_OVERLAY)
DPF(level,topic," DDSCAPS_OVERLAY");
if (lpDDSC->dwCaps & DDSCAPS_PALETTE)
DPF(level,topic," DDSCAPS_PALETTE");
if (lpDDSC->dwCaps & DDSCAPS_PRIMARYSURFACE)
DPF(level,topic," DDSCAPS_PRIMARYSURFACE");
if (lpDDSC->dwCaps & DDSCAPS_PRIMARYSURFACELEFT)
DPF(level,topic," DDSCAPS_PRIMARYSURFACELEFT");
if (lpDDSC->dwCaps & DDSCAPS_SYSTEMMEMORY)
DPF(level,topic," DDSCAPS_SYSTEMMEMORY");
if (lpDDSC->dwCaps & DDSCAPS_TEXTURE)
DPF(level,topic," DDSCAPS_TEXTURE");
if (lpDDSC->dwCaps & DDSCAPS_3DDEVICE)
DPF(level,topic," DDSCAPS_3DDEVICE");
if (lpDDSC->dwCaps & DDSCAPS_VIDEOMEMORY)
DPF(level,topic," DDSCAPS_VIDEOMEMORY");
if (lpDDSC->dwCaps & DDSCAPS_VISIBLE)
DPF(level,topic," DDSCAPS_VISIBLE");
if (lpDDSC->dwCaps & DDSCAPS_WRITEONLY)
DPF(level,topic," DDSCAPS_WRITEONLY");
if (lpDDSC->dwCaps & DDSCAPS_ZBUFFER)
DPF(level,topic," DDSCAPS_ZBUFFER");
if (lpDDSC->dwCaps & DDSCAPS_OWNDC)
DPF(level,topic," DDSCAPS_OWNDC");
if (lpDDSC->dwCaps & DDSCAPS_LIVEVIDEO)
DPF(level,topic," DDSCAPS_LIVEVIDEO");
if (lpDDSC->dwCaps & DDSCAPS_HWCODEC)
DPF(level,topic," DDSCAPS_HWCODEC");
if (lpDDSC->dwCaps & DDSCAPS_MODEX)
DPF(level,topic," DDSCAPS_MODEX");
if (lpDDSC->dwCaps & DDSCAPS_MIPMAP)
DPF(level,topic," DDSCAPS_MIPMAP");
#ifdef SHAREDZ
if (lpDDSC->dwCaps & DDSCAPS_SHAREDZBUFFER)
DPF(level,topic," DDSCAPS_SHAREDZBUFFER");
if (lpDDSC->dwCaps & DDSCAPS_SHAREDBACKBUFFER)
DPF(level,topic," DDSCAPS_SHAREDBACKBUFFER");
#endif
if (lpDDSC->dwCaps & DDSCAPS_ALLOCONLOAD)
DPF(level,topic," DDSCAPS_ALLOCONLOAD");
if (lpDDSC->dwCaps & DDSCAPS_VIDEOPORT)
DPF(level,topic," DDSCAPS_VIDEOPORT");
if (lpDDSC->dwCaps & DDSCAPS_LOCALVIDMEM)
DPF(level,topic," DDSCAPS_LOCALVIDMEM");
if (lpDDSC->dwCaps & DDSCAPS_NONLOCALVIDMEM)
DPF(level,topic," DDSCAPS_NONLOCALVIDMEM");
if (lpDDSC->dwCaps & DDSCAPS_STANDARDVGAMODE)
DPF(level,topic," DDSCAPS_STANDARDVGAMODE");
if (lpDDSC->dwCaps & DDSCAPS_OPTIMIZED)
DPF(level,topic," DDSCAPS_OPTIMIZED");
}
/*
* Dump a DDSCAPS2
*/
void DUMP_DDSCAPS2 (DWORD level, DWORD topic, LPDDSCAPS2 lpDDSC)
{
DUMP_DDSCAPS(level,topic,(LPDDSCAPS)lpDDSC);
//no more to dump yet
}
/*
* Dump a DDSURFACEDESC
*/
void DUMP_DDSURFACEDESC (DWORD level, DWORD topic, LPDDSURFACEDESC lpDDSD)
{
if (!lpDDSD)
{
DPF(level,topic," DDSURFACEDESC NULL");
return;
}
if (lpDDSD->dwFlags & DDSD_HEIGHT)
DPF(level,topic," DDSURFACEDESC->dwHeight = %d",lpDDSD->dwHeight);
if (lpDDSD->dwFlags & DDSD_WIDTH)
DPF(level,topic," DDSURFACEDESC->dwWidth = %d",lpDDSD->dwWidth);
if (lpDDSD->dwFlags & DDSD_PITCH)
DPF(level,topic," DDSURFACEDESC->lPitch = %d",lpDDSD->lPitch);
if (lpDDSD->dwFlags & DDSD_BACKBUFFERCOUNT)
DPF(level,topic," DDSURFACEDESC->dwBackBufferCount = %d",lpDDSD->dwBackBufferCount);
if (lpDDSD->dwFlags & DDSD_ZBUFFERBITDEPTH)
DPF(level,topic," DDSURFACEDESC->dwZBufferBitDepth = %d",lpDDSD->dwZBufferBitDepth);
if (lpDDSD->dwFlags & DDSD_MIPMAPCOUNT)
DPF(level,topic," DDSURFACEDESC->dwMipMapCount = %d",lpDDSD->dwMipMapCount);
if (lpDDSD->dwFlags & DDSD_REFRESHRATE)
DPF(level,topic," DDSURFACEDESC->dwRefreshRate = %d",lpDDSD->dwRefreshRate);
/*if (lpDDSD->dwFlags & DDSD_LPSURFACE)*/
DPF(level,topic," DDSURFACEDESC->lpSurface = %08x",lpDDSD->lpSurface);
if (lpDDSD->dwFlags & DDSD_PIXELFORMAT)
DUMP_DDPIXELFORMAT(level,topic, &lpDDSD->ddpfPixelFormat);
if (lpDDSD->dwFlags & DDSD_CAPS)
DUMP_DDSCAPS(level,topic, &lpDDSD->ddsCaps);
}
/*
* Dump a DDSURFACEDESC2
*/
void DUMP_DDSURFACEDESC2 (DWORD level, DWORD topic, LPDDSURFACEDESC2 lpDDSD)
{
if (!lpDDSD)
{
DPF(level,topic," DDSURFACEDESC2 NULL");
return;
}
if (lpDDSD->dwFlags & DDSD_HEIGHT)
DPF(level,topic," DDSURFACEDESC2->dwHeight = %d",lpDDSD->dwHeight);
if (lpDDSD->dwFlags & DDSD_WIDTH)
DPF(level,topic," DDSURFACEDESC2->dwWidth = %d",lpDDSD->dwWidth);
if (lpDDSD->dwFlags & DDSD_PITCH)
DPF(level,topic," DDSURFACEDESC2->lPitch = %d",lpDDSD->lPitch);
if (lpDDSD->dwFlags & DDSD_BACKBUFFERCOUNT)
DPF(level,topic," DDSURFACEDESC2->dwBackBufferCount = %d",lpDDSD->dwBackBufferCount);
if (lpDDSD->dwFlags & DDSD_MIPMAPCOUNT)
DPF(level,topic," DDSURFACEDESC2->dwMipMapCount = %d",lpDDSD->dwMipMapCount);
if (lpDDSD->dwFlags & DDSD_REFRESHRATE)
DPF(level,topic," DDSURFACEDESC2->dwRefreshRate = %d",lpDDSD->dwRefreshRate);
/*if (lpDDSD->dwFlags & DDSD_LPSURFACE)*/
DPF(level,topic," DDSURFACEDESC2->lpSurface = %08x",lpDDSD->lpSurface);
if (lpDDSD->dwFlags & DDSD_PIXELFORMAT)
DUMP_DDPIXELFORMAT(level,topic, &lpDDSD->ddpfPixelFormat);
if (lpDDSD->dwFlags & DDSD_CAPS)
DUMP_DDSCAPS2(level,topic, &lpDDSD->ddsCaps);
}
/*
* Dump a DDOPTSURFACEDESC
*/
void DUMP_DDOPTSURFACEDESC (DWORD level, DWORD topic, LPDDOPTSURFACEDESC lpDDSD)
{
if (!lpDDSD)
{
DPF(level,topic," DDOPTSURFACEDESC NULL");
return;
}
#if 0
if (lpDDSD->dwFlags & DDOSD_GUID)
DPF(level,topic," DDOPTSURFACEDESC->guid = %08x, %08x, %08x, %08x",lpDDSD->dwHeight);
#endif
if (lpDDSD->dwFlags & DDOSD_COMPRESSION_RATIO)
DPF(level,topic," DDOPTSURFACEDESC->dwCompressionRatio = %d",lpDDSD->dwCompressionRatio);
}
#endif //def DEBUG
/*
* GetInternalPointer
* This function can be called with a ULONG_PTR ordinal value, and will return
* a ULONG_PTR value.
*/
ULONG_PTR __stdcall GetOLEThunkData(ULONG_PTR dwOrdinal)
{
extern DWORD dwLastFrameRate;
switch(dwOrdinal)
{
case 0x1:
return dwLastFrameRate;
case 0x2:
return (ULONG_PTR) lpDriverObjectList;
case 0x3:
return (ULONG_PTR) lpAttachedProcesses;
case 0x4:
return 0;
case 0x5:
return (ULONG_PTR) CheckExclusiveMode;
case 6:
RELEASE_EXCLUSIVEMODE_MUTEX;
return 0;
}
return 0;
}
/*
* Check if exclusive mode is owned, and if so if it is owned by this ddraw local.
* This routine only works if the calling thread owns the ddraw critical section (which is assumed
* to at least own ddraw for all threads in this process.)
*
* We are only allowed to test for this ddraw object owning exclusive mode if this process
* owns the exclusive mode mutex. If it does, then the ddraw csect allows us to know that
* this thread can check the lpExclusiveOwner in the ddraw gbl thread-safely.
*
* The routine can optionally hold the exclusive mode mutex. This is done when the caller wishes to
* change the state of the ddraw gbl lpExclusiveOwner.
*
* Note that this routine will ONLY take the mutex if it's possible that this local can own exclusive mode.
* This means that callers only need to worry about releasing the mutex if
*/
void CheckExclusiveMode(LPDDRAWI_DIRECTDRAW_LCL this_lcl, LPBOOL pbExclusiveExists, LPBOOL pbThisLclOwnsExclusive, BOOL bKeepMutex, HWND hwnd, BOOL bCanGetIt)
{
LPDDRAWI_DIRECTDRAW_GBL this_gbl;
DWORD dwWaitResult;
this_gbl = this_lcl->lpGbl;
#ifdef WINNT
WaitForSingleObject( hCheckExclusiveModeMutex, INFINITE );
dwWaitResult = WaitForSingleObject(hExclusiveModeMutex, 0);
if (dwWaitResult == WAIT_OBJECT_0)
{
#endif
/*
* OK, so this process owns the exlusive mode object,
* are we the process (really the ddraw lcl) with exclusive mode?
*/
if (pbExclusiveExists)
*pbExclusiveExists = (BOOL)( NULL != this_gbl->lpExclusiveOwner );
if (pbThisLclOwnsExclusive)
*pbThisLclOwnsExclusive = (BOOL) ( this_gbl->lpExclusiveOwner == this_lcl );
/*
* It is possible that another app has set exclusive mode
* on another monitor, or that the same app is calling w/o first
*/
if( pbExclusiveExists )
{
if( !( *pbExclusiveExists ) )
{
LPDDRAWI_DIRECTDRAW_INT pdrv_int;
pdrv_int = lpDriverObjectList;
while (pdrv_int != NULL )
{
if( ( pdrv_int->lpLcl->lpGbl != this_gbl ) &&
( pdrv_int->lpLcl->dwLocalFlags & DDRAWILCL_HASEXCLUSIVEMODE ) &&
( pdrv_int->lpLcl->lpGbl->lpExclusiveOwner == pdrv_int->lpLcl ) )
{
if( bCanGetIt )
{
if( ( pdrv_int->lpLcl->hFocusWnd != PtrToUlong(hwnd) ) &&
( pdrv_int->lpLcl->lpGbl->dwFlags & DDRAWI_DISPLAYDRV ) &&
( this_gbl->dwFlags & DDRAWI_DISPLAYDRV ) )
{
*pbExclusiveExists = TRUE;
break;
}
}
else
{
*pbExclusiveExists = TRUE;
break;
}
}
pdrv_int = pdrv_int->lpLink;
}
}
}
#ifdef WINNT
/*
* Undo the temporary ref we just took on the mutex to check its state, if we're not actually
* taking ownership. We are not taking ownership if we already have ownership. This means this routine
* doesn't allow more than one ref on the exclusive mode mutex.
*/
if (!bKeepMutex || *pbThisLclOwnsExclusive)
{
ReleaseMutex( hExclusiveModeMutex );
}
}
else if (dwWaitResult == WAIT_TIMEOUT)
{
/*
* Some other thread owns the exclusive mode mutex. If that other thread took the mutex
* on this_lcl as well, then the current thread owns excl. mode.
*
* We can still check if the exclusive owner is us, because all we're doing is checking
* pointers that can only be set by whoever owns the mutex. The owner pointer will be 0
* until it becomes (until the mutex is released) some pointer. Thus we will never get
* a false positive when this thread asks if it owns excl. mode here.
*/
if (this_gbl->lpExclusiveOwner == this_lcl)
{
if (pbExclusiveExists)
*pbExclusiveExists = TRUE;
if (pbThisLclOwnsExclusive)
*pbThisLclOwnsExclusive = TRUE;
}
else
{
if (pbExclusiveExists)
*pbExclusiveExists = TRUE;
if (pbThisLclOwnsExclusive)
*pbThisLclOwnsExclusive = FALSE;
}
}
else if (dwWaitResult == WAIT_ABANDONED)
{
/*
* Some other thread lost exclusive mode. We have now picked it up.
*/
if (pbExclusiveExists)
*pbExclusiveExists = FALSE;
if (pbThisLclOwnsExclusive)
*pbThisLclOwnsExclusive = FALSE;
/*
* Undo the temporary ref we just took on the mutex to check its state, if we're not actually
* taking ownership.
*/
if (!bKeepMutex)
{
ReleaseMutex( hExclusiveModeMutex );
}
}
else
{
DPF(0, "Unexpected return from WaitForSingleObject.");
DDASSERT(FALSE);
if (pbExclusiveExists)
*pbExclusiveExists = TRUE;
if (pbThisLclOwnsExclusive)
*pbThisLclOwnsExclusive = FALSE;
}
ReleaseMutex( hCheckExclusiveModeMutex );
#endif
}