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.
6982 lines
210 KiB
6982 lines
210 KiB
/*==========================================================================
|
|
* Copyright (C) 1994-1995 Microsoft Corporation. All Rights Reserved.
|
|
*
|
|
* File: ddsurf.c
|
|
* Content: DirectDraw engine surface 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...
|
|
* 06-feb-95 craige performance tuning, ongoing work
|
|
* 27-feb-95 craige new sync. macros
|
|
* 07-mar-95 craige keep track of flippable surfaces
|
|
* 11-mar-95 craige palette stuff, keep track of process surface usage
|
|
* 15-mar-95 craige HEL
|
|
* 19-mar-95 craige use HRESULTs
|
|
* 20-mar-95 craige allow NULL rect to disable cliplist
|
|
* 31-mar-95 craige don't allow hWnd to be updated if in exclusive mode
|
|
* and requesting process isn't the holder
|
|
* 01-apr-95 craige happy fun joy updated header file
|
|
* 12-apr-95 craige proper call order for csects
|
|
* 15-apr-95 craige flags for GetFlipStatus, added GetBltStatus
|
|
* 16-apr-95 craige flip between two specific surfaces was broken
|
|
* 06-may-95 craige use driver-level csects only
|
|
* 23-may-95 craige no longer use MapLS_Pool
|
|
* 24-may-95 craige added Restore
|
|
* 28-may-95 craige cleaned up HAL: added GetBltStatus; GetFlipStatus
|
|
* 04-jun-95 craige flesh out Restore; check for SURFACE_LOST inside csect;
|
|
* added IsLost
|
|
* 11-jun-95 craige prevent restoration of primary if different mode
|
|
* 12-jun-95 craige new process list stuff
|
|
* 13-jun-95 kylej moved FindAttachedFlip to misc.c
|
|
* 17-jun-95 craige new surface structure
|
|
* 19-jun-95 craige split out surface notification methods
|
|
* 20-jun-95 craige go get current clip list if user didn't specify one
|
|
* 24-jun-95 kylej added MoveToSystemMemory
|
|
* 25-jun-95 craige one ddraw mutex
|
|
* 26-jun-95 craige reorganized surface structure
|
|
* 27-jun-95 craige don't let surfaces be restored if the mode is different
|
|
* 28-jun-95 craige fixed flip for overlays; ENTER_DDRAW at start of fns
|
|
* 30-jun-95 kylej only allow flip in exclusive mode, only allow surface
|
|
* restore in same video mode it was created, force
|
|
* primary to match existing primaries upon restore if
|
|
* not exclusive, added GetProcessPrimary,
|
|
* InvalidateAllPrimarySurfaces, FindGlobalPrimary,
|
|
* and MatchPrimary
|
|
* 30-jun-95 craige use DDRAWI_HASPIXELFORMAT/HASOVERLAYDATA
|
|
* 01-jul-95 craige allow flip always - just fail creation of flipping
|
|
* 04-jul-95 craige YEEHAW: new driver struct; SEH; redid Primary fns;
|
|
* fixes to MoveToSystemMemory; fixes to
|
|
* InvalidateAllPrimarySurfaces
|
|
* 05-jul-95 craige added Initialize
|
|
* 07-jul-95 craige added test for BUSY
|
|
* 08-jul-95 craige return DD_OK from Restore if surface is not lost;
|
|
* added InvalidateAllSurfaces
|
|
* 09-jul-95 craige Restore needs to reset pitch to aligned width before
|
|
* asking driver to reallocate; make MoveToSystemMemory
|
|
* recreate without VRAM so Restore can restore to sysmem
|
|
* 11-jul-95 craige GetDC fixes: no GetDC(NULL); need flag to check if
|
|
* DC has been allocated
|
|
* 15-jul-95 craige fixed flipping to move heap along with ptr
|
|
* 15-jul-95 ericeng SetCompression if0 out, obsolete
|
|
* 20-jul-95 toddla fixed MoveToSystemMemory for 16bpp
|
|
* 01-aug-95 craige hold win16 lock at start of Flip
|
|
* 04-aug-95 craige have MoveToSystemMemory use InternalLock/Unlock
|
|
* 10-aug-95 toddla added DDFLIP_WAIT flag, but it is not turned on
|
|
* 12-aug-95 craige added use_full_lock in MoveToSystemMemory
|
|
* 13-aug-95 craige turned on DDFLIP_WAIT
|
|
* 26-aug-95 craige bug 717
|
|
* 05-sep-95 craige bug 894: don't invalidate SYSMEMREQUESTED surfaces
|
|
* 10-sep-95 craige bug 828: random vidmem heap free
|
|
* 22-sep-95 craige bug 1268,1269: getbltstatus/getflipstatus flags wrong
|
|
* 09-dec-95 colinmc added execute buffer support
|
|
* 17-dec-95 colinmc added shared back and z-buffer support
|
|
* 02-jan-96 kylej handle new interface structs
|
|
* 26-jan-96 jeffno NT kernel conversation. NT Get/Release DC, flip GDI flag
|
|
* 09-feb-96 colinmc surface invalid flag moved from the global to local
|
|
* surface object
|
|
* 17-feb-96 colinmc removed execute buffer size limitation
|
|
* 26-feb-96 jeffno GetDC for emulated offscreen now returns a new dc
|
|
* 13-mar-96 kylej Added DD_Surface_GetDDInterface
|
|
* 17-mar-96 colinmc Bug 13124: flippable mip-maps
|
|
* 14-apr-96 colinmc Bug 17736: No driver notification of flip to GDI
|
|
* surface
|
|
* 26-mar-96 jeffno Handle mode changes before flip (NT)
|
|
* 05-sep-96 craige added code to display frame rate to debug monitor
|
|
* 05-jul-96 colinmc Work Item: Remove requirement on taking Win16 lock
|
|
* for VRAM surfaces (not primary)
|
|
* 07-oct-96 ketand Change PageLock/Unlock to cache Physical Addresses
|
|
* 12-oct-96 colinmc Improvements to Win16 locking code to reduce virtual
|
|
* memory usage
|
|
* 19-nov-96 colinmc Bug 4987: Fixed problems with Flip on the
|
|
* IDirectDrawSurface2 interface
|
|
* 10-jan-97 jeffno Flip the primary chain flags so that GDI<==>Primary
|
|
* after a ctrl-alt-del on NT.
|
|
* 12-jan-97 colinmc More Win16 lock work
|
|
* 18-jan-97 colinmc AGP support
|
|
* 31-jan-97 colinmc Bug 5457: Fixed aliased locking (no Win16 lock)
|
|
* problem with playing multiple AMovie clips at once.
|
|
* 22-feb-97 colinmc Enabled OWNDC support for explicit system memory
|
|
* surfaces
|
|
* 03-mar-97 smac Added kernel mode interface
|
|
* 04-mar-97 smac Bug 1987: Fixed bug flipping overlays when the
|
|
* surface didn't own the hardware
|
|
* 08-mar-97 colinmc Added function to let surface pointer be overridden
|
|
* 11-mar-97 jeffno Asynchronous DMA support
|
|
* 24-mar-97 jeffno Optimized Surfaces
|
|
* 30-sep-97 jeffno IDirectDraw4
|
|
* 03-oct-97 jeffno DDSCAPS2 and DDSURFACEDESC2
|
|
* 31-oct-97 johnstep Persistent-content surfaces for Windows 9x
|
|
* 11-nov-97 jvanaken New API call "Resize"
|
|
* 18-dec-97 jvanaken SetSurfDesc will free client-alloc'd surface memory.
|
|
* 25-may-00 RichGr IA64: Change debug output to use %p format specifier
|
|
* instead of %x for 32/64-bit pointers.
|
|
*
|
|
***************************************************************************/
|
|
#include "ddrawpr.h"
|
|
#ifdef WINNT
|
|
#include "ddrawgdi.h"
|
|
#endif
|
|
#define DPF_MODNAME "GetCaps"
|
|
|
|
/* Shorter name makes flip code a little easier to understand */
|
|
#define GBLMORE(lpGbl) GET_LPDDRAWSURFACE_GBL_MORE(lpGbl)
|
|
|
|
/*
|
|
* DD_Surface_GetCaps
|
|
*/
|
|
HRESULT DDAPI DD_Surface_GetCaps(
|
|
LPDIRECTDRAWSURFACE lpDDSurface,
|
|
LPDDSCAPS lpDDSCaps )
|
|
{
|
|
DDSCAPS2 ddscaps2 = {0,0,0,0};
|
|
HRESULT hr;
|
|
|
|
DPF(2,A,"ENTERAPI: DD_Surface_GetCaps");
|
|
|
|
hr = DD_Surface_GetCaps4(lpDDSurface, & ddscaps2 );
|
|
if (hr == DD_OK)
|
|
{
|
|
TRY
|
|
{
|
|
lpDDSCaps->dwCaps = ddscaps2.dwCaps;
|
|
}
|
|
EXCEPT( EXCEPTION_EXECUTE_HANDLER )
|
|
{
|
|
DPF_ERR( "Invalid DDSCAPS pointer" );
|
|
return DDERR_INVALIDPARAMS;
|
|
}
|
|
}
|
|
return hr;
|
|
}
|
|
|
|
HRESULT DDAPI DD_Surface_GetCaps4(
|
|
LPDIRECTDRAWSURFACE lpDDSurface,
|
|
LPDDSCAPS2 lpDDSCaps )
|
|
{
|
|
LPDDRAWI_DDRAWSURFACE_INT this_int;
|
|
LPDDRAWI_DDRAWSURFACE_LCL this_lcl;
|
|
LPDDRAWI_DDRAWSURFACE_GBL this;
|
|
|
|
ENTER_DDRAW();
|
|
|
|
DPF(2,A,"ENTERAPI: DD_Surface_GetCaps4");
|
|
|
|
TRY
|
|
{
|
|
this_int = (LPDDRAWI_DDRAWSURFACE_INT) lpDDSurface;
|
|
if( !VALID_DIRECTDRAWSURFACE_PTR( this_int ) )
|
|
{
|
|
LEAVE_DDRAW();
|
|
return DDERR_INVALIDOBJECT;
|
|
}
|
|
if( !VALID_DDSCAPS2_PTR( lpDDSCaps ) )
|
|
{
|
|
LEAVE_DDRAW();
|
|
return DDERR_INVALIDPARAMS;
|
|
}
|
|
this_lcl = this_int->lpLcl;
|
|
this = this_lcl->lpGbl;
|
|
lpDDSCaps->dwCaps = this_lcl->ddsCaps.dwCaps;
|
|
lpDDSCaps->ddsCapsEx = this_lcl->lpSurfMore->ddsCapsEx;
|
|
}
|
|
EXCEPT( EXCEPTION_EXECUTE_HANDLER )
|
|
{
|
|
DPF_ERR( "Exception encountered validating parameters" );
|
|
LEAVE_DDRAW();
|
|
return DDERR_INVALIDPARAMS;
|
|
}
|
|
LEAVE_DDRAW();
|
|
return DD_OK;
|
|
|
|
} /* DD_Surface_GetCaps */
|
|
|
|
#undef DPF_MODNAME
|
|
#define DPF_MODNAME "GetFlipStatus"
|
|
|
|
/*
|
|
* DD_Surface_GetFlipStatus
|
|
*/
|
|
HRESULT DDAPI DD_Surface_GetFlipStatus(
|
|
LPDIRECTDRAWSURFACE lpDDSurface,
|
|
DWORD dwFlags )
|
|
{
|
|
LPDDRAWI_DDRAWSURFACE_INT this_int;
|
|
LPDDRAWI_DDRAWSURFACE_LCL this_lcl;
|
|
LPDDRAWI_DDRAWSURFACE_GBL this;
|
|
LPDDHALSURFCB_GETFLIPSTATUS gfshalfn;
|
|
LPDDHALSURFCB_GETFLIPSTATUS gfsfn;
|
|
LPDDRAWI_DIRECTDRAW_LCL pdrv_lcl;
|
|
LPDDRAWI_DIRECTDRAW_GBL pdrv;
|
|
|
|
ENTER_DDRAW();
|
|
|
|
DPF(2,A,"ENTERAPI: DD_Surface_GetFlipStatus");
|
|
|
|
TRY
|
|
{
|
|
this_int = (LPDDRAWI_DDRAWSURFACE_INT) lpDDSurface;
|
|
if( !VALID_DIRECTDRAWSURFACE_PTR( this_int ) )
|
|
{
|
|
LEAVE_DDRAW();
|
|
return DDERR_INVALIDOBJECT;
|
|
}
|
|
if( dwFlags & ~DDGFS_VALID )
|
|
{
|
|
DPF_ERR( "Invalid flags" );
|
|
LEAVE_DDRAW();
|
|
return DDERR_INVALIDPARAMS;
|
|
}
|
|
if( dwFlags )
|
|
{
|
|
if( (dwFlags & (DDGFS_CANFLIP|DDGFS_ISFLIPDONE)) ==
|
|
(DDGFS_CANFLIP|DDGFS_ISFLIPDONE) )
|
|
{
|
|
DPF_ERR( "Invalid flags" );
|
|
LEAVE_DDRAW();
|
|
return DDERR_INVALIDPARAMS;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
DPF_ERR( "Invalid flags - no flag specified" );
|
|
LEAVE_DDRAW();
|
|
return DDERR_INVALIDPARAMS;
|
|
}
|
|
|
|
this_lcl = this_int->lpLcl;
|
|
this = this_lcl->lpGbl;
|
|
pdrv_lcl = this_lcl->lpSurfMore->lpDD_lcl;
|
|
pdrv = pdrv_lcl->lpGbl;
|
|
|
|
if( this_lcl->ddsCaps.dwCaps & DDSCAPS_EXECUTEBUFFER )
|
|
{
|
|
DPF_ERR( "Invalid surface type: can't get flip status" );
|
|
LEAVE_DDRAW();
|
|
return DDERR_INVALIDSURFACETYPE;
|
|
}
|
|
|
|
if( SURFACE_LOST( this_lcl ) )
|
|
{
|
|
LEAVE_DDRAW();
|
|
return DDERR_SURFACELOST;
|
|
}
|
|
|
|
#ifdef USE_ALIAS
|
|
if( pdrv->dwBusyDueToAliasedLock > 0 )
|
|
{
|
|
/*
|
|
* Aliased locks (the ones that don't take the Win16 lock) don't
|
|
* set the busy bit either (it can't or USER get's very confused).
|
|
* However, we must prevent blits happening via DirectDraw as
|
|
* otherwise we get into the old host talking to VRAM while
|
|
* blitter does at the same time. Bad. So fail if there is an
|
|
* outstanding aliased lock just as if the BUST bit had been
|
|
* set.
|
|
*/
|
|
DPF_ERR( "Graphics adapter is busy (due to a DirectDraw lock)" );
|
|
LEAVE_DDRAW();
|
|
return DDERR_SURFACEBUSY;
|
|
}
|
|
#endif /* USE_ALIAS */
|
|
|
|
/*
|
|
* device busy?
|
|
*/
|
|
if( *(pdrv->lpwPDeviceFlags) & BUSY )
|
|
{
|
|
DPF( 0, "BUSY" );
|
|
LEAVE_DDRAW()
|
|
return DDERR_SURFACEBUSY;
|
|
}
|
|
|
|
if( this_lcl->ddsCaps.dwCaps & DDSCAPS_SYSTEMMEMORY )
|
|
{
|
|
LEAVE_DDRAW()
|
|
return DD_OK;
|
|
}
|
|
}
|
|
EXCEPT( EXCEPTION_EXECUTE_HANDLER )
|
|
{
|
|
DPF_ERR( "Exception encountered validating parameters" );
|
|
LEAVE_DDRAW();
|
|
return DDERR_INVALIDPARAMS;
|
|
}
|
|
|
|
/*
|
|
* ask the driver to get the current flip status
|
|
*/
|
|
gfsfn = pdrv_lcl->lpDDCB->HALDDSurface.GetFlipStatus;
|
|
gfshalfn = pdrv_lcl->lpDDCB->cbDDSurfaceCallbacks.GetFlipStatus;
|
|
if( gfshalfn != NULL )
|
|
{
|
|
DDHAL_GETFLIPSTATUSDATA gfsd;
|
|
DWORD rc;
|
|
|
|
gfsd.GetFlipStatus = gfshalfn;
|
|
gfsd.lpDD = pdrv;
|
|
gfsd.dwFlags = dwFlags;
|
|
gfsd.lpDDSurface = this_lcl;
|
|
DOHALCALL( GetFlipStatus, gfsfn, gfsd, rc, FALSE );
|
|
if( rc == DDHAL_DRIVER_HANDLED )
|
|
{
|
|
LEAVE_DDRAW();
|
|
return gfsd.ddRVal;
|
|
}
|
|
}
|
|
|
|
LEAVE_DDRAW();
|
|
// if you have to ask the hel, it's already done
|
|
return DD_OK;
|
|
|
|
} /* DD_Surface_GetFlipStatus */
|
|
|
|
#undef DPF_MODNAME
|
|
#define DPF_MODNAME "InternalGetBltStatus"
|
|
HRESULT InternalGetBltStatus(LPDDRAWI_DIRECTDRAW_LCL pdrv_lcl, LPDDRAWI_DDRAWSURFACE_LCL this_lcl , DWORD dwFlags )
|
|
{
|
|
DDHAL_GETBLTSTATUSDATA gbsd;
|
|
LPDDHALSURFCB_GETBLTSTATUS gbsfn;
|
|
/*
|
|
* Ask the driver to get the current blt status
|
|
*
|
|
*/
|
|
if ( this_lcl->ddsCaps.dwCaps & DDSCAPS_SYSTEMMEMORY )
|
|
{
|
|
gbsfn = pdrv_lcl->lpDDCB->HALDDMiscellaneous.GetSysmemBltStatus;
|
|
gbsd.GetBltStatus = pdrv_lcl->lpDDCB->HALDDMiscellaneous.GetSysmemBltStatus;
|
|
}
|
|
else
|
|
{
|
|
gbsfn = pdrv_lcl->lpDDCB->HALDDSurface.GetBltStatus;
|
|
gbsd.GetBltStatus = pdrv_lcl->lpDDCB->cbDDSurfaceCallbacks.GetBltStatus;
|
|
}
|
|
|
|
if( gbsd.GetBltStatus != NULL )
|
|
{
|
|
DWORD rc;
|
|
|
|
gbsd.lpDD = pdrv_lcl->lpGbl;
|
|
gbsd.dwFlags = dwFlags;
|
|
gbsd.lpDDSurface = this_lcl;
|
|
DOHALCALL( GetBltStatus, gbsfn, gbsd, rc, FALSE );
|
|
if( rc == DDHAL_DRIVER_HANDLED )
|
|
{
|
|
return gbsd.ddRVal;
|
|
}
|
|
}
|
|
|
|
return DD_OK;
|
|
}
|
|
#undef DPF_MODNAME
|
|
#define DPF_MODNAME "GetBltStatus"
|
|
|
|
/*
|
|
* DD_Surface_GetBltStatus
|
|
*/
|
|
HRESULT DDAPI DD_Surface_GetBltStatus(
|
|
LPDIRECTDRAWSURFACE lpDDSurface,
|
|
DWORD dwFlags )
|
|
{
|
|
LPDDRAWI_DDRAWSURFACE_INT this_int;
|
|
LPDDRAWI_DDRAWSURFACE_LCL this_lcl;
|
|
LPDDRAWI_DDRAWSURFACE_GBL this;
|
|
LPDDRAWI_DIRECTDRAW_LCL pdrv_lcl;
|
|
LPDDRAWI_DIRECTDRAW_GBL pdrv;
|
|
HRESULT ddrval;
|
|
|
|
ENTER_DDRAW();
|
|
|
|
DPF(2,A,"ENTERAPI: DD_Surface_GetBltStatus");
|
|
|
|
TRY
|
|
{
|
|
this_int = (LPDDRAWI_DDRAWSURFACE_INT) lpDDSurface;
|
|
if( !VALID_DIRECTDRAWSURFACE_PTR( this_int ) )
|
|
{
|
|
LEAVE_DDRAW();
|
|
return DDERR_INVALIDOBJECT;
|
|
}
|
|
this_lcl = this_int->lpLcl;
|
|
if( dwFlags & ~DDGBS_VALID )
|
|
{
|
|
DPF_ERR( "Invalid flags" );
|
|
LEAVE_DDRAW();
|
|
return DDERR_INVALIDPARAMS;
|
|
}
|
|
if( dwFlags )
|
|
{
|
|
if( (dwFlags & (DDGBS_CANBLT|DDGBS_ISBLTDONE)) ==
|
|
(DDGBS_CANBLT|DDGBS_ISBLTDONE) )
|
|
{
|
|
DPF_ERR( "Invalid flags" );
|
|
LEAVE_DDRAW();
|
|
return DDERR_INVALIDPARAMS;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
DPF_ERR( "Invalid flags - no flag specified" );
|
|
LEAVE_DDRAW();
|
|
return DDERR_INVALIDPARAMS;
|
|
}
|
|
|
|
this = this_lcl->lpGbl;
|
|
pdrv_lcl = this_lcl->lpSurfMore->lpDD_lcl;
|
|
pdrv = pdrv_lcl->lpGbl;
|
|
|
|
if( SURFACE_LOST( this_lcl ) )
|
|
{
|
|
LEAVE_DDRAW();
|
|
return DDERR_SURFACELOST;
|
|
}
|
|
|
|
#ifdef USE_ALIAS
|
|
if( pdrv->dwBusyDueToAliasedLock > 0 )
|
|
{
|
|
/*
|
|
* Aliased locks (the ones that don't take the Win16 lock) don't
|
|
* set the busy bit either (it can't or USER get's very confused).
|
|
* However, we must prevent blits happening via DirectDraw as
|
|
* otherwise we get into the old host talking to VRAM while
|
|
* blitter does at the same time. Bad. So fail if there is an
|
|
* outstanding aliased lock just as if the BUST bit had been
|
|
* set.
|
|
*/
|
|
DPF_ERR( "Graphics adapter is busy (due to a DirectDraw lock)" );
|
|
LEAVE_DDRAW();
|
|
return DDERR_SURFACEBUSY;
|
|
}
|
|
#endif /* USE_ALIAS */
|
|
|
|
/*
|
|
* device busy?
|
|
*/
|
|
if( *(pdrv->lpwPDeviceFlags) & BUSY )
|
|
{
|
|
DPF( 0, "BUSY" );
|
|
LEAVE_DDRAW()
|
|
return DDERR_SURFACEBUSY;
|
|
}
|
|
|
|
// If DDCAPS_CANBLTSYSMEM is set, we have to let the driver tell us
|
|
// whether a system memory surface is currently being blitted
|
|
if( ( this_lcl->ddsCaps.dwCaps & DDSCAPS_SYSTEMMEMORY ) &&
|
|
!( pdrv->ddCaps.dwCaps & DDCAPS_CANBLTSYSMEM ) )
|
|
{
|
|
LEAVE_DDRAW()
|
|
return DD_OK;
|
|
}
|
|
}
|
|
EXCEPT( EXCEPTION_EXECUTE_HANDLER )
|
|
{
|
|
DPF_ERR( "Exception encountered validating parameters" );
|
|
LEAVE_DDRAW();
|
|
return DDERR_INVALIDPARAMS;
|
|
}
|
|
|
|
//
|
|
// If the current surface is optimized, quit
|
|
//
|
|
if (this_lcl->ddsCaps.dwCaps & DDSCAPS_OPTIMIZED)
|
|
{
|
|
DPF_ERR( "It is an optimized surface" );
|
|
LEAVE_DDRAW();
|
|
return DDERR_ISOPTIMIZEDSURFACE;
|
|
}
|
|
|
|
ddrval = InternalGetBltStatus( pdrv_lcl, this_lcl, dwFlags );
|
|
|
|
LEAVE_DDRAW();
|
|
return ddrval;
|
|
|
|
} /* DD_Surface_GetBltStatus */
|
|
|
|
#if 0
|
|
/*
|
|
* DD_Surface_Flush
|
|
*/
|
|
HRESULT DDAPI DD_Surface_Flush(
|
|
LPDIRECTDRAWSURFACE lpDDSurface,
|
|
DWORD dwFlags )
|
|
{
|
|
LPDDRAWI_DDRAWSURFACE_INT this_int;
|
|
LPDDRAWI_DDRAWSURFACE_LCL this_lcl;
|
|
LPDDRAWI_DDRAWSURFACE_GBL this;
|
|
LPDDRAWI_DIRECTDRAW_GBL pdrv;
|
|
|
|
ENTER_DDRAW();
|
|
|
|
DPF(2,A,"ENTERAPI: DD_Surface_Flush");
|
|
|
|
TRY
|
|
{
|
|
this_int = (LPDDRAWI_DDRAWSURFACE_INT) lpDDSurface;
|
|
if( !VALID_DIRECTDRAWSURFACE_PTR( this_int ) )
|
|
{
|
|
LEAVE_DDRAW();
|
|
return DDERR_INVALIDOBJECT;
|
|
}
|
|
this_lcl = this_int->lpLcl;
|
|
this = this_lcl->lpGbl;
|
|
pdrv = this->lpDD;
|
|
if( SURFACE_LOST( this_lcl ) )
|
|
{
|
|
LEAVE_DDRAW();
|
|
return DDERR_SURFACELOST;
|
|
}
|
|
}
|
|
EXCEPT( EXCEPTION_EXECUTE_HANDLER )
|
|
{
|
|
DPF_ERR( "Exception encountered validating parameters" );
|
|
LEAVE_DDRAW();
|
|
return DDERR_INVALIDPARAMS;
|
|
}
|
|
LEAVE_DDRAW();
|
|
return DD_OK;
|
|
|
|
} /* DD_Surface_Flush */
|
|
#endif
|
|
|
|
#undef DPF_MODNAME
|
|
#define DPF_MODNAME "Flip"
|
|
|
|
/*
|
|
* FlipMipMapChain
|
|
*
|
|
* Flip a chain of mip-map surfaces.
|
|
*/
|
|
static HRESULT FlipMipMapChain( LPDIRECTDRAWSURFACE lpDDSurface,
|
|
LPDIRECTDRAWSURFACE lpDDSurfaceDest,
|
|
DWORD dwFlags )
|
|
{
|
|
LPDDRAWI_DDRAWSURFACE_INT this_int;
|
|
LPDDRAWI_DDRAWSURFACE_LCL this_lcl;
|
|
LPDDRAWI_DDRAWSURFACE_GBL this;
|
|
LPDDRAWI_DDRAWSURFACE_INT next_int;
|
|
LPDDRAWI_DDRAWSURFACE_LCL next_lcl;
|
|
LPDDRAWI_DDRAWSURFACE_GBL next;
|
|
LPDDRAWI_DDRAWSURFACE_INT attached_int;
|
|
FLATPTR vidmem;
|
|
LPVMEMHEAP vidmemheap;
|
|
ULONG_PTR reserved;
|
|
DWORD gdi_flag;
|
|
ULONG_PTR handle;
|
|
BOOL toplevel;
|
|
int destindex;
|
|
int thisindex;
|
|
BOOL destfound;
|
|
#ifdef USE_ALIAS
|
|
FLATPTR aliasvidmem;
|
|
FLATPTR aliasofvidmem;
|
|
#endif /* USE_ALIAS */
|
|
FLATPTR physicalvidmem;
|
|
ULONG_PTR driverreserved;
|
|
|
|
TRY
|
|
{
|
|
this_int = (LPDDRAWI_DDRAWSURFACE_INT) lpDDSurface;
|
|
|
|
/*
|
|
* We validate each level of the mip-map before we do any
|
|
* flipping. This is in an effort to prevent half flipped
|
|
* surfaces.
|
|
*/
|
|
toplevel = TRUE;
|
|
do
|
|
{
|
|
/*
|
|
* At this point this_int points to the front buffer
|
|
* of a flippable chain of surface for this level of
|
|
* the mip-map.
|
|
*/
|
|
|
|
/*
|
|
* Invalid source surface?
|
|
*/
|
|
if( !VALID_DIRECTDRAWSURFACE_PTR( this_int ) )
|
|
{
|
|
DPF_ERR( "Invalid front buffer for flip" );
|
|
return DDERR_INVALIDOBJECT;
|
|
}
|
|
this_lcl = this_int->lpLcl;
|
|
this = this_lcl->lpGbl;
|
|
|
|
/*
|
|
* Source surface lost?
|
|
*/
|
|
if( SURFACE_LOST( this_lcl ) )
|
|
{
|
|
DPF_ERR( "Can't flip - front buffer is lost" );
|
|
return DDERR_SURFACELOST;
|
|
}
|
|
|
|
/*
|
|
* Source surface flippable?
|
|
*/
|
|
if( !(this_lcl->ddsCaps.dwCaps & DDSCAPS_FRONTBUFFER) )
|
|
{
|
|
DPF_ERR( "Can't flip - first surface is not a front buffer" );
|
|
return DDERR_NOTFLIPPABLE;
|
|
}
|
|
if( !(this_lcl->ddsCaps.dwCaps & DDSCAPS_FLIP) )
|
|
{
|
|
DPF_ERR( "Surface is not flippable" );
|
|
return DDERR_NOTFLIPPABLE;
|
|
}
|
|
|
|
/*
|
|
* Source surface locked?
|
|
*/
|
|
if( this->dwUsageCount > 0 )
|
|
{
|
|
DPF_ERR( "Can't flip - surface is locked" );
|
|
return DDERR_SURFACEBUSY;
|
|
}
|
|
|
|
/*
|
|
* Validate destination surfaces of flip.
|
|
*/
|
|
next_int = FindAttachedFlip( this_int );
|
|
if( next_int == NULL )
|
|
{
|
|
DPF_ERR( "Can't flip - no surface to flip to" );
|
|
return DDERR_NOTFLIPPABLE;
|
|
}
|
|
|
|
/*
|
|
* If this is the top level of the mip-map and a destination
|
|
* surface has been provided then we need to find out which
|
|
* buffer (by index) the supplied destination is so that we
|
|
* can flip to the matching buffers in the lower-level maps.
|
|
*/
|
|
if( NULL != lpDDSurfaceDest )
|
|
{
|
|
thisindex = 0;
|
|
destfound = FALSE;
|
|
if( toplevel )
|
|
destindex = -1;
|
|
}
|
|
|
|
do
|
|
{
|
|
/*
|
|
* If a destination surface has been supplied then is this
|
|
* it?
|
|
*/
|
|
if( NULL != lpDDSurfaceDest )
|
|
{
|
|
if( toplevel )
|
|
{
|
|
/*
|
|
* As we may have multiple interfaces pointing to the same
|
|
* object we need to compare objects not interface pointers
|
|
*/
|
|
if( next_int->lpLcl == ( (LPDDRAWI_DDRAWSURFACE_INT) lpDDSurfaceDest )->lpLcl )
|
|
{
|
|
destindex = thisindex;
|
|
destfound = TRUE;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if( thisindex == destindex )
|
|
{
|
|
destfound = TRUE;
|
|
}
|
|
}
|
|
}
|
|
|
|
/*
|
|
* Invalid destination surface?
|
|
*/
|
|
if( !VALID_DIRECTDRAWSURFACE_PTR( next_int ) )
|
|
{
|
|
DPF_ERR( "Can't flip - invalid back buffer" );
|
|
return DDERR_INVALIDOBJECT;
|
|
}
|
|
next_lcl = next_int->lpLcl;
|
|
next = next_lcl->lpGbl;
|
|
|
|
/*
|
|
* Destination surface lost?
|
|
*/
|
|
if( SURFACE_LOST( next_lcl ) )
|
|
{
|
|
DPF_ERR( "Can't flip - back buffer is lost" );
|
|
return DDERR_SURFACELOST;
|
|
}
|
|
|
|
/*
|
|
* Destination surface locked?
|
|
*/
|
|
if( next->dwUsageCount > 0 )
|
|
{
|
|
DPF_ERR( "Can't flip - back buffer is locked" );
|
|
return DDERR_SURFACEBUSY;
|
|
}
|
|
|
|
/*
|
|
* Ensure that both source and destination surfaces reside
|
|
* in the same kind of memory.
|
|
*/
|
|
if( ( ( this_lcl->ddsCaps.dwCaps & DDSCAPS_SYSTEMMEMORY ) &&
|
|
( next_lcl->ddsCaps.dwCaps & DDSCAPS_VIDEOMEMORY ) ) ||
|
|
( ( this_lcl->ddsCaps.dwCaps & DDSCAPS_VIDEOMEMORY ) &&
|
|
( next_lcl->ddsCaps.dwCaps & DDSCAPS_SYSTEMMEMORY ) ) )
|
|
{
|
|
DPF_ERR( "Can't flip between system/video memory surfaces" );
|
|
return DDERR_INVALIDPARAMS;
|
|
}
|
|
|
|
/*
|
|
* Next destination surface.
|
|
*/
|
|
next_int = FindAttachedFlip( next_int );
|
|
thisindex++;
|
|
|
|
} while( next_int->lpLcl != this_int->lpLcl );
|
|
|
|
/*
|
|
* If a destination was supplied did we find it?
|
|
*/
|
|
if( ( NULL != lpDDSurfaceDest ) && !destfound )
|
|
{
|
|
/*
|
|
* Could not find the destination.
|
|
*/
|
|
DPF_ERR( "Can't flip - destination surface not found in flippable chain" );
|
|
return DDERR_NOTFLIPPABLE;
|
|
}
|
|
DDASSERT( destindex != -1 );
|
|
|
|
/*
|
|
* Next mip-map level.
|
|
*/
|
|
this_int = FindAttachedMipMap( this_int );
|
|
toplevel = FALSE;
|
|
|
|
} while( this_int != NULL );
|
|
}
|
|
EXCEPT( EXCEPTION_EXECUTE_HANDLER )
|
|
{
|
|
DPF_ERR( "Exception encountered validating parameters" );
|
|
return DDERR_INVALIDPARAMS;
|
|
}
|
|
|
|
/*
|
|
* Now actually flip each level of the mip-map.
|
|
*/
|
|
this_int = (LPDDRAWI_DDRAWSURFACE_INT) lpDDSurface;
|
|
do
|
|
{
|
|
/*
|
|
* Process one level of the mip-map.
|
|
*/
|
|
|
|
this_lcl = this_int->lpLcl;
|
|
this = this_lcl->lpGbl;
|
|
|
|
/*
|
|
* Find the first destination surface of the flip.
|
|
*/
|
|
next_int = FindAttachedFlip( this_int );
|
|
if( NULL != lpDDSurfaceDest )
|
|
{
|
|
/*
|
|
* If an override destination has been provided find the
|
|
* appropriate back destination surface.
|
|
*/
|
|
for( thisindex = 0; thisindex < destindex; thisindex++ )
|
|
next_int = FindAttachedFlip( next_int );
|
|
}
|
|
|
|
DDASSERT( NULL != next_int );
|
|
next_lcl = next_int->lpLcl;
|
|
|
|
/*
|
|
* save the old values
|
|
*/
|
|
vidmem = next_lcl->lpGbl->fpVidMem;
|
|
#ifdef USE_ALIAS
|
|
aliasvidmem = GBLMORE(next_lcl->lpGbl)->fpAliasedVidMem;
|
|
aliasofvidmem = GBLMORE(next_lcl->lpGbl)->fpAliasOfVidMem;
|
|
#endif /* USE_ALIAS */
|
|
physicalvidmem = GBLMORE(next_lcl->lpGbl)->fpPhysicalVidMem;
|
|
driverreserved = GBLMORE(next_lcl->lpGbl)->dwDriverReserved;
|
|
vidmemheap = next_lcl->lpGbl->lpVidMemHeap;
|
|
reserved = next_lcl->lpGbl->dwReserved1;
|
|
gdi_flag = next_lcl->lpGbl->dwGlobalFlags & DDRAWISURFGBL_ISGDISURFACE;
|
|
handle = next_lcl->hDDSurface;
|
|
|
|
/*
|
|
* If a destination override was provided then find that destination surface
|
|
* and flip to it explicitly.
|
|
*/
|
|
if( NULL != lpDDSurfaceDest )
|
|
{
|
|
next_lcl->lpGbl->lpVidMemHeap = this->lpVidMemHeap;
|
|
next_lcl->lpGbl->fpVidMem = this->fpVidMem;
|
|
#ifdef USE_ALIAS
|
|
GBLMORE(next_lcl->lpGbl)->fpAliasedVidMem = GBLMORE(this)->fpAliasedVidMem;
|
|
GBLMORE(next_lcl->lpGbl)->fpAliasOfVidMem = GBLMORE(this)->fpAliasOfVidMem;
|
|
#endif /* USE_ALIAS */
|
|
GBLMORE(next_lcl->lpGbl)->fpPhysicalVidMem = GBLMORE(this)->fpPhysicalVidMem;
|
|
GBLMORE(next_lcl->lpGbl)->dwDriverReserved = GBLMORE(this)->dwDriverReserved;
|
|
next_lcl->lpGbl->dwReserved1 = this->dwReserved1;
|
|
next_lcl->lpGbl->dwGlobalFlags &= ~DDRAWISURFGBL_ISGDISURFACE;
|
|
next_lcl->lpGbl->dwGlobalFlags |= this->dwGlobalFlags & DDRAWISURFGBL_ISGDISURFACE;
|
|
next_lcl->hDDSurface = this_lcl->hDDSurface;
|
|
}
|
|
else
|
|
{
|
|
do
|
|
{
|
|
/*
|
|
* Remaining buffers in the chain (including copying the source surface's
|
|
* data.
|
|
*/
|
|
attached_int = FindAttachedFlip( next_int );
|
|
next_lcl->lpGbl->fpVidMem = attached_int->lpLcl->lpGbl->fpVidMem;
|
|
#ifdef USE_ALIAS
|
|
GBLMORE(next_lcl->lpGbl)->fpAliasedVidMem = GBLMORE(attached_int->lpLcl->lpGbl)->fpAliasedVidMem;
|
|
GBLMORE(next_lcl->lpGbl)->fpAliasOfVidMem = GBLMORE(attached_int->lpLcl->lpGbl)->fpAliasOfVidMem;
|
|
#endif /* USE_ALIAS */
|
|
GBLMORE(next_lcl->lpGbl)->fpPhysicalVidMem = GBLMORE(attached_int->lpLcl->lpGbl)->fpPhysicalVidMem;
|
|
GBLMORE(next_lcl->lpGbl)->dwDriverReserved = GBLMORE(attached_int->lpLcl->lpGbl)->dwDriverReserved;
|
|
next_lcl->lpGbl->lpVidMemHeap = attached_int->lpLcl->lpGbl->lpVidMemHeap;
|
|
next_lcl->lpGbl->dwReserved1 = attached_int->lpLcl->lpGbl->dwReserved1;
|
|
next_lcl->lpGbl->dwGlobalFlags &= ~DDRAWISURFGBL_ISGDISURFACE;
|
|
next_lcl->lpGbl->dwGlobalFlags |= attached_int->lpLcl->lpGbl->dwGlobalFlags & DDRAWISURFGBL_ISGDISURFACE;
|
|
next_lcl->hDDSurface = attached_int->lpLcl->hDDSurface;
|
|
next_int = attached_int;
|
|
next_lcl = next_int->lpLcl;
|
|
|
|
/*
|
|
* NOTE: We must compare objects not interfaces (there may be many
|
|
* different interfaces pointing to the same objects) to prevent a
|
|
* infinite loop.
|
|
*/
|
|
} while( next_int->lpLcl != this_int->lpLcl );
|
|
}
|
|
|
|
this->fpVidMem = vidmem;
|
|
#ifdef USE_ALIAS
|
|
GBLMORE(this)->fpAliasedVidMem = aliasvidmem;
|
|
GBLMORE(this)->fpAliasOfVidMem = aliasofvidmem;
|
|
#endif /* USE_ALIAS */
|
|
GBLMORE(this)->fpPhysicalVidMem = physicalvidmem;
|
|
GBLMORE(this)->dwDriverReserved = driverreserved;
|
|
this->lpVidMemHeap = vidmemheap;
|
|
this->dwReserved1 = reserved;
|
|
this->dwGlobalFlags &= ~DDRAWISURFGBL_ISGDISURFACE;
|
|
this->dwGlobalFlags |= gdi_flag;
|
|
this_lcl->hDDSurface = handle;
|
|
|
|
/*
|
|
* Next level of the mip-map.
|
|
*/
|
|
this_int = FindAttachedMipMap( this_int );
|
|
|
|
} while( this_int != NULL );
|
|
|
|
return DD_OK;
|
|
|
|
} /* FlipMipMapChain */
|
|
|
|
DWORD dwLastFrameRate = 0;
|
|
/*
|
|
* updateFrameRate
|
|
*/
|
|
static void updateFrameRate( void )
|
|
{
|
|
static DWORD dwFlipCnt;
|
|
static DWORD dwFlipTime=0xffffffff;
|
|
|
|
/*
|
|
* work out the frame rate if required...
|
|
*/
|
|
|
|
if( dwFlipTime == 0xffffffff )
|
|
{
|
|
dwFlipTime = GetTickCount();
|
|
}
|
|
|
|
dwFlipCnt++;
|
|
if( dwFlipCnt >= 120 )
|
|
{
|
|
DWORD time2;
|
|
DWORD fps;
|
|
char buff[256];
|
|
time2 = GetTickCount() - dwFlipTime;
|
|
fps = (dwFlipCnt*10000)/time2;
|
|
wsprintf( buff, "FPS = %ld.%01ld\r\n", fps/10, fps % 10 );
|
|
dwLastFrameRate = fps;
|
|
|
|
/*
|
|
* OINK32 whines about OutputDebugString, so hide it...
|
|
*/
|
|
{
|
|
HANDLE h;
|
|
h = LoadLibrary( "KERNEL32.DLL" );
|
|
if( h != NULL )
|
|
{
|
|
VOID (WINAPI *lpOutputDebugStringA)(LPCSTR) = (LPVOID)
|
|
GetProcAddress( h, "OutputDebugStringA" );
|
|
if( lpOutputDebugStringA != NULL )
|
|
{
|
|
lpOutputDebugStringA( buff );
|
|
}
|
|
FreeLibrary( h );
|
|
}
|
|
}
|
|
dwFlipTime = GetTickCount();
|
|
dwFlipCnt = 0;
|
|
}
|
|
|
|
} /* updateFrameRate */
|
|
|
|
/*
|
|
* DD_Surface_Flip
|
|
*
|
|
* Page flip to the next surface. Only valid for surfaces which are
|
|
* flippable.
|
|
*/
|
|
#undef DPF_MODNAME
|
|
#define DPF_MODNAME "Flip"
|
|
HRESULT DDAPI DD_Surface_Flip(
|
|
LPDIRECTDRAWSURFACE lpDDSurface,
|
|
LPDIRECTDRAWSURFACE lpDDSurfaceDest,
|
|
DWORD dwFlags )
|
|
{
|
|
LPDDRAWI_DDRAWSURFACE_INT this_int;
|
|
LPDDRAWI_DDRAWSURFACE_LCL this_lcl;
|
|
LPDDRAWI_DDRAWSURFACE_INT this_dest_int;
|
|
LPDDRAWI_DDRAWSURFACE_LCL this_dest_lcl;
|
|
LPDDRAWI_DDRAWSURFACE_INT next_int;
|
|
LPDDRAWI_DDRAWSURFACE_LCL next_lcl;
|
|
LPDDRAWI_DDRAWSURFACE_INT next_save_int;
|
|
LPDDRAWI_DDRAWSURFACE_INT attached_int;
|
|
LPDDRAWI_DDRAWSURFACE_GBL this;
|
|
LPDDRAWI_DDRAWSURFACE_GBL this_dest;
|
|
DWORD rc;
|
|
|
|
|
|
|
|
BOOL found_dest;
|
|
DDHAL_FLIPTOGDISURFACEDATA ftgsd;
|
|
LPDDHAL_FLIPTOGDISURFACE ftgshalfn;
|
|
LPDDHAL_FLIPTOGDISURFACE ftgsfn;
|
|
DDHAL_FLIPDATA fd;
|
|
LPDDHALSURFCB_FLIP fhalfn;
|
|
LPDDHALSURFCB_FLIP ffn;
|
|
BOOL emulation;
|
|
LPDDRAWI_DIRECTDRAW_LCL pdrv_lcl;
|
|
LPDDRAWI_DIRECTDRAW_GBL pdrv;
|
|
DWORD caps;
|
|
DWORD caps2;
|
|
DWORD dwNumSkipped;
|
|
DWORD dwCnt;
|
|
|
|
LPDDRAWI_DDRAWSURFACE_GBL_MORE lpSurfGblMore;
|
|
BOOL bStereo;
|
|
|
|
ENTER_BOTH();
|
|
|
|
DPF(2,A,"ENTERAPI: DD_Surface_Flip");
|
|
/* DPF_ENTERAPI(lpDDSurface); */
|
|
// 5/25/2000(RichGr): IA64: Use %p format specifier for 32/64-bit pointers.
|
|
DPF(3,A," Dest surface: 0x%p, flags: 0x%08x", lpDDSurfaceDest, dwFlags);
|
|
|
|
TRY
|
|
{
|
|
this_int = (LPDDRAWI_DDRAWSURFACE_INT) lpDDSurface;
|
|
if( !VALID_DIRECTDRAWSURFACE_PTR( this_int ) )
|
|
{
|
|
LEAVE_BOTH();
|
|
return DDERR_INVALIDOBJECT;
|
|
}
|
|
this_lcl = this_int->lpLcl;
|
|
this = this_lcl->lpGbl;
|
|
|
|
this_dest_int = (LPDDRAWI_DDRAWSURFACE_INT) lpDDSurfaceDest;
|
|
if( this_dest_int != NULL )
|
|
{
|
|
if( !VALID_DIRECTDRAWSURFACE_PTR( this_dest_int ) )
|
|
{
|
|
LEAVE_BOTH();
|
|
return DDERR_INVALIDOBJECT;
|
|
}
|
|
this_dest_lcl = this_dest_int->lpLcl;
|
|
this_dest = this_dest_lcl->lpGbl;
|
|
}
|
|
else
|
|
{
|
|
this_dest_lcl = NULL;
|
|
this_dest = NULL;
|
|
}
|
|
|
|
if( dwFlags & ~DDFLIP_VALID )
|
|
{
|
|
DPF_ERR( "Invalid flags") ;
|
|
LEAVE_BOTH();
|
|
return DDERR_INVALIDPARAMS;
|
|
}
|
|
|
|
if (!LOWERTHANSURFACE7(this_int))
|
|
{
|
|
if (dwFlags & DDFLIP_DONOTWAIT)
|
|
{
|
|
dwFlags &= ~DDFLIP_WAIT;
|
|
}
|
|
else
|
|
{
|
|
dwFlags |= DDFLIP_WAIT;
|
|
}
|
|
}
|
|
|
|
if( ( dwFlags & ( DDFLIP_EVEN | DDFLIP_ODD ) ) &&
|
|
!( this_lcl->ddsCaps.dwCaps & DDSCAPS_OVERLAY ) )
|
|
{
|
|
DPF_ERR( "Invalid flags") ;
|
|
LEAVE_BOTH();
|
|
return DDERR_INVALIDPARAMS;
|
|
}
|
|
|
|
if ( (dwFlags & DDFLIP_NOVSYNC) && (dwFlags & DDFLIP_INTERVALMASK) )
|
|
{
|
|
DPF_ERR( "Flip: DDFLIP_NOVSYNC and DDFLIP_INTERVALn are mutually exclusive") ;
|
|
LEAVE_BOTH();
|
|
return DDERR_INVALIDPARAMS;
|
|
}
|
|
|
|
pdrv_lcl = this_lcl->lpSurfMore->lpDD_lcl;
|
|
pdrv = pdrv_lcl->lpGbl;
|
|
#ifdef WIN95
|
|
if( !( pdrv_lcl->dwAppHackFlags & DDRAW_APPCOMPAT_SCREENSAVER ) ||
|
|
!( pdrv_lcl->dwLocalFlags & DDRAWILCL_POWEREDDOWN ) )
|
|
{
|
|
#endif
|
|
if( SURFACE_LOST( this_lcl ) )
|
|
{
|
|
LEAVE_BOTH();
|
|
return DDERR_SURFACELOST;
|
|
}
|
|
if( this_dest != NULL )
|
|
{
|
|
if( SURFACE_LOST( this_dest_lcl ) )
|
|
{
|
|
LEAVE_BOTH();
|
|
return DDERR_SURFACELOST;
|
|
}
|
|
}
|
|
#ifdef WIN95
|
|
}
|
|
#endif
|
|
|
|
/*
|
|
* device busy?
|
|
*/
|
|
|
|
#ifdef USE_ALIAS
|
|
if( pdrv->dwBusyDueToAliasedLock > 0 )
|
|
{
|
|
/*
|
|
* Aliased locks (the ones that don't take the Win16 lock) don't
|
|
* set the busy bit either (it can't or USER get's very confused).
|
|
* However, we must prevent blits happening via DirectDraw as
|
|
* otherwise we get into the old host talking to VRAM while
|
|
* blitter does at the same time. Bad. So fail if there is an
|
|
* outstanding aliased lock just as if the BUST bit had been
|
|
* set.
|
|
*/
|
|
DPF_ERR( "Graphics adapter is busy (due to a DirectDraw lock)" );
|
|
LEAVE_BOTH();
|
|
return DDERR_SURFACEBUSY;
|
|
}
|
|
#endif /* USE_ALIAS */
|
|
|
|
if( *(pdrv->lpwPDeviceFlags) & BUSY )
|
|
{
|
|
DPF( 0, "BUSY - Flip" );
|
|
LEAVE_BOTH()
|
|
return DDERR_SURFACEBUSY;
|
|
}
|
|
|
|
/*
|
|
* make sure that it's OK to flip this surface
|
|
*/
|
|
|
|
// DX7Stereo
|
|
if(dwFlags & DDFLIP_STEREO)
|
|
{
|
|
if (!(this_lcl->dwFlags & DDRAWISURF_STEREOSURFACELEFT))
|
|
{
|
|
DPF_ERR( "Invalid DDFLIP_STEREO flag on non stereo flipping chain") ;
|
|
LEAVE_BOTH();
|
|
return DDERR_INVALIDPARAMS;
|
|
}
|
|
}
|
|
|
|
if( !(this_lcl->ddsCaps.dwCaps & DDSCAPS_FRONTBUFFER) )
|
|
{
|
|
DPF_ERR("Can't flip because surface is not a front buffer");
|
|
LEAVE_BOTH();
|
|
return DDERR_NOTFLIPPABLE; // ACKACK: real error??
|
|
}
|
|
if( !(this_lcl->ddsCaps.dwCaps & DDSCAPS_FLIP) )
|
|
{
|
|
DPF_ERR("Can't flip because surface is not a DDSCAPS_FLIP surface");
|
|
LEAVE_BOTH();
|
|
return DDERR_NOTFLIPPABLE; // ACKACK: real error??
|
|
}
|
|
if( this->dwUsageCount > 0 )
|
|
{
|
|
DPF_ERR( "Can't flip because surface is locked" );
|
|
LEAVE_BOTH();
|
|
return DDERR_SURFACEBUSY;
|
|
}
|
|
if( (this_lcl->ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE) &&
|
|
(pdrv->lpExclusiveOwner != pdrv_lcl ) )
|
|
{
|
|
DPF_ERR( "Can't flip without exclusive access." );
|
|
LEAVE_BOTH();
|
|
return DDERR_NOEXCLUSIVEMODE;
|
|
}
|
|
}
|
|
EXCEPT( EXCEPTION_EXECUTE_HANDLER )
|
|
{
|
|
DPF_ERR( "Exception encountered validating parameters" );
|
|
LEAVE_BOTH();
|
|
return DDERR_INVALIDPARAMS;
|
|
}
|
|
|
|
/*
|
|
* Mip-map chain? In which case take special action.
|
|
*/
|
|
if( (this_lcl->ddsCaps.dwCaps & DDSCAPS_MIPMAP) &&
|
|
(0==(this_lcl->ddsCaps.dwCaps & DDSCAPS_OPTIMIZED)) )
|
|
{
|
|
rc = FlipMipMapChain( lpDDSurface, lpDDSurfaceDest, dwFlags );
|
|
LEAVE_BOTH();
|
|
return rc;
|
|
}
|
|
|
|
/*
|
|
* If this is the primary and the driver had previously flipped
|
|
* to display the GDI surface then we are now flipping away from
|
|
* the GDI surface so we need to let the driver know.
|
|
*/
|
|
if( ( this_lcl->ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE ) &&
|
|
( pdrv->dwFlags & DDRAWI_FLIPPEDTOGDI ) )
|
|
{
|
|
/*
|
|
* Notify the driver that we are about to flip away from the
|
|
* 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 = FALSE;
|
|
ftgsd.dwReserved = 0UL;
|
|
DOHALCALL( FlipToGDISurface, ftgsfn, ftgsd, rc, FALSE );
|
|
if( DDHAL_DRIVER_HANDLED == rc )
|
|
{
|
|
if( !FAILED( ftgsd.ddRVal ) )
|
|
{
|
|
/*
|
|
* Driver is no longer flipped to the GDI surface.
|
|
*/
|
|
pdrv->dwFlags &= ~DDRAWI_FLIPPEDTOGDI;
|
|
DPF( 4, "Driver handled the flip away from the GDI surface" );
|
|
LEAVE_BOTH();
|
|
return ftgsd.ddRVal;
|
|
}
|
|
else
|
|
{
|
|
DPF_ERR( "Driver failed the flip away from the GDI surface" );
|
|
LEAVE_BOTH();
|
|
return ftgsd.ddRVal;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/*
|
|
* make sure no surfaces are in use
|
|
*/
|
|
found_dest = FALSE;
|
|
if( ( lpDDSurface == lpDDSurfaceDest ) &&
|
|
( dwFlags & (DDFLIP_EVEN | DDFLIP_ODD) ) )
|
|
{
|
|
next_save_int = next_int = this_int;
|
|
dwCnt = dwNumSkipped = 0;
|
|
}
|
|
else
|
|
{
|
|
next_save_int = next_int = FindAttachedFlip( this_int );
|
|
dwCnt = dwNumSkipped = 1;
|
|
}
|
|
if( next_int == NULL )
|
|
{
|
|
DPF_ERR("Can't flip: No attached flippable surface");
|
|
LEAVE_BOTH();
|
|
return DDERR_NOTFLIPPABLE; // ACKACK: real error?
|
|
}
|
|
|
|
do
|
|
{
|
|
if( SURFACE_LOST( next_int->lpLcl ) )
|
|
{
|
|
DPF_ERR( "Can't flip - back buffer is lost" );
|
|
LEAVE_BOTH();
|
|
return DDERR_SURFACELOST;
|
|
}
|
|
|
|
if( next_int->lpLcl->lpGbl->dwUsageCount != 0 )
|
|
{
|
|
/*
|
|
* Previously we didn't allow Flips to suceed if any of the surfaces
|
|
* are lost, but DShow really wants to be able to do this so now we'll
|
|
* allow it as long as we aren't going to rotate the memory pointers, etc.
|
|
* for the locked surface.
|
|
*/
|
|
if( ( this_dest_lcl == NULL ) ||
|
|
( this_dest_lcl == next_int->lpLcl ) ||
|
|
( this_lcl == next_int->lpLcl ) )
|
|
{
|
|
LEAVE_BOTH();
|
|
return DDERR_SURFACEBUSY;
|
|
}
|
|
}
|
|
|
|
/*
|
|
* Do not allow flipping if any of the surfaces are used in kernel
|
|
* mode because we don't want the pointers to rotate.
|
|
*/
|
|
lpSurfGblMore = GET_LPDDRAWSURFACE_GBL_MORE( next_int->lpLcl->lpGbl );
|
|
if( lpSurfGblMore->hKernelSurface != 0 )
|
|
{
|
|
DPF_ERR( "Can't flip - kernel mode is using surface" );
|
|
LEAVE_BOTH();
|
|
return DDERR_SURFACEBUSY;
|
|
}
|
|
|
|
/*
|
|
* NOTE: Do NOT compare interface pointers here as we may
|
|
* well have multiple interfaces to the same surface object (i.e.,
|
|
* V1, V2, V3 etc.). Compare against the LOCAL object. This is the
|
|
* real object being handled.
|
|
*/
|
|
if( ( NULL != this_dest_int ) && ( this_dest_int->lpLcl == next_int->lpLcl ) )
|
|
{
|
|
dwNumSkipped = dwCnt;
|
|
found_dest = TRUE;
|
|
}
|
|
dwCnt++;
|
|
next_int = FindAttachedFlip( next_int );
|
|
} while( next_int->lpLcl != this_int->lpLcl );
|
|
|
|
/*
|
|
* see if we can use the specified destination
|
|
*/
|
|
if( this_dest_int != NULL )
|
|
{
|
|
if( !found_dest )
|
|
{
|
|
DPF_ERR( "Destination not part of flipping chain!" );
|
|
LEAVE_BOTH();
|
|
return DDERR_NOTFLIPPABLE; // ACKACK: real error?
|
|
}
|
|
next_save_int = this_dest_int;
|
|
}
|
|
|
|
/*
|
|
* found the linked surface we want to flip to
|
|
*/
|
|
next_int = next_save_int;
|
|
|
|
/*
|
|
* don't allow two destinations to be different (in case of a mixed chain)
|
|
*/
|
|
next_lcl = next_int->lpLcl;
|
|
if( ((next_lcl->ddsCaps.dwCaps & DDSCAPS_SYSTEMMEMORY) &&
|
|
(this_lcl->ddsCaps.dwCaps & DDSCAPS_VIDEOMEMORY)) ||
|
|
((next_lcl->ddsCaps.dwCaps & DDSCAPS_VIDEOMEMORY) &&
|
|
(this_lcl->ddsCaps.dwCaps & DDSCAPS_SYSTEMMEMORY)) )
|
|
{
|
|
DPF_ERR( "Can't flip between video/system memory surfaces" );
|
|
LEAVE_BOTH();
|
|
return DDERR_INVALIDPARAMS;
|
|
}
|
|
|
|
// DPF(9," flip (%d) Source Kernel handle is %08x, dest is %08x",__LINE__,this_lcl->hDDSurface,next_lcl->hDDSurface);
|
|
// DPF(9," flip source vidmem is %08x, dest is %08x",this->fpVidMem,next_lcl->lpGbl->fpVidMem);
|
|
/*
|
|
* is this an emulation surface or driver surface?
|
|
*/
|
|
if( (this_lcl->ddsCaps.dwCaps & DDSCAPS_SYSTEMMEMORY) )
|
|
{
|
|
ffn = pdrv_lcl->lpDDCB->HELDDSurface.Flip;
|
|
fhalfn = ffn;
|
|
emulation = TRUE;
|
|
caps = pdrv->ddHELCaps.dwCaps;
|
|
caps2 = pdrv->ddHELCaps.dwCaps2;
|
|
}
|
|
else
|
|
{
|
|
ffn = pdrv_lcl->lpDDCB->HALDDSurface.Flip;
|
|
fhalfn = pdrv_lcl->lpDDCB->cbDDSurfaceCallbacks.Flip;
|
|
emulation = FALSE;
|
|
caps = pdrv->ddCaps.dwCaps;
|
|
caps2 = pdrv->ddCaps.dwCaps2;
|
|
}
|
|
|
|
/*
|
|
* If the surface is fed by a video port, also flip the video port
|
|
*/
|
|
if( ( this_lcl->ddsCaps.dwCaps & DDSCAPS_VIDEOPORT) && dwNumSkipped )
|
|
{
|
|
rc = FlipVideoPortSurface( this_int, dwNumSkipped );
|
|
if( rc != DD_OK )
|
|
{
|
|
LEAVE_BOTH();
|
|
return DDERR_INVALIDPARAMS;
|
|
}
|
|
}
|
|
|
|
#ifdef WINNT
|
|
/*
|
|
* If ~ 50 seconds have passed (assuming a 10Hz flip rate)
|
|
* and this is a primary surface, then make a magic call to
|
|
* disable screen savers.
|
|
* This isn't needed on 9x since we make a SPI call on that OS
|
|
* to disable screen savers.
|
|
* We don't do this if the app is itself a screen-saver, since
|
|
* that would also disable the power-down.
|
|
*/
|
|
if( !( pdrv_lcl->dwAppHackFlags & DDRAW_APPCOMPAT_SCREENSAVER ))
|
|
{
|
|
if (this_lcl->ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE )
|
|
{
|
|
static DWORD dwMagicTime = 0;
|
|
dwMagicTime++;
|
|
if (dwMagicTime > (50*10) )
|
|
{
|
|
DWORD dw=60*15;
|
|
dwMagicTime = 0;
|
|
SystemParametersInfo(SPI_GETSCREENSAVETIMEOUT,0,&dw,0);
|
|
SystemParametersInfo(SPI_SETSCREENSAVETIMEOUT,dw,0,0);
|
|
}
|
|
}
|
|
}
|
|
#endif
|
|
|
|
/*
|
|
* Driver should be told its cache is invalid if the surface was flipped
|
|
*/
|
|
BUMP_SURFACE_STAMP(this);
|
|
BUMP_SURFACE_STAMP(next_lcl->lpGbl);
|
|
|
|
/*
|
|
* ask the driver to flip to the new surface if we are flipping
|
|
* a primary surface (or if we are flipping an overlay surface and
|
|
* the driver supports overlays.)
|
|
*/
|
|
|
|
bStereo = (BOOL) (this_lcl->dwFlags & DDRAWISURF_STEREOSURFACELEFT);
|
|
|
|
if( ( this_lcl->ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE ) ||
|
|
( ( this_lcl->ddsCaps.dwCaps & DDSCAPS_OVERLAY ) &&
|
|
( caps & DDCAPS_OVERLAY ) &&
|
|
( this_lcl->ddsCaps.dwCaps & DDSCAPS_VISIBLE ) ) )
|
|
{
|
|
if( fhalfn != NULL )
|
|
{
|
|
fd.Flip = fhalfn;
|
|
fd.lpDD = pdrv;
|
|
fd.dwFlags = (dwFlags & ~DDFLIP_WAIT);
|
|
fd.lpSurfCurr = this_lcl;
|
|
fd.lpSurfTarg = next_lcl;
|
|
|
|
// DX7Stereo
|
|
fd.lpSurfCurrLeft = NULL;
|
|
fd.lpSurfTargLeft = NULL;
|
|
|
|
if (bStereo &&
|
|
fd.dwFlags & DDFLIP_STEREO )
|
|
{
|
|
LPDDRAWI_DDRAWSURFACE_INT temp_this_int;
|
|
LPDDRAWI_DDRAWSURFACE_INT temp_next_int;
|
|
temp_this_int = FindAttachedSurfaceLeft(this_int);
|
|
temp_next_int = FindAttachedSurfaceLeft(next_int);
|
|
// oops, error
|
|
if (temp_this_int!=NULL && temp_next_int!=NULL)
|
|
{
|
|
fd.lpSurfCurrLeft = temp_this_int->lpLcl;
|
|
fd.lpSurfTargLeft = temp_next_int->lpLcl;
|
|
|
|
}
|
|
|
|
if (fd.lpSurfCurrLeft==NULL || fd.lpSurfTargLeft==NULL)
|
|
{
|
|
fd.lpSurfCurrLeft = NULL;
|
|
fd.lpSurfTargLeft = NULL;
|
|
|
|
fd.dwFlags &= ~DDFLIP_STEREO;
|
|
}
|
|
|
|
}
|
|
if (DDRAW_REGFLAGS_FLIPNONVSYNC & dwRegFlags)
|
|
{
|
|
fd.dwFlags &= ~DDFLIP_INTERVALMASK;
|
|
fd.dwFlags |= DDFLIP_NOVSYNC;
|
|
}
|
|
if (caps2 & DDCAPS2_FLIPINTERVAL)
|
|
{
|
|
//if the user didn't specify a flip interval, give the driver 'one'
|
|
//Also, make the interval consistent with FLIPNOVSYNC: if FLIPNOVSYNC is set,
|
|
//then we should keep the interval set to 0.
|
|
if ( ((fd.dwFlags & DDFLIP_INTERVALMASK) == 0) && ((dwFlags & DDFLIP_NOVSYNC)==0) )
|
|
{
|
|
fd.dwFlags |= DDFLIP_INTERVAL1;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
//don't let old drivers see the flip intervals
|
|
fd.dwFlags &= ~DDFLIP_INTERVALMASK;
|
|
}
|
|
|
|
//don't let old drivers see novsync
|
|
if ( (caps2 & DDCAPS2_FLIPNOVSYNC) == 0 )
|
|
{
|
|
fd.dwFlags &= ~DDFLIP_NOVSYNC;
|
|
}
|
|
|
|
try_again:
|
|
DOHALCALL_NOWIN16( Flip, ffn, fd, rc, emulation );
|
|
if( rc == DDHAL_DRIVER_HANDLED )
|
|
{
|
|
if( fd.ddRVal != DD_OK )
|
|
{
|
|
if( (dwFlags & DDFLIP_WAIT) && fd.ddRVal == DDERR_WASSTILLDRAWING )
|
|
{
|
|
DPF(4,"Waiting.....");
|
|
goto try_again;
|
|
}
|
|
LEAVE_BOTH();
|
|
return fd.ddRVal;
|
|
}
|
|
|
|
/*
|
|
* emulation, does not need the pointers rotated we are done
|
|
*
|
|
* NOTE we should do this with a special return code or
|
|
* even a rester cap, but for now this is as good as any.
|
|
*/
|
|
if( emulation )
|
|
{
|
|
LEAVE_WIN16LOCK();
|
|
if( dwRegFlags & DDRAW_REGFLAGS_SHOWFRAMERATE )
|
|
{
|
|
updateFrameRate();
|
|
}
|
|
LEAVE_DDRAW();
|
|
return DD_OK;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
LEAVE_BOTH();
|
|
return DDERR_NOFLIPHW;
|
|
}
|
|
}
|
|
|
|
/*
|
|
* save the old values
|
|
*/
|
|
|
|
if( dwNumSkipped )
|
|
{
|
|
#ifdef USE_ALIAS
|
|
FLATPTR aliasvidmem;
|
|
FLATPTR aliasofvidmem;
|
|
#endif /* USE_ALIAS */
|
|
FLATPTR vidmem;
|
|
LPVMEMHEAP vidmemheap;
|
|
FLATPTR physicalvidmem;
|
|
ULONG_PTR driverreserved;
|
|
ULONG_PTR reserved;
|
|
DWORD gdi_flag;
|
|
ULONG_PTR handle;
|
|
// same stack for left surface if we rotate stereo buffers
|
|
#ifdef USE_ALIAS
|
|
FLATPTR leftaliasvidmem;
|
|
FLATPTR leftaliasofvidmem;
|
|
#endif /* USE_ALIAS */
|
|
FLATPTR leftvidmem;
|
|
LPVMEMHEAP leftvidmemheap;
|
|
FLATPTR leftphysicalvidmem;
|
|
ULONG_PTR leftdriverreserved;
|
|
DWORD leftgdi_flag;
|
|
ULONG_PTR leftreserved;
|
|
ULONG_PTR lefthandle;
|
|
|
|
DWORD dwSurfaceHandle;
|
|
DWORD dwLeftSurfaceHandle;
|
|
|
|
|
|
LPDDRAWI_DDRAWSURFACE_INT next_left_int;
|
|
LPDDRAWI_DDRAWSURFACE_LCL next_left_lcl;
|
|
|
|
|
|
|
|
DPF(4,"Flip:rotating pointers etc");
|
|
vidmem = next_lcl->lpGbl->fpVidMem;
|
|
#ifdef USE_ALIAS
|
|
aliasvidmem = GBLMORE(next_lcl->lpGbl)->fpAliasedVidMem;
|
|
aliasofvidmem = GBLMORE(next_lcl->lpGbl)->fpAliasOfVidMem;
|
|
#endif /* USE_ALIAS */
|
|
physicalvidmem = GBLMORE(next_lcl->lpGbl)->fpPhysicalVidMem;
|
|
driverreserved = GBLMORE(next_lcl->lpGbl)->dwDriverReserved;
|
|
vidmemheap = next_lcl->lpGbl->lpVidMemHeap;
|
|
reserved = next_lcl->lpGbl->dwReserved1;
|
|
gdi_flag = next_lcl->lpGbl->dwGlobalFlags & DDRAWISURFGBL_ISGDISURFACE;
|
|
handle = next_lcl->hDDSurface;
|
|
dwSurfaceHandle = next_lcl->lpSurfMore->dwSurfaceHandle;
|
|
// DX7Stereo: save also left buffers
|
|
if (bStereo)
|
|
{
|
|
|
|
DPF(4,"Flip:rotating also stereo pointers etc");
|
|
|
|
next_left_int = FindAttachedSurfaceLeft(next_int);
|
|
if (next_left_int!=NULL)
|
|
{
|
|
next_left_lcl = next_left_int->lpLcl;
|
|
|
|
|
|
leftvidmem = next_left_lcl->lpGbl->fpVidMem;
|
|
#ifdef USE_ALIAS
|
|
leftaliasvidmem = GBLMORE(next_left_lcl->lpGbl)->fpAliasedVidMem;
|
|
leftaliasofvidmem = GBLMORE(next_left_lcl->lpGbl)->fpAliasOfVidMem;
|
|
#endif /* USE_ALIAS */
|
|
leftphysicalvidmem = GBLMORE(next_left_lcl->lpGbl)->fpPhysicalVidMem;
|
|
leftdriverreserved = GBLMORE(next_left_lcl->lpGbl)->dwDriverReserved;
|
|
leftvidmemheap = next_left_lcl->lpGbl->lpVidMemHeap;
|
|
leftreserved = next_left_lcl->lpGbl->dwReserved1;
|
|
leftgdi_flag = next_left_lcl->lpGbl->dwGlobalFlags & DDRAWISURFGBL_ISGDISURFACE;
|
|
lefthandle = next_left_lcl->hDDSurface;
|
|
dwLeftSurfaceHandle = next_left_lcl->lpSurfMore->dwSurfaceHandle;
|
|
|
|
} else
|
|
{
|
|
DPF(0,"Flip:rotating stereo pointers failed, dest. left surfaces invalid");
|
|
bStereo=FALSE;
|
|
}
|
|
}
|
|
|
|
/*
|
|
* set the new primary surface pointer
|
|
*/
|
|
if( this_lcl->ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE )
|
|
{
|
|
pdrv->vmiData.fpPrimary = vidmem;
|
|
}
|
|
|
|
/*
|
|
* rotate the memory pointers
|
|
*/
|
|
if( this_dest_lcl != NULL )
|
|
{
|
|
next_lcl->lpGbl->lpVidMemHeap = this->lpVidMemHeap;
|
|
next_lcl->lpGbl->fpVidMem = this->fpVidMem;
|
|
#ifdef USE_ALIAS
|
|
GBLMORE(next_lcl->lpGbl)->fpAliasedVidMem = GBLMORE(this)->fpAliasedVidMem;
|
|
GBLMORE(next_lcl->lpGbl)->fpAliasOfVidMem = GBLMORE(this)->fpAliasOfVidMem;
|
|
#endif /* USE_ALIAS */
|
|
GBLMORE(next_lcl->lpGbl)->fpPhysicalVidMem = GBLMORE(this)->fpPhysicalVidMem;
|
|
GBLMORE(next_lcl->lpGbl)->dwDriverReserved = GBLMORE(this)->dwDriverReserved;
|
|
next_lcl->lpGbl->dwReserved1 = this->dwReserved1;
|
|
next_lcl->lpGbl->dwGlobalFlags &= ~DDRAWISURFGBL_ISGDISURFACE;
|
|
next_lcl->lpGbl->dwGlobalFlags |= this->dwGlobalFlags & DDRAWISURFGBL_ISGDISURFACE;
|
|
next_lcl->hDDSurface = this_lcl->hDDSurface;
|
|
next_lcl->lpSurfMore->dwSurfaceHandle = this_lcl->lpSurfMore->dwSurfaceHandle;
|
|
|
|
if (this_lcl->lpSurfMore->dwSurfaceHandle)
|
|
{
|
|
// Since the SurfaceHandle was updated, update the mapping array
|
|
SURFACEHANDLELIST(pdrv_lcl).dwList[this_lcl->lpSurfMore->dwSurfaceHandle].lpSurface = next_lcl;
|
|
}
|
|
if (bStereo)
|
|
{
|
|
LPDDRAWI_DDRAWSURFACE_INT this_left_int;
|
|
LPDDRAWI_DDRAWSURFACE_LCL this_left_lcl;
|
|
|
|
this_left_int = FindAttachedSurfaceLeft(this_int);
|
|
this_left_lcl = this_left_int->lpLcl;
|
|
|
|
next_left_lcl->lpGbl->lpVidMemHeap = this_left_lcl->lpGbl->lpVidMemHeap;
|
|
next_left_lcl->lpGbl->fpVidMem = this_left_lcl->lpGbl->fpVidMem;
|
|
#ifdef USE_ALIAS
|
|
GBLMORE(next_left_lcl->lpGbl)->fpAliasedVidMem = GBLMORE(this_left_lcl->lpGbl)->fpAliasedVidMem;
|
|
GBLMORE(next_left_lcl->lpGbl)->fpAliasOfVidMem = GBLMORE(this_left_lcl->lpGbl)->fpAliasOfVidMem;
|
|
#endif /* USE_ALIAS */
|
|
GBLMORE(next_left_lcl->lpGbl)->fpPhysicalVidMem = GBLMORE(this_left_lcl->lpGbl)->fpPhysicalVidMem;
|
|
GBLMORE(next_left_lcl->lpGbl)->dwDriverReserved = GBLMORE(this_left_lcl->lpGbl)->dwDriverReserved;
|
|
next_left_lcl->lpGbl->dwGlobalFlags &= ~DDRAWISURFGBL_ISGDISURFACE;
|
|
next_left_lcl->lpGbl->dwGlobalFlags |= this_left_lcl->lpGbl->dwGlobalFlags & DDRAWISURFGBL_ISGDISURFACE;
|
|
next_left_lcl->lpGbl->dwReserved1 = this_left_lcl->lpGbl->dwReserved1;
|
|
next_left_lcl->hDDSurface = this_left_lcl->hDDSurface;
|
|
next_left_lcl->lpSurfMore->dwSurfaceHandle = this_left_lcl->lpSurfMore->dwSurfaceHandle;
|
|
if (this_left_lcl->lpSurfMore->dwSurfaceHandle)
|
|
{
|
|
// Since the SurfaceHandle was updated, update the mapping array
|
|
SURFACEHANDLELIST(pdrv_lcl).dwList[this_left_lcl->lpSurfMore->dwSurfaceHandle].lpSurface = next_left_lcl;
|
|
}
|
|
}
|
|
|
|
}
|
|
else
|
|
{
|
|
do
|
|
{
|
|
attached_int = FindAttachedFlip( next_int );
|
|
next_lcl = next_int->lpLcl;
|
|
next_lcl->lpGbl->lpVidMemHeap = attached_int->lpLcl->lpGbl->lpVidMemHeap;
|
|
next_lcl->lpGbl->fpVidMem = attached_int->lpLcl->lpGbl->fpVidMem;
|
|
#ifdef USE_ALIAS
|
|
GBLMORE(next_lcl->lpGbl)->fpAliasedVidMem = GBLMORE(attached_int->lpLcl->lpGbl)->fpAliasedVidMem;
|
|
GBLMORE(next_lcl->lpGbl)->fpAliasOfVidMem = GBLMORE(attached_int->lpLcl->lpGbl)->fpAliasOfVidMem;
|
|
#endif /* USE_ALIAS */
|
|
GBLMORE(next_lcl->lpGbl)->fpPhysicalVidMem = GBLMORE(attached_int->lpLcl->lpGbl)->fpPhysicalVidMem;
|
|
GBLMORE(next_lcl->lpGbl)->dwDriverReserved = GBLMORE(attached_int->lpLcl->lpGbl)->dwDriverReserved;
|
|
next_lcl->lpGbl->dwReserved1 = attached_int->lpLcl->lpGbl->dwReserved1;
|
|
next_lcl->lpGbl->dwGlobalFlags &= ~DDRAWISURFGBL_ISGDISURFACE;
|
|
next_lcl->lpGbl->dwGlobalFlags |= attached_int->lpLcl->lpGbl->dwGlobalFlags & DDRAWISURFGBL_ISGDISURFACE;
|
|
next_lcl->hDDSurface = attached_int->lpLcl->hDDSurface;
|
|
next_lcl->lpSurfMore->dwSurfaceHandle = attached_int->lpLcl->lpSurfMore->dwSurfaceHandle;
|
|
if (attached_int->lpLcl->lpSurfMore->dwSurfaceHandle)
|
|
{
|
|
// Since the SurfaceHandle was updated, update the mapping array
|
|
SURFACEHANDLELIST(pdrv_lcl).dwList[attached_int->lpLcl->lpSurfMore->dwSurfaceHandle].lpSurface = next_lcl;
|
|
}
|
|
if (bStereo)
|
|
{
|
|
LPDDRAWI_DDRAWSURFACE_INT attached_left_int;
|
|
LPDDRAWI_DDRAWSURFACE_LCL attached_left_lcl;
|
|
|
|
attached_left_int = FindAttachedSurfaceLeft(attached_int);
|
|
next_left_int = FindAttachedSurfaceLeft(next_int);
|
|
if (attached_left_int!=NULL && next_left_int!=NULL)
|
|
{
|
|
attached_left_lcl=attached_left_int->lpLcl;
|
|
next_left_lcl=next_left_int->lpLcl;
|
|
|
|
next_left_lcl->lpGbl->lpVidMemHeap = attached_left_int->lpLcl->lpGbl->lpVidMemHeap;
|
|
next_left_lcl->lpGbl->fpVidMem = attached_left_int->lpLcl->lpGbl->fpVidMem;
|
|
#ifdef USE_ALIAS
|
|
GBLMORE(next_left_lcl->lpGbl)->fpAliasedVidMem = GBLMORE(attached_left_int->lpLcl->lpGbl)->fpAliasedVidMem;
|
|
GBLMORE(next_left_lcl->lpGbl)->fpAliasOfVidMem = GBLMORE(attached_left_int->lpLcl->lpGbl)->fpAliasOfVidMem;
|
|
#endif /* USE_ALIAS */
|
|
GBLMORE(next_left_lcl->lpGbl)->fpPhysicalVidMem = GBLMORE(attached_left_int->lpLcl->lpGbl)->fpPhysicalVidMem;
|
|
GBLMORE(next_left_lcl->lpGbl)->dwDriverReserved = GBLMORE(attached_left_int->lpLcl->lpGbl)->dwDriverReserved;
|
|
next_left_lcl->lpGbl->dwReserved1 = attached_left_int->lpLcl->lpGbl->dwReserved1;
|
|
next_left_lcl->lpGbl->dwGlobalFlags &= ~DDRAWISURFGBL_ISGDISURFACE;
|
|
next_left_lcl->lpGbl->dwGlobalFlags |= attached_left_int->lpLcl->lpGbl->dwGlobalFlags & DDRAWISURFGBL_ISGDISURFACE;
|
|
next_left_lcl->hDDSurface = attached_left_int->lpLcl->hDDSurface;
|
|
next_left_lcl->lpSurfMore->dwSurfaceHandle = attached_left_int->lpLcl->lpSurfMore->dwSurfaceHandle;
|
|
if (attached_left_int->lpLcl->lpSurfMore->dwSurfaceHandle)
|
|
{
|
|
// Since the SurfaceHandle was updated, update the mapping array
|
|
SURFACEHANDLELIST(pdrv_lcl).dwList[attached_left_int->lpLcl->lpSurfMore->dwSurfaceHandle].lpSurface =
|
|
next_left_lcl;
|
|
}
|
|
} else
|
|
{
|
|
DPF(0,"Flip:left surface pointers corrupted");
|
|
bStereo=FALSE;
|
|
}
|
|
}
|
|
|
|
next_int = attached_int;
|
|
/*
|
|
* NOTE: Again, do NOT compare against interface pointers. We may
|
|
* have multiple interfaces to a single surface object leading to
|
|
* an infinite loop. Compare against the LOCAL object not the
|
|
* interface pointers.
|
|
*/
|
|
} while( next_int->lpLcl != this_int->lpLcl );
|
|
}
|
|
this->fpVidMem = vidmem;
|
|
#ifdef USE_ALIAS
|
|
GBLMORE(this)->fpAliasedVidMem = aliasvidmem;
|
|
GBLMORE(this)->fpAliasOfVidMem = aliasofvidmem;
|
|
#endif /* USE_ALIAS */
|
|
GBLMORE(this)->fpPhysicalVidMem = physicalvidmem;
|
|
GBLMORE(this)->dwDriverReserved = driverreserved;
|
|
this->lpVidMemHeap = vidmemheap;
|
|
this->dwReserved1 = reserved;
|
|
this->dwGlobalFlags &= ~DDRAWISURFGBL_ISGDISURFACE;
|
|
this->dwGlobalFlags |= gdi_flag;
|
|
this_lcl->hDDSurface = handle;
|
|
this_lcl->lpSurfMore->dwSurfaceHandle=dwSurfaceHandle;
|
|
|
|
if (dwSurfaceHandle)
|
|
{
|
|
// Since the SurfaceHandle was updated, update the mapping array
|
|
SURFACEHANDLELIST(pdrv_lcl).dwList[dwSurfaceHandle].lpSurface = this_lcl;
|
|
}
|
|
if (bStereo)
|
|
{
|
|
LPDDRAWI_DDRAWSURFACE_INT this_left_int;
|
|
LPDDRAWI_DDRAWSURFACE_LCL this_left_lcl;
|
|
|
|
this_left_int = FindAttachedSurfaceLeft(this_int);
|
|
if (this_left_int!=NULL)
|
|
{
|
|
this_left_lcl = this_left_int->lpLcl;
|
|
|
|
this_left_lcl->lpGbl->fpVidMem = leftvidmem;
|
|
#ifdef USE_ALIAS
|
|
GBLMORE(this_left_lcl->lpGbl)->fpAliasedVidMem = leftaliasvidmem;
|
|
GBLMORE(this_left_lcl->lpGbl)->fpAliasOfVidMem = leftaliasofvidmem;
|
|
#endif /* USE_ALIAS */
|
|
GBLMORE(this_left_lcl->lpGbl)->fpPhysicalVidMem = leftphysicalvidmem;
|
|
GBLMORE(this_left_lcl->lpGbl)->dwDriverReserved = leftdriverreserved;
|
|
this_left_lcl->lpGbl->lpVidMemHeap = leftvidmemheap;
|
|
this_left_lcl->lpGbl->dwReserved1 = leftreserved;
|
|
this_left_lcl->lpGbl->dwGlobalFlags &= ~DDRAWISURFGBL_ISGDISURFACE;
|
|
this_left_lcl->lpGbl->dwGlobalFlags |= leftgdi_flag;
|
|
this_left_lcl->hDDSurface = lefthandle;
|
|
this_left_lcl->lpSurfMore->dwSurfaceHandle=dwLeftSurfaceHandle;
|
|
if (dwLeftSurfaceHandle)
|
|
{
|
|
// Since the SurfaceHandle was updated, update the mapping array
|
|
SURFACEHANDLELIST(pdrv_lcl).dwList[dwLeftSurfaceHandle].lpSurface = this_left_lcl;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
if ((GetCurrentProcessId() == GETCURRPID()) &&
|
|
(pdrv_lcl->pSurfaceFlipNotify))
|
|
{
|
|
DDASSERT(pdrv_lcl->pD3DIUnknown != NULL);
|
|
pdrv_lcl->pSurfaceFlipNotify(pdrv_lcl->pD3DIUnknown);
|
|
}
|
|
|
|
/*
|
|
* If the driver was flipped to the GDI surface and we just flipped the
|
|
* primary chain then we are no longer showing the GDI surface.
|
|
*/
|
|
if( ( this_lcl->ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE ) &&
|
|
( pdrv->dwFlags & DDRAWI_FLIPPEDTOGDI ) )
|
|
{
|
|
pdrv->dwFlags &= ~DDRAWI_FLIPPEDTOGDI;
|
|
}
|
|
|
|
LEAVE_WIN16LOCK();
|
|
if( dwRegFlags & DDRAW_REGFLAGS_SHOWFRAMERATE )
|
|
{
|
|
updateFrameRate();
|
|
}
|
|
LEAVE_DDRAW();
|
|
return DD_OK;
|
|
|
|
} /* DD_Surface_Flip */
|
|
|
|
#undef DPF_MODNAME
|
|
#define DPF_MODNAME "GetPixelFormat"
|
|
|
|
/*
|
|
* DD_Surface_GetPixelFormat
|
|
*/
|
|
HRESULT DDAPI DD_Surface_GetPixelFormat(
|
|
LPDIRECTDRAWSURFACE lpDDSurface,
|
|
LPDDPIXELFORMAT lpDDPixelFormat )
|
|
{
|
|
LPDDRAWI_DDRAWSURFACE_INT this_int;
|
|
LPDDRAWI_DDRAWSURFACE_LCL this_lcl;
|
|
LPDDRAWI_DDRAWSURFACE_GBL this;
|
|
LPDDPIXELFORMAT pddpf;
|
|
|
|
ENTER_DDRAW();
|
|
|
|
DPF(2,A,"ENTERAPI: DD_Surface_GetPixelFormat");
|
|
|
|
TRY
|
|
{
|
|
this_int = (LPDDRAWI_DDRAWSURFACE_INT) lpDDSurface;
|
|
if( !VALID_DIRECTDRAWSURFACE_PTR( this_int ) )
|
|
{
|
|
LEAVE_DDRAW();
|
|
return DDERR_INVALIDOBJECT;
|
|
}
|
|
this_lcl = this_int->lpLcl;
|
|
if( !VALID_DDPIXELFORMAT_PTR( lpDDPixelFormat ) )
|
|
{
|
|
LEAVE_DDRAW();
|
|
return DDERR_INVALIDPARAMS;
|
|
}
|
|
/*
|
|
* Execute buffers don't have a pixel format.
|
|
*/
|
|
if( this_lcl->ddsCaps.dwCaps & DDSCAPS_EXECUTEBUFFER )
|
|
{
|
|
DPF_ERR( "Invalid surface type: can't get pixel format" );
|
|
LEAVE_DDRAW();
|
|
return DDERR_INVALIDSURFACETYPE;
|
|
}
|
|
this = this_lcl->lpGbl;
|
|
GET_PIXEL_FORMAT( this_lcl, this, pddpf );
|
|
*lpDDPixelFormat = *pddpf;
|
|
}
|
|
EXCEPT( EXCEPTION_EXECUTE_HANDLER )
|
|
{
|
|
DPF_ERR( "Exception encountered validating parameters" );
|
|
LEAVE_DDRAW();
|
|
return DDERR_INVALIDPARAMS;
|
|
}
|
|
LEAVE_DDRAW();
|
|
return DD_OK;
|
|
|
|
} /* DD_Surface_GetPixelFormat */
|
|
|
|
#if 0
|
|
/* GEE: removed this, obsolete */
|
|
/*
|
|
* DD_Surface_SetCompression
|
|
*/
|
|
HRESULT DDAPI DD_Surface_SetCompression(
|
|
LPDIRECTDRAWSURFACE lpDDSurface,
|
|
LPDDPIXELFORMAT lpDDPixelFormat )
|
|
{
|
|
LPDDRAWI_DDRAWSURFACE_LCL this_lcl;
|
|
LPDDRAWI_DDRAWSURFACE_GBL this;
|
|
|
|
ENTER_DDRAW();
|
|
|
|
DPF(2,A,"ENTERAPI: DD_Surface_SetCompression");
|
|
|
|
TRY
|
|
{
|
|
this_lcl = (LPDDRAWI_DDRAWSURFACE_LCL) lpDDSurface;
|
|
if( !VALID_DIRECTDRAWSURFACE_PTR( this_lcl ) )
|
|
{
|
|
LEAVE_DDRAW();
|
|
return DDERR_INVALIDOBJECT;
|
|
}
|
|
if( !VALID_DDPIXELFORMAT_PTR( lpDDPixelFormat ) )
|
|
{
|
|
LEAVE_DDRAW();
|
|
return DDERR_INVALIDPARAMS;
|
|
}
|
|
this = this_lcl->lpGbl;
|
|
}
|
|
EXCEPT( EXCEPTION_EXECUTE_HANDLER )
|
|
{
|
|
DPF_ERR( "Exception encountered validating parameters" );
|
|
LEAVE_DDRAW();
|
|
return DDERR_INVALIDPARAMS;
|
|
}
|
|
|
|
LEAVE_DDRAW();
|
|
return DDERR_UNSUPPORTED;
|
|
|
|
} /* DD_Surface_SetCompression */
|
|
#endif
|
|
|
|
#undef DPF_MODNAME
|
|
#define DPF_MODNAME "GetSurfaceDesc"
|
|
|
|
/*
|
|
* DD_Surface_GetSurfaceDesc
|
|
*/
|
|
HRESULT DDAPI DD_Surface_GetSurfaceDesc(
|
|
LPDIRECTDRAWSURFACE lpDDSurface,
|
|
LPDDSURFACEDESC lpDDSurfaceDesc )
|
|
{
|
|
LPDDRAWI_DDRAWSURFACE_INT this_int;
|
|
LPDDRAWI_DDRAWSURFACE_LCL this_lcl;
|
|
LPDDRAWI_DDRAWSURFACE_GBL this;
|
|
|
|
ENTER_DDRAW();
|
|
|
|
DPF(2,A,"ENTERAPI: DD_Surface_GetSurfaceDesc");
|
|
|
|
TRY
|
|
{
|
|
this_int = (LPDDRAWI_DDRAWSURFACE_INT) lpDDSurface;
|
|
if( !VALID_DIRECTDRAWSURFACE_PTR( this_int ) )
|
|
{
|
|
LEAVE_DDRAW();
|
|
return DDERR_INVALIDOBJECT;
|
|
}
|
|
this_lcl = this_int->lpLcl;
|
|
if( !VALID_DDSURFACEDESC_PTR( lpDDSurfaceDesc ) )
|
|
{
|
|
LEAVE_DDRAW();
|
|
return DDERR_INVALIDPARAMS;
|
|
}
|
|
this = this_lcl->lpGbl;
|
|
|
|
FillDDSurfaceDesc( this_lcl, lpDDSurfaceDesc );
|
|
}
|
|
EXCEPT( EXCEPTION_EXECUTE_HANDLER )
|
|
{
|
|
DPF_ERR( "Exception encountered validating parameters" );
|
|
LEAVE_DDRAW();
|
|
return DDERR_INVALIDPARAMS;
|
|
}
|
|
|
|
LEAVE_DDRAW();
|
|
return DD_OK;
|
|
|
|
} /* DD_Surface_GetSurfaceDesc */
|
|
|
|
/*
|
|
* DD_Surface_GetSurfaceDesc4
|
|
*/
|
|
HRESULT DDAPI DD_Surface_GetSurfaceDesc4(
|
|
LPDIRECTDRAWSURFACE lpDDSurface,
|
|
LPDDSURFACEDESC2 lpDDSurfaceDesc )
|
|
{
|
|
LPDDRAWI_DDRAWSURFACE_INT this_int;
|
|
LPDDRAWI_DDRAWSURFACE_LCL this_lcl;
|
|
LPDDRAWI_DDRAWSURFACE_GBL this;
|
|
|
|
ENTER_DDRAW();
|
|
|
|
DPF(2,A,"ENTERAPI: DD_Surface_GetSurfaceDesc4");
|
|
|
|
TRY
|
|
{
|
|
this_int = (LPDDRAWI_DDRAWSURFACE_INT) lpDDSurface;
|
|
if( !VALID_DIRECTDRAWSURFACE_PTR( this_int ) )
|
|
{
|
|
DPF_ERR("Bad IDirectDrawSurfaceX pointer");
|
|
LEAVE_DDRAW();
|
|
return DDERR_INVALIDOBJECT;
|
|
}
|
|
this_lcl = this_int->lpLcl;
|
|
if( !VALID_DDSURFACEDESC2_PTR( lpDDSurfaceDesc ) )
|
|
{
|
|
DPF_ERR("Bad DDSURFACEDESC pointer");
|
|
LEAVE_DDRAW();
|
|
return DDERR_INVALIDPARAMS;
|
|
}
|
|
this = this_lcl->lpGbl;
|
|
|
|
FillDDSurfaceDesc2( this_lcl, lpDDSurfaceDesc );
|
|
}
|
|
EXCEPT( EXCEPTION_EXECUTE_HANDLER )
|
|
{
|
|
DPF_ERR( "Exception encountered validating parameters" );
|
|
LEAVE_DDRAW();
|
|
return DDERR_INVALIDPARAMS;
|
|
}
|
|
|
|
LEAVE_DDRAW();
|
|
return DD_OK;
|
|
|
|
} /* DD_Surface_GetSurfaceDesc4 */
|
|
|
|
|
|
#ifdef WIN95
|
|
|
|
#undef DPF_MODNAME
|
|
#define DPF_MODNAME "InternalGetDC"
|
|
|
|
/*
|
|
* BIsValidDCFormat
|
|
*
|
|
* We should only try to get a DC on a format that GDI undersatnds
|
|
*/
|
|
BOOL bIsValidDCFormat( LPDDPIXELFORMAT lpPf )
|
|
{
|
|
//
|
|
// Must be an RGB format
|
|
//
|
|
if( !(lpPf->dwFlags & DDPF_RGB ) )
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
//
|
|
// Assume that 1, 4, and 8bpp surfaces are OK
|
|
//
|
|
if( ( lpPf->dwRGBBitCount == 8 ) ||
|
|
( lpPf->dwRGBBitCount == 4 ) ||
|
|
( lpPf->dwRGBBitCount == 1 ) )
|
|
{
|
|
return TRUE;
|
|
}
|
|
|
|
//
|
|
// If it's 16bpp, it must be 5:5:5 or 5:6:5
|
|
//
|
|
if( lpPf->dwRGBBitCount == 16 )
|
|
{
|
|
if( ( lpPf->dwRBitMask == 0xf800 ) &&
|
|
( lpPf->dwGBitMask == 0x07e0 ) &&
|
|
( lpPf->dwBBitMask == 0x001f ) )
|
|
{
|
|
// 5:6:5
|
|
return TRUE;
|
|
}
|
|
else if( ( lpPf->dwRBitMask == 0x7c00 ) &&
|
|
( lpPf->dwGBitMask == 0x03e0 ) &&
|
|
( lpPf->dwBBitMask == 0x001f ) )
|
|
{
|
|
// 5:5:5
|
|
return TRUE;
|
|
}
|
|
}
|
|
else if( ( lpPf->dwRGBBitCount == 24 ) ||
|
|
( lpPf->dwRGBBitCount == 32 ) )
|
|
{
|
|
if( ( lpPf->dwBBitMask == 0x0000FF ) &&
|
|
( lpPf->dwGBitMask == 0x00FF00 ) &&
|
|
( lpPf->dwRBitMask == 0xFF0000 ) )
|
|
{
|
|
// 8:8:8
|
|
return TRUE;
|
|
}
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
|
|
/*
|
|
* InternalGetDC
|
|
*
|
|
* This is the Windows 95 version of this function. The code paths are so radically
|
|
* different that we have broken this stuff out into two different functions.
|
|
*
|
|
* This functions assumes the DDRAW critical section is already held.
|
|
*
|
|
* This function will not return the OWNDC for an OWNDC surface. It always allocates
|
|
* a new DC.
|
|
*/
|
|
HRESULT InternalGetDC( LPDDRAWI_DDRAWSURFACE_INT this_int, HDC FAR* lphdc, BOOL bWin16Lock)
|
|
{
|
|
LPDDRAWI_DDRAWSURFACE_GBL this;
|
|
LPDDRAWI_DDRAWSURFACE_LCL this_lcl;
|
|
LPDDRAWI_DIRECTDRAW_LCL pdrv_lcl;
|
|
LPDDRAWI_DIRECTDRAW_GBL pdrv;
|
|
HRESULT ddrval;
|
|
HRESULT tmprval;
|
|
DDSURFACEDESC ddsd;
|
|
LPVOID pbits;
|
|
DWORD dwLockFlags = bWin16Lock ? DDLOCK_TAKE_WIN16 : 0;
|
|
DDASSERT( NULL != this_int );
|
|
DDASSERT( NULL != lphdc );
|
|
|
|
this_lcl = this_int->lpLcl;
|
|
DDASSERT( NULL != this_lcl );
|
|
|
|
this = this_lcl->lpGbl;
|
|
DDASSERT( NULL != this );
|
|
|
|
pdrv_lcl = this_lcl->lpSurfMore->lpDD_lcl;
|
|
DDASSERT( NULL != pdrv_lcl );
|
|
|
|
pdrv = pdrv_lcl->lpGbl;
|
|
DDASSERT( NULL != pdrv );
|
|
|
|
*lphdc = NULL;
|
|
|
|
/* Get a pointer to the bits of the surface */
|
|
ddrval = InternalLock( this_lcl, &pbits, NULL , DDLOCK_WAIT | dwLockFlags );
|
|
|
|
if( ddrval == DD_OK )
|
|
{
|
|
LPDDRAWI_DDRAWPALETTE_INT ppal;
|
|
|
|
DPF( 4,"GetDC: Lock succeeded." );
|
|
|
|
ddsd.dwSize = sizeof(ddsd);
|
|
FillDDSurfaceDesc( this_lcl, &ddsd );
|
|
ddsd.lpSurface = pbits;
|
|
|
|
ppal = this_lcl->lpDDPalette;
|
|
|
|
if( ( NULL != ppal ) && !( this_lcl->ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE ) )
|
|
*lphdc = DD16_GetDC( (HDC)pdrv_lcl->hDC, &ddsd, ppal->lpLcl->lpGbl->lpColorTable );
|
|
else
|
|
*lphdc = DD16_GetDC( (HDC)pdrv_lcl->hDC, &ddsd, NULL );
|
|
|
|
if( NULL == *lphdc )
|
|
{
|
|
tmprval = InternalUnlock( this_lcl, NULL, NULL, dwLockFlags );
|
|
DDASSERT( !FAILED(tmprval) );
|
|
DPF_ERR( "Could not obtain DC" );
|
|
ddrval = DDERR_CANTCREATEDC;
|
|
}
|
|
else
|
|
{
|
|
ddrval = InternalAssociateDC( *lphdc, this_lcl );
|
|
if( FAILED( ddrval ) )
|
|
{
|
|
DPF_ERR( "Could not associate DC" );
|
|
DD16_ReleaseDC( *lphdc );
|
|
tmprval = InternalUnlock( this_lcl, NULL, NULL, dwLockFlags );
|
|
DDASSERT( !FAILED(tmprval) );
|
|
*lphdc = NULL;
|
|
}
|
|
else
|
|
{
|
|
this_lcl->dwFlags |= DDRAWISURF_HASDC;
|
|
|
|
/*
|
|
* Currenlty OWNDC is only valid for EXPLICIT system
|
|
* memory surfaces so we don't need to hold the lock
|
|
* (cause the surface can't be lost).
|
|
*
|
|
* This is an OWNDC surface so we don't hold a lock
|
|
* for the duration. Unlock the surface now.
|
|
*/
|
|
if( this_lcl->ddsCaps.dwCaps & DDSCAPS_OWNDC )
|
|
{
|
|
tmprval = InternalUnlock( this_lcl, NULL, NULL, dwLockFlags );
|
|
DDASSERT( !FAILED(tmprval) );
|
|
}
|
|
}
|
|
}
|
|
} //if InternalLock succeeded
|
|
// We could not lock the primary surface. This is because the
|
|
// primary is already locked (and we should wait until it is
|
|
// unlocked) or we have no ddraw support AND no DCI support in
|
|
// the driver (in which case the HEL has created the primary
|
|
// and we will NEVER be able to lock it. In this case, we are
|
|
// on an emulated primary and the lock failed with
|
|
// DDERR_GENERIC.
|
|
else if( ( this_lcl->ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE ) &&
|
|
( this_lcl->ddsCaps.dwCaps & DDSCAPS_SYSTEMMEMORY ) &&
|
|
( ddrval != DD_OK ) )
|
|
{
|
|
#ifdef GETDC_NULL
|
|
DPF( 4, "GetDC: Returning GetDC(NULL).");
|
|
*lphdc = GetDC( NULL );
|
|
#else
|
|
DPF( 4, "GetDC: Returning device DC.");
|
|
DDASSERT( GetObjectType( (HDC)pdrv_lcl->hDC ) == OBJ_DC );
|
|
*lphdc = (HDC)pdrv_lcl->hDC;
|
|
#endif
|
|
|
|
if( NULL != *lphdc )
|
|
{
|
|
ddrval = InternalAssociateDC( *lphdc, this_lcl );
|
|
if( FAILED( ddrval ) )
|
|
{
|
|
DPF_ERR( "Could not associate DC" );
|
|
#ifdef GETDC_NULL
|
|
ReleaseDC( NULL, *lphdc );
|
|
#endif
|
|
*lphdc = NULL;
|
|
}
|
|
else
|
|
{
|
|
// signal to ourselves that we gave a DC without
|
|
// locking.
|
|
this_lcl->dwFlags |= ( DDRAWISURF_GETDCNULL | DDRAWISURF_HASDC );
|
|
|
|
if( !( this_lcl->ddsCaps.dwCaps & DDSCAPS_OWNDC ) )
|
|
{
|
|
this->dwUsageCount++;
|
|
CHANGE_GLOBAL_CNT( pdrv, this, 1 );
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
DPF_ERR( "Could not obtain DC" );
|
|
ddrval = DDERR_CANTCREATEDC;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
/*
|
|
* InternalLock failed, and the surface wasn't an emulated primary
|
|
*/
|
|
DPF_ERR( "Could not obtain DC" );
|
|
ddrval = DDERR_CANTCREATEDC;
|
|
}
|
|
|
|
/*
|
|
* If we managed to get a DC and we are an OWNDC surface then stash the HDC away
|
|
* for future reference.
|
|
*/
|
|
if( ( !FAILED(ddrval) ) && ( this_lcl->ddsCaps.dwCaps & DDSCAPS_OWNDC ) )
|
|
{
|
|
DDASSERT( NULL != *lphdc );
|
|
DDASSERT( 0UL == this_lcl->hDC );
|
|
|
|
this_lcl->hDC = (DWORD)*lphdc;
|
|
}
|
|
|
|
return ddrval;
|
|
} /* InternalGetDC */
|
|
|
|
#undef DPF_MODNAME
|
|
#define DPF_MODNAME "InternalReleaseDC"
|
|
|
|
/*
|
|
* InternalReleaseDC - Windows 95 version
|
|
*
|
|
* Assumes the DirectDraw critical section is already held
|
|
*/
|
|
HRESULT InternalReleaseDC( LPDDRAWI_DDRAWSURFACE_LCL this_lcl, HDC hdc, BOOL bWin16Lock )
|
|
{
|
|
LPDDRAWI_DDRAWSURFACE_GBL this;
|
|
LPDDRAWI_DIRECTDRAW_LCL pdrv_lcl;
|
|
LPDDRAWI_DIRECTDRAW_GBL pdrv;
|
|
HRESULT ddrval;
|
|
|
|
#ifdef WINNT
|
|
GdiFlush();
|
|
#endif
|
|
|
|
DDASSERT( NULL != this_lcl );
|
|
DDASSERT( NULL != hdc );
|
|
|
|
this = this_lcl->lpGbl;
|
|
DDASSERT( NULL != this );
|
|
|
|
pdrv_lcl = this_lcl->lpSurfMore->lpDD_lcl;
|
|
DDASSERT( NULL != pdrv_lcl );
|
|
|
|
pdrv = pdrv_lcl->lpGbl;
|
|
DDASSERT( NULL != pdrv );
|
|
|
|
ddrval = DD_OK;
|
|
|
|
if( ( this_lcl->ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE ) &&
|
|
( this_lcl->ddsCaps.dwCaps & DDSCAPS_SYSTEMMEMORY ) &&
|
|
( this_lcl->dwFlags & DDRAWISURF_GETDCNULL ) )
|
|
{
|
|
DPF( 4, "ReleaseDC: ReleaseDC(NULL)" );
|
|
|
|
if( !( this_lcl->ddsCaps.dwCaps & DDSCAPS_OWNDC ) )
|
|
{
|
|
this->dwUsageCount--;
|
|
CHANGE_GLOBAL_CNT( pdrv, this, -1 );
|
|
}
|
|
#ifdef GETDC_NULL
|
|
/*
|
|
* Only actually free the HDC if we are running in the
|
|
* application's context and not DDHELP's (if we are
|
|
* running on DDHELP's the HDC is already gone)
|
|
*/
|
|
if( GetCurrentProcessId() == GETCURRPID() )
|
|
ReleaseDC( NULL, hdc );
|
|
#endif
|
|
this_lcl->dwFlags &= ~DDRAWISURF_GETDCNULL;
|
|
}
|
|
else
|
|
{
|
|
DPF( 4, "ReleaseDC: DD16_ReleaseDC()");
|
|
|
|
/*
|
|
* Free the thing to give DDraw16 a chance
|
|
* to clean up what it's messed with. We can do this on
|
|
* the helper thread because DCs that are created by
|
|
* DD16_GetDC are 'alive' until DDRAW16 gets unloaded.
|
|
* However, they are dangerous because they point to data
|
|
* that might have been freed by the current app.
|
|
*/
|
|
DD16_ReleaseDC( hdc );
|
|
|
|
/*
|
|
* Only unlock if its not an OWNDC surface as OWNDC surfaces
|
|
* don't hold the lock while the HDC is out.
|
|
*/
|
|
if( !( this_lcl->ddsCaps.dwCaps & DDSCAPS_OWNDC ) )
|
|
{
|
|
ddrval = InternalUnlock( this_lcl, NULL, NULL, bWin16Lock ? DDLOCK_TAKE_WIN16 : 0);
|
|
DDASSERT( !FAILED( ddrval ) );
|
|
}
|
|
}
|
|
|
|
this_lcl->dwFlags &= ~DDRAWISURF_HASDC;
|
|
|
|
// Remove this DC from our list
|
|
InternalRemoveDCFromList( hdc, this_lcl );
|
|
|
|
/*
|
|
* If this is an OWNDC surface then remove it from the HDC cache
|
|
* in the local object.
|
|
*/
|
|
if( this_lcl->ddsCaps.dwCaps & DDSCAPS_OWNDC )
|
|
this_lcl->hDC = 0UL;
|
|
|
|
return ddrval;
|
|
} /* InternalReleaseDC */
|
|
|
|
#else /* WIN95 */
|
|
|
|
#undef DPF_MODNAME
|
|
#define DPF_MODNAME "InternalGetDC"
|
|
|
|
/*
|
|
* InternalGetDC - WinNT version
|
|
*
|
|
* This is the Windows NT version of this function. The code paths are so radically
|
|
* different that we have broken this stuff out into two different functions.
|
|
*
|
|
* This functions assumes the DDRAW mutex is already held.
|
|
*
|
|
* This function will not return the OWNDC for an OWNDC surface. It always allocates
|
|
* a new DC.
|
|
*/
|
|
HRESULT InternalGetDC( LPDDRAWI_DDRAWSURFACE_INT this_int, HDC FAR* lphDC )
|
|
{
|
|
LPDDRAWI_DDRAWSURFACE_GBL this;
|
|
LPDDRAWI_DDRAWSURFACE_LCL this_lcl;
|
|
LPDDRAWI_DIRECTDRAW_LCL pdrv_lcl;
|
|
LPDDRAWI_DIRECTDRAW_GBL pdrv;
|
|
HRESULT ddrval;
|
|
|
|
DDASSERT( NULL != this_int );
|
|
DDASSERT( NULL != lphDC );
|
|
|
|
this_lcl = this_int->lpLcl;
|
|
DDASSERT( NULL != this_lcl );
|
|
|
|
this = this_lcl->lpGbl;
|
|
DDASSERT( NULL != this );
|
|
|
|
pdrv_lcl = this_lcl->lpSurfMore->lpDD_lcl;
|
|
DDASSERT( NULL != pdrv_lcl );
|
|
|
|
pdrv = pdrv_lcl->lpGbl;
|
|
DDASSERT( NULL != pdrv );
|
|
|
|
*lphDC = NULL;
|
|
|
|
ddrval = DD_OK;
|
|
FlushD3DStates(this_lcl);
|
|
#if COLLECTSTATS
|
|
if(this_lcl->ddsCaps.dwCaps & DDSCAPS_TEXTURE)
|
|
++this_lcl->lpSurfMore->lpDD_lcl->dwNumTexGetDCs;
|
|
#endif
|
|
|
|
if( (this_lcl->ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE) &&
|
|
(this_lcl->ddsCaps.dwCaps & DDSCAPS_SYSTEMMEMORY) )
|
|
{
|
|
#ifdef GETDC_NULL
|
|
DPF( 4, "GetDC(NULL)" );
|
|
*lphDC = GetDC( NULL );
|
|
#else
|
|
DPF( 4, "GetDC: Returning device DC." );
|
|
DDASSERT( GetObjectType( (HDC)this_lcl->lpSurfMore->lpDD_lcl->hDC ) == OBJ_DC );
|
|
if (this_lcl->lpSurfMore->lpDD_lcl->dwLocalFlags & DDRAWILCL_DIRTYDC)
|
|
{
|
|
HDC hdc;
|
|
|
|
/*
|
|
* We need to destroy and recreate the device DC because a ChangeDisplaySettings
|
|
* will have messed up the vis rgn associated with that DC. We need to create
|
|
* the new DC before we destroy the old one just in case the destroy caused an
|
|
* unload of the driver
|
|
*/
|
|
hdc = DD_CreateDC( this_lcl->lpSurfMore->lpDD_lcl->lpGbl->cDriverName );
|
|
DeleteDC((HDC) this_lcl->lpSurfMore->lpDD_lcl->hDC);
|
|
this_lcl->lpSurfMore->lpDD_lcl->hDC = (ULONG_PTR) hdc;
|
|
|
|
if( this_lcl->lpDDPalette )
|
|
{
|
|
SelectPalette(hdc, (HPALETTE) this_lcl->lpDDPalette->lpLcl->lpGbl->dwReserved1, FALSE);
|
|
RealizePalette(hdc);
|
|
}
|
|
this_lcl->lpSurfMore->lpDD_lcl->dwLocalFlags &= ~DDRAWILCL_DIRTYDC;
|
|
}
|
|
*lphDC = (HDC)this_lcl->lpSurfMore->lpDD_lcl->hDC;
|
|
#endif
|
|
}
|
|
else
|
|
{
|
|
LPDDRAWI_DDRAWPALETTE_INT ppal;
|
|
|
|
DPF( 4, "DdGetDC" );
|
|
|
|
ppal = this_lcl->lpDDPalette;
|
|
if (this_lcl->hDDSurface || CompleteCreateSysmemSurface(this_lcl))
|
|
{
|
|
if( ( NULL != ppal ) && !( this_lcl->ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE ) )
|
|
*lphDC = DdGetDC( this_lcl, ppal->lpLcl->lpGbl->lpColorTable );
|
|
else
|
|
*lphDC = DdGetDC( this_lcl, NULL );
|
|
}
|
|
}
|
|
|
|
if( NULL == *lphDC )
|
|
{
|
|
DPF_ERR( "Could not obtain DC" );
|
|
ddrval = DDERR_CANTCREATEDC;
|
|
}
|
|
else
|
|
{
|
|
ddrval = InternalAssociateDC( *lphDC, this_lcl );
|
|
if( FAILED( ddrval ) )
|
|
{
|
|
DPF_ERR( "Could not associate DC" );
|
|
if( (this_lcl->ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE) &&
|
|
(this_lcl->ddsCaps.dwCaps & DDSCAPS_SYSTEMMEMORY) )
|
|
{
|
|
#ifdef GETDC_NULL
|
|
ReleaseDC( NULL, *lphDC );
|
|
#endif
|
|
}
|
|
else
|
|
{
|
|
DdReleaseDC( this_lcl );
|
|
}
|
|
|
|
*lphDC = NULL;
|
|
}
|
|
else
|
|
{
|
|
this_lcl->dwFlags |= DDRAWISURF_HASDC;
|
|
|
|
if( this_lcl->ddsCaps.dwCaps & DDSCAPS_OWNDC )
|
|
{
|
|
/*
|
|
* OWNDC surfaces don't hold a lock while the HDC is available.
|
|
*/
|
|
|
|
/*
|
|
* If this is an OWNDC surface then we need to stash the HDC
|
|
* away in the surface for future reference.
|
|
*/
|
|
DDASSERT( this->dwGlobalFlags & DDRAWISURFGBL_SYSMEMREQUESTED );
|
|
DDASSERT( 0UL == this_lcl->hDC );
|
|
|
|
this_lcl->hDC = (ULONG_PTR) *lphDC;
|
|
}
|
|
else
|
|
{
|
|
/*
|
|
* On NT we don't lock the surface to take the HDC. However, we
|
|
* want the semantics on both NT and 95 (where the lock is taken)
|
|
* to be the same so we* bump the usage counts and hold the mutex.
|
|
*/
|
|
this->dwUsageCount++;
|
|
CHANGE_GLOBAL_CNT( pdrv, this, 1 );
|
|
ENTER_DDRAW();
|
|
}
|
|
}
|
|
}
|
|
|
|
// Remove any cached RLE stuff for the surface
|
|
if( this_lcl->ddsCaps.dwCaps & DDSCAPS_SYSTEMMEMORY )
|
|
{
|
|
extern void FreeRleData(LPDDRAWI_DDRAWSURFACE_LCL psurf);
|
|
FreeRleData( this_lcl );
|
|
}
|
|
|
|
if(IsD3DManaged(this_lcl))
|
|
{
|
|
/* Mark everything dirty */
|
|
MarkDirty(this_lcl);
|
|
this_lcl->lpSurfMore->lpRegionList->rdh.nCount = NUM_RECTS_IN_REGIONLIST;
|
|
}
|
|
return ddrval;
|
|
} /* InternalGetDC */
|
|
|
|
#undef DPF_MODNAME
|
|
#define DPF_MODNAME "InternalReleaseDC"
|
|
|
|
/*
|
|
* InternalReleaseDC - Windows NT version
|
|
*
|
|
* Assumes the DirectDraw mutex is already held
|
|
*
|
|
* This function
|
|
*/
|
|
HRESULT InternalReleaseDC( LPDDRAWI_DDRAWSURFACE_LCL this_lcl, HDC hdc )
|
|
{
|
|
LPDDRAWI_DDRAWSURFACE_GBL this;
|
|
LPDDRAWI_DIRECTDRAW_LCL pdrv_lcl;
|
|
LPDDRAWI_DIRECTDRAW_GBL pdrv;
|
|
HRESULT ddrval;
|
|
|
|
DDASSERT( NULL != this_lcl );
|
|
DDASSERT( NULL != hdc );
|
|
|
|
this = this_lcl->lpGbl;
|
|
DDASSERT( NULL != this );
|
|
|
|
pdrv_lcl = this_lcl->lpSurfMore->lpDD_lcl;
|
|
DDASSERT( NULL != pdrv_lcl );
|
|
|
|
pdrv = pdrv_lcl->lpGbl;
|
|
DDASSERT( NULL != pdrv );
|
|
|
|
ddrval = DD_OK;
|
|
/*
|
|
* Since this function already marks the surface as not having a DC even if
|
|
* a failure is encountered destroying the DC, we always reduce the surface's
|
|
* usage count.
|
|
* This usage count decrement is done because we didn't call InternalLock on the
|
|
* GetDC, so we don't call InternalUnlock here, but we still mucked with the flags
|
|
* to ensure that ddraw.dll didn't hand out a lock while someone had a DC.
|
|
*
|
|
* NOTE: If this is an OWNDC surface we never even spoofed the lock so don't unspoof
|
|
* now.
|
|
*/
|
|
if( this_lcl->ddsCaps.dwCaps & DDSCAPS_OWNDC )
|
|
{
|
|
DDASSERT( this->dwGlobalFlags & DDRAWISURFGBL_SYSMEMREQUESTED );
|
|
DDASSERT( 0UL != this_lcl->hDC );
|
|
|
|
this_lcl->hDC = 0UL;
|
|
}
|
|
else
|
|
{
|
|
/*
|
|
* Undo the pseudo-lock we took to make NT behave like '95.
|
|
* The LEAVE_DDRAW may appear strange but we know we already
|
|
* have another reference to the mutex when we call this function.
|
|
*/
|
|
this->dwUsageCount--;
|
|
CHANGE_GLOBAL_CNT( pdrv, this, -1 );
|
|
LEAVE_DDRAW();
|
|
}
|
|
|
|
if( ( this_lcl->ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE ) &&
|
|
( this_lcl->ddsCaps.dwCaps & DDSCAPS_SYSTEMMEMORY ) )
|
|
{
|
|
#ifdef GETDC_NULL
|
|
DPF( 4, "NT emulation releasing primary DC" );
|
|
ReleaseDC( NULL, hdc );
|
|
#endif
|
|
}
|
|
else
|
|
{
|
|
if( !DdReleaseDC( this_lcl ) )
|
|
{
|
|
DPF( 0, "DDreleaseDC fails!" );
|
|
ddrval = DDERR_GENERIC;
|
|
}
|
|
}
|
|
|
|
this_lcl->dwFlags &= ~DDRAWISURF_HASDC;
|
|
|
|
// Remove this DC from our list
|
|
InternalRemoveDCFromList( hdc, this_lcl );
|
|
|
|
return ddrval;
|
|
}
|
|
|
|
#endif /* WIN95 */
|
|
|
|
#undef DPF_MODNAME
|
|
#define DPF_MODNAME "DD_Surface_GetDC"
|
|
|
|
/*
|
|
* DD_Surface_GetDC
|
|
*/
|
|
HRESULT DDAPI DD_Surface_GetDC(
|
|
LPDIRECTDRAWSURFACE lpDDSurface,
|
|
HDC FAR *lphDC )
|
|
{
|
|
LPDDRAWI_DDRAWSURFACE_INT this_int;
|
|
LPDDRAWI_DDRAWSURFACE_LCL this_lcl;
|
|
LPDDRAWI_DDRAWSURFACE_GBL this;
|
|
LPDDRAWI_DIRECTDRAW_GBL pdrv;
|
|
HRESULT ddrval;
|
|
|
|
ENTER_DDRAW();
|
|
|
|
DPF(2,A,"ENTERAPI: DD_Surface_GetDC");
|
|
/* DPF_ENTERAPI(lpDDSurface); */
|
|
// 5/25/2000(RichGr): IA64: Use %p format specifier for 32/64-bit pointers.
|
|
DPF(3,A," lphDC = 0x%p", lphDC);
|
|
|
|
TRY
|
|
{
|
|
this_int = (LPDDRAWI_DDRAWSURFACE_INT) lpDDSurface;
|
|
if( !VALID_DIRECTDRAWSURFACE_PTR( this_int ) )
|
|
{
|
|
LEAVE_DDRAW();
|
|
return DDERR_INVALIDOBJECT;
|
|
}
|
|
this_lcl = this_int->lpLcl;
|
|
if( !VALID_HDC_PTR( lphDC ) )
|
|
{
|
|
LEAVE_DDRAW();
|
|
return DDERR_INVALIDPARAMS;
|
|
}
|
|
this = this_lcl->lpGbl;
|
|
pdrv = this->lpDD;
|
|
if( this_lcl->ddsCaps.dwCaps & DDSCAPS_EXECUTEBUFFER ||
|
|
this_lcl->ddsCaps.dwCaps & DDSCAPS_OPTIMIZED )
|
|
{
|
|
DPF_ERR( "Invalid surface type: can't get DC" );
|
|
LEAVE_DDRAW();
|
|
return DDERR_INVALIDSURFACETYPE;
|
|
}
|
|
|
|
if( SURFACE_LOST( this_lcl ) )
|
|
{
|
|
LEAVE_DDRAW();
|
|
DPF(3,A,"Returning DDERR_SURFACELOST");
|
|
return DDERR_SURFACELOST;
|
|
}
|
|
// DC already returned for this surface? We don't need to
|
|
// check this if the surface is OWNDC. If so then we can
|
|
// hand out (the same) HDC as many times as we like.
|
|
if( ( this_lcl->dwFlags & DDRAWISURF_HASDC ) &&
|
|
!( this_lcl->ddsCaps.dwCaps & DDSCAPS_OWNDC ) )
|
|
{
|
|
DPF_ERR( "Can only return one DC per surface" );
|
|
LEAVE_DDRAW();
|
|
return DDERR_DCALREADYCREATED;
|
|
}
|
|
|
|
// default value is null:
|
|
*lphDC = (HDC) 0;
|
|
|
|
//
|
|
// For now, if the current surface is optimized, quit
|
|
//
|
|
if (this_lcl->ddsCaps.dwCaps & DDSCAPS_OPTIMIZED)
|
|
{
|
|
DPF_ERR( "It is an optimized surface" );
|
|
LEAVE_DDRAW();
|
|
return DDERR_ISOPTIMIZEDSURFACE;
|
|
}
|
|
|
|
//
|
|
// Fail if GDI doesn't understand the format
|
|
//
|
|
#ifdef WIN95
|
|
if (!LOWERTHANDDRAW7( this_lcl->lpSurfMore->lpDD_int ) )
|
|
{
|
|
LPDDPIXELFORMAT lpPf;
|
|
|
|
GET_PIXEL_FORMAT( this_lcl, this, lpPf );
|
|
if( !bIsValidDCFormat( lpPf ) )
|
|
{
|
|
DPF_ERR( "DCs cannot be used with this surface format" );
|
|
LEAVE_DDRAW();
|
|
return DDERR_INVALIDPIXELFORMAT;
|
|
}
|
|
}
|
|
#endif
|
|
}
|
|
EXCEPT( EXCEPTION_EXECUTE_HANDLER )
|
|
{
|
|
DPF_ERR( "Exception encountered validating parameters" );
|
|
LEAVE_DDRAW();
|
|
return DDERR_INVALIDPARAMS;
|
|
}
|
|
|
|
/*
|
|
* If this is an OWNDC surface and we currently have an HDC
|
|
* then just use that.
|
|
*/
|
|
if( ( this_lcl->ddsCaps.dwCaps & DDSCAPS_OWNDC ) &&
|
|
( 0UL != this_lcl->hDC ) )
|
|
{
|
|
/*
|
|
* We currently only support OWNDC for explicit system
|
|
* memory surfaces.
|
|
*/
|
|
DDASSERT( this->dwGlobalFlags & DDRAWISURFGBL_SYSMEMREQUESTED );
|
|
|
|
*lphDC = (HDC)this_lcl->hDC;
|
|
|
|
LEAVE_DDRAW();
|
|
return DD_OK;
|
|
}
|
|
|
|
ddrval = InternalGetDC( this_int, lphDC
|
|
#ifdef WIN95
|
|
, TRUE
|
|
#endif //WIN95
|
|
);
|
|
|
|
LEAVE_DDRAW();
|
|
return ddrval;
|
|
} /* DD_Surface_GetDC */
|
|
|
|
#undef DPF_MODNAME
|
|
#define DPF_MODNAME "ReleaseDC"
|
|
|
|
/*
|
|
* DD_Surface_ReleaseDC
|
|
*
|
|
* NOTE: This function does not actually release the HDC for an OWNDC surface.
|
|
* The HDC is only toasted when the surface is finally destroyed.
|
|
*/
|
|
HRESULT DDAPI DD_Surface_ReleaseDC(
|
|
LPDIRECTDRAWSURFACE lpDDSurface,
|
|
HDC hdc )
|
|
{
|
|
LPDDRAWI_DDRAWSURFACE_INT this_int;
|
|
LPDDRAWI_DDRAWSURFACE_LCL this_lcl;
|
|
LPDDRAWI_DDRAWSURFACE_GBL this;
|
|
LPDDRAWI_DIRECTDRAW_GBL pdrv;
|
|
HRESULT ddrval;
|
|
BOOL bFound;
|
|
DCINFO *pdcinfo;
|
|
DCINFO *pdcinfoPrev = NULL;
|
|
|
|
ENTER_DDRAW();
|
|
|
|
DPF(2,A,"ENTERAPI: DD_Surface_ReleaseDC");
|
|
|
|
TRY
|
|
{
|
|
this_int = (LPDDRAWI_DDRAWSURFACE_INT) lpDDSurface;
|
|
if( !VALID_DIRECTDRAWSURFACE_PTR( this_int ) )
|
|
{
|
|
LEAVE_DDRAW();
|
|
return DDERR_INVALIDOBJECT;
|
|
}
|
|
this_lcl = this_int->lpLcl;
|
|
this = this_lcl->lpGbl;
|
|
pdrv = this->lpDD;
|
|
#ifdef WIN95
|
|
if( SURFACE_LOST( this_lcl ) )
|
|
{
|
|
LEAVE_DDRAW();
|
|
return DDERR_SURFACELOST;
|
|
}
|
|
#endif
|
|
if( !(this_lcl->dwFlags & DDRAWISURF_HASDC) )
|
|
{
|
|
DPF_ERR( "No DC allocated" );
|
|
LEAVE_DDRAW();
|
|
return DDERR_NODC;
|
|
}
|
|
|
|
//
|
|
// For now, if the current surface is optimized, quit
|
|
//
|
|
if (this_lcl->ddsCaps.dwCaps & DDSCAPS_OPTIMIZED)
|
|
{
|
|
DPF_ERR( "It is an optimized surface" );
|
|
LEAVE_DDRAW();
|
|
return DDERR_ISOPTIMIZEDSURFACE;
|
|
}
|
|
|
|
/*
|
|
* Check for an invalid DC. Prior to DX5, we didn't check so it was
|
|
* possible to 1) release an DC that we didn't create and 2) release a
|
|
* DC that wasn't associated with the surface, causing things to get
|
|
* messed up.
|
|
*/
|
|
bFound = FALSE;
|
|
for( pdcinfo = g_pdcinfoHead; pdcinfo != NULL;
|
|
pdcinfoPrev = pdcinfo, pdcinfo = pdcinfo->pdcinfoNext )
|
|
{
|
|
DDASSERT( pdcinfo->pdds_lcl != NULL );
|
|
|
|
if( hdc == pdcinfo->hdc )
|
|
{
|
|
bFound = TRUE;
|
|
if( this_lcl != pdcinfo->pdds_lcl )
|
|
{
|
|
bFound = FALSE;
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
if( !bFound )
|
|
{
|
|
if( ( this_int->lpVtbl == &ddSurfaceCallbacks ) ||
|
|
( this_int->lpVtbl == &ddSurface2Callbacks ) )
|
|
{
|
|
DPF_ERR( "********************************************************************" );
|
|
DPF_ERR( "* Invalid DC specified in ReleaseDC - not associate with the surface" );
|
|
DPF_ERR( "********************************************************************" );
|
|
}
|
|
else
|
|
{
|
|
DPF_ERR( "Invalid DC specified in ReleaseDC" );
|
|
LEAVE_DDRAW();
|
|
return DDERR_INVALIDPARAMS;
|
|
}
|
|
}
|
|
}
|
|
EXCEPT( EXCEPTION_EXECUTE_HANDLER )
|
|
{
|
|
DPF_ERR( "Exception encountered validating parameters" );
|
|
LEAVE_DDRAW();
|
|
return DDERR_INVALIDPARAMS;
|
|
}
|
|
|
|
/*
|
|
* If this is an OWNDC surface then just check to make sure we
|
|
* were given back the correct HDC and return.
|
|
*/
|
|
if( this_lcl->ddsCaps.dwCaps & DDSCAPS_OWNDC )
|
|
{
|
|
DDASSERT( this->dwGlobalFlags & DDRAWISURFGBL_SYSMEMREQUESTED );
|
|
|
|
if( hdc != (HDC)this_lcl->hDC )
|
|
{
|
|
DPF_ERR( "ReleaseDC called with wrong HDC for OWNDC surface" );
|
|
LEAVE_DDRAW();
|
|
return DDERR_INVALIDPARAMS;
|
|
}
|
|
|
|
LEAVE_DDRAW();
|
|
return DD_OK;
|
|
}
|
|
|
|
ddrval = InternalReleaseDC( this_lcl, hdc
|
|
#ifdef WIN95
|
|
, TRUE
|
|
#endif //WIN95
|
|
);
|
|
|
|
BUMP_SURFACE_STAMP(this);
|
|
|
|
LEAVE_DDRAW();
|
|
return ddrval;
|
|
} /* DD_Surface_ReleaseDC */
|
|
|
|
#undef DPF_MODNAME
|
|
#define DPF_MODNAME "IsLost"
|
|
|
|
/*
|
|
* DD_Surface_IsLost
|
|
*/
|
|
HRESULT DDAPI DD_Surface_IsLost( LPDIRECTDRAWSURFACE lpDDSurface )
|
|
{
|
|
LPDDRAWI_DDRAWSURFACE_INT this_int;
|
|
LPDDRAWI_DDRAWSURFACE_LCL this_lcl;
|
|
LPDDRAWI_DDRAWSURFACE_GBL this;
|
|
LPDDRAWI_DIRECTDRAW_GBL pdrv;
|
|
|
|
ENTER_DDRAW();
|
|
|
|
DPF(2,A,"ENTERAPI: DD_Surface_IsLost");
|
|
|
|
TRY
|
|
{
|
|
this_int = (LPDDRAWI_DDRAWSURFACE_INT) lpDDSurface;
|
|
if( !VALID_DIRECTDRAWSURFACE_PTR( this_int ) )
|
|
{
|
|
LEAVE_DDRAW();
|
|
return DDERR_INVALIDOBJECT;
|
|
}
|
|
this_lcl = this_int->lpLcl;
|
|
this = this_lcl->lpGbl;
|
|
pdrv = this->lpDD;
|
|
if( SURFACE_LOST( this_lcl ) )
|
|
{
|
|
LEAVE_DDRAW();
|
|
return DDERR_SURFACELOST;
|
|
}
|
|
}
|
|
EXCEPT( EXCEPTION_EXECUTE_HANDLER )
|
|
{
|
|
DPF_ERR( "Exception encountered validating parameters" );
|
|
LEAVE_DDRAW();
|
|
return DDERR_INVALIDPARAMS;
|
|
}
|
|
|
|
if (this_lcl->ddsCaps.dwCaps & DDSCAPS_OPTIMIZED)
|
|
{
|
|
if (this->dwGlobalFlags & DDRAWISURFGBL_MEMFREE)
|
|
{
|
|
LEAVE_DDRAW();
|
|
return DDERR_NOTLOADED;
|
|
}
|
|
#if 0 //Old code
|
|
if (this->dwGlobalFlags & DDRAWISURFGBL_MEMFREE)
|
|
{
|
|
LEAVE_DDRAW();
|
|
return DDERR_NOTLOADED;
|
|
}
|
|
#endif //0
|
|
}
|
|
LEAVE_DDRAW();
|
|
return DD_OK;
|
|
|
|
} /* DD_Surface_IsLost */
|
|
|
|
#undef DPF_MODNAME
|
|
#define DPF_MODNAME "Initialize"
|
|
|
|
/*
|
|
* DD_Surface_Initialize
|
|
*/
|
|
HRESULT DDAPI DD_Surface_Initialize(
|
|
LPDIRECTDRAWSURFACE lpDDSurface,
|
|
LPDIRECTDRAW lpDD,
|
|
LPDDSURFACEDESC lpDDSurfaceDesc )
|
|
{
|
|
DPF(2,A,"ENTERAPI: DD_Surface_Initialize");
|
|
|
|
DPF_ERR( "DirectDrawSurface: Already initialized." );
|
|
return DDERR_ALREADYINITIALIZED;
|
|
|
|
} /* DD_Surface_Initialize */
|
|
|
|
HRESULT AtomicRestoreSurface(LPDDRAWI_DDRAWSURFACE_INT this_int)
|
|
{
|
|
LPDDRAWI_DIRECTDRAW_LCL pdrv_lcl;
|
|
LPDDRAWI_DIRECTDRAW_GBL pdrv;
|
|
LPDDRAWI_DDRAWSURFACE_LCL this_lcl;
|
|
LPDDRAWI_DDRAWSURFACE_GBL this;
|
|
DDHAL_CREATESURFACEDATA csd;
|
|
LPDDHAL_CREATESURFACE csfn;
|
|
LPDDHAL_CREATESURFACE cshalfn;
|
|
DWORD rc;
|
|
HRESULT ddrval = DD_OK;
|
|
UINT bpp;
|
|
LONG pitch;
|
|
BOOL do_alloc=TRUE;
|
|
BOOL emulation = FALSE;
|
|
DWORD scnt;
|
|
DDSURFACEDESC2 ddsd2;
|
|
|
|
this_lcl = this_int->lpLcl;
|
|
this = this_lcl->lpGbl;
|
|
|
|
pdrv_lcl = this_lcl->lpSurfMore->lpDD_lcl;
|
|
pdrv = pdrv_lcl->lpGbl;
|
|
#ifdef WINNT
|
|
// Update DDraw handle in driver GBL object.
|
|
pdrv->hDD = pdrv_lcl->hDD;
|
|
#endif //WINNT
|
|
|
|
DDASSERT( SURFACE_LOST( this_lcl ) );
|
|
|
|
#ifndef WINNT
|
|
if( this_lcl->dwModeCreatedIn != pdrv->dwModeIndex )
|
|
#else
|
|
if (!EQUAL_DISPLAYMODE(this_lcl->lpSurfMore->dmiCreated, pdrv->dmiCurrent))
|
|
#endif
|
|
{
|
|
DPF_ERR( "Surface was not created in the current mode" );
|
|
return DDERR_WRONGMODE;
|
|
}
|
|
|
|
if(this_lcl->ddsCaps.dwCaps & DDSCAPS_SYSTEMMEMORY)
|
|
{
|
|
emulation = TRUE;
|
|
}
|
|
|
|
#ifdef WINNT
|
|
if (this->dwGlobalFlags & DDRAWISURFGBL_NOTIFYWHENUNLOCKED)
|
|
{
|
|
if (--dwNumLockedWhenModeSwitched == 0)
|
|
{
|
|
NotifyDriverOfFreeAliasedLocks();
|
|
}
|
|
this->dwGlobalFlags &= ~DDRAWISURFGBL_NOTIFYWHENUNLOCKED;
|
|
}
|
|
#endif
|
|
|
|
if( emulation )
|
|
{
|
|
if( this_lcl->ddsCaps.dwCaps & DDSCAPS_EXECUTEBUFFER )
|
|
{
|
|
csfn = pdrv_lcl->lpDDCB->HELDDExeBuf.CreateExecuteBuffer;
|
|
}
|
|
else
|
|
{
|
|
csfn = pdrv_lcl->lpDDCB->HELDD.CreateSurface;
|
|
}
|
|
cshalfn = csfn;
|
|
}
|
|
else
|
|
{
|
|
if( this_lcl->ddsCaps.dwCaps & DDSCAPS_EXECUTEBUFFER )
|
|
{
|
|
csfn = pdrv_lcl->lpDDCB->HALDDExeBuf.CreateExecuteBuffer;
|
|
cshalfn = pdrv_lcl->lpDDCB->cbDDExeBufCallbacks.CreateExecuteBuffer;
|
|
}
|
|
else
|
|
{
|
|
csfn = pdrv_lcl->lpDDCB->HALDD.CreateSurface;
|
|
cshalfn = pdrv_lcl->lpDDCB->cbDDCallbacks.CreateSurface;
|
|
}
|
|
}
|
|
|
|
csd.CreateSurface = cshalfn;
|
|
csd.lpDD = pdrv;
|
|
if (this_lcl->dwFlags & DDRAWISURF_IMPLICITROOT)
|
|
{
|
|
//
|
|
// This is a complex surface, so we recorded the createsurface data
|
|
// at CS time.
|
|
//
|
|
DDASSERT(this_lcl->lpSurfMore->pCreatedDDSurfaceDesc2);
|
|
DDASSERT(this_lcl->lpSurfMore->slist);
|
|
DDASSERT(this_lcl->lpSurfMore->cSurfaces);
|
|
csd.lpDDSurfaceDesc = (LPDDSURFACEDESC) this_lcl->lpSurfMore->pCreatedDDSurfaceDesc2;
|
|
csd.lplpSList = this_lcl->lpSurfMore->slist;
|
|
csd.dwSCnt = this_lcl->lpSurfMore->cSurfaces;
|
|
//
|
|
// we record the surfacedesc for any complex surface except pure mipmaps
|
|
//
|
|
if ((this_lcl->ddsCaps.dwCaps & DDSCAPS_MIPMAP) &&
|
|
((this_lcl->lpSurfMore->ddsCapsEx.dwCaps2 & DDSCAPS2_CUBEMAP)==0) )
|
|
{
|
|
DDASSERT(0 == this_lcl->lpSurfMore->pCreatedDDSurfaceDesc2);
|
|
FillDDSurfaceDesc2( this_lcl, &ddsd2 );
|
|
csd.lpDDSurfaceDesc = (LPDDSURFACEDESC) &ddsd2;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// this is a single non-complex surface.
|
|
// Setup the createsurface data structure to reflect it
|
|
//
|
|
FillDDSurfaceDesc2( this_lcl, &ddsd2 );
|
|
csd.lpDDSurfaceDesc = (LPDDSURFACEDESC) &ddsd2;
|
|
csd.lplpSList = &this_lcl;
|
|
csd.dwSCnt = 1;
|
|
}
|
|
|
|
|
|
//
|
|
// Note, those surfaces for whom MEMFREE (i.e. the GDI surface) is not set also pass through
|
|
// this code path and are passed to the driver's createsurface
|
|
// This is different from the process for non-dx7 drivers.
|
|
// The non-dx7 driver restore path actually has a bug: the alias for the GDI surface
|
|
// is not restored.
|
|
//
|
|
for( scnt=0; scnt<csd.dwSCnt; scnt++ )
|
|
{
|
|
if (csd.lplpSList[scnt]->lpGbl->fpVidMem != 0xFFBADBAD)
|
|
csd.lplpSList[scnt]->lpGbl->fpVidMem = 0;
|
|
|
|
if( !( csd.lplpSList[scnt]->ddsCaps.dwCaps & DDSCAPS_EXECUTEBUFFER ) )
|
|
{
|
|
if( csd.lplpSList[scnt]->dwFlags & DDRAWISURF_HASPIXELFORMAT )
|
|
{
|
|
bpp = csd.lplpSList[scnt]->lpGbl->ddpfSurface.dwRGBBitCount;
|
|
}
|
|
else
|
|
{
|
|
bpp = pdrv->vmiData.ddpfDisplay.dwRGBBitCount;
|
|
}
|
|
pitch = (LONG) ComputePitch( pdrv, csd.lplpSList[scnt]->ddsCaps.dwCaps,
|
|
(DWORD) csd.lplpSList[scnt]->lpGbl->wWidth, bpp );
|
|
csd.lplpSList[scnt]->lpGbl->lPitch = pitch;
|
|
}
|
|
}
|
|
|
|
#ifdef WIN95
|
|
/* Copy the VXD handle from the per process local structure to global.
|
|
* This handle will be used by DDHAL32_VidMemAlloc(), rather than creating
|
|
* a new one using GetDXVxdHandle(). The assumptions here are:
|
|
* 1) Only one process can enter createSurface(), 2) Deferred calls to
|
|
* DDHAL32_VidMemAlloc() will result in the slow path, ie getting
|
|
* the VXD handle using GetDXVxdHandle().
|
|
* (snene 2/23/98)
|
|
*/
|
|
pdrv->hDDVxd = pdrv_lcl->hDDVxd;
|
|
#endif /* WIN95 */
|
|
|
|
/*
|
|
* NOTE: Different HAL entry points for execute buffers and
|
|
* conventional surfaces.
|
|
*/
|
|
if( this_lcl->ddsCaps.dwCaps & DDSCAPS_EXECUTEBUFFER )
|
|
{
|
|
DOHALCALL( CreateExecuteBuffer, csfn, csd, rc, emulation );
|
|
}
|
|
else
|
|
{
|
|
DOHALCALL( CreateSurface, csfn, csd, rc, emulation );
|
|
}
|
|
|
|
#ifdef WIN95
|
|
/* Restore the handle to INVALID_HANDLE_VALUE so that non-createSurface()
|
|
* calls using DDHAL32_VidMemAlloc() or deferred calls (possibly from other
|
|
* processes) will correctly recreate the handle using GetDXVxdHandle().
|
|
* (snene 2/23/98)
|
|
*/
|
|
pdrv->hDDVxd = (DWORD)INVALID_HANDLE_VALUE;
|
|
#endif /* WIN95 */
|
|
|
|
if( rc == DDHAL_DRIVER_HANDLED )
|
|
{
|
|
if( csd.ddRVal != DD_OK )
|
|
{
|
|
#ifdef DEBUG
|
|
if( emulation )
|
|
{
|
|
DPF( 1, "Restore: Emulation won't let surface be created, rc=%08lx (%ld)",
|
|
csd.ddRVal, LOWORD( csd.ddRVal ) );
|
|
}
|
|
else
|
|
{
|
|
DPF( 1, "Restore: Driver won't let surface be created, rc=%08lx (%ld)",
|
|
csd.ddRVal, LOWORD( csd.ddRVal ) );
|
|
}
|
|
#endif
|
|
|
|
return csd.ddRVal;
|
|
}
|
|
}
|
|
|
|
/*
|
|
* now, allocate any unallocated surfaces
|
|
*/
|
|
ddrval = AllocSurfaceMem( pdrv_lcl, csd.lplpSList, csd.dwSCnt );
|
|
if( ddrval != DD_OK )
|
|
{
|
|
return ddrval;
|
|
}
|
|
|
|
for( scnt=0; scnt<csd.dwSCnt; scnt++ )
|
|
{
|
|
LPDDRAWI_DDRAWSURFACE_GBL_MORE lpGblMore;
|
|
|
|
csd.lplpSList[scnt]->dwFlags &= ~DDRAWISURF_INVALID;
|
|
csd.lplpSList[scnt]->lpGbl->dwGlobalFlags &= ~DDRAWISURFGBL_MEMFREE;
|
|
|
|
#ifdef USE_ALIAS
|
|
/*
|
|
* If this device has heap aliases then precompute the pointer
|
|
* alias for the video memory returned at creation time. This
|
|
* is by far the most likely pointer we are going to be handing
|
|
* out at lock time so we are going to make lock a lot faster
|
|
* by precomputing this then at lock time all we need to do is
|
|
* compare the pointer we got from the driver with fpVidMem. If
|
|
* they are equal then we can just return this cached pointer.
|
|
*/
|
|
lpGblMore = GET_LPDDRAWSURFACE_GBL_MORE( csd.lplpSList[scnt]->lpGbl );
|
|
if( csd.lplpSList[scnt]->ddsCaps.dwCaps & DDSCAPS_VIDEOMEMORY )
|
|
{
|
|
lpGblMore->fpAliasedVidMem = GetAliasedVidMem( pdrv_lcl, csd.lplpSList[scnt],
|
|
csd.lplpSList[scnt]->lpGbl->fpVidMem );
|
|
// If we succeeded in getting an alias, cache it for future use. Also store the original
|
|
// fpVidMem to compare with before using the cached pointer to make sure the cached value
|
|
// is still valid
|
|
if (lpGblMore->fpAliasedVidMem)
|
|
lpGblMore->fpAliasOfVidMem = csd.lplpSList[scnt]->lpGbl->fpVidMem;
|
|
else
|
|
lpGblMore->fpAliasOfVidMem = 0;
|
|
}
|
|
else
|
|
{
|
|
lpGblMore->fpAliasedVidMem = 0UL;
|
|
lpGblMore->fpAliasOfVidMem = 0UL;
|
|
}
|
|
#endif /* USE_ALIAS */
|
|
|
|
#ifdef WIN95
|
|
if (csd.lplpSList[scnt]->lpSurfMore->ddsCapsEx.dwCaps2 & DDSCAPS2_PERSISTENTCONTENTS)
|
|
{
|
|
ddrval = RestoreSurfaceContents(csd.lplpSList[scnt]);
|
|
}
|
|
#endif
|
|
|
|
/*
|
|
* If a D3D texture managed surface is being restored,
|
|
* then we need to mark the corresponding system memory
|
|
* surface dirty, so that it is automatically refreshed
|
|
* prior to rendering.
|
|
*/
|
|
if (SUCCEEDED(ddrval))
|
|
{
|
|
if(!IsD3DManaged(csd.lplpSList[scnt]) && csd.lplpSList[scnt]->lpSurfMore->lpRegionList)
|
|
{
|
|
MarkDirty(csd.lplpSList[scnt]);
|
|
csd.lplpSList[scnt]->lpSurfMore->lpRegionList->rdh.nCount = NUM_RECTS_IN_REGIONLIST;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (
|
|
#ifdef WINNT
|
|
// on NT side, we still call CreateSurfaceEx if HW driver isn't called
|
|
emulation && this_lcl->hDDSurface &&
|
|
#endif //WINNT
|
|
TRUE
|
|
)
|
|
{
|
|
DDASSERT( pdrv_lcl == this_lcl->lpSurfMore->lpDD_lcl);
|
|
createsurfaceEx(this_lcl);
|
|
}
|
|
|
|
// If D3D Vertex Buffer, notify D3D
|
|
if ( (this_lcl->ddsCaps.dwCaps & DDSCAPS_EXECUTEBUFFER) &&
|
|
(this_lcl->ddsCaps.dwCaps & DDSCAPS_VIDEOMEMORY) &&
|
|
(this_lcl->lpGbl->dwUsageCount > 0) &&
|
|
(GetCurrentProcessId() == GETCURRPID()) &&
|
|
(this_lcl->lpSurfMore->lpDD_lcl->pBreakVBLock) &&
|
|
(this_lcl->lpSurfMore->lpVB) )
|
|
{
|
|
{
|
|
this_lcl->lpSurfMore->lpDD_lcl->pBreakVBLock(this_lcl->lpSurfMore->lpVB);
|
|
}
|
|
}
|
|
|
|
return ddrval;
|
|
}
|
|
|
|
#undef DPF_MODNAME
|
|
#define DPF_MODNAME "Restore"
|
|
|
|
/*
|
|
* restoreSurface
|
|
*
|
|
* restore the vidmem of one surface
|
|
*/
|
|
static HRESULT restoreSurface( LPDDRAWI_DDRAWSURFACE_INT this_int )
|
|
{
|
|
LPDDRAWI_DIRECTDRAW_LCL pdrv_lcl;
|
|
LPDDRAWI_DIRECTDRAW_GBL pdrv;
|
|
LPDDRAWI_DDRAWSURFACE_LCL this_lcl;
|
|
LPDDRAWI_DDRAWSURFACE_GBL this;
|
|
LPDDRAWI_DDRAWSURFACE_LCL slistx[1];
|
|
LPDDRAWI_DDRAWSURFACE_GBL slist[1];
|
|
DDHAL_CREATESURFACEDATA csd;
|
|
LPDDHAL_CREATESURFACE csfn;
|
|
LPDDHAL_CREATESURFACE cshalfn;
|
|
DDSURFACEDESC2 ddsd;
|
|
DWORD rc;
|
|
HRESULT ddrval;
|
|
UINT bpp;
|
|
LONG pitch = 0;
|
|
BOOL do_alloc=TRUE;
|
|
|
|
this_lcl = this_int->lpLcl;
|
|
this = this_lcl->lpGbl;
|
|
|
|
pdrv_lcl = this_lcl->lpSurfMore->lpDD_lcl;
|
|
pdrv = pdrv_lcl->lpGbl;
|
|
#ifdef WINNT
|
|
// Update DDraw handle in driver GBL object.
|
|
pdrv->hDD = pdrv_lcl->hDD;
|
|
#endif //WINNT
|
|
|
|
/*
|
|
* If we made it to here the local surface should be marked invalid.
|
|
*/
|
|
DDASSERT( SURFACE_LOST( this_lcl ) );
|
|
|
|
#ifndef WINNT
|
|
if( this_lcl->dwModeCreatedIn != pdrv->dwModeIndex )
|
|
#else
|
|
if (!EQUAL_DISPLAYMODE(this_lcl->lpSurfMore->dmiCreated, pdrv->dmiCurrent))
|
|
#endif
|
|
{
|
|
DPF_ERR( "Surface was not created in the current mode" );
|
|
return DDERR_WRONGMODE;
|
|
}
|
|
|
|
#ifdef WINNT
|
|
if (this->dwGlobalFlags & DDRAWISURFGBL_NOTIFYWHENUNLOCKED)
|
|
{
|
|
if (--dwNumLockedWhenModeSwitched == 0)
|
|
{
|
|
NotifyDriverOfFreeAliasedLocks();
|
|
}
|
|
this->dwGlobalFlags &= ~DDRAWISURFGBL_NOTIFYWHENUNLOCKED;
|
|
}
|
|
#endif
|
|
|
|
DPF(5,"RestoreSurface. GDI Flag is %d, MemFree flag is %d, Primary flag is %d",
|
|
this->dwGlobalFlags & DDRAWISURFGBL_ISGDISURFACE,
|
|
this->dwGlobalFlags & DDRAWISURFGBL_MEMFREE,
|
|
this_lcl->ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE
|
|
);
|
|
/*
|
|
* Two cases where we don't want to allocate any memory:
|
|
* -optimized surfaces
|
|
* -surfaces for which was just marked as invalid.
|
|
* If this is an optimized surface, Restore is basically a noop
|
|
* since memory is allocated at optimize time, not restore time.
|
|
*/
|
|
if(( (!(this->dwGlobalFlags & DDRAWISURFGBL_MEMFREE))
|
|
#ifdef WINNT
|
|
/*
|
|
* We need to call CreateSurface HAL callback on NT
|
|
*/
|
|
&& (((this->dwGlobalFlags & DDRAWISURFGBL_ISGDISURFACE) == 0)
|
|
|| (this_lcl->ddsCaps.dwCaps & DDSCAPS_SYSTEMMEMORY))
|
|
#endif
|
|
) || (this_lcl->ddsCaps.dwCaps & DDSCAPS_OPTIMIZED) )
|
|
{
|
|
this_lcl->dwFlags &= ~DDRAWISURF_INVALID;
|
|
ddrval = DD_OK;
|
|
do_alloc = FALSE;
|
|
}
|
|
else
|
|
{
|
|
slistx[0] = this_lcl;
|
|
slist[0] = this;
|
|
|
|
if (this->fpVidMem != 0xFFBADBAD)
|
|
this->fpVidMem = 0;
|
|
|
|
// 5/25/2000(RichGr): IA64: Use %p format specifier for 32/64-bit pointers.
|
|
DPF( 4, "Restoring 0x%p", this_lcl );
|
|
|
|
/*
|
|
* Execute buffers are handled very differently
|
|
* from ordinary surfaces. They have no width and
|
|
* height and store a linear size instead of a pitch.
|
|
* Note, the linear size includes any alignment
|
|
* requirements (added by ComputePitch on surface
|
|
* creation) so we do not recompute the pitch at this
|
|
* point. The surface structure as it stands is all we
|
|
* need.
|
|
*/
|
|
if( !( this_lcl->ddsCaps.dwCaps & DDSCAPS_EXECUTEBUFFER ) )
|
|
{
|
|
if( this_lcl->dwFlags & DDRAWISURF_HASPIXELFORMAT )
|
|
{
|
|
bpp = this->ddpfSurface.dwRGBBitCount;
|
|
}
|
|
else
|
|
{
|
|
bpp = pdrv->vmiData.ddpfDisplay.dwRGBBitCount;
|
|
}
|
|
pitch = (LONG) ComputePitch( pdrv, this_lcl->ddsCaps.dwCaps,
|
|
(DWORD) this->wWidth, bpp );
|
|
this->lPitch = pitch;
|
|
}
|
|
/*
|
|
* first, give the driver an opportunity to create it...
|
|
*/
|
|
if( this_lcl->ddsCaps.dwCaps & DDSCAPS_EXECUTEBUFFER )
|
|
{
|
|
cshalfn = pdrv_lcl->lpDDCB->cbDDExeBufCallbacks.CreateExecuteBuffer;
|
|
csfn = pdrv_lcl->lpDDCB->HALDDExeBuf.CreateExecuteBuffer;
|
|
}
|
|
else
|
|
{
|
|
cshalfn = pdrv_lcl->lpDDCB->cbDDCallbacks.CreateSurface;
|
|
csfn = pdrv_lcl->lpDDCB->HALDD.CreateSurface;
|
|
}
|
|
if( cshalfn != NULL )
|
|
{
|
|
DPF(4,"HAL CreateSurface to be called");
|
|
/*
|
|
* construct a new surface description
|
|
*/
|
|
FillDDSurfaceDesc2( this_lcl, &ddsd );
|
|
|
|
/*
|
|
* call the driver
|
|
*/
|
|
csd.CreateSurface = cshalfn;
|
|
csd.lpDD = pdrv;
|
|
csd.lpDDSurfaceDesc = (LPDDSURFACEDESC)&ddsd;
|
|
csd.lplpSList = slistx;
|
|
csd.dwSCnt = 1;
|
|
|
|
if( this_lcl->ddsCaps.dwCaps & DDSCAPS_EXECUTEBUFFER )
|
|
{
|
|
DOHALCALL( CreateExecuteBuffer, csfn, csd, rc, FALSE );
|
|
}
|
|
else
|
|
{
|
|
DOHALCALL( CreateSurface, csfn, csd, rc, FALSE );
|
|
}
|
|
if( rc == DDHAL_DRIVER_HANDLED )
|
|
{
|
|
if( csd.ddRVal != DD_OK )
|
|
{
|
|
do_alloc = FALSE;
|
|
ddrval = csd.ddRVal;
|
|
}
|
|
}
|
|
}
|
|
/*
|
|
* On NT, we will hit this code path for the GDI surface.
|
|
* We could probably just not do the alloc, but to avoid hard-to-test code paths
|
|
* I'll let the AllocSurfaceMem trivially allocate for the GDI surface.
|
|
*/
|
|
if( do_alloc )
|
|
{
|
|
/*
|
|
* allocate the memory now...
|
|
*/
|
|
ddrval = AllocSurfaceMem( pdrv_lcl, slistx, 1 );
|
|
if( ddrval != DD_OK )
|
|
{
|
|
this->lPitch = pitch;
|
|
DPF(2,"Moving to system memory");
|
|
ddrval = MoveToSystemMemory( this_int, FALSE, TRUE );
|
|
}
|
|
if( ddrval == DD_OK )
|
|
{
|
|
this_lcl->dwFlags &= ~DDRAWISURF_INVALID;
|
|
this->dwGlobalFlags &= ~DDRAWISURFGBL_MEMFREE;
|
|
}
|
|
}
|
|
}
|
|
|
|
#ifdef USE_ALIAS
|
|
{
|
|
LPDDRAWI_DDRAWSURFACE_GBL_MORE lpGblMore;
|
|
|
|
lpGblMore = GET_LPDDRAWSURFACE_GBL_MORE( this );
|
|
if( this_lcl->ddsCaps.dwCaps & DDSCAPS_VIDEOMEMORY )
|
|
{
|
|
lpGblMore->fpAliasedVidMem = GetAliasedVidMem( pdrv_lcl, this_lcl, this_lcl->lpGbl->fpVidMem );
|
|
// If we succeeded in getting an alias, cache it for future use. Also store the original
|
|
// fpVidMem to compare with before using the cached pointer to make sure the cached value
|
|
// is still valid
|
|
if (lpGblMore->fpAliasedVidMem)
|
|
lpGblMore->fpAliasOfVidMem = this_lcl->lpGbl->fpVidMem;
|
|
else
|
|
lpGblMore->fpAliasOfVidMem = 0;
|
|
}
|
|
else
|
|
{
|
|
lpGblMore->fpAliasedVidMem = 0UL;
|
|
lpGblMore->fpAliasOfVidMem = 0UL;
|
|
}
|
|
}
|
|
#endif /* USE_ALIAS */
|
|
|
|
|
|
#ifdef WIN95
|
|
if (SUCCEEDED(ddrval) && (this_lcl->lpSurfMore->ddsCapsEx.dwCaps2 & DDSCAPS2_PERSISTENTCONTENTS))
|
|
{
|
|
ddrval = RestoreSurfaceContents(this_lcl);
|
|
}
|
|
#endif
|
|
|
|
/*
|
|
* If a D3D texture managed surface is being restored,
|
|
* then we need to mark the corresponding system memory
|
|
* surface dirty, so that it is automatically refreshed
|
|
* prior to rendering.
|
|
*/
|
|
if(!IsD3DManaged(this_lcl) && this_lcl->lpSurfMore->lpRegionList)
|
|
{
|
|
MarkDirty(this_lcl);
|
|
this_lcl->lpSurfMore->lpRegionList->rdh.nCount = NUM_RECTS_IN_REGIONLIST;
|
|
}
|
|
|
|
return ddrval;
|
|
|
|
} /* restoreSurface */
|
|
|
|
/*
|
|
* restoreAttachments
|
|
*
|
|
* restore all attachments to a surface
|
|
*/
|
|
static HRESULT restoreAttachments( LPDDRAWI_DDRAWSURFACE_LCL this_lcl )
|
|
{
|
|
LPATTACHLIST pattachlist;
|
|
LPDDRAWI_DDRAWSURFACE_INT curr_int;
|
|
LPDDRAWI_DDRAWSURFACE_LCL curr_lcl;
|
|
LPDDRAWI_DDRAWSURFACE_GBL curr;
|
|
HRESULT ddrval;
|
|
|
|
pattachlist = this_lcl->lpAttachList;
|
|
while( pattachlist != NULL )
|
|
{
|
|
curr_int = pattachlist->lpIAttached;
|
|
|
|
curr_lcl = curr_int->lpLcl;
|
|
curr = curr_lcl->lpGbl;
|
|
if( curr_lcl->dwFlags & DDRAWISURF_IMPLICITCREATE )
|
|
{
|
|
ddrval = restoreSurface( curr_int );
|
|
if( ddrval != DD_OK )
|
|
{
|
|
DPF( 2, "restoreSurface failed: %08lx (%ld)", ddrval, LOWORD( ddrval ) );
|
|
return ddrval;
|
|
}
|
|
ddrval = restoreAttachments( curr_lcl );
|
|
if( ddrval != DD_OK )
|
|
{
|
|
DPF( 2, "restoreAttachents failed: %08lx (%ld)", ddrval, LOWORD( ddrval ) );
|
|
return ddrval;
|
|
}
|
|
}
|
|
pattachlist = pattachlist->lpLink;
|
|
}
|
|
return DD_OK;
|
|
|
|
} /* restoreAttachments */
|
|
|
|
/*
|
|
* DD_Surface_Restore
|
|
*
|
|
* Restore an invalidated surface
|
|
*/
|
|
#undef DPF_MODNAME
|
|
#define DPF_MODNAME "DD_Surface_Restore"
|
|
HRESULT DDAPI DD_Surface_Restore( LPDIRECTDRAWSURFACE lpDDSurface )
|
|
{
|
|
LPDDRAWI_DDRAWSURFACE_INT this_int;
|
|
LPDDRAWI_DDRAWSURFACE_LCL this_lcl;
|
|
LPDDRAWI_DDRAWSURFACE_GBL this;
|
|
LPDDRAWI_DIRECTDRAW_LCL pdrv_lcl;
|
|
LPDDRAWI_DIRECTDRAW_GBL pdrv;
|
|
HRESULT ddrval;
|
|
BOOL has_excl;
|
|
BOOL excl_exists;
|
|
DDSURFACEDESC2 ddsd;
|
|
|
|
ENTER_DDRAW();
|
|
|
|
DPF(2,A,"ENTERAPI: DD_Surface_Restore");
|
|
/* DPF_ENTERAPI(lpDDSurface); */
|
|
|
|
/*
|
|
* validate parameters
|
|
*/
|
|
TRY
|
|
{
|
|
this_int = (LPDDRAWI_DDRAWSURFACE_INT) lpDDSurface;
|
|
if( !VALID_DIRECTDRAWSURFACE_PTR( this_int ) )
|
|
{
|
|
DPF_ERR( "Invalid surface pointer" );
|
|
LEAVE_DDRAW();
|
|
DPF_APIRETURNS(DDERR_INVALIDOBJECT);
|
|
return DDERR_INVALIDOBJECT;
|
|
}
|
|
this_lcl = this_int->lpLcl;
|
|
this = this_lcl->lpGbl;
|
|
pdrv_lcl = this_lcl->lpSurfMore->lpDD_lcl;
|
|
pdrv = pdrv_lcl->lpGbl;
|
|
if( (this_lcl->dwFlags & DDRAWISURF_ISFREE) )
|
|
{
|
|
LEAVE_DDRAW();
|
|
DPF_APIRETURNS( DDERR_INVALIDOBJECT);
|
|
return DDERR_INVALIDOBJECT;
|
|
}
|
|
#ifdef WIN95
|
|
if( ( pdrv_lcl->dwAppHackFlags & DDRAW_APPCOMPAT_SCREENSAVER ) &&
|
|
( pdrv_lcl->dwLocalFlags & DDRAWILCL_POWEREDDOWN ) )
|
|
{
|
|
LEAVE_DDRAW();
|
|
return DDERR_SURFACELOST;
|
|
}
|
|
#endif
|
|
if( !SURFACE_LOST( this_lcl ) )
|
|
{
|
|
LEAVE_DDRAW();
|
|
DPF(2,"Returning DD_OK since not lost");
|
|
return DD_OK;;
|
|
}
|
|
}
|
|
EXCEPT( EXCEPTION_EXECUTE_HANDLER )
|
|
{
|
|
DPF_ERR( "Exception encountered validating parameters" );
|
|
LEAVE_DDRAW();
|
|
DPF_APIRETURNS(DDERR_INVALIDPARAMS);
|
|
return DDERR_INVALIDPARAMS;
|
|
}
|
|
|
|
// For now, disallow it for optimized surfaces
|
|
if (this_lcl->ddsCaps.dwCaps & DDSCAPS_OPTIMIZED)
|
|
{
|
|
DPF_ERR( "It is an optimized surface" );
|
|
LEAVE_DDRAW();
|
|
return DDERR_ISOPTIMIZEDSURFACE;
|
|
}
|
|
|
|
/*
|
|
* don't allow restoration of implicit surfaces
|
|
*/
|
|
if( (this_lcl->dwFlags & DDRAWISURF_IMPLICITCREATE) )
|
|
{
|
|
DPF_ERR( "Can't restore implicitly created surfaces" );
|
|
LEAVE_DDRAW();
|
|
DPF_APIRETURNS(DDERR_IMPLICITLYCREATED);
|
|
return DDERR_IMPLICITLYCREATED;
|
|
}
|
|
|
|
/*
|
|
* make sure we are in the same mode the surface was created in
|
|
*/
|
|
#ifdef WIN95
|
|
if( pdrv->dwModeIndex != this_lcl->dwModeCreatedIn )
|
|
#else
|
|
if (!EQUAL_DISPLAYMODE(this_lcl->lpSurfMore->dmiCreated, pdrv->dmiCurrent))
|
|
#endif
|
|
{
|
|
DPF(1, "Cannot restore surface, not in original mode");
|
|
LEAVE_DDRAW();
|
|
DPF_APIRETURNS(DDERR_WRONGMODE);
|
|
return DDERR_WRONGMODE;
|
|
}
|
|
|
|
/*
|
|
* If the device has an exclusive owner, we must not restore any surface
|
|
* in the device's video memory unless we are the device's exclusive owner.
|
|
* DDERR_WRONGMODE is returned to avoid regression problems by mimicking
|
|
* Restore() behavior in the case in which the device's exclusive owner has
|
|
* changed to a mode that's different from the one the surface was created in.
|
|
*
|
|
* We also handle the case where an exclusive mode app tries to restore
|
|
* surfaces while no one has exclusive mode (for example, when the app is
|
|
* minimized). The restore would commonly fail due to the app running in a
|
|
* different display mode from the current display mode. However, if the
|
|
* is running in the same display mode, we would previously allow the
|
|
* restore to succeed. As mentioned above, we'll return DDERR_WRONGMODE,
|
|
* to avoid regression problems, even though DDERR_NOEXCLUSIVEMODE would
|
|
* make more sense.
|
|
*/
|
|
CheckExclusiveMode(this_lcl->lpSurfMore->lpDD_lcl, &excl_exists , &has_excl, FALSE,
|
|
NULL, FALSE);
|
|
|
|
if((excl_exists && !has_excl) ||
|
|
(!excl_exists && (pdrv_lcl->dwLocalFlags & DDRAWILCL_HASEXCLUSIVEMODE)))
|
|
{
|
|
DPF_ERR("Another app has assumed exclusive ownership of device");
|
|
LEAVE_DDRAW();
|
|
DPF_APIRETURNS(DDERR_WRONGMODE);
|
|
return DDERR_WRONGMODE;
|
|
}
|
|
|
|
/*
|
|
* make sure we are not in the middle of a mode change, in which case
|
|
* DirectDraw is confused about the mode it is in
|
|
*/
|
|
if( pdrv->dwFlags & DDRAWI_CHANGINGMODE )
|
|
{
|
|
/*
|
|
* We really should fail this altogether since we are only
|
|
* asking for trouble, but we fear that regression risk might
|
|
* be worse, so we only fail this for a surface 3 interface.
|
|
* In the cases we do not fail, we handle the Blt case by not
|
|
* doing anything, but we're still vulnerable to Lock and GetDC.
|
|
*/
|
|
if( !( ( this_int->lpVtbl == &ddSurfaceCallbacks ) ||
|
|
( this_int->lpVtbl == &ddSurface2Callbacks ) ) )
|
|
{
|
|
DPF_ERR("Cannot restore surface, in the middle of a mode change");
|
|
LEAVE_DDRAW();
|
|
DPF_APIRETURNS(DDERR_WRONGMODE);
|
|
return DDERR_WRONGMODE;
|
|
}
|
|
else
|
|
{
|
|
/*
|
|
* Always output a message here. This serves two purposes:
|
|
* 1) Let us no why a stress failure occured,
|
|
* 2) Inform developers why they are seeing bugs.
|
|
*/
|
|
OutputDebugString( "WARNING: Restoring surface during a mode change!\n" );
|
|
}
|
|
}
|
|
|
|
if( this_lcl->ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE )
|
|
{
|
|
/*
|
|
* are we the process with exclusive mode?
|
|
*/
|
|
if( excl_exists && !has_excl )
|
|
{
|
|
DPF_ERR( "Cannot restore primary surface, not exclusive owner" );
|
|
LEAVE_DDRAW();
|
|
DPF_APIRETURNS(DDERR_NOEXCLUSIVEMODE);
|
|
return DDERR_NOEXCLUSIVEMODE;
|
|
}
|
|
else if( !excl_exists )
|
|
{
|
|
/*
|
|
* no exclusive mode
|
|
*/
|
|
FillDDSurfaceDesc2( this_lcl, &ddsd );
|
|
if( !MatchPrimary( pdrv, &ddsd ) )
|
|
{
|
|
DPF_ERR( "Can't restore primary, incompatible with current primary" );
|
|
LEAVE_DDRAW();
|
|
DPF_APIRETURNS(DDERR_INCOMPATIBLEPRIMARY);
|
|
return DDERR_INCOMPATIBLEPRIMARY;
|
|
}
|
|
}
|
|
/*
|
|
* otherwise, it is OK to restore primary
|
|
*/
|
|
|
|
#ifdef WINNT
|
|
/*
|
|
* Ctrl-Alt-Del on NT gives us no notice and so no FlipToGDISurface has been done.
|
|
* This means that the DDSCAPS_PRIMARY and DDRAWISURFGBL_ISGDISURFACE tags may
|
|
* not be on the same surface object (which is what FlipToGDISurface does).
|
|
* The NT user-side code expects that DDSCAPS_PRIMARY means DDRAWISURFGBL_ISGDISURFACE
|
|
* which it normally would, and should (i.e. GDI's surface should be the visible surface
|
|
* immediately before a switch back to a fullscreen app.)
|
|
* We force this situation here by running the attachment list for a primary and
|
|
* finding the GDI surface, then doing a surface-object-only flip (i.e. exchange
|
|
* these two objects' MEMFREE status, dwReserved and Kernel handle fields.
|
|
* I shall be extra paranoid and only attempt this if the primary doesn't have
|
|
* IS_GDISURFACE set. It should be safe to assume that the only way the GDI and
|
|
* PRIMARY flags got mismatched is via a flip that wasn't undone.
|
|
* This situation should never happen for an emulated primary (since Flip drops
|
|
* out early before doing the flag rotation).
|
|
*/
|
|
if ( !( this->dwGlobalFlags & DDRAWISURFGBL_ISGDISURFACE ) )
|
|
{
|
|
/*
|
|
* Run the attachments looking for the surface with the GDI flag
|
|
*/
|
|
LPDDRAWI_DDRAWSURFACE_INT curr_int;
|
|
|
|
DDASSERT( (this_lcl->ddsCaps.dwCaps & DDSCAPS_SYSTEMMEMORY) == 0);
|
|
DDASSERT(this_lcl->lpAttachList);
|
|
|
|
curr_int = FindAttachedFlip(this_int);
|
|
while( curr_int->lpLcl != this_lcl )
|
|
{
|
|
if( curr_int->lpLcl->lpGbl->dwGlobalFlags & DDRAWISURFGBL_ISGDISURFACE )
|
|
{
|
|
/*
|
|
* Found the GDI tagged surface
|
|
*/
|
|
break;
|
|
}
|
|
DDASSERT(curr_int->lpLcl->lpAttachList);
|
|
curr_int = FindAttachedFlip(curr_int);
|
|
}
|
|
if (curr_int->lpLcl != this_lcl)
|
|
{
|
|
/*
|
|
* curr_lcl != this_lcl means we found an attached surface with GDI set,
|
|
* so pseudo-flip them.
|
|
*/
|
|
DWORD memfreeflag;
|
|
ULONG_PTR reserved,handle;
|
|
LPDDRAWI_DDRAWSURFACE_GBL curr_gbl = curr_int->lpLcl->lpGbl;
|
|
|
|
DDASSERT(0 == curr_gbl->fpVidMem);
|
|
DDASSERT(NULL == curr_gbl->lpVidMemHeap);
|
|
|
|
/*
|
|
* The primary (this) needs to get the GDI flag set, and the other
|
|
* (the old GDI surface) needs to get GDI reset.
|
|
*/
|
|
curr_gbl->dwGlobalFlags &= ~DDRAWISURFGBL_ISGDISURFACE;
|
|
this->dwGlobalFlags |= DDRAWISURFGBL_ISGDISURFACE;
|
|
|
|
/*
|
|
* The two surfaces must trade their MEMFREE status.
|
|
*/
|
|
memfreeflag = curr_gbl->dwGlobalFlags & DDRAWISURFGBL_ISGDISURFACE;
|
|
curr_gbl->dwGlobalFlags = (curr_gbl->dwGlobalFlags & ~DDRAWISURFGBL_MEMFREE)
|
|
| (this->dwGlobalFlags & DDRAWISURFGBL_MEMFREE);
|
|
this->dwGlobalFlags = (this->dwGlobalFlags & ~DDRAWISURFGBL_MEMFREE)
|
|
| memfreeflag;
|
|
|
|
/*
|
|
* Swap reserved field and kernel handle
|
|
*/
|
|
reserved = curr_gbl->dwReserved1;
|
|
curr_gbl->dwReserved1 = this->dwReserved1;
|
|
this->dwReserved1 = reserved;
|
|
|
|
handle = curr_int->lpLcl->hDDSurface;
|
|
curr_int->lpLcl->hDDSurface = this_lcl->hDDSurface;
|
|
this_lcl->hDDSurface = handle;
|
|
}
|
|
}
|
|
#endif
|
|
|
|
} /* if primary surface */
|
|
|
|
if (NULL == pdrv->lpDDCBtmp->HALDDMiscellaneous2.CreateSurfaceEx)
|
|
{
|
|
//
|
|
// Non DX7 driver gets piece-meal restore
|
|
//
|
|
/*
|
|
* restore this surface
|
|
*/
|
|
ddrval = restoreSurface( this_int );
|
|
if( ddrval != DD_OK )
|
|
{
|
|
DPF( 1, "restoreSurface failed, rc=%08lx (%ld)", ddrval, LOWORD( ddrval ) );
|
|
LEAVE_DDRAW();
|
|
DPF_APIRETURNS(ddrval);
|
|
return ddrval;
|
|
}
|
|
|
|
/*
|
|
* restore all surfaces in an implicit chain
|
|
*/
|
|
if( this_lcl->dwFlags & DDRAWISURF_IMPLICITROOT )
|
|
{
|
|
ddrval = restoreAttachments( this_lcl );
|
|
}
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// DX7 driver gets atomic restore
|
|
//
|
|
ddrval = AtomicRestoreSurface(this_int);
|
|
}
|
|
|
|
LEAVE_DDRAW();
|
|
DPF_APIRETURNS(ddrval);
|
|
return ddrval;
|
|
|
|
} /* DD_Surface_Restore */
|
|
|
|
/*
|
|
* MoveToSystemMemory
|
|
*
|
|
* if possible, deallocate the video memory associated with this surface
|
|
* and allocate system memory instead. This is useful for drivers which have
|
|
* hardware flip and video memory capability but no blt capability. By
|
|
* moving the offscreen surfaces to system memory, we reduce the lock overhead
|
|
* and also reduce the bus bandwidth requirements.
|
|
*
|
|
* This function assumes the DRIVER LOCK HAS BEEN TAKEN.
|
|
*/
|
|
HRESULT MoveToSystemMemory(
|
|
LPDDRAWI_DDRAWSURFACE_INT this_int,
|
|
BOOL hasvram,
|
|
BOOL use_full_lock )
|
|
{
|
|
LPDDRAWI_DDRAWSURFACE_LCL this_lcl;
|
|
LPDDRAWI_DDRAWSURFACE_GBL this;
|
|
ULONG_PTR newreserved;
|
|
ULONG_PTR newreserved_lcl;
|
|
// LPVOID newvidmemheap;
|
|
LONG newpitch;
|
|
FLATPTR newvidmem;
|
|
DWORD newddscaps;
|
|
ULONG_PTR newhddsurface;
|
|
ULONG_PTR savereserved;
|
|
ULONG_PTR savereserved_lcl;
|
|
LPVOID savevidmemheap;
|
|
LONG savepitch;
|
|
FLATPTR savevidmem;
|
|
DWORD saveddscaps;
|
|
ULONG_PTR savehddsurface;
|
|
DDHAL_CREATESURFACEDATA csd;
|
|
DWORD rc;
|
|
DDSURFACEDESC2 ddsd;
|
|
LPDDRAWI_DDRAWSURFACE_LCL slistx;
|
|
LPBYTE lpvidmem;
|
|
LPBYTE lpsysmem;
|
|
DWORD bytecount;
|
|
DWORD line;
|
|
HRESULT ddrval;
|
|
LPVOID pbits;
|
|
WORD wHeight;
|
|
LPDDRAWI_DIRECTDRAW_LCL pdrv_lcl;
|
|
LPDDRAWI_DIRECTDRAW_GBL pdrv;
|
|
|
|
|
|
this_lcl = this_int->lpLcl;
|
|
this = this_lcl->lpGbl;
|
|
|
|
pdrv_lcl = this_lcl->lpSurfMore->lpDD_lcl;
|
|
pdrv = pdrv_lcl->lpGbl;
|
|
|
|
//
|
|
// We don't move to system memory on DX7 drivers, since this process doesn't
|
|
// inform them of the new sysmem surface
|
|
//
|
|
if (NULL != pdrv->lpDDCBtmp->HALDDMiscellaneous2.CreateSurfaceEx)
|
|
{
|
|
//this error code never percolates up to apps.
|
|
return DDERR_GENERIC;
|
|
}
|
|
|
|
#ifdef WINNT
|
|
{
|
|
// Update DDraw handle in driver GBL object.
|
|
pdrv->hDD = pdrv_lcl->hDD;
|
|
}
|
|
#endif //WINNT
|
|
|
|
if(hasvram && SURFACE_LOST( this_lcl ) )
|
|
{
|
|
return DDERR_SURFACELOST;
|
|
}
|
|
|
|
if( ( this_lcl->lpAttachList != NULL ) ||
|
|
( this_lcl->lpAttachListFrom != NULL ) ||
|
|
( this->dwUsageCount != 0 ) ||
|
|
( this_lcl->ddsCaps.dwCaps & DDSCAPS_SYSTEMMEMORY ) ||
|
|
( this_lcl->ddsCaps.dwCaps & DDSCAPS_OVERLAY ) ||
|
|
( this_lcl->dwFlags & (DDRAWISURF_HASPIXELFORMAT|DDRAWISURF_PARTOFPRIMARYCHAIN) ) )
|
|
{
|
|
/*
|
|
* can't move it to system memory
|
|
*/
|
|
// 5/25/2000(RichGr): IA64: Use %p format specifier for 32/64-bit pointers.
|
|
DPF( 2, "Unable to move surface 0x%p to system memory", this_int );
|
|
#ifdef DEBUG
|
|
if( this_lcl->lpAttachList != NULL )
|
|
{
|
|
DPF( 4, "AttachList is non-NULL" );
|
|
}
|
|
if( this_lcl->lpAttachListFrom != NULL )
|
|
{
|
|
DPF( 4, "AttachListFrom is non-NULL" );
|
|
}
|
|
if( this->dwUsageCount != 0 )
|
|
{
|
|
DPF( 4, "dwusageCount=%ld", this->dwUsageCount );
|
|
}
|
|
if( this_lcl->dwFlags & DDRAWISURF_PARTOFPRIMARYCHAIN )
|
|
{
|
|
DPF( 4, "part of the primary chain" );
|
|
}
|
|
if( this_lcl->ddsCaps.dwCaps & DDSCAPS_OVERLAY )
|
|
{
|
|
DPF( 4, "Is a hardware overlay" );
|
|
}
|
|
if( this_lcl->ddsCaps.dwCaps & DDSCAPS_SYSTEMMEMORY )
|
|
{
|
|
DPF( 4, "Is already in system memory" );
|
|
}
|
|
if( this_lcl->dwFlags & DDRAWISURF_HASPIXELFORMAT )
|
|
{
|
|
DPF( 4, "Has a different pixel format" );
|
|
}
|
|
#endif
|
|
return DDERR_GENERIC;
|
|
}
|
|
|
|
/*
|
|
* save the current state just in case the HEL
|
|
* CreateSurface call fails.
|
|
*/
|
|
savevidmem = this->fpVidMem;
|
|
savevidmemheap = this->lpVidMemHeap;
|
|
savereserved = this->dwReserved1;
|
|
savereserved_lcl= this_lcl->dwReserved1;
|
|
savepitch = this->lPitch;
|
|
saveddscaps = this_lcl->ddsCaps.dwCaps;
|
|
savehddsurface = this_lcl->hDDSurface;
|
|
|
|
/*
|
|
* lock the vram
|
|
*/
|
|
if( hasvram )
|
|
{
|
|
while( 1 )
|
|
{
|
|
if( use_full_lock )
|
|
{
|
|
ddsd.dwSize = sizeof( ddsd );
|
|
ddrval = DD_Surface_Lock(
|
|
(LPDIRECTDRAWSURFACE) this_int,
|
|
NULL,
|
|
(LPDDSURFACEDESC)&ddsd,
|
|
0,
|
|
NULL );
|
|
if( ddrval == DD_OK )
|
|
{
|
|
pbits = ddsd.lpSurface;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
ddrval = InternalLock( this_lcl, &pbits, NULL, 0 );
|
|
}
|
|
if( ddrval == DDERR_WASSTILLDRAWING )
|
|
{
|
|
continue;
|
|
}
|
|
break;
|
|
}
|
|
if( ddrval != DD_OK )
|
|
{
|
|
DPF( 0, "*** MoveToSystemMemory: Lock failed! rc = %08lx", ddrval );
|
|
return ddrval;
|
|
}
|
|
}
|
|
|
|
/*
|
|
* mark this object as system memory. NT needs this done before the
|
|
* CreateSurface HEL call, otherwise it gets confused about whether
|
|
* it's supposed to be a video memory or system memory surface.
|
|
*/
|
|
this_lcl->ddsCaps.dwCaps &= ~(DDSCAPS_VIDEOMEMORY|DDSCAPS_NONLOCALVIDMEM|DDSCAPS_LOCALVIDMEM);
|
|
this_lcl->ddsCaps.dwCaps |= DDSCAPS_SYSTEMMEMORY;
|
|
|
|
/*
|
|
* set up for a call to the HEL
|
|
*/
|
|
FillDDSurfaceDesc2( this_lcl, &ddsd );
|
|
slistx = this_lcl;
|
|
csd.lpDD = this->lpDD;
|
|
csd.lpDDSurfaceDesc = (LPDDSURFACEDESC)&ddsd;
|
|
csd.lplpSList = &slistx;
|
|
csd.dwSCnt = 1;
|
|
rc = this_lcl->lpSurfMore->lpDD_lcl->lpDDCB->HELDD.CreateSurface( &csd );
|
|
if( (rc == DDHAL_DRIVER_NOTHANDLED) || (csd.ddRVal != DD_OK) )
|
|
{
|
|
this->fpVidMem = savevidmem;
|
|
this->lpVidMemHeap = savevidmemheap;
|
|
this->lPitch = savepitch;
|
|
this->dwReserved1 = savereserved;
|
|
this_lcl->dwReserved1 = savereserved_lcl;
|
|
this_lcl->ddsCaps.dwCaps = saveddscaps;
|
|
this_lcl->hDDSurface = savehddsurface;
|
|
if( hasvram )
|
|
{
|
|
if( use_full_lock )
|
|
{
|
|
DD_Surface_Unlock( (LPDIRECTDRAWSURFACE) this_int, NULL );
|
|
}
|
|
else
|
|
{
|
|
InternalUnlock( this_lcl, NULL, NULL, 0 );
|
|
}
|
|
}
|
|
DPF( 0, "*** MoveToSystemMemory: HEL CreateSurface failed! rc = %08lx", csd.ddRVal );
|
|
return csd.ddRVal;
|
|
}
|
|
|
|
/*
|
|
* copy the bits from vidmem to systemmem
|
|
*/
|
|
if( hasvram )
|
|
{
|
|
lpvidmem = (LPBYTE)pbits;
|
|
lpsysmem = (LPBYTE)this_lcl->lpGbl->fpVidMem;
|
|
if( this_lcl->ddsCaps.dwCaps & DDSCAPS_EXECUTEBUFFER )
|
|
{
|
|
bytecount = this->dwLinearSize;
|
|
wHeight = 1;
|
|
}
|
|
else
|
|
{
|
|
bytecount = this->wWidth * ddsd.ddpfPixelFormat.dwRGBBitCount / 8;
|
|
wHeight = this->wHeight;
|
|
}
|
|
|
|
TRY
|
|
{
|
|
for( line=0; line<wHeight; line++)
|
|
{
|
|
memcpy( lpsysmem, lpvidmem, bytecount );
|
|
lpvidmem += savepitch;
|
|
lpsysmem += this->lPitch;
|
|
}
|
|
}
|
|
EXCEPT( EXCEPTION_EXECUTE_HANDLER )
|
|
{
|
|
DPF_ERR( "Exception encountered moving from video to system memory" );
|
|
this->fpVidMem = savevidmem;
|
|
this->lpVidMemHeap = savevidmemheap;
|
|
this->lPitch = savepitch;
|
|
this->dwReserved1 = savereserved;
|
|
this_lcl->dwReserved1 = savereserved_lcl;
|
|
this_lcl->ddsCaps.dwCaps = saveddscaps;
|
|
this_lcl->hDDSurface = savehddsurface;
|
|
if( hasvram )
|
|
{
|
|
if( use_full_lock )
|
|
{
|
|
DD_Surface_Unlock( (LPDIRECTDRAWSURFACE) this_int, NULL );
|
|
}
|
|
else
|
|
{
|
|
InternalUnlock( this_lcl, NULL, NULL, 0 );
|
|
}
|
|
}
|
|
return DDERR_EXCEPTION;
|
|
}
|
|
|
|
}
|
|
|
|
/*
|
|
* it worked, temporarily reset values and unlock surface
|
|
*/
|
|
if( hasvram )
|
|
{
|
|
newvidmem = this->fpVidMem;
|
|
// newvidmemheap = this->lpVidMemHeap; THIS IS NOT SET BY THE HEL
|
|
newreserved = this->dwReserved1;
|
|
newreserved_lcl = this_lcl->dwReserved1;
|
|
newpitch = this->lPitch;
|
|
newddscaps = this_lcl->ddsCaps.dwCaps;
|
|
newhddsurface = this_lcl->hDDSurface;
|
|
|
|
this->fpVidMem = savevidmem;
|
|
this->lpVidMemHeap = savevidmemheap;
|
|
this->lPitch = savepitch;
|
|
this->dwReserved1 = savereserved;
|
|
this_lcl->dwReserved1 = savereserved_lcl;
|
|
this_lcl->ddsCaps.dwCaps = saveddscaps;
|
|
this_lcl->hDDSurface = savehddsurface;
|
|
|
|
if( use_full_lock )
|
|
{
|
|
DD_Surface_Unlock( (LPDIRECTDRAWSURFACE) this_int, NULL );
|
|
}
|
|
else
|
|
{
|
|
InternalUnlock( this_lcl, NULL, NULL, 0 );
|
|
}
|
|
|
|
// Free the video memory, allow the driver to destroy the surface
|
|
DestroySurface( this_lcl );
|
|
// We just freed the memory but system memory surfaces never have
|
|
// this flag set so unset it.
|
|
this_lcl->lpGbl->dwGlobalFlags &= ~DDRAWISURFGBL_MEMFREE;
|
|
|
|
this->fpVidMem = newvidmem;
|
|
// this->lpVidMemHeap = newvidmemheap;
|
|
this->lpVidMemHeap = NULL; // should be NULL after HEL
|
|
this->lPitch = newpitch;
|
|
this->dwReserved1 = newreserved;
|
|
this_lcl->dwReserved1 = newreserved_lcl;
|
|
this_lcl->ddsCaps.dwCaps = newddscaps;
|
|
this_lcl->hDDSurface = newhddsurface;
|
|
}
|
|
|
|
|
|
/*
|
|
* the hel needs to know we touched the memory
|
|
*/
|
|
if( use_full_lock )
|
|
{
|
|
DD_Surface_Lock( (LPDIRECTDRAWSURFACE) this_int, NULL,
|
|
(LPDDSURFACEDESC)&ddsd, 0, NULL );
|
|
DD_Surface_Unlock( (LPDIRECTDRAWSURFACE) this_int, NULL );
|
|
}
|
|
else
|
|
{
|
|
InternalLock( this_lcl, &pbits, NULL, 0 );
|
|
InternalUnlock( this_lcl, NULL, NULL, 0 );
|
|
}
|
|
|
|
// 5/25/2000(RichGr): IA64: Use %p format specifier for 32/64-bit pointers.
|
|
DPF( 2, "Moved surface 0x%p to system memory", this_int );
|
|
return DD_OK;
|
|
|
|
} /* MoveToSystemMemory */
|
|
|
|
|
|
/*
|
|
* invalidateSurface
|
|
*
|
|
* invalidate one surface
|
|
*/
|
|
void invalidateSurface( LPDDRAWI_DDRAWSURFACE_LCL this_lcl )
|
|
{
|
|
if( !SURFACE_LOST( this_lcl ) )
|
|
{
|
|
if( this_lcl->ddsCaps.dwCaps & DDSCAPS_VIDEOMEMORY )
|
|
{
|
|
#ifdef USE_ALIAS
|
|
/*
|
|
* If the surface is locked then break the locks now.
|
|
* When a broken lock is finally unlocked by the API the
|
|
* driver is not called. So we get Create->Lock->Destroy
|
|
* rather than Create->Lock->Destroy->Unlock. Thus, drivers
|
|
* must be able to cope with Destroy undo any pending locks
|
|
* at the driver level but they should be able to cope with
|
|
* this as it could happen even before the alias changes.
|
|
*/
|
|
if(!(this_lcl->dwFlags & DDRAWISURF_DRIVERMANAGED) ||
|
|
(this_lcl->lpSurfMore->ddsCapsEx.dwCaps2 & DDSCAPS2_DONOTPERSIST))
|
|
{
|
|
if( this_lcl->lpGbl->dwUsageCount > 0)
|
|
{
|
|
// 5/25/2000(RichGr): IA64: Use %p format specifier for 32/64-bit pointers.
|
|
DPF( 4, "Breaking locks held on the surface 0x%p", this_lcl );
|
|
BreakSurfaceLocks( this_lcl->lpGbl );
|
|
}
|
|
}
|
|
#endif /* USE_ALIAS */
|
|
if (!(this_lcl->lpGbl->dwGlobalFlags & DDRAWISURFGBL_SYSMEMEXECUTEBUFFER))
|
|
{
|
|
if((this_lcl->dwFlags & DDRAWISURF_DRIVERMANAGED) &&
|
|
!(this_lcl->lpSurfMore->ddsCapsEx.dwCaps2 & DDSCAPS2_DONOTPERSIST))
|
|
{
|
|
LooseManagedSurface( this_lcl );
|
|
return;
|
|
}
|
|
else
|
|
DestroySurface( this_lcl );
|
|
}
|
|
}
|
|
if( (!(this_lcl->lpGbl->dwGlobalFlags & DDRAWISURFGBL_SYSMEMREQUESTED) ||
|
|
(this_lcl->dwFlags & DDRAWISURF_PARTOFPRIMARYCHAIN) ) &&
|
|
(!(this_lcl->lpGbl->dwGlobalFlags & DDRAWISURFGBL_SYSMEMEXECUTEBUFFER)) )
|
|
{
|
|
this_lcl->dwFlags |= DDRAWISURF_INVALID;
|
|
BUMP_SURFACE_STAMP(this_lcl->lpGbl);
|
|
}
|
|
}
|
|
} /* invalidateSurface */
|
|
|
|
/*
|
|
* invalidateAttachments
|
|
*
|
|
* invalidate all attachments to a surface
|
|
*/
|
|
static void invalidateAttachments( LPDDRAWI_DDRAWSURFACE_LCL this_lcl )
|
|
{
|
|
LPATTACHLIST pattachlist;
|
|
LPDDRAWI_DDRAWSURFACE_INT curr_int;
|
|
|
|
pattachlist = this_lcl->lpAttachList;
|
|
while( pattachlist != NULL )
|
|
{
|
|
curr_int = pattachlist->lpIAttached;
|
|
|
|
if( curr_int->lpLcl->dwFlags & DDRAWISURF_IMPLICITCREATE )
|
|
{
|
|
invalidateSurface( curr_int->lpLcl );
|
|
invalidateAttachments( curr_int->lpLcl );
|
|
}
|
|
pattachlist = pattachlist->lpLink;
|
|
}
|
|
|
|
} /* invalidateAttachments */
|
|
|
|
/*
|
|
* InvalidateAllPrimarySurfaces
|
|
*
|
|
* Traverses the driver object list and sets the invalid bit on all primary
|
|
* surfaces.
|
|
*/
|
|
void InvalidateAllPrimarySurfaces( LPDDRAWI_DIRECTDRAW_GBL this )
|
|
{
|
|
LPDDRAWI_DIRECTDRAW_LCL curr_lcl;
|
|
|
|
DPF(4, "******** invalidating all primary surfaces");
|
|
|
|
/*
|
|
* traverse the driver object list and invalidate all primaries for
|
|
* the specificed driver
|
|
*/
|
|
curr_lcl = lpDriverLocalList;
|
|
while( curr_lcl != NULL )
|
|
{
|
|
if( curr_lcl->lpGbl == this )
|
|
{
|
|
if( curr_lcl->lpPrimary != NULL )
|
|
{
|
|
invalidateSurface( curr_lcl->lpPrimary->lpLcl );
|
|
invalidateAttachments( curr_lcl->lpPrimary->lpLcl );
|
|
}
|
|
}
|
|
curr_lcl = curr_lcl->lpLink;
|
|
}
|
|
|
|
} /* InvalidateAllPrimarySurfaces */
|
|
|
|
#undef DPF_MODNAME
|
|
#define DPF_MODNAME "InvalidateAllSurfaces"
|
|
|
|
/*
|
|
* We define the page lock IOCTLs here so that we don't have to include ddvxd.h.
|
|
* These must match the corresponding entries in ddvxd.h
|
|
*/
|
|
#define DDVXD_IOCTL_MEMPAGELOCK 28
|
|
#define DDVXD_IOCTL_MEMPAGEUNLOCK 29
|
|
|
|
/*
|
|
* InvalidateAllSurfaces
|
|
*/
|
|
void InvalidateAllSurfaces( LPDDRAWI_DIRECTDRAW_GBL this, HANDLE hDDVxd, BOOL fRebuildAliases )
|
|
{
|
|
LPDDRAWI_DDRAWSURFACE_INT psurf_int;
|
|
LPDDRAWI_DDRAWSURFACE_LCL pTempLcl;
|
|
|
|
#pragma message( REMIND( "Failure conditions on InvalidateAllSurfaces need to be considered" ) )
|
|
|
|
#ifdef WIN95
|
|
BackupAllSurfaces(this);
|
|
CleanupD3D8(this, FALSE, 0);
|
|
#endif
|
|
|
|
DPF(4, "******** invalidating all surfaces");
|
|
|
|
#ifdef USE_ALIAS
|
|
/*
|
|
* As surface memory is about to be destroyed we need to ensure that
|
|
* anyone with outstanding locks is talking to dummy memory rather
|
|
* than real video memory
|
|
*
|
|
* NOTE: Not a lot we can do on failure here.
|
|
*/
|
|
if( ( NULL != this->phaiHeapAliases ) && ( this->phaiHeapAliases->dwRefCnt > 1UL ) )
|
|
{
|
|
DDASSERT( INVALID_HANDLE_VALUE != hDDVxd );
|
|
if( FAILED( MapHeapAliasesToDummyMem( hDDVxd, this->phaiHeapAliases ) ) )
|
|
{
|
|
// 5/25/2000(RichGr): IA64: Use %p format specifier for 32/64-bit pointers.
|
|
DPF( 0, "Could not map heap aliases for driver object 0x%p", this );
|
|
DDASSERT( FALSE );
|
|
}
|
|
|
|
if( fRebuildAliases )
|
|
{
|
|
ReleaseHeapAliases( hDDVxd, this->phaiHeapAliases );
|
|
this->phaiHeapAliases = NULL;
|
|
if( FAILED( CreateHeapAliases( hDDVxd, this ) ) )
|
|
{
|
|
// 5/25/2000(RichGr): IA64: Use %p format specifier for 32/64-bit pointers.
|
|
DPF( 0, "Could not create the heap aliases for driver object 0x%p", this );
|
|
DDASSERT( FALSE );
|
|
/*
|
|
* Not much we can do if anything goes wrong so simply fail over to needing
|
|
* to hold the Win16 lock.
|
|
*/
|
|
this->dwFlags |= DDRAWI_NEEDSWIN16FORVRAMLOCK;
|
|
}
|
|
}
|
|
}
|
|
#endif /* USE_ALIAS */
|
|
|
|
psurf_int = this->dsList;
|
|
|
|
while( psurf_int != NULL )
|
|
{
|
|
pTempLcl = psurf_int->lpLcl;
|
|
psurf_int = psurf_int->lpLink;
|
|
invalidateSurface( pTempLcl );
|
|
}
|
|
|
|
} /* InvalidateAllSurfaces */
|
|
|
|
/*
|
|
* FindGlobalPrimary
|
|
*
|
|
* Traverses the driver object list and looks for a primary surface (it doesn't
|
|
* matter if it is invalid). If it finds one, it returns a pointer to the
|
|
* global portion of that surface. If it doesn't, it returns NULL
|
|
*/
|
|
LPDDRAWI_DDRAWSURFACE_GBL FindGlobalPrimary( LPDDRAWI_DIRECTDRAW_GBL this )
|
|
{
|
|
LPDDRAWI_DIRECTDRAW_LCL curr_lcl;
|
|
LPDDRAWI_DDRAWSURFACE_INT psurf_int;
|
|
|
|
curr_lcl = lpDriverLocalList;
|
|
while( curr_lcl != NULL )
|
|
{
|
|
if( curr_lcl->lpGbl == this )
|
|
{
|
|
psurf_int = curr_lcl->lpPrimary;
|
|
if( psurf_int && !SURFACE_LOST( psurf_int->lpLcl ) )
|
|
{
|
|
return psurf_int->lpLcl->lpGbl;
|
|
}
|
|
}
|
|
curr_lcl = curr_lcl->lpLink;
|
|
}
|
|
|
|
return NULL;
|
|
|
|
} /* FindGlobalPrimary */
|
|
|
|
#ifdef SHAREDZ
|
|
/*
|
|
* FindGlobalZBuffer
|
|
*
|
|
* Traverses the driver object list and looks for a global shared Z. If it
|
|
* finds one, it returns a pointer to the global portion of that surface.
|
|
* If it doesn't, it returns NULL.
|
|
*
|
|
* NOTE: This function will return a shared Z buffer even if it has been lost.
|
|
* However, it will only return a shared Z buffer if it was created in the
|
|
* current mode. The idea being that there is one shared Z-buffer per mode
|
|
* and we will only return the shared Z-buffer for the current mode.
|
|
*/
|
|
LPDDRAWI_DDRAWSURFACE_GBL FindGlobalZBuffer( LPDDRAWI_DIRECTDRAW_GBL this )
|
|
{
|
|
LPDDRAWI_DIRECTDRAW_LCL curr_lcl;
|
|
LPDDRAWI_DDRAWSURFACE_LCL psurf_lcl;
|
|
|
|
curr_lcl = lpDriverLocalList;
|
|
while( curr_lcl != NULL )
|
|
{
|
|
if( curr_lcl->lpGbl == this )
|
|
{
|
|
psurf_lcl = curr_lcl->lpSharedZ;
|
|
if( psurf_lcl && ( psurf_lcl->dwModeCreatedIn == this->dwModeIndex ) )
|
|
{
|
|
return psurf_lcl->lpGbl;
|
|
}
|
|
}
|
|
curr_lcl = curr_lcl->lpLink;
|
|
}
|
|
|
|
return NULL;
|
|
|
|
} /* FindGlobalZBuffer */
|
|
|
|
/*
|
|
* FindGlobalBackBuffer
|
|
*
|
|
* Traverses the driver object list and looks for a global shared back-buffer.
|
|
* If it finds one, it returns a pointer to the global portion of that surface.
|
|
* If it doesn't, it returns NULL.
|
|
*
|
|
* NOTE: This function will return a shared back buffer even if it has been lost.
|
|
* However, it will only return a shared back buffer if it was created in the
|
|
* current mode. The idea being that there is one shared back-buffer per mode and
|
|
* we will only return the shared back-buffer for the current mode.
|
|
*/
|
|
LPDDRAWI_DDRAWSURFACE_GBL FindGlobalBackBuffer( LPDDRAWI_DIRECTDRAW_GBL this )
|
|
{
|
|
LPDDRAWI_DIRECTDRAW_LCL curr_lcl;
|
|
LPDDRAWI_DDRAWSURFACE_LCL psurf_lcl;
|
|
|
|
curr_lcl = lpDriverLocalList;
|
|
while( curr_lcl != NULL )
|
|
{
|
|
if( curr_lcl->lpGbl == this )
|
|
{
|
|
psurf_lcl = curr_lcl->lpSharedBack;
|
|
if( psurf_lcl && ( psurf_lcl->dwModeCreatedIn == this->dwModeIndex ) )
|
|
{
|
|
return psurf_lcl->lpGbl;
|
|
}
|
|
}
|
|
curr_lcl = curr_lcl->lpLink;
|
|
}
|
|
|
|
return NULL;
|
|
|
|
} /* FindGlobalBackBuffer */
|
|
#endif
|
|
|
|
/*
|
|
* MatchPrimary
|
|
*
|
|
* Traverses the driver object list and looks for valid primary surfaces. If
|
|
* a valid primary surface is found, it attempts to verify that the
|
|
* surface described by lpDDSD is compatible with the existing primary. If
|
|
* it is, the process continues until all valid primary surfaces have been
|
|
* checked. If a primary surface is not compatible, lpDDSD is modified to
|
|
* show a surface description which would have succeeded and FALSE is returned.
|
|
*/
|
|
BOOL MatchPrimary( LPDDRAWI_DIRECTDRAW_GBL pdrv, LPDDSURFACEDESC2 lpDDSD )
|
|
{
|
|
/*
|
|
* right now, the only requirement for two primary surfaces to be
|
|
* compatible is that they must both be allocated in video memory or in
|
|
* system memory. Traverse the driver object list until a valid primary
|
|
* surface is found. If a surface is found, verify that it is compatible
|
|
* with the requested surface. If no valid primary surface is found,
|
|
* return TRUE.
|
|
*/
|
|
LPDDRAWI_DDRAWSURFACE_INT psurf_int;
|
|
LPDDRAWI_DDRAWSURFACE_LCL psurf_lcl;
|
|
LPDDRAWI_DIRECTDRAW_LCL curr_lcl;
|
|
|
|
curr_lcl = lpDriverLocalList;
|
|
while( curr_lcl != NULL )
|
|
{
|
|
/*
|
|
* is this object pointing to the same driver data?
|
|
*/
|
|
if( curr_lcl->lpGbl == pdrv )
|
|
{
|
|
psurf_int = curr_lcl->lpPrimary;
|
|
if( psurf_int && !SURFACE_LOST( psurf_int->lpLcl ) )
|
|
{
|
|
psurf_lcl = psurf_int->lpLcl;
|
|
if( (psurf_lcl->ddsCaps.dwCaps & DDSCAPS_SYSTEMMEMORY) &&
|
|
(lpDDSD->ddsCaps.dwCaps & DDSCAPS_VIDEOMEMORY) )
|
|
{
|
|
lpDDSD->ddsCaps.dwCaps &= ~DDSCAPS_VIDEOMEMORY;
|
|
lpDDSD->ddsCaps.dwCaps |= DDSCAPS_SYSTEMMEMORY;
|
|
return FALSE;
|
|
}
|
|
if( (psurf_lcl->ddsCaps.dwCaps & DDSCAPS_VIDEOMEMORY) &&
|
|
(lpDDSD->ddsCaps.dwCaps & DDSCAPS_SYSTEMMEMORY) )
|
|
{
|
|
lpDDSD->ddsCaps.dwCaps &= ~DDSCAPS_SYSTEMMEMORY;
|
|
lpDDSD->ddsCaps.dwCaps |= DDSCAPS_VIDEOMEMORY;
|
|
return FALSE;
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
curr_lcl = curr_lcl->lpLink;
|
|
}
|
|
return TRUE;
|
|
|
|
} /* MatchPrimary */
|
|
|
|
#ifdef SHAREDZ
|
|
/*
|
|
* MatchSharedZBuffer
|
|
*
|
|
* Traverses the driver object list and looks for valid shared Z buffers. If
|
|
* a valid shared Z buffer is found, it attempts to verify that the
|
|
* surface described by lpDDSD is compatible with the existing shared Z buffer.
|
|
* If it is, the process continues until all valid shared Z buffers have been
|
|
* checked. If a shared Z buffer is not compatible, lpDDSD is modified to
|
|
* show a surface description which would have succeeded and FALSE is returned.
|
|
*/
|
|
BOOL MatchSharedZBuffer( LPDDRAWI_DIRECTDRAW_GBL pdrv, LPDDSURFACEDESC lpDDSD )
|
|
{
|
|
/*
|
|
* Currently we allow one shared Z-buffer per mode. So we don't care if we
|
|
* don't match against any other shared Z-buffers in different modes. We
|
|
* only need to match against shared Z-buffers created in the current mode.
|
|
*
|
|
* If we do come across another shared Z-buffer in the same mode then we
|
|
* check to ensure that its in the same type of memory (SYSTEM or VIDEO)
|
|
* and that the requested depths match.
|
|
*/
|
|
LPDDRAWI_DDRAWSURFACE_LCL psurf_lcl;
|
|
LPDDRAWI_DDRAWSURFACE_GBL psurf;
|
|
LPDDRAWI_DIRECTDRAW_LCL curr_lcl;
|
|
LPDDPIXELFORMAT lpddpf;
|
|
|
|
curr_lcl = lpDriverLocalList;
|
|
while( curr_lcl != NULL )
|
|
{
|
|
/*
|
|
* is this object pointing to the same driver data?
|
|
*/
|
|
if( curr_lcl->lpGbl == pdrv )
|
|
{
|
|
psurf_lcl = curr_lcl->lpSharedZ;
|
|
if( psurf_lcl && ( psurf_lcl->dwModeCreatedIn == pdrv->dwModeIndex ) )
|
|
{
|
|
if( (psurf_lcl->ddsCaps.dwCaps & DDSCAPS_SYSTEMMEMORY) &&
|
|
(lpDDSD->ddsCaps.dwCaps & DDSCAPS_VIDEOMEMORY) )
|
|
{
|
|
lpDDSD->ddsCaps.dwCaps &= ~DDSCAPS_VIDEOMEMORY;
|
|
lpDDSD->ddsCaps.dwCaps |= DDSCAPS_SYSTEMMEMORY;
|
|
return FALSE;
|
|
}
|
|
if( (psurf_lcl->ddsCaps.dwCaps & DDSCAPS_VIDEOMEMORY) &&
|
|
(lpDDSD->ddsCaps.dwCaps & DDSCAPS_SYSTEMMEMORY) )
|
|
{
|
|
lpDDSD->ddsCaps.dwCaps &= ~DDSCAPS_SYSTEMMEMORY;
|
|
lpDDSD->ddsCaps.dwCaps |= DDSCAPS_VIDEOMEMORY;
|
|
return FALSE;
|
|
}
|
|
|
|
psurf = psurf_lcl->lpGbl;
|
|
/*
|
|
* !!! NOTE: For when I finally get round to putting
|
|
* asserts in the code.
|
|
* ASSERT( psurf != NULL );
|
|
*/
|
|
GET_PIXEL_FORMAT( psurf_lcl, psurf, lpddpf );
|
|
/*
|
|
* ASSERT( lpddpf != NULL );
|
|
* ASSERT( lpddpf->dwFlags & DDPF_ZBUFFER );
|
|
*/
|
|
if( lpddpf->dwZBufferBitDepth != lpDDSD->dwZBufferBitDepth )
|
|
{
|
|
lpDDSD->dwZBufferBitDepth = lpddpf->dwZBufferBitDepth;
|
|
return FALSE;
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
curr_lcl = curr_lcl->lpLink;
|
|
}
|
|
return TRUE;
|
|
|
|
} /* MatchSharedZBuffer */
|
|
|
|
/*
|
|
* MatchSharedBackBuffer
|
|
*
|
|
* Traverses the driver object list and looks for valid shared back buffers. If
|
|
* a valid shared back buffer is found, it attempts to verify that the
|
|
* surface described by lpDDSD is compatible with the existing shared back buffer.
|
|
* If it is, the process continues until all valid shared back buffers have been
|
|
* checked. If a shared back buffer is not compatible, lpDDSD is modified to
|
|
* show a surface description which would have succeeded and FALSE is returned.
|
|
*/
|
|
BOOL MatchSharedBackBuffer( LPDDRAWI_DIRECTDRAW_GBL pdrv, LPDDSURFACEDESC lpDDSD )
|
|
{
|
|
/*
|
|
* Currently we allow one shared back-buffer per mode. So we don't care if we
|
|
* don't match against any other shared back-buffers in different modes. We
|
|
* only need to match against shared back-buffers created in the current mode.
|
|
*
|
|
* If we do come across another shared back-buffer in the same mode then we
|
|
* check to ensure that its in the same type of memory (SYSTEM or VIDEO)
|
|
* and that its pixel format matches.
|
|
*/
|
|
LPDDRAWI_DDRAWSURFACE_LCL psurf_lcl;
|
|
LPDDRAWI_DDRAWSURFACE_GBL psurf;
|
|
LPDDRAWI_DIRECTDRAW_LCL curr_lcl;
|
|
LPDDPIXELFORMAT lpddpf1;
|
|
LPDDPIXELFORMAT lpddpf2;
|
|
|
|
if( lpDDSD->dwFlags & DDSD_PIXELFORMAT )
|
|
lpddpf2 = &lpDDSD->ddpfPixelFormat;
|
|
else
|
|
lpddpf2 = &pdrv->vmiData.ddpfDisplay;
|
|
|
|
curr_lcl = lpDriverLocalList;
|
|
while( curr_lcl != NULL )
|
|
{
|
|
/*
|
|
* is this object pointing to the same driver data?
|
|
*/
|
|
if( curr_lcl->lpGbl == pdrv )
|
|
{
|
|
psurf_lcl = curr_lcl->lpSharedBack;
|
|
if( psurf_lcl && ( psurf_lcl->dwModeCreatedIn == pdrv->dwModeIndex ) )
|
|
{
|
|
if( (psurf_lcl->ddsCaps.dwCaps & DDSCAPS_SYSTEMMEMORY) &&
|
|
(lpDDSD->ddsCaps.dwCaps & DDSCAPS_VIDEOMEMORY) )
|
|
{
|
|
lpDDSD->ddsCaps.dwCaps &= ~DDSCAPS_VIDEOMEMORY;
|
|
lpDDSD->ddsCaps.dwCaps |= DDSCAPS_SYSTEMMEMORY;
|
|
return FALSE;
|
|
}
|
|
if( (psurf_lcl->ddsCaps.dwCaps & DDSCAPS_VIDEOMEMORY) &&
|
|
(lpDDSD->ddsCaps.dwCaps & DDSCAPS_SYSTEMMEMORY) )
|
|
{
|
|
lpDDSD->ddsCaps.dwCaps &= ~DDSCAPS_SYSTEMMEMORY;
|
|
lpDDSD->ddsCaps.dwCaps |= DDSCAPS_VIDEOMEMORY;
|
|
return FALSE;
|
|
}
|
|
|
|
psurf = psurf_lcl->lpGbl;
|
|
/*
|
|
* !!! NOTE: For when I finally get round to putting
|
|
* asserts in the code.
|
|
* ASSERT( psurf != NULL );
|
|
*/
|
|
GET_PIXEL_FORMAT( psurf_lcl, psurf, lpddpf1 );
|
|
|
|
/*
|
|
* ASSERT( lpddpf1 != NULL );
|
|
*/
|
|
if( IsDifferentPixelFormat( lpddpf1, lpddpf2 ) )
|
|
{
|
|
lpDDSD->dwFlags |= DDSD_PIXELFORMAT;
|
|
memcpy( &lpDDSD->ddpfPixelFormat, lpddpf1, sizeof( DDPIXELFORMAT ) );
|
|
return FALSE;
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
curr_lcl = curr_lcl->lpLink;
|
|
}
|
|
return TRUE;
|
|
|
|
} /* MatchSharedBackBuffer */
|
|
#endif
|
|
|
|
#undef DPF_MODNAME
|
|
#define DPF_MODNAME "PageLock"
|
|
|
|
/*
|
|
* DD_Surface_PageLock
|
|
*
|
|
* Prevents a system memory surface from being paged out.
|
|
*/
|
|
HRESULT DDAPI DD_Surface_PageLock(
|
|
LPDIRECTDRAWSURFACE lpDDSurface,
|
|
DWORD dwFlags )
|
|
{
|
|
LPDDRAWI_DDRAWSURFACE_INT this_int;
|
|
LPDDRAWI_DDRAWSURFACE_LCL this_lcl;
|
|
LPDDRAWI_DDRAWSURFACE_GBL this;
|
|
LPDDRAWI_DIRECTDRAW_LCL pdrv_lcl;
|
|
LPDDRAWI_DIRECTDRAW_GBL pdrv;
|
|
HRESULT hr;
|
|
|
|
ENTER_DDRAW();
|
|
|
|
DPF(2,A,"ENTERAPI: DD_Surface_PageLock");
|
|
/* DPF_ENTERAPI(lpDDSurface); */
|
|
|
|
TRY
|
|
{
|
|
this_int = (LPDDRAWI_DDRAWSURFACE_INT) lpDDSurface;
|
|
if( !VALID_DIRECTDRAWSURFACE_PTR( this_int ) )
|
|
{
|
|
LEAVE_DDRAW();
|
|
return DDERR_INVALIDOBJECT;
|
|
}
|
|
this_lcl = this_int->lpLcl;
|
|
this = this_lcl->lpGbl;
|
|
|
|
if( dwFlags & ~DDPAGELOCK_VALID )
|
|
{
|
|
DPF_ERR( "Invalid flags") ;
|
|
LEAVE_DDRAW();
|
|
return DDERR_INVALIDPARAMS;
|
|
}
|
|
|
|
if( SURFACE_LOST( this_lcl ) )
|
|
{
|
|
LEAVE_DDRAW();
|
|
return DDERR_SURFACELOST;
|
|
}
|
|
|
|
pdrv_lcl = this_lcl->lpSurfMore->lpDD_lcl;
|
|
pdrv = pdrv_lcl->lpGbl;
|
|
}
|
|
EXCEPT( EXCEPTION_EXECUTE_HANDLER )
|
|
{
|
|
DPF_ERR( "Exception encountered validating parameters" );
|
|
LEAVE_DDRAW();
|
|
return DDERR_INVALIDPARAMS;
|
|
}
|
|
|
|
//
|
|
// For now, if the current surface is optimized, quit
|
|
//
|
|
if (this_lcl->ddsCaps.dwCaps & DDSCAPS_OPTIMIZED)
|
|
{
|
|
DPF_ERR( "It is an optimized surface" );
|
|
LEAVE_DDRAW();
|
|
return DDERR_ISOPTIMIZEDSURFACE;
|
|
}
|
|
|
|
// Don't pagelock video memory or emulated primary surface
|
|
if( (this_lcl->ddsCaps.dwCaps & DDSCAPS_SYSTEMMEMORY ) &&
|
|
!(this_lcl->ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE ) )
|
|
{
|
|
hr = InternalPageLock(this_lcl, pdrv_lcl);
|
|
}
|
|
else
|
|
{
|
|
// Succeed but don't do anything if surface has video memory
|
|
// or if this is the emulated primary surface
|
|
hr = DD_OK;
|
|
}
|
|
|
|
LEAVE_DDRAW();
|
|
return hr;
|
|
}
|
|
|
|
#undef DPF_MODNAME
|
|
#define DPF_MODNAME "PageUnlock"
|
|
|
|
/*
|
|
* DD_Surface_PageUnlock
|
|
*/
|
|
HRESULT DDAPI DD_Surface_PageUnlock(
|
|
LPDIRECTDRAWSURFACE lpDDSurface,
|
|
DWORD dwFlags )
|
|
{
|
|
LPDDRAWI_DDRAWSURFACE_INT this_int;
|
|
LPDDRAWI_DDRAWSURFACE_LCL this_lcl;
|
|
LPDDRAWI_DDRAWSURFACE_GBL this;
|
|
LPDDRAWI_DIRECTDRAW_LCL pdrv_lcl;
|
|
LPDDRAWI_DIRECTDRAW_GBL pdrv;
|
|
HRESULT hr;
|
|
|
|
ENTER_DDRAW();
|
|
|
|
DPF(2,A,"ENTERAPI: DD_Surface_PageUnlock");
|
|
|
|
/* DPF_ENTERAPI(lpDDSurface); */
|
|
|
|
TRY
|
|
{
|
|
this_int = (LPDDRAWI_DDRAWSURFACE_INT) lpDDSurface;
|
|
if( !VALID_DIRECTDRAWSURFACE_PTR( this_int ) )
|
|
{
|
|
LEAVE_DDRAW();
|
|
return DDERR_INVALIDOBJECT;
|
|
}
|
|
this_lcl = this_int->lpLcl;
|
|
this = this_lcl->lpGbl;
|
|
|
|
if( dwFlags & ~DDPAGEUNLOCK_VALID )
|
|
{
|
|
DPF_ERR( "Invalid flags") ;
|
|
LEAVE_DDRAW();
|
|
return DDERR_INVALIDPARAMS;
|
|
}
|
|
|
|
if( SURFACE_LOST( this_lcl ) )
|
|
{
|
|
LEAVE_DDRAW();
|
|
return DDERR_SURFACELOST;
|
|
}
|
|
|
|
pdrv_lcl = this_lcl->lpSurfMore->lpDD_lcl;
|
|
pdrv = pdrv_lcl->lpGbl;
|
|
}
|
|
EXCEPT( EXCEPTION_EXECUTE_HANDLER )
|
|
{
|
|
DPF_ERR( "Exception encountered validating parameters" );
|
|
LEAVE_DDRAW();
|
|
return DDERR_INVALIDPARAMS;
|
|
}
|
|
|
|
//
|
|
// For now, if the current surface is optimized, quit
|
|
//
|
|
if (this_lcl->ddsCaps.dwCaps & DDSCAPS_OPTIMIZED)
|
|
{
|
|
DPF_ERR( "It is an optimized surface" );
|
|
LEAVE_DDRAW();
|
|
return DDERR_ISOPTIMIZEDSURFACE;
|
|
}
|
|
|
|
// Don't pageunlock video memory or emulated primary surface
|
|
if( (this_lcl->ddsCaps.dwCaps & DDSCAPS_SYSTEMMEMORY ) &&
|
|
!(this_lcl->ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE ) )
|
|
{
|
|
hr = InternalPageUnlock(this_lcl, pdrv_lcl);
|
|
}
|
|
else
|
|
{
|
|
// Succeed but don't do anything if surface has video memory
|
|
// or if this is the emulated primary surface
|
|
hr = DD_OK;
|
|
}
|
|
|
|
LEAVE_DDRAW();
|
|
return hr;
|
|
}
|
|
|
|
/*
|
|
* InternalPageLock
|
|
*
|
|
* Assumes driver lock is taken
|
|
*/
|
|
|
|
HRESULT InternalPageLock( LPDDRAWI_DDRAWSURFACE_LCL this_lcl,
|
|
LPDDRAWI_DIRECTDRAW_LCL pdrv_lcl )
|
|
{
|
|
BOOL rc;
|
|
DWORD cbReturned;
|
|
DWORD dwReturn;
|
|
LPDDRAWI_DDRAWSURFACE_GBL_MORE lpSurfGblMore = GET_LPDDRAWSURFACE_GBL_MORE(this_lcl->lpGbl);
|
|
|
|
struct _PLin
|
|
{
|
|
LPVOID pMem;
|
|
DWORD cbBuffer;
|
|
DWORD dwFlags;
|
|
LPDWORD pdwTable;
|
|
LPDWORD ppTable;
|
|
} PLin;
|
|
|
|
#ifndef WINNT
|
|
// If we're already locked; then just increment the count
|
|
if( this_lcl->lpSurfMore->dwPageLockCount )
|
|
{
|
|
this_lcl->lpSurfMore->dwPageLockCount++;
|
|
return DD_OK;
|
|
}
|
|
|
|
// Sanity Check
|
|
DDASSERT( this_lcl->ddsCaps.dwCaps & DDSCAPS_SYSTEMMEMORY );
|
|
DDASSERT( !(this_lcl->ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE) );
|
|
|
|
// Initialize Parameters to pass to VXD
|
|
PLin.pMem = (LPVOID)this_lcl->lpGbl->fpVidMem;
|
|
DDASSERT( PLin.pMem );
|
|
PLin.cbBuffer = this_lcl->lpSurfMore->dwBytesAllocated;
|
|
DDASSERT( PLin.cbBuffer );
|
|
PLin.dwFlags = 0;
|
|
|
|
PLin.pdwTable = &lpSurfGblMore->dwPhysicalPageTable;
|
|
PLin.ppTable = (LPDWORD) &lpSurfGblMore->pPageTable;
|
|
|
|
DDASSERT( pdrv_lcl->hDDVxd );
|
|
rc = DeviceIoControl( (HANDLE)(pdrv_lcl->hDDVxd),
|
|
DDVXD_IOCTL_MEMPAGELOCK,
|
|
&PLin,
|
|
sizeof( PLin ),
|
|
&dwReturn,
|
|
sizeof( dwReturn ),
|
|
&cbReturned,
|
|
NULL );
|
|
|
|
if( !rc )
|
|
{
|
|
lpSurfGblMore->dwPhysicalPageTable = 0;
|
|
lpSurfGblMore->pPageTable = 0;
|
|
lpSurfGblMore->cPages = 0;
|
|
return DDERR_CANTPAGELOCK;
|
|
}
|
|
DDASSERT( cbReturned == sizeof(dwReturn));
|
|
DDASSERT( *PLin.pdwTable && *PLin.ppTable );
|
|
DDASSERT( lpSurfGblMore->dwPhysicalPageTable && lpSurfGblMore->pPageTable );
|
|
|
|
// Massage Table
|
|
{
|
|
unsigned i;
|
|
DWORD *rgdwPhysical = lpSurfGblMore->pPageTable;
|
|
|
|
// Compute the number of pages
|
|
DWORD cPages = (((DWORD)PLin.pMem & 0xFFF) + 0xFFF + PLin.cbBuffer)/4096;
|
|
|
|
// Set the number of pages
|
|
lpSurfGblMore->cPages = cPages;
|
|
|
|
// Mask out the page-table flags
|
|
for( i = 0; i < cPages; i++ )
|
|
{
|
|
// Check that the page is present, user-accessible, and read/write
|
|
DDASSERT( rgdwPhysical[i] & 0x7 );
|
|
// Clear out the low bits
|
|
rgdwPhysical[i] &= 0xFFFFF000;
|
|
}
|
|
// Fix the first entry to point to the starting address
|
|
rgdwPhysical[0] |= ((DWORD)PLin.pMem & 0xFFF);
|
|
}
|
|
|
|
this_lcl->lpSurfMore->dwPageLockCount++;
|
|
DDASSERT( this_lcl->lpSurfMore->dwPageLockCount == 1 );
|
|
|
|
// 5/25/2000(RichGr): IA64: Use %p format specifier for 32/64-bit pointers.
|
|
DPF( 5, "Page Locked %d bytes at 0x%p (count=%d)", PLin.cbBuffer, PLin.pMem,
|
|
this_lcl->lpSurfMore->dwPageLockCount );
|
|
|
|
#endif
|
|
|
|
return DD_OK;
|
|
}
|
|
|
|
HRESULT InternalPageUnlock( LPDDRAWI_DDRAWSURFACE_LCL this_lcl,
|
|
LPDDRAWI_DIRECTDRAW_LCL pdrv_lcl )
|
|
{
|
|
BOOL rc;
|
|
DWORD cbReturned;
|
|
DWORD dwReturn;
|
|
struct _PLin
|
|
{
|
|
LPVOID pMem;
|
|
DWORD cbBuffer;
|
|
DWORD dwFlags;
|
|
LPDWORD pTable;
|
|
} PLin;
|
|
|
|
#ifndef WINNT
|
|
|
|
LPDDRAWI_DDRAWSURFACE_GBL_MORE lpSurfGblMore = GET_LPDDRAWSURFACE_GBL_MORE(this_lcl->lpGbl);
|
|
|
|
DDASSERT( this_lcl->ddsCaps.dwCaps & DDSCAPS_SYSTEMMEMORY );
|
|
DDASSERT( !(this_lcl->ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE) );
|
|
|
|
if( this_lcl->lpSurfMore->dwPageLockCount <= 0 )
|
|
{
|
|
return DDERR_NOTPAGELOCKED;
|
|
}
|
|
|
|
// If we're already locked more than once; then just decrement the count
|
|
if( this_lcl->lpSurfMore->dwPageLockCount > 1 )
|
|
{
|
|
this_lcl->lpSurfMore->dwPageLockCount--;
|
|
return DD_OK;
|
|
}
|
|
|
|
/*
|
|
* If it's a system memory surface, better wait for any pending DMA operations
|
|
* to finish.
|
|
*/
|
|
if( this_lcl->lpGbl->dwGlobalFlags & DDRAWISURFGBL_HARDWAREOPSTARTED )
|
|
{
|
|
WaitForDriverToFinishWithSurface( pdrv_lcl, this_lcl );
|
|
}
|
|
|
|
PLin.pMem = (LPVOID)this_lcl->lpGbl->fpVidMem;
|
|
DDASSERT( PLin.pMem );
|
|
PLin.cbBuffer = this_lcl->lpSurfMore->dwBytesAllocated;
|
|
DDASSERT( PLin.cbBuffer );
|
|
PLin.dwFlags = 0;
|
|
PLin.pTable = lpSurfGblMore->pPageTable;
|
|
|
|
DDASSERT( pdrv_lcl->hDDVxd );
|
|
rc = DeviceIoControl((HANDLE)(pdrv_lcl->hDDVxd),
|
|
DDVXD_IOCTL_MEMPAGEUNLOCK,
|
|
&PLin,
|
|
sizeof( PLin ),
|
|
&dwReturn,
|
|
sizeof( dwReturn ),
|
|
&cbReturned,
|
|
NULL);
|
|
|
|
if( !rc )
|
|
return DDERR_CANTPAGEUNLOCK;
|
|
DDASSERT( cbReturned == sizeof(dwReturn) );
|
|
|
|
this_lcl->lpSurfMore->dwPageLockCount--;
|
|
|
|
DDASSERT( this_lcl->lpSurfMore->dwPageLockCount == 0 );
|
|
|
|
lpSurfGblMore->dwPhysicalPageTable = 0;
|
|
lpSurfGblMore->pPageTable = 0;
|
|
lpSurfGblMore->cPages = 0;
|
|
|
|
// 5/25/2000(RichGr): IA64: Use %p format specifier for 32/64-bit pointers.
|
|
DPF(5, "Page Unlocked %d bytes at 0x%p (count=%d)", PLin.cbBuffer, PLin.pMem,
|
|
this_lcl->lpSurfMore->dwPageLockCount);
|
|
|
|
// Increment a timestamp counter; this will help
|
|
// a driver determine if the physical addresses have
|
|
// changed between the time that they have cached it
|
|
// and the time of the Blt/Render call
|
|
lpSurfGblMore->cPageUnlocks++;
|
|
|
|
#endif
|
|
|
|
return DD_OK;
|
|
}
|
|
|
|
HRESULT DDAPI DD_Surface_GetDDInterface(
|
|
LPDIRECTDRAWSURFACE lpDDSurface,
|
|
LPVOID FAR *lplpDD )
|
|
{
|
|
LPDDRAWI_DDRAWSURFACE_INT this_int;
|
|
LPDDRAWI_DIRECTDRAW_INT pdrv_int;
|
|
|
|
ENTER_DDRAW();
|
|
|
|
DPF(2,A,"ENTERAPI: DD_Surface_GetDDInterface");
|
|
|
|
TRY
|
|
{
|
|
this_int = (LPDDRAWI_DDRAWSURFACE_INT) lpDDSurface;
|
|
if( !VALID_DIRECTDRAWSURFACE_PTR( this_int ) )
|
|
{
|
|
LEAVE_DDRAW();
|
|
return DDERR_INVALIDOBJECT;
|
|
}
|
|
if( !VALID_PTR_PTR( lplpDD ) )
|
|
{
|
|
DPF_ERR( "Invalid DirectDraw Interface ptr ptr" );
|
|
LEAVE_DDRAW();
|
|
return DDERR_INVALIDPARAMS;
|
|
}
|
|
pdrv_int = this_int->lpLcl->lpSurfMore->lpDD_int;
|
|
*lplpDD = pdrv_int;
|
|
}
|
|
EXCEPT( EXCEPTION_EXECUTE_HANDLER )
|
|
{
|
|
DPF_ERR( "Exception encountered validating parameters" );
|
|
LEAVE_DDRAW();
|
|
return DDERR_INVALIDPARAMS;
|
|
}
|
|
|
|
// Addref the interface before giving it back to the app
|
|
DD_AddRef( (LPDIRECTDRAW)pdrv_int );
|
|
|
|
LEAVE_DDRAW();
|
|
return DD_OK;
|
|
|
|
} /* DD_Surface_GetDDInterface */
|
|
|
|
HRESULT InternalAssociateDC(
|
|
HDC hdc,
|
|
LPDDRAWI_DDRAWSURFACE_LCL pdds_lcl )
|
|
{
|
|
DCINFO *pdcinfo;
|
|
|
|
DDASSERT( hdc != NULL );
|
|
DDASSERT( pdds_lcl != NULL );
|
|
|
|
pdcinfo = (DCINFO *)MemAlloc( sizeof( DCINFO ) );
|
|
if( pdcinfo == NULL )
|
|
{
|
|
return DDERR_OUTOFMEMORY;
|
|
}
|
|
|
|
// initialize element
|
|
pdcinfo->hdc = hdc;
|
|
pdcinfo->pdds_lcl = pdds_lcl;
|
|
|
|
// Add element to front of list
|
|
pdcinfo->pdcinfoNext = g_pdcinfoHead;
|
|
g_pdcinfoHead = pdcinfo;
|
|
|
|
return DD_OK;
|
|
}
|
|
|
|
HRESULT InternalRemoveDCFromList(
|
|
HDC hdc,
|
|
LPDDRAWI_DDRAWSURFACE_LCL pdds_lcl )
|
|
{
|
|
// We may or may not have an hdc passed in.
|
|
// However, this lets us do an error check for
|
|
// some bad parameter cases.
|
|
DCINFO *pdcinfo;
|
|
DCINFO *pdcinfoPrev = NULL;
|
|
|
|
DDASSERT( pdds_lcl != NULL );
|
|
for( pdcinfo = g_pdcinfoHead; pdcinfo != NULL;
|
|
pdcinfoPrev = pdcinfo, pdcinfo = pdcinfo->pdcinfoNext )
|
|
{
|
|
DDASSERT( pdcinfo->pdds_lcl != NULL );
|
|
|
|
if( pdds_lcl == pdcinfo->pdds_lcl || hdc == pdcinfo->hdc )
|
|
{
|
|
// Check that punk & hdc are in synch -or-
|
|
// we didn't have an hdc passed in..
|
|
DDASSERT( hdc == NULL || (pdds_lcl == pdcinfo->pdds_lcl && hdc == pdcinfo->hdc) );
|
|
|
|
// Release this DC. We do this because it is dangerous
|
|
// to leave it around for windows to use because it points
|
|
// surface that we have just freed.
|
|
//
|
|
// However, don't release DCs that were created with the
|
|
// GetDC flag since that is automatically cleaned up by
|
|
// Windows. (Moreover, it wasn't allocated by DD16 who'll
|
|
// get confused.)
|
|
if( hdc == NULL && !(pdds_lcl->dwFlags & DDRAWISURF_GETDCNULL) )
|
|
{
|
|
DDASSERT( pdcinfo->hdc != NULL );
|
|
// 5/25/2000(RichGr): IA64: Use %p format specifier for 32/64-bit pointers.
|
|
DPF( 1, "Releasing Leaked DC = 0x%p", pdcinfo->hdc );
|
|
#ifdef WIN95
|
|
DD16_ReleaseDC( pdcinfo->hdc );
|
|
#else
|
|
if( ( pdds_lcl->ddsCaps.dwCaps & DDSCAPS_VIDEOMEMORY ) ||
|
|
!( pdds_lcl->ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE ) )
|
|
{
|
|
DdReleaseDC( pdds_lcl );
|
|
}
|
|
#endif
|
|
}
|
|
|
|
// Remove this dcinfo from the list.
|
|
if( pdcinfoPrev == NULL )
|
|
g_pdcinfoHead = pdcinfo->pdcinfoNext;
|
|
else
|
|
pdcinfoPrev->pdcinfoNext = pdcinfo->pdcinfoNext;
|
|
|
|
// Free this DcInfo
|
|
MemFree( pdcinfo );
|
|
|
|
return DD_OK;
|
|
}
|
|
// Not us? Then just sanity check the object we did find
|
|
DDASSERT( pdcinfo->pdds_lcl->dwFlags & DDRAWISURF_HASDC );
|
|
}
|
|
|
|
DPF_ERR( "DC/Surface association not found?" );
|
|
DDASSERT( 0 );
|
|
return DDERR_NOTFOUND;
|
|
}
|
|
|
|
HRESULT InternalGetSurfaceFromDC(
|
|
HDC hdc,
|
|
LPDIRECTDRAWSURFACE *ppdds,
|
|
HDC *phdcDriver,
|
|
LPVOID pCallbacks)
|
|
{
|
|
HRESULT ddrval = DDERR_INVALIDPARAMS;
|
|
|
|
ENTER_DDRAW();
|
|
|
|
DPF(2,A,"ENTERAPI: GetSurfaceFromDC");
|
|
|
|
TRY
|
|
{
|
|
DCINFO *pdcinfo;
|
|
|
|
if( !VALID_PTR_PTR( ppdds ) )
|
|
{
|
|
DPF_ERR( "Invalid IDirectDrawSurface Interface ptr ptr" );
|
|
LEAVE_DDRAW();
|
|
return DDERR_INVALIDPARAMS;
|
|
}
|
|
// Default value
|
|
*ppdds = NULL;
|
|
*phdcDriver = NULL;
|
|
|
|
ddrval = DDERR_GENERIC;
|
|
|
|
for ( pdcinfo = g_pdcinfoHead; pdcinfo != NULL; pdcinfo = pdcinfo->pdcinfoNext )
|
|
{
|
|
if( pdcinfo->hdc == hdc )
|
|
{
|
|
DDASSERT( pdcinfo->pdds_lcl != NULL );
|
|
DDASSERT( pdcinfo->pdds_lcl->dwFlags & DDRAWISURF_HASDC );
|
|
*ppdds = (LPVOID)getDDSInterface( pdcinfo->pdds_lcl->lpGbl->lpDD,
|
|
pdcinfo->pdds_lcl, pCallbacks );
|
|
|
|
if( *ppdds == NULL )
|
|
{
|
|
DPF_ERR( "GetSurfaceFromDC couldn't allocate interface" );
|
|
ddrval = DDERR_OUTOFMEMORY;
|
|
}
|
|
else
|
|
{
|
|
*phdcDriver = (HDC)pdcinfo->pdds_lcl->lpSurfMore->lpDD_lcl->hDC;
|
|
DD_Surface_AddRef( *ppdds );
|
|
ddrval = DD_OK;
|
|
}
|
|
LEAVE_DDRAW();
|
|
return ddrval;
|
|
}
|
|
}
|
|
DPF( 1, "GetSurfaceFromDC didn't find HDC" );
|
|
ddrval = DDERR_NOTFOUND;
|
|
}
|
|
EXCEPT( EXCEPTION_EXECUTE_HANDLER )
|
|
{
|
|
#ifdef DEBUG
|
|
if (ddrval == DDERR_INVALIDPARAMS)
|
|
DPF_ERR( "Exception encountered validating parameters" );
|
|
else
|
|
{
|
|
DPF_ERR( "Unexpected error during GetSurfaceFromDC" );
|
|
DDASSERT( 0 );
|
|
}
|
|
#endif
|
|
}
|
|
|
|
LEAVE_DDRAW();
|
|
return ddrval;
|
|
}
|
|
|
|
HRESULT EXTERN_DDAPI DD_GetSurfaceFromDC( LPDIRECTDRAW lpDD, HDC hdc, LPDIRECTDRAWSURFACE * pDDS)
|
|
{
|
|
HDC hdcTemp;
|
|
lpDD;
|
|
|
|
DPF(2,A,"ENTERAPI: DD_GetSurfaceFromDC");
|
|
|
|
if (LOWERTHANDDRAW7( ((LPDDRAWI_DIRECTDRAW_INT)lpDD)) )
|
|
return InternalGetSurfaceFromDC(hdc, pDDS, &hdcTemp, &ddSurfaceCallbacks);
|
|
|
|
return InternalGetSurfaceFromDC(hdc, pDDS, &hdcTemp, &ddSurface7Callbacks);
|
|
|
|
}
|
|
|
|
HRESULT EXTERN_DDAPI GetSurfaceFromDC(
|
|
HDC hdc,
|
|
LPDIRECTDRAWSURFACE *ppdds,
|
|
HDC *phdcDriver )
|
|
{
|
|
return InternalGetSurfaceFromDC(hdc, ppdds, phdcDriver, (LPVOID) &ddSurfaceCallbacks );
|
|
}
|
|
|
|
#ifdef WIN95
|
|
|
|
void InitColorTable( RGBQUAD *rgColors, LPPALETTEENTRY lpPalette )
|
|
{
|
|
int i;
|
|
|
|
for( i = 0; i < 256; i++ )
|
|
{
|
|
rgColors[i].rgbBlue = lpPalette[i].peBlue;
|
|
rgColors[i].rgbGreen = lpPalette[i].peGreen;
|
|
rgColors[i].rgbRed = lpPalette[i].peRed;
|
|
rgColors[i].rgbReserved = 0;
|
|
}
|
|
return;
|
|
}
|
|
// This function walks the list of outstanding DCs and figures out
|
|
// if the DC's colortable needs to be updated. It may be called in two ways:
|
|
//
|
|
// surface+pal -> this means that pal was attached to a surface
|
|
// just a surface -> this means that a palette was removed from a surface
|
|
void UpdateOutstandingDC( LPDDRAWI_DDRAWSURFACE_LCL psurf_lcl, LPDDRAWI_DDRAWPALETTE_GBL ppal_gbl )
|
|
{
|
|
BOOL fColorsInited = FALSE;
|
|
RGBQUAD rgColors[256];
|
|
PALETTEENTRY rgPalEntry[256];
|
|
LPDDPIXELFORMAT pddpf;
|
|
DCINFO *pdcinfo;
|
|
LPDDPIXELFORMAT pddpf_curr;
|
|
|
|
DDASSERT( psurf_lcl );
|
|
|
|
// Quick check to see if there are any DCs outstanding
|
|
// If not, then we don't have to do all this work
|
|
if( g_pdcinfoHead == NULL )
|
|
return;
|
|
|
|
GET_PIXEL_FORMAT( psurf_lcl, psurf_lcl->lpGbl, pddpf );
|
|
|
|
// Ignore non-8bit surfaces
|
|
if( !(pddpf->dwFlags & DDPF_PALETTEINDEXED8) )
|
|
return;
|
|
|
|
if( (psurf_lcl->ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE) )
|
|
{
|
|
// Primary?
|
|
// If it is, then we need to find all the outstanding
|
|
// DCs that are sharing the palette; and update them
|
|
for ( pdcinfo = g_pdcinfoHead; pdcinfo != NULL; pdcinfo = pdcinfo->pdcinfoNext )
|
|
{
|
|
DDASSERT( pdcinfo->pdds_lcl != NULL );
|
|
DDASSERT( pdcinfo->pdds_lcl->dwFlags & DDRAWISURF_HASDC );
|
|
|
|
GET_PIXEL_FORMAT( pdcinfo->pdds_lcl, pdcinfo->pdds_lcl->lpGbl, pddpf_curr );
|
|
|
|
// Ignore non palette-indexed 8-bit surfaces
|
|
if( !(pddpf_curr->dwFlags & DDPF_PALETTEINDEXED8) )
|
|
continue;
|
|
|
|
// Ignore DCs handed out by other direct draw interfaces
|
|
if( pdcinfo->pdds_lcl->lpGbl->lpDD != psurf_lcl->lpGbl->lpDD )
|
|
continue;
|
|
|
|
// Ignore surfaces that have their own palettes
|
|
// (except for our surface that is..)
|
|
if( pdcinfo->pdds_lcl->lpDDPalette != NULL &&
|
|
pdcinfo->pdds_lcl != psurf_lcl )
|
|
continue;
|
|
|
|
// We don't need to touch palettes that are of the
|
|
// DCNULL kind (it's already been updated
|
|
// because the DC isn't one of the ones we cooked ourselves)
|
|
if( pdcinfo->pdds_lcl->dwFlags & DDRAWISURF_GETDCNULL )
|
|
continue;
|
|
|
|
// Ok, this DC needs updating
|
|
// 5/25/2000(RichGr): IA64: Use %p format specifier for 32/64-bit pointers.
|
|
DPF( 3, "Updating colortable for HDC(0x%p)", pdcinfo->hdc );
|
|
|
|
// Have we init'ed our colors?
|
|
if( !fColorsInited )
|
|
{
|
|
if( ppal_gbl && ppal_gbl->dwFlags & DDRAWIPAL_EXCLUSIVE )
|
|
{
|
|
// If we're exclusive then use our colors as is
|
|
InitColorTable( rgColors, ppal_gbl->lpColorTable );
|
|
}
|
|
else
|
|
{
|
|
// Else, use the colors from current system palette
|
|
int n = GetSystemPaletteEntries( (HDC)psurf_lcl->lpSurfMore->lpDD_lcl->hDC,
|
|
0, 256, rgPalEntry );
|
|
DDASSERT( n == 256 );
|
|
InitColorTable( rgColors, rgPalEntry );
|
|
}
|
|
fColorsInited = TRUE;
|
|
}
|
|
// Set the colors into the DC, this will have the
|
|
// extra effect of resetting any cached translation tables
|
|
// so GDI won't use a wrong one inadvertently.
|
|
DPF(5, "Dib Color Table entry #50 == 0x%x", rgColors[50]);
|
|
SetDIBColorTable( pdcinfo->hdc, 0, 256, rgColors);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// Ordinary surface? Then find it in our list
|
|
for ( pdcinfo = g_pdcinfoHead; pdcinfo != NULL; pdcinfo = pdcinfo->pdcinfoNext )
|
|
{
|
|
DDASSERT( pdcinfo->pdds_lcl != NULL );
|
|
DDASSERT( pdcinfo->pdds_lcl->dwFlags & DDRAWISURF_HASDC );
|
|
|
|
// Ignored surfaces that have different global objects
|
|
if( pdcinfo->pdds_lcl->lpGbl != psurf_lcl->lpGbl )
|
|
continue;
|
|
|
|
// Ignore non palette-indexed 8-bit surfaces
|
|
GET_PIXEL_FORMAT( pdcinfo->pdds_lcl, pdcinfo->pdds_lcl->lpGbl, pddpf_curr );
|
|
if( !(pddpf_curr->dwFlags & DDPF_PALETTEINDEXED8) )
|
|
continue;
|
|
|
|
// Ok, this DC needs updating
|
|
// 5/25/2000(RichGr): IA64: Use %p format specifier for 32/64-bit pointers.
|
|
DPF( 3, "Updating colortable for non-primary HDC(0x%p)", pdcinfo->hdc );
|
|
|
|
if( !fColorsInited )
|
|
{
|
|
if( ppal_gbl )
|
|
{
|
|
// New color table for this offscreen surface?
|
|
// Use them directly
|
|
InitColorTable( rgColors, ppal_gbl->lpColorTable );
|
|
fColorsInited = TRUE;
|
|
}
|
|
else
|
|
{
|
|
int n;
|
|
|
|
// Someone is removing a palette from an offscreen surface?
|
|
// Then if the primary is at 8bpp, then we should
|
|
// steal the colors from it.
|
|
LPDDRAWI_DDRAWSURFACE_INT lpPrimary = pdcinfo->pdds_lcl->lpSurfMore->lpDD_lcl->lpPrimary;
|
|
if( lpPrimary )
|
|
{
|
|
// Check that the primary is 8bpp. If it is not,
|
|
// then we leave this surface alone.
|
|
GET_PIXEL_FORMAT( lpPrimary->lpLcl, lpPrimary->lpLcl->lpGbl, pddpf_curr );
|
|
|
|
if( !(pddpf_curr->dwFlags & DDPF_PALETTEINDEXED8) )
|
|
return;
|
|
}
|
|
else
|
|
{
|
|
// There is no primary surface attached to this
|
|
// DDraw. So we have no where useful to get colors from
|
|
// so return.
|
|
return;
|
|
}
|
|
|
|
DDASSERT( lpPrimary != NULL );
|
|
DDASSERT( pddpf_curr->dwFlags & DDPF_PALETTEINDEXED8 );
|
|
|
|
// Else, use the colors from current system palette
|
|
n = GetSystemPaletteEntries( (HDC)lpPrimary->lpLcl->lpSurfMore->lpDD_lcl->hDC,
|
|
0, 256, rgPalEntry );
|
|
DDASSERT( n == 256 );
|
|
InitColorTable( rgColors, rgPalEntry );
|
|
|
|
}
|
|
}
|
|
|
|
// Set the colors into the DC, this will have the
|
|
// extra effect of reseting any cached translation tables
|
|
// so GDI won't use a wrong one inadvertantly.
|
|
DPF(5, "Dib Color Table entry #50 == 0x%x", rgColors[50]);
|
|
SetDIBColorTable( pdcinfo->hdc, 0, 256, rgColors);
|
|
}
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
// This function handles the case when the entries of a
|
|
// palette have changed. We need to search for all the surfaces
|
|
// that may be affected and do something. However, we only
|
|
|
|
void UpdateDCOnPaletteChanges( LPDDRAWI_DDRAWPALETTE_GBL ppal_gbl )
|
|
{
|
|
DCINFO *pdcinfo;
|
|
DDASSERT( ppal_gbl != NULL );
|
|
|
|
// Quick check to see if there are any DCs outstanding
|
|
// If not, then we don't have to do all this work
|
|
if( g_pdcinfoHead == NULL )
|
|
return;
|
|
|
|
// Is this palette attached to our primary?
|
|
// We have to do this explicitly without regard to the outstanding
|
|
// DC list because the primary itself may have no outstanding DCs
|
|
// but offscreen surfaces may be logically 'sharing' the primary's palette
|
|
if( ppal_gbl->lpDD_lcl->lpPrimary &&
|
|
ppal_gbl->lpDD_lcl->lpPrimary->lpLcl->lpDDPalette &&
|
|
ppal_gbl->lpDD_lcl->lpPrimary->lpLcl->lpDDPalette->lpLcl->lpGbl == ppal_gbl )
|
|
{
|
|
// Update the palette for DCs associated with this primary
|
|
UpdateOutstandingDC( ppal_gbl->lpDD_lcl->lpPrimary->lpLcl, ppal_gbl );
|
|
}
|
|
|
|
// We walk all outstanding DCs looking for
|
|
// surfaces that are DIRECTLY affected this set entries.
|
|
for ( pdcinfo = g_pdcinfoHead; pdcinfo != NULL; pdcinfo = pdcinfo->pdcinfoNext )
|
|
{
|
|
DDASSERT( pdcinfo->pdds_lcl != NULL );
|
|
DDASSERT( pdcinfo->pdds_lcl->dwFlags & DDRAWISURF_HASDC );
|
|
|
|
// Ignore surfaces that don't have a palette;
|
|
// (If a surface doesn't have a palette, then that means
|
|
// it's using the palette from the primary. We handle that case
|
|
// above when we deal with the primary.)
|
|
if( pdcinfo->pdds_lcl->lpDDPalette == NULL )
|
|
continue;
|
|
|
|
// Ignore surfaces that aren't connected to us
|
|
if( pdcinfo->pdds_lcl->lpDDPalette->lpLcl->lpGbl != ppal_gbl )
|
|
continue;
|
|
|
|
// Ignore the primary that we already updated above
|
|
if( ppal_gbl->lpDD_lcl->lpPrimary &&
|
|
ppal_gbl->lpDD_lcl->lpPrimary->lpLcl == pdcinfo->pdds_lcl )
|
|
continue;
|
|
|
|
UpdateOutstandingDC( pdcinfo->pdds_lcl, ppal_gbl );
|
|
}
|
|
|
|
return;
|
|
}
|
|
#endif /* WIN95 */
|
|
|
|
#undef DPF_MODNAME
|
|
#define DPF_MODNAME "GetTopLevel"
|
|
|
|
LPDDRAWI_DDRAWSURFACE_LCL GetTopLevel(LPDDRAWI_DDRAWSURFACE_LCL lpLcl)
|
|
{
|
|
// loop to find the top level surface of a mipmap chain
|
|
for(; (lpLcl->lpSurfMore->ddsCapsEx.dwCaps2 & DDSCAPS2_MIPMAPSUBLEVEL) != 0;
|
|
lpLcl = lpLcl->lpAttachListFrom->lpAttached);
|
|
|
|
// if the top level surface is a cubemap face
|
|
if((lpLcl->lpSurfMore->ddsCapsEx.dwCaps2 & DDSCAPS2_CUBEMAP) != 0)
|
|
// then we need to return the top level surface of the cubemap
|
|
// The assumption here is that a cubemap is only one level deep
|
|
// and a cubemap subface is attached from ONLY a cubemap top level face
|
|
if(lpLcl->lpAttachListFrom != NULL)
|
|
lpLcl = lpLcl->lpAttachListFrom->lpAttached;
|
|
|
|
return lpLcl;
|
|
}
|
|
|
|
#undef DPF_MODNAME
|
|
#define DPF_MODNAME "DD_Surface_SetSurfaceDesc"
|
|
|
|
/*
|
|
* NOTE: There is a significant amount of code in this function that
|
|
* deals with video memory surfaces yet you will notice a check explicitly
|
|
* failing this function for surfaces which are not explicit system
|
|
* memory. This is deliberate. The intention is to mutate this function
|
|
* to work with video memory surfaces over time. The code is in place
|
|
* to start this process however unresolved issues remain.
|
|
*/
|
|
|
|
HRESULT DDAPI DD_Surface_SetSurfaceDesc(
|
|
LPDIRECTDRAWSURFACE3 lpDDSurface,
|
|
LPDDSURFACEDESC lpddsd,
|
|
DWORD dwFlags )
|
|
{
|
|
DDSURFACEDESC2 ddsd2 = {sizeof(ddsd2)};
|
|
|
|
DPF(2,A,"ENTERAPI: DD_Surface_SetSurfaceDesc");
|
|
|
|
ZeroMemory(&ddsd2,sizeof(ddsd2));
|
|
|
|
TRY
|
|
{
|
|
if( !VALID_DIRECTDRAWSURFACE_PTR( ((LPDDRAWI_DDRAWSURFACE_INT)lpDDSurface) ) )
|
|
{
|
|
DPF_ERR( "Invalid surface description passed" );
|
|
DPF_APIRETURNS(DDERR_INVALIDOBJECT);
|
|
return DDERR_INVALIDOBJECT;
|
|
}
|
|
|
|
if( 0UL != dwFlags )
|
|
{
|
|
DPF_ERR( "No flags are currently specified - 0 must be passed" );
|
|
DPF_APIRETURNS(DDERR_INVALIDPARAMS);
|
|
return DDERR_INVALIDPARAMS;
|
|
}
|
|
|
|
if( !VALID_DDSURFACEDESC_PTR( lpddsd ) )
|
|
{
|
|
DPF_ERR( "Invalid surface description. Did you set the dwSize member?" );
|
|
DPF_APIRETURNS(DDERR_INVALIDPARAMS);
|
|
return DDERR_INVALIDPARAMS;
|
|
}
|
|
|
|
memcpy(&ddsd2,lpddsd,sizeof(*lpddsd));
|
|
}
|
|
EXCEPT( EXCEPTION_EXECUTE_HANDLER )
|
|
{
|
|
DPF_ERR( "Exception encountered validating parameters: Bad LPDDSURFACEDESC" );
|
|
DPF_APIRETURNS(DDERR_INVALIDPARAMS);
|
|
return DDERR_INVALIDPARAMS;
|
|
}
|
|
|
|
ddsd2.dwSize = sizeof(ddsd2);
|
|
|
|
return DD_Surface_SetSurfaceDesc4(lpDDSurface, &ddsd2, dwFlags);
|
|
}
|
|
|
|
HRESULT DDAPI DD_Surface_SetSurfaceDesc4(
|
|
LPDIRECTDRAWSURFACE3 lpDDSurface,
|
|
LPDDSURFACEDESC2 lpddsd,
|
|
DWORD dwFlags )
|
|
{
|
|
LPDDRAWI_DDRAWSURFACE_INT this_int;
|
|
LPDDRAWI_DDRAWSURFACE_LCL this_lcl;
|
|
LPDDRAWI_DDRAWSURFACE_GBL this;
|
|
LPDDRAWI_DIRECTDRAW_INT pdrv_int;
|
|
LPDDRAWI_DIRECTDRAW_LCL pdrv_lcl;
|
|
LPDDRAWI_DIRECTDRAW_GBL pdrv;
|
|
BOOL emulation;
|
|
DWORD dwDummyFlags;
|
|
HRESULT ddres;
|
|
DDSURFACEDESC2 ddsd;
|
|
DDHAL_CANCREATESURFACEDATA ccsd;
|
|
LPDDHAL_CANCREATESURFACE ccsfn;
|
|
LPDDHAL_CANCREATESURFACE ccshalfn;
|
|
WORD wOldWidth;
|
|
WORD wOldHeight;
|
|
LONG lOldPitch;
|
|
DDPIXELFORMAT ddpfOldPixelFormat;
|
|
BOOL bIsCompressedTexture = FALSE;
|
|
WORD realwidth;
|
|
WORD realheight;
|
|
DWORD realsurfsize;
|
|
|
|
ENTER_DDRAW();
|
|
|
|
DPF(2,A,"ENTERAPI: DD_Surface_SetSurfaceDesc4");
|
|
|
|
TRY
|
|
{
|
|
this_int = (LPDDRAWI_DDRAWSURFACE_INT) lpDDSurface;
|
|
if( !VALID_DIRECTDRAWSURFACE_PTR( this_int ) )
|
|
{
|
|
DPF_ERR( "Invalid surface description passed" );
|
|
LEAVE_DDRAW();
|
|
return DDERR_INVALIDOBJECT;
|
|
}
|
|
this_lcl = this_int->lpLcl;
|
|
DDASSERT( NULL != this_lcl );
|
|
this = this_lcl->lpGbl;
|
|
DDASSERT( NULL != this );
|
|
pdrv_int = this_lcl->lpSurfMore->lpDD_int;
|
|
DDASSERT( NULL != pdrv_int );
|
|
pdrv_lcl = this_lcl->lpSurfMore->lpDD_lcl;
|
|
DDASSERT( NULL != pdrv_lcl );
|
|
pdrv = pdrv_lcl->lpGbl;
|
|
DDASSERT( NULL != pdrv );
|
|
|
|
//
|
|
// For now, if the current surface is optimized, quit
|
|
//
|
|
if (this_lcl->ddsCaps.dwCaps & DDSCAPS_OPTIMIZED)
|
|
{
|
|
DPF_ERR( "It is an optimized surface" );
|
|
LEAVE_DDRAW();
|
|
return DDERR_ISOPTIMIZEDSURFACE;
|
|
}
|
|
|
|
if( 0UL != dwFlags )
|
|
{
|
|
DPF_ERR( "No flags are currently specified - 0 must be passed" );
|
|
LEAVE_DDRAW();
|
|
return DDERR_INVALIDPARAMS;
|
|
}
|
|
|
|
if( !VALID_DDSURFACEDESC2_PTR( lpddsd ) )
|
|
{
|
|
DPF_ERR( "Surface description is invalid" );
|
|
LEAVE_DDRAW();
|
|
return DDERR_INVALIDPARAMS;
|
|
}
|
|
|
|
if( SURFACE_LOST( this_lcl ) )
|
|
{
|
|
DPF_ERR( "Could not set surface pointer - surface is lost" );
|
|
LEAVE_DDRAW();
|
|
return DDERR_SURFACELOST;
|
|
}
|
|
|
|
if( this->dwUsageCount > 0UL )
|
|
{
|
|
DPF_ERR( "Could not set surface pointer - surface is locked" );
|
|
LEAVE_DDRAW();
|
|
return DDERR_SURFACEBUSY;
|
|
}
|
|
|
|
/*
|
|
* Currently we don't allow anything but explicit system memory surfaces to
|
|
* have thier surface description (and pointer modified).
|
|
*/
|
|
#pragma message( REMIND( "Look into making SetSurfaceDesc work for video memory" ) )
|
|
if( !( this->dwGlobalFlags & DDRAWISURFGBL_SYSMEMREQUESTED ) )
|
|
{
|
|
DPF_ERR( "Could not set surface pointer - surface is not explicit system memory" );
|
|
LEAVE_DDRAW();
|
|
return DDERR_INVALIDSURFACETYPE;
|
|
}
|
|
DDASSERT( this_lcl->ddsCaps.dwCaps & DDSCAPS_SYSTEMMEMORY );
|
|
|
|
if( ( this_lcl->ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE ) ||
|
|
( this_lcl->ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACELEFT ) ||
|
|
( this_lcl->ddsCaps.dwCaps & DDSCAPS_OVERLAY ) ||
|
|
( this_lcl->ddsCaps.dwCaps & DDSCAPS_ALLOCONLOAD ) ||
|
|
( this_lcl->lpSurfMore->ddsCapsEx.dwCaps2 & DDSCAPS2_TEXTUREMANAGE ) ||
|
|
( this_lcl->lpSurfMore->ddsCapsEx.dwCaps2 & DDSCAPS2_D3DTEXTUREMANAGE ))
|
|
{
|
|
DPF_ERR( "Could not set surface pointer - surface is primary, overlay or device specific" );
|
|
LEAVE_DDRAW();
|
|
return DDERR_INVALIDSURFACETYPE;
|
|
}
|
|
|
|
/*
|
|
* Don't mess with anything that is part of the primary chain. That could get
|
|
* very nasty (destroying the primary surface pointer and replacing it with
|
|
* some app. specific garbage).
|
|
*/
|
|
if( this_lcl->dwFlags & DDRAWISURF_PARTOFPRIMARYCHAIN )
|
|
{
|
|
DPF_ERR( "Cannot set surface pointer - surface is part of the primary chain" );
|
|
LEAVE_DDRAW();
|
|
return DDERR_INVALIDSURFACETYPE;
|
|
}
|
|
|
|
if( lpddsd->dwFlags & ~( DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PITCH |
|
|
DDSD_LPSURFACE | DDSD_PIXELFORMAT ) )
|
|
{
|
|
DPF_ERR( "Can only specify caps, width, height, pitch, surface ptr and pixel format" );
|
|
LEAVE_DDRAW();
|
|
return DDERR_INVALIDPARAMS;
|
|
}
|
|
|
|
if( ( lpddsd->dwFlags & DDSD_WIDTH ) && ( 0UL == lpddsd->dwWidth ) )
|
|
{
|
|
DPF_ERR( "Invalid surface width specified" );
|
|
LEAVE_DDRAW();
|
|
return DDERR_INVALIDPARAMS;
|
|
}
|
|
|
|
if( ( lpddsd->dwFlags & DDSD_HEIGHT ) && ( 0UL == lpddsd->dwHeight ) )
|
|
{
|
|
DPF_ERR( "Invalid surface height specified" );
|
|
LEAVE_DDRAW();
|
|
return DDERR_INVALIDPARAMS;
|
|
}
|
|
|
|
if( ( lpddsd->dwFlags & DDSD_PITCH ) && (( lpddsd->lPitch <= 0L ) || (lpddsd->lPitch % 4)) )
|
|
{
|
|
DPF_ERR( "Invalid surface pitch specified" );
|
|
LEAVE_DDRAW();
|
|
return DDERR_INVALIDPARAMS;
|
|
}
|
|
|
|
if( lpddsd->dwFlags & DDSD_PIXELFORMAT )
|
|
{
|
|
if( !( this_lcl->dwFlags & DDRAWISURF_HASPIXELFORMAT ) )
|
|
{
|
|
/*
|
|
* This is very cheesy but the alternative is pretty nasty.
|
|
* Reallocting the global object with a pixel format if it
|
|
* does not already have one.
|
|
*/
|
|
DPF_ERR( "Cannot change the pixel format of a surface which does not have one" );
|
|
LEAVE_DDRAW();
|
|
return DDERR_INVALIDPARAMS;
|
|
}
|
|
|
|
if( !VALID_DDPIXELFORMAT_PTR( ( &(this->ddpfSurface) ) ) )
|
|
{
|
|
DPF_ERR( "Specifed pixel format is invalid" );
|
|
LEAVE_DDRAW();
|
|
return DDERR_INVALIDPARAMS;
|
|
}
|
|
}
|
|
|
|
if( ( ( lpddsd->dwFlags & DDSD_WIDTH ) && !( lpddsd->dwFlags & DDSD_PITCH ) ) ||
|
|
( ( lpddsd->dwFlags & DDSD_PITCH ) && !( lpddsd->dwFlags & DDSD_WIDTH ) ) )
|
|
{
|
|
DPF_ERR( "If width or pitch is specified then both width AND pitch must be specified" );
|
|
LEAVE_DDRAW();
|
|
return DDERR_INVALIDPARAMS;
|
|
}
|
|
|
|
if( !( lpddsd->dwFlags & DDSD_LPSURFACE ) )
|
|
{
|
|
DPF_ERR( "Must specify a surface memory pointer" );
|
|
LEAVE_DDRAW();
|
|
return DDERR_INVALIDPARAMS;
|
|
}
|
|
|
|
if( NULL == lpddsd->lpSurface )
|
|
{
|
|
DPF_ERR( "Surface memory pointer can't be NULL" );
|
|
LEAVE_DDRAW();
|
|
return DDERR_INVALIDPARAMS;
|
|
}
|
|
|
|
if( lpddsd->dwFlags & DDSD_CAPS )
|
|
{
|
|
if( lpddsd->ddsCaps.dwCaps != 0 )
|
|
{
|
|
DPF_ERR( "Illegal to set ddsCaps.dwCaps bits in surface desc" );
|
|
LEAVE_DDRAW();
|
|
return DDERR_INVALIDCAPS;
|
|
}
|
|
|
|
#if 0 // DDSCAPS2_LOCALALLOC, DDSCAPS2_COTASKMEM and DDRAWISURFGBL_DDFREESCLIENTMEM are gone
|
|
if( lpddsd->ddsCaps.dwCaps2 & ~(DDSCAPS2_LOCALALLOC | DDSCAPS2_COTASKMEM) )
|
|
{
|
|
DPF_ERR( "The only legal DDSCAPS2 flags are LOCALALLOC and COTASKMEM" );
|
|
LEAVE_DDRAW();
|
|
return DDERR_INVALIDCAPS;
|
|
}
|
|
|
|
if( !(~lpddsd->ddsCaps.dwCaps2 & (DDSCAPS2_LOCALALLOC | DDSCAPS2_COTASKMEM)) )
|
|
{
|
|
// Illegal to set LOCALALLOC and COTASKMEM flags simultaneously.
|
|
DPF_ERR( "DDSCAPS2 flags LOCALALLOC and COTASKMEM are mutually exclusive" );
|
|
LEAVE_DDRAW();
|
|
return DDERR_INVALIDCAPS;
|
|
}
|
|
#endif // 0
|
|
|
|
if( lpddsd->ddsCaps.dwCaps3 != 0 )
|
|
{
|
|
DPF_ERR( "Illegal to set ddsCaps.dwCaps3 bits in surface desc" );
|
|
LEAVE_DDRAW();
|
|
return DDERR_INVALIDCAPS;
|
|
}
|
|
|
|
if( lpddsd->ddsCaps.dwCaps4 != 0 )
|
|
{
|
|
DPF_ERR( "Illegal to set ddsCaps.dwCaps4 bits in surface desc" );
|
|
LEAVE_DDRAW();
|
|
return DDERR_INVALIDCAPS;
|
|
}
|
|
}
|
|
}
|
|
EXCEPT( EXCEPTION_EXECUTE_HANDLER )
|
|
{
|
|
DPF_ERR( "Exception encountered validating parameters" );
|
|
LEAVE_DDRAW();
|
|
return DDERR_INVALIDPARAMS;
|
|
}
|
|
|
|
/*
|
|
* Build a new surface description for the surface and fill in
|
|
* the new width, height and pitch.
|
|
*/
|
|
FillDDSurfaceDesc2( this_lcl, &ddsd );
|
|
if( lpddsd->dwFlags & DDSD_WIDTH )
|
|
ddsd.dwWidth = lpddsd->dwWidth;
|
|
if( lpddsd->dwFlags & DDSD_HEIGHT )
|
|
ddsd.dwHeight = lpddsd->dwHeight;
|
|
if( lpddsd->dwFlags & DDSD_PITCH )
|
|
ddsd.lPitch = lpddsd->lPitch;
|
|
if( lpddsd->dwFlags & DDSD_PIXELFORMAT )
|
|
ddsd.ddpfPixelFormat = lpddsd->ddpfPixelFormat;
|
|
|
|
emulation = ddsd.ddsCaps.dwCaps & DDSCAPS_SYSTEMMEMORY;
|
|
|
|
/*
|
|
* Validate that the new surface description makes some remote kind of
|
|
* sense.
|
|
*/
|
|
ddres = checkSurfaceDesc( &ddsd,
|
|
pdrv,
|
|
&dwDummyFlags,
|
|
emulation,
|
|
this->dwGlobalFlags & DDRAWISURFGBL_SYSMEMREQUESTED,
|
|
pdrv_int );
|
|
if( FAILED( ddres ) )
|
|
{
|
|
DPF_ERR( "Invalid surface description passed" );
|
|
LEAVE_DDRAW();
|
|
return ddres;
|
|
}
|
|
|
|
/*
|
|
* Ask the driver if it likes the look of this surface. We need to ask
|
|
* the driver again (even though we already did it when the surface was
|
|
* created) as the surface has changed size.
|
|
*/
|
|
if( emulation )
|
|
{
|
|
if( ddsd.ddsCaps.dwCaps & DDSCAPS_EXECUTEBUFFER )
|
|
{
|
|
ccsfn = pdrv_lcl->lpDDCB->HELDDExeBuf.CanCreateExecuteBuffer;
|
|
}
|
|
else
|
|
{
|
|
ccsfn = pdrv_lcl->lpDDCB->HELDD.CanCreateSurface;
|
|
}
|
|
ccshalfn = ccsfn;
|
|
}
|
|
else
|
|
{
|
|
if( ddsd.ddsCaps.dwCaps & DDSCAPS_EXECUTEBUFFER )
|
|
{
|
|
ccsfn = pdrv_lcl->lpDDCB->HALDDExeBuf.CanCreateExecuteBuffer;
|
|
ccshalfn = pdrv_lcl->lpDDCB->cbDDExeBufCallbacks.CanCreateExecuteBuffer;
|
|
}
|
|
else
|
|
{
|
|
ccsfn = pdrv_lcl->lpDDCB->HALDD.CanCreateSurface;
|
|
ccshalfn = pdrv_lcl->lpDDCB->cbDDCallbacks.CanCreateSurface;
|
|
}
|
|
}
|
|
|
|
if( ccshalfn != NULL )
|
|
{
|
|
BOOL is_diff;
|
|
HRESULT rc;
|
|
|
|
if( ddsd.dwFlags & DDSD_PIXELFORMAT )
|
|
{
|
|
is_diff = IsDifferentPixelFormat( &pdrv->vmiData.ddpfDisplay, &ddsd.ddpfPixelFormat );
|
|
}
|
|
else
|
|
{
|
|
is_diff = FALSE;
|
|
}
|
|
ccsd.CanCreateSurface = ccshalfn;
|
|
ccsd.lpDD = pdrv;
|
|
ccsd.lpDDSurfaceDesc = (LPDDSURFACEDESC)&ddsd;
|
|
ccsd.bIsDifferentPixelFormat = is_diff;
|
|
if( ddsd.ddsCaps.dwCaps & DDSCAPS_EXECUTEBUFFER )
|
|
{
|
|
DOHALCALL( CanCreateExecuteBuffer, ccsfn, ccsd, rc, emulation );
|
|
}
|
|
else
|
|
{
|
|
DOHALCALL( CanCreateSurface, ccsfn, ccsd, rc, emulation );
|
|
}
|
|
if( rc == DDHAL_DRIVER_HANDLED )
|
|
{
|
|
if( ccsd.ddRVal != DD_OK )
|
|
{
|
|
DPF_ERR( "Driver says surface can't be created" );
|
|
LEAVE_DDRAW();
|
|
return ccsd.ddRVal;
|
|
}
|
|
}
|
|
}
|
|
|
|
/*
|
|
* Stash away the surface settings to we can put them back if anything
|
|
* foes wrong.
|
|
*
|
|
* NOTE: We don't store away the heap or vid mem pointer if an error happens
|
|
* after this point the surface ends up lost and will need to be restored.
|
|
*/
|
|
wOldWidth = this->wWidth;
|
|
wOldHeight = this->wHeight;
|
|
lOldPitch = this->lPitch;
|
|
if( this_lcl->dwFlags & DDRAWISURF_HASPIXELFORMAT )
|
|
ddpfOldPixelFormat = this->ddpfSurface;
|
|
|
|
/* There could be pending TexBlts and stuff, so Sync with the token stream */
|
|
FlushD3DStates( this_lcl );
|
|
|
|
/*
|
|
* The driver has okayed the creation so toast the existing surface memory.
|
|
*/
|
|
DestroySurface( this_lcl );
|
|
|
|
/*
|
|
* Remove any cached RLE stuff for source surface
|
|
*/
|
|
if( this_lcl->ddsCaps.dwCaps & DDSCAPS_SYSTEMMEMORY )
|
|
{
|
|
extern void FreeRleData(LPDDRAWI_DDRAWSURFACE_LCL); //in junction.c
|
|
|
|
FreeRleData( this_lcl );
|
|
}
|
|
|
|
/*
|
|
* Now mutate the surface into its new form. Kind of spooky isn't it... a bit
|
|
* like The Fly. Stash away the original settings in case we need to put them back
|
|
* if something goes wrong.
|
|
*/
|
|
if( lpddsd->dwFlags & DDSD_WIDTH )
|
|
this->wWidth = (WORD)lpddsd->dwWidth;
|
|
if( lpddsd->dwFlags & DDSD_HEIGHT )
|
|
this->wHeight = (WORD)lpddsd->dwHeight;
|
|
if( lpddsd->dwFlags & DDSD_PITCH )
|
|
this->lPitch = lpddsd->lPitch;
|
|
if( lpddsd->dwFlags & DDSD_PIXELFORMAT )
|
|
{
|
|
this->ddpfSurface = lpddsd->ddpfPixelFormat;
|
|
// Now that the pixel format may have changed, we need to reset the pixel-format
|
|
// index that was previously cached by the HEL's AlphaBlt emulation routine.
|
|
this_lcl->lpSurfMore->dwPFIndex = PFINDEX_UNINITIALIZED;
|
|
// ATTENTION: If pixel format has changed, are old color keys still valid?
|
|
}
|
|
this->lpVidMemHeap = NULL;
|
|
this->fpVidMem = (FLATPTR)lpddsd->lpSurface;
|
|
#if 0 // DDRAWISURFGBL_DDFREESCLIENTMEM is gone
|
|
this->dwGlobalFlags &= ~(DDRAWISURFGBL_MEMFREE | DDRAWISURFGBL_DDFREESCLIENTMEM);
|
|
#else
|
|
this->dwGlobalFlags &= ~(DDRAWISURFGBL_MEMFREE);
|
|
#endif // 0
|
|
this->dwGlobalFlags |= DDRAWISURFGBL_ISCLIENTMEM;
|
|
this_lcl->dwFlags &= ~DDRAWISURF_INVALID;
|
|
#if 0 // DDSCAPS2_LOCALALLOC, DDSCAPS2_COTASKMEM and DDRAWISURFGBL_DDFREESCLIENTMEM are gone
|
|
this_lcl->lpSurfMore->ddsCapsEx.dwCaps2 &= ~(DDSCAPS2_LOCALALLOC | DDSCAPS2_COTASKMEM);
|
|
|
|
if( lpddsd->dwFlags & DDSD_CAPS &&
|
|
lpddsd->ddsCaps.dwCaps2 & (DDSCAPS2_LOCALALLOC | DDSCAPS2_COTASKMEM) )
|
|
{
|
|
/*
|
|
* Remember that DirectDraw will be responsible for freeing the
|
|
* client-allocated surface memory when it's no longer needed.
|
|
*/
|
|
this->dwGlobalFlags |= DDRAWISURFGBL_DDFREESCLIENTMEM;
|
|
|
|
this_lcl->lpSurfMore->ddsCapsEx.dwCaps2 |=
|
|
lpddsd->ddsCaps.dwCaps2 & (DDSCAPS2_LOCALALLOC | DDSCAPS2_COTASKMEM);
|
|
}
|
|
#endif // 0
|
|
|
|
#ifdef USE_ALIAS
|
|
{
|
|
/*
|
|
* If this is a video memory surface then we need to recompute the alias offset of
|
|
* the surface for locking purposes.
|
|
*/
|
|
LPDDRAWI_DDRAWSURFACE_GBL_MORE lpGblMore;
|
|
|
|
lpGblMore = GET_LPDDRAWSURFACE_GBL_MORE( this );
|
|
if( this_lcl->ddsCaps.dwCaps & DDSCAPS_VIDEOMEMORY )
|
|
{
|
|
lpGblMore->fpAliasedVidMem = GetAliasedVidMem( pdrv_lcl, this_lcl, this_lcl->lpGbl->fpVidMem );
|
|
// If we succeeded in getting an alias, cache it for future use. Also store the original
|
|
// fpVidMem to compare with before using the cached pointer to make sure the cached value
|
|
// is still valid
|
|
if (lpGblMore->fpAliasedVidMem)
|
|
lpGblMore->fpAliasOfVidMem = this_lcl->lpGbl->fpVidMem;
|
|
else
|
|
lpGblMore->fpAliasOfVidMem = 0;
|
|
}
|
|
else
|
|
{
|
|
lpGblMore->fpAliasedVidMem = 0UL;
|
|
lpGblMore->fpAliasOfVidMem = 0UL;
|
|
}
|
|
}
|
|
#endif /* USE_ALIAS */
|
|
|
|
#if 0
|
|
if( lpddsd->dwFlags & DDSD_LPSURFACE )
|
|
{
|
|
#endif //0
|
|
/*
|
|
* Set the access counter to zero (which means ddraw has no information on the moment
|
|
* to moment contents of the surface, so the driver should not cache).
|
|
*/
|
|
GET_LPDDRAWSURFACE_GBL_MORE(this)->dwContentsStamp = 0;
|
|
#if 0
|
|
}
|
|
else
|
|
{
|
|
/*
|
|
* Something probably changed
|
|
*/
|
|
BUMP_SURFACE_STAMP(this);
|
|
}
|
|
#endif //0
|
|
|
|
#ifdef WINNT
|
|
|
|
// The DDCreateSurfaceObject call fails when we
|
|
// specify a FOURCC system memory surface with pitch = 0
|
|
// and bits/pixel = 0. We must ensure these parameters
|
|
// are nonzero for the call.
|
|
|
|
if ((this_lcl->dwFlags & DDRAWISURF_HASPIXELFORMAT) &&
|
|
(this->ddpfSurface.dwFlags & DDPF_FOURCC) &&
|
|
(GetDxtBlkSize(this->ddpfSurface.dwFourCC) != 0))
|
|
{
|
|
LONG blksize;
|
|
WORD dx, dy;
|
|
|
|
/*
|
|
* This surface uses a FOURCC format that we understand.
|
|
* Figure out how much memory we allocated for it.
|
|
*/
|
|
blksize = GetDxtBlkSize(this->ddpfSurface.dwFourCC);
|
|
DDASSERT(blksize != 0);
|
|
|
|
DDASSERT(this->ddpfSurface.dwRGBBitCount == 0);
|
|
DDASSERT(this_lcl->ddsCaps.dwCaps & DDSCAPS_TEXTURE);
|
|
|
|
bIsCompressedTexture = TRUE;
|
|
|
|
// Save the surface's real width and height so we can restore them.
|
|
realwidth = this->wWidth;
|
|
realheight = this->wHeight;
|
|
realsurfsize = this->dwLinearSize; // union with lPitch
|
|
|
|
// The NT kernel won't let us create this surface unless we lie.
|
|
// We have to make up a width, height, pitch, and pixel size
|
|
// that GDI will accept as valid.
|
|
dx = (WORD)((realwidth + 3) >> 2); // number of 4x4 blocks in a row
|
|
dy = (WORD)((realheight + 3) >> 2); // number of 4x4 blocks in a column
|
|
|
|
this->wHeight = dy; // lie about height
|
|
this->lPitch = dx*blksize; // lie about pitch
|
|
this->wWidth = (WORD)this->lPitch; // lie about width
|
|
this->ddpfSurface.dwRGBBitCount = 8; // lie about pixel size
|
|
|
|
// GDI will reserve lpsurf->wWidth*lpsurf->lPitch bytes of virtual
|
|
// memory for the surface. This had better be equal to the amount
|
|
// of memory we actually allocated for the surface. What a pain.
|
|
DDASSERT(this_lcl->lpSurfMore->dwBytesAllocated ==
|
|
(DWORD)this->wHeight*this->lPitch);
|
|
}
|
|
else if ((this->ddpfSurface.dwFourCC == MAKEFOURCC('U','Y','V','Y')) ||
|
|
(this->ddpfSurface.dwFourCC == MAKEFOURCC('Y','U','Y','2')))
|
|
{
|
|
// These formats are really 8bpp; so we need to adjust
|
|
// the bits-per-pixel parameter to make NT happy
|
|
this->ddpfSurface.dwRGBBitCount = 16;
|
|
}
|
|
|
|
/*
|
|
* We deleted the surface object above, so we must create a new
|
|
* surface object before we return.
|
|
*/
|
|
if (!DdCreateSurfaceObject(this_lcl, FALSE))
|
|
{
|
|
if(!(DDSCAPS_SYSTEMMEMORY & this_lcl->ddsCaps.dwCaps))
|
|
{
|
|
DPF_ERR("GDI failed to create surface object!");
|
|
LEAVE_DDRAW();
|
|
return DDERR_INVALIDPARAMS;
|
|
}
|
|
}
|
|
if (bIsCompressedTexture)
|
|
{
|
|
// Restore the FOURCC surface's actual width, height, etc.
|
|
this->wWidth = (WORD)realwidth;
|
|
this->wHeight = (WORD)realheight;
|
|
this->dwLinearSize = realsurfsize;
|
|
}
|
|
|
|
//(Fix for Manbug 40941)-->
|
|
// The delete also killed any attachments the kernel may have to neighbouring surfaces.
|
|
//If this is a mipmap, then we need to recreate the attachments now, before the CSEx
|
|
//is called.
|
|
//ISSUE: This fix doesn't address:
|
|
// -cubemaps or other more complex attachments
|
|
// -How do we guarantee the right linked list order in the kernel? We'll have
|
|
// to destroy all attachments, then re-attach them again. (The app in question runs
|
|
// the mipmap chain in the correct order to re-create attachments in the kernel's
|
|
// linked list in the right order.)
|
|
|
|
// let the kernel know about the attachment only if the driver isn't emulated...
|
|
if ( pdrv->hDD )
|
|
{
|
|
LPATTACHLIST pal;
|
|
|
|
// The current surface has been disassociated from the two
|
|
// neighbouring levels. We need to repair two attachments:
|
|
// the next highst level to this level, and then this level
|
|
// to the next lowest level.
|
|
pal = this_lcl->lpAttachList;
|
|
|
|
if(pal) //while(pal) might be a better fix
|
|
{
|
|
DdAttachSurface( this_lcl, pal->lpAttached );
|
|
}
|
|
|
|
pal = this_lcl->lpAttachListFrom;
|
|
|
|
if(pal) //while(pal) might be a better fix
|
|
{
|
|
DdAttachSurface( pal->lpAttached, this_lcl );
|
|
}
|
|
}
|
|
//<--(End fix for Manbug 40941)
|
|
|
|
#endif //WINNT
|
|
|
|
if(this_lcl->lpSurfMore->dwSurfaceHandle != 0)
|
|
{
|
|
LPDDRAWI_DDRAWSURFACE_LCL lpLcl = GetTopLevel(this_lcl);
|
|
HRESULT HRet;
|
|
DDASSERT( pdrv_lcl == lpLcl->lpSurfMore->lpDD_lcl);
|
|
HRet = createsurfaceEx(lpLcl);
|
|
if (DD_OK != HRet)
|
|
{
|
|
LEAVE_DDRAW();
|
|
return HRet;
|
|
}
|
|
}
|
|
|
|
LEAVE_DDRAW();
|
|
|
|
return DD_OK;
|
|
} /* DD_Surface_SetSurfaceDesc */
|
|
|
|
|
|
/*
|
|
* GetNextMipMap
|
|
*/
|
|
LPDIRECTDRAWSURFACE GetNextMipMap(
|
|
LPDIRECTDRAWSURFACE lpLevel)
|
|
{
|
|
DDSCAPS ddsCaps;
|
|
LPDDRAWI_DDRAWSURFACE_LCL lpLcl;
|
|
LPATTACHLIST pal;
|
|
|
|
if (!lpLevel)
|
|
return NULL;
|
|
|
|
lpLcl = ((LPDDRAWI_DDRAWSURFACE_INT)lpLevel)->lpLcl;
|
|
|
|
ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_MIPMAP;
|
|
pal = lpLcl->lpAttachList;
|
|
while( pal != NULL )
|
|
{
|
|
if ( ((pal->lpAttached->ddsCaps.dwCaps) & (DDSCAPS_TEXTURE | DDSCAPS_MIPMAP))
|
|
== (DDSCAPS_TEXTURE | DDSCAPS_MIPMAP) )
|
|
{
|
|
/*
|
|
* Got both the right caps
|
|
*/
|
|
return (LPDIRECTDRAWSURFACE) pal->lpIAttached;
|
|
}
|
|
pal = pal->lpLink;
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
/*
|
|
* LateAllocateSurfaceMem
|
|
*
|
|
* Called by the D3D to allocate memory for a compressed surface.
|
|
* The input lpDDSurface must have certain state:
|
|
* -DDSCAPS_VIDEOMEMORY or DDSCAPS_SYSTEMMEMORY are allowed.
|
|
* -DDSCAPS_OPTIMIZED required.
|
|
* -fpVidMem must be either DDHAL_PLEASEALLOC_BLOCKSIZE, DDHAL_PLEASEALLOC_NOMEMORY or DDHAL_PLEASEALLOC_LINEARSIZE
|
|
* -If BLOCKSIZE, the blocksizes must be filled,
|
|
* -If LINEARSIZE, the dwLinearSize must be filled.
|
|
* -If LINEARSIZE is specified. Only the linear heaps will be traversed.
|
|
*/
|
|
#undef DPF_MODNAME
|
|
#define DPF_MODNAME "LateAllocateSurfaceMem"
|
|
HRESULT DDAPI LateAllocateSurfaceMem(LPDIRECTDRAWSURFACE lpDDSurface, DWORD dwAllocationType, DWORD dwWidthOrSize, DWORD dwHeight)
|
|
{
|
|
HRESULT ddrval;
|
|
LPDDRAWI_DDRAWSURFACE_INT psurf_int;
|
|
LPDDRAWI_DDRAWSURFACE_LCL psurf_lcl;
|
|
LPDDRAWI_DDRAWSURFACE_GBL psurf_gbl;
|
|
LPDDRAWI_DDRAWSURFACE_LCL surflist[1];
|
|
LONG lSurfacePitch;
|
|
|
|
DPF(2,A,"ENTERAPI: LateAllocSurfaceMem");
|
|
|
|
DDASSERT( lpDDSurface != 0 );
|
|
DDASSERT((dwAllocationType == DDHAL_PLEASEALLOC_BLOCKSIZE) || (dwAllocationType == DDHAL_PLEASEALLOC_LINEARSIZE));
|
|
|
|
psurf_int = (LPDDRAWI_DDRAWSURFACE_INT) lpDDSurface;
|
|
psurf_lcl = psurf_int->lpLcl;
|
|
psurf_gbl = psurf_lcl->lpGbl;
|
|
|
|
/*
|
|
* If driver has already filled in some memory for the surface then we'll just clean
|
|
* up some state and return
|
|
*/
|
|
if (psurf_gbl->fpVidMem)
|
|
{
|
|
DPF(4,V,"Driver has already allocated some space.");
|
|
psurf_gbl->dwGlobalFlags &= ~DDRAWISURFGBL_MEMFREE;
|
|
psurf_gbl->dwGlobalFlags &= ~DDRAWISURFGBL_LATEALLOCATELINEAR;
|
|
if (dwAllocationType == DDHAL_PLEASEALLOC_LINEARSIZE)
|
|
{
|
|
psurf_gbl->dwGlobalFlags |= DDRAWISURFGBL_LATEALLOCATELINEAR;
|
|
}
|
|
return DD_OK;
|
|
}
|
|
|
|
/*
|
|
* If the driver hasn't filled in itself, then we'd better have some sensible
|
|
* input to decide what to do.
|
|
*/
|
|
DDASSERT(dwWidthOrSize != 0);
|
|
DDASSERT(dwAllocationType == DDHAL_PLEASEALLOC_LINEARSIZE || dwHeight != 0);
|
|
|
|
/*
|
|
* Assert some things that we don't want AllocSurfaceMem to see.
|
|
*/
|
|
DDASSERT( (psurf_lcl->ddsCaps.dwCaps & DDSCAPS_EXECUTEBUFFER) == 0);
|
|
DDASSERT( (psurf_gbl->dwGlobalFlags & DDRAWISURFGBL_ISGDISURFACE) == 0);
|
|
|
|
if (dwAllocationType == DDHAL_PLEASEALLOC_BLOCKSIZE)
|
|
{
|
|
/*
|
|
* Surface can be allocated in either rectangular or linear heaps.
|
|
* (That's what the FALSE passed to AllocSurfaceMem means)
|
|
*/
|
|
psurf_gbl->fpVidMem = (FLATPTR) DDHAL_PLEASEALLOC_BLOCKSIZE;
|
|
psurf_gbl->dwBlockSizeX = dwWidthOrSize;
|
|
psurf_gbl->dwBlockSizeY = dwHeight;
|
|
if (psurf_lcl->ddsCaps.dwCaps & DDSCAPS_VIDEOMEMORY)
|
|
{
|
|
surflist[0] = psurf_lcl;
|
|
ddrval = AllocSurfaceMem(psurf_lcl->lpSurfMore->lpDD_lcl, surflist, 1 );
|
|
}
|
|
else
|
|
{
|
|
DWORD dwSurfaceSize;
|
|
DDASSERT(psurf_lcl->ddsCaps.dwCaps & DDSCAPS_SYSTEMMEMORY);
|
|
ddrval = DDERR_OUTOFMEMORY;
|
|
psurf_gbl->fpVidMem = (FLATPTR) HELAllocateSurfaceSysMem(
|
|
psurf_lcl,
|
|
psurf_gbl->dwBlockSizeX ,
|
|
psurf_gbl->dwBlockSizeY,
|
|
&dwSurfaceSize,
|
|
&lSurfacePitch );
|
|
/*
|
|
* Clean up overloaded fields
|
|
*/
|
|
psurf_gbl->lpRectList = NULL;
|
|
psurf_gbl->lpVidMemHeap = NULL;
|
|
}
|
|
if (psurf_gbl->fpVidMem)
|
|
{
|
|
psurf_gbl->dwGlobalFlags &= ~DDRAWISURFGBL_MEMFREE;
|
|
ddrval = DD_OK;
|
|
}
|
|
else
|
|
{
|
|
DPF(0,"Out of memory in LateAllocateSurfaceMem");
|
|
}
|
|
return ddrval;
|
|
}
|
|
else if (dwAllocationType == DDHAL_PLEASEALLOC_LINEARSIZE)
|
|
{
|
|
DWORD dwSurfaceConsumption;
|
|
|
|
if (0 == dwWidthOrSize)
|
|
{
|
|
/*
|
|
* Bad driver!
|
|
*/
|
|
DPF_ERR("Linear size set to 0 for a DDHAL_PLEASEALLOC_LINEARSIZE surface");
|
|
return DDERR_INVALIDPARAMS;
|
|
}
|
|
dwSurfaceConsumption = dwWidthOrSize;
|
|
psurf_gbl->dwGlobalFlags |= DDRAWISURFGBL_LATEALLOCATELINEAR;
|
|
/*
|
|
* Surface can only live in linear heaps.
|
|
* (That's what the TRUE passed to AllocSurfaceMem means)
|
|
*/
|
|
if (psurf_lcl->ddsCaps.dwCaps & DDSCAPS_VIDEOMEMORY)
|
|
{
|
|
/*
|
|
* Fool around with surface global data so that AllocSurfaceMem
|
|
* will allocate the correct linear size.
|
|
*/
|
|
psurf_gbl->dwLinearSize = dwWidthOrSize;
|
|
psurf_gbl->wHeight = 1;
|
|
psurf_gbl->fpVidMem = DDHAL_PLEASEALLOC_LINEARSIZE;
|
|
surflist[0] = psurf_lcl;
|
|
ddrval = AllocSurfaceMem(psurf_lcl->lpSurfMore->lpDD_lcl, surflist, 1 );
|
|
}
|
|
else
|
|
{
|
|
ddrval = DDERR_OUTOFMEMORY;
|
|
DDASSERT(psurf_lcl->ddsCaps.dwCaps & DDSCAPS_SYSTEMMEMORY);
|
|
psurf_gbl->fpVidMem = (FLATPTR) HELAllocateSurfaceSysMem(
|
|
psurf_lcl,
|
|
dwWidthOrSize,
|
|
1 ,
|
|
&dwSurfaceConsumption,
|
|
&lSurfacePitch );
|
|
psurf_gbl->dwLinearSize = dwSurfaceConsumption;
|
|
/*
|
|
* Clean up overloaded fields
|
|
*/
|
|
psurf_gbl->lpVidMemHeap = NULL;
|
|
psurf_gbl->lpRectList = NULL;
|
|
}
|
|
if (psurf_gbl->fpVidMem)
|
|
{
|
|
psurf_gbl->dwGlobalFlags &= ~DDRAWISURFGBL_MEMFREE;
|
|
/*
|
|
* The surface's size will be calculated using dwLinearSize
|
|
*/
|
|
ddrval = DD_OK;
|
|
}
|
|
else
|
|
{
|
|
/*
|
|
* Failed for some reason.
|
|
*/
|
|
psurf_gbl->dwGlobalFlags &= ~DDRAWISURFGBL_LATEALLOCATELINEAR;
|
|
DPF(0,"Out of memory in LateAllocateSurfaceMem");
|
|
}
|
|
return ddrval;
|
|
}
|
|
else
|
|
return DDERR_GENERIC;
|
|
}
|
|
|
|
|
|
#undef DPF_MODNAME
|
|
#define DPF_MODNAME "Resize"
|
|
|
|
#ifdef POSTPONED2
|
|
/*
|
|
* DD_Surface_Resize
|
|
*/
|
|
HRESULT DDAPI DD_Surface_Resize(
|
|
LPDIRECTDRAWSURFACE lpDDSurface,
|
|
DWORD dwFlags,
|
|
DWORD dwWidth,
|
|
DWORD dwHeight)
|
|
{
|
|
DWORD rc;
|
|
LPDDHAL_RESIZE pfn;
|
|
DDHAL_RESIZEDATA rszd;
|
|
LPDDRAWI_DDRAWSURFACE_INT this_int;
|
|
LPDDRAWI_DDRAWSURFACE_LCL this_lcl;
|
|
LPDDRAWI_DDRAWSURFACE_GBL this_gbl;
|
|
LPDDRAWI_DIRECTDRAW_LCL pdrv_lcl;
|
|
LPDDRAWI_DIRECTDRAW_GBL pdrv_gbl;
|
|
|
|
ENTER_DDRAW();
|
|
|
|
DPF(2,A,"ENTERAPI: DD_Surface_Resize");
|
|
|
|
TRY
|
|
{
|
|
this_int = (LPDDRAWI_DDRAWSURFACE_INT)lpDDSurface;
|
|
/*
|
|
* Validate surface pointer.
|
|
*/
|
|
if (!VALID_DIRECTDRAWSURFACE_PTR(this_int))
|
|
{
|
|
DPF_ERR("Invalid surface object");
|
|
LEAVE_DDRAW();
|
|
return DDERR_INVALIDOBJECT;
|
|
}
|
|
|
|
this_lcl = this_int->lpLcl; // internal local surface object
|
|
this_gbl = this_lcl->lpGbl; // internal global surface object
|
|
|
|
/*
|
|
* If this surface is in the process of being freed, return immediately.
|
|
*/
|
|
if( this_lcl->dwFlags & DDRAWISURF_ISFREE )
|
|
{
|
|
DPF(0, "Can't resize surface that's being freed" );
|
|
LEAVE_DDRAW();
|
|
return DDERR_GENERIC;
|
|
}
|
|
|
|
/*
|
|
* Avoid trying to resize an optimized surface.
|
|
*/
|
|
if (this_lcl->ddsCaps.dwCaps & DDSCAPS_OPTIMIZED)
|
|
{
|
|
DPF_ERR( "Can't resize an optimized surface" );
|
|
LEAVE_DDRAW();
|
|
return DDERR_ISOPTIMIZEDSURFACE;
|
|
}
|
|
|
|
/*
|
|
* Avoid resizing a primary surface, a texture surface, a surface that is part of a
|
|
* flipping chain or any other complex surface, or a surface that is currently visible.
|
|
*/
|
|
if (this_lcl->ddsCaps.dwCaps & (DDSCAPS_COMPLEX | DDSCAPS_FLIP | DDSCAPS_VIDEOPORT |
|
|
DDSCAPS_PRIMARYSURFACE | DDSCAPS_PRIMARYSURFACELEFT |
|
|
DDSCAPS_TEXTURE | DDSCAPS_MIPMAP | // redundant?
|
|
DDSCAPS_EXECUTEBUFFER | DDSCAPS_VISIBLE))
|
|
{
|
|
DPF_ERR("Can't resize visible surface, texture surface, complex surface, or execute buffer");
|
|
LEAVE_DDRAW();
|
|
return DDERR_INVALIDSURFACETYPE;
|
|
}
|
|
|
|
/*
|
|
* Avoid resizing an attached surface or a surface that has attached surfaces.
|
|
* (Note: Could have checked DDRAWISURF_ATTACHED and DDRAWISURF_ATTACHED_FROM
|
|
* bits in this_lcl->dwFlags, but these don't appear to be maintained properly.)
|
|
*/
|
|
if (this_lcl->lpAttachList != NULL || this_lcl->lpAttachListFrom != NULL)
|
|
{
|
|
DPF_ERR( "Can't resize surface that is attached or that has attached surfaces" );
|
|
LEAVE_DDRAW();
|
|
return DDERR_INVALIDSURFACETYPE;
|
|
}
|
|
|
|
/*
|
|
* Avoid resizing a surface to which a D3D device is still attached.
|
|
*/
|
|
if (this_lcl->lpSurfMore->lpD3DDevIList != NULL)
|
|
{
|
|
DPF_ERR( "Can't resize a surface that a Direct3D device is still attached to" );
|
|
LEAVE_DDRAW();
|
|
return DDERR_INVALIDSURFACETYPE;
|
|
}
|
|
|
|
pdrv_lcl = this_lcl->lpSurfMore->lpDD_lcl; // internal local DD object
|
|
pdrv_gbl = pdrv_lcl->lpGbl; // internal global DD object
|
|
#ifdef WINNT
|
|
// Update DDraw handle in driver GBL object.
|
|
pdrv_gbl->hDD = pdrv_lcl->hDD;
|
|
#endif //WINNT
|
|
|
|
/*
|
|
* Wait for driver to finish with any pending DMA operations
|
|
*/
|
|
if( this_gbl->dwGlobalFlags & DDRAWISURFGBL_HARDWAREOPSTARTED )
|
|
{
|
|
WaitForDriverToFinishWithSurface(pdrv_lcl, this_lcl);
|
|
}
|
|
|
|
/*
|
|
* Get pointer to driver's HAL callback Resize routine.
|
|
*/
|
|
if (this_lcl->ddsCaps.dwCaps & DDSCAPS_VIDEOMEMORY)
|
|
{
|
|
/*
|
|
* Surface resides in video memory. Use hardware driver callback.
|
|
*/
|
|
pfn = pdrv_lcl->lpDDCB->HALDDMiscellaneous2.Resize;
|
|
}
|
|
else
|
|
{
|
|
/*
|
|
* Surface resides in system memory. Use HEL emulation routine.
|
|
*/
|
|
pfn = pdrv_lcl->lpDDCB->HELDDMiscellaneous2.Resize;
|
|
}
|
|
if (pfn == NULL)
|
|
{
|
|
DPF_ERR("No driver support for Resize");
|
|
LEAVE_DDRAW();
|
|
return DDERR_UNSUPPORTED;
|
|
}
|
|
}
|
|
EXCEPT( EXCEPTION_EXECUTE_HANDLER )
|
|
{
|
|
DPF_ERR("Exception encountered validating parameters");
|
|
LEAVE_DDRAW();
|
|
return DDERR_INVALIDPARAMS;
|
|
}
|
|
|
|
/*
|
|
* Currently, no flags are defined for the Resize call.
|
|
*/
|
|
if (dwFlags)
|
|
{
|
|
DPF_ERR( "dwFlags arg must be zero" );
|
|
LEAVE_DDRAW();
|
|
return DDERR_INVALIDPARAMS;
|
|
}
|
|
|
|
/*
|
|
* Validate width and height parameters.
|
|
*/
|
|
if (dwWidth < 1 || dwHeight < 1)
|
|
{
|
|
DPF_ERR("Invalid surface width or height specified");
|
|
LEAVE_DDRAW();
|
|
return DDERR_INVALIDPARAMS;
|
|
}
|
|
|
|
/*
|
|
* Don't allow implicit surface to be resized.
|
|
*/
|
|
if (this_lcl->dwFlags & DDRAWISURF_IMPLICITCREATE)
|
|
{
|
|
DPF_ERR("Can't resize implicitly created surface");
|
|
LEAVE_DDRAW();
|
|
return DDERR_IMPLICITLYCREATED;
|
|
}
|
|
|
|
/*
|
|
* Don't allow source surface for visible overlay sprite to be resized.
|
|
*/
|
|
if (this_lcl->dwFlags & DDRAWISURF_INMASTERSPRITELIST)
|
|
{
|
|
DPF_ERR("Can't resize source surface for visible overlay sprite");
|
|
LEAVE_DDRAW();
|
|
return DDERR_INVALIDSURFACETYPE;
|
|
}
|
|
|
|
/*
|
|
* Don't allow client-allocated surface memory to be resized.
|
|
*/
|
|
if (this_gbl->dwGlobalFlags & DDRAWISURFGBL_ISCLIENTMEM)
|
|
{
|
|
DPF_ERR("Can't resize surface with client-allocated memory");
|
|
LEAVE_DDRAW();
|
|
return DDERR_INVALIDSURFACETYPE;
|
|
}
|
|
|
|
/*
|
|
* Make sure we are in the same mode the surface was created in.
|
|
*/
|
|
#ifdef WIN95
|
|
if (pdrv_gbl->dwModeIndex != this_lcl->dwModeCreatedIn)
|
|
#else
|
|
if (!EQUAL_DISPLAYMODE(pdrv_gbl->dmiCurrent, this_lcl->lpSurfMore->dmiCreated))
|
|
#endif
|
|
{
|
|
DPF_ERR("Not in mode in which surface was created");
|
|
LEAVE_DDRAW();
|
|
return DDERR_WRONGMODE;
|
|
}
|
|
|
|
/*
|
|
* Device busy?
|
|
*/
|
|
if (*(pdrv_gbl->lpwPDeviceFlags) & BUSY)
|
|
{
|
|
DPF_ERR("Can't resize locked surface");
|
|
LEAVE_DDRAW();
|
|
return DDERR_SURFACEBUSY;
|
|
}
|
|
|
|
BUMP_SURFACE_STAMP(this_gbl);
|
|
|
|
#ifdef WINNT
|
|
/*
|
|
* Once we delete the surface object, we are committed to
|
|
* creating a new surface object before we return. This is true
|
|
* regardless of whether we succeed in resizing the surface.
|
|
*/
|
|
if (!DdDeleteSurfaceObject(this_lcl))
|
|
{
|
|
/*
|
|
* Something is terribly wrong with GDI and/or DDraw!
|
|
*/
|
|
DPF_ERR("GDI failed to delete surface object!");
|
|
LEAVE_DDRAW();
|
|
return DDERR_GENERIC;
|
|
}
|
|
#endif //WINNT
|
|
|
|
/*
|
|
* Now call the driver to resize the surface for us.
|
|
*/
|
|
rszd.lpDD = pdrv_gbl;
|
|
rszd.lpDDSurface = this_lcl;
|
|
rszd.dwFlags = dwFlags;
|
|
rszd.dwWidth = dwWidth;
|
|
rszd.dwHeight = dwHeight;
|
|
rszd.ddRVal = 0;
|
|
|
|
// The following definition allows DOHALCALL to be used
|
|
// with thunkless, 32-bit callback.
|
|
#define _DDHAL_Resize NULL
|
|
|
|
DOHALCALL(Resize, pfn, rszd, rc, 0);
|
|
|
|
/*
|
|
* If driver callback succeeded, DirectDraw is responsible for
|
|
* updating the surface's width, height, etc.
|
|
*/
|
|
if (rszd.ddRVal == DD_OK)
|
|
{
|
|
// Driver should have set these parameters itself:
|
|
DDASSERT(this_gbl->fpVidMem != (FLATPTR)NULL);
|
|
DDASSERT(this_lcl->lpSurfMore->dwBytesAllocated != 0);
|
|
|
|
// Update surface parameters.
|
|
this_gbl->wWidth = (WORD)dwWidth;
|
|
this_gbl->wHeight = (WORD)dwHeight;
|
|
this_lcl->dwFlags &= ~DDRAWISURF_INVALID;
|
|
this_gbl->dwGlobalFlags &= ~DDRAWISURFGBL_MEMFREE;
|
|
}
|
|
|
|
#ifdef WINNT
|
|
/*
|
|
* We deleted the surface object above, so we must create a new
|
|
* surface object before we return. This is true regardless of
|
|
* whether the driver call succeeded in resizing the surface.
|
|
*/
|
|
if (!DdCreateSurfaceObject(this_lcl, FALSE))
|
|
{
|
|
if(!(DDSCAPS_SYSTEMMEMORY & this_lcl->ddsCaps.dwCaps))
|
|
{
|
|
/*
|
|
* We hope this is rare and pathological condition because we
|
|
* just destroyed the surface object the client gave us. Oops.
|
|
*/
|
|
DPF_ERR("GDI failed to create surface object!");
|
|
rszd.ddRVal = DDERR_GENERIC;
|
|
}
|
|
}
|
|
#endif //WINNT
|
|
|
|
if (rc != DDHAL_DRIVER_HANDLED)
|
|
{
|
|
DPF_ERR("Driver wouldn't handle callback");
|
|
LEAVE_DDRAW();
|
|
return DDERR_UNSUPPORTED;
|
|
}
|
|
|
|
LEAVE_DDRAW();
|
|
return rszd.ddRVal;
|
|
|
|
} /* DD_Surface_Resize */
|
|
#endif //POSTPONED2
|
|
|
|
#undef DPF_MODNAME
|
|
#define DPF_MODNAME "SetPriority"
|
|
|
|
HRESULT DDAPI DD_Surface_SetPriority(LPDIRECTDRAWSURFACE7 lpDDSurface, DWORD dwPriority)
|
|
{
|
|
HRESULT rc;
|
|
LPDDRAWI_DDRAWSURFACE_INT this_int;
|
|
LPDDRAWI_DDRAWSURFACE_LCL this_lcl;
|
|
LPDDRAWI_DIRECTDRAW_LCL pdrv_lcl;
|
|
|
|
#if DBG
|
|
DPF(2,A,"ENTERAPI: DD_Surface_SetPriority");
|
|
|
|
TRY
|
|
{
|
|
#endif
|
|
this_int = (LPDDRAWI_DDRAWSURFACE_INT)lpDDSurface;
|
|
#if DBG
|
|
/*
|
|
* Validate surface pointer.
|
|
*/
|
|
if (!VALID_DIRECTDRAWSURFACE_PTR(this_int))
|
|
{
|
|
DPF_ERR("Invalid surface object");
|
|
return DDERR_INVALIDOBJECT;
|
|
}
|
|
#endif
|
|
this_lcl = this_int->lpLcl; // internal local surface object
|
|
pdrv_lcl = this_lcl->lpSurfMore->lpDD_lcl; // internal local DD object
|
|
#if DBG
|
|
}
|
|
EXCEPT( EXCEPTION_EXECUTE_HANDLER )
|
|
{
|
|
DPF_ERR("Exception encountered validating parameters");
|
|
return DDERR_INVALIDPARAMS;
|
|
}
|
|
|
|
if(!IsToplevel(this_lcl))
|
|
{
|
|
DPF_ERR( "Cannot set priority on a mipmap sublevel or a cubemap subface" );
|
|
return DDERR_INVALIDPARAMS;
|
|
}
|
|
|
|
if(this_lcl->lpSurfMore->lpTex == NULL)
|
|
{
|
|
DPF_ERR("SetPriority can only be called on a managed texture");
|
|
return DDERR_INVALIDOBJECT;
|
|
}
|
|
|
|
if( pdrv_lcl->pD3DSetPriority == NULL )
|
|
{
|
|
DPF_ERR("D3D is not yet initialized or app didn't use DirectDrawCreateEx");
|
|
return DDERR_D3DNOTINITIALIZED;
|
|
}
|
|
#endif
|
|
if(pdrv_lcl->dwLocalFlags & DDRAWILCL_MULTITHREADED)
|
|
{
|
|
ENTER_DDRAW();
|
|
rc = pdrv_lcl->pD3DSetPriority(this_lcl->lpSurfMore->lpTex, dwPriority);
|
|
LEAVE_DDRAW();
|
|
}
|
|
else
|
|
{
|
|
rc = pdrv_lcl->pD3DSetPriority(this_lcl->lpSurfMore->lpTex, dwPriority);
|
|
}
|
|
|
|
return rc;
|
|
}
|
|
|
|
#undef DPF_MODNAME
|
|
#define DPF_MODNAME "GetPriority"
|
|
|
|
HRESULT DDAPI DD_Surface_GetPriority(LPDIRECTDRAWSURFACE7 lpDDSurface, LPDWORD lpdwPriority)
|
|
{
|
|
HRESULT rc;
|
|
LPDDRAWI_DDRAWSURFACE_INT this_int;
|
|
LPDDRAWI_DDRAWSURFACE_LCL this_lcl;
|
|
LPDDRAWI_DIRECTDRAW_LCL pdrv_lcl;
|
|
|
|
ENTER_DDRAW();
|
|
|
|
DPF(2,A,"ENTERAPI: DD_Surface_GetPriority");
|
|
|
|
TRY
|
|
{
|
|
this_int = (LPDDRAWI_DDRAWSURFACE_INT)lpDDSurface;
|
|
/*
|
|
* Validate surface pointer.
|
|
*/
|
|
if (!VALID_DIRECTDRAWSURFACE_PTR(this_int))
|
|
{
|
|
DPF_ERR("Invalid surface object");
|
|
LEAVE_DDRAW();
|
|
return DDERR_INVALIDOBJECT;
|
|
}
|
|
|
|
/*
|
|
* Validate DWORD pointer.
|
|
*/
|
|
if (!VALID_DWORD_PTR( lpdwPriority ))
|
|
{
|
|
DPF_ERR("Invalid DWORD pointer");
|
|
LEAVE_DDRAW();
|
|
return DDERR_INVALIDOBJECT;
|
|
}
|
|
|
|
this_lcl = this_int->lpLcl; // internal local surface object
|
|
pdrv_lcl = this_lcl->lpSurfMore->lpDD_lcl; // internal local DD object
|
|
}
|
|
EXCEPT( EXCEPTION_EXECUTE_HANDLER )
|
|
{
|
|
DPF_ERR("Exception encountered validating parameters");
|
|
LEAVE_DDRAW();
|
|
return DDERR_INVALIDPARAMS;
|
|
}
|
|
|
|
if(!IsToplevel(this_lcl))
|
|
{
|
|
DPF_ERR( "Cannot get priority from a mipmap sublevel or a cubemap subface" );
|
|
LEAVE_DDRAW();
|
|
return DDERR_INVALIDPARAMS;
|
|
}
|
|
|
|
if(this_lcl->lpSurfMore->lpTex == NULL)
|
|
{
|
|
DPF_ERR("GetPriority can only be called on a managed texture");
|
|
LEAVE_DDRAW();
|
|
return DDERR_INVALIDOBJECT;
|
|
}
|
|
|
|
if( pdrv_lcl->pD3DGetPriority == NULL )
|
|
{
|
|
DPF_ERR("D3D is not yet initialized or app didn't use DirectDrawCreateEx");
|
|
LEAVE_DDRAW();
|
|
return DDERR_D3DNOTINITIALIZED;
|
|
}
|
|
|
|
rc = pdrv_lcl->pD3DGetPriority(this_lcl->lpSurfMore->lpTex, lpdwPriority);
|
|
|
|
LEAVE_DDRAW();
|
|
|
|
return rc;
|
|
}
|
|
|
|
#undef DPF_MODNAME
|
|
#define DPF_MODNAME "SetLOD"
|
|
|
|
HRESULT DDAPI DD_Surface_SetLOD(LPDIRECTDRAWSURFACE7 lpDDSurface, DWORD dwLOD)
|
|
{
|
|
HRESULT rc;
|
|
LPDDRAWI_DDRAWSURFACE_INT this_int;
|
|
LPDDRAWI_DDRAWSURFACE_LCL this_lcl;
|
|
LPDDRAWI_DIRECTDRAW_LCL pdrv_lcl;
|
|
|
|
ENTER_DDRAW();
|
|
|
|
DPF(2,A,"ENTERAPI: DD_Surface_SetLOD");
|
|
|
|
TRY
|
|
{
|
|
this_int = (LPDDRAWI_DDRAWSURFACE_INT)lpDDSurface;
|
|
/*
|
|
* Validate surface pointer.
|
|
*/
|
|
if (!VALID_DIRECTDRAWSURFACE_PTR(this_int))
|
|
{
|
|
DPF_ERR("Invalid surface object");
|
|
LEAVE_DDRAW();
|
|
return DDERR_INVALIDOBJECT;
|
|
}
|
|
|
|
this_lcl = this_int->lpLcl; // internal local surface object
|
|
pdrv_lcl = this_lcl->lpSurfMore->lpDD_lcl; // internal local DD object
|
|
}
|
|
EXCEPT( EXCEPTION_EXECUTE_HANDLER )
|
|
{
|
|
DPF_ERR("Exception encountered validating parameters");
|
|
LEAVE_DDRAW();
|
|
return DDERR_INVALIDPARAMS;
|
|
}
|
|
|
|
if(!IsToplevel(this_lcl))
|
|
{
|
|
DPF_ERR( "Cannot set LOD on a mipmap sublevel or a cubemap subface" );
|
|
LEAVE_DDRAW();
|
|
return DDERR_INVALIDPARAMS;
|
|
}
|
|
|
|
if(this_lcl->lpSurfMore->lpTex == NULL)
|
|
{
|
|
DPF_ERR("SetLOD can only be called on a managed texture");
|
|
LEAVE_DDRAW();
|
|
return DDERR_INVALIDOBJECT;
|
|
}
|
|
|
|
if( pdrv_lcl->pD3DSetLOD == NULL )
|
|
{
|
|
DPF_ERR("D3D is not yet initialized or app didn't use DirectDrawCreateEx");
|
|
LEAVE_DDRAW();
|
|
return DDERR_D3DNOTINITIALIZED;
|
|
}
|
|
|
|
rc = pdrv_lcl->pD3DSetLOD(this_lcl->lpSurfMore->lpTex, dwLOD);
|
|
|
|
LEAVE_DDRAW();
|
|
|
|
return rc;
|
|
}
|
|
|
|
#undef DPF_MODNAME
|
|
#define DPF_MODNAME "GetLOD"
|
|
|
|
HRESULT DDAPI DD_Surface_GetLOD(LPDIRECTDRAWSURFACE7 lpDDSurface, LPDWORD lpdwLOD)
|
|
{
|
|
HRESULT rc;
|
|
LPDDRAWI_DDRAWSURFACE_INT this_int;
|
|
LPDDRAWI_DDRAWSURFACE_LCL this_lcl;
|
|
LPDDRAWI_DIRECTDRAW_LCL pdrv_lcl;
|
|
|
|
ENTER_DDRAW();
|
|
|
|
DPF(2,A,"ENTERAPI: DD_Surface_GetLOD");
|
|
|
|
TRY
|
|
{
|
|
this_int = (LPDDRAWI_DDRAWSURFACE_INT)lpDDSurface;
|
|
/*
|
|
* Validate surface pointer.
|
|
*/
|
|
if (!VALID_DIRECTDRAWSURFACE_PTR(this_int))
|
|
{
|
|
DPF_ERR("Invalid surface object");
|
|
LEAVE_DDRAW();
|
|
return DDERR_INVALIDOBJECT;
|
|
}
|
|
|
|
/*
|
|
* Validate DWORD pointer.
|
|
*/
|
|
if (!VALID_DWORD_PTR( lpdwLOD ))
|
|
{
|
|
DPF_ERR("Invalid DWORD pointer");
|
|
LEAVE_DDRAW();
|
|
return DDERR_INVALIDOBJECT;
|
|
}
|
|
|
|
this_lcl = this_int->lpLcl; // internal local surface object
|
|
pdrv_lcl = this_lcl->lpSurfMore->lpDD_lcl; // internal local DD object
|
|
}
|
|
EXCEPT( EXCEPTION_EXECUTE_HANDLER )
|
|
{
|
|
DPF_ERR("Exception encountered validating parameters");
|
|
LEAVE_DDRAW();
|
|
return DDERR_INVALIDPARAMS;
|
|
}
|
|
|
|
if(!IsToplevel(this_lcl))
|
|
{
|
|
DPF_ERR( "Cannot get LOD from a mipmap sublevel or a cubemap subface" );
|
|
LEAVE_DDRAW();
|
|
return DDERR_INVALIDPARAMS;
|
|
}
|
|
|
|
if(this_lcl->lpSurfMore->lpTex == NULL)
|
|
{
|
|
DPF_ERR("GetLOD can only be called on a managed texture");
|
|
LEAVE_DDRAW();
|
|
return DDERR_INVALIDOBJECT;
|
|
}
|
|
|
|
if( pdrv_lcl->pD3DGetLOD == NULL )
|
|
{
|
|
DPF_ERR("D3D is not yet initialized or app didn't use DirectDrawCreateEx");
|
|
LEAVE_DDRAW();
|
|
return DDERR_D3DNOTINITIALIZED;
|
|
}
|
|
|
|
rc = pdrv_lcl->pD3DGetLOD(this_lcl->lpSurfMore->lpTex, lpdwLOD);
|
|
|
|
LEAVE_DDRAW();
|
|
|
|
return rc;
|
|
}
|