From 7b0c1877b9a72ceaaf90832f909db3cff8a7301f Mon Sep 17 00:00:00 2001 From: Timo Kreuzer Date: Wed, 31 Dec 2014 15:15:44 +0000 Subject: [PATCH] [WIN32K] Rewrite IntEngMaskBlt to work with device managed surfaces. Should fix CORE-7821 and CORE-8711 svn path=/trunk/; revision=65919 --- reactos/win32ss/gdi/eng/bitblt.c | 148 +++++++++++++++++++++++-------- reactos/win32ss/gdi/eng/inteng.h | 1 + 2 files changed, 114 insertions(+), 35 deletions(-) diff --git a/reactos/win32ss/gdi/eng/bitblt.c b/reactos/win32ss/gdi/eng/bitblt.c index 96b031f1acf..8b6dd0009d2 100644 --- a/reactos/win32ss/gdi/eng/bitblt.c +++ b/reactos/win32ss/gdi/eng/bitblt.c @@ -65,6 +65,7 @@ BltMask(SURFOBJ* psoDest, DWORD fgndRop, bkgndRop; ASSERT(IS_VALID_ROP4(Rop4)); + ASSERT(psoMask->iBitmapFormat == BMF_1BPP); if (!psoMask) return FALSE; @@ -984,64 +985,141 @@ EngMaskBitBlt(SURFOBJ *psoDest, return Ret; } -BOOL APIENTRY -IntEngMaskBlt(SURFOBJ *psoDest, - SURFOBJ *psoMask, - CLIPOBJ *ClipRegion, - XLATEOBJ *DestColorTranslation, - XLATEOBJ *SourceColorTranslation, - RECTL *DestRect, - POINTL *pptlMask, - BRUSHOBJ *pbo, - POINTL *BrushOrigin) +BOOL +APIENTRY +IntEngMaskBlt( + _Inout_ SURFOBJ *psoDest, + _In_ SURFOBJ *psoMask, + _In_ CLIPOBJ *pco, + _In_ XLATEOBJ *pxloDest, + _In_ XLATEOBJ *pxloSource, + _In_ RECTL *prclDest, + _In_ POINTL *pptlMask, + _In_ BRUSHOBJ *pbo, + _In_ POINTL *pptlBrushOrg) { BOOLEAN ret; - RECTL OutputRect; - POINTL InputPoint = {0,0}; - //SURFACE *psurfDest; + RECTL rcDest; + POINTL ptMask = {0,0}; + PSURFACE psurfTemp; + RECTL rcTemp; + ASSERT(psoDest); ASSERT(psoMask); + /* Is this a 1 BPP mask? */ + if (psoMask->iBitmapFormat == BMF_1BPP) + { + /* Use IntEngBitBlt with an appropriate ROP4 */ + return IntEngBitBlt(psoDest, + NULL, + psoMask, + pco, + pxloDest, + prclDest, + NULL, + pptlMask, + pbo, + pptlBrushOrg, + ROP4_MASKPAINT); + } + + ASSERT(psoMask->iBitmapFormat == BMF_8BPP); + if (pptlMask) { - InputPoint = *pptlMask; + ptMask = *pptlMask; } /* Clip against the bounds of the clipping region so we won't try to write * outside the surface */ - if (NULL != ClipRegion) + if (pco != NULL) { - if (!RECTL_bIntersectRect(&OutputRect, DestRect, &ClipRegion->rclBounds)) + /* Intersect with the clip bounds and check if everything was clipped */ + if (!RECTL_bIntersectRect(&rcDest, prclDest, &pco->rclBounds)) { return TRUE; } - InputPoint.x += OutputRect.left - DestRect->left; - InputPoint.y += OutputRect.top - DestRect->top; + + /* Adjust the mask point */ + ptMask.x += rcDest.left - prclDest->left; + ptMask.y += rcDest.top - prclDest->top; } else { - OutputRect = *DestRect; + rcDest = *prclDest; } - /* No success yet */ - ret = FALSE; - ASSERT(psoDest); - //psurfDest = CONTAINING_RECORD(psoDest, SURFACE, SurfObj); + /* Check if the target surface is device managed */ + if (psoDest->iType != STYPE_BITMAP) + { + rcTemp.left = 0; + rcTemp.top = 0; + rcTemp.right = rcDest.right - rcDest.left; + rcTemp.bottom = rcDest.bottom - rcDest.top; - /* Dummy BitBlt to let driver know that it should flush its changes. - This should really be done using a call to DrvSynchronizeSurface, - but the VMware driver doesn't hook that call. */ - IntEngBitBlt(psoDest, NULL, psoMask, ClipRegion, DestColorTranslation, - DestRect, pptlMask, pptlMask, pbo, BrushOrigin, - ROP4_NOOP); + /* Allocate a temporary surface */ + psurfTemp = SURFACE_AllocSurface(STYPE_BITMAP, + rcTemp.right, + rcTemp.bottom, + psoDest->iBitmapFormat, + 0, + 0, + NULL); + if (psurfTemp == NULL) + { + return FALSE; + } - ret = EngMaskBitBlt(psoDest, psoMask, ClipRegion, DestColorTranslation, SourceColorTranslation, - &OutputRect, &InputPoint, pbo, BrushOrigin); + /* Copy the current target surface bits to the temp surface */ + ret = EngCopyBits(&psurfTemp->SurfObj, + psoDest, + NULL, // pco + NULL, // pxlo + &rcTemp, + (PPOINTL)&rcDest); - /* Dummy BitBlt to let driver know that something has changed. */ - IntEngBitBlt(psoDest, NULL, psoMask, ClipRegion, DestColorTranslation, - DestRect, pptlMask, pptlMask, pbo, BrushOrigin, - ROP4_NOOP); + if (ret) + { + /* Do the operation on the temp surface */ + ret = EngMaskBitBlt(&psurfTemp->SurfObj, + psoMask, + NULL, + pxloDest, + pxloSource, + &rcTemp, + &ptMask, + pbo, + pptlBrushOrg); + } + + if (ret) + { + /* Copy the result back to the dest surface */ + ret = EngCopyBits(psoDest, + &psurfTemp->SurfObj, + pco, + NULL, + &rcDest, + (PPOINTL)&rcTemp); + } + + /* Delete the temp surface */ + GDIOBJ_vDeleteObject(&psurfTemp->BaseObject); + } + else + { + /* Do the operation on the target surface */ + ret = EngMaskBitBlt(psoDest, + psoMask, + pco, + pxloDest, + pxloSource, + &rcDest, + &ptMask, + pbo, + pptlBrushOrg); + } return ret; } diff --git a/reactos/win32ss/gdi/eng/inteng.h b/reactos/win32ss/gdi/eng/inteng.h index 55b4fe2da05..6c82518274a 100644 --- a/reactos/win32ss/gdi/eng/inteng.h +++ b/reactos/win32ss/gdi/eng/inteng.h @@ -53,6 +53,7 @@ enum _R3_ROPCODES #define ROP4_NOOP (R3_OPINDEX_NOOP | (R3_OPINDEX_NOOP << 8)) #define ROP4_MASK (R3_OPINDEX_SRCCOPY | (R3_OPINDEX_NOOP << 8)) +#define ROP4_MASKPAINT (R3_OPINDEX_PATCOPY | (R3_OPINDEX_NOOP << 8)) /* Definitions of IntEngXxx functions */