DisplayImpl.cpp revision 33d7e5da34b4a867f2dcf7ee884f8f5f50692363
cabde247f900dcf6e58d009bbdd15099c028c6fcvboxsync * VirtualBox COM class implementation
cabde247f900dcf6e58d009bbdd15099c028c6fcvboxsync * Copyright (C) 2006-2014 Oracle Corporation
cabde247f900dcf6e58d009bbdd15099c028c6fcvboxsync * This file is part of VirtualBox Open Source Edition (OSE), as
cabde247f900dcf6e58d009bbdd15099c028c6fcvboxsync * available from http://www.virtualbox.org. This file is free software;
cabde247f900dcf6e58d009bbdd15099c028c6fcvboxsync * you can redistribute it and/or modify it under the terms of the GNU
cabde247f900dcf6e58d009bbdd15099c028c6fcvboxsync * General Public License (GPL) as published by the Free Software
cabde247f900dcf6e58d009bbdd15099c028c6fcvboxsync * Foundation, in version 2 as it comes in the "COPYING" file of the
cabde247f900dcf6e58d009bbdd15099c028c6fcvboxsync * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
cabde247f900dcf6e58d009bbdd15099c028c6fcvboxsync * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
cabde247f900dcf6e58d009bbdd15099c028c6fcvboxsync/* generated header */
cabde247f900dcf6e58d009bbdd15099c028c6fcvboxsync#if defined(DEBUG) || defined(VBOX_STRICT) /* for VM_ASSERT_EMT(). */
cabde247f900dcf6e58d009bbdd15099c028c6fcvboxsync#if defined(VBOX_WITH_CROGL) || defined(VBOX_WITH_CRHGSMI)
cabde247f900dcf6e58d009bbdd15099c028c6fcvboxsynctypedef enum
cabde247f900dcf6e58d009bbdd15099c028c6fcvboxsync * Display driver instance data.
cabde247f900dcf6e58d009bbdd15099c028c6fcvboxsync * @implements PDMIDISPLAYCONNECTOR
cabde247f900dcf6e58d009bbdd15099c028c6fcvboxsync /** Pointer to the display object. */
cabde247f900dcf6e58d009bbdd15099c028c6fcvboxsync /** Pointer to the driver instance structure. */
cabde247f900dcf6e58d009bbdd15099c028c6fcvboxsync /** Pointer to the keyboard port interface of the driver/device above us. */
cabde247f900dcf6e58d009bbdd15099c028c6fcvboxsync /** Our display connector interface. */
cabde247f900dcf6e58d009bbdd15099c028c6fcvboxsync#if defined(VBOX_WITH_VIDEOHWACCEL) || defined(VBOX_WITH_CRHGSMI)
cabde247f900dcf6e58d009bbdd15099c028c6fcvboxsync /** VBVA callbacks */
cabde247f900dcf6e58d009bbdd15099c028c6fcvboxsync/** Converts PDMIDISPLAYCONNECTOR pointer to a DRVMAINDISPLAY pointer. */
#define PDMIDISPLAYCONNECTOR_2_MAINDISPLAY(pInterface) RT_FROM_MEMBER(pInterface, DRVMAINDISPLAY, IConnector)
mfVideoAccelVRDP = false;
mfu32SupportedOrders = 0;
mcVideoAccelVRDPRefs = 0;
#ifdef VBOX_WITH_CROGL
mfCrOglDataHidden = false;
mfVMMDevInited = false;
#ifdef VBOX_WITH_HGSMI
mu32UpdateVBVAFlags = 0;
mfVMMDevSupportsGraphics = false;
#ifdef VBOX_WITH_VPX
maVideoRecEnabled[i] = true;
#ifdef VBOX_WITH_CRHGSMI
#ifdef VBOX_WITH_CROGL
return BaseFinalConstruct();
uninit();
#ifdef VBOX_WITH_CRHGSMI
// public initializer/uninitializer for internal purposes only
if (pu8Thumbnail)
src,
return rc;
#ifdef VBOX_WITH_CROGL
if (pVMMDev)
if (pScreenshot)
if (!f3DSnapshot)
int rc = Display::i_displayTakeScreenshotEMT(that, VBOX_VIDEO_PRIMARY_SCREEN, &pu8Data, &cbData, &cx, &cy);
if (pu8PNG)
cbPNG = 0;
cxPNG = 0;
cyPNG = 0;
if (cbThumbnail)
if (cbPNG)
DECLCALLBACK(int)
Display::i_displaySSMLoadScreenshot(PSSMHANDLE pSSM, void *pvUser, uint32_t uVersion, uint32_t uPass)
return rc;
DECLCALLBACK(void)
DECLCALLBACK(int)
return SSMR3SetCfgError(pSSM, RT_SRC_POS, N_("Number of monitors changed (%d->%d)!"), cMonitors, that->mcMonitors);
uint32_t w;
uint32_t h;
return VINF_SUCCESS;
mfSourceBitmapEnabled = true;
fVGAResizing = false;
#ifdef VBOX_WITH_HGSMI
#ifdef VBOX_WITH_CROGL
return S_OK;
unsigned uScreenId;
if (mParent)
if (mpDrv)
mfVMMDevInited = true;
/* uInstance is an arbitrary value greater than 1024. Such a value will ensure a quick seek in saved state file. */
rc = SSMR3RegisterExternal(pUVM, "DisplayScreenshot", 1100 /*uInstance*/, sSSMDisplayScreenshotVer, 0 /*cbGuess*/,
return VINF_SUCCESS;
DECLCALLBACK(void) Display::i_displayCrCmdFree(struct VBOXCRCMDCTL* pCmd, uint32_t cbCmd, int rc, void *pvCompletion)
return VINF_SUCCESS;
if (!mhCrOglSvc)
return VERR_INVALID_STATE;
if (!pVMMDev)
return VERR_INVALID_STATE;
if (!pData)
return VERR_NO_MEMORY;
return rc;
int Display::i_notifyCroglResize(const PVBVAINFOVIEW pView, const PVBVAINFOSCREEN pScreen, void *pvVRAM)
if (mfIsCr3DEnabled)
if (mhCrOglSvc)
if (pVMMDev)
if (pCtl)
return rc;
return VINF_SUCCESS;
return VINF_SUCCESS;
pFBInfo->w = w;
pFBInfo->h = h;
HRESULT hr = maFramebuffers[uScreenId].pFramebuffer->NotifyChange(uScreenId, 0, 0, w, h); /* @todo origin */
&ulWidth,
&ulHeight,
return VINF_SUCCESS;
if (*px < 0)
*px = 0;
if (*py < 0)
*py = 0;
#ifdef DEBUG_sunlover
bool fUpdateImage = RT_BOOL(maFramebuffers[uScreenId].u32Caps & FramebufferCapabilities_UpdateImage);
#ifndef VBOX_WITH_HGSMI
/* The following is from GuestImpl.cpp. */
if (!fNotify)
void Display::i_handleUpdateVBVAInputMapping(int32_t xOrigin, int32_t yOrigin, uint32_t cx, uint32_t cy)
if (!mpDrv)
HRESULT Display::i_reportHostCursorCapabilities(uint32_t fCapabilitiesAdded, uint32_t fCapabilitiesRemoved)
mpDrv->pUpPort->pfnReportHostCursorCapabilities (mpDrv->pUpPort, fCapabilitiesAdded, fCapabilitiesRemoved);
return hrc;
return S_OK;
return S_OK;
* sizeof(RTRECT));
if (!pVisibleRegion)
return VERR_NO_TMP_MEMORY;
unsigned uScreenId;
if (mpDrv)
uint32_t i;
for (i = 0; i < cRect; i++)
if (mhCrOglSvc)
pCtl = (VBOXCRCMDCTL_HGCM*)RTMemAlloc(RT_MAX(cRect, 1) * sizeof(RTRECT) + sizeof(VBOXCRCMDCTL_HGCM));
if (pCtl)
return VINF_SUCCESS;
return VERR_NOT_SUPPORTED;
#ifdef VBOX_WITH_HGSMI
bool fVideoAccelVRDP,
if (fVideoAccelVRDP)
LogRelFlowFunc((" fu32HostEvents = 0x%08X, fu32SupportedOrders = 0x%08X\n", fu32HostEvents, fu32SupportedOrders));
bool fVideoAccelVRDP,
unsigned cFBInfos)
unsigned uScreenId;
return rc;
return rc;
int c = fEnable?
Assert (c >= 0);
mfVideoAccelVRDP = false;
mfu32SupportedOrders = 0;
i_vbvaSetMemoryFlags(pVideoAccel->pVbvaMemory, pVideoAccel->fVideoAccelEnabled, mfVideoAccelVRDP, mfu32SupportedOrders,
#ifdef VBOX_WITH_HGSMI
&& !mfVideoAccelVRDP)
mfVideoAccelVRDP = true;
mfu32SupportedOrders = ~0;
i_vbvaSetMemoryFlags(pVideoAccel->pVbvaMemory, pVideoAccel->fVideoAccelEnabled, mfVideoAccelVRDP, mfu32SupportedOrders,
#ifdef VBOX_WITH_HGSMI
mfSourceBitmapEnabled = false;
while (uScreenId > 0)
--uScreenId;
pFBInfo->w,
pFBInfo->h,
HRESULT Display::getScreenResolution(ULONG aScreenId, ULONG *aWidth, ULONG *aHeight, ULONG *aBitsPerPixel,
if (mpDrv)
return E_INVALIDARG;
if (aWidth)
if (aHeight)
if (aBitsPerPixel)
if (aXOrigin)
if (aYOrigin)
if (aGuestMonitorStatus)
return S_OK;
size_t i;
if (mpDrv)
pFBInfo->w,
pFBInfo->h,
if (mfIsCr3DEnabled)
return S_OK;
if (mfIsCr3DEnabled)
return S_OK;
return S_OK;
if (!width)
if (!height)
if (!bpp)
return E_INVALIDARG;
return E_INVALIDARG;
return hrc;
if (pVMMDev)
if (pVMMDevPort)
return S_OK;
if (pVMMDev)
if (pVMMDevPort)
if (!enabled)
if (!pData)
return VERR_NO_MEMORY;
pData->aParms[0].u.pointer.size = 0; /* <- means null rects, NULL pRects address and 0 rects means "disable" */
return S_OK;
BOOL Display::i_displayCheckTakeScreenshotCrOgl(Display *pDisplay, ULONG aScreenId, uint8_t *pu8Data,
if (pVMMDev)
CRVBOXHGCMTAKESCREENSHOT *pScreenshot = (CRVBOXHGCMTAKESCREENSHOT*)RTMemAlloc(sizeof(*pScreenshot));
if (pScreenshot)
return TRUE;
return FALSE;
int Display::i_displayTakeScreenshotEMT(Display *pDisplay, ULONG aScreenId, uint8_t **ppu8Data, size_t *pcbData,
int rc;
rc = pDisplay->mpDrv->pUpPort->pfnTakeScreenshot(pDisplay->mpDrv->pUpPort, ppu8Data, pcbData, pu32Width, pu32Height);
if (cbRequired)
*pcbData = 0;
*pu32Width = 0;
*pu32Height = 0;
return rc;
static int i_displayTakeScreenshot(PUVM pUVM, Display *pDisplay, struct DRVMAINDISPLAY *pDrv, ULONG aScreenId,
if (Display::i_displayCheckTakeScreenshotCrOgl(pDisplay, aScreenId, (uint8_t*)address, width, height))
return VINF_SUCCESS;
while (cRetries-- > 0)
src,
return vrc;
int vrc = i_displayTakeScreenshot(ptrVM.rawUVM(), this, mpDrv, aScreenId, aAddress, aWidth, aHeight);
while (cPixels--)
while (cPixels--)
return rc;
return rc;
cbOut = 0;
return rc;
#ifdef VBOX_WITH_VPX
return VINF_SUCCESS;
return VERR_NOT_IMPLEMENTED;
#ifdef VBOX_WITH_VPX
return VINF_SUCCESS;
return rc;
if (pszSuff)
if (!pszAbsPath)
if (!pszSuff)
pszSuff);
return rc;
return VERR_NOT_IMPLEMENTED;
#ifdef VBOX_WITH_VPX
rc = pDisplay->mpDrv->pUpPort->pfnDisplayBlt(pDisplay->mpDrv->pUpPort, address, x, y, width, height);
&ulWidth,
&ulHeight,
xSrc = x;
ySrc = y;
return rc;
HRESULT Display::drawToScreen(ULONG aScreenId, BYTE *aAddress, ULONG aX, ULONG aY, ULONG aWidth, ULONG aHeight)
return rc;
unsigned uScreenId;
pDisplay->mpDrv->pUpPort->pfnUpdateDisplayAll(pDisplay->mpDrv->pUpPort, /* fFailOnResize = */ true);
&ulWidth,
&ulHeight,
if (!fUpdateAll)
return VINF_SUCCESS;
int rcVBox = VMR3ReqCallNoWaitU(ptrVM.rawUVM(), VMCPUID_ANY, (PFNRT)Display::i_InvalidateAndUpdateEMT,
return rc;
int rcVBox = VMR3ReqCallNoWaitU(ptrVM.rawUVM(), VMCPUID_ANY, (PFNRT)Display::i_InvalidateAndUpdateEMT,
return rc;
#ifdef VBOX_WITH_VIDEOHWACCEL
return S_OK;
return E_NOTIMPL;
AssertMsgReturn(aScreenId < mcMonitors, ("aScreendId=%d mcMonitors=%d\n", aScreenId, mcMonitors), E_INVALIDARG);
if (mfIsCr3DEnabled)
#ifdef VBOX_WITH_VMSVGA
if (mpDrv)
return S_OK;
bool fSetRenderVRAM = false;
bool fInvalidate = false;
if (!mfSourceBitmapEnabled)
return E_FAIL;
&ulWidth,
&ulHeight,
if (fSetRenderVRAM)
if (fInvalidate)
return hr;
switch (aType)
#ifdef VBOX_WITH_CROGL
i_crOglWindowsShow(true);
#ifdef VBOX_WITH_CROGL
i_crOglWindowsShow(false);
AssertFailed();
return S_OK;
if (!pVMMDev)
return VERR_INVALID_STATE;
#ifdef VBOX_WITH_CRHGSMI
if (pVMMDev)
return VINF_VGA_RESIZE_IN_PROGRESS;
int rc = pThis->i_handleDisplayResize(VBOX_VIDEO_PRIMARY_SCREEN, bpp, pvVRAM, cbLine, cx, cy, VBVA_SCREEN_F_ACTIVE);
AssertRelease(f);
return rc;
#ifdef DEBUG_sunlover
#ifdef DEBUG_sunlover_2
unsigned uScreenId;
#ifdef VBOX_WITH_VPX
if (ASMAtomicCmpXchgU32(&pDisplay->mfCrOglVideoRecState, CRVREC_STATE_SUBMITTED, CRVREC_STATE_IDLE))
rc = pDisplay->i_crCtlSubmit(&pData->Hdr, sizeof(*pData), Display::i_displayVRecCompletion, pDisplay);
#ifdef DEBUG_sunlover_2
DECLCALLBACK(void) Display::i_displayLFBModeChangeCallback(PPDMIDISPLAYCONNECTOR pInterface, bool fEnabled)
DECLCALLBACK(void) Display::i_displayProcessAdapterDataCallback(PPDMIDISPLAYCONNECTOR pInterface, void *pvVRAM,
#ifdef VBOX_WITH_VIDEOHWACCEL
#ifndef S_FALSE
return VERR_INVALID_PARAMETER;
return VINF_SUCCESS;
return VINF_CALLBACK_RETURN;
return VERR_NOT_IMPLEMENTED;
return VERR_GENERAL_FAILURE;
DECLCALLBACK(int) Display::i_displayVHWACommandProcess(PPDMIDISPLAYCONNECTOR pInterface, PVBOXVHWACMD pCommand)
#ifdef VBOX_WITH_CRHGSMI
void Display::i_handleCrHgsmiCommandCompletion(int32_t result, uint32_t u32Function, PVBOXHGCMSVCPARM pParam)
void Display::i_handleCrHgsmiControlCompletion(int32_t result, uint32_t u32Function, PVBOXHGCMSVCPARM pParam)
if (mhCrOglSvc)
if (pVMMDev)
if (mhCrOglSvc)
if (pVMMDev)
DECLCALLBACK(void) Display::i_displayCrHgsmiCommandProcess(PPDMIDISPLAYCONNECTOR pInterface, PVBOXVDMACMD_CHROMIUM_CMD pCmd,
DECLCALLBACK(void) Display::i_displayCrHgsmiControlProcess(PPDMIDISPLAYCONNECTOR pInterface, PVBOXVDMACMD_CHROMIUM_CTL pCmd,
DECLCALLBACK(void) Display::i_displayCrHgsmiCommandCompletion(int32_t result, uint32_t u32Function, PVBOXHGCMSVCPARM pParam,
void *pvContext)
DECLCALLBACK(void) Display::i_displayCrHgsmiControlCompletion(int32_t result, uint32_t u32Function, PVBOXHGCMSVCPARM pParam,
void *pvContext)
DECLCALLBACK(void) Display::i_displayCrHgcmCtlSubmitCompletion(int32_t result, uint32_t u32Function, PVBOXHGCMSVCPARM pParam,
void *pvContext)
void *pvCompletion)
if (!pVMMDev)
return VERR_INVALID_STATE;
int rc = pVMMDev->hgcmHostFastCallAsync(mhCrOglSvc, SHCRGL_HOST_FN_CTL, &parm, i_displayCrHgcmCtlSubmitCompletion,
return rc;
void *pvCompletion)
int Display::i_crCtlSubmit(struct VBOXCRCMDCTL* pCmd, uint32_t cbCmd, PFNCRCTLCOMPLETION pfnCompletion, void *pvCompletion)
if (mhCrOglSvc)
rc = mpDrv->pVBVACallbacks->pfnCrCtlSubmit(mpDrv->pVBVACallbacks, pCmd, cbCmd, pfnCompletion, pvCompletion);
return rc;
if (mhCrOglSvc)
return rc;
if (!pCmdCopy)
return VERR_NO_MEMORY;
return rc;
return VINF_SUCCESS;
int Display::i_crCtlSubmitSyncIfHasDataForScreen(uint32_t u32ScreenID, struct VBOXCRCMDCTL* pCmd, uint32_t cbCmd)
return rc;
# if VBOX_WITH_VPX
# if VBOX_WITH_VPX
HRESULT Display::notifyScaleFactorChange(ULONG aScreenId, ULONG aScaleFactorWMultiplied, ULONG aScaleFactorHMultiplied)
return E_INVALIDARG;
if (mfIsCr3DEnabled)
if (mhCrOglSvc)
if (pVMMDev)
pCtl = (VBOXCRCMDCTL_HGCM *)RTMemAlloc(sizeof(CRVBOXHGCMSETSCALEFACTOR) + sizeof(VBOXCRCMDCTL_HGCM));
if (pCtl)
int rc;
LogRel(("Attempt to specify OpenGL content scale factor while corresponding HGCM host service not yet runing. Ignored.\n"));
AssertMsgFailed(("Attempt to specify OpenGL content scale factor while 3D acceleration is disabled in VM config. Ignored.\n"));
return hr;
AssertMsgFailed(("Attempt to specify OpenGL content scale factor while corresponding functionality is disabled."));
return E_UNEXPECTED;
DECLCALLBACK(bool) Display::i_displayCrVRecScreenshotBegin(void *pvCtx, uint32_t uScreen, uint64_t u64TimeStamp)
DECLCALLBACK(void) Display::i_displayCrVRecScreenshotEnd(void *pvCtx, uint32_t uScreen, uint64_t u64TimeStamp)
DECLCALLBACK(void) Display::i_displayVRecCompletion(struct VBOXCRCMDCTL* pCmd, uint32_t cbCmd, int rc, void *pvCompletion)
#ifdef VBOX_WITH_HGSMI
DECLCALLBACK(int) Display::i_displayVBVAEnable(PPDMIDISPLAYCONNECTOR pInterface, unsigned uScreenId, PVBVAHOSTFLAGS pHostFlags,
bool fRenderThreadMode)
if (pThis->maFramebuffers[uScreenId].fVBVAEnabled && pThis->maFramebuffers[uScreenId].fRenderThreadMode != fRenderThreadMode)
#ifdef DEBUG_misha
return VERR_INVALID_STATE;
vbvaSetMemoryFlagsHGSMI(uScreenId, pThis->mfu32SupportedOrders, pThis->mfVideoAccelVRDP, &pThis->maFramebuffers[uScreenId]);
return VINF_SUCCESS;
DECLCALLBACK(void) Display::i_displayVBVADisable(PPDMIDISPLAYCONNECTOR pInterface, unsigned uScreenId)
DECLCALLBACK(void) Display::i_displayVBVAUpdateBegin(PPDMIDISPLAYCONNECTOR pInterface, unsigned uScreenId)
vbvaSetMemoryFlagsAllHGSMI(pThis->mfu32SupportedOrders, pThis->mfVideoAccelVRDP, pThis->maFramebuffers,
DECLCALLBACK(void) Display::i_displayVBVAUpdateProcess(PPDMIDISPLAYCONNECTOR pInterface, unsigned uScreenId,
LogFlowFunc(("uScreenId %d pCmd %p cbCmd %d, @%d,%d %dx%d\n", uScreenId, pCmd, cbCmd, pCmd->x, pCmd->y, pCmd->w, pCmd->h));
&ulWidth,
&ulHeight,
DECLCALLBACK(void) Display::i_displayVBVAUpdateEnd(PPDMIDISPLAYCONNECTOR pInterface, unsigned uScreenId, int32_t x, int32_t y,
#ifdef DEBUG_sunlover
static void logVBVAResize(const PVBVAINFOVIEW pView, const PVBVAINFOSCREEN pScreen, const DISPLAYFBINFO *pFBInfo)
pFBInfo->w,
pFBInfo->h,
DECLCALLBACK(int) Display::i_displayVBVAResize(PPDMIDISPLAYCONNECTOR pInterface, const PVBVAINFOVIEW pView,
return VINF_SUCCESS;
fResize = true;
if (fNewOrigin)
if (!fResize)
if (fNewOrigin)
return VINF_SUCCESS;
DECLCALLBACK(int) Display::i_displayVBVAMousePointerShape(PPDMIDISPLAYCONNECTOR pInterface, bool fVisible, bool fAlpha,
const void *pvShape)
if (pvShape)
return VINF_SUCCESS;
DECLCALLBACK(void) Display::i_displayVBVAGuestCapabilityUpdate(PPDMIDISPLAYCONNECTOR pInterface, uint32_t fCapabilities)
DECLCALLBACK(void) Display::i_displayVBVAInputMappingUpdate(PPDMIDISPLAYCONNECTOR pInterface, int32_t xOrigin, int32_t yOrigin,
return NULL;
#ifdef VBOX_WITH_VPX
#ifdef VBOX_WITH_CRHGSMI
#ifdef VBOX_WITH_VIDEOHWACCEL
#ifdef VBOX_WITH_CRHGSMI
#ifdef VBOX_WITH_HGSMI
return VERR_PDM_MISSING_INTERFACE_ABOVE;
return VERR_PDM_MISSING_INTERFACE_ABOVE;
void *pv;
return rc;
#ifdef VBOX_WITH_CRHGSMI
#ifdef VBOX_WITH_VPX
if (fEnabled)
return rc;
sizeof(DRVMAINDISPLAY),
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,