DisplayImpl.cpp revision eac18a2a75654a71176720265be9d2e77658481f
b6517c5cc3b7a38889416706905a3cf2fd010785vboxsync * VirtualBox COM class implementation
76110d8ef23142ec3bcab1f50622858bdb55c76dvboxsync * Copyright (C) 2006-2013 Oracle Corporation
b6517c5cc3b7a38889416706905a3cf2fd010785vboxsync * This file is part of VirtualBox Open Source Edition (OSE), as
b6517c5cc3b7a38889416706905a3cf2fd010785vboxsync * available from http://www.virtualbox.org. This file is free software;
b6517c5cc3b7a38889416706905a3cf2fd010785vboxsync * you can redistribute it and/or modify it under the terms of the GNU
b6517c5cc3b7a38889416706905a3cf2fd010785vboxsync * General Public License (GPL) as published by the Free Software
b6517c5cc3b7a38889416706905a3cf2fd010785vboxsync * Foundation, in version 2 as it comes in the "COPYING" file of the
b6517c5cc3b7a38889416706905a3cf2fd010785vboxsync * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
b6517c5cc3b7a38889416706905a3cf2fd010785vboxsync * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
b6517c5cc3b7a38889416706905a3cf2fd010785vboxsync/* generated header */
b6517c5cc3b7a38889416706905a3cf2fd010785vboxsync#if defined(VBOX_WITH_CROGL) || defined(VBOX_WITH_CRHGSMI)
2f827df539da232220444c27f2b207a707a045b0vboxsync * Display driver instance data.
4bb5cfa1f4d9e95d7d34b5d6ede18d9f4d433bc6vboxsync * @implements PDMIDISPLAYCONNECTOR
2f827df539da232220444c27f2b207a707a045b0vboxsync /** Pointer to the display object. */
b6517c5cc3b7a38889416706905a3cf2fd010785vboxsync /** Pointer to the driver instance structure. */
b6517c5cc3b7a38889416706905a3cf2fd010785vboxsync /** Pointer to the keyboard port interface of the driver/device above us. */
b6517c5cc3b7a38889416706905a3cf2fd010785vboxsync /** Our display connector interface. */
6f045c8e519b0f50a4c2eb2906e5f5e2c4679fa8vboxsync#if defined(VBOX_WITH_VIDEOHWACCEL) || defined(VBOX_WITH_CRHGSMI)
b6517c5cc3b7a38889416706905a3cf2fd010785vboxsync /** VBVA callbacks */
b6517c5cc3b7a38889416706905a3cf2fd010785vboxsync/** Converts PDMIDISPLAYCONNECTOR pointer to a DRVMAINDISPLAY pointer. */
b6517c5cc3b7a38889416706905a3cf2fd010785vboxsync#define PDMIDISPLAYCONNECTOR_2_MAINDISPLAY(pInterface) RT_FROM_MEMBER(pInterface, DRVMAINDISPLAY, IConnector)
6f045c8e519b0f50a4c2eb2906e5f5e2c4679fa8vboxsyncstatic int g_stam = 0;
6f045c8e519b0f50a4c2eb2906e5f5e2c4679fa8vboxsync#endif /* DEBUG_sunlover */
6f045c8e519b0f50a4c2eb2906e5f5e2c4679fa8vboxsync// constructor / destructor
6f045c8e519b0f50a4c2eb2906e5f5e2c4679fa8vboxsync/////////////////////////////////////////////////////////////////////////////
56f538fa476fdbd9cc3d60438083a3f0d5f3ff7fvboxsync// public initializer/uninitializer for internal purposes only
56f538fa476fdbd9cc3d60438083a3f0d5f3ff7fvboxsync/////////////////////////////////////////////////////////////////////////////
2f827df539da232220444c27f2b207a707a045b0vboxsync * Save thumbnail and screenshot of the guest screen.
56f538fa476fdbd9cc3d60438083a3f0d5f3ff7fvboxsyncstatic int displayMakeThumbnail(uint8_t *pu8Data, uint32_t cx, uint32_t cy,
56f538fa476fdbd9cc3d60438083a3f0d5f3ff7fvboxsync uint8_t **ppu8Thumbnail, uint32_t *pcbThumbnail, uint32_t *pcxThumbnail, uint32_t *pcyThumbnail)
2f827df539da232220444c27f2b207a707a045b0vboxsync LogRelFlowFunc(("%dx%d -> %dx%d\n", cx, cy, cxThumbnail, cyThumbnail));
f46e7db81f80ea09725c6cc048fa0cad86573dc2vboxsyncDisplay::displaySSMSaveScreenshot(PSSMHANDLE pSSM, void *pvUser)
b6517c5cc3b7a38889416706905a3cf2fd010785vboxsync /* 32bpp small RGB image. */
f46e7db81f80ea09725c6cc048fa0cad86573dc2vboxsync /* PNG screenshot. */
f5d67cb858e3b0b324de00cfbefb0e267238b78bvboxsync /* Query RGB bitmap. */
f5d67cb858e3b0b324de00cfbefb0e267238b78bvboxsync /* SSM code is executed on EMT(0), therefore no need to use VMR3ReqCallWait. */
f5d67cb858e3b0b324de00cfbefb0e267238b78bvboxsync int rc = Display::displayTakeScreenshotEMT(that, VBOX_VIDEO_PRIMARY_SCREEN, &pu8Data, &cbData, &cx, &cy);
f5d67cb858e3b0b324de00cfbefb0e267238b78bvboxsync * It is possible that success is returned but everything is 0 or NULL.
f5d67cb858e3b0b324de00cfbefb0e267238b78bvboxsync * (no display attached if a VM is running with VBoxHeadless on OSE for example)
f5d67cb858e3b0b324de00cfbefb0e267238b78bvboxsync /* Prepare a small thumbnail and a PNG screenshot. */
f5d67cb858e3b0b324de00cfbefb0e267238b78bvboxsync displayMakeThumbnail(pu8Data, cx, cy, &pu8Thumbnail, &cbThumbnail, &cxThumbnail, &cyThumbnail);
f5d67cb858e3b0b324de00cfbefb0e267238b78bvboxsync rc = DisplayMakePNG(pu8Data, cx, cy, &pu8PNG, &cbPNG, &cxPNG, &cyPNG, 1);
d857e2bd9418f4d7588db888e622f5df5c5d9eabvboxsync /* This can be called from any thread. */
d857e2bd9418f4d7588db888e622f5df5c5d9eabvboxsync that->mpDrv->pUpPort->pfnFreeScreenshot(that->mpDrv->pUpPort, pu8Data);
f46e7db81f80ea09725c6cc048fa0cad86573dc2vboxsync LogFunc(("Failed to get VM pointer 0x%x\n", ptrVM.rc()));
3adea7c30ebc76f2e5975ad9052a40c174f588f3vboxsync /* Regardless of rc, save what is available:
f46e7db81f80ea09725c6cc048fa0cad86573dc2vboxsync * Data format:
f46e7db81f80ea09725c6cc048fa0cad86573dc2vboxsync * uint32_t cBlocks;
f46e7db81f80ea09725c6cc048fa0cad86573dc2vboxsync * Each block is:
f46e7db81f80ea09725c6cc048fa0cad86573dc2vboxsync * uint32_t cbBlock; if 0 - no 'block data'.
f46e7db81f80ea09725c6cc048fa0cad86573dc2vboxsync * uint32_t typeOfBlock; 0 - 32bpp RGB bitmap, 1 - PNG, ignored if 'cbBlock' is 0.
f46e7db81f80ea09725c6cc048fa0cad86573dc2vboxsync * [block data]
f46e7db81f80ea09725c6cc048fa0cad86573dc2vboxsync * Block data for bitmap and PNG:
b6517c5cc3b7a38889416706905a3cf2fd010785vboxsync * uint32_t cx;
f46e7db81f80ea09725c6cc048fa0cad86573dc2vboxsync * uint32_t cy;
f46e7db81f80ea09725c6cc048fa0cad86573dc2vboxsync * [image data]
f46e7db81f80ea09725c6cc048fa0cad86573dc2vboxsync SSMR3PutU32(pSSM, 2); /* Write thumbnail and PNG screenshot. */
f46e7db81f80ea09725c6cc048fa0cad86573dc2vboxsync /* First block. */
f46e7db81f80ea09725c6cc048fa0cad86573dc2vboxsync SSMR3PutU32(pSSM, cbThumbnail + 2 * sizeof (uint32_t));
f46e7db81f80ea09725c6cc048fa0cad86573dc2vboxsync /* Second block. */
f46e7db81f80ea09725c6cc048fa0cad86573dc2vboxsyncDisplay::displaySSMLoadScreenshot(PSSMHANDLE pSSM, void *pvUser, uint32_t uVersion, uint32_t uPass)
f46e7db81f80ea09725c6cc048fa0cad86573dc2vboxsync /* Skip data. */
b6517c5cc3b7a38889416706905a3cf2fd010785vboxsync LogRelFlowFunc(("[%d] type %d, size %d bytes\n", i, typeOfBlock, cbBlock));
b6517c5cc3b7a38889416706905a3cf2fd010785vboxsync /* Note: displaySSMSaveScreenshot writes size of a block = 8 and
f46e7db81f80ea09725c6cc048fa0cad86573dc2vboxsync * do not write any data if the image size was 0.
b6517c5cc3b7a38889416706905a3cf2fd010785vboxsync * @todo Fix and increase saved state version.
f46e7db81f80ea09725c6cc048fa0cad86573dc2vboxsync * Save/Load some important guest state
f46e7db81f80ea09725c6cc048fa0cad86573dc2vboxsyncDisplay::displaySSMSave(PSSMHANDLE pSSM, void *pvUser)
f46e7db81f80ea09725c6cc048fa0cad86573dc2vboxsync SSMR3PutU32(pSSM, that->maFramebuffers[i].u32Offset);
f46e7db81f80ea09725c6cc048fa0cad86573dc2vboxsync SSMR3PutU32(pSSM, that->maFramebuffers[i].u32MaxFramebufferSize);
f46e7db81f80ea09725c6cc048fa0cad86573dc2vboxsync SSMR3PutU32(pSSM, that->maFramebuffers[i].u32InformationSize);
f46e7db81f80ea09725c6cc048fa0cad86573dc2vboxsync SSMR3PutS32(pSSM, that->maFramebuffers[i].xOrigin);
f46e7db81f80ea09725c6cc048fa0cad86573dc2vboxsync SSMR3PutS32(pSSM, that->maFramebuffers[i].yOrigin);
56f538fa476fdbd9cc3d60438083a3f0d5f3ff7fvboxsyncDisplay::displaySSMLoad(PSSMHANDLE pSSM, void *pvUser, uint32_t uVersion, uint32_t uPass)
56f538fa476fdbd9cc3d60438083a3f0d5f3ff7fvboxsync return SSMR3SetCfgError(pSSM, RT_SRC_POS, N_("Number of monitors changed (%d->%d)!"), cMonitors, that->mcMonitors);
2f827df539da232220444c27f2b207a707a045b0vboxsync SSMR3GetU32(pSSM, &that->maFramebuffers[i].u32Offset);
56f538fa476fdbd9cc3d60438083a3f0d5f3ff7fvboxsync SSMR3GetU32(pSSM, &that->maFramebuffers[i].u32MaxFramebufferSize);
b6517c5cc3b7a38889416706905a3cf2fd010785vboxsync SSMR3GetU32(pSSM, &that->maFramebuffers[i].u32InformationSize);
4bb5cfa1f4d9e95d7d34b5d6ede18d9f4d433bc6vboxsync that->maFramebuffers[i].fDisabled = (that->maFramebuffers[i].flags & VBVA_SCREEN_F_DISABLED) != 0;
4bb5cfa1f4d9e95d7d34b5d6ede18d9f4d433bc6vboxsync * Initializes the display object.
4bb5cfa1f4d9e95d7d34b5d6ede18d9f4d433bc6vboxsync * @returns COM result indicator
4bb5cfa1f4d9e95d7d34b5d6ede18d9f4d433bc6vboxsync * @param parent handle of our parent object
4bb5cfa1f4d9e95d7d34b5d6ede18d9f4d433bc6vboxsync * @param qemuConsoleData address of common console data structure
4bb5cfa1f4d9e95d7d34b5d6ede18d9f4d433bc6vboxsync /* Enclose the state transition NotReady->InInit->Ready */
4bb5cfa1f4d9e95d7d34b5d6ede18d9f4d433bc6vboxsync // by default, we have an internal framebuffer which is
4bb5cfa1f4d9e95d7d34b5d6ede18d9f4d433bc6vboxsync // NULL, i.e. a black hole for no display output
4bb5cfa1f4d9e95d7d34b5d6ede18d9f4d433bc6vboxsync LogFlow(("Failed to create Video Recording Context\n"));
4bb5cfa1f4d9e95d7d34b5d6ede18d9f4d433bc6vboxsync mParent->machine()->COMGETTER(VideoCaptureEnabled)(&fEnabled);
4bb5cfa1f4d9e95d7d34b5d6ede18d9f4d433bc6vboxsync mParent->machine()->COMGETTER(VideoCaptureWidth)(&ulVideoCaptureHorzRes);
4bb5cfa1f4d9e95d7d34b5d6ede18d9f4d433bc6vboxsync mParent->machine()->COMGETTER(VideoCaptureHeight)(&ulVideoCaptureVertRes);
4bb5cfa1f4d9e95d7d34b5d6ede18d9f4d433bc6vboxsync mParent->machine()->COMGETTER(VideoCaptureFile)(&strVideoCaptureFile);
4bb5cfa1f4d9e95d7d34b5d6ede18d9f4d433bc6vboxsync if (VideoRecContextInit(mpVideoRecContext, strVideoCaptureFile,
4bb5cfa1f4d9e95d7d34b5d6ede18d9f4d433bc6vboxsync LogFlow(("Failed to initialize video recording context\n"));
6f045c8e519b0f50a4c2eb2906e5f5e2c4679fa8vboxsync /* All secondary monitors are disabled at startup. */
6f045c8e519b0f50a4c2eb2906e5f5e2c4679fa8vboxsync maFramebuffers[ul].flags = maFramebuffers[ul].fDisabled? VBVA_SCREEN_F_DISABLED: 0;
b6517c5cc3b7a38889416706905a3cf2fd010785vboxsync maFramebuffers[ul].u32ResizeStatus = ResizeStatus_Void;
6f045c8e519b0f50a4c2eb2906e5f5e2c4679fa8vboxsync memset (&maFramebuffers[ul].dirtyRect, 0 , sizeof (maFramebuffers[ul].dirtyRect));
b6517c5cc3b7a38889416706905a3cf2fd010785vboxsync memset (&maFramebuffers[ul].pendingResize, 0 , sizeof (maFramebuffers[ul].pendingResize));
6f045c8e519b0f50a4c2eb2906e5f5e2c4679fa8vboxsync memset (&maFramebuffers[ul].vbvaSkippedRect, 0, sizeof (maFramebuffers[ul].vbvaSkippedRect));
6f045c8e519b0f50a4c2eb2906e5f5e2c4679fa8vboxsync#endif /* VBOX_WITH_HGSMI */
6f045c8e519b0f50a4c2eb2906e5f5e2c4679fa8vboxsync // register listener for state change events
6f045c8e519b0f50a4c2eb2906e5f5e2c4679fa8vboxsync eventTypes.push_back(VBoxEventType_OnStateChanged);
6f045c8e519b0f50a4c2eb2906e5f5e2c4679fa8vboxsync es->RegisterListener(this, ComSafeArrayAsInParam(eventTypes), true);
6f045c8e519b0f50a4c2eb2906e5f5e2c4679fa8vboxsync /* Confirm a successful initialization */
b6517c5cc3b7a38889416706905a3cf2fd010785vboxsync * Uninitializes the instance and sets the ready flag to FALSE.
1313e5cbe01a41e7ccb1499d2d73c455a2495955vboxsync * Called either from FinalRelease() or by the parent when it gets destroyed.
1313e5cbe01a41e7ccb1499d2d73c455a2495955vboxsync /* Enclose the state transition Ready->InUninit->NotReady */
6f045c8e519b0f50a4c2eb2906e5f5e2c4679fa8vboxsync * Register the SSM methods. Called by the power up thread to be able to
b6517c5cc3b7a38889416706905a3cf2fd010785vboxsync /* Version 2 adds width and height of the framebuffer; version 3 adds
b6517c5cc3b7a38889416706905a3cf2fd010785vboxsync * the framebuffer offset in the virtual desktop and the framebuffer flags.
b6517c5cc3b7a38889416706905a3cf2fd010785vboxsync int rc = SSMR3RegisterExternal(pUVM, "DisplayData", 0, sSSMDisplayVer3,
b6517c5cc3b7a38889416706905a3cf2fd010785vboxsync mcMonitors * sizeof(uint32_t) * 8 + sizeof(uint32_t),
6f045c8e519b0f50a4c2eb2906e5f5e2c4679fa8vboxsync * Register loaders for old saved states where iInstance was
6f045c8e519b0f50a4c2eb2906e5f5e2c4679fa8vboxsync * 3 * sizeof(uint32_t *) due to a code mistake.
b6517c5cc3b7a38889416706905a3cf2fd010785vboxsync rc = SSMR3RegisterExternal(pUVM, "DisplayData", 12 /*uInstance*/, sSSMDisplayVer, 0 /*cbGuess*/,
b6517c5cc3b7a38889416706905a3cf2fd010785vboxsync rc = SSMR3RegisterExternal(pUVM, "DisplayData", 24 /*uInstance*/, sSSMDisplayVer, 0 /*cbGuess*/,
b6517c5cc3b7a38889416706905a3cf2fd010785vboxsync /* uInstance is an arbitrary value greater than 1024. Such a value will ensure a quick seek in saved state file. */
b6517c5cc3b7a38889416706905a3cf2fd010785vboxsync rc = SSMR3RegisterExternal(pUVM, "DisplayScreenshot", 1100 /*uInstance*/, sSSMDisplayScreenshotVer, 0 /*cbGuess*/,
switch (aType)
mfMachineRunning = true;
mfMachineRunning = false;
AssertFailed();
return S_OK;
if (!finished)
return VINF_VGA_RESIZE_IN_PROGRESS;
return VINF_SUCCESS;
return VINF_SUCCESS;
mLastWidth = w;
mLastHeight = h;
switch (bpp)
return VINF_VGA_RESIZE_IN_PROGRESS;
return rc;
return VINF_SUCCESS;
unsigned uScreenId;
bool f = ASMAtomicCmpXchgU32 (&pFBInfo->u32ResizeStatus, ResizeStatus_Void, ResizeStatus_UpdateDisplayData);
pFBInfo->pendingResize.cbLine, pFBInfo->pendingResize.w, pFBInfo->pendingResize.h, pFBInfo->pendingResize.flags);
#ifdef DEBUG_sunlover
if (!g_stam)
if (is3denabled)
if (pVMMDev)
pVMMDev->hgcmHostCall("VBoxSharedCrOpenGL", SHCRGL_HOST_FN_SCREEN_CHANGED, SHCRGL_CPARMS_SCREEN_CHANGED, &parm);
if (*px < 0)
*px = 0;
if (*py < 0)
*py = 0;
unsigned mapCoordsToScreen(DISPLAYFBINFO *pInfos, unsigned cInfos, int *px, int *py, int *pw, int *ph)
unsigned uScreenId;
LogSunlover ((" [%d] %d,%d %dx%d\n", uScreenId, pInfo->xOrigin, pInfo->yOrigin, pInfo->w, pInfo->h));
uScreenId = 0;
return uScreenId;
#ifdef DEBUG_sunlover
#ifdef DEBUG_sunlover
#ifndef VBOX_WITH_HGSMI
if (!mfVideoAccelEnabled)
if (!mpDrv)
* sizeof (RTRECT));
if (!pVisibleRegion)
return VERR_NO_TMP_MEMORY;
unsigned uScreenId;
if (mpDrv)
uint32_t i;
for (i = 0; i < cRect; i++)
return VINF_SUCCESS;
return VERR_NOT_SUPPORTED;
typedef struct _VBVADIRTYREGION
unsigned cMonitors;
static void vbvaRgnInit (VBVADIRTYREGION *prgn, DISPLAYFBINFO *paFramebuffers, unsigned cMonitors, Display *pd, PPDMIDISPLAYPORT pp)
unsigned uScreenId;
prgn->pPort->pfnUpdateDisplayRect (prgn->pPort, pFBInfo->dirtyRect.xLeft, pFBInfo->dirtyRect.yTop, w, h);
bool fVideoAccelEnabled,
bool fVideoAccelVRDP,
unsigned cFBInfos)
if (pVbvaMemory)
if (fVideoAccelEnabled)
if (fVideoAccelVRDP)
unsigned uScreenId;
#ifdef VBOX_WITH_HGSMI
bool fVideoAccelVRDP,
if (fVideoAccelVRDP)
LogRelFlowFunc((" fu32HostEvents = 0x%08X, fu32SupportedOrders = 0x%08X\n", fu32HostEvents, fu32SupportedOrders));
bool fVideoAccelVRDP,
unsigned cFBInfos)
unsigned uScreenId;
int rc;
vbvaLock();
vbvaUnlock();
return rc;
if (!VideoAccelAllowed ())
return VERR_NOT_SUPPORTED;
if (!mfMachineRunning)
if (fEnable)
return rc;
return rc;
if (mfVideoAccelEnabled)
videoAccelFlush ();
mfVideoAccelEnabled = false;
if (pVMMDev)
if (pVMMDevPort)
if (fEnable)
mfVideoAccelEnabled = true;
vbvaSetMemoryFlags(mpVbvaMemory, mfVideoAccelEnabled, mfVideoAccelVRDP, mfu32SupportedOrders, maFramebuffers, mcMonitors);
mfu32PendingVideoAccelDisable = false;
return rc;
vbvaLock();
int c = fEnable?
Assert (c >= 0);
mfVideoAccelVRDP = false;
mfu32SupportedOrders = 0;
vbvaSetMemoryFlags (mpVbvaMemory, mfVideoAccelEnabled, mfVideoAccelVRDP, mfu32SupportedOrders, maFramebuffers, mcMonitors);
#ifdef VBOX_WITH_HGSMI
&& !mfVideoAccelVRDP)
mfVideoAccelVRDP = true;
mfu32SupportedOrders = ~0;
vbvaSetMemoryFlags (mpVbvaMemory, mfVideoAccelEnabled, mfVideoAccelVRDP, mfu32SupportedOrders, maFramebuffers, mcMonitors);
#ifdef VBOX_WITH_HGSMI
vbvaUnlock();
if (i32Diff <= 0)
static bool vbvaPartialRead (uint8_t **ppu8, uint32_t *pcb, uint32_t cbRecord, VBVAMEMORY *pVbvaMemory)
if (*ppu8)
if (!pu8New)
cbRecord));
if (*ppu8)
*pcb = 0;
#ifdef DEBUG_sunlover
#ifdef DEBUG_sunlover
if (mcbVbvaPartial)
LogFlowFunc (("continue partial record mcbVbvaPartial = %d cbRecord 0x%08X, first = %d, free = %d\n",
mcbVbvaPartial = 0;
#ifdef DEBUG_sunlover
LogFlowFunc (("started partial record mcbVbvaPartial = 0x%08X cbRecord 0x%08X, first = %d, free = %d\n",
if (cbRecord)
if (!dst)
#ifdef DEBUG_sunlover
#ifdef DEBUG_sunlover
#ifdef DEBUG_sunlover
mcbVbvaPartial = 0;
vbvaLock();
vbvaUnlock();
#ifdef DEBUG_sunlover_2
if (!mfVideoAccelEnabled)
#ifdef DEBUG_sunlover_2
mpVbvaMemory->indexRecordFirst, mpVbvaMemory->indexRecordFree, mpVbvaMemory->off32Data, mpVbvaMemory->off32Free));
unsigned uScreenId;
Log(("Display::VideoAccelFlush: unable to fetch command. off32Data = %d, off32Free = %d. Disabling VBVA!!!\n",
if (cbCmd != 0)
#ifdef DEBUG_sunlover
int x = phdr->x;
int y = phdr->y;
int w = phdr->w;
int h = phdr->h;
vbvaLock();
else if (mfPendingVideoAccelEnable)
if (mfMachineRunning)
mfPendingVideoAccelEnable = false;
if (mfVideoAccelEnabled)
videoAccelFlush ();
vbvaUnlock();
return rc;
return E_INVALIDARG;
if (aWidth)
if (aHeight)
if (aBitsPerPixel)
return S_OK;
if (is3denabled)
if (pVMMDev)
vrc = pVMMDev->hgcmHostCall("VBoxSharedCrOpenGL", SHCRGL_HOST_FN_SCREEN_CHANGED, SHCRGL_CPARMS_SCREEN_CHANGED, &parm);
return S_OK;
return E_INVALIDARG;
if (*aFramebuffer)
if (aXOrigin)
if (aYOrigin)
return S_OK;
if (!width)
if (!height)
if (!bpp)
return E_INVALIDARG;
return E_INVALIDARG;
if (pVMMDev)
if (pVMMDevPort)
return S_OK;
if (pVMMDev)
if (pVMMDevPort)
return S_OK;
int Display::displayTakeScreenshotEMT(Display *pDisplay, ULONG aScreenId, uint8_t **ppu8Data, size_t *pcbData, uint32_t *pu32Width, uint32_t *pu32Height)
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 displayTakeScreenshot(PUVM pUVM, Display *pDisplay, struct DRVMAINDISPLAY *pDrv, ULONG aScreenId,
while (cRetries-- > 0)
src,
return vrc;
return rc;
if (!pu8Data)
return E_OUTOFMEMORY;
while (cPixels)
cPixels--;
return rc;
if (!pu8Data)
return E_OUTOFMEMORY;
if (pu8PNG)
if (pu8PNG)
return rc;
int Display::drawToScreenEMT(Display *pDisplay, ULONG aScreenId, BYTE *address, ULONG x, ULONG y, ULONG width, ULONG height)
rc = pDisplay->mpDrv->pUpPort->pfnDisplayBlt(pDisplay->mpDrv->pUpPort, address, x, y, width, height);
xSrc = x;
ySrc = y;
return rc;
return rc;
unsigned uScreenId;
if (!fUpdateAll)
/* pdm.h says that this has to be called from the EMT thread */
int rcVBox = VMR3ReqCallVoidWaitU(ptrVM.rawUVM(), VMCPUID_ANY, (PFNRT)Display::InvalidateAndUpdateEMT,
return rc;
return S_OK;
#ifdef VBOX_WITH_VIDEOHWACCEL
return S_OK;
return E_NOTIMPL;
if (is3denabled)
if (pVMMDev)
pVMMDev->hgcmHostCall("VBoxSharedCrOpenGL", SHCRGL_HOST_FN_VIEWPORT_CHANGED, SHCRGL_CPARMS_VIEWPORT_CHANGED, aParms);
return S_OK;
if (!mpDrv)
#ifdef VBOX_STRICT
if (pFramebuffer)
#ifdef VBOX_WITH_CRHGSMI
if (pVMMDev)
unsigned uScreenId)
#if defined(VBOX_WITH_CROGL)
if (is3denabled)
pFBInfo->w,
pFBInfo->h,
return VINF_SUCCESS;
return pDrv->pDisplay->handleDisplayResize(VBOX_VIDEO_PRIMARY_SCREEN, bpp, pvVRAM, cbLine, cx, cy, VBVA_SCREEN_F_ACTIVE);
#ifdef DEBUG_sunlover
#ifdef DEBUG_sunlover
#ifdef DEBUG_sunlover_2
bool fNoUpdate = false; /* Do not update the display if any of the framebuffers is being resized. */
unsigned uScreenId;
fNoUpdate = true;
if (!fNoUpdate)
#ifdef VBOX_WITH_VPX
int rc;
switch (ulBitsPerPixel)
#ifdef DEBUG_sunlover
#ifdef DEBUG_sunlover_2
DECLCALLBACK(void) Display::displayLFBModeChangeCallback(PPDMIDISPLAYCONNECTOR pInterface, bool fEnabled)
/* The LFBModeChange function is called under DevVGA lock. Postpone disabling VBVA, do it in the refresh timer. */
DECLCALLBACK(void) Display::displayProcessAdapterDataCallback(PPDMIDISPLAYCONNECTOR pInterface, void *pvVRAM, uint32_t u32VRAMSize)
#ifndef VBOX_WITH_HGSMI
LogRel(("VBoxVideo: Guest adapter information %s invalid length %d!!!\n", "DISPLAY", pHdr->u16Length));
LogRelFlow(("VBOX_VIDEO_INFO_TYPE_DISPLAY: %d: at 0x%08X, size 0x%08X, info 0x%08X\n", pDisplay->u32Index, pDisplay->u32Offset, pDisplay->u32FramebufferSize, pDisplay->u32InformationSize));
LogRel(("VBoxVideo: Guest adapter information %s invalid length %d!!!\n", "CONF32", pHdr->u16Length));
else if (pHdr->u8Type != VBOX_VIDEO_INFO_TYPE_NV_HEAP) /** @todo why is Additions/WINNT/Graphics/Miniport/VBoxVideo.cpp pushing this to us? */
LogRel(("Guest adapter information contains unsupported type %d. The block has been skipped.\n", pHdr->u8Type));
DECLCALLBACK(void) Display::displayProcessDisplayDataCallback(PPDMIDISPLAYCONNECTOR pInterface, void *pvVRAM, unsigned uScreenId)
LogRel(("VBoxVideo: Guest display information %s invalid length %d!!!\n", "SCREEN", pHdr->u16Length));
LogRelFlow(("VBOX_VIDEO_INFO_TYPE_SCREEN: (%p) %d: at %d,%d, linesize 0x%X, size %dx%d, bpp %d, flags 0x%02X\n",
pHdr, uScreenId, pScreen->xOrigin, pScreen->yOrigin, pScreen->u32LineSize, pScreen->u16Width, pScreen->u16Height, pScreen->bitsPerPixel, pScreen->u8Flags));
pDrv->pDisplay->handleDisplayResize(uScreenId, pScreen->bitsPerPixel, (uint8_t *)pvVRAM + pFBInfo->u32Offset, pScreen->u32LineSize, pScreen->u16Width, pScreen->u16Height, VBVA_SCREEN_F_ACTIVE);
LogRel(("VBoxVideo: Guest display information %s invalid length %d!!!\n", "HOST_EVENTS", pHdr->u16Length));
pHostEvents));
LogRel(("VBoxVideo: Guest adapter information %s invalid length %d!!!\n", "LINK", pHdr->u16Length));
#ifdef VBOX_WITH_VIDEOHWACCEL
#ifdef DEBUG_misha
DECLCALLBACK(void) Display::displayVHWACommandProcess(PPDMIDISPLAYCONNECTOR pInterface, PVBOXVHWACMD pCommand)
#ifdef VBOX_WITH_CRHGSMI
void Display::handleCrHgsmiCommandCompletion(int32_t result, uint32_t u32Function, PVBOXHGCMSVCPARM pParam)
mpDrv->pVBVACallbacks->pfnCrHgsmiCommandCompleteAsync(mpDrv->pVBVACallbacks, (PVBOXVDMACMD_CHROMIUM_CMD)pParam->u.pointer.addr, result);
void Display::handleCrHgsmiControlCompletion(int32_t result, uint32_t u32Function, PVBOXHGCMSVCPARM pParam)
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)
if (mhCrOglSvc)
if (pVMMDev)
void Display::handleCrHgsmiControlProcess(PPDMIDISPLAYCONNECTOR pInterface, PVBOXVDMACMD_CHROMIUM_CTL pCtl, uint32_t cbCtl)
if (mhCrOglSvc)
if (pVMMDev)
rc = pVMMDev->hgcmHostFastCallAsync(mhCrOglSvc, SHCRGL_HOST_FN_CRHGSMI_CTL, &parm, Display::displayCrHgsmiControlCompletion, this);
DECLCALLBACK(void) Display::displayCrHgsmiCommandProcess(PPDMIDISPLAYCONNECTOR pInterface, PVBOXVDMACMD_CHROMIUM_CMD pCmd, uint32_t cbCmd)
DECLCALLBACK(void) Display::displayCrHgsmiControlProcess(PPDMIDISPLAYCONNECTOR pInterface, PVBOXVDMACMD_CHROMIUM_CTL pCmd, uint32_t cbCmd)
DECLCALLBACK(void) Display::displayCrHgsmiCommandCompletion(int32_t result, uint32_t u32Function, PVBOXHGCMSVCPARM pParam, void *pvContext)
DECLCALLBACK(void) Display::displayCrHgsmiControlCompletion(int32_t result, uint32_t u32Function, PVBOXHGCMSVCPARM pParam, void *pvContext)
#ifdef VBOX_WITH_HGSMI
DECLCALLBACK(int) Display::displayVBVAEnable(PPDMIDISPLAYCONNECTOR pInterface, unsigned uScreenId, PVBVAHOSTFLAGS pHostFlags)
vbvaSetMemoryFlagsHGSMI(uScreenId, pThis->mfu32SupportedOrders, pThis->mfVideoAccelVRDP, &pThis->maFramebuffers[uScreenId]);
return VINF_SUCCESS;
DECLCALLBACK(void) Display::displayVBVADisable(PPDMIDISPLAYCONNECTOR pInterface, unsigned uScreenId)
pFBInfo->w = 0;
pFBInfo->h = 0;
DECLCALLBACK(void) Display::displayVBVAUpdateBegin(PPDMIDISPLAYCONNECTOR pInterface, unsigned uScreenId)
vbvaSetMemoryFlagsAllHGSMI(pThis->mfu32SupportedOrders, pThis->mfVideoAccelVRDP, pThis->maFramebuffers, pThis->mcMonitors);
DECLCALLBACK(void) Display::displayVBVAUpdateProcess(PPDMIDISPLAYCONNECTOR pInterface, unsigned uScreenId, const PVBVACMDHDR pCmd, size_t cbCmd)
LogFlowFunc(("uScreenId %d pCmd %p cbCmd %d, @%d,%d %dx%d\n", uScreenId, pCmd, cbCmd, pCmd->x, pCmd->y, pCmd->w, pCmd->h));
DECLCALLBACK(void) Display::displayVBVAUpdateEnd(PPDMIDISPLAYCONNECTOR pInterface, unsigned uScreenId, int32_t x, int32_t y, uint32_t cx, uint32_t cy)
#ifdef DEBUG_sunlover
static void logVBVAResize(const PVBVAINFOVIEW pView, const PVBVAINFOSCREEN pScreen, const DISPLAYFBINFO *pFBInfo)
" pFBInfo->pendingResize.cbLine 0x%08X\n"
pFBInfo->w,
pFBInfo->h,
DECLCALLBACK(int) Display::displayVBVAResize(PPDMIDISPLAYCONNECTOR pInterface, const PVBVAINFOVIEW pView, const PVBVAINFOSCREEN pScreen, void *pvVRAM)
return VINF_SUCCESS;
if (fNewOrigin)
if (is3denabled)
if (pVMMDev)
pVMMDev->hgcmHostCall("VBoxSharedCrOpenGL", SHCRGL_HOST_FN_SCREEN_CHANGED, SHCRGL_CPARMS_SCREEN_CHANGED, &parm);
if (!fResize)
if (fNewOrigin)
return VINF_SUCCESS;
/* If no framebuffer, the resize will be done later when a new framebuffer will be set in changeFramebuffer. */
return VINF_SUCCESS;
DECLCALLBACK(int) Display::displayVBVAMousePointerShape(PPDMIDISPLAYCONNECTOR pInterface, bool fVisible, bool fAlpha,
const void *pvShape)
if (pvShape)
if (pvShape)
return VINF_SUCCESS;
return NULL;
#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
return VINF_SUCCESS;
sizeof(DRVMAINDISPLAY),
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,