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;