DisplayImpl.cpp revision ed0d9ad011741656c6a8456b97b036e1aa815da2
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync/* $Id$ */
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync/** @file
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync * VBox frontends: Basic Frontend (BFE):
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync * Implementation of Display class
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync */
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync/*
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync * Copyright (C) 2006-2007 Oracle Corporation
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync *
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
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync#define LOG_GROUP LOG_GROUP_MAIN
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync#ifdef VBOXBFE_WITHOUT_COM
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync# include "COMDefs.h"
d4a9d525e6f2111d462d2d96462dced6b9ec00efvboxsync# include <iprt/string.h>
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync#else
7b9f0c34e9ea328981c99e97054bdf8684d9d620vboxsync# include <VBox/com/defs.h>
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync#endif
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync#include <iprt/mem.h>
0fd108a555ae02f2fb557d5f2c40281999b60d15vboxsync#include <iprt/semaphore.h>
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync#include <iprt/thread.h>
b1cc3e87518139898395f96974ecff9e6bf228fbvboxsync#include <VBox/pdm.h>
b1cc3e87518139898395f96974ecff9e6bf228fbvboxsync#include <VBox/VMMDev.h>
7862f4bd000f1eb6c86289f5ac2849e9cf943ca9vboxsync#include <VBox/cfgm.h>
388b6b190a5407548753b7fde12fa58134ec3563vboxsync#include <VBox/err.h>
7862f4bd000f1eb6c86289f5ac2849e9cf943ca9vboxsync#include <iprt/assert.h>
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync#include <VBox/log.h>
f9ce005e61f0fbb51a2cabc53d58c3485151faa9vboxsync#include <iprt/asm.h>
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync#include <iprt/uuid.h>
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync
4121d226ac899f17e13aff3aff42b603c8b5c1fevboxsync#ifdef RT_OS_L4
4121d226ac899f17e13aff3aff42b603c8b5c1fevboxsync# include <stdio.h>
4121d226ac899f17e13aff3aff42b603c8b5c1fevboxsync# include <l4/util/util.h>
4121d226ac899f17e13aff3aff42b603c8b5c1fevboxsync# include <l4/log/l4log.h>
4121d226ac899f17e13aff3aff42b603c8b5c1fevboxsync#endif
4121d226ac899f17e13aff3aff42b603c8b5c1fevboxsync
c4b821bf03ae7641a0791e3fd161247e66433b68vboxsync#include "DisplayImpl.h"
c4b821bf03ae7641a0791e3fd161247e66433b68vboxsync#include "Framebuffer.h"
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync#include "VMMDev.h"
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync/*******************************************************************************
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync* Structures and Typedefs *
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync*******************************************************************************/
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync/**
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync * Display driver instance data.
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync */
2f3883b126a405f92b19e829472f614c7352b4f9vboxsynctypedef struct DRVMAINDISPLAY
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync{
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync /** Pointer to the display object. */
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync Display *pDisplay;
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync /** Pointer to the driver instance structure. */
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync PPDMDRVINS pDrvIns;
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync /** Pointer to the keyboard port interface of the driver/device above us. */
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync PPDMIDISPLAYPORT pUpPort;
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync /** Our display connector interface. */
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync PDMIDISPLAYCONNECTOR Connector;
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync} DRVMAINDISPLAY, *PDRVMAINDISPLAY;
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync
687794577e2e35c3cae67e692a7f2130d1262a82vboxsync/** Converts PDMIDISPLAYCONNECTOR pointer to a DRVMAINDISPLAY pointer. */
d4a9d525e6f2111d462d2d96462dced6b9ec00efvboxsync#define PDMIDISPLAYCONNECTOR_2_MAINDISPLAY(pInterface) ( (PDRVMAINDISPLAY) ((uintptr_t)pInterface - RT_OFFSETOF(DRVMAINDISPLAY, Connector)) )
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync
702a8ee2dc1de96f2f77e97135015d3e243186fdvboxsync
702a8ee2dc1de96f2f77e97135015d3e243186fdvboxsync// constructor / destructor
c142e0f462e6c921a73d84ee50f41396b3a99db5vboxsync/////////////////////////////////////////////////////////////////////////////
c142e0f462e6c921a73d84ee50f41396b3a99db5vboxsync
2f3883b126a405f92b19e829472f614c7352b4f9vboxsyncDisplay::Display()
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync{
d4a9d525e6f2111d462d2d96462dced6b9ec00efvboxsync mpDrv = NULL;
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync
907b6adfa052386a0666d5557bee9bdbc100c2e5vboxsync mpVbvaMemory = NULL;
d4a9d525e6f2111d462d2d96462dced6b9ec00efvboxsync mfVideoAccelEnabled = false;
5f2b03bf7695dabd71222dba123532a3f76828c1vboxsync
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync mpPendingVbvaMemory = NULL;
5f2b03bf7695dabd71222dba123532a3f76828c1vboxsync mfPendingVideoAccelEnable = false;
5f2b03bf7695dabd71222dba123532a3f76828c1vboxsync
5f2b03bf7695dabd71222dba123532a3f76828c1vboxsync mfMachineRunning = false;
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync mpu8VbvaPartial = NULL;
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync mcbVbvaPartial = 0;
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync // by default, we have an internal Framebuffer which is
702a8ee2dc1de96f2f77e97135015d3e243186fdvboxsync // NULL, i.e. a black hole for no display output
d4a9d525e6f2111d462d2d96462dced6b9ec00efvboxsync mFramebuffer = NULL;
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync mFramebufferOpened = false;
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync mu32ResizeStatus = ResizeStatus_Void;
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync}
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync
2f3883b126a405f92b19e829472f614c7352b4f9vboxsyncDisplay::~Display()
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync{
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync mFramebuffer = 0;
702a8ee2dc1de96f2f77e97135015d3e243186fdvboxsync}
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync// public methods only for internal purposes
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync/////////////////////////////////////////////////////////////////////////////
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync/**
9523921c89c66f4bececdbd5ac95aed0039eda1bvboxsync * Handle display resize event.
9523921c89c66f4bececdbd5ac95aed0039eda1bvboxsync *
d4a9d525e6f2111d462d2d96462dced6b9ec00efvboxsync * @returns COM status code
d4a9d525e6f2111d462d2d96462dced6b9ec00efvboxsync * @param w New display width
9523921c89c66f4bececdbd5ac95aed0039eda1bvboxsync * @param h New display height
d4a9d525e6f2111d462d2d96462dced6b9ec00efvboxsync */
d4a9d525e6f2111d462d2d96462dced6b9ec00efvboxsyncint Display::handleDisplayResize (int w, int h)
9523921c89c66f4bececdbd5ac95aed0039eda1bvboxsync{
d4a9d525e6f2111d462d2d96462dced6b9ec00efvboxsync LogFlow(("Display::handleDisplayResize(): w=%d, h=%d\n", w, h));
9523921c89c66f4bececdbd5ac95aed0039eda1bvboxsync
d4a9d525e6f2111d462d2d96462dced6b9ec00efvboxsync // if there is no Framebuffer, this call is not interesting
d4a9d525e6f2111d462d2d96462dced6b9ec00efvboxsync if (mFramebuffer == NULL)
9523921c89c66f4bececdbd5ac95aed0039eda1bvboxsync return VINF_SUCCESS;
d4a9d525e6f2111d462d2d96462dced6b9ec00efvboxsync
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.
d4a9d525e6f2111d462d2d96462dced6b9ec00efvboxsync */
9523921c89c66f4bececdbd5ac95aed0039eda1bvboxsync bool f = ASMAtomicCmpXchgU32 (&mu32ResizeStatus, ResizeStatus_InProgress, ResizeStatus_Void);
ed9d3db07648c7e3a979105c15ad752ee9ea18devboxsync AssertRelease(f);NOREF(f);
ed9d3db07648c7e3a979105c15ad752ee9ea18devboxsync
ed9d3db07648c7e3a979105c15ad752ee9ea18devboxsync // callback into the Framebuffer to notify it
ed9d3db07648c7e3a979105c15ad752ee9ea18devboxsync BOOL finished;
ed9d3db07648c7e3a979105c15ad752ee9ea18devboxsync
ed9d3db07648c7e3a979105c15ad752ee9ea18devboxsync mFramebuffer->Lock();
d4a9d525e6f2111d462d2d96462dced6b9ec00efvboxsync
9523921c89c66f4bececdbd5ac95aed0039eda1bvboxsync mFramebuffer->RequestResize(w, h, &finished);
9523921c89c66f4bececdbd5ac95aed0039eda1bvboxsync
5f2b03bf7695dabd71222dba123532a3f76828c1vboxsync if (!finished)
5f2b03bf7695dabd71222dba123532a3f76828c1vboxsync {
9523921c89c66f4bececdbd5ac95aed0039eda1bvboxsync LogFlow(("Display::handleDisplayResize: external framebuffer wants us to wait!\n"));
d4a9d525e6f2111d462d2d96462dced6b9ec00efvboxsync
d4a9d525e6f2111d462d2d96462dced6b9ec00efvboxsync /* Note: The previously obtained framebuffer lock must be preserved.
d4a9d525e6f2111d462d2d96462dced6b9ec00efvboxsync * The EMT keeps the framebuffer lock until the resize process completes.
702a8ee2dc1de96f2f77e97135015d3e243186fdvboxsync */
702a8ee2dc1de96f2f77e97135015d3e243186fdvboxsync
9523921c89c66f4bececdbd5ac95aed0039eda1bvboxsync return VINF_VGA_RESIZE_IN_PROGRESS;
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync }
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync /* Set the status so the 'handleResizeCompleted' would work. */
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync f = ASMAtomicCmpXchgU32 (&mu32ResizeStatus, ResizeStatus_UpdateDisplayData, ResizeStatus_InProgress);
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync AssertRelease(f);NOREF(f);
06ea6bcf23874b662d499b3f130024c98b2dd7a6vboxsync
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync /* The method also unlocks the framebuffer. */
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync handleResizeCompletedEMT();
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync return VINF_SUCCESS;
702a8ee2dc1de96f2f77e97135015d3e243186fdvboxsync}
702a8ee2dc1de96f2f77e97135015d3e243186fdvboxsync
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync/**
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync * Framebuffer has been resized.
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync * Read the new display data and unlock the framebuffer.
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync *
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync * @thread EMT
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync */
2f3883b126a405f92b19e829472f614c7352b4f9vboxsyncvoid Display::handleResizeCompletedEMT (void)
5f2b03bf7695dabd71222dba123532a3f76828c1vboxsync{
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync LogFlowFunc(("\n"));
702a8ee2dc1de96f2f77e97135015d3e243186fdvboxsync if (mFramebuffer)
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync {
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync /* Framebuffer has completed the resize. Update the connector data. */
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync updateDisplayData();
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync
06ea6bcf23874b662d499b3f130024c98b2dd7a6vboxsync mpDrv->pUpPort->pfnSetRenderVRAM (mpDrv->pUpPort, true);
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync /* Unlock framebuffer. */
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync mFramebuffer->Unlock();
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync }
702a8ee2dc1de96f2f77e97135015d3e243186fdvboxsync
702a8ee2dc1de96f2f77e97135015d3e243186fdvboxsync /* Go into non resizing state. */
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync bool f = ASMAtomicCmpXchgU32 (&mu32ResizeStatus, ResizeStatus_Void, ResizeStatus_UpdateDisplayData);
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync AssertRelease(f);NOREF(f);
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync}
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync/**
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync * Notification that the framebuffer has completed the
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync * asynchronous resize processing
5f2b03bf7695dabd71222dba123532a3f76828c1vboxsync *
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync * @returns COM status code
702a8ee2dc1de96f2f77e97135015d3e243186fdvboxsync */
2f3883b126a405f92b19e829472f614c7352b4f9vboxsyncSTDMETHODIMP Display::ResizeCompleted()
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync{
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync LogFlow(("Display::ResizeCompleted\n"));
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync
06ea6bcf23874b662d499b3f130024c98b2dd7a6vboxsync // this is only valid for external framebuffers
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync if (!mFramebuffer)
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync return E_FAIL;
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync
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);
702a8ee2dc1de96f2f77e97135015d3e243186fdvboxsync AssertRelease(f);NOREF(f);
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync return S_OK;
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync}
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync
2f3883b126a405f92b19e829472f614c7352b4f9vboxsyncSTDMETHODIMP Display::GetScreenResolution(ULONG aScreenId, ULONG *aWidth, ULONG *aHeight, ULONG *aBitsPerPixel)
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync{
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync if (aWidth)
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync *aWidth = getWidth();
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync if (aHeight)
702a8ee2dc1de96f2f77e97135015d3e243186fdvboxsync *aHeight = getHeight();
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync if (aBitsPerPixel)
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync *aBitsPerPixel = getBitsPerPixel();
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync return S_OK;
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync}
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync
2f3883b126a405f92b19e829472f614c7352b4f9vboxsyncvoid Display::getFramebufferDimensions(int32_t *px1, int32_t *py1,
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync int32_t *px2, int32_t *py2)
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync{
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync AssertPtrReturnVoid(px1);
702a8ee2dc1de96f2f77e97135015d3e243186fdvboxsync AssertPtrReturnVoid(py1);
702a8ee2dc1de96f2f77e97135015d3e243186fdvboxsync AssertPtrReturnVoid(px2);
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync AssertPtrReturnVoid(py2);
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync *px1 = 0;
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync *py1 = 0;
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync *px2 = getWidth();
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync *py2 = getHeight();
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync}
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync
2f3883b126a405f92b19e829472f614c7352b4f9vboxsyncstatic void checkCoordBounds (int *px, int *py, int *pw, int *ph, int cx, int cy)
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync{
702a8ee2dc1de96f2f77e97135015d3e243186fdvboxsync /* Correct negative x and y coordinates. */
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync if (*px < 0)
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync {
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync *px += *pw; /* Compute xRight which is also the new width. */
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync *pw = (*px < 0) ? 0: *px;
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync *px = 0;
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync }
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync if (*py < 0)
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync {
702a8ee2dc1de96f2f77e97135015d3e243186fdvboxsync *py += *ph; /* Compute xBottom, which is also the new height. */
702a8ee2dc1de96f2f77e97135015d3e243186fdvboxsync *ph = (*py < 0) ? 0: *py;
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync *py = 0;
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync }
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync /* Also check if coords are greater than the display resolution. */
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync if (*px + *pw > cx)
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync *pw = cx > *px ? cx - *px: 0;
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync if (*py + *ph > cy)
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync *ph = cy > *py ? cy - *py: 0;
702a8ee2dc1de96f2f77e97135015d3e243186fdvboxsync}
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync/**
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync * Handle display update
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync *
7e8ef90d3160234df0f254131b87af4243d79476vboxsync * @returns COM status code
7e8ef90d3160234df0f254131b87af4243d79476vboxsync * @param w New display width
7e8ef90d3160234df0f254131b87af4243d79476vboxsync * @param h New display height
7e8ef90d3160234df0f254131b87af4243d79476vboxsync */
7e8ef90d3160234df0f254131b87af4243d79476vboxsyncvoid Display::handleDisplayUpdate (int x, int y, int w, int h)
7e8ef90d3160234df0f254131b87af4243d79476vboxsync{
7e8ef90d3160234df0f254131b87af4243d79476vboxsync // if there is no Framebuffer, this call is not interesting
7e8ef90d3160234df0f254131b87af4243d79476vboxsync if (mFramebuffer == NULL)
7e8ef90d3160234df0f254131b87af4243d79476vboxsync return;
7e8ef90d3160234df0f254131b87af4243d79476vboxsync
7e8ef90d3160234df0f254131b87af4243d79476vboxsync mFramebuffer->Lock();
7e8ef90d3160234df0f254131b87af4243d79476vboxsync
7e8ef90d3160234df0f254131b87af4243d79476vboxsync checkCoordBounds (&x, &y, &w, &h, mpDrv->Connector.cx, mpDrv->Connector.cy);
7e8ef90d3160234df0f254131b87af4243d79476vboxsync
7e8ef90d3160234df0f254131b87af4243d79476vboxsync if (w == 0 || h == 0)
7e8ef90d3160234df0f254131b87af4243d79476vboxsync {
7e8ef90d3160234df0f254131b87af4243d79476vboxsync mFramebuffer->Unlock();
7e8ef90d3160234df0f254131b87af4243d79476vboxsync return;
7e8ef90d3160234df0f254131b87af4243d79476vboxsync }
06ea6bcf23874b662d499b3f130024c98b2dd7a6vboxsync
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync mFramebuffer->NotifyUpdate(x, y, w, h);
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync mFramebuffer->Unlock();
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync}
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync
702a8ee2dc1de96f2f77e97135015d3e243186fdvboxsync// IDisplay properties
702a8ee2dc1de96f2f77e97135015d3e243186fdvboxsync/////////////////////////////////////////////////////////////////////////////
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync/**
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync * Returns the current display width in pixel
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync *
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync * @returns COM status code
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync * @param width Address of result variable.
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync */
702a8ee2dc1de96f2f77e97135015d3e243186fdvboxsyncuint32_t Display::getWidth()
702a8ee2dc1de96f2f77e97135015d3e243186fdvboxsync{
702a8ee2dc1de96f2f77e97135015d3e243186fdvboxsync Assert(mpDrv);
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync return mpDrv->Connector.cx;
702a8ee2dc1de96f2f77e97135015d3e243186fdvboxsync}
702a8ee2dc1de96f2f77e97135015d3e243186fdvboxsync
702a8ee2dc1de96f2f77e97135015d3e243186fdvboxsync/**
702a8ee2dc1de96f2f77e97135015d3e243186fdvboxsync * Returns the current display height in pixel
702a8ee2dc1de96f2f77e97135015d3e243186fdvboxsync *
702a8ee2dc1de96f2f77e97135015d3e243186fdvboxsync * @returns COM status code
702a8ee2dc1de96f2f77e97135015d3e243186fdvboxsync * @param height Address of result variable.
702a8ee2dc1de96f2f77e97135015d3e243186fdvboxsync */
2f3883b126a405f92b19e829472f614c7352b4f9vboxsyncuint32_t Display::getHeight()
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync{
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync Assert(mpDrv);
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync return mpDrv->Connector.cy;
1cd59fdf671ca60c64d77e3f7046aaecf7003824vboxsync}
1cd59fdf671ca60c64d77e3f7046aaecf7003824vboxsync
1cd59fdf671ca60c64d77e3f7046aaecf7003824vboxsync/**
1cd59fdf671ca60c64d77e3f7046aaecf7003824vboxsync * Returns the current display color depth in bits
1cd59fdf671ca60c64d77e3f7046aaecf7003824vboxsync *
1cd59fdf671ca60c64d77e3f7046aaecf7003824vboxsync * @returns COM status code
1cd59fdf671ca60c64d77e3f7046aaecf7003824vboxsync * @param bitsPerPixel Address of result variable.
1cd59fdf671ca60c64d77e3f7046aaecf7003824vboxsync */
1cd59fdf671ca60c64d77e3f7046aaecf7003824vboxsyncuint32_t Display::getBitsPerPixel()
1cd59fdf671ca60c64d77e3f7046aaecf7003824vboxsync{
1cd59fdf671ca60c64d77e3f7046aaecf7003824vboxsync Assert(mpDrv);
1cd59fdf671ca60c64d77e3f7046aaecf7003824vboxsync return mpDrv->Connector.cBits;
1cd59fdf671ca60c64d77e3f7046aaecf7003824vboxsync}
1cd59fdf671ca60c64d77e3f7046aaecf7003824vboxsync
1cd59fdf671ca60c64d77e3f7046aaecf7003824vboxsyncvoid Display::updatePointerShape(bool fVisible, bool fAlpha, uint32_t xHot, uint32_t yHot, uint32_t width, uint32_t height, void *pShape)
1cd59fdf671ca60c64d77e3f7046aaecf7003824vboxsync{
1cd59fdf671ca60c64d77e3f7046aaecf7003824vboxsync}
1cd59fdf671ca60c64d77e3f7046aaecf7003824vboxsync
1cd59fdf671ca60c64d77e3f7046aaecf7003824vboxsync
1cd59fdf671ca60c64d77e3f7046aaecf7003824vboxsync// IDisplay methods
1cd59fdf671ca60c64d77e3f7046aaecf7003824vboxsync/////////////////////////////////////////////////////////////////////////////
1cd59fdf671ca60c64d77e3f7046aaecf7003824vboxsync
1cd59fdf671ca60c64d77e3f7046aaecf7003824vboxsync/**
1cd59fdf671ca60c64d77e3f7046aaecf7003824vboxsync * Registers an external Framebuffer
1cd59fdf671ca60c64d77e3f7046aaecf7003824vboxsync *
1cd59fdf671ca60c64d77e3f7046aaecf7003824vboxsync * @returns COM status code
1cd59fdf671ca60c64d77e3f7046aaecf7003824vboxsync * @param Framebuffer external Framebuffer object
1cd59fdf671ca60c64d77e3f7046aaecf7003824vboxsync */
2f3883b126a405f92b19e829472f614c7352b4f9vboxsyncSTDMETHODIMP Display::SetFramebuffer(unsigned iScreenID, Framebuffer *Framebuffer)
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync{
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync if (!Framebuffer)
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync return E_POINTER;
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync
702a8ee2dc1de96f2f77e97135015d3e243186fdvboxsync // free current Framebuffer (if there is any)
702a8ee2dc1de96f2f77e97135015d3e243186fdvboxsync mFramebuffer = 0;
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync mFramebuffer = Framebuffer;
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync updateDisplayData();
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync return S_OK;
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync}
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync
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. */
2f3883b126a405f92b19e829472f614c7352b4f9vboxsyncvoid
702a8ee2dc1de96f2f77e97135015d3e243186fdvboxsyncDisplay::doInvalidateAndUpdate(struct DRVMAINDISPLAY *mpDrv)
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync{
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync mpDrv->pDisplay->mFramebuffer->Lock();
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync mpDrv->pUpPort->pfnUpdateDisplayAll( mpDrv->pUpPort);
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync mpDrv->pDisplay->mFramebuffer->Unlock();
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync}
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync/**
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync * Does a full invalidation of the VM display and instructs the VM
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync * to update it immediately.
702a8ee2dc1de96f2f77e97135015d3e243186fdvboxsync *
702a8ee2dc1de96f2f77e97135015d3e243186fdvboxsync * @returns COM status code
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync */
2f3883b126a405f92b19e829472f614c7352b4f9vboxsyncSTDMETHODIMP Display::InvalidateAndUpdate()
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync{
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync LogFlow (("Display::InvalidateAndUpdate(): BEGIN\n"));
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync HRESULT rc = S_OK;
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync LogFlow (("Display::InvalidateAndUpdate(): sending DPYUPDATE request\n"));
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync Assert(gpVM);
702a8ee2dc1de96f2f77e97135015d3e243186fdvboxsync /* pdm.h says that this has to be called from the EMT thread */
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync int rcVBox = VMR3ReqCallVoidWait(gpVM, VMCPUID_ANY,
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync (PFNRT)Display::doInvalidateAndUpdate, 1, mpDrv);
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync if (RT_FAILURE(rcVBox))
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync rc = E_FAIL;
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync LogFlow (("Display::InvalidateAndUpdate(): END: rc=%08X\n", rc));
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync return rc;
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync}
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync
702a8ee2dc1de96f2f77e97135015d3e243186fdvboxsync// private methods
702a8ee2dc1de96f2f77e97135015d3e243186fdvboxsync/////////////////////////////////////////////////////////////////////////////
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync/**
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync * Helper to update the display information from the Framebuffer
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync *
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync */
2f3883b126a405f92b19e829472f614c7352b4f9vboxsyncvoid Display::updateDisplayData()
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync{
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync while(!mFramebuffer)
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync {
702a8ee2dc1de96f2f77e97135015d3e243186fdvboxsync#if RT_OS_L4
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync asm volatile ("nop":::"memory");
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync l4_sleep(5);
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync#else
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync RTThreadYield();
d4a9d525e6f2111d462d2d96462dced6b9ec00efvboxsync#endif
d4a9d525e6f2111d462d2d96462dced6b9ec00efvboxsync }
d4a9d525e6f2111d462d2d96462dced6b9ec00efvboxsync Assert(mFramebuffer);
d4a9d525e6f2111d462d2d96462dced6b9ec00efvboxsync // the driver might not have been constructed yet
d4a9d525e6f2111d462d2d96462dced6b9ec00efvboxsync if (mpDrv)
d4a9d525e6f2111d462d2d96462dced6b9ec00efvboxsync {
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);
d4a9d525e6f2111d462d2d96462dced6b9ec00efvboxsync mpDrv->pUpPort->pfnSetRenderVRAM (mpDrv->pUpPort,
5f2b03bf7695dabd71222dba123532a3f76828c1vboxsync !!(mpDrv->Connector.pu8Data != (uint8_t*)~0UL));
d4a9d525e6f2111d462d2d96462dced6b9ec00efvboxsync }
d4a9d525e6f2111d462d2d96462dced6b9ec00efvboxsync}
d4a9d525e6f2111d462d2d96462dced6b9ec00efvboxsync
d4a9d525e6f2111d462d2d96462dced6b9ec00efvboxsyncvoid Display::resetFramebuffer()
d4a9d525e6f2111d462d2d96462dced6b9ec00efvboxsync{
d4a9d525e6f2111d462d2d96462dced6b9ec00efvboxsync if (!mFramebuffer)
d4a9d525e6f2111d462d2d96462dced6b9ec00efvboxsync return;
4121d226ac899f17e13aff3aff42b603c8b5c1fevboxsync
35e6d303696e46d969aaf9a59cc381333a483b0bvboxsync // the driver might not have been constructed yet
35e6d303696e46d969aaf9a59cc381333a483b0bvboxsync if (mpDrv)
35e6d303696e46d969aaf9a59cc381333a483b0bvboxsync {
35e6d303696e46d969aaf9a59cc381333a483b0bvboxsync mFramebuffer->getAddress ((uintptr_t *)&mpDrv->Connector.pu8Data);
5366e994777f9d9391cf809dc77610f57270d75dvboxsync mFramebuffer->getBitsPerPixel ((ULONG*)&mpDrv->Connector.cBits);
5366e994777f9d9391cf809dc77610f57270d75dvboxsync mpDrv->pUpPort->pfnSetRenderVRAM (mpDrv->pUpPort,
5366e994777f9d9391cf809dc77610f57270d75dvboxsync !!(mpDrv->Connector.pu8Data != (uint8_t*)~0UL));
6b9d50a0f466bd5a61458ed53925480ab28a3c17vboxsync }
35e6d303696e46d969aaf9a59cc381333a483b0bvboxsync}
35e6d303696e46d969aaf9a59cc381333a483b0bvboxsync
35e6d303696e46d969aaf9a59cc381333a483b0bvboxsync/**
35e6d303696e46d969aaf9a59cc381333a483b0bvboxsync * Handle display resize event
35e6d303696e46d969aaf9a59cc381333a483b0bvboxsync *
35e6d303696e46d969aaf9a59cc381333a483b0bvboxsync * @param pInterface Display connector.
35e6d303696e46d969aaf9a59cc381333a483b0bvboxsync * @param cx New width in pixels.
35e6d303696e46d969aaf9a59cc381333a483b0bvboxsync * @param cy New height in pixels.
35e6d303696e46d969aaf9a59cc381333a483b0bvboxsync */
35e6d303696e46d969aaf9a59cc381333a483b0bvboxsyncDECLCALLBACK(int) Display::displayResizeCallback(PPDMIDISPLAYCONNECTOR pInterface, uint32_t bpp, void *pvVRAM, uint32_t cbLine, uint32_t cx, uint32_t cy)
35e6d303696e46d969aaf9a59cc381333a483b0bvboxsync{
35e6d303696e46d969aaf9a59cc381333a483b0bvboxsync PDRVMAINDISPLAY pDrv = PDMIDISPLAYCONNECTOR_2_MAINDISPLAY(pInterface);
35e6d303696e46d969aaf9a59cc381333a483b0bvboxsync
35e6d303696e46d969aaf9a59cc381333a483b0bvboxsync // forward call to instance handler
35e6d303696e46d969aaf9a59cc381333a483b0bvboxsync return pDrv->pDisplay->handleDisplayResize(cx, cy);
35e6d303696e46d969aaf9a59cc381333a483b0bvboxsync}
35e6d303696e46d969aaf9a59cc381333a483b0bvboxsync
35e6d303696e46d969aaf9a59cc381333a483b0bvboxsync/**
35e6d303696e46d969aaf9a59cc381333a483b0bvboxsync * Handle display update
35e6d303696e46d969aaf9a59cc381333a483b0bvboxsync *
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.
35e6d303696e46d969aaf9a59cc381333a483b0bvboxsync */
35e6d303696e46d969aaf9a59cc381333a483b0bvboxsyncDECLCALLBACK(void) Display::displayUpdateCallback(PPDMIDISPLAYCONNECTOR pInterface,
35e6d303696e46d969aaf9a59cc381333a483b0bvboxsync uint32_t x, uint32_t y, uint32_t cx, uint32_t cy)
35e6d303696e46d969aaf9a59cc381333a483b0bvboxsync{
35e6d303696e46d969aaf9a59cc381333a483b0bvboxsync PDRVMAINDISPLAY pDrv = PDMIDISPLAYCONNECTOR_2_MAINDISPLAY(pInterface);
35e6d303696e46d969aaf9a59cc381333a483b0bvboxsync
35e6d303696e46d969aaf9a59cc381333a483b0bvboxsync // forward call to instance handler
35e6d303696e46d969aaf9a59cc381333a483b0bvboxsync pDrv->pDisplay->handleDisplayUpdate(x, y, cx, cy);
35e6d303696e46d969aaf9a59cc381333a483b0bvboxsync}
35e6d303696e46d969aaf9a59cc381333a483b0bvboxsync
35e6d303696e46d969aaf9a59cc381333a483b0bvboxsync/**
35e6d303696e46d969aaf9a59cc381333a483b0bvboxsync * Periodic display refresh callback.
35e6d303696e46d969aaf9a59cc381333a483b0bvboxsync *
35e6d303696e46d969aaf9a59cc381333a483b0bvboxsync * @param pInterface Display connector.
35e6d303696e46d969aaf9a59cc381333a483b0bvboxsync */
35e6d303696e46d969aaf9a59cc381333a483b0bvboxsyncDECLCALLBACK(void) Display::displayRefreshCallback(PPDMIDISPLAYCONNECTOR pInterface)
35e6d303696e46d969aaf9a59cc381333a483b0bvboxsync{
35e6d303696e46d969aaf9a59cc381333a483b0bvboxsync PDRVMAINDISPLAY pDrv = PDMIDISPLAYCONNECTOR_2_MAINDISPLAY(pInterface);
35e6d303696e46d969aaf9a59cc381333a483b0bvboxsync
35e6d303696e46d969aaf9a59cc381333a483b0bvboxsync
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. */
4121d226ac899f17e13aff3aff42b603c8b5c1fevboxsync
4121d226ac899f17e13aff3aff42b603c8b5c1fevboxsync Display *pDisplay = pDrv->pDisplay;
4121d226ac899f17e13aff3aff42b603c8b5c1fevboxsync
35e6d303696e46d969aaf9a59cc381333a483b0bvboxsync uint32_t u32ResizeStatus = pDisplay->mu32ResizeStatus;
4121d226ac899f17e13aff3aff42b603c8b5c1fevboxsync
4121d226ac899f17e13aff3aff42b603c8b5c1fevboxsync if (u32ResizeStatus == ResizeStatus_UpdateDisplayData)
4121d226ac899f17e13aff3aff42b603c8b5c1fevboxsync {
4121d226ac899f17e13aff3aff42b603c8b5c1fevboxsync#ifdef DEBUG_sunlover
4121d226ac899f17e13aff3aff42b603c8b5c1fevboxsync LogFlowFunc (("ResizeStatus_UpdateDisplayData\n"));
4121d226ac899f17e13aff3aff42b603c8b5c1fevboxsync#endif /* DEBUG_sunlover */
35e6d303696e46d969aaf9a59cc381333a483b0bvboxsync /* The framebuffer was resized and display data need to be updated. */
35e6d303696e46d969aaf9a59cc381333a483b0bvboxsync pDisplay->handleResizeCompletedEMT ();
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 pDrv->pUpPort->pfnUpdateDisplayAll(pDrv->pUpPort);
ca3db470494a8b6eaec69ea37468a5cda65e2da8vboxsync /* Ignore the refresh to replay the logic. */
ca3db470494a8b6eaec69ea37468a5cda65e2da8vboxsync return;
ca3db470494a8b6eaec69ea37468a5cda65e2da8vboxsync }
ca3db470494a8b6eaec69ea37468a5cda65e2da8vboxsync else if (u32ResizeStatus == ResizeStatus_InProgress)
ca3db470494a8b6eaec69ea37468a5cda65e2da8vboxsync {
ca3db470494a8b6eaec69ea37468a5cda65e2da8vboxsync#ifdef DEBUG_sunlover
ca3db470494a8b6eaec69ea37468a5cda65e2da8vboxsync LogFlowFunc (("ResizeStatus_InProcess\n"));
ca3db470494a8b6eaec69ea37468a5cda65e2da8vboxsync#endif /* DEBUG_sunlover */
ca3db470494a8b6eaec69ea37468a5cda65e2da8vboxsync /* The framebuffer is being resized. Do not call the VGA device back. Immediately return. */
ca3db470494a8b6eaec69ea37468a5cda65e2da8vboxsync return;
ca3db470494a8b6eaec69ea37468a5cda65e2da8vboxsync }
ca3db470494a8b6eaec69ea37468a5cda65e2da8vboxsync
ca3db470494a8b6eaec69ea37468a5cda65e2da8vboxsync if (pDisplay->mfPendingVideoAccelEnable)
ca3db470494a8b6eaec69ea37468a5cda65e2da8vboxsync {
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 */
ca3db470494a8b6eaec69ea37468a5cda65e2da8vboxsync Assert(pDisplay->mpPendingVbvaMemory);
ca3db470494a8b6eaec69ea37468a5cda65e2da8vboxsync
ca3db470494a8b6eaec69ea37468a5cda65e2da8vboxsync /* Acceleration can not be yet enabled.*/
ca3db470494a8b6eaec69ea37468a5cda65e2da8vboxsync Assert(pDisplay->mpVbvaMemory == NULL);
ca3db470494a8b6eaec69ea37468a5cda65e2da8vboxsync Assert(!pDisplay->mfVideoAccelEnabled);
ca3db470494a8b6eaec69ea37468a5cda65e2da8vboxsync
ca3db470494a8b6eaec69ea37468a5cda65e2da8vboxsync if (pDisplay->mfMachineRunning)
ca3db470494a8b6eaec69ea37468a5cda65e2da8vboxsync {
ca3db470494a8b6eaec69ea37468a5cda65e2da8vboxsync pDisplay->VideoAccelEnable (pDisplay->mfPendingVideoAccelEnable, pDisplay->mpPendingVbvaMemory);
ca3db470494a8b6eaec69ea37468a5cda65e2da8vboxsync
ca3db470494a8b6eaec69ea37468a5cda65e2da8vboxsync /* Reset the pending state. */
ca3db470494a8b6eaec69ea37468a5cda65e2da8vboxsync pDisplay->mfPendingVideoAccelEnable = false;
ca3db470494a8b6eaec69ea37468a5cda65e2da8vboxsync pDisplay->mpPendingVbvaMemory = NULL;
ca3db470494a8b6eaec69ea37468a5cda65e2da8vboxsync }
ca3db470494a8b6eaec69ea37468a5cda65e2da8vboxsync }
ca3db470494a8b6eaec69ea37468a5cda65e2da8vboxsync else
ca3db470494a8b6eaec69ea37468a5cda65e2da8vboxsync {
ca3db470494a8b6eaec69ea37468a5cda65e2da8vboxsync Assert(pDisplay->mpPendingVbvaMemory == NULL);
ca3db470494a8b6eaec69ea37468a5cda65e2da8vboxsync
ca3db470494a8b6eaec69ea37468a5cda65e2da8vboxsync if (pDisplay->mfVideoAccelEnabled)
ca3db470494a8b6eaec69ea37468a5cda65e2da8vboxsync {
ca3db470494a8b6eaec69ea37468a5cda65e2da8vboxsync Assert(pDisplay->mpVbvaMemory);
ca3db470494a8b6eaec69ea37468a5cda65e2da8vboxsync pDisplay->VideoAccelFlush ();
ca3db470494a8b6eaec69ea37468a5cda65e2da8vboxsync }
ca3db470494a8b6eaec69ea37468a5cda65e2da8vboxsync else
ca3db470494a8b6eaec69ea37468a5cda65e2da8vboxsync {
ca3db470494a8b6eaec69ea37468a5cda65e2da8vboxsync Assert(pDrv->Connector.pu8Data);
ca3db470494a8b6eaec69ea37468a5cda65e2da8vboxsync pDisplay->mFramebuffer->Lock();
ca3db470494a8b6eaec69ea37468a5cda65e2da8vboxsync pDrv->pUpPort->pfnUpdateDisplay(pDrv->pUpPort);
ca3db470494a8b6eaec69ea37468a5cda65e2da8vboxsync pDisplay->mFramebuffer->Unlock();
ca3db470494a8b6eaec69ea37468a5cda65e2da8vboxsync }
ca3db470494a8b6eaec69ea37468a5cda65e2da8vboxsync }
ca3db470494a8b6eaec69ea37468a5cda65e2da8vboxsync}
ca3db470494a8b6eaec69ea37468a5cda65e2da8vboxsync
ca3db470494a8b6eaec69ea37468a5cda65e2da8vboxsync/**
ca3db470494a8b6eaec69ea37468a5cda65e2da8vboxsync * Reset notification
ca3db470494a8b6eaec69ea37468a5cda65e2da8vboxsync *
ca3db470494a8b6eaec69ea37468a5cda65e2da8vboxsync * @param pInterface Display connector.
ca3db470494a8b6eaec69ea37468a5cda65e2da8vboxsync */
ca3db470494a8b6eaec69ea37468a5cda65e2da8vboxsyncDECLCALLBACK(void) Display::displayResetCallback(PPDMIDISPLAYCONNECTOR pInterface)
ca3db470494a8b6eaec69ea37468a5cda65e2da8vboxsync{
ca3db470494a8b6eaec69ea37468a5cda65e2da8vboxsync PDRVMAINDISPLAY pDrv = PDMIDISPLAYCONNECTOR_2_MAINDISPLAY(pInterface);
ca3db470494a8b6eaec69ea37468a5cda65e2da8vboxsync
ca3db470494a8b6eaec69ea37468a5cda65e2da8vboxsync LogFlow(("Display::displayResetCallback\n"));
ca3db470494a8b6eaec69ea37468a5cda65e2da8vboxsync
ca3db470494a8b6eaec69ea37468a5cda65e2da8vboxsync /* Disable VBVA mode. */
ca3db470494a8b6eaec69ea37468a5cda65e2da8vboxsync pDrv->pDisplay->VideoAccelEnable (false, NULL);
ca3db470494a8b6eaec69ea37468a5cda65e2da8vboxsync}
ca3db470494a8b6eaec69ea37468a5cda65e2da8vboxsync
ca3db470494a8b6eaec69ea37468a5cda65e2da8vboxsync/**
ca3db470494a8b6eaec69ea37468a5cda65e2da8vboxsync * LFBModeChange notification
ca3db470494a8b6eaec69ea37468a5cda65e2da8vboxsync *
ca3db470494a8b6eaec69ea37468a5cda65e2da8vboxsync * @see PDMIDISPLAYCONNECTOR::pfnLFBModeChange
ca3db470494a8b6eaec69ea37468a5cda65e2da8vboxsync */
ca3db470494a8b6eaec69ea37468a5cda65e2da8vboxsyncDECLCALLBACK(void) Display::displayLFBModeChangeCallback(PPDMIDISPLAYCONNECTOR pInterface, bool fEnabled)
ca3db470494a8b6eaec69ea37468a5cda65e2da8vboxsync{
ca3db470494a8b6eaec69ea37468a5cda65e2da8vboxsync PDRVMAINDISPLAY pDrv = PDMIDISPLAYCONNECTOR_2_MAINDISPLAY(pInterface);
ca3db470494a8b6eaec69ea37468a5cda65e2da8vboxsync
ca3db470494a8b6eaec69ea37468a5cda65e2da8vboxsync LogFlow(("Display::displayLFBModeChangeCallback: %d\n", fEnabled));
ca3db470494a8b6eaec69ea37468a5cda65e2da8vboxsync
ca3db470494a8b6eaec69ea37468a5cda65e2da8vboxsync NOREF(fEnabled);
ca3db470494a8b6eaec69ea37468a5cda65e2da8vboxsync
ca3db470494a8b6eaec69ea37468a5cda65e2da8vboxsync /**
ca3db470494a8b6eaec69ea37468a5cda65e2da8vboxsync * @todo: If we got the callback then VM if definitely running.
ca3db470494a8b6eaec69ea37468a5cda65e2da8vboxsync * But a better method should be implemented.
ca3db470494a8b6eaec69ea37468a5cda65e2da8vboxsync */
ca3db470494a8b6eaec69ea37468a5cda65e2da8vboxsync pDrv->pDisplay->mfMachineRunning = true;
ca3db470494a8b6eaec69ea37468a5cda65e2da8vboxsync
ca3db470494a8b6eaec69ea37468a5cda65e2da8vboxsync /* Disable VBVA mode in any case. The guest driver reenables VBVA mode if necessary. */
ca3db470494a8b6eaec69ea37468a5cda65e2da8vboxsync pDrv->pDisplay->VideoAccelEnable (false, NULL);
ca3db470494a8b6eaec69ea37468a5cda65e2da8vboxsync}
ca3db470494a8b6eaec69ea37468a5cda65e2da8vboxsync
ca3db470494a8b6eaec69ea37468a5cda65e2da8vboxsyncDECLCALLBACK(void) Display::displayProcessAdapterDataCallback(PPDMIDISPLAYCONNECTOR pInterface, void *pvVRAM, uint32_t u32VRAMSize)
ca3db470494a8b6eaec69ea37468a5cda65e2da8vboxsync{
ca3db470494a8b6eaec69ea37468a5cda65e2da8vboxsync NOREF(pInterface);
ca3db470494a8b6eaec69ea37468a5cda65e2da8vboxsync NOREF(pvVRAM);
ca3db470494a8b6eaec69ea37468a5cda65e2da8vboxsync NOREF(u32VRAMSize);
ca3db470494a8b6eaec69ea37468a5cda65e2da8vboxsync}
ca3db470494a8b6eaec69ea37468a5cda65e2da8vboxsync
ca3db470494a8b6eaec69ea37468a5cda65e2da8vboxsyncDECLCALLBACK(void) Display::displayProcessDisplayDataCallback(PPDMIDISPLAYCONNECTOR pInterface, void *pvVRAM, unsigned uScreenId)
ca3db470494a8b6eaec69ea37468a5cda65e2da8vboxsync{
ca3db470494a8b6eaec69ea37468a5cda65e2da8vboxsync NOREF(pInterface);
ca3db470494a8b6eaec69ea37468a5cda65e2da8vboxsync NOREF(pvVRAM);
ca3db470494a8b6eaec69ea37468a5cda65e2da8vboxsync NOREF(uScreenId);
ca3db470494a8b6eaec69ea37468a5cda65e2da8vboxsync}
ca3db470494a8b6eaec69ea37468a5cda65e2da8vboxsync
ca3db470494a8b6eaec69ea37468a5cda65e2da8vboxsync
8bc8d66f188d5357155b8340e2d489573be2b607vboxsynctypedef struct _VBVADIRTYREGION
8bc8d66f188d5357155b8340e2d489573be2b607vboxsync{
8bc8d66f188d5357155b8340e2d489573be2b607vboxsync /* Copies of object's pointers used by vbvaRgn functions. */
8bc8d66f188d5357155b8340e2d489573be2b607vboxsync Framebuffer *pFramebuffer;
8bc8d66f188d5357155b8340e2d489573be2b607vboxsync Display *pDisplay;
8bc8d66f188d5357155b8340e2d489573be2b607vboxsync PPDMIDISPLAYPORT pPort;
88cc9bf61296bc5526344415167bb2625ae1dd99vboxsync
8bc8d66f188d5357155b8340e2d489573be2b607vboxsync /* Merged rectangles. */
88cc9bf61296bc5526344415167bb2625ae1dd99vboxsync int32_t xLeft;
88cc9bf61296bc5526344415167bb2625ae1dd99vboxsync int32_t xRight;
88cc9bf61296bc5526344415167bb2625ae1dd99vboxsync int32_t yTop;
88cc9bf61296bc5526344415167bb2625ae1dd99vboxsync int32_t yBottom;
8bc8d66f188d5357155b8340e2d489573be2b607vboxsync
88cc9bf61296bc5526344415167bb2625ae1dd99vboxsync} VBVADIRTYREGION;
8bc8d66f188d5357155b8340e2d489573be2b607vboxsync
88cc9bf61296bc5526344415167bb2625ae1dd99vboxsyncvoid vbvaRgnInit (VBVADIRTYREGION *prgn, Framebuffer *pfb, Display *pd, PPDMIDISPLAYPORT pp)
88cc9bf61296bc5526344415167bb2625ae1dd99vboxsync{
8bc8d66f188d5357155b8340e2d489573be2b607vboxsync memset (prgn, 0, sizeof (VBVADIRTYREGION));
88cc9bf61296bc5526344415167bb2625ae1dd99vboxsync
88cc9bf61296bc5526344415167bb2625ae1dd99vboxsync prgn->pFramebuffer = pfb;
8bc8d66f188d5357155b8340e2d489573be2b607vboxsync prgn->pDisplay = pd;
88cc9bf61296bc5526344415167bb2625ae1dd99vboxsync prgn->pPort = pp;
88cc9bf61296bc5526344415167bb2625ae1dd99vboxsync
8bc8d66f188d5357155b8340e2d489573be2b607vboxsync return;
8bc8d66f188d5357155b8340e2d489573be2b607vboxsync}
8bc8d66f188d5357155b8340e2d489573be2b607vboxsync
8bc8d66f188d5357155b8340e2d489573be2b607vboxsyncvoid vbvaRgnDirtyRect (VBVADIRTYREGION *prgn, VBVACMDHDR *phdr)
8bc8d66f188d5357155b8340e2d489573be2b607vboxsync{
687794577e2e35c3cae67e692a7f2130d1262a82vboxsync LogFlow(("vbvaRgnDirtyRect: x = %d, y = %d, w = %d, h = %d\n", phdr->x, phdr->y, phdr->w, phdr->h));
687794577e2e35c3cae67e692a7f2130d1262a82vboxsync
907b6adfa052386a0666d5557bee9bdbc100c2e5vboxsync /*
907b6adfa052386a0666d5557bee9bdbc100c2e5vboxsync * Here update rectangles are accumulated to form an update area.
687794577e2e35c3cae67e692a7f2130d1262a82vboxsync * @todo
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.
cc1ef2ef9bbc6a0ff964928d61b7298e5bfcce5fvboxsync */
cc1ef2ef9bbc6a0ff964928d61b7298e5bfcce5fvboxsync if (phdr->w == 0 || phdr->h == 0)
cc1ef2ef9bbc6a0ff964928d61b7298e5bfcce5fvboxsync {
907b6adfa052386a0666d5557bee9bdbc100c2e5vboxsync /* Empty rectangle. */
687794577e2e35c3cae67e692a7f2130d1262a82vboxsync return;
cc1ef2ef9bbc6a0ff964928d61b7298e5bfcce5fvboxsync }
687794577e2e35c3cae67e692a7f2130d1262a82vboxsync
687794577e2e35c3cae67e692a7f2130d1262a82vboxsync int32_t xRight = phdr->x + phdr->w;
687794577e2e35c3cae67e692a7f2130d1262a82vboxsync int32_t yBottom = phdr->y + phdr->h;
687794577e2e35c3cae67e692a7f2130d1262a82vboxsync
687794577e2e35c3cae67e692a7f2130d1262a82vboxsync if (prgn->xRight == 0)
687794577e2e35c3cae67e692a7f2130d1262a82vboxsync {
907b6adfa052386a0666d5557bee9bdbc100c2e5vboxsync /* This is the first rectangle to be added. */
687794577e2e35c3cae67e692a7f2130d1262a82vboxsync prgn->xLeft = phdr->x;
907b6adfa052386a0666d5557bee9bdbc100c2e5vboxsync prgn->yTop = phdr->y;
907b6adfa052386a0666d5557bee9bdbc100c2e5vboxsync prgn->xRight = xRight;
907b6adfa052386a0666d5557bee9bdbc100c2e5vboxsync prgn->yBottom = yBottom;
907b6adfa052386a0666d5557bee9bdbc100c2e5vboxsync }
907b6adfa052386a0666d5557bee9bdbc100c2e5vboxsync else
687794577e2e35c3cae67e692a7f2130d1262a82vboxsync {
687794577e2e35c3cae67e692a7f2130d1262a82vboxsync /* Adjust region coordinates. */
d4a9d525e6f2111d462d2d96462dced6b9ec00efvboxsync if (prgn->xLeft > phdr->x)
d4a9d525e6f2111d462d2d96462dced6b9ec00efvboxsync prgn->xLeft = phdr->x;
d4a9d525e6f2111d462d2d96462dced6b9ec00efvboxsync
d4a9d525e6f2111d462d2d96462dced6b9ec00efvboxsync if (prgn->yTop > phdr->y)
d4a9d525e6f2111d462d2d96462dced6b9ec00efvboxsync prgn->yTop = phdr->y;
d4a9d525e6f2111d462d2d96462dced6b9ec00efvboxsync
d4a9d525e6f2111d462d2d96462dced6b9ec00efvboxsync if (prgn->xRight < xRight)
d4a9d525e6f2111d462d2d96462dced6b9ec00efvboxsync prgn->xRight = xRight;
d4a9d525e6f2111d462d2d96462dced6b9ec00efvboxsync
5f2b03bf7695dabd71222dba123532a3f76828c1vboxsync if (prgn->yBottom < yBottom)
d4a9d525e6f2111d462d2d96462dced6b9ec00efvboxsync prgn->yBottom = yBottom;
d4a9d525e6f2111d462d2d96462dced6b9ec00efvboxsync }
d4a9d525e6f2111d462d2d96462dced6b9ec00efvboxsync}
d4a9d525e6f2111d462d2d96462dced6b9ec00efvboxsync
d4a9d525e6f2111d462d2d96462dced6b9ec00efvboxsyncvoid vbvaRgnUpdateFramebuffer (VBVADIRTYREGION *prgn)
d4a9d525e6f2111d462d2d96462dced6b9ec00efvboxsync{
d4a9d525e6f2111d462d2d96462dced6b9ec00efvboxsync uint32_t w = prgn->xRight - prgn->xLeft;
004d74842597dacc4009803171296dfcf9398c69vboxsync uint32_t h = prgn->yBottom - prgn->yTop;
004d74842597dacc4009803171296dfcf9398c69vboxsync
004d74842597dacc4009803171296dfcf9398c69vboxsync if (prgn->pFramebuffer && w != 0 && h != 0)
004d74842597dacc4009803171296dfcf9398c69vboxsync {
004d74842597dacc4009803171296dfcf9398c69vboxsync prgn->pPort->pfnUpdateDisplayRect (prgn->pPort, prgn->xLeft, prgn->yTop, w, h);
004d74842597dacc4009803171296dfcf9398c69vboxsync prgn->pDisplay->handleDisplayUpdate (prgn->xLeft, prgn->yTop, w, h);
004d74842597dacc4009803171296dfcf9398c69vboxsync }
004d74842597dacc4009803171296dfcf9398c69vboxsync}
004d74842597dacc4009803171296dfcf9398c69vboxsync
004d74842597dacc4009803171296dfcf9398c69vboxsyncstatic void vbvaSetMemoryFlags (VBVAMEMORY *pVbvaMemory, bool fVideoAccelEnabled, bool fVideoAccelVRDP)
004d74842597dacc4009803171296dfcf9398c69vboxsync{
004d74842597dacc4009803171296dfcf9398c69vboxsync if (pVbvaMemory)
004d74842597dacc4009803171296dfcf9398c69vboxsync {
004d74842597dacc4009803171296dfcf9398c69vboxsync /* This called only on changes in mode. So reset VRDP always. */
004d74842597dacc4009803171296dfcf9398c69vboxsync uint32_t fu32Flags = VBVA_F_MODE_VRDP_RESET;
004d74842597dacc4009803171296dfcf9398c69vboxsync
004d74842597dacc4009803171296dfcf9398c69vboxsync if (fVideoAccelEnabled)
004d74842597dacc4009803171296dfcf9398c69vboxsync {
004d74842597dacc4009803171296dfcf9398c69vboxsync fu32Flags |= VBVA_F_MODE_ENABLED;
004d74842597dacc4009803171296dfcf9398c69vboxsync
004d74842597dacc4009803171296dfcf9398c69vboxsync if (fVideoAccelVRDP)
004d74842597dacc4009803171296dfcf9398c69vboxsync fu32Flags |= VBVA_F_MODE_VRDP;
004d74842597dacc4009803171296dfcf9398c69vboxsync }
004d74842597dacc4009803171296dfcf9398c69vboxsync
004d74842597dacc4009803171296dfcf9398c69vboxsync pVbvaMemory->fu32ModeFlags = fu32Flags;
004d74842597dacc4009803171296dfcf9398c69vboxsync }
004d74842597dacc4009803171296dfcf9398c69vboxsync}
004d74842597dacc4009803171296dfcf9398c69vboxsync
004d74842597dacc4009803171296dfcf9398c69vboxsyncbool Display::VideoAccelAllowed (void)
004d74842597dacc4009803171296dfcf9398c69vboxsync{
004d74842597dacc4009803171296dfcf9398c69vboxsync return true;
004d74842597dacc4009803171296dfcf9398c69vboxsync}
004d74842597dacc4009803171296dfcf9398c69vboxsync
004d74842597dacc4009803171296dfcf9398c69vboxsync/**
004d74842597dacc4009803171296dfcf9398c69vboxsync * @thread EMT
004d74842597dacc4009803171296dfcf9398c69vboxsync */
004d74842597dacc4009803171296dfcf9398c69vboxsyncint Display::VideoAccelEnable (bool fEnable, VBVAMEMORY *pVbvaMemory)
004d74842597dacc4009803171296dfcf9398c69vboxsync{
004d74842597dacc4009803171296dfcf9398c69vboxsync int rc = VINF_SUCCESS;
004d74842597dacc4009803171296dfcf9398c69vboxsync
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 *
004d74842597dacc4009803171296dfcf9398c69vboxsync * VGA device disables acceleration on each video mode change
004d74842597dacc4009803171296dfcf9398c69vboxsync * and on reset.
004d74842597dacc4009803171296dfcf9398c69vboxsync *
004d74842597dacc4009803171296dfcf9398c69vboxsync * Guest enabled acceleration at will. And it needs to enable
004d74842597dacc4009803171296dfcf9398c69vboxsync * acceleration after a mode change.
004d74842597dacc4009803171296dfcf9398c69vboxsync */
004d74842597dacc4009803171296dfcf9398c69vboxsync LogFlow(("Display::VideoAccelEnable: mfVideoAccelEnabled = %d, fEnable = %d, pVbvaMemory = %p\n",
004d74842597dacc4009803171296dfcf9398c69vboxsync mfVideoAccelEnabled, fEnable, pVbvaMemory));
004d74842597dacc4009803171296dfcf9398c69vboxsync
004d74842597dacc4009803171296dfcf9398c69vboxsync /* Strictly check parameters. Callers must not pass anything in the case. */
004d74842597dacc4009803171296dfcf9398c69vboxsync Assert((fEnable && pVbvaMemory) || (!fEnable && pVbvaMemory == NULL));
004d74842597dacc4009803171296dfcf9398c69vboxsync
004d74842597dacc4009803171296dfcf9398c69vboxsync if (!VideoAccelAllowed ())
004d74842597dacc4009803171296dfcf9398c69vboxsync return VERR_NOT_SUPPORTED;
004d74842597dacc4009803171296dfcf9398c69vboxsync
004d74842597dacc4009803171296dfcf9398c69vboxsync /*
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 */
004d74842597dacc4009803171296dfcf9398c69vboxsync if (!mfMachineRunning)
004d74842597dacc4009803171296dfcf9398c69vboxsync {
004d74842597dacc4009803171296dfcf9398c69vboxsync Assert (!mfVideoAccelEnabled);
004d74842597dacc4009803171296dfcf9398c69vboxsync
004d74842597dacc4009803171296dfcf9398c69vboxsync LogFlow(("Display::VideoAccelEnable: Machine is not yet running.\n"));
004d74842597dacc4009803171296dfcf9398c69vboxsync
004d74842597dacc4009803171296dfcf9398c69vboxsync if (fEnable)
004d74842597dacc4009803171296dfcf9398c69vboxsync {
004d74842597dacc4009803171296dfcf9398c69vboxsync mfPendingVideoAccelEnable = fEnable;
004d74842597dacc4009803171296dfcf9398c69vboxsync mpPendingVbvaMemory = pVbvaMemory;
004d74842597dacc4009803171296dfcf9398c69vboxsync }
004d74842597dacc4009803171296dfcf9398c69vboxsync
004d74842597dacc4009803171296dfcf9398c69vboxsync return rc;
004d74842597dacc4009803171296dfcf9398c69vboxsync }
004d74842597dacc4009803171296dfcf9398c69vboxsync
004d74842597dacc4009803171296dfcf9398c69vboxsync /* Check that current status is not being changed */
004d74842597dacc4009803171296dfcf9398c69vboxsync if (mfVideoAccelEnabled == fEnable)
004d74842597dacc4009803171296dfcf9398c69vboxsync return rc;
004d74842597dacc4009803171296dfcf9398c69vboxsync
004d74842597dacc4009803171296dfcf9398c69vboxsync if (mfVideoAccelEnabled)
004d74842597dacc4009803171296dfcf9398c69vboxsync {
004d74842597dacc4009803171296dfcf9398c69vboxsync /* Process any pending orders and empty the VBVA ring buffer. */
5366e994777f9d9391cf809dc77610f57270d75dvboxsync VideoAccelFlush ();
5366e994777f9d9391cf809dc77610f57270d75dvboxsync }
5366e994777f9d9391cf809dc77610f57270d75dvboxsync
5366e994777f9d9391cf809dc77610f57270d75dvboxsync if (!fEnable && mpVbvaMemory)
5366e994777f9d9391cf809dc77610f57270d75dvboxsync mpVbvaMemory->fu32ModeFlags &= ~VBVA_F_MODE_ENABLED;
5366e994777f9d9391cf809dc77610f57270d75dvboxsync
88cc9bf61296bc5526344415167bb2625ae1dd99vboxsync /* Safety precaution. There is no more VBVA until everything is setup! */
88cc9bf61296bc5526344415167bb2625ae1dd99vboxsync mpVbvaMemory = NULL;
88cc9bf61296bc5526344415167bb2625ae1dd99vboxsync mfVideoAccelEnabled = false;
88cc9bf61296bc5526344415167bb2625ae1dd99vboxsync
5366e994777f9d9391cf809dc77610f57270d75dvboxsync /* Update entire display. */
88cc9bf61296bc5526344415167bb2625ae1dd99vboxsync mpDrv->pUpPort->pfnUpdateDisplayAll(mpDrv->pUpPort);
5366e994777f9d9391cf809dc77610f57270d75dvboxsync
88cc9bf61296bc5526344415167bb2625ae1dd99vboxsync /* Everything OK. VBVA status can be changed. */
88cc9bf61296bc5526344415167bb2625ae1dd99vboxsync
5366e994777f9d9391cf809dc77610f57270d75dvboxsync /* Notify the VMMDev, which saves VBVA status in the saved state,
88cc9bf61296bc5526344415167bb2625ae1dd99vboxsync * and needs to know current status.
88cc9bf61296bc5526344415167bb2625ae1dd99vboxsync */
5366e994777f9d9391cf809dc77610f57270d75dvboxsync PPDMIVMMDEVPORT pVMMDevPort = gVMMDev->getVMMDevPort ();
88cc9bf61296bc5526344415167bb2625ae1dd99vboxsync
88cc9bf61296bc5526344415167bb2625ae1dd99vboxsync if (pVMMDevPort)
5366e994777f9d9391cf809dc77610f57270d75dvboxsync pVMMDevPort->pfnVBVAChange (pVMMDevPort, fEnable);
5366e994777f9d9391cf809dc77610f57270d75dvboxsync
5366e994777f9d9391cf809dc77610f57270d75dvboxsync if (fEnable)
5366e994777f9d9391cf809dc77610f57270d75dvboxsync {
5366e994777f9d9391cf809dc77610f57270d75dvboxsync mpVbvaMemory = pVbvaMemory;
e378dfdadd62aadc0a012c9953322d979d7606e6vboxsync mfVideoAccelEnabled = true;
e378dfdadd62aadc0a012c9953322d979d7606e6vboxsync
e378dfdadd62aadc0a012c9953322d979d7606e6vboxsync /* Initialize the hardware memory. */
e378dfdadd62aadc0a012c9953322d979d7606e6vboxsync vbvaSetMemoryFlags (mpVbvaMemory, mfVideoAccelEnabled, false);
4121d226ac899f17e13aff3aff42b603c8b5c1fevboxsync mpVbvaMemory->off32Data = 0;
4121d226ac899f17e13aff3aff42b603c8b5c1fevboxsync mpVbvaMemory->off32Free = 0;
4121d226ac899f17e13aff3aff42b603c8b5c1fevboxsync
4121d226ac899f17e13aff3aff42b603c8b5c1fevboxsync memset (mpVbvaMemory->aRecords, 0, sizeof (mpVbvaMemory->aRecords));
4121d226ac899f17e13aff3aff42b603c8b5c1fevboxsync mpVbvaMemory->indexRecordFirst = 0;
4121d226ac899f17e13aff3aff42b603c8b5c1fevboxsync mpVbvaMemory->indexRecordFree = 0;
4121d226ac899f17e13aff3aff42b603c8b5c1fevboxsync
4121d226ac899f17e13aff3aff42b603c8b5c1fevboxsync LogRel(("VBVA: Enabled.\n"));
4121d226ac899f17e13aff3aff42b603c8b5c1fevboxsync }
4121d226ac899f17e13aff3aff42b603c8b5c1fevboxsync else
4121d226ac899f17e13aff3aff42b603c8b5c1fevboxsync {
4121d226ac899f17e13aff3aff42b603c8b5c1fevboxsync LogRel(("VBVA: Disabled.\n"));
4121d226ac899f17e13aff3aff42b603c8b5c1fevboxsync }
4121d226ac899f17e13aff3aff42b603c8b5c1fevboxsync
4121d226ac899f17e13aff3aff42b603c8b5c1fevboxsync LogFlow(("Display::VideoAccelEnable: rc = %Rrc.\n", rc));
4121d226ac899f17e13aff3aff42b603c8b5c1fevboxsync
4121d226ac899f17e13aff3aff42b603c8b5c1fevboxsync return rc;
4121d226ac899f17e13aff3aff42b603c8b5c1fevboxsync}
4121d226ac899f17e13aff3aff42b603c8b5c1fevboxsync
4121d226ac899f17e13aff3aff42b603c8b5c1fevboxsyncstatic bool vbvaVerifyRingBuffer (VBVAMEMORY *pVbvaMemory)
4121d226ac899f17e13aff3aff42b603c8b5c1fevboxsync{
4121d226ac899f17e13aff3aff42b603c8b5c1fevboxsync return true;
4121d226ac899f17e13aff3aff42b603c8b5c1fevboxsync}
4121d226ac899f17e13aff3aff42b603c8b5c1fevboxsync
4121d226ac899f17e13aff3aff42b603c8b5c1fevboxsyncstatic void vbvaFetchBytes (VBVAMEMORY *pVbvaMemory, uint8_t *pu8Dst, uint32_t cbDst)
4121d226ac899f17e13aff3aff42b603c8b5c1fevboxsync{
4121d226ac899f17e13aff3aff42b603c8b5c1fevboxsync if (cbDst >= VBVA_RING_BUFFER_SIZE)
4121d226ac899f17e13aff3aff42b603c8b5c1fevboxsync {
4121d226ac899f17e13aff3aff42b603c8b5c1fevboxsync AssertFailed ();
4121d226ac899f17e13aff3aff42b603c8b5c1fevboxsync return;
4121d226ac899f17e13aff3aff42b603c8b5c1fevboxsync }
4121d226ac899f17e13aff3aff42b603c8b5c1fevboxsync
3ff8aa7d3c74cfbe8da5f77b8ea6c748cc79213avboxsync uint32_t u32BytesTillBoundary = VBVA_RING_BUFFER_SIZE - pVbvaMemory->off32Data;
5366e994777f9d9391cf809dc77610f57270d75dvboxsync uint8_t *src = &pVbvaMemory->au8RingBuffer[pVbvaMemory->off32Data];
5366e994777f9d9391cf809dc77610f57270d75dvboxsync int32_t i32Diff = cbDst - u32BytesTillBoundary;
e378dfdadd62aadc0a012c9953322d979d7606e6vboxsync
6b9d50a0f466bd5a61458ed53925480ab28a3c17vboxsync if (i32Diff <= 0)
e378dfdadd62aadc0a012c9953322d979d7606e6vboxsync {
e378dfdadd62aadc0a012c9953322d979d7606e6vboxsync /* Chunk will not cross buffer boundary. */
e378dfdadd62aadc0a012c9953322d979d7606e6vboxsync memcpy (pu8Dst, src, cbDst);
e378dfdadd62aadc0a012c9953322d979d7606e6vboxsync }
e378dfdadd62aadc0a012c9953322d979d7606e6vboxsync else
e378dfdadd62aadc0a012c9953322d979d7606e6vboxsync {
e378dfdadd62aadc0a012c9953322d979d7606e6vboxsync /* Chunk crosses buffer boundary. */
e378dfdadd62aadc0a012c9953322d979d7606e6vboxsync memcpy (pu8Dst, src, u32BytesTillBoundary);
e378dfdadd62aadc0a012c9953322d979d7606e6vboxsync memcpy (pu8Dst + u32BytesTillBoundary, &pVbvaMemory->au8RingBuffer[0], i32Diff);
5366e994777f9d9391cf809dc77610f57270d75dvboxsync }
5366e994777f9d9391cf809dc77610f57270d75dvboxsync
e378dfdadd62aadc0a012c9953322d979d7606e6vboxsync /* Advance data offset. */
e378dfdadd62aadc0a012c9953322d979d7606e6vboxsync pVbvaMemory->off32Data = (pVbvaMemory->off32Data + cbDst) % VBVA_RING_BUFFER_SIZE;
e378dfdadd62aadc0a012c9953322d979d7606e6vboxsync
e378dfdadd62aadc0a012c9953322d979d7606e6vboxsync return;
5366e994777f9d9391cf809dc77610f57270d75dvboxsync}
e378dfdadd62aadc0a012c9953322d979d7606e6vboxsync
8bc8d66f188d5357155b8340e2d489573be2b607vboxsyncvoid Display::SetVideoModeHint(ULONG aWidth, ULONG aHeight, ULONG aBitsPerPixel, ULONG aDisplay)
e378dfdadd62aadc0a012c9953322d979d7606e6vboxsync{
e378dfdadd62aadc0a012c9953322d979d7606e6vboxsync PPDMIVMMDEVPORT pVMMDevPort = gVMMDev->getVMMDevPort ();
e378dfdadd62aadc0a012c9953322d979d7606e6vboxsync
e378dfdadd62aadc0a012c9953322d979d7606e6vboxsync if (pVMMDevPort)
e378dfdadd62aadc0a012c9953322d979d7606e6vboxsync pVMMDevPort->pfnRequestDisplayChange(pVMMDevPort, aWidth, aHeight, aBitsPerPixel, aDisplay);
5366e994777f9d9391cf809dc77610f57270d75dvboxsync}
5366e994777f9d9391cf809dc77610f57270d75dvboxsync
5366e994777f9d9391cf809dc77610f57270d75dvboxsyncstatic bool vbvaPartialRead (uint8_t **ppu8, uint32_t *pcb, uint32_t cbRecord, VBVAMEMORY *pVbvaMemory)
e378dfdadd62aadc0a012c9953322d979d7606e6vboxsync{
e378dfdadd62aadc0a012c9953322d979d7606e6vboxsync uint8_t *pu8New;
e378dfdadd62aadc0a012c9953322d979d7606e6vboxsync
e378dfdadd62aadc0a012c9953322d979d7606e6vboxsync LogFlow(("MAIN::DisplayImpl::vbvaPartialRead: p = %p, cb = %d, cbRecord 0x%08X\n",
e378dfdadd62aadc0a012c9953322d979d7606e6vboxsync *ppu8, *pcb, cbRecord));
e378dfdadd62aadc0a012c9953322d979d7606e6vboxsync
e378dfdadd62aadc0a012c9953322d979d7606e6vboxsync if (*ppu8)
e378dfdadd62aadc0a012c9953322d979d7606e6vboxsync {
e378dfdadd62aadc0a012c9953322d979d7606e6vboxsync Assert (*pcb);
e378dfdadd62aadc0a012c9953322d979d7606e6vboxsync pu8New = (uint8_t *)RTMemRealloc (*ppu8, cbRecord);
5366e994777f9d9391cf809dc77610f57270d75dvboxsync }
5366e994777f9d9391cf809dc77610f57270d75dvboxsync else
5366e994777f9d9391cf809dc77610f57270d75dvboxsync {
5366e994777f9d9391cf809dc77610f57270d75dvboxsync Assert (!*pcb);
5366e994777f9d9391cf809dc77610f57270d75dvboxsync pu8New = (uint8_t *)RTMemAlloc (cbRecord);
5366e994777f9d9391cf809dc77610f57270d75dvboxsync }
e378dfdadd62aadc0a012c9953322d979d7606e6vboxsync
e378dfdadd62aadc0a012c9953322d979d7606e6vboxsync if (!pu8New)
5366e994777f9d9391cf809dc77610f57270d75dvboxsync {
e378dfdadd62aadc0a012c9953322d979d7606e6vboxsync /* Memory allocation failed, fail the function. */
e378dfdadd62aadc0a012c9953322d979d7606e6vboxsync Log(("MAIN::vbvaPartialRead: failed to (re)alocate memory for partial record!!! cbRecord 0x%08X\n",
e378dfdadd62aadc0a012c9953322d979d7606e6vboxsync cbRecord));
e378dfdadd62aadc0a012c9953322d979d7606e6vboxsync
e378dfdadd62aadc0a012c9953322d979d7606e6vboxsync if (*ppu8)
e378dfdadd62aadc0a012c9953322d979d7606e6vboxsync RTMemFree (*ppu8);
e378dfdadd62aadc0a012c9953322d979d7606e6vboxsync
e378dfdadd62aadc0a012c9953322d979d7606e6vboxsync *ppu8 = NULL;
e378dfdadd62aadc0a012c9953322d979d7606e6vboxsync *pcb = 0;
8bc8d66f188d5357155b8340e2d489573be2b607vboxsync
e378dfdadd62aadc0a012c9953322d979d7606e6vboxsync return false;
e378dfdadd62aadc0a012c9953322d979d7606e6vboxsync }
e378dfdadd62aadc0a012c9953322d979d7606e6vboxsync
e378dfdadd62aadc0a012c9953322d979d7606e6vboxsync /* Fetch data from the ring buffer. */
e378dfdadd62aadc0a012c9953322d979d7606e6vboxsync vbvaFetchBytes (pVbvaMemory, pu8New + *pcb, cbRecord - *pcb);
e378dfdadd62aadc0a012c9953322d979d7606e6vboxsync
e378dfdadd62aadc0a012c9953322d979d7606e6vboxsync *ppu8 = pu8New;
e378dfdadd62aadc0a012c9953322d979d7606e6vboxsync *pcb = cbRecord;
e378dfdadd62aadc0a012c9953322d979d7606e6vboxsync
5f2b03bf7695dabd71222dba123532a3f76828c1vboxsync return true;
5f2b03bf7695dabd71222dba123532a3f76828c1vboxsync}
5f2b03bf7695dabd71222dba123532a3f76828c1vboxsync
5f2b03bf7695dabd71222dba123532a3f76828c1vboxsync/* For contiguous chunks just return the address in the buffer.
5f2b03bf7695dabd71222dba123532a3f76828c1vboxsync * For crossing boundary - allocate a buffer from heap.
7862f4bd000f1eb6c86289f5ac2849e9cf943ca9vboxsync */
7862f4bd000f1eb6c86289f5ac2849e9cf943ca9vboxsyncbool Display::vbvaFetchCmd (VBVACMDHDR **ppHdr, uint32_t *pcbCmd)
7862f4bd000f1eb6c86289f5ac2849e9cf943ca9vboxsync{
7862f4bd000f1eb6c86289f5ac2849e9cf943ca9vboxsync uint32_t indexRecordFirst = mpVbvaMemory->indexRecordFirst;
7862f4bd000f1eb6c86289f5ac2849e9cf943ca9vboxsync uint32_t indexRecordFree = mpVbvaMemory->indexRecordFree;
40c1a23e86c79b24a917a43c186b2e54504d12c1vboxsync
40c1a23e86c79b24a917a43c186b2e54504d12c1vboxsync#ifdef DEBUG_sunlover
40c1a23e86c79b24a917a43c186b2e54504d12c1vboxsync LogFlow(("MAIN::DisplayImpl::vbvaFetchCmd:first = %d, free = %d\n",
40c1a23e86c79b24a917a43c186b2e54504d12c1vboxsync indexRecordFirst, indexRecordFree));
40c1a23e86c79b24a917a43c186b2e54504d12c1vboxsync#endif /* DEBUG_sunlover */
d4a9d525e6f2111d462d2d96462dced6b9ec00efvboxsync
d4a9d525e6f2111d462d2d96462dced6b9ec00efvboxsync if (!vbvaVerifyRingBuffer (mpVbvaMemory))
d4a9d525e6f2111d462d2d96462dced6b9ec00efvboxsync {
d4a9d525e6f2111d462d2d96462dced6b9ec00efvboxsync return false;
d4a9d525e6f2111d462d2d96462dced6b9ec00efvboxsync }
d4a9d525e6f2111d462d2d96462dced6b9ec00efvboxsync
d4a9d525e6f2111d462d2d96462dced6b9ec00efvboxsync if (indexRecordFirst == indexRecordFree)
5f2b03bf7695dabd71222dba123532a3f76828c1vboxsync {
d4a9d525e6f2111d462d2d96462dced6b9ec00efvboxsync /* No records to process. Return without assigning output variables. */
6b9d50a0f466bd5a61458ed53925480ab28a3c17vboxsync return true;
6b9d50a0f466bd5a61458ed53925480ab28a3c17vboxsync }
6b9d50a0f466bd5a61458ed53925480ab28a3c17vboxsync
5f2b03bf7695dabd71222dba123532a3f76828c1vboxsync VBVARECORD *pRecord = &mpVbvaMemory->aRecords[indexRecordFirst];
d4a9d525e6f2111d462d2d96462dced6b9ec00efvboxsync
d4a9d525e6f2111d462d2d96462dced6b9ec00efvboxsync#ifdef DEBUG_sunlover
d4a9d525e6f2111d462d2d96462dced6b9ec00efvboxsync LogFlow(("MAIN::DisplayImpl::vbvaFetchCmd: cbRecord = 0x%08X\n",
d4a9d525e6f2111d462d2d96462dced6b9ec00efvboxsync pRecord->cbRecord));
d4a9d525e6f2111d462d2d96462dced6b9ec00efvboxsync#endif /* DEBUG_sunlover */
d4a9d525e6f2111d462d2d96462dced6b9ec00efvboxsync
d4a9d525e6f2111d462d2d96462dced6b9ec00efvboxsync uint32_t cbRecord = pRecord->cbRecord & ~VBVA_F_RECORD_PARTIAL;
5366e994777f9d9391cf809dc77610f57270d75dvboxsync
5366e994777f9d9391cf809dc77610f57270d75dvboxsync if (mcbVbvaPartial)
5366e994777f9d9391cf809dc77610f57270d75dvboxsync {
5366e994777f9d9391cf809dc77610f57270d75dvboxsync /* There is a partial read in process. Continue with it. */
5366e994777f9d9391cf809dc77610f57270d75dvboxsync
5366e994777f9d9391cf809dc77610f57270d75dvboxsync Assert (mpu8VbvaPartial);
5366e994777f9d9391cf809dc77610f57270d75dvboxsync
5366e994777f9d9391cf809dc77610f57270d75dvboxsync LogFlow(("MAIN::DisplayImpl::vbvaFetchCmd: continue partial record mcbVbvaPartial = %d cbRecord 0x%08X, first = %d, free = %d\n",
5366e994777f9d9391cf809dc77610f57270d75dvboxsync mcbVbvaPartial, pRecord->cbRecord, indexRecordFirst, indexRecordFree));
d4a9d525e6f2111d462d2d96462dced6b9ec00efvboxsync
cc1ef2ef9bbc6a0ff964928d61b7298e5bfcce5fvboxsync if (cbRecord > mcbVbvaPartial)
cc1ef2ef9bbc6a0ff964928d61b7298e5bfcce5fvboxsync {
5366e994777f9d9391cf809dc77610f57270d75dvboxsync /* New data has been added to the record. */
5366e994777f9d9391cf809dc77610f57270d75dvboxsync if (!vbvaPartialRead (&mpu8VbvaPartial, &mcbVbvaPartial, cbRecord, mpVbvaMemory))
5366e994777f9d9391cf809dc77610f57270d75dvboxsync return false;
5366e994777f9d9391cf809dc77610f57270d75dvboxsync }
5366e994777f9d9391cf809dc77610f57270d75dvboxsync
5366e994777f9d9391cf809dc77610f57270d75dvboxsync if (!(pRecord->cbRecord & VBVA_F_RECORD_PARTIAL))
5366e994777f9d9391cf809dc77610f57270d75dvboxsync {
5366e994777f9d9391cf809dc77610f57270d75dvboxsync /* The record is completed by guest. Return it to the caller. */
5366e994777f9d9391cf809dc77610f57270d75dvboxsync *ppHdr = (VBVACMDHDR *)mpu8VbvaPartial;
5366e994777f9d9391cf809dc77610f57270d75dvboxsync *pcbCmd = mcbVbvaPartial;
5366e994777f9d9391cf809dc77610f57270d75dvboxsync
5366e994777f9d9391cf809dc77610f57270d75dvboxsync mpu8VbvaPartial = NULL;
5366e994777f9d9391cf809dc77610f57270d75dvboxsync mcbVbvaPartial = 0;
cc1ef2ef9bbc6a0ff964928d61b7298e5bfcce5fvboxsync
d4a9d525e6f2111d462d2d96462dced6b9ec00efvboxsync /* Advance the record index. */
ed9d3db07648c7e3a979105c15ad752ee9ea18devboxsync mpVbvaMemory->indexRecordFirst = (indexRecordFirst + 1) % VBVA_MAX_RECORDS;
d4a9d525e6f2111d462d2d96462dced6b9ec00efvboxsync
ed9d3db07648c7e3a979105c15ad752ee9ea18devboxsync#ifdef DEBUG_sunlover
ed9d3db07648c7e3a979105c15ad752ee9ea18devboxsync LogFlow(("MAIN::DisplayImpl::vbvaFetchBytes: partial done ok, data = %d, free = %d\n",
ed9d3db07648c7e3a979105c15ad752ee9ea18devboxsync mpVbvaMemory->off32Data, mpVbvaMemory->off32Free));
7e8ef90d3160234df0f254131b87af4243d79476vboxsync#endif /* DEBUG_sunlover */
7e8ef90d3160234df0f254131b87af4243d79476vboxsync }
7e8ef90d3160234df0f254131b87af4243d79476vboxsync
d4a9d525e6f2111d462d2d96462dced6b9ec00efvboxsync return true;
d4a9d525e6f2111d462d2d96462dced6b9ec00efvboxsync }
d4a9d525e6f2111d462d2d96462dced6b9ec00efvboxsync
d4a9d525e6f2111d462d2d96462dced6b9ec00efvboxsync /* A new record need to be processed. */
d4a9d525e6f2111d462d2d96462dced6b9ec00efvboxsync if (pRecord->cbRecord & VBVA_F_RECORD_PARTIAL)
d4a9d525e6f2111d462d2d96462dced6b9ec00efvboxsync {
d4a9d525e6f2111d462d2d96462dced6b9ec00efvboxsync /* Current record is being written by guest. '=' is important here. */
907b6adfa052386a0666d5557bee9bdbc100c2e5vboxsync if (cbRecord >= VBVA_RING_BUFFER_SIZE - VBVA_RING_BUFFER_THRESHOLD)
907b6adfa052386a0666d5557bee9bdbc100c2e5vboxsync {
d4a9d525e6f2111d462d2d96462dced6b9ec00efvboxsync /* Partial read must be started. */
d4a9d525e6f2111d462d2d96462dced6b9ec00efvboxsync if (!vbvaPartialRead (&mpu8VbvaPartial, &mcbVbvaPartial, cbRecord, mpVbvaMemory))
d4a9d525e6f2111d462d2d96462dced6b9ec00efvboxsync return false;
cc1ef2ef9bbc6a0ff964928d61b7298e5bfcce5fvboxsync
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));
907b6adfa052386a0666d5557bee9bdbc100c2e5vboxsync }
907b6adfa052386a0666d5557bee9bdbc100c2e5vboxsync
5f2b03bf7695dabd71222dba123532a3f76828c1vboxsync return true;
5f2b03bf7695dabd71222dba123532a3f76828c1vboxsync }
6b9d50a0f466bd5a61458ed53925480ab28a3c17vboxsync
687794577e2e35c3cae67e692a7f2130d1262a82vboxsync /* Current record is complete. */
5f2b03bf7695dabd71222dba123532a3f76828c1vboxsync
5f2b03bf7695dabd71222dba123532a3f76828c1vboxsync /* The size of largest contiguous chunk in the ring biffer. */
5f2b03bf7695dabd71222dba123532a3f76828c1vboxsync uint32_t u32BytesTillBoundary = VBVA_RING_BUFFER_SIZE - mpVbvaMemory->off32Data;
907b6adfa052386a0666d5557bee9bdbc100c2e5vboxsync
6b9d50a0f466bd5a61458ed53925480ab28a3c17vboxsync /* The ring buffer pointer. */
5f2b03bf7695dabd71222dba123532a3f76828c1vboxsync uint8_t *au8RingBuffer = &mpVbvaMemory->au8RingBuffer[0];
5f2b03bf7695dabd71222dba123532a3f76828c1vboxsync
5f2b03bf7695dabd71222dba123532a3f76828c1vboxsync /* The pointer to data in the ring buffer. */
5f2b03bf7695dabd71222dba123532a3f76828c1vboxsync uint8_t *src = &au8RingBuffer[mpVbvaMemory->off32Data];
5f2b03bf7695dabd71222dba123532a3f76828c1vboxsync
5f2b03bf7695dabd71222dba123532a3f76828c1vboxsync /* Fetch or point the data. */
5f2b03bf7695dabd71222dba123532a3f76828c1vboxsync if (u32BytesTillBoundary >= cbRecord)
6b9d50a0f466bd5a61458ed53925480ab28a3c17vboxsync {
6b9d50a0f466bd5a61458ed53925480ab28a3c17vboxsync /* The command does not cross buffer boundary. Return address in the buffer. */
6b9d50a0f466bd5a61458ed53925480ab28a3c17vboxsync *ppHdr = (VBVACMDHDR *)src;
5f2b03bf7695dabd71222dba123532a3f76828c1vboxsync
5f2b03bf7695dabd71222dba123532a3f76828c1vboxsync /* Advance data offset. */
5f2b03bf7695dabd71222dba123532a3f76828c1vboxsync mpVbvaMemory->off32Data = (mpVbvaMemory->off32Data + cbRecord) % VBVA_RING_BUFFER_SIZE;
5f2b03bf7695dabd71222dba123532a3f76828c1vboxsync }
5f2b03bf7695dabd71222dba123532a3f76828c1vboxsync else
88cc9bf61296bc5526344415167bb2625ae1dd99vboxsync {
88cc9bf61296bc5526344415167bb2625ae1dd99vboxsync /* The command crosses buffer boundary. Rare case, so not optimized. */
d4a9d525e6f2111d462d2d96462dced6b9ec00efvboxsync uint8_t *dst = (uint8_t *)RTMemAlloc (cbRecord);
88cc9bf61296bc5526344415167bb2625ae1dd99vboxsync
88cc9bf61296bc5526344415167bb2625ae1dd99vboxsync if (!dst)
88cc9bf61296bc5526344415167bb2625ae1dd99vboxsync {
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 }
88cc9bf61296bc5526344415167bb2625ae1dd99vboxsync
88cc9bf61296bc5526344415167bb2625ae1dd99vboxsync vbvaFetchBytes (mpVbvaMemory, dst, cbRecord);
cc1ef2ef9bbc6a0ff964928d61b7298e5bfcce5fvboxsync
88cc9bf61296bc5526344415167bb2625ae1dd99vboxsync *ppHdr = (VBVACMDHDR *)dst;
88cc9bf61296bc5526344415167bb2625ae1dd99vboxsync
88cc9bf61296bc5526344415167bb2625ae1dd99vboxsync#ifdef DEBUG_sunlover
88cc9bf61296bc5526344415167bb2625ae1dd99vboxsync LogFlow(("MAIN::DisplayImpl::vbvaFetchBytes: Allocated from heap %p\n", dst));
88cc9bf61296bc5526344415167bb2625ae1dd99vboxsync#endif /* DEBUG_sunlover */
d4a9d525e6f2111d462d2d96462dced6b9ec00efvboxsync }
d4a9d525e6f2111d462d2d96462dced6b9ec00efvboxsync
5f2b03bf7695dabd71222dba123532a3f76828c1vboxsync *pcbCmd = cbRecord;
d4a9d525e6f2111d462d2d96462dced6b9ec00efvboxsync
ccbdc11833996cb9f3be7868f1ebaefcacafb94dvboxsync /* Advance the record index. */
5f2b03bf7695dabd71222dba123532a3f76828c1vboxsync mpVbvaMemory->indexRecordFirst = (indexRecordFirst + 1) % VBVA_MAX_RECORDS;
687794577e2e35c3cae67e692a7f2130d1262a82vboxsync
687794577e2e35c3cae67e692a7f2130d1262a82vboxsync#ifdef DEBUG_sunlover
687794577e2e35c3cae67e692a7f2130d1262a82vboxsync LogFlow(("MAIN::DisplayImpl::vbvaFetchBytes: done ok, data = %d, free = %d\n",
687794577e2e35c3cae67e692a7f2130d1262a82vboxsync mpVbvaMemory->off32Data, mpVbvaMemory->off32Free));
687794577e2e35c3cae67e692a7f2130d1262a82vboxsync#endif /* DEBUG_sunlover */
687794577e2e35c3cae67e692a7f2130d1262a82vboxsync
687794577e2e35c3cae67e692a7f2130d1262a82vboxsync return true;
687794577e2e35c3cae67e692a7f2130d1262a82vboxsync}
687794577e2e35c3cae67e692a7f2130d1262a82vboxsync
687794577e2e35c3cae67e692a7f2130d1262a82vboxsyncvoid Display::vbvaReleaseCmd (VBVACMDHDR *pHdr, int32_t cbCmd)
687794577e2e35c3cae67e692a7f2130d1262a82vboxsync{
687794577e2e35c3cae67e692a7f2130d1262a82vboxsync uint8_t *au8RingBuffer = mpVbvaMemory->au8RingBuffer;
687794577e2e35c3cae67e692a7f2130d1262a82vboxsync
687794577e2e35c3cae67e692a7f2130d1262a82vboxsync if ( (uint8_t *)pHdr >= au8RingBuffer
687794577e2e35c3cae67e692a7f2130d1262a82vboxsync && (uint8_t *)pHdr < &au8RingBuffer[VBVA_RING_BUFFER_SIZE])
687794577e2e35c3cae67e692a7f2130d1262a82vboxsync {
687794577e2e35c3cae67e692a7f2130d1262a82vboxsync /* The pointer is inside ring buffer. Must be continuous chunk. */
687794577e2e35c3cae67e692a7f2130d1262a82vboxsync Assert (VBVA_RING_BUFFER_SIZE - ((uint8_t *)pHdr - au8RingBuffer) >= cbCmd);
687794577e2e35c3cae67e692a7f2130d1262a82vboxsync
687794577e2e35c3cae67e692a7f2130d1262a82vboxsync /* Do nothing. */
687794577e2e35c3cae67e692a7f2130d1262a82vboxsync
687794577e2e35c3cae67e692a7f2130d1262a82vboxsync Assert (!mpu8VbvaPartial && mcbVbvaPartial == 0);
687794577e2e35c3cae67e692a7f2130d1262a82vboxsync }
687794577e2e35c3cae67e692a7f2130d1262a82vboxsync else
687794577e2e35c3cae67e692a7f2130d1262a82vboxsync {
687794577e2e35c3cae67e692a7f2130d1262a82vboxsync /* The pointer is outside. It is then an allocated copy. */
687794577e2e35c3cae67e692a7f2130d1262a82vboxsync
687794577e2e35c3cae67e692a7f2130d1262a82vboxsync#ifdef DEBUG_sunlover
687794577e2e35c3cae67e692a7f2130d1262a82vboxsync LogFlow(("MAIN::DisplayImpl::vbvaReleaseCmd: Free heap %p\n", pHdr));
687794577e2e35c3cae67e692a7f2130d1262a82vboxsync#endif /* DEBUG_sunlover */
687794577e2e35c3cae67e692a7f2130d1262a82vboxsync
687794577e2e35c3cae67e692a7f2130d1262a82vboxsync if ((uint8_t *)pHdr == mpu8VbvaPartial)
d4a9d525e6f2111d462d2d96462dced6b9ec00efvboxsync {
d4a9d525e6f2111d462d2d96462dced6b9ec00efvboxsync mpu8VbvaPartial = NULL;
0fd108a555ae02f2fb557d5f2c40281999b60d15vboxsync mcbVbvaPartial = 0;
0fd108a555ae02f2fb557d5f2c40281999b60d15vboxsync }
0fd108a555ae02f2fb557d5f2c40281999b60d15vboxsync else
0fd108a555ae02f2fb557d5f2c40281999b60d15vboxsync {
0fd108a555ae02f2fb557d5f2c40281999b60d15vboxsync Assert (!mpu8VbvaPartial && mcbVbvaPartial == 0);
0fd108a555ae02f2fb557d5f2c40281999b60d15vboxsync }
0fd108a555ae02f2fb557d5f2c40281999b60d15vboxsync
88cc9bf61296bc5526344415167bb2625ae1dd99vboxsync RTMemFree (pHdr);
88cc9bf61296bc5526344415167bb2625ae1dd99vboxsync }
88cc9bf61296bc5526344415167bb2625ae1dd99vboxsync
88cc9bf61296bc5526344415167bb2625ae1dd99vboxsync return;
0fd108a555ae02f2fb557d5f2c40281999b60d15vboxsync}
88cc9bf61296bc5526344415167bb2625ae1dd99vboxsync
88cc9bf61296bc5526344415167bb2625ae1dd99vboxsync/**
88cc9bf61296bc5526344415167bb2625ae1dd99vboxsync * Called regularly on the DisplayRefresh timer.
88cc9bf61296bc5526344415167bb2625ae1dd99vboxsync * Also on behalf of guest, when the ring buffer is full.
88cc9bf61296bc5526344415167bb2625ae1dd99vboxsync *
0fd108a555ae02f2fb557d5f2c40281999b60d15vboxsync * @thread EMT
88cc9bf61296bc5526344415167bb2625ae1dd99vboxsync */
88cc9bf61296bc5526344415167bb2625ae1dd99vboxsyncvoid Display::VideoAccelFlush (void)
0fd108a555ae02f2fb557d5f2c40281999b60d15vboxsync{
88cc9bf61296bc5526344415167bb2625ae1dd99vboxsync#ifdef DEBUG_sunlover
88cc9bf61296bc5526344415167bb2625ae1dd99vboxsync LogFlow(("Display::VideoAccelFlush: mfVideoAccelEnabled = %d\n", mfVideoAccelEnabled));
88cc9bf61296bc5526344415167bb2625ae1dd99vboxsync#endif /* DEBUG_sunlover */
0fd108a555ae02f2fb557d5f2c40281999b60d15vboxsync
88cc9bf61296bc5526344415167bb2625ae1dd99vboxsync if (!mfVideoAccelEnabled)
88cc9bf61296bc5526344415167bb2625ae1dd99vboxsync {
0fd108a555ae02f2fb557d5f2c40281999b60d15vboxsync Log(("Display::VideoAccelFlush: called with disabled VBVA!!! Ignoring.\n"));
0fd108a555ae02f2fb557d5f2c40281999b60d15vboxsync return;
0fd108a555ae02f2fb557d5f2c40281999b60d15vboxsync }
0fd108a555ae02f2fb557d5f2c40281999b60d15vboxsync
0fd108a555ae02f2fb557d5f2c40281999b60d15vboxsync /* Here VBVA is enabled and we have the accelerator memory pointer. */
f9ce005e61f0fbb51a2cabc53d58c3485151faa9vboxsync Assert(mpVbvaMemory);
f9ce005e61f0fbb51a2cabc53d58c3485151faa9vboxsync
f9ce005e61f0fbb51a2cabc53d58c3485151faa9vboxsync#ifdef DEBUG_sunlover
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
f9ce005e61f0fbb51a2cabc53d58c3485151faa9vboxsync /* Quick check for "nothing to update" case. */
f9ce005e61f0fbb51a2cabc53d58c3485151faa9vboxsync if (mpVbvaMemory->indexRecordFirst == mpVbvaMemory->indexRecordFree)
0fd108a555ae02f2fb557d5f2c40281999b60d15vboxsync return;
0fd108a555ae02f2fb557d5f2c40281999b60d15vboxsync
0fd108a555ae02f2fb557d5f2c40281999b60d15vboxsync /* Process the ring buffer */
0fd108a555ae02f2fb557d5f2c40281999b60d15vboxsync
f9ce005e61f0fbb51a2cabc53d58c3485151faa9vboxsync bool fFramebufferIsNull = (mFramebuffer == NULL);
f9ce005e61f0fbb51a2cabc53d58c3485151faa9vboxsync
f9ce005e61f0fbb51a2cabc53d58c3485151faa9vboxsync if (!fFramebufferIsNull)
f9ce005e61f0fbb51a2cabc53d58c3485151faa9vboxsync mFramebuffer->Lock();
f9ce005e61f0fbb51a2cabc53d58c3485151faa9vboxsync
f9ce005e61f0fbb51a2cabc53d58c3485151faa9vboxsync /* Initialize dirty rectangles accumulator. */
f9ce005e61f0fbb51a2cabc53d58c3485151faa9vboxsync VBVADIRTYREGION rgn;
f9ce005e61f0fbb51a2cabc53d58c3485151faa9vboxsync vbvaRgnInit (&rgn, mFramebuffer, this, mpDrv->pUpPort);
f9ce005e61f0fbb51a2cabc53d58c3485151faa9vboxsync
0fd108a555ae02f2fb557d5f2c40281999b60d15vboxsync for (;;)
f9ce005e61f0fbb51a2cabc53d58c3485151faa9vboxsync {
f9ce005e61f0fbb51a2cabc53d58c3485151faa9vboxsync VBVACMDHDR *phdr = NULL;
f9ce005e61f0fbb51a2cabc53d58c3485151faa9vboxsync uint32_t cbCmd = 0;
f9ce005e61f0fbb51a2cabc53d58c3485151faa9vboxsync
f9ce005e61f0fbb51a2cabc53d58c3485151faa9vboxsync /* Fetch the command data. */
f9ce005e61f0fbb51a2cabc53d58c3485151faa9vboxsync if (!vbvaFetchCmd (&phdr, &cbCmd))
f9ce005e61f0fbb51a2cabc53d58c3485151faa9vboxsync {
f9ce005e61f0fbb51a2cabc53d58c3485151faa9vboxsync Log(("Display::VideoAccelFlush: unable to fetch command. off32Data = %d, off32Free = %d. Disabling VBVA!!!\n",
f9ce005e61f0fbb51a2cabc53d58c3485151faa9vboxsync mpVbvaMemory->off32Data, mpVbvaMemory->off32Free));
0fd108a555ae02f2fb557d5f2c40281999b60d15vboxsync
f9ce005e61f0fbb51a2cabc53d58c3485151faa9vboxsync /* Disable VBVA on those processing errors. */
f9ce005e61f0fbb51a2cabc53d58c3485151faa9vboxsync VideoAccelEnable (false, NULL);
f9ce005e61f0fbb51a2cabc53d58c3485151faa9vboxsync
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync break;
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync }
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync if (!cbCmd)
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync {
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync /* No more commands yet in the queue. */
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync break;
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync }
702a8ee2dc1de96f2f77e97135015d3e243186fdvboxsync
702a8ee2dc1de96f2f77e97135015d3e243186fdvboxsync if (!fFramebufferIsNull)
9523921c89c66f4bececdbd5ac95aed0039eda1bvboxsync {
d4a9d525e6f2111d462d2d96462dced6b9ec00efvboxsync#ifdef DEBUG_sunlover
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
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync /* Handle the command.
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync *
0fd108a555ae02f2fb557d5f2c40281999b60d15vboxsync * Guest is responsible for updating the guest video memory.
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync * The Windows guest does all drawing using Eng*.
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync *
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync * For local output, only dirty rectangle information is used
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync * to update changed areas.
0fd108a555ae02f2fb557d5f2c40281999b60d15vboxsync *
0fd108a555ae02f2fb557d5f2c40281999b60d15vboxsync * Dirty rectangles are accumulated to exclude overlapping updates and
0fd108a555ae02f2fb557d5f2c40281999b60d15vboxsync * group small updates to a larger one.
0fd108a555ae02f2fb557d5f2c40281999b60d15vboxsync */
702a8ee2dc1de96f2f77e97135015d3e243186fdvboxsync
702a8ee2dc1de96f2f77e97135015d3e243186fdvboxsync /* Accumulate the update. */
0fd108a555ae02f2fb557d5f2c40281999b60d15vboxsync vbvaRgnDirtyRect (&rgn, phdr);
0fd108a555ae02f2fb557d5f2c40281999b60d15vboxsync
0fd108a555ae02f2fb557d5f2c40281999b60d15vboxsync// /* Forward the command to VRDP server. */
0fd108a555ae02f2fb557d5f2c40281999b60d15vboxsync// mParent->consoleVRDPServer()->SendUpdate (phdr, cbCmd);
0fd108a555ae02f2fb557d5f2c40281999b60d15vboxsync }
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync vbvaReleaseCmd (phdr, cbCmd);
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync }
0fd108a555ae02f2fb557d5f2c40281999b60d15vboxsync
0fd108a555ae02f2fb557d5f2c40281999b60d15vboxsync if (!fFramebufferIsNull)
0fd108a555ae02f2fb557d5f2c40281999b60d15vboxsync mFramebuffer->Unlock ();
0fd108a555ae02f2fb557d5f2c40281999b60d15vboxsync
0fd108a555ae02f2fb557d5f2c40281999b60d15vboxsync /* Draw the framebuffer. */
0fd108a555ae02f2fb557d5f2c40281999b60d15vboxsync vbvaRgnUpdateFramebuffer (&rgn);
0fd108a555ae02f2fb557d5f2c40281999b60d15vboxsync}
0fd108a555ae02f2fb557d5f2c40281999b60d15vboxsync
0fd108a555ae02f2fb557d5f2c40281999b60d15vboxsync/**
0fd108a555ae02f2fb557d5f2c40281999b60d15vboxsync * @interface_method_impl{PDMIBASE,pfnQueryInterface}
0fd108a555ae02f2fb557d5f2c40281999b60d15vboxsync */
0fd108a555ae02f2fb557d5f2c40281999b60d15vboxsyncDECLCALLBACK(void *) Display::drvQueryInterface(PPDMIBASE pInterface, const char *pszIID)
0fd108a555ae02f2fb557d5f2c40281999b60d15vboxsync{
6b9d50a0f466bd5a61458ed53925480ab28a3c17vboxsync PPDMDRVINS pDrvIns = PDMIBASE_2_PDMDRV(pInterface);
0fd108a555ae02f2fb557d5f2c40281999b60d15vboxsync PDRVMAINDISPLAY pDrv = PDMINS_2_DATA(pDrvIns, PDRVMAINDISPLAY);
0fd108a555ae02f2fb557d5f2c40281999b60d15vboxsync
0fd108a555ae02f2fb557d5f2c40281999b60d15vboxsync if (RTUuidCompare2Strs(pszIID, PDMIBASE_IID) == 0)
0fd108a555ae02f2fb557d5f2c40281999b60d15vboxsync return &pDrvIns->IBase;
0fd108a555ae02f2fb557d5f2c40281999b60d15vboxsync if (RTUuidCompare2Strs(pszIID, PDMIDISPLAYCONNECTOR_IID) == 0)
0fd108a555ae02f2fb557d5f2c40281999b60d15vboxsync return &pDrv->Connector;
0fd108a555ae02f2fb557d5f2c40281999b60d15vboxsync return NULL;
0fd108a555ae02f2fb557d5f2c40281999b60d15vboxsync}
0fd108a555ae02f2fb557d5f2c40281999b60d15vboxsync
6b9d50a0f466bd5a61458ed53925480ab28a3c17vboxsync
6b9d50a0f466bd5a61458ed53925480ab28a3c17vboxsync/**
6b9d50a0f466bd5a61458ed53925480ab28a3c17vboxsync * Construct a display driver instance.
0fd108a555ae02f2fb557d5f2c40281999b60d15vboxsync *
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync * @copydoc FNPDMDRVCONSTRUCT
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync */
2f3883b126a405f92b19e829472f614c7352b4f9vboxsyncDECLCALLBACK(int) Display::drvConstruct(PPDMDRVINS pDrvIns, PCFGMNODE pCfg, uint32_t fFlags)
0fd108a555ae02f2fb557d5f2c40281999b60d15vboxsync{
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync PDRVMAINDISPLAY pData = PDMINS_2_DATA(pDrvIns, PDRVMAINDISPLAY);
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync LogFlow(("Display::drvConstruct: iInstance=%d\n", pDrvIns->iInstance));
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync PDMDRV_CHECK_VERSIONS_RETURN(pDrvIns);
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync
0fd108a555ae02f2fb557d5f2c40281999b60d15vboxsync /*
0fd108a555ae02f2fb557d5f2c40281999b60d15vboxsync * Validate configuration.
0fd108a555ae02f2fb557d5f2c40281999b60d15vboxsync */
0fd108a555ae02f2fb557d5f2c40281999b60d15vboxsync if (!CFGMR3AreValuesValid(pCfg, "Object\0"))
702a8ee2dc1de96f2f77e97135015d3e243186fdvboxsync return VERR_PDM_DRVINS_UNKNOWN_CFG_VALUES;
702a8ee2dc1de96f2f77e97135015d3e243186fdvboxsync AssertMsgReturn(PDMDrvHlpNoAttach(pDrvIns) == VERR_PDM_NO_ATTACHED_DRIVER,
0fd108a555ae02f2fb557d5f2c40281999b60d15vboxsync ("Configuration error: Not possible to attach anything to this driver!\n"),
0fd108a555ae02f2fb557d5f2c40281999b60d15vboxsync VERR_PDM_DRVINS_NO_ATTACH);
0fd108a555ae02f2fb557d5f2c40281999b60d15vboxsync
0fd108a555ae02f2fb557d5f2c40281999b60d15vboxsync /*
0fd108a555ae02f2fb557d5f2c40281999b60d15vboxsync * Init Interfaces.
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync */
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync pDrvIns->IBase.pfnQueryInterface = Display::drvQueryInterface;
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync
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
0fd108a555ae02f2fb557d5f2c40281999b60d15vboxsync /*
0fd108a555ae02f2fb557d5f2c40281999b60d15vboxsync * Get the IDisplayPort interface of the above driver/device.
0fd108a555ae02f2fb557d5f2c40281999b60d15vboxsync */
0fd108a555ae02f2fb557d5f2c40281999b60d15vboxsync pData->pUpPort = PDMIBASE_QUERY_INTERFACE(pDrvIns->pUpBase, PDMIDISPLAYPORT);
0fd108a555ae02f2fb557d5f2c40281999b60d15vboxsync if (!pData->pUpPort)
6b9d50a0f466bd5a61458ed53925480ab28a3c17vboxsync {
0fd108a555ae02f2fb557d5f2c40281999b60d15vboxsync AssertMsgFailed(("Configuration error: No display port interface above!\n"));
0fd108a555ae02f2fb557d5f2c40281999b60d15vboxsync return VERR_PDM_MISSING_INTERFACE_ABOVE;
0fd108a555ae02f2fb557d5f2c40281999b60d15vboxsync }
0fd108a555ae02f2fb557d5f2c40281999b60d15vboxsync
0fd108a555ae02f2fb557d5f2c40281999b60d15vboxsync /*
0fd108a555ae02f2fb557d5f2c40281999b60d15vboxsync * Get the Display object pointer and update the mpDrv member.
0fd108a555ae02f2fb557d5f2c40281999b60d15vboxsync */
0fd108a555ae02f2fb557d5f2c40281999b60d15vboxsync void *pv;
0fd108a555ae02f2fb557d5f2c40281999b60d15vboxsync int rc = CFGMR3QueryPtr(pCfg, "Object", &pv);
6b9d50a0f466bd5a61458ed53925480ab28a3c17vboxsync if (RT_FAILURE(rc))
6b9d50a0f466bd5a61458ed53925480ab28a3c17vboxsync {
6b9d50a0f466bd5a61458ed53925480ab28a3c17vboxsync AssertMsgFailed(("Configuration error: No/bad \"Object\" value! rc=%Rrc\n", rc));
6b9d50a0f466bd5a61458ed53925480ab28a3c17vboxsync return rc;
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync }
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync pData->pDisplay = (Display *)pv; /** @todo Check this cast! */
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync pData->pDisplay->mpDrv = pData;
35e6d303696e46d969aaf9a59cc381333a483b0bvboxsync
4121d226ac899f17e13aff3aff42b603c8b5c1fevboxsync /*
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync * If there is a Framebuffer, we have to update our display information
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync */
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync if (pData->pDisplay->mFramebuffer)
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync pData->pDisplay->updateDisplayData();
702a8ee2dc1de96f2f77e97135015d3e243186fdvboxsync
702a8ee2dc1de96f2f77e97135015d3e243186fdvboxsync /*
35e6d303696e46d969aaf9a59cc381333a483b0bvboxsync * Start periodic screen refreshes
35e6d303696e46d969aaf9a59cc381333a483b0bvboxsync */
35e6d303696e46d969aaf9a59cc381333a483b0bvboxsync pData->pUpPort->pfnSetRefreshRate(pData->pUpPort, 50);
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync return VINF_SUCCESS;
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync}
35e6d303696e46d969aaf9a59cc381333a483b0bvboxsync
35e6d303696e46d969aaf9a59cc381333a483b0bvboxsync
35e6d303696e46d969aaf9a59cc381333a483b0bvboxsync/**
35e6d303696e46d969aaf9a59cc381333a483b0bvboxsync * Display driver registration record.
35e6d303696e46d969aaf9a59cc381333a483b0bvboxsync */
35e6d303696e46d969aaf9a59cc381333a483b0bvboxsyncconst PDMDRVREG Display::DrvReg =
35e6d303696e46d969aaf9a59cc381333a483b0bvboxsync{
5366e994777f9d9391cf809dc77610f57270d75dvboxsync /* u32Version */
5366e994777f9d9391cf809dc77610f57270d75dvboxsync PDM_DRVREG_VERSION,
5366e994777f9d9391cf809dc77610f57270d75dvboxsync /* szName */
5366e994777f9d9391cf809dc77610f57270d75dvboxsync "MainDisplay",
5366e994777f9d9391cf809dc77610f57270d75dvboxsync /* szRCMod */
35e6d303696e46d969aaf9a59cc381333a483b0bvboxsync "",
35e6d303696e46d969aaf9a59cc381333a483b0bvboxsync /* szR0Mod */
35e6d303696e46d969aaf9a59cc381333a483b0bvboxsync "",
35e6d303696e46d969aaf9a59cc381333a483b0bvboxsync /* pszDescription */
35e6d303696e46d969aaf9a59cc381333a483b0bvboxsync "Main display driver (Main as in the API).",
4121d226ac899f17e13aff3aff42b603c8b5c1fevboxsync /* fFlags */
4121d226ac899f17e13aff3aff42b603c8b5c1fevboxsync PDM_DRVREG_FLAGS_HOST_BITS_DEFAULT,
35e6d303696e46d969aaf9a59cc381333a483b0bvboxsync /* fClass. */
35e6d303696e46d969aaf9a59cc381333a483b0bvboxsync PDM_DRVREG_CLASS_DISPLAY,
35e6d303696e46d969aaf9a59cc381333a483b0bvboxsync /* cMaxInstances */
35e6d303696e46d969aaf9a59cc381333a483b0bvboxsync ~0,
35e6d303696e46d969aaf9a59cc381333a483b0bvboxsync /* cbInstance */
35e6d303696e46d969aaf9a59cc381333a483b0bvboxsync sizeof(DRVMAINDISPLAY),
35e6d303696e46d969aaf9a59cc381333a483b0bvboxsync /* pfnConstruct */
35e6d303696e46d969aaf9a59cc381333a483b0bvboxsync Display::drvConstruct,
35e6d303696e46d969aaf9a59cc381333a483b0bvboxsync /* pfnDestruct */
35e6d303696e46d969aaf9a59cc381333a483b0bvboxsync NULL,
35e6d303696e46d969aaf9a59cc381333a483b0bvboxsync /* pfnRelocate */
35e6d303696e46d969aaf9a59cc381333a483b0bvboxsync NULL,
35e6d303696e46d969aaf9a59cc381333a483b0bvboxsync /* pfnIOCtl */
35e6d303696e46d969aaf9a59cc381333a483b0bvboxsync NULL,
35e6d303696e46d969aaf9a59cc381333a483b0bvboxsync /* pfnPowerOn */
35e6d303696e46d969aaf9a59cc381333a483b0bvboxsync NULL,
35e6d303696e46d969aaf9a59cc381333a483b0bvboxsync /* pfnReset */
35e6d303696e46d969aaf9a59cc381333a483b0bvboxsync NULL,
35e6d303696e46d969aaf9a59cc381333a483b0bvboxsync /* pfnSuspend */
35e6d303696e46d969aaf9a59cc381333a483b0bvboxsync NULL,
35e6d303696e46d969aaf9a59cc381333a483b0bvboxsync /* pfnResume */
35e6d303696e46d969aaf9a59cc381333a483b0bvboxsync NULL,
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync /* pfnAttach */
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync NULL,
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync /* pfnDetach */
3641904508e6a0671c21a083a2ed03ebad8d976cvboxsync NULL,
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync /* pfnPowerOff */
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync NULL,
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync /* pfnSoftReset */
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync NULL,
702a8ee2dc1de96f2f77e97135015d3e243186fdvboxsync /* u32EndVersion */
702a8ee2dc1de96f2f77e97135015d3e243186fdvboxsync PDM_DRVREG_VERSION
36f3c24e4ad9c6b813767db1faeabbe7e2ecc057vboxsync};
36f3c24e4ad9c6b813767db1faeabbe7e2ecc057vboxsync
36f3c24e4ad9c6b813767db1faeabbe7e2ecc057vboxsync