2007-11-02 04:23:31 +00:00
|
|
|
|
2010-04-26 13:58:46 +00:00
|
|
|
#include <win32k.h>
|
2007-11-02 04:23:31 +00:00
|
|
|
|
|
|
|
#define NDEBUG
|
|
|
|
#include <debug.h>
|
|
|
|
|
2019-03-02 17:30:21 +00:00
|
|
|
BOOL FASTCALL IntPatBlt( PDC,INT,INT,INT,INT,DWORD,PEBRUSHOBJ);
|
2019-03-09 04:21:41 +00:00
|
|
|
BOOL APIENTRY IntExtTextOutW(IN PDC,IN INT,IN INT,IN UINT,IN OPTIONAL PRECTL,IN LPCWSTR,IN INT,IN OPTIONAL LPINT,IN DWORD);
|
|
|
|
|
2007-11-02 04:23:31 +00:00
|
|
|
|
|
|
|
//
|
|
|
|
// Gdi Batch Flush support functions.
|
|
|
|
//
|
|
|
|
|
2007-12-04 07:51:03 +00:00
|
|
|
//
|
|
|
|
// DoDeviceSync
|
|
|
|
//
|
|
|
|
// based on IntEngEnter from eng/engmisc.c
|
|
|
|
//
|
|
|
|
VOID
|
|
|
|
FASTCALL
|
|
|
|
DoDeviceSync( SURFOBJ *Surface, PRECTL Rect, FLONG fl)
|
|
|
|
{
|
2009-03-20 18:02:55 +00:00
|
|
|
PPDEVOBJ Device = (PDEVOBJ*)Surface->hdev;
|
[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
|
|
|
// No punting and "Handle to a surface, provided that the surface is device-managed.
|
2007-12-04 07:51:03 +00:00
|
|
|
// Otherwise, dhsurf is zero".
|
|
|
|
if (!(Device->flFlags & PDEV_DRIVER_PUNTED_CALL) && (Surface->dhsurf))
|
|
|
|
{
|
|
|
|
if (Device->DriverFunctions.SynchronizeSurface)
|
2009-07-31 18:21:24 +00:00
|
|
|
{
|
|
|
|
Device->DriverFunctions.SynchronizeSurface(Surface, Rect, fl);
|
|
|
|
}
|
2007-12-04 07:51:03 +00:00
|
|
|
else
|
|
|
|
{
|
|
|
|
if (Device->DriverFunctions.Synchronize)
|
2009-07-31 18:21:24 +00:00
|
|
|
{
|
|
|
|
Device->DriverFunctions.Synchronize(Surface->dhpdev, Rect);
|
|
|
|
}
|
2007-12-04 07:51:03 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
VOID
|
|
|
|
FASTCALL
|
2019-03-09 04:21:41 +00:00
|
|
|
SynchronizeDriver(FLONG Flags)
|
2007-12-04 07:51:03 +00:00
|
|
|
{
|
[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
|
|
|
SURFOBJ *SurfObj;
|
2011-09-11 16:56:56 +00:00
|
|
|
//PPDEVOBJ Device;
|
[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
|
|
|
|
2007-12-04 07:51:03 +00:00
|
|
|
if (Flags & GCAPS2_SYNCFLUSH)
|
|
|
|
Flags = DSS_FLUSH_EVENT;
|
|
|
|
if (Flags & GCAPS2_SYNCTIMER)
|
|
|
|
Flags = DSS_TIMER_EVENT;
|
|
|
|
|
2011-09-11 16:56:56 +00:00
|
|
|
//Device = IntEnumHDev();
|
2010-01-30 21:12:42 +00:00
|
|
|
// UNIMPLEMENTED;
|
|
|
|
//ASSERT(FALSE);
|
|
|
|
SurfObj = 0;// EngLockSurface( Device->pSurface );
|
2007-12-04 07:51:03 +00:00
|
|
|
if(!SurfObj) return;
|
|
|
|
DoDeviceSync( SurfObj, NULL, Flags);
|
|
|
|
EngUnlockSurface(SurfObj);
|
|
|
|
return;
|
|
|
|
}
|
2007-11-02 04:23:31 +00:00
|
|
|
|
|
|
|
//
|
|
|
|
// Process the batch.
|
|
|
|
//
|
|
|
|
ULONG
|
|
|
|
FASTCALL
|
2008-05-28 22:25:08 +00:00
|
|
|
GdiFlushUserBatch(PDC dc, PGDIBATCHHDR pHdr)
|
2007-11-02 04:23:31 +00:00
|
|
|
{
|
2010-03-24 23:35:23 +00:00
|
|
|
ULONG Cmd = 0, Size = 0;
|
2009-03-20 04:51:26 +00:00
|
|
|
PDC_ATTR pdcattr = NULL;
|
2008-11-03 06:52:42 +00:00
|
|
|
|
2008-05-28 22:25:08 +00:00
|
|
|
if (dc)
|
2007-11-18 13:51:34 +00:00
|
|
|
{
|
2010-03-24 23:35:23 +00:00
|
|
|
pdcattr = dc->pdcattr;
|
2007-11-18 13:51:34 +00:00
|
|
|
}
|
2010-03-24 23:35:23 +00:00
|
|
|
|
|
|
|
_SEH2_TRY
|
|
|
|
{
|
|
|
|
Cmd = pHdr->Cmd;
|
|
|
|
Size = pHdr->Size; // Return the full size of the structure.
|
|
|
|
}
|
|
|
|
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
|
|
|
|
{
|
|
|
|
DPRINT1("WARNING! GdiBatch Fault!\n");
|
2013-01-04 11:02:43 +00:00
|
|
|
_SEH2_YIELD(return 0;)
|
2010-03-24 23:35:23 +00:00
|
|
|
}
|
2013-01-04 11:02:43 +00:00
|
|
|
_SEH2_END;
|
2010-03-24 23:35:23 +00:00
|
|
|
|
|
|
|
switch(Cmd)
|
2007-11-02 04:23:31 +00:00
|
|
|
{
|
2013-01-04 11:02:43 +00:00
|
|
|
case GdiBCPatBlt:
|
2019-03-02 17:30:21 +00:00
|
|
|
{
|
|
|
|
PGDIBSPATBLT pgDPB;
|
|
|
|
DWORD dwRop, flags;
|
|
|
|
HBRUSH hOrgBrush;
|
|
|
|
COLORREF crColor, crBkColor, crBrushClr;
|
|
|
|
ULONG ulForegroundClr, ulBackgroundClr, ulBrushClr;
|
|
|
|
if (!dc) break;
|
|
|
|
pgDPB = (PGDIBSPATBLT) pHdr;
|
|
|
|
/* Convert the ROP3 to a ROP4 */
|
|
|
|
dwRop = pgDPB->dwRop;
|
|
|
|
dwRop = MAKEROP4(dwRop & 0xFF0000, dwRop);
|
|
|
|
/* Check if the rop uses a source */
|
|
|
|
if (WIN32_ROP4_USES_SOURCE(dwRop))
|
|
|
|
{
|
|
|
|
/* This is not possible */
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
/* Check if the DC has no surface (empty mem or info DC) */
|
|
|
|
if (dc->dclevel.pSurface == NULL)
|
|
|
|
{
|
|
|
|
/* Nothing to do */
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
// Save current attributes and flags
|
|
|
|
crColor = dc->pdcattr->crForegroundClr;
|
|
|
|
crBkColor = dc->pdcattr->ulBackgroundClr;
|
|
|
|
crBrushClr = dc->pdcattr->crBrushClr;
|
|
|
|
ulForegroundClr = dc->pdcattr->ulForegroundClr;
|
|
|
|
ulBackgroundClr = dc->pdcattr->ulBackgroundClr;
|
|
|
|
ulBrushClr = dc->pdcattr->ulBrushClr;
|
|
|
|
hOrgBrush = dc->pdcattr->hbrush;
|
|
|
|
flags = dc->pdcattr->ulDirty_ & (DIRTY_BACKGROUND | DIRTY_TEXT | DIRTY_FILL | DC_BRUSH_DIRTY);
|
|
|
|
// Set the attribute snapshot
|
|
|
|
dc->pdcattr->hbrush = pgDPB->hbrush;
|
|
|
|
dc->pdcattr->crForegroundClr = pgDPB->crForegroundClr;
|
|
|
|
dc->pdcattr->crBackgroundClr = pgDPB->crBackgroundClr;
|
|
|
|
dc->pdcattr->crBrushClr = pgDPB->crBrushClr;
|
|
|
|
dc->pdcattr->ulForegroundClr = pgDPB->ulForegroundClr;
|
|
|
|
dc->pdcattr->ulBackgroundClr = pgDPB->ulBackgroundClr;
|
|
|
|
dc->pdcattr->ulBrushClr = pgDPB->ulBrushClr;
|
2019-03-09 04:21:41 +00:00
|
|
|
// Process dirty attributes if any.
|
2019-03-02 17:30:21 +00:00
|
|
|
if (dc->pdcattr->ulDirty_ & (DIRTY_FILL | DC_BRUSH_DIRTY))
|
|
|
|
DC_vUpdateFillBrush(dc);
|
|
|
|
if (dc->pdcattr->ulDirty_ & DIRTY_TEXT)
|
|
|
|
DC_vUpdateTextBrush(dc);
|
|
|
|
if (pdcattr->ulDirty_ & DIRTY_BACKGROUND)
|
|
|
|
DC_vUpdateBackgroundBrush(dc);
|
|
|
|
/* Call the internal function */
|
|
|
|
IntPatBlt(dc, pgDPB->nXLeft, pgDPB->nYLeft, pgDPB->nWidth, pgDPB->nHeight, dwRop, &dc->eboFill);
|
|
|
|
// Restore attributes and flags
|
|
|
|
dc->pdcattr->hbrush = hOrgBrush;
|
|
|
|
dc->pdcattr->crForegroundClr = crColor;
|
|
|
|
dc->pdcattr->crBackgroundClr = crBkColor;
|
|
|
|
dc->pdcattr->crBrushClr = crBrushClr;
|
|
|
|
dc->pdcattr->ulForegroundClr = ulForegroundClr;
|
|
|
|
dc->pdcattr->ulBackgroundClr = ulBackgroundClr;
|
|
|
|
dc->pdcattr->ulBrushClr = ulBrushClr;
|
|
|
|
dc->pdcattr->ulDirty_ |= flags;
|
2007-11-02 04:23:31 +00:00
|
|
|
break;
|
2019-03-02 17:30:21 +00:00
|
|
|
}
|
2013-01-04 11:02:43 +00:00
|
|
|
|
2007-11-02 04:23:31 +00:00
|
|
|
case GdiBCPolyPatBlt:
|
2019-03-02 17:30:21 +00:00
|
|
|
{
|
|
|
|
PGDIBSPPATBLT pgDPB;
|
|
|
|
EBRUSHOBJ eboFill;
|
|
|
|
PBRUSH pbrush;
|
|
|
|
PPATRECT pRects;
|
2019-03-09 04:21:41 +00:00
|
|
|
INT i;
|
2019-03-02 17:30:21 +00:00
|
|
|
DWORD dwRop, flags;
|
|
|
|
COLORREF crColor, crBkColor, crBrushClr;
|
|
|
|
ULONG ulForegroundClr, ulBackgroundClr, ulBrushClr;
|
|
|
|
if (!dc) break;
|
|
|
|
pgDPB = (PGDIBSPPATBLT) pHdr;
|
|
|
|
/* Convert the ROP3 to a ROP4 */
|
|
|
|
dwRop = pgDPB->rop4;
|
|
|
|
dwRop = MAKEROP4(dwRop & 0xFF0000, dwRop);
|
|
|
|
/* Check if the rop uses a source */
|
|
|
|
if (WIN32_ROP4_USES_SOURCE(dwRop))
|
|
|
|
{
|
|
|
|
/* This is not possible */
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
/* Check if the DC has no surface (empty mem or info DC) */
|
|
|
|
if (dc->dclevel.pSurface == NULL)
|
|
|
|
{
|
|
|
|
/* Nothing to do */
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
// Save current attributes and flags
|
|
|
|
crColor = dc->pdcattr->crForegroundClr;
|
|
|
|
crBkColor = dc->pdcattr->ulBackgroundClr;
|
|
|
|
crBrushClr = dc->pdcattr->crBrushClr;
|
|
|
|
ulForegroundClr = dc->pdcattr->ulForegroundClr;
|
|
|
|
ulBackgroundClr = dc->pdcattr->ulBackgroundClr;
|
|
|
|
ulBrushClr = dc->pdcattr->ulBrushClr;
|
|
|
|
flags = dc->pdcattr->ulDirty_ & (DIRTY_BACKGROUND | DIRTY_TEXT | DIRTY_FILL | DC_BRUSH_DIRTY);
|
|
|
|
// Set the attribute snapshot
|
|
|
|
dc->pdcattr->crForegroundClr = pgDPB->crForegroundClr;
|
|
|
|
dc->pdcattr->crBackgroundClr = pgDPB->crBackgroundClr;
|
|
|
|
dc->pdcattr->crBrushClr = pgDPB->crBrushClr;
|
|
|
|
dc->pdcattr->ulForegroundClr = pgDPB->ulForegroundClr;
|
|
|
|
dc->pdcattr->ulBackgroundClr = pgDPB->ulBackgroundClr;
|
|
|
|
dc->pdcattr->ulBrushClr = pgDPB->ulBrushClr;
|
|
|
|
// Process dirty attributes if any
|
|
|
|
if (dc->pdcattr->ulDirty_ & DIRTY_TEXT)
|
|
|
|
DC_vUpdateTextBrush(dc);
|
|
|
|
if (pdcattr->ulDirty_ & DIRTY_BACKGROUND)
|
|
|
|
DC_vUpdateBackgroundBrush(dc);
|
|
|
|
|
|
|
|
DPRINT1("GdiBCPolyPatBlt Testing\n");
|
2019-03-09 04:21:41 +00:00
|
|
|
pRects = &pgDPB->pRect[0];
|
2013-01-04 11:02:43 +00:00
|
|
|
|
2019-03-09 04:21:41 +00:00
|
|
|
for (i = 0; i < pgDPB->Count; i++)
|
2019-03-02 17:30:21 +00:00
|
|
|
{
|
|
|
|
pbrush = BRUSH_ShareLockBrush(pRects->hBrush);
|
|
|
|
|
|
|
|
/* Check if we could lock the brush */
|
|
|
|
if (pbrush != NULL)
|
|
|
|
{
|
|
|
|
/* Initialize a brush object */
|
|
|
|
EBRUSHOBJ_vInitFromDC(&eboFill, pbrush, dc);
|
|
|
|
|
|
|
|
IntPatBlt(
|
|
|
|
dc,
|
|
|
|
pRects->r.left,
|
|
|
|
pRects->r.top,
|
|
|
|
pRects->r.right,
|
|
|
|
pRects->r.bottom,
|
|
|
|
dwRop,
|
|
|
|
&eboFill);
|
|
|
|
|
|
|
|
/* Cleanup the brush object and unlock the brush */
|
|
|
|
EBRUSHOBJ_vCleanup(&eboFill);
|
|
|
|
BRUSH_ShareUnlockBrush(pbrush);
|
|
|
|
}
|
|
|
|
pRects++;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Restore attributes and flags
|
|
|
|
dc->pdcattr->crForegroundClr = crColor;
|
|
|
|
dc->pdcattr->crBackgroundClr = crBkColor;
|
|
|
|
dc->pdcattr->crBrushClr = crBrushClr;
|
|
|
|
dc->pdcattr->ulForegroundClr = ulForegroundClr;
|
|
|
|
dc->pdcattr->ulBackgroundClr = ulBackgroundClr;
|
|
|
|
dc->pdcattr->ulBrushClr = ulBrushClr;
|
|
|
|
dc->pdcattr->ulDirty_ |= flags;
|
|
|
|
break;
|
2019-03-09 04:21:41 +00:00
|
|
|
}
|
|
|
|
|
2007-11-02 04:23:31 +00:00
|
|
|
case GdiBCTextOut:
|
2019-03-09 04:21:41 +00:00
|
|
|
{
|
|
|
|
PGDIBSTEXTOUT pgO;
|
|
|
|
COLORREF crColor = -1, crBkColor;
|
|
|
|
ULONG ulForegroundClr, ulBackgroundClr;
|
2019-05-02 15:11:11 +00:00
|
|
|
DWORD flags = 0, flXform = 0, saveflags, saveflXform = 0;
|
2019-03-09 04:21:41 +00:00
|
|
|
FLONG flTextAlign = -1;
|
|
|
|
HANDLE hlfntNew;
|
|
|
|
PRECTL lprc;
|
|
|
|
USHORT jBkMode;
|
|
|
|
LONG lBkMode;
|
2019-05-02 15:11:11 +00:00
|
|
|
POINTL ptlViewportOrg;
|
2019-03-09 04:21:41 +00:00
|
|
|
if (!dc) break;
|
|
|
|
pgO = (PGDIBSTEXTOUT) pHdr;
|
|
|
|
|
|
|
|
// Save current attributes, flags and Set the attribute snapshots
|
|
|
|
saveflags = dc->pdcattr->ulDirty_ & (DIRTY_BACKGROUND|DIRTY_LINE|DIRTY_TEXT|DIRTY_FILL|DC_BRUSH_DIRTY|DIRTY_CHARSET);
|
|
|
|
|
|
|
|
// In this instance check for differences and set the appropriate dirty flags.
|
|
|
|
if ( dc->pdcattr->crForegroundClr != pgO->crForegroundClr)
|
|
|
|
{
|
|
|
|
crColor = dc->pdcattr->crForegroundClr;
|
|
|
|
dc->pdcattr->crForegroundClr = pgO->crForegroundClr;
|
|
|
|
ulForegroundClr = dc->pdcattr->ulForegroundClr;
|
|
|
|
dc->pdcattr->ulForegroundClr = pgO->ulForegroundClr;
|
|
|
|
flags |= (DIRTY_FILL|DIRTY_LINE|DIRTY_TEXT);
|
|
|
|
}
|
|
|
|
if (dc->pdcattr->crBackgroundClr != pgO->crBackgroundClr)
|
|
|
|
{
|
|
|
|
crBkColor = dc->pdcattr->ulBackgroundClr;
|
|
|
|
dc->pdcattr->crBackgroundClr = pgO->crBackgroundClr;
|
|
|
|
ulBackgroundClr = dc->pdcattr->ulBackgroundClr;
|
|
|
|
dc->pdcattr->ulBackgroundClr = pgO->ulBackgroundClr;
|
|
|
|
flags |= (DIRTY_FILL|DIRTY_LINE|DIRTY_TEXT|DIRTY_BACKGROUND);
|
|
|
|
}
|
|
|
|
if (dc->pdcattr->flTextAlign != pgO->flTextAlign)
|
|
|
|
{
|
|
|
|
flTextAlign = dc->pdcattr->flTextAlign;
|
|
|
|
dc->pdcattr->flTextAlign = pgO->flTextAlign;
|
|
|
|
}
|
|
|
|
if (dc->pdcattr->hlfntNew != pgO->hlfntNew)
|
|
|
|
{
|
|
|
|
hlfntNew = dc->pdcattr->hlfntNew;
|
|
|
|
dc->pdcattr->hlfntNew = pgO->hlfntNew;
|
|
|
|
dc->pdcattr->ulDirty_ &= ~SLOW_WIDTHS;
|
|
|
|
flags |= DIRTY_CHARSET;
|
|
|
|
}
|
|
|
|
|
2019-05-02 15:11:11 +00:00
|
|
|
if ( dc->pdcattr->ptlViewportOrg.x != pgO->ptlViewportOrg.x ||
|
|
|
|
dc->pdcattr->ptlViewportOrg.y != pgO->ptlViewportOrg.y )
|
|
|
|
{
|
|
|
|
saveflXform = dc->pdcattr->flXform & (PAGE_XLATE_CHANGED|WORLD_XFORM_CHANGED|DEVICE_TO_WORLD_INVALID);
|
|
|
|
ptlViewportOrg = dc->pdcattr->ptlViewportOrg;
|
|
|
|
dc->pdcattr->ptlViewportOrg = pgO->ptlViewportOrg;
|
|
|
|
flXform = (PAGE_XLATE_CHANGED|WORLD_XFORM_CHANGED|DEVICE_TO_WORLD_INVALID);
|
|
|
|
}
|
|
|
|
|
2019-05-02 15:16:50 +00:00
|
|
|
dc->pdcattr->flXform |= flXform;
|
2019-03-09 04:21:41 +00:00
|
|
|
dc->pdcattr->ulDirty_ |= flags;
|
|
|
|
|
|
|
|
jBkMode = dc->pdcattr->jBkMode;
|
|
|
|
dc->pdcattr->jBkMode = pgO->lBkMode;
|
|
|
|
lBkMode = dc->pdcattr->lBkMode;
|
|
|
|
dc->pdcattr->lBkMode = pgO->lBkMode;
|
|
|
|
|
|
|
|
lprc = (pgO->Options & GDIBS_NORECT) ? NULL : &pgO->Rect;
|
|
|
|
pgO->Options &= ~GDIBS_NORECT;
|
|
|
|
|
|
|
|
IntExtTextOutW( dc,
|
|
|
|
pgO->x,
|
|
|
|
pgO->y,
|
|
|
|
pgO->Options,
|
|
|
|
lprc,
|
|
|
|
(LPCWSTR)&pgO->String[pgO->Size/sizeof(WCHAR)],
|
|
|
|
pgO->cbCount,
|
|
|
|
pgO->Size ? (LPINT)&pgO->Buffer : NULL,
|
|
|
|
pgO->iCS_CP );
|
|
|
|
|
|
|
|
// Restore attributes and flags
|
|
|
|
dc->pdcattr->jBkMode = jBkMode;
|
|
|
|
dc->pdcattr->lBkMode = lBkMode;
|
|
|
|
|
2019-05-02 15:11:11 +00:00
|
|
|
if (saveflXform)
|
|
|
|
{
|
|
|
|
dc->pdcattr->ptlViewportOrg = ptlViewportOrg;
|
|
|
|
dc->pdcattr->flXform |= saveflXform|flXform;
|
|
|
|
}
|
|
|
|
|
2019-03-09 04:21:41 +00:00
|
|
|
if (flags & DIRTY_TEXT && crColor != -1)
|
|
|
|
{
|
|
|
|
dc->pdcattr->crForegroundClr = crColor;
|
|
|
|
dc->pdcattr->ulForegroundClr = ulForegroundClr;
|
|
|
|
}
|
|
|
|
if (flags & DIRTY_BACKGROUND)
|
|
|
|
{
|
|
|
|
dc->pdcattr->crBackgroundClr = crBkColor;
|
|
|
|
dc->pdcattr->ulBackgroundClr = ulBackgroundClr;
|
|
|
|
}
|
|
|
|
if (flTextAlign != -1)
|
|
|
|
{
|
|
|
|
dc->pdcattr->flTextAlign = flTextAlign;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (flags & DIRTY_CHARSET)
|
|
|
|
{
|
|
|
|
dc->pdcattr->hlfntNew = hlfntNew;
|
|
|
|
dc->pdcattr->ulDirty_ &= ~SLOW_WIDTHS;
|
|
|
|
}
|
|
|
|
dc->pdcattr->ulDirty_ |= saveflags | flags;
|
2019-05-02 16:56:55 +00:00
|
|
|
dc->pdcattr->flXform |= saveflXform | flXform;
|
2007-11-02 04:23:31 +00:00
|
|
|
break;
|
2019-03-09 04:21:41 +00:00
|
|
|
}
|
2013-01-04 11:02:43 +00:00
|
|
|
|
2007-11-02 04:23:31 +00:00
|
|
|
case GdiBCExtTextOut:
|
2019-03-02 17:30:21 +00:00
|
|
|
{
|
2019-03-09 04:21:41 +00:00
|
|
|
PGDIBSEXTTEXTOUT pgO;
|
|
|
|
COLORREF crBkColor;
|
|
|
|
ULONG ulBackgroundClr;
|
2019-05-02 15:11:11 +00:00
|
|
|
POINTL ptlViewportOrg;
|
|
|
|
DWORD flags = 0, flXform = 0, saveflags, saveflXform = 0;
|
2019-03-09 04:21:41 +00:00
|
|
|
if (!dc) break;
|
|
|
|
pgO = (PGDIBSEXTTEXTOUT) pHdr;
|
|
|
|
|
|
|
|
saveflags = dc->pdcattr->ulDirty_ & (DIRTY_BACKGROUND|DIRTY_TEXT|DIRTY_FILL|DC_BRUSH_DIRTY|DIRTY_CHARSET);
|
|
|
|
|
|
|
|
if (dc->pdcattr->crBackgroundClr != pgO->ulBackgroundClr)
|
|
|
|
{
|
|
|
|
crBkColor = dc->pdcattr->crBackgroundClr;
|
|
|
|
ulBackgroundClr = dc->pdcattr->ulBackgroundClr;
|
|
|
|
dc->pdcattr->crBackgroundClr = pgO->ulBackgroundClr;
|
|
|
|
dc->pdcattr->ulBackgroundClr = pgO->ulBackgroundClr;
|
|
|
|
flags |= (DIRTY_BACKGROUND|DIRTY_LINE|DIRTY_FILL);
|
|
|
|
}
|
|
|
|
|
2019-05-02 15:11:11 +00:00
|
|
|
if ( dc->pdcattr->ptlViewportOrg.x != pgO->ptlViewportOrg.x ||
|
|
|
|
dc->pdcattr->ptlViewportOrg.y != pgO->ptlViewportOrg.y )
|
|
|
|
{
|
|
|
|
saveflXform = dc->pdcattr->flXform & (PAGE_XLATE_CHANGED|WORLD_XFORM_CHANGED|DEVICE_TO_WORLD_INVALID);
|
|
|
|
ptlViewportOrg = dc->pdcattr->ptlViewportOrg;
|
|
|
|
dc->pdcattr->ptlViewportOrg = pgO->ptlViewportOrg;
|
|
|
|
flXform = (PAGE_XLATE_CHANGED|WORLD_XFORM_CHANGED|DEVICE_TO_WORLD_INVALID);
|
|
|
|
}
|
|
|
|
|
2019-05-02 15:16:50 +00:00
|
|
|
dc->pdcattr->flXform |= flXform;
|
2019-03-09 04:21:41 +00:00
|
|
|
dc->pdcattr->ulDirty_ |= flags;
|
|
|
|
|
|
|
|
IntExtTextOutW( dc,
|
|
|
|
0,
|
|
|
|
0,
|
|
|
|
pgO->Options,
|
|
|
|
&pgO->Rect,
|
|
|
|
NULL,
|
|
|
|
pgO->Count,
|
|
|
|
NULL,
|
|
|
|
0 );
|
|
|
|
|
2019-05-02 15:11:11 +00:00
|
|
|
if (saveflXform)
|
|
|
|
{
|
|
|
|
dc->pdcattr->ptlViewportOrg = ptlViewportOrg;
|
|
|
|
dc->pdcattr->flXform |= saveflXform|flXform;
|
|
|
|
}
|
|
|
|
|
2019-03-09 04:21:41 +00:00
|
|
|
if (flags & DIRTY_BACKGROUND)
|
|
|
|
{
|
|
|
|
dc->pdcattr->crBackgroundClr = crBkColor;
|
|
|
|
dc->pdcattr->ulBackgroundClr = ulBackgroundClr;
|
|
|
|
}
|
|
|
|
dc->pdcattr->ulDirty_ |= saveflags | flags;
|
2019-05-02 16:56:55 +00:00
|
|
|
dc->pdcattr->flXform |= saveflXform | flXform;
|
2007-11-02 04:23:31 +00:00
|
|
|
break;
|
2019-03-02 17:30:21 +00:00
|
|
|
}
|
2013-01-04 11:02:43 +00:00
|
|
|
|
2007-11-02 04:23:31 +00:00
|
|
|
case GdiBCSetBrushOrg:
|
|
|
|
{
|
2007-11-27 01:14:38 +00:00
|
|
|
PGDIBSSETBRHORG pgSBO;
|
2010-04-07 00:46:16 +00:00
|
|
|
if (!dc) break;
|
2007-11-26 11:24:48 +00:00
|
|
|
pgSBO = (PGDIBSSETBRHORG) pHdr;
|
2009-03-20 04:51:26 +00:00
|
|
|
pdcattr->ptlBrushOrigin = pgSBO->ptlBrushOrigin;
|
2012-05-03 18:55:38 +00:00
|
|
|
DC_vSetBrushOrigin(dc, pgSBO->ptlBrushOrigin.x, pgSBO->ptlBrushOrigin.y);
|
2007-11-02 04:23:31 +00:00
|
|
|
break;
|
|
|
|
}
|
2013-01-04 11:02:43 +00:00
|
|
|
|
2007-11-02 04:23:31 +00:00
|
|
|
case GdiBCExtSelClipRgn:
|
2019-05-09 17:33:21 +00:00
|
|
|
{
|
|
|
|
PGDIBSEXTSELCLPRGN pgO;
|
|
|
|
if (!dc) break;
|
|
|
|
pgO = (PGDIBSEXTSELCLPRGN) pHdr;
|
|
|
|
IntGdiExtSelectClipRect( dc, &pgO->rcl, pgO->fnMode);
|
2007-11-02 04:23:31 +00:00
|
|
|
break;
|
2019-05-09 17:33:21 +00:00
|
|
|
}
|
2013-01-04 11:02:43 +00:00
|
|
|
|
2007-11-02 04:23:31 +00:00
|
|
|
case GdiBCSelObj:
|
2007-12-01 02:09:39 +00:00
|
|
|
{
|
|
|
|
PGDIBSOBJECT pgO;
|
2010-04-07 00:46:16 +00:00
|
|
|
|
|
|
|
if (!dc) break;
|
2007-12-01 02:09:39 +00:00
|
|
|
pgO = (PGDIBSOBJECT) pHdr;
|
2010-04-07 00:46:16 +00:00
|
|
|
|
2013-01-04 11:02:43 +00:00
|
|
|
DC_hSelectFont(dc, (HFONT)pgO->hgdiobj);
|
2010-04-07 00:46:16 +00:00
|
|
|
break;
|
2007-12-01 02:09:39 +00:00
|
|
|
}
|
2013-01-04 11:02:43 +00:00
|
|
|
|
2007-11-02 04:23:31 +00:00
|
|
|
case GdiBCDelRgn:
|
2010-02-23 04:18:24 +00:00
|
|
|
DPRINT("Delete Region Object!\n");
|
2013-01-04 11:02:43 +00:00
|
|
|
/* Fall through */
|
2010-02-23 04:18:24 +00:00
|
|
|
case GdiBCDelObj:
|
2007-11-05 01:50:59 +00:00
|
|
|
{
|
|
|
|
PGDIBSOBJECT pgO = (PGDIBSOBJECT) pHdr;
|
2009-03-25 20:24:34 +00:00
|
|
|
GreDeleteObject( pgO->hgdiobj );
|
2007-11-02 04:23:31 +00:00
|
|
|
break;
|
2007-11-05 01:50:59 +00:00
|
|
|
}
|
2013-01-04 11:02:43 +00:00
|
|
|
|
2007-11-02 04:23:31 +00:00
|
|
|
default:
|
2007-11-05 02:25:43 +00:00
|
|
|
break;
|
2007-11-02 04:23:31 +00:00
|
|
|
}
|
2008-11-03 06:52:42 +00:00
|
|
|
|
[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
|
|
|
return Size;
|
2007-11-02 04:23:31 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* NtGdiFlush
|
|
|
|
*
|
|
|
|
* Flushes the calling thread's current batch.
|
|
|
|
*/
|
2015-03-10 00:10:33 +00:00
|
|
|
__kernel_entry
|
|
|
|
NTSTATUS
|
2007-11-02 04:23:31 +00:00
|
|
|
APIENTRY
|
2015-03-10 00:10:33 +00:00
|
|
|
NtGdiFlush(
|
|
|
|
VOID)
|
2007-11-02 04:23:31 +00:00
|
|
|
{
|
2019-03-09 04:21:41 +00:00
|
|
|
SynchronizeDriver(GCAPS2_SYNCFLUSH);
|
2015-03-10 00:10:33 +00:00
|
|
|
return STATUS_SUCCESS;
|
2007-11-02 04:23:31 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* NtGdiFlushUserBatch
|
|
|
|
*
|
|
|
|
* Callback for thread batch flush routine.
|
|
|
|
*
|
|
|
|
* Think small & fast!
|
|
|
|
*/
|
|
|
|
NTSTATUS
|
|
|
|
APIENTRY
|
|
|
|
NtGdiFlushUserBatch(VOID)
|
|
|
|
{
|
|
|
|
PTEB pTeb = NtCurrentTeb();
|
|
|
|
ULONG GdiBatchCount = pTeb->GdiBatchCount;
|
2007-11-06 02:33:38 +00:00
|
|
|
|
|
|
|
if( (GdiBatchCount > 0) && (GdiBatchCount <= (GDIBATCHBUFSIZE/4)))
|
2007-11-02 04:23:31 +00:00
|
|
|
{
|
|
|
|
HDC hDC = (HDC) pTeb->GdiTebBatch.HDC;
|
2008-05-28 22:25:08 +00:00
|
|
|
|
|
|
|
/* If hDC is zero and the buffer fills up with delete objects we need
|
2010-02-23 04:18:24 +00:00
|
|
|
to run anyway.
|
|
|
|
*/
|
|
|
|
if (hDC || GdiBatchCount)
|
2007-11-02 04:23:31 +00:00
|
|
|
{
|
2008-05-28 22:25:08 +00:00
|
|
|
PCHAR pHdr = (PCHAR)&pTeb->GdiTebBatch.Buffer[0];
|
|
|
|
PDC pDC = NULL;
|
|
|
|
|
[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 (GDI_HANDLE_GET_TYPE(hDC) == GDILoObjType_LO_DC_TYPE && GreIsHandleValid(hDC))
|
2008-06-03 23:59:26 +00:00
|
|
|
{
|
|
|
|
pDC = DC_LockDc(hDC);
|
|
|
|
}
|
2008-05-28 22:25:08 +00:00
|
|
|
|
2007-11-02 04:23:31 +00:00
|
|
|
// No need to init anything, just go!
|
|
|
|
for (; GdiBatchCount > 0; GdiBatchCount--)
|
|
|
|
{
|
2010-03-24 23:35:23 +00:00
|
|
|
ULONG Size;
|
2007-11-02 04:23:31 +00:00
|
|
|
// Process Gdi Batch!
|
2010-03-24 23:35:23 +00:00
|
|
|
Size = GdiFlushUserBatch(pDC, (PGDIBATCHHDR) pHdr);
|
|
|
|
if (!Size) break;
|
|
|
|
pHdr += Size;
|
2008-05-28 22:25:08 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if (pDC)
|
|
|
|
{
|
|
|
|
DC_UnlockDc(pDC);
|
2007-11-02 04:23:31 +00:00
|
|
|
}
|
2008-05-28 22:25:08 +00:00
|
|
|
|
2007-11-02 04:23:31 +00:00
|
|
|
// Exit and clear out for the next round.
|
|
|
|
pTeb->GdiTebBatch.Offset = 0;
|
|
|
|
pTeb->GdiBatchCount = 0;
|
|
|
|
pTeb->GdiTebBatch.HDC = 0;
|
|
|
|
}
|
|
|
|
}
|
2008-05-28 22:25:08 +00:00
|
|
|
|
2011-12-14 04:07:06 +00:00
|
|
|
// FIXME: On Windows XP the function returns &pTeb->RealClientId, maybe VOID?
|
2007-11-02 04:23:31 +00:00
|
|
|
return STATUS_SUCCESS;
|
|
|
|
}
|