BOOL APIENTRY
VBoxDispDrvStretchBlt(SURFOBJ *psoDest, SURFOBJ *psoSrc, SURFOBJ *psoMask, CLIPOBJ *pco, XLATEOBJ *pxlo,
                      COLORADJUSTMENT *pca, POINTL *pptlHTOrg, RECTL *prclDest, RECTL *prclSrc,
                      POINTL *pptlMask, ULONG iMode)
{
    BOOL bRc;
    LOGF_ENTER();
    STATDRVENTRY(StretchBlt, psoDest);

    bRc = EngStretchBlt(getSurfObj(psoDest), getSurfObj(psoSrc), psoMask, pco, pxlo, pca, pptlHTOrg,
                        prclDest, prclSrc, pptlMask, iMode);
    VBVA_OPERATION(psoDest, StretchBlt,
                   (psoDest, psoSrc, psoMask, pco, pxlo, pca, pptlHTOrg, prclDest, prclSrc, pptlMask, iMode));

    LOGF_LEAVE();
    return bRc;
}
BOOL APIENTRY
VBoxDispDrvBitBlt(SURFOBJ *psoTrg, SURFOBJ *psoSrc, SURFOBJ *psoMask, CLIPOBJ *pco, XLATEOBJ *pxlo,
                  RECTL *prclTrg, POINTL *pptlSrc, POINTL *pptlMask, BRUSHOBJ *pbo, POINTL *pptlBrush, ROP4 rop4)
{
    BOOL bRc;
    LOGF_ENTER();
    STATDRVENTRY(BitBlt, psoTrg);

    LOG(("psoTrg = %p, psoSrc = %p, psoMask = %p, pco = %p, pxlo = %p, prclTrg = %p, pptlSrc = %p, "
         "pptlMask = %p, pbo = %p, pptlBrush = %p, rop4 = %08X",
         psoTrg, psoSrc, psoMask, pco, pxlo, prclTrg, pptlSrc, pptlMask, pbo, pptlBrush, rop4));

    bRc = EngBitBlt(getSurfObj(psoTrg), getSurfObj(psoSrc), psoMask, pco, pxlo, prclTrg, pptlSrc, pptlMask, pbo, pptlBrush, rop4);
    VBVA_OPERATION(psoTrg, BitBlt,
                   (psoTrg, psoSrc, psoMask, pco, pxlo, prclTrg, pptlSrc, pptlMask, pbo, pptlBrush, rop4));

    LOGF_LEAVE();
    return bRc;
}
BOOL APIENTRY VBoxDispDrvPaint(SURFOBJ *pso, CLIPOBJ *pco, BRUSHOBJ *pbo, POINTL *pptlBrushOrg, MIX mix)
{
    BOOL bRc;
    LOGF_ENTER();
    STATDRVENTRY(Paint, pso);

    bRc = EngPaint (getSurfObj(pso), pco, pbo, pptlBrushOrg, mix);
    VBVA_OPERATION(pso, Paint, (pso, pco, pbo, pptlBrushOrg, mix));

    LOGF_LEAVE();
    return bRc;
}
BOOL APIENTRY
VBoxDispDrvFillPath(SURFOBJ *pso, PATHOBJ *ppo, CLIPOBJ *pco, BRUSHOBJ *pbo, POINTL *pptlBrushOrg,
                    MIX mix, FLONG flOptions)
{
    BOOL bRc;
    LOGF_ENTER();
    STATDRVENTRY(FillPath, pso);

    bRc = EngFillPath(getSurfObj(pso), ppo, pco, pbo, pptlBrushOrg, mix, flOptions);
    VBVA_OPERATION(pso, FillPath, (pso, ppo, pco, pbo, pptlBrushOrg, mix, flOptions));

    LOGF_LEAVE();
    return bRc;
}
BOOL APIENTRY
VBoxDispDrvStrokePath(SURFOBJ *pso, PATHOBJ *ppo, CLIPOBJ *pco, XFORMOBJ *pxo,
                      BRUSHOBJ  *pbo, POINTL *pptlBrushOrg, LINEATTRS *plineattrs, MIX mix)
{
    BOOL bRc;
    LOGF_ENTER();
    STATDRVENTRY(StrokePath, pso);

    bRc = EngStrokePath(getSurfObj(pso), ppo, pco, pxo, pbo, pptlBrushOrg, plineattrs, mix);
    VBVA_OPERATION(pso, StrokePath, (pso, ppo, pco, pxo, pbo, pptlBrushOrg, plineattrs, mix));

    LOGF_LEAVE();
    return bRc;
}
BOOL APIENTRY
VBoxDispDrvLineTo(SURFOBJ *pso, CLIPOBJ *pco, BRUSHOBJ *pbo, LONG x1, LONG y1, LONG x2, LONG y2,
                  RECTL *prclBounds, MIX mix)
{
    BOOL bRc;
    LOGF_ENTER();
    STATDRVENTRY(LineTo, pso);

    bRc = EngLineTo(getSurfObj(pso), pco, pbo, x1, y1, x2, y2, prclBounds, mix);
    VBVA_OPERATION(pso, LineTo, (pso, pco, pbo, x1, y1, x2, y2, prclBounds, mix));

    LOGF_LEAVE();
    return bRc;
}
BOOL APIENTRY
VBoxDispDrvTextOut(SURFOBJ *pso, STROBJ *pstro, FONTOBJ *pfo, CLIPOBJ *pco,
                   RECTL *prclExtra, RECTL *prclOpaque, BRUSHOBJ *pboFore,
                   BRUSHOBJ *pboOpaque, POINTL *pptlOrg, MIX mix)
{
    BOOL bRc;
    LOGF_ENTER();
    STATDRVENTRY(TextOut, pso);

    bRc = EngTextOut(getSurfObj(pso), pstro, pfo, pco, prclExtra, prclOpaque, pboFore, pboOpaque, pptlOrg, mix);
    VBVA_OPERATION(pso, TextOut, (pso, pstro, pfo, pco, prclExtra, prclOpaque, pboFore, pboOpaque, pptlOrg, mix));

    LOGF_LEAVE();
    return bRc;
}
Beispiel #8
0
static int vrdpGetIntersectingClipRects(VRDPCLIPRECTS *pClipRects, SURFOBJ *pso, RECTL *prcl, CLIPOBJ *pco, POINTL *pptlSrc)
{
    BOOL bTooManyRects = FALSE;

    LOGF(("pso = %p, pptlSrc = %p", pso, pptlSrc));

    pso = getSurfObj(pso);

    pClipRects->rclDstOrig = *prcl;
    pClipRects->rclDst     = *prcl;
    pClipRects->rects.c    = 0;

    vrdpAdjustRect(pso, &pClipRects->rclDst);

    if (pco && (pco->iDComplexity != DC_TRIVIAL))
    {
        ULONG iDirection = CD_ANY;

        if (pptlSrc)
        {
            /* Operation is performed on the same (screen) surface and enumeration direction
             * must take into account the position of source and target rectangles.
             */
            if (pptlSrc->x <= prcl->left)
            {
                if (pptlSrc->y <= prcl->top)
                {
                    iDirection = CD_LEFTUP;
                }
                else
                {
                    iDirection = CD_LEFTDOWN;
                }
            }
            else
            {
                if (pptlSrc->y <= prcl->top)
                {
                    iDirection = CD_RIGHTUP;
                }
                else
                {
                    iDirection = CD_RIGHTDOWN;
                }
            }
        }

        /* Clip the target rect by entire clipping region. Obtain the effective target. */
        vrdpIntersectRects(&pClipRects->rclDst, &pClipRects->rclDst, &pco->rclBounds);

        /* Enumerate rectangles. Try to get all rectangles at once and if there is not
         * enough space (too many rectangles) fail with the bTooManyRects condition.
         */
        CLIPOBJ_cEnumStart(pco, FALSE, CT_RECTANGLES, iDirection, 0);

        bTooManyRects = CLIPOBJ_bEnum(pco, sizeof(pClipRects->rects), &pClipRects->rects.c);

        if (!bTooManyRects)
        {
            RECTL *prclClipSrc = &pClipRects->rects.arcl[0];
            RECTL *prclClipDst = prclClipSrc;

            ULONG cRects = pClipRects->rects.c;

            LOGF(("%d rects", cRects));

            if (cRects > 0)
            {
                for (; cRects != 0; cRects--, prclClipSrc++)
                {
                    vrdpIntersectRects(prclClipDst, prclClipSrc, &pClipRects->rclDst);

                    if (vrdpIsRectEmpty(prclClipDst))
                    {
                        pClipRects->rects.c--;
                    }
                    else
                    {
                        prclClipDst++;
                    }
                }
            }

            if (pClipRects->rects.c == 0)
            {
                pClipRects->rclDst.left = pClipRects->rclDst.right = 0;
            }
            LOGF(("%d rects remains", pClipRects->rects.c));
        }
    }

    if (vrdpIsRectEmpty(&pClipRects->rclDst))
    {
        return VRDP_CLIP_NO_INTERSECTION;
    }

    if (bTooManyRects)
    {
        pClipRects->rects.c = 0;

        return VRDP_CLIP_TOO_MANY_RECTS;
    }

    return VRDP_CLIP_OK;
}
Beispiel #9
0
void vrdpDrvSaveScreenBits(SURFOBJ *pso, ULONG iMode, ULONG_PTR ident, RECTL *prcl)
{
    PVBOXDISPDEV pDev = (PVBOXDISPDEV)pso->dhpdev;

    switch (iMode)
    {
        case SS_SAVE:
        {
            VRDEORDERSAVESCREEN order;

            order.pt1.x = (int16_t)prcl->left;
            order.pt1.y = (int16_t)prcl->top;
            order.pt2.x = (int16_t)prcl->right;
            order.pt2.y = (int16_t)prcl->bottom;

            order.ident = (uint8_t)ident;
            order.restore = 0;

            vrdpReportOrderGeneric(pDev, NULL, &order, sizeof (order), VRDE_ORDER_SAVESCREEN);
        } break;

        case SS_RESTORE:
        {
            VRDEORDERSAVESCREEN order;

            order.pt1.x = (int16_t)prcl->left;
            order.pt1.y = (int16_t)prcl->top;
            order.pt2.x = (int16_t)prcl->right;
            order.pt2.y = (int16_t)prcl->bottom;

            order.ident = (uint8_t)ident;
            order.restore = 1;

            if (vrdpReportOrderGeneric(pDev, NULL, &order, sizeof (order), VRDE_ORDER_SAVESCREEN))
            {
                uint8_t *pu8Bits;
                int32_t lDelta;
                uint32_t w;
                uint32_t h;

                int cbPixel;

                pso = getSurfObj(pso);

                cbPixel = format2BytesPerPixel(pso);

                pu8Bits = (uint8_t *)pso->pvScan0 +
                                     pso->lDelta * prcl->top +
                                     cbPixel * prcl->left;

                lDelta  = pso->lDelta;

                w = prcl->right - prcl->left;
                h = prcl->bottom - prcl->top;

                vrdpWriteBits(pDev, pu8Bits, lDelta, prcl->left, prcl->top, w, h, cbPixel);
            }
        } break;

        default:
           WARN(("Invalid mode %d!!!", iMode));
    }
}
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;
}
ULONG_PTR APIENTRY VBoxDispDrvSaveScreenBits(SURFOBJ *pso, ULONG iMode, ULONG_PTR ident, RECTL *prcl)
{
    ULONG_PTR rc = 0; /* 0 means the function failure for every iMode. */
    RECTL rcl;
    SSB *pSSB;
    SURFOBJ *psoOrg = pso;
    BOOL bCallVBVA = FALSE;

    PVBOXDISPDEV pDev = (PVBOXDISPDEV) pso->dhpdev;

    LOGF(("%p, %d, %d, %d,%d %d,%d", pso, iMode, ident, prcl->left, prcl->top, prcl->right, prcl->bottom));

    if (!pDev)
    {
        return rc;
    }

    pso = getSurfObj(pso);

    /* Order the rectangle. */
    if (prcl->left <= prcl->right)
    {
        rcl.left = prcl->left;
        rcl.right = prcl->right;
    }
    else
    {
        rcl.left = prcl->right;
        rcl.right = prcl->left;
    }

    if (prcl->top <= prcl->bottom)
    {
        rcl.top = prcl->top;
        rcl.bottom = prcl->bottom;
    }
    else
    {
        rcl.top = prcl->bottom;
        rcl.bottom = prcl->top;
    }

    /* Implementation of the save/restore is a bit complicated because RDP
     * requires "the sequencing of saves and restores is such that they
     * behave as a last-in, first-out stack.".
     */
    switch (iMode)
    {
        case SS_SAVE:
        {
            LOG(("SS_SAVE %d", pDev->cSSB));

            if (pDev->cSSB >= RT_ELEMENTS(pDev->aSSB))
            {
                /* All slots are already in use. Fail. */
                WARN(("no more slots %d!!!", pDev->cSSB));
                break;
            }

            /* Get pointer to the slot where bits will be saved. */
            pSSB = &pDev->aSSB[pDev->cSSB];

            /* Allocate memory for screen bits and copy them to the buffer. */
            if (ssbCopy(pSSB, pso, &rcl, FALSE /* bToScreen */))
            {
                /* Bits where successfully copied. Increase the active slot number
                 * and call VBVA levels, 'ident' is also assigned, the VBVA level
                 * will use it even for the SS_SAVE.
                 */
                ident = rc = pSSB->ident = ++pDev->cSSB;
                bCallVBVA = TRUE;
            }
        } break;

        case SS_RESTORE:
        {
            LOG(("SS_RESTORE"));

            if (pDev->cSSB == 0 || ident == 0 || ident > pDev->cSSB)
            {
                WARN(("no slot: pDev->cSSB = %d!!!", pDev->cSSB));
                break;
            }

            if (ident < pDev->cSSB)
            {
                ssbDiscardUpperSlots(pDev, ident);
            }

            Assert(ident == pDev->cSSB);
            Assert(ident != 0);

            pSSB = &pDev->aSSB[ident - 1];

            ssbCopy(pSSB, pso, &rcl, TRUE /* bToScreen */);

            /* Bits must be discarded. */
            ssbDiscardTopSlot (pDev);

            rc = TRUE;
            bCallVBVA = TRUE;
        } break;

        case SS_FREE:
        {
            LOG(("SS_FREE"));

            if (pDev->cSSB == 0 || ident == 0 || ident > pDev->cSSB)
            {
                WARN(("no slot: pDev->cSSB = %d!!!", pDev->cSSB));
                break;
            }

            if (ident < pDev->cSSB)
            {
                ssbDiscardUpperSlots(pDev, ident);
            }

            Assert(ident == pDev->cSSB);
            Assert(ident != 0);

            /* Bits must be discarded. */
            ssbDiscardTopSlot(pDev);

            rc = TRUE;
        } break;
    }

    /* Now call the VBVA/VRDP levels. */
    if (bCallVBVA)
    {
        LOG(("calling VBVA"));
        VBVA_OPERATION(psoOrg, SaveScreenBits, (psoOrg, iMode, ident, &rcl));
    }

    LOGF(("return %d", rc));
    return rc;
}