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;