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>
|
|
|
|
|
|
|
|
|
|
|
|
//
|
|
|
|
//
|
|
|
|
// 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;
|
2007-12-04 07:51:03 +00:00
|
|
|
// No punting and "Handle to a surface, provided that the surface is device-managed.
|
|
|
|
// 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
|
|
|
|
SynchonizeDriver(FLONG Flags)
|
|
|
|
{
|
|
|
|
SURFOBJ *SurfObj;
|
2009-03-20 18:02:55 +00:00
|
|
|
PPDEVOBJ Device;
|
2007-12-04 07:51:03 +00:00
|
|
|
|
|
|
|
if (Flags & GCAPS2_SYNCFLUSH)
|
|
|
|
Flags = DSS_FLUSH_EVENT;
|
|
|
|
if (Flags & GCAPS2_SYNCTIMER)
|
|
|
|
Flags = DSS_TIMER_EVENT;
|
|
|
|
|
|
|
|
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
|
|
|
BOOL Hit = FALSE;
|
|
|
|
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)
|
|
|
|
{
|
|
|
|
Hit = TRUE;
|
|
|
|
}
|
|
|
|
_SEH2_END;
|
|
|
|
|
|
|
|
if (Hit)
|
|
|
|
{
|
|
|
|
DPRINT1("WARNING! GdiBatch Fault!\n");
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2010-03-23 01:34:30 +00:00
|
|
|
// FYI! The thread is approaching the end of sunset.
|
2010-03-24 23:35:23 +00:00
|
|
|
switch(Cmd)
|
2007-11-02 04:23:31 +00:00
|
|
|
{
|
|
|
|
case GdiBCPatBlt: // Highest pri first!
|
|
|
|
break;
|
|
|
|
case GdiBCPolyPatBlt:
|
|
|
|
break;
|
|
|
|
case GdiBCTextOut:
|
|
|
|
break;
|
|
|
|
case GdiBCExtTextOut:
|
|
|
|
break;
|
|
|
|
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;
|
2010-04-07 00:46:16 +00:00
|
|
|
IntptlBrushOrigin(dc, pgSBO->ptlBrushOrigin.x, pgSBO->ptlBrushOrigin.y);
|
2007-11-02 04:23:31 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
case GdiBCExtSelClipRgn:
|
|
|
|
break;
|
|
|
|
case GdiBCSelObj:
|
2007-12-01 02:09:39 +00:00
|
|
|
{
|
|
|
|
PGDIBSOBJECT pgO;
|
2010-09-06 23:55:53 +00:00
|
|
|
PTEXTOBJ pNewFnt = NULL;
|
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
|
|
|
|
|
|
|
if (NT_SUCCESS(TextIntRealizeFont((HFONT)pgO->hgdiobj,NULL)))
|
|
|
|
{
|
|
|
|
/* LFONTOBJ use share and locking. */
|
|
|
|
pNewFnt = TEXTOBJ_LockText(pgO->hgdiobj);
|
|
|
|
|
|
|
|
dc->dclevel.plfnt = pNewFnt;
|
|
|
|
dc->hlfntCur = pgO->hgdiobj;
|
|
|
|
pdcattr->hlfntNew = pgO->hgdiobj;
|
|
|
|
pdcattr->ulDirty_ |= DIRTY_CHARSET;
|
|
|
|
pdcattr->ulDirty_ &= ~SLOW_WIDTHS;
|
|
|
|
}
|
|
|
|
if (pNewFnt) TEXTOBJ_UnlockText(pNewFnt);
|
|
|
|
break;
|
2007-12-01 02:09:39 +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");
|
|
|
|
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
|
|
|
}
|
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
|
|
|
|
2010-03-24 23:35:23 +00:00
|
|
|
return Size;
|
2007-11-02 04:23:31 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* NtGdiFlush
|
|
|
|
*
|
|
|
|
* Flushes the calling thread's current batch.
|
|
|
|
*/
|
|
|
|
VOID
|
|
|
|
APIENTRY
|
|
|
|
NtGdiFlush(VOID)
|
|
|
|
{
|
2007-12-04 07:51:03 +00:00
|
|
|
SynchonizeDriver(GCAPS2_SYNCFLUSH);
|
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;
|
|
|
|
|
2008-06-03 23:59:26 +00:00
|
|
|
if (hDC && !IsObjectDead(hDC))
|
|
|
|
{
|
|
|
|
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
|
|
|
|
|
|
|
// FIXME: on xp the function returns &pTeb->RealClientId, maybe VOID?
|
2007-11-02 04:23:31 +00:00
|
|
|
return STATUS_SUCCESS;
|
|
|
|
}
|
|
|
|
|
2007-12-01 02:09:39 +00:00
|
|
|
|