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