mirror of https://github.com/lianthony/NT4.0
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
3097 lines
80 KiB
3097 lines
80 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)
|
|
*
|
|
***************************************************************************/
|
|
#include "ddrawpr.h"
|
|
#ifdef WINNT
|
|
#include "ddrawgdi.h"
|
|
#endif
|
|
#define DPF_MODNAME "GetCaps"
|
|
|
|
/*
|
|
* DD_Surface_GetCaps
|
|
*/
|
|
HRESULT DDAPI DD_Surface_GetCaps(
|
|
LPDIRECTDRAWSURFACE lpDDSurface,
|
|
LPDDSCAPS lpDDSCaps )
|
|
{
|
|
LPDDRAWI_DDRAWSURFACE_INT this_int;
|
|
LPDDRAWI_DDRAWSURFACE_LCL this_lcl;
|
|
LPDDRAWI_DDRAWSURFACE_GBL this;
|
|
|
|
ENTER_DDRAW();
|
|
|
|
TRY
|
|
{
|
|
this_int = (LPDDRAWI_DDRAWSURFACE_INT) lpDDSurface;
|
|
if( !VALID_DIRECTDRAWSURFACE_PTR( this_int ) )
|
|
{
|
|
LEAVE_DDRAW();
|
|
return DDERR_INVALIDOBJECT;
|
|
}
|
|
if( !VALID_DDSCAPS_PTR( lpDDSCaps ) )
|
|
{
|
|
LEAVE_DDRAW();
|
|
return DDERR_INVALIDPARAMS;
|
|
}
|
|
this_lcl = this_int->lpLcl;
|
|
this = this_lcl->lpGbl;
|
|
lpDDSCaps->dwCaps = this_lcl->ddsCaps.dwCaps;
|
|
}
|
|
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();
|
|
|
|
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) ||
|
|
!(this_lcl->ddsCaps.dwCaps & DDSCAPS_FLIP) )
|
|
{
|
|
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;
|
|
}
|
|
|
|
/*
|
|
* device busy?
|
|
*/
|
|
if( *(pdrv->lpwPDeviceFlags) & BUSY )
|
|
{
|
|
DPF( 2, "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 "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;
|
|
LPDDHALSURFCB_GETBLTSTATUS gbshalfn;
|
|
LPDDHALSURFCB_GETBLTSTATUS gbsfn;
|
|
LPDDRAWI_DIRECTDRAW_LCL pdrv_lcl;
|
|
LPDDRAWI_DIRECTDRAW_GBL pdrv;
|
|
|
|
ENTER_DDRAW();
|
|
|
|
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;
|
|
}
|
|
|
|
/*
|
|
* device busy?
|
|
*/
|
|
if( *(pdrv->lpwPDeviceFlags) & BUSY )
|
|
{
|
|
DPF( 3, "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;
|
|
}
|
|
|
|
/*
|
|
* ask the driver to get the current blt status
|
|
*/
|
|
gbsfn = pdrv_lcl->lpDDCB->HALDDSurface.GetBltStatus;
|
|
gbshalfn = pdrv_lcl->lpDDCB->cbDDSurfaceCallbacks.GetBltStatus;
|
|
if( gbshalfn != NULL )
|
|
{
|
|
DDHAL_GETBLTSTATUSDATA gbsd;
|
|
DWORD rc;
|
|
|
|
gbsd.GetBltStatus = gbshalfn;
|
|
gbsd.lpDD = pdrv;
|
|
gbsd.dwFlags = dwFlags;
|
|
gbsd.lpDDSurface = this_lcl;
|
|
DOHALCALL( GetBltStatus, gbsfn, gbsd, rc, FALSE );
|
|
if( rc == DDHAL_DRIVER_HANDLED )
|
|
{
|
|
LEAVE_DDRAW();
|
|
return gbsd.ddRVal;
|
|
}
|
|
}
|
|
|
|
// if you have to ask the hel, it's already done...
|
|
LEAVE_DDRAW();
|
|
return DD_OK;
|
|
|
|
} /* 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();
|
|
|
|
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;
|
|
DWORD reserved;
|
|
DWORD gdi_flag;
|
|
DWORD handle;
|
|
BOOL toplevel;
|
|
int destindex;
|
|
int thisindex;
|
|
BOOL destfound;
|
|
|
|
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 )
|
|
{
|
|
if( next_int == (LPDDRAWI_DDRAWSURFACE_INT) lpDDSurfaceDest )
|
|
{
|
|
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 != this_int );
|
|
|
|
/*
|
|
* 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;
|
|
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;
|
|
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;
|
|
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;
|
|
|
|
} while( next_int != this_int );
|
|
}
|
|
|
|
this->fpVidMem = vidmem;
|
|
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 */
|
|
|
|
/*
|
|
* DD_Surface_Flip
|
|
*
|
|
* Page flip to the next surface. Only valid for surfaces which are
|
|
* flippable.
|
|
*/
|
|
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;
|
|
FLATPTR vidmem;
|
|
LPVMEMHEAP vidmemheap;
|
|
DWORD reserved;
|
|
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 gdi_flag;
|
|
DWORD handle;
|
|
|
|
ENTER_BOTH();
|
|
|
|
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( SURFACE_LOST( this_lcl ) )
|
|
{
|
|
LEAVE_BOTH();
|
|
return DDERR_SURFACELOST;
|
|
}
|
|
if( this_dest != NULL )
|
|
{
|
|
if( SURFACE_LOST( this_dest_lcl ) )
|
|
{
|
|
LEAVE_BOTH();
|
|
return DDERR_SURFACELOST;
|
|
}
|
|
}
|
|
|
|
/*
|
|
* device busy?
|
|
*/
|
|
pdrv_lcl = this_lcl->lpSurfMore->lpDD_lcl;
|
|
pdrv = pdrv_lcl->lpGbl;
|
|
|
|
if( *(pdrv->lpwPDeviceFlags) & BUSY )
|
|
{
|
|
DPF( 2, "BUSY - Flip" );
|
|
LEAVE_BOTH()
|
|
return DDERR_SURFACEBUSY;
|
|
}
|
|
|
|
/*
|
|
* make sure that it's OK to flip this surface
|
|
*/
|
|
if( !(this_lcl->ddsCaps.dwCaps & DDSCAPS_FRONTBUFFER) )
|
|
{
|
|
LEAVE_BOTH();
|
|
return DDERR_NOTFLIPPABLE; // ACKACK: real error??
|
|
}
|
|
if( !(this_lcl->ddsCaps.dwCaps & DDSCAPS_FLIP) )
|
|
{
|
|
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 == NULL) || (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 )
|
|
{
|
|
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;
|
|
next_save_int = next_int = FindAttachedFlip( this_int );
|
|
if( next_int == NULL )
|
|
{
|
|
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 )
|
|
{
|
|
LEAVE_BOTH();
|
|
return DDERR_SURFACEBUSY;
|
|
}
|
|
if( this_dest_int == next_int )
|
|
{
|
|
found_dest = TRUE;
|
|
}
|
|
next_int = FindAttachedFlip( next_int );
|
|
} while( next_int != this_int );
|
|
|
|
/*
|
|
* 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;
|
|
}
|
|
else
|
|
{
|
|
ffn = pdrv_lcl->lpDDCB->HALDDSurface.Flip;
|
|
fhalfn = pdrv_lcl->lpDDCB->cbDDSurfaceCallbacks.Flip;
|
|
emulation = FALSE;
|
|
caps = pdrv->ddCaps.dwCaps;
|
|
}
|
|
|
|
/*
|
|
* 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.)
|
|
*/
|
|
if( ( this_lcl->ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE ) ||
|
|
( ( this_lcl->ddsCaps.dwCaps & DDSCAPS_OVERLAY ) &&
|
|
( caps & DDCAPS_OVERLAY ) ) )
|
|
{
|
|
if( fhalfn != NULL )
|
|
{
|
|
fd.Flip = fhalfn;
|
|
fd.lpDD = pdrv;
|
|
fd.dwFlags = 0;
|
|
fd.lpSurfCurr = this_lcl;
|
|
fd.lpSurfTarg = next_lcl;
|
|
try_again:
|
|
DOHALCALL_NOWIN16( Flip, ffn, fd, rc, emulation );
|
|
if( rc == DDHAL_DRIVER_HANDLED )
|
|
{
|
|
#ifdef WINNT
|
|
if (0) //fd.ddRVal == DDERR_SURFACELOST)
|
|
{
|
|
if (!NTModeChanged(pdrv))
|
|
{
|
|
DPF( 0,"Mode change not successful");
|
|
LEAVE_BOTH();
|
|
return DDERR_INVALIDMODE;
|
|
}
|
|
goto try_again;
|
|
}//if surfacelost
|
|
#endif
|
|
|
|
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_BOTH();
|
|
return DD_OK;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
LEAVE_BOTH();
|
|
return DDERR_NOFLIPHW;
|
|
}
|
|
}
|
|
|
|
/*
|
|
* save the old values
|
|
*/
|
|
DPF(9,"Flip:rotating pointers etc");
|
|
vidmem = next_lcl->lpGbl->fpVidMem;
|
|
vidmemheap = next_lcl->lpGbl->lpVidMemHeap;
|
|
reserved = next_lcl->lpGbl->dwReserved1;
|
|
gdi_flag = next_lcl->lpGbl->dwGlobalFlags & DDRAWISURFGBL_ISGDISURFACE;
|
|
handle = next_lcl->hDDSurface;
|
|
|
|
/*
|
|
* 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;
|
|
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
|
|
{
|
|
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;
|
|
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;
|
|
} while( next_int != this_int );
|
|
}
|
|
this->fpVidMem = vidmem;
|
|
this->lpVidMemHeap = vidmemheap;
|
|
this->dwReserved1 = reserved;
|
|
this->dwGlobalFlags &= ~DDRAWISURFGBL_ISGDISURFACE;
|
|
this->dwGlobalFlags |= gdi_flag;
|
|
this_lcl->hDDSurface = handle;
|
|
|
|
/*
|
|
* 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_BOTH();
|
|
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();
|
|
|
|
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();
|
|
|
|
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();
|
|
|
|
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 */
|
|
|
|
#undef DPF_MODNAME
|
|
#define DPF_MODNAME "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();
|
|
|
|
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 )
|
|
{
|
|
DPF_ERR( "Invalid surface type: can't get DC" );
|
|
LEAVE_DDRAW();
|
|
return DDERR_INVALIDSURFACETYPE;
|
|
}
|
|
if( SURFACE_LOST( this_lcl ) )
|
|
{
|
|
LEAVE_DDRAW();
|
|
return DDERR_SURFACELOST;
|
|
}
|
|
// DC already returned for this surface?
|
|
if( this_lcl->dwFlags & DDRAWISURF_HASDC )
|
|
{
|
|
DPF_ERR( "Can only return one DC per surface" );
|
|
LEAVE_DDRAW();
|
|
return DDERR_DCALREADYCREATED;
|
|
}
|
|
|
|
// default value is null:
|
|
*lphDC = (HDC) 0;
|
|
|
|
}
|
|
EXCEPT( EXCEPTION_EXECUTE_HANDLER )
|
|
{
|
|
DPF_ERR( "Exception encountered validating parameters" );
|
|
LEAVE_DDRAW();
|
|
return DDERR_INVALIDPARAMS;
|
|
}
|
|
|
|
{
|
|
DDSURFACEDESC ddsd;
|
|
LPVOID pbits;
|
|
ddrval = InternalLock(this_lcl, &pbits, NULL , DDLOCK_WAIT | DDLOCK_TAKE_WIN16 );
|
|
|
|
if( ddrval == DD_OK )
|
|
{
|
|
DPF(10,"GetDC: Lock succeeded.");
|
|
|
|
#ifdef WIN95
|
|
ddsd.dwSize = sizeof(ddsd);
|
|
FillDDSurfaceDesc( this_lcl, &ddsd );
|
|
ddsd.lpSurface = pbits;
|
|
|
|
*lphDC = DD16_GetDC(&ddsd);
|
|
#else
|
|
|
|
if (this_lcl->ddsCaps.dwCaps & DDSCAPS_VIDEOMEMORY)
|
|
{
|
|
HDC hdc;
|
|
hdc = GetDC(NULL);
|
|
*lphDC = NULL;
|
|
if (hdc)
|
|
{
|
|
DPF(10,"DdGetDC");
|
|
*lphDC = DdGetDC(this_lcl);
|
|
ReleaseDC(NULL,hdc);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (this_lcl->ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE)
|
|
{
|
|
DPF(10,"GetDC(NULL)");
|
|
*lphDC = GetDC(NULL);
|
|
}
|
|
else
|
|
{
|
|
DPF(10,"Duplicate DIBSection's DC");
|
|
SelectObject( (HDC) this_lcl->hDC, CreateBitmap(0,0,1,1,NULL));
|
|
*lphDC = CreateCompatibleDC((HDC) this_lcl->hDC );
|
|
this->dwReserved1 = (DWORD) SelectObject(*lphDC,(HGDIOBJ)this_lcl->dwReserved1);
|
|
//*lphDC = (HDC) this_lcl->hDC;
|
|
}
|
|
}
|
|
#endif
|
|
|
|
if( *lphDC == NULL )
|
|
{
|
|
DD_Surface_Unlock(lpDDSurface, NULL);
|
|
DPF_ERR( "Could not obtain DC" );
|
|
ddrval = DDERR_CANTCREATEDC;
|
|
}
|
|
else
|
|
{
|
|
this_lcl->dwFlags |= DDRAWISURF_HASDC;
|
|
}
|
|
}
|
|
#ifdef WIN95
|
|
// 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) )
|
|
{
|
|
DPF(10,"GetDC: Returning GetDC(NULL).");
|
|
*lphDC = GetDC(NULL);
|
|
if (*lphDC)
|
|
{
|
|
// signal to ourselves that we gave a DC without
|
|
// locking.
|
|
this_lcl->dwFlags |= DDRAWISURF_GETDCNULL;
|
|
|
|
ddrval = DD_OK;
|
|
this_lcl->dwFlags |= DDRAWISURF_HASDC;
|
|
this->dwUsageCount++;
|
|
CHANGE_GLOBAL_CNT( pdrv, this, 1 );
|
|
}
|
|
else
|
|
{
|
|
DPF_ERR( "Could not obtain DC" );
|
|
ddrval = DDERR_CANTCREATEDC;
|
|
}
|
|
}
|
|
#endif
|
|
else
|
|
{
|
|
DPF(1, "Unable to lock surface err=%d", ddrval);
|
|
}
|
|
}
|
|
|
|
LEAVE_DDRAW();
|
|
return ddrval;
|
|
|
|
} /* DD_Surface_GetDC */
|
|
|
|
#undef DPF_MODNAME
|
|
#define DPF_MODNAME "ReleaseDC"
|
|
|
|
/*
|
|
* DD_Surface_ReleaseDC
|
|
*/
|
|
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;
|
|
|
|
ENTER_DDRAW();
|
|
|
|
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;
|
|
}
|
|
}
|
|
EXCEPT( EXCEPTION_EXECUTE_HANDLER )
|
|
{
|
|
DPF_ERR( "Exception encountered validating parameters" );
|
|
LEAVE_DDRAW();
|
|
return DDERR_INVALIDPARAMS;
|
|
}
|
|
|
|
#ifdef WIN95
|
|
if( (this_lcl->ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE) &&
|
|
(this_lcl->ddsCaps.dwCaps & DDSCAPS_SYSTEMMEMORY) &&
|
|
(this_lcl->dwFlags & DDRAWISURF_GETDCNULL) )
|
|
{
|
|
DPF(10,"ReleaseDC: Returning ReleaseDC(NULL).");
|
|
this->dwUsageCount--;
|
|
CHANGE_GLOBAL_CNT( pdrv, this, -1 );
|
|
ReleaseDC(NULL,hdc);
|
|
this_lcl->dwFlags &= ~(DDRAWISURF_HASDC | DDRAWISURF_GETDCNULL);
|
|
LEAVE_DDRAW();
|
|
return DD_OK;
|
|
}
|
|
else
|
|
{
|
|
DPF(10,"ReleaseDC: Normal DD16_ReleaseDC.");
|
|
DD16_ReleaseDC(hdc);
|
|
}
|
|
#else // WINNT
|
|
{
|
|
if (this_lcl->ddsCaps.dwCaps & DDSCAPS_VIDEOMEMORY)
|
|
{
|
|
ddrval = DD_OK;
|
|
if (!DdReleaseDC(this_lcl))
|
|
{
|
|
DPF(9,"DDreleaseDC fails!");
|
|
ddrval = DDERR_GENERIC;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (this_lcl->ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE)
|
|
{
|
|
DPF(2,"NT emulation releasing primary DC");
|
|
ReleaseDC( NULL, hdc );
|
|
}
|
|
//if (hdc != this_lcl ->hDC)
|
|
else
|
|
{
|
|
SelectObject(hdc,(HGDIOBJ) (this->dwReserved1)); //this_lcl->dwReserved1);
|
|
SelectObject((HDC)this_lcl->hDC, (HGDIOBJ) (this_lcl->dwReserved1));
|
|
DeleteDC(hdc);
|
|
}
|
|
}
|
|
}
|
|
#endif // WINNT
|
|
|
|
ddrval = DD_Surface_Unlock(lpDDSurface, NULL);
|
|
|
|
this_lcl->dwFlags &= ~DDRAWISURF_HASDC;
|
|
|
|
#ifdef DEBUG
|
|
if(ddrval != DD_OK)
|
|
{
|
|
DPF(1,"DD_Surface_ReleaseDC: DD_Surface_Unlock failed: 0x%x",ddrval);
|
|
}
|
|
#endif // DEBUG
|
|
|
|
LEAVE_DDRAW();
|
|
return ddrval;
|
|
|
|
} /* DD_Surface_ReleaseDC */
|
|
|
|
#undef DPF_MODNAME
|
|
#define DPF_MODNAME "SetFourCCCode"
|
|
|
|
/*
|
|
* DD_Surface_SetFourCCCode
|
|
*/
|
|
HRESULT DDAPI DD_Surface_SetFourCCCode(
|
|
LPDIRECTDRAWSURFACE lpDDSurface,
|
|
LPDDPIXELFORMAT lpDDPixelFormat )
|
|
{
|
|
LPDDRAWI_DDRAWSURFACE_INT this_int;
|
|
LPDDRAWI_DDRAWSURFACE_LCL this_lcl;
|
|
LPDDRAWI_DDRAWSURFACE_GBL this;
|
|
LPDDRAWI_DIRECTDRAW_GBL pdrv;
|
|
|
|
ENTER_DDRAW();
|
|
|
|
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 ) )
|
|
{
|
|
DPF_ERR( "Invalid pixel format" );
|
|
LEAVE_DDRAW();
|
|
return DDERR_INVALIDPARAMS;
|
|
}
|
|
|
|
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 DDERR_UNSUPPORTED;
|
|
|
|
} /* DD_Surface_SetFourCCCode */
|
|
|
|
#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();
|
|
|
|
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_IsLost */
|
|
|
|
#undef DPF_MODNAME
|
|
#define DPF_MODNAME "Initialize"
|
|
|
|
/*
|
|
* DD_Surface_Initialize
|
|
*/
|
|
HRESULT DDAPI DD_Surface_Initialize(
|
|
LPDIRECTDRAWSURFACE lpDDSurface,
|
|
LPDIRECTDRAW lpDD,
|
|
LPDDSURFACEDESC lpDDSurfaceDesc )
|
|
{
|
|
DPF_ERR( "DirectDrawSurface: Already initialized." );
|
|
return DDERR_ALREADYINITIALIZED;
|
|
|
|
} /* DD_Surface_Initialize */
|
|
|
|
|
|
#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;
|
|
DDSURFACEDESC ddsd;
|
|
DWORD rc;
|
|
HRESULT ddrval;
|
|
UINT bpp;
|
|
LONG pitch;
|
|
BOOL do_alloc=TRUE;
|
|
|
|
this_lcl = this_int->lpLcl;
|
|
this = this_lcl->lpGbl;
|
|
|
|
pdrv_lcl = this_lcl->lpSurfMore->lpDD_lcl;
|
|
pdrv = pdrv_lcl->lpGbl;
|
|
|
|
/*
|
|
* If we made it to here the local surface should be marked invalid.
|
|
*/
|
|
DDASSERT( SURFACE_LOST( this_lcl ) );
|
|
|
|
if( this_lcl->dwModeCreatedIn != pdrv->dwModeIndex )
|
|
{
|
|
DPF_ERR( "Surface was not created in the current mode" );
|
|
return DDERR_WRONGMODE;
|
|
}
|
|
|
|
#ifdef WINNT
|
|
/*
|
|
* NT kernel needs to know to delete any previously allocated handles, but only in the context
|
|
* of the process that created that handle. So, we wait until surface restore time to delete a
|
|
* previously allocated handle for a lost surface.
|
|
* This needs to be done before the create surface HAL call in order to preserve any resources
|
|
* allocated by NT Kernel at that time.
|
|
*/
|
|
if ( (this_lcl->ddsCaps.dwCaps & DDSCAPS_VIDEOMEMORY) &&
|
|
!(this_lcl->ddsCaps.dwCaps & DDSCAPS_EXECUTEBUFFER )) //don't let NT kernel know about exec buffers
|
|
{
|
|
if (0 != this_lcl->hDDSurface)
|
|
{
|
|
DPF(9,"RestoreSurface: Deleting previously allocated NT kernel mode surface object");
|
|
DdDeleteSurfaceObject(this_lcl);
|
|
}
|
|
}
|
|
#endif
|
|
|
|
DPF(14,"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
|
|
);
|
|
|
|
/*
|
|
* was the memory freed or was it just marked as invalid?
|
|
*/
|
|
if( !(this->dwGlobalFlags & DDRAWISURFGBL_MEMFREE) )
|
|
{
|
|
this_lcl->dwFlags &= ~DDRAWISURF_INVALID;
|
|
ddrval = DD_OK;
|
|
}
|
|
else
|
|
{
|
|
slistx[0] = this_lcl;
|
|
slist[0] = this;
|
|
this->fpVidMem = 0;
|
|
|
|
DPF( 4, "Restoring 0x%08lx", 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(6,"HAL CreateSurface to be called");
|
|
/*
|
|
* construct a new surface description
|
|
*/
|
|
FillDDSurfaceDesc( this_lcl, &ddsd );
|
|
|
|
/*
|
|
* call the driver
|
|
*/
|
|
csd.CreateSurface = cshalfn;
|
|
csd.lpDD = pdrv;
|
|
csd.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;
|
|
}
|
|
}
|
|
}
|
|
|
|
if( do_alloc )
|
|
{
|
|
/*
|
|
* allocate the memory now...
|
|
*/
|
|
ddrval = AllocSurfaceMem( pdrv, slistx, 1 );
|
|
if( ddrval != DD_OK )
|
|
{
|
|
this->lPitch = pitch;
|
|
DPF(14,"Moving to system memory");
|
|
ddrval = MoveToSystemMemory( this_int, FALSE, TRUE );
|
|
}
|
|
if( ddrval == DD_OK )
|
|
{
|
|
this_lcl->dwFlags &= ~DDRAWISURF_INVALID;
|
|
this->dwGlobalFlags &= ~DDRAWISURFGBL_MEMFREE;
|
|
}
|
|
}
|
|
}
|
|
|
|
#ifdef WINNT
|
|
if( ddrval == DD_OK )
|
|
{
|
|
/*
|
|
* NT kernel needs to know about surface
|
|
*/
|
|
if ( (this_lcl->ddsCaps.dwCaps & DDSCAPS_VIDEOMEMORY) &&
|
|
!(this_lcl->ddsCaps.dwCaps & DDSCAPS_EXECUTEBUFFER )) //don't let NT kernel know about exec buffers
|
|
{
|
|
DPF(9,"RestoreSurface: Attempting to recreate NT kernel mode surface object");
|
|
if (!DdCreateSurfaceObject(this_lcl,this->dwGlobalFlags & DDRAWISURFGBL_ISGDISURFACE) )//DDSCAPS_PRIMARYSURFACE))
|
|
{
|
|
DPF_ERR("NT kernel mode stuff won't recreate its surface object!");
|
|
return DDERR_GENERIC;
|
|
}
|
|
DPF(9,"Kernel mode handle is %08x",this_lcl->hDDSurface);
|
|
}
|
|
}
|
|
#endif
|
|
|
|
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
|
|
*/
|
|
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 is_excl;
|
|
BOOL excl_exists;
|
|
DDSURFACEDESC ddsd;
|
|
|
|
ENTER_DDRAW();
|
|
|
|
/*
|
|
* validate parameters
|
|
*/
|
|
TRY
|
|
{
|
|
this_int = (LPDDRAWI_DDRAWSURFACE_INT) lpDDSurface;
|
|
if( !VALID_DIRECTDRAWSURFACE_PTR( this_int ) )
|
|
{
|
|
DPF_ERR( "Invalid surface pointer" );
|
|
LEAVE_DDRAW();
|
|
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();
|
|
return DDERR_INVALIDOBJECT;
|
|
}
|
|
if( !SURFACE_LOST( this_lcl ) )
|
|
{
|
|
LEAVE_DDRAW();
|
|
return DD_OK;;
|
|
}
|
|
}
|
|
EXCEPT( EXCEPTION_EXECUTE_HANDLER )
|
|
{
|
|
DPF_ERR( "Exception encountered validating parameters" );
|
|
LEAVE_DDRAW();
|
|
return DDERR_INVALIDPARAMS;
|
|
}
|
|
|
|
#ifdef WINNT
|
|
/*
|
|
* On NT after a Ctrl-Alt-Del closely followed by an esc, the system can
|
|
* end up back on the desktop, but the app still thinks it's fullscreen
|
|
* since we got no WM_ACTIVATEAPP(0) to deactivate it.
|
|
* Here we detect this case (app thinks it's fullscreen, different mode to app's preferred,
|
|
* not iconic, app wants full screen) and send ourselves a deactivate mesage.
|
|
* Eeesh what a hack.
|
|
*/
|
|
if (
|
|
!IsIconic((HWND)pdrv_lcl->hWnd) && //i.e. app not minimized
|
|
pdrv_lcl->dwPreferredMode != pdrv->dwModeIndex && //i.e. not in app's mode
|
|
pdrv_lcl->dwLocalFlags & DDRAWILCL_ISFULLSCREEN && //i.e. app wants FSE
|
|
pdrv_lcl->dwLocalFlags & DDRAWILCL_ACTIVEYES //i.e. app thinks it has FSE
|
|
)
|
|
{
|
|
/*
|
|
* Note! Could be a thread id different from the one that normally
|
|
* runs the app's message loop!
|
|
*/
|
|
DPF(1,"Sending WM_ACTIVATEAPP 0 to app after CAD");
|
|
PostMessage( (HWND)pdrv_lcl->hWnd, WM_ACTIVATEAPP, 0, GetCurrentThreadId() );
|
|
}
|
|
#endif
|
|
|
|
|
|
/*
|
|
* don't allow restoration of implicit surfaces
|
|
*/
|
|
if( (this_lcl->dwFlags & DDRAWISURF_IMPLICITCREATE) )
|
|
{
|
|
DPF_ERR( "Can't restore implicitly created surfaces" );
|
|
LEAVE_DDRAW();
|
|
return DDERR_IMPLICITLYCREATED;
|
|
}
|
|
|
|
/*
|
|
* make sure we are in the same mode the surface was created in
|
|
*/
|
|
if( pdrv->dwModeIndex != this_lcl->dwModeCreatedIn )
|
|
{
|
|
DPF_ERR("Cannot restore surface, not in original mode");
|
|
LEAVE_DDRAW();
|
|
return DDERR_WRONGMODE;
|
|
}
|
|
|
|
if( this_lcl->ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE )
|
|
{
|
|
/*
|
|
* are we the process with exclusive mode?
|
|
*/
|
|
if( pdrv->lpExclusiveOwner != NULL )
|
|
{
|
|
excl_exists = TRUE;
|
|
}
|
|
else
|
|
{
|
|
excl_exists = FALSE;
|
|
}
|
|
|
|
if( pdrv->lpExclusiveOwner == pdrv_lcl )
|
|
{
|
|
is_excl = TRUE;
|
|
}
|
|
else
|
|
{
|
|
is_excl = FALSE;
|
|
}
|
|
|
|
if( excl_exists && !is_excl )
|
|
{
|
|
DPF_ERR( "Cannot restore primary surface, not exclusive owner" );
|
|
LEAVE_DDRAW();
|
|
return DDERR_NOEXCLUSIVEMODE;
|
|
}
|
|
else if( !excl_exists )
|
|
{
|
|
/*
|
|
* no exclusive mode
|
|
*/
|
|
FillDDSurfaceDesc( this_lcl, &ddsd );
|
|
if( !MatchPrimary( pdrv, &ddsd ) )
|
|
{
|
|
DPF_ERR( "Can't restore primary, incompatible with current primary" );
|
|
LEAVE_DDRAW();
|
|
return DDERR_INCOMPATIBLEPRIMARY;
|
|
}
|
|
}
|
|
/*
|
|
* otherwise, it is OK to restore primary
|
|
*/
|
|
}
|
|
|
|
/*
|
|
* restore this surface
|
|
*/
|
|
ddrval = restoreSurface( this_int );
|
|
if( ddrval != DD_OK )
|
|
{
|
|
DPF( 2, "restoreSurface failed, rc=%08lx (%ld)", ddrval, LOWORD( ddrval ) );
|
|
LEAVE_DDRAW();
|
|
return ddrval;
|
|
}
|
|
|
|
/*
|
|
* restore all surfaces in an implicit chain
|
|
*/
|
|
if( this_lcl->dwFlags & DDRAWISURF_IMPLICITROOT )
|
|
{
|
|
ddrval = restoreAttachments( this_lcl );
|
|
}
|
|
|
|
LEAVE_DDRAW();
|
|
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;
|
|
DWORD newreserved;
|
|
DWORD newreserved_lcl;
|
|
// LPVOID newvidmemheap;
|
|
LONG newpitch;
|
|
FLATPTR newvidmem;
|
|
DWORD savereserved;
|
|
DWORD savereserved_lcl;
|
|
LPVOID savevidmemheap;
|
|
LONG savepitch;
|
|
FLATPTR savevidmem;
|
|
DDHAL_CREATESURFACEDATA csd;
|
|
DWORD rc;
|
|
DDSURFACEDESC ddsd;
|
|
LPDDRAWI_DDRAWSURFACE_LCL slistx;
|
|
LPBYTE lpvidmem;
|
|
LPBYTE lpsysmem;
|
|
DWORD bytecount;
|
|
DWORD line;
|
|
HRESULT ddrval;
|
|
LPVOID pbits;
|
|
WORD wHeight;
|
|
|
|
this_lcl = this_int->lpLcl;
|
|
this = this_lcl->lpGbl;
|
|
|
|
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
|
|
*/
|
|
DPF( 3, "Unable to move surface %08lx to system memory", this_int );
|
|
#ifdef DEBUG
|
|
if( this_lcl->lpAttachList != NULL )
|
|
{
|
|
DPF( 3, "AttachList is non-NULL" );
|
|
}
|
|
if( this_lcl->lpAttachListFrom != NULL )
|
|
{
|
|
DPF( 3, "AttachListFrom is non-NULL" );
|
|
}
|
|
if( this->dwUsageCount != 0 )
|
|
{
|
|
DPF( 3, "dwusageCount=%ld", this->dwUsageCount );
|
|
}
|
|
if( this_lcl->dwFlags & DDRAWISURF_PARTOFPRIMARYCHAIN )
|
|
{
|
|
DPF( 3, "part of the primary chain" );
|
|
}
|
|
if( this_lcl->ddsCaps.dwCaps & DDSCAPS_OVERLAY )
|
|
{
|
|
DPF( 3, "Is a hardware overlay" );
|
|
}
|
|
if( this_lcl->ddsCaps.dwCaps & DDSCAPS_SYSTEMMEMORY )
|
|
{
|
|
DPF( 3, "Is already in system memory" );
|
|
}
|
|
if( this_lcl->dwFlags & DDRAWISURF_HASPIXELFORMAT )
|
|
{
|
|
DPF( 3, "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;
|
|
|
|
/*
|
|
* lock the vram
|
|
*/
|
|
if( hasvram )
|
|
{
|
|
while( 1 )
|
|
{
|
|
if( use_full_lock )
|
|
{
|
|
ddsd.dwSize = sizeof( ddsd );
|
|
ddrval = DD_Surface_Lock(
|
|
(LPDIRECTDRAWSURFACE) this_int,
|
|
NULL,
|
|
&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( 1, "*** MoveToSystemMemory: Lock failed! rc = %08lx", ddrval );
|
|
return ddrval;
|
|
}
|
|
}
|
|
|
|
/*
|
|
* set up for a call to the HEL
|
|
*/
|
|
FillDDSurfaceDesc( this_lcl, &ddsd );
|
|
slistx = this_lcl;
|
|
csd.lpDD = this->lpDD;
|
|
csd.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;
|
|
if( hasvram )
|
|
{
|
|
if( use_full_lock )
|
|
{
|
|
DD_Surface_Unlock( (LPDIRECTDRAWSURFACE) this_int, NULL );
|
|
}
|
|
else
|
|
{
|
|
InternalUnlock( this_lcl, NULL, 0 );
|
|
}
|
|
}
|
|
DPF( 1, "*** 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;
|
|
if( hasvram )
|
|
{
|
|
if( use_full_lock )
|
|
{
|
|
DD_Surface_Unlock( (LPDIRECTDRAWSURFACE) this_int, NULL );
|
|
}
|
|
else
|
|
{
|
|
InternalUnlock( this_lcl, 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;
|
|
|
|
this->fpVidMem = savevidmem;
|
|
this->lpVidMemHeap = savevidmemheap;
|
|
this->lPitch = savepitch;
|
|
this->dwReserved1 = savereserved;
|
|
this_lcl->dwReserved1 = savereserved_lcl;
|
|
|
|
if( use_full_lock )
|
|
{
|
|
DD_Surface_Unlock( (LPDIRECTDRAWSURFACE) this_int, NULL );
|
|
}
|
|
else
|
|
{
|
|
InternalUnlock( this_lcl, 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;
|
|
}
|
|
|
|
/*
|
|
* mark this object as system memory
|
|
*/
|
|
this_lcl->ddsCaps.dwCaps &= ~DDSCAPS_VIDEOMEMORY;
|
|
this_lcl->ddsCaps.dwCaps |= DDSCAPS_SYSTEMMEMORY;
|
|
|
|
/*
|
|
* the hel needs to know we touched the memory
|
|
*/
|
|
if( use_full_lock )
|
|
{
|
|
DD_Surface_Lock( (LPDIRECTDRAWSURFACE) this_int, NULL, &ddsd, 0, NULL );
|
|
DD_Surface_Unlock( (LPDIRECTDRAWSURFACE) this_int, NULL );
|
|
}
|
|
else
|
|
{
|
|
InternalLock( this_lcl, &pbits, NULL, 0 );
|
|
InternalUnlock( this_lcl, NULL, 0 );
|
|
}
|
|
|
|
DPF( 3, "Moved surface %08lx to system memory", this_int );
|
|
return DD_OK;
|
|
|
|
} /* MoveToSystemMemory */
|
|
|
|
/*
|
|
* invalidateSurface
|
|
*
|
|
* invalidate one surface
|
|
*/
|
|
static void invalidateSurface( LPDDRAWI_DDRAWSURFACE_LCL this_lcl )
|
|
{
|
|
if( !SURFACE_LOST( this_lcl ) )
|
|
{
|
|
if( this_lcl->ddsCaps.dwCaps & DDSCAPS_VIDEOMEMORY )
|
|
{
|
|
DestroySurface( this_lcl );
|
|
}
|
|
if( !(this_lcl->lpGbl->dwGlobalFlags & DDRAWISURFGBL_SYSMEMREQUESTED) ||
|
|
(this_lcl->dwFlags & DDRAWISURF_PARTOFPRIMARYCHAIN) )
|
|
{
|
|
this_lcl->dwFlags |= DDRAWISURF_INVALID;
|
|
}
|
|
}
|
|
} /* 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_INT curr_int;
|
|
LPDDRAWI_DIRECTDRAW_LCL curr_lcl;
|
|
|
|
DPF(1, "******** invalidating all primary surfaces");
|
|
|
|
/*
|
|
* traverse the driver object list and invalidate all primaries for
|
|
* the specificed driver
|
|
*/
|
|
curr_int = lpDriverObjectList;
|
|
while( curr_int != NULL )
|
|
{
|
|
curr_lcl = curr_int->lpLcl;
|
|
if( curr_lcl->lpGbl == this )
|
|
{
|
|
if( curr_lcl->lpPrimary != NULL )
|
|
{
|
|
invalidateSurface( curr_lcl->lpPrimary->lpLcl );
|
|
invalidateAttachments( curr_lcl->lpPrimary->lpLcl );
|
|
}
|
|
}
|
|
curr_int = curr_int->lpLink;
|
|
}
|
|
|
|
} /* InvalidateAllPrimarySurfaces */
|
|
|
|
#undef DPF_MODNAME
|
|
#define DPF_MODNAME "InvalidateAllSurfaces"
|
|
|
|
/*
|
|
* InvalidateAllSurfaces
|
|
*/
|
|
void InvalidateAllSurfaces( LPDDRAWI_DIRECTDRAW_GBL this )
|
|
{
|
|
LPDDRAWI_DDRAWSURFACE_INT psurf_int;
|
|
|
|
DPF(1, "******** invalidating all surfaces");
|
|
|
|
#ifdef WINNT
|
|
if (!(this->dwFlags & DDRAWI_NOHARDWARE))
|
|
{
|
|
DdDisableAllSurfaces(this);
|
|
}
|
|
#endif
|
|
|
|
psurf_int = this->dsList;
|
|
|
|
while( psurf_int != NULL )
|
|
{
|
|
invalidateSurface( psurf_int->lpLcl );
|
|
psurf_int = psurf_int->lpLink;
|
|
}
|
|
|
|
} /* 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_INT curr_int;
|
|
LPDDRAWI_DIRECTDRAW_LCL curr_lcl;
|
|
LPDDRAWI_DDRAWSURFACE_INT psurf_int;
|
|
|
|
curr_int = lpDriverObjectList;
|
|
while( curr_int != NULL )
|
|
{
|
|
curr_lcl = curr_int->lpLcl;
|
|
if( curr_lcl->lpGbl == this )
|
|
{
|
|
psurf_int = curr_lcl->lpPrimary;
|
|
if( psurf_int && !SURFACE_LOST( psurf_int->lpLcl ) )
|
|
{
|
|
return psurf_int->lpLcl->lpGbl;
|
|
}
|
|
}
|
|
curr_int = curr_int->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_INT curr_int;
|
|
LPDDRAWI_DIRECTDRAW_LCL curr_lcl;
|
|
LPDDRAWI_DDRAWSURFACE_LCL psurf_lcl;
|
|
|
|
curr_int = lpDriverObjectList;
|
|
while( curr_int != NULL )
|
|
{
|
|
curr_lcl = curr_int->lpLcl;
|
|
if( curr_lcl->lpGbl == this )
|
|
{
|
|
psurf_lcl = curr_lcl->lpSharedZ;
|
|
if( psurf_lcl && ( psurf_lcl->dwModeCreatedIn == this->dwModeIndex ) )
|
|
{
|
|
return psurf_lcl->lpGbl;
|
|
}
|
|
}
|
|
curr_int = curr_int->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 = lpDriverObjectList;
|
|
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, LPDDSURFACEDESC 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_INT curr_int;
|
|
LPDDRAWI_DIRECTDRAW_LCL curr_lcl;
|
|
|
|
curr_int = lpDriverObjectList;
|
|
while( curr_int != NULL )
|
|
{
|
|
/*
|
|
* is this object pointing to the same driver data?
|
|
*/
|
|
curr_lcl = curr_int->lpLcl;
|
|
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_int = curr_int->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 = lpDriverObjectList;
|
|
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 = lpDriverObjectList;
|
|
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();
|
|
|
|
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;
|
|
}
|
|
|
|
// 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();
|
|
|
|
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;
|
|
}
|
|
|
|
// 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;
|
|
}
|
|
|
|
/*
|
|
* We define the page lock IOCTLs here so that we don't have to include dsvxd.h.
|
|
* These must match the corresponding entries in dsvxd.h
|
|
*/
|
|
#define DSVXD_IOCTL_MEMPAGELOCK 28
|
|
#define DSVXD_IOCTL_MEMPAGEUNLOCK 29
|
|
/*
|
|
* InternalPageLock
|
|
*
|
|
* Assumes driver lock is taken
|
|
*/
|
|
HRESULT InternalPageLock( LPDDRAWI_DDRAWSURFACE_LCL this_lcl,
|
|
LPDDRAWI_DIRECTDRAW_LCL pdrv_lcl )
|
|
{
|
|
BOOL rc;
|
|
DWORD cbReturned;
|
|
DWORD dwReturn;
|
|
struct _PLin
|
|
{
|
|
LPVOID pMem;
|
|
DWORD cbBuffer;
|
|
DWORD dwFlags;
|
|
} PLin;
|
|
|
|
|
|
DDASSERT( this_lcl->ddsCaps.dwCaps & DDSCAPS_SYSTEMMEMORY );
|
|
DDASSERT( !(this_lcl->ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE) );
|
|
|
|
PLin.pMem = (LPVOID)this_lcl->lpGbl->fpVidMem;
|
|
DDASSERT( PLin.pMem );
|
|
PLin.cbBuffer = this_lcl->lpSurfMore->dwBytesAllocated;
|
|
DDASSERT( PLin.cbBuffer );
|
|
PLin.dwFlags = 0;
|
|
|
|
DDASSERT( pdrv_lcl->hDSVxd );
|
|
rc = DeviceIoControl((HANDLE)(pdrv_lcl->hDSVxd),
|
|
DSVXD_IOCTL_MEMPAGELOCK,
|
|
&PLin,
|
|
sizeof( PLin ),
|
|
&dwReturn,
|
|
sizeof( dwReturn ),
|
|
&cbReturned,
|
|
NULL);
|
|
|
|
if( !rc )
|
|
return DDERR_CANTPAGELOCK;
|
|
DDASSERT( cbReturned == sizeof(dwReturn));
|
|
|
|
this_lcl->lpSurfMore->dwPageLockCount++;
|
|
DPF(3, "Page Locked %d bytes at %08lx (count=%d)", PLin.cbBuffer, PLin.pMem,
|
|
this_lcl->lpSurfMore->dwPageLockCount);
|
|
|
|
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;
|
|
} PLin;
|
|
|
|
|
|
if( this_lcl->lpSurfMore->dwPageLockCount <= 0 )
|
|
{
|
|
return DDERR_NOTPAGELOCKED;
|
|
}
|
|
DDASSERT( this_lcl->ddsCaps.dwCaps & DDSCAPS_SYSTEMMEMORY );
|
|
DDASSERT( !(this_lcl->ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE) );
|
|
|
|
PLin.pMem = (LPVOID)this_lcl->lpGbl->fpVidMem;
|
|
DDASSERT( PLin.pMem );
|
|
PLin.cbBuffer = this_lcl->lpSurfMore->dwBytesAllocated;
|
|
DDASSERT( PLin.cbBuffer );
|
|
PLin.dwFlags = 0;
|
|
|
|
DDASSERT( pdrv_lcl->hDSVxd );
|
|
rc = DeviceIoControl((HANDLE)(pdrv_lcl->hDSVxd),
|
|
DSVXD_IOCTL_MEMPAGEUNLOCK,
|
|
&PLin,
|
|
sizeof( PLin ),
|
|
&dwReturn,
|
|
sizeof( dwReturn ),
|
|
&cbReturned,
|
|
NULL);
|
|
|
|
if( !rc )
|
|
return DDERR_CANTPAGEUNLOCK;
|
|
DDASSERT( cbReturned == sizeof(dwReturn));
|
|
|
|
this_lcl->lpSurfMore->dwPageLockCount--;
|
|
DPF(3, "Page Unlocked %d bytes at %08lx (count=%d)", PLin.cbBuffer, PLin.pMem,
|
|
this_lcl->lpSurfMore->dwPageLockCount);
|
|
|
|
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();
|
|
|
|
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 */
|