1 2 #include <win32k.h> 3 4 #define NDEBUG 5 #include <debug.h> 6 7 BOOL FASTCALL IntPatBlt( PDC,INT,INT,INT,INT,DWORD,PEBRUSHOBJ); 8 BOOL APIENTRY IntExtTextOutW(IN PDC,IN INT,IN INT,IN UINT,IN OPTIONAL PRECTL,IN LPCWSTR,IN INT,IN OPTIONAL LPINT,IN DWORD); 9 10 11 // 12 // Gdi Batch Flush support functions. 13 // 14 15 // 16 // DoDeviceSync 17 // 18 // based on IntEngEnter from eng/engmisc.c 19 // 20 VOID 21 FASTCALL 22 DoDeviceSync( SURFOBJ *Surface, PRECTL Rect, FLONG fl) 23 { 24 PPDEVOBJ Device = (PDEVOBJ*)Surface->hdev; 25 // No punting and "Handle to a surface, provided that the surface is device-managed. 26 // Otherwise, dhsurf is zero". 27 if (!(Device->flFlags & PDEV_DRIVER_PUNTED_CALL) && (Surface->dhsurf)) 28 { 29 if (Device->DriverFunctions.SynchronizeSurface) 30 { 31 Device->DriverFunctions.SynchronizeSurface(Surface, Rect, fl); 32 } 33 else 34 { 35 if (Device->DriverFunctions.Synchronize) 36 { 37 Device->DriverFunctions.Synchronize(Surface->dhpdev, Rect); 38 } 39 } 40 } 41 } 42 43 VOID 44 FASTCALL 45 SynchronizeDriver(FLONG Flags) 46 { 47 SURFOBJ *SurfObj; 48 //PPDEVOBJ Device; 49 50 if (Flags & GCAPS2_SYNCFLUSH) 51 Flags = DSS_FLUSH_EVENT; 52 if (Flags & GCAPS2_SYNCTIMER) 53 Flags = DSS_TIMER_EVENT; 54 55 //Device = IntEnumHDev(); 56 // UNIMPLEMENTED; 57 //ASSERT(FALSE); 58 SurfObj = 0;// EngLockSurface( Device->pSurface ); 59 if(!SurfObj) return; 60 DoDeviceSync( SurfObj, NULL, Flags); 61 EngUnlockSurface(SurfObj); 62 return; 63 } 64 65 // 66 // Process the batch. 67 // 68 ULONG 69 FASTCALL 70 GdiFlushUserBatch(PDC dc, PGDIBATCHHDR pHdr) 71 { 72 ULONG Cmd = 0, Size = 0; 73 PDC_ATTR pdcattr = NULL; 74 75 if (dc) 76 { 77 pdcattr = dc->pdcattr; 78 } 79 80 _SEH2_TRY 81 { 82 Cmd = pHdr->Cmd; 83 Size = pHdr->Size; // Return the full size of the structure. 84 } 85 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 86 { 87 DPRINT1("WARNING! GdiBatch Fault!\n"); 88 _SEH2_YIELD(return 0;) 89 } 90 _SEH2_END; 91 92 switch(Cmd) 93 { 94 case GdiBCPatBlt: 95 { 96 PGDIBSPATBLT pgDPB; 97 DWORD dwRop, flags; 98 HBRUSH hOrgBrush; 99 COLORREF crColor, crBkColor, crBrushClr; 100 ULONG ulForegroundClr, ulBackgroundClr, ulBrushClr; 101 if (!dc) break; 102 pgDPB = (PGDIBSPATBLT) pHdr; 103 /* Convert the ROP3 to a ROP4 */ 104 dwRop = pgDPB->dwRop; 105 dwRop = MAKEROP4(dwRop & 0xFF0000, dwRop); 106 /* Check if the rop uses a source */ 107 if (WIN32_ROP4_USES_SOURCE(dwRop)) 108 { 109 /* This is not possible */ 110 break; 111 } 112 /* Check if the DC has no surface (empty mem or info DC) */ 113 if (dc->dclevel.pSurface == NULL) 114 { 115 /* Nothing to do */ 116 break; 117 } 118 // Save current attributes and flags 119 crColor = dc->pdcattr->crForegroundClr; 120 crBkColor = dc->pdcattr->ulBackgroundClr; 121 crBrushClr = dc->pdcattr->crBrushClr; 122 ulForegroundClr = dc->pdcattr->ulForegroundClr; 123 ulBackgroundClr = dc->pdcattr->ulBackgroundClr; 124 ulBrushClr = dc->pdcattr->ulBrushClr; 125 hOrgBrush = dc->pdcattr->hbrush; 126 flags = dc->pdcattr->ulDirty_ & (DIRTY_BACKGROUND | DIRTY_TEXT | DIRTY_FILL | DC_BRUSH_DIRTY); 127 // Set the attribute snapshot 128 dc->pdcattr->hbrush = pgDPB->hbrush; 129 dc->pdcattr->crForegroundClr = pgDPB->crForegroundClr; 130 dc->pdcattr->crBackgroundClr = pgDPB->crBackgroundClr; 131 dc->pdcattr->crBrushClr = pgDPB->crBrushClr; 132 dc->pdcattr->ulForegroundClr = pgDPB->ulForegroundClr; 133 dc->pdcattr->ulBackgroundClr = pgDPB->ulBackgroundClr; 134 dc->pdcattr->ulBrushClr = pgDPB->ulBrushClr; 135 // Process dirty attributes if any. 136 if (dc->pdcattr->ulDirty_ & (DIRTY_FILL | DC_BRUSH_DIRTY)) 137 DC_vUpdateFillBrush(dc); 138 if (dc->pdcattr->ulDirty_ & DIRTY_TEXT) 139 DC_vUpdateTextBrush(dc); 140 if (pdcattr->ulDirty_ & DIRTY_BACKGROUND) 141 DC_vUpdateBackgroundBrush(dc); 142 /* Call the internal function */ 143 IntPatBlt(dc, pgDPB->nXLeft, pgDPB->nYLeft, pgDPB->nWidth, pgDPB->nHeight, dwRop, &dc->eboFill); 144 // Restore attributes and flags 145 dc->pdcattr->hbrush = hOrgBrush; 146 dc->pdcattr->crForegroundClr = crColor; 147 dc->pdcattr->crBackgroundClr = crBkColor; 148 dc->pdcattr->crBrushClr = crBrushClr; 149 dc->pdcattr->ulForegroundClr = ulForegroundClr; 150 dc->pdcattr->ulBackgroundClr = ulBackgroundClr; 151 dc->pdcattr->ulBrushClr = ulBrushClr; 152 dc->pdcattr->ulDirty_ |= flags; 153 break; 154 } 155 156 case GdiBCPolyPatBlt: 157 { 158 PGDIBSPPATBLT pgDPB; 159 EBRUSHOBJ eboFill; 160 PBRUSH pbrush; 161 PPATRECT pRects; 162 INT i; 163 DWORD dwRop, flags; 164 COLORREF crColor, crBkColor, crBrushClr; 165 ULONG ulForegroundClr, ulBackgroundClr, ulBrushClr; 166 if (!dc) break; 167 pgDPB = (PGDIBSPPATBLT) pHdr; 168 /* Convert the ROP3 to a ROP4 */ 169 dwRop = pgDPB->rop4; 170 dwRop = MAKEROP4(dwRop & 0xFF0000, dwRop); 171 /* Check if the rop uses a source */ 172 if (WIN32_ROP4_USES_SOURCE(dwRop)) 173 { 174 /* This is not possible */ 175 break; 176 } 177 /* Check if the DC has no surface (empty mem or info DC) */ 178 if (dc->dclevel.pSurface == NULL) 179 { 180 /* Nothing to do */ 181 break; 182 } 183 // Save current attributes and flags 184 crColor = dc->pdcattr->crForegroundClr; 185 crBkColor = dc->pdcattr->ulBackgroundClr; 186 crBrushClr = dc->pdcattr->crBrushClr; 187 ulForegroundClr = dc->pdcattr->ulForegroundClr; 188 ulBackgroundClr = dc->pdcattr->ulBackgroundClr; 189 ulBrushClr = dc->pdcattr->ulBrushClr; 190 flags = dc->pdcattr->ulDirty_ & (DIRTY_BACKGROUND | DIRTY_TEXT | DIRTY_FILL | DC_BRUSH_DIRTY); 191 // Set the attribute snapshot 192 dc->pdcattr->crForegroundClr = pgDPB->crForegroundClr; 193 dc->pdcattr->crBackgroundClr = pgDPB->crBackgroundClr; 194 dc->pdcattr->crBrushClr = pgDPB->crBrushClr; 195 dc->pdcattr->ulForegroundClr = pgDPB->ulForegroundClr; 196 dc->pdcattr->ulBackgroundClr = pgDPB->ulBackgroundClr; 197 dc->pdcattr->ulBrushClr = pgDPB->ulBrushClr; 198 // Process dirty attributes if any 199 if (dc->pdcattr->ulDirty_ & DIRTY_TEXT) 200 DC_vUpdateTextBrush(dc); 201 if (pdcattr->ulDirty_ & DIRTY_BACKGROUND) 202 DC_vUpdateBackgroundBrush(dc); 203 204 DPRINT1("GdiBCPolyPatBlt Testing\n"); 205 pRects = &pgDPB->pRect[0]; 206 207 for (i = 0; i < pgDPB->Count; i++) 208 { 209 pbrush = BRUSH_ShareLockBrush(pRects->hBrush); 210 211 /* Check if we could lock the brush */ 212 if (pbrush != NULL) 213 { 214 /* Initialize a brush object */ 215 EBRUSHOBJ_vInitFromDC(&eboFill, pbrush, dc); 216 217 IntPatBlt( 218 dc, 219 pRects->r.left, 220 pRects->r.top, 221 pRects->r.right, 222 pRects->r.bottom, 223 dwRop, 224 &eboFill); 225 226 /* Cleanup the brush object and unlock the brush */ 227 EBRUSHOBJ_vCleanup(&eboFill); 228 BRUSH_ShareUnlockBrush(pbrush); 229 } 230 pRects++; 231 } 232 233 // Restore attributes and flags 234 dc->pdcattr->crForegroundClr = crColor; 235 dc->pdcattr->crBackgroundClr = crBkColor; 236 dc->pdcattr->crBrushClr = crBrushClr; 237 dc->pdcattr->ulForegroundClr = ulForegroundClr; 238 dc->pdcattr->ulBackgroundClr = ulBackgroundClr; 239 dc->pdcattr->ulBrushClr = ulBrushClr; 240 dc->pdcattr->ulDirty_ |= flags; 241 break; 242 } 243 244 case GdiBCTextOut: 245 { 246 PGDIBSTEXTOUT pgO; 247 COLORREF crColor = -1, crBkColor; 248 ULONG ulForegroundClr, ulBackgroundClr; 249 DWORD flags = 0, saveflags; 250 FLONG flTextAlign = -1; 251 HANDLE hlfntNew; 252 PRECTL lprc; 253 USHORT jBkMode; 254 LONG lBkMode; 255 if (!dc) break; 256 pgO = (PGDIBSTEXTOUT) pHdr; 257 258 // Save current attributes, flags and Set the attribute snapshots 259 saveflags = dc->pdcattr->ulDirty_ & (DIRTY_BACKGROUND|DIRTY_LINE|DIRTY_TEXT|DIRTY_FILL|DC_BRUSH_DIRTY|DIRTY_CHARSET); 260 261 // In this instance check for differences and set the appropriate dirty flags. 262 if ( dc->pdcattr->crForegroundClr != pgO->crForegroundClr) 263 { 264 crColor = dc->pdcattr->crForegroundClr; 265 dc->pdcattr->crForegroundClr = pgO->crForegroundClr; 266 ulForegroundClr = dc->pdcattr->ulForegroundClr; 267 dc->pdcattr->ulForegroundClr = pgO->ulForegroundClr; 268 flags |= (DIRTY_FILL|DIRTY_LINE|DIRTY_TEXT); 269 } 270 if (dc->pdcattr->crBackgroundClr != pgO->crBackgroundClr) 271 { 272 crBkColor = dc->pdcattr->ulBackgroundClr; 273 dc->pdcattr->crBackgroundClr = pgO->crBackgroundClr; 274 ulBackgroundClr = dc->pdcattr->ulBackgroundClr; 275 dc->pdcattr->ulBackgroundClr = pgO->ulBackgroundClr; 276 flags |= (DIRTY_FILL|DIRTY_LINE|DIRTY_TEXT|DIRTY_BACKGROUND); 277 } 278 if (dc->pdcattr->flTextAlign != pgO->flTextAlign) 279 { 280 flTextAlign = dc->pdcattr->flTextAlign; 281 dc->pdcattr->flTextAlign = pgO->flTextAlign; 282 } 283 if (dc->pdcattr->hlfntNew != pgO->hlfntNew) 284 { 285 hlfntNew = dc->pdcattr->hlfntNew; 286 dc->pdcattr->hlfntNew = pgO->hlfntNew; 287 dc->pdcattr->ulDirty_ &= ~SLOW_WIDTHS; 288 flags |= DIRTY_CHARSET; 289 } 290 291 dc->pdcattr->ulDirty_ |= flags; 292 293 jBkMode = dc->pdcattr->jBkMode; 294 dc->pdcattr->jBkMode = pgO->lBkMode; 295 lBkMode = dc->pdcattr->lBkMode; 296 dc->pdcattr->lBkMode = pgO->lBkMode; 297 298 lprc = (pgO->Options & GDIBS_NORECT) ? NULL : &pgO->Rect; 299 pgO->Options &= ~GDIBS_NORECT; 300 301 IntExtTextOutW( dc, 302 pgO->x, 303 pgO->y, 304 pgO->Options, 305 lprc, 306 (LPCWSTR)&pgO->String[pgO->Size/sizeof(WCHAR)], 307 pgO->cbCount, 308 pgO->Size ? (LPINT)&pgO->Buffer : NULL, 309 pgO->iCS_CP ); 310 311 // Restore attributes and flags 312 dc->pdcattr->jBkMode = jBkMode; 313 dc->pdcattr->lBkMode = lBkMode; 314 315 if (flags & DIRTY_TEXT && crColor != -1) 316 { 317 dc->pdcattr->crForegroundClr = crColor; 318 dc->pdcattr->ulForegroundClr = ulForegroundClr; 319 } 320 if (flags & DIRTY_BACKGROUND) 321 { 322 dc->pdcattr->crBackgroundClr = crBkColor; 323 dc->pdcattr->ulBackgroundClr = ulBackgroundClr; 324 } 325 if (flTextAlign != -1) 326 { 327 dc->pdcattr->flTextAlign = flTextAlign; 328 } 329 330 if (flags & DIRTY_CHARSET) 331 { 332 dc->pdcattr->hlfntNew = hlfntNew; 333 dc->pdcattr->ulDirty_ &= ~SLOW_WIDTHS; 334 } 335 dc->pdcattr->ulDirty_ |= saveflags | flags; 336 break; 337 } 338 339 case GdiBCExtTextOut: 340 { 341 PGDIBSEXTTEXTOUT pgO; 342 COLORREF crBkColor; 343 ULONG ulBackgroundClr; 344 DWORD flags = 0, saveflags; 345 if (!dc) break; 346 pgO = (PGDIBSEXTTEXTOUT) pHdr; 347 348 saveflags = dc->pdcattr->ulDirty_ & (DIRTY_BACKGROUND|DIRTY_TEXT|DIRTY_FILL|DC_BRUSH_DIRTY|DIRTY_CHARSET); 349 350 if (dc->pdcattr->crBackgroundClr != pgO->ulBackgroundClr) 351 { 352 crBkColor = dc->pdcattr->crBackgroundClr; 353 ulBackgroundClr = dc->pdcattr->ulBackgroundClr; 354 dc->pdcattr->crBackgroundClr = pgO->ulBackgroundClr; 355 dc->pdcattr->ulBackgroundClr = pgO->ulBackgroundClr; 356 flags |= (DIRTY_BACKGROUND|DIRTY_LINE|DIRTY_FILL); 357 } 358 359 dc->pdcattr->ulDirty_ |= flags; 360 361 IntExtTextOutW( dc, 362 0, 363 0, 364 pgO->Options, 365 &pgO->Rect, 366 NULL, 367 pgO->Count, 368 NULL, 369 0 ); 370 371 if (flags & DIRTY_BACKGROUND) 372 { 373 dc->pdcattr->crBackgroundClr = crBkColor; 374 dc->pdcattr->ulBackgroundClr = ulBackgroundClr; 375 } 376 dc->pdcattr->ulDirty_ |= saveflags | flags; 377 break; 378 } 379 380 case GdiBCSetBrushOrg: 381 { 382 PGDIBSSETBRHORG pgSBO; 383 if (!dc) break; 384 pgSBO = (PGDIBSSETBRHORG) pHdr; 385 pdcattr->ptlBrushOrigin = pgSBO->ptlBrushOrigin; 386 DC_vSetBrushOrigin(dc, pgSBO->ptlBrushOrigin.x, pgSBO->ptlBrushOrigin.y); 387 break; 388 } 389 390 case GdiBCExtSelClipRgn: 391 break; 392 393 case GdiBCSelObj: 394 { 395 PGDIBSOBJECT pgO; 396 397 if (!dc) break; 398 pgO = (PGDIBSOBJECT) pHdr; 399 400 DC_hSelectFont(dc, (HFONT)pgO->hgdiobj); 401 break; 402 } 403 404 case GdiBCDelRgn: 405 DPRINT("Delete Region Object!\n"); 406 /* Fall through */ 407 case GdiBCDelObj: 408 { 409 PGDIBSOBJECT pgO = (PGDIBSOBJECT) pHdr; 410 GreDeleteObject( pgO->hgdiobj ); 411 break; 412 } 413 414 default: 415 break; 416 } 417 418 return Size; 419 } 420 421 /* 422 * NtGdiFlush 423 * 424 * Flushes the calling thread's current batch. 425 */ 426 __kernel_entry 427 NTSTATUS 428 APIENTRY 429 NtGdiFlush( 430 VOID) 431 { 432 SynchronizeDriver(GCAPS2_SYNCFLUSH); 433 return STATUS_SUCCESS; 434 } 435 436 /* 437 * NtGdiFlushUserBatch 438 * 439 * Callback for thread batch flush routine. 440 * 441 * Think small & fast! 442 */ 443 NTSTATUS 444 APIENTRY 445 NtGdiFlushUserBatch(VOID) 446 { 447 PTEB pTeb = NtCurrentTeb(); 448 ULONG GdiBatchCount = pTeb->GdiBatchCount; 449 450 if( (GdiBatchCount > 0) && (GdiBatchCount <= (GDIBATCHBUFSIZE/4))) 451 { 452 HDC hDC = (HDC) pTeb->GdiTebBatch.HDC; 453 454 /* If hDC is zero and the buffer fills up with delete objects we need 455 to run anyway. 456 */ 457 if (hDC || GdiBatchCount) 458 { 459 PCHAR pHdr = (PCHAR)&pTeb->GdiTebBatch.Buffer[0]; 460 PDC pDC = NULL; 461 462 if (GDI_HANDLE_GET_TYPE(hDC) == GDILoObjType_LO_DC_TYPE && GreIsHandleValid(hDC)) 463 { 464 pDC = DC_LockDc(hDC); 465 } 466 467 // No need to init anything, just go! 468 for (; GdiBatchCount > 0; GdiBatchCount--) 469 { 470 ULONG Size; 471 // Process Gdi Batch! 472 Size = GdiFlushUserBatch(pDC, (PGDIBATCHHDR) pHdr); 473 if (!Size) break; 474 pHdr += Size; 475 } 476 477 if (pDC) 478 { 479 DC_UnlockDc(pDC); 480 } 481 482 // Exit and clear out for the next round. 483 pTeb->GdiTebBatch.Offset = 0; 484 pTeb->GdiBatchCount = 0; 485 pTeb->GdiTebBatch.HDC = 0; 486 } 487 } 488 489 // FIXME: On Windows XP the function returns &pTeb->RealClientId, maybe VOID? 490 return STATUS_SUCCESS; 491 } 492 493 494