Пример #1
0
void vrdpDrvBitBlt(SURFOBJ *psoTrg, SURFOBJ *psoSrc, SURFOBJ *psoMask, CLIPOBJ *pco, XLATEOBJ *pxlo,
                   RECTL *prclTrg, POINTL *pptlSrc, POINTL *pptlMask, BRUSHOBJ *pbo, POINTL *pptlBrush,
                   ROP4 rop4)
{
    PVBOXDISPDEV pDev = (PVBOXDISPDEV)psoTrg->dhpdev;

    /*
     * BitBlt operation is supported by following RDP orders:
     *   RDP_ORDER_DESTBLT   ROP on the screen bits (BLACKNESS, WHITENESS, DSTINVERT).
     *   RDP_ORDER_PATBLT    ROP with screen bits and a brush.
     *   RDP_ORDER_SCREENBLT Screen to screen with ROP.
     *   RDP_ORDER_RECT      Solid fill (SRCCOPY).
     *   RDP_ORDER_MEMBLT    ROP with screen and cached offscreen bitmap.
     *   RDP_ORDER_TRIBLT    ROP with screen, cached offscreen bitmap and a brush.
     *
     * Actual BitBlts must be mapped to these RDP operations.
     * Anything that can not be mapped must be emulated with dirty rect.
     *
     */
    VRDPCLIPRECTS clipRects;

    int clipResult;

    RECTL rclTrg = *prclTrg;
    vrdpOrderRect (&rclTrg);

    LOGF_ENTER();

    clipResult = vrdpGetIntersectingClipRects(&clipRects, psoTrg, &rclTrg, pco,
                                              VBoxDispIsScreenSurface(psoSrc)? pptlSrc: NULL);

    if (clipResult == VRDP_CLIP_NO_INTERSECTION)
    {
        /* Do nothing. The Blt does not affect anything. */
        WARN(("VRDP_CLIP_NO_INTERSECTION!!!"));
        dumpPCO (&rclTrg, pco);
    }
    else if (clipResult == VRDP_CLIP_TOO_MANY_RECTS)
    {
        /* A very complex clip. Better to emulate it. */
        WARN(("VRDP_CLIP_TOO_MANY_RECTS!!!"));
        dumpPCO (&rclTrg, pco);

        vrdpReportDirtyRects(pDev, &clipRects);
    }
    else if (ROP4_NEED_MASK (rop4))
    {
        /* Operation with mask is not supported. */
        WARN(("Operation with mask is not supported."));
        vrdpReportDirtyRects(pDev, &clipRects);
    }
    else if (ROP3_NEED_BRUSH(rop4))
    {
        LOG(("Operation requires brush."));

        /* Operation requires brush. */

        if (ROP3_NEED_SRC(rop4))
        {
            /* @todo Three way blt. RDP_ORDER_TRIBLT. */
            LOG(("TRIBLT pbo->iSolidColor = 0x%08X.", pbo->iSolidColor));
            vrdpReportDirtyRects(pDev, &clipRects);
        }
        else
        {
            /* Only brush and destination. Check if the brush is solid. */
            if (pbo->iSolidColor != 0xFFFFFFFF)
            {
                /* Solid brush. The iSolidColor is the target surface color. */
                uint32_t rgb = vrdpColor2RGB(psoTrg, pbo->iSolidColor);

                /* Mix with solid brush. RDP_ORDER_PATBLT. Or RDP_ORDER_RECT for rop4 = 0xF0F0. */
                LOG(("Solid PATBLT color = %08X, rgb %08X.", pbo->iSolidColor, rgb));

                if (rop4 == 0xF0F0)
                {
                    vrdpReportSolidRect(pDev, &rclTrg, &clipRects, rgb);
                }
                else
                {
                    vrdpReportSolidBlt(pDev, &rclTrg, &clipRects, rgb, (uint8_t)rop4);
                }
            }
            else
            {
                /* Non solid brush. RDP_ORDER_PATBLT. */
                LOG(("VRDP::vrdpBitBlt: PATBLT pbo->pvRbrush = %p.", pbo->pvRbrush));

                /* Realize brush. */
                if (!pbo->pvRbrush)
                {
                    BRUSHOBJ_pvGetRbrush (pbo);
                }

                if (pbo->pvRbrush)
                {
                    /* Brush has been realized. */
                    VRDPBRUSH *pBrush = (VRDPBRUSH *)pbo->pvRbrush;

                    if (pBrush->fPattern)
                    {
                        vrdpReportPatBlt(pDev, &rclTrg, &clipRects, pBrush, pptlBrush, (uint8_t)rop4);
                    }
                    else
                    {
                        /* @todo BITMAPCACHE followed by MEMBLT? */
                        vrdpReportDirtyRects(pDev, &clipRects);
                    }
                }
                else
                {
                    /* Unsupported brush format. Fallback to dirty rects. */
                    vrdpReportDirtyRects(pDev, &clipRects);
                }
            }
        }
    }
    else
    {
        /* Operation does not require brush. */
        if (ROP3_NEED_SRC(rop4))
        {
            LOG(("MEMBLT or SCREENBLT."));

            /* MEMBLT or SCREENBLT. */
            if (VBoxDispIsScreenSurface(psoSrc))
            {
                /* Screen to screen transfer. SCREENBLT. */
                LOG(("SCREENBLT."));
                vrdpReportScreenBlt(pDev, &rclTrg, &clipRects, pptlSrc, (uint8_t)rop4);
            }
            else
            {
                /* Offscreen bitmap to screen. MEMBLT. */
                VRDPBCHASH hash;
                VRDPBCHASH hashDeleted;
                int cacheResult;

                LOG(("MEMBLT: bitmap %dx%d.", psoSrc->sizlBitmap.cx, psoSrc->sizlBitmap.cy));
                if (   pDev->bBitmapCacheDisabled
                    || (psoSrc->fjBitmap & BMF_DONTCACHE) != 0
                    || psoSrc->iUniq == 0
                       /* Bitmaps with hdev == 0 seems to have different RGB layout for 16BPP modes.
                        * Just do not cache these bitmaps and report the dirty display area instead.
                        */
                    || (   psoSrc->hdev == 0
                        && !(psoSrc->iBitmapFormat == BMF_24BPP || psoSrc->iBitmapFormat == BMF_32BPP)
                       )
                       /* Do not try to cache large bitmaps. The cache should be mostly used for icons, etc.
                        * Computing a bitmap hash increases CPU load. Up to 384K pixels (~620x620)
                        */
                    || psoSrc->sizlBitmap.cx * psoSrc->sizlBitmap.cy > 384 * _1K
                   )
                {
                    LOG(("MEMBLT: non cacheable bitmap."));
                    cacheResult = VRDPBMP_RC_NOT_CACHED;
                }
                else
                {
                    LOG(("MEMBLT: going to cache."));
                    cacheResult = vrdpbmpCacheSurface(&pDev->vrdpCache, psoSrc, &hash, &hashDeleted, FALSE);
                }

                LOG(("MEMBLT: cacheResult 0x%08X", cacheResult));

                if (cacheResult & VRDPBMP_RC_F_DELETED)
                {
                    LOG(("VRDPBMP_RC_F_DELETED"));
                    vrdpReportDeletedBitmap(pDev, &hashDeleted);
                    cacheResult &= ~VRDPBMP_RC_F_DELETED;
                }

                switch (cacheResult)
                {
                    case VRDPBMP_RC_CACHED:
                        vrdpReportCachedBitmap(pDev, psoSrc, &hash);
                        LOG(("MEMBLT: cached add %dx%d",
                             psoSrc->sizlBitmap.cx, psoSrc->sizlBitmap.cy));
                        /* Continue and report MEMBLT order. */

                    case VRDPBMP_RC_ALREADY_CACHED:
                        vrdpReportMemBlt(pDev, &clipRects, pptlSrc, (uint8_t)rop4, &hash);
                        LOG(("MEMBLT: cached use %dx%d from %d,%d %dx%d",
                             psoSrc->sizlBitmap.cx, psoSrc->sizlBitmap.cy,
                             pptlSrc->x, pptlSrc->y,
                             rclTrg.right - rclTrg.left,
                             rclTrg.bottom - rclTrg.top));
                        LOG(("        %08X %08X %08X %08X",
                                 *(uint32_t *)&((uint8_t *)&hash)[0],
                                 *(uint32_t *)&((uint8_t *)&hash)[4],
                                 *(uint32_t *)&((uint8_t *)&hash)[8],
                                 *(uint32_t *)&((uint8_t *)&hash)[12]
                               ));
                        break;

                    default:
                        /* The surface was not cached. Fallback to dirty rects. */
                        LOG(("MEMBLT: not cached %dx%d from %d,%d %dx%d",
                             psoSrc->sizlBitmap.cx, psoSrc->sizlBitmap.cy,
                             pptlSrc->x, pptlSrc->y,
                             rclTrg.right - rclTrg.left,
                             rclTrg.bottom - rclTrg.top));
                        VBoxDispDumpPSO(psoSrc, "psoSrc");
                        vrdpReportDirtyRects(pDev, &clipRects);
                }
            }
        }
        else
        {
            /* No source and no brush, only dest affected. DESTBLT. */
            LOG(("DSTBLT with rop 0x%08X", rop4));
            vrdpReportDstBlt(pDev, &rclTrg, &clipRects, (uint8_t)rop4);
        }
    }
}
Пример #2
0
LONG
GetColor(
    PPDEV       pPDev,
    BRUSHOBJ    *pbo,
    LPDWORD     pColorFG,
    PDEVBRUSH   *ppDevBrush,
    ROP4        Rop4
    )

