Author: tkreuzer
Date: Thu Dec 18 08:12:23 2014
New Revision: 65730
URL:
http://svn.reactos.org/svn/reactos?rev=65730&view=rev
Log:
[WIN32K]
- Rewrite NtGdiFillRgn and IntGdiPaintRgn
We now properly support painting regions on DCs with arbitrary world transforms, with
pattern brushes and we respect the foreground ROP and mode of the DC. And we don't run
into deadlocks due to having an exclusive region lock while trying to lock a DC. LOCKING
MUST BE DONE IN PROPER ORDER!
Modified:
trunk/reactos/win32ss/gdi/ntgdi/bitblt.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] Thu Dec 18 08:12:23 2014
@@ -1021,103 +1021,146 @@
if (IntGdiCombineRgn(prgnDest, prgnSrc, NULL, RGN_COPY) == ERROR)
return FALSE;
- return REGION_bXformRgn(prgnDest, &pdc->dclevel.mxWorldToDevice);
+ return REGION_bXformRgn(prgnDest, DC_pmxWorldToDevice(pdc));
+}
+
+BOOL
+IntGdiFillRgn(
+ _In_ PDC pdc,
+ _In_ PREGION prgn,
+ _In_ BRUSHOBJ *pbo)
+{
+ PREGION prgnClip;
+ XCLIPOBJ xcoClip;
+ BOOL bRet;
+ PSURFACE psurf;
+ DWORD rop2Fg;
+ MIX mix;
+
+ NT_ASSERT((pdc != NULL) && (prgn != NULL));
+
+ psurf = pdc->dclevel.pSurface;
+ if (psurf == NULL)
+ {
+ return TRUE;
+ }
+
+ prgnClip = IntSysCreateRectpRgn(0, 0, 0, 0);
+ if (prgnClip == NULL)
+ {
+ return FALSE;
+ }
+
+ /* Transform region into device coordinates */
+ if (!REGION_LPTODP(pdc, prgnClip, prgn) ||
+ IntGdiOffsetRgn(prgnClip, pdc->ptlDCOrig.x, pdc->ptlDCOrig.y) == ERROR)
+ {
+ 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);
+
+ IntEngInitClipObj(&xcoClip);
+ IntEngUpdateClipRegion(&xcoClip,
+ prgnClip->rdh.nCount,
+ prgnClip->Buffer,
+ &prgnClip->rdh.rcBound );
+
+ /* Get the FG rop and create a MIX based on the BK mode */
+ rop2Fg = pdc->pdcattr->jROP2;
+ mix = rop2Fg | (pdc->pdcattr->jBkMode == OPAQUE ? rop2Fg : R2_NOP) << 8;
+
+ /* Call the internal function */
+ bRet = IntEngPaint(&psurf->SurfObj,
+ &xcoClip.ClipObj,
+ pbo,
+ &pdc->pdcattr->ptlBrushOrigin,
+ mix);
+
+ REGION_Delete(prgnClip);
+ IntEngFreeClipResources(&xcoClip);
+
+ // Fill the region
+ return bRet;
}
BOOL
FASTCALL
IntGdiPaintRgn(
- PDC dc,
- PREGION Rgn)
-{
- PREGION VisRgn;
- XCLIPOBJ ClipRegion;
- BOOL bRet = FALSE;
- POINTL BrushOrigin;
- SURFACE *psurf;
- PDC_ATTR pdcattr;
-
- if ((dc == NULL) || (Rgn == NULL))
- return FALSE;
-
- pdcattr = dc->pdcattr;
-
- ASSERT(!(pdcattr->ulDirty_ & (DIRTY_FILL | DC_BRUSH_DIRTY)));
-
- VisRgn = IntSysCreateRectpRgn(0, 0, 0, 0);
- if (VisRgn == NULL)
- {
- return FALSE;
- }
-
- // Transform region into device co-ords
- if (!REGION_LPTODP(dc, VisRgn, Rgn) ||
- IntGdiOffsetRgn(VisRgn, dc->ptlDCOrig.x, dc->ptlDCOrig.y) == ERROR)
- {
- REGION_Delete(VisRgn);
- return FALSE;
- }
-
- if (dc->prgnRao)
- IntGdiCombineRgn(VisRgn, VisRgn, dc->prgnRao, RGN_AND);
-
- IntEngInitClipObj(&ClipRegion);
- IntEngUpdateClipRegion(&ClipRegion,
- VisRgn->rdh.nCount,
- VisRgn->Buffer,
- &VisRgn->rdh.rcBound );
-
- BrushOrigin.x = pdcattr->ptlBrushOrigin.x;
- BrushOrigin.y = pdcattr->ptlBrushOrigin.y;
- psurf = dc->dclevel.pSurface;
- /* FIXME: Handle psurf == NULL !!!! */
-
- bRet = IntEngPaint(&psurf->SurfObj,
- &ClipRegion.ClipObj,
- &dc->eboFill.BrushObject,
- &BrushOrigin,
- 0xFFFF); // FIXME: Don't know what to put here
-
- REGION_Delete(VisRgn);
- IntEngFreeClipResources(&ClipRegion);
-
- // Fill the region
- return bRet;
+ _In_ PDC pdc,
+ _In_ PREGION prgn)
+{
+ if (pdc->pdcattr->ulDirty_ & (DIRTY_FILL | DC_BRUSH_DIRTY))
+ DC_vUpdateFillBrush(pdc);
+
+ return IntGdiFillRgn(pdc, prgn, &pdc->eboFill.BrushObject);
}
BOOL
APIENTRY
NtGdiFillRgn(
- HDC hDC,
- HRGN hRgn,
- HBRUSH hBrush)
-{
- HBRUSH oldhBrush;
- PREGION rgn;
- PRECTL r;
-
- rgn = RGNOBJAPI_Lock(hRgn, NULL);
- if (rgn == NULL)
- {
- return FALSE;
- }
-
- oldhBrush = NtGdiSelectBrush(hDC, hBrush);
- if (oldhBrush == NULL)
- {
- RGNOBJAPI_Unlock(rgn);
- return FALSE;
- }
-
- for (r = rgn->Buffer; r < rgn->Buffer + rgn->rdh.nCount; r++)
- {
- NtGdiPatBlt(hDC, r->left, r->top, r->right - r->left, r->bottom -
r->top, PATCOPY);
- }
-
- RGNOBJAPI_Unlock(rgn);
- NtGdiSelectBrush(hDC, oldhBrush);
-
- return TRUE;
+ _In_ HDC hdc,
+ _In_ HRGN hrgn,
+ _In_ HBRUSH hbrush)
+{
+ PDC pdc;
+ PREGION prgn;
+ PBRUSH pbrFill;
+ EBRUSHOBJ eboFill;
+ BOOL bResult;
+
+ /* Lock the DC */
+ pdc = DC_LockDc(hdc);
+ if (pdc == NULL)
+ {
+ ERR("Failed to lock hdc %p\n", hdc);
+ return FALSE;
+ }
+
+ /* Check if the DC has no surface (empty mem or info DC) */
+ if (pdc->dclevel.pSurface == NULL)
+ {
+ DC_UnlockDc(pdc);
+ return TRUE;
+ }
+
+ /* Lock the region */
+ prgn = RGNOBJAPI_Lock(hrgn, NULL);
+ if (prgn == NULL)
+ {
+ ERR("Failed to lock hrgn %p\n", hrgn);
+ DC_UnlockDc(pdc);
+ return FALSE;
+ }
+
+ /* Lock the brush */
+ pbrFill = BRUSH_ShareLockBrush(hbrush);
+ if (pbrFill == NULL)
+ {
+ ERR("Failed to lock hbrush %p\n", hbrush);
+ RGNOBJAPI_Unlock(prgn);
+ DC_UnlockDc(pdc);
+ return FALSE;
+ }
+
+ /* Initialize the brush object */
+ /// \todo Check parameters
+ EBRUSHOBJ_vInit(&eboFill, pbrFill, pdc->dclevel.pSurface, 0x00FFFFFF, 0,
NULL);
+
+ /* Call the internal function */
+ bResult = IntGdiFillRgn(pdc, prgn, &eboFill.BrushObject);
+
+ /* Cleanup locks */
+ BRUSH_ShareUnlockBrush(pbrFill);
+ RGNOBJAPI_Unlock(prgn);
+ DC_UnlockDc(pdc);
+
+ return bResult;
}
BOOL