Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

928 lines
30 KiB

/******************************Module*Header*******************************\
* Module Name: bitblt.c
*
* Banked Frame Buffer bitblit
*
* Copyright (c) 1992 Microsoft Corporation
*
\**************************************************************************/
#include "driver.h"
/************************************************************************\
* bIntersectRect
*
* Calculates the intersection between *prcSrc1 and *prcSrc2,
* returning the resulting rect in *prcDst. Returns TRUE if
* *prcSrc1 intersects *prcSrc2, FALSE otherwise. If there is no
* intersection, an empty rect is returned in *prcDst.
\************************************************************************/
static const RECTL rclEmpty = { 0, 0, 0, 0 };
BOOL bIntersectRect(
PRECTL prcDst,
PRECTL prcSrc1,
PRECTL prcSrc2)
{
prcDst->left = max(prcSrc1->left, prcSrc2->left);
prcDst->right = min(prcSrc1->right, prcSrc2->right);
// check for empty rect
if (prcDst->left < prcDst->right)
{
prcDst->top = max(prcSrc1->top, prcSrc2->top);
prcDst->bottom = min(prcSrc1->bottom, prcSrc2->bottom);
// check for empty rect
if (prcDst->top < prcDst->bottom)
return(TRUE); // not empty
}
// empty rect
*prcDst = rclEmpty;
return(FALSE);
}
/******************************Public*Routine******************************\
* BOOL bPuntScreenToScreenCopyBits(ppdev, pco, pxlo, prclDest, pptlSrc)
*
* Performs a screen-to-screen CopyBits entirely using an intermediate
* temporary buffer and GDI.
*
* We found that on most machines it was faster to have the engine copy
* the source to a buffer, then blit the buffer to the destination, than
* to have optimized ASM code that copies a word at a time. The reason?
* The engine does d-word moves, which are faster than word moves even
* going over the bus to a 16 bit display device.
*
* We could also write optimized ASM code that does d-word moves, but the
* win will be marginal, we're time constrained, we also need a routine
* like this to handle complex clip objects and palette translates, and
* most of the other times we can use planar copies for important things
* like scrolls, anyways.
*
\**************************************************************************/
BOOL bPuntScreenToScreenCopyBits(
PPDEV ppdev,
CLIPOBJ* pco,
XLATEOBJ* pxlo,
RECTL* prclDest,
POINTL* pptlSrc)
{
RECTL rclDest;
POINTL ptlSrc;
BOOL b = TRUE;
SURFOBJ* pso = ppdev->pSurfObj;
SURFOBJ* psoTmp = ppdev->psoTmp;
if (prclDest->top < pptlSrc->y)
{
////////////////////////////////////////////////////////////////
// Do a top-to-bottom copy:
////////////////////////////////////////////////////////////////
LONG ySrcBottom;
LONG yDestBottom;
LONG yDestTop = prclDest->top;
LONG ySrcTop = pptlSrc->y;
LONG ySrcLast = ySrcTop + (prclDest->bottom - prclDest->top);
if (ySrcTop < ppdev->rcl1WindowClip.top ||
ySrcTop >= ppdev->rcl1WindowClip.bottom)
{
ppdev->pfnBankControl(ppdev, ySrcTop, JustifyTop);
}
pso->pvScan0 = ppdev->pvBitmapStart;
while (TRUE)
{
// Copy an entire source bank into the temporary buffer:
ySrcBottom = min(ySrcLast, ppdev->rcl1WindowClip.bottom);
ptlSrc.x = pptlSrc->x;
ptlSrc.y = ySrcTop;
rclDest.left = prclDest->left;
rclDest.top = 0;
rclDest.right = prclDest->right;
rclDest.bottom = ySrcBottom - ySrcTop;
b &= EngCopyBits(psoTmp, pso, NULL, NULL, &rclDest, &ptlSrc);
yDestBottom = yDestTop + rclDest.bottom;
if (ppdev->rcl1WindowClip.top >= yDestBottom)
{
ppdev->pfnBankControl(ppdev, yDestBottom - 1, JustifyBottom);
pso->pvScan0 = ppdev->pvBitmapStart;
}
while (TRUE)
{
// Copy the temporary buffer into one or more destination
// banks:
LONG yThisTop;
LONG yThisBottom;
LONG yOffset;
yThisBottom = min(yDestBottom, ppdev->rcl1WindowClip.bottom);
yThisTop = max(yDestTop, ppdev->rcl1WindowClip.top);
yOffset = yThisTop - yDestTop;
ptlSrc.x = prclDest->left;
ptlSrc.y = yOffset;
rclDest.left = prclDest->left;
rclDest.top = yThisTop;
rclDest.right = prclDest->right;
rclDest.bottom = yThisBottom;
b &= EngCopyBits(pso, psoTmp, pco, pxlo, &rclDest, &ptlSrc);
if (yOffset == 0)
break;
ppdev->pfnBankControl(ppdev, yThisTop - 1, JustifyBottom);
pso->pvScan0 = ppdev->pvBitmapStart;
}
if (ySrcBottom >= ySrcLast)
break;
yDestTop = yDestBottom;
ySrcTop = ySrcBottom;
ppdev->pfnBankControl(ppdev, ySrcTop, JustifyTop);
pso->pvScan0 = ppdev->pvBitmapStart;
}
}
else
{
////////////////////////////////////////////////////////////////
// Do a bottom-to-top copy:
////////////////////////////////////////////////////////////////
LONG ySrcTop;
LONG yDestTop;
LONG yDestBottom = prclDest->bottom;
LONG ySrcFirst = pptlSrc->y;
LONG ySrcBottom = ySrcFirst + (prclDest->bottom - prclDest->top);
if (ySrcBottom <= ppdev->rcl1WindowClip.top ||
ySrcBottom > ppdev->rcl1WindowClip.bottom)
{
ppdev->pfnBankControl(ppdev, ySrcBottom - 1, JustifyBottom);
}
pso->pvScan0 = ppdev->pvBitmapStart;
while (TRUE)
{
// Copy an entire source bank into the temporary buffer:
ySrcTop = max(ySrcFirst, ppdev->rcl1WindowClip.top);
ptlSrc.x = pptlSrc->x;
ptlSrc.y = ySrcTop;
rclDest.left = prclDest->left;
rclDest.top = 0;
rclDest.right = prclDest->right;
rclDest.bottom = ySrcBottom - ySrcTop;
b &= EngCopyBits(psoTmp, pso, NULL, NULL, &rclDest, &ptlSrc);
yDestTop = yDestBottom - rclDest.bottom;
if (ppdev->rcl1WindowClip.bottom <= yDestTop)
{
ppdev->pfnBankControl(ppdev, yDestTop, JustifyTop);
pso->pvScan0 = ppdev->pvBitmapStart;
}
while (TRUE)
{
// Copy the temporary buffer into one or more destination
// banks:
LONG yThisTop;
LONG yThisBottom;
LONG yOffset;
yThisTop = max(yDestTop, ppdev->rcl1WindowClip.top);
yThisBottom = min(yDestBottom, ppdev->rcl1WindowClip.bottom);
yOffset = yThisTop - yDestTop;
ptlSrc.x = prclDest->left;
ptlSrc.y = yOffset;
rclDest.left = prclDest->left;
rclDest.top = yThisTop;
rclDest.right = prclDest->right;
rclDest.bottom = yThisBottom;
b &= EngCopyBits(pso, psoTmp, pco, pxlo, &rclDest, &ptlSrc);
if (yThisBottom == yDestBottom)
break;
ppdev->pfnBankControl(ppdev, yThisBottom, JustifyTop);
pso->pvScan0 = ppdev->pvBitmapStart;
}
if (ySrcTop <= ySrcFirst)
break;
yDestBottom = yDestTop;
ySrcBottom = ySrcTop;
ppdev->pfnBankControl(ppdev, ySrcBottom - 1, JustifyBottom);
pso->pvScan0 = ppdev->pvBitmapStart;
}
}
return(b);
}
/******************************Public*Routine******************************\
* BOOL bPuntScreenToScreenBitBlt(...)
*
* Performs a screen-to-screen BitBlt entirely using an intermediate temporary
* buffer and GDI.
*
* This function is basically a clone of bPuntScreenToScreenCopyBits,
* except that it can handle funky ROPs and stuff.
\**************************************************************************/
BOOL bPuntScreenToScreenBitBlt(
PPDEV ppdev,
SURFOBJ* psoMask,
CLIPOBJ* pco,
XLATEOBJ* pxlo,
RECTL* prclDest,
POINTL* pptlSrc,
POINTL* pptlMask,
BRUSHOBJ* pbo,
POINTL* pptlBrush,
ROP4 rop4)
{
RECTL rclDest; // Temporary destination rectangle
POINTL ptlSrc; // Temporary source point
POINTL ptlMask; // Temporary mask offset
POINTL ptlMaskAdjust; // Adjustment for mask offset
BOOL b = TRUE;
SURFOBJ* pso = ppdev->pSurfObj;
SURFOBJ* psoTmp = ppdev->psoTmp;
if (psoMask != NULL)
{
ptlMaskAdjust.x = prclDest->left - pptlMask->x;
ptlMaskAdjust.y = prclDest->top - pptlMask->y;
}
if (prclDest->top < pptlSrc->y)
{
////////////////////////////////////////////////////////////////
// Do a top-to-bottom copy:
////////////////////////////////////////////////////////////////
LONG ySrcBottom;
LONG yDestBottom;
LONG yDestTop = prclDest->top;
LONG ySrcTop = pptlSrc->y;
LONG ySrcLast = ySrcTop + (prclDest->bottom - prclDest->top);
if (ySrcTop < ppdev->rcl1WindowClip.top ||
ySrcTop >= ppdev->rcl1WindowClip.bottom)
{
ppdev->pfnBankControl(ppdev, ySrcTop, JustifyTop);
}
pso->pvScan0 = ppdev->pvBitmapStart;
while (TRUE)
{
// Copy an entire source bank into the temporary buffer:
ySrcBottom = min(ySrcLast, ppdev->rcl1WindowClip.bottom);
ptlSrc.x = pptlSrc->x;
ptlSrc.y = ySrcTop;
rclDest.left = prclDest->left;
rclDest.top = 0;
rclDest.right = prclDest->right;
rclDest.bottom = ySrcBottom - ySrcTop;
b &= EngCopyBits(psoTmp, pso, NULL, NULL, &rclDest, &ptlSrc);
yDestBottom = yDestTop + rclDest.bottom;
if (ppdev->rcl1WindowClip.top >= yDestBottom)
{
ppdev->pfnBankControl(ppdev, yDestBottom - 1, JustifyBottom);
pso->pvScan0 = ppdev->pvBitmapStart;
}
while (TRUE)
{
// Copy the temporary buffer into one or more destination
// banks:
LONG yThisTop;
LONG yThisBottom;
LONG yOffset;
yThisBottom = min(yDestBottom, ppdev->rcl1WindowClip.bottom);
yThisTop = max(yDestTop, ppdev->rcl1WindowClip.top);
yOffset = yThisTop - yDestTop;
ptlSrc.x = prclDest->left;
ptlSrc.y = yOffset;
rclDest.left = prclDest->left;
rclDest.top = yThisTop;
rclDest.right = prclDest->right;
rclDest.bottom = yThisBottom;
ptlMask.x = rclDest.left - ptlMaskAdjust.x;
ptlMask.y = rclDest.top - ptlMaskAdjust.y;
b &= EngBitBlt(pso, psoTmp, psoMask, pco, pxlo, &rclDest,
&ptlSrc, &ptlMask, pbo, pptlBrush, rop4);
if (yOffset == 0)
break;
ppdev->pfnBankControl(ppdev, yThisTop - 1, JustifyBottom);
pso->pvScan0 = ppdev->pvBitmapStart;
}
if (ySrcBottom >= ySrcLast)
break;
yDestTop = yDestBottom;
ySrcTop = ySrcBottom;
ppdev->pfnBankControl(ppdev, ySrcTop, JustifyTop);
pso->pvScan0 = ppdev->pvBitmapStart;
}
}
else
{
////////////////////////////////////////////////////////////////
// Do a bottom-to-top copy:
////////////////////////////////////////////////////////////////
LONG ySrcTop;
LONG yDestTop;
LONG yDestBottom = prclDest->bottom;
LONG ySrcFirst = pptlSrc->y;
LONG ySrcBottom = ySrcFirst + (prclDest->bottom - prclDest->top);
if (ySrcBottom <= ppdev->rcl1WindowClip.top ||
ySrcBottom > ppdev->rcl1WindowClip.bottom)
{
ppdev->pfnBankControl(ppdev, ySrcBottom - 1, JustifyBottom);
}
pso->pvScan0 = ppdev->pvBitmapStart;
while (TRUE)
{
// Copy an entire source bank into the temporary buffer:
ySrcTop = max(ySrcFirst, ppdev->rcl1WindowClip.top);
ptlSrc.x = pptlSrc->x;
ptlSrc.y = ySrcTop;
rclDest.left = prclDest->left;
rclDest.top = 0;
rclDest.right = prclDest->right;
rclDest.bottom = ySrcBottom - ySrcTop;
b &= EngCopyBits(psoTmp, pso, NULL, NULL, &rclDest, &ptlSrc);
yDestTop = yDestBottom - rclDest.bottom;
if (ppdev->rcl1WindowClip.bottom <= yDestTop)
{
ppdev->pfnBankControl(ppdev, yDestTop, JustifyTop);
pso->pvScan0 = ppdev->pvBitmapStart;
}
while (TRUE)
{
// Copy the temporary buffer into one or more destination
// banks:
LONG yThisTop;
LONG yThisBottom;
LONG yOffset;
yThisTop = max(yDestTop, ppdev->rcl1WindowClip.top);
yThisBottom = min(yDestBottom, ppdev->rcl1WindowClip.bottom);
yOffset = yThisTop - yDestTop;
ptlSrc.x = prclDest->left;
ptlSrc.y = yOffset;
rclDest.left = prclDest->left;
rclDest.top = yThisTop;
rclDest.right = prclDest->right;
rclDest.bottom = yThisBottom;
ptlMask.x = rclDest.left - ptlMaskAdjust.x;
ptlMask.y = rclDest.top - ptlMaskAdjust.y;
b &= EngBitBlt(pso, psoTmp, psoMask, pco, pxlo, &rclDest,
&ptlSrc, &ptlMask, pbo, pptlBrush, rop4);
if (yThisBottom == yDestBottom)
break;
ppdev->pfnBankControl(ppdev, yThisBottom, JustifyTop);
pso->pvScan0 = ppdev->pvBitmapStart;
}
if (ySrcTop <= ySrcFirst)
break;
yDestBottom = yDestTop;
ySrcBottom = ySrcTop;
ppdev->pfnBankControl(ppdev, ySrcBottom - 1, JustifyBottom);
pso->pvScan0 = ppdev->pvBitmapStart;
}
}
return(b);
}
/******************************Public*Data*********************************\
* ROP to mix translation table
*
* Table to translate ternary raster ops to mixes (binary raster ops). Ternary
* raster ops that can't be translated to mixes are translated to 0 (0 is not
* a valid mix).
*
\**************************************************************************/
UCHAR jRop3ToMix[256] = {
R2_BLACK, 0, 0, 0, 0, R2_NOTMERGEPEN, 0, 0,
0, 0, R2_MASKNOTPEN, 0, 0, 0, 0, R2_NOTCOPYPEN,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
R2_MASKPENNOT, 0, 0, 0, 0, R2_NOT, 0, 0,
0, 0, R2_XORPEN, 0, 0, 0, 0, R2_NOTMASKPEN,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
R2_MASKPEN, 0, 0, 0, 0, R2_NOTXORPEN, 0, 0,
0, 0, R2_NOP, 0, 0, 0, 0, R2_MERGENOTPEN,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
R2_COPYPEN, 0, 0, 0, 0, R2_MERGEPENNOT, 0, 0,
0, 0, R2_MERGEPEN, 0, 0, 0, 0, R2_WHITE
};
/******************************Public*Routine******************************\
* BOOL DrvBitBlt(psoDest, psoSrc, psoMask, pco, pxlo, prclDest, pptlSrc,
* pptlMask, pbo, pptlBrush, rop4)
*
* This routine will handle any blit. Perhaps glacially, but it will be
* handled.
\**************************************************************************/
BOOL DrvBitBlt(
SURFOBJ* psoDest,
SURFOBJ* psoSrc,
SURFOBJ* psoMask,
CLIPOBJ* pco,
XLATEOBJ* pxlo,
RECTL* prclDest,
POINTL* pptlSrc,
POINTL* pptlMask,
BRUSHOBJ* pbo,
POINTL* pptlBrush,
ROP4 rop4)
{
BOOL b;
POINTL ptlSrc;
RECTL rclDest;
PPDEV ppdev;
SURFOBJ* pso;
BYTE jClipping;
RECTL rclTmp;
POINTL ptlTmp;
BBENUM bben; // Clip enumerator
BOOL bMore; // Clip continuation flag
POINTL ptlMask; // Temporary mask for engine call-backs
POINTL ptlMaskAdjust; // Adjustment for mask
INT iCopyDir;
// Set up the clipping type
if (pco == (CLIPOBJ *) NULL) {
// No CLIPOBJ provided, so we don't have to worry about clipping
jClipping = DC_TRIVIAL;
} else {
// Use the CLIPOBJ-provided clipping
jClipping = pco->iDComplexity;
}
// Get the correct surface object for the target and the source
if (psoDest->iType == STYPE_DEVICE) {
if ((psoSrc != NULL) && (psoSrc->iType == STYPE_DEVICE)) {
////////////////////////////////////////////////////////////////
// BitBlt screen-to-screen:
////////////////////////////////////////////////////////////////
ppdev = (PPDEV) psoDest->dhsurf;
// See if we can do a simple CopyBits:
if (rop4 == 0x0000CCCC)
{
ppdev = (PPDEV) psoDest->dhsurf;
// We can handle quadpixel-aligned screen-to-screen blts with
// no translation:
if ((((pptlSrc->x ^ prclDest->left) & 1) == 0) &&
(ppdev->fl & DRIVER_PLANAR_CAPABLE) &&
((pxlo == NULL) || (pxlo->flXlate & XO_TRIVIAL)))
{
switch(jClipping)
{
case DC_TRIVIAL:
vPlanarCopyBits(ppdev, prclDest, pptlSrc);
return(TRUE);
case DC_RECT:
// Clip the target rectangle to the clip rectangle:
if (!bIntersectRect(&rclTmp, prclDest, &pco->rclBounds))
{
DISPDBG((0, "DrvBitBlt: Nothing to draw."));
return(TRUE);
}
ptlTmp.x = pptlSrc->x + rclTmp.left - prclDest->left;
ptlTmp.y = pptlSrc->y + rclTmp.top - prclDest->top;
vPlanarCopyBits(ppdev, &rclTmp, &ptlTmp);
return(TRUE);
case DC_COMPLEX:
if (pptlSrc->y >= prclDest->top)
{
if (pptlSrc->x >= prclDest->left)
iCopyDir = CD_RIGHTDOWN;
else
iCopyDir = CD_LEFTDOWN;
}
else
{
if (pptlSrc->x >= prclDest->left)
iCopyDir = CD_RIGHTUP;
else
iCopyDir = CD_LEFTUP;
}
CLIPOBJ_cEnumStart(pco, FALSE, CT_RECTANGLES, iCopyDir, 0);
do {
RECTL* prcl;
RECTL* prclEnd;
bMore = CLIPOBJ_bEnum(pco, (ULONG) sizeof(bben),
(PVOID) &bben);
prclEnd = &bben.arcl[bben.c];
for (prcl = bben.arcl; prcl < prclEnd; prcl++)
{
if (bIntersectRect(prcl, prclDest, prcl))
{
ptlTmp.x = pptlSrc->x + prcl->left - prclDest->left;
ptlTmp.y = pptlSrc->y + prcl->top - prclDest->top;
vPlanarCopyBits(ppdev, prcl, &ptlTmp);
}
}
} while (bMore);
return(TRUE);
}
}
// Can't handle in hardware, so punt:
return(bPuntScreenToScreenCopyBits(ppdev,
pco,
pxlo,
prclDest,
pptlSrc));
}
// It's more complicated than a CopyBits, so punt it:
return(bPuntScreenToScreenBitBlt(ppdev,
psoMask,
pco,
pxlo,
prclDest,
pptlSrc,
pptlMask,
pbo,
pptlBrush,
rop4));
}
////////////////////////////////////////////////////////////////
// BitBlt to screen:
////////////////////////////////////////////////////////////////
ppdev = (PPDEV) psoDest->dhsurf;
// Punt the memory-to-screen call back to the engine:
if (psoMask != NULL)
{
ptlMaskAdjust.x = prclDest->left - pptlMask->x;
ptlMaskAdjust.y = prclDest->top - pptlMask->y;
}
pso = ppdev->pSurfObj;
vBankStartBltDest(ppdev, pso, pptlSrc, prclDest, &ptlSrc, &rclDest);
do {
ptlMask.x = rclDest.left - ptlMaskAdjust.x;
ptlMask.y = rclDest.top - ptlMaskAdjust.y;
b = EngBitBlt(pso,
psoSrc,
psoMask,
pco,
pxlo,
&rclDest,
&ptlSrc,
&ptlMask,
pbo,
pptlBrush,
rop4);
} while (b && bBankEnumBltDest(ppdev, pso, pptlSrc, prclDest,
&ptlSrc, &rclDest));
return(b);
}
else if ((psoSrc != NULL) && (psoSrc->iType == STYPE_DEVICE))
{
////////////////////////////////////////////////////////////////
// BitBlt from screen:
////////////////////////////////////////////////////////////////
if (psoMask != NULL)
{
ptlMaskAdjust.x = prclDest->left - pptlMask->x;
ptlMaskAdjust.y = prclDest->top - pptlMask->y;
}
ppdev = (PPDEV) psoSrc->dhsurf;
pso = ppdev->pSurfObj;
vBankStartBltSrc(ppdev, pso, pptlSrc, prclDest, &ptlSrc, &rclDest);
do {
ptlMask.x = rclDest.left - ptlMaskAdjust.x;
ptlMask.y = rclDest.top - ptlMaskAdjust.y;
b = EngBitBlt(psoDest,
pso,
psoMask,
pco,
pxlo,
&rclDest,
&ptlSrc,
&ptlMask,
pbo,
pptlBrush,
rop4);
} while (b && bBankEnumBltSrc(ppdev, pso, pptlSrc, prclDest,
&ptlSrc, &rclDest));
return(b);
}
RIP("Got a funky format?");
return(FALSE);
}
/***************************************************************************\
* DrvCopyBits
\***************************************************************************/
BOOL DrvCopyBits(
SURFOBJ* psoDest,
SURFOBJ* psoSrc,
CLIPOBJ* pco,
XLATEOBJ* pxlo,
RECTL* prclDest,
POINTL* pptlSrc)
{
BOOL b;
POINTL ptlSrc;
RECTL rclDest;
PPDEV ppdev;
SURFOBJ* pso;
BBENUM bben;
BOOL bMore;
BYTE jClipping;
POINTL ptlTmp;
RECTL rclTmp;
INT iCopyDir;
// Get the correct surface object for the target and the source
if (psoDest->iType == STYPE_DEVICE)
{
// We have to special case screen-to-screen operations:
if ((psoSrc != NULL) && (psoSrc->iType == STYPE_DEVICE))
{
////////////////////////////////////////////////////////////////
// CopyBits screen-to-screen:
////////////////////////////////////////////////////////////////
ppdev = (PPDEV) psoDest->dhsurf;
// We check to see if we can do a planar copy, because usually
// it will be faster. But the hardware has to be capable of
// doing it, and the source and destination must be 4-pel
// aligned.
if ((((pptlSrc->x ^ prclDest->left) & 1) == 0) &&
(ppdev->fl & DRIVER_PLANAR_CAPABLE) &&
((pxlo == NULL) || (pxlo->flXlate & XO_TRIVIAL)))
{
jClipping = (pco != NULL) ? pco->iDComplexity : DC_TRIVIAL;
switch(jClipping)
{
case DC_TRIVIAL:
vPlanarCopyBits(ppdev, prclDest, pptlSrc);
return(TRUE);
case DC_RECT:
// Clip the target rectangle to the clip rectangle:
if (!bIntersectRect(&rclTmp, prclDest, &pco->rclBounds))
{
DISPDBG((0, "DrvCopyBits: Nothing to draw."));
return(TRUE);
}
ptlTmp.x = pptlSrc->x + rclTmp.left - prclDest->left;
ptlTmp.y = pptlSrc->y + rclTmp.top - prclDest->top;
vPlanarCopyBits(ppdev, &rclTmp, &ptlTmp);
return(TRUE);
case DC_COMPLEX:
if (pptlSrc->y >= prclDest->top)
{
if (pptlSrc->x >= prclDest->left)
iCopyDir = CD_RIGHTDOWN;
else
iCopyDir = CD_LEFTDOWN;
}
else
{
if (pptlSrc->x >= prclDest->left)
iCopyDir = CD_RIGHTUP;
else
iCopyDir = CD_LEFTUP;
}
CLIPOBJ_cEnumStart(pco, FALSE, CT_RECTANGLES, iCopyDir, 0);
do {
RECTL* prcl;
RECTL* prclEnd;
bMore = CLIPOBJ_bEnum(pco, (ULONG) sizeof(bben),
(PVOID) &bben);
prclEnd = &bben.arcl[bben.c];
for (prcl = bben.arcl; prcl < prclEnd; prcl++)
{
if (bIntersectRect(prcl, prclDest, prcl))
{
ptlTmp.x = pptlSrc->x + prcl->left - prclDest->left;
ptlTmp.y = pptlSrc->y + prcl->top - prclDest->top;
vPlanarCopyBits(ppdev, prcl, &ptlTmp);
}
}
} while (bMore);
return(TRUE);
}
}
return(bPuntScreenToScreenCopyBits(ppdev,
pco,
pxlo,
prclDest,
pptlSrc));
}
ppdev = (PPDEV) psoDest->dhsurf;
// Fall back to the engine:
pso = ppdev->pSurfObj;
vBankStartBltDest(ppdev, pso, pptlSrc, prclDest, &ptlSrc, &rclDest);
do {
b = EngCopyBits(pso,
psoSrc,
pco,
pxlo,
&rclDest,
&ptlSrc);
} while (b && bBankEnumBltDest(ppdev, pso, pptlSrc, prclDest,
&ptlSrc, &rclDest));
return(b);
}
else if ((psoSrc != NULL) && (psoSrc->iType == STYPE_DEVICE))
{
////////////////////////////////////////////////////////////////
// CopyBits from screen:
////////////////////////////////////////////////////////////////
ppdev = (PPDEV) psoSrc->dhsurf;
pso = ppdev->pSurfObj;
vBankStartBltSrc(ppdev, pso, pptlSrc, prclDest, &ptlSrc, &rclDest);
do {
b = EngCopyBits(psoDest,
pso,
pco,
pxlo,
&rclDest,
&ptlSrc);
} while (b && bBankEnumBltSrc(ppdev, pso, pptlSrc, prclDest,
&ptlSrc, &rclDest));
return(b);
}
/* we should never be here */
return FALSE;
}