- Add support for pattern brushes and bottom-to-top blt in new EngBitblt
- implement a new much simpler EngCopyBits
- improve clip enumeration code
The code now generally works very well now, only has a few bugs left

svn path=/trunk/; revision=56219
This commit is contained in:
Timo Kreuzer 2012-03-24 16:24:46 +00:00
parent 720cab7b58
commit 4ffc097ef2

View file

@ -23,22 +23,26 @@ CalculateCoordinates(
{ {
ULONG cx, cy; 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 */ /* Calculate width and height of this rect */
pbltdata->ulWidth = prclClipped->right - prclClipped->left; pbltdata->ulWidth = prclClipped->right - prclClipped->left;
pbltdata->ulHeight = prclClipped->bottom - prclClipped->top; pbltdata->ulHeight = prclClipped->bottom - prclClipped->top;
/* Calculate the offset to the origin coordinates */
cx = (prclClipped->left - prclOrg->left);
if (pbltdata->dy < 0)
cy = (prclClipped->bottom - 1 - prclOrg->top);
else
cy = (prclClipped->top - prclOrg->top);
/* Calculate the target start point */
pbltdata->siDst.ptOrig.x = prclOrg->left + cx;
pbltdata->siDst.ptOrig.y = prclOrg->top + cy;
/* Calculate start position for target */ /* Calculate start position for target */
pbltdata->siDst.pjBase = pbltdata->siDst.pvScan0; pbltdata->siDst.pjBase = pbltdata->siDst.pvScan0;
pbltdata->siDst.pjBase += pbltdata->siDst.ptOrig.y * pbltdata->siDst.lDelta; pbltdata->siDst.pjBase += pbltdata->siDst.ptOrig.y * pbltdata->siDst.lDelta;
pbltdata->siDst.pjBase += pbltdata->siDst.ptOrig.x * pbltdata->siDst.jBpp / 8; 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) if (pptlSrc)
{ {
@ -97,8 +101,12 @@ EngBitBlt(
BOOL bEnumMore; BOOL bEnumMore;
RECT_ENUM rcenum; RECT_ENUM rcenum;
PSIZEL psizlPat; PSIZEL psizlPat;
SURFOBJ *psoPattern;
//static int count = 0;
//if (++count >= 1230) __debugbreak();
/* Sanity checks */
ASSERT(psoTrg); ASSERT(psoTrg);
ASSERT(psoTrg->iBitmapFormat >= BMF_1BPP); ASSERT(psoTrg->iBitmapFormat >= BMF_1BPP);
ASSERT(psoTrg->iBitmapFormat <= BMF_32BPP); ASSERT(psoTrg->iBitmapFormat <= BMF_32BPP);
@ -110,15 +118,14 @@ EngBitBlt(
rcTrg = *prclTrg; rcTrg = *prclTrg;
bltdata.dy = 1;
bltdata.rop4 = rop4; bltdata.rop4 = rop4;
bltdata.apfnDoRop[0] = gapfnRop[ROP4_BKGND(rop4)];
bltdata.apfnDoRop[1] = gapfnRop[ROP4_FGND(rop4)];
if (!pxlo) pxlo = &gexloTrivial.xlo; if (!pxlo) pxlo = &gexloTrivial.xlo;
bltdata.pxlo = pxlo; bltdata.pxlo = pxlo;
bltdata.pfnXlate = XLATEOBJ_pfnXlate(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 */ /* Check if the ROP uses a source */
if (ROP4_USES_SOURCE(rop4)) if (ROP4_USES_SOURCE(rop4))
{ {
@ -132,18 +139,18 @@ EngBitBlt(
ASSERT(pptlSrc->x <= psoSrc->sizlBitmap.cx); ASSERT(pptlSrc->x <= psoSrc->sizlBitmap.cx);
ASSERT(pptlSrc->y <= psoSrc->sizlBitmap.cy); 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 */ /* Check if source and target are equal */
if (psoSrc == psoTrg) if (psoSrc == psoTrg)
{ {
/* Analyze the copying direction */ /* Analyze the copying direction */
if (rcTrg.top < pptlSrc->y) if (rcTrg.top > pptlSrc->y)
iDirection = rcTrg.left < pptlSrc->x ? CD_RIGHTDOWN : CD_LEFTDOWN; {
else /* Need to copy from bottom to top */
iDirection = rcTrg.left < pptlSrc->x ? CD_RIGHTUP : CD_LEFTUP; iDirection = rcTrg.left < pptlSrc->x ? CD_RIGHTUP : CD_LEFTUP;
bltdata.dy = -1;
}
else
iDirection = rcTrg.left < pptlSrc->x ? CD_RIGHTDOWN : CD_LEFTDOWN;
/* Check for special right to left case */ /* Check for special right to left case */
if ((rcTrg.top == pptlSrc->y) && (rcTrg.left > pptlSrc->x)) if ((rcTrg.top == pptlSrc->y) && (rcTrg.left > pptlSrc->x))
@ -151,6 +158,7 @@ EngBitBlt(
/* Use 0 as target format to get special right to left versions */ /* Use 0 as target format to get special right to left versions */
bltdata.siDst.iFormat = 0; bltdata.siDst.iFormat = 0;
bltdata.siSrc.iFormat = psoSrc->iBitmapFormat; bltdata.siSrc.iFormat = psoSrc->iBitmapFormat;
__debugbreak();
} }
else else
{ {
@ -164,12 +172,24 @@ EngBitBlt(
bltdata.siDst.iFormat = psoTrg->iBitmapFormat; bltdata.siDst.iFormat = psoTrg->iBitmapFormat;
bltdata.siSrc.iFormat = psoSrc->iBitmapFormat; bltdata.siSrc.iFormat = psoSrc->iBitmapFormat;
} }
/* Set the source format info */
bltdata.siSrc.pvScan0 = psoSrc->pvScan0;
bltdata.siSrc.lDelta = psoSrc->lDelta;
bltdata.siSrc.cjAdvanceY = bltdata.dy * psoSrc->lDelta;
bltdata.siSrc.jBpp = gajBitsPerFormat[psoSrc->iBitmapFormat];
} }
else else
{ {
bltdata.siDst.iFormat = psoTrg->iBitmapFormat; bltdata.siDst.iFormat = psoTrg->iBitmapFormat;
} }
/* Set the destination format info */
bltdata.siDst.pvScan0 = psoTrg->pvScan0;
bltdata.siDst.lDelta = psoTrg->lDelta;
bltdata.siDst.cjAdvanceY = bltdata.dy * psoTrg->lDelta;
bltdata.siDst.jBpp = gajBitsPerFormat[psoTrg->iBitmapFormat];
/* Check if the ROP uses a pattern / brush */ /* Check if the ROP uses a pattern / brush */
if (ROP4_USES_PATTERN(rop4)) if (ROP4_USES_PATTERN(rop4))
{ {
@ -182,17 +202,25 @@ EngBitBlt(
/* Check if this is a pattern brush */ /* Check if this is a pattern brush */
if (pbo->iSolidColor == 0xFFFFFFFF) if (pbo->iSolidColor == 0xFFFFFFFF)
{ {
__debugbreak(); /* Get the realized pattern bitmap */
psoPattern = BRUSHOBJ_psoPattern(pbo);
if (!psoPattern)
{
__debugbreak();
return FALSE;
}
// FIXME /* Set the pattern format info */
bltdata.siPat.iFormat = 0;//psoPat->iBitmapFormat; bltdata.siPat.iFormat = psoPattern->iBitmapFormat;
bltdata.siPat.pvScan0 = 0;//psoPat->pvScan0; bltdata.siPat.pvScan0 = psoPattern->pvScan0;
bltdata.siPat.lDelta = 0;//psoPat->lDelta; bltdata.siPat.lDelta = psoPattern->lDelta;
bltdata.siPat.cjAdvanceY = bltdata.dy * psoPattern->lDelta;
bltdata.siPat.jBpp = gajBitsPerFormat[psoPattern->iBitmapFormat];
bltdata.ulPatWidth = 0; bltdata.ulPatWidth = psoPattern->sizlBitmap.cx;
bltdata.ulPatHeight = 0; bltdata.ulPatHeight = psoPattern->sizlBitmap.cy;
psizlPat = 0;// fixme psizlPat = &psoPattern->sizlBitmap;
} }
else else
{ {
@ -218,9 +246,8 @@ EngBitBlt(
bltdata.siMsk.iFormat = psoMask->iBitmapFormat; bltdata.siMsk.iFormat = psoMask->iBitmapFormat;
bltdata.siMsk.pvScan0 = psoMask->pvScan0; bltdata.siMsk.pvScan0 = psoMask->pvScan0;
bltdata.siMsk.lDelta = psoMask->lDelta; bltdata.siMsk.lDelta = psoMask->lDelta;
bltdata.siMsk.cjAdvanceY = bltdata.dy * psoMask->lDelta;
bltdata.apfnDoRop[0] = gapfnRop[ROP4_BKGND(rop4)]; bltdata.siMsk.jBpp = 1;
bltdata.apfnDoRop[1] = gapfnRop[ROP4_FGND(rop4)];
/* Calculate the masking function index */ /* Calculate the masking function index */
iFunctionIndex = ROP4_USES_PATTERN(rop4) ? 1 : 0; iFunctionIndex = ROP4_USES_PATTERN(rop4) ? 1 : 0;
@ -247,56 +274,54 @@ EngBitBlt(
{ {
/* Start the enumeration of the clip object */ /* Start the enumeration of the clip object */
CLIPOBJ_cEnumStart(pco, FALSE, CT_RECTANGLES, iDirection, 0); CLIPOBJ_cEnumStart(pco, FALSE, CT_RECTANGLES, iDirection, 0);
do bEnumMore = CLIPOBJ_bEnum(pco, sizeof(rcenum), (ULONG*)&rcenum);
{ }
/* Enumerate a set of rectangles */ else if (pco->iDComplexity == DC_RECT)
bEnumMore = CLIPOBJ_bEnum(pco, sizeof(rcenum), (ULONG*)&rcenum); {
/* Use the clip bounds */
/* Loop all rectangles we got */ rcenum.arcl[0] = pco->rclBounds;
for (i = 0; i < rcenum.c; i++) rcenum.c = 1;
{ bEnumMore = FALSE;
/* 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 else
{ {
/* Check if there is something to clip */ /* Use the target rect */
if (pco->iDComplexity == DC_RECT) rcenum.arcl[0] = rcTrg;
rcenum.c = 1;
bEnumMore = FALSE;
}
/* Enter enumeration loop */
while (TRUE)
{
/* Loop all rectangles we got */
for (i = 0; i < rcenum.c; i++)
{ {
/* Clip the target rect to the bounds of the clipping region */ /* Intersect this rect with the target rect */
RECTL_bIntersectRect(&rcTrg, &rcTrg, &pco->rclBounds); if (!RECTL_bIntersectRect(&rcenum.arcl[i], &rcenum.arcl[i], &rcTrg))
{
/* This rect is outside the bounds, continue */
continue;
}
/* Calculate coordinates and pointers */
CalculateCoordinates(&bltdata,
&rcenum.arcl[i],
prclTrg,
pptlSrc,
pptlMask,
pptlBrush,
psizlPat);
/* Call the dib function */
pfnBitBlt(&bltdata);
} }
/* Calculate the coordinates */ /* Bail out, when there's nothing more to do */
CalculateCoordinates(&bltdata, if(!bEnumMore) break;
&rcTrg,
prclTrg,
pptlSrc,
pptlMask,
pptlBrush,
psizlPat);
/* Call the dib function */ /* Enumerate more rectangles */
pfnBitBlt(&bltdata); bEnumMore = CLIPOBJ_bEnum(pco, sizeof(rcenum), (ULONG*)&rcenum);
} }
return TRUE; return TRUE;
@ -563,4 +588,43 @@ NtGdiEngBitBlt(
return bResult; return bResult;
} }
BOOL
APIENTRY
EngCopyBits(
SURFOBJ *psoTrg,
SURFOBJ *psoSrc,
CLIPOBJ *pco,
XLATEOBJ *pxlo,
RECTL *prclTrg,
POINTL *pptlSrc)
{
PFN_DrvCopyBits pfnCopyBits;
/* Is the target surface device managed? */
if (SURFOBJ_flags(psoTrg) & HOOK_COPYBITS)
{
pfnCopyBits = GDIDEVFUNCS(psoTrg).CopyBits;
}
if (SURFOBJ_flags(psoSrc) & HOOK_COPYBITS)
{
pfnCopyBits = GDIDEVFUNCS(psoSrc).CopyBits;
}
else
{
/* Use SRCCOPY for 2 bitmaps */
return EngBitBlt(psoTrg,
psoSrc,
NULL,
pco,
pxlo,
prclTrg,
pptlSrc,
NULL,
NULL,
NULL,
ROP4_SRCCOPY);
}
/* Forward to the driver */
return pfnCopyBits(psoTrg, psoSrc, pco, pxlo, prclTrg, pptlSrc);
}