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