1 /* 2 * COPYRIGHT: See COPYING in the top level directory 3 * PROJECT: ReactOS kernel 4 * PURPOSE: Functions for creation and destruction of DCs 5 * FILE: win32ss/gdi/ntgdi/dclife.c 6 * PROGRAMER: Timo Kreuzer (timo.kreuzer@rectos.org) 7 */ 8 9 #include <win32k.h> 10 11 #define NDEBUG 12 #include <debug.h> 13 14 // FIXME: Windows uses 0x0012009f 15 #define DIRTY_DEFAULT DIRTY_CHARSET|DIRTY_BACKGROUND|DIRTY_TEXT|DIRTY_LINE|DIRTY_FILL 16 17 PSURFACE psurfDefaultBitmap = NULL; 18 PBRUSH pbrDefaultBrush = NULL; 19 20 const MATRIX gmxWorldToDeviceDefault = 21 { 22 FLOATOBJ_16, FLOATOBJ_0, 23 FLOATOBJ_0, FLOATOBJ_16, 24 FLOATOBJ_0, FLOATOBJ_0, 25 0, 0, 0x4b 26 }; 27 28 const MATRIX gmxDeviceToWorldDefault = 29 { 30 FLOATOBJ_1_16, FLOATOBJ_0, 31 FLOATOBJ_0, FLOATOBJ_1_16, 32 FLOATOBJ_0, FLOATOBJ_0, 33 0, 0, 0x53 34 }; 35 36 const MATRIX gmxWorldToPageDefault = 37 { 38 FLOATOBJ_1, FLOATOBJ_0, 39 FLOATOBJ_0, FLOATOBJ_1, 40 FLOATOBJ_0, FLOATOBJ_0, 41 0, 0, 0x63 42 }; 43 44 // HACK!! Fix XFORMOBJ then use 1:16 / 16:1 45 #define gmxWorldToDeviceDefault gmxWorldToPageDefault 46 #define gmxDeviceToWorldDefault gmxWorldToPageDefault 47 48 /** Internal functions ********************************************************/ 49 50 CODE_SEG("INIT") 51 NTSTATUS 52 NTAPI 53 InitDcImpl(VOID) 54 { 55 psurfDefaultBitmap = SURFACE_ShareLockSurface(StockObjects[DEFAULT_BITMAP]); 56 if (!psurfDefaultBitmap) 57 return STATUS_UNSUCCESSFUL; 58 59 pbrDefaultBrush = BRUSH_ShareLockBrush(StockObjects[BLACK_BRUSH]); 60 if (!pbrDefaultBrush) 61 return STATUS_UNSUCCESSFUL; 62 63 return STATUS_SUCCESS; 64 } 65 66 67 PDC 68 NTAPI 69 DC_AllocDcWithHandle(GDILOOBJTYPE eDcObjType) 70 { 71 PDC pdc; 72 73 NT_ASSERT((eDcObjType == GDILoObjType_LO_DC_TYPE) || 74 (eDcObjType == GDILoObjType_LO_ALTDC_TYPE)); 75 76 /* Allocate the object */ 77 pdc = (PDC)GDIOBJ_AllocateObject(GDIObjType_DC_TYPE, 78 sizeof(DC), 79 BASEFLAG_LOOKASIDE); 80 if (!pdc) 81 { 82 DPRINT1("Could not allocate a DC.\n"); 83 return NULL; 84 } 85 86 /* Set the actual DC type */ 87 pdc->BaseObject.hHmgr = UlongToHandle(eDcObjType); 88 89 pdc->pdcattr = &pdc->dcattr; 90 91 /* Insert the object */ 92 if (!GDIOBJ_hInsertObject(&pdc->BaseObject, GDI_OBJ_HMGR_POWNED)) 93 { 94 DPRINT1("Could not insert DC into handle table.\n"); 95 GDIOBJ_vFreeObject(&pdc->BaseObject); 96 return NULL; 97 } 98 99 return pdc; 100 } 101 102 103 void 104 DC_InitHack(PDC pdc) 105 { 106 if (defaultDCstate == NULL) 107 { 108 defaultDCstate = ExAllocatePoolWithTag(PagedPool, sizeof(DC), TAG_DC); 109 ASSERT(defaultDCstate); 110 RtlZeroMemory(defaultDCstate, sizeof(DC)); 111 defaultDCstate->pdcattr = &defaultDCstate->dcattr; 112 DC_vCopyState(pdc, defaultDCstate, TRUE); 113 } 114 115 if (prgnDefault == NULL) 116 { 117 prgnDefault = IntSysCreateRectpRgn(0, 0, 0, 0); 118 } 119 120 TextIntRealizeFont(pdc->pdcattr->hlfntNew,NULL); 121 pdc->pdcattr->iCS_CP = ftGdiGetTextCharsetInfo(pdc,NULL,0); 122 123 /* This should never fail */ 124 ASSERT(pdc->dclevel.ppal); 125 } 126 127 VOID 128 NTAPI 129 DC_vInitDc( 130 PDC pdc, 131 DCTYPE dctype, 132 PPDEVOBJ ppdev) 133 { 134 /* Setup some basic fields */ 135 pdc->dctype = dctype; 136 pdc->ppdev = ppdev; 137 pdc->dhpdev = ppdev->dhpdev; 138 pdc->hsem = ppdev->hsemDevLock; 139 pdc->flGraphicsCaps = ppdev->devinfo.flGraphicsCaps; 140 pdc->flGraphicsCaps2 = ppdev->devinfo.flGraphicsCaps2; 141 pdc->fs = DC_DIRTY_RAO; 142 143 /* Setup dc attribute */ 144 pdc->pdcattr = &pdc->dcattr; 145 pdc->dcattr.pvLDC = NULL; 146 pdc->dcattr.ulDirty_ = DIRTY_DEFAULT; 147 if (ppdev == gppdevPrimary) 148 pdc->dcattr.ulDirty_ |= DC_PRIMARY_DISPLAY; 149 150 /* Setup the DC size */ 151 if (dctype == DCTYPE_MEMORY) 152 { 153 /* Memory DCs have a 1 x 1 bitmap by default */ 154 pdc->dclevel.sizl.cx = 1; 155 pdc->dclevel.sizl.cy = 1; 156 } 157 else 158 { 159 /* Other DC's are as big as the related PDEV */ 160 pdc->dclevel.sizl.cx = ppdev->gdiinfo.ulHorzRes; 161 pdc->dclevel.sizl.cy = ppdev->gdiinfo.ulVertRes; 162 } 163 164 /* Setup Window rect based on DC size */ 165 pdc->erclWindow.left = 0; 166 pdc->erclWindow.top = 0; 167 pdc->erclWindow.right = pdc->dclevel.sizl.cx; 168 pdc->erclWindow.bottom = pdc->dclevel.sizl.cy; 169 170 if (dctype == DCTYPE_DIRECT) 171 { 172 /* Direct DCs get the surface from the PDEV */ 173 pdc->dclevel.pSurface = PDEVOBJ_pSurface(ppdev); 174 175 pdc->erclBounds.left = 0x7fffffff; 176 pdc->erclBounds.top = 0x7fffffff; 177 pdc->erclBounds.right = 0x80000000; 178 pdc->erclBounds.bottom = 0x80000000; 179 pdc->erclBoundsApp.left = 0xffffffff; 180 pdc->erclBoundsApp.top = 0xfffffffc; 181 pdc->erclBoundsApp.right = 0x00007ffc; // FIXME 182 pdc->erclBoundsApp.bottom = 0x00000333; // FIXME 183 pdc->erclClip = pdc->erclBounds; 184 pdc->co = gxcoTrivial; 185 } 186 else 187 { 188 /* Non-direct DCs don't have a surface by default */ 189 pdc->dclevel.pSurface = NULL; 190 191 pdc->erclBounds.left = 0; 192 pdc->erclBounds.top = 0; 193 pdc->erclBounds.right = 0; 194 pdc->erclBounds.bottom = 0; 195 pdc->erclBoundsApp = pdc->erclBounds; 196 pdc->erclClip = pdc->erclWindow; 197 pdc->co = gxcoTrivial; 198 } 199 200 //pdc->dcattr.VisRectRegion: 201 202 /* Setup coordinate transformation data */ 203 pdc->dclevel.mxWorldToDevice = gmxWorldToDeviceDefault; 204 pdc->dclevel.mxDeviceToWorld = gmxDeviceToWorldDefault; 205 pdc->dclevel.mxWorldToPage = gmxWorldToPageDefault; 206 pdc->dclevel.efM11PtoD = gef16; 207 pdc->dclevel.efM22PtoD = gef16; 208 pdc->dclevel.efDxPtoD = gef0; 209 pdc->dclevel.efDyPtoD = gef0; 210 pdc->dclevel.efM11_TWIPS = gef0; 211 pdc->dclevel.efM22_TWIPS = gef0; 212 pdc->dclevel.efPr11 = gef0; 213 pdc->dclevel.efPr22 = gef0; 214 pdc->dcattr.mxWorldToDevice = pdc->dclevel.mxWorldToDevice; 215 pdc->dcattr.mxDeviceToWorld = pdc->dclevel.mxDeviceToWorld; 216 pdc->dcattr.mxWorldToPage = pdc->dclevel.mxWorldToPage; 217 pdc->dcattr.efM11PtoD = pdc->dclevel.efM11PtoD; 218 pdc->dcattr.efM22PtoD = pdc->dclevel.efM22PtoD; 219 pdc->dcattr.efDxPtoD = pdc->dclevel.efDxPtoD; 220 pdc->dcattr.efDyPtoD = pdc->dclevel.efDyPtoD; 221 pdc->dcattr.iMapMode = MM_TEXT; 222 pdc->dcattr.dwLayout = 0; 223 pdc->dcattr.flXform = PAGE_TO_DEVICE_SCALE_IDENTITY | 224 PAGE_TO_DEVICE_IDENTITY | 225 WORLD_TO_PAGE_IDENTITY; 226 227 /* Setup more coordinates */ 228 pdc->ptlDCOrig.x = 0; 229 pdc->ptlDCOrig.y = 0; 230 pdc->dcattr.lWindowOrgx = 0; 231 pdc->dcattr.ptlWindowOrg.x = 0; 232 pdc->dcattr.ptlWindowOrg.y = 0; 233 pdc->dcattr.szlWindowExt.cx = 1; 234 pdc->dcattr.szlWindowExt.cy = 1; 235 pdc->dcattr.ptlViewportOrg.x = 0; 236 pdc->dcattr.ptlViewportOrg.y = 0; 237 pdc->dcattr.szlViewportExt.cx = 1; 238 pdc->dcattr.szlViewportExt.cy = 1; 239 pdc->dcattr.szlVirtualDevicePixel.cx = ppdev->gdiinfo.ulHorzRes; 240 pdc->dcattr.szlVirtualDevicePixel.cy = ppdev->gdiinfo.ulVertRes; 241 pdc->dcattr.szlVirtualDeviceMm.cx = ppdev->gdiinfo.ulHorzSize; 242 pdc->dcattr.szlVirtualDeviceMm.cy = ppdev->gdiinfo.ulVertSize; 243 pdc->dcattr.szlVirtualDeviceSize.cx = 0; 244 pdc->dcattr.szlVirtualDeviceSize.cy = 0; 245 246 /* Setup regions */ 247 pdc->prgnAPI = NULL; 248 pdc->prgnRao = NULL; 249 pdc->dclevel.prgnClip = NULL; 250 pdc->dclevel.prgnMeta = NULL; 251 /* Allocate a Vis region */ 252 pdc->prgnVis = IntSysCreateRectpRgn(0, 0, pdc->dclevel.sizl.cx, pdc->dclevel.sizl.cy); 253 ASSERT(pdc->prgnVis); 254 255 /* Setup Vis Region Attribute information */ 256 UpdateVisRgn(pdc); 257 258 /* Initialize Clip object */ 259 IntEngInitClipObj(&pdc->co); 260 261 /* Setup palette */ 262 pdc->dclevel.hpal = StockObjects[DEFAULT_PALETTE]; 263 pdc->dclevel.ppal = PALETTE_ShareLockPalette(pdc->dclevel.hpal); 264 265 /* Setup path */ 266 pdc->dclevel.hPath = NULL; 267 pdc->dclevel.flPath = 0; 268 // pdc->dclevel.lapath: 269 270 /* Setup colors */ 271 pdc->dcattr.crBackgroundClr = RGB(0xff, 0xff, 0xff); 272 pdc->dcattr.ulBackgroundClr = RGB(0xff, 0xff, 0xff); 273 pdc->dcattr.crForegroundClr = RGB(0, 0, 0); 274 pdc->dcattr.ulForegroundClr = RGB(0, 0, 0); 275 pdc->dcattr.crBrushClr = RGB(0xff, 0xff, 0xff); 276 pdc->dcattr.ulBrushClr = RGB(0xff, 0xff, 0xff); 277 pdc->dcattr.crPenClr = RGB(0, 0, 0); 278 pdc->dcattr.ulPenClr = RGB(0, 0, 0); 279 280 /* Select the default fill and line brush */ 281 pdc->dcattr.hbrush = StockObjects[WHITE_BRUSH]; 282 pdc->dcattr.hpen = StockObjects[BLACK_PEN]; 283 pdc->dclevel.pbrFill = BRUSH_ShareLockBrush(pdc->pdcattr->hbrush); 284 pdc->dclevel.pbrLine = PEN_ShareLockPen(pdc->pdcattr->hpen); 285 pdc->dclevel.ptlBrushOrigin.x = 0; 286 pdc->dclevel.ptlBrushOrigin.y = 0; 287 pdc->dcattr.ptlBrushOrigin = pdc->dclevel.ptlBrushOrigin; 288 289 /* Initialize EBRUSHOBJs */ 290 EBRUSHOBJ_vInitFromDC(&pdc->eboFill, pdc->dclevel.pbrFill, pdc); 291 EBRUSHOBJ_vInitFromDC(&pdc->eboLine, pdc->dclevel.pbrLine, pdc); 292 EBRUSHOBJ_vInitFromDC(&pdc->eboText, pbrDefaultBrush, pdc); 293 EBRUSHOBJ_vInitFromDC(&pdc->eboBackground, pbrDefaultBrush, pdc); 294 295 /* Setup fill data */ 296 pdc->dcattr.jROP2 = R2_COPYPEN; 297 pdc->dcattr.jBkMode = 2; 298 pdc->dcattr.lBkMode = 2; 299 pdc->dcattr.jFillMode = ALTERNATE; 300 pdc->dcattr.lFillMode = 1; 301 pdc->dcattr.jStretchBltMode = 1; 302 pdc->dcattr.lStretchBltMode = 1; 303 pdc->ptlFillOrigin.x = 0; 304 pdc->ptlFillOrigin.y = 0; 305 306 /* Setup drawing position */ 307 pdc->dcattr.ptlCurrent.x = 0; 308 pdc->dcattr.ptlCurrent.y = 0; 309 pdc->dcattr.ptfxCurrent.x = 0; 310 pdc->dcattr.ptfxCurrent.y = 0; 311 312 /* Setup ICM data */ 313 pdc->dclevel.lIcmMode = 0; 314 pdc->dcattr.lIcmMode = 0; 315 pdc->dcattr.hcmXform = NULL; 316 pdc->dcattr.flIcmFlags = 0; 317 pdc->dcattr.IcmBrushColor = CLR_INVALID; 318 pdc->dcattr.IcmPenColor = CLR_INVALID; 319 pdc->dcattr.pvLIcm = NULL; 320 pdc->dcattr.hColorSpace = NULL; // FIXME: 0189001f 321 pdc->dclevel.pColorSpace = NULL; // FIXME 322 pdc->pClrxFormLnk = NULL; 323 // pdc->dclevel.ca = 324 325 /* Setup font data */ 326 pdc->hlfntCur = NULL; // FIXME: 2f0a0cf8 327 pdc->pPFFList = NULL; 328 pdc->flSimulationFlags = 0; 329 pdc->lEscapement = 0; 330 pdc->prfnt = NULL; 331 pdc->dcattr.flFontMapper = 0; 332 pdc->dcattr.flTextAlign = 0; 333 pdc->dcattr.lTextAlign = 0; 334 pdc->dcattr.lTextExtra = 0; 335 pdc->dcattr.lRelAbs = 1; 336 pdc->dcattr.lBreakExtra = 0; 337 pdc->dcattr.cBreak = 0; 338 pdc->dcattr.hlfntNew = StockObjects[SYSTEM_FONT]; 339 pdc->dclevel.plfnt = LFONT_ShareLockFont(pdc->dcattr.hlfntNew); 340 341 /* Other stuff */ 342 pdc->hdcNext = NULL; 343 pdc->hdcPrev = NULL; 344 pdc->ipfdDevMax = 0; 345 pdc->ulCopyCount = -1; 346 pdc->ptlDoBanding.x = 0; 347 pdc->ptlDoBanding.y = 0; 348 pdc->dclevel.lSaveDepth = 1; 349 pdc->dclevel.hdcSave = NULL; 350 pdc->dcattr.iGraphicsMode = GM_COMPATIBLE; 351 pdc->dcattr.iCS_CP = 0; 352 pdc->pSurfInfo = NULL; 353 } 354 355 VOID 356 NTAPI 357 DC_vCleanup(PVOID ObjectBody) 358 { 359 PDC pdc = (PDC)ObjectBody; 360 361 /* Free DC_ATTR */ 362 DC_vFreeDcAttr(pdc); 363 364 /* Delete saved DCs */ 365 DC_vRestoreDC(pdc, 1); 366 367 /* Deselect dc objects */ 368 DC_vSelectSurface(pdc, NULL); 369 DC_vSelectFillBrush(pdc, NULL); 370 DC_vSelectLineBrush(pdc, NULL); 371 DC_vSelectPalette(pdc, NULL); 372 373 /* Cleanup the dc brushes */ 374 EBRUSHOBJ_vCleanup(&pdc->eboFill); 375 EBRUSHOBJ_vCleanup(&pdc->eboLine); 376 EBRUSHOBJ_vCleanup(&pdc->eboText); 377 EBRUSHOBJ_vCleanup(&pdc->eboBackground); 378 379 /* Release font */ 380 if (pdc->dclevel.plfnt) 381 LFONT_ShareUnlockFont(pdc->dclevel.plfnt); 382 383 /* Free regions */ 384 if (pdc->dclevel.prgnClip) 385 REGION_Delete(pdc->dclevel.prgnClip); 386 if (pdc->dclevel.prgnMeta) 387 REGION_Delete(pdc->dclevel.prgnMeta); 388 if (pdc->prgnVis) 389 REGION_Delete(pdc->prgnVis); 390 if (pdc->prgnRao) 391 REGION_Delete(pdc->prgnRao); 392 if (pdc->prgnAPI) 393 REGION_Delete(pdc->prgnAPI); 394 395 /* Free CLIPOBJ resources */ 396 IntEngFreeClipResources(&pdc->co); 397 398 if (pdc->dclevel.hPath) 399 { 400 DPRINT("DC_vCleanup Path\n"); 401 PATH_Delete(pdc->dclevel.hPath); 402 pdc->dclevel.hPath = 0; 403 pdc->dclevel.flPath = 0; 404 } 405 if (pdc->dclevel.pSurface) 406 SURFACE_ShareUnlockSurface(pdc->dclevel.pSurface); 407 408 if (pdc->ppdev) 409 PDEVOBJ_vRelease(pdc->ppdev); 410 } 411 412 VOID 413 NTAPI 414 DC_vSetOwner(PDC pdc, ULONG ulOwner) 415 { 416 /* Delete saved DCs */ 417 DC_vRestoreDC(pdc, 1); 418 419 if (pdc->dclevel.hPath) 420 { 421 GreSetObjectOwner(pdc->dclevel.hPath, ulOwner); 422 } 423 424 /* Dereference current brush and pen */ 425 BRUSH_ShareUnlockBrush(pdc->dclevel.pbrFill); 426 BRUSH_ShareUnlockBrush(pdc->dclevel.pbrLine); 427 428 /* Select the default fill and line brush */ 429 pdc->dcattr.hbrush = StockObjects[WHITE_BRUSH]; 430 pdc->dcattr.hpen = StockObjects[BLACK_PEN]; 431 pdc->dclevel.pbrFill = BRUSH_ShareLockBrush(pdc->pdcattr->hbrush); 432 pdc->dclevel.pbrLine = PEN_ShareLockPen(pdc->pdcattr->hpen); 433 434 /* Mark them as dirty */ 435 pdc->pdcattr->ulDirty_ |= DIRTY_FILL|DIRTY_LINE; 436 437 /* Allocate or free DC attribute */ 438 if (ulOwner == GDI_OBJ_HMGR_PUBLIC || ulOwner == GDI_OBJ_HMGR_NONE) 439 { 440 if (pdc->pdcattr != &pdc->dcattr) 441 DC_vFreeDcAttr(pdc); 442 } 443 else if (ulOwner == GDI_OBJ_HMGR_POWNED) 444 { 445 if (pdc->pdcattr == &pdc->dcattr) 446 DC_bAllocDcAttr(pdc); 447 } 448 449 /* Set the DC's ownership */ 450 GDIOBJ_vSetObjectOwner(&pdc->BaseObject, ulOwner); 451 } 452 453 BOOL 454 NTAPI 455 GreSetDCOwner(HDC hdc, ULONG ulOwner) 456 { 457 PDC pdc; 458 459 pdc = DC_LockDc(hdc); 460 if (!pdc) 461 { 462 DPRINT1("GreSetDCOwner: Could not lock DC\n"); 463 return FALSE; 464 } 465 466 /* Call the internal DC function */ 467 DC_vSetOwner(pdc, ulOwner); 468 469 DC_UnlockDc(pdc); 470 return TRUE; 471 } 472 473 static 474 void 475 DC_vUpdateDC(PDC pdc) 476 { 477 // PREGION VisRgn ; 478 PPDEVOBJ ppdev = pdc->ppdev; 479 480 pdc->dhpdev = ppdev->dhpdev; 481 482 SURFACE_ShareUnlockSurface(pdc->dclevel.pSurface); 483 pdc->dclevel.pSurface = PDEVOBJ_pSurface(ppdev); 484 485 PDEVOBJ_sizl(pdc->ppdev, &pdc->dclevel.sizl); 486 #if 0 487 VisRgn = IntSysCreateRectpRgn(0, 0, pdc->dclevel.sizl.cx, pdc->dclevel.sizl.cy); 488 ASSERT(VisRgn); 489 GdiSelectVisRgn(pdc->BaseObject.hHmgr, VisRgn); 490 REGION_Delete(VisRgn); 491 #endif 492 493 pdc->flGraphicsCaps = ppdev->devinfo.flGraphicsCaps; 494 pdc->flGraphicsCaps2 = ppdev->devinfo.flGraphicsCaps2; 495 496 /* Mark EBRUSHOBJs as dirty */ 497 pdc->pdcattr->ulDirty_ |= DIRTY_DEFAULT ; 498 } 499 500 /* Prepare a blit for up to 2 DCs */ 501 /* rc1 and rc2 are the rectangles where we want to draw or 502 * from where we take pixels. */ 503 VOID 504 FASTCALL 505 DC_vPrepareDCsForBlit( 506 PDC pdcDest, 507 const RECT* rcDest, 508 PDC pdcSrc, 509 const RECT* rcSrc) 510 { 511 PDC pdcFirst, pdcSecond; 512 const RECT *prcFirst, *prcSecond; 513 514 /* Update brushes */ 515 if (pdcDest->pdcattr->ulDirty_ & (DIRTY_FILL | DC_BRUSH_DIRTY)) 516 DC_vUpdateFillBrush(pdcDest); 517 if (pdcDest->pdcattr->ulDirty_ & (DIRTY_LINE | DC_PEN_DIRTY)) 518 DC_vUpdateLineBrush(pdcDest); 519 if(pdcDest->pdcattr->ulDirty_ & DIRTY_TEXT) 520 DC_vUpdateTextBrush(pdcDest); 521 522 /* Lock them in good order */ 523 if (pdcSrc) 524 { 525 if((ULONG_PTR)pdcDest->ppdev->hsemDevLock >= 526 (ULONG_PTR)pdcSrc->ppdev->hsemDevLock) 527 { 528 pdcFirst = pdcDest; 529 prcFirst = rcDest; 530 pdcSecond = pdcSrc; 531 prcSecond = rcSrc; 532 } 533 else 534 { 535 pdcFirst = pdcSrc; 536 prcFirst = rcSrc; 537 pdcSecond = pdcDest; 538 prcSecond = rcDest; 539 } 540 } 541 else 542 { 543 pdcFirst = pdcDest; 544 prcFirst = rcDest; 545 pdcSecond = NULL; 546 prcSecond = NULL; 547 } 548 549 if (pdcDest->fs & DC_FLAG_DIRTY_RAO) 550 CLIPPING_UpdateGCRegion(pdcDest); 551 552 /* Lock and update first DC */ 553 if (pdcFirst->dctype == DCTYPE_DIRECT) 554 { 555 EngAcquireSemaphore(pdcFirst->ppdev->hsemDevLock); 556 557 /* Update surface if needed */ 558 if (pdcFirst->ppdev->pSurface != pdcFirst->dclevel.pSurface) 559 { 560 DC_vUpdateDC(pdcFirst); 561 } 562 } 563 564 if (pdcFirst->dctype == DCTYPE_DIRECT) 565 { 566 if (!prcFirst) 567 prcFirst = &pdcFirst->erclClip; 568 569 MouseSafetyOnDrawStart(pdcFirst->ppdev, 570 prcFirst->left, 571 prcFirst->top, 572 prcFirst->right, 573 prcFirst->bottom) ; 574 } 575 576 #if DBG 577 pdcFirst->fs |= DC_PREPARED; 578 #endif 579 580 if (!pdcSecond) 581 return; 582 583 /* Lock and update second DC */ 584 if (pdcSecond->dctype == DCTYPE_DIRECT) 585 { 586 EngAcquireSemaphore(pdcSecond->ppdev->hsemDevLock); 587 588 /* Update surface if needed */ 589 if (pdcSecond->ppdev->pSurface != pdcSecond->dclevel.pSurface) 590 { 591 DC_vUpdateDC(pdcSecond); 592 } 593 } 594 595 if (pdcSecond->dctype == DCTYPE_DIRECT) 596 { 597 if (!prcSecond) 598 prcSecond = &pdcSecond->erclClip; 599 MouseSafetyOnDrawStart(pdcSecond->ppdev, 600 prcSecond->left, 601 prcSecond->top, 602 prcSecond->right, 603 prcSecond->bottom) ; 604 } 605 606 #if DBG 607 pdcSecond->fs |= DC_PREPARED; 608 #endif 609 } 610 611 /* Finishes a blit for one or two DCs */ 612 VOID 613 FASTCALL 614 DC_vFinishBlit(PDC pdc1, PDC pdc2) 615 { 616 if (pdc1->dctype == DCTYPE_DIRECT) 617 { 618 MouseSafetyOnDrawEnd(pdc1->ppdev); 619 EngReleaseSemaphore(pdc1->ppdev->hsemDevLock); 620 } 621 #if DBG 622 pdc1->fs &= ~DC_PREPARED; 623 #endif 624 625 if (pdc2) 626 { 627 if (pdc2->dctype == DCTYPE_DIRECT) 628 { 629 MouseSafetyOnDrawEnd(pdc2->ppdev); 630 EngReleaseSemaphore(pdc2->ppdev->hsemDevLock); 631 } 632 #if DBG 633 pdc2->fs &= ~DC_PREPARED; 634 #endif 635 } 636 } 637 638 HDC 639 NTAPI 640 GreOpenDCW( 641 PUNICODE_STRING pustrDevice, 642 DEVMODEW *pdmInit, 643 PUNICODE_STRING pustrLogAddr, 644 ULONG iType, 645 BOOL bDisplay, 646 HANDLE hspool, 647 VOID *pDriverInfo2, 648 PVOID *pUMdhpdev) 649 { 650 PPDEVOBJ ppdev; 651 PDC pdc; 652 HDC hdc; 653 654 DPRINT("GreOpenDCW(%S, iType=%lu)\n", 655 pustrDevice ? pustrDevice->Buffer : NULL, iType); 656 657 /* Get a PDEVOBJ for the device */ 658 ppdev = EngpGetPDEV(pustrDevice); 659 if (!ppdev) 660 { 661 DPRINT1("Didn't find a suitable PDEV\n"); 662 return NULL; 663 } 664 665 DPRINT("GreOpenDCW - ppdev = %p\n", ppdev); 666 667 pdc = DC_AllocDcWithHandle(GDILoObjType_LO_DC_TYPE); 668 if (!pdc) 669 { 670 DPRINT1("Could not Allocate a DC\n"); 671 PDEVOBJ_vRelease(ppdev); 672 return NULL; 673 } 674 hdc = pdc->BaseObject.hHmgr; 675 676 /* Lock ppdev and initialize the new DC */ 677 DC_vInitDc(pdc, iType, ppdev); 678 if (pUMdhpdev) *pUMdhpdev = ppdev->dhpdev; 679 /* FIXME: HACK! */ 680 DC_InitHack(pdc); 681 682 DC_bAllocDcAttr(pdc); 683 684 DC_UnlockDc(pdc); 685 686 DPRINT("Returning hdc = %p\n", hdc); 687 688 return hdc; 689 } 690 691 __kernel_entry 692 HDC 693 APIENTRY 694 NtGdiOpenDCW( 695 _In_opt_ PUNICODE_STRING pustrDevice, 696 _In_ DEVMODEW *pdmInit, 697 _In_ PUNICODE_STRING pustrLogAddr, 698 _In_ ULONG iType, 699 _In_ BOOL bDisplay, 700 _In_opt_ HANDLE hspool, 701 /*_In_opt_ DRIVER_INFO2W *pdDriverInfo2, Need this soon!!!! */ 702 _At_((PUMDHPDEV*)pUMdhpdev, _Out_) PVOID pUMdhpdev) 703 { 704 UNICODE_STRING ustrDevice; 705 WCHAR awcDevice[CCHDEVICENAME]; 706 PVOID dhpdev; 707 HDC hdc; 708 WORD dmSize, dmDriverExtra; 709 DWORD Size; 710 DEVMODEW * _SEH2_VOLATILE pdmAllocated = NULL; 711 712 /* Only if a devicename is given, we need any data */ 713 if (pustrDevice) 714 { 715 /* Initialize destination string */ 716 RtlInitEmptyUnicodeString(&ustrDevice, awcDevice, sizeof(awcDevice)); 717 718 _SEH2_TRY 719 { 720 /* Probe the UNICODE_STRING and the buffer */ 721 ProbeForRead(pustrDevice, sizeof(UNICODE_STRING), 1); 722 ProbeForRead(pustrDevice->Buffer, pustrDevice->Length, 1); 723 724 /* Copy the string */ 725 RtlCopyUnicodeString(&ustrDevice, pustrDevice); 726 727 /* Allocate and store pdmAllocated if pdmInit is not NULL */ 728 if (pdmInit) 729 { 730 ProbeForRead(pdmInit, sizeof(DEVMODEW), 1); 731 732 dmSize = pdmInit->dmSize; 733 dmDriverExtra = pdmInit->dmDriverExtra; 734 Size = dmSize + dmDriverExtra; 735 ProbeForRead(pdmInit, Size, 1); 736 737 pdmAllocated = ExAllocatePoolWithTag(PagedPool | POOL_RAISE_IF_ALLOCATION_FAILURE, 738 Size, 739 TAG_DC); 740 RtlCopyMemory(pdmAllocated, pdmInit, Size); 741 pdmAllocated->dmSize = dmSize; 742 pdmAllocated->dmDriverExtra = dmDriverExtra; 743 } 744 745 if (pUMdhpdev) 746 { 747 ProbeForWrite(pUMdhpdev, sizeof(HANDLE), 1); 748 } 749 } 750 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 751 { 752 if (pdmAllocated) 753 { 754 ExFreePoolWithTag(pdmAllocated, TAG_DC); 755 } 756 SetLastNtError(_SEH2_GetExceptionCode()); 757 _SEH2_YIELD(return NULL); 758 } 759 _SEH2_END 760 } 761 else 762 { 763 pdmInit = NULL; 764 pUMdhpdev = NULL; 765 // return UserGetDesktopDC(iType, FALSE, TRUE); 766 } 767 768 /* FIXME: HACK! */ 769 if (pustrDevice) 770 { 771 UNICODE_STRING ustrDISPLAY = RTL_CONSTANT_STRING(L"DISPLAY"); 772 if (RtlEqualUnicodeString(&ustrDevice, &ustrDISPLAY, TRUE)) 773 { 774 pustrDevice = NULL; 775 } 776 } 777 778 /* Call the internal function */ 779 hdc = GreOpenDCW(pustrDevice ? &ustrDevice : NULL, 780 pdmAllocated, 781 NULL, // FIXME: pwszLogAddress 782 iType, 783 bDisplay, 784 hspool, 785 NULL, // FIXME: pDriverInfo2 786 pUMdhpdev ? &dhpdev : NULL); 787 788 /* If we got a HDC and a UM dhpdev is requested,... */ 789 if (hdc && pUMdhpdev) 790 { 791 /* Copy dhpdev to caller */ 792 _SEH2_TRY 793 { 794 /* Pointer was already probed */ 795 *(HANDLE*)pUMdhpdev = dhpdev; 796 } 797 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 798 { 799 /* Ignore error */ 800 (void)0; 801 } 802 _SEH2_END 803 } 804 805 /* Free the allocated */ 806 if (pdmAllocated) 807 { 808 ExFreePoolWithTag(pdmAllocated, TAG_DC); 809 } 810 811 return hdc; 812 } 813 814 815 HDC 816 APIENTRY 817 GreCreateCompatibleDC(HDC hdc, BOOL bAltDc) 818 { 819 GDILOOBJTYPE eDcObjType; 820 HDC hdcNew; 821 PPDEVOBJ ppdev; 822 PDC pdc, pdcNew; 823 824 DPRINT("NtGdiCreateCompatibleDC(0x%p)\n", hdc); 825 826 /* Did the caller provide a DC? */ 827 if (hdc) 828 { 829 /* Yes, try to lock it */ 830 pdc = DC_LockDc(hdc); 831 if (!pdc) 832 { 833 DPRINT1("Could not lock source DC %p\n", hdc); 834 return NULL; 835 } 836 837 /* Get the pdev from the DC */ 838 ppdev = pdc->ppdev; 839 PDEVOBJ_vReference(ppdev); 840 841 /* Unlock the source DC */ 842 DC_UnlockDc(pdc); 843 } 844 else 845 { 846 /* No DC given, get default device */ 847 ppdev = EngpGetPDEV(NULL); 848 } 849 850 if (!ppdev) 851 { 852 DPRINT1("Didn't find a suitable PDEV\n"); 853 return NULL; 854 } 855 856 /* Allocate a new DC */ 857 eDcObjType = bAltDc ? GDILoObjType_LO_ALTDC_TYPE : GDILoObjType_LO_DC_TYPE; 858 pdcNew = DC_AllocDcWithHandle(eDcObjType); 859 if (!pdcNew) 860 { 861 DPRINT1("Could not allocate a new DC\n"); 862 PDEVOBJ_vRelease(ppdev); 863 return NULL; 864 } 865 hdcNew = pdcNew->BaseObject.hHmgr; 866 867 /* Lock ppdev and initialize the new DC */ 868 DC_vInitDc(pdcNew, bAltDc ? DCTYPE_INFO : DCTYPE_MEMORY, ppdev); 869 /* FIXME: HACK! */ 870 DC_InitHack(pdcNew); 871 872 /* Allocate a dc attribute */ 873 DC_bAllocDcAttr(pdcNew); 874 875 DC_UnlockDc(pdcNew); 876 877 DPRINT("Leave NtGdiCreateCompatibleDC hdcNew = %p\n", hdcNew); 878 879 return hdcNew; 880 } 881 882 HDC 883 APIENTRY 884 NtGdiCreateCompatibleDC(HDC hdc) 885 { 886 /* Call the internal function to create a normal memory DC */ 887 return GreCreateCompatibleDC(hdc, FALSE); 888 } 889 890 BOOL 891 FASTCALL 892 IntGdiDeleteDC(HDC hDC, BOOL Force) 893 { 894 PDC DCToDelete = DC_LockDc(hDC); 895 896 if (DCToDelete == NULL) 897 { 898 EngSetLastError(ERROR_INVALID_HANDLE); 899 return FALSE; 900 } 901 902 if (!Force) 903 { 904 /* Windows permits NtGdiDeleteObjectApp to delete a permanent DC 905 * For some reason, it's still a valid handle, pointing to some kernel data. 906 * Not sure if this is a bug, a feature, some cache stuff... Who knows? 907 * See NtGdiDeleteObjectApp test for details */ 908 if (DCToDelete->fs & DC_FLAG_PERMANENT) 909 { 910 DC_UnlockDc(DCToDelete); 911 if(UserReleaseDC(NULL, hDC, FALSE)) 912 { 913 /* ReactOS feature: Call UserReleaseDC 914 * I don't think Windows does it. 915 * Still, complain, no one should ever call DeleteDC 916 * on a window DC */ 917 DPRINT1("No, you naughty application!\n"); 918 return TRUE; 919 } 920 else 921 { 922 /* This is not a window owned DC. 923 * Force its deletion */ 924 return IntGdiDeleteDC(hDC, TRUE); 925 } 926 } 927 } 928 929 DC_UnlockDc(DCToDelete); 930 931 if (GreIsHandleValid(hDC)) 932 { 933 if (!GreDeleteObject(hDC)) 934 { 935 DPRINT1("DC_FreeDC failed\n"); 936 return FALSE; 937 } 938 } 939 else 940 { 941 DPRINT1("Attempted to Delete 0x%p currently being destroyed!!!\n", hDC); 942 return FALSE; 943 } 944 945 return TRUE; 946 } 947 948 BOOL 949 APIENTRY 950 NtGdiDeleteObjectApp(HANDLE hobj) 951 { 952 if (GDI_HANDLE_IS_STOCKOBJ(hobj)) return TRUE; 953 954 if (GreGetObjectOwner(hobj) != GDI_OBJ_HMGR_POWNED) 955 { 956 EngSetLastError(ERROR_INVALID_HANDLE); 957 return FALSE; 958 } 959 960 if (GDI_HANDLE_GET_TYPE(hobj) != GDI_OBJECT_TYPE_DC) 961 return GreDeleteObject(hobj); 962 963 // FIXME: Everything should be callback based 964 return IntGdiDeleteDC(hobj, FALSE); 965 } 966 967 BOOL 968 FASTCALL 969 MakeInfoDC(PDC pdc, BOOL bSet) 970 { 971 PSURFACE pSurface; 972 SIZEL sizl; 973 974 /* Can not be a display DC. */ 975 if (pdc->fs & DC_FLAG_DISPLAY) return FALSE; 976 if (bSet) 977 { 978 if (pdc->fs & DC_FLAG_TEMPINFODC || pdc->dctype == DC_TYPE_DIRECT) 979 return FALSE; 980 981 pSurface = pdc->dclevel.pSurface; 982 pdc->fs |= DC_FLAG_TEMPINFODC; 983 pdc->pSurfInfo = pSurface; 984 pdc->dctype = DC_TYPE_INFO; 985 pdc->dclevel.pSurface = NULL; 986 987 PDEVOBJ_sizl(pdc->ppdev, &sizl); 988 989 if ( sizl.cx == pdc->dclevel.sizl.cx && 990 sizl.cy == pdc->dclevel.sizl.cy ) 991 return TRUE; 992 993 pdc->dclevel.sizl.cx = sizl.cx; 994 pdc->dclevel.sizl.cy = sizl.cy; 995 } 996 else 997 { 998 if (!(pdc->fs & DC_FLAG_TEMPINFODC) || pdc->dctype != DC_TYPE_INFO) 999 return FALSE; 1000 1001 pSurface = pdc->pSurfInfo; 1002 pdc->fs &= ~DC_FLAG_TEMPINFODC; 1003 pdc->dclevel.pSurface = pSurface; 1004 pdc->dctype = DC_TYPE_DIRECT; 1005 pdc->pSurfInfo = NULL; 1006 1007 if ( !pSurface || 1008 (pSurface->SurfObj.sizlBitmap.cx == pdc->dclevel.sizl.cx && 1009 pSurface->SurfObj.sizlBitmap.cy == pdc->dclevel.sizl.cy) ) 1010 return TRUE; 1011 1012 pdc->dclevel.sizl.cx = pSurface->SurfObj.sizlBitmap.cx; 1013 pdc->dclevel.sizl.cy = pSurface->SurfObj.sizlBitmap.cy; 1014 } 1015 return IntSetDefaultRegion(pdc); 1016 } 1017 1018 /* 1019 * @implemented 1020 */ 1021 BOOL 1022 APIENTRY 1023 NtGdiMakeInfoDC( 1024 IN HDC hdc, 1025 IN BOOL bSet) 1026 { 1027 BOOL Ret; 1028 PDC pdc = DC_LockDc(hdc); 1029 if (pdc) 1030 { 1031 Ret = MakeInfoDC(pdc, bSet); 1032 DC_UnlockDc(pdc); 1033 return Ret; 1034 } 1035 return FALSE; 1036 } 1037 1038 1039 HDC FASTCALL 1040 IntGdiCreateDC( 1041 PUNICODE_STRING Driver, 1042 PUNICODE_STRING pustrDevice, 1043 PVOID pUMdhpdev, 1044 CONST PDEVMODEW pdmInit, 1045 BOOL CreateAsIC) 1046 { 1047 HDC hdc; 1048 1049 hdc = GreOpenDCW(pustrDevice, 1050 pdmInit, 1051 NULL, 1052 CreateAsIC ? DCTYPE_INFO : 1053 (Driver ? DC_TYPE_DIRECT : DC_TYPE_DIRECT), 1054 TRUE, 1055 NULL, 1056 NULL, 1057 pUMdhpdev); 1058 1059 return hdc; 1060 } 1061 1062 HDC FASTCALL 1063 IntGdiCreateDisplayDC(HDEV hDev, ULONG DcType, BOOL EmptyDC) 1064 { 1065 HDC hDC; 1066 UNIMPLEMENTED; 1067 ASSERT(FALSE); 1068 1069 if (DcType == DC_TYPE_MEMORY) 1070 hDC = NtGdiCreateCompatibleDC(NULL); // OH~ Yuck! I think I taste vomit in my mouth! 1071 else 1072 hDC = IntGdiCreateDC(NULL, NULL, NULL, NULL, (DcType == DC_TYPE_INFO)); 1073 1074 return hDC; 1075 } 1076 1077