- 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
This commit is contained in:
Timo Kreuzer
2014-12-30 19:38:07 +00:00
parent e1f04ea0de
commit 3c30e5af66
2 changed files with 114 additions and 31 deletions
+107 -18
View File
@@ -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
+7 -13
View File
@@ -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;