2009-03-24 04:42:21 +00:00
/*
2009-03-23 03:43:11 +00:00
* COPYRIGHT : See COPYING in the top level directory
2011-12-14 04:07:06 +00:00
* PROJECT : ReactOS Win32k subsystem
2009-03-25 20:24:34 +00:00
* PURPOSE : Functions for saving and restoring dc states
2015-11-10 17:41:55 +00:00
* FILE : win32ss / gdi / ntgdi / dcstate . c
2009-03-23 03:43:11 +00:00
* PROGRAMER : Timo Kreuzer ( timo . kreuzer @ rectos . org )
*/
2010-04-26 13:58:46 +00:00
# include <win32k.h>
2009-03-23 03:43:11 +00:00
# define NDEBUG
# include <debug.h>
VOID
FASTCALL
2010-01-25 01:33:01 +00:00
DC_vCopyState ( PDC pdcSrc , PDC pdcDst , BOOL To )
2009-03-23 03:43:11 +00:00
{
2010-01-30 21:12:42 +00:00
DPRINT ( " DC_vCopyState(%p, %p) \n " , pdcSrc - > BaseObject . hHmgr , pdcDst - > BaseObject . hHmgr ) ;
2009-03-25 04:20:59 +00:00
/* Copy full DC attribute */
* pdcDst - > pdcattr = * pdcSrc - > pdcattr ;
2009-03-23 03:43:11 +00:00
2009-03-24 04:42:21 +00:00
/* Get/SetDCState() don't change hVisRgn field ("Undoc. Windows" p.559). */
2009-03-25 04:20:59 +00:00
/* The VisRectRegion field needs to be set to a valid state */
/* Mark some fields as dirty */
2011-12-30 02:52:43 +00:00
pdcDst - > pdcattr - > ulDirty_ | = ( DIRTY_FILL | DIRTY_LINE | DIRTY_TEXT | DIRTY_BACKGROUND | DIRTY_CHARSET | DC_ICM_NOT_CALIBRATED | DC_ICM_NOT_SET ) ; // Note: Use if, To is FALSE....
2009-03-25 04:20:59 +00:00
/* Copy DC level */
pdcDst - > dclevel . pColorSpace = pdcSrc - > dclevel . pColorSpace ;
pdcDst - > dclevel . laPath = pdcSrc - > dclevel . laPath ;
pdcDst - > dclevel . ca = pdcSrc - > dclevel . ca ;
pdcDst - > dclevel . mxWorldToDevice = pdcSrc - > dclevel . mxWorldToDevice ;
pdcDst - > dclevel . mxDeviceToWorld = pdcSrc - > dclevel . mxDeviceToWorld ;
pdcDst - > dclevel . mxWorldToPage = pdcSrc - > dclevel . mxWorldToPage ;
pdcDst - > dclevel . efM11PtoD = pdcSrc - > dclevel . efM11PtoD ;
pdcDst - > dclevel . efM22PtoD = pdcSrc - > dclevel . efM22PtoD ;
pdcDst - > dclevel . sizl = pdcSrc - > dclevel . sizl ;
2009-07-15 21:06:40 +00:00
pdcDst - > dclevel . hpal = pdcSrc - > dclevel . hpal ;
2009-03-25 04:20:59 +00:00
/* Handle references here correctly */
2009-03-26 00:56:46 +00:00
DC_vSelectFillBrush ( pdcDst , pdcSrc - > dclevel . pbrFill ) ;
DC_vSelectLineBrush ( pdcDst , pdcSrc - > dclevel . pbrLine ) ;
2009-07-15 21:06:40 +00:00
DC_vSelectPalette ( pdcDst , pdcSrc - > dclevel . ppal ) ;
2009-03-25 04:20:59 +00:00
2013-01-03 08:45:00 +00:00
/* Dereference the old font, reference the new one */
if ( pdcDst - > dclevel . plfnt ) LFONT_ShareUnlockFont ( pdcDst - > dclevel . plfnt ) ; /// @todo should aways be != NULL
GDIOBJ_vReferenceObjectByPointer ( & pdcSrc - > dclevel . plfnt - > BaseObject ) ;
2009-03-25 04:20:59 +00:00
pdcDst - > dclevel . plfnt = pdcSrc - > dclevel . plfnt ;
2010-01-25 01:33:01 +00:00
/* Get/SetDCState() don't change hVisRgn field ("Undoc. Windows" p.559). */
2014-07-23 16:05:47 +00:00
if ( ! To )
2010-01-25 01:33:01 +00:00
{
2014-07-23 16:05:47 +00:00
IntGdiExtSelectClipRgn ( pdcDst , pdcSrc - > dclevel . prgnClip , RGN_COPY ) ;
if ( pdcDst - > dclevel . prgnMeta )
2010-01-25 01:33:01 +00:00
{
2014-07-23 16:05:47 +00:00
REGION_Delete ( pdcDst - > dclevel . prgnMeta ) ;
pdcDst - > dclevel . prgnMeta = NULL ;
2010-01-25 01:33:01 +00:00
}
2019-05-09 17:33:21 +00:00
/* The only way to reset the Meta Region to its original state is to return to a previously saved version of the DC with SaveDC. */
2014-07-23 16:05:47 +00:00
if ( pdcSrc - > dclevel . prgnMeta )
{
pdcDst - > dclevel . prgnMeta = IntSysCreateRectpRgn ( 0 , 0 , 0 , 0 ) ;
IntGdiCombineRgn ( pdcDst - > dclevel . prgnMeta , pdcSrc - > dclevel . prgnMeta , NULL , RGN_COPY ) ;
}
pdcDst - > fs | = DC_FLAG_DIRTY_RAO ;
2010-01-25 01:33:01 +00:00
}
2009-03-23 03:43:11 +00:00
}
2014-07-23 16:05:47 +00:00
BOOL
FASTCALL
2009-03-25 04:20:59 +00:00
IntGdiCleanDC ( HDC hDC )
{
PDC dc ;
if ( ! hDC ) return FALSE ;
dc = DC_LockDc ( hDC ) ;
if ( ! dc ) return FALSE ;
// Clean the DC
2012-07-12 17:00:39 +00:00
if ( defaultDCstate )
{
DC_vCopyState ( defaultDCstate , dc , FALSE ) ;
/* Update the brushes now, because they reference some objects (the DC palette)
* Which belong to the current process , and this DC might be used for another process
* after being cleaned up ( for GetDC ( 0 ) for instance ) */
DC_vUpdateFillBrush ( dc ) ;
DC_vUpdateBackgroundBrush ( dc ) ;
DC_vUpdateLineBrush ( dc ) ;
DC_vUpdateTextBrush ( dc ) ;
}
2009-03-23 03:43:11 +00:00
2016-09-08 22:37:41 +00:00
// Remove Path and reset flags.
if ( dc - > dclevel . hPath )
{
DPRINT ( " Clean DC Remove Path \n " ) ;
if ( ! PATH_Delete ( dc - > dclevel . hPath ) )
{
DPRINT1 ( " Failed to remove Path \n " ) ;
}
dc - > dclevel . hPath = 0 ;
dc - > dclevel . flPath = 0 ;
}
2014-07-23 16:05:47 +00:00
/* DC_vCopyState frees the Clip rgn and the Meta rgn. Take care of the other ones
* There is no need to clear prgnVis , as UserGetDC updates it immediately . */
if ( dc - > prgnRao )
REGION_Delete ( dc - > prgnRao ) ;
if ( dc - > prgnAPI )
REGION_Delete ( dc - > prgnAPI ) ;
dc - > prgnRao = dc - > prgnAPI = NULL ;
dc - > fs | = DC_FLAG_DIRTY_RAO ;
2009-03-25 04:20:59 +00:00
DC_UnlockDc ( dc ) ;
2009-03-23 03:43:11 +00:00
2009-03-25 04:20:59 +00:00
return TRUE ;
2009-03-23 03:43:11 +00:00
}
2015-03-10 00:11:29 +00:00
__kernel_entry
2009-03-23 03:43:11 +00:00
BOOL
APIENTRY
NtGdiResetDC (
2015-03-10 00:11:29 +00:00
_In_ HDC hdc ,
_In_ LPDEVMODEW pdm ,
_Out_ PBOOL pbBanding ,
_In_opt_ DRIVER_INFO_2W * pDriverInfo2 ,
_At_ ( ( PUMDHPDEV * ) ppUMdhpdev , _Out_ ) PVOID ppUMdhpdev )
2009-03-23 03:43:11 +00:00
{
2015-03-10 00:11:29 +00:00
/* According to a comment in Windows SDK the size of the buffer for
pdm is ( pdm - > dmSize + pdm - > dmDriverExtra ) */
2009-03-24 04:42:21 +00:00
UNIMPLEMENTED ;
2015-03-10 00:11:29 +00:00
return FALSE ;
2009-03-23 03:43:11 +00:00
}
2009-03-25 04:20:59 +00:00
2010-01-30 21:12:42 +00:00
VOID
NTAPI
DC_vRestoreDC (
IN PDC pdc ,
2009-03-25 04:20:59 +00:00
INT iSaveLevel )
2009-03-23 03:43:11 +00:00
{
2010-01-30 21:12:42 +00:00
HDC hdcSave ;
PDC pdcSave ;
2009-03-23 03:43:11 +00:00
2015-10-31 19:37:36 +00:00
NT_ASSERT ( iSaveLevel > 0 ) ;
2010-01-30 21:12:42 +00:00
DPRINT ( " DC_vRestoreDC(%p, %ld) \n " , pdc - > BaseObject . hHmgr , iSaveLevel ) ;
2009-03-23 03:43:11 +00:00
2009-03-25 04:20:59 +00:00
/* Loop the save levels */
while ( pdc - > dclevel . lSaveDepth > iSaveLevel )
2009-03-24 04:42:21 +00:00
{
2009-03-25 04:20:59 +00:00
hdcSave = pdc - > dclevel . hdcSave ;
2010-01-30 21:12:42 +00:00
DPRINT ( " RestoreDC = %p \n " , hdcSave ) ;
2009-03-23 03:43:11 +00:00
2009-03-25 04:20:59 +00:00
/* Set us as the owner */
[WIN32K]
Rewrite of the GDI handle manager
- The old handle manager used a completely retarded spinlock in combination with KeDelayExecutionThread() for both exclusive
and shared locks. This is probably the most uneffective algorithm possible. It was also duplicating code everywhere and it was a overall mess It
is now replaced with a lock-free reference counter for shared locks and a pushlock for exclusive locks. -> Better performance and scalability.
- Allocate user mode object attributes from the new gdi pool. This way, we don't need any caching, since the pool serves as a cache. Its also
much faster and uses much less memory.
- Allow object allocations of different size, instead of fixed size from a table. This way a single allocation can take care of actual needs.
- Allow allcoating objects without a handle and insert them into the handle table later
- Properly synchronize the process GDIHandleCount. Now gdiview and taskmanager show the correct number of gdi handles.
- Implement a new event tracking system, that is capable of tracking all reverences and locks of objects and pool allocations to help track
possible leaks
- Make sure that all objects of a process are deleted in cleanup
- Make sure all usermode memory allocations are freed, when cleaning up the process pool.
- Make sure that each object type is using the correct type of lock (either shared or exclusive, not a mixture)
- Fix some object / reference leaks
- Lots of inferface improvements
- Use global variables for certain things instead of members in the mapped gdi handle table
- Make IntSysCreateRectpRgn create a region without a handle
- Fix detection od source and mask use in GreStretchBltMask
- Use GDIOBJ_bLockMultipleObjects in NtGdiCombineRegion to avoid possible deadlocks
- Fix NtGdiAbortPath to reset DCPATH_ACTIVE flag in the dc and only bail out on error, instead of always
- Replace DC_AllocateDcAttr and DC_AllocDcAttr with DC_bAllocDcAttr using the new user mode pool
- Remove DCU_SyncDcAttrtoUser and DCU_SynchDcAttrtoUser. Those functions were unused and didn't do anything useful anyway,
- Replace IntGdiSetDCOwnerEx and DC_SetOwnership with GreSetDCOwner, remove unused NoSetBrush parameter
- Replace GDIOBJ_bValidateHandle and IsObjectDead with GreIsHandleValid
- Chage GDIOBJ_bLockMultipleObjects: pass object type, return a BOOL, whether all objects could be locked, cleanup on failure
svn path=/trunk/; revision=51470
2011-04-28 08:26:46 +00:00
if ( ! GreSetObjectOwner ( hdcSave , GDI_OBJ_HMGR_POWNED ) )
2009-03-24 04:42:21 +00:00
{
2009-03-25 04:20:59 +00:00
/* Could not get ownership. That's bad! */
2010-01-30 21:12:42 +00:00
DPRINT1 ( " Could not get ownership of saved DC (%p) for hdc %p! \n " ,
hdcSave , pdc - > BaseObject . hHmgr ) ;
2015-10-31 19:37:36 +00:00
NT_ASSERT ( FALSE ) ;
2010-01-30 21:12:42 +00:00
return ; // FALSE;
2009-03-24 04:42:21 +00:00
}
2009-03-25 04:20:59 +00:00
/* Lock the saved dc */
pdcSave = DC_LockDc ( hdcSave ) ;
if ( ! pdcSave )
2009-03-24 04:42:21 +00:00
{
2009-03-25 04:20:59 +00:00
/* WTF? Internal error! */
DPRINT1 ( " Could not lock the saved DC (%p) for dc %p! \n " ,
2010-01-30 21:12:42 +00:00
hdcSave , pdc - > BaseObject . hHmgr ) ;
2015-10-31 19:37:36 +00:00
NT_ASSERT ( FALSE ) ;
2010-01-30 21:12:42 +00:00
return ; // FALSE;
2009-03-25 04:20:59 +00:00
}
2009-03-24 04:42:21 +00:00
2009-03-25 04:20:59 +00:00
/* Remove the saved dc from the queue */
pdc - > dclevel . hdcSave = pdcSave - > dclevel . hdcSave ;
/* Decrement save level */
pdc - > dclevel . lSaveDepth - - ;
/* Is this the state we want? */
if ( pdc - > dclevel . lSaveDepth = = iSaveLevel )
{
/* Copy the state back */
2010-01-25 01:33:01 +00:00
DC_vCopyState ( pdcSave , pdc , FALSE ) ;
2009-03-24 04:42:21 +00:00
2010-04-01 22:36:40 +00:00
/* Only memory DC's change their surface */
2010-06-10 00:40:09 +00:00
if ( pdc - > dctype = = DCTYPE_MEMORY )
2010-04-01 22:36:40 +00:00
DC_vSelectSurface ( pdc , pdcSave - > dclevel . pSurface ) ;
2016-09-08 22:37:41 +00:00
if ( pdcSave - > dclevel . hPath )
2009-03-24 04:42:21 +00:00
{
2016-09-08 22:37:41 +00:00
PATH_RestorePath ( pdc , pdcSave ) ;
2009-03-24 04:42:21 +00:00
}
}
2009-03-25 04:20:59 +00:00
2010-01-30 21:12:42 +00:00
/* Prevent save dc from being restored */
pdcSave - > dclevel . lSaveDepth = 1 ;
2010-03-28 22:27:57 +00:00
/* Unlock it */
DC_UnlockDc ( pdcSave ) ;
2009-03-25 04:20:59 +00:00
/* Delete the saved dc */
2009-12-29 21:07:04 +00:00
GreDeleteObject ( hdcSave ) ;
2009-03-24 04:42:21 +00:00
}
2009-03-25 04:20:59 +00:00
2010-01-30 21:12:42 +00:00
DPRINT ( " Leave DC_vRestoreDC() \n " ) ;
}
BOOL
APIENTRY
NtGdiRestoreDC (
HDC hdc ,
INT iSaveLevel )
{
PDC pdc ;
DPRINT ( " NtGdiRestoreDC(%p, %d) \n " , hdc , iSaveLevel ) ;
/* Lock the original DC */
pdc = DC_LockDc ( hdc ) ;
if ( ! pdc )
{
2010-12-25 11:01:14 +00:00
EngSetLastError ( ERROR_INVALID_HANDLE ) ;
2010-01-30 21:12:42 +00:00
return FALSE ;
}
ASSERT ( pdc - > dclevel . lSaveDepth > 0 ) ;
/* Negative values are relative to the stack top */
if ( iSaveLevel < 0 )
iSaveLevel = pdc - > dclevel . lSaveDepth + iSaveLevel ;
/* Check if we have a valid instance */
if ( iSaveLevel < = 0 | | iSaveLevel > = pdc - > dclevel . lSaveDepth )
{
DPRINT ( " Illegal save level, requested: %ld, current: %ld \n " ,
iSaveLevel , pdc - > dclevel . lSaveDepth ) ;
DC_UnlockDc ( pdc ) ;
2010-12-25 11:01:14 +00:00
EngSetLastError ( ERROR_INVALID_PARAMETER ) ;
2010-01-30 21:12:42 +00:00
return FALSE ;
}
/* Call the internal function */
DC_vRestoreDC ( pdc , iSaveLevel ) ;
2009-03-25 04:20:59 +00:00
DC_UnlockDc ( pdc ) ;
2010-01-30 21:12:42 +00:00
DPRINT ( " Leave NtGdiRestoreDC \n " ) ;
2009-03-25 04:20:59 +00:00
return TRUE ;
2009-03-23 03:43:11 +00:00
}
2009-03-25 04:20:59 +00:00
INT
APIENTRY
2009-03-24 04:42:21 +00:00
NtGdiSaveDC (
HDC hDC )
2009-03-23 03:43:11 +00:00
{
2009-03-25 04:20:59 +00:00
HDC hdcSave ;
PDC pdc , pdcSave ;
INT lSaveDepth ;
2009-03-23 03:43:11 +00:00
2010-01-30 21:12:42 +00:00
DPRINT ( " NtGdiSaveDC(%p) \n " , hDC ) ;
2009-03-23 03:43:11 +00:00
2009-03-25 04:20:59 +00:00
/* Lock the original dc */
pdc = DC_LockDc ( hDC ) ;
if ( pdc = = NULL )
2009-03-24 04:42:21 +00:00
{
2009-03-25 04:20:59 +00:00
DPRINT ( " Could not lock DC \n " ) ;
2010-12-25 11:01:14 +00:00
EngSetLastError ( ERROR_INVALID_HANDLE ) ;
2009-03-24 04:42:21 +00:00
return 0 ;
}
2009-03-25 04:20:59 +00:00
/* Allocate a new dc */
2014-12-29 13:12:05 +00:00
pdcSave = DC_AllocDcWithHandle ( GDILoObjType_LO_DC_TYPE ) ;
2009-03-25 04:20:59 +00:00
if ( pdcSave = = NULL )
2009-03-24 04:42:21 +00:00
{
2009-03-25 04:20:59 +00:00
DPRINT ( " Could not allocate a new DC \n " ) ;
DC_UnlockDc ( pdc ) ;
2009-03-24 04:42:21 +00:00
return 0 ;
}
2009-03-25 04:20:59 +00:00
hdcSave = pdcSave - > BaseObject . hHmgr ;
2009-03-23 03:43:11 +00:00
2019-11-24 20:22:21 +00:00
PDEVOBJ_vReference ( pdc - > ppdev ) ;
2010-01-30 21:12:42 +00:00
DC_vInitDc ( pdcSave , DCTYPE_MEMORY , pdc - > ppdev ) ;
2010-04-01 02:52:00 +00:00
/* Handle references here correctly */
2011-12-14 04:07:06 +00:00
//pdcSrc->dclevel.pSurface = NULL;
//pdcSrc->dclevel.pbrFill = NULL;
//pdcSrc->dclevel.pbrLine = NULL;
//pdcSrc->dclevel.ppal = NULL;
2010-01-25 01:33:01 +00:00
2009-07-15 21:06:40 +00:00
/* Make it a kernel handle
2011-12-14 04:07:06 +00:00
( FIXME : Windows handles this differently , see Wiki ) */
2012-05-01 10:33:36 +00:00
GDIOBJ_vSetObjectOwner ( & pdcSave - > BaseObject , GDI_OBJ_HMGR_PUBLIC ) ;
2009-03-23 03:43:11 +00:00
2009-03-25 04:20:59 +00:00
/* Copy the current state */
2014-07-23 16:05:47 +00:00
DC_vCopyState ( pdc , pdcSave , FALSE ) ;
2009-03-23 03:43:11 +00:00
2010-04-01 22:36:40 +00:00
/* Only memory DC's change their surface */
if ( pdc - > dctype = = DCTYPE_MEMORY )
DC_vSelectSurface ( pdcSave , pdc - > dclevel . pSurface ) ;
2012-05-01 10:33:36 +00:00
/* Copy path */
2016-09-08 22:37:41 +00:00
if ( pdc - > dclevel . hPath )
{
PATH_SavePath ( pdcSave , pdc ) ;
}
2009-03-25 04:20:59 +00:00
pdcSave - > dclevel . flPath = pdc - > dclevel . flPath | DCPATH_SAVESTATE ;
2009-03-23 03:43:11 +00:00
2009-03-25 04:20:59 +00:00
/* Set new dc as save dc */
2015-10-31 19:37:36 +00:00
pdcSave - > dclevel . hdcSave = pdc - > dclevel . hdcSave ;
2009-03-25 04:20:59 +00:00
pdc - > dclevel . hdcSave = hdcSave ;
/* Increase save depth, return old value */
lSaveDepth = pdc - > dclevel . lSaveDepth + + ;
/* Cleanup and return */
DC_UnlockDc ( pdcSave ) ;
DC_UnlockDc ( pdc ) ;
2010-01-30 21:12:42 +00:00
DPRINT ( " Leave NtGdiSaveDC: %ld, hdcSave = %p \n " , lSaveDepth , hdcSave ) ;
2009-03-25 04:20:59 +00:00
return lSaveDepth ;
2009-03-23 03:43:11 +00:00
}
2011-12-14 04:07:06 +00:00
/* EOF */