summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichael Thayer <michael.thayer@oracle.com>2017-10-14 10:23:47 +0200
committerMichael Thayer <michael.thayer@oracle.com>2017-10-14 10:23:47 +0200
commitab07f97612d045d8c0a376174b39a294d028fef2 (patch)
tree8f71def44da9cdfb6ecca6ec742bf48c173b3494
Initial commit.
-rw-r--r--.gitignore78
-rw-r--r--COPYING26
-rw-r--r--Makefile.am33
-rw-r--r--README20
-rwxr-xr-xautogen.sh14
-rw-r--r--configure.ac97
-rw-r--r--man/Makefile.am41
-rw-r--r--man/vboxvideo.man27
-rw-r--r--src/HGSMI.h258
-rw-r--r--src/HGSMIBase.c293
-rw-r--r--src/HGSMIBase.h54
-rw-r--r--src/HGSMIBuffers.c118
-rw-r--r--src/HGSMIChSetup.h79
-rw-r--r--src/HGSMIChannels.h64
-rw-r--r--src/HGSMICommon.c449
-rw-r--r--src/HGSMIContext.h104
-rw-r--r--src/HGSMIDefs.h118
-rw-r--r--src/HGSMIMemAlloc.h56
-rw-r--r--src/Makefile.am68
-rw-r--r--src/Modesetting.c386
-rw-r--r--src/README.testing34
-rw-r--r--src/VBVABase.c390
-rw-r--r--src/VBoxVideo.h2106
-rw-r--r--src/VBoxVideoErr.h64
-rw-r--r--src/VBoxVideoGuest.h175
-rw-r--r--src/VBoxVideoIPRT.h221
-rw-r--r--src/VBoxVideoVBE.h81
-rw-r--r--src/edid.c166
-rw-r--r--src/getmode.c318
-rw-r--r--src/helpers.c81
-rw-r--r--src/hgsmimemalloc.c106
-rw-r--r--src/pointer.c493
-rw-r--r--src/setmode.c132
-rw-r--r--src/vboxvideo.c1492
-rw-r--r--src/vboxvideo.h240
-rw-r--r--src/vbva.c252
-rw-r--r--src/version-generated.h14
37 files changed, 8748 insertions, 0 deletions
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..a8dcac1
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,78 @@
+#
+# X.Org module default exclusion patterns
+# The next section if for module specific patterns
+#
+# Do not edit the following section
+# GNU Build System (Autotools)
+aclocal.m4
+autom4te.cache/
+autoscan.log
+ChangeLog
+compile
+config.guess
+config.h
+config.h.in
+config.log
+config-ml.in
+config.py
+config.status
+config.status.lineno
+config.sub
+configure
+configure.scan
+depcomp
+.deps/
+INSTALL
+install-sh
+.libs/
+libtool
+libtool.m4
+ltmain.sh
+lt~obsolete.m4
+ltoptions.m4
+ltsugar.m4
+ltversion.m4
+Makefile
+Makefile.in
+mdate-sh
+missing
+mkinstalldirs
+*.pc
+py-compile
+stamp-h?
+symlink-tree
+texinfo.tex
+ylwrap
+
+# Do not edit the following section
+# Edit Compile Debug Document Distribute
+*~
+*.[0-9]
+*.[0-9]x
+*.bak
+*.bin
+core
+*.dll
+*.exe
+*-ISO*.bdf
+*-JIS*.bdf
+*-KOI8*.bdf
+*.kld
+*.ko
+*.ko.cmd
+*.lai
+*.l[oa]
+*.[oa]
+*.obj
+*.patch
+*.so
+*.pcf.gz
+*.pdb
+*.tar.bz2
+*.tar.gz
+#
+# Add & Override patterns for xf86-video-vboxvideo
+#
+# Edit the following section as needed
+# For example, !report.pc overrides *.pc. See 'man gitignore'
+#
diff --git a/COPYING b/COPYING
new file mode 100644
index 0000000..75e9178
--- /dev/null
+++ b/COPYING
@@ -0,0 +1,26 @@
+Copyright (c) 2000 by Conectiva S.A. (http://www.conectiva.com)
+Copyright 2008 Red Hat, Inc.
+Copyright (C) 2005-2017 Oracle Corporation
+
+Permission is hereby granted, free of charge, to any person obtaining a
+copy of this software and associated documentation files (the "Software"),
+to deal in the Software without restriction, including without limitation
+the rights to use, copy, modify, merge, publish, distribute, sublicense,
+and/or sell copies of the Software, and to permit persons to whom the
+Software is furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+CONECTIVA LINUX BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
+OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+
+Except as contained in this notice, the name of Conectiva Linux shall
+not be used in advertising or otherwise to promote the sale, use or other
+dealings in this Software without prior written authorization from
+Conectiva Linux.
diff --git a/Makefile.am b/Makefile.am
new file mode 100644
index 0000000..a94ec19
--- /dev/null
+++ b/Makefile.am
@@ -0,0 +1,33 @@
+# Copyright 2005 Adam Jackson.
+# Copyright 2017 Oracle Corporation
+#
+# Permission is hereby granted, free of charge, to any person obtaining a
+# copy of this software and associated documentation files (the "Software"),
+# to deal in the Software without restriction, including without limitation
+# on the rights to use, copy, modify, merge, publish, distribute, sub
+# license, and/or sell copies of the Software, and to permit persons to whom
+# the Software is furnished to do so, subject to the following conditions:
+#
+# The above copyright notice and this permission notice (including the next
+# paragraph) shall be included in all copies or substantial portions of the
+# Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
+# THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM,
+# DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+# OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+# USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+SUBDIRS = src man
+MAINTAINERCLEANFILES = ChangeLog INSTALL
+.PHONY: ChangeLog INSTALL
+
+INSTALL:
+ $(INSTALL_CMD)
+
+ChangeLog:
+ $(CHANGELOG_CMD)
+
+dist-hook: ChangeLog INSTALL
diff --git a/README b/README
new file mode 100644
index 0000000..2fbb692
--- /dev/null
+++ b/README
@@ -0,0 +1,20 @@
+xf86-video-vboxvideo - VirtualBox video driver for the Xorg X server
+
+Please submit bugs & patches to the Xorg bugzilla:
+
+ https://bugs.freedesktop.org/enter_bug.cgi?product=xorg
+
+All questions regarding this software should be directed at the
+Xorg mailing list:
+
+ http://lists.freedesktop.org/mailman/listinfo/xorg
+
+The master development code repository can be found at:
+
+ git://anongit.freedesktop.org/git/xorg/driver/xf86-video-vboxvideo
+
+ http://cgit.freedesktop.org/xorg/driver/xf86-video-vboxvideo
+
+For more information on the git code manager, see:
+
+ http://wiki.x.org/wiki/GitPage
diff --git a/autogen.sh b/autogen.sh
new file mode 100755
index 0000000..fc34bd5
--- /dev/null
+++ b/autogen.sh
@@ -0,0 +1,14 @@
+#! /bin/sh
+
+srcdir=`dirname $0`
+test -z "$srcdir" && srcdir=.
+
+ORIGDIR=`pwd`
+cd $srcdir
+
+autoreconf -v --install || exit 1
+cd $ORIGDIR || exit $?
+
+if test -z "$NOCONFIGURE"; then
+ $srcdir/configure "$@"
+fi
diff --git a/configure.ac b/configure.ac
new file mode 100644
index 0000000..78abe2e
--- /dev/null
+++ b/configure.ac
@@ -0,0 +1,97 @@
+# Copyright 2005 Adam Jackson.
+#
+# Permission is hereby granted, free of charge, to any person obtaining a
+# copy of this software and associated documentation files (the "Software"),
+# to deal in the Software without restriction, including without limitation
+# on the rights to use, copy, modify, merge, publish, distribute, sub
+# license, and/or sell copies of the Software, and to permit persons to whom
+# the Software is furnished to do so, subject to the following conditions:
+#
+# The above copyright notice and this permission notice (including the next
+# paragraph) shall be included in all copies or substantial portions of the
+# Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
+# ADAM JACKSON BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+# IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+#
+# Process this file with autoconf to produce a configure script
+
+# Initialize Autoconf
+AC_PREREQ([2.60])
+AC_INIT([xf86-video-vboxvideo],
+ [2.3.4],
+ [https://bugs.freedesktop.org/enter_bug.cgi?product=xorg],
+ [xf86-video-vboxvideo])
+AC_CONFIG_SRCDIR([Makefile.am])
+AC_CONFIG_HEADERS([config.h])
+AC_CONFIG_AUX_DIR(.)
+
+# Initialize Automake
+AM_INIT_AUTOMAKE([foreign dist-bzip2])
+
+# Require X.Org macros 1.8 or later for MAN_SUBSTS set by XORG_MANPAGE_SECTIONS
+m4_ifndef([XORG_MACROS_VERSION],
+ [m4_fatal([must install xorg-macros 1.8 or later before running autoconf/autogen])])
+XORG_MACROS_VERSION(1.8)
+XORG_DEFAULT_OPTIONS
+
+# Initialize libtool
+AC_DISABLE_STATIC
+AC_PROG_LIBTOOL
+
+AH_TOP([#include "xorg-server.h"])
+
+# Define a configure option for an alternate module directory
+AC_ARG_WITH(xorg-module-dir, [ --with-xorg-module-dir=DIR ],
+ [ moduledir="$withval" ],
+ [ moduledir="$libdir/xorg/modules" ])
+AC_SUBST(moduledir)
+
+# Store the list of server defined optional extensions in REQUIRED_MODULES
+XORG_DRIVER_CHECK_EXT(RANDR, randrproto)
+XORG_DRIVER_CHECK_EXT(RENDER, renderproto)
+XORG_DRIVER_CHECK_EXT(DPMSExtension, xextproto)
+
+# Obtain compiler/linker options for the driver dependencies
+PKG_CHECK_MODULES(XORG, xorg-server >= 1.6 xproto fontsproto $REQUIRED_MODULES)
+PKG_CHECK_MODULES(XEXT, [xextproto >= 7.0.99.1],
+ HAVE_XEXTPROTO_71="yes", HAVE_XEXTPROTO_71="no")
+
+if test "x$HAVE_XEXTPROTO_71" = xyes; then
+ AC_DEFINE(HAVE_XEXTPROTO_71, 1, [xextproto 7.1 available])
+fi
+
+save_CFLAGS="$CFLAGS"
+CFLAGS="$XORG_CFLAGS"
+AC_CHECK_DECL(xf86ConfigIsaEntity,
+ [AC_DEFINE(HAVE_ISA, 1, [Have ISA support])],
+ [],
+ [#include "xf86.h"])
+CFLAGS="$save_CFLAGS"
+
+save_CFLAGS="$CFLAGS"
+CFLAGS="$XORG_CFLAGS"
+AC_CHECK_DECL(XSERVER_LIBPCIACCESS,
+ [XSERVER_LIBPCIACCESS=yes], [XSERVER_LIBPCIACCESS=no],
+ [#include "xorg-server.h"])
+CFLAGS="$save_CFLAGS"
+
+if test "x$XSERVER_LIBPCIACCESS" = xyes; then
+ PKG_CHECK_MODULES([PCIACCESS], [pciaccess >= 0.12.901])
+fi
+
+# Checks for libraries.
+
+DRIVER_NAME=vboxvideo
+AC_SUBST([DRIVER_NAME])
+
+AC_CONFIG_FILES([
+ Makefile
+ src/Makefile
+ man/Makefile
+])
+AC_OUTPUT
diff --git a/man/Makefile.am b/man/Makefile.am
new file mode 100644
index 0000000..b3688ce
--- /dev/null
+++ b/man/Makefile.am
@@ -0,0 +1,41 @@
+#
+# Copyright 2005 Sun Microsystems, Inc. All rights reserved.
+#
+# Permission is hereby granted, free of charge, to any person obtaining a
+# copy of this software and associated documentation files (the "Software"),
+# to deal in the Software without restriction, including without limitation
+# the rights to use, copy, modify, merge, publish, distribute, sublicense,
+# and/or sell copies of the Software, and to permit persons to whom the
+# Software is furnished to do so, subject to the following conditions:
+#
+# The above copyright notice and this permission notice (including the next
+# paragraph) shall be included in all copies or substantial portions of the
+# Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+# DEALINGS IN THE SOFTWARE.
+#
+
+drivermandir = $(DRIVER_MAN_DIR)
+
+driverman_PRE = @DRIVER_NAME@.man
+
+driverman_DATA = $(driverman_PRE:man=@DRIVER_MAN_SUFFIX@)
+
+EXTRA_DIST = @DRIVER_NAME@.man
+
+CLEANFILES = $(driverman_DATA)
+
+
+# String replacements in MAN_SUBSTS now come from xorg-macros.m4 via configure
+
+
+SUFFIXES = .$(DRIVER_MAN_SUFFIX) .man
+
+.man.$(DRIVER_MAN_SUFFIX):
+ $(AM_V_GEN)$(SED) $(MAN_SUBSTS) < $< > $@
diff --git a/man/vboxvideo.man b/man/vboxvideo.man
new file mode 100644
index 0000000..d61a22a
--- /dev/null
+++ b/man/vboxvideo.man
@@ -0,0 +1,27 @@
+.\" shorthand for double quote that works everywhere.
+.ds q \N'34'
+.TH VBOXVIDEO __drivermansuffix__ __vendorversion__
+.SH NAME
+vboxvideo \- VirtualBox video driver
+.SH SYNOPSIS
+.nf
+.B "Section \*qDevice\*q"
+.BI " Identifier \*q" devname \*q
+.B " Driver \*qvboxvideo\*q"
+\ \ ...
+.B EndSection
+.fi
+.SH DESCRIPTION
+.B vboxvideo
+is an __xservername__ driver for the VirtualBox virtual video card.
+.SH SUPPORTED HARDWARE
+The
+.B vboxvideo
+driver supports the VirtualBox virtual video card.
+.SH CONFIGURATION DETAILS
+Please refer to __xconfigfile__(__filemansuffix__) for general configuration
+details.
+.SH "SEE ALSO"
+__xservername__(__appmansuffix__), __xconfigfile__(__filemansuffix__), Xserver(__appmansuffix__), X(__miscmansuffix__)
+.SH AUTHORS
+Authors include: Paulo Ce\'sar Pereira de Andrade, Michael Thayer.
diff --git a/src/HGSMI.h b/src/HGSMI.h
new file mode 100644
index 0000000..9b621b5
--- /dev/null
+++ b/src/HGSMI.h
@@ -0,0 +1,258 @@
+/*
+ * Copyright (C) 2006-2017 Oracle Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+
+#ifndef ___VBox_Graphics_HGSMI_h
+#define ___VBox_Graphics_HGSMI_h
+
+#include "VBoxVideoIPRT.h"
+
+#include "HGSMIDefs.h"
+#include "HGSMIChannels.h"
+#include "HGSMIMemAlloc.h"
+
+/*
+ * Basic mechanism for the HGSMI is to prepare and pass data buffer to the host and the guest.
+ * Data inside these buffers are opaque for the HGSMI and are interpreted by higher levels.
+ *
+ * Every shared memory buffer passed between the guest/host has the following structure:
+ *
+ * HGSMIBUFFERHEADER header;
+ * uint8_t data[header.u32BufferSize];
+ * HGSMIBUFFERTAIL tail;
+ *
+ * Note: Offset of the 'header' in the memory is used for virtual hardware IO.
+ *
+ * Buffers are verifyed using the offset and the content of the header and the tail,
+ * which are constant during a call.
+ *
+ * Invalid buffers are ignored.
+ *
+ * Actual 'data' is not verifyed, as it is expected that the data can be changed by the
+ * called function.
+ *
+ * Since only the offset of the buffer is passed in a IO operation, the header and tail
+ * must contain:
+ * * size of data in this buffer;
+ * * checksum for buffer verification.
+ *
+ * For segmented transfers:
+ * * the sequence identifier;
+ * * offset of the current segment in the sequence;
+ * * total bytes in the transfer.
+ *
+ * Additionally contains:
+ * * the channel ID;
+ * * the channel information.
+ */
+
+typedef struct HGSMIHEAP
+{
+ HGSMIAREA area; /* Description. */
+ HGSMIMADATA ma; /* Memory allocator */
+} HGSMIHEAP;
+
+/* The size of the array of channels. Array indexes are uint8_t. Note: the value must not be changed. */
+#define HGSMI_NUMBER_OF_CHANNELS 0x100
+
+/* Channel handler called when the guest submits a buffer. */
+typedef DECLCALLBACK(int) FNHGSMICHANNELHANDLER(void *pvHandler, uint16_t u16ChannelInfo, void *pvBuffer, HGSMISIZE cbBuffer);
+typedef FNHGSMICHANNELHANDLER *PFNHGSMICHANNELHANDLER;
+
+/* Information about a handler: pfn + context. */
+typedef struct _HGSMICHANNELHANDLER
+{
+ PFNHGSMICHANNELHANDLER pfnHandler;
+ void *pvHandler;
+} HGSMICHANNELHANDLER;
+
+/* Channel description. */
+typedef struct _HGSMICHANNEL
+{
+ HGSMICHANNELHANDLER handler; /* The channel handler. */
+ const char *pszName; /* NULL for hardcoded channels or RTStrDup'ed name. */
+ uint8_t u8Channel; /* The channel id, equal to the channel index in the array. */
+ uint8_t u8Flags; /* HGSMI_CH_F_* */
+} HGSMICHANNEL;
+
+typedef struct _HGSMICHANNELINFO
+{
+ HGSMICHANNEL Channels[HGSMI_NUMBER_OF_CHANNELS]; /* Channel handlers indexed by the channel id.
+ * The array is accessed under the instance lock.
+ */
+} HGSMICHANNELINFO;
+
+
+RT_C_DECLS_BEGIN
+
+DECLINLINE(HGSMIBUFFERHEADER *) HGSMIBufferHeaderFromPtr(void *pvBuffer)
+{
+ return (HGSMIBUFFERHEADER *)pvBuffer;
+}
+
+DECLINLINE(uint8_t *) HGSMIBufferDataFromPtr(void *pvBuffer)
+{
+ return (uint8_t *)pvBuffer + sizeof(HGSMIBUFFERHEADER);
+}
+
+DECLINLINE(HGSMIBUFFERTAIL *) HGSMIBufferTailFromPtr(void *pvBuffer,
+ uint32_t u32DataSize)
+{
+ return (HGSMIBUFFERTAIL *)(HGSMIBufferDataFromPtr(pvBuffer) + u32DataSize);
+}
+
+DECLINLINE(HGSMISIZE) HGSMIBufferMinimumSize(void)
+{
+ return sizeof(HGSMIBUFFERHEADER) + sizeof(HGSMIBUFFERTAIL);
+}
+
+DECLINLINE(HGSMIBUFFERHEADER *) HGSMIBufferHeaderFromData(const void *pvData)
+{
+ return (HGSMIBUFFERHEADER *)((uint8_t *)pvData - sizeof(HGSMIBUFFERHEADER));
+}
+
+DECLINLINE(HGSMISIZE) HGSMIBufferRequiredSize(uint32_t u32DataSize)
+{
+ return HGSMIBufferMinimumSize() + u32DataSize;
+}
+
+DECLINLINE(HGSMIOFFSET) HGSMIPointerToOffset(const HGSMIAREA *pArea,
+ const void *pv)
+{
+ return pArea->offBase + (HGSMIOFFSET)((uint8_t *)pv - pArea->pu8Base);
+}
+
+DECLINLINE(void *) HGSMIOffsetToPointer(const HGSMIAREA *pArea,
+ HGSMIOFFSET offBuffer)
+{
+ return pArea->pu8Base + (offBuffer - pArea->offBase);
+}
+
+DECLINLINE(uint8_t *) HGSMIBufferDataFromOffset(const HGSMIAREA *pArea,
+ HGSMIOFFSET offBuffer)
+{
+ void *pvBuffer = HGSMIOffsetToPointer(pArea, offBuffer);
+ return HGSMIBufferDataFromPtr(pvBuffer);
+}
+
+DECLINLINE(HGSMIOFFSET) HGSMIBufferOffsetFromData(const HGSMIAREA *pArea,
+ void *pvData)
+{
+ HGSMIBUFFERHEADER *pHeader = HGSMIBufferHeaderFromData(pvData);
+ return HGSMIPointerToOffset(pArea, pHeader);
+}
+
+DECLINLINE(uint8_t *) HGSMIBufferDataAndChInfoFromOffset(const HGSMIAREA *pArea,
+ HGSMIOFFSET offBuffer,
+ uint16_t *pu16ChannelInfo)
+{
+ HGSMIBUFFERHEADER *pHeader = (HGSMIBUFFERHEADER *)HGSMIOffsetToPointer(pArea, offBuffer);
+ *pu16ChannelInfo = pHeader->u16ChannelInfo;
+ return HGSMIBufferDataFromPtr(pHeader);
+}
+
+uint32_t HGSMIChecksum(HGSMIOFFSET offBuffer,
+ const HGSMIBUFFERHEADER *pHeader,
+ const HGSMIBUFFERTAIL *pTail);
+
+int HGSMIAreaInitialize(HGSMIAREA *pArea,
+ void *pvBase,
+ HGSMISIZE cbArea,
+ HGSMIOFFSET offBase);
+
+void HGSMIAreaClear(HGSMIAREA *pArea);
+
+DECLINLINE(bool) HGSMIAreaContainsOffset(const HGSMIAREA *pArea, HGSMIOFFSET off)
+{
+ return off >= pArea->offBase && off - pArea->offBase < pArea->cbArea;
+}
+
+DECLINLINE(bool) HGSMIAreaContainsPointer(const HGSMIAREA *pArea, const void *pv)
+{
+ return (uintptr_t)pv >= (uintptr_t)pArea->pu8Base && (uintptr_t)pv - (uintptr_t)pArea->pu8Base < pArea->cbArea;
+}
+
+HGSMIOFFSET HGSMIBufferInitializeSingle(const HGSMIAREA *pArea,
+ HGSMIBUFFERHEADER *pHeader,
+ HGSMISIZE cbBuffer,
+ uint8_t u8Channel,
+ uint16_t u16ChannelInfo);
+
+int HGSMIHeapSetup(HGSMIHEAP *pHeap,
+ void *pvBase,
+ HGSMISIZE cbArea,
+ HGSMIOFFSET offBase,
+ const HGSMIENV *pEnv);
+
+void HGSMIHeapDestroy(HGSMIHEAP *pHeap);
+
+void *HGSMIHeapBufferAlloc(HGSMIHEAP *pHeap,
+ HGSMISIZE cbBuffer);
+
+void HGSMIHeapBufferFree(HGSMIHEAP *pHeap,
+ void *pvBuf);
+
+void *HGSMIHeapAlloc(HGSMIHEAP *pHeap,
+ HGSMISIZE cbData,
+ uint8_t u8Channel,
+ uint16_t u16ChannelInfo);
+
+void HGSMIHeapFree(HGSMIHEAP *pHeap,
+ void *pvData);
+
+DECLINLINE(const HGSMIAREA *) HGSMIHeapArea(HGSMIHEAP *pHeap)
+{
+ return &pHeap->area;
+}
+
+DECLINLINE(HGSMIOFFSET) HGSMIHeapOffset(HGSMIHEAP *pHeap)
+{
+ return HGSMIHeapArea(pHeap)->offBase;
+}
+
+DECLINLINE(HGSMISIZE) HGSMIHeapSize(HGSMIHEAP *pHeap)
+{
+ return HGSMIHeapArea(pHeap)->cbArea;
+}
+
+DECLINLINE(HGSMIOFFSET) HGSMIHeapBufferOffset(HGSMIHEAP *pHeap,
+ void *pvData)
+{
+ return HGSMIBufferOffsetFromData(HGSMIHeapArea(pHeap), pvData);
+}
+
+HGSMICHANNEL *HGSMIChannelFindById(HGSMICHANNELINFO *pChannelInfo,
+ uint8_t u8Channel);
+
+int HGSMIChannelRegister(HGSMICHANNELINFO *pChannelInfo,
+ uint8_t u8Channel,
+ const char *pszName,
+ PFNHGSMICHANNELHANDLER pfnChannelHandler,
+ void *pvChannelHandler);
+
+int HGSMIBufferProcess(const HGSMIAREA *pArea,
+ HGSMICHANNELINFO *pChannelInfo,
+ HGSMIOFFSET offBuffer);
+RT_C_DECLS_END
+
+#endif /* !___VBox_Graphics_HGSMI_h */
+
diff --git a/src/HGSMIBase.c b/src/HGSMIBase.c
new file mode 100644
index 0000000..f6cfbb3
--- /dev/null
+++ b/src/HGSMIBase.c
@@ -0,0 +1,293 @@
+/*
+ * Copyright (C) 2006-2017 Oracle Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#include <HGSMIBase.h>
+#include <VBoxVideoIPRT.h>
+#include <VBoxVideoGuest.h>
+#include <VBoxVideoVBE.h>
+#include <HGSMIChannels.h>
+#include <HGSMIChSetup.h>
+
+/** Detect whether HGSMI is supported by the host. */
+DECLHIDDEN(bool) VBoxHGSMIIsSupported(void)
+{
+ uint16_t DispiId;
+
+ VBVO_PORT_WRITE_U16(VBE_DISPI_IOPORT_INDEX, VBE_DISPI_INDEX_ID);
+ VBVO_PORT_WRITE_U16(VBE_DISPI_IOPORT_DATA, VBE_DISPI_ID_HGSMI);
+
+ DispiId = VBVO_PORT_READ_U16(VBE_DISPI_IOPORT_DATA);
+
+ return (DispiId == VBE_DISPI_ID_HGSMI);
+}
+
+
+/**
+ * Inform the host of the location of the host flags in VRAM via an HGSMI command.
+ * @returns IPRT status value.
+ * @returns VERR_NOT_IMPLEMENTED if the host does not support the command.
+ * @returns VERR_NO_MEMORY if a heap allocation fails.
+ * @param pCtx the context of the guest heap to use.
+ * @param offLocation the offset chosen for the flags withing guest VRAM.
+ */
+DECLHIDDEN(int) VBoxHGSMIReportFlagsLocation(PHGSMIGUESTCOMMANDCONTEXT pCtx, HGSMIOFFSET offLocation)
+{
+ HGSMIBUFFERLOCATION *p;
+
+ /* Allocate the IO buffer. */
+ p = (HGSMIBUFFERLOCATION *)VBoxHGSMIBufferAlloc(pCtx, sizeof(*p), HGSMI_CH_HGSMI,
+ HGSMI_CC_HOST_FLAGS_LOCATION);
+ if (!p)
+ return VERR_NO_MEMORY;
+
+ /* Prepare data to be sent to the host. */
+ p->offLocation = offLocation;
+ p->cbLocation = sizeof(HGSMIHOSTFLAGS);
+ /* No need to check that the buffer is valid as we have just allocated it. */
+ VBoxHGSMIBufferSubmit(pCtx, p);
+ /* Free the IO buffer. */
+ VBoxHGSMIBufferFree(pCtx, p);
+
+ return VINF_SUCCESS;
+}
+
+
+/**
+ * Notify the host of HGSMI-related guest capabilities via an HGSMI command.
+ * @returns IPRT status value.
+ * @returns VERR_NOT_IMPLEMENTED if the host does not support the command.
+ * @returns VERR_NO_MEMORY if a heap allocation fails.
+ * @param pCtx the context of the guest heap to use.
+ * @param fCaps the capabilities to report, see VBVACAPS.
+ */
+DECLHIDDEN(int) VBoxHGSMISendCapsInfo(PHGSMIGUESTCOMMANDCONTEXT pCtx, uint32_t fCaps)
+{
+ VBVACAPS *p;
+
+ /* Allocate the IO buffer. */
+ p = (VBVACAPS *)VBoxHGSMIBufferAlloc(pCtx, sizeof(*p), HGSMI_CH_VBVA, VBVA_INFO_CAPS);
+
+ if (!p)
+ return VERR_NO_MEMORY;
+
+ /* Prepare data to be sent to the host. */
+ p->rc = VERR_NOT_IMPLEMENTED;
+ p->fCaps = fCaps;
+ /* No need to check that the buffer is valid as we have just allocated it. */
+ VBoxHGSMIBufferSubmit(pCtx, p);
+
+ AssertRC(p->rc);
+ /* Free the IO buffer. */
+ VBoxHGSMIBufferFree(pCtx, p);
+ return p->rc;
+}
+
+
+/**
+ * Get the information needed to map the basic communication structures in
+ * device memory into our address space. All pointer parameters are optional.
+ *
+ * @param cbVRAM how much video RAM is allocated to the device
+ * @param poffVRAMBaseMapping where to save the offset from the start of the
+ * device VRAM of the whole area to map
+ * @param pcbMapping where to save the mapping size
+ * @param poffGuestHeapMemory where to save the offset into the mapped area
+ * of the guest heap backing memory
+ * @param pcbGuestHeapMemory where to save the size of the guest heap
+ * backing memory
+ * @param poffHostFlags where to save the offset into the mapped area
+ * of the host flags
+ */
+DECLHIDDEN(void) VBoxHGSMIGetBaseMappingInfo(uint32_t cbVRAM,
+ uint32_t *poffVRAMBaseMapping,
+ uint32_t *pcbMapping,
+ uint32_t *poffGuestHeapMemory,
+ uint32_t *pcbGuestHeapMemory,
+ uint32_t *poffHostFlags)
+{
+ AssertPtrNullReturnVoid(poffVRAMBaseMapping);
+ AssertPtrNullReturnVoid(pcbMapping);
+ AssertPtrNullReturnVoid(poffGuestHeapMemory);
+ AssertPtrNullReturnVoid(pcbGuestHeapMemory);
+ AssertPtrNullReturnVoid(poffHostFlags);
+ if (poffVRAMBaseMapping)
+ *poffVRAMBaseMapping = cbVRAM - VBVA_ADAPTER_INFORMATION_SIZE;
+ if (pcbMapping)
+ *pcbMapping = VBVA_ADAPTER_INFORMATION_SIZE;
+ if (poffGuestHeapMemory)
+ *poffGuestHeapMemory = 0;
+ if (pcbGuestHeapMemory)
+ *pcbGuestHeapMemory = VBVA_ADAPTER_INFORMATION_SIZE
+ - sizeof(HGSMIHOSTFLAGS);
+ if (poffHostFlags)
+ *poffHostFlags = VBVA_ADAPTER_INFORMATION_SIZE
+ - sizeof(HGSMIHOSTFLAGS);
+}
+
+/**
+ * Query the host for an HGSMI configuration parameter via an HGSMI command.
+ * @returns iprt status value
+ * @param pCtx the context containing the heap used
+ * @param u32Index the index of the parameter to query,
+ * @see VBVACONF32::u32Index
+ * @param pulValue where to store the value of the parameter on success
+ */
+DECLHIDDEN(int) VBoxQueryConfHGSMI(PHGSMIGUESTCOMMANDCONTEXT pCtx, uint32_t u32Index, uint32_t *pulValue)
+{
+ VBVACONF32 *p;
+
+ /* Allocate the IO buffer. */
+ p = (VBVACONF32 *)VBoxHGSMIBufferAlloc(pCtx, sizeof(*p), HGSMI_CH_VBVA,
+ VBVA_QUERY_CONF32);
+ if (!p)
+ return VERR_NO_MEMORY;
+
+ /* Prepare data to be sent to the host. */
+ p->u32Index = u32Index;
+ p->u32Value = UINT32_MAX;
+ /* No need to check that the buffer is valid as we have just allocated it. */
+ VBoxHGSMIBufferSubmit(pCtx, p);
+ *pulValue = p->u32Value;
+ /* Free the IO buffer. */
+ VBoxHGSMIBufferFree(pCtx, p);
+ return VINF_SUCCESS;
+}
+
+/**
+ * Pass the host a new mouse pointer shape via an HGSMI command.
+ *
+ * @returns success or failure
+ * @param pCtx the context containing the heap to be used
+ * @param fFlags cursor flags, @see VMMDevReqMousePointer::fFlags
+ * @param cHotX horizontal position of the hot spot
+ * @param cHotY vertical position of the hot spot
+ * @param cWidth width in pixels of the cursor
+ * @param cHeight height in pixels of the cursor
+ * @param pPixels pixel data, @see VMMDevReqMousePointer for the format
+ * @param cbLength size in bytes of the pixel data
+ */
+DECLHIDDEN(int) VBoxHGSMIUpdatePointerShape(PHGSMIGUESTCOMMANDCONTEXT pCtx, uint32_t fFlags,
+ uint32_t cHotX, uint32_t cHotY, uint32_t cWidth, uint32_t cHeight,
+ uint8_t *pPixels, uint32_t cbLength)
+{
+ VBVAMOUSEPOINTERSHAPE *p;
+ uint32_t cbPixels = 0;
+ int rc;
+
+ if (fFlags & VBOX_MOUSE_POINTER_SHAPE)
+ {
+ /*
+ * Size of the pointer data:
+ * sizeof (AND mask) + sizeof (XOR_MASK)
+ */
+ cbPixels = ((((cWidth + 7) / 8) * cHeight + 3) & ~3)
+ + cWidth * 4 * cHeight;
+ if (cbPixels > cbLength)
+ return VERR_INVALID_PARAMETER;
+ /*
+ * If shape is supplied, then always create the pointer visible.
+ * See comments in 'vboxUpdatePointerShape'
+ */
+ fFlags |= VBOX_MOUSE_POINTER_VISIBLE;
+ }
+ /* Allocate the IO buffer. */
+ p = (VBVAMOUSEPOINTERSHAPE *)VBoxHGSMIBufferAlloc(pCtx, sizeof(*p) + cbPixels, HGSMI_CH_VBVA,
+ VBVA_MOUSE_POINTER_SHAPE);
+ if (!p)
+ return VERR_NO_MEMORY;
+ /* Prepare data to be sent to the host. */
+ /* Will be updated by the host. */
+ p->i32Result = VINF_SUCCESS;
+ /* We have our custom flags in the field */
+ p->fu32Flags = fFlags;
+ p->u32HotX = cHotX;
+ p->u32HotY = cHotY;
+ p->u32Width = cWidth;
+ p->u32Height = cHeight;
+ if (cbPixels)
+ /* Copy the actual pointer data. */
+ memcpy (p->au8Data, pPixels, cbPixels);
+ /* No need to check that the buffer is valid as we have just allocated it. */
+ VBoxHGSMIBufferSubmit(pCtx, p);
+ rc = p->i32Result;
+ /* Free the IO buffer. */
+ VBoxHGSMIBufferFree(pCtx, p);
+ return rc;
+}
+
+
+/**
+ * Report the guest cursor position. The host may wish to use this information
+ * to re-position its own cursor (though this is currently unlikely). The
+ * current host cursor position is returned.
+ * @param pCtx The context containing the heap used.
+ * @param fReportPosition Are we reporting a position?
+ * @param x Guest cursor X position.
+ * @param y Guest cursor Y position.
+ * @param pxHost Host cursor X position is stored here. Optional.
+ * @param pyHost Host cursor Y position is stored here. Optional.
+ * @returns iprt status code.
+ * @returns VERR_NO_MEMORY HGSMI heap allocation failed.
+ */
+DECLHIDDEN(int) VBoxHGSMICursorPosition(PHGSMIGUESTCOMMANDCONTEXT pCtx, bool fReportPosition,
+ uint32_t x, uint32_t y, uint32_t *pxHost, uint32_t *pyHost)
+{
+ VBVACURSORPOSITION *p;
+
+ /* Allocate the IO buffer. */
+ p = (VBVACURSORPOSITION *)VBoxHGSMIBufferAlloc(pCtx, sizeof(*p), HGSMI_CH_VBVA,
+ VBVA_CURSOR_POSITION);
+ if (!p)
+ return VERR_NO_MEMORY;
+ /* Prepare data to be sent to the host. */
+ p->fReportPosition = fReportPosition;
+ p->x = x;
+ p->y = y;
+ /* No need to check that the buffer is valid as we have just allocated it. */
+ VBoxHGSMIBufferSubmit(pCtx, p);
+ if (pxHost)
+ *pxHost = p->x;
+ if (pyHost)
+ *pyHost = p->y;
+ /* Free the IO buffer. */
+ VBoxHGSMIBufferFree(pCtx, p);
+ return VINF_SUCCESS;
+}
+
+
+/**
+ * @todo Mouse pointer position to be read from VMMDev memory, address of the
+ * memory region can be queried from VMMDev via an IOCTL. This VMMDev memory
+ * region will contain host information which is needed by the guest.
+ *
+ * Reading will not cause a switch to the host.
+ *
+ * Have to take into account:
+ * * synchronization: host must write to the memory only from EMT,
+ * large structures must be read under flag, which tells the host
+ * that the guest is currently reading the memory (OWNER flag?).
+ * * guest writes: may be allocate a page for the host info and make
+ * the page readonly for the guest.
+ * * the information should be available only for additions drivers.
+ * * VMMDev additions driver will inform the host which version of the info
+ * it expects, host must support all versions.
+ */
diff --git a/src/HGSMIBase.h b/src/HGSMIBase.h
new file mode 100644
index 0000000..c8d898c
--- /dev/null
+++ b/src/HGSMIBase.h
@@ -0,0 +1,54 @@
+/*
+ * Copyright (C) 2006-2017 Oracle Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM,
+ * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+ * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+ * USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+
+#ifndef ___VBox_Graphics_HGSMIBase_h___
+#define ___VBox_Graphics_HGSMIBase_h___
+
+#include "HGSMI.h"
+#include "HGSMIContext.h"
+#include "VBoxVideoIPRT.h"
+
+RT_C_DECLS_BEGIN
+
+/** @name Base HGSMI Buffer APIs
+ * @{ */
+
+/** Acknowlege an IRQ. */
+DECLINLINE(void) VBoxHGSMIClearIrq(PHGSMIHOSTCOMMANDCONTEXT pCtx)
+{
+ VBVO_PORT_WRITE_U32(pCtx->port, HGSMIOFFSET_VOID);
+}
+
+DECLHIDDEN(void *) VBoxHGSMIBufferAlloc(PHGSMIGUESTCOMMANDCONTEXT pCtx,
+ HGSMISIZE cbData,
+ uint8_t u8Ch,
+ uint16_t u16Op);
+DECLHIDDEN(void) VBoxHGSMIBufferFree(PHGSMIGUESTCOMMANDCONTEXT pCtx,
+ void *pvBuffer);
+DECLHIDDEN(int) VBoxHGSMIBufferSubmit(PHGSMIGUESTCOMMANDCONTEXT pCtx,
+ void *pvBuffer);
+/** @} */
+
+RT_C_DECLS_END
+
+#endif
diff --git a/src/HGSMIBuffers.c b/src/HGSMIBuffers.c
new file mode 100644
index 0000000..1f8ed07
--- /dev/null
+++ b/src/HGSMIBuffers.c
@@ -0,0 +1,118 @@
+/*
+ * Copyright (C) 2006-2017 Oracle Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#include <VBoxVideoGuest.h>
+#include <VBoxVideoVBE.h>
+#include <VBoxVideoIPRT.h>
+
+/**
+ * Set up the HGSMI guest-to-host command context.
+ * @returns iprt status value
+ * @param pCtx the context to set up
+ * @param pvGuestHeapMemory a pointer to the mapped backing memory for
+ * the guest heap
+ * @param cbGuestHeapMemory the size of the backing memory area
+ * @param offVRAMGuestHeapMemory the offset of the memory pointed to by
+ * @a pvGuestHeapMemory within the video RAM
+ * @param pEnv HGSMI environment.
+ */
+DECLHIDDEN(int) VBoxHGSMISetupGuestContext(PHGSMIGUESTCOMMANDCONTEXT pCtx,
+ void *pvGuestHeapMemory,
+ uint32_t cbGuestHeapMemory,
+ uint32_t offVRAMGuestHeapMemory,
+ const HGSMIENV *pEnv)
+{
+ /** @todo should we be using a fixed ISA port value here? */
+ pCtx->port = (RTIOPORT)VGA_PORT_HGSMI_GUEST;
+#ifdef VBOX_WDDM_MINIPORT
+ return VBoxSHGSMIInit(&pCtx->heapCtx, pvGuestHeapMemory,
+ cbGuestHeapMemory, offVRAMGuestHeapMemory, pEnv);
+#else
+ return HGSMIHeapSetup(&pCtx->heapCtx, pvGuestHeapMemory,
+ cbGuestHeapMemory, offVRAMGuestHeapMemory, pEnv);
+#endif
+}
+
+
+/**
+ * Allocate and initialise a command descriptor in the guest heap for a
+ * guest-to-host command.
+ *
+ * @returns pointer to the descriptor's command data buffer
+ * @param pCtx the context containing the heap to be used
+ * @param cbData the size of the command data to go into the descriptor
+ * @param u8Ch the HGSMI channel to be used, set to the descriptor
+ * @param u16Op the HGSMI command to be sent, set to the descriptor
+ */
+DECLHIDDEN(void *) VBoxHGSMIBufferAlloc(PHGSMIGUESTCOMMANDCONTEXT pCtx,
+ HGSMISIZE cbData,
+ uint8_t u8Ch,
+ uint16_t u16Op)
+{
+#ifdef VBOX_WDDM_MINIPORT
+ return VBoxSHGSMIHeapAlloc (&pCtx->heapCtx, cbData, u8Ch, u16Op);
+#else
+ return HGSMIHeapAlloc (&pCtx->heapCtx, cbData, u8Ch, u16Op);
+#endif
+}
+
+
+/**
+ * Free a descriptor allocated by @a VBoxHGSMIBufferAlloc.
+ *
+ * @param pCtx the context containing the heap used
+ * @param pvBuffer the pointer returned by @a VBoxHGSMIBufferAlloc
+ */
+DECLHIDDEN(void) VBoxHGSMIBufferFree(PHGSMIGUESTCOMMANDCONTEXT pCtx,
+ void *pvBuffer)
+{
+#ifdef VBOX_WDDM_MINIPORT
+ VBoxSHGSMIHeapFree (&pCtx->heapCtx, pvBuffer);
+#else
+ HGSMIHeapFree (&pCtx->heapCtx, pvBuffer);
+#endif
+}
+
+/**
+ * Submit a command descriptor allocated by @a VBoxHGSMIBufferAlloc.
+ *
+ * @param pCtx the context containing the heap used
+ * @param pvBuffer the pointer returned by @a VBoxHGSMIBufferAlloc
+ */
+DECLHIDDEN(int) VBoxHGSMIBufferSubmit(PHGSMIGUESTCOMMANDCONTEXT pCtx,
+ void *pvBuffer)
+{
+ /* Initialize the buffer and get the offset for port IO. */
+ HGSMIOFFSET offBuffer = HGSMIHeapBufferOffset (HGSMIGUESTCMDHEAP_GET(&pCtx->heapCtx), pvBuffer);
+
+ Assert(offBuffer != HGSMIOFFSET_VOID);
+ if (offBuffer != HGSMIOFFSET_VOID)
+ {
+ /* Submit the buffer to the host. */
+ VBVO_PORT_WRITE_U32(pCtx->port, offBuffer);
+ /* Make the compiler aware that the host has changed memory. */
+ ASMCompilerBarrier();
+ return VINF_SUCCESS;
+ }
+
+ return VERR_INVALID_PARAMETER;
+}
diff --git a/src/HGSMIChSetup.h b/src/HGSMIChSetup.h
new file mode 100644
index 0000000..fcf62f3
--- /dev/null
+++ b/src/HGSMIChSetup.h
@@ -0,0 +1,79 @@
+/*
+ * Copyright (C) 2006-2017 Oracle Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#ifndef ___VBox_Graphics_HGSMIChSetup_h
+#define ___VBox_Graphics_HGSMIChSetup_h
+
+#include "HGSMIDefs.h"
+
+/* HGSMI setup and configuration channel commands and data structures. */
+/*
+ * Tell the host the location of hgsmi_host_flags structure, where the host
+ * can write information about pending buffers, etc, and which can be quickly
+ * polled by the guest without a need to port IO.
+ */
+#define HGSMI_CC_HOST_FLAGS_LOCATION 0
+
+typedef struct HGSMIBUFFERLOCATION
+{
+ HGSMIOFFSET offLocation;
+ HGSMISIZE cbLocation;
+} HGSMIBUFFERLOCATION;
+AssertCompileSize(HGSMIBUFFERLOCATION, 8);
+
+/* HGSMI setup and configuration data structures. */
+/* host->guest commands pending, should be accessed under FIFO lock only */
+#define HGSMIHOSTFLAGS_COMMANDS_PENDING UINT32_C(0x01)
+/* IRQ is fired, should be accessed under VGAState::lock only */
+#define HGSMIHOSTFLAGS_IRQ UINT32_C(0x02)
+#ifdef VBOX_WITH_WDDM
+/* one or more guest commands is completed, should be accessed under FIFO lock only */
+# define HGSMIHOSTFLAGS_GCOMMAND_COMPLETED UINT32_C(0x04)
+/* watchdog timer interrupt flag (used for debugging), should be accessed under VGAState::lock only */
+# define HGSMIHOSTFLAGS_WATCHDOG UINT32_C(0x08)
+#endif
+/* vsync interrupt flag, should be accessed under VGAState::lock only */
+#define HGSMIHOSTFLAGS_VSYNC UINT32_C(0x10)
+/** monitor hotplug flag, should be accessed under VGAState::lock only */
+#define HGSMIHOSTFLAGS_HOTPLUG UINT32_C(0x20)
+/**
+ * Cursor capability state change flag, should be accessed under
+ * VGAState::lock only. @see VBVACONF32.
+ */
+#define HGSMIHOSTFLAGS_CURSOR_CAPABILITIES UINT32_C(0x40)
+
+typedef struct HGSMIHOSTFLAGS
+{
+ /*
+ * Host flags can be accessed and modified in multiple threads
+ * concurrently, e.g. CrOpenGL HGCM and GUI threads when completing
+ * HGSMI 3D and Video Accel respectively, EMT thread when dealing with
+ * HGSMI command processing, etc.
+ * Besides settings/cleaning flags atomically, some flags have their
+ * own special sync restrictions, see comments for flags above.
+ */
+ volatile uint32_t u32HostFlags;
+ uint32_t au32Reserved[3];
+} HGSMIHOSTFLAGS;
+AssertCompileSize(HGSMIHOSTFLAGS, 16);
+
+#endif
diff --git a/src/HGSMIChannels.h b/src/HGSMIChannels.h
new file mode 100644
index 0000000..12af291
--- /dev/null
+++ b/src/HGSMIChannels.h
@@ -0,0 +1,64 @@
+/*
+ * Copyright (C) 2006-2017 Oracle Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+
+#ifndef __HGSMIChannels_h__
+#define __HGSMIChannels_h__
+
+
+/*
+ * Each channel has an 8 bit identifier. There are a number of predefined
+ * (hardcoded) channels.
+ *
+ * HGSMI_CH_HGSMI channel can be used to map a string channel identifier
+ * to a free 16 bit numerical value. values are allocated in range
+ * [HGSMI_CH_STRING_FIRST;HGSMI_CH_STRING_LAST].
+ */
+
+
+/* Predefined channel identifiers. Used internally by VBOX to simplify the channel setup. */
+/* A reserved channel value */
+#define HGSMI_CH_RESERVED 0x00
+/* HGCMI: setup and configuration */
+#define HGSMI_CH_HGSMI 0x01
+/* Graphics: VBVA */
+#define HGSMI_CH_VBVA 0x02
+/* Graphics: Seamless with a single guest region */
+#define HGSMI_CH_SEAMLESS 0x03
+/* Graphics: Seamless with separate host windows */
+#define HGSMI_CH_SEAMLESS2 0x04
+/* Graphics: OpenGL HW acceleration */
+#define HGSMI_CH_OPENGL 0x05
+
+
+/* Dynamically allocated channel identifiers. */
+/* The first channel index to be used for string mappings (inclusive) */
+#define HGSMI_CH_STRING_FIRST 0x20
+/* The last channel index for string mappings (inclusive) */
+#define HGSMI_CH_STRING_LAST 0xff
+
+
+/* Check whether the channel identifier is allocated for a dynamic channel */
+#define HGSMI_IS_DYNAMIC_CHANNEL(_channel) (((uint8_t)(_channel) & 0xE0) != 0)
+
+
+#endif /* !__HGSMIChannels_h__*/
diff --git a/src/HGSMICommon.c b/src/HGSMICommon.c
new file mode 100644
index 0000000..59d3325
--- /dev/null
+++ b/src/HGSMICommon.c
@@ -0,0 +1,449 @@
+/*
+ * Copyright (C) 2006-2017 Oracle Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#define LOG_DISABLED /* Maybe we can enabled it all the time now? */
+/** @note commented out all logging statements to avoid pulling the logging
+ * sub-system into places like the Linux kernel driver. Perhaps the best
+ * thing would be to use return enough information for callers to log what
+ * is needed. */
+#define LOG_GROUP LOG_GROUP_HGSMI
+
+#include <VBoxVideoIPRT.h>
+
+#include <HGSMI.h>
+
+/* Channel flags. */
+#define HGSMI_CH_F_REGISTERED 0x01
+
+/* Assertions for situations which could happen and normally must be processed properly
+ * but must be investigated during development: guest misbehaving, etc.
+ */
+#ifdef HGSMI_STRICT
+#define HGSMI_STRICT_ASSERT_FAILED() AssertFailed()
+#define HGSMI_STRICT_ASSERT(expr) Assert(expr)
+#else
+#define HGSMI_STRICT_ASSERT_FAILED() do {} while (0)
+#define HGSMI_STRICT_ASSERT(expr) do {} while (0)
+#endif /* !HGSMI_STRICT */
+
+/*
+ * We do not want assertions in Linux kernel code to reduce symbol dependencies.
+ */
+#if defined(IN_RING0) && defined(RT_OS_LINUX)
+# define HGSMI_ASSERT_PTR_RETURN(a, b) if (!(a)) return (b)
+#else
+# define HGSMI_ASSERT_PTR_RETURN(a, b) if (!(a)) return (b)
+#endif /* !IN_RING0 && RT_OS_LINUX */
+
+/* One-at-a-Time Hash from
+ * http://www.burtleburtle.net/bob/hash/doobs.html
+ *
+ * ub4 one_at_a_time(char *key, ub4 len)
+ * {
+ * ub4 hash, i;
+ * for (hash=0, i=0; i<len; ++i)
+ * {
+ * hash += key[i];
+ * hash += (hash << 10);
+ * hash ^= (hash >> 6);
+ * }
+ * hash += (hash << 3);
+ * hash ^= (hash >> 11);
+ * hash += (hash << 15);
+ * return hash;
+ * }
+ */
+
+static uint32_t hgsmiHashBegin(void)
+{
+ return 0;
+}
+
+static uint32_t hgsmiHashProcess(uint32_t hash,
+ const void *pvData,
+ size_t cbData)
+{
+ const uint8_t *pu8Data = (const uint8_t *)pvData;
+
+ while (cbData--)
+ {
+ hash += *pu8Data++;
+ hash += (hash << 10);
+ hash ^= (hash >> 6);
+ }
+
+ return hash;
+}
+
+static uint32_t hgsmiHashEnd(uint32_t hash)
+{
+ hash += (hash << 3);
+ hash ^= (hash >> 11);
+ hash += (hash << 15);
+
+ return hash;
+}
+
+uint32_t HGSMIChecksum(HGSMIOFFSET offBuffer,
+ const HGSMIBUFFERHEADER *pHeader,
+ const HGSMIBUFFERTAIL *pTail)
+{
+ uint32_t u32Checksum = hgsmiHashBegin();
+
+ u32Checksum = hgsmiHashProcess(u32Checksum, &offBuffer, sizeof(offBuffer));
+ u32Checksum = hgsmiHashProcess(u32Checksum, pHeader, sizeof(HGSMIBUFFERHEADER));
+ u32Checksum = hgsmiHashProcess(u32Checksum, pTail, offsetof(HGSMIBUFFERTAIL, u32Checksum));
+
+ return hgsmiHashEnd(u32Checksum);
+}
+
+int HGSMIAreaInitialize(HGSMIAREA *pArea,
+ void *pvBase,
+ HGSMISIZE cbArea,
+ HGSMIOFFSET offBase)
+{
+ uint8_t *pu8Base = (uint8_t *)pvBase;
+
+ if ( !pArea /* Check that the area: */
+ || cbArea < HGSMIBufferMinimumSize() /* large enough; */
+ || pu8Base + cbArea < pu8Base /* no address space wrap; */
+ || offBase > UINT32_C(0xFFFFFFFF) - cbArea /* area within the 32 bit space: offBase + cbMem <= 0xFFFFFFFF. */
+ )
+ {
+ return VERR_INVALID_PARAMETER;
+ }
+
+ pArea->pu8Base = pu8Base;
+ pArea->offBase = offBase;
+ pArea->offLast = cbArea - HGSMIBufferMinimumSize() + offBase;
+ pArea->cbArea = cbArea;
+
+ return VINF_SUCCESS;
+}
+
+void HGSMIAreaClear(HGSMIAREA *pArea)
+{
+ if (pArea)
+ {
+ memset(pArea, 0, sizeof(*pArea));
+ }
+}
+
+/* Initialize the memory buffer including its checksum.
+ * No changes alloed to the header and the tail after that.
+ */
+HGSMIOFFSET HGSMIBufferInitializeSingle(const HGSMIAREA *pArea,
+ HGSMIBUFFERHEADER *pHeader,
+ HGSMISIZE cbBuffer,
+ uint8_t u8Channel,
+ uint16_t u16ChannelInfo)
+{
+ if ( !pArea
+ || !pHeader
+ || cbBuffer < HGSMIBufferMinimumSize())
+ {
+ return HGSMIOFFSET_VOID;
+ }
+
+ /* Buffer must be within the area:
+ * * header data size do not exceed the maximum data size;
+ * * buffer address is greater than the area base address;
+ * * buffer address is lower than the maximum allowed for the given data size.
+ */
+ HGSMISIZE cbMaximumDataSize = pArea->offLast - pArea->offBase;
+ uint32_t u32DataSize = cbBuffer - HGSMIBufferMinimumSize();
+
+ if ( u32DataSize > cbMaximumDataSize
+ || (uint8_t *)pHeader < pArea->pu8Base
+ || (uint8_t *)pHeader > pArea->pu8Base + cbMaximumDataSize - u32DataSize)
+ {
+ return HGSMIOFFSET_VOID;
+ }
+
+ HGSMIOFFSET offBuffer = HGSMIPointerToOffset(pArea, pHeader);
+
+ pHeader->u8Flags = HGSMI_BUFFER_HEADER_F_SEQ_SINGLE;
+ pHeader->u32DataSize = u32DataSize;
+ pHeader->u8Channel = u8Channel;
+ pHeader->u16ChannelInfo = u16ChannelInfo;
+ memset(&pHeader->u.au8Union, 0, sizeof(pHeader->u.au8Union));
+
+ HGSMIBUFFERTAIL *pTail = HGSMIBufferTailFromPtr(pHeader, u32DataSize);
+ pTail->u32Reserved = 0;
+ pTail->u32Checksum = HGSMIChecksum(offBuffer, pHeader, pTail);
+
+ return offBuffer;
+}
+
+int HGSMIHeapSetup(HGSMIHEAP *pHeap,
+ void *pvBase,
+ HGSMISIZE cbArea,
+ HGSMIOFFSET offBase,
+ const HGSMIENV *pEnv)
+{
+ HGSMI_ASSERT_PTR_RETURN(pHeap, VERR_INVALID_PARAMETER);
+ HGSMI_ASSERT_PTR_RETURN(pvBase, VERR_INVALID_PARAMETER);
+
+ int rc = HGSMIAreaInitialize(&pHeap->area, pvBase, cbArea, offBase);
+ if (RT_SUCCESS(rc))
+ {
+ rc = HGSMIMAInit(&pHeap->ma, &pHeap->area, NULL, 0, 0, pEnv);
+ if (RT_FAILURE(rc))
+ {
+ HGSMIAreaClear(&pHeap->area);
+ }
+ }
+
+ return rc;
+}
+
+void HGSMIHeapDestroy(HGSMIHEAP *pHeap)
+{
+ if (pHeap)
+ {
+ HGSMIMAUninit(&pHeap->ma);
+ memset(pHeap, 0, sizeof(*pHeap));
+ }
+}
+
+void *HGSMIHeapAlloc(HGSMIHEAP *pHeap,
+ HGSMISIZE cbData,
+ uint8_t u8Channel,
+ uint16_t u16ChannelInfo)
+{
+ HGSMISIZE cbAlloc = HGSMIBufferRequiredSize(cbData);
+ HGSMIBUFFERHEADER *pHeader = (HGSMIBUFFERHEADER *)HGSMIHeapBufferAlloc(pHeap, cbAlloc);
+ if (pHeader)
+ {
+ HGSMIOFFSET offBuffer = HGSMIBufferInitializeSingle(HGSMIHeapArea(pHeap), pHeader,
+ cbAlloc, u8Channel, u16ChannelInfo);
+ if (offBuffer == HGSMIOFFSET_VOID)
+ {
+ HGSMIHeapBufferFree(pHeap, pHeader);
+ pHeader = NULL;
+ }
+ }
+
+ return pHeader? HGSMIBufferDataFromPtr(pHeader): NULL;
+}
+
+void HGSMIHeapFree(HGSMIHEAP *pHeap,
+ void *pvData)
+{
+ if (pvData)
+ {
+ HGSMIBUFFERHEADER *pHeader = HGSMIBufferHeaderFromData(pvData);
+ HGSMIHeapBufferFree(pHeap, pHeader);
+ }
+}
+
+void *HGSMIHeapBufferAlloc(HGSMIHEAP *pHeap,
+ HGSMISIZE cbBuffer)
+{
+ void *pvBuf = HGSMIMAAlloc(&pHeap->ma, cbBuffer);
+ return pvBuf;
+}
+
+void HGSMIHeapBufferFree(HGSMIHEAP *pHeap,
+ void *pvBuf)
+{
+ HGSMIMAFree(&pHeap->ma, pvBuf);
+}
+
+typedef struct HGSMIBUFFERCONTEXT
+{
+ const HGSMIBUFFERHEADER *pHeader; /* The original buffer header. */
+ void *pvData; /* Payload data in the buffer./ */
+ uint32_t cbData; /* Size of data */
+} HGSMIBUFFERCONTEXT;
+
+/** Verify that the given offBuffer points to a valid buffer, which is within the area.
+ *
+ * @returns VBox status and the buffer information in pBufferContext.
+ * @param pArea Area which supposed to contain the buffer.
+ * @param offBuffer The buffer location in the area.
+ * @param pBufferContext Where to write information about the buffer.
+ */
+static int hgsmiVerifyBuffer(const HGSMIAREA *pArea,
+ HGSMIOFFSET offBuffer,
+ HGSMIBUFFERCONTEXT *pBufferContext)
+{
+ // LogFlowFunc(("buffer 0x%x, area %p %x [0x%x;0x%x]\n",
+ // offBuffer, pArea->pu8Base, pArea->cbArea, pArea->offBase, pArea->offLast));
+
+ int rc = VINF_SUCCESS;
+
+ if ( offBuffer < pArea->offBase
+ || offBuffer > pArea->offLast)
+ {
+ // LogFunc(("offset 0x%x is outside the area [0x%x;0x%x]!!!\n",
+ // offBuffer, pArea->offBase, pArea->offLast));
+ rc = VERR_INVALID_PARAMETER;
+ HGSMI_STRICT_ASSERT_FAILED();
+ }
+ else
+ {
+ void *pvBuffer = HGSMIOffsetToPointer(pArea, offBuffer);
+ HGSMIBUFFERHEADER header = *HGSMIBufferHeaderFromPtr(pvBuffer);
+
+ /* Quick check of the data size, it should be less than the maximum
+ * data size for the buffer at this offset.
+ */
+ // LogFlowFunc(("datasize check: header.u32DataSize = 0x%x pArea->offLast - offBuffer = 0x%x\n",
+ // header.u32DataSize, pArea->offLast - offBuffer));
+
+ if (header.u32DataSize <= pArea->offLast - offBuffer)
+ {
+ HGSMIBUFFERTAIL tail = *HGSMIBufferTailFromPtr(pvBuffer, header.u32DataSize);
+
+ /* At least both header and tail structures are in the area. Check the checksum. */
+ uint32_t u32Checksum = HGSMIChecksum(offBuffer, &header, &tail);
+ // LogFlowFunc(("checksum check: u32Checksum = 0x%x pTail->u32Checksum = 0x%x\n",
+ // u32Checksum, tail.u32Checksum));
+ if (u32Checksum == tail.u32Checksum)
+ {
+ /* Success. */
+ pBufferContext->pHeader = HGSMIBufferHeaderFromPtr(pvBuffer);
+ pBufferContext->pvData = HGSMIBufferDataFromPtr(pvBuffer);
+ pBufferContext->cbData = header.u32DataSize;
+ }
+ else
+ {
+ // LogFunc(("invalid checksum 0x%x, expected 0x%x!!!\n",
+ // u32Checksum, tail.u32Checksum));
+ rc = VERR_INVALID_STATE;
+ HGSMI_STRICT_ASSERT_FAILED();
+ }
+ }
+ else
+ {
+ // LogFunc(("invalid data size 0x%x, maximum is 0x%x!!!\n",
+ // header.u32DataSize, pArea->offLast - offBuffer));
+ rc = VERR_TOO_MUCH_DATA;
+ HGSMI_STRICT_ASSERT_FAILED();
+ }
+ }
+
+ return rc;
+}
+
+/** Helper to convert HGSMI channel index to the channel structure pointer.
+ *
+ * @returns Pointer to the channel data.
+ * @param pChannelInfo The channel pool.
+ * @param u8Channel The channel index.
+ */
+HGSMICHANNEL *HGSMIChannelFindById(HGSMICHANNELINFO *pChannelInfo,
+ uint8_t u8Channel)
+{
+ AssertCompile(RT_ELEMENTS(pChannelInfo->Channels) >= 0x100);
+ HGSMICHANNEL *pChannel = &pChannelInfo->Channels[u8Channel];
+
+ if (pChannel->u8Flags & HGSMI_CH_F_REGISTERED)
+ {
+ return pChannel;
+ }
+
+ return NULL;
+}
+
+/** Process a guest buffer.
+ *
+ * @returns VBox status code.
+ * @param pArea Area which supposed to contain the buffer.
+ * @param pChannelInfo The channel pool.
+ * @param offBuffer The buffer location in the area.
+ */
+int HGSMIBufferProcess(const HGSMIAREA *pArea,
+ HGSMICHANNELINFO *pChannelInfo,
+ HGSMIOFFSET offBuffer)
+{
+ // LogFlowFunc(("pArea %p, offBuffer 0x%x\n", pArea, offBuffer));
+
+ HGSMI_ASSERT_PTR_RETURN(pArea, VERR_INVALID_PARAMETER);
+ HGSMI_ASSERT_PTR_RETURN(pChannelInfo, VERR_INVALID_PARAMETER);
+
+ /* Guest has prepared a command description at 'offBuffer'. */
+ HGSMIBUFFERCONTEXT bufferContext = { NULL, NULL, 0 }; /* Makes old GCC happier. */
+ int rc = hgsmiVerifyBuffer(pArea, offBuffer, &bufferContext);
+ if (RT_SUCCESS(rc))
+ {
+ /* Pass the command to the appropriate handler registered with this instance.
+ * Start with the handler list head, which is the preallocated HGSMI setup channel.
+ */
+ const HGSMICHANNEL *pChannel = HGSMIChannelFindById(pChannelInfo, bufferContext.pHeader->u8Channel);
+ if (pChannel)
+ {
+ const HGSMICHANNELHANDLER *pHandler = &pChannel->handler;
+ if (pHandler->pfnHandler)
+ {
+ pHandler->pfnHandler(pHandler->pvHandler, bufferContext.pHeader->u16ChannelInfo,
+ bufferContext.pvData, bufferContext.cbData);
+ }
+ HGSMI_STRICT_ASSERT(RT_SUCCESS(hgsmiVerifyBuffer(pArea, offBuffer, &bufferContext)));
+ }
+ else
+ {
+ rc = VERR_INVALID_FUNCTION;
+ HGSMI_STRICT_ASSERT_FAILED();
+ }
+ }
+
+ return rc;
+}
+
+/** Register a new HGSMI channel by index.
+ *
+ * @returns VBox status code.
+ * @param pChannelInfo The channel pool managed by the caller.
+ * @param u8Channel Index of the channel.
+ * @param pszName Name of the channel (optional, allocated by the caller).
+ * @param pfnChannelHandler The channel callback.
+ * @param pvChannelHandler The callback pointer.
+ */
+int HGSMIChannelRegister(HGSMICHANNELINFO *pChannelInfo,
+ uint8_t u8Channel,
+ const char *pszName,
+ PFNHGSMICHANNELHANDLER pfnChannelHandler,
+ void *pvChannelHandler)
+{
+ /* Check whether the channel is already registered. */
+ HGSMICHANNEL *pChannel = HGSMIChannelFindById(pChannelInfo, u8Channel);
+ if (pChannel)
+ {
+ HGSMI_STRICT_ASSERT_FAILED();
+ return VERR_ALREADY_EXISTS;
+ }
+
+ /* Channel is not yet registered. */
+ pChannel = &pChannelInfo->Channels[u8Channel];
+
+ pChannel->u8Flags = HGSMI_CH_F_REGISTERED;
+ pChannel->u8Channel = u8Channel;
+
+ pChannel->handler.pfnHandler = pfnChannelHandler;
+ pChannel->handler.pvHandler = pvChannelHandler;
+
+ pChannel->pszName = pszName;
+
+ return VINF_SUCCESS;
+}
diff --git a/src/HGSMIContext.h b/src/HGSMIContext.h
new file mode 100644
index 0000000..716dc42
--- /dev/null
+++ b/src/HGSMIContext.h
@@ -0,0 +1,104 @@
+/*
+ * Copyright (C) 2006-2017 Oracle Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM,
+ * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+ * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+ * USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+
+#ifndef ___VBox_Graphics_HGSMIContext_h___
+#define ___VBox_Graphics_HGSMIContext_h___
+
+#include "HGSMI.h"
+#include "HGSMIChSetup.h"
+#include "VBoxVideoIPRT.h"
+
+#ifdef VBOX_WDDM_MINIPORT
+# include "wddm/VBoxMPShgsmi.h"
+ typedef VBOXSHGSMI HGSMIGUESTCMDHEAP;
+# define HGSMIGUESTCMDHEAP_GET(_p) (&(_p)->Heap)
+#else
+ typedef HGSMIHEAP HGSMIGUESTCMDHEAP;
+# define HGSMIGUESTCMDHEAP_GET(_p) (_p)
+#endif
+
+RT_C_DECLS_BEGIN
+
+/**
+ * Structure grouping the context needed for submitting commands to the host
+ * via HGSMI
+ */
+typedef struct HGSMIGUESTCOMMANDCONTEXT
+{
+ /** Information about the memory heap located in VRAM from which data
+ * structures to be sent to the host are allocated. */
+ HGSMIGUESTCMDHEAP heapCtx;
+ /** The I/O port used for submitting commands to the host by writing their
+ * offsets into the heap. */
+ RTIOPORT port;
+} HGSMIGUESTCOMMANDCONTEXT, *PHGSMIGUESTCOMMANDCONTEXT;
+
+
+/**
+ * Structure grouping the context needed for receiving commands from the host
+ * via HGSMI
+ */
+typedef struct HGSMIHOSTCOMMANDCONTEXT
+{
+ /** Information about the memory area located in VRAM in which the host
+ * places data structures to be read by the guest. */
+ HGSMIAREA areaCtx;
+ /** Convenience structure used for matching host commands to handlers. */
+ /** @todo handlers are registered individually in code rather than just
+ * passing a static structure in order to gain extra flexibility. There is
+ * currently no expected usage case for this though. Is the additional
+ * complexity really justified? */
+ HGSMICHANNELINFO channels;
+ /** Flag to indicate that one thread is currently processing the command
+ * queue. */
+ volatile bool fHostCmdProcessing;
+ /* Pointer to the VRAM location where the HGSMI host flags are kept. */
+ volatile HGSMIHOSTFLAGS *pfHostFlags;
+ /** The I/O port used for receiving commands from the host as offsets into
+ * the memory area and sending back confirmations (command completion,
+ * IRQ acknowlegement). */
+ RTIOPORT port;
+} HGSMIHOSTCOMMANDCONTEXT, *PHGSMIHOSTCOMMANDCONTEXT;
+
+/** @name HGSMI context initialisation APIs.
+ * @{ */
+
+/** @todo we should provide a cleanup function too as part of the API */
+DECLHIDDEN(int) VBoxHGSMISetupGuestContext(PHGSMIGUESTCOMMANDCONTEXT pCtx,
+ void *pvGuestHeapMemory,
+ uint32_t cbGuestHeapMemory,
+ uint32_t offVRAMGuestHeapMemory,
+ const HGSMIENV *pEnv);
+DECLHIDDEN(void) VBoxHGSMISetupHostContext(PHGSMIHOSTCOMMANDCONTEXT pCtx,
+ void *pvBaseMapping,
+ uint32_t offHostFlags,
+ void *pvHostAreaMapping,
+ uint32_t offVRAMHostArea,
+ uint32_t cbHostArea);
+
+/** @} */
+
+RT_C_DECLS_END
+
+#endif
+
diff --git a/src/HGSMIDefs.h b/src/HGSMIDefs.h
new file mode 100644
index 0000000..14e51b4
--- /dev/null
+++ b/src/HGSMIDefs.h
@@ -0,0 +1,118 @@
+/*
+ * Copyright (C) 2006-2017 Oracle Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+
+#ifndef ___VBox_Graphics_HGSMIDefs_h
+#define ___VBox_Graphics_HGSMIDefs_h
+
+#include "VBoxVideoIPRT.h"
+
+/* HGSMI uses 32 bit offsets and sizes. */
+typedef uint32_t HGSMISIZE;
+typedef uint32_t HGSMIOFFSET;
+
+#define HGSMIOFFSET_VOID ((HGSMIOFFSET)~0)
+
+/* Describes a shared memory area buffer.
+ * Used for calculations with offsets and for buffers verification.
+ */
+typedef struct HGSMIAREA
+{
+ uint8_t *pu8Base; /* The starting address of the area. Corresponds to offset 'offBase'. */
+ HGSMIOFFSET offBase; /* The starting offset of the area. */
+ HGSMIOFFSET offLast; /* The last valid offset:
+ * offBase + cbArea - 1 - (sizeof(header) + sizeof(tail)).
+ */
+ HGSMISIZE cbArea; /* Size of the area. */
+} HGSMIAREA;
+
+
+/* The buffer description flags. */
+#define HGSMI_BUFFER_HEADER_F_SEQ_MASK 0x03 /* Buffer sequence type mask. */
+#define HGSMI_BUFFER_HEADER_F_SEQ_SINGLE 0x00 /* Single buffer, not a part of a sequence. */
+#define HGSMI_BUFFER_HEADER_F_SEQ_START 0x01 /* The first buffer in a sequence. */
+#define HGSMI_BUFFER_HEADER_F_SEQ_CONTINUE 0x02 /* A middle buffer in a sequence. */
+#define HGSMI_BUFFER_HEADER_F_SEQ_END 0x03 /* The last buffer in a sequence. */
+
+
+#pragma pack(1) /** @todo not necessary. use AssertCompileSize instead. */
+/* 16 bytes buffer header. */
+typedef struct HGSMIBUFFERHEADER
+{
+ uint32_t u32DataSize; /* Size of data that follows the header. */
+
+ uint8_t u8Flags; /* The buffer description: HGSMI_BUFFER_HEADER_F_* */
+
+ uint8_t u8Channel; /* The channel the data must be routed to. */
+ uint16_t u16ChannelInfo; /* Opaque to the HGSMI, used by the channel. */
+
+ union {
+ uint8_t au8Union[8]; /* Opaque placeholder to make the union 8 bytes. */
+
+ struct
+ { /* HGSMI_BUFFER_HEADER_F_SEQ_SINGLE */
+ uint32_t u32Reserved1; /* A reserved field, initialize to 0. */
+ uint32_t u32Reserved2; /* A reserved field, initialize to 0. */
+ } Buffer;
+
+ struct
+ { /* HGSMI_BUFFER_HEADER_F_SEQ_START */
+ uint32_t u32SequenceNumber; /* The sequence number, the same for all buffers in the sequence. */
+ uint32_t u32SequenceSize; /* The total size of the sequence. */
+ } SequenceStart;
+
+ struct
+ { /* HGSMI_BUFFER_HEADER_F_SEQ_CONTINUE and HGSMI_BUFFER_HEADER_F_SEQ_END */
+ uint32_t u32SequenceNumber; /* The sequence number, the same for all buffers in the sequence. */
+ uint32_t u32SequenceOffset; /* Data offset in the entire sequence. */
+ } SequenceContinue;
+ } u;
+} HGSMIBUFFERHEADER;
+
+/* 8 bytes buffer tail. */
+typedef struct HGSMIBUFFERTAIL
+{
+ uint32_t u32Reserved; /* Reserved, must be initialized to 0. */
+ uint32_t u32Checksum; /* Verifyer for the buffer header and offset and for first 4 bytes of the tail. */
+} HGSMIBUFFERTAIL;
+#pragma pack()
+
+AssertCompileSize(HGSMIBUFFERHEADER, 16);
+AssertCompileSize(HGSMIBUFFERTAIL, 8);
+
+/* The size of the array of channels. Array indexes are uint8_t. Note: the value must not be changed. */
+#define HGSMI_NUMBER_OF_CHANNELS 0x100
+
+typedef struct HGSMIENV
+{
+ /* Environment context pointer. */
+ void *pvEnv;
+
+ /* Allocate system memory. */
+ DECLCALLBACKMEMBER(void *, pfnAlloc)(void *pvEnv, HGSMISIZE cb);
+
+ /* Free system memory. */
+ DECLCALLBACKMEMBER(void, pfnFree)(void *pvEnv, void *pv);
+} HGSMIENV;
+
+#endif /* !___VBox_Graphics_HGSMIDefs_h */
+
diff --git a/src/HGSMIMemAlloc.h b/src/HGSMIMemAlloc.h
new file mode 100644
index 0000000..fc324ce
--- /dev/null
+++ b/src/HGSMIMemAlloc.h
@@ -0,0 +1,56 @@
+/* $Id: HGSMIMemAlloc.h 118341 2017-10-12 14:07:17Z michael $ */
+/*
+ * Copyright (C) 2017 Oracle Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM,
+ * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+ * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+ * USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+
+/* In builds inside of the VirtualBox source tree we override the default
+ * HGSMIMemAlloc.h using -include, therefore this define must match the one
+ * there. */
+#ifndef ___VBox_Graphics_HGSMIMemAlloc_h
+#define ___VBox_Graphics_HGSMIMemAlloc_h
+
+#include "HGSMIDefs.h"
+#include "VBoxVideoIPRT.h"
+
+#define HGSMI_MA_DESC_ORDER_BASE UINT32_C(5)
+
+#define HGSMI_MA_BLOCK_SIZE_MIN (UINT32_C(1) << (HGSMI_MA_DESC_ORDER_BASE + 0))
+
+typedef struct HGSMIMADATA
+{
+ HGSMIAREA area;
+ bool fAllocated;
+} HGSMIMADATA;
+
+RT_C_DECLS_BEGIN
+
+int HGSMIMAInit(HGSMIMADATA *pMA, const HGSMIAREA *pArea,
+ HGSMIOFFSET *paDescriptors, uint32_t cDescriptors, HGSMISIZE cbMaxBlock,
+ const HGSMIENV *pEnv);
+void HGSMIMAUninit(HGSMIMADATA *pMA);
+
+void *HGSMIMAAlloc(HGSMIMADATA *pMA, HGSMISIZE cb);
+void HGSMIMAFree(HGSMIMADATA *pMA, void *pv);
+
+RT_C_DECLS_END
+
+#endif /* !___VBox_Graphics_HGSMIMemAlloc_h */
diff --git a/src/Makefile.am b/src/Makefile.am
new file mode 100644
index 0000000..fe691a6
--- /dev/null
+++ b/src/Makefile.am
@@ -0,0 +1,68 @@
+# Copyright 2005 Adam Jackson.
+# Copyright 2017 Oracle Corporation
+#
+# Permission is hereby granted, free of charge, to any person obtaining a
+# copy of this software and associated documentation files (the "Software"),
+# to deal in the Software without restriction, including without limitation
+# on the rights to use, copy, modify, merge, publish, distribute, sub
+# license, and/or sell copies of the Software, and to permit persons to whom
+# the Software is furnished to do so, subject to the following conditions:
+#
+# The above copyright notice and this permission notice (including the next
+# paragraph) shall be included in all copies or substantial portions of the
+# Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
+# THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM,
+# DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+# OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+# USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+
+# this is obnoxious:
+# -module lets us name the module exactly how we want
+# -avoid-version prevents gratuitous .0.0.0 version numbers on the end
+# _ladir passes a dummy rpath to libtool so the thing will actually link
+# TODO: -nostdlib/-Bstatic/-lgcc platform magic, not installing the .a, etc.
+
+AM_CFLAGS = $(XORG_CFLAGS) $(PCIACCESS_CFLAGS) \
+ -DXORG_7X \
+ -DIN_RING3 \
+ -DPCIACCESS \
+ -DVBOXVIDEO_13 \
+ -include xorg-server.h
+
+vboxvideo_drv_la_LTLIBRARIES = vboxvideo_drv.la
+vboxvideo_drv_la_LDFLAGS = -module -avoid-version
+vboxvideo_drv_ladir = @moduledir@/drivers
+
+vboxvideo_drv_la_SOURCES = \
+ edid.c \
+ getmode.c \
+ helpers.c \
+ HGSMIBase.c \
+ HGSMIBase.h \
+ HGSMIBuffers.c \
+ HGSMIChannels.h \
+ HGSMIChSetup.h \
+ HGSMICommon.c \
+ HGSMIContext.h \
+ HGSMIDefs.h \
+ HGSMI.h \
+ hgsmimemalloc.c \
+ HGSMIMemAlloc.h \
+ Modesetting.c \
+ pointer.c \
+ setmode.c \
+ vboxvideo.c \
+ VBoxVideoErr.h \
+ VBoxVideoGuest.h \
+ vboxvideo.h \
+ VBoxVideo.h \
+ VBoxVideoIPRT.h \
+ VBoxVideoVBE.h \
+ VBVABase.c \
+ vbva.c \
+ version-generated.h
diff --git a/src/Modesetting.c b/src/Modesetting.c
new file mode 100644
index 0000000..6da53e2
--- /dev/null
+++ b/src/Modesetting.c
@@ -0,0 +1,386 @@
+/*
+ * Copyright (C) 2006-2017 Oracle Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#include <VBoxVideoGuest.h>
+#include <VBoxVideoVBE.h>
+#include <HGSMIChannels.h>
+
+#ifndef VBOX_GUESTR3XF86MOD
+# include <VBoxVideoIPRT.h>
+#endif
+
+/**
+ * Gets the count of virtual monitors attached to the guest via an HGSMI
+ * command
+ *
+ * @returns the right count on success or 1 on failure.
+ * @param pCtx the context containing the heap to use
+ */
+DECLHIDDEN(uint32_t) VBoxHGSMIGetMonitorCount(PHGSMIGUESTCOMMANDCONTEXT pCtx)
+{
+ /* Query the configured number of displays. */
+ uint32_t cDisplays = 0;
+ VBoxQueryConfHGSMI(pCtx, VBOX_VBVA_CONF32_MONITOR_COUNT, &cDisplays);
+ // LogFunc(("cDisplays = %d\n", cDisplays));
+ if (cDisplays == 0 || cDisplays > VBOX_VIDEO_MAX_SCREENS)
+ /* Host reported some bad value. Continue in the 1 screen mode. */
+ cDisplays = 1;
+ return cDisplays;
+}
+
+
+/**
+ * Returns the size of the video RAM in bytes.
+ *
+ * @returns the size
+ */
+DECLHIDDEN(uint32_t) VBoxVideoGetVRAMSize(void)
+{
+ /** @note A 32bit read on this port returns the VRAM size. */
+ return VBVO_PORT_READ_U32(VBE_DISPI_IOPORT_DATA);
+}
+
+
+/**
+ * Check whether this hardware allows the display width to have non-multiple-
+ * of-eight values.
+ *
+ * @returns true if any width is allowed, false otherwise.
+ */
+DECLHIDDEN(bool) VBoxVideoAnyWidthAllowed(void)
+{
+ unsigned DispiId;
+ VBVO_PORT_WRITE_U16(VBE_DISPI_IOPORT_INDEX, VBE_DISPI_INDEX_ID);
+ VBVO_PORT_WRITE_U16(VBE_DISPI_IOPORT_DATA, VBE_DISPI_ID_ANYX);
+ DispiId = VBVO_PORT_READ_U16(VBE_DISPI_IOPORT_DATA);
+ return (DispiId == VBE_DISPI_ID_ANYX);
+}
+
+
+/**
+ * Tell the host about how VRAM is divided up between each screen via an HGSMI
+ * command. It is acceptable to specifiy identical data for each screen if
+ * they share a single framebuffer.
+ *
+ * @returns iprt status code, either VERR_NO_MEMORY or the status returned by
+ * @a pfnFill
+ * @todo What was I thinking of with that callback function? It
+ * would be much simpler to just pass in a structure in normal
+ * memory and copy it.
+ * @param pCtx the context containing the heap to use
+ * @param u32Count the number of screens we are activating
+ * @param pfnFill a callback which initialises the VBVAINFOVIEW structures
+ * for all screens
+ * @param pvData context data for @a pfnFill
+ */
+DECLHIDDEN(int) VBoxHGSMISendViewInfo(PHGSMIGUESTCOMMANDCONTEXT pCtx,
+ uint32_t u32Count,
+ PFNHGSMIFILLVIEWINFO pfnFill,
+ void *pvData)
+{
+ int rc;
+ /* Issue the screen info command. */
+ void *p = VBoxHGSMIBufferAlloc(pCtx, sizeof(VBVAINFOVIEW) * u32Count,
+ HGSMI_CH_VBVA, VBVA_INFO_VIEW);
+ if (p)
+ {
+ VBVAINFOVIEW *pInfo = (VBVAINFOVIEW *)p;
+ rc = pfnFill(pvData, pInfo, u32Count);
+ if (RT_SUCCESS(rc))
+ VBoxHGSMIBufferSubmit (pCtx, p);
+ VBoxHGSMIBufferFree(pCtx, p);
+ }
+ else
+ rc = VERR_NO_MEMORY;
+ return rc;
+}
+
+
+/**
+ * Set a video mode using port registers. This must be done for the first
+ * screen before every HGSMI modeset and also works when HGSM is not enabled.
+ * @param cWidth the mode width
+ * @param cHeight the mode height
+ * @param cVirtWidth the mode pitch
+ * @param cBPP the colour depth of the mode
+ * @param fFlags flags for the mode. These will be or-ed with the
+ * default _ENABLED flag, so unless you are restoring
+ * a saved mode or have special requirements you can pass
+ * zero here.
+ * @param cx the horizontal panning offset
+ * @param cy the vertical panning offset
+ */
+DECLHIDDEN(void) VBoxVideoSetModeRegisters(uint16_t cWidth, uint16_t cHeight,
+ uint16_t cVirtWidth, uint16_t cBPP,
+ uint16_t fFlags, uint16_t cx,
+ uint16_t cy)
+{
+ /* set the mode characteristics */
+ VBVO_PORT_WRITE_U16(VBE_DISPI_IOPORT_INDEX, VBE_DISPI_INDEX_XRES);
+ VBVO_PORT_WRITE_U16(VBE_DISPI_IOPORT_DATA, cWidth);
+ VBVO_PORT_WRITE_U16(VBE_DISPI_IOPORT_INDEX, VBE_DISPI_INDEX_YRES);
+ VBVO_PORT_WRITE_U16(VBE_DISPI_IOPORT_DATA, cHeight);
+ VBVO_PORT_WRITE_U16(VBE_DISPI_IOPORT_INDEX,
+ VBE_DISPI_INDEX_VIRT_WIDTH);
+ VBVO_PORT_WRITE_U16(VBE_DISPI_IOPORT_DATA, cVirtWidth);
+ VBVO_PORT_WRITE_U16(VBE_DISPI_IOPORT_INDEX, VBE_DISPI_INDEX_BPP);
+ VBVO_PORT_WRITE_U16(VBE_DISPI_IOPORT_DATA, cBPP);
+ /* enable the mode */
+ VBVO_PORT_WRITE_U16(VBE_DISPI_IOPORT_INDEX,
+ VBE_DISPI_INDEX_ENABLE);
+ VBVO_PORT_WRITE_U16(VBE_DISPI_IOPORT_DATA,
+ fFlags | VBE_DISPI_ENABLED);
+ /* Panning registers */
+ VBVO_PORT_WRITE_U16(VBE_DISPI_IOPORT_INDEX,
+ VBE_DISPI_INDEX_X_OFFSET);
+ VBVO_PORT_WRITE_U16(VBE_DISPI_IOPORT_DATA, cx);
+ VBVO_PORT_WRITE_U16(VBE_DISPI_IOPORT_INDEX,
+ VBE_DISPI_INDEX_Y_OFFSET);
+ VBVO_PORT_WRITE_U16(VBE_DISPI_IOPORT_DATA, cy);
+ /** @todo read from the port to see if the mode switch was successful */
+}
+
+
+/**
+ * Get the video mode for the first screen using the port registers. All
+ * parameters are optional
+ * @returns true if the VBE mode returned is active, false if we are in VGA
+ * mode
+ * @note If anyone else needs additional register values just extend the
+ * function with additional parameters and fix any existing callers.
+ * @param pcWidth where to store the mode width
+ * @param pcHeight where to store the mode height
+ * @param pcVirtWidth where to store the mode pitch
+ * @param pcBPP where to store the colour depth of the mode
+ * @param pfFlags where to store the flags for the mode
+ */
+DECLHIDDEN(bool) VBoxVideoGetModeRegisters(uint16_t *pcWidth, uint16_t *pcHeight,
+ uint16_t *pcVirtWidth, uint16_t *pcBPP,
+ uint16_t *pfFlags)
+{
+ uint16_t fFlags;
+
+ VBVO_PORT_WRITE_U16(VBE_DISPI_IOPORT_INDEX,
+ VBE_DISPI_INDEX_ENABLE);
+ fFlags = VBVO_PORT_READ_U16(VBE_DISPI_IOPORT_DATA);
+ if (pcWidth)
+ {
+ VBVO_PORT_WRITE_U16(VBE_DISPI_IOPORT_INDEX,
+ VBE_DISPI_INDEX_XRES);
+ *pcWidth = VBVO_PORT_READ_U16(VBE_DISPI_IOPORT_DATA);
+ }
+ if (pcHeight)
+ {
+ VBVO_PORT_WRITE_U16(VBE_DISPI_IOPORT_INDEX,
+ VBE_DISPI_INDEX_YRES);
+ *pcHeight = VBVO_PORT_READ_U16(VBE_DISPI_IOPORT_DATA);
+ }
+ if (pcVirtWidth)
+ {
+ VBVO_PORT_WRITE_U16(VBE_DISPI_IOPORT_INDEX,
+ VBE_DISPI_INDEX_VIRT_WIDTH);
+ *pcVirtWidth = VBVO_PORT_READ_U16(VBE_DISPI_IOPORT_DATA);
+ }
+ if (pcBPP)
+ {
+ VBVO_PORT_WRITE_U16(VBE_DISPI_IOPORT_INDEX,
+ VBE_DISPI_INDEX_BPP);
+ *pcBPP = VBVO_PORT_READ_U16(VBE_DISPI_IOPORT_DATA);
+ }
+ if (pfFlags)
+ *pfFlags = fFlags;
+ return !!(fFlags & VBE_DISPI_ENABLED);
+}
+
+
+/**
+ * Disable our extended graphics mode and go back to VGA mode.
+ */
+DECLHIDDEN(void) VBoxVideoDisableVBE(void)
+{
+ VBVO_PORT_WRITE_U16(VBE_DISPI_IOPORT_INDEX,
+ VBE_DISPI_INDEX_ENABLE);
+ VBVO_PORT_WRITE_U16(VBE_DISPI_IOPORT_DATA, 0);
+}
+
+
+/**
+ * Set a video mode via an HGSMI request. The views must have been
+ * initialised first using @a VBoxHGSMISendViewInfo and if the mode is being
+ * set on the first display then it must be set first using registers.
+ * @param pCtx The context containing the heap to use.
+ * @param cDisplay the screen number
+ * @param cOriginX the horizontal displacement relative to the first screen
+ * @param cOriginY the vertical displacement relative to the first screen
+ * @param offStart the offset of the visible area of the framebuffer
+ * relative to the framebuffer start
+ * @param cbPitch the offset in bytes between the starts of two adjecent
+ * scan lines in video RAM
+ * @param cWidth the mode width
+ * @param cHeight the mode height
+ * @param cBPP the colour depth of the mode
+ * @param fFlags flags
+ */
+DECLHIDDEN(void) VBoxHGSMIProcessDisplayInfo(PHGSMIGUESTCOMMANDCONTEXT pCtx,
+ uint32_t cDisplay,
+ int32_t cOriginX,
+ int32_t cOriginY,
+ uint32_t offStart,
+ uint32_t cbPitch,
+ uint32_t cWidth,
+ uint32_t cHeight,
+ uint16_t cBPP,
+ uint16_t fFlags)
+{
+ /* Issue the screen info command. */
+ void *p = VBoxHGSMIBufferAlloc(pCtx,
+ sizeof (VBVAINFOSCREEN),
+ HGSMI_CH_VBVA,
+ VBVA_INFO_SCREEN);
+ if (!p)
+ {
+ // LogFunc(("HGSMIHeapAlloc failed\n"));
+ }
+ else
+ {
+ VBVAINFOSCREEN *pScreen = (VBVAINFOSCREEN *)p;
+
+ pScreen->u32ViewIndex = cDisplay;
+ pScreen->i32OriginX = cOriginX;
+ pScreen->i32OriginY = cOriginY;
+ pScreen->u32StartOffset = offStart;
+ pScreen->u32LineSize = cbPitch;
+ pScreen->u32Width = cWidth;
+ pScreen->u32Height = cHeight;
+ pScreen->u16BitsPerPixel = cBPP;
+ pScreen->u16Flags = fFlags;
+
+ VBoxHGSMIBufferSubmit(pCtx, p);
+
+ VBoxHGSMIBufferFree(pCtx, p);
+ }
+}
+
+
+/** Report the rectangle relative to which absolute pointer events should be
+ * expressed. This information remains valid until the next VBVA resize event
+ * for any screen, at which time it is reset to the bounding rectangle of all
+ * virtual screens.
+ * @param pCtx The context containing the heap to use.
+ * @param cOriginX Upper left X co-ordinate relative to the first screen.
+ * @param cOriginY Upper left Y co-ordinate relative to the first screen.
+ * @param cWidth Rectangle width.
+ * @param cHeight Rectangle height.
+ * @returns iprt status code.
+ * @returns VERR_NO_MEMORY HGSMI heap allocation failed.
+ */
+DECLHIDDEN(int) VBoxHGSMIUpdateInputMapping(PHGSMIGUESTCOMMANDCONTEXT pCtx, int32_t cOriginX, int32_t cOriginY,
+ uint32_t cWidth, uint32_t cHeight)
+{
+ int rc = VINF_SUCCESS;
+ VBVAREPORTINPUTMAPPING *p;
+ // Log(("%s: cOriginX=%d, cOriginY=%d, cWidth=%u, cHeight=%u\n", __PRETTY_FUNCTION__, (int)cOriginX, (int)cOriginX,
+ // (unsigned)cWidth, (unsigned)cHeight));
+
+ /* Allocate the IO buffer. */
+ p = (VBVAREPORTINPUTMAPPING *)VBoxHGSMIBufferAlloc(pCtx, sizeof(VBVAREPORTINPUTMAPPING), HGSMI_CH_VBVA,
+ VBVA_REPORT_INPUT_MAPPING);
+ if (p)
+ {
+ /* Prepare data to be sent to the host. */
+ p->x = cOriginX;
+ p->y = cOriginY;
+ p->cx = cWidth;
+ p->cy = cHeight;
+ rc = VBoxHGSMIBufferSubmit(pCtx, p);
+ /* Free the IO buffer. */
+ VBoxHGSMIBufferFree(pCtx, p);
+ }
+ else
+ rc = VERR_NO_MEMORY;
+ // LogFunc(("rc = %d\n", rc));
+ return rc;
+}
+
+
+/**
+ * Get most recent video mode hints.
+ * @param pCtx the context containing the heap to use
+ * @param cScreens the number of screens to query hints for, starting at 0.
+ * @param paHints array of VBVAMODEHINT structures for receiving the hints.
+ * @returns iprt status code
+ * @returns VERR_NO_MEMORY HGSMI heap allocation failed.
+ * @returns VERR_NOT_SUPPORTED Host does not support this command.
+ */
+DECLHIDDEN(int) VBoxHGSMIGetModeHints(PHGSMIGUESTCOMMANDCONTEXT pCtx,
+ unsigned cScreens, VBVAMODEHINT *paHints)
+{
+ int rc;
+ void *p;
+
+ AssertPtr(paHints);
+ if (!paHints)
+ return VERR_INVALID_POINTER;
+
+ p = VBoxHGSMIBufferAlloc(pCtx, sizeof(VBVAQUERYMODEHINTS)
+ + cScreens * sizeof(VBVAMODEHINT),
+ HGSMI_CH_VBVA, VBVA_QUERY_MODE_HINTS);
+ if (!p)
+ {
+ // LogFunc(("HGSMIHeapAlloc failed\n"));
+ return VERR_NO_MEMORY;
+ }
+ else
+ {
+ VBVAQUERYMODEHINTS *pQuery = (VBVAQUERYMODEHINTS *)p;
+
+ pQuery->cHintsQueried = cScreens;
+ pQuery->cbHintStructureGuest = sizeof(VBVAMODEHINT);
+ pQuery->rc = VERR_NOT_SUPPORTED;
+
+ VBoxHGSMIBufferSubmit(pCtx, p);
+ rc = pQuery->rc;
+ if (RT_SUCCESS(rc))
+ memcpy(paHints, ((uint8_t *)p) + sizeof(VBVAQUERYMODEHINTS),
+ cScreens * sizeof(VBVAMODEHINT));
+
+ VBoxHGSMIBufferFree(pCtx, p);
+ }
+ return rc;
+}
+
+
+/**
+ * Query the supported flags in VBVAINFOSCREEN::u16Flags.
+ *
+ * @returns The mask of VBVA_SCREEN_F_* flags or 0 if host does not support the request.
+ * @param pCtx the context containing the heap to use
+ */
+DECLHIDDEN(uint16_t) VBoxHGSMIGetScreenFlags(PHGSMIGUESTCOMMANDCONTEXT pCtx)
+{
+ uint32_t u32Flags = 0;
+ int rc = VBoxQueryConfHGSMI(pCtx, VBOX_VBVA_CONF32_SCREEN_FLAGS, &u32Flags);
+ // LogFunc(("u32Flags = 0x%x rc %Rrc\n", u32Flags, rc));
+ if (RT_FAILURE(rc) || u32Flags > UINT16_MAX)
+ u32Flags = 0;
+ return (uint16_t)u32Flags;
+}
diff --git a/src/README.testing b/src/README.testing
new file mode 100644
index 0000000..dc441c1
--- /dev/null
+++ b/src/README.testing
@@ -0,0 +1,34 @@
+This file contains some notes about things to try out to give the X.Org video
+driver a reasonably thorough test. We will add cases of things which have been
+known to fail in the past to this file as we discover them.
+
+ * Test XFree86 guests (CentOS 3), early X.Org (CentOS 5) and recent
+ (CentOS 6 and 7, current Ubuntu/Fedora). Test Solaris guests (10 and 11?).
+ * Dynamic resizing should work, on CentOS 6 and later Linux guests it should
+ work without VBoxClient running.
+ * Disabling and enabling virtual screens (VBoxManage in 4.3).
+ * Dynamic resizing with one of more virtual screens disabled.
+ * Test switching to virtual terminals and back from windowed, full screen and
+ seamless modes (seamless currently only works properly with VBoxClient
+ running).
+ * Test switching directly between normal, full-screen, seamless and scaled
+ modes.
+ * execute "xprop -root | grep VBOX" after resizing a screen: VBOX_SIZE_HINTS
+ should be set, and VBOX_SIZE_HINTS_MISMATCH should equal 0 on CentOS 6 and
+ later (4.4 and later).
+ * Test re-ordering the virtual screen using the native guest operating system
+ tools and make sure that mouse integration still works as expected.
+ * Test disabling and re-enabling guest screens with the native system tools.
+ * Try disabling and re-enabling mouse integration and check that capturing
+ works with multiple guest screens.
+ * Shutting down and re-starting a virtual machine should restore the last size
+ for all monitors (note: currently only after log-in). Full shut-down, not
+ a reboot.
+ * Test power management by disabling guest screens ("xrandr --output VGA-n
+ --off") and re-enabling them ("xrandr --output VGA-n --preferred --pos XxY")
+ where X and Y are the position of the screen before disabling it.
+ * Test sending video mode hints with screen position information via
+ VBoxManage. The screen position is a hint only. The approximate position
+ should be preserved after a shut down and re-start of the guest.
+ * Test re-starting the X server after resizing all guest windows. The server
+ should not crash.
diff --git a/src/VBVABase.c b/src/VBVABase.c
new file mode 100644
index 0000000..8f1d545
--- /dev/null
+++ b/src/VBVABase.c
@@ -0,0 +1,390 @@
+/*
+ * Copyright (C) 2006-2017 Oracle Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#include <VBoxVideoGuest.h>
+#include <VBoxVideoIPRT.h>
+#include <HGSMIChannels.h>
+
+/*
+ * There is a hardware ring buffer in the graphics device video RAM, formerly
+ * in the VBox VMMDev PCI memory space.
+ * All graphics commands go there serialized by VBoxVBVABufferBeginUpdate.
+ * and vboxHwBufferEndUpdate.
+ *
+ * off32Free is writing position. off32Data is reading position.
+ * off32Free == off32Data means buffer is empty.
+ * There must be always gap between off32Data and off32Free when data
+ * are in the buffer.
+ * Guest only changes off32Free, host changes off32Data.
+ */
+
+/* Forward declarations of internal functions. */
+static void vboxHwBufferFlush(PHGSMIGUESTCOMMANDCONTEXT pCtx);
+static void vboxHwBufferPlaceDataAt(PVBVABUFFERCONTEXT pCtx, const void *p,
+ uint32_t cb, uint32_t offset);
+static bool vboxHwBufferWrite(PVBVABUFFERCONTEXT pCtx,
+ PHGSMIGUESTCOMMANDCONTEXT pHGSMICtx,
+ const void *p, uint32_t cb);
+
+
+static bool vboxVBVAInformHost(PVBVABUFFERCONTEXT pCtx,
+ PHGSMIGUESTCOMMANDCONTEXT pHGSMICtx,
+ int32_t cScreen, bool bEnable)
+{
+ bool bRc = false;
+
+#if 0 /* All callers check this */
+ if (ppdev->bHGSMISupported)
+#endif
+ {
+ void *p = VBoxHGSMIBufferAlloc(pHGSMICtx,
+ sizeof (VBVAENABLE_EX),
+ HGSMI_CH_VBVA,
+ VBVA_ENABLE);
+ if (!p)
+ {
+ // LogFunc(("HGSMIHeapAlloc failed\n"));
+ }
+ else
+ {
+ VBVAENABLE_EX *pEnable = (VBVAENABLE_EX *)p;
+
+ pEnable->Base.u32Flags = bEnable? VBVA_F_ENABLE: VBVA_F_DISABLE;
+ pEnable->Base.u32Offset = pCtx->offVRAMBuffer;
+ pEnable->Base.i32Result = VERR_NOT_SUPPORTED;
+ if (cScreen >= 0)
+ {
+ pEnable->Base.u32Flags |= VBVA_F_EXTENDED | VBVA_F_ABSOFFSET;
+ pEnable->u32ScreenId = cScreen;
+ }
+
+ VBoxHGSMIBufferSubmit(pHGSMICtx, p);
+
+ if (bEnable)
+ {
+ bRc = RT_SUCCESS(pEnable->Base.i32Result);
+ }
+ else
+ {
+ bRc = true;
+ }
+
+ VBoxHGSMIBufferFree(pHGSMICtx, p);
+ }
+ }
+
+ return bRc;
+}
+
+/*
+ * Public hardware buffer methods.
+ */
+DECLHIDDEN(bool) VBoxVBVAEnable(PVBVABUFFERCONTEXT pCtx,
+ PHGSMIGUESTCOMMANDCONTEXT pHGSMICtx,
+ VBVABUFFER *pVBVA, int32_t cScreen)
+{
+ bool bRc = false;
+
+ // LogFlowFunc(("pVBVA %p\n", pVBVA));
+
+#if 0 /* All callers check this */
+ if (ppdev->bHGSMISupported)
+#endif
+ {
+ // LogFunc(("pVBVA %p vbva off 0x%x\n", pVBVA, pCtx->offVRAMBuffer));
+
+ pVBVA->hostFlags.u32HostEvents = 0;
+ pVBVA->hostFlags.u32SupportedOrders = 0;
+ pVBVA->off32Data = 0;
+ pVBVA->off32Free = 0;
+ memset(pVBVA->aRecords, 0, sizeof (pVBVA->aRecords));
+ pVBVA->indexRecordFirst = 0;
+ pVBVA->indexRecordFree = 0;
+ pVBVA->cbPartialWriteThreshold = 256;
+ pVBVA->cbData = pCtx->cbBuffer - sizeof (VBVABUFFER) + sizeof (pVBVA->au8Data);
+
+ pCtx->fHwBufferOverflow = false;
+ pCtx->pRecord = NULL;
+ pCtx->pVBVA = pVBVA;
+
+ bRc = vboxVBVAInformHost(pCtx, pHGSMICtx, cScreen, true);
+ }
+
+ if (!bRc)
+ {
+ VBoxVBVADisable(pCtx, pHGSMICtx, cScreen);
+ }
+
+ return bRc;
+}
+
+DECLHIDDEN(void) VBoxVBVADisable(PVBVABUFFERCONTEXT pCtx,
+ PHGSMIGUESTCOMMANDCONTEXT pHGSMICtx,
+ int32_t cScreen)
+{
+ // LogFlowFunc(("\n"));
+
+ pCtx->fHwBufferOverflow = false;
+ pCtx->pRecord = NULL;
+ pCtx->pVBVA = NULL;
+
+ vboxVBVAInformHost(pCtx, pHGSMICtx, cScreen, false);
+
+ return;
+}
+
+DECLHIDDEN(bool) VBoxVBVABufferBeginUpdate(PVBVABUFFERCONTEXT pCtx,
+ PHGSMIGUESTCOMMANDCONTEXT pHGSMICtx)
+{
+ bool bRc = false;
+
+ // LogFunc(("flags = 0x%08X\n", pCtx->pVBVA? pCtx->pVBVA->u32HostEvents: -1));
+
+ if ( pCtx->pVBVA
+ && (pCtx->pVBVA->hostFlags.u32HostEvents & VBVA_F_MODE_ENABLED))
+ {
+ uint32_t indexRecordNext;
+
+ Assert(!pCtx->fHwBufferOverflow);
+ Assert(pCtx->pRecord == NULL);
+
+ indexRecordNext = (pCtx->pVBVA->indexRecordFree + 1) % VBVA_MAX_RECORDS;
+
+ if (indexRecordNext == pCtx->pVBVA->indexRecordFirst)
+ {
+ /* All slots in the records queue are used. */
+ vboxHwBufferFlush (pHGSMICtx);
+ }
+
+ if (indexRecordNext == pCtx->pVBVA->indexRecordFirst)
+ {
+ /* Even after flush there is no place. Fail the request. */
+ // LogFunc(("no space in the queue of records!!! first %d, last %d\n",
+ // pCtx->pVBVA->indexRecordFirst, pCtx->pVBVA->indexRecordFree));
+ }
+ else
+ {
+ /* Initialize the record. */
+ VBVARECORD *pRecord = &pCtx->pVBVA->aRecords[pCtx->pVBVA->indexRecordFree];
+
+ pRecord->cbRecord = VBVA_F_RECORD_PARTIAL;
+
+ pCtx->pVBVA->indexRecordFree = indexRecordNext;
+
+ // LogFunc(("indexRecordNext = %d\n", indexRecordNext));
+
+ /* Remember which record we are using. */
+ pCtx->pRecord = pRecord;
+
+ bRc = true;
+ }
+ }
+
+ return bRc;
+}
+
+DECLHIDDEN(void) VBoxVBVABufferEndUpdate(PVBVABUFFERCONTEXT pCtx)
+{
+ VBVARECORD *pRecord;
+
+ // LogFunc(("\n"));
+
+ Assert(pCtx->pVBVA);
+
+ pRecord = pCtx->pRecord;
+ Assert(pRecord && (pRecord->cbRecord & VBVA_F_RECORD_PARTIAL));
+
+ /* Mark the record completed. */
+ pRecord->cbRecord &= ~VBVA_F_RECORD_PARTIAL;
+
+ pCtx->fHwBufferOverflow = false;
+ pCtx->pRecord = NULL;
+
+ return;
+}
+
+/*
+ * Private operations.
+ */
+static uint32_t vboxHwBufferAvail (const VBVABUFFER *pVBVA)
+{
+ int32_t i32Diff = pVBVA->off32Data - pVBVA->off32Free;
+
+ return i32Diff > 0? i32Diff: pVBVA->cbData + i32Diff;
+}
+
+static void vboxHwBufferFlush(PHGSMIGUESTCOMMANDCONTEXT pCtx)
+{
+ /* Issue the flush command. */
+ void *p = VBoxHGSMIBufferAlloc(pCtx,
+ sizeof (VBVAFLUSH),
+ HGSMI_CH_VBVA,
+ VBVA_FLUSH);
+ if (!p)
+ {
+ // LogFunc(("HGSMIHeapAlloc failed\n"));
+ }
+ else
+ {
+ VBVAFLUSH *pFlush = (VBVAFLUSH *)p;
+
+ pFlush->u32Reserved = 0;
+
+ VBoxHGSMIBufferSubmit(pCtx, p);
+
+ VBoxHGSMIBufferFree(pCtx, p);
+ }
+
+ return;
+}
+
+static void vboxHwBufferPlaceDataAt(PVBVABUFFERCONTEXT pCtx, const void *p,
+ uint32_t cb, uint32_t offset)
+{
+ VBVABUFFER *pVBVA = pCtx->pVBVA;
+ uint32_t u32BytesTillBoundary = pVBVA->cbData - offset;
+ uint8_t *dst = &pVBVA->au8Data[offset];
+ int32_t i32Diff = cb - u32BytesTillBoundary;
+
+ if (i32Diff <= 0)
+ {
+ /* Chunk will not cross buffer boundary. */
+ memcpy (dst, p, cb);
+ }
+ else
+ {
+ /* Chunk crosses buffer boundary. */
+ memcpy (dst, p, u32BytesTillBoundary);
+ memcpy (&pVBVA->au8Data[0], (uint8_t *)p + u32BytesTillBoundary, i32Diff);
+ }
+
+ return;
+}
+
+static bool vboxHwBufferWrite(PVBVABUFFERCONTEXT pCtx,
+ PHGSMIGUESTCOMMANDCONTEXT pHGSMICtx,
+ const void *p, uint32_t cb)
+{
+ VBVARECORD *pRecord;
+ uint32_t cbHwBufferAvail;
+
+ uint32_t cbWritten = 0;
+
+ VBVABUFFER *pVBVA = pCtx->pVBVA;
+ Assert(pVBVA);
+
+ if (!pVBVA || pCtx->fHwBufferOverflow)
+ {
+ return false;
+ }
+
+ Assert(pVBVA->indexRecordFirst != pVBVA->indexRecordFree);
+
+ pRecord = pCtx->pRecord;
+ Assert(pRecord && (pRecord->cbRecord & VBVA_F_RECORD_PARTIAL));
+
+ // LogFunc(("%d\n", cb));
+
+ cbHwBufferAvail = vboxHwBufferAvail (pVBVA);
+
+ while (cb > 0)
+ {
+ uint32_t cbChunk = cb;
+
+ // LogFunc(("pVBVA->off32Free %d, pRecord->cbRecord 0x%08X, cbHwBufferAvail %d, cb %d, cbWritten %d\n",
+ // pVBVA->off32Free, pRecord->cbRecord, cbHwBufferAvail, cb, cbWritten));
+
+ if (cbChunk >= cbHwBufferAvail)
+ {
+ // LogFunc(("1) avail %d, chunk %d\n", cbHwBufferAvail, cbChunk));
+
+ vboxHwBufferFlush (pHGSMICtx);
+
+ cbHwBufferAvail = vboxHwBufferAvail (pVBVA);
+
+ if (cbChunk >= cbHwBufferAvail)
+ {
+ // LogFunc(("no place for %d bytes. Only %d bytes available after flush. Going to partial writes.\n",
+ // cb, cbHwBufferAvail));
+
+ if (cbHwBufferAvail <= pVBVA->cbPartialWriteThreshold)
+ {
+ // LogFunc(("Buffer overflow!!!\n"));
+ pCtx->fHwBufferOverflow = true;
+ Assert(false);
+ return false;
+ }
+
+ cbChunk = cbHwBufferAvail - pVBVA->cbPartialWriteThreshold;
+ }
+ }
+
+ Assert(cbChunk <= cb);
+ Assert(cbChunk <= vboxHwBufferAvail (pVBVA));
+
+ vboxHwBufferPlaceDataAt (pCtx, (uint8_t *)p + cbWritten, cbChunk, pVBVA->off32Free);
+
+ pVBVA->off32Free = (pVBVA->off32Free + cbChunk) % pVBVA->cbData;
+ pRecord->cbRecord += cbChunk;
+ cbHwBufferAvail -= cbChunk;
+
+ cb -= cbChunk;
+ cbWritten += cbChunk;
+ }
+
+ return true;
+}
+
+/*
+ * Public writer to the hardware buffer.
+ */
+DECLHIDDEN(bool) VBoxVBVAWrite(PVBVABUFFERCONTEXT pCtx,
+ PHGSMIGUESTCOMMANDCONTEXT pHGSMICtx,
+ const void *pv, uint32_t cb)
+{
+ return vboxHwBufferWrite (pCtx, pHGSMICtx, pv, cb);
+}
+
+DECLHIDDEN(bool) VBoxVBVAOrderSupported(PVBVABUFFERCONTEXT pCtx, unsigned code)
+{
+ VBVABUFFER *pVBVA = pCtx->pVBVA;
+
+ if (!pVBVA)
+ {
+ return false;
+ }
+
+ if (pVBVA->hostFlags.u32SupportedOrders & (1 << code))
+ {
+ return true;
+ }
+
+ return false;
+}
+
+DECLHIDDEN(void) VBoxVBVASetupBufferContext(PVBVABUFFERCONTEXT pCtx,
+ uint32_t offVRAMBuffer,
+ uint32_t cbBuffer)
+{
+ pCtx->offVRAMBuffer = offVRAMBuffer;
+ pCtx->cbBuffer = cbBuffer;
+}
diff --git a/src/VBoxVideo.h b/src/VBoxVideo.h
new file mode 100644
index 0000000..2001246
--- /dev/null
+++ b/src/VBoxVideo.h
@@ -0,0 +1,2106 @@
+/** @file
+ * VirtualBox Video interface.
+ */
+
+/*
+ * Copyright (C) 2006-2016 Oracle Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM,
+ * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+ * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+ * USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ */
+
+#ifndef ___VBox_Graphics_VBoxVideo_h
+#define ___VBox_Graphics_VBoxVideo_h
+
+#include "VBoxVideoIPRT.h"
+
+/* this should be in sync with monitorCount <xsd:maxInclusive value="64"/> in src/VBox/Main/xml/VirtualBox-settings-common.xsd */
+#define VBOX_VIDEO_MAX_SCREENS 64
+
+/*
+ * The last 4096 bytes of the guest VRAM contains the generic info for all
+ * DualView chunks: sizes and offsets of chunks. This is filled by miniport.
+ *
+ * Last 4096 bytes of each chunk contain chunk specific data: framebuffer info,
+ * etc. This is used exclusively by the corresponding instance of a display driver.
+ *
+ * The VRAM layout:
+ * Last 4096 bytes - Adapter information area.
+ * 4096 bytes aligned miniport heap (value specified in the config rouded up).
+ * Slack - what left after dividing the VRAM.
+ * 4096 bytes aligned framebuffers:
+ * last 4096 bytes of each framebuffer is the display information area.
+ *
+ * The Virtual Graphics Adapter information in the guest VRAM is stored by the
+ * guest video driver using structures prepended by VBOXVIDEOINFOHDR.
+ *
+ * When the guest driver writes dword 0 to the VBE_DISPI_INDEX_VBOX_VIDEO
+ * the host starts to process the info. The first element at the start of
+ * the 4096 bytes region should be normally be a LINK that points to
+ * actual information chain. That way the guest driver can have some
+ * fixed layout of the information memory block and just rewrite
+ * the link to point to relevant memory chain.
+ *
+ * The processing stops at the END element.
+ *
+ * The host can access the memory only when the port IO is processed.
+ * All data that will be needed later must be copied from these 4096 bytes.
+ * But other VRAM can be used by host until the mode is disabled.
+ *
+ * The guest driver writes dword 0xffffffff to the VBE_DISPI_INDEX_VBOX_VIDEO
+ * to disable the mode.
+ *
+ * VBE_DISPI_INDEX_VBOX_VIDEO is used to read the configuration information
+ * from the host and issue commands to the host.
+ *
+ * The guest writes the VBE_DISPI_INDEX_VBOX_VIDEO index register, the the
+ * following operations with the VBE data register can be performed:
+ *
+ * Operation Result
+ * write 16 bit value NOP
+ * read 16 bit value count of monitors
+ * write 32 bit value sets the vbox command value and the command processed by the host
+ * read 32 bit value result of the last vbox command is returned
+ */
+
+#define VBOX_VIDEO_PRIMARY_SCREEN 0
+#define VBOX_VIDEO_NO_SCREEN ~0
+
+/**
+ * VBVA command header.
+ *
+ * @todo Where does this fit in?
+ */
+typedef struct VBVACMDHDR
+{
+ /** Coordinates of affected rectangle. */
+ int16_t x;
+ int16_t y;
+ uint16_t w;
+ uint16_t h;
+} VBVACMDHDR;
+AssertCompileSize(VBVACMDHDR, 8);
+
+/** @name VBVA ring defines.
+ *
+ * The VBVA ring buffer is suitable for transferring large (< 2GB) amount of
+ * data. For example big bitmaps which do not fit to the buffer.
+ *
+ * Guest starts writing to the buffer by initializing a record entry in the
+ * aRecords queue. VBVA_F_RECORD_PARTIAL indicates that the record is being
+ * written. As data is written to the ring buffer, the guest increases off32End
+ * for the record.
+ *
+ * The host reads the aRecords on flushes and processes all completed records.
+ * When host encounters situation when only a partial record presents and
+ * cbRecord & ~VBVA_F_RECORD_PARTIAL >= VBVA_RING_BUFFER_SIZE -
+ * VBVA_RING_BUFFER_THRESHOLD, the host fetched all record data and updates
+ * off32Head. After that on each flush the host continues fetching the data
+ * until the record is completed.
+ *
+ */
+#define VBVA_RING_BUFFER_SIZE (_4M - _1K)
+#define VBVA_RING_BUFFER_THRESHOLD (4 * _1K)
+
+#define VBVA_MAX_RECORDS (64)
+
+#define VBVA_F_MODE_ENABLED UINT32_C(0x00000001)
+#define VBVA_F_MODE_VRDP UINT32_C(0x00000002)
+#define VBVA_F_MODE_VRDP_RESET UINT32_C(0x00000004)
+#define VBVA_F_MODE_VRDP_ORDER_MASK UINT32_C(0x00000008)
+
+#define VBVA_F_STATE_PROCESSING UINT32_C(0x00010000)
+
+#define VBVA_F_RECORD_PARTIAL UINT32_C(0x80000000)
+
+/**
+ * VBVA record.
+ */
+typedef struct VBVARECORD
+{
+ /** The length of the record. Changed by guest. */
+ uint32_t cbRecord;
+} VBVARECORD;
+AssertCompileSize(VBVARECORD, 4);
+
+/* The size of the information. */
+/*
+ * The minimum HGSMI heap size is PAGE_SIZE (4096 bytes) and is a restriction of the
+ * runtime heapsimple API. Use minimum 2 pages here, because the info area also may
+ * contain other data (for example HGSMIHOSTFLAGS structure).
+ */
+#ifndef VBOX_XPDM_MINIPORT
+# define VBVA_ADAPTER_INFORMATION_SIZE (64*_1K)
+#else
+#define VBVA_ADAPTER_INFORMATION_SIZE (16*_1K)
+#define VBVA_DISPLAY_INFORMATION_SIZE (64*_1K)
+#endif
+#define VBVA_MIN_BUFFER_SIZE (64*_1K)
+
+
+/* The value for port IO to let the adapter to interpret the adapter memory. */
+#define VBOX_VIDEO_DISABLE_ADAPTER_MEMORY 0xFFFFFFFF
+
+/* The value for port IO to let the adapter to interpret the adapter memory. */
+#define VBOX_VIDEO_INTERPRET_ADAPTER_MEMORY 0x00000000
+
+/* The value for port IO to let the adapter to interpret the display memory.
+ * The display number is encoded in low 16 bits.
+ */
+#define VBOX_VIDEO_INTERPRET_DISPLAY_MEMORY_BASE 0x00010000
+
+
+/* The end of the information. */
+#define VBOX_VIDEO_INFO_TYPE_END 0
+/* Instructs the host to fetch the next VBOXVIDEOINFOHDR at the given offset of VRAM. */
+#define VBOX_VIDEO_INFO_TYPE_LINK 1
+/* Information about a display memory position. */
+#define VBOX_VIDEO_INFO_TYPE_DISPLAY 2
+/* Information about a screen. */
+#define VBOX_VIDEO_INFO_TYPE_SCREEN 3
+/* Information about host notifications for the driver. */
+#define VBOX_VIDEO_INFO_TYPE_HOST_EVENTS 4
+/* Information about non-volatile guest VRAM heap. */
+#define VBOX_VIDEO_INFO_TYPE_NV_HEAP 5
+/* VBVA enable/disable. */
+#define VBOX_VIDEO_INFO_TYPE_VBVA_STATUS 6
+/* VBVA flush. */
+#define VBOX_VIDEO_INFO_TYPE_VBVA_FLUSH 7
+/* Query configuration value. */
+#define VBOX_VIDEO_INFO_TYPE_QUERY_CONF32 8
+
+
+#pragma pack(1)
+typedef struct VBOXVIDEOINFOHDR
+{
+ uint8_t u8Type;
+ uint8_t u8Reserved;
+ uint16_t u16Length;
+} VBOXVIDEOINFOHDR;
+
+
+typedef struct VBOXVIDEOINFOLINK
+{
+ /* Relative offset in VRAM */
+ int32_t i32Offset;
+} VBOXVIDEOINFOLINK;
+
+
+/* Resides in adapter info memory. Describes a display VRAM chunk. */
+typedef struct VBOXVIDEOINFODISPLAY
+{
+ /* Index of the framebuffer assigned by guest. */
+ uint32_t u32Index;
+
+ /* Absolute offset in VRAM of the framebuffer to be displayed on the monitor. */
+ uint32_t u32Offset;
+
+ /* The size of the memory that can be used for the screen. */
+ uint32_t u32FramebufferSize;
+
+ /* The size of the memory that is used for the Display information.
+ * The information is at u32Offset + u32FramebufferSize
+ */
+ uint32_t u32InformationSize;
+
+} VBOXVIDEOINFODISPLAY;
+
+
+/* Resides in display info area, describes the current video mode. */
+#define VBOX_VIDEO_INFO_SCREEN_F_NONE 0x00
+#define VBOX_VIDEO_INFO_SCREEN_F_ACTIVE 0x01
+
+typedef struct VBOXVIDEOINFOSCREEN
+{
+ /* Physical X origin relative to the primary screen. */
+ int32_t xOrigin;
+
+ /* Physical Y origin relative to the primary screen. */
+ int32_t yOrigin;
+
+ /* The scan line size in bytes. */
+ uint32_t u32LineSize;
+
+ /* Width of the screen. */
+ uint16_t u16Width;
+
+ /* Height of the screen. */
+ uint16_t u16Height;
+
+ /* Color depth. */
+ uint8_t bitsPerPixel;
+
+ /* VBOX_VIDEO_INFO_SCREEN_F_* */
+ uint8_t u8Flags;
+} VBOXVIDEOINFOSCREEN;
+
+/* The guest initializes the structure to 0. The positions of the structure in the
+ * display info area must not be changed, host will update the structure. Guest checks
+ * the events and modifies the structure as a response to host.
+ */
+#define VBOX_VIDEO_INFO_HOST_EVENTS_F_NONE 0x00000000
+#define VBOX_VIDEO_INFO_HOST_EVENTS_F_VRDP_RESET 0x00000080
+
+typedef struct VBOXVIDEOINFOHOSTEVENTS
+{
+ /* Host events. */
+ uint32_t fu32Events;
+} VBOXVIDEOINFOHOSTEVENTS;
+
+/* Resides in adapter info memory. Describes the non-volatile VRAM heap. */
+typedef struct VBOXVIDEOINFONVHEAP
+{
+ /* Absolute offset in VRAM of the start of the heap. */
+ uint32_t u32HeapOffset;
+
+ /* The size of the heap. */
+ uint32_t u32HeapSize;
+
+} VBOXVIDEOINFONVHEAP;
+
+/* Display information area. */
+typedef struct VBOXVIDEOINFOVBVASTATUS
+{
+ /* Absolute offset in VRAM of the start of the VBVA QUEUE. 0 to disable VBVA. */
+ uint32_t u32QueueOffset;
+
+ /* The size of the VBVA QUEUE. 0 to disable VBVA. */
+ uint32_t u32QueueSize;
+
+} VBOXVIDEOINFOVBVASTATUS;
+
+typedef struct VBOXVIDEOINFOVBVAFLUSH
+{
+ uint32_t u32DataStart;
+
+ uint32_t u32DataEnd;
+
+} VBOXVIDEOINFOVBVAFLUSH;
+
+#define VBOX_VIDEO_QCI32_MONITOR_COUNT 0
+#define VBOX_VIDEO_QCI32_OFFSCREEN_HEAP_SIZE 1
+
+typedef struct VBOXVIDEOINFOQUERYCONF32
+{
+ uint32_t u32Index;
+
+ uint32_t u32Value;
+
+} VBOXVIDEOINFOQUERYCONF32;
+#pragma pack()
+
+#ifdef VBOX_WITH_VIDEOHWACCEL
+#pragma pack(1)
+
+#define VBOXVHWA_VERSION_MAJ 0
+#define VBOXVHWA_VERSION_MIN 0
+#define VBOXVHWA_VERSION_BLD 6
+#define VBOXVHWA_VERSION_RSV 0
+
+typedef enum
+{
+ VBOXVHWACMD_TYPE_SURF_CANCREATE = 1,
+ VBOXVHWACMD_TYPE_SURF_CREATE,
+ VBOXVHWACMD_TYPE_SURF_DESTROY,
+ VBOXVHWACMD_TYPE_SURF_LOCK,
+ VBOXVHWACMD_TYPE_SURF_UNLOCK,
+ VBOXVHWACMD_TYPE_SURF_BLT,
+ VBOXVHWACMD_TYPE_SURF_FLIP,
+ VBOXVHWACMD_TYPE_SURF_OVERLAY_UPDATE,
+ VBOXVHWACMD_TYPE_SURF_OVERLAY_SETPOSITION,
+ VBOXVHWACMD_TYPE_SURF_COLORKEY_SET,
+ VBOXVHWACMD_TYPE_QUERY_INFO1,
+ VBOXVHWACMD_TYPE_QUERY_INFO2,
+ VBOXVHWACMD_TYPE_ENABLE,
+ VBOXVHWACMD_TYPE_DISABLE,
+ VBOXVHWACMD_TYPE_HH_CONSTRUCT,
+ VBOXVHWACMD_TYPE_HH_RESET
+#ifdef VBOX_WITH_WDDM
+ , VBOXVHWACMD_TYPE_SURF_GETINFO
+ , VBOXVHWACMD_TYPE_SURF_COLORFILL
+#endif
+ , VBOXVHWACMD_TYPE_HH_DISABLE
+ , VBOXVHWACMD_TYPE_HH_ENABLE
+ , VBOXVHWACMD_TYPE_HH_SAVESTATE_SAVEBEGIN
+ , VBOXVHWACMD_TYPE_HH_SAVESTATE_SAVEEND
+ , VBOXVHWACMD_TYPE_HH_SAVESTATE_SAVEPERFORM
+ , VBOXVHWACMD_TYPE_HH_SAVESTATE_LOADPERFORM
+} VBOXVHWACMD_TYPE;
+
+/* the command processing was asynch, set by the host to indicate asynch command completion
+ * must not be cleared once set, the command completion is performed by issuing a host->guest completion command
+ * while keeping this flag unchanged */
+#define VBOXVHWACMD_FLAG_HG_ASYNCH 0x00010000
+/* asynch completion is performed by issuing the event */
+#define VBOXVHWACMD_FLAG_GH_ASYNCH_EVENT 0x00000001
+/* issue interrupt on asynch completion */
+#define VBOXVHWACMD_FLAG_GH_ASYNCH_IRQ 0x00000002
+/* guest does not do any op on completion of this command, the host may copy the command and indicate that it does not need the command anymore
+ * by setting the VBOXVHWACMD_FLAG_HG_ASYNCH_RETURNED flag */
+#define VBOXVHWACMD_FLAG_GH_ASYNCH_NOCOMPLETION 0x00000004
+/* the host has copied the VBOXVHWACMD_FLAG_GH_ASYNCH_NOCOMPLETION command and returned it to the guest */
+#define VBOXVHWACMD_FLAG_HG_ASYNCH_RETURNED 0x00020000
+/* this is the host->host cmd, i.e. a configuration command posted by the host to the framebuffer */
+#define VBOXVHWACMD_FLAG_HH_CMD 0x10000000
+
+typedef struct VBOXVHWACMD
+{
+ VBOXVHWACMD_TYPE enmCmd; /* command type */
+ volatile int32_t rc; /* command result */
+ int32_t iDisplay; /* display index */
+ volatile int32_t Flags; /* ored VBOXVHWACMD_FLAG_xxx values */
+ uint64_t GuestVBVAReserved1; /* field internally used by the guest VBVA cmd handling, must NOT be modified by clients */
+ uint64_t GuestVBVAReserved2; /* field internally used by the guest VBVA cmd handling, must NOT be modified by clients */
+ volatile uint32_t cRefs;
+ int32_t Reserved;
+ union
+ {
+ struct VBOXVHWACMD *pNext;
+ uint32_t offNext;
+ uint64_t Data; /* the body is 64-bit aligned */
+ } u;
+ char body[1];
+} VBOXVHWACMD;
+
+#define VBOXVHWACMD_HEADSIZE() (RT_OFFSETOF(VBOXVHWACMD, body))
+#define VBOXVHWACMD_SIZE_FROMBODYSIZE(_s) (VBOXVHWACMD_HEADSIZE() + (_s))
+#define VBOXVHWACMD_SIZE(_tCmd) (VBOXVHWACMD_SIZE_FROMBODYSIZE(sizeof(_tCmd)))
+typedef unsigned int VBOXVHWACMD_LENGTH;
+typedef uint64_t VBOXVHWA_SURFHANDLE;
+#define VBOXVHWA_SURFHANDLE_INVALID 0ULL
+#define VBOXVHWACMD_BODY(_p, _t) ((_t*)(_p)->body)
+#define VBOXVHWACMD_HEAD(_pb) ((VBOXVHWACMD*)((uint8_t *)(_pb) - RT_OFFSETOF(VBOXVHWACMD, body)))
+
+typedef struct VBOXVHWA_RECTL
+{
+ int32_t left;
+ int32_t top;
+ int32_t right;
+ int32_t bottom;
+} VBOXVHWA_RECTL;
+
+typedef struct VBOXVHWA_COLORKEY
+{
+ uint32_t low;
+ uint32_t high;
+} VBOXVHWA_COLORKEY;
+
+typedef struct VBOXVHWA_PIXELFORMAT
+{
+ uint32_t flags;
+ uint32_t fourCC;
+ union
+ {
+ uint32_t rgbBitCount;
+ uint32_t yuvBitCount;
+ } c;
+
+ union
+ {
+ uint32_t rgbRBitMask;
+ uint32_t yuvYBitMask;
+ } m1;
+
+ union
+ {
+ uint32_t rgbGBitMask;
+ uint32_t yuvUBitMask;
+ } m2;
+
+ union
+ {
+ uint32_t rgbBBitMask;
+ uint32_t yuvVBitMask;
+ } m3;
+
+ union
+ {
+ uint32_t rgbABitMask;
+ } m4;
+
+ uint32_t Reserved;
+} VBOXVHWA_PIXELFORMAT;
+
+typedef struct VBOXVHWA_SURFACEDESC
+{
+ uint32_t flags;
+ uint32_t height;
+ uint32_t width;
+ uint32_t pitch;
+ uint32_t sizeX;
+ uint32_t sizeY;
+ uint32_t cBackBuffers;
+ uint32_t Reserved;
+ VBOXVHWA_COLORKEY DstOverlayCK;
+ VBOXVHWA_COLORKEY DstBltCK;
+ VBOXVHWA_COLORKEY SrcOverlayCK;
+ VBOXVHWA_COLORKEY SrcBltCK;
+ VBOXVHWA_PIXELFORMAT PixelFormat;
+ uint32_t surfCaps;
+ uint32_t Reserved2;
+ VBOXVHWA_SURFHANDLE hSurf;
+ uint64_t offSurface;
+} VBOXVHWA_SURFACEDESC;
+
+typedef struct VBOXVHWA_BLTFX
+{
+ uint32_t flags;
+ uint32_t rop;
+ uint32_t rotationOp;
+ uint32_t rotation;
+ uint32_t fillColor;
+ uint32_t Reserved;
+ VBOXVHWA_COLORKEY DstCK;
+ VBOXVHWA_COLORKEY SrcCK;
+} VBOXVHWA_BLTFX;
+
+typedef struct VBOXVHWA_OVERLAYFX
+{
+ uint32_t flags;
+ uint32_t Reserved1;
+ uint32_t fxFlags;
+ uint32_t Reserved2;
+ VBOXVHWA_COLORKEY DstCK;
+ VBOXVHWA_COLORKEY SrcCK;
+} VBOXVHWA_OVERLAYFX;
+
+#define VBOXVHWA_CAPS_BLT 0x00000040
+#define VBOXVHWA_CAPS_BLTCOLORFILL 0x04000000
+#define VBOXVHWA_CAPS_BLTFOURCC 0x00000100
+#define VBOXVHWA_CAPS_BLTSTRETCH 0x00000200
+#define VBOXVHWA_CAPS_BLTQUEUE 0x00000080
+
+#define VBOXVHWA_CAPS_OVERLAY 0x00000800
+#define VBOXVHWA_CAPS_OVERLAYFOURCC 0x00002000
+#define VBOXVHWA_CAPS_OVERLAYSTRETCH 0x00004000
+#define VBOXVHWA_CAPS_OVERLAYCANTCLIP 0x00001000
+
+#define VBOXVHWA_CAPS_COLORKEY 0x00400000
+#define VBOXVHWA_CAPS_COLORKEYHWASSIST 0x01000000
+
+#define VBOXVHWA_SCAPS_BACKBUFFER 0x00000004
+#define VBOXVHWA_SCAPS_COMPLEX 0x00000008
+#define VBOXVHWA_SCAPS_FLIP 0x00000010
+#define VBOXVHWA_SCAPS_FRONTBUFFER 0x00000020
+#define VBOXVHWA_SCAPS_OFFSCREENPLAIN 0x00000040
+#define VBOXVHWA_SCAPS_OVERLAY 0x00000080
+#define VBOXVHWA_SCAPS_PRIMARYSURFACE 0x00000200
+#define VBOXVHWA_SCAPS_SYSTEMMEMORY 0x00000800
+#define VBOXVHWA_SCAPS_VIDEOMEMORY 0x00004000
+#define VBOXVHWA_SCAPS_VISIBLE 0x00008000
+#define VBOXVHWA_SCAPS_LOCALVIDMEM 0x10000000
+
+#define VBOXVHWA_PF_PALETTEINDEXED8 0x00000020
+#define VBOXVHWA_PF_RGB 0x00000040
+#define VBOXVHWA_PF_RGBTOYUV 0x00000100
+#define VBOXVHWA_PF_YUV 0x00000200
+#define VBOXVHWA_PF_FOURCC 0x00000004
+
+#define VBOXVHWA_LOCK_DISCARDCONTENTS 0x00002000
+
+#define VBOXVHWA_CFG_ENABLED 0x00000001
+
+#define VBOXVHWA_SD_BACKBUFFERCOUNT 0x00000020
+#define VBOXVHWA_SD_CAPS 0x00000001
+#define VBOXVHWA_SD_CKDESTBLT 0x00004000
+#define VBOXVHWA_SD_CKDESTOVERLAY 0x00002000
+#define VBOXVHWA_SD_CKSRCBLT 0x00010000
+#define VBOXVHWA_SD_CKSRCOVERLAY 0x00008000
+#define VBOXVHWA_SD_HEIGHT 0x00000002
+#define VBOXVHWA_SD_PITCH 0x00000008
+#define VBOXVHWA_SD_PIXELFORMAT 0x00001000
+/*#define VBOXVHWA_SD_REFRESHRATE 0x00040000*/
+#define VBOXVHWA_SD_WIDTH 0x00000004
+
+#define VBOXVHWA_CKEYCAPS_DESTBLT 0x00000001
+#define VBOXVHWA_CKEYCAPS_DESTBLTCLRSPACE 0x00000002
+#define VBOXVHWA_CKEYCAPS_DESTBLTCLRSPACEYUV 0x00000004
+#define VBOXVHWA_CKEYCAPS_DESTBLTYUV 0x00000008
+#define VBOXVHWA_CKEYCAPS_DESTOVERLAY 0x00000010
+#define VBOXVHWA_CKEYCAPS_DESTOVERLAYCLRSPACE 0x00000020
+#define VBOXVHWA_CKEYCAPS_DESTOVERLAYCLRSPACEYUV 0x00000040
+#define VBOXVHWA_CKEYCAPS_DESTOVERLAYONEACTIVE 0x00000080
+#define VBOXVHWA_CKEYCAPS_DESTOVERLAYYUV 0x00000100
+#define VBOXVHWA_CKEYCAPS_SRCBLT 0x00000200
+#define VBOXVHWA_CKEYCAPS_SRCBLTCLRSPACE 0x00000400
+#define VBOXVHWA_CKEYCAPS_SRCBLTCLRSPACEYUV 0x00000800
+#define VBOXVHWA_CKEYCAPS_SRCBLTYUV 0x00001000
+#define VBOXVHWA_CKEYCAPS_SRCOVERLAY 0x00002000
+#define VBOXVHWA_CKEYCAPS_SRCOVERLAYCLRSPACE 0x00004000
+#define VBOXVHWA_CKEYCAPS_SRCOVERLAYCLRSPACEYUV 0x00008000
+#define VBOXVHWA_CKEYCAPS_SRCOVERLAYONEACTIVE 0x00010000
+#define VBOXVHWA_CKEYCAPS_SRCOVERLAYYUV 0x00020000
+#define VBOXVHWA_CKEYCAPS_NOCOSTOVERLAY 0x00040000
+
+#define VBOXVHWA_BLT_COLORFILL 0x00000400
+#define VBOXVHWA_BLT_DDFX 0x00000800
+#define VBOXVHWA_BLT_EXTENDED_FLAGS 0x40000000
+#define VBOXVHWA_BLT_EXTENDED_LINEAR_CONTENT 0x00000004
+#define VBOXVHWA_BLT_EXTENDED_PRESENTATION_STRETCHFACTOR 0x00000010
+#define VBOXVHWA_BLT_KEYDESTOVERRIDE 0x00004000
+#define VBOXVHWA_BLT_KEYSRCOVERRIDE 0x00010000
+#define VBOXVHWA_BLT_LAST_PRESENTATION 0x20000000
+#define VBOXVHWA_BLT_PRESENTATION 0x10000000
+#define VBOXVHWA_BLT_ROP 0x00020000
+
+
+#define VBOXVHWA_OVER_DDFX 0x00080000
+#define VBOXVHWA_OVER_HIDE 0x00000200
+#define VBOXVHWA_OVER_KEYDEST 0x00000400
+#define VBOXVHWA_OVER_KEYDESTOVERRIDE 0x00000800
+#define VBOXVHWA_OVER_KEYSRC 0x00001000
+#define VBOXVHWA_OVER_KEYSRCOVERRIDE 0x00002000
+#define VBOXVHWA_OVER_SHOW 0x00004000
+
+#define VBOXVHWA_CKEY_COLORSPACE 0x00000001
+#define VBOXVHWA_CKEY_DESTBLT 0x00000002
+#define VBOXVHWA_CKEY_DESTOVERLAY 0x00000004
+#define VBOXVHWA_CKEY_SRCBLT 0x00000008
+#define VBOXVHWA_CKEY_SRCOVERLAY 0x00000010
+
+#define VBOXVHWA_BLT_ARITHSTRETCHY 0x00000001
+#define VBOXVHWA_BLT_MIRRORLEFTRIGHT 0x00000002
+#define VBOXVHWA_BLT_MIRRORUPDOWN 0x00000004
+
+#define VBOXVHWA_OVERFX_ARITHSTRETCHY 0x00000001
+#define VBOXVHWA_OVERFX_MIRRORLEFTRIGHT 0x00000002
+#define VBOXVHWA_OVERFX_MIRRORUPDOWN 0x00000004
+
+#define VBOXVHWA_CAPS2_CANRENDERWINDOWED 0x00080000
+#define VBOXVHWA_CAPS2_WIDESURFACES 0x00001000
+#define VBOXVHWA_CAPS2_COPYFOURCC 0x00008000
+/*#define VBOXVHWA_CAPS2_FLIPINTERVAL 0x00200000*/
+/*#define VBOXVHWA_CAPS2_FLIPNOVSYNC 0x00400000*/
+
+
+#define VBOXVHWA_OFFSET64_VOID (UINT64_MAX)
+
+typedef struct VBOXVHWA_VERSION
+{
+ uint32_t maj;
+ uint32_t min;
+ uint32_t bld;
+ uint32_t reserved;
+} VBOXVHWA_VERSION;
+
+#define VBOXVHWA_VERSION_INIT(_pv) do { \
+ (_pv)->maj = VBOXVHWA_VERSION_MAJ; \
+ (_pv)->min = VBOXVHWA_VERSION_MIN; \
+ (_pv)->bld = VBOXVHWA_VERSION_BLD; \
+ (_pv)->reserved = VBOXVHWA_VERSION_RSV; \
+ } while(0)
+
+typedef struct VBOXVHWACMD_QUERYINFO1
+{
+ union
+ {
+ struct
+ {
+ VBOXVHWA_VERSION guestVersion;
+ } in;
+
+ struct
+ {
+ uint32_t cfgFlags;
+ uint32_t caps;
+
+ uint32_t caps2;
+ uint32_t colorKeyCaps;
+
+ uint32_t stretchCaps;
+ uint32_t surfaceCaps;
+
+ uint32_t numOverlays;
+ uint32_t curOverlays;
+
+ uint32_t numFourCC;
+ uint32_t reserved;
+ } out;
+ } u;
+} VBOXVHWACMD_QUERYINFO1;
+
+typedef struct VBOXVHWACMD_QUERYINFO2
+{
+ uint32_t numFourCC;
+ uint32_t FourCC[1];
+} VBOXVHWACMD_QUERYINFO2;
+
+#define VBOXVHWAINFO2_SIZE(_cFourCC) RT_OFFSETOF(VBOXVHWACMD_QUERYINFO2, FourCC[_cFourCC])
+
+typedef struct VBOXVHWACMD_SURF_CANCREATE
+{
+ VBOXVHWA_SURFACEDESC SurfInfo;
+ union
+ {
+ struct
+ {
+ uint32_t bIsDifferentPixelFormat;
+ uint32_t Reserved;
+ } in;
+
+ struct
+ {
+ int32_t ErrInfo;
+ } out;
+ } u;
+} VBOXVHWACMD_SURF_CANCREATE;
+
+typedef struct VBOXVHWACMD_SURF_CREATE
+{
+ VBOXVHWA_SURFACEDESC SurfInfo;
+} VBOXVHWACMD_SURF_CREATE;
+
+#ifdef VBOX_WITH_WDDM
+typedef struct VBOXVHWACMD_SURF_GETINFO
+{
+ VBOXVHWA_SURFACEDESC SurfInfo;
+} VBOXVHWACMD_SURF_GETINFO;
+#endif
+
+typedef struct VBOXVHWACMD_SURF_DESTROY
+{
+ union
+ {
+ struct
+ {
+ VBOXVHWA_SURFHANDLE hSurf;
+ } in;
+ } u;
+} VBOXVHWACMD_SURF_DESTROY;
+
+typedef struct VBOXVHWACMD_SURF_LOCK
+{
+ union
+ {
+ struct
+ {
+ VBOXVHWA_SURFHANDLE hSurf;
+ uint64_t offSurface;
+ uint32_t flags;
+ uint32_t rectValid;
+ VBOXVHWA_RECTL rect;
+ } in;
+ } u;
+} VBOXVHWACMD_SURF_LOCK;
+
+typedef struct VBOXVHWACMD_SURF_UNLOCK
+{
+ union
+ {
+ struct
+ {
+ VBOXVHWA_SURFHANDLE hSurf;
+ uint32_t xUpdatedMemValid;
+ uint32_t reserved;
+ VBOXVHWA_RECTL xUpdatedMemRect;
+ } in;
+ } u;
+} VBOXVHWACMD_SURF_UNLOCK;
+
+typedef struct VBOXVHWACMD_SURF_BLT
+{
+ uint64_t DstGuestSurfInfo;
+ uint64_t SrcGuestSurfInfo;
+ union
+ {
+ struct
+ {
+ VBOXVHWA_SURFHANDLE hDstSurf;
+ uint64_t offDstSurface;
+ VBOXVHWA_RECTL dstRect;
+ VBOXVHWA_SURFHANDLE hSrcSurf;
+ uint64_t offSrcSurface;
+ VBOXVHWA_RECTL srcRect;
+ uint32_t flags;
+ uint32_t xUpdatedSrcMemValid;
+ VBOXVHWA_BLTFX desc;
+ VBOXVHWA_RECTL xUpdatedSrcMemRect;
+ } in;
+ } u;
+} VBOXVHWACMD_SURF_BLT;
+
+#ifdef VBOX_WITH_WDDM
+typedef struct VBOXVHWACMD_SURF_COLORFILL
+{
+ union
+ {
+ struct
+ {
+ VBOXVHWA_SURFHANDLE hSurf;
+ uint64_t offSurface;
+ uint32_t u32Reserved;
+ uint32_t cRects;
+ VBOXVHWA_RECTL aRects[1];
+ } in;
+ } u;
+} VBOXVHWACMD_SURF_COLORFILL;
+#endif
+
+typedef struct VBOXVHWACMD_SURF_FLIP
+{
+ uint64_t TargGuestSurfInfo;
+ uint64_t CurrGuestSurfInfo;
+ union
+ {
+ struct
+ {
+ VBOXVHWA_SURFHANDLE hTargSurf;
+ uint64_t offTargSurface;
+ VBOXVHWA_SURFHANDLE hCurrSurf;
+ uint64_t offCurrSurface;
+ uint32_t flags;
+ uint32_t xUpdatedTargMemValid;
+ VBOXVHWA_RECTL xUpdatedTargMemRect;
+ } in;
+ } u;
+} VBOXVHWACMD_SURF_FLIP;
+
+typedef struct VBOXVHWACMD_SURF_COLORKEY_SET
+{
+ union
+ {
+ struct
+ {
+ VBOXVHWA_SURFHANDLE hSurf;
+ uint64_t offSurface;
+ VBOXVHWA_COLORKEY CKey;
+ uint32_t flags;
+ uint32_t reserved;
+ } in;
+ } u;
+} VBOXVHWACMD_SURF_COLORKEY_SET;
+
+#define VBOXVHWACMD_SURF_OVERLAY_UPDATE_F_SRCMEMRECT 0x00000001
+#define VBOXVHWACMD_SURF_OVERLAY_UPDATE_F_DSTMEMRECT 0x00000002
+
+typedef struct VBOXVHWACMD_SURF_OVERLAY_UPDATE
+{
+ union
+ {
+ struct
+ {
+ VBOXVHWA_SURFHANDLE hDstSurf;
+ uint64_t offDstSurface;
+ VBOXVHWA_RECTL dstRect;
+ VBOXVHWA_SURFHANDLE hSrcSurf;
+ uint64_t offSrcSurface;
+ VBOXVHWA_RECTL srcRect;
+ uint32_t flags;
+ uint32_t xFlags;
+ VBOXVHWA_OVERLAYFX desc;
+ VBOXVHWA_RECTL xUpdatedSrcMemRect;
+ VBOXVHWA_RECTL xUpdatedDstMemRect;
+ } in;
+ } u;
+}VBOXVHWACMD_SURF_OVERLAY_UPDATE;
+
+typedef struct VBOXVHWACMD_SURF_OVERLAY_SETPOSITION
+{
+ union
+ {
+ struct
+ {
+ VBOXVHWA_SURFHANDLE hDstSurf;
+ uint64_t offDstSurface;
+ VBOXVHWA_SURFHANDLE hSrcSurf;
+ uint64_t offSrcSurface;
+ uint32_t xPos;
+ uint32_t yPos;
+ uint32_t flags;
+ uint32_t reserved;
+ } in;
+ } u;
+} VBOXVHWACMD_SURF_OVERLAY_SETPOSITION;
+
+typedef struct VBOXVHWACMD_HH_CONSTRUCT
+{
+ void *pVM;
+ /* VRAM info for the backend to be able to properly translate VRAM offsets */
+ void *pvVRAM;
+ uint32_t cbVRAM;
+} VBOXVHWACMD_HH_CONSTRUCT;
+
+typedef struct VBOXVHWACMD_HH_SAVESTATE_SAVEPERFORM
+{
+ struct SSMHANDLE * pSSM;
+} VBOXVHWACMD_HH_SAVESTATE_SAVEPERFORM;
+
+typedef struct VBOXVHWACMD_HH_SAVESTATE_LOADPERFORM
+{
+ struct SSMHANDLE * pSSM;
+} VBOXVHWACMD_HH_SAVESTATE_LOADPERFORM;
+
+typedef DECLCALLBACK(void) FNVBOXVHWA_HH_CALLBACK(void*);
+typedef FNVBOXVHWA_HH_CALLBACK *PFNVBOXVHWA_HH_CALLBACK;
+
+#define VBOXVHWA_HH_CALLBACK_SET(_pCmd, _pfn, _parg) \
+ do { \
+ (_pCmd)->GuestVBVAReserved1 = (uint64_t)(uintptr_t)(_pfn); \
+ (_pCmd)->GuestVBVAReserved2 = (uint64_t)(uintptr_t)(_parg); \
+ }while(0)
+
+#define VBOXVHWA_HH_CALLBACK_GET(_pCmd) ((PFNVBOXVHWA_HH_CALLBACK)(_pCmd)->GuestVBVAReserved1)
+#define VBOXVHWA_HH_CALLBACK_GET_ARG(_pCmd) ((void*)(_pCmd)->GuestVBVAReserved2)
+
+#pragma pack()
+#endif /* #ifdef VBOX_WITH_VIDEOHWACCEL */
+
+/* All structures are without alignment. */
+#pragma pack(1)
+
+typedef struct VBVAHOSTFLAGS
+{
+ uint32_t u32HostEvents;
+ uint32_t u32SupportedOrders;
+} VBVAHOSTFLAGS;
+
+typedef struct VBVABUFFER
+{
+ VBVAHOSTFLAGS hostFlags;
+
+ /* The offset where the data start in the buffer. */
+ uint32_t off32Data;
+ /* The offset where next data must be placed in the buffer. */
+ uint32_t off32Free;
+
+ /* The queue of record descriptions. */
+ VBVARECORD aRecords[VBVA_MAX_RECORDS];
+ uint32_t indexRecordFirst;
+ uint32_t indexRecordFree;
+
+ /* Space to leave free in the buffer when large partial records are transferred. */
+ uint32_t cbPartialWriteThreshold;
+
+ uint32_t cbData;
+ uint8_t au8Data[1]; /* variable size for the rest of the VBVABUFFER area in VRAM. */
+} VBVABUFFER;
+
+#define VBVA_MAX_RECORD_SIZE (128*_1M)
+
+/* guest->host commands */
+#define VBVA_QUERY_CONF32 1
+#define VBVA_SET_CONF32 2
+#define VBVA_INFO_VIEW 3
+#define VBVA_INFO_HEAP 4
+#define VBVA_FLUSH 5
+#define VBVA_INFO_SCREEN 6
+#define VBVA_ENABLE 7
+#define VBVA_MOUSE_POINTER_SHAPE 8
+#ifdef VBOX_WITH_VIDEOHWACCEL
+# define VBVA_VHWA_CMD 9
+#endif /* # ifdef VBOX_WITH_VIDEOHWACCEL */
+#ifdef VBOX_WITH_VDMA
+# define VBVA_VDMA_CTL 10 /* setup G<->H DMA channel info */
+# define VBVA_VDMA_CMD 11 /* G->H DMA command */
+#endif
+#define VBVA_INFO_CAPS 12 /* informs host about HGSMI caps. see VBVACAPS below */
+#define VBVA_SCANLINE_CFG 13 /* configures scanline, see VBVASCANLINECFG below */
+#define VBVA_SCANLINE_INFO 14 /* requests scanline info, see VBVASCANLINEINFO below */
+#define VBVA_CMDVBVA_SUBMIT 16 /* inform host about VBVA Command submission */
+#define VBVA_CMDVBVA_FLUSH 17 /* inform host about VBVA Command submission */
+#define VBVA_CMDVBVA_CTL 18 /* G->H DMA command */
+#define VBVA_QUERY_MODE_HINTS 19 /* Query most recent mode hints sent. */
+/** Report the guest virtual desktop position and size for mapping host and
+ * guest pointer positions. */
+#define VBVA_REPORT_INPUT_MAPPING 20
+/** Report the guest cursor position and query the host position. */
+#define VBVA_CURSOR_POSITION 21
+
+/* host->guest commands */
+#define VBVAHG_EVENT 1
+#define VBVAHG_DISPLAY_CUSTOM 2
+#ifdef VBOX_WITH_VDMA
+#define VBVAHG_SHGSMI_COMPLETION 3
+#endif
+
+#ifdef VBOX_WITH_VIDEOHWACCEL
+#define VBVAHG_DCUSTOM_VHWA_CMDCOMPLETE 1
+#pragma pack(1)
+typedef struct VBVAHOSTCMDVHWACMDCOMPLETE
+{
+ uint32_t offCmd;
+}VBVAHOSTCMDVHWACMDCOMPLETE;
+#pragma pack()
+#endif /* # ifdef VBOX_WITH_VIDEOHWACCEL */
+
+#pragma pack(1)
+typedef enum
+{
+ VBVAHOSTCMD_OP_EVENT = 1,
+ VBVAHOSTCMD_OP_CUSTOM
+}VBVAHOSTCMD_OP_TYPE;
+
+typedef struct VBVAHOSTCMDEVENT
+{
+ uint64_t pEvent;
+}VBVAHOSTCMDEVENT;
+
+
+typedef struct VBVAHOSTCMD
+{
+ /* destination ID if >=0 specifies display index, otherwize the command is directed to the miniport */
+ int32_t iDstID;
+ int32_t customOpCode;
+ union
+ {
+ struct VBVAHOSTCMD *pNext;
+ uint32_t offNext;
+ uint64_t Data; /* the body is 64-bit aligned */
+ } u;
+ char body[1];
+}VBVAHOSTCMD;
+
+#define VBVAHOSTCMD_SIZE(_size) (sizeof(VBVAHOSTCMD) + (_size))
+#define VBVAHOSTCMD_BODY(_pCmd, _tBody) ((_tBody*)(_pCmd)->body)
+#define VBVAHOSTCMD_HDR(_pBody) ((VBVAHOSTCMD*)(((uint8_t*)_pBody) - RT_OFFSETOF(VBVAHOSTCMD, body)))
+#define VBVAHOSTCMD_HDRSIZE (RT_OFFSETOF(VBVAHOSTCMD, body))
+
+#pragma pack()
+
+/* VBVACONF32::u32Index */
+#define VBOX_VBVA_CONF32_MONITOR_COUNT 0
+#define VBOX_VBVA_CONF32_HOST_HEAP_SIZE 1
+/** Returns VINF_SUCCESS if the host can report mode hints via VBVA.
+ * Set value to VERR_NOT_SUPPORTED before calling. */
+#define VBOX_VBVA_CONF32_MODE_HINT_REPORTING 2
+/** Returns VINF_SUCCESS if the host can report guest cursor enabled status via
+ * VBVA. Set value to VERR_NOT_SUPPORTED before calling. */
+#define VBOX_VBVA_CONF32_GUEST_CURSOR_REPORTING 3
+/** Returns the currently available host cursor capabilities. Available if
+ * VBVACONF32::VBOX_VBVA_CONF32_GUEST_CURSOR_REPORTING returns success.
+ * @see VMMDevReqMouseStatus::mouseFeatures. */
+#define VBOX_VBVA_CONF32_CURSOR_CAPABILITIES 4
+/** Returns the supported flags in VBVAINFOSCREEN::u8Flags. */
+#define VBOX_VBVA_CONF32_SCREEN_FLAGS 5
+/** Returns the max size of VBVA record. */
+#define VBOX_VBVA_CONF32_MAX_RECORD_SIZE 6
+
+typedef struct VBVACONF32
+{
+ uint32_t u32Index;
+ uint32_t u32Value;
+} VBVACONF32;
+
+/** Reserved for historical reasons. */
+#define VBOX_VBVA_CURSOR_CAPABILITY_RESERVED0 RT_BIT(0)
+/** Guest cursor capability: can the host show a hardware cursor at the host
+ * pointer location? */
+#define VBOX_VBVA_CURSOR_CAPABILITY_HARDWARE RT_BIT(1)
+/** Reserved for historical reasons. */
+#define VBOX_VBVA_CURSOR_CAPABILITY_RESERVED2 RT_BIT(2)
+/** Reserved for historical reasons. Must always be unset. */
+#define VBOX_VBVA_CURSOR_CAPABILITY_RESERVED3 RT_BIT(3)
+/** Reserved for historical reasons. */
+#define VBOX_VBVA_CURSOR_CAPABILITY_RESERVED4 RT_BIT(4)
+/** Reserved for historical reasons. */
+#define VBOX_VBVA_CURSOR_CAPABILITY_RESERVED5 RT_BIT(5)
+
+typedef struct VBVAINFOVIEW
+{
+ /* Index of the screen, assigned by the guest. */
+ uint32_t u32ViewIndex;
+
+ /* The screen offset in VRAM, the framebuffer starts here. */
+ uint32_t u32ViewOffset;
+
+ /* The size of the VRAM memory that can be used for the view. */
+ uint32_t u32ViewSize;
+
+ /* The recommended maximum size of the VRAM memory for the screen. */
+ uint32_t u32MaxScreenSize;
+} VBVAINFOVIEW;
+
+typedef struct VBVAINFOHEAP
+{
+ /* Absolute offset in VRAM of the start of the heap. */
+ uint32_t u32HeapOffset;
+
+ /* The size of the heap. */
+ uint32_t u32HeapSize;
+
+} VBVAINFOHEAP;
+
+typedef struct VBVAFLUSH
+{
+ uint32_t u32Reserved;
+
+} VBVAFLUSH;
+
+typedef struct VBVACMDVBVASUBMIT
+{
+ uint32_t u32Reserved;
+} VBVACMDVBVASUBMIT;
+
+/* flush is requested because due to guest command buffer overflow */
+#define VBVACMDVBVAFLUSH_F_GUEST_BUFFER_OVERFLOW 1
+
+typedef struct VBVACMDVBVAFLUSH
+{
+ uint32_t u32Flags;
+} VBVACMDVBVAFLUSH;
+
+
+/* VBVAINFOSCREEN::u8Flags */
+#define VBVA_SCREEN_F_NONE 0x0000
+#define VBVA_SCREEN_F_ACTIVE 0x0001
+/** The virtual monitor has been disabled by the guest and should be removed
+ * by the host and ignored for purposes of pointer position calculation. */
+#define VBVA_SCREEN_F_DISABLED 0x0002
+/** The virtual monitor has been blanked by the guest and should be blacked
+ * out by the host using width, height, etc values from the VBVAINFOSCREEN request. */
+#define VBVA_SCREEN_F_BLANK 0x0004
+/** The virtual monitor has been blanked by the guest and should be blacked
+ * out by the host using the previous mode values for width. height, etc. */
+#define VBVA_SCREEN_F_BLANK2 0x0008
+
+typedef struct VBVAINFOSCREEN
+{
+ /* Which view contains the screen. */
+ uint32_t u32ViewIndex;
+
+ /* Physical X origin relative to the primary screen. */
+ int32_t i32OriginX;
+
+ /* Physical Y origin relative to the primary screen. */
+ int32_t i32OriginY;
+
+ /* Offset of visible framebuffer relative to the framebuffer start. */
+ uint32_t u32StartOffset;
+
+ /* The scan line size in bytes. */
+ uint32_t u32LineSize;
+
+ /* Width of the screen. */
+ uint32_t u32Width;
+
+ /* Height of the screen. */
+ uint32_t u32Height;
+
+ /* Color depth. */
+ uint16_t u16BitsPerPixel;
+
+ /* VBVA_SCREEN_F_* */
+ uint16_t u16Flags;
+} VBVAINFOSCREEN;
+
+
+/* VBVAENABLE::u32Flags */
+#define VBVA_F_NONE 0x00000000
+#define VBVA_F_ENABLE 0x00000001
+#define VBVA_F_DISABLE 0x00000002
+/* extended VBVA to be used with WDDM */
+#define VBVA_F_EXTENDED 0x00000004
+/* vbva offset is absolute VRAM offset */
+#define VBVA_F_ABSOFFSET 0x00000008
+
+typedef struct VBVAENABLE
+{
+ uint32_t u32Flags;
+ uint32_t u32Offset;
+ int32_t i32Result;
+} VBVAENABLE;
+
+typedef struct VBVAENABLE_EX
+{
+ VBVAENABLE Base;
+ uint32_t u32ScreenId;
+} VBVAENABLE_EX;
+
+
+typedef struct VBVAMOUSEPOINTERSHAPE
+{
+ /* The host result. */
+ int32_t i32Result;
+
+ /* VBOX_MOUSE_POINTER_* bit flags. */
+ uint32_t fu32Flags;
+
+ /* X coordinate of the hot spot. */
+ uint32_t u32HotX;
+
+ /* Y coordinate of the hot spot. */
+ uint32_t u32HotY;
+
+ /* Width of the pointer in pixels. */
+ uint32_t u32Width;
+
+ /* Height of the pointer in scanlines. */
+ uint32_t u32Height;
+
+ /* Pointer data.
+ *
+ ****
+ * The data consists of 1 bpp AND mask followed by 32 bpp XOR (color) mask.
+ *
+ * For pointers without alpha channel the XOR mask pixels are 32 bit values: (lsb)BGR0(msb).
+ * For pointers with alpha channel the XOR mask consists of (lsb)BGRA(msb) 32 bit values.
+ *
+ * Guest driver must create the AND mask for pointers with alpha channel, so if host does not
+ * support alpha, the pointer could be displayed as a normal color pointer. The AND mask can
+ * be constructed from alpha values. For example alpha value >= 0xf0 means bit 0 in the AND mask.
+ *
+ * The AND mask is 1 bpp bitmap with byte aligned scanlines. Size of AND mask,
+ * therefore, is cbAnd = (width + 7) / 8 * height. The padding bits at the
+ * end of any scanline are undefined.
+ *
+ * The XOR mask follows the AND mask on the next 4 bytes aligned offset:
+ * uint8_t *pXor = pAnd + (cbAnd + 3) & ~3
+ * Bytes in the gap between the AND and the XOR mask are undefined.
+ * XOR mask scanlines have no gap between them and size of XOR mask is:
+ * cXor = width * 4 * height.
+ ****
+ *
+ * Preallocate 4 bytes for accessing actual data as p->au8Data.
+ */
+ uint8_t au8Data[4];
+
+} VBVAMOUSEPOINTERSHAPE;
+
+/** @name VBVAMOUSEPOINTERSHAPE::fu32Flags
+ * @note The VBOX_MOUSE_POINTER_* flags are used in the guest video driver,
+ * values must be <= 0x8000 and must not be changed. (try make more sense
+ * of this, please).
+ * @{
+ */
+/** pointer is visible */
+#define VBOX_MOUSE_POINTER_VISIBLE (0x0001)
+/** pointer has alpha channel */
+#define VBOX_MOUSE_POINTER_ALPHA (0x0002)
+/** pointerData contains new pointer shape */
+#define VBOX_MOUSE_POINTER_SHAPE (0x0004)
+/** @} */
+
+/* the guest driver can handle asynch guest cmd completion by reading the command offset from io port */
+#define VBVACAPS_COMPLETEGCMD_BY_IOREAD 0x00000001
+/* the guest driver can handle video adapter IRQs */
+#define VBVACAPS_IRQ 0x00000002
+/** The guest can read video mode hints sent via VBVA. */
+#define VBVACAPS_VIDEO_MODE_HINTS 0x00000004
+/** The guest can switch to a software cursor on demand. */
+#define VBVACAPS_DISABLE_CURSOR_INTEGRATION 0x00000008
+/** The guest does not depend on host handling the VBE registers. */
+#define VBVACAPS_USE_VBVA_ONLY 0x00000010
+typedef struct VBVACAPS
+{
+ int32_t rc;
+ uint32_t fCaps;
+} VBVACAPS;
+
+/* makes graphics device generate IRQ on VSYNC */
+#define VBVASCANLINECFG_ENABLE_VSYNC_IRQ 0x00000001
+/* guest driver may request the current scanline */
+#define VBVASCANLINECFG_ENABLE_SCANLINE_INFO 0x00000002
+/* request the current refresh period, returned in u32RefreshPeriodMs */
+#define VBVASCANLINECFG_QUERY_REFRESH_PERIOD 0x00000004
+/* set new refresh period specified in u32RefreshPeriodMs.
+ * if used with VBVASCANLINECFG_QUERY_REFRESH_PERIOD,
+ * u32RefreshPeriodMs is set to the previous refresh period on return */
+#define VBVASCANLINECFG_SET_REFRESH_PERIOD 0x00000008
+
+typedef struct VBVASCANLINECFG
+{
+ int32_t rc;
+ uint32_t fFlags;
+ uint32_t u32RefreshPeriodMs;
+ uint32_t u32Reserved;
+} VBVASCANLINECFG;
+
+typedef struct VBVASCANLINEINFO
+{
+ int32_t rc;
+ uint32_t u32ScreenId;
+ uint32_t u32InVBlank;
+ uint32_t u32ScanLine;
+} VBVASCANLINEINFO;
+
+/** Query the most recent mode hints received from the host. */
+typedef struct VBVAQUERYMODEHINTS
+{
+ /** The maximum number of screens to return hints for. */
+ uint16_t cHintsQueried;
+ /** The size of the mode hint structures directly following this one. */
+ uint16_t cbHintStructureGuest;
+ /** The return code for the operation. Initialise to VERR_NOT_SUPPORTED. */
+ int32_t rc;
+} VBVAQUERYMODEHINTS;
+
+/** Structure in which a mode hint is returned. The guest allocates an array
+ * of these immediately after the VBVAQUERYMODEHINTS structure. To accomodate
+ * future extensions, the VBVAQUERYMODEHINTS structure specifies the size of
+ * the VBVAMODEHINT structures allocated by the guest, and the host only fills
+ * out structure elements which fit into that size. The host should fill any
+ * unused members (e.g. dx, dy) or structure space on the end with ~0. The
+ * whole structure can legally be set to ~0 to skip a screen. */
+typedef struct VBVAMODEHINT
+{
+ uint32_t magic;
+ uint32_t cx;
+ uint32_t cy;
+ uint32_t cBPP; /* Which has never been used... */
+ uint32_t cDisplay;
+ uint32_t dx; /**< X offset into the virtual frame-buffer. */
+ uint32_t dy; /**< Y offset into the virtual frame-buffer. */
+ uint32_t fEnabled; /* Not fFlags. Add new members for new flags. */
+} VBVAMODEHINT;
+
+#define VBVAMODEHINT_MAGIC UINT32_C(0x0801add9)
+
+/** Report the rectangle relative to which absolute pointer events should be
+ * expressed. This information remains valid until the next VBVA resize event
+ * for any screen, at which time it is reset to the bounding rectangle of all
+ * virtual screens and must be re-set.
+ * @see VBVA_REPORT_INPUT_MAPPING. */
+typedef struct VBVAREPORTINPUTMAPPING
+{
+ int32_t x; /**< Upper left X co-ordinate relative to the first screen. */
+ int32_t y; /**< Upper left Y co-ordinate relative to the first screen. */
+ uint32_t cx; /**< Rectangle width. */
+ uint32_t cy; /**< Rectangle height. */
+} VBVAREPORTINPUTMAPPING;
+
+/** Report the guest cursor position and query the host one. The host may wish
+ * to use the guest information to re-position its own cursor (though this is
+ * currently unlikely).
+ * @see VBVA_CURSOR_POSITION */
+typedef struct VBVACURSORPOSITION
+{
+ uint32_t fReportPosition; /**< Are we reporting a position? */
+ uint32_t x; /**< Guest cursor X position */
+ uint32_t y; /**< Guest cursor Y position */
+} VBVACURSORPOSITION;
+
+#pragma pack()
+
+typedef uint64_t VBOXVIDEOOFFSET;
+
+#define VBOXVIDEOOFFSET_VOID ((VBOXVIDEOOFFSET)~0)
+
+#pragma pack(1)
+
+/*
+ * VBOXSHGSMI made on top HGSMI and allows receiving notifications
+ * about G->H command completion
+ */
+/* SHGSMI command header */
+typedef struct VBOXSHGSMIHEADER
+{
+ uint64_t pvNext; /*<- completion processing queue */
+ uint32_t fFlags; /*<- see VBOXSHGSMI_FLAG_XXX Flags */
+ uint32_t cRefs; /*<- command referece count */
+ uint64_t u64Info1; /*<- contents depends on the fFlags value */
+ uint64_t u64Info2; /*<- contents depends on the fFlags value */
+} VBOXSHGSMIHEADER, *PVBOXSHGSMIHEADER;
+
+typedef enum
+{
+ VBOXVDMACMD_TYPE_UNDEFINED = 0,
+ VBOXVDMACMD_TYPE_DMA_PRESENT_BLT = 1,
+ VBOXVDMACMD_TYPE_DMA_BPB_TRANSFER,
+ VBOXVDMACMD_TYPE_DMA_BPB_FILL,
+ VBOXVDMACMD_TYPE_DMA_PRESENT_SHADOW2PRIMARY,
+ VBOXVDMACMD_TYPE_DMA_PRESENT_CLRFILL,
+ VBOXVDMACMD_TYPE_DMA_PRESENT_FLIP,
+ VBOXVDMACMD_TYPE_DMA_NOP,
+ VBOXVDMACMD_TYPE_CHROMIUM_CMD, /* chromium cmd */
+ VBOXVDMACMD_TYPE_DMA_BPB_TRANSFER_VRAMSYS,
+ VBOXVDMACMD_TYPE_CHILD_STATUS_IRQ /* make the device notify child (monitor) state change IRQ */
+} VBOXVDMACMD_TYPE;
+
+#pragma pack()
+
+/* the command processing was asynch, set by the host to indicate asynch command completion
+ * must not be cleared once set, the command completion is performed by issuing a host->guest completion command
+ * while keeping this flag unchanged */
+#define VBOXSHGSMI_FLAG_HG_ASYNCH 0x00010000
+#if 0
+/* if set - asynch completion is performed by issuing the event,
+ * if cleared - asynch completion is performed by calling a callback */
+#define VBOXSHGSMI_FLAG_GH_ASYNCH_EVENT 0x00000001
+#endif
+/* issue interrupt on asynch completion, used for critical G->H commands,
+ * i.e. for completion of which guest is waiting. */
+#define VBOXSHGSMI_FLAG_GH_ASYNCH_IRQ 0x00000002
+/* guest does not do any op on completion of this command,
+ * the host may copy the command and indicate that it does not need the command anymore
+ * by not setting VBOXSHGSMI_FLAG_HG_ASYNCH */
+#define VBOXSHGSMI_FLAG_GH_ASYNCH_NOCOMPLETION 0x00000004
+/* guest requires the command to be processed asynchronously,
+ * not setting VBOXSHGSMI_FLAG_HG_ASYNCH by the host in this case is treated as command failure */
+#define VBOXSHGSMI_FLAG_GH_ASYNCH_FORCE 0x00000008
+/* force IRQ on cmd completion */
+#define VBOXSHGSMI_FLAG_GH_ASYNCH_IRQ_FORCE 0x00000010
+/* an IRQ-level callback is associated with the command */
+#define VBOXSHGSMI_FLAG_GH_ASYNCH_CALLBACK_IRQ 0x00000020
+/* guest expects this command to be completed synchronously */
+#define VBOXSHGSMI_FLAG_GH_SYNCH 0x00000040
+
+
+DECLINLINE(uint8_t *) VBoxSHGSMIBufferData (const VBOXSHGSMIHEADER* pHeader)
+{
+ return (uint8_t *)pHeader + sizeof (VBOXSHGSMIHEADER);
+}
+
+#define VBoxSHGSMIBufferHeaderSize() (sizeof (VBOXSHGSMIHEADER))
+
+DECLINLINE(PVBOXSHGSMIHEADER) VBoxSHGSMIBufferHeader (const void *pvData)
+{
+ return (PVBOXSHGSMIHEADER)((uint8_t *)pvData - sizeof (VBOXSHGSMIHEADER));
+}
+
+#ifdef VBOX_WITH_VDMA
+# pragma pack(1)
+
+/* VDMA - Video DMA */
+
+/* VDMA Control API */
+/* VBOXVDMA_CTL::u32Flags */
+typedef enum
+{
+ VBOXVDMA_CTL_TYPE_NONE = 0,
+ VBOXVDMA_CTL_TYPE_ENABLE,
+ VBOXVDMA_CTL_TYPE_DISABLE,
+ VBOXVDMA_CTL_TYPE_FLUSH,
+ VBOXVDMA_CTL_TYPE_WATCHDOG
+} VBOXVDMA_CTL_TYPE;
+
+typedef struct VBOXVDMA_CTL
+{
+ VBOXVDMA_CTL_TYPE enmCtl;
+ uint32_t u32Offset;
+ int32_t i32Result;
+} VBOXVDMA_CTL, *PVBOXVDMA_CTL;
+
+typedef struct VBOXVDMA_RECTL
+{
+ int16_t left;
+ int16_t top;
+ uint16_t width;
+ uint16_t height;
+} VBOXVDMA_RECTL, *PVBOXVDMA_RECTL;
+
+typedef enum
+{
+ VBOXVDMA_PIXEL_FORMAT_UNKNOWN = 0,
+ VBOXVDMA_PIXEL_FORMAT_R8G8B8 = 20,
+ VBOXVDMA_PIXEL_FORMAT_A8R8G8B8 = 21,
+ VBOXVDMA_PIXEL_FORMAT_X8R8G8B8 = 22,
+ VBOXVDMA_PIXEL_FORMAT_R5G6B5 = 23,
+ VBOXVDMA_PIXEL_FORMAT_X1R5G5B5 = 24,
+ VBOXVDMA_PIXEL_FORMAT_A1R5G5B5 = 25,
+ VBOXVDMA_PIXEL_FORMAT_A4R4G4B4 = 26,
+ VBOXVDMA_PIXEL_FORMAT_R3G3B2 = 27,
+ VBOXVDMA_PIXEL_FORMAT_A8 = 28,
+ VBOXVDMA_PIXEL_FORMAT_A8R3G3B2 = 29,
+ VBOXVDMA_PIXEL_FORMAT_X4R4G4B4 = 30,
+ VBOXVDMA_PIXEL_FORMAT_A2B10G10R10 = 31,
+ VBOXVDMA_PIXEL_FORMAT_A8B8G8R8 = 32,
+ VBOXVDMA_PIXEL_FORMAT_X8B8G8R8 = 33,
+ VBOXVDMA_PIXEL_FORMAT_G16R16 = 34,
+ VBOXVDMA_PIXEL_FORMAT_A2R10G10B10 = 35,
+ VBOXVDMA_PIXEL_FORMAT_A16B16G16R16 = 36,
+ VBOXVDMA_PIXEL_FORMAT_A8P8 = 40,
+ VBOXVDMA_PIXEL_FORMAT_P8 = 41,
+ VBOXVDMA_PIXEL_FORMAT_L8 = 50,
+ VBOXVDMA_PIXEL_FORMAT_A8L8 = 51,
+ VBOXVDMA_PIXEL_FORMAT_A4L4 = 52,
+ VBOXVDMA_PIXEL_FORMAT_V8U8 = 60,
+ VBOXVDMA_PIXEL_FORMAT_L6V5U5 = 61,
+ VBOXVDMA_PIXEL_FORMAT_X8L8V8U8 = 62,
+ VBOXVDMA_PIXEL_FORMAT_Q8W8V8U8 = 63,
+ VBOXVDMA_PIXEL_FORMAT_V16U16 = 64,
+ VBOXVDMA_PIXEL_FORMAT_W11V11U10 = 65,
+ VBOXVDMA_PIXEL_FORMAT_A2W10V10U10 = 67
+} VBOXVDMA_PIXEL_FORMAT;
+
+typedef struct VBOXVDMA_SURF_DESC
+{
+ uint32_t width;
+ uint32_t height;
+ VBOXVDMA_PIXEL_FORMAT format;
+ uint32_t bpp;
+ uint32_t pitch;
+ uint32_t fFlags;
+} VBOXVDMA_SURF_DESC, *PVBOXVDMA_SURF_DESC;
+
+/*typedef uint64_t VBOXVDMAPHADDRESS;*/
+typedef uint64_t VBOXVDMASURFHANDLE;
+
+/* region specified as a rectangle, otherwize it is a size of memory pointed to by phys address */
+#define VBOXVDMAOPERAND_FLAGS_RECTL 0x1
+/* Surface handle is valid */
+#define VBOXVDMAOPERAND_FLAGS_PRIMARY 0x2
+/* address is offset in VRAM */
+#define VBOXVDMAOPERAND_FLAGS_VRAMOFFSET 0x4
+
+
+/* VBOXVDMACBUF_DR::phBuf specifies offset in VRAM */
+#define VBOXVDMACBUF_FLAG_BUF_VRAM_OFFSET 0x00000001
+/* command buffer follows the VBOXVDMACBUF_DR in VRAM, VBOXVDMACBUF_DR::phBuf is ignored */
+#define VBOXVDMACBUF_FLAG_BUF_FOLLOWS_DR 0x00000002
+
+/*
+ * We can not submit the DMA command via VRAM since we do not have control over
+ * DMA command buffer [de]allocation, i.e. we only control the buffer contents.
+ * In other words the system may call one of our callbacks to fill a command buffer
+ * with the necessary commands and then discard the buffer w/o any notification.
+ *
+ * We have only DMA command buffer physical address at submission time.
+ *
+ * so the only way is to */
+typedef struct VBOXVDMACBUF_DR
+{
+ uint16_t fFlags;
+ uint16_t cbBuf;
+ /* RT_SUCCESS() - on success
+ * VERR_INTERRUPTED - on preemption
+ * VERR_xxx - on error */
+ int32_t rc;
+ union
+ {
+ uint64_t phBuf;
+ VBOXVIDEOOFFSET offVramBuf;
+ } Location;
+ uint64_t aGuestData[7];
+} VBOXVDMACBUF_DR, *PVBOXVDMACBUF_DR;
+
+#define VBOXVDMACBUF_DR_TAIL(_pCmd, _t) ( (_t*)(((uint8_t*)(_pCmd)) + sizeof (VBOXVDMACBUF_DR)) )
+#define VBOXVDMACBUF_DR_FROM_TAIL(_pCmd) ( (VBOXVDMACBUF_DR*)(((uint8_t*)(_pCmd)) - sizeof (VBOXVDMACBUF_DR)) )
+
+typedef struct VBOXVDMACMD
+{
+ VBOXVDMACMD_TYPE enmType;
+ uint32_t u32CmdSpecific;
+} VBOXVDMACMD, *PVBOXVDMACMD;
+
+#define VBOXVDMACMD_HEADER_SIZE() sizeof (VBOXVDMACMD)
+#define VBOXVDMACMD_SIZE_FROMBODYSIZE(_s) (VBOXVDMACMD_HEADER_SIZE() + (_s))
+#define VBOXVDMACMD_SIZE(_t) (VBOXVDMACMD_SIZE_FROMBODYSIZE(sizeof (_t)))
+#define VBOXVDMACMD_BODY(_pCmd, _t) ( (_t*)(((uint8_t*)(_pCmd)) + VBOXVDMACMD_HEADER_SIZE()) )
+#define VBOXVDMACMD_BODY_SIZE(_s) ( (_s) - VBOXVDMACMD_HEADER_SIZE() )
+#define VBOXVDMACMD_FROM_BODY(_pCmd) ( (VBOXVDMACMD*)(((uint8_t*)(_pCmd)) - VBOXVDMACMD_HEADER_SIZE()) )
+#define VBOXVDMACMD_BODY_FIELD_OFFSET(_ot, _t, _f) ( (_ot)(uintptr_t)( VBOXVDMACMD_BODY(0, uint8_t) + RT_OFFSETOF(_t, _f) ) )
+
+typedef struct VBOXVDMACMD_DMA_PRESENT_BLT
+{
+ VBOXVIDEOOFFSET offSrc;
+ VBOXVIDEOOFFSET offDst;
+ VBOXVDMA_SURF_DESC srcDesc;
+ VBOXVDMA_SURF_DESC dstDesc;
+ VBOXVDMA_RECTL srcRectl;
+ VBOXVDMA_RECTL dstRectl;
+ uint32_t u32Reserved;
+ uint32_t cDstSubRects;
+ VBOXVDMA_RECTL aDstSubRects[1];
+} VBOXVDMACMD_DMA_PRESENT_BLT, *PVBOXVDMACMD_DMA_PRESENT_BLT;
+
+typedef struct VBOXVDMACMD_DMA_PRESENT_SHADOW2PRIMARY
+{
+ VBOXVDMA_RECTL Rect;
+} VBOXVDMACMD_DMA_PRESENT_SHADOW2PRIMARY, *PVBOXVDMACMD_DMA_PRESENT_SHADOW2PRIMARY;
+
+
+#define VBOXVDMACMD_DMA_BPB_TRANSFER_F_SRC_VRAMOFFSET 0x00000001
+#define VBOXVDMACMD_DMA_BPB_TRANSFER_F_DST_VRAMOFFSET 0x00000002
+
+typedef struct VBOXVDMACMD_DMA_BPB_TRANSFER
+{
+ uint32_t cbTransferSize;
+ uint32_t fFlags;
+ union
+ {
+ uint64_t phBuf;
+ VBOXVIDEOOFFSET offVramBuf;
+ } Src;
+ union
+ {
+ uint64_t phBuf;
+ VBOXVIDEOOFFSET offVramBuf;
+ } Dst;
+} VBOXVDMACMD_DMA_BPB_TRANSFER, *PVBOXVDMACMD_DMA_BPB_TRANSFER;
+
+#define VBOXVDMACMD_SYSMEMEL_F_PAGELIST 0x00000001
+
+typedef struct VBOXVDMACMD_SYSMEMEL
+{
+ uint32_t cPages;
+ uint32_t fFlags;
+ uint64_t phBuf[1];
+} VBOXVDMACMD_SYSMEMEL, *PVBOXVDMACMD_SYSMEMEL;
+
+#define VBOXVDMACMD_SYSMEMEL_NEXT(_pEl) (((_pEl)->fFlags & VBOXVDMACMD_SYSMEMEL_F_PAGELIST) ? \
+ ((PVBOXVDMACMD_SYSMEMEL)(((uint8_t*)(_pEl))+RT_OFFSETOF(VBOXVDMACMD_SYSMEMEL, phBuf[(_pEl)->cPages]))) \
+ : \
+ ((_pEl)+1)
+
+#define VBOXVDMACMD_DMA_BPB_TRANSFER_VRAMSYS_SYS2VRAM 0x00000001
+
+typedef struct VBOXVDMACMD_DMA_BPB_TRANSFER_VRAMSYS
+{
+ uint32_t cTransferPages;
+ uint32_t fFlags;
+ VBOXVIDEOOFFSET offVramBuf;
+ VBOXVDMACMD_SYSMEMEL FirstEl;
+} VBOXVDMACMD_DMA_BPB_TRANSFER_VRAMSYS, *PVBOXVDMACMD_DMA_BPB_TRANSFER_VRAMSYS;
+
+typedef struct VBOXVDMACMD_DMA_BPB_FILL
+{
+ VBOXVIDEOOFFSET offSurf;
+ uint32_t cbFillSize;
+ uint32_t u32FillPattern;
+} VBOXVDMACMD_DMA_BPB_FILL, *PVBOXVDMACMD_DMA_BPB_FILL;
+
+#define VBOXVDMA_CHILD_STATUS_F_CONNECTED 0x01
+#define VBOXVDMA_CHILD_STATUS_F_DISCONNECTED 0x02
+#define VBOXVDMA_CHILD_STATUS_F_ROTATED 0x04
+
+typedef struct VBOXVDMA_CHILD_STATUS
+{
+ uint32_t iChild;
+ uint8_t fFlags;
+ uint8_t u8RotationAngle;
+ uint16_t u16Reserved;
+} VBOXVDMA_CHILD_STATUS, *PVBOXVDMA_CHILD_STATUS;
+
+/* apply the aInfos are applied to all targets, the iTarget is ignored */
+#define VBOXVDMACMD_CHILD_STATUS_IRQ_F_APPLY_TO_ALL 0x00000001
+
+typedef struct VBOXVDMACMD_CHILD_STATUS_IRQ
+{
+ uint32_t cInfos;
+ uint32_t fFlags;
+ VBOXVDMA_CHILD_STATUS aInfos[1];
+} VBOXVDMACMD_CHILD_STATUS_IRQ, *PVBOXVDMACMD_CHILD_STATUS_IRQ;
+
+# pragma pack()
+#endif /* #ifdef VBOX_WITH_VDMA */
+
+#pragma pack(1)
+typedef struct VBOXVDMACMD_CHROMIUM_BUFFER
+{
+ VBOXVIDEOOFFSET offBuffer;
+ uint32_t cbBuffer;
+ uint32_t u32GuestData;
+ uint64_t u64GuestData;
+} VBOXVDMACMD_CHROMIUM_BUFFER, *PVBOXVDMACMD_CHROMIUM_BUFFER;
+
+typedef struct VBOXVDMACMD_CHROMIUM_CMD
+{
+ uint32_t cBuffers;
+ uint32_t u32Reserved;
+ VBOXVDMACMD_CHROMIUM_BUFFER aBuffers[1];
+} VBOXVDMACMD_CHROMIUM_CMD, *PVBOXVDMACMD_CHROMIUM_CMD;
+
+typedef enum
+{
+ VBOXVDMACMD_CHROMIUM_CTL_TYPE_UNKNOWN = 0,
+ VBOXVDMACMD_CHROMIUM_CTL_TYPE_CRHGSMI_SETUP,
+ VBOXVDMACMD_CHROMIUM_CTL_TYPE_SAVESTATE_BEGIN,
+ VBOXVDMACMD_CHROMIUM_CTL_TYPE_SAVESTATE_END,
+ VBOXVDMACMD_CHROMIUM_CTL_TYPE_CRHGSMI_SETUP_MAINCB,
+ VBOXVDMACMD_CHROMIUM_CTL_TYPE_CRCONNECT,
+ VBOXVDMACMD_CHROMIUM_CTL_TYPE_SIZEHACK = 0x7fffffff
+} VBOXVDMACMD_CHROMIUM_CTL_TYPE;
+
+typedef struct VBOXVDMACMD_CHROMIUM_CTL
+{
+ VBOXVDMACMD_CHROMIUM_CTL_TYPE enmType;
+ uint32_t cbCmd;
+} VBOXVDMACMD_CHROMIUM_CTL, *PVBOXVDMACMD_CHROMIUM_CTL;
+
+
+typedef struct PDMIDISPLAYVBVACALLBACKS *HCRHGSMICMDCOMPLETION;
+typedef DECLCALLBACK(int) FNCRHGSMICMDCOMPLETION(HCRHGSMICMDCOMPLETION hCompletion, PVBOXVDMACMD_CHROMIUM_CMD pCmd, int rc);
+typedef FNCRHGSMICMDCOMPLETION *PFNCRHGSMICMDCOMPLETION;
+
+/* tells whether 3D backend has some 3D overlay data displayed */
+typedef DECLCALLBACK(bool) FNCROGLHASDATA(void);
+typedef FNCROGLHASDATA *PFNCROGLHASDATA;
+
+/* same as PFNCROGLHASDATA, but for specific screen */
+typedef DECLCALLBACK(bool) FNCROGLHASDATAFORSCREEN(uint32_t i32ScreenID);
+typedef FNCROGLHASDATAFORSCREEN *PFNCROGLHASDATAFORSCREEN;
+
+/* callbacks chrogl gives to main */
+typedef struct CR_MAIN_INTERFACE
+{
+ PFNCROGLHASDATA pfnHasData;
+ PFNCROGLHASDATAFORSCREEN pfnHasDataForScreen;
+} CR_MAIN_INTERFACE;
+
+typedef struct VBOXVDMACMD_CHROMIUM_CTL_CRHGSMI_SETUP_MAINCB
+{
+ VBOXVDMACMD_CHROMIUM_CTL Hdr;
+ /*in*/
+ HCRHGSMICMDCOMPLETION hCompletion;
+ PFNCRHGSMICMDCOMPLETION pfnCompletion;
+ /*out*/
+ CR_MAIN_INTERFACE MainInterface;
+} VBOXVDMACMD_CHROMIUM_CTL_CRHGSMI_SETUP_MAINCB, *PVBOXVDMACMD_CHROMIUM_CTL_CRHGSMI_SETUP_MAINCB;
+
+typedef struct VBOXCRCON_SERVER *HVBOXCRCON_SERVER;
+typedef struct PDMIDISPLAYVBVACALLBACKS* HVBOXCRCON_CLIENT;
+
+typedef struct VBOXCRCON_3DRGN_CLIENT* HVBOXCRCON_3DRGN_CLIENT;
+typedef struct VBOXCRCON_3DRGN_ASYNCCLIENT* HVBOXCRCON_3DRGN_ASYNCCLIENT;
+
+/* server callbacks */
+/* submit chromium cmd */
+typedef DECLCALLBACK(int) FNVBOXCRCON_SVR_CRCMD(HVBOXCRCON_SERVER hServer, PVBOXVDMACMD_CHROMIUM_CMD pCmd, uint32_t cbCmd);
+typedef FNVBOXCRCON_SVR_CRCMD *PFNVBOXCRCON_SVR_CRCMD;
+
+/* submit chromium control cmd */
+typedef DECLCALLBACK(int) FNVBOXCRCON_SVR_CRCTL(HVBOXCRCON_SERVER hServer, PVBOXVDMACMD_CHROMIUM_CTL pCtl, uint32_t cbCmd);
+typedef FNVBOXCRCON_SVR_CRCTL *PFNVBOXCRCON_SVR_CRCTL;
+
+/* request 3D data.
+ * The protocol is the following:
+ * 1. if there is no 3D data displayed on screen, returns VINF_EOF immediately w/o calling any PFNVBOXCRCON_3DRGN_XXX callbacks
+ * 2. otherwise calls PFNVBOXCRCON_3DRGN_ONSUBMIT, submits the "regions get" request to the CrOpenGL server to process it asynchronously and returns VINF_SUCCESS
+ * 2.a on "regions get" request processing calls PFNVBOXCRCON_3DRGN_BEGIN,
+ * 2.b then PFNVBOXCRCON_3DRGN_REPORT zero or more times for each 3D region,
+ * 2.c and then PFNVBOXCRCON_3DRGN_END
+ * 3. returns VERR_XXX code on failure
+ * */
+typedef DECLCALLBACK(int) FNVBOXCRCON_SVR_3DRGN_GET(HVBOXCRCON_SERVER hServer, HVBOXCRCON_3DRGN_CLIENT hRgnClient, uint32_t idScreen);
+typedef FNVBOXCRCON_SVR_3DRGN_GET *PFNVBOXCRCON_SVR_3DRGN_GET;
+
+/* 3D Regions Client callbacks */
+/* called from the PFNVBOXCRCON_SVR_3DRGN_GET callback in case server has 3D data and is going to process the request asynchronously,
+ * see comments for PFNVBOXCRCON_SVR_3DRGN_GET above */
+typedef DECLCALLBACK(int) FNVBOXCRCON_3DRGN_ONSUBMIT(HVBOXCRCON_3DRGN_CLIENT hRgnClient, uint32_t idScreen, HVBOXCRCON_3DRGN_ASYNCCLIENT *phRgnAsyncClient);
+typedef FNVBOXCRCON_3DRGN_ONSUBMIT *PFNVBOXCRCON_3DRGN_ONSUBMIT;
+
+/* called from the "regions get" command processing thread, to indicate that the "regions get" is started.
+ * see comments for PFNVBOXCRCON_SVR_3DRGN_GET above */
+typedef DECLCALLBACK(int) FNVBOXCRCON_3DRGN_BEGIN(HVBOXCRCON_3DRGN_ASYNCCLIENT hRgnAsyncClient, uint32_t idScreen);
+typedef FNVBOXCRCON_3DRGN_BEGIN *PFNVBOXCRCON_3DRGN_BEGIN;
+
+/* called from the "regions get" command processing thread, to report a 3D region.
+ * see comments for PFNVBOXCRCON_SVR_3DRGN_GET above */
+typedef DECLCALLBACK(int) FNVBOXCRCON_3DRGN_REPORT(HVBOXCRCON_3DRGN_ASYNCCLIENT hRgnAsyncClient, uint32_t idScreen, void *pvData, uint32_t cbStride, const RTRECT *pRect);
+typedef FNVBOXCRCON_3DRGN_REPORT *PFNVBOXCRCON_3DRGN_REPORT;
+
+/* called from the "regions get" command processing thread, to indicate that the "regions get" is completed.
+ * see comments for PFNVBOXCRCON_SVR_3DRGN_GET above */
+typedef DECLCALLBACK(int) FNVBOXCRCON_3DRGN_END(HVBOXCRCON_3DRGN_ASYNCCLIENT hRgnAsyncClient, uint32_t idScreen);
+typedef FNVBOXCRCON_3DRGN_END *PFNVBOXCRCON_3DRGN_END;
+
+
+/* client callbacks */
+/* complete chromium cmd */
+typedef DECLCALLBACK(int) FNVBOXCRCON_CLT_CRCTL_COMPLETE(HVBOXCRCON_CLIENT hClient, PVBOXVDMACMD_CHROMIUM_CTL pCtl, int rc);
+typedef FNVBOXCRCON_CLT_CRCTL_COMPLETE *PFNVBOXCRCON_CLT_CRCTL_COMPLETE;
+
+/* complete chromium control cmd */
+typedef DECLCALLBACK(int) FNVBOXCRCON_CLT_CRCMD_COMPLETE(HVBOXCRCON_CLIENT hClient, PVBOXVDMACMD_CHROMIUM_CMD pCmd, int rc);
+typedef FNVBOXCRCON_CLT_CRCMD_COMPLETE *PFNVBOXCRCON_CLT_CRCMD_COMPLETE;
+
+typedef struct VBOXCRCON_SERVER_CALLBACKS
+{
+ HVBOXCRCON_SERVER hServer;
+ PFNVBOXCRCON_SVR_CRCMD pfnCrCmd;
+ PFNVBOXCRCON_SVR_CRCTL pfnCrCtl;
+ PFNVBOXCRCON_SVR_3DRGN_GET pfn3DRgnGet;
+} VBOXCRCON_SERVER_CALLBACKS, *PVBOXCRCON_SERVER_CALLBACKS;
+
+typedef struct VBOXCRCON_CLIENT_CALLBACKS
+{
+ HVBOXCRCON_CLIENT hClient;
+ PFNVBOXCRCON_CLT_CRCMD_COMPLETE pfnCrCmdComplete;
+ PFNVBOXCRCON_CLT_CRCTL_COMPLETE pfnCrCtlComplete;
+ PFNVBOXCRCON_3DRGN_ONSUBMIT pfn3DRgnOnSubmit;
+ PFNVBOXCRCON_3DRGN_BEGIN pfn3DRgnBegin;
+ PFNVBOXCRCON_3DRGN_REPORT pfn3DRgnReport;
+ PFNVBOXCRCON_3DRGN_END pfn3DRgnEnd;
+} VBOXCRCON_CLIENT_CALLBACKS, *PVBOXCRCON_CLIENT_CALLBACKS;
+
+/* issued by Main to establish connection between Main and CrOpenGL service */
+typedef struct VBOXVDMACMD_CHROMIUM_CTL_CRCONNECT
+{
+ VBOXVDMACMD_CHROMIUM_CTL Hdr;
+ /*input (filled by Client) :*/
+ /*class VMMDev*/void *pVMMDev;
+ VBOXCRCON_CLIENT_CALLBACKS ClientCallbacks;
+ /*output (filled by Server) :*/
+ VBOXCRCON_SERVER_CALLBACKS ServerCallbacks;
+} VBOXVDMACMD_CHROMIUM_CTL_CRCONNECT, *PVBOXVDMACMD_CHROMIUM_CTL_CRCONNECT;
+
+/* ring command buffer dr */
+#define VBOXCMDVBVA_STATE_SUBMITTED 1
+#define VBOXCMDVBVA_STATE_CANCELLED 2
+#define VBOXCMDVBVA_STATE_IN_PROGRESS 3
+/* the "completed" state is signalled via the ring buffer values */
+
+/* CrHgsmi command */
+#define VBOXCMDVBVA_OPTYPE_CRCMD 1
+/* blit command that does blitting of allocations identified by VRAM offset or host id
+ * for VRAM-offset ones the size and format are same as primary */
+#define VBOXCMDVBVA_OPTYPE_BLT 2
+/* flip */
+#define VBOXCMDVBVA_OPTYPE_FLIP 3
+/* ColorFill */
+#define VBOXCMDVBVA_OPTYPE_CLRFILL 4
+/* allocation paging transfer request */
+#define VBOXCMDVBVA_OPTYPE_PAGING_TRANSFER 5
+/* allocation paging fill request */
+#define VBOXCMDVBVA_OPTYPE_PAGING_FILL 6
+/* same as VBOXCMDVBVA_OPTYPE_NOP, but contains VBOXCMDVBVA_HDR data */
+#define VBOXCMDVBVA_OPTYPE_NOPCMD 7
+/* actual command is stored in guest system memory */
+#define VBOXCMDVBVA_OPTYPE_SYSMEMCMD 8
+/* complex command - i.e. can contain multiple commands
+ * i.e. the VBOXCMDVBVA_OPTYPE_COMPLEXCMD VBOXCMDVBVA_HDR is followed
+ * by one or more VBOXCMDVBVA_HDR commands.
+ * Each command's size is specified in it's VBOXCMDVBVA_HDR's u32FenceID field */
+#define VBOXCMDVBVA_OPTYPE_COMPLEXCMD 9
+
+/* nop - is a one-bit command. The buffer size to skip is determined by VBVA buffer size */
+#define VBOXCMDVBVA_OPTYPE_NOP 0x80
+
+/* u8Flags flags */
+/* transfer from RAM to Allocation */
+#define VBOXCMDVBVA_OPF_PAGING_TRANSFER_IN 0x80
+
+#define VBOXCMDVBVA_OPF_BLT_TYPE_SAMEDIM_A8R8G8B8 0
+#define VBOXCMDVBVA_OPF_BLT_TYPE_GENERIC_A8R8G8B8 1
+#define VBOXCMDVBVA_OPF_BLT_TYPE_OFFPRIMSZFMT_OR_ID 2
+
+#define VBOXCMDVBVA_OPF_BLT_TYPE_MASK 3
+
+
+#define VBOXCMDVBVA_OPF_CLRFILL_TYPE_GENERIC_A8R8G8B8 0
+
+#define VBOXCMDVBVA_OPF_CLRFILL_TYPE_MASK 1
+
+
+/* blit direction is from first operand to second */
+#define VBOXCMDVBVA_OPF_BLT_DIR_IN_2 0x10
+/* operand 1 contains host id */
+#define VBOXCMDVBVA_OPF_OPERAND1_ISID 0x20
+/* operand 2 contains host id */
+#define VBOXCMDVBVA_OPF_OPERAND2_ISID 0x40
+/* primary hint id is src */
+#define VBOXCMDVBVA_OPF_PRIMARY_HINT_SRC 0x80
+
+/* trying to make the header as small as possible,
+ * we'd have pretty few op codes actually, so 8bit is quite enough,
+ * we will be able to extend it in any way. */
+typedef struct VBOXCMDVBVA_HDR
+{
+ /* one VBOXCMDVBVA_OPTYPE_XXX, except NOP, see comments above */
+ uint8_t u8OpCode;
+ /* command-specific
+ * VBOXCMDVBVA_OPTYPE_CRCMD - must be null
+ * VBOXCMDVBVA_OPTYPE_BLT - OR-ed VBOXCMDVBVA_OPF_ALLOC_XXX flags
+ * VBOXCMDVBVA_OPTYPE_PAGING_TRANSFER - must be null
+ * VBOXCMDVBVA_OPTYPE_PAGING_FILL - must be null
+ * VBOXCMDVBVA_OPTYPE_NOPCMD - must be null
+ * VBOXCMDVBVA_OPTYPE_NOP - not applicable (as the entire VBOXCMDVBVA_HDR is not valid) */
+ uint8_t u8Flags;
+ /* one of VBOXCMDVBVA_STATE_XXX*/
+ volatile uint8_t u8State;
+ union
+ {
+ /* result, 0 on success, otherwise contains the failure code TBD */
+ int8_t i8Result;
+ uint8_t u8PrimaryID;
+ } u;
+ union
+ {
+ /* complex command (VBOXCMDVBVA_OPTYPE_COMPLEXCMD) element data */
+ struct
+ {
+ /* command length */
+ uint16_t u16CbCmdHost;
+ /* guest-specific data, host expects it to be NULL */
+ uint16_t u16CbCmdGuest;
+ } complexCmdEl;
+ /* DXGK DDI fence ID */
+ uint32_t u32FenceID;
+ } u2;
+} VBOXCMDVBVA_HDR;
+
+typedef uint32_t VBOXCMDVBVAOFFSET;
+typedef uint64_t VBOXCMDVBVAPHADDR;
+typedef uint32_t VBOXCMDVBVAPAGEIDX;
+
+typedef struct VBOXCMDVBVA_CRCMD_BUFFER
+{
+ uint32_t cbBuffer;
+ VBOXCMDVBVAOFFSET offBuffer;
+} VBOXCMDVBVA_CRCMD_BUFFER;
+
+typedef struct VBOXCMDVBVA_CRCMD_CMD
+{
+ uint32_t cBuffers;
+ VBOXCMDVBVA_CRCMD_BUFFER aBuffers[1];
+} VBOXCMDVBVA_CRCMD_CMD;
+
+typedef struct VBOXCMDVBVA_CRCMD
+{
+ VBOXCMDVBVA_HDR Hdr;
+ VBOXCMDVBVA_CRCMD_CMD Cmd;
+} VBOXCMDVBVA_CRCMD;
+
+typedef struct VBOXCMDVBVA_ALLOCINFO
+{
+ union
+ {
+ VBOXCMDVBVAOFFSET offVRAM;
+ uint32_t id;
+ } u;
+} VBOXCMDVBVA_ALLOCINFO;
+
+typedef struct VBOXCMDVBVA_ALLOCDESC
+{
+ VBOXCMDVBVA_ALLOCINFO Info;
+ uint16_t u16Width;
+ uint16_t u16Height;
+} VBOXCMDVBVA_ALLOCDESC;
+
+typedef struct VBOXCMDVBVA_RECT
+{
+ /** Coordinates of affected rectangle. */
+ int16_t xLeft;
+ int16_t yTop;
+ int16_t xRight;
+ int16_t yBottom;
+} VBOXCMDVBVA_RECT;
+
+typedef struct VBOXCMDVBVA_POINT
+{
+ int16_t x;
+ int16_t y;
+} VBOXCMDVBVA_POINT;
+
+typedef struct VBOXCMDVBVA_BLT_HDR
+{
+ VBOXCMDVBVA_HDR Hdr;
+ VBOXCMDVBVA_POINT Pos;
+} VBOXCMDVBVA_BLT_HDR;
+
+typedef struct VBOXCMDVBVA_BLT_PRIMARY
+{
+ VBOXCMDVBVA_BLT_HDR Hdr;
+ VBOXCMDVBVA_ALLOCINFO alloc;
+ /* the rects count is determined from the command size */
+ VBOXCMDVBVA_RECT aRects[1];
+} VBOXCMDVBVA_BLT_PRIMARY;
+
+typedef struct VBOXCMDVBVA_BLT_PRIMARY_GENERIC_A8R8G8B8
+{
+ VBOXCMDVBVA_BLT_HDR Hdr;
+ VBOXCMDVBVA_ALLOCDESC alloc;
+ /* the rects count is determined from the command size */
+ VBOXCMDVBVA_RECT aRects[1];
+} VBOXCMDVBVA_BLT_PRIMARY_GENERIC_A8R8G8B8;
+
+typedef struct VBOXCMDVBVA_BLT_OFFPRIMSZFMT_OR_ID
+{
+ VBOXCMDVBVA_BLT_HDR Hdr;
+ VBOXCMDVBVA_ALLOCINFO alloc;
+ uint32_t id;
+ /* the rects count is determined from the command size */
+ VBOXCMDVBVA_RECT aRects[1];
+} VBOXCMDVBVA_BLT_OFFPRIMSZFMT_OR_ID;
+
+typedef struct VBOXCMDVBVA_BLT_SAMEDIM_A8R8G8B8
+{
+ VBOXCMDVBVA_BLT_HDR Hdr;
+ VBOXCMDVBVA_ALLOCDESC alloc1;
+ VBOXCMDVBVA_ALLOCINFO info2;
+ /* the rects count is determined from the command size */
+ VBOXCMDVBVA_RECT aRects[1];
+} VBOXCMDVBVA_BLT_SAMEDIM_A8R8G8B8;
+
+typedef struct VBOXCMDVBVA_BLT_GENERIC_A8R8G8B8
+{
+ VBOXCMDVBVA_BLT_HDR Hdr;
+ VBOXCMDVBVA_ALLOCDESC alloc1;
+ VBOXCMDVBVA_ALLOCDESC alloc2;
+ /* the rects count is determined from the command size */
+ VBOXCMDVBVA_RECT aRects[1];
+} VBOXCMDVBVA_BLT_GENERIC_A8R8G8B8;
+
+#define VBOXCMDVBVA_SIZEOF_BLTSTRUCT_MAX (sizeof (VBOXCMDVBVA_BLT_GENERIC_A8R8G8B8))
+
+typedef struct VBOXCMDVBVA_FLIP
+{
+ VBOXCMDVBVA_HDR Hdr;
+ VBOXCMDVBVA_ALLOCINFO src;
+ VBOXCMDVBVA_RECT aRects[1];
+} VBOXCMDVBVA_FLIP;
+
+#define VBOXCMDVBVA_SIZEOF_FLIPSTRUCT_MIN (RT_OFFSETOF(VBOXCMDVBVA_FLIP, aRects))
+
+typedef struct VBOXCMDVBVA_CLRFILL_HDR
+{
+ VBOXCMDVBVA_HDR Hdr;
+ uint32_t u32Color;
+} VBOXCMDVBVA_CLRFILL_HDR;
+
+typedef struct VBOXCMDVBVA_CLRFILL_PRIMARY
+{
+ VBOXCMDVBVA_CLRFILL_HDR Hdr;
+ VBOXCMDVBVA_RECT aRects[1];
+} VBOXCMDVBVA_CLRFILL_PRIMARY;
+
+typedef struct VBOXCMDVBVA_CLRFILL_GENERIC_A8R8G8B8
+{
+ VBOXCMDVBVA_CLRFILL_HDR Hdr;
+ VBOXCMDVBVA_ALLOCDESC dst;
+ VBOXCMDVBVA_RECT aRects[1];
+} VBOXCMDVBVA_CLRFILL_GENERIC_A8R8G8B8;
+
+#define VBOXCMDVBVA_SIZEOF_CLRFILLSTRUCT_MAX (sizeof (VBOXCMDVBVA_CLRFILL_GENERIC_A8R8G8B8))
+
+#if 0
+#define VBOXCMDVBVA_SYSMEMEL_CPAGES_MAX 0x1000
+
+typedef struct VBOXCMDVBVA_SYSMEMEL
+{
+ uint32_t cPagesAfterFirst : 12;
+ uint32_t iPage1 : 20;
+ uint32_t iPage2;
+} VBOXCMDVBVA_SYSMEMEL;
+#endif
+
+typedef struct VBOXCMDVBVA_PAGING_TRANSFER_DATA
+{
+ /* for now can only contain offVRAM.
+ * paging transfer can NOT be initiated for allocations having host 3D object (hostID) associated */
+ VBOXCMDVBVA_ALLOCINFO Alloc;
+ VBOXCMDVBVAPAGEIDX aPageNumbers[1];
+} VBOXCMDVBVA_PAGING_TRANSFER_DATA;
+
+typedef struct VBOXCMDVBVA_PAGING_TRANSFER
+{
+ VBOXCMDVBVA_HDR Hdr;
+ VBOXCMDVBVA_PAGING_TRANSFER_DATA Data;
+} VBOXCMDVBVA_PAGING_TRANSFER;
+
+typedef struct VBOXCMDVBVA_PAGING_FILL
+{
+ VBOXCMDVBVA_HDR Hdr;
+ uint32_t u32CbFill;
+ uint32_t u32Pattern;
+ /* paging transfer can NOT be initiated for allocations having host 3D object (hostID) associated */
+ VBOXCMDVBVAOFFSET offVRAM;
+} VBOXCMDVBVA_PAGING_FILL;
+
+typedef struct VBOXCMDVBVA_SYSMEMCMD
+{
+ VBOXCMDVBVA_HDR Hdr;
+ VBOXCMDVBVAPHADDR phCmd;
+} VBOXCMDVBVA_SYSMEMCMD;
+
+#define VBOXCMDVBVACTL_TYPE_ENABLE 1
+#define VBOXCMDVBVACTL_TYPE_3DCTL 2
+#define VBOXCMDVBVACTL_TYPE_RESIZE 3
+
+typedef struct VBOXCMDVBVA_CTL
+{
+ uint32_t u32Type;
+ int32_t i32Result;
+} VBOXCMDVBVA_CTL;
+
+typedef struct VBOXCMDVBVA_CTL_ENABLE
+{
+ VBOXCMDVBVA_CTL Hdr;
+ VBVAENABLE Enable;
+} VBOXCMDVBVA_CTL_ENABLE;
+
+#define VBOXCMDVBVA_SCREENMAP_SIZE(_elType) ((VBOX_VIDEO_MAX_SCREENS + sizeof (_elType) - 1) / sizeof (_elType))
+#define VBOXCMDVBVA_SCREENMAP_DECL(_elType, _name) _elType _name[VBOXCMDVBVA_SCREENMAP_SIZE(_elType)]
+
+typedef struct VBOXCMDVBVA_RESIZE_ENTRY
+{
+ VBVAINFOSCREEN Screen;
+ VBOXCMDVBVA_SCREENMAP_DECL(uint32_t, aTargetMap);
+} VBOXCMDVBVA_RESIZE_ENTRY;
+
+typedef struct VBOXCMDVBVA_RESIZE
+{
+ VBOXCMDVBVA_RESIZE_ENTRY aEntries[1];
+} VBOXCMDVBVA_RESIZE;
+
+typedef struct VBOXCMDVBVA_CTL_RESIZE
+{
+ VBOXCMDVBVA_CTL Hdr;
+ VBOXCMDVBVA_RESIZE Resize;
+} VBOXCMDVBVA_CTL_RESIZE;
+
+#define VBOXCMDVBVA3DCTL_TYPE_CONNECT 1
+#define VBOXCMDVBVA3DCTL_TYPE_DISCONNECT 2
+#define VBOXCMDVBVA3DCTL_TYPE_CMD 3
+
+typedef struct VBOXCMDVBVA_3DCTL
+{
+ uint32_t u32Type;
+ uint32_t u32CmdClientId;
+} VBOXCMDVBVA_3DCTL;
+
+typedef struct VBOXCMDVBVA_3DCTL_CONNECT
+{
+ VBOXCMDVBVA_3DCTL Hdr;
+ uint32_t u32MajorVersion;
+ uint32_t u32MinorVersion;
+ uint64_t u64Pid;
+} VBOXCMDVBVA_3DCTL_CONNECT;
+
+typedef struct VBOXCMDVBVA_3DCTL_CMD
+{
+ VBOXCMDVBVA_3DCTL Hdr;
+ VBOXCMDVBVA_HDR Cmd;
+} VBOXCMDVBVA_3DCTL_CMD;
+
+typedef struct VBOXCMDVBVA_CTL_3DCTL_CMD
+{
+ VBOXCMDVBVA_CTL Hdr;
+ VBOXCMDVBVA_3DCTL_CMD Cmd;
+} VBOXCMDVBVA_CTL_3DCTL_CMD;
+
+typedef struct VBOXCMDVBVA_CTL_3DCTL_CONNECT
+{
+ VBOXCMDVBVA_CTL Hdr;
+ VBOXCMDVBVA_3DCTL_CONNECT Connect;
+} VBOXCMDVBVA_CTL_3DCTL_CONNECT;
+
+typedef struct VBOXCMDVBVA_CTL_3DCTL
+{
+ VBOXCMDVBVA_CTL Hdr;
+ VBOXCMDVBVA_3DCTL Ctl;
+} VBOXCMDVBVA_CTL_3DCTL;
+
+#pragma pack()
+
+
+#ifdef VBOXVDMA_WITH_VBVA
+# pragma pack(1)
+
+typedef struct VBOXVDMAVBVACMD
+{
+ HGSMIOFFSET offCmd;
+} VBOXVDMAVBVACMD;
+
+#pragma pack()
+#endif
+
+#endif
+
diff --git a/src/VBoxVideoErr.h b/src/VBoxVideoErr.h
new file mode 100644
index 0000000..81c6c46
--- /dev/null
+++ b/src/VBoxVideoErr.h
@@ -0,0 +1,64 @@
+/*
+ * Copyright (C) 2017 Oracle Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: Michael Thayer <michael.thayer@oracle.com>
+ */
+
+#ifndef __VBOX_ERR_H__
+#define __VBOX_ERR_H__
+
+/** @name VirtualBox error macros
+ * @{ */
+
+#define VINF_SUCCESS 0
+#define VERR_INVALID_PARAMETER (-2)
+#define VERR_INVALID_POINTER (-6)
+#define VERR_NO_MEMORY (-8)
+#define VERR_NOT_IMPLEMENTED (-12)
+#define VERR_INVALID_FUNCTION (-36)
+#define VERR_NOT_SUPPORTED (-37)
+#define VERR_TOO_MUCH_DATA (-42)
+#define VERR_NOT_FOUND (-78)
+#define VERR_INVALID_STATE (-79)
+#define VERR_OUT_OF_RESOURCES (-80)
+#define VERR_ALREADY_EXISTS (-105)
+#define VERR_INTERNAL_ERROR (-225)
+
+#define RT_SUCCESS_NP(rc) ( (int)(rc) >= VINF_SUCCESS )
+#define RT_SUCCESS(rc) ( likely(RT_SUCCESS_NP(rc)) )
+#define RT_FAILURE(rc) ( unlikely(!RT_SUCCESS_NP(rc)) )
+
+/** @} */
+
+/** @name VirtualBox assertions
+ * @{ */
+
+/* Unlike BUILD_BUG_ON(), these can be used outside of functions. */
+extern int vbox_assert_var[1];
+#define assert_compile(expr) \
+ extern int vbox_assert_var[1] __attribute__((__unused__)), \
+ vbox_assert_var[(expr) ? 1 : 0] __attribute__((__unused__))
+#define assert_compile_size(type, size) \
+ assert_compile(sizeof(type) == (size))
+
+/** @} */
+
+#endif
diff --git a/src/VBoxVideoGuest.h b/src/VBoxVideoGuest.h
new file mode 100644
index 0000000..ce6e563
--- /dev/null
+++ b/src/VBoxVideoGuest.h
@@ -0,0 +1,175 @@
+/*
+ * Copyright (C) 2006-2017 Oracle Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+
+#ifndef ___VBox_Graphics_VBoxVideoGuest_h___
+#define ___VBox_Graphics_VBoxVideoGuest_h___
+
+#include "VBoxVideoIPRT.h"
+#include "HGSMIBase.h"
+#include "VBoxVideo.h"
+
+RT_C_DECLS_BEGIN
+
+/**
+ * Structure grouping the context needed for sending graphics acceleration
+ * information to the host via VBVA. Each screen has its own VBVA buffer.
+ */
+typedef struct VBVABUFFERCONTEXT
+{
+ /** Offset of the buffer in the VRAM section for the screen */
+ uint32_t offVRAMBuffer;
+ /** Length of the buffer in bytes */
+ uint32_t cbBuffer;
+ /** This flag is set if we wrote to the buffer faster than the host could
+ * read it. */
+ bool fHwBufferOverflow;
+ /** The VBVA record that we are currently preparing for the host, NULL if
+ * none. */
+ struct VBVARECORD *pRecord;
+ /** Pointer to the VBVA buffer mapped into the current address space. Will
+ * be NULL if VBVA is not enabled. */
+ struct VBVABUFFER *pVBVA;
+} VBVABUFFERCONTEXT, *PVBVABUFFERCONTEXT;
+
+/** @name Base HGSMI APIs
+ * @{ */
+
+DECLHIDDEN(bool) VBoxHGSMIIsSupported(void);
+DECLHIDDEN(void) VBoxHGSMIGetBaseMappingInfo(uint32_t cbVRAM,
+ uint32_t *poffVRAMBaseMapping,
+ uint32_t *pcbMapping,
+ uint32_t *poffGuestHeapMemory,
+ uint32_t *pcbGuestHeapMemory,
+ uint32_t *poffHostFlags);
+DECLHIDDEN(int) VBoxHGSMIReportFlagsLocation(PHGSMIGUESTCOMMANDCONTEXT pCtx,
+ HGSMIOFFSET offLocation);
+DECLHIDDEN(int) VBoxHGSMISendCapsInfo(PHGSMIGUESTCOMMANDCONTEXT pCtx,
+ uint32_t fCaps);
+DECLHIDDEN(void) VBoxHGSMIGetHostAreaMapping(PHGSMIGUESTCOMMANDCONTEXT pCtx,
+ uint32_t cbVRAM,
+ uint32_t offVRAMBaseMapping,
+ uint32_t *poffVRAMHostArea,
+ uint32_t *pcbHostArea);
+DECLHIDDEN(int) VBoxHGSMISendHostCtxInfo(PHGSMIGUESTCOMMANDCONTEXT pCtx,
+ HGSMIOFFSET offVRAMFlagsLocation,
+ uint32_t fCaps,
+ uint32_t offVRAMHostArea,
+ uint32_t cbHostArea);
+DECLHIDDEN(int) VBoxQueryConfHGSMI(PHGSMIGUESTCOMMANDCONTEXT pCtx,
+ uint32_t u32Index, uint32_t *pulValue);
+DECLHIDDEN(int) VBoxQueryConfHGSMIDef(PHGSMIGUESTCOMMANDCONTEXT pCtx,
+ uint32_t u32Index, uint32_t u32DefValue, uint32_t *pulValue);
+DECLHIDDEN(int) VBoxHGSMIUpdatePointerShape(PHGSMIGUESTCOMMANDCONTEXT pCtx,
+ uint32_t fFlags,
+ uint32_t cHotX,
+ uint32_t cHotY,
+ uint32_t cWidth,
+ uint32_t cHeight,
+ uint8_t *pPixels,
+ uint32_t cbLength);
+DECLHIDDEN(int) VBoxHGSMICursorPosition(PHGSMIGUESTCOMMANDCONTEXT pCtx, bool fReportPosition, uint32_t x, uint32_t y,
+ uint32_t *pxHost, uint32_t *pyHost);
+
+/** @} */
+
+/** @name VBVA APIs
+ * @{ */
+DECLHIDDEN(bool) VBoxVBVAEnable(PVBVABUFFERCONTEXT pCtx,
+ PHGSMIGUESTCOMMANDCONTEXT pHGSMICtx,
+ struct VBVABUFFER *pVBVA, int32_t cScreen);
+DECLHIDDEN(void) VBoxVBVADisable(PVBVABUFFERCONTEXT pCtx,
+ PHGSMIGUESTCOMMANDCONTEXT pHGSMICtx,
+ int32_t cScreen);
+DECLHIDDEN(bool) VBoxVBVABufferBeginUpdate(PVBVABUFFERCONTEXT pCtx,
+ PHGSMIGUESTCOMMANDCONTEXT pHGSMICtx);
+DECLHIDDEN(void) VBoxVBVABufferEndUpdate(PVBVABUFFERCONTEXT pCtx);
+DECLHIDDEN(bool) VBoxVBVAWrite(PVBVABUFFERCONTEXT pCtx,
+ PHGSMIGUESTCOMMANDCONTEXT pHGSMICtx,
+ const void *pv, uint32_t cb);
+DECLHIDDEN(bool) VBoxVBVAOrderSupported(PVBVABUFFERCONTEXT pCtx, unsigned code);
+DECLHIDDEN(void) VBoxVBVASetupBufferContext(PVBVABUFFERCONTEXT pCtx,
+ uint32_t offVRAMBuffer,
+ uint32_t cbBuffer);
+
+/** @} */
+
+/** @name Modesetting APIs
+ * @{ */
+
+DECLHIDDEN(uint32_t) VBoxHGSMIGetMonitorCount(PHGSMIGUESTCOMMANDCONTEXT pCtx);
+DECLHIDDEN(uint32_t) VBoxVideoGetVRAMSize(void);
+DECLHIDDEN(bool) VBoxVideoAnyWidthAllowed(void);
+DECLHIDDEN(uint16_t) VBoxHGSMIGetScreenFlags(PHGSMIGUESTCOMMANDCONTEXT pCtx);
+
+struct VBVAINFOVIEW;
+/**
+ * Callback funtion called from @a VBoxHGSMISendViewInfo to initialise
+ * the @a VBVAINFOVIEW structure for each screen.
+ *
+ * @returns iprt status code
+ * @param pvData context data for the callback, passed to @a
+ * VBoxHGSMISendViewInfo along with the callback
+ * @param pInfo array of @a VBVAINFOVIEW structures to be filled in
+ * @todo explicitly pass the array size
+ */
+typedef DECLCALLBACK(int) FNHGSMIFILLVIEWINFO(void *pvData,
+ struct VBVAINFOVIEW *pInfo,
+ uint32_t cViews);
+/** Pointer to a FNHGSMIFILLVIEWINFO callback */
+typedef FNHGSMIFILLVIEWINFO *PFNHGSMIFILLVIEWINFO;
+
+DECLHIDDEN(int) VBoxHGSMISendViewInfo(PHGSMIGUESTCOMMANDCONTEXT pCtx,
+ uint32_t u32Count,
+ PFNHGSMIFILLVIEWINFO pfnFill,
+ void *pvData);
+DECLHIDDEN(void) VBoxVideoSetModeRegisters(uint16_t cWidth, uint16_t cHeight,
+ uint16_t cVirtWidth, uint16_t cBPP,
+ uint16_t fFlags,
+ uint16_t cx, uint16_t cy);
+DECLHIDDEN(bool) VBoxVideoGetModeRegisters(uint16_t *pcWidth,
+ uint16_t *pcHeight,
+ uint16_t *pcVirtWidth,
+ uint16_t *pcBPP,
+ uint16_t *pfFlags);
+DECLHIDDEN(void) VBoxVideoDisableVBE(void);
+DECLHIDDEN(void) VBoxHGSMIProcessDisplayInfo(PHGSMIGUESTCOMMANDCONTEXT pCtx,
+ uint32_t cDisplay,
+ int32_t cOriginX,
+ int32_t cOriginY,
+ uint32_t offStart,
+ uint32_t cbPitch,
+ uint32_t cWidth,
+ uint32_t cHeight,
+ uint16_t cBPP,
+ uint16_t fFlags);
+DECLHIDDEN(int) VBoxHGSMIUpdateInputMapping(PHGSMIGUESTCOMMANDCONTEXT pCtx, int32_t cOriginX, int32_t cOriginY,
+ uint32_t cWidth, uint32_t cHeight);
+DECLHIDDEN(int) VBoxHGSMIGetModeHints(PHGSMIGUESTCOMMANDCONTEXT pCtx,
+ unsigned cScreens, VBVAMODEHINT *paHints);
+
+/** @} */
+
+RT_C_DECLS_END
+
+#endif
+
diff --git a/src/VBoxVideoIPRT.h b/src/VBoxVideoIPRT.h
new file mode 100644
index 0000000..773044c
--- /dev/null
+++ b/src/VBoxVideoIPRT.h
@@ -0,0 +1,221 @@
+/* $Id: VBoxVideoIPRT.h 118373 2017-10-13 17:01:46Z michael $ */
+/*
+ * Copyright (C) 2017 Oracle Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM,
+ * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+ * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+ * USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/* In builds inside of the VirtualBox source tree we override the default
+ * VBoxVideoIPRT.h using -include, therefore this define must match the one
+ * there. */
+#ifndef ___VBox_Graphics_VBoxVideoIPRT_h
+#define ___VBox_Graphics_VBoxVideoIPRT_h
+
+# include "VBoxVideoErr.h"
+
+#ifndef __cplusplus
+typedef enum
+{
+ false = 0,
+ true
+} bool;
+# define RT_C_DECLS_BEGIN
+# define RT_C_DECLS_END
+#else
+# define RT_C_DECLS_BEGIN extern "C" {
+# define RT_C_DECLS_END }
+#endif
+
+#if defined(IN_XF86_MODULE) && !defined(NO_ANSIC)
+# ifdef __cplusplus
+/* xf86Module.h redefines this. */
+# define NULL 0
+# endif
+RT_C_DECLS_BEGIN
+# include "xf86_ansic.h"
+RT_C_DECLS_END
+#endif /* defined(IN_XF86_MODULE) && !defined(NO_ANSIC) */
+#define __STDC_LIMIT_MACROS /* define *INT*_MAX on C++ too. */
+#include "compiler.h" /* Can pull in <sdtint.h>. Must come after xf86_ansic.h on XFree86. */
+#include <X11/Xfuncproto.h>
+#include <stdint.h>
+#if defined(IN_XF86_MODULE) && !defined(NO_ANSIC)
+/* XFree86 did not have these. Not that I care much for micro-optimisations
+ * in most cases anyway. */
+# define _X_LIKELY(x) (x)
+# define _X_UNLIKELY(x) (x)
+# ifndef offsetof
+# define offsetof(type, member) ( (int)(uintptr_t)&( ((type *)(void *)0)->member) )
+# endif
+#else /* !(defined(IN_XF86_MODULE) && !defined(NO_ANSIC)) */
+# include <stdarg.h>
+# include <stddef.h>
+# include <string.h>
+#endif /* !(defined(IN_XF86_MODULE) && !defined(NO_ANSIC)) */
+
+RT_C_DECLS_BEGIN
+extern int RTASSERTVAR[1];
+RT_C_DECLS_END
+
+#define AssertCompile(expr) \
+ extern int RTASSERTVAR[1] __attribute__((__unused__)), \
+ RTASSERTVAR[(expr) ? 1 : 0] __attribute__((__unused__))
+#define AssertCompileSize(type, size) \
+ AssertCompile(sizeof(type) == (size))
+#define AssertPtrNullReturnVoid(a) do { } while(0)
+
+#if !defined(IN_XF86_MODULE) && defined(DEBUG)
+# include <assert.h>
+# define Assert assert
+# define AssertFailed() assert(0)
+# define AssertMsg(expr, msg) \
+ do { \
+ if (!(expr)) xf86ErrorF msg; \
+ assert((expr)); \
+ } while (0)
+# define AssertPtr assert
+# define AssertRC(expr) assert (!expr)
+#else
+# define Assert(expr) do { } while(0)
+# define AssertFailed() do { } while(0)
+# define AssertMsg(expr, msg) do { } while(0)
+# define AssertPtr(expr) do { } while(0)
+# define AssertRC(expr) do { } while(0)
+#endif
+
+#define DECLCALLBACK(type) type
+#define DECLCALLBACKMEMBER(type, name) type (* name)
+#if __GNUC__ >= 4
+# define DECLHIDDEN(type) __attribute__((visibility("hidden"))) type
+#else
+# define DECLHIDDEN(type) type
+#endif
+#define DECLINLINE(type) static __inline__ type
+
+#define _1K 1024
+#define ASMCompilerBarrier mem_barrier
+#define RT_BIT(bit) ( 1U << (bit) )
+#define RT_BOOL(Value) ( !!(Value) )
+#define RT_BZERO(pv, cb) do { memset((pv), 0, cb); } while (0)
+#define RT_CLAMP(Value, Min, Max) ( (Value) > (Max) ? (Max) : (Value) < (Min) ? (Min) : (Value) )
+#define RT_ELEMENTS(aArray) ( sizeof(aArray) / sizeof((aArray)[0]) )
+#define RTIOPORT unsigned short
+#define RT_NOREF(...) (void)(__VA_ARGS__)
+#define RT_OFFSETOF(type, member) offsetof(type, member)
+#define RT_ZERO(Obj) RT_BZERO(&(Obj), sizeof(Obj))
+#define VALID_PTR(ptr) ( (uintptr_t)(ptr) + 0x1000U >= 0x2000U )
+#ifndef INT16_C
+# define INT16_C(Value) (Value)
+#endif
+#ifndef UINT16_C
+# define UINT16_C(Value) (Value)
+#endif
+#ifndef INT32_C
+# define INT32_C(Value) (Value ## U)
+#endif
+#ifndef UINT32_C
+# define UINT32_C(Value) (Value ## U)
+#endif
+
+#define likely _X_LIKELY
+#define unlikely _X_UNLIKELY
+
+/**
+ * A point in a two dimentional coordinate system.
+ */
+typedef struct RTPOINT
+{
+ /** X coordinate. */
+ int32_t x;
+ /** Y coordinate. */
+ int32_t y;
+} RTPOINT;
+
+/**
+ * Rectangle data type, double point.
+ */
+typedef struct RTRECT
+{
+ /** left X coordinate. */
+ int32_t xLeft;
+ /** top Y coordinate. */
+ int32_t yTop;
+ /** right X coordinate. (exclusive) */
+ int32_t xRight;
+ /** bottom Y coordinate. (exclusive) */
+ int32_t yBottom;
+} RTRECT;
+
+/**
+ * Rectangle data type, point + size.
+ */
+typedef struct RTRECT2
+{
+ /** X coordinate.
+ * Unless stated otherwise, this is the top left corner. */
+ int32_t x;
+ /** Y coordinate.
+ * Unless stated otherwise, this is the top left corner. */
+ int32_t y;
+ /** The width.
+ * Unless stated otherwise, this is to the right of (x,y) and will not
+ * be a negative number. */
+ int32_t cx;
+ /** The height.
+ * Unless stated otherwise, this is down from (x,y) and will not be a
+ * negative number. */
+ int32_t cy;
+} RTRECT2;
+
+/**
+ * The size of a rectangle.
+ */
+typedef struct RTRECTSIZE
+{
+ /** The width (along the x-axis). */
+ uint32_t cx;
+ /** The height (along the y-axis). */
+ uint32_t cy;
+} RTRECTSIZE;
+
+/** @name Port I/O helpers
+ * @{ */
+
+/** Write an 8-bit value to an I/O port. */
+#define VBVO_PORT_WRITE_U8(Port, Value) \
+ outb(Port, Value)
+/** Write a 16-bit value to an I/O port. */
+#define VBVO_PORT_WRITE_U16(Port, Value) \
+ outw(Port, Value)
+/** Write a 32-bit value to an I/O port. */
+#define VBVO_PORT_WRITE_U32(Port, Value) \
+ outl(Port, Value)
+/** Read an 8-bit value from an I/O port. */
+#define VBVO_PORT_READ_U8(Port) \
+ inb(Port)
+/** Read a 16-bit value from an I/O port. */
+#define VBVO_PORT_READ_U16(Port) \
+ inw(Port)
+/** Read a 32-bit value from an I/O port. */
+#define VBVO_PORT_READ_U32(Port) \
+ inl(Port)
+
+/** @} */
+
+#endif
diff --git a/src/VBoxVideoVBE.h b/src/VBoxVideoVBE.h
new file mode 100644
index 0000000..78f8a89
--- /dev/null
+++ b/src/VBoxVideoVBE.h
@@ -0,0 +1,81 @@
+/*
+ * Copyright (C) 2006-2017 Oracle Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#ifndef ___VBox_Graphics_VBoxVideoVBE_h
+#define ___VBox_Graphics_VBoxVideoVBE_h
+
+/* GUEST <-> HOST Communication API */
+
+/** @todo FIXME: Either dynamicly ask host for this or put somewhere high in
+ * physical memory like 0xE0000000. */
+
+#define VBE_DISPI_BANK_ADDRESS 0xA0000
+#define VBE_DISPI_BANK_SIZE_KB 64
+
+#define VBE_DISPI_MAX_XRES 16384
+#define VBE_DISPI_MAX_YRES 16384
+#define VBE_DISPI_MAX_BPP 32
+
+#define VBE_DISPI_IOPORT_INDEX 0x01CE
+#define VBE_DISPI_IOPORT_DATA 0x01CF
+
+#define VBE_DISPI_IOPORT_DAC_WRITE_INDEX 0x03C8
+#define VBE_DISPI_IOPORT_DAC_DATA 0x03C9
+
+#define VBE_DISPI_INDEX_ID 0x0
+#define VBE_DISPI_INDEX_XRES 0x1
+#define VBE_DISPI_INDEX_YRES 0x2
+#define VBE_DISPI_INDEX_BPP 0x3
+#define VBE_DISPI_INDEX_ENABLE 0x4
+#define VBE_DISPI_INDEX_BANK 0x5
+#define VBE_DISPI_INDEX_VIRT_WIDTH 0x6
+#define VBE_DISPI_INDEX_VIRT_HEIGHT 0x7
+#define VBE_DISPI_INDEX_X_OFFSET 0x8
+#define VBE_DISPI_INDEX_Y_OFFSET 0x9
+#define VBE_DISPI_INDEX_VBOX_VIDEO 0xa
+#define VBE_DISPI_INDEX_FB_BASE_HI 0xb
+
+#define VBE_DISPI_ID0 0xB0C0
+#define VBE_DISPI_ID1 0xB0C1
+#define VBE_DISPI_ID2 0xB0C2
+#define VBE_DISPI_ID3 0xB0C3
+#define VBE_DISPI_ID4 0xB0C4
+
+#define VBE_DISPI_ID_VBOX_VIDEO 0xBE00
+/* The VBOX interface id. Indicates support for VBVA shared memory interface. */
+#define VBE_DISPI_ID_HGSMI 0xBE01
+#define VBE_DISPI_ID_ANYX 0xBE02
+
+#define VBE_DISPI_DISABLED 0x00
+#define VBE_DISPI_ENABLED 0x01
+#define VBE_DISPI_GETCAPS 0x02
+#define VBE_DISPI_8BIT_DAC 0x20
+/** @note this definition is a BOCHS legacy, used only in the video BIOS
+ * code and ignored by the emulated hardware. */
+#define VBE_DISPI_LFB_ENABLED 0x40
+#define VBE_DISPI_NOCLEARMEM 0x80
+
+#define VGA_PORT_HGSMI_HOST 0x3b0
+#define VGA_PORT_HGSMI_GUEST 0x3d0
+
+#endif /* !___VBox_Graphics_VBoxVideoVBE_h */
+
diff --git a/src/edid.c b/src/edid.c
new file mode 100644
index 0000000..fa88639
--- /dev/null
+++ b/src/edid.c
@@ -0,0 +1,166 @@
+/* $Id: edid.c 118361 2017-10-13 14:17:38Z michael $ */
+/** @file
+ *
+ * Linux Additions X11 graphics driver, EDID construction
+ */
+
+/*
+ * Copyright (C) 2006-2017 Oracle Corporation
+ *
+ * This code is based on drmmode_display.c from the X.Org xf86-video-intel
+ * driver with the following copyright notice:
+ *
+ * Copyright © 2007 Red Hat, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * Authors:
+ * Dave Airlie <airlied@redhat.com>
+ * Michael Thayer <michael.thayer@oracle.com>
+ */
+
+#include "misc.h"
+#include "xf86DDC.h"
+#include "xf86Crtc.h"
+#include "vboxvideo.h"
+
+enum { EDID_SIZE = 128 };
+
+const unsigned char g_acszEDIDBase[EDID_SIZE] =
+{
+ 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, /* header */
+ 0x58, 0x58, /* manufacturer (VBX) */
+ 0x00, 0x00, /* product code */
+ 0x00, 0x00,0x00, 0x00, /* serial number goes here */
+ 0x01, /* week of manufacture */
+ 0x00, /* year of manufacture */
+ 0x01, 0x03, /* EDID version */
+ 0x80, /* capabilities - digital */
+ 0x00, /* horiz. res in cm, zero for projectors */
+ 0x00, /* vert. res in cm */
+ 0x78, /* display gamma (120 == 2.2). Should we ask the host for this? */
+ 0xEE, /* features (standby, suspend, off, RGB, standard colour space,
+ * preferred timing mode) */
+ 0xEE, 0x91, 0xA3, 0x54, 0x4C, 0x99, 0x26, 0x0F, 0x50, 0x54,
+ /* chromaticity for standard colour space - should we ask the host? */
+ 0x00, 0x00, 0x00, /* no default timings */
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, /* no standard timings */
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* descriptor block 1 goes here */
+ 0x00, 0x00, 0x00, 0xFD, 0x00, /* descriptor block 2, monitor ranges */
+ 0x00, 0xC8, 0x00, 0xC8, 0x64, 0x00, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, /* 0-200Hz vertical, 0-200KHz horizontal, 1000MHz pixel clock */
+ 0x00, 0x00, 0x00, 0xFC, 0x00, /* descriptor block 3, monitor name */
+ 'V', 'B', 'O', 'X', ' ', 'm', 'o', 'n', 'i', 't', 'o', 'r', '\n',
+ 0x00, 0x00, 0x00, 0x10, 0x00, /* descriptor block 4: dummy data */
+ 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20,
+ 0x00, /* number of extensions */
+ 0x00 /* checksum goes here */
+};
+
+static void fillDescBlockTimings(unsigned char *pchDescBlock,
+ DisplayModePtr mode)
+{
+ struct detailed_timings timing;
+
+ timing.clock = mode->Clock * 1000;
+ timing.h_active = mode->HDisplay;
+ timing.h_blanking = mode->HTotal - mode->HDisplay;
+ timing.v_active = mode->VDisplay;
+ timing.v_blanking = mode->VTotal - mode->VDisplay;
+ timing.h_sync_off = mode->HSyncStart - mode->HDisplay;
+ timing.h_sync_width = mode->HSyncEnd - mode->HSyncStart;
+ timing.v_sync_off = mode->VSyncStart - mode->VDisplay;
+ timing.v_sync_width = mode->VSyncEnd - mode->VSyncStart;
+ pchDescBlock[0] = (timing.clock / 10000) & 0xff;
+ pchDescBlock[1] = (timing.clock / 10000) >> 8;
+ pchDescBlock[2] = timing.h_active & 0xff;
+ pchDescBlock[3] = timing.h_blanking & 0xff;
+ pchDescBlock[4] = (timing.h_active >> 4) & 0xf0;
+ pchDescBlock[4] |= (timing.h_blanking >> 8) & 0xf;
+ pchDescBlock[5] = timing.v_active & 0xff;
+ pchDescBlock[6] = timing.v_blanking & 0xff;
+ pchDescBlock[7] = (timing.v_active >> 4) & 0xf0;
+ pchDescBlock[7] |= (timing.v_blanking >> 8) & 0xf;
+ pchDescBlock[8] = timing.h_sync_off & 0xff;
+ pchDescBlock[9] = timing.h_sync_width & 0xff;
+ pchDescBlock[10] = (timing.v_sync_off << 4) & 0xf0;
+ pchDescBlock[10] |= timing.v_sync_width & 0xf;
+ pchDescBlock[11] = (timing.h_sync_off >> 2) & 0xC0;
+ pchDescBlock[11] |= (timing.h_sync_width >> 4) & 0x30;
+ pchDescBlock[11] |= (timing.v_sync_off >> 2) & 0xC;
+ pchDescBlock[11] |= (timing.v_sync_width >> 4) & 0x3;
+ pchDescBlock[12] = pchDescBlock[13] = pchDescBlock[14]
+ = pchDescBlock[15] = pchDescBlock[16]
+ = pchDescBlock[17] = 0;
+}
+
+
+static void setEDIDChecksum(unsigned char *pch)
+{
+ unsigned i, sum = 0;
+ for (i = 0; i < EDID_SIZE - 1; ++i)
+ sum += pch[i];
+ pch[EDID_SIZE - 1] = (0x100 - (sum & 0xFF)) & 0xFF;
+}
+
+
+/**
+ * Construct an EDID for an output given a preferred mode. The main reason for
+ * doing this is to confound gnome-settings-deamon which tries to reset the
+ * last mode configuration if the same monitors are plugged in again, which is
+ * a reasonable thing to do but not what we want in a VM. We evily store
+ * the (empty) raw EDID data at the end of the structure so that it gets
+ * freed automatically along with the structure.
+ */
+Bool VBOXEDIDSet(xf86OutputPtr output, DisplayModePtr pmode)
+{
+ unsigned char *pch, *pchEDID;
+ xf86MonPtr pEDIDMon;
+
+ pch = calloc(1, sizeof(xf86Monitor) + EDID_SIZE);
+ if (!pch)
+ {
+ xf86DrvMsg(output->scrn->scrnIndex, X_ERROR,
+ "Can't allocate memory for EDID structure.\n");
+ return FALSE;
+ }
+ pchEDID = pch + sizeof(xf86Monitor);
+ memcpy(pchEDID, g_acszEDIDBase, EDID_SIZE);
+ pchEDID[12] = pmode->HDisplay & 0xff;
+ pchEDID[13] = pmode->HDisplay >> 8;
+ pchEDID[14] = pmode->VDisplay & 0xff;
+ pchEDID[15] = pmode->VDisplay >> 8;
+ fillDescBlockTimings(pchEDID + 54, pmode);
+ setEDIDChecksum(pchEDID);
+ pEDIDMon = xf86InterpretEDID(output->scrn->scrnIndex, pchEDID);
+ if (!pEDIDMon)
+ {
+ free(pch);
+ return FALSE;
+ }
+ memcpy(pch, pEDIDMon, sizeof(xf86Monitor));
+ free(pEDIDMon);
+ pEDIDMon = (xf86MonPtr)pch;
+ xf86OutputSetEDID(output, pEDIDMon);
+ return TRUE;
+}
diff --git a/src/getmode.c b/src/getmode.c
new file mode 100644
index 0000000..72947fe
--- /dev/null
+++ b/src/getmode.c
@@ -0,0 +1,318 @@
+/* $Id: getmode.c 118345 2017-10-12 18:18:01Z michael $ */
+/** @file
+ * VirtualBox X11 Additions graphics driver dynamic video mode functions.
+ */
+
+/*
+ * Copyright (C) 2006-2017 Oracle Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM,
+ * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+ * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+ * USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#include "vboxvideo.h"
+
+#define NEED_XF86_TYPES
+#include "xf86.h"
+
+#ifdef XORG_7X
+# include <stdio.h>
+# include <stdlib.h>
+# include <string.h>
+#endif
+
+#ifdef VBOXVIDEO_13
+# ifdef RT_OS_LINUX
+# include <linux/input.h>
+# ifndef EVIOCGRAB
+# define EVIOCGRAB _IOW('E', 0x90, int)
+# endif
+# ifndef KEY_SWITCHVIDEOMODE
+# define KEY_SWITCHVIDEOMODE 227
+# endif
+# include <dirent.h>
+# include <errno.h>
+# include <fcntl.h>
+# include <unistd.h>
+# endif /* RT_OS_LINUX */
+#endif /* VBOXVIDEO_13 */
+
+/**************************************************************************
+* Main functions *
+**************************************************************************/
+
+/**
+ * Fills a display mode M with a built-in mode of name pszName and dimensions
+ * cx and cy.
+ */
+static void vboxFillDisplayMode(ScrnInfoPtr pScrn, DisplayModePtr m,
+ const char *pszName, unsigned cx, unsigned cy)
+{
+ VBOXPtr pVBox = pScrn->driverPrivate;
+ char szName[256];
+ DisplayModePtr pPrev = m->prev;
+ DisplayModePtr pNext = m->next;
+
+ if (!pszName)
+ {
+ sprintf(szName, "%ux%u", cx, cy);
+ pszName = szName;
+ }
+ TRACE_LOG("pszName=%s, cx=%u, cy=%u\n", pszName, cx, cy);
+ if (m->name)
+ free((void*)m->name);
+ memset(m, '\0', sizeof(*m));
+ m->prev = pPrev;
+ m->next = pNext;
+ m->status = MODE_OK;
+ m->type = M_T_BUILTIN;
+ /* Older versions of VBox only support screen widths which are a multiple
+ * of 8 */
+ if (pVBox->fAnyX)
+ m->HDisplay = cx;
+ else
+ m->HDisplay = cx & ~7;
+ m->HSyncStart = m->HDisplay + 2;
+ m->HSyncEnd = m->HDisplay + 4;
+ m->HTotal = m->HDisplay + 6;
+ m->VDisplay = cy;
+ m->VSyncStart = m->VDisplay + 2;
+ m->VSyncEnd = m->VDisplay + 4;
+ m->VTotal = m->VDisplay + 6;
+ m->Clock = m->HTotal * m->VTotal * 60 / 1000; /* kHz */
+ m->name = xnfstrdup(pszName);
+}
+
+/**
+ * Allocates an empty display mode and links it into the doubly linked list of
+ * modes pointed to by pScrn->modes. Returns a pointer to the newly allocated
+ * memory.
+ */
+static DisplayModePtr vboxAddEmptyScreenMode(ScrnInfoPtr pScrn)
+{
+ DisplayModePtr pMode = xnfcalloc(sizeof(DisplayModeRec), 1);
+
+ TRACE_ENTRY();
+ if (!pScrn->modes)
+ {
+ pScrn->modes = pMode;
+ pMode->next = pMode;
+ pMode->prev = pMode;
+ }
+ else
+ {
+ pMode->next = pScrn->modes;
+ pMode->prev = pScrn->modes->prev;
+ pMode->next->prev = pMode;
+ pMode->prev->next = pMode;
+ }
+ return pMode;
+}
+
+/**
+ * Create display mode entries in the screen information structure for each
+ * of the graphics modes that we wish to support, that is:
+ * - A dynamic mode in first place which will be updated by the RandR code.
+ * - Any modes that the user requested in xorg.conf/XFree86Config.
+ */
+void vboxAddModes(ScrnInfoPtr pScrn)
+{
+ unsigned cx = 0;
+ unsigned cy = 0;
+ unsigned i;
+ DisplayModePtr pMode;
+
+ /* Add two dynamic mode entries. When we receive a new size hint we will
+ * update whichever of these is not current. */
+ pMode = vboxAddEmptyScreenMode(pScrn);
+ vboxFillDisplayMode(pScrn, pMode, NULL, 800, 600);
+ pMode = vboxAddEmptyScreenMode(pScrn);
+ vboxFillDisplayMode(pScrn, pMode, NULL, 800, 600);
+ /* Add any modes specified by the user. We assume here that the mode names
+ * reflect the mode sizes. */
+ for (i = 0; pScrn->display->modes && pScrn->display->modes[i]; i++)
+ {
+ if (sscanf(pScrn->display->modes[i], "%ux%u", &cx, &cy) == 2)
+ {
+ pMode = vboxAddEmptyScreenMode(pScrn);
+ vboxFillDisplayMode(pScrn, pMode, pScrn->display->modes[i], cx, cy);
+ }
+ }
+}
+
+/** Set the initial values for the guest screen size hints to standard values
+ * in case nothing else is available. */
+void VBoxInitialiseSizeHints(ScrnInfoPtr pScrn)
+{
+ VBOXPtr pVBox = VBOXGetRec(pScrn);
+ unsigned i;
+
+ for (i = 0; i < pVBox->cScreens; ++i)
+ {
+ pVBox->pScreens[i].aPreferredSize.cx = 800;
+ pVBox->pScreens[i].aPreferredSize.cy = 600;
+ pVBox->pScreens[i].afConnected = true;
+ }
+ /* Set up the first mode correctly to match the requested initial mode. */
+ pScrn->modes->HDisplay = pVBox->pScreens[0].aPreferredSize.cx;
+ pScrn->modes->VDisplay = pVBox->pScreens[0].aPreferredSize.cy;
+}
+
+static Bool useHardwareCursor(uint32_t fCursorCapabilities)
+{
+ if (fCursorCapabilities & VBOX_VBVA_CURSOR_CAPABILITY_HARDWARE)
+ return true;
+ return false;
+}
+
+static void compareAndMaybeSetUseHardwareCursor(VBOXPtr pVBox, uint32_t fCursorCapabilities, Bool *pfChanged, Bool fSet)
+{
+ if (pVBox->fUseHardwareCursor != useHardwareCursor(fCursorCapabilities))
+ *pfChanged = true;
+ if (fSet)
+ pVBox->fUseHardwareCursor = useHardwareCursor(fCursorCapabilities);
+}
+
+#define COMPARE_AND_MAYBE_SET(pDest, src, pfChanged, fSet) \
+do { \
+ if (*(pDest) != (src)) \
+ { \
+ if (fSet) \
+ *(pDest) = (src); \
+ *(pfChanged) = true; \
+ } \
+} while(0)
+
+/** Read in information about the most recent size hints and cursor
+ * capabilities requested for the guest screens from HGSMI. */
+void vbvxReadSizesAndCursorIntegrationFromHGSMI(ScrnInfoPtr pScrn, Bool *pfNeedUpdate)
+{
+ VBOXPtr pVBox = VBOXGetRec(pScrn);
+ int rc;
+ unsigned i;
+ Bool fChanged = false;
+ uint32_t fCursorCapabilities;
+
+ if (!pVBox->fHaveHGSMIModeHints)
+ return;
+ rc = VBoxHGSMIGetModeHints(&pVBox->guestCtx, pVBox->cScreens, pVBox->paVBVAModeHints);
+ AssertMsg(rc == VINF_SUCCESS, ("VBoxHGSMIGetModeHints failed, rc=%d.\n", rc));
+ for (i = 0; i < pVBox->cScreens; ++i)
+ if (pVBox->paVBVAModeHints[i].magic == VBVAMODEHINT_MAGIC)
+ {
+ COMPARE_AND_MAYBE_SET(&pVBox->pScreens[i].aPreferredSize.cx, pVBox->paVBVAModeHints[i].cx & 0x8fff, &fChanged, true);
+ COMPARE_AND_MAYBE_SET(&pVBox->pScreens[i].aPreferredSize.cy, pVBox->paVBVAModeHints[i].cy & 0x8fff, &fChanged, true);
+ COMPARE_AND_MAYBE_SET(&pVBox->pScreens[i].afConnected, RT_BOOL(pVBox->paVBVAModeHints[i].fEnabled), &fChanged, true);
+ COMPARE_AND_MAYBE_SET(&pVBox->pScreens[i].aPreferredLocation.x, (int32_t)pVBox->paVBVAModeHints[i].dx & 0x8fff, &fChanged,
+ true);
+ COMPARE_AND_MAYBE_SET(&pVBox->pScreens[i].aPreferredLocation.y, (int32_t)pVBox->paVBVAModeHints[i].dy & 0x8fff, &fChanged,
+ true);
+ if (pVBox->paVBVAModeHints[i].dx != ~(uint32_t)0 && pVBox->paVBVAModeHints[i].dy != ~(uint32_t)0)
+ COMPARE_AND_MAYBE_SET(&pVBox->pScreens[i].afHaveLocation, true, &fChanged, true);
+ else
+ COMPARE_AND_MAYBE_SET(&pVBox->pScreens[i].afHaveLocation, false, &fChanged, true);
+ }
+ rc = VBoxQueryConfHGSMI(&pVBox->guestCtx, VBOX_VBVA_CONF32_CURSOR_CAPABILITIES, &fCursorCapabilities);
+ AssertMsg(rc == VINF_SUCCESS, ("Getting VBOX_VBVA_CONF32_CURSOR_CAPABILITIES failed, rc=%d.\n", rc));
+ compareAndMaybeSetUseHardwareCursor(pVBox, fCursorCapabilities, &fChanged, true);
+ if (pfNeedUpdate != NULL && fChanged)
+ *pfNeedUpdate = true;
+}
+
+#undef COMPARE_AND_MAYBE_SET
+
+#ifdef VBOXVIDEO_13
+# ifdef RT_OS_LINUX
+/** We have this for two purposes: one is to ensure that the X server is woken
+ * up when we get a video ACPI event. Two is to grab ACPI video events to
+ * prevent gnome-settings-daemon from seeing them, as older versions ignored
+ * the time stamp and handled them at the wrong time. */
+static void acpiEventHandler(int fd, void *pvData)
+{
+ struct input_event event;
+ ssize_t rc;
+ RT_NOREF(pvData);
+
+ do
+ rc = read(fd, &event, sizeof(event));
+ while (rc > 0 || (rc == -1 && errno == EINTR));
+ /* Why do they return EAGAIN instead of zero bytes read like everyone else does? */
+ AssertMsg(rc != -1 || errno == EAGAIN, ("Reading ACPI input event failed.\n"));
+}
+
+void vbvxSetUpLinuxACPI(ScreenPtr pScreen)
+{
+ VBOXPtr pVBox = VBOXGetRec(xf86Screens[pScreen->myNum]);
+ struct dirent *pDirent;
+ DIR *pDir;
+ int fd = -1;
+
+ if (pVBox->fdACPIDevices != -1 || pVBox->hACPIEventHandler != NULL)
+ FatalError("ACPI input file descriptor not initialised correctly.\n");
+ pDir = opendir("/dev/input");
+ if (pDir == NULL)
+ return;
+ for (pDirent = readdir(pDir); pDirent != NULL; pDirent = readdir(pDir))
+ {
+ if (strncmp(pDirent->d_name, "event", sizeof("event") - 1) == 0)
+ {
+#define BITS_PER_BLOCK (sizeof(unsigned long) * 8)
+ char szFile[64] = "/dev/input/";
+ char szDevice[64] = "";
+ unsigned long afKeys[KEY_MAX / BITS_PER_BLOCK];
+
+ strncat(szFile, pDirent->d_name, sizeof(szFile) - sizeof("/dev/input/"));
+ if (fd != -1)
+ close(fd);
+ fd = open(szFile, O_RDONLY | O_NONBLOCK);
+ if ( fd == -1
+ || ioctl(fd, EVIOCGNAME(sizeof(szDevice)), szDevice) == -1
+ || strcmp(szDevice, "Video Bus") != 0)
+ continue;
+ if ( ioctl(fd, EVIOCGBIT(EV_KEY, sizeof(afKeys)), afKeys) == -1
+ || (( afKeys[KEY_SWITCHVIDEOMODE / BITS_PER_BLOCK]
+ >> KEY_SWITCHVIDEOMODE % BITS_PER_BLOCK) & 1) == 0)
+ break;
+ if (ioctl(fd, EVIOCGRAB, (void *)1) != 0)
+ break;
+ pVBox->hACPIEventHandler
+ = xf86AddGeneralHandler(fd, acpiEventHandler, pScreen);
+ if (pVBox->hACPIEventHandler == NULL)
+ break;
+ pVBox->fdACPIDevices = fd;
+ fd = -1;
+ break;
+#undef BITS_PER_BLOCK
+ }
+ }
+ if (fd != -1)
+ close(fd);
+ closedir(pDir);
+}
+
+void vbvxCleanUpLinuxACPI(ScreenPtr pScreen)
+{
+ VBOXPtr pVBox = VBOXGetRec(xf86Screens[pScreen->myNum]);
+ if (pVBox->fdACPIDevices != -1)
+ close(pVBox->fdACPIDevices);
+ pVBox->fdACPIDevices = -1;
+ xf86RemoveGeneralHandler(pVBox->hACPIEventHandler);
+ pVBox->hACPIEventHandler = NULL;
+}
+# endif /* RT_OS_LINUX */
+#endif /* VBOXVIDEO_13 */
diff --git a/src/helpers.c b/src/helpers.c
new file mode 100644
index 0000000..ed35bbf
--- /dev/null
+++ b/src/helpers.c
@@ -0,0 +1,81 @@
+/*
+ * Copyright (C) 2014-2017 Oracle Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM,
+ * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+ * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+ * USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#include "vboxvideo.h"
+#include "os.h"
+#include "propertyst.h"
+#include "windowstr.h"
+#include "xf86.h"
+#include <X11/Xatom.h>
+#ifdef XORG_7X
+# include <string.h>
+#endif
+#include "VBoxVideoErr.h"
+
+VBOXPtr vbvxGetRec(ScrnInfoPtr pScrn)
+{
+ return ((VBOXPtr)pScrn->driverPrivate);
+}
+
+int vbvxGetIntegerPropery(ScrnInfoPtr pScrn, char *pszName, size_t *pcData, int32_t **ppaData)
+{
+ Atom atom;
+ PropertyPtr prop;
+
+ /* We can get called early, before the root window is created. */
+ if (!ROOT_WINDOW(pScrn))
+ return VERR_NOT_FOUND;
+ atom = MakeAtom(pszName, strlen(pszName), TRUE);
+ if (atom == BAD_RESOURCE)
+ return VERR_NOT_FOUND;
+ for (prop = wUserProps(ROOT_WINDOW(pScrn));
+ prop != NULL && prop->propertyName != atom; prop = prop->next);
+ if (prop == NULL)
+ return VERR_NOT_FOUND;
+ if (prop->type != XA_INTEGER || prop->format != 32)
+ return VERR_NOT_FOUND;
+ *pcData = prop->size;
+ *ppaData = (int32_t *)prop->data;
+ return VINF_SUCCESS;
+}
+
+void vbvxSetIntegerPropery(ScrnInfoPtr pScrn, char *pszName, size_t cData, int32_t *paData, Bool fSendEvent)
+{
+ Atom property_name;
+
+ property_name = MakeAtom(pszName, strlen(pszName), TRUE);
+ AssertMsg(property_name != BAD_RESOURCE, ("Failed to set atom \"%s\"\n", pszName));
+ ChangeWindowProperty(ROOT_WINDOW(pScrn), property_name, XA_INTEGER, 32, PropModeReplace, cData, paData, fSendEvent);
+}
+
+void vbvxReprobeCursor(ScrnInfoPtr pScrn)
+{
+ if (ROOT_WINDOW(pScrn) == NULL)
+ return;
+#ifdef XF86_SCRN_INTERFACE
+ pScrn->EnableDisableFBAccess(pScrn, FALSE);
+ pScrn->EnableDisableFBAccess(pScrn, TRUE);
+#else
+ pScrn->EnableDisableFBAccess(pScrn->scrnIndex, FALSE);
+ pScrn->EnableDisableFBAccess(pScrn->scrnIndex, TRUE);
+#endif
+}
diff --git a/src/hgsmimemalloc.c b/src/hgsmimemalloc.c
new file mode 100644
index 0000000..e689e20
--- /dev/null
+++ b/src/hgsmimemalloc.c
@@ -0,0 +1,106 @@
+/* $Id: hgsmimemalloc.c 118341 2017-10-12 14:07:17Z michael $ */
+/*
+ * Copyright (C) 2017 Oracle Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM,
+ * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+ * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+ * USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/*
+ * Memory allocator
+ * ----------------
+ *
+ * Implementation
+ * --------------
+ *
+ * Since the X.Org driver is single threaded and works using an allocate,
+ * submit and free pattern, we replace the generic allocator with a simple
+ * Boolean. Need more be said?
+ */
+
+#include <VBoxVideoIPRT.h>
+#include <HGSMIMemAlloc.h>
+#include <HGSMI.h>
+
+int HGSMIMAInit(HGSMIMADATA *pMA, const HGSMIAREA *pArea,
+ HGSMIOFFSET *paDescriptors, uint32_t cDescriptors, HGSMISIZE cbMaxBlock,
+ const HGSMIENV *pEnv)
+{
+ (void)paDescriptors;
+ (void)cDescriptors;
+ (void)cbMaxBlock;
+ (void)pEnv;
+ if (!(pArea->cbArea < UINT32_C(0x80000000)))
+ return VERR_INVALID_PARAMETER;
+ if (!(pArea->cbArea >= HGSMI_MA_BLOCK_SIZE_MIN))
+ return VERR_INVALID_PARAMETER;
+
+ pMA->area = *pArea;
+ pMA->fAllocated = false;
+ return VINF_SUCCESS;
+}
+
+void HGSMIMAUninit(HGSMIMADATA *pMA)
+{
+ (void)pMA;
+}
+
+static HGSMIOFFSET HGSMIMAPointerToOffset(const HGSMIMADATA *pMA, const void *pv)
+{
+ if (HGSMIAreaContainsPointer(&pMA->area, pv))
+ {
+ return HGSMIPointerToOffset(&pMA->area, pv);
+ }
+
+ AssertFailed();
+ return HGSMIOFFSET_VOID;
+}
+
+static void *HGSMIMAOffsetToPointer(const HGSMIMADATA *pMA, HGSMIOFFSET off)
+{
+ if (HGSMIAreaContainsOffset(&pMA->area, off))
+ {
+ return HGSMIOffsetToPointer(&pMA->area, off);
+ }
+
+ AssertFailed();
+ return NULL;
+}
+
+void *HGSMIMAAlloc(HGSMIMADATA *pMA, HGSMISIZE cb)
+{
+ (void)cb;
+ if (pMA->fAllocated)
+ return NULL;
+ HGSMIOFFSET off = pMA->area.offBase;
+ return HGSMIMAOffsetToPointer(pMA, off);
+ pMA->fAllocated = true;
+}
+
+void HGSMIMAFree(HGSMIMADATA *pMA, void *pv)
+{
+ HGSMIOFFSET off = HGSMIMAPointerToOffset(pMA, pv);
+ if (off != HGSMIOFFSET_VOID)
+ {
+ pMA->fAllocated = false;
+ }
+ else
+ {
+ AssertFailed();
+ }
+}
diff --git a/src/pointer.c b/src/pointer.c
new file mode 100644
index 0000000..0b01ab4
--- /dev/null
+++ b/src/pointer.c
@@ -0,0 +1,493 @@
+/* $Id: pointer.c 118361 2017-10-13 14:17:38Z michael $ */
+/** @file
+ * VirtualBox X11 Additions graphics driver utility functions
+ */
+
+/*
+ * Copyright (C) 2006-2017 Oracle Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM,
+ * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+ * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+ * USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#ifndef PCIACCESS
+# include "xf86Pci.h"
+# include <Pci.h>
+#endif
+
+#include "xf86.h"
+#define NEED_XF86_TYPES
+#include "compiler.h"
+#include "cursorstr.h"
+#include "servermd.h"
+
+#include "vboxvideo.h"
+
+#ifdef XORG_7X
+# include <stdlib.h>
+# include <string.h>
+#endif
+
+#define VBOX_MAX_CURSOR_WIDTH 64
+#define VBOX_MAX_CURSOR_HEIGHT 64
+
+/**************************************************************************
+* Debugging functions and macros *
+**************************************************************************/
+
+/* #define DEBUG_POINTER */
+
+#ifdef DEBUG
+# define PUT_PIXEL(c) ErrorF ("%c", c)
+#else /* DEBUG_VIDEO not defined */
+# define PUT_PIXEL(c) do { } while(0)
+#endif /* DEBUG_VIDEO not defined */
+
+/** Macro to printf an error message and return from a function */
+#define RETERROR(scrnIndex, RetVal, ...) \
+ do \
+ { \
+ xf86DrvMsg(scrnIndex, X_ERROR, __VA_ARGS__); \
+ return RetVal; \
+ } \
+ while (0)
+
+/** Structure to pass cursor image data between realise_cursor() and
+ * load_cursor_image(). The members match the parameters to
+ * @a VBoxHGSMIUpdatePointerShape(). */
+struct vboxCursorImage
+{
+ uint32_t fFlags;
+ uint32_t cHotX;
+ uint32_t cHotY;
+ uint32_t cWidth;
+ uint32_t cHeight;
+ uint8_t *pPixels;
+ uint32_t cbLength;
+};
+
+#ifdef DEBUG_POINTER
+static void
+vbox_show_shape(unsigned short w, unsigned short h, CARD32 bg, unsigned char *image)
+{
+ size_t x, y;
+ unsigned short pitch;
+ CARD32 *color;
+ unsigned char *mask;
+ size_t sizeMask;
+
+ image += sizeof(struct vboxCursorImage);
+ mask = image;
+ pitch = (w + 7) / 8;
+ sizeMask = (pitch * h + 3) & ~3;
+ color = (CARD32 *)(image + sizeMask);
+
+ TRACE_ENTRY();
+ for (y = 0; y < h; ++y, mask += pitch, color += w)
+ {
+ for (x = 0; x < w; ++x)
+ {
+ if (mask[x / 8] & (1 << (7 - (x % 8))))
+ ErrorF (" ");
+ else
+ {
+ CARD32 c = color[x];
+ if (c == bg)
+ ErrorF("Y");
+ else
+ ErrorF("X");
+ }
+ }
+ ErrorF("\n");
+ }
+}
+#endif
+
+/**************************************************************************
+* Main functions *
+**************************************************************************/
+
+void vbvxCursorTerm(VBOXPtr pVBox)
+{
+ TRACE_ENTRY();
+
+ xf86DestroyCursorInfoRec(pVBox->pCurs);
+ pVBox->pCurs = NULL;
+ TRACE_EXIT();
+}
+
+static void
+vbox_vmm_hide_cursor(ScrnInfoPtr pScrn, VBOXPtr pVBox)
+{
+ int rc;
+ RT_NOREF(pScrn);
+
+ rc = VBoxHGSMIUpdatePointerShape(&pVBox->guestCtx, 0, 0, 0, 0, 0, NULL, 0);
+ AssertMsg(rc == VINF_SUCCESS, ("Could not hide the virtual mouse pointer, VBox error %d.\n", rc));
+}
+
+static void
+vbox_vmm_show_cursor(ScrnInfoPtr pScrn, VBOXPtr pVBox)
+{
+ int rc;
+ RT_NOREF(pScrn);
+
+ if (!pVBox->fUseHardwareCursor)
+ return;
+ rc = VBoxHGSMIUpdatePointerShape(&pVBox->guestCtx, VBOX_MOUSE_POINTER_VISIBLE,
+ 0, 0, 0, 0, NULL, 0);
+ AssertMsg(rc == VINF_SUCCESS, ("Could not unhide the virtual mouse pointer.\n"));
+}
+
+static void
+vbox_vmm_load_cursor_image(ScrnInfoPtr pScrn, VBOXPtr pVBox,
+ unsigned char *pvImage)
+{
+ int rc;
+ struct vboxCursorImage *pImage;
+ pImage = (struct vboxCursorImage *)pvImage;
+ RT_NOREF(pScrn);
+
+#ifdef DEBUG_POINTER
+ vbox_show_shape(pImage->cWidth, pImage->cHeight, 0, pvImage);
+#endif
+
+ rc = VBoxHGSMIUpdatePointerShape(&pVBox->guestCtx, pImage->fFlags,
+ pImage->cHotX, pImage->cHotY, pImage->cWidth, pImage->cHeight,
+ pImage->pPixels, pImage->cbLength);
+ AssertMsg(rc == VINF_SUCCESS, ("Unable to set the virtual mouse pointer image.\n"));
+}
+
+static void
+vbox_set_cursor_colors(ScrnInfoPtr pScrn, int bg, int fg)
+{
+ RT_NOREF(pScrn);
+ RT_NOREF(bg);
+ RT_NOREF(fg);
+ /* ErrorF("vbox_set_cursor_colors NOT IMPLEMENTED\n"); */
+}
+
+
+static void
+vbox_set_cursor_position(ScrnInfoPtr pScrn, int x, int y)
+{
+ VBOXPtr pVBox = pScrn->driverPrivate;
+
+ /* This currently does nothing. */
+ VBoxHGSMICursorPosition(&pVBox->guestCtx, true, x, y, NULL, NULL);
+}
+
+static void
+vbox_hide_cursor(ScrnInfoPtr pScrn)
+{
+ VBOXPtr pVBox = pScrn->driverPrivate;
+
+ vbox_vmm_hide_cursor(pScrn, pVBox);
+}
+
+static void
+vbox_show_cursor(ScrnInfoPtr pScrn)
+{
+ VBOXPtr pVBox = pScrn->driverPrivate;
+
+ vbox_vmm_show_cursor(pScrn, pVBox);
+}
+
+static void
+vbox_load_cursor_image(ScrnInfoPtr pScrn, unsigned char *image)
+{
+ VBOXPtr pVBox = pScrn->driverPrivate;
+
+ vbox_vmm_load_cursor_image(pScrn, pVBox, image);
+}
+
+static Bool
+vbox_use_hw_cursor(ScreenPtr pScreen, CursorPtr pCurs)
+{
+ ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
+ VBOXPtr pVBox = pScrn->driverPrivate;
+ RT_NOREF(pCurs);
+ return pVBox->fUseHardwareCursor;
+}
+
+static unsigned char
+color_to_byte(unsigned c)
+{
+ return (c >> 8) & 0xff;
+}
+
+static unsigned char *
+vbox_realize_cursor(xf86CursorInfoPtr infoPtr, CursorPtr pCurs)
+{
+ VBOXPtr pVBox;
+ CursorBitsPtr bitsp;
+ unsigned short w, h, x, y;
+ unsigned char *c, *p, *pm, *ps, *m;
+ size_t sizeRequest, sizeRgba, sizeMask, srcPitch, dstPitch;
+ CARD32 fc, bc, *cp;
+ int scrnIndex = infoPtr->pScrn->scrnIndex;
+ struct vboxCursorImage *pImage;
+
+ pVBox = infoPtr->pScrn->driverPrivate;
+ bitsp = pCurs->bits;
+ w = bitsp->width;
+ h = bitsp->height;
+
+ if (!w || !h || w > VBOX_MAX_CURSOR_WIDTH || h > VBOX_MAX_CURSOR_HEIGHT)
+ RETERROR(scrnIndex, NULL,
+ "Error invalid cursor dimensions %dx%d\n", w, h);
+
+ if ((bitsp->xhot > w) || (bitsp->yhot > h))
+ RETERROR(scrnIndex, NULL,
+ "Error invalid cursor hotspot location %dx%d (max %dx%d)\n",
+ bitsp->xhot, bitsp->yhot, w, h);
+
+ srcPitch = PixmapBytePad (bitsp->width, 1);
+ dstPitch = (w + 7) / 8;
+ sizeMask = ((dstPitch * h) + 3) & (size_t) ~3;
+ sizeRgba = w * h * 4;
+ sizeRequest = sizeMask + sizeRgba + sizeof(*pImage);
+
+ p = c = calloc (1, sizeRequest);
+ if (!c)
+ RETERROR(scrnIndex, NULL,
+ "Error failed to alloc %lu bytes for cursor\n",
+ (unsigned long) sizeRequest);
+
+ pImage = (struct vboxCursorImage *)p;
+ pImage->pPixels = m = p + sizeof(*pImage);
+ cp = (CARD32 *)(m + sizeMask);
+
+ TRACE_LOG ("w=%d h=%d sm=%d sr=%d p=%d\n",
+ w, h, (int) sizeMask, (int) sizeRgba, (int) dstPitch);
+ TRACE_LOG ("m=%p c=%p cp=%p\n", m, c, (void *)cp);
+
+ fc = color_to_byte (pCurs->foreBlue)
+ | (color_to_byte (pCurs->foreGreen) << 8)
+ | (color_to_byte (pCurs->foreRed) << 16);
+
+ bc = color_to_byte (pCurs->backBlue)
+ | (color_to_byte (pCurs->backGreen) << 8)
+ | (color_to_byte (pCurs->backRed) << 16);
+
+ /*
+ * Convert the Xorg source/mask bits to the and/xor bits VBox needs.
+ * Xorg:
+ * The mask is a bitmap indicating which parts of the cursor are
+ * transparent and which parts are drawn. The source is a bitmap
+ * indicating which parts of the non-transparent portion of the
+ * the cursor should be painted in the foreground color and which
+ * should be painted in the background color. By default, set bits
+ * indicate the opaque part of the mask bitmap and clear bits
+ * indicate the transparent part.
+ * VBox:
+ * The color data is the XOR mask. The AND mask bits determine
+ * which pixels of the color data (XOR mask) will replace (overwrite)
+ * the screen pixels (AND mask bit = 0) and which ones will be XORed
+ * with existing screen pixels (AND mask bit = 1).
+ * For example when you have the AND mask all 0, then you see the
+ * correct mouse pointer image surrounded by black square.
+ */
+ for (pm = bitsp->mask, ps = bitsp->source, y = 0;
+ y < h;
+ ++y, pm += srcPitch, ps += srcPitch, m += dstPitch)
+ {
+ for (x = 0; x < w; ++x)
+ {
+ if (pm[x / 8] & (1 << (x % 8)))
+ {
+ /* opaque, leave AND mask bit at 0 */
+ if (ps[x / 8] & (1 << (x % 8)))
+ {
+ *cp++ = fc;
+ PUT_PIXEL('X');
+ }
+ else
+ {
+ *cp++ = bc;
+ PUT_PIXEL('*');
+ }
+ }
+ else
+ {
+ /* transparent, set AND mask bit */
+ m[x / 8] |= 1 << (7 - (x % 8));
+ /* don't change the screen pixel */
+ *cp++ = 0;
+ PUT_PIXEL(' ');
+ }
+ }
+ PUT_PIXEL('\n');
+ }
+
+ pImage->cWidth = w;
+ pImage->cHeight = h;
+ pImage->cHotX = bitsp->xhot;
+ pImage->cHotY = bitsp->yhot;
+ pImage->fFlags = VBOX_MOUSE_POINTER_VISIBLE | VBOX_MOUSE_POINTER_SHAPE;
+ pImage->cbLength = sizeRequest - sizeof(*pImage);
+
+#ifdef DEBUG_POINTER
+ ErrorF("shape = %p\n", p);
+ vbox_show_shape(w, h, bc, c);
+#endif
+
+ return p;
+}
+
+#ifdef ARGB_CURSOR
+static Bool
+vbox_use_hw_cursor_argb(ScreenPtr pScreen, CursorPtr pCurs)
+{
+ ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
+ VBOXPtr pVBox = pScrn->driverPrivate;
+
+ if (!pVBox->fUseHardwareCursor)
+ return FALSE;
+ if ( (pCurs->bits->height > VBOX_MAX_CURSOR_HEIGHT)
+ || (pCurs->bits->width > VBOX_MAX_CURSOR_WIDTH)
+ || (pScrn->bitsPerPixel <= 8))
+ return FALSE;
+ return TRUE;
+}
+
+
+static void
+vbox_load_cursor_argb(ScrnInfoPtr pScrn, CursorPtr pCurs)
+{
+ VBOXPtr pVBox;
+ CursorBitsPtr bitsp;
+ unsigned short w, h;
+ unsigned short cx, cy;
+ unsigned char *pm;
+ CARD32 *pc;
+ size_t sizeData, sizeMask;
+ CARD8 *p;
+ int scrnIndex;
+ uint32_t fFlags = VBOX_MOUSE_POINTER_VISIBLE | VBOX_MOUSE_POINTER_SHAPE
+ | VBOX_MOUSE_POINTER_ALPHA;
+
+ pVBox = pScrn->driverPrivate;
+ bitsp = pCurs->bits;
+ w = bitsp->width;
+ h = bitsp->height;
+ scrnIndex = pScrn->scrnIndex;
+
+ /* Mask must be generated for alpha cursors, that is required by VBox. */
+ /* note: (michael) the next struct must be 32bit aligned. */
+ sizeMask = ((w + 7) / 8 * h + 3) & ~3;
+
+ if (!w || !h || w > VBOX_MAX_CURSOR_WIDTH || h > VBOX_MAX_CURSOR_HEIGHT)
+ RETERROR(scrnIndex, ,
+ "Error invalid cursor dimensions %dx%d\n", w, h);
+
+ if ((bitsp->xhot > w) || (bitsp->yhot > h))
+ RETERROR(scrnIndex, ,
+ "Error invalid cursor hotspot location %dx%d (max %dx%d)\n",
+ bitsp->xhot, bitsp->yhot, w, h);
+
+ sizeData = w * h * 4 + sizeMask;
+ p = calloc(1, sizeData);
+ if (!p)
+ RETERROR(scrnIndex, ,
+ "Error failed to alloc %lu bytes for cursor\n",
+ (unsigned long)sizeData);
+
+ memcpy(p + sizeMask, bitsp->argb, w * h * 4);
+
+ /* Emulate the AND mask. */
+ pm = p;
+ pc = bitsp->argb;
+
+ /* Init AND mask to 1 */
+ memset(pm, 0xFF, sizeMask);
+
+ /*
+ * The additions driver must provide the AND mask for alpha cursors. The host frontend
+ * which can handle alpha channel, will ignore the AND mask and draw an alpha cursor.
+ * But if the host does not support ARGB, then it simply uses the AND mask and the color
+ * data to draw a normal color cursor.
+ */
+ for (cy = 0; cy < h; cy++)
+ {
+ unsigned char bitmask = 0x80;
+
+ for (cx = 0; cx < w; cx++, bitmask >>= 1)
+ {
+ if (bitmask == 0)
+ bitmask = 0x80;
+
+ if (pc[cx] >= 0xF0000000)
+ pm[cx / 8] &= ~bitmask;
+ }
+
+ /* Point to next source and dest scans */
+ pc += w;
+ pm += (w + 7) / 8;
+ }
+
+ VBoxHGSMIUpdatePointerShape(&pVBox->guestCtx, fFlags, bitsp->xhot,
+ bitsp->yhot, w, h, p, sizeData);
+ free(p);
+}
+#endif
+
+Bool vbvxCursorInit(ScreenPtr pScreen)
+{
+ ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
+ VBOXPtr pVBox = pScrn->driverPrivate;
+ xf86CursorInfoPtr pCurs = NULL;
+ Bool rc = TRUE;
+
+ TRACE_ENTRY();
+ pVBox->pCurs = pCurs = xf86CreateCursorInfoRec();
+ if (!pCurs) {
+ xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+ "Failed to create X Window cursor information structures for virtual mouse.\n");
+ rc = FALSE;
+ }
+ if (rc) {
+ pCurs->MaxWidth = VBOX_MAX_CURSOR_WIDTH;
+ pCurs->MaxHeight = VBOX_MAX_CURSOR_HEIGHT;
+ pCurs->Flags = HARDWARE_CURSOR_TRUECOLOR_AT_8BPP
+ | HARDWARE_CURSOR_SOURCE_MASK_INTERLEAVE_1
+ | HARDWARE_CURSOR_BIT_ORDER_MSBFIRST
+ | HARDWARE_CURSOR_UPDATE_UNHIDDEN;
+
+ pCurs->SetCursorColors = vbox_set_cursor_colors;
+ pCurs->SetCursorPosition = vbox_set_cursor_position;
+ pCurs->LoadCursorImage = vbox_load_cursor_image;
+ pCurs->HideCursor = vbox_hide_cursor;
+ pCurs->ShowCursor = vbox_show_cursor;
+ pCurs->UseHWCursor = vbox_use_hw_cursor;
+ pCurs->RealizeCursor = vbox_realize_cursor;
+
+#ifdef ARGB_CURSOR
+ pCurs->UseHWCursorARGB = vbox_use_hw_cursor_argb;
+ pCurs->LoadCursorARGB = vbox_load_cursor_argb;
+#endif
+
+ rc = xf86InitCursor(pScreen, pCurs);
+ }
+ if (!rc)
+ xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+ "Failed to enable mouse pointer integration.\n");
+ if (!rc && (pCurs != NULL))
+ xf86DestroyCursorInfoRec(pCurs);
+ return rc;
+}
diff --git a/src/setmode.c b/src/setmode.c
new file mode 100644
index 0000000..e3b95a1
--- /dev/null
+++ b/src/setmode.c
@@ -0,0 +1,132 @@
+/* $Id: setmode.c 118346 2017-10-12 18:48:38Z michael $ */
+/** @file
+ * Linux Additions X11 graphics driver, mode setting
+ */
+
+/*
+ * Copyright (C) 2006-2017 Oracle Corporation
+ *
+ * This code is based on:
+ *
+ * X11 VESA driver
+ *
+ * Copyright (c) 2000 by Conectiva S.A. (http://www.conectiva.com)
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM,
+ * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+ * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+ * USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Except as contained in this notice, the name of Conectiva Linux shall
+ * not be used in advertising or otherwise to promote the sale, use or other
+ * dealings in this Software without prior written authorization from
+ * Conectiva Linux.
+ *
+ * Authors: Paulo César Pereira de Andrade <pcpa@conectiva.com.br>
+ * Michael Thayer <michael.thayer@oracle.com>
+ */
+
+#ifdef XORG_7X
+/* We include <unistd.h> for Solaris below, and the ANSI C emulation layer
+ * interferes with that. */
+# define _XF86_ANSIC_H
+# define XF86_LIBC_H
+# include <string.h>
+#endif
+#include "vboxvideo.h"
+#include "xf86.h"
+
+/* VGA hardware functions for setting and restoring text mode */
+#include "vgaHW.h"
+
+#ifdef RT_OS_SOLARIS
+# include <sys/vuid_event.h>
+# include <sys/msio.h>
+# include <errno.h>
+# include <fcntl.h>
+# include <unistd.h>
+#endif
+
+/** Clear the virtual framebuffer in VRAM. Optionally also clear up to the
+ * size of a new framebuffer. Framebuffer sizes larger than available VRAM
+ * be treated as zero and passed over. */
+void vbvxClearVRAM(ScrnInfoPtr pScrn, size_t cbOldSize, size_t cbNewSize)
+{
+ VBOXPtr pVBox = VBOXGetRec(pScrn);
+
+ /* Assume 32BPP - this is just a sanity test. */
+ AssertMsg( cbOldSize / 4 <= VBOX_VIDEO_MAX_VIRTUAL * VBOX_VIDEO_MAX_VIRTUAL
+ && cbNewSize / 4 <= VBOX_VIDEO_MAX_VIRTUAL * VBOX_VIDEO_MAX_VIRTUAL,
+ ("cbOldSize=%llu cbNewSize=%llu, max=%u.\n", (unsigned long long)cbOldSize, (unsigned long long)cbNewSize,
+ VBOX_VIDEO_MAX_VIRTUAL * VBOX_VIDEO_MAX_VIRTUAL));
+ if (cbOldSize > (size_t)pVBox->cbFBMax)
+ cbOldSize = pVBox->cbFBMax;
+ if (cbNewSize > (size_t)pVBox->cbFBMax)
+ cbNewSize = pVBox->cbFBMax;
+ memset(pVBox->base, 0, max(cbOldSize, cbNewSize));
+}
+
+/** Set a graphics mode. Poke any required values into registers, do an HGSMI
+ * mode set and tell the host we support advanced graphics functions.
+ */
+void vbvxSetMode(ScrnInfoPtr pScrn, unsigned cDisplay, unsigned cWidth, unsigned cHeight, int x, int y, Bool fEnabled,
+ Bool fConnected, struct vbvxFrameBuffer *pFrameBuffer)
+{
+ VBOXPtr pVBox = VBOXGetRec(pScrn);
+ uint32_t offStart;
+ uint16_t fFlags;
+ int rc;
+ Bool fEnabledAndVisible = fEnabled && x + cWidth <= pFrameBuffer->cWidth && y + cHeight <= pFrameBuffer->cHeight;
+ /* Recent host code has a flag to blank the screen; older code needs BPP set to zero. */
+ uint32_t cBPP = fEnabledAndVisible || pVBox->fHostHasScreenBlankingFlag ? pFrameBuffer->cBPP : 0;
+
+ TRACE_LOG("cDisplay=%u, cWidth=%u, cHeight=%u, x=%d, y=%d, fEnabled=%d, fConnected=%d, pFrameBuffer: { x0=%d, y0=%d, cWidth=%u, cHeight=%u, cBPP=%u }\n",
+ cDisplay, cWidth, cHeight, x, y, fEnabled, fConnected, pFrameBuffer->x0, pFrameBuffer->y0, pFrameBuffer->cWidth,
+ pFrameBuffer->cHeight, pFrameBuffer->cBPP);
+ AssertMsg(cWidth != 0 && cHeight != 0, ("cWidth = 0 or cHeight = 0\n"));
+ offStart = (y * pFrameBuffer->cWidth + x) * pFrameBuffer->cBPP / 8;
+ if (cDisplay == 0 && fEnabled)
+ VBoxVideoSetModeRegisters(cWidth, cHeight, pFrameBuffer->cWidth, pFrameBuffer->cBPP, 0, x, y);
+ fFlags = VBVA_SCREEN_F_ACTIVE;
+ fFlags |= (fConnected ? 0 : VBVA_SCREEN_F_DISABLED);
+ fFlags |= (!fEnabledAndVisible && pVBox->fHostHasScreenBlankingFlag ? VBVA_SCREEN_F_BLANK : 0);
+ VBoxHGSMIProcessDisplayInfo(&pVBox->guestCtx, cDisplay, x - pFrameBuffer->x0, y - pFrameBuffer->y0, offStart,
+ pFrameBuffer->cWidth * pFrameBuffer->cBPP / 8, cWidth, cHeight, cBPP, fFlags);
+ rc = VBoxHGSMIUpdateInputMapping(&pVBox->guestCtx, 0 - pFrameBuffer->x0, 0 - pFrameBuffer->y0, pFrameBuffer->cWidth,
+ pFrameBuffer->cHeight);
+ if (RT_FAILURE(rc))
+ FatalError("Failed to update the input mapping.\n");
+}
+
+/** Tell the virtual mouse device about the new virtual desktop size. */
+void vbvxSetSolarisMouseRange(int width, int height)
+{
+#ifdef RT_OS_SOLARIS
+ int rc;
+ int hMouse = open("/dev/mouse", O_RDWR);
+
+ if (hMouse >= 0)
+ {
+ do {
+ Ms_screen_resolution Res = { height, width };
+ rc = ioctl(hMouse, MSIOSRESOLUTION, &Res);
+ } while ((rc != 0) && (errno == EINTR));
+ close(hMouse);
+ }
+#else
+ (void)width; (void)height;
+#endif
+}
diff --git a/src/vboxvideo.c b/src/vboxvideo.c
new file mode 100644
index 0000000..facb004
--- /dev/null
+++ b/src/vboxvideo.c
@@ -0,0 +1,1492 @@
+/* $Id: vboxvideo.c 118369 2017-10-13 15:50:47Z michael $ */
+/** @file
+ * Linux Additions X11 graphics driver
+ */
+
+/*
+ * Copyright (C) 2006-2017 Oracle Corporation
+ *
+ * This code is based on the X.Org VESA driver with the following copyrights:
+ *
+ * Copyright (c) 2000 by Conectiva S.A. (http://www.conectiva.com)
+ * Copyright 2008 Red Hat, Inc.
+ * Copyright 2012 Red Hat, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM,
+ * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+ * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+ * USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Except as contained in this notice, the name of Conectiva Linux shall
+ * not be used in advertising or otherwise to promote the sale, use or other
+ * dealings in this Software without prior written authorization from
+ * Conectiva Linux.
+ *
+ * Authors: Paulo César Pereira de Andrade <pcpa@conectiva.com.br>
+ * David Dawes <dawes@xfree86.org>
+ * Adam Jackson <ajax@redhat.com>
+ * Dave Airlie <airlied@redhat.com>
+ * Michael Thayer <michael.thayer@oracle.com>
+ */
+
+#include "vboxvideo.h"
+#include <VBoxVideoVBE.h>
+
+/* Basic definitions and functions needed by all drivers. */
+#include "xf86.h"
+/* For video memory mapping. */
+#include "xf86_OSproc.h"
+#if GET_ABI_MAJOR(ABI_VIDEODRV_VERSION) < 6
+/* PCI resources. */
+# include "xf86Resources.h"
+#endif
+/* Generic server linear frame-buffer APIs. */
+#include "fb.h"
+/* Colormap and visual handling. */
+#include "micmap.h"
+#include "xf86cmap.h"
+/* ShadowFB support */
+#include "shadowfb.h"
+/* VGA hardware functions for setting and restoring text mode */
+#include "vgaHW.h"
+#ifdef VBOXVIDEO_13
+/* X.org 1.3+ mode setting */
+# define _HAVE_STRING_ARCH_strsep /* bits/string2.h, __strsep_1c. */
+# include "xf86Crtc.h"
+# include "xf86Modes.h"
+/* For xf86RandR12GetOriginalVirtualSize(). */
+# include "xf86RandR12.h"
+#endif
+/* For setting the root window property. */
+#include "property.h"
+#include <X11/Xatom.h>
+
+#ifdef XORG_7X
+# include <stdlib.h>
+# include <string.h>
+# include <fcntl.h>
+# include <unistd.h>
+#endif
+
+/* Mandatory functions */
+
+static const OptionInfoRec * VBOXAvailableOptions(int chipid, int busid);
+static void VBOXIdentify(int flags);
+#ifndef PCIACCESS
+static Bool VBOXProbe(DriverPtr drv, int flags);
+#else
+static Bool VBOXPciProbe(DriverPtr drv, int entity_num,
+ struct pci_device *dev, intptr_t match_data);
+#endif
+static Bool VBOXPreInit(ScrnInfoPtr pScrn, int flags);
+static Bool VBOXScreenInit(ScreenPtr pScreen, int argc, char **argv);
+static Bool VBOXEnterVT(ScrnInfoPtr pScrn);
+static void VBOXLeaveVT(ScrnInfoPtr pScrn);
+static Bool VBOXCloseScreen(ScreenPtr pScreen);
+#ifndef VBOXVIDEO_13
+static Bool VBOXSaveScreen(ScreenPtr pScreen, int mode);
+#endif
+static Bool VBOXSwitchMode(ScrnInfoPtr pScrn, DisplayModePtr pMode);
+static void VBOXAdjustFrame(ScrnInfoPtr pScrn, int x, int y);
+static void VBOXFreeScreen(ScrnInfoPtr pScrn);
+#ifndef VBOXVIDEO_13
+static void VBOXDisplayPowerManagementSet(ScrnInfoPtr pScrn, int mode, int flags);
+#endif
+
+/* locally used functions */
+static Bool VBOXMapVidMem(ScrnInfoPtr pScrn);
+static void VBOXUnmapVidMem(ScrnInfoPtr pScrn);
+static void VBOXSaveMode(ScrnInfoPtr pScrn);
+static void VBOXRestoreMode(ScrnInfoPtr pScrn);
+static void setSizesAndCursorIntegration(ScrnInfoPtr pScrn, Bool fScreenInitTime);
+
+#ifndef XF86_SCRN_INTERFACE
+# define xf86ScreenToScrn(pScreen) xf86Screens[(pScreen)->myNum]
+# define xf86ScrnToScreen(pScrn) screenInfo.screens[(pScrn)->scrnIndex]
+#endif
+
+static inline void VBOXSetRec(ScrnInfoPtr pScrn)
+{
+ if (!pScrn->driverPrivate)
+ {
+ VBOXPtr pVBox = (VBOXPtr)xnfcalloc(sizeof(VBOXRec), 1);
+ pScrn->driverPrivate = pVBox;
+#if defined(VBOXVIDEO_13) && defined(RT_OS_LINUX)
+ pVBox->fdACPIDevices = -1;
+#endif
+ }
+}
+
+enum GenericTypes
+{
+ CHIP_VBOX_GENERIC
+};
+
+#ifdef PCIACCESS
+static const struct pci_id_match vbox_device_match[] = {
+ {
+ VBOX_VENDORID, VBOX_DEVICEID, PCI_MATCH_ANY, PCI_MATCH_ANY,
+ 0, 0, 0
+ },
+
+ { 0, 0, 0 },
+};
+#endif
+
+/* Supported chipsets */
+static SymTabRec VBOXChipsets[] =
+{
+ {VBOX_DEVICEID, "vbox"},
+ {-1, NULL}
+};
+
+static PciChipsets VBOXPCIchipsets[] = {
+ { VBOX_DEVICEID, VBOX_DEVICEID, RES_SHARED_VGA },
+ { -1, -1, RES_UNDEFINED },
+};
+
+/*
+ * This contains the functions needed by the server after loading the
+ * driver module. It must be supplied, and gets added the driver list by
+ * the Module Setup function in the dynamic case. In the static case a
+ * reference to this is compiled in, and this requires that the name of
+ * this DriverRec be an upper-case version of the driver name.
+ */
+
+#ifdef XORG_7X
+_X_EXPORT
+#endif
+DriverRec VBOXVIDEO = {
+ VBOX_VERSION,
+ VBOX_DRIVER_NAME,
+ VBOXIdentify,
+#ifdef PCIACCESS
+ NULL,
+#else
+ VBOXProbe,
+#endif
+ VBOXAvailableOptions,
+ NULL,
+ 0,
+#ifdef XORG_7X
+ NULL,
+#endif
+#ifdef PCIACCESS
+ vbox_device_match,
+ VBOXPciProbe
+#endif
+};
+
+/* No options for now */
+static const OptionInfoRec VBOXOptions[] = {
+ { -1, NULL, OPTV_NONE, {0}, FALSE }
+};
+
+#ifndef XORG_7X
+/*
+ * List of symbols from other modules that this module references. This
+ * list is used to tell the loader that it is OK for symbols here to be
+ * unresolved providing that it hasn't been told that they haven't been
+ * told that they are essential via a call to xf86LoaderReqSymbols() or
+ * xf86LoaderReqSymLists(). The purpose is this is to avoid warnings about
+ * unresolved symbols that are not required.
+ */
+static const char *fbSymbols[] = {
+ "fbPictureInit",
+ "fbScreenInit",
+ NULL
+};
+
+static const char *shadowfbSymbols[] = {
+ "ShadowFBInit2",
+ NULL
+};
+
+static const char *ramdacSymbols[] = {
+ "xf86DestroyCursorInfoRec",
+ "xf86InitCursor",
+ "xf86CreateCursorInfoRec",
+ NULL
+};
+
+static const char *vgahwSymbols[] = {
+ "vgaHWFreeHWRec",
+ "vgaHWGetHWRec",
+ "vgaHWGetIOBase",
+ "vgaHWGetIndex",
+ "vgaHWRestore",
+ "vgaHWSave",
+ "vgaHWSetStdFuncs",
+ NULL
+};
+#endif /* !XORG_7X */
+
+/** Resize the virtual framebuffer. */
+static Bool adjustScreenPixmap(ScrnInfoPtr pScrn, int width, int height)
+{
+ ScreenPtr pScreen = xf86ScrnToScreen(pScrn);
+ VBOXPtr pVBox = VBOXGetRec(pScrn);
+ int adjustedWidth = pScrn->bitsPerPixel == 16 ? (width + 1) & ~1 : width;
+ int cbLine = adjustedWidth * pScrn->bitsPerPixel / 8;
+ PixmapPtr pPixmap;
+
+ TRACE_LOG("width=%d, height=%d\n", width, height);
+ AssertMsg(width >= 0 && height >= 0, ("Invalid negative width (%d) or height (%d)\n", width, height));
+ if (pScreen == NULL) /* Not yet initialised. */
+ return TRUE;
+ pPixmap = pScreen->GetScreenPixmap(pScreen);
+ AssertMsg(pPixmap != NULL, ("Failed to get the screen pixmap.\n"));
+ TRACE_LOG("pPixmap=%p adjustedWidth=%d height=%d pScrn->depth=%d pScrn->bitsPerPixel=%d cbLine=%d pVBox->base=%p pPixmap->drawable.width=%d pPixmap->drawable.height=%d\n",
+ (void *)pPixmap, adjustedWidth, height, pScrn->depth,
+ pScrn->bitsPerPixel, cbLine, pVBox->base,
+ pPixmap->drawable.width, pPixmap->drawable.height);
+ if ( adjustedWidth != pPixmap->drawable.width
+ || height != pPixmap->drawable.height)
+ {
+ if ( adjustedWidth > VBOX_VIDEO_MAX_VIRTUAL || height > VBOX_VIDEO_MAX_VIRTUAL
+ || (unsigned)cbLine * (unsigned)height >= pVBox->cbFBMax)
+ {
+ xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+ "Virtual framebuffer %dx%d too large. For information, video memory: %u Kb.\n",
+ adjustedWidth, height, (unsigned) pVBox->cbFBMax / 1024);
+ return FALSE;
+ }
+ if (pScrn->vtSema)
+ vbvxClearVRAM(pScrn, ((size_t)pScrn->virtualX) * pScrn->virtualY * (pScrn->bitsPerPixel / 8),
+ ((size_t)adjustedWidth) * height * (pScrn->bitsPerPixel / 8));
+ pScreen->ModifyPixmapHeader(pPixmap, adjustedWidth, height, pScrn->depth, pScrn->bitsPerPixel, cbLine, pVBox->base);
+ }
+ pScrn->displayWidth = pScrn->virtualX = adjustedWidth;
+ pScrn->virtualY = height;
+ return TRUE;
+}
+
+#ifndef VBOXVIDEO_13
+/** Set a video mode to the hardware, RandR 1.1 version.
+ *
+ * Since we no longer do virtual frame buffers, adjust the screen pixmap
+ * dimensions to match. The "override" parameters are for when we received a
+ * mode hint while switched to a virtual terminal. In this case VBoxClient will
+ * have told us about the mode, but not yet been able to do a mode switch using
+ * RandR. We solve this by setting the requested mode to the host but keeping
+ * the virtual frame-
+ * buffer matching what the X server expects. */
+static void setModeRandR11(ScrnInfoPtr pScrn, DisplayModePtr pMode, Bool fScreenInitTime, Bool fEnterVTTime,
+ int cXOverRide, int cYOverRide)
+{
+ VBOXPtr pVBox = VBOXGetRec(pScrn);
+ struct vbvxFrameBuffer frameBuffer = { 0, 0, pMode->HDisplay, pMode->VDisplay, pScrn->bitsPerPixel};
+ int cXPhysical = cXOverRide > 0 ? min(cXOverRide, pMode->HDisplay) : pMode->HDisplay;
+ int cYPhysical = cYOverRide > 0 ? min(cYOverRide, pMode->VDisplay) : pMode->VDisplay;
+
+ pVBox->pScreens[0].aScreenLocation.cx = pMode->HDisplay;
+ pVBox->pScreens[0].aScreenLocation.cy = pMode->VDisplay;
+ if (fScreenInitTime)
+ {
+ /* The screen structure is not fully set up yet, so do not touch it. */
+ pScrn->displayWidth = pScrn->virtualX = pMode->HDisplay;
+ pScrn->virtualY = pMode->VDisplay;
+ }
+ else
+ {
+ xf86ScrnToScreen(pScrn)->width = pMode->HDisplay;
+ xf86ScrnToScreen(pScrn)->height = pMode->VDisplay;
+ /* This prevents a crash in CentOS 3. I was unable to debug it to
+ * satisfaction, partly due to the lack of symbols. My guess is that
+ * pScrn->ModifyPixmapHeader() expects certain things to be set up when
+ * it sees pScrn->vtSema set to true which are not quite done at this
+ * point of the VT switch. */
+ if (fEnterVTTime)
+ pScrn->vtSema = FALSE;
+ adjustScreenPixmap(pScrn, pMode->HDisplay, pMode->VDisplay);
+ if (fEnterVTTime)
+ pScrn->vtSema = TRUE;
+ }
+ if (pMode->HDisplay != 0 && pMode->VDisplay != 0 && pScrn->vtSema)
+ vbvxSetMode(pScrn, 0, cXPhysical, cYPhysical, 0, 0, true, true, &frameBuffer);
+ pScrn->currentMode = pMode;
+}
+#endif
+
+#ifdef VBOXVIDEO_13
+/* X.org 1.3+ mode-setting support ******************************************/
+
+/** Set a video mode to the hardware, RandR 1.2 version. If this is the first
+ * screen, re-set the current mode for all others (the offset for the first
+ * screen is always treated as zero by the hardware, so all other screens need
+ * to be changed to compensate for any changes!). The mode to set is taken
+ * from the X.Org Crtc structure. */
+static void setModeRandR12(ScrnInfoPtr pScrn, unsigned cScreen)
+{
+ VBOXPtr pVBox = VBOXGetRec(pScrn);
+ unsigned i;
+ struct vbvxFrameBuffer frameBuffer = { pVBox->pScreens[0].paCrtcs->x, pVBox->pScreens[0].paCrtcs->y, pScrn->virtualX,
+ pScrn->virtualY, pScrn->bitsPerPixel };
+ unsigned cFirst = cScreen;
+ unsigned cLast = cScreen != 0 ? cScreen + 1 : pVBox->cScreens;
+ int originalX, originalY;
+
+ /* Check that this code cannot trigger the resizing bug in X.Org Server 1.3.
+ * See the work-around in ScreenInit. */
+ xf86RandR12GetOriginalVirtualSize(pScrn, &originalX, &originalY);
+ AssertMsg(originalX == VBOX_VIDEO_MAX_VIRTUAL && originalY == VBOX_VIDEO_MAX_VIRTUAL, ("OriginalSize=%dx%d",
+ originalX, originalY));
+ for (i = cFirst; i < cLast; ++i)
+ if (pVBox->pScreens[i].paCrtcs->mode.HDisplay != 0 && pVBox->pScreens[i].paCrtcs->mode.VDisplay != 0 && pScrn->vtSema)
+ vbvxSetMode(pScrn, i, pVBox->pScreens[i].paCrtcs->mode.HDisplay, pVBox->pScreens[i].paCrtcs->mode.VDisplay,
+ pVBox->pScreens[i].paCrtcs->x, pVBox->pScreens[i].paCrtcs->y, pVBox->pScreens[i].fPowerOn,
+ pVBox->pScreens[i].paOutputs->status == XF86OutputStatusConnected, &frameBuffer);
+}
+
+/** Wrapper around setModeRandR12() to avoid exposing non-obvious semantics.
+ */
+static void setAllModesRandR12(ScrnInfoPtr pScrn)
+{
+ setModeRandR12(pScrn, 0);
+}
+
+/* For descriptions of these functions and structures, see
+ hw/xfree86/modes/xf86Crtc.h and hw/xfree86/modes/xf86Modes.h in the
+ X.Org source tree. */
+
+static Bool vbox_config_resize(ScrnInfoPtr pScrn, int cw, int ch)
+{
+ VBOXPtr pVBox = VBOXGetRec(pScrn);
+ Bool rc;
+ unsigned i;
+
+ TRACE_LOG("width=%d, height=%d\n", cw, ch);
+ rc = adjustScreenPixmap(pScrn, cw, ch);
+ /* Power-on all screens (the server expects this) and set the new pitch to them. */
+ for (i = 0; i < pVBox->cScreens; ++i)
+ pVBox->pScreens[i].fPowerOn = true;
+ setAllModesRandR12(pScrn);
+ vbvxSetSolarisMouseRange(cw, ch);
+ return rc;
+}
+
+static const xf86CrtcConfigFuncsRec VBOXCrtcConfigFuncs = {
+ vbox_config_resize
+};
+
+static void
+vbox_crtc_dpms(xf86CrtcPtr crtc, int mode)
+{
+ ScrnInfoPtr pScrn = crtc->scrn;
+ VBOXPtr pVBox = VBOXGetRec(pScrn);
+ unsigned cDisplay = (uintptr_t)crtc->driver_private;
+
+ TRACE_LOG("mode=%d\n", mode);
+ pVBox->pScreens[cDisplay].fPowerOn = (mode != DPMSModeOff);
+ setModeRandR12(pScrn, cDisplay);
+}
+
+static Bool
+vbox_crtc_lock (xf86CrtcPtr crtc)
+{ RT_NOREF(crtc); return FALSE; }
+
+
+/* We use this function to check whether the X server owns the active virtual
+ * terminal before attempting a mode switch, since the RandR extension isn't
+ * very dilligent here, which can mean crashes if we are unlucky. This is
+ * not the way it the function is intended - it is meant for reporting modes
+ * which the hardware can't handle. I hope that this won't confuse any clients
+ * connecting to us. */
+static Bool
+vbox_crtc_mode_fixup (xf86CrtcPtr crtc, DisplayModePtr mode,
+ DisplayModePtr adjusted_mode)
+{ RT_NOREF(crtc, mode, adjusted_mode); return TRUE; }
+
+static void
+vbox_crtc_stub (xf86CrtcPtr crtc)
+{ RT_NOREF(crtc); }
+
+static void
+vbox_crtc_mode_set (xf86CrtcPtr crtc, DisplayModePtr mode,
+ DisplayModePtr adjusted_mode, int x, int y)
+{
+ RT_NOREF(mode);
+ VBOXPtr pVBox = VBOXGetRec(crtc->scrn);
+ unsigned cDisplay = (uintptr_t)crtc->driver_private;
+
+ TRACE_LOG("name=%s, HDisplay=%d, VDisplay=%d, x=%d, y=%d\n", adjusted_mode->name,
+ adjusted_mode->HDisplay, adjusted_mode->VDisplay, x, y);
+ pVBox->pScreens[cDisplay].fPowerOn = true;
+ pVBox->pScreens[cDisplay].aScreenLocation.cx = adjusted_mode->HDisplay;
+ pVBox->pScreens[cDisplay].aScreenLocation.cy = adjusted_mode->VDisplay;
+ pVBox->pScreens[cDisplay].aScreenLocation.x = x;
+ pVBox->pScreens[cDisplay].aScreenLocation.y = y;
+ setModeRandR12(crtc->scrn, cDisplay);
+}
+
+static void
+vbox_crtc_gamma_set (xf86CrtcPtr crtc, CARD16 *red,
+ CARD16 *green, CARD16 *blue, int size)
+{ RT_NOREF(crtc, red, green, blue, size); }
+
+static void *
+vbox_crtc_shadow_allocate (xf86CrtcPtr crtc, int width, int height)
+{ RT_NOREF(crtc, width, height); return NULL; }
+
+static const xf86CrtcFuncsRec VBOXCrtcFuncs = {
+ .dpms = vbox_crtc_dpms,
+ .save = NULL, /* These two are never called by the server. */
+ .restore = NULL,
+ .lock = vbox_crtc_lock,
+ .unlock = NULL, /* This will not be invoked if lock returns FALSE. */
+ .mode_fixup = vbox_crtc_mode_fixup,
+ .prepare = vbox_crtc_stub,
+ .mode_set = vbox_crtc_mode_set,
+ .commit = vbox_crtc_stub,
+ .gamma_set = vbox_crtc_gamma_set,
+ .shadow_allocate = vbox_crtc_shadow_allocate,
+ .shadow_create = NULL, /* These two should not be invoked if allocate
+ returns NULL. */
+ .shadow_destroy = NULL,
+ .set_cursor_colors = NULL, /* We are still using the old cursor API. */
+ .set_cursor_position = NULL,
+ .show_cursor = NULL,
+ .hide_cursor = NULL,
+ .load_cursor_argb = NULL,
+ .destroy = vbox_crtc_stub
+};
+
+static void
+vbox_output_stub (xf86OutputPtr output)
+{ RT_NOREF(output); }
+
+static void
+vbox_output_dpms (xf86OutputPtr output, int mode)
+{
+ RT_NOREF(output, mode);
+}
+
+static int
+vbox_output_mode_valid (xf86OutputPtr output, DisplayModePtr mode)
+{
+ return MODE_OK;
+}
+
+static Bool
+vbox_output_mode_fixup (xf86OutputPtr output, DisplayModePtr mode,
+ DisplayModePtr adjusted_mode)
+{ RT_NOREF(output, mode, adjusted_mode); return TRUE; }
+
+static void
+vbox_output_mode_set (xf86OutputPtr output, DisplayModePtr mode,
+ DisplayModePtr adjusted_mode)
+{ RT_NOREF(output, mode, adjusted_mode); }
+
+static xf86OutputStatus
+vbox_output_detect (xf86OutputPtr output)
+{
+ ScrnInfoPtr pScrn = output->scrn;
+ VBOXPtr pVBox = VBOXGetRec(pScrn);
+ uint32_t iScreen = (uintptr_t)output->driver_private;
+ return pVBox->pScreens[iScreen].afConnected
+ ? XF86OutputStatusConnected : XF86OutputStatusDisconnected;
+}
+
+static DisplayModePtr vbox_output_add_mode(VBOXPtr pVBox, DisplayModePtr *pModes, const char *pszName, int x, int y,
+ Bool isPreferred, Bool isUserDef)
+{
+ TRACE_LOG("pszName=%s, x=%d, y=%d\n", pszName ? pszName : "(null)", x, y);
+ DisplayModePtr pMode = xnfcalloc(1, sizeof(DisplayModeRec));
+ int cRefresh = 60;
+
+ pMode->status = MODE_OK;
+ /* We don't ask the host whether it likes user defined modes,
+ * as we assume that the user really wanted that mode. */
+ pMode->type = isUserDef ? M_T_USERDEF : M_T_BUILTIN;
+ if (isPreferred)
+ pMode->type |= M_T_PREFERRED;
+ /* Older versions of VBox only support screen widths which are a multiple
+ * of 8 */
+ if (pVBox->fAnyX)
+ pMode->HDisplay = x;
+ else
+ pMode->HDisplay = x & ~7;
+ pMode->HSyncStart = pMode->HDisplay + 2;
+ pMode->HSyncEnd = pMode->HDisplay + 4;
+ pMode->HTotal = pMode->HDisplay + 6;
+ pMode->VDisplay = y;
+ pMode->VSyncStart = pMode->VDisplay + 2;
+ pMode->VSyncEnd = pMode->VDisplay + 4;
+ pMode->VTotal = pMode->VDisplay + 6;
+ pMode->Clock = pMode->HTotal * pMode->VTotal * cRefresh / 1000; /* kHz */
+ if (NULL == pszName) {
+ xf86SetModeDefaultName(pMode);
+ } else {
+ pMode->name = xnfstrdup(pszName);
+ }
+ *pModes = xf86ModesAdd(*pModes, pMode);
+ return pMode;
+}
+
+static DisplayModePtr
+vbox_output_get_modes (xf86OutputPtr output)
+{
+ DisplayModePtr pModes = NULL;
+ DisplayModePtr pPreferred = NULL;
+ ScrnInfoPtr pScrn = output->scrn;
+ VBOXPtr pVBox = VBOXGetRec(pScrn);
+
+ TRACE_ENTRY();
+ uint32_t iScreen = (uintptr_t)output->driver_private;
+ pPreferred = vbox_output_add_mode(pVBox, &pModes, NULL,
+ RT_CLAMP(pVBox->pScreens[iScreen].aPreferredSize.cx, VBOX_VIDEO_MIN_SIZE, VBOX_VIDEO_MAX_VIRTUAL),
+ RT_CLAMP(pVBox->pScreens[iScreen].aPreferredSize.cy, VBOX_VIDEO_MIN_SIZE, VBOX_VIDEO_MAX_VIRTUAL),
+ TRUE, FALSE);
+ vbox_output_add_mode(pVBox, &pModes, NULL, 2560, 1600, FALSE, FALSE);
+ vbox_output_add_mode(pVBox, &pModes, NULL, 2560, 1440, FALSE, FALSE);
+ vbox_output_add_mode(pVBox, &pModes, NULL, 2048, 1536, FALSE, FALSE);
+ vbox_output_add_mode(pVBox, &pModes, NULL, 1920, 1600, FALSE, FALSE);
+ vbox_output_add_mode(pVBox, &pModes, NULL, 1920, 1080, FALSE, FALSE);
+ vbox_output_add_mode(pVBox, &pModes, NULL, 1680, 1050, FALSE, FALSE);
+ vbox_output_add_mode(pVBox, &pModes, NULL, 1600, 1200, FALSE, FALSE);
+ vbox_output_add_mode(pVBox, &pModes, NULL, 1400, 1050, FALSE, FALSE);
+ vbox_output_add_mode(pVBox, &pModes, NULL, 1280, 1024, FALSE, FALSE);
+ vbox_output_add_mode(pVBox, &pModes, NULL, 1024, 768, FALSE, FALSE);
+ vbox_output_add_mode(pVBox, &pModes, NULL, 800, 600, FALSE, FALSE);
+ vbox_output_add_mode(pVBox, &pModes, NULL, 640, 480, FALSE, FALSE);
+ VBOXEDIDSet(output, pPreferred);
+ TRACE_EXIT();
+ return pModes;
+}
+
+static const xf86OutputFuncsRec VBOXOutputFuncs = {
+ .create_resources = vbox_output_stub,
+ .dpms = vbox_output_dpms,
+ .save = NULL, /* These two are never called by the server. */
+ .restore = NULL,
+ .mode_valid = vbox_output_mode_valid,
+ .mode_fixup = vbox_output_mode_fixup,
+ .prepare = vbox_output_stub,
+ .commit = vbox_output_stub,
+ .mode_set = vbox_output_mode_set,
+ .detect = vbox_output_detect,
+ .get_modes = vbox_output_get_modes,
+#ifdef RANDR_12_INTERFACE
+ .set_property = NULL,
+#endif
+ .destroy = vbox_output_stub
+};
+#endif /* VBOXVIDEO_13 */
+
+/* Module loader interface */
+static MODULESETUPPROTO(vboxSetup);
+
+static XF86ModuleVersionInfo vboxVersionRec =
+{
+ VBOX_DRIVER_NAME,
+ "Oracle Corporation",
+ MODINFOSTRING1,
+ MODINFOSTRING2,
+#ifdef XORG_7X
+ XORG_VERSION_CURRENT,
+#else
+ XF86_VERSION_CURRENT,
+#endif
+ 1, /* Module major version. Xorg-specific */
+ 0, /* Module minor version. Xorg-specific */
+ 1, /* Module patchlevel. Xorg-specific */
+ ABI_CLASS_VIDEODRV, /* This is a video driver */
+ ABI_VIDEODRV_VERSION,
+ MOD_CLASS_VIDEODRV,
+ {0, 0, 0, 0}
+};
+
+/*
+ * This data is accessed by the loader. The name must be the module name
+ * followed by "ModuleData".
+ */
+#ifdef XORG_7X
+_X_EXPORT
+#endif
+XF86ModuleData vboxvideoModuleData = { &vboxVersionRec, vboxSetup, NULL };
+
+static pointer
+vboxSetup(pointer Module, pointer Options, int *ErrorMajor, int *ErrorMinor)
+{
+ static Bool Initialised = FALSE;
+ RT_NOREF(Options, ErrorMinor);
+
+ if (!Initialised)
+ {
+ Initialised = TRUE;
+#ifdef PCIACCESS
+ xf86AddDriver(&VBOXVIDEO, Module, HaveDriverFuncs);
+#else
+ xf86AddDriver(&VBOXVIDEO, Module, 0);
+#endif
+#ifndef XORG_7X
+ LoaderRefSymLists(fbSymbols,
+ shadowfbSymbols,
+ ramdacSymbols,
+ vgahwSymbols,
+ NULL);
+#endif
+ xf86Msg(X_CONFIG, "Load address of symbol \"VBOXVIDEO\" is %p\n",
+ (void *)&VBOXVIDEO);
+ return (pointer)TRUE;
+ }
+
+ if (ErrorMajor)
+ *ErrorMajor = LDR_ONCEONLY;
+ return (NULL);
+}
+
+
+static const OptionInfoRec *
+VBOXAvailableOptions(int chipid, int busid)
+{
+ RT_NOREF(chipid, busid);
+ return (VBOXOptions);
+}
+
+static void
+VBOXIdentify(int flags)
+{
+ RT_NOREF(flags);
+ xf86PrintChipsets(VBOX_NAME, "guest driver for VirtualBox", VBOXChipsets);
+}
+
+#ifndef XF86_SCRN_INTERFACE
+# define SCRNINDEXAPI(pfn) pfn ## Index
+static Bool VBOXScreenInitIndex(int scrnIndex, ScreenPtr pScreen, int argc, char **argv)
+{
+ RT_NOREF(scrnIndex);
+ return VBOXScreenInit(pScreen, argc, argv);
+}
+
+static Bool VBOXEnterVTIndex(int scrnIndex, int flags)
+{ RT_NOREF(flags); return VBOXEnterVT(xf86Screens[scrnIndex]); }
+
+static void VBOXLeaveVTIndex(int scrnIndex, int flags)
+{ RT_NOREF(flags); VBOXLeaveVT(xf86Screens[scrnIndex]); }
+
+static Bool VBOXCloseScreenIndex(int scrnIndex, ScreenPtr pScreen)
+{ RT_NOREF(scrnIndex); return VBOXCloseScreen(pScreen); }
+
+static Bool VBOXSwitchModeIndex(int scrnIndex, DisplayModePtr pMode, int flags)
+{ RT_NOREF(flags); return VBOXSwitchMode(xf86Screens[scrnIndex], pMode); }
+
+static void VBOXAdjustFrameIndex(int scrnIndex, int x, int y, int flags)
+{ RT_NOREF(flags); VBOXAdjustFrame(xf86Screens[scrnIndex], x, y); }
+
+static void VBOXFreeScreenIndex(int scrnIndex, int flags)
+{ RT_NOREF(flags); VBOXFreeScreen(xf86Screens[scrnIndex]); }
+# else
+# define SCRNINDEXAPI(pfn) pfn
+#endif /* XF86_SCRN_INTERFACE */
+
+static void setScreenFunctions(ScrnInfoPtr pScrn, xf86ProbeProc pfnProbe)
+{
+ pScrn->driverVersion = VBOX_VERSION;
+ pScrn->driverName = VBOX_DRIVER_NAME;
+ pScrn->name = VBOX_NAME;
+ pScrn->Probe = pfnProbe;
+ pScrn->PreInit = VBOXPreInit;
+ pScrn->ScreenInit = SCRNINDEXAPI(VBOXScreenInit);
+ pScrn->SwitchMode = SCRNINDEXAPI(VBOXSwitchMode);
+ pScrn->AdjustFrame = SCRNINDEXAPI(VBOXAdjustFrame);
+ pScrn->EnterVT = SCRNINDEXAPI(VBOXEnterVT);
+ pScrn->LeaveVT = SCRNINDEXAPI(VBOXLeaveVT);
+ pScrn->FreeScreen = SCRNINDEXAPI(VBOXFreeScreen);
+}
+
+/*
+ * One of these functions is called once, at the start of the first server
+ * generation to do a minimal probe for supported hardware.
+ */
+
+#ifdef PCIACCESS
+static Bool
+VBOXPciProbe(DriverPtr drv, int entity_num, struct pci_device *dev,
+ intptr_t match_data)
+{
+ ScrnInfoPtr pScrn;
+ int drmFd;
+
+ TRACE_ENTRY();
+
+ drmFd = open("/dev/dri/card0", O_RDWR, 0);
+ if (drmFd >= 0)
+ {
+ xf86Msg(X_INFO, "vboxvideo: kernel driver found, not loading.\n");
+ close(drmFd);
+ return FALSE;
+ }
+ /* It is safe to call this, as the X server enables I/O access before
+ * calling the probe call-backs. */
+ if (!xf86EnableIO())
+ {
+ xf86Msg(X_INFO, "vboxvideo: this driver requires direct hardware access. You may wish to use the kernel driver instead.\n");
+ return FALSE;
+ }
+ pScrn = xf86ConfigPciEntity(NULL, 0, entity_num, VBOXPCIchipsets,
+ NULL, NULL, NULL, NULL, NULL);
+ if (pScrn != NULL) {
+ VBOXPtr pVBox;
+
+ VBOXSetRec(pScrn);
+ pVBox = VBOXGetRec(pScrn);
+ if (!pVBox)
+ return FALSE;
+ setScreenFunctions(pScrn, NULL);
+ pVBox->pciInfo = dev;
+ }
+
+ TRACE_LOG("returning %s\n", pScrn == NULL ? "false" : "true");
+ return (pScrn != NULL);
+}
+#endif
+
+#ifndef PCIACCESS
+static Bool
+VBOXProbe(DriverPtr drv, int flags)
+{
+ Bool foundScreen = FALSE;
+ int numDevSections;
+ GDevPtr *devSections;
+
+ /*
+ * Find the config file Device sections that match this
+ * driver, and return if there are none.
+ */
+ if ((numDevSections = xf86MatchDevice(VBOX_NAME,
+ &devSections)) <= 0)
+ return (FALSE);
+
+ /* PCI BUS */
+ if (xf86GetPciVideoInfo())
+ {
+ int numUsed;
+ int *usedChips;
+ int i;
+ numUsed = xf86MatchPciInstances(VBOX_NAME, VBOX_VENDORID,
+ VBOXChipsets, VBOXPCIchipsets,
+ devSections, numDevSections,
+ drv, &usedChips);
+ if (numUsed > 0)
+ {
+ if (flags & PROBE_DETECT)
+ foundScreen = TRUE;
+ else
+ for (i = 0; i < numUsed; i++)
+ {
+ ScrnInfoPtr pScrn = NULL;
+ /* Allocate a ScrnInfoRec */
+ if ((pScrn = xf86ConfigPciEntity(pScrn,0,usedChips[i],
+ VBOXPCIchipsets,NULL,
+ NULL,NULL,NULL,NULL)))
+ {
+ setScreenFunctions(pScrn, VBOXProbe);
+ foundScreen = TRUE;
+ }
+ }
+ free(usedChips);
+ }
+ }
+ free(devSections);
+ return (foundScreen);
+}
+#endif
+
+
+/*
+ * QUOTE from the XFree86 DESIGN document:
+ *
+ * The purpose of this function is to find out all the information
+ * required to determine if the configuration is usable, and to initialise
+ * those parts of the ScrnInfoRec that can be set once at the beginning of
+ * the first server generation.
+ *
+ * (...)
+ *
+ * This includes probing for video memory, clocks, ramdac, and all other
+ * HW info that is needed. It includes determining the depth/bpp/visual
+ * and related info. It includes validating and determining the set of
+ * video modes that will be used (and anything that is required to
+ * determine that).
+ *
+ * This information should be determined in the least intrusive way
+ * possible. The state of the HW must remain unchanged by this function.
+ * Although video memory (including MMIO) may be mapped within this
+ * function, it must be unmapped before returning.
+ *
+ * END QUOTE
+ */
+
+static Bool
+VBOXPreInit(ScrnInfoPtr pScrn, int flags)
+{
+ VBOXPtr pVBox;
+ Gamma gzeros = {0.0, 0.0, 0.0};
+ rgb rzeros = {0, 0, 0};
+
+ TRACE_ENTRY();
+ /* Are we really starting the server, or is this just a dummy run? */
+ if (flags & PROBE_DETECT)
+ return (FALSE);
+
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+ "VirtualBox guest additions video driver version %d.%d\n",
+ VBOX_VERSION_MAJOR, VBOX_VERSION_MINOR);
+
+ /* The ramdac module is needed for the hardware cursor. */
+ if (!xf86LoadSubModule(pScrn, "ramdac"))
+ return FALSE;
+
+ /* The framebuffer module. */
+ if (!xf86LoadSubModule(pScrn, "fb"))
+ return (FALSE);
+
+ if (!xf86LoadSubModule(pScrn, "shadowfb"))
+ return FALSE;
+
+ if (!xf86LoadSubModule(pScrn, "vgahw"))
+ return FALSE;
+
+ /* Get our private data from the ScrnInfoRec structure. */
+ VBOXSetRec(pScrn);
+ pVBox = VBOXGetRec(pScrn);
+ if (!pVBox)
+ return FALSE;
+
+ /* Entity information seems to mean bus information. */
+ pVBox->pEnt = xf86GetEntityInfo(pScrn->entityList[0]);
+
+#ifndef PCIACCESS
+ if (pVBox->pEnt->location.type != BUS_PCI)
+ return FALSE;
+
+ pVBox->pciInfo = xf86GetPciInfoForEntity(pVBox->pEnt->index);
+ pVBox->pciTag = pciTag(pVBox->pciInfo->bus,
+ pVBox->pciInfo->device,
+ pVBox->pciInfo->func);
+#endif
+
+ /* Set up our ScrnInfoRec structure to describe our virtual
+ capabilities to X. */
+
+ pScrn->chipset = "vbox";
+ /** @note needed during colourmap initialisation */
+ pScrn->rgbBits = 8;
+
+ /* Let's create a nice, capable virtual monitor. */
+ pScrn->monitor = pScrn->confScreen->monitor;
+ pScrn->monitor->DDC = NULL;
+ pScrn->monitor->nHsync = 1;
+ pScrn->monitor->hsync[0].lo = 1;
+ pScrn->monitor->hsync[0].hi = 10000;
+ pScrn->monitor->nVrefresh = 1;
+ pScrn->monitor->vrefresh[0].lo = 1;
+ pScrn->monitor->vrefresh[0].hi = 100;
+
+ pScrn->progClock = TRUE;
+
+ /* Using the PCI information caused problems with non-powers-of-two
+ sized video RAM configurations */
+ pVBox->cbFBMax = VBoxVideoGetVRAMSize();
+ pScrn->videoRam = pVBox->cbFBMax / 1024;
+
+ /* Check if the chip restricts horizontal resolution or not. */
+ pVBox->fAnyX = VBoxVideoAnyWidthAllowed();
+
+ /* Set up clock information that will support all modes we need. */
+ pScrn->clockRanges = xnfcalloc(sizeof(ClockRange), 1);
+ pScrn->clockRanges->minClock = 1000;
+ pScrn->clockRanges->maxClock = 1000000000;
+ pScrn->clockRanges->clockIndex = -1;
+ pScrn->clockRanges->ClockMulFactor = 1;
+ pScrn->clockRanges->ClockDivFactor = 1;
+
+ if (!xf86SetDepthBpp(pScrn, 24, 0, 0, Support32bppFb))
+ return FALSE;
+ /* We only support 16 and 24 bits depth (i.e. 16 and 32bpp) */
+ if (pScrn->bitsPerPixel != 32 && pScrn->bitsPerPixel != 16)
+ {
+ xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+ "The VBox additions only support 16 and 32bpp graphics modes\n");
+ return FALSE;
+ }
+ xf86PrintDepthBpp(pScrn);
+ vboxAddModes(pScrn);
+
+#ifdef VBOXVIDEO_13
+ pScrn->virtualX = VBOX_VIDEO_MAX_VIRTUAL;
+ pScrn->virtualY = VBOX_VIDEO_MAX_VIRTUAL;
+#else
+ /* We don't validate with xf86ValidateModes and xf86PruneModes as we
+ * already know what we like and what we don't. */
+
+ pScrn->currentMode = pScrn->modes;
+
+ /* Set the right virtual resolution. */
+ pScrn->virtualX = pScrn->bitsPerPixel == 16 ? (pScrn->currentMode->HDisplay + 1) & ~1 : pScrn->currentMode->HDisplay;
+ pScrn->virtualY = pScrn->currentMode->VDisplay;
+
+#endif /* !VBOXVIDEO_13 */
+
+ pScrn->displayWidth = pScrn->virtualX;
+
+ xf86PrintModes(pScrn);
+
+ /* VGA hardware initialisation */
+ if (!vgaHWGetHWRec(pScrn))
+ return FALSE;
+ /* Must be called before any VGA registers are saved or restored */
+ vgaHWSetStdFuncs(VGAHWPTR(pScrn));
+ vgaHWGetIOBase(VGAHWPTR(pScrn));
+
+ /* Colour weight - we always call this, since we are always in
+ truecolour. */
+ if (!xf86SetWeight(pScrn, rzeros, rzeros))
+ return (FALSE);
+
+ /* visual init */
+ if (!xf86SetDefaultVisual(pScrn, -1))
+ return (FALSE);
+
+ xf86SetGamma(pScrn, gzeros);
+
+ /* Set the DPI. Perhaps we should read this from the host? */
+ xf86SetDpi(pScrn, 96, 96);
+
+ if (pScrn->memPhysBase == 0) {
+#ifdef PCIACCESS
+ pScrn->memPhysBase = pVBox->pciInfo->regions[0].base_addr;
+#else
+ pScrn->memPhysBase = pVBox->pciInfo->memBase[0];
+#endif
+ pScrn->fbOffset = 0;
+ }
+
+ TRACE_EXIT();
+ return (TRUE);
+}
+
+/**
+ * Dummy function for setting the colour palette, which we actually never
+ * touch. However, the server still requires us to provide this.
+ */
+static void
+vboxLoadPalette(ScrnInfoPtr pScrn, int numColors, int *indices,
+ LOCO *colors, VisualPtr pVisual)
+{
+ RT_NOREF(pScrn, numColors, indices, colors, pVisual);
+}
+
+/** Set the graphics and guest cursor support capabilities to the host if
+ * the user-space helper is running. */
+static void updateGraphicsCapability(ScrnInfoPtr pScrn, Bool hasVT)
+{
+ VBOXPtr pVBox = VBOXGetRec(pScrn);
+
+ if (!pVBox->fHaveHGSMIModeHints)
+ return;
+ VBoxHGSMISendCapsInfo(&pVBox->guestCtx, hasVT
+ ? VBVACAPS_VIDEO_MODE_HINTS | VBVACAPS_DISABLE_CURSOR_INTEGRATION
+ : VBVACAPS_DISABLE_CURSOR_INTEGRATION);
+}
+
+#ifndef VBOXVIDEO_13
+
+#define PREFERRED_MODE_ATOM_NAME "VBOXVIDEO_PREFERRED_MODE"
+
+static void setSizesRandR11(ScrnInfoPtr pScrn)
+{
+ VBOXPtr pVBox = VBOXGetRec(pScrn);
+ DisplayModePtr pNewMode;
+ int32_t propertyValue;
+
+ pNewMode = pScrn->modes != pScrn->currentMode ? pScrn->modes : pScrn->modes->next;
+ pNewMode->HDisplay = RT_CLAMP(pVBox->pScreens[0].aPreferredSize.cx, VBOX_VIDEO_MIN_SIZE, VBOX_VIDEO_MAX_VIRTUAL);
+ pNewMode->VDisplay = RT_CLAMP(pVBox->pScreens[0].aPreferredSize.cy, VBOX_VIDEO_MIN_SIZE, VBOX_VIDEO_MAX_VIRTUAL);
+ propertyValue = (pNewMode->HDisplay << 16) + pNewMode->VDisplay;
+ ChangeWindowProperty(ROOT_WINDOW(pScrn), MakeAtom(PREFERRED_MODE_ATOM_NAME,
+ sizeof(PREFERRED_MODE_ATOM_NAME) - 1, TRUE), XA_INTEGER, 32,
+ PropModeReplace, 1, &propertyValue, TRUE);
+}
+
+#endif
+
+static void reprobeCursor(ScrnInfoPtr pScrn)
+{
+ if (ROOT_WINDOW(pScrn) == NULL)
+ return;
+#ifdef XF86_SCRN_INTERFACE
+ pScrn->EnableDisableFBAccess(pScrn, FALSE);
+ pScrn->EnableDisableFBAccess(pScrn, TRUE);
+#else
+ pScrn->EnableDisableFBAccess(pScrn->scrnIndex, FALSE);
+ pScrn->EnableDisableFBAccess(pScrn->scrnIndex, TRUE);
+#endif
+}
+
+static void setSizesAndCursorIntegration(ScrnInfoPtr pScrn, Bool fScreenInitTime)
+{
+ RT_NOREF(fScreenInitTime);
+ TRACE_LOG("fScreenInitTime=%d\n", (int)fScreenInitTime);
+#ifdef VBOXVIDEO_13
+# if GET_ABI_MAJOR(ABI_VIDEODRV_VERSION) >= 5
+ RRGetInfo(xf86ScrnToScreen(pScrn), TRUE);
+# else
+ RRGetInfo(xf86ScrnToScreen(pScrn));
+# endif
+#else
+ setSizesRandR11(pScrn);
+#endif
+ /* This calls EnableDisableFBAccess(), so only use when switched in. */
+ if (pScrn->vtSema)
+ reprobeCursor(pScrn);
+}
+
+/* We update the size hints from the X11 property set by VBoxClient every time
+ * that the X server goes to sleep (to catch the property change request).
+ * Although this is far more often than necessary it should not have real-life
+ * performance consequences and allows us to simplify the code quite a bit. */
+static void vboxBlockHandler(pointer pData,
+#if GET_ABI_MAJOR(ABI_VIDEODRV_VERSION) < 23
+ OSTimePtr pTimeout,
+ pointer pReadmask
+#else
+ void *pTimeout
+#endif
+ )
+{
+ ScrnInfoPtr pScrn = (ScrnInfoPtr)pData;
+ Bool fNeedUpdate = false;
+
+ RT_NOREF(pTimeout);
+#if GET_ABI_MAJOR(ABI_VIDEODRV_VERSION) < 23
+ RT_NOREF(pReadmask);
+#endif
+ if (pScrn->vtSema)
+ vbvxReadSizesAndCursorIntegrationFromHGSMI(pScrn, &fNeedUpdate);
+ if (fNeedUpdate)
+ setSizesAndCursorIntegration(pScrn, false);
+}
+
+/*
+ * QUOTE from the XFree86 DESIGN document:
+ *
+ * This is called at the start of each server generation.
+ *
+ * (...)
+ *
+ * Decide which operations need to be placed under resource access
+ * control. (...) Map any video memory or other memory regions. (...)
+ * Save the video card state. (...) Initialise the initial video
+ * mode.
+ *
+ * End QUOTE.
+ */
+static Bool VBOXScreenInit(ScreenPtr pScreen, int argc, char **argv)
+{
+ ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
+ VBOXPtr pVBox = VBOXGetRec(pScrn);
+ VisualPtr visual;
+ RT_NOREF(argc, argv);
+
+ TRACE_ENTRY();
+
+ if (!VBOXMapVidMem(pScrn))
+ return (FALSE);
+
+ /* save current video state */
+ VBOXSaveMode(pScrn);
+
+ /* mi layer - reset the visual list (?)*/
+ miClearVisualTypes();
+ if (!miSetVisualTypes(pScrn->depth, TrueColorMask,
+ pScrn->rgbBits, TrueColor))
+ return (FALSE);
+ if (!miSetPixmapDepths())
+ return (FALSE);
+
+ if (!fbScreenInit(pScreen, pVBox->base,
+ pScrn->virtualX, pScrn->virtualY,
+ pScrn->xDpi, pScrn->yDpi,
+ pScrn->displayWidth, pScrn->bitsPerPixel))
+ return (FALSE);
+
+ /* Fixup RGB ordering */
+ /** @note the X server uses this even in true colour. */
+ visual = pScreen->visuals + pScreen->numVisuals;
+ while (--visual >= pScreen->visuals) {
+ if ((visual->class | DynamicClass) == DirectColor) {
+ visual->offsetRed = pScrn->offset.red;
+ visual->offsetGreen = pScrn->offset.green;
+ visual->offsetBlue = pScrn->offset.blue;
+ visual->redMask = pScrn->mask.red;
+ visual->greenMask = pScrn->mask.green;
+ visual->blueMask = pScrn->mask.blue;
+ }
+ }
+
+ /* must be after RGB ordering fixed */
+ fbPictureInit(pScreen, 0, 0);
+
+ xf86SetBlackWhitePixels(pScreen);
+ pScrn->vtSema = TRUE;
+
+#if defined(VBOXVIDEO_13) && defined(RT_OS_LINUX)
+ vbvxSetUpLinuxACPI(pScreen);
+#endif
+
+ if (!VBoxHGSMIIsSupported())
+ {
+ xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Graphics device too old to support.\n");
+ return FALSE;
+ }
+ vbvxSetUpHGSMIHeapInGuest(pVBox, pScrn->videoRam * 1024);
+ pVBox->cScreens = VBoxHGSMIGetMonitorCount(&pVBox->guestCtx);
+ pVBox->pScreens = xnfcalloc(pVBox->cScreens, sizeof(*pVBox->pScreens));
+ pVBox->paVBVAModeHints = xnfcalloc(pVBox->cScreens, sizeof(*pVBox->paVBVAModeHints));
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Requested monitor count: %u\n", pVBox->cScreens);
+ vboxEnableVbva(pScrn);
+ /* Set up the dirty rectangle handler. It will be added into a function
+ * chain and gets removed when the screen is cleaned up. */
+ if (ShadowFBInit2(pScreen, NULL, vbvxHandleDirtyRect) != TRUE)
+ return FALSE;
+ VBoxInitialiseSizeHints(pScrn);
+
+#ifdef VBOXVIDEO_13
+ /* Initialise CRTC and output configuration for use with randr1.2. */
+ xf86CrtcConfigInit(pScrn, &VBOXCrtcConfigFuncs);
+
+ {
+ uint32_t i;
+
+ for (i = 0; i < pVBox->cScreens; ++i)
+ {
+ char szOutput[256];
+
+ /* Setup our virtual CRTCs. */
+ pVBox->pScreens[i].paCrtcs = xf86CrtcCreate(pScrn, &VBOXCrtcFuncs);
+ pVBox->pScreens[i].paCrtcs->driver_private = (void *)(uintptr_t)i;
+
+ /* Set up our virtual outputs. */
+ snprintf(szOutput, sizeof(szOutput), "VGA-%u", i);
+ pVBox->pScreens[i].paOutputs
+ = xf86OutputCreate(pScrn, &VBOXOutputFuncs, szOutput);
+
+ /* We are not interested in the monitor section in the
+ * configuration file. */
+ xf86OutputUseScreenMonitor(pVBox->pScreens[i].paOutputs, FALSE);
+ pVBox->pScreens[i].paOutputs->possible_crtcs = 1 << i;
+ pVBox->pScreens[i].paOutputs->possible_clones = 0;
+ pVBox->pScreens[i].paOutputs->driver_private = (void *)(uintptr_t)i;
+ TRACE_LOG("Created crtc (%p) and output %s (%p)\n",
+ (void *)pVBox->pScreens[i].paCrtcs, szOutput,
+ (void *)pVBox->pScreens[i].paOutputs);
+ }
+ }
+
+ /* Set a sane minimum and maximum mode size to match what the hardware
+ * supports. */
+ xf86CrtcSetSizeRange(pScrn, VBOX_VIDEO_MIN_SIZE, VBOX_VIDEO_MIN_SIZE, VBOX_VIDEO_MAX_VIRTUAL, VBOX_VIDEO_MAX_VIRTUAL);
+
+ /* Now create our initial CRTC/output configuration. */
+ if (!xf86InitialConfiguration(pScrn, TRUE)) {
+ xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Initial CRTC configuration failed!\n");
+ return (FALSE);
+ }
+
+ /* Work around a bug in the original X server modesetting code, which took
+ * the first valid values set to these two as maxima over the server
+ * lifetime. This bug was introduced on Feb 15 2007 and was fixed in commit
+ * fa877d7f three months later, so it was present in X.Org Server 1.3. */
+ pScrn->virtualX = VBOX_VIDEO_MAX_VIRTUAL;
+ pScrn->virtualY = VBOX_VIDEO_MAX_VIRTUAL;
+
+ /* Initialise randr 1.2 mode-setting functions. */
+ if (!xf86CrtcScreenInit(pScreen)) {
+ return FALSE;
+ }
+
+ /* set first video mode */
+ if (!xf86SetDesiredModes(pScrn)) {
+ return FALSE;
+ }
+#else /* !VBOXVIDEO_13 */
+ /* set first video mode */
+ setModeRandR11(pScrn, pScrn->currentMode, true, false, 0, 0);
+#endif /* !VBOXVIDEO_13 */
+
+ /* Say that we support graphics. */
+ updateGraphicsCapability(pScrn, TRUE);
+
+#if GET_ABI_MAJOR(ABI_VIDEODRV_VERSION) >= 23
+# define WakeupHandlerProcPtr ServerWakeupHandlerProcPtr
+#endif
+
+ /* Register block and wake-up handlers for getting new screen size hints. */
+ RegisterBlockAndWakeupHandlers(vboxBlockHandler, (WakeupHandlerProcPtr)NoopDDA, (pointer)pScrn);
+
+ /* software cursor */
+ miDCInitialize(pScreen, xf86GetPointerScreenFuncs());
+
+ /* colourmap code */
+ if (!miCreateDefColormap(pScreen))
+ return (FALSE);
+
+ if(!xf86HandleColormaps(pScreen, 256, 8, vboxLoadPalette, NULL, 0))
+ return (FALSE);
+
+ pVBox->CloseScreen = pScreen->CloseScreen;
+ pScreen->CloseScreen = SCRNINDEXAPI(VBOXCloseScreen);
+#ifdef VBOXVIDEO_13
+ pScreen->SaveScreen = xf86SaveScreen;
+#else
+ pScreen->SaveScreen = VBOXSaveScreen;
+#endif
+
+#ifdef VBOXVIDEO_13
+ xf86DPMSInit(pScreen, xf86DPMSSet, 0);
+#else
+ /* We probably do want to support power management - even if we just use
+ a dummy function. */
+ xf86DPMSInit(pScreen, VBOXDisplayPowerManagementSet, 0);
+#endif
+
+ /* Report any unused options (only for the first generation) */
+ if (serverGeneration == 1)
+ xf86ShowUnusedOptions(pScrn->scrnIndex, pScrn->options);
+
+ if (vbvxCursorInit(pScreen) != TRUE)
+ xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+ "Unable to start the VirtualBox mouse pointer integration with the host system.\n");
+
+ return (TRUE);
+}
+
+#define NO_VT_ATOM_NAME "VBOXVIDEO_NO_VT"
+
+static Bool VBOXEnterVT(ScrnInfoPtr pScrn)
+{
+ VBOXPtr pVBox = VBOXGetRec(pScrn);
+#ifndef VBOXVIDEO_13
+ /* If we got a mode request while we were switched out, temporarily override
+ * the physical mode set to the device while keeping things consistent from
+ * the server's point of view. */
+ int cXOverRide = RT_CLAMP(pVBox->pScreens[0].aPreferredSize.cx, VBOX_VIDEO_MIN_SIZE, VBOX_VIDEO_MAX_VIRTUAL);
+ int cYOverRide = RT_CLAMP(pVBox->pScreens[0].aPreferredSize.cy, VBOX_VIDEO_MIN_SIZE, VBOX_VIDEO_MAX_VIRTUAL);
+#endif
+
+ TRACE_ENTRY();
+ vbvxSetUpHGSMIHeapInGuest(pVBox, pScrn->videoRam * 1024);
+ vboxEnableVbva(pScrn);
+ /* Re-set video mode */
+#ifdef VBOXVIDEO_13
+ if (!xf86SetDesiredModes(pScrn)) {
+ return FALSE;
+ }
+#else
+ setModeRandR11(pScrn, pScrn->currentMode, false, true, cXOverRide, cYOverRide);
+ DeleteProperty(ROOT_WINDOW(pScrn), MakeAtom(NO_VT_ATOM_NAME, sizeof(NO_VT_ATOM_NAME) - 1, TRUE));
+#endif
+ updateGraphicsCapability(pScrn, TRUE);
+ return TRUE;
+}
+
+static void VBOXLeaveVT(ScrnInfoPtr pScrn)
+{
+#ifdef VBOXVIDEO_13
+ VBOXPtr pVBox = VBOXGetRec(pScrn);
+ unsigned i;
+#else
+ int32_t propertyValue = 0;
+#endif
+
+ TRACE_ENTRY();
+#ifdef VBOXVIDEO_13
+ for (i = 0; i < pVBox->cScreens; ++i)
+ vbox_crtc_dpms(pVBox->pScreens[i].paCrtcs, DPMSModeOff);
+#else
+ ChangeWindowProperty(ROOT_WINDOW(pScrn), MakeAtom(NO_VT_ATOM_NAME, sizeof(NO_VT_ATOM_NAME) - 1, FALSE), XA_INTEGER, 32,
+ PropModeReplace, 1, &propertyValue, TRUE);
+#endif
+ updateGraphicsCapability(pScrn, FALSE);
+ vboxDisableVbva(pScrn);
+ vbvxClearVRAM(pScrn, ((size_t)pScrn->virtualX) * pScrn->virtualY * (pScrn->bitsPerPixel / 8), 0);
+ VBOXRestoreMode(pScrn);
+ TRACE_EXIT();
+}
+
+static Bool VBOXCloseScreen(ScreenPtr pScreen)
+{
+ ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
+ VBOXPtr pVBox = VBOXGetRec(pScrn);
+ BOOL ret;
+
+ if (pScrn->vtSema)
+ {
+#ifdef VBOXVIDEO_13
+ unsigned i;
+
+ for (i = 0; i < pVBox->cScreens; ++i)
+ vbox_crtc_dpms(pVBox->pScreens[i].paCrtcs, DPMSModeOff);
+#endif
+ vboxDisableVbva(pScrn);
+ vbvxClearVRAM(pScrn, ((size_t)pScrn->virtualX) * pScrn->virtualY * (pScrn->bitsPerPixel / 8), 0);
+ }
+ if (pScrn->vtSema)
+ VBOXRestoreMode(pScrn);
+ if (pScrn->vtSema)
+ VBOXUnmapVidMem(pScrn);
+ pScrn->vtSema = FALSE;
+
+ vbvxCursorTerm(pVBox);
+
+ pScreen->CloseScreen = pVBox->CloseScreen;
+#if defined(VBOXVIDEO_13) && defined(RT_OS_LINUX)
+ vbvxCleanUpLinuxACPI(pScreen);
+#endif
+#ifndef XF86_SCRN_INTERFACE
+ ret = pScreen->CloseScreen(pScreen->myNum, pScreen);
+#else
+ ret = pScreen->CloseScreen(pScreen);
+#endif
+ return ret;
+}
+
+static Bool VBOXSwitchMode(ScrnInfoPtr pScrn, DisplayModePtr pMode)
+{
+ Bool rc = TRUE;
+
+ TRACE_LOG("HDisplay=%d, VDisplay=%d\n", pMode->HDisplay, pMode->VDisplay);
+#ifdef VBOXVIDEO_13
+ rc = xf86SetSingleMode(pScrn, pMode, RR_Rotate_0);
+#else
+ setModeRandR11(pScrn, pMode, false, false, 0, 0);
+#endif
+ TRACE_LOG("returning %s\n", rc ? "TRUE" : "FALSE");
+ return rc;
+}
+
+static void VBOXAdjustFrame(ScrnInfoPtr pScrn, int x, int y)
+{ RT_NOREF(pScrn, x, y); }
+
+static void VBOXFreeScreen(ScrnInfoPtr pScrn)
+{
+ /* Destroy the VGA hardware record */
+ vgaHWFreeHWRec(pScrn);
+ /* And our private record */
+ free(pScrn->driverPrivate);
+ pScrn->driverPrivate = NULL;
+}
+
+static Bool
+VBOXMapVidMem(ScrnInfoPtr pScrn)
+{
+ VBOXPtr pVBox = VBOXGetRec(pScrn);
+ Bool rc = TRUE;
+
+ TRACE_ENTRY();
+ if (!pVBox->base)
+ {
+#ifdef PCIACCESS
+ (void) pci_device_map_range(pVBox->pciInfo,
+ pScrn->memPhysBase,
+ pScrn->videoRam * 1024,
+ PCI_DEV_MAP_FLAG_WRITABLE,
+ & pVBox->base);
+#else
+ pVBox->base = xf86MapPciMem(pScrn->scrnIndex,
+ VIDMEM_FRAMEBUFFER,
+ pVBox->pciTag, pScrn->memPhysBase,
+ (unsigned) pScrn->videoRam * 1024);
+#endif
+ if (!pVBox->base)
+ rc = FALSE;
+ }
+ TRACE_LOG("returning %s\n", rc ? "TRUE" : "FALSE");
+ return rc;
+}
+
+static void
+VBOXUnmapVidMem(ScrnInfoPtr pScrn)
+{
+ VBOXPtr pVBox = VBOXGetRec(pScrn);
+
+ TRACE_ENTRY();
+ if (pVBox->base == NULL)
+ return;
+
+#ifdef PCIACCESS
+ (void) pci_device_unmap_range(pVBox->pciInfo,
+ pVBox->base,
+ pScrn->videoRam * 1024);
+#else
+ xf86UnMapVidMem(pScrn->scrnIndex, pVBox->base,
+ (unsigned) pScrn->videoRam * 1024);
+#endif
+ pVBox->base = NULL;
+ TRACE_EXIT();
+}
+
+#ifndef VBOXVIDEO_13
+static Bool
+VBOXSaveScreen(ScreenPtr pScreen, int mode)
+{
+ RT_NOREF(pScreen, mode);
+ return TRUE;
+}
+#endif
+
+void
+VBOXSaveMode(ScrnInfoPtr pScrn)
+{
+ VBOXPtr pVBox = VBOXGetRec(pScrn);
+ vgaRegPtr vgaReg;
+
+ TRACE_ENTRY();
+ vgaReg = &VGAHWPTR(pScrn)->SavedReg;
+ vgaHWSave(pScrn, vgaReg, VGA_SR_ALL);
+ pVBox->fSavedVBEMode = VBoxVideoGetModeRegisters(&pVBox->cSavedWidth,
+ &pVBox->cSavedHeight,
+ &pVBox->cSavedPitch,
+ &pVBox->cSavedBPP,
+ &pVBox->fSavedFlags);
+}
+
+void
+VBOXRestoreMode(ScrnInfoPtr pScrn)
+{
+ VBOXPtr pVBox = VBOXGetRec(pScrn);
+ vgaRegPtr vgaReg;
+
+ TRACE_ENTRY();
+ vgaReg = &VGAHWPTR(pScrn)->SavedReg;
+ vgaHWRestore(pScrn, vgaReg, VGA_SR_ALL);
+ if (pVBox->fSavedVBEMode)
+ VBoxVideoSetModeRegisters(pVBox->cSavedWidth, pVBox->cSavedHeight,
+ pVBox->cSavedPitch, pVBox->cSavedBPP,
+ pVBox->fSavedFlags, 0, 0);
+ else
+ VBoxVideoDisableVBE();
+}
+
+#ifndef VBOXVIDEO_13
+static void
+VBOXDisplayPowerManagementSet(ScrnInfoPtr pScrn, int mode, int flags)
+{
+ RT_NOREF(pScrn, mode, flags);
+}
+#endif
diff --git a/src/vboxvideo.h b/src/vboxvideo.h
new file mode 100644
index 0000000..83f8f84
--- /dev/null
+++ b/src/vboxvideo.h
@@ -0,0 +1,240 @@
+/* $Id: vboxvideo.h 118369 2017-10-13 15:50:47Z michael $ */
+/** @file
+ * VirtualBox X11 Additions graphics driver
+ */
+
+/*
+ * Copyright (C) 2006-2017 Oracle Corporation
+ *
+ * This code is based on:
+ *
+ * X11 VESA driver
+ *
+ * Copyright (c) 2000 by Conectiva S.A. (http://www.conectiva.com)
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM,
+ * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+ * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+ * USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Except as contained in this notice, the name of Conectiva Linux shall
+ * not be used in advertising or otherwise to promote the sale, use or other
+ * dealings in this Software without prior written authorization from
+ * Conectiva Linux.
+ *
+ * Authors: Paulo César Pereira de Andrade <pcpa@conectiva.com.br>
+ * Michael Thayer <michael.thayer@oracle.com>
+ */
+
+#ifndef _VBOXVIDEO_H_
+#define _VBOXVIDEO_H_
+
+#include <VBoxVideoGuest.h>
+#include <VBoxVideo.h>
+#include "version-generated.h"
+
+#define VBOX_VENDORID 0x80EE
+#define VBOX_DEVICEID 0xBEEF
+
+#ifndef VBVA_SCREEN_F_BLANK
+# define VBVA_SCREEN_F_BLANK 0x0004
+#endif
+
+#include <VBoxVideoVBE.h>
+
+#include "xf86.h"
+#include "xf86str.h"
+#include "xf86Cursor.h"
+
+#ifdef DEBUG
+
+#define TRACE_ENTRY() do { xf86ErrorF("%s: entering\n", __func__); } while(0)
+#define TRACE_EXIT() do { xf86ErrorF("%s: leaving\n", __func__); } while(0)
+#define TRACE_LINE() \
+ do { xf86ErrorF("%s: line\n", __func__, __LINE__); } while(0)
+#define TRACE_LOG(...) \
+do { \
+ xf86ErrorF("%s: ", __func__); \
+ xf86ErrorF(__VA_ARGS__); \
+} while(0)
+
+#else /* !DEBUG */
+
+#define TRACE_ENTRY() do { } while (0)
+#define TRACE_EXIT() do { } while (0)
+#define TRACE_LOG(...) do { } while (0)
+
+#endif /* !DEBUG */
+
+#define VBOX_VERSION VBOX_VERSION_MAJOR * 10000 \
+ + VBOX_VERSION_MINOR * 100
+#define VBOX_NAME "VBoxVideo"
+#define VBOX_DRIVER_NAME "vboxvideo"
+
+#define VBOX_VIDEO_MAJOR VBOX_VERSION_MAJOR
+#define VBOX_VIDEO_MINOR VBOX_VERSION_MINOR
+
+#define VBOX_VIDEO_MIN_SIZE 64
+#define VBOX_VIDEO_MAX_VIRTUAL (INT16_MAX - 1)
+
+#define VBOXPTR(p) ((VBOXPtr)((p)->driverPrivate))
+
+/** Helper to work round different ways of getting the root window in different
+ * server versions. */
+#if defined(XORG_VERSION_CURRENT) && XORG_VERSION_CURRENT < 70000000 \
+ && XORG_VERSION_CURRENT >= 10900000
+# define ROOT_WINDOW(pScrn) screenInfo.screens[(pScrn)->scrnIndex]->root
+#else
+# define ROOT_WINDOW(pScrn) WindowTable[(pScrn)->scrnIndex]
+#endif
+
+/** ChangeWindowProperty for X.Org Server 1.19 and later */
+#if defined(XORG_VERSION_CURRENT) && XORG_VERSION_CURRENT < 70000000 \
+ && XORG_VERSION_CURRENT >= 11900000
+# define ChangeWindowProperty(pWin, property, type, format, mode, \
+ len, value, sendevent) \
+ dixChangeWindowProperty(serverClient, pWin, property, type, format, \
+ mode, len, value, sendevent)
+#endif
+
+/** Structure containing all virtual monitor-specific information. */
+struct VBoxScreen
+{
+ /** Position information for each virtual screen for the purposes of
+ * sending dirty rectangle information to the right one. */
+ RTRECT2 aScreenLocation;
+ /** Is this CRTC enabled or in DPMS off state? */
+ Bool fPowerOn;
+#ifdef VBOXVIDEO_13
+ /** The virtual crtcs. */
+ struct _xf86Crtc *paCrtcs;
+ /** The virtual outputs, logically not distinct from crtcs. */
+ struct _xf86Output *paOutputs;
+#endif
+ /** Offsets of VBVA buffers in video RAM */
+ uint32_t aoffVBVABuffer;
+ /** Context information about the VBVA buffers for each screen */
+ struct VBVABUFFERCONTEXT aVbvaCtx;
+ /** The current preferred resolution for the screen */
+ RTRECTSIZE aPreferredSize;
+ /** The current preferred location for the screen. */
+ RTPOINT aPreferredLocation;
+ /** Has this screen been enabled by the host? */
+ Bool afConnected;
+ /** Does this screen have a preferred location? */
+ Bool afHaveLocation;
+};
+
+typedef struct VBOXRec
+{
+ EntityInfoPtr pEnt;
+#ifdef PCIACCESS
+ struct pci_device *pciInfo;
+#else
+ pciVideoPtr pciInfo;
+ PCITAG pciTag;
+#endif
+ void *base;
+ /** The amount of VRAM available for use as a framebuffer */
+ unsigned long cbFBMax;
+ /** The size of the framebuffer and the VBVA buffers at the end of it. */
+ unsigned long cbView;
+ /** Whether the pre-X-server mode was a VBE mode */
+ Bool fSavedVBEMode;
+ /** Paramters of the saved pre-X-server VBE mode, invalid if there is none
+ */
+ uint16_t cSavedWidth, cSavedHeight, cSavedPitch, cSavedBPP, fSavedFlags;
+ CloseScreenProcPtr CloseScreen;
+ /** Default X server procedure for enabling and disabling framebuffer access */
+ xf86EnableDisableFBAccessProc *EnableDisableFBAccess;
+ OptionInfoPtr Options;
+ /** @todo we never actually free this */
+ xf86CursorInfoPtr pCurs;
+ /** Do we currently want to use the host cursor? */
+ Bool fUseHardwareCursor;
+ /** Number of screens attached */
+ uint32_t cScreens;
+ /** Information about each virtual screen. */
+ struct VBoxScreen *pScreens;
+ /** Can we get mode hint and cursor integration information from HGSMI? */
+ Bool fHaveHGSMIModeHints;
+ /** Does the host support the screen blanking flag? */
+ Bool fHostHasScreenBlankingFlag;
+ /** Array of structures for receiving mode hints. */
+ VBVAMODEHINT *paVBVAModeHints;
+#ifdef VBOXVIDEO_13
+# ifdef RT_OS_LINUX
+ /** Input device file descriptor for getting ACPI hot-plug events. */
+ int fdACPIDevices;
+ /** Input handler handle for ACPI hot-plug listener. */
+ void *hACPIEventHandler;
+# endif
+#endif
+ /** HGSMI guest heap context */
+ HGSMIGUESTCOMMANDCONTEXT guestCtx;
+ /** Unrestricted horizontal resolution flag. */
+ Bool fAnyX;
+} VBOXRec, *VBOXPtr;
+
+#define VBOXGetRec(pScrn) ((VBOXPtr)(pScrn)->driverPrivate)
+
+/* setmode.c */
+
+/** Structure describing the virtual frame buffer. It starts at the beginning
+ * of the video RAM. */
+struct vbvxFrameBuffer {
+ /** X offset of first screen in frame buffer. */
+ int x0;
+ /** Y offset of first screen in frame buffer. */
+ int y0;
+ /** Frame buffer virtual width. */
+ unsigned cWidth;
+ /** Frame buffer virtual height. */
+ unsigned cHeight;
+ /** Bits per pixel. */
+ unsigned cBPP;
+};
+
+extern void vbvxClearVRAM(ScrnInfoPtr pScrn, size_t cbOldSize, size_t cbNewSize);
+extern void vbvxSetMode(ScrnInfoPtr pScrn, unsigned cDisplay, unsigned cWidth, unsigned cHeight, int x, int y, Bool fEnabled,
+ Bool fConnected, struct vbvxFrameBuffer *pFrameBuffer);
+extern void vbvxSetSolarisMouseRange(int width, int height);
+
+/* pointer.h */
+extern Bool vbvxCursorInit(ScreenPtr pScreen);
+extern void vbvxCursorTerm(VBOXPtr pVBox);
+
+/* vbva.c */
+extern void vbvxHandleDirtyRect(ScrnInfoPtr pScrn, int iRects, BoxPtr aRects);
+extern void vbvxSetUpHGSMIHeapInGuest(VBOXPtr pVBox, uint32_t cbVRAM);
+extern Bool vboxEnableVbva(ScrnInfoPtr pScrn);
+extern void vboxDisableVbva(ScrnInfoPtr pScrn);
+
+/* getmode.c */
+extern void vboxAddModes(ScrnInfoPtr pScrn);
+extern void VBoxInitialiseSizeHints(ScrnInfoPtr pScrn);
+extern void vbvxReadSizesAndCursorIntegrationFromProperties(ScrnInfoPtr pScrn, Bool *pfNeedUpdate);
+extern void vbvxReadSizesAndCursorIntegrationFromHGSMI(ScrnInfoPtr pScrn, Bool *pfNeedUpdate);
+extern void vbvxSetUpLinuxACPI(ScreenPtr pScreen);
+extern void vbvxCleanUpLinuxACPI(ScreenPtr pScreen);
+
+/* EDID generation */
+#ifdef VBOXVIDEO_13
+extern Bool VBOXEDIDSet(struct _xf86Output *output, DisplayModePtr pmode);
+#endif
+
+#endif /* _VBOXVIDEO_H_ */
+
diff --git a/src/vbva.c b/src/vbva.c
new file mode 100644
index 0000000..c927cae
--- /dev/null
+++ b/src/vbva.c
@@ -0,0 +1,252 @@
+/* $Id: vbva.c 118368 2017-10-13 15:48:13Z michael $ */
+/** @file
+ * VirtualBox X11 Additions graphics driver 2D acceleration functions
+ */
+
+/*
+ * Copyright (C) 2006-2017 Oracle Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM,
+ * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+ * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+ * USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#if defined(IN_XF86_MODULE) && !defined(NO_ANSIC)
+# include "xf86_ansic.h"
+#endif
+#include "compiler.h"
+
+#include "vboxvideo.h"
+
+#ifdef XORG_7X
+# include <stdlib.h>
+# include <string.h>
+#endif
+
+/**************************************************************************
+* Main functions *
+**************************************************************************/
+
+/**
+ * Callback function called by the X server to tell us about dirty
+ * rectangles in the video buffer.
+ *
+ * @param pScrn pointer to the information structure for the current
+ * screen
+ * @param iRects Number of dirty rectangles to update
+ * @param aRects Array of structures containing the coordinates of the
+ * rectangles
+ */
+void vbvxHandleDirtyRect(ScrnInfoPtr pScrn, int iRects, BoxPtr aRects)
+{
+ VBVACMDHDR cmdHdr;
+ VBOXPtr pVBox;
+ int i;
+ unsigned j;
+
+ pVBox = pScrn->driverPrivate;
+ if (!pScrn->vtSema)
+ return;
+
+ for (j = 0; j < pVBox->cScreens; ++j)
+ {
+ /* Just continue quietly if VBVA is not currently active. */
+ struct VBVABUFFER *pVBVA = pVBox->pScreens[j].aVbvaCtx.pVBVA;
+ if ( !pVBVA
+ || !(pVBVA->hostFlags.u32HostEvents & VBVA_F_MODE_ENABLED))
+ continue;
+ for (i = 0; i < iRects; ++i)
+ {
+ if ( aRects[i].x1 > pVBox->pScreens[j].aScreenLocation.x
+ + pVBox->pScreens[j].aScreenLocation.cx
+ || aRects[i].y1 > pVBox->pScreens[j].aScreenLocation.y
+ + pVBox->pScreens[j].aScreenLocation.cy
+ || aRects[i].x2 < pVBox->pScreens[j].aScreenLocation.x
+ || aRects[i].y2 < pVBox->pScreens[j].aScreenLocation.y)
+ continue;
+ cmdHdr.x = (int16_t)aRects[i].x1 - pVBox->pScreens[0].aScreenLocation.x;
+ cmdHdr.y = (int16_t)aRects[i].y1 - pVBox->pScreens[0].aScreenLocation.y;
+ cmdHdr.w = (uint16_t)(aRects[i].x2 - aRects[i].x1);
+ cmdHdr.h = (uint16_t)(aRects[i].y2 - aRects[i].y1);
+
+#if 0
+ TRACE_LOG("display=%u, x=%d, y=%d, w=%d, h=%d\n",
+ j, cmdHdr.x, cmdHdr.y, cmdHdr.w, cmdHdr.h);
+#endif
+
+ if (VBoxVBVABufferBeginUpdate(&pVBox->pScreens[j].aVbvaCtx,
+ &pVBox->guestCtx))
+ {
+ VBoxVBVAWrite(&pVBox->pScreens[j].aVbvaCtx, &pVBox->guestCtx, &cmdHdr,
+ sizeof(cmdHdr));
+ VBoxVBVABufferEndUpdate(&pVBox->pScreens[j].aVbvaCtx);
+ }
+ }
+ }
+}
+
+static DECLCALLBACK(void *) hgsmiEnvAlloc(void *pvEnv, HGSMISIZE cb)
+{
+ RT_NOREF(pvEnv);
+ return calloc(1, cb);
+}
+
+static DECLCALLBACK(void) hgsmiEnvFree(void *pvEnv, void *pv)
+{
+ RT_NOREF(pvEnv);
+ free(pv);
+}
+
+static HGSMIENV g_hgsmiEnv =
+{
+ NULL,
+ hgsmiEnvAlloc,
+ hgsmiEnvFree
+};
+
+/**
+ * Calculate the location in video RAM of and initialise the heap for guest to
+ * host messages.
+ */
+void vbvxSetUpHGSMIHeapInGuest(VBOXPtr pVBox, uint32_t cbVRAM)
+{
+ int rc;
+ uint32_t offVRAMBaseMapping, offGuestHeapMemory, cbGuestHeapMemory;
+ void *pvGuestHeapMemory;
+
+ VBoxHGSMIGetBaseMappingInfo(cbVRAM, &offVRAMBaseMapping, NULL, &offGuestHeapMemory, &cbGuestHeapMemory, NULL);
+ pvGuestHeapMemory = ((uint8_t *)pVBox->base) + offVRAMBaseMapping + offGuestHeapMemory;
+ rc = VBoxHGSMISetupGuestContext(&pVBox->guestCtx, pvGuestHeapMemory, cbGuestHeapMemory,
+ offVRAMBaseMapping + offGuestHeapMemory, &g_hgsmiEnv);
+ AssertMsg(RT_SUCCESS(rc), ("Failed to set up the guest-to-host message buffer heap, rc=%d\n", rc));
+ pVBox->cbView = offVRAMBaseMapping;
+}
+
+/** Callback to fill in the view structures */
+static DECLCALLBACK(int) vboxFillViewInfo(void *pvVBox, struct VBVAINFOVIEW *pViews, uint32_t cViews)
+{
+ VBOXPtr pVBox = (VBOXPtr)pvVBox;
+ unsigned i;
+ for (i = 0; i < cViews; ++i)
+ {
+ pViews[i].u32ViewIndex = i;
+ pViews[i].u32ViewOffset = 0;
+ pViews[i].u32ViewSize = pVBox->cbView;
+ pViews[i].u32MaxScreenSize = pVBox->cbFBMax;
+ }
+ return VINF_SUCCESS;
+}
+
+/**
+ * Initialise VirtualBox's accelerated video extensions.
+ *
+ * @returns TRUE on success, FALSE on failure
+ */
+static Bool vboxSetupVRAMVbva(VBOXPtr pVBox)
+{
+ int rc = VINF_SUCCESS;
+ unsigned i;
+
+ pVBox->cbFBMax = pVBox->cbView;
+ for (i = 0; i < pVBox->cScreens; ++i)
+ {
+ pVBox->cbFBMax -= VBVA_MIN_BUFFER_SIZE;
+ pVBox->pScreens[i].aoffVBVABuffer = pVBox->cbFBMax;
+ TRACE_LOG("VBVA buffer offset for screen %u: 0x%lx\n", i,
+ (unsigned long) pVBox->cbFBMax);
+ VBoxVBVASetupBufferContext(&pVBox->pScreens[i].aVbvaCtx,
+ pVBox->pScreens[i].aoffVBVABuffer,
+ VBVA_MIN_BUFFER_SIZE);
+ }
+ TRACE_LOG("Maximum framebuffer size: %lu (0x%lx)\n",
+ (unsigned long) pVBox->cbFBMax,
+ (unsigned long) pVBox->cbFBMax);
+ rc = VBoxHGSMISendViewInfo(&pVBox->guestCtx, pVBox->cScreens,
+ vboxFillViewInfo, (void *)pVBox);
+ AssertMsg(RT_SUCCESS(rc), ("Failed to send the view information to the host, rc=%d\n", rc));
+ return TRUE;
+}
+
+static Bool haveHGSMIModeHintAndCursorReportingInterface(VBOXPtr pVBox)
+{
+ uint32_t fModeHintReporting, fCursorReporting;
+
+ return RT_SUCCESS(VBoxQueryConfHGSMI(&pVBox->guestCtx, VBOX_VBVA_CONF32_MODE_HINT_REPORTING, &fModeHintReporting))
+ && RT_SUCCESS(VBoxQueryConfHGSMI(&pVBox->guestCtx, VBOX_VBVA_CONF32_GUEST_CURSOR_REPORTING, &fCursorReporting))
+ && fModeHintReporting == VINF_SUCCESS
+ && fCursorReporting == VINF_SUCCESS;
+}
+
+static Bool hostHasScreenBlankingFlag(VBOXPtr pVBox)
+{
+ uint32_t fScreenFlags;
+
+ return RT_SUCCESS(VBoxQueryConfHGSMI(&pVBox->guestCtx, VBOX_VBVA_CONF32_SCREEN_FLAGS, &fScreenFlags))
+ && fScreenFlags & VBVA_SCREEN_F_BLANK;
+}
+
+/**
+ * Inform VBox that we will supply it with dirty rectangle information
+ * and install the dirty rectangle handler.
+ *
+ * @returns TRUE for success, FALSE for failure
+ * @param pScrn Pointer to a structure describing the X screen in use
+ */
+Bool
+vboxEnableVbva(ScrnInfoPtr pScrn)
+{
+ Bool rc = TRUE;
+ unsigned i;
+ VBOXPtr pVBox = pScrn->driverPrivate;
+
+ TRACE_ENTRY();
+ if (!vboxSetupVRAMVbva(pVBox))
+ return FALSE;
+ for (i = 0; i < pVBox->cScreens; ++i)
+ {
+ struct VBVABUFFER *pVBVA;
+
+ pVBVA = (struct VBVABUFFER *) ( ((uint8_t *)pVBox->base)
+ + pVBox->pScreens[i].aoffVBVABuffer);
+ if (!VBoxVBVAEnable(&pVBox->pScreens[i].aVbvaCtx, &pVBox->guestCtx,
+ pVBVA, i))
+ rc = FALSE;
+ }
+ AssertMsg(rc, ("Failed to enable screen update reporting for at least one virtual monitor.\n"));
+ pVBox->fHaveHGSMIModeHints = haveHGSMIModeHintAndCursorReportingInterface(pVBox);
+ pVBox->fHostHasScreenBlankingFlag = hostHasScreenBlankingFlag(pVBox);
+ return rc;
+}
+
+/**
+ * Inform VBox that we will stop supplying it with dirty rectangle
+ * information. This function is intended to be called when an X
+ * virtual terminal is disabled, or the X server is terminated.
+ *
+ * @returns TRUE for success, FALSE for failure
+ * @param pScrn Pointer to a structure describing the X screen in use
+ */
+void
+vboxDisableVbva(ScrnInfoPtr pScrn)
+{
+ unsigned i;
+ VBOXPtr pVBox = pScrn->driverPrivate;
+
+ TRACE_ENTRY();
+ for (i = 0; i < pVBox->cScreens; ++i)
+ VBoxVBVADisable(&pVBox->pScreens[i].aVbvaCtx, &pVBox->guestCtx, i);
+}
diff --git a/src/version-generated.h b/src/version-generated.h
new file mode 100644
index 0000000..b2a3279
--- /dev/null
+++ b/src/version-generated.h
@@ -0,0 +1,14 @@
+#ifndef ___version_generated_h___
+#define ___version_generated_h___
+
+#define VBOX_VERSION_MAJOR 5
+#define VBOX_VERSION_MINOR 2
+#define VBOX_VERSION_BUILD 0
+#define VBOX_VERSION_PRERELEASE "RC1"
+#define VBOX_VERSION_STRING_RAW "5.2.0"
+#define VBOX_VERSION_STRING "5.2.0_RC1"
+#define VBOX_API_VERSION_STRING "5_2"
+
+#define VBOX_PRIVATE_BUILD_DESC "Private build by michael"
+
+#endif