Author: tkreuzer Date: Tue Dec 30 19:38:07 2014 New Revision: 65910
URL: http://svn.reactos.org/svn/reactos?rev=65910&view=rev Log: [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.
Modified: trunk/reactos/win32ss/gdi/ntgdi/bitblt.c trunk/reactos/win32ss/gdi/ntgdi/dclife.c
Modified: trunk/reactos/win32ss/gdi/ntgdi/bitblt.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/win32ss/gdi/ntgdi/bitblt.c?... ============================================================================== --- trunk/reactos/win32ss/gdi/ntgdi/bitblt.c [iso-8859-1] (original) +++ trunk/reactos/win32ss/gdi/ntgdi/bitblt.c [iso-8859-1] Tue Dec 30 19:38:07 2014 @@ -1025,6 +1025,81 @@ }
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, _In_ PREGION prgn, @@ -1190,34 +1265,48 @@ BOOL APIENTRY NtGdiInvertRgn( - HDC hDC, - HRGN hRgn) -{ - PREGION RgnData; - ULONG i; - PRECTL rc; - - RgnData = REGION_LockRgn(hRgn); - if (RgnData == NULL) + _In_ HDC hdc, + _In_ HRGN hrgn) +{ + BOOL bResult; + PDC pdc; + PREGION prgn; + + /* 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++) - { - - if (!NtGdiPatBlt(hDC, rc->left, rc->top, rc->right - rc->left, rc->bottom - rc->top, DSTINVERT)) - { - REGION_UnlockRgn(RgnData); - return FALSE; - } - rc++; - } - - REGION_UnlockRgn(RgnData); - return TRUE; + /* Check if the DC has no surface (empty mem or info DC) */ + if (pdc->dclevel.pSurface == NULL) + { + /* Nothing to do, Windows returns TRUE! */ + DC_UnlockDc(pdc); + 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
Modified: trunk/reactos/win32ss/gdi/ntgdi/dclife.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/win32ss/gdi/ntgdi/dclife.c?... ============================================================================== --- trunk/reactos/win32ss/gdi/ntgdi/dclife.c [iso-8859-1] (original) +++ trunk/reactos/win32ss/gdi/ntgdi/dclife.c [iso-8859-1] Tue Dec 30 19:38:07 2014 @@ -506,7 +506,8 @@ /* 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 @@ 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 @@ } }
- if(pdcFirst->dctype == DCTYPE_DIRECT) + if (pdcFirst->dctype == DCTYPE_DIRECT) { if (!prcFirst) prcFirst = &pdcFirst->erclClip; @@ -567,9 +560,10 @@ 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 @@ } }
- if(pdcSecond->dctype == DCTYPE_DIRECT) + if (pdcSecond->dctype == DCTYPE_DIRECT) { if (!prcSecond) prcSecond = &pdcSecond->erclClip;