Create a branch for working on csrss and co.
[reactos.git] / win32ss / gdi / ntgdi / gdibatch.c
1
2 #include <win32k.h>
3
4 #define NDEBUG
5 #include <debug.h>
6
7
8 //
9 // Gdi Batch Flush support functions.
10 //
11
12 //
13 // DoDeviceSync
14 //
15 // based on IntEngEnter from eng/engmisc.c
16 //
17 VOID
18 FASTCALL
19 DoDeviceSync( SURFOBJ *Surface, PRECTL Rect, FLONG fl)
20 {
21 PPDEVOBJ Device = (PDEVOBJ*)Surface->hdev;
22 // No punting and "Handle to a surface, provided that the surface is device-managed.
23 // Otherwise, dhsurf is zero".
24 if (!(Device->flFlags & PDEV_DRIVER_PUNTED_CALL) && (Surface->dhsurf))
25 {
26 if (Device->DriverFunctions.SynchronizeSurface)
27 {
28 Device->DriverFunctions.SynchronizeSurface(Surface, Rect, fl);
29 }
30 else
31 {
32 if (Device->DriverFunctions.Synchronize)
33 {
34 Device->DriverFunctions.Synchronize(Surface->dhpdev, Rect);
35 }
36 }
37 }
38 }
39
40 VOID
41 FASTCALL
42 SynchonizeDriver(FLONG Flags)
43 {
44 SURFOBJ *SurfObj;
45 //PPDEVOBJ Device;
46
47 if (Flags & GCAPS2_SYNCFLUSH)
48 Flags = DSS_FLUSH_EVENT;
49 if (Flags & GCAPS2_SYNCTIMER)
50 Flags = DSS_TIMER_EVENT;
51
52 //Device = IntEnumHDev();
53 // UNIMPLEMENTED;
54 //ASSERT(FALSE);
55 SurfObj = 0;// EngLockSurface( Device->pSurface );
56 if(!SurfObj) return;
57 DoDeviceSync( SurfObj, NULL, Flags);
58 EngUnlockSurface(SurfObj);
59 return;
60 }
61
62 //
63 // Process the batch.
64 //
65 ULONG
66 FASTCALL
67 GdiFlushUserBatch(PDC dc, PGDIBATCHHDR pHdr)
68 {
69 BOOL Hit = FALSE;
70 ULONG Cmd = 0, Size = 0;
71 PDC_ATTR pdcattr = NULL;
72
73 if (dc)
74 {
75 pdcattr = dc->pdcattr;
76 }
77
78 _SEH2_TRY
79 {
80 Cmd = pHdr->Cmd;
81 Size = pHdr->Size; // Return the full size of the structure.
82 }
83 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
84 {
85 Hit = TRUE;
86 }
87 _SEH2_END;
88
89 if (Hit)
90 {
91 DPRINT1("WARNING! GdiBatch Fault!\n");
92 return 0;
93 }
94
95 // FYI! The thread is approaching the end of sunset.
96 switch(Cmd)
97 {
98 case GdiBCPatBlt: // Highest pri first!
99 break;
100 case GdiBCPolyPatBlt:
101 break;
102 case GdiBCTextOut:
103 break;
104 case GdiBCExtTextOut:
105 break;
106 case GdiBCSetBrushOrg:
107 {
108 PGDIBSSETBRHORG pgSBO;
109 if (!dc) break;
110 pgSBO = (PGDIBSSETBRHORG) pHdr;
111 pdcattr->ptlBrushOrigin = pgSBO->ptlBrushOrigin;
112 DC_vSetBrushOrigin(dc, pgSBO->ptlBrushOrigin.x, pgSBO->ptlBrushOrigin.y);
113 break;
114 }
115 case GdiBCExtSelClipRgn:
116 break;
117 case GdiBCSelObj:
118 {
119 PGDIBSOBJECT pgO;
120 PTEXTOBJ pNewFnt = NULL;
121
122 if (!dc) break;
123 pgO = (PGDIBSOBJECT) pHdr;
124
125 if (NT_SUCCESS(TextIntRealizeFont((HFONT)pgO->hgdiobj,NULL)))
126 {
127 /* LFONTOBJ use share and locking. */
128 pNewFnt = TEXTOBJ_LockText(pgO->hgdiobj);
129
130 dc->dclevel.plfnt = pNewFnt;
131 dc->hlfntCur = pgO->hgdiobj;
132 pdcattr->hlfntNew = pgO->hgdiobj;
133 pdcattr->ulDirty_ |= DIRTY_CHARSET;
134 pdcattr->ulDirty_ &= ~SLOW_WIDTHS;
135 }
136 if (pNewFnt) TEXTOBJ_UnlockText(pNewFnt);
137 break;
138 }
139 case GdiBCDelRgn:
140 DPRINT("Delete Region Object!\n");
141 case GdiBCDelObj:
142 {
143 PGDIBSOBJECT pgO = (PGDIBSOBJECT) pHdr;
144 GreDeleteObject( pgO->hgdiobj );
145 break;
146 }
147 default:
148 break;
149 }
150
151 return Size;
152 }
153
154 /*
155 * NtGdiFlush
156 *
157 * Flushes the calling thread's current batch.
158 */
159 VOID
160 APIENTRY
161 NtGdiFlush(VOID)
162 {
163 SynchonizeDriver(GCAPS2_SYNCFLUSH);
164 }
165
166 /*
167 * NtGdiFlushUserBatch
168 *
169 * Callback for thread batch flush routine.
170 *
171 * Think small & fast!
172 */
173 NTSTATUS
174 APIENTRY
175 NtGdiFlushUserBatch(VOID)
176 {
177 PTEB pTeb = NtCurrentTeb();
178 ULONG GdiBatchCount = pTeb->GdiBatchCount;
179
180 if( (GdiBatchCount > 0) && (GdiBatchCount <= (GDIBATCHBUFSIZE/4)))
181 {
182 HDC hDC = (HDC) pTeb->GdiTebBatch.HDC;
183
184 /* If hDC is zero and the buffer fills up with delete objects we need
185 to run anyway.
186 */
187 if (hDC || GdiBatchCount)
188 {
189 PCHAR pHdr = (PCHAR)&pTeb->GdiTebBatch.Buffer[0];
190 PDC pDC = NULL;
191
192 if (GDI_HANDLE_GET_TYPE(hDC) == GDILoObjType_LO_DC_TYPE && GreIsHandleValid(hDC))
193 {
194 pDC = DC_LockDc(hDC);
195 }
196
197 // No need to init anything, just go!
198 for (; GdiBatchCount > 0; GdiBatchCount--)
199 {
200 ULONG Size;
201 // Process Gdi Batch!
202 Size = GdiFlushUserBatch(pDC, (PGDIBATCHHDR) pHdr);
203 if (!Size) break;
204 pHdr += Size;
205 }
206
207 if (pDC)
208 {
209 DC_UnlockDc(pDC);
210 }
211
212 // Exit and clear out for the next round.
213 pTeb->GdiTebBatch.Offset = 0;
214 pTeb->GdiBatchCount = 0;
215 pTeb->GdiTebBatch.HDC = 0;
216 }
217 }
218
219 // FIXME: On Windows XP the function returns &pTeb->RealClientId, maybe VOID?
220 return STATUS_SUCCESS;
221 }
222
223