DisplayImpl.h revision 4da5064278fde975a71aa6b7f331e0e0278a1eb0
/* $Id$ */
/** @file
* VirtualBox COM class implementation
*/
/*
* Copyright (C) 2006-2014 Oracle Corporation
*
* This file is part of VirtualBox Open Source Edition (OSE), as
* available from http://www.virtualbox.org. This file is free software;
* you can redistribute it and/or modify it under the terms of the GNU
* General Public License (GPL) as published by the Free Software
* Foundation, in version 2 as it comes in the "COPYING" file of the
* VirtualBox OSE distribution. VirtualBox OSE is distributed in the
* hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
*/
#ifndef ____H_DISPLAYIMPL
#define ____H_DISPLAYIMPL
#include "SchemaDefs.h"
#include <iprt/semaphore.h>
#include <VBox/vmm/pdmdrv.h>
#include <VBox/VMMDev.h>
#include <VBox/VBoxVideo.h>
#include <VBox/vmm/pdmifs.h>
#include "DisplayWrap.h"
#ifdef VBOX_WITH_CROGL
# include <VBox/HostServices/VBoxCrOpenGLSvc.h>
#endif
#include "DisplaySourceBitmapWrap.h"
class Console;
struct VIDEORECCONTEXT;
typedef struct _DISPLAYFBINFO
{
uint32_t u32Offset;
uint32_t u32MaxFramebufferSize;
uint32_t u32InformationSize;
ComPtr<IFramebuffer> pFramebuffer;
ComPtr<IDisplaySourceBitmap> pSourceBitmap;
bool fDisabled;
FramebufferUpdateMode_T enmFramebufferUpdateMode;
struct
{
ComPtr<IDisplaySourceBitmap> pSourceBitmap;
uint8_t *pu8Address;
uint32_t cbLine;
} updateImage;
LONG xOrigin;
LONG yOrigin;
ULONG w;
ULONG h;
uint16_t u16BitsPerPixel;
uint8_t *pu8FramebufferVRAM;
uint32_t u32LineSize;
uint16_t flags;
VBOXVIDEOINFOHOSTEVENTS *pHostEvents;
/** The framebuffer has default format and must be updates immediately. */
bool fDefaultFormat;
struct
{
/* The rectangle that includes all dirty rectangles. */
int32_t xLeft;
int32_t xRight;
int32_t yTop;
int32_t yBottom;
} dirtyRect;
#ifdef VBOX_WITH_HGSMI
bool fVBVAEnabled;
bool fVBVAForceResize;
bool fRenderThreadMode;
PVBVAHOSTFLAGS pVBVAHostFlags;
#endif /* VBOX_WITH_HGSMI */
#ifdef VBOX_WITH_CROGL
struct
{
bool fPending;
ULONG x;
ULONG y;
ULONG width;
ULONG height;
} pendingViewportInfo;
#endif /* VBOX_WITH_CROGL */
} DISPLAYFBINFO;
class DisplayMouseInterface
{
public:
virtual HRESULT i_getScreenResolution(ULONG cScreen, ULONG *pcx,
ULONG *pcy, ULONG *pcBPP, LONG *pXOrigin, LONG *pYOrigin) = 0;
virtual void i_getFramebufferDimensions(int32_t *px1, int32_t *py1,
int32_t *px2, int32_t *py2) = 0;
};
class VMMDev;
class ATL_NO_VTABLE Display :
public DisplayWrap,
public DisplayMouseInterface
{
public:
DECLARE_EMPTY_CTOR_DTOR(Display)
HRESULT FinalConstruct();
void FinalRelease();
// public initializer/uninitializer for internal purposes only
HRESULT init(Console *aParent);
void uninit();
int i_registerSSM(PUVM pUVM);
// public methods only for internal purposes
int i_handleDisplayResize(unsigned uScreenId, uint32_t bpp, void *pvVRAM, uint32_t cbLine,
uint32_t w, uint32_t h, uint16_t flags);
void i_handleDisplayUpdateLegacy(int x, int y, int cx, int cy);
void i_handleDisplayUpdate(unsigned uScreenId, int x, int y, int w, int h);
#ifdef VBOX_WITH_VIDEOHWACCEL
int i_handleVHWACommandProcess(PVBOXVHWACMD pCommand);
#endif
#ifdef VBOX_WITH_CRHGSMI
void i_handleCrHgsmiCommandCompletion(int32_t result, uint32_t u32Function, PVBOXHGCMSVCPARM pParam);
void i_handleCrHgsmiControlCompletion(int32_t result, uint32_t u32Function, PVBOXHGCMSVCPARM pParam);
void i_handleCrHgsmiCommandProcess(PVBOXVDMACMD_CHROMIUM_CMD pCmd, uint32_t cbCmd);
void i_handleCrHgsmiControlProcess(PVBOXVDMACMD_CHROMIUM_CTL pCtl, uint32_t cbCtl);
#endif
#if defined(VBOX_WITH_HGCM) && defined(VBOX_WITH_CROGL)
int i_handleCrHgcmCtlSubmit(struct VBOXCRCMDCTL* pCmd, uint32_t cbCmd,
PFNCRCTLCOMPLETION pfnCompletion,
void *pvCompletion);
void i_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);
bool i_handleCrVRecScreenshotBegin(uint32_t uScreen, uint64_t u64TimeStamp);
void i_handleCrVRecScreenshotEnd(uint32_t uScreen, uint64_t u64TimeStamp);
void i_handleVRecCompletion();
#endif
int i_notifyCroglResize(const PVBVAINFOVIEW pView, const PVBVAINFOSCREEN pScreen, void *pvVRAM);
int i_handleSetVisibleRegion(uint32_t cRect, PRTRECT pRect);
int i_handleQueryVisibleRegion(uint32_t *pcRect, PRTRECT pRect);
int i_VideoAccelEnable(bool fEnable, VBVAMEMORY *pVbvaMemory);
void i_VideoAccelFlush(void);
bool i_VideoAccelAllowed(void);
void i_VideoAccelVRDP(bool fEnable);
int i_VideoCaptureStart();
void i_VideoCaptureStop();
int i_VideoCaptureEnableScreens(ComSafeArrayIn(BOOL, aScreens));
void i_notifyPowerDown(void);
// DisplayMouseInterface methods
virtual HRESULT i_getScreenResolution(ULONG cScreen, ULONG *pcx,
ULONG *pcy, ULONG *pcBPP, LONG *pXOrigin, LONG *pYOrigin)
{
return getScreenResolution(cScreen, pcx, pcy, pcBPP, pXOrigin, pYOrigin);
}
virtual void i_getFramebufferDimensions(int32_t *px1, int32_t *py1,
int32_t *px2, int32_t *py2);
static const PDMDRVREG DrvReg;
private:
// Wrapped IDisplay properties
// Wrapped IDisplay methods
virtual HRESULT getScreenResolution(ULONG aScreenId,
ULONG *aWidth,
ULONG *aHeight,
ULONG *aBitsPerPixel,
LONG *aXOrigin,
LONG *aYOrigin);
virtual HRESULT attachFramebuffer(ULONG aScreenId,
const ComPtr<IFramebuffer> &aFramebuffer);
virtual HRESULT detachFramebuffer(ULONG aScreenId);
virtual HRESULT queryFramebuffer(ULONG aScreenId,
ComPtr<IFramebuffer> &aFramebuffer);
virtual HRESULT setVideoModeHint(ULONG aDisplay,
BOOL aEnabled,
BOOL aChangeOrigin,
LONG aOriginX,
LONG aOriginY,
ULONG aWidth,
ULONG aHeight,
ULONG aBitsPerPixel);
virtual HRESULT setSeamlessMode(BOOL aEnabled);
virtual HRESULT takeScreenShot(ULONG aScreenId,
BYTE *aAddress,
ULONG aWidth,
ULONG aHeight,
BitmapFormat_T aBitmapFormat);
virtual HRESULT takeScreenShotToArray(ULONG aScreenId,
ULONG aWidth,
ULONG aHeight,
BitmapFormat_T aBitmapFormat,
std::vector<BYTE> &aScreenData);
virtual HRESULT drawToScreen(ULONG aScreenId,
BYTE *aAddress,
ULONG aX,
ULONG aY,
ULONG aWidth,
ULONG aHeight);
virtual HRESULT invalidateAndUpdate();
virtual HRESULT invalidateAndUpdateScreen(ULONG aScreenId);
virtual HRESULT completeVHWACommand(BYTE *aCommand);
virtual HRESULT viewportChanged(ULONG aScreenId,
ULONG aX,
ULONG aY,
ULONG aWidth,
ULONG aHeight);
virtual HRESULT querySourceBitmap(ULONG aScreenId,
ComPtr<IDisplaySourceBitmap> &aDisplaySourceBitmap);
virtual HRESULT setFramebufferUpdateMode(ULONG aScreenId,
FramebufferUpdateMode_T aFramebufferUpdateMode);
// Wrapped IEventListener properties
// Wrapped IEventListener methods
virtual HRESULT handleEvent(const ComPtr<IEvent> &aEvent);
// other internal methods
HRESULT takeScreenShotWorker(ULONG aScreenId,
BYTE *aAddress,
ULONG aWidth,
ULONG aHeight,
BitmapFormat_T aBitmapFormat,
ULONG *pcbOut);
#ifdef VBOX_WITH_CRHGSMI
void i_setupCrHgsmiData(void);
void i_destructCrHgsmiData(void);
#endif
#if defined(VBOX_WITH_HGCM) && defined(VBOX_WITH_CROGL)
int i_crViewportNotify(ULONG aScreenId, ULONG x, ULONG y, ULONG width, ULONG height);
#endif
static DECLCALLBACK(void*) i_drvQueryInterface(PPDMIBASE pInterface, const char *pszIID);
static DECLCALLBACK(int) i_drvConstruct(PPDMDRVINS pDrvIns, PCFGMNODE pCfg, uint32_t fFlags);
static DECLCALLBACK(void) i_drvDestruct(PPDMDRVINS pDrvIns);
static DECLCALLBACK(int) i_displayResizeCallback(PPDMIDISPLAYCONNECTOR pInterface, uint32_t bpp, void *pvVRAM,
uint32_t cbLine, uint32_t cx, uint32_t cy);
static DECLCALLBACK(void) i_displayUpdateCallback(PPDMIDISPLAYCONNECTOR pInterface,
uint32_t x, uint32_t y, uint32_t cx, uint32_t cy);
static DECLCALLBACK(void) i_displayRefreshCallback(PPDMIDISPLAYCONNECTOR pInterface);
static DECLCALLBACK(void) i_displayResetCallback(PPDMIDISPLAYCONNECTOR pInterface);
static DECLCALLBACK(void) i_displayLFBModeChangeCallback(PPDMIDISPLAYCONNECTOR pInterface, bool fEnabled);
static DECLCALLBACK(void) i_displayProcessAdapterDataCallback(PPDMIDISPLAYCONNECTOR pInterface,
void *pvVRAM, uint32_t u32VRAMSize);
static DECLCALLBACK(void) i_displayProcessDisplayDataCallback(PPDMIDISPLAYCONNECTOR pInterface,
void *pvVRAM, unsigned uScreenId);
#ifdef VBOX_WITH_VIDEOHWACCEL
static DECLCALLBACK(int) i_displayVHWACommandProcess(PPDMIDISPLAYCONNECTOR pInterface, PVBOXVHWACMD pCommand);
#endif
#ifdef VBOX_WITH_CRHGSMI
static DECLCALLBACK(void) i_displayCrHgsmiCommandProcess(PPDMIDISPLAYCONNECTOR pInterface,
PVBOXVDMACMD_CHROMIUM_CMD pCmd, uint32_t cbCmd);
static DECLCALLBACK(void) i_displayCrHgsmiControlProcess(PPDMIDISPLAYCONNECTOR pInterface, PVBOXVDMACMD_CHROMIUM_CTL pCtl,
uint32_t cbCtl);
static DECLCALLBACK(void) i_displayCrHgsmiCommandCompletion(int32_t result, uint32_t u32Function, PVBOXHGCMSVCPARM pParam,
void *pvContext);
static DECLCALLBACK(void) i_displayCrHgsmiControlCompletion(int32_t result, uint32_t u32Function, PVBOXHGCMSVCPARM pParam,
void *pvContext);
#endif
#if defined(VBOX_WITH_HGCM) && defined(VBOX_WITH_CROGL)
static DECLCALLBACK(int) i_displayCrHgcmCtlSubmit(PPDMIDISPLAYCONNECTOR pInterface,
struct VBOXCRCMDCTL* pCmd, uint32_t cbCmd,
PFNCRCTLCOMPLETION pfnCompletion,
void *pvCompletion);
static DECLCALLBACK(void) i_displayCrHgcmCtlSubmitCompletion(int32_t result, uint32_t u32Function, PVBOXHGCMSVCPARM pParam,
void *pvContext);
#endif
#ifdef VBOX_WITH_HGSMI
static DECLCALLBACK(int) i_displayVBVAEnable(PPDMIDISPLAYCONNECTOR pInterface, unsigned uScreenId,
PVBVAHOSTFLAGS pHostFlags, bool fRenderThreadMode);
static DECLCALLBACK(void) i_displayVBVADisable(PPDMIDISPLAYCONNECTOR pInterface, unsigned uScreenId);
static DECLCALLBACK(void) i_displayVBVAUpdateBegin(PPDMIDISPLAYCONNECTOR pInterface, unsigned uScreenId);
static DECLCALLBACK(void) i_displayVBVAUpdateProcess(PPDMIDISPLAYCONNECTOR pInterface, unsigned uScreenId,
const PVBVACMDHDR pCmd, size_t cbCmd);
static DECLCALLBACK(void) i_displayVBVAUpdateEnd(PPDMIDISPLAYCONNECTOR pInterface, unsigned uScreenId, int32_t x, int32_t y,
uint32_t cx, uint32_t cy);
static DECLCALLBACK(int) i_displayVBVAResize(PPDMIDISPLAYCONNECTOR pInterface, const PVBVAINFOVIEW pView,
const PVBVAINFOSCREEN pScreen, void *pvVRAM);
static DECLCALLBACK(int) i_displayVBVAMousePointerShape(PPDMIDISPLAYCONNECTOR pInterface, bool fVisible, bool fAlpha,
uint32_t xHot, uint32_t yHot, uint32_t cx, uint32_t cy,
const void *pvShape);
#endif
#if defined(VBOX_WITH_HGCM) && defined(VBOX_WITH_CROGL)
static DECLCALLBACK(void) i_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);
static DECLCALLBACK(bool) i_displayCrVRecScreenshotBegin(void *pvCtx, uint32_t uScreen, uint64_t u64TimeStamp);
static DECLCALLBACK(void) i_displayCrVRecScreenshotEnd(void *pvCtx, uint32_t uScreen, uint64_t u64TimeStamp);
static DECLCALLBACK(void) i_displayVRecCompletion(struct VBOXCRCMDCTL* pCmd, uint32_t cbCmd, int rc, void *pvCompletion);
#endif
static DECLCALLBACK(void) i_displayCrCmdFree(struct VBOXCRCMDCTL* pCmd, uint32_t cbCmd, int rc, void *pvCompletion);
static DECLCALLBACK(void) i_displaySSMSaveScreenshot(PSSMHANDLE pSSM, void *pvUser);
static DECLCALLBACK(int) i_displaySSMLoadScreenshot(PSSMHANDLE pSSM, void *pvUser, uint32_t uVersion, uint32_t uPass);
static DECLCALLBACK(void) i_displaySSMSave(PSSMHANDLE pSSM, void *pvUser);
static DECLCALLBACK(int) i_displaySSMLoad(PSSMHANDLE pSSM, void *pvUser, uint32_t uVersion, uint32_t uPass);
Console * const mParent;
/** Pointer to the associated display driver. */
struct DRVMAINDISPLAY *mpDrv;
/** Pointer to the device instance for the VMM Device. */
PPDMDEVINS mpVMMDev;
/** Set after the first attempt to find the VMM Device. */
bool mfVMMDevInited;
unsigned mcMonitors;
DISPLAYFBINFO maFramebuffers[SchemaDefs::MaxGuestMonitors];
bool mfSourceBitmapEnabled;
bool volatile fVGAResizing;
VBVAMEMORY *mpVbvaMemory;
bool mfVideoAccelEnabled;
bool mfVideoAccelVRDP;
uint32_t mfu32SupportedOrders;
int32_t volatile mcVideoAccelVRDPRefs;
VBVAMEMORY *mpPendingVbvaMemory;
bool mfPendingVideoAccelEnable;
bool mfMachineRunning;
#ifdef VBOX_WITH_CROGL
bool mfCrOglDataHidden;
#endif
uint8_t *mpu8VbvaPartial;
uint32_t mcbVbvaPartial;
#ifdef VBOX_WITH_CRHGSMI
/* for fast host hgcm calls */
HGCMCVSHANDLE mhCrOglSvc;
RTCRITSECTRW mCrOglLock;
#endif
#ifdef VBOX_WITH_CROGL
CR_MAIN_INTERFACE mCrOglCallbacks;
volatile uint32_t mfCrOglVideoRecState;
CRVBOXHGCMTAKESCREENSHOT mCrOglScreenshotData;
VBOXCRCMDCTL_HGCM mCrOglScreenshotCtl;
#endif
bool i_vbvaFetchCmd(VBVACMDHDR **ppHdr, uint32_t *pcbCmd);
void i_vbvaReleaseCmd(VBVACMDHDR *pHdr, int32_t cbCmd);
void i_handleResizeCompletedEMT(unsigned uScreenId, BOOL fResizeContext);
/* Old guest additions (3.x?) use VMMDev for VBVA and the host VBVA code (VideoAccel*)
* can be executed concurrently by VGA refresh timer and the guest VMMDev request
* in SMP VMs. The lock serialized this.
*/
RTCRITSECT mVBVALock;
volatile uint32_t mfu32PendingVideoAccelDisable;
int i_vbvaLock(void);
void i_vbvaUnlock(void);
public:
bool i_vbvaLockIsOwner(void);
static int i_displayTakeScreenshotEMT(Display *pDisplay, ULONG aScreenId, uint8_t **ppu8Data, size_t *pcbData,
uint32_t *pu32Width, uint32_t *pu32Height);
#if defined(VBOX_WITH_HGCM) && defined(VBOX_WITH_CROGL)
static BOOL i_displayCheckTakeScreenshotCrOgl(Display *pDisplay, ULONG aScreenId, uint8_t *pu8Data,
uint32_t u32Width, uint32_t u32Height);
int i_crCtlSubmit(struct VBOXCRCMDCTL* pCmd, uint32_t cbCmd, PFNCRCTLCOMPLETION pfnCompletion, void *pvCompletion);
int i_crCtlSubmitSync(struct VBOXCRCMDCTL* pCmd, uint32_t cbCmd);
/* copies the given command and submits it asynchronously,
* i.e. the pCmd data may be discarded right after the call returns */
int i_crCtlSubmitAsyncCmdCopy(struct VBOXCRCMDCTL* pCmd, uint32_t cbCmd);
/* performs synchronous request processing if 3D backend has something to display
* this is primarily to work-around 3d<->main thread deadlocks on OSX
* in case of async completion, the command is coppied to the allocated buffer,
* freeded on command completion
* can be used for "notification" commands, when client is not interested in command result,
* that must synchronize with 3D backend only when some 3D data is displayed.
* The routine does NOT provide any info on whether command is processed asynchronously or not */
int i_crCtlSubmitSyncIfHasDataForScreen(uint32_t u32ScreenID, struct VBOXCRCMDCTL* pCmd, uint32_t cbCmd);
#endif
private:
static int i_InvalidateAndUpdateEMT(Display *pDisplay, unsigned uId, bool fUpdateAll);
static int i_drawToScreenEMT(Display *pDisplay, ULONG aScreenId, BYTE *address, ULONG x, ULONG y, ULONG width, ULONG height);
int i_videoAccelRefreshProcess(void);
/* Functions run under VBVA lock. */
int i_videoAccelEnable(bool fEnable, VBVAMEMORY *pVbvaMemory);
int i_videoAccelFlush(void);
#if defined(VBOX_WITH_HGCM) && defined(VBOX_WITH_CROGL)
int i_crOglWindowsShow(bool fShow);
#endif
#ifdef VBOX_WITH_HGSMI
volatile uint32_t mu32UpdateVBVAFlags;
#endif
#ifdef VBOX_WITH_VPX
VIDEORECCONTEXT *mpVideoRecCtx;
bool maVideoRecEnabled[SchemaDefs::MaxGuestMonitors];
#endif
};
/* helper function, code in DisplayResampleImage.cpp */
void gdImageCopyResampled(uint8_t *dst, uint8_t *src,
int dstX, int dstY, int srcX, int srcY,
int dstW, int dstH, int srcW, int srcH);
void BitmapScale32(uint8_t *dst, int dstW, int dstH,
const uint8_t *src, int iDeltaLine, int srcW, int srcH);
/* helper function, code in DisplayPNGUtul.cpp */
int DisplayMakePNG(uint8_t *pu8Data, uint32_t cx, uint32_t cy,
uint8_t **ppu8PNG, uint32_t *pcbPNG, uint32_t *pcxPNG, uint32_t *pcyPNG,
uint8_t fLimitSize);
class ATL_NO_VTABLE DisplaySourceBitmap:
public DisplaySourceBitmapWrap
{
public:
DECLARE_EMPTY_CTOR_DTOR(DisplaySourceBitmap)
HRESULT FinalConstruct();
void FinalRelease();
/* Public initializer/uninitializer for internal purposes only. */
HRESULT init(ComObjPtr<Display> pDisplay, unsigned uScreenId, DISPLAYFBINFO *pFBInfo);
void uninit();
bool i_usesVRAM(void) { return m.pu8Allocated == NULL; }
private:
// wrapped IDisplaySourceBitmap properties
virtual HRESULT getScreenId(ULONG *aScreenId);
// wrapped IDisplaySourceBitmap methods
virtual HRESULT queryBitmapInfo(BYTE **aAddress,
ULONG *aWidth,
ULONG *aHeight,
ULONG *aBitsPerPixel,
ULONG *aBytesPerLine,
ULONG *aPixelFormat);
int initSourceBitmap(unsigned aScreenId, DISPLAYFBINFO *pFBInfo);
struct Data
{
ComObjPtr<Display> pDisplay;
unsigned uScreenId;
DISPLAYFBINFO *pFBInfo;
uint8_t *pu8Allocated;
uint8_t *pu8Address;
ULONG ulWidth;
ULONG ulHeight;
ULONG ulBitsPerPixel;
ULONG ulBytesPerLine;
ULONG ulPixelFormat;
};
Data m;
};
#endif // ____H_DISPLAYIMPL
/* vi: set tabstop=4 shiftwidth=4 expandtab: */