Merge freeldr from amd64 branch:
[reactos.git] / reactos / 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 PGDIDEVICE Device = (GDIDEVICE*)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 return Device->DriverFunctions.SynchronizeSurface(Surface, Rect, fl);
29 else
30 {
31 if (Device->DriverFunctions.Synchronize)
32 return Device->DriverFunctions.Synchronize(Surface->dhpdev, Rect);
33 }
34 }
35 return;
36 }
37
38 VOID
39 FASTCALL
40 SynchonizeDriver(FLONG Flags)
41 {
42 SURFOBJ *SurfObj;
43 PGDIDEVICE Device;
44
45 if (Flags & GCAPS2_SYNCFLUSH)
46 Flags = DSS_FLUSH_EVENT;
47 if (Flags & GCAPS2_SYNCTIMER)
48 Flags = DSS_TIMER_EVENT;
49
50 Device = IntEnumHDev();
51
52 SurfObj = EngLockSurface( Device->pSurface );
53 if(!SurfObj) return;
54 DoDeviceSync( SurfObj, NULL, Flags);
55 EngUnlockSurface(SurfObj);
56 return;
57 }
58
59 //
60 // Process the batch.
61 //
62 ULONG
63 FASTCALL
64 GdiFlushUserBatch(PDC dc, PGDIBATCHHDR pHdr)
65 {
66 PDC_ATTR Dc_Attr = NULL;
67
68 if (dc)
69 {
70 Dc_Attr = dc->pDc_Attr;
71 if (!Dc_Attr) Dc_Attr = &dc->Dc_Attr;
72 }
73 // The thread is approaching the end of sunset.
74 switch(pHdr->Cmd)
75 {
76 case GdiBCPatBlt: // Highest pri first!
77 break;
78 case GdiBCPolyPatBlt:
79 break;
80 case GdiBCTextOut:
81 break;
82 case GdiBCExtTextOut:
83 break;
84 case GdiBCSetBrushOrg:
85 {
86 PGDIBSSETBRHORG pgSBO;
87 if(!dc) break;
88 pgSBO = (PGDIBSSETBRHORG) pHdr;
89 Dc_Attr->ptlBrushOrigin = pgSBO->ptlBrushOrigin;
90 break;
91 }
92 case GdiBCExtSelClipRgn:
93 break;
94 case GdiBCSelObj:
95 {
96 PGDIBSOBJECT pgO;
97 if(!dc) break;
98 pgO = (PGDIBSOBJECT) pHdr;
99 TextIntRealizeFont((HFONT) pgO->hgdiobj, NULL);
100 Dc_Attr->ulDirty_ &= ~(DIRTY_CHARSET);
101 }
102 case GdiBCDelObj:
103 case GdiBCDelRgn:
104 {
105 PGDIBSOBJECT pgO = (PGDIBSOBJECT) pHdr;
106 NtGdiDeleteObject( pgO->hgdiobj );
107 break;
108 }
109 default:
110 break;
111 }
112
113 return pHdr->Size; // Return the full size of the structure.
114 }
115
116 /*
117 * NtGdiFlush
118 *
119 * Flushes the calling thread's current batch.
120 */
121 VOID
122 APIENTRY
123 NtGdiFlush(VOID)
124 {
125 SynchonizeDriver(GCAPS2_SYNCFLUSH);
126 }
127
128 /*
129 * NtGdiFlushUserBatch
130 *
131 * Callback for thread batch flush routine.
132 *
133 * Think small & fast!
134 */
135 NTSTATUS
136 APIENTRY
137 NtGdiFlushUserBatch(VOID)
138 {
139 PTEB pTeb = NtCurrentTeb();
140 ULONG GdiBatchCount = pTeb->GdiBatchCount;
141
142 if( (GdiBatchCount > 0) && (GdiBatchCount <= (GDIBATCHBUFSIZE/4)))
143 {
144 HDC hDC = (HDC) pTeb->GdiTebBatch.HDC;
145
146 /* If hDC is zero and the buffer fills up with delete objects we need
147 to run anyway. So, hard code to the system batch limit. */
148 if ((hDC) || (GdiBatchCount >= GDI_BATCH_LIMIT))
149 {
150 PCHAR pHdr = (PCHAR)&pTeb->GdiTebBatch.Buffer[0];
151 PDC pDC = NULL;
152
153 if (hDC && !IsObjectDead(hDC))
154 {
155 pDC = DC_LockDc(hDC);
156 }
157
158 // No need to init anything, just go!
159 for (; GdiBatchCount > 0; GdiBatchCount--)
160 {
161 // Process Gdi Batch!
162 pHdr += GdiFlushUserBatch(pDC, (PGDIBATCHHDR) pHdr);
163 }
164
165 if (pDC)
166 {
167 DC_UnlockDc(pDC);
168 }
169
170 // Exit and clear out for the next round.
171 pTeb->GdiTebBatch.Offset = 0;
172 pTeb->GdiBatchCount = 0;
173 pTeb->GdiTebBatch.HDC = 0;
174 }
175 }
176
177 // FIXME: on xp the function returns &pTeb->RealClientId, maybe VOID?
178 return STATUS_SUCCESS;
179 }
180
181