- Correctly translate output rect
[reactos.git] / reactos / subsys / win32k / eng / bitblt.c
index ae12887..79349c8 100644 (file)
@@ -16,7 +16,7 @@
  *  along with this program; if not, write to the Free Software
  *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  */
-/* $Id: bitblt.c,v 1.57 2004/07/03 17:40:25 navaraf Exp $
+/* $Id$
  *
  * COPYRIGHT:        See COPYING in the top level directory
  * PROJECT:          ReactOS kernel
@@ -75,7 +75,7 @@ BOOL STDCALL EngIntersectRect(RECTL* prcDst, RECTL* prcSrc1, RECTL* prcSrc2)
 static BOOLEAN STDCALL
 BltMask(SURFOBJ* Dest,
        SURFOBJ* Source,
-       SURFOBJ* Mask, 
+       SURFOBJ* Mask,
        XLATEOBJ* ColorTranslation,
        RECTL* DestRect,
        POINTL* SourcePoint,
@@ -88,11 +88,11 @@ BltMask(SURFOBJ* Dest,
    BYTE *tMask, *lMask;
    static BYTE maskbit[8] = { 0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01 };
    /* Pattern brushes */
-   PGDIBRUSHOBJ GdiBrush = NULL;
-   HBITMAP PatternSurface = NULL;
+   PGDIBRUSHINST GdiBrush = NULL;
    SURFOBJ *PatternObj = NULL;
+   PBITMAPOBJ PatternBitmap;
    ULONG PatternWidth = 0, PatternHeight = 0, PatternY = 0;
