/* $Id$ */
/** @file
* VBox XPDM Display driver, DirectDraw callbacks VHWA related
*/
/*
* Copyright (C) 2011 Oracle Corporation
*
* This file is part of VirtualBox Open Source Edition (OSE), as
* available from http://www.virtualbox.org. This file is free software;
* you can redistribute it and/or modify it under the terms of the GNU
* General Public License (GPL) as published by the Free Software
* Foundation, in version 2 as it comes in the "COPYING" file of the
* VirtualBox OSE distribution. VirtualBox OSE is distributed in the
* hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
*/
#include "VBoxDisp.h"
#include "VBoxDispDDraw.h"
#include <iprt/asm.h>
static DECLCALLBACK(void) VBoxDispVHWASurfBltCompletion(PVBOXDISPDEV pDev, VBOXVHWACMD * pCmd, void * pContext)
{
VBOXVHWACMD_SURF_BLT *pBody = VBOXVHWACMD_BODY(pCmd, VBOXVHWACMD_SURF_BLT);
PVBOXVHWASURFDESC pSrcDesc = (PVBOXVHWASURFDESC)pBody->SrcGuestSurfInfo;
PVBOXVHWASURFDESC pDestDesc = (PVBOXVHWASURFDESC)pBody->DstGuestSurfInfo;
ASMAtomicDecU32(&pSrcDesc->cPendingBltsSrc);
ASMAtomicDecU32(&pDestDesc->cPendingBltsDst);
VBoxDispVHWACommandRelease(pDev, pCmd);
}
static DECLCALLBACK(void) VBoxDispVHWASurfFlipCompletion(PVBOXDISPDEV pDev, VBOXVHWACMD * pCmd, void * pContext)
{
VBOXVHWACMD_SURF_FLIP *pBody = VBOXVHWACMD_BODY(pCmd, VBOXVHWACMD_SURF_FLIP);
PVBOXVHWASURFDESC pCurrDesc = (PVBOXVHWASURFDESC)pBody->CurrGuestSurfInfo;
PVBOXVHWASURFDESC pTargDesc = (PVBOXVHWASURFDESC)pBody->TargGuestSurfInfo;
ASMAtomicDecU32(&pCurrDesc->cPendingFlipsCurr);
ASMAtomicDecU32(&pTargDesc->cPendingFlipsTarg);
VBoxDispVHWACommandRelease(pDev, pCmd);
}
#define VBOXVHWA_CAP(_pdev, _cap) ((_pdev)->vhwa.caps & (_cap))
#define ROP_INDEX(_rop) ((BYTE)((_rop)>>16))
#define SET_SUPPORT_ROP(_aRops, _rop) _aRops[ROP_INDEX(_rop)/32] |= 1L << ((DWORD)(ROP_INDEX(_rop)%32))
int VBoxDispVHWAUpdateDDHalInfo(PVBOXDISPDEV pDev, DD_HALINFO *pHalInfo)
{
if (!VBOXVHWA_CAP(pDev, VBOXVHWA_CAPS_BLT) && !VBOXVHWA_CAP(pDev, VBOXVHWA_CAPS_OVERLAY))
{
return VERR_NOT_SUPPORTED;
}
pHalInfo->ddCaps.dwCaps |= VBoxDispVHWAToDDCAPS(pDev->vhwa.caps);
if (VBOXVHWA_CAP(pDev, VBOXVHWA_CAPS_BLT))
{
/* we only support simple dst=src copy
* Note: search "ternary raster operations" on msdn for more info
*/
SET_SUPPORT_ROP(pHalInfo->ddCaps.dwRops, SRCCOPY);
}
pHalInfo->ddCaps.ddsCaps.dwCaps |= VBoxDispVHWAToDDSCAPS(pDev->vhwa.surfaceCaps);
pHalInfo->ddCaps.dwCaps2 |= VBoxDispVHWAToDDCAPS2(pDev->vhwa.caps2);
if (VBOXVHWA_CAP(pDev, VBOXVHWA_CAPS_BLT) && VBOXVHWA_CAP(pDev, VBOXVHWA_CAPS_BLTSTRETCH))
{
pHalInfo->ddCaps.dwFXCaps |= DDFXCAPS_BLTSTRETCHX|DDFXCAPS_BLTSTRETCHY|
DDFXCAPS_BLTSTRETCHXN|DDFXCAPS_BLTSTRETCHYN|
DDFXCAPS_BLTSHRINKX|DDFXCAPS_BLTSHRINKY|
DDFXCAPS_BLTSHRINKXN|DDFXCAPS_BLTSHRINKYN|
DDFXCAPS_BLTARITHSTRETCHY;
}
if (VBOXVHWA_CAP(pDev, VBOXVHWA_CAPS_OVERLAY) && VBOXVHWA_CAP(pDev, VBOXVHWA_CAPS_OVERLAYSTRETCH))
{
pHalInfo->ddCaps.dwFXCaps |= DDFXCAPS_OVERLAYSTRETCHX|DDFXCAPS_OVERLAYSTRETCHY|
DDFXCAPS_OVERLAYSTRETCHXN|DDFXCAPS_OVERLAYSTRETCHYN|
DDFXCAPS_OVERLAYSHRINKX|DDFXCAPS_OVERLAYSHRINKY|
DDFXCAPS_OVERLAYSHRINKXN|DDFXCAPS_OVERLAYSHRINKYN|
DDFXCAPS_OVERLAYARITHSTRETCHY;
}
pHalInfo->ddCaps.dwCKeyCaps = VBoxDispVHWAToDDCKEYCAPS(pDev->vhwa.colorKeyCaps);
if (VBOXVHWA_CAP(pDev, VBOXVHWA_CAPS_OVERLAY))
{
pHalInfo->ddCaps.dwMaxVisibleOverlays = pDev->vhwa.numOverlays;
pHalInfo->ddCaps.dwCurrVisibleOverlays = 0;
pHalInfo->ddCaps.dwMinOverlayStretch = 1;
pHalInfo->ddCaps.dwMaxOverlayStretch = 32000;
}
return VINF_SUCCESS;
}
/*
* DirectDraw callbacks.
*/
#define IF_NOT_SUPPORTED(_guid) \
if (IsEqualIID(&lpData->guidInfo, &(_guid))) \
{ \
LOG((#_guid)); \
}
DWORD APIENTRY VBoxDispDDGetDriverInfo(DD_GETDRIVERINFODATA *lpData)
{
LOGF_ENTER();
lpData->ddRVal = DDERR_CURRENTLYNOTAVAIL;
if (IsEqualIID(&lpData->guidInfo, &GUID_NTPrivateDriverCaps))
{
LOG(("GUID_NTPrivateDriverCaps"));
DD_NTPRIVATEDRIVERCAPS caps;
memset(&caps, 0, sizeof(caps));
caps.dwSize = sizeof(DD_NTPRIVATEDRIVERCAPS);
caps.dwPrivateCaps = DDHAL_PRIVATECAP_NOTIFYPRIMARYCREATION;
lpData->dwActualSize = sizeof(DD_NTPRIVATEDRIVERCAPS);
lpData->ddRVal = DD_OK;
memcpy(lpData->lpvData, &caps, min(lpData->dwExpectedSize, sizeof(DD_NTPRIVATEDRIVERCAPS)));
}
else IF_NOT_SUPPORTED(GUID_NTCallbacks)
else IF_NOT_SUPPORTED(GUID_D3DCallbacks2)
else IF_NOT_SUPPORTED(GUID_D3DCallbacks3)
else IF_NOT_SUPPORTED(GUID_D3DExtendedCaps)
else IF_NOT_SUPPORTED(GUID_ZPixelFormats)
else IF_NOT_SUPPORTED(GUID_D3DParseUnknownCommandCallback)
else IF_NOT_SUPPORTED(GUID_Miscellaneous2Callbacks)
else IF_NOT_SUPPORTED(GUID_UpdateNonLocalHeap)
else IF_NOT_SUPPORTED(GUID_GetHeapAlignment)
else IF_NOT_SUPPORTED(GUID_DDStereoMode)
else IF_NOT_SUPPORTED(GUID_NonLocalVidMemCaps)
else IF_NOT_SUPPORTED(GUID_KernelCaps)
else IF_NOT_SUPPORTED(GUID_KernelCallbacks)
else IF_NOT_SUPPORTED(GUID_MotionCompCallbacks)
else IF_NOT_SUPPORTED(GUID_VideoPortCallbacks)
else IF_NOT_SUPPORTED(GUID_ColorControlCallbacks)
else IF_NOT_SUPPORTED(GUID_VideoPortCaps)
else IF_NOT_SUPPORTED(GUID_DDMoreSurfaceCaps)
else
{
LOG(("unknown guid"));
}
LOGF_LEAVE();
return DDHAL_DRIVER_HANDLED;
}
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;
}
DWORD APIENTRY VBoxDispDDAddAttachedSurface(PDD_ADDATTACHEDSURFACEDATA lpAddAttachedSurface)
{
LOGF_ENTER();
lpAddAttachedSurface->ddRVal = DD_OK;
LOGF_LEAVE();
return DDHAL_DRIVER_HANDLED;
}
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;
}
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;
}
DWORD APIENTRY VBoxDispDDGetBltStatus(PDD_GETBLTSTATUSDATA lpGetBltStatus)
{
PVBOXDISPDEV pDev = (PVBOXDISPDEV) lpGetBltStatus->lpDD->dhpdev;
PVBOXVHWASURFDESC pDesc = (PVBOXVHWASURFDESC)lpGetBltStatus->lpDDSurface->lpGbl->dwReserved1;
LOGF_ENTER();
if(lpGetBltStatus->dwFlags == DDGBS_CANBLT)
{
lpGetBltStatus->ddRVal = DD_OK;
}
else /* DDGBS_ISBLTDONE */
{
if (pDesc)
{
if(ASMAtomicUoReadU32(&pDesc->cPendingBltsSrc) || ASMAtomicUoReadU32(&pDesc->cPendingBltsDst))
{
VBoxDispVHWACommandCheckHostCmds(pDev);
if(ASMAtomicUoReadU32(&pDesc->cPendingBltsSrc) || ASMAtomicUoReadU32(&pDesc->cPendingBltsDst))
{
lpGetBltStatus->ddRVal = DDERR_WASSTILLDRAWING;
}
else
{
lpGetBltStatus->ddRVal = DD_OK;
}
}
else
{
lpGetBltStatus->ddRVal = DD_OK;
}
}
else
{
WARN(("!pDesc"));
lpGetBltStatus->ddRVal = DDERR_GENERIC;
}
}
LOGF_LEAVE();
return DDHAL_DRIVER_HANDLED;
}
DWORD APIENTRY VBoxDispDDGetFlipStatus(PDD_GETFLIPSTATUSDATA lpGetFlipStatus)
{
PVBOXDISPDEV pDev = (PVBOXDISPDEV) lpGetFlipStatus->lpDD->dhpdev;
PVBOXVHWASURFDESC pDesc = (PVBOXVHWASURFDESC)lpGetFlipStatus->lpDDSurface->lpGbl->dwReserved1;
LOGF_ENTER();
/*can't flip is there's a flip pending, so result is same for DDGFS_CANFLIP/DDGFS_ISFLIPDONE */
if (pDesc)
{
if(ASMAtomicUoReadU32(&pDesc->cPendingFlipsTarg) || ASMAtomicUoReadU32(&pDesc->cPendingFlipsCurr))
{
VBoxDispVHWACommandCheckHostCmds(pDev);
if(ASMAtomicUoReadU32(&pDesc->cPendingFlipsTarg) || ASMAtomicUoReadU32(&pDesc->cPendingFlipsCurr))
{
lpGetFlipStatus->ddRVal = DDERR_WASSTILLDRAWING;
}
else
{
lpGetFlipStatus->ddRVal = DD_OK;
}
}
else
{
lpGetFlipStatus->ddRVal = DD_OK;
}
}
else
{
WARN(("!pDesc"));
lpGetFlipStatus->ddRVal = DDERR_GENERIC;
}
LOGF_LEAVE();
return DDHAL_DRIVER_HANDLED;
}
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;
}
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;
}