8cb32a7188e3ac9e4a43ecbb8f0a420e92b40968
[reactos.git] / subsystems / win32 / win32k / objects / gdibatch.c
1
2 #include <w32k.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
55 SurfObj = 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 PDC_ATTR pdcattr = NULL;
70
71 if (dc)
72 {
73 pdcattr = dc->pdcattr;
74 }
75 // The thread is approaching the end of sunset.
76 switch(pHdr->Cmd)
77 {
78 case GdiBCPatBlt: // Highest pri first!
79 break;
80 case GdiBCPolyPatBlt:
81 break;
82 case GdiBCTextOut:
83 break;
84 case GdiBCExtTextOut:
85 break;
86 case GdiBCSetBrushOrg:
87 {
88 PGDIBSSETBRHORG pgSBO;
89 if(!dc) break;
90 pgSBO = (PGDIBSSETBRHORG) pHdr;
91 pdcattr->ptlBrushOrigin = pgSBO->ptlBrushOrigin;
92 break;
93 }
94 case GdiBCExtSelClipRgn:
95 break;
96 case GdiBCSelObj:
97 {
98 PGDIBSOBJECT pgO;
99 if(!dc) break;
100 pgO = (PGDIBSOBJECT) pHdr;
101 TextIntRealizeFont((HFONT) pgO->hgdiobj, NULL);
102 pdcattr->ulDirty_ &= ~(DIRTY_CHARSET);
103 }
104 case GdiBCDelObj:
105 case GdiBCDelRgn:
106 {
107 PGDIBSOBJECT pgO = (PGDIBSOBJECT) pHdr;
108 GreDeleteObject( pgO->hgdiobj );
109 break;
110 }
111 default:
112 break;
113 }
114
115 return pHdr->Size; // Return the full size of the structure.
116 }
117
118 /*
119 * NtGdiFlush
120 *
121 * Flushes the calling thread's current batch.
122 */
123 VOID
124 APIENTRY
125 NtGdiFlush(VOID)
126 {
127 SynchonizeDriver(GCAPS2_SYNCFLUSH);
128 }
129
130 /*
131 * NtGdiFlushUserBatch
132 *
133 * Callback for thread batch flush routine.
134 *
135 * Think small & fast!
136 */
137 NTSTATUS
138 APIENTRY
139 NtGdiFlushUserBatch(VOID)
140 {
141 PTEB pTeb = NtCurrentTeb();
142 ULONG GdiBatchCount = pTeb->GdiBatchCount;
143
144 if( (GdiBatchCount > 0) && (GdiBatchCount <= (GDIBATCHBUFSIZE/4)))
145 {
146 HDC hDC = (HDC) pTeb->GdiTebBatch.HDC;
147
148 /* If hDC is zero and the buffer fills up with delete objects we need
149 to run anyway. So, hard code to the system batch limit. */
150 if ((hDC) || (GdiBatchCount >= GDI_BATCH_LIMIT))
151 {
152 PCHAR pHdr = (PCHAR)&pTeb->GdiTebBatch.Buffer[0];
153 PDC pDC = NULL;
154
155 if (hDC && !IsObjectDead(hDC))
156 {
157 pDC = DC_LockDc(hDC);
158 }
159
160 // No need to init anything, just go!
161 for (; GdiBatchCount > 0; GdiBatchCount--)
162 {
163 // Process Gdi Batch!
164 pHdr += GdiFlushUserBatch(pDC, (PGDIBATCHHDR) pHdr);
165 }
166
167 if (pDC)
168 {
169 DC_UnlockDc(pDC);
170 }
171
172 // Exit and clear out for the next round.
173 pTeb->GdiTebBatch.Offset = 0;
174 pTeb->GdiBatchCount = 0;
175 pTeb->GdiTebBatch.HDC = 0;
176 }
177 }
178
179 // FIXME: on xp the function returns &pTeb->RealClientId, maybe VOID?
180 return STATUS_SUCCESS;
181 }
182
183