diff options
author | Anas Nashif <anas.nashif@intel.com> | 2012-11-06 21:17:37 -0800 |
---|---|---|
committer | Anas Nashif <anas.nashif@intel.com> | 2012-11-06 21:17:37 -0800 |
commit | 9aa09856bf24e0a58e4b63034a80c948a1f44c53 (patch) | |
tree | 103710a7f7efc528607be5c3872bd162af08b936 /src | |
download | xf86-video-vmware-9aa09856bf24e0a58e4b63034a80c948a1f44c53.tar.gz xf86-video-vmware-9aa09856bf24e0a58e4b63034a80c948a1f44c53.tar.bz2 xf86-video-vmware-9aa09856bf24e0a58e4b63034a80c948a1f44c53.zip |
Imported Upstream version 12.0.2.007bed3upstream/12.0.2.007bed3upstream/12.0.212.0.2upstream
Diffstat (limited to 'src')
-rw-r--r-- | src/Makefile.am | 63 | ||||
-rw-r--r-- | src/Makefile.in | 711 | ||||
-rw-r--r-- | src/bits2pixels.c | 1418 | ||||
-rw-r--r-- | src/bits2pixels.h | 23 | ||||
-rw-r--r-- | src/compat-api.h | 99 | ||||
-rw-r--r-- | src/guest_os.h | 28 | ||||
-rw-r--r-- | src/includeCheck.h | 2 | ||||
-rw-r--r-- | src/svga_escape.h | 30 | ||||
-rw-r--r-- | src/svga_limits.h | 55 | ||||
-rw-r--r-- | src/svga_modes.h | 48 | ||||
-rw-r--r-- | src/svga_overlay.h | 50 | ||||
-rw-r--r-- | src/svga_reg.h | 1566 | ||||
-rw-r--r-- | src/svga_struct.h | 40 | ||||
-rw-r--r-- | src/vm_basic_types.h | 171 | ||||
-rw-r--r-- | src/vm_device_version.h | 62 | ||||
-rw-r--r-- | src/vmware.c | 1666 | ||||
-rw-r--r-- | src/vmware.h | 316 | ||||
-rw-r--r-- | src/vmware_bootstrap.c | 502 | ||||
-rw-r--r-- | src/vmware_bootstrap.h | 71 | ||||
-rw-r--r-- | src/vmware_common.c | 163 | ||||
-rw-r--r-- | src/vmware_common.h | 43 | ||||
-rw-r--r-- | src/vmwarectrl.c | 624 | ||||
-rw-r--r-- | src/vmwarectrl.h | 48 | ||||
-rw-r--r-- | src/vmwarectrlproto.h | 122 | ||||
-rw-r--r-- | src/vmwarecurs.c | 487 | ||||
-rw-r--r-- | src/vmwaremodes.c | 163 | ||||
-rw-r--r-- | src/vmwarevideo.c | 1352 | ||||
-rw-r--r-- | src/vmwarexinerama.c | 728 |
28 files changed, 10651 insertions, 0 deletions
diff --git a/src/Makefile.am b/src/Makefile.am new file mode 100644 index 0000000..b0dd147 --- /dev/null +++ b/src/Makefile.am @@ -0,0 +1,63 @@ +# 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. + +# 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. + +vmware_drv_la_LTLIBRARIES = vmware_drv.la +vmware_drv_la_LDFLAGS = -module -avoid-version +vmware_drv_la_CFLAGS = $(CWARNFLAGS) @XORG_CFLAGS@ +vmware_drv_ladir = @moduledir@/drivers + +if BUILD_VMWGFX +vmware_drv_la_LIBADD = $(top_builddir)/vmwgfx/libvmwgfx.la +vmware_drv_la_DEPENDENCIES = $(top_builddir)/vmwgfx/libvmwgfx.la +endif + +vmware_drv_la_SOURCES = \ + bits2pixels.c \ + bits2pixels.h \ + compat-api.h \ + guest_os.h \ + includeCheck.h \ + svga_escape.h \ + svga_limits.h \ + svga_modes.h \ + svga_overlay.h \ + svga_reg.h \ + svga_struct.h \ + vm_basic_types.h \ + vm_device_version.h \ + vmware.c \ + vmwarecurs.c \ + vmware.h \ + vmwarectrl.c \ + vmwarectrl.h \ + vmwarectrlproto.h \ + vmwarexinerama.c \ + vmwarevideo.c \ + vmwaremodes.c \ + vmware_bootstrap.h \ + vmware_bootstrap.c \ + vmware_common.c \ + vmware_common.h diff --git a/src/Makefile.in b/src/Makefile.in new file mode 100644 index 0000000..1c6fb5d --- /dev/null +++ b/src/Makefile.in @@ -0,0 +1,711 @@ +# Makefile.in generated by automake 1.11.1 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, +# 2003, 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation, +# Inc. +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + +# 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. + +# 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. + +VPATH = @srcdir@ +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +subdir = src +DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = $(top_builddir)/config.h +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; +am__vpath_adj = case $$p in \ + $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ + *) f=$$p;; \ + esac; +am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; +am__install_max = 40 +am__nobase_strip_setup = \ + srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` +am__nobase_strip = \ + for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" +am__nobase_list = $(am__nobase_strip_setup); \ + for p in $$list; do echo "$$p $$p"; done | \ + sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ + $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ + if (++n[$$2] == $(am__install_max)) \ + { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ + END { for (dir in files) print dir, files[dir] }' +am__base_list = \ + sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ + sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' +am__installdirs = "$(DESTDIR)$(vmware_drv_ladir)" +LTLIBRARIES = $(vmware_drv_la_LTLIBRARIES) +am_vmware_drv_la_OBJECTS = vmware_drv_la-bits2pixels.lo \ + vmware_drv_la-vmware.lo vmware_drv_la-vmwarecurs.lo \ + vmware_drv_la-vmwarectrl.lo vmware_drv_la-vmwarexinerama.lo \ + vmware_drv_la-vmwarevideo.lo vmware_drv_la-vmwaremodes.lo \ + vmware_drv_la-vmware_bootstrap.lo \ + vmware_drv_la-vmware_common.lo +vmware_drv_la_OBJECTS = $(am_vmware_drv_la_OBJECTS) +AM_V_lt = $(am__v_lt_$(V)) +am__v_lt_ = $(am__v_lt_$(AM_DEFAULT_VERBOSITY)) +am__v_lt_0 = --silent +vmware_drv_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CCLD) $(vmware_drv_la_CFLAGS) \ + $(CFLAGS) $(vmware_drv_la_LDFLAGS) $(LDFLAGS) -o $@ +DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) +depcomp = $(SHELL) $(top_srcdir)/depcomp +am__depfiles_maybe = depfiles +am__mv = mv -f +COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ + $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ + $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ + $(AM_CFLAGS) $(CFLAGS) +AM_V_CC = $(am__v_CC_$(V)) +am__v_CC_ = $(am__v_CC_$(AM_DEFAULT_VERBOSITY)) +am__v_CC_0 = @echo " CC " $@; +AM_V_at = $(am__v_at_$(V)) +am__v_at_ = $(am__v_at_$(AM_DEFAULT_VERBOSITY)) +am__v_at_0 = @ +CCLD = $(CC) +LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ + $(AM_LDFLAGS) $(LDFLAGS) -o $@ +AM_V_CCLD = $(am__v_CCLD_$(V)) +am__v_CCLD_ = $(am__v_CCLD_$(AM_DEFAULT_VERBOSITY)) +am__v_CCLD_0 = @echo " CCLD " $@; +AM_V_GEN = $(am__v_GEN_$(V)) +am__v_GEN_ = $(am__v_GEN_$(AM_DEFAULT_VERBOSITY)) +am__v_GEN_0 = @echo " GEN " $@; +SOURCES = $(vmware_drv_la_SOURCES) +DIST_SOURCES = $(vmware_drv_la_SOURCES) +ETAGS = etags +CTAGS = ctags +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +ADMIN_MAN_DIR = @ADMIN_MAN_DIR@ +ADMIN_MAN_SUFFIX = @ADMIN_MAN_SUFFIX@ +AMTAR = @AMTAR@ +AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +APP_MAN_DIR = @APP_MAN_DIR@ +APP_MAN_SUFFIX = @APP_MAN_SUFFIX@ +AR = @AR@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +BASE_CFLAGS = @BASE_CFLAGS@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CHANGELOG_CMD = @CHANGELOG_CMD@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CWARNFLAGS = @CWARNFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DRIVER_MAN_DIR = @DRIVER_MAN_DIR@ +DRIVER_MAN_SUFFIX = @DRIVER_MAN_SUFFIX@ +DRIVER_NAME = @DRIVER_NAME@ +DSYMUTIL = @DSYMUTIL@ +DUMPBIN = @DUMPBIN@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +FGREP = @FGREP@ +FILE_MAN_DIR = @FILE_MAN_DIR@ +FILE_MAN_SUFFIX = @FILE_MAN_SUFFIX@ +GREP = @GREP@ +INSTALL = @INSTALL@ +INSTALL_CMD = @INSTALL_CMD@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +LD = @LD@ +LDFLAGS = @LDFLAGS@ +LIBDRM_CFLAGS = @LIBDRM_CFLAGS@ +LIBDRM_LIBS = @LIBDRM_LIBS@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBTOOL = @LIBTOOL@ +LIB_MAN_DIR = @LIB_MAN_DIR@ +LIB_MAN_SUFFIX = @LIB_MAN_SUFFIX@ +LIPO = @LIPO@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +MAINT = @MAINT@ +MAKEINFO = @MAKEINFO@ +MAN_SUBSTS = @MAN_SUBSTS@ +MISC_MAN_DIR = @MISC_MAN_DIR@ +MISC_MAN_SUFFIX = @MISC_MAN_SUFFIX@ +MKDIR_P = @MKDIR_P@ +NM = @NM@ +NMEDIT = @NMEDIT@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +OTOOL = @OTOOL@ +OTOOL64 = @OTOOL64@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PCIACCESS_CFLAGS = @PCIACCESS_CFLAGS@ +PCIACCESS_LIBS = @PCIACCESS_LIBS@ +PKG_CONFIG = @PKG_CONFIG@ +PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ +PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ +RANLIB = @RANLIB@ +SED = @SED@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +STRICT_CFLAGS = @STRICT_CFLAGS@ +STRIP = @STRIP@ +VERSION = @VERSION@ +X11_CFLAGS = @X11_CFLAGS@ +X11_LIBS = @X11_LIBS@ +XATRACKER_CFLAGS = @XATRACKER_CFLAGS@ +XATRACKER_LIBS = @XATRACKER_LIBS@ +XORG_CFLAGS = @XORG_CFLAGS@ +XORG_LIBS = @XORG_LIBS@ +XORG_MAN_PAGE = @XORG_MAN_PAGE@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +lt_ECHO = @lt_ECHO@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +moduledir = @moduledir@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +srcdir = @srcdir@ +sysconfdir = @sysconfdir@ +target_alias = @target_alias@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +vmware_drv_la_LTLIBRARIES = vmware_drv.la +vmware_drv_la_LDFLAGS = -module -avoid-version +vmware_drv_la_CFLAGS = $(CWARNFLAGS) @XORG_CFLAGS@ +vmware_drv_ladir = @moduledir@/drivers +@BUILD_VMWGFX_TRUE@vmware_drv_la_LIBADD = $(top_builddir)/vmwgfx/libvmwgfx.la +@BUILD_VMWGFX_TRUE@vmware_drv_la_DEPENDENCIES = $(top_builddir)/vmwgfx/libvmwgfx.la +vmware_drv_la_SOURCES = \ + bits2pixels.c \ + bits2pixels.h \ + compat-api.h \ + guest_os.h \ + includeCheck.h \ + svga_escape.h \ + svga_limits.h \ + svga_modes.h \ + svga_overlay.h \ + svga_reg.h \ + svga_struct.h \ + vm_basic_types.h \ + vm_device_version.h \ + vmware.c \ + vmwarecurs.c \ + vmware.h \ + vmwarectrl.c \ + vmwarectrl.h \ + vmwarectrlproto.h \ + vmwarexinerama.c \ + vmwarevideo.c \ + vmwaremodes.c \ + vmware_bootstrap.h \ + vmware_bootstrap.c \ + vmware_common.c \ + vmware_common.h + +all: all-am + +.SUFFIXES: +.SUFFIXES: .c .lo .o .obj +$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign src/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --foreign src/Makefile +.PRECIOUS: Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): +install-vmware_drv_laLTLIBRARIES: $(vmware_drv_la_LTLIBRARIES) + @$(NORMAL_INSTALL) + test -z "$(vmware_drv_ladir)" || $(MKDIR_P) "$(DESTDIR)$(vmware_drv_ladir)" + @list='$(vmware_drv_la_LTLIBRARIES)'; test -n "$(vmware_drv_ladir)" || list=; \ + list2=; for p in $$list; do \ + if test -f $$p; then \ + list2="$$list2 $$p"; \ + else :; fi; \ + done; \ + test -z "$$list2" || { \ + echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 '$(DESTDIR)$(vmware_drv_ladir)'"; \ + $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 "$(DESTDIR)$(vmware_drv_ladir)"; \ + } + +uninstall-vmware_drv_laLTLIBRARIES: + @$(NORMAL_UNINSTALL) + @list='$(vmware_drv_la_LTLIBRARIES)'; test -n "$(vmware_drv_ladir)" || list=; \ + for p in $$list; do \ + $(am__strip_dir) \ + echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(vmware_drv_ladir)/$$f'"; \ + $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(vmware_drv_ladir)/$$f"; \ + done + +clean-vmware_drv_laLTLIBRARIES: + -test -z "$(vmware_drv_la_LTLIBRARIES)" || rm -f $(vmware_drv_la_LTLIBRARIES) + @list='$(vmware_drv_la_LTLIBRARIES)'; for p in $$list; do \ + dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \ + test "$$dir" != "$$p" || dir=.; \ + echo "rm -f \"$${dir}/so_locations\""; \ + rm -f "$${dir}/so_locations"; \ + done +vmware_drv.la: $(vmware_drv_la_OBJECTS) $(vmware_drv_la_DEPENDENCIES) + $(AM_V_CCLD)$(vmware_drv_la_LINK) -rpath $(vmware_drv_ladir) $(vmware_drv_la_OBJECTS) $(vmware_drv_la_LIBADD) $(LIBS) + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/vmware_drv_la-bits2pixels.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/vmware_drv_la-vmware.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/vmware_drv_la-vmware_bootstrap.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/vmware_drv_la-vmware_common.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/vmware_drv_la-vmwarectrl.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/vmware_drv_la-vmwarecurs.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/vmware_drv_la-vmwaremodes.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/vmware_drv_la-vmwarevideo.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/vmware_drv_la-vmwarexinerama.Plo@am__quote@ + +.c.o: +@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(COMPILE) -c $< + +.c.obj: +@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(COMPILE) -c `$(CYGPATH_W) '$<'` + +.c.lo: +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo +@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LTCOMPILE) -c -o $@ $< + +vmware_drv_la-bits2pixels.lo: bits2pixels.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(vmware_drv_la_CFLAGS) $(CFLAGS) -MT vmware_drv_la-bits2pixels.lo -MD -MP -MF $(DEPDIR)/vmware_drv_la-bits2pixels.Tpo -c -o vmware_drv_la-bits2pixels.lo `test -f 'bits2pixels.c' || echo '$(srcdir)/'`bits2pixels.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/vmware_drv_la-bits2pixels.Tpo $(DEPDIR)/vmware_drv_la-bits2pixels.Plo +@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='bits2pixels.c' object='vmware_drv_la-bits2pixels.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(vmware_drv_la_CFLAGS) $(CFLAGS) -c -o vmware_drv_la-bits2pixels.lo `test -f 'bits2pixels.c' || echo '$(srcdir)/'`bits2pixels.c + +vmware_drv_la-vmware.lo: vmware.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(vmware_drv_la_CFLAGS) $(CFLAGS) -MT vmware_drv_la-vmware.lo -MD -MP -MF $(DEPDIR)/vmware_drv_la-vmware.Tpo -c -o vmware_drv_la-vmware.lo `test -f 'vmware.c' || echo '$(srcdir)/'`vmware.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/vmware_drv_la-vmware.Tpo $(DEPDIR)/vmware_drv_la-vmware.Plo +@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='vmware.c' object='vmware_drv_la-vmware.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(vmware_drv_la_CFLAGS) $(CFLAGS) -c -o vmware_drv_la-vmware.lo `test -f 'vmware.c' || echo '$(srcdir)/'`vmware.c + +vmware_drv_la-vmwarecurs.lo: vmwarecurs.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(vmware_drv_la_CFLAGS) $(CFLAGS) -MT vmware_drv_la-vmwarecurs.lo -MD -MP -MF $(DEPDIR)/vmware_drv_la-vmwarecurs.Tpo -c -o vmware_drv_la-vmwarecurs.lo `test -f 'vmwarecurs.c' || echo '$(srcdir)/'`vmwarecurs.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/vmware_drv_la-vmwarecurs.Tpo $(DEPDIR)/vmware_drv_la-vmwarecurs.Plo +@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='vmwarecurs.c' object='vmware_drv_la-vmwarecurs.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(vmware_drv_la_CFLAGS) $(CFLAGS) -c -o vmware_drv_la-vmwarecurs.lo `test -f 'vmwarecurs.c' || echo '$(srcdir)/'`vmwarecurs.c + +vmware_drv_la-vmwarectrl.lo: vmwarectrl.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(vmware_drv_la_CFLAGS) $(CFLAGS) -MT vmware_drv_la-vmwarectrl.lo -MD -MP -MF $(DEPDIR)/vmware_drv_la-vmwarectrl.Tpo -c -o vmware_drv_la-vmwarectrl.lo `test -f 'vmwarectrl.c' || echo '$(srcdir)/'`vmwarectrl.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/vmware_drv_la-vmwarectrl.Tpo $(DEPDIR)/vmware_drv_la-vmwarectrl.Plo +@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='vmwarectrl.c' object='vmware_drv_la-vmwarectrl.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(vmware_drv_la_CFLAGS) $(CFLAGS) -c -o vmware_drv_la-vmwarectrl.lo `test -f 'vmwarectrl.c' || echo '$(srcdir)/'`vmwarectrl.c + +vmware_drv_la-vmwarexinerama.lo: vmwarexinerama.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(vmware_drv_la_CFLAGS) $(CFLAGS) -MT vmware_drv_la-vmwarexinerama.lo -MD -MP -MF $(DEPDIR)/vmware_drv_la-vmwarexinerama.Tpo -c -o vmware_drv_la-vmwarexinerama.lo `test -f 'vmwarexinerama.c' || echo '$(srcdir)/'`vmwarexinerama.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/vmware_drv_la-vmwarexinerama.Tpo $(DEPDIR)/vmware_drv_la-vmwarexinerama.Plo +@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='vmwarexinerama.c' object='vmware_drv_la-vmwarexinerama.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(vmware_drv_la_CFLAGS) $(CFLAGS) -c -o vmware_drv_la-vmwarexinerama.lo `test -f 'vmwarexinerama.c' || echo '$(srcdir)/'`vmwarexinerama.c + +vmware_drv_la-vmwarevideo.lo: vmwarevideo.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(vmware_drv_la_CFLAGS) $(CFLAGS) -MT vmware_drv_la-vmwarevideo.lo -MD -MP -MF $(DEPDIR)/vmware_drv_la-vmwarevideo.Tpo -c -o vmware_drv_la-vmwarevideo.lo `test -f 'vmwarevideo.c' || echo '$(srcdir)/'`vmwarevideo.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/vmware_drv_la-vmwarevideo.Tpo $(DEPDIR)/vmware_drv_la-vmwarevideo.Plo +@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='vmwarevideo.c' object='vmware_drv_la-vmwarevideo.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(vmware_drv_la_CFLAGS) $(CFLAGS) -c -o vmware_drv_la-vmwarevideo.lo `test -f 'vmwarevideo.c' || echo '$(srcdir)/'`vmwarevideo.c + +vmware_drv_la-vmwaremodes.lo: vmwaremodes.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(vmware_drv_la_CFLAGS) $(CFLAGS) -MT vmware_drv_la-vmwaremodes.lo -MD -MP -MF $(DEPDIR)/vmware_drv_la-vmwaremodes.Tpo -c -o vmware_drv_la-vmwaremodes.lo `test -f 'vmwaremodes.c' || echo '$(srcdir)/'`vmwaremodes.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/vmware_drv_la-vmwaremodes.Tpo $(DEPDIR)/vmware_drv_la-vmwaremodes.Plo +@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='vmwaremodes.c' object='vmware_drv_la-vmwaremodes.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(vmware_drv_la_CFLAGS) $(CFLAGS) -c -o vmware_drv_la-vmwaremodes.lo `test -f 'vmwaremodes.c' || echo '$(srcdir)/'`vmwaremodes.c + +vmware_drv_la-vmware_bootstrap.lo: vmware_bootstrap.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(vmware_drv_la_CFLAGS) $(CFLAGS) -MT vmware_drv_la-vmware_bootstrap.lo -MD -MP -MF $(DEPDIR)/vmware_drv_la-vmware_bootstrap.Tpo -c -o vmware_drv_la-vmware_bootstrap.lo `test -f 'vmware_bootstrap.c' || echo '$(srcdir)/'`vmware_bootstrap.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/vmware_drv_la-vmware_bootstrap.Tpo $(DEPDIR)/vmware_drv_la-vmware_bootstrap.Plo +@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='vmware_bootstrap.c' object='vmware_drv_la-vmware_bootstrap.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(vmware_drv_la_CFLAGS) $(CFLAGS) -c -o vmware_drv_la-vmware_bootstrap.lo `test -f 'vmware_bootstrap.c' || echo '$(srcdir)/'`vmware_bootstrap.c + +vmware_drv_la-vmware_common.lo: vmware_common.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(vmware_drv_la_CFLAGS) $(CFLAGS) -MT vmware_drv_la-vmware_common.lo -MD -MP -MF $(DEPDIR)/vmware_drv_la-vmware_common.Tpo -c -o vmware_drv_la-vmware_common.lo `test -f 'vmware_common.c' || echo '$(srcdir)/'`vmware_common.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/vmware_drv_la-vmware_common.Tpo $(DEPDIR)/vmware_drv_la-vmware_common.Plo +@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='vmware_common.c' object='vmware_drv_la-vmware_common.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(vmware_drv_la_CFLAGS) $(CFLAGS) -c -o vmware_drv_la-vmware_common.lo `test -f 'vmware_common.c' || echo '$(srcdir)/'`vmware_common.c + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs + +ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + mkid -fID $$unique +tags: TAGS + +TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + set x; \ + here=`pwd`; \ + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + shift; \ + if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + if test $$# -gt 0; then \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + "$$@" $$unique; \ + else \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$unique; \ + fi; \ + fi +ctags: CTAGS +CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + test -z "$(CTAGS_ARGS)$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && $(am__cd) $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) "$$here" + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +distdir: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-am +all-am: Makefile $(LTLIBRARIES) +installdirs: + for dir in "$(DESTDIR)$(vmware_drv_ladir)"; do \ + test -z "$$dir" || $(MKDIR_P) "$$dir"; \ + done +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + `test -z '$(STRIP)' || \ + echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-am + +clean-am: clean-generic clean-libtool clean-vmware_drv_laLTLIBRARIES \ + mostlyclean-am + +distclean: distclean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +distclean-am: clean-am distclean-compile distclean-generic \ + distclean-tags + +dvi: dvi-am + +dvi-am: + +html: html-am + +html-am: + +info: info-am + +info-am: + +install-data-am: install-vmware_drv_laLTLIBRARIES + +install-dvi: install-dvi-am + +install-dvi-am: + +install-exec-am: + +install-html: install-html-am + +install-html-am: + +install-info: install-info-am + +install-info-am: + +install-man: + +install-pdf: install-pdf-am + +install-pdf-am: + +install-ps: install-ps-am + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-compile mostlyclean-generic \ + mostlyclean-libtool + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: uninstall-vmware_drv_laLTLIBRARIES + +.MAKE: install-am install-strip + +.PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \ + clean-libtool clean-vmware_drv_laLTLIBRARIES ctags distclean \ + distclean-compile distclean-generic distclean-libtool \ + distclean-tags distdir dvi dvi-am html html-am info info-am \ + install install-am install-data install-data-am install-dvi \ + install-dvi-am install-exec install-exec-am install-html \ + install-html-am install-info install-info-am install-man \ + install-pdf install-pdf-am install-ps install-ps-am \ + install-strip install-vmware_drv_laLTLIBRARIES installcheck \ + installcheck-am installdirs maintainer-clean \ + maintainer-clean-generic mostlyclean mostlyclean-compile \ + mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ + tags uninstall uninstall-am uninstall-vmware_drv_laLTLIBRARIES + + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/src/bits2pixels.c b/src/bits2pixels.c new file mode 100644 index 0000000..e3801c5 --- /dev/null +++ b/src/bits2pixels.c @@ -0,0 +1,1418 @@ +/* ********************************************************** + * Copyright (C) 1999-2001 VMware, Inc. + * All Rights Reserved + * **********************************************************/ +#ifdef VMX86_DEVEL +char rcsId_bits2pixels[] = "Id: bits2pixels.c,v 1.6 2001/01/26 23:32:15 yoel Exp $"; +#else +#define FILECODE "F(814)" +#endif + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +/* + * bits2pixels.c -- + * + * Emulation routines to convert bitmaps to pixmaps + */ + +#include "vm_basic_types.h" +#include "bits2pixels.h" + + +/* + * Local functions + */ + +static void RasterBitsToPixels8(uint8 *bits, uint32 bits_increment, + uint8 *pix, uint32 pix_increment, + uint32 width, uint32 height, uint32 fg, uint32 bg); + +static void RasterBitsToPixels16(uint8 *bits, uint32 bits_increment, + uint8 *pix, uint32 pix_increment, + uint32 width, uint32 height, uint32 fg, uint32 bg); + +static void RasterBitsToPixels24(uint8 *bits, uint32 bits_increment, + uint8 *pix, uint32 pix_increment, + uint32 width, uint32 height, uint32 fg, uint32 bg); + +static void RasterBitsToPixels32(uint8 *bits, uint32 bits_increment, + uint8 *pix, uint32 pix_increment, + uint32 width, uint32 height, uint32 fg, uint32 bg); + + +/* + *---------------------------------------------------------------------- + * + * vmwareRaster_BitsToPixels -- + * + * Convert a bitmap to a pixmap, converting 1 bits to the foreground + * color (fg) and 0 bits to the background color (bg). + * + * Results: + * Pixmap filled with pixels + * + * Side effects: + * None + * + *---------------------------------------------------------------------- + */ + +void +vmwareRaster_BitsToPixels(uint8 *bits, uint32 bits_increment, + uint8 *pix, uint32 pix_increment, int bytes_per_pixel, + uint32 width, uint32 height, uint32 fg, uint32 bg) +{ + switch (bytes_per_pixel) { + case 1: + RasterBitsToPixels8(bits, bits_increment, pix, pix_increment, + width, height, fg, bg); + break; + + case 2: + RasterBitsToPixels16(bits, bits_increment, pix, pix_increment, + width, height, fg, bg); + break; + + case 3: + RasterBitsToPixels24(bits, bits_increment, pix, pix_increment, + width, height, fg, bg); + break; + + case 4: + RasterBitsToPixels32(bits, bits_increment, pix, pix_increment, + width, height, fg, bg); + break; + } +} + + +/* + *---------------------------------------------------------------------- + * + * RasterBitsToPixels8 -- + * + * Convert a bitmap to a pixmap, converting 1 bits to the foreground + * color (fg) and 0 bits to the background color (bg), for an 8-bit + * pixmap + * + * Results: + * Pixmap filled with pixels + * + * Side effects: + * None + * + *---------------------------------------------------------------------- + */ + +void +RasterBitsToPixels8(uint8 *bits, uint32 bits_increment, + uint8 *pix, uint32 pix_increment, + uint32 width, uint32 height, uint32 fg, uint32 bg) +{ + uint8 *lpix, *lbits; + int i, j; + uint32 expbits = 0; /* Bits to be expanded */ + + for (i=0; i<height; i++) { + lpix = pix; + lbits = bits; + for (j = width ; j > 0; j -= 4) { + expbits = (*lbits >> 4) & 0x0f; + + if (j < 4) + break; + + switch (expbits) { + case 0: + *lpix++ = bg; + *lpix++ = bg; + *lpix++ = bg; + *lpix++ = bg; + break; + case 1: + *lpix++ = bg; + *lpix++ = bg; + *lpix++ = bg; + *lpix++ = fg; + break; + case 2: + *lpix++ = bg; + *lpix++ = bg; + *lpix++ = fg; + *lpix++ = bg; + break; + case 3: + *lpix++ = bg; + *lpix++ = bg; + *lpix++ = fg; + *lpix++ = fg; + break; + case 4: + *lpix++ = bg; + *lpix++ = fg; + *lpix++ = bg; + *lpix++ = bg; + break; + case 5: + *lpix++ = bg; + *lpix++ = fg; + *lpix++ = bg; + *lpix++ = fg; + break; + case 6: + *lpix++ = bg; + *lpix++ = fg; + *lpix++ = fg; + *lpix++ = bg; + break; + case 7: + *lpix++ = bg; + *lpix++ = fg; + *lpix++ = fg; + *lpix++ = fg; + break; + case 8: + *lpix++ = fg; + *lpix++ = bg; + *lpix++ = bg; + *lpix++ = bg; + break; + case 9: + *lpix++ = fg; + *lpix++ = bg; + *lpix++ = bg; + *lpix++ = fg; + break; + case 10: + *lpix++ = fg; + *lpix++ = bg; + *lpix++ = fg; + *lpix++ = bg; + break; + case 11: + *lpix++ = fg; + *lpix++ = bg; + *lpix++ = fg; + *lpix++ = fg; + break; + case 12: + *lpix++ = fg; + *lpix++ = fg; + *lpix++ = bg; + *lpix++ = bg; + break; + case 13: + *lpix++ = fg; + *lpix++ = fg; + *lpix++ = bg; + *lpix++ = fg; + break; + case 14: + *lpix++ = fg; + *lpix++ = fg; + *lpix++ = fg; + *lpix++ = bg; + break; + case 15: + *lpix++ = fg; + *lpix++ = fg; + *lpix++ = fg; + *lpix++ = fg; + break; + } + + expbits = *lbits & 0x0f; + + j -= 4; + if (j < 4) { + break; + } + + switch (expbits) { + case 0: + *lpix++ = bg; + *lpix++ = bg; + *lpix++ = bg; + *lpix++ = bg; + break; + case 1: + *lpix++ = bg; + *lpix++ = bg; + *lpix++ = bg; + *lpix++ = fg; + break; + case 2: + *lpix++ = bg; + *lpix++ = bg; + *lpix++ = fg; + *lpix++ = bg; + break; + case 3: + *lpix++ = bg; + *lpix++ = bg; + *lpix++ = fg; + *lpix++ = fg; + break; + case 4: + *lpix++ = bg; + *lpix++ = fg; + *lpix++ = bg; + *lpix++ = bg; + break; + case 5: + *lpix++ = bg; + *lpix++ = fg; + *lpix++ = bg; + *lpix++ = fg; + break; + case 6: + *lpix++ = bg; + *lpix++ = fg; + *lpix++ = fg; + *lpix++ = bg; + break; + case 7: + *lpix++ = bg; + *lpix++ = fg; + *lpix++ = fg; + *lpix++ = fg; + break; + case 8: + *lpix++ = fg; + *lpix++ = bg; + *lpix++ = bg; + *lpix++ = bg; + break; + case 9: + *lpix++ = fg; + *lpix++ = bg; + *lpix++ = bg; + *lpix++ = fg; + break; + case 10: + *lpix++ = fg; + *lpix++ = bg; + *lpix++ = fg; + *lpix++ = bg; + break; + case 11: + *lpix++ = fg; + *lpix++ = bg; + *lpix++ = fg; + *lpix++ = fg; + break; + case 12: + *lpix++ = fg; + *lpix++ = fg; + *lpix++ = bg; + *lpix++ = bg; + break; + case 13: + *lpix++ = fg; + *lpix++ = fg; + *lpix++ = bg; + *lpix++ = fg; + break; + case 14: + *lpix++ = fg; + *lpix++ = fg; + *lpix++ = fg; + *lpix++ = bg; + break; + case 15: + *lpix++ = fg; + *lpix++ = fg; + *lpix++ = fg; + *lpix++ = fg; + break; + } + lbits++; + } + + if (j > 0) { + *lpix++ = (expbits & 0x08) ? fg : bg; + j--; + if (j > 0) { + *lpix++ = (expbits & 0x04) ? fg : bg; + j--; + if (j > 0) { + *lpix++ = (expbits & 0x02) ? fg : bg; + j--; + } + } + } + + pix += pix_increment; + bits += bits_increment; + } + return; +} + + +/* + *---------------------------------------------------------------------- + * + * RasterBitsToPixels16 -- + * + * Convert a bitmap to a pixmap, converting 1 bits to the foreground + * color (fg) and 0 bits to the background color (bg), for a 16-bit + * pixmap + * + * Results: + * Pixmap filled with pixels + * + * Side effects: + * None + * + *---------------------------------------------------------------------- + */ + +void +RasterBitsToPixels16(uint8 *bits, uint32 bits_increment, + uint8 *pix, uint32 pix_increment, + uint32 width, uint32 height, uint32 fg, uint32 bg) +{ + uint16 *lpix; + uint8 *lbits; + int i, j; + uint32 expbits = 0; /* Bits to be expanded */ + + for (i=0; i<height; i++) { + lpix = (uint16 *)pix; + lbits = bits; + for (j = width; j > 0; j -= 4) { + expbits = (*lbits >> 4) & 0x0f; + + if (j < 4) + break; + + switch (expbits) { + case 0: + *lpix++ = bg; + *lpix++ = bg; + *lpix++ = bg; + *lpix++ = bg; + break; + case 1: + *lpix++ = bg; + *lpix++ = bg; + *lpix++ = bg; + *lpix++ = fg; + break; + case 2: + *lpix++ = bg; + *lpix++ = bg; + *lpix++ = fg; + *lpix++ = bg; + break; + case 3: + *lpix++ = bg; + *lpix++ = bg; + *lpix++ = fg; + *lpix++ = fg; + break; + case 4: + *lpix++ = bg; + *lpix++ = fg; + *lpix++ = bg; + *lpix++ = bg; + break; + case 5: + *lpix++ = bg; + *lpix++ = fg; + *lpix++ = bg; + *lpix++ = fg; + break; + case 6: + *lpix++ = bg; + *lpix++ = fg; + *lpix++ = fg; + *lpix++ = bg; + break; + case 7: + *lpix++ = bg; + *lpix++ = fg; + *lpix++ = fg; + *lpix++ = fg; + break; + case 8: + *lpix++ = fg; + *lpix++ = bg; + *lpix++ = bg; + *lpix++ = bg; + break; + case 9: + *lpix++ = fg; + *lpix++ = bg; + *lpix++ = bg; + *lpix++ = fg; + break; + case 10: + *lpix++ = fg; + *lpix++ = bg; + *lpix++ = fg; + *lpix++ = bg; + break; + case 11: + *lpix++ = fg; + *lpix++ = bg; + *lpix++ = fg; + *lpix++ = fg; + break; + case 12: + *lpix++ = fg; + *lpix++ = fg; + *lpix++ = bg; + *lpix++ = bg; + break; + case 13: + *lpix++ = fg; + *lpix++ = fg; + *lpix++ = bg; + *lpix++ = fg; + break; + case 14: + *lpix++ = fg; + *lpix++ = fg; + *lpix++ = fg; + *lpix++ = bg; + break; + case 15: + *lpix++ = fg; + *lpix++ = fg; + *lpix++ = fg; + *lpix++ = fg; + break; + } + + expbits = *lbits & 0x0f; + + j -= 4; + if (j < 4) { + break; + } + + switch (expbits) { + case 0: + *lpix++ = bg; + *lpix++ = bg; + *lpix++ = bg; + *lpix++ = bg; + break; + case 1: + *lpix++ = bg; + *lpix++ = bg; + *lpix++ = bg; + *lpix++ = fg; + break; + case 2: + *lpix++ = bg; + *lpix++ = bg; + *lpix++ = fg; + *lpix++ = bg; + break; + case 3: + *lpix++ = bg; + *lpix++ = bg; + *lpix++ = fg; + *lpix++ = fg; + break; + case 4: + *lpix++ = bg; + *lpix++ = fg; + *lpix++ = bg; + *lpix++ = bg; + break; + case 5: + *lpix++ = bg; + *lpix++ = fg; + *lpix++ = bg; + *lpix++ = fg; + break; + case 6: + *lpix++ = bg; + *lpix++ = fg; + *lpix++ = fg; + *lpix++ = bg; + break; + case 7: + *lpix++ = bg; + *lpix++ = fg; + *lpix++ = fg; + *lpix++ = fg; + break; + case 8: + *lpix++ = fg; + *lpix++ = bg; + *lpix++ = bg; + *lpix++ = bg; + break; + case 9: + *lpix++ = fg; + *lpix++ = bg; + *lpix++ = bg; + *lpix++ = fg; + break; + case 10: + *lpix++ = fg; + *lpix++ = bg; + *lpix++ = fg; + *lpix++ = bg; + break; + case 11: + *lpix++ = fg; + *lpix++ = bg; + *lpix++ = fg; + *lpix++ = fg; + break; + case 12: + *lpix++ = fg; + *lpix++ = fg; + *lpix++ = bg; + *lpix++ = bg; + break; + case 13: + *lpix++ = fg; + *lpix++ = fg; + *lpix++ = bg; + *lpix++ = fg; + break; + case 14: + *lpix++ = fg; + *lpix++ = fg; + *lpix++ = fg; + *lpix++ = bg; + break; + case 15: + *lpix++ = fg; + *lpix++ = fg; + *lpix++ = fg; + *lpix++ = fg; + break; + } + lbits++; + } + + if (j > 0) { + *lpix++ = (expbits & 0x08) ? fg : bg; + j--; + if (j > 0) { + *lpix++ = (expbits & 0x04) ? fg : bg; + j--; + if (j > 0) { + *lpix++ = (expbits & 0x02) ? fg : bg; + j--; + } + } + } + + pix += pix_increment; + bits += bits_increment; + } + return; +} + + + +/* + *---------------------------------------------------------------------- + * + * RasterBitsToPixels24 -- + * + * Convert a bitmap to a pixmap, converting 1 bits to the foreground + * color (fg) and 0 bits to the background color (bg), for a 24-bit + * pixmap + * + * Results: + * Pixmap filled with pixels + * + * Side effects: + * None + * + *---------------------------------------------------------------------- + */ + +void +RasterBitsToPixels24(uint8 *bits, uint32 bits_increment, + uint8 *pix, uint32 pix_increment, + uint32 width, uint32 height, uint32 fg, uint32 bg) +{ + uint8 *lpix, *lbits; + uint32 fgColor1, fgColor2, fgColor3; + uint32 bgColor1, bgColor2, bgColor3; + + int i, j; + uint32 expbits = 0; /* Bits to be expanded */ + + fgColor1 = fg & 0x000000ff; + fgColor2 = (fg >> 8) & 0x000000ff; + fgColor3 = (fg >> 16) & 0x000000ff; + + bgColor1 = bg & 0x000000ff; + bgColor2 = (bg >> 8) & 0x000000ff; + bgColor3 = (bg >> 16) & 0x000000ff; + + for (i=0; i<height; i++) { + lpix = pix; + lbits = bits; + for (j = width; j > 0; j -= 4) { + expbits = (*lbits >> 4) & 0x0f; + + if (j < 4) + break; + + switch (expbits) { + case 0: + *lpix++ = bgColor1; + *lpix++ = bgColor2; + *lpix++ = bgColor3; + *lpix++ = bgColor1; + *lpix++ = bgColor2; + *lpix++ = bgColor3; + *lpix++ = bgColor1; + *lpix++ = bgColor2; + *lpix++ = bgColor3; + *lpix++ = bgColor1; + *lpix++ = bgColor2; + *lpix++ = bgColor3; + break; + case 1: + *lpix++ = bgColor1; + *lpix++ = bgColor2; + *lpix++ = bgColor3; + *lpix++ = bgColor1; + *lpix++ = bgColor2; + *lpix++ = bgColor3; + *lpix++ = bgColor1; + *lpix++ = bgColor2; + *lpix++ = bgColor3; + *lpix++ = fgColor1; + *lpix++ = fgColor2; + *lpix++ = fgColor3; + break; + case 2: + *lpix++ = bgColor1; + *lpix++ = bgColor2; + *lpix++ = bgColor3; + *lpix++ = bgColor1; + *lpix++ = bgColor2; + *lpix++ = bgColor3; + *lpix++ = fgColor1; + *lpix++ = fgColor2; + *lpix++ = fgColor3; + *lpix++ = bgColor1; + *lpix++ = bgColor2; + *lpix++ = bgColor3; + break; + case 3: + *lpix++ = bgColor1; + *lpix++ = bgColor2; + *lpix++ = bgColor3; + *lpix++ = bgColor1; + *lpix++ = bgColor2; + *lpix++ = bgColor3; + *lpix++ = fgColor1; + *lpix++ = fgColor2; + *lpix++ = fgColor3; + *lpix++ = fgColor1; + *lpix++ = fgColor2; + *lpix++ = fgColor3; + break; + case 4: + *lpix++ = bgColor1; + *lpix++ = bgColor2; + *lpix++ = bgColor3; + *lpix++ = fgColor1; + *lpix++ = fgColor2; + *lpix++ = fgColor3; + *lpix++ = bgColor1; + *lpix++ = bgColor2; + *lpix++ = bgColor3; + *lpix++ = bgColor1; + *lpix++ = bgColor2; + *lpix++ = bgColor3; + break; + case 5: + *lpix++ = bgColor1; + *lpix++ = bgColor2; + *lpix++ = bgColor3; + *lpix++ = fgColor1; + *lpix++ = fgColor2; + *lpix++ = fgColor3; + *lpix++ = bgColor1; + *lpix++ = bgColor2; + *lpix++ = bgColor3; + *lpix++ = fgColor1; + *lpix++ = fgColor2; + *lpix++ = fgColor3; + break; + case 6: + *lpix++ = bgColor1; + *lpix++ = bgColor2; + *lpix++ = bgColor3; + *lpix++ = fgColor1; + *lpix++ = fgColor2; + *lpix++ = fgColor3; + *lpix++ = fgColor1; + *lpix++ = fgColor2; + *lpix++ = fgColor3; + *lpix++ = bgColor1; + *lpix++ = bgColor2; + *lpix++ = bgColor3; + break; + case 7: + *lpix++ = bgColor1; + *lpix++ = bgColor2; + *lpix++ = bgColor3; + *lpix++ = fgColor1; + *lpix++ = fgColor2; + *lpix++ = fgColor3; + *lpix++ = fgColor1; + *lpix++ = fgColor2; + *lpix++ = fgColor3; + *lpix++ = fgColor1; + *lpix++ = fgColor2; + *lpix++ = fgColor3; + break; + case 8: + *lpix++ = fgColor1; + *lpix++ = fgColor2; + *lpix++ = fgColor3; + *lpix++ = bgColor1; + *lpix++ = bgColor2; + *lpix++ = bgColor3; + *lpix++ = bgColor1; + *lpix++ = bgColor2; + *lpix++ = bgColor3; + *lpix++ = bgColor1; + *lpix++ = bgColor2; + *lpix++ = bgColor3; + break; + case 9: + *lpix++ = fgColor1; + *lpix++ = fgColor2; + *lpix++ = fgColor3; + *lpix++ = bgColor1; + *lpix++ = bgColor2; + *lpix++ = bgColor3; + *lpix++ = bgColor1; + *lpix++ = bgColor2; + *lpix++ = bgColor3; + *lpix++ = fgColor1; + *lpix++ = fgColor2; + *lpix++ = fgColor3; + break; + case 10: + *lpix++ = fgColor1; + *lpix++ = fgColor2; + *lpix++ = fgColor3; + *lpix++ = bgColor1; + *lpix++ = bgColor2; + *lpix++ = bgColor3; + *lpix++ = fgColor1; + *lpix++ = fgColor2; + *lpix++ = fgColor3; + *lpix++ = bgColor1; + *lpix++ = bgColor2; + *lpix++ = bgColor3; + break; + case 11: + *lpix++ = fgColor1; + *lpix++ = fgColor2; + *lpix++ = fgColor3; + *lpix++ = bgColor1; + *lpix++ = bgColor2; + *lpix++ = bgColor3; + *lpix++ = fgColor1; + *lpix++ = fgColor2; + *lpix++ = fgColor3; + *lpix++ = fgColor1; + *lpix++ = fgColor2; + *lpix++ = fgColor3; + break; + case 12: + *lpix++ = fgColor1; + *lpix++ = fgColor2; + *lpix++ = fgColor3; + *lpix++ = fgColor1; + *lpix++ = fgColor2; + *lpix++ = fgColor3; + *lpix++ = bgColor1; + *lpix++ = bgColor2; + *lpix++ = bgColor3; + *lpix++ = bgColor1; + *lpix++ = bgColor2; + *lpix++ = bgColor3; + break; + case 13: + *lpix++ = fgColor1; + *lpix++ = fgColor2; + *lpix++ = fgColor3; + *lpix++ = fgColor1; + *lpix++ = fgColor2; + *lpix++ = fgColor3; + *lpix++ = bgColor1; + *lpix++ = bgColor2; + *lpix++ = bgColor3; + *lpix++ = fgColor1; + *lpix++ = fgColor2; + *lpix++ = fgColor3; + break; + case 14: + *lpix++ = fgColor1; + *lpix++ = fgColor2; + *lpix++ = fgColor3; + *lpix++ = fgColor1; + *lpix++ = fgColor2; + *lpix++ = fgColor3; + *lpix++ = fgColor1; + *lpix++ = fgColor2; + *lpix++ = fgColor3; + *lpix++ = bgColor1; + *lpix++ = bgColor2; + *lpix++ = bgColor3; + break; + case 15: + *lpix++ = fgColor1; + *lpix++ = fgColor2; + *lpix++ = fgColor3; + *lpix++ = fgColor1; + *lpix++ = fgColor2; + *lpix++ = fgColor3; + *lpix++ = fgColor1; + *lpix++ = fgColor2; + *lpix++ = fgColor3; + *lpix++ = fgColor1; + *lpix++ = fgColor2; + *lpix++ = fgColor3; + break; + } + + expbits = *lbits & 0x0f; + + j -= 4; + if (j < 4) { + break; + } + + switch (expbits) { + case 0: + *lpix++ = bgColor1; + *lpix++ = bgColor2; + *lpix++ = bgColor3; + *lpix++ = bgColor1; + *lpix++ = bgColor2; + *lpix++ = bgColor3; + *lpix++ = bgColor1; + *lpix++ = bgColor2; + *lpix++ = bgColor3; + *lpix++ = bgColor1; + *lpix++ = bgColor2; + *lpix++ = bgColor3; + break; + case 1: + *lpix++ = bgColor1; + *lpix++ = bgColor2; + *lpix++ = bgColor3; + *lpix++ = bgColor1; + *lpix++ = bgColor2; + *lpix++ = bgColor3; + *lpix++ = bgColor1; + *lpix++ = bgColor2; + *lpix++ = bgColor3; + *lpix++ = fgColor1; + *lpix++ = fgColor2; + *lpix++ = fgColor3; + break; + case 2: + *lpix++ = bgColor1; + *lpix++ = bgColor2; + *lpix++ = bgColor3; + *lpix++ = bgColor1; + *lpix++ = bgColor2; + *lpix++ = bgColor3; + *lpix++ = fgColor1; + *lpix++ = fgColor2; + *lpix++ = fgColor3; + *lpix++ = bgColor1; + *lpix++ = bgColor2; + *lpix++ = bgColor3; + break; + case 3: + *lpix++ = bgColor1; + *lpix++ = bgColor2; + *lpix++ = bgColor3; + *lpix++ = bgColor1; + *lpix++ = bgColor2; + *lpix++ = bgColor3; + *lpix++ = fgColor1; + *lpix++ = fgColor2; + *lpix++ = fgColor3; + *lpix++ = fgColor1; + *lpix++ = fgColor2; + *lpix++ = fgColor3; + break; + case 4: + *lpix++ = bgColor1; + *lpix++ = bgColor2; + *lpix++ = bgColor3; + *lpix++ = fgColor1; + *lpix++ = fgColor2; + *lpix++ = fgColor3; + *lpix++ = bgColor1; + *lpix++ = bgColor2; + *lpix++ = bgColor3; + *lpix++ = bgColor1; + *lpix++ = bgColor2; + *lpix++ = bgColor3; + break; + case 5: + *lpix++ = bgColor1; + *lpix++ = bgColor2; + *lpix++ = bgColor3; + *lpix++ = fgColor1; + *lpix++ = fgColor2; + *lpix++ = fgColor3; + *lpix++ = bgColor1; + *lpix++ = bgColor2; + *lpix++ = bgColor3; + *lpix++ = fgColor1; + *lpix++ = fgColor2; + *lpix++ = fgColor3; + break; + case 6: + *lpix++ = bgColor1; + *lpix++ = bgColor2; + *lpix++ = bgColor3; + *lpix++ = fgColor1; + *lpix++ = fgColor2; + *lpix++ = fgColor3; + *lpix++ = fgColor1; + *lpix++ = fgColor2; + *lpix++ = fgColor3; + *lpix++ = bgColor1; + *lpix++ = bgColor2; + *lpix++ = bgColor3; + break; + case 7: + *lpix++ = bgColor1; + *lpix++ = bgColor2; + *lpix++ = bgColor3; + *lpix++ = fgColor1; + *lpix++ = fgColor2; + *lpix++ = fgColor3; + *lpix++ = fgColor1; + *lpix++ = fgColor2; + *lpix++ = fgColor3; + *lpix++ = fgColor1; + *lpix++ = fgColor2; + *lpix++ = fgColor3; + break; + case 8: + *lpix++ = fgColor1; + *lpix++ = fgColor2; + *lpix++ = fgColor3; + *lpix++ = bgColor1; + *lpix++ = bgColor2; + *lpix++ = bgColor3; + *lpix++ = bgColor1; + *lpix++ = bgColor2; + *lpix++ = bgColor3; + *lpix++ = bgColor1; + *lpix++ = bgColor2; + *lpix++ = bgColor3; + break; + case 9: + *lpix++ = fgColor1; + *lpix++ = fgColor2; + *lpix++ = fgColor3; + *lpix++ = bgColor1; + *lpix++ = bgColor2; + *lpix++ = bgColor3; + *lpix++ = bgColor1; + *lpix++ = bgColor2; + *lpix++ = bgColor3; + *lpix++ = fgColor1; + *lpix++ = fgColor2; + *lpix++ = fgColor3; + break; + case 10: + *lpix++ = fgColor1; + *lpix++ = fgColor2; + *lpix++ = fgColor3; + *lpix++ = bgColor1; + *lpix++ = bgColor2; + *lpix++ = bgColor3; + *lpix++ = fgColor1; + *lpix++ = fgColor2; + *lpix++ = fgColor3; + *lpix++ = bgColor1; + *lpix++ = bgColor2; + *lpix++ = bgColor3; + break; + case 11: + *lpix++ = fgColor1; + *lpix++ = fgColor2; + *lpix++ = fgColor3; + *lpix++ = bgColor1; + *lpix++ = bgColor2; + *lpix++ = bgColor3; + *lpix++ = fgColor1; + *lpix++ = fgColor2; + *lpix++ = fgColor3; + *lpix++ = fgColor1; + *lpix++ = fgColor2; + *lpix++ = fgColor3; + break; + case 12: + *lpix++ = fgColor1; + *lpix++ = fgColor2; + *lpix++ = fgColor3; + *lpix++ = fgColor1; + *lpix++ = fgColor2; + *lpix++ = fgColor3; + *lpix++ = bgColor1; + *lpix++ = bgColor2; + *lpix++ = bgColor3; + *lpix++ = bgColor1; + *lpix++ = bgColor2; + *lpix++ = bgColor3; + break; + case 13: + *lpix++ = fgColor1; + *lpix++ = fgColor2; + *lpix++ = fgColor3; + *lpix++ = fgColor1; + *lpix++ = fgColor2; + *lpix++ = fgColor3; + *lpix++ = bgColor1; + *lpix++ = bgColor2; + *lpix++ = bgColor3; + *lpix++ = fgColor1; + *lpix++ = fgColor2; + *lpix++ = fgColor3; + break; + case 14: + *lpix++ = fgColor1; + *lpix++ = fgColor2; + *lpix++ = fgColor3; + *lpix++ = fgColor1; + *lpix++ = fgColor2; + *lpix++ = fgColor3; + *lpix++ = fgColor1; + *lpix++ = fgColor2; + *lpix++ = fgColor3; + *lpix++ = bgColor1; + *lpix++ = bgColor2; + *lpix++ = bgColor3; + break; + case 15: + *lpix++ = fgColor1; + *lpix++ = fgColor2; + *lpix++ = fgColor3; + *lpix++ = fgColor1; + *lpix++ = fgColor2; + *lpix++ = fgColor3; + *lpix++ = fgColor1; + *lpix++ = fgColor2; + *lpix++ = fgColor3; + *lpix++ = fgColor1; + *lpix++ = fgColor2; + *lpix++ = fgColor3; + break; + } + lbits++; + } + + if (j > 0) { + *lpix++ = (expbits & 0x08) ? fgColor1 : bgColor1; + *lpix++ = (expbits & 0x08) ? fgColor2 : bgColor2; + *lpix++ = (expbits & 0x08) ? fgColor3 : bgColor3; + j--; + if (j > 0) { + *lpix++ = (expbits & 0x04) ? fgColor1 : bgColor1; + *lpix++ = (expbits & 0x04) ? fgColor2 : bgColor2; + *lpix++ = (expbits & 0x04) ? fgColor3 : bgColor3; + j--; + if (j > 0) { + *lpix++ = (expbits & 0x02) ? fgColor1 : bgColor1; + *lpix++ = (expbits & 0x02) ? fgColor2 : bgColor2; + *lpix++ = (expbits & 0x02) ? fgColor3 : bgColor3; + j--; + } + } + } + + pix += pix_increment; + bits += bits_increment; + } + return; +} + + + +/* + *---------------------------------------------------------------------- + * + * RasterBitsToPixels32 -- + * + * Convert a bitmap to a pixmap, converting 1 bits to the foreground + * color (fg) and 0 bits to the background color (bg), for a 32-bit + * pixmap + * + * Results: + * Pixmap filled with pixels + * + * Side effects: + * None + * + *---------------------------------------------------------------------- + */ + +void +RasterBitsToPixels32(uint8 *bits, uint32 bits_increment, + uint8 *pix, uint32 pix_increment, + uint32 width, uint32 height, uint32 fg, uint32 bg) +{ + uint32 *lpix; + uint8 *lbits; + int i, j; + uint32 expbits = 0; /* Bits to be expanded */ + + for (i=0; i<height; i++) { + lpix = (uint32 *)pix; + lbits = bits; + for (j = width; j > 0; j -= 4) { + expbits = (*lbits >> 4) & 0x0f; + + if (j < 4) + break; + + switch (expbits) { + case 0: + *lpix++ = bg; + *lpix++ = bg; + *lpix++ = bg; + *lpix++ = bg; + break; + case 1: + *lpix++ = bg; + *lpix++ = bg; + *lpix++ = bg; + *lpix++ = fg; + break; + case 2: + *lpix++ = bg; + *lpix++ = bg; + *lpix++ = fg; + *lpix++ = bg; + break; + case 3: + *lpix++ = bg; + *lpix++ = bg; + *lpix++ = fg; + *lpix++ = fg; + break; + case 4: + *lpix++ = bg; + *lpix++ = fg; + *lpix++ = bg; + *lpix++ = bg; + break; + case 5: + *lpix++ = bg; + *lpix++ = fg; + *lpix++ = bg; + *lpix++ = fg; + break; + case 6: + *lpix++ = bg; + *lpix++ = fg; + *lpix++ = fg; + *lpix++ = bg; + break; + case 7: + *lpix++ = bg; + *lpix++ = fg; + *lpix++ = fg; + *lpix++ = fg; + break; + case 8: + *lpix++ = fg; + *lpix++ = bg; + *lpix++ = bg; + *lpix++ = bg; + break; + case 9: + *lpix++ = fg; + *lpix++ = bg; + *lpix++ = bg; + *lpix++ = fg; + break; + case 10: + *lpix++ = fg; + *lpix++ = bg; + *lpix++ = fg; + *lpix++ = bg; + break; + case 11: + *lpix++ = fg; + *lpix++ = bg; + *lpix++ = fg; + *lpix++ = fg; + break; + case 12: + *lpix++ = fg; + *lpix++ = fg; + *lpix++ = bg; + *lpix++ = bg; + break; + case 13: + *lpix++ = fg; + *lpix++ = fg; + *lpix++ = bg; + *lpix++ = fg; + break; + case 14: + *lpix++ = fg; + *lpix++ = fg; + *lpix++ = fg; + *lpix++ = bg; + break; + case 15: + *lpix++ = fg; + *lpix++ = fg; + *lpix++ = fg; + *lpix++ = fg; + break; + } + + expbits = *lbits & 0x0f; + + j -= 4; + if (j < 4) { + break; + } + + switch (expbits) { + case 0: + *lpix++ = bg; + *lpix++ = bg; + *lpix++ = bg; + *lpix++ = bg; + break; + case 1: + *lpix++ = bg; + *lpix++ = bg; + *lpix++ = bg; + *lpix++ = fg; + break; + case 2: + *lpix++ = bg; + *lpix++ = bg; + *lpix++ = fg; + *lpix++ = bg; + break; + case 3: + *lpix++ = bg; + *lpix++ = bg; + *lpix++ = fg; + *lpix++ = fg; + break; + case 4: + *lpix++ = bg; + *lpix++ = fg; + *lpix++ = bg; + *lpix++ = bg; + break; + case 5: + *lpix++ = bg; + *lpix++ = fg; + *lpix++ = bg; + *lpix++ = fg; + break; + case 6: + *lpix++ = bg; + *lpix++ = fg; + *lpix++ = fg; + *lpix++ = bg; + break; + case 7: + *lpix++ = bg; + *lpix++ = fg; + *lpix++ = fg; + *lpix++ = fg; + break; + case 8: + *lpix++ = fg; + *lpix++ = bg; + *lpix++ = bg; + *lpix++ = bg; + break; + case 9: + *lpix++ = fg; + *lpix++ = bg; + *lpix++ = bg; + *lpix++ = fg; + break; + case 10: + *lpix++ = fg; + *lpix++ = bg; + *lpix++ = fg; + *lpix++ = bg; + break; + case 11: + *lpix++ = fg; + *lpix++ = bg; + *lpix++ = fg; + *lpix++ = fg; + break; + case 12: + *lpix++ = fg; + *lpix++ = fg; + *lpix++ = bg; + *lpix++ = bg; + break; + case 13: + *lpix++ = fg; + *lpix++ = fg; + *lpix++ = bg; + *lpix++ = fg; + break; + case 14: + *lpix++ = fg; + *lpix++ = fg; + *lpix++ = fg; + *lpix++ = bg; + break; + case 15: + *lpix++ = fg; + *lpix++ = fg; + *lpix++ = fg; + *lpix++ = fg; + break; + } + lbits++; + } + + if (j > 0) { + *lpix++ = (expbits & 0x08) ? fg : bg; + j--; + if (j > 0) { + *lpix++ = (expbits & 0x04) ? fg : bg; + j--; + if (j > 0) { + *lpix++ = (expbits & 0x02) ? fg : bg; + j--; + } + } + } + + pix += pix_increment; + bits += bits_increment; + } + return; +} diff --git a/src/bits2pixels.h b/src/bits2pixels.h new file mode 100644 index 0000000..7eb4631 --- /dev/null +++ b/src/bits2pixels.h @@ -0,0 +1,23 @@ +/* ********************************************************** + * Copyright (C) 1999-2001 VMware, Inc. + * All Rights Reserved + * **********************************************************/ + +/* + * bits2pixels.h -- + * + * Drawing emulation routines + */ + +#ifndef _BITS2PIXELS_H_ +#define _BITS2PIXELS_H_ + +#define INCLUDE_ALLOW_USERLEVEL +#include "includeCheck.h" + +void +vmwareRaster_BitsToPixels(uint8 *bits, uint32 bits_increment, + uint8 *pix, uint32 pix_increment, int bytes_per_pixel, + uint32 width, uint32 height, uint32 fg, uint32 bg); + +#endif /* _BITS4PIXELS_H_ */ diff --git a/src/compat-api.h b/src/compat-api.h new file mode 100644 index 0000000..205ac59 --- /dev/null +++ b/src/compat-api.h @@ -0,0 +1,99 @@ +/* + * 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 (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. + * + * Author: Dave Airlie <airlied@redhat.com> + */ + +/* this file provides API compat between server post 1.13 and pre it, + it should be reused inside as many drivers as possible */ +#ifndef COMPAT_API_H +#define COMPAT_API_H + +#ifndef GLYPH_HAS_GLYPH_PICTURE_ACCESSOR +#define GetGlyphPicture(g, s) GlyphPicture((g))[(s)->myNum] +#define SetGlyphPicture(g, s, p) GlyphPicture((g))[(s)->myNum] = p +#endif + +#ifndef XF86_HAS_SCRN_CONV +#define xf86ScreenToScrn(s) xf86Screens[(s)->myNum] +#define xf86ScrnToScreen(s) screenInfo.screens[(s)->scrnIndex] +#endif + +#ifndef XF86_SCRN_INTERFACE + +#define SCRN_ARG_TYPE int +#define SCRN_INFO_PTR(arg1) ScrnInfoPtr pScrn = xf86Screens[(arg1)] + +#define SCREEN_ARG_TYPE int +#define SCREEN_PTR(arg1) ScreenPtr pScreen = screenInfo.screens[(arg1)] + +#define SCREEN_INIT_ARGS_DECL int scrnIndex, ScreenPtr pScreen, int argc, char **argv + +#define BLOCKHANDLER_ARGS_DECL int arg, pointer blockData, pointer pTimeout, pointer pReadmask +#define BLOCKHANDLER_ARGS arg, blockData, pTimeout, pReadmask + +#define CLOSE_SCREEN_ARGS_DECL int scrnIndex, ScreenPtr pScreen +#define CLOSE_SCREEN_ARGS scrnIndex, pScreen + +#define ADJUST_FRAME_ARGS_DECL int arg, int x, int y, int flags +#define ADJUST_FRAME_ARGS(arg, x, y) (arg)->scrnIndex, x, y, 0 + +#define SWITCH_MODE_ARGS_DECL int arg, DisplayModePtr mode, int flags +#define SWITCH_MODE_ARGS(arg, m) (arg)->scrnIndex, m, 0 + +#define FREE_SCREEN_ARGS_DECL int arg, int flags + +#define VT_FUNC_ARGS_DECL int arg, int flags +#define VT_FUNC_ARGS pScrn->scrnIndex, 0 + +#define XF86_SCRN_ARG(x) ((x)->scrnIndex) +#else +#define SCRN_ARG_TYPE ScrnInfoPtr +#define SCRN_INFO_PTR(arg1) ScrnInfoPtr pScrn = (arg1) + +#define SCREEN_ARG_TYPE ScreenPtr +#define SCREEN_PTR(arg1) ScreenPtr pScreen = (arg1) + +#define SCREEN_INIT_ARGS_DECL ScreenPtr pScreen, int argc, char **argv + +#define BLOCKHANDLER_ARGS_DECL ScreenPtr arg, pointer pTimeout, pointer pReadmask +#define BLOCKHANDLER_ARGS arg, pTimeout, pReadmask + +#define CLOSE_SCREEN_ARGS_DECL ScreenPtr pScreen +#define CLOSE_SCREEN_ARGS pScreen + +#define ADJUST_FRAME_ARGS_DECL ScrnInfoPtr arg, int x, int y +#define ADJUST_FRAME_ARGS(arg, x, y) arg, x, y + +#define SWITCH_MODE_ARGS_DECL ScrnInfoPtr arg, DisplayModePtr mode +#define SWITCH_MODE_ARGS(arg, m) arg, m + +#define FREE_SCREEN_ARGS_DECL ScrnInfoPtr arg + +#define VT_FUNC_ARGS_DECL ScrnInfoPtr arg +#define VT_FUNC_ARGS pScrn + +#define XF86_SCRN_ARG(x) (x) + +#endif + +#endif diff --git a/src/guest_os.h b/src/guest_os.h new file mode 100644 index 0000000..4beaf7c --- /dev/null +++ b/src/guest_os.h @@ -0,0 +1,28 @@ +/* ********************************************************* + * Copyright (C) 1999-2001 VMware, Inc. + * All Rights Reserved + * **********************************************************/ + +#ifndef _GUEST_OS_H_ +#define _GUEST_OS_H_ + +#define INCLUDE_ALLOW_USERLEVEL +#include "includeCheck.h" + +#define GUEST_OS_BASE 0x5000 + +#define GUEST_OS_DOS (GUEST_OS_BASE+1) +#define GUEST_OS_WIN31 (GUEST_OS_BASE+2) +#define GUEST_OS_WINDOWS95 (GUEST_OS_BASE+3) +#define GUEST_OS_WINDOWS98 (GUEST_OS_BASE+4) +#define GUEST_OS_WINDOWSME (GUEST_OS_BASE+5) +#define GUEST_OS_NT (GUEST_OS_BASE+6) +#define GUEST_OS_WIN2000 (GUEST_OS_BASE+7) +#define GUEST_OS_LINUX (GUEST_OS_BASE+8) +#define GUEST_OS_OS2 (GUEST_OS_BASE+9) +#define GUEST_OS_OTHER (GUEST_OS_BASE+10) +#define GUEST_OS_FREEBSD (GUEST_OS_BASE+11) +#define GUEST_OS_WHISTLER (GUEST_OS_BASE+12) + + +#endif diff --git a/src/includeCheck.h b/src/includeCheck.h new file mode 100644 index 0000000..88ac8ef --- /dev/null +++ b/src/includeCheck.h @@ -0,0 +1,2 @@ +/* This space intentionally left blank. */ + diff --git a/src/svga_escape.h b/src/svga_escape.h new file mode 100644 index 0000000..c9e7b23 --- /dev/null +++ b/src/svga_escape.h @@ -0,0 +1,30 @@ +/* ********************************************************** + * Copyright 2007 VMware, Inc. All rights reserved. + * **********************************************************/ + +/* + * svga_escape.h -- + * + * Definitions for our own (vendor-specific) SVGA Escape commands. + */ + +#ifndef _SVGA_ESCAPE_H_ +#define _SVGA_ESCAPE_H_ + +/* + * Namespace IDs for the escape command + */ + +#define SVGA_ESCAPE_NSID_VMWARE 0x00000000 +#define SVGA_ESCAPE_NSID_DEVEL 0xFFFFFFFF + +/* + * Within SVGA_ESCAPE_NSID_VMWARE, we multiplex commands according to + * the first DWORD of escape data (after the nsID and size). As a + * guideline we're using the high word and low word as a major and + * minor command number, respectively. + */ + +#define SVGA_ESCAPE_VMWARE_MAJOR_MASK 0xFFFF0000 + +#endif /* _SVGA_ESCAPE_H_ */ diff --git a/src/svga_limits.h b/src/svga_limits.h new file mode 100644 index 0000000..3b35ccc --- /dev/null +++ b/src/svga_limits.h @@ -0,0 +1,55 @@ +/* ********************************************************** + * Copyright (C) 1998-2001 VMware, Inc. + * All Rights Reserved + * **********************************************************/ + +/* + * svga_limits.h -- + * + * SVGA limits + */ + +#ifndef _SVGA_LIMITS_H_ +#define _SVGA_LIMITS_H_ + +#define INCLUDE_ALLOW_USERLEVEL +#define INCLUDE_ALLOW_MONITOR +#include "includeCheck.h" + +/* + * Location and size of SVGA frame buffer and the FIFO. + */ +#define SVGA_VRAM_SIZE (16*1024*1024) +#define SVGA_MEM_SIZE (256*1024) + +/* + * SVGA_FB_START is the default starting address of the SVGA frame + * buffer in the guest's physical address space. + * SVGA_FB_START_BIGMEM is the starting address of the SVGA frame + * buffer for VMs that have a large amount of physical memory. + * + * The address of SVGA_FB_START is set to 2GB - (SVGA_FB_MAX_SIZE + SVGA_MEM_SIZE), + * thus the SVGA frame buffer sits at [SVGA_FB_START .. 2GB-1] in the + * physical address space. Our older SVGA drivers for NT treat the + * address of the frame buffer as a signed integer. For backwards + * compatibility, we keep the default location of the frame buffer + * at under 2GB in the address space. This restricts VMs to have "only" + * up to ~2031MB (i.e., up to SVGA_FB_START) of physical memory. + * + * For VMs that want more memory than the ~2031MB, we place the SVGA + * frame buffer at SVGA_FB_START_BIGMEM. This allows VMs to have up + * to 3584MB, at least as far as the SVGA frame buffer is concerned + * (note that there may be other issues that limit the VM memory + * size). PCI devices use high memory addresses, so we have to put + * SVGA_FB_START_BIGMEM low enough so that it doesn't overlap with any + * of these devices. Placing SVGA_FB_START_BIGMEM at 0xE0000000 + * should leave plenty of room for the PCI devices. + * + * NOTE: All of that is only true for the 0710 chipset. As of the 0405 + * chipset, the framebuffer start is determined solely based on the value + * the guest BIOS or OS programs into the PCI base address registers. + */ +#define SVGA_FB_LEGACY_START 0x7EFC0000 +#define SVGA_FB_LEGACY_START_BIGMEM 0xE0000000 + +#endif diff --git a/src/svga_modes.h b/src/svga_modes.h new file mode 100644 index 0000000..97d869e --- /dev/null +++ b/src/svga_modes.h @@ -0,0 +1,48 @@ +/* ********************************************************** + * Copyright (C) 2007 VMware, Inc. All Rights Reserved + * **********************************************************/ + +#ifndef _SVGA_MODES_H_ +#define _SVGA_MODES_H_ + +#define INCLUDE_ALLOW_USERLEVEL +#include "includeCheck.h" + +#define SVGA_DEFAULT_MODES \ + /* 4:3 modes */ \ + SVGA_DEFAULT_MODE( 320, 240) \ + SVGA_DEFAULT_MODE( 400, 300) \ + SVGA_DEFAULT_MODE( 512, 384) \ + SVGA_DEFAULT_MODE( 640, 480) \ + SVGA_DEFAULT_MODE( 800, 600) \ + SVGA_DEFAULT_MODE(1024, 768) \ + SVGA_DEFAULT_MODE(1152, 864) \ + SVGA_DEFAULT_MODE(1280, 960) \ + SVGA_DEFAULT_MODE(1400, 1050) \ + SVGA_DEFAULT_MODE(1600, 1200) \ + SVGA_DEFAULT_MODE(1920, 1440) \ + SVGA_DEFAULT_MODE(2048, 1536) \ + SVGA_DEFAULT_MODE(2560, 1920) \ + /* 16:9 modes */ \ + SVGA_DEFAULT_MODE( 854, 480) \ + SVGA_DEFAULT_MODE(1280, 720) \ + SVGA_DEFAULT_MODE(1366, 768) \ + SVGA_DEFAULT_MODE(1920, 1080) \ + /* 16:10 modes */ \ + SVGA_DEFAULT_MODE(1280, 800) \ + SVGA_DEFAULT_MODE(1440, 900) \ + SVGA_DEFAULT_MODE(1680, 1050) \ + SVGA_DEFAULT_MODE(1920, 1200) \ + SVGA_DEFAULT_MODE(2560, 1600) \ + /* DVD modes */ \ + SVGA_DEFAULT_MODE( 720, 480) \ + SVGA_DEFAULT_MODE( 720, 576) \ + /* Odd modes */ \ + SVGA_DEFAULT_MODE( 320, 200) \ + SVGA_DEFAULT_MODE( 640, 400) \ + SVGA_DEFAULT_MODE( 800, 480) \ + SVGA_DEFAULT_MODE(1280, 768) \ + SVGA_DEFAULT_MODE(1280, 1024) + + +#endif /* _SVGA_MODES_H_ */ diff --git a/src/svga_overlay.h b/src/svga_overlay.h new file mode 100644 index 0000000..46aef9d --- /dev/null +++ b/src/svga_overlay.h @@ -0,0 +1,50 @@ +/* ********************************************************** + * Copyright 2007 VMware, Inc. All rights reserved. + * **********************************************************/ + +/* + * svga_overlay.h -- + * + * Definitions for video-overlay support. + */ + +#ifndef _SVGA_OVERLAY_H_ +#define _SVGA_OVERLAY_H_ + +/* + * Video formats we support + */ + +#define VMWARE_FOURCC_YV12 0x32315659 /* 'Y' 'V' '1' '2' */ +#define VMWARE_FOURCC_YUY2 0x32595559 /* 'Y' 'U' 'Y' '2' */ +#define VMWARE_FOURCC_UYVY 0x59565955 /* 'U' 'Y' 'V' 'Y' */ + +#define SVGA_ESCAPE_VMWARE_VIDEO 0x00020000 + +#define SVGA_ESCAPE_VMWARE_VIDEO_SET_REGS 0x00020001 + /* FIFO escape layout: + * Type, Stream Id, (Register Id, Value) pairs */ + +#define SVGA_ESCAPE_VMWARE_VIDEO_FLUSH 0x00020002 + /* FIFO escape layout: + * Type, Stream Id */ + +typedef struct SVGAEscapeVideoSetRegs { + struct { + uint32 cmdType; + uint32 streamId; + } header; + + /* May include zero or more items. */ + struct { + uint32 registerId; + uint32 value; + } items[1]; +} SVGAEscapeVideoSetRegs; + +typedef struct SVGAEscapeVideoFlush { + uint32 cmdType; + uint32 streamId; +} SVGAEscapeVideoFlush; + +#endif /* _SVGA_OVERLAY_H_ */ diff --git a/src/svga_reg.h b/src/svga_reg.h new file mode 100644 index 0000000..0e1aa17 --- /dev/null +++ b/src/svga_reg.h @@ -0,0 +1,1566 @@ +/********************************************************** + * Copyright 1998-2009 VMware, 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 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. + * + **********************************************************/ + +/* + * svga_reg.h -- + * + * Virtual hardware definitions for the VMware SVGA II device. + */ + +#ifndef _SVGA_REG_H_ +#define _SVGA_REG_H_ + +/* + * PCI device IDs. + */ +#define PCI_VENDOR_ID_VMWARE 0x15AD +#define PCI_DEVICE_ID_VMWARE_SVGA2 0x0405 + +/* + * SVGA_REG_ENABLE bit definitions. + */ +#define SVGA_REG_ENABLE_DISABLE 0 +#define SVGA_REG_ENABLE_ENABLE 1 +#define SVGA_REG_ENABLE_HIDE 2 +#define SVGA_REG_ENABLE_ENABLE_HIDE (SVGA_REG_ENABLE_ENABLE |\ + SVGA_REG_ENABLE_HIDE) + +/* + * Legal values for the SVGA_REG_CURSOR_ON register in old-fashioned + * cursor bypass mode. This is still supported, but no new guest + * drivers should use it. + */ +#define SVGA_CURSOR_ON_HIDE 0x0 /* Must be 0 to maintain backward compatibility */ +#define SVGA_CURSOR_ON_SHOW 0x1 /* Must be 1 to maintain backward compatibility */ +#define SVGA_CURSOR_ON_REMOVE_FROM_FB 0x2 /* Remove the cursor from the framebuffer because we need to see what's under it */ +#define SVGA_CURSOR_ON_RESTORE_TO_FB 0x3 /* Put the cursor back in the framebuffer so the user can see it */ + +/* + * The maximum framebuffer size that can traced for e.g. guests in VESA mode. + * The changeMap in the monitor is proportional to this number. Therefore, we'd + * like to keep it as small as possible to reduce monitor overhead (using + * SVGA_VRAM_MAX_SIZE for this increases the size of the shared area by over + * 4k!). + * + * NB: For compatibility reasons, this value must be greater than 0xff0000. + * See bug 335072. + */ +#define SVGA_FB_MAX_TRACEABLE_SIZE 0x1000000 + +#define SVGA_MAX_PSEUDOCOLOR_DEPTH 8 +#define SVGA_MAX_PSEUDOCOLORS (1 << SVGA_MAX_PSEUDOCOLOR_DEPTH) +#define SVGA_NUM_PALETTE_REGS (3 * SVGA_MAX_PSEUDOCOLORS) + +/* Base and Offset gets us headed the right way for PCI Base Addr Registers */ +#define SVGA_LEGACY_BASE_PORT 0x4560 +#define SVGA_NUM_PORTS 0x3 + +#define SVGA_MAGIC 0x900000UL +#define SVGA_MAKE_ID(ver) (SVGA_MAGIC << 8 | (ver)) + +/* Version 2 let the address of the frame buffer be unsigned on Win32 */ +#define SVGA_VERSION_2 2 +#define SVGA_ID_2 SVGA_MAKE_ID(SVGA_VERSION_2) + +/* Version 1 has new registers starting with SVGA_REG_CAPABILITIES so + PALETTE_BASE has moved */ +#define SVGA_VERSION_1 1 +#define SVGA_ID_1 SVGA_MAKE_ID(SVGA_VERSION_1) + +/* Version 0 is the initial version */ +#define SVGA_VERSION_0 0 +#define SVGA_ID_0 SVGA_MAKE_ID(SVGA_VERSION_0) + +/* "Invalid" value for all SVGA IDs. (Version ID, screen object ID, surface ID...) */ +#define SVGA_ID_INVALID 0xFFFFFFFF + +/* Port offsets, relative to BAR0 */ +#define SVGA_INDEX_PORT 0x0 +#define SVGA_VALUE_PORT 0x1 +#define SVGA_BIOS_PORT 0x2 +#define SVGA_IRQSTATUS_PORT 0x8 + +/* + * Interrupt source flags for IRQSTATUS_PORT and IRQMASK. + * + * Interrupts are only supported when the + * SVGA_CAP_IRQMASK capability is present. + */ +#define SVGA_IRQFLAG_ANY_FENCE 0x1 /* Any fence was passed */ +#define SVGA_IRQFLAG_FIFO_PROGRESS 0x2 /* Made forward progress in the FIFO */ +#define SVGA_IRQFLAG_FENCE_GOAL 0x4 /* SVGA_FIFO_FENCE_GOAL reached */ + +/* + * Registers + */ + +enum { + SVGA_REG_ID = 0, + SVGA_REG_ENABLE = 1, + SVGA_REG_WIDTH = 2, + SVGA_REG_HEIGHT = 3, + SVGA_REG_MAX_WIDTH = 4, + SVGA_REG_MAX_HEIGHT = 5, + SVGA_REG_DEPTH = 6, + SVGA_REG_BITS_PER_PIXEL = 7, /* Current bpp in the guest */ + SVGA_REG_PSEUDOCOLOR = 8, + SVGA_REG_RED_MASK = 9, + SVGA_REG_GREEN_MASK = 10, + SVGA_REG_BLUE_MASK = 11, + SVGA_REG_BYTES_PER_LINE = 12, + SVGA_REG_FB_START = 13, /* (Deprecated) */ + SVGA_REG_FB_OFFSET = 14, + SVGA_REG_VRAM_SIZE = 15, + SVGA_REG_FB_SIZE = 16, + + /* ID 0 implementation only had the above registers, then the palette */ + + SVGA_REG_CAPABILITIES = 17, + SVGA_REG_MEM_START = 18, /* (Deprecated) */ + SVGA_REG_MEM_SIZE = 19, + SVGA_REG_CONFIG_DONE = 20, /* Set when memory area configured */ + SVGA_REG_SYNC = 21, /* See "FIFO Synchronization Registers" */ + SVGA_REG_BUSY = 22, /* See "FIFO Synchronization Registers" */ + SVGA_REG_GUEST_ID = 23, /* Set guest OS identifier */ + SVGA_REG_CURSOR_ID = 24, /* (Deprecated) */ + SVGA_REG_CURSOR_X = 25, /* (Deprecated) */ + SVGA_REG_CURSOR_Y = 26, /* (Deprecated) */ + SVGA_REG_CURSOR_ON = 27, /* (Deprecated) */ + SVGA_REG_HOST_BITS_PER_PIXEL = 28, /* (Deprecated) */ + SVGA_REG_SCRATCH_SIZE = 29, /* Number of scratch registers */ + SVGA_REG_MEM_REGS = 30, /* Number of FIFO registers */ + SVGA_REG_NUM_DISPLAYS = 31, /* (Deprecated) */ + SVGA_REG_PITCHLOCK = 32, /* Fixed pitch for all modes */ + SVGA_REG_IRQMASK = 33, /* Interrupt mask */ + + /* Legacy multi-monitor support */ + SVGA_REG_NUM_GUEST_DISPLAYS = 34,/* Number of guest displays in X/Y direction */ + SVGA_REG_DISPLAY_ID = 35, /* Display ID for the following display attributes */ + SVGA_REG_DISPLAY_IS_PRIMARY = 36,/* Whether this is a primary display */ + SVGA_REG_DISPLAY_POSITION_X = 37,/* The display position x */ + SVGA_REG_DISPLAY_POSITION_Y = 38,/* The display position y */ + SVGA_REG_DISPLAY_WIDTH = 39, /* The display's width */ + SVGA_REG_DISPLAY_HEIGHT = 40, /* The display's height */ + + /* See "Guest memory regions" below. */ + SVGA_REG_GMR_ID = 41, + SVGA_REG_GMR_DESCRIPTOR = 42, + SVGA_REG_GMR_MAX_IDS = 43, + SVGA_REG_GMR_MAX_DESCRIPTOR_LENGTH = 44, + + SVGA_REG_TRACES = 45, /* Enable trace-based updates even when FIFO is on */ + SVGA_REG_GMRS_MAX_PAGES = 46, /* Maximum number of 4KB pages for all GMRs */ + SVGA_REG_MEMORY_SIZE = 47, /* Total dedicated device memory excluding FIFO */ + SVGA_REG_TOP = 48, /* Must be 1 more than the last register */ + + SVGA_PALETTE_BASE = 1024, /* Base of SVGA color map */ + /* Next 768 (== 256*3) registers exist for colormap */ + + SVGA_SCRATCH_BASE = SVGA_PALETTE_BASE + SVGA_NUM_PALETTE_REGS + /* Base of scratch registers */ + /* Next reg[SVGA_REG_SCRATCH_SIZE] registers exist for scratch usage: + First 4 are reserved for VESA BIOS Extension; any remaining are for + the use of the current SVGA driver. */ +}; + +/* + * Macros to compute variable length items (sizes in 32-bit words, except + * for SVGA_GLYPH_SCANLINE_SIZE, which is in bytes). + */ +#define SVGA_BITMAP_SIZE(w,h) ((((w)+31) >> 5) * (h)) +#define SVGA_PIXMAP_SIZE(w,h,bpp) ((( ((w)*(bpp))+31 ) >> 5) * (h)) +#define SVGA_BITMAP_INCREMENT(w) ((( (w)+31 ) >> 5) * sizeof (uint32)) +#define SVGA_PIXMAP_INCREMENT(w,bpp) ((( ((w)*(bpp))+31 ) >> 5) * sizeof (uint32)) + +/* + * Guest memory regions (GMRs): + * + * This is a new memory mapping feature available in SVGA devices + * which have the SVGA_CAP_GMR bit set. Previously, there were two + * fixed memory regions available with which to share data between the + * device and the driver: the FIFO ('MEM') and the framebuffer. GMRs + * are our name for an extensible way of providing arbitrary DMA + * buffers for use between the driver and the SVGA device. They are a + * new alternative to framebuffer memory, usable for both 2D and 3D + * graphics operations. + * + * Since GMR mapping must be done synchronously with guest CPU + * execution, we use a new pair of SVGA registers: + * + * SVGA_REG_GMR_ID -- + * + * Read/write. + * This register holds the 32-bit ID (a small positive integer) + * of a GMR to create, delete, or redefine. Writing this register + * has no side-effects. + * + * SVGA_REG_GMR_DESCRIPTOR -- + * + * Write-only. + * Writing this register will create, delete, or redefine the GMR + * specified by the above ID register. If this register is zero, + * the GMR is deleted. Any pointers into this GMR (including those + * currently being processed by FIFO commands) will be + * synchronously invalidated. + * + * If this register is nonzero, it must be the physical page + * number (PPN) of a data structure which describes the physical + * layout of the memory region this GMR should describe. The + * descriptor structure will be read synchronously by the SVGA + * device when this register is written. The descriptor need not + * remain allocated for the lifetime of the GMR. + * + * The guest driver should write SVGA_REG_GMR_ID first, then + * SVGA_REG_GMR_DESCRIPTOR. + * + * SVGA_REG_GMR_MAX_IDS -- + * + * Read-only. + * The SVGA device may choose to support a maximum number of + * user-defined GMR IDs. This register holds the number of supported + * IDs. (The maximum supported ID plus 1) + * + * SVGA_REG_GMR_MAX_DESCRIPTOR_LENGTH -- + * + * Read-only. + * The SVGA device may choose to put a limit on the total number + * of SVGAGuestMemDescriptor structures it will read when defining + * a single GMR. + * + * The descriptor structure is an array of SVGAGuestMemDescriptor + * structures. Each structure may do one of three things: + * + * - Terminate the GMR descriptor list. + * (ppn==0, numPages==0) + * + * - Add a PPN or range of PPNs to the GMR's virtual address space. + * (ppn != 0, numPages != 0) + * + * - Provide the PPN of the next SVGAGuestMemDescriptor, in order to + * support multi-page GMR descriptor tables without forcing the + * driver to allocate physically contiguous memory. + * (ppn != 0, numPages == 0) + * + * Note that each physical page of SVGAGuestMemDescriptor structures + * can describe at least 2MB of guest memory. If the driver needs to + * use more than one page of descriptor structures, it must use one of + * its SVGAGuestMemDescriptors to point to an additional page. The + * device will never automatically cross a page boundary. + * + * Once the driver has described a GMR, it is immediately available + * for use via any FIFO command that uses an SVGAGuestPtr structure. + * These pointers include a GMR identifier plus an offset into that + * GMR. + * + * The driver must check the SVGA_CAP_GMR bit before using the GMR + * registers. + */ + +/* + * Special GMR IDs, allowing SVGAGuestPtrs to point to framebuffer + * memory as well. In the future, these IDs could even be used to + * allow legacy memory regions to be redefined by the guest as GMRs. + * + * Using the guest framebuffer (GFB) at BAR1 for general purpose DMA + * is being phased out. Please try to use user-defined GMRs whenever + * possible. + */ +#define SVGA_GMR_NULL ((uint32) -1) +#define SVGA_GMR_FRAMEBUFFER ((uint32) -2) /* Guest Framebuffer (GFB) */ + +typedef +struct SVGAGuestMemDescriptor { + uint32 ppn; + uint32 numPages; +} SVGAGuestMemDescriptor; + +typedef +struct SVGAGuestPtr { + uint32 gmrId; + uint32 offset; +} SVGAGuestPtr; + + +/* + * SVGAGMRImageFormat -- + * + * This is a packed representation of the source 2D image format + * for a GMR-to-screen blit. Currently it is defined as an encoding + * of the screen's color depth and bits-per-pixel, however, 16 bits + * are reserved for future use to identify other encodings (such as + * RGBA or higher-precision images). + * + * Currently supported formats: + * + * bpp depth Format Name + * --- ----- ----------- + * 32 24 32-bit BGRX + * 24 24 24-bit BGR + * 16 16 RGB 5-6-5 + * 16 15 RGB 5-5-5 + * + */ + +typedef +struct SVGAGMRImageFormat { + union { + struct { + uint32 bitsPerPixel : 8; + uint32 colorDepth : 8; + uint32 reserved : 16; /* Must be zero */ + }; + + uint32 value; + }; +} SVGAGMRImageFormat; + +typedef +struct SVGAGuestImage { + SVGAGuestPtr ptr; + + /* + * A note on interpretation of pitch: This value of pitch is the + * number of bytes between vertically adjacent image + * blocks. Normally this is the number of bytes between the first + * pixel of two adjacent scanlines. With compressed textures, + * however, this may represent the number of bytes between + * compression blocks rather than between rows of pixels. + * + * XXX: Compressed textures currently must be tightly packed in guest memory. + * + * If the image is 1-dimensional, pitch is ignored. + * + * If 'pitch' is zero, the SVGA3D device calculates a pitch value + * assuming each row of blocks is tightly packed. + */ + uint32 pitch; +} SVGAGuestImage; + +/* + * SVGAColorBGRX -- + * + * A 24-bit color format (BGRX), which does not depend on the + * format of the legacy guest framebuffer (GFB) or the current + * GMRFB state. + */ + +typedef +struct SVGAColorBGRX { + union { + struct { + uint32 b : 8; + uint32 g : 8; + uint32 r : 8; + uint32 x : 8; /* Unused */ + }; + + uint32 value; + }; +} SVGAColorBGRX; + + +/* + * SVGASignedRect -- + * SVGASignedPoint -- + * + * Signed rectangle and point primitives. These are used by the new + * 2D primitives for drawing to Screen Objects, which can occupy a + * signed virtual coordinate space. + * + * SVGASignedRect specifies a half-open interval: the (left, top) + * pixel is part of the rectangle, but the (right, bottom) pixel is + * not. + */ + +typedef +struct SVGASignedRect { + int32 left; + int32 top; + int32 right; + int32 bottom; +} SVGASignedRect; + +typedef +struct SVGASignedPoint { + int32 x; + int32 y; +} SVGASignedPoint; + + +/* + * Capabilities + * + * Note the holes in the bitfield. Missing bits have been deprecated, + * and must not be reused. Those capabilities will never be reported + * by new versions of the SVGA device. + * + * SVGA_CAP_GMR2 -- + * Provides asynchronous commands to define and remap guest memory + * regions. Adds device registers SVGA_REG_GMRS_MAX_PAGES and + * SVGA_REG_MEMORY_SIZE. + * + * SVGA_CAP_SCREEN_OBJECT_2 -- + * Allow screen object support, and require backing stores from the + * guest for each screen object. + */ + +#define SVGA_CAP_NONE 0x00000000 +#define SVGA_CAP_RECT_COPY 0x00000002 +#define SVGA_CAP_CURSOR 0x00000020 +#define SVGA_CAP_CURSOR_BYPASS 0x00000040 /* Legacy (Use Cursor Bypass 3 instead) */ +#define SVGA_CAP_CURSOR_BYPASS_2 0x00000080 /* Legacy (Use Cursor Bypass 3 instead) */ +#define SVGA_CAP_8BIT_EMULATION 0x00000100 +#define SVGA_CAP_ALPHA_CURSOR 0x00000200 +#define SVGA_CAP_3D 0x00004000 +#define SVGA_CAP_EXTENDED_FIFO 0x00008000 +#define SVGA_CAP_MULTIMON 0x00010000 /* Legacy multi-monitor support */ +#define SVGA_CAP_PITCHLOCK 0x00020000 +#define SVGA_CAP_IRQMASK 0x00040000 +#define SVGA_CAP_DISPLAY_TOPOLOGY 0x00080000 /* Legacy multi-monitor support */ +#define SVGA_CAP_GMR 0x00100000 +#define SVGA_CAP_TRACES 0x00200000 +#define SVGA_CAP_GMR2 0x00400000 +#define SVGA_CAP_SCREEN_OBJECT_2 0x00800000 + + +/* + * FIFO register indices. + * + * The FIFO is a chunk of device memory mapped into guest physmem. It + * is always treated as 32-bit words. + * + * The guest driver gets to decide how to partition it between + * - FIFO registers (there are always at least 4, specifying where the + * following data area is and how much data it contains; there may be + * more registers following these, depending on the FIFO protocol + * version in use) + * - FIFO data, written by the guest and slurped out by the VMX. + * These indices are 32-bit word offsets into the FIFO. + */ + +enum { + /* + * Block 1 (basic registers): The originally defined FIFO registers. + * These exist and are valid for all versions of the FIFO protocol. + */ + + SVGA_FIFO_MIN = 0, + SVGA_FIFO_MAX, /* The distance from MIN to MAX must be at least 10K */ + SVGA_FIFO_NEXT_CMD, + SVGA_FIFO_STOP, + + /* + * Block 2 (extended registers): Mandatory registers for the extended + * FIFO. These exist if the SVGA caps register includes + * SVGA_CAP_EXTENDED_FIFO; some of them are valid only if their + * associated capability bit is enabled. + * + * Note that when originally defined, SVGA_CAP_EXTENDED_FIFO implied + * support only for (FIFO registers) CAPABILITIES, FLAGS, and FENCE. + * This means that the guest has to test individually (in most cases + * using FIFO caps) for the presence of registers after this; the VMX + * can define "extended FIFO" to mean whatever it wants, and currently + * won't enable it unless there's room for that set and much more. + */ + + SVGA_FIFO_CAPABILITIES = 4, + SVGA_FIFO_FLAGS, + /* Valid with SVGA_FIFO_CAP_FENCE: */ + SVGA_FIFO_FENCE, + + /* + * Block 3a (optional extended registers): Additional registers for the + * extended FIFO, whose presence isn't actually implied by + * SVGA_CAP_EXTENDED_FIFO; these exist if SVGA_FIFO_MIN is high enough to + * leave room for them. + * + * These in block 3a, the VMX currently considers mandatory for the + * extended FIFO. + */ + + /* Valid if exists (i.e. if extended FIFO enabled): */ + SVGA_FIFO_3D_HWVERSION, /* See SVGA3dHardwareVersion in svga3d_reg.h */ + /* Valid with SVGA_FIFO_CAP_PITCHLOCK: */ + SVGA_FIFO_PITCHLOCK, + + /* Valid with SVGA_FIFO_CAP_CURSOR_BYPASS_3: */ + SVGA_FIFO_CURSOR_ON, /* Cursor bypass 3 show/hide register */ + SVGA_FIFO_CURSOR_X, /* Cursor bypass 3 x register */ + SVGA_FIFO_CURSOR_Y, /* Cursor bypass 3 y register */ + SVGA_FIFO_CURSOR_COUNT, /* Incremented when any of the other 3 change */ + SVGA_FIFO_CURSOR_LAST_UPDATED,/* Last time the host updated the cursor */ + + /* Valid with SVGA_FIFO_CAP_RESERVE: */ + SVGA_FIFO_RESERVED, /* Bytes past NEXT_CMD with real contents */ + + /* + * Valid with SVGA_FIFO_CAP_SCREEN_OBJECT or SVGA_FIFO_CAP_SCREEN_OBJECT_2: + * + * By default this is SVGA_ID_INVALID, to indicate that the cursor + * coordinates are specified relative to the virtual root. If this + * is set to a specific screen ID, cursor position is reinterpreted + * as a signed offset relative to that screen's origin. + */ + SVGA_FIFO_CURSOR_SCREEN_ID, + + /* + * Valid with SVGA_FIFO_CAP_DEAD + * + * An arbitrary value written by the host, drivers should not use it. + */ + SVGA_FIFO_DEAD, + + /* + * Valid with SVGA_FIFO_CAP_3D_HWVERSION_REVISED: + * + * Contains 3D HWVERSION (see SVGA3dHardwareVersion in svga3d_reg.h) + * on platforms that can enforce graphics resource limits. + */ + SVGA_FIFO_3D_HWVERSION_REVISED, + + /* + * XXX: The gap here, up until SVGA_FIFO_3D_CAPS, can be used for new + * registers, but this must be done carefully and with judicious use of + * capability bits, since comparisons based on SVGA_FIFO_MIN aren't + * enough to tell you whether the register exists: we've shipped drivers + * and products that used SVGA_FIFO_3D_CAPS but didn't know about some of + * the earlier ones. The actual order of introduction was: + * - PITCHLOCK + * - 3D_CAPS + * - CURSOR_* (cursor bypass 3) + * - RESERVED + * So, code that wants to know whether it can use any of the + * aforementioned registers, or anything else added after PITCHLOCK and + * before 3D_CAPS, needs to reason about something other than + * SVGA_FIFO_MIN. + */ + + /* + * 3D caps block space; valid with 3D hardware version >= + * SVGA3D_HWVERSION_WS6_B1. + */ + SVGA_FIFO_3D_CAPS = 32, + SVGA_FIFO_3D_CAPS_LAST = 32 + 255, + + /* + * End of VMX's current definition of "extended-FIFO registers". + * Registers before here are always enabled/disabled as a block; either + * the extended FIFO is enabled and includes all preceding registers, or + * it's disabled entirely. + * + * Block 3b (truly optional extended registers): Additional registers for + * the extended FIFO, which the VMX already knows how to enable and + * disable with correct granularity. + * + * Registers after here exist if and only if the guest SVGA driver + * sets SVGA_FIFO_MIN high enough to leave room for them. + */ + + /* Valid if register exists: */ + SVGA_FIFO_GUEST_3D_HWVERSION, /* Guest driver's 3D version */ + SVGA_FIFO_FENCE_GOAL, /* Matching target for SVGA_IRQFLAG_FENCE_GOAL */ + SVGA_FIFO_BUSY, /* See "FIFO Synchronization Registers" */ + + /* + * Always keep this last. This defines the maximum number of + * registers we know about. At power-on, this value is placed in + * the SVGA_REG_MEM_REGS register, and we expect the guest driver + * to allocate this much space in FIFO memory for registers. + */ + SVGA_FIFO_NUM_REGS +}; + + +/* + * Definition of registers included in extended FIFO support. + * + * The guest SVGA driver gets to allocate the FIFO between registers + * and data. It must always allocate at least 4 registers, but old + * drivers stopped there. + * + * The VMX will enable extended FIFO support if and only if the guest + * left enough room for all registers defined as part of the mandatory + * set for the extended FIFO. + * + * Note that the guest drivers typically allocate the FIFO only at + * initialization time, not at mode switches, so it's likely that the + * number of FIFO registers won't change without a reboot. + * + * All registers less than this value are guaranteed to be present if + * svgaUser->fifo.extended is set. Any later registers must be tested + * individually for compatibility at each use (in the VMX). + * + * This value is used only by the VMX, so it can change without + * affecting driver compatibility; keep it that way? + */ +#define SVGA_FIFO_EXTENDED_MANDATORY_REGS (SVGA_FIFO_3D_CAPS_LAST + 1) + + +/* + * FIFO Synchronization Registers + * + * This explains the relationship between the various FIFO + * sync-related registers in IOSpace and in FIFO space. + * + * SVGA_REG_SYNC -- + * + * The SYNC register can be used in two different ways by the guest: + * + * 1. If the guest wishes to fully sync (drain) the FIFO, + * it will write once to SYNC then poll on the BUSY + * register. The FIFO is sync'ed once BUSY is zero. + * + * 2. If the guest wants to asynchronously wake up the host, + * it will write once to SYNC without polling on BUSY. + * Ideally it will do this after some new commands have + * been placed in the FIFO, and after reading a zero + * from SVGA_FIFO_BUSY. + * + * (1) is the original behaviour that SYNC was designed to + * support. Originally, a write to SYNC would implicitly + * trigger a read from BUSY. This causes us to synchronously + * process the FIFO. + * + * This behaviour has since been changed so that writing SYNC + * will *not* implicitly cause a read from BUSY. Instead, it + * makes a channel call which asynchronously wakes up the MKS + * thread. + * + * New guests can use this new behaviour to implement (2) + * efficiently. This lets guests get the host's attention + * without waiting for the MKS to poll, which gives us much + * better CPU utilization on SMP hosts and on UP hosts while + * we're blocked on the host GPU. + * + * Old guests shouldn't notice the behaviour change. SYNC was + * never guaranteed to process the entire FIFO, since it was + * bounded to a particular number of CPU cycles. Old guests will + * still loop on the BUSY register until the FIFO is empty. + * + * Writing to SYNC currently has the following side-effects: + * + * - Sets SVGA_REG_BUSY to TRUE (in the monitor) + * - Asynchronously wakes up the MKS thread for FIFO processing + * - The value written to SYNC is recorded as a "reason", for + * stats purposes. + * + * If SVGA_FIFO_BUSY is available, drivers are advised to only + * write to SYNC if SVGA_FIFO_BUSY is FALSE. Drivers should set + * SVGA_FIFO_BUSY to TRUE after writing to SYNC. The MKS will + * eventually set SVGA_FIFO_BUSY on its own, but this approach + * lets the driver avoid sending multiple asynchronous wakeup + * messages to the MKS thread. + * + * SVGA_REG_BUSY -- + * + * This register is set to TRUE when SVGA_REG_SYNC is written, + * and it reads as FALSE when the FIFO has been completely + * drained. + * + * Every read from this register causes us to synchronously + * process FIFO commands. There is no guarantee as to how many + * commands each read will process. + * + * CPU time spent processing FIFO commands will be billed to + * the guest. + * + * New drivers should avoid using this register unless they + * need to guarantee that the FIFO is completely drained. It + * is overkill for performing a sync-to-fence. Older drivers + * will use this register for any type of synchronization. + * + * SVGA_FIFO_BUSY -- + * + * This register is a fast way for the guest driver to check + * whether the FIFO is already being processed. It reads and + * writes at normal RAM speeds, with no monitor intervention. + * + * If this register reads as TRUE, the host is guaranteeing that + * any new commands written into the FIFO will be noticed before + * the MKS goes back to sleep. + * + * If this register reads as FALSE, no such guarantee can be + * made. + * + * The guest should use this register to quickly determine + * whether or not it needs to wake up the host. If the guest + * just wrote a command or group of commands that it would like + * the host to begin processing, it should: + * + * 1. Read SVGA_FIFO_BUSY. If it reads as TRUE, no further + * action is necessary. + * + * 2. Write TRUE to SVGA_FIFO_BUSY. This informs future guest + * code that we've already sent a SYNC to the host and we + * don't need to send a duplicate. + * + * 3. Write a reason to SVGA_REG_SYNC. This will send an + * asynchronous wakeup to the MKS thread. + */ + + +/* + * FIFO Capabilities + * + * Fence -- Fence register and command are supported + * Accel Front -- Front buffer only commands are supported + * Pitch Lock -- Pitch lock register is supported + * Video -- SVGA Video overlay units are supported + * Escape -- Escape command is supported + * + * XXX: Add longer descriptions for each capability, including a list + * of the new features that each capability provides. + * + * SVGA_FIFO_CAP_SCREEN_OBJECT -- + * + * Provides dynamic multi-screen rendering, for improved Unity and + * multi-monitor modes. With Screen Object, the guest can + * dynamically create and destroy 'screens', which can represent + * Unity windows or virtual monitors. Screen Object also provides + * strong guarantees that DMA operations happen only when + * guest-initiated. Screen Object deprecates the BAR1 guest + * framebuffer (GFB) and all commands that work only with the GFB. + * + * New registers: + * FIFO_CURSOR_SCREEN_ID, VIDEO_DATA_GMRID, VIDEO_DST_SCREEN_ID + * + * New 2D commands: + * DEFINE_SCREEN, DESTROY_SCREEN, DEFINE_GMRFB, BLIT_GMRFB_TO_SCREEN, + * BLIT_SCREEN_TO_GMRFB, ANNOTATION_FILL, ANNOTATION_COPY + * + * New 3D commands: + * BLIT_SURFACE_TO_SCREEN + * + * New guarantees: + * + * - The host will not read or write guest memory, including the GFB, + * except when explicitly initiated by a DMA command. + * + * - All DMA, including legacy DMA like UPDATE and PRESENT_READBACK, + * is guaranteed to complete before any subsequent FENCEs. + * + * - All legacy commands which affect a Screen (UPDATE, PRESENT, + * PRESENT_READBACK) as well as new Screen blit commands will + * all behave consistently as blits, and memory will be read + * or written in FIFO order. + * + * For example, if you PRESENT from one SVGA3D surface to multiple + * places on the screen, the data copied will always be from the + * SVGA3D surface at the time the PRESENT was issued in the FIFO. + * This was not necessarily true on devices without Screen Object. + * + * This means that on devices that support Screen Object, the + * PRESENT_READBACK command should not be necessary unless you + * actually want to read back the results of 3D rendering into + * system memory. (And for that, the BLIT_SCREEN_TO_GMRFB + * command provides a strict superset of functionality.) + * + * - When a screen is resized, either using Screen Object commands or + * legacy multimon registers, its contents are preserved. + * + * SVGA_FIFO_CAP_GMR2 -- + * + * Provides new commands to define and remap guest memory regions (GMR). + * + * New 2D commands: + * DEFINE_GMR2, REMAP_GMR2. + * + * SVGA_FIFO_CAP_3D_HWVERSION_REVISED -- + * + * Indicates new register SVGA_FIFO_3D_HWVERSION_REVISED exists. + * This register may replace SVGA_FIFO_3D_HWVERSION on platforms + * that enforce graphics resource limits. This allows the platform + * to clear SVGA_FIFO_3D_HWVERSION and disable 3D in legacy guest + * drivers that do not limit their resources. + * + * Note this is an alias to SVGA_FIFO_CAP_GMR2 because these indicators + * are codependent (and thus we use a single capability bit). + * + * SVGA_FIFO_CAP_SCREEN_OBJECT_2 -- + * + * Modifies the DEFINE_SCREEN command to include a guest provided + * backing store in GMR memory and the bytesPerLine for the backing + * store. This capability requires the use of a backing store when + * creating screen objects. However if SVGA_FIFO_CAP_SCREEN_OBJECT + * is present then backing stores are optional. + * + * SVGA_FIFO_CAP_DEAD -- + * + * Drivers should not use this cap bit. This cap bit can not be + * reused since some hosts already expose it. + */ + +#define SVGA_FIFO_CAP_NONE 0 +#define SVGA_FIFO_CAP_FENCE (1<<0) +#define SVGA_FIFO_CAP_ACCELFRONT (1<<1) +#define SVGA_FIFO_CAP_PITCHLOCK (1<<2) +#define SVGA_FIFO_CAP_VIDEO (1<<3) +#define SVGA_FIFO_CAP_CURSOR_BYPASS_3 (1<<4) +#define SVGA_FIFO_CAP_ESCAPE (1<<5) +#define SVGA_FIFO_CAP_RESERVE (1<<6) +#define SVGA_FIFO_CAP_SCREEN_OBJECT (1<<7) +#define SVGA_FIFO_CAP_GMR2 (1<<8) +#define SVGA_FIFO_CAP_3D_HWVERSION_REVISED SVGA_FIFO_CAP_GMR2 +#define SVGA_FIFO_CAP_SCREEN_OBJECT_2 (1<<9) +#define SVGA_FIFO_CAP_DEAD (1<<10) + + +/* + * FIFO Flags + * + * Accel Front -- Driver should use front buffer only commands + */ + +#define SVGA_FIFO_FLAG_NONE 0 +#define SVGA_FIFO_FLAG_ACCELFRONT (1<<0) +#define SVGA_FIFO_FLAG_RESERVED (1<<31) /* Internal use only */ + +/* + * FIFO reservation sentinel value + */ + +#define SVGA_FIFO_RESERVED_UNKNOWN 0xffffffff + + +/* + * Video overlay support + */ + +#define SVGA_NUM_OVERLAY_UNITS 32 + + +/* + * Video capabilities that the guest is currently using + */ + +#define SVGA_VIDEO_FLAG_COLORKEY 0x0001 + + +/* + * Offsets for the video overlay registers + */ + +enum { + SVGA_VIDEO_ENABLED = 0, + SVGA_VIDEO_FLAGS, + SVGA_VIDEO_DATA_OFFSET, + SVGA_VIDEO_FORMAT, + SVGA_VIDEO_COLORKEY, + SVGA_VIDEO_SIZE, /* Deprecated */ + SVGA_VIDEO_WIDTH, + SVGA_VIDEO_HEIGHT, + SVGA_VIDEO_SRC_X, + SVGA_VIDEO_SRC_Y, + SVGA_VIDEO_SRC_WIDTH, + SVGA_VIDEO_SRC_HEIGHT, + SVGA_VIDEO_DST_X, /* Signed int32 */ + SVGA_VIDEO_DST_Y, /* Signed int32 */ + SVGA_VIDEO_DST_WIDTH, + SVGA_VIDEO_DST_HEIGHT, + SVGA_VIDEO_PITCH_1, + SVGA_VIDEO_PITCH_2, + SVGA_VIDEO_PITCH_3, + SVGA_VIDEO_DATA_GMRID, /* Optional, defaults to SVGA_GMR_FRAMEBUFFER */ + SVGA_VIDEO_DST_SCREEN_ID, /* Optional, defaults to virtual coords (SVGA_ID_INVALID) */ + SVGA_VIDEO_NUM_REGS +}; + + +/* + * SVGA Overlay Units + * + * width and height relate to the entire source video frame. + * srcX, srcY, srcWidth and srcHeight represent subset of the source + * video frame to be displayed. + */ + +typedef struct SVGAOverlayUnit { + uint32 enabled; + uint32 flags; + uint32 dataOffset; + uint32 format; + uint32 colorKey; + uint32 size; + uint32 width; + uint32 height; + uint32 srcX; + uint32 srcY; + uint32 srcWidth; + uint32 srcHeight; + int32 dstX; + int32 dstY; + uint32 dstWidth; + uint32 dstHeight; + uint32 pitches[3]; + uint32 dataGMRId; + uint32 dstScreenId; +} SVGAOverlayUnit; + + +/* + * SVGAScreenObject -- + * + * This is a new way to represent a guest's multi-monitor screen or + * Unity window. Screen objects are only supported if the + * SVGA_FIFO_CAP_SCREEN_OBJECT capability bit is set. + * + * If Screen Objects are supported, they can be used to fully + * replace the functionality provided by the framebuffer registers + * (SVGA_REG_WIDTH, HEIGHT, etc.) and by SVGA_CAP_DISPLAY_TOPOLOGY. + * + * The screen object is a struct with guaranteed binary + * compatibility. New flags can be added, and the struct may grow, + * but existing fields must retain their meaning. + * + * Added with SVGA_FIFO_CAP_SCREEN_OBJECT_2 are required fields of + * a SVGAGuestPtr that is used to back the screen contents. This + * memory must come from the GFB. The guest is not allowed to + * access the memory and doing so will have undefined results. The + * backing store is required to be page aligned and the size is + * padded to the next page boundry. The number of pages is: + * (bytesPerLine * size.width * 4 + PAGE_SIZE - 1) / PAGE_SIZE + * + * The pitch in the backingStore is required to be at least large + * enough to hold a 32bbp scanline. It is recommended that the + * driver pad bytesPerLine for a potential performance win. + * + * The cloneCount field is treated as a hint from the guest that + * the user wants this display to be cloned, countCount times. A + * value of zero means no cloning should happen. + */ + +#define SVGA_SCREEN_MUST_BE_SET (1 << 0) /* Must be set or results undefined */ +#define SVGA_SCREEN_HAS_ROOT SVGA_SCREEN_MUST_BE_SET /* Deprecated */ +#define SVGA_SCREEN_IS_PRIMARY (1 << 1) /* Guest considers this screen to be 'primary' */ +#define SVGA_SCREEN_FULLSCREEN_HINT (1 << 2) /* Guest is running a fullscreen app here */ + +/* + * Added with SVGA_FIFO_CAP_SCREEN_OBJECT_2. When the screen is + * deactivated the base layer is defined to lose all contents and + * become black. When a screen is deactivated the backing store is + * optional. When set backingPtr and bytesPerLine will be ignored. + */ +#define SVGA_SCREEN_DEACTIVATE (1 << 3) + +/* + * Added with SVGA_FIFO_CAP_SCREEN_OBJECT_2. When this flag is set + * the screen contents will be outputted as all black to the user + * though the base layer contents is preserved. The screen base layer + * can still be read and written to like normal though the no visible + * effect will be seen by the user. When the flag is changed the + * screen will be blanked or redrawn to the current contents as needed + * without any extra commands from the driver. This flag only has an + * effect when the screen is not deactivated. + */ +#define SVGA_SCREEN_BLANKING (1 << 4) + +typedef +struct SVGAScreenObject { + uint32 structSize; /* sizeof(SVGAScreenObject) */ + uint32 id; + uint32 flags; + struct { + uint32 width; + uint32 height; + } size; + struct { + int32 x; + int32 y; + } root; + + /* + * Added and required by SVGA_FIFO_CAP_SCREEN_OBJECT_2, optional + * with SVGA_FIFO_CAP_SCREEN_OBJECT. + */ + SVGAGuestImage backingStore; + uint32 cloneCount; +} SVGAScreenObject; + + +/* + * Commands in the command FIFO: + * + * Command IDs defined below are used for the traditional 2D FIFO + * communication (not all commands are available for all versions of the + * SVGA FIFO protocol). + * + * Note the holes in the command ID numbers: These commands have been + * deprecated, and the old IDs must not be reused. + * + * Command IDs from 1000 to 1999 are reserved for use by the SVGA3D + * protocol. + * + * Each command's parameters are described by the comments and + * structs below. + */ + +typedef enum { + SVGA_CMD_INVALID_CMD = 0, + SVGA_CMD_UPDATE = 1, + SVGA_CMD_RECT_COPY = 3, + SVGA_CMD_DEFINE_CURSOR = 19, + SVGA_CMD_DEFINE_ALPHA_CURSOR = 22, + SVGA_CMD_UPDATE_VERBOSE = 25, + SVGA_CMD_FRONT_ROP_FILL = 29, + SVGA_CMD_FENCE = 30, + SVGA_CMD_ESCAPE = 33, + SVGA_CMD_DEFINE_SCREEN = 34, + SVGA_CMD_DESTROY_SCREEN = 35, + SVGA_CMD_DEFINE_GMRFB = 36, + SVGA_CMD_BLIT_GMRFB_TO_SCREEN = 37, + SVGA_CMD_BLIT_SCREEN_TO_GMRFB = 38, + SVGA_CMD_ANNOTATION_FILL = 39, + SVGA_CMD_ANNOTATION_COPY = 40, + SVGA_CMD_DEFINE_GMR2 = 41, + SVGA_CMD_REMAP_GMR2 = 42, + SVGA_CMD_MAX +} SVGAFifoCmdId; + +#define SVGA_CMD_MAX_ARGS 64 + + +/* + * SVGA_CMD_UPDATE -- + * + * This is a DMA transfer which copies from the Guest Framebuffer + * (GFB) at BAR1 + SVGA_REG_FB_OFFSET to any screens which + * intersect with the provided virtual rectangle. + * + * This command does not support using arbitrary guest memory as a + * data source- it only works with the pre-defined GFB memory. + * This command also does not support signed virtual coordinates. + * If you have defined screens (using SVGA_CMD_DEFINE_SCREEN) with + * negative root x/y coordinates, the negative portion of those + * screens will not be reachable by this command. + * + * This command is not necessary when using framebuffer + * traces. Traces are automatically enabled if the SVGA FIFO is + * disabled, and you may explicitly enable/disable traces using + * SVGA_REG_TRACES. With traces enabled, any write to the GFB will + * automatically act as if a subsequent SVGA_CMD_UPDATE was issued. + * + * Traces and SVGA_CMD_UPDATE are the only supported ways to render + * pseudocolor screen updates. The newer Screen Object commands + * only support true color formats. + * + * Availability: + * Always available. + */ + +typedef +struct SVGAFifoCmdUpdate { + uint32 x; + uint32 y; + uint32 width; + uint32 height; +} SVGAFifoCmdUpdate; + + +/* + * SVGA_CMD_RECT_COPY -- + * + * Perform a rectangular DMA transfer from one area of the GFB to + * another, and copy the result to any screens which intersect it. + * + * Availability: + * SVGA_CAP_RECT_COPY + */ + +typedef +struct SVGAFifoCmdRectCopy { + uint32 srcX; + uint32 srcY; + uint32 destX; + uint32 destY; + uint32 width; + uint32 height; +} SVGAFifoCmdRectCopy; + + +/* + * SVGA_CMD_DEFINE_CURSOR -- + * + * Provide a new cursor image, as an AND/XOR mask. + * + * The recommended way to position the cursor overlay is by using + * the SVGA_FIFO_CURSOR_* registers, supported by the + * SVGA_FIFO_CAP_CURSOR_BYPASS_3 capability. + * + * Availability: + * SVGA_CAP_CURSOR + */ + +typedef +struct SVGAFifoCmdDefineCursor { + uint32 id; /* Reserved, must be zero. */ + uint32 hotspotX; + uint32 hotspotY; + uint32 width; + uint32 height; + uint32 andMaskDepth; /* Value must be 1 or equal to BITS_PER_PIXEL */ + uint32 xorMaskDepth; /* Value must be 1 or equal to BITS_PER_PIXEL */ + /* + * Followed by scanline data for AND mask, then XOR mask. + * Each scanline is padded to a 32-bit boundary. + */ +} SVGAFifoCmdDefineCursor; + + +/* + * SVGA_CMD_DEFINE_ALPHA_CURSOR -- + * + * Provide a new cursor image, in 32-bit BGRA format. + * + * The recommended way to position the cursor overlay is by using + * the SVGA_FIFO_CURSOR_* registers, supported by the + * SVGA_FIFO_CAP_CURSOR_BYPASS_3 capability. + * + * Availability: + * SVGA_CAP_ALPHA_CURSOR + */ + +typedef +struct SVGAFifoCmdDefineAlphaCursor { + uint32 id; /* Reserved, must be zero. */ + uint32 hotspotX; + uint32 hotspotY; + uint32 width; + uint32 height; + /* Followed by scanline data */ +} SVGAFifoCmdDefineAlphaCursor; + + +/* + * SVGA_CMD_UPDATE_VERBOSE -- + * + * Just like SVGA_CMD_UPDATE, but also provide a per-rectangle + * 'reason' value, an opaque cookie which is used by internal + * debugging tools. Third party drivers should not use this + * command. + * + * Availability: + * SVGA_CAP_EXTENDED_FIFO + */ + +typedef +struct SVGAFifoCmdUpdateVerbose { + uint32 x; + uint32 y; + uint32 width; + uint32 height; + uint32 reason; +} SVGAFifoCmdUpdateVerbose; + + +/* + * SVGA_CMD_FRONT_ROP_FILL -- + * + * This is a hint which tells the SVGA device that the driver has + * just filled a rectangular region of the GFB with a solid + * color. Instead of reading these pixels from the GFB, the device + * can assume that they all equal 'color'. This is primarily used + * for remote desktop protocols. + * + * Availability: + * SVGA_FIFO_CAP_ACCELFRONT + */ + +#define SVGA_ROP_COPY 0x03 + +#define SVGA_INVALID_DISPLAY_ID ((uint32)-1) + +typedef +struct SVGAFifoCmdFrontRopFill { + uint32 color; /* In the same format as the GFB */ + uint32 x; + uint32 y; + uint32 width; + uint32 height; + uint32 rop; /* Must be SVGA_ROP_COPY */ +} SVGAFifoCmdFrontRopFill; + + +/* + * SVGA_CMD_FENCE -- + * + * Insert a synchronization fence. When the SVGA device reaches + * this command, it will copy the 'fence' value into the + * SVGA_FIFO_FENCE register. It will also compare the fence against + * SVGA_FIFO_FENCE_GOAL. If the fence matches the goal and the + * SVGA_IRQFLAG_FENCE_GOAL interrupt is enabled, the device will + * raise this interrupt. + * + * Availability: + * SVGA_FIFO_FENCE for this command, + * SVGA_CAP_IRQMASK for SVGA_FIFO_FENCE_GOAL. + */ + +typedef +struct { + uint32 fence; +} SVGAFifoCmdFence; + + +/* + * SVGA_CMD_ESCAPE -- + * + * Send an extended or vendor-specific variable length command. + * This is used for video overlay, third party plugins, and + * internal debugging tools. See svga_escape.h + * + * Availability: + * SVGA_FIFO_CAP_ESCAPE + */ + +typedef +struct SVGAFifoCmdEscape { + uint32 nsid; + uint32 size; + /* followed by 'size' bytes of data */ +} SVGAFifoCmdEscape; + + +/* + * SVGA_CMD_DEFINE_SCREEN -- + * + * Define or redefine an SVGAScreenObject. See the description of + * SVGAScreenObject above. The video driver is responsible for + * generating new screen IDs. They should be small positive + * integers. The virtual device will have an implementation + * specific upper limit on the number of screen IDs + * supported. Drivers are responsible for recycling IDs. The first + * valid ID is zero. + * + * - Interaction with other registers: + * + * For backwards compatibility, when the GFB mode registers (WIDTH, + * HEIGHT, PITCHLOCK, BITS_PER_PIXEL) are modified, the SVGA device + * deletes all screens other than screen #0, and redefines screen + * #0 according to the specified mode. Drivers that use + * SVGA_CMD_DEFINE_SCREEN should destroy or redefine screen #0. + * + * If you use screen objects, do not use the legacy multi-mon + * registers (SVGA_REG_NUM_GUEST_DISPLAYS, SVGA_REG_DISPLAY_*). + * + * Availability: + * SVGA_FIFO_CAP_SCREEN_OBJECT or SVGA_FIFO_CAP_SCREEN_OBJECT_2 + */ + +typedef +struct { + SVGAScreenObject screen; /* Variable-length according to version */ +} SVGAFifoCmdDefineScreen; + + +/* + * SVGA_CMD_DESTROY_SCREEN -- + * + * Destroy an SVGAScreenObject. Its ID is immediately available for + * re-use. + * + * Availability: + * SVGA_FIFO_CAP_SCREEN_OBJECT or SVGA_FIFO_CAP_SCREEN_OBJECT_2 + */ + +typedef +struct { + uint32 screenId; +} SVGAFifoCmdDestroyScreen; + + +/* + * SVGA_CMD_DEFINE_GMRFB -- + * + * This command sets a piece of SVGA device state called the + * Guest Memory Region Framebuffer, or GMRFB. The GMRFB is a + * piece of light-weight state which identifies the location and + * format of an image in guest memory or in BAR1. The GMRFB has + * an arbitrary size, and it doesn't need to match the geometry + * of the GFB or any screen object. + * + * The GMRFB can be redefined as often as you like. You could + * always use the same GMRFB, you could redefine it before + * rendering from a different guest screen, or you could even + * redefine it before every blit. + * + * There are multiple ways to use this command. The simplest way is + * to use it to move the framebuffer either to elsewhere in the GFB + * (BAR1) memory region, or to a user-defined GMR. This lets a + * driver use a framebuffer allocated entirely out of normal system + * memory, which we encourage. + * + * Another way to use this command is to set up a ring buffer of + * updates in GFB memory. If a driver wants to ensure that no + * frames are skipped by the SVGA device, it is important that the + * driver not modify the source data for a blit until the device is + * done processing the command. One efficient way to accomplish + * this is to use a ring of small DMA buffers. Each buffer is used + * for one blit, then we move on to the next buffer in the + * ring. The FENCE mechanism is used to protect each buffer from + * re-use until the device is finished with that buffer's + * corresponding blit. + * + * This command does not affect the meaning of SVGA_CMD_UPDATE. + * UPDATEs always occur from the legacy GFB memory area. This + * command has no support for pseudocolor GMRFBs. Currently only + * true-color 15, 16, and 24-bit depths are supported. Future + * devices may expose capabilities for additional framebuffer + * formats. + * + * The default GMRFB value is undefined. Drivers must always send + * this command at least once before performing any blit from the + * GMRFB. + * + * Availability: + * SVGA_FIFO_CAP_SCREEN_OBJECT or SVGA_FIFO_CAP_SCREEN_OBJECT_2 + */ + +typedef +struct { + SVGAGuestPtr ptr; + uint32 bytesPerLine; + SVGAGMRImageFormat format; +} SVGAFifoCmdDefineGMRFB; + + +/* + * SVGA_CMD_BLIT_GMRFB_TO_SCREEN -- + * + * This is a guest-to-host blit. It performs a DMA operation to + * copy a rectangular region of pixels from the current GMRFB to + * one or more Screen Objects. + * + * The destination coordinate may be specified relative to a + * screen's origin (if a screen ID is specified) or relative to the + * virtual coordinate system's origin (if the screen ID is + * SVGA_ID_INVALID). The actual destination may span zero or more + * screens, in the case of a virtual destination rect or a rect + * which extends off the edge of the specified screen. + * + * This command writes to the screen's "base layer": the underlying + * framebuffer which exists below any cursor or video overlays. No + * action is necessary to explicitly hide or update any overlays + * which exist on top of the updated region. + * + * The SVGA device is guaranteed to finish reading from the GMRFB + * by the time any subsequent FENCE commands are reached. + * + * This command consumes an annotation. See the + * SVGA_CMD_ANNOTATION_* commands for details. + * + * Availability: + * SVGA_FIFO_CAP_SCREEN_OBJECT or SVGA_FIFO_CAP_SCREEN_OBJECT_2 + */ + +typedef +struct { + SVGASignedPoint srcOrigin; + SVGASignedRect destRect; + uint32 destScreenId; +} SVGAFifoCmdBlitGMRFBToScreen; + + +/* + * SVGA_CMD_BLIT_SCREEN_TO_GMRFB -- + * + * This is a host-to-guest blit. It performs a DMA operation to + * copy a rectangular region of pixels from a single Screen Object + * back to the current GMRFB. + * + * Usage note: This command should be used rarely. It will + * typically be inefficient, but it is necessary for some types of + * synchronization between 3D (GPU) and 2D (CPU) rendering into + * overlapping areas of a screen. + * + * The source coordinate is specified relative to a screen's + * origin. The provided screen ID must be valid. If any parameters + * are invalid, the resulting pixel values are undefined. + * + * This command reads the screen's "base layer". Overlays like + * video and cursor are not included, but any data which was sent + * using a blit-to-screen primitive will be available, no matter + * whether the data's original source was the GMRFB or the 3D + * acceleration hardware. + * + * Note that our guest-to-host blits and host-to-guest blits aren't + * symmetric in their current implementation. While the parameters + * are identical, host-to-guest blits are a lot less featureful. + * They do not support clipping: If the source parameters don't + * fully fit within a screen, the blit fails. They must originate + * from exactly one screen. Virtual coordinates are not directly + * supported. + * + * Host-to-guest blits do support the same set of GMRFB formats + * offered by guest-to-host blits. + * + * The SVGA device is guaranteed to finish writing to the GMRFB by + * the time any subsequent FENCE commands are reached. + * + * Availability: + * SVGA_FIFO_CAP_SCREEN_OBJECT or SVGA_FIFO_CAP_SCREEN_OBJECT_2 + */ + +typedef +struct { + SVGASignedPoint destOrigin; + SVGASignedRect srcRect; + uint32 srcScreenId; +} SVGAFifoCmdBlitScreenToGMRFB; + + +/* + * SVGA_CMD_ANNOTATION_FILL -- + * + * This is a blit annotation. This command stores a small piece of + * device state which is consumed by the next blit-to-screen + * command. The state is only cleared by commands which are + * specifically documented as consuming an annotation. Other + * commands (such as ESCAPEs for debugging) may intervene between + * the annotation and its associated blit. + * + * This annotation is a promise about the contents of the next + * blit: The video driver is guaranteeing that all pixels in that + * blit will have the same value, specified here as a color in + * SVGAColorBGRX format. + * + * The SVGA device can still render the blit correctly even if it + * ignores this annotation, but the annotation may allow it to + * perform the blit more efficiently, for example by ignoring the + * source data and performing a fill in hardware. + * + * This annotation is most important for performance when the + * user's display is being remoted over a network connection. + * + * Availability: + * SVGA_FIFO_CAP_SCREEN_OBJECT or SVGA_FIFO_CAP_SCREEN_OBJECT_2 + */ + +typedef +struct { + SVGAColorBGRX color; +} SVGAFifoCmdAnnotationFill; + + +/* + * SVGA_CMD_ANNOTATION_COPY -- + * + * This is a blit annotation. See SVGA_CMD_ANNOTATION_FILL for more + * information about annotations. + * + * This annotation is a promise about the contents of the next + * blit: The video driver is guaranteeing that all pixels in that + * blit will have the same value as those which already exist at an + * identically-sized region on the same or a different screen. + * + * Note that the source pixels for the COPY in this annotation are + * sampled before applying the anqnotation's associated blit. They + * are allowed to overlap with the blit's destination pixels. + * + * The copy source rectangle is specified the same way as the blit + * destination: it can be a rectangle which spans zero or more + * screens, specified relative to either a screen or to the virtual + * coordinate system's origin. If the source rectangle includes + * pixels which are not from exactly one screen, the results are + * undefined. + * + * Availability: + * SVGA_FIFO_CAP_SCREEN_OBJECT or SVGA_FIFO_CAP_SCREEN_OBJECT_2 + */ + +typedef +struct { + SVGASignedPoint srcOrigin; + uint32 srcScreenId; +} SVGAFifoCmdAnnotationCopy; + + +/* + * SVGA_CMD_DEFINE_GMR2 -- + * + * Define guest memory region v2. See the description of GMRs above. + * + * Availability: + * SVGA_CAP_GMR2 + */ + +typedef +struct { + uint32 gmrId; + uint32 numPages; +} SVGAFifoCmdDefineGMR2; + + +/* + * SVGA_CMD_REMAP_GMR2 -- + * + * Remap guest memory region v2. See the description of GMRs above. + * + * This command allows guest to modify a portion of an existing GMR by + * invalidating it or reassigning it to different guest physical pages. + * The pages are identified by physical page number (PPN). The pages + * are assumed to be pinned and valid for DMA operations. + * + * Description of command flags: + * + * SVGA_REMAP_GMR2_VIA_GMR: If enabled, references a PPN list in a GMR. + * The PPN list must not overlap with the remap region (this can be + * handled trivially by referencing a separate GMR). If flag is + * disabled, PPN list is appended to SVGARemapGMR command. + * + * SVGA_REMAP_GMR2_PPN64: If set, PPN list is in PPN64 format, otherwise + * it is in PPN32 format. + * + * SVGA_REMAP_GMR2_SINGLE_PPN: If set, PPN list contains a single entry. + * A single PPN can be used to invalidate a portion of a GMR or + * map it to to a single guest scratch page. + * + * Availability: + * SVGA_CAP_GMR2 + */ + +typedef enum { + SVGA_REMAP_GMR2_PPN32 = 0, + SVGA_REMAP_GMR2_VIA_GMR = (1 << 0), + SVGA_REMAP_GMR2_PPN64 = (1 << 1), + SVGA_REMAP_GMR2_SINGLE_PPN = (1 << 2), +} SVGARemapGMR2Flags; + +typedef +struct { + uint32 gmrId; + SVGARemapGMR2Flags flags; + uint32 offsetPages; /* offset in pages to begin remap */ + uint32 numPages; /* number of pages to remap */ + /* + * Followed by additional data depending on SVGARemapGMR2Flags. + * + * If flag SVGA_REMAP_GMR2_VIA_GMR is set, single SVGAGuestPtr follows. + * Otherwise an array of page descriptors in PPN32 or PPN64 format + * (according to flag SVGA_REMAP_GMR2_PPN64) follows. If flag + * SVGA_REMAP_GMR2_SINGLE_PPN is set, array contains a single entry. + */ +} SVGAFifoCmdRemapGMR2; + +#endif diff --git a/src/svga_struct.h b/src/svga_struct.h new file mode 100644 index 0000000..fe4f0bf --- /dev/null +++ b/src/svga_struct.h @@ -0,0 +1,40 @@ +/* ********************************************************** + * Copyright (C) 1998-2000 VMware, Inc. + * All Rights Reserved + * **********************************************************/ + +#ifndef _SVGA_STRUCT_H_ +#define _SVGA_STRUCT_H_ + +#define INCLUDE_ALLOW_USERLEVEL +#define INCLUDE_ALLOW_MONITOR +#include "includeCheck.h" + + /* + * Offscreen memory surface structure + * + */ + +enum SVGASurfaceVersion { + SVGA_SURFACE_VERSION_1 = 1 /* Initial version... */ +}; + +typedef struct _SVGASurface { + uint32 size; /* Size of the structure */ + uint32 version; /* Version of this surface structure. */ + uint32 bpp; /* Format of the surface */ + uint32 width; /* Width of the surface */ + uint32 height; /* Height of the surface */ + uint32 pitch; /* Pitch of the surface */ + volatile uint32 numQueued; /* Number of times this bitmap has been queued */ + volatile uint32 numDequeued; /* Number of times this bitmap has been dequeued */ + uint32 userData; /* Driver defined data */ + uint32 dataOffset; /* Offset to the data */ +} SVGASurface; + +typedef struct SVGAPoint { + int16 x; + int16 y; +} SVGAPoint; + +#endif diff --git a/src/vm_basic_types.h b/src/vm_basic_types.h new file mode 100644 index 0000000..37272ee --- /dev/null +++ b/src/vm_basic_types.h @@ -0,0 +1,171 @@ +/* ********************************************************** + * Copyright (C) 1998-2001 VMware, Inc. + * All Rights Reserved + * **********************************************************/ + +/* + * + * vm_basic_types.h -- + * + * basic data types. + */ + + +#ifndef _VM_BASIC_TYPES_H_ +#define _VM_BASIC_TYPES_H_ + +#define INCLUDE_ALLOW_USERLEVEL +#define INCLUDE_ALLOW_MONITOR +#define INCLUDE_ALLOW_MODULE +#define INCLUDE_ALLOW_VMKERNEL +#include "includeCheck.h" + +/* STRICT ANSI means the Xserver build and X defines Bool differently. */ +#if 0 +typedef char Bool; +#endif + +#ifndef FALSE +#define FALSE 0 +#endif + +#ifndef TRUE +#define TRUE 1 +#endif + +#ifdef _MSC_VER +typedef unsigned __int64 uint64; +typedef signed __int64 int64; + +#pragma warning (disable :4018) // signed/unsigned mismatch +#pragma warning (disable :4761) // integral size mismatch in argument; conversion supplied +#pragma warning (disable :4305) // truncation from 'const int' to 'short' +#pragma warning (disable :4244) // conversion from 'unsigned short' to 'unsigned char' +//#pragma warning (disable :4101) // unreferenced local variable +#pragma warning (disable :4133) // incompatible types - from 'struct VM *' to 'int *' +#pragma warning (disable :4047) // differs in levels of indirection +#pragma warning (disable :4146) // unary minus operator applied to unsigned type, result still unsigned +#pragma warning (disable :4142) // benign redefinition of type + +#elif defined(__GNUC__) +/* The Xserver source compiles with -ansi -pendantic */ +#ifndef __STRICT_ANSI__ +typedef unsigned long long uint64; +typedef long long int64; +#endif +#else +/* int64/uint64 aren't actually used in the vmware driver. */ +#if 0 +#error - Need compiler define for int64/uint64 +#endif +#endif + +typedef unsigned int uint32; +typedef unsigned short uint16; +typedef unsigned char uint8; + +typedef int int32; +typedef short int16; +typedef char int8; + + +/* + * Printf format for 64-bit number. Use it like this: + * printf("%"FMT64"d\n", big); + */ + +#ifdef _MSC_VER +#define FMT64 "I64" +#elif defined(__GNUC__) +#define FMT64 "L" +#else +/* FMT64 isn't actually used in the vmware driver. */ +#if 0 +#error - Need compiler define for FMT64 +#endif +#endif + +typedef uint32 VA; +typedef uint32 VPN; + +typedef uint32 PA; +typedef uint32 PPN; + +typedef uint32 MA; +typedef uint32 MPN; + +#define INVALID_MPN ((MPN)-1) + +#define EXTERN extern +/* + * Right now our use of CONST is broken enough that it only works + * with GCC. XXX Need to fix this. + */ +#ifdef __GNUC__ +#define CONST const +#else +#ifndef CONST +#define CONST +#endif +#endif + +#ifdef _MSC_VER +#ifndef INLINE +#define INLINE __inline +#endif +#else +#ifndef INLINE +#define INLINE inline +#endif +#endif + + +#if defined(WIN32) && !defined(VMX86_NO_THREADS) +#define THREADSPECIFIC _declspec(thread) +#else +#define THREADSPECIFIC +#endif + +/* + * Like "INLINE" but use this token to mark functions that are inline + * because they have only a single call site. In other words, if a second + * call site is introduced, the "INLINE_SINGLE_CALLER" token should be + * removed. + */ +#define INLINE_SINGLE_CALLER INLINE + +/* + * Attributes placed on function declarations to tell the compiler + * that the function never returns. + */ +#ifdef _MSC_VER +#define NORETURN_DECL(_fndecl) __declspec(noreturn) _fndecl +#elif defined(__GNUC__) && __GNUC__ >= 2 && __GNUC_MINOR__ >= 5 +#define NORETURN_DECL(_fndecl) _fndecl __attribute__((__noreturn__)) +#else +#define NORETURN_DECL(_fndecl) _fndecl +#endif + + +/* + * GCC's argument checking for printf-like functions + * This is conditional until we have replaced all `"%x", void *' + * with `"0x%08x", (uint32) void *'. Note that %p prints different things + * on different platforms. + * + * fmtPos is the position of the format string argument, beginning at 1 + * varPos is the position of the variable argument, beginning at 1 + */ +#if defined(__GNUC__) && defined(notdef) +# define PRINTF_DECL(fmtPos, varPos) __attribute__((__format__(__printf__, fmtPos, varPos))) +#else +# define PRINTF_DECL(fmtPos, varPos) +#endif + +/* + * Used to silence compiler warnings that get generated when the + * compiler thinks that a function returns when it is marked noreturn. + */ +#define INFINITE_LOOP() do { } while (1) + +#endif diff --git a/src/vm_device_version.h b/src/vm_device_version.h new file mode 100644 index 0000000..92a5cac --- /dev/null +++ b/src/vm_device_version.h @@ -0,0 +1,62 @@ +/* ********************************************************** + * Copyright (C) 1998-2001 VMware, Inc. + * All Rights Reserved + * **********************************************************/ + + +#ifndef VM_DEVICE_VERSION_H +#define VM_DEVICE_VERSION_H + +#define INCLUDE_ALLOW_USERLEVEL +#define INCLUDE_ALLOW_MONITOR +#define INCLUDE_ALLOW_MODULE +#define INCLUDE_ALLOW_VMKERNEL +#include "includeCheck.h" + +#define PCI_VENDOR_ID_VMWARE 0x15AD +#define PCI_DEVICE_ID_VMWARE_SVGA2 0x0405 +#define PCI_DEVICE_ID_VMWARE_SVGA 0x0710 +#define PCI_DEVICE_ID_VMWARE_NET 0x0720 +#define PCI_DEVICE_ID_VMWARE_SCSI 0x0730 +#define PCI_DEVICE_ID_VMWARE_IDE 0x1729 + +/* From linux/pci.h. We emulate an AMD ethernet controller */ +#define PCI_VENDOR_ID_AMD 0x1022 +#define PCI_DEVICE_ID_AMD_VLANCE 0x2000 +#define PCI_VENDOR_ID_BUSLOGIC 0x104B +#define PCI_DEVICE_ID_BUSLOGIC_MULTIMASTER_NC 0x0140 +#define PCI_DEVICE_ID_BUSLOGIC_MULTIMASTER 0x1040 + +/* Intel Values for the chipset */ +#define PCI_VENDOR_ID_INTEL 0x8086 +#define PCI_DEVICE_ID_INTEL_82439TX 0x7100 +#define PCI_DEVICE_ID_INTEL_82371AB_0 0x7110 +#define PCI_DEVICE_ID_INTEL_82371AB_3 0x7113 +#define PCI_DEVICE_ID_INTEL_82371AB 0x7111 +#define PCI_DEVICE_ID_INTEL_82443BX 0x7192 + + +/************* Strings for IDE Identity Fields **************************/ +#define VIDE_ID_SERIAL_STR "00000000000000000001" /* Must be 20 Bytes */ +#define VIDE_ID_FIRMWARE_STR "00000001" /* Must be 8 Bytes */ + +/* No longer than 40 Bytes and must be an even length. */ +#define VIDE_ATA_MODEL_STR PRODUCT_GENERIC_NAME " Virtual IDE Hard Drive " +#define VIDE_ATAPI_MODEL_STR PRODUCT_GENERIC_NAME " Virtual IDE CDROM Drive " + +#define ATAPI_VENDOR_ID "NECVMWar" /* Must be 8 Bytes */ +#define ATAPI_PRODUCT_ID PRODUCT_GENERIC_NAME " IDE CDROM" /* Must be 16 Bytes */ +#define ATAPI_REV_LEVEL "1.00" /* Must be 4 Bytes */ + + +/************* Strings for SCSI Identity Fields **************************/ +#define SCSI_DISK_MODEL_STR PRODUCT_GENERIC_NAME " Virtual SCSI Hard Drive" +#define SCSI_CDROM_MODEL_STR PRODUCT_GENERIC_NAME " Virtual SCSI CDROM Drive" + +/************* Strings for the VESA BIOS Identity Fields *****************/ +#define VBE_OEM_STRING COMPANY_NAME " SVGA" +#define VBE_VENDOR_NAME COMPANY_NAME +#define VBE_PRODUCT_NAME PRODUCT_GENERIC_NAME + + +#endif /* VM_DEVICE_VERSION_H */ diff --git a/src/vmware.c b/src/vmware.c new file mode 100644 index 0000000..41201f1 --- /dev/null +++ b/src/vmware.c @@ -0,0 +1,1666 @@ +/* ********************************************************** + * Copyright (C) 1998-2001 VMware, Inc. + * All Rights Reserved + * **********************************************************/ +#ifdef VMX86_DEVEL +char rcsId_vmware[] = + "Id: vmware.c,v 1.11 2001/02/23 02:10:39 yoel Exp $"; +#endif + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +/* + * TODO: support the vmware linux kernel fb driver (Option "UseFBDev"). + */ + +#include "xf86.h" +#include "xf86_OSproc.h" + +#include "compiler.h" /* inb/outb */ + +#include "xf86Pci.h" /* pci */ + +#include "mipointer.h" /* sw cursor */ +#include "mibstore.h" /* backing store */ +#include "micmap.h" /* mi color map */ +#include "vgaHW.h" /* VGA hardware */ +#include "fb.h" +#include "shadowfb.h" /* ShadowFB wrappers */ + +#include "xf86cmap.h" /* xf86HandleColormaps */ + +#include "vmware.h" +#include "guest_os.h" +#include "vm_device_version.h" +#include "svga_modes.h" +#include "vmware_bootstrap.h" +#include "vmware_common.h" + +#ifndef HAVE_XORG_SERVER_1_5_0 +#include <xf86_ansic.h> +#include <xf86_libc.h> +#endif + +#if (GET_ABI_MAJOR(ABI_VIDEODRV_VERSION) >= 5) + +#define xf86LoaderReqSymLists(...) do {} while (0) +#define LoaderRefSymLists(...) do {} while (0) + +#else + +const char *vgahwSymbols[] = { + "vgaHWGetHWRec", + "vgaHWGetIOBase", + "vgaHWGetIndex", + "vgaHWInit", + "vgaHWProtect", + "vgaHWRestore", + "vgaHWSave", + "vgaHWSaveScreen", + "vgaHWUnlock", + NULL +}; + +static const char *fbSymbols[] = { + "fbCreateDefColormap", + "fbPictureInit", + "fbScreenInit", + NULL +}; + +static const char *ramdacSymbols[] = { + "xf86CreateCursorInfoRec", + "xf86DestroyCursorInfoRec", + "xf86InitCursor", + NULL +}; + +static const char *shadowfbSymbols[] = { + "ShadowFBInit2", + NULL +}; +#endif + +/* Table of default modes to always add to the mode list. */ + +typedef struct { + int width; + int height; +} VMWAREDefaultMode; + +#define VMW_MIN_INITIAL_WIDTH 800 +#define VMW_MIN_INITIAL_HEIGHT 600 + +#define SVGA_DEFAULT_MODE(width, height) { width, height, }, + +static const VMWAREDefaultMode VMWAREDefaultModes[] = { + SVGA_DEFAULT_MODES +}; + +#undef SVGA_DEFAULT_MODE + +static void VMWAREStopFIFO(ScrnInfoPtr pScrn); +static void VMWARESave(ScrnInfoPtr pScrn); + +static Bool +VMWAREGetRec(ScrnInfoPtr pScrn) +{ + if (pScrn->driverPrivate != NULL) { + return TRUE; + } + pScrn->driverPrivate = xnfcalloc(sizeof(VMWARERec), 1); + /* FIXME: Initialize driverPrivate... */ + return TRUE; +} + +static void +VMWAREFreeRec(ScrnInfoPtr pScrn) +{ + if (pScrn->driverPrivate) { + free(pScrn->driverPrivate); + pScrn->driverPrivate = NULL; + } +} + +CARD32 +vmwareReadReg(VMWAREPtr pVMWARE, int index) +{ + /* + * Block SIGIO for the duration, so we don't get interrupted after the + * outl but before the inl by a mouse move (which write to our registers). + */ + int oldsigio, ret; + oldsigio = xf86BlockSIGIO(); + outl(pVMWARE->indexReg, index); + ret = inl(pVMWARE->valueReg); + xf86UnblockSIGIO(oldsigio); + return ret; +} + +void +vmwareWriteReg(VMWAREPtr pVMWARE, int index, CARD32 value) +{ + /* + * Block SIGIO for the duration, so we don't get interrupted in between + * the outls by a mouse move (which write to our registers). + */ + int oldsigio; + oldsigio = xf86BlockSIGIO(); + outl(pVMWARE->indexReg, index); + outl(pVMWARE->valueReg, value); + xf86UnblockSIGIO(oldsigio); +} + +void +vmwareWriteWordToFIFO(VMWAREPtr pVMWARE, CARD32 value) +{ + volatile CARD32* vmwareFIFO = pVMWARE->vmwareFIFO; + + /* Need to sync? */ + if ((vmwareFIFO[SVGA_FIFO_NEXT_CMD] + sizeof(CARD32) == vmwareFIFO[SVGA_FIFO_STOP]) + || (vmwareFIFO[SVGA_FIFO_NEXT_CMD] == vmwareFIFO[SVGA_FIFO_MAX] - sizeof(CARD32) && + vmwareFIFO[SVGA_FIFO_STOP] == vmwareFIFO[SVGA_FIFO_MIN])) { + VmwareLog(("Syncing because of full fifo\n")); + vmwareWaitForFB(pVMWARE); + } + + vmwareFIFO[vmwareFIFO[SVGA_FIFO_NEXT_CMD] / sizeof(CARD32)] = value; + + write_mem_barrier(); + + if(vmwareFIFO[SVGA_FIFO_NEXT_CMD] == vmwareFIFO[SVGA_FIFO_MAX] - + sizeof(CARD32)) { + vmwareFIFO[SVGA_FIFO_NEXT_CMD] = vmwareFIFO[SVGA_FIFO_MIN]; + } else { + vmwareFIFO[SVGA_FIFO_NEXT_CMD] += sizeof(CARD32); + } +} + +void +vmwareWaitForFB(VMWAREPtr pVMWARE) +{ + vmwareWriteReg(pVMWARE, SVGA_REG_SYNC, 1); + while (vmwareReadReg(pVMWARE, SVGA_REG_BUSY)); +} + +void +vmwareSendSVGACmdUpdate(VMWAREPtr pVMWARE, BoxPtr pBB) +{ + vmwareWriteWordToFIFO(pVMWARE, SVGA_CMD_UPDATE); + vmwareWriteWordToFIFO(pVMWARE, pBB->x1); + vmwareWriteWordToFIFO(pVMWARE, pBB->y1); + vmwareWriteWordToFIFO(pVMWARE, pBB->x2 - pBB->x1); + vmwareWriteWordToFIFO(pVMWARE, pBB->y2 - pBB->y1); +} + +void +vmwareSendSVGACmdUpdateFullScreen(VMWAREPtr pVMWARE) +{ + BoxRec BB; + + BB.x1 = 0; + BB.y1 = 0; + BB.x2 = pVMWARE->ModeReg.svga_reg_width; + BB.y2 = pVMWARE->ModeReg.svga_reg_height; + vmwareSendSVGACmdUpdate(pVMWARE, &BB); +} + +static CARD32 +vmwareCalculateWeight(CARD32 mask) +{ + CARD32 weight; + + for (weight = 0; mask; mask >>= 1) { + if (mask & 1) { + weight++; + } + } + return weight; +} + +/* + *----------------------------------------------------------------------------- + * + * VMXGetVMwareSvgaId -- + * + * Retrieve the SVGA_ID of the VMware SVGA adapter. + * This function should hide any backward compatibility mess. + * + * Results: + * The SVGA_ID_* of the present VMware adapter. + * + * Side effects: + * ins/outs + * + *----------------------------------------------------------------------------- + */ + +static uint32 +VMXGetVMwareSvgaId(VMWAREPtr pVMWARE) +{ + uint32 vmware_svga_id; + + /* Any version with any SVGA_ID_* support will initialize SVGA_REG_ID + * to SVGA_ID_0 to support versions of this driver with SVGA_ID_0. + * + * Versions of SVGA_ID_0 ignore writes to the SVGA_REG_ID register. + * + * Versions of SVGA_ID_1 will allow us to overwrite the content + * of the SVGA_REG_ID register only with the values SVGA_ID_0 or SVGA_ID_1. + * + * Versions of SVGA_ID_2 will allow us to overwrite the content + * of the SVGA_REG_ID register only with the values SVGA_ID_0 or SVGA_ID_1 + * or SVGA_ID_2. + */ + + vmwareWriteReg(pVMWARE, SVGA_REG_ID, SVGA_ID_2); + vmware_svga_id = vmwareReadReg(pVMWARE, SVGA_REG_ID); + if (vmware_svga_id == SVGA_ID_2) { + return SVGA_ID_2; + } + + vmwareWriteReg(pVMWARE, SVGA_REG_ID, SVGA_ID_1); + vmware_svga_id = vmwareReadReg(pVMWARE, SVGA_REG_ID); + if (vmware_svga_id == SVGA_ID_1) { + return SVGA_ID_1; + } + + if (vmware_svga_id == SVGA_ID_0) { + return SVGA_ID_0; + } + + /* No supported VMware SVGA devices found */ + return SVGA_ID_INVALID; +} + +static Bool +VMWAREPreInit(ScrnInfoPtr pScrn, int flags) +{ + MessageType from; + VMWAREPtr pVMWARE; + OptionInfoPtr options; + int bpp24flags; + uint32 id; + int i; + ClockRange* clockRanges; + unsigned long domainIOBase = 0; + uint32 width = 0, height = 0; + Bool defaultMode; + +#if GET_ABI_MAJOR(ABI_VIDEODRV_VERSION) < 12 +#ifndef BUILD_FOR_420 + domainIOBase = pScrn->domainIOBase; +#endif +#endif + + if (flags & PROBE_DETECT) { + return FALSE; + } + + if (pScrn->numEntities != 1) { + return FALSE; + } + + if (!VMWAREGetRec(pScrn)) { + return FALSE; + } + pVMWARE = VMWAREPTR(pScrn); + + pVMWARE->pvtSema = &pScrn->vtSema; + + pVMWARE->pEnt = xf86GetEntityInfo(pScrn->entityList[0]); + if (pVMWARE->pEnt->location.type != BUS_PCI) { + return FALSE; + } + pVMWARE->PciInfo = xf86GetPciInfoForEntity(pVMWARE->pEnt->index); + if (pVMWARE->PciInfo == NULL) { + return FALSE; + } + + if (DEVICE_ID(pVMWARE->PciInfo) == PCI_DEVICE_ID_VMWARE_SVGA) { + pVMWARE->indexReg = domainIOBase + + SVGA_LEGACY_BASE_PORT + SVGA_INDEX_PORT*sizeof(uint32); + pVMWARE->valueReg = domainIOBase + + SVGA_LEGACY_BASE_PORT + SVGA_VALUE_PORT*sizeof(uint32); + } else { + /* Note: This setting of valueReg causes unaligned I/O */ +#if XSERVER_LIBPCIACCESS + pVMWARE->portIOBase = pVMWARE->PciInfo->regions[0].base_addr; +#else + pVMWARE->portIOBase = pVMWARE->PciInfo->ioBase[0]; +#endif + pVMWARE->indexReg = domainIOBase + + pVMWARE->portIOBase + SVGA_INDEX_PORT; + pVMWARE->valueReg = domainIOBase + + pVMWARE->portIOBase + SVGA_VALUE_PORT; + } + xf86DrvMsg(pScrn->scrnIndex, X_PROBED, + "VMware SVGA regs at (0x%04lx, 0x%04lx)\n", + pVMWARE->indexReg, pVMWARE->valueReg); + + if (!xf86LoadSubModule(pScrn, "vgahw")) { + return FALSE; + } + + xf86LoaderReqSymLists(vgahwSymbols, NULL); + + if (!vgaHWGetHWRec(pScrn)) { + return FALSE; + } + +#ifdef HAVE_XORG_SERVER_1_12_0 + vgaHWSetStdFuncs(VGAHWPTR(pScrn)); +#endif + + /* + * Save the current video state. Do it here before VMXGetVMwareSvgaId + * writes to any registers. + */ + VMWARESave(pScrn); + + id = VMXGetVMwareSvgaId(pVMWARE); + if (id == SVGA_ID_0 || id == SVGA_ID_INVALID) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "No supported VMware SVGA found (read ID 0x%08x).\n", id); + return FALSE; + } + pVMWARE->suspensionSavedRegId = id; + +#if !XSERVER_LIBPCIACCESS + pVMWARE->PciTag = pciTag(pVMWARE->PciInfo->bus, pVMWARE->PciInfo->device, + pVMWARE->PciInfo->func); +#endif + pVMWARE->Primary = xf86IsPrimaryPci(pVMWARE->PciInfo); + + pScrn->monitor = pScrn->confScreen->monitor; + +#ifdef ACCELERATE_OPS + pVMWARE->vmwareCapability = vmwareReadReg(pVMWARE, SVGA_REG_CAPABILITIES); +#else + pVMWARE->vmwareCapability = 0; +#endif + + pVMWARE->bitsPerPixel = vmwareReadReg(pVMWARE, + SVGA_REG_HOST_BITS_PER_PIXEL); + if (pVMWARE->vmwareCapability & SVGA_CAP_8BIT_EMULATION) { + vmwareWriteReg(pVMWARE, SVGA_REG_BITS_PER_PIXEL, pVMWARE->bitsPerPixel); + } + + pVMWARE->depth = vmwareReadReg(pVMWARE, SVGA_REG_DEPTH); + pVMWARE->videoRam = vmwareReadReg(pVMWARE, SVGA_REG_VRAM_SIZE); + pVMWARE->memPhysBase = vmwareReadReg(pVMWARE, SVGA_REG_FB_START); + pVMWARE->maxWidth = vmwareReadReg(pVMWARE, SVGA_REG_MAX_WIDTH); + pVMWARE->maxHeight = vmwareReadReg(pVMWARE, SVGA_REG_MAX_HEIGHT); + pVMWARE->cursorDefined = FALSE; + pVMWARE->cursorShouldBeHidden = FALSE; + + if (pVMWARE->vmwareCapability & SVGA_CAP_CURSOR_BYPASS_2) { + pVMWARE->cursorRemoveFromFB = SVGA_CURSOR_ON_REMOVE_FROM_FB; + pVMWARE->cursorRestoreToFB = SVGA_CURSOR_ON_RESTORE_TO_FB; + } else { + pVMWARE->cursorRemoveFromFB = SVGA_CURSOR_ON_HIDE; + pVMWARE->cursorRestoreToFB = SVGA_CURSOR_ON_SHOW; + } + + xf86DrvMsgVerb(pScrn->scrnIndex, X_PROBED, 2, "caps: 0x%08X\n", pVMWARE->vmwareCapability); + xf86DrvMsgVerb(pScrn->scrnIndex, X_PROBED, 2, "depth: %d\n", pVMWARE->depth); + xf86DrvMsgVerb(pScrn->scrnIndex, X_PROBED, 2, "bpp: %d\n", pVMWARE->bitsPerPixel); + + xf86DrvMsgVerb(pScrn->scrnIndex, X_PROBED, 2, "vram: %d\n", pVMWARE->videoRam); + xf86DrvMsgVerb(pScrn->scrnIndex, X_PROBED, 2, "pbase: 0x%08lx\n", pVMWARE->memPhysBase); + xf86DrvMsgVerb(pScrn->scrnIndex, X_PROBED, 2, "mwidt: %d\n", pVMWARE->maxWidth); + xf86DrvMsgVerb(pScrn->scrnIndex, X_PROBED, 2, "mheig: %d\n", pVMWARE->maxHeight); + + if (pVMWARE->vmwareCapability & SVGA_CAP_8BIT_EMULATION) { + bpp24flags = Support24bppFb | Support32bppFb; + } else { + switch (pVMWARE->depth) { + case 16: + /* + * In certain cases, the Windows host appears to + * report 16 bpp and 16 depth but 555 weight. Just + * silently convert it to depth of 15. + */ + if (pVMWARE->bitsPerPixel == 16 && + pVMWARE->weight.green == 5) + pVMWARE->depth = 15; + case 8: + case 15: + bpp24flags = NoDepth24Support; + break; + case 32: + /* + * There is no 32 bit depth, apparently it can get + * reported this way sometimes on the Windows host. + */ + if (pVMWARE->bitsPerPixel == 32) + pVMWARE->depth = 24; + case 24: + if (pVMWARE->bitsPerPixel == 24) + bpp24flags = Support24bppFb; + else + bpp24flags = Support32bppFb; + break; + default: + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "Adapter is using an unsupported depth (%d).\n", + pVMWARE->depth); + return FALSE; + } + } + + if (!xf86SetDepthBpp(pScrn, pVMWARE->depth, pVMWARE->bitsPerPixel, + pVMWARE->bitsPerPixel, bpp24flags)) { + return FALSE; + } + + /* Check that the returned depth is one we support */ + switch (pScrn->depth) { + case 8: + case 15: + case 16: + case 24: + /* OK */ + break; + default: + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "Given depth (%d) is not supported by this driver\n", + pScrn->depth); + return FALSE; + } + + if (pScrn->bitsPerPixel != pVMWARE->bitsPerPixel) { + if (pVMWARE->vmwareCapability & SVGA_CAP_8BIT_EMULATION) { + vmwareWriteReg(pVMWARE, SVGA_REG_BITS_PER_PIXEL, + pScrn->bitsPerPixel); + pVMWARE->bitsPerPixel = + vmwareReadReg(pVMWARE, SVGA_REG_BITS_PER_PIXEL); + pVMWARE->depth = vmwareReadReg(pVMWARE, SVGA_REG_DEPTH); + } else { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "Currently unavailable depth/bpp of %d/%d requested.\n" + "\tThe guest X server must run at the same depth and bpp as the host\n" + "\t(which are currently %d/%d). This is automatically detected. Please\n" + "\tdo not specify a depth on the command line or via the config file.\n", + pScrn->depth, pScrn->bitsPerPixel, + pVMWARE->depth, pVMWARE->bitsPerPixel); + return FALSE; + } + } + + /* + * Defer reading the colour registers until here in case we changed + * bpp above. + */ + + pVMWARE->weight.red = + vmwareCalculateWeight(vmwareReadReg(pVMWARE, SVGA_REG_RED_MASK)); + pVMWARE->weight.green = + vmwareCalculateWeight(vmwareReadReg(pVMWARE, SVGA_REG_GREEN_MASK)); + pVMWARE->weight.blue = + vmwareCalculateWeight(vmwareReadReg(pVMWARE, SVGA_REG_BLUE_MASK)); + pVMWARE->offset.blue = 0; + pVMWARE->offset.green = pVMWARE->weight.blue; + pVMWARE->offset.red = pVMWARE->weight.green + pVMWARE->offset.green; + pVMWARE->defaultVisual = vmwareReadReg(pVMWARE, SVGA_REG_PSEUDOCOLOR) ? + PseudoColor : TrueColor; + + xf86DrvMsgVerb(pScrn->scrnIndex, X_PROBED, + 2, "depth: %d\n", pVMWARE->depth); + xf86DrvMsgVerb(pScrn->scrnIndex, X_PROBED, + 2, "bpp: %d\n", pVMWARE->bitsPerPixel); + xf86DrvMsgVerb(pScrn->scrnIndex, X_PROBED, + 2, "w.red: %d\n", (int)pVMWARE->weight.red); + xf86DrvMsgVerb(pScrn->scrnIndex, X_PROBED, + 2, "w.grn: %d\n", (int)pVMWARE->weight.green); + xf86DrvMsgVerb(pScrn->scrnIndex, X_PROBED, + 2, "w.blu: %d\n", (int)pVMWARE->weight.blue); + xf86DrvMsgVerb(pScrn->scrnIndex, X_PROBED, + 2, "vis: %d\n", pVMWARE->defaultVisual); + + if (pScrn->depth != pVMWARE->depth) { + if (pVMWARE->vmwareCapability & SVGA_CAP_8BIT_EMULATION) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "Currently unavailable depth of %d requested.\n" + "\tIf the guest X server's BPP matches the host's " + "BPP, then\n\tthe guest X server's depth must also " + "match the\n\thost's depth (currently %d).\n", + pScrn->depth, pVMWARE->depth); + } else { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "Currently unavailable depth of %d requested.\n" + "\tThe guest X server must run at the same depth as " + "the host (which\n\tis currently %d). This is " + "automatically detected. Please do not\n\tspecify " + "a depth on the command line or via the config file.\n", + pScrn->depth, pVMWARE->depth); + } + return FALSE; + } + xf86PrintDepthBpp(pScrn); + +#if 0 + if (pScrn->depth == 24 && pix24bpp == 0) { + pix24bpp = xf86GetBppFromDepth(pScrn, 24); + } +#endif + + if (pScrn->depth > 8) { + rgb zeros = { 0, 0, 0 }; + + if (!xf86SetWeight(pScrn, pVMWARE->weight, zeros)) { + return FALSE; + } + /* FIXME check returned weight */ + } + if (!xf86SetDefaultVisual(pScrn, pVMWARE->defaultVisual)) { + return FALSE; + } + if (pScrn->defaultVisual != pVMWARE->defaultVisual) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "Given visual (%d) is not supported by this driver (%d is required)\n", + pScrn->defaultVisual, pVMWARE->defaultVisual); + return FALSE; + } +#if 0 + bytesPerPixel = pScrn->bitsPerPixel / 8; +#endif + pScrn->progClock = TRUE; + +#if 0 /* MGA does not do this */ + if (pScrn->visual != 0) { /* FIXME */ + /* print error message */ + return FALSE; + } +#endif + + xf86CollectOptions(pScrn, NULL); + if (!(options = VMWARECopyOptions())) + return FALSE; + xf86ProcessOptions(pScrn->scrnIndex, pScrn->options, options); + + if (pScrn->depth <= 8) { + pScrn->rgbBits = 8; + } + + if (!pScrn->chipset) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "ChipID 0x%04x is not recognised\n", DEVICE_ID(pVMWARE->PciInfo)); + return FALSE; + } + + from = X_DEFAULT; + pVMWARE->hwCursor = TRUE; + if (xf86GetOptValBool(options, OPTION_HW_CURSOR, &pVMWARE->hwCursor)) { + from = X_CONFIG; + } + if (pVMWARE->hwCursor && !(pVMWARE->vmwareCapability & SVGA_CAP_CURSOR)) { + xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "HW cursor is not supported in this configuration\n"); + from = X_PROBED; + pVMWARE->hwCursor = FALSE; + } + xf86DrvMsg(pScrn->scrnIndex, from, "Using %s cursor\n", + pVMWARE->hwCursor ? "HW" : "SW"); + pScrn->videoRam = pVMWARE->videoRam / 1024; + pScrn->memPhysBase = pVMWARE->memPhysBase; + + from = X_DEFAULT; + defaultMode = TRUE; + if (xf86GetOptValBool(options, OPTION_DEFAULT_MODE, &defaultMode)) { + from = X_CONFIG; + } + + width = vmwareReadReg(pVMWARE, SVGA_REG_WIDTH); + height = vmwareReadReg(pVMWARE, SVGA_REG_HEIGHT); + width = MAX(width, VMW_MIN_INITIAL_WIDTH); + height = MAX(height, VMW_MIN_INITIAL_HEIGHT); + + if (width > pVMWARE->maxWidth || height > pVMWARE->maxHeight) { + /* + * This is an error condition and shouldn't happen. + * revert to MIN_INITIAL_ values + */ + width = VMW_MIN_INITIAL_WIDTH; + height = VMW_MIN_INITIAL_HEIGHT; + } + + xf86DrvMsg(pScrn->scrnIndex, from, + "Will %sset up a driver mode with dimensions %dx%d.\n", + defaultMode ? "" : "not ", width, height); + + free(options); + + { + Gamma zeros = { 0.0, 0.0, 0.0 }; + if (!xf86SetGamma(pScrn, zeros)) { + return FALSE; + } + } +#if 0 + if ((i = xf86GetPciInfoForScreen(pScrn->scrnIndex, &pciList, NULL)) != 1) { + /* print error message */ + VMWAREFreeRec(pScrn); + if (i > 0) { + free(pciList); + } + return FALSE; + } +#endif + clockRanges = xnfcalloc(sizeof(ClockRange), 1); + clockRanges->next = NULL; + clockRanges->minClock = 1; + clockRanges->maxClock = 400000000; + clockRanges->clockIndex = -1; + clockRanges->interlaceAllowed = FALSE; + clockRanges->doubleScanAllowed = FALSE; + clockRanges->ClockMulFactor = 1; + clockRanges->ClockDivFactor = 1; + + if (defaultMode) { + vmwareAddDefaultMode(pScrn, width, height); + } + + i = xf86ValidateModes(pScrn, pScrn->monitor->Modes, pScrn->display->modes, + clockRanges, NULL, 256, pVMWARE->maxWidth, + pVMWARE->bitsPerPixel * 1, + 128, pVMWARE->maxHeight, + pScrn->display->virtualX, pScrn->display->virtualY, + pVMWARE->videoRam, + LOOKUP_BEST_REFRESH | LOOKUP_OPTIONAL_TOLERANCES); + + if (i == -1) { + VMWAREFreeRec(pScrn); + return FALSE; + } + xf86PruneDriverModes(pScrn); + if (i == 0 || pScrn->modes == NULL) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "No valid modes found\n"); + VMWAREFreeRec(pScrn); + return FALSE; + } + + pScrn->currentMode = pScrn->modes; + pScrn->virtualX = pScrn->modes->HDisplay; + pScrn->virtualY = pScrn->modes->VDisplay; + + xf86SetCrtcForModes(pScrn, INTERLACE_HALVE_V); + + xf86PrintModes(pScrn); + xf86SetDpi(pScrn, 0, 0); + if (!xf86LoadSubModule(pScrn, "fb") || + !xf86LoadSubModule(pScrn, "shadowfb")) { + VMWAREFreeRec(pScrn); + return FALSE; + } + xf86LoaderReqSymLists(fbSymbols, shadowfbSymbols, NULL); + + /* Need ramdac for hwcursor */ + if (pVMWARE->hwCursor) { + if (!xf86LoadSubModule(pScrn, "ramdac")) { + VMWAREFreeRec(pScrn); + return FALSE; + } + xf86LoaderReqSymLists(ramdacSymbols, NULL); + } + + return TRUE; +} + +static Bool +VMWAREMapMem(ScrnInfoPtr pScrn) +{ + VMWAREPtr pVMWARE = VMWAREPTR(pScrn); +#if XSERVER_LIBPCIACCESS + int err; + struct pci_device *const device = pVMWARE->PciInfo; + void *fbBase; +#endif + +#if XSERVER_LIBPCIACCESS + err = pci_device_map_range(device, + pVMWARE->memPhysBase, + pVMWARE->videoRam, + PCI_DEV_MAP_FLAG_WRITABLE, + &fbBase); + if (err) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "Unable to map frame buffer BAR. %s (%d)\n", + strerror (err), err); + return FALSE; + } + pVMWARE->FbBase = fbBase; +#else + pVMWARE->FbBase = xf86MapPciMem(pScrn->scrnIndex, 0, + pVMWARE->PciTag, + pVMWARE->memPhysBase, + pVMWARE->videoRam); +#endif + if (!pVMWARE->FbBase) + return FALSE; + + VmwareLog(("FB Mapped: %p/%u -> %p/%u\n", + pVMWARE->memPhysBase, pVMWARE->videoRam, + pVMWARE->FbBase, pVMWARE->videoRam)); + return TRUE; +} + +static Bool +VMWAREUnmapMem(ScrnInfoPtr pScrn) +{ + VMWAREPtr pVMWARE; + + pVMWARE = VMWAREPTR(pScrn); + + VmwareLog(("Unmapped: %p/%u\n", pVMWARE->FbBase, pVMWARE->videoRam)); + +#if XSERVER_LIBPCIACCESS + pci_device_unmap_range(pVMWARE->PciInfo, pVMWARE->FbBase, pVMWARE->videoRam); +#else + xf86UnMapVidMem(pScrn->scrnIndex, pVMWARE->FbBase, pVMWARE->videoRam); +#endif + pVMWARE->FbBase = NULL; + return TRUE; +} + +static void +VMWARESave(ScrnInfoPtr pScrn) +{ + vgaHWPtr hwp = VGAHWPTR(pScrn); + vgaRegPtr vgaReg = &hwp->SavedReg; + VMWAREPtr pVMWARE = VMWAREPTR(pScrn); + VMWARERegPtr vmwareReg = &pVMWARE->SavedReg; + + vgaHWSave(pScrn, vgaReg, VGA_SR_ALL); + + vmwareReg->svga_reg_enable = vmwareReadReg(pVMWARE, SVGA_REG_ENABLE); + vmwareReg->svga_reg_width = vmwareReadReg(pVMWARE, SVGA_REG_WIDTH); + vmwareReg->svga_reg_height = vmwareReadReg(pVMWARE, SVGA_REG_HEIGHT); + vmwareReg->svga_reg_bits_per_pixel = + vmwareReadReg(pVMWARE, SVGA_REG_BITS_PER_PIXEL); + vmwareReg->svga_reg_id = vmwareReadReg(pVMWARE, SVGA_REG_ID); + + /* XXX this should be based on the cap bit, not hwCursor... */ + if (pVMWARE->hwCursor) { + vmwareReg->svga_reg_cursor_on = + vmwareReadReg(pVMWARE, SVGA_REG_CURSOR_ON); + vmwareReg->svga_reg_cursor_x = + vmwareReadReg(pVMWARE, SVGA_REG_CURSOR_X); + vmwareReg->svga_reg_cursor_y = + vmwareReadReg(pVMWARE, SVGA_REG_CURSOR_Y); + vmwareReg->svga_reg_cursor_id = + vmwareReadReg(pVMWARE, SVGA_REG_CURSOR_ID); + } + + vmwareReg->svga_fifo_enabled = vmwareReadReg(pVMWARE, SVGA_REG_CONFIG_DONE); +} + +static void +VMWARERestoreRegs(ScrnInfoPtr pScrn, VMWARERegPtr vmwareReg) +{ + VMWAREPtr pVMWARE = VMWAREPTR(pScrn); + VmwareLog(("VMWARERestoreRegs: W: %d, H: %d, BPP: %d, Enable: %d\n", + vmwareReg->svga_reg_width, vmwareReg->svga_reg_height, + vmwareReg->svga_reg_bits_per_pixel, vmwareReg->svga_reg_enable)); + if (vmwareReg->svga_reg_enable) { + vmwareWriteReg(pVMWARE, SVGA_REG_ID, vmwareReg->svga_reg_id); + vmwareWriteReg(pVMWARE, SVGA_REG_WIDTH, vmwareReg->svga_reg_width); + vmwareWriteReg(pVMWARE, SVGA_REG_HEIGHT, vmwareReg->svga_reg_height); + vmwareWriteReg(pVMWARE, SVGA_REG_BITS_PER_PIXEL, + vmwareReg->svga_reg_bits_per_pixel); + vmwareWriteReg(pVMWARE, SVGA_REG_ENABLE, vmwareReg->svga_reg_enable); + vmwareWriteReg(pVMWARE, SVGA_REG_GUEST_ID, GUEST_OS_LINUX); + if (pVMWARE->hwCursor) { + vmwareWriteReg(pVMWARE, SVGA_REG_CURSOR_ID, + vmwareReg->svga_reg_cursor_id); + vmwareWriteReg(pVMWARE, SVGA_REG_CURSOR_X, + vmwareReg->svga_reg_cursor_x); + vmwareWriteReg(pVMWARE, SVGA_REG_CURSOR_Y, + vmwareReg->svga_reg_cursor_y); + vmwareWriteReg(pVMWARE, SVGA_REG_CURSOR_ON, + vmwareReg->svga_reg_cursor_on); + } + } else { + vmwareWriteReg(pVMWARE, SVGA_REG_ID, vmwareReg->svga_reg_id); + vmwareWriteReg(pVMWARE, SVGA_REG_WIDTH, vmwareReg->svga_reg_width); + vmwareWriteReg(pVMWARE, SVGA_REG_HEIGHT, vmwareReg->svga_reg_height); + vmwareWriteReg(pVMWARE, SVGA_REG_BITS_PER_PIXEL, + vmwareReg->svga_reg_bits_per_pixel); + vmwareWriteReg(pVMWARE, SVGA_REG_ENABLE, vmwareReg->svga_reg_enable); + } +} + +static void +VMWARERestore(ScrnInfoPtr pScrn) +{ + vgaHWPtr hwp = VGAHWPTR(pScrn); + vgaRegPtr vgaReg = &hwp->SavedReg; + VMWAREPtr pVMWARE = VMWAREPTR(pScrn); + VMWARERegPtr vmwareReg = &pVMWARE->SavedReg; + + vmwareWaitForFB(pVMWARE); + if (!vmwareReg->svga_fifo_enabled) { + VMWAREStopFIFO(pScrn); + } + + vgaHWProtect(pScrn, TRUE); + VMWARERestoreRegs(pScrn, vmwareReg); + vgaHWRestore(pScrn, vgaReg, VGA_SR_ALL); + vgaHWProtect(pScrn, FALSE); +} + +static Bool +VMWAREModeInit(ScrnInfoPtr pScrn, DisplayModePtr mode, Bool rebuildPixmap) +{ + vgaHWPtr hwp = VGAHWPTR(pScrn); + vgaRegPtr vgaReg = &hwp->ModeReg; + VMWAREPtr pVMWARE = VMWAREPTR(pScrn); + VMWARERegPtr vmwareReg = &pVMWARE->ModeReg; + + vgaHWUnlock(hwp); + if (!vgaHWInit(pScrn, mode)) + return FALSE; + pScrn->vtSema = TRUE; + + vmwareReg->svga_reg_enable = 1; + vmwareReg->svga_reg_width = max(mode->HDisplay, pScrn->virtualX); + vmwareReg->svga_reg_height = max(mode->VDisplay, pScrn->virtualY); + vmwareReg->svga_reg_bits_per_pixel = pVMWARE->bitsPerPixel; + + vgaHWProtect(pScrn, TRUE); + + vgaHWRestore(pScrn, vgaReg, VGA_SR_ALL); + VMWARERestoreRegs(pScrn, vmwareReg); + + if (pVMWARE->hwCursor) { + vmwareCursorModeInit(pScrn, mode); + } + + VmwareLog(("Required mode: %ux%u\n", mode->HDisplay, mode->VDisplay)); + VmwareLog(("Virtual: %ux%u\n", pScrn->virtualX, pScrn->virtualY)); + VmwareLog(("dispWidth: %u\n", pScrn->displayWidth)); + pVMWARE->fbOffset = vmwareReadReg(pVMWARE, SVGA_REG_FB_OFFSET); + pVMWARE->fbPitch = vmwareReadReg(pVMWARE, SVGA_REG_BYTES_PER_LINE); + pVMWARE->FbSize = vmwareReadReg(pVMWARE, SVGA_REG_FB_SIZE); + + pScrn->displayWidth = (pVMWARE->fbPitch * 8) / ((pScrn->bitsPerPixel + 7) & ~7); + VmwareLog(("fbOffset: %u\n", pVMWARE->fbOffset)); + VmwareLog(("fbPitch: %u\n", pVMWARE->fbPitch)); + VmwareLog(("fbSize: %u\n", pVMWARE->FbSize)); + VmwareLog(("New dispWidth: %u\n", pScrn->displayWidth)); + + vmwareCheckVideoSanity(pScrn); + + if (rebuildPixmap) { + pScrn->pScreen->ModifyPixmapHeader((*pScrn->pScreen->GetScreenPixmap)(pScrn->pScreen), + pScrn->pScreen->width, + pScrn->pScreen->height, + pScrn->pScreen->rootDepth, + pScrn->bitsPerPixel, + PixmapBytePad(pScrn->displayWidth, + pScrn->pScreen->rootDepth), + (pointer)(pVMWARE->FbBase + pScrn->fbOffset)); + + (*pScrn->EnableDisableFBAccess)(XF86_SCRN_ARG(pScrn), FALSE); + (*pScrn->EnableDisableFBAccess)(XF86_SCRN_ARG(pScrn), TRUE); + } + + vgaHWProtect(pScrn, FALSE); + + /* + * Push the new Xinerama state to X clients and the hardware, + * synchronously with the mode change. Note that this must happen + * AFTER we write the new width and height to the hardware + * registers, since updating the WIDTH and HEIGHT registers will + * reset the device's multimon topology. + */ + vmwareNextXineramaState(pVMWARE); + + return TRUE; +} + +void +vmwareNextXineramaState(VMWAREPtr pVMWARE) +{ + VMWARERegPtr vmwareReg = &pVMWARE->ModeReg; + + /* + * Switch to the next Xinerama state (from pVMWARE->xineramaNextState). + * + * This new state will be available to X clients via the Xinerama + * extension, and we push the new state to the virtual hardware, + * in order to configure a number of virtual monitors within the + * device's framebuffer. + * + * This function can be called at any time, but it should usually be + * called just after a mode switch. This is for two reasons: + * + * 1) We don't want X clients to see a Xinerama topology and a video + * mode that are inconsistent with each other, so we'd like to switch + * both at the same time. + * + * 2) We must set the host's display topology registers after setting + * the new video mode, since writes to WIDTH/HEIGHT will reset the + * hardware display topology. + */ + + /* + * Update Xinerama info appropriately. + */ + if (pVMWARE->xinerama && !pVMWARE->xineramaStatic) { + if (pVMWARE->xineramaNextState) { + free(pVMWARE->xineramaState); + pVMWARE->xineramaState = pVMWARE->xineramaNextState; + pVMWARE->xineramaNumOutputs = pVMWARE->xineramaNextNumOutputs; + + pVMWARE->xineramaNextState = NULL; + pVMWARE->xineramaNextNumOutputs = 0; + + } else { + /* + * There is no next state pending. Switch back to + * single-monitor mode. This is necessary for resetting the + * Xinerama state if we get a mode change which doesn't + * follow a VMwareCtrlDoSetTopology call. + */ + VMWAREXineramaPtr basicState = + (VMWAREXineramaPtr)calloc(1, sizeof (VMWAREXineramaRec)); + if (basicState) { + basicState->x_org = 0; + basicState->y_org = 0; + basicState->width = vmwareReg->svga_reg_width; + basicState->height = vmwareReg->svga_reg_height; + + free(pVMWARE->xineramaState); + pVMWARE->xineramaState = basicState; + pVMWARE->xineramaNumOutputs = 1; + } + } + } + + /* + * Update host's view of guest topology. This tells the device + * how we're carving up its framebuffer into virtual screens. + */ + if (pVMWARE->vmwareCapability & SVGA_CAP_DISPLAY_TOPOLOGY) { + if (pVMWARE->xinerama) { + int i = 0; + VMWAREXineramaPtr xineramaState = pVMWARE->xineramaState; + vmwareWriteReg(pVMWARE, SVGA_REG_NUM_GUEST_DISPLAYS, + pVMWARE->xineramaNumOutputs); + + for (i = 0; i < pVMWARE->xineramaNumOutputs; i++) { + vmwareWriteReg(pVMWARE, SVGA_REG_DISPLAY_ID, i); + vmwareWriteReg(pVMWARE, SVGA_REG_DISPLAY_IS_PRIMARY, i == 0); + vmwareWriteReg(pVMWARE, SVGA_REG_DISPLAY_POSITION_X, + xineramaState[i].x_org); + vmwareWriteReg(pVMWARE, SVGA_REG_DISPLAY_POSITION_Y, + xineramaState[i].y_org); + vmwareWriteReg(pVMWARE, SVGA_REG_DISPLAY_WIDTH, + xineramaState[i].width); + vmwareWriteReg(pVMWARE, SVGA_REG_DISPLAY_HEIGHT, + xineramaState[i].height); + } + } else { + vmwareWriteReg(pVMWARE, SVGA_REG_NUM_GUEST_DISPLAYS, 1); + + vmwareWriteReg(pVMWARE, SVGA_REG_DISPLAY_ID, 0); + vmwareWriteReg(pVMWARE, SVGA_REG_DISPLAY_IS_PRIMARY, TRUE); + vmwareWriteReg(pVMWARE, SVGA_REG_DISPLAY_POSITION_X, 0); + vmwareWriteReg(pVMWARE, SVGA_REG_DISPLAY_POSITION_Y, 0); + vmwareWriteReg(pVMWARE, SVGA_REG_DISPLAY_WIDTH, vmwareReg->svga_reg_width); + vmwareWriteReg(pVMWARE, SVGA_REG_DISPLAY_HEIGHT, vmwareReg->svga_reg_height); + } + + /* Done. */ + vmwareWriteReg(pVMWARE, SVGA_REG_DISPLAY_ID, SVGA_INVALID_DISPLAY_ID); + } +} + +static void +VMWAREAdjustFrame(ADJUST_FRAME_ARGS_DECL) +{ + /* FIXME */ +} + +static void +VMWAREInitFIFO(ScrnInfoPtr pScrn) +{ + VMWAREPtr pVMWARE = VMWAREPTR(pScrn); +#if XSERVER_LIBPCIACCESS + struct pci_device *const device = pVMWARE->PciInfo; + int err; + void *mmioVirtBase; +#endif + volatile CARD32* vmwareFIFO; + Bool extendedFifo; + int min; + + TRACEPOINT + + pVMWARE->mmioPhysBase = vmwareReadReg(pVMWARE, SVGA_REG_MEM_START); + pVMWARE->mmioSize = vmwareReadReg(pVMWARE, SVGA_REG_MEM_SIZE) & ~3; +#if XSERVER_LIBPCIACCESS + err = pci_device_map_range(device, pVMWARE->mmioPhysBase, + pVMWARE->mmioSize, + PCI_DEV_MAP_FLAG_WRITABLE, + &mmioVirtBase); + if (err) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "Unable to map mmio BAR. %s (%d)\n", + strerror (err), err); + return; + } + pVMWARE->mmioVirtBase = mmioVirtBase; +#else + pVMWARE->mmioVirtBase = xf86MapPciMem(pScrn->scrnIndex, VIDMEM_MMIO, + pVMWARE->PciTag, + pVMWARE->mmioPhysBase, + pVMWARE->mmioSize); +#endif + vmwareFIFO = pVMWARE->vmwareFIFO = (CARD32*)pVMWARE->mmioVirtBase; + + extendedFifo = pVMWARE->vmwareCapability & SVGA_CAP_EXTENDED_FIFO; + min = extendedFifo ? vmwareReadReg(pVMWARE, SVGA_REG_MEM_REGS) : 4; + + vmwareWaitForFB(pVMWARE); + vmwareWriteReg(pVMWARE, SVGA_REG_CONFIG_DONE, 0); + + vmwareFIFO[SVGA_FIFO_MIN] = min * sizeof(CARD32); + vmwareFIFO[SVGA_FIFO_MAX] = pVMWARE->mmioSize; + vmwareFIFO[SVGA_FIFO_NEXT_CMD] = min * sizeof(CARD32); + vmwareFIFO[SVGA_FIFO_STOP] = min * sizeof(CARD32); + vmwareWriteReg(pVMWARE, SVGA_REG_CONFIG_DONE, 1); +} + +static void +VMWAREStopFIFO(ScrnInfoPtr pScrn) +{ + VMWAREPtr pVMWARE = VMWAREPTR(pScrn); + + TRACEPOINT + + vmwareWriteReg(pVMWARE, SVGA_REG_CONFIG_DONE, 0); +#if XSERVER_LIBPCIACCESS + pci_device_unmap_range(pVMWARE->PciInfo, pVMWARE->mmioVirtBase, pVMWARE->mmioSize); +#else + xf86UnMapVidMem(pScrn->scrnIndex, pVMWARE->mmioVirtBase, pVMWARE->mmioSize); +#endif +} + +static Bool +VMWARECloseScreen(CLOSE_SCREEN_ARGS_DECL) +{ + ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen); + VMWAREPtr pVMWARE = VMWAREPTR(pScrn); + ScreenPtr save = &pVMWARE->ScrnFuncs; + + VmwareLog(("cursorSema: %d\n", pVMWARE->cursorSema)); + + if (*pVMWARE->pvtSema) { + if (pVMWARE->videoStreams) { + vmwareVideoEnd(pScreen); + } + + if (pVMWARE->CursorInfoRec) { + vmwareCursorCloseScreen(pScreen); + } + + VMWARERestore(pScrn); + VMWAREUnmapMem(pScrn); + + pScrn->vtSema = FALSE; + } + + pScreen->CloseScreen = save->CloseScreen; + pScreen->SaveScreen = save->SaveScreen; + +#if VMWARE_DRIVER_FUNC + pScrn->DriverFunc = NULL; +#endif + + return (*pScreen->CloseScreen)(CLOSE_SCREEN_ARGS); +} + +static Bool +VMWARESaveScreen(ScreenPtr pScreen, int mode) +{ + VmwareLog(("VMWareSaveScreen() mode = %d\n", mode)); + + /* + * This thoroughly fails to do anything useful to svga mode. I doubt + * we care; who wants to idle-blank their VM's screen anyway? + */ + return vgaHWSaveScreen(pScreen, mode); +} + +/* disabled by default to reduce spew in DEBUG_LOGGING mode. */ +/*#define DEBUG_LOG_UPDATES*/ + +static void +VMWAREPreDirtyBBUpdate(ScrnInfoPtr pScrn, int nboxes, BoxPtr boxPtr) +{ + VMWAREPtr pVMWARE = VMWAREPTR(pScrn); + +#ifdef DEBUG_LOG_UPDATES + { + int i; + for (i = 0; i < nboxes; i++) { + VmwareLog(("PreUpdate #%d (%d, %d, w = %d, h = %d)\n", nboxes - i, + boxPtr[i].x1, boxPtr[i].y1, + boxPtr[i].x2 - boxPtr[i].x1, + boxPtr[i].y2 - boxPtr[i].y1)); + } + } +#endif + + /* + * We only register this callback if we have a HW cursor. + */ + while (nboxes--) { + if (BOX_INTERSECT(*boxPtr, pVMWARE->hwcur.box)) { + if (!pVMWARE->cursorExcludedForUpdate) { + PRE_OP_HIDE_CURSOR(); + pVMWARE->cursorExcludedForUpdate = TRUE; + } + break; + } + boxPtr++; + } +} + +static void +VMWAREPostDirtyBBUpdate(ScrnInfoPtr pScrn, int nboxes, BoxPtr boxPtr) +{ + VMWAREPtr pVMWARE = VMWAREPTR(pScrn); + while (nboxes--) { +#ifdef DEBUG_LOG_UPDATES + VmwareLog(("PostUpdate #%d (%d, %d, w = %d, h = %d)\n", nboxes, + boxPtr->x1, boxPtr->y1, + boxPtr->x2 - boxPtr->x1, boxPtr->y2 - boxPtr->y1)); +#endif + + /* Clip off (y only) for offscreen memory */ + if (boxPtr->y2 >= pVMWARE->ModeReg.svga_reg_height) + boxPtr->y2 = pVMWARE->ModeReg.svga_reg_height; + if (boxPtr->y1 >= pVMWARE->ModeReg.svga_reg_height) + boxPtr->y1 = pVMWARE->ModeReg.svga_reg_height; + if (boxPtr->y1 == boxPtr->y2) { + boxPtr++; + continue; + } + + vmwareSendSVGACmdUpdate(pVMWARE, boxPtr++); + } + + if (pVMWARE->hwCursor && pVMWARE->cursorExcludedForUpdate) { + POST_OP_SHOW_CURSOR(); + pVMWARE->cursorExcludedForUpdate = FALSE; + } +} + +static void +VMWARELoadPalette(ScrnInfoPtr pScrn, int numColors, int* indices, + LOCO* colors, VisualPtr pVisual) +{ + VMWAREPtr pVMWARE = VMWAREPTR(pScrn); + int i; + + for (i = 0; i < numColors; i++) { + vmwareWriteReg(pVMWARE, SVGA_PALETTE_BASE + *indices * 3 + 0, colors[*indices].red); + vmwareWriteReg(pVMWARE, SVGA_PALETTE_BASE + *indices * 3 + 1, colors[*indices].green); + vmwareWriteReg(pVMWARE, SVGA_PALETTE_BASE + *indices * 3 + 2, colors[*indices].blue); + indices++; + } + VmwareLog(("Palette loading done\n")); +} + + +DisplayModeRec * +VMWAREAddDisplayMode(ScrnInfoPtr pScrn, + const char *name, + int width, + int height) +{ + DisplayModeRec *mode; + + mode = malloc(sizeof(DisplayModeRec)); + memset(mode, 0, sizeof *mode); + + mode->name = malloc(strlen(name) + 1); + strcpy(mode->name, name); + mode->status = MODE_OK; + mode->type = M_T_DEFAULT; + mode->HDisplay = width; + mode->VDisplay = height; + + mode->next = pScrn->modes; + mode->prev = pScrn->modes->prev; + pScrn->modes->prev->next = mode; + pScrn->modes->prev = mode; + + return mode; +} + + +/* + *----------------------------------------------------------------------------- + * + * vmwareIsRegionEqual -- + * + * This function implements REGION_EQUAL because older versions of + * regionstr.h don't define it. + * It is a slightly modified version of miRegionEqual from $Xorg: miregion.c + * + * Results: + * TRUE if regions are equal; FALSE otherwise + * + * Side effects: + * None. + * + *----------------------------------------------------------------------------- + */ + +Bool +vmwareIsRegionEqual(const RegionPtr reg1, + const RegionPtr reg2) +{ + int i, num; + BoxPtr rects1, rects2; + + if ((reg1->extents.x1 != reg2->extents.x1) || + (reg1->extents.x2 != reg2->extents.x2) || + (reg1->extents.y1 != reg2->extents.y1) || + (reg1->extents.y2 != reg2->extents.y2)) { + return FALSE; + } + + num = REGION_NUM_RECTS(reg1); + if (num != REGION_NUM_RECTS(reg2)) { + return FALSE; + } + + rects1 = REGION_RECTS(reg1); + rects2 = REGION_RECTS(reg2); + + for (i = 0; i < num; i++) { + if ((rects1[i].x1 != rects2[i].x1) || + (rects1[i].x2 != rects2[i].x2) || + (rects1[i].y1 != rects2[i].y1) || + (rects1[i].y2 != rects2[i].y2)) { + return FALSE; + } + } + + return TRUE; +} + +static Bool +VMWAREScreenInit(SCREEN_INIT_ARGS_DECL) +{ + ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen); + vgaHWPtr hwp; + VMWAREPtr pVMWARE; + OptionInfoPtr options; + Bool useXinerama = TRUE; + + pVMWARE = VMWAREPTR(pScrn); + + + xf86CollectOptions(pScrn, NULL); + if (!(options = VMWARECopyOptions())) + return FALSE; + xf86ProcessOptions(pScrn->scrnIndex, pScrn->options, options); + + /* + * Init xinerama preferences. + */ + useXinerama = xf86ReturnOptValBool(options, OPTION_XINERAMA, + pVMWARE->vmwareCapability & SVGA_CAP_MULTIMON); + if (useXinerama && !(pVMWARE->vmwareCapability & SVGA_CAP_MULTIMON)) { + xf86DrvMsg(pScrn->scrnIndex, X_WARNING, + "Xinerama is not safely supported by the current virtual hardware. " + "Do not request resolutions that require > 16MB of framebuffer.\n"); + } + + + if (useXinerama && xf86IsOptionSet(options, OPTION_GUI_LAYOUT)) { + char *topology = xf86GetOptValString(options, OPTION_GUI_LAYOUT); + if (topology) { + pVMWARE->xineramaState = + VMWAREParseTopologyString(pScrn, topology, + &pVMWARE->xineramaNumOutputs, "gui"); + + pVMWARE->xineramaStatic = pVMWARE->xineramaState != NULL; + + free(topology); + } + } else if (useXinerama && + xf86IsOptionSet(options, OPTION_STATIC_XINERAMA)) { + char *topology = xf86GetOptValString(options, OPTION_STATIC_XINERAMA); + if (topology) { + pVMWARE->xineramaState = + VMWAREParseTopologyString(pScrn, topology, + &pVMWARE->xineramaNumOutputs, + "static Xinerama"); + + pVMWARE->xineramaStatic = pVMWARE->xineramaState != NULL; + + free(topology); + } + } + + free(options); + + /* Initialise VMWARE_CTRL extension. */ + VMwareCtrl_ExtInit(pScrn); + + /* Initialise Xinerama extension. */ + if (useXinerama) { + VMwareXinerama_ExtInit(pScrn); + } + + if (pVMWARE->xinerama && pVMWARE->xineramaStatic) { + xf86DrvMsg(pScrn->scrnIndex, X_INFO, pVMWARE->xineramaState ? + "Using static Xinerama.\n" : + "Failed to configure static Xinerama.\n"); + } + + /* + * If using the vgahw module, its data structures and related + * things are typically initialised/mapped here. + */ + hwp = VGAHWPTR(pScrn); + vgaHWGetIOBase(hwp); + + VMWAREInitFIFO(pScrn); + + /* Initialise the first mode */ + VMWAREModeInit(pScrn, pScrn->currentMode, FALSE); + + /* Set the viewport if supported */ + VMWAREAdjustFrame(ADJUST_FRAME_ARGS(pScrn, pScrn->frameX0, pScrn->frameY0)); + + /* + * Setup the screen's visuals, and initialise the framebuffer + * code. + */ + VMWAREMapMem(pScrn); + + /* + * Clear the framebuffer (and any black-border mode areas). + */ + memset(pVMWARE->FbBase, 0, pVMWARE->FbSize); + vmwareSendSVGACmdUpdateFullScreen(pVMWARE); + + /* Reset the visual list */ + miClearVisualTypes(); + + /* + * Setup the visuals supported. This driver only supports + * TrueColor for bpp > 8, so the default set of visuals isn't + * acceptable. To deal with this, call miSetVisualTypes with + * the appropriate visual mask. + */ + if (pScrn->bitsPerPixel > 8) { + if (!miSetVisualTypes(pScrn->depth, TrueColorMask, + pScrn->rgbBits, pScrn->defaultVisual)) { + return FALSE; + } + } else { + if (!miSetVisualTypes(pScrn->depth, + miGetDefaultVisualMask(pScrn->depth), + pScrn->rgbBits, pScrn->defaultVisual)) { + return FALSE; + } + } + + miSetPixmapDepths(); + + /* + * Initialise the framebuffer. + */ + if (!fbScreenInit(pScreen, pVMWARE->FbBase + pVMWARE->fbOffset, + pScrn->virtualX, pScrn->virtualY, + pScrn->xDpi, pScrn->yDpi, + pScrn->displayWidth, + pScrn->bitsPerPixel)) { + return FALSE; + } + + /* Override the default mask/offset settings */ + if (pScrn->bitsPerPixel > 8) { + int i; + VisualPtr visual; + + for (i = 0, visual = pScreen->visuals; + i < pScreen->numVisuals; i++, visual++) { + 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); + + /* + * Save the old screen vector. + */ + pVMWARE->ScrnFuncs = *pScreen; + + /* + * Set initial black & white colourmap indices. + */ + xf86SetBlackWhitePixels(pScreen); + + /* + * Initialize shadowfb to notify us of dirty rectangles. We only + * need preFB access callbacks if we're using the hw cursor. + */ + if (!ShadowFBInit2(pScreen, + pVMWARE->hwCursor ? VMWAREPreDirtyBBUpdate : NULL, + VMWAREPostDirtyBBUpdate)) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "ShadowFB initialization failed\n"); + return FALSE; + } + + /* + * If we have a hw cursor, we need to hook functions that might + * read from the framebuffer. + */ + if (pVMWARE->hwCursor) { + vmwareCursorHookWrappers(pScreen); + } + + /* + * If backing store is to be supported (as is usually the case), + * initialise it. + */ + miInitializeBackingStore(pScreen); + xf86SetBackingStore(pScreen); + xf86SetSilkenMouse(pScreen); + + /* + * Initialize software cursor. + */ + miDCInitialize(pScreen, xf86GetPointerScreenFuncs()); + + /* + * Initialize hardware cursor. + */ + if (pVMWARE->hwCursor) { + if (!vmwareCursorInit(pScreen)) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "Hardware cursor initialization failed\n"); + pVMWARE->hwCursor = FALSE; + } + } + + /* + * Install colourmap functions. If using the vgahw module, + * vgaHandleColormaps would usually be called here. + */ + if (!fbCreateDefColormap(pScreen)) + return FALSE; + + if (!xf86HandleColormaps(pScreen, 256, 8, + VMWARELoadPalette, NULL, + CMAP_PALETTED_TRUECOLOR | + CMAP_RELOAD_ON_MODE_SWITCH)) { + return FALSE; + } + + /* + * We explictly add a set of default modes because the X server will + * not include modes larger than the initial one. + */ + { + unsigned int i; + unsigned int numModes = sizeof (VMWAREDefaultModes) / sizeof *(VMWAREDefaultModes); + char name[10]; + for (i = 0; i < numModes; i++) { + const VMWAREDefaultMode *mode = &VMWAREDefaultModes[i]; + + /* Only modes that fit the hardware maximums should be added. */ + if (mode->width <= pVMWARE->maxWidth && mode->height <= pVMWARE->maxHeight) { + snprintf(name, 10, "%dx%d", mode->width, mode->height); + VMWAREAddDisplayMode(pScrn, name, mode->width, mode->height); + } + } + + /* Add the hardware maximums as a mode. */ + snprintf(name, 10, "%dx%d", pVMWARE->maxWidth, pVMWARE->maxHeight); + VMWAREAddDisplayMode(pScrn, name, pVMWARE->maxWidth, pVMWARE->maxHeight); + } + + /* + * We will lazily add the dynamic modes as the are needed when new + * modes are requested through the control extension. + */ + memset(&pVMWARE->dynModes, 0, sizeof pVMWARE->dynModes); + +#if VMWARE_DRIVER_FUNC + pScrn->DriverFunc = VMWareDriverFunc; +#endif + + /* Report any unused options (only for the first generation) */ + if (serverGeneration == 1) { + xf86ShowUnusedOptions(pScrn->scrnIndex, pScrn->options); + } + + /* Initialize Xv extension */ + pVMWARE->videoStreams = NULL; + if (vmwareVideoEnabled(pVMWARE)) { + if (!vmwareVideoInit(pScreen)) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Xv initialization failed\n"); + } + } + + /** + * Wrap CloseScreen and SaveScreen. Do this late since we + * want to be first in the callchain, to avoid using resources + * already taken down in CloseScreen. + */ + + pVMWARE->ScrnFuncs.CloseScreen = pScreen->CloseScreen; + pVMWARE->ScrnFuncs.SaveScreen = pScreen->SaveScreen; + + pScreen->CloseScreen = VMWARECloseScreen; + pScreen->SaveScreen = VMWARESaveScreen; + + /* Done */ + return TRUE; +} + +static Bool +VMWARESwitchMode(SWITCH_MODE_ARGS_DECL) +{ + SCRN_INFO_PTR(arg); + ScreenPtr pScreen = pScrn->pScreen; + + pScreen->mmWidth = (pScreen->width * VMWARE_INCHTOMM + + pScrn->xDpi / 2) / pScrn->xDpi; + pScreen->mmHeight = (pScreen->height * VMWARE_INCHTOMM + + pScrn->yDpi / 2) / pScrn->yDpi; + + return VMWAREModeInit(pScrn, mode, TRUE); +} + +static Bool +VMWAREEnterVT(VT_FUNC_ARGS_DECL) +{ + SCRN_INFO_PTR(arg); + VMWAREPtr pVMWARE = VMWAREPTR(pScrn); + + /* + * After system resumes from hiberation, EnterVT will be called and this + * is a good place to restore the SVGA ID register. + */ + vmwareWriteReg(pVMWARE, SVGA_REG_ID, pVMWARE->suspensionSavedRegId); + + if (!pVMWARE->SavedReg.svga_fifo_enabled) { + VMWAREInitFIFO(pScrn); + } + + return VMWAREModeInit(pScrn, pScrn->currentMode, TRUE); +} + +static void +VMWARELeaveVT(VT_FUNC_ARGS_DECL) +{ + SCRN_INFO_PTR(arg); + VMWAREPtr pVMWARE = VMWAREPTR(pScrn); + + /* + * Before shutting down system for hibneration, LeaveVT will be called, + * we save the ID register value here and later restore it in EnterVT. + */ + pVMWARE->suspensionSavedRegId = vmwareReadReg(pVMWARE, SVGA_REG_ID); + + VMWARERestore(pScrn); +} + +static void +VMWAREFreeScreen(FREE_SCREEN_ARGS_DECL) +{ + SCRN_INFO_PTR(arg); + /* + * If the vgahw module is used vgaHWFreeHWRec() would be called + * here. + */ + VMWAREFreeRec(pScrn); +} + +static ModeStatus +VMWAREValidMode(SCRN_ARG_TYPE arg, DisplayModePtr mode, Bool verbose, int flags) +{ + return MODE_OK; +} + +void +vmwlegacy_hookup(ScrnInfoPtr pScrn) +{ + pScrn->PreInit = VMWAREPreInit; + pScrn->ScreenInit = VMWAREScreenInit; + pScrn->SwitchMode = VMWARESwitchMode; + pScrn->EnterVT = VMWAREEnterVT; + pScrn->LeaveVT = VMWARELeaveVT; + pScrn->FreeScreen = VMWAREFreeScreen; + pScrn->ValidMode = VMWAREValidMode; +} + +#ifdef XFree86LOADER +void +VMWARERefSymLists(void) +{ + LoaderRefSymLists(vgahwSymbols, fbSymbols, ramdacSymbols, + shadowfbSymbols, NULL); +} +#endif /* XFree86LOADER */ diff --git a/src/vmware.h b/src/vmware.h new file mode 100644 index 0000000..028dff3 --- /dev/null +++ b/src/vmware.h @@ -0,0 +1,316 @@ +/* ********************************************************** + * Copyright (C) 1998-2001 VMware, Inc. + * All Rights Reserved + * **********************************************************/ + +#ifndef VMWARE_H +#define VMWARE_H + + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#ifdef HAVE_XORG_SERVER_1_1_0 +#include <string.h> +#endif + +#include "xf86.h" +#include "xf86_OSproc.h" + +#include <X11/extensions/panoramiXproto.h> + +#ifdef XSERVER_LIBPCIACCESS +#include <pciaccess.h> +#else +#include "xf86Resources.h" +#endif + +#include "compiler.h" /* inb/outb */ + +#include "xf86Pci.h" /* pci */ +#include "xf86Cursor.h" /* hw cursor */ +#include "cursorstr.h" /* xhot/yhot */ + +#include "vgaHW.h" /* VGA hardware */ +#include "fb.h" + +#include "xf86cmap.h" /* xf86HandleColormaps */ + +#include "vm_basic_types.h" +#include "svga_reg.h" +#include "svga_struct.h" +#include "vmware_bootstrap.h" +#include <xf86Module.h> + +#if GET_ABI_MAJOR(ABI_VIDEODRV_VERSION) < 12 +#define _swapl(x, n) swapl(x,n) +#define _swaps(x, n) swaps(x,n) +#else +#define _swapl(x, n) (void) n; swapl(x) +#define _swaps(x, n) (void) n; swaps(x) +#endif + +/* + * The virtual hardware's cursor limits are pretty big. Some VMware + * product versions limit to 1024x1024 pixels, others limit to 128 + * kilobytes of cursor data. We just choose an arbitrary maximum + * cursor size. 64x64 is a common value for real hardware, so we'll go + * with that. + */ +#define MAX_CURS 64 + +#define NUM_DYN_MODES 2 + + +typedef struct { + CARD32 svga_reg_enable; + CARD32 svga_reg_width; + CARD32 svga_reg_height; + CARD32 svga_reg_bits_per_pixel; + + CARD32 svga_reg_cursor_on; + CARD32 svga_reg_cursor_x; + CARD32 svga_reg_cursor_y; + CARD32 svga_reg_cursor_id; + + Bool svga_fifo_enabled; + + CARD32 svga_reg_id; +} VMWARERegRec, *VMWARERegPtr; + +typedef xXineramaScreenInfo VMWAREXineramaRec, *VMWAREXineramaPtr; + +typedef struct { + EntityInfoPtr pEnt; +#if XSERVER_LIBPCIACCESS + struct pci_device *PciInfo; +#else + pciVideoPtr PciInfo; + PCITAG PciTag; +#endif + Bool Primary; + int depth; + int bitsPerPixel; + rgb weight; + rgb offset; + int defaultVisual; + int videoRam; + unsigned long memPhysBase; + unsigned long fbOffset; + unsigned long fbPitch; + unsigned long ioBase; + unsigned long portIOBase; + int maxWidth; + int maxHeight; + unsigned int vmwareCapability; + + unsigned char* FbBase; + unsigned long FbSize; + + VMWARERegRec SavedReg; + VMWARERegRec ModeReg; + CARD32 suspensionSavedRegId; + + DisplayModePtr dynModes[NUM_DYN_MODES]; + + Bool* pvtSema; + + Bool noAccel; + Bool hwCursor; + Bool cursorDefined; + int cursorSema; + Bool cursorExcludedForUpdate; + Bool cursorShouldBeHidden; + + unsigned int cursorRemoveFromFB; + unsigned int cursorRestoreToFB; + +#ifdef RENDER + CompositeProcPtr Composite; + void (*EnableDisableFBAccess)(int, Bool); +#endif /* RENDER */ + + unsigned long mmioPhysBase; + unsigned long mmioSize; + + unsigned char* mmioVirtBase; + CARD32* vmwareFIFO; + + xf86CursorInfoPtr CursorInfoRec; + CursorPtr oldCurs; + struct { + int bg, fg, x, y; + int hotX, hotY; + BoxRec box; + + uint32 mask[SVGA_BITMAP_SIZE(MAX_CURS, MAX_CURS)]; + uint32 maskPixmap[SVGA_PIXMAP_SIZE(MAX_CURS, MAX_CURS, 32)]; + uint32 source[SVGA_BITMAP_SIZE(MAX_CURS, MAX_CURS)]; + uint32 sourcePixmap[SVGA_PIXMAP_SIZE(MAX_CURS, MAX_CURS, 32)]; + } hwcur; + + unsigned long indexReg, valueReg; + + ScreenRec ScrnFuncs; + + /* + * Xinerama state + */ + Bool xinerama; + Bool xineramaStatic; + + VMWAREXineramaPtr xineramaState; + unsigned int xineramaNumOutputs; + + VMWAREXineramaPtr xineramaNextState; + unsigned int xineramaNextNumOutputs; + + /* + * Xv + */ + DevUnion *videoStreams; + +} VMWARERec, *VMWAREPtr; + +#define VMWAREPTR(p) ((VMWAREPtr)((p)->driverPrivate)) + +#define MIN(a,b) ((a)<(b)?(a):(b)) +#define MAX(a,b) ((a)>(b)?(a):(b)) +#define ABS(x) (((x) >= 0) ? (x) : -(x)) + +#define BOX_INTERSECT(a, b) \ + (ABS(((a).x1 + (a).x2) - ((b).x1 + (b).x2)) <= \ + ((a).x2 - (a).x1) + ((b).x2 - (b).x1) && \ + ABS(((a).y1 + (a).y2) - ((b).y1 + (b).y2)) <= \ + ((a).y2 - (a).y1) + ((b).y2 - (b).y1)) + +#define SVGA_GLYPH_SCANLINE_SIZE_DWORDS(w) (((w) + 31) >> 5) + +#define PRE_OP_HIDE_CURSOR() \ + if (pVMWARE->cursorDefined && *pVMWARE->pvtSema) { \ + pVMWARE->cursorSema++; \ + if (pVMWARE->cursorSema == 1) { \ + vmwareWriteCursorRegs(pVMWARE, FALSE, FALSE); \ + } \ + } +#define POST_OP_SHOW_CURSOR() \ + if (pVMWARE->cursorDefined && *pVMWARE->pvtSema) { \ + pVMWARE->cursorSema--; \ + if (!pVMWARE->cursorSema && !pVMWARE->cursorShouldBeHidden) { \ + vmwareWriteCursorRegs(pVMWARE, TRUE, FALSE); \ + } \ + } + +#define MOUSE_ID 1 + +/* Undefine this to kill all acceleration */ +#define ACCELERATE_OPS + +#if XSERVER_LIBPCIACCESS +#define VENDOR_ID(p) (p)->vendor_id +#define DEVICE_ID(p) (p)->device_id +#define SUBVENDOR_ID(p) (p)->subvendor_id +#define SUBSYS_ID(p) (p)->subdevice_id +#define CHIP_REVISION(p) (p)->revision +#else +#define VENDOR_ID(p) (p)->vendor +#define DEVICE_ID(p) (p)->chipType +#define SUBVENDOR_ID(p) (p)->subsysVendor +#define SUBSYS_ID(p) (p)->subsysCard +#define CHIP_REVISION(p) (p)->chipRev +#endif + +void vmwareWriteReg( + VMWAREPtr pVMWARE, int index, CARD32 value + ); + +CARD32 vmwareReadReg( + VMWAREPtr pVMWARE, int index + ); + +void vmwareWriteWordToFIFO( + VMWAREPtr pVMWARE, CARD32 value + ); + +void vmwareWaitForFB( + VMWAREPtr pVMWARE + ); + +void vmwareSendSVGACmdUpdate( + VMWAREPtr pVMWARE, BoxPtr pBB + ); + +void vmwareSendSVGACmdUpdateFullScreen( + VMWAREPtr pVMWARE + ); + +DisplayModeRec *VMWAREAddDisplayMode( + ScrnInfoPtr pScrn, + const char *name, + int width, + int height + ); + +Bool vmwareIsRegionEqual( + const RegionPtr reg1, + const RegionPtr reg2 + ); + +void vmwareNextXineramaState( + VMWAREPtr pVMWARE + ); + +/* vmwarecurs.c */ +Bool vmwareCursorInit( + ScreenPtr pScr + ); + +void vmwareCursorModeInit( + ScrnInfoPtr pScrn, + DisplayModePtr mode + ); + +void vmwareCursorCloseScreen( + ScreenPtr pScr + ); + +void vmwareWriteCursorRegs( + VMWAREPtr pVMWARE, + Bool visible, + Bool force + ); + +void vmwareCursorHookWrappers( + ScreenPtr pScreen + ); + + +/* vmwarectrl.c */ +void VMwareCtrl_ExtInit(ScrnInfoPtr pScrn); + +/* vmwarexinerama.c */ +void VMwareXinerama_ExtInit(ScrnInfoPtr pScrn); + +/* vmwarevideo.c */ +Bool vmwareVideoInit( + ScreenPtr pScreen + ); +void vmwareVideoEnd( + ScreenPtr pScreen + ); +Bool vmwareVideoEnabled( + VMWAREPtr pVMWARE + ); + +void vmwareCheckVideoSanity( + ScrnInfoPtr pScrn + ); + +/* vmwaremode.c */ +void vmwareAddDefaultMode( + ScrnInfoPtr pScrn, + uint32 dwidth, + uint32 dheight + ); +#endif diff --git a/src/vmware_bootstrap.c b/src/vmware_bootstrap.c new file mode 100644 index 0000000..ea5be19 --- /dev/null +++ b/src/vmware_bootstrap.c @@ -0,0 +1,502 @@ +/* + * Copyright 2011 VMWare, 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, 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 TUNGSTEN GRAPHICS 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. + * + * Author: Unknown at vmware + * Author: Thomas Hellstrom <thellstrom@vmware.com> + */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "xf86.h" +#include "compiler.h" +#include "xf86Pci.h" /* pci */ +#include "vm_device_version.h" +#include "vmware_bootstrap.h" + +#if GET_ABI_MAJOR(ABI_VIDEODRV_VERSION) < 6 +#include "xf86Resources.h" +#endif + +#ifndef XSERVER_LIBPCIACCESS +#include "vm_basic_types.h" +#include "svga_reg.h" +#endif + +#ifndef HAVE_XORG_SERVER_1_5_0 +#include <xf86_ansic.h> +#include <xf86_libc.h> +#endif + +#ifdef HaveDriverFuncs +#define VMWARE_DRIVER_FUNC HaveDriverFuncs +#else +#define VMWARE_DRIVER_FUNC 0 +#endif + +/* + * So that the file compiles unmodified when dropped in to a < 6.9 source tree. + */ +#ifndef _X_EXPORT +#define _X_EXPORT +#endif +/* + * So that the file compiles unmodified when dropped into an xfree source tree. + */ +#ifndef XORG_VERSION_CURRENT +#define XORG_VERSION_CURRENT XF86_VERSION_CURRENT +#endif + +/* + * This is the only way I know to turn a #define of an integer constant into + * a constant string. + */ +#define VMW_INNERSTRINGIFY(s) #s +#define VMW_STRING(str) VMW_INNERSTRINGIFY(str) + +#define VMWARE_NAME "vmware" +#define VMWARE_DRIVER_NAME "vmware" +#define VMWARE_DRIVER_VERSION \ + (PACKAGE_VERSION_MAJOR * 65536 + PACKAGE_VERSION_MINOR * 256 + PACKAGE_VERSION_PATCHLEVEL) +#define VMWARE_DRIVER_VERSION_STRING \ + VMW_STRING(PACKAGE_VERSION_MAJOR) "." VMW_STRING(PACKAGE_VERSION_MINOR) \ + "." VMW_STRING(PACKAGE_VERSION_PATCHLEVEL) + +static const char VMWAREBuildStr[] = "VMware Guest X Server " + VMWARE_DRIVER_VERSION_STRING " - build=$Name$\n"; + +/* + * Standard four digit version string expected by VMware Tools installer. + * As the driver's version is only {major, minor, patchlevel}, + * The fourth digit may describe the commit number relative to the + * last version tag as output from `git describe` + */ + +#ifdef __GNUC__ +#ifdef VMW_SUBPATCH +const char vmware_drv_modinfo[] +__attribute__((section(".modinfo"),unused)) = + "version=" VMWARE_DRIVER_VERSION_STRING "." VMW_STRING(VMW_SUBPATCH); +#else +const char vmware_drv_modinfo[] +__attribute__((section(".modinfo"),unused)) = + "version=" VMWARE_DRIVER_VERSION_STRING ".0"; +#endif /*VMW_SUBPATCH*/ +#endif + +#ifndef XSERVER_LIBPCIACCESS +static resRange vmwareLegacyRes[] = { + { ResExcIoBlock, SVGA_LEGACY_BASE_PORT, + SVGA_LEGACY_BASE_PORT + SVGA_NUM_PORTS*sizeof(uint32)}, + _VGA_EXCLUSIVE, _END +}; +#else +#define vmwareLegacyRes NULL +#endif + +#if XSERVER_LIBPCIACCESS +#define VENDOR_ID(p) (p)->vendor_id +#define DEVICE_ID(p) (p)->device_id +#define SUBVENDOR_ID(p) (p)->subvendor_id +#define SUBSYS_ID(p) (p)->subdevice_id +#define CHIP_REVISION(p) (p)->revision +#else +#define VENDOR_ID(p) (p)->vendor +#define DEVICE_ID(p) (p)->chipType +#define SUBVENDOR_ID(p) (p)->subsysVendor +#define SUBSYS_ID(p) (p)->subsysCard +#define CHIP_REVISION(p) (p)->chipRev +#endif + +#if XSERVER_LIBPCIACCESS + +#define VMWARE_DEVICE_MATCH(d, i) \ + {PCI_VENDOR_ID_VMWARE, (d), PCI_MATCH_ANY, PCI_MATCH_ANY, 0, 0, (i) } + +static const struct pci_id_match VMwareDeviceMatch[] = { + VMWARE_DEVICE_MATCH (PCI_DEVICE_ID_VMWARE_SVGA2, 0 ), + VMWARE_DEVICE_MATCH (PCI_DEVICE_ID_VMWARE_SVGA, 0 ), + { 0, 0, 0 }, +}; +#endif + +/* + * Currently, even the PCI obedient 0405 chip still only obeys IOSE and + * MEMSE for the SVGA resources. Thus, RES_EXCLUSIVE_VGA is required. + * + * The 0710 chip also uses hardcoded IO ports that aren't disablable. + */ + +static PciChipsets VMWAREPciChipsets[] = { + { PCI_DEVICE_ID_VMWARE_SVGA2, PCI_DEVICE_ID_VMWARE_SVGA2, RES_EXCLUSIVE_VGA }, + { PCI_DEVICE_ID_VMWARE_SVGA, PCI_DEVICE_ID_VMWARE_SVGA, vmwareLegacyRes }, + { -1, -1, RES_UNDEFINED } +}; + +static SymTabRec VMWAREChipsets[] = { + { PCI_DEVICE_ID_VMWARE_SVGA2, "vmware0405" }, + { PCI_DEVICE_ID_VMWARE_SVGA, "vmware0710" }, + { -1, NULL } +}; + +#ifdef XFree86LOADER +static XF86ModuleVersionInfo vmwareVersRec = { + VMWARE_DRIVER_NAME, + MODULEVENDORSTRING, + MODINFOSTRING1, + MODINFOSTRING2, + XORG_VERSION_CURRENT, + PACKAGE_VERSION_MAJOR, PACKAGE_VERSION_MINOR, PACKAGE_VERSION_PATCHLEVEL, + ABI_CLASS_VIDEODRV, + ABI_VIDEODRV_VERSION, + MOD_CLASS_VIDEODRV, + { 0, 0, 0, 0} +}; +#endif /* XFree86LOADER */ + +static const OptionInfoRec VMWAREOptions[] = { + { OPTION_HW_CURSOR, "HWcursor", OPTV_BOOLEAN, {0}, FALSE }, + { OPTION_XINERAMA, "Xinerama", OPTV_BOOLEAN, {0}, FALSE }, + { OPTION_STATIC_XINERAMA, "StaticXinerama", OPTV_STRING, {0}, FALSE }, + { OPTION_GUI_LAYOUT, "GuiLayout", OPTV_STRING, {0}, FALSE }, + { OPTION_DEFAULT_MODE, "AddDefaultMode", OPTV_BOOLEAN, {0}, FALSE }, + { OPTION_RENDER_ACCEL, "RenderAccel", OPTV_BOOLEAN, {0}, FALSE}, + { OPTION_DRI, "DRI", OPTV_BOOLEAN, {0}, FALSE}, + { OPTION_DIRECT_PRESENTS, "DirectPresents", OPTV_BOOLEAN, {0}, FALSE}, + { OPTION_HW_PRESENTS, "HWPresents", OPTV_BOOLEAN, {0}, FALSE}, + { OPTION_RENDERCHECK, "RenderCheck", OPTV_BOOLEAN, {0}, FALSE}, + { -1, NULL, OPTV_NONE, {0}, FALSE } +}; + +OptionInfoPtr VMWARECopyOptions(void) +{ + OptionInfoPtr options; + if (!(options = malloc(sizeof(VMWAREOptions)))) + return NULL; + + memcpy(options, VMWAREOptions, sizeof(VMWAREOptions)); + return options; +} + +static Bool +VMwarePreinitStub(ScrnInfoPtr pScrn, int flags) +{ +#if XSERVER_LIBPCIACCESS + struct pci_device *pciInfo; +#else + pciVideoPtr pciInfo; +#endif /* XSERVER_LIBPCIACCESS */ + EntityInfoPtr pEnt; + + pScrn->PreInit = pScrn->driverPrivate; + +#ifdef BUILD_VMWGFX + pScrn->driverPrivate = NULL; + + /* + * Try vmwgfx path. + */ + if ((*pScrn->PreInit)(pScrn, flags)) + return TRUE; + +#else + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "Driver was compiled without KMS- and 3D support.\n"); +#endif /* defined(BUILD_VMWGFX) */ + xf86DrvMsg(pScrn->scrnIndex, X_WARNING, + "Disabling 3D support.\n"); + xf86DrvMsg(pScrn->scrnIndex, X_WARNING, + "Disabling Render Acceleration.\n"); + xf86DrvMsg(pScrn->scrnIndex, X_WARNING, + "Disabling RandR12+ support.\n"); + + pScrn->driverPrivate = NULL; + vmwlegacy_hookup(pScrn); + + pEnt = xf86GetEntityInfo(pScrn->entityList[0]); + if (pEnt->location.type != BUS_PCI) + return FALSE; + + pciInfo = xf86GetPciInfoForEntity(pEnt->index); + if (pciInfo == NULL) + return FALSE; + + pScrn->chipset = (char*)xf86TokenToString(VMWAREChipsets, + DEVICE_ID(pciInfo)); + + return (*pScrn->PreInit)(pScrn, flags); +}; + +#if XSERVER_LIBPCIACCESS +static Bool +VMwarePciProbe (DriverPtr drv, + int entity_num, + struct pci_device *device, + intptr_t match_data) +{ + ScrnInfoPtr scrn = NULL; + EntityInfoPtr entity; + + scrn = xf86ConfigPciEntity(scrn, 0, entity_num, VMWAREPciChipsets, + NULL, NULL, NULL, NULL, NULL); + if (scrn != NULL) { + scrn->driverVersion = VMWARE_DRIVER_VERSION; + scrn->driverName = VMWARE_DRIVER_NAME; + scrn->name = VMWARE_NAME; + scrn->Probe = NULL; + } + + entity = xf86GetEntityInfo(entity_num); + switch (DEVICE_ID(device)) { + case PCI_DEVICE_ID_VMWARE_SVGA2: + case PCI_DEVICE_ID_VMWARE_SVGA: + xf86MsgVerb(X_INFO, 4, "VMwarePciProbe: Valid device\n"); + +#ifdef BUILD_VMWGFX + vmwgfx_hookup(scrn); +#else + vmwlegacy_hookup(scrn); +#endif /* defined(BUILD_VMWGFX) */ + + scrn->driverPrivate = scrn->PreInit; + scrn->PreInit = VMwarePreinitStub; + break; + default: + xf86MsgVerb(X_INFO, 4, "VMwarePciProbe: Unknown device\n"); + } + return scrn != NULL; +} +#else + +/* + *---------------------------------------------------------------------- + * + * RewriteTagString -- + * + * Rewrites the given string, removing the $Name$, and + * replacing it with the contents. The output string must + * have enough room, or else. + * + * Results: + * + * Output string updated. + * + * Side effects: + * None. + * + *---------------------------------------------------------------------- + */ + +static void +RewriteTagString(const char *istr, char *ostr, int osize) +{ + int chr; + Bool inTag = FALSE; + char *op = ostr; + + do { + chr = *istr++; + if (chr == '$') { + if (inTag) { + inTag = FALSE; + for (; op > ostr && op[-1] == ' '; op--) { + } + continue; + } + if (strncmp(istr, "Name:", 5) == 0) { + istr += 5; + istr += strspn(istr, " "); + inTag = TRUE; + continue; + } + } + *op++ = chr; + } while (chr); +} + +static Bool +VMWAREProbe(DriverPtr drv, int flags) +{ + int numDevSections, numUsed; + GDevPtr *devSections; + int *usedChips; + int i; + Bool foundScreen = FALSE; + char buildString[sizeof(VMWAREBuildStr)]; + + RewriteTagString(VMWAREBuildStr, buildString, sizeof(VMWAREBuildStr)); + xf86MsgVerb(X_PROBED, 4, "%s", buildString); + + numDevSections = xf86MatchDevice(VMWARE_DRIVER_NAME, &devSections); + if (numDevSections <= 0) { +#ifdef DEBUG + xf86MsgVerb(X_ERROR, 0, "No vmware driver section\n"); +#endif + return FALSE; + } + if (xf86GetPciVideoInfo()) { + VmwareLog(("Some PCI Video Info Exists\n")); + numUsed = xf86MatchPciInstances(VMWARE_NAME, PCI_VENDOR_ID_VMWARE, + VMWAREChipsets, VMWAREPciChipsets, devSections, + numDevSections, drv, &usedChips); + free(devSections); + if (numUsed <= 0) + return FALSE; + if (flags & PROBE_DETECT) + foundScreen = TRUE; + else + for (i = 0; i < numUsed; i++) { + ScrnInfoPtr pScrn = NULL; + + VmwareLog(("Even some VMware SVGA PCI instances exists\n")); + pScrn = xf86ConfigPciEntity(pScrn, flags, usedChips[i], + VMWAREPciChipsets, NULL, NULL, NULL, + NULL, NULL); + if (pScrn) { + VmwareLog(("And even configuration suceeded\n")); + pScrn->driverVersion = VMWARE_DRIVER_VERSION; + pScrn->driverName = VMWARE_DRIVER_NAME; + pScrn->name = VMWARE_NAME; + pScrn->Probe = VMWAREProbe; + +#ifdef BUILD_VMWGFX + vmwgfx_hookup(pScrn); +#else + vmwlegacy_hookup(pScrn); +#endif /* defined(BUILD_VMWGFX) */ + + pScrn->driverPrivate = pScrn->PreInit; + pScrn->PreInit = VMwarePreinitStub; + foundScreen = TRUE; + } + } + free(usedChips); + } + return foundScreen; +} +#endif + +static void +VMWAREIdentify(int flags) +{ + xf86PrintChipsets(VMWARE_NAME, "driver for VMware SVGA", VMWAREChipsets); +} + +static const OptionInfoRec * +VMWAREAvailableOptions(int chipid, int busid) +{ + return VMWAREOptions; +} + +#if VMWARE_DRIVER_FUNC +static Bool +VMWareDriverFunc(ScrnInfoPtr pScrn, + xorgDriverFuncOp op, + pointer data) +{ + CARD32 *flag; + xorgRRModeMM *modemm; + + switch (op) { + case GET_REQUIRED_HW_INTERFACES: + flag = (CARD32 *)data; + + if (flag) { + *flag = HW_IO | HW_MMIO; + } + return TRUE; + case RR_GET_MODE_MM: + modemm = (xorgRRModeMM *)data; + + /* + * Because changing the resolution of the guest is usually changing the size + * of a window on the host desktop, the real physical DPI will not change. To + * keep the guest in sync, we scale the 'physical' screen dimensions to + * keep the DPI constant. + */ + if (modemm && modemm->mode) { + modemm->mmWidth = (modemm->mode->HDisplay * VMWARE_INCHTOMM + + pScrn->xDpi / 2) / pScrn->xDpi; + modemm->mmHeight = (modemm->mode->VDisplay * VMWARE_INCHTOMM + + pScrn->yDpi / 2) / pScrn->yDpi; + } + return TRUE; + default: + return FALSE; + } +} +#endif + + +_X_EXPORT DriverRec vmware = { + VMWARE_DRIVER_VERSION, + VMWARE_DRIVER_NAME, + VMWAREIdentify, +#if XSERVER_LIBPCIACCESS + NULL, +#else + VMWAREProbe, +#endif + VMWAREAvailableOptions, + NULL, + 0, +#if VMWARE_DRIVER_FUNC + VMWareDriverFunc, +#endif +#if XSERVER_LIBPCIACCESS + VMwareDeviceMatch, + VMwarePciProbe, +#endif +}; + + +#ifdef XFree86LOADER +static MODULESETUPPROTO(vmwareSetup); + +_X_EXPORT XF86ModuleData vmwareModuleData = { + &vmwareVersRec, + vmwareSetup, + NULL +}; + +static pointer +vmwareSetup(pointer module, pointer opts, int *errmaj, int *errmin) +{ + static Bool setupDone = FALSE; + + if (!setupDone) { + setupDone = TRUE; + + xf86AddDriver(&vmware, module, VMWARE_DRIVER_FUNC); + + VMWARERefSymLists(); + + return (pointer)1; + } + if (errmaj) { + *errmaj = LDR_ONCEONLY; + } + return NULL; +} +#endif /* XFree86LOADER */ diff --git a/src/vmware_bootstrap.h b/src/vmware_bootstrap.h new file mode 100644 index 0000000..f72d298 --- /dev/null +++ b/src/vmware_bootstrap.h @@ -0,0 +1,71 @@ +/* + * Copyright 2011 VMWare, 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, 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 TUNGSTEN GRAPHICS 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. + * + * Author: Thomas Hellstrom <thellstrom@vmware.com> + */ +#ifndef _VMWARE_BOOTSTRAP_H_ +#define _VMWARE_BOOTSTRAP_H_ + +#include <xf86.h> + +#define VMWARE_INCHTOMM 25.4 + +typedef enum { + OPTION_HW_CURSOR, + OPTION_XINERAMA, + OPTION_STATIC_XINERAMA, + OPTION_GUI_LAYOUT, + OPTION_DEFAULT_MODE, + OPTION_RENDER_ACCEL, + OPTION_DRI, + OPTION_DIRECT_PRESENTS, + OPTION_HW_PRESENTS, + OPTION_RENDERCHECK +} VMWAREOpts; + +OptionInfoPtr VMWARECopyOptions(void); + +void +vmwlegacy_hookup(ScrnInfoPtr pScrn); + +#ifdef BUILD_VMWGFX +void +vmwgfx_hookup(ScrnInfoPtr pScrn); +#endif /* defined(BUILD_VMWGFX) */ + +#ifdef XFree86LOADER +void +VMWARERefSymLists(void); +#endif /* XFree86LOADER */ + +/*#define DEBUG_LOGGING*/ +#ifdef DEBUG_LOGGING +# define VmwareLog(args) ErrorF args +# define TRACEPOINT VmwareLog(("%s : %s\n", __FUNCTION__, __FILE__)); +#else +# define VmwareLog(args) +# define TRACEPOINT +#endif + +#endif diff --git a/src/vmware_common.c b/src/vmware_common.c new file mode 100644 index 0000000..6ef7ca6 --- /dev/null +++ b/src/vmware_common.c @@ -0,0 +1,163 @@ +/* + * Copyright 2011 VMWare, 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, 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 TUNGSTEN GRAPHICS 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. + * + * Author: Unknown at vmware + */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <xf86.h> +#include "vmware_common.h" + +#ifndef HAVE_XORG_SERVER_1_5_0 +#include <xf86_ansic.h> +#include <xf86_libc.h> +#endif + +static int +VMWAREParseTopologyElement(ScrnInfoPtr pScrn, + unsigned int output, + const char *elementName, + const char *element, + const char *expectedTerminators, + Bool needTerminator, + unsigned int *outValue) +{ + char buf[10] = {0, }; + size_t i = 0; + int retVal = -1; + const char *str = element; + + for (i = 0; str[i] >= '0' && str[i] <= '9'; i++); + if (i == 0) { + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Output %u: unable to parse %s.\n", + output, elementName); + goto exit; + } + + strncpy(buf, str, i); + *outValue = atoi(buf); + + if (*outValue > (unsigned short)-1) { + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Output %u: %s must be less than %hu.\n", + output, elementName, (unsigned short)-1); + goto exit; + } + + str += i; + + if (needTerminator || str[0] != '\0') { + Bool unexpected = TRUE; + + for (i = 0; i < strlen(expectedTerminators); i++) { + if (str[0] == expectedTerminators[i]) { + unexpected = FALSE; + } + } + + if (unexpected) { + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "Output %u: unexpected character '%c' after %s.\n", + output, str[0], elementName); + goto exit; + } else { + str++; + } + } + + retVal = str - element; + + exit: + return retVal; +} + +xXineramaScreenInfo * +VMWAREParseTopologyString(ScrnInfoPtr pScrn, + const char *topology, + unsigned int *retNumOutputs, + const char info[]) +{ + xXineramaScreenInfo *extents = NULL; + unsigned int numOutputs = 0; + const char *str = topology; + + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Parsing %s topology: Starting...\n", + info); + + do { + unsigned int x, y, width, height; + int i; + + i = VMWAREParseTopologyElement(pScrn, numOutputs, "width", str, "xX", TRUE, &width); + if (i == -1) { + goto error; + } + str += i; + + i = VMWAREParseTopologyElement(pScrn, numOutputs, "height", str, "+", TRUE, &height); + if (i == -1) { + goto error; + } + str += i; + + i= VMWAREParseTopologyElement(pScrn, numOutputs, "X offset", str, "+", TRUE, &x); + if (i == -1) { + goto error; + } + str += i; + + i = VMWAREParseTopologyElement(pScrn, numOutputs, "Y offset", str, ";", FALSE, &y); + if (i == -1) { + goto error; + } + str += i; + + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Output %u: %ux%u+%u+%u\n", + numOutputs, width, height, x, y); + + numOutputs++; + extents = realloc(extents, numOutputs * sizeof (xXineramaScreenInfo)); + extents[numOutputs - 1].x_org = x; + extents[numOutputs - 1].y_org = y; + extents[numOutputs - 1].width = width; + extents[numOutputs - 1].height = height; + } while (*str != 0); + + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Parsing %s topology: Succeeded.\n", + info); + goto exit; + + error: + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Parsing %s topology: Failed.\n", + info); + + free(extents); + extents = NULL; + numOutputs = 0; + + exit: + *retNumOutputs = numOutputs; + return extents; +} diff --git a/src/vmware_common.h b/src/vmware_common.h new file mode 100644 index 0000000..5629c10 --- /dev/null +++ b/src/vmware_common.h @@ -0,0 +1,43 @@ +/* + * Copyright 2011 VMWare, 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, 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 TUNGSTEN GRAPHICS 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. + * + * Author: Unknown at vmware + * Author: Thomas Hellstrom <thellstrom@vmware.com> + */ + +#ifndef _VMWARE_COMMON_H_ +#define _VMWARE_COMMON_H_ + +#include <X11/extensions/panoramiXproto.h> +#include <xf86.h> + +#include "compat-api.h" + +xXineramaScreenInfo * +VMWAREParseTopologyString(ScrnInfoPtr pScrn, + const char *topology, + unsigned int *retNumOutputs, + const char info[]); + +#endif diff --git a/src/vmwarectrl.c b/src/vmwarectrl.c new file mode 100644 index 0000000..d31bef6 --- /dev/null +++ b/src/vmwarectrl.c @@ -0,0 +1,624 @@ +/* + * Copyright 2006 by VMware, 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 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. + * + * Except as contained in this notice, the name of the copyright holder(s) + * and author(s) shall not be used in advertising or otherwise to promote + * the sale, use or other dealings in this Software without prior written + * authorization from the copyright holder(s) and author(s). + */ + +/* + * vmwarectrl.c -- + * + * The implementation of the VMWARE_CTRL protocol extension that + * allows X clients to communicate with the driver. + */ + + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "dixstruct.h" +#include "extnsionst.h" +#include "randrstr.h" +#include <X11/X.h> +#include <X11/extensions/panoramiXproto.h> + +#include "vmware.h" +#include "vmwarectrlproto.h" + +#ifndef HAVE_XORG_SERVER_1_5_0 +#include <xf86_ansic.h> +#include <xf86_libc.h> +#endif + +/* + *---------------------------------------------------------------------------- + * + * VMwareCtrlQueryVersion -- + * + * Implementation of QueryVersion command handler. Initialises and + * sends a reply. + * + * Results: + * Standard response codes. + * + * Side effects: + * Writes reply to client + * + *---------------------------------------------------------------------------- + */ + +static int +VMwareCtrlQueryVersion(ClientPtr client) +{ + xVMwareCtrlQueryVersionReply rep = { 0, }; + register int n; + + REQUEST_SIZE_MATCH(xVMwareCtrlQueryVersionReq); + + rep.type = X_Reply; + rep.length = 0; + rep.sequenceNumber = client->sequence; + rep.majorVersion = VMWARE_CTRL_MAJOR_VERSION; + rep.minorVersion = VMWARE_CTRL_MINOR_VERSION; + if (client->swapped) { + _swaps(&rep.sequenceNumber, n); + _swapl(&rep.length, n); + _swapl(&rep.majorVersion, n); + _swapl(&rep.minorVersion, n); + } + WriteToClient(client, sizeof(xVMwareCtrlQueryVersionReply), (char *)&rep); + + return client->noClientException; +} + + +/* + *---------------------------------------------------------------------------- + * + * VMwareCtrlDoSetRes -- + * + * Set the custom resolution into the mode list. + * + * This is done by alternately updating one of two dynamic modes. It is + * done this way because the server gets upset if you try to switch + * to a new resolution that has the same index as the current one. + * + * Results: + * TRUE on success, FALSE otherwise. + * + * Side effects: + * One dynamic mode will be updated if successful. + * + *---------------------------------------------------------------------------- + */ + +static Bool +VMwareCtrlDoSetRes(ScrnInfoPtr pScrn, + CARD32 x, + CARD32 y, + Bool resetXinerama) +{ + int modeIndex; + DisplayModePtr mode; + VMWAREPtr pVMWARE = VMWAREPTR(pScrn); + + if (pScrn && pScrn->modes) { + VmwareLog(("DoSetRes: %d %d\n", x, y)); + + if (resetXinerama) { + free(pVMWARE->xineramaNextState); + pVMWARE->xineramaNextState = NULL; + pVMWARE->xineramaNextNumOutputs = 0; + } + + /* + * Don't resize larger than possible but don't + * return an X Error either. + */ + if (x > pVMWARE->maxWidth || + y > pVMWARE->maxHeight) { + return TRUE; + } + + /* + * Find an dynamic mode which isn't current, and replace it with + * the requested mode. Normally this will cause us to alternate + * between two dynamic mode slots, but there are some important + * corner cases to consider. For example, adding the same mode + * multiple times, adding a mode that we never switch to, or + * adding a mode which is a duplicate of a built-in mode. The + * best way to handle all of these cases is to directly test the + * dynamic mode against the current mode pointer for this + * screen. + */ + + for (modeIndex = 0; modeIndex < NUM_DYN_MODES; modeIndex++) { + /* + * Initialise the dynamic mode if it hasn't been used before. + */ + if (!pVMWARE->dynModes[modeIndex]) { + pVMWARE->dynModes[modeIndex] = VMWAREAddDisplayMode(pScrn, "DynMode", 1, 1); + } + + mode = pVMWARE->dynModes[modeIndex]; + if (mode != pScrn->currentMode) { + break; + } + } + + mode->HDisplay = x; + mode->VDisplay = y; + + return TRUE; + } else { + return FALSE; + } +} + + +/* + *---------------------------------------------------------------------------- + * + * VMwareCtrlSetRes -- + * + * Implementation of SetRes command handler. Initialises and sends a + * reply. + * + * Results: + * Standard response codes. + * + * Side effects: + * Writes reply to client + * + *---------------------------------------------------------------------------- + */ + +static int +VMwareCtrlSetRes(ClientPtr client) +{ + REQUEST(xVMwareCtrlSetResReq); + xVMwareCtrlSetResReply rep = { 0, }; + ScrnInfoPtr pScrn; + ExtensionEntry *ext; + register int n; + + REQUEST_SIZE_MATCH(xVMwareCtrlSetResReq); + + if (!(ext = CheckExtension(VMWARE_CTRL_PROTOCOL_NAME))) { + return BadMatch; + } + + pScrn = ext->extPrivate; + if (pScrn->scrnIndex != stuff->screen) { + return BadMatch; + } + + if (!VMwareCtrlDoSetRes(pScrn, stuff->x, stuff->y, TRUE)) { + return BadValue; + } + + rep.type = X_Reply; + rep.length = (sizeof(xVMwareCtrlSetResReply) - sizeof(xGenericReply)) >> 2; + rep.sequenceNumber = client->sequence; + rep.screen = stuff->screen; + rep.x = stuff->x; + rep.y = stuff->y; + if (client->swapped) { + _swaps(&rep.sequenceNumber, n); + _swapl(&rep.length, n); + _swapl(&rep.screen, n); + _swapl(&rep.x, n); + _swapl(&rep.y, n); + } + WriteToClient(client, sizeof(xVMwareCtrlSetResReply), (char *)&rep); + + return client->noClientException; +} + + +/* + *---------------------------------------------------------------------------- + * + * VMwareCtrlDoSetTopology -- + * + * Set the custom topology and set a dynamic mode to the bounding box + * of the passed topology. If a topology is already pending, then do + * nothing but do not return failure. + * + * Results: + * TRUE on success, FALSE otherwise. + * + * Side effects: + * One dynamic mode and the pending xinerama state will be updated if + * successful. + * + *---------------------------------------------------------------------------- + */ + +static Bool +VMwareCtrlDoSetTopology(ScrnInfoPtr pScrn, + xXineramaScreenInfo *extents, + unsigned long number) +{ + VMWAREPtr pVMWARE = VMWAREPTR(pScrn); + + if (pVMWARE && pVMWARE->xinerama) { + VMWAREXineramaPtr xineramaState; + short maxX = 0; + short maxY = 0; + size_t i; + + if (pVMWARE->xineramaNextState) { + VmwareLog(("DoSetTopology: Aborting due to existing pending state\n")); + return TRUE; + } + + for (i = 0; i < number; i++) { + maxX = MAX(maxX, extents[i].x_org + extents[i].width); + maxY = MAX(maxY, extents[i].y_org + extents[i].height); + } + + VmwareLog(("DoSetTopology: %d %d\n", maxX, maxY)); + + xineramaState = (VMWAREXineramaPtr)calloc(number, sizeof(VMWAREXineramaRec)); + if (xineramaState) { + memcpy(xineramaState, extents, number * sizeof (VMWAREXineramaRec)); + + /* + * Make this the new pending Xinerama state. Normally we'll + * wait until the next mode switch in order to synchronously + * push this state out to X clients and the virtual hardware. + * + * However, if we're already in the right video mode, there + * will be no mode change. In this case, push it out + * immediately. + */ + free(pVMWARE->xineramaNextState); + pVMWARE->xineramaNextState = xineramaState; + pVMWARE->xineramaNextNumOutputs = number; + + if (maxX == pVMWARE->ModeReg.svga_reg_width && + maxY == pVMWARE->ModeReg.svga_reg_height) { + + /* + * The annoyance here is that when we reprogram the + * SVGA device's monitor topology registers, it may + * rearrange those monitors on the host's screen, but they + * will still have the old contents. This might be + * correct, but it isn't guaranteed to match what's on X's + * framebuffer at the moment. So we'll send a + * full-framebuffer update rect afterwards. + */ + + vmwareNextXineramaState(pVMWARE); +#ifdef HAVE_XORG_SERVER_1_2_0 + RRSendConfigNotify(pScrn->pScreen); +#endif + vmwareSendSVGACmdUpdateFullScreen(pVMWARE); + + return TRUE; + } else { + return VMwareCtrlDoSetRes(pScrn, maxX, maxY, FALSE); + } + + } else { + return FALSE; + } + } else { + return FALSE; + } +} + + +/* + *---------------------------------------------------------------------------- + * + * VMwareCtrlSetTopology -- + * + * Implementation of SetTopology command handler. Initialises and sends a + * reply. + * + * Results: + * Standard response codes. + * + * Side effects: + * Writes reply to client + * + *---------------------------------------------------------------------------- + */ + +static int +VMwareCtrlSetTopology(ClientPtr client) +{ + REQUEST(xVMwareCtrlSetTopologyReq); + xVMwareCtrlSetTopologyReply rep = { 0, }; + ScrnInfoPtr pScrn; + ExtensionEntry *ext; + register int n; + xXineramaScreenInfo *extents; + + REQUEST_AT_LEAST_SIZE(xVMwareCtrlSetTopologyReq); + + if (!(ext = CheckExtension(VMWARE_CTRL_PROTOCOL_NAME))) { + return BadMatch; + } + + pScrn = ext->extPrivate; + if (pScrn->scrnIndex != stuff->screen) { + return BadMatch; + } + + extents = (xXineramaScreenInfo *)(stuff + 1); + if (!VMwareCtrlDoSetTopology(pScrn, extents, stuff->number)) { + return BadValue; + } + + rep.type = X_Reply; + rep.length = (sizeof(xVMwareCtrlSetTopologyReply) - sizeof(xGenericReply)) >> 2; + rep.sequenceNumber = client->sequence; + rep.screen = stuff->screen; + if (client->swapped) { + _swaps(&rep.sequenceNumber, n); + _swapl(&rep.length, n); + _swapl(&rep.screen, n); + } + WriteToClient(client, sizeof(xVMwareCtrlSetTopologyReply), (char *)&rep); + + return client->noClientException; +} + + +/* + *---------------------------------------------------------------------------- + * + * VMwareCtrlDispatch -- + * + * Dispatcher for VMWARE_CTRL commands. Calls the correct handler for + * each command type. + * + * Results: + * Standard response codes. + * + * Side effects: + * Side effects of individual command handlers. + * + *---------------------------------------------------------------------------- + */ + +static int +VMwareCtrlDispatch(ClientPtr client) +{ + REQUEST(xReq); + + switch(stuff->data) { + case X_VMwareCtrlQueryVersion: + return VMwareCtrlQueryVersion(client); + case X_VMwareCtrlSetRes: + return VMwareCtrlSetRes(client); + case X_VMwareCtrlSetTopology: + return VMwareCtrlSetTopology(client); + } + return BadRequest; +} + + +/* + *---------------------------------------------------------------------------- + * + * SVMwareCtrlQueryVersion -- + * + * Wrapper for QueryVersion handler that handles input from other-endian + * clients. + * + * Results: + * Standard response codes. + * + * Side effects: + * Side effects of unswapped implementation. + * + *---------------------------------------------------------------------------- + */ + +static int +SVMwareCtrlQueryVersion(ClientPtr client) +{ + register int n; + + REQUEST(xVMwareCtrlQueryVersionReq); + REQUEST_SIZE_MATCH(xVMwareCtrlQueryVersionReq); + + _swaps(&stuff->length, n); + + return VMwareCtrlQueryVersion(client); +} + + +/* + *---------------------------------------------------------------------------- + * + * SVMwareCtrlSetRes -- + * + * Wrapper for SetRes handler that handles input from other-endian + * clients. + * + * Results: + * Standard response codes. + * + * Side effects: + * Side effects of unswapped implementation. + * + *---------------------------------------------------------------------------- + */ + +static int +SVMwareCtrlSetRes(ClientPtr client) +{ + register int n; + + REQUEST(xVMwareCtrlSetResReq); + REQUEST_SIZE_MATCH(xVMwareCtrlSetResReq); + + _swaps(&stuff->length, n); + _swapl(&stuff->screen, n); + _swapl(&stuff->x, n); + _swapl(&stuff->y, n); + + return VMwareCtrlSetRes(client); +} + + +/* + *---------------------------------------------------------------------------- + * + * SVMwareCtrlSetTopology -- + * + * Wrapper for SetTopology handler that handles input from other-endian + * clients. + * + * Results: + * Standard response codes. + * + * Side effects: + * Side effects of unswapped implementation. + * + *---------------------------------------------------------------------------- + */ + +static int +SVMwareCtrlSetTopology(ClientPtr client) +{ + register int n; + + REQUEST(xVMwareCtrlSetTopologyReq); + REQUEST_SIZE_MATCH(xVMwareCtrlSetTopologyReq); + + _swaps(&stuff->length, n); + _swapl(&stuff->screen, n); + _swapl(&stuff->number, n); + /* Each extent is a struct of shorts. */ + SwapRestS(stuff); + + return VMwareCtrlSetTopology(client); +} + + +/* + *---------------------------------------------------------------------------- + * + * SVMwareCtrlDispatch -- + * + * Wrapper for dispatcher that handles input from other-endian clients. + * + * Results: + * Standard response codes. + * + * Side effects: + * Side effects of individual command handlers. + * + *---------------------------------------------------------------------------- + */ + +static int +SVMwareCtrlDispatch(ClientPtr client) +{ + REQUEST(xReq); + + switch(stuff->data) { + case X_VMwareCtrlQueryVersion: + return SVMwareCtrlQueryVersion(client); + case X_VMwareCtrlSetRes: + return SVMwareCtrlSetRes(client); + case X_VMwareCtrlSetTopology: + return SVMwareCtrlSetTopology(client); + } + return BadRequest; +} + + +/* + *---------------------------------------------------------------------------- + * + * VMwareCtrlResetProc -- + * + * Cleanup handler called when the extension is removed. + * + * Results: + * None + * + * Side effects: + * None + * + *---------------------------------------------------------------------------- + */ + +static void +VMwareCtrlResetProc(ExtensionEntry* extEntry) +{ + /* Currently, no cleanup is necessary. */ +} + + +/* + *---------------------------------------------------------------------------- + * + * VMwareCtrl_ExitInit -- + * + * Initialiser for the VMWARE_CTRL protocol extension. + * + * Results: + * None. + * + * Side effects: + * Protocol extension will be registered if successful. + * + *---------------------------------------------------------------------------- + */ + +void +VMwareCtrl_ExtInit(ScrnInfoPtr pScrn) +{ + ExtensionEntry *myext; + + if (!(myext = CheckExtension(VMWARE_CTRL_PROTOCOL_NAME))) { + if (!(myext = AddExtension(VMWARE_CTRL_PROTOCOL_NAME, 0, 0, + VMwareCtrlDispatch, + SVMwareCtrlDispatch, + VMwareCtrlResetProc, + StandardMinorOpcode))) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "Failed to add VMWARE_CTRL extension\n"); + return; + } + + /* + * For now, only support one screen as that's all the virtual + * hardware supports. + */ + myext->extPrivate = pScrn; + + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "Initialized VMWARE_CTRL extension version %d.%d\n", + VMWARE_CTRL_MAJOR_VERSION, VMWARE_CTRL_MINOR_VERSION); + } +} diff --git a/src/vmwarectrl.h b/src/vmwarectrl.h new file mode 100644 index 0000000..a671ae1 --- /dev/null +++ b/src/vmwarectrl.h @@ -0,0 +1,48 @@ +/* + * Copyright 2006 by VMware, 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 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. + * + * Except as contained in this notice, the name of the copyright holder(s) + * and author(s) shall not be used in advertising or otherwise to promote + * the sale, use or other dealings in this Software without prior written + * authorization from the copyright holder(s) and author(s). + */ + +/* + * vmwarectrl.h -- + * + * The definitions used by the VMWARE_CTRL protocol extension that + * allows X clients to communicate with the driver. + */ + + +#ifndef _VMWARE_CTRL_H_ +#define _VMWARE_CTRL_H_ + +#define VMWARE_CTRL_PROTOCOL_NAME "VMWARE_CTRL" + +#define VMWARE_CTRL_MAJOR_VERSION 0 +#define VMWARE_CTRL_MINOR_VERSION 2 + +#define X_VMwareCtrlQueryVersion 0 +#define X_VMwareCtrlSetRes 1 +#define X_VMwareCtrlSetTopology 2 + +#endif /* _VMWARE_CTRL_H_ */ diff --git a/src/vmwarectrlproto.h b/src/vmwarectrlproto.h new file mode 100644 index 0000000..76f157f --- /dev/null +++ b/src/vmwarectrlproto.h @@ -0,0 +1,122 @@ +/* + * Copyright 2006 by VMware, 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 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. + * + * Except as contained in this notice, the name of the copyright holder(s) + * and author(s) shall not be used in advertising or otherwise to promote + * the sale, use or other dealings in this Software without prior written + * authorization from the copyright holder(s) and author(s). + */ + +/* + * vmwarectrlproto.h -- + * + * The description of the VMWARE_CTRL protocol extension that + * allows X clients to communicate with the driver. + */ + +#ifndef _VMWARE_CTRL_PROTO_H_ +#define _VMWARE_CTRL_PROTO_H_ + + +#include <X11/X.h> +#include "vmwarectrl.h" + + +/* + * Requests and Replies + */ + +/* Version 0.1 definitions. */ + +typedef struct { + CARD8 reqType; /* always X_VMwareCtrlReqCode */ + CARD8 VMwareCtrlReqType; /* always X_VMwareCtrlQueryVersion */ + CARD16 length B16; + CARD32 majorVersion B32; + CARD32 minorVersion B32; +} xVMwareCtrlQueryVersionReq; +#define sz_xVMwareCtrlQueryVersionReq 12 + +typedef struct { + BYTE type; /* X_Reply */ + BYTE pad1; + CARD16 sequenceNumber B16; + CARD32 length B32; + CARD32 majorVersion B32; + CARD32 minorVersion B32; + CARD32 pad2 B32; + CARD32 pad3 B32; + CARD32 pad4 B32; + CARD32 pad5 B32; +} xVMwareCtrlQueryVersionReply; +#define sz_xVMwareCtrlQueryVersionReply 32 + +typedef struct { + CARD8 reqType; /* always X_VMwareCtrlReqCode */ + CARD8 VMwareCtrlReqType; /* always X_VMwareCtrlSetRes */ + CARD16 length B16; + CARD32 screen B32; + CARD32 x B32; + CARD32 y B32; +} xVMwareCtrlSetResReq; +#define sz_xVMwareCtrlSetResReq 16 + +typedef struct { + BYTE type; /* X_Reply */ + BYTE pad1; + CARD16 sequenceNumber B16; + CARD32 length B32; + CARD32 screen B32; + CARD32 x B32; + CARD32 y B32; + CARD32 pad2 B32; + CARD32 pad3 B32; + CARD32 pad4 B32; +} xVMwareCtrlSetResReply; +#define sz_xVMwareCtrlSetResReply 32 + +/* Version 0.2 definitions. */ + +typedef struct { + CARD8 reqType; /* always X_VMwareCtrlReqCode */ + CARD8 VMwareCtrlReqType; /* always X_VMwareCtrlSetTopology */ + CARD16 length B16; + CARD32 screen B32; + CARD32 number B32; + CARD32 pad1 B32; +} xVMwareCtrlSetTopologyReq; +#define sz_xVMwareCtrlSetTopologyReq 16 + +typedef struct { + BYTE type; /* X_Reply */ + BYTE pad1; + CARD16 sequenceNumber B16; + CARD32 length B32; + CARD32 screen B32; + CARD32 pad2 B32; + CARD32 pad3 B32; + CARD32 pad4 B32; + CARD32 pad5 B32; + CARD32 pad6 B32; +} xVMwareCtrlSetTopologyReply; +#define sz_xVMwareCtrlSetTopologyReply 32 + +#endif /* _VMWARE_CTRL_PROTO_H_ */ diff --git a/src/vmwarecurs.c b/src/vmwarecurs.c new file mode 100644 index 0000000..93dacc0 --- /dev/null +++ b/src/vmwarecurs.c @@ -0,0 +1,487 @@ +/* ********************************************************** + * Copyright (C) 1998-2001 VMware, Inc. + * All Rights Reserved + * **********************************************************/ +#ifdef VMX86_DEVEL +char rcsId_vmwarecurs[] = + "Id: vmwarecurs.c,v 1.5 2001/01/30 23:33:02 bennett Exp $"; +#endif + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "vmware.h" +#include "vmware_common.h" +#include "bits2pixels.h" + +static void VMWAREGetImage(DrawablePtr src, int x, int y, int w, int h, + unsigned int format, unsigned long planeMask, + char *pBinImage); +static void VMWARECopyWindow(WindowPtr pWin, DDXPointRec ptOldOrg, + RegionPtr prgnSrc); + +#ifdef RENDER +static void VMWAREComposite(CARD8 op, PicturePtr pSrc, PicturePtr pMask, + PicturePtr pDst, INT16 xSrc, INT16 ySrc, + INT16 xMask, INT16 yMask, INT16 xDst, INT16 yDst, + CARD16 width, CARD16 height); +#endif /* RENDER */ + +static void +RedefineCursor(VMWAREPtr pVMWARE) +{ + int i; + + VmwareLog(("RedefineCursor\n")); + + pVMWARE->cursorDefined = FALSE; + + /* Define cursor */ + vmwareWriteWordToFIFO(pVMWARE, SVGA_CMD_DEFINE_CURSOR); + vmwareWriteWordToFIFO(pVMWARE, MOUSE_ID); + vmwareWriteWordToFIFO(pVMWARE, pVMWARE->hwcur.hotX); + vmwareWriteWordToFIFO(pVMWARE, pVMWARE->hwcur.hotY); + vmwareWriteWordToFIFO(pVMWARE, pVMWARE->CursorInfoRec->MaxWidth); + vmwareWriteWordToFIFO(pVMWARE, pVMWARE->CursorInfoRec->MaxHeight); + vmwareWriteWordToFIFO(pVMWARE, 1); + vmwareWriteWordToFIFO(pVMWARE, pVMWARE->bitsPerPixel); + + /* + * Since we have AND and XOR masks rather than 'source' and 'mask', + * color expand 'mask' with all zero as its foreground and all one as + * its background. This makes 'image & 0 ^ 'source' = source. We + * arange for 'image' & 1 ^ 'source' = 'image' below when we clip + * 'source' below. + */ + vmwareRaster_BitsToPixels((uint8 *) pVMWARE->hwcur.mask, + SVGA_BITMAP_INCREMENT(pVMWARE->CursorInfoRec->MaxWidth), + (uint8 *) pVMWARE->hwcur.maskPixmap, + SVGA_PIXMAP_INCREMENT(pVMWARE->CursorInfoRec->MaxWidth, + pVMWARE->bitsPerPixel), + pVMWARE->bitsPerPixel / 8, + pVMWARE->CursorInfoRec->MaxWidth, + pVMWARE->CursorInfoRec->MaxHeight, 0, ~0); + for (i = 0; i < SVGA_BITMAP_SIZE(pVMWARE->CursorInfoRec->MaxWidth, + pVMWARE->CursorInfoRec->MaxHeight); i++) { + vmwareWriteWordToFIFO(pVMWARE, ~pVMWARE->hwcur.mask[i]); + } + + vmwareRaster_BitsToPixels((uint8 *) pVMWARE->hwcur.source, + SVGA_BITMAP_INCREMENT(pVMWARE->CursorInfoRec->MaxWidth), + (uint8 *) pVMWARE->hwcur.sourcePixmap, + SVGA_PIXMAP_INCREMENT(pVMWARE->CursorInfoRec->MaxWidth, + pVMWARE->bitsPerPixel), + pVMWARE->bitsPerPixel / 8, + pVMWARE->CursorInfoRec->MaxWidth, + pVMWARE->CursorInfoRec->MaxHeight, + pVMWARE->hwcur.fg, pVMWARE->hwcur.bg); + /* + * As pointed out above, we need to clip the expanded 'source' against + * the expanded 'mask' since we actually have AND and XOR masks in the + * virtual hardware. Effectively, 'source' becomes a three color fg/bg/0 + * pixmap that XORs appropriately. + */ + for (i = 0; i < SVGA_PIXMAP_SIZE(pVMWARE->CursorInfoRec->MaxWidth, + pVMWARE->CursorInfoRec->MaxHeight, + pVMWARE->bitsPerPixel); i++) { + pVMWARE->hwcur.sourcePixmap[i] &= ~pVMWARE->hwcur.maskPixmap[i]; + vmwareWriteWordToFIFO(pVMWARE, pVMWARE->hwcur.sourcePixmap[i]); + } + + /* Sync the FIFO, so that the definition preceeds any use of the cursor */ + vmwareWaitForFB(pVMWARE); + pVMWARE->cursorDefined = TRUE; +} + +static void +vmwareSetCursorColors(ScrnInfoPtr pScrn, int bg, int fg) +{ + VMWAREPtr pVMWARE = VMWAREPTR(pScrn); + TRACEPOINT + + if (pVMWARE->hwcur.fg != fg || pVMWARE->hwcur.bg != bg) { + VmwareLog(("SetCursorColors(0x%08x, 0x%08x)\n", bg, fg)); + pVMWARE->hwcur.fg = fg; + pVMWARE->hwcur.bg = bg; + RedefineCursor(pVMWARE); + } +} + +static Bool +vmwareUseHWCursor(ScreenPtr pScreen, CursorPtr pCurs) +{ + ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen); + VMWAREPtr pVMWARE = VMWAREPTR(pScrn); + VmwareLog(("UseHWCursor new cursor %p refcnt %i old cursor %p refcnt %i\n", + pCurs, pCurs->refcnt, pVMWARE->oldCurs, pVMWARE->oldCurs ? pVMWARE->oldCurs->refcnt : 0)); + pCurs->refcnt++; + if (pVMWARE->oldCurs) + FreeCursor(pVMWARE->oldCurs, None); + pVMWARE->oldCurs = pCurs; + + pVMWARE->hwcur.hotX = pCurs->bits->xhot; + pVMWARE->hwcur.hotY = pCurs->bits->yhot; + + return pScrn->bitsPerPixel > 8; +} + +static void +vmwareLoadCursorImage(ScrnInfoPtr pScrn, unsigned char *src ) +{ + VMWAREPtr pVMWARE = VMWAREPTR(pScrn); + const int imageSize = SVGA_BITMAP_SIZE(pVMWARE->CursorInfoRec->MaxWidth, + pVMWARE->CursorInfoRec->MaxHeight); + TRACEPOINT + + memcpy(pVMWARE->hwcur.source, src, imageSize * sizeof(uint32)); + memcpy(pVMWARE->hwcur.mask, + src + imageSize * sizeof(uint32), imageSize * sizeof(uint32)); + RedefineCursor(pVMWARE); +} + +#ifdef ARGB_CURSOR +#include "cursorstr.h" + +static Bool +vmwareUseHWCursorARGB(ScreenPtr pScreen, CursorPtr pCurs) +{ + ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen); + VMWAREPtr pVMWARE = VMWAREPTR(pScrn); + VmwareLog(("UseHWCursorARGB new cursor %p refcnt %i old cursor %p refcnt %i\n", + pCurs, pCurs->refcnt, pVMWARE->oldCurs, pVMWARE->oldCurs ? pVMWARE->oldCurs->refcnt : 0)); + pCurs->refcnt++; + if (pVMWARE->oldCurs) + FreeCursor(pVMWARE->oldCurs, None); + pVMWARE->oldCurs = pCurs; + + return pCurs->bits->height <= MAX_CURS && + pCurs->bits->width <= MAX_CURS && + pScrn->bitsPerPixel > 8; +} + +static void +vmwareLoadCursorARGB(ScrnInfoPtr pScrn, CursorPtr pCurs) +{ + VMWAREPtr pVMWARE = VMWAREPTR(pScrn); + CARD32 width = pCurs->bits->width; + CARD32 height = pCurs->bits->height; + CARD32* image = pCurs->bits->argb; + CARD32* imageEnd = image + (width * height); + + pVMWARE->cursorDefined = FALSE; + + pVMWARE->hwcur.hotX = pCurs->bits->xhot; + pVMWARE->hwcur.hotY = pCurs->bits->yhot; + + vmwareWriteWordToFIFO(pVMWARE, SVGA_CMD_DEFINE_ALPHA_CURSOR); + vmwareWriteWordToFIFO(pVMWARE, MOUSE_ID); + vmwareWriteWordToFIFO(pVMWARE, pCurs->bits->xhot); + vmwareWriteWordToFIFO(pVMWARE, pCurs->bits->yhot); + vmwareWriteWordToFIFO(pVMWARE, width); + vmwareWriteWordToFIFO(pVMWARE, height); + + while (image != imageEnd) { + vmwareWriteWordToFIFO(pVMWARE, *image++); + } + + vmwareWaitForFB(pVMWARE); + pVMWARE->cursorDefined = TRUE; +} +#endif + +void +vmwareWriteCursorRegs(VMWAREPtr pVMWARE, Bool visible, Bool force) +{ + int enableVal; + + vmwareWriteReg(pVMWARE, SVGA_REG_CURSOR_ID, MOUSE_ID); + if (visible) { + vmwareWriteReg(pVMWARE, SVGA_REG_CURSOR_X, + pVMWARE->hwcur.x + pVMWARE->hwcur.hotX); + vmwareWriteReg(pVMWARE, SVGA_REG_CURSOR_Y, + pVMWARE->hwcur.y + pVMWARE->hwcur.hotY); + } + + if (force) { + enableVal = visible ? SVGA_CURSOR_ON_SHOW : SVGA_CURSOR_ON_HIDE; + } else { + enableVal = visible ? pVMWARE->cursorRestoreToFB : + pVMWARE->cursorRemoveFromFB; + } + vmwareWriteReg(pVMWARE, SVGA_REG_CURSOR_ON, enableVal); +} + +/* disabled by default to reduce spew in DEBUG_LOGGING mode. */ +/* #define DEBUG_LOG_MOUSE_HIDE_SHOW */ + +static void +vmwareShowCursor(ScrnInfoPtr pScrn) +{ + VMWAREPtr pVMWARE = VMWAREPTR(pScrn); +#ifdef DEBUG_LOG_MOUSE_HIDE_SHOW + VmwareLog(("Show: %d %d %d\n", pVMWARE->cursorSema, pVMWARE->cursorDefined, + pVMWARE->cursorShouldBeHidden)); +#endif + pVMWARE->cursorShouldBeHidden = FALSE; + if (pVMWARE->cursorSema == 0 && pVMWARE->cursorDefined) { + vmwareWriteCursorRegs(pVMWARE, TRUE, TRUE); + } +} + +static void +vmwareHideCursor(ScrnInfoPtr pScrn) +{ + VMWAREPtr pVMWARE = VMWAREPTR(pScrn); +#ifdef DEBUG_LOG_MOUSE_HIDE_SHOW + VmwareLog(("Hide: %d %d %d\n", pVMWARE->cursorSema, pVMWARE->cursorDefined, + pVMWARE->cursorShouldBeHidden)); +#endif + if (pVMWARE->cursorDefined) { + vmwareWriteCursorRegs(pVMWARE, FALSE, TRUE); + } + pVMWARE->cursorShouldBeHidden = TRUE; +} + +/* disabled by default to reduce spew in DEBUG_LOGGING mode. */ +/* #define DEBUG_LOG_MOUSE_MOVE */ + +static void +vmwareSetCursorPosition(ScrnInfoPtr pScrn, int x, int y) +{ + VMWAREPtr pVMWARE = VMWAREPTR(pScrn); +#ifdef DEBUG_LOG_MOUSE_MOVE + VmwareLog(("Move: %d %d %d\n", pVMWARE->cursorSema, pVMWARE->cursorDefined, + pVMWARE->cursorShouldBeHidden)); +#endif + /* + * We're bad people. We have no concept of a frame (VMWAREAdjustFrame() + * is a NOP). The hwcursor code expects us to be frame aware though, so + * we have to do this. I'm open to suggestions. I tried not even + * hooking AdjustFrame and it didn't help. + */ + pVMWARE->hwcur.x = x + pScrn->frameX0; + pVMWARE->hwcur.y = y + pScrn->frameY0; + pVMWARE->hwcur.box.x1 = pVMWARE->hwcur.x; + pVMWARE->hwcur.box.x2 = pVMWARE->hwcur.x + pVMWARE->CursorInfoRec->MaxWidth; + pVMWARE->hwcur.box.y1 = pVMWARE->hwcur.y; + pVMWARE->hwcur.box.y2 = pVMWARE->hwcur.y + pVMWARE->CursorInfoRec->MaxHeight; + + vmwareShowCursor(pScrn); +} + +void +vmwareCursorModeInit(ScrnInfoPtr pScrn, DisplayModePtr mode) +{ + VMWAREPtr pVMWARE = VMWAREPTR(pScrn); + + if (pVMWARE->cursorDefined) { + vmwareWriteCursorRegs(pVMWARE, !pVMWARE->cursorShouldBeHidden, TRUE); + } +} + +Bool +vmwareCursorInit(ScreenPtr pScreen) +{ + xf86CursorInfoPtr infoPtr; + VMWAREPtr pVMWARE = VMWAREPTR(xf86ScreenToScrn(pScreen)); + Bool ret; + + TRACEPOINT + + /* Require cursor bypass for hwcursor. Ignore deprecated FIFO hwcursor */ + if (!(pVMWARE->vmwareCapability & SVGA_CAP_CURSOR_BYPASS)) { + return FALSE; + } + + infoPtr = xf86CreateCursorInfoRec(); + if (!infoPtr) + return FALSE; + + pVMWARE->CursorInfoRec = infoPtr; + pVMWARE->oldCurs = NULL; + + infoPtr->MaxWidth = MAX_CURS; + infoPtr->MaxHeight = MAX_CURS; + infoPtr->Flags = HARDWARE_CURSOR_BIT_ORDER_MSBFIRST | + HARDWARE_CURSOR_UPDATE_UNHIDDEN | + HARDWARE_CURSOR_SOURCE_MASK_NOT_INTERLEAVED; + infoPtr->SetCursorColors = vmwareSetCursorColors; + infoPtr->SetCursorPosition = vmwareSetCursorPosition; + infoPtr->LoadCursorImage = vmwareLoadCursorImage; + infoPtr->HideCursor = vmwareHideCursor; + infoPtr->ShowCursor = vmwareShowCursor; + infoPtr->UseHWCursor = vmwareUseHWCursor; + +#ifdef ARGB_CURSOR + if (pVMWARE->vmwareCapability & SVGA_CAP_ALPHA_CURSOR) { + infoPtr->UseHWCursorARGB = vmwareUseHWCursorARGB; + infoPtr->LoadCursorARGB = vmwareLoadCursorARGB; + } +#endif + + ret = xf86InitCursor(pScreen, infoPtr); + if (!ret) { + xf86DestroyCursorInfoRec(infoPtr); + pVMWARE->CursorInfoRec = NULL; + } + return ret; +} + +void +vmwareCursorCloseScreen(ScreenPtr pScreen) +{ + ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen); + VMWAREPtr pVMWARE = VMWAREPTR(pScrn); +#ifdef RENDER + PictureScreenPtr ps = GetPictureScreenIfSet(pScreen); +#endif + + pScreen->GetImage = pVMWARE->ScrnFuncs.GetImage; + pScreen->CopyWindow = pVMWARE->ScrnFuncs.CopyWindow; +#ifdef RENDER + if (ps) { + ps->Composite = pVMWARE->Composite; + } +#endif /* RENDER */ + + vmwareHideCursor(pScrn); + if (pVMWARE->oldCurs) + FreeCursor(pVMWARE->oldCurs, None); + pVMWARE->oldCurs = NULL; + xf86DestroyCursorInfoRec(pVMWARE->CursorInfoRec); +} + +/*** Wrap functions that read from the framebuffer ***/ + +void +vmwareCursorHookWrappers(ScreenPtr pScreen) +{ + VMWAREPtr pVMWARE = VMWAREPTR(xf86ScreenToScrn(pScreen)); +#ifdef RENDER + PictureScreenPtr ps = GetPictureScreenIfSet(pScreen); +#endif + + TRACEPOINT + + pVMWARE->ScrnFuncs.GetImage = pScreen->GetImage; + pVMWARE->ScrnFuncs.CopyWindow = pScreen->CopyWindow; + pScreen->GetImage = VMWAREGetImage; + pScreen->CopyWindow = VMWARECopyWindow; + +#ifdef RENDER + if (ps) { + pVMWARE->Composite = ps->Composite; + ps->Composite = VMWAREComposite; + } +#endif /* RENDER */ + +} + +static void +VMWAREGetImage(DrawablePtr src, int x, int y, int w, int h, + unsigned int format, unsigned long planeMask, char *pBinImage) +{ + ScreenPtr pScreen = src->pScreen; + VMWAREPtr pVMWARE = VMWAREPTR(xf86ScreenToScrn(src->pScreen)); + BoxRec box; + Bool hidden = FALSE; + + VmwareLog(("VMWAREGetImage(%p, %d, %d, %d, %d, %d, %d, %p)\n", + src, x, y, w, h, format, planeMask, pBinImage)); + + box.x1 = src->x + x; + box.y1 = src->y + y; + box.x2 = box.x1 + w; + box.y2 = box.y1 + h; + + if (BOX_INTERSECT(box, pVMWARE->hwcur.box)) { + PRE_OP_HIDE_CURSOR(); + hidden = TRUE; + } + + pScreen->GetImage = pVMWARE->ScrnFuncs.GetImage; + (*pScreen->GetImage)(src, x, y, w, h, format, planeMask, pBinImage); + pScreen->GetImage = VMWAREGetImage; + + if (hidden) { + POST_OP_SHOW_CURSOR(); + } +} + +static void +VMWARECopyWindow(WindowPtr pWin, DDXPointRec ptOldOrg, RegionPtr prgnSrc) +{ + ScreenPtr pScreen = pWin->drawable.pScreen; + VMWAREPtr pVMWARE = VMWAREPTR(xf86ScreenToScrn(pWin->drawable.pScreen)); + BoxPtr pBB; + Bool hidden = FALSE; + + /* + * We only worry about the source region here, since shadowfb will + * take care of the destination region. + */ + pBB = REGION_EXTENTS(pWin->drawable.pScreen, prgnSrc); + + VmwareLog(("VMWARECopyWindow(%p, (%d, %d), (%d, %d - %d, %d)\n", + pWin, ptOldOrg.x, ptOldOrg.y, + pBB->x1, pBB->y1, pBB->x2, pBB->y2)); + + if (BOX_INTERSECT(*pBB, pVMWARE->hwcur.box)) { + PRE_OP_HIDE_CURSOR(); + hidden = TRUE; + } + + pScreen->CopyWindow = pVMWARE->ScrnFuncs.CopyWindow; + (*pScreen->CopyWindow)(pWin, ptOldOrg, prgnSrc); + pScreen->CopyWindow = VMWARECopyWindow; + + if (hidden) { + POST_OP_SHOW_CURSOR(); + } +} + +#ifdef RENDER +static void +VMWAREComposite(CARD8 op, PicturePtr pSrc, PicturePtr pMask, + PicturePtr pDst, INT16 xSrc, INT16 ySrc, + INT16 xMask, INT16 yMask, INT16 xDst, INT16 yDst, + CARD16 width, CARD16 height) +{ + ScreenPtr pScreen = pDst->pDrawable->pScreen; + VMWAREPtr pVMWARE = VMWAREPTR(xf86ScreenToScrn(pScreen)); + PictureScreenPtr ps = GetPictureScreen(pScreen); + BoxRec box; + Bool hidden = FALSE; + + if (pSrc->pDrawable) { + VmwareLog(("VMWAREComposite op = %d, pSrc = %p, pMask = %p, pDst = %p," + " src = (%d, %d), mask = (%d, %d), dst = (%d, %d), w = %d," + " h = %d\n", op, pSrc, pMask, pDst, xSrc, ySrc, xMask, yMask, + xDst, yDst, width, height)); + + /* + * We only worry about the source region here, since shadowfb or XAA + * will take care of the destination region. + */ + box.x1 = pSrc->pDrawable->x + xSrc; + box.y1 = pSrc->pDrawable->y + ySrc; + box.x2 = box.x1 + width; + box.y2 = box.y1 + height; + + if (BOX_INTERSECT(box, pVMWARE->hwcur.box)) { + PRE_OP_HIDE_CURSOR(); + hidden = TRUE; + } + } + + ps->Composite = pVMWARE->Composite; + (*ps->Composite)(op, pSrc, pMask, pDst, xSrc, ySrc, + xMask, yMask, xDst, yDst, width, height); + ps->Composite = VMWAREComposite; + + if (hidden) { + POST_OP_SHOW_CURSOR(); + } +} +#endif /* RENDER */ diff --git a/src/vmwaremodes.c b/src/vmwaremodes.c new file mode 100644 index 0000000..2965dca --- /dev/null +++ b/src/vmwaremodes.c @@ -0,0 +1,163 @@ +/* + * Copyright 2007 by VMware, 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 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. + * + * Except as contained in this notice, the name of the copyright holder(s) + * and author(s) shall not be used in advertising or otherwise to promote + * the sale, use or other dealings in this Software without prior written + * authorization from the copyright holder(s) and author(s). + */ + +/* + * vmwaremodes.c -- + * + * Provide additional modes for the driver. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif +#include "xf86.h" +#ifdef HAVE_XORG_SERVER_1_2_0 +#include <xf86Modes.h> +#endif +#include "vm_basic_types.h" +#include "vmware.h" + +#ifndef M_T_DRIVER +# define M_T_DRIVER 0x40 /* Supplied by the driver (EDID, etc) */ +#endif + +#define MODEPREFIX NULL, NULL, NULL, 0, M_T_DRIVER +#define MODESUFFIX 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,FALSE,FALSE,0,NULL,0,0.0,0.0 + +#define VMW_DEFLT_MODE_NAME "vmwlegacy-default-%dx%d" + +/* + *----------------------------------------------------------------------------- + * + * vmwareAddDefaultMode -- + * + * Add a default mode with the current screen dimensions. + * + * Results: + * The default mode. + * + * Side effects: + * None. + * + *----------------------------------------------------------------------------- + */ + +void +vmwareAddDefaultMode(ScrnInfoPtr pScrn, uint32 dwidth, uint32 dheight) +{ + DisplayModePtr *monitorModes = &pScrn->monitor->Modes; + DisplayModePtr modes = NULL; + + if (monitorModes == NULL || *monitorModes == NULL) { + goto out_err; + } + +#ifdef HAVE_XORG_SERVER_1_2_0 + if (dwidth && dheight) { + MonPtr monitor = pScrn->monitor; + DisplayModePtr mode = NULL; + DisplayModeRec dynamic = + { MODEPREFIX, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, MODESUFFIX }; + unsigned dispModeCount = 0; + char **dispModeList; + char *dynModeName; + char name[80]; + VMWAREPtr pVMWARE = VMWAREPTR(pScrn); + + /* First, add the default mode name to the display mode + * requests. + */ + + snprintf(name, sizeof(name), VMW_DEFLT_MODE_NAME, dwidth, dheight); + + dynModeName = xnfstrdup(name); + if (!dynModeName || !pScrn->display) + goto out_err; + + if (pScrn->display->modes) { + dispModeList = pScrn->display->modes; + while(*dispModeList) + dispModeList++; + dispModeCount = dispModeList - pScrn->display->modes; + } + + dispModeList = xnfcalloc(dispModeCount + 2, sizeof(*dispModeList)); + if (!dispModeList) + goto out_err; + + memcpy(dispModeList, pScrn->display->modes, + dispModeCount * sizeof(*dispModeList)); + dispModeList[dispModeCount] = dynModeName; + pScrn->display->modes = dispModeList; + + /* Then, add the default mode itself. + */ + + dynamic.name = name; + dynamic.HDisplay = dwidth; + dynamic.HSyncStart = dynamic.HDisplay + 1; + dynamic.HSyncEnd = dynamic.HSyncStart + 1; + dynamic.HTotal = dynamic.HSyncEnd * 5 / 4; + dynamic.VDisplay = dheight; + dynamic.VSyncStart = dynamic.VDisplay + 1; + dynamic.VSyncEnd = dynamic.VSyncStart + 1; + dynamic.VTotal = dynamic.VSyncEnd + 1; + if (monitor->nVrefresh > 0) + dynamic.VRefresh = monitor->vrefresh[0].lo; + else + dynamic.VRefresh = 60; + dynamic.Clock = dynamic.VRefresh * dynamic.VTotal * + dynamic.HTotal / 1000; + mode = xf86DuplicateMode(&dynamic); + modes = xf86ModesAdd(modes, mode); + + if (dispModeCount == 0) { + + /* + * Set up a large virtual size, so that we allow also + * setting modes larger than the initial mode. + * + * We might also want to consider the case where + * dispModeCount != 0, but the requested display modes + * are not available. This is sufficient for now. + */ + + if (pScrn->display->virtualX == 0) + pScrn->display->virtualX = pVMWARE->maxWidth; + if (pScrn->display->virtualY == 0) + pScrn->display->virtualY = pVMWARE->maxHeight; + } + } + + *monitorModes = xf86ModesAdd(*monitorModes, modes); +#else + (void) modes; +#endif + return; + out_err: + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Failed to add default mode."); +} diff --git a/src/vmwarevideo.c b/src/vmwarevideo.c new file mode 100644 index 0000000..745c71f --- /dev/null +++ b/src/vmwarevideo.c @@ -0,0 +1,1352 @@ +/* + * Copyright 2007 by VMware, 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 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. + * + * Except as contained in this notice, the name of the copyright holder(s) + * and author(s) shall not be used in advertising or otherwise to promote + * the sale, use or other dealings in this Software without prior written + * authorization from the copyright holder(s) and author(s). + */ + +/* + * vmwarevideo.c -- + * + * Xv extension support. + * See http://www.xfree86.org/current/DESIGN16.html + * + */ + + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "vmware.h" +#include "vmware_common.h" +#include "xf86xv.h" +#include "fourcc.h" +#include "svga_escape.h" +#include "svga_overlay.h" + +#include <X11/extensions/Xv.h> + +#ifndef HAVE_XORG_SERVER_1_5_0 +#include <xf86_ansic.h> +#include <xf86_libc.h> +#endif + + +#define HAVE_FILLKEYHELPERDRAWABLE \ + ((GET_ABI_MAJOR(ABI_VIDEODRV_VERSION) >= 2) || \ + ((GET_ABI_MAJOR(ABI_VIDEODRV_VERSION) == 1) && \ + (GET_ABI_MINOR(ABI_VIDEODRV_VERSION) >= 2))) + +#define MAKE_ATOM(a) MakeAtom(a, sizeof(a) - 1, TRUE) + +/* + * Used to pack structs + */ +#define PACKED __attribute__((__packed__)) + +/* + * Number of videos that can be played simultaneously + */ +#define VMWARE_VID_NUM_PORTS 1 + +/* + * Using a dark shade as the default colorKey + */ +#define VMWARE_VIDEO_COLORKEY 0x100701 + +/* + * Maximum dimensions + */ +#define VMWARE_VID_MAX_WIDTH 2048 +#define VMWARE_VID_MAX_HEIGHT 2048 + +#define VMWARE_VID_NUM_ENCODINGS 1 +static XF86VideoEncodingRec vmwareVideoEncodings[] = +{ + { + 0, + "XV_IMAGE", + VMWARE_VID_MAX_WIDTH, VMWARE_VID_MAX_HEIGHT, + {1, 1} + } +}; + +#define VMWARE_VID_NUM_FORMATS 2 +static XF86VideoFormatRec vmwareVideoFormats[] = +{ + { 16, TrueColor}, + { 24, TrueColor} +}; + +#define VMWARE_VID_NUM_IMAGES 3 +static XF86ImageRec vmwareVideoImages[] = +{ + XVIMAGE_YV12, + XVIMAGE_YUY2, + XVIMAGE_UYVY +}; + +#define VMWARE_VID_NUM_ATTRIBUTES 2 +static XF86AttributeRec vmwareVideoAttributes[] = +{ + { + XvGettable | XvSettable, + 0x000000, + 0xffffff, + "XV_COLORKEY" + }, + { + XvGettable | XvSettable, + 0, + 1, + "XV_AUTOPAINT_COLORKEY" + } +}; + +/* + * Video frames are stored in a circular list of buffers. + */ +#define VMWARE_VID_NUM_BUFFERS 1 +/* + * Defines the structure used to hold and pass video data to the host + */ +typedef struct { + uint32 dataOffset; + pointer data; +} VMWAREVideoBuffer; + +typedef struct { + uint32 size; + uint32 offset; +} VMWAREOffscreenRec, *VMWAREOffscreenPtr; + +/* + * Trivial offscreen manager that allocates memory from the + * bottom of the VRAM. + */ +static VMWAREOffscreenRec offscreenMgr; + +/* + * structs that reside in fmt_priv. + */ +typedef struct { + int pitches[3]; + int offsets[3]; +} VMWAREVideoFmtData; + +/* + * Structure representing a specific video stream. + */ +struct VMWAREVideoRec { + uint32 streamId; + /* + * Function prototype same as XvPutImage. + */ + int (*play)(ScrnInfoPtr, struct VMWAREVideoRec *, + short, short, short, short, short, + short, short, short, int, unsigned char*, + short, short, RegionPtr, DrawablePtr); + /* + * Offscreen memory region used to pass video data to the host. + */ + VMWAREOffscreenPtr fbarea; + VMWAREVideoBuffer bufs[VMWARE_VID_NUM_BUFFERS]; + uint8 currBuf; + uint32 size; + uint32 colorKey; + Bool isAutoPaintColorkey; + uint32 flags; + RegionRec clipBoxes; + VMWAREVideoFmtData *fmt_priv; +}; + +typedef struct VMWAREVideoRec VMWAREVideoRec; +typedef VMWAREVideoRec *VMWAREVideoPtr; + +/* + * Callback functions + */ +#if (GET_ABI_MAJOR(ABI_VIDEODRV_VERSION) >= 1) +static int vmwareXvPutImage(ScrnInfoPtr pScrn, short src_x, short src_y, + short drw_x, short drw_y, short src_w, short src_h, + short drw_w, short drw_h, int image, + unsigned char *buf, short width, short height, + Bool sync, RegionPtr clipBoxes, pointer data, + DrawablePtr dst); +#else +static int vmwareXvPutImage(ScrnInfoPtr pScrn, short src_x, short src_y, + short drw_x, short drw_y, short src_w, short src_h, + short drw_w, short drw_h, int image, + unsigned char *buf, short width, short height, + Bool sync, RegionPtr clipBoxes, pointer data); +#endif +static void vmwareStopVideo(ScrnInfoPtr pScrn, pointer data, Bool Cleanup); +static int vmwareQueryImageAttributes(ScrnInfoPtr pScrn, int format, + unsigned short *width, + unsigned short *height, int *pitches, + int *offsets); +static int vmwareSetPortAttribute(ScrnInfoPtr pScrn, Atom attribute, + INT32 value, pointer data); +static int vmwareGetPortAttribute(ScrnInfoPtr pScrn, Atom attribute, + INT32 *value, pointer data); +static void vmwareQueryBestSize(ScrnInfoPtr pScrn, Bool motion, + short vid_w, short vid_h, short drw_w, + short drw_h, unsigned int *p_w, + unsigned int *p_h, pointer data); + +/* + * Local functions for video streams + */ +static XF86VideoAdaptorPtr vmwareVideoSetup(ScrnInfoPtr pScrn); +static int vmwareVideoInitStream(ScrnInfoPtr pScrn, VMWAREVideoPtr pVid, + short src_x, short src_y, short drw_x, + short drw_y, short src_w, short src_h, + short drw_w, short drw_h, int format, + unsigned char *buf, short width, + short height, RegionPtr clipBoxes, + DrawablePtr draw); +static int vmwareVideoInitAttributes(ScrnInfoPtr pScrn, VMWAREVideoPtr pVid, + int format, unsigned short width, + unsigned short height); +static int vmwareVideoPlay(ScrnInfoPtr pScrn, VMWAREVideoPtr pVid, + short src_x, short src_y, short drw_x, + short drw_y, short src_w, short src_h, + short drw_w, short drw_h, int format, + unsigned char *buf, short width, + short height, RegionPtr clipBoxes, + DrawablePtr draw); +static void vmwareVideoFlush(VMWAREPtr pVMWARE, uint32 streamId); +static void vmwareVideoSetOneReg(VMWAREPtr pVMWARE, uint32 streamId, + uint32 regId, uint32 value); +static void vmwareVideoEndStream(ScrnInfoPtr pScrn, VMWAREVideoPtr pVid); + +/* + * Offscreen memory manager functions + */ +static void vmwareOffscreenInit(void); +static VMWAREOffscreenPtr vmwareOffscreenAllocate(VMWAREPtr pVMWARE, + uint32 size); +static void vmwareOffscreenFree(VMWAREOffscreenPtr memptr); + + +/* + *----------------------------------------------------------------------------- + * + * vmwareCheckVideoSanity -- + * + * Ensures that on ModeSwitch the offscreen memory used + * by the Xv streams doesn't become part of the guest framebuffer. + * + * Results: + * None + * + * Side effects: + * If it is found that the offscreen used by video streams lies + * within the range of the framebuffer(after ModeSwitch) then the video + * streams will be stopped. + * + *----------------------------------------------------------------------------- + */ + +void +vmwareCheckVideoSanity(ScrnInfoPtr pScrn) +{ + VMWAREPtr pVMWARE = VMWAREPTR(pScrn); + VMWAREVideoPtr pVid; + + if (offscreenMgr.size == 0 || + offscreenMgr.offset > pVMWARE->FbSize) { + return ; + } + + pVid = (VMWAREVideoPtr) &pVMWARE->videoStreams[VMWARE_VID_NUM_PORTS]; + vmwareStopVideo(pScrn, pVid, TRUE); +} + + +/* + *----------------------------------------------------------------------------- + * + * vmwareOffscreenInit -- + * + * Initializes the trivial Offscreen memory manager. + * + * Results: + * None. + * + * Side effects: + * Initializes the Offscreen manager meta-data structure. + * + *----------------------------------------------------------------------------- + */ + +static void +vmwareOffscreenInit(void) +{ + offscreenMgr.size = 0; + offscreenMgr.offset = 0; +} + + +/* + *----------------------------------------------------------------------------- + * + * vmwareOffscreenAllocate -- + * + * Allocates offscreen memory. + * Memory is allocated from the bottom part of the VRAM. + * The memory manager is trivial iand can handle only 1 video-stream. + * ---------- + * | | + * | FB | + * | | + * |--------- + * | | + * | | + * |--------| + * | Offscr | + * |--------| + * + * VRAM + * + * Results: + * Pointer to the allocated Offscreen memory. + * + * Side effects: + * Updates the Offscreen memory manager meta-data structure. + * + *----------------------------------------------------------------------------- + */ + +static VMWAREOffscreenPtr +vmwareOffscreenAllocate(VMWAREPtr pVMWARE, uint32 size) +{ + VMWAREOffscreenPtr memptr; + + if ((pVMWARE->videoRam - pVMWARE->FbSize - pVMWARE->fbPitch - 7) < size) { + return NULL; + } + + memptr = malloc(sizeof(VMWAREOffscreenRec)); + if (!memptr) { + return NULL; + } + memptr->size = size; + memptr->offset = (pVMWARE->videoRam - size) & ~7; + + VmwareLog(("vmwareOffscreenAllocate: Offset:%x", memptr->offset)); + + offscreenMgr.size = memptr->size; + offscreenMgr.offset = memptr->offset; + return memptr; +} + + +/* + *----------------------------------------------------------------------------- + * + * vmwareOffscreenFree -- + * + * Frees the allocated offscreen memory. + * + * Results: + * None. + * + * Side effects: + * Updates the Offscreen memory manager meta-data structure. + * + *----------------------------------------------------------------------------- + */ + +static void +vmwareOffscreenFree(VMWAREOffscreenPtr memptr) +{ + if (memptr) { + free(memptr); + } + + offscreenMgr.size = 0; + offscreenMgr.offset = 0; +} + + +/* + *----------------------------------------------------------------------------- + * + * vmwareVideoEnabled -- + * + * Checks if Video FIFO and Escape FIFO cap are enabled. + * + * Results: + * TRUE if required caps are enabled, FALSE otherwise. + * + * Side effects: + * None. + * + *----------------------------------------------------------------------------- + */ + +Bool +vmwareVideoEnabled(VMWAREPtr pVMWARE) +{ + return ((pVMWARE->vmwareCapability & SVGA_CAP_EXTENDED_FIFO) && + (pVMWARE->vmwareFIFO[SVGA_FIFO_CAPABILITIES] & + (SVGA_FIFO_CAP_VIDEO | SVGA_FIFO_CAP_ESCAPE))); +} + + +/* + *----------------------------------------------------------------------------- + * + * vmwareVideoInit -- + * + * Initializes Xv support. + * + * Results: + * TRUE on success, FALSE on error. + * + * Side effects: + * Xv support is initialized. Memory is allocated for all supported + * video streams. + * + *----------------------------------------------------------------------------- + */ + +Bool +vmwareVideoInit(ScreenPtr pScreen) +{ + ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen); + XF86VideoAdaptorPtr *overlayAdaptors, *newAdaptors = NULL; + XF86VideoAdaptorPtr newAdaptor = NULL; + int numAdaptors; + + TRACEPOINT + + vmwareOffscreenInit(); + + numAdaptors = xf86XVListGenericAdaptors(pScrn, &overlayAdaptors); + + newAdaptor = vmwareVideoSetup(pScrn); + if (!newAdaptor) { + VmwareLog(("Failed to initialize Xv extension \n")); + return FALSE; + } + + if (!numAdaptors) { + numAdaptors = 1; + overlayAdaptors = &newAdaptor; + } else { + newAdaptors = malloc((numAdaptors + 1) * + sizeof(XF86VideoAdaptorPtr*)); + if (!newAdaptors) { + xf86XVFreeVideoAdaptorRec(newAdaptor); + return FALSE; + } + + memcpy(newAdaptors, overlayAdaptors, + numAdaptors * sizeof(XF86VideoAdaptorPtr)); + newAdaptors[numAdaptors++] = newAdaptor; + overlayAdaptors = newAdaptors; + } + + if (!xf86XVScreenInit(pScreen, overlayAdaptors, numAdaptors)) { + VmwareLog(("Failed to initialize Xv extension\n")); + xf86XVFreeVideoAdaptorRec(newAdaptor); + return FALSE; + } + + if (newAdaptors) { + free(newAdaptors); + } + + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "Initialized VMware Xv extension successfully.\n"); + return TRUE; +} + + +/* + *----------------------------------------------------------------------------- + * + * vmwareVideoEnd -- + * + * Unitializes video. + * + * Results: + * None. + * + * Side effects: + * pVMWARE->videoStreams = NULL + * + *----------------------------------------------------------------------------- + */ + +void +vmwareVideoEnd(ScreenPtr pScreen) +{ + ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen); + VMWAREPtr pVMWARE = VMWAREPTR(pScrn); + VMWAREVideoPtr pVid; + int i; + + TRACEPOINT + + /* + * Video streams are allocated after the DevUnion array + * (see VideoSetup) + */ + pVid = (VMWAREVideoPtr) &pVMWARE->videoStreams[VMWARE_VID_NUM_PORTS]; + for (i = 0; i < VMWARE_VID_NUM_PORTS; ++i) { + vmwareVideoEndStream(pScrn, &pVid[i]); + REGION_UNINIT(pScreen, &pVid[i].clipBoxes); + } + + free(pVMWARE->videoStreams); + pVMWARE->videoStreams = NULL; +} + + +/* + *----------------------------------------------------------------------------- + * + * vmwareVideoSetup -- + * + * Initializes a XF86VideoAdaptor structure with the capabilities and + * functions supported by this video driver. + * + * Results: + * On success initialized XF86VideoAdaptor struct or NULL on error + * + * Side effects: + * None. + * + *----------------------------------------------------------------------------- + */ + +static XF86VideoAdaptorPtr +vmwareVideoSetup(ScrnInfoPtr pScrn) +{ + VMWAREPtr pVMWARE = VMWAREPTR(pScrn); + XF86VideoAdaptorPtr adaptor; + VMWAREVideoPtr pPriv; + DevUnion *du; + int i; + + TRACEPOINT + + adaptor = xf86XVAllocateVideoAdaptorRec(pScrn); + if (!adaptor) { + VmwareLog(("Not enough memory\n")); + return NULL; + } + du = calloc(1, VMWARE_VID_NUM_PORTS * + (sizeof(DevUnion) + sizeof(VMWAREVideoRec))); + + if (!du) { + VmwareLog(("Not enough memory.\n")); + xf86XVFreeVideoAdaptorRec(adaptor); + return NULL; + } + + adaptor->type = XvInputMask | XvImageMask | XvWindowMask; + adaptor->flags = VIDEO_OVERLAID_IMAGES | VIDEO_CLIP_TO_VIEWPORT; + adaptor->name = "VMware Video Engine"; + adaptor->nEncodings = VMWARE_VID_NUM_ENCODINGS; + adaptor->pEncodings = vmwareVideoEncodings; + adaptor->nFormats = VMWARE_VID_NUM_FORMATS; + adaptor->pFormats = vmwareVideoFormats; + adaptor->nPorts = VMWARE_VID_NUM_PORTS; + + pPriv = (VMWAREVideoPtr) &du[VMWARE_VID_NUM_PORTS]; + adaptor->pPortPrivates = du; + + for (i = 0; i < VMWARE_VID_NUM_PORTS; ++i) { + pPriv[i].streamId = i; + pPriv[i].play = vmwareVideoInitStream; + pPriv[i].flags = SVGA_VIDEO_FLAG_COLORKEY; + pPriv[i].colorKey = VMWARE_VIDEO_COLORKEY; + pPriv[i].isAutoPaintColorkey = TRUE; + REGION_NULL(pScreen, &pPriv[i].clipBoxes); + adaptor->pPortPrivates[i].ptr = &pPriv[i]; + } + pVMWARE->videoStreams = du; + + adaptor->nAttributes = VMWARE_VID_NUM_ATTRIBUTES; + adaptor->pAttributes = vmwareVideoAttributes; + + adaptor->nImages = VMWARE_VID_NUM_IMAGES; + adaptor->pImages = vmwareVideoImages; + + adaptor->PutVideo = NULL; + adaptor->PutStill = NULL; + adaptor->GetVideo = NULL; + adaptor->GetStill = NULL; + adaptor->StopVideo = vmwareStopVideo; + adaptor->SetPortAttribute = vmwareSetPortAttribute; + adaptor->GetPortAttribute = vmwareGetPortAttribute; + adaptor->QueryBestSize = vmwareQueryBestSize; + adaptor->PutImage = vmwareXvPutImage; + adaptor->QueryImageAttributes = vmwareQueryImageAttributes; + + return adaptor; +} + + +/* + *----------------------------------------------------------------------------- + * + * vmwareVideoInitStream -- + * + * Initializes a video stream in response to the first PutImage() on a + * video stream. The process goes as follows: + * - Figure out characteristics according to format + * - Allocate offscreen memory + * - Pass on video to Play() functions + * + * Results: + * Success or XvBadAlloc on failure. + * + * Side effects: + * Video stream is initialized and its first frame sent to the host + * (done by VideoPlay() function called at the end) + * + *----------------------------------------------------------------------------- + */ + +static int +vmwareVideoInitStream(ScrnInfoPtr pScrn, VMWAREVideoPtr pVid, + short src_x, short src_y, short drw_x, + short drw_y, short src_w, short src_h, + short drw_w, short drw_h, int format, + unsigned char *buf, short width, + short height, RegionPtr clipBoxes, + DrawablePtr draw) +{ + VMWAREPtr pVMWARE = VMWAREPTR(pScrn); + int i; + + TRACEPOINT + + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "Initializing Xv video-stream with id:%d format:%d\n", + pVid->streamId, format); + + pVid->size = vmwareVideoInitAttributes(pScrn, pVid, format, width, + height); + + if (pVid->size == -1) { + VmwareLog(("Could not initialize 0x%x video stream\n", format)); + return XvBadAlloc; + } + + pVid->play = vmwareVideoPlay; + + pVid->fbarea = vmwareOffscreenAllocate(pVMWARE, + pVid->size * VMWARE_VID_NUM_BUFFERS); + + if (!pVid->fbarea) { + VmwareLog(("Could not allocate offscreen memory\n")); + vmwareVideoEndStream(pScrn, pVid); + return BadAlloc; + } + + pVid->bufs[0].dataOffset = pVid->fbarea->offset; + pVid->bufs[0].data = pVMWARE->FbBase + pVid->bufs[0].dataOffset; + + for (i = 1; i < VMWARE_VID_NUM_BUFFERS; ++i) { + pVid->bufs[i].dataOffset = pVid->bufs[i-1].dataOffset + pVid->size; + pVid->bufs[i].data = pVMWARE->FbBase + pVid->bufs[i].dataOffset; + } + pVid->currBuf = 0; + + REGION_COPY(pScrn->pScreen, &pVid->clipBoxes, clipBoxes); + + if (pVid->isAutoPaintColorkey) { + BoxPtr boxes = REGION_RECTS(&pVid->clipBoxes); + int nBoxes = REGION_NUM_RECTS(&pVid->clipBoxes); + +#if HAVE_FILLKEYHELPERDRAWABLE + xf86XVFillKeyHelperDrawable(draw, pVid->colorKey, clipBoxes); +#else + xf86XVFillKeyHelper(pScrn->pScreen, pVid->colorKey, clipBoxes); +#endif + /** + * Force update to paint the colorkey before the overlay flush. + */ + + while(nBoxes--) + vmwareSendSVGACmdUpdate(pVMWARE, boxes++); + } + + VmwareLog(("Got offscreen region, offset %d, size %d " + "(yuv size in bytes: %d)\n", + pVid->fbarea->offset, pVid->fbarea->size, pVid->size)); + + return pVid->play(pScrn, pVid, src_x, src_y, drw_x, drw_y, src_w, src_h, + drw_w, drw_h, format, buf, width, height, clipBoxes, + draw); +} + + +/* + *----------------------------------------------------------------------------- + * + * vmwareVideoInitAttributes -- + * + * Fetches the format specific attributes using QueryImageAttributes(). + * + * Results: + * size of the YUV frame on success and -1 on error. + * + * Side effects: + * The video stream gets the format specific attributes(fmtData). + * + *----------------------------------------------------------------------------- + */ + +static int +vmwareVideoInitAttributes(ScrnInfoPtr pScrn, VMWAREVideoPtr pVid, + int format, unsigned short width, + unsigned short height) +{ + int size; + VMWAREVideoFmtData *fmtData; + + TRACEPOINT + + fmtData = calloc(1, sizeof(VMWAREVideoFmtData)); + if (!fmtData) { + return -1; + } + + size = vmwareQueryImageAttributes(pScrn, format, &width, &height, + fmtData->pitches, fmtData->offsets); + if (size == -1) { + free(fmtData); + return -1; + } + + pVid->fmt_priv = fmtData; + return size; +} + + +/* + *----------------------------------------------------------------------------- + * + * vmwareVideoPlay -- + * + * Sends all the attributes associated with the video frame using the + * FIFO ESCAPE mechanism to the host. + * + * Results: + * Always returns Success. + * + * Side effects: + * None. + * + *----------------------------------------------------------------------------- + */ + +static int +vmwareVideoPlay(ScrnInfoPtr pScrn, VMWAREVideoPtr pVid, + short src_x, short src_y, short drw_x, + short drw_y, short src_w, short src_h, + short drw_w, short drw_h, int format, + unsigned char *buf, short width, + short height, RegionPtr clipBoxes, + DrawablePtr draw) +{ + VMWAREPtr pVMWARE = VMWAREPTR(pScrn); + uint32 *fifoItem; + int i, regId; + struct PACKED _item { + uint32 regId; + uint32 value; + }; + + struct PACKED _body { + uint32 escape; + uint32 streamId; + struct _item items[SVGA_VIDEO_NUM_REGS]; + }; + + struct PACKED _cmdSetRegs { + uint32 cmd; + uint32 nsid; + uint32 size; + struct _body body; + }; + + struct _cmdSetRegs cmdSetRegs; + struct _item *items; + int size; + VMWAREVideoFmtData *fmtData; + unsigned short w, h; + + w = width; + h = height; + fmtData = pVid->fmt_priv; + + size = vmwareQueryImageAttributes(pScrn, format, &w, &h, + fmtData->pitches, fmtData->offsets); + + if (size > pVid->size) { + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Increase in size of Xv video " + "frame streamId:%d.\n", pVid->streamId); + vmwareStopVideo(pScrn, pVid, TRUE); + return pVid->play(pScrn, pVid, src_x, src_y, drw_x, drw_y, src_w, + src_h, drw_w, drw_h, format, buf, width, height, + clipBoxes, draw); + } + + pVid->size = size; + memcpy(pVid->bufs[pVid->currBuf].data, buf, pVid->size); + + cmdSetRegs.cmd = SVGA_CMD_ESCAPE; + cmdSetRegs.nsid = SVGA_ESCAPE_NSID_VMWARE; + cmdSetRegs.size = sizeof(cmdSetRegs.body); + cmdSetRegs.body.escape = SVGA_ESCAPE_VMWARE_VIDEO_SET_REGS; + cmdSetRegs.body.streamId = pVid->streamId; + + items = cmdSetRegs.body.items; + for (i = SVGA_VIDEO_ENABLED; i < SVGA_VIDEO_NUM_REGS; i++) { + items[i].regId = i; + } + + items[SVGA_VIDEO_ENABLED].value = TRUE; + items[SVGA_VIDEO_DATA_OFFSET].value = + pVid->bufs[pVid->currBuf].dataOffset; + items[SVGA_VIDEO_SIZE].value = pVid->size; + items[SVGA_VIDEO_FORMAT].value = format; + items[SVGA_VIDEO_WIDTH].value = w; + items[SVGA_VIDEO_HEIGHT].value = h; + items[SVGA_VIDEO_SRC_X].value = src_x; + items[SVGA_VIDEO_SRC_Y].value = src_y; + items[SVGA_VIDEO_SRC_WIDTH].value = src_w; + items[SVGA_VIDEO_SRC_HEIGHT].value = src_h; + items[SVGA_VIDEO_DST_X].value = drw_x; + items[SVGA_VIDEO_DST_Y].value = drw_y; + items[SVGA_VIDEO_DST_WIDTH]. value = drw_w; + items[SVGA_VIDEO_DST_HEIGHT].value = drw_h; + items[SVGA_VIDEO_COLORKEY].value = pVid->colorKey; + items[SVGA_VIDEO_FLAGS].value = pVid->flags; + + for (i = 0, regId = SVGA_VIDEO_PITCH_1; i < 3; i++, regId++) { + items[regId].value = fmtData->pitches[i]; + } + + fifoItem = (uint32 *) &cmdSetRegs; + for (i = 0; i < sizeof(cmdSetRegs) / sizeof(uint32); i++) { + vmwareWriteWordToFIFO(pVMWARE, fifoItem[i]); + } + + /* + * Update the clipList and paint the colorkey, if required. + */ + if (!vmwareIsRegionEqual(&pVid->clipBoxes, clipBoxes)) { + REGION_COPY(pScrn->pScreen, &pVid->clipBoxes, clipBoxes); + if (pVid->isAutoPaintColorkey) { + BoxPtr boxes = REGION_RECTS(&pVid->clipBoxes); + int nBoxes = REGION_NUM_RECTS(&pVid->clipBoxes); + +#if HAVE_FILLKEYHELPERDRAWABLE + xf86XVFillKeyHelperDrawable(draw, pVid->colorKey, clipBoxes); +#else + xf86XVFillKeyHelper(pScrn->pScreen, pVid->colorKey, clipBoxes); +#endif + /** + * Force update to paint the colorkey before the overlay flush. + */ + + while(nBoxes--) + vmwareSendSVGACmdUpdate(pVMWARE, boxes++); + + } + } + + vmwareVideoFlush(pVMWARE, pVid->streamId); + + pVid->currBuf = ++pVid->currBuf & (VMWARE_VID_NUM_BUFFERS - 1); + + return Success; +} + + +/* + *----------------------------------------------------------------------------- + * + * vmwareVideoFlush -- + * + * Sends the VIDEO_FLUSH command (FIFO ESCAPE mechanism) asking the host + * to play the video stream or end it. + * + * Results: + * None. + * + * Side effects: + * None. + * + *----------------------------------------------------------------------------- + */ + +static void +vmwareVideoFlush(VMWAREPtr pVMWARE, uint32 streamId) +{ + struct PACKED _body { + uint32 escape; + uint32 streamId; + }; + + struct PACKED _cmdFlush { + uint32 cmd; + uint32 nsid; + uint32 size; + struct _body body; + }; + + struct _cmdFlush cmdFlush; + uint32 *fifoItem; + int i; + + cmdFlush.cmd = SVGA_CMD_ESCAPE; + cmdFlush.nsid = SVGA_ESCAPE_NSID_VMWARE; + cmdFlush.size = sizeof(cmdFlush.body); + cmdFlush.body.escape = SVGA_ESCAPE_VMWARE_VIDEO_FLUSH; + cmdFlush.body.streamId = streamId; + + fifoItem = (uint32 *) &cmdFlush; + for (i = 0; i < sizeof(cmdFlush) / sizeof(uint32); i++) { + vmwareWriteWordToFIFO(pVMWARE, fifoItem[i]); + } +} + + +/* + *----------------------------------------------------------------------------- + * + * vmwareVideoSetOneReg -- + * + * Sets one video register using the FIFO ESCAPE mechanidm. + * + * Results: + * None. + * + * Side effects: + * None. + *----------------------------------------------------------------------------- + */ + +static void +vmwareVideoSetOneReg(VMWAREPtr pVMWARE, uint32 streamId, + uint32 regId, uint32 value) +{ + struct PACKED _item { + uint32 regId; + uint32 value; + }; + + struct PACKED _body { + uint32 escape; + uint32 streamId; + struct _item item; + }; + + struct PACKED _cmdSetRegs { + uint32 cmd; + uint32 nsid; + uint32 size; + struct _body body; + }; + + struct _cmdSetRegs cmdSetRegs; + int i; + uint32 *fifoItem; + + cmdSetRegs.cmd = SVGA_CMD_ESCAPE; + cmdSetRegs.nsid = SVGA_ESCAPE_NSID_VMWARE; + cmdSetRegs.size = sizeof(cmdSetRegs.body); + cmdSetRegs.body.escape = SVGA_ESCAPE_VMWARE_VIDEO_SET_REGS; + cmdSetRegs.body.streamId = streamId; + cmdSetRegs.body.item.regId = regId; + cmdSetRegs.body.item.value = value; + + fifoItem = (uint32 *) &cmdSetRegs; + for (i = 0; i < sizeof(cmdSetRegs) / sizeof(uint32); i++) { + vmwareWriteWordToFIFO(pVMWARE, fifoItem[i]); + } +} + + +/* + *----------------------------------------------------------------------------- + * + * vmwareVideoEndStream -- + * + * Frees up all resources (if any) taken by a video stream. + * + * Results: + * None. + * + * Side effects: + * Same as above. + * + *----------------------------------------------------------------------------- + */ + +static void +vmwareVideoEndStream(ScrnInfoPtr pScrn, VMWAREVideoPtr pVid) +{ + uint32 id, colorKey, flags; + Bool isAutoPaintColorkey; + + if (pVid->fmt_priv) { + free(pVid->fmt_priv); + } + + if (pVid->fbarea) { + vmwareOffscreenFree(pVid->fbarea); + pVid->fbarea = NULL; + } + + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "Terminating Xv video-stream id:%d\n", pVid->streamId); + /* + * reset stream for next video + */ + id = pVid->streamId; + colorKey = pVid->colorKey; + flags = pVid->flags; + isAutoPaintColorkey = pVid->isAutoPaintColorkey; + + memset(pVid, 0, sizeof(*pVid)); + + pVid->streamId = id; + pVid->play = vmwareVideoInitStream; + pVid->colorKey = colorKey; + pVid->flags = flags; + pVid->isAutoPaintColorkey = isAutoPaintColorkey; +} + + +/* + *----------------------------------------------------------------------------- + * + * vmwareXvPutImage -- + * + * Main video playback function. It copies the passed data which is in + * the specified format (e.g. FOURCC_YV12) into the overlay. + * + * If sync is TRUE the driver should not return from this + * function until it is through reading the data from buf. + * + * There are two function prototypes to cope with the API change in X.org + * 7.1 + * + * Results: + * Success or XvBadAlloc on failure + * + * Side effects: + * Video stream will be played(initialized if 1st frame) on success + * or will fail on error. + * + *----------------------------------------------------------------------------- + */ + +#if (GET_ABI_MAJOR(ABI_VIDEODRV_VERSION) >= 1) +static int +vmwareXvPutImage(ScrnInfoPtr pScrn, short src_x, short src_y, + short drw_x, short drw_y, short src_w, short src_h, + short drw_w, short drw_h, int format, + unsigned char *buf, short width, short height, + Bool sync, RegionPtr clipBoxes, pointer data, + DrawablePtr dst) +#else +static int +vmwareXvPutImage(ScrnInfoPtr pScrn, short src_x, short src_y, + short drw_x, short drw_y, short src_w, short src_h, + short drw_w, short drw_h, int format, + unsigned char *buf, short width, short height, + Bool sync, RegionPtr clipBoxes, pointer data) +#endif +{ + VMWAREPtr pVMWARE = VMWAREPTR(pScrn); + VMWAREVideoPtr pVid = data; + + TRACEPOINT + + if (!vmwareVideoEnabled(pVMWARE)) { + return XvBadAlloc; + } + +#if (GET_ABI_MAJOR(ABI_VIDEODRV_VERSION) >= 1) + return pVid->play(pScrn, pVid, src_x, src_y, drw_x, drw_y, src_w, src_h, + drw_w, drw_h, format, buf, width, height, clipBoxes, + dst); +#else + return pVid->play(pScrn, pVid, src_x, src_y, drw_x, drw_y, src_w, src_h, + drw_w, drw_h, format, buf, width, height, clipBoxes, + NULL); +#endif +} + + +/* + *----------------------------------------------------------------------------- + * + * vmwareStopVideo -- + * + * Called when we should stop playing video for a particular stream. If + * Cleanup is FALSE, the "stop" operation is only temporary, and thus we + * don't do anything. If Cleanup is TRUE we kill the video stream by + * sending a message to the host and freeing up the stream. + * + * Results: + * None. + * + * Side effects: + * See above. + * + *----------------------------------------------------------------------------- + */ + +static void +vmwareStopVideo(ScrnInfoPtr pScrn, pointer data, Bool Cleanup) +{ + VMWAREVideoPtr pVid = data; + VMWAREPtr pVMWARE = VMWAREPTR(pScrn); + TRACEPOINT + + if (!vmwareVideoEnabled(pVMWARE)) { + return; + } + + REGION_EMPTY(pScrn->pScreen, &pVid->clipBoxes); + + if (!Cleanup) { + VmwareLog(("vmwareStopVideo: Cleanup is FALSE.\n")); + return; + } + vmwareVideoSetOneReg(pVMWARE, pVid->streamId, + SVGA_VIDEO_ENABLED, FALSE); + + vmwareVideoFlush(pVMWARE, pVid->streamId); + vmwareVideoEndStream(pScrn, pVid); + +} + + +/* + *----------------------------------------------------------------------------- + * + * vmwareQueryImageAttributes -- + * + * From the spec: This function is called to let the driver specify how data + * for a particular image of size width by height should be stored. + * Sometimes only the size and corrected width and height are needed. In + * that case pitches and offsets are NULL. + * + * Results: + * The size of the memory required for the image, or -1 on error. + * + * Side effects: + * None. + * + *----------------------------------------------------------------------------- + */ + +static int +vmwareQueryImageAttributes(ScrnInfoPtr pScrn, int format, + unsigned short *width, unsigned short *height, + int *pitches, int *offsets) +{ + INT32 size, tmp; + + TRACEPOINT + + if (*width > VMWARE_VID_MAX_WIDTH) { + *width = VMWARE_VID_MAX_WIDTH; + } + if (*height > VMWARE_VID_MAX_HEIGHT) { + *height = VMWARE_VID_MAX_HEIGHT; + } + + *width = (*width + 1) & ~1; + if (offsets != NULL) { + offsets[0] = 0; + } + + switch (format) { + case FOURCC_YV12: + *height = (*height + 1) & ~1; + size = (*width + 3) & ~3; + if (pitches) { + pitches[0] = size; + } + size *= *height; + if (offsets) { + offsets[1] = size; + } + tmp = ((*width >> 1) + 3) & ~3; + if (pitches) { + pitches[1] = pitches[2] = tmp; + } + tmp *= (*height >> 1); + size += tmp; + if (offsets) { + offsets[2] = size; + } + size += tmp; + break; + case FOURCC_UYVY: + case FOURCC_YUY2: + size = *width * 2; + if (pitches) { + pitches[0] = size; + } + size *= *height; + break; + default: + VmwareLog(("Query for invalid video format %d\n", format)); + return -1; + } + return size; +} + + +/* + *----------------------------------------------------------------------------- + * + * vmwareSetPortAttribute -- + * + * From the spec: A port may have particular attributes such as colorKey, hue, + * saturation, brightness or contrast. Xv clients set these + * attribute values by sending attribute strings (Atoms) to the server. + * + * Results: + * Success if the attribute exists and XvBadAlloc otherwise. + * + * Side effects: + * The respective attribute gets the new value. + * + *----------------------------------------------------------------------------- + */ + +static int +vmwareSetPortAttribute(ScrnInfoPtr pScrn, Atom attribute, + INT32 value, pointer data) +{ + VMWAREVideoPtr pVid = (VMWAREVideoPtr) data; + Atom xvColorKey = MAKE_ATOM("XV_COLORKEY"); + Atom xvAutoPaint = MAKE_ATOM("XV_AUTOPAINT_COLORKEY"); + + if (attribute == xvColorKey) { + VmwareLog(("Set colorkey:0x%x\n", value)); + pVid->colorKey = value; + } else if (attribute == xvAutoPaint) { + VmwareLog(("Set autoPaint: %s\n", value? "TRUE": "FALSE")); + pVid->isAutoPaintColorkey = value; + } else { + return XvBadAlloc; + } + + return Success; +} + + +/* + *----------------------------------------------------------------------------- + * + * vmwareGetPortAttribute -- + * + * From the spec: A port may have particular attributes such as hue, + * saturation, brightness or contrast. Xv clients get these + * attribute values by sending attribute strings (Atoms) to the server + * + * Results: + * Success if the attribute exists and XvBadAlloc otherwise. + * + * Side effects: + * "value" contains the requested attribute on success. + * + *----------------------------------------------------------------------------- + */ + +static int +vmwareGetPortAttribute(ScrnInfoPtr pScrn, Atom attribute, + INT32 *value, pointer data) +{ + VMWAREVideoPtr pVid = (VMWAREVideoPtr) data; + Atom xvColorKey = MAKE_ATOM("XV_COLORKEY"); + Atom xvAutoPaint = MAKE_ATOM("XV_AUTOPAINT_COLORKEY"); + + if (attribute == xvColorKey) { + *value = pVid->colorKey; + } else if (attribute == xvAutoPaint) { + *value = pVid->isAutoPaintColorkey; + } else { + return XvBadAlloc; + } + + return Success; +} + + +/* + *----------------------------------------------------------------------------- + * + * vmwareQueryBestSize -- + * + * From the spec: QueryBestSize provides the client with a way to query what + * the destination dimensions would end up being if they were to request + * that an area vid_w by vid_h from the video stream be scaled to rectangle + * of drw_w by drw_h on the screen. Since it is not expected that all + * hardware will be able to get the target dimensions exactly, it is + * important that the driver provide this function. + * + * This function seems to never be called, but to be on the safe side + * we apply the same logic that QueryImageAttributes has for width + * and height + * + * Results: + * None. + * + * Side effects: + * None + * + *----------------------------------------------------------------------------- + */ + +static void +vmwareQueryBestSize(ScrnInfoPtr pScrn, Bool motion, + short vid_w, short vid_h, short drw_w, + short drw_h, unsigned int *p_w, + unsigned int *p_h, pointer data) +{ + *p_w = (drw_w + 1) & ~1; + *p_h = drw_h; + + return; +} + diff --git a/src/vmwarexinerama.c b/src/vmwarexinerama.c new file mode 100644 index 0000000..954abdc --- /dev/null +++ b/src/vmwarexinerama.c @@ -0,0 +1,728 @@ +/* + * Copyright 2006 by VMware, 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 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. + * + * Except as contained in this notice, the name of the copyright holder(s) + * and author(s) shall not be used in advertising or otherwise to promote + * the sale, use or other dealings in this Software without prior written + * authorization from the copyright holder(s) and author(s). + */ + +/* + * vmwarexinerama.c -- + * + * The implementation of the Xinerama protocol extension. + */ + + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "dixstruct.h" +#include "extnsionst.h" +#include <X11/X.h> +#include <X11/extensions/panoramiXproto.h> + +#include "vmware.h" + +#ifndef HAVE_XORG_SERVER_1_5_0 +#include <xf86_ansic.h> +#include <xf86_libc.h> +#endif + +/* + * LookupWindow was removed with video abi 11. + */ +#if (GET_ABI_MAJOR(ABI_VIDEODRV_VERSION) < 4) +#ifndef DixGetAttrAccess +#define DixGetAttrAccess (1<<4) +#endif +#endif + +#if (GET_ABI_MAJOR(ABI_VIDEODRV_VERSION) < 2) +static inline int +dixLookupWindow(WindowPtr *pWin, XID id, ClientPtr client, Mask access) +{ + *pWin = LookupWindow(id, client); + if (!*pWin) + return BadWindow; + return Success; +} +#endif + + +/* + *---------------------------------------------------------------------------- + * + * VMwareXineramaQueryVersion -- + * + * Implementation of QueryVersion command handler. Initialises and + * sends a reply. + * + * Results: + * Standard response codes. + * + * Side effects: + * Writes reply to client. + * + *---------------------------------------------------------------------------- + */ + +static int +VMwareXineramaQueryVersion(ClientPtr client) +{ + xPanoramiXQueryVersionReply rep; + register int n; + + REQUEST_SIZE_MATCH(xPanoramiXQueryVersionReq); + rep.type = X_Reply; + rep.length = 0; + rep.sequenceNumber = client->sequence; + rep.majorVersion = 1; + rep.minorVersion = 0; + if(client->swapped) { + _swaps(&rep.sequenceNumber, n); + _swapl(&rep.length, n); + _swaps(&rep.majorVersion, n); + _swaps(&rep.minorVersion, n); + } + WriteToClient(client, sizeof(xPanoramiXQueryVersionReply), (char *)&rep); + return (client->noClientException); +} + + +/* + *---------------------------------------------------------------------------- + * + * VMwareXineramaGetState -- + * + * Implementation of GetState command handler. Initialises and + * sends a reply. + * + * Results: + * Standard response codes. + * + * Side effects: + * Writes reply to client. + * + *---------------------------------------------------------------------------- + */ + +static int +VMwareXineramaGetState(ClientPtr client) +{ + REQUEST(xPanoramiXGetStateReq); + WindowPtr pWin; + xPanoramiXGetStateReply rep; + register int n; + ExtensionEntry *ext; + ScrnInfoPtr pScrn; + VMWAREPtr pVMWARE; + int rc; + + REQUEST_SIZE_MATCH(xPanoramiXGetStateReq); + rc = dixLookupWindow(&pWin, stuff->window, client, DixGetAttrAccess); + if (rc != Success) + return rc; + + if (!(ext = CheckExtension(PANORAMIX_PROTOCOL_NAME))) { + return BadMatch; + } + pScrn = ext->extPrivate; + pVMWARE = VMWAREPTR(pScrn); + + rep.type = X_Reply; + rep.length = 0; + rep.sequenceNumber = client->sequence; + rep.state = pVMWARE->xinerama; + rep.window = stuff->window; + if(client->swapped) { + _swaps (&rep.sequenceNumber, n); + _swapl (&rep.length, n); + _swapl (&rep.window, n); + } + WriteToClient(client, sizeof(xPanoramiXGetStateReply), (char *)&rep); + return client->noClientException; +} + + +/* + *---------------------------------------------------------------------------- + * + * VMwareXineramaGetScreenCount -- + * + * Implementation of GetScreenCount command handler. Initialises and + * sends a reply. + * + * Results: + * Standard response codes. + * + * Side effects: + * Writes reply to client. + * + *---------------------------------------------------------------------------- + */ + +static int +VMwareXineramaGetScreenCount(ClientPtr client) +{ + REQUEST(xPanoramiXGetScreenCountReq); + WindowPtr pWin; + xPanoramiXGetScreenCountReply rep; + register int n; + ExtensionEntry *ext; + ScrnInfoPtr pScrn; + VMWAREPtr pVMWARE; + int rc; + + REQUEST_SIZE_MATCH(xPanoramiXGetScreenCountReq); + rc = dixLookupWindow(&pWin, stuff->window, client, DixGetAttrAccess); + if (rc != Success) + return rc; + + if (!(ext = CheckExtension(PANORAMIX_PROTOCOL_NAME))) { + return BadMatch; + } + pScrn = ext->extPrivate; + pVMWARE = VMWAREPTR(pScrn); + + rep.type = X_Reply; + rep.length = 0; + rep.sequenceNumber = client->sequence; + rep.ScreenCount = pVMWARE->xineramaNumOutputs; + rep.window = stuff->window; + + if(client->swapped) { + _swaps(&rep.sequenceNumber, n); + _swapl(&rep.length, n); + _swapl(&rep.window, n); + } + WriteToClient(client, sizeof(xPanoramiXGetScreenCountReply), (char *)&rep); + return client->noClientException; +} + + +/* + *---------------------------------------------------------------------------- + * + * VMwareXineramaGetScreenSize -- + * + * Implementation of GetScreenSize command handler. Initialises and + * sends a reply. + * + * Results: + * Standard response codes. + * + * Side effects: + * Writes reply to client. + * + *---------------------------------------------------------------------------- + */ + +static int +VMwareXineramaGetScreenSize(ClientPtr client) +{ + REQUEST(xPanoramiXGetScreenSizeReq); + WindowPtr pWin; + xPanoramiXGetScreenSizeReply rep; + register int n; + ExtensionEntry *ext; + ScrnInfoPtr pScrn; + VMWAREPtr pVMWARE; + int rc; + + + REQUEST_SIZE_MATCH(xPanoramiXGetScreenSizeReq); + rc = dixLookupWindow(&pWin, stuff->window, client, DixGetAttrAccess); + if (rc != Success) + return rc; + + if (!(ext = CheckExtension(PANORAMIX_PROTOCOL_NAME))) { + return BadMatch; + } + pScrn = ext->extPrivate; + pVMWARE = VMWAREPTR(pScrn); + + rep.type = X_Reply; + rep.length = 0; + rep.sequenceNumber = client->sequence; + rep.width = pVMWARE->xineramaState[stuff->screen].width; + rep.height = pVMWARE->xineramaState[stuff->screen].height; + rep.window = stuff->window; + rep.screen = stuff->screen; + if(client->swapped) { + _swaps(&rep.sequenceNumber, n); + _swapl(&rep.length, n); + _swapl(&rep.width, n); + _swapl(&rep.height, n); + _swapl(&rep.window, n); + _swapl(&rep.screen, n); + } + WriteToClient(client, sizeof(xPanoramiXGetScreenSizeReply), (char *)&rep); + return client->noClientException; +} + + +/* + *---------------------------------------------------------------------------- + * + * VMwareXineramaIsActive -- + * + * Implementation of IsActive command handler. Initialises and + * sends a reply. + * + * Results: + * Standard response codes. + * + * Side effects: + * Writes reply to client. + * + *---------------------------------------------------------------------------- + */ + +static int +VMwareXineramaIsActive(ClientPtr client) +{ + xXineramaIsActiveReply rep; + ExtensionEntry *ext; + ScrnInfoPtr pScrn; + VMWAREPtr pVMWARE; + + REQUEST_SIZE_MATCH(xXineramaIsActiveReq); + + if (!(ext = CheckExtension(PANORAMIX_PROTOCOL_NAME))) { + return BadMatch; + } + pScrn = ext->extPrivate; + pVMWARE = VMWAREPTR(pScrn); + + rep.type = X_Reply; + rep.length = 0; + rep.sequenceNumber = client->sequence; + rep.state = pVMWARE->xinerama; + if(client->swapped) { + register int n; + _swaps(&rep.sequenceNumber, n); + _swapl(&rep.length, n); + _swapl(&rep.state, n); + } + WriteToClient(client, sizeof(xXineramaIsActiveReply), (char *) &rep); + return client->noClientException; +} + + +/* + *---------------------------------------------------------------------------- + * + * VMwareXineramaQueryScreens -- + * + * Implementation of QueryScreens command handler. Initialises and + * sends a reply. + * + * Results: + * Standard response codes. + * + * Side effects: + * Writes reply to client. + * + *---------------------------------------------------------------------------- + */ + +static int +VMwareXineramaQueryScreens(ClientPtr client) +{ + xXineramaQueryScreensReply rep; + ExtensionEntry *ext; + ScrnInfoPtr pScrn; + VMWAREPtr pVMWARE; + + REQUEST_SIZE_MATCH(xXineramaQueryScreensReq); + + if (!(ext = CheckExtension(PANORAMIX_PROTOCOL_NAME))) { + return BadMatch; + } + pScrn = ext->extPrivate; + pVMWARE = VMWAREPTR(pScrn); + + rep.type = X_Reply; + rep.sequenceNumber = client->sequence; + rep.number = pVMWARE->xinerama ? pVMWARE->xineramaNumOutputs : 0; + rep.length = rep.number * sz_XineramaScreenInfo >> 2; + if(client->swapped) { + register int n; + _swaps(&rep.sequenceNumber, n); + _swapl(&rep.length, n); + _swapl(&rep.number, n); + } + WriteToClient(client, sizeof(xXineramaQueryScreensReply), (char *)&rep); + + if(pVMWARE->xinerama) { + xXineramaScreenInfo scratch; + int i; + + for(i = 0; i < pVMWARE->xineramaNumOutputs; i++) { + scratch.x_org = pVMWARE->xineramaState[i].x_org; + scratch.y_org = pVMWARE->xineramaState[i].y_org; + scratch.width = pVMWARE->xineramaState[i].width; + scratch.height = pVMWARE->xineramaState[i].height; + if(client->swapped) { + register int n; + _swaps(&scratch.x_org, n); + _swaps(&scratch.y_org, n); + _swaps(&scratch.width, n); + _swaps(&scratch.height, n); + } + WriteToClient(client, sz_XineramaScreenInfo, (char *)&scratch); + } + } + + return client->noClientException; +} + + +/* + *---------------------------------------------------------------------------- + * + * VMwareXineramaDispatch -- + * + * Dispatcher for Xinerama commands. Calls the correct handler for + * each command type. + * + * Results: + * Standard response codes. + * + * Side effects: + * Side effects of individual command handlers. + * + *---------------------------------------------------------------------------- + */ + +static int +VMwareXineramaDispatch(ClientPtr client) +{ + REQUEST(xReq); + switch (stuff->data) { + case X_PanoramiXQueryVersion: + return VMwareXineramaQueryVersion(client); + case X_PanoramiXGetState: + return VMwareXineramaGetState(client); + case X_PanoramiXGetScreenCount: + return VMwareXineramaGetScreenCount(client); + case X_PanoramiXGetScreenSize: + return VMwareXineramaGetScreenSize(client); + case X_XineramaIsActive: + return VMwareXineramaIsActive(client); + case X_XineramaQueryScreens: + return VMwareXineramaQueryScreens(client); + } + return BadRequest; +} + + +/* + *---------------------------------------------------------------------------- + * + * SVMwareXineramaQueryVersion -- + * + * Wrapper for QueryVersion handler that handles input from other-endian + * clients. + * + * Results: + * Standard response codes. + * + * Side effects: + * Side effects of unswapped implementation. + * + *---------------------------------------------------------------------------- + */ + +static int +SVMwareXineramaQueryVersion (ClientPtr client) +{ + REQUEST(xPanoramiXQueryVersionReq); + register int n; + _swaps(&stuff->length,n); + REQUEST_SIZE_MATCH (xPanoramiXQueryVersionReq); + return VMwareXineramaQueryVersion(client); +} + + +/* + *---------------------------------------------------------------------------- + * + * SVMwareXineramaGetState -- + * + * Wrapper for GetState handler that handles input from other-endian + * clients. + * + * Results: + * Standard response codes. + * + * Side effects: + * Side effects of unswapped implementation. + * + *---------------------------------------------------------------------------- + */ + +static int +SVMwareXineramaGetState(ClientPtr client) +{ + REQUEST(xPanoramiXGetStateReq); + register int n; + _swaps (&stuff->length, n); + REQUEST_SIZE_MATCH(xPanoramiXGetStateReq); + return VMwareXineramaGetState(client); +} + + +/* + *---------------------------------------------------------------------------- + * + * SVMwareXineramaGetScreenCount -- + * + * Wrapper for GetScreenCount handler that handles input from other-endian + * clients. + * + * Results: + * Standard response codes. + * + * Side effects: + * Side effects of unswapped implementation. + * + *---------------------------------------------------------------------------- + */ + +static int +SVMwareXineramaGetScreenCount(ClientPtr client) +{ + REQUEST(xPanoramiXGetScreenCountReq); + register int n; + _swaps (&stuff->length, n); + REQUEST_SIZE_MATCH(xPanoramiXGetScreenCountReq); + return VMwareXineramaGetScreenCount(client); +} + + +/* + *---------------------------------------------------------------------------- + * + * SVMwareXineramaGetScreenSize -- + * + * Wrapper for GetScreenSize handler that handles input from other-endian + * clients. + * + * Results: + * Standard response codes. + * + * Side effects: + * Side effects of unswapped implementation. + * + *---------------------------------------------------------------------------- + */ + +static int +SVMwareXineramaGetScreenSize(ClientPtr client) +{ + REQUEST(xPanoramiXGetScreenSizeReq); + register int n; + _swaps (&stuff->length, n); + REQUEST_SIZE_MATCH(xPanoramiXGetScreenSizeReq); + return VMwareXineramaGetScreenSize(client); +} + + +/* + *---------------------------------------------------------------------------- + * + * SVMwareXineramaIsActive -- + * + * Wrapper for IsActive handler that handles input from other-endian + * clients. + * + * Results: + * Standard response codes. + * + * Side effects: + * Side effects of unswapped implementation. + * + *---------------------------------------------------------------------------- + */ + +static int +SVMwareXineramaIsActive(ClientPtr client) +{ + REQUEST(xXineramaIsActiveReq); + register int n; + _swaps (&stuff->length, n); + REQUEST_SIZE_MATCH(xXineramaIsActiveReq); + return VMwareXineramaIsActive(client); +} + + +/* + *---------------------------------------------------------------------------- + * + * SVMwareXineramaQueryScreens -- + * + * Wrapper for QueryScreens handler that handles input from other-endian + * clients. + * + * Results: + * Standard response codes. + * + * Side effects: + * Side effects of unswapped implementation. + * + *---------------------------------------------------------------------------- + */ + +static int +SVMwareXineramaQueryScreens(ClientPtr client) +{ + REQUEST(xXineramaQueryScreensReq); + register int n; + _swaps (&stuff->length, n); + REQUEST_SIZE_MATCH(xXineramaQueryScreensReq); + return VMwareXineramaQueryScreens(client); +} + + +/* + *---------------------------------------------------------------------------- + * + * SVMwareXineramaDispatch -- + * + * Wrapper for dispatcher that handles input from other-endian clients. + * + * Results: + * Standard response codes. + * + * Side effects: + * Side effects of individual command handlers. + * + *---------------------------------------------------------------------------- + */ + +static int +SVMwareXineramaDispatch(ClientPtr client) +{ + REQUEST(xReq); + switch (stuff->data) { + case X_PanoramiXQueryVersion: + return SVMwareXineramaQueryVersion(client); + case X_PanoramiXGetState: + return SVMwareXineramaGetState(client); + case X_PanoramiXGetScreenCount: + return SVMwareXineramaGetScreenCount(client); + case X_PanoramiXGetScreenSize: + return SVMwareXineramaGetScreenSize(client); + case X_XineramaIsActive: + return SVMwareXineramaIsActive(client); + case X_XineramaQueryScreens: + return SVMwareXineramaQueryScreens(client); + } + return BadRequest; +} + + +/* + *---------------------------------------------------------------------------- + * + * VMwareXineramaResetProc -- + * + * Cleanup handler called when the extension is removed. + * + * Results: + * None + * + * Side effects: + * None + * + *---------------------------------------------------------------------------- + */ + +static void +VMwareXineramaResetProc(ExtensionEntry* extEntry) +{ + /* Called by CloseDownExtensions() */ + + ScrnInfoPtr pScrn = extEntry->extPrivate; + VMWAREPtr pVMWARE = VMWAREPTR(pScrn); + + if (pVMWARE->xineramaState) { + free(pVMWARE->xineramaState); + pVMWARE->xineramaState = NULL; + pVMWARE->xineramaNumOutputs = 0; + pVMWARE->xinerama = FALSE; + } +} + + +/* + *---------------------------------------------------------------------------- + * + * VMwareCtrl_ExitInit -- + * + * Initialiser for the Xinerama protocol extension. + * + * Results: + * None. + * + * Side effects: + * Protocol extension will be registered if successful. + * + *---------------------------------------------------------------------------- + */ + +void +VMwareXinerama_ExtInit(ScrnInfoPtr pScrn) +{ + ExtensionEntry *myext; + VMWAREPtr pVMWARE = VMWAREPTR(pScrn); + +#ifdef PANORAMIX + if(!noPanoramiXExtension) { + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "Built-in Xinerama active, not initializing VMware Xinerama\n"); + pVMWARE->xinerama = FALSE; + return; + } +#endif + + if (!(myext = CheckExtension(PANORAMIX_PROTOCOL_NAME))) { + if (!(myext = AddExtension(PANORAMIX_PROTOCOL_NAME, 0, 0, + VMwareXineramaDispatch, + SVMwareXineramaDispatch, + VMwareXineramaResetProc, + StandardMinorOpcode))) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "Failed to add VMware Xinerama extension.\n"); + return; + } + + pVMWARE->xinerama = TRUE; + + myext->extPrivate = pScrn; + + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "Initialized VMware Xinerama extension.\n"); + } +} |