From 3c30e5af661ca1bbc47a3b6a3a778adfff4db9e4 Mon Sep 17 00:00:00 2001 From: Timo Kreuzer Date: Tue, 30 Dec 2014 19:38:07 +0000 Subject: [PATCH] [WIN32K] - Rewrite NtGdiInvertRgn to not violate locking order - Remove DceUpdateVisRgn from DC_vPrepareDCsForBlit: It is not GDI's task to handle Window clipping, it violates locking order, it's slow, it's ugly to call USER functions from GDI internals, it's a hack. I couldn't see any clipping regression, if you find anything, let me know. svn path=/trunk/; revision=65910 --- reactos/win32ss/gdi/ntgdi/bitblt.c | 125 ++++++++++++++++++++++++----- reactos/win32ss/gdi/ntgdi/dclife.c | 20 ++--- 2 files changed, 114 insertions(+), 31 deletions(-) diff --git a/reactos/win32ss/gdi/ntgdi/bitblt.c b/reactos/win32ss/gdi/ntgdi/bitblt.c index c4cddac209e..3e2cd5a5c0a 100644 --- a/reactos/win32ss/gdi/ntgdi/bitblt.c +++ b/reactos/win32ss/gdi/ntgdi/bitblt.c @@ -1024,6 +1024,81 @@ REGION_LPTODP( return REGION_bXformRgn(prgnDest, DC_pmxWorldToDevice(pdc)); } +BOOL +APIENTRY +IntGdiBitBltRgn( + _In_ PDC pdc, + _In_ PREGION prgn, + _In_opt_ BRUSHOBJ *pbo, + _In_opt_ POINTL *pptlBrush, + _In_ ROP4 rop4) +{ + PREGION prgnClip; + XCLIPOBJ xcoClip; + BOOL bResult; + PSURFACE psurf; + NT_ASSERT((pdc != NULL) && (prgn != NULL)); + + /* Get the surface */ + psurf = pdc->dclevel.pSurface; + if (psurf == NULL) + { + return TRUE; + } + + /* Create an empty clip region */ + prgnClip = IntSysCreateRectpRgn(0, 0, 0, 0); + if (prgnClip == NULL) + { + return FALSE; + } + + /* Transform given region into device coordinates */ + if (!REGION_LPTODP(pdc, prgnClip, prgn) || + !REGION_bOffsetRgn(prgnClip, pdc->ptlDCOrig.x, pdc->ptlDCOrig.y)) + { + REGION_Delete(prgnClip); + return FALSE; + } + + /* Intersect with the system or RAO region */ + if (pdc->prgnRao) + IntGdiCombineRgn(prgnClip, prgnClip, pdc->prgnRao, RGN_AND); + else + IntGdiCombineRgn(prgnClip, prgnClip, pdc->prgnVis, RGN_AND); + + /* Initialize a clip object */ + IntEngInitClipObj(&xcoClip); + IntEngUpdateClipRegion(&xcoClip, + prgnClip->rdh.nCount, + prgnClip->Buffer, + &prgnClip->rdh.rcBound); + + /* Prepare the DC */ + DC_vPrepareDCsForBlit(pdc, &prgnClip->rdh.rcBound, NULL, NULL); + + /* Call the Eng or Drv function */ + bResult = IntEngBitBlt(&psurf->SurfObj, + NULL, + NULL, + &xcoClip.ClipObj, + NULL, + &prgnClip->rdh.rcBound, + NULL, + NULL, + pbo, + pptlBrush, + rop4); + + /* Cleanup */ + DC_vFinishBlit(pdc, NULL); + REGION_Delete(prgnClip); + IntEngFreeClipResources(&xcoClip); + + /* Return the result */ + return bResult; +} + BOOL IntGdiFillRgn( _In_ PDC pdc, @@ -1190,34 +1265,48 @@ NtGdiFrameRgn( BOOL APIENTRY NtGdiInvertRgn( - HDC hDC, - HRGN hRgn) + _In_ HDC hdc, + _In_ HRGN hrgn) { - PREGION RgnData; - ULONG i; - PRECTL rc; + BOOL bResult; + PDC pdc; + PREGION prgn; - RgnData = REGION_LockRgn(hRgn); - if (RgnData == NULL) + /* Lock the DC */ + pdc = DC_LockDc(hdc); + if (pdc == NULL) { EngSetLastError(ERROR_INVALID_HANDLE); return FALSE; } - rc = RgnData->Buffer; - for (i = 0; i < RgnData->rdh.nCount; i++) + /* Check if the DC has no surface (empty mem or info DC) */ + if (pdc->dclevel.pSurface == NULL) { - - if (!NtGdiPatBlt(hDC, rc->left, rc->top, rc->right - rc->left, rc->bottom - rc->top, DSTINVERT)) - { - REGION_UnlockRgn(RgnData); - return FALSE; - } - rc++; + /* Nothing to do, Windows returns TRUE! */ + DC_UnlockDc(pdc); + return TRUE; } - REGION_UnlockRgn(RgnData); - return TRUE; + /* Lock the region */ + prgn = REGION_LockRgn(hrgn); + if (prgn == NULL) + { + DC_UnlockDc(pdc); + return FALSE; + } + + /* Call the internal function */ + bResult = IntGdiBitBltRgn(pdc, + prgn, + NULL, // pbo + NULL, // pptlBrush, + ROP_TO_ROP4(DSTINVERT)); + + /* Unlock the region and DC and return the result */ + REGION_UnlockRgn(prgn); + DC_UnlockDc(pdc); + return bResult; } COLORREF diff --git a/reactos/win32ss/gdi/ntgdi/dclife.c b/reactos/win32ss/gdi/ntgdi/dclife.c index 22056f34ec3..ffdb0e4fd67 100644 --- a/reactos/win32ss/gdi/ntgdi/dclife.c +++ b/reactos/win32ss/gdi/ntgdi/dclife.c @@ -506,7 +506,8 @@ DC_vPrepareDCsForBlit( /* Lock them in good order */ if(pdcSrc) { - if((ULONG_PTR)pdcDest->ppdev->hsemDevLock >= (ULONG_PTR)pdcSrc->ppdev->hsemDevLock) + if((ULONG_PTR)pdcDest->ppdev->hsemDevLock >= + (ULONG_PTR)pdcSrc->ppdev->hsemDevLock) { pdcFirst = pdcDest; prcFirst = rcDest; @@ -529,19 +530,11 @@ DC_vPrepareDCsForBlit( prcSecond = NULL; } - /* Update clipping of dest DC if needed */ - if (pdcDest->dctype == DCTYPE_DIRECT) - { - DCE* dce = DceGetDceFromDC(pdcDest->BaseObject.hHmgr); - if (dce) - DceUpdateVisRgn(dce, dce->pwndOrg, dce->DCXFlags); - } - if (pdcDest->fs & DC_FLAG_DIRTY_RAO) CLIPPING_UpdateGCRegion(pdcDest); /* Lock and update first DC */ - if(pdcFirst->dctype == DCTYPE_DIRECT) + if (pdcFirst->dctype == DCTYPE_DIRECT) { EngAcquireSemaphore(pdcFirst->ppdev->hsemDevLock); /* Update surface if needed */ @@ -551,7 +544,7 @@ DC_vPrepareDCsForBlit( } } - if(pdcFirst->dctype == DCTYPE_DIRECT) + if (pdcFirst->dctype == DCTYPE_DIRECT) { if (!prcFirst) prcFirst = &pdcFirst->erclClip; @@ -567,9 +560,10 @@ DC_vPrepareDCsForBlit( return; /* Lock and update second DC */ - if(pdcSecond->dctype == DCTYPE_DIRECT) + if (pdcSecond->dctype == DCTYPE_DIRECT) { EngAcquireSemaphore(pdcSecond->ppdev->hsemDevLock); + /* Update surface if needed */ if(pdcSecond->ppdev->pSurface != pdcSecond->dclevel.pSurface) { @@ -577,7 +571,7 @@ DC_vPrepareDCsForBlit( } } - if(pdcSecond->dctype == DCTYPE_DIRECT) + if (pdcSecond->dctype == DCTYPE_DIRECT) { if (!prcSecond) prcSecond = &pdcSecond->erclClip;