DisplayImpl.cpp revision ed0d9ad011741656c6a8456b97b036e1aa815da2
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync * VBox frontends: Basic Frontend (BFE):
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync * Implementation of Display class
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync * Copyright (C) 2006-2007 Oracle Corporation
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync * This file is part of VirtualBox Open Source Edition (OSE), as
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync * available from http://www.virtualbox.org. This file is free software;
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync * you can redistribute it and/or modify it under the terms of the GNU
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync * General Public License (GPL) as published by the Free Software
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync * Foundation, in version 2 as it comes in the "COPYING" file of the
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync/*******************************************************************************
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync* Structures and Typedefs *
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync*******************************************************************************/
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync * Display driver instance data.
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync /** Pointer to the display object. */
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync /** Pointer to the driver instance structure. */
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync /** Pointer to the keyboard port interface of the driver/device above us. */
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync /** Our display connector interface. */
687794577e2e35c3cae67e692a7f2130d1262a82vboxsync/** Converts PDMIDISPLAYCONNECTOR pointer to a DRVMAINDISPLAY pointer. */
d4a9d525e6f2111d462d2d96462dced6b9ec00efvboxsync#define PDMIDISPLAYCONNECTOR_2_MAINDISPLAY(pInterface) ( (PDRVMAINDISPLAY) ((uintptr_t)pInterface - RT_OFFSETOF(DRVMAINDISPLAY, Connector)) )
702a8ee2dc1de96f2f77e97135015d3e243186fdvboxsync// constructor / destructor
c142e0f462e6c921a73d84ee50f41396b3a99db5vboxsync/////////////////////////////////////////////////////////////////////////////
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync // by default, we have an internal Framebuffer which is
702a8ee2dc1de96f2f77e97135015d3e243186fdvboxsync // NULL, i.e. a black hole for no display output
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync// public methods only for internal purposes
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync/////////////////////////////////////////////////////////////////////////////
9523921c89c66f4bececdbd5ac95aed0039eda1bvboxsync * Handle display resize event.
d4a9d525e6f2111d462d2d96462dced6b9ec00efvboxsync * @returns COM status code
d4a9d525e6f2111d462d2d96462dced6b9ec00efvboxsync * @param w New display width
9523921c89c66f4bececdbd5ac95aed0039eda1bvboxsync * @param h New display height
d4a9d525e6f2111d462d2d96462dced6b9ec00efvboxsync LogFlow(("Display::handleDisplayResize(): w=%d, h=%d\n", w, h));
d4a9d525e6f2111d462d2d96462dced6b9ec00efvboxsync // if there is no Framebuffer, this call is not interesting
d4a9d525e6f2111d462d2d96462dced6b9ec00efvboxsync /* Atomically set the resize status before calling the framebuffer. The new InProgress status will
9523921c89c66f4bececdbd5ac95aed0039eda1bvboxsync * disable access to the VGA device by the EMT thread.
9523921c89c66f4bececdbd5ac95aed0039eda1bvboxsync bool f = ASMAtomicCmpXchgU32 (&mu32ResizeStatus, ResizeStatus_InProgress, ResizeStatus_Void);
ed9d3db07648c7e3a979105c15ad752ee9ea18devboxsync // callback into the Framebuffer to notify it
9523921c89c66f4bececdbd5ac95aed0039eda1bvboxsync LogFlow(("Display::handleDisplayResize: external framebuffer wants us to wait!\n"));
d4a9d525e6f2111d462d2d96462dced6b9ec00efvboxsync /* Note: The previously obtained framebuffer lock must be preserved.
d4a9d525e6f2111d462d2d96462dced6b9ec00efvboxsync * The EMT keeps the framebuffer lock until the resize process completes.
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync /* Set the status so the 'handleResizeCompleted' would work. */
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync f = ASMAtomicCmpXchgU32 (&mu32ResizeStatus, ResizeStatus_UpdateDisplayData, ResizeStatus_InProgress);
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync /* The method also unlocks the framebuffer. */
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync * Framebuffer has been resized.
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync * Read the new display data and unlock the framebuffer.
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync * @thread EMT
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync /* Framebuffer has completed the resize. Update the connector data. */
06ea6bcf23874b662d499b3f130024c98b2dd7a6vboxsync mpDrv->pUpPort->pfnSetRenderVRAM (mpDrv->pUpPort, true);
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync /* Unlock framebuffer. */
702a8ee2dc1de96f2f77e97135015d3e243186fdvboxsync /* Go into non resizing state. */
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync bool f = ASMAtomicCmpXchgU32 (&mu32ResizeStatus, ResizeStatus_Void, ResizeStatus_UpdateDisplayData);
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync * Notification that the framebuffer has completed the
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync * asynchronous resize processing
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync * @returns COM status code
06ea6bcf23874b662d499b3f130024c98b2dd7a6vboxsync // this is only valid for external framebuffers
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync /* Set the flag indicating that the resize has completed and display data need to be updated. */
702a8ee2dc1de96f2f77e97135015d3e243186fdvboxsync bool f = ASMAtomicCmpXchgU32 (&mu32ResizeStatus, ResizeStatus_UpdateDisplayData, ResizeStatus_InProgress);
2f3883b126a405f92b19e829472f614c7352b4f9vboxsyncSTDMETHODIMP Display::GetScreenResolution(ULONG aScreenId, ULONG *aWidth, ULONG *aHeight, ULONG *aBitsPerPixel)
2f3883b126a405f92b19e829472f614c7352b4f9vboxsyncvoid Display::getFramebufferDimensions(int32_t *px1, int32_t *py1,
2f3883b126a405f92b19e829472f614c7352b4f9vboxsyncstatic void checkCoordBounds (int *px, int *py, int *pw, int *ph, int cx, int cy)
702a8ee2dc1de96f2f77e97135015d3e243186fdvboxsync /* Correct negative x and y coordinates. */
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync *px += *pw; /* Compute xRight which is also the new width. */
702a8ee2dc1de96f2f77e97135015d3e243186fdvboxsync *py += *ph; /* Compute xBottom, which is also the new height. */
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync /* Also check if coords are greater than the display resolution. */
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync * Handle display update
7e8ef90d3160234df0f254131b87af4243d79476vboxsync * @returns COM status code
7e8ef90d3160234df0f254131b87af4243d79476vboxsync * @param w New display width
7e8ef90d3160234df0f254131b87af4243d79476vboxsync * @param h New display height
7e8ef90d3160234df0f254131b87af4243d79476vboxsyncvoid Display::handleDisplayUpdate (int x, int y, int w, int h)
7e8ef90d3160234df0f254131b87af4243d79476vboxsync // if there is no Framebuffer, this call is not interesting
7e8ef90d3160234df0f254131b87af4243d79476vboxsync checkCoordBounds (&x, &y, &w, &h, mpDrv->Connector.cx, mpDrv->Connector.cy);
7e8ef90d3160234df0f254131b87af4243d79476vboxsync if (w == 0 || h == 0)
702a8ee2dc1de96f2f77e97135015d3e243186fdvboxsync// IDisplay properties
702a8ee2dc1de96f2f77e97135015d3e243186fdvboxsync/////////////////////////////////////////////////////////////////////////////
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync * Returns the current display width in pixel
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync * @returns COM status code
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync * @param width Address of result variable.
702a8ee2dc1de96f2f77e97135015d3e243186fdvboxsync * Returns the current display height in pixel
702a8ee2dc1de96f2f77e97135015d3e243186fdvboxsync * @returns COM status code
702a8ee2dc1de96f2f77e97135015d3e243186fdvboxsync * @param height Address of result variable.
1cd59fdf671ca60c64d77e3f7046aaecf7003824vboxsync * Returns the current display color depth in bits
1cd59fdf671ca60c64d77e3f7046aaecf7003824vboxsync * @returns COM status code
1cd59fdf671ca60c64d77e3f7046aaecf7003824vboxsync * @param bitsPerPixel Address of result variable.
1cd59fdf671ca60c64d77e3f7046aaecf7003824vboxsyncvoid Display::updatePointerShape(bool fVisible, bool fAlpha, uint32_t xHot, uint32_t yHot, uint32_t width, uint32_t height, void *pShape)
1cd59fdf671ca60c64d77e3f7046aaecf7003824vboxsync// IDisplay methods
1cd59fdf671ca60c64d77e3f7046aaecf7003824vboxsync/////////////////////////////////////////////////////////////////////////////
1cd59fdf671ca60c64d77e3f7046aaecf7003824vboxsync * Registers an external Framebuffer
1cd59fdf671ca60c64d77e3f7046aaecf7003824vboxsync * @returns COM status code
1cd59fdf671ca60c64d77e3f7046aaecf7003824vboxsync * @param Framebuffer external Framebuffer object
2f3883b126a405f92b19e829472f614c7352b4f9vboxsyncSTDMETHODIMP Display::SetFramebuffer(unsigned iScreenID, Framebuffer *Framebuffer)
702a8ee2dc1de96f2f77e97135015d3e243186fdvboxsync // free current Framebuffer (if there is any)
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync/* InvalidateAndUpdate schedules a request that eventually calls */
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync/* mpDrv->pUpPort->pfnUpdateDisplayAll which in turns accesses the */
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync/* framebuffer. In order to synchronize with other framebuffer */
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync/* related activities this call needs to be framed by Lock/Unlock. */
702a8ee2dc1de96f2f77e97135015d3e243186fdvboxsyncDisplay::doInvalidateAndUpdate(struct DRVMAINDISPLAY *mpDrv)
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync mpDrv->pUpPort->pfnUpdateDisplayAll( mpDrv->pUpPort);
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync * Does a full invalidation of the VM display and instructs the VM
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync * to update it immediately.
702a8ee2dc1de96f2f77e97135015d3e243186fdvboxsync * @returns COM status code
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync LogFlow (("Display::InvalidateAndUpdate(): BEGIN\n"));
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync LogFlow (("Display::InvalidateAndUpdate(): sending DPYUPDATE request\n"));
702a8ee2dc1de96f2f77e97135015d3e243186fdvboxsync /* pdm.h says that this has to be called from the EMT thread */
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync int rcVBox = VMR3ReqCallVoidWait(gpVM, VMCPUID_ANY,
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync LogFlow (("Display::InvalidateAndUpdate(): END: rc=%08X\n", rc));
702a8ee2dc1de96f2f77e97135015d3e243186fdvboxsync// private methods
702a8ee2dc1de96f2f77e97135015d3e243186fdvboxsync/////////////////////////////////////////////////////////////////////////////
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync * Helper to update the display information from the Framebuffer
d4a9d525e6f2111d462d2d96462dced6b9ec00efvboxsync // the driver might not have been constructed yet
d4a9d525e6f2111d462d2d96462dced6b9ec00efvboxsync mFramebuffer->getAddress ((uintptr_t *)&mpDrv->Connector.pu8Data);
d4a9d525e6f2111d462d2d96462dced6b9ec00efvboxsync mFramebuffer->getLineSize ((ULONG*)&mpDrv->Connector.cbScanline);
d4a9d525e6f2111d462d2d96462dced6b9ec00efvboxsync mFramebuffer->getBitsPerPixel ((ULONG*)&mpDrv->Connector.cBits);
d4a9d525e6f2111d462d2d96462dced6b9ec00efvboxsync mFramebuffer->getWidth ((ULONG*)&mpDrv->Connector.cx);
d4a9d525e6f2111d462d2d96462dced6b9ec00efvboxsync mFramebuffer->getHeight ((ULONG*)&mpDrv->Connector.cy);
35e6d303696e46d969aaf9a59cc381333a483b0bvboxsync // the driver might not have been constructed yet
35e6d303696e46d969aaf9a59cc381333a483b0bvboxsync mFramebuffer->getAddress ((uintptr_t *)&mpDrv->Connector.pu8Data);
5366e994777f9d9391cf809dc77610f57270d75dvboxsync mFramebuffer->getBitsPerPixel ((ULONG*)&mpDrv->Connector.cBits);
35e6d303696e46d969aaf9a59cc381333a483b0bvboxsync * Handle display resize event
35e6d303696e46d969aaf9a59cc381333a483b0bvboxsync * @param pInterface Display connector.
35e6d303696e46d969aaf9a59cc381333a483b0bvboxsync * @param cx New width in pixels.
35e6d303696e46d969aaf9a59cc381333a483b0bvboxsync * @param cy New height in pixels.
35e6d303696e46d969aaf9a59cc381333a483b0bvboxsyncDECLCALLBACK(int) Display::displayResizeCallback(PPDMIDISPLAYCONNECTOR pInterface, uint32_t bpp, void *pvVRAM, uint32_t cbLine, uint32_t cx, uint32_t cy)
35e6d303696e46d969aaf9a59cc381333a483b0bvboxsync PDRVMAINDISPLAY pDrv = PDMIDISPLAYCONNECTOR_2_MAINDISPLAY(pInterface);
35e6d303696e46d969aaf9a59cc381333a483b0bvboxsync // forward call to instance handler
35e6d303696e46d969aaf9a59cc381333a483b0bvboxsync return pDrv->pDisplay->handleDisplayResize(cx, cy);
35e6d303696e46d969aaf9a59cc381333a483b0bvboxsync * Handle display update
35e6d303696e46d969aaf9a59cc381333a483b0bvboxsync * @param pInterface Display connector.
35e6d303696e46d969aaf9a59cc381333a483b0bvboxsync * @param x Left upper boundary x.
5366e994777f9d9391cf809dc77610f57270d75dvboxsync * @param y Left upper boundary y.
5366e994777f9d9391cf809dc77610f57270d75dvboxsync * @param cx Update rect width.
35e6d303696e46d969aaf9a59cc381333a483b0bvboxsync * @param cy Update rect height.
35e6d303696e46d969aaf9a59cc381333a483b0bvboxsyncDECLCALLBACK(void) Display::displayUpdateCallback(PPDMIDISPLAYCONNECTOR pInterface,
35e6d303696e46d969aaf9a59cc381333a483b0bvboxsync PDRVMAINDISPLAY pDrv = PDMIDISPLAYCONNECTOR_2_MAINDISPLAY(pInterface);
35e6d303696e46d969aaf9a59cc381333a483b0bvboxsync // forward call to instance handler
35e6d303696e46d969aaf9a59cc381333a483b0bvboxsync * Periodic display refresh callback.
35e6d303696e46d969aaf9a59cc381333a483b0bvboxsync * @param pInterface Display connector.
35e6d303696e46d969aaf9a59cc381333a483b0bvboxsyncDECLCALLBACK(void) Display::displayRefreshCallback(PPDMIDISPLAYCONNECTOR pInterface)
35e6d303696e46d969aaf9a59cc381333a483b0bvboxsync PDRVMAINDISPLAY pDrv = PDMIDISPLAYCONNECTOR_2_MAINDISPLAY(pInterface);
4121d226ac899f17e13aff3aff42b603c8b5c1fevboxsync /* Contrary to displayUpdateCallback and displayResizeCallback
4121d226ac899f17e13aff3aff42b603c8b5c1fevboxsync * the framebuffer lock must be taken since the function
4121d226ac899f17e13aff3aff42b603c8b5c1fevboxsync * pointed to by pDrv->pUpPort->pfnUpdateDisplay is unaware
35e6d303696e46d969aaf9a59cc381333a483b0bvboxsync * of any locking issues. */
35e6d303696e46d969aaf9a59cc381333a483b0bvboxsync uint32_t u32ResizeStatus = pDisplay->mu32ResizeStatus;
4121d226ac899f17e13aff3aff42b603c8b5c1fevboxsync if (u32ResizeStatus == ResizeStatus_UpdateDisplayData)
4121d226ac899f17e13aff3aff42b603c8b5c1fevboxsync LogFlowFunc (("ResizeStatus_UpdateDisplayData\n"));
4121d226ac899f17e13aff3aff42b603c8b5c1fevboxsync#endif /* DEBUG_sunlover */
35e6d303696e46d969aaf9a59cc381333a483b0bvboxsync /* The framebuffer was resized and display data need to be updated. */
35e6d303696e46d969aaf9a59cc381333a483b0bvboxsync /* Continue with normal processing because the status here is ResizeStatus_Void. */
35e6d303696e46d969aaf9a59cc381333a483b0bvboxsync Assert (pDisplay->mu32ResizeStatus == ResizeStatus_Void);
35e6d303696e46d969aaf9a59cc381333a483b0bvboxsync /* Repaint the display because VM continued to run during the framebuffer resize. */
ca3db470494a8b6eaec69ea37468a5cda65e2da8vboxsync /* Ignore the refresh to replay the logic. */
ca3db470494a8b6eaec69ea37468a5cda65e2da8vboxsync else if (u32ResizeStatus == ResizeStatus_InProgress)
ca3db470494a8b6eaec69ea37468a5cda65e2da8vboxsync#endif /* DEBUG_sunlover */
ca3db470494a8b6eaec69ea37468a5cda65e2da8vboxsync /* The framebuffer is being resized. Do not call the VGA device back. Immediately return. */
ca3db470494a8b6eaec69ea37468a5cda65e2da8vboxsync /* Acceleration was enabled while machine was not yet running
ca3db470494a8b6eaec69ea37468a5cda65e2da8vboxsync * due to restoring from saved state. Update entire display and
ca3db470494a8b6eaec69ea37468a5cda65e2da8vboxsync * actually enable acceleration.
ca3db470494a8b6eaec69ea37468a5cda65e2da8vboxsync /* Acceleration can not be yet enabled.*/
ca3db470494a8b6eaec69ea37468a5cda65e2da8vboxsync pDisplay->VideoAccelEnable (pDisplay->mfPendingVideoAccelEnable, pDisplay->mpPendingVbvaMemory);
ca3db470494a8b6eaec69ea37468a5cda65e2da8vboxsync /* Reset the pending state. */
ca3db470494a8b6eaec69ea37468a5cda65e2da8vboxsync * Reset notification
ca3db470494a8b6eaec69ea37468a5cda65e2da8vboxsync * @param pInterface Display connector.
ca3db470494a8b6eaec69ea37468a5cda65e2da8vboxsyncDECLCALLBACK(void) Display::displayResetCallback(PPDMIDISPLAYCONNECTOR pInterface)
ca3db470494a8b6eaec69ea37468a5cda65e2da8vboxsync PDRVMAINDISPLAY pDrv = PDMIDISPLAYCONNECTOR_2_MAINDISPLAY(pInterface);
ca3db470494a8b6eaec69ea37468a5cda65e2da8vboxsync /* Disable VBVA mode. */
ca3db470494a8b6eaec69ea37468a5cda65e2da8vboxsync * LFBModeChange notification
ca3db470494a8b6eaec69ea37468a5cda65e2da8vboxsync * @see PDMIDISPLAYCONNECTOR::pfnLFBModeChange
ca3db470494a8b6eaec69ea37468a5cda65e2da8vboxsyncDECLCALLBACK(void) Display::displayLFBModeChangeCallback(PPDMIDISPLAYCONNECTOR pInterface, bool fEnabled)
ca3db470494a8b6eaec69ea37468a5cda65e2da8vboxsync PDRVMAINDISPLAY pDrv = PDMIDISPLAYCONNECTOR_2_MAINDISPLAY(pInterface);
ca3db470494a8b6eaec69ea37468a5cda65e2da8vboxsync LogFlow(("Display::displayLFBModeChangeCallback: %d\n", fEnabled));
ca3db470494a8b6eaec69ea37468a5cda65e2da8vboxsync * @todo: If we got the callback then VM if definitely running.
ca3db470494a8b6eaec69ea37468a5cda65e2da8vboxsync * But a better method should be implemented.
ca3db470494a8b6eaec69ea37468a5cda65e2da8vboxsync /* Disable VBVA mode in any case. The guest driver reenables VBVA mode if necessary. */
ca3db470494a8b6eaec69ea37468a5cda65e2da8vboxsyncDECLCALLBACK(void) Display::displayProcessAdapterDataCallback(PPDMIDISPLAYCONNECTOR pInterface, void *pvVRAM, uint32_t u32VRAMSize)
ca3db470494a8b6eaec69ea37468a5cda65e2da8vboxsyncDECLCALLBACK(void) Display::displayProcessDisplayDataCallback(PPDMIDISPLAYCONNECTOR pInterface, void *pvVRAM, unsigned uScreenId)
8bc8d66f188d5357155b8340e2d489573be2b607vboxsync /* Copies of object's pointers used by vbvaRgn functions. */
8bc8d66f188d5357155b8340e2d489573be2b607vboxsync /* Merged rectangles. */
88cc9bf61296bc5526344415167bb2625ae1dd99vboxsyncvoid vbvaRgnInit (VBVADIRTYREGION *prgn, Framebuffer *pfb, Display *pd, PPDMIDISPLAYPORT pp)
8bc8d66f188d5357155b8340e2d489573be2b607vboxsyncvoid vbvaRgnDirtyRect (VBVADIRTYREGION *prgn, VBVACMDHDR *phdr)
687794577e2e35c3cae67e692a7f2130d1262a82vboxsync LogFlow(("vbvaRgnDirtyRect: x = %d, y = %d, w = %d, h = %d\n", phdr->x, phdr->y, phdr->w, phdr->h));
907b6adfa052386a0666d5557bee9bdbc100c2e5vboxsync * Here update rectangles are accumulated to form an update area.
687794577e2e35c3cae67e692a7f2130d1262a82vboxsync * Now the simplest method is used which builds one rectangle that
cc1ef2ef9bbc6a0ff964928d61b7298e5bfcce5fvboxsync * includes all update areas. A bit more advanced method can be
cc1ef2ef9bbc6a0ff964928d61b7298e5bfcce5fvboxsync * employed here. The method should be fast however.
907b6adfa052386a0666d5557bee9bdbc100c2e5vboxsync /* Empty rectangle. */
907b6adfa052386a0666d5557bee9bdbc100c2e5vboxsync /* This is the first rectangle to be added. */
687794577e2e35c3cae67e692a7f2130d1262a82vboxsync /* Adjust region coordinates. */
d4a9d525e6f2111d462d2d96462dced6b9ec00efvboxsyncvoid vbvaRgnUpdateFramebuffer (VBVADIRTYREGION *prgn)
004d74842597dacc4009803171296dfcf9398c69vboxsync prgn->pPort->pfnUpdateDisplayRect (prgn->pPort, prgn->xLeft, prgn->yTop, w, h);
004d74842597dacc4009803171296dfcf9398c69vboxsync prgn->pDisplay->handleDisplayUpdate (prgn->xLeft, prgn->yTop, w, h);
004d74842597dacc4009803171296dfcf9398c69vboxsyncstatic void vbvaSetMemoryFlags (VBVAMEMORY *pVbvaMemory, bool fVideoAccelEnabled, bool fVideoAccelVRDP)
004d74842597dacc4009803171296dfcf9398c69vboxsync /* This called only on changes in mode. So reset VRDP always. */
004d74842597dacc4009803171296dfcf9398c69vboxsync return true;
004d74842597dacc4009803171296dfcf9398c69vboxsync * @thread EMT
004d74842597dacc4009803171296dfcf9398c69vboxsyncint Display::VideoAccelEnable (bool fEnable, VBVAMEMORY *pVbvaMemory)
004d74842597dacc4009803171296dfcf9398c69vboxsync /* Called each time the guest wants to use acceleration,
004d74842597dacc4009803171296dfcf9398c69vboxsync * or when the VGA device disables acceleration,
004d74842597dacc4009803171296dfcf9398c69vboxsync * or when restoring the saved state with accel enabled.
004d74842597dacc4009803171296dfcf9398c69vboxsync * VGA device disables acceleration on each video mode change
004d74842597dacc4009803171296dfcf9398c69vboxsync * and on reset.
004d74842597dacc4009803171296dfcf9398c69vboxsync * Guest enabled acceleration at will. And it needs to enable
004d74842597dacc4009803171296dfcf9398c69vboxsync * acceleration after a mode change.
004d74842597dacc4009803171296dfcf9398c69vboxsync LogFlow(("Display::VideoAccelEnable: mfVideoAccelEnabled = %d, fEnable = %d, pVbvaMemory = %p\n",
004d74842597dacc4009803171296dfcf9398c69vboxsync /* Strictly check parameters. Callers must not pass anything in the case. */
004d74842597dacc4009803171296dfcf9398c69vboxsync Assert((fEnable && pVbvaMemory) || (!fEnable && pVbvaMemory == NULL));
004d74842597dacc4009803171296dfcf9398c69vboxsync * Verify that the VM is in running state. If it is not,
004d74842597dacc4009803171296dfcf9398c69vboxsync * then this must be postponed until it goes to running.
004d74842597dacc4009803171296dfcf9398c69vboxsync LogFlow(("Display::VideoAccelEnable: Machine is not yet running.\n"));
004d74842597dacc4009803171296dfcf9398c69vboxsync /* Check that current status is not being changed */
004d74842597dacc4009803171296dfcf9398c69vboxsync /* Process any pending orders and empty the VBVA ring buffer. */
5366e994777f9d9391cf809dc77610f57270d75dvboxsync mpVbvaMemory->fu32ModeFlags &= ~VBVA_F_MODE_ENABLED;
88cc9bf61296bc5526344415167bb2625ae1dd99vboxsync /* Safety precaution. There is no more VBVA until everything is setup! */
5366e994777f9d9391cf809dc77610f57270d75dvboxsync /* Update entire display. */
88cc9bf61296bc5526344415167bb2625ae1dd99vboxsync mpDrv->pUpPort->pfnUpdateDisplayAll(mpDrv->pUpPort);
88cc9bf61296bc5526344415167bb2625ae1dd99vboxsync /* Everything OK. VBVA status can be changed. */
5366e994777f9d9391cf809dc77610f57270d75dvboxsync /* Notify the VMMDev, which saves VBVA status in the saved state,
88cc9bf61296bc5526344415167bb2625ae1dd99vboxsync * and needs to know current status.
5366e994777f9d9391cf809dc77610f57270d75dvboxsync PPDMIVMMDEVPORT pVMMDevPort = gVMMDev->getVMMDevPort ();
e378dfdadd62aadc0a012c9953322d979d7606e6vboxsync /* Initialize the hardware memory. */
e378dfdadd62aadc0a012c9953322d979d7606e6vboxsync vbvaSetMemoryFlags (mpVbvaMemory, mfVideoAccelEnabled, false);
4121d226ac899f17e13aff3aff42b603c8b5c1fevboxsync memset (mpVbvaMemory->aRecords, 0, sizeof (mpVbvaMemory->aRecords));
4121d226ac899f17e13aff3aff42b603c8b5c1fevboxsync LogFlow(("Display::VideoAccelEnable: rc = %Rrc.\n", rc));
4121d226ac899f17e13aff3aff42b603c8b5c1fevboxsyncstatic bool vbvaVerifyRingBuffer (VBVAMEMORY *pVbvaMemory)
4121d226ac899f17e13aff3aff42b603c8b5c1fevboxsync return true;
4121d226ac899f17e13aff3aff42b603c8b5c1fevboxsyncstatic void vbvaFetchBytes (VBVAMEMORY *pVbvaMemory, uint8_t *pu8Dst, uint32_t cbDst)
3ff8aa7d3c74cfbe8da5f77b8ea6c748cc79213avboxsync uint32_t u32BytesTillBoundary = VBVA_RING_BUFFER_SIZE - pVbvaMemory->off32Data;
5366e994777f9d9391cf809dc77610f57270d75dvboxsync uint8_t *src = &pVbvaMemory->au8RingBuffer[pVbvaMemory->off32Data];
e378dfdadd62aadc0a012c9953322d979d7606e6vboxsync /* Chunk will not cross buffer boundary. */
e378dfdadd62aadc0a012c9953322d979d7606e6vboxsync /* Chunk crosses buffer boundary. */
e378dfdadd62aadc0a012c9953322d979d7606e6vboxsync memcpy (pu8Dst + u32BytesTillBoundary, &pVbvaMemory->au8RingBuffer[0], i32Diff);
e378dfdadd62aadc0a012c9953322d979d7606e6vboxsync /* Advance data offset. */
e378dfdadd62aadc0a012c9953322d979d7606e6vboxsync pVbvaMemory->off32Data = (pVbvaMemory->off32Data + cbDst) % VBVA_RING_BUFFER_SIZE;
8bc8d66f188d5357155b8340e2d489573be2b607vboxsyncvoid Display::SetVideoModeHint(ULONG aWidth, ULONG aHeight, ULONG aBitsPerPixel, ULONG aDisplay)
e378dfdadd62aadc0a012c9953322d979d7606e6vboxsync PPDMIVMMDEVPORT pVMMDevPort = gVMMDev->getVMMDevPort ();
e378dfdadd62aadc0a012c9953322d979d7606e6vboxsync pVMMDevPort->pfnRequestDisplayChange(pVMMDevPort, aWidth, aHeight, aBitsPerPixel, aDisplay);
5366e994777f9d9391cf809dc77610f57270d75dvboxsyncstatic bool vbvaPartialRead (uint8_t **ppu8, uint32_t *pcb, uint32_t cbRecord, VBVAMEMORY *pVbvaMemory)
e378dfdadd62aadc0a012c9953322d979d7606e6vboxsync LogFlow(("MAIN::DisplayImpl::vbvaPartialRead: p = %p, cb = %d, cbRecord 0x%08X\n",
e378dfdadd62aadc0a012c9953322d979d7606e6vboxsync pu8New = (uint8_t *)RTMemRealloc (*ppu8, cbRecord);
e378dfdadd62aadc0a012c9953322d979d7606e6vboxsync /* Memory allocation failed, fail the function. */
e378dfdadd62aadc0a012c9953322d979d7606e6vboxsync Log(("MAIN::vbvaPartialRead: failed to (re)alocate memory for partial record!!! cbRecord 0x%08X\n",
e378dfdadd62aadc0a012c9953322d979d7606e6vboxsync return false;
e378dfdadd62aadc0a012c9953322d979d7606e6vboxsync /* Fetch data from the ring buffer. */
e378dfdadd62aadc0a012c9953322d979d7606e6vboxsync vbvaFetchBytes (pVbvaMemory, pu8New + *pcb, cbRecord - *pcb);
5f2b03bf7695dabd71222dba123532a3f76828c1vboxsync return true;
5f2b03bf7695dabd71222dba123532a3f76828c1vboxsync/* For contiguous chunks just return the address in the buffer.
5f2b03bf7695dabd71222dba123532a3f76828c1vboxsync * For crossing boundary - allocate a buffer from heap.
7862f4bd000f1eb6c86289f5ac2849e9cf943ca9vboxsyncbool Display::vbvaFetchCmd (VBVACMDHDR **ppHdr, uint32_t *pcbCmd)
7862f4bd000f1eb6c86289f5ac2849e9cf943ca9vboxsync uint32_t indexRecordFirst = mpVbvaMemory->indexRecordFirst;
7862f4bd000f1eb6c86289f5ac2849e9cf943ca9vboxsync uint32_t indexRecordFree = mpVbvaMemory->indexRecordFree;
40c1a23e86c79b24a917a43c186b2e54504d12c1vboxsync LogFlow(("MAIN::DisplayImpl::vbvaFetchCmd:first = %d, free = %d\n",
40c1a23e86c79b24a917a43c186b2e54504d12c1vboxsync#endif /* DEBUG_sunlover */
d4a9d525e6f2111d462d2d96462dced6b9ec00efvboxsync return false;
d4a9d525e6f2111d462d2d96462dced6b9ec00efvboxsync /* No records to process. Return without assigning output variables. */
6b9d50a0f466bd5a61458ed53925480ab28a3c17vboxsync return true;
5f2b03bf7695dabd71222dba123532a3f76828c1vboxsync VBVARECORD *pRecord = &mpVbvaMemory->aRecords[indexRecordFirst];
d4a9d525e6f2111d462d2d96462dced6b9ec00efvboxsync LogFlow(("MAIN::DisplayImpl::vbvaFetchCmd: cbRecord = 0x%08X\n",
d4a9d525e6f2111d462d2d96462dced6b9ec00efvboxsync#endif /* DEBUG_sunlover */
d4a9d525e6f2111d462d2d96462dced6b9ec00efvboxsync uint32_t cbRecord = pRecord->cbRecord & ~VBVA_F_RECORD_PARTIAL;
5366e994777f9d9391cf809dc77610f57270d75dvboxsync /* There is a partial read in process. Continue with it. */
5366e994777f9d9391cf809dc77610f57270d75dvboxsync LogFlow(("MAIN::DisplayImpl::vbvaFetchCmd: continue partial record mcbVbvaPartial = %d cbRecord 0x%08X, first = %d, free = %d\n",
5366e994777f9d9391cf809dc77610f57270d75dvboxsync mcbVbvaPartial, pRecord->cbRecord, indexRecordFirst, indexRecordFree));
5366e994777f9d9391cf809dc77610f57270d75dvboxsync /* New data has been added to the record. */
5366e994777f9d9391cf809dc77610f57270d75dvboxsync if (!vbvaPartialRead (&mpu8VbvaPartial, &mcbVbvaPartial, cbRecord, mpVbvaMemory))
5366e994777f9d9391cf809dc77610f57270d75dvboxsync return false;
5366e994777f9d9391cf809dc77610f57270d75dvboxsync /* The record is completed by guest. Return it to the caller. */
d4a9d525e6f2111d462d2d96462dced6b9ec00efvboxsync /* Advance the record index. */
ed9d3db07648c7e3a979105c15ad752ee9ea18devboxsync mpVbvaMemory->indexRecordFirst = (indexRecordFirst + 1) % VBVA_MAX_RECORDS;
ed9d3db07648c7e3a979105c15ad752ee9ea18devboxsync LogFlow(("MAIN::DisplayImpl::vbvaFetchBytes: partial done ok, data = %d, free = %d\n",
ed9d3db07648c7e3a979105c15ad752ee9ea18devboxsync mpVbvaMemory->off32Data, mpVbvaMemory->off32Free));
7e8ef90d3160234df0f254131b87af4243d79476vboxsync#endif /* DEBUG_sunlover */
d4a9d525e6f2111d462d2d96462dced6b9ec00efvboxsync return true;
d4a9d525e6f2111d462d2d96462dced6b9ec00efvboxsync /* A new record need to be processed. */
d4a9d525e6f2111d462d2d96462dced6b9ec00efvboxsync /* Current record is being written by guest. '=' is important here. */
907b6adfa052386a0666d5557bee9bdbc100c2e5vboxsync if (cbRecord >= VBVA_RING_BUFFER_SIZE - VBVA_RING_BUFFER_THRESHOLD)
d4a9d525e6f2111d462d2d96462dced6b9ec00efvboxsync /* Partial read must be started. */
d4a9d525e6f2111d462d2d96462dced6b9ec00efvboxsync if (!vbvaPartialRead (&mpu8VbvaPartial, &mcbVbvaPartial, cbRecord, mpVbvaMemory))
d4a9d525e6f2111d462d2d96462dced6b9ec00efvboxsync return false;
cc1ef2ef9bbc6a0ff964928d61b7298e5bfcce5fvboxsync LogFlow(("MAIN::DisplayImpl::vbvaFetchCmd: started partial record mcbVbvaPartial = 0x%08X cbRecord 0x%08X, first = %d, free = %d\n",
907b6adfa052386a0666d5557bee9bdbc100c2e5vboxsync mcbVbvaPartial, pRecord->cbRecord, indexRecordFirst, indexRecordFree));
5f2b03bf7695dabd71222dba123532a3f76828c1vboxsync return true;
687794577e2e35c3cae67e692a7f2130d1262a82vboxsync /* Current record is complete. */
5f2b03bf7695dabd71222dba123532a3f76828c1vboxsync /* The size of largest contiguous chunk in the ring biffer. */
5f2b03bf7695dabd71222dba123532a3f76828c1vboxsync uint32_t u32BytesTillBoundary = VBVA_RING_BUFFER_SIZE - mpVbvaMemory->off32Data;
6b9d50a0f466bd5a61458ed53925480ab28a3c17vboxsync /* The ring buffer pointer. */
5f2b03bf7695dabd71222dba123532a3f76828c1vboxsync uint8_t *au8RingBuffer = &mpVbvaMemory->au8RingBuffer[0];
5f2b03bf7695dabd71222dba123532a3f76828c1vboxsync /* The pointer to data in the ring buffer. */
5f2b03bf7695dabd71222dba123532a3f76828c1vboxsync uint8_t *src = &au8RingBuffer[mpVbvaMemory->off32Data];
5f2b03bf7695dabd71222dba123532a3f76828c1vboxsync /* Fetch or point the data. */
6b9d50a0f466bd5a61458ed53925480ab28a3c17vboxsync /* The command does not cross buffer boundary. Return address in the buffer. */
5f2b03bf7695dabd71222dba123532a3f76828c1vboxsync /* Advance data offset. */
5f2b03bf7695dabd71222dba123532a3f76828c1vboxsync mpVbvaMemory->off32Data = (mpVbvaMemory->off32Data + cbRecord) % VBVA_RING_BUFFER_SIZE;
88cc9bf61296bc5526344415167bb2625ae1dd99vboxsync /* The command crosses buffer boundary. Rare case, so not optimized. */
88cc9bf61296bc5526344415167bb2625ae1dd99vboxsync LogFlow(("MAIN::DisplayImpl::vbvaFetchCmd: could not allocate %d bytes from heap!!!\n", cbRecord));
d4a9d525e6f2111d462d2d96462dced6b9ec00efvboxsync mpVbvaMemory->off32Data = (mpVbvaMemory->off32Data + cbRecord) % VBVA_RING_BUFFER_SIZE;
88cc9bf61296bc5526344415167bb2625ae1dd99vboxsync return false;
88cc9bf61296bc5526344415167bb2625ae1dd99vboxsync LogFlow(("MAIN::DisplayImpl::vbvaFetchBytes: Allocated from heap %p\n", dst));
88cc9bf61296bc5526344415167bb2625ae1dd99vboxsync#endif /* DEBUG_sunlover */
ccbdc11833996cb9f3be7868f1ebaefcacafb94dvboxsync /* Advance the record index. */
5f2b03bf7695dabd71222dba123532a3f76828c1vboxsync mpVbvaMemory->indexRecordFirst = (indexRecordFirst + 1) % VBVA_MAX_RECORDS;
687794577e2e35c3cae67e692a7f2130d1262a82vboxsync LogFlow(("MAIN::DisplayImpl::vbvaFetchBytes: done ok, data = %d, free = %d\n",
687794577e2e35c3cae67e692a7f2130d1262a82vboxsync mpVbvaMemory->off32Data, mpVbvaMemory->off32Free));
687794577e2e35c3cae67e692a7f2130d1262a82vboxsync#endif /* DEBUG_sunlover */
687794577e2e35c3cae67e692a7f2130d1262a82vboxsync return true;
687794577e2e35c3cae67e692a7f2130d1262a82vboxsyncvoid Display::vbvaReleaseCmd (VBVACMDHDR *pHdr, int32_t cbCmd)
687794577e2e35c3cae67e692a7f2130d1262a82vboxsync uint8_t *au8RingBuffer = mpVbvaMemory->au8RingBuffer;
687794577e2e35c3cae67e692a7f2130d1262a82vboxsync && (uint8_t *)pHdr < &au8RingBuffer[VBVA_RING_BUFFER_SIZE])
687794577e2e35c3cae67e692a7f2130d1262a82vboxsync /* The pointer is inside ring buffer. Must be continuous chunk. */
687794577e2e35c3cae67e692a7f2130d1262a82vboxsync Assert (VBVA_RING_BUFFER_SIZE - ((uint8_t *)pHdr - au8RingBuffer) >= cbCmd);
687794577e2e35c3cae67e692a7f2130d1262a82vboxsync /* Do nothing. */
687794577e2e35c3cae67e692a7f2130d1262a82vboxsync /* The pointer is outside. It is then an allocated copy. */
687794577e2e35c3cae67e692a7f2130d1262a82vboxsync LogFlow(("MAIN::DisplayImpl::vbvaReleaseCmd: Free heap %p\n", pHdr));
687794577e2e35c3cae67e692a7f2130d1262a82vboxsync#endif /* DEBUG_sunlover */
88cc9bf61296bc5526344415167bb2625ae1dd99vboxsync * Called regularly on the DisplayRefresh timer.
88cc9bf61296bc5526344415167bb2625ae1dd99vboxsync * Also on behalf of guest, when the ring buffer is full.
0fd108a555ae02f2fb557d5f2c40281999b60d15vboxsync * @thread EMT
88cc9bf61296bc5526344415167bb2625ae1dd99vboxsync LogFlow(("Display::VideoAccelFlush: mfVideoAccelEnabled = %d\n", mfVideoAccelEnabled));
88cc9bf61296bc5526344415167bb2625ae1dd99vboxsync#endif /* DEBUG_sunlover */
0fd108a555ae02f2fb557d5f2c40281999b60d15vboxsync Log(("Display::VideoAccelFlush: called with disabled VBVA!!! Ignoring.\n"));
0fd108a555ae02f2fb557d5f2c40281999b60d15vboxsync /* Here VBVA is enabled and we have the accelerator memory pointer. */
f9ce005e61f0fbb51a2cabc53d58c3485151faa9vboxsync LogFlow(("Display::VideoAccelFlush: indexRecordFirst = %d, indexRecordFree = %d, off32Data = %d, off32Free = %d\n",
f9ce005e61f0fbb51a2cabc53d58c3485151faa9vboxsync mpVbvaMemory->indexRecordFirst, mpVbvaMemory->indexRecordFree, mpVbvaMemory->off32Data, mpVbvaMemory->off32Free));
f9ce005e61f0fbb51a2cabc53d58c3485151faa9vboxsync#endif /* DEBUG_sunlover */
f9ce005e61f0fbb51a2cabc53d58c3485151faa9vboxsync /* Quick check for "nothing to update" case. */
f9ce005e61f0fbb51a2cabc53d58c3485151faa9vboxsync if (mpVbvaMemory->indexRecordFirst == mpVbvaMemory->indexRecordFree)
0fd108a555ae02f2fb557d5f2c40281999b60d15vboxsync /* Process the ring buffer */
f9ce005e61f0fbb51a2cabc53d58c3485151faa9vboxsync /* Initialize dirty rectangles accumulator. */
f9ce005e61f0fbb51a2cabc53d58c3485151faa9vboxsync vbvaRgnInit (&rgn, mFramebuffer, this, mpDrv->pUpPort);
f9ce005e61f0fbb51a2cabc53d58c3485151faa9vboxsync /* Fetch the command data. */
f9ce005e61f0fbb51a2cabc53d58c3485151faa9vboxsync Log(("Display::VideoAccelFlush: unable to fetch command. off32Data = %d, off32Free = %d. Disabling VBVA!!!\n",
f9ce005e61f0fbb51a2cabc53d58c3485151faa9vboxsync mpVbvaMemory->off32Data, mpVbvaMemory->off32Free));
f9ce005e61f0fbb51a2cabc53d58c3485151faa9vboxsync /* Disable VBVA on those processing errors. */
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync /* No more commands yet in the queue. */
702a8ee2dc1de96f2f77e97135015d3e243186fdvboxsync LogFlow(("MAIN::DisplayImpl::VideoAccelFlush: hdr: cbCmd = %d, x=%d, y=%d, w=%d, h=%d\n", cbCmd, phdr->x, phdr->y, phdr->w, phdr->h));
d4a9d525e6f2111d462d2d96462dced6b9ec00efvboxsync#endif /* DEBUG_sunlover */
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync /* Handle the command.
0fd108a555ae02f2fb557d5f2c40281999b60d15vboxsync * Guest is responsible for updating the guest video memory.
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync * The Windows guest does all drawing using Eng*.
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync * For local output, only dirty rectangle information is used
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync * to update changed areas.
0fd108a555ae02f2fb557d5f2c40281999b60d15vboxsync * Dirty rectangles are accumulated to exclude overlapping updates and
0fd108a555ae02f2fb557d5f2c40281999b60d15vboxsync * group small updates to a larger one.
702a8ee2dc1de96f2f77e97135015d3e243186fdvboxsync /* Accumulate the update. */
0fd108a555ae02f2fb557d5f2c40281999b60d15vboxsync// /* Forward the command to VRDP server. */
0fd108a555ae02f2fb557d5f2c40281999b60d15vboxsync// mParent->consoleVRDPServer()->SendUpdate (phdr, cbCmd);
0fd108a555ae02f2fb557d5f2c40281999b60d15vboxsync /* Draw the framebuffer. */
0fd108a555ae02f2fb557d5f2c40281999b60d15vboxsync * @interface_method_impl{PDMIBASE,pfnQueryInterface}
0fd108a555ae02f2fb557d5f2c40281999b60d15vboxsyncDECLCALLBACK(void *) Display::drvQueryInterface(PPDMIBASE pInterface, const char *pszIID)
6b9d50a0f466bd5a61458ed53925480ab28a3c17vboxsync PPDMDRVINS pDrvIns = PDMIBASE_2_PDMDRV(pInterface);
0fd108a555ae02f2fb557d5f2c40281999b60d15vboxsync PDRVMAINDISPLAY pDrv = PDMINS_2_DATA(pDrvIns, PDRVMAINDISPLAY);
0fd108a555ae02f2fb557d5f2c40281999b60d15vboxsync if (RTUuidCompare2Strs(pszIID, PDMIDISPLAYCONNECTOR_IID) == 0)
6b9d50a0f466bd5a61458ed53925480ab28a3c17vboxsync * Construct a display driver instance.
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync * @copydoc FNPDMDRVCONSTRUCT
2f3883b126a405f92b19e829472f614c7352b4f9vboxsyncDECLCALLBACK(int) Display::drvConstruct(PPDMDRVINS pDrvIns, PCFGMNODE pCfg, uint32_t fFlags)
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync PDRVMAINDISPLAY pData = PDMINS_2_DATA(pDrvIns, PDRVMAINDISPLAY);
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync LogFlow(("Display::drvConstruct: iInstance=%d\n", pDrvIns->iInstance));
0fd108a555ae02f2fb557d5f2c40281999b60d15vboxsync * Validate configuration.
702a8ee2dc1de96f2f77e97135015d3e243186fdvboxsync AssertMsgReturn(PDMDrvHlpNoAttach(pDrvIns) == VERR_PDM_NO_ATTACHED_DRIVER,
0fd108a555ae02f2fb557d5f2c40281999b60d15vboxsync ("Configuration error: Not possible to attach anything to this driver!\n"),
0fd108a555ae02f2fb557d5f2c40281999b60d15vboxsync * Init Interfaces.
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync pDrvIns->IBase.pfnQueryInterface = Display::drvQueryInterface;
0fd108a555ae02f2fb557d5f2c40281999b60d15vboxsync pData->Connector.pfnResize = Display::displayResizeCallback;
0fd108a555ae02f2fb557d5f2c40281999b60d15vboxsync pData->Connector.pfnUpdateRect = Display::displayUpdateCallback;
0fd108a555ae02f2fb557d5f2c40281999b60d15vboxsync pData->Connector.pfnRefresh = Display::displayRefreshCallback;
0fd108a555ae02f2fb557d5f2c40281999b60d15vboxsync pData->Connector.pfnReset = Display::displayResetCallback;
0fd108a555ae02f2fb557d5f2c40281999b60d15vboxsync pData->Connector.pfnLFBModeChange = Display::displayLFBModeChangeCallback;
0fd108a555ae02f2fb557d5f2c40281999b60d15vboxsync pData->Connector.pfnProcessAdapterData = Display::displayProcessAdapterDataCallback;
0fd108a555ae02f2fb557d5f2c40281999b60d15vboxsync pData->Connector.pfnProcessDisplayData = Display::displayProcessDisplayDataCallback;
0fd108a555ae02f2fb557d5f2c40281999b60d15vboxsync * Get the IDisplayPort interface of the above driver/device.
0fd108a555ae02f2fb557d5f2c40281999b60d15vboxsync pData->pUpPort = PDMIBASE_QUERY_INTERFACE(pDrvIns->pUpBase, PDMIDISPLAYPORT);
0fd108a555ae02f2fb557d5f2c40281999b60d15vboxsync AssertMsgFailed(("Configuration error: No display port interface above!\n"));
0fd108a555ae02f2fb557d5f2c40281999b60d15vboxsync * Get the Display object pointer and update the mpDrv member.
6b9d50a0f466bd5a61458ed53925480ab28a3c17vboxsync AssertMsgFailed(("Configuration error: No/bad \"Object\" value! rc=%Rrc\n", rc));
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync pData->pDisplay = (Display *)pv; /** @todo Check this cast! */
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync * If there is a Framebuffer, we have to update our display information
35e6d303696e46d969aaf9a59cc381333a483b0bvboxsync * Start periodic screen refreshes
35e6d303696e46d969aaf9a59cc381333a483b0bvboxsync pData->pUpPort->pfnSetRefreshRate(pData->pUpPort, 50);
35e6d303696e46d969aaf9a59cc381333a483b0bvboxsync * Display driver registration record.
5366e994777f9d9391cf809dc77610f57270d75dvboxsync /* u32Version */
5366e994777f9d9391cf809dc77610f57270d75dvboxsync /* szName */
5366e994777f9d9391cf809dc77610f57270d75dvboxsync "MainDisplay",
5366e994777f9d9391cf809dc77610f57270d75dvboxsync /* szRCMod */
35e6d303696e46d969aaf9a59cc381333a483b0bvboxsync /* szR0Mod */
35e6d303696e46d969aaf9a59cc381333a483b0bvboxsync /* pszDescription */
35e6d303696e46d969aaf9a59cc381333a483b0bvboxsync "Main display driver (Main as in the API).",
4121d226ac899f17e13aff3aff42b603c8b5c1fevboxsync /* fFlags */
35e6d303696e46d969aaf9a59cc381333a483b0bvboxsync /* fClass. */
35e6d303696e46d969aaf9a59cc381333a483b0bvboxsync /* cMaxInstances */
35e6d303696e46d969aaf9a59cc381333a483b0bvboxsync /* cbInstance */
35e6d303696e46d969aaf9a59cc381333a483b0bvboxsync /* pfnConstruct */
35e6d303696e46d969aaf9a59cc381333a483b0bvboxsync /* pfnDestruct */
35e6d303696e46d969aaf9a59cc381333a483b0bvboxsync /* pfnRelocate */
35e6d303696e46d969aaf9a59cc381333a483b0bvboxsync /* pfnIOCtl */
35e6d303696e46d969aaf9a59cc381333a483b0bvboxsync /* pfnPowerOn */
35e6d303696e46d969aaf9a59cc381333a483b0bvboxsync /* pfnReset */
35e6d303696e46d969aaf9a59cc381333a483b0bvboxsync /* pfnSuspend */
35e6d303696e46d969aaf9a59cc381333a483b0bvboxsync /* pfnResume */
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync /* pfnAttach */
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync /* pfnDetach */
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync /* pfnPowerOff */
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync /* pfnSoftReset */
702a8ee2dc1de96f2f77e97135015d3e243186fdvboxsync /* u32EndVersion */