-  
+
    if (Mask == NULL)
    {
       return FALSE;
@@ -103,35 +103,36 @@ BltMask(SURFOBJ* Dest,
 
    if (Brush->iSolidColor == 0xFFFFFFFF)
    {
-      PBITMAPOBJ PatternBitmap;
-
       GdiBrush = CONTAINING_RECORD(
          Brush,
-         GDIBRUSHOBJ,
+         GDIBRUSHINST,
          BrushObject);
 
-      PatternSurface = GdiBrush->hbmPattern;
-      PatternBitmap = BITMAPOBJ_LockBitmap(GdiBrush->hbmPattern);
-
-      PatternObj = &PatternBitmap->SurfObj;
-      PatternWidth = PatternObj->sizlBitmap.cx;
-      PatternHeight = PatternObj->sizlBitmap.cy;
+      PatternBitmap = BITMAPOBJ_LockBitmap(GdiBrush->GdiBrushObject->hbmPattern);
+      if(PatternBitmap != NULL)
+      {
+        PatternObj = &PatternBitmap->SurfObj;
+        PatternWidth = PatternObj->sizlBitmap.cx;
+        PatternHeight = PatternObj->sizlBitmap.cy;
+      }
    }
+   else
+     PatternBitmap = NULL;
 
    tMask = Mask->pvScan0 + SourcePoint->y * Mask->lDelta + (SourcePoint->x >> 3);
    for (j = 0; j < dy; j++)
    {
       lMask = tMask;
       c8 = SourcePoint->x & 0x07;
-      
-      if(PatternSurface)
+
+      if(PatternBitmap != NULL)
          PatternY = (DestRect->top + j) % PatternHeight;
-      
+
       for (i = 0; i < dx; i++)
       {
          if (0 != (*lMask & maskbit[c8]))
          {
-            if (PatternSurface == NULL)
+            if (PatternBitmap == NULL)
             {
                DibFunctionsForBitmapFormat[Dest->iBitmapFormat].DIB_PutPixel(
                   Dest, DestRect->left + i, DestRect->top + j, Brush->iSolidColor);
@@ -140,7 +141,7 @@ BltMask(SURFOBJ* Dest,
             {
                DibFunctionsForBitmapFormat[Dest->iBitmapFormat].DIB_PutPixel(
                   Dest, DestRect->left + i, DestRect->top + j,
-                  DIB_1BPP_GetPixel(PatternObj, (DestRect->left + i) % PatternWidth, PatternY) ? GdiBrush->crFore : GdiBrush->crBack);
+                  DIB_GetSource(PatternObj, (DestRect->left + i) % PatternWidth, PatternY, GdiBrush->XlateObject));
             }
          }
          c8++;
@@ -153,8 +154,8 @@ BltMask(SURFOBJ* Dest,
       tMask += Mask->lDelta;
    }
 
-   if (PatternSurface != NULL)
-      BITMAPOBJ_UnlockBitmap(PatternSurface);
+   if (PatternBitmap != NULL)
+      BITMAPOBJ_UnlockBitmap(PatternBitmap);
 
    return TRUE;
 }
@@ -162,7 +163,7 @@ BltMask(SURFOBJ* Dest,
 static BOOLEAN STDCALL
 BltPatCopy(SURFOBJ* Dest,
           SURFOBJ* Source,
-          SURFOBJ* Mask, 
+          SURFOBJ* Mask,
           XLATEOBJ* ColorTranslation,
           RECTL* DestRect,
           POINTL* SourcePoint,
@@ -173,15 +174,8 @@ BltPatCopy(SURFOBJ* Dest,
 {
   // These functions are assigned if we're working with a DIB
   // The assigned functions depend on the bitsPerPixel of the DIB
-  LONG y;
-  ULONG LineWidth;
 
-  LineWidth  = DestRect->right - DestRect->left;
-  for (y = DestRect->top; y < DestRect->bottom; y++)
-  {
-    DibFunctionsForBitmapFormat[Dest->iBitmapFormat].DIB_HLine(
-      Dest, DestRect->left, DestRect->right, y,  Brush->iSolidColor);
-  }
+  DibFunctionsForBitmapFormat[Dest->iBitmapFormat].DIB_ColorFill(Dest, DestRect, Brush->iSolidColor);
 
   return TRUE;
 }
@@ -198,18 +192,54 @@ CallDibBitBlt(SURFOBJ* OutputObj,
               POINTL* BrushOrigin,
               ROP4 Rop4)
 {
-  POINTL RealBrushOrigin;
-  if (BrushOrigin == NULL)
-    {
-      RealBrushOrigin.x = RealBrushOrigin.y = 0;
-    }
-  else
-    {
-      RealBrushOrigin = *BrushOrigin;
-    }
+   BLTINFO BltInfo;
+   PGDIBRUSHINST GdiBrush = NULL;
+   BITMAPOBJ *bmPattern;
+   BOOLEAN Result;
+
+   BltInfo.DestSurface = OutputObj;
+   BltInfo.SourceSurface = InputObj;
+   BltInfo.PatternSurface = NULL;
+   BltInfo.XlateSourceToDest = ColorTranslation;
+   BltInfo.DestRect = *OutputRect;
+   BltInfo.SourcePoint = *InputPoint;
+
+   if (ROP3_TO_ROP4(SRCCOPY) == Rop4)
+      return DibFunctionsForBitmapFormat[OutputObj->iBitmapFormat].DIB_BitBltSrcCopy(&BltInfo);
+
+   BltInfo.XlatePatternToDest = NULL;
+   BltInfo.Brush = Brush;
+   BltInfo.BrushOrigin = *BrushOrigin;
+   BltInfo.Rop4 = Rop4;
+
+   /* Pattern brush */
+   if (ROP4_USES_PATTERN(Rop4) && Brush->iSolidColor == 0xFFFFFFFF)
+   {
+      GdiBrush = CONTAINING_RECORD(Brush, GDIBRUSHINST, BrushObject);
+      if((bmPattern = BITMAPOBJ_LockBitmap(GdiBrush->GdiBrushObject->hbmPattern)))
+      {
+        BltInfo.PatternSurface = &bmPattern->SurfObj;
+      }
+      else
+      {
+        /* FIXME - What to do here? */
+      }
+      BltInfo.XlatePatternToDest = GdiBrush->XlateObject;
+   }
+   else
+   {
+     bmPattern = NULL;
+   }
+
+   Result = DibFunctionsForBitmapFormat[OutputObj->iBitmapFormat].DIB_BitBlt(&BltInfo);
 
-  return DibFunctionsForBitmapFormat[OutputObj->iBitmapFormat].DIB_BitBlt(
-    OutputObj, InputObj, OutputRect, InputPoint, Brush, RealBrushOrigin, ColorTranslation, Rop4);
+   /* Pattern brush */
+   if (bmPattern != NULL)
+   {
+      BITMAPOBJ_UnlockBitmap(bmPattern);
+   }
+
+   return Result;
 }
 
 INT abs(INT nm);
@@ -252,15 +282,15 @@ EngBitBlt(SURFOBJ *DestObj,
   BOOL               UsesPattern;
   POINTL             AdjustedBrushOrigin;
 
-  UsesSource = ((Rop4 & 0xCC0000) >> 2) != (Rop4 & 0x330000);
-  UsesPattern = ((Rop4 & 0xF00000) >> 4) != (Rop4 & 0x0F0000);
-  if (ROP_NOOP == Rop4)
+  UsesSource = ROP4_USES_SOURCE(Rop4);
+  UsesPattern = ROP4_USES_PATTERN(Rop4);
+  if (R4_NOOP == Rop4)
     {
     /* Copy destination onto itself: nop */
     return TRUE;
     }
 
-  if (NULL != SourcePoint)
+  if (UsesSource && NULL != SourcePoint)
     {
     InputRect.left = SourcePoint->x;
     InputRect.right = SourcePoint->x + (DestRect->right - DestRect->left);
@@ -332,11 +362,11 @@ EngBitBlt(SURFOBJ *DestObj,
     return FALSE;
     }
 
-  OutputRect.left = DestRect->left + Translate.x;
-  OutputRect.right = DestRect->right + Translate.x;
-  OutputRect.top = DestRect->top + Translate.y;
-  OutputRect.bottom = DestRect->bottom + Translate.y;
-  
+  OutputRect.left += Translate.x;
+  OutputRect.right += Translate.x;
+  OutputRect.top += Translate.y;
+  OutputRect.bottom += Translate.y;
+
   if(BrushOrigin)
   {
     AdjustedBrushOrigin.x = BrushOrigin->x + Translate.x;
@@ -353,20 +383,16 @@ EngBitBlt(SURFOBJ *DestObj,
     clippingType = ClipRegion->iDComplexity;
   }
 
-  if (0xaacc == Rop4)
+  if (R4_MASK == Rop4)
     {
       BltRectFunc = BltMask;
     }
-  else if (PATCOPY == Rop4)
+  else if (ROP3_TO_ROP4(PATCOPY) == Rop4)
     {
-#if 0
-      BltRectFunc = BltPatCopy;
-#else
       if (Brush->iSolidColor == 0xFFFFFFFF)
         BltRectFunc = CallDibBitBlt;
       else
         BltRectFunc = BltPatCopy;
-#endif
     }
   else
     {
@@ -386,11 +412,13 @@ EngBitBlt(SURFOBJ *DestObj,
       ClipRect.right = ClipRegion->rclBounds.right + Translate.x;
       ClipRect.top = ClipRegion->rclBounds.top + Translate.y;
       ClipRect.bottom = ClipRegion->rclBounds.bottom + Translate.y;
-      EngIntersectRect(&CombinedRect, &OutputRect, &ClipRect);
-      Pt.x = InputPoint.x + CombinedRect.left - OutputRect.left;
-      Pt.y = InputPoint.y + CombinedRect.top - OutputRect.top;
-      Ret = (*BltRectFunc)(OutputObj, InputObj, Mask, ColorTranslation,
-                           &CombinedRect, &Pt, MaskOrigin, Brush, &AdjustedBrushOrigin, Rop4);
+      if (EngIntersectRect(&CombinedRect, &OutputRect, &ClipRect))
+        {
+          Pt.x = InputPoint.x + CombinedRect.left - OutputRect.left;
+          Pt.y = InputPoint.y + CombinedRect.top - OutputRect.top;
+          Ret = (*BltRectFunc)(OutputObj, InputObj, Mask, ColorTranslation,
+                               &CombinedRect, &Pt, MaskOrigin, Brush, &AdjustedBrushOrigin, Rop4);
+        }
       break;
     case DC_COMPLEX:
       Ret = TRUE;
@@ -420,12 +448,15 @@ EngBitBlt(SURFOBJ *DestObj,
              ClipRect.right = RectEnum.arcl[i].right + Translate.x;
              ClipRect.top = RectEnum.arcl[i].top + Translate.y;
              ClipRect.bottom = RectEnum.arcl[i].bottom + Translate.y;
-             EngIntersectRect(&CombinedRect, &OutputRect, &ClipRect);
-             Pt.x = InputPoint.x + CombinedRect.left - OutputRect.left;
-             Pt.y = InputPoint.y + CombinedRect.top - OutputRect.top;
-             Ret = (*BltRectFunc)(OutputObj, InputObj, Mask, ColorTranslation,
-                                  &CombinedRect, &Pt, MaskOrigin, Brush, &AdjustedBrushOrigin, Rop4) &&
-                   Ret;
+             if (EngIntersectRect(&CombinedRect, &OutputRect, &ClipRect))
+                {
+                  Pt.x = InputPoint.x + CombinedRect.left - OutputRect.left;
+                  Pt.y = InputPoint.y + CombinedRect.top - OutputRect.top;
+                  Ret = (*BltRectFunc)(OutputObj, InputObj, Mask,
+                                       ColorTranslation, &CombinedRect, &Pt,
+                                       MaskOrigin, Brush, &AdjustedBrushOrigin,
+                                       Rop4) && Ret;
+                }
            }
        }
       while(EnumMore);
@@ -457,10 +488,14 @@ IntEngBitBlt(BITMAPOBJ *DestObj,
   RECTL OutputRect;
   POINTL InputPoint;
   BOOLEAN UsesSource;
-  SURFOBJ *DestSurf = &DestObj->SurfObj;
+  SURFOBJ *DestSurf;
   SURFOBJ *SourceSurf = SourceObj ? &SourceObj->SurfObj : NULL;
   SURFOBJ *MaskSurf = MaskObj ? &MaskObj->SurfObj : NULL;
 
+  ASSERT(DestObj);
+  DestSurf = &DestObj->SurfObj;
+  ASSERT(DestSurf);
+
   InputClippedRect = *DestRect;
   if (InputClippedRect.right < InputClippedRect.left)
     {
@@ -472,10 +507,10 @@ IntEngBitBlt(BITMAPOBJ *DestObj,
       InputClippedRect.top = DestRect->bottom;
       InputClippedRect.bottom = DestRect->top;
     }
-  UsesSource = ((Rop4 & 0xCC0000) >> 2) != (Rop4 & 0x330000);
+  UsesSource = ROP4_USES_SOURCE(Rop4);
   if (UsesSource)
     {
-      if (NULL == SourcePoint || NULL == SourceObj)
+      if (NULL == SourcePoint || NULL == SourceSurf)
         {
           return FALSE;
         }
@@ -605,7 +640,7 @@ EngStretchBlt(
        )
 {
   // www.osr.com/ddk/graphics/gdifncs_0bs7.htm
-  
+
   POINTL             InputPoint;
   RECTL              InputRect;
   RECTL              OutputRect;
@@ -630,7 +665,7 @@ EngStretchBlt(
 
   InputPoint.x = InputRect.left + Translate.x;
   InputPoint.y = InputRect.top + Translate.y;
+
   OutputRect = *prclDest;
 
   /* Check for degenerate case: if height or width of OutputRect is 0 pixels there's
@@ -651,7 +686,7 @@ EngStretchBlt(
   OutputRect.right = prclDest->right + Translate.x;
   OutputRect.top = prclDest->top + Translate.y;
   OutputRect.bottom = prclDest->bottom + Translate.y;
-  
+
   if (NULL != BrushOrigin)
     {
       AdjustedBrushOrigin.x = BrushOrigin->x + Translate.x;
@@ -668,8 +703,8 @@ EngStretchBlt(
       DPRINT("EngStretchBlt isn't capable of handling mask yet.\n");
       IntEngLeave(&EnterLeaveDest);
       IntEngLeave(&EnterLeaveSource);
-      
-      return FALSE;      
+
+      return FALSE;
     }
   else
     {
@@ -703,24 +738,29 @@ IntEngStretchBlt(BITMAPOBJ *DestObj,
   BOOLEAN ret;
   COLORADJUSTMENT ca;
   POINT MaskOrigin;
-  SURFOBJ *DestSurf = &DestObj->SurfObj;
+  SURFOBJ *DestSurf;
   SURFOBJ *SourceSurf = SourceObj ? &SourceObj->SurfObj : NULL;
   SURFOBJ *MaskSurf = MaskObj ? &MaskObj->SurfObj : NULL;
 
+  ASSERT(DestObj);
+  DestSurf = &DestObj->SurfObj;
+  ASSERT(DestSurf);
+
   if (pMaskOrigin != NULL)
     {
       MaskOrigin.x = pMaskOrigin->x; MaskOrigin.y = pMaskOrigin->y;
     }
 
-  if (NULL != SourceObj)
+  if (NULL != SourceSurf)
     {
+    ASSERT(SourceRect);
     MouseSafetyOnDrawStart(SourceSurf, SourceRect->left, SourceRect->top,
-                           (SourceRect->left + abs(SourceRect->right - SourceRect->left)),
-                          (SourceRect->top + abs(SourceRect->bottom - SourceRect->top)));
+                           SourceRect->right, SourceRect->bottom);
     }
 
   /* No success yet */
   ret = FALSE;
+  ASSERT(DestRect);
   MouseSafetyOnDrawStart(DestSurf, DestRect->left, DestRect->top,
                          DestRect->right, DestRect->bottom);
 
@@ -759,7 +799,7 @@ IntEngStretchBlt(BITMAPOBJ *DestObj,
 static BOOLEAN STDCALL
 AlphaBltMask(SURFOBJ* Dest,
        SURFOBJ* Source,
-       SURFOBJ* Mask, 
+       SURFOBJ* Mask,
        XLATEOBJ* ColorTranslation,
        XLATEOBJ* SrcColorTranslation,
        RECTL* DestRect,
@@ -782,43 +822,44 @@ AlphaBltMask(SURFOBJ* Dest,
       r = (int)GetRValue(BrushColor);
       g = (int)GetGValue(BrushColor);
       b = (int)GetBValue(BrushColor);
-      
-      tMask = Mask->pvBits + (SourcePoint->y * Mask->lDelta) + SourcePoint->x;
+
+      tMask = Mask->pvScan0 + (SourcePoint->y * Mask->lDelta) + SourcePoint->x;
       for (j = 0; j < dy; j++)
-       {
-         lMask = tMask;
-         for (i = 0; i < dx; i++)
-           {
-             if (*lMask > 0)
-               {
-                       if(*lMask == 0xff)
-                       {
-                               DibFunctionsForBitmapFormat[Dest->iBitmapFormat].DIB_PutPixel(
-                                       Dest, DestRect->left + i, DestRect->top + j, Brush->iSolidColor);
-                       }
-                       else
-                       {
-                               Background = DIB_GetSource(Dest, DestRect->left + i, DestRect->top + j, SrcColorTranslation);
-
-                               NewColor = 
-                                    RGB((*lMask * (r - GetRValue(Background)) >> 8) + GetRValue(Background),
-                                        (*lMask * (g - GetGValue(Background)) >> 8) + GetGValue(Background),
-                                        (*lMask * (b - GetBValue(Background)) >> 8) + GetBValue(Background));
-                               
-                               Background = XLATEOBJ_iXlate(ColorTranslation, NewColor);
-                               DibFunctionsForBitmapFormat[Dest->iBitmapFormat].DIB_PutPixel(
-                                       Dest, DestRect->left + i, DestRect->top + j, Background);
-                       }
-               }
-                 lMask++;
-           }
-         tMask += Mask->lDelta;
-       }
+        {
+          lMask = tMask;
+          for (i = 0; i < dx; i++)
+            {
+              if (*lMask > 0)
+                {
+                  if (*lMask == 0xff)
+                    {
+                      DibFunctionsForBitmapFormat[Dest->iBitmapFormat].DIB_PutPixel(
+                          Dest, DestRect->left + i, DestRect->top + j, Brush->iSolidColor);
+                    }
+                  else
+                    {
+                      Background = DIB_GetSource(Dest, DestRect->left + i, DestRect->top + j,
+                                                 SrcColorTranslation);
+
+                      NewColor =
+                          RGB((*lMask * (r - GetRValue(Background)) >> 8) + GetRValue(Background),
+                              (*lMask * (g - GetGValue(Background)) >> 8) + GetGValue(Background),
+                              (*lMask * (b - GetBValue(Background)) >> 8) + GetBValue(Background));
+
+                      Background = XLATEOBJ_iXlate(ColorTranslation, NewColor);
+                      DibFunctionsForBitmapFormat[Dest->iBitmapFormat].DIB_PutPixel(
+                        Dest, DestRect->left + i, DestRect->top + j, Background);
+                    }
+                }
+              lMask++;
+            }
+          tMask += Mask->lDelta;
+        }
       return TRUE;
     }
   else
     {
-    return FALSE;
+      return FALSE;
     }
 }
 
@@ -853,6 +894,8 @@ EngMaskBitBlt(SURFOBJ *DestObj,
   ULONG              Direction;
   POINTL             AdjustedBrushOrigin;
 
+  ASSERT ( Mask );
+
   if (NULL != SourcePoint)
     {
     InputRect.left = SourcePoint->x;
@@ -868,7 +911,7 @@ EngMaskBitBlt(SURFOBJ *DestObj,
     InputRect.bottom = DestRect->bottom - DestRect->top;
     }
 
-  if (! IntEngEnter(&EnterLeaveSource, NULL, &InputRect, TRUE, &Translate, &InputObj))
+  if (! IntEngEnter(&EnterLeaveSource, DestObj, &InputRect, TRUE, &Translate, &InputObj))
     {
     return FALSE;
     }
@@ -929,7 +972,7 @@ EngMaskBitBlt(SURFOBJ *DestObj,
   OutputRect.right = DestRect->right + Translate.x;
   OutputRect.top = DestRect->top + Translate.y;
   OutputRect.bottom = DestRect->bottom + Translate.y;
-  
+
   if(BrushOrigin)
   {
     AdjustedBrushOrigin.x = BrushOrigin->x + Translate.x;
@@ -954,7 +997,8 @@ EngMaskBitBlt(SURFOBJ *DestObj,
                            &OutputRect, &InputPoint, MaskOrigin, Brush, &AdjustedBrushOrigin);
       else
         Ret = BltMask(OutputObj, InputObj, Mask, DestColorTranslation,
-                           &OutputRect, &InputPoint, MaskOrigin, Brush, &AdjustedBrushOrigin, 0xAACC);
+                           &OutputRect, &InputPoint, MaskOrigin, Brush, &AdjustedBrushOrigin,
+                           R4_MASK);
       break;
     case DC_RECT:
       // Clip the blt to the clip rectangle
@@ -962,15 +1006,21 @@ EngMaskBitBlt(SURFOBJ *DestObj,
       ClipRect.right = ClipRegion->rclBounds.right + Translate.x;
       ClipRect.top = ClipRegion->rclBounds.top + Translate.y;
       ClipRect.bottom = ClipRegion->rclBounds.bottom + Translate.y;
-      EngIntersectRect(&CombinedRect, &OutputRect, &ClipRect);
-      Pt.x = InputPoint.x + CombinedRect.left - OutputRect.left;
-      Pt.y = InputPoint.y + CombinedRect.top - OutputRect.top;
-      if(Mask->iBitmapFormat == BMF_8BPP)
-        Ret = AlphaBltMask(OutputObj, InputObj, Mask, DestColorTranslation, SourceColorTranslation,
-                           &CombinedRect, &Pt, MaskOrigin, Brush, &AdjustedBrushOrigin);
-      else
-        Ret = BltMask(OutputObj, InputObj, Mask, DestColorTranslation,
-                           &CombinedRect, &Pt, MaskOrigin, Brush, &AdjustedBrushOrigin, 0xAACC);
+      if (EngIntersectRect(&CombinedRect, &OutputRect, &ClipRect))
+        {
+          Pt.x = InputPoint.x + CombinedRect.left - OutputRect.left;
+          Pt.y = InputPoint.y + CombinedRect.top - OutputRect.top;
+          if(Mask->iBitmapFormat == BMF_8BPP)
+            {
+              Ret = AlphaBltMask(OutputObj, InputObj, Mask, DestColorTranslation, SourceColorTranslation,
+                                 &CombinedRect, &Pt, MaskOrigin, Brush, &AdjustedBrushOrigin);
+            }
+          else
+            {
+              Ret = BltMask(OutputObj, InputObj, Mask, DestColorTranslation,
+                            &CombinedRect, &Pt, MaskOrigin, Brush, &AdjustedBrushOrigin, R4_MASK);
+            }
+        }
       break;
     case DC_COMPLEX:
       Ret = TRUE;
@@ -1000,15 +1050,26 @@ EngMaskBitBlt(SURFOBJ *DestObj,
              ClipRect.right = RectEnum.arcl[i].right + Translate.x;
              ClipRect.top = RectEnum.arcl[i].top + Translate.y;
              ClipRect.bottom = RectEnum.arcl[i].bottom + Translate.y;
-             EngIntersectRect(&CombinedRect, &OutputRect, &ClipRect);
-             Pt.x = InputPoint.x + CombinedRect.left - OutputRect.left;
-             Pt.y = InputPoint.y + CombinedRect.top - OutputRect.top;
-             if(Mask->iBitmapFormat == BMF_8BPP)
-               Ret = AlphaBltMask(OutputObj, InputObj, Mask, DestColorTranslation, SourceColorTranslation,
-                                  &CombinedRect, &Pt, MaskOrigin, Brush, &AdjustedBrushOrigin) && Ret;
-              else
-                Ret = BltMask(OutputObj, InputObj, Mask, DestColorTranslation,
-                                   &CombinedRect, &Pt, MaskOrigin, Brush, &AdjustedBrushOrigin, 0xAACC) && Ret;
+             if (EngIntersectRect(&CombinedRect, &OutputRect, &ClipRect))
+                {
+                  Pt.x = InputPoint.x + CombinedRect.left - OutputRect.left;
+                  Pt.y = InputPoint.y + CombinedRect.top - OutputRect.top;
+                  if(Mask->iBitmapFormat == BMF_8BPP)
+                    {
+                      Ret = AlphaBltMask(OutputObj, InputObj, Mask,
+                                         DestColorTranslation,
+                                         SourceColorTranslation,
+                                         &CombinedRect, &Pt, MaskOrigin, Brush,
+                                         &AdjustedBrushOrigin) && Ret;
+                    }
+                  else
+                    {
+                      Ret = BltMask(OutputObj, InputObj, Mask,
+                                    DestColorTranslation, &CombinedRect, &Pt,
+                                    MaskOrigin, Brush, &AdjustedBrushOrigin,
+                                    R4_MASK) && Ret;
+                    }
+                }
            }
        }
       while(EnumMore);
@@ -1019,31 +1080,27 @@ EngMaskBitBlt(SURFOBJ *DestObj,
   IntEngLeave(&EnterLeaveDest);
   IntEngLeave(&EnterLeaveSource);
 
-  /* Dummy BitBlt to let driver know that something has changed.
-     0x00AA0029 is the Rop for D (no-op) */
-  /* FIXME: Remove the typecast! */
-  IntEngBitBlt((BITMAPOBJ*)DestObj, NULL, (BITMAPOBJ*)Mask, ClipRegion, DestColorTranslation,
-               DestRect, SourcePoint, MaskOrigin, Brush, BrushOrigin, ROP_NOOP);
-
   return Ret;
 }
 
 BOOL STDCALL
 IntEngMaskBlt(SURFOBJ *DestObj,
-             SURFOBJ *Mask,
-             CLIPOBJ *ClipRegion,
-             XLATEOBJ *DestColorTranslation,
-             XLATEOBJ *SourceColorTranslation,
-             RECTL *DestRect,
-             POINTL *SourcePoint,
-             POINTL *MaskOrigin,
-             BRUSHOBJ *Brush,
-             POINTL *BrushOrigin)
+              SURFOBJ *Mask,
+              CLIPOBJ *ClipRegion,
+              XLATEOBJ *DestColorTranslation,
+              XLATEOBJ *SourceColorTranslation,
+              RECTL *DestRect,
+              POINTL *SourcePoint,
+              POINTL *MaskOrigin,
+              BRUSHOBJ *Brush,
+              POINTL *BrushOrigin)
 {
   BOOLEAN ret;
   RECTL OutputRect;
   POINTL InputPoint;
 
+  ASSERT(Mask);
+
   if (NULL != SourcePoint)
     {
       InputPoint = *SourcePoint;
@@ -1067,12 +1124,25 @@ IntEngMaskBlt(SURFOBJ *DestObj,
 
   /* No success yet */
   ret = FALSE;
+  ASSERT(DestObj);
   MouseSafetyOnDrawStart(DestObj, OutputRect.left, OutputRect.top,
                          OutputRect.right, OutputRect.bottom);
 
+  /* 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. */
+  /* FIXME: Remove the typecast! */
+  IntEngBitBlt((BITMAPOBJ*)DestObj, NULL, (BITMAPOBJ*)Mask, ClipRegion, DestColorTranslation,
+               DestRect, SourcePoint, MaskOrigin, Brush, BrushOrigin, R4_NOOP);
+
   ret = EngMaskBitBlt(DestObj, Mask, ClipRegion, DestColorTranslation, SourceColorTranslation,
                       &OutputRect, &InputPoint, MaskOrigin, Brush, BrushOrigin);
 
+  /* Dummy BitBlt to let driver know that something has changed. */
+  /* FIXME: Remove the typecast! */
+  IntEngBitBlt((BITMAPOBJ*)DestObj, NULL, (BITMAPOBJ*)Mask, ClipRegion, DestColorTranslation,
+               DestRect, SourcePoint, MaskOrigin, Brush, BrushOrigin, R4_NOOP);
+
   MouseSafetyOnDrawEnd(DestObj);
 
   return ret;