Author: tkreuzer Date: Thu Mar 22 20:43:31 2012 New Revision: 56213
URL: http://svn.reactos.org/svn/reactos?rev=56213&view=rev Log: [WIN32K] - Initial implementations of IntEngBitBlt, EngBitBlt, NtGdiBitBlt
Added: trunk/reactos/subsystems/win32/win32k/eng/bitblt_new.c (with props)
Added: trunk/reactos/subsystems/win32/win32k/eng/bitblt_new.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/subsystems/win32/win32k/eng... ============================================================================== --- trunk/reactos/subsystems/win32/win32k/eng/bitblt_new.c (added) +++ trunk/reactos/subsystems/win32/win32k/eng/bitblt_new.c [iso-8859-1] Thu Mar 22 20:43:31 2012 @@ -1,0 +1,576 @@ + +#include <win32k.h> +#include "../diblib/DibLib_interface.h" +DBG_DEFAULT_CHANNEL(GdiFont); + +#define SURFOBJ_flags(pso) (CONTAINING_RECORD(pso, SURFACE, SurfObj)->flags) + +#define XCLIPOBJ CLIPGDI + +XCLIPOBJ gxcoTrivial; + + +static +void +CalculateCoordinates( + PBLTDATA pbltdata, + PRECTL prclClipped, + PRECTL prclOrg, + PPOINTL pptlSrc, + PPOINTL pptlMask, + PPOINTL pptlPat, + PSIZEL psizlPat) +{ + ULONG cx, cy; + + /* Copy the target start point */ + pbltdata->siDst.ptOrig.x = prclClipped->left; + pbltdata->siDst.ptOrig.y = prclClipped->top; + + /* Calculate width and height of this rect */ + pbltdata->ulWidth = prclClipped->right - prclClipped->left; + pbltdata->ulHeight = prclClipped->bottom - prclClipped->top; + + /* Calculate start position for target */ + pbltdata->siDst.pjBase = pbltdata->siDst.pvScan0; + pbltdata->siDst.pjBase += pbltdata->siDst.ptOrig.y * pbltdata->siDst.lDelta; + pbltdata->siDst.pjBase += pbltdata->siDst.ptOrig.x * pbltdata->siDst.jBpp / 8; + + /* Calculate the offset from the original coordinates */ + cx = (prclClipped->left - prclOrg->left); + cy = (prclClipped->top - prclOrg->top); + + if (pptlSrc) + { + /* Calculate current origin for the source */ + pbltdata->siSrc.ptOrig.x = pptlSrc->x + cx; + pbltdata->siSrc.ptOrig.y = pptlSrc->y + cy; + + /* Calculate start position for source */ + pbltdata->siSrc.pjBase = pbltdata->siSrc.pvScan0; + pbltdata->siSrc.pjBase += pbltdata->siSrc.ptOrig.y * pbltdata->siSrc.lDelta; + pbltdata->siSrc.pjBase += pbltdata->siSrc.ptOrig.x * pbltdata->siSrc.jBpp / 8; + } + + if (pptlMask) + { + pbltdata->siMsk.ptOrig.x = pptlMask->x + cx; + pbltdata->siMsk.ptOrig.y = pptlMask->y + cy; + + /* Calculate start position for mask */ + pbltdata->siMsk.pjBase = pbltdata->siMsk.pvScan0; + pbltdata->siMsk.pjBase += pbltdata->siMsk.ptOrig.y * pbltdata->siMsk.lDelta; + pbltdata->siMsk.pjBase += pbltdata->siMsk.ptOrig.x * pbltdata->siMsk.jBpp / 8; + } + + if (pptlPat) + { + pbltdata->siPat.ptOrig.x = (pptlPat->x + cx) % psizlPat->cx; + pbltdata->siPat.ptOrig.y = (pptlPat->x + cy) % psizlPat->cy; + + /* Calculate start position for pattern */ + pbltdata->siPat.pjBase = pbltdata->siPat.pvScan0; + pbltdata->siPat.pjBase += pbltdata->siPat.ptOrig.y * pbltdata->siPat.lDelta; + pbltdata->siPat.pjBase += pbltdata->siPat.ptOrig.x * pbltdata->siPat.jBpp / 8; + } +} + +BOOL +APIENTRY +EngBitBlt( + _Inout_ SURFOBJ *psoTrg, + _In_opt_ SURFOBJ *psoSrc, + _In_opt_ SURFOBJ *psoMask, + _In_opt_ CLIPOBJ *pco, + _In_opt_ XLATEOBJ *pxlo, + _In_ RECTL *prclTrg, + _When_(psoSrc, _In_) POINTL *pptlSrc, + _When_(psoMask, _In_) POINTL *pptlMask, + _In_opt_ BRUSHOBJ *pbo, + _When_(pbo, _In_) POINTL *pptlBrush, + _In_ ROP4 rop4) +{ + BLTDATA bltdata; + ULONG i, iFunctionIndex, iDirection = CD_ANY; + RECTL rcTrg; + PFN_DIBFUNCTION pfnBitBlt; + BOOL bEnumMore; + RECT_ENUM rcenum; + PSIZEL psizlPat; + +__debugbreak(); + + ASSERT(psoTrg); + ASSERT(psoTrg->iBitmapFormat >= BMF_1BPP); + ASSERT(psoTrg->iBitmapFormat <= BMF_32BPP); + ASSERT(prclTrg); + ASSERT(prclTrg->left >= 0); + ASSERT(prclTrg->top >= 0); + ASSERT(prclTrg->right <= psoTrg->sizlBitmap.cx); + ASSERT(prclTrg->bottom <= psoTrg->sizlBitmap.cy); + + rcTrg = *prclTrg; + + bltdata.rop4 = rop4; + bltdata.pxlo = pxlo; + bltdata.pfnXlate = XLATEOBJ_pfnXlate(pxlo); + + bltdata.siDst.pvScan0 = psoTrg->pvScan0; + bltdata.siDst.lDelta = psoTrg->lDelta; + bltdata.siDst.jBpp = gajBitsPerFormat[psoTrg->iBitmapFormat]; + + /* Check if the ROP uses a source */ + if (ROP4_USES_SOURCE(rop4)) + { + /* Sanity checks */ + ASSERT(psoSrc); + ASSERT(psoSrc->iBitmapFormat >= BMF_1BPP); + ASSERT(psoSrc->iBitmapFormat <= BMF_32BPP); + ASSERT(pptlSrc); + ASSERT(pptlSrc->x >= 0); + ASSERT(pptlSrc->y >= 0); + ASSERT(pptlSrc->x <= psoSrc->sizlBitmap.cx); + ASSERT(pptlSrc->y <= psoSrc->sizlBitmap.cy); + + bltdata.siSrc.pvScan0 = psoSrc->pvScan0; + bltdata.siSrc.lDelta = psoSrc->lDelta; + bltdata.siSrc.jBpp = gajBitsPerFormat[psoSrc->iBitmapFormat]; + + /* Check if source and target are equal */ + if (psoSrc == psoTrg) + { + /* Analyze the copying direction */ + if (rcTrg.top < pptlSrc->y) + iDirection = rcTrg.left < pptlSrc->x ? CD_RIGHTDOWN : CD_LEFTDOWN; + else + iDirection = rcTrg.left < pptlSrc->x ? CD_RIGHTUP : CD_LEFTUP; + + /* Check for special right to left case */ + if ((rcTrg.top == pptlSrc->y) && (rcTrg.left > pptlSrc->x)) + { + /* Use 0 as target format to get special right to left versions */ + bltdata.siDst.iFormat = 0; + bltdata.siSrc.iFormat = psoSrc->iBitmapFormat; + } + else + { + /* Use 0 as source format to get special equal surface versions */ + bltdata.siDst.iFormat = psoTrg->iBitmapFormat; + bltdata.siSrc.iFormat = 0; + } + } + else + { + bltdata.siDst.iFormat = psoTrg->iBitmapFormat; + bltdata.siSrc.iFormat = psoSrc->iBitmapFormat; + } + } + else + { + bltdata.siDst.iFormat = psoTrg->iBitmapFormat; + } + + /* Check of the ROP uses a pattern / brush */ + if (ROP4_USES_PATTERN(rop4)) + { + /* Must have a brush */ + ASSERT(pbo); // FIXME: test this! + + /* Copy the solid color */ + bltdata.ulSolidColor = pbo->iSolidColor; + + /* Check if this is a pattern brush */ + if (pbo->iSolidColor == 0xFFFFFFFF) + { + __debugbreak(); + + // FIXME + bltdata.siPat.iFormat = 0;//psoPat->iBitmapFormat; + bltdata.siPat.pvScan0 = 0;//psoPat->pvScan0; + bltdata.siPat.lDelta = 0;//psoPat->lDelta; + + bltdata.ulPatWidth = 0; + bltdata.ulPatHeight = 0; + + psizlPat = 0;// fixme + } + else + { + pptlBrush = NULL; + psizlPat = NULL; + } + } + else + { + pptlBrush = NULL; + psizlPat = NULL; + } + + /* Check if the ROP uses a mask */ + if (ROP4_USES_MASK(rop4)) + { + /* Must have a mask surface and point */ + ASSERT(psoMask); + ASSERT(pptlMask); + + bltdata.siMsk.iFormat = psoMask->iBitmapFormat; + bltdata.siMsk.pvScan0 = psoMask->pvScan0; + bltdata.siMsk.lDelta = psoMask->lDelta; + + bltdata.apfnDoRop[0] = gapfnRop[ROP4_BKGND(rop4)]; + bltdata.apfnDoRop[1] = gapfnRop[ROP4_FGND(rop4)]; + + ASSERT(FALSE); + // get masking function! + pfnBitBlt = 0; + } + else + { + /* Get the function index from the foreground ROP index*/ + iFunctionIndex = aiIndexPerRop[ROP4_FGND(rop4)]; + + /* Get the dib function */ + pfnBitBlt = apfnDibFunction[iFunctionIndex]; + } + + /* If no clip object is given, use trivial one */ + if (!pco) pco = (CLIPOBJ*)&gxcoTrivial; + + /* Check if we need to enumerate rects */ + if (pco->iDComplexity == DC_COMPLEX) + { + /* Start the enumeration of the clip object */ + CLIPOBJ_cEnumStart(pco, FALSE, CT_RECTANGLES, iDirection, 0); + do + { + /* Enumerate a set of rectangles */ + bEnumMore = CLIPOBJ_bEnum(pco, sizeof(rcenum), (ULONG*)&rcenum); + + /* Loop all rectangles we got */ + for (i = 0; i < rcenum.c; i++) + { + /* Intersect this rect with the target rect */ + if (!RECTL_bIntersectRect(&rcenum.arcl[i], &rcenum.arcl[i], &rcTrg)) + { + /* This rect is outside the bounds, continue */ + continue; + } + + /* Calculate the coordinates */ + CalculateCoordinates(&bltdata, + &rcenum.arcl[i], + prclTrg, + pptlSrc, + pptlMask, + pptlBrush, + psizlPat); + + /* Call the dib function */ + pfnBitBlt(&bltdata); + } + } + while (bEnumMore); + } + else + { + /* Check if there is something to clip */ + if (pco->iDComplexity == DC_RECT) + { + /* Clip the target rect to the bounds of the clipping region */ + RECTL_bIntersectRect(&rcTrg, &rcTrg, &pco->rclBounds); + } + + /* Calculate the coordinates */ + CalculateCoordinates(&bltdata, + &rcTrg, + prclTrg, + pptlSrc, + pptlMask, + pptlBrush, + psizlPat); + + /* Call the dib function */ + pfnBitBlt(&bltdata); + } + + return TRUE; +} + + +static +VOID +AdjustOffsetAndSize( + _Out_ PPOINTL pptOffset, + _Out_ PSIZEL psizTrg, + _In_ PPOINTL pptlSrc, + _In_ PSIZEL psizSrc) +{ + LONG x, y, cxMax, cyMax; + + x = pptlSrc->x + pptOffset->x; + if (x < 0) pptOffset->x -= x, x = 0; + + cxMax = psizSrc->cx - x; + if (psizTrg->cx > cxMax) psizTrg->cx= cxMax; + + y = pptlSrc->y + pptOffset->y; + if (y < 0) pptOffset->y -= y, y = 0; + + cyMax = psizSrc->cy - y; + if (psizTrg->cy > cyMax) psizTrg->cy = cyMax; +} + +BOOL +APIENTRY +IntEngBitBlt( + _Inout_ SURFOBJ *psoTrg, + _In_opt_ SURFOBJ *psoSrc, + _In_opt_ SURFOBJ *psoMask, + _In_opt_ CLIPOBJ *pco, + _In_opt_ XLATEOBJ *pxlo, + _In_ RECTL *prclTrg, + _When_(psoSrc, _In_) POINTL *pptlSrc, + _When_(psoMask, _In_) POINTL *pptlMask, + _In_opt_ BRUSHOBJ *pbo, + _When_(pbo, _In_) POINTL *pptlBrush, + _In_ ROP4 rop4) +{ + BOOL bResult; + RECTL rcClipped; + POINTL ptOffset, ptSrc, ptMask; + SIZEL sizTrg; + PFN_DrvBitBlt pfnBitBlt; + +//__debugbreak(); + + /* Sanity checks */ + ASSERT(IS_VALID_ROP4(rop4)); + ASSERT(psoTrg); + ASSERT(psoTrg->iBitmapFormat >= BMF_1BPP); + ASSERT(psoTrg->iBitmapFormat <= BMF_32BPP); + ASSERT(prclTrg); + ASSERT(RECTL_bIsWellOrdered(prclTrg)); + + /* Clip the target rect to the extents of the target surface */ + rcClipped.left = max(prclTrg->left, 0); + rcClipped.top = max(prclTrg->top, 0); + rcClipped.right = min(prclTrg->right, psoTrg->sizlBitmap.cx); + rcClipped.bottom = min(prclTrg->bottom, psoTrg->sizlBitmap.cy); + + /* If no clip object is given, use trivial one */ + if (!pco) pco = (CLIPOBJ*)&gxcoTrivial; + + /* Check if there is something to clip */ + if (pco->iDComplexity != DC_TRIVIAL) + { + /* Clip the target rect to the bounds of the clipping region */ + RECTL_bIntersectRect(&rcClipped, &rcClipped, &pco->rclBounds); + } + + /* Don't pass a clip object with a single rectangle */ +// if (pco->iDComplexity == DC_RECT) pco = (CLIPOBJ*)&gxcoTrivial; + + /* Calculate initial offset and size */ + ptOffset.x = rcClipped.left - prclTrg->left; + ptOffset.y = rcClipped.top - prclTrg->top; + sizTrg.cx = rcClipped.right - rcClipped.left; + sizTrg.cy = rcClipped.bottom - rcClipped.top; + + /* Check if the ROP uses a source */ + if (ROP4_USES_SOURCE(rop4)) + { + /* Must have a source surface and point */ + ASSERT(psoSrc); + ASSERT(pptlSrc); + + /* Get the source point */ + ptSrc = *pptlSrc; + + /* Clip against the extents of the source surface */ + AdjustOffsetAndSize(&ptOffset, &sizTrg, &ptSrc, &psoSrc->sizlBitmap); + } + else + { + psoSrc = NULL; + ptSrc.x = 0; + ptSrc.y = 0; + } + + /* Check if the ROP uses a mask */ + if (ROP4_USES_MASK(rop4)) + { + /* Must have a mask surface and point */ + ASSERT(psoMask); + ASSERT(pptlMask); + + /* Get the mask point */ + ptMask = *pptlMask; + + /* Clip against the extents of the mask surface */ + AdjustOffsetAndSize(&ptOffset, &sizTrg, &ptMask, &psoMask->sizlBitmap); + } + else + { + psoMask = NULL; + ptMask.x = 0; + ptMask.y = 0; + } + + /* Adjust the points */ + ptSrc.x += ptOffset.x; + ptSrc.y += ptOffset.y; + ptMask.x += ptOffset.x; + ptMask.y += ptOffset.y; + + /* Recalculate the target rect */ + rcClipped.left = prclTrg->left + ptOffset.x; + rcClipped.top = prclTrg->top + ptOffset.y; + rcClipped.right = rcClipped.left + sizTrg.cx; + rcClipped.bottom = rcClipped.top + sizTrg.cy; + + /* Is the target surface device managed? */ + if (SURFOBJ_flags(psoTrg) & HOOK_BITBLT) + { + /* Is the source a different device managed surface? */ + if (psoSrc && (psoSrc->hdev != psoTrg->hdev) && + (SURFOBJ_flags(psoSrc) & HOOK_BITBLT)) + { + ERR("Need to copy to standard bitmap format!\n"); + ASSERT(FALSE); + } + + pfnBitBlt = GDIDEVFUNCS(psoTrg).BitBlt; + } + /* Otherwise is the source surface device managed? */ + else if (psoSrc && (SURFOBJ_flags(psoSrc) & HOOK_BITBLT)) + { + pfnBitBlt = GDIDEVFUNCS(psoSrc).BitBlt; + } + else + { + pfnBitBlt = EngBitBlt; + } + + bResult = pfnBitBlt(psoTrg, + psoSrc, + psoMask, + pco, + pxlo, + &rcClipped, + psoSrc ? &ptSrc : NULL, + psoMask ? &ptMask : NULL, + pbo, + pptlBrush, + rop4); + + // FIXME: cleanup temp surface! + + return bResult; +} + +BOOL +APIENTRY +NtGdiEngBitBlt( + IN SURFOBJ *psoTrgUMPD, + IN SURFOBJ *psoSrcUMPD, + IN SURFOBJ *psoMaskUMPD, + IN CLIPOBJ *pcoUMPD, + IN XLATEOBJ *pxloUMPD, + IN RECTL *prclTrg, + IN POINTL *pptlSrc, + IN POINTL *pptlMask, + IN BRUSHOBJ *pboUMPD, + IN POINTL *pptlBrush, + IN ROP4 rop4) +{ + RECTL rclTrg; + POINTL ptlSrc, ptlMask, ptlBrush; + HSURF hsurfTrg, hsurfSrc = NULL, hsurfMask = NULL; + HANDLE hBrushObj; // HUMPDOBJ + SURFOBJ *psoTrg, *psoSrc, *psoMask; + CLIPOBJ *pco; + XLATEOBJ *pxlo; + BRUSHOBJ *pbo; + BOOL bResult; + + _SEH2_TRY + { + ProbeForRead(prclTrg, sizeof(RECTL), 1); + rclTrg = *prclTrg; + + ProbeForRead(psoTrgUMPD, sizeof(SURFOBJ), 1); + hsurfTrg = psoTrgUMPD->hsurf; + + if (ROP4_USES_SOURCE(rop4)) + { + ProbeForRead(pptlSrc, sizeof(POINTL), 1); + ptlSrc = *pptlSrc; + + ProbeForRead(psoSrcUMPD, sizeof(SURFOBJ), 1); + hsurfSrc = psoSrcUMPD->hsurf; + } + + if (ROP4_USES_MASK(rop4)) + { + ProbeForRead(pptlMask, sizeof(POINTL), 1); + ptlMask = *pptlMask; + + ProbeForRead(psoMaskUMPD, sizeof(SURFOBJ), 1); + hsurfMask = psoMaskUMPD->hsurf; + } + + if (ROP4_USES_PATTERN(rop4)) + { + ProbeForRead(pptlBrush, sizeof(POINTL), 1); + ptlBrush = *pptlBrush; + + ProbeForRead(psoSrcUMPD, sizeof(SURFOBJ), 1); + hBrushObj = pboUMPD->pvRbrush; // FIXME + } + } + _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) + { + _SEH2_YIELD(return FALSE); + } + _SEH2_END; + + // FIXME: these need to be converted/locked! + psoTrg = NULL; + psoSrc = NULL; + psoMask = NULL; + pco = NULL; + pxlo = NULL; + pbo = NULL; + + bResult = EngBitBlt(psoTrg, + psoSrc, + psoMask, + pco, + pxlo, + &rclTrg, + pptlSrc ? &ptlSrc : NULL, + pptlMask ? &ptlMask : NULL, + pbo, + pptlBrush ? &ptlBrush : NULL, + rop4); + + return bResult; +} + +BOOL +NTAPI +IntEngMaskBlt( + SURFOBJ *psoDest, + SURFOBJ *psoMask, + CLIPOBJ *pco, + XLATEOBJ *pxloDest, + XLATEOBJ *pxloSource, + RECTL *DestRect, + POINTL *pptlMask, + BRUSHOBJ *pbo, + POINTL *pptlBrushOrigin) +{ + ASSERT(FALSE); + return 0; +} +
Propchange: trunk/reactos/subsystems/win32/win32k/eng/bitblt_new.c ------------------------------------------------------------------------------ svn:eol-style = native