summaryrefslogtreecommitdiff
path: root/src/VBox/Main/src-client/DisplayImpl.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/VBox/Main/src-client/DisplayImpl.cpp')
-rw-r--r--src/VBox/Main/src-client/DisplayImpl.cpp1649
1 files changed, 1204 insertions, 445 deletions
diff --git a/src/VBox/Main/src-client/DisplayImpl.cpp b/src/VBox/Main/src-client/DisplayImpl.cpp
index fc261019..3477a07c 100644
--- a/src/VBox/Main/src-client/DisplayImpl.cpp
+++ b/src/VBox/Main/src-client/DisplayImpl.cpp
@@ -4,7 +4,7 @@
*/
/*
- * Copyright (C) 2006-2012 Oracle Corporation
+ * Copyright (C) 2006-2013 Oracle Corporation
*
* This file is part of VirtualBox Open Source Edition (OSE), as
* available from http://www.virtualbox.org. This file is free software;
@@ -30,10 +30,11 @@
#include <iprt/semaphore.h>
#include <iprt/thread.h>
#include <iprt/asm.h>
+#include <iprt/time.h>
#include <iprt/cpp/utils.h>
#include <VBox/vmm/pdmdrv.h>
-#ifdef DEBUG /* for VM_ASSERT_EMT(). */
+#if defined(DEBUG) || defined(VBOX_STRICT) /* for VM_ASSERT_EMT(). */
# include <VBox/vmm/vm.h>
#endif
@@ -48,9 +49,18 @@
#include <VBox/com/array.h>
#ifdef VBOX_WITH_VPX
+# include <iprt/path.h>
# include "VideoRec.h"
#endif
+#ifdef VBOX_WITH_CROGL
+typedef enum
+{
+ CRVREC_STATE_IDLE,
+ CRVREC_STATE_SUBMITTED
+} CRVREC_STATE;
+#endif
+
/**
* Display driver instance data.
*
@@ -76,8 +86,8 @@ typedef struct DRVMAINDISPLAY
#define PDMIDISPLAYCONNECTOR_2_MAINDISPLAY(pInterface) RT_FROM_MEMBER(pInterface, DRVMAINDISPLAY, IConnector)
#ifdef DEBUG_sunlover
-static STAMPROFILE StatDisplayRefresh;
-static int stam = 0;
+static STAMPROFILE g_StatDisplayRefresh;
+static int g_stam = 0;
#endif /* DEBUG_sunlover */
// constructor / destructor
@@ -105,6 +115,9 @@ HRESULT Display::FinalConstruct()
mfPendingVideoAccelEnable = false;
mfMachineRunning = false;
+#ifdef VBOX_WITH_CROGL
+ mfCrOglDataHidden = false;
+#endif
mpu8VbvaPartial = NULL;
mcbVbvaPartial = 0;
@@ -121,11 +134,34 @@ HRESULT Display::FinalConstruct()
int rc = RTCritSectInit(&mVBVALock);
AssertRC(rc);
+
+ rc = RTCritSectInit(&mSaveSeamlessRectLock);
+ AssertRC(rc);
+
mfu32PendingVideoAccelDisable = false;
#ifdef VBOX_WITH_HGSMI
mu32UpdateVBVAFlags = 0;
#endif
+#ifdef VBOX_WITH_VPX
+ mpVideoRecCtx = NULL;
+ for (unsigned i = 0; i < RT_ELEMENTS(maVideoRecEnabled); i++)
+ maVideoRecEnabled[i] = true;
+#endif
+
+#ifdef VBOX_WITH_CRHGSMI
+ mhCrOglSvc = NULL;
+#endif
+#ifdef VBOX_WITH_CROGL
+ RT_ZERO(mCrOglCallbacks);
+ RT_ZERO(mCrOglScreenshotData);
+ mfCrOglVideoRecState = CRVREC_STATE_IDLE;
+ mCrOglScreenshotData.u32Screen = CRSCREEN_ALL;
+ mCrOglScreenshotData.pvContext = this;
+ mCrOglScreenshotData.pfnScreenshotBegin = displayCrVRecScreenshotBegin;
+ mCrOglScreenshotData.pfnScreenshotPerform = displayCrVRecScreenshotPerform;
+ mCrOglScreenshotData.pfnScreenshotEnd = displayCrVRecScreenshotEnd;
+#endif
return BaseFinalConstruct();
}
@@ -137,7 +173,13 @@ void Display::FinalRelease()
if (RTCritSectIsInitialized (&mVBVALock))
{
RTCritSectDelete (&mVBVALock);
- memset (&mVBVALock, 0, sizeof (mVBVALock));
+ RT_ZERO(mVBVALock);
+ }
+
+ if (RTCritSectIsInitialized(&mSaveSeamlessRectLock))
+ {
+ RTCritSectDelete(&mSaveSeamlessRectLock);
+ RT_ZERO(mSaveSeamlessRectLock);
}
BaseFinalRelease();
}
@@ -205,6 +247,47 @@ static int displayMakeThumbnail(uint8_t *pu8Data, uint32_t cx, uint32_t cy,
return rc;
}
+#ifdef VBOX_WITH_CROGL
+typedef struct
+{
+ CRVBOXHGCMTAKESCREENSHOT Base;
+
+ /* 32bpp small RGB image. */
+ uint8_t *pu8Thumbnail;
+ uint32_t cbThumbnail;
+ uint32_t cxThumbnail;
+ uint32_t cyThumbnail;
+
+ /* PNG screenshot. */
+ uint8_t *pu8PNG;
+ uint32_t cbPNG;
+ uint32_t cxPNG;
+ uint32_t cyPNG;
+} VBOX_DISPLAY_SAVESCREENSHOT_DATA;
+
+static DECLCALLBACK(void) displaySaveScreenshotReport(void *pvCtx, uint32_t uScreen,
+ uint32_t x, uint32_t y, uint32_t uBitsPerPixel,
+ uint32_t uBytesPerLine, uint32_t uGuestWidth, uint32_t uGuestHeight,
+ uint8_t *pu8BufferAddress, uint64_t u64TimeStamp)
+{
+ VBOX_DISPLAY_SAVESCREENSHOT_DATA *pData = (VBOX_DISPLAY_SAVESCREENSHOT_DATA*)pvCtx;
+ displayMakeThumbnail(pu8BufferAddress, uGuestWidth, uGuestHeight, &pData->pu8Thumbnail, &pData->cbThumbnail, &pData->cxThumbnail, &pData->cyThumbnail);
+ int rc = DisplayMakePNG(pu8BufferAddress, uGuestWidth, uGuestHeight, &pData->pu8PNG, &pData->cbPNG, &pData->cxPNG, &pData->cyPNG, 1);
+ if (RT_FAILURE(rc))
+ {
+ AssertMsgFailed(("DisplayMakePNG failed %d\n", rc));
+ if (pData->pu8PNG)
+ {
+ RTMemFree(pData->pu8PNG);
+ pData->pu8PNG = NULL;
+ }
+ pData->cbPNG = 0;
+ pData->cxPNG = 0;
+ pData->cyPNG = 0;
+ }
+}
+#endif
+
DECLCALLBACK(void)
Display::displaySSMSaveScreenshot(PSSMHANDLE pSSM, void *pvUser)
{
@@ -222,8 +305,8 @@ Display::displaySSMSaveScreenshot(PSSMHANDLE pSSM, void *pvUser)
uint32_t cxPNG = 0;
uint32_t cyPNG = 0;
- Console::SafeVMPtr pVM (that->mParent);
- if (SUCCEEDED(pVM.rc()))
+ Console::SafeVMPtr ptrVM(that->mParent);
+ if (ptrVM.isOk())
{
/* Query RGB bitmap. */
uint8_t *pu8Data = NULL;
@@ -231,39 +314,101 @@ Display::displaySSMSaveScreenshot(PSSMHANDLE pSSM, void *pvUser)
uint32_t cx = 0;
uint32_t cy = 0;
- /* SSM code is executed on EMT(0), therefore no need to use VMR3ReqCallWait. */
- int rc = Display::displayTakeScreenshotEMT(that, VBOX_VIDEO_PRIMARY_SCREEN, &pu8Data, &cbData, &cx, &cy);
+#ifdef VBOX_WITH_CROGL
+ BOOL f3DSnapshot = FALSE;
+ BOOL is3denabled;
+ that->mParent->machine()->COMGETTER(Accelerate3DEnabled)(&is3denabled);
+ if (is3denabled && that->mCrOglCallbacks.pfnHasData())
+ {
+ VMMDev *pVMMDev = that->mParent->getVMMDev();
+ if (pVMMDev)
+ {
+ VBOX_DISPLAY_SAVESCREENSHOT_DATA *pScreenshot = (VBOX_DISPLAY_SAVESCREENSHOT_DATA*)RTMemAllocZ(sizeof (*pScreenshot));
+ if (pScreenshot)
+ {
+ /* screen id or CRSCREEN_ALL to specify all enabled */
+ pScreenshot->Base.u32Screen = 0;
+ pScreenshot->Base.u32Width = 0;
+ pScreenshot->Base.u32Height = 0;
+ pScreenshot->Base.u32Pitch = 0;
+ pScreenshot->Base.pvBuffer = NULL;
+ pScreenshot->Base.pvContext = pScreenshot;
+ pScreenshot->Base.pfnScreenshotBegin = NULL;
+ pScreenshot->Base.pfnScreenshotPerform = displaySaveScreenshotReport;
+ pScreenshot->Base.pfnScreenshotEnd = NULL;
+
+ VBOXHGCMSVCPARM parm;
+
+ parm.type = VBOX_HGCM_SVC_PARM_PTR;
+ parm.u.pointer.addr = &pScreenshot->Base;
+ parm.u.pointer.size = sizeof (pScreenshot->Base);
+
+ int rc = pVMMDev->hgcmHostCall("VBoxSharedCrOpenGL", SHCRGL_HOST_FN_TAKE_SCREENSHOT, 1, &parm);
+ if (RT_SUCCESS(rc))
+ {
+ if (pScreenshot->pu8PNG)
+ {
+ pu8Thumbnail = pScreenshot->pu8Thumbnail;
+ cbThumbnail = pScreenshot->cbThumbnail;
+ cxThumbnail = pScreenshot->cxThumbnail;
+ cyThumbnail = pScreenshot->cyThumbnail;
+
+ /* PNG screenshot. */
+ pu8PNG = pScreenshot->pu8PNG;
+ cbPNG = pScreenshot->cbPNG;
+ cxPNG = pScreenshot->cxPNG;
+ cyPNG = pScreenshot->cyPNG;
+ f3DSnapshot = TRUE;
+ }
+ else
+ AssertMsgFailed(("no png\n"));
+ }
+ else
+ AssertMsgFailed(("SHCRGL_HOST_FN_TAKE_SCREENSHOT failed %d\n", rc));
- /*
- * It is possible that success is returned but everything is 0 or NULL.
- * (no display attached if a VM is running with VBoxHeadless on OSE for example)
- */
- if (RT_SUCCESS(rc) && pu8Data)
+
+ RTMemFree(pScreenshot);
+ }
+ }
+ }
+
+ if (!f3DSnapshot)
+#endif
{
- Assert(cx && cy);
+ /* SSM code is executed on EMT(0), therefore no need to use VMR3ReqCallWait. */
+ int rc = Display::displayTakeScreenshotEMT(that, VBOX_VIDEO_PRIMARY_SCREEN, &pu8Data, &cbData, &cx, &cy);
- /* Prepare a small thumbnail and a PNG screenshot. */
- displayMakeThumbnail(pu8Data, cx, cy, &pu8Thumbnail, &cbThumbnail, &cxThumbnail, &cyThumbnail);
- rc = DisplayMakePNG(pu8Data, cx, cy, &pu8PNG, &cbPNG, &cxPNG, &cyPNG, 1);
- if (RT_FAILURE(rc))
+ /*
+ * It is possible that success is returned but everything is 0 or NULL.
+ * (no display attached if a VM is running with VBoxHeadless on OSE for example)
+ */
+ if (RT_SUCCESS(rc) && pu8Data)
{
- if (pu8PNG)
+ Assert(cx && cy);
+
+ /* Prepare a small thumbnail and a PNG screenshot. */
+ displayMakeThumbnail(pu8Data, cx, cy, &pu8Thumbnail, &cbThumbnail, &cxThumbnail, &cyThumbnail);
+ rc = DisplayMakePNG(pu8Data, cx, cy, &pu8PNG, &cbPNG, &cxPNG, &cyPNG, 1);
+ if (RT_FAILURE(rc))
{
- RTMemFree(pu8PNG);
- pu8PNG = NULL;
+ if (pu8PNG)
+ {
+ RTMemFree(pu8PNG);
+ pu8PNG = NULL;
+ }
+ cbPNG = 0;
+ cxPNG = 0;
+ cyPNG = 0;
}
- cbPNG = 0;
- cxPNG = 0;
- cyPNG = 0;
- }
- /* This can be called from any thread. */
- that->mpDrv->pUpPort->pfnFreeScreenshot(that->mpDrv->pUpPort, pu8Data);
+ /* This can be called from any thread. */
+ that->mpDrv->pUpPort->pfnFreeScreenshot(that->mpDrv->pUpPort, pu8Data);
+ }
}
}
else
{
- LogFunc(("Failed to get VM pointer 0x%x\n", pVM.rc()));
+ LogFunc(("Failed to get VM pointer 0x%x\n", ptrVM.rc()));
}
/* Regardless of rc, save what is available:
@@ -436,40 +581,8 @@ HRESULT Display::init(Console *aParent)
unconst(mParent) = aParent;
- // by default, we have an internal framebuffer which is
- // NULL, i.e. a black hole for no display output
- mFramebufferOpened = false;
-
ULONG ul;
mParent->machine()->COMGETTER(MonitorCount)(&ul);
-
-#ifdef VBOX_WITH_VPX
- if (VideoRecContextCreate(&mpVideoRecContext))
- {
- LogFlow(("Failed to create Video Recording Context\n"));
- return E_FAIL;
- }
-
- BOOL fEnabled = false;
- mParent->machine()->COMGETTER(VideoCaptureEnabled)(&fEnabled);
- if (fEnabled)
- {
- ULONG ulVideoCaptureHorzRes;
- mParent->machine()->COMGETTER(VideoCaptureWidth)(&ulVideoCaptureHorzRes);
- ULONG ulVideoCaptureVertRes;
- mParent->machine()->COMGETTER(VideoCaptureHeight)(&ulVideoCaptureVertRes);
- BSTR strVideoCaptureFile;
- mParent->machine()->COMGETTER(VideoCaptureFile)(&strVideoCaptureFile);
- LogFlow(("VidoeRecording VPX enabled\n"));
- if (VideoRecContextInit(mpVideoRecContext, strVideoCaptureFile,
- ulVideoCaptureHorzRes, ulVideoCaptureVertRes))
- {
- LogFlow(("Failed to initialize video recording context\n"));
- return E_FAIL;
- }
- }
-#endif
-
mcMonitors = ul;
for (ul = 0; ul < mcMonitors; ul++)
@@ -500,14 +613,20 @@ HRESULT Display::init(Console *aParent)
maFramebuffers[ul].fDefaultFormat = false;
- memset (&maFramebuffers[ul].dirtyRect, 0 , sizeof (maFramebuffers[ul].dirtyRect));
- memset (&maFramebuffers[ul].pendingResize, 0 , sizeof (maFramebuffers[ul].pendingResize));
+ maFramebuffers[ul].mcSavedVisibleRegion = 0;
+ maFramebuffers[ul].mpSavedVisibleRegion = NULL;
+
+ RT_ZERO(maFramebuffers[ul].dirtyRect);
+ RT_ZERO(maFramebuffers[ul].pendingResize);
#ifdef VBOX_WITH_HGSMI
maFramebuffers[ul].fVBVAEnabled = false;
maFramebuffers[ul].cVBVASkipUpdate = 0;
- memset (&maFramebuffers[ul].vbvaSkippedRect, 0, sizeof (maFramebuffers[ul].vbvaSkippedRect));
+ RT_ZERO(maFramebuffers[ul].vbvaSkippedRect);
maFramebuffers[ul].pVBVAHostFlags = NULL;
#endif /* VBOX_WITH_HGSMI */
+#ifdef VBOX_WITH_CROGL
+ RT_ZERO(maFramebuffers[ul].pendingViewportInfo);
+#endif
}
{
@@ -557,23 +676,18 @@ void Display::uninit()
mpDrv = NULL;
mpVMMDev = NULL;
mfVMMDevInited = true;
-
-#ifdef VBOX_WITH_VPX
- if (mpVideoRecContext)
- VideoRecContextClose(mpVideoRecContext);
-#endif
}
/**
* Register the SSM methods. Called by the power up thread to be able to
* pass pVM
*/
-int Display::registerSSM(PVM pVM)
+int Display::registerSSM(PUVM pUVM)
{
/* Version 2 adds width and height of the framebuffer; version 3 adds
* the framebuffer offset in the virtual desktop and the framebuffer flags.
*/
- int rc = SSMR3RegisterExternal(pVM, "DisplayData", 0, sSSMDisplayVer3,
+ int rc = SSMR3RegisterExternal(pUVM, "DisplayData", 0, sSSMDisplayVer3,
mcMonitors * sizeof(uint32_t) * 8 + sizeof(uint32_t),
NULL, NULL, NULL,
NULL, displaySSMSave, NULL,
@@ -584,20 +698,20 @@ int Display::registerSSM(PVM pVM)
* Register loaders for old saved states where iInstance was
* 3 * sizeof(uint32_t *) due to a code mistake.
*/
- rc = SSMR3RegisterExternal(pVM, "DisplayData", 12 /*uInstance*/, sSSMDisplayVer, 0 /*cbGuess*/,
+ rc = SSMR3RegisterExternal(pUVM, "DisplayData", 12 /*uInstance*/, sSSMDisplayVer, 0 /*cbGuess*/,
NULL, NULL, NULL,
NULL, NULL, NULL,
NULL, displaySSMLoad, NULL, this);
AssertRCReturn(rc, rc);
- rc = SSMR3RegisterExternal(pVM, "DisplayData", 24 /*uInstance*/, sSSMDisplayVer, 0 /*cbGuess*/,
+ rc = SSMR3RegisterExternal(pUVM, "DisplayData", 24 /*uInstance*/, sSSMDisplayVer, 0 /*cbGuess*/,
NULL, NULL, NULL,
NULL, NULL, NULL,
NULL, displaySSMLoad, NULL, this);
AssertRCReturn(rc, rc);
/* uInstance is an arbitrary value greater than 1024. Such a value will ensure a quick seek in saved state file. */
- rc = SSMR3RegisterExternal(pVM, "DisplayScreenshot", 1100 /*uInstance*/, sSSMDisplayScreenshotVer, 0 /*cbGuess*/,
+ rc = SSMR3RegisterExternal(pUVM, "DisplayScreenshot", 1100 /*uInstance*/, sSSMDisplayScreenshotVer, 0 /*cbGuess*/,
NULL, NULL, NULL,
NULL, displaySSMSaveScreenshot, NULL,
NULL, displaySSMLoadScreenshot, NULL, this);
@@ -607,6 +721,46 @@ int Display::registerSSM(PVM pVM)
return VINF_SUCCESS;
}
+#ifdef VBOX_WITH_CROGL
+int Display::crOglWindowsShow(bool fShow)
+{
+ if (!mfCrOglDataHidden == !!fShow)
+ return VINF_SUCCESS;
+
+ if (!mhCrOglSvc)
+ {
+ /* no 3D */
+#ifdef DEBUG
+ BOOL is3denabled;
+ mParent->machine()->COMGETTER(Accelerate3DEnabled)(&is3denabled);
+ Assert(!is3denabled);
+#endif
+ return VERR_INVALID_STATE;
+ }
+
+ VMMDev *pVMMDev = mParent->getVMMDev();
+ if (!pVMMDev)
+ {
+ AssertMsgFailed(("no vmmdev\n"));
+ return VERR_INVALID_STATE;
+ }
+
+ VBOXHGCMSVCPARM parm;
+
+ parm.type = VBOX_HGCM_SVC_PARM_32BIT;
+ parm.u.uint32 = (uint32_t)fShow;
+
+ int rc = pVMMDev->hgcmHostFastCallAsync(mhCrOglSvc, SHCRGL_HOST_FN_WINDOWS_SHOW, &parm, NULL, NULL);
+ if (RT_SUCCESS(rc))
+ mfCrOglDataHidden = !fShow;
+ else
+ AssertMsgFailed(("hgcmHostFastCallAsync failed rc %n", rc));
+
+ return rc;
+}
+#endif
+
+
// IEventListener method
STDMETHODIMP Display::HandleEvent(IEvent * aEvent)
{
@@ -629,9 +783,20 @@ STDMETHODIMP Display::HandleEvent(IEvent * aEvent)
LogRelFlowFunc(("Machine is running.\n"));
mfMachineRunning = true;
+
+#ifdef VBOX_WITH_CROGL
+ crOglWindowsShow(true);
+#endif
}
else
+ {
mfMachineRunning = false;
+
+#ifdef VBOX_WITH_CROGL
+ if (machineState == MachineState_Paused)
+ crOglWindowsShow(false);
+#endif
+ }
break;
}
default:
@@ -650,7 +815,7 @@ STDMETHODIMP Display::HandleEvent(IEvent * aEvent)
static int callFramebufferResize (IFramebuffer *pFramebuffer, unsigned uScreenId,
ULONG pixelFormat, void *pvVRAM,
uint32_t bpp, uint32_t cbLine,
- int w, int h)
+ uint32_t w, uint32_t h)
{
Assert (pFramebuffer);
@@ -662,13 +827,53 @@ static int callFramebufferResize (IFramebuffer *pFramebuffer, unsigned uScreenId
if (!finished)
{
- LogRelFlowFunc (("External framebuffer wants us to wait!\n"));
+ LogRelFlowFunc(("External framebuffer wants us to wait!\n"));
return VINF_VGA_RESIZE_IN_PROGRESS;
}
return VINF_SUCCESS;
}
+int Display::notifyCroglResize(const PVBVAINFOVIEW pView, const PVBVAINFOSCREEN pScreen, void *pvVRAM)
+{
+#if defined(VBOX_WITH_HGCM) && defined(VBOX_WITH_CROGL)
+ BOOL is3denabled;
+ mParent->machine()->COMGETTER(Accelerate3DEnabled)(&is3denabled);
+
+ if (is3denabled)
+ {
+ int rc = VERR_INVALID_STATE;
+ if (mhCrOglSvc)
+ {
+ VMMDev *pVMMDev = mParent->getVMMDev();
+ if (pVMMDev)
+ {
+ CRVBOXHGCMDEVRESIZE *pData = (CRVBOXHGCMDEVRESIZE*)RTMemAlloc(sizeof (*pData));
+ if (pData)
+ {
+ pData->Screen = *pScreen;
+ pData->pvVRAM = pvVRAM;
+
+ VBOXHGCMSVCPARM parm;
+
+ parm.type = VBOX_HGCM_SVC_PARM_PTR;
+ parm.u.pointer.addr = pData;
+ parm.u.pointer.size = sizeof (*pData);
+
+ rc = pVMMDev->hgcmHostFastCallAsync(mhCrOglSvc, SHCRGL_HOST_FN_DEV_RESIZE, &parm, displayCrAsyncCmdCompletion, this);
+ AssertRC(rc);
+ }
+ else
+ rc = VERR_NO_MEMORY;
+ }
+ }
+
+ return rc;
+ }
+#endif /* #if defined(VBOX_WITH_HGCM) && defined(VBOX_WITH_CROGL) */
+ return VINF_SUCCESS;
+}
+
/**
* Handles display resize event.
* Disables access to VGA device;
@@ -682,11 +887,11 @@ static int callFramebufferResize (IFramebuffer *pFramebuffer, unsigned uScreenId
* @thread EMT
*/
int Display::handleDisplayResize (unsigned uScreenId, uint32_t bpp, void *pvVRAM,
- uint32_t cbLine, int w, int h, uint16_t flags)
+ uint32_t cbLine, uint32_t w, uint32_t h, uint16_t flags)
{
- LogRel (("Display::handleDisplayResize(): uScreenId = %d, pvVRAM=%p "
- "w=%d h=%d bpp=%d cbLine=0x%X, flags=0x%X\n",
- uScreenId, pvVRAM, w, h, bpp, cbLine, flags));
+ LogRel(("Display::handleDisplayResize(): uScreenId = %d, pvVRAM=%p "
+ "w=%d h=%d bpp=%d cbLine=0x%X, flags=0x%X\n",
+ uScreenId, pvVRAM, w, h, bpp, cbLine, flags));
/* If there is no framebuffer, this call is not interesting. */
if ( uScreenId >= mcMonitors
@@ -695,12 +900,15 @@ int Display::handleDisplayResize (unsigned uScreenId, uint32_t bpp, void *pvVRAM
return VINF_SUCCESS;
}
- mLastAddress = pvVRAM;
- mLastBytesPerLine = cbLine;
- mLastBitsPerPixel = bpp,
- mLastWidth = w;
- mLastHeight = h;
- mLastFlags = flags;
+ if (uScreenId == VBOX_VIDEO_PRIMARY_SCREEN)
+ {
+ mLastAddress = pvVRAM;
+ mLastBytesPerLine = cbLine;
+ mLastBitsPerPixel = bpp;
+ mLastWidth = w;
+ mLastHeight = h;
+ mLastFlags = flags;
+ }
ULONG pixelFormat;
@@ -732,7 +940,7 @@ int Display::handleDisplayResize (unsigned uScreenId, uint32_t bpp, void *pvVRAM
*
* Note: the resize information is only accessed on EMT so no serialization is required.
*/
- LogRel (("Display::handleDisplayResize(): Warning: resize postponed.\n"));
+ LogRel(("Display::handleDisplayResize(): Warning: resize postponed.\n"));
maFramebuffers[uScreenId].pendingResize.fPending = true;
maFramebuffers[uScreenId].pendingResize.pixelFormat = pixelFormat;
@@ -746,6 +954,10 @@ int Display::handleDisplayResize (unsigned uScreenId, uint32_t bpp, void *pvVRAM
return VINF_VGA_RESIZE_IN_PROGRESS;
}
+ /* Framebuffer will be invalid during resize, make sure that it is not accessed. */
+ if (uScreenId == VBOX_VIDEO_PRIMARY_SCREEN)
+ mpDrv->pUpPort->pfnSetRenderVRAM (mpDrv->pUpPort, false);
+
int rc = callFramebufferResize (maFramebuffers[uScreenId].pFramebuffer, uScreenId,
pixelFormat, pvVRAM, bpp, cbLine, w, h);
if (rc == VINF_VGA_RESIZE_IN_PROGRESS)
@@ -810,11 +1022,17 @@ void Display::handleResizeCompletedEMT (void)
continue;
}
+ /* Inform VRDP server about the change of display parameters.
+ * Must be done before calling NotifyUpdate below.
+ */
+ LogRelFlowFunc(("Calling VRDP\n"));
+ mParent->consoleVRDPServer()->SendResize();
+
/* @todo Merge these two 'if's within one 'if (!pFBInfo->pFramebuffer.isNull())' */
if (uScreenId == VBOX_VIDEO_PRIMARY_SCREEN && !pFBInfo->pFramebuffer.isNull())
{
/* Primary framebuffer has completed the resize. Update the connector data for VGA device. */
- updateDisplayData();
+ int rc2 = updateDisplayData();
/* Check the framebuffer pixel format to setup the rendering in VGA device. */
BOOL usesGuestVRAM = FALSE;
@@ -825,7 +1043,7 @@ void Display::handleResizeCompletedEMT (void)
/* If the primary framebuffer is disabled, tell the VGA device to not to copy
* pixels from VRAM to the framebuffer.
*/
- if (pFBInfo->fDisabled)
+ if (pFBInfo->fDisabled || RT_FAILURE(rc2))
mpDrv->pUpPort->pfnSetRenderVRAM (mpDrv->pUpPort, false);
else
mpDrv->pUpPort->pfnSetRenderVRAM (mpDrv->pUpPort,
@@ -854,22 +1072,33 @@ void Display::handleResizeCompletedEMT (void)
}
LogRelFlow(("[%d]: default format %d\n", uScreenId, pFBInfo->fDefaultFormat));
-#ifdef DEBUG_sunlover
- if (!stam)
+ /* Handle the case if there are some saved visible region that needs to be
+ * applied after the resize of the framebuffer is completed
+ */
+ SaveSeamlessRectLock();
+ PRTRECT pSavedVisibleRegion = pFBInfo->mpSavedVisibleRegion;
+ uint32_t cSavedVisibleRegion = pFBInfo->mcSavedVisibleRegion;
+ pFBInfo->mpSavedVisibleRegion = NULL;
+ pFBInfo->mcSavedVisibleRegion = 0;
+ SaveSeamlessRectUnLock();
+
+ if (pSavedVisibleRegion)
{
- /* protect mpVM */
- Console::SafeVMPtr pVM (mParent);
- AssertComRC (pVM.rc());
+ handleSetVisibleRegion(cSavedVisibleRegion, pSavedVisibleRegion);
+ RTMemFree(pSavedVisibleRegion);
+ }
- STAM_REG(pVM, &StatDisplayRefresh, STAMTYPE_PROFILE, "/PROF/Display/Refresh", STAMUNIT_TICKS_PER_CALL, "Time spent in EMT for display updates.");
- stam = 1;
+#ifdef DEBUG_sunlover
+ if (!g_stam)
+ {
+ Console::SafeVMPtr ptrVM(mParent);
+ AssertComRC(ptrVM.rc());
+ STAMR3RegisterU(ptrVM.rawUVM(), &g_StatDisplayRefresh, STAMTYPE_PROFILE, STAMVISIBILITY_ALWAYS,
+ "/PROF/Display/Refresh", STAMUNIT_TICKS_PER_CALL, "Time spent in EMT for display updates.");
+ g_stam = 1;
}
#endif /* DEBUG_sunlover */
- /* Inform VRDP server about the change of display parameters. */
- LogRelFlowFunc (("Calling VRDP\n"));
- mParent->consoleVRDPServer()->SendResize();
-
#if defined(VBOX_WITH_HGCM) && defined(VBOX_WITH_CROGL)
{
BOOL is3denabled;
@@ -884,7 +1113,16 @@ void Display::handleResizeCompletedEMT (void)
VMMDev *pVMMDev = mParent->getVMMDev();
if (pVMMDev)
+ {
+#if 0
+ if (mhCrOglSvc)
+ pVMMDev->hgcmHostFastCallAsync(mhCrOglSvc, SHCRGL_HOST_FN_SCREEN_CHANGED, &parm, NULL, NULL);
+ else
+ AssertMsgFailed(("mhCrOglSvc is NULL\n"));
+#else
pVMMDev->hgcmHostCall("VBoxSharedCrOpenGL", SHCRGL_HOST_FN_SCREEN_CHANGED, SHCRGL_CPARMS_SCREEN_CHANGED, &parm);
+#endif
+ }
}
}
#endif /* VBOX_WITH_CROGL */
@@ -928,17 +1166,17 @@ unsigned mapCoordsToScreen(DISPLAYFBINFO *pInfos, unsigned cInfos, int *px, int
{
DISPLAYFBINFO *pInfo = pInfos;
unsigned uScreenId;
- LogSunlover (("mapCoordsToScreen: %d,%d %dx%d\n", *px, *py, *pw, *ph));
+ LogSunlover(("mapCoordsToScreen: %d,%d %dx%d\n", *px, *py, *pw, *ph));
for (uScreenId = 0; uScreenId < cInfos; uScreenId++, pInfo++)
{
- LogSunlover ((" [%d] %d,%d %dx%d\n", uScreenId, pInfo->xOrigin, pInfo->yOrigin, pInfo->w, pInfo->h));
+ LogSunlover((" [%d] %d,%d %dx%d\n", uScreenId, pInfo->xOrigin, pInfo->yOrigin, pInfo->w, pInfo->h));
if ( (pInfo->xOrigin <= *px && *px < pInfo->xOrigin + (int)pInfo->w)
&& (pInfo->yOrigin <= *py && *py < pInfo->yOrigin + (int)pInfo->h))
{
/* The rectangle belongs to the screen. Correct coordinates. */
*px -= pInfo->xOrigin;
*py -= pInfo->yOrigin;
- LogSunlover ((" -> %d,%d", *px, *py));
+ LogSunlover((" -> %d,%d", *px, *py));
break;
}
}
@@ -947,7 +1185,7 @@ unsigned mapCoordsToScreen(DISPLAYFBINFO *pInfos, unsigned cInfos, int *px, int
/* Map to primary screen. */
uScreenId = 0;
}
- LogSunlover ((" scr %d\n", uScreenId));
+ LogSunlover((" scr %d\n", uScreenId));
return uScreenId;
}
@@ -967,7 +1205,7 @@ void Display::handleDisplayUpdateLegacy (int x, int y, int w, int h)
unsigned uScreenId = mapCoordsToScreen(maFramebuffers, mcMonitors, &x, &y, &w, &h);
#ifdef DEBUG_sunlover
- LogFlowFunc (("%d,%d %dx%d (checked)\n", x, y, w, h));
+ LogFlowFunc(("%d,%d %dx%d (checked)\n", x, y, w, h));
#endif /* DEBUG_sunlover */
handleDisplayUpdate (uScreenId, x, y, w, h);
@@ -981,8 +1219,8 @@ void Display::handleDisplayUpdate (unsigned uScreenId, int x, int y, int w, int
*/
#ifdef DEBUG_sunlover
- LogFlowFunc (("[%d] %d,%d %dx%d (%d,%d)\n",
- uScreenId, x, y, w, h, mpDrv->IConnector.cx, mpDrv->IConnector.cy));
+ LogFlowFunc(("[%d] %d,%d %dx%d (%d,%d)\n",
+ uScreenId, x, y, w, h, mpDrv->IConnector.cx, mpDrv->IConnector.cy));
#endif /* DEBUG_sunlover */
IFramebuffer *pFramebuffer = maFramebuffers[uScreenId].pFramebuffer;
@@ -1041,7 +1279,7 @@ void Display::getFramebufferDimensions(int32_t *px1, int32_t *py1,
return;
/* If VBVA is not in use then this flag will not be set and this
* will still work as it should. */
- if (!(maFramebuffers[0].fDisabled))
+ if (!maFramebuffers[0].fDisabled)
{
x1 = (int32_t)maFramebuffers[0].xOrigin;
y1 = (int32_t)maFramebuffers[0].yOrigin;
@@ -1050,7 +1288,7 @@ void Display::getFramebufferDimensions(int32_t *px1, int32_t *py1,
}
for (unsigned i = 1; i < mcMonitors; ++i)
{
- if (!(maFramebuffers[i].fDisabled))
+ if (!maFramebuffers[i].fDisabled)
{
x1 = RT_MIN(x1, maFramebuffers[i].xOrigin);
y1 = RT_MIN(y1, maFramebuffers[i].yOrigin);
@@ -1115,6 +1353,38 @@ int Display::handleSetVisibleRegion(uint32_t cRect, PRTRECT pRect)
if (!pFBInfo->pFramebuffer.isNull())
{
+ if (pFBInfo->u32ResizeStatus != ResizeStatus_Void)
+ {
+ /* handle the case where new rectangles are received from the GA
+ * when framebuffer resizing is in progress.
+ * Just save the rectangles to be applied for later time when FB resizing is complete
+ * (from handleResizeCompletedEMT).
+ * This is done to prevent a race condition where a new rectangles are received
+ * from the GA after a resize event and framebuffer resizing is still in progress
+ * As a result the coordinates of the framebuffer are still
+ * not updated and hence there is no intersection with the new rectangles passed
+ * for the new region (THis is checked in the above if condition ). With 0 intersection,
+ * cRectVisibleRegions = 0 is returned to the GUI and if GUI has invalidated its
+ * earlier region then it draws nothihing and seamless mode doesn't display the
+ * guest desktop.
+ */
+ SaveSeamlessRectLock();
+ RTMemFree(pFBInfo->mpSavedVisibleRegion);
+
+ pFBInfo->mpSavedVisibleRegion = (RTRECT *)RTMemAlloc( RT_MAX(cRect, 1)
+ * sizeof (RTRECT));
+ if (pFBInfo->mpSavedVisibleRegion)
+ {
+ memcpy(pFBInfo->mpSavedVisibleRegion, pRect, cRect * sizeof(RTRECT));
+ pFBInfo->mcSavedVisibleRegion = cRect;
+ }
+ else
+ {
+ pFBInfo->mcSavedVisibleRegion = 0;
+ }
+ SaveSeamlessRectUnLock();
+ continue;
+ }
/* Prepare a new array of rectangles which intersect with the framebuffer.
*/
RTRECT rectFramebuffer;
@@ -1156,13 +1426,11 @@ int Display::handleSetVisibleRegion(uint32_t cRect, PRTRECT pRect)
cRectVisibleRegion++;
}
}
-
pFBInfo->pFramebuffer->SetVisibleRegion((BYTE *)pVisibleRegion, cRectVisibleRegion);
}
}
-#if defined(RT_OS_DARWIN) && defined(VBOX_WITH_HGCM) && defined(VBOX_WITH_CROGL)
- // @todo fix for multimonitor
+#if defined(VBOX_WITH_HGCM) && defined(VBOX_WITH_CROGL)
BOOL is3denabled = FALSE;
mParent->machine()->COMGETTER(Accelerate3DEnabled)(&is3denabled);
@@ -1170,15 +1438,27 @@ int Display::handleSetVisibleRegion(uint32_t cRect, PRTRECT pRect)
VMMDev *vmmDev = mParent->getVMMDev();
if (is3denabled && vmmDev)
{
- VBOXHGCMSVCPARM parms[2];
+ if (mhCrOglSvc)
+ {
+ RTRECT *pRectsCopy = (RTRECT *)RTMemAlloc( RT_MAX(cRect, 1)
+ * sizeof (RTRECT));
+ if (pRectsCopy)
+ {
+ memcpy(pRectsCopy, pRect, cRect * sizeof (RTRECT));
+
+ VBOXHGCMSVCPARM parm;
- parms[0].type = VBOX_HGCM_SVC_PARM_PTR;
- parms[0].u.pointer.addr = pRect;
- parms[0].u.pointer.size = 0; /* We don't actually care. */
- parms[1].type = VBOX_HGCM_SVC_PARM_32BIT;
- parms[1].u.uint32 = cRect;
+ parm.type = VBOX_HGCM_SVC_PARM_PTR;
+ parm.u.pointer.addr = pRectsCopy;
+ parm.u.pointer.size = cRect * sizeof (RTRECT);
- vmmDev->hgcmHostCall("VBoxSharedCrOpenGL", SHCRGL_HOST_FN_SET_VISIBLE_REGION, 2, &parms[0]);
+ vmmDev->hgcmHostFastCallAsync(mhCrOglSvc, SHCRGL_HOST_FN_SET_VISIBLE_REGION, &parm, displayCrAsyncCmdCompletion, this);
+ }
+ else
+ AssertMsgFailed(("failed to allocate rects memory\n"));
+ }
+ else
+ AssertMsgFailed(("mhCrOglSvc is NULL\n"));
}
#endif
@@ -1215,14 +1495,14 @@ static void vbvaRgnInit (VBVADIRTYREGION *prgn, DISPLAYFBINFO *paFramebuffers, u
{
DISPLAYFBINFO *pFBInfo = &prgn->paFramebuffers[uScreenId];
- memset (&pFBInfo->dirtyRect, 0, sizeof (pFBInfo->dirtyRect));
+ RT_ZERO(pFBInfo->dirtyRect);
}
}
static void vbvaRgnDirtyRect (VBVADIRTYREGION *prgn, unsigned uScreenId, VBVACMDHDR *phdr)
{
- LogSunlover (("x = %d, y = %d, w = %d, h = %d\n",
- phdr->x, phdr->y, phdr->w, phdr->h));
+ LogSunlover(("x = %d, y = %d, w = %d, h = %d\n",
+ phdr->x, phdr->y, phdr->w, phdr->h));
/*
* Here update rectangles are accumulated to form an update area.
@@ -1396,6 +1676,17 @@ void Display::vbvaUnlock(void)
RTCritSectLeave(&mVBVALock);
}
+int Display::SaveSeamlessRectLock(void)
+{
+ return RTCritSectEnter(&mSaveSeamlessRectLock);
+}
+
+void Display::SaveSeamlessRectUnLock(void)
+{
+ RTCritSectLeave(&mSaveSeamlessRectLock);
+}
+
+
/**
* @thread EMT
*/
@@ -1422,7 +1713,7 @@ int Display::videoAccelEnable (bool fEnable, VBVAMEMORY *pVbvaMemory)
* Guest enabled acceleration at will. And it has to enable
* acceleration after a mode change.
*/
- LogRelFlowFunc (("mfVideoAccelEnabled = %d, fEnable = %d, pVbvaMemory = %p\n",
+ LogRelFlowFunc(("mfVideoAccelEnabled = %d, fEnable = %d, pVbvaMemory = %p\n",
mfVideoAccelEnabled, fEnable, pVbvaMemory));
/* Strictly check parameters. Callers must not pass anything in the case. */
@@ -1439,7 +1730,7 @@ int Display::videoAccelEnable (bool fEnable, VBVAMEMORY *pVbvaMemory)
{
Assert (!mfVideoAccelEnabled);
- LogRelFlowFunc (("Machine is not yet running.\n"));
+ LogRelFlowFunc(("Machine is not yet running.\n"));
if (fEnable)
{
@@ -1507,7 +1798,7 @@ int Display::videoAccelEnable (bool fEnable, VBVAMEMORY *pVbvaMemory)
LogRel(("VBVA: Disabled.\n"));
}
- LogRelFlowFunc (("VideoAccelEnable: rc = %Rrc.\n", rc));
+ LogRelFlowFunc(("VideoAccelEnable: rc = %Rrc.\n", rc));
return rc;
}
@@ -1582,7 +1873,7 @@ static void vbvaFetchBytes (VBVAMEMORY *pVbvaMemory, uint8_t *pu8Dst, uint32_t c
{
if (cbDst >= VBVA_RING_BUFFER_SIZE)
{
- AssertMsgFailed (("cbDst = 0x%08X, ring buffer size 0x%08X", cbDst, VBVA_RING_BUFFER_SIZE));
+ AssertMsgFailed (("cbDst = 0x%08X, ring buffer size 0x%08X\n", cbDst, VBVA_RING_BUFFER_SIZE));
return;
}
@@ -1662,8 +1953,8 @@ bool Display::vbvaFetchCmd (VBVACMDHDR **ppHdr, uint32_t *pcbCmd)
uint32_t indexRecordFree = mpVbvaMemory->indexRecordFree;
#ifdef DEBUG_sunlover
- LogFlowFunc (("first = %d, free = %d\n",
- indexRecordFirst, indexRecordFree));
+ LogFlowFunc(("first = %d, free = %d\n",
+ indexRecordFirst, indexRecordFree));
#endif /* DEBUG_sunlover */
if (!vbvaVerifyRingBuffer (mpVbvaMemory))
@@ -1680,7 +1971,7 @@ bool Display::vbvaFetchCmd (VBVACMDHDR **ppHdr, uint32_t *pcbCmd)
VBVARECORD *pRecord = &mpVbvaMemory->aRecords[indexRecordFirst];
#ifdef DEBUG_sunlover
- LogFlowFunc (("cbRecord = 0x%08X\n", pRecord->cbRecord));
+ LogFlowFunc(("cbRecord = 0x%08X\n", pRecord->cbRecord));
#endif /* DEBUG_sunlover */
uint32_t cbRecord = pRecord->cbRecord & ~VBVA_F_RECORD_PARTIAL;
@@ -1691,7 +1982,7 @@ bool Display::vbvaFetchCmd (VBVACMDHDR **ppHdr, uint32_t *pcbCmd)
Assert (mpu8VbvaPartial);
- LogFlowFunc (("continue partial record mcbVbvaPartial = %d cbRecord 0x%08X, first = %d, free = %d\n",
+ LogFlowFunc(("continue partial record mcbVbvaPartial = %d cbRecord 0x%08X, first = %d, free = %d\n",
mcbVbvaPartial, pRecord->cbRecord, indexRecordFirst, indexRecordFree));
if (cbRecord > mcbVbvaPartial)
@@ -1716,7 +2007,7 @@ bool Display::vbvaFetchCmd (VBVACMDHDR **ppHdr, uint32_t *pcbCmd)
mpVbvaMemory->indexRecordFirst = (indexRecordFirst + 1) % VBVA_MAX_RECORDS;
#ifdef DEBUG_sunlover
- LogFlowFunc (("partial done ok, data = %d, free = %d\n",
+ LogFlowFunc(("partial done ok, data = %d, free = %d\n",
mpVbvaMemory->off32Data, mpVbvaMemory->off32Free));
#endif /* DEBUG_sunlover */
}
@@ -1736,7 +2027,7 @@ bool Display::vbvaFetchCmd (VBVACMDHDR **ppHdr, uint32_t *pcbCmd)
return false;
}
- LogFlowFunc (("started partial record mcbVbvaPartial = 0x%08X cbRecord 0x%08X, first = %d, free = %d\n",
+ LogFlowFunc(("started partial record mcbVbvaPartial = 0x%08X cbRecord 0x%08X, first = %d, free = %d\n",
mcbVbvaPartial, pRecord->cbRecord, indexRecordFirst, indexRecordFree));
}
@@ -1771,7 +2062,7 @@ bool Display::vbvaFetchCmd (VBVACMDHDR **ppHdr, uint32_t *pcbCmd)
if (!dst)
{
- LogRelFlowFunc (("could not allocate %d bytes from heap!!!\n", cbRecord));
+ LogRelFlowFunc(("could not allocate %d bytes from heap!!!\n", cbRecord));
mpVbvaMemory->off32Data = (mpVbvaMemory->off32Data + cbRecord) % VBVA_RING_BUFFER_SIZE;
return false;
}
@@ -1781,7 +2072,7 @@ bool Display::vbvaFetchCmd (VBVACMDHDR **ppHdr, uint32_t *pcbCmd)
*ppHdr = (VBVACMDHDR *)dst;
#ifdef DEBUG_sunlover
- LogFlowFunc (("Allocated from heap %p\n", dst));
+ LogFlowFunc(("Allocated from heap %p\n", dst));
#endif /* DEBUG_sunlover */
}
}
@@ -1792,8 +2083,8 @@ bool Display::vbvaFetchCmd (VBVACMDHDR **ppHdr, uint32_t *pcbCmd)
mpVbvaMemory->indexRecordFirst = (indexRecordFirst + 1) % VBVA_MAX_RECORDS;
#ifdef DEBUG_sunlover
- LogFlowFunc (("done ok, data = %d, free = %d\n",
- mpVbvaMemory->off32Data, mpVbvaMemory->off32Free));
+ LogFlowFunc(("done ok, data = %d, free = %d\n",
+ mpVbvaMemory->off32Data, mpVbvaMemory->off32Free));
#endif /* DEBUG_sunlover */
return true;
@@ -1818,7 +2109,7 @@ void Display::vbvaReleaseCmd (VBVACMDHDR *pHdr, int32_t cbCmd)
/* The pointer is outside. It is then an allocated copy. */
#ifdef DEBUG_sunlover
- LogFlowFunc (("Free heap %p\n", pHdr));
+ LogFlowFunc(("Free heap %p\n", pHdr));
#endif /* DEBUG_sunlover */
if ((uint8_t *)pHdr == mpu8VbvaPartial)
@@ -1855,7 +2146,7 @@ void Display::VideoAccelFlush (void)
void Display::videoAccelFlush (void)
{
#ifdef DEBUG_sunlover_2
- LogFlowFunc (("mfVideoAccelEnabled = %d\n", mfVideoAccelEnabled));
+ LogFlowFunc(("mfVideoAccelEnabled = %d\n", mfVideoAccelEnabled));
#endif /* DEBUG_sunlover_2 */
if (!mfVideoAccelEnabled)
@@ -1868,7 +2159,7 @@ void Display::videoAccelFlush (void)
Assert(mpVbvaMemory);
#ifdef DEBUG_sunlover_2
- LogFlowFunc (("indexRecordFirst = %d, indexRecordFree = %d, off32Data = %d, off32Free = %d\n",
+ LogFlowFunc(("indexRecordFirst = %d, indexRecordFree = %d, off32Data = %d, off32Free = %d\n",
mpVbvaMemory->indexRecordFirst, mpVbvaMemory->indexRecordFree, mpVbvaMemory->off32Data, mpVbvaMemory->off32Free));
#endif /* DEBUG_sunlover_2 */
@@ -1911,8 +2202,8 @@ void Display::videoAccelFlush (void)
if (cbCmd != 0)
{
#ifdef DEBUG_sunlover
- LogFlowFunc (("hdr: cbCmd = %d, x=%d, y=%d, w=%d, h=%d\n",
- cbCmd, phdr->x, phdr->y, phdr->w, phdr->h));
+ LogFlowFunc(("hdr: cbCmd = %d, x=%d, y=%d, w=%d, h=%d\n",
+ cbCmd, phdr->x, phdr->y, phdr->w, phdr->h));
#endif /* DEBUG_sunlover */
VBVACMDHDR hdrSaved = *phdr;
@@ -2024,9 +2315,10 @@ int Display::videoAccelRefreshProcess(void)
// IDisplay methods
/////////////////////////////////////////////////////////////////////////////
STDMETHODIMP Display::GetScreenResolution (ULONG aScreenId,
- ULONG *aWidth, ULONG *aHeight, ULONG *aBitsPerPixel)
+ ULONG *aWidth, ULONG *aHeight, ULONG *aBitsPerPixel,
+ LONG *aXOrigin, LONG *aYOrigin)
{
- LogRelFlowFunc (("aScreenId = %d\n", aScreenId));
+ LogRelFlowFunc(("aScreenId = %d\n", aScreenId));
AutoCaller autoCaller(this);
if (FAILED(autoCaller.rc())) return autoCaller.rc();
@@ -2036,10 +2328,12 @@ STDMETHODIMP Display::GetScreenResolution (ULONG aScreenId,
uint32_t u32Width = 0;
uint32_t u32Height = 0;
uint32_t u32BitsPerPixel = 0;
+ int32_t xOrigin = 0;
+ int32_t yOrigin = 0;
if (aScreenId == VBOX_VIDEO_PRIMARY_SCREEN)
{
- CHECK_CONSOLE_DRV (mpDrv);
+ CHECK_CONSOLE_DRV(mpDrv);
u32Width = mpDrv->IConnector.cx;
u32Height = mpDrv->IConnector.cy;
@@ -2052,6 +2346,8 @@ STDMETHODIMP Display::GetScreenResolution (ULONG aScreenId,
u32Width = pFBInfo->w;
u32Height = pFBInfo->h;
u32BitsPerPixel = pFBInfo->u16BitsPerPixel;
+ xOrigin = pFBInfo->xOrigin;
+ yOrigin = pFBInfo->yOrigin;
}
else
{
@@ -2064,33 +2360,37 @@ STDMETHODIMP Display::GetScreenResolution (ULONG aScreenId,
*aHeight = u32Height;
if (aBitsPerPixel)
*aBitsPerPixel = u32BitsPerPixel;
+ if (aXOrigin)
+ *aXOrigin = xOrigin;
+ if (aYOrigin)
+ *aYOrigin = yOrigin;
return S_OK;
}
-STDMETHODIMP Display::SetFramebuffer (ULONG aScreenId,
- IFramebuffer *aFramebuffer)
+STDMETHODIMP Display::SetFramebuffer(ULONG aScreenId, IFramebuffer *aFramebuffer)
{
- LogRelFlowFunc (("\n"));
+ LogRelFlowFunc(("\n"));
if (aFramebuffer != NULL)
CheckComArgOutPointerValid(aFramebuffer);
AutoCaller autoCaller(this);
- if (FAILED(autoCaller.rc())) return autoCaller.rc();
+ if (FAILED(autoCaller.rc()))
+ return autoCaller.rc();
AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
- Console::SafeVMPtrQuiet pVM (mParent);
- if (pVM.isOk())
+ Console::SafeVMPtrQuiet ptrVM(mParent);
+ if (ptrVM.isOk())
{
/* Must release the lock here because the changeFramebuffer will
* also obtain it. */
alock.release();
/* send request to the EMT thread */
- int vrc = VMR3ReqCallWait (pVM, VMCPUID_ANY,
- (PFNRT) changeFramebuffer, 3, this, aFramebuffer, aScreenId);
+ int vrc = VMR3ReqCallWaitU(ptrVM.rawUVM(), VMCPUID_ANY,
+ (PFNRT)changeFramebuffer, 3, this, aFramebuffer, aScreenId);
alock.acquire();
@@ -2113,7 +2413,16 @@ STDMETHODIMP Display::SetFramebuffer (ULONG aScreenId,
alock.release();
if (pVMMDev)
- vrc = pVMMDev->hgcmHostCall("VBoxSharedCrOpenGL", SHCRGL_HOST_FN_SCREEN_CHANGED, SHCRGL_CPARMS_SCREEN_CHANGED, &parm);
+ {
+#if 0
+ if (mhCrOglSvc)
+ pVMMDev->hgcmHostFastCallAsync(mhCrOglSvc, SHCRGL_HOST_FN_SCREEN_CHANGED, &parm, NULL, NULL);
+ else
+ AssertMsgFailed(("mhCrOglSvc is NULL\n"));
+#else
+ pVMMDev->hgcmHostCall("VBoxSharedCrOpenGL", SHCRGL_HOST_FN_SCREEN_CHANGED, SHCRGL_CPARMS_SCREEN_CHANGED, &parm);
+#endif
+ }
/*ComAssertRCRet (vrc, E_FAIL);*/
alock.acquire();
@@ -2131,10 +2440,10 @@ STDMETHODIMP Display::SetFramebuffer (ULONG aScreenId,
return S_OK;
}
-STDMETHODIMP Display::GetFramebuffer (ULONG aScreenId,
- IFramebuffer **aFramebuffer, LONG *aXOrigin, LONG *aYOrigin)
+STDMETHODIMP Display::GetFramebuffer(ULONG aScreenId,
+ IFramebuffer **aFramebuffer, LONG *aXOrigin, LONG *aYOrigin)
{
- LogRelFlowFunc (("aScreenId = %d\n", aScreenId));
+ LogRelFlowFunc(("aScreenId = %d\n", aScreenId));
CheckComArgOutPointerValid(aFramebuffer);
@@ -2169,13 +2478,7 @@ STDMETHODIMP Display::SetVideoModeHint(ULONG aDisplay, BOOL aEnabled,
AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
- CHECK_CONSOLE_DRV (mpDrv);
-
- /* XXX Ignore these parameters for now: */
- NOREF(aChangeOrigin);
- NOREF(aOriginX);
- NOREF(aOriginY);
- NOREF(aEnabled);
+ CHECK_CONSOLE_DRV(mpDrv);
/*
* Do some rough checks for valid input
@@ -2215,7 +2518,9 @@ STDMETHODIMP Display::SetVideoModeHint(ULONG aDisplay, BOOL aEnabled,
{
PPDMIVMMDEVPORT pVMMDevPort = pVMMDev->getVMMDevPort();
if (pVMMDevPort)
- pVMMDevPort->pfnRequestDisplayChange(pVMMDevPort, aWidth, aHeight, aBitsPerPixel, aDisplay);
+ pVMMDevPort->pfnRequestDisplayChange(pVMMDevPort, aWidth, aHeight, aBitsPerPixel,
+ aDisplay, aOriginX, aOriginY,
+ RT_BOOL(aEnabled), RT_BOOL(aChangeOrigin));
}
return S_OK;
}
@@ -2237,9 +2542,83 @@ STDMETHODIMP Display::SetSeamlessMode (BOOL enabled)
if (pVMMDevPort)
pVMMDevPort->pfnRequestSeamlessChange(pVMMDevPort, !!enabled);
}
+
+#if defined(VBOX_WITH_HGCM) && defined(VBOX_WITH_CROGL)
+ if (!enabled)
+ {
+ BOOL is3denabled = FALSE;
+
+ mParent->machine()->COMGETTER(Accelerate3DEnabled)(&is3denabled);
+
+ VMMDev *vmmDev = mParent->getVMMDev();
+ if (is3denabled && vmmDev)
+ {
+ VBOXHGCMSVCPARM parm;
+
+ parm.type = VBOX_HGCM_SVC_PARM_PTR;
+ /* NULL means disable */
+ parm.u.pointer.addr = NULL;
+ parm.u.pointer.size = 0; /* <- means null rects, NULL pRects address and 0 rects means "disable" */
+
+ if (mhCrOglSvc)
+ vmmDev->hgcmHostFastCallAsync(mhCrOglSvc, SHCRGL_HOST_FN_SET_VISIBLE_REGION, &parm, NULL, NULL);
+ else
+ AssertMsgFailed(("mhCrOglSvc is NULL\n"));
+
+ }
+ }
+#endif
return S_OK;
}
+#ifdef VBOX_WITH_CROGL
+BOOL Display::displayCheckTakeScreenshotCrOgl(Display *pDisplay, ULONG aScreenId, uint8_t *pu8Data, uint32_t u32Width, uint32_t u32Height)
+{
+ BOOL is3denabled;
+ pDisplay->mParent->machine()->COMGETTER(Accelerate3DEnabled)(&is3denabled);
+ if (is3denabled && pDisplay->mCrOglCallbacks.pfnHasData())
+ {
+ VMMDev *pVMMDev = pDisplay->mParent->getVMMDev();
+ if (pVMMDev)
+ {
+ CRVBOXHGCMTAKESCREENSHOT *pScreenshot = (CRVBOXHGCMTAKESCREENSHOT*)RTMemAlloc(sizeof (*pScreenshot));
+ if (pScreenshot)
+ {
+ /* screen id or CRSCREEN_ALL to specify all enabled */
+ pScreenshot->u32Screen = aScreenId;
+ pScreenshot->u32Width = u32Width;
+ pScreenshot->u32Height = u32Height;
+ pScreenshot->u32Pitch = u32Width * 4;
+ pScreenshot->pvBuffer = pu8Data;
+ pScreenshot->pvContext = NULL;
+ pScreenshot->pfnScreenshotBegin = NULL;
+ pScreenshot->pfnScreenshotPerform = NULL;
+ pScreenshot->pfnScreenshotEnd = NULL;
+
+ VBOXHGCMSVCPARM parm;
+
+ parm.type = VBOX_HGCM_SVC_PARM_PTR;
+ parm.u.pointer.addr = pScreenshot;
+ parm.u.pointer.size = sizeof (*pScreenshot);
+
+ int rc = pVMMDev->hgcmHostCall("VBoxSharedCrOpenGL", SHCRGL_HOST_FN_TAKE_SCREENSHOT, 1, &parm);
+
+ RTMemFree(pScreenshot);
+
+ if (RT_SUCCESS(rc))
+ return TRUE;
+ else
+ {
+ AssertMsgFailed(("failed to get screenshot data from crOgl %d\n", rc));
+ /* fall back to the non-3d mechanism */
+ }
+ }
+ }
+ }
+ return FALSE;
+}
+#endif
+
int Display::displayTakeScreenshotEMT(Display *pDisplay, ULONG aScreenId, uint8_t **ppu8Data, size_t *pcbData, uint32_t *pu32Width, uint32_t *pu32Height)
{
int rc;
@@ -2287,15 +2666,15 @@ int Display::displayTakeScreenshotEMT(Display *pDisplay, ULONG aScreenId, uint8_
uint32_t u32DstBitsPerPixel = 32;
rc = pDisplay->mpDrv->pUpPort->pfnCopyRect(pDisplay->mpDrv->pUpPort,
- width, height,
- pu8Src,
- xSrc, ySrc,
- u32SrcWidth, u32SrcHeight,
- u32SrcLineSize, u32SrcBitsPerPixel,
- pu8Dst,
- xDst, yDst,
- u32DstWidth, u32DstHeight,
- u32DstLineSize, u32DstBitsPerPixel);
+ width, height,
+ pu8Src,
+ xSrc, ySrc,
+ u32SrcWidth, u32SrcHeight,
+ u32SrcLineSize, u32SrcBitsPerPixel,
+ pu8Dst,
+ xDst, yDst,
+ u32DstWidth, u32DstHeight,
+ u32DstLineSize, u32DstBitsPerPixel);
if (RT_SUCCESS(rc))
{
*ppu8Data = pu8Data;
@@ -2306,6 +2685,14 @@ int Display::displayTakeScreenshotEMT(Display *pDisplay, ULONG aScreenId, uint8_
else
{
RTMemFree(pu8Data);
+
+ /* CopyRect can fail if VBVA was paused in VGA device, retry using the generic method. */
+ if ( rc == VERR_INVALID_STATE
+ && aScreenId == VBOX_VIDEO_PRIMARY_SCREEN)
+ {
+ rc = pDisplay->mpDrv->pUpPort->pfnTakeScreenshot(pDisplay->mpDrv->pUpPort,
+ ppu8Data, pcbData, pu32Width, pu32Height);
+ }
}
}
}
@@ -2327,7 +2714,8 @@ int Display::displayTakeScreenshotEMT(Display *pDisplay, ULONG aScreenId, uint8_
return rc;
}
-static int displayTakeScreenshot(PVM pVM, Display *pDisplay, struct DRVMAINDISPLAY *pDrv, ULONG aScreenId, BYTE *address, ULONG width, ULONG height)
+static int displayTakeScreenshot(PUVM pUVM, Display *pDisplay, struct DRVMAINDISPLAY *pDrv, ULONG aScreenId,
+ BYTE *address, ULONG width, ULONG height)
{
uint8_t *pu8Data = NULL;
size_t cbData = 0;
@@ -2335,6 +2723,11 @@ static int displayTakeScreenshot(PVM pVM, Display *pDisplay, struct DRVMAINDISPL
uint32_t cy = 0;
int vrc = VINF_SUCCESS;
+# if defined(VBOX_WITH_HGCM) && defined(VBOX_WITH_CROGL)
+ if (Display::displayCheckTakeScreenshotCrOgl(pDisplay, aScreenId, (uint8_t*)address, width, height))
+ return VINF_SUCCESS;
+#endif
+
int cRetries = 5;
while (cRetries-- > 0)
@@ -2342,8 +2735,8 @@ static int displayTakeScreenshot(PVM pVM, Display *pDisplay, struct DRVMAINDISPL
/* Note! Not sure if the priority call is such a good idea here, but
it would be nice to have an accurate screenshot for the bug
report if the VM deadlocks. */
- vrc = VMR3ReqPriorityCallWait(pVM, VMCPUID_ANY, (PFNRT)Display::displayTakeScreenshotEMT, 6,
- pDisplay, aScreenId, &pu8Data, &cbData, &cx, &cy);
+ vrc = VMR3ReqPriorityCallWaitU(pUVM, VMCPUID_ANY, (PFNRT)Display::displayTakeScreenshotEMT, 6,
+ pDisplay, aScreenId, &pu8Data, &cbData, &cx, &cy);
if (vrc != VERR_TRY_AGAIN)
{
break;
@@ -2419,10 +2812,12 @@ STDMETHODIMP Display::TakeScreenShot(ULONG aScreenId, BYTE *address, ULONG width
AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
- CHECK_CONSOLE_DRV(mpDrv);
+ if (!mpDrv)
+ return E_FAIL;
- Console::SafeVMPtr pVM(mParent);
- if (FAILED(pVM.rc())) return pVM.rc();
+ Console::SafeVMPtr ptrVM(mParent);
+ if (!ptrVM.isOk())
+ return ptrVM.rc();
HRESULT rc = S_OK;
@@ -2435,7 +2830,7 @@ STDMETHODIMP Display::TakeScreenShot(ULONG aScreenId, BYTE *address, ULONG width
*/
alock.release();
- int vrc = displayTakeScreenshot(pVM, this, mpDrv, aScreenId, address, width, height);
+ int vrc = displayTakeScreenshot(ptrVM.rawUVM(), this, mpDrv, aScreenId, address, width, height);
if (vrc == VERR_NOT_IMPLEMENTED)
rc = setError(E_NOTIMPL,
@@ -2447,7 +2842,7 @@ STDMETHODIMP Display::TakeScreenShot(ULONG aScreenId, BYTE *address, ULONG width
rc = setError(VBOX_E_IPRT_ERROR,
tr("Could not take a screenshot (%Rrc)"), vrc);
- LogRelFlowFunc(("rc=%08X\n", rc));
+ LogRelFlowFunc(("rc=%Rhrc\n", rc));
return rc;
}
@@ -2471,10 +2866,12 @@ STDMETHODIMP Display::TakeScreenShotToArray(ULONG aScreenId, ULONG width, ULONG
AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
- CHECK_CONSOLE_DRV(mpDrv);
+ if (!mpDrv)
+ return E_FAIL;
- Console::SafeVMPtr pVM(mParent);
- if (FAILED(pVM.rc())) return pVM.rc();
+ Console::SafeVMPtr ptrVM(mParent);
+ if (!ptrVM.isOk())
+ return ptrVM.rc();
HRESULT rc = S_OK;
@@ -2493,7 +2890,7 @@ STDMETHODIMP Display::TakeScreenShotToArray(ULONG aScreenId, ULONG width, ULONG
if (!pu8Data)
return E_OUTOFMEMORY;
- int vrc = displayTakeScreenshot(pVM, this, mpDrv, aScreenId, pu8Data, width, height);
+ int vrc = displayTakeScreenshot(ptrVM.rawUVM(), this, mpDrv, aScreenId, pu8Data, width, height);
if (RT_SUCCESS(vrc))
{
@@ -2523,7 +2920,7 @@ STDMETHODIMP Display::TakeScreenShotToArray(ULONG aScreenId, ULONG width, ULONG
RTMemFree(pu8Data);
- LogRelFlowFunc(("rc=%08X\n", rc));
+ LogRelFlowFunc(("rc=%Rhrc\n", rc));
return rc;
}
@@ -2549,8 +2946,9 @@ STDMETHODIMP Display::TakeScreenShotPNGToArray(ULONG aScreenId, ULONG width, ULO
CHECK_CONSOLE_DRV(mpDrv);
- Console::SafeVMPtr pVM(mParent);
- if (FAILED(pVM.rc())) return pVM.rc();
+ Console::SafeVMPtr ptrVM(mParent);
+ if (!ptrVM.isOk())
+ return ptrVM.rc();
HRESULT rc = S_OK;
@@ -2569,7 +2967,7 @@ STDMETHODIMP Display::TakeScreenShotPNGToArray(ULONG aScreenId, ULONG width, ULO
if (!pu8Data)
return E_OUTOFMEMORY;
- int vrc = displayTakeScreenshot(pVM, this, mpDrv, aScreenId, pu8Data, width, height);
+ int vrc = displayTakeScreenshot(ptrVM.rawUVM(), this, mpDrv, aScreenId, pu8Data, width, height);
if (RT_SUCCESS(vrc))
{
@@ -2605,12 +3003,136 @@ STDMETHODIMP Display::TakeScreenShotPNGToArray(ULONG aScreenId, ULONG width, ULO
RTMemFree(pu8Data);
- LogRelFlowFunc(("rc=%08X\n", rc));
+ LogRelFlowFunc(("rc=%Rhrc\n", rc));
return rc;
}
+int Display::VideoCaptureEnableScreens(ComSafeArrayIn(BOOL, aScreens))
+{
+#ifdef VBOX_WITH_VPX
+ com::SafeArray<BOOL> Screens(ComSafeArrayInArg(aScreens));
+ for (unsigned i = 0; i < Screens.size(); i++)
+ maVideoRecEnabled[i] = RT_BOOL(Screens[i]);
+ return VINF_SUCCESS;
+#else
+ return VERR_NOT_IMPLEMENTED;
+#endif
+}
-int Display::drawToScreenEMT(Display *pDisplay, ULONG aScreenId, BYTE *address, ULONG x, ULONG y, ULONG width, ULONG height)
+/**
+ * Start video capturing. Does nothing if capturing is already active.
+ */
+int Display::VideoCaptureStart()
+{
+#ifdef VBOX_WITH_VPX
+ if (VideoRecIsEnabled(mpVideoRecCtx))
+ return VINF_SUCCESS;
+
+ int rc = VideoRecContextCreate(&mpVideoRecCtx, mcMonitors);
+ if (RT_FAILURE(rc))
+ {
+ LogFlow(("Failed to create video recording context (%Rrc)!\n", rc));
+ return rc;
+ }
+ ComPtr<IMachine> pMachine = mParent->machine();
+ com::SafeArray<BOOL> screens;
+ HRESULT hrc = pMachine->COMGETTER(VideoCaptureScreens)(ComSafeArrayAsOutParam(screens));
+ AssertComRCReturn(hrc, VERR_COM_UNEXPECTED);
+ for (unsigned i = 0; i < RT_ELEMENTS(maVideoRecEnabled); i++)
+ maVideoRecEnabled[i] = i < screens.size() && screens[i];
+ ULONG ulWidth;
+ hrc = pMachine->COMGETTER(VideoCaptureWidth)(&ulWidth);
+ AssertComRCReturn(hrc, VERR_COM_UNEXPECTED);
+ ULONG ulHeight;
+ hrc = pMachine->COMGETTER(VideoCaptureHeight)(&ulHeight);
+ AssertComRCReturn(hrc, VERR_COM_UNEXPECTED);
+ ULONG ulRate;
+ hrc = pMachine->COMGETTER(VideoCaptureRate)(&ulRate);
+ AssertComRCReturn(hrc, VERR_COM_UNEXPECTED);
+ ULONG ulFPS;
+ hrc = pMachine->COMGETTER(VideoCaptureFPS)(&ulFPS);
+ AssertComRCReturn(hrc, VERR_COM_UNEXPECTED);
+ BSTR strFile;
+ hrc = pMachine->COMGETTER(VideoCaptureFile)(&strFile);
+ AssertComRCReturn(hrc, VERR_COM_UNEXPECTED);
+ RTTIMESPEC ts;
+ RTTimeNow(&ts);
+ RTTIME time;
+ RTTimeExplode(&time, &ts);
+ for (unsigned uScreen = 0; uScreen < mcMonitors; uScreen++)
+ {
+ char *pszAbsPath = RTPathAbsDup(com::Utf8Str(strFile).c_str());
+ char *pszExt = RTPathExt(pszAbsPath);
+ if (pszExt)
+ pszExt = RTStrDup(pszExt);
+ RTPathStripExt(pszAbsPath);
+ if (!pszAbsPath)
+ rc = VERR_INVALID_PARAMETER;
+ if (!pszExt)
+ pszExt = RTStrDup(".webm");
+ char *pszName = NULL;
+ if (RT_SUCCESS(rc))
+ {
+ if (mcMonitors > 1)
+ rc = RTStrAPrintf(&pszName, "%s-%u%s", pszAbsPath, uScreen+1, pszExt);
+ else
+ rc = RTStrAPrintf(&pszName, "%s%s", pszAbsPath, pszExt);
+ }
+ if (RT_SUCCESS(rc))
+ {
+ rc = VideoRecStrmInit(mpVideoRecCtx, uScreen,
+ pszName, ulWidth, ulHeight, ulRate, ulFPS);
+ if (rc == VERR_ALREADY_EXISTS)
+ {
+ RTStrFree(pszName);
+ pszName = NULL;
+
+ if (mcMonitors > 1)
+ rc = RTStrAPrintf(&pszName, "%s-%04d-%02u-%02uT%02u-%02u-%02u-%09uZ-%u%s",
+ pszAbsPath, time.i32Year, time.u8Month, time.u8MonthDay,
+ time.u8Hour, time.u8Minute, time.u8Second, time.u32Nanosecond,
+ uScreen+1, pszExt);
+ else
+ rc = RTStrAPrintf(&pszName, "%s-%04d-%02u-%02uT%02u-%02u-%02u-%09uZ%s",
+ pszAbsPath, time.i32Year, time.u8Month, time.u8MonthDay,
+ time.u8Hour, time.u8Minute, time.u8Second, time.u32Nanosecond,
+ pszExt);
+ if (RT_SUCCESS(rc))
+ rc = VideoRecStrmInit(mpVideoRecCtx, uScreen,
+ pszName, ulWidth, ulHeight, ulRate, ulFPS);
+ }
+ }
+
+ if (RT_SUCCESS(rc))
+ LogRel(("WebM/VP8 video recording screen #%u with %ux%u @ %u kbps, %u fps to '%s' enabled.\n",
+ uScreen, ulWidth, ulHeight, ulRate, ulFPS, pszName));
+ else
+ LogRel(("Failed to initialize video recording context #%u (%Rrc)!\n", uScreen, rc));
+ RTStrFree(pszName);
+ RTStrFree(pszExt);
+ RTStrFree(pszAbsPath);
+ }
+ return rc;
+#else
+ return VERR_NOT_IMPLEMENTED;
+#endif
+}
+
+/**
+ * Stop video capturing. Does nothing if video capturing is not active.
+ */
+void Display::VideoCaptureStop()
+{
+#ifdef VBOX_WITH_VPX
+ if (VideoRecIsEnabled(mpVideoRecCtx))
+ LogRel(("WebM/VP8 video recording stopped.\n"));
+ VideoRecContextClose(mpVideoRecCtx);
+ mpVideoRecCtx = NULL;
+#endif
+}
+
+int Display::drawToScreenEMT(Display *pDisplay, ULONG aScreenId, BYTE *address,
+ ULONG x, ULONG y, ULONG width, ULONG height)
{
int rc = VINF_SUCCESS;
pDisplay->vbvaLock();
@@ -2661,7 +3183,7 @@ int Display::drawToScreenEMT(Display *pDisplay, ULONG aScreenId, BYTE *address,
* it to update. And for default format, render the guest VRAM to framebuffer.
*/
if ( pFBInfo->fDefaultFormat
- && !(pFBInfo->fDisabled))
+ && !pFBInfo->fDisabled)
{
address = NULL;
HRESULT hrc = pFBInfo->pFramebuffer->COMGETTER(Address) (&address);
@@ -2706,15 +3228,16 @@ int Display::drawToScreenEMT(Display *pDisplay, ULONG aScreenId, BYTE *address,
rc = VERR_INVALID_PARAMETER;
}
- if (RT_SUCCESS(rc) && pDisplay->maFramebuffers[aScreenId].u32ResizeStatus == ResizeStatus_Void)
+ if ( RT_SUCCESS(rc)
+ && pDisplay->maFramebuffers[aScreenId].u32ResizeStatus == ResizeStatus_Void)
pDisplay->mParent->consoleVRDPServer()->SendUpdateBitmap(aScreenId, x, y, width, height);
pDisplay->vbvaUnlock();
return rc;
}
-STDMETHODIMP Display::DrawToScreen (ULONG aScreenId, BYTE *address, ULONG x, ULONG y,
- ULONG width, ULONG height)
+STDMETHODIMP Display::DrawToScreen(ULONG aScreenId, BYTE *address,
+ ULONG x, ULONG y, ULONG width, ULONG height)
{
/// @todo (r=dmik) this function may take too long to complete if the VM
// is doing something like saving state right now. Which, in case if it
@@ -2722,7 +3245,7 @@ STDMETHODIMP Display::DrawToScreen (ULONG aScreenId, BYTE *address, ULONG x, ULO
// check the machine state here (by enclosing the check and VMRequCall
// within the Console lock to make it atomic).
- LogRelFlowFunc (("address=%p, x=%d, y=%d, width=%d, height=%d\n",
+ LogRelFlowFunc(("address=%p, x=%d, y=%d, width=%d, height=%d\n",
(void *)address, x, y, width, height));
CheckComArgNotNull(address);
@@ -2734,10 +3257,11 @@ STDMETHODIMP Display::DrawToScreen (ULONG aScreenId, BYTE *address, ULONG x, ULO
AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
- CHECK_CONSOLE_DRV (mpDrv);
+ CHECK_CONSOLE_DRV(mpDrv);
- Console::SafeVMPtr pVM(mParent);
- if (FAILED(pVM.rc())) return pVM.rc();
+ Console::SafeVMPtr ptrVM(mParent);
+ if (!ptrVM.isOk())
+ return ptrVM.rc();
/* Release lock because the call scheduled on EMT may also try to take it. */
alock.release();
@@ -2746,8 +3270,8 @@ STDMETHODIMP Display::DrawToScreen (ULONG aScreenId, BYTE *address, ULONG x, ULO
* Again we're lazy and make the graphics device do all the
* dirty conversion work.
*/
- int rcVBox = VMR3ReqCallWait(pVM, VMCPUID_ANY, (PFNRT)Display::drawToScreenEMT, 7,
- this, aScreenId, address, x, y, width, height);
+ int rcVBox = VMR3ReqCallWaitU(ptrVM.rawUVM(), VMCPUID_ANY, (PFNRT)Display::drawToScreenEMT, 7,
+ this, aScreenId, address, x, y, width, height);
/*
* If the function returns not supported, we'll have to do all the
@@ -2769,15 +3293,15 @@ STDMETHODIMP Display::DrawToScreen (ULONG aScreenId, BYTE *address, ULONG x, ULO
// handleDisplayUpdate (x, y, width, height);
// }
- LogRelFlowFunc (("rc=%08X\n", rc));
+ LogRelFlowFunc(("rc=%Rhrc\n", rc));
return rc;
}
-void Display::InvalidateAndUpdateEMT(Display *pDisplay)
+void Display::InvalidateAndUpdateEMT(Display *pDisplay, unsigned uId, bool fUpdateAll)
{
pDisplay->vbvaLock();
unsigned uScreenId;
- for (uScreenId = 0; uScreenId < pDisplay->mcMonitors; uScreenId++)
+ for (uScreenId = (fUpdateAll ? 0 : uId); uScreenId < pDisplay->mcMonitors; uScreenId++)
{
DISPLAYFBINFO *pFBInfo = &pDisplay->maFramebuffers[uScreenId];
@@ -2788,7 +3312,8 @@ void Display::InvalidateAndUpdateEMT(Display *pDisplay)
else
{
if ( !pFBInfo->pFramebuffer.isNull()
- && !(pFBInfo->fDisabled))
+ && !pFBInfo->fDisabled
+ && pFBInfo->u32ResizeStatus == ResizeStatus_Void)
{
/* Render complete VRAM screen to the framebuffer.
* When framebuffer uses VRAM directly, just notify it to update.
@@ -2796,6 +3321,10 @@ void Display::InvalidateAndUpdateEMT(Display *pDisplay)
if (pFBInfo->fDefaultFormat)
{
BYTE *address = NULL;
+ ULONG uWidth = 0;
+ ULONG uHeight = 0;
+ pFBInfo->pFramebuffer->COMGETTER(Width) (&uWidth);
+ pFBInfo->pFramebuffer->COMGETTER(Height) (&uHeight);
HRESULT hrc = pFBInfo->pFramebuffer->COMGETTER(Address) (&address);
if (SUCCEEDED(hrc) && address != NULL)
{
@@ -2819,22 +3348,32 @@ void Display::InvalidateAndUpdateEMT(Display *pDisplay)
uint32_t u32DstLineSize = u32DstWidth * 4;
uint32_t u32DstBitsPerPixel = 32;
- pDisplay->mpDrv->pUpPort->pfnCopyRect(pDisplay->mpDrv->pUpPort,
- width, height,
- pu8Src,
- xSrc, ySrc,
- u32SrcWidth, u32SrcHeight,
- u32SrcLineSize, u32SrcBitsPerPixel,
- pu8Dst,
- xDst, yDst,
- u32DstWidth, u32DstHeight,
- u32DstLineSize, u32DstBitsPerPixel);
+ /* if uWidth != pFBInfo->w and uHeight != pFBInfo->h
+ * implies resize of Framebuffer is in progress and
+ * copyrect should not be called.
+ */
+ if (uWidth == pFBInfo->w && uHeight == pFBInfo->h)
+ {
+
+ pDisplay->mpDrv->pUpPort->pfnCopyRect(pDisplay->mpDrv->pUpPort,
+ width, height,
+ pu8Src,
+ xSrc, ySrc,
+ u32SrcWidth, u32SrcHeight,
+ u32SrcLineSize, u32SrcBitsPerPixel,
+ pu8Dst,
+ xDst, yDst,
+ u32DstWidth, u32DstHeight,
+ u32DstLineSize, u32DstBitsPerPixel);
+ }
}
}
pDisplay->handleDisplayUpdate (uScreenId, 0, 0, pFBInfo->w, pFBInfo->h);
}
}
+ if (!fUpdateAll)
+ break;
}
pDisplay->vbvaUnlock();
}
@@ -2854,28 +3393,29 @@ STDMETHODIMP Display::InvalidateAndUpdate()
AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
- CHECK_CONSOLE_DRV (mpDrv);
+ CHECK_CONSOLE_DRV(mpDrv);
- Console::SafeVMPtr pVM(mParent);
- if (FAILED(pVM.rc())) return pVM.rc();
+ Console::SafeVMPtr ptrVM(mParent);
+ if (!ptrVM.isOk())
+ return ptrVM.rc();
HRESULT rc = S_OK;
- LogRelFlowFunc (("Sending DPYUPDATE request\n"));
+ LogRelFlowFunc(("Sending DPYUPDATE request\n"));
/* Have to release the lock when calling EMT. */
alock.release();
/* pdm.h says that this has to be called from the EMT thread */
- int rcVBox = VMR3ReqCallVoidWait(pVM, VMCPUID_ANY, (PFNRT)Display::InvalidateAndUpdateEMT,
- 1, this);
+ int rcVBox = VMR3ReqCallVoidWaitU(ptrVM.rawUVM(), VMCPUID_ANY, (PFNRT)Display::InvalidateAndUpdateEMT,
+ 3, this, 0, true);
alock.acquire();
if (RT_FAILURE(rcVBox))
rc = setError(VBOX_E_IPRT_ERROR,
tr("Could not invalidate and update the screen (%Rrc)"), rcVBox);
- LogRelFlowFunc (("rc=%08X\n", rc));
+ LogRelFlowFunc(("rc=%Rhrc\n", rc));
return rc;
}
@@ -2887,7 +3427,7 @@ STDMETHODIMP Display::InvalidateAndUpdate()
*/
STDMETHODIMP Display::ResizeCompleted(ULONG aScreenId)
{
- LogRelFlowFunc (("\n"));
+ LogRelFlowFunc(("\n"));
/// @todo (dmik) can we AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS); here?
// This will require general code review and may add some details.
@@ -2926,33 +3466,33 @@ STDMETHODIMP Display::CompleteVHWACommand(BYTE *pCommand)
STDMETHODIMP Display::ViewportChanged(ULONG aScreenId, ULONG x, ULONG y, ULONG width, ULONG height)
{
#if defined(VBOX_WITH_HGCM) && defined(VBOX_WITH_CROGL)
+
+ if (mcMonitors <= aScreenId)
+ {
+ AssertMsgFailed(("invalid screen id\n"));
+ return E_INVALIDARG;
+ }
+
BOOL is3denabled;
mParent->machine()->COMGETTER(Accelerate3DEnabled)(&is3denabled);
if (is3denabled)
{
- VBOXHGCMSVCPARM aParms[5];
-
- aParms[0].type = VBOX_HGCM_SVC_PARM_32BIT;
- aParms[0].u.uint32 = aScreenId;
-
- aParms[1].type = VBOX_HGCM_SVC_PARM_32BIT;
- aParms[1].u.uint32 = x;
-
- aParms[2].type = VBOX_HGCM_SVC_PARM_32BIT;
- aParms[2].u.uint32 = y;
-
-
- aParms[3].type = VBOX_HGCM_SVC_PARM_32BIT;
- aParms[3].u.uint32 = width;
-
- aParms[4].type = VBOX_HGCM_SVC_PARM_32BIT;
- aParms[4].u.uint32 = height;
-
VMMDev *pVMMDev = mParent->getVMMDev();
if (pVMMDev)
- pVMMDev->hgcmHostCall("VBoxSharedCrOpenGL", SHCRGL_HOST_FN_VIEWPORT_CHANGED, SHCRGL_CPARMS_VIEWPORT_CHANGED, aParms);
+ {
+ crViewportNotify(pVMMDev, aScreenId, x, y, width, height);
+ }
+ else
+ {
+ DISPLAYFBINFO *pFb = &maFramebuffers[aScreenId];
+ pFb->pendingViewportInfo.fPending = true;
+ pFb->pendingViewportInfo.x = x;
+ pFb->pendingViewportInfo.y = y;
+ pFb->pendingViewportInfo.width = width;
+ pFb->pendingViewportInfo.height = height;
+ }
}
#endif /* VBOX_WITH_CROGL && VBOX_WITH_HGCM */
return S_OK;
@@ -2966,15 +3506,15 @@ STDMETHODIMP Display::ViewportChanged(ULONG aScreenId, ULONG x, ULONG y, ULONG w
*
* @thread EMT
*/
-void Display::updateDisplayData(void)
+int Display::updateDisplayData(void)
{
- LogRelFlowFunc (("\n"));
+ LogRelFlowFunc(("\n"));
/* the driver might not have been constructed yet */
if (!mpDrv)
- return;
+ return VINF_SUCCESS;
-#if DEBUG
+#ifdef VBOX_STRICT
/*
* Sanity check. Note that this method may be called on EMT after Console
* has started the power down procedure (but before our #drvDestruct() is
@@ -2983,9 +3523,12 @@ void Display::updateDisplayData(void)
* build to save some ms (necessary to construct SafeVMPtrQuiet) in this
* time-critical method.
*/
- Console::SafeVMPtrQuiet pVM (mParent);
- if (pVM.isOk())
- VM_ASSERT_EMT (pVM.raw());
+ Console::SafeVMPtrQuiet ptrVM(mParent);
+ if (ptrVM.isOk())
+ {
+ PVM pVM = VMR3GetVM(ptrVM.rawUVM());
+ Assert(VM_IS_EMT(pVM));
+ }
#endif
/* The method is only relevant to the primary framebuffer. */
@@ -3010,6 +3553,14 @@ void Display::updateDisplayData(void)
rc = pFramebuffer->COMGETTER(Height) (&height);
AssertComRC (rc);
+ if ( (width != mLastWidth && mLastWidth != 0)
+ || (height != mLastHeight && mLastHeight != 0))
+ {
+ LogRel(("updateDisplayData: size mismatch w %d(%d) h %d(%d)\n",
+ width, mLastWidth, height, mLastHeight));
+ return VERR_INVALID_STATE;
+ }
+
mpDrv->IConnector.pu8Data = (uint8_t *) address;
mpDrv->IConnector.cbScanline = bytesPerLine;
mpDrv->IConnector.cBits = bitsPerPixel;
@@ -3025,8 +3576,57 @@ void Display::updateDisplayData(void)
mpDrv->IConnector.cx = 0;
mpDrv->IConnector.cy = 0;
}
- LogRelFlowFunc (("leave\n"));
+ LogRelFlowFunc(("leave\n"));
+ return VINF_SUCCESS;
+}
+
+#ifdef VBOX_WITH_CROGL
+void Display::crViewportNotify(VMMDev *pVMMDev, ULONG aScreenId, ULONG x, ULONG y, ULONG width, ULONG height)
+{
+#if 0
+ VBOXHGCMSVCPARM parm;
+
+ CRVBOXHGCMVIEWPORT *pViewportInfo = (CRVBOXHGCMVIEWPORT*)RTMemAlloc(sizeof (*pViewportInfo));
+ if(!pViewportInfo)
+ {
+ AssertMsgFailed(("RTMemAlloc failed!\n"));
+ return;
+ }
+
+ pViewportInfo->u32Screen = aScreenId;
+ pViewportInfo->x = x;
+ pViewportInfo->y = y;
+ pViewportInfo->width = width;
+ pViewportInfo->height = height;
+
+ parm.type = VBOX_HGCM_SVC_PARM_PTR;
+ parm.u.pointer.addr = pViewportInfo;
+ parm.u.pointer.size = sizeof (*pViewportInfo);
+
+ pVMMDev->hgcmHostFastCallAsync(mhCrOglSvc, SHCRGL_HOST_FN_VIEWPORT_CHANGED2, &parm, displayCrAsyncCmdCompletion, this);
+#else
+ VBOXHGCMSVCPARM aParms[5];
+
+ aParms[0].type = VBOX_HGCM_SVC_PARM_32BIT;
+ aParms[0].u.uint32 = aScreenId;
+
+ aParms[1].type = VBOX_HGCM_SVC_PARM_32BIT;
+ aParms[1].u.uint32 = x;
+
+ aParms[2].type = VBOX_HGCM_SVC_PARM_32BIT;
+ aParms[2].u.uint32 = y;
+
+
+ aParms[3].type = VBOX_HGCM_SVC_PARM_32BIT;
+ aParms[3].u.uint32 = width;
+
+ aParms[4].type = VBOX_HGCM_SVC_PARM_32BIT;
+ aParms[4].u.uint32 = height;
+
+ pVMMDev->hgcmHostCall("VBoxSharedCrOpenGL", SHCRGL_HOST_FN_VIEWPORT_CHANGED, SHCRGL_CPARMS_VIEWPORT_CHANGED, aParms);
+#endif
}
+#endif
#ifdef VBOX_WITH_CRHGSMI
void Display::setupCrHgsmiData(void)
@@ -3041,8 +3641,8 @@ void Display::setupCrHgsmiData(void)
{
Assert(mhCrOglSvc);
/* setup command completion callback */
- VBOXVDMACMD_CHROMIUM_CTL_CRHGSMI_SETUP_COMPLETION Completion;
- Completion.Hdr.enmType = VBOXVDMACMD_CHROMIUM_CTL_TYPE_CRHGSMI_SETUP_COMPLETION;
+ VBOXVDMACMD_CHROMIUM_CTL_CRHGSMI_SETUP_MAINCB Completion;
+ Completion.Hdr.enmType = VBOXVDMACMD_CHROMIUM_CTL_TYPE_CRHGSMI_SETUP_MAINCB;
Completion.Hdr.cbCmd = sizeof (Completion);
Completion.hCompletion = mpDrv->pVBVACallbacks;
Completion.pfnCompletion = mpDrv->pVBVACallbacks->pfnCrHgsmiCommandCompleteAsync;
@@ -3054,7 +3654,23 @@ void Display::setupCrHgsmiData(void)
rc = pVMMDev->hgcmHostCall("VBoxSharedCrOpenGL", SHCRGL_HOST_FN_CRHGSMI_CTL, 1, &parm);
if (RT_SUCCESS(rc))
+ {
+ ULONG ul;
+
+ for (ul = 0; ul < mcMonitors; ul++)
+ {
+ DISPLAYFBINFO *pFb = &maFramebuffers[ul];
+ if (!pFb->pendingViewportInfo.fPending)
+ continue;
+
+ crViewportNotify(pVMMDev, ul, pFb->pendingViewportInfo.x, pFb->pendingViewportInfo.y, pFb->pendingViewportInfo.width, pFb->pendingViewportInfo.height);
+ pFb->pendingViewportInfo.fPending = false;
+ }
+
+ mCrOglCallbacks = Completion.MainInterface;
+
return;
+ }
AssertMsgFailed(("VBOXVDMACMD_CHROMIUM_CTL_TYPE_CRHGSMI_SETUP_COMPLETION failed rc %d", rc));
}
@@ -3079,7 +3695,7 @@ void Display::destructCrHgsmiData(void)
DECLCALLBACK(int) Display::changeFramebuffer (Display *that, IFramebuffer *aFB,
unsigned uScreenId)
{
- LogRelFlowFunc (("uScreenId = %d\n", uScreenId));
+ LogRelFlowFunc(("uScreenId = %d\n", uScreenId));
AssertReturn(that, VERR_INVALID_PARAMETER);
AssertReturn(uScreenId < that->mcMonitors, VERR_INVALID_PARAMETER);
@@ -3137,7 +3753,7 @@ DECLCALLBACK(int) Display::changeFramebuffer (Display *that, IFramebuffer *aFB,
}
}
- LogRelFlowFunc (("leave\n"));
+ LogRelFlowFunc(("leave\n"));
return VINF_SUCCESS;
}
@@ -3151,7 +3767,7 @@ DECLCALLBACK(int) Display::displayResizeCallback(PPDMIDISPLAYCONNECTOR pInterfac
{
PDRVMAINDISPLAY pDrv = PDMIDISPLAYCONNECTOR_2_MAINDISPLAY(pInterface);
- LogRelFlowFunc (("bpp %d, pvVRAM %p, cbLine %d, cx %d, cy %d\n",
+ LogRelFlowFunc(("bpp %d, pvVRAM %p, cbLine %d, cx %d, cy %d\n",
bpp, pvVRAM, cbLine, cx, cy));
return pDrv->pDisplay->handleDisplayResize(VBOX_VIDEO_PRIMARY_SCREEN, bpp, pvVRAM, cbLine, cx, cy, VBVA_SCREEN_F_ACTIVE);
@@ -3168,8 +3784,8 @@ DECLCALLBACK(void) Display::displayUpdateCallback(PPDMIDISPLAYCONNECTOR pInterfa
PDRVMAINDISPLAY pDrv = PDMIDISPLAYCONNECTOR_2_MAINDISPLAY(pInterface);
#ifdef DEBUG_sunlover
- LogFlowFunc (("mfVideoAccelEnabled = %d, %d,%d %dx%d\n",
- pDrv->pDisplay->mfVideoAccelEnabled, x, y, cx, cy));
+ LogFlowFunc(("mfVideoAccelEnabled = %d, %d,%d %dx%d\n",
+ pDrv->pDisplay->mfVideoAccelEnabled, x, y, cx, cy));
#endif /* DEBUG_sunlover */
/* This call does update regardless of VBVA status.
@@ -3184,25 +3800,26 @@ DECLCALLBACK(void) Display::displayUpdateCallback(PPDMIDISPLAYCONNECTOR pInterfa
* Periodic display refresh callback.
*
* @see PDMIDISPLAYCONNECTOR::pfnRefresh
+ * @thread EMT
*/
DECLCALLBACK(void) Display::displayRefreshCallback(PPDMIDISPLAYCONNECTOR pInterface)
{
PDRVMAINDISPLAY pDrv = PDMIDISPLAYCONNECTOR_2_MAINDISPLAY(pInterface);
#ifdef DEBUG_sunlover
- STAM_PROFILE_START(&StatDisplayRefresh, a);
+ STAM_PROFILE_START(&g_StatDisplayRefresh, a);
#endif /* DEBUG_sunlover */
#ifdef DEBUG_sunlover_2
- LogFlowFunc (("pDrv->pDisplay->mfVideoAccelEnabled = %d\n",
- pDrv->pDisplay->mfVideoAccelEnabled));
+ LogFlowFunc(("pDrv->pDisplay->mfVideoAccelEnabled = %d\n",
+ pDrv->pDisplay->mfVideoAccelEnabled));
#endif /* DEBUG_sunlover_2 */
Display *pDisplay = pDrv->pDisplay;
bool fNoUpdate = false; /* Do not update the display if any of the framebuffers is being resized. */
unsigned uScreenId;
- LogFlow(("DisplayRefreshCallback\n"));
+ Log2(("DisplayRefreshCallback\n"));
for (uScreenId = 0; uScreenId < pDisplay->mcMonitors; uScreenId++)
{
DISPLAYFBINFO *pFBInfo = &pDisplay->maFramebuffers[uScreenId];
@@ -3214,7 +3831,7 @@ DECLCALLBACK(void) Display::displayRefreshCallback(PPDMIDISPLAYCONNECTOR pInterf
if (u32ResizeStatus == ResizeStatus_UpdateDisplayData)
{
- LogRelFlowFunc (("ResizeStatus_UpdateDisplayData %d\n", uScreenId));
+ LogRelFlowFunc(("ResizeStatus_UpdateDisplayData %d\n", uScreenId));
fNoUpdate = true; /* Always set it here, because pfnUpdateDisplayAll can cause a new resize. */
/* The framebuffer was resized and display data need to be updated. */
pDisplay->handleResizeCompletedEMT ();
@@ -3226,12 +3843,12 @@ DECLCALLBACK(void) Display::displayRefreshCallback(PPDMIDISPLAYCONNECTOR pInterf
/* Continue with normal processing because the status here is ResizeStatus_Void.
* Repaint all displays because VM continued to run during the framebuffer resize.
*/
- pDisplay->InvalidateAndUpdateEMT(pDisplay);
+ pDisplay->InvalidateAndUpdateEMT(pDisplay, uScreenId, false);
}
else if (u32ResizeStatus == ResizeStatus_InProgress)
{
/* The framebuffer is being resized. Do not call the VGA device back. Immediately return. */
- LogRelFlowFunc (("ResizeStatus_InProcess\n"));
+ LogRelFlowFunc(("ResizeStatus_InProcess\n"));
fNoUpdate = true;
continue;
}
@@ -3275,72 +3892,94 @@ DECLCALLBACK(void) Display::displayRefreshCallback(PPDMIDISPLAYCONNECTOR pInterf
}
#ifdef VBOX_WITH_VPX
- if (VideoRecIsEnabled(pDisplay->mpVideoRecContext))
- {
- uint32_t u32VideoRecImgFormat = VPX_IMG_FMT_NONE;
- ULONG ulGuestHeight = 0;
- ULONG ulGuestWidth = 0;
- ULONG ulBitsPerPixel;
- int rc;
- DISPLAYFBINFO *pFBInfo = &pDisplay->maFramebuffers[VBOX_VIDEO_PRIMARY_SCREEN];
-
- if ( !pFBInfo->pFramebuffer.isNull()
- && !(pFBInfo->fDisabled)
- && pFBInfo->u32ResizeStatus == ResizeStatus_Void)
- {
- if (pFBInfo->fVBVAEnabled && pFBInfo->pu8FramebufferVRAM)
- {
- rc = VideoRecCopyToIntBuffer(pDisplay->mpVideoRecContext, 0, 0,
- FramebufferPixelFormat_FOURCC_RGB, pFBInfo->u16BitsPerPixel,
- pFBInfo->u32LineSize, pFBInfo->w, pFBInfo->h,
- pFBInfo->pu8FramebufferVRAM);
- ulGuestWidth = pFBInfo->w;
- ulGuestHeight = pFBInfo->h;
- ulBitsPerPixel = pFBInfo->u16BitsPerPixel;
- }
- else
+ if (VideoRecIsEnabled(pDisplay->mpVideoRecCtx))
+ {
+ do {
+# if defined(VBOX_WITH_HGCM) && defined(VBOX_WITH_CROGL)
+ BOOL is3denabled;
+ pDisplay->mParent->machine()->COMGETTER(Accelerate3DEnabled)(&is3denabled);
+ if (is3denabled)
{
- rc = VideoRecCopyToIntBuffer(pDisplay->mpVideoRecContext, 0, 0,
- FramebufferPixelFormat_FOURCC_RGB, pDrv->IConnector.cBits,
- pDrv->IConnector.cbScanline, pDrv->IConnector.cx,
- pDrv->IConnector.cy, pDrv->IConnector.pu8Data);
- ulGuestWidth = pDrv->IConnector.cx;
- ulGuestHeight = pDrv->IConnector.cy;
- ulBitsPerPixel = pDrv->IConnector.cBits;
- }
+ if (ASMAtomicCmpXchgU32(&pDisplay->mfCrOglVideoRecState, CRVREC_STATE_SUBMITTED, CRVREC_STATE_IDLE))
+ {
+ if (pDisplay->mCrOglCallbacks.pfnHasData())
+ {
+ /* submit */
+
+ VBOXHGCMSVCPARM parm;
+
+ parm.type = VBOX_HGCM_SVC_PARM_PTR;
+ parm.u.pointer.addr = &pDisplay->mCrOglScreenshotData;
+ parm.u.pointer.size = sizeof (pDisplay->mCrOglScreenshotData);
+
+ VMMDev *pVMMDev = pDisplay->mParent->getVMMDev();
+ if (pVMMDev)
+ {
+ int rc = pVMMDev->hgcmHostFastCallAsync(pDisplay->mhCrOglSvc, SHCRGL_HOST_FN_TAKE_SCREENSHOT, &parm, displayVRecCompletion, pDisplay);
+ if (RT_SUCCESS(rc))
+ break;
+ else
+ AssertMsgFailed(("hgcmHostFastCallAsync failed %f\n", rc));
+ }
+ else
+ AssertMsgFailed(("no VMMDev\n"));
+ }
- switch (ulBitsPerPixel)
- {
- case 32:
- u32VideoRecImgFormat = VPX_IMG_FMT_RGB32;
- Log2(("FFmpeg::RequestResize: setting ffmpeg pixel format to VPX_IMG_FMT_RGB32\n"));
- break;
- case 24:
- u32VideoRecImgFormat = VPX_IMG_FMT_RGB24;
- Log2(("FFmpeg::RequestResize: setting ffmpeg pixel format to VPX_IMG_FMT_RGB24\n"));
- break;
- case 16:
- u32VideoRecImgFormat = VPX_IMG_FMT_RGB565;
- Log2(("FFmpeg::RequestResize: setting ffmpeg pixel format to VPX_IMG_FMT_RGB565\n"));
- break;
- default:
- Log2(("No Proper Format detected\n"));
+ /* no 3D data available, or error has occured,
+ * go the straight way */
+ ASMAtomicWriteU32(&pDisplay->mfCrOglVideoRecState, CRVREC_STATE_IDLE);
+ }
+ else
+ {
+ /* record request is still in progress, don't do anything */
break;
+ }
}
+# endif /* VBOX_WITH_HGCM && VBOX_WITH_CROGL */
- /* Just return in case of failure without any assertion */
- if( RT_SUCCESS(rc))
- if (RT_SUCCESS(VideoRecDoRGBToYUV(pDisplay->mpVideoRecContext, u32VideoRecImgFormat)))
- VideoRecEncodeAndWrite(pDisplay->mpVideoRecContext, ulGuestWidth, ulGuestHeight);
- }
+ uint64_t u64Now = RTTimeProgramMilliTS();
+ for (uScreenId = 0; uScreenId < pDisplay->mcMonitors; uScreenId++)
+ {
+ if (!pDisplay->maVideoRecEnabled[uScreenId])
+ continue;
+
+ DISPLAYFBINFO *pFBInfo = &pDisplay->maFramebuffers[uScreenId];
+
+ if ( !pFBInfo->pFramebuffer.isNull()
+ && !pFBInfo->fDisabled
+ && pFBInfo->u32ResizeStatus == ResizeStatus_Void)
+ {
+ int rc;
+ if ( pFBInfo->fVBVAEnabled
+ && pFBInfo->pu8FramebufferVRAM)
+ {
+ rc = VideoRecCopyToIntBuf(pDisplay->mpVideoRecCtx, uScreenId, 0, 0,
+ FramebufferPixelFormat_FOURCC_RGB,
+ pFBInfo->u16BitsPerPixel,
+ pFBInfo->u32LineSize, pFBInfo->w, pFBInfo->h,
+ pFBInfo->pu8FramebufferVRAM, u64Now);
+ }
+ else
+ {
+ rc = VideoRecCopyToIntBuf(pDisplay->mpVideoRecCtx, uScreenId, 0, 0,
+ FramebufferPixelFormat_FOURCC_RGB,
+ pDrv->IConnector.cBits,
+ pDrv->IConnector.cbScanline, pDrv->IConnector.cx,
+ pDrv->IConnector.cy, pDrv->IConnector.pu8Data, u64Now);
+ }
+ if (rc == VINF_TRY_AGAIN)
+ break;
+ }
+ }
+ } while (0);
}
-#endif
+#endif /* VBOX_WITH_VPX */
#ifdef DEBUG_sunlover
- STAM_PROFILE_STOP(&StatDisplayRefresh, a);
+ STAM_PROFILE_STOP(&g_StatDisplayRefresh, a);
#endif /* DEBUG_sunlover */
#ifdef DEBUG_sunlover_2
- LogFlowFunc (("leave\n"));
+ LogFlowFunc(("leave\n"));
#endif /* DEBUG_sunlover_2 */
}
@@ -3353,7 +3992,7 @@ DECLCALLBACK(void) Display::displayResetCallback(PPDMIDISPLAYCONNECTOR pInterfac
{
PDRVMAINDISPLAY pDrv = PDMIDISPLAYCONNECTOR_2_MAINDISPLAY(pInterface);
- LogRelFlowFunc (("\n"));
+ LogRelFlowFunc(("\n"));
/* Disable VBVA mode. */
pDrv->pDisplay->VideoAccelEnable (false, NULL);
@@ -3368,7 +4007,7 @@ DECLCALLBACK(void) Display::displayLFBModeChangeCallback(PPDMIDISPLAYCONNECTOR p
{
PDRVMAINDISPLAY pDrv = PDMIDISPLAYCONNECTOR_2_MAINDISPLAY(pInterface);
- LogRelFlowFunc (("fEnabled=%d\n", fEnabled));
+ LogRelFlowFunc(("fEnabled=%d\n", fEnabled));
NOREF(fEnabled);
@@ -3611,48 +4250,42 @@ DECLCALLBACK(void) Display::displayProcessDisplayDataCallback(PPDMIDISPLAYCONNEC
#ifdef VBOX_WITH_VIDEOHWACCEL
-void Display::handleVHWACommandProcess(PPDMIDISPLAYCONNECTOR pInterface, PVBOXVHWACMD pCommand)
+#ifndef S_FALSE
+# define S_FALSE ((HRESULT)1L)
+#endif
+
+int Display::handleVHWACommandProcess(PVBOXVHWACMD pCommand)
{
unsigned id = (unsigned)pCommand->iDisplay;
int rc = VINF_SUCCESS;
- if (id < mcMonitors)
- {
- IFramebuffer *pFramebuffer = maFramebuffers[id].pFramebuffer;
-#ifdef DEBUG_misha
- Assert (pFramebuffer);
-#endif
+ if (id >= mcMonitors)
+ return VERR_INVALID_PARAMETER;
- if (pFramebuffer != NULL)
- {
- HRESULT hr = pFramebuffer->ProcessVHWACommand((BYTE*)pCommand);
- if (FAILED(hr))
- {
- rc = (hr == E_NOTIMPL) ? VERR_NOT_IMPLEMENTED : VERR_GENERAL_FAILURE;
- }
- }
- else
- {
- rc = VERR_NOT_IMPLEMENTED;
- }
- }
- else
- {
- rc = VERR_INVALID_PARAMETER;
- }
+ ComPtr<IFramebuffer> pFramebuffer;
+ AutoReadLock arlock(this COMMA_LOCKVAL_SRC_POS);
+ pFramebuffer = maFramebuffers[id].pFramebuffer;
+ arlock.release();
- if (RT_FAILURE(rc))
- {
- /* tell the guest the command is complete */
- pCommand->Flags &= (~VBOXVHWACMD_FLAG_HG_ASYNCH);
- pCommand->rc = rc;
- }
+ if (pFramebuffer == NULL)
+ return VERR_INVALID_STATE; /* notify we can not handle request atm */
+
+ HRESULT hr = pFramebuffer->ProcessVHWACommand((BYTE*)pCommand);
+ if (hr == S_FALSE)
+ return VINF_SUCCESS;
+ else if (SUCCEEDED(hr))
+ return VINF_CALLBACK_RETURN;
+ else if (hr == E_ACCESSDENIED)
+ return VERR_INVALID_STATE; /* notify we can not handle request atm */
+ else if (hr == E_NOTIMPL)
+ return VERR_NOT_IMPLEMENTED;
+ return VERR_GENERAL_FAILURE;
}
-DECLCALLBACK(void) Display::displayVHWACommandProcess(PPDMIDISPLAYCONNECTOR pInterface, PVBOXVHWACMD pCommand)
+DECLCALLBACK(int) Display::displayVHWACommandProcess(PPDMIDISPLAYCONNECTOR pInterface, PVBOXVHWACMD pCommand)
{
PDRVMAINDISPLAY pDrv = PDMIDISPLAYCONNECTOR_2_MAINDISPLAY(pInterface);
- pDrv->pDisplay->handleVHWACommandProcess(pInterface, pCommand);
+ return pDrv->pDisplay->handleVHWACommandProcess(pCommand);
}
#endif
@@ -3667,9 +4300,9 @@ void Display::handleCrHgsmiControlCompletion(int32_t result, uint32_t u32Functio
mpDrv->pVBVACallbacks->pfnCrHgsmiControlCompleteAsync(mpDrv->pVBVACallbacks, (PVBOXVDMACMD_CHROMIUM_CTL)pParam->u.pointer.addr, result);
}
-void Display::handleCrHgsmiCommandProcess(PPDMIDISPLAYCONNECTOR pInterface, PVBOXVDMACMD_CHROMIUM_CMD pCmd, uint32_t cbCmd)
+void Display::handleCrHgsmiCommandProcess(PVBOXVDMACMD_CHROMIUM_CMD pCmd, uint32_t cbCmd)
{
- int rc = VERR_INVALID_FUNCTION;
+ int rc = VERR_NOT_SUPPORTED;
VBOXHGCMSVCPARM parm;
parm.type = VBOX_HGCM_SVC_PARM_PTR;
parm.u.pointer.addr = pCmd;
@@ -3695,9 +4328,9 @@ void Display::handleCrHgsmiCommandProcess(PPDMIDISPLAYCONNECTOR pInterface, PVBO
handleCrHgsmiCommandCompletion(rc, SHCRGL_HOST_FN_CRHGSMI_CMD, &parm);
}
-void Display::handleCrHgsmiControlProcess(PPDMIDISPLAYCONNECTOR pInterface, PVBOXVDMACMD_CHROMIUM_CTL pCtl, uint32_t cbCtl)
+void Display::handleCrHgsmiControlProcess(PVBOXVDMACMD_CHROMIUM_CTL pCtl, uint32_t cbCtl)
{
- int rc = VERR_INVALID_FUNCTION;
+ int rc = VERR_NOT_SUPPORTED;
VBOXHGCMSVCPARM parm;
parm.type = VBOX_HGCM_SVC_PARM_PTR;
parm.u.pointer.addr = pCtl;
@@ -3721,19 +4354,18 @@ void Display::handleCrHgsmiControlProcess(PPDMIDISPLAYCONNECTOR pInterface, PVBO
handleCrHgsmiControlCompletion(rc, SHCRGL_HOST_FN_CRHGSMI_CTL, &parm);
}
-
DECLCALLBACK(void) Display::displayCrHgsmiCommandProcess(PPDMIDISPLAYCONNECTOR pInterface, PVBOXVDMACMD_CHROMIUM_CMD pCmd, uint32_t cbCmd)
{
PDRVMAINDISPLAY pDrv = PDMIDISPLAYCONNECTOR_2_MAINDISPLAY(pInterface);
- pDrv->pDisplay->handleCrHgsmiCommandProcess(pInterface, pCmd, cbCmd);
+ pDrv->pDisplay->handleCrHgsmiCommandProcess(pCmd, cbCmd);
}
DECLCALLBACK(void) Display::displayCrHgsmiControlProcess(PPDMIDISPLAYCONNECTOR pInterface, PVBOXVDMACMD_CHROMIUM_CTL pCmd, uint32_t cbCmd)
{
PDRVMAINDISPLAY pDrv = PDMIDISPLAYCONNECTOR_2_MAINDISPLAY(pInterface);
- pDrv->pDisplay->handleCrHgsmiControlProcess(pInterface, pCmd, cbCmd);
+ pDrv->pDisplay->handleCrHgsmiControlProcess(pCmd, cbCmd);
}
DECLCALLBACK(void) Display::displayCrHgsmiCommandCompletion(int32_t result, uint32_t u32Function, PVBOXHGCMSVCPARM pParam, void *pvContext)
@@ -3750,6 +4382,131 @@ DECLCALLBACK(void) Display::displayCrHgsmiControlCompletion(int32_t result, uint
}
#endif
+DECLCALLBACK(void) Display::displayCrHgcmCtlSubmitCompletion(int32_t result, uint32_t u32Function, PVBOXHGCMSVCPARM pParam, void *pvContext)
+{
+ VBOXCRCMDCTL *pCmd = (VBOXCRCMDCTL*)pParam->u.pointer.addr;
+ if (pCmd->pfnInternal)
+ ((PFNCRCTLCOMPLETION)pCmd->pfnInternal)(pCmd, pParam->u.pointer.size, result, pvContext);
+}
+
+int Display::handleCrHgcmCtlSubmit(struct VBOXCRCMDCTL* pCmd, uint32_t cbCmd,
+ PFNCRCTLCOMPLETION pfnCompletion,
+ void *pvCompletion)
+{
+ VMMDev *pVMMDev = mParent->getVMMDev();
+ if (!pVMMDev)
+ {
+ AssertMsgFailed(("no vmmdev\n"));
+ return VERR_INVALID_STATE;
+ }
+
+ Assert(mhCrOglSvc);
+ VBOXHGCMSVCPARM parm;
+ parm.type = VBOX_HGCM_SVC_PARM_PTR;
+ parm.u.pointer.addr = pCmd;
+ parm.u.pointer.size = cbCmd;
+
+ pCmd->pfnInternal = (void(*)())pfnCompletion;
+ int rc = pVMMDev->hgcmHostFastCallAsync(mhCrOglSvc, SHCRGL_HOST_FN_CTL, &parm, displayCrHgcmCtlSubmitCompletion, pvCompletion);
+ if (!RT_SUCCESS(rc))
+ AssertMsgFailed(("hgcmHostFastCallAsync failed rc %n", rc));
+
+ return rc;
+}
+
+DECLCALLBACK(int) Display::displayCrHgcmCtlSubmit(PPDMIDISPLAYCONNECTOR pInterface,
+ struct VBOXCRCMDCTL* pCmd, uint32_t cbCmd,
+ PFNCRCTLCOMPLETION pfnCompletion,
+ void *pvCompletion)
+{
+ PDRVMAINDISPLAY pDrv = PDMIDISPLAYCONNECTOR_2_MAINDISPLAY(pInterface);
+ Display *pThis = pDrv->pDisplay;
+ return pThis->handleCrHgcmCtlSubmit(pCmd, cbCmd, pfnCompletion, pvCompletion);
+}
+
+#if defined(VBOX_WITH_HGCM) && defined(VBOX_WITH_CROGL)
+DECLCALLBACK(void) Display::displayCrAsyncCmdCompletion(int32_t result, uint32_t u32Function, PVBOXHGCMSVCPARM pParam, void *pvContext)
+{
+ Display *pDisplay = (Display *)pvContext;
+ pDisplay->handleCrAsyncCmdCompletion(result, u32Function, pParam);
+}
+
+
+void Display::handleCrAsyncCmdCompletion(int32_t result, uint32_t u32Function, PVBOXHGCMSVCPARM pParam)
+{
+ if (pParam->type == VBOX_HGCM_SVC_PARM_PTR && pParam->u.pointer.addr)
+ RTMemFree(pParam->u.pointer.addr);
+}
+
+bool Display::handleCrVRecScreenshotBegin(uint32_t uScreen, uint64_t u64TimeStamp)
+{
+# if VBOX_WITH_VPX
+ return VideoRecIsReady(mpVideoRecCtx, uScreen, u64TimeStamp);
+# else
+ return false;
+# endif
+}
+
+void Display::handleCrVRecScreenshotEnd(uint32_t uScreen, uint64_t u64TimeStamp)
+{
+}
+
+void Display::handleCrVRecScreenshotPerform(uint32_t uScreen,
+ uint32_t x, uint32_t y, uint32_t uPixelFormat,
+ uint32_t uBitsPerPixel, uint32_t uBytesPerLine,
+ uint32_t uGuestWidth, uint32_t uGuestHeight,
+ uint8_t *pu8BufferAddress, uint64_t u64TimeStamp)
+{
+ Assert(mfCrOglVideoRecState == CRVREC_STATE_SUBMITTED);
+# if VBOX_WITH_VPX
+ int rc = VideoRecCopyToIntBuf(mpVideoRecCtx, uScreen, x, y,
+ uPixelFormat,
+ uBitsPerPixel, uBytesPerLine,
+ uGuestWidth, uGuestHeight,
+ pu8BufferAddress, u64TimeStamp);
+ Assert(rc == VINF_SUCCESS /* || rc == VERR_TRY_AGAIN || rc == VINF_TRY_AGAIN*/);
+# endif
+}
+
+void Display::handleVRecCompletion(int32_t result, uint32_t u32Function, PVBOXHGCMSVCPARM pParam, void *pvContext)
+{
+ Assert(mfCrOglVideoRecState == CRVREC_STATE_SUBMITTED);
+ ASMAtomicWriteU32(&mfCrOglVideoRecState, CRVREC_STATE_IDLE);
+}
+
+DECLCALLBACK(void) Display::displayCrVRecScreenshotPerform(void *pvCtx, uint32_t uScreen,
+ uint32_t x, uint32_t y,
+ uint32_t uBitsPerPixel, uint32_t uBytesPerLine,
+ uint32_t uGuestWidth, uint32_t uGuestHeight,
+ uint8_t *pu8BufferAddress, uint64_t u64TimeStamp)
+{
+ Display *pDisplay = (Display *)pvCtx;
+ pDisplay->handleCrVRecScreenshotPerform(uScreen,
+ x, y, FramebufferPixelFormat_FOURCC_RGB, uBitsPerPixel,
+ uBytesPerLine, uGuestWidth, uGuestHeight,
+ pu8BufferAddress, u64TimeStamp);
+}
+
+DECLCALLBACK(bool) Display::displayCrVRecScreenshotBegin(void *pvCtx, uint32_t uScreen, uint64_t u64TimeStamp)
+{
+ Display *pDisplay = (Display *)pvCtx;
+ return pDisplay->handleCrVRecScreenshotBegin(uScreen, u64TimeStamp);
+}
+
+DECLCALLBACK(void) Display::displayCrVRecScreenshotEnd(void *pvCtx, uint32_t uScreen, uint64_t u64TimeStamp)
+{
+ Display *pDisplay = (Display *)pvCtx;
+ pDisplay->handleCrVRecScreenshotEnd(uScreen, u64TimeStamp);
+}
+
+DECLCALLBACK(void) Display::displayVRecCompletion(int32_t result, uint32_t u32Function, PVBOXHGCMSVCPARM pParam, void *pvContext)
+{
+ Display *pDisplay = (Display *)pvContext;
+ pDisplay->handleVRecCompletion(result, u32Function, pParam, pvContext);
+}
+
+#endif
+
#ifdef VBOX_WITH_HGSMI
DECLCALLBACK(int) Display::displayVBVAEnable(PPDMIDISPLAYCONNECTOR pInterface, unsigned uScreenId, PVBVAHOSTFLAGS pHostFlags)
@@ -3868,7 +4625,7 @@ DECLCALLBACK(void) Display::displayVBVAUpdateProcess(PPDMIDISPLAYCONNECTOR pInte
pDrv->pUpPort->pfnUpdateDisplayRect (pDrv->pUpPort, pCmd->x, pCmd->y, pCmd->w, pCmd->h);
}
else if ( !pFBInfo->pFramebuffer.isNull()
- && !(pFBInfo->fDisabled))
+ && !pFBInfo->fDisabled)
{
/* Render VRAM content to the framebuffer. */
BYTE *address = NULL;
@@ -3916,7 +4673,7 @@ DECLCALLBACK(void) Display::displayVBVAUpdateProcess(PPDMIDISPLAYCONNECTOR pInte
pHdrUnconst->y -= (int16_t)pFBInfo->yOrigin;
/* @todo new SendUpdate entry which can get a separate cmd header or coords. */
- pThis->mParent->consoleVRDPServer()->SendUpdate (uScreenId, pCmd, cbCmd);
+ pThis->mParent->consoleVRDPServer()->SendUpdate (uScreenId, pCmd, (uint32_t)cbCmd);
*pHdrUnconst = hdrSaved;
}
@@ -4078,14 +4835,18 @@ DECLCALLBACK(int) Display::displayVBVAResize(PPDMIDISPLAYCONNECTOR pInterface, c
if (pScreen->u16Flags & VBVA_SCREEN_F_DISABLED)
{
+ pThis->notifyCroglResize(pView, pScreen, pvVRAM);
+
pFBInfo->fDisabled = true;
pFBInfo->flags = pScreen->u16Flags;
- /* Temporary: ask framebuffer to resize using a default format. The framebuffer will be black. */
- pThis->handleDisplayResize(pScreen->u32ViewIndex, 0,
- (uint8_t *)NULL,
- pScreen->u32LineSize, pScreen->u32Width,
- pScreen->u32Height, pScreen->u16Flags);
+ /* Ask the framebuffer to resize using a default format. The framebuffer will be black.
+ * So if the frontend does not support GuestMonitorChangedEventType_Disabled event,
+ * the VM window will be black. */
+ uint32_t u32Width = pFBInfo->w ? pFBInfo->w : 640;
+ uint32_t u32Height = pFBInfo->h ? pFBInfo->h : 480;
+ pThis->handleDisplayResize(pScreen->u32ViewIndex, 0, (uint8_t *)NULL, 0,
+ u32Width, u32Height, pScreen->u16Flags);
fireGuestMonitorChangedEvent(pThis->mParent->getEventSource(),
GuestMonitorChangedEventType_Disabled,
@@ -4099,17 +4860,6 @@ DECLCALLBACK(int) Display::displayVBVAResize(PPDMIDISPLAYCONNECTOR pInterface, c
*/
bool fResize = pFBInfo->fDisabled || pFBInfo->pFramebuffer.isNull();
- if (pFBInfo->fDisabled)
- {
- pFBInfo->fDisabled = false;
- fireGuestMonitorChangedEvent(pThis->mParent->getEventSource(),
- GuestMonitorChangedEventType_Enabled,
- pScreen->u32ViewIndex,
- pScreen->i32OriginX, pScreen->i32OriginY,
- pScreen->u32Width, pScreen->u32Height);
- /* Continue to update pFBInfo. */
- }
-
/* Check if this is a real resize or a notification about the screen origin.
* The guest uses this VBVAResize call for both.
*/
@@ -4123,6 +4873,20 @@ DECLCALLBACK(int) Display::displayVBVAResize(PPDMIDISPLAYCONNECTOR pInterface, c
bool fNewOrigin = pFBInfo->xOrigin != pScreen->i32OriginX
|| pFBInfo->yOrigin != pScreen->i32OriginY;
+ if (fNewOrigin || fResize)
+ pThis->notifyCroglResize(pView, pScreen, pvVRAM);
+
+ if (pFBInfo->fDisabled)
+ {
+ pFBInfo->fDisabled = false;
+ fireGuestMonitorChangedEvent(pThis->mParent->getEventSource(),
+ GuestMonitorChangedEventType_Enabled,
+ pScreen->u32ViewIndex,
+ pScreen->i32OriginX, pScreen->i32OriginY,
+ pScreen->u32Width, pScreen->u32Height);
+ /* Continue to update pFBInfo. */
+ }
+
pFBInfo->u32Offset = pView->u32ViewOffset; /* Not used in HGSMI. */
pFBInfo->u32MaxFramebufferSize = pView->u32MaxScreenSize; /* Not used in HGSMI. */
pFBInfo->u32InformationSize = 0; /* Not used in HGSMI. */
@@ -4148,34 +4912,13 @@ DECLCALLBACK(int) Display::displayVBVAResize(PPDMIDISPLAYCONNECTOR pInterface, c
0, 0);
}
-#if defined(VBOX_WITH_HGCM) && defined(VBOX_WITH_CROGL)
- if (fNewOrigin && !fResize)
- {
- BOOL is3denabled;
- pThis->mParent->machine()->COMGETTER(Accelerate3DEnabled)(&is3denabled);
-
- if (is3denabled)
- {
- VBOXHGCMSVCPARM parm;
-
- parm.type = VBOX_HGCM_SVC_PARM_32BIT;
- parm.u.uint32 = pScreen->u32ViewIndex;
-
- VMMDev *pVMMDev = pThis->mParent->getVMMDev();
-
- if (pVMMDev)
- pVMMDev->hgcmHostCall("VBoxSharedCrOpenGL", SHCRGL_HOST_FN_SCREEN_CHANGED, SHCRGL_CPARMS_SCREEN_CHANGED, &parm);
- }
- }
-#endif /* VBOX_WITH_CROGL */
-
if (!fResize)
{
/* No parameters of the framebuffer have actually changed. */
if (fNewOrigin)
{
/* VRDP server still need this notification. */
- LogRelFlowFunc (("Calling VRDP\n"));
+ LogRelFlowFunc(("Calling VRDP\n"));
pThis->mParent->consoleVRDPServer()->SendResize();
}
return VINF_SUCCESS;
@@ -4244,23 +4987,26 @@ DECLCALLBACK(void *) Display::drvQueryInterface(PPDMIBASE pInterface, const cha
*/
DECLCALLBACK(void) Display::drvDestruct(PPDMDRVINS pDrvIns)
{
- PDRVMAINDISPLAY pData = PDMINS_2_DATA(pDrvIns, PDRVMAINDISPLAY);
- LogRelFlowFunc (("iInstance=%d\n", pDrvIns->iInstance));
PDMDRV_CHECK_VERSIONS_RETURN_VOID(pDrvIns);
+ PDRVMAINDISPLAY pThis = PDMINS_2_DATA(pDrvIns, PDRVMAINDISPLAY);
+ LogRelFlowFunc(("iInstance=%d\n", pDrvIns->iInstance));
- if (pData->pDisplay)
+ if (pThis->pDisplay)
{
- AutoWriteLock displayLock(pData->pDisplay COMMA_LOCKVAL_SRC_POS);
+ AutoWriteLock displayLock(pThis->pDisplay COMMA_LOCKVAL_SRC_POS);
+#ifdef VBOX_WITH_VPX
+ pThis->pDisplay->VideoCaptureStop();
+#endif
#ifdef VBOX_WITH_CRHGSMI
- pData->pDisplay->destructCrHgsmiData();
+ pThis->pDisplay->destructCrHgsmiData();
#endif
- pData->pDisplay->mpDrv = NULL;
- pData->pDisplay->mpVMMDev = NULL;
- pData->pDisplay->mLastAddress = NULL;
- pData->pDisplay->mLastBytesPerLine = 0;
- pData->pDisplay->mLastBitsPerPixel = 0,
- pData->pDisplay->mLastWidth = 0;
- pData->pDisplay->mLastHeight = 0;
+ pThis->pDisplay->mpDrv = NULL;
+ pThis->pDisplay->mpVMMDev = NULL;
+ pThis->pDisplay->mLastAddress = NULL;
+ pThis->pDisplay->mLastBytesPerLine = 0;
+ pThis->pDisplay->mLastBitsPerPixel = 0,
+ pThis->pDisplay->mLastWidth = 0;
+ pThis->pDisplay->mLastHeight = 0;
}
}
@@ -4272,9 +5018,9 @@ DECLCALLBACK(void) Display::drvDestruct(PPDMDRVINS pDrvIns)
*/
DECLCALLBACK(int) Display::drvConstruct(PPDMDRVINS pDrvIns, PCFGMNODE pCfg, uint32_t fFlags)
{
- PDRVMAINDISPLAY pData = PDMINS_2_DATA(pDrvIns, PDRVMAINDISPLAY);
- LogRelFlowFunc (("iInstance=%d\n", pDrvIns->iInstance));
PDMDRV_CHECK_VERSIONS_RETURN(pDrvIns);
+ PDRVMAINDISPLAY pThis = PDMINS_2_DATA(pDrvIns, PDRVMAINDISPLAY);
+ LogRelFlowFunc(("iInstance=%d\n", pDrvIns->iInstance));
/*
* Validate configuration.
@@ -4288,44 +5034,45 @@ DECLCALLBACK(int) Display::drvConstruct(PPDMDRVINS pDrvIns, PCFGMNODE pCfg, uint
/*
* Init Interfaces.
*/
- pDrvIns->IBase.pfnQueryInterface = Display::drvQueryInterface;
-
- pData->IConnector.pfnResize = Display::displayResizeCallback;
- pData->IConnector.pfnUpdateRect = Display::displayUpdateCallback;
- pData->IConnector.pfnRefresh = Display::displayRefreshCallback;
- pData->IConnector.pfnReset = Display::displayResetCallback;
- pData->IConnector.pfnLFBModeChange = Display::displayLFBModeChangeCallback;
- pData->IConnector.pfnProcessAdapterData = Display::displayProcessAdapterDataCallback;
- pData->IConnector.pfnProcessDisplayData = Display::displayProcessDisplayDataCallback;
+ pDrvIns->IBase.pfnQueryInterface = Display::drvQueryInterface;
+
+ pThis->IConnector.pfnResize = Display::displayResizeCallback;
+ pThis->IConnector.pfnUpdateRect = Display::displayUpdateCallback;
+ pThis->IConnector.pfnRefresh = Display::displayRefreshCallback;
+ pThis->IConnector.pfnReset = Display::displayResetCallback;
+ pThis->IConnector.pfnLFBModeChange = Display::displayLFBModeChangeCallback;
+ pThis->IConnector.pfnProcessAdapterData = Display::displayProcessAdapterDataCallback;
+ pThis->IConnector.pfnProcessDisplayData = Display::displayProcessDisplayDataCallback;
#ifdef VBOX_WITH_VIDEOHWACCEL
- pData->IConnector.pfnVHWACommandProcess = Display::displayVHWACommandProcess;
+ pThis->IConnector.pfnVHWACommandProcess = Display::displayVHWACommandProcess;
#endif
#ifdef VBOX_WITH_CRHGSMI
- pData->IConnector.pfnCrHgsmiCommandProcess = Display::displayCrHgsmiCommandProcess;
- pData->IConnector.pfnCrHgsmiControlProcess = Display::displayCrHgsmiControlProcess;
+ pThis->IConnector.pfnCrHgsmiCommandProcess = Display::displayCrHgsmiCommandProcess;
+ pThis->IConnector.pfnCrHgsmiControlProcess = Display::displayCrHgsmiControlProcess;
#endif
+ pThis->IConnector.pfnCrHgcmCtlSubmit = Display::displayCrHgcmCtlSubmit;
#ifdef VBOX_WITH_HGSMI
- pData->IConnector.pfnVBVAEnable = Display::displayVBVAEnable;
- pData->IConnector.pfnVBVADisable = Display::displayVBVADisable;
- pData->IConnector.pfnVBVAUpdateBegin = Display::displayVBVAUpdateBegin;
- pData->IConnector.pfnVBVAUpdateProcess = Display::displayVBVAUpdateProcess;
- pData->IConnector.pfnVBVAUpdateEnd = Display::displayVBVAUpdateEnd;
- pData->IConnector.pfnVBVAResize = Display::displayVBVAResize;
- pData->IConnector.pfnVBVAMousePointerShape = Display::displayVBVAMousePointerShape;
+ pThis->IConnector.pfnVBVAEnable = Display::displayVBVAEnable;
+ pThis->IConnector.pfnVBVADisable = Display::displayVBVADisable;
+ pThis->IConnector.pfnVBVAUpdateBegin = Display::displayVBVAUpdateBegin;
+ pThis->IConnector.pfnVBVAUpdateProcess = Display::displayVBVAUpdateProcess;
+ pThis->IConnector.pfnVBVAUpdateEnd = Display::displayVBVAUpdateEnd;
+ pThis->IConnector.pfnVBVAResize = Display::displayVBVAResize;
+ pThis->IConnector.pfnVBVAMousePointerShape = Display::displayVBVAMousePointerShape;
#endif
/*
* Get the IDisplayPort interface of the above driver/device.
*/
- pData->pUpPort = PDMIBASE_QUERY_INTERFACE(pDrvIns->pUpBase, PDMIDISPLAYPORT);
- if (!pData->pUpPort)
+ pThis->pUpPort = PDMIBASE_QUERY_INTERFACE(pDrvIns->pUpBase, PDMIDISPLAYPORT);
+ if (!pThis->pUpPort)
{
AssertMsgFailed(("Configuration error: No display port interface above!\n"));
return VERR_PDM_MISSING_INTERFACE_ABOVE;
}
#if defined(VBOX_WITH_VIDEOHWACCEL) || defined(VBOX_WITH_CRHGSMI)
- pData->pVBVACallbacks = PDMIBASE_QUERY_INTERFACE(pDrvIns->pUpBase, PDMIDISPLAYVBVACALLBACKS);
- if (!pData->pVBVACallbacks)
+ pThis->pVBVACallbacks = PDMIBASE_QUERY_INTERFACE(pDrvIns->pUpBase, PDMIDISPLAYVBVACALLBACKS);
+ if (!pThis->pVBVACallbacks)
{
AssertMsgFailed(("Configuration error: No VBVA callback interface above!\n"));
return VERR_PDM_MISSING_INTERFACE_ABOVE;
@@ -4341,24 +5088,36 @@ DECLCALLBACK(int) Display::drvConstruct(PPDMDRVINS pDrvIns, PCFGMNODE pCfg, uint
AssertMsgFailed(("Configuration error: No/bad \"Object\" value! rc=%Rrc\n", rc));
return rc;
}
- pData->pDisplay = (Display *)pv; /** @todo Check this cast! */
- pData->pDisplay->mpDrv = pData;
-
+ Display *pDisplay = (Display *)pv; /** @todo Check this cast! */
+ pThis->pDisplay = pDisplay;
+ pThis->pDisplay->mpDrv = pThis;
/*
* Update our display information according to the framebuffer
*/
- pData->pDisplay->updateDisplayData();
+ pDisplay->updateDisplayData();
/*
* Start periodic screen refreshes
*/
- pData->pUpPort->pfnSetRefreshRate(pData->pUpPort, 20);
+ pThis->pUpPort->pfnSetRefreshRate(pThis->pUpPort, 20);
#ifdef VBOX_WITH_CRHGSMI
- pData->pDisplay->setupCrHgsmiData();
+ pDisplay->setupCrHgsmiData();
#endif
- return VINF_SUCCESS;
+#ifdef VBOX_WITH_VPX
+ ComPtr<IMachine> pMachine = pDisplay->mParent->machine();
+ BOOL fEnabled = false;
+ HRESULT hrc = pMachine->COMGETTER(VideoCaptureEnabled)(&fEnabled);
+ AssertComRCReturn(hrc, VERR_COM_UNEXPECTED);
+ if (fEnabled)
+ {
+ rc = pDisplay->VideoCaptureStart();
+ fireVideoCaptureChangedEvent(pDisplay->mParent->getEventSource());
+ }
+#endif
+
+ return rc;
}