Example #1
0
BOOL APIENTRY
VBoxDispDrvRealizeBrush(BRUSHOBJ *pbo, SURFOBJ *psoTarget, SURFOBJ *psoPattern, SURFOBJ *psoMask,
                        XLATEOBJ *pxlo, ULONG iHatch)
{
    BOOL bRc = FALSE;
    LOGF_ENTER();

    if (VBoxDispIsScreenSurface(psoTarget))
    {
        PVBOXDISPDEV pDev = (PVBOXDISPDEV)psoTarget->dhpdev;

        if (pDev->vbvaCtx.pVBVA && (pDev->vbvaCtx.pVBVA->hostFlags.u32HostEvents & VBVA_F_MODE_ENABLED))
        {
            if (pDev->vbvaCtx.pVBVA->hostFlags.u32HostEvents & VBOX_VIDEO_INFO_HOST_EVENTS_F_VRDP_RESET)
            {
                vrdpReset(pDev);
                pDev->vbvaCtx.pVBVA->hostFlags.u32HostEvents &= ~VBOX_VIDEO_INFO_HOST_EVENTS_F_VRDP_RESET;
            }

            if (pDev->vbvaCtx.pVBVA->hostFlags.u32HostEvents & VBVA_F_MODE_VRDP)
            {
                bRc = vrdpDrvRealizeBrush(pbo, psoTarget, psoPattern, psoMask, pxlo, iHatch);
            }
        }
    }

    LOGF_LEAVE();
    return bRc;
}
Example #2
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);
        }
    }
}
BOOL APIENTRY
VBoxDispDrvCopyBits(SURFOBJ *psoDest, SURFOBJ *psoSrc, CLIPOBJ *pco, XLATEOBJ *pxlo,
                    RECTL *prclDest, POINTL *pptlSrc)
{
    BOOL bRc;
    RECTL rclDest = *prclDest;
    POINTL ptlSrc = *pptlSrc;
    BOOL bDo = TRUE;
    LOGF_ENTER();
    STATDRVENTRY(CopyBits, psoDest);

    LOG(("psoDest = %p, psoSrc = %p, pco = %p, pxlo = %p, prclDest = %p, pptlSrc = %p",
         psoDest, psoSrc, pco, pxlo, prclDest, pptlSrc));
    DUMPSURF(psoSrc, "psoSrc");
    DUMPSURF(psoDest, "psoDest");
    STATPRINT;

#ifdef VBOX_VBVA_ADJUST_RECT
    /* Experimental fix for too large bitmap updates.
     *
     * Some application do a large bitmap update event if only
     * a small part of the bitmap is actually changed.
     *
     * The driver will find the changed rectangle by comparing
     * the current framebuffer content with the source bitmap.
     *
     * The optimization is only active when:
     *  - the VBVA extension is enabled;
     *  - the source bitmap is not cacheable;
     *  - the bitmap formats of both the source and the screen surfaces are equal.
     *
     */
    if (   psoSrc
        && !VBoxDispIsScreenSurface(psoSrc)
        && VBoxDispIsScreenSurface(psoDest))
    {
        PVBOXDISPDEV pDev = ((PVBOXDISPDEV))psoDest->dhpdev;

        LOG(("offscreen->screen"));

        if (   pDev->vbvaCtx.pVBVA
            && (pDev->vbvaCtx.pVBVA->hostFlags.u32HostEvents & VBVA_F_MODE_ENABLED))
        {
            if (   (psoSrc->fjBitmap & BMF_DONTCACHE) != 0
                || psoSrc->iUniq == 0)
            {
                LOG(("non-cacheable %d->%d (pDev %p)", psoSrc->iBitmapFormat, psoDest->iBitmapFormat, pDev));

                /* It is possible to apply the fix. */
                bDo = vbvaFindChangedRect(getSurfObj(psoDest), getSurfObj(psoSrc), &rclDest, &ptlSrc);
            }
        }
    }

    if (!bDo)
    {
        /* The operation is a NOP. Just return success. */
        LOGF_LEAVE();
        return TRUE;
    }
#endif /* VBOX_VBVA_ADJUST_RECT */

    bRc = EngCopyBits(getSurfObj(psoDest), getSurfObj(psoSrc), pco, pxlo, &rclDest, &ptlSrc);
    VBVA_OPERATION(psoDest, CopyBits, (psoDest, psoSrc, pco, pxlo, &rclDest, &ptlSrc));

    LOGF_LEAVE();
    return bRc;
}