1033 lines
40 KiB
C
1033 lines
40 KiB
C
/******************************Module*Header*******************************\
|
|
* Module Name: copybits.c
|
|
*
|
|
* DrvCopyBits
|
|
*
|
|
* Copyright (c) 1992-1995 Microsoft Corporation
|
|
\**************************************************************************/
|
|
#include "driver.h"
|
|
#include "bitblt.h"
|
|
|
|
|
|
BOOL DrvCopyBits
|
|
(
|
|
SURFOBJ *psoTrg,
|
|
SURFOBJ *psoSrc,
|
|
CLIPOBJ *pco,
|
|
XLATEOBJ *pxlo,
|
|
PRECTL prclTrg,
|
|
PPOINTL pptlSrc
|
|
)
|
|
{
|
|
PDEVSURF pdsurf; // Pointer to a device surface
|
|
|
|
LONG lDelta; // Delta to next scan of destination
|
|
PVOID pjDstScan0; // Pointer to scan 0 of destination DIB
|
|
ULONG *pulXlate; // Pointer to color xlate vector
|
|
|
|
BOOL bMore; // Clip continuation flag
|
|
ULONG ircl; // Clip enumeration rectangle index
|
|
RECT_ENUM cben; // Clip enumerator
|
|
RECTL rclTemp;
|
|
PRECTL prcl;
|
|
POINTL ptlTemp;
|
|
DEVSURF dsurfTmp;
|
|
PDEVSURF pdsurfTrg; // Pointer for target
|
|
PDEVSURF pdsurfSrc; // Pointer for source if present
|
|
INT iCopyDir;
|
|
PFN_ScreenToScreenBlt pfn_Blt;
|
|
RECT_ENUM bben; // Clip enumerator
|
|
BYTE jClipping;
|
|
UCHAR *pucDIB4ToVGAConvTables;
|
|
|
|
ULONG ulWidth;
|
|
ULONG ulNumSlices;
|
|
ULONG ulRight;
|
|
|
|
ULONG x;
|
|
|
|
|
|
//
|
|
// if you remove the following code that sets pxlo to NULL for trivial
|
|
// XLATEOBJs then you must go find all checks the text pxlo, and add
|
|
// a check for (pxlo->flXlate & XO_TRIVIAL)
|
|
//
|
|
// ie. change all pxlo => (pxlo && !(pxlo->flXlate & XO_TRIVIAL))
|
|
//
|
|
|
|
if (pxlo && (pxlo->flXlate & XO_TRIVIAL))
|
|
{
|
|
pxlo = NULL;
|
|
}
|
|
|
|
if (pxlo &&
|
|
((psoTrg->iType == STYPE_DEVICE)||(psoTrg->iType == STYPE_DEVBITMAP)))
|
|
{
|
|
//
|
|
// send through blt compiler because we won't do translates for DFBs
|
|
//
|
|
// note: blt compiler can't handle DIB targets
|
|
//
|
|
|
|
return(DrvBitBlt(psoTrg,
|
|
psoSrc,
|
|
(SURFOBJ *) NULL,
|
|
pco,
|
|
pxlo,
|
|
prclTrg,
|
|
pptlSrc,
|
|
(POINTL *) NULL,
|
|
(BRUSHOBJ *) NULL,
|
|
(POINTL *) NULL,
|
|
0x0000cccc));
|
|
}
|
|
|
|
// Check for device surface to device surface
|
|
|
|
if ((psoTrg->iType == STYPE_DEVICE) && (psoSrc->iType == STYPE_DEVICE)) {
|
|
pdsurfTrg = (PDEVSURF) psoTrg->dhsurf;
|
|
pdsurfSrc = (PDEVSURF) psoSrc->dhsurf;
|
|
|
|
// It's a screen-to-screen aligned SRCCOPY; special-case it
|
|
|
|
// Determine the direction in which the copy must proceed
|
|
// Note that although we could detect cases where the source
|
|
// and dest don't overlap and handle them top to bottom, all
|
|
// copy directions are equally fast, so there's no reason to go
|
|
// top to bottom except possibly that it looks better. But it
|
|
// also takes time to detect non-overlap, so I'm not doing it
|
|
|
|
// 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;
|
|
}
|
|
|
|
|
|
if (pptlSrc->y >= prclTrg->top) {
|
|
if (pptlSrc->x >= prclTrg->left) {
|
|
iCopyDir = CD_RIGHTDOWN;
|
|
} else {
|
|
iCopyDir = CD_LEFTDOWN;
|
|
}
|
|
} else {
|
|
if (pptlSrc->x >= prclTrg->left) {
|
|
iCopyDir = CD_RIGHTUP;
|
|
} else {
|
|
iCopyDir = CD_LEFTUP;
|
|
}
|
|
}
|
|
|
|
//
|
|
// These values are expected by vAlignedSrcCopy
|
|
//
|
|
|
|
switch(jClipping) {
|
|
|
|
case DC_TRIVIAL:
|
|
// Just copy the rectangle
|
|
if ((((prclTrg->left ^ pptlSrc->x) & 0x07) == 0)) {
|
|
vAlignedSrcCopy(pdsurfTrg, prclTrg,
|
|
pptlSrc, iCopyDir);
|
|
} else {
|
|
vNonAlignedSrcCopy(pdsurfTrg, prclTrg,
|
|
pptlSrc, iCopyDir);
|
|
}
|
|
break;
|
|
|
|
case DC_RECT:
|
|
// Clip the solid fill to the clip rectangle
|
|
if (!DrvIntersectRect(&rclTemp, prclTrg,
|
|
&pco->rclBounds)) {
|
|
// Nothing to draw; completely clipped
|
|
return TRUE;
|
|
}
|
|
|
|
// Adjust the source point for clipping too
|
|
ptlTemp.x = pptlSrc->x + rclTemp.left - prclTrg->left;
|
|
ptlTemp.y = pptlSrc->y + rclTemp.top - prclTrg->top;
|
|
|
|
// Copy the clipped rectangle
|
|
if ((((prclTrg->left ^ pptlSrc->x) & 0x07) == 0)) {
|
|
vAlignedSrcCopy(pdsurfTrg, &rclTemp, &ptlTemp,
|
|
iCopyDir);
|
|
} else {
|
|
vNonAlignedSrcCopy(pdsurfTrg, &rclTemp, &ptlTemp,
|
|
iCopyDir);
|
|
}
|
|
break;
|
|
|
|
case DC_COMPLEX:
|
|
|
|
if ((((prclTrg->left ^ pptlSrc->x) & 0x07) == 0)) {
|
|
pfn_Blt = vAlignedSrcCopy;
|
|
} else {
|
|
pfn_Blt = vNonAlignedSrcCopy;
|
|
}
|
|
|
|
CLIPOBJ_cEnumStart(pco, FALSE, CT_RECTANGLES,
|
|
iCopyDir, ENUM_RECT_LIMIT);
|
|
|
|
do {
|
|
bMore = CLIPOBJ_bEnum(pco,(ULONG) sizeof(bben),
|
|
(PVOID) &bben);
|
|
|
|
prcl = bben.arcl;
|
|
for (ircl = 0; ircl < bben.c; ircl++, prcl++) {
|
|
|
|
DrvIntersectRect(prcl,prcl,prclTrg);
|
|
|
|
// Adjust the source point for clipping too
|
|
ptlTemp.x = pptlSrc->x + prcl->left -
|
|
prclTrg->left;
|
|
ptlTemp.y = pptlSrc->y + prcl->top -
|
|
prclTrg->top;
|
|
pfn_Blt(pdsurfTrg, prcl,
|
|
&ptlTemp, iCopyDir);
|
|
|
|
}
|
|
} while(bMore);
|
|
break;
|
|
}
|
|
return TRUE;
|
|
}
|
|
|
|
if ((psoSrc->iType == STYPE_DEVBITMAP) && (psoTrg->iType == STYPE_BITMAP)) {
|
|
//
|
|
// DFB to DIB
|
|
//
|
|
|
|
switch(psoTrg->iBitmapFormat)
|
|
{
|
|
case BMF_4BPP: // special case compatible DIBs with no translation
|
|
|
|
if (pxlo == NULL)
|
|
{
|
|
// Make just enough of a fake DEVSURF for the dest so that
|
|
// the DFB to DIB code can work
|
|
|
|
dsurfTmp.lNextScan = psoTrg->lDelta;
|
|
dsurfTmp.pvBitmapStart = psoTrg->pvScan0;
|
|
|
|
// Clip as needed
|
|
|
|
if ((pco == NULL) || (pco->iDComplexity == DC_TRIVIAL)) {
|
|
|
|
// No clipping, just copy the DFB to the DIB
|
|
|
|
ulWidth = prclTrg->right - prclTrg->left;
|
|
|
|
if (ulWidth <= MAX_SCAN_WIDTH) {
|
|
vDFB2DIB(&dsurfTmp, (PDEVSURF) psoSrc->dhsurf,
|
|
prclTrg, pptlSrc);
|
|
} else {
|
|
rclTemp.left = prclTrg->left;
|
|
rclTemp.right = prclTrg->right;
|
|
rclTemp.top = prclTrg->top;
|
|
rclTemp.bottom = prclTrg->bottom;
|
|
|
|
//
|
|
// cut rect into slices MAX_SCAN_WIDTH wide
|
|
//
|
|
ulRight = rclTemp.right; // save right edge
|
|
rclTemp.right = rclTemp.left+MAX_SCAN_WIDTH;
|
|
ulNumSlices = (ulWidth+MAX_SCAN_WIDTH-1) / MAX_SCAN_WIDTH;
|
|
for (x=0; x<ulNumSlices-1; x++) {
|
|
// Adjust the source point for clipping too
|
|
ptlTemp.x = pptlSrc->x + rclTemp.left - prclTrg->left;
|
|
ptlTemp.y = pptlSrc->y + rclTemp.top - prclTrg->top;
|
|
vDFB2DIB(&dsurfTmp, (PDEVSURF) psoSrc->dhsurf,
|
|
&rclTemp, &ptlTemp);
|
|
rclTemp.left = rclTemp.right;
|
|
rclTemp.right += MAX_SCAN_WIDTH;
|
|
}
|
|
rclTemp.right = ulRight;
|
|
// Adjust the source point for clipping too
|
|
ptlTemp.x = pptlSrc->x + rclTemp.left - prclTrg->left;
|
|
ptlTemp.y = pptlSrc->y + rclTemp.top - prclTrg->top;
|
|
vDFB2DIB(&dsurfTmp, (PDEVSURF) psoSrc->dhsurf,
|
|
&rclTemp, &ptlTemp);
|
|
}
|
|
}
|
|
else if (pco->iDComplexity == DC_RECT) {
|
|
|
|
// Clip the destination to the clip rectangle; we
|
|
// should never get a NULL result
|
|
|
|
if (DrvIntersectRect(&rclTemp, prclTrg, &pco->rclBounds)) {
|
|
|
|
ulWidth = rclTemp.right - rclTemp.left;
|
|
|
|
if (ulWidth <= MAX_SCAN_WIDTH) {
|
|
// Adjust the source point for clipping too
|
|
ptlTemp.x = pptlSrc->x + rclTemp.left - prclTrg->left;
|
|
ptlTemp.y = pptlSrc->y + rclTemp.top - prclTrg->top;
|
|
vDFB2DIB(&dsurfTmp, (PDEVSURF) psoSrc->dhsurf,
|
|
&rclTemp, &ptlTemp);
|
|
} else {
|
|
//
|
|
// cut rect into slices MAX_SCAN_WIDTH wide
|
|
//
|
|
ulRight = rclTemp.right; // save right edge
|
|
rclTemp.right = rclTemp.left+MAX_SCAN_WIDTH;
|
|
ulNumSlices = (ulWidth+MAX_SCAN_WIDTH-1) / MAX_SCAN_WIDTH;
|
|
for (x=0; x<ulNumSlices-1; x++) {
|
|
// Adjust the source point for clipping too
|
|
ptlTemp.x = pptlSrc->x + rclTemp.left - prclTrg->left;
|
|
ptlTemp.y = pptlSrc->y + rclTemp.top - prclTrg->top;
|
|
vDFB2DIB(&dsurfTmp, (PDEVSURF) psoSrc->dhsurf,
|
|
&rclTemp, &ptlTemp);
|
|
rclTemp.left = rclTemp.right;
|
|
rclTemp.right += MAX_SCAN_WIDTH;
|
|
}
|
|
rclTemp.right = ulRight;
|
|
// Adjust the source point for clipping too
|
|
ptlTemp.x = pptlSrc->x + rclTemp.left - prclTrg->left;
|
|
ptlTemp.y = pptlSrc->y + rclTemp.top - prclTrg->top;
|
|
vDFB2DIB(&dsurfTmp, (PDEVSURF) psoSrc->dhsurf,
|
|
&rclTemp, &ptlTemp);
|
|
}
|
|
}
|
|
return(TRUE);
|
|
|
|
} else { // DC_COMPLEX:
|
|
|
|
CLIPOBJ_cEnumStart(pco, FALSE, CT_RECTANGLES,
|
|
CD_ANY, ENUM_RECT_LIMIT);
|
|
|
|
do {
|
|
bMore = CLIPOBJ_bEnum(pco,(ULONG) sizeof(bben),
|
|
(PVOID) &bben);
|
|
prcl = bben.arcl;
|
|
for (ircl = 0; ircl < bben.c; ircl++, prcl++) {
|
|
|
|
// Clip the destination to the clip rectangle;
|
|
// we should never get a NULL result
|
|
DrvIntersectRect(prcl,prcl,prclTrg);
|
|
|
|
ulWidth = prcl->right - prcl->left;
|
|
|
|
if (ulWidth <= MAX_SCAN_WIDTH) {
|
|
// Adjust the source point for clipping too
|
|
ptlTemp.x = pptlSrc->x + prcl->left - prclTrg->left;
|
|
ptlTemp.y = pptlSrc->y + prcl->top - prclTrg->top;
|
|
vDFB2DIB(&dsurfTmp, (PDEVSURF) psoSrc->dhsurf,
|
|
prcl, &ptlTemp);
|
|
} else {
|
|
//
|
|
// cut rect into slices MAX_SCAN_WIDTH wide
|
|
//
|
|
ulRight = prcl->right; // save right edge
|
|
prcl->right = prcl->left+MAX_SCAN_WIDTH;
|
|
ulNumSlices = (ulWidth+MAX_SCAN_WIDTH-1) / MAX_SCAN_WIDTH;
|
|
for (x=0; x<ulNumSlices-1; x++) {
|
|
// Adjust the source point for clipping too
|
|
ptlTemp.x = pptlSrc->x + prcl->left - prclTrg->left;
|
|
ptlTemp.y = pptlSrc->y + prcl->top - prclTrg->top;
|
|
vDFB2DIB(&dsurfTmp, (PDEVSURF) psoSrc->dhsurf,
|
|
prcl, &ptlTemp);
|
|
prcl->left = prcl->right;
|
|
prcl->right += MAX_SCAN_WIDTH;
|
|
}
|
|
prcl->right = ulRight;
|
|
// Adjust the source point for clipping too
|
|
ptlTemp.x = pptlSrc->x + prcl->left - prclTrg->left;
|
|
ptlTemp.y = pptlSrc->y + prcl->top - prclTrg->top;
|
|
vDFB2DIB(&dsurfTmp, (PDEVSURF) psoSrc->dhsurf,
|
|
prcl, &ptlTemp);
|
|
}
|
|
}
|
|
} while(bMore);
|
|
|
|
}
|
|
|
|
return(TRUE);
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
|
|
if ((psoSrc->iType == STYPE_DEVBITMAP) && (psoTrg->iType == STYPE_DEVBITMAP)) {
|
|
//
|
|
// DFB to DFB
|
|
//
|
|
|
|
if (psoSrc==psoTrg) // Src and Trg are same DFB
|
|
{
|
|
rclTemp.top = pptlSrc->y;
|
|
rclTemp.left = pptlSrc->x;
|
|
rclTemp.bottom = pptlSrc->y + (prclTrg->bottom - prclTrg->top);
|
|
rclTemp.right = pptlSrc->x + (prclTrg->right - prclTrg->left);
|
|
|
|
//
|
|
// if the copy overlaps and the dst is lower than or equal to the
|
|
// src, then corruption would occur if we use a left to right, top
|
|
// to bottom copy. Therefore, we would copy through the blt
|
|
// compiler which will copy the other way
|
|
//
|
|
|
|
if (prclTrg->top >= pptlSrc->y)
|
|
{
|
|
if (DrvIntersectRect(&rclTemp,&rclTemp,prclTrg))
|
|
{
|
|
return(DrvBitBlt(psoTrg, // send through blt compiler
|
|
psoSrc,
|
|
(SURFOBJ *) NULL,
|
|
pco,
|
|
pxlo,
|
|
prclTrg,
|
|
pptlSrc,
|
|
(POINTL *) NULL,
|
|
(BRUSHOBJ *) NULL,
|
|
(POINTL *) NULL,
|
|
0x0000cccc));
|
|
}
|
|
}
|
|
}
|
|
|
|
if (pxlo == NULL)
|
|
{
|
|
// Clip as needed
|
|
|
|
if ((pco == NULL) || (pco->iDComplexity == DC_TRIVIAL)) {
|
|
|
|
// No clipping, just copy the DFB to the DFB
|
|
|
|
vDFB2DFB((PDEVSURF) psoTrg->dhsurf, (PDEVSURF) psoSrc->dhsurf, prclTrg,
|
|
pptlSrc);
|
|
|
|
} else if (pco->iDComplexity == DC_RECT) {
|
|
|
|
// Clip the destination to the clip rectangle; we
|
|
// should never get a NULL result
|
|
if (DrvIntersectRect(&rclTemp, prclTrg, &pco->rclBounds)) {
|
|
|
|
// Adjust the source point for clipping too
|
|
ptlTemp.x = pptlSrc->x + rclTemp.left - prclTrg->left;
|
|
ptlTemp.y = pptlSrc->y + rclTemp.top - prclTrg->top;
|
|
|
|
// Blt the clipped rectangle
|
|
vDFB2DFB((PDEVSURF) psoTrg->dhsurf, (PDEVSURF) psoSrc->dhsurf,
|
|
&rclTemp, &ptlTemp);
|
|
}
|
|
return(TRUE);
|
|
|
|
} else { // DC_COMPLEX:
|
|
|
|
CLIPOBJ_cEnumStart(pco, FALSE, CT_RECTANGLES,
|
|
CD_ANY, ENUM_RECT_LIMIT);
|
|
|
|
do {
|
|
bMore = CLIPOBJ_bEnum(pco,(ULONG) sizeof(bben),
|
|
(PVOID) &bben);
|
|
prcl = bben.arcl;
|
|
for (ircl = 0; ircl < bben.c; ircl++, prcl++) {
|
|
|
|
// Clip the destination to the clip rectangle;
|
|
// we should never get a NULL result
|
|
DrvIntersectRect(prcl,prcl,prclTrg);
|
|
|
|
// Adjust the source point for clipping too
|
|
ptlTemp.x = pptlSrc->x + prcl->left -
|
|
prclTrg->left;
|
|
ptlTemp.y = pptlSrc->y + prcl->top -
|
|
prclTrg->top;
|
|
|
|
// Blt the clipped rectangle
|
|
vDFB2DFB((PDEVSURF) psoTrg->dhsurf,
|
|
(PDEVSURF) psoSrc->dhsurf, prcl, &ptlTemp);
|
|
}
|
|
} while(bMore);
|
|
|
|
}
|
|
|
|
return(TRUE);
|
|
}
|
|
}
|
|
|
|
if ((psoSrc->iType == STYPE_DEVBITMAP) && (psoTrg->iType == STYPE_DEVICE)) {
|
|
//
|
|
// DFB to screen
|
|
//
|
|
|
|
if (pxlo == NULL)
|
|
{
|
|
// Clip as needed
|
|
|
|
if ((pco == NULL) || (pco->iDComplexity == DC_TRIVIAL)) {
|
|
|
|
// No clipping, just copy the DFB to the VGA
|
|
|
|
vDFB2VGA((PDEVSURF) psoTrg->dhsurf, (PDEVSURF) psoSrc->dhsurf, prclTrg,
|
|
pptlSrc);
|
|
|
|
} else if (pco->iDComplexity == DC_RECT) {
|
|
|
|
// Clip the destination to the clip rectangle; we
|
|
// should never get a NULL result
|
|
if (DrvIntersectRect(&rclTemp, prclTrg, &pco->rclBounds)) {
|
|
|
|
// Adjust the source point for clipping too
|
|
ptlTemp.x = pptlSrc->x + rclTemp.left - prclTrg->left;
|
|
ptlTemp.y = pptlSrc->y + rclTemp.top - prclTrg->top;
|
|
|
|
// Blt the clipped rectangle
|
|
vDFB2VGA((PDEVSURF) psoTrg->dhsurf, (PDEVSURF) psoSrc->dhsurf,
|
|
&rclTemp, &ptlTemp);
|
|
}
|
|
return(TRUE);
|
|
|
|
} else { // DC_COMPLEX:
|
|
|
|
CLIPOBJ_cEnumStart(pco, FALSE, CT_RECTANGLES,
|
|
CD_ANY, ENUM_RECT_LIMIT);
|
|
|
|
do {
|
|
bMore = CLIPOBJ_bEnum(pco,(ULONG) sizeof(bben),
|
|
(PVOID) &bben);
|
|
prcl = bben.arcl;
|
|
for (ircl = 0; ircl < bben.c; ircl++, prcl++) {
|
|
|
|
// Clip the destination to the clip rectangle;
|
|
// we should never get a NULL result
|
|
DrvIntersectRect(prcl,prcl,prclTrg);
|
|
|
|
// Adjust the source point for clipping too
|
|
ptlTemp.x = pptlSrc->x + prcl->left -
|
|
prclTrg->left;
|
|
ptlTemp.y = pptlSrc->y + prcl->top -
|
|
prclTrg->top;
|
|
|
|
// Blt the clipped rectangle
|
|
vDFB2VGA((PDEVSURF) psoTrg->dhsurf,
|
|
(PDEVSURF) psoSrc->dhsurf, prcl, &ptlTemp);
|
|
}
|
|
} while(bMore);
|
|
|
|
}
|
|
|
|
return(TRUE);
|
|
}
|
|
}
|
|
|
|
if ((psoSrc->iType == STYPE_BITMAP) && (psoTrg->iType == STYPE_DEVBITMAP)) {
|
|
//
|
|
// DIB to DFB
|
|
//
|
|
|
|
switch(psoSrc->iBitmapFormat)
|
|
{
|
|
case BMF_4BPP: // special case compatible DIBs with no translation
|
|
|
|
if (pxlo == NULL)
|
|
{
|
|
pucDIB4ToVGAConvTables =
|
|
((PDEVSURF) psoTrg->dhsurf)->ppdev->
|
|
pucDIB4ToVGAConvTables;
|
|
|
|
// Make just enough of a fake DEVSURF for the source so that
|
|
// the DIB to DFB code can work
|
|
|
|
dsurfTmp.lNextScan = psoSrc->lDelta;
|
|
dsurfTmp.pvBitmapStart = psoSrc->pvScan0;
|
|
|
|
// Clip as needed
|
|
|
|
if ((pco == NULL) || (pco->iDComplexity == DC_TRIVIAL)) {
|
|
|
|
// No clipping, just copy the DFB to the DIB
|
|
|
|
ulWidth = prclTrg->right - prclTrg->left;
|
|
|
|
if (ulWidth <= MAX_SCAN_WIDTH) {
|
|
vDIB2VGA((PDEVSURF) psoTrg->dhsurf, &dsurfTmp, prclTrg,
|
|
pptlSrc, pucDIB4ToVGAConvTables, DFB_TARGET);
|
|
} else {
|
|
rclTemp.left = prclTrg->left;
|
|
rclTemp.right = prclTrg->right;
|
|
rclTemp.top = prclTrg->top;
|
|
rclTemp.bottom = prclTrg->bottom;
|
|
|
|
//
|
|
// cut rect into slices MAX_SCAN_WIDTH wide
|
|
//
|
|
ulRight = rclTemp.right; // save right edge
|
|
rclTemp.right = rclTemp.left+MAX_SCAN_WIDTH;
|
|
ulNumSlices = (ulWidth+MAX_SCAN_WIDTH-1) / MAX_SCAN_WIDTH;
|
|
for (x=0; x<ulNumSlices-1; x++) {
|
|
// Adjust the source point for clipping too
|
|
ptlTemp.x = pptlSrc->x + rclTemp.left - prclTrg->left;
|
|
ptlTemp.y = pptlSrc->y + rclTemp.top - prclTrg->top;
|
|
vDIB2VGA((PDEVSURF) psoTrg->dhsurf, &dsurfTmp,
|
|
&rclTemp, &ptlTemp, pucDIB4ToVGAConvTables, DFB_TARGET);
|
|
rclTemp.left = rclTemp.right;
|
|
rclTemp.right += MAX_SCAN_WIDTH;
|
|
}
|
|
rclTemp.right = ulRight;
|
|
// Adjust the source point for clipping too
|
|
ptlTemp.x = pptlSrc->x + rclTemp.left - prclTrg->left;
|
|
ptlTemp.y = pptlSrc->y + rclTemp.top - prclTrg->top;
|
|
vDIB2VGA((PDEVSURF) psoTrg->dhsurf, &dsurfTmp,
|
|
&rclTemp, &ptlTemp, pucDIB4ToVGAConvTables, DFB_TARGET);
|
|
}
|
|
}
|
|
else if (pco->iDComplexity == DC_RECT) {
|
|
|
|
// Clip the destination to the clip rectangle; we
|
|
// should never get a NULL result
|
|
|
|
if (DrvIntersectRect(&rclTemp, prclTrg, &pco->rclBounds)) {
|
|
|
|
ulWidth = rclTemp.right - rclTemp.left;
|
|
|
|
if (ulWidth <= MAX_SCAN_WIDTH) {
|
|
// Adjust the source point for clipping too
|
|
ptlTemp.x = pptlSrc->x + rclTemp.left - prclTrg->left;
|
|
ptlTemp.y = pptlSrc->y + rclTemp.top - prclTrg->top;
|
|
vDIB2VGA((PDEVSURF) psoTrg->dhsurf, &dsurfTmp,
|
|
&rclTemp, &ptlTemp, pucDIB4ToVGAConvTables, DFB_TARGET);
|
|
} else {
|
|
//
|
|
// cut rect into slices MAX_SCAN_WIDTH wide
|
|
//
|
|
ulRight = rclTemp.right; // save right edge
|
|
rclTemp.right = rclTemp.left+MAX_SCAN_WIDTH;
|
|
ulNumSlices = (ulWidth+MAX_SCAN_WIDTH-1) / MAX_SCAN_WIDTH;
|
|
for (x=0; x<ulNumSlices-1; x++) {
|
|
// Adjust the source point for clipping too
|
|
ptlTemp.x = pptlSrc->x + rclTemp.left - prclTrg->left;
|
|
ptlTemp.y = pptlSrc->y + rclTemp.top - prclTrg->top;
|
|
vDIB2VGA((PDEVSURF) psoTrg->dhsurf, &dsurfTmp,
|
|
&rclTemp, &ptlTemp, pucDIB4ToVGAConvTables, DFB_TARGET);
|
|
rclTemp.left = rclTemp.right;
|
|
rclTemp.right += MAX_SCAN_WIDTH;
|
|
}
|
|
rclTemp.right = ulRight;
|
|
// Adjust the source point for clipping too
|
|
ptlTemp.x = pptlSrc->x + rclTemp.left - prclTrg->left;
|
|
ptlTemp.y = pptlSrc->y + rclTemp.top - prclTrg->top;
|
|
vDIB2VGA((PDEVSURF) psoTrg->dhsurf, &dsurfTmp,
|
|
&rclTemp, &ptlTemp, pucDIB4ToVGAConvTables, DFB_TARGET);
|
|
}
|
|
}
|
|
return(TRUE);
|
|
|
|
} else { // DC_COMPLEX:
|
|
|
|
CLIPOBJ_cEnumStart(pco, FALSE, CT_RECTANGLES,
|
|
CD_ANY, ENUM_RECT_LIMIT);
|
|
|
|
do {
|
|
bMore = CLIPOBJ_bEnum(pco,(ULONG) sizeof(bben),
|
|
(PVOID) &bben);
|
|
prcl = bben.arcl;
|
|
for (ircl = 0; ircl < bben.c; ircl++, prcl++) {
|
|
|
|
// Clip the destination to the clip rectangle;
|
|
// we should never get a NULL result
|
|
DrvIntersectRect(prcl,prcl,prclTrg);
|
|
|
|
ulWidth = prcl->right - prcl->left;
|
|
|
|
if (ulWidth <= MAX_SCAN_WIDTH) {
|
|
// Adjust the source point for clipping too
|
|
ptlTemp.x = pptlSrc->x + prcl->left - prclTrg->left;
|
|
ptlTemp.y = pptlSrc->y + prcl->top - prclTrg->top;
|
|
vDIB2VGA((PDEVSURF) psoTrg->dhsurf, &dsurfTmp,
|
|
prcl, &ptlTemp, pucDIB4ToVGAConvTables, DFB_TARGET);
|
|
} else {
|
|
//
|
|
// cut rect into slices MAX_SCAN_WIDTH wide
|
|
//
|
|
ulRight = prcl->right; // save right edge
|
|
prcl->right = prcl->left+MAX_SCAN_WIDTH;
|
|
ulNumSlices = (ulWidth+MAX_SCAN_WIDTH-1) / MAX_SCAN_WIDTH;
|
|
for (x=0; x<ulNumSlices-1; x++) {
|
|
// Adjust the source point for clipping too
|
|
ptlTemp.x = pptlSrc->x + prcl->left - prclTrg->left;
|
|
ptlTemp.y = pptlSrc->y + prcl->top - prclTrg->top;
|
|
vDIB2VGA((PDEVSURF) psoTrg->dhsurf, &dsurfTmp,
|
|
prcl, &ptlTemp, pucDIB4ToVGAConvTables, DFB_TARGET);
|
|
prcl->left = prcl->right;
|
|
prcl->right += MAX_SCAN_WIDTH;
|
|
}
|
|
prcl->right = ulRight;
|
|
// Adjust the source point for clipping too
|
|
ptlTemp.x = pptlSrc->x + prcl->left - prclTrg->left;
|
|
ptlTemp.y = pptlSrc->y + prcl->top - prclTrg->top;
|
|
vDIB2VGA((PDEVSURF) psoTrg->dhsurf, &dsurfTmp,
|
|
prcl, &ptlTemp, pucDIB4ToVGAConvTables, DFB_TARGET);
|
|
}
|
|
}
|
|
} while(bMore);
|
|
|
|
}
|
|
|
|
return(TRUE);
|
|
}
|
|
break;
|
|
|
|
case BMF_1BPP:
|
|
case BMF_8BPP:
|
|
return(DrvBitBlt(psoTrg, // send through blt compiler
|
|
psoSrc,
|
|
(SURFOBJ *) NULL,
|
|
pco,
|
|
pxlo,
|
|
prclTrg,
|
|
pptlSrc,
|
|
(POINTL *) NULL,
|
|
(BRUSHOBJ *) NULL,
|
|
(POINTL *) NULL,
|
|
0x0000cccc));
|
|
}
|
|
}
|
|
|
|
if ((psoSrc->iType == STYPE_BITMAP) && (psoTrg->iType == STYPE_DEVICE)) {
|
|
//
|
|
// DIB to screen
|
|
//
|
|
|
|
switch(psoSrc->iBitmapFormat)
|
|
{
|
|
case BMF_4BPP: // special case compatible DIBs with no translation
|
|
|
|
if (pxlo == NULL)
|
|
{
|
|
pucDIB4ToVGAConvTables =
|
|
((PDEVSURF) psoTrg->dhsurf)->ppdev->
|
|
pucDIB4ToVGAConvTables;
|
|
|
|
// Make just enough of a fake DEVSURF for the source so that
|
|
// the DIB to VGA code can work
|
|
|
|
dsurfTmp.lNextScan = psoSrc->lDelta;
|
|
dsurfTmp.pvBitmapStart = psoSrc->pvScan0;
|
|
|
|
// Clip as needed
|
|
|
|
if ((pco == NULL) || (pco->iDComplexity == DC_TRIVIAL)) {
|
|
|
|
// No clipping, just copy the DIB to the VGA
|
|
|
|
vDIB2VGA((PDEVSURF) psoTrg->dhsurf, &dsurfTmp, prclTrg,
|
|
pptlSrc, pucDIB4ToVGAConvTables, VGA_TARGET);
|
|
|
|
} else if (pco->iDComplexity == DC_RECT) {
|
|
|
|
// Clip the destination to the clip rectangle; we
|
|
// should never get a NULL result
|
|
if (DrvIntersectRect(&rclTemp, prclTrg, &pco->rclBounds)) {
|
|
|
|
// Adjust the source point for clipping too
|
|
ptlTemp.x = pptlSrc->x + rclTemp.left - prclTrg->left;
|
|
ptlTemp.y = pptlSrc->y + rclTemp.top - prclTrg->top;
|
|
|
|
// Blt the clipped rectangle
|
|
vDIB2VGA((PDEVSURF) psoTrg->dhsurf, &dsurfTmp,
|
|
&rclTemp, &ptlTemp, pucDIB4ToVGAConvTables, VGA_TARGET);
|
|
}
|
|
return(TRUE);
|
|
|
|
} else { // DC_COMPLEX:
|
|
|
|
CLIPOBJ_cEnumStart(pco, FALSE, CT_RECTANGLES,
|
|
CD_ANY, ENUM_RECT_LIMIT);
|
|
|
|
do {
|
|
bMore = CLIPOBJ_bEnum(pco,(ULONG) sizeof(bben),
|
|
(PVOID) &bben);
|
|
prcl = bben.arcl;
|
|
for (ircl = 0; ircl < bben.c; ircl++, prcl++) {
|
|
|
|
// Clip the destination to the clip rectangle;
|
|
// we should never get a NULL result
|
|
DrvIntersectRect(prcl,prcl,prclTrg);
|
|
|
|
// Adjust the source point for clipping too
|
|
ptlTemp.x = pptlSrc->x + prcl->left -
|
|
prclTrg->left;
|
|
ptlTemp.y = pptlSrc->y + prcl->top -
|
|
prclTrg->top;
|
|
|
|
// Blt the clipped rectangle
|
|
vDIB2VGA((PDEVSURF) psoTrg->dhsurf,
|
|
&dsurfTmp, prcl, &ptlTemp,
|
|
pucDIB4ToVGAConvTables, VGA_TARGET);
|
|
}
|
|
} while(bMore);
|
|
|
|
}
|
|
|
|
return(TRUE);
|
|
}
|
|
break;
|
|
|
|
case BMF_1BPP:
|
|
case BMF_8BPP:
|
|
return(DrvBitBlt(psoTrg, // send through blt compiler
|
|
psoSrc,
|
|
(SURFOBJ *) NULL,
|
|
pco,
|
|
pxlo,
|
|
prclTrg,
|
|
pptlSrc,
|
|
(POINTL *) NULL,
|
|
(BRUSHOBJ *) NULL,
|
|
(POINTL *) NULL,
|
|
0x0000cccc));
|
|
|
|
case BMF_8RLE:
|
|
case BMF_4RLE:
|
|
return(bRleBlt(psoTrg, psoSrc, pco, pxlo, prclTrg, pptlSrc));
|
|
|
|
}
|
|
}
|
|
|
|
if ((psoSrc->iType == STYPE_DEVICE) && (psoTrg->iType == STYPE_BITMAP)) {
|
|
//
|
|
// screen to DIB
|
|
//
|
|
|
|
if (psoTrg->iBitmapFormat == BMF_4BPP)
|
|
{
|
|
pdsurf = (PDEVSURF) psoSrc->dhsurf;
|
|
|
|
// Get the data for the destination DIB.
|
|
|
|
lDelta = psoTrg->lDelta;
|
|
pjDstScan0 = (PBYTE) psoTrg->pvScan0;
|
|
|
|
// Setup for any color translation which may be needed !!! Is any needed at all?
|
|
|
|
if (pxlo == NULL)
|
|
{
|
|
pulXlate = NULL;
|
|
}
|
|
else
|
|
{
|
|
if (pxlo->flXlate & XO_TABLE)
|
|
pulXlate = pxlo->pulXlate;
|
|
else
|
|
{
|
|
pulXlate = (PULONG) NULL;
|
|
}
|
|
}
|
|
|
|
// Set up for clip enumeration.
|
|
|
|
if (pco != (CLIPOBJ *) NULL)
|
|
{
|
|
switch(pco->iDComplexity)
|
|
{
|
|
case DC_TRIVIAL:
|
|
bMore = FALSE;
|
|
cben.c = 1;
|
|
cben.arcl[0] = *prclTrg; // Use the target for clipping
|
|
break;
|
|
|
|
case DC_RECT:
|
|
bMore = FALSE;
|
|
cben.c = 1;
|
|
cben.arcl[0] = pco->rclBounds; // Use the bounds for clipping
|
|
break;
|
|
|
|
case DC_COMPLEX:
|
|
bMore = TRUE;
|
|
cben.c = 0;
|
|
CLIPOBJ_cEnumStart(pco, FALSE, CT_RECTANGLES, CD_ANY, ENUM_RECT_LIMIT);
|
|
break;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
bMore = FALSE;
|
|
cben.c = 1;
|
|
cben.arcl[0] = *prclTrg; // Use the target for clipping
|
|
}
|
|
|
|
// Call the VGA conversion routine, adjusted for each rectangle
|
|
|
|
do
|
|
{
|
|
LONG xSrc;
|
|
LONG ySrc;
|
|
RECTL *prcl;
|
|
|
|
if (bMore)
|
|
bMore = CLIPOBJ_bEnum(pco,(ULONG) sizeof(cben), (PVOID) &cben);
|
|
|
|
for (ircl = 0; ircl < cben.c; ircl++)
|
|
{
|
|
prcl = &cben.arcl[ircl];
|
|
|
|
if (DrvIntersectRect(&rclTemp, prclTrg, prcl))
|
|
{
|
|
xSrc = pptlSrc->x + rclTemp.left - prclTrg->left;
|
|
ySrc = pptlSrc->y + rclTemp.top - prclTrg->top;
|
|
|
|
vConvertVGA2DIB(pdsurf,
|
|
xSrc,
|
|
ySrc,
|
|
pjDstScan0,
|
|
rclTemp.left,
|
|
rclTemp.top,
|
|
rclTemp.right - rclTemp.left,
|
|
rclTemp.bottom - rclTemp.top,
|
|
lDelta,
|
|
psoTrg->iBitmapFormat,
|
|
pulXlate);
|
|
}
|
|
}
|
|
} while (bMore);
|
|
|
|
return(TRUE);
|
|
}
|
|
}
|
|
|
|
//
|
|
// This is how we do any formats that we don't support in our inner loops.
|
|
//
|
|
|
|
return(SimCopyBits(psoTrg, psoSrc, pco, pxlo, prclTrg, pptlSrc));
|
|
}
|
|
|
|
/******************************Public*Routine******************************\
|
|
* SimCopyBits
|
|
*
|
|
* This function simulates CopyBits for the driver when the driver is asked
|
|
* to blt to formats it does not support. It converts any blt to be between
|
|
* the device's preferred format and the screen.
|
|
*
|
|
\**************************************************************************/
|
|
|
|
BOOL SimCopyBits
|
|
(
|
|
SURFOBJ *psoTrg,
|
|
SURFOBJ *psoSrc,
|
|
CLIPOBJ *pco,
|
|
XLATEOBJ *pxlo,
|
|
PRECTL prclTrg,
|
|
PPOINTL pptlSrc
|
|
)
|
|
{
|
|
HBITMAP hbmTmp;
|
|
SURFOBJ *psoTmp;
|
|
RECTL rclTmp;
|
|
SIZEL sizlTmp;
|
|
BOOL bReturn = FALSE;
|
|
POINTL ptl00 = {0,0};
|
|
|
|
DISPDBG((1,"SimCopyBits %lu-%lu => %lu-%lu (%08x, %08x)\n",
|
|
psoSrc->iType,
|
|
psoSrc->iBitmapFormat,
|
|
psoTrg->iType,
|
|
psoTrg->iBitmapFormat,
|
|
pco ? pco->iDComplexity : 0,
|
|
pxlo));
|
|
|
|
rclTmp.top = rclTmp.left = 0;
|
|
rclTmp.right = sizlTmp.cx = prclTrg->right - prclTrg->left;
|
|
rclTmp.bottom = sizlTmp.cy = prclTrg->bottom - prclTrg->top;
|
|
|
|
// Create bitmap in our compatible format.
|
|
|
|
hbmTmp = EngCreateBitmap(sizlTmp, sizlTmp.cx / 2, BMF_4BPP, 0, NULL);
|
|
|
|
if (hbmTmp)
|
|
{
|
|
if ((psoTmp = EngLockSurface((HSURF)hbmTmp)) != NULL)
|
|
{
|
|
if (((psoSrc->iType == STYPE_BITMAP) && (psoTrg->iType == STYPE_DEVICE)) ||
|
|
((psoSrc->iType == STYPE_BITMAP) && (psoTrg->iType == STYPE_DEVBITMAP)))
|
|
{
|
|
//
|
|
// DIB to VGA or DIB to DFB
|
|
//
|
|
|
|
if (EngCopyBits(psoTmp, psoSrc, NULL, pxlo, &rclTmp, pptlSrc))
|
|
{
|
|
//
|
|
// Let DrvCopyBits do this easy case copy to screen.
|
|
//
|
|
bReturn = DrvCopyBits(psoTrg, psoTmp, pco, NULL, prclTrg, &ptl00);
|
|
}
|
|
else
|
|
{
|
|
DISPDBG((0, "SimCopyBits: EngCopyBits DIB -> DEV failed"));
|
|
}
|
|
}
|
|
else if (((psoSrc->iType == STYPE_DEVICE) && (psoTrg->iType == STYPE_BITMAP)) ||
|
|
((psoSrc->iType == STYPE_DEVBITMAP) && (psoTrg->iType == STYPE_BITMAP)))
|
|
{
|
|
//
|
|
// VGA to DIB or DFB to DIB
|
|
//
|
|
|
|
if (DrvCopyBits(psoTmp, psoSrc, NULL, NULL, &rclTmp, pptlSrc))
|
|
{
|
|
//
|
|
// Let EngCopyBits copy between DIBS
|
|
//
|
|
bReturn = EngCopyBits(psoTrg, psoTmp, pco, pxlo, prclTrg, &ptl00);
|
|
}
|
|
else
|
|
{
|
|
DISPDBG((0, "SimCopyBits: DrvCopyBits DEV -> DIB failed"));
|
|
}
|
|
}
|
|
else if (((psoSrc->iType == STYPE_DEVICE) || (psoSrc->iType == STYPE_DEVBITMAP)) &&
|
|
((psoTrg->iType == STYPE_DEVICE) || (psoTrg->iType == STYPE_DEVBITMAP)))
|
|
{
|
|
//
|
|
// VGA or DFB to VGA or DFB
|
|
//
|
|
|
|
if (DrvCopyBits(psoTmp, psoSrc, NULL, NULL, &rclTmp, pptlSrc))
|
|
{
|
|
bReturn = DrvCopyBits(psoTrg, psoTmp, pco, pxlo, prclTrg, &ptl00);
|
|
}
|
|
else
|
|
{
|
|
DISPDBG((0, "SimCopyBits: DrvCopyBits DEV -> DEV failed"));
|
|
}
|
|
}
|
|
|
|
EngUnlockSurface(psoTmp);
|
|
}
|
|
else
|
|
{
|
|
DISPDBG((0, "SimCopyBits: EngLockSurface failed (psoTmp == NULL)"));
|
|
}
|
|
|
|
EngDeleteSurface((HSURF)hbmTmp);
|
|
}
|
|
else
|
|
{
|
|
DISPDBG((0, "SimCopyBits: EngCreateBitmap failed (hbmTmp == NULL)"));
|
|
}
|
|
|
|
if (!bReturn)
|
|
{
|
|
DISPDBG((0,"SimCopyBits failed %lu-%lu => %lu-%lu (%08x, %08x)\n",
|
|
psoSrc->iType,
|
|
psoSrc->iBitmapFormat,
|
|
psoTrg->iType,
|
|
psoTrg->iBitmapFormat,
|
|
pco ? pco->iDComplexity : 0,
|
|
pxlo));
|
|
}
|
|
|
|
return(bReturn);
|
|
}
|
|
|