/*++

Routine Description:

    Realize the brush color and return the color


Arguments:

    pPDev       - Pointer to our DEV

    pbo         - Engine brush object

    pColorFG    - pointer to the ULONG to received forground color, NULL if
                  not needed

    ppDevBrush  - Pointer to the location to received brush, NULL if not
                  needed

    Rop4        - Rop4 to be used, this function looks at this in order to
                  determine if the brush can be used with the HPGL2 cmds or
                  that the brush will have to be simulated.

Return Value:

    LONG    > 0     The Brush is compatible with device format (Fill command)
            = 0     Failed
            < 0     The brush must send to device via a bitblt

Author:

    13-Jan-1994 Thu 20:18:49 created  

    15-Jan-1994 Sat 06:58:56 updated  
        Change parameters and return value

    16-May-1994 Mon 15:59:45 updated  
        Adding PDEV

Revision History:


--*/

{
    PDEVBRUSH   pDevBrush = NULL;
    LONG        RetVal    = 1;
    DWORD       SolidColor = 0xFFFFFF;
    DWORD       RopBG;
    DWORD       RopFG;


    //
    // Get the ROP for the foureground and background. This information is
    // used to determine if the brush has to be simulated, or can be
    // used with selectable pens in the target device.

    RopBG = ROP4_BG_ROP(Rop4);
    RopFG = ROP4_FG_ROP(Rop4);

    //
    // Get the current color and select the appropriate pen, this should
    // ONLY be a solid color as we don't support stroking with arbitrary
    // brushes.
    //

    if (pbo) {

        //
        // get the brush realization, and select a pen.
        // If the BRUSHOBJ's iSolidColor field is a valid color, then
        // we must do a solid fill with that pen.  Otherwise, we must
        // check the realization of the brush to do a pattern fill.
        //
        // To return a Fillable pattern by DoFill, one of the following conditions
        // must be true and in this sequence
        //
        //  1. SOLID COLOR
        //  2. STANDARD PATTERN
        //  3. Device compatible bitmap
        //

        if ((SolidColor = (DWORD)pbo->iSolidColor) == CLR_INVALID) {

            PLOTDBG(DBG_GETCLR, ("iSolodColor == CLR_INVALID, pBrush=%08lx",
                                                                pbo->pvRbrush));

            //
            // This is a pattern brush, but we will just use its
            // foreground color.
            //

            if ((pDevBrush = (PDEVBRUSH)pbo->pvRbrush) ||
                (pDevBrush = BRUSHOBJ_pvGetRbrush(pbo))) {


                //
                // Grab the foreground color and use it.
                //

                SolidColor = pDevBrush->ColorFG;


                if ((pDevBrush->PatIndex < HS_DDI_MAX) ||
                    (pDevBrush->pbgr24)) {

                    ;

                } else {

                    PLOTDBG(DBG_GETCLR, ("GETColor: NOT DEVICE_PAT"));

                    RetVal = -1;
                }

            } else {

                RetVal = 0;
                PLOTDBG(DBG_GETCLR, ("GetColor(): couldn't realize brush!"));
            }

        } else {

            PLOTDBG(DBG_GETCLR,
                    ("GETColor: is a SOLID COLOR=%08lx", pbo->iSolidColor));
        }

    } else if ((RopFG == 0x00) || (RopBG == 0x00)) {

        if (IS_RASTER(pPDev)) {

            SolidColor = 0x0;

        } else {

            //
            // If we are not a raster device (which supports overprint)
            // match the best non-white pen, in order to fill with.
            //

            SolidColor = (DWORD)BestMatchNonWhitePen(pPDev, 0, 0, 0);

            PLOTDBG(DBG_GETCLR,
                    ("GETColor: pbo=NULL, BLACK Pen Idx=%ld", SolidColor));

        }
    }

    if ((!IS_RASTER(pPDev)) && (SolidColor == 0x00FFFFFF)) {

        SolidColor = WHITE_INDEX;

        PLOTDBG(DBG_GETCLR,
                ("GETColor: Pen plotter using WHITE COLOR Idx=%ld", SolidColor));
    }

    if (pColorFG) {

        *pColorFG = SolidColor;
    }

    if (ppDevBrush) {

        *ppDevBrush = pDevBrush;
    }

    return(RetVal);
}