File xf86-video-vmware-13.3.0+12.obscpio of Package xf86-video-vmware

07070100000000000081A400000000000000000000000161A68E12000003F2000000000000000000000000000000000000002700000000xf86-video-vmware-13.3.0+12/.gitignore#
#		X.Org module default exclusion patterns
#		The next section if for module specific patterns
#
#	Do not edit the following section
# 	GNU Build System (Autotools)
aclocal.m4
autom4te.cache/
autoscan.log
ChangeLog
compile
config.guess
config.h
config.h.in
config.log
config-ml.in
config.py
config.status
config.status.lineno
config.sub
configure
configure.scan
depcomp
.deps/
INSTALL
install-sh
.libs/
libtool
libtool.m4
ltmain.sh
lt~obsolete.m4
ltoptions.m4
ltsugar.m4
ltversion.m4
Makefile
Makefile.in
mdate-sh
missing
mkinstalldirs
*.pc
py-compile
stamp-h?
symlink-tree
texinfo.tex
ylwrap

#	Do not edit the following section
# 	Edit Compile Debug Document Distribute
*~
*.[0-9]
*.[0-9]x
*.bak
*.bin
core
*.dll
*.exe
*-ISO*.bdf
*-JIS*.bdf
*-KOI8*.bdf
*.kld
*.ko
*.ko.cmd
*.lai
*.l[oa]
*.[oa]
*.obj
*.patch
*.so
*.pcf.gz
*.pdb
*.tar.bz2
*.tar.gz
#
#		Add & Override patterns for xf86-video-vmware 
#
#		Edit the following section as needed
# For example, !report.pc overrides *.pc. See 'man gitignore'
# 
07070100000001000081A400000000000000000000000161A68E1200000988000000000000000000000000000000000000002400000000xf86-video-vmware-13.3.0+12/COPYINGCopyright 2006 by VMware, Inc.
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).

Copyright 2010 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.

07070100000002000081A400000000000000000000000161A68E120000053F000000000000000000000000000000000000002800000000xf86-video-vmware-13.3.0+12/Makefile.am#  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.

# Order: vmwgfx before src
SUBDIRS = man saa vmwgfx src vmwarectrl

MAINTAINERCLEANFILES = ChangeLog INSTALL
.PHONY: ChangeLog INSTALL

INSTALL:
	$(INSTALL_CMD)

ChangeLog:
	$(CHANGELOG_CMD)

dist-hook: ChangeLog INSTALL
07070100000003000081A400000000000000000000000161A68E1200000129000000000000000000000000000000000000002300000000xf86-video-vmware-13.3.0+12/READMECopyright (C) 1999-2009 VMware, Inc.
All Rights Reserved

The code here may be used/distributed under the terms of the standard
XFree86 license.

Documentation on the VMware SVGA Device programming model
has been updated and expanded, and it now lives at:

http://vmware-svga.sourceforge.net/

--
07070100000004000081ED00000000000000000000000161A68E1200000166000000000000000000000000000000000000002700000000xf86-video-vmware-13.3.0+12/autogen.sh#! /bin/sh

srcdir=`dirname "$0"`
test -z "$srcdir" && srcdir=.

ORIGDIR=`pwd`
cd "$srcdir"

autoreconf -v --install || exit 1
cd "$ORIGDIR" || exit $?

git config --local --get format.subjectPrefix >/dev/null 2>&1 ||
    git config --local format.subjectPrefix "PATCH xf86-video-vmware"

if test -z "$NOCONFIGURE"; then
    exec "$srcdir"/configure "$@"
fi
07070100000005000081A400000000000000000000000161A68E12000018C4000000000000000000000000000000000000002900000000xf86-video-vmware-13.3.0+12/configure.ac#  Copyright 2005 Adam Jackson.
#
#  Permission is hereby granted, free of charge, to any person obtaining a
#  copy of this software and associated documentation files (the "Software"),
#  to deal in the Software without restriction, including without limitation
#  on the rights to use, copy, modify, merge, publish, distribute, sub
#  license, and/or sell copies of the Software, and to permit persons to whom
#  the Software is furnished to do so, subject to the following conditions:
#
#  The above copyright notice and this permission notice (including the next
#  paragraph) shall be included in all copies or substantial portions of the
#  Software.
#
#  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
#  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
#  FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.  IN NO EVENT SHALL
#  ADAM JACKSON BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
#  IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
#  CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#
# Process this file with autoconf to produce a configure script

# Initialize Autoconf
AC_PREREQ([2.60])
AC_INIT([xf86-video-vmware],
        [13.3.0],
        [https://bugs.freedesktop.org/enter_bug.cgi?product=xorg],
        [xf86-video-vmware])
AC_CONFIG_SRCDIR([Makefile.am])
AC_CONFIG_HEADERS([config.h])
AC_CONFIG_AUX_DIR(.)
AC_SYS_LARGEFILE

# Initialize Automake
AM_INIT_AUTOMAKE([foreign dist-bzip2])

# Require X.Org macros 1.8 or later for MAN_SUBSTS set by XORG_MANPAGE_SECTIONS
m4_ifndef([XORG_MACROS_VERSION],
          [m4_fatal([must install xorg-macros 1.8 or later before running autoconf/autogen])])
XORG_MACROS_VERSION(1.8)
XORG_DEFAULT_OPTIONS

# Initialize libtool
AC_DISABLE_STATIC
AC_PROG_LIBTOOL

# Checks for programs.
AM_PROG_CC_C_O

AH_TOP([#include "xorg-server.h"])

# Define a configure option for an alternate module directory
AC_ARG_WITH(xorg-module-dir,
            AS_HELP_STRING([--with-xorg-module-dir=DIR],
                           [Default xorg module directory [[default=$libdir/xorg/modules]]]),
            [moduledir="$withval"],
            [moduledir="$libdir/xorg/modules"])

# Define a configure option to build the vmwarectrl client tool
AC_ARG_ENABLE(vmwarectrl-client,
              AS_HELP_STRING([--enable-vmwarectrl-client],
                             [Enable vmwarectrl client (default: disabled)]),
                             [VMWARECTRL=$enableval], [VMWARECTRL=no])
AM_CONDITIONAL(BUILD_VMWARECTRL, [test "x$VMWARECTRL" = xyes])

# Store the list of server defined optional extensions in REQUIRED_MODULES
XORG_DRIVER_CHECK_EXT(RANDR, randrproto)
XORG_DRIVER_CHECK_EXT(RENDER, renderproto)
XORG_DRIVER_CHECK_EXT(DPMSExtension, xextproto)
XORG_DRIVER_CHECK_EXT(XINERAMA, xineramaproto)
XORG_DRIVER_CHECK_EXT(XV, videoproto)

# Obtain compiler/linker options for the driver dependencies
PKG_CHECK_MODULES(XORG, [xorg-server >= 1.0.1 xproto fontsproto $REQUIRED_MODULES])
PKG_CHECK_EXISTS([xorg-server >= 1.1.0],
                 [AC_DEFINE([HAVE_XORG_SERVER_1_1_0], 1,
                 [Has version 1.1.0 or greater of the Xserver])])

PKG_CHECK_EXISTS([xorg-server >= 1.2.0],
                 [AC_DEFINE([HAVE_XORG_SERVER_1_2_0], 1,
                 [Has version 1.2.0 or greater of the Xserver])])

PKG_CHECK_EXISTS([xorg-server >= 1.4.99],
                 [AC_DEFINE([HAVE_XORG_SERVER_1_5_0], 1,
                 [Has version 1.5.0 or greater of the Xserver])])

PKG_CHECK_EXISTS([xorg-server >= 1.7.0],
                 [AC_DEFINE([HAVE_XORG_SERVER_1_7_0], 1,
                 [Has version 1.7.0 or greater of the Xserver])
		 BUILD_VMWGFX=yes],[BUILD_VMWGFX=no])

PKG_CHECK_EXISTS([xorg-server >= 1.12.0],
                 [AC_DEFINE([HAVE_XORG_SERVER_1_12_0], 1,
                 [Has version 1.12.0 or greater of the Xserver])])

# Obtain compiler/linker options for the vmwarectrl client tool
PKG_CHECK_MODULES(X11, x11 xext)

# Checks for libraries.

save_CFLAGS="$CFLAGS"
CFLAGS="$XORG_CFLAGS"
AC_CHECK_DECL(XSERVER_LIBPCIACCESS,
             [XSERVER_LIBPCIACCESS=yes], [XSERVER_LIBPCIACCESS=no],
             [#include "xorg-server.h"])
CFLAGS="$save_CFLAGS"

if test x$XSERVER_LIBPCIACCESS = xyes; then
	PKG_CHECK_MODULES([PCIACCESS], [pciaccess >= 0.8.0])
fi

AM_CONDITIONAL(XSERVER_LIBPCIACCESS, test "x$XSERVER_LIBPCIACCESS" = xyes)

AC_SUBST([moduledir])

if test x$BUILD_VMWGFX = xyes; then
	PKG_CHECK_MODULES([LIBDRM], [libdrm],[],[BUILD_VMWGFX=no])
fi
if test x$BUILD_VMWGFX = xyes; then
#
# Early versions of mesa 10 forgot to bump the XA major version number in
# the xa_tracker.h header
#
	PKG_CHECK_MODULES([XATRACKER], [xatracker >= 0.4.0],
			  [PKG_CHECK_EXISTS([xatracker = 2.0.0],
	                  [AC_DEFINE([HAVE_XA_2], 1,
               		  [Has version 2 of XA])])],
			  [BUILD_VMWGFX=no])
#
# Check for prime.
#
	PKG_CHECK_EXISTS([libdrm >= 2.4.38],
			 [AC_DEFINE([HAVE_LIBDRM_2_4_38], 1,
			 [Has version 2.4.38 or greater of libdrm])])
#
# Check for drmGetDeviceNameFromFd2. On linux we need
# 2.4.96 for compatibility with the standalone vmwgfx driver
#
	PKG_CHECK_EXISTS([libdrm >= 2.4.74],
			 [AC_DEFINE([HAVE_LIBDRM_2_4_74], 1,
			 [Has version 2.4.74 or greater of libdrm])])
	PKG_CHECK_EXISTS([libdrm >= 2.4.96],
			 [AC_DEFINE([HAVE_LIBDRM_2_4_96], 1,
			 [Has version 2.4.96 or greater of libdrm])])
fi

DRIVER_NAME=vmware
AC_SUBST([DRIVER_NAME])

AC_MSG_CHECKING([whether to build Kernel Mode Setting and 3D])
if test x$BUILD_VMWGFX = xyes; then
	AC_MSG_RESULT([yes])
        AC_DEFINE([BUILD_VMWGFX], 1, [Building the vmwgfx driver path])
	libudev_check=yes
	AC_ARG_WITH([libudev],
		[AS_HELP_STRING([--without-libudev],
			[Use to build without libudev on linux])],
			[if test x$withval = xno; then libudev_check=no; fi]
			[])
	if test $libudev_check != no; then
		PKG_CHECK_MODULES(LIBUDEV, [libudev],
					   [AC_DEFINE([HAVE_LIBUDEV], 1,
					   [Has libudev installed])],
					   []);
        fi
else
	AC_MSG_RESULT([no])
fi

AM_CONDITIONAL(BUILD_VMWGFX, test "x$BUILD_VMWGFX" = xyes)

AC_CONFIG_FILES([
                Makefile
                man/Makefile
                saa/Makefile
                vmwgfx/Makefile
                src/Makefile
                vmwarectrl/Makefile
])

AC_OUTPUT
07070100000006000041ED00000000000000000000000261A68E1200000000000000000000000000000000000000000000002000000000xf86-video-vmware-13.3.0+12/man07070100000007000081A400000000000000000000000161A68E1200000606000000000000000000000000000000000000002C00000000xf86-video-vmware-13.3.0+12/man/Makefile.am#
# Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
#
# Permission is hereby granted, free of charge, to any person obtaining a
# copy of this software and associated documentation files (the "Software"),
# to deal in the Software without restriction, including without limitation
# the rights to use, copy, modify, merge, publish, distribute, sublicense,
# and/or sell copies of the Software, and to permit persons to whom the
# Software is furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice (including the next
# paragraph) shall be included in all copies or substantial portions of the
# Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
# DEALINGS IN THE SOFTWARE.
# 

drivermandir = $(DRIVER_MAN_DIR)

driverman_PRE = @DRIVER_NAME@.man

driverman_DATA = $(driverman_PRE:man=@DRIVER_MAN_SUFFIX@)

EXTRA_DIST = @DRIVER_NAME@.man

CLEANFILES = $(driverman_DATA)


# String replacements in MAN_SUBSTS now come from xorg-macros.m4 via configure


SUFFIXES = .$(DRIVER_MAN_SUFFIX) .man

.man.$(DRIVER_MAN_SUFFIX):
	$(AM_V_GEN)$(SED) $(MAN_SUBSTS) < $< > $@
07070100000008000081A400000000000000000000000161A68E12000011C8000000000000000000000000000000000000002B00000000xf86-video-vmware-13.3.0+12/man/vmware.man.\" shorthand for double quote that works everywhere.
.ds q \N'34'
.TH VMWARE __drivermansuffix__ __vendorversion__
.SH NAME
vmware \- VMware SVGA video driver
.SH SYNOPSIS
.nf
.B "Section \*qDevice\*q"
.BI "  Identifier \*q"  devname \*q
.B  "  Driver \*qvmware\*q"
\ \ ...
.B EndSection
.fi
.SH DESCRIPTION
.B vmware 
is an __xservername__ driver for VMware virtual video cards. 
.SH MODESETTING, XINERAMA AND RANDR12
If the driver can connect to the \*qvmwgfx\*q kernel module on linux, it
will attempt to use kernel modesetting and will then also use RandR12 for
multiple output operation instead of Xinerama. The X server log or the
\*qxrandr\*q application can be used to determine whether RandR12 or Xinerama
is actually used.
.SH 3D ACCELERATION
If the driver can connect to the \*qvmwgfx\*q kernel module on linux, and
the Virtual Machine is set up to use 3D acceleration, the driver will try to
use Gallium3D XA to accelerate 3D operations. It will also by default enable
DRI, the Direct Rendering Infrastructure, primarily for accelerated OpenGL.
If 3D acceleration is available,
the driver will in addition provide an additional XVideo adaptor for textured
video. Gallium3D XA,\*libxatracker.so\*q and the accelerated OpenGL driver,
\*qvmwgfx_dri.so\*q is provided by the mesa distribution.
.SH CONFIGURATION DETAILS
Please refer to __xconfigfile__(__filemansuffix__) for general configuration
details.  This section only covers configuration details specific to this
driver.
.PP
The driver auto-detects the version of any virtual VMware SVGA adapter.
.PP
The following driver
.B Options
are supported:
.TP
.BI "Option \*qHWCursor\*q \*q" boolean \*q
Enable or disable the HW cursor.  Default: off.
.TP
.BI "Option \*qXinerama\*q \*q" boolean \*q
Disable or enable Xinerama support. Default: xinerama is enabled if the
hardware supports it.
.TP
.BI "Option \*qStaticXinerama\*q \*q" string \*q
Provide a static xinerama geometry that will be active at server startup
and will not be overridden at runtime.
The format is "Width1xHeight1+Xoffset1+Yoffset1;Width2xHeight2+Xoffset2+Yoffset2" and so on. Negative offsets are not supported. If the driver is using
RandR12, this option should be used to place and enable outputs at driver
startup time or else when VMware tools is not used for that purpose.
Also please see option \*qGuiLayout\*q.
.TP
.BI "Option \*qGuiLayout\*q \*q" string \*q
A synonym to option \*qStaticXinerama\*q, since the latter name is somewhat
misleading when RandR12 is favoured before Xinerarma.
.TP
.BI "Option \*qAddDefaultMode\*q \*q" boolean \*q
Provide a default mode with a resolution identical to the resolution of the
guest before the X server was started. The X server will thus try to start
without changing resolution. Default: on.
.TP
.BI "Option \*qRenderAccel\*q \*q" boolean \*q
Try to accelerate render operations if the operations are reading from
previously accelerated contents (3D or video). This option is needed for
3D support. Default: on if 3D acceleration is supported. Otherwise off.
.TP
.BI "Option \*qDRI\*q \*q" boolean \*q
Enable the Direct Rendering Infrastructure. Default: on if 3D acceleration is
supported and \*qRenderAccel\*q is enabled. Otherwise off.
.TP
.BI "Option \*qDirectPresents\*q \*q" boolean \*q
Speed up OpenGL swapbuffers by skipping a copy operation. This provides some
OpenGL swapbuffer speedups, but may cause performance
degradation and rendering errors when 3D contents is read back for mixing
with software rendered contents. Default: off.
.TP
.BI "Option \*qHwPresents\*q \*q" boolean \*q
This is a developer convenience option and should not be used by distros
or normal users. When enabled, it copies software rendered contents to a
3D surface before presenting it, so that the visible screen is always present
on a 3D surface. Default: off.
.TP
.BI "Option \*qRenderCheck\*q \*q" boolean \*q
This is a developer convenience option and should not be used by distros
or normal users. When enabled, it tries to use 3D acceleration for all
XRender operations where 3D acceleration is supported, resulting in a
considerable slowdown due to the increased number of readbacks of
accelerated contents from host to guest. This option is used to verify
that the accelerated Xrender paths works correctly with the "rendercheck"
application. Default: off.
.TP
.SH "SEE ALSO"
__xservername__(__appmansuffix__), __xconfigfile__(__filemansuffix__), Xserver(__appmansuffix__), X(__miscmansuffix__), xrandr(__appmansuffix__)
.SH AUTHORS
Copyright (c) 1999-2007 VMware, Inc.
07070100000009000041ED00000000000000000000000261A68E1200000000000000000000000000000000000000000000002000000000xf86-video-vmware-13.3.0+12/saa0707010000000A000081A400000000000000000000000161A68E120000010B000000000000000000000000000000000000002C00000000xf86-video-vmware-13.3.0+12/saa/Makefile.am
if BUILD_VMWGFX
noinst_LTLIBRARIES = libsaa.la

libsaa_la_CFLAGS = $(CWARNFLAGS) $(XORG_CFLAGS) -I$(top_srcdir)/src
libsaa_la_LDFLAGS = -static
libsaa_la_SOURCES = \
	saa.c \
	saa_pixmap.c \
	saa_unaccel.c \
	saa_priv.h \
	saa_render.c \
	saa_accel.c \
	saa.h
endif
0707010000000B000081A400000000000000000000000161A68E12000056F6000000000000000000000000000000000000002600000000xf86-video-vmware-13.3.0+12/saa/saa.c/*
 * Copyright © 2001 Keith Packard
 *
 * Partly based on code that is Copyright © The XFree86 Project Inc.
 *
 * Permission to use, copy, modify, distribute, and sell this software and its
 * documentation for any purpose is hereby granted without fee, provided that
 * the above copyright notice appear in all copies and that both that
 * copyright notice and this permission notice appear in supporting
 * documentation, and that the name of Keith Packard not be used in
 * advertising or publicity pertaining to distribution of the software without
 * specific, written prior permission.  Keith Packard makes no
 * representations about the suitability of this software for any purpose.  It
 * is provided "as is" without express or implied warranty.
 *
 * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
 * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR
 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
 * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
 * PERFORMANCE OF THIS SOFTWARE.
 */

/** @file
 * This file covers the initialization and teardown of SAA, and has various
 * functions not responsible for performing rendering, pixmap migration, or
 * memory management.
 */

#ifdef HAVE_DIX_CONFIG_H
#include <dix-config.h>
#endif

#include <stdlib.h>

#include "saa_priv.h"
#include <X11/fonts/fontstruct.h>
#include "regionstr.h"
#include "saa.h"
#include "saa_priv.h"

#ifdef SAA_DEVPRIVATEKEYREC
DevPrivateKeyRec saa_screen_index;
DevPrivateKeyRec saa_pixmap_index;
DevPrivateKeyRec saa_gc_index;
#else
int saa_screen_index = -1;
int saa_pixmap_index = -1;
int saa_gc_index = -1;
#endif

/**
 * saa_get_drawable_pixmap() returns a backing pixmap for a given drawable.
 *
 * @param pDrawable the drawable being requested.
 *
 * This function returns the backing pixmap for a drawable, whether it is a
 * redirected window, unredirected window, or already a pixmap.  Note that
 * coordinate translation is needed when drawing to the backing pixmap of a
 * redirected window, and the translation coordinates are provided by calling
 * saa_get_drawable_pixmap() on the drawable.
 */
PixmapPtr
saa_get_drawable_pixmap(DrawablePtr pDrawable)
{
    if (pDrawable->type == DRAWABLE_WINDOW)
	return pDrawable->pScreen->GetWindowPixmap((WindowPtr) pDrawable);
    else
	return (PixmapPtr) pDrawable;
}

/**
 * Sets the offsets to add to coordinates to make them address the same bits in
 * the backing drawable. These coordinates are nonzero only for redirected
 * windows.
 */
void
saa_get_drawable_deltas(DrawablePtr pDrawable, PixmapPtr pPixmap,
			int *xp, int *yp)
{
#ifdef COMPOSITE
    if (pDrawable->type == DRAWABLE_WINDOW) {
	*xp = -pPixmap->screen_x;
	*yp = -pPixmap->screen_y;
	return;
    }
#endif

    *xp = 0;
    *yp = 0;
}

/**
 * Returns the pixmap which backs a drawable, and the offsets to add to
 * coordinates to make them address the same bits in the backing drawable.
 */
PixmapPtr
saa_get_pixmap(DrawablePtr drawable, int *xp, int *yp)
{
    PixmapPtr pixmap = saa_get_drawable_pixmap(drawable);

    saa_get_drawable_deltas(drawable, pixmap, xp, yp);

    return pixmap;
}

static Bool
saa_download_from_hw(PixmapPtr pix, RegionPtr readback)
{
    struct saa_screen_priv *sscreen = saa_screen(pix->drawable.pScreen);
    struct saa_driver *driver = sscreen->driver;
    struct saa_pixmap *spix = saa_pixmap(pix);
    void *addr;
    Bool ret;

    if (spix->mapped_access)
	driver->release_from_cpu(driver, pix, spix->mapped_access);

    ret = driver->download_from_hw(driver, pix, readback);

    if (spix->mapped_access) {
	addr = driver->sync_for_cpu(driver, pix, spix->mapped_access);
	if (addr != NULL)
	    spix->addr = addr;
    }

    return ret;
}

Bool
saa_prepare_access_pixmap(PixmapPtr pix, saa_access_t access,
			  RegionPtr read_reg)
{
    ScreenPtr pScreen = pix->drawable.pScreen;
    struct saa_screen_priv *sscreen = saa_screen(pScreen);
    struct saa_driver *driver = sscreen->driver;
    struct saa_pixmap *spix = saa_pixmap(pix);
    saa_access_t map_access = 0;
    Bool ret = TRUE;

    if (read_reg && REGION_NOTEMPTY(pScreen, read_reg))
	ret = saa_download_from_hw(pix, read_reg);

    if (!ret) {
	LogMessage(X_ERROR, "Prepare access pixmap failed.\n");
	return ret;
    }

    if ((access & SAA_ACCESS_R) != 0 && spix->read_access++ == 0)
	map_access = SAA_ACCESS_R;
    if ((access & SAA_ACCESS_W) != 0 && spix->write_access++ == 0)
	map_access |= SAA_ACCESS_W;

    if (map_access) {
	if (spix->auth_loc != saa_loc_override) {
	    (void)driver->sync_for_cpu(driver, pix, map_access);
	    spix->addr = driver->map(driver, pix, map_access);
	} else
	    spix->addr = spix->override;
	spix->mapped_access |= map_access;
    }

    pix->devPrivate.ptr = spix->addr;
    return TRUE;
}

void
saa_finish_access_pixmap(PixmapPtr pix, saa_access_t access)
{
    struct saa_screen_priv *sscreen = saa_screen(pix->drawable.pScreen);
    struct saa_driver *driver = sscreen->driver;
    struct saa_pixmap *spix = saa_pixmap(pix);
    saa_access_t unmap_access = 0;

    if ((access & SAA_ACCESS_R) != 0 && --spix->read_access == 0)
	unmap_access = SAA_ACCESS_R;
    if ((access & SAA_ACCESS_W) != 0 && --spix->write_access == 0)
	unmap_access |= SAA_ACCESS_W;

    if (spix->read_access < 0)
	LogMessage(X_ERROR, "Incorrect read access.\n");
    if (spix->write_access < 0)
	LogMessage(X_ERROR, "Incorrect write access.\n");

    if (unmap_access) {
	if (spix->auth_loc != saa_loc_override) {
	    driver->unmap(driver, pix, unmap_access);
	    driver->release_from_cpu(driver, pix, unmap_access);
	}
	spix->mapped_access &= ~unmap_access;
    }
    if (!spix->mapped_access) {
	spix->addr = NULL;
	pix->devPrivate.ptr = SAA_INVALID_ADDRESS;
    }
}

/*
 * Callback that is called after a rendering operation. We try to
 * determine whether it's a shadow damage or a hw damage and call the
 * driver callback.
 */

static void
saa_report_damage(DamagePtr damage, RegionPtr reg, void *closure)
{
    PixmapPtr pixmap = (PixmapPtr) closure;
    struct saa_pixmap *spix = saa_get_saa_pixmap(pixmap);
    struct saa_driver *driver = saa_screen(pixmap->drawable.pScreen)->driver;

    if (spix->read_access || spix->write_access)
	LogMessage(X_ERROR, "Damage report inside prepare access.\n");

    driver->operation_complete(driver, pixmap);
    DamageEmpty(damage);
}

/**
 * saa_notify_destroy_damage - Handle destroy damage notification
 *
 * \param damage[in] damage Pointer to damage about to be destroyed
 * \param closure[in] closure Closure.
 *
 * Makes sure that whatever code destroys a damage object clears the
 * saa_pixmap damage pointer. This is extra protection. Typically
 * saa_destroy_pixmap should be correct if the various subsystem
 * DestroyPixmap functions are called in the right order.
 */
static void
saa_notify_destroy_damage(DamagePtr damage, void *closure)
{
    PixmapPtr pixmap = (PixmapPtr) closure;
    struct saa_pixmap *spix = saa_get_saa_pixmap(pixmap);

    if (spix->damage == damage)
	spix->damage = NULL;
}

Bool
saa_add_damage(PixmapPtr pixmap)
{
    ScreenPtr pScreen = pixmap->drawable.pScreen;
    struct saa_pixmap *spix = saa_get_saa_pixmap(pixmap);

    if (spix->damage)
	return TRUE;

    spix->damage = DamageCreate(saa_report_damage, saa_notify_destroy_damage,
				DamageReportRawRegion, TRUE, pScreen, pixmap);
    if (!spix->damage)
	return FALSE;

    DamageRegister(&pixmap->drawable, spix->damage);
    DamageSetReportAfterOp(spix->damage, TRUE);

    return TRUE;
}

static inline RegionPtr
saa_pix_damage_region(struct saa_pixmap *spix)
{
    return (spix->damage ? DamageRegion(spix->damage) : NULL);
}

Bool
saa_pad_read(DrawablePtr draw)
{
    ScreenPtr pScreen = draw->pScreen;
    PixmapPtr pix;
    int xp;
    int yp;
    BoxRec box;
    RegionRec entire;
    Bool ret;

    (void)pScreen;
    pix = saa_get_pixmap(draw, &xp, &yp);

    box.x1 = draw->x + xp;
    box.y1 = draw->y + yp;
    box.x2 = box.x1 + draw->width;
    box.y2 = box.y1 + draw->height;

    REGION_INIT(pScreen, &entire, &box, 1);
    ret = saa_prepare_access_pixmap(pix, SAA_ACCESS_R, &entire);
    REGION_UNINIT(pScreen, &entire);
    return ret;
}

Bool
saa_pad_read_box(DrawablePtr draw, int x, int y, int w, int h)
{
    ScreenPtr pScreen = draw->pScreen;
    PixmapPtr pix;
    int xp;
    int yp;
    BoxRec box;
    RegionRec entire;
    Bool ret;

    (void)pScreen;
    pix = saa_get_pixmap(draw, &xp, &yp);

    box.x1 = x + xp;
    box.y1 = y + yp;
    box.x2 = box.x1 + w;
    box.y2 = box.y1 + h;

    REGION_INIT(pScreen, &entire, &box, 1);
    ret = saa_prepare_access_pixmap(pix, SAA_ACCESS_R, &entire);
    REGION_UNINIT(pScreen, &entire);
    return ret;
}

/**
 * Prepares a drawable destination for access, and maps it read-write.
 * If check_read is TRUE, pGC should point to a valid GC. The drawable
 * may then be mapped write-only if the pending operation admits.
 */

Bool
saa_pad_write(DrawablePtr draw, GCPtr pGC, Bool check_read,
	      saa_access_t * access)
{
    int xp;
    int yp;
    PixmapPtr pixmap = saa_get_pixmap(draw, &xp, &yp);
    struct saa_pixmap *spix = saa_pixmap(pixmap);

    *access = SAA_ACCESS_W;

    /*
     * If the to-be-damaged area doesn't depend at all on previous
     * rendered contents, we don't need to do any readback.
     */

    if (check_read && !saa_gc_reads_destination(draw, pGC))
	return saa_prepare_access_pixmap(pixmap, *access, NULL);

    *access |= SAA_ACCESS_R;

    /*
     * Read back the area to be damaged.
     */

    return saa_prepare_access_pixmap(pixmap, *access,
				     saa_pix_damage_pending(spix));
}

void
saa_fad_read(DrawablePtr draw)
{
    saa_finish_access_pixmap(saa_get_drawable_pixmap(draw), SAA_ACCESS_R);
}

void
saa_fad_write(DrawablePtr draw, saa_access_t access)
{
    PixmapPtr pix = saa_get_drawable_pixmap(draw);
    struct saa_pixmap *spix = saa_pixmap(pix);

    saa_finish_access_pixmap(pix, access);
    if (spix->damage)
	saa_pixmap_dirty(pix, FALSE, saa_pix_damage_pending(spix));
}

Bool
saa_gc_reads_destination(DrawablePtr pDrawable, GCPtr pGC)
{
    return ((pGC->alu != GXcopy && pGC->alu != GXclear && pGC->alu != GXset &&
	     pGC->alu != GXcopyInverted) || pGC->fillStyle == FillStippled ||
	    pGC->clientClip != NULL ||
	    !SAA_PM_IS_SOLID(pDrawable, pGC->planemask));
}

Bool
saa_op_reads_destination(CARD8 op)
{
    /* FALSE (does not read destination) is the list of ops in the protocol
     * document with "0" in the "Fb" column and no "Ab" in the "Fa" column.
     * That's just Clear and Src.  ReduceCompositeOp() will already have
     * converted con/disjoint clear/src to Clear or Src.
     */
    switch (op) {
    case PictOpClear:
    case PictOpSrc:
	return FALSE;
    default:
	return TRUE;
    }
}

static void
saa_validate_gc(GCPtr pGC, unsigned long changes, DrawablePtr pDrawable)
{
    /* fbValidateGC will do direct access to pixmaps if the tiling has changed.
     * Do a few smart things so fbValidateGC can do it's work.
     */

    ScreenPtr pScreen = pDrawable->pScreen;
    struct saa_screen_priv *sscreen = saa_screen(pScreen);
    struct saa_gc_priv *sgc = saa_gc(pGC);
    PixmapPtr pTile = NULL;
    Bool finish_current_tile = FALSE;

    /* Either of these conditions is enough to trigger access to a tile pixmap. */
    /* With pGC->tileIsPixel == 1, you run the risk of dereferencing an invalid tile pixmap pointer. */
    if (pGC->fillStyle == FillTiled
	|| ((changes & GCTile) && !pGC->tileIsPixel)) {
	pTile = pGC->tile.pixmap;

	/* Sometimes tile pixmaps are swapped, you need access to:
	 * - The current tile if it depth matches.
	 * - Or the rotated tile if that one matches depth and !(changes & GCTile).
	 * - Or the current tile pixmap and a newly created one.
	 */
	if (pTile && pTile->drawable.depth != pDrawable->depth
	    && !(changes & GCTile)) {
	    PixmapPtr pRotatedTile = fbGetRotatedPixmap(pGC);

	    if (pRotatedTile
		&& pRotatedTile->drawable.depth == pDrawable->depth)
		pTile = pRotatedTile;
	    else
		finish_current_tile = TRUE;	/* CreatePixmap will be called. */
	}
    }

    if (pGC->stipple && !saa_pad_read(&pGC->stipple->drawable)) {
	LogMessage(X_ERROR, "Failed stipple prepareaccess.\n");
	return;
    }

    if (pTile && !saa_pad_read(&pTile->drawable)) {
	LogMessage(X_ERROR, "Failed stipple prepareaccess.\n");
	goto out_no_tile;
    }

    /* Calls to Create/DestroyPixmap have to be identified as special, so
     * up sscreen->fallback_count.
     */

    sscreen->fallback_count++;
    saa_swap(sgc, pGC, funcs);
    (*pGC->funcs->ValidateGC) (pGC, changes, pDrawable);
    saa_swap(sgc, pGC, funcs);

    if (finish_current_tile && pGC->tile.pixmap)
	saa_fad_write(&pGC->tile.pixmap->drawable, SAA_ACCESS_W);
    sscreen->fallback_count--;

    if (pTile)
	saa_fad_read(&pTile->drawable);
 out_no_tile:
    if (pGC->stipple)
	saa_fad_read(&pGC->stipple->drawable);
}

static void
saa_destroy_gc(GCPtr pGC)
{
    struct saa_gc_priv *sgc = saa_gc(pGC);

    saa_swap(sgc, pGC, funcs);
    (*pGC->funcs->DestroyGC) (pGC);
    saa_swap(sgc, pGC, funcs);
}

static void
saa_change_gc(GCPtr pGC, unsigned long mask)
{
    struct saa_gc_priv *sgc = saa_gc(pGC);

    saa_swap(sgc, pGC, funcs);
    (*pGC->funcs->ChangeGC) (pGC, mask);
    saa_swap(sgc, pGC, funcs);
}

static void
saa_copy_gc(GCPtr pGCSrc, unsigned long mask, GCPtr pGCDst)
{
    struct saa_gc_priv *sgc = saa_gc(pGCDst);

    saa_swap(sgc, pGCDst, funcs);
    (*pGCDst->funcs->CopyGC) (pGCSrc, mask, pGCDst);
    saa_swap(sgc, pGCDst, funcs);
}

static void
saa_change_clip(GCPtr pGC, int type, pointer pvalue, int nrects)
{
    struct saa_gc_priv *sgc = saa_gc(pGC);

    saa_swap(sgc, pGC, funcs);
    (*pGC->funcs->ChangeClip) (pGC, type, pvalue, nrects);
    saa_swap(sgc, pGC, funcs);
}

static void
saa_copy_clip(GCPtr pGCDst, GCPtr pGCSrc)
{
    struct saa_gc_priv *sgc = saa_gc(pGCDst);

    saa_swap(sgc, pGCDst, funcs);
    (*pGCDst->funcs->CopyClip) (pGCDst, pGCSrc);
    saa_swap(sgc, pGCDst, funcs);
}

static void
saa_destroy_clip(GCPtr pGC)
{
    struct saa_gc_priv *sgc = saa_gc(pGC);

    saa_swap(sgc, pGC, funcs);
    (*pGC->funcs->DestroyClip) (pGC);
    saa_swap(sgc, pGC, funcs);
}

static GCFuncs saa_gc_funcs = {
    saa_validate_gc,
    saa_change_gc,
    saa_copy_gc,
    saa_destroy_gc,
    saa_change_clip,
    saa_destroy_clip,
    saa_copy_clip
};

/**
 * saa_create_gc makes a new GC and hooks up its funcs handler, so that
 * saa_validate_gc() will get called.
 */
int
saa_create_gc(GCPtr pGC)
{
    ScreenPtr pScreen = pGC->pScreen;
    struct saa_screen_priv *sscreen = saa_screen(pScreen);
    struct saa_gc_priv *sgc = saa_gc(pGC);
    Bool ret;

    saa_swap(sscreen, pScreen, CreateGC);
    ret = pScreen->CreateGC(pGC);
    if (ret) {
	saa_wrap(sgc, pGC, funcs, &saa_gc_funcs);
	saa_wrap(sgc, pGC, ops, &saa_gc_ops);
    }
    saa_swap(sscreen, pScreen, CreateGC);

    return ret;
}

static Bool
saa_prepare_access_window(WindowPtr pWin)
{
    if (pWin->backgroundState == BackgroundPixmap) {
	if (!saa_pad_read(&pWin->background.pixmap->drawable))
	    return FALSE;
    }

    if (pWin->borderIsPixel == FALSE) {
	if (!saa_pad_read(&pWin->border.pixmap->drawable)) {
	    if (pWin->backgroundState == BackgroundPixmap)
		saa_fad_read(&pWin->background.pixmap->drawable);
	    return FALSE;
	}
    }
    return TRUE;
}

static void
saa_finish_access_window(WindowPtr pWin)
{
    if (pWin->backgroundState == BackgroundPixmap)
	saa_fad_read(&pWin->background.pixmap->drawable);

    if (pWin->borderIsPixel == FALSE)
	saa_fad_read(&pWin->border.pixmap->drawable);
}

static Bool
saa_change_window_attributes(WindowPtr pWin, unsigned long mask)
{
    Bool ret;

    if (!saa_prepare_access_window(pWin))
	return FALSE;
    ret = fbChangeWindowAttributes(pWin, mask);
    saa_finish_access_window(pWin);
    return ret;
}

RegionPtr
saa_bitmap_to_region(PixmapPtr pPix)
{
    RegionPtr ret;

    if (!saa_pad_read(&pPix->drawable))
	return NULL;
    ret = fbPixmapToRegion(pPix);
    saa_fad_read(&pPix->drawable);
    return ret;
}

void
saa_set_fallback_debug(ScreenPtr screen, Bool enable)
{
    struct saa_screen_priv *sscreen = saa_screen(screen);

    sscreen->fallback_debug = enable;
}

/**
 * saa_early_close_screen() Makes sure we call saa_destroy_pixmap on the
 * miScreenInit() pixmap _before_ damageCloseScreen, after which it will
 * generate an invalid memory access. Also unwraps the functions we
 * wrapped _after_ DamageSetup().
 */
static Bool
saa_early_close_screen(CLOSE_SCREEN_ARGS_DECL)
{
    struct saa_screen_priv *sscreen = saa_screen(pScreen);

    if (pScreen->devPrivate) {
	/* Destroy the pixmap created by miScreenInit() *before*
	 * chaining up as we finalize ourselves here and so this
	 * is the last chance we have of releasing our resources
	 * associated with the Pixmap. So do it first.
	 */
	(void)(*pScreen->DestroyPixmap) (pScreen->devPrivate);
	pScreen->devPrivate = NULL;
    }

    saa_unwrap_early(sscreen, pScreen, CloseScreen);
    saa_unwrap(sscreen, pScreen, DestroyPixmap);

    return (*pScreen->CloseScreen) (CLOSE_SCREEN_ARGS);
}

/**
 * saa_close_screen() unwraps its wrapped screen functions and tears down SAA's
 * screen private, before calling down to the next CloseScreen.
 */
Bool
saa_close_screen(CLOSE_SCREEN_ARGS_DECL)
{
    struct saa_screen_priv *sscreen = saa_screen(pScreen);
    struct saa_driver *driver = sscreen->driver;

    saa_unwrap(sscreen, pScreen, CloseScreen);
    saa_unwrap(sscreen, pScreen, CreateGC);
    saa_unwrap(sscreen, pScreen, ChangeWindowAttributes);
    saa_unwrap(sscreen, pScreen, CreatePixmap);
    saa_unwrap(sscreen, pScreen, ModifyPixmapHeader);
    saa_unwrap(sscreen, pScreen, BitmapToRegion);
#ifdef RENDER
    saa_render_takedown(pScreen);
#endif
    saa_unaccel_takedown(pScreen);
    driver->takedown(driver);

    free(sscreen);

    return (*pScreen->CloseScreen) (CLOSE_SCREEN_ARGS);
}

struct saa_driver *
saa_get_driver(ScreenPtr pScreen)
{
    return saa_screen(pScreen)->driver;
}

/**
 * @param pScreen screen being initialized
 * @param pScreenInfo SAA driver record
 *
 * saa_driver_init sets up SAA given a driver record filled in by the driver.
 * pScreenInfo should have been allocated by saa_driver_alloc().  See the
 * comments in _SaaDriver for what must be filled in and what is optional.
 *
 * @return TRUE if SAA was successfully initialized.
 */
Bool
saa_driver_init(ScreenPtr screen, struct saa_driver * saa_driver)
{
    struct saa_screen_priv *sscreen;

    if (!saa_driver)
	return FALSE;

    if (saa_driver->saa_major != SAA_VERSION_MAJOR ||
	saa_driver->saa_minor > SAA_VERSION_MINOR) {
	LogMessage(X_ERROR,
		   "SAA(%d): driver's SAA version requirements "
		   "(%d.%d) are incompatible with SAA version (%d.%d)\n",
		   screen->myNum, saa_driver->saa_major,
		   saa_driver->saa_minor, SAA_VERSION_MAJOR, SAA_VERSION_MINOR);
	return FALSE;
    }
#if 0
    if (!saa_driver->prepare_solid) {
	LogMessage(X_ERROR,
		   "SAA(%d): saa_driver_t::prepare_solid must be "
		   "non-NULL\n", screen->myNum);
	return FALSE;
    }

    if (!saa_driver->prepare_copy) {
	LogMessage(X_ERROR,
		   "SAA(%d): saa_driver_t::prepare_copy must be "
		   "non-NULL\n", screen->myNum);
	return FALSE;
    }
#endif
#ifdef SAA_DEVPRIVATEKEYREC
    if (!dixRegisterPrivateKey(&saa_screen_index, PRIVATE_SCREEN, 0)) {
	LogMessage(X_ERROR, "Failed to register SAA screen private.\n");
	return FALSE;
    }
    if (!dixRegisterPrivateKey(&saa_pixmap_index, PRIVATE_PIXMAP,
			       saa_driver->pixmap_size)) {
	LogMessage(X_ERROR, "Failed to register SAA pixmap private.\n");
	return FALSE;
    }
    if (!dixRegisterPrivateKey(&saa_gc_index, PRIVATE_GC,
			       sizeof(struct saa_gc_priv))) {
	LogMessage(X_ERROR, "Failed to register SAA gc private.\n");
	return FALSE;
    }
#else
    if (!dixRequestPrivate(&saa_screen_index, 0)) {
	LogMessage(X_ERROR, "Failed to register SAA screen private.\n");
	return FALSE;
    }
    if (!dixRequestPrivate(&saa_pixmap_index, saa_driver->pixmap_size)) {
	LogMessage(X_ERROR, "Failed to register SAA pixmap private.\n");
	return FALSE;
    }
    if (!dixRequestPrivate(&saa_gc_index, sizeof(struct saa_gc_priv))) {
	LogMessage(X_ERROR, "Failed to register SAA gc private.\n");
	return FALSE;
    }
#endif

    sscreen = calloc(1, sizeof(*sscreen));

    if (!sscreen) {
	LogMessage(X_WARNING,
		   "SAA(%d): Failed to allocate screen private\n",
		   screen->myNum);
	return FALSE;
    }

    sscreen->driver = saa_driver;
    dixSetPrivate(&screen->devPrivates, &saa_screen_index, sscreen);

    /*
     * Replace various fb screen functions
     */

    saa_wrap(sscreen, screen, CloseScreen, saa_close_screen);
    saa_wrap(sscreen, screen, CreateGC, saa_create_gc);
    saa_wrap(sscreen, screen, ChangeWindowAttributes,
	     saa_change_window_attributes);
    saa_wrap(sscreen, screen, CreatePixmap, saa_create_pixmap);
    saa_wrap(sscreen, screen, ModifyPixmapHeader, saa_modify_pixmap_header);
    saa_wrap(sscreen, screen, BitmapToRegion, saa_bitmap_to_region);
    saa_unaccel_setup(screen);
#ifdef RENDER
    saa_render_setup(screen);
#endif

    /*
     * Correct saa functionality relies on Damage, so set it up now.
     * Note that this must happen _after_ wrapping the rendering functionality
     * so that damage happens outside of saa.
     */
    if (!DamageSetup(screen))
	return FALSE;

    /*
     * Wrap DestroyPixmap after DamageSetup, so that saa_destroy_pixmap is
     * called _before_ damageDestroyPixmap. This is to make damageDestroyPixmap
     * doesn't free objects pointed to by our damage pointers.
     *
     * Also wrap an early CloseScreen to perform actions needed to be done
     * before damageCloseScreen and to unwrap DestroyPixmap correctly.
     */
    saa_wrap(sscreen, screen, DestroyPixmap, saa_destroy_pixmap);
    saa_wrap_early(sscreen, screen, CloseScreen, saa_early_close_screen);

    return TRUE;
}

Bool
saa_resources_init(ScreenPtr screen)
{
/*    if (!saa_glyphs_init(screen))
	return FALSE;
*/
    return TRUE;
}
0707010000000C000081A400000000000000000000000161A68E1200001959000000000000000000000000000000000000002600000000xf86-video-vmware-13.3.0+12/saa/saa.h/*
 *
 * Copyright (C) 2000 Keith Packard
 *               2004 Eric Anholt
 *               2005 Zack Rusin
 *
 * Copyright 2011 VMWare, Inc. All rights reserved.
 *
 * Permission to use, copy, modify, distribute, and sell this software and its
 * documentation for any purpose is hereby granted without fee, provided that
 * the above copyright notice appear in all copies and that both that
 * copyright notice and this permission notice appear in supporting
 * documentation, and that the name of copyright holders not be used in
 * advertising or publicity pertaining to distribution of the software without
 * specific, written prior permission. Copyright holders make no
 * representations about the suitability of this software for any purpose.  It
 * is provided "as is" without express or implied warranty.
 *
 * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS
 * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
 * FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY
 * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
 * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
 * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
 * SOFTWARE.
 *
 * Author: Based on "exa.h"
 * Author: Thomas Hellstrom <thellstrom@vmware.com>
 */

#ifndef _SAA_H_
#define _SAA_H_

#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#ifdef HAVE_DIX_CONFIG_H
#include <dix-config.h>
#else
#include <xorg-server.h>
#endif
#include <xf86.h>
#include <damage.h>
#include <picturestr.h>

#include "../src/compat-api.h"

#define SAA_VERSION_MAJOR 0
#define SAA_VERSION_MINOR 1

#define SAA_ACCESS_R (1 << 0)
#define SAA_ACCESS_W (1 << 1)
#define SAA_ACCESS_RW (SAA_ACCESS_R | SAA_ACCESS_W)

#define SAA_PIXMAP_HINT_CREATE_HW (1 << 25)
#define SAA_PIXMAP_PREFER_SHADOW  (1 << 0)

typedef unsigned int saa_access_t;

enum saa_pixmap_loc {
    saa_loc_driver,
    saa_loc_override,
};

struct saa_pixmap {
    PixmapPtr pixmap;
    int read_access;
    int write_access;
    unsigned int mapped_access;
    Bool fallback_created;
    RegionRec dirty_shadow;
    RegionRec dirty_hw;
    RegionRec shadow_damage;
    DamagePtr damage;
    void *addr;
    void *override;
    enum saa_pixmap_loc auth_loc;
    PictFormatShort src_format;
    PictFormatShort dst_format;
    uint32_t pad[16];
};

struct saa_driver {
    unsigned int saa_major;
    unsigned int saa_minor;
    size_t pixmap_size;
     Bool(*damage) (struct saa_driver * driver, PixmapPtr pixmap,
		    Bool hw, RegionPtr damage);
    void (*operation_complete) (struct saa_driver * driver, PixmapPtr pixmap);
     Bool(*download_from_hw) (struct saa_driver * driver, PixmapPtr pixmap,
			      RegionPtr readback);
    void (*release_from_cpu) (struct saa_driver * driver, PixmapPtr pixmap,
			      saa_access_t access);
    void *(*sync_for_cpu) (struct saa_driver * driver, PixmapPtr pixmap,
			   saa_access_t access);
    void *(*map) (struct saa_driver * driver, PixmapPtr pixmap,
		  saa_access_t access);
    void (*unmap) (struct saa_driver * driver, PixmapPtr pixmap,
		   saa_access_t access);
     Bool(*create_pixmap) (struct saa_driver * driver, struct saa_pixmap * spix,
			   int w, int h, int depth, unsigned int usage_hint,
			   int bpp, int *new_pitch);
    void (*destroy_pixmap) (struct saa_driver * driver, PixmapPtr pixmap);
    Bool (*modify_pixmap_header) (PixmapPtr pixmap, int w, int h, int depth,
				  int bpp, int devkind, void *pPixData);

    Bool (*copy_prepare) (struct saa_driver * driver, PixmapPtr src_pixmap,
			 PixmapPtr dst_pixmap, int dx, int dy, int alu,
			 RegionPtr scr_reg, uint32_t plane_mask);
    void (*copy) (struct saa_driver * driver, int src_x, int src_y, int dst_x,
		  int dst_y, int w, int h);
    void (*copy_done) (struct saa_driver * driver);
    Bool (*composite_prepare) (struct saa_driver *driver, CARD8 op,
			       PicturePtr src_pict, PicturePtr mask_pict,
			       PicturePtr dst_pict,
			       PixmapPtr src_pix, PixmapPtr mask_pix,
			       PixmapPtr dst_pix,
			       RegionPtr src_region,
			       RegionPtr mask_region,
			       RegionPtr dst_region);
    void (*composite) (struct saa_driver *driver,
		       int src_x, int src_y, int mask_x, int mask_y,
		       int dst_x, int dst_y,
		       int width, int height);
    void (*composite_done) (struct saa_driver *driver);

    void (*takedown) (struct saa_driver * driver);
    uint32_t pad[16];
};

extern _X_EXPORT PixmapPtr
saa_get_drawable_pixmap(DrawablePtr pDrawable);

extern _X_EXPORT void
saa_get_drawable_deltas(DrawablePtr pDrawable, PixmapPtr pPixmap,
			int *xp, int *yp);

extern _X_EXPORT PixmapPtr
saa_get_pixmap(DrawablePtr drawable, int *xp, int *yp);

extern _X_EXPORT Bool
saa_prepare_access_pixmap(PixmapPtr pix, saa_access_t access,
			  RegionPtr read_reg);

extern _X_EXPORT Bool
saa_pad_read(DrawablePtr draw);

Bool
saa_pad_read_box(DrawablePtr draw, int x, int y, int w, int h);

extern _X_EXPORT Bool
saa_pad_write(DrawablePtr draw, GCPtr pGC, Bool check_read,
	      saa_access_t * access);

extern _X_EXPORT void
saa_finish_access_pixmap(PixmapPtr pix, saa_access_t access);

extern _X_EXPORT void
saa_fad_read(DrawablePtr draw);

extern _X_EXPORT void
saa_fad_write(DrawablePtr draw, saa_access_t access);

extern _X_EXPORT Bool
saa_resources_init(ScreenPtr screen);

extern _X_EXPORT void
saa_driver_fini(ScreenPtr pScreen);

extern _X_EXPORT int
saa_create_gc(GCPtr pGC);

extern _X_EXPORT RegionPtr
saa_bitmap_to_region(PixmapPtr pPix);

extern _X_EXPORT Bool
saa_close_screen(CLOSE_SCREEN_ARGS_DECL);

extern _X_EXPORT Bool
saa_gc_reads_destination(DrawablePtr pDrawable, GCPtr pGC);

extern _X_EXPORT Bool
saa_op_reads_destination(CARD8 op);

extern _X_EXPORT void
saa_set_fallback_debug(ScreenPtr screen, Bool enable);

extern _X_EXPORT
struct saa_pixmap *saa_get_saa_pixmap(PixmapPtr pPixmap);

extern _X_EXPORT Bool
saa_add_damage(PixmapPtr pixmap);

extern _X_EXPORT struct saa_driver *
saa_get_driver(ScreenPtr pScreen);

extern _X_EXPORT Bool
saa_driver_init(ScreenPtr screen, struct saa_driver *saa_driver);

extern _X_EXPORT void
saa_pixmap_dirty(PixmapPtr pixmap, Bool hw, RegionPtr reg);

extern _X_EXPORT void
saa_drawable_dirty(DrawablePtr draw, Bool hw, RegionPtr reg);

#define SAA_PM_IS_SOLID(_pDrawable, _pm) \
  (((_pm) & FbFullMask((_pDrawable)->depth)) == \
   FbFullMask((_pDrawable)->depth))

#endif
0707010000000D000081A400000000000000000000000161A68E12000012F6000000000000000000000000000000000000002C00000000xf86-video-vmware-13.3.0+12/saa/saa_accel.c/*
 * Copyright © 2001 Keith Packard
 * Copyright 2011 VMWare, Inc. All Rights Reserved.
 * May partly be based on code that is Copyright © The XFree86 Project 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, 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: Eric Anholt <eric@anholt.net>
 * Author: Michel Dänzer <michel@tungstengraphics.com>
 * Author: Thomas Hellstrom <thellstrom@vmware.com>
 */

#include "saa.h"
#include "saa_priv.h"
#include <mi.h>

Bool
saa_hw_copy_nton(DrawablePtr pSrcDrawable,
		 DrawablePtr pDstDrawable,
		 GCPtr pGC,
		 BoxPtr pbox,
		 int nbox, int dx, int dy, Bool reverse, Bool upsidedown)
{
    ScreenPtr pScreen = pDstDrawable->pScreen;
    struct saa_screen_priv *sscreen = saa_screen(pDstDrawable->pScreen);
    struct saa_driver *driver = sscreen->driver;
    PixmapPtr pSrcPixmap, pDstPixmap;
    struct saa_pixmap *src_spix, *dst_spix;
    int src_off_x, src_off_y;
    int dst_off_x, dst_off_y;
    RegionRec dst_reg, *src_reg;
    int ordering;
    Bool ret = TRUE;

    (void)pScreen;

    /* avoid doing copy operations if no boxes */
    if (nbox == 0)
	return TRUE;

    pSrcPixmap = saa_get_pixmap(pSrcDrawable, &src_off_x, &src_off_y);
    pDstPixmap = saa_get_pixmap(pDstDrawable, &dst_off_x, &dst_off_y);
    src_spix = saa_pixmap(pSrcPixmap);
    dst_spix = saa_pixmap(pDstPixmap);

    if (src_spix->auth_loc != saa_loc_driver ||
	dst_spix->auth_loc != saa_loc_driver)
	return FALSE;


    ordering = (nbox == 1 || (dx > 0 && dy > 0) ||
		(pDstDrawable != pSrcDrawable &&
		 (pDstDrawable->type != DRAWABLE_WINDOW ||
		  pSrcDrawable->type != DRAWABLE_WINDOW))) ?
	CT_YXBANDED : CT_UNSORTED;

    src_reg = saa_boxes_to_region(pScreen, nbox, pbox, ordering);
    if (!src_reg)
	return FALSE;

    REGION_NULL(pScreen, &dst_reg);
    REGION_COPY(pScreen, &dst_reg, src_reg);
    REGION_TRANSLATE(pScreen, src_reg, dx + src_off_x, dy + src_off_y);
    REGION_TRANSLATE(pScreen, &dst_reg, dst_off_x, dst_off_y);

    if (!(driver->copy_prepare) (driver, pSrcPixmap, pDstPixmap,
				 reverse ? -1 : 1,
				 upsidedown ? -1 : 1,
				 pGC ? pGC->alu : GXcopy,
				 src_reg, pGC ? pGC->planemask : FB_ALLONES)) {
	goto fallback;
    }

    while (nbox--) {
	(driver->copy) (driver,
			pbox->x1 + dx + src_off_x,
			pbox->y1 + dy + src_off_y,
			pbox->x1 + dst_off_x, pbox->y1 + dst_off_y,
			pbox->x2 - pbox->x1, pbox->y2 - pbox->y1);
	pbox++;
    }

    (driver->copy_done) (driver);
    saa_pixmap_dirty(pDstPixmap, TRUE, &dst_reg);
    goto out;

 fallback:
    ret = FALSE;

 out:
    REGION_UNINIT(pScreen, &dst_reg);
    REGION_DESTROY(pScreen, src_reg);

    return ret;
}

static void
saa_copy_nton(DrawablePtr pSrcDrawable,
	      DrawablePtr pDstDrawable,
	      GCPtr pGC,
	      BoxPtr pbox,
	      int nbox,
	      int dx,
	      int dy,
	      Bool reverse, Bool upsidedown, Pixel bitplane, void *closure)
{
    if (saa_hw_copy_nton(pSrcDrawable, pDstDrawable, pGC, pbox, nbox, dx, dy,
			 reverse, upsidedown))
	return;

    saa_check_copy_nton(pSrcDrawable, pDstDrawable, pGC, pbox, nbox, dx, dy,
			reverse, upsidedown, bitplane, closure);
}

RegionPtr
saa_copy_area(DrawablePtr pSrcDrawable, DrawablePtr pDstDrawable, GCPtr pGC,
	      int srcx, int srcy, int width, int height, int dstx, int dsty)
{
    struct saa_screen_priv *sscreen = saa_screen(pDstDrawable->pScreen);

    if (sscreen->fallback_count) {
	return saa_check_copy_area(pSrcDrawable, pDstDrawable, pGC,
				   srcx, srcy, width, height, dstx, dsty);
    }

#if (GET_ABI_MAJOR(ABI_VIDEODRV_VERSION) >= 6)
    return miDoCopy(pSrcDrawable, pDstDrawable, pGC,
		    srcx, srcy, width, height,
		    dstx, dsty, saa_copy_nton, 0, NULL);
#else
    return fbDoCopy(pSrcDrawable, pDstDrawable, pGC,
		    srcx, srcy, width, height,
		    dstx, dsty, saa_copy_nton, 0, NULL);
#endif
}
0707010000000E000081A400000000000000000000000161A68E12000019CB000000000000000000000000000000000000002D00000000xf86-video-vmware-13.3.0+12/saa/saa_pixmap.c/*
 * Copyright © 2009 Maarten Maathuis
 * 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: Based on "exa_driver.c"
 * Author: Thomas Hellstrom <thellstrom@vmware.com>
 */

#include "saa_priv.h"
#include "saa.h"

PixmapPtr
saa_create_pixmap(ScreenPtr pScreen, int w, int h, int depth,
		  unsigned usage_hint)
{
    PixmapPtr pPixmap;
    struct saa_pixmap *spix;
    int bpp;
    size_t paddedWidth;
    struct saa_screen_priv *sscreen = saa_screen(pScreen);
    int new_pitch = 0;
    struct saa_driver *driver = sscreen->driver;

    if (w > 32767 || h > 32767)
	return NullPixmap;

    /*
     * Create a scratch pixmap without backing storage (w and h are zero)
     */

    saa_swap(sscreen, pScreen, CreatePixmap);
    pPixmap = pScreen->CreatePixmap(pScreen, 0, 0, depth, usage_hint);
    saa_swap(sscreen, pScreen, CreatePixmap);

    if (!pPixmap)
	goto out_no_pix;

    spix = saa_pixmap(pPixmap);
    memset(spix, 0, driver->pixmap_size);
    REGION_NULL(pScreen, &spix->dirty_shadow);
    REGION_NULL(pScreen, &spix->dirty_hw);
    REGION_NULL(pScreen, &spix->shadow_damage);
    spix->read_access = 0;
    spix->write_access = 0;
    spix->mapped_access = 0;
    spix->addr = NULL;
    spix->auth_loc = saa_loc_override;
    spix->override = SAA_INVALID_ADDRESS;
    spix->pixmap = pPixmap;
    bpp = pPixmap->drawable.bitsPerPixel;

    if (!driver->create_pixmap(driver, spix, w, h, depth,
			       usage_hint, bpp, &new_pitch))
	goto out_no_driver_priv;

    paddedWidth = new_pitch;
    spix->damage = NULL;

    /*
     * Now set w and h to the correct value. This might allocate
     * backing store if w and h are NON-NULL.
     */

    if (!(*pScreen->ModifyPixmapHeader) (pPixmap, w, h, 0, 0,
					 paddedWidth, NULL))
	goto out_no_pixmap_header;

    /*
     * During a fallback we must prepare access. This hack is initially used
     * for pixmaps created during ValidateGC.
     */

    spix->fallback_created = FALSE;
    if (sscreen->fallback_count) {
	if (!saa_prepare_access_pixmap(pPixmap, SAA_ACCESS_W, NULL))
	    goto out_no_access;

	spix->fallback_created = TRUE;
    }

    return pPixmap;
 out_no_access:
 out_no_pixmap_header:
    driver->destroy_pixmap(driver, pPixmap);
 out_no_driver_priv:
    saa_swap(sscreen, pScreen, DestroyPixmap);
    pScreen->DestroyPixmap(pPixmap);
    saa_swap(sscreen, pScreen, DestroyPixmap);
 out_no_pix:
    LogMessage(X_ERROR, "Failing pixmap creation.\n");
    return NullPixmap;
}

Bool
saa_destroy_pixmap(PixmapPtr pPixmap)
{
    ScreenPtr pScreen = pPixmap->drawable.pScreen;
    struct saa_screen_priv *sscreen = saa_screen(pScreen);
    Bool ret;
    struct saa_driver *driver = sscreen->driver;

    if (pPixmap->refcnt == 1) {
	struct saa_pixmap *spix = saa_pixmap(pPixmap);

	if (spix->fallback_created) {
	    if (!sscreen->fallback_count)
		LogMessage(X_ERROR, "Fallback pixmap destroyed outside "
			   "fallback.\n");

	    saa_finish_access_pixmap(pPixmap, SAA_ACCESS_W);
	}

	driver->destroy_pixmap(driver, pPixmap);

	REGION_UNINIT(pScreen, &spix->dirty_hw);
	REGION_UNINIT(pScreen, &spix->dirty_shadow);
	if (spix->damage)
	    DamageDestroy(spix->damage);
    }

    saa_swap(sscreen, pScreen, DestroyPixmap);
    ret = pScreen->DestroyPixmap(pPixmap);
    saa_swap(sscreen, pScreen, DestroyPixmap);

    return ret;
}

Bool
saa_modify_pixmap_header(PixmapPtr pPixmap, int width, int height, int depth,
			 int bitsPerPixel, int devKind, pointer pPixData)
{
    ScreenPtr pScreen;
    struct saa_screen_priv *sscreen;
    struct saa_pixmap *spix;
    struct saa_driver *driver;
    Bool ret = TRUE;

    if (!pPixmap)
	return FALSE;

    pScreen = pPixmap->drawable.pScreen;
    sscreen = saa_screen(pScreen);
    spix = saa_pixmap(pPixmap);
    driver = sscreen->driver;

    if (spix && driver->modify_pixmap_header &&
	driver->modify_pixmap_header(pPixmap, width, height, depth,
				     bitsPerPixel, devKind, pPixData)) {
	spix->auth_loc = saa_loc_driver;
	spix->override = SAA_INVALID_ADDRESS;
	goto out;
    }

    saa_swap(sscreen, pScreen, ModifyPixmapHeader);
    ret = pScreen->ModifyPixmapHeader(pPixmap, width, height, depth,
				      bitsPerPixel, devKind, pPixData);
    saa_swap(sscreen, pScreen, ModifyPixmapHeader);
    spix->override = pPixmap->devPrivate.ptr;
    spix->auth_loc = saa_loc_override;

 out:
    pPixmap->devPrivate.ptr = NULL;
    return ret;
}

struct saa_pixmap *
saa_get_saa_pixmap(PixmapPtr pPixmap)
{
    return saa_pixmap(pPixmap);
}

void
saa_pixmap_dirty(PixmapPtr pixmap, Bool hw, RegionPtr reg)
{
    struct saa_pixmap *spix = saa_pixmap(pixmap);
    struct saa_screen_priv *sscreen = saa_screen(pixmap->drawable.pScreen);

    if (hw) {
	REGION_UNION(pixmap->drawable.pScreen, &spix->dirty_hw,
		     &spix->dirty_hw, reg);
	REGION_SUBTRACT(pixmap->drawable.pScreen, &spix->dirty_shadow,
			&spix->dirty_shadow, reg);
    } else {
	REGION_UNION(pixmap->drawable.pScreen, &spix->dirty_shadow,
		     &spix->dirty_shadow, reg);
	REGION_SUBTRACT(pixmap->drawable.pScreen, &spix->dirty_hw,
			&spix->dirty_hw, reg);
    }

    sscreen->driver->damage(sscreen->driver, pixmap, hw, reg);
}

void
saa_drawable_dirty(DrawablePtr draw, Bool hw, RegionPtr reg)
{
    PixmapPtr pixmap;
    int x_offset, y_offset;

    pixmap = saa_get_pixmap(draw, &x_offset, &y_offset);
    REGION_TRANSLATE(draw->pScreen, reg, x_offset, y_offset);
    saa_pixmap_dirty(pixmap, hw, reg);
    REGION_TRANSLATE(draw->pScreen, reg, -x_offset, -y_offset);
}
0707010000000F000081A400000000000000000000000161A68E1200001E8A000000000000000000000000000000000000002B00000000xf86-video-vmware-13.3.0+12/saa/saa_priv.h/*
 *
 * Copyright (C) 2000 Keith Packard, member of The XFree86 Project, Inc.
 *               2005 Zack Rusin, Trolltech
 * Copyright 2011 VMWare, inc. All rights reserved.
 *
 * Permission to use, copy, modify, distribute, and sell this software and its
 * documentation for any purpose is hereby granted without fee, provided that
 * the above copyright notice appear in all copies and that both that
 * copyright notice and this permission notice appear in supporting
 * documentation, and that the name of Keith Packard not be used in
 * advertising or publicity pertaining to distribution of the software without
 * specific, written prior permission.  Keith Packard makes no
 * representations about the suitability of this software for any purpose.  It
 * is provided "as is" without express or implied warranty.
 *
 * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS
 * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
 * FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY
 * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
 * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
 * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
 * SOFTWARE.
 *
 * Authors: Based on exa_priv.h
 * Authors: Thomas Hellstrom <thellstrom@vmware.com>
 */

#ifndef _SAA_PRIV_H
#define _SAA_PRIV_H

#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#ifdef HAVE_DIX_CONFIG_H
#include <dix-config.h>
#else
#include <xorg-server.h>
#endif
#include "xf86.h"

#include "saa.h"

#include <X11/X.h>
#include <X11/Xproto.h>
#include "scrnintstr.h"
#include "pixmapstr.h"
#include "windowstr.h"
#include "servermd.h"
#include "colormapst.h"
#include "gcstruct.h"
#include "input.h"
#include "mipointer.h"
#include "mi.h"
#include "dix.h"
#include "fb.h"
#ifdef RENDER
#include "glyphstr.h"
#endif
#include "damage.h"
#include "../src/common_compat.h"

#define SAA_INVALID_ADDRESS \
  ((void *) ((unsigned long) 0xFFFFFFFF - 1024*1024))

struct saa_gc_priv {
    /* GC values from the layer below. */
    CONST_ABI_18_0 GCOps *saved_ops;
    CONST_ABI_18_0 GCFuncs *saved_funcs;
};

struct saa_screen_priv {
    struct saa_driver *driver;
    CreateGCProcPtr saved_CreateGC;
    CloseScreenProcPtr saved_CloseScreen;
    CloseScreenProcPtr saved_early_CloseScreen;
    GetImageProcPtr saved_GetImage;
    GetSpansProcPtr saved_GetSpans;
    CreatePixmapProcPtr saved_CreatePixmap;
    DestroyPixmapProcPtr saved_DestroyPixmap;
    CopyWindowProcPtr saved_CopyWindow;
    ChangeWindowAttributesProcPtr saved_ChangeWindowAttributes;
    BitmapToRegionProcPtr saved_BitmapToRegion;
    ModifyPixmapHeaderProcPtr saved_ModifyPixmapHeader;
#ifdef RENDER
    CompositeProcPtr saved_Composite;
    CompositeRectsProcPtr saved_CompositeRects;
    TrianglesProcPtr saved_Triangles;
    GlyphsProcPtr saved_Glyphs;
    TrapezoidsProcPtr saved_Trapezoids;
    AddTrapsProcPtr saved_AddTraps;
    UnrealizeGlyphProcPtr saved_UnrealizeGlyph;
    SourceValidateProcPtr saved_SourceValidate;
#endif
    Bool fallback_debug;

    unsigned int fallback_count;

    RegionRec srcReg;
    RegionRec maskReg;
    DrawablePtr srcDraw;
};

extern GCOps saa_gc_ops;

#if DEBUG_TRACE_FALL
#define SAA_FALLBACK(x)						\
do {								\
	ErrorF("SAA fallback at %s: ", __FUNCTION__);		\
	ErrorF x;						\
} while (0)

#define saa_drawable_location() ("u")
#else
#define SAA_FALLBACK(x)
#endif

/*
 * Some macros to deal with function wrapping.
 */
#define saa_wrap(priv, real, mem, func) {\
	(priv)->saved_##mem = (real)->mem;	\
	(real)->mem = func;			\
}

#define saa_unwrap(priv, real, mem) {\
	(real)->mem = (priv)->saved_##mem;	\
}

#define saa_wrap_early(priv, real, mem, func) {		\
	(priv)->saved_early_##mem = (real)->mem;	\
	(real)->mem = func;				\
}

#define saa_unwrap_early(priv, real, mem) {		\
	(real)->mem = (priv)->saved_early_##mem;	\
}

#define saa_swap(priv, real, mem) {\
	CONST_ABI_18_0 void *tmp = (priv)->saved_##mem;		\
	(priv)->saved_##mem = (real)->mem;	\
	(real)->mem = tmp;			\
}

#if (GET_ABI_MAJOR(ABI_VIDEODRV_VERSION) >= 8)
#define SAA_DEVPRIVATEKEYREC 1

extern DevPrivateKeyRec saa_screen_index;
extern DevPrivateKeyRec saa_pixmap_index;
extern DevPrivateKeyRec saa_gc_index;

static inline struct saa_screen_priv *
saa_screen(ScreenPtr screen)
{
    return (struct saa_screen_priv *)dixGetPrivate(&screen->devPrivates,
						   &saa_screen_index);
}

static inline struct saa_gc_priv *
saa_gc(GCPtr gc)
{
    return (struct saa_gc_priv *)dixGetPrivateAddr(&gc->devPrivates,
						   &saa_gc_index);
}

static inline struct saa_pixmap *
saa_pixmap(PixmapPtr pix)
{
    return (struct saa_pixmap *)dixGetPrivateAddr(&pix->devPrivates,
						  &saa_pixmap_index);
}
#else
#undef SAA_DEVPRIVATEKEYREC
extern int saa_screen_index;
extern int saa_pixmap_index;
extern int saa_gc_index;

static inline struct saa_screen_priv *
saa_screen(ScreenPtr screen)
{
    return (struct saa_screen_priv *)dixLookupPrivate(&screen->devPrivates,
						      &saa_screen_index);
}

static inline struct saa_gc_priv *
saa_gc(GCPtr gc)
{
    return (struct saa_gc_priv *)dixLookupPrivateAddr(&gc->devPrivates,
						      &saa_gc_index);
}

static inline struct saa_pixmap *
saa_pixmap(PixmapPtr pix)
{
    return (struct saa_pixmap *)dixLookupPrivateAddr(&pix->devPrivates,
							  &saa_pixmap_index);
}

#endif

extern void
saa_check_fill_spans(DrawablePtr pDrawable, GCPtr pGC, int nspans,
		     DDXPointPtr ppt, int *pwidth, int fSorted);
extern void
saa_check_poly_fill_rect(DrawablePtr pDrawable, GCPtr pGC,
			 int nrect, xRectangle * prect);
extern RegionPtr
saa_check_copy_area(DrawablePtr pSrc, DrawablePtr pDst, GCPtr pGC,
		    int srcx, int srcy, int w, int h, int dstx, int dsty);
extern void
saa_check_copy_nton(DrawablePtr pSrc, DrawablePtr pDst, GCPtr pGC,
		    BoxPtr pbox, int nbox, int dx, int dy, Bool reverse,
		    Bool upsidedown, Pixel bitplane, void *closure);

extern void
saa_unaccel_setup(ScreenPtr pScreen);

extern void
saa_unaccel_takedown(ScreenPtr pScreen);

extern RegionPtr
saa_copy_area(DrawablePtr pSrcDrawable, DrawablePtr pDstDrawable, GCPtr pGC,
	      int srcx, int srcy, int width, int height, int dstx, int dsty);

extern Bool
saa_hw_copy_nton(DrawablePtr pSrcDrawable,
		 DrawablePtr pDstDrawable,
		 GCPtr pGC,
		 BoxPtr pbox,
		 int nbox, int dx, int dy, Bool reverse, Bool upsidedown);

#ifdef RENDER
extern void
saa_render_setup(ScreenPtr pScreen);

extern void
saa_render_takedown(ScreenPtr pScreen);


extern void
saa_check_composite(CARD8 op,
		    PicturePtr pSrc,
		    PicturePtr pMask,
		    PicturePtr pDst,
		    INT16 xSrc,
		    INT16 ySrc,
		    INT16 xMask,
		    INT16 yMask,
		    INT16 xDst, INT16 yDst, CARD16 width, CARD16 height,
		    RegionPtr src_region,
		    RegionPtr mask_region,
		    RegionPtr dst_region);
#endif

extern Bool
saa_modify_pixmap_header(PixmapPtr pPixmap, int width, int height, int depth,
			 int bitsPerPixel, int devKind, pointer pPixData);

extern PixmapPtr
saa_create_pixmap(ScreenPtr pScreen, int w, int h, int depth,
		  unsigned usage_hint);

extern Bool
saa_destroy_pixmap(PixmapPtr pPixmap);

static inline RegionPtr
saa_pix_damage_pending(struct saa_pixmap *spix)
{
    return (spix->damage ? DamagePendingRegion(spix->damage) : NULL);
}

extern RegionPtr
saa_boxes_to_region(ScreenPtr pScreen, int nbox, BoxPtr pbox, int ordering);


Bool
saa_compute_composite_regions(ScreenPtr pScreen,
			      PicturePtr pSrc,
			      PicturePtr pMask,
			      PicturePtr pDst,
			      INT16 xSrc, INT16 ySrc, INT16 xMask,
			      INT16 yMask, INT16 xDst,
			      INT16 yDst, INT16 width, INT16 height,
			      RegionPtr dst_reg,
			      RegionPtr *src_reg,
			      RegionPtr *mask_reg);

#endif
07070100000010000081A400000000000000000000000161A68E12000030E6000000000000000000000000000000000000002D00000000xf86-video-vmware-13.3.0+12/saa/saa_render.c/*
 * Copyright © 2001 Keith Packard
 * Copyright 2011 VMWare, Inc. All Rights Reserved.
 * May partly be based on code that is Copyright © The XFree86 Project 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, 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: Eric Anholt <eric@anholt.net>
 * Author: Michel Dänzer <michel@tungstengraphics.com>
 * Author: Thomas Hellstrom <thellstrom@vmware.com>
 */
#include "saa.h"
#include "saa_priv.h"

#ifdef RENDER
#include <mipict.h>

/**
 * Same as miCreateAlphaPicture, except it uses
 * saa_check_poly_fill_rect instead
 */

static PicturePtr
saa_create_alpha_picture(ScreenPtr pScreen,
			 PicturePtr pDst,
			 PictFormatPtr pPictFormat, CARD16 width, CARD16 height)
{
    PixmapPtr pPixmap;
    PicturePtr pPicture;
    GCPtr pGC;
    int error;
    xRectangle rect;

    if (width > 32767 || height > 32767)
	return 0;

    if (!pPictFormat) {
	if (pDst->polyEdge == PolyEdgeSharp)
	    pPictFormat = PictureMatchFormat(pScreen, 1, PICT_a1);
	else
	    pPictFormat = PictureMatchFormat(pScreen, 8, PICT_a8);
	if (!pPictFormat)
	    return 0;
    }

    pPixmap = (*pScreen->CreatePixmap) (pScreen, width, height,
					pPictFormat->depth, 0);
    if (!pPixmap)
	return 0;
    pGC = GetScratchGC(pPixmap->drawable.depth, pScreen);
    if (!pGC) {
	(*pScreen->DestroyPixmap) (pPixmap);
	return 0;
    }
    ValidateGC(&pPixmap->drawable, pGC);
    rect.x = 0;
    rect.y = 0;
    rect.width = width;
    rect.height = height;
    saa_check_poly_fill_rect(&pPixmap->drawable, pGC, 1, &rect);
    FreeScratchGC(pGC);
    pPicture = CreatePicture(0, &pPixmap->drawable, pPictFormat,
			     0, 0, serverClient, &error);
    (*pScreen->DestroyPixmap) (pPixmap);
    return pPicture;
}

/**
 * saa_trapezoids is essentially a copy of miTrapezoids that uses
 * saa_create_alpha_picture instead of miCreateAlphaPicture.
 *
 * The problem with miCreateAlphaPicture is that it calls PolyFillRect
 * to initialize the contents after creating the pixmap, which
 * causes the pixmap to be moved in for acceleration. The subsequent
 * call to RasterizeTrapezoid won't be accelerated however, which
 * forces the pixmap to be moved out again.
 *
 */
static void
saa_trapezoids(CARD8 op, PicturePtr pSrc, PicturePtr pDst,
	       PictFormatPtr maskFormat, INT16 xSrc, INT16 ySrc,
	       int ntrap, xTrapezoid * traps)
{
    ScreenPtr pScreen = pDst->pDrawable->pScreen;
    PictureScreenPtr ps = GetPictureScreen(pScreen);
    BoxRec bounds;

    if (maskFormat) {
	PicturePtr pPicture;
	INT16 xDst, yDst;
	INT16 xRel, yRel;
	saa_access_t access;

	miTrapezoidBounds(ntrap, traps, &bounds);

	if (bounds.y1 >= bounds.y2 || bounds.x1 >= bounds.x2)
	    return;

	xDst = traps[0].left.p1.x >> 16;
	yDst = traps[0].left.p1.y >> 16;

	pPicture = saa_create_alpha_picture(pScreen, pDst, maskFormat,
					    bounds.x2 - bounds.x1,
					    bounds.y2 - bounds.y1);
	if (!pPicture)
	    return;

	if (saa_pad_write(pPicture->pDrawable, NULL, FALSE, &access)) {
	    for (; ntrap; ntrap--, traps++)
		(*ps->RasterizeTrapezoid) (pPicture, traps,
					   -bounds.x1, -bounds.y1);
	    saa_fad_write(pPicture->pDrawable, access);
	}

	xRel = bounds.x1 + xSrc - xDst;
	yRel = bounds.y1 + ySrc - yDst;
	CompositePicture(op, pSrc, pPicture, pDst,
			 xRel, yRel, 0, 0, bounds.x1, bounds.y1,
			 bounds.x2 - bounds.x1, bounds.y2 - bounds.y1);
	FreePicture(pPicture, 0);
    } else {
	if (pDst->polyEdge == PolyEdgeSharp)
	    maskFormat = PictureMatchFormat(pScreen, 1, PICT_a1);
	else
	    maskFormat = PictureMatchFormat(pScreen, 8, PICT_a8);
	for (; ntrap; ntrap--, traps++)
	    saa_trapezoids(op, pSrc, pDst, maskFormat, xSrc, ySrc, 1, traps);
    }
}

/**
 * saa_triangles is essentially a copy of miTriangles that uses
 * saa_create_alpha_picture instead of miCreateAlphaPicture.
 *
 * The problem with miCreateAlphaPicture is that it calls PolyFillRect
 * to initialize the contents after creating the pixmap, which
 * causes the pixmap to be moved in for acceleration. The subsequent
 * call to AddTriangles won't be accelerated however, which forces the pixmap
 * to be moved out again.
 */
static void
saa_triangles(CARD8 op, PicturePtr pSrc, PicturePtr pDst,
	      PictFormatPtr maskFormat, INT16 xSrc, INT16 ySrc,
	      int ntri, xTriangle * tris)
{
    ScreenPtr pScreen = pDst->pDrawable->pScreen;
    PictureScreenPtr ps = GetPictureScreen(pScreen);
    BoxRec bounds;

    if (maskFormat) {
	PicturePtr pPicture;
	INT16 xDst, yDst;
	INT16 xRel, yRel;
	saa_access_t access;

	miTriangleBounds(ntri, tris, &bounds);

	if (bounds.y1 >= bounds.y2 || bounds.x1 >= bounds.x2)
	    return;

	xDst = tris[0].p1.x >> 16;
	yDst = tris[0].p1.y >> 16;

	pPicture = saa_create_alpha_picture(pScreen, pDst, maskFormat,
					    bounds.x2 - bounds.x1,
					    bounds.y2 - bounds.y1);
	if (!pPicture)
	    return;

	if (saa_pad_write(pPicture->pDrawable, NULL, FALSE, &access)) {
	    (*ps->AddTriangles) (pPicture, -bounds.x1, -bounds.y1, ntri, tris);
	    saa_fad_write(pPicture->pDrawable, access);
	}

	xRel = bounds.x1 + xSrc - xDst;
	yRel = bounds.y1 + ySrc - yDst;
	CompositePicture(op, pSrc, pPicture, pDst,
			 xRel, yRel, 0, 0, bounds.x1, bounds.y1,
			 bounds.x2 - bounds.x1, bounds.y2 - bounds.y1);
	FreePicture(pPicture, 0);
    } else {
	if (pDst->polyEdge == PolyEdgeSharp)
	    maskFormat = PictureMatchFormat(pScreen, 1, PICT_a1);
	else
	    maskFormat = PictureMatchFormat(pScreen, 8, PICT_a8);

	for (; ntri; ntri--, tris++)
	    saa_triangles(op, pSrc, pDst, maskFormat, xSrc, ySrc, 1, tris);
    }
}

static Bool
saa_driver_composite(CARD8		op,
		     PicturePtr	pSrc,
		     PicturePtr	pMask,
		     PicturePtr	pDst,
		     INT16		xSrc,
		     INT16		ySrc,
		     INT16		xMask,
		     INT16		yMask,
		     INT16		xDst,
		     INT16		yDst,
		     CARD16		width,
		     CARD16		height,
		     RegionPtr src_reg,
		     RegionPtr mask_reg,
		     RegionPtr dst_reg)
{
    struct saa_screen_priv *sscreen = saa_screen(pDst->pDrawable->pScreen);
    BoxPtr pbox;
    int nbox;
    int src_off_x, src_off_y, mask_off_x, mask_off_y, dst_off_x, dst_off_y;
    PixmapPtr src_pix = NULL, mask_pix = NULL, dst_pix;
    struct saa_driver *driver = sscreen->driver;

    if (!driver->composite_prepare)
	return FALSE;

    dst_pix = saa_get_pixmap(pDst->pDrawable, &dst_off_x, &dst_off_y);
    if (saa_pixmap(dst_pix)->auth_loc != saa_loc_driver)
	return FALSE;

    if (pMask && pMask->pDrawable) {
	mask_pix = saa_get_pixmap(pMask->pDrawable, &mask_off_x, &mask_off_y);
	if (saa_pixmap(mask_pix)->auth_loc != saa_loc_driver)
	    return FALSE;
    }
    if (pSrc->pDrawable) {
	src_pix = saa_get_pixmap(pSrc->pDrawable, &src_off_x, &src_off_y);
	if (saa_pixmap(src_pix)->auth_loc != saa_loc_driver)
	    return FALSE;
    }

    if (!driver->composite_prepare(driver, op, pSrc, pMask, pDst,
				   src_pix, mask_pix, dst_pix,
				   src_reg, mask_reg, dst_reg))
	return FALSE;

    nbox = REGION_NUM_RECTS(dst_reg);
    pbox = REGION_RECTS(dst_reg);

    xDst += pDst->pDrawable->x + dst_off_x;
    yDst += pDst->pDrawable->y + dst_off_y;

    if (src_pix) {
	xSrc += pSrc->pDrawable->x + src_off_x - xDst;
	ySrc += pSrc->pDrawable->y + src_off_y - yDst;
    }
    if (mask_pix) {
	xMask += pMask->pDrawable->x + mask_off_x - xDst;
	yMask += pMask->pDrawable->y + mask_off_y - yDst;
    }

    while (nbox--) {
	driver->composite(driver,
			  pbox->x1 + xSrc,
			  pbox->y1 + ySrc,
			  pbox->x1 + xMask,
			  pbox->y1 + yMask,
			  pbox->x1,
			  pbox->y1,
			  pbox->x2 - pbox->x1,
			  pbox->y2 - pbox->y1);
	pbox++;
    }

    driver->composite_done(driver);
    saa_pixmap_dirty(dst_pix, TRUE, dst_reg);

    return TRUE;
}

/*
 * Try to turn a composite operation into an accelerated copy.
 * We can do that in some special cases for PictOpSrc and PictOpOver.
 */

static Bool
saa_copy_composite(CARD8 op,
		   PicturePtr pSrc,
		   PicturePtr pMask,
		   PicturePtr pDst,
		   INT16 xSrc,
		   INT16 ySrc,
		   INT16 xMask,
		   INT16 yMask,
		   INT16 xDst, INT16 yDst, CARD16 width, CARD16 height,
		   RegionPtr dst_region)
{
    if (!pSrc->pDrawable || pSrc->transform ||
	pSrc->repeat || xSrc < 0 || ySrc < 0 ||
	xSrc + width > pSrc->pDrawable->width ||
	ySrc + height > pSrc->pDrawable->height)
	return FALSE;

    if (op == PictOpSrc ||
	(op == PictOpOver && PICT_FORMAT_A(pSrc->format) == 0 &&
	 pMask == NULL)) {

	int xoff, yoff;
	PixmapPtr dst_pix = saa_get_pixmap(pDst->pDrawable, &xoff, &yoff);
	struct saa_pixmap *dst_spix = saa_pixmap(dst_pix);
	struct saa_pixmap *src_spix =
	    saa_pixmap(saa_get_drawable_pixmap(pSrc->pDrawable));
	int ret;

	if (src_spix->auth_loc != saa_loc_driver ||
	    dst_spix->auth_loc != saa_loc_driver)
	    return FALSE;

	src_spix->src_format = pSrc->format;
	dst_spix->dst_format = pDst->format;

	xDst += pDst->pDrawable->x;
	yDst += pDst->pDrawable->y;
	xSrc += pSrc->pDrawable->x;
	ySrc += pSrc->pDrawable->y;

	/*
	 * Dst region is in backing pixmap space. We need to
	 * translate it.
	 */
	REGION_TRANSLATE(pScreen, dst_region, -xoff, -yoff);
	ret = saa_hw_copy_nton(pSrc->pDrawable, pDst->pDrawable, NULL,
			       REGION_RECTS(dst_region),
			       REGION_NUM_RECTS(dst_region),
			       xSrc - xDst, ySrc - yDst, FALSE, FALSE);
	REGION_TRANSLATE(pScreen, dst_region, xoff, yoff);

	src_spix->src_format = 0;
	dst_spix->dst_format = 0;

	if (ret)
	    return TRUE;
    }
    return FALSE;
}

static void
saa_composite(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;
    RegionRec dst_region;
    RegionPtr src_region;
    RegionPtr mask_region;

    REGION_NULL(pScreen, &dst_region);
    if (!saa_compute_composite_regions(pScreen, pSrc, pMask, pDst,
				       xSrc, ySrc, xMask, yMask, xDst,
				       yDst, width, height,
				       &dst_region, &src_region, &mask_region))
	goto out;

    if (saa_copy_composite(op, pSrc, pMask, pDst, xSrc, ySrc, xMask, yMask,
			   xDst, yDst, width, height, &dst_region))
	goto out;

    if (saa_driver_composite(op, pSrc, pMask, pDst, xSrc, ySrc, xMask, yMask,
			     xDst, yDst, width, height, src_region,
			     mask_region, &dst_region))
	goto out;

    saa_check_composite(op, pSrc, pMask, pDst, xSrc, ySrc, xMask, yMask,
			xDst, yDst, width, height,
			src_region, mask_region, &dst_region);
  out:
    if (src_region)
	REGION_UNINIT(pScreen, src_region);
    if (mask_region && mask_region != src_region)
	REGION_UNINIT(pScreen, mask_region);
    REGION_UNINIT(pScreen, &dst_region);
}

void
saa_render_setup(ScreenPtr pScreen)
{
    PictureScreenPtr ps = GetPictureScreenIfSet(pScreen);
    struct saa_screen_priv *sscreen = saa_screen(pScreen);

    if (ps) {
	saa_wrap(sscreen, ps, Trapezoids, saa_trapezoids);
	saa_wrap(sscreen, ps, Triangles, saa_triangles);
	saa_wrap(sscreen, ps, Composite, saa_composite);
	saa_wrap(sscreen, ps, Glyphs,    miGlyphs);
	saa_wrap(sscreen, ps, UnrealizeGlyph, miUnrealizeGlyph);
    }
}

void
saa_render_takedown(ScreenPtr pScreen)
{
    PictureScreenPtr ps = GetPictureScreenIfSet(pScreen);
    struct saa_screen_priv *sscreen = saa_screen(pScreen);

    if (ps) {
	saa_unwrap(sscreen, ps, Trapezoids);
	saa_unwrap(sscreen, ps, Triangles);
	saa_unwrap(sscreen, ps, Composite);
	saa_unwrap(sscreen, ps, Glyphs);
	saa_unwrap(sscreen, ps, UnrealizeGlyph);
    }
}
#endif
07070100000011000081A400000000000000000000000161A68E12000079F1000000000000000000000000000000000000002E00000000xf86-video-vmware-13.3.0+12/saa/saa_unaccel.c/*
 * Copyright © 1999 Keith Packard
 * 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: Based on "exa_unaccel.c"
 * Author: Thomas Hellstrom <thellstrom@vmware.com>
 */

#include "saa_priv.h"
#include "saa.h"
#include "mipict.h"

/**
 * Calls saa_prepare_access with SAA_ACCESS_R for the tile, if that is the
 * current fill style.
 *
 * Solid doesn't use an extra pixmap source, and Stippled/OpaqueStippled are
 * 1bpp and never in fb, so we don't worry about them.
 * We should worry about them for completeness sake and going forward.
 */
static Bool
saa_prepare_access_gc(GCPtr pGC)
{
    if (pGC->stipple)
	if (!saa_pad_read(&pGC->stipple->drawable))
	    return FALSE;
    if (pGC->fillStyle == FillTiled)
	if (!saa_pad_read(&pGC->tile.pixmap->drawable)) {
	    if (pGC->stipple)
		saa_fad_read(&pGC->stipple->drawable);
	    return FALSE;
	}
    return TRUE;
}

/**
 * Finishes access to the tile in the GC, if used.
 */
static void
saa_finish_access_gc(GCPtr pGC)
{
    if (pGC->fillStyle == FillTiled)
	saa_fad_read(&pGC->tile.pixmap->drawable);
    if (pGC->stipple)
	saa_fad_read(&pGC->stipple->drawable);
}

void
saa_check_fill_spans(DrawablePtr pDrawable, GCPtr pGC, int nspans,
		     DDXPointPtr ppt, int *pwidth, int fSorted)
{
    struct saa_screen_priv *sscreen = saa_screen(pGC->pScreen);
    struct saa_gc_priv *sgc = saa_gc(pGC);
    saa_access_t access;

    SAA_FALLBACK(("to %p (%c)\n", pDrawable, saa_drawable_location(pDrawable)));

    sscreen->fallback_count++;
    if (saa_pad_write(pDrawable, NULL, FALSE, &access)) {
	if (saa_prepare_access_gc(pGC)) {
	    saa_swap(sgc, pGC, ops);
	    pGC->ops->FillSpans(pDrawable, pGC, nspans, ppt, pwidth, fSorted);
	    saa_swap(sgc, pGC, ops);
	    saa_finish_access_gc(pGC);
	}
	saa_fad_write(pDrawable, access);
    }
    sscreen->fallback_count--;
}

static void
saa_check_set_spans(DrawablePtr pDrawable, GCPtr pGC, char *psrc,
		    DDXPointPtr ppt, int *pwidth, int nspans, int fSorted)
{
    struct saa_screen_priv *sscreen = saa_screen(pGC->pScreen);
    struct saa_gc_priv *sgc = saa_gc(pGC);
    saa_access_t access
	SAA_FALLBACK(("to %p (%c)\n", pDrawable, saa_drawable_loc(pDrawable)));

    sscreen->fallback_count++;
    if (saa_pad_write(pDrawable, NULL, FALSE, &access)) {
	saa_swap(sgc, pGC, ops);
	pGC->ops->SetSpans(pDrawable, pGC, psrc, ppt, pwidth, nspans, fSorted);
	saa_swap(sgc, pGC, ops);
	saa_fad_write(pDrawable, access);
    }
    sscreen->fallback_count--;
}

static void
saa_check_put_image(DrawablePtr pDrawable, GCPtr pGC, int depth,
		    int x, int y, int w, int h, int leftPad, int format,
		    char *bits)
{
    struct saa_screen_priv *sscreen = saa_screen(pGC->pScreen);
    struct saa_gc_priv *sgc = saa_gc(pGC);
    saa_access_t access;

    SAA_FALLBACK(("to %p (%c)\n", pDrawable, saa_drawable_loc(pDrawable)));
    sscreen->fallback_count++;
    if (saa_pad_write(pDrawable, pGC, TRUE, &access)) {
	saa_swap(sgc, pGC, ops);
	pGC->ops->PutImage(pDrawable, pGC, depth, x, y, w, h, leftPad,
			   format, bits);
	saa_swap(sgc, pGC, ops);
	saa_fad_write(pDrawable, access);
    }
    sscreen->fallback_count--;
}

RegionPtr
saa_boxes_to_region(ScreenPtr pScreen, int nbox, BoxPtr pbox, int ordering)
{
    xRectangle *rects = malloc(nbox * sizeof(*rects));
    int i;
    RegionPtr reg;

    if (!rects)
	return NULL;

    for (i = 0; i < nbox; i++) {
	rects[i].x = pbox[i].x1;
	rects[i].y = pbox[i].y1;
	rects[i].width = pbox[i].x2 - pbox[i].x1;
	rects[i].height = pbox[i].y2 - pbox[i].y1;
    }

    reg = RECTS_TO_REGION(pScreen, nbox, rects, ordering);
    free(rects);
    return reg;
}

void
saa_check_copy_nton(DrawablePtr pSrc, DrawablePtr pDst, GCPtr pGC,
		    BoxPtr pbox, int nbox, int dx, int dy, Bool reverse,
		    Bool upsidedown, Pixel bitplane, void *closure)
{
    ScreenPtr pScreen = pSrc->pScreen;
    struct saa_screen_priv *sscreen = saa_screen(pScreen);
    RegionPtr reg, readback;
    int src_xoff, src_yoff, dst_xoff, dst_yoff;
    struct saa_gc_priv *sgc = saa_gc(pGC);
    PixmapPtr src_pixmap;
    PixmapPtr dst_pixmap;
    saa_access_t access = SAA_ACCESS_R;
    int ordering;

    sscreen->fallback_count++;
    SAA_FALLBACK(("from %p to %p (%c,%c)\n", pSrc, pDst,
		  saa_drawable_loc(pSrc), saa_drawable_loc(pDst)));

    src_pixmap = saa_get_pixmap(pSrc, &src_xoff, &src_yoff);
    dst_pixmap = saa_get_pixmap(pDst, &dst_xoff, &dst_yoff);

    ordering = (nbox == 1 || (dx > 0 && dy > 0) ||
		(pDst != pSrc &&
		 (pDst->type != DRAWABLE_WINDOW ||
		  pSrc->type != DRAWABLE_WINDOW))) ? CT_YXBANDED : CT_UNSORTED;

    reg = saa_boxes_to_region(pScreen, nbox, pbox, ordering);
    if (!reg)
	return;

    REGION_TRANSLATE(pScreen, reg, src_xoff + dx, src_yoff + dy);
    if (!saa_prepare_access_pixmap(src_pixmap, SAA_ACCESS_R, reg))
	goto out_no_access;

    REGION_TRANSLATE(pScreen, reg, dst_xoff - dx - src_xoff,
		     dst_yoff - dy - src_yoff);

    if (saa_gc_reads_destination(pDst, pGC)) {
	readback = reg;
	access = SAA_ACCESS_RW;
    } else {
	readback = NULL;
	access = SAA_ACCESS_W;
    }

    if (!saa_prepare_access_pixmap(dst_pixmap, access, readback))
	goto out_no_dst;

    saa_swap(sgc, pGC, ops);
    while (nbox--) {
	pGC->ops->CopyArea(pSrc, pDst, pGC, pbox->x1 - pSrc->x + dx,
			   pbox->y1 - pSrc->y + dy,
			   pbox->x2 - pbox->x1, pbox->y2 - pbox->y1,
			   pbox->x1 - pDst->x, pbox->y1 - pDst->y);
	pbox++;
    }

    saa_swap(sgc, pGC, ops);
    saa_finish_access_pixmap(dst_pixmap, access);
    saa_pixmap_dirty(dst_pixmap, FALSE, reg);
 out_no_dst:
    saa_fad_read(pSrc);
 out_no_access:
    sscreen->fallback_count--;
    REGION_DESTROY(pScreen, reg);
}

RegionPtr
saa_check_copy_area(DrawablePtr pSrc, DrawablePtr pDst, GCPtr pGC,
		    int srcx, int srcy, int w, int h, int dstx, int dsty)
{
    RegionPtr ret = NULL;
    struct saa_gc_priv *sgc = saa_gc(pGC);
    saa_access_t access;
    struct saa_screen_priv *sscreen = saa_screen(pGC->pScreen);

    SAA_FALLBACK(("from %p to %p (%c,%c)\n", pSrc, pDst,
		  saa_drawable_loc(pSrc), saa_drawable_loc(pDst)));
    sscreen->fallback_count++;
    if (!saa_pad_read_box(pSrc, srcx, srcy, w, h))
	goto out_no_access;
    if (!saa_pad_write(pDst, pGC, TRUE, &access))
	goto out_no_dst;

    saa_swap(sgc, pGC, ops);
    ret = pGC->ops->CopyArea(pSrc, pDst, pGC, srcx, srcy, w, h, dstx, dsty);
    saa_swap(sgc, pGC, ops);

    saa_fad_write(pDst, access);
 out_no_dst:
    saa_fad_read(pSrc);
 out_no_access:
    sscreen->fallback_count--;

    return ret;
}

static RegionPtr
saa_check_copy_plane(DrawablePtr pSrc, DrawablePtr pDst, GCPtr pGC,
		     int srcx, int srcy, int w, int h, int dstx, int dsty,
		     unsigned long bitplane)
{
    RegionPtr ret = NULL;
    struct saa_gc_priv *sgc = saa_gc(pGC);
    saa_access_t access;
    struct saa_screen_priv *sscreen = saa_screen(pGC->pScreen);

    SAA_FALLBACK(("from %p to %p (%c,%c)\n", pSrc, pDst,
		  saa_drawable_loc(pSrc), saa_drawable_loc(pDst)));
    sscreen->fallback_count++;
    if (!saa_pad_read_box(pSrc, srcx, srcy, w, h))
	goto out_no_src;
    if (!saa_pad_write(pDst, pGC, TRUE, &access))
	goto out_no_dst;

    saa_swap(sgc, pGC, ops);
    ret = pGC->ops->CopyPlane(pSrc, pDst, pGC, srcx, srcy, w, h, dstx, dsty,
			      bitplane);
    saa_swap(sgc, pGC, ops);

    saa_fad_write(pDst, access);
 out_no_dst:
    saa_fad_read(pSrc);
 out_no_src:
    sscreen->fallback_count--;

    return ret;
}

static void
saa_check_poly_point(DrawablePtr pDrawable, GCPtr pGC, int mode, int npt,
		     DDXPointPtr pptInit)
{
    struct saa_gc_priv *sgc = saa_gc(pGC);
    saa_access_t access;
    struct saa_screen_priv *sscreen = saa_screen(pGC->pScreen);

    sscreen->fallback_count++;
    SAA_FALLBACK(("to %p (%c)\n", pDrawable, saa_drawable_loc(pDrawable)));
    if (!saa_pad_write(pDrawable, NULL, FALSE, &access))
	goto out_no_access;
    saa_swap(sgc, pGC, ops);
    pGC->ops->PolyPoint(pDrawable, pGC, mode, npt, pptInit);
    saa_swap(sgc, pGC, ops);
    saa_fad_write(pDrawable, access);

 out_no_access:
    sscreen->fallback_count--;
}

static void
saa_check_poly_lines(DrawablePtr pDrawable, GCPtr pGC,
		     int mode, int npt, DDXPointPtr ppt)
{
    struct saa_gc_priv *sgc = saa_gc(pGC);
    saa_access_t access;
    struct saa_screen_priv *sscreen = saa_screen(pGC->pScreen);

    SAA_FALLBACK(("to %p (%c), width %d, mode %d, count %d\n",
		  pDrawable, saa_drawable_loc(pDrawable),
		  pGC->lineWidth, mode, npt));

    sscreen->fallback_count++;
    if (!saa_pad_write(pDrawable, NULL, FALSE, &access))
	goto out_no_access;
    if (!saa_prepare_access_gc(pGC))
	goto out_no_gc;
    saa_swap(sgc, pGC, ops);
    pGC->ops->Polylines(pDrawable, pGC, mode, npt, ppt);
    saa_swap(sgc, pGC, ops);
    saa_finish_access_gc(pGC);
 out_no_gc:
    saa_fad_write(pDrawable, access);
 out_no_access:
    sscreen->fallback_count--;
}

static void
saa_check_poly_segment(DrawablePtr pDrawable, GCPtr pGC,
		       int nsegInit, xSegment * pSegInit)
{
    struct saa_gc_priv *sgc = saa_gc(pGC);
    saa_access_t access;
    struct saa_screen_priv *sscreen = saa_screen(pGC->pScreen);

    SAA_FALLBACK(("to %p (%c) width %d, count %d\n", pDrawable,
		  saa_drawable_loc(pDrawable), pGC->lineWidth, nsegInit));

    sscreen->fallback_count++;
    if (!saa_pad_write(pDrawable, NULL, FALSE, &access))
	goto out_no_access;;
    if (!saa_prepare_access_gc(pGC))
	goto out_no_gc;
    saa_swap(sgc, pGC, ops);
    pGC->ops->PolySegment(pDrawable, pGC, nsegInit, pSegInit);
    saa_swap(sgc, pGC, ops);
    saa_finish_access_gc(pGC);
 out_no_gc:
    saa_fad_write(pDrawable, access);
 out_no_access:
    sscreen->fallback_count--;
}

static void
saa_check_poly_arc(DrawablePtr pDrawable, GCPtr pGC, int narcs, xArc * pArcs)
{
    struct saa_gc_priv *sgc = saa_gc(pGC);
    saa_access_t access;
    struct saa_screen_priv *sscreen = saa_screen(pGC->pScreen);

    SAA_FALLBACK(("to %p (%c)\n", pDrawable, saa_drawable_loc(pDrawable)));

    sscreen->fallback_count++;
    if (!saa_pad_write(pDrawable, NULL, FALSE, &access))
	goto out_no_access;;
    if (!saa_prepare_access_gc(pGC))
	goto out_no_gc;
    saa_swap(sgc, pGC, ops);
    pGC->ops->PolyArc(pDrawable, pGC, narcs, pArcs);
    saa_swap(sgc, pGC, ops);
    saa_finish_access_gc(pGC);
 out_no_gc:
    saa_fad_write(pDrawable, access);
 out_no_access:
    sscreen->fallback_count--;
}


/**
 * saa_check_poly_fill_rect_noreadback - PolyFillRect avoiding unnecessary readbacks.
 *
 * @pDrawable: The drawable on which to fill.
 * @pGC: Pointer to the GC to use.
 * @nrect: Number of rectangles to fill.
 * @xRectangle: Pointer to rectangles to fill.
 *
 * During a standard saa polyFillRect, the damage region is usually the bounding
 * box of all rectangles. Since we mark the software pixmap dirty based on that
 * damage region, we need to read all of it back first, even if the fill operation
 * itself doesn't read anything. This version of polyFillRect improves on that by
 * only damaging the area we actually fill. If it's a non-reading fill we thus don't
 * need to read back anything, but this may come at the cost of increased dirty
 * region fragmentation. In any case, this greatly improves on the performance of
 * shaped windows on top of accelerated contents, for example unscaled OSD in xine.
 */
static Bool
saa_check_poly_fill_rect_noreadback(DrawablePtr pDrawable, GCPtr pGC,
				    int nrect, xRectangle *prect)
{
    struct saa_gc_priv *sgc = saa_gc(pGC);
    struct saa_screen_priv *sscreen = saa_screen(pGC->pScreen);
    RegionPtr region;
    saa_access_t access;
    Bool ret;
    PixmapPtr pPixmap;
    xRectangle *prect_save = prect;
    int xoff, yoff;
    struct saa_pixmap *spix;

    if (!nrect)
	return TRUE;

    sscreen->fallback_count++;

    pPixmap = saa_get_pixmap(pDrawable, &xoff, &yoff);
    spix = saa_get_saa_pixmap(pPixmap);
    region = RECTS_TO_REGION(pGC->pScreen, nrect, prect, CT_UNSORTED);
    if (!region)
	goto out_no_region;

    REGION_TRANSLATE(pGC->pScreen, region, pDrawable->x, pDrawable->y);
    REGION_INTERSECT(pGC->pScreen, region, fbGetCompositeClip(pGC), region);
    REGION_TRANSLATE(pGC->pScreen, region, xoff, yoff);

    access = SAA_ACCESS_W;
    if (saa_gc_reads_destination(pDrawable, pGC)) {
	/*
	 * We need to do a readback anyway. In case of more than an
	 * ad hoc number of say 4 rectangles, we might as well do a
	 * readback of the whole damage area to avoid fragmentation.
	 */
	if (REGION_NUM_RECTS(region) > 4)
	    goto out_no_access;

	access |= SAA_ACCESS_R;
	ret = saa_prepare_access_pixmap(pPixmap, access, region);
    } else
	ret = saa_prepare_access_pixmap(pPixmap, access, NULL);

    if (!ret)
	goto out_no_access;

    if (!saa_prepare_access_gc(pGC))
	goto out_no_gc;

    saa_swap(sgc, pGC, ops);
    pGC->ops->PolyFillRect(pDrawable, pGC, nrect, prect_save);
    saa_swap(sgc, pGC, ops);

    saa_finish_access_gc(pGC);
    saa_finish_access_pixmap(pPixmap, access);

    if (spix->damage) {
	REGION_INTERSECT(pGC->pScreen, region, region,
			 saa_pix_damage_pending(spix));
	saa_pixmap_dirty(pPixmap, FALSE, region);
    }

    REGION_DESTROY(pGC->pScreen, region);

    sscreen->fallback_count--;

    return TRUE;

  out_no_gc:
    saa_finish_access_pixmap(pPixmap, access);
  out_no_access:
    REGION_DESTROY(pGC->pScreen, region);
  out_no_region:
    sscreen->fallback_count--;

    return FALSE;
}

void
saa_check_poly_fill_rect(DrawablePtr pDrawable, GCPtr pGC,
			 int nrect, xRectangle * prect)
{
    struct saa_gc_priv *sgc = saa_gc(pGC);
    saa_access_t access;
    struct saa_screen_priv *sscreen = saa_screen(pGC->pScreen);

    SAA_FALLBACK(("to %p (%c)\n", pDrawable, saa_drawable_loc(pDrawable)));

    if (saa_check_poly_fill_rect_noreadback(pDrawable, pGC, nrect, prect))
	return;

    sscreen->fallback_count++;

    /*
     * TODO: Use @prect for readback / damaging instead of
     * the damage region. This may fragment the dirty regions more
     * but should avoid unnecessary readbacks.
     */
    if (!saa_pad_write(pDrawable, pGC, FALSE, &access))
	goto out_no_access;;
    if (!saa_prepare_access_gc(pGC))
	goto out_no_gc;
    saa_swap(sgc, pGC, ops);
    pGC->ops->PolyFillRect(pDrawable, pGC, nrect, prect);
    saa_swap(sgc, pGC, ops);
    saa_finish_access_gc(pGC);
 out_no_gc:
    saa_fad_write(pDrawable, access);
 out_no_access:
    sscreen->fallback_count--;
}

static void
saa_check_image_glyph_blt(DrawablePtr pDrawable, GCPtr pGC,
			  int x, int y, unsigned int nglyph,
			  CharInfoPtr * ppci, pointer pglyphBase)
{
    struct saa_gc_priv *sgc = saa_gc(pGC);
    saa_access_t access;
    struct saa_screen_priv *sscreen = saa_screen(pGC->pScreen);

    SAA_FALLBACK(("to %p (%c)\n", pDrawable, saa_drawable_loc(pDrawable)));

    sscreen->fallback_count++;
    if (!saa_pad_write(pDrawable, NULL, FALSE, &access))
	goto out_no_access;;
    if (!saa_prepare_access_gc(pGC))
	goto out_no_gc;
    saa_swap(sgc, pGC, ops);
    pGC->ops->ImageGlyphBlt(pDrawable, pGC, x, y, nglyph, ppci, pglyphBase);
    saa_swap(sgc, pGC, ops);
    saa_finish_access_gc(pGC);
 out_no_gc:
    saa_fad_write(pDrawable, access);
 out_no_access:
    sscreen->fallback_count--;
}

static void
saa_check_poly_glyph_blt(DrawablePtr pDrawable, GCPtr pGC,
			 int x, int y, unsigned int nglyph,
			 CharInfoPtr * ppci, pointer pglyphBase)
{
    struct saa_gc_priv *sgc = saa_gc(pGC);
    saa_access_t access;
    struct saa_screen_priv *sscreen = saa_screen(pGC->pScreen);

    SAA_FALLBACK(("to %p (%c), style %d alu %d\n", pDrawable,
		  saa_drawable_loc(pDrawable), pGC->fillStyle, pGC->alu));

    sscreen->fallback_count++;
    if (!saa_pad_write(pDrawable, NULL, FALSE, &access))
	goto out_no_access;;
    if (!saa_prepare_access_gc(pGC))
	goto out_no_gc;
    saa_swap(sgc, pGC, ops);
    pGC->ops->PolyGlyphBlt(pDrawable, pGC, x, y, nglyph, ppci, pglyphBase);
    saa_swap(sgc, pGC, ops);
    saa_finish_access_gc(pGC);
 out_no_gc:
    saa_fad_write(pDrawable, access);
 out_no_access:
    sscreen->fallback_count--;
}

static void
saa_check_push_pixels(GCPtr pGC, PixmapPtr pBitmap,
		      DrawablePtr pDrawable, int w, int h, int x, int y)
{
    struct saa_gc_priv *sgc = saa_gc(pGC);
    saa_access_t access;
    struct saa_screen_priv *sscreen = saa_screen(pGC->pScreen);

    SAA_FALLBACK(("from %p to %p (%c,%c)\n", pBitmap, pDrawable,
		  saa_drawable_loc(&pBitmap->drawable),
		  saa_drawable_loc(pDrawable)));

    sscreen->fallback_count++;
    if (!saa_pad_write(pDrawable, pGC, TRUE, &access))
	goto out_no_access;;
    if (!saa_pad_read_box(&pBitmap->drawable, 0, 0, w, h))
	goto out_no_src;
    if (!saa_prepare_access_gc(pGC))
	goto out_no_gc;
    saa_swap(sgc, pGC, ops);
    pGC->ops->PushPixels(pGC, pBitmap, pDrawable, w, h, x, y);
    saa_swap(sgc, pGC, ops);
    saa_finish_access_gc(pGC);
 out_no_gc:
    saa_fad_read(&pBitmap->drawable);
 out_no_src:
    saa_fad_write(pDrawable, access);
 out_no_access:
    sscreen->fallback_count--;
}

static void
saa_check_copy_window(WindowPtr pWin, DDXPointRec ptOldOrg, RegionPtr prgnSrc)
{
    DrawablePtr pDrawable = &pWin->drawable;
    ScreenPtr pScreen = pDrawable->pScreen;
    struct saa_screen_priv *sscreen = saa_screen(pScreen);
    int xoff, yoff;
    PixmapPtr pPixmap = saa_get_pixmap(&pWin->drawable, &xoff, &yoff);
    Bool ret;

    SAA_FALLBACK(("from %p\n", pWin));

    /* Only need the source bits, the destination region will be overwritten */

    sscreen->fallback_count++;
    REGION_TRANSLATE(pScreen, prgnSrc, xoff, yoff);
    ret = saa_prepare_access_pixmap(pPixmap, SAA_ACCESS_R, prgnSrc);
    REGION_TRANSLATE(pScreen, prgnSrc, -xoff, -yoff);
    if (!ret)
	goto out_no_access;;

    if (saa_prepare_access_pixmap(pPixmap, SAA_ACCESS_W, NULL)) {
	struct saa_pixmap *spix;
	RegionRec rgnDst;

	REGION_NULL(pScreen, &rgnDst);
	REGION_COPY(pScreen, &rgnDst, prgnSrc);

	saa_swap(sscreen, pScreen, CopyWindow);
	pScreen->CopyWindow(pWin, ptOldOrg, prgnSrc);
	saa_swap(sscreen, pScreen, CopyWindow);
	saa_finish_access_pixmap(pPixmap, SAA_ACCESS_W);

	spix = saa_get_saa_pixmap(pPixmap);
	if (spix->damage) {
	    int dx, dy;

	    dx = ptOldOrg.x - pWin->drawable.x;
	    dy = ptOldOrg.y - pWin->drawable.y;
	    REGION_TRANSLATE(pScreen, &rgnDst, -dx, -dy);
	    REGION_INTERSECT(pSreen, &rgnDst, &pWin->borderClip, &rgnDst);
	    REGION_TRANSLATE(pScreen, &rgnDst, xoff, yoff);

	    REGION_INTERSECT(pScreen, &rgnDst, &rgnDst,
			     saa_pix_damage_pending(spix));
	    saa_pixmap_dirty(pPixmap, FALSE, &rgnDst);
	}
	REGION_UNINIT(pScreen, &rgnDst);
    }
    saa_fad_read(pDrawable);
 out_no_access:
    sscreen->fallback_count--;
}

#ifdef RENDER

#if (GET_ABI_MAJOR(ABI_VIDEODRV_VERSION) >= 10)
static void
saa_src_validate(DrawablePtr pDrawable,
		 int x,
		 int y, int width, int height, unsigned int subWindowMode)
#else
static void
saa_src_validate(DrawablePtr pDrawable, int x, int y, int width, int height)
#endif
{
    ScreenPtr pScreen = pDrawable->pScreen;
    struct saa_screen_priv *sscreen = saa_screen(pScreen);
    int xoff, yoff;
    BoxRec box;
    RegionRec reg;
    RegionPtr dst;

    (void) saa_get_pixmap(pDrawable, &xoff, &yoff);
    box.x1 = x + xoff;
    box.y1 = y + yoff;
    box.x2 = box.x1 + width;
    box.y2 = box.y1 + height;

    dst = (sscreen->srcDraw == pDrawable) ?
	&sscreen->srcReg : &sscreen->maskReg;

    REGION_INIT(pScreen, &reg, &box, 1);
    REGION_UNION(pScreen, dst, dst, &reg);
    REGION_UNINIT(pScreen, &reg);

    if (sscreen->saved_SourceValidate) {
	saa_swap(sscreen, pScreen, SourceValidate);
	pScreen->SourceValidate(pDrawable, x, y, width, height
#if (GET_ABI_MAJOR(ABI_VIDEODRV_VERSION) >= 10)
				, subWindowMode
#endif
	    );
	saa_swap(sscreen, pScreen, SourceValidate);
    }
}

static void
saa_check_get_image(DrawablePtr pDrawable, int x, int y, int w, int h,
		    unsigned int format, unsigned long planeMask, char *d)
{
    ScreenPtr pScreen = pDrawable->pScreen;
    struct saa_screen_priv *sscreen = saa_screen(pScreen);

    SAA_FALLBACK(("from %p (%c)\n", pDrawable, saa_drawable_loc(pDrawable)));

    sscreen->fallback_count++;
    if (!saa_pad_read_box(pDrawable, x, y, w, h))
	goto out_no_access;;
    saa_swap(sscreen, pScreen, GetImage);
    pScreen->GetImage(pDrawable, x, y, w, h, format, planeMask, d);
    saa_swap(sscreen, pScreen, GetImage);
    saa_fad_read(pDrawable);
 out_no_access:
    sscreen->fallback_count--;
}

static void
saa_check_get_spans(DrawablePtr pDrawable,
		    int wMax,
		    DDXPointPtr ppt, int *pwidth, int nspans, char *pdstStart)
{
    ScreenPtr pScreen = pDrawable->pScreen;
    struct saa_screen_priv *sscreen = saa_screen(pScreen);

    SAA_FALLBACK(("from %p (%c)\n", pDrawable, saa_drawable_loc(pDrawable)));

    sscreen->fallback_count++;
    if (!saa_pad_read(pDrawable))
	goto out_no_access;;
    saa_swap(sscreen, pScreen, GetSpans);
    pScreen->GetSpans(pDrawable, wMax, ppt, pwidth, nspans, pdstStart);
    saa_swap(sscreen, pScreen, GetSpans);
    saa_fad_read(pDrawable);
 out_no_access:
    sscreen->fallback_count--;
}

/*
 * Compute composite regions taking transforms into account.
 * The caller must provide a pointer to an initialized dst_reg,
 * and the function returns pointers to set up source- and mask regions.
 * The source and mask regions must be uninitialized after use.
 */

Bool
saa_compute_composite_regions(ScreenPtr pScreen,
			      PicturePtr pSrc,
			      PicturePtr pMask,
			      PicturePtr pDst,
			      INT16 xSrc, INT16 ySrc, INT16 xMask,
			      INT16 yMask, INT16 xDst,
			      INT16 yDst, INT16 width, INT16 height,
			      RegionPtr dst_reg,
			      RegionPtr *src_reg,
			      RegionPtr *mask_reg)
{
    struct saa_screen_priv *sscreen = saa_screen(pScreen);
    RegionPtr srcReg = NULL;
    RegionPtr maskReg = NULL;
    Bool ret;
    int xoff, yoff;

    *src_reg = NULL;
    *mask_reg = NULL;

    if (pSrc->pDrawable) {
	REGION_NULL(pScreen, &sscreen->srcReg);
	srcReg = &sscreen->srcReg;
	sscreen->srcDraw = pSrc->pDrawable;
	if (pSrc != pDst)
	    REGION_TRANSLATE(pScreen, pSrc->pCompositeClip,
			     -pSrc->pDrawable->x, -pSrc->pDrawable->y);
    }

    if (pMask && pMask->pDrawable) {
	REGION_NULL(pScreen, &sscreen->maskReg);
	maskReg = &sscreen->maskReg;
	if (pMask != pDst && pMask != pSrc)
	    REGION_TRANSLATE(pScreen, pMask->pCompositeClip,
			     -pMask->pDrawable->x, -pMask->pDrawable->y);
    }

    REGION_TRANSLATE(pScreen, pDst->pCompositeClip,
		     -pDst->pDrawable->x, -pDst->pDrawable->y);

    sscreen->saved_SourceValidate = saa_src_validate;
    saa_swap(sscreen, pScreen, SourceValidate);
    ret = miComputeCompositeRegion(dst_reg, pSrc, pMask, pDst,
				   xSrc, ySrc, xMask, yMask,
				   xDst, yDst, width, height);
    saa_swap(sscreen, pScreen, SourceValidate);

    REGION_TRANSLATE(pScreen, pDst->pCompositeClip,
		     pDst->pDrawable->x, pDst->pDrawable->y);
    if (pSrc->pDrawable && pSrc != pDst)
	REGION_TRANSLATE(pScreen, pSrc->pCompositeClip,
			 pSrc->pDrawable->x, pSrc->pDrawable->y);
    if (pMask && pMask->pDrawable && pMask != pDst && pMask != pSrc)
	REGION_TRANSLATE(pScreen, pMask->pCompositeClip,
			 pMask->pDrawable->x, pMask->pDrawable->y);

    if (!ret) {
	if (srcReg)
	    REGION_UNINIT(pScreen, srcReg);
	if (maskReg)
	    REGION_UNINIT(pScreen, maskReg);

	return FALSE;
    }

    *src_reg = srcReg;
    *mask_reg = maskReg;

    /*
     * Translate dst region to pixmap space.
     */
    (void) saa_get_pixmap(pDst->pDrawable, &xoff, &yoff);
    REGION_TRANSLATE(pScreen, dst_reg, pDst->pDrawable->x + xoff,
		     pDst->pDrawable->y + yoff);


    return TRUE;
}

static Bool
saa_prepare_composite_reg(ScreenPtr pScreen,
			  CARD8 op,
			  PicturePtr pSrc,
			  PicturePtr pMask,
			  PicturePtr pDst,
			  INT16 xSrc,
			  INT16 ySrc,
			  INT16 xMask,
			  INT16 yMask,
			  INT16 xDst,
			  INT16 yDst,
			  CARD16 width,
			  CARD16 height,
			  RegionPtr src_region,
			  RegionPtr mask_region,
			  RegionPtr dst_region,
			  saa_access_t * access)
{
    RegionPtr dstReg = NULL;
    PixmapPtr pSrcPix = NULL;
    PixmapPtr pMaskPix = NULL;
    PixmapPtr pDstPix;
    struct saa_pixmap *dst_spix;

    *access = SAA_ACCESS_W;

    if (pSrc->pDrawable)
	pSrcPix = saa_get_drawable_pixmap(pSrc->pDrawable);
    if (pMask && pMask->pDrawable)
	pMaskPix = saa_get_drawable_pixmap(pMask->pDrawable);

    /*
     * Don't limit alphamaps readbacks for now until we've figured out how that
     * should be done.
     */

    if (pSrc->alphaMap && pSrc->alphaMap->pDrawable)
	if (!saa_pad_read(pSrc->alphaMap->pDrawable))
	    goto out_no_src_alpha;
    if (pMask && pMask->alphaMap && pMask->alphaMap->pDrawable)
	if (!saa_pad_read(pMask->alphaMap->pDrawable))
	    goto out_no_mask_alpha;
    if (pSrcPix)
	if (!saa_prepare_access_pixmap(pSrcPix, SAA_ACCESS_R, src_region))
	    goto out_no_src;
    if (pMaskPix)
	if (!saa_prepare_access_pixmap(pMaskPix, SAA_ACCESS_R, mask_region))
	    goto out_no_mask;

    pDstPix = saa_get_drawable_pixmap(pDst->pDrawable);
    dst_spix = saa_get_saa_pixmap(pDstPix);

    if (dst_spix->damage && saa_op_reads_destination(op)) {
	dstReg = dst_region;
	*access |= SAA_ACCESS_R;
    }

    if (pDst->alphaMap && pDst->alphaMap->pDrawable)
	if (!saa_prepare_access_pixmap
	    (saa_get_drawable_pixmap(pDst->alphaMap->pDrawable),
	     *access, dstReg))
	    goto out_no_dst_alpha;

    if (!saa_prepare_access_pixmap(pDstPix, *access, dstReg))
	goto out_no_dst;

    return TRUE;

 out_no_dst:
    LogMessage(X_ERROR, "No dst\n");
    saa_finish_access_pixmap
	(saa_get_drawable_pixmap(pDst->alphaMap->pDrawable), *access);
 out_no_dst_alpha:
    LogMessage(X_ERROR, "No dst alpha\n");
    if (pMaskPix)
	saa_finish_access_pixmap(pMaskPix, SAA_ACCESS_R);
 out_no_mask:
    LogMessage(X_ERROR, "No mask\n");
    if (pSrcPix)
	saa_finish_access_pixmap(pSrcPix, SAA_ACCESS_R);
 out_no_src:
    LogMessage(X_ERROR, "No src\n");
    if (pMask && pMask->alphaMap && pMask->alphaMap->pDrawable)
	saa_fad_read(pMask->alphaMap->pDrawable);
 out_no_mask_alpha:
    LogMessage(X_ERROR, "No mask alpha\n");
    if (pSrc && pSrc->alphaMap && pSrc->alphaMap->pDrawable)
	saa_fad_read(pSrc->alphaMap->pDrawable);
 out_no_src_alpha:
    LogMessage(X_ERROR, "No src alpha\n");
    return FALSE;

}

void
saa_check_composite(CARD8 op,
		    PicturePtr pSrc,
		    PicturePtr pMask,
		    PicturePtr pDst,
		    INT16 xSrc,
		    INT16 ySrc,
		    INT16 xMask,
		    INT16 yMask,
		    INT16 xDst, INT16 yDst, CARD16 width, CARD16 height,
		    RegionPtr src_region,
		    RegionPtr mask_region,
		    RegionPtr dst_region)
{
    ScreenPtr pScreen = pDst->pDrawable->pScreen;
    PictureScreenPtr ps = GetPictureScreen(pScreen);
    struct saa_screen_priv *sscreen = saa_screen(pScreen);
    saa_access_t access;
    PixmapPtr pixmap;

    sscreen->fallback_count++;
    if (!saa_prepare_composite_reg(pScreen, op, pSrc, pMask, pDst, xSrc,
				   ySrc, xMask, yMask, xDst, yDst, width,
				   height,
				   src_region,
				   mask_region,
				   dst_region,
				   &access)) {
	goto out_no_access;;
    }

    saa_swap(sscreen, ps, Composite);
    ps->Composite(op,
		  pSrc,
		  pMask,
		  pDst, xSrc, ySrc, xMask, yMask, xDst, yDst, width, height);
    saa_swap(sscreen, ps, Composite);
    if (pMask && pMask->pDrawable != NULL)
	saa_fad_read(pMask->pDrawable);
    if (pSrc->pDrawable != NULL)
	saa_fad_read(pSrc->pDrawable);
    pixmap = saa_get_drawable_pixmap(pDst->pDrawable);
    saa_finish_access_pixmap(pixmap, access);
    saa_pixmap_dirty(pixmap, FALSE, dst_region);
    if (pDst->alphaMap && pDst->alphaMap->pDrawable) {
	pixmap = saa_get_drawable_pixmap(pDst->alphaMap->pDrawable);
	saa_finish_access_pixmap(pixmap, access);
	saa_pixmap_dirty(pixmap, FALSE, dst_region);
    }
    if (pSrc->alphaMap && pSrc->alphaMap->pDrawable)
	saa_fad_read(pSrc->alphaMap->pDrawable);
    if (pMask && pMask->alphaMap && pMask->alphaMap->pDrawable)
	saa_fad_read(pMask->alphaMap->pDrawable);
 out_no_access:
    sscreen->fallback_count--;
}

static void
saa_check_add_traps(PicturePtr pPicture,
		    INT16 x_off, INT16 y_off, int ntrap, xTrap * traps)
{
    ScreenPtr pScreen = pPicture->pDrawable->pScreen;
    PictureScreenPtr ps = GetPictureScreen(pScreen);
    struct saa_screen_priv *sscreen = saa_screen(pScreen);
    saa_access_t access;

    SAA_FALLBACK(("to pict %p (%c)\n", saa_drawable_loc(pPicture->pDrawable)));

    sscreen->fallback_count++;
    if (!saa_pad_write(pPicture->pDrawable, NULL, FALSE, &access))
	goto out_no_access;
    saa_swap(sscreen, ps, AddTraps);
    ps->AddTraps(pPicture, x_off, y_off, ntrap, traps);
    saa_swap(sscreen, ps, AddTraps);
    saa_fad_write(pPicture->pDrawable, access);
 out_no_access:
    sscreen->fallback_count--;
}

#endif

void
saa_unaccel_setup(ScreenPtr pScreen)
{
#ifdef RENDER
    PictureScreenPtr ps = GetPictureScreenIfSet(pScreen);
#endif
    struct saa_screen_priv *sscreen = saa_screen(pScreen);

    saa_wrap(sscreen, pScreen, GetImage, saa_check_get_image);
    saa_wrap(sscreen, pScreen, GetSpans, saa_check_get_spans);
    saa_wrap(sscreen, pScreen, CopyWindow, saa_check_copy_window);

#ifdef RENDER
    if (ps) {
	saa_wrap(sscreen, ps, AddTraps, saa_check_add_traps);
    }
#endif
}

void
saa_unaccel_takedown(ScreenPtr pScreen)
{
#ifdef RENDER
    PictureScreenPtr ps = GetPictureScreenIfSet(pScreen);
#endif
    struct saa_screen_priv *sscreen = saa_screen(pScreen);

    saa_unwrap(sscreen, pScreen, GetImage);
    saa_unwrap(sscreen, pScreen, GetSpans);
    saa_unwrap(sscreen, pScreen, CopyWindow);

#ifdef RENDER
    if (ps) {
	saa_unwrap(sscreen, ps, AddTraps);
    }
#endif
}

GCOps saa_gc_ops = {
    saa_check_fill_spans,
    saa_check_set_spans,
    saa_check_put_image,
    saa_copy_area,
    saa_check_copy_plane,
    saa_check_poly_point,
    saa_check_poly_lines,
    saa_check_poly_segment,
    miPolyRectangle,
    saa_check_poly_arc,
    miFillPolygon,
    saa_check_poly_fill_rect,
    miPolyFillArc,
    miPolyText8,
    miPolyText16,
    miImageText8,
    miImageText16,
    saa_check_image_glyph_blt,
    saa_check_poly_glyph_blt,
    saa_check_push_pixels,
};
07070100000012000041ED00000000000000000000000261A68E1200000000000000000000000000000000000000000000002000000000xf86-video-vmware-13.3.0+12/src07070100000013000081A400000000000000000000000161A68E12000008C2000000000000000000000000000000000000002C00000000xf86-video-vmware-13.3.0+12/src/Makefile.am#  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 \
	common_compat.h
07070100000014000081A400000000000000000000000161A68E1200006D2E000000000000000000000000000000000000002E00000000xf86-video-vmware-13.3.0+12/src/bits2pixels.c/* **********************************************************
 * 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;
}
07070100000015000081A400000000000000000000000161A68E1200000241000000000000000000000000000000000000002E00000000xf86-video-vmware-13.3.0+12/src/bits2pixels.h/* **********************************************************
 * 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_ */
07070100000016000081A400000000000000000000000161A68E12000003AC000000000000000000000000000000000000003000000000xf86-video-vmware-13.3.0+12/src/common_compat.h#ifndef _COMMON_COMPAT_H_
#define _COMMOM_COMPAT_H_

#if (GET_ABI_MAJOR(ABI_VIDEODRV_VERSION) >= 18)
#define CONST_ABI_18_0 const
#else
#define CONST_ABI_18_0
#endif

#if (GET_ABI_MAJOR(ABI_VIDEODRV_VERSION) >= 16)
#define CONST_ABI_16_0 const
#else
#define CONST_ABI_16_0
#endif

#if ((GET_ABI_MAJOR(ABI_VIDEODRV_VERSION) >= 16) && \
     (GET_ABI_MAJOR(ABI_VIDEODRV_VERSION) < 19))
#define CONST_ABI_16_TO_19 const
#else
#define CONST_ABI_16_TO_19
#endif

#if (GET_ABI_MAJOR(ABI_VIDEODRV_VERSION) < 13)
static inline void
xf86SaveModeContents(DisplayModePtr intern, const DisplayModeRec *mode)
{
    *intern = *mode;
    intern->prev = intern->next = NULL;
    intern->name = NULL;
    intern->PrivSize = 0;
    intern->PrivFlags = 0;
    intern->Private = NULL;
}
#endif

#ifndef fbGetRotatedPixmap
#define fbGetRotatedPixmap(_pGC) NULL
#endif

#ifndef DRM_MODE_FB_DIRTY_MAX_CLIPS
#define DRM_MODE_FB_DIRTY_MAX_CLIPS 256
#endif

#endif

07070100000017000081A400000000000000000000000161A68E1200000E92000000000000000000000000000000000000002D00000000xf86-video-vmware-13.3.0+12/src/compat-api.h/*
 * 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

#if ABI_VIDEODRV_VERSION >= SET_ABI_VERSION(23, 0)
#define BLOCKHANDLER_ARGS_DECL ScreenPtr arg, pointer pTimeout
#define BLOCKHANDLER_ARGS arg, pTimeout
#else
#define BLOCKHANDLER_ARGS_DECL ScreenPtr arg, pointer pTimeout, pointer pReadmask
#define BLOCKHANDLER_ARGS arg, pTimeout, pReadmask
#endif

#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
07070100000018000081A400000000000000000000000161A68E1200000376000000000000000000000000000000000000002B00000000xf86-video-vmware-13.3.0+12/src/guest_os.h/* *********************************************************
 * 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 
07070100000019000081A400000000000000000000000161A68E120000002C000000000000000000000000000000000000002F00000000xf86-video-vmware-13.3.0+12/src/includeCheck.h/* This space intentionally left blank. */

0707010000001A000081A400000000000000000000000161A68E120000031A000000000000000000000000000000000000002E00000000xf86-video-vmware-13.3.0+12/src/svga_escape.h/* **********************************************************
 * 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_ */
0707010000001B000081A400000000000000000000000161A68E1200000848000000000000000000000000000000000000002E00000000xf86-video-vmware-13.3.0+12/src/svga_limits.h/* **********************************************************
 * 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
0707010000001C000081A400000000000000000000000161A68E12000005DC000000000000000000000000000000000000002D00000000xf86-video-vmware-13.3.0+12/src/svga_modes.h/* **********************************************************
 * 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) \
   SVGA_DEFAULT_MODE(2560, 1440) \
   /* 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_ */
0707010000001D000081A400000000000000000000000161A68E12000004CC000000000000000000000000000000000000002F00000000xf86-video-vmware-13.3.0+12/src/svga_overlay.h/* **********************************************************
 * 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_ */
0707010000001E000081A400000000000000000000000161A68E120000D5E0000000000000000000000000000000000000002B00000000xf86-video-vmware-13.3.0+12/src/svga_reg.h/**********************************************************
 * 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;

#define SVGA_CB_MAX_COMMAND_SIZE (32 * 1024) /* 32 KB */

/*
 * 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
0707010000001F000081A400000000000000000000000161A68E12000004D5000000000000000000000000000000000000002E00000000xf86-video-vmware-13.3.0+12/src/svga_struct.h/* **********************************************************
 * 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
07070100000020000081A400000000000000000000000161A68E12000010C1000000000000000000000000000000000000003100000000xf86-video-vmware-13.3.0+12/src/vm_basic_types.h/* **********************************************************
 * 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
07070100000021000081A400000000000000000000000161A68E120000093F000000000000000000000000000000000000003400000000xf86-video-vmware-13.3.0+12/src/vm_device_version.h/* **********************************************************
 * 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 */
07070100000022000081A400000000000000000000000161A68E120000CC32000000000000000000000000000000000000002900000000xf86-video-vmware-13.3.0+12/src/vmware.c/* **********************************************************
 * 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 "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"
#include "common_compat.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 rIndex)
{
    /*
     * 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 ret;
#if (GET_ABI_MAJOR(ABI_VIDEODRV_VERSION) < 22)
    int oldsigio;
    
    oldsigio = xf86BlockSIGIO();
#else
    input_lock();
#endif
    outl(pVMWARE->indexReg, rIndex);
    ret = inl(pVMWARE->valueReg);
#if (GET_ABI_MAJOR(ABI_VIDEODRV_VERSION) < 22)
    xf86UnblockSIGIO(oldsigio);
#else
    input_unlock();
#endif
    return ret;
}

void
vmwareWriteReg(VMWAREPtr pVMWARE, int wIndex, 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).
     */
#if (GET_ABI_MAJOR(ABI_VIDEODRV_VERSION) < 22)
    int oldsigio;
    oldsigio = xf86BlockSIGIO();
#else
    input_lock();
#endif
    outl(pVMWARE->indexReg, wIndex);
    outl(pVMWARE->valueReg, value);
#if (GET_ABI_MAJOR(ABI_VIDEODRV_VERSION) < 22)
    xf86UnblockSIGIO(oldsigio);
#else
    input_unlock();
#endif
}

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]);
    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 = vmwareReadReg(pVMWARE, SVGA_REG_CAPABILITIES) &
	SVGA_CAP_PITCHLOCK;
#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;

    if (pVMWARE->vmwareCapability & SVGA_CAP_PITCHLOCK)
	vmwareWriteReg(pVMWARE, SVGA_REG_PITCHLOCK, 0);
    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;
   char * modeName;

   mode = malloc(sizeof(DisplayModeRec));
   memset(mode, 0, sizeof *mode);

   modeName = malloc(strlen(name) + 1);
   strcpy(modeName, name);
   mode->name = modeName;
   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)) {
       CONST_ABI_18_0 char *topology = xf86GetOptValString(options, OPTION_GUI_LAYOUT);
       if (topology) {
          pVMWARE->xineramaState =
             VMWAREParseTopologyString(pScrn, topology,
				       &pVMWARE->xineramaNumOutputs, "gui");

         pVMWARE->xineramaStatic = pVMWARE->xineramaState != NULL;

         free((void *)topology);
       }
    } else if (useXinerama &&
	       xf86IsOptionSet(options, OPTION_STATIC_XINERAMA)) {
       CONST_ABI_18_0 char *topology = xf86GetOptValString(options, OPTION_STATIC_XINERAMA);
       if (topology) {
          pVMWARE->xineramaState =
             VMWAREParseTopologyString(pScrn, topology,
				       &pVMWARE->xineramaNumOutputs,
				       "static Xinerama");

         pVMWARE->xineramaStatic = pVMWARE->xineramaState != NULL;

         free((void *)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.
     */
    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 */
07070100000023000081A400000000000000000000000161A68E1200001AB0000000000000000000000000000000000000002900000000xf86-video-vmware-13.3.0+12/src/vmware.h/* **********************************************************
 * 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
07070100000024000081A400000000000000000000000161A68E1200003CD1000000000000000000000000000000000000003300000000xf86-video-vmware-13.3.0+12/src/vmware_bootstrap.c/*
 * 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"
#include <stdint.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 XSERVER_PLATFORM_BUS
#include "xf86platformBus.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_DRIVER_NAME "vmware"
#define VMWARE_NAME "vmware"

static char vmware_driver_name[] = VMWARE_DRIVER_NAME;

#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)

#if !XSERVER_LIBPCIACCESS
static const char VMWAREBuildStr[] = "VMware Guest X Server "
    VMWARE_DRIVER_VERSION_STRING " - build=$Name$\n";
#else
static char vmware_name[] = VMWARE_NAME;
#endif

/*
 * 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;
}

/*
 * Also in vmwgfx_hosted.h, which we don't include.
 */
void *
vmwgfx_hosted_detect(void);

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;

    /*
     * Can't run legacy hosted
     */
    if (vmwgfx_hosted_detect())
	return FALSE;
#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]);
    pciInfo = xf86GetPciInfoForEntity(pEnt->index);
    if (pciInfo == NULL)
        return FALSE;

    pScrn->chipset = xstrdup(xf86TokenToString(VMWAREChipsets,
					       DEVICE_ID(pciInfo)));
    if (pScrn->chipset == NULL)
	return FALSE;

    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;

    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;
    }

    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

#ifdef XSERVER_PLATFORM_BUS
static Bool
VMwarePlatformProbe(DriverPtr drv, int entity, int flags,
                    struct xf86_platform_device *dev, intptr_t match_data)
{
    ScrnInfoPtr pScrn;
    int scrnFlag = 0;

    if (!dev->pdev)
        return FALSE;

    if (flags & PLATFORM_PROBE_GPU_SCREEN)
        scrnFlag = XF86_ALLOCATE_GPU_SCREEN;

    pScrn = xf86AllocateScreen(drv, scrnFlag);
    if (!pScrn)
        return FALSE;

    if (xf86IsEntitySharable(entity))
        xf86SetEntityShared(entity);

    xf86AddEntityToScreen(pScrn, entity);

    pScrn->driverVersion = VMWARE_DRIVER_VERSION;
    pScrn->driverName = VMWARE_DRIVER_NAME;
    pScrn->name = VMWARE_NAME;
    pScrn->Probe = NULL;
#ifdef BUILD_VMWGFX
    vmwgfx_hookup(pScrn);
#else
    vmwlegacy_hookup(pScrn);
#endif
    pScrn->driverPrivate = pScrn->PreInit;
    pScrn->PreInit = VMwarePreinitStub;

    return TRUE;
}
#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)
{
   uint32_t *flag;
   xorgRRModeMM *modemm;

   switch (op) {
   case GET_REQUIRED_HW_INTERFACES:
      flag = (uint32_t *)data;

      if (flag) {
#ifdef BUILD_VMWGFX
	  vmwgfx_modify_flags(flag);
#else
         *flag = HW_IO | HW_MMIO;
#endif
      }
      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;
#if GET_ABI_MAJOR(ABI_VIDEODRV_VERSION) >= 18
   case SUPPORTS_SERVER_FDS:
      return TRUE;
#endif
   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 GET_ABI_MAJOR(ABI_VIDEODRV_VERSION) >= 4
#if XSERVER_LIBPCIACCESS
    VMwareDeviceMatch,
    VMwarePciProbe,
#else
    NULL,
    NULL,
#endif
#endif
#if GET_ABI_MAJOR(ABI_VIDEODRV_VERSION) >= 13
#ifdef XSERVER_PLATFORM_BUS
    VMwarePlatformProbe,
#else
    NULL,
#endif
#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 */
07070100000025000081A400000000000000000000000161A68E1200000852000000000000000000000000000000000000003300000000xf86-video-vmware-13.3.0+12/src/vmware_bootstrap.h/*
 * 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);
void
vmwgfx_modify_flags(uint32_t *flags);
#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
07070100000026000081A400000000000000000000000161A68E1200001264000000000000000000000000000000000000003000000000xf86-video-vmware-13.3.0+12/src/vmware_common.c/*
 * 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;
}
07070100000027000081A400000000000000000000000161A68E120000064A000000000000000000000000000000000000003000000000xf86-video-vmware-13.3.0+12/src/vmware_common.h/*
 * 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
07070100000028000081A400000000000000000000000161A68E12000040A9000000000000000000000000000000000000002D00000000xf86-video-vmware-13.3.0+12/src/vmwarectrl.c/*
 * 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);
   }
}
07070100000029000081A400000000000000000000000161A68E120000074C000000000000000000000000000000000000002D00000000xf86-video-vmware-13.3.0+12/src/vmwarectrl.h/*
 * 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_ */
0707010000002A000081A400000000000000000000000161A68E1200000D9C000000000000000000000000000000000000003200000000xf86-video-vmware-13.3.0+12/src/vmwarectrlproto.h/*
 * 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;
   CARD32 majorVersion;
   CARD32 minorVersion;
} xVMwareCtrlQueryVersionReq;
#define sz_xVMwareCtrlQueryVersionReq 12

typedef struct {
   BYTE    type; /* X_Reply */
   BYTE    pad1;
   CARD16  sequenceNumber;
   CARD32  length;
   CARD32  majorVersion;
   CARD32  minorVersion;
   CARD32  pad2;
   CARD32  pad3;
   CARD32  pad4;
   CARD32  pad5;
} xVMwareCtrlQueryVersionReply;
#define sz_xVMwareCtrlQueryVersionReply 32

typedef struct {
   CARD8  reqType;           /* always X_VMwareCtrlReqCode */
   CARD8  VMwareCtrlReqType; /* always X_VMwareCtrlSetRes */
   CARD16 length;
   CARD32 screen;
   CARD32 x;
   CARD32 y;
} xVMwareCtrlSetResReq;
#define sz_xVMwareCtrlSetResReq 16

typedef struct {
   BYTE   type; /* X_Reply */
   BYTE   pad1;
   CARD16 sequenceNumber;
   CARD32 length;
   CARD32 screen;
   CARD32 x;
   CARD32 y;
   CARD32 pad2;
   CARD32 pad3;
   CARD32 pad4;
} xVMwareCtrlSetResReply;
#define sz_xVMwareCtrlSetResReply 32

/* Version 0.2 definitions. */

typedef struct {
   CARD8  reqType;           /* always X_VMwareCtrlReqCode */
   CARD8  VMwareCtrlReqType; /* always X_VMwareCtrlSetTopology */
   CARD16 length;
   CARD32 screen;
   CARD32 number;
   CARD32 pad1;
} xVMwareCtrlSetTopologyReq;
#define sz_xVMwareCtrlSetTopologyReq 16

typedef struct {
   BYTE   type; /* X_Reply */
   BYTE   pad1;
   CARD16 sequenceNumber;
   CARD32 length;
   CARD32 screen;
   CARD32 pad2;
   CARD32 pad3;
   CARD32 pad4;
   CARD32 pad5;
   CARD32 pad6;
} xVMwareCtrlSetTopologyReply;
#define sz_xVMwareCtrlSetTopologyReply 32

#endif /* _VMWARE_CTRL_PROTO_H_ */
0707010000002B000081A400000000000000000000000161A68E1200003DC2000000000000000000000000000000000000002D00000000xf86-video-vmware-13.3.0+12/src/vmwarecurs.c/* **********************************************************
 * 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 */
0707010000002C000081A400000000000000000000000161A68E12000013ED000000000000000000000000000000000000002E00000000xf86-video-vmware-13.3.0+12/src/vmwaremodes.c/*
 * 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"
#include "common_compat.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;
	CONST_ABI_18_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 = (unsigned)(((size_t)dispModeList -
	                                (size_t)pScrn->display->modes) /
	                               sizeof(*dispModeList));
	}

	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.");
}
0707010000002D000081A400000000000000000000000161A68E1200009633000000000000000000000000000000000000002E00000000xf86-video-vmware-13.3.0+12/src/vmwarevideo.c/*
 * 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 "common_compat.h"

#include <X11/extensions/Xv.h>

#ifndef HAVE_XORG_SERVER_1_5_0
#include <xf86_ansic.h>
#include <xf86_libc.h>
#endif

static CONST_ABI_16_0 char xv_adapt_name[] = "VMWare Overlay Video Engine";
static CONST_ABI_16_0 char xv_image_name[] = "XV_IMAGE";

#define HAVE_FILLKEYHELPERDRAWABLE \
    ((GET_ABI_MAJOR(ABI_VIDEODRV_VERSION) >= 2) ||  \
     ((GET_ABI_MAJOR(ABI_VIDEODRV_VERSION) == 1) && \
      (GET_ABI_MINOR(ABI_VIDEODRV_VERSION) >= 2)))

#if HAVE_FILLKEYHELPERDRAWABLE
#include <damage.h>
#endif

#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_name,
       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
};

static CONST_ABI_16_TO_19 char xv_colorkey_name[] = "XV_COLORKEY";
static CONST_ABI_16_TO_19 char xv_autopaint_name[] = "XV_AUTOPAINT_COLORKEY";

#define VMWARE_VID_NUM_ATTRIBUTES 2
static XF86AttributeRec vmwareVideoAttributes[] =
{
    {
        XvGettable | XvSettable,
        0x000000,
        0xffffff,
        xv_colorkey_name,
    },
    {
        XvGettable | XvSettable,
        0,
        1,
        xv_autopaint_name,
    }
};

/*
 * 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 = xv_adapt_name;
    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
	if (draw->type == DRAWABLE_WINDOW) {
	    xf86XVFillKeyHelperDrawable(draw, pVid->colorKey, clipBoxes);
	    DamageDamageRegion(draw, clipBoxes);
	} else {
	    xf86XVFillKeyHelper(pScrn->pScreen, 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;
        /* Old hosts can not handle more then these regs */
        struct _item items[SVGA_VIDEO_DATA_GMRID];
    };

    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_DATA_GMRID; 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;
}

0707010000002E000081A400000000000000000000000161A68E120000492E000000000000000000000000000000000000003100000000xf86-video-vmware-13.3.0+12/src/vmwarexinerama.c/*
 * 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");
   }
}
0707010000002F000041ED00000000000000000000000261A68E1200000000000000000000000000000000000000000000002700000000xf86-video-vmware-13.3.0+12/vmwarectrl07070100000030000081A400000000000000000000000161A68E1200000048000000000000000000000000000000000000003200000000xf86-video-vmware-13.3.0+12/vmwarectrl/.gitignore#		Add & Override for this directory and it's subdirectories
vmwarectrl
07070100000031000081A400000000000000000000000161A68E12000000E1000000000000000000000000000000000000003300000000xf86-video-vmware-13.3.0+12/vmwarectrl/Makefile.am
if BUILD_VMWARECTRL

bin_PROGRAMS = vmwarectrl

AM_CPPFLAGS = -I$(top_srcdir)/src
AM_CFLAGS = $(X11_CFLAGS)
AM_LDFLAGS = $(X11_LIBS)

vmwarectrl_SOURCES = vmwarectrl.c libvmwarectrl.c libvmwarectrl.h

endif BUILD_VMWARECTRL
07070100000032000081A400000000000000000000000161A68E1200001C37000000000000000000000000000000000000003700000000xf86-video-vmware-13.3.0+12/vmwarectrl/libvmwarectrl.c/*
 * 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).
 */

/*
 * libvmwarectrl.c --
 *
 *      The VMWARE_CTRL client library.
 */


#include <X11/Xlibint.h>
#include "libvmwarectrl.h"
#include "vmwarectrlproto.h"
#include <X11/extensions/Xext.h>
#include <X11/extensions/extutil.h>


/*
 * Static data and functions.
 */
 
static XExtensionInfo _vmwarectrl_info_data;
static XExtensionInfo *vmwarectrl_info = &_vmwarectrl_info_data;
static char *vmwarectrl_extension_name = VMWARE_CTRL_PROTOCOL_NAME;

#define VMwareCtrlCheckExtension(dpy, i, val) \
  XextCheckExtension(dpy, i, vmwarectrl_extension_name, val)

static int close_display(Display *dpy, XExtCodes *codes);

static /* const */ XExtensionHooks vmwarectrl_extension_hooks = {
    NULL,          /* create_gc */
    NULL,          /* copy_gc */
    NULL,          /* flush_gc */
    NULL,          /* free_gc */
    NULL,          /* create_font */
    NULL,          /* free_font */
    close_display, /* close_display */
    NULL,          /* wire_to_event */
    NULL,          /* event_to_wire */
    NULL,          /* error */
    NULL,          /* error_string */
};

static XEXT_GENERATE_CLOSE_DISPLAY (close_display, vmwarectrl_info)

static XEXT_GENERATE_FIND_DISPLAY (find_display, vmwarectrl_info,
				   vmwarectrl_extension_name,
				   &vmwarectrl_extension_hooks,
				   0, NULL)

/*
 *----------------------------------------------------------------------------
 *
 * VMwareCtrl_QueryExtension --
 *
 *      Standard QueryExtension implementation. Not very interesting for
 *      VMWARE_CTRL as it doesn't define any events or errors.
 *
 * Results:
 *      True if information is successfully retrieved. False otherwise.
 *
 * Side effects:
 *      None.
 *
 *----------------------------------------------------------------------------
 */

Bool
VMwareCtrl_QueryExtension(Display *dpy,     // IN:
                          int *event_basep, // OUT:
                          int *error_basep) // OUT:
{
   XExtDisplayInfo *info = find_display(dpy);

   if (XextHasExtension(info)) {
      *event_basep = info->codes->first_event;
      *error_basep = info->codes->first_error;
      return True;
   } else {
      return False;
   }
}


/*
 *----------------------------------------------------------------------------
 *
 * VMwareCtrl_QueryVersion --
 *
 *      Send the QueryVersion command to the driver and return the results.
 *
 * Results:
 *      True if information is successfully retrieved. False otherwise.
 *
 * Side effects:
 *      None.
 *
 *----------------------------------------------------------------------------
 */

Bool
VMwareCtrl_QueryVersion(Display *dpy,      // IN:
                        int *majorVersion, // OUT:
                        int *minorVersion) // OUT:
{
   xVMwareCtrlQueryVersionReply rep;
   xVMwareCtrlQueryVersionReq *req;
   XExtDisplayInfo *info = find_display(dpy);
   Bool ret = False;

   VMwareCtrlCheckExtension(dpy, info, False);
   LockDisplay(dpy);

   GetReq(VMwareCtrlQueryVersion, req);
   req->reqType = info->codes->major_opcode;
   req->VMwareCtrlReqType = X_VMwareCtrlQueryVersion;

   if (!_XReply(dpy, (xReply *)&rep, 0, xFalse)) {
      goto exit;
   }
   *majorVersion = rep.majorVersion;
   *minorVersion = rep.minorVersion;

   ret = True;

exit:
   UnlockDisplay(dpy);
   SyncHandle();

   return ret;
}


/*
 *----------------------------------------------------------------------------
 *
 * VMwareCtrl_SetRes --
 *
 *      Send the SetRes command to the driver.
 *
 * Results:
 *      True if the resolution was set. False otherwise.
 *
 * Side effects:
 *      None.
 *
 *----------------------------------------------------------------------------
 */

Bool
VMwareCtrl_SetRes(Display *dpy, // IN:
                  int screen,   // IN:
                  int x,        // IN:
                  int y)        // IN:
{
   xVMwareCtrlSetResReply rep;
   xVMwareCtrlSetResReq *req;
   XExtDisplayInfo *info = find_display(dpy);
   Bool ret = False;

   VMwareCtrlCheckExtension(dpy, info, False);
   LockDisplay(dpy);

   GetReq(VMwareCtrlSetRes, req);
   req->reqType = info->codes->major_opcode;
   req->VMwareCtrlReqType = X_VMwareCtrlSetRes;
   req->screen = screen;
   req->x = x;
   req->y = y;

   if (!_XReply(dpy, (xReply *)&rep,
                (SIZEOF(xVMwareCtrlSetResReply) - SIZEOF(xReply)) >> 2,
                xFalse)) {
      goto exit;
   }

   ret = True;

exit:
   UnlockDisplay(dpy);
   SyncHandle();

   return ret;
}


/*
 *----------------------------------------------------------------------------
 *
 * VMwareCtrl_SetTopology --
 *
 *      Send the SetTopology command to the driver.
 *
 * Results:
 *      True if the resolution and xinerama topology were set. False otherwise.
 *
 * Side effects:
 *      None.
 *
 *----------------------------------------------------------------------------
 */

Bool
VMwareCtrl_SetTopology(Display *dpy,          // IN:
                       int screen,            // IN:
                       xXineramaScreenInfo extents[], // IN:
                       int number)            // IN:
{
   xVMwareCtrlSetTopologyReply rep;
   xVMwareCtrlSetTopologyReq *req;
   XExtDisplayInfo *info = find_display(dpy);
   Bool ret = False;
   long len;

   VMwareCtrlCheckExtension(dpy, info, False);
   LockDisplay(dpy);

   GetReq(VMwareCtrlSetTopology, req);
   req->reqType = info->codes->major_opcode;
   req->VMwareCtrlReqType = X_VMwareCtrlSetTopology;
   req->screen = screen;
   req->number = number;

   len = ((long) number) << 1;
   SetReqLen(req, len, len);
   len <<= 2;
   _XSend(dpy, (char *)extents, len);

   if (!_XReply(dpy, (xReply *)&rep,
                (SIZEOF(xVMwareCtrlSetTopologyReply) - SIZEOF(xReply)) >> 2,
                xFalse)) {
      goto exit;
   }

   ret = True;

exit:
   UnlockDisplay(dpy);
   SyncHandle();

   return ret;
}
07070100000033000081A400000000000000000000000161A68E12000007B8000000000000000000000000000000000000003700000000xf86-video-vmware-13.3.0+12/vmwarectrl/libvmwarectrl.h/*
 * 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).
 */

/*
 * libvmwarectrl.c --
 *
 *      The VMWARE_CTRL client library.
 */


#ifndef _LIB_VMWARE_CTRL_H_
#define _LIB_VMWARE_CTRL_H_

#include <X11/X.h>
#include <X11/Xmd.h>
#include <X11/extensions/panoramiXproto.h>

Bool VMwareCtrl_QueryExtension(Display *dpy, int *event_basep, int *error_basep);
Bool VMwareCtrl_QueryVersion(Display *dpy, int *majorVersion, int *minorVersion);
Bool VMwareCtrl_SetRes(Display *dpy, int screen, int x, int y);
Bool VMwareCtrl_SetTopology(Display *dpy, int screen, xXineramaScreenInfo[], int number);

#endif /* _LIB_VMWARE_CTRL_H_ */
07070100000034000081A400000000000000000000000161A68E120000077D000000000000000000000000000000000000003400000000xf86-video-vmware-13.3.0+12/vmwarectrl/vmwarectrl.c#include <stdio.h>
#include <X11/Xlib.h>
#include <X11/Xlibint.h>
#include <X11/Xproto.h>
#include <X11/extensions/panoramiXproto.h>
#include <string.h>
#include <stdlib.h>

#include "libvmwarectrl.h"

int
main (int argc, char **argv)
{
   Display *dpy;
   char *displayName = NULL;
   int screen;
   int major, minor;

   dpy = XOpenDisplay(displayName);
   if (!dpy) {
      printf("Could not open default X Display\n");
      exit(EXIT_FAILURE);
   }
   screen = DefaultScreen(dpy);

   if (VMwareCtrl_QueryVersion(dpy, &major, &minor)) {
      printf("Got Extension version %d.%d\n", major, minor);
   } else {
      printf("VMWARE_CTRL Extension not found.\n");
      exit(EXIT_FAILURE);
   }

   if (argc >= 2) {
      if (strcmp(argv[1], "setres") == 0) {
         int x, y;
         if (argc < 4) {
            printf("Setres needs x and y too\n");
            exit(EXIT_FAILURE);
         }

         x = atoi(argv[2]);
         y = atoi(argv[3]);

         if (VMwareCtrl_SetRes(dpy, screen, x, y)) {
            printf("Set Res was successful\n");
         } else {
            printf("Set Res failed\n");
         }
      } else if (strcmp(argv[1], "settopology") == 0) {
         xXineramaScreenInfo extents[2];

         if (major == 0 && minor < 2) {
            printf("VMWARE_CTRL version >= 0.2 is required\n");
            exit(EXIT_FAILURE);
         }

         printf("Requesting hard-coded topology\n");

         extents[0].x_org = 0;
         extents[0].y_org = 0;
         extents[0].width = 800;
         extents[0].height = 600;
         extents[1].x_org = 800;
         extents[1].y_org = 0;
         extents[1].width = 800;
         extents[1].height = 600;
         if (VMwareCtrl_SetTopology(dpy, screen, extents, 2)) {
            printf("SetTopology was successful\n");
         } else {
            printf("SetTopology failed\n");
         }
      }
   }

   return EXIT_SUCCESS;
}
07070100000035000041ED00000000000000000000000261A68E1200000000000000000000000000000000000000000000002300000000xf86-video-vmware-13.3.0+12/vmwgfx07070100000036000081A400000000000000000000000161A68E120000033C000000000000000000000000000000000000002F00000000xf86-video-vmware-13.3.0+12/vmwgfx/Makefile.am
if BUILD_VMWGFX
noinst_LTLIBRARIES = libvmwgfx.la
libvmwgfx_la_CFLAGS = $(CWARNFLAGS) $(XORG_CFLAGS) @LIBDRM_CFLAGS@ @XATRACKER_CFLAGS@ @LIBUDEV_CFLAGS@ -I$(top_srcdir)/src -I$(top_srcdir)/saa
libvmwgfx_la_LIBADD = @LIBDRM_LIBS@ $(top_builddir)/saa/libsaa.la\
	@XATRACKER_LIBS@ @LIBUDEV_LIBS@
libvmwgfx_la_DEPENDENCIES = $(top_builddir)/saa/libsaa.la

libvmwgfx_la_SOURCES = \
	svga3d_reg.h \
	vmwgfx_driver.c \
	vmwgfx_driver.h \
	vmwgfx_drm.h \
	vmwgfx_crtc.c \
	vmwgfx_output.c \
	vmwgfx_dri2.c \
	vmwgfx_tex_video.c \
	vmwgfx_saa.c \
	vmwgfx_saa.h \
	vmwgfx_saa_priv.h \
	vmwgfx_drmi.c \
	vmwgfx_drmi.h \
	vmwgfx_overlay.c \
	vmwgfx_ctrl.c \
	vmwgfx_ctrl.h \
	vmwgfx_xa_composite.c \
	vmwgfx_xa_surface.c \
	vmwgfx_hosted.c \
	vmwgfx_hosted.h \
	vmwgfx_layout.c \
	vmwgfx_rr_inlines.h \
	vmwgfx_dri3.c \
	wsbm_util.h
endif
07070100000037000081A400000000000000000000000161A68E120000F62D000000000000000000000000000000000000003000000000xf86-video-vmware-13.3.0+12/vmwgfx/svga3d_reg.h/**********************************************************
 * 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.
 *
 **********************************************************/

/*
 * svga3d_reg.h --
 *
 *       SVGA 3D hardware definitions
 */

#ifndef _SVGA3D_REG_H_
#define _SVGA3D_REG_H_

#include "svga_reg.h"


/*
 * 3D Hardware Version
 *
 *   The hardware version is stored in the SVGA_FIFO_3D_HWVERSION fifo
 *   register.   Is set by the host and read by the guest.  This lets
 *   us make new guest drivers which are backwards-compatible with old
 *   SVGA hardware revisions.  It does not let us support old guest
 *   drivers.  Good enough for now.
 *
 */

#define SVGA3D_MAKE_HWVERSION(major, minor)      (((major) << 16) | ((minor) & 0xFF))
#define SVGA3D_MAJOR_HWVERSION(version)          ((version) >> 16)
#define SVGA3D_MINOR_HWVERSION(version)          ((version) & 0xFF)

typedef enum {
   SVGA3D_HWVERSION_WS5_RC1   = SVGA3D_MAKE_HWVERSION(0, 1),
   SVGA3D_HWVERSION_WS5_RC2   = SVGA3D_MAKE_HWVERSION(0, 2),
   SVGA3D_HWVERSION_WS51_RC1  = SVGA3D_MAKE_HWVERSION(0, 3),
   SVGA3D_HWVERSION_WS6_B1    = SVGA3D_MAKE_HWVERSION(1, 1),
   SVGA3D_HWVERSION_FUSION_11 = SVGA3D_MAKE_HWVERSION(1, 4),
   SVGA3D_HWVERSION_WS65_B1   = SVGA3D_MAKE_HWVERSION(2, 0),
   SVGA3D_HWVERSION_CURRENT   = SVGA3D_HWVERSION_WS65_B1,
} SVGA3dHardwareVersion;

/*
 * Generic Types
 */

typedef uint32 SVGA3dBool; /* 32-bit Bool definition */
#define SVGA3D_NUM_CLIPPLANES                   6
#define SVGA3D_MAX_SIMULTANEOUS_RENDER_TARGETS  8


/*
 * Surface formats.
 *
 * If you modify this list, be sure to keep GLUtil.c in sync. It
 * includes the internal format definition of each surface in
 * GLUtil_ConvertSurfaceFormat, and it contains a table of
 * human-readable names in GLUtil_GetFormatName.
 */

typedef enum SVGA3dSurfaceFormat {
   SVGA3D_FORMAT_INVALID = 0,

   SVGA3D_X8R8G8B8       = 1,
   SVGA3D_A8R8G8B8       = 2,

   SVGA3D_R5G6B5         = 3,
   SVGA3D_X1R5G5B5       = 4,
   SVGA3D_A1R5G5B5       = 5,
   SVGA3D_A4R4G4B4       = 6,

   SVGA3D_Z_D32          = 7,
   SVGA3D_Z_D16          = 8,
   SVGA3D_Z_D24S8        = 9,
   SVGA3D_Z_D15S1        = 10,

   SVGA3D_LUMINANCE8            = 11,
   SVGA3D_LUMINANCE4_ALPHA4     = 12,
   SVGA3D_LUMINANCE16           = 13,
   SVGA3D_LUMINANCE8_ALPHA8     = 14,

   SVGA3D_DXT1           = 15,
   SVGA3D_DXT2           = 16,
   SVGA3D_DXT3           = 17,
   SVGA3D_DXT4           = 18,
   SVGA3D_DXT5           = 19,

   SVGA3D_BUMPU8V8       = 20,
   SVGA3D_BUMPL6V5U5     = 21,
   SVGA3D_BUMPX8L8V8U8   = 22,
   SVGA3D_BUMPL8V8U8     = 23,

   SVGA3D_ARGB_S10E5     = 24,   /* 16-bit floating-point ARGB */
   SVGA3D_ARGB_S23E8     = 25,   /* 32-bit floating-point ARGB */

   SVGA3D_A2R10G10B10    = 26,

   /* signed formats */
   SVGA3D_V8U8           = 27,
   SVGA3D_Q8W8V8U8       = 28,
   SVGA3D_CxV8U8         = 29,

   /* mixed formats */
   SVGA3D_X8L8V8U8       = 30,
   SVGA3D_A2W10V10U10    = 31,

   SVGA3D_ALPHA8         = 32,

   /* Single- and dual-component floating point formats */
   SVGA3D_R_S10E5        = 33,
   SVGA3D_R_S23E8        = 34,
   SVGA3D_RG_S10E5       = 35,
   SVGA3D_RG_S23E8       = 36,

   /*
    * Any surface can be used as a buffer object, but SVGA3D_BUFFER is
    * the most efficient format to use when creating new surfaces
    * expressly for index or vertex data.
    */
   SVGA3D_BUFFER         = 37,

   SVGA3D_Z_D24X8        = 38,

   SVGA3D_V16U16         = 39,

   SVGA3D_G16R16         = 40,
   SVGA3D_A16B16G16R16   = 41,

   /* Packed Video formats */
   SVGA3D_UYVY           = 42,
   SVGA3D_YUY2           = 43,

   SVGA3D_FORMAT_MAX
} SVGA3dSurfaceFormat;

typedef uint32 SVGA3dColor; /* a, r, g, b */

/*
 * These match the D3DFORMAT_OP definitions used by Direct3D. We need
 * them so that we can query the host for what the supported surface
 * operations are (when we're using the D3D backend, in particular),
 * and so we can send those operations to the guest.
 */
typedef enum {
   SVGA3DFORMAT_OP_TEXTURE                               = 0x00000001,
   SVGA3DFORMAT_OP_VOLUMETEXTURE                         = 0x00000002,
   SVGA3DFORMAT_OP_CUBETEXTURE                           = 0x00000004,
   SVGA3DFORMAT_OP_OFFSCREEN_RENDERTARGET                = 0x00000008,
   SVGA3DFORMAT_OP_SAME_FORMAT_RENDERTARGET              = 0x00000010,
   SVGA3DFORMAT_OP_ZSTENCIL                              = 0x00000040,
   SVGA3DFORMAT_OP_ZSTENCIL_WITH_ARBITRARY_COLOR_DEPTH   = 0x00000080,

/*
 * This format can be used as a render target if the current display mode
 * is the same depth if the alpha channel is ignored. e.g. if the device
 * can render to A8R8G8B8 when the display mode is X8R8G8B8, then the
 * format op list entry for A8R8G8B8 should have this cap.
 */
   SVGA3DFORMAT_OP_SAME_FORMAT_UP_TO_ALPHA_RENDERTARGET  = 0x00000100,

/*
 * This format contains DirectDraw support (including Flip).  This flag
 * should not to be set on alpha formats.
 */
   SVGA3DFORMAT_OP_DISPLAYMODE                           = 0x00000400,

/*
 * The rasterizer can support some level of Direct3D support in this format
 * and implies that the driver can create a Context in this mode (for some
 * render target format).  When this flag is set, the SVGA3DFORMAT_OP_DISPLAYMODE
 * flag must also be set.
 */
   SVGA3DFORMAT_OP_3DACCELERATION                        = 0x00000800,

/*
 * This is set for a private format when the driver has put the bpp in
 * the structure.
 */
   SVGA3DFORMAT_OP_PIXELSIZE                             = 0x00001000,

/*
 * Indicates that this format can be converted to any RGB format for which
 * SVGA3DFORMAT_OP_MEMBEROFGROUP_ARGB is specified
 */
   SVGA3DFORMAT_OP_CONVERT_TO_ARGB                       = 0x00002000,

/*
 * Indicates that this format can be used to create offscreen plain surfaces.
 */
   SVGA3DFORMAT_OP_OFFSCREENPLAIN                        = 0x00004000,

/*
 * Indicated that this format can be read as an SRGB texture (meaning that the
 * sampler will linearize the looked up data)
 */
   SVGA3DFORMAT_OP_SRGBREAD                              = 0x00008000,

/*
 * Indicates that this format can be used in the bumpmap instructions
 */
   SVGA3DFORMAT_OP_BUMPMAP                               = 0x00010000,

/*
 * Indicates that this format can be sampled by the displacement map sampler
 */
   SVGA3DFORMAT_OP_DMAP                                  = 0x00020000,

/*
 * Indicates that this format cannot be used with texture filtering
 */
   SVGA3DFORMAT_OP_NOFILTER                              = 0x00040000,

/*
 * Indicates that format conversions are supported to this RGB format if
 * SVGA3DFORMAT_OP_CONVERT_TO_ARGB is specified in the source format.
 */
   SVGA3DFORMAT_OP_MEMBEROFGROUP_ARGB                    = 0x00080000,

/*
 * Indicated that this format can be written as an SRGB target (meaning that the
 * pixel pipe will DE-linearize data on output to format)
 */
   SVGA3DFORMAT_OP_SRGBWRITE                             = 0x00100000,

/*
 * Indicates that this format cannot be used with alpha blending
 */
   SVGA3DFORMAT_OP_NOALPHABLEND                          = 0x00200000,

/*
 * Indicates that the device can auto-generated sublevels for resources
 * of this format
 */
   SVGA3DFORMAT_OP_AUTOGENMIPMAP                         = 0x00400000,

/*
 * Indicates that this format can be used by vertex texture sampler
 */
   SVGA3DFORMAT_OP_VERTEXTEXTURE                         = 0x00800000,

/*
 * Indicates that this format supports neither texture coordinate wrap
 * modes, nor mipmapping
 */
   SVGA3DFORMAT_OP_NOTEXCOORDWRAPNORMIP                  = 0x01000000
} SVGA3dFormatOp;

/*
 * This structure is a conversion of SVGA3DFORMAT_OP_*.
 * Entries must be located at the same position.
 */
typedef union {
   uint32 value;
   struct {
      uint32 texture : 1;
      uint32 volumeTexture : 1;
      uint32 cubeTexture : 1;
      uint32 offscreenRenderTarget : 1;
      uint32 sameFormatRenderTarget : 1;
      uint32 unknown1 : 1;
      uint32 zStencil : 1;
      uint32 zStencilArbitraryDepth : 1;
      uint32 sameFormatUpToAlpha : 1;
      uint32 unknown2 : 1;
      uint32 displayMode : 1;
      uint32 acceleration3d : 1;
      uint32 pixelSize : 1;
      uint32 convertToARGB : 1;
      uint32 offscreenPlain : 1;
      uint32 sRGBRead : 1;
      uint32 bumpMap : 1;
      uint32 dmap : 1;
      uint32 noFilter : 1;
      uint32 memberOfGroupARGB : 1;
      uint32 sRGBWrite : 1;
      uint32 noAlphaBlend : 1;
      uint32 autoGenMipMap : 1;
      uint32 vertexTexture : 1;
      uint32 noTexCoordWrapNorMip : 1;
   };
} SVGA3dSurfaceFormatCaps;

/*
 * SVGA_3D_CMD_SETRENDERSTATE Types.  All value types
 * must fit in a uint32.
 */

typedef enum {
   SVGA3D_RS_INVALID                   = 0,
   SVGA3D_RS_ZENABLE                   = 1,     /* SVGA3dBool */
   SVGA3D_RS_ZWRITEENABLE              = 2,     /* SVGA3dBool */
   SVGA3D_RS_ALPHATESTENABLE           = 3,     /* SVGA3dBool */
   SVGA3D_RS_DITHERENABLE              = 4,     /* SVGA3dBool */
   SVGA3D_RS_BLENDENABLE               = 5,     /* SVGA3dBool */
   SVGA3D_RS_FOGENABLE                 = 6,     /* SVGA3dBool */
   SVGA3D_RS_SPECULARENABLE            = 7,     /* SVGA3dBool */
   SVGA3D_RS_STENCILENABLE             = 8,     /* SVGA3dBool */
   SVGA3D_RS_LIGHTINGENABLE            = 9,     /* SVGA3dBool */
   SVGA3D_RS_NORMALIZENORMALS          = 10,    /* SVGA3dBool */
   SVGA3D_RS_POINTSPRITEENABLE         = 11,    /* SVGA3dBool */
   SVGA3D_RS_POINTSCALEENABLE          = 12,    /* SVGA3dBool */
   SVGA3D_RS_STENCILREF                = 13,    /* uint32 */
   SVGA3D_RS_STENCILMASK               = 14,    /* uint32 */
   SVGA3D_RS_STENCILWRITEMASK          = 15,    /* uint32 */
   SVGA3D_RS_FOGSTART                  = 16,    /* float */
   SVGA3D_RS_FOGEND                    = 17,    /* float */
   SVGA3D_RS_FOGDENSITY                = 18,    /* float */
   SVGA3D_RS_POINTSIZE                 = 19,    /* float */
   SVGA3D_RS_POINTSIZEMIN              = 20,    /* float */
   SVGA3D_RS_POINTSIZEMAX              = 21,    /* float */
   SVGA3D_RS_POINTSCALE_A              = 22,    /* float */
   SVGA3D_RS_POINTSCALE_B              = 23,    /* float */
   SVGA3D_RS_POINTSCALE_C              = 24,    /* float */
   SVGA3D_RS_FOGCOLOR                  = 25,    /* SVGA3dColor */
   SVGA3D_RS_AMBIENT                   = 26,    /* SVGA3dColor */
   SVGA3D_RS_CLIPPLANEENABLE           = 27,    /* SVGA3dClipPlanes */
   SVGA3D_RS_FOGMODE                   = 28,    /* SVGA3dFogMode */
   SVGA3D_RS_FILLMODE                  = 29,    /* SVGA3dFillMode */
   SVGA3D_RS_SHADEMODE                 = 30,    /* SVGA3dShadeMode */
   SVGA3D_RS_LINEPATTERN               = 31,    /* SVGA3dLinePattern */
   SVGA3D_RS_SRCBLEND                  = 32,    /* SVGA3dBlendOp */
   SVGA3D_RS_DSTBLEND                  = 33,    /* SVGA3dBlendOp */
   SVGA3D_RS_BLENDEQUATION             = 34,    /* SVGA3dBlendEquation */
   SVGA3D_RS_CULLMODE                  = 35,    /* SVGA3dFace */
   SVGA3D_RS_ZFUNC                     = 36,    /* SVGA3dCmpFunc */
   SVGA3D_RS_ALPHAFUNC                 = 37,    /* SVGA3dCmpFunc */
   SVGA3D_RS_STENCILFUNC               = 38,    /* SVGA3dCmpFunc */
   SVGA3D_RS_STENCILFAIL               = 39,    /* SVGA3dStencilOp */
   SVGA3D_RS_STENCILZFAIL              = 40,    /* SVGA3dStencilOp */
   SVGA3D_RS_STENCILPASS               = 41,    /* SVGA3dStencilOp */
   SVGA3D_RS_ALPHAREF                  = 42,    /* float (0.0 .. 1.0) */
   SVGA3D_RS_FRONTWINDING              = 43,    /* SVGA3dFrontWinding */
   SVGA3D_RS_COORDINATETYPE            = 44,    /* SVGA3dCoordinateType */
   SVGA3D_RS_ZBIAS                     = 45,    /* float */
   SVGA3D_RS_RANGEFOGENABLE            = 46,    /* SVGA3dBool */
   SVGA3D_RS_COLORWRITEENABLE          = 47,    /* SVGA3dColorMask */
   SVGA3D_RS_VERTEXMATERIALENABLE      = 48,    /* SVGA3dBool */
   SVGA3D_RS_DIFFUSEMATERIALSOURCE     = 49,    /* SVGA3dVertexMaterial */
   SVGA3D_RS_SPECULARMATERIALSOURCE    = 50,    /* SVGA3dVertexMaterial */
   SVGA3D_RS_AMBIENTMATERIALSOURCE     = 51,    /* SVGA3dVertexMaterial */
   SVGA3D_RS_EMISSIVEMATERIALSOURCE    = 52,    /* SVGA3dVertexMaterial */
   SVGA3D_RS_TEXTUREFACTOR             = 53,    /* SVGA3dColor */
   SVGA3D_RS_LOCALVIEWER               = 54,    /* SVGA3dBool */
   SVGA3D_RS_SCISSORTESTENABLE         = 55,    /* SVGA3dBool */
   SVGA3D_RS_BLENDCOLOR                = 56,    /* SVGA3dColor */
   SVGA3D_RS_STENCILENABLE2SIDED       = 57,    /* SVGA3dBool */
   SVGA3D_RS_CCWSTENCILFUNC            = 58,    /* SVGA3dCmpFunc */
   SVGA3D_RS_CCWSTENCILFAIL            = 59,    /* SVGA3dStencilOp */
   SVGA3D_RS_CCWSTENCILZFAIL           = 60,    /* SVGA3dStencilOp */
   SVGA3D_RS_CCWSTENCILPASS            = 61,    /* SVGA3dStencilOp */
   SVGA3D_RS_VERTEXBLEND               = 62,    /* SVGA3dVertexBlendFlags */
   SVGA3D_RS_SLOPESCALEDEPTHBIAS       = 63,    /* float */
   SVGA3D_RS_DEPTHBIAS                 = 64,    /* float */


   /*
    * Output Gamma Level
    *
    * Output gamma effects the gamma curve of colors that are output from the
    * rendering pipeline.  A value of 1.0 specifies a linear color space. If the
    * value is <= 0.0, gamma correction is ignored and linear color space is
    * used.
    */

   SVGA3D_RS_OUTPUTGAMMA               = 65,    /* float */
   SVGA3D_RS_ZVISIBLE                  = 66,    /* SVGA3dBool */
   SVGA3D_RS_LASTPIXEL                 = 67,    /* SVGA3dBool */
   SVGA3D_RS_CLIPPING                  = 68,    /* SVGA3dBool */
   SVGA3D_RS_WRAP0                     = 69,    /* SVGA3dWrapFlags */
   SVGA3D_RS_WRAP1                     = 70,    /* SVGA3dWrapFlags */
   SVGA3D_RS_WRAP2                     = 71,    /* SVGA3dWrapFlags */
   SVGA3D_RS_WRAP3                     = 72,    /* SVGA3dWrapFlags */
   SVGA3D_RS_WRAP4                     = 73,    /* SVGA3dWrapFlags */
   SVGA3D_RS_WRAP5                     = 74,    /* SVGA3dWrapFlags */
   SVGA3D_RS_WRAP6                     = 75,    /* SVGA3dWrapFlags */
   SVGA3D_RS_WRAP7                     = 76,    /* SVGA3dWrapFlags */
   SVGA3D_RS_WRAP8                     = 77,    /* SVGA3dWrapFlags */
   SVGA3D_RS_WRAP9                     = 78,    /* SVGA3dWrapFlags */
   SVGA3D_RS_WRAP10                    = 79,    /* SVGA3dWrapFlags */
   SVGA3D_RS_WRAP11                    = 80,    /* SVGA3dWrapFlags */
   SVGA3D_RS_WRAP12                    = 81,    /* SVGA3dWrapFlags */
   SVGA3D_RS_WRAP13                    = 82,    /* SVGA3dWrapFlags */
   SVGA3D_RS_WRAP14                    = 83,    /* SVGA3dWrapFlags */
   SVGA3D_RS_WRAP15                    = 84,    /* SVGA3dWrapFlags */
   SVGA3D_RS_MULTISAMPLEANTIALIAS      = 85,    /* SVGA3dBool */
   SVGA3D_RS_MULTISAMPLEMASK           = 86,    /* uint32 */
   SVGA3D_RS_INDEXEDVERTEXBLENDENABLE  = 87,    /* SVGA3dBool */
   SVGA3D_RS_TWEENFACTOR               = 88,    /* float */
   SVGA3D_RS_ANTIALIASEDLINEENABLE     = 89,    /* SVGA3dBool */
   SVGA3D_RS_COLORWRITEENABLE1         = 90,    /* SVGA3dColorMask */
   SVGA3D_RS_COLORWRITEENABLE2         = 91,    /* SVGA3dColorMask */
   SVGA3D_RS_COLORWRITEENABLE3         = 92,    /* SVGA3dColorMask */
   SVGA3D_RS_SEPARATEALPHABLENDENABLE  = 93,    /* SVGA3dBool */
   SVGA3D_RS_SRCBLENDALPHA             = 94,    /* SVGA3dBlendOp */
   SVGA3D_RS_DSTBLENDALPHA             = 95,    /* SVGA3dBlendOp */
   SVGA3D_RS_BLENDEQUATIONALPHA        = 96,    /* SVGA3dBlendEquation */
   SVGA3D_RS_MAX
} SVGA3dRenderStateName;

typedef enum {
   SVGA3D_VERTEXMATERIAL_NONE     = 0,    /* Use the value in the current material */
   SVGA3D_VERTEXMATERIAL_DIFFUSE  = 1,    /* Use the value in the diffuse component */
   SVGA3D_VERTEXMATERIAL_SPECULAR = 2,    /* Use the value in the specular component */
} SVGA3dVertexMaterial;

typedef enum {
   SVGA3D_FILLMODE_INVALID = 0,
   SVGA3D_FILLMODE_POINT   = 1,
   SVGA3D_FILLMODE_LINE    = 2,
   SVGA3D_FILLMODE_FILL    = 3,
   SVGA3D_FILLMODE_MAX
} SVGA3dFillModeType;


typedef
union {
   struct {
      uint16   mode;       /* SVGA3dFillModeType */
      uint16   face;       /* SVGA3dFace */
   };
   uint32 uintValue;
} SVGA3dFillMode;

typedef enum {
   SVGA3D_SHADEMODE_INVALID = 0,
   SVGA3D_SHADEMODE_FLAT    = 1,
   SVGA3D_SHADEMODE_SMOOTH  = 2,
   SVGA3D_SHADEMODE_PHONG   = 3,     /* Not supported */
   SVGA3D_SHADEMODE_MAX
} SVGA3dShadeMode;

typedef
union {
   struct {
      uint16 repeat;
      uint16 pattern;
   };
   uint32 uintValue;
} SVGA3dLinePattern;

typedef enum {
   SVGA3D_BLENDOP_INVALID            = 0,
   SVGA3D_BLENDOP_ZERO               = 1,
   SVGA3D_BLENDOP_ONE                = 2,
   SVGA3D_BLENDOP_SRCCOLOR           = 3,
   SVGA3D_BLENDOP_INVSRCCOLOR        = 4,
   SVGA3D_BLENDOP_SRCALPHA           = 5,
   SVGA3D_BLENDOP_INVSRCALPHA        = 6,
   SVGA3D_BLENDOP_DESTALPHA          = 7,
   SVGA3D_BLENDOP_INVDESTALPHA       = 8,
   SVGA3D_BLENDOP_DESTCOLOR          = 9,
   SVGA3D_BLENDOP_INVDESTCOLOR       = 10,
   SVGA3D_BLENDOP_SRCALPHASAT        = 11,
   SVGA3D_BLENDOP_BLENDFACTOR        = 12,
   SVGA3D_BLENDOP_INVBLENDFACTOR     = 13,
   SVGA3D_BLENDOP_MAX
} SVGA3dBlendOp;

typedef enum {
   SVGA3D_BLENDEQ_INVALID            = 0,
   SVGA3D_BLENDEQ_ADD                = 1,
   SVGA3D_BLENDEQ_SUBTRACT           = 2,
   SVGA3D_BLENDEQ_REVSUBTRACT        = 3,
   SVGA3D_BLENDEQ_MINIMUM            = 4,
   SVGA3D_BLENDEQ_MAXIMUM            = 5,
   SVGA3D_BLENDEQ_MAX
} SVGA3dBlendEquation;

typedef enum {
   SVGA3D_FRONTWINDING_INVALID = 0,
   SVGA3D_FRONTWINDING_CW      = 1,
   SVGA3D_FRONTWINDING_CCW     = 2,
   SVGA3D_FRONTWINDING_MAX
} SVGA3dFrontWinding;

typedef enum {
   SVGA3D_FACE_INVALID  = 0,
   SVGA3D_FACE_NONE     = 1,
   SVGA3D_FACE_FRONT    = 2,
   SVGA3D_FACE_BACK     = 3,
   SVGA3D_FACE_FRONT_BACK = 4,
   SVGA3D_FACE_MAX
} SVGA3dFace;

/*
 * The order and the values should not be changed
 */

typedef enum {
   SVGA3D_CMP_INVALID              = 0,
   SVGA3D_CMP_NEVER                = 1,
   SVGA3D_CMP_LESS                 = 2,
   SVGA3D_CMP_EQUAL                = 3,
   SVGA3D_CMP_LESSEQUAL            = 4,
   SVGA3D_CMP_GREATER              = 5,
   SVGA3D_CMP_NOTEQUAL             = 6,
   SVGA3D_CMP_GREATEREQUAL         = 7,
   SVGA3D_CMP_ALWAYS               = 8,
   SVGA3D_CMP_MAX
} SVGA3dCmpFunc;

/*
 * SVGA3D_FOGFUNC_* specifies the fog equation, or PER_VERTEX which allows
 * the fog factor to be specified in the alpha component of the specular
 * (a.k.a. secondary) vertex color.
 */
typedef enum {
   SVGA3D_FOGFUNC_INVALID          = 0,
   SVGA3D_FOGFUNC_EXP              = 1,
   SVGA3D_FOGFUNC_EXP2             = 2,
   SVGA3D_FOGFUNC_LINEAR           = 3,
   SVGA3D_FOGFUNC_PER_VERTEX       = 4
} SVGA3dFogFunction;

/*
 * SVGA3D_FOGTYPE_* specifies if fog factors are computed on a per-vertex
 * or per-pixel basis.
 */
typedef enum {
   SVGA3D_FOGTYPE_INVALID          = 0,
   SVGA3D_FOGTYPE_VERTEX           = 1,
   SVGA3D_FOGTYPE_PIXEL            = 2,
   SVGA3D_FOGTYPE_MAX              = 3
} SVGA3dFogType;

/*
 * SVGA3D_FOGBASE_* selects depth or range-based fog. Depth-based fog is
 * computed using the eye Z value of each pixel (or vertex), whereas range-
 * based fog is computed using the actual distance (range) to the eye.
 */
typedef enum {
   SVGA3D_FOGBASE_INVALID          = 0,
   SVGA3D_FOGBASE_DEPTHBASED       = 1,
   SVGA3D_FOGBASE_RANGEBASED       = 2,
   SVGA3D_FOGBASE_MAX              = 3
} SVGA3dFogBase;

typedef enum {
   SVGA3D_STENCILOP_INVALID        = 0,
   SVGA3D_STENCILOP_KEEP           = 1,
   SVGA3D_STENCILOP_ZERO           = 2,
   SVGA3D_STENCILOP_REPLACE        = 3,
   SVGA3D_STENCILOP_INCRSAT        = 4,
   SVGA3D_STENCILOP_DECRSAT        = 5,
   SVGA3D_STENCILOP_INVERT         = 6,
   SVGA3D_STENCILOP_INCR           = 7,
   SVGA3D_STENCILOP_DECR           = 8,
   SVGA3D_STENCILOP_MAX
} SVGA3dStencilOp;

typedef enum {
   SVGA3D_CLIPPLANE_0              = (1 << 0),
   SVGA3D_CLIPPLANE_1              = (1 << 1),
   SVGA3D_CLIPPLANE_2              = (1 << 2),
   SVGA3D_CLIPPLANE_3              = (1 << 3),
   SVGA3D_CLIPPLANE_4              = (1 << 4),
   SVGA3D_CLIPPLANE_5              = (1 << 5),
} SVGA3dClipPlanes;

typedef enum {
   SVGA3D_CLEAR_COLOR              = 0x1,
   SVGA3D_CLEAR_DEPTH              = 0x2,
   SVGA3D_CLEAR_STENCIL            = 0x4
} SVGA3dClearFlag;

typedef enum {
   SVGA3D_RT_DEPTH                 = 0,
   SVGA3D_RT_STENCIL               = 1,
   SVGA3D_RT_COLOR0                = 2,
   SVGA3D_RT_COLOR1                = 3,
   SVGA3D_RT_COLOR2                = 4,
   SVGA3D_RT_COLOR3                = 5,
   SVGA3D_RT_COLOR4                = 6,
   SVGA3D_RT_COLOR5                = 7,
   SVGA3D_RT_COLOR6                = 8,
   SVGA3D_RT_COLOR7                = 9,
   SVGA3D_RT_MAX,
   SVGA3D_RT_INVALID               = ((uint32)-1),
} SVGA3dRenderTargetType;

#define SVGA3D_MAX_RT_COLOR (SVGA3D_RT_COLOR7 - SVGA3D_RT_COLOR0 + 1)

typedef
union {
   struct {
      uint32  red   : 1;
      uint32  green : 1;
      uint32  blue  : 1;
      uint32  alpha : 1;
   };
   uint32 uintValue;
} SVGA3dColorMask;

typedef enum {
   SVGA3D_VBLEND_DISABLE            = 0,
   SVGA3D_VBLEND_1WEIGHT            = 1,
   SVGA3D_VBLEND_2WEIGHT            = 2,
   SVGA3D_VBLEND_3WEIGHT            = 3,
} SVGA3dVertexBlendFlags;

typedef enum {
   SVGA3D_WRAPCOORD_0   = 1 << 0,
   SVGA3D_WRAPCOORD_1   = 1 << 1,
   SVGA3D_WRAPCOORD_2   = 1 << 2,
   SVGA3D_WRAPCOORD_3   = 1 << 3,
   SVGA3D_WRAPCOORD_ALL = 0xF,
} SVGA3dWrapFlags;

/*
 * SVGA_3D_CMD_TEXTURESTATE Types.  All value types
 * must fit in a uint32.
 */

typedef enum {
   SVGA3D_TS_INVALID                    = 0,
   SVGA3D_TS_BIND_TEXTURE               = 1,    /* SVGA3dSurfaceId */
   SVGA3D_TS_COLOROP                    = 2,    /* SVGA3dTextureCombiner */
   SVGA3D_TS_COLORARG1                  = 3,    /* SVGA3dTextureArgData */
   SVGA3D_TS_COLORARG2                  = 4,    /* SVGA3dTextureArgData */
   SVGA3D_TS_ALPHAOP                    = 5,    /* SVGA3dTextureCombiner */
   SVGA3D_TS_ALPHAARG1                  = 6,    /* SVGA3dTextureArgData */
   SVGA3D_TS_ALPHAARG2                  = 7,    /* SVGA3dTextureArgData */
   SVGA3D_TS_ADDRESSU                   = 8,    /* SVGA3dTextureAddress */
   SVGA3D_TS_ADDRESSV                   = 9,    /* SVGA3dTextureAddress */
   SVGA3D_TS_MIPFILTER                  = 10,   /* SVGA3dTextureFilter */
   SVGA3D_TS_MAGFILTER                  = 11,   /* SVGA3dTextureFilter */
   SVGA3D_TS_MINFILTER                  = 12,   /* SVGA3dTextureFilter */
   SVGA3D_TS_BORDERCOLOR                = 13,   /* SVGA3dColor */
   SVGA3D_TS_TEXCOORDINDEX              = 14,   /* uint32 */
   SVGA3D_TS_TEXTURETRANSFORMFLAGS      = 15,   /* SVGA3dTexTransformFlags */
   SVGA3D_TS_TEXCOORDGEN                = 16,   /* SVGA3dTextureCoordGen */
   SVGA3D_TS_BUMPENVMAT00               = 17,   /* float */
   SVGA3D_TS_BUMPENVMAT01               = 18,   /* float */
   SVGA3D_TS_BUMPENVMAT10               = 19,   /* float */
   SVGA3D_TS_BUMPENVMAT11               = 20,   /* float */
   SVGA3D_TS_TEXTURE_MIPMAP_LEVEL       = 21,   /* uint32 */
   SVGA3D_TS_TEXTURE_LOD_BIAS           = 22,   /* float */
   SVGA3D_TS_TEXTURE_ANISOTROPIC_LEVEL  = 23,   /* uint32 */
   SVGA3D_TS_ADDRESSW                   = 24,   /* SVGA3dTextureAddress */


   /*
    * Sampler Gamma Level
    *
    * Sampler gamma effects the color of samples taken from the sampler.  A
    * value of 1.0 will produce linear samples.  If the value is <= 0.0 the
    * gamma value is ignored and a linear space is used.
    */

   SVGA3D_TS_GAMMA                      = 25,   /* float */
   SVGA3D_TS_BUMPENVLSCALE              = 26,   /* float */
   SVGA3D_TS_BUMPENVLOFFSET             = 27,   /* float */
   SVGA3D_TS_COLORARG0                  = 28,   /* SVGA3dTextureArgData */
   SVGA3D_TS_ALPHAARG0                  = 29,   /* SVGA3dTextureArgData */
   SVGA3D_TS_MAX
} SVGA3dTextureStateName;

typedef enum {
   SVGA3D_TC_INVALID                   = 0,
   SVGA3D_TC_DISABLE                   = 1,
   SVGA3D_TC_SELECTARG1                = 2,
   SVGA3D_TC_SELECTARG2                = 3,
   SVGA3D_TC_MODULATE                  = 4,
   SVGA3D_TC_ADD                       = 5,
   SVGA3D_TC_ADDSIGNED                 = 6,
   SVGA3D_TC_SUBTRACT                  = 7,
   SVGA3D_TC_BLENDTEXTUREALPHA         = 8,
   SVGA3D_TC_BLENDDIFFUSEALPHA         = 9,
   SVGA3D_TC_BLENDCURRENTALPHA         = 10,
   SVGA3D_TC_BLENDFACTORALPHA          = 11,
   SVGA3D_TC_MODULATE2X                = 12,
   SVGA3D_TC_MODULATE4X                = 13,
   SVGA3D_TC_DSDT                      = 14,
   SVGA3D_TC_DOTPRODUCT3               = 15,
   SVGA3D_TC_BLENDTEXTUREALPHAPM       = 16,
   SVGA3D_TC_ADDSIGNED2X               = 17,
   SVGA3D_TC_ADDSMOOTH                 = 18,
   SVGA3D_TC_PREMODULATE               = 19,
   SVGA3D_TC_MODULATEALPHA_ADDCOLOR    = 20,
   SVGA3D_TC_MODULATECOLOR_ADDALPHA    = 21,
   SVGA3D_TC_MODULATEINVALPHA_ADDCOLOR = 22,
   SVGA3D_TC_MODULATEINVCOLOR_ADDALPHA = 23,
   SVGA3D_TC_BUMPENVMAPLUMINANCE       = 24,
   SVGA3D_TC_MULTIPLYADD               = 25,
   SVGA3D_TC_LERP                      = 26,
   SVGA3D_TC_MAX
} SVGA3dTextureCombiner;

#define SVGA3D_TC_CAP_BIT(svga3d_tc_op) (svga3d_tc_op ? (1 << (svga3d_tc_op - 1)) : 0)

typedef enum {
   SVGA3D_TEX_ADDRESS_INVALID    = 0,
   SVGA3D_TEX_ADDRESS_WRAP       = 1,
   SVGA3D_TEX_ADDRESS_MIRROR     = 2,
   SVGA3D_TEX_ADDRESS_CLAMP      = 3,
   SVGA3D_TEX_ADDRESS_BORDER     = 4,
   SVGA3D_TEX_ADDRESS_MIRRORONCE = 5,
   SVGA3D_TEX_ADDRESS_EDGE       = 6,
   SVGA3D_TEX_ADDRESS_MAX
} SVGA3dTextureAddress;

/*
 * SVGA3D_TEX_FILTER_NONE as the minification filter means mipmapping is
 * disabled, and the rasterizer should use the magnification filter instead.
 */
typedef enum {
   SVGA3D_TEX_FILTER_NONE           = 0,
   SVGA3D_TEX_FILTER_NEAREST        = 1,
   SVGA3D_TEX_FILTER_LINEAR         = 2,
   SVGA3D_TEX_FILTER_ANISOTROPIC    = 3,
   SVGA3D_TEX_FILTER_FLATCUBIC      = 4, // Deprecated, not implemented
   SVGA3D_TEX_FILTER_GAUSSIANCUBIC  = 5, // Deprecated, not implemented
   SVGA3D_TEX_FILTER_PYRAMIDALQUAD  = 6, // Not currently implemented
   SVGA3D_TEX_FILTER_GAUSSIANQUAD   = 7, // Not currently implemented
   SVGA3D_TEX_FILTER_MAX
} SVGA3dTextureFilter;

typedef enum {
   SVGA3D_TEX_TRANSFORM_OFF    = 0,
   SVGA3D_TEX_TRANSFORM_S      = (1 << 0),
   SVGA3D_TEX_TRANSFORM_T      = (1 << 1),
   SVGA3D_TEX_TRANSFORM_R      = (1 << 2),
   SVGA3D_TEX_TRANSFORM_Q      = (1 << 3),
   SVGA3D_TEX_PROJECTED        = (1 << 15),
} SVGA3dTexTransformFlags;

typedef enum {
   SVGA3D_TEXCOORD_GEN_OFF              = 0,
   SVGA3D_TEXCOORD_GEN_EYE_POSITION     = 1,
   SVGA3D_TEXCOORD_GEN_EYE_NORMAL       = 2,
   SVGA3D_TEXCOORD_GEN_REFLECTIONVECTOR = 3,
   SVGA3D_TEXCOORD_GEN_SPHERE           = 4,
   SVGA3D_TEXCOORD_GEN_MAX
} SVGA3dTextureCoordGen;

/*
 * Texture argument constants for texture combiner
 */
typedef enum {
   SVGA3D_TA_INVALID    = 0,
   SVGA3D_TA_CONSTANT   = 1,
   SVGA3D_TA_PREVIOUS   = 2,
   SVGA3D_TA_DIFFUSE    = 3,
   SVGA3D_TA_TEXTURE    = 4,
   SVGA3D_TA_SPECULAR   = 5,
   SVGA3D_TA_MAX
} SVGA3dTextureArgData;

#define SVGA3D_TM_MASK_LEN 4

/* Modifiers for texture argument constants defined above. */
typedef enum {
   SVGA3D_TM_NONE       = 0,
   SVGA3D_TM_ALPHA      = (1 << SVGA3D_TM_MASK_LEN),
   SVGA3D_TM_ONE_MINUS  = (2 << SVGA3D_TM_MASK_LEN),
} SVGA3dTextureArgModifier;

#define SVGA3D_INVALID_ID         ((uint32)-1)
#define SVGA3D_MAX_CLIP_PLANES    6

/*
 * This is the limit to the number of fixed-function texture
 * transforms and texture coordinates we can support. It does *not*
 * correspond to the number of texture image units (samplers) we
 * support!
 */
#define SVGA3D_MAX_TEXTURE_COORDS 8

/*
 * Vertex declarations
 *
 * Notes:
 *
 * SVGA3D_DECLUSAGE_POSITIONT is for pre-transformed vertices. If you
 * draw with any POSITIONT vertex arrays, the programmable vertex
 * pipeline will be implicitly disabled. Drawing will take place as if
 * no vertex shader was bound.
 */

typedef enum {
   SVGA3D_DECLUSAGE_POSITION     = 0,
   SVGA3D_DECLUSAGE_BLENDWEIGHT,       //  1
   SVGA3D_DECLUSAGE_BLENDINDICES,      //  2
   SVGA3D_DECLUSAGE_NORMAL,            //  3
   SVGA3D_DECLUSAGE_PSIZE,             //  4
   SVGA3D_DECLUSAGE_TEXCOORD,          //  5
   SVGA3D_DECLUSAGE_TANGENT,           //  6
   SVGA3D_DECLUSAGE_BINORMAL,          //  7
   SVGA3D_DECLUSAGE_TESSFACTOR,        //  8
   SVGA3D_DECLUSAGE_POSITIONT,         //  9
   SVGA3D_DECLUSAGE_COLOR,             // 10
   SVGA3D_DECLUSAGE_FOG,               // 11
   SVGA3D_DECLUSAGE_DEPTH,             // 12
   SVGA3D_DECLUSAGE_SAMPLE,            // 13
   SVGA3D_DECLUSAGE_MAX
} SVGA3dDeclUsage;

typedef enum {
   SVGA3D_DECLMETHOD_DEFAULT     = 0,
   SVGA3D_DECLMETHOD_PARTIALU,
   SVGA3D_DECLMETHOD_PARTIALV,
   SVGA3D_DECLMETHOD_CROSSUV,          // Normal
   SVGA3D_DECLMETHOD_UV,
   SVGA3D_DECLMETHOD_LOOKUP,           // Lookup a displacement map
   SVGA3D_DECLMETHOD_LOOKUPPRESAMPLED, // Lookup a pre-sampled displacement map
} SVGA3dDeclMethod;

typedef enum {
   SVGA3D_DECLTYPE_FLOAT1        =  0,
   SVGA3D_DECLTYPE_FLOAT2        =  1,
   SVGA3D_DECLTYPE_FLOAT3        =  2,
   SVGA3D_DECLTYPE_FLOAT4        =  3,
   SVGA3D_DECLTYPE_D3DCOLOR      =  4,
   SVGA3D_DECLTYPE_UBYTE4        =  5,
   SVGA3D_DECLTYPE_SHORT2        =  6,
   SVGA3D_DECLTYPE_SHORT4        =  7,
   SVGA3D_DECLTYPE_UBYTE4N       =  8,
   SVGA3D_DECLTYPE_SHORT2N       =  9,
   SVGA3D_DECLTYPE_SHORT4N       = 10,
   SVGA3D_DECLTYPE_USHORT2N      = 11,
   SVGA3D_DECLTYPE_USHORT4N      = 12,
   SVGA3D_DECLTYPE_UDEC3         = 13,
   SVGA3D_DECLTYPE_DEC3N         = 14,
   SVGA3D_DECLTYPE_FLOAT16_2     = 15,
   SVGA3D_DECLTYPE_FLOAT16_4     = 16,
   SVGA3D_DECLTYPE_MAX,
} SVGA3dDeclType;

/*
 * This structure is used for the divisor for geometry instancing;
 * it's a direct translation of the Direct3D equivalent.
 */
typedef union {
   struct {
      /*
       * For index data, this number represents the number of instances to draw.
       * For instance data, this number represents the number of
       * instances/vertex in this stream
       */
      uint32 count : 30;

      /*
       * This is 1 if this is supposed to be the data that is repeated for
       * every instance.
       */
      uint32 indexedData : 1;

      /*
       * This is 1 if this is supposed to be the per-instance data.
       */
      uint32 instanceData : 1;
   };

   uint32 value;
} SVGA3dVertexDivisor;

typedef enum {
   SVGA3D_PRIMITIVE_INVALID                     = 0,
   SVGA3D_PRIMITIVE_TRIANGLELIST                = 1,
   SVGA3D_PRIMITIVE_POINTLIST                   = 2,
   SVGA3D_PRIMITIVE_LINELIST                    = 3,
   SVGA3D_PRIMITIVE_LINESTRIP                   = 4,
   SVGA3D_PRIMITIVE_TRIANGLESTRIP               = 5,
   SVGA3D_PRIMITIVE_TRIANGLEFAN                 = 6,
   SVGA3D_PRIMITIVE_MAX
} SVGA3dPrimitiveType;

typedef enum {
   SVGA3D_COORDINATE_INVALID                   = 0,
   SVGA3D_COORDINATE_LEFTHANDED                = 1,
   SVGA3D_COORDINATE_RIGHTHANDED               = 2,
   SVGA3D_COORDINATE_MAX
} SVGA3dCoordinateType;

typedef enum {
   SVGA3D_TRANSFORM_INVALID                     = 0,
   SVGA3D_TRANSFORM_WORLD                       = 1,
   SVGA3D_TRANSFORM_VIEW                        = 2,
   SVGA3D_TRANSFORM_PROJECTION                  = 3,
   SVGA3D_TRANSFORM_TEXTURE0                    = 4,
   SVGA3D_TRANSFORM_TEXTURE1                    = 5,
   SVGA3D_TRANSFORM_TEXTURE2                    = 6,
   SVGA3D_TRANSFORM_TEXTURE3                    = 7,
   SVGA3D_TRANSFORM_TEXTURE4                    = 8,
   SVGA3D_TRANSFORM_TEXTURE5                    = 9,
   SVGA3D_TRANSFORM_TEXTURE6                    = 10,
   SVGA3D_TRANSFORM_TEXTURE7                    = 11,
   SVGA3D_TRANSFORM_WORLD1                      = 12,
   SVGA3D_TRANSFORM_WORLD2                      = 13,
   SVGA3D_TRANSFORM_WORLD3                      = 14,
   SVGA3D_TRANSFORM_MAX
} SVGA3dTransformType;

typedef enum {
   SVGA3D_LIGHTTYPE_INVALID                     = 0,
   SVGA3D_LIGHTTYPE_POINT                       = 1,
   SVGA3D_LIGHTTYPE_SPOT1                       = 2, /* 1-cone, in degrees */
   SVGA3D_LIGHTTYPE_SPOT2                       = 3, /* 2-cone, in radians */
   SVGA3D_LIGHTTYPE_DIRECTIONAL                 = 4,
   SVGA3D_LIGHTTYPE_MAX
} SVGA3dLightType;

typedef enum {
   SVGA3D_CUBEFACE_POSX                         = 0,
   SVGA3D_CUBEFACE_NEGX                         = 1,
   SVGA3D_CUBEFACE_POSY                         = 2,
   SVGA3D_CUBEFACE_NEGY                         = 3,
   SVGA3D_CUBEFACE_POSZ                         = 4,
   SVGA3D_CUBEFACE_NEGZ                         = 5,
} SVGA3dCubeFace;

typedef enum {
   SVGA3D_SHADERTYPE_COMPILED_DX8               = 0,
   SVGA3D_SHADERTYPE_VS                         = 1,
   SVGA3D_SHADERTYPE_PS                         = 2,
   SVGA3D_SHADERTYPE_MAX
} SVGA3dShaderType;

typedef enum {
   SVGA3D_CONST_TYPE_FLOAT                      = 0,
   SVGA3D_CONST_TYPE_INT                        = 1,
   SVGA3D_CONST_TYPE_BOOL                       = 2,
} SVGA3dShaderConstType;

#define SVGA3D_MAX_SURFACE_FACES                6

typedef enum {
   SVGA3D_STRETCH_BLT_POINT                     = 0,
   SVGA3D_STRETCH_BLT_LINEAR                    = 1,
   SVGA3D_STRETCH_BLT_MAX
} SVGA3dStretchBltMode;

typedef enum {
   SVGA3D_QUERYTYPE_OCCLUSION                   = 0,
   SVGA3D_QUERYTYPE_MAX
} SVGA3dQueryType;

typedef enum {
   SVGA3D_QUERYSTATE_PENDING     = 0,      /* Waiting on the host (set by guest) */
   SVGA3D_QUERYSTATE_SUCCEEDED   = 1,      /* Completed successfully (set by host) */
   SVGA3D_QUERYSTATE_FAILED      = 2,      /* Completed unsuccessfully (set by host) */
   SVGA3D_QUERYSTATE_NEW         = 3,      /* Never submitted (For guest use only) */
} SVGA3dQueryState;

typedef enum {
   SVGA3D_WRITE_HOST_VRAM        = 1,
   SVGA3D_READ_HOST_VRAM         = 2,
} SVGA3dTransferType;

/*
 * The maximum number of vertex arrays we're guaranteed to support in
 * SVGA_3D_CMD_DRAWPRIMITIVES.
 */
#define SVGA3D_MAX_VERTEX_ARRAYS   32

/*
 * The maximum number of primitive ranges we're guaranteed to support
 * in SVGA_3D_CMD_DRAWPRIMITIVES.
 */
#define SVGA3D_MAX_DRAW_PRIMITIVE_RANGES 32

/*
 * Identifiers for commands in the command FIFO.
 *
 * IDs between 1000 and 1039 (inclusive) were used by obsolete versions of
 * the SVGA3D protocol and remain reserved; they should not be used in the
 * future.
 *
 * IDs between 1040 and 1999 (inclusive) are available for use by the
 * current SVGA3D protocol.
 *
 * FIFO clients other than SVGA3D should stay below 1000, or at 2000
 * and up.
 */

#define SVGA_3D_CMD_LEGACY_BASE            1000
#define SVGA_3D_CMD_BASE                   1040

#define SVGA_3D_CMD_SURFACE_DEFINE         SVGA_3D_CMD_BASE + 0
#define SVGA_3D_CMD_SURFACE_DESTROY        SVGA_3D_CMD_BASE + 1
#define SVGA_3D_CMD_SURFACE_COPY           SVGA_3D_CMD_BASE + 2
#define SVGA_3D_CMD_SURFACE_STRETCHBLT     SVGA_3D_CMD_BASE + 3
#define SVGA_3D_CMD_SURFACE_DMA            SVGA_3D_CMD_BASE + 4
#define SVGA_3D_CMD_CONTEXT_DEFINE         SVGA_3D_CMD_BASE + 5
#define SVGA_3D_CMD_CONTEXT_DESTROY        SVGA_3D_CMD_BASE + 6
#define SVGA_3D_CMD_SETTRANSFORM           SVGA_3D_CMD_BASE + 7
#define SVGA_3D_CMD_SETZRANGE              SVGA_3D_CMD_BASE + 8
#define SVGA_3D_CMD_SETRENDERSTATE         SVGA_3D_CMD_BASE + 9
#define SVGA_3D_CMD_SETRENDERTARGET        SVGA_3D_CMD_BASE + 10
#define SVGA_3D_CMD_SETTEXTURESTATE        SVGA_3D_CMD_BASE + 11
#define SVGA_3D_CMD_SETMATERIAL            SVGA_3D_CMD_BASE + 12
#define SVGA_3D_CMD_SETLIGHTDATA           SVGA_3D_CMD_BASE + 13
#define SVGA_3D_CMD_SETLIGHTENABLED        SVGA_3D_CMD_BASE + 14
#define SVGA_3D_CMD_SETVIEWPORT            SVGA_3D_CMD_BASE + 15
#define SVGA_3D_CMD_SETCLIPPLANE           SVGA_3D_CMD_BASE + 16
#define SVGA_3D_CMD_CLEAR                  SVGA_3D_CMD_BASE + 17
#define SVGA_3D_CMD_PRESENT                SVGA_3D_CMD_BASE + 18    // Deprecated
#define SVGA_3D_CMD_SHADER_DEFINE          SVGA_3D_CMD_BASE + 19
#define SVGA_3D_CMD_SHADER_DESTROY         SVGA_3D_CMD_BASE + 20
#define SVGA_3D_CMD_SET_SHADER             SVGA_3D_CMD_BASE + 21
#define SVGA_3D_CMD_SET_SHADER_CONST       SVGA_3D_CMD_BASE + 22
#define SVGA_3D_CMD_DRAW_PRIMITIVES        SVGA_3D_CMD_BASE + 23
#define SVGA_3D_CMD_SETSCISSORRECT         SVGA_3D_CMD_BASE + 24
#define SVGA_3D_CMD_BEGIN_QUERY            SVGA_3D_CMD_BASE + 25
#define SVGA_3D_CMD_END_QUERY              SVGA_3D_CMD_BASE + 26
#define SVGA_3D_CMD_WAIT_FOR_QUERY         SVGA_3D_CMD_BASE + 27
#define SVGA_3D_CMD_PRESENT_READBACK       SVGA_3D_CMD_BASE + 28    // Deprecated
#define SVGA_3D_CMD_BLIT_SURFACE_TO_SCREEN SVGA_3D_CMD_BASE + 29
#define SVGA_3D_CMD_MAX                    SVGA_3D_CMD_BASE + 30

#define SVGA_3D_CMD_FUTURE_MAX             2000

/*
 * Common substructures used in multiple FIFO commands:
 */

typedef struct {
   union {
      struct {
         uint16  function;       // SVGA3dFogFunction
         uint8   type;           // SVGA3dFogType
         uint8   base;           // SVGA3dFogBase
      };
      uint32     uintValue;
   };
} SVGA3dFogMode;

/*
 * Uniquely identify one image (a 1D/2D/3D array) from a surface. This
 * is a surface ID as well as face/mipmap indices.
 */

typedef
struct SVGA3dSurfaceImageId {
   uint32               sid;
   uint32               face;
   uint32               mipmap;
} SVGA3dSurfaceImageId;

typedef
struct SVGA3dGuestImage {
   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;
} SVGA3dGuestImage;


/*
 * FIFO command format definitions:
 */

/*
 * The data size header following cmdNum for every 3d command
 */
typedef
struct {
   uint32               id;
   uint32               size;
} SVGA3dCmdHeader;

/*
 * A surface is a hierarchy of host VRAM surfaces: 1D, 2D, or 3D, with
 * optional mipmaps and cube faces.
 */

typedef
struct {
   uint32               width;
   uint32               height;
   uint32               depth;
} SVGA3dSize;

typedef enum {
   SVGA3D_SURFACE_CUBEMAP              = (1 << 0),
   SVGA3D_SURFACE_HINT_STATIC          = (1 << 1),
   SVGA3D_SURFACE_HINT_DYNAMIC         = (1 << 2),
   SVGA3D_SURFACE_HINT_INDEXBUFFER     = (1 << 3),
   SVGA3D_SURFACE_HINT_VERTEXBUFFER    = (1 << 4),
   SVGA3D_SURFACE_HINT_TEXTURE         = (1 << 5),
   SVGA3D_SURFACE_HINT_RENDERTARGET    = (1 << 6),
   SVGA3D_SURFACE_HINT_DEPTHSTENCIL    = (1 << 7),
   SVGA3D_SURFACE_HINT_WRITEONLY       = (1 << 8),
} SVGA3dSurfaceFlags;

typedef
struct {
   uint32               numMipLevels;
} SVGA3dSurfaceFace;

typedef
struct {
   uint32                      sid;
   SVGA3dSurfaceFlags          surfaceFlags;
   SVGA3dSurfaceFormat         format;
   SVGA3dSurfaceFace           face[SVGA3D_MAX_SURFACE_FACES];
   /*
    * Followed by an SVGA3dSize structure for each mip level in each face.
    *
    * A note on surface sizes: Sizes are always specified in pixels,
    * even if the true surface size is not a multiple of the minimum
    * block size of the surface's format. For example, a 3x3x1 DXT1
    * compressed texture would actually be stored as a 4x4x1 image in
    * memory.
    */
} SVGA3dCmdDefineSurface;       /* SVGA_3D_CMD_SURFACE_DEFINE */

typedef
struct {
   uint32               sid;
} SVGA3dCmdDestroySurface;      /* SVGA_3D_CMD_SURFACE_DESTROY */

typedef
struct {
   uint32               cid;
} SVGA3dCmdDefineContext;       /* SVGA_3D_CMD_CONTEXT_DEFINE */

typedef
struct {
   uint32               cid;
} SVGA3dCmdDestroyContext;      /* SVGA_3D_CMD_CONTEXT_DESTROY */

typedef
struct {
   uint32               cid;
   SVGA3dClearFlag      clearFlag;
   uint32               color;
   float                depth;
   uint32               stencil;
   /* Followed by variable number of SVGA3dRect structures */
} SVGA3dCmdClear;               /* SVGA_3D_CMD_CLEAR */

typedef
struct SVGA3dCopyRect {
   uint32               x;
   uint32               y;
   uint32               w;
   uint32               h;
   uint32               srcx;
   uint32               srcy;
} SVGA3dCopyRect;

typedef
struct SVGA3dCopyBox {
   uint32               x;
   uint32               y;
   uint32               z;
   uint32               w;
   uint32               h;
   uint32               d;
   uint32               srcx;
   uint32               srcy;
   uint32               srcz;
} SVGA3dCopyBox;

typedef
struct {
   uint32               x;
   uint32               y;
   uint32               w;
   uint32               h;
} SVGA3dRect;

typedef
struct {
   uint32               x;
   uint32               y;
   uint32               z;
   uint32               w;
   uint32               h;
   uint32               d;
} SVGA3dBox;

typedef
struct {
   uint32               x;
   uint32               y;
   uint32               z;
} SVGA3dPoint;

typedef
struct {
   SVGA3dLightType      type;
   SVGA3dBool           inWorldSpace;
   float                diffuse[4];
   float                specular[4];
   float                ambient[4];
   float                position[4];
   float                direction[4];
   float                range;
   float                falloff;
   float                attenuation0;
   float                attenuation1;
   float                attenuation2;
   float                theta;
   float                phi;
} SVGA3dLightData;

typedef
struct {
   uint32               sid;
   /* Followed by variable number of SVGA3dCopyRect structures */
} SVGA3dCmdPresent;             /* SVGA_3D_CMD_PRESENT */

typedef
struct {
   SVGA3dRenderStateName   state;
   union {
      uint32               uintValue;
      float                floatValue;
   };
} SVGA3dRenderState;

typedef
struct {
   uint32               cid;
   /* Followed by variable number of SVGA3dRenderState structures */
} SVGA3dCmdSetRenderState;      /* SVGA_3D_CMD_SETRENDERSTATE */

typedef
struct {
   uint32                 cid;
   SVGA3dRenderTargetType type;
   SVGA3dSurfaceImageId   target;
} SVGA3dCmdSetRenderTarget;     /* SVGA_3D_CMD_SETRENDERTARGET */

typedef
struct {
   SVGA3dSurfaceImageId  src;
   SVGA3dSurfaceImageId  dest;
   /* Followed by variable number of SVGA3dCopyBox structures */
} SVGA3dCmdSurfaceCopy;               /* SVGA_3D_CMD_SURFACE_COPY */

typedef
struct {
   SVGA3dSurfaceImageId  src;
   SVGA3dSurfaceImageId  dest;
   SVGA3dBox             boxSrc;
   SVGA3dBox             boxDest;
   SVGA3dStretchBltMode  mode;
} SVGA3dCmdSurfaceStretchBlt;         /* SVGA_3D_CMD_SURFACE_STRETCHBLT */

typedef
struct {
   /*
    * If the discard flag is present in a surface DMA operation, the host may
    * discard the contents of the current mipmap level and face of the target
    * surface before applying the surface DMA contents.
    */
   uint32 discard : 1;

   /*
    * If the unsynchronized flag is present, the host may perform this upload
    * without syncing to pending reads on this surface.
    */
   uint32 unsynchronized : 1;

   /*
    * Guests *MUST* set the reserved bits to 0 before submitting the command
    * suffix as future flags may occupy these bits.
    */
   uint32 reserved : 30;
} SVGA3dSurfaceDMAFlags;

typedef
struct {
   SVGA3dGuestImage      guest;
   SVGA3dSurfaceImageId  host;
   SVGA3dTransferType    transfer;
   /*
    * Followed by variable number of SVGA3dCopyBox structures. For consistency
    * in all clipping logic and coordinate translation, we define the
    * "source" in each copyBox as the guest image and the
    * "destination" as the host image, regardless of transfer
    * direction.
    *
    * For efficiency, the SVGA3D device is free to copy more data than
    * specified. For example, it may round copy boxes outwards such
    * that they lie on particular alignment boundaries.
    */
} SVGA3dCmdSurfaceDMA;                /* SVGA_3D_CMD_SURFACE_DMA */

/*
 * SVGA3dCmdSurfaceDMASuffix --
 *
 *    This is a command suffix that will appear after a SurfaceDMA command in
 *    the FIFO.  It contains some extra information that hosts may use to
 *    optimize performance or protect the guest.  This suffix exists to preserve
 *    backwards compatibility while also allowing for new functionality to be
 *    implemented.
 */

typedef
struct {
   uint32 suffixSize;

   /*
    * The maximum offset is used to determine the maximum offset from the
    * guestPtr base address that will be accessed or written to during this
    * surfaceDMA.  If the suffix is supported, the host will respect this
    * boundary while performing surface DMAs.
    *
    * Defaults to MAX_UINT32
    */
   uint32 maximumOffset;

   /*
    * A set of flags that describes optimizations that the host may perform
    * while performing this surface DMA operation.  The guest should never rely
    * on behaviour that is different when these flags are set for correctness.
    *
    * Defaults to 0
    */
   SVGA3dSurfaceDMAFlags flags;
} SVGA3dCmdSurfaceDMASuffix;

/*
 * SVGA_3D_CMD_DRAW_PRIMITIVES --
 *
 *   This command is the SVGA3D device's generic drawing entry point.
 *   It can draw multiple ranges of primitives, optionally using an
 *   index buffer, using an arbitrary collection of vertex buffers.
 *
 *   Each SVGA3dVertexDecl defines a distinct vertex array to bind
 *   during this draw call. The declarations specify which surface
 *   the vertex data lives in, what that vertex data is used for,
 *   and how to interpret it.
 *
 *   Each SVGA3dPrimitiveRange defines a collection of primitives
 *   to render using the same vertex arrays. An index buffer is
 *   optional.
 */

typedef
struct {
   /*
    * A range hint is an optional specification for the range of indices
    * in an SVGA3dArray that will be used. If 'last' is zero, it is assumed
    * that the entire array will be used.
    *
    * These are only hints. The SVGA3D device may use them for
    * performance optimization if possible, but it's also allowed to
    * ignore these values.
    */
   uint32               first;
   uint32               last;
} SVGA3dArrayRangeHint;

typedef
struct {
   /*
    * Define the origin and shape of a vertex or index array. Both
    * 'offset' and 'stride' are in bytes. The provided surface will be
    * reinterpreted as a flat array of bytes in the same format used
    * by surface DMA operations. To avoid unnecessary conversions, the
    * surface should be created with the SVGA3D_BUFFER format.
    *
    * Index 0 in the array starts 'offset' bytes into the surface.
    * Index 1 begins at byte 'offset + stride', etc. Array indices may
    * not be negative.
    */
   uint32               surfaceId;
   uint32               offset;
   uint32               stride;
} SVGA3dArray;

typedef
struct {
   /*
    * Describe a vertex array's data type, and define how it is to be
    * used by the fixed function pipeline or the vertex shader. It
    * isn't useful to have two VertexDecls with the same
    * VertexArrayIdentity in one draw call.
    */
   SVGA3dDeclType       type;
   SVGA3dDeclMethod     method;
   SVGA3dDeclUsage      usage;
   uint32               usageIndex;
} SVGA3dVertexArrayIdentity;

typedef
struct {
   SVGA3dVertexArrayIdentity  identity;
   SVGA3dArray                array;
   SVGA3dArrayRangeHint       rangeHint;
} SVGA3dVertexDecl;

typedef
struct {
   /*
    * Define a group of primitives to render, from sequential indices.
    *
    * The value of 'primitiveType' and 'primitiveCount' imply the
    * total number of vertices that will be rendered.
    */
   SVGA3dPrimitiveType  primType;
   uint32               primitiveCount;

   /*
    * Optional index buffer. If indexArray.surfaceId is
    * SVGA3D_INVALID_ID, we render without an index buffer. Rendering
    * without an index buffer is identical to rendering with an index
    * buffer containing the sequence [0, 1, 2, 3, ...].
    *
    * If an index buffer is in use, indexWidth specifies the width in
    * bytes of each index value. It must be less than or equal to
    * indexArray.stride.
    *
    * (Currently, the SVGA3D device requires index buffers to be tightly
    * packed. In other words, indexWidth == indexArray.stride)
    */
   SVGA3dArray          indexArray;
   uint32               indexWidth;

   /*
    * Optional index bias. This number is added to all indices from
    * indexArray before they are used as vertex array indices. This
    * can be used in multiple ways:
    *
    *  - When not using an indexArray, this bias can be used to
    *    specify where in the vertex arrays to begin rendering.
    *
    *  - A positive number here is equivalent to increasing the
    *    offset in each vertex array.
    *
    *  - A negative number can be used to render using a small
    *    vertex array and an index buffer that contains large
    *    values. This may be used by some applications that
    *    crop a vertex buffer without modifying their index
    *    buffer.
    *
    * Note that rendering with a negative bias value may be slower and
    * use more memory than rendering with a positive or zero bias.
    */
   int32                indexBias;
} SVGA3dPrimitiveRange;

typedef
struct {
   uint32               cid;
   uint32               numVertexDecls;
   uint32               numRanges;

   /*
    * There are two variable size arrays after the
    * SVGA3dCmdDrawPrimitives structure. In order,
    * they are:
    *
    * 1. SVGA3dVertexDecl, quantity 'numVertexDecls', but no more than
    *    SVGA3D_MAX_VERTEX_ARRAYS;
    * 2. SVGA3dPrimitiveRange, quantity 'numRanges', but no more than
    *    SVGA3D_MAX_DRAW_PRIMITIVE_RANGES;
    * 3. Optionally, SVGA3dVertexDivisor, quantity 'numVertexDecls' (contains
    *    the frequency divisor for the corresponding vertex decl).
    */
} SVGA3dCmdDrawPrimitives;      /* SVGA_3D_CMD_DRAWPRIMITIVES */

typedef
struct {
   uint32                   stage;
   SVGA3dTextureStateName   name;
   union {
      uint32                value;
      float                 floatValue;
   };
} SVGA3dTextureState;

typedef
struct {
   uint32               cid;
   /* Followed by variable number of SVGA3dTextureState structures */
} SVGA3dCmdSetTextureState;      /* SVGA_3D_CMD_SETTEXTURESTATE */

typedef
struct {
   uint32                   cid;
   SVGA3dTransformType      type;
   float                    matrix[16];
} SVGA3dCmdSetTransform;          /* SVGA_3D_CMD_SETTRANSFORM */

typedef
struct {
   float                min;
   float                max;
} SVGA3dZRange;

typedef
struct {
   uint32               cid;
   SVGA3dZRange         zRange;
} SVGA3dCmdSetZRange;             /* SVGA_3D_CMD_SETZRANGE */

typedef
struct {
   float                diffuse[4];
   float                ambient[4];
   float                specular[4];
   float                emissive[4];
   float                shininess;
} SVGA3dMaterial;

typedef
struct {
   uint32               cid;
   SVGA3dFace           face;
   SVGA3dMaterial       material;
} SVGA3dCmdSetMaterial;           /* SVGA_3D_CMD_SETMATERIAL */

typedef
struct {
   uint32               cid;
   uint32               index;
   SVGA3dLightData      data;
} SVGA3dCmdSetLightData;           /* SVGA_3D_CMD_SETLIGHTDATA */

typedef
struct {
   uint32               cid;
   uint32               index;
   uint32               enabled;
} SVGA3dCmdSetLightEnabled;      /* SVGA_3D_CMD_SETLIGHTENABLED */

typedef
struct {
   uint32               cid;
   SVGA3dRect           rect;
} SVGA3dCmdSetViewport;           /* SVGA_3D_CMD_SETVIEWPORT */

typedef
struct {
   uint32               cid;
   SVGA3dRect           rect;
} SVGA3dCmdSetScissorRect;         /* SVGA_3D_CMD_SETSCISSORRECT */

typedef
struct {
   uint32               cid;
   uint32               index;
   float                plane[4];
} SVGA3dCmdSetClipPlane;           /* SVGA_3D_CMD_SETCLIPPLANE */

typedef
struct {
   uint32               cid;
   uint32               shid;
   SVGA3dShaderType     type;
   /* Followed by variable number of DWORDs for shader bycode */
} SVGA3dCmdDefineShader;           /* SVGA_3D_CMD_SHADER_DEFINE */

typedef
struct {
   uint32               cid;
   uint32               shid;
   SVGA3dShaderType     type;
} SVGA3dCmdDestroyShader;         /* SVGA_3D_CMD_SHADER_DESTROY */

typedef
struct {
   uint32                  cid;
   uint32                  reg;     /* register number */
   SVGA3dShaderType        type;
   SVGA3dShaderConstType   ctype;
   uint32                  values[4];
} SVGA3dCmdSetShaderConst;        /* SVGA_3D_CMD_SET_SHADER_CONST */

typedef
struct {
   uint32               cid;
   SVGA3dShaderType     type;
   uint32               shid;
} SVGA3dCmdSetShader;             /* SVGA_3D_CMD_SET_SHADER */

typedef
struct {
   uint32               cid;
   SVGA3dQueryType      type;
} SVGA3dCmdBeginQuery;           /* SVGA_3D_CMD_BEGIN_QUERY */

typedef
struct {
   uint32               cid;
   SVGA3dQueryType      type;
   SVGAGuestPtr         guestResult;  /* Points to an SVGA3dQueryResult structure */
} SVGA3dCmdEndQuery;                  /* SVGA_3D_CMD_END_QUERY */

typedef
struct {
   uint32               cid;          /* Same parameters passed to END_QUERY */
   SVGA3dQueryType      type;
   SVGAGuestPtr         guestResult;
} SVGA3dCmdWaitForQuery;              /* SVGA_3D_CMD_WAIT_FOR_QUERY */

typedef
struct {
   uint32               totalSize;    /* Set by guest before query is ended. */
   SVGA3dQueryState     state;        /* Set by host or guest. See SVGA3dQueryState. */
   union {                            /* Set by host on exit from PENDING state */
      uint32            result32;
   };
} SVGA3dQueryResult;

/*
 * SVGA_3D_CMD_BLIT_SURFACE_TO_SCREEN --
 *
 *    This is a blit from an SVGA3D surface to a Screen Object. Just
 *    like GMR-to-screen blits, this blit may be directed at a
 *    specific screen or to the virtual coordinate space.
 *
 *    The blit copies from a rectangular region of an SVGA3D surface
 *    image to a rectangular region of a screen or screens.
 *
 *    This command takes an optional variable-length list of clipping
 *    rectangles after the body of the command. If no rectangles are
 *    specified, there is no clipping region. The entire destRect is
 *    drawn to. If one or more rectangles are included, they describe
 *    a clipping region. The clip rectangle coordinates are measured
 *    relative to the top-left corner of destRect.
 *
 *    This clipping region serves multiple purposes:
 *
 *      - It can be used to perform an irregularly shaped blit more
 *        efficiently than by issuing many separate blit commands.
 *
 *      - It is equivalent to allowing blits with non-integer
 *        source coordinates. You could blit just one half-pixel
 *        of a source, for example, by specifying a larger
 *        destination rectangle than you need, then removing
 *        part of it using a clip rectangle.
 *
 * Availability:
 *    SVGA_FIFO_CAP_SCREEN_OBJECT
 *
 * Limitations:
 *
 *    - Currently, no backend supports blits from a mipmap or face
 *      other than the first one.
 */

typedef
struct {
   SVGA3dSurfaceImageId srcImage;
   SVGASignedRect       srcRect;
   uint32               destScreenId; /* Screen ID or SVGA_ID_INVALID for virt. coords */
   SVGASignedRect       destRect;     /* Supports scaling if src/rest different size */
   /* Clipping: zero or more SVGASignedRects follow */
} SVGA3dCmdBlitSurfaceToScreen;         /* SVGA_3D_CMD_BLIT_SURFACE_TO_SCREEN */


/*
 * Capability query index.
 *
 * Notes:
 *
 *   1. SVGA3D_DEVCAP_MAX_TEXTURES reflects the maximum number of
 *      fixed-function texture units available. Each of these units
 *      work in both FFP and Shader modes, and they support texture
 *      transforms and texture coordinates. The host may have additional
 *      texture image units that are only usable with shaders.
 *
 *   2. The BUFFER_FORMAT capabilities are deprecated, and they always
 *      return TRUE. Even on physical hardware that does not support
 *      these formats natively, the SVGA3D device will provide an emulation
 *      which should be invisible to the guest OS.
 *
 *      In general, the SVGA3D device should support any operation on
 *      any surface format, it just may perform some of these
 *      operations in software depending on the capabilities of the
 *      available physical hardware.
 *
 *      XXX: In the future, we will add capabilities that describe in
 *      detail what formats are supported in hardware for what kinds
 *      of operations.
 */

typedef enum {
   SVGA3D_DEVCAP_3D                                = 0,
   SVGA3D_DEVCAP_MAX_LIGHTS                        = 1,
   SVGA3D_DEVCAP_MAX_TEXTURES                      = 2,  /* See note (1) */
   SVGA3D_DEVCAP_MAX_CLIP_PLANES                   = 3,
   SVGA3D_DEVCAP_VERTEX_SHADER_VERSION             = 4,
   SVGA3D_DEVCAP_VERTEX_SHADER                     = 5,
   SVGA3D_DEVCAP_FRAGMENT_SHADER_VERSION           = 6,
   SVGA3D_DEVCAP_FRAGMENT_SHADER                   = 7,
   SVGA3D_DEVCAP_MAX_RENDER_TARGETS                = 8,
   SVGA3D_DEVCAP_S23E8_TEXTURES                    = 9,
   SVGA3D_DEVCAP_S10E5_TEXTURES                    = 10,
   SVGA3D_DEVCAP_MAX_FIXED_VERTEXBLEND             = 11,
   SVGA3D_DEVCAP_D16_BUFFER_FORMAT                 = 12, /* See note (2) */
   SVGA3D_DEVCAP_D24S8_BUFFER_FORMAT               = 13, /* See note (2) */
   SVGA3D_DEVCAP_D24X8_BUFFER_FORMAT               = 14, /* See note (2) */
   SVGA3D_DEVCAP_QUERY_TYPES                       = 15,
   SVGA3D_DEVCAP_TEXTURE_GRADIENT_SAMPLING         = 16,
   SVGA3D_DEVCAP_MAX_POINT_SIZE                    = 17,
   SVGA3D_DEVCAP_MAX_SHADER_TEXTURES               = 18,
   SVGA3D_DEVCAP_MAX_TEXTURE_WIDTH                 = 19,
   SVGA3D_DEVCAP_MAX_TEXTURE_HEIGHT                = 20,
   SVGA3D_DEVCAP_MAX_VOLUME_EXTENT                 = 21,
   SVGA3D_DEVCAP_MAX_TEXTURE_REPEAT                = 22,
   SVGA3D_DEVCAP_MAX_TEXTURE_ASPECT_RATIO          = 23,
   SVGA3D_DEVCAP_MAX_TEXTURE_ANISOTROPY            = 24,
   SVGA3D_DEVCAP_MAX_PRIMITIVE_COUNT               = 25,
   SVGA3D_DEVCAP_MAX_VERTEX_INDEX                  = 26,
   SVGA3D_DEVCAP_MAX_VERTEX_SHADER_INSTRUCTIONS    = 27,
   SVGA3D_DEVCAP_MAX_FRAGMENT_SHADER_INSTRUCTIONS  = 28,
   SVGA3D_DEVCAP_MAX_VERTEX_SHADER_TEMPS           = 29,
   SVGA3D_DEVCAP_MAX_FRAGMENT_SHADER_TEMPS         = 30,
   SVGA3D_DEVCAP_TEXTURE_OPS                       = 31,
   SVGA3D_DEVCAP_SURFACEFMT_X8R8G8B8               = 32,
   SVGA3D_DEVCAP_SURFACEFMT_A8R8G8B8               = 33,
   SVGA3D_DEVCAP_SURFACEFMT_A2R10G10B10            = 34,
   SVGA3D_DEVCAP_SURFACEFMT_X1R5G5B5               = 35,
   SVGA3D_DEVCAP_SURFACEFMT_A1R5G5B5               = 36,
   SVGA3D_DEVCAP_SURFACEFMT_A4R4G4B4               = 37,
   SVGA3D_DEVCAP_SURFACEFMT_R5G6B5                 = 38,
   SVGA3D_DEVCAP_SURFACEFMT_LUMINANCE16            = 39,
   SVGA3D_DEVCAP_SURFACEFMT_LUMINANCE8_ALPHA8      = 40,
   SVGA3D_DEVCAP_SURFACEFMT_ALPHA8                 = 41,
   SVGA3D_DEVCAP_SURFACEFMT_LUMINANCE8             = 42,
   SVGA3D_DEVCAP_SURFACEFMT_Z_D16                  = 43,
   SVGA3D_DEVCAP_SURFACEFMT_Z_D24S8                = 44,
   SVGA3D_DEVCAP_SURFACEFMT_Z_D24X8                = 45,
   SVGA3D_DEVCAP_SURFACEFMT_DXT1                   = 46,
   SVGA3D_DEVCAP_SURFACEFMT_DXT2                   = 47,
   SVGA3D_DEVCAP_SURFACEFMT_DXT3                   = 48,
   SVGA3D_DEVCAP_SURFACEFMT_DXT4                   = 49,
   SVGA3D_DEVCAP_SURFACEFMT_DXT5                   = 50,
   SVGA3D_DEVCAP_SURFACEFMT_BUMPX8L8V8U8           = 51,
   SVGA3D_DEVCAP_SURFACEFMT_A2W10V10U10            = 52,
   SVGA3D_DEVCAP_SURFACEFMT_BUMPU8V8               = 53,
   SVGA3D_DEVCAP_SURFACEFMT_Q8W8V8U8               = 54,
   SVGA3D_DEVCAP_SURFACEFMT_CxV8U8                 = 55,
   SVGA3D_DEVCAP_SURFACEFMT_R_S10E5                = 56,
   SVGA3D_DEVCAP_SURFACEFMT_R_S23E8                = 57,
   SVGA3D_DEVCAP_SURFACEFMT_RG_S10E5               = 58,
   SVGA3D_DEVCAP_SURFACEFMT_RG_S23E8               = 59,
   SVGA3D_DEVCAP_SURFACEFMT_ARGB_S10E5             = 60,
   SVGA3D_DEVCAP_SURFACEFMT_ARGB_S23E8             = 61,
   SVGA3D_DEVCAP_MAX_VERTEX_SHADER_TEXTURES        = 63,

   /*
    * Note that MAX_SIMULTANEOUS_RENDER_TARGETS is a maximum count of color
    * render targets.  This does no include the depth or stencil targets.
    */
   SVGA3D_DEVCAP_MAX_SIMULTANEOUS_RENDER_TARGETS   = 64,

   SVGA3D_DEVCAP_SURFACEFMT_V16U16                 = 65,
   SVGA3D_DEVCAP_SURFACEFMT_G16R16                 = 66,
   SVGA3D_DEVCAP_SURFACEFMT_A16B16G16R16           = 67,
   SVGA3D_DEVCAP_SURFACEFMT_UYVY                   = 68,
   SVGA3D_DEVCAP_SURFACEFMT_YUY2                   = 69,

   /*
    * Don't add new caps into the previous section; the values in this
    * enumeration must not change. You can put new values right before
    * SVGA3D_DEVCAP_MAX.
    */
   SVGA3D_DEVCAP_MAX                                  /* This must be the last index. */
} SVGA3dDevCapIndex;

typedef union {
   Bool   b;
   uint32 u;
   int32  i;
   float  f;
} SVGA3dDevCapResult;

#endif /* _SVGA3D_REG_H_ */
07070100000038000081A400000000000000000000000161A68E12000035B4000000000000000000000000000000000000003100000000xf86-video-vmware-13.3.0+12/vmwgfx/vmwgfx_crtc.c/*
 * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas.
 * 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: Alan Hourihane <alanh@tungstengraphics.com>
 * Author: Jakob Bornecrantz <wallbraker@gmail.com>
 * Author: Thomas Hellstrom <thellstrom@vmware.com>
 */
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif

#include <unistd.h>
#include <string.h>
#include <assert.h>
#include <stdlib.h>
#include <math.h>
#include <stdint.h>

#include "xorg-server.h"
#include <xf86.h>
#include <xf86i2c.h>
#include <xf86Crtc.h>
#include <cursorstr.h>
#include "vmwgfx_driver.h"
#include "xf86Modes.h"
#include "vmwgfx_saa.h"

#ifdef HAVE_XEXTPROTO_71
#include <X11/extensions/dpmsconst.h>
#else
#define DPMS_SERVER
#include <X11/extensions/dpms.h>
#endif

struct crtc_private
{
    drmModeCrtcPtr drm_crtc;

    /* hwcursor */
    struct vmwgfx_dmabuf *cursor_bo;
    uint32_t scanout_id;
    unsigned cursor_handle;

    /* Scanout info for pixmaps */
    struct vmwgfx_screen_entry entry;
};

static void
crtc_dpms(xf86CrtcPtr crtc, int mode)
{
    struct crtc_private *crtcp = crtc->driver_private;
    /* ScrnInfoPtr pScrn = crtc->scrn; */

    switch (mode) {
    case DPMSModeOn:
    case DPMSModeStandby:
    case DPMSModeSuspend:
	break;
    case DPMSModeOff:

      /*
       * The xf86 modesetting code uses DPMS off to turn off
       * crtcs that are not enabled. However, the DPMS code does the same.
       * We assume, that if we get this call with the crtc not enabled,
       * it's a permanent switch off which will only be reversed by a
       * major modeset.
       *
       * If it's a DPMS switch off, (crtc->enabled == TRUE),
       * the crtc may be turned on again by
       * another dpms call, so don't release the scanout pixmap ref.
       */
	if (!crtc->enabled && crtcp->entry.pixmap) {
	    vmwgfx_scanout_unref(&crtcp->entry);
	}
	break;
    }
}

/*
 * Disable outputs and crtcs and drop the scanout reference from
 * scanout pixmaps. This will essentialy free all kms fb allocations.
 */

void
vmwgfx_disable_scanout(ScrnInfoPtr pScrn)
{
    int i;
    Bool save_enabled;
    xf86CrtcPtr crtc;
    xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(pScrn);

    xf86DPMSSet(pScrn, DPMSModeOff, 0);
    for (i=0; i < config->num_crtc; ++i) {
	crtc = config->crtc[i];
	save_enabled = crtc->enabled;
	crtc->enabled = FALSE;
	crtc_dpms(crtc, DPMSModeOff);
	crtc->enabled = save_enabled;
    }
    xf86RotateFreeShadow(pScrn);
}

static Bool
vmwgfx_scanout_equals_pixmap(DisplayModePtr mode, PixmapPtr pixmap,
			     int x, int y)
{
    return x == 0 && y == 0;
/*
 * Mode test is disabled for now, since the X server has a tendency to first
 * change the pixmap dimensions, then change the mode, keeping the pixmap.
 * This would lead to a lot of false non-equals, or flickering if we were to
 * kill the drm fb in between.
 * However, currently we prefer false equals as long as x == 0 and y == 0.
 * The false equals will then typically correspond to the primary screen in a
 * multimon setup. Let's live with that for now.
 */
#if 0
	&& mode->HDisplay == pixmap->drawable.width &&
	mode->VDisplay == pixmap->drawable.height;
#endif
}

static Bool
crtc_set_mode_major(xf86CrtcPtr crtc, DisplayModePtr mode,
		    Rotation rotation, int x, int y)
{
    xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(crtc->scrn);
    modesettingPtr ms = modesettingPTR(crtc->scrn);
    ScreenPtr pScreen = crtc->scrn->pScreen;
    xf86OutputPtr output = NULL;
    struct crtc_private *crtcp = crtc->driver_private;
    drmModeCrtcPtr drm_crtc = crtcp->drm_crtc;
    drmModeModeInfo drm_mode;
    int i, ret;
    unsigned int connector_id;
    PixmapPtr pixmap;

    for (i = 0; i < config->num_output; output = NULL, i++) {
	output = config->output[i];

	if (output->crtc == crtc)
	    break;
    }

    if (!output) {
	LogMessage(X_ERROR, "No output for this crtc.\n");
	return FALSE;
    }

    connector_id = xorg_output_get_id(output);

    memset(&drm_mode, 0, sizeof(drm_mode));
    drm_mode.clock = mode->Clock;
    drm_mode.hdisplay = mode->HDisplay;
    drm_mode.hsync_start = mode->HSyncStart;
    drm_mode.hsync_end = mode->HSyncEnd;
    drm_mode.htotal = mode->HTotal;
    drm_mode.vdisplay = mode->VDisplay;
    drm_mode.vsync_start = mode->VSyncStart;
    drm_mode.vsync_end = mode->VSyncEnd;
    drm_mode.vtotal = mode->VTotal;
    drm_mode.flags = mode->Flags;
    drm_mode.hskew = mode->HSkew;
    drm_mode.vscan = mode->VScan;
    drm_mode.vrefresh = mode->VRefresh;
    if (!mode->name)
	xf86SetModeDefaultName(mode);
    strncpy(drm_mode.name, mode->name, DRM_DISPLAY_MODE_LEN - 1);
    drm_mode.name[DRM_DISPLAY_MODE_LEN - 1] = '\0';

    /*
     * Check if we need to scanout from something else than the root
     * pixmap. In that case, xf86CrtcRotate will take care of allocating
     * new opaque scanout buffer data "crtc->rotatedData".
     * However, it will not wrap
     * that data into pixmaps until the first rotated damage composite.
     * In out case, the buffer data is actually already a pixmap.
     */

    if (!xf86CrtcRotate(crtc))
	return FALSE;

    if (crtc->transform_in_use && crtc->rotatedData) {
	x = 0;
	y = 0;
	pixmap = (PixmapPtr) crtc->rotatedData;
    } else
	pixmap = pScreen->GetScreenPixmap(pScreen);

    if (crtcp->entry.pixmap != pixmap) {
	if (crtcp->entry.pixmap)
	    vmwgfx_scanout_unref(&crtcp->entry);

	crtcp->entry.pixmap = pixmap;
	crtcp->scanout_id = vmwgfx_scanout_ref
	    (&crtcp->entry, vmwgfx_scanout_equals_pixmap(mode, pixmap, x, y));
	if (crtcp->scanout_id == -1) {
	    crtcp->entry.pixmap = NULL;
	    LogMessage(X_ERROR, "Failed to convert pixmap to scanout.\n");
	    return FALSE;
	}
    }
    ret = drmModeSetCrtc(ms->fd, drm_crtc->crtc_id, crtcp->scanout_id, x, y,
			 &connector_id, 1, &drm_mode);
    if (ret)
	return FALSE;

    vmwgfx_scanout_refresh(pixmap);

    /* Only set gamma when needed, to avoid unneeded delays. */
#if defined(XF86_CRTC_VERSION) && XF86_CRTC_VERSION >= 3
    if (!crtc->active && crtc->version >= 3)
	crtc->funcs->gamma_set(crtc, crtc->gamma_red, crtc->gamma_green,
			       crtc->gamma_blue, crtc->gamma_size);
    crtc->active = TRUE;
#endif

    /*
     * Strictly, this needs to be done only once per configuration change,
     * not once per crtc, but there's no better place to put this. Since
     * Intel wrote the crtc code, let's do what the xf86-video-intel driver
     * does.
     */
#if (GET_ABI_MAJOR(ABI_VIDEODRV_VERSION) < 23)
    if (pScreen)
	xf86_reload_cursors(pScreen);
#endif

    return TRUE;
}

static void
crtc_gamma_set(xf86CrtcPtr crtc, CARD16 * red, CARD16 * green, CARD16 * blue,
	       int size)
{
    modesettingPtr ms = modesettingPTR(crtc->scrn);
    struct crtc_private *crtcp = crtc->driver_private;

    drmModeCrtcSetGamma(ms->fd, crtcp->drm_crtc->crtc_id, size, red, green, blue);
}

static void *
crtc_shadow_allocate(xf86CrtcPtr crtc, int width, int height)
{
    ScreenPtr pScreen = crtc->scrn->pScreen;
    PixmapPtr rootpix = pScreen->GetScreenPixmap(pScreen);

    /*
     * Use the same depth as for the root pixmap.
     * The associated kms fb will be created on demand once this pixmap
     * is used as scanout by a crtc.
     */

    return pScreen->CreatePixmap(pScreen, width, height,
				 rootpix->drawable.depth, 0);
}

static PixmapPtr
crtc_shadow_create(xf86CrtcPtr crtc, void *data, int width, int height)
{
    return (PixmapPtr) data;
}

static void
crtc_shadow_destroy(xf86CrtcPtr crtc, PixmapPtr rotate_pixmap, void *data)
{
    ScreenPtr pScreen;

    if (rotate_pixmap == NULL)
        return;

    pScreen = rotate_pixmap->drawable.pScreen;
    pScreen->DestroyPixmap(rotate_pixmap);
}


/*
 * Cursor functions
 */

static void
crtc_set_cursor_colors(xf86CrtcPtr crtc, int bg, int fg)
{
    /* XXX: See if this one is needed, as we only support ARGB cursors */
}

static void
crtc_set_cursor_position(xf86CrtcPtr crtc, int x, int y)
{
    modesettingPtr ms = modesettingPTR(crtc->scrn);
    struct crtc_private *crtcp = crtc->driver_private;

    /* Seems like newer X servers try to move cursors without images */
    if (!crtcp->cursor_bo)
	return;

    drmModeMoveCursor(ms->fd, crtcp->drm_crtc->crtc_id, x, y);
}

static void
crtc_load_cursor_argb_kms(xf86CrtcPtr crtc, CARD32 * image)
{
    modesettingPtr ms = modesettingPTR(crtc->scrn);
    struct crtc_private *crtcp = crtc->driver_private;
    unsigned char *ptr;
    xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(crtc->scrn);
    CursorPtr c = config->cursor;

    if (vmwgfx_cursor_bypass(ms->fd, c->bits->xhot, c->bits->yhot) != 0) {
	xf86DrvMsg(crtc->scrn->scrnIndex, X_ERROR,
		   "Failed to set VMWare cursor bypass.\n");
    }

    if (!crtcp->cursor_bo) {
	size_t size = 64*64*4;
        crtcp->cursor_bo = vmwgfx_dmabuf_alloc(ms->fd, size);
	if (!crtcp->cursor_bo) {
	    xf86DrvMsg(crtc->scrn->scrnIndex, X_ERROR,
		       "Failed to create a dmabuf for cursor.\n");
	    return;
	}
	crtcp->cursor_handle = crtcp->cursor_bo->handle;
    }

    ptr = vmwgfx_dmabuf_map(crtcp->cursor_bo);
    if (ptr) {
	memcpy(ptr, image, 64*64*4);
	vmwgfx_dmabuf_unmap(crtcp->cursor_bo);
    } else {
	xf86DrvMsg(crtc->scrn->scrnIndex, X_ERROR,
		   "Failed to map cursor dmabuf.\n");
    }

    if (crtc->cursor_shown)
	drmModeSetCursor(ms->fd, crtcp->drm_crtc->crtc_id,
			 crtcp->cursor_handle, 64, 64);

    return;
}

static void
crtc_load_cursor_argb(xf86CrtcPtr crtc, CARD32 * image)
{
    xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(crtc->scrn);
    modesettingPtr ms = modesettingPTR(crtc->scrn);

    /* Older X servers have cursor reference counting bugs leading to use of
     * freed memory and consequently random crashes. Should be fixed as of
     * xserver 1.8, but this workaround shouldn't hurt anyway.
     */
    if (config->cursor)
       config->cursor->refcnt++;

    if (ms->cursor)
       FreeCursor(ms->cursor, None);

    ms->cursor = config->cursor;
    crtc_load_cursor_argb_kms(crtc, image);
}

static void
crtc_show_cursor(xf86CrtcPtr crtc)
{
    modesettingPtr ms = modesettingPTR(crtc->scrn);
    struct crtc_private *crtcp = crtc->driver_private;

    if (crtcp->cursor_bo)
	drmModeSetCursor(ms->fd, crtcp->drm_crtc->crtc_id,
			 crtcp->cursor_handle, 64, 64);
}

static void
crtc_hide_cursor(xf86CrtcPtr crtc)
{
    modesettingPtr ms = modesettingPTR(crtc->scrn);
    struct crtc_private *crtcp = crtc->driver_private;

    drmModeSetCursor(ms->fd, crtcp->drm_crtc->crtc_id, 0, 0, 0);
}

/**
 * Called at vt leave
 */
void
xorg_crtc_cursor_destroy(xf86CrtcPtr crtc)
{
    struct crtc_private *crtcp = crtc->driver_private;

    if (crtcp->cursor_bo) {
	vmwgfx_dmabuf_destroy(crtcp->cursor_bo);
	crtcp->cursor_bo = NULL;
    }
}

/*
 * Misc functions
 */

static void
crtc_destroy(xf86CrtcPtr crtc)
{
    struct crtc_private *crtcp = crtc->driver_private;

    if (!WSBMLISTEMPTY(&crtcp->entry.scanout_head))
	vmwgfx_scanout_unref(&crtcp->entry);

    xorg_crtc_cursor_destroy(crtc);

    drmModeFreeCrtc(crtcp->drm_crtc);

    free(crtcp);
    crtc->driver_private = NULL;
}

static const xf86CrtcFuncsRec crtc_funcs = {
    .dpms = crtc_dpms,
    .set_mode_major = crtc_set_mode_major,

    .set_cursor_colors = crtc_set_cursor_colors,
    .set_cursor_position = crtc_set_cursor_position,
    .show_cursor = crtc_show_cursor,
    .hide_cursor = crtc_hide_cursor,
    .load_cursor_argb = crtc_load_cursor_argb,

    .shadow_create = crtc_shadow_create,
    .shadow_allocate = crtc_shadow_allocate,
    .shadow_destroy = crtc_shadow_destroy,

    .gamma_set = crtc_gamma_set,
    .destroy = crtc_destroy,
};

void
xorg_crtc_init(ScrnInfoPtr pScrn)
{
    modesettingPtr ms = modesettingPTR(pScrn);
    xf86CrtcPtr crtc;
    drmModeResPtr res;
    drmModeCrtcPtr drm_crtc = NULL;
    struct crtc_private *crtcp;
    int c;

    res = drmModeGetResources(ms->fd);
    if (res == 0) {
	ErrorF("Failed drmModeGetResources %d\n", errno);
	return;
    }

    for (c = 0; c < res->count_crtcs; c++) {
	drm_crtc = drmModeGetCrtc(ms->fd, res->crtcs[c]);

	if (!drm_crtc)
	    continue;

	crtc = xf86CrtcCreate(pScrn, &crtc_funcs);
	if (crtc == NULL)
	    goto out;

	crtcp = calloc(1, sizeof(struct crtc_private));
	if (!crtcp) {
	    xf86CrtcDestroy(crtc);
	    goto out;
	}

	crtcp->drm_crtc = drm_crtc;
	crtcp->entry.pixmap = NULL;
	WSBMINITLISTHEAD(&crtcp->entry.scanout_head);

	crtc->driver_private = crtcp;
    }

  out:
    drmModeFreeResources(res);
}

PixmapPtr
crtc_get_scanout(xf86CrtcPtr crtc)
{
    struct crtc_private *crtcp = crtc->driver_private;
    return crtcp->entry.pixmap;
}

/* vim: set sw=4 ts=8 sts=4: */
07070100000039000081A400000000000000000000000161A68E12000033F1000000000000000000000000000000000000003100000000xf86-video-vmware-13.3.0+12/vmwgfx/vmwgfx_ctrl.c/*
 * Copyright 2006-2011 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 <xorg-server.h>
#include "dixstruct.h"
#include "extnsionst.h"
#include <X11/X.h>
#include <X11/extensions/panoramiXproto.h>

#include "vmwarectrlproto.h"
#include "vmwgfx_driver.h"
#include "vmwgfx_drmi.h"

/*
 *----------------------------------------------------------------------------
 *
 * 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)
{
   modesettingPtr ms = modesettingPTR(pScrn);
   struct drm_vmw_rect rect;
   int ret;

   rect.x = 0;
   rect.y = 0;
   rect.w = x;
   rect.h = y;

   ms->autoLayout = FALSE;
   ret = vmwgfx_update_gui_layout(ms->fd, 1, &rect);
   return (ret == 0);
}


/*
 *----------------------------------------------------------------------------
 *
 * 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)) {
      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)
{
   modesettingPtr ms = modesettingPTR(pScrn);
   struct drm_vmw_rect *rects;
   int i;
   int ret;

   rects = calloc(number, sizeof(*rects));
   if (!rects)
      return FALSE;

   for (i = 0; i < number; i++) {
      rects[i].x = extents[i].x_org;
      rects[i].y = extents[i].y_org;
      rects[i].w = extents[i].width;
      rects[i].h = extents[i].height;
   }

   ms->autoLayout = FALSE;
   ret = vmwgfx_update_gui_layout(ms->fd, number, rects);

   free(rects);
   return (ret == 0);
}


/*
 *----------------------------------------------------------------------------
 *
 * 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
vmw_ctrl_ext_init(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);
   }
}
0707010000003A000081A400000000000000000000000161A68E120000074A000000000000000000000000000000000000003100000000xf86-video-vmware-13.3.0+12/vmwgfx/vmwgfx_ctrl.h/*
 * 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).
 */

/*
 * vmwgfx_ctrl.h --
 *
 *      The definitions used by the VMWARE_CTRL protocol extension that
 *      allows X clients to communicate with the driver.
 */


#ifndef _VMWGFX_CTRL_H_
#define _VMWGFX_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 /* _VMW_CTRL_H_ */
0707010000003B000081A400000000000000000000000161A68E12000034F8000000000000000000000000000000000000003100000000xf86-video-vmware-13.3.0+12/vmwgfx/vmwgfx_dri2.c/*
 * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas.
 * 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: Alan Hourihane <alanh@tungstengraphics.com>
 * Author: Jakob Bornecrantz <wallbraker@gmail.com>
 * Author: Thomas Hellstrom <thellstrom@vmware.com>
 *
 */
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif

#include "xorg-server.h"
#include "xf86.h"
#include "xf86_OSproc.h"

#include "vmwgfx_driver.h"
#include "../saa/saa.h"

#include "dri2.h"
#include "gcstruct.h"
#include "gc.h"
#include "vmwgfx_saa.h"
#include "wsbm_util.h"
#include <unistd.h>
#include "vmwgfx_hosted.h"

#define VMWGFX_FD_PATH_LEN 80

typedef struct {
    int refcount;
    PixmapPtr pPixmap;
    struct xa_surface *srf;
    unsigned int dri2_depth;
} *BufferPrivatePtr;


/*
 * Attempt to guess what the dri state tracker is up to.
 * Currently it sends only bpp as format.
 */

static unsigned int
vmwgfx_color_format_to_depth(unsigned int format)
{
    return format;
}

static unsigned int
vmwgfx_zs_format_to_depth(unsigned int format)
{
    if (format == 24)
	return 32;
    return format;
}

static unsigned int
vmwgfx_z_format_to_depth(unsigned int format)
{
    return format;
}

static Bool
dri2_do_create_buffer(DrawablePtr pDraw, DRI2Buffer2Ptr buffer, unsigned int format)
{
    ScreenPtr pScreen = pDraw->pScreen;
    ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
    modesettingPtr ms = modesettingPTR(pScrn);
    BufferPrivatePtr private = buffer->driverPrivate;
    PixmapPtr pPixmap;
    struct vmwgfx_saa_pixmap *vpix;
    struct xa_surface *srf = NULL;
    unsigned int depth;


    if (pDraw->type == DRAWABLE_PIXMAP)
	pPixmap = (PixmapPtr) pDraw;
    else
	pPixmap = (*pScreen->GetWindowPixmap)((WindowPtr) pDraw);

    vpix = vmwgfx_saa_pixmap(pPixmap);
    private->refcount = 0;

    switch (buffer->attachment) {
    default:
	depth = (format) ? vmwgfx_color_format_to_depth(format) :
	    pDraw->depth;

	if (buffer->attachment != DRI2BufferFakeFrontLeft ||
	    &pPixmap->drawable != pDraw) {

	    pPixmap = (*pScreen->CreatePixmap)(pScreen,
					       pDraw->width,
					       pDraw->height,
					       depth,
					       0);
	    if (pPixmap == NullPixmap)
		return FALSE;

	    private->pPixmap = pPixmap;
	    private->dri2_depth = depth;
	    vpix = vmwgfx_saa_pixmap(pPixmap);
	}
	break;
    case DRI2BufferFrontLeft:
      if (&pPixmap->drawable == pDraw)
	  break;
      buffer->name = 0;
      buffer->pitch = 0;
      buffer->cpp = pDraw->bitsPerPixel / 8;
      buffer->driverPrivate = private;
      buffer->flags = 0; /* not tiled */
      buffer->format = pDraw->bitsPerPixel;
      if (!private->pPixmap) {
	private->dri2_depth = 0;
	private->pPixmap = pPixmap;
	pPixmap->refcnt++;
      }
      return TRUE;
    case DRI2BufferStencil:
    case DRI2BufferDepthStencil:
	if (!pScrn->vtSema)
	    return FALSE;

	depth = (format) ? vmwgfx_zs_format_to_depth(format) : 32;

	/*
	 * The SVGA device uses the zs ordering.
	 */

	srf = xa_surface_create(ms->xat, pDraw->width, pDraw->height,
				depth, xa_type_zs, xa_format_unknown,
				XA_FLAG_SHARED );
	if (!srf)
	    return FALSE;

	private->dri2_depth = depth;

       break;
    case DRI2BufferDepth:
	if (!pScrn->vtSema)
	    return FALSE;

	depth = (format) ? vmwgfx_z_format_to_depth(format) :
	    pDraw->bitsPerPixel;

	if (depth == 24)
	    srf = xa_surface_create(ms->xat, pDraw->width, pDraw->height,
				    depth, xa_type_zs, xa_format_unknown,
				    XA_FLAG_SHARED );
	else
	    srf = xa_surface_create(ms->xat, pDraw->width, pDraw->height,
				    depth,
				    xa_type_z, xa_format_unknown,
				    XA_FLAG_SHARED);
	if (!srf)
	    return FALSE;

	private->dri2_depth = depth;

	break;
    }

    if (!private->pPixmap) {
	private->pPixmap = pPixmap;
	pPixmap->refcnt++;
    }

    if (!srf) {
	depth = (format) ? vmwgfx_color_format_to_depth(format) :
	    pDraw->depth;

	if (!vmwgfx_hw_dri2_validate(pPixmap, depth))
	    return FALSE;

	srf = vpix->hw;
	private->refcount++;
	private->dri2_depth = depth;

	/*
	 * Compiz workaround. See vmwgfx_dirty();
	 */

	if (buffer->attachment == DRI2BufferFrontLeft ||
	    buffer->attachment == DRI2BufferFakeFrontLeft)
	    vpix->hw_is_dri2_fronts++;
    }

    private->srf = srf;
    if (_xa_surface_handle(srf, &buffer->name, &buffer->pitch) != 0)
	return FALSE;

    buffer->cpp = xa_format_depth(xa_surface_format(srf)) / 8;
    buffer->driverPrivate = private;
    buffer->flags = 0; /* not tiled */
    buffer->format = format;
    private->refcount++;

    return TRUE;
}

static void
dri2_do_destroy_buffer(DrawablePtr pDraw, DRI2BufferPtr buffer)
{
    BufferPrivatePtr private = buffer->driverPrivate;
    struct xa_surface *srf = private->srf;
    ScreenPtr pScreen = pDraw->pScreen;
    struct vmwgfx_saa_pixmap *vpix = vmwgfx_saa_pixmap(private->pPixmap);

    if (--private->refcount == 0 && srf) {
	xa_surface_destroy(srf);
    }

    /*
     * Compiz workaround. See vmwgfx_dirty();
     */

    if ((buffer->attachment == DRI2BufferFrontLeft ||
	 buffer->attachment == DRI2BufferFakeFrontLeft) &&
	private->refcount == 1 &&
	--vpix->hw_is_dri2_fronts == 0)
	WSBMLISTDELINIT(&vpix->sync_x_head);

    private->srf = NULL;
    pScreen->DestroyPixmap(private->pPixmap);
}


static DRI2Buffer2Ptr
dri2_create_buffer(DrawablePtr pDraw, unsigned int attachment, unsigned int format)
{
    DRI2Buffer2Ptr buffer;
    BufferPrivatePtr private;

    buffer = calloc(1, sizeof *buffer);
    if (!buffer)
	return NULL;

    private = calloc(1, sizeof *private);
    if (!private) {
	goto fail;
    }

    buffer->attachment = attachment;
    buffer->driverPrivate = private;

    if (dri2_do_create_buffer(pDraw, buffer, format))
	return buffer;

    free(private);
fail:
    free(buffer);
    return NULL;
}

static void
dri2_destroy_buffer(DrawablePtr pDraw, DRI2Buffer2Ptr buffer)
{
    /* So far it is safe to downcast a DRI2Buffer2Ptr to DRI2BufferPtr */
    dri2_do_destroy_buffer(pDraw, (DRI2BufferPtr)buffer);

    free(buffer->driverPrivate);
    free(buffer);
}

static void
dri2_copy_region(DrawablePtr pDraw, RegionPtr pRegion,
                 DRI2Buffer2Ptr pDestBuffer, DRI2Buffer2Ptr pSrcBuffer)
{


    ScreenPtr pScreen = pDraw->pScreen;
    BufferPrivatePtr dst_priv = pDestBuffer->driverPrivate;
    BufferPrivatePtr src_priv = pSrcBuffer->driverPrivate;
    DrawablePtr src_draw;
    DrawablePtr dst_draw;
    RegionPtr myClip;
    GCPtr gc;
    ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);

    /*
     * This is a fragile protection against HW operations when not master.
     * Needs to be blocked higher up in the dri2 code.
     */
    if (!pScrn->vtSema)
	return;

    /*
     * In driCreateBuffers we dewrap windows into the
     * backing pixmaps in order to get to the texture.
     * We need to use the real drawable in CopyArea
     * so that cliprects and offsets are correct.
     */
    src_draw = (pSrcBuffer->attachment == DRI2BufferFrontLeft) ? pDraw :
       &src_priv->pPixmap->drawable;
    dst_draw = (pDestBuffer->attachment == DRI2BufferFrontLeft) ? pDraw :
       &dst_priv->pPixmap->drawable;

    /*
     * The clients implements glXWaitX with a copy front to fake and then
     * waiting on the server to signal its completion of it. While
     * glXWaitGL is a client side flush and a copy from fake to front.
     * This is how it is done in the DRI2 protocol, how ever depending
     * which type of drawables the server does things a bit differently
     * then what the protocol says as the fake and front are the same.
     *
     * for pixmaps glXWaitX is a server flush.
     * for pixmaps glXWaitGL is a client flush.
     * for windows glXWaitX is a copy from front to fake then a server flush.
     * for windows glXWaitGL is a client flush then a copy from fake to front.
     *
     * XXX in the windows case this code always flushes but that isn't a
     * must in the glXWaitGL case but we don't know if this is a glXWaitGL
     * or a glFlush/glFinish call.
     */
    if (dst_priv->pPixmap == src_priv->pPixmap) {
	/* pixmap glXWaitX */
	if (pSrcBuffer->attachment == DRI2BufferFrontLeft &&
	    pDestBuffer->attachment == DRI2BufferFakeFrontLeft) {
	    
	    if (!vmwgfx_hw_dri2_validate(dst_priv->pPixmap,
					 dst_priv->dri2_depth))
		return;
	}
	/* pixmap glXWaitGL */
	if (pDestBuffer->attachment == DRI2BufferFrontLeft &&
	    pSrcBuffer->attachment == DRI2BufferFakeFrontLeft) {
	    return;
	} else {
	    vmwgfx_flush_dri2(pScreen);
	    return;
	}
    }

    gc = GetScratchGC(pDraw->depth, pScreen);
    myClip = REGION_CREATE(pScreen, REGION_RECTS(pRegion),
			   REGION_NUM_RECTS(pRegion));
    (*gc->funcs->ChangeClip) (gc, CT_REGION, myClip, 0);
    ValidateGC(dst_draw, gc);

    /*
     * Damage the src drawable in order for damageCopyArea to pick up
     * that something changed.
     */
    DamageRegionAppend(src_draw, pRegion);
    if (pSrcBuffer->attachment != DRI2BufferFrontLeft)
	saa_drawable_dirty(src_draw, TRUE, pRegion);
    DamageRegionProcessPending(src_draw);

    /*
     * Call CopyArea. This usually means a call to damageCopyArea that
     * is wrapping saa_copy_area. The damageCopyArea function will make
     * sure the destination drawable is appropriately damaged.
     */
    (*gc->ops->CopyArea)(src_draw, dst_draw, gc,
			 0, 0, pDraw->width, pDraw->height, 0, 0);

    /*
     * FreeScratchGC will free myClip as well.
     */
    myClip = NULL;
    FreeScratchGC(gc);
}

#if (DRI2INFOREC_VERSION >= 8 && DRI2INFOREC_VERSION < 10)
static int vmw_dri_auth_magic2(ScreenPtr pScreen, uint32_t magic)
{
    ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
    modesettingPtr ms = modesettingPTR(pScrn);

    return vmwgfx_hosted_dri_auth(ms->hdriver, ms->hosted, NULL, magic);
}
#endif

#if (DRI2INFOREC_VERSION >= 10)
static int vmw_dri_auth_magic3(ClientPtr client, ScreenPtr pScreen,
			       uint32_t magic)
{
    ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
    modesettingPtr ms = modesettingPTR(pScrn);

    return vmwgfx_hosted_dri_auth(ms->hdriver, ms->hosted, client, magic);
}
#endif

Bool
xorg_dri2_init(ScreenPtr pScreen)
{
    ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
    modesettingPtr ms = modesettingPTR(pScrn);
    DRI2InfoRec dri2info;
    int major, minor;

    memset(&dri2info, 0, sizeof(dri2info));

    if (xf86LoaderCheckSymbol("DRI2Version")) {
	DRI2Version(&major, &minor);
    } else {
	/* Assume version 1.0 */
	major = 1;
	minor = 0;
    }

    dri2info.version = min(DRI2INFOREC_VERSION, 3);
    dri2info.fd = ms->fd;
    dri2info.driverName = "vmwgfx";

#ifdef VMWGFX_LIBDRM_DEVICENAME
    ms->dri2_device_name = drmGetDeviceNameFromFd2(ms->fd);

    if (!ms->dri2_device_name) {
	xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
		   "Could not find the drm device name. Disabling dri2.\n");
	return FALSE;
    }
#else
    /*
     * This way of obtaining the DRM device name is a bit
     * os-specific. Currently this works only for Linux.
     */
    {
	char fdPath[VMWGFX_FD_PATH_LEN];
	ssize_t numChar;

	memset(fdPath, 0, VMWGFX_FD_PATH_LEN);
	snprintf(fdPath, VMWGFX_FD_PATH_LEN - 1, "/proc/self/fd/%d", ms->fd);
	numChar = readlink(fdPath, ms->dri2_device_name, VMWGFX_DRI_DEVICE_LEN);
	if (numChar <= 0 || numChar >= VMWGFX_DRI_DEVICE_LEN) {
	    xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
		       "Could not find the drm device name. Disabling dri2.\n");
	    return FALSE;
	}
	ms->dri2_device_name[numChar] = 0;
    }
#endif
    dri2info.deviceName = ms->dri2_device_name;
    xf86DrvMsg(pScrn->scrnIndex, X_INFO,
	       "Path of drm device is \"%s\".\n", ms->dri2_device_name);

    dri2info.CreateBuffer = dri2_create_buffer;
    dri2info.DestroyBuffer = dri2_destroy_buffer;

    dri2info.CopyRegion = dri2_copy_region;
    dri2info.Wait = NULL;

#if (DRI2INFOREC_VERSION >= 8 && DRI2INFOREC_VERSION < 10)
    if (vmwgfx_is_hosted(ms->hdriver)) {
	dri2info.version = 8;
	dri2info.AuthMagic2 = vmw_dri_auth_magic2;
    }
#endif
#if (DRI2INFOREC_VERSION >= 10)
    if (vmwgfx_is_hosted(ms->hdriver)) {
	dri2info.version = 10;
	dri2info.AuthMagic3 = vmw_dri_auth_magic3;
    }
#endif

    return DRI2ScreenInit(pScreen, &dri2info);
}

void
xorg_dri2_close(ScreenPtr pScreen)
{
#ifdef VMWGFX_LIBDRM_DEVICENAME
    ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
    modesettingPtr ms = modesettingPTR(pScrn);

    free(ms->dri2_device_name);
#endif

    DRI2CloseScreen(pScreen);
}

/* vim: set sw=4 ts=8 sts=4: */
0707010000003C000081A400000000000000000000000161A68E12000023B1000000000000000000000000000000000000003100000000xf86-video-vmware-13.3.0+12/vmwgfx/vmwgfx_dri3.c/*
 * Copyright 2017 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>
 *
 */
#ifdef _HAVE_CONFIG_H_
#include "config.h"
#endif

#include <xorg-server.h>

#ifdef DRI3
#include "vmwgfx_driver.h"
#if (XA_TRACKER_VERSION_MAJOR == VMW_XA_VERSION_MAJOR_DRI3 &&   \
     XA_TRACKER_VERSION_MINOR >= VMW_XA_VERSION_MINOR_DRI3)

#include "vmwgfx_driver.h"
#include "vmwgfx_saa_priv.h"
#include <dri3.h>
#include <misyncshm.h>
#include <xf86drm.h>
#include <unistd.h>


/**
 * \brief DRI3 fd_from_pixmap callback.
 *
 */
static int
vmwgfx_dri3_fd_from_pixmap(ScreenPtr screen, PixmapPtr pixmap,
                           CARD16 *stride, CARD32 *size)
{
    struct vmwgfx_saa_pixmap *vpix = vmwgfx_saa_pixmap(pixmap);
    uint32_t handle;
    unsigned int byte_stride;
    ScrnInfoPtr pScrn = xf86ScreenToScrn(screen);

    if (!vmwgfx_hw_dri2_validate(pixmap, 0)) {
        xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
                   "DRI3 pixmap export failed to create HW surface.\n");
        return -1;
    }

    if (xa_surface_handle(vpix->hw, xa_handle_type_fd, &handle,
                          &byte_stride)) {
        xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
                   "DRI3 pixmap export failed to create handle.\n");
        return -1;
    }

    *stride = byte_stride;
    *size = byte_stride * pixmap->drawable.height;

    /*
     * hw_is_dri2_fronts will make sure any software rendering to
     * this pixmap is immediately flushed to the underlying surface.
     * Strictly, we could wait for glxWaitX to do that, but alas,
     * even the dri3 glxWaitX appears as broken as the dri2 version.
     * If we, however, wanted to do that, we'd hook up a shm fence
     * trigger callback. (Like glamor does).
     */
    vpix->hw_is_dri2_fronts = 1;

    return handle;
}

/**
 * \brief DRI3 pixmap_from_fd callback.
 *
 */
static PixmapPtr
vmwgfx_dri3_pixmap_from_fd(ScreenPtr screen, int fd,
                           CARD16 width, CARD16 height, CARD16 stride,
                           CARD8 depth, CARD8 bpp)
{
    struct vmwgfx_saa *vsaa = to_vmwgfx_saa(saa_get_driver(screen));
    struct xa_surface *srf;
    struct vmwgfx_saa_pixmap *vpix;
    ScrnInfoPtr pScrn = xf86ScreenToScrn(screen);
    PixmapPtr pixmap;

    if (width == 0 || height == 0 ||
        depth < 15 || bpp != BitsPerPixel(depth) || stride < width * bpp / 8)
        return NULL;

    pixmap = screen->CreatePixmap(screen, width, height, depth, 0);
    if (!pixmap) {
        xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "DRI3 pixmap creation failed.\n");
        return NULL;
    }

    vpix = vmwgfx_saa_pixmap(pixmap);

    if (!vmwgfx_hw_dri2_stage(pixmap, depth)) {
        xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
                   "DRI3 pixmap creation bad format.\n");
        goto out_bad_format;
    }

    srf = xa_surface_from_handle2(vsaa->xat, width, height, depth,
                                  xa_type_other,
                                  vpix->staging_format,
                                  vpix->staging_add_flags,
                                  xa_handle_type_fd,
                                  fd, stride);
    if (!srf) {
        xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
                   "DRI3 pixmap creation surface sharing failed.\n");
        goto out_bad_format;
    }

    vpix->xa_flags = vpix->staging_add_flags;
    vpix->hw = srf;
    if (!vmwgfx_create_hw(vsaa, pixmap, TRUE)) {
        xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
                   "DRI3 pixmap creation failed SAA enabling.\n");
        goto out_no_damage;
    }

    vpix->hw_is_dri2_fronts = 1;
    return pixmap;

  out_no_damage:
    xa_surface_unref(srf);
  out_bad_format:
    screen->DestroyPixmap(pixmap);

    return NULL;
}

/**
 * \brief Open a render node.
 *
 * \param screen[IN]  Pointer to the screen
 * \return  A valid file descriptor or -1 on failure.
 */
static int
vmwgfx_dri3_open_render(ScreenPtr screen)
{
    ScrnInfoPtr pScrn = xf86ScreenToScrn(screen);
    modesettingPtr ms = modesettingPTR(pScrn);
    char bus_id[64];
    int fd;

    snprintf(bus_id, sizeof(bus_id), "PCI:%d:%d:%d",
             ((ms->PciInfo->domain << 8) | ms->PciInfo->bus),
             ms->PciInfo->dev, ms->PciInfo->func);

    /* Render nodes can't be opened by busid yet.. */
    fd = drmOpenWithType("vmwgfx", bus_id, DRM_NODE_RENDER);
    if (fd < 0)
        xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
                   "DRI3 client open busid \"%s\" failed.\n", bus_id);

    return fd;
}

/**
 * \brief DRI3 open_client callback.
 *
 */
static int
vmwgfx_dri3_open_client(ClientPtr client, ScreenPtr screen,
                        RRProviderPtr provider, int *pfd)
{
    *pfd = vmwgfx_dri3_open_render(screen);

    return (*pfd >= 0) ? Success : BadAlloc;
}

/**
 * \brief Verify that surface sharing between render client and X server
 * works.
 *
 * \param screen[IN,OUT]  A pointer to the current screen.
 * \return TRUE if successful, FALSE otherwise.
 *
 * Opens a render client, creates a surface and tries to share that surface
 * with the X server. There is a vmwgfx kernel driver bug that, combined
 * with a pre-guest-backed-surface svga mesa driver bug,
 * prevents this sharing to happen and thus breaks dri3.
 *
 * Also, we need to make sure that we can share an XRGB surface as an
 * ARGB surface since DRI3 does not appear to be as strict about internal
 * surface formats as DRI2.
 */
static Bool
vmwgfx_dri3_verify_sharing(ScreenPtr screen)
{
    ScrnInfoPtr pScrn = xf86ScreenToScrn(screen);
    modesettingPtr ms = modesettingPTR(pScrn);
    int fd = vmwgfx_dri3_open_render(screen);
    struct xa_tracker *xat;
    struct xa_surface *srf1;
    unsigned int stride;
    uint32_t handle;
    Bool ret = FALSE;

    if (fd < 0)
        return FALSE;

    xat = xa_tracker_create(fd);
    if (!xat)
        goto out_no_xa;

    /* Here we're the render client (xat) */
    srf1 = xa_surface_create(xat, 16, 16, 32, xa_type_argb,
                             xa_format_unknown,
                             XA_FLAG_RENDER_TARGET | XA_FLAG_SHARED);
    if (!srf1)
        goto out_no_surface;

    if (xa_surface_handle(srf1, xa_handle_type_fd, &handle, &stride) !=
        XA_ERR_NONE)
        goto out_no_handle;

    xa_surface_unref(srf1);

    /* Now we're the X server (ms->xat) */
    srf1 = xa_surface_from_handle2(ms->xat, 16, 16, 24, xa_type_argb,
                                   xa_format_unknown,
                                   XA_FLAG_RENDER_TARGET | XA_FLAG_SHARED,
                                   xa_handle_type_fd, handle, stride);
    if (!srf1)
        goto out_no_surface;

    ret = TRUE;
    close(handle);

  out_no_handle:
    xa_surface_unref(srf1);
  out_no_surface:
    xa_tracker_destroy(xat);
  out_no_xa:
    close(fd);

    return ret;
}

static dri3_screen_info_rec vmwgfx_dri3_info = {
    .version = 1,
    .open = NULL,
    .pixmap_from_fd = vmwgfx_dri3_pixmap_from_fd,
    .fd_from_pixmap = vmwgfx_dri3_fd_from_pixmap,
    .open_client = vmwgfx_dri3_open_client,
};


/**
 * \brief Initialize dri3.
 *
 * \param screen[IN,OUT]  A pointer to the current screen.
 * \return TRUE if successful, FALSE otherwise.
 */
Bool
vmwgfx_dri3_init(ScreenPtr screen)
{
    ScrnInfoPtr pScrn = xf86ScreenToScrn(screen);

    if (!vmwgfx_dri3_verify_sharing(screen)) {
        xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
                   "Failed to verify XA surface sharing for DRI3.\n");
        return FALSE;
    }

    if (!miSyncShmScreenInit(screen)) {
        xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
                   "Failed to initialize xshm sync for DRI3.\n");
        return FALSE;
    }

    if (!dri3_screen_init(screen, &vmwgfx_dri3_info)) {
        xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Failed to initialize DRI3.\n");
        return FALSE;
    }

    return TRUE;
}

#else /* XA INCLUDES SUFFICIENT */
Bool
vmwgfx_dri3_init(ScreenPtr screen)
{
    return FALSE;
}

#endif /* !XA INCLUDES SUFFICIENT */
#endif /* DRI3 */
0707010000003D000081A400000000000000000000000161A68E1200008C6F000000000000000000000000000000000000003300000000xf86-video-vmware-13.3.0+12/vmwgfx/vmwgfx_driver.c/*
 * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas.
 * 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: Alan Hourihane <alanh@tungstengraphics.com>
 * Author: Jakob Bornecrantz <wallbraker@gmail.com>
 * Author: Thomas Hellstrom <thellstrom@vmware.com>
 */

#ifdef HAVE_CONFIG_H
#include "config.h"
#endif

#include <unistd.h>
#include <fcntl.h>
#include "xorg-server.h"
#include "xf86.h"
#include "xf86_OSproc.h"
#include "compiler.h"
#include "xf86Pci.h"
#include "mipointer.h"
#include "micmap.h"
#include <X11/extensions/randr.h>
#include "fb.h"
#include "edid.h"
#include "xf86i2c.h"
#include "xf86Crtc.h"
#include "miscstruct.h"
#include "dixstruct.h"
#include "xf86cmap.h"
#include "xf86xv.h"
#include "xorgVersion.h"
#ifndef XSERVER_LIBPCIACCESS
#error "libpciaccess needed"
#endif

#include <pciaccess.h>

#ifdef XSERVER_PLATFORM_BUS
#include "xf86platformBus.h"
#endif

#include "vmwgfx_driver.h"

#include <saa.h>
#include "vmwgfx_saa.h"
#include "../src/vmware_bootstrap.h"
#include "../src/vmware_common.h"
#include "vmwgfx_hosted.h"
#include "common_compat.h"

/*
 * We can't incude svga_types.h due to conflicting types for Bool.
 */
typedef int64_t int64;
typedef uint64_t uint64;

typedef int32_t int32;
typedef uint32_t uint32;

typedef int16_t int16;
typedef uint16_t uint16;

typedef int8_t int8;
typedef uint8_t uint8;
#include "../src/svga_reg.h"

#define XA_VERSION_MINOR_REQUIRED 0
#define XA_VERSION_MAJOR_REQUIRED 1
#define XA_VERSION_MAJOR_COMPAT 2

#define DRM_VERSION_MAJOR_REQUIRED 2
#define DRM_VERSION_MINOR_REQUIRED 3

/*
 * Some macros to deal with function wrapping.
 */
#define vmwgfx_wrap(priv, real, mem, func) {\
	(priv)->saved_##mem = (real)->mem;	\
	(real)->mem = func;			\
}

#define vmwgfx_unwrap(priv, real, mem) {\
	(real)->mem = (priv)->saved_##mem;	\
}

#define vmwgfx_swap(priv, real, mem) {\
	void *tmp = (priv)->saved_##mem;		\
	(priv)->saved_##mem = (real)->mem;	\
	(real)->mem = tmp;			\
}

/*
 * Functions and symbols exported to Xorg via pointers.
 */

static Bool drv_pre_init(ScrnInfoPtr pScrn, int flags);
static Bool drv_screen_init(SCREEN_INIT_ARGS_DECL);
static Bool drv_switch_mode(SWITCH_MODE_ARGS_DECL);
static void drv_adjust_frame(ADJUST_FRAME_ARGS_DECL);
static Bool drv_enter_vt(VT_FUNC_ARGS_DECL);
static void drv_leave_vt(VT_FUNC_ARGS_DECL);
static void drv_free_screen(FREE_SCREEN_ARGS_DECL);
static ModeStatus drv_valid_mode(SCRN_ARG_TYPE arg, DisplayModePtr mode, Bool verbose,
			         int flags);

extern void xorg_tracker_set_functions(ScrnInfoPtr scrn);

void
vmwgfx_hookup(ScrnInfoPtr pScrn)
{
    pScrn->PreInit = drv_pre_init;
    pScrn->ScreenInit = drv_screen_init;
    pScrn->SwitchMode = drv_switch_mode;
    pScrn->FreeScreen = drv_free_screen;
    pScrn->ValidMode = drv_valid_mode;
}

void
vmwgfx_modify_flags(uint32_t *flags)
{
    *flags &= ~(HW_IO);
    vmwgfx_hosted_modify_flags(flags);
}
/*
 * Internal function definitions
 */

static Bool drv_close_screen(CLOSE_SCREEN_ARGS_DECL);

/*
 * Internal functions
 */

static Bool
drv_get_rec(ScrnInfoPtr pScrn)
{
    if (pScrn->driverPrivate)
	return TRUE;

    pScrn->driverPrivate = xnfcalloc(1, sizeof(modesettingRec));

    return TRUE;
}

static void
drv_free_rec(ScrnInfoPtr pScrn)
{
    if (!pScrn)
	return;

    if (!pScrn->driverPrivate)
	return;

    free(pScrn->driverPrivate);

    pScrn->driverPrivate = NULL;
}

static void
drv_probe_ddc(ScrnInfoPtr pScrn, int _index)
{
    ConfiguredMonitor = NULL;
}

static Bool
drv_crtc_resize(ScrnInfoPtr pScrn, int width, int height)
{
    modesettingPtr ms = modesettingPTR(pScrn);
    ScreenPtr pScreen = pScrn->pScreen;
    int old_width, old_height;
    PixmapPtr rootPixmap;

    if (width == pScrn->virtualX && height == pScrn->virtualY)
	return TRUE;

    if (ms->check_fb_size) {
	size_t size = width*(pScrn->bitsPerPixel / 8) * height + 1024;

	if (size > ms->max_fb_size) {
	    xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
		       "Requested framebuffer size %dx%dx%d will not fit "
		       "in display memory.\n",
		       width, height, pScrn->bitsPerPixel);
	    return FALSE;
	}
    }

    old_width = pScrn->virtualX;
    old_height = pScrn->virtualY;
    pScrn->virtualX = width;
    pScrn->virtualY = height;

    /* ms->create_front_buffer will remove the old front buffer */

    rootPixmap = pScreen->GetScreenPixmap(pScreen);
    vmwgfx_disable_scanout(pScrn);
    if (!pScreen->ModifyPixmapHeader(rootPixmap, width, height, -1, -1, -1, NULL))
	goto error_modify;

    pScrn->displayWidth = rootPixmap->devKind / (rootPixmap->drawable.bitsPerPixel / 8);

    xf86SetDesiredModes(pScrn);
    return TRUE;

    /*
     * FIXME: Try out this error recovery path and fix problems.

     */
    //error_create:
    if (!pScreen->ModifyPixmapHeader(rootPixmap, old_width, old_height, -1, -1, -1, NULL))
	FatalError("failed to resize rootPixmap error path\n");

    pScrn->displayWidth = rootPixmap->devKind /
	(rootPixmap->drawable.bitsPerPixel / 8);


error_modify:
    pScrn->virtualX = old_width;
    pScrn->virtualY = old_height;

    if (xf86SetDesiredModes(pScrn))
	return FALSE;

    FatalError("failed to setup old framebuffer\n");
    return FALSE;
}

static const xf86CrtcConfigFuncsRec crtc_config_funcs = {
    .resize = drv_crtc_resize
};

static Bool vmwgfx_use_server_fd(modesettingPtr ms)
{
#ifdef XF86_PDEV_SERVER_FD
    return ms->platform_dev && (ms->platform_dev->flags & XF86_PDEV_SERVER_FD);
#else
    return FALSE;
#endif
}

static Bool
drv_init_drm(ScrnInfoPtr pScrn)
{
    modesettingPtr ms = modesettingPTR(pScrn);

    /* deal with server regeneration */
    if (ms->fd < 0) {

	ms->fd = vmwgfx_hosted_drm_fd(ms->hdriver, ms->hosted, ms->PciInfo);

#ifdef ODEV_ATTRIB_FD
	if (ms->fd < 0 && vmwgfx_use_server_fd(ms))
	    ms->fd = xf86_get_platform_device_int_attrib(ms->platform_dev,
	                                                 ODEV_ATTRIB_FD, -1);
#endif

	if (ms->fd < 0) {

	    char bus_id[64];

	    snprintf(bus_id, sizeof(bus_id), "PCI:%d:%d:%d",
		     ((ms->PciInfo->domain << 8) | ms->PciInfo->bus),
		     ms->PciInfo->dev, ms->PciInfo->func
		);

	    ms->fd = drmOpen("vmwgfx", bus_id);
	    ms->isMaster = TRUE;

	}

	if (ms->fd >= 0) {
	    drmVersionPtr ver = drmGetVersion(ms->fd);

	    if (ver == NULL) {
		xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
			   "Could not determine DRM version.\n");
		return FALSE;
	    }

	    ms->drm_major = ver->version_major;
	    ms->drm_minor = ver->version_minor;
	    ms->drm_patch = ver->version_patchlevel;

	    drmFreeVersion(ver);
	    return TRUE;
	}

	xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
		   "Failed to open drm.\n");

	return FALSE;
    }

    return TRUE;
}

/**
 * vmwgfx_set_topology - Set the GUI topology according to an option string
 *
 * @pScrn: Pointer to a ScrnInfo struct.
 * @topology: String containing the topology description.
 * @info: Info describing the option used to invoke this function.
 *
 * This function reads a GUI topology according from @topology, and
 * calls into the kernel to set that topology.
 */
static Bool
vmwgfx_set_topology(ScrnInfoPtr pScrn, const char *topology, const char *info)
{
    modesettingPtr ms = modesettingPTR(pScrn);
    unsigned int num_outputs;
    xXineramaScreenInfo *screen_info;
    struct drm_vmw_rect *rects;
    int ret;
    unsigned int i;

    screen_info = VMWAREParseTopologyString(pScrn, topology, &num_outputs,
					    info);

    if (screen_info == NULL)
	return FALSE;

    rects = calloc(num_outputs, sizeof(*rects));
    if (rects == NULL) {
	xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
		   "Failed to allocate topology data.\n");
	goto out_no_rects;
    }

    for(i = 0; i < num_outputs; ++i) {
	rects[i].x = screen_info[i].x_org;
	rects[i].y = screen_info[i].y_org;
	rects[i].w = screen_info[i].width;
	rects[i].h = screen_info[i].height;
    }

    ret = vmwgfx_update_gui_layout(ms->fd, num_outputs, rects);
    free(rects);
    free(screen_info);

    return (ret == 0);

  out_no_rects:
    free(screen_info);
    return FALSE;
}


static Bool
vmwgfx_pre_init_mode(ScrnInfoPtr pScrn, int flags)
{
    modesettingPtr ms = modesettingPTR(pScrn);
    Bool ret = TRUE;

    ms->from_dp = (xf86GetOptValBool(ms->Options, OPTION_DIRECT_PRESENTS,
				     &ms->direct_presents)) ?
	X_CONFIG : X_DEFAULT;

    ms->from_hwp = (xf86GetOptValBool(ms->Options, OPTION_HW_PRESENTS,
				      &ms->only_hw_presents)) ?
	X_CONFIG : X_DEFAULT;

    /* Allocate an xf86CrtcConfig */
    xf86CrtcConfigInit(pScrn, &crtc_config_funcs);

    /* get max width and height */
    {
	drmModeResPtr res;
	int max_width, max_height;

	res = drmModeGetResources(ms->fd);
	max_width = res->max_width;
	max_height = res->max_height;

	xf86CrtcSetSizeRange(pScrn, res->min_width,
			     res->min_height, max_width, max_height);
	xf86DrvMsg(pScrn->scrnIndex, X_PROBED,
		   "Min width %d, Max Width %d.\n",
		   res->min_width, max_width);
	xf86DrvMsg(pScrn->scrnIndex, X_PROBED,
		   "Min height %d, Max Height %d.\n",
		   res->min_height, max_height);
	drmModeFreeResources(res);
    }

    ms->SWCursor = FALSE;
    if (!xf86ReturnOptValBool(ms->Options, OPTION_HW_CURSOR, TRUE)) {
	ms->SWCursor = TRUE;
    }

    if (xf86IsOptionSet(ms->Options, OPTION_GUI_LAYOUT)) {
	CONST_ABI_18_0 char *topology =
	    xf86GetOptValString(ms->Options, OPTION_GUI_LAYOUT);

	ret = FALSE;
	if (topology) {
	    ret = vmwgfx_set_topology(pScrn, topology, "gui");
	    free((void *)topology);
	}

    } else if (xf86IsOptionSet(ms->Options, OPTION_STATIC_XINERAMA)) {
	CONST_ABI_18_0 char *topology =
	    xf86GetOptValString(ms->Options, OPTION_STATIC_XINERAMA);

	ret = FALSE;
	if (topology) {
	    ret = vmwgfx_set_topology(pScrn, topology, "static Xinerama");
	    free((void *)topology);
	}
    }

    if (!ret)
	xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Falied parsing or setting "
		   "gui topology from config file.\n");

    xorg_crtc_init(pScrn);
    xorg_output_init(pScrn);

    if (!xf86InitialConfiguration(pScrn, TRUE)) {
	xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "No valid modes.\n");
	goto out_modes;
    }

    if (pScrn->modes == NULL) {
	xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "No available modes.\n");
	goto out_modes;
    }

    pScrn->currentMode = pScrn->modes;

    return TRUE;

  out_modes:
    return FALSE;
}

static Bool
drv_pre_init(ScrnInfoPtr pScrn, int flags)
{
    modesettingPtr ms;
    rgb defaultWeight = { 0, 0, 0 };
    Gamma zeros = { 0.0, 0.0, 0.0 };
    EntityInfoPtr pEnt;
    uint64_t cap;

    if (pScrn->numEntities != 1)
	return FALSE;

    pEnt = xf86GetEntityInfo(pScrn->entityList[0]);

    if (flags & PROBE_DETECT) {
	drv_probe_ddc(pScrn, pEnt->index);
	return TRUE;
    }

    pScrn->driverPrivate = NULL;

    /* Allocate driverPrivate */
    if (!drv_get_rec(pScrn)) {
	xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
		   "Failed to allocate driver private.\n");
    }

    ms = modesettingPTR(pScrn);
    ms->pEnt = pEnt;

    pScrn->displayWidth = 640;	       /* default it */

    ms->PciInfo = xf86GetPciInfoForEntity(ms->pEnt->index);
    if (!ms->PciInfo) {
	xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
		   "Incorrect bus for device.\n");
	goto out_err_bus;
    }

#ifdef XSERVER_PLATFORM_BUS
    if (pEnt->location.type == BUS_PLATFORM)
        ms->platform_dev = pEnt->location.id.plat;
#endif

    xf86SetPrimInitDone(pScrn->entityList[0]);

    ms->hdriver = vmwgfx_hosted_detect();
    ms->hosted = vmwgfx_hosted_create(ms->hdriver, pScrn);
    if (ms->hdriver && !ms->hosted) {
	xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
		   "Failed to set up compositor hosted environment.\n");
	goto out_err_bus;
    }

    pScrn->monitor = pScrn->confScreen->monitor;
    pScrn->progClock = TRUE;
    pScrn->rgbBits = 8;

    if (!xf86SetDepthBpp
	(pScrn, 0, 0, 0,
	 PreferConvert24to32 | SupportConvert24to32 | Support32bppFb)) {
	xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Failed to set depth and bpp.\n");
	goto out_err_bus;
    }

    if (!vmwgfx_hosted_pre_init(ms->hdriver, ms->hosted, flags))
	goto out_err_bus;

    ms->fd = -1;
    if (!drv_init_drm(pScrn))
	goto out_no_drm;

    if (ms->drm_major != DRM_VERSION_MAJOR_REQUIRED ||
	ms->drm_minor < DRM_VERSION_MINOR_REQUIRED) {
	xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
		   "DRM driver version is %d.%d.%d\n",
		   ms->drm_major, ms->drm_minor, ms->drm_patch);
	xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
		   "But KMS- and 3D functionality needs at least "
		   "%d.%d.0 to work.\n",
		   DRM_VERSION_MAJOR_REQUIRED,
		   DRM_VERSION_MINOR_REQUIRED);
	goto out_drm_version;
    } else {
	xf86DrvMsg(pScrn->scrnIndex, X_PROBED,
		   "DRM driver version is %d.%d.%d\n",
		   ms->drm_major, ms->drm_minor, ms->drm_patch);
    }

    ms->has_screen_targets = ms->drm_major > 2 ||
	(ms->drm_major == 2 && ms->drm_minor >= 7);
    ms->has_screen_targets = (ms->has_screen_targets &&
			      !vmwgfx_get_param(ms->fd,
						DRM_VMW_PARAM_SCREEN_TARGET,
						&cap) &&
			      cap != 0);

    ms->check_fb_size = (vmwgfx_max_fb_size(ms->fd, &ms->max_fb_size) == 0);

    switch (pScrn->depth) {
    case 15:
    case 16:
    case 24:
	break;
    default:
	xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
		   "Given depth (%d) is not supported with KMS enabled.\n",
		   pScrn->depth);
	goto out_depth;
    }
    xf86PrintDepthBpp(pScrn);

    if (!xf86SetWeight(pScrn, defaultWeight, defaultWeight))
	goto out_depth;
    if (!xf86SetDefaultVisual(pScrn, -1))
	goto out_depth;

    /* Process the options */
    xf86CollectOptions(pScrn, NULL);
    if (!(ms->Options = VMWARECopyOptions()))
	goto out_depth;
    xf86ProcessOptions(pScrn->scrnIndex, pScrn->options, ms->Options);

    ms->accelerate_render = TRUE;
    ms->from_render = xf86GetOptValBool(ms->Options, OPTION_RENDER_ACCEL,
					&ms->accelerate_render) ?
	X_CONFIG : X_PROBED;

    ms->rendercheck = FALSE;
    ms->from_rendercheck = xf86GetOptValBool(ms->Options, OPTION_RENDERCHECK,
					     &ms->rendercheck) ?
	X_CONFIG : X_DEFAULT;

    ms->enable_dri = ms->accelerate_render;
    ms->from_dri = xf86GetOptValBool(ms->Options, OPTION_DRI,
				     &ms->enable_dri) ?
	X_CONFIG : X_PROBED;

    ms->direct_presents = FALSE;
    ms->only_hw_presents = FALSE;
    ms->SWCursor = TRUE;
    if (!vmwgfx_is_hosted(ms->hdriver)) {
	if (!vmwgfx_pre_init_mode(pScrn, flags))
	    goto out_modes;
    } else {
	ms->from_dp = X_CONFIG;
	ms->from_hwp = X_CONFIG;
    }

    xf86SetDpi(pScrn, 0, 0);

    if (!xf86SetGamma(pScrn, zeros)) {
	xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Failed to set gamma.\n");
	goto out_modes;
    }

    /* Load the required sub modules */
    if (!xf86LoadSubModule(pScrn, "fb")) {
	xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Failed to load fb module.\n");
	goto out_modes;
    }

    if (!xf86LoadSubModule(pScrn, "dri2")) {
	xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Failed to load dri2 module.\n");
	goto out_modes;
    }

#ifdef DRI3
    if (!xf86LoadSubModule(pScrn, "dri3")) {
	xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Failed to load dri3 module.\n");
	goto out_modes;
    }
#endif

    return TRUE;

  out_modes:
    free(ms->Options);
  out_depth:
  out_drm_version:
    if (!vmwgfx_is_hosted(ms->hdriver) && !vmwgfx_use_server_fd(ms))
	close(ms->fd);
  out_no_drm:
    vmwgfx_hosted_destroy(ms->hdriver, ms->hosted);
  out_err_bus:
    drv_free_rec(pScrn);
    return FALSE;

}

static Bool
vmwgfx_scanout_update(int drm_fd, int fb_id, RegionPtr dirty)
{
    BoxPtr clips = REGION_RECTS(dirty);
    unsigned int num_clips = REGION_NUM_RECTS(dirty);
    unsigned int alloc_clips = min(num_clips, DRM_MODE_FB_DIRTY_MAX_CLIPS);
    drmModeClip *rects, *r;
    int i, ret;

    if (num_clips == 0)
	return TRUE;

    rects = malloc(alloc_clips * sizeof(*rects));
    if (!rects) {
	LogMessage(X_ERROR, "Failed to alloc cliprects for scanout update.\n");
	return FALSE;
    }

    while (num_clips > 0) {
	unsigned int cur_clips = min(num_clips, DRM_MODE_FB_DIRTY_MAX_CLIPS);

	memset(rects, 0, alloc_clips * sizeof(*rects));

	for (i = 0, r = rects; i < cur_clips; ++i, ++r, ++clips) {
	    r->x1 = clips->x1;
	    r->y1 = clips->y1;
	    r->x2 = clips->x2;
	    r->y2 = clips->y2;
	}

	ret = drmModeDirtyFB(drm_fd, fb_id, rects, cur_clips);
	if (ret) {
	    LogMessage(X_ERROR, "%s: failed to send dirty (%i, %s)\n",
		       __func__, ret, strerror(-ret));
	    return FALSE;
	}

	num_clips -= cur_clips;
    }

    free(rects);

    return TRUE;
}

static Bool
vmwgfx_scanout_present(ScreenPtr pScreen, int drm_fd,
		       struct vmwgfx_saa_pixmap *vpix,
		       RegionPtr dirty)
{
    uint32_t handle;
    unsigned int dummy;

    if (!REGION_NOTEMPTY(pScreen, dirty))
	return TRUE;

    if (!vpix->hw) {
	LogMessage(X_ERROR, "No surface to present from.\n");
	return FALSE;
    }

    if (_xa_surface_handle(vpix->hw, &handle, &dummy) != 0) {
	LogMessage(X_ERROR, "Could not get present surface handle.\n");
	return FALSE;
    }

    if (vmwgfx_present(drm_fd, vpix->fb_id, 0, 0, dirty, handle) != 0) {
	LogMessage(X_ERROR, "Failed present kernel call.\n");
	return FALSE;
    }

    return TRUE;
}

void xorg_flush(ScreenPtr pScreen)
{
    ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
    modesettingPtr ms = modesettingPTR(pScrn);
    xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(pScrn);
    PixmapPtr pixmap = NULL;
    struct vmwgfx_saa_pixmap *vpix;
    int i;
    xf86CrtcPtr crtc;
    PixmapPtr *pixmaps = calloc(config->num_crtc, sizeof(*pixmaps));
    unsigned int num_scanout = 0;
    unsigned int j;

    if (!pixmaps) {
	LogMessage(X_ERROR, "Failed memory allocation during screen "
		   "update.\n");
	return;
    }

    /*
     * Get an array of pixmaps from which we scan out.
     */
    for (i=0; i<config->num_crtc; ++i) {
	crtc = config->crtc[i];
	if (crtc->enabled) {
	    pixmap = crtc_get_scanout(crtc);
	    if (pixmap) {

		/*
		 * Remove duplicates.
		 */
		for (j=0; j<num_scanout; ++j) {
		    if (pixmap == pixmaps[j])
			break;
		}

		if (j == num_scanout)
		    pixmaps[num_scanout++] = pixmap;
	    }
	}
    }

    if (!num_scanout)
	return;

    for (j=0; j<num_scanout; ++j) {
	pixmap = pixmaps[j];
	vpix = vmwgfx_saa_pixmap(pixmap);

	if (vpix->fb_id != -1) {
	    if (vpix->pending_update) {
		if (vpix->scanout_hw &&
		    REGION_NOTEMPTY(pscreen, vpix->pending_update)) {
		    (void) vmwgfx_hw_accel_validate(pixmap, 0, XA_FLAG_SCANOUT,
						    0, NULL);
		    REGION_UNION(pScreen, vpix->pending_present,
				 vpix->pending_present, vpix->pending_update);
		} else
		    (void) vmwgfx_scanout_update(ms->fd, vpix->fb_id,
						 vpix->pending_update);
		REGION_EMPTY(pScreen, vpix->pending_update);
	    }
	    if (vpix->pending_present) {
		if (vpix->scanout_hw)
		    (void) vmwgfx_scanout_update(ms->fd, vpix->fb_id,
						 vpix->pending_present);
		else
		    (void) vmwgfx_scanout_present(pScreen, ms->fd, vpix,
						  vpix->pending_present);
		REGION_EMPTY(pScreen, vpix->pending_present);
	    }
	}
    }
    free(pixmaps);
}

static void drv_block_handler(BLOCKHANDLER_ARGS_DECL)
{
    SCREEN_PTR(arg);
    modesettingPtr ms = modesettingPTR(xf86ScreenToScrn(pScreen));

    vmwgfx_swap(ms, pScreen, BlockHandler);
    pScreen->BlockHandler(BLOCKHANDLER_ARGS);
    vmwgfx_swap(ms, pScreen, BlockHandler);

    if (vmwgfx_is_hosted(ms->hdriver))
	vmwgfx_hosted_post_damage(ms->hdriver, ms->hosted);
    else
	xorg_flush(pScreen);
}

static Bool
drv_create_screen_resources(ScreenPtr pScreen)
{
    ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
    modesettingPtr ms = modesettingPTR(pScrn);
    Bool ret;

    vmwgfx_swap(ms, pScreen, CreateScreenResources);
    ret = pScreen->CreateScreenResources(pScreen);
    vmwgfx_swap(ms, pScreen, CreateScreenResources);
    if (!ret)
	return ret;

    drv_adjust_frame(ADJUST_FRAME_ARGS(pScrn, pScrn->frameX0, pScrn->frameY0));
    vmwgfx_uevent_init(pScrn, ms);

    return drv_enter_vt(VT_FUNC_ARGS);
}

static Bool
drv_set_master(ScrnInfoPtr pScrn)
{
    modesettingPtr ms = modesettingPTR(pScrn);

    if (!vmwgfx_is_hosted(ms->hdriver) && !vmwgfx_use_server_fd(ms) &&
            !ms->isMaster && drmSetMaster(ms->fd) != 0) {
	if (errno == EINVAL) {
	    xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
		       "drmSetMaster failed: 2.6.29 or newer kernel required for "
		       "multi-server DRI\n");
	} else {
	    xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
		       "drmSetMaster failed: %s\n", strerror(errno));
	}
	return FALSE;
    }

    ms->isMaster = TRUE;
    return TRUE;
}

/**
 * vmwgfx_use_hw_cursor_argb - wrapper around hw argb cursor check.
 *
 * screen: Pointer to the current screen metadata.
 * cursor: Pointer to the current cursor metadata.
 *
 * In addition to the default test, also check whether we might be
 * needing more than one hw cursor (which we don't support).
 */
static Bool
vmwgfx_use_hw_cursor_argb(ScreenPtr screen, CursorPtr cursor)
{
    ScrnInfoPtr pScrn = xf86ScreenToScrn(screen);
    xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
    xf86CursorInfoPtr cursor_info = xf86_config->cursor_info;
    modesettingPtr ms = modesettingPTR(pScrn);
    Bool ret;

    vmwgfx_swap(ms, cursor_info, UseHWCursorARGB);
    ret = cursor_info->UseHWCursorARGB(screen, cursor);
    vmwgfx_swap(ms, cursor_info, UseHWCursorARGB);
    if (!ret)
	return FALSE;

    /*
     * If there is a chance we might need two cursors,
     * revert to sw cursor.
     */
    return !vmwgfx_output_explicit_overlap(pScrn);
}

/**
 * vmwgfx_use_hw_cursor - wrapper around hw cursor check.
 *
 * screen: Pointer to the current screen metadata.
 * cursor: Pointer to the current cursor metadata.
 *
 * In addition to the default test, also check whether we might be
 * needing more than one hw cursor (which we don't support).
 */
static Bool
vmwgfx_use_hw_cursor(ScreenPtr screen, CursorPtr cursor)
{
    ScrnInfoPtr pScrn = xf86ScreenToScrn(screen);
    xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
    xf86CursorInfoPtr cursor_info = xf86_config->cursor_info;
    modesettingPtr ms = modesettingPTR(pScrn);
    Bool ret;

    vmwgfx_swap(ms, cursor_info, UseHWCursor);
    ret = cursor_info->UseHWCursor(screen, cursor);
    vmwgfx_swap(ms, cursor_info, UseHWCursor);
    if (!ret)
	return FALSE;

    /*
     * If there is a chance we might need two simultaneous cursors,
     * revert to sw cursor.
     */
    return !vmwgfx_output_explicit_overlap(pScrn);
}

/**
 * vmwgfx_wrap_use_hw_cursor - Wrap functions that check for hw cursor
 * support.
 *
 * pScrn: Pointer to current screen info.
 *
 * Enables the device-specific hw cursor support check functions.
 */
static void vmwgfx_wrap_use_hw_cursor(ScrnInfoPtr pScrn)
{
    xf86CrtcConfigPtr   xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
    xf86CursorInfoPtr	cursor_info = xf86_config->cursor_info;
    modesettingPtr ms = modesettingPTR(pScrn);

    vmwgfx_wrap(ms, cursor_info, UseHWCursor, vmwgfx_use_hw_cursor);
    vmwgfx_wrap(ms, cursor_info, UseHWCursorARGB, vmwgfx_use_hw_cursor_argb);
}


static void drv_load_palette(ScrnInfoPtr pScrn, int numColors,
			     int *indices, LOCO *colors, VisualPtr pVisual)
{
    xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
    modesettingPtr ms = modesettingPTR(pScrn);
    int _index, j, i;
    int c;

    switch(pScrn->depth) {
    case 15:
	for (i = 0; i < numColors; i++) {
	    _index = indices[i];
	    for (j = 0; j < 8; j++) {
		ms->lut_r[_index * 8 + j] = colors[_index].red << 8;
		ms->lut_g[_index * 8 + j] = colors[_index].green << 8;
		ms->lut_b[_index * 8 + j] = colors[_index].blue << 8;
	    }
	}
	break;
    case 16:
	for (i = 0; i < numColors; i++) {
	    _index = indices[i];

	    if (_index < 32) {
		for (j = 0; j < 8; j++) {
		    ms->lut_r[_index * 8 + j] = colors[_index].red << 8;
		    ms->lut_b[_index * 8 + j] = colors[_index].blue << 8;
		}
	    }

	    for (j = 0; j < 4; j++) {
		ms->lut_g[_index * 4 + j] = colors[_index].green << 8;
	    }
	}
	break;
    default:
	for (i = 0; i < numColors; i++) {
	    _index = indices[i];
	    ms->lut_r[_index] = colors[_index].red << 8;
	    ms->lut_g[_index] = colors[_index].green << 8;
	    ms->lut_b[_index] = colors[_index].blue << 8;
	}
	break;
    }

    for (c = 0; c < xf86_config->num_crtc; c++) {
	xf86CrtcPtr crtc = xf86_config->crtc[c];

	/* Make the change through RandR */
#ifdef RANDR_12_INTERFACE
	if (crtc->randr_crtc)
	    RRCrtcGammaSet(crtc->randr_crtc, ms->lut_r, ms->lut_g, ms->lut_b);
	else
#endif
	    crtc->funcs->gamma_set(crtc, ms->lut_r, ms->lut_g, ms->lut_b, 256);
    }
}


static Bool
drv_screen_init(SCREEN_INIT_ARGS_DECL)
{
    ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
    modesettingPtr ms = modesettingPTR(pScrn);
    VisualPtr visual;

    if (!drv_set_master(pScrn))
	return FALSE;

    pScrn->pScreen = pScreen;

    /* HW dependent - FIXME */
    pScrn->displayWidth = pScrn->virtualX;

    miClearVisualTypes();

    if (!miSetVisualTypes(pScrn->depth,
			  miGetDefaultVisualMask(pScrn->depth),
			  pScrn->rgbBits, pScrn->defaultVisual))
	return FALSE;

    if (!miSetPixmapDepths())
	return FALSE;

    pScrn->memPhysBase = 0;
    pScrn->fbOffset = 0;

    if (!fbScreenInit(pScreen, NULL,
		      pScrn->virtualX, pScrn->virtualY,
		      pScrn->xDpi, pScrn->yDpi,
		      pScrn->displayWidth, pScrn->bitsPerPixel))
	return FALSE;

    if (pScrn->bitsPerPixel > 8) {
	/* Fixup RGB ordering */
	visual = pScreen->visuals + pScreen->numVisuals;
	while (--visual >= pScreen->visuals) {
	    if ((visual->class | DynamicClass) == DirectColor) {
		visual->offsetRed = pScrn->offset.red;
		visual->offsetGreen = pScrn->offset.green;
		visual->offsetBlue = pScrn->offset.blue;
		visual->redMask = pScrn->mask.red;
		visual->greenMask = pScrn->mask.green;
		visual->blueMask = pScrn->mask.blue;
	    }
	}
    }

    fbPictureInit(pScreen, NULL, 0);

    vmwgfx_wrap(ms, pScreen, BlockHandler, drv_block_handler);
    vmwgfx_wrap(ms, pScreen, CreateScreenResources,
		drv_create_screen_resources);

    xf86SetBlackWhitePixels(pScreen);

    ms->autoLayout = TRUE;
    vmw_ctrl_ext_init(pScrn);

    if (ms->accelerate_render) {
	/*
	 * Some versions of the Gallium loader close our drm file
	 * descriptor if xa_tracker_create() fails (typically 2D VMs.)
	 * While this is mostly fixed everywhere we implement a
	 * workaround to avoid tracking down the same bug again and again
	 * on those setups where this is not fixed in mesa.
	 */

	int tmp_fd = dup(ms->fd);
	long flags = fcntl(ms->fd, F_GETFD);

	ms->xat = xa_tracker_create(ms->fd);
	if (fcntl(ms->fd, F_GETFD) == -1) {
	    if (tmp_fd == -1 || flags == -1 || fcntl(tmp_fd, F_SETFD, flags)) {
		xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
			   "XA closed our DRM file descriptor. Giving up.\n");
		return FALSE;
	    }
	    ms->fd = tmp_fd;
	} else {
	    close(tmp_fd);
	}
	    
	if (!ms->xat) {
	    xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
		       "Failed to initialize Gallium3D Xa. "
                       "No render acceleration available.\n");
	    ms->from_render = X_PROBED;
	} else {
	    int major, minor, patch;

	    xa_tracker_version(&major, &minor, &patch);
	    xf86DrvMsg(pScrn->scrnIndex, X_INFO,
		       "Gallium3D XA version: %d.%d.%d.\n",
		       major, minor, patch);

	    if (major < XA_VERSION_MAJOR_REQUIRED ||
		major > XA_VERSION_MAJOR_COMPAT ||
		(major == XA_VERSION_MAJOR_REQUIRED &&
		 minor < XA_VERSION_MINOR_REQUIRED)) {
		xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
			   "Expecting %d.%d.x >= XA version < %d.0.0.\n",
			   XA_VERSION_MAJOR_REQUIRED,
			   XA_VERSION_MINOR_REQUIRED,
			   XA_VERSION_MAJOR_COMPAT + 1);
		xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
			   "No render acceleration available.\n");
		xa_tracker_destroy(ms->xat);
		ms->xat = NULL;
		ms->from_render = X_PROBED;
	    }
#ifdef DRI3
	    if (major == VMW_XA_VERSION_MAJOR_DRI3 &&
		minor >= VMW_XA_VERSION_MINOR_DRI3) {
		ms->xa_dri3 = TRUE;
	    } else {
		ms->xa_dri3 = FALSE;
		LogMessage(X_WARNING,
			   "Gallium3D XA version insufficient for dri3.\n");
	    }
#endif
	}
	if (ms->xat == NULL && ms->rendercheck) {
	    xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
		       "Turning off renercheck mode.\n");
	    ms->rendercheck = FALSE;
	    ms->from_rendercheck = X_PROBED;
	}
    }

    if (vmwgfx_is_hosted(ms->hdriver) && !ms->xat) {
	xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
		   "Can't run hosted without XA. Giving up.\n");
	return FALSE;
    }

    if (!vmwgfx_saa_init(pScreen, ms->fd, ms->xat, &xorg_flush,
			 ms->direct_presents,
			 ms->only_hw_presents,
			 ms->rendercheck,
			 ms->has_screen_targets)) {
	FatalError("Failed to initialize SAA.\n");
    }

    ms->dri2_available = FALSE;
#ifdef DRI3
    ms->dri3_available = FALSE;
#endif
    if (ms->enable_dri) {
	if (ms->xat) {
	    ms->dri2_available = xorg_dri2_init(pScreen);
	    if (!ms->dri2_available)
		xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
			   "Failed to initialize direct rendering DRI2.\n");
#ifdef DRI3
	    if (ms->xa_dri3) {
	        ms->dri3_available = vmwgfx_dri3_init(pScreen);
		if (!ms->dri3_available)
		    xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
			       "Failed to initialize direct rendering DRI3.\n");
	    }
#endif /* DRI3 */
	} else {
	    xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
		       "Skipped initialization of direct rendering due "
		       "to lack of render acceleration.\n");
	    ms->from_dri = X_PROBED;
	}
    }

    xf86DrvMsg(pScrn->scrnIndex, ms->from_render, "Render acceleration is %s.\n",
	       (ms->xat != NULL) ? "enabled" : "disabled");

    xf86DrvMsg(pScrn->scrnIndex, ms->from_rendercheck,
	       "Rendercheck mode is %s.\n",
	       (ms->rendercheck) ? "enabled" : "disabled");

    xf86DrvMsg(pScrn->scrnIndex, ms->from_dri,
	       "Direct rendering (DRI2 3D) is %s.\n",
	       (ms->dri2_available) ? "enabled" : "disabled");
#ifdef DRI3
    xf86DrvMsg(pScrn->scrnIndex, ms->from_dri,
	       "Direct rendering (DRI3 3D) is %s.\n",
	       (ms->dri3_available) ? "enabled" : "disabled");
#endif
    if (ms->xat != NULL) {
	xf86DrvMsg(pScrn->scrnIndex, ms->from_dp, "Direct presents are %s.\n",
		   (ms->direct_presents) ? "enabled" : "disabled");
	if (ms->only_hw_presents)
	    xf86DrvMsg(pScrn->scrnIndex, ms->from_hwp, "Hardware only presents "
		       "are enabled.\n");
	else
	    xf86DrvMsg(pScrn->scrnIndex, ms->from_hwp, "Hardware only presents "
		       "are %s.\n",
		       (ms->has_screen_targets) ? "automatic per scanout" :
		       "disabled");
    }

    xf86SetBackingStore(pScreen);
    xf86SetSilkenMouse(pScreen);
    miDCInitialize(pScreen, xf86GetPointerScreenFuncs());

    if (!vmwgfx_hosted_screen_init(ms->hdriver, ms->hosted, pScreen)) {
	xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
		   "Failed hosted Screen init. Giving up.\n");
	return FALSE;
    }

    /* Need to extend HWcursor support to handle mask interleave */
    if (!ms->SWCursor) {
	xf86_cursors_init(pScreen, 64, 64,
			  HARDWARE_CURSOR_SOURCE_MASK_INTERLEAVE_64 |
			  HARDWARE_CURSOR_ARGB |
			  HARDWARE_CURSOR_UPDATE_UNHIDDEN);
	vmwgfx_wrap_use_hw_cursor(pScrn);
    }

    /* Must force it before EnterVT, so we are in control of VT and
     * later memory should be bound when allocating, e.g rotate_mem */
    pScrn->vtSema = TRUE;

    pScreen->SaveScreen = xf86SaveScreen;
    vmwgfx_wrap(ms, pScreen, CloseScreen, drv_close_screen);

    if (!xf86CrtcScreenInit(pScreen))
	return FALSE;

    if (!miCreateDefColormap(pScreen))
	return FALSE;
    if (!xf86HandleColormaps(pScreen, 256, 8, drv_load_palette, NULL,
			     CMAP_PALETTED_TRUECOLOR |
			     CMAP_RELOAD_ON_MODE_SWITCH))
	return FALSE;

    xf86DPMSInit(pScreen, xf86DPMSSet, 0);

    if (serverGeneration == 1)
	xf86ShowUnusedOptions(pScrn->scrnIndex, pScrn->options);


    vmwgfx_wrap(ms, pScrn, EnterVT, drv_enter_vt);
    vmwgfx_wrap(ms, pScrn, LeaveVT, drv_leave_vt);
    vmwgfx_wrap(ms, pScrn, AdjustFrame, drv_adjust_frame);

    /*
     * Must be called _after_ function wrapping.
     */
    xorg_xv_init(pScreen);

    return TRUE;
}

static void
drv_adjust_frame(ADJUST_FRAME_ARGS_DECL)
{
    SCRN_INFO_PTR(arg);
    modesettingPtr ms = modesettingPTR(pScrn);
    xf86CrtcConfigPtr config;
    xf86OutputPtr output;
    xf86CrtcPtr crtc;

    if (vmwgfx_is_hosted(ms->hdriver))
	return;

    config = XF86_CRTC_CONFIG_PTR(pScrn);
    output = config->output[config->compat_output];
    crtc = output->crtc;

    if (crtc && crtc->enabled) {
      //	crtc->funcs->set_mode_major(crtc, pScrn->currentMode,
      //				    RR_Rotate_0, x, y);
	crtc->x = output->initial_x + x;
	crtc->y = output->initial_y + y;
    }
}

static void
drv_free_screen(FREE_SCREEN_ARGS_DECL)
{
    SCRN_INFO_PTR(arg);
    modesettingPtr ms = modesettingPTR(pScrn);

    vmwgfx_hosted_destroy(ms->hdriver, ms->hosted);
    drv_free_rec(pScrn);
}

static void
drv_leave_vt(VT_FUNC_ARGS_DECL)
{
    SCRN_INFO_PTR(arg);
    modesettingPtr ms = modesettingPTR(pScrn);

    if (!vmwgfx_is_hosted(ms->hdriver)) {
	vmwgfx_cursor_bypass(ms->fd, 0, 0);
	vmwgfx_disable_scanout(pScrn);
    }

    vmwgfx_saa_drop_master(pScrn->pScreen);

    if (!vmwgfx_is_hosted(ms->hdriver) && !vmwgfx_use_server_fd(ms) &&
            drmDropMaster(ms->fd))
	xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
		   "drmDropMaster failed: %s\n", strerror(errno));
    ms->isMaster = FALSE;
    pScrn->vtSema = FALSE;
}

/*
 * This gets called when gaining control of the VT, and from ScreenInit().
 */
static Bool
drv_enter_vt(VT_FUNC_ARGS_DECL)
{
    SCRN_INFO_PTR(arg);
    modesettingPtr ms = modesettingPTR(pScrn);

    if (!drv_set_master(pScrn))
	return FALSE;

    vmwgfx_saa_set_master(pScrn->pScreen);

    if (!vmwgfx_is_hosted(ms->hdriver) && !xf86SetDesiredModes(pScrn))
	return FALSE;

    return TRUE;
}

static Bool
drv_switch_mode(SWITCH_MODE_ARGS_DECL)
{
    SCRN_INFO_PTR(arg);

    return xf86SetSingleMode(pScrn, mode, RR_Rotate_0);
}

static Bool
drv_close_screen(CLOSE_SCREEN_ARGS_DECL)
{
    ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
    modesettingPtr ms = modesettingPTR(pScrn);
    Bool ret;

    if (ms->cursor) {
       FreeCursor(ms->cursor, None);
       ms->cursor = NULL;
    }

    if (ms->dri2_available)
	xorg_dri2_close(pScreen);

    if (pScrn->vtSema)
        pScrn->LeaveVT(VT_FUNC_ARGS);

    vmwgfx_uevent_fini(pScrn, ms);
    vmw_xv_close(pScreen);

    pScrn->vtSema = FALSE;

    vmwgfx_unwrap(ms, pScrn, EnterVT);
    vmwgfx_unwrap(ms, pScrn, LeaveVT);
    vmwgfx_unwrap(ms, pScrn, AdjustFrame);
    vmwgfx_unwrap(ms, pScreen, CloseScreen);
    vmwgfx_hosted_screen_close(ms->hdriver, ms->hosted);
    vmwgfx_unwrap(ms, pScreen, BlockHandler);
    vmwgfx_unwrap(ms, pScreen, CreateScreenResources);

    ret = (*pScreen->CloseScreen) (CLOSE_SCREEN_ARGS);
    
    if (ms->xat)
	xa_tracker_destroy(ms->xat);

    return ret;
}

static ModeStatus
drv_valid_mode(SCRN_ARG_TYPE arg, DisplayModePtr mode, Bool verbose, int flags)
{
    return MODE_OK;
}

/* vim: set sw=4 ts=8 sts=4: */
0707010000003E000081A400000000000000000000000161A68E120000199A000000000000000000000000000000000000003300000000xf86-video-vmware-13.3.0+12/vmwgfx/vmwgfx_driver.h/*
 * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas.
 * 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 n<otice 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: Alan Hourihane <alanh@tungstengraphics.com>
 * Author: Jakob Bornecrantz <wallbraker@gmail.com>
 * Author: Thomas Hellstrom <thellstrom@vmware.com>
 */

#ifndef _VMWGFX_DRIVER_H_
#define _VMWGFX_DRIVER_H_


#include <stddef.h>
#include <stdint.h>
#include <errno.h>
#include <xorg-server.h>
#include <xf86.h>
#include <xf86Crtc.h>
#include <xf86xv.h>
#include <xa_tracker.h>
#include <xf86Module.h>
#include <drm.h>
#include <xf86drm.h>
#include <xf86drmMode.h>

#include "../src/compat-api.h"
#ifdef DRI2
#include <dri2.h>
#if (!defined(DRI2INFOREC_VERSION) || (DRI2INFOREC_VERSION < 3))
#undef DRI2
#endif
#endif

#ifdef HAVE_LIBUDEV
#include <libudev.h>
#endif

#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

#define DRV_ERROR(msg)	xf86DrvMsg(pScrn->scrnIndex, X_ERROR, msg);
#define debug_printf(...)

#define VMWGFX_DRI_DEVICE_LEN 80

#undef VMWGFX_LIBDRM_DEVICENAME
#if defined(HAVE_LIBDRM_2_4_96) || \
  (defined(HAVE_LIBDRM_2_4_74) && !defined(__linux__))
#define VMWGFX_LIBDRM_DEVICENAME
#endif

typedef struct
{
    int lastInstance;
    int refCount;
    ScrnInfoPtr pScrn_1;
    ScrnInfoPtr pScrn_2;
} EntRec, *EntPtr;

#define XORG_NR_FENCES 3

enum xorg_throttling_reason {
    THROTTLE_RENDER,
    THROTTLE_SWAP
};

struct vmwgfx_hosted;
struct xf86_platform_device;
struct vmwgfx_layout;

typedef struct _modesettingRec
{
    /* drm */
    int fd;
    int drm_major;
    int drm_minor;
    int drm_patch;

    /* X */
    EntPtr entityPrivate;

    int Chipset;
    EntityInfoPtr pEnt;
    struct pci_device *PciInfo;
    struct xf86_platform_device *platform_dev;

    /* Accel */
    Bool accelerate_render;
    MessageType from_render;
    Bool rendercheck;
    MessageType from_rendercheck;
    Bool SWCursor;
    CursorPtr cursor;
    Bool enable_dri;
    MessageType from_dri;
    Bool direct_presents;
    MessageType from_dp;
    Bool only_hw_presents;
    MessageType from_hwp;
    Bool isMaster;
    Bool has_screen_targets;


    /* Broken-out options. */
    OptionInfoPtr Options;

    ScreenBlockHandlerProcPtr saved_BlockHandler;
    CreateScreenResourcesProcPtr saved_CreateScreenResources;
    CloseScreenProcPtr saved_CloseScreen;
    Bool (*saved_EnterVT)(VT_FUNC_ARGS_DECL);
    void (*saved_LeaveVT)(VT_FUNC_ARGS_DECL);
    void (*saved_AdjustFrame)(ADJUST_FRAME_ARGS_DECL);
    Bool (*saved_UseHWCursor)(ScreenPtr, CursorPtr);
    Bool (*saved_UseHWCursorARGB)(ScreenPtr, CursorPtr);

    uint16_t lut_r[256], lut_g[256], lut_b[256];

    Bool check_fb_size;
    size_t max_fb_size;

    struct xa_tracker *xat;
    const struct vmwgfx_hosted_driver *hdriver;
    struct vmwgfx_hosted *hosted;
#ifdef DRI2
    Bool dri2_available;
#ifdef VMWGFX_LIBDRM_DEVICENAME
    char *dri2_device_name;
#else
    char dri2_device_name[VMWGFX_DRI_DEVICE_LEN];
#endif
#endif
#ifdef HAVE_LIBUDEV
    struct udev_monitor *uevent_monitor;
    InputHandlerProc uevent_handler;
    struct vmwgfx_layout *layout;
#endif
    Bool autoLayout;
#ifdef DRI3
    Bool xa_dri3;
    Bool dri3_available;
#endif

    /* Video */
    XF86VideoAdaptorPtr overlay;
    XF86VideoAdaptorPtr textured;

} modesettingRec, *modesettingPtr;

#define modesettingPTR(p) ((modesettingPtr)((p)->driverPrivate))

void xorg_flush(ScreenPtr pScreen);
/***********************************************************************
 * xorg_dri2.c
 */
Bool
xorg_dri2_init(ScreenPtr pScreen);

void
xorg_dri2_close(ScreenPtr pScreen);


/***********************************************************************
 * xorg_crtc.c
 */
void
xorg_crtc_init(ScrnInfoPtr pScrn);

void
xorg_crtc_cursor_destroy(xf86CrtcPtr crtc);

void
vmwgfx_disable_scanout(ScrnInfoPtr pScrn);

PixmapPtr
crtc_get_scanout(xf86CrtcPtr crtc);


/***********************************************************************
 * xorg_output.c
 */
void
xorg_output_init(ScrnInfoPtr pScrn);

unsigned
xorg_output_get_id(xf86OutputPtr output);

Bool
vmwgfx_output_explicit_overlap(ScrnInfoPtr pScrn);
void
vmwgfx_uevent_init(ScrnInfoPtr scrn, modesettingPtr ms);
void
vmwgfx_uevent_fini(ScrnInfoPtr scrn, modesettingPtr ms);
Bool
vmwgfx_output_has_origin(xf86OutputPtr output);
void
vmwgfx_output_origin(xf86OutputPtr output, int *x, int *y);
void
vmwgfx_outputs_off(ScrnInfoPtr pScrn);
void
vmwgfx_outputs_on(ScrnInfoPtr pScrn);

/***********************************************************************
 * vmwgfx_layout.c
 */
struct vmwgfx_layout *
vmwgfx_layout_from_kms(ScrnInfoPtr pScrn);
void
vmwgfx_layout_configuration(ScrnInfoPtr pScrn, struct vmwgfx_layout *layout);
void
vmwgfx_layout_handler(ScrnInfoPtr pScrn);

/***********************************************************************
 * xorg_xv.c
 */
void
xorg_xv_init(ScreenPtr pScreen);

XF86VideoAdaptorPtr
vmw_video_init_adaptor(ScrnInfoPtr pScrn);
void
vmw_video_free_adaptor(XF86VideoAdaptorPtr adaptor);
void
vmw_xv_close(ScreenPtr pScreen);

void
vmw_ctrl_ext_init(ScrnInfoPtr pScrn);

/***********************************************************************
 * vmwgfx_dri3.c
 */
#define VMW_XA_VERSION_MAJOR_DRI3 2
#define VMW_XA_VERSION_MINOR_DRI3 4

Bool
vmwgfx_dri3_init(ScreenPtr screen);

#endif /* _XORG_TRACKER_H_ */
0707010000003F000081A400000000000000000000000161A68E12000057B8000000000000000000000000000000000000003000000000xf86-video-vmware-13.3.0+12/vmwgfx/vmwgfx_drm.h/**************************************************************************
 *
 * Copyright © 2009 VMware, Inc., Palo Alto, CA., USA
 * 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
 * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM,
 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
 * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
 * USE OR OTHER DEALINGS IN THE SOFTWARE.
 *
 **************************************************************************/

#ifndef __VMWGFX_DRM_H__
#define __VMWGFX_DRM_H__
#include <drm.h>

#define DRM_VMW_MAX_SURFACE_FACES 6
#define DRM_VMW_MAX_MIP_LEVELS 24


#define DRM_VMW_GET_PARAM            0
#define DRM_VMW_ALLOC_DMABUF         1
#define DRM_VMW_UNREF_DMABUF         2
#define DRM_VMW_CURSOR_BYPASS        3
/* guarded by DRM_VMW_PARAM_NUM_STREAMS != 0*/
#define DRM_VMW_CONTROL_STREAM       4
#define DRM_VMW_CLAIM_STREAM         5
#define DRM_VMW_UNREF_STREAM         6
/* guarded by DRM_VMW_PARAM_3D == 1 */
#define DRM_VMW_CREATE_CONTEXT       7
#define DRM_VMW_UNREF_CONTEXT        8
#define DRM_VMW_CREATE_SURFACE       9
#define DRM_VMW_UNREF_SURFACE        10
#define DRM_VMW_REF_SURFACE          11
#define DRM_VMW_EXECBUF              12
#define DRM_VMW_GET_3D_CAP           13
#define DRM_VMW_FENCE_WAIT           14
#define DRM_VMW_FENCE_SIGNALED       15
#define DRM_VMW_FENCE_UNREF          16
#define DRM_VMW_FENCE_EVENT          17
#define DRM_VMW_PRESENT              18
#define DRM_VMW_PRESENT_READBACK     19
#define DRM_VMW_UPDATE_LAYOUT        20

/*************************************************************************/
/**
 * DRM_VMW_GET_PARAM - get device information.
 *
 * DRM_VMW_PARAM_FIFO_OFFSET:
 * Offset to use to map the first page of the FIFO read-only.
 * The fifo is mapped using the mmap() system call on the drm device.
 *
 * DRM_VMW_PARAM_OVERLAY_IOCTL:
 * Does the driver support the overlay ioctl.
 */

#define DRM_VMW_PARAM_NUM_STREAMS      0
#define DRM_VMW_PARAM_NUM_FREE_STREAMS 1
#define DRM_VMW_PARAM_3D               2
#define DRM_VMW_PARAM_HW_CAPS          3
#define DRM_VMW_PARAM_FIFO_CAPS        4
#define DRM_VMW_PARAM_MAX_FB_SIZE      5
#define DRM_VMW_PARAM_FIFO_HW_VERSION  6
#define DRM_VMW_PARAM_SCREEN_TARGET    11

/**
 * struct drm_vmw_getparam_arg
 *
 * @value: Returned value. //Out
 * @param: Parameter to query. //In.
 *
 * Argument to the DRM_VMW_GET_PARAM Ioctl.
 */

struct drm_vmw_getparam_arg {
	uint64_t value;
	uint32_t param;
	uint32_t pad64;
};

/*************************************************************************/
/**
 * DRM_VMW_CREATE_CONTEXT - Create a host context.
 *
 * Allocates a device unique context id, and queues a create context command
 * for the host. Does not wait for host completion.
 */

/**
 * struct drm_vmw_context_arg
 *
 * @cid: Device unique context ID.
 *
 * Output argument to the DRM_VMW_CREATE_CONTEXT Ioctl.
 * Input argument to the DRM_VMW_UNREF_CONTEXT Ioctl.
 */

struct drm_vmw_context_arg {
	int32_t cid;
	uint32_t pad64;
};

/*************************************************************************/
/**
 * DRM_VMW_UNREF_CONTEXT - Create a host context.
 *
 * Frees a global context id, and queues a destroy host command for the host.
 * Does not wait for host completion. The context ID can be used directly
 * in the command stream and shows up as the same context ID on the host.
 */

/*************************************************************************/
/**
 * DRM_VMW_CREATE_SURFACE - Create a host suface.
 *
 * Allocates a device unique surface id, and queues a create surface command
 * for the host. Does not wait for host completion. The surface ID can be
 * used directly in the command stream and shows up as the same surface
 * ID on the host.
 */

/**
 * struct drm_wmv_surface_create_req
 *
 * @flags: Surface flags as understood by the host.
 * @format: Surface format as understood by the host.
 * @mip_levels: Number of mip levels for each face.
 * An unused face should have 0 encoded.
 * @size_addr: Address of a user-space array of sruct drm_vmw_size
 * cast to an uint64_t for 32-64 bit compatibility.
 * The size of the array should equal the total number of mipmap levels.
 * @shareable: Boolean whether other clients (as identified by file descriptors)
 * may reference this surface.
 * @scanout: Boolean whether the surface is intended to be used as a
 * scanout.
 *
 * Input data to the DRM_VMW_CREATE_SURFACE Ioctl.
 * Output data from the DRM_VMW_REF_SURFACE Ioctl.
 */

struct drm_vmw_surface_create_req {
	uint32_t flags;
	uint32_t format;
	uint32_t mip_levels[DRM_VMW_MAX_SURFACE_FACES];
	uint64_t size_addr;
	int32_t shareable;
	int32_t scanout;
};

/**
 * struct drm_wmv_surface_arg
 *
 * @sid: Surface id of created surface or surface to destroy or reference.
 *
 * Output data from the DRM_VMW_CREATE_SURFACE Ioctl.
 * Input argument to the DRM_VMW_UNREF_SURFACE Ioctl.
 * Input argument to the DRM_VMW_REF_SURFACE Ioctl.
 */

struct drm_vmw_surface_arg {
	int32_t sid;
	uint32_t pad64;
};

/**
 * struct drm_vmw_size ioctl.
 *
 * @width - mip level width
 * @height - mip level height
 * @depth - mip level depth
 *
 * Description of a mip level.
 * Input data to the DRM_WMW_CREATE_SURFACE Ioctl.
 */

struct drm_vmw_size {
	uint32_t width;
	uint32_t height;
	uint32_t depth;
	uint32_t pad64;
};

/**
 * union drm_vmw_surface_create_arg
 *
 * @rep: Output data as described above.
 * @req: Input data as described above.
 *
 * Argument to the DRM_VMW_CREATE_SURFACE Ioctl.
 */

union drm_vmw_surface_create_arg {
	struct drm_vmw_surface_arg rep;
	struct drm_vmw_surface_create_req req;
};

/*************************************************************************/
/**
 * DRM_VMW_REF_SURFACE - Reference a host surface.
 *
 * Puts a reference on a host surface with a give sid, as previously
 * returned by the DRM_VMW_CREATE_SURFACE ioctl.
 * A reference will make sure the surface isn't destroyed while we hold
 * it and will allow the calling client to use the surface ID in the command
 * stream.
 *
 * On successful return, the Ioctl returns the surface information given
 * in the DRM_VMW_CREATE_SURFACE ioctl.
 */

/**
 * union drm_vmw_surface_reference_arg
 *
 * @rep: Output data as described above.
 * @req: Input data as described above.
 *
 * Argument to the DRM_VMW_REF_SURFACE Ioctl.
 */

union drm_vmw_surface_reference_arg {
	struct drm_vmw_surface_create_req rep;
	struct drm_vmw_surface_arg req;
};

/*************************************************************************/
/**
 * DRM_VMW_UNREF_SURFACE - Unreference a host surface.
 *
 * Clear a reference previously put on a host surface.
 * When all references are gone, including the one implicitly placed
 * on creation,
 * a destroy surface command will be queued for the host.
 * Does not wait for completion.
 */

/*************************************************************************/
/**
 * DRM_VMW_EXECBUF
 *
 * Submit a command buffer for execution on the host, and return a
 * fence seqno that when signaled, indicates that the command buffer has
 * executed.
 */

/**
 * struct drm_vmw_execbuf_arg
 *
 * @commands: User-space address of a command buffer cast to an uint64_t.
 * @command-size: Size in bytes of the command buffer.
 * @throttle-us: Sleep until software is less than @throttle_us
 * microseconds ahead of hardware. The driver may round this value
 * to the nearest kernel tick.
 * @fence_rep: User-space address of a struct drm_vmw_fence_rep cast to an
 * uint64_t.
 * @version: Allows expanding the execbuf ioctl parameters without breaking
 * backwards compatibility, since user-space will always tell the kernel
 * which version it uses.
 * @flags: Execbuf flags. None currently.
 *
 * Argument to the DRM_VMW_EXECBUF Ioctl.
 */

#define DRM_VMW_EXECBUF_VERSION 1

struct drm_vmw_execbuf_arg {
	uint64_t commands;
	uint32_t command_size;
	uint32_t throttle_us;
	uint64_t fence_rep;
	uint32_t version;
	uint32_t flags;
};

/**
 * struct drm_vmw_fence_rep
 *
 * @handle: Fence object handle for fence associated with a command submission.
 * @mask: Fence flags relevant for this fence object.
 * @seqno: Fence sequence number in fifo. A fence object with a lower
 * seqno will signal the EXEC flag before a fence object with a higher
 * seqno. This can be used by user-space to avoid kernel calls to determine
 * whether a fence has signaled the EXEC flag. Note that @seqno will
 * wrap at 32-bit.
 * @passed_seqno: The highest seqno number processed by the hardware
 * so far. This can be used to mark user-space fence objects as signaled, and
 * to determine whether a fence seqno might be stale.
 * @error: This member should've been set to -EFAULT on submission.
 * The following actions should be take on completion:
 * error == -EFAULT: Fence communication failed. The host is synchronized.
 * Use the last fence id read from the FIFO fence register.
 * error != 0 && error != -EFAULT:
 * Fence submission failed. The host is synchronized. Use the fence_seq member.
 * error == 0: All is OK, The host may not be synchronized.
 * Use the fence_seq member.
 *
 * Input / Output data to the DRM_VMW_EXECBUF Ioctl.
 */

struct drm_vmw_fence_rep {
	uint32_t handle;
	uint32_t mask;
	uint32_t seqno;
	uint32_t passed_seqno;
	uint32_t pad64;
	int32_t error;
};

/*************************************************************************/
/**
 * DRM_VMW_ALLOC_DMABUF
 *
 * Allocate a DMA buffer that is visible also to the host.
 * NOTE: The buffer is
 * identified by a handle and an offset, which are private to the guest, but
 * useable in the command stream. The guest kernel may translate these
 * and patch up the command stream accordingly. In the future, the offset may
 * be zero at all times, or it may disappear from the interface before it is
 * fixed.
 *
 * The DMA buffer may stay user-space mapped in the guest at all times,
 * and is thus suitable for sub-allocation.
 *
 * DMA buffers are mapped using the mmap() syscall on the drm device.
 */

/**
 * struct drm_vmw_alloc_dmabuf_req
 *
 * @size: Required minimum size of the buffer.
 *
 * Input data to the DRM_VMW_ALLOC_DMABUF Ioctl.
 */

struct drm_vmw_alloc_dmabuf_req {
	uint32_t size;
	uint32_t pad64;
};

/**
 * struct drm_vmw_dmabuf_rep
 *
 * @map_handle: Offset to use in the mmap() call used to map the buffer.
 * @handle: Handle unique to this buffer. Used for unreferencing.
 * @cur_gmr_id: GMR id to use in the command stream when this buffer is
 * referenced. See not above.
 * @cur_gmr_offset: Offset to use in the command stream when this buffer is
 * referenced. See note above.
 *
 * Output data from the DRM_VMW_ALLOC_DMABUF Ioctl.
 */

struct drm_vmw_dmabuf_rep {
	uint64_t map_handle;
	uint32_t handle;
	uint32_t cur_gmr_id;
	uint32_t cur_gmr_offset;
	uint32_t pad64;
};

/**
 * union drm_vmw_dmabuf_arg
 *
 * @req: Input data as described above.
 * @rep: Output data as described above.
 *
 * Argument to the DRM_VMW_ALLOC_DMABUF Ioctl.
 */

union drm_vmw_alloc_dmabuf_arg {
	struct drm_vmw_alloc_dmabuf_req req;
	struct drm_vmw_dmabuf_rep rep;
};

/*************************************************************************/
/**
 * DRM_VMW_UNREF_DMABUF - Free a DMA buffer.
 *
 */

/**
 * struct drm_vmw_unref_dmabuf_arg
 *
 * @handle: Handle indicating what buffer to free. Obtained from the
 * DRM_VMW_ALLOC_DMABUF Ioctl.
 *
 * Argument to the DRM_VMW_UNREF_DMABUF Ioctl.
 */

struct drm_vmw_unref_dmabuf_arg {
	uint32_t handle;
	uint32_t pad64;
};

/*************************************************************************/
/**
 * DRM_VMW_CONTROL_STREAM - Control overlays, aka streams.
 *
 * This IOCTL controls the overlay units of the svga device.
 * The SVGA overlay units does not work like regular hardware units in
 * that they do not automaticaly read back the contents of the given dma
 * buffer. But instead only read back for each call to this ioctl, and
 * at any point between this call being made and a following call that
 * either changes the buffer or disables the stream.
 */

/**
 * struct drm_vmw_rect
 *
 * Defines a rectangle. Used in the overlay ioctl to define
 * source and destination rectangle.
 */

struct drm_vmw_rect {
	int32_t x;
	int32_t y;
	uint32_t w;
	uint32_t h;
};

/**
 * struct drm_vmw_control_stream_arg
 *
 * @stream_id: Stearm to control
 * @enabled: If false all following arguments are ignored.
 * @handle: Handle to buffer for getting data from.
 * @format: Format of the overlay as understood by the host.
 * @width: Width of the overlay.
 * @height: Height of the overlay.
 * @size: Size of the overlay in bytes.
 * @pitch: Array of pitches, the two last are only used for YUV12 formats.
 * @offset: Offset from start of dma buffer to overlay.
 * @src: Source rect, must be within the defined area above.
 * @dst: Destination rect, x and y may be negative.
 *
 * Argument to the DRM_VMW_CONTROL_STREAM Ioctl.
 */

struct drm_vmw_control_stream_arg {
	uint32_t stream_id;
	uint32_t enabled;

	uint32_t flags;
	uint32_t color_key;

	uint32_t handle;
	uint32_t offset;
	int32_t format;
	uint32_t size;
	uint32_t width;
	uint32_t height;
	uint32_t pitch[3];

	uint32_t pad64;
	struct drm_vmw_rect src;
	struct drm_vmw_rect dst;
};

/*************************************************************************/
/**
 * DRM_VMW_CURSOR_BYPASS - Give extra information about cursor bypass.
 *
 */

#define DRM_VMW_CURSOR_BYPASS_ALL    (1 << 0)
#define DRM_VMW_CURSOR_BYPASS_FLAGS       (1)

/**
 * struct drm_vmw_cursor_bypass_arg
 *
 * @flags: Flags.
 * @crtc_id: Crtc id, only used if DMR_CURSOR_BYPASS_ALL isn't passed.
 * @xpos: X position of cursor.
 * @ypos: Y position of cursor.
 * @xhot: X hotspot.
 * @yhot: Y hotspot.
 *
 * Argument to the DRM_VMW_CURSOR_BYPASS Ioctl.
 */

struct drm_vmw_cursor_bypass_arg {
	uint32_t flags;
	uint32_t crtc_id;
	int32_t xpos;
	int32_t ypos;
	int32_t xhot;
	int32_t yhot;
};

/*************************************************************************/
/**
 * DRM_VMW_CLAIM_STREAM - Claim a single stream.
 */

/**
 * struct drm_vmw_context_arg
 *
 * @stream_id: Device unique context ID.
 *
 * Output argument to the DRM_VMW_CREATE_CONTEXT Ioctl.
 * Input argument to the DRM_VMW_UNREF_CONTEXT Ioctl.
 */

struct drm_vmw_stream_arg {
	uint32_t stream_id;
	uint32_t pad64;
};

/*************************************************************************/
/**
 * DRM_VMW_UNREF_STREAM - Unclaim a stream.
 *
 * Return a single stream that was claimed by this process. Also makes
 * sure that the stream has been stopped.
 */

/*************************************************************************/
/**
 * DRM_VMW_GET_3D_CAP
 *
 * Read 3D capabilities from the FIFO
 *
 */

/**
 * struct drm_vmw_get_3d_cap_arg
 *
 * @buffer: Pointer to a buffer for capability data, cast to an uint64_t
 * @size: Max size to copy
 *
 * Input argument to the DRM_VMW_GET_3D_CAP_IOCTL
 * ioctls.
 */

struct drm_vmw_get_3d_cap_arg {
	uint64_t buffer;
	uint32_t max_size;
	uint32_t pad64;
};


/*************************************************************************/
/**
 * DRM_VMW_FENCE_WAIT
 *
 * Waits for a fence object to signal. The wait is interruptible, so that
 * signals may be delivered during the interrupt. The wait may timeout,
 * in which case the calls returns -EBUSY. If the wait is restarted,
 * that is restarting without resetting @cookie_valid to zero,
 * the timeout is computed from the first call.
 *
 * The flags argument to the DRM_VMW_FENCE_WAIT ioctl indicates what to wait
 * on:
 * DRM_VMW_FENCE_FLAG_EXEC: All commands ahead of the fence in the command
 * stream
 * have executed.
 * DRM_VMW_FENCE_FLAG_QUERY: All query results resulting from query finish
 * commands
 * in the buffer given to the EXECBUF ioctl returning the fence object handle
 * are available to user-space.
 *
 * DRM_VMW_WAIT_OPTION_UNREF: If this wait option is given, and the
 * fenc wait ioctl returns 0, the fence object has been unreferenced after
 * the wait.
 */

#define DRM_VMW_FENCE_FLAG_EXEC   (1 << 0)
#define DRM_VMW_FENCE_FLAG_QUERY  (1 << 1)

#define DRM_VMW_WAIT_OPTION_UNREF (1 << 0)

/**
 * struct drm_vmw_fence_wait_arg
 *
 * @handle: Fence object handle as returned by the DRM_VMW_EXECBUF ioctl.
 * @cookie_valid: Must be reset to 0 on first call. Left alone on restart.
 * @kernel_cookie: Set to 0 on first call. Left alone on restart.
 * @timeout_us: Wait timeout in microseconds. 0 for indefinite timeout.
 * @lazy: Set to 1 if timing is not critical. Allow more than a kernel tick
 * before returning.
 * @flags: Fence flags to wait on.
 * @wait_options: Options that control the behaviour of the wait ioctl.
 *
 * Input argument to the DRM_VMW_FENCE_WAIT ioctl.
 */

struct drm_vmw_fence_wait_arg {
	uint32_t handle;
	int32_t  cookie_valid;
	uint64_t kernel_cookie;
	uint64_t timeout_us;
	int32_t lazy;
	int32_t flags;
	int32_t wait_options;
	int32_t pad64;
};

/*************************************************************************/
/**
 * DRM_VMW_FENCE_SIGNALED
 *
 * Checks if a fence object is signaled..
 */

/**
 * struct drm_vmw_fence_signaled_arg
 *
 * @handle: Fence object handle as returned by the DRM_VMW_EXECBUF ioctl.
 * @flags: Fence object flags input to DRM_VMW_FENCE_SIGNALED ioctl
 * @signaled: Out: Flags signaled.
 * @sequence: Out: Highest sequence passed so far. Can be used to signal the
 * EXEC flag of user-space fence objects.
 *
 * Input/Output argument to the DRM_VMW_FENCE_SIGNALED and DRM_VMW_FENCE_UNREF
 * ioctls.
 */

struct drm_vmw_fence_signaled_arg {
	 uint32_t handle;
	 uint32_t flags;
	 int32_t signaled;
	 uint32_t passed_seqno;
	 uint32_t signaled_flags;
	 uint32_t pad64;
};

/*************************************************************************/
/**
 * DRM_VMW_FENCE_UNREF
 *
 * Unreferences a fence object, and causes it to be destroyed if there are no
 * other references to it.
 *
 */

/**
 * struct drm_vmw_fence_arg
 *
 * @handle: Fence object handle as returned by the DRM_VMW_EXECBUF ioctl.
 *
 * Input/Output argument to the DRM_VMW_FENCE_UNREF ioctl..
 */

struct drm_vmw_fence_arg {
	 uint32_t handle;
	 uint32_t pad64;
};


/*************************************************************************/
/**
 * DRM_VMW_FENCE_EVENT
 *
 * Queues an event on a fence to be delivered on the drm character device
 * when the fence has signaled the DRM_VMW_FENCE_FLAG_EXEC flag.
 * Optionally the approximate time when the fence signaled is
 * given by the event.
 */

/*
 * The event type
 */
#define DRM_VMW_EVENT_FENCE_SIGNALED 0x80000000

struct drm_vmw_event_fence {
	struct drm_event base;
	uint64_t user_data;
	uint32_t tv_sec;
	uint32_t tv_usec;
};

/*
 * Flags that may be given to the command.
 */
/* Request fence signaled time on the event. */
#define DRM_VMW_FE_FLAG_REQ_TIME (1 << 0)

/**
 * struct drm_vmw_fence_event_arg
 *
 * @fence_rep: Pointer to fence_rep structure cast to uint64_t or 0 if
 * the fence is not supposed to be referenced by user-space.
 * @user_info: Info to be delivered with the event.
 * @handle: Attach the event to this fence only.
 * @flags: A set of flags as defined above.
 */
struct drm_vmw_fence_event_arg {
	uint64_t fence_rep;
	uint64_t user_data;
	uint32_t handle;
	uint32_t flags;
};


/*************************************************************************/
/**
 * DRM_VMW_PRESENT
 *
 * Executes an SVGA present on a given fb for a given surface. The surface
 * is placed on the framebuffer. Cliprects are given relative to the given
 * point (the point disignated by dest_{x|y}).
 *
 */

/**
 * struct drm_vmw_present_arg
 * @fb_id: framebuffer id to present / read back from.
 * @sid: Surface id to present from.
 * @dest_x: X placement coordinate for surface.
 * @dest_y: Y placement coordinate for surface.
 * @clips_ptr: Pointer to an array of clip rects cast to an uint64_t.
 * @num_clips: Number of cliprects given relative to the framebuffer origin,
 * in the same coordinate space as the frame buffer.
 * @pad64: Unused 64-bit padding.
 *
 * Input argument to the DRM_VMW_PRESENT ioctl.
 */

struct drm_vmw_present_arg {
	uint32_t fb_id;
	uint32_t sid;
	int32_t dest_x;
	int32_t dest_y;
	uint64_t clips_ptr;
	uint32_t num_clips;
	uint32_t pad64;
};


/*************************************************************************/
/**
 * DRM_VMW_PRESENT_READBACK
 *
 * Executes an SVGA present readback from a given fb to the dma buffer
 * currently bound as the fb. If there is no dma buffer bound to the fb,
 * an error will be returned.
 *
 */

/**
 * struct drm_vmw_present_arg
 * @fb_id: fb_id to present / read back from.
 * @num_clips: Number of cliprects.
 * @clips_ptr: Pointer to an array of clip rects cast to an uint64_t.
 * @fence_rep: Pointer to a struct drm_vmw_fence_rep, cast to an uint64_t.
 * If this member is NULL, then the ioctl should not return a fence.
 */

struct drm_vmw_present_readback_arg {
	 uint32_t fb_id;
	 uint32_t num_clips;
	 uint64_t clips_ptr;
	 uint64_t fence_rep;
};

/*************************************************************************/
/**
 * DRM_VMW_UPDATE_LAYOUT - Update layout
 *
 * Updates the preferred modes and connection status for connectors. The
 * command consists of one drm_vmw_update_layout_arg pointing to an array
 * of num_outputs drm_vmw_rect's.
 */

/**
 * struct drm_vmw_update_layout_arg
 *
 * @num_outputs: number of active connectors
 * @rects: pointer to array of drm_vmw_rect cast to an uint64_t
 *
 * Input argument to the DRM_VMW_UPDATE_LAYOUT Ioctl.
 */
struct drm_vmw_update_layout_arg {
	uint32_t num_outputs;
	uint32_t pad64;
	uint64_t rects;
};

#endif
07070100000040000081A400000000000000000000000161A68E12000036E0000000000000000000000000000000000000003100000000xf86-video-vmware-13.3.0+12/vmwgfx/vmwgfx_drmi.c/*
 * 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: Jakob Bornecrantz <wallbraker@gmail.com>
 * Author: Thomas Hellstrom <thellstrom@vmware.com>
 */

#ifdef HAVE_CONFIG_H
#include "config.h"
#endif

#include <stdint.h>
#include <errno.h>
#include <sys/mman.h>
#include "vmwgfx_drm.h"
#include <xf86drm.h>
#include "vmwgfx_drmi.h"

#define uint32 uint32_t
#define int32 int32_t
#define uint16 uint16_t
#define uint8 uint8_t

#include "svga3d_reg.h"
#include "vmwgfx_driver.h"
#include "common_compat.h"

static int
vmwgfx_fence_wait(int drm_fd, uint32_t handle, Bool unref)
{
	struct drm_vmw_fence_wait_arg farg;
	memset(&farg, 0, sizeof(farg));

	farg.handle = handle;
	farg.flags = DRM_VMW_FENCE_FLAG_EXEC;
	farg.timeout_us = 10*1000000;
	farg.cookie_valid = 0;

	if (unref)
	    farg.wait_options |= DRM_VMW_WAIT_OPTION_UNREF;

	return drmCommandWriteRead(drm_fd, DRM_VMW_FENCE_WAIT, &farg,
				   sizeof(farg));
}

static void
vmwgfx_fence_unref(int drm_fd, uint32_t handle)
{
	struct drm_vmw_fence_arg farg;
	memset(&farg, 0, sizeof(farg));

	farg.handle = handle;

	(void) drmCommandWrite(drm_fd, DRM_VMW_FENCE_UNREF, &farg,
			       sizeof(farg));
}


int
vmwgfx_present_readback(int drm_fd, uint32_t fb_id, RegionPtr region)
{
    BoxPtr clips = REGION_RECTS(region);
    unsigned int num_clips = REGION_NUM_RECTS(region);
    unsigned int alloc_clips = min(num_clips, DRM_MODE_FB_DIRTY_MAX_CLIPS);
    struct drm_vmw_fence_rep rep;
    struct drm_vmw_present_readback_arg arg;
    int ret;
    unsigned i;
    struct drm_vmw_rect *rects, *r;

    if (num_clips == 0)
	return 0;

    rects = malloc(alloc_clips * sizeof(*rects));
    if (!rects) {
	LogMessage(X_ERROR, "Failed to alloc cliprects for "
		   "present readback.\n");
	return -1;
    }

    while (num_clips > 0) {
	unsigned int cur_clips = min(num_clips, DRM_MODE_FB_DIRTY_MAX_CLIPS);

	memset(&arg, 0, sizeof(arg));
	memset(&rep, 0, sizeof(rep));
	memset(rects, 0, alloc_clips * sizeof(*rects));

	arg.fb_id = fb_id;
	arg.num_clips = cur_clips;
	arg.clips_ptr = (unsigned long) rects;

	/* Only request a fence on the last clip batch */
	arg.fence_rep = (cur_clips == num_clips) ? (unsigned long) &rep : 0UL;
	rep.error = -EFAULT;

	for (i = 0, r = rects; i < cur_clips; ++i, ++r, ++clips) {
	    r->x = clips->x1;
	    r->y = clips->y1;
	    r->w = clips->x2 - clips->x1;
	    r->h = clips->y2 - clips->y1;
	}

	ret = drmCommandWrite(drm_fd, DRM_VMW_PRESENT_READBACK, &arg,
			      sizeof(arg));
	if (ret)
	    LogMessage(X_ERROR, "Present readback error %s.\n", strerror(-ret));

	/* Sync if we have a fence to avoid racing with Xorg SW rendering. */
	if (rep.error == 0) {
	    ret = vmwgfx_fence_wait(drm_fd, rep.handle, TRUE);
	    if (ret) {
		LogMessage(X_ERROR, "Present readback fence wait error %s.\n",
			   strerror(-ret));
		/* vmwgfx_fence_wait() takes care of this if ret == 0. */
		vmwgfx_fence_unref(drm_fd, rep.handle);
	    }
	}

	num_clips -= cur_clips;
    }

    free(rects);

    return 0;
}


int
vmwgfx_present(int drm_fd, uint32_t fb_id, unsigned int dst_x,
	       unsigned int dst_y, RegionPtr region, uint32_t handle)
{
    BoxPtr clips = REGION_RECTS(region);
    unsigned int num_clips = REGION_NUM_RECTS(region);
    unsigned int alloc_clips = min(num_clips, DRM_MODE_FB_DIRTY_MAX_CLIPS);
    struct drm_vmw_present_arg arg;
    unsigned int i;
    struct drm_vmw_rect *rects, *r;
    int ret;

    if (num_clips == 0)
	return 0;

    rects = malloc(alloc_clips * sizeof(*rects));
    if (!rects) {
	LogMessage(X_ERROR, "Failed to alloc cliprects for "
		   "present.\n");
	return -1;
    }

    while (num_clips > 0) {
	unsigned int cur_clips = min(num_clips, DRM_MODE_FB_DIRTY_MAX_CLIPS);

	memset(&arg, 0, sizeof(arg));
	memset(rects, 0, alloc_clips * sizeof(*rects));
	arg.fb_id = fb_id;
	arg.sid = handle;
	arg.dest_x = dst_x;
	arg.dest_y = dst_y;
	arg.num_clips = cur_clips;
	arg.clips_ptr = (unsigned long) rects;

	for (i = 0, r = rects; i < cur_clips; ++i, ++r, ++clips) {
	    r->x = clips->x1;
	    r->y = clips->y1;
	    r->w = clips->x2 - clips->x1;
	    r->h = clips->y2 - clips->y1;
	}

	ret = drmCommandWrite(drm_fd, DRM_VMW_PRESENT, &arg, sizeof(arg));
	if (ret)
	    LogMessage(X_ERROR, "Present error %s.\n", strerror(-ret));

	num_clips -= cur_clips;
    }

    free(rects);

    return 0;
}


struct vmwgfx_int_dmabuf {
    struct vmwgfx_dmabuf buf;
    uint64_t map_handle;
    uint64_t sync_handle;
    int sync_valid;
    int drm_fd;
    uint32_t map_count;
    void *addr;
};

static inline struct vmwgfx_int_dmabuf *
vmwgfx_int_dmabuf(struct vmwgfx_dmabuf *buf)
{
    return (struct vmwgfx_int_dmabuf *) buf;
}

struct vmwgfx_dmabuf*
vmwgfx_dmabuf_alloc(int drm_fd, size_t size)
{
    union drm_vmw_alloc_dmabuf_arg arg;
    struct vmwgfx_dmabuf *buf;
    struct vmwgfx_int_dmabuf *ibuf;
    int ret;

    ibuf = calloc(1, sizeof(*ibuf));
    if (!ibuf)
	return NULL;

    buf = &ibuf->buf;
    memset(&arg, 0, sizeof(arg));
    arg.req.size = size;

    ret = drmCommandWriteRead(drm_fd, DRM_VMW_ALLOC_DMABUF, &arg,
			      sizeof(arg));
    if (ret)
	goto out_kernel_fail;

    ibuf = vmwgfx_int_dmabuf(buf);
    ibuf->map_handle = arg.rep.map_handle;
    ibuf->drm_fd = drm_fd;
    buf->handle = arg.rep.handle;
    buf->gmr_id = arg.rep.cur_gmr_id;
    buf->gmr_offset = arg.rep.cur_gmr_offset;
    buf->size = size;

    return buf;
  out_kernel_fail:
    free(buf);
    return NULL;
}

void *
vmwgfx_dmabuf_map(struct vmwgfx_dmabuf *buf)
{
    struct vmwgfx_int_dmabuf *ibuf = vmwgfx_int_dmabuf(buf);

    if (ibuf->addr)
	return ibuf->addr;

    ibuf->addr =  mmap(NULL, buf->size, PROT_READ | PROT_WRITE, MAP_SHARED,
		       ibuf->drm_fd, ibuf->map_handle);

    if (ibuf->addr == MAP_FAILED) {
	ibuf->addr = NULL;
	return NULL;
    }

    ibuf->map_count++;
    return ibuf->addr;
}

void
vmwgfx_dmabuf_unmap(struct vmwgfx_dmabuf *buf)
{
    struct vmwgfx_int_dmabuf *ibuf = vmwgfx_int_dmabuf(buf);

    if (--ibuf->map_count)
	return;

    /*
     * It's a pretty important performance optimzation not to call
     * munmap here, although we should watch out for cases where we might fill
     * the virtual memory space of the process.
     */
}

void
vmwgfx_dmabuf_destroy(struct vmwgfx_dmabuf *buf)
{
    struct vmwgfx_int_dmabuf *ibuf = vmwgfx_int_dmabuf(buf);
    struct drm_vmw_unref_dmabuf_arg arg;

    if (ibuf->addr) {
	munmap(ibuf->addr, buf->size);
	ibuf->addr = NULL;
    }

    memset(&arg, 0, sizeof(arg));
    arg.handle = buf->handle;

    (void) drmCommandWrite(ibuf->drm_fd, DRM_VMW_UNREF_DMABUF, &arg,
			   sizeof(arg));
    free(buf);
}

int
vmwgfx_dma(int host_x, int host_y,
	   RegionPtr region, struct vmwgfx_dmabuf *buf,
	   uint32_t buf_pitch, uint32_t surface_handle, int to_surface)
{
    BoxPtr clips = REGION_RECTS(region);
    unsigned int num_clips = REGION_NUM_RECTS(region);
    struct drm_vmw_execbuf_arg arg;
    struct drm_vmw_fence_rep rep;
    int ret;
    unsigned i;
    SVGA3dCopyBox *cb;
    SVGA3dCmdSurfaceDMASuffix *suffix;
    SVGA3dCmdSurfaceDMA *body;
    struct vmwgfx_int_dmabuf *ibuf = vmwgfx_int_dmabuf(buf);
    struct {
	SVGA3dCmdHeader header;
	SVGA3dCmdSurfaceDMA body;
	SVGA3dCopyBox cb;
    } *cmd;
    static unsigned int max_clips =
	(SVGA_CB_MAX_COMMAND_SIZE - sizeof(*cmd) - sizeof(*suffix)) /
	sizeof(cmd->cb) + 1;

    while (num_clips > 0) {
	unsigned int size;
	unsigned int cur_clips;

	cur_clips = min(num_clips, max_clips);
	size = sizeof(*cmd) + (cur_clips - 1) * sizeof(cmd->cb) +
	    sizeof(*suffix);

	cmd = calloc(1, size);
	if (!cmd)
	    return -1;

	cmd->header.id = SVGA_3D_CMD_SURFACE_DMA;
	cmd->header.size = sizeof(cmd->body) + cur_clips * sizeof(cmd->cb) +
	    sizeof(*suffix);
	cb = &cmd->cb;

	suffix = (SVGA3dCmdSurfaceDMASuffix *) &cb[cur_clips];
	suffix->suffixSize = sizeof(*suffix);
	suffix->maximumOffset = (uint32_t) -1;
	suffix->flags.discard = 0;
	suffix->flags.unsynchronized = 0;
	suffix->flags.reserved = 0;

	body = &cmd->body;
	body->guest.ptr.gmrId = buf->gmr_id;
	body->guest.ptr.offset = buf->gmr_offset;
	body->guest.pitch = buf_pitch;
	body->host.sid = surface_handle;
	body->host.face = 0;
	body->host.mipmap = 0;

	body->transfer = (to_surface ? SVGA3D_WRITE_HOST_VRAM :
			  SVGA3D_READ_HOST_VRAM);

	for (i = 0; i < cur_clips; i++, cb++, clips++) {
	    cb->x = (uint16_t) clips->x1 + host_x;
	    cb->y = (uint16_t) clips->y1 + host_y;
	    cb->z = 0;
	    cb->srcx = (uint16_t) clips->x1;
	    cb->srcy = (uint16_t) clips->y1;
	    cb->srcz = 0;
	    cb->w = (uint16_t) (clips->x2 - clips->x1);
	    cb->h = (uint16_t) (clips->y2 - clips->y1);
	    cb->d = 1;
#if 0
	    LogMessage(X_INFO, "DMA! x: %u y: %u srcx: %u srcy: %u w: %u h: %u %s\n",
		       cb->x, cb->y, cb->srcx, cb->srcy, cb->w, cb->h,
		       to_surface ? "to" : "from");
#endif

	}

	memset(&arg, 0, sizeof(arg));
	memset(&rep, 0, sizeof(rep));

	rep.error = -EFAULT;

	/* Only require a fence if readback and last batch of cliprects. */
	arg.fence_rep = ((to_surface && (cur_clips == num_clips)) ?
			 0UL : (unsigned long) &rep);
	arg.commands = (unsigned long)cmd;
	arg.command_size = size;
	arg.throttle_us = 0;
	arg.version = DRM_VMW_EXECBUF_VERSION;

	ret = drmCommandWrite(ibuf->drm_fd, DRM_VMW_EXECBUF, &arg, sizeof(arg));
	if (ret) {
	    LogMessage(X_ERROR, "DMA error %s.\n", strerror(-ret));
	}

	free(cmd);
	num_clips -= cur_clips;

	if (rep.error == 0) {
	    ret = vmwgfx_fence_wait(ibuf->drm_fd, rep.handle, TRUE);
	    if (ret) {
		LogMessage(X_ERROR, "DMA from host fence wait error %s.\n",
			   strerror(-ret));
		/* vmwgfx_fence_wait() takes care of this if ret == 0. */
		vmwgfx_fence_unref(ibuf->drm_fd, rep.handle);
	    }
	}
    }

    return 0;
}

int
vmwgfx_get_param(int drm_fd, uint32_t param, uint64_t *out)
{
    struct drm_vmw_getparam_arg gp_arg;
    int ret;

    memset(&gp_arg, 0, sizeof(gp_arg));
    gp_arg.param = param;
    ret = drmCommandWriteRead(drm_fd, DRM_VMW_GET_PARAM,
	    &gp_arg, sizeof(gp_arg));

    if (ret == 0) {
	*out = gp_arg.value;
    }

    return ret;
}

int
vmwgfx_num_streams(int drm_fd, uint32_t *ntot, uint32_t *nfree)
{
    uint64_t v1, v2;
    int ret;

    ret = vmwgfx_get_param(drm_fd, DRM_VMW_PARAM_NUM_STREAMS, &v1);
    if (ret)
	return ret;

    ret = vmwgfx_get_param(drm_fd, DRM_VMW_PARAM_NUM_FREE_STREAMS, &v2);
    if (ret)
	return ret;

    *ntot = (uint32_t)v1;
    *nfree = (uint32_t)v2;

    return 0;
}

int
vmwgfx_claim_stream(int drm_fd, uint32_t *out)
{
    struct drm_vmw_stream_arg s_arg;
    int ret;

    ret = drmCommandRead(drm_fd, DRM_VMW_CLAIM_STREAM,
			 &s_arg, sizeof(s_arg));

    if (ret)
	return -1;

    *out = s_arg.stream_id;
    return 0;
}

int
vmwgfx_unref_stream(int drm_fd, uint32_t stream_id)
{
    struct drm_vmw_stream_arg s_arg;
    int ret;

    memset(&s_arg, 0, sizeof(s_arg));
    s_arg.stream_id = stream_id;

    ret = drmCommandWrite(drm_fd, DRM_VMW_UNREF_STREAM,
			  &s_arg, sizeof(s_arg));

    return (ret != 0) ? -1 : 0;
}

int
vmwgfx_cursor_bypass(int drm_fd, int xhot, int yhot)
{
    struct drm_vmw_cursor_bypass_arg arg;
    int ret;

    memset(&arg, 0, sizeof(arg));
    arg.flags = DRM_VMW_CURSOR_BYPASS_ALL;
    arg.xhot = xhot;
    arg.yhot = yhot;

    ret = drmCommandWrite(drm_fd, DRM_VMW_CURSOR_BYPASS,
			  &arg, sizeof(arg));

    return ret;
}

int
vmwgfx_update_gui_layout(int drm_fd, unsigned int num_rects,
			 struct drm_vmw_rect *rects)
{
    struct drm_vmw_update_layout_arg arg;

    memset(&arg, 0, sizeof(arg));

    arg.num_outputs = num_rects;
    arg.rects = (unsigned long) rects;

    return drmCommandWrite(drm_fd, DRM_VMW_UPDATE_LAYOUT, &arg,
			   sizeof(arg));
}


int
vmwgfx_max_fb_size(int drm_fd, size_t *size)
{
    uint64_t tmp_size;

    if (vmwgfx_get_param(drm_fd, DRM_VMW_PARAM_MAX_FB_SIZE, &tmp_size) != 0)
	return -1;

    *size = tmp_size;

    return 0;
}

#ifdef HAVE_LIBDRM_2_4_38
/**
 * vmwgfx_prime_fd_to_handle - Return a TTM handle to a prime object
 *
 * @drm_fd: File descriptor for the drm connection.
 * @prime_fd: File descriptor identifying the prime object.
 * @handle: Pointer to returned TTM handle.
 *
 * Takes a reference on the underlying object and returns a TTM handle to it.
 */
int
vmwgfx_prime_fd_to_handle(int drm_fd, int prime_fd, uint32_t *handle)
{
    *handle = 0;

    return drmPrimeFDToHandle(drm_fd, prime_fd, handle);
}

/**
 * vmwgfx_prime_release_handle - Release a reference on a TTM object
 *
 * @drm_fd: File descriptor for the drm connection.
 * @handle: TTM handle as returned by vmwgfx_prime_fd_to_handle.
 *
 * Releases the reference obtained by vmwgfx_prime_fd_to_handle().
 */
void
vmwgfx_prime_release_handle(int drm_fd, uint32_t handle)
{
    struct drm_vmw_surface_arg s_arg;

    memset(&s_arg, 0, sizeof(s_arg));
    s_arg.sid = handle;

    (void) drmCommandWrite(drm_fd, DRM_VMW_UNREF_SURFACE, &s_arg,
			   sizeof(s_arg));
}
#endif /* HAVE_LIBDRM_2_4_38 */
07070100000041000081A400000000000000000000000161A68E1200000B41000000000000000000000000000000000000003100000000xf86-video-vmware-13.3.0+12/vmwgfx/vmwgfx_drmi.h/*
 * 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: Jakob Bornecrantz <wallbraker@gmail.com>
 * Author: Thomas Hellstrom <thellstrom@vmware.com>
 */

#ifndef _VMWGFX_DRMI_H_
#define _VMWGFX_DRMI_H_

#include <xorg-server.h>
#include <regionstr.h>
#include <stdint.h>
#include "vmwgfx_drm.h"

struct vmwgfx_dma_ctx;

extern int
vmwgfx_present_readback(int drm_fd, uint32_t fb_id, RegionPtr region);

extern int
vmwgfx_present(int drm_fd, uint32_t fb_id, unsigned int dst_x,
	       unsigned int dst_y, RegionPtr region, uint32_t handle);

struct vmwgfx_dmabuf {
  uint32_t handle;
  uint32_t gmr_id;
  uint32_t gmr_offset;
  size_t size;
};

extern struct vmwgfx_dmabuf*
vmwgfx_dmabuf_alloc(int drm_fd, size_t size);
extern void
vmwgfx_dmabuf_destroy(struct vmwgfx_dmabuf *buf);
extern void *
vmwgfx_dmabuf_map(struct vmwgfx_dmabuf *buf);
extern void
vmwgfx_dmabuf_unmap(struct vmwgfx_dmabuf *buf);

extern int
vmwgfx_dma(int host_x, int host_y,
	   RegionPtr region, struct vmwgfx_dmabuf *buf,
	   uint32_t buf_pitch, uint32_t surface_handle, int to_surface);

extern int
vmwgfx_num_streams(int drm_fd, uint32_t *ntot, uint32_t *nfree);

extern int
vmwgfx_claim_stream(int drm_fd, uint32_t *out);

extern int
vmwgfx_unref_stream(int drm_fd, uint32_t stream_id);

int
vmwgfx_cursor_bypass(int drm_fd, int xhot, int yhot);

int
vmwgfx_max_fb_size(int drm_fd, size_t *size);

int
vmwgfx_update_gui_layout(int drm_fd, unsigned int num_rects,
			 struct drm_vmw_rect *rects);
int
vmwgfx_get_param(int drm_fd, uint32_t param, uint64_t *out);

#ifdef HAVE_LIBDRM_2_4_38
int
vmwgfx_prime_fd_to_handle(int drm_fd, int prime_fd, uint32_t *handle);

void
vmwgfx_prime_release_handle(int drm_fd, uint32_t handle);
#endif /* HAVE_LIBDRM_2_4_38 */
#endif
07070100000042000081A400000000000000000000000161A68E1200000810000000000000000000000000000000000000003300000000xf86-video-vmware-13.3.0+12/vmwgfx/vmwgfx_hosted.c/*
 * Copyright 2013 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>
 */

#ifdef HAVE_CONFIG_H
#include "config.h"
#endif

#include "vmwgfx_hosted.h"

/*
 * Hook up hosted environments here.
 */

/**
 * vmwgfx_hosted_detect - Check whether we are hosted
 *
 * Check whether we are hosted by a compositor and
 * in that case return a pointer to a valid struct vmwgfx_hosted_driver.
 * If not hosted, return NULL.
 */
const struct vmwgfx_hosted_driver *
vmwgfx_hosted_detect(void)
{
    return NULL;
}

/**
 * vmwgfx_hosted_modify_flags - Modify driver flags if hosted.
 *
 * @flag: Pointer to the flag argument given to the vmware driver's
 * DriverFunc function, when operation is GET_REQUIRED_HW_INTERFACES.
 *
 * Checks whether we are running hosted, and in that case modifies
 * the flag according to the hosted environment's requirements.
 */
void
vmwgfx_hosted_modify_flags(uint32_t *flags)
{
}
07070100000043000081A400000000000000000000000161A68E1200001F91000000000000000000000000000000000000003300000000xf86-video-vmware-13.3.0+12/vmwgfx/vmwgfx_hosted.h/*
 * Copyright 2013 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>
 * Note: "Hosted" is a term stolen from the xf86-video-intel driver.
 */

#ifndef _VMWGFX_HOSTED_H
#define _VMWGFX_HOSTED_H

#include <xorg-server.h>
#include <xf86.h>


/**
 * struct vmwgfx_hosted - hosting environment private information.
 *
 * This struct is completely opaque to callers and should be defined
 * by the hosting environment.
 */
struct vmwgfx_hosted;

/**
 * struct vmwgfx-hosted-driver - Driver for environments that we can run
 * hosted under.
 *
 * @create: Initialize and create an opaque struct vmwgfx_hosted with
 * environment private information. Should return NULL on failure.
 * @destroy: Undo what's done in @create.
 * @drm_fd: Return a file descriptor opened to DRM.
 * @pre_init: Callback from vmwgfx preInit.
 * @screen_init: Callback from vmwgfx screenInit.
 * @screen_close: Callback from vmwgfx screenClose.
 * @post_damage: Callback from vmwgfx blockHandler. This callback should
 * instruct the hosting environment about damaged windows.
 * @dri_auth: Authenticate a dri client.
 */
struct vmwgfx_hosted_driver {
    struct vmwgfx_hosted *(*create)(ScrnInfoPtr);
    void (*destroy)(struct vmwgfx_hosted *);
    int (*drm_fd)(struct vmwgfx_hosted *, const struct pci_device *);
    Bool (*pre_init)(struct vmwgfx_hosted *, int);
    Bool (*screen_init)(struct vmwgfx_hosted *, ScreenPtr);
    void (*screen_close)(struct vmwgfx_hosted *);
    void (*post_damage)(struct vmwgfx_hosted *);
    int (*dri_auth)(struct vmwgfx_hosted *, ClientPtr client, uint32_t magic);
};

extern const struct vmwgfx_hosted_driver *vmwgfx_hosted_detect(void);
extern void vmwgfx_hosted_modify_flags(uint32_t *flags);

/**
 * vmwgfx_is_hosted - Check whether we're running hosted.
 *
 * @driver: Pointer to a struct vmwgfx_hosted_driver as returned by
 * vmwgfx_hosted_detect()
 *
 */
static inline Bool
vmwgfx_is_hosted(const struct vmwgfx_hosted_driver *driver)
{
    return (driver != NULL);
}

/**
 * vmwgfx_hosted_create - Set up and initialize a struct vmwgfx_hosted
 *
 * @driver: Pointer to a struct vmwgfx_hosted_driver as returned by
 * vmwgfx_hosted_detect()
 * @pScrn: Pointer to a ScrnInfo structure, that has not been populated yet.
 *
 * Convenience wrapper around the hosted_driver function.
 */
static inline struct vmwgfx_hosted*
vmwgfx_hosted_create(const struct vmwgfx_hosted_driver *driver,
		     ScrnInfoPtr pScrn)
{
    if (!vmwgfx_is_hosted(driver))
	return NULL;

    return driver->create(pScrn);
}

/**
 * vmwgfx_hosted_destroy - free a struct vmwgfx_hosted and take down
 * hosted environment.
 *
 * @driver: Pointer to a struct vmwgfx_hosted_driver as returned by
 * vmwgfx_hosted_detect()
 * @hosted: Pointer to a struct vmwgfx_hosted, as returned by
 * vmwgfx_hosted_create()
 *
 * Convenience wrapper around the hosted_driver function.
 */
static inline void
vmwgfx_hosted_destroy(const struct vmwgfx_hosted_driver *driver,
		      struct vmwgfx_hosted *hosted)
{
    if (!vmwgfx_is_hosted(driver))
	return;

    driver->destroy(hosted);
}

/**
 * vmwgfx_hosted_drm_fd - Return a drm file descriptor
 *
 * @driver: Pointer to a struct vmwgfx_hosted_driver as returned by
 * vmwgfx_hosted_detect()
 * @hosted: Pointer to a struct vmwgfx_hosted, as returned by
 * vmwgfx_hosted_create()
 * @pci: Pointer to a valid struct pci_device, describing our device.
 *
 * Convenience wrapper around the hosted_driver function. Returns an
 * invalid file descriptor if we're not hosted.
 */
static inline int
vmwgfx_hosted_drm_fd(const struct vmwgfx_hosted_driver *driver,
		     struct vmwgfx_hosted *hosted,
		     const struct pci_device *pci)
{
    if (!vmwgfx_is_hosted(driver))
	return -1;

    return driver->drm_fd(hosted, pci);
}

/**
 * vmwgfx_hosted_pre_init - Initiate preInit callback.
 *
 * @driver: Pointer to a struct vmwgfx_hosted_driver as returned by
 * vmwgfx_hosted_detect()
 * @hosted: Pointer to a struct vmwgfx_hosted, as returned by
 * vmwgfx_hosted_create()
 * @flags: Flags passed to the vmwgfx preInit function
 *
 * Convenience wrapper around the hosted_driver function. Returns TRUE
 * (success) if not hosted.
 */
static inline Bool
vmwgfx_hosted_pre_init(const struct vmwgfx_hosted_driver *driver,
		       struct vmwgfx_hosted *hosted, int flags)
{
    if (!vmwgfx_is_hosted(driver))
	return TRUE;

    return driver->pre_init(hosted, flags);
}

/**
 * vmwgfx_hosted_screen_init - Initiate screenInit callback.
 *
 * @driver: Pointer to a struct vmwgfx_hosted_driver as returned by
 * vmwgfx_hosted_detect()
 * @hosted: Pointer to a struct vmwgfx_hosted, as returned by
 * vmwgfx_hosted_create()
 * @pScreen: ScreenPtr identifying the screen we're setting up.
 *
 * Convenience wrapper around the hosted_driver function. Returns TRUE
 * (success) if not hosted.
 */
static inline Bool
vmwgfx_hosted_screen_init(const struct vmwgfx_hosted_driver *driver,
			  struct vmwgfx_hosted *hosted, ScreenPtr pScreen)
{
    if (!vmwgfx_is_hosted(driver))
	return TRUE;

    return driver->screen_init(hosted, pScreen);
}

/**
 * vmwgfx_hosted_screen_close - Initiate screenClose callback.
 *
 * @driver: Pointer to a struct vmwgfx_hosted_driver as returned by
 * vmwgfx_hosted_detect()
 * @hosted: Pointer to a struct vmwgfx_hosted, as returned by
 * vmwgfx_hosted_create()
 *
 * Convenience wrapper around the hosted_driver function.
 * Does nothing if not hosted.
 */
static inline void
vmwgfx_hosted_screen_close(const struct vmwgfx_hosted_driver *driver,
			   struct vmwgfx_hosted *hosted)
{
    if (!vmwgfx_is_hosted(driver))
	return;

    driver->screen_close(hosted);
}

/**
 * vmwgfx_hosted_post_damage - Inform the hosting environment about
 * recent rendering
 *
 * @driver: Pointer to a struct vmwgfx_hosted_driver as returned by
 * vmwgfx_hosted_detect()
 * @hosted: Pointer to a struct vmwgfx_hosted, as returned by
 * vmwgfx_hosted_create()
 *
 * Convenience wrapper around the hosted_driver function.
 * Does nothing if not hosted.
 */
static inline void
vmwgfx_hosted_post_damage(const struct vmwgfx_hosted_driver *driver,
			  struct vmwgfx_hosted *hosted)
{
    if (!vmwgfx_is_hosted(driver))
	return;

    driver->post_damage(hosted);
}

/**
 * vmwgfx_hosted_dri_auth - Ask the hosting environment to authenticate a
 * dri client.
 *
 * @driver: Pointer to a struct vmwgfx_hosted_driver as returned by
 * vmwgfx_hosted_detect()
 * @hosted: Pointer to a struct vmwgfx_hosted, as returned by
 * vmwgfx_hosted_create()
 * @client: The client to be authenticated
 * @magic: The drm magic used for authentication
 *
 * Convenience wrapper around the hosted_driver function.
 * Does nothing if not hosted.
 */
static inline int
vmwgfx_hosted_dri_auth(const struct vmwgfx_hosted_driver *driver,
		       struct vmwgfx_hosted *hosted,
		       ClientPtr client,
		       uint32_t magic)
{
    return driver->dri_auth(hosted, client, magic);
}
#endif /* _VMWGFX_HOSTED_H */
07070100000044000081A400000000000000000000000161A68E1200001E52000000000000000000000000000000000000003300000000xf86-video-vmware-13.3.0+12/vmwgfx/vmwgfx_layout.c/**************************************************************************
 * Copyright © 2016 VMware, Inc., Palo Alto, CA., USA
 * 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
 * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM,
 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
 * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
 * USE OR OTHER DEALINGS IN THE SOFTWARE.
 *
 **************************************************************************/

#ifdef HAVE_CONFIG_H
#include "config.h"
#endif

#ifdef HAVE_LIBUDEV
#include "vmwgfx_driver.h"
#include <xf86Crtc.h>
#include "vmwgfx_rr_inlines.h"
#include "../src/common_compat.h"

#ifndef X_DEBUG
#define X_DEBUG X_NOTICE
#endif

/**
 * struct vmwgfx_layout_box - Struct representing a GUI layout rect
 *
 * @x: X value of the origin.
 * @y: Y value of the origin.
 * @width: Width of the rect.
 * @height: Height of the rect.
 */
struct vmwgfx_layout_box {
    int x, y, width, height;
};

/**
 * struct vmwgfx_layout - Struct representing a complete GUI layout
 *
 * @connected: Number of connected outputs.
 * @root_width: Width of full desktop.
 * @root_height: Height of full desktop.
 * @boxes: Array of GUI layout rects.
 */
struct vmwgfx_layout {
    int connected;
    int root_width;
    int root_height;
    struct vmwgfx_layout_box boxes[];
};

/**
 * vmwgfx_layout_debug - Log debug info of a layout struct.
 *
 * @pScrn: ScrnInfoPtr: Pointer to the ScrnInfo struct for the screen the
 * layout should be logged for.
 * @l1: Pointer to a valid struct vmwgfx_layout.
 */
static void
vmwgfx_layout_debug(ScrnInfoPtr pScrn, const struct vmwgfx_layout *l1)
{
    int i;

    xf86DrvMsg(pScrn->scrnIndex, X_DEBUG, "New layout.\n");
    for (i = 0; i < l1->connected; ++i)
	xf86DrvMsg(pScrn->scrnIndex, X_DEBUG,
		   "%d: %d %d %d %d\n", i, l1->boxes[i].x,
		   l1->boxes[i].y, l1->boxes[i].width, l1->boxes[i].height);
    xf86DrvMsg(pScrn->scrnIndex, X_DEBUG, "\n");
}

/**
 * vmwgfx_layouts_equal - Determine whether two layouts are equal.
 *
 * @l1: Pointer to the first struct vmwgfx_layout.
 * @l2: Pointer to the second struct vmwgfx_layout.
 *
 * Returns: TRUE if the layouts are equal. FALSE otherwise.
 */
static Bool
vmwgfx_layouts_equal(const struct vmwgfx_layout *l1,
		     const struct vmwgfx_layout *l2)
{
    if (l1->connected != l2->connected)
	return FALSE;

    if (!l1->connected)
	return TRUE;

    return !memcmp(l1->boxes, l2->boxes,
		   l1->connected*sizeof(struct vmwgfx_layout_box));
}

/**
 * vmwgfx_layout_from_kms - Construct a struct vmwgfx_layout from KMS info.
 *
 * @pScrn: Pointer to a ScrnInfo struct.
 *
 * Returns: A pointer to a newly allocated struct vmwgfx_layout if
 * successful. NULL otherwise.
 */
struct vmwgfx_layout *
vmwgfx_layout_from_kms(ScrnInfoPtr pScrn)
{
    xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(pScrn);
    int i, connected;
    struct vmwgfx_layout *layout;
    size_t size;
    int min_x = INT_MAX, max_x = INT_MIN, min_y = INT_MAX, max_y = INT_MIN;

    for (i = 0; i < config->num_output; ++i) {
	xf86OutputPtr output = config->output[i];

	if (!vmwgfx_output_has_origin(output))
	    return NULL;

	if (output->status != XF86OutputStatusConnected)
	    break;
    }
    connected = i;

    size = offsetof(struct vmwgfx_layout, boxes) +
	connected * sizeof(struct vmwgfx_layout_box);
    layout = calloc(1, size);
    if (!layout)
	return NULL;

    layout->connected = connected;
    for (i = 0; i < connected; ++i) {
	struct vmwgfx_layout_box *box = &layout->boxes[i];
	xf86OutputPtr output = config->output[i];
	DisplayModePtr mode = output->probed_modes;

	if (mode == NULL) {
	    free(layout);
	    return NULL;
	}

	vmwgfx_output_origin(output, &box->x, &box->y);
	box->width = output->probed_modes->HDisplay;
	box->height = output->probed_modes->VDisplay;
	min_x = min(min_x, box->x);
	min_y = min(min_y, box->y);
	max_x = max(max_x, box->x + box->width);
	max_y = max(max_y, box->y + box->height);
    }

    layout->root_width = max_x;
    layout->root_height = max_y;

    return layout;
}

/**
 * vmwgfx_layout_configuration - Set up the screen modesetting configuration
 * from a struct vmwgfx_layout.
 *
 * @pScrn: Pointer to a ScrnInfo struct.
 * @layout: Layout to use for the new configuration.
 *
 * Sets up a new modesetting configuration. Note that the configuration needs
 * to be committed using xf86SetDesiredModes().
 */
void
vmwgfx_layout_configuration(ScrnInfoPtr pScrn, struct vmwgfx_layout *layout)
{
    xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(pScrn);
    struct vmwgfx_layout_box *box;
    xf86OutputPtr output;
    xf86CrtcPtr crtc;
    int i, j;

    for (j = 0; j < config->num_crtc; ++j) {
	crtc = config->crtc[j];
	crtc->enabled = FALSE;
    }

    for (i = 0, box = layout->boxes; i < config->num_output; ++i, ++box) {
	output = config->output[i];
	output->crtc = NULL;
	if (i >= layout->connected)
	    continue;

	for (j = 0; j < config->num_crtc; ++j) {
	    crtc = config->crtc[j];
	    if (!crtc->enabled && (output->possible_crtcs & (1 << j))) {
		crtc->enabled = TRUE;
		output->crtc = crtc;
		break;
	    }
	}

	if (!output->crtc)
	    continue;

	crtc = output->crtc;
	xf86SaveModeContents(&crtc->desiredMode, output->probed_modes);
	crtc->desiredRotation = RR_Rotate_0;
	crtc->desiredX = box->x;
	crtc->desiredY = box->y;
	crtc->desiredTransformPresent = FALSE;
    }
}

/**
 * vmwgfx_layout_handler - Obtain and set a new layout.
 *
 * @pScrn: Pointer to a ScrnInfo struct.
 *
 * Obtains a new layout from DRM. If the layout differs from the current one,
 * Try to set the new layout. If that fails, (typically due to root pixmap
 * resizing issues) try hard to revert to the old layout. Finally
 * update RandR in a way that tries to block racing display managers
 * from setting up the layout in a different way.
 */
void
vmwgfx_layout_handler(ScrnInfoPtr pScrn)
{

    ScreenPtr pScreen = xf86ScrnToScreen(pScrn);
    modesettingPtr ms = modesettingPTR(pScrn);
    struct vmwgfx_layout *layout;

    if (!pScreen)
	return;

    /*
     * Construct a layout from the new information and determine whether we
     * need to take action
     */
    layout = vmwgfx_layout_from_kms(pScrn);
    if (layout && (!ms->layout || !vmwgfx_layouts_equal(ms->layout, layout))) {
	vmwgfx_layout_debug(pScrn, layout);
	vmwgfx_outputs_off(pScrn);
	xf86DisableUnusedFunctions(pScrn);
	if (!vmwgfx_rr_screen_set_size(pScreen, layout->root_width,
				       layout->root_height)) {
	    xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Resizing screen failed.\n");
	    vmwgfx_outputs_on(pScrn);
	    free(layout);
	} else {
	    vmwgfx_layout_configuration(pScrn, layout);
	    if (ms->layout)
	      free(ms->layout);
	    ms->layout = layout;
	}
	xf86SetDesiredModes(pScrn);
	vmwgfx_notify_rr(pScreen);
    } else if (layout) {
	free(layout);
    }
}

#endif /* HAVE_LIBUDEV */
07070100000045000081A400000000000000000000000161A68E1200005BB5000000000000000000000000000000000000003300000000xf86-video-vmware-13.3.0+12/vmwgfx/vmwgfx_output.c/*
 * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas.
 * 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: Alan Hourihane <alanh@tungstengraphics.com>
 * Author: Jakob Bornecrantz <wallbraker@gmail.com>
 *
 */
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif

#include "xorg-server.h"
#include <xf86drm.h>
#include <xf86str.h>
#include <randrstr.h>
#include <xf86Crtc.h>
#include <X11/Xatom.h>
#include <dix.h>

#ifdef HAVE_XEXTPROTO_71
#include <X11/extensions/dpmsconst.h>
#else
#define DPMS_SERVER
#include <X11/extensions/dpms.h>
#endif

#include "vmwgfx_driver.h"

/**
 * struct output_prop - Structure representing an output property.
 *
 * @mode_prop: Pointer to the corresponding drmModeProperty or
 * NULL if the property doesn't have a DRM counterpart.
 * @value: The value of the property.
 * @num_atoms: Number of atoms in the @atoms array.
 * @atoms: Atoms used by this poperty.
 * @index: Index into the drm connector prop_values array.
 */
struct output_prop {
    drmModePropertyPtr mode_prop;
    uint64_t value;
    int num_atoms;
    Atom *atoms;
    int index;
};

struct output_private
{
    drmModeConnectorPtr drm_connector;
    int num_props;
    struct output_prop *props;
    int c;
    int suggested_x;
    int suggested_y;
    int implicit_placement;
    xf86CrtcPtr saved_crtc;
    Bool saved_crtc_enabled;
};

static const char *output_enum_list[] = {
    "Unknown",
    "VGA",
    "DVI",
    "DVI",
    "DVI",
    "Composite",
    "SVIDEO",
    "LVDS",
    "CTV",
    "DIN",
    "DP",
    "HDMI",
    "HDMI",
    "TV",
    "EDP",
    "Virtual",
};

/**
 * vmwgfx_output_has_origin - Whether we've detected layout info on the DRM
 * connector.
 *
 * @output: The output to consider.
 *
 * Returns: TRUE if the corresponding DRM connector has layout info.
 * FALSE otherwise.
 */
Bool
vmwgfx_output_has_origin(xf86OutputPtr output)
{
    struct output_private *vmwgfx_output = output->driver_private;

    return vmwgfx_output->suggested_x != -1 &&
	vmwgfx_output->suggested_y != -1;
}

/**
 * vmwgfx_output_origin - Get the origin for an output in the GUI layout.
 *
 * @output: The output to consider.
 * @x: Outputs the x coordinate of the origin.
 * @y: Outputs the y coordinate of the origin.
 */
void
vmwgfx_output_origin(xf86OutputPtr output, int *x, int *y)
{
    struct output_private *vmwgfx_output = output->driver_private;

    *x = vmwgfx_output->props[vmwgfx_output->suggested_x].value;
    *y = vmwgfx_output->props[vmwgfx_output->suggested_y].value;
}

/**
 * vmwgfx_output_is_implicit - Whether an output uses implicit placement
 *
 * output: The output to consider.
 *
 * Returns: TRUE if the output uses implicit placement. False otherwise.
 */
static Bool
vmwgfx_output_is_implicit(xf86OutputPtr output)
{
    struct output_private *vmwgfx_output = output->driver_private;

    if (vmwgfx_output->implicit_placement == -1)
	return TRUE;

    return !!vmwgfx_output->props[vmwgfx_output->implicit_placement].value;
}

/**
 * output_property_ignore - Function to determine whether to ignore or
 * to re-export a drm property.
 *
 * @prop: Pointer to the drmModeProperty to consider
 *
 * RETURNS: TRUE if the property should be re-exported. FALSE otherwise.
 */
static Bool
output_property_ignore(drmModePropertyPtr prop)
{
    if (!prop)
	return TRUE;
    /* ignore blob prop */
    if (prop->flags & DRM_MODE_PROP_BLOB)
	return TRUE;
    /* ignore standard property */
    if (!strcmp(prop->name, "EDID") ||
	!strcmp(prop->name, "DPMS") ||
	!strcmp(prop->name, "dirty"))
	return TRUE;

    return FALSE;
}

static void
output_create_resources(xf86OutputPtr output)
{
    modesettingPtr ms = modesettingPTR(output->scrn);
    struct output_private *vmwgfx_output = output->driver_private;
    drmModeConnectorPtr drm_connector = vmwgfx_output->drm_connector;
    drmModePropertyPtr drmmode_prop;
    int i, j, err;

    vmwgfx_output->props = calloc(drm_connector->count_props,
				  sizeof(struct output_prop));
    if (!vmwgfx_output->props)
	return;

    vmwgfx_output->num_props = 0;
    for (i = 0, j = 0; i < drm_connector->count_props; i++) {
	drmmode_prop = drmModeGetProperty(ms->fd, drm_connector->props[i]);
	if (output_property_ignore(drmmode_prop)) {
	    drmModeFreeProperty(drmmode_prop);
	    continue;
	}
	vmwgfx_output->props[j].index = i;
	vmwgfx_output->props[j].mode_prop = drmmode_prop;
	vmwgfx_output->props[j].value = drm_connector->prop_values[i];
	if (!strcmp(drmmode_prop->name,"suggested X"))
	    vmwgfx_output->suggested_x = j;
	if (!strcmp(drmmode_prop->name,"suggested Y"))
	    vmwgfx_output->suggested_y = j;
	if (!strcmp(drmmode_prop->name,"implicit_placement"))
	    vmwgfx_output->implicit_placement = j;
	vmwgfx_output->num_props++;
	j++;
    }

    for (i = 0; i < vmwgfx_output->num_props; i++) {
	struct output_prop *p = &vmwgfx_output->props[i];
	drmmode_prop = p->mode_prop;

	if (drmmode_prop->flags & DRM_MODE_PROP_RANGE) {
	    INT32 qrange[2];
	    INT32 value = p->value;

	    p->num_atoms = 1;
	    p->atoms = calloc(p->num_atoms, sizeof(Atom));
	    if (!p->atoms)
		continue;
	    p->atoms[0] = MakeAtom(drmmode_prop->name, strlen(drmmode_prop->name), TRUE);
	    qrange[0] = drmmode_prop->values[0];
	    qrange[1] = drmmode_prop->values[1];
	    err = RRConfigureOutputProperty(output->randr_output, p->atoms[0],
		    FALSE, TRUE,
		    drmmode_prop->flags & DRM_MODE_PROP_IMMUTABLE ? TRUE : FALSE,
		    2, qrange);
	    if (err != 0) {
		xf86DrvMsg(output->scrn->scrnIndex, X_ERROR,
			"RRConfigureOutputProperty error, %d\n", err);
	    }
	    err = RRChangeOutputProperty(output->randr_output, p->atoms[0],
		    XA_INTEGER, 32, PropModeReplace, 1, &value, FALSE, TRUE);
	    if (err != 0) {
		xf86DrvMsg(output->scrn->scrnIndex, X_ERROR,
			"RRChangeOutputProperty error, %d\n", err);
	    }
	} else if (drmmode_prop->flags & DRM_MODE_PROP_ENUM) {
	    p->num_atoms = drmmode_prop->count_enums + 1;
	    p->atoms = calloc(p->num_atoms, sizeof(Atom));
	    if (!p->atoms)
		continue;
	    p->atoms[0] = MakeAtom(drmmode_prop->name, strlen(drmmode_prop->name), TRUE);
	    for (j = 1; j <= drmmode_prop->count_enums; j++) {
		struct drm_mode_property_enum *e = &drmmode_prop->enums[j-1];
		p->atoms[j] = MakeAtom(e->name, strlen(e->name), TRUE);
	    }
	    err = RRConfigureOutputProperty(output->randr_output, p->atoms[0],
		    FALSE, FALSE,
		    drmmode_prop->flags & DRM_MODE_PROP_IMMUTABLE ? TRUE : FALSE,
		    p->num_atoms - 1, (INT32 *)&p->atoms[1]);
	    if (err != 0) {
		xf86DrvMsg(output->scrn->scrnIndex, X_ERROR,
			"RRConfigureOutputProperty error, %d\n", err);
	    }
	    for (j = 0; j < drmmode_prop->count_enums; j++)
		if (drmmode_prop->enums[j].value == p->value)
		    break;
	    /* there's always a matching value */
	    err = RRChangeOutputProperty(output->randr_output, p->atoms[0],
		    XA_ATOM, 32, PropModeReplace, 1, &p->atoms[j+1], FALSE, TRUE);
	    if (err != 0) {
		xf86DrvMsg(output->scrn->scrnIndex, X_ERROR,
			"RRChangeOutputProperty error, %d\n", err);
	    }
	}
    }
}

static void
output_dpms(xf86OutputPtr output, int mode)
{
}

static xf86OutputStatus
output_detect(xf86OutputPtr output)
{
    modesettingPtr ms = modesettingPTR(output->scrn);
    struct output_private *priv = output->driver_private;
    drmModeConnectorPtr drm_connector;
    xf86OutputStatus status;

    drm_connector = drmModeGetConnector(ms->fd, priv->drm_connector->connector_id);
    if (drm_connector) {
	drmModeFreeConnector(priv->drm_connector);
	priv->drm_connector = drm_connector;
    } else {
	drm_connector = priv->drm_connector;
    }

    switch (drm_connector->connection) {
    case DRM_MODE_CONNECTED:
	status = XF86OutputStatusConnected;
	break;
    case DRM_MODE_DISCONNECTED:
	status = XF86OutputStatusDisconnected;
	break;
    default:
	status = XF86OutputStatusUnknown;
    }

    return status;
}

static DisplayModePtr
output_get_modes(xf86OutputPtr output)
{
    struct output_private *priv = output->driver_private;
    drmModeConnectorPtr drm_connector = priv->drm_connector;
    drmModeModeInfoPtr drm_mode = NULL;
    DisplayModePtr modes = NULL, mode = NULL;
    int i;

    for (i = 0; i < drm_connector->count_modes; i++) {
	drm_mode = &drm_connector->modes[i];
	if (drm_mode) {
	    mode = calloc(1, sizeof(DisplayModeRec));
	    if (!mode)
		continue;
	    mode->Clock = drm_mode->clock;
	    mode->HDisplay = drm_mode->hdisplay;
	    mode->HSyncStart = drm_mode->hsync_start;
	    mode->HSyncEnd = drm_mode->hsync_end;
	    mode->HTotal = drm_mode->htotal;
	    mode->VDisplay = drm_mode->vdisplay;
	    mode->VSyncStart = drm_mode->vsync_start;
	    mode->VSyncEnd = drm_mode->vsync_end;
	    mode->VTotal = drm_mode->vtotal;
	    mode->Flags = drm_mode->flags;
	    mode->HSkew = drm_mode->hskew;
	    mode->VScan = drm_mode->vscan;
	    mode->VRefresh = xf86ModeVRefresh(mode);
	    mode->Private = (void *)drm_mode;
	    mode->type = 0;
	    if (drm_mode->type & DRM_MODE_TYPE_PREFERRED)
		mode->type |= M_T_PREFERRED;
	    if (drm_mode->type & DRM_MODE_TYPE_DRIVER)
		mode->type |= M_T_DRIVER;
	    xf86SetModeDefaultName(mode);
	    modes = xf86ModesAdd(modes, mode);
	}
    }

    return modes;
}

static int
output_mode_valid(xf86OutputPtr output, DisplayModePtr pMode)
{
  //    modesettingPtr ms = modesettingPTR(output->scrn);
    //    CustomizerPtr cust = ms->cust;

#if 0
    if (cust && cust->winsys_check_fb_size &&
	!cust->winsys_check_fb_size(cust, pMode->HDisplay *
				    output->scrn->bitsPerPixel / 8,
				    pMode->VDisplay))
	return MODE_BAD;
#endif
    return MODE_OK;
}

#ifdef RANDR_12_INTERFACE
static Bool
output_set_property(xf86OutputPtr output, Atom property, RRPropertyValuePtr value)
{
    modesettingPtr ms = modesettingPTR(output->scrn);
    struct output_private *vmwgfx_output = output->driver_private;
    int i;

    for (i = 0; i < vmwgfx_output->num_props; i++) {
	struct output_prop *p = &vmwgfx_output->props[i];

	if (p->atoms[0] != property)
	    continue;

	if (p->mode_prop->flags & DRM_MODE_PROP_RANGE) {
	    uint32_t val;

	    if (value->type != XA_INTEGER || value->format != 32 ||
		    value->size != 1)
		return FALSE;
	    val = *(uint32_t *)value->data;
	    p->value = val;
	    drmModeConnectorSetProperty
		(ms->fd, vmwgfx_output->drm_connector->connector_id,
		 p->mode_prop->prop_id, (uint64_t)val);
	    return TRUE;
	} else if (p->mode_prop->flags & DRM_MODE_PROP_ENUM) {
	    Atom	atom;
	    const char	*name;
	    int		j;

	    if (value->type != XA_ATOM || value->format != 32 || value->size != 1)
		return FALSE;
	    memcpy(&atom, value->data, 4);
	    name = NameForAtom(atom);

	    /* search for matching name string, then set its value down */
	    for (j = 0; j < p->mode_prop->count_enums; j++) {
		if (!strcmp(p->mode_prop->enums[j].name, name)) {
		    p->value = p->mode_prop->enums[j].value;
		    drmModeConnectorSetProperty
			(ms->fd, vmwgfx_output->drm_connector->connector_id,
			 p->mode_prop->prop_id, p->value);
		    return TRUE;
		}
	    }
	}
    }

    return TRUE;
}
#endif /* RANDR_12_INTERFACE */

/**
 * vmwgfx_output_property_scan - Update a single property on a single output
 * @output: Pointer to the output to consider.
 * @p: The property to update.
 *
 * Reads the property value from the drm connector corresponding to
 * @output and notifies the RandR code of the new value, sending out an
 * event if the new value doesn't match the old one. Finally updates @p
 * with the new value.
 */
static Bool
vmwgfx_output_property_scan(xf86OutputPtr output,
			    struct output_prop *p)
{
    struct output_private *vmwgfx_output = output->driver_private;
    uint32_t value = vmwgfx_output->drm_connector->prop_values[p->index];
    int err = 0;

#ifdef RANDR_13_INTERFACE
    if (p->mode_prop->flags & DRM_MODE_PROP_RANGE) {
	err = RRChangeOutputProperty(output->randr_output,
				     p->atoms[0], XA_INTEGER, 32,
				     PropModeReplace, 1, &value,
				     value != p->value, FALSE);
    } else if (p->mode_prop->flags & DRM_MODE_PROP_ENUM) {
	int j;

	/* search for matching name string, then set its value down */
	for (j = 0; j < p->mode_prop->count_enums; j++) {
	    if (p->mode_prop->enums[j].value == value)
		break;
	}

	err = RRChangeOutputProperty(output->randr_output, p->atoms[0],
				     XA_ATOM, 32, PropModeReplace, 1,
				     &p->atoms[j+1], value != p->value,
				     FALSE);
    }
#endif /* RANDR_13_INTERFACE */
    if (!err)
	p->value = value;

    return !err;
}

#ifdef RANDR_13_INTERFACE
static Bool
output_get_property(xf86OutputPtr output, Atom property)
{
    modesettingPtr ms = modesettingPTR(output->scrn);
    struct output_private *vmwgfx_output = output->driver_private;
    int i;

    if (output->scrn->vtSema) {
	drmModeConnectorPtr drm_connector =
	    drmModeGetConnector(ms->fd,
				vmwgfx_output->drm_connector->connector_id);

	if (drm_connector) {
	    drmModeFreeConnector(vmwgfx_output->drm_connector);
	    vmwgfx_output->drm_connector = drm_connector;
	}
    }

    for (i = 0; i < vmwgfx_output->num_props; i++) {
	struct output_prop *p = &vmwgfx_output->props[i];
	if (p->atoms[0] != property)
	    continue;

	return vmwgfx_output_property_scan(output, p);
    }

    return FALSE;
}
#endif /* RANDR_13_INTERFACE */

static void
output_destroy(xf86OutputPtr output)
{
    struct output_private *priv = output->driver_private;
    int i;

    for (i = 0; i < priv->num_props; i++) {
	drmModeFreeProperty(priv->props[i].mode_prop);
	free(priv->props[i].atoms);
    }
    free(priv->props);

    drmModeFreeConnector(priv->drm_connector);
    free(priv);
    output->driver_private = NULL;
}

static const xf86OutputFuncsRec output_funcs = {
    .create_resources = output_create_resources,
#ifdef RANDR_12_INTERFACE
    .set_property = output_set_property,
#endif
#ifdef RANDR_13_INTERFACE
    .get_property = output_get_property,
#endif
    .dpms = output_dpms,
    .detect = output_detect,

    .get_modes = output_get_modes,
    .mode_valid = output_mode_valid,
    .destroy = output_destroy,
};

/**
 * vmwgfx_output_explicit_overlap -- Check for explicit output overlaps
 *
 * This function returns TRUE iff the bounding box in screen space of an
 * exlplicit output overlaps the bounding box in screen space of any other
 * output.
 */
Bool
vmwgfx_output_explicit_overlap(ScrnInfoPtr pScrn)
{
    xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(pScrn);
    xf86OutputPtr output;
    ScreenPtr pScreen = pScrn->pScreen;
    RegionRec output_union;
    RegionRec cur_output;
    RegionRec result;
    xf86CrtcPtr crtc;
    Bool overlap = FALSE;
    int i;

    (void) pScreen;
    REGION_NULL(pScreen, &output_union);
    REGION_NULL(pScreen, &cur_output);
    REGION_NULL(pScreen, &result);

    /*
     * Collect a region of implicit outputs. These may overlap.
     */
    for (i = 0; i < config->num_output; i++) {
	output = config->output[i];
	crtc = output->crtc;

	if (!crtc || !crtc->enabled || !vmwgfx_output_is_implicit(output))
	    continue;

	REGION_RESET(pScreen, &cur_output, &crtc->bounds);
	REGION_UNION(pScreen, &output_union, &output_union, &cur_output);
    }

    /*
     * Explicit outputs may not overlap any other output.
     */
    for (i = 0; i < config->num_output; i++) {
	output = config->output[i];
	crtc = output->crtc;

	if (!crtc || !crtc->enabled || vmwgfx_output_is_implicit(output))
	    continue;

	REGION_RESET(pScreen, &cur_output, &crtc->bounds);
	REGION_NULL(pScreen, &result);
	REGION_INTERSECT(pScreen, &result, &output_union, &cur_output);
	overlap = REGION_NOTEMPTY(vsaa->pScreen, &result);
	if (overlap)
	    break;

	REGION_UNION(pScreen, &output_union, &output_union, &cur_output);
    }

    REGION_UNINIT(pScreen, &output_union);
    REGION_UNINIT(pScreen, &cur_output);
    REGION_UNINIT(pScreen, &result);

    return overlap;
}

void
xorg_output_init(ScrnInfoPtr pScrn)
{
    modesettingPtr ms = modesettingPTR(pScrn);
    xf86OutputPtr output;
    drmModeResPtr res;
    drmModeConnectorPtr drm_connector = NULL;
    drmModeEncoderPtr drm_encoder = NULL;
    struct output_private *priv;
    char name[32];
    int c;

    res = drmModeGetResources(ms->fd);
    if (res == 0) {
	DRV_ERROR("Failed drmModeGetResources\n");
	return;
    }

    for (c = 0; c < res->count_connectors; c++) {
	drm_connector = drmModeGetConnector(ms->fd, res->connectors[c]);
	if (!drm_connector)
	    goto out;

	if (drm_connector->connector_type >=
	    sizeof(output_enum_list) / sizeof(output_enum_list[0]))
	    drm_connector->connector_type = 0;

	snprintf(name, 32, "%s%d",
		 output_enum_list[drm_connector->connector_type],
		 drm_connector->connector_type_id);


	priv = calloc(sizeof(*priv), 1);
	if (!priv) {
	    continue;
	}

	output = xf86OutputCreate(pScrn, &output_funcs, name);
	if (!output) {
	    free(priv);
	    continue;
	}

	priv->suggested_x = -1;
	priv->suggested_y = -1;
	priv->implicit_placement = -1;

	drm_encoder = drmModeGetEncoder(ms->fd, drm_connector->encoders[0]);
	if (drm_encoder) {
	    output->possible_crtcs = drm_encoder->possible_crtcs;
	    output->possible_clones = drm_encoder->possible_clones;
	    drmModeFreeEncoder(drm_encoder);
	} else {
	    output->possible_crtcs = 0;
	    output->possible_clones = 0;
	}
	priv->c = c;
	priv->drm_connector = drm_connector;
	output->driver_private = priv;
	output->subpixel_order = SubPixelHorizontalRGB;
	output->interlaceAllowed = FALSE;
	output->doubleScanAllowed = FALSE;
    }

  out:
    drmModeFreeResources(res);
}

unsigned
xorg_output_get_id(xf86OutputPtr output)
{
    struct output_private *priv = output->driver_private;
    return priv->drm_connector->connector_id;
}

#ifdef HAVE_LIBUDEV

/**
 * vmwgfx_output_properties_scan - Update all properties on all outputs
 * on this screen.
 * @pScrn: Pointer to the ScrnInfo structure for this screen.
 *
 * Updates all connector info from DRM and then calls
 * vmwgfx_output_property_scan() for all properties on all connectors.
 */
static void
vmwgfx_output_properties_scan(ScrnInfoPtr pScrn)
{
    xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(pScrn);
    modesettingPtr ms = modesettingPTR(pScrn);
    int i;

    for (i = 0; i < config->num_output; i++) {
	xf86OutputPtr output = config->output[i];
	struct output_private *vmwgfx_output = output->driver_private;
	int j;

	if (output->scrn->vtSema) {
	    int id = vmwgfx_output->drm_connector->connector_id;

	    if (vmwgfx_output->drm_connector)
		drmModeFreeConnector(vmwgfx_output->drm_connector);
	    vmwgfx_output->drm_connector = drmModeGetConnector(ms->fd, id);
	}

	if (!vmwgfx_output->drm_connector)
	    continue;

	for (j = 0; j < vmwgfx_output->num_props; j++) {
	    struct output_prop *p = &vmwgfx_output->props[j];

	    (void) vmwgfx_output_property_scan(output, p);
	}
    }
}

/**
 * vmwgfx_outputs_off - Mark all crtc / output pairs as disabled and save
 * their configuration.
 *
 * @pScrn: Pointer to a ScrnInfo struct.
 *
 * Note that to commit this to the display system, a call to this function
 * should be followed by a call to xf86DisableUnusedFunctions()
 */
void
vmwgfx_outputs_off(ScrnInfoPtr pScrn)
{
    xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(pScrn);
    int i;

    for (i = 0; i < config->num_output; ++i) {
	xf86OutputPtr output = config->output[i];
	struct output_private *vmwgfx_output = output->driver_private;

	vmwgfx_output->saved_crtc = output->crtc;
	if (output->crtc) {
	    vmwgfx_output->saved_crtc_enabled = output->crtc->enabled;
	    output->crtc->enabled = FALSE;
	    output->crtc = NULL;
	}
    }
}

/**
 * vmwgfx_outputs_on - Reset crtc / output pairs to a configuation saved
 * using vmwgfx_output_off.
 *
 * @pScrn: Pointer to a ScrnInfo struct.
 *
 * Note that to commit the setup to the display system, a call to this
 * function should be followed by a call to xf86SetDesiredModes().
 */
void
vmwgfx_outputs_on(ScrnInfoPtr pScrn)
{
    xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(pScrn);
    int i;

    for (i = 0; i < config->num_output; ++i) {
	xf86OutputPtr output = config->output[i];
	struct output_private *vmwgfx_output = output->driver_private;

	if (vmwgfx_output->saved_crtc) {
	    output->crtc = vmwgfx_output->saved_crtc;
	    output->crtc->enabled = vmwgfx_output->saved_crtc_enabled;
	}
    }
}

/**
 * vmwgfx_handle uevent - Property update callback
 *
 * @fd: File descriptor for the uevent
 * @closure: Pointer to the driver-private per-screen data cast to a void *
 */
static void
vmwgfx_handle_uevents(int fd, void *closure)
{
    ScrnInfoPtr scrn = closure;
    modesettingPtr ms = modesettingPTR(scrn);
    struct udev_device *dev;
    ScreenPtr pScreen = xf86ScrnToScreen(scrn);

    dev = udev_monitor_receive_device(ms->uevent_monitor);
    if (!dev)
	return;

    /* Read new properties, connection status and preferred modes from DRM. */
    vmwgfx_output_properties_scan(scrn);

    if (pScreen)
	RRGetInfo(pScreen, TRUE);

    if (ms->autoLayout)
	vmwgfx_layout_handler(scrn);

    udev_device_unref(dev);
}
#endif  /* HAVE_LIBUDEV */

/**
 * vmwgfx_uevent_init - Initialize the property update monitor
 *
 * @scrn: Pointer to the ScrnInfo for this screen
 * @ms: Pointer to the driver private per-screen data
 */
void vmwgfx_uevent_init(ScrnInfoPtr scrn, modesettingPtr ms)
{
#ifdef HAVE_LIBUDEV
    struct udev *u;
    struct udev_monitor *mon;

    u = udev_new();
    if (!u)
	return;
    mon = udev_monitor_new_from_netlink(u, "udev");
    if (!mon) {
	udev_unref(u);
	return;
    }

    if (udev_monitor_filter_add_match_subsystem_devtype(mon,
							"drm",
							"drm_minor") < 0 ||
	udev_monitor_enable_receiving(mon) < 0) {
	udev_monitor_unref(mon);
	udev_unref(u);
	return;
    }

    ms->uevent_handler = xf86AddGeneralHandler(udev_monitor_get_fd(mon),
					       vmwgfx_handle_uevents,
					       scrn);

    ms->uevent_monitor = mon;
#endif  /* HAVE_LIBUDEV */
}

/**
 * vmwgfx_uevent_fini - Close the property update monitor
 *
 * @scrn: Pointer to the ScrnInfo for this screen
 * @ms: Pointer to the driver private per-screen data
 */
void vmwgfx_uevent_fini(ScrnInfoPtr scrn, modesettingPtr ms)
{
#ifdef HAVE_LIBUDEV
    if (ms->uevent_handler) {
	struct udev *u = udev_monitor_get_udev(ms->uevent_monitor);

	xf86RemoveGeneralHandler(ms->uevent_handler);

	udev_monitor_unref(ms->uevent_monitor);
	udev_unref(u);
    }
#endif /* HAVE_LIBUDEV */
}

/* vim: set sw=4 ts=8 sts=4: */
07070100000046000081A400000000000000000000000161A68E120000671A000000000000000000000000000000000000003400000000xf86-video-vmware-13.3.0+12/vmwgfx/vmwgfx_overlay.c/*
 * Copyright 2007-2011 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 "xorg-server.h"
#include "xf86xv.h"
#include "fourcc.h"
#define debug_printf(...)

/*
 * We can't incude svga_types.h due to conflicting types for Bool.
 */
typedef int64_t int64;
typedef uint64_t uint64;

typedef int32_t int32;
typedef uint32_t uint32;

typedef int16_t int16;
typedef uint16_t uint16;

typedef int8_t int8;
typedef uint8_t uint8;

#include "../src/svga_reg.h"
#include "../src/svga_escape.h"
#include "../src/svga_overlay.h"
#include "../src/common_compat.h"

#include <X11/extensions/Xv.h>

#include "xf86drm.h"
#include "vmwgfx_drm.h"
#include "vmwgfx_drmi.h"
#include "vmwgfx_driver.h"
#include "vmwgfx_hosted.h"

#define MAKE_ATOM(a) MakeAtom(a, sizeof(a) - 1, TRUE)

/*
 * 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
};

static CONST_ABI_16_TO_19 char xv_colorkey_name[] = "XV_COLORKEY";
static CONST_ABI_16_TO_19 char xv_autopaint_name[] = "XV_AUTOPAINT_COLORKEY";

#define VMWARE_VID_NUM_ATTRIBUTES 2
static XF86AttributeRec vmwareVideoAttributes[] =
{
    {
        XvGettable | XvSettable,
        0x000000,
        0xffffff,
        xv_colorkey_name,
    },
    {
        XvGettable | XvSettable,
        0,
        1,
        xv_autopaint_name,
    }
};

/*
 * Video frames are stored in a circular list of buffers.
 * Must be power or two, See vmw_video_port_play.
 */
#define VMWARE_VID_NUM_BUFFERS 1

/*
 * Defines the structure used to hold and pass video data to the host
 */
struct vmw_video_buffer
{
    int size;
    void *data;
    struct vmwgfx_dmabuf *buf;
};


/**
 * Structure representing a single video stream, aka port.
 *
 * Ports maps one to one to a SVGA stream. Port is just
 * what Xv calls a SVGA stream.
 */
struct vmwgfx_overlay_port
{
    /*
     * Function prototype same as XvPutImage.
     *
     * This is either set to vmw_video_port_init or vmw_video_port_play.
     * At init this function is set to port_init. In port_init we set it
     * to port_play and call it, after initializing the struct.
     */
    int (*play)(ScrnInfoPtr, struct vmwgfx_overlay_port *,
                short, short, short, short, short,
                short, short, short, int, unsigned char*,
                short, short, RegionPtr, DrawablePtr);

    /* values to go into the SVGAOverlayUnit */
    uint32 streamId;
    uint32 colorKey;
    uint32 flags;

    /* round robin of buffers */
    unsigned currBuf;
    struct vmw_video_buffer bufs[VMWARE_VID_NUM_BUFFERS];

    /* properties that applies to all buffers */
    int size;
    int pitches[3];
    int offsets[3];

    /* things for X */
    RegionRec clipBoxes;
    Bool isAutoPaintColorkey;
    int drm_fd;
};

/*
 * Callback functions exported to Xv, prefixed with vmw_xv_*.
 */
static int vmw_xv_put_image(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);
static void vmw_xv_stop_video(ScrnInfoPtr pScrn, pointer data, Bool Cleanup);
static int vmw_xv_query_image_attributes(ScrnInfoPtr pScrn, int format,
                                         unsigned short *width,
                                         unsigned short *height, int *pitches,
                                         int *offsets);
static int vmw_xv_set_port_attribute(ScrnInfoPtr pScrn, Atom attribute,
                                     INT32 value, pointer data);
static int vmw_xv_get_port_attribute(ScrnInfoPtr pScrn, Atom attribute,
                                     INT32 *value, pointer data);
static void vmw_xv_query_best_size(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.
 */
static int vmw_video_port_init(ScrnInfoPtr pScrn,
                               struct vmwgfx_overlay_port *port,
                               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 pDraw);
static int vmw_video_port_play(ScrnInfoPtr pScrn, struct vmwgfx_overlay_port *port,
                               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 pDraw);
static void vmw_video_port_cleanup(ScrnInfoPtr pScrn, struct vmwgfx_overlay_port *port);

static int vmw_video_buffer_alloc(int drm_fd, int size,
                                  struct vmw_video_buffer *out);
static int vmw_video_buffer_free(struct vmw_video_buffer *out);


static struct vmwgfx_overlay_port *
vmwgfx_overlay_port_create(int drm_fd, ScreenPtr pScreen)
{
    struct vmwgfx_overlay_port *port = calloc(1, sizeof(*port));

    if (!port)
	return NULL;

    port->drm_fd = drm_fd;
    port->play = vmw_video_port_init;
    port->flags = SVGA_VIDEO_FLAG_COLORKEY;
    port->colorKey = VMWARE_VIDEO_COLORKEY;
    port->isAutoPaintColorkey = TRUE;
    return port;
}

void
vmw_video_free_adaptor(XF86VideoAdaptorPtr adaptor)
{
    int i;

    for (i = 0; i < adaptor->nPorts; ++i)
	free(adaptor->pPortPrivates[i].ptr);

    free(adaptor->pPortPrivates);
    xf86XVFreeVideoAdaptorRec(adaptor);
}

/*
 *-----------------------------------------------------------------------------
 *
 * vmw_video_init_adaptor --
 *
 *    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.
 *
 *-----------------------------------------------------------------------------
 */

XF86VideoAdaptorPtr
vmw_video_init_adaptor(ScrnInfoPtr pScrn)
{
    XF86VideoAdaptorPtr adaptor;
    modesettingPtr ms = modesettingPTR(pScrn);
    int i;
    DevUnion *dev_unions;
    uint32_t ntot, nfree;

    if (vmwgfx_is_hosted(ms->hdriver))
	return NULL;

    if (vmwgfx_num_streams(ms->fd, &ntot, &nfree) != 0) {
        debug_printf("No stream ioctl support\n");
        return NULL;
    }
    if (nfree == 0) {
        debug_printf("No free streams\n");
        return NULL;
    }
    adaptor = xf86XVAllocateVideoAdaptorRec(pScrn);
    dev_unions = calloc(VMWARE_VID_NUM_PORTS, sizeof(DevUnion));
    if (adaptor == NULL || dev_unions == NULL) {
	xf86XVFreeVideoAdaptorRec(adaptor);
	free(dev_unions);
	return NULL;
    }

    adaptor->type = XvInputMask | XvImageMask | XvWindowMask;

    /**
     * Note: CLIP_TO_VIEWPORT was removed from the flags, since with the
     * crtc/output based modesetting, the viewport is not updated on
     * RandR modeswitches. Hence the video may incorrectly be clipped away.
     * The correct approach, (if needed) would be to clip against the
     * scanout area union of all active crtcs. Revisit if needed.
     */

    adaptor->flags = VIDEO_OVERLAID_IMAGES;
    adaptor->name = "VMware Overlay 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;
    adaptor->pPortPrivates = dev_unions;

    for (i = 0; i < VMWARE_VID_NUM_PORTS; ++i) {
	struct vmwgfx_overlay_port *priv =
	    vmwgfx_overlay_port_create(ms->fd, pScrn->pScreen);

        adaptor->pPortPrivates[i].ptr = (pointer) priv;
    }

    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 = vmw_xv_stop_video;
    adaptor->SetPortAttribute = vmw_xv_set_port_attribute;
    adaptor->GetPortAttribute = vmw_xv_get_port_attribute;
    adaptor->QueryBestSize = vmw_xv_query_best_size;
    adaptor->PutImage = vmw_xv_put_image;
    adaptor->QueryImageAttributes = vmw_xv_query_image_attributes;

    return adaptor;
}


/*
 *-----------------------------------------------------------------------------
 *
 * vmw_video_port_init --
 *
 *    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
vmw_video_port_init(ScrnInfoPtr pScrn, struct vmwgfx_overlay_port *port,
                    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 pDraw)
{
    unsigned short w, h;
    int i, ret;

    debug_printf("\t%s: id %d, format %d\n", __func__, port->streamId, format);

    ret = vmwgfx_claim_stream(port->drm_fd, &port->streamId);
    if (ret != 0)
	return XvBadAlloc;

    w = width;
    h = height;
    /* init all the format attributes, used for buffers */
    port->size = vmw_xv_query_image_attributes(pScrn, format, &w, &h,
                                               port->pitches, port->offsets);

    if (port->size == -1) {
	ret = XvBadAlloc;
	goto out_bad_size;
    }

    for (i = 0; i < VMWARE_VID_NUM_BUFFERS; ++i) {
	ret = vmw_video_buffer_alloc(port->drm_fd, port->size, &port->bufs[i]);
	if (ret != Success)
	    goto out_no_buffer;
    }

    port->currBuf = 0;
    REGION_NULL(pScrn->pScreen, &port->clipBoxes);
    port->play = vmw_video_port_play;
    return port->play(pScrn, port, src_x, src_y, drw_x, drw_y, src_w, src_h,
                      drw_w, drw_h, format, buf, width, height, clipBoxes, pDraw);

  out_no_buffer:
    while(i-- != 0) {
	vmw_video_buffer_free(&port->bufs[i]);
    }
  out_bad_size:
    (void) vmwgfx_unref_stream(port->drm_fd, port->streamId);

    return ret;
}


/*
 *-----------------------------------------------------------------------------
 *
 * vmw_video_port_play --
 *
 *    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
vmw_video_port_play(ScrnInfoPtr pScrn, struct vmwgfx_overlay_port *port,
                    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 pDraw)
{
    struct drm_vmw_control_stream_arg arg;
    unsigned short w, h;
    int size;
    int ret;

    debug_printf("\t%s: enter\n", __func__);

    w = width;
    h = height;

    /* we don't update the ports size */
    size = vmw_xv_query_image_attributes(pScrn, format, &w, &h,
                                         port->pitches, port->offsets);

    if (size != port->size) {
        vmw_xv_stop_video(pScrn, port, TRUE);
        return port->play(pScrn, port, src_x, src_y, drw_x, drw_y, src_w,
                          src_h, drw_w, drw_h, format, buf, width, height,
                          clipBoxes, pDraw);
    }

    memcpy(port->bufs[port->currBuf].data, buf, port->size);

    memset(&arg, 0, sizeof(arg));

    arg.stream_id = port->streamId;
    arg.enabled = TRUE;
    arg.flags = port->flags;
    arg.color_key = port->colorKey;
    arg.handle = port->bufs[port->currBuf].buf->handle;
    arg.format = format;
    arg.size = port->size;
    arg.width = w;
    arg.height = h;
    arg.src.x = src_x;
    arg.src.y = src_y;
    arg.src.w = src_w;
    arg.src.h = src_h;
    arg.dst.x = drw_x;
    arg.dst.y = drw_y;
    arg.dst.w = drw_w;
    arg.dst.h = drw_h;
    arg.pitch[0] = port->pitches[0];
    arg.pitch[1] = port->pitches[1];
    arg.pitch[2] = port->pitches[2];
    arg.offset = 0;

    /*
     *  Update the clipList and paint the colorkey, if required.
     */
    if (!REGION_EQUAL(pScrn->pScreen, &port->clipBoxes, clipBoxes)) {
        REGION_COPY(pScrn->pScreen, &port->clipBoxes, clipBoxes);
        if (port->isAutoPaintColorkey) {
            if (pDraw->type == DRAWABLE_WINDOW) {
                xf86XVFillKeyHelperDrawable(pDraw, port->colorKey, clipBoxes);
                DamageDamageRegion(pDraw, clipBoxes);
            } else {
                xf86XVFillKeyHelper(pScrn->pScreen, port->colorKey, clipBoxes);
            }
        }
    }

    xorg_flush(pScrn->pScreen);
    ret = drmCommandWrite(port->drm_fd, DRM_VMW_CONTROL_STREAM, &arg, sizeof(arg));
    if (ret) {
	vmw_video_port_cleanup(pScrn, port);
	return XvBadAlloc;
    }

    if (++(port->currBuf) >= VMWARE_VID_NUM_BUFFERS)
	port->currBuf = 0;

    return Success;
}


/*
 *-----------------------------------------------------------------------------
 *
 * vmw_video_port_cleanup --
 *
 *    Frees up all resources (if any) taken by a video stream.
 *
 * Results:
 *    None.
 *
 * Side effects:
 *    Same as above.
 *
 *-----------------------------------------------------------------------------
 */

static void
vmw_video_port_cleanup(ScrnInfoPtr pScrn, struct vmwgfx_overlay_port *port)
{
    int i;

    debug_printf("\t%s: enter\n", __func__);

    if (port->play == vmw_video_port_init)
	return;

    port->play = vmw_video_port_init;
    (void) vmwgfx_unref_stream(port->drm_fd, port->streamId);

    for (i = 0; i < VMWARE_VID_NUM_BUFFERS; i++) {
	vmw_video_buffer_free(&port->bufs[i]);
    }

    REGION_UNINIT(pScreen->pScreen, &port->clipBoxes);
}


/*
 *-----------------------------------------------------------------------------
 *
 * vmw_video_buffer_alloc --
 *
 *    Allocates and map a kernel buffer to be used as data storage.
 *
 * Results:
 *    XvBadAlloc on failure, otherwise Success.
 *
 * Side effects:
 *    Calls into the kernel, sets members of out.
 *
 *-----------------------------------------------------------------------------
 */

static int
vmw_video_buffer_alloc(int drm_fd, int size,
                       struct vmw_video_buffer *out)
{
    out->buf = vmwgfx_dmabuf_alloc(drm_fd, size);
    if (!out->buf)
	return XvBadAlloc;

    out->data = vmwgfx_dmabuf_map(out->buf);
    if (!out->data) {
	vmwgfx_dmabuf_destroy(out->buf);
	out->buf = NULL;
	return XvBadAlloc;
    }

    out->size = size;
    debug_printf("\t\t%s: allocated buffer %p of size %i\n", __func__, out, size);

    return Success;
}


/*
 *-----------------------------------------------------------------------------
 *
 * vmw_video_buffer_free --
 *
 *    Frees and unmaps an allocated kernel buffer.
 *
 * Results:
 *    Success.
 *
 * Side effects:
 *    Calls into the kernel, sets members of out to 0.
 *
 *-----------------------------------------------------------------------------
 */

static int
vmw_video_buffer_free(struct vmw_video_buffer *out)
{
    if (out->size == 0)
	return Success;

    vmwgfx_dmabuf_unmap(out->buf);
    vmwgfx_dmabuf_destroy(out->buf);

    out->buf = NULL;
    out->data = NULL;
    out->size = 0;

    debug_printf("\t\t%s: freed buffer %p\n", __func__, out);

    return Success;
}


/*
 *-----------------------------------------------------------------------------
 *
 * vmw_xv_put_image --
 *
 *    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.
 *
 * Results:
 *    Success or XvBadAlloc on failure
 *
 * Side effects:
 *    Video port will be played(initialized if 1st frame) on success
 *    or will fail on error.
 *
 *-----------------------------------------------------------------------------
 */

static int
vmw_xv_put_image(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)
{
    struct vmwgfx_overlay_port *port = data;

    debug_printf("%s: enter (%u, %u) (%ux%u) (%u, %u) (%ux%u) (%ux%u)\n", __func__,
		 src_x, src_y, src_w, src_h,
		 drw_x, drw_y, drw_w, drw_h,
		 width, height);

    return port->play(pScrn, port, src_x, src_y, drw_x, drw_y, src_w, src_h,
                      drw_w, drw_h, format, buf, width, height, clipBoxes, dst);
}


/*
 *-----------------------------------------------------------------------------
 *
 * vmw_xv_stop_video --
 *
 *    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 port by
 *    sending a message to the host and freeing up the stream.
 *
 * Results:
 *    None.
 *
 * Side effects:
 *    See above.
 *
 *-----------------------------------------------------------------------------
 */

static void
vmw_xv_stop_video(ScrnInfoPtr pScrn, pointer data, Bool cleanup)
{
    struct vmwgfx_overlay_port *port = data;

    debug_printf("%s: cleanup is %s\n", __func__, cleanup ? "TRUE" : "FALSE");
    REGION_EMPTY(pScrn->pScreen, &port->clipBoxes);

    if (!cleanup)
        return;

    vmw_video_port_cleanup(pScrn, port);
}


/*
 *-----------------------------------------------------------------------------
 *
 * vmw_xv_query_image_attributes --
 *
 *    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
vmw_xv_query_image_attributes(ScrnInfoPtr pScrn, int format,
                              unsigned short *width, unsigned short *height,
                              int *pitches, int *offsets)
{
    INT32 size, tmp;

    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:
           debug_printf("Query for invalid video format %d\n", format);
           return -1;
    }
    return size;
}


/*
 *-----------------------------------------------------------------------------
 *
 * vmw_xv_set_port_attribute --
 *
 *    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
vmw_xv_set_port_attribute(ScrnInfoPtr pScrn, Atom attribute,
                          INT32 value, pointer data)
{
    struct vmwgfx_overlay_port *port = data;
    Atom xvColorKey = MAKE_ATOM("XV_COLORKEY");
    Atom xvAutoPaint = MAKE_ATOM("XV_AUTOPAINT_COLORKEY");

    if (attribute == xvColorKey) {
        debug_printf("%s: Set colorkey:0x%x\n", __func__, (unsigned)value);
        port->colorKey = value;
    } else if (attribute == xvAutoPaint) {
        debug_printf("%s: Set autoPaint: %s\n", __func__, value? "TRUE": "FALSE");
        port->isAutoPaintColorkey = value;
    } else {
        return XvBadAlloc;
    }

    return Success;
}


/*
 *-----------------------------------------------------------------------------
 *
 * vmw_xv_get_port_attribute --
 *
 *    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
vmw_xv_get_port_attribute(ScrnInfoPtr pScrn, Atom attribute,
                          INT32 *value, pointer data)
{
    struct vmwgfx_overlay_port *port = data;
    Atom xvColorKey = MAKE_ATOM("XV_COLORKEY");
    Atom xvAutoPaint = MAKE_ATOM("XV_AUTOPAINT_COLORKEY");

    if (attribute == xvColorKey) {
        *value = port->colorKey;
    } else if (attribute == xvAutoPaint) {
        *value = port->isAutoPaintColorkey;
    } else {
        return XvBadAlloc;
    }

    return Success;
}


/*
 *-----------------------------------------------------------------------------
 *
 * vmw_xv_query_best_size --
 *
 *    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
vmw_xv_query_best_size(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;
}
07070100000047000081A400000000000000000000000161A68E1200000CBC000000000000000000000000000000000000003700000000xf86-video-vmware-13.3.0+12/vmwgfx/vmwgfx_rr_inlines.h/**************************************************************************
 * Copyright © 2016 VMware, Inc., Palo Alto, CA., USA
 * 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
 * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM,
 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
 * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
 * USE OR OTHER DEALINGS IN THE SOFTWARE.
 *
 **************************************************************************/
/*
 * This file contains calls into the RandR1.2 code and modification of core
 * RandR data structures that probably were never intended from drivers.
 */

#ifndef _VMWGFX_RR_INLINES_H_
#define _VMWGFX_RR_INLINES_H_

#include <xf86Crtc.h>
#include <xf86RandR12.h>

#define VMW_DPI 96.
#define VMW_INCH_TO_MM 25.4

/**
 * vmwgfx_notify_rr - Notify RandR that our configuration has changed.
 *
 * @pScreen: Pointer to the affected screen.
 *
 * Normally screen configurations are typically only changed using RandR,
 * so when we do it in an udev handler, we need to notify RandR that we've
 * made a change, so that it can be propagated to all RandR clients.
 */
static inline void
vmwgfx_notify_rr(ScreenPtr pScreen)
{
    rrScrPriv(pScreen);


    /*
     * We need to update the time-stamps, otherwise X clients that haven't
     * yet read this config might just overwrite it.
     * This effectively stops the desktop manager from trying to
     * outsmart us, since RandR simply doesn't accept requests from
     * clients that haven't read this config and tag their request with
     * an earlier timestamp.
     */
    pScrPriv->lastSetTime = currentTime;
    pScrPriv->lastConfigTime = currentTime;
#ifdef RANDR_12_INTERFACE
    xf86RandR12TellChanged(pScreen);
#else
    RRTellChanged(pScreen);
#endif
}

/**
 * vmwgfx_rr_screen_set_size - Use RandR to change the root pixmap dimensions.
 *
 * @pScreen: Pointer to the affected screen.
 *
 * Returns: TRUE if successful. False otherwise.
 */
static inline Bool
vmwgfx_rr_screen_set_size(ScreenPtr pScreen, int width, int height)
{
    rrScrPriv(pScreen);
    float mm_width, mm_height;

    mm_width = ((float) width) * VMW_INCH_TO_MM / VMW_DPI + .5;
    mm_height = ((float) height) * VMW_INCH_TO_MM / VMW_DPI + .5;

    return pScrPriv->rrScreenSetSize(pScreen, width, height,
				     (int) mm_width, (int) mm_height);
}

#endif
07070100000048000081A400000000000000000000000161A68E120000B5C1000000000000000000000000000000000000003000000000xf86-video-vmware-13.3.0+12/vmwgfx/vmwgfx_saa.c/*
 * 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>
 */

#include <xorg-server.h>
#include <xorgVersion.h>
#include <mi.h>
#include <fb.h>
#include <xa_context.h>
#include "vmwgfx_saa.h"
#include "vmwgfx_drmi.h"
#include "vmwgfx_saa_priv.h"
#include <xf86drmMode.h>

/*
 * Damage to be added as soon as we attach storage to the pixmap.
 */
static Bool
vmwgfx_pixmap_add_damage(PixmapPtr pixmap)
{
    struct saa_pixmap *spix = saa_get_saa_pixmap(pixmap);
    struct vmwgfx_saa_pixmap *vpix = to_vmwgfx_saa_pixmap(spix);
    DrawablePtr draw = &pixmap->drawable;
    BoxRec box;

    if (spix->damage)
	return TRUE;

    if (!saa_add_damage(pixmap))
	return FALSE;

    box.x1 = 0;
    box.x2 = draw->width;
    box.y1 = 0;
    box.y2 = draw->height;

    if (vpix->hw) {
	REGION_RESET(draw->pScreen, &spix->dirty_hw, &box);
	REGION_EMPTY(draw->pScreen, &spix->dirty_shadow);
    } else {
	REGION_RESET(draw->pScreen, &spix->dirty_shadow, &box);
	REGION_EMPTY(draw->pScreen, &spix->dirty_hw);
    }

    return TRUE;
}

static void
vmwgfx_pixmap_remove_damage(PixmapPtr pixmap)
{
    struct saa_pixmap *spix = saa_get_saa_pixmap(pixmap);
    struct vmwgfx_saa_pixmap *vpix = to_vmwgfx_saa_pixmap(spix);

    if (!spix->damage || vpix->hw || vpix->gmr || vpix->malloc)
	return;

#if XORG_VERSION_CURRENT >= XORG_VERSION_NUMERIC(1,14,99,2,0)
    DamageUnregister(spix->damage);
#else
    DamageUnregister(&pixmap->drawable, spix->damage);
#endif

    DamageDestroy(spix->damage);
    spix->damage = NULL;
}

static void
vmwgfx_pixmap_remove_present(struct vmwgfx_saa_pixmap *vpix)
{
    if (vpix->dirty_present)
	REGION_DESTROY(pixmap->drawable.pScreen, vpix->dirty_present);
    if (vpix->present_damage)
	REGION_DESTROY(pixmap->drawable.pScreen, vpix->present_damage);
    if (vpix->pending_update)
	REGION_DESTROY(pixmap->drawable.pScreen, vpix->pending_update);
    if (vpix->pending_present)
	REGION_DESTROY(pixmap->drawable.pScreen, vpix->pending_present);
    vpix->dirty_present = NULL;
    vpix->present_damage = NULL;
    vpix->pending_update = NULL;
    vpix->pending_present = NULL;
}

static Bool
vmwgfx_pixmap_add_present(PixmapPtr pixmap, Bool present_opt)
{
    struct vmwgfx_saa_pixmap *vpix = vmwgfx_saa_pixmap(pixmap);
    ScreenPtr pScreen = pixmap->drawable.pScreen;
    (void) pScreen;

    if (present_opt) {
	vpix->dirty_present = REGION_CREATE(pScreen, NULL, 0);
	if (!vpix->dirty_present)
	    return FALSE;
	vpix->present_damage = REGION_CREATE(pScreen, NULL, 0);
	if (!vpix->present_damage)
	    goto out_no_present_damage;
    }
    vpix->pending_update = REGION_CREATE(pScreen, NULL, 0);
    if (!vpix->pending_update)
	goto out_no_pending_update;
    vpix->pending_present = REGION_CREATE(pScreen, NULL, 0);
    if (!vpix->pending_present)
	goto out_no_pending_present;

    return TRUE;
  out_no_pending_present:
    REGION_DESTROY(pScreen, vpix->pending_update);
  out_no_pending_update:
    if (vpix->present_damage)
	REGION_DESTROY(pScreen, vpix->present_damage);
  out_no_present_damage:
    if (vpix->dirty_present)
	REGION_DESTROY(pScreen, vpix->dirty_present);
    return FALSE;
}

static void
vmwgfx_pixmap_free_storage(struct vmwgfx_saa_pixmap *vpix)
{
    if (!(vpix->backing & VMWGFX_PIX_MALLOC) && vpix->malloc) {
	free(vpix->malloc);
	vpix->malloc = NULL;
    }
    if (!(vpix->backing & VMWGFX_PIX_SURFACE) && vpix->hw) {
	xa_surface_destroy(vpix->hw);
	vpix->hw = NULL;
    }
    if (!(vpix->backing & VMWGFX_PIX_GMR) && vpix->gmr) {
	vmwgfx_dmabuf_destroy(vpix->gmr);
	vpix->gmr = NULL;
    }
}

static Bool
vmwgfx_pixmap_create_gmr(struct vmwgfx_saa *vsaa, PixmapPtr pixmap)
{
    struct vmwgfx_saa_pixmap *vpix = vmwgfx_saa_pixmap(pixmap);
    size_t size;
    struct vmwgfx_dmabuf *gmr;
    void *addr;

    if (vpix->gmr)
	return TRUE;

    size = pixmap->devKind * pixmap->drawable.height;
    gmr = vmwgfx_dmabuf_alloc(vsaa->drm_fd, size);
    if (!gmr)
	return FALSE;

    if (vpix->malloc) {

	addr = vmwgfx_dmabuf_map(gmr);
	if (!addr)
	    goto out_no_transfer;
	memcpy(addr, vpix->malloc, size);
	vmwgfx_dmabuf_unmap(gmr);

    } else if (!vmwgfx_pixmap_add_damage(pixmap))
	goto out_no_transfer;

    vpix->backing |= VMWGFX_PIX_GMR;
    vpix->backing &= ~VMWGFX_PIX_MALLOC;
    vpix->gmr = gmr;

    vmwgfx_pixmap_free_storage(vpix);

    return TRUE;

  out_no_transfer:
    vmwgfx_dmabuf_destroy(gmr);
    return FALSE;
}

static Bool
vmwgfx_pixmap_create_sw(struct vmwgfx_saa *vsaa, PixmapPtr pixmap)
{
    struct vmwgfx_saa_pixmap *vpix = vmwgfx_saa_pixmap(pixmap);

    if (!(vpix->backing & (VMWGFX_PIX_MALLOC | VMWGFX_PIX_GMR)))
	return FALSE;

    if (!vpix->malloc && (vpix->backing & VMWGFX_PIX_MALLOC)) {
	vpix->malloc = malloc(pixmap->devKind * pixmap->drawable.height);
	if (!vpix->malloc)
	    goto out_no_malloc;
	if (!vmwgfx_pixmap_add_damage(pixmap))
	    goto out_no_damage;
    } else if (vpix->backing & VMWGFX_PIX_GMR)
	return vmwgfx_pixmap_create_gmr(vsaa, pixmap);

    return TRUE;

  out_no_damage:
    free(vpix->malloc);
    vpix->malloc = NULL;
  out_no_malloc:
    return FALSE;
}


/**
 *
 * Makes sure all presented contents covered by @region are read
 * back and are present in a valid GMR.
 */

static Bool
vmwgfx_pixmap_present_readback(struct vmwgfx_saa *vsaa,
			       PixmapPtr pixmap,
			       RegionPtr region)
{
    struct saa_pixmap *spix = saa_get_saa_pixmap(pixmap);
    struct vmwgfx_saa_pixmap *vpix = to_vmwgfx_saa_pixmap(spix);
    RegionRec intersection;

    if (!spix->damage || !REGION_NOTEMPTY(vsaa->pScreen, &spix->dirty_hw) ||
	!vpix->dirty_present)
	return TRUE;

    /*
     * Intersect dirty region with region to be read back, if any.
     */

    REGION_NULL(vsaa->pScreen, &intersection);
    REGION_COPY(vsaa->pScreen, &intersection, &spix->dirty_hw);
    REGION_INTERSECT(vsaa->pScreen, &intersection, &intersection,
		     vpix->dirty_present);

    if (region)
	REGION_INTERSECT(vsaa->pScreen, &intersection, &intersection, region);

    if (!REGION_NOTEMPTY(vsaa->pScreen, &intersection))
	goto out;

    /*
     * Make really sure there is a GMR to read back to.
     */

    if (!vmwgfx_pixmap_create_gmr(vsaa, pixmap))
	goto out_err;

    if (vmwgfx_present_readback(vsaa->drm_fd, vpix->fb_id,
				&intersection) != 0)
	goto out_err;

    REGION_SUBTRACT(vsaa->pScreen, &spix->dirty_hw,
		    &spix->dirty_hw, &intersection);
  out:
    REGION_UNINIT(vsaa->pScreen, &intersection);
    return TRUE;

  out_err:
    REGION_UNINIT(vsaa->pScreen, &intersection);
    return FALSE;
}

static Bool
vmwgfx_saa_dma(struct vmwgfx_saa *vsaa,
	       PixmapPtr pixmap,
	       RegionPtr reg,
	       Bool to_hw,
	       int dx,
	       int dy,
	       struct xa_surface *srf)
{
    struct vmwgfx_saa_pixmap *vpix = vmwgfx_saa_pixmap(pixmap);

    if (!srf)
	srf = vpix->hw;

    if (!srf || (!vpix->gmr && !vpix->malloc))
	return TRUE;

    if (vpix->gmr && vsaa->can_optimize_dma) {
	uint32_t handle, dummy;

	if (_xa_surface_handle(srf, &handle, &dummy) != 0)
	    goto out_err;
	if (vmwgfx_dma(dx, dy, reg, vpix->gmr, pixmap->devKind, handle,
		       to_hw) != 0)
	    goto out_err;
    } else {
	uint8_t *data = (uint8_t *) vpix->malloc;
	int ret;

	if (vpix->gmr) {
	    data = (uint8_t *) vmwgfx_dmabuf_map(vpix->gmr);
	    if (!data)
		goto out_err;
	}

	if (dx || dy) {
	    REGION_TRANSLATE(pScreen, reg, dx, dy);
	    data -= ((dx * pixmap->drawable.bitsPerPixel + 7)/8 +
		     dy * pixmap->devKind);
	}

	ret = xa_surface_dma(vsaa->xa_ctx, srf, data, pixmap->devKind,
			     (int) to_hw,
			     (struct xa_box *) REGION_RECTS(reg),
			     REGION_NUM_RECTS(reg));
	if (to_hw)
	    xa_context_flush(vsaa->xa_ctx);
	if (vpix->gmr)
	    vmwgfx_dmabuf_unmap(vpix->gmr);
	if (dx || dy)
	    REGION_TRANSLATE(pScreen, reg, -dx, -dy);
	if (ret)
	    goto out_err;
    }
    return TRUE;
  out_err:
    LogMessage(X_ERROR, "DMA %s surface failed.\n",
	       to_hw ? "to" : "from");
    return FALSE;
}


static Bool
vmwgfx_download_from_hw(struct saa_driver *driver, PixmapPtr pixmap,
			RegionPtr readback)
{
    struct vmwgfx_saa *vsaa = to_vmwgfx_saa(driver);
    struct saa_pixmap *spix = saa_get_saa_pixmap(pixmap);
    struct vmwgfx_saa_pixmap *vpix = to_vmwgfx_saa_pixmap(spix);

    RegionRec intersection;

    if (!vmwgfx_pixmap_present_readback(vsaa, pixmap, readback))
	return FALSE;

    if (!REGION_NOTEMPTY(vsaa->pScreen, &spix->dirty_hw))
	return TRUE;

    if (!vpix->hw)
	return TRUE;

    REGION_NULL(vsaa->pScreen, &intersection);
    REGION_INTERSECT(vsaa->pScreen, &intersection, readback,
		     &spix->dirty_hw);
    readback = &intersection;

    if (!vmwgfx_pixmap_create_sw(vsaa, pixmap))
	goto out_err;

    if (!vmwgfx_saa_dma(vsaa, pixmap, readback, FALSE, 0, 0, NULL))
	goto out_err;
    REGION_SUBTRACT(vsaa->pScreen, &spix->dirty_hw, &spix->dirty_hw, readback);
    REGION_UNINIT(vsaa->pScreen, &intersection);

    return TRUE;
 out_err:
    REGION_UNINIT(vsaa->pScreen, &intersection);
    return FALSE;
}


static Bool
vmwgfx_upload_to_hw(struct saa_driver *driver, PixmapPtr pixmap,
		    RegionPtr upload)
{
    return vmwgfx_saa_dma(to_vmwgfx_saa(driver), pixmap, upload, TRUE,
			  0, 0, NULL);
}

static void
vmwgfx_release_from_cpu(struct saa_driver *driver, PixmapPtr pixmap, saa_access_t access)
{
  //    LogMessage(X_INFO, "Release 0x%08lx access 0x%08x\n",
  //	       (unsigned long) pixmap, (unsigned) access);
}

static void *
vmwgfx_sync_for_cpu(struct saa_driver *driver, PixmapPtr pixmap, saa_access_t access)
{
    /*
     * Errors in this functions will turn up in subsequent map
     * calls.
     */

    (void) vmwgfx_pixmap_create_sw(to_vmwgfx_saa(driver), pixmap);

    return NULL;
}

static void *
vmwgfx_map(struct saa_driver *driver, PixmapPtr pixmap, saa_access_t access)
{
    struct vmwgfx_saa_pixmap *vpix = vmwgfx_saa_pixmap(pixmap);

    if (vpix->malloc)
	return vpix->malloc;
    else if (vpix->gmr)
	return vmwgfx_dmabuf_map(vpix->gmr);
    else
	return NULL;
}

static void
vmwgfx_unmap(struct saa_driver *driver, PixmapPtr pixmap, saa_access_t access)
{
    struct vmwgfx_saa_pixmap *vpix = vmwgfx_saa_pixmap(pixmap);

    if (vpix->gmr)
	return vmwgfx_dmabuf_unmap(vpix->gmr);

//    LogMessage(X_INFO, "Unmap 0x%08lx access 0x%08x\n",
    //       (unsigned long) pixmap, (unsigned) access);
    ;
}

static Bool
vmwgfx_create_pixmap(struct saa_driver *driver, struct saa_pixmap *spix,
		     int w, int h, int depth,
		     unsigned int usage_hint, int bpp, int *new_pitch)
{
    struct vmwgfx_saa_pixmap *vpix = to_vmwgfx_saa_pixmap(spix);

    *new_pitch = ((w * bpp + FB_MASK) >> FB_SHIFT) * sizeof(FbBits);

    WSBMINITLISTHEAD(&vpix->sync_x_head);
    WSBMINITLISTHEAD(&vpix->scanout_list);
    WSBMINITLISTHEAD(&vpix->pixmap_list);

    return TRUE;
}

Bool
vmwgfx_hw_kill(struct vmwgfx_saa *vsaa,
	       struct saa_pixmap *spix)
{
    struct vmwgfx_saa_pixmap *vpix = to_vmwgfx_saa_pixmap(spix);

    if (!vpix->hw)
	return TRUE;

    /*
     * Read back any dirty regions from hardware.
     */

    if (!vmwgfx_download_from_hw(&vsaa->driver, spix->pixmap,
				 &spix->dirty_hw))
	return FALSE;

    xa_surface_destroy(vpix->hw);
    vpix->hw = NULL;

    /*
     * Remove damage tracking if this is not a scanout pixmap.
     */

    if (WSBMLISTEMPTY(&vpix->scanout_list))
	vmwgfx_pixmap_remove_damage(spix->pixmap);

    return TRUE;
}

void
vmwgfx_flush_dri2(ScreenPtr pScreen)
{
    struct vmwgfx_saa *vsaa =
	to_vmwgfx_saa(saa_get_driver(pScreen));
    struct _WsbmListHead *list, *next;
    ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);

    if (!pScrn->vtSema)
	return;

    WSBMLISTFOREACHSAFE(list, next, &vsaa->sync_x_list) {
	struct vmwgfx_saa_pixmap *vpix =
	    WSBMLISTENTRY(list, struct vmwgfx_saa_pixmap, sync_x_head);
	struct saa_pixmap *spix = &vpix->base;
	PixmapPtr pixmap = spix->pixmap;

	if (vmwgfx_upload_to_hw(&vsaa->driver, pixmap, &spix->dirty_shadow)) {
	    REGION_EMPTY(vsaa->pScreen, &spix->dirty_shadow);
	    WSBMLISTDELINIT(list);
	}
    }
}


static void
vmwgfx_destroy_pixmap(struct saa_driver *driver, PixmapPtr pixmap)
{
    ScreenPtr pScreen = to_vmwgfx_saa(driver)->pScreen;
    struct vmwgfx_saa_pixmap *vpix = vmwgfx_saa_pixmap(pixmap);
    (void) pScreen;

    vpix->backing = 0;
    vmwgfx_pixmap_free_storage(vpix);

    /*
     * Any damage we've registered has already been removed by the server
     * at this point. Any attempt to unregister / destroy it will result
     * in a double free.
     */

    vmwgfx_pixmap_remove_present(vpix);
    WSBMLISTDELINIT(&vpix->pixmap_list);
    WSBMLISTDELINIT(&vpix->sync_x_head);
}



/**
 *
 * Makes sure we have a surface with valid contents.
 */

static void
vmwgfx_copy_stride(uint8_t *dst, uint8_t *src, unsigned int dst_pitch,
		   unsigned int src_pitch, unsigned int dst_height,
		   unsigned int src_height)
{
    unsigned int i;
    unsigned int height = (dst_height < src_height) ? dst_height : src_height;
    unsigned int pitch = (dst_pitch < src_pitch) ? dst_pitch : src_pitch;

    for(i=0; i<height; ++i) {
	memcpy(dst, src, pitch);
	dst += dst_pitch;
	src += src_pitch;
    }
}


static Bool
vmwgfx_pix_resize(PixmapPtr pixmap, unsigned int old_pitch,
		  unsigned int old_height, unsigned int old_width)
{
    ScreenPtr pScreen = pixmap->drawable.pScreen;
    struct vmwgfx_saa *vsaa = to_vmwgfx_saa(saa_get_driver(pScreen));
    struct saa_pixmap *spix = saa_get_saa_pixmap(pixmap);
    struct vmwgfx_saa_pixmap *vpix = to_vmwgfx_saa_pixmap(spix);
    DrawablePtr draw = &pixmap->drawable;
    unsigned int size = pixmap->devKind * draw->height;
    BoxRec b_box;
    RegionRec b_reg;

    /*
     * Ignore copying errors. At worst they will show up as rendering
     * artefacts.
     */

    if (vpix->malloc) {

	void *new_malloc = malloc(size);
	if (!new_malloc)
	    return FALSE;

	vmwgfx_copy_stride(new_malloc, vpix->malloc, pixmap->devKind,
			   old_pitch, draw->height,
			   old_height);
	free(vpix->malloc);
	vpix->malloc = new_malloc;
    }

    if (vpix->gmr) {
	struct vmwgfx_dmabuf *gmr;
	void *new_addr;
	void *old_addr;

	gmr = vmwgfx_dmabuf_alloc(vsaa->drm_fd, size);
	if (!gmr)
	    return FALSE;

	new_addr = vmwgfx_dmabuf_map(gmr);
	old_addr = vmwgfx_dmabuf_map(vpix->gmr);

	if (new_addr && old_addr)
	    vmwgfx_copy_stride(new_addr, old_addr, pixmap->devKind,
			       old_pitch, draw->height,
			       old_height);
	else
	    LogMessage(X_ERROR, "Failed pixmap resize copy.\n");

	if (old_addr)
	    vmwgfx_dmabuf_unmap(vpix->gmr);
	if (new_addr)
	    vmwgfx_dmabuf_unmap(gmr);
	vmwgfx_dmabuf_destroy(vpix->gmr);
	vpix->gmr = gmr;
    }

    if (vpix->hw) {
      if (!vmwgfx_xa_surface_redefine(vpix, vpix->hw, draw->width,
				      draw->height, draw->depth, xa_type_argb,
				      xa_format_unknown, vpix->xa_flags, 1))
	    return FALSE;
    }

    b_box.x1 = 0;
    b_box.x2 = draw->width;
    b_box.y1 = 0;
    b_box.y2 = draw->height;

    REGION_INIT(pScreen, &b_reg, &b_box, 1);
    REGION_INTERSECT(pScreen, &spix->dirty_shadow, &spix->dirty_shadow,
		     &b_reg);
    REGION_INTERSECT(pScreen, &spix->dirty_hw, &spix->dirty_hw, &b_reg);
    if (vpix->dirty_present)
	REGION_INTERSECT(pScreen, vpix->dirty_present, vpix->dirty_present,
			 &b_reg);
    if (vpix->pending_update)
	REGION_INTERSECT(pScreen, vpix->pending_update, vpix->pending_update,
			 &b_reg);
    if (vpix->pending_present)
	REGION_INTERSECT(pScreen, vpix->pending_present,
			 vpix->pending_present, &b_reg);
    if (vpix->present_damage)
	REGION_INTERSECT(pScreen, vpix->present_damage, vpix->present_damage,
			 &b_reg);

    REGION_UNINIT(pScreen, &b_reg);

    return TRUE;
}


static Bool
vmwgfx_modify_pixmap_header (PixmapPtr pixmap, int w, int h, int depth,
			     int bpp, int devkind, void *pixdata)
{
    struct vmwgfx_saa_pixmap *vpix = vmwgfx_saa_pixmap(pixmap);
    ScreenPtr pScreen = pixmap->drawable.pScreen;
    struct vmwgfx_saa *vsaa = to_vmwgfx_saa(saa_get_driver(pScreen));
    unsigned int old_height;
    unsigned int old_width;
    unsigned int old_pitch;

    if (!vpix) {
	LogMessage(X_ERROR, "Not an SAA pixmap.\n");
	return FALSE;
    }

    if (pixdata) {
	vpix->backing = 0;
	vmwgfx_pixmap_free_storage(vpix);
	return FALSE;
    }

    if (depth <= 0)
	depth = pixmap->drawable.depth;

    if (bpp <= 0)
	bpp = pixmap->drawable.bitsPerPixel;

    if (w <= 0)
	w = pixmap->drawable.width;

    if (h <= 0)
	h = pixmap->drawable.height;

    if (w <= 0 || h <= 0 || depth <= 0)
	return FALSE;

    old_height = pixmap->drawable.height;
    old_width = pixmap->drawable.width;
    old_pitch = pixmap->devKind;

    if (!miModifyPixmapHeader(pixmap, w, h, depth,
			      bpp, devkind, NULL))
	goto out_no_modify;

    if (!vpix->backing)
	vpix->backing = VMWGFX_PIX_MALLOC;

    vmwgfx_pix_resize(pixmap, old_pitch, old_height, old_width);
    vmwgfx_pixmap_free_storage(vpix);
    if (WSBMLISTEMPTY(&vpix->pixmap_list))
	WSBMLISTADDTAIL(&vpix->pixmap_list, &vsaa->pixmaps);

    return TRUE;

  out_no_modify:
    return FALSE;
}

static Bool
vmwgfx_present_prepare(struct vmwgfx_saa *vsaa,
		       struct vmwgfx_saa_pixmap *src_vpix,
		       struct vmwgfx_saa_pixmap *dst_vpix)
{
    ScreenPtr pScreen = vsaa->pScreen;
    unsigned int dummy;

    (void) pScreen;
    if (src_vpix == dst_vpix || !src_vpix->hw ||
	_xa_surface_handle(src_vpix->hw, &vsaa->src_handle, &dummy) != 0)
	return FALSE;

    REGION_NULL(pScreen, &vsaa->present_region);
    vsaa->diff_valid = FALSE;
    vsaa->dst_vpix = dst_vpix;
    vsaa->present_flush(pScreen);

    return TRUE;
}

/**
 * Determine whether we should try present copies on this pixmap.
 */

static Bool
vmwgfx_is_present_hw(PixmapPtr pixmap)
{
    struct vmwgfx_saa_pixmap *vpix = vmwgfx_saa_pixmap(pixmap);
    return (vpix->dirty_present != NULL);
}

static void
vmwgfx_check_hw_contents(struct vmwgfx_saa *vsaa,
			 struct vmwgfx_saa_pixmap *vpix,
			 RegionPtr region,
			 Bool *has_dirty_hw,
			 Bool *has_valid_hw)
{
    RegionRec intersection;


    if (!vpix->hw) {
	*has_dirty_hw = FALSE;
	*has_valid_hw = FALSE;
	return;
    }

    if (!region) {
	*has_dirty_hw = REGION_NOTEMPTY(vsaa->pScreen,
					&vpix->base.dirty_hw);
	*has_valid_hw = !REGION_NOTEMPTY(vsaa->pScreen,
					 &vpix->base.dirty_shadow);
	return;
    }

    REGION_NULL(vsaa->pScreen, &intersection);
    REGION_INTERSECT(vsaa->pScreen, &intersection, &vpix->base.dirty_hw,
		     region);
    *has_dirty_hw = REGION_NOTEMPTY(vsaa->pScreen, &intersection);
    REGION_INTERSECT(vsaa->pScreen, &intersection, &vpix->base.dirty_shadow,
		     region);
    *has_valid_hw = !REGION_NOTEMPTY(vsaa->pScreen, &intersection);
    REGION_UNINIT(vsaa->pScreen, &intersection);
}

/**
 * vmwgfx_prefer_gmr: Prefer a dma buffer over malloced memory for software
 * rendered storage
 *
 * @vsaa: Pointer to a struct vmwgfx_saa accelerator.
 * @pixmap: Pointer to pixmap whose storage preference we want to alter.
 *
 * If possible, alter the storage or future storage of the software contents
 * of this pixmap to be in a DMA buffer rather than in malloced memory.
 * This function should be called when it's likely that frequent DMA operations
 * will occur between a surface and the memory holding the software
 * contents.
 */
static void
vmwgfx_prefer_gmr(struct vmwgfx_saa *vsaa, PixmapPtr pixmap)
{
    struct vmwgfx_saa_pixmap *vpix = vmwgfx_saa_pixmap(pixmap);

    if (vsaa->can_optimize_dma) {
	if (vpix->malloc) {
	    (void) vmwgfx_pixmap_create_gmr(vsaa, pixmap);
	} else if (vpix->backing & VMWGFX_PIX_MALLOC) {
	    vpix->backing |= VMWGFX_PIX_GMR;
	    vpix->backing &= ~VMWGFX_PIX_MALLOC;
	}
    }
}

Bool
vmwgfx_create_hw(struct vmwgfx_saa *vsaa,
		 PixmapPtr pixmap,
		 Bool shared)
{
    struct vmwgfx_saa_pixmap *vpix = vmwgfx_saa_pixmap(pixmap);
    struct xa_surface *hw;
    uint32_t new_flags;

    if (!vsaa->xat)
	return FALSE;

    if (!shared) {
	if (vpix->hw)
	    return TRUE;

	new_flags = (vpix->xa_flags & ~vpix->staging_remove_flags) |
	    vpix->staging_add_flags | XA_FLAG_SHARED;

	hw = xa_surface_create(vsaa->xat,
			       pixmap->drawable.width,
			       pixmap->drawable.height,
			       0,
			       xa_type_other,
			       vpix->staging_format,
			       new_flags);
    } else {
	new_flags = vpix->xa_flags;
	hw = vpix->hw;
    }

    if (hw == NULL)
	return FALSE;

    vpix->xa_flags = new_flags;
    vpix->hw = hw;

    if (!vmwgfx_pixmap_add_damage(pixmap))
	goto out_no_damage;

    vpix->backing |= VMWGFX_PIX_SURFACE;
    vmwgfx_pixmap_free_storage(vpix);

    /*
     * If there is a HW surface, make sure that the shadow is
     * (or will be) a GMR, provided we can do fast DMAs from / to it.
     */
    vmwgfx_prefer_gmr(vsaa, pixmap);

    return TRUE;

out_no_damage:
    vpix->hw = NULL;
    xa_surface_destroy(hw);
    return FALSE;
}


Bool
vmwgfx_hw_validate(PixmapPtr pixmap, RegionPtr region)
{
    struct vmwgfx_saa *vsaa =
	to_vmwgfx_saa(saa_get_driver(pixmap->drawable.pScreen));
    struct saa_pixmap *spix = saa_get_saa_pixmap(pixmap);
    struct vmwgfx_saa_pixmap *vpix = to_vmwgfx_saa_pixmap(spix);
    RegionRec intersection;

    if (!vmwgfx_pixmap_present_readback(vsaa, pixmap, region))
	return FALSE;

    REGION_NULL(vsaa->pScreen, &intersection);
    REGION_COPY(vsaa->pScreen, &intersection, &spix->dirty_shadow);

    if (vpix->dirty_present)
	REGION_UNION(vsaa->pScreen, &intersection, vpix->dirty_present,
		     &spix->dirty_shadow);

    if (spix->damage && REGION_NOTEMPTY(vsaa->pScreen, &intersection)) {
	RegionPtr upload = &intersection;

	/*
	 * Check whether we need to upload from GMR.
	 */

	if (region) {
	    REGION_INTERSECT(vsaa->pScreen, &intersection, region,
			     &intersection);
	    upload = &intersection;
	}

	if (REGION_NOTEMPTY(vsaa->pScreen, upload)) {
	    Bool ret = vmwgfx_upload_to_hw(&vsaa->driver, pixmap, upload);
	    if (ret) {
		REGION_SUBTRACT(vsaa->pScreen, &spix->dirty_shadow,
				&spix->dirty_shadow, upload);
		if (vpix->dirty_present)
		    REGION_SUBTRACT(vsaa->pScreen, vpix->dirty_present,
				    vpix->dirty_present, upload);
	    } else {
		REGION_UNINIT(vsaa->pScreen, &intersection);
		return FALSE;
	    }
	}
    }
    REGION_UNINIT(vsaa->pScreen, &intersection);
    return TRUE;
}

static Bool
vmwgfx_copy_prepare(struct saa_driver *driver,
		    PixmapPtr src_pixmap,
		    PixmapPtr dst_pixmap,
		    int dx,
		    int dy,
		    int alu,
		    RegionPtr src_reg,
		    uint32_t plane_mask)
{
    struct vmwgfx_saa *vsaa = to_vmwgfx_saa(driver);
    struct vmwgfx_saa_pixmap *src_vpix;
    struct vmwgfx_saa_pixmap *dst_vpix;
    Bool has_dirty_hw;
    Bool has_valid_hw;

    if (!vsaa->xat || !SAA_PM_IS_SOLID(&dst_pixmap->drawable, plane_mask) ||
	alu != GXcopy || !vsaa->is_master)
	return FALSE;

    src_vpix = vmwgfx_saa_pixmap(src_pixmap);
    dst_vpix = vmwgfx_saa_pixmap(dst_pixmap);

    vmwgfx_check_hw_contents(vsaa, src_vpix, src_reg,
			     &has_dirty_hw, &has_valid_hw);

    if (vmwgfx_is_present_hw(dst_pixmap) &&
	src_vpix->backing & VMWGFX_PIX_SURFACE) {

	if (!has_dirty_hw && !has_valid_hw)
	    return FALSE;

	if (!vmwgfx_hw_accel_validate(src_pixmap, 0, 0, 0, src_reg))
	    return FALSE;
	if (vmwgfx_present_prepare(vsaa, src_vpix, dst_vpix)) {
	    vsaa->present_copy = TRUE;
	    return TRUE;
	}
	return FALSE;
    }

    vsaa->present_copy = FALSE;
    if (src_vpix != dst_vpix) {

	/*
	 * Use hardware acceleration either if source is partially only
	 * in hardware, or if source is entirely in hardware and destination
	 * has a hardware surface.
	 */

	if (!has_dirty_hw && !(has_valid_hw && (dst_vpix->hw != NULL)))
	    return FALSE;

	/*
	 * Determine surface formats.
	 */

	if (src_vpix->base.src_format == 0) {
	    if (!vmwgfx_hw_accel_stage(src_pixmap, 0, XA_FLAG_RENDER_TARGET, 0))
		return FALSE;
	} else {
	    if (PICT_FORMAT_TYPE(src_vpix->base.src_format) != PICT_TYPE_ARGB ||
		!vmwgfx_hw_composite_src_stage(src_pixmap, src_vpix->base.src_format))
		return FALSE;
	}

	if (dst_vpix->base.dst_format == 0) {
	    if (!vmwgfx_hw_accel_stage(dst_pixmap, 0, XA_FLAG_RENDER_TARGET, 0))
		return FALSE;
	} else {
	    if (PICT_FORMAT_TYPE(dst_vpix->base.dst_format) != PICT_TYPE_ARGB ||
		!vmwgfx_hw_composite_dst_stage(dst_pixmap, dst_vpix->base.dst_format))
		return FALSE;
	}

	/*
	 * Create hardware surfaces.
	 */

	if (!vmwgfx_hw_commit(src_pixmap))
	    return FALSE;
	if (!vmwgfx_hw_commit(dst_pixmap))
	    return FALSE;

	/*
	 * Migrate data.
	 */

	if (!vmwgfx_hw_validate(src_pixmap, src_reg)) {
	    xa_copy_done(vsaa->xa_ctx);
	    xa_context_flush(vsaa->xa_ctx);
	    return FALSE;
	}

	/*
	 * Setup copy state.
	 */

	if (xa_copy_prepare(vsaa->xa_ctx, dst_vpix->hw, src_vpix->hw) !=
	    XA_ERR_NONE)
	    return FALSE;

	return TRUE;
    }

    return FALSE;
}


static void
vmwgfx_present_done(struct vmwgfx_saa *vsaa)
{
    ScreenPtr pScreen = vsaa->pScreen;
    struct vmwgfx_saa_pixmap *dst_vpix = vsaa->dst_vpix;

    (void) pScreen;
    if (!vsaa->diff_valid)
	return;

    (void) vmwgfx_present(vsaa->drm_fd, dst_vpix->fb_id,
			  vsaa->xdiff, vsaa->ydiff,
			  &vsaa->present_region, vsaa->src_handle);

    REGION_TRANSLATE(pScreen, &vsaa->present_region, vsaa->xdiff, vsaa->ydiff);
    REGION_UNION(pScreen, dst_vpix->present_damage, dst_vpix->present_damage,
		 &vsaa->present_region);
    vsaa->diff_valid = FALSE;
    REGION_UNINIT(pScreen, &vsaa->present_region);
}

static void
vmwgfx_present_copy(struct vmwgfx_saa *vsaa,
		    int src_x,
		    int src_y,
		    int dst_x,
		    int dst_y,
		    int w,
		    int h)
{
    int xdiff = dst_x - src_x;
    int ydiff = dst_y - src_y;
    BoxRec box;
    RegionRec reg;

    if (vsaa->diff_valid && ((xdiff != vsaa->xdiff) || (ydiff != vsaa->ydiff)))
	(void) vmwgfx_present_done(vsaa);

    if (!vsaa->diff_valid) {
	vsaa->xdiff = xdiff;
	vsaa->ydiff = ydiff;
	vsaa->diff_valid = TRUE;
    }

    box.x1 = src_x;
    box.x2 = src_x + w;
    box.y1 = src_y;
    box.y2 = src_y + h;

    REGION_INIT(pScreen, &reg, &box, 1);
    REGION_UNION(pScreen, &vsaa->present_region, &vsaa->present_region, &reg);
    REGION_UNINIT(pScreen, &reg);
}

static void
vmwgfx_copy(struct saa_driver *driver,
	    int src_x,
	    int src_y,
	    int dst_x,
	    int dst_y,
	    int w,
	    int h)
{
    struct vmwgfx_saa *vsaa = to_vmwgfx_saa(driver);

    if (vsaa->present_copy) {
	vmwgfx_present_copy(vsaa, src_x, src_y, dst_x, dst_y, w, h);
	return;
    }
    xa_copy(vsaa->xa_ctx, dst_x, dst_y, src_x, src_y, w, h);
}

static void
vmwgfx_copy_done(struct saa_driver *driver)
{
    struct vmwgfx_saa *vsaa = to_vmwgfx_saa(driver);

    if (vsaa->present_copy) {
	vmwgfx_present_done(vsaa);
	return;
    }
    xa_copy_done(vsaa->xa_ctx);
    xa_context_flush(vsaa->xa_ctx);
}

static Bool
vmwgfx_composite_prepare(struct saa_driver *driver, CARD8 op,
			 PicturePtr src_pict, PicturePtr mask_pict,
			 PicturePtr dst_pict,
			 PixmapPtr src_pix, PixmapPtr mask_pix,
			 PixmapPtr dst_pix,
			 RegionPtr src_region,
			 RegionPtr mask_region,
			 RegionPtr dst_region)
{
    struct vmwgfx_saa *vsaa = to_vmwgfx_saa(driver);
    struct vmwgfx_saa_pixmap *src_vpix;
    struct vmwgfx_saa_pixmap *dst_vpix;
    struct vmwgfx_saa_pixmap *mask_vpix;
    Bool tmp_valid_hw;
    Bool dirty_hw;
    Bool valid_hw;
    RegionRec empty;
    struct xa_composite *xa_comp;

    if (!vsaa->is_master)
	return FALSE;

    REGION_NULL(pScreen, &empty);

    /*
     * First we define our migration policy. We accelerate only if there
     * are dirty hw regions to be read or if all source data is
     * available in hw, and the destination has a hardware surface.
     */
    dst_vpix = vmwgfx_saa_pixmap(dst_pix);
    valid_hw = (dst_vpix->hw != NULL);
    if (saa_op_reads_destination(op)) {
	vmwgfx_check_hw_contents(vsaa, dst_vpix, dst_region,
				 &dirty_hw, &tmp_valid_hw);
	valid_hw = (valid_hw && tmp_valid_hw);
    } else {
	dirty_hw = FALSE;
	dst_region = &empty;
    }

    if (src_pix && !dirty_hw) {
	src_vpix = vmwgfx_saa_pixmap(src_pix);
	vmwgfx_check_hw_contents(vsaa, src_vpix, src_region,
				 &dirty_hw, &tmp_valid_hw);
	valid_hw = (valid_hw && tmp_valid_hw);
    }

    if (mask_pict && mask_pix && !dirty_hw) {
	mask_vpix = vmwgfx_saa_pixmap(mask_pix);
	vmwgfx_check_hw_contents(vsaa, mask_vpix, mask_region,
				 &dirty_hw, &tmp_valid_hw);
	valid_hw = (valid_hw && tmp_valid_hw);
    }

    /*
     * In rendercheck mode we try to accelerate all supported
     * composite operations.
     */

    if (!valid_hw && !dirty_hw && !vsaa->rendercheck)
	goto out_err;

    /*
     * Then, setup most of the XA composite state (except hardware surfaces)
     * and check whether XA can accelerate.
     */

    if (!mask_pix)
	mask_pict = NULL;
    xa_comp = vmwgfx_xa_setup_comp(vsaa->vcomp, op,
				   src_pict, mask_pict, dst_pict);
    if (!xa_comp)
	goto out_err;

    if (xa_composite_check_accelerated(xa_comp) != XA_ERR_NONE)
	goto out_err;

    /*
     * Check that we can create the needed hardware surfaces.
     */
    if (src_pix && !vmwgfx_hw_composite_src_stage(src_pix, src_pict->format))
	goto out_err;
    if (mask_pict && mask_pix &&
	!vmwgfx_hw_composite_src_stage(mask_pix, mask_pict->format))
	goto out_err;
    if (!vmwgfx_hw_composite_dst_stage(dst_pix, dst_pict->format))
	goto out_err;

    /*
     * Seems OK. Commit the changes, creating hardware surfaces.
     */
    if (src_pix && !vmwgfx_hw_commit(src_pix))
	goto out_err;
    if (mask_pict && mask_pix && !vmwgfx_hw_commit(mask_pix))
	goto out_err;
    if (!vmwgfx_hw_commit(dst_pix))
	goto out_err;

    /*
     * Update the XA state with our hardware surfaces and
     * surface formats
     */
    if (!vmwgfx_xa_update_comp(xa_comp, src_pix, mask_pix, dst_pix))
	goto out_err;

    /*
     * Migrate data to surfaces.
     */
    if (src_pix && src_region && !vmwgfx_hw_validate(src_pix, NULL))
	goto out_err;
    if (mask_pict && mask_pix && mask_region &&
	!vmwgfx_hw_validate(mask_pix, NULL))
	goto out_err;
    if (dst_region && !vmwgfx_hw_validate(dst_pix, NULL))
	goto out_err;


    /*
     * Bind the XA state. This must be done after data migration, since
     * migration may change the hardware surfaces.
     */
    if (xa_composite_prepare(vsaa->xa_ctx, xa_comp))
	goto out_err;

    return TRUE;

  out_err:
    return FALSE;
}

static void
vmwgfx_composite(struct saa_driver *driver,
		 int src_x, int src_y, int mask_x, int mask_y,
		 int dst_x, int dst_y,
		 int width, int height)
{
    struct vmwgfx_saa *vsaa = to_vmwgfx_saa(driver);

    xa_composite_rect(vsaa->xa_ctx, src_x, src_y, mask_x, mask_y,
		      dst_x, dst_y, width, height);
}

static void
vmwgfx_composite_done(struct saa_driver *driver)
{
   struct vmwgfx_saa *vsaa = to_vmwgfx_saa(driver);

   xa_composite_done(vsaa->xa_ctx);
   xa_context_flush(vsaa->xa_ctx);
}

static void
vmwgfx_takedown(struct saa_driver *driver)
{
    struct vmwgfx_saa *vsaa = to_vmwgfx_saa(driver);

    if (vsaa->vcomp)
	vmwgfx_free_composite(vsaa->vcomp);
    free(vsaa);
}

/*
 * This function call originates from the damage layer (outside SAA)
 * to indicate that an operation is complete, and that damage is being
 * processed.
 */
static void
vmwgfx_operation_complete(struct saa_driver *driver,
			  PixmapPtr pixmap)
{
    struct vmwgfx_saa *vsaa = to_vmwgfx_saa(driver);
    struct saa_pixmap *spix = saa_get_saa_pixmap(pixmap);
    struct vmwgfx_saa_pixmap *vpix = to_vmwgfx_saa_pixmap(spix);
    ScrnInfoPtr pScrn = xf86ScreenToScrn(vsaa->pScreen);

    /*
     * Make dri2 drawables up to date, or add them to the flush list
     * executed at glxWaitX(). Currently glxWaitX() is broken, so
     * we flush immediately, unless we're VT-switched away, in which
     * case a flush would deadlock in the kernel.
     *
     * For pixmaps for which vpix->hw_is_hosted is true, we can explicitly
     * inform the compositor when contents has changed, so for those pixmaps
     * we defer the upload until the compositor is informed, by putting
     * them on the sync_x_list. Note that hw_is_dri2_fronts take precedence.
     */
    if (vpix->hw && (vpix->hw_is_dri2_fronts || vpix->hw_is_hosted)) {
	if (pScrn->vtSema && vpix->hw_is_dri2_fronts &&
	    vmwgfx_upload_to_hw(driver, pixmap, &spix->dirty_shadow)) {

	    REGION_EMPTY(vsaa->pScreen, &spix->dirty_shadow);
	    return;
	}

	if (WSBMLISTEMPTY(&vpix->sync_x_head))
	    WSBMLISTADDTAIL(&vpix->sync_x_head, &vsaa->sync_x_list);
    }
}

/*
 * This function is called by SAA to indicate that SAA has
 * dirtied a region of a pixmap, either as hw (accelerated) or as
 * !hw (not accelerated).
 */
static Bool
vmwgfx_dirty(struct saa_driver *driver, PixmapPtr pixmap,
	     Bool hw, RegionPtr damage)
{
    struct vmwgfx_saa *vsaa = to_vmwgfx_saa(driver);
    struct saa_pixmap *spix = saa_get_saa_pixmap(pixmap);
    struct vmwgfx_saa_pixmap *vpix = to_vmwgfx_saa_pixmap(spix);

    /*
     * Return if this is not a scanout pixmap.
     */
    if (WSBMLISTEMPTY(&vpix->scanout_list))
	return TRUE;

#if 0
    /*
     * This code can be enabled to immediately upload scanout sw
     * contents to the hw surface. Otherwise this is done
     * just before we call the kms update function for the hw
     * surface.
     */
    if (vpix->scanout_hw) {
	if (!hw && !vmwgfx_upload_to_hw(&vsaa->driver, pixmap, damage))
	    return FALSE;

	REGION_SUBTRACT(&vsaa->pScreen, &spix->dirty_shadow,
			&spix->dirty_shadow, damage);
	hw = TRUE;
    }
#endif

    /*
     * Is the new scanout damage hw or sw?
     */
    if (hw) {
	/*
	 * Dump pending present into present tracking region.
	 */
	if (vpix->dirty_present &&
	    REGION_NOTEMPTY(vsaa->pScreen, vpix->present_damage)) {
	    REGION_UNION(vsaa->pScreen, vpix->dirty_present,
			 vpix->dirty_present, damage);
	    REGION_EMPTY(vsaa->pScreen, vpix->present_damage);
	} else {
	    if (REGION_NOTEMPTY(vsaa->pScreen, vpix->pending_update)) {
		RegionRec reg;

		REGION_NULL(vsaa->pScreen, &reg);
		REGION_INTERSECT(vsaa->pScreen, &reg, vpix->pending_update,
				 damage);
		if (REGION_NOTEMPTY(vsaa->pScreen, &reg))
		    vsaa->present_flush(vsaa->pScreen);
		REGION_UNINIT(pScreen, &reg);
	    }
	    REGION_UNION(vsaa->pScreen, vpix->pending_present,
			 vpix->pending_present, damage);
	    if (vpix->dirty_present)
		REGION_SUBTRACT(vsaa->pScreen, vpix->dirty_present,
				vpix->dirty_present, damage);
	}
    } else {
	    if (REGION_NOTEMPTY(vsaa->pScreen, vpix->pending_present)) {
		RegionRec reg;

		REGION_NULL(vsaa->pScreen, &reg);
		REGION_INTERSECT(vsaa->pScreen, &reg, vpix->pending_present,
				 damage);
		if (REGION_NOTEMPTY(vsaa->pScreen, &reg))
		    vsaa->present_flush(vsaa->pScreen);
		REGION_UNINIT(pScreen, &reg);
	    }
	    REGION_UNION(vsaa->pScreen, vpix->pending_update,
			 vpix->pending_update, damage);
	    if (vpix->dirty_present)
		REGION_SUBTRACT(vsaa->pScreen, vpix->dirty_present,
				vpix->dirty_present, damage);
    }

    return TRUE;
}


static const struct saa_driver vmwgfx_saa_driver = {
    .saa_major = SAA_VERSION_MAJOR,
    .saa_minor = SAA_VERSION_MINOR,
    .pixmap_size = sizeof(struct vmwgfx_saa_pixmap),
    .damage = vmwgfx_dirty,
    .operation_complete = vmwgfx_operation_complete,
    .download_from_hw = vmwgfx_download_from_hw,
    .release_from_cpu = vmwgfx_release_from_cpu,
    .sync_for_cpu = vmwgfx_sync_for_cpu,
    .map = vmwgfx_map,
    .unmap = vmwgfx_unmap,
    .create_pixmap = vmwgfx_create_pixmap,
    .destroy_pixmap = vmwgfx_destroy_pixmap,
    .modify_pixmap_header = vmwgfx_modify_pixmap_header,
    .copy_prepare = vmwgfx_copy_prepare,
    .copy = vmwgfx_copy,
    .copy_done = vmwgfx_copy_done,
    .composite_prepare = vmwgfx_composite_prepare,
    .composite = vmwgfx_composite,
    .composite_done = vmwgfx_composite_done,
    .takedown = vmwgfx_takedown,
};


Bool
vmwgfx_saa_init(ScreenPtr pScreen, int drm_fd, struct xa_tracker *xat,
		void (*present_flush)(ScreenPtr pScreen),
		Bool direct_presents,
		Bool only_hw_presents,
		Bool rendercheck,
		Bool has_screen_targets)
{
    struct vmwgfx_saa *vsaa;

    vsaa = calloc(1, sizeof(*vsaa));
    if (!vsaa)
	return FALSE;

    if (xat == NULL) {
	direct_presents = FALSE;
	only_hw_presents = FALSE;
	has_screen_targets = FALSE;
    }

    vsaa->pScreen = pScreen;
    vsaa->xat = xat;
    if (xat)
	vsaa->xa_ctx = xa_context_default(xat);
    vsaa->drm_fd = drm_fd;
    vsaa->present_flush = present_flush;
    vsaa->can_optimize_dma = TRUE;
    vsaa->use_present_opt = direct_presents;
    vsaa->only_hw_presents = only_hw_presents;
    vsaa->rendercheck = rendercheck;
    vsaa->is_master = TRUE;
    vsaa->known_prime_format = FALSE;
    vsaa->has_screen_targets = has_screen_targets;
    WSBMINITLISTHEAD(&vsaa->sync_x_list);
    WSBMINITLISTHEAD(&vsaa->pixmaps);

    vsaa->driver = vmwgfx_saa_driver;
    vsaa->vcomp = vmwgfx_alloc_composite();

    if (!vsaa->vcomp)
	vsaa->driver.composite_prepare = NULL;

    if (!saa_driver_init(pScreen, &vsaa->driver))
	goto out_no_saa;

    return TRUE;
  out_no_saa:
    free(vsaa);
    return FALSE;
}

/*
 * *************************************************************************
 * Scanout functions.
 * These do not strictly belong here, but we choose to hide the scanout
 * pixmap private data in the saa pixmaps. Might want to revisit this.
 */

/*
 * Make sure we flush / update this scanout on next update run.
 */

void
vmwgfx_scanout_refresh(PixmapPtr pixmap)
{
    ScreenPtr pScreen = pixmap->drawable.pScreen;
    struct vmwgfx_saa_pixmap *vpix = vmwgfx_saa_pixmap(pixmap);
    BoxRec box;

    (void) pScreen;
    box.x1 = 0;
    box.y1 = 0;
    box.x2 = pixmap->drawable.width;
    box.y2 = pixmap->drawable.height;

    REGION_RESET(vsaa->pScreen, vpix->pending_present, &box);
    if (vpix->dirty_present)
	REGION_SUBTRACT(vsaa->pScreen, vpix->pending_present,
			vpix->pending_present, vpix->dirty_present);
    REGION_SUBTRACT(vsaa->pScreen, vpix->pending_present,
		    vpix->pending_present, &vpix->base.dirty_shadow);
    REGION_COPY(vsaa->pScreen, vpix->pending_update,
		&vpix->base.dirty_shadow);
}

/*
 * Take a "scanout reference" on a pixmap. If this is the first scanout
 * reference, allocate resources needed for scanout, like proper
 * damage tracking and kms fbs.
 */

uint32_t
vmwgfx_scanout_ref(struct vmwgfx_screen_entry  *entry,
		   Bool scanout_equals_pixmap)
{
    PixmapPtr pixmap = entry->pixmap;
    struct vmwgfx_saa *vsaa =
	to_vmwgfx_saa(saa_get_driver(pixmap->drawable.pScreen));
    struct vmwgfx_saa_pixmap *vpix = vmwgfx_saa_pixmap(pixmap);

    if (WSBMLISTEMPTY(&vpix->scanout_list)) {
	uint32_t handle, dummy;
	unsigned int depth;

	vpix->scanout_hw = vsaa->only_hw_presents ||
	    (vsaa->has_screen_targets && scanout_equals_pixmap);

	if (vpix->scanout_hw) {
	    /*
	     * The KMS fb will be a HW surface. Create it, add damage
	     * and get the handle.
	     */
	    if (!vmwgfx_hw_accel_validate(pixmap, 0, XA_FLAG_SCANOUT |
					  XA_FLAG_RENDER_TARGET, 0, NULL))
		goto out_err;
	    if (_xa_surface_handle(vpix->hw, &handle, &dummy) != 0)
		goto out_err;
	    depth = xa_format_depth(xa_surface_format(vpix->hw));

	} else {
	    /*
	     * The KMS fb will be a Guest Memory Region. Create it,
	     * add damage and get the handle.
	     */
	    if (!vmwgfx_pixmap_create_gmr(vsaa, pixmap))
		goto out_err;

	    handle = vpix->gmr->handle;
	    depth = pixmap->drawable.depth;

	}

        if (!vmwgfx_pixmap_add_present(pixmap, vsaa->use_present_opt))
	    goto out_no_present;

	if (drmModeAddFB(vsaa->drm_fd,
			 pixmap->drawable.width,
			 pixmap->drawable.height,
			 depth,
			 pixmap->drawable.bitsPerPixel,
			 pixmap->devKind,
			 handle,
			 &vpix->fb_id) != 0)
	    goto out_no_fb;;
    }
    pixmap->refcnt += 1;
    WSBMLISTADDTAIL(&entry->scanout_head, &vpix->scanout_list);
    return vpix->fb_id;

  out_no_fb:
    vmwgfx_pixmap_remove_present(vpix);
  out_no_present:
    vmwgfx_pixmap_remove_damage(pixmap);
  out_err:
    vpix->fb_id = -1;
    return -1;
}

/*
 * Free a "scanout reference" on a pixmap. If this was the last scanout
 * reference, free pixmap resources needed for scanout, like
 * damage tracking and kms fbs.
 */
void
vmwgfx_scanout_unref(struct vmwgfx_screen_entry *entry)
{
    struct vmwgfx_saa *vsaa;
    struct vmwgfx_saa_pixmap *vpix;
    PixmapPtr pixmap = entry->pixmap;

    if (!pixmap)
	return;

    vsaa = to_vmwgfx_saa(saa_get_driver(pixmap->drawable.pScreen));
    vpix = vmwgfx_saa_pixmap(pixmap);
    WSBMLISTDELINIT(&entry->scanout_head);

    if (WSBMLISTEMPTY(&vpix->scanout_list)) {
	REGION_EMPTY(vsaa->pScreen, vpix->pending_update);
	drmModeRmFB(vsaa->drm_fd, vpix->fb_id);
	vpix->fb_id = -1;
	vmwgfx_pixmap_present_readback(vsaa, pixmap, NULL);
	vmwgfx_pixmap_remove_present(vpix);
	vmwgfx_pixmap_remove_damage(pixmap);
    }

    entry->pixmap = NULL;
    pixmap->drawable.pScreen->DestroyPixmap(pixmap);
}

void
vmwgfx_saa_set_master(ScreenPtr pScreen)
{
    struct vmwgfx_saa *vsaa = to_vmwgfx_saa(saa_get_driver(pScreen));

    vsaa->is_master = TRUE;
    vmwgfx_flush_dri2(pScreen);
}

void
vmwgfx_saa_drop_master(ScreenPtr pScreen)
{
    struct vmwgfx_saa *vsaa = to_vmwgfx_saa(saa_get_driver(pScreen));
    struct _WsbmListHead *list;
    struct vmwgfx_saa_pixmap *vpix;
    struct saa_pixmap *spix;

    WSBMLISTFOREACH(list, &vsaa->pixmaps) {
	vpix = WSBMLISTENTRY(list, struct vmwgfx_saa_pixmap, pixmap_list);
	spix = &vpix->base;

	if (!vpix->hw)
	    continue;

	(void) vmwgfx_download_from_hw(&vsaa->driver, spix->pixmap,
				       &spix->dirty_hw);
	REGION_EMPTY(draw->pScreen, &spix->dirty_hw);
    }

    vsaa->is_master = FALSE;
}

/*
 * *************************************************************************
 * Helpers for hosted.
 */

#if (XA_TRACKER_VERSION_MAJOR >= 2) && defined(HAVE_LIBDRM_2_4_38)

/**
 * vmwgfx_saa_copy_to_surface - Copy Drawable contents to an external surface.
 *
 * @pDraw: Pointer to source drawable.
 * @surface_fd: Prime file descriptor of external surface to copy to.
 * @dst_box: BoxRec describing the destination bounding box.
 * @region: Region of drawable to copy. Note: The code assumes that the
 * region is relative to the drawable origin, not the underlying pixmap
 * origin.
 *
 * Copies the contents (both software- and accelerated contents) to an
 * external surface.
 */
Bool
vmwgfx_saa_copy_to_surface(DrawablePtr pDraw, uint32_t surface_fd,
			   const BoxRec *dst_box, RegionPtr region)
{
    ScreenPtr pScreen = pDraw->pScreen;
    struct vmwgfx_saa *vsaa = to_vmwgfx_saa(saa_get_driver(pScreen));
    PixmapPtr src;
    struct saa_pixmap *spix;
    struct vmwgfx_saa_pixmap *vpix;
    const BoxRec *box;
    int n;
    int sx, sy, dx, dy;
    struct xa_surface *dst;
    uint32_t handle;
    Bool ret = TRUE;
    RegionRec intersection;
    RegionPtr copy_region = region;

    if (vmwgfx_prime_fd_to_handle(vsaa->drm_fd, surface_fd, &handle) < 0)
	return FALSE;

    dst = xa_surface_from_handle(vsaa->xat, pDraw->width, pDraw->height,
				 pDraw->depth, xa_type_argb,
				 xa_format_unknown,
				 XA_FLAG_SHARED | XA_FLAG_RENDER_TARGET,
				 handle,
				 (pDraw->width * pDraw->bitsPerPixel + 7) / 8);

    if (!dst) {
	ret = FALSE;
	goto out_no_surface;
    }

    /*
     * Assume damage region is relative to the source window.
     */
    src = saa_get_pixmap(pDraw, &sx, &sy);
    sx += pDraw->x;
    sy += pDraw->y;
    if (sx || sy)
	REGION_TRANSLATE(pScreen, region, sx, sy);

    dx = dst_box->x1 - sx;
    dy = dst_box->y1 - sy;

    spix = saa_get_saa_pixmap(src);
    vpix = to_vmwgfx_saa_pixmap(spix);

    /*
     * Make sure software contents of the source pixmap is henceforth put
     * in a GMR to avoid the extra copy in the xa DMA.
     */
    vmwgfx_prefer_gmr(vsaa, src);

    /*
     * Determine the intersection between software contents and region to copy.
     */

    if (vsaa->known_prime_format) {
	REGION_NULL(pScreen, &intersection);
	if (!vpix->hw)
	    REGION_COPY(pScreen, &intersection, region);
	else if (spix->damage && REGION_NOTEMPTY(pScreen, &spix->dirty_shadow))
	    REGION_INTERSECT(pScreen, &intersection, region, &spix->dirty_shadow);

	/*
	 * DMA software contents directly into the destination. Then subtract
	 * the region we've DMA'd from the region to copy.
	 */
	if (REGION_NOTEMPTY(pScreen, &intersection)) {
	    if (vmwgfx_saa_dma(vsaa, src, &intersection, TRUE, dx, dy, dst)) {
		REGION_SUBTRACT(pScreen, &intersection, region, &intersection);
		copy_region = &intersection;
	    }
	}
    }

    if (!REGION_NOTEMPTY(pScreen, copy_region))
	goto out_no_copy;

    /*
     * Copy Hardware contents to the destination
     */
    box = REGION_RECTS(copy_region);
    n = REGION_NUM_RECTS(copy_region);

    if (!vmwgfx_hw_accel_validate(src, 0, 0, 0, copy_region)) {
	ret = FALSE;
	goto out_no_copy;
    }

    if (xa_copy_prepare(vsaa->xa_ctx, dst, vpix->hw) != XA_ERR_NONE) {
	ret = FALSE;
	goto out_no_copy;
    }

    while(n--) {
	xa_copy(vsaa->xa_ctx, box->x1 + dx, box->y1 + dy, box->x1, box->y1,
		box->x2 - box->x1, box->y2 - box->y1);
	box++;
    }

    xa_copy_done(vsaa->xa_ctx);
    xa_context_flush(vsaa->xa_ctx);

  out_no_copy:
    if (vsaa->known_prime_format)
	REGION_UNINIT(pScreen, &intersection);
    if (sx || sy)
	REGION_TRANSLATE(pScreen, region, -sx, -sy);
    xa_surface_unref(dst);
  out_no_surface:
    vmwgfx_prime_release_handle(vsaa->drm_fd, handle);

    return ret;
}
#endif
07070100000049000081A400000000000000000000000161A68E120000109E000000000000000000000000000000000000003000000000xf86-video-vmware-13.3.0+12/vmwgfx/vmwgfx_saa.h/*
 * 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 _VMWGFX_SAA_H_
#define _VMWGFX_SAA_H_

#include "saa.h"
#include <xa_composite.h>
#include "vmwgfx_drmi.h"
#include "wsbm_util.h"


#define VMWGFX_FLAG_FORCE_GMR     (1 << 0) /* Create with GMR as backing store */
#define VMWGFX_FLAG_FORCE_SURFACE (1 << 1) /* Create with surface as backing store */
#define VMWGFX_FLAG_AVOID_HWACCEL (1 << 2) /* Avoid Hardware acceleration on this pixmap */
#define VMWGFX_FLAG_USE_PRESENT   (1 << 3) /* Use presents when copying to this pixmap */

struct vmwgfx_saa_pixmap {
    struct saa_pixmap base;
    RegionPtr dirty_present;
    RegionPtr present_damage;
    RegionPtr pending_update;
    RegionPtr pending_present;
    uint32_t usage_flags;
    uint32_t backing;
    void *malloc;
    struct vmwgfx_dmabuf *gmr;
    struct xa_surface *hw;
    uint32_t fb_id;
    int hw_is_dri2_fronts;
    Bool hw_is_hosted;
    struct _WsbmListHead sync_x_head;
    struct _WsbmListHead scanout_list;
    struct _WsbmListHead pixmap_list;
    Bool scanout_hw;

    uint32_t xa_flags;
    uint32_t staging_add_flags;
    uint32_t staging_remove_flags;
    enum xa_formats staging_format;
};

struct vmwgfx_screen_entry {
    struct _WsbmListHead scanout_head;
    PixmapPtr pixmap;
};

static inline struct vmwgfx_saa_pixmap *
to_vmwgfx_saa_pixmap(struct saa_pixmap *spix)
{
    return (struct vmwgfx_saa_pixmap *) spix;
}

static inline struct vmwgfx_saa_pixmap*
vmwgfx_saa_pixmap(PixmapPtr pix)
{
    return to_vmwgfx_saa_pixmap(saa_get_saa_pixmap(pix));
}

extern Bool
vmwgfx_saa_init(ScreenPtr pScreen, int drm_fd, struct xa_tracker *xat,
		void (*present_flush)(ScreenPtr pScreen),
		Bool direct_presents,
		Bool only_hw_presents,
		Bool rendercheck,
		Bool has_screen_targets);

extern uint32_t
vmwgfx_scanout_ref(struct vmwgfx_screen_entry *entry,
		   Bool scanout_equals_pixmap);

extern void
vmwgfx_scanout_unref(struct vmwgfx_screen_entry *box);

extern void
vmwgfx_scanout_refresh(PixmapPtr pixmap);

extern void
vmwgfx_remove_dri2_list(struct vmwgfx_saa_pixmap *vpix);

extern void
vmwgfx_flush_dri2(ScreenPtr pScreen);

extern Bool
vmwgfx_hw_dri2_validate(PixmapPtr pixmap, unsigned int depth);

Bool
vmwgfx_hw_accel_validate(PixmapPtr pixmap, unsigned int depth,
			 uint32_t add_flags, uint32_t remove_flags,
			 RegionPtr region);

void
vmwgfx_saa_set_master(ScreenPtr pScreen);

void
vmwgfx_saa_drop_master(ScreenPtr pScreen);

#if (XA_TRACKER_VERSION_MAJOR >= 2) && defined(HAVE_LIBDRM_2_4_38)
Bool
vmwgfx_saa_copy_to_surface(DrawablePtr pDraw, uint32_t surface_fd,
			   const BoxRec *dst_box, RegionPtr region);
#endif /* (XA_TRACKER_VERSION_MAJOR >= 2) && defined(HAVE_LIBDRM_2_4_38) */

#if (XA_TRACKER_VERSION_MAJOR <= 1) && !defined(HAVE_XA_2)

#define _xa_surface_handle(_a, _b, _c) xa_surface_handle(_a, _b, _c)
#define xa_context_flush(_a)

#else

#define xa_surface_destroy(_a) xa_surface_unref(_a)
#define _xa_surface_handle(_a, _b, _c)		\
    xa_surface_handle(_a, xa_handle_type_shared, _b, _c)

#endif /*  (XA_TRACKER_VERSION_MAJOR <= 1) */
#endif
0707010000004A000081A400000000000000000000000161A68E1200000F19000000000000000000000000000000000000003500000000xf86-video-vmware-13.3.0+12/vmwgfx/vmwgfx_saa_priv.h/*
 * 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 _VMWGFX_SAA_PRIV_H_
#define _VMWGFX_SAA_PRIV_H_

#define VMWGFX_PIX_MALLOC  (1 << 0)
#define VMWGFX_PIX_GMR     (1 << 1)
#define VMWGFX_PIX_SURFACE (1 << 2)

#include <xorg-server.h>
#include <picturestr.h>
#include "vmwgfx_saa.h"

struct vmwgfx_saa {
    struct saa_driver driver;
    struct vmwgfx_dma_ctx *ctx;
    struct xa_tracker *xat;
    struct xa_context *xa_ctx;
    ScreenPtr pScreen;
    int drm_fd;
    struct vmwgfx_saa_pixmap *src_vpix;
    struct vmwgfx_saa_pixmap *dst_vpix;
    Bool present_copy;
    Bool diff_valid;
    int xdiff;
    int ydiff;
    RegionRec present_region;
    uint32_t src_handle;
    Bool can_optimize_dma;
    Bool use_present_opt;
    Bool only_hw_presents;
    Bool rendercheck;
    Bool is_master;
    Bool known_prime_format;
    Bool has_screen_targets;
    void (*present_flush) (ScreenPtr pScreen);
    struct _WsbmListHead sync_x_list;
    struct _WsbmListHead pixmaps;
    struct vmwgfx_composite *vcomp;
};

static inline struct vmwgfx_saa *
to_vmwgfx_saa(struct saa_driver *driver) {
    return (struct vmwgfx_saa *) driver;
}

/*
 * In vmwgfx_saa.c
 */

Bool
vmwgfx_hw_kill(struct vmwgfx_saa *vsaa,
	       struct saa_pixmap *spix);
Bool
vmwgfx_create_hw(struct vmwgfx_saa *vsaa,
		 PixmapPtr pixmap,
		 Bool shared);


/*
 * vmwgfx_xa_surface.c
 */

enum xa_formats
vmwgfx_xa_format(enum _PictFormatShort format);
Bool
vmwgfx_hw_validate(PixmapPtr pixmap, RegionPtr region);
Bool
vmwgfx_hw_dri2_stage(PixmapPtr pixmap, unsigned int depth);
Bool
vmwgfx_hw_accel_stage(PixmapPtr pixmap, unsigned int depth,
		      uint32_t add_flags, uint32_t remove_flags);
Bool
vmwgfx_hw_composite_src_stage(PixmapPtr pixmap,
			      enum _PictFormatShort pict_format);
Bool
vmwgfx_hw_composite_dst_stage(PixmapPtr pixmap,
			      enum _PictFormatShort pict_format);
Bool
vmwgfx_hw_commit(PixmapPtr pixmap);

Bool
vmwgfx_xa_surface_redefine(struct vmwgfx_saa_pixmap *vpix,
			   struct xa_surface *srf,
			   int width,
			   int height,
			   int depth,
			   enum xa_surface_type stype,
			   enum xa_formats rgb_format,
			   unsigned int new_flags,
			   int copy_contents);

/*
 * vmwgfx_xa_composite.c
 */

struct vmwgfx_composite;

void
vmwgfx_free_composite(struct vmwgfx_composite *vcomp);
struct vmwgfx_composite *
vmwgfx_alloc_composite(void);

Bool
vmwgfx_xa_update_comp(struct xa_composite *comp,
		      PixmapPtr src_pix,
		      PixmapPtr mask_pix,
		      PixmapPtr dst_pix);

struct xa_composite *
vmwgfx_xa_setup_comp(struct vmwgfx_composite *vcomp,
		     int op,
		     PicturePtr src_pict,
		     PicturePtr mask_pict,
		     PicturePtr dst_pict);


#endif
0707010000004B000081A400000000000000000000000161A68E1200006C76000000000000000000000000000000000000003600000000xf86-video-vmware-13.3.0+12/vmwgfx/vmwgfx_tex_video.c/*
 * Copyright 2009-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>
 * Author: Zack Rusin <zackr@vmware.com>
 */
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif

#include "vmwgfx_driver.h"
#include "vmwgfx_drmi.h"
#include "vmwgfx_saa.h"
#include "../src/common_compat.h"

#include <xf86xv.h>
#include <X11/extensions/Xv.h>
#include <fourcc.h>
#include <xa_tracker.h>
#include <xa_context.h>
#include <math.h>

static CONST_ABI_16_0 char xv_adapt_name[] = "XA G3D Textured Video";

/*Xxx get these from pipe's texture limits */
#define IMAGE_MAX_WIDTH		2048
#define IMAGE_MAX_HEIGHT	2048

#define RES_720P_X 1280
#define RES_720P_Y 720


#define MAKE_ATOM(a) MakeAtom(a, sizeof(a) - 1, TRUE)

/*
 * ITU-R BT.601, BT.709 transfer matrices.
 * [R', G', B'] values are in the range [0, 1], Y' is in the range [0,1]
 * and [Pb, Pr] components are in the range [-0.5, 0.5].
 *
 * The matrices are transposed to fit the xa conversion matrix format.
 */

static const float bt_601[] = {
    1.f, 1.f, 1.f, 0.f,
    0.f, -0.344136f, 1.772f, 0.f,
    1.402f,  -0.714136f, 0.f, 0.f
};

static const float bt_709[] = {
    1.f, 1.f, 1.f, 0.f,
    0.f, -0.187324f, 1.8556f, 0.f,
    1.5748f, -0.468124f, 0.f, 0.f
};

static Atom xvBrightness, xvContrast, xvSaturation, xvHue;
static CONST_ABI_16_TO_19 char xv_brightness_name[] = "XV_BRIGHTNESS";
static CONST_ABI_16_TO_19 char xv_contrast_name[] = "XV_CONTRAST";
static CONST_ABI_16_TO_19 char xv_saturation_name[] = "XV_SATURATION";
static CONST_ABI_16_TO_19 char xv_hue_name[] = "XV_HUE";
static CONST_ABI_16_TO_19 char xv_image_name[] = "XV_IMAGE";

#define NUM_TEXTURED_ATTRIBUTES 4
static const XF86AttributeRec TexturedAttributes[NUM_TEXTURED_ATTRIBUTES] = {
    {XvSettable | XvGettable, -1000, 1000, xv_brightness_name},
    {XvSettable | XvGettable, -1000, 1000, xv_contrast_name},
    {XvSettable | XvGettable, -1000, 1000, xv_saturation_name},
    {XvSettable | XvGettable, -1000, 1000, xv_hue_name}
};

#define NUM_FORMATS 3
static XF86VideoFormatRec Formats[NUM_FORMATS] = {
   {15, TrueColor}, {16, TrueColor}, {24, TrueColor}
};

static XF86VideoEncodingRec DummyEncoding[1] = {
   {
      0,
      xv_image_name,
      IMAGE_MAX_WIDTH, IMAGE_MAX_HEIGHT,
      {1, 1}
   }
};

#define NUM_IMAGES 3
static XF86ImageRec Images[NUM_IMAGES] = {
   XVIMAGE_UYVY,
   XVIMAGE_YUY2,
   XVIMAGE_YV12,
};

struct xorg_xv_port_priv {
    struct xa_tracker *xat;
    struct xa_context *r;
    struct xa_fence *fence;

    RegionRec clip;

    int brightness;
    int contrast;
    int saturation;
    int hue;

    int current_set;
    struct xa_surface *yuv[2][3];

    struct xa_surface *bounce;
    struct xa_box bounce_box;
    struct xa_picture *src_pic;
    struct xa_picture *dst_pic;
    struct xa_composite *comp;

    int drm_fd;

    Bool hdtv;
    float uv_offset;
    float uv_scale;
    float y_offset;
    float y_scale;
    float rgb_offset;
    float rgb_scale;
    float sinhue;
    float coshue;
    float cm[16];
};

/*
 * vmwgfx_update_conversion_matrix - Compute the effective color conversion
 * matrix.
 *
 * Applies yuv- and resulting rgb scales and offsets to compute the correct
 * color conversion matrix. These scales and offsets are properties of the
 * video stream and can be adjusted using XV properties as well.
 */
static void
vmwgfx_update_conversion_matrix(struct xorg_xv_port_priv *priv)
{
    int i;
    float *cm = priv->cm;
    static const float *bt;

    bt = (priv->hdtv) ? bt_709 : bt_601;

    memcpy(cm, bt, sizeof(bt_601));

    /*
     * Apply hue rotation
     */
    cm[4] = priv->coshue * bt[4] - priv->sinhue * bt[8];
    cm[8] = priv->sinhue * bt[4] + priv->coshue * bt[8];
    cm[5] = priv->coshue * bt[5] - priv->sinhue * bt[9];
    cm[9] = priv->sinhue * bt[5] + priv->coshue * bt[9];
    cm[6] = priv->coshue * bt[6] - priv->sinhue * bt[10];
    cm[10] = priv->sinhue * bt[6] + priv->coshue * bt[10];

    /*
     * Adjust for yuv scales in input and rgb scale in the converted output.
     */
    for(i = 0; i < 3; ++i) {
	cm[i] *= (priv->y_scale*priv->rgb_scale);
	cm[i+4] *= (priv->uv_scale*priv->rgb_scale);
	cm[i+8] *= (priv->uv_scale*priv->rgb_scale);
    }

    /*
     * Adjust for yuv offsets in input and rgb offset in the converted output.
     */
    for (i = 0; i < 3; ++i)
	cm[i+12] = -cm[i]*priv->y_offset - (cm[i+4] + cm[i+8])*priv->uv_offset
	    - priv->rgb_offset*priv->rgb_scale;

    /*
     * Alpha is 1, unconditionally.
     */
    cm[15] = 1.f;
}

/**
 * vmwgfx_video_free_comp - free members used for composite bounce blit
 *
 * @priv: Pointer to the port private
 *
 * Frees any port priv resources allocated for a composite bounce blit.
 */
static void
vmwgfx_video_free_comp(struct xorg_xv_port_priv *priv)
{
    if (priv->dst_pic)
	free(priv->dst_pic);
    if (priv->src_pic)
	free(priv->src_pic);
    if (priv->comp)
	free(priv->comp);

    priv->dst_pic = NULL;
    priv->src_pic = NULL;
    priv->comp = NULL;
}

static void
stop_video(ScrnInfoPtr pScrn, pointer data, Bool shutdown)
{
   struct xorg_xv_port_priv *priv = (struct xorg_xv_port_priv *)data;
   int i, j;

   REGION_EMPTY(pScrn->pScreen, &priv->clip);
   if (shutdown) {

       /*
	* No need to destroy the xa context or xa tracker since
	* they are copied from the screen resources.
	*/

       xa_fence_destroy(priv->fence);
       priv->fence = NULL;
       vmwgfx_video_free_comp(priv);

       for (i=0; i<3; ++i) {
	   for (j=0; j<2; ++j) {
	       if (priv->yuv[i]) {
		   xa_surface_destroy(priv->yuv[j][i]);
		   priv->yuv[j][i] = NULL;
	       }
	       if (priv->bounce) {
		   xa_surface_destroy(priv->bounce);
		   priv->bounce = NULL;
	       }
	   }
       }
   }
}

static int
set_port_attribute(ScrnInfoPtr pScrn,
                   Atom attribute, INT32 value, pointer data)
{
   struct xorg_xv_port_priv *priv = (struct xorg_xv_port_priv *)data;

   if (attribute == xvBrightness) {
       if ((value < -1000) || (value > 1000))
	   return BadValue;

       priv->brightness = value;
       priv->y_offset = -((float) value)/1000.f;

   } else if (attribute == xvContrast) {
       if ((value < -1000) || (value > 1000))
	   return BadValue;

       priv->contrast = value;
       priv->rgb_scale = ((float) value + 1000.f)/1000.f;

   } else if (attribute == xvSaturation) {
       if ((value < -1000) || (value > 1000))
	   return BadValue;

       priv->saturation = value;
       priv->uv_scale = ((float) value + 1000.f)/1000.f;

   } else if (attribute == xvHue) {
       double hue_angle;

       if ((value < -1000) || (value > 1000))
	   return BadValue;

       priv->hue = value;
       hue_angle = (double) value * M_PI / 1000.;
       priv->sinhue = sin(hue_angle);
       priv->coshue = cos(hue_angle);

   } else
      return BadMatch;

   vmwgfx_update_conversion_matrix(priv);
   return Success;
}

static int
get_port_attribute(ScrnInfoPtr pScrn,
                   Atom attribute, INT32 * value, pointer data)
{
    struct xorg_xv_port_priv *priv = (struct xorg_xv_port_priv *)data;

    if (attribute == xvBrightness)
	*value = priv->brightness;
    else if (attribute == xvContrast)
	*value = priv->contrast;
    else if (attribute == xvSaturation)
	*value = priv->saturation;
    else if (attribute == xvHue)
	*value = priv->hue;
    else
	return BadMatch;

    return Success;
}

static void
query_best_size(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)
{
   if (vid_w > (drw_w << 1))
      drw_w = vid_w >> 1;
   if (vid_h > (drw_h << 1))
      drw_h = vid_h >> 1;

   *p_w = drw_w;
   *p_h = drw_h;
}

static int
check_yuv_surfaces(struct xorg_xv_port_priv *priv,  int id,
		   int width, int height)
{
    struct xa_surface **yuv = priv->yuv[priv->current_set];
    int ret = 0;
    int i;

    for (i=0; i<3; ++i) {

	/*
	 * Adjust u,v texture size and DMA buffer to what's required by
	 * the format.
	 */
	if (i == 1) {
	    switch(id) {
	    case FOURCC_YV12:
		height /= 2;
		/* Fall through */
	    case FOURCC_YUY2:
	    case FOURCC_UYVY:
		width /= 2;
		break;
	    default:
		break;
	    }
	}

	if (!yuv[i])
	    yuv[i] = xa_surface_create(priv->xat, width, height, 8,
				       xa_type_yuv_component,
				       xa_format_unknown, 0);
	else
	    ret = xa_surface_redefine(yuv[i], width, height, 8,
				      xa_type_yuv_component,
				      xa_format_unknown, 0, 0);
	if (ret || !yuv[i])
	    return BadAlloc;

    }
    return Success;
}


/**
 * vmwgfx_video_setup_comp - Set up port priv members for a composite
 * bounce blit
 *
 * @priv: Pointer to the port priv.
 * @format: XA format of the destination drawable surface.
 *
 * Tries to allocate and set up port priv resources to perform a composite
 * bounce blit (except the bounce surface itself). On failure, all resources
 * are freed. On success, TRUE is returned and @priv::comp is non-NULL. If
 * resources are already allocated, update them for the current @format.
 */
static Bool
vmwgfx_video_setup_comp(struct xorg_xv_port_priv *priv, enum xa_formats format)
{
    const struct xa_composite_allocation *alloc;
    struct xa_picture *pic;

    if (priv->comp) {
	if (priv->src_pic->pict_format != format) {
	    priv->src_pic->pict_format = format;
	    priv->dst_pic->pict_format = format;
	    if (xa_composite_check_accelerated(priv->comp) != XA_ERR_NONE) {
		vmwgfx_video_free_comp(priv);
		return FALSE;
	    }
	}
	return TRUE;
    }

    alloc = xa_composite_allocation();
    priv->comp = calloc(1, alloc->xa_composite_size);
    priv->src_pic = calloc(1, alloc->xa_picture_size);
    priv->dst_pic = calloc(1, alloc->xa_picture_size);

    if (!priv->comp || !priv->src_pic || !priv->dst_pic) {
	vmwgfx_video_free_comp(priv);
	return FALSE;
    }

    pic = priv->src_pic;
    pic->pict_format = format;
    pic->wrap = xa_wrap_clamp_to_border;
    pic->filter = xa_filter_linear;

    *priv->dst_pic = *pic;

    priv->comp->src = priv->src_pic;
    priv->comp->dst = priv->dst_pic;
    priv->comp->op = xa_op_src;
    priv->comp->no_solid = 1;

    if (xa_composite_check_accelerated(priv->comp) != XA_ERR_NONE) {
	vmwgfx_video_free_comp(priv);
	return FALSE;
    }

    return TRUE;
}

/**
 * vmwgfx_video_setup_coord_matrix - Set up a bounce - to destination
 * transformation matrix
 *
 * @src_x: Upper left corner of source image as given to putImage.
 * @src_y: Upper left corner of source image as given to putImage.
 * @src_w: Width of source image.
 * @src_h: Height of source image.
 * @dst_x: Upper left corner of destination image as given to putImage.
 * @dst_y: Upper left corner of destination image as given to putImage.
 * @dst_w: Width of destination image.
 * @dst_h: Height of destination image.
 * @bounce_w: Width of bounce surface.
 * @bounce_h: Height of bounce surface.
 * @mat: Pointer to transformation matrix.
 *
 * Computes a transformation matrix that can be used by the XA composite API
 * to transform between the destination coordinate space and the bounce
 * surface coordinate space. Scaling and translation.
 */
static void
vmwgfx_video_setup_coord_matrix(int src_x, int src_y, int src_w, int src_h,
				int dst_x, int dst_y, int dst_w, int dst_h,
				int bounce_w, int bounce_h,
				float *mat)
{
    if (dst_w == 0 || dst_h == 0 || src_w == 0 || src_h == 0) {
	mat[0] = mat[6] = 0.;
	mat[4] = mat[7] = 0.;
	mat[8] = 1.f;
	return;
    }

    mat[0] = (float) bounce_w / (float) dst_w;
    mat[6] = (float) src_x * (float) bounce_w / (float) src_w -
      (float) dst_x * mat[0];
    mat[4] = (float) bounce_h / (float) dst_h;
    mat[7] = (float) src_y * (float) bounce_h / (float) src_h -
      (float) dst_y * mat[4];
    mat[8] = 1.f;
}

/**
 * vmwgfx_video_bounce_surface: (Re)Allocate a bounce surface if desired.
 *
 * @priv: Pointer to the port private.
 * @d_with: Width of destination image.
 * @d_height: Height of destination image.
 * @width: Width of source video image.
 * @height: Height of source video image.
 * @dst_format: Format of destination drawable surface.
 *
 * If the destination video image is a suitable factor larger than the source
 * video image. Allocate a bounce RGB surface that will be the target of the
 * more expensive color conversion blit, and source of the scaling blit.
 */
static Bool
vmwgfx_video_bounce_surface(struct xorg_xv_port_priv *priv,
			    int d_width, int d_height,
			    int width, int height,
			    enum xa_formats dst_format)
{
    float bounce_area, dst_area;

    if (d_width < width)
	width = d_width;

    if (d_height < height)
	height = d_height;

    bounce_area = (float) width * (float) height;
    dst_area = (float) d_width * (float) d_height;

    if (dst_area > bounce_area * 1.5f &&
	vmwgfx_video_setup_comp(priv, dst_format)) {

	if (!priv->bounce) {
	    priv->bounce = xa_surface_create(priv->xat, width, height,
					     xa_format_depth(dst_format),
					     xa_format_type(dst_format),
					     dst_format, XA_FLAG_RENDER_TARGET);
	} else {
	    if (xa_surface_redefine(priv->bounce, width, height,
				    xa_format_depth(dst_format),
				    xa_format_type(dst_format),
				    dst_format,
				    XA_FLAG_RENDER_TARGET, 0) != XA_ERR_NONE) {
		xa_surface_destroy(priv->bounce);
		priv->bounce = NULL;
	    }
	}

    } else {
	xa_surface_destroy(priv->bounce);
	priv->bounce = NULL;
    }

    if (priv->bounce) {
	priv->bounce_box.x1 = 0;
	priv->bounce_box.x2 = width;
	priv->bounce_box.y1 = 0;
	priv->bounce_box.y2 = height;
    }

    return TRUE;
}

static int
query_image_attributes(ScrnInfoPtr pScrn,
                       int id,
                       unsigned short *w, unsigned short *h,
                       int *pitches, int *offsets)
{
   int size, tmp;

   if (*w > IMAGE_MAX_WIDTH)
      *w = IMAGE_MAX_WIDTH;
   if (*h > IMAGE_MAX_HEIGHT)
      *h = IMAGE_MAX_HEIGHT;

   *w = (*w + 1) & ~1;
   if (offsets)
      offsets[0] = 0;

   switch (id) {
   case FOURCC_YV12:
      *h = (*h + 1) & ~1;
      size = (*w + 3) & ~3;
      if (pitches) {
         pitches[0] = size;
      }
      size *= *h;
      if (offsets) {
         offsets[1] = size;
      }
      tmp = ((*w >> 1) + 3) & ~3;
      if (pitches) {
         pitches[1] = pitches[2] = tmp;
      }
      tmp *= (*h >> 1);
      size += tmp;
      if (offsets) {
         offsets[2] = size;
      }
      size += tmp;
      break;
   case FOURCC_UYVY:
   case FOURCC_YUY2:
   default:
      size = *w << 1;
      if (pitches)
	 pitches[0] = size;
      size *= *h;
      break;
   }

   return size;
}

static int
copy_packed_data(ScrnInfoPtr pScrn,
                 struct xorg_xv_port_priv *port,
                 int id,
                 unsigned char *buf,
                 int left,
                 int top,
                 unsigned short w, unsigned short h)
{
    int i;
   struct xa_surface **yuv = port->yuv[port->current_set];
   char *ymap, *vmap, *umap;
   unsigned char _y1, _y2, u, v;
   int yidx, uidx, vidx;
   int y_array_size = w * h;
   int ret = BadAlloc;

   ymap = xa_surface_map(port->r, yuv[0], XA_MAP_WRITE);
   if (!ymap)
       return BadAlloc;
   umap = xa_surface_map(port->r, yuv[1], XA_MAP_WRITE);
   if (!umap)
       goto out_no_umap;
   vmap = xa_surface_map(port->r, yuv[2], XA_MAP_WRITE);
   if (!vmap)
       goto out_no_vmap;


   yidx = uidx = vidx = 0;

   switch (id) {
   case FOURCC_YV12: {
      int pitches[3], offsets[3];
      unsigned char *yp, *up, *vp;
      query_image_attributes(pScrn, FOURCC_YV12,
                             &w, &h, pitches, offsets);

      yp = buf + offsets[0];
      vp = buf + offsets[1];
      up = buf + offsets[2];
      memcpy(ymap, yp, w*h);
      memcpy(vmap, vp, w*h/4);
      memcpy(umap, up, w*h/4);
      break;
   }
   case FOURCC_UYVY:
      for (i = 0; i < y_array_size; i +=2 ) {
         /* extracting two pixels */
         u  = buf[0];
         _y1 = buf[1];
         v  = buf[2];
         _y2 = buf[3];
         buf += 4;

         ymap[yidx++] = _y1;
         ymap[yidx++] = _y2;
         umap[uidx++] = u;
         vmap[vidx++] = v;
      }
      break;
   case FOURCC_YUY2:
      for (i = 0; i < y_array_size; i +=2 ) {
         /* extracting two pixels */
         _y1 = buf[0];
         u  = buf[1];
         _y2 = buf[2];
         v  = buf[3];

         buf += 4;

         ymap[yidx++] = _y1;
         ymap[yidx++] = _y2;
         umap[uidx++] = u;
         vmap[vidx++] = v;
      }
      break;
   default:
       ret = BadAlloc;
       break;
   }

   ret = Success;
   xa_surface_unmap(yuv[2]);
  out_no_vmap:
   xa_surface_unmap(yuv[1]);
  out_no_umap:
   xa_surface_unmap(yuv[0]);

   return ret;
}


static int
display_video(ScreenPtr pScreen, struct xorg_xv_port_priv *pPriv, int id,
              RegionPtr dstRegion,
              int src_x, int src_y, int src_w, int src_h,
              int dst_x, int dst_y, int dst_w, int dst_h,
	      int width, int height,
              PixmapPtr pPixmap)
{
    struct vmwgfx_saa_pixmap *vpix = vmwgfx_saa_pixmap(pPixmap);
    Bool hdtv;
    RegionRec reg;
    int ret = BadAlloc;
    int blit_ret;

    REGION_NULL(pScreen, &reg);

    if (!vmwgfx_hw_accel_validate(pPixmap, 0, XA_FLAG_RENDER_TARGET, 0, &reg))
	goto out_no_dst;

   hdtv = ((src_w >= RES_720P_X) && (src_h >= RES_720P_Y));
   if (hdtv != pPriv->hdtv) {
       pPriv->hdtv = hdtv;
       vmwgfx_update_conversion_matrix(pPriv);
   }

#ifdef COMPOSITE

   /*
    * For redirected windows, we need to fix up the destination coordinates.
    */

   REGION_TRANSLATE(pScreen, dstRegion, -pPixmap->screen_x,
		    -pPixmap->screen_y);
   dst_x -= pPixmap->screen_x;
   dst_y -= pPixmap->screen_y;
#endif

   /*
    * Throttle on previous blit.
    */

   if (pPriv->fence) {
       (void) xa_fence_wait(pPriv->fence, 1000000000ULL);
       xa_fence_destroy(pPriv->fence);
       pPriv->fence = NULL;
   }

   (void) vmwgfx_video_bounce_surface(pPriv, dst_w, dst_h, width, height,
				      xa_surface_format(vpix->hw));

   DamageRegionAppend(&pPixmap->drawable, dstRegion);

   if (pPriv->bounce) {
       BoxPtr b;
       int i;

       /*
	* If we have a bounce buffer, First perform a (potentially down-
	* scaling) color conversion blit with an expensive shader.
	*/
       blit_ret = xa_yuv_planar_blit(pPriv->r, 0, 0, src_w, src_h,
				     src_x, src_y,
				     pPriv->bounce_box.x2,
				     pPriv->bounce_box.y2,
				     &pPriv->bounce_box, 1,
				     pPriv->cm,
				     pPriv->bounce,
				     pPriv->yuv[pPriv->current_set]);

       if (blit_ret)
	   goto out_blit;

       /*
	* Then an upscaling blit with a cheap shader. Note that we never
	* scale up a dimenstion that was previously downscaled in the color
	* conversion blit.
	*/
       pPriv->src_pic->srf = pPriv->bounce;
       pPriv->dst_pic->srf = vpix->hw;
       vmwgfx_video_setup_coord_matrix(src_x, src_y, src_w, src_h,
				       dst_x, dst_y, dst_w, dst_h,
				       pPriv->bounce_box.x2,
				       pPriv->bounce_box.y2,
				       pPriv->src_pic->transform);
       pPriv->src_pic->has_transform = 1;

       if (xa_composite_prepare(pPriv->r, pPriv->comp) != XA_ERR_NONE) {
	   blit_ret = 1;
	   goto out_blit;
       }

       b =  REGION_RECTS(dstRegion);
       for (i = 0; i < REGION_NUM_RECTS(dstRegion); ++i, ++b) {
	       xa_composite_rect(pPriv->r, b->x1, b->y1, 0, 0,
				 b->x1, b->y1, b->x2 - b->x1,
				 b->y2 - b->y1);
       }

       xa_composite_done(pPriv->r);
   } else {
       /*
	* Perform color conversion and scaling in the same blit.
	*/
       blit_ret = xa_yuv_planar_blit(pPriv->r, src_x, src_y, src_w, src_h,
				     dst_x, dst_y, dst_w, dst_h,
				     (struct xa_box *)REGION_RECTS(dstRegion),
				     REGION_NUM_RECTS(dstRegion),
				     pPriv->cm,
				     vpix->hw,
				     pPriv->yuv[pPriv->current_set ]);
   }

  out_blit:

   saa_pixmap_dirty(pPixmap, TRUE, dstRegion);
   DamageRegionProcessPending(&pPixmap->drawable);
   ret = Success;

   if (!blit_ret) {
       ret = Success;
       pPriv->fence = xa_fence_get(pPriv->r);
   } else
       ret = BadAlloc;

   out_no_dst:
   REGION_UNINIT(pScreen, &reg);
   return ret;
}

static int
put_image(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 id, unsigned char *buf,
          short width, short height,
          Bool sync, RegionPtr clipBoxes, pointer data,
          DrawablePtr pDraw)
{
   struct xorg_xv_port_priv *pPriv = (struct xorg_xv_port_priv *) data;
   ScreenPtr pScreen = xf86ScrnToScreen(pScrn);
   PixmapPtr pPixmap;
   INT32 x1, x2, _y1, _y2;
   BoxRec dstBox;
   int ret;

   /* Clip */
   x1 = src_x;
   x2 = src_x + src_w;
   _y1 = src_y;
   _y2 = src_y + src_h;

   dstBox.x1 = drw_x;
   dstBox.x2 = drw_x + drw_w;
   dstBox.y1 = drw_y;
   dstBox.y2 = drw_y + drw_h;

   if (!xf86XVClipVideoHelper(&dstBox, &x1, &x2, &_y1, &_y2, clipBoxes,
			      width, height))
      return Success;

   ret = check_yuv_surfaces(pPriv, id, width, height);
   if (ret)
       return ret;

   ret = copy_packed_data(pScrn, pPriv, id, buf,
			  src_x, src_y, width, height);
   if (ret)
       return ret;

   if (pDraw->type == DRAWABLE_WINDOW) {
      pPixmap = (*pScreen->GetWindowPixmap)((WindowPtr)pDraw);
   } else {
      pPixmap = (PixmapPtr)pDraw;
   }

   display_video(pScrn->pScreen, pPriv, id, clipBoxes,
                 src_x, src_y, src_w, src_h,
                 drw_x, drw_y,
                 drw_w, drw_h,
		 width, height, pPixmap);

   pPriv->current_set = (pPriv->current_set + 1) & 1;
   return Success;
}

static struct xorg_xv_port_priv *
port_priv_create(struct xa_tracker *xat, struct xa_context *r,
		 int drm_fd)
{
   struct xorg_xv_port_priv *priv = NULL;

   priv = calloc(1, sizeof(struct xorg_xv_port_priv));

   if (!priv)
      return NULL;

   priv->r = r;
   priv->xat = xat;
   priv->drm_fd = drm_fd;
   REGION_NULL(pScreen, &priv->clip);
   priv->hdtv = FALSE;
   priv->uv_offset = 0.5f;
   priv->uv_scale = 1.f;
   priv->y_offset = 0.f;
   priv->y_scale = 1.f;
   priv->rgb_offset = 0.f;
   priv->rgb_scale = 1.f;
   priv->sinhue = 0.f;
   priv->coshue = 1.f;

   vmwgfx_update_conversion_matrix(priv);

   return priv;
}

static void
vmwgfx_free_textured_adaptor(XF86VideoAdaptorPtr adaptor)
{
    int i;

    for (i = 0; i < adaptor->nPorts; ++i)
	free(adaptor->pPortPrivates[i].ptr);

    free(adaptor->pAttributes);
    free(adaptor->pPortPrivates);
    xf86XVFreeVideoAdaptorRec(adaptor);
}

static XF86VideoAdaptorPtr
xorg_setup_textured_adapter(ScreenPtr pScreen)
{
   ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
   modesettingPtr ms = modesettingPTR(pScrn);
   XF86VideoAdaptorPtr adapt;
   XF86AttributePtr attrs;
   DevUnion *dev_unions;
   int nports = 16, i;
   int nattributes;
   struct xa_context *xar;

   /*
    * Use the XA default context since we don't expect the X server
    * to render from multiple threads.
    */

   xar = xa_context_default(ms->xat);
   nattributes = NUM_TEXTURED_ATTRIBUTES;

   adapt = calloc(1, sizeof(XF86VideoAdaptorRec));
   dev_unions = calloc(nports, sizeof(DevUnion));
   attrs = calloc(nattributes, sizeof(XF86AttributeRec));
   if (adapt == NULL || dev_unions == NULL || attrs == NULL) {
      free(adapt);
      free(dev_unions);
      free(attrs);
      return NULL;
   }

   adapt->type = XvWindowMask | XvInputMask | XvImageMask;
   adapt->flags = 0;
   adapt->name = xv_adapt_name;
   adapt->nEncodings = 1;
   adapt->pEncodings = DummyEncoding;
   adapt->nFormats = NUM_FORMATS;
   adapt->pFormats = Formats;
   adapt->nPorts = 0;
   adapt->pPortPrivates = dev_unions;
   adapt->nAttributes = nattributes;
   adapt->pAttributes = attrs;
   memcpy(attrs, TexturedAttributes, nattributes * sizeof(XF86AttributeRec));
   adapt->nImages = NUM_IMAGES;
   adapt->pImages = Images;
   adapt->PutVideo = NULL;
   adapt->PutStill = NULL;
   adapt->GetVideo = NULL;
   adapt->GetStill = NULL;
   adapt->StopVideo = stop_video;
   adapt->SetPortAttribute = set_port_attribute;
   adapt->GetPortAttribute = get_port_attribute;
   adapt->QueryBestSize = query_best_size;
   adapt->PutImage = put_image;
   adapt->QueryImageAttributes = query_image_attributes;


   for (i = 0; i < nports; i++) {
       struct xorg_xv_port_priv *priv =
	  port_priv_create(ms->xat, xar, ms->fd);

      adapt->pPortPrivates[i].ptr = (pointer) (priv);
      adapt->nPorts++;
   }

   return adapt;
}

void
vmw_xv_close(ScreenPtr pScreen)
{
   ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
   modesettingPtr ms = modesettingPTR(pScrn);

   if (ms->overlay) {
       vmw_video_free_adaptor(ms->overlay);
       ms->overlay = NULL;
   }

   if (ms->textured) {
       vmwgfx_free_textured_adaptor(ms->textured);
       ms->textured = NULL;
   }
}

void
xorg_xv_init(ScreenPtr pScreen)
{
   ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
   modesettingPtr ms = modesettingPTR(pScrn);
   XF86VideoAdaptorPtr *adaptors, *new_adaptors = NULL;
   XF86VideoAdaptorPtr textured_adapter = NULL, overlay_adaptor = NULL;
   int num_adaptors;

   num_adaptors = xf86XVListGenericAdaptors(pScrn, &adaptors);
   new_adaptors = malloc((num_adaptors + 2) * sizeof(XF86VideoAdaptorPtr *));
   if (new_adaptors == NULL)
       return;

   memcpy(new_adaptors, adaptors, num_adaptors * sizeof(XF86VideoAdaptorPtr));
   adaptors = new_adaptors;

   /* Add the adaptors supported by our hardware.  First, set up the atoms
    * that will be used by both output adaptors.
    */
   xvBrightness = MAKE_ATOM("XV_BRIGHTNESS");
   xvContrast = MAKE_ATOM("XV_CONTRAST");
   xvSaturation = MAKE_ATOM("XV_SATURATION");
   xvHue = MAKE_ATOM("XV_HUE");

   if (ms->xat) {
       textured_adapter = xorg_setup_textured_adapter(pScreen);
       if (textured_adapter)
	   adaptors[num_adaptors++] = textured_adapter;
   } else {
       xf86DrvMsg(pScrn->scrnIndex, X_INFO,
		  "No 3D acceleration. Not setting up textured video.\n");
   }

   overlay_adaptor = vmw_video_init_adaptor(pScrn);
   if (overlay_adaptor)
       adaptors[num_adaptors++] = overlay_adaptor;

   if (num_adaptors) {
       if (xf86XVScreenInit(pScreen, adaptors, num_adaptors)) {
	   ms->overlay = overlay_adaptor;
	   ms->textured = textured_adapter;
       } else {
	   ms->overlay = NULL;
	   ms->textured = NULL;
	   xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
		      "Failed to initialize Xv.\n");
       }
   } else {
       xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
		  "Disabling Xv because no adaptors could be initialized.\n");
   }

   free(new_adaptors);
}
0707010000004C000081A400000000000000000000000161A68E1200001D8C000000000000000000000000000000000000003900000000xf86-video-vmware-13.3.0+12/vmwgfx/vmwgfx_xa_composite.c/*
 * Copyright 2009-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>
 * Author: Zack Ruzin <zackr@vmware.com>
 *
 * The code in this file translates XRender PICT composite stuff
 * to fit the libxatracker API.
 */

#ifdef HAVE_CONFIG_H
#include "config.h"
#endif

#include <pixman.h>
#include <picturestr.h>
#include "xa_composite.h"
#include "vmwgfx_saa.h"
#include "vmwgfx_saa_priv.h"


struct vmwgfx_composite {
    union xa_source_pict *src_spict;
    union xa_source_pict *mask_spict;
    union xa_source_pict *dst_spict;
    struct xa_picture *src_pict;
    struct xa_picture *mask_pict;
    struct xa_picture *dst_pict;
    struct xa_composite *comp;
};

static const enum xa_composite_op vmwgfx_op_map[] = {
    [PictOpClear] = xa_op_clear,
    [PictOpSrc] = xa_op_src,
    [PictOpDst] = xa_op_dst,
    [PictOpOver] = xa_op_over,
    [PictOpOverReverse] = xa_op_over_reverse,
    [PictOpIn] = xa_op_in,
    [PictOpInReverse] = xa_op_in_reverse,
    [PictOpOut] = xa_op_out,
    [PictOpOutReverse] = xa_op_out_reverse,
    [PictOpAtop] = xa_op_atop,
    [PictOpAtopReverse] = xa_op_atop_reverse,
    [PictOpXor] = xa_op_xor,
    [PictOpAdd] = xa_op_add
};

static const unsigned int vmwgfx_op_map_size =
    sizeof(vmwgfx_op_map) / sizeof(enum xa_composite_op);

static Bool
vmwgfx_matrix_from_pict_transform(PictTransform *trans, float *matrix)
{
   if (!trans)
      return FALSE;

   matrix[0] = pixman_fixed_to_double(trans->matrix[0][0]);
   matrix[3] = pixman_fixed_to_double(trans->matrix[0][1]);
   matrix[6] = pixman_fixed_to_double(trans->matrix[0][2]);

   matrix[1] = pixman_fixed_to_double(trans->matrix[1][0]);
   matrix[4] = pixman_fixed_to_double(trans->matrix[1][1]);
   matrix[7] = pixman_fixed_to_double(trans->matrix[1][2]);

   matrix[2] = pixman_fixed_to_double(trans->matrix[2][0]);
   matrix[5] = pixman_fixed_to_double(trans->matrix[2][1]);
   matrix[8] = pixman_fixed_to_double(trans->matrix[2][2]);

   return TRUE;
}

static enum xa_composite_wrap
vmwgfx_xa_setup_wrap(Bool pict_has_repeat, int pict_repeat)
{
    enum xa_composite_wrap wrap = xa_wrap_clamp_to_border;

    if (!pict_has_repeat)
	return wrap;

    switch(pict_repeat) {
    case RepeatNormal:
	wrap = xa_wrap_repeat;
	break;
    case RepeatReflect:
	wrap = xa_wrap_mirror_repeat;
	break;
    case RepeatPad:
	wrap = xa_wrap_clamp_to_edge;
	break;
    default:
	break;
    }
    return wrap;
}

static Bool
vmwgfx_render_filter_to_xa(int xrender_filter,
			   enum xa_composite_filter *out_filter)
{
   switch (xrender_filter) {
   case PictFilterConvolution:
   case PictFilterNearest:
   case PictFilterFast:
       *out_filter = xa_filter_nearest;
      break;
   case PictFilterBest:
   case PictFilterGood:
   case PictFilterBilinear:
       *out_filter = xa_filter_linear;
      break;
   default:
       *out_filter = xa_filter_nearest;
       return FALSE;
   }
   return TRUE;
}

static Bool
vmwgfx_xa_setup_pict(PicturePtr pict,
		     struct xa_picture *xa_pict,
		     union xa_source_pict *src_pict)
{
    if (!pict)
	return FALSE;

    memset(xa_pict, 0, sizeof(*xa_pict));

    xa_pict->pict_format = vmwgfx_xa_format(pict->format);
    if (xa_pict->pict_format == xa_format_unknown)
	return FALSE;

    /*
     * Saa doesn't let drivers accelerate alpha maps.
     */
    xa_pict->alpha_map = NULL;
    xa_pict->component_alpha = pict->componentAlpha;

    xa_pict->has_transform =
	vmwgfx_matrix_from_pict_transform(pict->transform,
					  xa_pict->transform);

    xa_pict->wrap = vmwgfx_xa_setup_wrap(pict->repeat,
					 pict->repeatType);

    (void) vmwgfx_render_filter_to_xa(pict->filter, &xa_pict->filter);

    if (pict->pSourcePict) {
	if (pict->pSourcePict->type != SourcePictTypeSolidFill)
	    return FALSE;

	src_pict->type = xa_src_pict_solid_fill;
	src_pict->solid_fill.color = pict->pSourcePict->solidFill.color;
	xa_pict->src_pict = src_pict;
    }

    return TRUE;
}

struct xa_composite *
vmwgfx_xa_setup_comp(struct vmwgfx_composite *vcomp,
		     int op,
		     PicturePtr src_pict,
		     PicturePtr mask_pict,
		     PicturePtr dst_pict)
{
    struct xa_composite *comp = vcomp->comp;

    if (op >= vmwgfx_op_map_size)
	return NULL;

    comp->op = vmwgfx_op_map[op];
    if (comp->op == xa_op_clear && op != PictOpClear)
	return NULL;

    if (!vmwgfx_xa_setup_pict(dst_pict, vcomp->dst_pict,
			      vcomp->dst_spict))
	return NULL;
    if (!vmwgfx_xa_setup_pict(src_pict, vcomp->src_pict,
			      vcomp->src_spict))
	return NULL;
    if (mask_pict && !vmwgfx_xa_setup_pict(mask_pict,
					   vcomp->mask_pict,
					   vcomp->mask_spict))
	return NULL;

    comp->dst = vcomp->dst_pict;
    comp->src = vcomp->src_pict;
    comp->mask = (mask_pict) ? vcomp->mask_pict : NULL;

    return comp;
}

Bool
vmwgfx_xa_update_comp(struct xa_composite *comp,
		      PixmapPtr src_pix,
		      PixmapPtr mask_pix,
		      PixmapPtr dst_pix)
{
    comp->dst->srf = vmwgfx_saa_pixmap(dst_pix)->hw;
    if (src_pix)
	comp->src->srf = vmwgfx_saa_pixmap(src_pix)->hw;
    if (mask_pix && comp->mask)
	comp->mask->srf = vmwgfx_saa_pixmap(mask_pix)->hw;
    return TRUE;
}


void
vmwgfx_free_composite(struct vmwgfx_composite *vcomp)
{
    if (!vcomp)
	return;

    if (vcomp->src_spict)
	free(vcomp->src_spict);
    if (vcomp->mask_spict)
	free(vcomp->mask_spict);
    if (vcomp->dst_spict)
	free(vcomp->dst_spict);
    if (vcomp->src_pict)
	free(vcomp->src_pict);
    if (vcomp->mask_pict)
	free(vcomp->mask_pict);
    if (vcomp->dst_pict)
	free(vcomp->dst_pict);
    if (vcomp->comp)
	free(vcomp->comp);
    free(vcomp);
}

struct vmwgfx_composite *
vmwgfx_alloc_composite(void)
{
    const struct xa_composite_allocation *a = xa_composite_allocation();
    struct vmwgfx_composite *vcomp = calloc(1, sizeof(*vcomp));

    if (!vcomp)
	return NULL;

    vcomp->src_spict = calloc(1, a->xa_source_pict_size);
    vcomp->mask_spict = calloc(1, a->xa_source_pict_size);
    vcomp->dst_spict = calloc(1, a->xa_source_pict_size);
    vcomp->src_pict = calloc(1, a->xa_picture_size);
    vcomp->mask_pict = calloc(1, a->xa_picture_size);
    vcomp->dst_pict = calloc(1, a->xa_picture_size);
    vcomp->comp = calloc(1, a->xa_composite_size);

    if (!vcomp->src_spict || !vcomp->mask_spict || !vcomp->dst_spict ||
	!vcomp->src_pict || !vcomp->mask_pict || !vcomp->dst_pict ||
	!vcomp->comp) {
	vmwgfx_free_composite(vcomp);
	return NULL;
    }

    return vcomp;
}
0707010000004D000081A400000000000000000000000161A68E1200002BFD000000000000000000000000000000000000003700000000xf86-video-vmware-13.3.0+12/vmwgfx/vmwgfx_xa_surface.c/*
 * 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>
 */
#ifdef _HAVE_CONFIG_H_
#include "config.h"
#endif

#include <xorg-server.h>
#include "vmwgfx_saa_priv.h"


static const enum xa_surface_type vmwgfx_stype_map[] = {
  [PICT_TYPE_OTHER] = xa_type_other,
  [PICT_TYPE_A] = xa_type_a,
  [PICT_TYPE_ARGB] = xa_type_argb,
  [PICT_TYPE_ABGR] = xa_type_abgr,
  [PICT_TYPE_BGRA] = xa_type_bgra
};

static const unsigned int vmwgfx_stype_map_size =
    sizeof(vmwgfx_stype_map) / sizeof(enum xa_surface_type);

/**
 * vmwgfx_xa_surface_redefine - wrapper around xa_surface_redefine
 *
 * @vpix: Pointer to the struct vmwgfx_saa_pixmap the surface is attached to.
 * @srf: The surface.
 * @width: New width.
 * @height: New height.
 * @depth: New pixel depth.
 * @stype: New surface type.
 * @rgb_format: New rgb format.
 * @new_flags: New surface flags.
 * @copy_contents: Copy contents if new backing store is allocated.
 *
 * This is a wrapper that prints out an error message if the backing store
 * of an active scanout surface is changed.
 */
Bool
vmwgfx_xa_surface_redefine(struct vmwgfx_saa_pixmap *vpix,
			   struct xa_surface *srf,
			   int width,
			   int height,
			   int depth,
			   enum xa_surface_type stype,
			   enum xa_formats rgb_format,
			   unsigned int new_flags,
			   int copy_contents)
{
    uint32_t handle, new_handle, dummy;
    Bool have_handle = FALSE;

    if (!WSBMLISTEMPTY(&vpix->scanout_list))
	have_handle = (_xa_surface_handle(srf, &handle, &dummy) == XA_ERR_NONE);

    if (xa_surface_redefine(srf, width, height, depth, stype, rgb_format,
			    new_flags, copy_contents) != XA_ERR_NONE)
	return FALSE;

    if (!WSBMLISTEMPTY(&vpix->scanout_list) && have_handle &&
	_xa_surface_handle(srf, &new_handle, &dummy) == XA_ERR_NONE &&
	new_handle != handle) {
	LogMessage(X_ERROR, "Changed active scanout surface handle.\n");
    }

    return TRUE;
}


/*
 * Create an xa format from a PICT format.
 */
enum xa_formats
vmwgfx_xa_format(enum _PictFormatShort format)
{
    uint32_t ptype = PICT_FORMAT_TYPE(format);

    if (ptype >= vmwgfx_stype_map_size ||
	vmwgfx_stype_map[ptype] == 0 ||
	vmwgfx_stype_map[ptype] == xa_type_other)
	return xa_format_unknown;

    return xa_format(PICT_FORMAT_BPP(format),
		     vmwgfx_stype_map[ptype],
		     PICT_FORMAT_A(format),
		     PICT_FORMAT_R(format),
		     PICT_FORMAT_G(format),
		     PICT_FORMAT_B(format));
}

/*
 * Choose formats and flags for a dri2 surface.
 */
Bool
vmwgfx_hw_dri2_stage(PixmapPtr pixmap, unsigned int depth)
{
    struct vmwgfx_saa_pixmap *vpix = vmwgfx_saa_pixmap(pixmap);
    enum xa_formats format;

    if (depth == 0)
	depth = pixmap->drawable.depth;

    switch(depth) {
    case 32:
	format = xa_format_a8r8g8b8;
	break;
    case 24:
        format = xa_format_x8r8g8b8;
	break;
    case 16:
	format = xa_format_r5g6b5;
	break;
    case 15:
	format = xa_format_x1r5g5b5;
	break;
    default:
	return FALSE;
    }

    vpix->staging_format = format;
    vpix->staging_remove_flags = 0;
    vpix->staging_add_flags = XA_FLAG_RENDER_TARGET | XA_FLAG_SHARED;

    return TRUE;
}

/*
 * Is composite old format compatible? Only difference is that old format
 * has more alpha bits?
 */
static inline Bool
vmwgfx_old_format_compatible(enum xa_formats format,
			     enum xa_formats old_format)
{
    return (format == old_format ||
	    (xa_format_type(format) == xa_format_type(old_format) &&
	     xa_format_a(format) <= xa_format_a(old_format) &&
	     xa_format_r(format) == xa_format_r(old_format) &&
	     xa_format_g(format) == xa_format_g(old_format) &&
	     xa_format_b(format) == xa_format_b(old_format)));
}


/*
 * Choose format and flags for a composite dst surface.
 */
Bool
vmwgfx_hw_composite_dst_stage(PixmapPtr pixmap,
			      enum _PictFormatShort pict_format)
{
    struct vmwgfx_saa *vsaa =
	to_vmwgfx_saa(saa_get_driver(pixmap->drawable.pScreen));
    struct vmwgfx_saa_pixmap *vpix = vmwgfx_saa_pixmap(pixmap);
    enum xa_formats format = vmwgfx_xa_format(pict_format);

    /*
     * Check if we can reuse old hardware format.
     */
    if (vpix->hw) {
	enum xa_formats old_format = xa_surface_format(vpix->hw);

	if (vmwgfx_old_format_compatible(format, old_format))
	    format = old_format;
    }

    if (xa_format_check_supported(vsaa->xat, format,
				  vpix->xa_flags | XA_FLAG_RENDER_TARGET) !=
	XA_ERR_NONE) {
	return FALSE;
    }

    vpix->staging_format = format;
    vpix->staging_remove_flags = 0;
    vpix->staging_add_flags = XA_FLAG_RENDER_TARGET | XA_FLAG_SHARED;

    return TRUE;
}

/*
 * Choose format and flags for a composite src surface.
 */
Bool
vmwgfx_hw_composite_src_stage(PixmapPtr pixmap,
			      enum _PictFormatShort pict_format)
{
    struct vmwgfx_saa *vsaa =
	to_vmwgfx_saa(saa_get_driver(pixmap->drawable.pScreen));
    struct vmwgfx_saa_pixmap *vpix = vmwgfx_saa_pixmap(pixmap);
    enum xa_formats format = vmwgfx_xa_format(pict_format);
    enum xa_formats swizzle_format = xa_format_unknown;
    enum xa_surface_type ftype;

    if (format == xa_format_unknown)
	return FALSE;

    ftype = xa_format_type(format);
    if (ftype == xa_type_abgr) {

	swizzle_format = xa_format(xa_format_bpp(format),
				   xa_type_argb,
				   xa_format_a(format),
				   xa_format_r(format),
				   xa_format_g(format),
				   xa_format_b(format));
    }

    /*
     * Check if we can reuse old format.
     */

    if (vpix->hw) {
	enum xa_formats old_format = xa_surface_format(vpix->hw);

	if (vmwgfx_old_format_compatible(format, old_format) ||
	    (swizzle_format != xa_format_unknown &&
	     vmwgfx_old_format_compatible(swizzle_format, old_format))) {
	    format = old_format;
	    goto have_format;
	}
    }

    if (swizzle_format != xa_format_unknown &&
	xa_format_check_supported(vsaa->xat, swizzle_format, vpix->xa_flags) ==
	XA_ERR_NONE) {
	format = swizzle_format;
	goto have_format;
    }

    if (xa_format_check_supported(vsaa->xat, format, vpix->xa_flags) ==
	XA_ERR_NONE) {
	goto have_format;
    }

    return FALSE;
  have_format:
    vpix->staging_format = format;
    vpix->staging_remove_flags = 0;
    vpix->staging_add_flags = 0;

    return TRUE;
}

/*
 * Choose accel format given depth.
 */
static enum xa_formats
vmwgfx_choose_accel_format(unsigned int depth)
{
    switch(depth) {
    case 32:
	return xa_format_a8r8g8b8;
    case 24:
	return xa_format_x8r8g8b8;
    case 16:
	return xa_format_r5g6b5;
    case 15:
	return xa_format_x1r5g5b5;
    case 8:
	return xa_format_a8;
    default:
	break;
    }
    return xa_format_unknown;
}


/*
 * Determine xa format and flags for an ordinary accel surface.
 */
Bool
vmwgfx_hw_accel_stage(PixmapPtr pixmap, unsigned int depth,
		      uint32_t add_flags, uint32_t remove_flags)
{
    struct vmwgfx_saa_pixmap *vpix = vmwgfx_saa_pixmap(pixmap);
    enum xa_formats format = xa_format_unknown;

    if (depth == 0)
	depth = pixmap->drawable.depth;

    if (vpix->hw) {
	enum xa_formats old_format = xa_surface_format(vpix->hw);
	enum xa_surface_type ftype = xa_format_type(old_format);

	if (ftype != xa_type_argb &&
	    ftype != xa_type_a) {
	    LogMessage(X_ERROR,
		       "Acceleration fallback due to strange hw format.\n");
	    return FALSE;
	}

	if (xa_format_depth(old_format) == depth ||
	    (xa_format_depth(old_format) == 32 &&
	     depth == 24))
	    format = old_format;
    }

    if (format == xa_format_unknown)
	format = vmwgfx_choose_accel_format(depth);

    if (format == xa_format_unknown)
	return FALSE;

    vpix->staging_add_flags = add_flags;
    vpix->staging_remove_flags = remove_flags;
    vpix->staging_format = format;

    return TRUE;
}

/*
 * Create a surface with a format and flags determined by one of
 * the staging functions.
 */
Bool
vmwgfx_hw_commit(PixmapPtr pixmap)
{
    struct vmwgfx_saa *vsaa =
	to_vmwgfx_saa(saa_get_driver(pixmap->drawable.pScreen));
    struct saa_pixmap *spix = saa_get_saa_pixmap(pixmap);
    struct vmwgfx_saa_pixmap *vpix = to_vmwgfx_saa_pixmap(spix);
    enum xa_formats format = vpix->staging_format;

    if (vpix->hw) {
	enum xa_formats old_format = xa_surface_format(vpix->hw);

	if (vpix->staging_format != old_format) {
	    if (xa_format_type(format) != xa_format_type(old_format) ||
		xa_format_r(format) != xa_format_r(old_format) ||
		xa_format_g(format) != xa_format_g(old_format) ||
		xa_format_b(format) != xa_format_b(old_format)) {

		LogMessage(X_INFO, "Killing old hw surface.\n");

		if (!vmwgfx_hw_kill(vsaa, spix))
		    return FALSE;
	    }
	}
    }

    if (vpix->hw) {
	uint32_t new_flags;

	new_flags = (vpix->xa_flags & ~vpix->staging_remove_flags) |
	    vpix->staging_add_flags | XA_FLAG_SHARED;

	if (vpix->staging_format != xa_surface_format(vpix->hw))
	    LogMessage(X_INFO, "Changing hardware format.\n");

	if (!vmwgfx_xa_surface_redefine(vpix,
					vpix->hw,
					pixmap->drawable.width,
					pixmap->drawable.height,
					0,
					xa_type_other,
					vpix->staging_format,
					new_flags, 1) != XA_ERR_NONE)
	    return FALSE;
	vpix->xa_flags = new_flags;
    } else if (!vmwgfx_create_hw(vsaa, pixmap, FALSE))
	return FALSE;

    return TRUE;
}

/*
 * Create an accel surface if there is none, and make sure the region
 * given by @region is valid. If @region is NULL, the whole surface
 * will be valid. This is a utility convenience function only.
 */
Bool
vmwgfx_hw_accel_validate(PixmapPtr pixmap, unsigned int depth,
			 uint32_t add_flags, uint32_t remove_flags,
			 RegionPtr region)
{
    return (vmwgfx_hw_accel_stage(pixmap, depth, add_flags, remove_flags) &&
	    vmwgfx_hw_commit(pixmap) &&
	    vmwgfx_hw_validate(pixmap, region));
}


/*
 * Create a dri2 surface if there is none,
 * and make sure the whole surfade is valid.
 * This is a utility convenience function only.
 */
Bool
vmwgfx_hw_dri2_validate(PixmapPtr pixmap, unsigned int depth)
{
    struct vmwgfx_saa *vsaa =
	to_vmwgfx_saa(saa_get_driver(pixmap->drawable.pScreen));

    if (!vsaa->is_master)
	    return FALSE;

    return (vmwgfx_hw_dri2_stage(pixmap, depth) &&
	    vmwgfx_hw_commit(pixmap) &&
	    vmwgfx_hw_validate(pixmap, NULL));
}
0707010000004E000081A400000000000000000000000161A68E1200000861000000000000000000000000000000000000002F00000000xf86-video-vmware-13.3.0+12/vmwgfx/wsbm_util.h/*
 * This file is not copyrighted.
 */

#ifndef _WSBM_UTIL_H_
#define _WSBM_UTIL_H_

#include <stddef.h>

#ifndef containerOf
#define containerOf(__item, __type, __field)				\
      ((__type *)(((char *) (__item)) - offsetof(__type, __field)))
#endif

struct _WsbmListHead
{
    struct _WsbmListHead *prev;
    struct _WsbmListHead *next;
};

#define WSBMINITLISTHEAD(__item)		       \
    do{						       \
	(__item)->prev = (__item);		       \
	(__item)->next = (__item);		       \
    } while (0)

#define WSBMLISTADD(__item, __list)		\
  do {						\
    (__item)->prev = (__list);			\
    (__item)->next = (__list)->next;		\
    (__list)->next->prev = (__item);		\
    (__list)->next = (__item);			\
  } while (0)

#define WSBMLISTADDTAIL(__item, __list)		\
  do {						\
    (__item)->next = (__list);			\
    (__item)->prev = (__list)->prev;		\
    (__list)->prev->next = (__item);		\
    (__list)->prev = (__item);			\
  } while(0)

#define WSBMLISTDEL(__item)			\
  do {						\
    (__item)->prev->next = (__item)->next;	\
    (__item)->next->prev = (__item)->prev;	\
  } while(0)

#define WSBMLISTDELINIT(__item)			\
  do {						\
    (__item)->prev->next = (__item)->next;	\
    (__item)->next->prev = (__item)->prev;	\
    (__item)->next = (__item);			\
    (__item)->prev = (__item);			\
  } while(0)

#define WSBMLISTFOREACH(__item, __list) \
    for((__item) = (__list)->next; (__item) != (__list); (__item) = (__item)->next)

#define WSBMLISTFOREACHPREV(__item, __list) \
    for((__item) = (__list)->prev; (__item) != (__list); (__item) = (__item)->prev)

#define WSBMLISTFOREACHSAFE(__item, __next, __list)		\
        for((__item) = (__list)->next, (__next) = (__item)->next;	\
	(__item) != (__list);					\
	(__item) = (__next), (__next) = (__item)->next)

#define WSBMLISTFOREACHPREVSAFE(__item, __prev, __list)		\
    for((__item) = (__list)->prev, (__prev) = (__item->prev);	\
	(__item) != (__list);					\
	(__item) = (__prev), (__prev) = (__item)->prev)

#define WSBMLISTENTRY(__item, __type, __field)			\
    containerOf(__item, __type, __field)

#define WSBMLISTEMPTY(__item)			\
    ((__item)->next == (__item))

#endif
07070100000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000B00000000TRAILER!!!1550 blocks
openSUSE Build Service is sponsored by