10 // Gdi Batch Flush support functions.
16 // based on IntEngEnter from eng/engmisc.c
20 DoDeviceSync( SURFOBJ
*Surface
, PRECTL Rect
, FLONG fl
)
22 PPDEVOBJ Device
= (PDEVOBJ
*)Surface
->hdev
;
23 // No punting and "Handle to a surface, provided that the surface is device-managed.
24 // Otherwise, dhsurf is zero".
25 if (!(Device
->flFlags
& PDEV_DRIVER_PUNTED_CALL
) && (Surface
->dhsurf
))
27 if (Device
->DriverFunctions
.SynchronizeSurface
)
29 Device
->DriverFunctions
.SynchronizeSurface(Surface
, Rect
, fl
);
33 if (Device
->DriverFunctions
.Synchronize
)
35 Device
->DriverFunctions
.Synchronize(Surface
->dhpdev
, Rect
);
43 SynchonizeDriver(FLONG Flags
)
48 if (Flags
& GCAPS2_SYNCFLUSH
)
49 Flags
= DSS_FLUSH_EVENT
;
50 if (Flags
& GCAPS2_SYNCTIMER
)
51 Flags
= DSS_TIMER_EVENT
;
53 Device
= IntEnumHDev();
55 SurfObj
= EngLockSurface( Device
->pSurface
);
57 DoDeviceSync( SurfObj
, NULL
, Flags
);
58 EngUnlockSurface(SurfObj
);
67 GdiFlushUserBatch(PDC dc
, PGDIBATCHHDR pHdr
)
70 ULONG Cmd
= 0, Size
= 0;
71 PDC_ATTR pdcattr
= NULL
;
75 pdcattr
= dc
->pdcattr
;
81 Size
= pHdr
->Size
; // Return the full size of the structure.
83 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
91 DPRINT1("WARNING! GdiBatch Fault!\n");
95 // FYI! The thread is approaching the end of sunset.
98 case GdiBCPatBlt
: // Highest pri first!
100 case GdiBCPolyPatBlt
:
104 case GdiBCExtTextOut
:
106 case GdiBCSetBrushOrg
:
108 PGDIBSSETBRHORG pgSBO
;
110 pgSBO
= (PGDIBSSETBRHORG
) pHdr
;
111 pdcattr
->ptlBrushOrigin
= pgSBO
->ptlBrushOrigin
;
112 IntptlBrushOrigin(dc
, pgSBO
->ptlBrushOrigin
.x
, pgSBO
->ptlBrushOrigin
.y
);
115 case GdiBCExtSelClipRgn
:
120 PTEXTOBJ pOrgFnt
, pNewFnt
= NULL
;
121 HFONT hOrgFont
= NULL
;
124 pgO
= (PGDIBSOBJECT
) pHdr
;
126 if (NT_SUCCESS(TextIntRealizeFont((HFONT
)pgO
->hgdiobj
,NULL
)))
128 /* LFONTOBJ use share and locking. */
129 pNewFnt
= TEXTOBJ_LockText(pgO
->hgdiobj
);
131 pOrgFnt
= dc
->dclevel
.plfnt
;
134 hOrgFont
= pOrgFnt
->BaseObject
.hHmgr
;
138 hOrgFont
= pdcattr
->hlfntNew
;
140 dc
->dclevel
.plfnt
= pNewFnt
;
141 dc
->hlfntCur
= pgO
->hgdiobj
;
142 pdcattr
->hlfntNew
= pgO
->hgdiobj
;
143 pdcattr
->ulDirty_
|= DIRTY_CHARSET
;
144 pdcattr
->ulDirty_
&= ~SLOW_WIDTHS
;
146 if (pNewFnt
) TEXTOBJ_UnlockText(pNewFnt
);
150 DPRINT("Delete Region Object!\n");
153 PGDIBSOBJECT pgO
= (PGDIBSOBJECT
) pHdr
;
154 GreDeleteObject( pgO
->hgdiobj
);
167 * Flushes the calling thread's current batch.
173 SynchonizeDriver(GCAPS2_SYNCFLUSH
);
177 * NtGdiFlushUserBatch
179 * Callback for thread batch flush routine.
181 * Think small & fast!
185 NtGdiFlushUserBatch(VOID
)
187 PTEB pTeb
= NtCurrentTeb();
188 ULONG GdiBatchCount
= pTeb
->GdiBatchCount
;
190 if( (GdiBatchCount
> 0) && (GdiBatchCount
<= (GDIBATCHBUFSIZE
/4)))
192 HDC hDC
= (HDC
) pTeb
->GdiTebBatch
.HDC
;
194 /* If hDC is zero and the buffer fills up with delete objects we need
197 if (hDC
|| GdiBatchCount
)
199 PCHAR pHdr
= (PCHAR
)&pTeb
->GdiTebBatch
.Buffer
[0];
202 if (hDC
&& !IsObjectDead(hDC
))
204 pDC
= DC_LockDc(hDC
);
207 // No need to init anything, just go!
208 for (; GdiBatchCount
> 0; GdiBatchCount
--)
211 // Process Gdi Batch!
212 Size
= GdiFlushUserBatch(pDC
, (PGDIBATCHHDR
) pHdr
);
222 // Exit and clear out for the next round.
223 pTeb
->GdiTebBatch
.Offset
= 0;
224 pTeb
->GdiBatchCount
= 0;
225 pTeb
->GdiTebBatch
.HDC
= 0;
229 // FIXME: on xp the function returns &pTeb->RealClientId, maybe VOID?
230 return STATUS_SUCCESS
;