summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThomas Hellstrom <thellstrom@vmware.com>2011-12-19 20:25:43 +0100
committerThomas Hellstrom <thellstrom@vmware.com>2011-12-19 20:25:43 +0100
commitb5546fb1de3f3859151a91e98ab0bd24b6789e2e (patch)
tree8e5283d6610e87d796e0d64b0a06c42469422b0d
parentabf9cb75630cb27bb4741d194cb23014fe3d09b1 (diff)
parent5748c33535bc7d3009b9758653885e6ae0e73002 (diff)
Merge branch 'vmwgfx_branch'
-rw-r--r--Makefile.am2
-rw-r--r--configure.ac35
-rw-r--r--saa/Makefile.am13
-rw-r--r--saa/saa.c748
-rw-r--r--saa/saa.h209
-rw-r--r--saa/saa_accel.c153
-rw-r--r--saa/saa_pixmap.c222
-rw-r--r--saa/saa_priv.h279
-rw-r--r--saa/saa_render.c424
-rw-r--r--saa/saa_unaccel.c935
-rw-r--r--src/Makefile.am27
-rw-r--r--src/svga_reg.h1433
-rw-r--r--src/vmware.c547
-rw-r--r--src/vmware_bootstrap.c503
-rw-r--r--src/vmware_bootstrap.h59
-rw-r--r--src/vmware_common.c163
-rw-r--r--src/vmware_common.h41
-rw-r--r--src/vmwaremodule.c256
-rw-r--r--vmwgfx/Makefile.am26
-rw-r--r--vmwgfx/svga3d_reg.h1801
-rw-r--r--vmwgfx/vmwgfx_crtc.c455
-rw-r--r--vmwgfx/vmwgfx_ctrl.c523
-rw-r--r--vmwgfx/vmwgfx_ctrl.h48
-rw-r--r--vmwgfx/vmwgfx_dri2.c426
-rw-r--r--vmwgfx/vmwgfx_driver.c1200
-rw-r--r--vmwgfx/vmwgfx_driver.h186
-rw-r--r--vmwgfx/vmwgfx_drm.h792
-rw-r--r--vmwgfx/vmwgfx_drmi.c502
-rw-r--r--vmwgfx/vmwgfx_drmi.h87
-rw-r--r--vmwgfx/vmwgfx_output.c393
-rw-r--r--vmwgfx/vmwgfx_overlay.c893
-rw-r--r--vmwgfx/vmwgfx_saa.c1514
-rw-r--r--vmwgfx/vmwgfx_saa.h110
-rw-r--r--vmwgfx/vmwgfx_saa_priv.h125
-rw-r--r--vmwgfx/vmwgfx_tex_video.c855
-rw-r--r--vmwgfx/vmwgfx_xa_composite.c277
-rw-r--r--vmwgfx/vmwgfx_xa_surface.c368
-rw-r--r--vmwgfx/wsbm_util.h79
38 files changed, 15548 insertions, 1161 deletions
diff --git a/Makefile.am b/Makefile.am
index 093e9f5..1203715 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -20,3 +20,3 @@
-SUBDIRS = src man vmwarectrl
+SUBDIRS = @VMWGFX_DIRS@ src man vmwarectrl
MAINTAINERCLEANFILES = ChangeLog INSTALL
diff --git a/configure.ac b/configure.ac
index 74fd1b9..3aec9af 100644
--- a/configure.ac
+++ b/configure.ac
@@ -74,7 +74,2 @@ XORG_DRIVER_CHECK_EXT(XV, videoproto)
PKG_CHECK_MODULES(XORG, [xorg-server >= 1.0.1 xproto fontsproto $REQUIRED_MODULES])
-PKG_CHECK_MODULES(LIBDRM,
- [libdrm],
- [AC_DEFINE([HAVE_LIBDRM], 1, [Has libdrm])],
- [echo "Will not try support for 3D or kernel modesetting."])
-
PKG_CHECK_EXISTS([xorg-server >= 1.1.0],
@@ -93,3 +88,4 @@ 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])])
+ [Has version 1.7.0 or greater of the Xserver])
+ BUILD_VMWGFX=yes],[BUILD_VMWGFX=no])
@@ -115,2 +111,9 @@ 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
+ PKG_CHECK_MODULES([XATRACKER], [xatracker >= 0.4.0],[],[BUILD_VMWGFX=no])
+fi
+
DRIVER_NAME=vmware
@@ -118,2 +121,21 @@ AC_SUBST([DRIVER_NAME])
+AC_MSG_CHECKING([whether to build Kernel Mode Setting and 3D])
+VMWGFX_DIRS=
+if test x$BUILD_VMWGFX = xyes; then
+ AC_MSG_RESULT([yes])
+ AC_SYS_LARGEFILE
+ VMWGFX_DIRS="saa vmwgfx"
+ VMWGFX_LIBADD='$(top_srcdir)/vmwgfx/libvmwgfx.la'
+ AC_CONFIG_FILES([
+ saa/Makefile
+ vmwgfx/Makefile
+ ])
+ AC_DEFINE([BUILD_VMWGFX], 1,
+ [Building the vmwgfx driver path])
+else
+ AC_MSG_RESULT([no])
+fi
+
+AC_SUBST([VMWGFX_DIRS])
+AC_SUBST([VMWGFX_LIBADD])
AC_CONFIG_FILES([
@@ -124,2 +146,3 @@ AC_CONFIG_FILES([
])
+
AC_OUTPUT
diff --git a/saa/Makefile.am b/saa/Makefile.am
new file mode 100644
index 0000000..849ced9
--- /dev/null
+++ b/saa/Makefile.am
@@ -0,0 +1,13 @@
+noinst_LTLIBRARIES = libsaa.la
+
+libsaa_la_CFLAGS = $(CWARNFLAGS) $(XORG_CFLAGS)
+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
+
diff --git a/saa/saa.c b/saa/saa.c
new file mode 100644
index 0000000..173c090
--- /dev/null
+++ b/saa/saa.c
@@ -0,0 +1,748 @@
+/*
+ * 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);
+}
+
+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, NULL,
+ 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->clientClipType != CT_NONE ||
+ !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_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(int i, ScreenPtr pScreen)
+{
+ struct saa_screen_priv *sscreen = saa_screen(pScreen);
+ struct saa_driver *driver = sscreen->driver;
+
+ 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(sscreen, pScreen, CloseScreen);
+ saa_unwrap(sscreen, pScreen, CreateGC);
+ saa_unwrap(sscreen, pScreen, ChangeWindowAttributes);
+ saa_unwrap(sscreen, pScreen, CreatePixmap);
+ saa_unwrap(sscreen, pScreen, DestroyPixmap);
+ 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) (i, pScreen);
+}
+
+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, DestroyPixmap, saa_destroy_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
+
+ return TRUE;
+}
+
+Bool
+saa_resources_init(ScreenPtr screen)
+{
+/* if (!saa_glyphs_init(screen))
+ return FALSE;
+*/
+ return TRUE;
+}
diff --git a/saa/saa.h b/saa/saa.h
new file mode 100644
index 0000000..c7aa3b6
--- /dev/null
+++ b/saa/saa.h
@@ -0,0 +1,209 @@
+/*
+ *
+ * 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>
+
+#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(int i, ScreenPtr pScreen);
+
+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
diff --git a/saa/saa_accel.c b/saa/saa_accel.c
new file mode 100644
index 0000000..5e1501b
--- /dev/null
+++ b/saa/saa_accel.c
@@ -0,0 +1,153 @@
+/*
+ * 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
+}
diff --git a/saa/saa_pixmap.c b/saa/saa_pixmap.c
new file mode 100644
index 0000000..0d63091
--- /dev/null
+++ b/saa/saa_pixmap.c
@@ -0,0 +1,222 @@
+/*
+ * 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);
+ spix->damage = NULL;
+ }
+
+ 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);
+}
diff --git a/saa/saa_priv.h b/saa/saa_priv.h
new file mode 100644
index 0000000..6652054
--- /dev/null
+++ b/saa/saa_priv.h
@@ -0,0 +1,279 @@
+/*
+ *
+ * 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 "mibstore.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"
+
+#define SAA_INVALID_ADDRESS \
+ ((void *) ((unsigned long) 0xFFFFFFFF - 1024*1024))
+
+struct saa_gc_priv {
+ /* GC values from the layer below. */
+ GCOps *saved_ops;
+ GCFuncs *saved_funcs;
+};
+
+struct saa_screen_priv {
+ struct saa_driver *driver;
+ CreateGCProcPtr saved_CreateGC;
+ CloseScreenProcPtr saved_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_swap(priv, real, mem) {\
+ 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
diff --git a/saa/saa_render.c b/saa/saa_render.c
new file mode 100644
index 0000000..c69f2c9
--- /dev/null
+++ b/saa/saa_render.c
@@ -0,0 +1,424 @@
+/*
+ * 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);
+ }
+}
+
+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);
+ }
+}
+#endif
diff --git a/saa/saa_unaccel.c b/saa/saa_unaccel.c
new file mode 100644
index 0000000..deaf5aa
--- /dev/null
+++ b/saa/saa_unaccel.c
@@ -0,0 +1,935 @@
+/*
+ * 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--;
+}
+
+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)));
+
+ 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)) {
+ saa_swap(sscreen, pScreen, CopyWindow);
+ pScreen->CopyWindow(pWin, ptOldOrg, prgnSrc);
+ saa_swap(sscreen, pScreen, CopyWindow);
+ saa_fad_write(pDrawable, SAA_ACCESS_W);
+ }
+ 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);
+ PixmapPtr dst_pixmap;
+ 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.
+ */
+ dst_pixmap = 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,
+};
diff --git a/src/Makefile.am b/src/Makefile.am
index 7c972cf..64a9069 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -26,8 +26,10 @@
-vmwlegacy_drv_la_LTLIBRARIES = vmwlegacy_drv.la
-vmwlegacy_drv_la_LDFLAGS = -module -avoid-version
-vmwlegacy_drv_la_CFLAGS = @XORG_CFLAGS@
-vmwlegacy_drv_ladir = @moduledir@/drivers
+vmware_drv_la_LTLIBRARIES = vmware_drv.la
+vmware_drv_la_LDFLAGS = -module -avoid-version
+vmware_drv_la_CFLAGS = @XORG_CFLAGS@
+vmware_drv_ladir = @moduledir@/drivers
+vmware_drv_la_LIBADD = @VMWGFX_LIBADD@
+vmware_drv_la_DEPENDENCIES = @VMWGFX_LIBADD@
-vmwlegacy_drv_la_SOURCES = \
+vmware_drv_la_SOURCES = \
bits2pixels.c \
@@ -52,11 +54,6 @@ vmwlegacy_drv_la_SOURCES = \
vmwarevideo.c \
- vmwaremodes.c
-
-vmware_drv_la_LTLIBRARIES = vmware_drv.la
-vmware_drv_la_LDFLAGS = -module -avoid-version
-vmware_drv_la_CFLAGS = @XORG_CFLAGS@ @LIBDRM_CFLAGS@
-vmware_drv_la_LIBADD = @LIBDRM_LIBS@
-vmware_drv_ladir = @moduledir@/drivers
-
-vmware_drv_la_SOURCES = \
- vmwaremodule.c
+ vmwaremodes.c \
+ vmware_bootstrap.h \
+ vmware_bootstrap.c \
+ vmware_common.c \
+ vmware_common.h
diff --git a/src/svga_reg.h b/src/svga_reg.h
index 4fa363a..6757aa6 100644
--- a/src/svga_reg.h
+++ b/src/svga_reg.h
@@ -1,4 +1,25 @@
-/* **********************************************************
- * Copyright 1998 VMware, Inc. All rights reserved.
- * **********************************************************/
+/**********************************************************
+ * 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.
+ *
+ **********************************************************/
@@ -7,3 +28,3 @@
*
- * SVGA hardware definitions
+ * Virtual hardware definitions for the VMware SVGA II device.
*/
@@ -13,38 +34,46 @@
-#define INCLUDE_ALLOW_USERLEVEL
-#define INCLUDE_ALLOW_VMMEXT
-#define INCLUDE_ALLOW_VMCORE
-#include "includeCheck.h"
+/*
+ * PCI device IDs.
+ */
+#define PCI_VENDOR_ID_VMWARE 0x15AD
+#define PCI_DEVICE_ID_VMWARE_SVGA2 0x0405
/*
- * Memory and port addresses and fundamental constants
+ * 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)
/*
- * Note-- MAX_WIDTH and MAX_HEIGHT are largely ignored by the code. This
- * isn't such a bad thing for forward compatibility. --Jeremy.
+ * 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_MAX_WIDTH 2360
-#define SVGA_MAX_HEIGHT 1770
-#define SVGA_MAX_BITS_PER_PIXEL 32
-#define SVGA_MAX_DEPTH 24
-#define SVGA_MAX_DISPLAYS 10
+#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 size of the onscreen framebuffer. The size of the
- * changeMap in the monitor is proportional to this number since it's
- * the amount of memory we need to trace in VESA mode. Therefore, we'd
+ * 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!).
+ * 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_SIZE \
- ((((SVGA_MAX_WIDTH * SVGA_MAX_HEIGHT * \
- SVGA_MAX_BITS_PER_PIXEL / 8) >> PAGE_SHIFT) + 1) << PAGE_SHIFT)
+#define SVGA_FB_MAX_TRACEABLE_SIZE 0x1000000
-#define SVGA_MAX_PSEUDOCOLOR_DEPTH 8
-#define SVGA_MAX_PSEUDOCOLORS (1 << SVGA_MAX_PSEUDOCOLOR_DEPTH)
+#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_MAGIC 0x900000UL
@@ -65,15 +94,10 @@
-/* Invalid SVGA_ID_ */
+/* "Invalid" value for all SVGA IDs. (Version ID, screen object ID, surface ID...) */
#define SVGA_ID_INVALID 0xFFFFFFFF
-/* More backwards compatibility, old location of color map: */
-#define SVGA_OLD_PALETTE_BASE 17
-
-/* Base and Offset gets us headed the right way for PCI Base Addr Registers */
-#define SVGA_LEGACY_BASE_PORT 0x4560
-#define SVGA_INDEX_PORT 0x0
-#define SVGA_VALUE_PORT 0x1
-#define SVGA_BIOS_PORT 0x2
-#define SVGA_NUM_PORTS 0x3
-#define SVGA_IRQSTATUS_PORT 0x8
+/* 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
@@ -89,11 +113,2 @@
-/* This port is deprecated, but retained because of old drivers. */
-#define SVGA_LEGACY_ACCEL_PORT 0x3
-
-/* Legal values for the SVGA_REG_CURSOR_ON register in cursor bypass mode */
-#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 */
-
/*
@@ -110,3 +125,3 @@ enum {
SVGA_REG_DEPTH = 6,
- SVGA_REG_BITS_PER_PIXEL = 7, /* Current bpp in the guest */
+ SVGA_REG_BITS_PER_PIXEL = 7, /* Current bpp in the guest */
SVGA_REG_PSEUDOCOLOR = 8,
@@ -116,3 +131,3 @@ enum {
SVGA_REG_BYTES_PER_LINE = 12,
- SVGA_REG_FB_START = 13,
+ SVGA_REG_FB_START = 13, /* (Deprecated) */
SVGA_REG_FB_OFFSET = 14,
@@ -124,20 +139,22 @@ enum {
SVGA_REG_CAPABILITIES = 17,
- SVGA_REG_MEM_START = 18, /* Memory for command FIFO and bitmaps */
+ 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, /* ID of cursor */
- SVGA_REG_CURSOR_X = 25, /* Set cursor X position */
- SVGA_REG_CURSOR_Y = 26, /* Set cursor Y position */
- SVGA_REG_CURSOR_ON = 27, /* Turn cursor on/off */
- SVGA_REG_HOST_BITS_PER_PIXEL = 28, /* Current bpp in the host */
- SVGA_REG_SCRATCH_SIZE = 29, /* Number of scratch registers */
- SVGA_REG_MEM_REGS = 30, /* Number of FIFO registers */
- SVGA_REG_NUM_DISPLAYS = 31, /* Number of guest displays */
- SVGA_REG_PITCHLOCK = 32, /* Fixed pitch for all modes */
- SVGA_REG_IRQMASK = 33, /* Interrupt mask */
+ 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, /* The display ID for the following display attributes */
+ SVGA_REG_DISPLAY_ID = 35, /* Display ID for the following display attributes */
SVGA_REG_DISPLAY_IS_PRIMARY = 36,/* Whether this is a primary display */
@@ -147,6 +164,17 @@ enum {
SVGA_REG_DISPLAY_HEIGHT = 40, /* The display's height */
- SVGA_REG_TOP = 41, /* Must be 1 more than the last register */
- SVGA_PALETTE_BASE = 1024, /* Base of SVGA color map */
+ /* 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
@@ -158,28 +186,118 @@ enum {
+/*
+ * 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))
/*
- * Capabilities
+ * 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.
*/
-#define SVGA_CAP_NONE 0x00000000
-#define SVGA_CAP_RECT_FILL 0x00000001
-#define SVGA_CAP_RECT_COPY 0x00000002
-#define SVGA_CAP_RECT_PAT_FILL 0x00000004
-#define SVGA_CAP_LEGACY_OFFSCREEN 0x00000008
-#define SVGA_CAP_RASTER_OP 0x00000010
-#define SVGA_CAP_CURSOR 0x00000020
-#define SVGA_CAP_CURSOR_BYPASS 0x00000040
-#define SVGA_CAP_CURSOR_BYPASS_2 0x00000080
-#define SVGA_CAP_8BIT_EMULATION 0x00000100
-#define SVGA_CAP_ALPHA_CURSOR 0x00000200
-#define SVGA_CAP_GLYPH 0x00000400
-#define SVGA_CAP_GLYPH_CLIPPING 0x00000800
-#define SVGA_CAP_OFFSCREEN_1 0x00001000
-#define SVGA_CAP_ALPHA_BLEND 0x00002000
-#define SVGA_CAP_3D 0x00004000
-#define SVGA_CAP_EXTENDED_FIFO 0x00008000
-#define SVGA_CAP_MULTIMON 0x00010000
-#define SVGA_CAP_PITCHLOCK 0x00020000
-#define SVGA_CAP_IRQMASK 0x00040000
-#define SVGA_CAP_DISPLAY_TOPOLOGY 0x00080000
+/*
+ * 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;
@@ -187,93 +305,141 @@ enum {
/*
- * Raster op codes (same encoding as X) used by FIFO drivers.
+ * 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
+ *
*/
-#define SVGA_ROP_CLEAR 0x00 /* 0 */
-#define SVGA_ROP_AND 0x01 /* src AND dst */
-#define SVGA_ROP_AND_REVERSE 0x02 /* src AND NOT dst */
-#define SVGA_ROP_COPY 0x03 /* src */
-#define SVGA_ROP_AND_INVERTED 0x04 /* NOT src AND dst */
-#define SVGA_ROP_NOOP 0x05 /* dst */
-#define SVGA_ROP_XOR 0x06 /* src XOR dst */
-#define SVGA_ROP_OR 0x07 /* src OR dst */
-#define SVGA_ROP_NOR 0x08 /* NOT src AND NOT dst */
-#define SVGA_ROP_EQUIV 0x09 /* NOT src XOR dst */
-#define SVGA_ROP_INVERT 0x0a /* NOT dst */
-#define SVGA_ROP_OR_REVERSE 0x0b /* src OR NOT dst */
-#define SVGA_ROP_COPY_INVERTED 0x0c /* NOT src */
-#define SVGA_ROP_OR_INVERTED 0x0d /* NOT src OR dst */
-#define SVGA_ROP_NAND 0x0e /* NOT src OR NOT dst */
-#define SVGA_ROP_SET 0x0f /* 1 */
-#define SVGA_ROP_UNSUPPORTED 0x10
+typedef
+struct SVGAGMRImageFormat {
+ union {
+ struct {
+ uint32 bitsPerPixel : 8;
+ uint32 colorDepth : 8;
+ uint32 reserved : 16; /* Must be zero */
+ };
-#define SVGA_NUM_SUPPORTED_ROPS 16
-#define SVGA_ROP_ALL (MASK(SVGA_NUM_SUPPORTED_ROPS))
-#define SVGA_IS_VALID_ROP(rop) (rop < SVGA_NUM_SUPPORTED_ROPS)
+ uint32 value;
+ };
+} SVGAGMRImageFormat;
-#define SVGA_INVALID_DISPLAY_ID ((uint32)-1)
+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;
/*
- * Ops
- * For each pixel, the four channels of the image are computed with:
- *
- * C = Ca * Fa + Cb * Fb
- *
- * where C, Ca, Cb are the values of the respective channels and Fa
- * and Fb come from the following table:
- *
- * BlendOp Fa Fb
- * ------------------------------------------
- * Clear 0 0
- * Src 1 0
- * Dst 0 1
- * Over 1 1-Aa
- * OverReverse 1-Ab 1
- * In Ab 0
- * InReverse 0 Aa
- * Out 1-Ab 0
- * OutReverse 0 1-Aa
- * Atop Ab 1-Aa
- * AtopReverse 1-Ab Aa
- * Xor 1-Ab 1-Aa
- * Add 1 1
- * Saturate min(1,(1-Ab)/Aa) 1
- *
- * Flags
- * You can use the following flags to achieve additional affects:
- *
- * Flag Effect
- * ------------------------------------------
- * ConstantSourceAlpha Ca = Ca * Param0
- * ConstantDestAlpha Cb = Cb * Param1
- *
- * Flag effects resolve before the op. For example
- * BlendOp == Add && Flags == ConstantSourceAlpha |
- * ConstantDestAlpha results in:
- *
- * C = (Ca * Param0) + (Cb * Param1)
- */
-
-#define SVGA_BLENDOP_CLEAR 0
-#define SVGA_BLENDOP_SRC 1
-#define SVGA_BLENDOP_DST 2
-#define SVGA_BLENDOP_OVER 3
-#define SVGA_BLENDOP_OVER_REVERSE 4
-#define SVGA_BLENDOP_IN 5
-#define SVGA_BLENDOP_IN_REVERSE 6
-#define SVGA_BLENDOP_OUT 7
-#define SVGA_BLENDOP_OUT_REVERSE 8
-#define SVGA_BLENDOP_ATOP 9
-#define SVGA_BLENDOP_ATOP_REVERSE 10
-#define SVGA_BLENDOP_XOR 11
-#define SVGA_BLENDOP_ADD 12
-#define SVGA_BLENDOP_SATURATE 13
-
-#define SVGA_NUM_BLENDOPS 14
-#define SVGA_IS_VALID_BLENDOP(op) (op >= 0 && op < SVGA_NUM_BLENDOPS)
-
-#define SVGA_BLENDFLAG_CONSTANT_SOURCE_ALPHA 0x01
-#define SVGA_BLENDFLAG_CONSTANT_DEST_ALPHA 0x02
-#define SVGA_NUM_BLENDFLAGS 2
-#define SVGA_BLENDFLAG_ALL (MASK(SVGA_NUM_BLENDFLAGS))
-#define SVGA_IS_VALID_BLENDFLAG(flag) ((flag & ~SVGA_BLENDFLAG_ALL) == 0)
+ * 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
@@ -334,3 +500,3 @@ enum {
*/
-
+
/* Valid if exists (i.e. if extended FIFO enabled): */
@@ -339,2 +505,3 @@ enum {
SVGA_FIFO_PITCHLOCK,
+
/* Valid with SVGA_FIFO_CAP_CURSOR_BYPASS_3: */
@@ -345,4 +512,31 @@ enum {
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,
+
/*
@@ -363,2 +557,3 @@ enum {
*/
+
/*
@@ -535,2 +730,83 @@ enum {
* 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.
*/
@@ -545,2 +821,7 @@ enum {
#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)
@@ -588,3 +869,3 @@ enum {
SVGA_VIDEO_COLORKEY,
- SVGA_VIDEO_SIZE,
+ SVGA_VIDEO_SIZE, /* Deprecated */
SVGA_VIDEO_WIDTH,
@@ -595,4 +876,4 @@ enum {
SVGA_VIDEO_SRC_HEIGHT,
- SVGA_VIDEO_DST_X,
- SVGA_VIDEO_DST_Y,
+ SVGA_VIDEO_DST_X, /* Signed int32 */
+ SVGA_VIDEO_DST_Y, /* Signed int32 */
SVGA_VIDEO_DST_WIDTH,
@@ -602,2 +883,4 @@ enum {
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
@@ -627,4 +910,4 @@ typedef struct SVGAOverlayUnit {
uint32 srcHeight;
- uint32 dstX;
- uint32 dstY;
+ int32 dstX;
+ int32 dstY;
uint32 dstWidth;
@@ -632,2 +915,4 @@ typedef struct SVGAOverlayUnit {
uint32 pitches[3];
+ uint32 dataGMRId;
+ uint32 dstScreenId;
} SVGAOverlayUnit;
@@ -636,230 +921,644 @@ typedef struct SVGAOverlayUnit {
/*
- * Drawing object ID's, in the range 0 to SVGA_MAX_ID
+ * 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_MAX_ID 499
+#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 */
/*
- * Macros to compute variable length items (sizes in 32-bit words, except
- * for SVGA_GLYPH_SCANLINE_SIZE, which is in bytes).
+ * 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;
-#define SVGA_BITMAP_SIZE(w,h) ((((w)+31) >> 5) * (h))
-#define SVGA_BITMAP_SCANLINE_SIZE(w) (( (w)+31 ) >> 5)
-#define SVGA_PIXMAP_SIZE(w,h,bpp) ((( ((w)*(bpp))+31 ) >> 5) * (h))
-#define SVGA_PIXMAP_SCANLINE_SIZE(w,bpp) (( ((w)*(bpp))+31 ) >> 5)
-#define SVGA_GLYPH_SIZE(w,h) ((((((w) + 7) >> 3) * (h)) + 3) >> 2)
-#define SVGA_GLYPH_SCANLINE_SIZE(w) (((w) + 7) >> 3)
-#define SVGA_ESCAPE_SIZE(s) (((s) + 3) >> 2)
/*
- * Increment from one scanline to the next of a bitmap or pixmap
+ * 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.
*/
-#define SVGA_BITMAP_INCREMENT(w) ((( (w)+31 ) >> 5) * sizeof (uint32))
-#define SVGA_PIXMAP_INCREMENT(w,bpp) ((( ((w)*(bpp))+31 ) >> 5) * sizeof (uint32))
+
+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
+
/*
- * Transparent color for DRAW_GLYPH_CLIPPED
+ * 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.
*/
-#define SVGA_COLOR_TRANSPARENT (~0)
+
+typedef
+struct SVGAFifoCmdUpdate {
+ uint32 x;
+ uint32 y;
+ uint32 width;
+ uint32 height;
+} SVGAFifoCmdUpdate;
+
/*
- * Commands in the command FIFO
+ * 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
*/
-#define SVGA_CMD_INVALID_CMD 0
- /* FIFO layout:
- <nothing> (well, undefined) */
+typedef
+struct SVGAFifoCmdRectCopy {
+ uint32 srcX;
+ uint32 srcY;
+ uint32 destX;
+ uint32 destY;
+ uint32 width;
+ uint32 height;
+} SVGAFifoCmdRectCopy;
-#define SVGA_CMD_UPDATE 1
- /* FIFO layout:
- X, Y, Width, Height */
-#define SVGA_CMD_RECT_FILL 2
- /* FIFO layout:
- Color, X, Y, Width, Height */
+/*
+ * 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
+ */
-#define SVGA_CMD_RECT_COPY 3
- /* FIFO layout:
- Source X, Source Y, Dest X, Dest Y, Width, Height */
+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;
-#define SVGA_CMD_DEFINE_BITMAP 4
- /* FIFO layout:
- Pixmap ID, Width, Height, <scanlines> */
-#define SVGA_CMD_DEFINE_BITMAP_SCANLINE 5
- /* FIFO layout:
- Pixmap ID, Width, Height, Line #, scanline */
+/*
+ * 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
+ */
-#define SVGA_CMD_DEFINE_PIXMAP 6
- /* FIFO layout:
- Pixmap ID, Width, Height, Depth, <scanlines> */
+typedef
+struct SVGAFifoCmdDefineAlphaCursor {
+ uint32 id; /* Reserved, must be zero. */
+ uint32 hotspotX;
+ uint32 hotspotY;
+ uint32 width;
+ uint32 height;
+ /* Followed by scanline data */
+} SVGAFifoCmdDefineAlphaCursor;
-#define SVGA_CMD_DEFINE_PIXMAP_SCANLINE 7
- /* FIFO layout:
- Pixmap ID, Width, Height, Depth, Line #, scanline */
-#define SVGA_CMD_RECT_BITMAP_FILL 8
- /* FIFO layout:
- Bitmap ID, X, Y, Width, Height, Foreground, Background */
+/*
+ * 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
+ */
-#define SVGA_CMD_RECT_PIXMAP_FILL 9
- /* FIFO layout:
- Pixmap ID, X, Y, Width, Height */
+typedef
+struct SVGAFifoCmdUpdateVerbose {
+ uint32 x;
+ uint32 y;
+ uint32 width;
+ uint32 height;
+ uint32 reason;
+} SVGAFifoCmdUpdateVerbose;
-#define SVGA_CMD_RECT_BITMAP_COPY 10
- /* FIFO layout:
- Bitmap ID, Source X, Source Y, Dest X, Dest Y,
- Width, Height, Foreground, Background */
-#define SVGA_CMD_RECT_PIXMAP_COPY 11
- /* FIFO layout:
- Pixmap ID, Source X, Source Y, Dest X, Dest Y, Width, Height */
+/*
+ * 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_CMD_FREE_OBJECT 12
- /* FIFO layout:
- Object (pixmap, bitmap, ...) ID */
+#define SVGA_INVALID_DISPLAY_ID ((uint32)-1)
-#define SVGA_CMD_RECT_ROP_FILL 13
- /* FIFO layout:
- Color, X, Y, Width, Height, ROP */
+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;
-#define SVGA_CMD_RECT_ROP_COPY 14
- /* FIFO layout:
- Source X, Source Y, Dest X, Dest Y, Width, Height, ROP */
-#define SVGA_CMD_RECT_ROP_BITMAP_FILL 15
- /* FIFO layout:
- ID, X, Y, Width, Height, Foreground, Background, ROP */
+/*
+ * 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.
+ */
-#define SVGA_CMD_RECT_ROP_PIXMAP_FILL 16
- /* FIFO layout:
- ID, X, Y, Width, Height, ROP */
+typedef
+struct {
+ uint32 fence;
+} SVGAFifoCmdFence;
-#define SVGA_CMD_RECT_ROP_BITMAP_COPY 17
- /* FIFO layout:
- ID, Source X, Source Y,
- Dest X, Dest Y, Width, Height, Foreground, Background, ROP */
-#define SVGA_CMD_RECT_ROP_PIXMAP_COPY 18
- /* FIFO layout:
- ID, Source X, Source Y, Dest X, Dest Y, Width, Height, ROP */
+/*
+ * 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
+ */
-#define SVGA_CMD_DEFINE_CURSOR 19
- /* FIFO layout:
- ID, Hotspot X, Hotspot Y, Width, Height,
- Depth for AND mask, Depth for XOR mask,
- <scanlines for AND mask>, <scanlines for XOR mask> */
+typedef
+struct SVGAFifoCmdEscape {
+ uint32 nsid;
+ uint32 size;
+ /* followed by 'size' bytes of data */
+} SVGAFifoCmdEscape;
-#define SVGA_CMD_DISPLAY_CURSOR 20
- /* FIFO layout:
- ID, On/Off (1 or 0) */
-#define SVGA_CMD_MOVE_CURSOR 21
- /* FIFO layout:
- X, Y */
+/*
+ * 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
+ */
-#define SVGA_CMD_DEFINE_ALPHA_CURSOR 22
- /* FIFO layout:
- ID, Hotspot X, Hotspot Y, Width, Height,
- <scanlines> */
+typedef
+struct {
+ SVGAScreenObject screen; /* Variable-length according to version */
+} SVGAFifoCmdDefineScreen;
-#define SVGA_CMD_DRAW_GLYPH 23
- /* FIFO layout:
- X, Y, W, H, FGCOLOR, <stencil buffer> */
-
-#define SVGA_CMD_DRAW_GLYPH_CLIPPED 24
- /* FIFO layout:
- X, Y, W, H, FGCOLOR, BGCOLOR, <cliprect>, <stencil buffer>
- Transparent color expands are done by setting BGCOLOR to ~0 */
-
-#define SVGA_CMD_UPDATE_VERBOSE 25
- /* FIFO layout:
- X, Y, Width, Height, Reason */
-
-#define SVGA_CMD_SURFACE_FILL 26
- /* FIFO layout:
- color, dstSurfaceOffset, x, y, w, h, rop */
-
-#define SVGA_CMD_SURFACE_COPY 27
- /* FIFO layout:
- srcSurfaceOffset, dstSurfaceOffset, srcX, srcY,
- destX, destY, w, h, rop */
-
-#define SVGA_CMD_SURFACE_ALPHA_BLEND 28
- /* FIFO layout:
- srcSurfaceOffset, dstSurfaceOffset, srcX, srcY,
- destX, destY, w, h, op (SVGA_BLENDOP*), flags (SVGA_BLENDFLAGS*),
- param1, param2 */
-
-#define SVGA_CMD_FRONT_ROP_FILL 29
- /* FIFO layout:
- Color, X, Y, Width, Height, ROP */
-
-#define SVGA_CMD_FENCE 30
- /* FIFO layout:
- Fence value */
-
-#define SVGA_CMD_VIDEO_PLAY_OBSOLETE 31
- /* Obsolete; do not use. */
-
-#define SVGA_CMD_VIDEO_END_OBSOLETE 32
- /* Obsolete; do not use. */
-
-#define SVGA_CMD_ESCAPE 33
- /* FIFO layout:
- Namespace ID, size(bytes), data */
-
-#define SVGA_CMD_MAX 34
-
-#define SVGA_CMD_MAX_ARGS 64
-
-/*
- * Location and size of SVGA frame buffer and the FIFO.
- */
-#define SVGA_VRAM_MIN_SIZE (4 * 640 * 480) /* bytes */
-#define SVGA_VRAM_MAX_SIZE (128 * 1024 * 1024)
-
-#define SVGA_VRAM_SIZE_WS (16 * 1024 * 1024) /* 16 MB */
-#define SVGA_MEM_SIZE_WS (2 * 1024 * 1024) /* 2 MB */
-#define SVGA_VRAM_SIZE_SERVER (4 * 1024 * 1024) /* 4 MB */
-#define SVGA_MEM_SIZE_SERVER (256 * 1024) /* 256 KB */
-
-#if /* defined(VMX86_WGS) || */ defined(VMX86_SERVER)
-#define SVGA_VRAM_SIZE SVGA_VRAM_SIZE_SERVER
-#define SVGA_MEM_SIZE SVGA_MEM_SIZE_SERVER
-#else
-#define SVGA_VRAM_SIZE SVGA_VRAM_SIZE_WS
-#define SVGA_MEM_SIZE SVGA_MEM_SIZE_WS
-#endif
/*
- * 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
+ * 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;
diff --git a/src/vmware.c b/src/vmware.c
index fa01dca..9160cf2 100644
--- a/src/vmware.c
+++ b/src/vmware.c
@@ -41,2 +41,4 @@ char rcsId_vmware[] =
#include "svga_modes.h"
+#include "vmware_bootstrap.h"
+#include "vmware_common.h"
@@ -47,185 +49,5 @@ char rcsId_vmware[] =
-#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
-
-/*
- * Sanity check that xf86PciInfo.h has the correct values (which come from
- * the VMware source tree in vm_device_version.h.
- */
-#if PCI_CHIP_VMWARE0405 != PCI_DEVICE_ID_VMWARE_SVGA2
-#error "PCI_CHIP_VMWARE0405 is wrong, update it from vm_device_version.h"
-#endif
-#if PCI_CHIP_VMWARE0710 != PCI_DEVICE_ID_VMWARE_SVGA
-#error "PCI_CHIP_VMWARE0710 is wrong, update it from vm_device_version.h"
-#endif
-#if PCI_VENDOR_VMWARE != PCI_VENDOR_ID_VMWARE
-#error "PCI_VENDOR_VMWARE is wrong, update it from vm_device_version.h"
-#endif
-
-#define VMWARE_INCHTOMM 25.4
-
-/*
- * This is the only way I know to turn a #define of an integer constant into
- * a constant string.
- */
-#define VMW_INNERSTRINGIFY(s) #s
-#define VMW_STRING(str) VMW_INNERSTRINGIFY(str)
-
-#define VMWARE_NAME "vmwlegacy"
-#define VMWARE_DRIVER_NAME "vmwlegacy"
-#define VMWARE_DRIVER_VERSION \
- (PACKAGE_VERSION_MAJOR * 65536 + PACKAGE_VERSION_MINOR * 256 + PACKAGE_VERSION_PATCHLEVEL)
-#define VMWARE_DRIVER_VERSION_STRING \
- VMW_STRING(PACKAGE_VERSION_MAJOR) "." VMW_STRING(PACKAGE_VERSION_MINOR) \
- "." VMW_STRING(PACKAGE_VERSION_PATCHLEVEL)
-
-static const char VMWAREBuildStr[] = "VMware Guest X Server "
- VMWARE_DRIVER_VERSION_STRING " - build=$Name$\n";
-
-/*
- * Standard four digit version string expected by VMware Tools installer.
- * As the driver's version is only {major, minor, patchlevel},
- * The fourth digit may describe the commit number relative to the
- * last version tag as output from `git describe`
- */
-
-#ifdef __GNUC__
-#ifdef VMW_SUBPATCH
-const char vmwlegacy_drv_modinfo[]
-__attribute__((section(".modinfo"),unused)) =
- "version=" VMWARE_DRIVER_VERSION_STRING "." VMW_STRING(VMW_SUBPATCH);
-#else
-const char vmwlegacy_drv_modinfo[]
-__attribute__((section(".modinfo"),unused)) =
- "version=" VMWARE_DRIVER_VERSION_STRING ".0";
-#endif /*VMW_SUBPATCH*/
-#endif
-
-static SymTabRec VMWAREChipsets[] = {
- { PCI_CHIP_VMWARE0405, "vmware0405" },
- { PCI_CHIP_VMWARE0710, "vmware0710" },
- { -1, NULL }
-};
-
-#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 VMWARE_DEVICE_MATCH(d, i) \
- {PCI_VENDOR_VMWARE, (d), PCI_MATCH_ANY, PCI_MATCH_ANY, 0, 0, (i) }
-
-static const struct pci_id_match VMwareDeviceMatch[] = {
- VMWARE_DEVICE_MATCH (PCI_CHIP_VMWARE0405, 0 ),
- VMWARE_DEVICE_MATCH (PCI_CHIP_VMWARE0710, 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_CHIP_VMWARE0405, PCI_CHIP_VMWARE0405, RES_EXCLUSIVE_VGA },
- { PCI_CHIP_VMWARE0710, PCI_CHIP_VMWARE0710, vmwareLegacyRes },
- { -1, -1, RES_UNDEFINED }
-};
-
-#if HAVE_XORG_SERVER_1_7_0
-
+#if (GET_ABI_MAJOR(ABI_VIDEODRV_VERSION) >= 5)
#define xf86LoaderReqSymLists(...) do {} while (0)
-#define LoaderRefSymLists(...) do {} while (0)
-
-#else
-
-static 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 /* HAVE_XORG_SERVER_1_7_0 */
-
-#ifdef XFree86LOADER
-static XF86ModuleVersionInfo vmwlegacyVersRec = {
- 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 */
-
-typedef enum {
- OPTION_HW_CURSOR,
- OPTION_XINERAMA,
- OPTION_STATIC_XINERAMA,
- OPTION_DEFAULT_MODE,
-} VMWAREOpts;
-
-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_DEFAULT_MODE, "AddDefaultMode", OPTV_BOOLEAN, {0}, FALSE },
- { -1, NULL, OPTV_NONE, {0}, FALSE }
-};
+#endif
@@ -468,137 +290,2 @@ RewriteTagString(const char *istr, char *ostr, int osize)
-static void
-VMWAREIdentify(int flags)
-{
- xf86PrintChipsets(VMWARE_NAME, "driver for VMware SVGA", VMWAREChipsets);
-}
-
-static const OptionInfoRec *
-VMWAREAvailableOptions(int chipid, int busid)
-{
- return VMWAREOptions;
-}
-
-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;
-}
-
-static xXineramaScreenInfo *
-VMWAREParseTopologyString(ScrnInfoPtr pScrn,
- const char *topology,
- unsigned int *retNumOutputs)
-{
- xXineramaScreenInfo *extents = NULL;
- unsigned int numOutputs = 0;
- const char *str = topology;
-
- xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Parsing static Xinerama topology: Starting...\n");
-
- 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 static Xinerama topology: Succeeded.\n");
- goto exit;
-
- error:
- xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Parsing static Xinerama topology: Failed.\n");
-
- free(extents);
- extents = NULL;
- numOutputs = 0;
-
- exit:
- *retNumOutputs = numOutputs;
- return extents;
-}
-
-
static Bool
@@ -901,5 +588,4 @@ VMWAREPreInit(ScrnInfoPtr pScrn, int flags)
xf86CollectOptions(pScrn, NULL);
- if (!(options = malloc(sizeof(VMWAREOptions))))
+ if (!(options = VMWARECopyOptions()))
return FALSE;
- memcpy(options, VMWAREOptions, sizeof(VMWAREOptions));
xf86ProcessOptions(pScrn->scrnIndex, pScrn->options, options);
@@ -910,5 +596,2 @@ VMWAREPreInit(ScrnInfoPtr pScrn, int flags)
- from = X_PROBED;
- pScrn->chipset = (char*)xf86TokenToString(VMWAREChipsets, DEVICE_ID(pVMWARE->PciInfo));
-
if (!pScrn->chipset) {
@@ -1610,42 +1293,2 @@ vmwareIsRegionEqual(const RegionPtr reg1,
-#if VMWARE_DRIVER_FUNC
-static Bool
-VMWareDriverFunc(ScrnInfoPtr pScrn,
- xorgDriverFuncOp op,
- pointer data)
-{
- CARD32 *flag;
- xorgRRModeMM *modemm;
-
- switch (op) {
- case GET_REQUIRED_HW_INTERFACES:
- flag = (CARD32 *)data;
-
- if (flag) {
- *flag = HW_IO | HW_MMIO;
- }
- return TRUE;
- case RR_GET_MODE_MM:
- modemm = (xorgRRModeMM *)data;
-
- /*
- * Because changing the resolution of the guest is usually changing the size
- * of a window on the host desktop, the real physical DPI will not change. To
- * keep the guest in sync, we scale the 'physical' screen dimensions to
- * keep the DPI constant.
- */
- if (modemm && modemm->mode) {
- modemm->mmWidth = (modemm->mode->HDisplay * VMWARE_INCHTOMM +
- pScrn->xDpi / 2) / pScrn->xDpi;
- modemm->mmHeight = (modemm->mode->VDisplay * VMWARE_INCHTOMM +
- pScrn->yDpi / 2) / pScrn->yDpi;
- }
- return TRUE;
- default:
- return FALSE;
- }
-}
-#endif
-
-
static Bool
@@ -1665,5 +1308,4 @@ VMWAREScreenInit(int scrnIndex, ScreenPtr pScreen, int argc, char **argv)
xf86CollectOptions(pScrn, NULL);
- if (!(options = malloc(sizeof(VMWAREOptions))))
+ if (!(options = VMWARECopyOptions()))
return FALSE;
- memcpy(options, VMWAREOptions, sizeof(VMWAREOptions));
xf86ProcessOptions(pScrn->scrnIndex, pScrn->options, options);
@@ -1682,3 +1324,15 @@ VMWAREScreenInit(int scrnIndex, ScreenPtr pScreen, int argc, char **argv)
- if (useXinerama && xf86IsOptionSet(options, OPTION_STATIC_XINERAMA)) {
+ if (useXinerama && xf86IsOptionSet(options, OPTION_GUI_LAYOUT)) {
+ char *topology = xf86GetOptValString(options, OPTION_GUI_LAYOUT);
+ if (topology) {
+ pVMWARE->xineramaState =
+ VMWAREParseTopologyString(pScrn, topology,
+ &pVMWARE->xineramaNumOutputs, "gui");
+
+ pVMWARE->xineramaStatic = pVMWARE->xineramaState != NULL;
+
+ free(topology);
+ }
+ } else if (useXinerama &&
+ xf86IsOptionSet(options, OPTION_STATIC_XINERAMA)) {
char *topology = xf86GetOptValString(options, OPTION_STATIC_XINERAMA);
@@ -1686,3 +1340,5 @@ VMWAREScreenInit(int scrnIndex, ScreenPtr pScreen, int argc, char **argv)
pVMWARE->xineramaState =
- VMWAREParseTopologyString(pScrn, topology, &pVMWARE->xineramaNumOutputs);
+ VMWAREParseTopologyString(pScrn, topology,
+ &pVMWARE->xineramaNumOutputs,
+ "static Xinerama");
@@ -1988,153 +1644,12 @@ VMWAREValidMode(int scrnIndex, DisplayModePtr mode, Bool verbose, int flags)
-#if XSERVER_LIBPCIACCESS
-static Bool
-VMwarePciProbe (DriverPtr drv,
- int entity_num,
- struct pci_device *device,
- intptr_t match_data)
-{
- ScrnInfoPtr scrn = NULL;
- EntityInfoPtr entity;
-
- scrn = xf86ConfigPciEntity(scrn, 0, entity_num, VMWAREPciChipsets,
- NULL, NULL, NULL, NULL, NULL);
- if (scrn != NULL) {
- scrn->driverVersion = VMWARE_DRIVER_VERSION;
- scrn->driverName = VMWARE_DRIVER_NAME;
- scrn->name = VMWARE_NAME;
- scrn->Probe = NULL;
- }
-
- entity = xf86GetEntityInfo(entity_num);
- switch (DEVICE_ID(device)) {
- case PCI_CHIP_VMWARE0405:
- case PCI_CHIP_VMWARE0710:
- xf86MsgVerb(X_INFO, 4, "VMwarePciProbe: Valid device\n");
- scrn->PreInit = VMWAREPreInit;
- scrn->ScreenInit = VMWAREScreenInit;
- scrn->SwitchMode = VMWARESwitchMode;
- scrn->EnterVT = VMWAREEnterVT;
- scrn->LeaveVT = VMWARELeaveVT;
- scrn->FreeScreen = VMWAREFreeScreen;
- scrn->ValidMode = VMWAREValidMode;
- break;
- default:
- xf86MsgVerb(X_INFO, 4, "VMwarePciProbe: Unknown device\n");
- }
- return scrn != NULL;
-}
-#else
-
-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_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;
- pScrn->PreInit = VMWAREPreInit;
- pScrn->ScreenInit = VMWAREScreenInit;
- pScrn->SwitchMode = VMWARESwitchMode;
- pScrn->AdjustFrame = VMWAREAdjustFrame;
- pScrn->EnterVT = VMWAREEnterVT;
- pScrn->LeaveVT = VMWARELeaveVT;
- pScrn->FreeScreen = VMWAREFreeScreen;
- pScrn->ValidMode = VMWAREValidMode;
- foundScreen = TRUE;
- }
- }
- free(usedChips);
- }
- return foundScreen;
-}
-#endif
-
-
-_X_EXPORT DriverRec vmwlegacy = {
- VMWARE_DRIVER_VERSION,
- VMWARE_DRIVER_NAME,
- VMWAREIdentify,
-#if XSERVER_LIBPCIACCESS
- NULL,
-#else
- VMWAREProbe,
-#endif
- VMWAREAvailableOptions,
- NULL,
- 0,
-#if VMWARE_DRIVER_FUNC
- VMWareDriverFunc,
-#endif
-#if XSERVER_LIBPCIACCESS
- VMwareDeviceMatch,
- VMwarePciProbe,
-#endif
-};
-
-#ifdef XFree86LOADER
-static MODULESETUPPROTO(vmwlegacySetup);
-
-_X_EXPORT XF86ModuleData vmwlegacyModuleData = {
- &vmwlegacyVersRec,
- vmwlegacySetup,
- NULL
-};
-
-static pointer
-vmwlegacySetup(pointer module, pointer opts, int *errmaj, int *errmin)
+void
+vmwlegacy_hookup(ScrnInfoPtr pScrn)
{
- static Bool setupDone = FALSE;
-
- if (!setupDone) {
- setupDone = TRUE;
-
- xf86AddDriver(&vmwlegacy, module, VMWARE_DRIVER_FUNC);
-
- LoaderRefSymLists(vgahwSymbols, fbSymbols, ramdacSymbols,
- shadowfbSymbols, NULL);
-
- return (pointer)1;
- }
- if (errmaj) {
- *errmaj = LDR_ONCEONLY;
- }
- return NULL;
+ pScrn->PreInit = VMWAREPreInit;
+ pScrn->ScreenInit = VMWAREScreenInit;
+ pScrn->SwitchMode = VMWARESwitchMode;
+ pScrn->EnterVT = VMWAREEnterVT;
+ pScrn->LeaveVT = VMWARELeaveVT;
+ pScrn->FreeScreen = VMWAREFreeScreen;
+ pScrn->ValidMode = VMWAREValidMode;
}
-#endif /* XFree86LOADER */
diff --git a/src/vmware_bootstrap.c b/src/vmware_bootstrap.c
new file mode 100644
index 0000000..522fec0
--- /dev/null
+++ b/src/vmware_bootstrap.c
@@ -0,0 +1,503 @@
+/*
+ * 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 "xf86PciInfo.h" /* pci vendor id */
+#include "xf86Pci.h" /* pci */
+#include "vm_device_version.h"
+#include "vmware_bootstrap.h"
+
+#ifndef HAVE_XORG_SERVER_1_5_0
+#include <xf86_ansic.h>
+#include <xf86_libc.h>
+#endif
+
+#ifdef HaveDriverFuncs
+#define VMWARE_DRIVER_FUNC HaveDriverFuncs
+#else
+#define VMWARE_DRIVER_FUNC 0
+#endif
+
+/*
+ * So that the file compiles unmodified when dropped in to a < 6.9 source tree.
+ */
+#ifndef _X_EXPORT
+#define _X_EXPORT
+#endif
+/*
+ * So that the file compiles unmodified when dropped into an xfree source tree.
+ */
+#ifndef XORG_VERSION_CURRENT
+#define XORG_VERSION_CURRENT XF86_VERSION_CURRENT
+#endif
+
+/*
+ * Sanity check that xf86PciInfo.h has the correct values (which come from
+ * the VMware source tree in vm_device_version.h.
+ */
+#if PCI_CHIP_VMWARE0405 != PCI_DEVICE_ID_VMWARE_SVGA2
+#error "PCI_CHIP_VMWARE0405 is wrong, update it from vm_device_version.h"
+#endif
+#if PCI_CHIP_VMWARE0710 != PCI_DEVICE_ID_VMWARE_SVGA
+#error "PCI_CHIP_VMWARE0710 is wrong, update it from vm_device_version.h"
+#endif
+#if PCI_VENDOR_VMWARE != PCI_VENDOR_ID_VMWARE
+#error "PCI_VENDOR_VMWARE is wrong, update it from vm_device_version.h"
+#endif
+
+/*
+ * This is the only way I know to turn a #define of an integer constant into
+ * a constant string.
+ */
+#define VMW_INNERSTRINGIFY(s) #s
+#define VMW_STRING(str) VMW_INNERSTRINGIFY(str)
+
+#define VMWARE_NAME "vmware"
+#define VMWARE_DRIVER_NAME "vmware"
+#define VMWARE_DRIVER_VERSION \
+ (PACKAGE_VERSION_MAJOR * 65536 + PACKAGE_VERSION_MINOR * 256 + PACKAGE_VERSION_PATCHLEVEL)
+#define VMWARE_DRIVER_VERSION_STRING \
+ VMW_STRING(PACKAGE_VERSION_MAJOR) "." VMW_STRING(PACKAGE_VERSION_MINOR) \
+ "." VMW_STRING(PACKAGE_VERSION_PATCHLEVEL)
+
+static const char VMWAREBuildStr[] = "VMware Guest X Server "
+ VMWARE_DRIVER_VERSION_STRING " - build=$Name$\n";
+
+/*
+ * Standard four digit version string expected by VMware Tools installer.
+ * As the driver's version is only {major, minor, patchlevel},
+ * The fourth digit may describe the commit number relative to the
+ * last version tag as output from `git describe`
+ */
+
+#ifdef __GNUC__
+#ifdef VMW_SUBPATCH
+const char vmware_drv_modinfo[]
+__attribute__((section(".modinfo"),unused)) =
+ "version=" VMWARE_DRIVER_VERSION_STRING "." VMW_STRING(VMW_SUBPATCH);
+#else
+const char vmware_drv_modinfo[]
+__attribute__((section(".modinfo"),unused)) =
+ "version=" VMWARE_DRIVER_VERSION_STRING ".0";
+#endif /*VMW_SUBPATCH*/
+#endif
+
+#ifndef XSERVER_LIBPCIACCESS
+static resRange vmwareLegacyRes[] = {
+ { ResExcIoBlock, SVGA_LEGACY_BASE_PORT,
+ SVGA_LEGACY_BASE_PORT + SVGA_NUM_PORTS*sizeof(uint32)},
+ _VGA_EXCLUSIVE, _END
+};
+#else
+#define vmwareLegacyRes NULL
+#endif
+
+#if XSERVER_LIBPCIACCESS
+#define VENDOR_ID(p) (p)->vendor_id
+#define DEVICE_ID(p) (p)->device_id
+#define SUBVENDOR_ID(p) (p)->subvendor_id
+#define SUBSYS_ID(p) (p)->subdevice_id
+#define CHIP_REVISION(p) (p)->revision
+#else
+#define VENDOR_ID(p) (p)->vendor
+#define DEVICE_ID(p) (p)->chipType
+#define SUBVENDOR_ID(p) (p)->subsysVendor
+#define SUBSYS_ID(p) (p)->subsysCard
+#define CHIP_REVISION(p) (p)->chipRev
+#endif
+
+#if XSERVER_LIBPCIACCESS
+
+#define VMWARE_DEVICE_MATCH(d, i) \
+ {PCI_VENDOR_VMWARE, (d), PCI_MATCH_ANY, PCI_MATCH_ANY, 0, 0, (i) }
+
+static const struct pci_id_match VMwareDeviceMatch[] = {
+ VMWARE_DEVICE_MATCH (PCI_CHIP_VMWARE0405, 0 ),
+ VMWARE_DEVICE_MATCH (PCI_CHIP_VMWARE0710, 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_CHIP_VMWARE0405, PCI_CHIP_VMWARE0405, RES_EXCLUSIVE_VGA },
+ { PCI_CHIP_VMWARE0710, PCI_CHIP_VMWARE0710, vmwareLegacyRes },
+ { -1, -1, RES_UNDEFINED }
+};
+
+static SymTabRec VMWAREChipsets[] = {
+ { PCI_CHIP_VMWARE0405, "vmware0405" },
+ { PCI_CHIP_VMWARE0710, "vmware0710" },
+ { -1, NULL }
+};
+
+#ifdef XFree86LOADER
+static XF86ModuleVersionInfo vmwareVersRec = {
+ VMWARE_DRIVER_NAME,
+ MODULEVENDORSTRING,
+ MODINFOSTRING1,
+ MODINFOSTRING2,
+ XORG_VERSION_CURRENT,
+ PACKAGE_VERSION_MAJOR, PACKAGE_VERSION_MINOR, PACKAGE_VERSION_PATCHLEVEL,
+ ABI_CLASS_VIDEODRV,
+ ABI_VIDEODRV_VERSION,
+ MOD_CLASS_VIDEODRV,
+ { 0, 0, 0, 0}
+};
+#endif /* XFree86LOADER */
+
+static const OptionInfoRec VMWAREOptions[] = {
+ { OPTION_HW_CURSOR, "HWcursor", OPTV_BOOLEAN, {0}, FALSE },
+ { OPTION_XINERAMA, "Xinerama", OPTV_BOOLEAN, {0}, FALSE },
+ { OPTION_STATIC_XINERAMA, "StaticXinerama", OPTV_STRING, {0}, FALSE },
+ { OPTION_GUI_LAYOUT, "GuiLayout", OPTV_STRING, {0}, FALSE },
+ { OPTION_DEFAULT_MODE, "AddDefaultMode", OPTV_BOOLEAN, {0}, FALSE },
+ { OPTION_RENDER_ACCEL, "RenderAccel", OPTV_BOOLEAN, {0}, FALSE},
+ { OPTION_DRI, "DRI", OPTV_BOOLEAN, {0}, FALSE},
+ { OPTION_DIRECT_PRESENTS, "DirectPresents", OPTV_BOOLEAN, {0}, FALSE},
+ { OPTION_HW_PRESENTS, "HWPresents", OPTV_BOOLEAN, {0}, FALSE},
+ { OPTION_RENDERCHECK, "RenderCheck", OPTV_BOOLEAN, {0}, FALSE},
+ { -1, NULL, OPTV_NONE, {0}, FALSE }
+};
+
+OptionInfoPtr VMWARECopyOptions(void)
+{
+ OptionInfoPtr options;
+ if (!(options = malloc(sizeof(VMWAREOptions))))
+ return NULL;
+
+ memcpy(options, VMWAREOptions, sizeof(VMWAREOptions));
+ return options;
+}
+
+static Bool
+VMwarePreinitStub(ScrnInfoPtr pScrn, int flags)
+{
+#if XSERVER_LIBPCIACCESS
+ struct pci_device *pciInfo;
+#else
+ pciVideoPtr pciInfo;
+#endif /* XSERVER_LIBPCIACCESS */
+ EntityInfoPtr pEnt;
+
+ pScrn->PreInit = pScrn->driverPrivate;
+
+#ifdef BUILD_VMWGFX
+ pScrn->driverPrivate = NULL;
+
+ /*
+ * Try vmwgfx path.
+ */
+ if ((*pScrn->PreInit)(pScrn, flags))
+ return TRUE;
+
+#else
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+ "Driver was compiled without KMS- and 3D support.\n");
+#endif /* defined(BUILD_VMWGFX) */
+ xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
+ "Disabling 3D support.\n");
+ xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
+ "Disabling Render Acceleration.\n");
+ xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
+ "Disabling RandR12+ support.\n");
+
+ pScrn->driverPrivate = NULL;
+ vmwlegacy_hookup(pScrn);
+
+ pEnt = xf86GetEntityInfo(pScrn->entityList[0]);
+ if (pEnt->location.type != BUS_PCI)
+ return FALSE;
+
+ pciInfo = xf86GetPciInfoForEntity(pEnt->index);
+ if (pciInfo == NULL)
+ return FALSE;
+
+ pScrn->chipset = (char*)xf86TokenToString(VMWAREChipsets,
+ DEVICE_ID(pciInfo));
+
+ return (*pScrn->PreInit)(pScrn, flags);
+};
+
+#if XSERVER_LIBPCIACCESS
+static Bool
+VMwarePciProbe (DriverPtr drv,
+ int entity_num,
+ struct pci_device *device,
+ intptr_t match_data)
+{
+ ScrnInfoPtr scrn = NULL;
+ EntityInfoPtr entity;
+
+ scrn = xf86ConfigPciEntity(scrn, 0, entity_num, VMWAREPciChipsets,
+ NULL, NULL, NULL, NULL, NULL);
+ if (scrn != NULL) {
+ scrn->driverVersion = VMWARE_DRIVER_VERSION;
+ scrn->driverName = VMWARE_DRIVER_NAME;
+ scrn->name = VMWARE_NAME;
+ scrn->Probe = NULL;
+ }
+
+ entity = xf86GetEntityInfo(entity_num);
+ switch (DEVICE_ID(device)) {
+ case PCI_CHIP_VMWARE0405:
+ case PCI_CHIP_VMWARE0710:
+ 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
+
+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_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;
+ pScrn->PreInit = VMWAREPreInit;
+
+#ifdef BUILD_VMWGFX
+ vmwgfx_hookup(scrn);
+#else
+ vmwlegacy_hookup(scrn);
+#endif /* defined(BUILD_VMWGFX) */
+
+ scrn->driverPrivate = scrn->PreInit;
+ scrn->PreInit = VMwarePreinitStub;
+ foundScreen = TRUE;
+ }
+ }
+ free(usedChips);
+ }
+ return foundScreen;
+}
+#endif
+
+static void
+VMWAREIdentify(int flags)
+{
+ xf86PrintChipsets(VMWARE_NAME, "driver for VMware SVGA", VMWAREChipsets);
+}
+
+static const OptionInfoRec *
+VMWAREAvailableOptions(int chipid, int busid)
+{
+ return VMWAREOptions;
+}
+
+#if VMWARE_DRIVER_FUNC
+static Bool
+VMWareDriverFunc(ScrnInfoPtr pScrn,
+ xorgDriverFuncOp op,
+ pointer data)
+{
+ CARD32 *flag;
+ xorgRRModeMM *modemm;
+
+ switch (op) {
+ case GET_REQUIRED_HW_INTERFACES:
+ flag = (CARD32 *)data;
+
+ if (flag) {
+ *flag = HW_IO | HW_MMIO;
+ }
+ return TRUE;
+ case RR_GET_MODE_MM:
+ modemm = (xorgRRModeMM *)data;
+
+ /*
+ * Because changing the resolution of the guest is usually changing the size
+ * of a window on the host desktop, the real physical DPI will not change. To
+ * keep the guest in sync, we scale the 'physical' screen dimensions to
+ * keep the DPI constant.
+ */
+ if (modemm && modemm->mode) {
+ modemm->mmWidth = (modemm->mode->HDisplay * VMWARE_INCHTOMM +
+ pScrn->xDpi / 2) / pScrn->xDpi;
+ modemm->mmHeight = (modemm->mode->VDisplay * VMWARE_INCHTOMM +
+ pScrn->yDpi / 2) / pScrn->yDpi;
+ }
+ return TRUE;
+ default:
+ return FALSE;
+ }
+}
+#endif
+
+
+_X_EXPORT DriverRec vmware = {
+ VMWARE_DRIVER_VERSION,
+ VMWARE_DRIVER_NAME,
+ VMWAREIdentify,
+#if XSERVER_LIBPCIACCESS
+ NULL,
+#else
+ VMWAREProbe,
+#endif
+ VMWAREAvailableOptions,
+ NULL,
+ 0,
+#if VMWARE_DRIVER_FUNC
+ VMWareDriverFunc,
+#endif
+#if XSERVER_LIBPCIACCESS
+ VMwareDeviceMatch,
+ VMwarePciProbe,
+#endif
+};
+
+#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
+
+#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);
+
+ LoaderRefSymLists(vgahwSymbols, fbSymbols, ramdacSymbols,
+ shadowfbSymbols, NULL);
+
+ return (pointer)1;
+ }
+ if (errmaj) {
+ *errmaj = LDR_ONCEONLY;
+ }
+ return NULL;
+}
+#endif /* XFree86LOADER */
diff --git a/src/vmware_bootstrap.h b/src/vmware_bootstrap.h
new file mode 100644
index 0000000..172deb8
--- /dev/null
+++ b/src/vmware_bootstrap.h
@@ -0,0 +1,59 @@
+/*
+ * 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);
+const char **vgahwSymbols;
+
+void
+vmwlegacy_hookup(ScrnInfoPtr pScrn);
+
+#ifdef BUILD_VMWGFX
+void
+vmwgfx_hookup(ScrnInfoPtr pScrn);
+#endif /* defined(BUILD_VMWGFX) */
+
+
+#endif
diff --git a/src/vmware_common.c b/src/vmware_common.c
new file mode 100644
index 0000000..6ef7ca6
--- /dev/null
+++ b/src/vmware_common.c
@@ -0,0 +1,163 @@
+/*
+ * Copyright 2011 VMWare, Inc.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Author: Unknown at vmware
+ */
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <xf86.h>
+#include "vmware_common.h"
+
+#ifndef HAVE_XORG_SERVER_1_5_0
+#include <xf86_ansic.h>
+#include <xf86_libc.h>
+#endif
+
+static int
+VMWAREParseTopologyElement(ScrnInfoPtr pScrn,
+ unsigned int output,
+ const char *elementName,
+ const char *element,
+ const char *expectedTerminators,
+ Bool needTerminator,
+ unsigned int *outValue)
+{
+ char buf[10] = {0, };
+ size_t i = 0;
+ int retVal = -1;
+ const char *str = element;
+
+ for (i = 0; str[i] >= '0' && str[i] <= '9'; i++);
+ if (i == 0) {
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Output %u: unable to parse %s.\n",
+ output, elementName);
+ goto exit;
+ }
+
+ strncpy(buf, str, i);
+ *outValue = atoi(buf);
+
+ if (*outValue > (unsigned short)-1) {
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Output %u: %s must be less than %hu.\n",
+ output, elementName, (unsigned short)-1);
+ goto exit;
+ }
+
+ str += i;
+
+ if (needTerminator || str[0] != '\0') {
+ Bool unexpected = TRUE;
+
+ for (i = 0; i < strlen(expectedTerminators); i++) {
+ if (str[0] == expectedTerminators[i]) {
+ unexpected = FALSE;
+ }
+ }
+
+ if (unexpected) {
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+ "Output %u: unexpected character '%c' after %s.\n",
+ output, str[0], elementName);
+ goto exit;
+ } else {
+ str++;
+ }
+ }
+
+ retVal = str - element;
+
+ exit:
+ return retVal;
+}
+
+xXineramaScreenInfo *
+VMWAREParseTopologyString(ScrnInfoPtr pScrn,
+ const char *topology,
+ unsigned int *retNumOutputs,
+ const char info[])
+{
+ xXineramaScreenInfo *extents = NULL;
+ unsigned int numOutputs = 0;
+ const char *str = topology;
+
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Parsing %s topology: Starting...\n",
+ info);
+
+ do {
+ unsigned int x, y, width, height;
+ int i;
+
+ i = VMWAREParseTopologyElement(pScrn, numOutputs, "width", str, "xX", TRUE, &width);
+ if (i == -1) {
+ goto error;
+ }
+ str += i;
+
+ i = VMWAREParseTopologyElement(pScrn, numOutputs, "height", str, "+", TRUE, &height);
+ if (i == -1) {
+ goto error;
+ }
+ str += i;
+
+ i= VMWAREParseTopologyElement(pScrn, numOutputs, "X offset", str, "+", TRUE, &x);
+ if (i == -1) {
+ goto error;
+ }
+ str += i;
+
+ i = VMWAREParseTopologyElement(pScrn, numOutputs, "Y offset", str, ";", FALSE, &y);
+ if (i == -1) {
+ goto error;
+ }
+ str += i;
+
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Output %u: %ux%u+%u+%u\n",
+ numOutputs, width, height, x, y);
+
+ numOutputs++;
+ extents = realloc(extents, numOutputs * sizeof (xXineramaScreenInfo));
+ extents[numOutputs - 1].x_org = x;
+ extents[numOutputs - 1].y_org = y;
+ extents[numOutputs - 1].width = width;
+ extents[numOutputs - 1].height = height;
+ } while (*str != 0);
+
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Parsing %s topology: Succeeded.\n",
+ info);
+ goto exit;
+
+ error:
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Parsing %s topology: Failed.\n",
+ info);
+
+ free(extents);
+ extents = NULL;
+ numOutputs = 0;
+
+ exit:
+ *retNumOutputs = numOutputs;
+ return extents;
+}
diff --git a/src/vmware_common.h b/src/vmware_common.h
new file mode 100644
index 0000000..9cd7194
--- /dev/null
+++ b/src/vmware_common.h
@@ -0,0 +1,41 @@
+/*
+ * 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>
+
+xXineramaScreenInfo *
+VMWAREParseTopologyString(ScrnInfoPtr pScrn,
+ const char *topology,
+ unsigned int *retNumOutputs,
+ const char info[]);
+
+#endif
diff --git a/src/vmwaremodule.c b/src/vmwaremodule.c
deleted file mode 100644
index 0da2440..0000000
--- a/src/vmwaremodule.c
+++ /dev/null
@@ -1,256 +0,0 @@
-/**********************************************************
- * 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.
- *
- **********************************************************/
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#ifdef HAVE_LIBDRM
-#include <xf86drm.h>
-#endif
-
-#include <xorg-server.h>
-#include <xf86.h>
-
-#ifndef HAVE_XORG_SERVER_1_5_0
-#include <xf86_ansic.h>
-#include <xf86_libc.h>
-#endif
-
-/*
- * Defines and exported module info.
- */
-
-#define VMWARE_DRIVER_NAME "vmware"
-#define VMWGFX_DRIVER_NAME "vmwgfx"
-#define VMWGFX_MODULE_NAME "vmwgfx"
-#define VMWGFX_COMPAT_MAJOR 11
-#define VMWGFX_REQUIRED_MAJOR 11
-#define VMWGFX_REQUIRED_MINOR 0
-#define VMWLEGACY_DRIVER_NAME "vmwlegacy"
-
-#define VMW_STRING_INNER(s) #s
-#define VMW_STRING(str) VMW_STRING_INNER(str)
-
-#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)
-
-/*
- * 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
-
-static XF86ModuleVersionInfo vmware_version;
-static MODULESETUPPROTO(vmware_setup);
-
-_X_EXPORT XF86ModuleData vmwareModuleData = {
- &vmware_version,
- vmware_setup,
- NULL
-};
-
-extern XF86ModuleData *VMWGFX_MODULE_DATA;
-
-/*
- * Chain loading functions
- */
-
-static Bool
-vmware_check_kernel_module()
-{
-#ifdef HAVE_LIBDRM
- /* Super simple way of knowing if the kernel driver is loaded */
- int ret = drmOpen(VMWGFX_MODULE_NAME, NULL);
- if (ret < 0) {
- /* This shouldn't go in the log as the original message does not */
- fprintf(stderr, "%s: Please ignore above \"FATAL: Module %s not found."
- "\"\n", VMWARE_DRIVER_NAME, VMWGFX_MODULE_NAME);
- /* This is what goes into the log on the other hand */
- xf86DrvMsg(-1, X_PROBED, "%s: Please ignore above \"[drm] failed to "
- "load kernel module \"%s\"\"\n", VMWARE_DRIVER_NAME,
- VMWGFX_MODULE_NAME);
- return FALSE;
- }
-
- drmClose(ret);
-
- return TRUE;
-#else
- return FALSE;
-#endif /* HAVE_LIBDRM */
-}
-
-static Bool
-vmware_check_vmwgfx_driver(int matched, pointer opts)
-{
-#ifdef HAVE_LIBDRM
- int major; int minor;
- pointer module;
- CARD32 version;
-
- if (matched) {
- xf86DrvMsg(-1, X_PROBED, "%s: X configured to use %s X driver assume "
- "who ever did that knows what they are doing\n",
- VMWARE_DRIVER_NAME, VMWGFX_DRIVER_NAME);
- /* Also how did they end up here, if the configured X to use vmwgfx and
- * X should load that driver for that hardware. And since there is only
- * one SVGA device this driver shouldn't be loaded. Weird...
- */
- return TRUE;
- }
-
- module = xf86LoadOneModule(VMWGFX_DRIVER_NAME, opts);
- if (!module) {
- xf86DrvMsg(-1, X_ERROR, "%s: Please ignore the above warnings about "
- "not being able to to load module/driver %s\n",
- VMWARE_DRIVER_NAME, VMWGFX_DRIVER_NAME);
- return FALSE;
- }
-
- version = xf86GetModuleVersion(module);
- major = GET_MODULE_MAJOR_VERSION(version);
- minor = GET_MODULE_MINOR_VERSION(version);
-
- if (major > VMWGFX_COMPAT_MAJOR ||
- major < VMWGFX_REQUIRED_MAJOR ||
- (major == VMWGFX_REQUIRED_MAJOR && minor < VMWGFX_REQUIRED_MINOR)) {
- xf86DrvMsg(-1, X_PROBED, "%s: The %s X driver failed version "
- "checking.\n", VMWARE_DRIVER_NAME, VMWGFX_DRIVER_NAME);
- goto err;
- }
-
- return TRUE;
-
-err:
- /* XXX We should drop the reference on the module here */
-#endif /* HAVE_LIBDRM */
- return FALSE;
-}
-
-static Bool
-vmware_chain_module(pointer opts)
-{
- int vmwlegacy_devices;
- int vmwgfx_devices;
- int vmware_devices;
- int matched;
- char *driver_name;
- GDevPtr *gdevs;
- GDevPtr gdev;
- int i;
-
- vmware_devices = xf86MatchDevice(VMWARE_DRIVER_NAME, &gdevs);
- vmwgfx_devices = xf86MatchDevice(VMWGFX_DRIVER_NAME, NULL);
- vmwlegacy_devices = xf86MatchDevice(VMWLEGACY_DRIVER_NAME, NULL);
-
- if (vmware_check_vmwgfx_driver(vmwgfx_devices, opts) &&
- vmware_check_kernel_module()) {
- xf86DrvMsg(-1, X_INFO, "%s: Using %s X driver.\n",
- VMWARE_DRIVER_NAME, VMWGFX_DRIVER_NAME);
- driver_name = VMWGFX_DRIVER_NAME;
- matched = 1;
- } else {
- xf86DrvMsg(-1, X_INFO, "%s: Using %s driver everything is fine.\n",
- VMWARE_DRIVER_NAME, VMWLEGACY_DRIVER_NAME);
- driver_name = VMWLEGACY_DRIVER_NAME;
- matched = vmwlegacy_devices;
- }
-
- /* Xorg -configure returns 1 from xf86MatchDevice with NULL gdevs */
- for (i = 0; gdevs && i < vmware_devices; i++) {
- gdev = gdevs[i];
- gdev->driver = driver_name;
- }
-
- free(gdevs);
-
- if (!matched) {
- if (xf86LoadOneModule(driver_name, opts) == NULL) {
- xf86DrvMsg(-1, X_ERROR, "%s: Unexpected failure while "
- "loading the \"%s\" driver. Giving up.\n",
- VMWARE_DRIVER_NAME, driver_name);
- return FALSE;
- }
- }
-
- return TRUE;
-}
-
-
-/*
- * Module info
- */
-
-static XF86ModuleVersionInfo vmware_version = {
- 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}
-};
-
-static pointer
-vmware_setup(pointer module, pointer opts, int *errmaj, int *errmin)
-{
- static Bool setupDone = 0;
-
- /* This module should be loaded only once, but check to be sure. */
- if (!setupDone) {
- setupDone = 1;
-
- /* Chain load the real driver */
- if (vmware_chain_module(opts))
- return (pointer) 1;
- else {
- if (errmaj)
- *errmaj = LDR_NOSUBENT;
- return NULL;
- }
- } else {
- if (errmaj)
- *errmaj = LDR_ONCEONLY;
- return NULL;
- }
-}
diff --git a/vmwgfx/Makefile.am b/vmwgfx/Makefile.am
new file mode 100644
index 0000000..1ee6582
--- /dev/null
+++ b/vmwgfx/Makefile.am
@@ -0,0 +1,26 @@
+noinst_LTLIBRARIES = libvmwgfx.la
+libvmwgfx_la_CFLAGS = $(CWARNFLAGS) $(XORG_CFLAGS) @LIBDRM_CFLAGS@ @XATRACKER_CFLAGS@ -I$(top_srcdir)/src -I$(top_srcdir)/saa
+libvmwgfx_la_LIBADD = @LIBDRM_LIBS@ $(top_srcdir)/saa/libsaa.la\
+ @XATRACKER_LIBS@
+libvmwgfx_la_DEPENDENCIES = $(top_srcdir)/saa/libsaa.la
+
+libvmwgfx_la_SOURCES = \
+ vmwgfx_driver.c \
+ vmwgfx_driver.h \
+ vmwgfx_crtc.c \
+ vmwgfx_output.c \
+ vmwgfx_dri2.c \
+ vmwgfx_tex_video.c \
+ vmwgfx_saa.c \
+ vmwgfx_saa.h \
+ vmwgfx_drmi.c \
+ vmwgfx_drmi.h \
+ vmwgfx_overlay.c \
+ vmwgfx_ctrl.c \
+ vmwgfx_ctrl.h \
+ vmwgfx_xa_composite.c \
+ vmwgfx_xa_surface.c \
+ wsbm_util.h
+
+
+
diff --git a/vmwgfx/svga3d_reg.h b/vmwgfx/svga3d_reg.h
new file mode 100644
index 0000000..a527d7d
--- /dev/null
+++ b/vmwgfx/svga3d_reg.h
@@ -0,0 +1,1801 @@
+/**********************************************************
+ * 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_ */
diff --git a/vmwgfx/vmwgfx_crtc.c b/vmwgfx/vmwgfx_crtc.c
new file mode 100644
index 0000000..eaf87b2
--- /dev/null
+++ b/vmwgfx/vmwgfx_crtc.c
@@ -0,0 +1,455 @@
+/*
+ * 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>
+ */
+
+#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
+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);
+
+ 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);
+ if (crtcp->scanout_id == -1) {
+ 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
+
+ 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 = 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;
+
+ 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)
+ 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);
+ }
+
+ 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: */
diff --git a/vmwgfx/vmwgfx_ctrl.c b/vmwgfx/vmwgfx_ctrl.c
new file mode 100644
index 0000000..3185879
--- /dev/null
+++ b/vmwgfx/vmwgfx_ctrl.c
@@ -0,0 +1,523 @@
+/*
+ * 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.
+ */
+
+#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;
+
+ 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;
+ }
+
+ 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);
+ }
+}
diff --git a/vmwgfx/vmwgfx_ctrl.h b/vmwgfx/vmwgfx_ctrl.h
new file mode 100644
index 0000000..8fedbce
--- /dev/null
+++ b/vmwgfx/vmwgfx_ctrl.h
@@ -0,0 +1,48 @@
+/*
+ * Copyright 2006 by VMware, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Except as contained in this notice, the name of the copyright holder(s)
+ * and author(s) shall not be used in advertising or otherwise to promote
+ * the sale, use or other dealings in this Software without prior written
+ * authorization from the copyright holder(s) and author(s).
+ */
+
+/*
+ * 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_ */
diff --git a/vmwgfx/vmwgfx_dri2.c b/vmwgfx/vmwgfx_dri2.c
new file mode 100644
index 0000000..1b82ac4
--- /dev/null
+++ b/vmwgfx/vmwgfx_dri2.c
@@ -0,0 +1,426 @@
+/*
+ * 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>
+ *
+ */
+
+#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>
+
+#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 = xf86Screens[pScreen->myNum];
+ 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:
+
+ 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:
+ 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;
+
+ /*
+ * 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);
+}
+
+Bool
+xorg_dri2_init(ScreenPtr pScreen)
+{
+ ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
+ modesettingPtr ms = modesettingPTR(pScrn);
+ DRI2InfoRec dri2info;
+ int major, minor;
+ char fdPath[VMWGFX_FD_PATH_LEN];
+ ssize_t numChar;
+
+ 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";
+
+ /*
+ * This way of obtaining the DRM device name is a bit
+ * os-specific. It would be better to obtain it from
+ * drmOpen. Currently this works only for Linux.
+ */
+ 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;
+ 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;
+
+ return DRI2ScreenInit(pScreen, &dri2info);
+}
+
+void
+xorg_dri2_close(ScreenPtr pScreen)
+{
+ DRI2CloseScreen(pScreen);
+}
+
+/* vim: set sw=4 ts=8 sts=4: */
diff --git a/vmwgfx/vmwgfx_driver.c b/vmwgfx/vmwgfx_driver.c
new file mode 100644
index 0000000..dcb6c83
--- /dev/null
+++ b/vmwgfx/vmwgfx_driver.c
@@ -0,0 +1,1200 @@
+/*
+ * 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>
+ */
+
+
+#include <unistd.h>
+#include "xorg-server.h"
+#include "xf86.h"
+#include "xf86_OSproc.h"
+#include "compiler.h"
+#include "xf86PciInfo.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>
+
+#include "vmwgfx_driver.h"
+
+#include <saa.h>
+#include "vmwgfx_saa.h"
+#include "../src/vmware_bootstrap.h"
+#include "../src/vmware_common.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 6
+#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(int scrnIndex, ScreenPtr pScreen, int argc,
+ char **argv);
+static Bool drv_switch_mode(int scrnIndex, DisplayModePtr mode, int flags);
+static void drv_adjust_frame(int scrnIndex, int x, int y, int flags);
+static Bool drv_enter_vt(int scrnIndex, int flags);
+static void drv_leave_vt(int scrnIndex, int flags);
+static void drv_free_screen(int scrnIndex, int flags);
+static ModeStatus drv_valid_mode(int scrnIndex, 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;
+}
+
+/*
+ * Internal function definitions
+ */
+
+static Bool drv_close_screen(int scrnIndex, ScreenPtr pScreen);
+
+/*
+ * 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
+drv_init_drm(ScrnInfoPtr pScrn)
+{
+ modesettingPtr ms = modesettingPTR(pScrn);
+
+ /* deal with server regeneration */
+ if (ms->fd < 0) {
+ char *BusID;
+
+ BusID = malloc(64);
+ sprintf(BusID, "PCI:%d:%d:%d",
+ ((ms->PciInfo->domain << 8) | ms->PciInfo->bus),
+ ms->PciInfo->dev, ms->PciInfo->func
+ );
+
+
+ ms->fd = drmOpen("vmwgfx", BusID);
+ ms->isMaster = TRUE;
+ free(BusID);
+
+ 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
+drv_pre_init(ScrnInfoPtr pScrn, int flags)
+{
+ xf86CrtcConfigPtr xf86_config;
+ modesettingPtr ms;
+ rgb defaultWeight = { 0, 0, 0 };
+ EntityInfoPtr pEnt;
+ uint64_t cap;
+ Bool ret = TRUE;
+
+ 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 */
+
+ if (ms->pEnt->location.type != BUS_PCI) {
+ xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+ "Incorrect bus for device.\n");
+ goto out_err_bus;
+ }
+
+ ms->PciInfo = xf86GetPciInfoForEntity(ms->pEnt->index);
+ xf86SetPrimInitDone(pScrn->entityList[0]);
+
+ ms->fd = -1;
+ if (!drv_init_drm(pScrn))
+ goto out_err_bus;
+
+ 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->check_fb_size = (vmwgfx_max_fb_size(ms->fd, &ms->max_fb_size) == 0);
+
+ 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_depth;
+ }
+
+ if (vmwgfx_get_param(ms->fd, DRM_VMW_PARAM_HW_CAPS, &cap) != 0) {
+ xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Failed to detect device "
+ "screen object capability.\n");
+ goto out_depth;
+ }
+
+ if ((cap & SVGA_CAP_SCREEN_OBJECT_2) == 0) {
+ xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Device is not screen object "
+ "capable.\n");
+ goto out_depth;
+ }
+
+ 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->from_dp = xf86GetOptValBool(ms->Options, OPTION_DIRECT_PRESENTS,
+ &ms->direct_presents) ?
+ X_CONFIG : X_DEFAULT;
+
+ ms->only_hw_presents = FALSE;
+ 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);
+ xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
+
+ /* 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);
+ }
+
+
+ if (!xf86ReturnOptValBool(ms->Options, OPTION_HW_CURSOR, TRUE)) {
+ ms->SWCursor = TRUE;
+ }
+
+ if (xf86IsOptionSet(ms->Options, OPTION_GUI_LAYOUT)) {
+ char *topology =
+ xf86GetOptValString(ms->Options, OPTION_GUI_LAYOUT);
+
+ ret = FALSE;
+ if (topology) {
+ ret = vmwgfx_set_topology(pScrn, topology, "gui");
+ free(topology);
+ }
+
+ } else if (xf86IsOptionSet(ms->Options, OPTION_STATIC_XINERAMA)) {
+ char *topology =
+ xf86GetOptValString(ms->Options, OPTION_STATIC_XINERAMA);
+
+ ret = FALSE;
+ if (topology) {
+ ret = vmwgfx_set_topology(pScrn, topology, "static Xinerama");
+ free(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 the driver can do gamma correction, it should call xf86SetGamma() here.
+ */
+ {
+ Gamma zeros = { 0.0, 0.0, 0.0 };
+
+ if (!xf86SetGamma(pScrn, zeros)) {
+ xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Failed to set gamma.\n");
+ goto out_modes;
+ }
+ }
+
+ if (pScrn->modes == NULL) {
+ xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "No available modes.\n");
+ goto out_modes;
+ }
+
+ pScrn->currentMode = pScrn->modes;
+
+ /* Set display resolution */
+ xf86SetDpi(pScrn, 0, 0);
+
+ /* 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;
+ }
+
+ return TRUE;
+
+ out_modes:
+ free(ms->Options);
+ out_depth:
+ out_drm_version:
+ close(ms->fd);
+ out_err_bus:
+ drv_free_rec(pScrn);
+ return FALSE;
+
+}
+
+static Bool
+vmwgfx_scanout_update(int drm_fd, int fb_id, RegionPtr dirty)
+{
+ unsigned num_cliprects = REGION_NUM_RECTS(dirty);
+ drmModeClip *clip = alloca(num_cliprects * sizeof(drmModeClip));
+ BoxPtr rect = REGION_RECTS(dirty);
+ int i, ret;
+
+ if (!num_cliprects)
+ return TRUE;
+
+ for (i = 0; i < num_cliprects; i++, rect++) {
+ clip[i].x1 = rect->x1;
+ clip[i].y1 = rect->y1;
+ clip[i].x2 = rect->x2;
+ clip[i].y2 = rect->y2;
+ }
+
+ ret = drmModeDirtyFB(drm_fd, fb_id, clip, num_cliprects);
+ if (ret)
+ LogMessage(X_ERROR, "%s: failed to send dirty (%i, %s)\n",
+ __func__, ret, strerror(-ret));
+ return (ret == 0);
+}
+
+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 = xf86Screens[pScreen->myNum];
+ 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) {
+ unsigned int j;
+
+ /*
+ * 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 (ms->only_hw_presents &&
+ 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 (ms->only_hw_presents)
+ (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(int i, pointer blockData, pointer pTimeout,
+ pointer pReadmask)
+{
+ ScreenPtr pScreen = screenInfo.screens[i];
+ modesettingPtr ms = modesettingPTR(xf86Screens[pScreen->myNum]);
+
+ vmwgfx_swap(ms, pScreen, BlockHandler);
+ pScreen->BlockHandler(i, blockData, pTimeout, pReadmask);
+ vmwgfx_swap(ms, pScreen, BlockHandler);
+
+ vmwgfx_flush_dri2(pScreen);
+ xorg_flush(pScreen);
+}
+
+static Bool
+drv_create_screen_resources(ScreenPtr pScreen)
+{
+ ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
+ modesettingPtr ms = modesettingPTR(pScrn);
+ Bool ret;
+
+ vmwgfx_swap(ms, pScreen, CreateScreenResources);
+ ret = pScreen->CreateScreenResources(pScreen);
+ vmwgfx_swap(ms, pScreen, CreateScreenResources);
+
+ drv_adjust_frame(pScrn->scrnIndex, pScrn->frameX0, pScrn->frameY0, 0);
+
+ return drv_enter_vt(pScreen->myNum, 1);
+}
+
+static Bool
+drv_set_master(ScrnInfoPtr pScrn)
+{
+ modesettingPtr ms = modesettingPTR(pScrn);
+
+ if (!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 = xf86Screens[screen->myNum];
+ 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 = xf86Screens[screen->myNum];
+ 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(int scrnIndex, ScreenPtr pScreen, int argc, char **argv)
+{
+ ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
+ 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);
+
+ vmw_ctrl_ext_init(pScrn);
+
+ if (ms->accelerate_render) {
+ ms->xat = xa_tracker_create(ms->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 (XA_TRACKER_VERSION_MAJOR == 0) {
+ if (minor != XA_TRACKER_VERSION_MINOR) {
+ xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
+ "Expecting XA version 0.%d.x.\n",
+ XA_TRACKER_VERSION_MINOR);
+ xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
+ "No render acceleration available.\n");
+ xa_tracker_destroy(ms->xat);
+ ms->xat = NULL;
+ ms->from_render = X_PROBED;
+ }
+ }
+ if (major != XA_TRACKER_VERSION_MAJOR ||
+ minor < XA_VERSION_MINOR_REQUIRED) {
+ xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
+ "Expecting %d.%d.x >= XA version < %d.0.0.\n",
+ XA_TRACKER_VERSION_MAJOR,
+ XA_VERSION_MINOR_REQUIRED,
+ XA_TRACKER_VERSION_MAJOR + 1);
+ xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
+ "No render acceleration available.\n");
+ xa_tracker_destroy(ms->xat);
+ ms->xat = NULL;
+ ms->from_render = X_PROBED;
+ }
+ }
+ 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_saa_init(pScreen, ms->fd, ms->xat, &xorg_flush,
+ ms->direct_presents,
+ ms->only_hw_presents,
+ ms->rendercheck)) {
+ FatalError("Failed to initialize SAA.\n");
+ }
+
+ ms->dri2_available = FALSE;
+ 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.\n");
+ } 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 (3D) is %s.\n",
+ (ms->dri2_available) ? "enabled" : "disabled");
+ if (ms->xat != NULL) {
+ xf86DrvMsg(pScrn->scrnIndex, ms->from_dp, "Direct presents are %s.\n",
+ (ms->direct_presents) ? "enabled" : "disabled");
+ xf86DrvMsg(pScrn->scrnIndex, ms->from_hwp, "Hardware only presents "
+ "are %s.\n",
+ (ms->only_hw_presents) ? "enabled" : "disabled");
+ }
+
+ miInitializeBackingStore(pScreen);
+ xf86SetBackingStore(pScreen);
+ xf86SetSilkenMouse(pScreen);
+ miDCInitialize(pScreen, xf86GetPointerScreenFuncs());
+
+ /* 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(int scrnIndex, int x, int y, int flags)
+{
+ ScrnInfoPtr pScrn = xf86Screens[scrnIndex];
+ xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(pScrn);
+ xf86OutputPtr output = config->output[config->compat_output];
+ xf86CrtcPtr 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(int scrnIndex, int flags)
+{
+ drv_free_rec(xf86Screens[scrnIndex]);
+}
+
+static void
+drv_leave_vt(int scrnIndex, int flags)
+{
+ ScrnInfoPtr pScrn = xf86Screens[scrnIndex];
+ modesettingPtr ms = modesettingPTR(pScrn);
+
+ vmwgfx_cursor_bypass(ms->fd, 0, 0);
+ vmwgfx_disable_scanout(pScrn);
+
+ if (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(int scrnIndex, int flags)
+{
+ ScrnInfoPtr pScrn = xf86Screens[scrnIndex];
+
+ if (!drv_set_master(pScrn))
+ return FALSE;
+
+ if (!xf86SetDesiredModes(pScrn))
+ return FALSE;
+
+ return TRUE;
+}
+
+static Bool
+drv_switch_mode(int scrnIndex, DisplayModePtr mode, int flags)
+{
+ ScrnInfoPtr pScrn = xf86Screens[scrnIndex];
+
+ return xf86SetSingleMode(pScrn, mode, RR_Rotate_0);
+}
+
+static Bool
+drv_close_screen(int scrnIndex, ScreenPtr pScreen)
+{
+ ScrnInfoPtr pScrn = xf86Screens[scrnIndex];
+ modesettingPtr ms = modesettingPTR(pScrn);
+
+ if (ms->cursor) {
+ FreeCursor(ms->cursor, None);
+ ms->cursor = NULL;
+ }
+
+ if (ms->dri2_available)
+ xorg_dri2_close(pScreen);
+
+ if (pScrn->vtSema)
+ pScrn->LeaveVT(scrnIndex, 0);
+
+ pScrn->vtSema = FALSE;
+
+ vmwgfx_unwrap(ms, pScrn, EnterVT);
+ vmwgfx_unwrap(ms, pScrn, LeaveVT);
+ vmwgfx_unwrap(ms, pScrn, AdjustFrame);
+ vmwgfx_unwrap(ms, pScreen, CloseScreen);
+ vmwgfx_unwrap(ms, pScreen, BlockHandler);
+ vmwgfx_unwrap(ms, pScreen, CreateScreenResources);
+
+ if (ms->xat)
+ xa_tracker_destroy(ms->xat);
+
+ return (*pScreen->CloseScreen) (scrnIndex, pScreen);
+}
+
+static ModeStatus
+drv_valid_mode(int scrnIndex, DisplayModePtr mode, Bool verbose, int flags)
+{
+ return MODE_OK;
+}
+
+/* vim: set sw=4 ts=8 sts=4: */
diff --git a/vmwgfx/vmwgfx_driver.h b/vmwgfx/vmwgfx_driver.h
new file mode 100644
index 0000000..3290f0e
--- /dev/null
+++ b/vmwgfx/vmwgfx_driver.h
@@ -0,0 +1,186 @@
+/*
+ * 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 <drm.h>
+#include <xf86drm.h>
+#include <xf86drmMode.h>
+#include <xorg-server.h>
+#include <xf86.h>
+#include <xf86Crtc.h>
+#include <xf86xv.h>
+#include <xa_tracker.h>
+
+#ifdef DRI2
+#include <dri2.h>
+#if (!defined(DRI2INFOREC_VERSION) || (DRI2INFOREC_VERSION < 3))
+#undef DRI2
+#endif
+#endif
+
+#define DRV_ERROR(msg) xf86DrvMsg(pScrn->scrnIndex, X_ERROR, msg);
+#define debug_printf(...)
+
+#define VMWGFX_DRI_DEVICE_LEN 80
+
+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
+};
+
+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;
+
+ /* 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;
+
+
+ /* Broken-out options. */
+ OptionInfoPtr Options;
+
+ ScreenBlockHandlerProcPtr saved_BlockHandler;
+ CreateScreenResourcesProcPtr saved_CreateScreenResources;
+ CloseScreenProcPtr saved_CloseScreen;
+ Bool (*saved_EnterVT)(int, int);
+ void (*saved_LeaveVT)(int, int);
+ void (*saved_AdjustFrame)(int, int, int, int);
+ 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;
+#ifdef DRI2
+ Bool dri2_available;
+ char dri2_device_name[VMWGFX_DRI_DEVICE_LEN];
+#endif
+} 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);
+
+
+/***********************************************************************
+ * xorg_xv.c
+ */
+void
+xorg_xv_init(ScreenPtr pScreen);
+
+XF86VideoAdaptorPtr
+vmw_video_init_adaptor(ScrnInfoPtr pScrn);
+void
+vmw_video_free_adaptor(XF86VideoAdaptorPtr adaptor, Bool free_ports);
+
+void
+vmw_ctrl_ext_init(ScrnInfoPtr pScrn);
+
+#endif /* _XORG_TRACKER_H_ */
diff --git a/vmwgfx/vmwgfx_drm.h b/vmwgfx/vmwgfx_drm.h
new file mode 100644
index 0000000..906a41c
--- /dev/null
+++ b/vmwgfx/vmwgfx_drm.h
@@ -0,0 +1,792 @@
+/**************************************************************************
+ *
+ * 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
+
+/**
+ * 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
diff --git a/vmwgfx/vmwgfx_drmi.c b/vmwgfx/vmwgfx_drmi.c
new file mode 100644
index 0000000..e326d31
--- /dev/null
+++ b/vmwgfx/vmwgfx_drmi.c
@@ -0,0 +1,502 @@
+/*
+ * Copyright 2011 VMWare, Inc.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Author: 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"
+
+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);
+ struct drm_vmw_fence_rep rep;
+ struct drm_vmw_present_readback_arg arg;
+ int ret;
+ unsigned i;
+ struct drm_vmw_rect *rects, *r;
+
+ rects = calloc(num_clips, sizeof(*rects));
+ if (!rects) {
+ LogMessage(X_ERROR, "Failed to alloc cliprects for "
+ "present readback.\n");
+ return -1;
+ }
+
+ memset(&arg, 0, sizeof(arg));
+ memset(&rep, 0, sizeof(rep));
+
+ arg.fb_id = fb_id;
+ arg.num_clips = num_clips;
+ arg.clips_ptr = (unsigned long) rects;
+ arg.fence_rep = (unsigned long) &rep;
+ rep.error = -EFAULT;
+
+ for (i = 0, r = rects; i < num_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));
+ free(rects);
+
+ /*
+ * Sync 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_unref(drm_fd, rep.handle);
+ }
+ }
+
+ 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);
+ struct drm_vmw_present_arg arg;
+ unsigned int i;
+ struct drm_vmw_rect *rects, *r;
+ int ret;
+
+ if (num_clips == 0)
+ return 0;
+
+ rects = calloc(num_clips, sizeof(*rects));
+ if (!rects) {
+ LogMessage(X_ERROR, "Failed to alloc cliprects for "
+ "present.\n");
+ return -1;
+ }
+
+ memset(&arg, 0, sizeof(arg));
+ arg.fb_id = fb_id;
+ arg.sid = handle;
+ arg.dest_x = dst_x;
+ arg.dest_y = dst_y;
+ arg.num_clips = num_clips;
+ arg.clips_ptr = (unsigned long) rects;
+
+ for (i = 0, r = rects; i < num_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));
+ }
+
+ free(rects);
+ return ((ret != 0) ? -1 : 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(unsigned int host_x, unsigned 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 int size;
+ 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;
+
+ if (num_clips == 0)
+ return 0;
+
+ size = sizeof(*cmd) + (num_clips - 1) * sizeof(cmd->cb) +
+ sizeof(*suffix);
+ cmd = malloc(size);
+ if (!cmd)
+ return -1;
+
+ cmd->header.id = SVGA_3D_CMD_SURFACE_DMA;
+ cmd->header.size = sizeof(cmd->body) + num_clips * sizeof(cmd->cb) +
+ sizeof(*suffix);
+ cb = &cmd->cb;
+
+ suffix = (SVGA3dCmdSurfaceDMASuffix *) &cb[num_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 < num_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;
+ arg.fence_rep = ((to_surface) ? 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);
+
+ 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_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 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;
+}
diff --git a/vmwgfx/vmwgfx_drmi.h b/vmwgfx/vmwgfx_drmi.h
new file mode 100644
index 0000000..2435009
--- /dev/null
+++ b/vmwgfx/vmwgfx_drmi.h
@@ -0,0 +1,87 @@
+/*
+ * 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(unsigned int host_x, unsigned 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);
+#endif
diff --git a/vmwgfx/vmwgfx_output.c b/vmwgfx/vmwgfx_output.c
new file mode 100644
index 0000000..4f52f1d
--- /dev/null
+++ b/vmwgfx/vmwgfx_output.c
@@ -0,0 +1,393 @@
+/*
+ * 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>
+ *
+ */
+
+#include "xorg-server.h"
+#include <xf86.h>
+#include <xf86i2c.h>
+#include <xf86Crtc.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <string.h>
+#include <sys/stat.h>
+#include <sys/types.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_private
+{
+ drmModeConnectorPtr drm_connector;
+
+ int c;
+
+ Bool is_implicit;
+};
+
+static char *output_enum_list[] = {
+ "Unknown",
+ "VGA",
+ "DVI",
+ "DVI",
+ "DVI",
+ "Composite",
+ "SVIDEO",
+ "LVDS",
+ "CTV",
+ "DIN",
+ "DP",
+ "HDMI",
+ "HDMI",
+ "TV",
+ "EDP",
+ "Virtual",
+};
+
+static void
+output_create_resources(xf86OutputPtr output)
+{
+#ifdef RANDR_12_INTERFACE
+#endif /* RANDR_12_INTERFACE */
+}
+
+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);
+ xf86PrintModeline(0, 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)
+{
+ return TRUE;
+}
+#endif /* RANDR_12_INTERFACE */
+
+#ifdef RANDR_13_INTERFACE
+static Bool
+output_get_property(xf86OutputPtr output, Atom property)
+{
+ return TRUE;
+}
+#endif /* RANDR_13_INTERFACE */
+
+static void
+output_destroy(xf86OutputPtr output)
+{
+ struct output_private *priv = output->driver_private;
+ 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;
+ struct output_private *priv;
+ 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];
+ priv = output->driver_private;
+ crtc = output->crtc;
+
+ if (!crtc || !crtc->enabled || !priv->is_implicit)
+ 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];
+ priv = output->driver_private;
+ crtc = output->crtc;
+
+ if (!crtc || !crtc->enabled || priv->is_implicit)
+ 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, p;
+
+ res = drmModeGetResources(ms->fd);
+ if (res == 0) {
+ DRV_ERROR("Failed drmModeGetResources\n");
+ return;
+ }
+
+ for (c = 0; c < res->count_connectors; c++) {
+ Bool is_implicit = TRUE;
+
+ drm_connector = drmModeGetConnector(ms->fd, res->connectors[c]);
+ if (!drm_connector)
+ goto out;
+
+
+ for (p = 0; p < drm_connector->count_props; p++) {
+ drmModePropertyPtr prop;
+
+ prop = drmModeGetProperty(ms->fd, drm_connector->props[p]);
+
+ if (prop) {
+
+#if 0
+ /*
+ * Disabled until we sort out what the interface should
+ * look like.
+ */
+
+ if (strcmp(prop->name, "implicit placement") == 0) {
+ drmModeConnectorSetProperty(ms->fd,
+ drm_connector->connector_id,
+ prop->prop_id,
+ 0);
+ is_implicit = FALSE;
+ }
+#endif
+ drmModeFreeProperty(prop);
+ }
+ }
+
+ 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->is_implicit = is_implicit;
+
+ 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;
+ } 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;
+}
+
+/* vim: set sw=4 ts=8 sts=4: */
diff --git a/vmwgfx/vmwgfx_overlay.c b/vmwgfx/vmwgfx_overlay.c
new file mode 100644
index 0000000..6624a10
--- /dev/null
+++ b/vmwgfx/vmwgfx_overlay.c
@@ -0,0 +1,893 @@
+/*
+ * 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
+ *
+ */
+
+
+#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 <X11/extensions/Xv.h>
+
+#include "xf86drm.h"
+#include "vmwgfx_drm.h"
+#include "vmwgfx_drmi.h"
+#include "vmwgfx_driver.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
+};
+
+#define VMWARE_VID_NUM_ATTRIBUTES 2
+static XF86AttributeRec vmwareVideoAttributes[] =
+{
+ {
+ XvGettable | XvSettable,
+ 0x000000,
+ 0xffffff,
+ "XV_COLORKEY"
+ },
+ {
+ XvGettable | XvSettable,
+ 0,
+ 1,
+ "XV_AUTOPAINT_COLORKEY"
+ }
+};
+
+/*
+ * Video frames are stored in a circular list of buffers.
+ * 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);
+
+ /* 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);
+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);
+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, Bool free_ports)
+{
+ if (free_ports) {
+ 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_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)
+{
+ 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);
+
+ 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)
+{
+ 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);
+ }
+
+ 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)
+ 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);
+}
+
+
+/*
+ *-----------------------------------------------------------------------------
+ *
+ * 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;
+}
diff --git a/vmwgfx/vmwgfx_saa.c b/vmwgfx/vmwgfx_saa.c
new file mode 100644
index 0000000..0a6b98f
--- /dev/null
+++ b/vmwgfx/vmwgfx_saa.c
@@ -0,0 +1,1514 @@
+/*
+ * 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 <mi.h>
+#include <fb.h>
+#include <xf86drmMode.h>
+#include <xa_context.h>
+#include "vmwgfx_saa.h"
+#include "vmwgfx_drmi.h"
+#include "vmwgfx_saa_priv.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;
+
+ DamageUnregister(&pixmap->drawable, spix->damage);
+ 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)
+{
+ struct vmwgfx_saa_pixmap *vpix = vmwgfx_saa_pixmap(pixmap);
+
+ if (!vpix->hw || (!vpix->gmr && !vpix->malloc))
+ return TRUE;
+
+ if (vpix->gmr && vsaa->can_optimize_dma) {
+ uint32_t handle, dummy;
+
+ if (xa_surface_handle(vpix->hw, &handle, &dummy) != 0)
+ goto out_err;
+ if (vmwgfx_dma(0, 0, reg, vpix->gmr, pixmap->devKind, handle,
+ to_hw) != 0)
+ goto out_err;
+ } else {
+ void *data = vpix->malloc;
+ int ret;
+
+ if (vpix->gmr) {
+ data = vmwgfx_dmabuf_map(vpix->gmr);
+ if (!data)
+ goto out_err;
+ }
+
+ ret = xa_surface_dma(vsaa->xa_ctx, vpix->hw, data, pixmap->devKind,
+ (int) to_hw,
+ (struct xa_box *) REGION_RECTS(reg),
+ REGION_NUM_RECTS(reg));
+ if (vpix->gmr)
+ vmwgfx_dmabuf_unmap(vpix->gmr);
+ 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))
+ 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);
+}
+
+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);
+
+ 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 = xf86Screens[pScreen->myNum];
+
+ 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->sync_x_head);
+
+ if (vpix->hw_is_dri2_fronts)
+ LogMessage(X_ERROR, "Incorrect dri2 front count.\n");
+}
+
+
+
+/**
+ *
+ * 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 (xa_surface_redefine(vpix->hw, draw->width, draw->height,
+ draw->depth, xa_type_argb,
+ xa_format_unknown, vpix->xa_flags, 1) != 0)
+ 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);
+ 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);
+ 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);
+}
+
+
+Bool
+vmwgfx_create_hw(struct vmwgfx_saa *vsaa,
+ PixmapPtr pixmap)
+{
+ struct vmwgfx_saa_pixmap *vpix = vmwgfx_saa_pixmap(pixmap);
+ struct xa_surface *hw;
+ uint32_t new_flags;
+
+ if (!vsaa->xat)
+ return FALSE;
+
+ if (vpix->hw)
+ return TRUE;
+
+ new_flags = (vpix->xa_flags & ~vpix->staging_remove_flags) |
+ vpix->staging_add_flags;
+
+ hw = xa_surface_create(vsaa->xat,
+ pixmap->drawable.width,
+ pixmap->drawable.height,
+ 0,
+ xa_type_other,
+ vpix->staging_format,
+ new_flags);
+ if (hw == NULL)
+ return FALSE;
+
+ vpix->xa_flags = new_flags;
+
+ if (!vmwgfx_pixmap_add_damage(pixmap))
+ goto out_no_damage;
+
+ /*
+ * Even if we don't have a GMR yet, indicate that when needed it
+ * should be created.
+ */
+
+ vpix->hw = hw;
+ vpix->backing |= VMWGFX_PIX_SURFACE;
+ vmwgfx_pixmap_free_storage(vpix);
+
+ return TRUE;
+
+out_no_damage:
+ 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)
+ 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);
+ 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);
+}
+
+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;
+
+ 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.
+ */
+
+ 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;
+
+ REGION_UNINIT(pScreen, &empty);
+ return TRUE;
+
+ out_err:
+ REGION_UNINIT(pScreen, &empty);
+ 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);
+}
+
+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 = xf86Screens[vsaa->pScreen->myNum];
+
+ /*
+ * 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.
+ */
+
+ if (vpix->hw && vpix->hw_is_dri2_fronts) {
+ if (1 && pScrn->vtSema &&
+ 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 (vsaa->only_hw_presents) {
+ 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)
+{
+ struct vmwgfx_saa *vsaa;
+
+ vsaa = calloc(1, sizeof(*vsaa));
+ if (!vsaa)
+ return FALSE;
+
+ if (xat == NULL) {
+ direct_presents = FALSE;
+ only_hw_presents = 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 = FALSE;
+ vsaa->use_present_opt = direct_presents;
+ vsaa->only_hw_presents = only_hw_presents;
+ vsaa->rendercheck = rendercheck;
+ WSBMINITLISTHEAD(&vsaa->sync_x_list);
+
+ 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)
+{
+ 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;
+
+ if (vsaa->only_hw_presents) {
+ /*
+ * 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, 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);
+}
diff --git a/vmwgfx/vmwgfx_saa.h b/vmwgfx/vmwgfx_saa.h
new file mode 100644
index 0000000..bb8ec96
--- /dev/null
+++ b/vmwgfx/vmwgfx_saa.h
@@ -0,0 +1,110 @@
+/*
+ * 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;
+ struct _WsbmListHead sync_x_head;
+ struct _WsbmListHead scanout_list;
+
+ 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);
+
+extern uint32_t
+vmwgfx_scanout_ref(struct vmwgfx_screen_entry *box);
+
+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);
+#endif
diff --git a/vmwgfx/vmwgfx_saa_priv.h b/vmwgfx/vmwgfx_saa_priv.h
new file mode 100644
index 0000000..5f46dee
--- /dev/null
+++ b/vmwgfx/vmwgfx_saa_priv.h
@@ -0,0 +1,125 @@
+/*
+ * 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;
+ void (*present_flush) (ScreenPtr pScreen);
+ struct _WsbmListHead sync_x_list;
+ 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);
+
+
+/*
+ * vmwgfx_xa_surface.c
+ */
+
+enum xa_formats
+vmwgfx_xa_format(enum _PictFormatShort format);
+Bool
+vmwgfx_hw_validate(PixmapPtr pixmap, RegionPtr region);
+
+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);
+
+/*
+ * 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
diff --git a/vmwgfx/vmwgfx_tex_video.c b/vmwgfx/vmwgfx_tex_video.c
new file mode 100644
index 0000000..cc94c20
--- /dev/null
+++ b/vmwgfx/vmwgfx_tex_video.c
@@ -0,0 +1,855 @@
+/*
+ * 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>
+ */
+
+#include "vmwgfx_driver.h"
+#include "vmwgfx_drmi.h"
+#include "vmwgfx_saa.h"
+
+#include <xf86xv.h>
+#include <X11/extensions/Xv.h>
+#include <fourcc.h>
+#include <xa_tracker.h>
+#include <xa_context.h>
+#include <math.h>
+
+/*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;
+
+#define NUM_TEXTURED_ATTRIBUTES 4
+static XF86AttributeRec TexturedAttributes[NUM_TEXTURED_ATTRIBUTES] = {
+ {XvSettable | XvGettable, -1000, 1000, "XV_BRIGHTNESS"},
+ {XvSettable | XvGettable, -1000, 1000, "XV_CONTRAST"},
+ {XvSettable | XvGettable, -1000, 1000, "XV_SATURATION"},
+ {XvSettable | XvGettable, -1000, 1000, "XV_HUE"}
+};
+
+#define NUM_FORMATS 3
+static XF86VideoFormatRec Formats[NUM_FORMATS] = {
+ {15, TrueColor}, {16, TrueColor}, {24, TrueColor}
+};
+
+static XF86VideoEncodingRec DummyEncoding[1] = {
+ {
+ 0,
+ "XV_IMAGE",
+ 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 vmwgfx_dmabuf *bounce[2][3];
+ struct xa_surface *yuv[3];
+
+ 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;
+}
+
+
+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;
+
+ for (i=0; i<3; ++i) {
+ if (priv->yuv[i]) {
+ xa_surface_destroy(priv->yuv[i]);
+ priv->yuv[i] = NULL;
+ }
+ for (j=0; j<2; ++j) {
+ if (priv->bounce[j][i]) {
+ vmwgfx_dmabuf_destroy(priv->bounce[j][i]);
+ priv->bounce[0][i] = 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;
+ struct vmwgfx_dmabuf **bounce = priv->bounce[priv->current_set];
+ int ret = 0;
+ int i;
+ size_t size;
+
+ 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;
+
+ size = width * height;
+
+ if (bounce[i] && (bounce[i]->size < size ||
+ bounce[i]->size > 2*size)) {
+ vmwgfx_dmabuf_destroy(bounce[i]);
+ bounce[i] = NULL;
+ }
+
+ if (!bounce[i]) {
+ bounce[i] = vmwgfx_dmabuf_alloc(priv->drm_fd, size);
+ if (!bounce[i])
+ return BadAlloc;
+ }
+ }
+ return Success;
+}
+
+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 vmwgfx_dmabuf **bounce = port->bounce[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;
+
+ /*
+ * Here, we could use xa_surface_[map|unmap], but given the size of
+ * the yuv textures, that could stress the xa tracker dma buffer pool,
+ * particularaly with multiple videos rendering simultaneously.
+ *
+ * Instead, cheat and allocate vmwgfx dma buffers directly.
+ */
+
+ ymap = (char *)vmwgfx_dmabuf_map(bounce[0]);
+ if (!ymap)
+ return BadAlloc;
+ umap = (char *)vmwgfx_dmabuf_map(bounce[1]);
+ if (!umap)
+ goto out_no_umap;
+ vmap = (char *)vmwgfx_dmabuf_map(bounce[2]);
+ if (!vmap)
+ goto out_no_vmap;
+
+
+ yidx = uidx = vidx = 0;
+
+ switch (id) {
+ case FOURCC_YV12: {
+ int pitches[3], offsets[3];
+ unsigned char *y, *u, *v;
+ query_image_attributes(pScrn, FOURCC_YV12,
+ &w, &h, pitches, offsets);
+
+ y = buf + offsets[0];
+ v = buf + offsets[1];
+ u = buf + offsets[2];
+ memcpy(ymap, y, w*h);
+ memcpy(vmap, v, w*h/4);
+ memcpy(umap, u, 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;
+ vmwgfx_dmabuf_unmap(bounce[2]);
+ out_no_vmap:
+ vmwgfx_dmabuf_unmap(bounce[1]);
+ out_no_umap:
+ vmwgfx_dmabuf_unmap(bounce[0]);
+
+ if (ret == Success) {
+ struct xa_surface *srf;
+ struct vmwgfx_dmabuf *buf;
+ uint32_t handle;
+ unsigned int stride;
+ BoxRec box;
+ RegionRec reg;
+
+ box.x1 = 0;
+ box.x2 = w;
+ box.y1 = 0;
+ box.y2 = h;
+
+ REGION_INIT(pScrn->pScreen, &reg, &box, 1);
+
+ for (i=0; i<3; ++i) {
+ srf = port->yuv[i];
+ buf = bounce[i];
+
+ if (i == 1) {
+ switch(id) {
+ case FOURCC_YV12:
+ h /= 2;
+ /* Fall through */
+ case FOURCC_YUY2:
+ case FOURCC_UYVY:
+ w /= 2;
+ break;
+ default:
+ break;
+ }
+
+ box.x1 = 0;
+ box.x2 = w;
+ box.y1 = 0;
+ box.y2 = h;
+
+ REGION_RESET(pScrn->pScreen, &reg, &box);
+ }
+
+ if (xa_surface_handle(srf, &handle, &stride) != 0) {
+ ret = BadAlloc;
+ break;
+ }
+
+ if (vmwgfx_dma(0, 0, &reg, buf, w, handle, 1) != 0) {
+ ret = BadAlloc;
+ break;
+ }
+ }
+ REGION_UNINIT(pScrn->pScreen, &reg);
+ }
+
+ 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,
+ 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;
+ }
+
+ DamageRegionAppend(&pPixmap->drawable, dstRegion);
+
+ 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);
+
+ 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 = screenInfo.screens[pScrn->scrnIndex];
+ 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, 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, Bool free_ports)
+{
+ if (free_ports) {
+ 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 = xf86Screens[pScreen->myNum];
+ 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 = "XA G3D Textured Video";
+ 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
+xorg_xv_init(ScreenPtr pScreen)
+{
+ ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
+ 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) {
+ Bool ret;
+ ret = xf86XVScreenInit(pScreen, adaptors, num_adaptors);
+ if (textured_adapter)
+ vmwgfx_free_textured_adaptor(textured_adapter, !ret);
+ if (overlay_adaptor)
+ vmw_video_free_adaptor(overlay_adaptor, !ret);
+ if (!ret)
+ 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");
+ }
+
+
+ out_err_mem:
+ free(adaptors);
+}
diff --git a/vmwgfx/vmwgfx_xa_composite.c b/vmwgfx/vmwgfx_xa_composite.c
new file mode 100644
index 0000000..a2e3970
--- /dev/null
+++ b/vmwgfx/vmwgfx_xa_composite.c
@@ -0,0 +1,277 @@
+/*
+ * 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 <picturestr.h>
+#include <X11/extensions/Xrender.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] = XFixedToDouble(trans->matrix[0][0]);
+ matrix[3] = XFixedToDouble(trans->matrix[0][1]);
+ matrix[6] = XFixedToDouble(trans->matrix[0][2]);
+
+ matrix[1] = XFixedToDouble(trans->matrix[1][0]);
+ matrix[4] = XFixedToDouble(trans->matrix[1][1]);
+ matrix[7] = XFixedToDouble(trans->matrix[1][2]);
+
+ matrix[2] = XFixedToDouble(trans->matrix[2][0]);
+ matrix[5] = XFixedToDouble(trans->matrix[2][1]);
+ matrix[8] = XFixedToDouble(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;
+}
diff --git a/vmwgfx/vmwgfx_xa_surface.c b/vmwgfx/vmwgfx_xa_surface.c
new file mode 100644
index 0000000..2a18762
--- /dev/null
+++ b/vmwgfx/vmwgfx_xa_surface.c
@@ -0,0 +1,368 @@
+/*
+ * 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);
+
+
+/*
+ * 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.
+ */
+static 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;
+
+ 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;
+
+ if (vpix->staging_format != xa_surface_format(vpix->hw))
+ LogMessage(X_INFO, "Changing hardware format.\n");
+
+ if (xa_surface_redefine(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))
+ 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)
+{
+ return (vmwgfx_hw_dri2_stage(pixmap, depth) &&
+ vmwgfx_hw_commit(pixmap) &&
+ vmwgfx_hw_validate(pixmap, NULL));
+}
diff --git a/vmwgfx/wsbm_util.h b/vmwgfx/wsbm_util.h
new file mode 100644
index 0000000..2a2613b
--- /dev/null
+++ b/vmwgfx/wsbm_util.h
@@ -0,0 +1,79 @@
+/*
+ * 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