Пример #1
0
DWORD APIENTRY VBoxDispDDSetOverlayPosition(PDD_SETOVERLAYPOSITIONDATA lpSetOverlayPosition)
{
    PVBOXDISPDEV pDev = (PVBOXDISPDEV) lpSetOverlayPosition->lpDD->dhpdev;
    DD_SURFACE_LOCAL *pSrcSurf = lpSetOverlayPosition->lpDDSrcSurface;
    DD_SURFACE_LOCAL *pDstSurf = lpSetOverlayPosition->lpDDDestSurface;
    PVBOXVHWASURFDESC pSrcDesc = (PVBOXVHWASURFDESC) pSrcSurf->lpGbl->dwReserved1;
    PVBOXVHWASURFDESC pDstDesc = (PVBOXVHWASURFDESC) pDstSurf->lpGbl->dwReserved1;

    LOGF_ENTER();

    if (pSrcDesc && pDstDesc)
    {
        if (!pSrcDesc->bVisible)
        {
            WARN(("!pSrcDesc->bVisible"));
            lpSetOverlayPosition->ddRVal = DDERR_GENERIC;
            return DDHAL_DRIVER_HANDLED;
        }

        VBOXVHWACMD *pCmd;

        pCmd = VBoxDispVHWACommandCreate(pDev, VBOXVHWACMD_TYPE_SURF_OVERLAY_SETPOSITION, sizeof(VBOXVHWACMD_SURF_OVERLAY_SETPOSITION));
        if (pCmd)
        {
            VBOXVHWACMD_SURF_OVERLAY_SETPOSITION *pBody = VBOXVHWACMD_BODY(pCmd, VBOXVHWACMD_SURF_OVERLAY_SETPOSITION);
            memset(pBody, 0, sizeof(VBOXVHWACMD_SURF_OVERLAY_SETPOSITION));

            pBody->u.in.offSrcSurface = VBoxDispVHWAVramOffsetFromPDEV(pDev, pSrcSurf->lpGbl->fpVidMem);
            pBody->u.in.offDstSurface = VBoxDispVHWAVramOffsetFromPDEV(pDev, pDstSurf->lpGbl->fpVidMem);

            pBody->u.in.hSrcSurf = pSrcDesc->hHostHandle;
            pBody->u.in.hDstSurf = pDstDesc->hHostHandle;

            pBody->u.in.xPos = lpSetOverlayPosition->lXPos;
            pBody->u.in.yPos = lpSetOverlayPosition->lYPos;

            VBoxDispVHWACommandSubmitAsynchAndComplete(pDev, pCmd);

            lpSetOverlayPosition->ddRVal = DD_OK;
        }
        else
        {
            WARN(("VBoxDispVHWACommandCreate failed!"));
            lpSetOverlayPosition->ddRVal = DDERR_GENERIC;
        }
    }
    else
    {
        WARN(("!(pSrcDesc && pDstDesc)"));
        lpSetOverlayPosition->ddRVal = DDERR_GENERIC;
    }

    LOGF_LEAVE();
    return DDHAL_DRIVER_HANDLED;
}
Пример #2
0
DWORD APIENTRY VBoxDispDDSetColorKey(PDD_SETCOLORKEYDATA lpSetColorKey)
{
    PVBOXDISPDEV pDev = (PVBOXDISPDEV) lpSetColorKey->lpDD->dhpdev;
    LOGF_ENTER();

    DD_SURFACE_LOCAL *pSurf = lpSetColorKey->lpDDSurface;
    PVBOXVHWASURFDESC pDesc = (PVBOXVHWASURFDESC)pSurf->lpGbl->dwReserved1;
    VBOXVHWACMD* pCmd;

    lpSetColorKey->ddRVal = DD_OK;

    if (pDesc)
    {
        pCmd = VBoxDispVHWACommandCreate(pDev, VBOXVHWACMD_TYPE_SURF_COLORKEY_SET, sizeof(VBOXVHWACMD_SURF_COLORKEY_SET));

        if (pCmd)
        {
            VBOXVHWACMD_SURF_COLORKEY_SET *pBody = VBOXVHWACMD_BODY(pCmd, VBOXVHWACMD_SURF_COLORKEY_SET);
            memset(pBody, 0, sizeof(VBOXVHWACMD_SURF_COLORKEY_SET));

            pBody->u.in.offSurface = VBoxDispVHWAVramOffsetFromPDEV(pDev, pSurf->lpGbl->fpVidMem);
            pBody->u.in.hSurf = pDesc->hHostHandle;
            pBody->u.in.flags = VBoxDispVHWAFromDDCKEYs(lpSetColorKey->dwFlags);
            VBoxDispVHWAFromDDCOLORKEY(&pBody->u.in.CKey, &lpSetColorKey->ckNew);

            VBoxDispVHWACommandSubmitAsynchAndComplete(pDev, pCmd);
        }
        else
        {
            WARN(("VBoxDispVHWACommandCreate failed!"));
            lpSetColorKey->ddRVal = DDERR_GENERIC;
        }
    }
    else
    {
        WARN(("!pDesc"));
        lpSetColorKey->ddRVal = DDERR_GENERIC;
    }

    LOGF_LEAVE();
    return DDHAL_DRIVER_HANDLED;
}
/* Lock specified area of surface */
DWORD APIENTRY VBoxDispDDLock(PDD_LOCKDATA lpLock)
{
    PVBOXDISPDEV pDev = (PVBOXDISPDEV) lpLock->lpDD->dhpdev;
    LOGF_ENTER();

    DD_SURFACE_LOCAL* pSurf = lpLock->lpDDSurface;

    lpLock->ddRVal = DD_OK;

#if 0
#ifdef VBOX_WITH_VIDEOHWACCEL
    if(pDev->vhwa.bEnabled)
    {
        PVBOXVHWASURFDESC pDesc = (PVBOXVHWASURFDESC) pSurf->lpGbl->dwReserved1;
        RECTL tmpRect, *pRect;

        if (!pDesc)
        {
            WARN(("!pDesc, memory overwrite somewhere?"));
            lpLock->ddRVal = DDERR_GENERIC;
            return DDHAL_DRIVER_HANDLED;
        }

        /* Check if host is still processing drawing commands */
        if (ASMAtomicUoReadU32(&pDesc->cPendingBltsSrc)
            || ASMAtomicUoReadU32(&pDesc->cPendingFlipsCurr)
            || ASMAtomicUoReadU32(&pDesc->cPendingBltsDst)
            || ASMAtomicUoReadU32(&pDesc->cPendingFlipsTarg))
        {
            VBoxDispVHWACommandCheckHostCmds(pDev);
            if(ASMAtomicUoReadU32(&pDesc->cPendingBltsSrc)
               || ASMAtomicUoReadU32(&pDesc->cPendingFlipsCurr)
               || ASMAtomicUoReadU32(&pDesc->cPendingBltsDst)
               || ASMAtomicUoReadU32(&pDesc->cPendingFlipsTarg))
            {
                lpLock->ddRVal = DDERR_WASSTILLDRAWING;
                return DDHAL_DRIVER_HANDLED;
            }
        }

        if (lpLock->bHasRect)
        {
            pRect = &lpLock->rArea;
        }
        else
        {
            tmpRect.left = 0;
            tmpRect.top = 0;
            tmpRect.right = pSurf->lpGbl->wWidth-1;
            tmpRect.bottom = pSurf->lpGbl->wHeight-1;
            pRect = &tmpRect;
        }

        if (lpLock->dwFlags & DDLOCK_DISCARDCONTENTS)
        {
            VBoxDispVHWARegionTrySubstitute(&pDesc->NonupdatedMemRegion, pRect);
            VBoxDispVHWARegionAdd(&pDesc->UpdatedMemRegion, pRect);
        }
        else if (!VBoxDispVHWARegionIntersects(&pDesc->NonupdatedMemRegion, pRect))
        {
            VBoxDispVHWARegionAdd(&pDesc->UpdatedMemRegion, pRect);
        }
        else
        {
            VBOXVHWACMD *pCmd;
            pCmd = VBoxDispVHWACommandCreate(pDev, VBOXVHWACMD_TYPE_SURF_LOCK, sizeof(VBOXVHWACMD_SURF_LOCK));

            if (pCmd)
            {
                VBOXVHWACMD_SURF_LOCK *pBody = VBOXVHWACMD_BODY(pCmd, VBOXVHWACMD_SURF_LOCK);
                memset(pBody, 0, sizeof(VBOXVHWACMD_SURF_LOCK));

                pBody->u.in.offSurface = VBoxDispVHWAVramOffsetFromPDEV(pDev, pSurf->lpGbl->fpVidMem);

                VBoxDispVHWAFromRECTL(&pBody->u.in.rect, &pDesc->NonupdatedMemRegion.Rect);
                pBody->u.in.rectValid = 1;

                pBody->u.in.hSurf = pDesc->hHostHandle;

                /* wait for the surface to be locked and memory buffer updated */
                VBoxDispVHWACommandSubmit(pDev, pCmd);
                VBOX_WARNRC(pCmd->rc);
                VBoxDispVHWACommandRelease(pDev, pCmd);
                VBoxDispVHWARegionClear(&pDesc->NonupdatedMemRegion);
            }
            else
            {
                WARN(("VBoxDispVHWACommandCreate failed!"));
                lpLock->ddRVal = DDERR_GENERIC;
            }
        }

        return DDHAL_DRIVER_NOTHANDLED;
    }
#endif /*VBOX_WITH_VIDEOHWACCEL*/
#endif

    /* We only care about primary surface as we'd have to report dirty rectangles to the host in the DDUnlock*/
    if (pSurf->ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE)
    {
        pDev->ddpsLock.bLocked = TRUE;

        if (lpLock->bHasRect)
        {
            pDev->ddpsLock.rect = lpLock->rArea;
        }
        else
        {
            pDev->ddpsLock.rect.left = 0;
            pDev->ddpsLock.rect.top = 0;
            pDev->ddpsLock.rect.right = pDev->mode.ulWidth;
            pDev->ddpsLock.rect.bottom = pDev->mode.ulHeight;
        }
    }

    LOGF_LEAVE();
    return DDHAL_DRIVER_NOTHANDLED;
}
/* Called to create DirectDraw surface.
 * Note: we always return DDHAL_DRIVER_NOTHANDLED, which asks DirectDraw memory manager
 * to perform actual memory allocation in our DDraw heap.
 */
