File:  [WindowsNT SDKs] / ntddk / src / video / displays / vga / copybits.c
Revision 1.1.1.1 (vendor branch): download - view: text, annotated - select for diffs
Thu Aug 9 18:31:12 2018 UTC (7 years, 9 months ago) by root
Branches: msft, MAIN
CVS tags: ntddk-nov-1993, HEAD
Microsoft Windows NT Build 511 (DDK SDK) 11-01-1993

/******************************Module*Header*******************************\
* Module Name: copybits.c
*
* DrvCopyBits
*
* Copyright (c) 1992 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     dsurfSrc;
    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;


//    ASSERT(psoTrg  != (SURFOBJ *) NULL, "DrvCopyBits: NULL Pointer for Target\n");
//    ASSERT(psoSrc  != (SURFOBJ *) NULL, "DrvCopyBits: NULL Pointer for Source\n");
//    ASSERT(prclTrg != (RECTL *)   NULL, "DrvCopyBits: NULL Pointer for Rect\n");
//    ASSERT(pptlSrc != (POINTL *)  NULL, "DrvCopyBits: NULL Pointer for Point\n");

//    ASSERT(((psoTrg->dhsurf != (DHSURF) 0) || (psoSrc->dhsurf != (DHSURF) 0)),
//            "DrvCopyBits: No device surface involved\n");

// 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
//        ASSERT(((CD_RIGHTDOWN == 0) && (CD_LEFTDOWN == 1) &&
//               (CD_RIGHTUP == 2) && (CD_LEFTUP == 3)),
//               "DrvBitBlt: Bad clip enumeration direction constants");

        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_BITMAP) {

        // DIB to screen

        switch(psoSrc->iBitmapFormat)
        {
        case BMF_4BPP:  // special case compatible DIBs with no translation

            if ((pxlo == NULL) || (pxlo->flXlate == XO_TRIVIAL)) {

                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

                dsurfSrc.lNextScan = psoSrc->lDelta;
                dsurfSrc.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, &dsurfSrc, prclTrg,
                            pptlSrc, pucDIB4ToVGAConvTables);

                } 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, &dsurfSrc,
                                &rclTemp, &ptlTemp, pucDIB4ToVGAConvTables);
                    }
                    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,
                                    &dsurfSrc, prcl, &ptlTemp,
                                    pucDIB4ToVGAConvTables);
                        }
                    } while(bMore);

                }

                return(TRUE);
            }

        case BMF_1BPP:
        case BMF_8BPP:

            return(DrvBitBlt(psoTrg,
                             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));

        }
    }
    else
    {
    // screen to DIB

//        ASSERT(psoTrg->iType == STYPE_BITMAP, "ERROR CopyBits got 2 DIBs");

        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
                {
//                    ASSERT(pxlo->flXlate & XO_TRIVIAL, "DrvCopyBits: Hopelessly complex translation\n");
                    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];

                    xSrc = pptlSrc->x + prcl->left - prclTrg->left;
                    ySrc = pptlSrc->y + prcl->top  - prclTrg->top;

                    vConvertVGA2DIB(pdsurf,
                                    xSrc,
                                    ySrc,
                                    pjDstScan0,
                                    prcl->left,
                                    prcl->top,
                                    prcl->right - prcl->left,
                                    prcl->bottom - prcl->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;
    static POINTL ptl00 = {0,0};

    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)
            {
            // blting from DIB to screen

                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
            {
            // blting from screen to DIB

                if (DrvCopyBits(psoTmp, psoSrc, NULL, NULL, &rclTmp, pptlSrc))
                {
                // Let EngCopyBits copy between DIBS

                    bReturn = EngCopyBits(psoTrg, psoTmp, pco, pxlo, prclTrg, &ptl00);
                }
            }

            EngUnlockSurface(psoTmp);
        }

        EngDeleteSurface((HSURF)hbmTmp);
    }

    return(bReturn);
}

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.