-#include <w32k.h>
+#include <win32k.h>
#define NDEBUG
#include <debug.h>
// Gdi Batch Flush support functions.
//
+//
+// DoDeviceSync
+//
+// based on IntEngEnter from eng/engmisc.c
+//
+VOID
+FASTCALL
+DoDeviceSync( SURFOBJ *Surface, PRECTL Rect, FLONG fl)
+{
+ PPDEVOBJ Device = (PDEVOBJ*)Surface->hdev;
+// 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)
+ {
+ Device->DriverFunctions.SynchronizeSurface(Surface, Rect, fl);
+ }
+ else
+ {
+ if (Device->DriverFunctions.Synchronize)
+ {
+ Device->DriverFunctions.Synchronize(Surface->dhpdev, Rect);
+ }
+ }
+ }
+}
+
+VOID
+FASTCALL
+SynchonizeDriver(FLONG Flags)
+{
+ SURFOBJ *SurfObj;
+ PPDEVOBJ Device;
+
+ if (Flags & GCAPS2_SYNCFLUSH)
+ Flags = DSS_FLUSH_EVENT;
+ if (Flags & GCAPS2_SYNCTIMER)
+ Flags = DSS_TIMER_EVENT;
+
+ Device = IntEnumHDev();
+// UNIMPLEMENTED;
+//ASSERT(FALSE);
+ SurfObj = 0;// EngLockSurface( Device->pSurface );
+ if(!SurfObj) return;
+ DoDeviceSync( SurfObj, NULL, Flags);
+ EngUnlockSurface(SurfObj);
+ return;
+}
//
// Process the batch.
//
ULONG
FASTCALL
-GdiFlushUserBatch(HDC hDC, PGDIBATCHHDR pHdr)
+GdiFlushUserBatch(PDC dc, PGDIBATCHHDR pHdr)
{
- PDC dc = NULL;
- PDC_ATTR Dc_Attr = NULL;
- PGDIBSSETBRHORG pgSBO;
- if (hDC)
+ BOOL Hit = FALSE;
+ ULONG Cmd = 0, Size = 0;
+ PDC_ATTR pdcattr = NULL;
+
+ if (dc)
+ {
+ pdcattr = dc->pdcattr;
+ }
+
+ _SEH2_TRY
{
- dc = DC_LockDc(hDC);
- Dc_Attr = dc->pDc_Attr;
- if (!Dc_Attr) Dc_Attr = &dc->Dc_Attr;
+ Cmd = pHdr->Cmd;
+ Size = pHdr->Size; // Return the full size of the structure.
}
- // The thread is approaching the end of sunset.
- switch(pHdr->Cmd)
+ _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+ {
+ Hit = TRUE;
+ }
+ _SEH2_END;
+
+ if (Hit)
+ {
+ DPRINT1("WARNING! GdiBatch Fault!\n");
+ return 0;
+ }
+
+ // FYI! The thread is approaching the end of sunset.
+ switch(Cmd)
{
case GdiBCPatBlt: // Highest pri first!
break;
break;
case GdiBCSetBrushOrg:
{
+ PGDIBSSETBRHORG pgSBO;
if (!dc) break;
pgSBO = (PGDIBSSETBRHORG) pHdr;
- Dc_Attr->ptlBrushOrigin = pgSBO->ptlBrushOrigin;
+ pdcattr->ptlBrushOrigin = pgSBO->ptlBrushOrigin;
+ IntptlBrushOrigin(dc, pgSBO->ptlBrushOrigin.x, pgSBO->ptlBrushOrigin.y);
break;
}
case GdiBCExtSelClipRgn:
break;
case GdiBCSelObj:
+ {
+ PGDIBSOBJECT pgO;
+ PTEXTOBJ pNewFnt = NULL;
+
+ if (!dc) break;
+ pgO = (PGDIBSOBJECT) pHdr;
+
+ 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;
- case GdiBCDelObj:
+ }
case GdiBCDelRgn:
+ DPRINT("Delete Region Object!\n");
+ case GdiBCDelObj:
{
PGDIBSOBJECT pgO = (PGDIBSOBJECT) pHdr;
- NtGdiDeleteObject( pgO->hgdiobj );
+ GreDeleteObject( pgO->hgdiobj );
break;
}
default:
break;
}
- if (dc) DC_UnlockDc(dc);
- return pHdr->Size; // Return the full size of the structure.
+
+ return Size;
}
/*
APIENTRY
NtGdiFlush(VOID)
{
- UNIMPLEMENTED;
+ SynchonizeDriver(GCAPS2_SYNCFLUSH);
}
/*
if( (GdiBatchCount > 0) && (GdiBatchCount <= (GDIBATCHBUFSIZE/4)))
{
HDC hDC = (HDC) pTeb->GdiTebBatch.HDC;
-//
-// If hDC is zero and the buffer fills up with delete objects we need to run
-// anyway. So, hard code to the system batch limit.
-//
- if ((hDC) || ((!hDC) && (GdiBatchCount >= GDI_BATCH_LIMIT)))
+
+ /* If hDC is zero and the buffer fills up with delete objects we need
+ to run anyway.
+ */
+ if (hDC || GdiBatchCount)
{
- PULONG pHdr = &pTeb->GdiTebBatch.Buffer[0];
+ PCHAR pHdr = (PCHAR)&pTeb->GdiTebBatch.Buffer[0];
+ PDC pDC = NULL;
+
+ if (hDC && !IsObjectDead(hDC))
+ {
+ pDC = DC_LockDc(hDC);
+ }
+
// No need to init anything, just go!
for (; GdiBatchCount > 0; GdiBatchCount--)
{
+ ULONG Size;
// Process Gdi Batch!
- pHdr += GdiFlushUserBatch( hDC, (PGDIBATCHHDR) pHdr );
+ Size = GdiFlushUserBatch(pDC, (PGDIBATCHHDR) pHdr);
+ if (!Size) break;
+ pHdr += Size;
}
+
+ if (pDC)
+ {
+ DC_UnlockDc(pDC);
+ }
+
// Exit and clear out for the next round.
pTeb->GdiTebBatch.Offset = 0;
pTeb->GdiBatchCount = 0;
pTeb->GdiTebBatch.HDC = 0;
}
}
+
+ // FIXME: on xp the function returns &pTeb->RealClientId, maybe VOID?
return STATUS_SUCCESS;
}
+