Author: khornicek Date: Sat Nov 21 15:09:27 2009 New Revision: 44252
URL: http://svn.reactos.org/svn/reactos?rev=44252&view=rev Log: - bring alpha blend from trunk
Modified: branches/arwinss/reactos/subsystems/win32/win32k/eng/engblt.c branches/arwinss/reactos/subsystems/win32/win32k/gdi/bitmap.c branches/arwinss/reactos/subsystems/win32/win32k/gre/bitblt.c branches/arwinss/reactos/subsystems/win32/win32k/include/gre.h
Modified: branches/arwinss/reactos/subsystems/win32/win32k/eng/engblt.c URL: http://svn.reactos.org/svn/reactos/branches/arwinss/reactos/subsystems/win32... ============================================================================== --- branches/arwinss/reactos/subsystems/win32/win32k/eng/engblt.c [iso-8859-1] (original) +++ branches/arwinss/reactos/subsystems/win32/win32k/eng/engblt.c [iso-8859-1] Sat Nov 21 15:09:27 2009 @@ -4,6 +4,7 @@ * FILE: subsystems/win32/win32k/eng/engblt.c * PURPOSE: Bit-Block Transfer Support Routines * PROGRAMMERS: Stefan Ginsberg (stefan__100__@hotmail.com) + Jason Filby */
/* INCLUDES ******************************************************************/ @@ -429,16 +430,247 @@
BOOL APIENTRY -EngAlphaBlend(IN SURFOBJ* DestSurf, - IN SURFOBJ* SourceSurf, +EngAlphaBlend(IN SURFOBJ* psoDest, + IN SURFOBJ* psoSource, IN CLIPOBJ* ClipRegion, IN XLATEOBJ* ColorTranslation, IN PRECTL DestRect, IN PRECTL SourceRect, IN BLENDOBJ* BlendObj) { - UNIMPLEMENTED; - return FALSE; + RECTL SourceStretchedRect; + SIZEL SourceStretchedSize; + HBITMAP SourceStretchedBitmap = 0; + SURFOBJ* SourceStretchedObj = NULL; + RECTL InputRect; + RECTL OutputRect; + RECTL ClipRect; + RECTL CombinedRect; + RECTL Rect; + POINTL Translate; + INTENG_ENTER_LEAVE EnterLeaveSource; + INTENG_ENTER_LEAVE EnterLeaveDest; + SURFOBJ* InputObj; + SURFOBJ* OutputObj; + LONG Width; + LONG ClippingType; + RECT_ENUM RectEnum; + BOOL EnumMore; + INT i; + BOOLEAN Ret; + + DPRINT("EngAlphaBlend(psoDest:0x%p, psoSource:0x%p, ClipRegion:0x%p, ColorTranslation:0x%p,\n", psoDest, psoSource, ClipRegion, ColorTranslation); + DPRINT(" DestRect:{0x%x, 0x%x, 0x%x, 0x%x}, SourceRect:{0x%x, 0x%x, 0x%x, 0x%x},\n", + DestRect->left, DestRect->top, DestRect->right, DestRect->bottom, + SourceRect->left, SourceRect->top, SourceRect->right, SourceRect->bottom); + DPRINT(" BlendObj:{0x%x, 0x%x, 0x%x, 0x%x}\n", BlendObj->BlendFunction.BlendOp, + BlendObj->BlendFunction.BlendFlags, BlendObj->BlendFunction.SourceConstantAlpha, + BlendObj->BlendFunction.AlphaFormat); + + + /* Validate output */ + OutputRect = *DestRect; + if (OutputRect.right < OutputRect.left) + { + OutputRect.left = DestRect->right; + OutputRect.right = DestRect->left; + } + if (OutputRect.bottom < OutputRect.top) + { + OutputRect.left = DestRect->right; + OutputRect.right = DestRect->left; + } + + + /* Validate input */ + + /* FIXME when WindowOrg.x or .y are negitve this check are not vaild, + * we need convert the inputRect to the windows org and do it right */ + InputRect = *SourceRect; + if ( (InputRect.top < 0) || (InputRect.bottom < 0) || + (InputRect.left < 0) || (InputRect.right < 0) ) + { + SetLastWin32Error(ERROR_INVALID_PARAMETER); + return FALSE; + } + + if (psoDest == psoSource && + !(OutputRect.left >= SourceRect->right || InputRect.left >= OutputRect.right || + OutputRect.top >= SourceRect->bottom || InputRect.top >= OutputRect.bottom)) + { + DPRINT1("Source and destination rectangles overlap!\n"); + return FALSE; + } + + if (BlendObj->BlendFunction.BlendOp != AC_SRC_OVER) + { + DPRINT1("BlendOp != AC_SRC_OVER (0x%x)\n", BlendObj->BlendFunction.BlendOp); + return FALSE; + } + if (BlendObj->BlendFunction.BlendFlags != 0) + { + DPRINT1("BlendFlags != 0 (0x%x)\n", BlendObj->BlendFunction.BlendFlags); + return FALSE; + } + if ((BlendObj->BlendFunction.AlphaFormat & ~AC_SRC_ALPHA) != 0) + { + DPRINT1("Unsupported AlphaFormat (0x%x)\n", BlendObj->BlendFunction.AlphaFormat); + return FALSE; + } + + /* Check if there is anything to draw */ + if (ClipRegion != NULL && + (ClipRegion->rclBounds.left >= ClipRegion->rclBounds.right || + ClipRegion->rclBounds.top >= ClipRegion->rclBounds.bottom)) + { + /* Nothing to do */ + return TRUE; + } + + /* Stretch source if needed */ + if (OutputRect.right - OutputRect.left != InputRect.right - InputRect.left || + OutputRect.bottom - OutputRect.top != InputRect.bottom - InputRect.top) + { + SourceStretchedSize.cx = OutputRect.right - OutputRect.left; + SourceStretchedSize.cy = OutputRect.bottom - OutputRect.top; + Width = DIB_GetDIBWidthBytes(SourceStretchedSize.cx, BitsPerFormat(psoSource->iBitmapFormat)); + /* FIXME: Maybe it is a good idea to use EngCreateDeviceBitmap and IntEngStretchBlt + if possible to get a HW accelerated stretch. */ + SourceStretchedBitmap = EngCreateBitmap(SourceStretchedSize, Width, psoSource->iBitmapFormat, + BMF_TOPDOWN | BMF_NOZEROINIT, NULL); + + if (SourceStretchedBitmap == 0) + { + DPRINT1("EngCreateBitmap failed!\n"); + return FALSE; + } + SourceStretchedObj = EngLockSurface(SourceStretchedBitmap); + if (SourceStretchedObj == NULL) + { + DPRINT1("EngLockSurface failed!\n"); + EngDeleteSurface(SourceStretchedBitmap); + return FALSE; + } + + SourceStretchedRect.left = 0; + SourceStretchedRect.right = SourceStretchedSize.cx; + SourceStretchedRect.top = 0; + SourceStretchedRect.bottom = SourceStretchedSize.cy; + /* FIXME: IntEngStretchBlt isn't used here atm because it results in a + try to acquire an already acquired mutex (lock the already locked source surface) */ + /*if (!IntEngStretchBlt(SourceStretchedObj, psoSource, NULL, NULL, + NULL, &SourceStretchedRect, SourceRect, NULL, + NULL, NULL, COLORONCOLOR))*/ + if (!EngStretchBlt(SourceStretchedObj, psoSource, NULL, NULL, NULL, + NULL, NULL, &SourceStretchedRect, &InputRect, + NULL, COLORONCOLOR)) + { + DPRINT1("EngStretchBlt failed!\n"); + EngFreeMem(SourceStretchedObj->pvBits); + EngUnlockSurface(SourceStretchedObj); + EngDeleteSurface((HSURF)SourceStretchedBitmap); + return FALSE; + } + InputRect.top = SourceStretchedRect.top; + InputRect.bottom = SourceStretchedRect.bottom; + InputRect.left = SourceStretchedRect.left; + InputRect.right = SourceStretchedRect.right; + psoSource = SourceStretchedObj; + } + + /* Now call the DIB function */ + if (!IntEngEnter(&EnterLeaveSource, psoSource, &InputRect, TRUE, &Translate, &InputObj)) + { + EngUnlockSurface(SourceStretchedObj); + EngDeleteSurface(SourceStretchedBitmap); + return FALSE; + } + + InputRect.left += Translate.x; + InputRect.right += Translate.x; + InputRect.top += Translate.y; + InputRect.bottom += Translate.y; + + if (!IntEngEnter(&EnterLeaveDest, psoDest, &OutputRect, FALSE, &Translate, &OutputObj)) + { + IntEngLeave(&EnterLeaveSource); + EngUnlockSurface(SourceStretchedObj); + EngDeleteSurface(SourceStretchedBitmap); + return FALSE; + } + OutputRect.left += Translate.x; + OutputRect.right += Translate.x; + OutputRect.top += Translate.y; + OutputRect.bottom += Translate.y; + + Ret = FALSE; + ClippingType = (ClipRegion == NULL) ? DC_TRIVIAL : ClipRegion->iDComplexity; + switch (ClippingType) + { + case DC_TRIVIAL: + Ret = DibFunctionsForBitmapFormat[OutputObj->iBitmapFormat].DIB_AlphaBlend( + OutputObj, InputObj, &OutputRect, &InputRect, ClipRegion, ColorTranslation, BlendObj); + break; + + case DC_RECT: + 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 (RECTL_bIntersectRect(&CombinedRect, &OutputRect, &ClipRect)) + { + Rect.left = InputRect.left + CombinedRect.left - OutputRect.left; + Rect.right = InputRect.right + CombinedRect.right - OutputRect.right; + Rect.top = InputRect.top + CombinedRect.top - OutputRect.top; + Rect.bottom = InputRect.bottom + CombinedRect.bottom - OutputRect.bottom; + Ret = DibFunctionsForBitmapFormat[OutputObj->iBitmapFormat].DIB_AlphaBlend( + OutputObj, InputObj, &CombinedRect, &Rect, ClipRegion, ColorTranslation, BlendObj); + } + break; + + case DC_COMPLEX: + Ret = TRUE; + 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++) + { + 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 (RECTL_bIntersectRect(&CombinedRect, &OutputRect, &ClipRect)) + { + Rect.left = InputRect.left + CombinedRect.left - OutputRect.left; + Rect.right = InputRect.right + CombinedRect.right - OutputRect.right; + Rect.top = InputRect.top + CombinedRect.top - OutputRect.top; + Rect.bottom = InputRect.bottom + CombinedRect.bottom - OutputRect.bottom; + Ret = DibFunctionsForBitmapFormat[OutputObj->iBitmapFormat].DIB_AlphaBlend( + OutputObj, InputObj, &CombinedRect, &Rect, ClipRegion, ColorTranslation, BlendObj) && Ret; + } + } + } + while (EnumMore); + break; + + default: + UNIMPLEMENTED; + ASSERT(FALSE); + break; + } + + IntEngLeave(&EnterLeaveDest); + IntEngLeave(&EnterLeaveSource); + + if(SourceStretchedObj != NULL) + EngUnlockSurface(SourceStretchedObj); + if(SourceStretchedBitmap != 0) + EngDeleteSurface(SourceStretchedBitmap); + + return Ret; }
BOOL
Modified: branches/arwinss/reactos/subsystems/win32/win32k/gdi/bitmap.c URL: http://svn.reactos.org/svn/reactos/branches/arwinss/reactos/subsystems/win32... ============================================================================== --- branches/arwinss/reactos/subsystems/win32/win32k/gdi/bitmap.c [iso-8859-1] (original) +++ branches/arwinss/reactos/subsystems/win32/win32k/gdi/bitmap.c [iso-8859-1] Sat Nov 21 15:09:27 2009 @@ -17,12 +17,31 @@
/* PUBLIC FUNCTIONS **********************************************************/
-BOOL APIENTRY RosGdiAlphaBlend(HDC devDst, INT xDst, INT yDst, INT widthDst, INT heightDst, - HDC devSrc, INT xSrc, INT ySrc, INT widthSrc, INT heightSrc, +BOOL APIENTRY RosGdiAlphaBlend(HDC physDevDst, INT xDst, INT yDst, INT widthDst, INT heightDst, + HDC physDevSrc, INT xSrc, INT ySrc, INT widthSrc, INT heightSrc, BLENDFUNCTION blendfn) { - UNIMPLEMENTED; - return FALSE; + BOOLEAN bRes; + PDC pSrc, pDst; + + DPRINT("AlphaBlend %x -> %x\n", physDevSrc, physDevDst); + + /* Get a pointer to the DCs */ + pSrc = DC_Lock(physDevSrc); + if (physDevSrc != physDevDst) + pDst = DC_Lock(physDevDst); + else + pDst = pSrc; + + /* Call the internal helper */ + bRes = GreAlphaBlend(pDst, xDst, yDst, widthDst, heightDst, pSrc, xSrc, ySrc, widthSrc, heightSrc, blendfn); + + /* Release DC objects */ + if (physDevSrc != physDevDst) DC_Unlock(pDst); + DC_Unlock(pSrc); + + /* Return status */ + return bRes; }
BOOL APIENTRY RosGdiBitBlt( HDC physDevDst, INT xDst, INT yDst,
Modified: branches/arwinss/reactos/subsystems/win32/win32k/gre/bitblt.c URL: http://svn.reactos.org/svn/reactos/branches/arwinss/reactos/subsystems/win32... ============================================================================== --- branches/arwinss/reactos/subsystems/win32/win32k/gre/bitblt.c [iso-8859-1] (original) +++ branches/arwinss/reactos/subsystems/win32/win32k/gre/bitblt.c [iso-8859-1] Sat Nov 21 15:09:27 2009 @@ -61,6 +61,69 @@ return ((width * depth + 31) & ~31) >> 3; }
+BOOL APIENTRY +GrepAlphaBlend(IN SURFOBJ *psoDest, + IN SURFOBJ *psoSource, + IN CLIPOBJ *ClipRegion, + IN XLATEOBJ *ColorTranslation, + IN PRECTL DestRect, + IN PRECTL SourceRect, + IN BLENDOBJ *BlendObj) +{ + BOOL ret = FALSE; + SURFACE *psurfDest; + SURFACE *psurfSource; + + ASSERT(psoDest); + psurfDest = CONTAINING_RECORD(psoDest, SURFACE, SurfObj); + + ASSERT(psoSource); + psurfSource = CONTAINING_RECORD(psoSource, SURFACE, SurfObj); + + ASSERT(DestRect); + ASSERT(SourceRect); + + /* Check if there is anything to draw */ + if (ClipRegion != NULL && + (ClipRegion->rclBounds.left >= ClipRegion->rclBounds.right || + ClipRegion->rclBounds.top >= ClipRegion->rclBounds.bottom)) + { + /* Nothing to do */ + return TRUE; + } + + SURFACE_LockBitmapBits(psurfDest); + MouseSafetyOnDrawStart(psoDest, DestRect->left, DestRect->top, + DestRect->right, DestRect->bottom); + + if (psoSource != psoDest) + SURFACE_LockBitmapBits(psurfSource); + MouseSafetyOnDrawStart(psoSource, SourceRect->left, SourceRect->top, + SourceRect->right, SourceRect->bottom); + + /* Call the driver's DrvAlphaBlend if available */ + if (psurfDest->flHooks & HOOK_ALPHABLEND) + { + ret = GDIDEVFUNCS(psoDest).AlphaBlend( + psoDest, psoSource, ClipRegion, ColorTranslation, + DestRect, SourceRect, BlendObj); + } + + if (! ret) + { + ret = EngAlphaBlend(psoDest, psoSource, ClipRegion, ColorTranslation, + DestRect, SourceRect, BlendObj); + } + + MouseSafetyOnDrawEnd(psoSource); + if (psoSource != psoDest) + SURFACE_UnlockBitmapBits(psurfSource); + MouseSafetyOnDrawEnd(psoDest); + SURFACE_UnlockBitmapBits(psurfDest); + + return ret; +} + BOOLEAN NTAPI GrepBitBltEx( @@ -192,6 +255,67 @@ }
/* PUBLIC FUNCTIONS **********************************************************/ + +BOOLEAN +NTAPI +GreAlphaBlend(PDC pDest, INT XDest, INT YDest, + INT WidthDst, INT HeightDst, PDC pSrc, + INT XSrc, INT YSrc, INT WidthSrc, INT HeightSrc, + BLENDFUNCTION blendfn) +{ + RECTL DestRect, SrcRect; + BOOL Status; + XLATEOBJ *XlateObj; + BLENDOBJ BlendObj; + BlendObj.BlendFunction = blendfn; + + DestRect.left = XDest; + DestRect.top = YDest; + DestRect.right = XDest+WidthDst; + DestRect.bottom = YDest+HeightDst; + + DestRect.left += pDest->rcVport.left + pDest->rcDcRect.left; + DestRect.top += pDest->rcVport.top + pDest->rcDcRect.top; + DestRect.right += pDest->rcVport.left + pDest->rcDcRect.left; + DestRect.bottom += pDest->rcVport.top + pDest->rcDcRect.top; + + SrcRect.left = XSrc; + SrcRect.top = YSrc; + SrcRect.right = XSrc+WidthSrc; + SrcRect.bottom = YSrc+HeightSrc; + + SrcRect.left += pSrc->rcVport.left + pSrc->rcDcRect.left; + SrcRect.top += pSrc->rcVport.top + pSrc->rcDcRect.top; + SrcRect.right += pSrc->rcVport.left + pSrc->rcDcRect.left; + SrcRect.bottom += pSrc->rcVport.top + pSrc->rcDcRect.top; + + /* Create the XLATEOBJ. */ + XlateObj = IntCreateXlateForBlt(pDest, pSrc, pDest->pBitmap, pSrc->pBitmap); + + if (XlateObj == (XLATEOBJ*)-1) + { + DPRINT1("couldn't create XlateObj\n"); + SetLastWin32Error(ERROR_NO_SYSTEM_RESOURCES); + XlateObj = NULL; + Status = FALSE; + } + else + { + /* Perform the alpha blend operation */ + Status = GrepAlphaBlend(&pDest->pBitmap->SurfObj, + &pSrc->pBitmap->SurfObj, + pDest->CombinedClip, + XlateObj, + &DestRect, + &SrcRect, + &BlendObj); + } + + if (XlateObj != NULL) + EngDeleteXlate(XlateObj); + + return Status; +}
BOOLEAN NTAPI
Modified: branches/arwinss/reactos/subsystems/win32/win32k/include/gre.h URL: http://svn.reactos.org/svn/reactos/branches/arwinss/reactos/subsystems/win32... ============================================================================== --- branches/arwinss/reactos/subsystems/win32/win32k/include/gre.h [iso-8859-1] (original) +++ branches/arwinss/reactos/subsystems/win32/win32k/include/gre.h [iso-8859-1] Sat Nov 21 15:09:27 2009 @@ -3,6 +3,12 @@
/* bitblt.c */ INT NTAPI DIB_GetDIBWidthBytes(INT width, INT depth); + +BOOLEAN NTAPI +GreAlphaBlend(PDC pDest, INT XDest, INT YDest, + INT WidthDst, INT HeightDst, PDC pSrc, + INT XSrc, INT YSrc, INT WidthSrc, INT HeightSrc, + BLENDFUNCTION blendfn);
BOOLEAN NTAPI GreBitBlt(PDC pDevDst, INT xDst, INT yDst,