Index: subsystems/win32/win32k/dib/dib.c =================================================================== --- subsystems/win32/win32k/dib/dib.c (revision 39873) +++ subsystems/win32/win32k/dib/dib.c (working copy) @@ -224,10 +224,12 @@ } BOOLEAN Dummy_StretchBlt(SURFOBJ *DestSurf, SURFOBJ *SourceSurf, + SURFOBJ *PatternSurface, RECTL* DestRect, RECTL *SourceRect, POINTL* MaskOrigin, BRUSHOBJ* Brush, - POINTL* BrushOrign, CLIPOBJ *ClipRegion, - XLATEOBJ *ColorTranslation, ROP4 Rop) + POINTL* BrushOrign, + XLATEOBJ *ColorTranslation, + XLATEOBJ *XlatePatternToDest, ROP4 Rop) { return FALSE; } Index: subsystems/win32/win32k/dib/dib.h =================================================================== --- subsystems/win32/win32k/dib/dib.h (revision 39873) +++ subsystems/win32/win32k/dib/dib.h (working copy) @@ -41,7 +41,7 @@ typedef VOID (*PFN_DIB_HLine)(SURFOBJ*,LONG,LONG,LONG,ULONG); typedef VOID (*PFN_DIB_VLine)(SURFOBJ*,LONG,LONG,LONG,ULONG); typedef BOOLEAN (*PFN_DIB_BitBlt)(PBLTINFO); -typedef BOOLEAN (*PFN_DIB_StretchBlt)(SURFOBJ*,SURFOBJ*,RECTL*,RECTL*,POINTL*,BRUSHOBJ*,POINTL*,CLIPOBJ*,XLATEOBJ*,ROP4); +typedef BOOLEAN (*PFN_DIB_StretchBlt)(SURFOBJ*,SURFOBJ*,SURFOBJ*,RECTL*,RECTL*,POINTL*,BRUSHOBJ*,POINTL*,XLATEOBJ*,XLATEOBJ*,ROP4); typedef BOOLEAN (*PFN_DIB_TransparentBlt)(SURFOBJ*,SURFOBJ*,RECTL*,POINTL*,XLATEOBJ*,ULONG); typedef BOOLEAN (*PFN_DIB_ColorFill)(SURFOBJ*, RECTL*, ULONG); typedef BOOLEAN (*PFN_DIB_AlphaBlend)(SURFOBJ*, SURFOBJ*, RECTL*, RECTL*, CLIPOBJ*, XLATEOBJ*, BLENDOBJ*); @@ -67,7 +67,7 @@ VOID Dummy_HLine(SURFOBJ*,LONG,LONG,LONG,ULONG); VOID Dummy_VLine(SURFOBJ*,LONG,LONG,LONG,ULONG); BOOLEAN Dummy_BitBlt(PBLTINFO); -BOOLEAN Dummy_StretchBlt(SURFOBJ*,SURFOBJ*,RECTL*,RECTL*,POINTL*,BRUSHOBJ*,POINTL*,CLIPOBJ*,XLATEOBJ*,ROP4); +BOOLEAN Dummy_StretchBlt(SURFOBJ*,SURFOBJ*,SURFOBJ*,RECTL*,RECTL*,POINTL*,BRUSHOBJ*,POINTL*,XLATEOBJ*,XLATEOBJ*,ROP4); BOOLEAN Dummy_TransparentBlt(SURFOBJ*,SURFOBJ*,RECTL*,POINTL*,XLATEOBJ*,ULONG); BOOLEAN Dummy_ColorFill(SURFOBJ*, RECTL*, ULONG); BOOLEAN Dummy_AlphaBlend(SURFOBJ*, SURFOBJ*, RECTL*, RECTL*, CLIPOBJ*, XLATEOBJ*, BLENDOBJ*); @@ -132,7 +132,7 @@ BOOLEAN DIB_32BPP_ColorFill(SURFOBJ*, RECTL*, ULONG); BOOLEAN DIB_32BPP_AlphaBlend(SURFOBJ*, SURFOBJ*, RECTL*, RECTL*, CLIPOBJ*, XLATEOBJ*, BLENDOBJ*); -BOOLEAN DIB_XXBPP_StretchBlt(SURFOBJ*,SURFOBJ*,RECTL*,RECTL*,POINTL*,BRUSHOBJ*,POINTL*,CLIPOBJ*,XLATEOBJ*,ROP4); +BOOLEAN DIB_XXBPP_StretchBlt(SURFOBJ*,SURFOBJ*,SURFOBJ*,RECTL*,RECTL*,POINTL*,BRUSHOBJ*,POINTL*,XLATEOBJ*,XLATEOBJ*,ROP4); extern unsigned char notmask[2]; extern unsigned char altnotmask[2]; Index: subsystems/win32/win32k/dib/dibXXbpp.c =================================================================== --- subsystems/win32/win32k/dib/dibXXbpp.c (revision 39873) +++ subsystems/win32/win32k/dib/dibXXbpp.c (working copy) @@ -23,42 +23,34 @@ #include BOOLEAN DIB_XXBPP_StretchBlt(SURFOBJ *DestSurf, SURFOBJ *SourceSurf, + SURFOBJ *PatternSurface, RECTL *DestRect, RECTL *SourceRect, POINTL *MaskOrigin, BRUSHOBJ *Brush, - POINTL *BrushOrigin, CLIPOBJ *ClipRegion, - XLATEOBJ *ColorTranslation, ROP4 ROP) + POINTL *BrushOrigin, + XLATEOBJ *ColorTranslation, + XLATEOBJ *XlatePatternToDest, ROP4 ROP) { - LONG SrcSizeY; - LONG SrcSizeX; - LONG DesSizeY; - LONG DesSizeX; LONG sx = 0; LONG sy = 0; LONG DesX; LONG DesY; - LONG SrcZoomXHight; - LONG SrcZoomXLow; - LONG SrcZoomYHight; - LONG SrcZoomYLow; + LONG dstHight; + LONG dstWidth; + LONG srcHight; + LONG srcWidth; - LONG sy_dec = 0; - LONG sy_max; - - LONG sx_dec = 0; - LONG sx_max; ULONG color; ULONG Dest, Source = 0, Pattern = 0; ULONG xxBPPMask; + BOOL IsDraw = FALSE; PFN_DIB_GetPixel fnSource_GetPixel = NULL; PFN_DIB_GetPixel fnDest_GetPixel = NULL; PFN_DIB_PutPixel fnDest_PutPixel = NULL; + PFN_DIB_GetPixel fnPattern_GetPixel = NULL; - RECT_ENUM RectEnum; - BOOL EnumMore; - unsigned i; - RECTL OutputRect; + ULONG PatternX = 0, PatternY = 0; BOOL UsesSource = ROP4_USES_SOURCE(ROP); BOOL UsesPattern = ROP4_USES_PATTERN(ROP); @@ -76,31 +68,13 @@ BitsPerFormat(SourceSurf->iBitmapFormat), SourceRect->left, SourceRect->top, SourceRect->right, SourceRect->bottom); } - /* Calc the Zoom height of Source */ - SrcSizeY = SourceRect->bottom - SourceRect->top; + dstHight = DestRect->bottom - DestRect->top; + dstWidth = DestRect->right - DestRect->left; + srcHight = SourceRect->bottom - SourceRect->top; + srcWidth = SourceRect->right - SourceRect->left; - /* Calc the Zoom Width of Source */ - SrcSizeX = SourceRect->right - SourceRect->left; + /* FIXME : MaskOrigin? */ - /* Calc the Zoom height of Destinations */ - DesSizeY = DestRect->bottom - DestRect->top; - - /* Calc the Zoom width of Destinations */ - DesSizeX = DestRect->right - DestRect->left; - - /* Calc the zoom factor of source height */ - SrcZoomYHight = SrcSizeY / DesSizeY; - SrcZoomYLow = SrcSizeY - (SrcZoomYHight * DesSizeY); - - /* Calc the zoom factor of source width */ - SrcZoomXHight = SrcSizeX / DesSizeX; - SrcZoomXLow = SrcSizeX - (SrcZoomXHight * DesSizeX); - - sx_max = DesSizeX; - sy_max = DesSizeY; - - /* FIXME : MaskOrigin, BrushOrigin? */ - switch(DestSurf->iBitmapFormat) { case BMF_1BPP: xxBPPMask = 0x1; break; @@ -114,73 +88,76 @@ if (UsesPattern) { - DPRINT1("StretchBlt does not support pattern ROPs yet\n"); - return TRUE; + if (PatternSurface) + { + PatternY = (DestRect->top - BrushOrigin->y) % PatternSurface->sizlBitmap.cy; + if (PatternY < 0) + { + PatternY += PatternSurface->sizlBitmap.cy; + } + fnPattern_GetPixel = DibFunctionsForBitmapFormat[PatternSurface->iBitmapFormat].DIB_GetPixel; + } + else + { + if (Brush) + Pattern = Brush->iSolidColor; + } } - - CLIPOBJ_cEnumStart(ClipRegion, FALSE, CT_RECTANGLES, CD_ANY, 0); - do - { - EnumMore = CLIPOBJ_bEnum(ClipRegion,(ULONG) sizeof(RectEnum), (PVOID) &RectEnum); - for (i = 0; i < RectEnum.c; i++) + + for (DesY=DestRect->top; DesYbottom; DesY++) + { + if (PatternSurface) { - OutputRect.left = RectEnum.arcl[i].left; - OutputRect.right = RectEnum.arcl[i].right; - OutputRect.top = RectEnum.arcl[i].top; - OutputRect.bottom = RectEnum.arcl[i].bottom; - - sy = SourceRect->top; - sy_dec = 0; - for (DesY=DestRect->top; DesYbottom; DesY++) + PatternX = (DestRect->left - BrushOrigin->x) % PatternSurface->sizlBitmap.cx; + if (PatternX < 0) { - sx = SourceRect->left; - sx_dec = 0; + PatternX += PatternSurface->sizlBitmap.cx; + } + } + if (UsesSource) + sy = SourceRect->top+(DesY - DestRect->top) * srcHight / dstHight; - for (DesX=DestRect->left; DesXright; DesX++) + for (DesX=DestRect->left; DesXright; DesX++) + { + IsDraw = TRUE; + if (UsesSource) + { + sx = SourceRect->left+(DesX - DestRect->left) * srcWidth / dstWidth; + if (sx >= 0 && sy >= 0 && + SourceSurf->sizlBitmap.cx > sx && SourceSurf->sizlBitmap.cy > sy) { - /* Check if inside clip region */ - if (DesX >= OutputRect.left && - DesX < OutputRect.right && - DesY >= OutputRect.top && - DesY < OutputRect.bottom) - { - if (UsesSource) - { - Source = XLATEOBJ_iXlate(ColorTranslation, fnSource_GetPixel(SourceSurf, sx, sy)); - } - - if (UsesPattern) - { - /* TBD as soon as BRUSHOBJ is available */ - } - - Dest = fnDest_GetPixel(DestSurf, DesX, DesY); - color = DIB_DoRop(ROP, Dest, Source, Pattern) & xxBPPMask; - - fnDest_PutPixel(DestSurf, DesX, DesY, color); - - } - sx += SrcZoomXHight; - sx_dec += SrcZoomXLow; - if (sx_dec >= sx_max) - { - sx++; - sx_dec -= sx_max; - } + Source = XLATEOBJ_iXlate(ColorTranslation, fnSource_GetPixel(SourceSurf, sx, sy)); } + else + { + Source = 0; + IsDraw = (ROP3_TO_ROP4(SRCCOPY) != ROP); + } + } - sy += SrcZoomYHight; - sy_dec += SrcZoomYLow; - if (sy_dec >= sy_max) + if (IsDraw) + { + if (PatternSurface) { - sy++; - sy_dec -= sy_max; + Pattern = XLATEOBJ_iXlate(XlatePatternToDest, fnPattern_GetPixel(PatternSurface, PatternX, PatternY)); + PatternX++; + PatternX %= PatternSurface->sizlBitmap.cx; } + + Dest = fnDest_GetPixel(DestSurf, DesX, DesY); + color = DIB_DoRop(ROP, Dest, Source, Pattern) & xxBPPMask; + + fnDest_PutPixel(DestSurf, DesX, DesY, color); } } + + if (PatternSurface) + { + PatternY++; + PatternY %= PatternSurface->sizlBitmap.cy; + } } - while (EnumMore); return TRUE; } Index: subsystems/win32/win32k/eng/bitblt.c =================================================================== --- subsystems/win32/win32k/eng/bitblt.c (revision 39873) +++ subsystems/win32/win32k/eng/bitblt.c (working copy) @@ -45,7 +45,6 @@ typedef BOOLEAN (APIENTRY *PSTRETCHRECTFUNC)(SURFOBJ* OutputObj, SURFOBJ* InputObj, SURFOBJ* Mask, - CLIPOBJ* ClipRegion, XLATEOBJ* ColorTranslation, RECTL* OutputRect, RECTL* InputRect, @@ -737,7 +736,6 @@ CallDibStretchBlt(SURFOBJ* psoDest, SURFOBJ* psoSource, SURFOBJ* Mask, - CLIPOBJ* ClipRegion, XLATEOBJ* ColorTranslation, RECTL* OutputRect, RECTL* InputRect, @@ -747,6 +745,11 @@ ROP4 Rop4) { POINTL RealBrushOrigin; + SURFACE* psurfPattern; + PGDIBRUSHINST GdiBrush = NULL; + SURFOBJ* PatternSurface = NULL; + XLATEOBJ* XlatePatternToDest = NULL; + if (BrushOrigin == NULL) { RealBrushOrigin.x = RealBrushOrigin.y = 0; @@ -755,8 +758,37 @@ { RealBrushOrigin = *BrushOrigin; } + + /* Pattern brush */ + if (ROP4_USES_PATTERN(Rop4) && Brush && Brush->iSolidColor == 0xFFFFFFFF) + { + GdiBrush = CONTAINING_RECORD(Brush, GDIBRUSHINST, BrushObject); + psurfPattern = SURFACE_LockSurface(GdiBrush->GdiBrushObject->hbmPattern); + if (psurfPattern) + { + PatternSurface = &psurfPattern->SurfObj; + } + else + { + /* FIXME - What to do here? */ + } + XlatePatternToDest = GdiBrush->XlateObject; + } + else + { + psurfPattern = NULL; + } + return DibFunctionsForBitmapFormat[psoDest->iBitmapFormat].DIB_StretchBlt( - psoDest, psoSource, OutputRect, InputRect, MaskOrigin, Brush, &RealBrushOrigin, ClipRegion, ColorTranslation, Rop4); + psoDest, psoSource, PatternSurface, + OutputRect, InputRect, MaskOrigin, Brush, &RealBrushOrigin, + ColorTranslation, XlatePatternToDest, Rop4); + + /* Pattern brush */ + if (psurfPattern) + { + SURFACE_UnlockSurface(psurfPattern); + } } @@ -836,10 +868,34 @@ SURFOBJ* psoInput; SURFOBJ* psoOutput; PSTRETCHRECTFUNC BltRectFunc; - BOOLEAN Ret; + BOOLEAN Ret = TRUE; POINTL AdjustedBrushOrigin; BOOL UsesSource = ROP4_USES_SOURCE(ROP4); + BYTE clippingType; + RECTL ClipRect; + RECT_ENUM RectEnum; + BOOL EnumMore; + ULONG Direction; + RECTL CombinedRect; + RECTL InputToCombinedRect; + unsigned i; + + LONG dstHight; + LONG dstWidth; + LONG srcHight; + LONG srcWidth; + + /* Determine clipping type */ + if (ClipRegion == (CLIPOBJ *) NULL) + { + clippingType = DC_TRIVIAL; + } + else + { + clippingType = ClipRegion->iDComplexity; + } + if (ROP4 == R4_NOOP) { /* Copy destination onto itself: nop */ @@ -866,18 +922,6 @@ return FALSE; } - /* Make sure we don't try to copy anything outside the valid source region */ - if (InputRect.left < 0) - { - OutputRect.left -= InputRect.left; - InputRect.left = 0; - } - if (InputRect.top < 0) - { - OutputRect.top -= InputRect.top; - InputRect.top = 0; - } - if (! IntEngEnter(&EnterLeaveSource, psoSource, &InputRect, TRUE, &Translate, &psoInput)) { @@ -965,9 +1009,88 @@ BltRectFunc = CallDibStretchBlt; } - Ret = (*BltRectFunc)(psoOutput, psoInput, Mask, ClipRegion, + dstHight = OutputRect.bottom - OutputRect.top; + dstWidth = OutputRect.right - OutputRect.left; + srcHight = InputRect.bottom - InputRect.top; + srcWidth = InputRect.right - InputRect.left; + switch (clippingType) + { + case DC_TRIVIAL: + Ret = (*BltRectFunc)(psoOutput, psoInput, Mask, ColorTranslation, &OutputRect, &InputRect, MaskOrigin, Brush, &AdjustedBrushOrigin, ROP4); + break; + case DC_RECT: + // Clip the blt to the clip rectangle + ClipRect.left = ClipRegion->rclBounds.left + Translate.x; + ClipRect.right = ClipRegion->rclBounds.right + Translate.x; + ClipRect.top = ClipRegion->rclBounds.top + Translate.y; + ClipRect.bottom = ClipRegion->rclBounds.bottom + Translate.y; + if (EngIntersectRect(&CombinedRect, &OutputRect, &ClipRect)) + { + InputToCombinedRect.top = InputRect.top + (CombinedRect.top - OutputRect.top) * srcHight / dstHight; + InputToCombinedRect.bottom = InputRect.top + (CombinedRect.bottom - OutputRect.top) * srcHight / dstHight; + InputToCombinedRect.left = InputRect.left + (CombinedRect.left - OutputRect.left) * srcWidth / dstWidth; + InputToCombinedRect.right = InputRect.left + (CombinedRect.right - OutputRect.left) * srcWidth / dstWidth; + Ret = (*BltRectFunc)(psoOutput, psoInput, Mask, + ColorTranslation, + &CombinedRect, + &InputToCombinedRect, + MaskOrigin, + Brush, + &AdjustedBrushOrigin, + ROP4); + } + break; + case DC_COMPLEX: + if (psoOutput == psoInput) + { + if (OutputRect.top < InputRect.top) + { + Direction = OutputRect.left < InputRect.left ? + CD_RIGHTDOWN : CD_LEFTDOWN; + } + else + { + Direction = OutputRect.left < InputRect.left ? + CD_RIGHTUP : CD_LEFTUP; + } + } + else + { + Direction = CD_ANY; + } + CLIPOBJ_cEnumStart(ClipRegion, FALSE, CT_RECTANGLES, Direction, 0); + do + { + EnumMore = CLIPOBJ_bEnum(ClipRegion,(ULONG) sizeof(RectEnum), + (PVOID) &RectEnum); + for (i = 0; i < RectEnum.c; i++) + { + ClipRect.left = RectEnum.arcl[i].left + Translate.x; + ClipRect.right = RectEnum.arcl[i].right + Translate.x; + ClipRect.top = RectEnum.arcl[i].top + Translate.y; + ClipRect.bottom = RectEnum.arcl[i].bottom + Translate.y; + if (EngIntersectRect(&CombinedRect, &OutputRect, &ClipRect)) + { + InputToCombinedRect.top = InputRect.top + (CombinedRect.top - OutputRect.top) * srcHight / dstHight; + InputToCombinedRect.bottom = InputRect.top + (CombinedRect.bottom - OutputRect.top) * srcHight / dstHight; + InputToCombinedRect.left = InputRect.left + (CombinedRect.left - OutputRect.left) * srcWidth / dstWidth; + InputToCombinedRect.right = InputRect.left + (CombinedRect.right - OutputRect.left) * srcWidth / dstWidth; + Ret = (*BltRectFunc)(psoOutput, psoInput, Mask, + ColorTranslation, + &CombinedRect, + &InputToCombinedRect, + MaskOrigin, + Brush, + &AdjustedBrushOrigin, + ROP4); + } + } + } + while (EnumMore); + break; + } IntEngLeave(&EnterLeaveDest); if (UsesSource) @@ -1009,7 +1132,7 @@ MaskOrigin, Mode, NULL, - SRCCOPY); + ROP3_TO_ROP4(SRCCOPY)); } BOOL APIENTRY @@ -1061,18 +1184,6 @@ } InputRect = *SourceRect; - /* Make sure we don't try to copy anything outside the valid source region */ - if (InputRect.left < 0) - { - InputClippedRect.left -= InputRect.left; - InputRect.left = 0; - } - if (InputRect.top < 0) - { - InputClippedRect.top -= InputRect.top; - InputRect.top = 0; - } - if (InputClippedRect.right < InputClippedRect.left || InputClippedRect.bottom < InputClippedRect.top) { @@ -1129,19 +1240,18 @@ /* Prepare color adjustment */ /* Call the driver's DrvStretchBlt if available */ - if (psurfDest->flHooks & HOOK_STRETCHBLT) + if (psurfDest->flHooks & HOOK_STRETCHBLTROP) { - /* Drv->StretchBlt (look at http://www.osr.com/ddk/graphics/ddifncs_3ew7.htm ) */ + /* Drv->StretchBltROP (look at http://www.osronline.com/ddkx/graphics/ddifncs_0z3b.htm ) */ // FIXME: MaskOrigin is always NULL ! - ret = GDIDEVFUNCS(psoDest).StretchBlt( - psoDest, (UsesSource) ? psoSource : NULL, MaskSurf, ClipRegion, ColorTranslation, - &ca, BrushOrigin, &OutputRect, &InputRect, NULL, ROP); + ret = GDIDEVFUNCS(psoDest).StretchBltROP(psoDest, (UsesSource) ? psoSource : NULL, MaskSurf, ClipRegion, ColorTranslation, + &ca, BrushOrigin, &OutputRect, &InputRect, NULL, COLORONCOLOR, Brush, ROP); } if (! ret) { // FIXME: see previous fixme - ret = EngStretchBltROP(psoDest, psoSource, MaskSurf, ClipRegion, ColorTranslation, + ret = EngStretchBltROP(psoDest, (UsesSource) ? psoSource : NULL, MaskSurf, ClipRegion, ColorTranslation, &ca, BrushOrigin, &OutputRect, &InputRect, NULL, COLORONCOLOR, Brush, ROP); } Index: subsystems/win32/win32k/objects/bitblt.c =================================================================== --- subsystems/win32/win32k/objects/bitblt.c (revision 39873) +++ subsystems/win32/win32k/objects/bitblt.c (working copy) @@ -878,6 +878,9 @@ BrushOrigin = *((PPOINTL)&BrushObj->ptOrigin); IntGdiInitBrushInstance(&BrushInst, BrushObj, DCDest->XlateBrush); } + /* Start offset Brush */ + BrushOrigin.x += DCDest->ptlDCOrig.x; + BrushOrigin.y += DCDest->ptlDCOrig.y; /* Perform the bitblt operation */ Status = IntEngStretchBlt(&BitmapDest->SurfObj, &BitmapSrc->SurfObj,