DWORD APIENTRY VBoxDispDDCreateSurface(PDD_CREATESURFACEDATA lpCreateSurface)
{
    PVBOXDISPDEV pDev = (PVBOXDISPDEV) lpCreateSurface->lpDD->dhpdev;
    LOGF_ENTER();

    PDD_SURFACE_LOCAL pSurf = lpCreateSurface->lplpSList[0];

    if (pSurf->ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE)
    {
        LOG(("primary surface"));
        pSurf->lpGbl->fpVidMem = 0;
    }
    else
    {
        LOG(("non primary surface"));
        pSurf->lpGbl->fpVidMem = DDHAL_PLEASEALLOC_BLOCKSIZE;
    }
    pSurf->lpGbl->dwReserved1 = 0;

#ifdef VBOX_WITH_VIDEOHWACCEL
    if(pDev->vhwa.bEnabled)
    {
        VBOXVHWACMD* pCmd;

        pCmd = VBoxDispVHWACommandCreate(pDev, VBOXVHWACMD_TYPE_SURF_CREATE, sizeof(VBOXVHWACMD_SURF_CREATE));
        if (pCmd)
        {
            VBOXVHWACMD_SURF_CREATE *pBody = VBOXVHWACMD_BODY(pCmd, VBOXVHWACMD_SURF_CREATE);
            PVBOXVHWASURFDESC pDesc;
            int rc;

            memset(pBody, 0, sizeof(VBOXVHWACMD_SURF_CREATE));
            rc = VBoxDispVHWAFromDDSURFACEDESC(&pBody->SurfInfo, lpCreateSurface->lpDDSurfaceDesc);
            VBOX_WARNRC(rc);

            pBody->SurfInfo.surfCaps = VBoxDispVHWAFromDDSCAPS(pSurf->ddsCaps.dwCaps);
            pBody->SurfInfo.flags |= DDSD_CAPS;

            pBody->SurfInfo.height = pSurf->lpGbl->wHeight;
            pBody->SurfInfo.width = pSurf->lpGbl->wWidth;
            pBody->SurfInfo.flags |= DDSD_HEIGHT | DDSD_WIDTH;

            VBoxDispVHWAFromDDPIXELFORMAT(&pBody->SurfInfo.PixelFormat, &pSurf->lpGbl->ddpfSurface);
            pBody->SurfInfo.flags |= VBOXVHWA_SD_PIXELFORMAT;

            if (pSurf->ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE)
            {
                pBody->SurfInfo.offSurface = VBoxDispVHWAVramOffsetFromPDEV(pDev, 0);
            }
            else
            {
                pBody->SurfInfo.offSurface = VBOXVHWA_OFFSET64_VOID;
            }

            pDesc = VBoxDispVHWASurfDescAlloc();
            if (pDesc)
            {
                VBoxDispVHWACommandSubmit(pDev, pCmd);
                if (RT_SUCCESS(pCmd->rc))
                {
                    uint32_t surfSizeX = pBody->SurfInfo.sizeX;
                    uint32_t surfSizeY = pBody->SurfInfo.sizeY;
                    pDesc->hHostHandle = pBody->SurfInfo.hSurf;

                    if(!!(pSurf->ddsCaps.dwCaps & DDSCAPS_OVERLAY)
                       && !!(pSurf->ddsCaps.dwCaps & DDSCAPS_VISIBLE))
                    {
                        pDesc->bVisible = true;
                    }

                    pSurf->lpGbl->dwBlockSizeX = pBody->SurfInfo.sizeX;
                    pSurf->lpGbl->dwBlockSizeY = pBody->SurfInfo.sizeY;
                    pSurf->lpGbl->lPitch       = pBody->SurfInfo.pitch;

                    lpCreateSurface->lpDDSurfaceDesc->lPitch = pSurf->lpGbl->lPitch;
                    lpCreateSurface->lpDDSurfaceDesc->dwFlags |= DDSD_PITCH;


                    /*@todo: it's probably a memory leak, because DDDestroySurface wouldn't be called for
                     *       primary surfaces.
                     */
                    pSurf->lpGbl->dwReserved1 = (ULONG_PTR)pDesc;
                }
                else
                {
                    WARN(("VBoxDispVHWACommandSubmit failed with rc=%#x", rc));
                    VBoxDispVHWASurfDescFree(pDesc);
                }
            }
            else
            {
                WARN(("VBoxDispVHWASurfDescAlloc failed"));
            }
            VBoxDispVHWACommandRelease(pDev, pCmd);
        }
        else
        {
            WARN(("VBoxDispVHWACommandCreate failed"));
        }
        return DDHAL_DRIVER_NOTHANDLED;
    }
#endif /*VBOX_WITH_VIDEOHWACCEL*/

    LPDDSURFACEDESC pDesc = lpCreateSurface->lpDDSurfaceDesc;

    if (pDesc->ddpfPixelFormat.dwFlags & DDPF_PALETTEINDEXED4)
    {
        pSurf->lpGbl->lPitch = RT_ALIGN_T(pSurf->lpGbl->wWidth/2, 32, LONG);
    }
    else
    if (pDesc->ddpfPixelFormat.dwFlags & DDPF_PALETTEINDEXED8)
    {
        pSurf->lpGbl->lPitch = RT_ALIGN_T(pSurf->lpGbl->wWidth, 32, LONG);
    }
    else
    {
        pSurf->lpGbl->lPitch = pSurf->lpGbl->wWidth*(pDesc->ddpfPixelFormat.dwRGBBitCount/8);
    }

    pSurf->lpGbl->dwBlockSizeX = pSurf->lpGbl->lPitch;
    pSurf->lpGbl->dwBlockSizeY = pSurf->lpGbl->wHeight;

    pDesc->lPitch = pSurf->lpGbl->lPitch;
    pDesc->dwFlags |= DDSD_PITCH;

    LOGF_LEAVE();
    return DDHAL_DRIVER_NOTHANDLED;
}
Пример #5
0
DWORD APIENTRY VBoxDispDDUpdateOverlay(PDD_UPDATEOVERLAYDATA lpUpdateOverlay)
{
    PVBOXDISPDEV pDev = (PVBOXDISPDEV) lpUpdateOverlay->lpDD->dhpdev;
    DD_SURFACE_LOCAL* pSrcSurf = lpUpdateOverlay->lpDDSrcSurface;
    DD_SURFACE_LOCAL* pDstSurf = lpUpdateOverlay->lpDDDestSurface;
    PVBOXVHWASURFDESC pSrcDesc = (PVBOXVHWASURFDESC) pSrcSurf->lpGbl->dwReserved1;

    LOGF_ENTER();

    if (pSrcDesc)
    {
        VBOXVHWACMD* pCmd;

        pCmd = VBoxDispVHWACommandCreate (pDev, VBOXVHWACMD_TYPE_SURF_OVERLAY_UPDATE, sizeof(VBOXVHWACMD_SURF_OVERLAY_UPDATE));
        if (pCmd)
        {
            VBOXVHWACMD_SURF_OVERLAY_UPDATE *pBody = VBOXVHWACMD_BODY(pCmd, VBOXVHWACMD_SURF_OVERLAY_UPDATE);
            memset(pBody, 0, sizeof(VBOXVHWACMD_SURF_OVERLAY_UPDATE));

            pBody->u.in.offSrcSurface = VBoxDispVHWAVramOffsetFromPDEV(pDev, pSrcSurf->lpGbl->fpVidMem);

            pBody->u.in.hSrcSurf = pSrcDesc->hHostHandle;

            VBoxDispVHWAFromRECTL(&pBody->u.in.dstRect, &lpUpdateOverlay->rDest);
            VBoxDispVHWAFromRECTL(&pBody->u.in.srcRect, &lpUpdateOverlay->rSrc);

            pBody->u.in.flags = VBoxDispVHWAFromDDOVERs(lpUpdateOverlay->dwFlags);
            VBoxDispVHWAFromDDOVERLAYFX(&pBody->u.in.desc, &lpUpdateOverlay->overlayFX);

            if (lpUpdateOverlay->dwFlags & DDOVER_HIDE)
            {
                pSrcDesc->bVisible = false;
            }
            else if(lpUpdateOverlay->dwFlags & DDOVER_SHOW)
            {
                pSrcDesc->bVisible = true;
                if(pSrcDesc->UpdatedMemRegion.bValid)
                {
                    pBody->u.in.xFlags = VBOXVHWACMD_SURF_OVERLAY_UPDATE_F_SRCMEMRECT;
                    VBoxDispVHWAFromRECTL(&pBody->u.in.xUpdatedSrcMemRect, &pSrcDesc->UpdatedMemRegion.Rect);
                    VBoxDispVHWARegionClear(&pSrcDesc->UpdatedMemRegion);
                }
            }

            if(pDstSurf)
            {
                PVBOXVHWASURFDESC pDstDesc = (PVBOXVHWASURFDESC) pDstSurf->lpGbl->dwReserved1;

                if (!pDstDesc)
                {
                    WARN(("!pDstDesc"));
                    lpUpdateOverlay->ddRVal = DDERR_GENERIC;
                    return DDHAL_DRIVER_HANDLED;
                }

                pBody->u.in.hDstSurf = pDstDesc->hHostHandle;
                pBody->u.in.offDstSurface = VBoxDispVHWAVramOffsetFromPDEV(pDev, pDstSurf->lpGbl->fpVidMem);
            }

            VBoxDispVHWACommandSubmitAsynchAndComplete(pDev, pCmd);

            lpUpdateOverlay->ddRVal = DD_OK;
        }
        else
        {
            WARN(("VBoxDispVHWACommandCreate failed!"));
            lpUpdateOverlay->ddRVal = DDERR_GENERIC;
        }
    }
    else
    {
        WARN(("!pSrcDesc"));
        lpUpdateOverlay->ddRVal = DDERR_GENERIC;
    }

    LOGF_LEAVE();
    return DDHAL_DRIVER_HANDLED;
}
Пример #6
0
DWORD APIENTRY VBoxDispDDFlip(PDD_FLIPDATA lpFlip)
{
    PVBOXDISPDEV pDev = (PVBOXDISPDEV) lpFlip->lpDD->dhpdev;
    LOGF_ENTER();

    DD_SURFACE_LOCAL *pCurrSurf = lpFlip->lpSurfCurr;
    DD_SURFACE_LOCAL *pTargSurf = lpFlip->lpSurfTarg;
    PVBOXVHWASURFDESC pCurrDesc = (PVBOXVHWASURFDESC) pCurrSurf->lpGbl->dwReserved1;
    PVBOXVHWASURFDESC pTargDesc = (PVBOXVHWASURFDESC) pTargSurf->lpGbl->dwReserved1;

    if (pCurrDesc && pTargDesc)
    {
        if(ASMAtomicUoReadU32(&pCurrDesc->cPendingFlipsTarg) || ASMAtomicUoReadU32(&pCurrDesc->cPendingFlipsCurr)
           || ASMAtomicUoReadU32(&pTargDesc->cPendingFlipsTarg) || ASMAtomicUoReadU32(&pTargDesc->cPendingFlipsCurr))
        {
            VBoxDispVHWACommandCheckHostCmds(pDev);

            if(ASMAtomicUoReadU32(&pCurrDesc->cPendingFlipsTarg) || ASMAtomicUoReadU32(&pCurrDesc->cPendingFlipsCurr)
               || ASMAtomicUoReadU32(&pTargDesc->cPendingFlipsTarg) || ASMAtomicUoReadU32(&pTargDesc->cPendingFlipsCurr))
            {
                lpFlip->ddRVal = DDERR_WASSTILLDRAWING;
                return DDHAL_DRIVER_HANDLED;
            }
        }

        VBOXVHWACMD *pCmd;

        pCmd = VBoxDispVHWACommandCreate(pDev, VBOXVHWACMD_TYPE_SURF_FLIP, sizeof(VBOXVHWACMD_SURF_FLIP));

        if (pCmd)
        {
            VBOXVHWACMD_SURF_FLIP *pBody = VBOXVHWACMD_BODY(pCmd, VBOXVHWACMD_SURF_FLIP);
            memset(pBody, 0, sizeof(VBOXVHWACMD_SURF_FLIP));

            pBody->u.in.offCurrSurface = VBoxDispVHWAVramOffsetFromPDEV(pDev, pCurrSurf->lpGbl->fpVidMem);
            pBody->u.in.offTargSurface = VBoxDispVHWAVramOffsetFromPDEV(pDev, pTargSurf->lpGbl->fpVidMem);

            pBody->u.in.hTargSurf = pTargDesc->hHostHandle;
            pBody->u.in.hCurrSurf = pCurrDesc->hHostHandle;
            pBody->TargGuestSurfInfo = (uint64_t)pTargDesc;
            pBody->CurrGuestSurfInfo = (uint64_t)pCurrDesc;

            pTargDesc->bVisible = pCurrDesc->bVisible;
            pCurrDesc->bVisible = false;


            ASMAtomicIncU32(&pCurrDesc->cPendingFlipsCurr);
            ASMAtomicIncU32(&pTargDesc->cPendingFlipsTarg);
#ifdef DEBUG
            ASMAtomicIncU32(&pCurrDesc->cFlipsCurr);
            ASMAtomicIncU32(&pTargDesc->cFlipsTarg);
#endif

            if(pTargDesc->UpdatedMemRegion.bValid)
            {
                pBody->u.in.xUpdatedTargMemValid = 1;
                VBoxDispVHWAFromRECTL(&pBody->u.in.xUpdatedTargMemRect, &pTargDesc->UpdatedMemRegion.Rect);
                VBoxDispVHWARegionClear(&pTargDesc->UpdatedMemRegion);
            }

            VBoxDispVHWACommandSubmitAsynch(pDev, pCmd, VBoxDispVHWASurfFlipCompletion, NULL);

            lpFlip->ddRVal = DD_OK;
        }
        else
        {
            WARN(("VBoxDispVHWACommandCreate failed!"));
            lpFlip->ddRVal = DDERR_GENERIC;
        }
    }
    else
    {
        WARN(("!(pCurrDesc && pTargDesc)"));
        lpFlip->ddRVal = DDERR_GENERIC;
    }

    LOGF_LEAVE();
    return DDHAL_DRIVER_HANDLED;
}
Пример #7
0
DWORD APIENTRY VBoxDispDDBlt(PDD_BLTDATA lpBlt)
{
    PVBOXDISPDEV pDev = (PVBOXDISPDEV) lpBlt->lpDD->dhpdev;
    LOGF_ENTER();

    DD_SURFACE_LOCAL *pSrcSurf = lpBlt->lpDDSrcSurface;
    DD_SURFACE_LOCAL *pDstSurf = lpBlt->lpDDDestSurface;
    PVBOXVHWASURFDESC pSrcDesc = (PVBOXVHWASURFDESC) pSrcSurf->lpGbl->dwReserved1;
    PVBOXVHWASURFDESC pDstDesc = (PVBOXVHWASURFDESC) pDstSurf->lpGbl->dwReserved1;

    if (pSrcDesc && pDstDesc)
    {
        VBOXVHWACMD *pCmd;

        pCmd = VBoxDispVHWACommandCreate(pDev, VBOXVHWACMD_TYPE_SURF_BLT, sizeof(VBOXVHWACMD_SURF_BLT));
        if (pCmd)
        {
            VBOXVHWACMD_SURF_BLT *pBody = VBOXVHWACMD_BODY(pCmd, VBOXVHWACMD_SURF_BLT);
            memset(pBody, 0, sizeof(VBOXVHWACMD_SURF_BLT));

            pBody->u.in.offSrcSurface = VBoxDispVHWAVramOffsetFromPDEV(pDev, pSrcSurf->lpGbl->fpVidMem);
            pBody->u.in.offDstSurface = VBoxDispVHWAVramOffsetFromPDEV(pDev, pDstSurf->lpGbl->fpVidMem);

            pBody->u.in.hDstSurf = pDstDesc->hHostHandle;
            VBoxDispVHWAFromRECTL(&pBody->u.in.dstRect, &lpBlt->rDest);
            pBody->u.in.hSrcSurf = pSrcDesc->hHostHandle;
            VBoxDispVHWAFromRECTL(&pBody->u.in.srcRect, &lpBlt->rSrc);
            pBody->DstGuestSurfInfo = (uint64_t)pDstDesc;
            pBody->SrcGuestSurfInfo = (uint64_t)pSrcDesc;

            pBody->u.in.flags = VBoxDispVHWAFromDDBLTs(lpBlt->dwFlags);
            VBoxDispVHWAFromDDBLTFX(&pBody->u.in.desc, &lpBlt->bltFX);

            ASMAtomicIncU32(&pSrcDesc->cPendingBltsSrc);
            ASMAtomicIncU32(&pDstDesc->cPendingBltsDst);

            VBoxDispVHWARegionAdd(&pDstDesc->NonupdatedMemRegion, &lpBlt->rDest);
            VBoxDispVHWARegionTrySubstitute(&pDstDesc->UpdatedMemRegion, &lpBlt->rDest);

            if(pSrcDesc->UpdatedMemRegion.bValid)
            {
                pBody->u.in.xUpdatedSrcMemValid = 1;
                VBoxDispVHWAFromRECTL(&pBody->u.in.xUpdatedSrcMemRect, &pSrcDesc->UpdatedMemRegion.Rect);
                VBoxDispVHWARegionClear(&pSrcDesc->UpdatedMemRegion);
            }

            VBoxDispVHWACommandSubmitAsynch(pDev, pCmd, VBoxDispVHWASurfBltCompletion, NULL);

            lpBlt->ddRVal = DD_OK;
        }
        else
        {
            WARN(("VBoxDispVHWACommandCreate failed!"));
            lpBlt->ddRVal = DDERR_GENERIC;
        }
    }
    else
    {
        WARN(("!(pSrcDesc && pDstDesc)"));
        lpBlt->ddRVal = DDERR_GENERIC;
    }

    LOGF_LEAVE();
    return DDHAL_DRIVER_HANDLED;
}