[Xquartz-changes] xserver: Branch 'master' - 35 commits

Jeremy Huddleston jeremyhu at freedesktop.org
Fri Nov 8 10:18:20 PST 2013


 Makefile.am                             |   12 
 Xext/shm.c                              |  168 ++++++
 Xext/shmint.h                           |   10 
 Xext/sync.c                             |   51 +-
 Xext/syncsrv.h                          |   13 
 Xext/xvdisp.c                           |   13 
 configure.ac                            |  116 +++-
 dix/region.c                            |   15 
 dri3/Makefile.am                        |   13 
 dri3/dri3.c                             |   87 +++
 dri3/dri3.h                             |   65 ++
 dri3/dri3_event.c                       |  163 ++++++
 dri3/dri3_priv.h                        |   80 +++
 dri3/dri3_request.c                     |  394 ++++++++++++++++
 dri3/dri3_screen.c                      |   80 +++
 dri3/dri3int.h                          |   26 +
 glx/glxcmds.c                           |    3 
 hw/dmx/dmxextension.c                   |    3 
 hw/dmx/dmxinit.c                        |    2 
 hw/kdrive/ephyr/hostx.c                 |   22 
 hw/xfree86/Makefile.am                  |    9 
 hw/xfree86/common/compiler.h            |    2 
 hw/xfree86/common/xf86Configure.c       |    2 
 hw/xfree86/common/xf86DPMS.c            |    9 
 hw/xfree86/common/xf86Events.c          |   31 -
 hw/xfree86/common/xf86RandR.c           |   16 
 hw/xfree86/modes/xf86Crtc.c             |   20 
 hw/xfree86/os-support/linux/lnx_video.c |    3 
 hw/xfree86/sdksyms.sh                   |    4 
 include/dix-config.h.in                 |    9 
 include/dixstruct.h                     |    8 
 include/extinit.h                       |   10 
 include/misc.h                          |   29 +
 include/os.h                            |    5 
 include/regionstr.h                     |    2 
 include/servermd.h                      |   14 
 include/xorg-config.h.in                |    6 
 include/xorg-server.h.in                |    9 
 mi/miinitext.c                          |    4 
 miext/damage/damage.c                   |    5 
 miext/sync/Makefile.am                  |    8 
 miext/sync/misync.c                     |   31 -
 miext/sync/misync.h                     |   21 
 miext/sync/misyncshm.c                  |  176 +++++++
 miext/sync/misyncshm.h                  |   28 +
 miext/sync/misyncstr.h                  |   15 
 os/backtrace.c                          |    5 
 os/connection.c                         |    2 
 os/io.c                                 |   29 +
 os/utils.c                              |   27 +
 os/xstrans.c                            |    2 
 present/Makefile.am                     |   17 
 present/present.c                       |  775 ++++++++++++++++++++++++++++++++
 present/present.h                       |  118 ++++
 present/present_event.c                 |  239 +++++++++
 present/present_fake.c                  |  140 +++++
 present/present_fence.c                 |  112 ++++
 present/present_notify.c                |  114 ++++
 present/present_priv.h                  |  288 +++++++++++
 present/present_request.c               |  330 +++++++++++++
 present/present_screen.c                |  231 +++++++++
 present/presentext.h                    |   29 +
 test/Makefile.am                        |   11 
 63 files changed, 4169 insertions(+), 112 deletions(-)

New commits:
commit ab4b1fb38a61feb73d8336cc7a3399eb9d3d25be
Author: Andreas Schwab <schwab at suse.de>
Date:   Thu Aug 15 12:03:42 2013 +0200

    ARM64: Add support for aarch64
    
    Signed-off-by: Andreas Schwab <schwab at suse.de>
    Reviewed-by: Mark Kettenis <kettenis at openbsd.org>
    Reviewed-by: Adam Jackson <ajax at redhat.com>
    Signed-off-by: Keith Packard <keithp at keithp.com>

diff --git a/hw/xfree86/common/compiler.h b/hw/xfree86/common/compiler.h
index c980bee..3a57186 100644
--- a/hw/xfree86/common/compiler.h
+++ b/hw/xfree86/common/compiler.h
@@ -1351,7 +1351,7 @@ stl_u(unsigned long val, unsigned int *p)
 #else                           /* ix86 */
 
 #if !defined(__SUNPRO_C)
-#if !defined(FAKEIT) && !defined(__mc68000__) && !defined(__arm__) && !defined(__sh__) && !defined(__hppa__) && !defined(__s390__) && !defined(__m32r__)
+#if !defined(FAKEIT) && !defined(__mc68000__) && !defined(__arm__) && !defined(__sh__) && !defined(__hppa__) && !defined(__s390__) && !defined(__m32r__) && !defined(__aarch64__)
 #ifdef GCCUSESGAS
 
 /*
diff --git a/hw/xfree86/os-support/linux/lnx_video.c b/hw/xfree86/os-support/linux/lnx_video.c
index d9a5da1..43d0a36 100644
--- a/hw/xfree86/os-support/linux/lnx_video.c
+++ b/hw/xfree86/os-support/linux/lnx_video.c
@@ -58,7 +58,8 @@ static Bool ExtendedEnabled = FALSE;
       !defined(__sparc__) && \
       !defined(__mips__) && \
       !defined(__nds32__) && \
-      !defined(__arm__)
+      !defined(__arm__) && \
+      !defined(__aarch64__)
 
 /*
  * Due to conflicts with "compiler.h", don't rely on <sys/io.h> to declare
diff --git a/include/servermd.h b/include/servermd.h
index d6a9a3a..11f6c10 100644
--- a/include/servermd.h
+++ b/include/servermd.h
@@ -286,6 +286,20 @@ SOFTWARE.
 #define GLYPHPADBYTES		4
 #endif                          /* linux/s390 */
 
+#ifdef __aarch64__
+
+#ifdef __AARCH64EL__
+#define IMAGE_BYTE_ORDER        LSBFirst
+#define BITMAP_BIT_ORDER        LSBFirst
+#endif
+#ifdef __AARCH64EB__
+#define IMAGE_BYTE_ORDER        MSBFirst
+#define BITMAP_BIT_ORDER        MSBFirst
+#endif
+#define GLYPHPADBYTES           4
+
+#endif                          /* __aarch64__ */
+
 /* size of buffer to use with GetImage, measured in bytes. There's obviously
  * a trade-off between the amount of heap used and the number of times the
  * ddx routine has to be called.
commit 8fcf82cbf015609e00b3feb9bc567133c7aee5cf
Author: Keith Packard <keithp at keithp.com>
Date:   Tue Nov 5 18:39:11 2013 -0800

    Use $GL_LIBS instead of -lGL for linking
    
    -lGL presumes that the GL library is in the system path, while
     $GL_LIBS is auto-detected.
    
    Signed-off-by: Keith Packard <keithp at keithp.com>

diff --git a/configure.ac b/configure.ac
index feeae04..6925df8 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1075,7 +1075,7 @@ if test "x$GLX" = xyes; then
 	AC_SUBST(XLIB_CFLAGS)
 	AC_DEFINE(GLXEXT, 1, [Build GLX extension])
 	GLX_LIBS='$(top_builddir)/glx/libglx.la'
-	GLX_SYS_LIBS="$GLX_SYS_LIBS -lGL"
+	GLX_SYS_LIBS="$GLX_SYS_LIBS $GL_LIBS"
 else
         GLX=no
 fi
commit f348935e7d2c84a438aba08eee2f2c4e0dc77d20
Author: Keith Packard <keithp at keithp.com>
Date:   Tue Nov 5 18:37:12 2013 -0800

    Link with xshmfence, reference miSyncShmScreenInit in sdksyms
    
    This gets the server to link with xshmfence again, and also ensures
    that the miSyncShm code is linked into the server with the reference
    from sdksyms.
    
    Signed-off-by: Keith Packard <keithp at keithp.com>

diff --git a/configure.ac b/configure.ac
index a7515a3..feeae04 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1144,6 +1144,7 @@ AM_CONDITIONAL(XSHMFENCE, test "x$HAVE_XSHMFENCE" = xyes)
 case x"$HAVE_XSHMFENCE" in
 	xyes)
 		AC_DEFINE(HAVE_XSHMFENCE, 1, [Have X Shared Memory Fence library])
+		REQUIRED_LIBS="$REQUIRED_LIBS xshmfence"
 		;;
 esac
 
diff --git a/hw/xfree86/sdksyms.sh b/hw/xfree86/sdksyms.sh
index 7c9734c..d7f259d 100755
--- a/hw/xfree86/sdksyms.sh
+++ b/hw/xfree86/sdksyms.sh
@@ -44,6 +44,9 @@ cat > sdksyms.c << EOF
 /* miext/sync/Makefile.am */
 #include "misync.h"
 #include "misyncstr.h"
+#if HAVE_XSHMFENCE
+#include "misyncshm.h"
+#endif
 
 /* Xext/Makefile.am -- half is module, half is builtin */
 #ifdef XV
diff --git a/include/dix-config.h.in b/include/dix-config.h.in
index 397ee96..156383b 100644
--- a/include/dix-config.h.in
+++ b/include/dix-config.h.in
@@ -449,4 +449,7 @@
 #include "dix-config-apple-verbatim.h"
 #endif
 
+/* Have support for X shared memory fence library (xshmfence) */
+#undef HAVE_XSHMFENCE
+
 #endif /* _DIX_CONFIG_H_ */
diff --git a/include/xorg-config.h.in b/include/xorg-config.h.in
index 487d7ad..e3444da 100644
--- a/include/xorg-config.h.in
+++ b/include/xorg-config.h.in
@@ -145,4 +145,7 @@
 /* Support APM/ACPI power management in the server */
 #undef XF86PM
 
+/* Have support for X shared memory fence library (xshmfence) */
+#undef HAVE_XSHMFENCE
+
 #endif /* _XORG_CONFIG_H_ */
commit 5f1e832694e57986c0185048a941b3af51b2f85f
Author: Julien Cristau <jcristau at debian.org>
Date:   Tue Nov 5 07:08:21 2013 -0800

    os: Actually use the computed clockid in GetTimeInMicros
    
    The selection of which clock to use for this function was not actually
    getting used when fetching the final clock value.
    
    Reported-by: Julien Cristau <jcristau at debian.org>
    Signed-off-by: Keith Packard <keithp at keithp.com>

diff --git a/os/utils.c b/os/utils.c
index 995f62a..fb20da7 100644
--- a/os/utils.c
+++ b/os/utils.c
@@ -480,7 +480,7 @@ GetTimeInMicros(void)
         else
             clockid = ~0L;
     }
-    if (clock_gettime(CLOCK_MONOTONIC, &tp) == 0)
+    if (clockid != ~0L && clock_gettime(clockid, &tp) == 0)
         return (CARD64) tp.tv_sec * (CARD64)1000000 + tp.tv_nsec / 1000;
 #endif
 
commit 903a058370645ea075ea98d380fd565efb6160c9
Author: Keith Packard <keithp at keithp.com>
Date:   Mon Nov 4 19:01:26 2013 -0800

    hw/xfree86: Link libdri3 only when DRI3 is defined
    
    Don't attempt to link non-existant libraries...
    
    Signed-off-by: Keith Packard <keithp at keithp.com>

diff --git a/hw/xfree86/Makefile.am b/hw/xfree86/Makefile.am
index eea16a8..485386f 100644
--- a/hw/xfree86/Makefile.am
+++ b/hw/xfree86/Makefile.am
@@ -9,6 +9,11 @@ DRI2_SUBDIR = dri2
 DRI2_LIB = dri2/libdri2.la
 endif
 
+if DRI3
+DRI3_BUILDDIR = $(top_builddir)/dri3
+DRI3_LIB = $(DRI3_BUILDDIR)/libdri3.la
+endif
+
 if XF86UTILS
 XF86UTILS_SUBDIR = utils
 endif
@@ -59,7 +64,7 @@ LOCAL_LIBS = \
             dixmods/libxorgxkb.la \
             $(DRI_LIB) \
             $(DRI2_LIB) \
-	    $(top_builddir)/dri3/libdri3.la \
+	    $(DRI3_LIB) \
 	    $(top_builddir)/miext/sync/libsync.la \
             $(top_builddir)/mi/libmi.la \
             $(top_builddir)/os/libos.la
commit aaf0e29619196a283fee7ead2020a91032d84f48
Author: Keith Packard <keithp at keithp.com>
Date:   Sun Nov 3 09:56:02 2013 -0800

    Disable DRI3 and sync fence FD functions if xshmfence isn't available
    
    Make sure the server can build when the xshmfence library isn't present
    
    Signed-off-by: Keith Packard <keithp at keithp.com>

diff --git a/Xext/sync.c b/Xext/sync.c
index a04c383..dd18cde 100644
--- a/Xext/sync.c
+++ b/Xext/sync.c
@@ -919,6 +919,7 @@ SyncCreate(ClientPtr client, XID id, unsigned char type)
 int
 SyncCreateFenceFromFD(ClientPtr client, DrawablePtr pDraw, XID id, int fd, BOOL initially_triggered)
 {
+#if HAVE_XSHMFENCE
     SyncFence  *pFence;
     int         status;
 
@@ -936,12 +937,19 @@ SyncCreateFenceFromFD(ClientPtr client, DrawablePtr pDraw, XID id, int fd, BOOL
         return BadAlloc;
 
     return Success;
+#else
+    return BadImplementation;
+#endif
 }
 
 int
 SyncFDFromFence(ClientPtr client, DrawablePtr pDraw, SyncFence *pFence)
 {
+#if HAVE_XSHMFENCE
     return miSyncFDFromFence(pDraw, pFence);
+#else
+    return BadImplementation;
+#endif
 }
 
 static SyncCounter *
diff --git a/configure.ac b/configure.ac
index 0d855f2..a7515a3 100644
--- a/configure.ac
+++ b/configure.ac
@@ -792,6 +792,7 @@ DMXPROTO="dmxproto >= 2.2.99.1"
 VIDMODEPROTO="xf86vidmodeproto >= 2.2.99.1"
 WINDOWSWMPROTO="windowswmproto"
 APPLEWMPROTO="applewmproto >= 1.4"
+XSHMFENCE="xshmfence"
 
 dnl Required modules
 XPROTO="xproto >= 7.0.22"
@@ -1119,17 +1120,59 @@ AM_CONDITIONAL(DRI2, test "x$DRI2" = xyes)
 
 PKG_CHECK_MODULES([DRI3PROTO], $DRI3PROTO,
                   [HAVE_DRI3PROTO=yes], [HAVE_DRI3PROTO=no])
+
 case "$DRI3,$HAVE_DRI3PROTO" in
+	yes,yes | auto,yes)
+		;;
 	yes,no)
 		AC_MSG_ERROR([DRI3 requested, but dri3proto not found.])
+		DRI3=no
+		;;
+	no,*)
+		;;
+	*)
+		AC_MSG_NOTICE([DRI3 disabled because dri3proto not found.])
+		DRI3=no
 		;;
+esac
+
+PKG_CHECK_MODULES([XSHMFENCE], $XSHMFENCE,
+		  [HAVE_XSHMFENCE=yes], [HAVE_XSHMFENCE=no])
+
+AM_CONDITIONAL(XSHMFENCE, test "x$HAVE_XSHMFENCE" = xyes)
+
+case x"$HAVE_XSHMFENCE" in
+	xyes)
+		AC_DEFINE(HAVE_XSHMFENCE, 1, [Have X Shared Memory Fence library])
+		;;
+esac
+
+
+case "$DRI3,$HAVE_XSHMFENCE" in
 	yes,yes | auto,yes)
-		AC_DEFINE(DRI3, 1, [Build DRI3 extension])
+		;;
+	yes,no)
+		AC_MSG_ERROR("DRI3 requested, but xshmfence not found.])
+		DRI3=no
+		;;
+	no,*)
+		;;
+	*)
+		AC_MSG_NOTICE([DRI3 disabled because xshmfence not found.])
+		DRI3=no
+		;;
+esac
+
+case x"$DRI3" in
+	xyes|xauto)
 		DRI3=yes
+		AC_DEFINE(DRI3, 1, [Build DRI3 extension])
 		DRI3_LIB='$(top_builddir)/dri3/libdri3.la'
 		SDK_REQUIRED_MODULES="$SDK_REQUIRED_MODULES $DRI3PROTO"
+		AC_MSG_NOTICE([DRI3 enabled]);
 		;;
 esac
+
 AM_CONDITIONAL(DRI3, test "x$DRI3" = xyes)
 
 if test "x$DRI" = xyes || test "x$DRI2" = xyes || test "x$DRI3" = xyes || test "x$CONFIG_UDEV_KMS" = xyes; then
@@ -1333,7 +1376,6 @@ if test "x$XDMAUTH" = xyes; then
 		XDMCP_MODULES="xdmcp"
 	fi
 fi
-REQUIRED_LIBS="$REQUIRED_LIBS xshmfence"
 
 AC_DEFINE_DIR(COMPILEDDEFAULTFONTPATH, FONTPATH, [Default font path])
 AC_DEFINE_DIR(SERVER_MISC_CONFIG_PATH, SERVERCONFIG, [Server miscellaneous config path])
diff --git a/dri3/dri3.h b/dri3/dri3.h
index 7774c87..7c0c330 100644
--- a/dri3/dri3.h
+++ b/dri3/dri3.h
@@ -23,6 +23,10 @@
 #ifndef _DRI3_H_
 #define _DRI3_H_
 
+#include <xorg-server.h>
+
+#ifdef DRI3
+
 #include <X11/extensions/dri3proto.h>
 #include <randrstr.h>
 
@@ -56,4 +60,6 @@ typedef struct dri3_screen_info {
 extern _X_EXPORT Bool
 dri3_screen_init(ScreenPtr screen, dri3_screen_info_ptr info);
 
+#endif
+
 #endif /* _DRI3_H_ */
diff --git a/include/xorg-server.h.in b/include/xorg-server.h.in
index 1281b3e..960817e 100644
--- a/include/xorg-server.h.in
+++ b/include/xorg-server.h.in
@@ -218,4 +218,7 @@
 #define _XSERVER64 1
 #endif
 
+/* Have support for X shared memory fence library (xshmfence) */
+#undef HAVE_XSHMFENCE
+
 #endif /* _XORG_SERVER_H_ */
diff --git a/miext/sync/Makefile.am b/miext/sync/Makefile.am
index e25ceac..ac13c52 100644
--- a/miext/sync/Makefile.am
+++ b/miext/sync/Makefile.am
@@ -8,8 +8,13 @@ if XORG
 sdk_HEADERS = misync.h misyncstr.h misyncshm.h
 endif
 
+XSHMFENCE_SRCS = misyncshm.c
+
 libsync_la_SOURCES =	\
 	misync.c	\
 	misync.h	\
-	misyncshm.c	\
 	misyncstr.h
+
+if XSHMFENCE
+libsync_la_SOURCES += $(XSHMFENCE_SRCS)
+endif
commit 33c85beed521c9db140cadd8c5aa9992398ee1fe
Author: Keith Packard <keithp at keithp.com>
Date:   Fri Nov 1 01:01:58 2013 -0700

    Set version to 1.14.99.901 (1.15 RC1)
    
    Signed-off-by: Keith Packard <keithp at keithp.com>

diff --git a/configure.ac b/configure.ac
index 3d9832b..0d855f2 100644
--- a/configure.ac
+++ b/configure.ac
@@ -26,9 +26,9 @@ dnl
 dnl Process this file with autoconf to create configure.
 
 AC_PREREQ(2.60)
-AC_INIT([xorg-server], 1.14.99.3, [https://bugs.freedesktop.org/enter_bug.cgi?product=xorg], xorg-server)
-RELEASE_DATE="2013-10-18"
-RELEASE_NAME="Bundaberg"
+AC_INIT([xorg-server], 1.14.99.901, [https://bugs.freedesktop.org/enter_bug.cgi?product=xorg], xorg-server)
+RELEASE_DATE="2013-10-31"
+RELEASE_NAME="Bom Retiro"
 AC_CONFIG_SRCDIR([Makefile.am])
 AM_INIT_AUTOMAKE([foreign dist-bzip2])
 
commit 9db1d66f6d2c6857de220d8f1c08965962fe1416
Author: Keith Packard <keithp at keithp.com>
Date:   Fri Nov 1 01:43:59 2013 -0700

    Add dri3 and present directorys to distribution
    
    Signed-off-by: Keith Packard <keithp at keithp.com>

diff --git a/Makefile.am b/Makefile.am
index 28266c5..5bf760b 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -101,6 +101,8 @@ DIST_SUBDIRS = \
 	glx \
 	exa \
 	config \
+	dri3 \
+	present \
 	hw \
 	test
 
commit 977e2644b1d9e13b44debcb9a372bbc832ee32a3
Merge: 66c5ee0 f36f5a6
Author: Keith Packard <keithp at keithp.com>
Date:   Fri Nov 1 00:34:18 2013 -0700

    Merge remote-tracking branch 'whot/for-keith'

commit 66c5ee0ff4690e630a69656331fd9d545c99c26c
Author: Egbert Eich <eich at freedesktop.org>
Date:   Wed Aug 14 18:18:56 2013 +0200

    config/APM: Add option to disable building of APM support on Linux
    
        APM support in the Xserver was used to restore the console mode
        prior to a power management event. This was to ensure the mode
        upon suspend/resume was one that the system firmware or kernel
        could deal with.
        APM support is now largely obsolete, KMS drivers don't require a
        mode restoration anyhow. Therefore it should be possible to disable
        this feature.
    
    (small modification by keithp - move test for XF86PM flag after check
    for APM, then move XF86PM flag to xorg-config.h.in)
    
    Signed-off-by: Egbert Eich <eich at freedesktop.org>
    Tested-by: Keith Packard <keithp at keithp.com>
    Signed-off-by: Keith Packard <keithp at keithp.com>

diff --git a/configure.ac b/configure.ac
index 9b8b89f..c48d2aa 100644
--- a/configure.ac
+++ b/configure.ac
@@ -228,10 +228,6 @@ dnl AGPGART headers
 AC_CHECK_HEADERS([linux/agpgart.h sys/agpio.h sys/agpgart.h], AGP=yes)
 AM_CONDITIONAL(AGP, [test "x$AGP" = xyes])
 
-dnl APM header
-AC_CHECK_HEADERS([linux/apm_bios.h], LNXAPM=yes)
-AM_CONDITIONAL(LNXAPM, [test "x$LNXAPM" = xyes])
-
 dnl fbdev header
 AC_CHECK_HEADERS([linux/fb.h], FBDEV=yes)
 AM_CONDITIONAL(FBDEVHW, [test "x$FBDEV" = xyes])
@@ -638,6 +634,7 @@ AC_ARG_ENABLE(libdrm,         AS_HELP_STRING([--enable-libdrm], [Build Xorg with
 AC_ARG_ENABLE(clientids,      AS_HELP_STRING([--disable-clientids], [Build Xorg with client ID tracking (default: enabled)]), [CLIENTIDS=$enableval], [CLIENTIDS=yes])
 AC_ARG_ENABLE(pciaccess, AS_HELP_STRING([--enable-pciaccess], [Build Xorg with pciaccess library (default: enabled)]), [PCI=$enableval], [PCI=yes])
 AC_ARG_ENABLE(linux_acpi, AC_HELP_STRING([--disable-linux-acpi], [Disable building ACPI support on Linux (if available).]), [enable_linux_acpi=$enableval], [enable_linux_acpi=yes])
+AC_ARG_ENABLE(linux_apm, AC_HELP_STRING([--disable-linux-apm], [Disable building APM support on Linux (if available).]), [enable_linux_apm=$enableval], [enable_linux_apm=yes])
 
 dnl DDXes.
 AC_ARG_ENABLE(xorg,    	      AS_HELP_STRING([--enable-xorg], [Build Xorg server (default: auto)]), [XORG=$enableval], [XORG=auto])
@@ -1736,9 +1733,6 @@ if test "x$XORG" = xyes; then
 
 	case $host_os in
 	  linux*)
-		if test "x$LNXAPM" = xyes; then
-			XORG_CFLAGS="$XORG_CFLAGS -DXF86PM"
-		fi
 		XORG_OS_SUBDIR="linux"
 		linux_acpi="no"
 		case $host_cpu in
@@ -1751,6 +1745,11 @@ if test "x$XORG" = xyes; then
 		  *)
 			;;
 		esac
+		dnl APM header
+		AC_CHECK_HEADERS([linux/apm_bios.h], [linux_apm=$enable_linux_apm])
+		if test "x$linux_apm" = xyes -o "x$linux_acpi" = xyes; then
+			AC_DEFINE(XF86PM, 1, [Support APM/ACPI power management in the server])
+		fi
 		;;
 	  freebsd* | kfreebsd*-gnu | dragonfly*)
 		XORG_OS_SUBDIR="bsd"
@@ -1913,6 +1912,7 @@ AM_CONDITIONAL([XORG_BUS_BSDPCI], [test "x$xorg_bus_bsdpci" = xyes])
 AM_CONDITIONAL([XORG_BUS_SPARC], [test "x$xorg_bus_sparc" = xyes])
 AM_CONDITIONAL([LINUX_ALPHA], [test "x$linux_alpha" = xyes])
 AM_CONDITIONAL([LNXACPI], [test "x$linux_acpi" = xyes])
+AM_CONDITIONAL([LNXAPM], [test "x$linux_apm" = xyes])
 AM_CONDITIONAL([SOLARIS_ASM_INLINE], [test "x$solaris_asm_inline" = xyes])
 AM_CONDITIONAL([SOLARIS_VT], [test "x$solaris_vt" = xyes])
 AM_CONDITIONAL([DGA], [test "x$DGA" = xyes])
diff --git a/include/xorg-config.h.in b/include/xorg-config.h.in
index 0df31ae..487d7ad 100644
--- a/include/xorg-config.h.in
+++ b/include/xorg-config.h.in
@@ -142,4 +142,7 @@
 /* Define to 1 if you have the `seteuid' function. */
 #undef HAVE_SETEUID
 
+/* Support APM/ACPI power management in the server */
+#undef XF86PM
+
 #endif /* _XORG_CONFIG_H_ */
commit f36f5a65f639b6524191d888d5bf89e73027156c
Author: Peter Hutterer <peter.hutterer at who-t.net>
Date:   Wed Oct 30 15:40:58 2013 +1000

    sync: fix corner-case in triggering idle alarms
    
    ProcessInputEvent() resets the device idle times. If idle time was higher than
    the lower bracket, this should trigger an event in the idle time wakeup
    handler.
    
    If processing is slow, the idle time may advance past the lower bracket
    between the reset and the time the BlockHandler is called. In that case, we'd
    never schedule a wakeup to handle the event, causing us to randomly miss
    events.
    
    Ran tests with a neg transition trigger on 5ms with 200 repeats of the test
    and it succeeded. Anything below that gets a bit tricky to make sure the
    server sees the same idle time as the client usleeps for.
    
    Signed-off-by: Peter Hutterer <peter.hutterer at who-t.net>
    Reviewed-by: Keith Packard <keithp at keithp.com>

diff --git a/Xext/sync.c b/Xext/sync.c
index b2ee92e..53f769d 100644
--- a/Xext/sync.c
+++ b/Xext/sync.c
@@ -2654,7 +2654,16 @@ IdleTimeBlockHandler(pointer pCounter, struct timeval **wt, pointer LastSelectMa
     IdleTimeQueryValue(counter, &idle);
     counter->value = idle;      /* push, so CheckTrigger works */
 
-    if (less && XSyncValueLessOrEqual(idle, *less)) {
+    /**
+     * There's an indefinite amount of time between ProcessInputEvents()
+     * where the idle time is reset and the time we actually get here. idle
+     * may be past the lower bracket if we dawdled with the events, so
+     * check for whether we did reset and bomb out of select immediately.
+     */
+    if (less && XSyncValueGreaterThan(idle, *less) &&
+        LastEventTimeWasReset(priv->deviceid)) {
+        AdjustWaitForDelay(wt, 0);
+    } else if (less && XSyncValueLessOrEqual(idle, *less)) {
         /*
          * We've been idle for less than the threshold value, and someone
          * wants to know about that, but now we need to know whether they
commit f994d99539192a10a8c83047e11991f52e0ca677
Author: Egbert Eich <eich at freedesktop.org>
Date:   Wed Aug 14 18:18:39 2013 +0200

    config/ACPI: Add option to disable building of ACPI support on Linux
    
    ACPI support in the Xserver was used to restore the console mode
    prior to a power management event. This was to ensure the mode
    upon suspend/resume was one that the system firmware or kernel
    could deal with.
    The feature depended on acpid to be running. Most of this functionality
    is now take over by systemd, KMS drivers don't require a mode restoration
    anyhow. Therefore it should be possible to disable this feature under
    some circumstances.
    
    Tested-by: Keith Packard <keithp at keithp.com>
    Signed-off-by: Keith Packard <keithp at keithp.com>

diff --git a/configure.ac b/configure.ac
index 7432912..9b8b89f 100644
--- a/configure.ac
+++ b/configure.ac
@@ -637,6 +637,7 @@ AC_ARG_ENABLE(windowswm,      AS_HELP_STRING([--enable-windowswm], [Build XWin w
 AC_ARG_ENABLE(libdrm,         AS_HELP_STRING([--enable-libdrm], [Build Xorg with libdrm support (default: enabled)]), [DRM=$enableval],[DRM=yes])
 AC_ARG_ENABLE(clientids,      AS_HELP_STRING([--disable-clientids], [Build Xorg with client ID tracking (default: enabled)]), [CLIENTIDS=$enableval], [CLIENTIDS=yes])
 AC_ARG_ENABLE(pciaccess, AS_HELP_STRING([--enable-pciaccess], [Build Xorg with pciaccess library (default: enabled)]), [PCI=$enableval], [PCI=yes])
+AC_ARG_ENABLE(linux_acpi, AC_HELP_STRING([--disable-linux-acpi], [Disable building ACPI support on Linux (if available).]), [enable_linux_acpi=$enableval], [enable_linux_acpi=yes])
 
 dnl DDXes.
 AC_ARG_ENABLE(xorg,    	      AS_HELP_STRING([--enable-xorg], [Build Xorg server (default: auto)]), [XORG=$enableval], [XORG=auto])
@@ -1745,7 +1746,7 @@ if test "x$XORG" = xyes; then
 		  	linux_alpha=yes
 			;;
 		  i*86|amd64*|x86_64*|ia64*)
-			linux_acpi="yes"
+			linux_acpi=$enable_linux_acpi
 			;;
 		  *)
 			;;
commit 2aa5092b88174cb9988076ae96298217c97ad75f
Author: Egbert Eich <eich at freedesktop.org>
Date:   Mon Aug 12 18:21:33 2013 +0200

    DDX/Randr: Avoid server crash when xrandr SetConfig is called while switched away
    
    A call to Xrandr SetScreenConfig (for randr 1.1) causes the Xserver to
    crash when xf86SetViewport() which does not check if the hardware is
    accessible.
    Wrap accesses to xf86SetViewport() with if (vtSema) { ... } to avoid that.
    
    Signed-off-by: Egbert Eich <eich at freedesktop.org>
    Reviewed-by: Keith Packard <keithp at keithp.com>
    Signed-off-by: Keith Packard <keithp at keithp.com>

diff --git a/hw/xfree86/common/xf86RandR.c b/hw/xfree86/common/xf86RandR.c
index 5606bee..2418731 100644
--- a/hw/xfree86/common/xf86RandR.c
+++ b/hw/xfree86/common/xf86RandR.c
@@ -214,13 +214,15 @@ xf86RandRSetMode(ScreenPtr pScreen,
      */
     xf86ReconfigureLayout();
 
-    /*
-     * Make sure the whole screen is visible
-     */
-    xf86SetViewport(pScreen, pScreen->width, pScreen->height);
-    xf86SetViewport(pScreen, 0, 0);
-    if (pRoot && scrp->vtSema)
-        (*scrp->EnableDisableFBAccess) (scrp, TRUE);
+    if (scrp->vtSema) {
+        /*
+         * Make sure the whole screen is visible
+         */
+        xf86SetViewport (pScreen, pScreen->width, pScreen->height);
+        xf86SetViewport (pScreen, 0, 0);
+        if (pRoot)
+            (*scrp->EnableDisableFBAccess) (scrp, TRUE);
+    }
     return ret;
 }
 
commit 508e05777aba823c93a2417cc26d18c9f061ca26
Author: Egbert Eich <eich at freedesktop.org>
Date:   Mon Aug 12 18:20:36 2013 +0200

    DDX/Events: Distinguish between Input- and GeneralHandlers in xf86VTSwitch()
    
    When enabling/disabling input handlers in xf86VTSwitch() we treat Input-
    and GeneralHandlers equally. The result is that after a VT switch the
    masks for EnabledDevices and AllSockets are equal and the distiction
    between both types is lost.
    
    Signed-off-by: Egbert Eich <eich at freedesktop.org>
    Reviewed-by: Daniel Stone <daniel at fooishbar.org>
    Reviewed-by: Peter Hutterer <peter.hutterer at who-t.net>
    Signed-off-by: Keith Packard <keithp at keithp.com>

diff --git a/hw/xfree86/common/xf86Events.c b/hw/xfree86/common/xf86Events.c
index 7a949fd..d0b1431 100644
--- a/hw/xfree86/common/xf86Events.c
+++ b/hw/xfree86/common/xf86Events.c
@@ -116,6 +116,7 @@ typedef struct x_IHRec {
     InputHandlerProc ihproc;
     pointer data;
     Bool enabled;
+    Bool is_input;
     struct x_IHRec *next;
 } IHRec, *IHPtr;
 
@@ -446,8 +447,12 @@ xf86VTSwitch(void)
          * Keep the order: Disable Device > LeaveVT
          *                        EnterVT > EnableDevice
          */
-        for (ih = InputHandlers; ih; ih = ih->next)
-            xf86DisableInputHandler(ih);
+        for (ih = InputHandlers; ih; ih = ih->next) {
+            if (ih->is_input)
+                xf86DisableInputHandler(ih);
+            else
+                xf86DisableGeneralHandler(ih);
+        }
         for (pInfo = xf86InputDevs; pInfo; pInfo = pInfo->next) {
             if (pInfo->dev) {
                 if (!pInfo->dev->enabled)
@@ -496,9 +501,12 @@ xf86VTSwitch(void)
                 pInfo->flags &= ~XI86_DEVICE_DISABLED;
                 pInfo = pInfo->next;
             }
-            for (ih = InputHandlers; ih; ih = ih->next)
-                xf86EnableInputHandler(ih);
-
+            for (ih = InputHandlers; ih; ih = ih->next) {
+                if (ih->is_input)
+                    xf86EnableInputHandler(ih);
+                else
+                    xf86EnableGeneralHandler(ih);
+            }
             OsReleaseSIGIO();
 
         }
@@ -558,9 +566,12 @@ xf86VTSwitch(void)
             pInfo = pInfo->next;
         }
 
-        for (ih = InputHandlers; ih; ih = ih->next)
-            xf86EnableInputHandler(ih);
-
+        for (ih = InputHandlers; ih; ih = ih->next) {
+            if (ih->is_input)
+                xf86EnableInputHandler(ih);
+            else
+                xf86EnableGeneralHandler(ih);
+        }
 #ifdef XSERVER_PLATFORM_BUS
         /* check for any new output devices */
         xf86platformVTProbe();
@@ -600,8 +611,10 @@ xf86AddInputHandler(int fd, InputHandlerProc proc, pointer data)
 {
     IHPtr ih = addInputHandler(fd, proc, data);
 
-    if (ih)
+    if (ih) {
         AddEnabledDevice(fd);
+        ih->is_input = TRUE;
+    }
     return ih;
 }
 
commit 0cb33ce34081d7d123ec565582d7d19bdb3964ad
Author: Egbert Eich <eich at freedesktop.org>
Date:   Sat Oct 5 08:02:28 2013 +0200

    DDX/modes: Add a sanity check when using screen sizes from EDID
    
    EDID sometimes lies about screen sizes. Since the screen size is used
    by clients to determine the DPI a wrong ration will lead to terrible
    looking fonts.
    Add a sanity check for the h/v ratio cutting off at 2.4. This would
    still accept the cinemascope aspect ratio as valid.
    Also add message suggesting to add a quirk table entry.
    
    Signed-off-by: Egbert Eich <eich at freedesktop.org>
    Reviewed-by: Keith Packard <keithp at keithp.com>
    Signed-off-by: Keith Packard <keithp at keithp.com>

diff --git a/hw/xfree86/modes/xf86Crtc.c b/hw/xfree86/modes/xf86Crtc.c
index 35845e8..2a02c85 100644
--- a/hw/xfree86/modes/xf86Crtc.c
+++ b/hw/xfree86/modes/xf86Crtc.c
@@ -3045,10 +3045,22 @@ handle_detailed_physical_size(struct detailed_monitor_section
     if (det_mon->type == DT &&
         det_mon->section.d_timings.h_size != 0 &&
         det_mon->section.d_timings.v_size != 0) {
-
-        p->output->mm_width = det_mon->section.d_timings.h_size;
-        p->output->mm_height = det_mon->section.d_timings.v_size;
-        p->ret = TRUE;
+        /* some sanity checking for aspect ratio:
+           assume any h / v (or v / h) > 2.4 to be bogus.
+           This would even include cinemascope */
+        if (((det_mon->section.d_timings.h_size * 5) <
+             (det_mon->section.d_timings.v_size * 12)) &&
+            ((det_mon->section.d_timings.v_size * 5) <
+             (det_mon->section.d_timings.h_size * 12))) {
+            p->output->mm_width = det_mon->section.d_timings.h_size;
+            p->output->mm_height = det_mon->section.d_timings.v_size;
+            p->ret = TRUE;
+        } else
+            xf86DrvMsg(p->output->scrn->scrnIndex, X_WARNING,
+                       "Output %s: Strange aspect ratio (%i/%i), "
+                       "consider adding a quirk\n", p->output->name,
+                       det_mon->section.d_timings.h_size,
+                       det_mon->section.d_timings.v_size);
     }
 }
 
commit 41d4beb2616ceb3f1a1b8694733e85bae70de59a
Author: Egbert Eich <eich at freedesktop.org>
Date:   Wed Aug 14 11:50:26 2013 +0200

    DDX/DPMS: Call dixSaveScreens() also when screen is turned on
    
    DMPS calls dixSaveScreens() when turned off but not when turned
    on. In most cases this is irrelevant as DPMS is done when a
    key is hit in which case dixSaveScreens() will be called to
    unblank anyhow. This isn't the case if we use xset (or the
    DPMS extension directly) to unblank.
    Check screenIsSaved to make sure the state needs to be changed
    before calling dixSaveScreens().
    
    Signed-off-by: Egbert Eich <eich at freedesktop.org>
    Reviewed-by: Keith Packard <keithp at keithp.com>
    Signed-off-by: Keith Packard <keithp at keithp.com>

diff --git a/hw/xfree86/common/xf86DPMS.c b/hw/xfree86/common/xf86DPMS.c
index 3f1e142..881cb27 100644
--- a/hw/xfree86/common/xf86DPMS.c
+++ b/hw/xfree86/common/xf86DPMS.c
@@ -36,6 +36,7 @@
 #include <X11/X.h>
 #include "os.h"
 #include "globals.h"
+#include "windowstr.h"
 #include "xf86.h"
 #include "xf86Priv.h"
 #ifdef DPMSExtension
@@ -159,7 +160,13 @@ DPMSSet(ClientPtr client, int level)
         return Success;
 
     if (level != DPMSModeOn) {
-        rc = dixSaveScreens(client, SCREEN_SAVER_FORCER, ScreenSaverActive);
+        if (xf86IsUnblank(screenIsSaved)) {
+            rc = dixSaveScreens(client, SCREEN_SAVER_FORCER, ScreenSaverActive);
+            if (rc != Success)
+                return rc;
+        }
+    } else if (!xf86IsUnblank(screenIsSaved)) {
+        rc = dixSaveScreens(client, SCREEN_SAVER_FORCER, ScreenSaverReset);
         if (rc != Success)
             return rc;
     }
commit 623c4147650d0404cfbea0f9b7df66dc7d928e00
Author: Søren Sandmann Pedersen <ssp at redhat.com>
Date:   Mon Oct 21 17:11:56 2013 -0400

    ephyr: Ensure stride of private framebuffer is multiple of 4
    
    The fb layer of X can't deal with strides that are not a multiple of
    4, so when Xephyr allocates its own framebuffer it should make sure to
    align it.
    
    This fixes crashes and rendering corruption when Xephyr runs in a
    depth that is different from the host X server and its screen size is
    not a multiple of 4 / depth. (This is particularly easy to trigger if
    you use the -resizeable option).
    
    Reviewed-by: Eric Anholt <eric at anholt.net>
    Signed-off-by: Soren Sandmann <ssp at redhat.com>
    Reviewed-by: Adam Jackson <ajax at redhat.com>

diff --git a/hw/kdrive/ephyr/hostx.c b/hw/kdrive/ephyr/hostx.c
index 6020e8d..ee9ae45 100644
--- a/hw/kdrive/ephyr/hostx.c
+++ b/hw/kdrive/ephyr/hostx.c
@@ -721,12 +721,14 @@ hostx_screen_init(KdScreenInfo *screen,
         return scrpriv->ximg->data;
     }
     else {
-        *bytes_per_line = width * (scrpriv->server_depth >> 3);
+        int bytes_per_pixel = scrpriv->server_depth >> 3;
+        int stride = (width * bytes_per_pixel + 0x3) & ~0x3;
+
+        *bytes_per_line = stride;
         *bits_per_pixel = scrpriv->server_depth;
 
-        EPHYR_DBG("server bpp %i", scrpriv->server_depth >> 3);
-        scrpriv->fb_data =
-            malloc(width * buffer_height * (scrpriv->server_depth >> 3));
+        EPHYR_DBG("server bpp %i", bytes_per_pixel);
+        scrpriv->fb_data = malloc (stride * buffer_height);
         return scrpriv->fb_data;
     }
 }
@@ -765,15 +767,14 @@ hostx_paint_rect(KdScreenInfo *screen,
 
     if (!host_depth_matches_server(scrpriv)) {
         int x, y, idx, bytes_per_pixel = (scrpriv->server_depth >> 3);
+        int stride = (scrpriv->win_width * bytes_per_pixel + 0x3) & ~0x3;
         unsigned char r, g, b;
         unsigned long host_pixel;
 
         EPHYR_DBG("Unmatched host depth scrpriv=%p\n", scrpriv);
         for (y = sy; y < sy + height; y++)
             for (x = sx; x < sx + width; x++) {
-                idx =
-                    (scrpriv->win_width * y * bytes_per_pixel) +
-                    (x * bytes_per_pixel);
+                idx = y * stride + x * bytes_per_pixel;
 
                 switch (scrpriv->server_depth) {
                 case 16:
commit 97cf53cc2ad7ecfdd495133bad31d0ec7d939326
Author: Søren Sandmann Pedersen <ssp at redhat.com>
Date:   Mon Oct 21 16:58:54 2013 -0400

    ephyr: hostx_screen_init(): Fix bits_per_pixel and bytes_per_line
    
    When the depth of the Xephyr server matches that of the host X server,
    Xephyr simply uses the buffer associated with the XImage as its
    framebuffer. In this case, it is correct to get the bits_per_pixel and
    bytes_per_line values returned from hostx_screen_init() from the XImage.
    
    However, when the depth doesn't match the host, Xephyr uses a private
    framebuffer that is periodically copied to the XImage. In this case,
    the returned values of bits_per_pixel and bytes_per_line should be
    those of the private framebuffer, not those of the XImage.
    
    Reviewed-by: Eric Anholt <eric at anholt.net>
    Signed-off-by: Soren Sandmann <ssp at redhat.com>
    Reviewed-by: Adam Jackson <ajax at redhat.com>

diff --git a/hw/kdrive/ephyr/hostx.c b/hw/kdrive/ephyr/hostx.c
index 5fa33b9..6020e8d 100644
--- a/hw/kdrive/ephyr/hostx.c
+++ b/hw/kdrive/ephyr/hostx.c
@@ -695,9 +695,6 @@ hostx_screen_init(KdScreenInfo *screen,
             malloc(scrpriv->ximg->stride * buffer_height);
     }
 
-    *bytes_per_line = scrpriv->ximg->stride;
-    *bits_per_pixel = scrpriv->ximg->bpp;
-
     if (scrpriv->win_pre_existing == None && !EphyrWantResize) {
         /* Ask the WM to keep our size static */
         xcb_size_hints_t size_hints = {0};
@@ -717,10 +714,16 @@ hostx_screen_init(KdScreenInfo *screen,
     scrpriv->win_height = height;
 
     if (host_depth_matches_server(scrpriv)) {
+        *bytes_per_line = scrpriv->ximg->stride;
+        *bits_per_pixel = scrpriv->ximg->bpp;
+
         EPHYR_DBG("Host matches server");
         return scrpriv->ximg->data;
     }
     else {
+        *bytes_per_line = width * (scrpriv->server_depth >> 3);
+        *bits_per_pixel = scrpriv->server_depth;
+
         EPHYR_DBG("server bpp %i", scrpriv->server_depth >> 3);
         scrpriv->fb_data =
             malloc(width * buffer_height * (scrpriv->server_depth >> 3));
commit 55246b67b755d4c1039d54971fe3f77ea60d604e
Author: Søren Sandmann Pedersen <ssp at redhat.com>
Date:   Tue Oct 8 17:45:40 2013 -0400

    xf86AddBusDeviceToConfigure(): Store device in DevToConfig[i].pVideo
    
    After fc3ab84d the pVideo field in DevToConfig[i] is no longer
    initialized, so it's always NULL. This causes the duplicate finding
    algorithm in the beginning of the function to not work anymore as it
    is based on this field.
    
    The symptom of this bug is that X -configure reports
    
        Number of created screens does not match number of detected devices.
          Configuration failed.
        Server terminated with error (2). Closing log file.
    
    rather than producing a working config file.
    
    This patch fixes that bug by initializing the field before calling
    xf86PciConfigureNewDev().
    
    Cc: tvignatti at gmail.com
    Signed-off-by: Soren Sandmann <ssp at redhat.com>
    Reviewed-by: Adam Jackson <ajax at redhat.com>

diff --git a/hw/xfree86/common/xf86Configure.c b/hw/xfree86/common/xf86Configure.c
index 6c5e359..91e8df9 100644
--- a/hw/xfree86/common/xf86Configure.c
+++ b/hw/xfree86/common/xf86Configure.c
@@ -123,12 +123,14 @@ xf86AddBusDeviceToConfigure(const char *driver, BusType bus, void *busData,
     switch (bus) {
 #ifdef XSERVER_LIBPCIACCESS
     case BUS_PCI:
+	DevToConfig[i].pVideo = busData;
         xf86PciConfigureNewDev(busData, DevToConfig[i].pVideo,
                                &DevToConfig[i].GDev, &chipset);
         break;
 #endif
 #if (defined(__sparc__) || defined(__sparc)) && !defined(__OpenBSD__)
     case BUS_SBUS:
+	DevToConfig[i].sVideo = busData;
         xf86SbusConfigureNewDev(busData, DevToConfig[i].sVideo,
                                 &DevToConfig[i].GDev);
         break;
commit 95bf478b78e466002c382bcde7d4d62591e9215d
Merge: abf5d5a bb745f2
Author: Keith Packard <keithp at keithp.com>
Date:   Thu Oct 31 18:18:19 2013 -0700

    Merge remote-tracking branch 'jeremyhu/master'

commit abf5d5ac12437ebe156b4dd500c2acd69eea3654
Author: Jeremy Huddleston Sequoia <jeremyhu at apple.com>
Date:   Thu Oct 31 08:57:56 2013 -0700

    miext/damage: Partial revert of "Only wrap into the GC ops chain if there's a listener (v3)"
    
    Fixes regression from: 4dc2a76740d921c824a4d8193f39dd373475f02a
    
    http://lists.x.org/archives/xorg-devel/2013-May/036241.html
    https://trac.macports.org/ticket/38993
    
    Signed-off-by: Jeremy Huddleston Sequoia <jeremyhu at apple.com>
    Reviewed-by: Adam Jackson <ajax at redhat.com>
    Signed-off-by: Keith Packard <keithp at keithp.com>

diff --git a/miext/damage/damage.c b/miext/damage/damage.c
index cc02991..173fe50 100644
--- a/miext/damage/damage.c
+++ b/miext/damage/damage.c
@@ -382,10 +382,7 @@ damageValidateGC(GCPtr pGC, unsigned long changes, DrawablePtr pDrawable)
     drawableDamage(pDrawable);
     DAMAGE_GC_FUNC_PROLOGUE(pGC);
     (*pGC->funcs->ValidateGC) (pGC, changes, pDrawable);
-    if (pDamage)
-        pGCPriv->ops = pGC->ops; /* so it's not NULL, so FUNC_EPILOGUE does work */
-    else
-        pGCPriv->ops = NULL;
+    pGCPriv->ops = pGC->ops; /* just so it's not NULL */
     DAMAGE_GC_FUNC_EPILOGUE(pGC);
 }
 
commit e4636072949a76477fe7c9d54662a0b3536b1372
Merge: 17ed7ac 5c5c1b7
Author: Keith Packard <keithp at keithp.com>
Date:   Thu Oct 31 17:05:48 2013 -0700

    Merge remote-tracking branch 'keithp/dri3'

commit 17ed7ac1fe7426d66f688087c09da5ff1dbb41d3
Author: Adam Jackson <ajax at redhat.com>
Date:   Thu Oct 31 18:39:22 2013 -0400

    glx: Lie about GLX_Y_INVERTED_EXT
    
    Well, that was lame.  The problem with reporting y inversion honestly is
    that libGL asks the driver _its_ opinion of Y inversion, which it just
    fabricates from whole cloth.  So then when libGL goes to compare the
    driver's idea of fbconfigs with that of the server - a fairly dumb idea
    to begin with - nothing matches, and direct rendering fails, and
    sadness.
    
    So until the DRI drivers are fixed we should just continue to lie about
    Y inversion.  GLX_DONT_CARE is what libGL would make up for that
    attribute if we hadn't sent it, so just send that instead.
    
    Signed-off-by: Adam Jackson <ajax at redhat.com>
    Tested-by: Keith Packard <keithp at keithp.com>
    Signed-off-by: Keith Packard <keithp at keithp.com>

diff --git a/glx/glxcmds.c b/glx/glxcmds.c
index 64ebf9e..efa4aec 100644
--- a/glx/glxcmds.c
+++ b/glx/glxcmds.c
@@ -1118,7 +1118,8 @@ DoGetFBConfigs(__GLXclientState * cl, unsigned screen)
         WRITE_PAIR(GLX_BIND_TO_MIPMAP_TEXTURE_EXT, modes->bindToMipmapTexture);
         WRITE_PAIR(GLX_BIND_TO_TEXTURE_TARGETS_EXT,
                    modes->bindToTextureTargets);
-	WRITE_PAIR(GLX_Y_INVERTED_EXT, modes->yInverted);
+	/* can't report honestly until mesa is fixed */
+	WRITE_PAIR(GLX_Y_INVERTED_EXT, GLX_DONT_CARE);
 	if (modes->drawableType & GLX_PBUFFER_BIT) {
 	    WRITE_PAIR(GLX_MAX_PBUFFER_WIDTH, modes->maxPbufferWidth);
 	    WRITE_PAIR(GLX_MAX_PBUFFER_HEIGHT, modes->maxPbufferHeight);
commit 5c5c1b77982a9af7279a90bc3c2be48adaa9c778
Author: Keith Packard <keithp at keithp.com>
Date:   Thu Jul 11 16:11:57 2013 -0700

    present: Add Present extension
    
    Provides both a software implementation using timers and driver hooks
    to base everything on vblank intervals.
    
    Signed-off-by: Keith Packard <keithp at keithp.com>
    Reviewed-by: Adam Jackson <ajax at redhat.com>

diff --git a/Makefile.am b/Makefile.am
index 7a8fc5b..28266c5 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -21,6 +21,10 @@ if DRI3
 DRI3_DIR=dri3
 endif
 
+if PRESENT
+PRESENT_DIR=present
+endif
+
 SUBDIRS = \
 	doc \
 	man \
@@ -42,6 +46,7 @@ SUBDIRS = \
 	damageext \
 	$(COMPOSITE_DIR) \
 	$(GLX_DIR) \
+	$(PRESENT_DIR) \
 	$(DRI3_DIR) \
 	exa \
 	config \
diff --git a/configure.ac b/configure.ac
index 546790d..7432912 100644
--- a/configure.ac
+++ b/configure.ac
@@ -614,6 +614,7 @@ AC_ARG_ENABLE(glx,            AS_HELP_STRING([--disable-glx], [Build GLX extensi
 AC_ARG_ENABLE(dri,            AS_HELP_STRING([--enable-dri], [Build DRI extension (default: auto)]), [DRI=$enableval])
 AC_ARG_ENABLE(dri2,           AS_HELP_STRING([--enable-dri2], [Build DRI2 extension (default: auto)]), [DRI2=$enableval], [DRI2=auto])
 AC_ARG_ENABLE(dri3,           AS_HELP_STRING([--enable-dri3], [Build DRI3 extension (default: auto)]), [DRI3=$enableval], [DRI3=auto])
+AC_ARG_ENABLE(present,	      AS_HELP_STRING([--disable-present], [Build Present extension (default: enabled)]), [PRESENT=$enableval], [PRESENT=yes])
 AC_ARG_ENABLE(xinerama,	      AS_HELP_STRING([--disable-xinerama], [Build Xinerama extension (default: enabled)]), [XINERAMA=$enableval], [XINERAMA=yes])
 AC_ARG_ENABLE(xf86vidmode,    AS_HELP_STRING([--disable-xf86vidmode], [Build XF86VidMode extension (default: auto)]), [XF86VIDMODE=$enableval], [XF86VIDMODE=auto])
 AC_ARG_ENABLE(xace,           AS_HELP_STRING([--disable-xace], [Build X-ACE extension (default: enabled)]), [XACE=$enableval], [XACE=yes])
@@ -807,6 +808,7 @@ DAMAGEPROTO="damageproto >= 1.1"
 XCMISCPROTO="xcmiscproto >= 1.2.0"
 BIGREQSPROTO="bigreqsproto >= 1.1.0"
 XTRANS="xtrans >= 1.2.2"
+PRESENTPROTO="presentproto >= 1.0"
 
 dnl List of libraries that require a specific version
 LIBAPPLEWM="applewm >= 1.4"
@@ -1160,6 +1162,14 @@ if test "x$DRI2" = xyes; then
 fi
 AM_CONDITIONAL(DRI2_AIGLX, test "x$DRI2_AIGLX" = xyes)
 
+AM_CONDITIONAL(PRESENT, [test "x$PRESENT" = xyes])
+if test "x$PRESENT" = xyes; then
+	AC_DEFINE(PRESENT, 1, [Support Present extension])
+	REQUIRED_MODULES="$REQUIRED_MODULES $PRESENTPROTO"
+	SDK_REQUIRED_MODULES="$SDK_REQUIRED_MODULES $PRESENTPROTO"
+	PRESENT_INC='-I$(top_srcdir)/present'
+	PRESENT_LIB='$(top_builddir)/present/libpresent.la'
+fi
 
 AM_CONDITIONAL(XINERAMA, [test "x$XINERAMA" = xyes])
 if test "x$XINERAMA" = xyes; then
@@ -1584,7 +1594,7 @@ AC_EGREP_CPP([I_AM_SVR4],[
 AC_DEFINE([SVR4],1,[Define to 1 on systems derived from System V Release 4])
 AC_MSG_RESULT([yes])], AC_MSG_RESULT([no]))
 
-XSERVER_CFLAGS="$XSERVER_CFLAGS $CORE_INCS $XEXT_INC $COMPOSITE_INC $DAMAGE_INC $FIXES_INC $XI_INC $MI_INC $MIEXT_SYNC_INC $MIEXT_SHADOW_INC $MIEXT_LAYER_INC $MIEXT_DAMAGE_INC $RENDER_INC $RANDR_INC $FB_INC $DBE_INC"
+XSERVER_CFLAGS="$XSERVER_CFLAGS $CORE_INCS $XEXT_INC $COMPOSITE_INC $DAMAGE_INC $FIXES_INC $XI_INC $MI_INC $MIEXT_SYNC_INC $MIEXT_SHADOW_INC $MIEXT_LAYER_INC $MIEXT_DAMAGE_INC $RENDER_INC $RANDR_INC $FB_INC $DBE_INC $PRESENT_INC"
 
 dnl ---------------------------------------------------------------------------
 dnl DDX section.
@@ -1597,7 +1607,7 @@ AC_MSG_RESULT([$XVFB])
 AM_CONDITIONAL(XVFB, [test "x$XVFB" = xyes])
 
 if test "x$XVFB" = xyes; then
-	XVFB_LIBS="$FB_LIB $FIXES_LIB $XEXT_LIB $DBE_LIB $RECORD_LIB $GLX_LIBS $RANDR_LIB $RENDER_LIB $DAMAGE_LIB $DRI3_LIB $MIEXT_SYNC_LIB $MIEXT_DAMAGE_LIB $MIEXT_SHADOW_LIB $XI_LIB $XKB_LIB $XKB_STUB_LIB $COMPOSITE_LIB"
+	XVFB_LIBS="$FB_LIB $FIXES_LIB $XEXT_LIB $DBE_LIB $RECORD_LIB $GLX_LIBS $RANDR_LIB $RENDER_LIB $DAMAGE_LIB $DRI3_LIB $PRESENT_LIB $MIEXT_SYNC_LIB $MIEXT_DAMAGE_LIB $MIEXT_SHADOW_LIB $XI_LIB $XKB_LIB $XKB_STUB_LIB $COMPOSITE_LIB"
 	XVFB_SYS_LIBS="$XVFBMODULES_LIBS $GLX_SYS_LIBS"
 	AC_SUBST([XVFB_LIBS])
 	AC_SUBST([XVFB_SYS_LIBS])
@@ -1618,7 +1628,7 @@ if test "x$XNEST" = xyes; then
 	if test "x$have_xnest" = xno; then
 		AC_MSG_ERROR([Xnest build explicitly requested, but required modules not found.])
 	fi
-	XNEST_LIBS="$FB_LIB $FIXES_LIB $MI_LIB $XEXT_LIB $DBE_LIB $RECORD_LIB $GLX_LIBS $RANDR_LIB $RENDER_LIB $DAMAGE_LIB  $DRI3_LIB $MIEXT_SYNC_LIB $MIEXT_DAMAGE_LIB $MIEXT_SHADOW_LIB $XI_LIB $XKB_LIB $XKB_STUB_LIB $COMPOSITE_LIB $MAIN_LIB $DIX_LIB $OS_LIB"
+	XNEST_LIBS="$FB_LIB $FIXES_LIB $MI_LIB $XEXT_LIB $DBE_LIB $RECORD_LIB $GLX_LIBS $RANDR_LIB $RENDER_LIB $DAMAGE_LIB  $DRI3_LIB $PRESENT_LIB $MIEXT_SYNC_LIB $MIEXT_DAMAGE_LIB $MIEXT_SHADOW_LIB $XI_LIB $XKB_LIB $XKB_STUB_LIB $COMPOSITE_LIB $MAIN_LIB $DIX_LIB $OS_LIB"
 	XNEST_SYS_LIBS="$XNESTMODULES_LIBS $GLX_SYS_LIBS"
 	AC_SUBST([XNEST_LIBS])
 	AC_SUBST([XNEST_SYS_LIBS])
@@ -1643,7 +1653,7 @@ if test "x$XORG" = xyes; then
 	XORG_OSINCS='-I$(top_srcdir)/hw/xfree86/os-support -I$(top_srcdir)/hw/xfree86/os-support/bus -I$(top_srcdir)/os'
 	XORG_INCS="$XORG_DDXINCS $XORG_OSINCS"
 	XORG_CFLAGS="$XORGSERVER_CFLAGS -DHAVE_XORG_CONFIG_H"
-	XORG_LIBS="$COMPOSITE_LIB $FIXES_LIB $XEXT_LIB $DBE_LIB $RECORD_LIB $RANDR_LIB $RENDER_LIB $DAMAGE_LIB $DRI3_LIB $MIEXT_SYNC_LIB $MIEXT_DAMAGE_LIB $XI_LIB $XKB_LIB"
+	XORG_LIBS="$COMPOSITE_LIB $FIXES_LIB $XEXT_LIB $DBE_LIB $RECORD_LIB $RANDR_LIB $RENDER_LIB $DAMAGE_LIB $DRI3_LIB $PRESENT_LIB $MIEXT_SYNC_LIB $MIEXT_DAMAGE_LIB $XI_LIB $XKB_LIB"
 
 	dnl ==================================================================
 	dnl symbol visibility
@@ -2056,7 +2066,7 @@ if test "x$DMX" = xyes; then
 	fi
 	DMX_INCLUDES="$XEXT_INC $RENDER_INC $RECORD_INC"
 	XDMX_CFLAGS="$DMXMODULES_CFLAGS"
-	XDMX_LIBS="$FB_LIB $MI_LIB $XEXT_LIB $RENDER_LIB $RECORD_LIB $XI_LIB $XKB_LIB $XKB_STUB_LIB  $DRI3_LIB $MIEXT_SYNC_LIB $MIEXT_SHADOW_LIB $MIEXT_DAMAGE_LIB $COMPOSITE_LIB $DAMAGE_LIB $MAIN_LIB $DIX_LIB $CONFIG_LIB $OS_LIB $FIXES_LIB"
+	XDMX_LIBS="$FB_LIB $MI_LIB $XEXT_LIB $RENDER_LIB $RECORD_LIB $XI_LIB $XKB_LIB $XKB_STUB_LIB  $DRI3_LIB $PRESENT_LIB $MIEXT_SYNC_LIB $MIEXT_SHADOW_LIB $MIEXT_DAMAGE_LIB $COMPOSITE_LIB $DAMAGE_LIB $MAIN_LIB $DIX_LIB $CONFIG_LIB $OS_LIB $FIXES_LIB"
 	XDMX_SYS_LIBS="$DMXMODULES_LIBS"
 	AC_SUBST([XDMX_CFLAGS])
 	AC_SUBST([XDMX_LIBS])
@@ -2165,7 +2175,7 @@ if test "$KDRIVE" = yes; then
     
     KDRIVE_CFLAGS="$XSERVER_CFLAGS -DHAVE_KDRIVE_CONFIG_H $TSLIB_CFLAGS"
 
-    KDRIVE_PURE_LIBS="$FB_LIB $MI_LIB $FIXES_LIB $XEXT_LIB $DBE_LIB $RECORD_LIB $GLX_LIBS $RANDR_LIB $RENDER_LIB $DAMAGE_LIB $DRI3_LIB $MIEXT_SYNC_LIB $MIEXT_DAMAGE_LIB $MIEXT_SHADOW_LIB $XI_LIB $XKB_LIB $XKB_STUB_LIB $COMPOSITE_LIB $OS_LIB"
+    KDRIVE_PURE_LIBS="$FB_LIB $MI_LIB $FIXES_LIB $XEXT_LIB $DBE_LIB $RECORD_LIB $GLX_LIBS $RANDR_LIB $RENDER_LIB $DAMAGE_LIB $DRI3_LIB $PRESENT_LIB $MIEXT_SYNC_LIB $MIEXT_DAMAGE_LIB $MIEXT_SHADOW_LIB $XI_LIB $XKB_LIB $XKB_STUB_LIB $COMPOSITE_LIB $OS_LIB"
     KDRIVE_LIB='$(top_builddir)/hw/kdrive/src/libkdrive.la'
     case $host_os in
 	*linux*)
@@ -2288,6 +2298,7 @@ Xi/Makefile
 xfixes/Makefile
 exa/Makefile
 dri3/Makefile
+present/Makefile
 hw/Makefile
 hw/xfree86/Makefile
 hw/xfree86/common/Makefile
diff --git a/hw/dmx/dmxextension.c b/hw/dmx/dmxextension.c
index d7296ae..c6c6a8e 100644
--- a/hw/dmx/dmxextension.c
+++ b/hw/dmx/dmxextension.c
@@ -68,6 +68,9 @@
  * _any_ header files. */
 extern FontPtr defaultFont;
 
+/* Hack to get Present to build (present requires RandR) */
+RESTYPE RRCrtcType;
+
 /** This routine provides information to the DMX protocol extension
  * about a particular screen. */
 Bool
diff --git a/include/dix-config.h.in b/include/dix-config.h.in
index d96da6a..397ee96 100644
--- a/include/dix-config.h.in
+++ b/include/dix-config.h.in
@@ -255,6 +255,9 @@
 /* Internal define for Xinerama */
 #undef PANORAMIX
 
+/* Support Present extension */
+#undef PRESENT
+
 /* Overall prefix */
 #undef PROJECTROOT
 
diff --git a/include/extinit.h b/include/extinit.h
index bdb149c..fa5f293 100644
--- a/include/extinit.h
+++ b/include/extinit.h
@@ -181,4 +181,9 @@ extern void XvMCExtensionInit(void);
 extern void dri3_extension_init(void);
 #endif
 
+#if defined(PRESENT)
+#include <X11/extensions/presentproto.h>
+#include "presentext.h"
+#endif
+
 #endif
diff --git a/include/xorg-server.h.in b/include/xorg-server.h.in
index 5b3b664..1281b3e 100644
--- a/include/xorg-server.h.in
+++ b/include/xorg-server.h.in
@@ -70,6 +70,9 @@
 /* Internal define for Xinerama */
 #undef PANORAMIX
 
+/* Support Present extension */
+#undef PRESENT
+
 /* Support RANDR extension */
 #undef RANDR
 
diff --git a/mi/miinitext.c b/mi/miinitext.c
index e49948b..6366182 100644
--- a/mi/miinitext.c
+++ b/mi/miinitext.c
@@ -287,7 +287,10 @@ static ExtensionModule staticExtensions[] = {
 #ifdef DPMSExtension
     {DPMSExtensionInit, DPMSExtensionName, &noDPMSExtension},
 #endif
+    {present_extension_init, PRESENT_NAME, NULL},
+#ifdef DRI3
     {dri3_extension_init, DRI3_NAME, NULL},
+#endif
 #ifdef RES
     {ResExtensionInit, XRES_NAME, &noResExtension},
 #endif
diff --git a/present/Makefile.am b/present/Makefile.am
new file mode 100644
index 0000000..7fea669
--- /dev/null
+++ b/present/Makefile.am
@@ -0,0 +1,17 @@
+noinst_LTLIBRARIES = libpresent.la
+AM_CFLAGS = \
+	-DHAVE_XORG_CONFIG_H \
+	@DIX_CFLAGS@ @XORG_CFLAGS@
+
+libpresent_la_SOURCES = \
+	present.h \
+	present.c \
+	present_event.c \
+	present_fake.c \
+	present_fence.c \
+	present_notify.c \
+	present_priv.h \
+	present_request.c \
+	present_screen.c
+
+sdk_HEADERS = present.h presentext.h
diff --git a/present/present.c b/present/present.c
new file mode 100644
index 0000000..4c97ce4
--- /dev/null
+++ b/present/present.c
@@ -0,0 +1,775 @@
+/*
+ * Copyright © 2013 Keith Packard
+ *
+ * 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 the copyright holders not be used in advertising or
+ * publicity pertaining to distribution of the software without specific,
+ * written prior permission.  The 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.
+ */
+
+#ifdef HAVE_XORG_CONFIG_H
+#include <xorg-config.h>
+#endif
+
+#include "present_priv.h"
+#include <gcstruct.h>
+#include <misync.h>
+#include <misyncstr.h>
+#ifdef MONOTONIC_CLOCK
+#include <time.h>
+#endif
+
+static uint64_t         present_event_id;
+static struct xorg_list present_exec_queue;
+static struct xorg_list present_flip_queue;
+
+#if 0
+#define DebugPresent(x) ErrorF x
+#else
+#define DebugPresent(x)
+#endif
+
+/*
+ * Copies the update region from a pixmap to the target drawable
+ */
+static void
+present_copy_region(DrawablePtr drawable,
+                    PixmapPtr pixmap,
+                    RegionPtr update,
+                    int16_t x_off,
+                    int16_t y_off)
+{
+    ScreenPtr   screen = drawable->pScreen;
+    GCPtr       gc;
+
+    gc = GetScratchGC(drawable->depth, screen);
+    if (update) {
+        ChangeGCVal     changes[2];
+
+        changes[0].val = x_off;
+        changes[1].val = y_off;
+        ChangeGC(serverClient, gc,
+                 GCClipXOrigin|GCClipYOrigin,
+                 changes);
+        (*gc->funcs->ChangeClip)(gc, CT_REGION, update, 0);
+    }
+    ValidateGC(drawable, gc);
+    (*gc->ops->CopyArea)(&pixmap->drawable,
+                         drawable,
+                         gc,
+                         0, 0,
+                         pixmap->drawable.width, pixmap->drawable.height,
+                         x_off, y_off);
+    if (update)
+        (*gc->funcs->ChangeClip)(gc, CT_NONE, NULL, 0);
+    FreeScratchGC(gc);
+}
+
+static Bool
+present_check_flip(RRCrtcPtr    crtc,
+                   WindowPtr    window,
+                   PixmapPtr    pixmap,
+                   Bool         sync_flip,
+                   RegionPtr    valid,
+                   int16_t      x_off,
+                   int16_t      y_off)
+{
+    ScreenPtr                   screen = window->drawable.pScreen;
+    WindowPtr                   root = screen->root;
+    present_screen_priv_ptr     screen_priv = present_screen_priv(screen);
+
+    if (!screen_priv)
+        return FALSE;
+
+    if (!screen_priv->info)
+        return FALSE;
+
+    if (!crtc)
+        return FALSE;
+
+    /* Check to see if the driver supports flips at all */
+    if (!screen_priv->info->flip)
+        return FALSE;
+
+    /* Can't pend a flip while unflipping */
+    if (screen_priv->unflip_event_id) {
+        return FALSE;
+    }
+
+    /* Can't have two pending flips at the same time */
+    if (screen_priv->flip_pending) {
+        return FALSE;
+    }
+
+    /* Make sure the window hasn't been redirected with Composite */
+    if (screen->GetWindowPixmap(window) != screen->GetScreenPixmap(screen))
+        return FALSE;
+
+    /* Check for full-screen window */
+    if (!RegionEqual(&window->clipList, &root->winSize)) {
+        return FALSE;
+    }
+
+    /* Source pixmap must align with window exactly */
+    if (x_off || y_off) {
+        return FALSE;
+    }
+
+    /* Make sure the area marked as valid fills the screen */
+    if (valid && !RegionEqual(valid, &root->winSize)) {
+        return FALSE;
+    }
+
+    /* Does the window match the pixmap exactly? */
+    if (window->drawable.x != 0 || window->drawable.y != 0 ||
+#ifdef COMPOSITE
+        window->drawable.x != pixmap->screen_x || window->drawable.y != pixmap->screen_y ||
+#endif
+        window->drawable.width != pixmap->drawable.width ||
+        window->drawable.height != pixmap->drawable.height) {
+        return FALSE;
+    }
+
+    /* Ask the driver for permission */
+    if (screen_priv->info->check_flip) {
+        if (!(*screen_priv->info->check_flip) (crtc, window, pixmap, sync_flip)) {
+            return FALSE;
+        }
+    }
+
+    return TRUE;
+}
+
+static Bool
+present_flip(RRCrtcPtr crtc,
+             uint64_t event_id,
+             uint64_t target_msc,
+             PixmapPtr pixmap,
+             Bool sync_flip)
+{
+    ScreenPtr                   screen = crtc->pScreen;
+    present_screen_priv_ptr     screen_priv = present_screen_priv(screen);
+
+    return (*screen_priv->info->flip) (crtc, event_id, target_msc, pixmap, sync_flip);
+}
+
+static void
+present_vblank_notify(present_vblank_ptr vblank, CARD8 kind, CARD8 mode, uint64_t ust, uint64_t crtc_msc)
+{
+    int         n;
+
+    present_send_complete_notify(vblank->window, kind, mode, vblank->serial, ust, crtc_msc - vblank->msc_offset);
+    for (n = 0; n < vblank->num_notifies; n++) {
+        WindowPtr   window = vblank->notifies[n].window;
+        CARD32      serial = vblank->notifies[n].serial;
+
+        if (window)
+            present_send_complete_notify(window, kind, mode, serial, ust, crtc_msc - vblank->msc_offset);
+    }
+}
+
+static void
+present_pixmap_idle(PixmapPtr pixmap, WindowPtr window, CARD32 serial, struct present_fence *present_fence)
+{
+    present_fence_set_triggered(present_fence);
+    present_send_idle_notify(window, serial, pixmap, present_fence);
+}
+
+RRCrtcPtr
+present_get_crtc(WindowPtr window)
+{
+    ScreenPtr                   screen = window->drawable.pScreen;
+    present_screen_priv_ptr     screen_priv = present_screen_priv(screen);
+
+    if (!screen_priv)
+        return NULL;
+
+    if (!screen_priv->info)
+        return NULL;
+
+    return (*screen_priv->info->get_crtc)(window);
+}
+
+uint32_t
+present_query_capabilities(RRCrtcPtr crtc)
+{
+    present_screen_priv_ptr     screen_priv;
+
+    if (!crtc)
+        return 0;
+
+    screen_priv = present_screen_priv(crtc->pScreen);
+
+    if (!screen_priv)
+        return 0;
+
+    if (!screen_priv->info)
+        return 0;
+
+    return screen_priv->info->capabilities;
+}
+
+static int
+present_get_ust_msc(WindowPtr window, RRCrtcPtr crtc, uint64_t *ust, uint64_t *msc)
+{
+    ScreenPtr                   screen = window->drawable.pScreen;
+    present_screen_priv_ptr     screen_priv = present_screen_priv(screen);
+
+    if (crtc == NULL)
+        return present_fake_get_ust_msc(screen, ust, msc);
+    else
+        return (*screen_priv->info->get_ust_msc)(crtc, ust, msc);
+}
+
+static void
+present_flush(WindowPtr window)
+{
+    ScreenPtr                   screen = window->drawable.pScreen;
+    present_screen_priv_ptr     screen_priv = present_screen_priv(screen);
+
+    if (!screen_priv)
+        return;
+
+    if (!screen_priv->info)
+        return;
+
+    (*screen_priv->info->flush) (window);
+}
+
+static int
+present_queue_vblank(ScreenPtr screen,
+                     RRCrtcPtr crtc,
+                     uint64_t event_id,
+                     uint64_t msc)
+{
+    Bool                        ret;
+
+    if (crtc == NULL)
+        ret = present_fake_queue_vblank(screen, event_id, msc);
+    else
+    {
+        present_screen_priv_ptr     screen_priv = present_screen_priv(screen);
+        ret = (*screen_priv->info->queue_vblank) (crtc, event_id, msc);
+    }
+    return ret;
+}
+
+static uint64_t
+present_window_to_crtc_msc(WindowPtr window, RRCrtcPtr crtc, uint64_t window_msc, uint64_t new_msc)
+{
+    present_window_priv_ptr     window_priv = present_get_window_priv(window, TRUE);
+
+    if (crtc != window_priv->crtc) {
+        uint64_t        old_ust, old_msc;
+
+        /* The old CRTC may have been turned off, in which case
+         * we'll just use whatever previous MSC we'd seen from this CRTC
+         */
+
+        if (present_get_ust_msc(window, window_priv->crtc, &old_ust, &old_msc) != Success)
+            old_msc = window_priv->msc;
+
+        window_priv->msc_offset += new_msc - old_msc;
+        window_priv->crtc = crtc;
+    }
+
+    return window_msc + window_priv->msc_offset;
+}
+
+static void
+present_flip_idle(ScreenPtr screen)
+{
+    present_screen_priv_ptr screen_priv = present_screen_priv(screen);
+
+    if (screen_priv->flip_pixmap) {
+        present_pixmap_idle(screen_priv->flip_pixmap, screen_priv->flip_window,
+                            screen_priv->flip_serial, screen_priv->flip_idle_fence);
+        present_fence_destroy(screen_priv->flip_idle_fence);
+        dixDestroyPixmap(screen_priv->flip_pixmap, screen_priv->flip_pixmap->drawable.id);
+        screen_priv->flip_crtc = NULL;
+        screen_priv->flip_window = NULL;
+        screen_priv->flip_serial = 0;
+        screen_priv->flip_pixmap = NULL;
+        screen_priv->flip_idle_fence = NULL;
+    }
+}
+
+static void
+present_unflip(ScreenPtr screen)
+{
+    present_screen_priv_ptr screen_priv = present_screen_priv(screen);
+
+    assert (!screen_priv->unflip_event_id);
+    assert (!screen_priv->flip_pending);
+
+    /* Update the screen pixmap with the current flip pixmap contents
+     */
+    if (screen_priv->flip_pixmap) {
+        present_copy_region(&screen->GetScreenPixmap(screen)->drawable,
+                            screen_priv->flip_pixmap,
+                            NULL, 0, 0);
+    }
+    screen_priv->unflip_event_id = ++present_event_id;
+    DebugPresent(("u %lld\n", screen_priv->unflip_event_id));
+    (*screen_priv->info->unflip) (screen, screen_priv->unflip_event_id);
+}
+
+static void
+present_execute(present_vblank_ptr vblank, uint64_t ust, uint64_t crtc_msc);
+
+static void
+present_flip_notify(present_vblank_ptr vblank, uint64_t ust, uint64_t crtc_msc)
+{
+    WindowPtr                   window = vblank->window;
+    ScreenPtr                   screen = window->drawable.pScreen;
+    present_screen_priv_ptr     screen_priv = present_screen_priv(screen);
+
+    DebugPresent(("\tn %p %8lld: %08lx -> %08lx\n", vblank, vblank->target_msc,
+           vblank->pixmap ? vblank->pixmap->drawable.id : 0,
+                  vblank->window->drawable.id));
+
+    assert (vblank == screen_priv->flip_pending);
+
+    present_flip_idle(screen);
+
+    /* Transfer reference for pixmap and fence from vblank to screen_priv */
+    screen_priv->flip_crtc = vblank->crtc;
+    screen_priv->flip_window = vblank->window;
+    screen_priv->flip_serial = vblank->serial;
+    screen_priv->flip_pixmap = vblank->pixmap;
+    screen_priv->flip_idle_fence = vblank->idle_fence;
+
+    vblank->pixmap = NULL;
+    vblank->idle_fence = NULL;
+
+    screen_priv->flip_pending = NULL;
+
+    if (vblank->abort_flip)
+        present_unflip(screen);
+
+    if (!vblank->window_destroyed)
+        present_vblank_notify(vblank, PresentCompleteKindPixmap, PresentCompleteModeFlip, ust, crtc_msc);
+    present_vblank_destroy(vblank);
+}
+
+void
+present_event_notify(uint64_t event_id, uint64_t ust, uint64_t msc)
+{
+    present_vblank_ptr  vblank, tmp;
+    int                 s;
+
+    xorg_list_for_each_entry_safe(vblank, tmp, &present_exec_queue, event_queue) {
+        if (vblank->event_id == event_id) {
+            xorg_list_del(&vblank->event_queue);
+            present_execute(vblank, ust, msc);
+            return;
+        }
+    }
+    xorg_list_for_each_entry_safe(vblank, tmp, &present_flip_queue, event_queue) {
+        if (vblank->event_id == event_id) {
+            xorg_list_del(&vblank->event_queue);
+            present_flip_notify(vblank, ust, msc);
+            return;
+        }
+    }
+
+    for (s = 0; s < screenInfo.numScreens; s++) {
+        ScreenPtr               screen = screenInfo.screens[s];
+        present_screen_priv_ptr screen_priv = present_screen_priv(screen);
+
+        if (event_id == screen_priv->unflip_event_id) {
+            DebugPresent(("\tun %lld\n", event_id));
+            screen_priv->unflip_event_id = 0;
+            present_flip_idle(screen);
+        }
+    }
+}
+
+/*
+ * 'window' is being reconfigured. Check to see if it is involved
+ * in flipping and clean up as necessary
+ */
+void
+present_check_flip_window (WindowPtr window)
+{
+    ScreenPtr                   screen = window->drawable.pScreen;
+    present_screen_priv_ptr     screen_priv = present_screen_priv(screen);
+    present_window_priv_ptr     window_priv = present_window_priv(window);
+    present_vblank_ptr          flip_pending = screen_priv->flip_pending;
+    present_vblank_ptr          vblank;
+
+    /* If this window hasn't ever been used with Present, it can't be
+     * flipping
+     */
+    if (!window_priv)
+        return;
+
+    if (screen_priv->unflip_event_id)
+        return;
+
+    if (flip_pending) {
+        /*
+         * Check pending flip
+         */
+        if (flip_pending->window == window) {
+            if (!present_check_flip(flip_pending->crtc, window, flip_pending->pixmap,
+                                    flip_pending->sync_flip, NULL, 0, 0))
+                flip_pending->abort_flip = TRUE;
+        }
+    } else {
+        /*
+         * Check current flip
+         */
+        if (window == screen_priv->flip_window) {
+            if (!present_check_flip(screen_priv->flip_crtc, window, screen_priv->flip_pixmap, FALSE, NULL, 0, 0))
+                present_unflip(screen);
+        }
+    }
+
+    /* Now check any queued vblanks */
+    xorg_list_for_each_entry(vblank, &window_priv->vblank, window_list) {
+        if (vblank->flip && !present_check_flip(vblank->crtc, window, vblank->pixmap, FALSE, NULL, 0, 0))
+            vblank->flip = FALSE;
+    }
+}
+
+/*
+ * Once the required MSC has been reached, execute the pending request.
+ *
+ * For requests to actually present something, either blt contents to
+ * the screen or queue a frame buffer swap.
+ *
+ * For requests to just get the current MSC/UST combo, skip that part and
+ * go straight to event delivery
+ */
+
+static void
+present_execute(present_vblank_ptr vblank, uint64_t ust, uint64_t crtc_msc)
+{
+    WindowPtr                   window = vblank->window;
+    present_screen_priv_ptr     screen_priv = present_screen_priv(window->drawable.pScreen);
+
+    if (vblank->wait_fence) {
+        /* XXX check fence, queue if not ready */
+    }
+
+    xorg_list_del(&vblank->event_queue);
+    if (vblank->pixmap) {
+
+        if (vblank->flip && screen_priv->flip_pending == NULL && !screen_priv->unflip_event_id) {
+
+            DebugPresent(("\tf %p %8lld: %08lx -> %08lx\n", vblank, crtc_msc, vblank->pixmap->drawable.id, vblank->window->drawable.id));
+            /* Prepare to flip by removing from the window/screen lists
+             * and sticking it into the flip_pending field
+             */
+            screen_priv->flip_pending = vblank;
+            xorg_list_del(&vblank->window_list);
+
+            xorg_list_add(&vblank->event_queue, &present_flip_queue);
+            /* Try to flip
+             */
+            if (present_flip(vblank->crtc, vblank->event_id, vblank->target_msc, vblank->pixmap, vblank->sync_flip))
+                return;
+
+            xorg_list_del(&vblank->event_queue);
+            /* Oops, flip failed. Clear the flip_pending field
+              */
+            screen_priv->flip_pending = NULL;
+            vblank->flip = FALSE;
+        }
+        DebugPresent(("\tc %p %8lld: %08lx -> %08lx\n", vblank, crtc_msc, vblank->pixmap->drawable.id, vblank->window->drawable.id));
+        if (screen_priv->flip_pending) {
+
+            /* Check pending flip
+             */
+            if (window == screen_priv->flip_pending->window)
+                screen_priv->flip_pending->abort_flip = TRUE;
+        } else if (!screen_priv->unflip_event_id) {
+
+            /* Check current flip
+             */
+            if (window == screen_priv->flip_window)
+                present_unflip(window->drawable.pScreen);
+        }
+        present_copy_region(&window->drawable, vblank->pixmap, vblank->update, vblank->x_off, vblank->y_off);
+
+        /* present_copy_region sticks the region into a scratch GC,
+         * which is then freed, freeing the region
+         */
+        vblank->update = NULL;
+        present_flush(window);
+
+        present_pixmap_idle(vblank->pixmap, vblank->window, vblank->serial, vblank->idle_fence);
+    }
+    present_vblank_notify(vblank, vblank->kind, PresentCompleteModeCopy, ust, crtc_msc);
+    present_vblank_destroy(vblank);
+}
+
+int
+present_pixmap(WindowPtr window,
+               PixmapPtr pixmap,
+               CARD32 serial,
+               RegionPtr valid,
+               RegionPtr update,
+               int16_t x_off,
+               int16_t y_off,
+               RRCrtcPtr target_crtc,
+               SyncFence *wait_fence,
+               SyncFence *idle_fence,
+               uint32_t options,
+               uint64_t window_msc,
+               uint64_t divisor,
+               uint64_t remainder,
+               present_notify_ptr notifies,
+               int num_notifies)
+{
+    uint64_t                    ust;
+    uint64_t                    target_msc;
+    uint64_t                    crtc_msc;
+    int                         ret;
+    present_vblank_ptr          vblank;
+    ScreenPtr                   screen = window->drawable.pScreen;
+    present_window_priv_ptr     window_priv = present_get_window_priv(window, TRUE);
+    present_screen_priv_ptr     screen_priv = present_screen_priv(screen);
+
+    if (!window_priv)
+        return BadAlloc;
+
+    if (!target_crtc) {
+        /* Update the CRTC if we have a pixmap or we don't have a CRTC
+         */
+        if (!pixmap)
+            target_crtc = window_priv->crtc;
+
+        if (!target_crtc)
+            target_crtc = present_get_crtc(window);
+    }
+
+    present_get_ust_msc(window, target_crtc, &ust, &crtc_msc);
+
+    target_msc = present_window_to_crtc_msc(window, target_crtc, window_msc, crtc_msc);
+
+    /* Stash the current MSC away in case we need it later
+     */
+    window_priv->msc = crtc_msc;
+
+    /* Adjust target_msc to match modulus
+     */
+    if (crtc_msc >= target_msc) {
+        if (divisor != 0) {
+            target_msc = crtc_msc - (crtc_msc % divisor) + remainder;
+            if (target_msc <= crtc_msc)
+                target_msc += divisor;
+        } else
+            target_msc = crtc_msc;
+    }
+
+    /*
+     * Look for a matching presentation already on the list and
+     * don't bother doing the previous one if this one will overwrite it
+     * in the same frame
+     */
+
+    if (!update) {
+        xorg_list_for_each_entry(vblank, &window_priv->vblank, window_list) {
+
+            if (!vblank->pixmap)
+                continue;
+
+            if (vblank->crtc != target_crtc || vblank->target_msc != target_msc)
+                continue;
+
+            present_pixmap_idle(vblank->pixmap, vblank->window, vblank->serial, vblank->idle_fence);
+            present_fence_destroy(vblank->idle_fence);
+            dixDestroyPixmap(vblank->pixmap, vblank->pixmap->drawable.id);
+
+            vblank->pixmap = NULL;
+            vblank->idle_fence = NULL;
+        }
+    }
+
+    vblank = calloc (1, sizeof (present_vblank_rec));
+    if (!vblank)
+        return BadAlloc;
+
+    xorg_list_append(&vblank->window_list, &window_priv->vblank);
+    xorg_list_init(&vblank->event_queue);
+
+    vblank->screen = screen;
+    vblank->window = window;
+    vblank->pixmap = pixmap;
+    vblank->event_id = ++present_event_id;
+    if (pixmap) {
+        vblank->kind = PresentCompleteKindPixmap;
+        pixmap->refcnt++;
+    } else
+        vblank->kind = PresentCompleteKindNotifyMSC;
+
+    vblank->serial = serial;
+
+    if (valid) {
+        vblank->valid = RegionDuplicate(valid);
+        if (!vblank->valid)
+            goto no_mem;
+    }
+    if (update) {
+        vblank->update = RegionDuplicate(update);
+        if (!vblank->update)
+            goto no_mem;
+    }
+
+    vblank->x_off = x_off;
+    vblank->y_off = y_off;
+    vblank->target_msc = target_msc;
+    vblank->crtc = target_crtc;
+    vblank->msc_offset = window_priv->msc_offset;
+    vblank->notifies = notifies;
+    vblank->num_notifies = num_notifies;
+
+    if (!screen_priv->info || !(screen_priv->info->capabilities & PresentCapabilityAsync))
+        vblank->sync_flip = TRUE;
+
+    if (pixmap && present_check_flip (target_crtc, window, pixmap, vblank->sync_flip, valid, x_off, y_off)) {
+        vblank->flip = TRUE;
+        if (vblank->sync_flip)
+            target_msc--;
+    }
+
+    if (idle_fence) {
+        vblank->idle_fence = present_fence_create(idle_fence);
+        if (!vblank->idle_fence)
+            goto no_mem;
+    }
+
+    if (pixmap)
+        DebugPresent(("q %p %8lld: %08lx -> %08lx (crtc %d)\n",
+                      vblank, target_msc, vblank->pixmap->drawable.id, vblank->window->drawable.id, target_crtc ? 1 : 0));
+
+    xorg_list_add(&vblank->event_queue, &present_exec_queue);
+    if (target_msc >= crtc_msc) {
+        ret = present_queue_vblank(screen, target_crtc, vblank->event_id, target_msc);
+        if (ret != Success) {
+            xorg_list_del(&vblank->event_queue);
+            goto failure;
+        }
+    } else
+        present_execute(vblank, ust, crtc_msc);
+
+    return Success;
+
+no_mem:
+    ret = BadAlloc;
+failure:
+    vblank->notifies = NULL;
+    present_vblank_destroy(vblank);
+    return ret;
+}
+
+void
+present_abort_vblank(ScreenPtr screen, RRCrtcPtr crtc, uint64_t event_id, uint64_t msc)
+{
+    present_vblank_ptr  vblank, tmp;
+
+    if (crtc == NULL)
+        present_fake_abort_vblank(screen, event_id, msc);
+    else
+    {
+        present_screen_priv_ptr     screen_priv = present_screen_priv(screen);
+
+        (*screen_priv->info->abort_vblank) (crtc, event_id, msc);
+    }
+
+    xorg_list_for_each_entry_safe(vblank, tmp, &present_exec_queue, event_queue) {
+        if (vblank->event_id == event_id) {
+            xorg_list_del(&vblank->event_queue);
+            return;
+        }
+    }
+    xorg_list_for_each_entry_safe(vblank, tmp, &present_flip_queue, event_queue) {
+        if (vblank->event_id == event_id) {
+            xorg_list_del(&vblank->event_queue);
+            return;
+        }
+    }
+}
+
+int
+present_notify_msc(WindowPtr window,
+                   CARD32 serial,
+                   uint64_t target_msc,
+                   uint64_t divisor,
+                   uint64_t remainder)
+{
+    return present_pixmap(window,
+                          NULL,
+                          serial,
+                          NULL, NULL,
+                          0, 0,
+                          NULL,
+                          NULL, NULL,
+                          0,
+                          target_msc, divisor, remainder, NULL, 0);
+}
+
+void
+present_flip_destroy(ScreenPtr screen)
+{
+    present_screen_priv_ptr     screen_priv = present_screen_priv(screen);
+
+    /* XXX this needs to be synchronous for server reset */
+
+    /* Do the actual cleanup once the flip has been performed by the hardware */
+    if (screen_priv->flip_pending)
+        screen_priv->flip_pending->abort_flip = TRUE;
+}
+
+void
+present_vblank_destroy(present_vblank_ptr vblank)
+{
+    /* Remove vblank from window and screen lists */
+    xorg_list_del(&vblank->window_list);
+
+    DebugPresent(("\td %p %8lld: %08lx -> %08lx\n", vblank, vblank->target_msc,
+                  vblank->pixmap ? vblank->pixmap->drawable.id : 0,
+                  vblank->window->drawable.id));
+
+    /* Drop pixmap reference */
+    if (vblank->pixmap)
+        dixDestroyPixmap(vblank->pixmap, vblank->pixmap->drawable.id);
+
+    /* Free regions */
+    if (vblank->valid)
+        RegionDestroy(vblank->valid);
+    if (vblank->update)
+        RegionDestroy(vblank->update);
+
+    if (vblank->idle_fence)
+        present_fence_destroy(vblank->idle_fence);
+
+    if (vblank->notifies)
+        present_destroy_notifies(vblank->notifies, vblank->num_notifies);
+
+    free(vblank);
+}
+
+Bool
+present_init(void)
+{
+    xorg_list_init(&present_exec_queue);
+    xorg_list_init(&present_flip_queue);
+    present_fake_queue_init();
+    return TRUE;
+}
diff --git a/present/present.h b/present/present.h
new file mode 100644
index 0000000..6a451fb
--- /dev/null
+++ b/present/present.h
@@ -0,0 +1,118 @@
+/*
+ * Copyright © 2013 Keith Packard
+ *
+ * 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 the copyright holders not be used in advertising or
+ * publicity pertaining to distribution of the software without specific,
+ * written prior permission.  The 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.
+ */
+
+#ifndef _PRESENT_H_
+#define _PRESENT_H_
+
+#include <X11/extensions/presentproto.h>
+#include "randrstr.h"
+#include "presentext.h"
+
+typedef struct present_vblank present_vblank_rec, *present_vblank_ptr;
+
+/* Return the current CRTC for 'window'.
+ */
+typedef RRCrtcPtr (*present_get_crtc_ptr) (WindowPtr window);
+
+/* Return the current ust/msc for 'crtc'
+ */
+typedef int (*present_get_ust_msc_ptr) (RRCrtcPtr crtc, uint64_t *ust, uint64_t *msc);
+
+/* Queue callback on 'crtc' for time 'msc'. Call present_event_notify with 'event_id'
+ * at or after 'msc'. Return false if it didn't happen (which might occur if 'crtc'
+ * is not currently generating vblanks).
+ */
+typedef Bool (*present_queue_vblank_ptr) (RRCrtcPtr crtc,
+                                          uint64_t event_id,
+                                          uint64_t msc);
+
+/* Abort pending vblank. The extension is no longer interested in
+ * 'event_id' which was to be notified at 'msc'. If possible, the
+ * driver is free to de-queue the notification.
+ */
+typedef void (*present_abort_vblank_ptr) (RRCrtcPtr crtc, uint64_t event_id, uint64_t msc);
+
+/* Flush pending drawing on 'window' to the hardware.
+ */
+typedef void (*present_flush_ptr) (WindowPtr window);
+
+/* Check if 'pixmap' is suitable for flipping to 'window'.
+ */
+typedef Bool (*present_check_flip_ptr) (RRCrtcPtr crtc, WindowPtr window, PixmapPtr pixmap, Bool sync_flip);
+
+/* Flip pixmap, return false if it didn't happen.
+ *
+ * 'crtc' is to be used for any necessary synchronization.
+ *
+ * 'sync_flip' requests that the flip be performed at the next
+ * vertical blank interval to avoid tearing artifacts. If false, the
+ * flip should be performed as soon as possible.
+ *
+ * present_event_notify should be called with 'event_id' when the flip
+ * occurs
+ */
+typedef Bool (*present_flip_ptr) (RRCrtcPtr crtc,
+                                  uint64_t event_id,
+                                  uint64_t target_msc,
+                                  PixmapPtr pixmap,
+                                  Bool sync_flip);
+
+/* "unflip" back to the regular screen scanout buffer
+ *
+ * present_event_notify should be called with 'event_id' when the unflip occurs.
+ */
+typedef void (*present_unflip_ptr) (ScreenPtr screen,
+                                    uint64_t event_id);
+
+#define PRESENT_SCREEN_INFO_VERSION        0
+
+typedef struct present_screen_info {
+    uint32_t                            version;
+
+    present_get_crtc_ptr                get_crtc;
+    present_get_ust_msc_ptr             get_ust_msc;
+    present_queue_vblank_ptr            queue_vblank;
+    present_abort_vblank_ptr            abort_vblank;
+    present_flush_ptr                   flush;
+    uint32_t                            capabilities;
+    present_check_flip_ptr              check_flip;
+    present_flip_ptr                    flip;
+    present_unflip_ptr                  unflip;
+
+} present_screen_info_rec, *present_screen_info_ptr;
+
+/*
+ * Called when 'event_id' occurs. 'ust' and 'msc' indicate when the
+ * event actually happened
+ */
+extern _X_EXPORT void
+present_event_notify(uint64_t event_id, uint64_t ust, uint64_t msc);
+
+/* 'crtc' has been turned off, so any pending events will never occur.
+ */
+extern _X_EXPORT void
+present_event_abandon(RRCrtcPtr crtc);
+
+extern _X_EXPORT Bool
+present_screen_init(ScreenPtr screen, present_screen_info_ptr info);
+
+#endif /* _PRESENT_H_ */
diff --git a/present/present_event.c b/present/present_event.c
new file mode 100644
index 0000000..a30bc82
--- /dev/null
+++ b/present/present_event.c
@@ -0,0 +1,239 @@
+/*
+ * Copyright © 2013 Keith Packard
+ *
+ * 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 the copyright holders not be used in advertising or
+ * publicity pertaining to distribution of the software without specific,
+ * written prior permission.  The 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.
+ */
+
+#ifdef HAVE_XORG_CONFIG_H
+#include <xorg-config.h>
+#endif
+
+#include "present_priv.h"
+
+#include "present_priv.h"
+
+RESTYPE present_event_type;
+
+static int
+present_free_event(pointer data, XID id)
+{
+    present_event_ptr present_event = (present_event_ptr) data;
+    present_window_priv_ptr window_priv = present_window_priv(present_event->window);
+    present_event_ptr *previous, current;
+
+    for (previous = &window_priv->events; (current = *previous); previous = &current->next) {
+        if (current == present_event) {
+            *previous = present_event->next;
+            break;
+        }
+    }
+    free((pointer) present_event);
+    return 1;
+
+}
+
+void
+present_free_events(WindowPtr window)
+{
+    present_window_priv_ptr window_priv = present_window_priv(window);
+    present_event_ptr event;
+
+    if (!window_priv)
+        return;
+
+    while ((event = window_priv->events))
+        FreeResource(event->id, RT_NONE);
+}
+
+static void
+present_event_swap(xGenericEvent *from, xGenericEvent *to)
+{
+    *to = *from;
+    swaps(&to->sequenceNumber);
+    swapl(&to->length);
+    swaps(&to->evtype);
+    switch (from->evtype) {
+    case PresentConfigureNotify: {
+        xPresentConfigureNotify *c = (xPresentConfigureNotify *) to;
+
+        swapl(&c->eid);
+        swapl(&c->window);
+        swaps(&c->x);
+        swaps(&c->y);
+        swaps(&c->width);
+        swaps(&c->height);
+        swaps(&c->off_x);
+        swaps(&c->off_y);
+        swaps(&c->pixmap_width);
+        swaps(&c->pixmap_height);
+        swapl(&c->pixmap_flags);
+        break;
+    }
+    case PresentCompleteNotify:
+    {
+        xPresentCompleteNotify *c = (xPresentCompleteNotify *) to;
+        swapl(&c->eid);
+        swapl(&c->window);
+        swapl(&c->serial);
+        swapll(&c->ust);
+        swapll(&c->msc);
+    }
+    case PresentIdleNotify:
+    {
+        xPresentIdleNotify *c = (xPresentIdleNotify *) to;
+        swapl(&c->eid);
+        swapl(&c->window);
+        swapl(&c->serial);
+        swapl(&c->idle_fence);
+    }
+    }
+}
+
+void
+present_send_config_notify(WindowPtr window, int x, int y, int w, int h, int bw, WindowPtr sibling)
+{
+    present_window_priv_ptr window_priv = present_window_priv(window);
+
+    if (window_priv) {
+        xPresentConfigureNotify cn = {
+            .type = GenericEvent,
+            .extension = present_request,
+            .length = (sizeof(xPresentConfigureNotify) - 32) >> 2,
+            .evtype = PresentConfigureNotify,
+            .eid = 0,
+            .window = window->drawable.id,
+            .x = x,
+            .y = y,
+            .width = w,
+            .height = h,
+            .off_x = 0,
+            .off_y = 0,
+            .pixmap_width = w,
+            .pixmap_height = h,
+            .pixmap_flags = 0
+        };
+        present_event_ptr event;
+
+        for (event = window_priv->events; event; event = event->next) {
+            if (event->mask & (1 << PresentConfigureNotify)) {
+                cn.eid = event->id;
+                WriteEventsToClient(event->client, 1, (xEvent *) &cn);
+            }
+        }
+    }
+}
+
+void
+present_send_complete_notify(WindowPtr window, CARD8 kind, CARD8 mode, CARD32 serial, uint64_t ust, uint64_t msc)
+{
+    present_window_priv_ptr window_priv = present_window_priv(window);
+
+    if (window_priv) {
+        xPresentCompleteNotify cn = {
+            .type = GenericEvent,
+            .extension = present_request,
+            .length = (sizeof(xPresentCompleteNotify) - 32) >> 2,
+            .evtype = PresentCompleteNotify,
+            .kind = kind,
+            .mode = mode,
+            .eid = 0,
+            .window = window->drawable.id,
+            .serial = serial,
+            .ust = ust,
+            .msc = msc,
+        };
+        present_event_ptr event;
+
+        for (event = window_priv->events; event; event = event->next) {
+            if (event->mask & PresentCompleteNotifyMask) {
+                cn.eid = event->id;
+                WriteEventsToClient(event->client, 1, (xEvent *) &cn);
+            }
+        }
+    }
+}
+
+void
+present_send_idle_notify(WindowPtr window, CARD32 serial, PixmapPtr pixmap, struct present_fence *idle_fence)
+{
+    present_window_priv_ptr window_priv = present_window_priv(window);
+
+    if (window_priv) {
+        xPresentIdleNotify in = {
+            .type = GenericEvent,
+            .extension = present_request,
+            .length = (sizeof(xPresentIdleNotify) - 32) >> 2,
+            .evtype = PresentIdleNotify,
+            .eid = 0,
+            .window = window->drawable.id,
+            .serial = serial,
+            .pixmap = pixmap->drawable.id,
+            .idle_fence = present_fence_id(idle_fence)
+        };
+        present_event_ptr event;
+
+        for (event = window_priv->events; event; event = event->next) {
+            if (event->mask & PresentIdleNotifyMask) {
+                in.eid = event->id;
+                WriteEventsToClient(event->client, 1, (xEvent *) &in);
+            }
+        }
+    }
+}
+
+int
+present_select_input(ClientPtr client, XID eid, WindowPtr window, CARD32 mask)
+{
+    present_window_priv_ptr window_priv = present_get_window_priv(window, mask != 0);
+    present_event_ptr event;
+
+    if (!window_priv) {
+        if (mask)
+            return BadAlloc;
+        return Success;
+    }
+
+    event = calloc (1, sizeof (present_event_rec));
+    if (!event)
+        return BadAlloc;
+
+    event->client = client;
+    event->window = window;
+    event->id = eid;
+    event->mask = mask;
+
+    event->next = window_priv->events;
+    window_priv->events = event;
+
+    if (!AddResource(event->id, present_event_type, (pointer) event))
+        return BadAlloc;
+
+    return Success;
+}
+
+Bool
+present_event_init(void)
+{
+    present_event_type = CreateNewResourceType(present_free_event, "PresentEvent");
+    if (!present_event_type)
+        return FALSE;
+
+    GERegisterExtension(present_request, present_event_swap);
+    return TRUE;
+}
diff --git a/present/present_fake.c b/present/present_fake.c
new file mode 100644
index 0000000..a677592
--- /dev/null
+++ b/present/present_fake.c
@@ -0,0 +1,140 @@
+/*
+ * Copyright © 2013 Keith Packard
+ *
+ * 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 the copyright holders not be used in advertising or
+ * publicity pertaining to distribution of the software without specific,
+ * written prior permission.  The 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.
+ */
+
+#ifdef HAVE_XORG_CONFIG_H
+#include <xorg-config.h>
+#endif
+
+#include "present_priv.h"
+#include "list.h"
+
+static struct xorg_list fake_vblank_queue;
+
+typedef struct present_fake_vblank {
+    struct xorg_list            list;
+    uint64_t                    event_id;
+    OsTimerPtr                  timer;
+    ScreenPtr                   screen;
+} present_fake_vblank_rec, *present_fake_vblank_ptr;
+
+int
+present_fake_get_ust_msc(ScreenPtr screen, uint64_t *ust, uint64_t *msc)
+{
+    present_screen_priv_ptr screen_priv = present_screen_priv(screen);
+
+    *ust = GetTimeInMicros();
+    *msc = *ust / screen_priv->fake_interval;
+    return Success;
+}
+
+static void
+present_fake_notify(ScreenPtr screen, uint64_t event_id)
+{
+    uint64_t                    ust, msc;
+
+    present_fake_get_ust_msc(screen, &ust, &msc);
+    present_event_notify(event_id, ust, msc);
+}
+
+static CARD32
+present_fake_do_timer(OsTimerPtr timer,
+                      CARD32 time,
+                      pointer arg)
+{
+    present_fake_vblank_ptr     fake_vblank = arg;
+
+    present_fake_notify(fake_vblank->screen, fake_vblank->event_id);
+    xorg_list_del(&fake_vblank->list);
+    free(fake_vblank);
+    return 0;
+}
+
+void
+present_fake_abort_vblank(ScreenPtr screen, uint64_t event_id, uint64_t msc)
+{
+    present_fake_vblank_ptr     fake_vblank, tmp;
+
+    xorg_list_for_each_entry_safe(fake_vblank, tmp, &fake_vblank_queue, list) {
+        if (fake_vblank->event_id == event_id) {
+            TimerCancel(fake_vblank->timer);
+            xorg_list_del(&fake_vblank->list);
+            free (fake_vblank);
+            break;
+        }
+    }
+}
+
+int
+present_fake_queue_vblank(ScreenPtr     screen,
+                          uint64_t      event_id,
+                          uint64_t      msc)
+{
+    present_screen_priv_ptr     screen_priv = present_screen_priv(screen);
+    uint64_t                    ust = msc * screen_priv->fake_interval;
+    uint64_t                    now = GetTimeInMicros();
+    INT32                       delay = ((int64_t) (ust - now)) / 1000;
+    present_fake_vblank_ptr     fake_vblank;
+
+    if (delay <= 0) {
+        present_fake_notify(screen, event_id);
+        return Success;
+    }
+
+    fake_vblank = calloc (1, sizeof (present_fake_vblank_rec));
+    if (!fake_vblank)
+        return BadAlloc;
+
+    fake_vblank->screen = screen;
+    fake_vblank->event_id = event_id;
+    fake_vblank->timer = TimerSet(NULL, 0, delay, present_fake_do_timer, fake_vblank);
+    if (!fake_vblank->timer) {
+        free(fake_vblank);
+        return BadAlloc;
+    }
+
+    xorg_list_add(&fake_vblank->list, &fake_vblank_queue);
+
+    return Success;
+}
+
+void
+present_fake_screen_init(ScreenPtr screen)
+{
+    present_screen_priv_ptr screen_priv = present_screen_priv(screen);
+
+    /* For screens with hardware vblank support, the fake code
+     * will be used for off-screen windows and while screens are blanked,
+     * in which case we want a slow interval here
+     *
+     * Otherwise, pretend that the screen runs at 60Hz
+     */
+    if (screen_priv->info && screen_priv->info->get_crtc)
+        screen_priv->fake_interval = 1000000;
+    else
+        screen_priv->fake_interval = 16667;
+}
+
+void
+present_fake_queue_init(void)
+{
+    xorg_list_init(&fake_vblank_queue);
+}
diff --git a/present/present_fence.c b/present/present_fence.c
new file mode 100644
index 0000000..db5efca
--- /dev/null
+++ b/present/present_fence.c
@@ -0,0 +1,112 @@
+/*
+ * Copyright © 2013 Keith Packard
+ *
+ * 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 the copyright holders not be used in advertising or
+ * publicity pertaining to distribution of the software without specific,
+ * written prior permission.  The 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.
+ */
+
+#ifdef HAVE_XORG_CONFIG_H
+#include <xorg-config.h>
+#endif
+
+#include "present_priv.h"
+#include <gcstruct.h>
+#include <misync.h>
+#include <misyncstr.h>
+
+/*
+ * Wraps SyncFence objects so we can add a SyncTrigger to find out
+ * when the SyncFence gets destroyed and clean up appropriately
+ */
+
+struct present_fence {
+    SyncTrigger         trigger;
+    SyncFence           *fence;
+};
+
+/*
+ * SyncTrigger callbacks
+ */
+static Bool
+present_fence_sync_check_trigger(SyncTrigger *trigger, XSyncValue oldval)
+{
+    return FALSE;
+}
+
+static void
+present_fence_sync_trigger_fired(SyncTrigger *trigger)
+{
+}
+
+static void
+present_fence_sync_counter_destroyed(SyncTrigger *trigger)
+{
+    struct present_fence        *present_fence = container_of(trigger, struct present_fence, trigger);
+
+    present_fence->fence = NULL;
+}
+
+struct present_fence *
+present_fence_create(SyncFence *fence)
+{
+    struct present_fence        *present_fence;
+
+    present_fence = calloc (1, sizeof (struct present_fence));
+    if (!present_fence)
+        return NULL;
+
+    present_fence->fence = fence;
+    present_fence->trigger.pSync = (SyncObject *) fence;
+    present_fence->trigger.CheckTrigger = present_fence_sync_check_trigger;
+    present_fence->trigger.TriggerFired = present_fence_sync_trigger_fired;
+    present_fence->trigger.CounterDestroyed = present_fence_sync_counter_destroyed;
+
+    if (SyncAddTriggerToSyncObject(&present_fence->trigger) != Success) {
+        free (present_fence);
+        return NULL;
+    }
+    return present_fence;
+}
+
+void
+present_fence_destroy(struct present_fence *present_fence)
+{
+    if (present_fence) {
+        if (present_fence->fence)
+            SyncDeleteTriggerFromSyncObject(&present_fence->trigger);
+        free(present_fence);
+    }
+}
+
+void
+present_fence_set_triggered(struct present_fence *present_fence)
+{
+    if (present_fence)
+        if (present_fence->fence)
+            (*present_fence->fence->funcs.SetTriggered) (present_fence->fence);
+}
+
+XID
+present_fence_id(struct present_fence *present_fence)
+{
+    if (!present_fence)
+        return None;
+    if (!present_fence->fence)
+        return None;
+    return present_fence->fence->sync.id;
+}
diff --git a/present/present_notify.c b/present/present_notify.c
new file mode 100644
index 0000000..e272e08
--- /dev/null
+++ b/present/present_notify.c
@@ -0,0 +1,114 @@
+/*
+ * Copyright © 2013 Keith Packard
+ *
+ * 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 the copyright holders not be used in advertising or
+ * publicity pertaining to distribution of the software without specific,
+ * written prior permission.  The 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.
+ */
+
+#ifdef HAVE_XORG_CONFIG_H
+#include <xorg-config.h>
+#endif
+
+#include "present_priv.h"
+
+/*
+ * Mark all pending notifies for 'window' as invalid when
+ * the window is destroyed
+ */
+
+void
+present_clear_window_notifies(WindowPtr window)
+{
+    present_notify_ptr          notify;
+    present_window_priv_ptr     window_priv = present_window_priv(window);
+
+    if (!window_priv)
+        return;
+
+    xorg_list_for_each_entry(notify, &window_priv->notifies, window_list) {
+        notify->window = NULL;
+    }
+}
+
+/*
+ * 'notify' is being freed; remove it from the window's notify list
+ */
+
+void
+present_free_window_notify(present_notify_ptr notify)
+{
+    xorg_list_del(&notify->window_list);
+}
+
+/*
+ * 'notify' is new; add it to the specified window
+ */
+
+int
+present_add_window_notify(present_notify_ptr notify)
+{
+    WindowPtr                   window = notify->window;
+    present_window_priv_ptr     window_priv = present_get_window_priv(window, TRUE);
+
+    if (!window_priv)
+        return BadAlloc;
+
+    xorg_list_add(&notify->window_list, &window_priv->notifies);
+    return Success;
+}
+
+int
+present_create_notifies(ClientPtr client, int num_notifies, xPresentNotify *x_notifies, present_notify_ptr *p_notifies)
+{
+    present_notify_ptr  notifies;
+    int                 i;
+    int                 added = 0;
+    int                 status;
+
+    notifies = calloc (num_notifies, sizeof (present_notify_rec));
+    if (!notifies)
+        return BadAlloc;
+
+    for (i = 0; i < num_notifies; i++) {
+        status = dixLookupWindow(&notifies[i].window, x_notifies[i].window, client, DixGetAttrAccess);
+        if (status != Success)
+            goto bail;
+
+        notifies[i].serial = x_notifies[i].serial;
+        status = present_add_window_notify(&notifies[i]);
+        if (status != Success)
+            goto bail;
+
+        added = i;
+    }
+    return Success;
+
+bail:
+    present_destroy_notifies(notifies, added);
+    return status;
+}
+
+void
+present_destroy_notifies(present_notify_ptr notifies, int num_notifies)
+{
+    int i;
+    for (i = 0; i < num_notifies; i++)
+        present_free_window_notify(&notifies[i]);
+
+    free(notifies);
+}
diff --git a/present/present_priv.h b/present/present_priv.h
new file mode 100644
index 0000000..a92b62a
--- /dev/null
+++ b/present/present_priv.h
@@ -0,0 +1,288 @@
+/*
+ * Copyright © 2013 Keith Packard
+ *
+ * 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 the copyright holders not be used in advertising or
+ * publicity pertaining to distribution of the software without specific,
+ * written prior permission.  The 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.
+ */
+
+#ifndef _PRESENT_PRIV_H_
+#define _PRESENT_PRIV_H_
+
+#include <X11/X.h>
+#include "scrnintstr.h"
+#include "misc.h"
+#include "list.h"
+#include "windowstr.h"
+#include "dixstruct.h"
+#include "present.h"
+#include <syncsdk.h>
+#include <syncsrv.h>
+#include <xfixes.h>
+#include <randrstr.h>
+
+extern int present_request;
+
+extern DevPrivateKeyRec present_screen_private_key;
+
+typedef struct present_fence *present_fence_ptr;
+
+typedef struct present_notify present_notify_rec, *present_notify_ptr;
+
+struct present_notify {
+    struct xorg_list    window_list;
+    WindowPtr           window;
+    CARD32              serial;
+};
+
+struct present_vblank {
+    struct xorg_list    window_list;
+    struct xorg_list    event_queue;
+    ScreenPtr           screen;
+    WindowPtr           window;
+    PixmapPtr           pixmap;
+    RegionPtr           valid;
+    RegionPtr           update;
+    RRCrtcPtr           crtc;
+    uint32_t            serial;
+    int16_t             x_off;
+    int16_t             y_off;
+    CARD16              kind;
+    uint64_t            event_id;
+    uint64_t            target_msc;
+    uint64_t            msc_offset;
+    present_fence_ptr   idle_fence;
+    present_fence_ptr   wait_fence;
+    present_notify_ptr  notifies;
+    int                 num_notifies;
+    Bool                flip;
+    Bool                sync_flip;
+    Bool                abort_flip;
+
+    Bool                window_destroyed;
+};
+
+typedef struct present_screen_priv {
+    CloseScreenProcPtr          CloseScreen;
+    ConfigNotifyProcPtr         ConfigNotify;
+    DestroyWindowProcPtr        DestroyWindow;
+    ClipNotifyProcPtr           ClipNotify;
+
+    present_vblank_ptr          flip_pending;
+    uint64_t                    unflip_event_id;
+
+    uint32_t                    fake_interval;
+
+    /* Currently active flipped pixmap and fence */
+    RRCrtcPtr                   flip_crtc;
+    WindowPtr                   flip_window;
+    uint32_t                    flip_serial;
+    PixmapPtr                   flip_pixmap;
+    present_fence_ptr           flip_idle_fence;
+
+    present_screen_info_ptr     info;
+} present_screen_priv_rec, *present_screen_priv_ptr;
+
+#define wrap(priv,real,mem,func) {\
+    priv->mem = real->mem; \
+    real->mem = func; \
+}
+
+#define unwrap(priv,real,mem) {\
+    real->mem = priv->mem; \
+}
+
+static inline present_screen_priv_ptr
+present_screen_priv(ScreenPtr screen)
+{
+    return (present_screen_priv_ptr)dixLookupPrivate(&(screen)->devPrivates, &present_screen_private_key);
+}
+
+/*
+ * Each window has a list of clients and event masks
+ */
+typedef struct present_event *present_event_ptr;
+
+typedef struct present_event {
+    present_event_ptr next;
+    ClientPtr client;
+    WindowPtr window;
+    XID id;
+    int mask;
+} present_event_rec;
+
+typedef struct present_window_priv {
+    present_event_ptr      events;
+    RRCrtcPtr              crtc;        /* Last reported CRTC from get_ust_msc */
+    uint64_t               msc_offset;
+    uint64_t               msc;         /* Last reported MSC from the current crtc */
+    struct xorg_list       vblank;
+    struct xorg_list       notifies;
+} present_window_priv_rec, *present_window_priv_ptr;
+
+extern DevPrivateKeyRec present_window_private_key;
+
+static inline present_window_priv_ptr
+present_window_priv(WindowPtr window)
+{
+    return (present_window_priv_ptr)dixGetPrivate(&(window)->devPrivates, &present_window_private_key);
+}
+
+present_window_priv_ptr
+present_get_window_priv(WindowPtr window, Bool create);
+
+extern RESTYPE present_event_type;
+
+/*
+ * present.c
+ */
+int
+present_pixmap(WindowPtr window,
+               PixmapPtr pixmap,
+               CARD32 serial,
+               RegionPtr valid,
+               RegionPtr update,
+               int16_t x_off,
+               int16_t y_off,
+               RRCrtcPtr target_crtc,
+               SyncFence *wait_fence,
+               SyncFence *idle_fence,
+               uint32_t options,
+               uint64_t target_msc,
+               uint64_t divisor,
+               uint64_t remainder,
+               present_notify_ptr notifies,
+               int num_notifies);
+
+int
+present_notify_msc(WindowPtr window,
+                   CARD32 serial,
+                   uint64_t target_msc,
+                   uint64_t divisor,
+                   uint64_t remainder);
+
+void
+present_abort_vblank(ScreenPtr screen, RRCrtcPtr crtc, uint64_t event_id, uint64_t msc);
+
+void
+present_vblank_destroy(present_vblank_ptr vblank);
+
+void
+present_flip_destroy(ScreenPtr screen);
+
+void
+present_check_flip_window(WindowPtr window);
+
+RRCrtcPtr
+present_get_crtc(WindowPtr window);
+
+uint32_t
+present_query_capabilities(RRCrtcPtr crtc);
+
+Bool
+present_init(void);
+
+/*
+ * present_event.c
+ */
+
+void
+present_free_events(WindowPtr window);
+
+void
+present_send_config_notify(WindowPtr window, int x, int y, int w, int h, int bw, WindowPtr sibling);
+
+void
+present_send_complete_notify(WindowPtr window, CARD8 kind, CARD8 mode, CARD32 serial, uint64_t ust, uint64_t msc);
+
+void
+present_send_idle_notify(WindowPtr window, CARD32 serial, PixmapPtr pixmap, present_fence_ptr idle_fence);
+
+int
+present_select_input(ClientPtr client,
+                     CARD32 eid,
+                     WindowPtr window,
+                     CARD32 event_mask);
+
+Bool
+present_event_init(void);
+
+/*
+ * present_fake.c
+ */
+int
+present_fake_get_ust_msc(ScreenPtr screen, uint64_t *ust, uint64_t *msc);
+
+int
+present_fake_queue_vblank(ScreenPtr screen, uint64_t event_id, uint64_t msc);
+
+void
+present_fake_abort_vblank(ScreenPtr screen, uint64_t event_id, uint64_t msc);
+
+void
+present_fake_screen_init(ScreenPtr screen);
+
+void
+present_fake_queue_init(void);
+
+/*
+ * present_fence.c
+ */
+struct present_fence *
+present_fence_create(SyncFence *sync_fence);
+
+void
+present_fence_destroy(struct present_fence *present_fence);
+
+void
+present_fence_set_triggered(struct present_fence *present_fence);
+
+XID
+present_fence_id(struct present_fence *present_fence);
+
+/*
+ * present_notify.c
+ */
+void
+present_clear_window_notifies(WindowPtr window);
+
+void
+present_free_window_notify(present_notify_ptr notify);
+
+int
+present_add_window_notify(present_notify_ptr notify);
+
+int
+present_create_notifies(ClientPtr client, int num_notifies, xPresentNotify *x_notifies, present_notify_ptr *p_notifies);
+
+void
+present_destroy_notifies(present_notify_ptr notifies, int num_notifies);
+
+/*
+ * present_request.c
+ */
+int
+proc_present_dispatch(ClientPtr client);
+
+int
+sproc_present_dispatch(ClientPtr client);
+
+/*
+ * present_screen.c
+ */
+
+#endif /*  _PRESENT_PRIV_H_ */
diff --git a/present/present_request.c b/present/present_request.c
new file mode 100644
index 0000000..095fa2d
--- /dev/null
+++ b/present/present_request.c
@@ -0,0 +1,330 @@
+/*
+ * Copyright © 2013 Keith Packard
+ *
+ * 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 the copyright holders not be used in advertising or
+ * publicity pertaining to distribution of the software without specific,
+ * written prior permission.  The 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.
+ */
+
+#ifdef HAVE_XORG_CONFIG_H
+#include <xorg-config.h>
+#endif
+
+#include "present_priv.h"
+#include "randrstr.h"
+
+static int
+proc_present_query_version(ClientPtr client)
+{
+    REQUEST(xPresentQueryVersionReq);
+    xPresentQueryVersionReply rep = {
+        .type = X_Reply,
+        .sequenceNumber = client->sequence,
+        .length = 0,
+        .majorVersion = PRESENT_MAJOR,
+        .minorVersion = PRESENT_MINOR
+    };
+
+    REQUEST_SIZE_MATCH(xPresentQueryVersionReq);
+    (void) stuff;
+    if (client->swapped) {
+        swaps(&rep.sequenceNumber);
+        swapl(&rep.length);
+        swapl(&rep.majorVersion);
+        swapl(&rep.minorVersion);
+    }
+    WriteToClient(client, sizeof(rep), &rep);
+    return Success;
+}
+
+#define VERIFY_FENCE_OR_NONE(fence_ptr, fence_id, client, access) do {  \
+        if ((fence_id) == None)                                         \
+            (fence_ptr) = NULL;                                         \
+        else {                                                          \
+            int __rc__ = SyncVerifyFence(&fence_ptr, fence_id, client, access); \
+            if (__rc__ != Success)                                      \
+                return __rc__;                                          \
+        }                                                               \
+    } while (0)
+
+#define VERIFY_CRTC_OR_NONE(crtc_ptr, crtc_id, client, access) do {     \
+        if ((crtc_id) == None)                                          \
+            (crtc_ptr) = NULL;                                          \
+        else {                                                          \
+            VERIFY_RR_CRTC(crtc_id, crtc_ptr, access);                  \
+        }                                                               \
+    } while (0)
+
+static int
+proc_present_pixmap(ClientPtr client)
+{
+    REQUEST(xPresentPixmapReq);
+    WindowPtr           window;
+    PixmapPtr           pixmap;
+    RegionPtr           valid = NULL;
+    RegionPtr           update = NULL;
+    SyncFence           *wait_fence;
+    SyncFence           *idle_fence;
+    RRCrtcPtr           target_crtc;
+    int                 ret;
+    int                 nnotifies;
+    present_notify_ptr  notifies = NULL;
+
+    REQUEST_AT_LEAST_SIZE(xPresentPixmapReq);
+    ret = dixLookupWindow(&window, stuff->window, client, DixWriteAccess);
+    if (ret != Success)
+        return ret;
+    ret = dixLookupResourceByType((pointer *) &pixmap, stuff->pixmap, RT_PIXMAP, client, DixReadAccess);
+    if (ret != Success)
+        return ret;
+
+    if (window->drawable.depth != pixmap->drawable.depth)
+        return BadMatch;
+
+    VERIFY_REGION_OR_NONE(valid, stuff->valid, client, DixReadAccess);
+    VERIFY_REGION_OR_NONE(update, stuff->update, client, DixReadAccess);
+
+    VERIFY_CRTC_OR_NONE(target_crtc, stuff->target_crtc, client, DixReadAccess);
+
+    VERIFY_FENCE_OR_NONE(wait_fence, stuff->wait_fence, client, DixReadAccess);
+    VERIFY_FENCE_OR_NONE(idle_fence, stuff->idle_fence, client, DixWriteAccess);
+
+    if (stuff->options & ~(PresentAllOptions)) {
+        client->errorValue = stuff->options;
+        return BadValue;
+    }
+
+    /*
+     * Check to see if remainder is sane
+     */
+    if (stuff->divisor == 0) {
+        if (stuff->remainder != 0) {
+            client->errorValue = (CARD32) stuff->remainder;
+            return BadValue;
+        }
+    } else {
+        if (stuff->remainder >= stuff->divisor) {
+            client->errorValue = (CARD32) stuff->remainder;
+            return BadValue;
+        }
+    }
+
+    nnotifies = (client->req_len << 2) - sizeof (xPresentPixmapReq);
+    if (nnotifies % sizeof (xPresentNotify))
+        return BadLength;
+
+    nnotifies /= sizeof (xPresentNotify);
+    if (nnotifies) {
+        ret = present_create_notifies(client, nnotifies, (xPresentNotify *) (stuff + 1), &notifies);
+        if (ret != Success)
+            return ret;
+    }
+
+    ret = present_pixmap(window, pixmap, stuff->serial, valid, update,
+                         stuff->x_off, stuff->y_off, target_crtc,
+                         wait_fence, idle_fence, stuff->options,
+                         stuff->target_msc, stuff->divisor, stuff->remainder, notifies, nnotifies);
+    if (ret != Success)
+        present_destroy_notifies(notifies, nnotifies);
+    return ret;
+}
+
+static int
+proc_present_notify_msc(ClientPtr client)
+{
+    REQUEST(xPresentNotifyMSCReq);
+    WindowPtr   window;
+    int         rc;
+
+    REQUEST_SIZE_MATCH(xPresentNotifyMSCReq);
+    rc = dixLookupWindow(&window, stuff->window, client, DixReadAccess);
+    if (rc != Success)
+        return rc;
+
+    /*
+     * Check to see if remainder is sane
+     */
+    if (stuff->divisor == 0) {
+        if (stuff->remainder != 0) {
+            client->errorValue = (CARD32) stuff->remainder;
+            return BadValue;
+        }
+    } else {
+        if (stuff->remainder >= stuff->divisor) {
+            client->errorValue = (CARD32) stuff->remainder;
+            return BadValue;
+        }
+    }
+
+    return present_notify_msc(window, stuff->serial,
+                              stuff->target_msc, stuff->divisor, stuff->remainder);
+}
+
+static int
+proc_present_select_input (ClientPtr client)
+{
+    REQUEST(xPresentSelectInputReq);
+    WindowPtr window;
+    int rc;
+
+    REQUEST_SIZE_MATCH(xPresentSelectInputReq);
+
+    LEGAL_NEW_RESOURCE(stuff->eid, client);
+
+    rc = dixLookupWindow(&window, stuff->window, client, DixGetAttrAccess);
+    if (rc != Success)
+        return rc;
+
+    if (stuff->eventMask & ~PresentAllEvents) {
+        client->errorValue = stuff->eventMask;
+        return BadValue;
+    }
+    return present_select_input(client, stuff->eid, window, stuff->eventMask);
+}
+
+static int
+proc_present_query_capabilities (ClientPtr client)
+{
+    REQUEST(xPresentQueryCapabilitiesReq);
+    xPresentQueryCapabilitiesReply rep = {
+        .type = X_Reply,
+        .sequenceNumber = client->sequence,
+        .length = 0,
+    };
+    WindowPtr   window;
+    RRCrtcPtr   crtc = NULL;
+    int         r;
+
+    r = dixLookupWindow(&window, stuff->target, client, DixGetAttrAccess);
+    switch (r) {
+    case Success:
+        crtc = present_get_crtc(window);
+        break;
+    case BadWindow:
+        VERIFY_RR_CRTC(stuff->target, crtc, DixGetAttrAccess);
+        break;
+    default:
+        return r;
+    }
+
+    rep.capabilities = present_query_capabilities(crtc);
+
+    if (client->swapped) {
+        swaps(&rep.sequenceNumber);
+        swapl(&rep.length);
+        swapl(&rep.capabilities);
+    }
+    WriteToClient(client, sizeof(rep), &rep);
+    return Success;
+}
+
+int (*proc_present_vector[PresentNumberRequests]) (ClientPtr) = {
+    proc_present_query_version,            /* 0 */
+    proc_present_pixmap,                   /* 1 */
+    proc_present_notify_msc,               /* 2 */
+    proc_present_select_input,             /* 3 */
+    proc_present_query_capabilities,       /* 4 */
+};
+
+int
+proc_present_dispatch(ClientPtr client)
+{
+    REQUEST(xReq);
+    if (stuff->data >= PresentNumberRequests || !proc_present_vector[stuff->data])
+        return BadRequest;
+    return (*proc_present_vector[stuff->data]) (client);
+}
+
+static int
+sproc_present_query_version(ClientPtr client)
+{
+    REQUEST(xPresentQueryVersionReq);
+
+    swaps(&stuff->length);
+    swapl(&stuff->majorVersion);
+    swapl(&stuff->minorVersion);
+    return (*proc_present_vector[stuff->presentReqType]) (client);
+}
+
+static int
+sproc_present_pixmap(ClientPtr client)
+{
+    REQUEST(xPresentPixmapReq);
+
+    swaps(&stuff->length);
+    swapl(&stuff->window);
+    swapl(&stuff->pixmap);
+    swapl(&stuff->valid);
+    swapl(&stuff->update);
+    swaps(&stuff->x_off);
+    swaps(&stuff->y_off);
+    swapll(&stuff->target_msc);
+    swapll(&stuff->divisor);
+    swapll(&stuff->remainder);
+    swapl(&stuff->idle_fence);
+    return (*proc_present_vector[stuff->presentReqType]) (client);
+}
+
+static int
+sproc_present_notify_msc(ClientPtr client)
+{
+    REQUEST(xPresentNotifyMSCReq);
+
+    swaps(&stuff->length);
+    swapl(&stuff->window);
+    swapll(&stuff->target_msc);
+    swapll(&stuff->divisor);
+    swapll(&stuff->remainder);
+    return (*proc_present_vector[stuff->presentReqType]) (client);
+}
+
+static int
+sproc_present_select_input (ClientPtr client)
+{
+    REQUEST(xPresentSelectInputReq);
+
+    swaps(&stuff->length);
+    swapl(&stuff->window);
+    swapl(&stuff->eventMask);
+    return (*proc_present_vector[stuff->presentReqType]) (client);
+}
+
+static int
+sproc_present_query_capabilities (ClientPtr client)
+{
+    REQUEST(xPresentQueryCapabilitiesReq);
+    swaps(&stuff->length);
+    swapl(&stuff->target);
+    return (*proc_present_vector[stuff->presentReqType]) (client);
+}
+
+int (*sproc_present_vector[PresentNumberRequests]) (ClientPtr) = {
+    sproc_present_query_version,           /* 0 */
+    sproc_present_pixmap,                  /* 1 */
+    sproc_present_notify_msc,              /* 2 */
+    sproc_present_select_input,            /* 3 */
+    sproc_present_query_capabilities,      /* 4 */
+};
+
+int
+sproc_present_dispatch(ClientPtr client)
+{
+    REQUEST(xReq);
+    if (stuff->data >= PresentNumberRequests || !sproc_present_vector[stuff->data])
+        return BadRequest;
+    return (*sproc_present_vector[stuff->data]) (client);
+}
diff --git a/present/present_screen.c b/present/present_screen.c
new file mode 100644
index 0000000..50b2b2d
--- /dev/null
+++ b/present/present_screen.c
@@ -0,0 +1,231 @@
+/*
+ * Copyright © 2013 Keith Packard
+ *
+ * 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 the copyright holders not be used in advertising or
+ * publicity pertaining to distribution of the software without specific,
+ * written prior permission.  The 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.
+ */
+
+#ifdef HAVE_XORG_CONFIG_H
+#include <xorg-config.h>
+#endif
+
+#include "present_priv.h"
+
+int present_request;
+DevPrivateKeyRec present_screen_private_key;
+DevPrivateKeyRec present_window_private_key;
+
+/*
+ * Get a pointer to a present window private, creating if necessary
+ */
+present_window_priv_ptr
+present_get_window_priv(WindowPtr window, Bool create)
+{
+    present_window_priv_ptr window_priv = present_window_priv(window);
+
+    if (!create || window_priv != NULL)
+        return window_priv;
+    window_priv = calloc (1, sizeof (present_window_priv_rec));
+    if (!window_priv)
+        return NULL;
+    xorg_list_init(&window_priv->vblank);
+    xorg_list_init(&window_priv->notifies);
+    dixSetPrivate(&window->devPrivates, &present_window_private_key, window_priv);
+    return window_priv;
+}
+
+/*
+ * Hook the close screen function to clean up our screen private
+ */
+static Bool
+present_close_screen(ScreenPtr screen)
+{
+    present_screen_priv_ptr screen_priv = present_screen_priv(screen);
+
+    present_flip_destroy(screen);
+
+    unwrap(screen_priv, screen, CloseScreen);
+    (*screen->CloseScreen) (screen);
+    free(screen_priv);
+    return TRUE;
+}
+
+/*
+ * Free any queued presentations for this window
+ */
+static void
+present_free_window_vblank(WindowPtr window)
+{
+    present_window_priv_ptr     window_priv = present_window_priv(window);
+    present_vblank_ptr          vblank, tmp;
+
+    xorg_list_for_each_entry_safe(vblank, tmp, &window_priv->vblank, window_list) {
+        present_abort_vblank(window->drawable.pScreen, vblank->crtc, vblank->event_id, vblank->target_msc);
+        present_vblank_destroy(vblank);
+    }
+}
+
+/*
+ * Clean up any pending or current flips for this window
+ */
+static void
+present_clear_window_flip(WindowPtr window)
+{
+    ScreenPtr                   screen = window->drawable.pScreen;
+    present_screen_priv_ptr     screen_priv = present_screen_priv(screen);
+    present_vblank_ptr          flip_pending = screen_priv->flip_pending;
+
+    if (flip_pending && flip_pending->window == window) {
+        assert (flip_pending->abort_flip);
+        flip_pending->window_destroyed = TRUE;
+    }
+    if (screen_priv->flip_window == window)
+        screen_priv->flip_window = NULL;
+}
+
+/*
+ * Hook the close window function to clean up our window private
+ */
+static Bool
+present_destroy_window(WindowPtr window)
+{
+    Bool ret;
+    ScreenPtr screen = window->drawable.pScreen;
+    present_screen_priv_ptr screen_priv = present_screen_priv(screen);
+    present_window_priv_ptr window_priv = present_window_priv(window);
+
+    if (window_priv) {
+        present_clear_window_notifies(window);
+        present_free_events(window);
+        present_free_window_vblank(window);
+        present_clear_window_flip(window);
+        free(window_priv);
+    }
+    unwrap(screen_priv, screen, DestroyWindow);
+    if (screen->DestroyWindow)
+        ret = screen->DestroyWindow (window);
+    else
+        ret = TRUE;
+    wrap(screen_priv, screen, DestroyWindow, present_destroy_window);
+    return ret;
+}
+
+/*
+ * Hook the config notify screen function to deliver present config notify events
+ */
+static int
+present_config_notify(WindowPtr window,
+                   int x, int y, int w, int h, int bw,
+                   WindowPtr sibling)
+{
+    int ret;
+    ScreenPtr screen = window->drawable.pScreen;
+    present_screen_priv_ptr screen_priv = present_screen_priv(screen);
+
+    present_send_config_notify(window, x, y, w, h, bw, sibling);
+
+    unwrap(screen_priv, screen, ConfigNotify);
+    if (screen->ConfigNotify)
+        ret = screen->ConfigNotify (window, x, y, w, h, bw, sibling);
+    else
+        ret = 0;
+    wrap(screen_priv, screen, ConfigNotify, present_config_notify);
+    return ret;
+}
+
+/*
+ * Hook the clip notify screen function to un-flip as necessary
+ */
+
+static void
+present_clip_notify(WindowPtr window, int dx, int dy)
+{
+    ScreenPtr screen = window->drawable.pScreen;
+    present_screen_priv_ptr screen_priv = present_screen_priv(screen);
+
+    present_check_flip_window(window);
+    unwrap(screen_priv, screen, ClipNotify)
+    if (screen->ClipNotify)
+        screen->ClipNotify (window, dx, dy);
+    wrap(screen_priv, screen, ClipNotify, present_clip_notify);
+}
+
+/*
+ * Initialize a screen for use with present
+ */
+int
+present_screen_init(ScreenPtr screen, present_screen_info_ptr info)
+{
+    if (!dixRegisterPrivateKey(&present_screen_private_key, PRIVATE_SCREEN, 0))
+        return FALSE;
+
+    if (!dixRegisterPrivateKey(&present_window_private_key, PRIVATE_WINDOW, 0))
+        return FALSE;
+
+    if (!present_screen_priv(screen)) {
+        present_screen_priv_ptr screen_priv = calloc(1, sizeof (present_screen_priv_rec));
+        if (!screen_priv)
+            return FALSE;
+
+        wrap(screen_priv, screen, CloseScreen, present_close_screen);
+        wrap(screen_priv, screen, DestroyWindow, present_destroy_window);
+        wrap(screen_priv, screen, ConfigNotify, present_config_notify);
+        wrap(screen_priv, screen, ClipNotify, present_clip_notify);
+
+        screen_priv->info = info;
+
+        dixSetPrivate(&screen->devPrivates, &present_screen_private_key, screen_priv);
+
+        present_fake_screen_init(screen);
+    }
+
+    return TRUE;
+}
+
+/*
+ * Initialize the present extension
+ */
+void
+present_extension_init(void)
+{
+    ExtensionEntry *extension;
+    int i;
+
+    extension = AddExtension(PRESENT_NAME, PresentNumberEvents, PresentNumberErrors,
+                             proc_present_dispatch, sproc_present_dispatch,
+                             NULL, StandardMinorOpcode);
+    if (!extension)
+        goto bail;
+
+    present_request = extension->base;
+
+    if (!present_init())
+        goto bail;
+
+    if (!present_event_init())
+        goto bail;
+
+    for (i = 0; i < screenInfo.numScreens; i++) {
+        if (!present_screen_init(screenInfo.screens[i], NULL))
+            goto bail;
+    }
+    return;
+
+bail:
+    FatalError("Cannot initialize Present extension");
+}
diff --git a/present/presentext.h b/present/presentext.h
new file mode 100644
index 0000000..f177f55
--- /dev/null
+++ b/present/presentext.h
@@ -0,0 +1,29 @@
+/*
+ * Copyright © 2013 Keith Packard
+ *
+ * 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 the copyright holders not be used in advertising or
+ * publicity pertaining to distribution of the software without specific,
+ * written prior permission.  The 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.
+ */
+
+#ifndef _PRESENTEXT_H_
+#define _PRESENTEXT_H_
+
+extern _X_EXPORT void
+present_extension_init(void);
+
+#endif /* _PRESENTEXT_H_ */
commit 563138298868f62501875d3016f03469dcffaad0
Author: Keith Packard <keithp at keithp.com>
Date:   Tue Apr 9 19:59:39 2013 -0700

    dri3: Add DRI3 extension
    
    Adds DRM compatible fences using futexes.
    Uses FD passing to get pixmaps from DRM applications.
    
    Signed-off-by: Keith Packard <keithp at keithp.com>
    Reviewed-by: Adam Jackson <ajax at redhat.com>

diff --git a/Makefile.am b/Makefile.am
index 7be4271..7a8fc5b 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -17,6 +17,10 @@ if RECORD
 RECORD_DIR=record
 endif
 
+if DRI3
+DRI3_DIR=dri3
+endif
+
 SUBDIRS = \
 	doc \
 	man \
@@ -38,6 +42,7 @@ SUBDIRS = \
 	damageext \
 	$(COMPOSITE_DIR) \
 	$(GLX_DIR) \
+	$(DRI3_DIR) \
 	exa \
 	config \
 	hw \
diff --git a/Xext/sync.c b/Xext/sync.c
index b2ee92e..126ce43 100644
--- a/Xext/sync.c
+++ b/Xext/sync.c
@@ -141,7 +141,7 @@ SyncCheckWarnIsCounter(const SyncObject * pSync, const char *warning)
  *  interested in the counter.  The two functions below are used to
  *  delete and add triggers on this list.
  */
-static void
+void
 SyncDeleteTriggerFromSyncObject(SyncTrigger * pTrigger)
 {
     SyncTriggerList *pCur;
@@ -184,7 +184,7 @@ SyncDeleteTriggerFromSyncObject(SyncTrigger * pTrigger)
     }
 }
 
-static int
+int
 SyncAddTriggerToSyncObject(SyncTrigger * pTrigger)
 {
     SyncTriggerList *pCur;
@@ -916,6 +916,34 @@ SyncCreate(ClientPtr client, XID id, unsigned char type)
     return pSync;
 }
 
+int
+SyncCreateFenceFromFD(ClientPtr client, DrawablePtr pDraw, XID id, int fd, BOOL initially_triggered)
+{
+    SyncFence  *pFence;
+    int         status;
+
+    pFence = (SyncFence *) SyncCreate(client, id, SYNC_FENCE);
+    if (!pFence)
+        return BadAlloc;
+
+    status = miSyncInitFenceFromFD(pDraw, pFence, fd, initially_triggered);
+    if (status != Success) {
+        miSyncDestroyFence(pFence);
+        return status;
+    }
+
+    if (!AddResource(id, RTFence, (pointer) pFence))
+        return BadAlloc;
+
+    return Success;
+}
+
+int
+SyncFDFromFence(ClientPtr client, DrawablePtr pDraw, SyncFence *pFence)
+{
+    return miSyncFDFromFence(pDraw, pFence);
+}
+
 static SyncCounter *
 SyncCreateCounter(ClientPtr client, XSyncCounter id, CARD64 initialvalue)
 {
diff --git a/Xext/syncsrv.h b/Xext/syncsrv.h
index c68229f..45fca04 100644
--- a/Xext/syncsrv.h
+++ b/Xext/syncsrv.h
@@ -136,4 +136,17 @@ extern void SyncDestroySystemCounter(pointer pCounter);
 
 extern SyncCounter *SyncInitDeviceIdleTime(DeviceIntPtr dev);
 extern void SyncRemoveDeviceIdleTime(SyncCounter *counter);
+
+int
+SyncCreateFenceFromFD(ClientPtr client, DrawablePtr pDraw, XID id, int fd, BOOL initially_triggered);
+
+int
+SyncFDFromFence(ClientPtr client, DrawablePtr pDraw, SyncFence *fence);
+
+void
+SyncDeleteTriggerFromSyncObject(SyncTrigger * pTrigger);
+
+int
+SyncAddTriggerToSyncObject(SyncTrigger * pTrigger);
+
 #endif                          /* _SYNCSRV_H_ */
diff --git a/configure.ac b/configure.ac
index d29f170..546790d 100644
--- a/configure.ac
+++ b/configure.ac
@@ -613,6 +613,7 @@ AC_ARG_ENABLE(xdm-auth-1,     AS_HELP_STRING([--disable-xdm-auth-1], [Build XDM-
 AC_ARG_ENABLE(glx,            AS_HELP_STRING([--disable-glx], [Build GLX extension (default: enabled)]), [GLX=$enableval], [GLX=yes])
 AC_ARG_ENABLE(dri,            AS_HELP_STRING([--enable-dri], [Build DRI extension (default: auto)]), [DRI=$enableval])
 AC_ARG_ENABLE(dri2,           AS_HELP_STRING([--enable-dri2], [Build DRI2 extension (default: auto)]), [DRI2=$enableval], [DRI2=auto])
+AC_ARG_ENABLE(dri3,           AS_HELP_STRING([--enable-dri3], [Build DRI3 extension (default: auto)]), [DRI3=$enableval], [DRI3=auto])
 AC_ARG_ENABLE(xinerama,	      AS_HELP_STRING([--disable-xinerama], [Build Xinerama extension (default: enabled)]), [XINERAMA=$enableval], [XINERAMA=yes])
 AC_ARG_ENABLE(xf86vidmode,    AS_HELP_STRING([--disable-xf86vidmode], [Build XF86VidMode extension (default: auto)]), [XF86VIDMODE=$enableval], [XF86VIDMODE=auto])
 AC_ARG_ENABLE(xace,           AS_HELP_STRING([--disable-xace], [Build X-ACE extension (default: enabled)]), [XACE=$enableval], [XACE=yes])
@@ -715,6 +716,7 @@ case $host_os in
 		CONFIG_UDEV_KMS=no
 		DGA=no
 		DRI2=no
+		DRI3=no
 		INT10MODULE=no
 		PCI=no
 		VGAHW=no
@@ -732,6 +734,7 @@ case $host_os in
 		VBE=no
 		DRM=no
 		DRI2=no
+		DRI3=no
 
 		if test x$XQUARTZ = xauto; then
 			AC_CACHE_CHECK([whether to build Xquartz],xorg_cv_Carbon_framework,[
@@ -781,6 +784,7 @@ SCRNSAVERPROTO="scrnsaverproto >= 1.1"
 RESOURCEPROTO="resourceproto >= 1.2.0"
 DRIPROTO="xf86driproto >= 2.1.0"
 DRI2PROTO="dri2proto >= 2.8"
+DRI3PROTO="dri3proto >= 1.0"
 XINERAMAPROTO="xineramaproto"
 BIGFONTPROTO="xf86bigfontproto >= 1.2.0"
 DGAPROTO="xf86dgaproto >= 2.0.99.1"
@@ -1113,7 +1117,22 @@ case "$DRI2,$HAVE_DRI2PROTO" in
 esac
 AM_CONDITIONAL(DRI2, test "x$DRI2" = xyes)
 
-if test "x$DRI" = xyes || test "x$DRI2" = xyes || test "x$CONFIG_UDEV_KMS" = xyes; then
+PKG_CHECK_MODULES([DRI3PROTO], $DRI3PROTO,
+                  [HAVE_DRI3PROTO=yes], [HAVE_DRI3PROTO=no])
+case "$DRI3,$HAVE_DRI3PROTO" in
+	yes,no)
+		AC_MSG_ERROR([DRI3 requested, but dri3proto not found.])
+		;;
+	yes,yes | auto,yes)
+		AC_DEFINE(DRI3, 1, [Build DRI3 extension])
+		DRI3=yes
+		DRI3_LIB='$(top_builddir)/dri3/libdri3.la'
+		SDK_REQUIRED_MODULES="$SDK_REQUIRED_MODULES $DRI3PROTO"
+		;;
+esac
+AM_CONDITIONAL(DRI3, test "x$DRI3" = xyes)
+
+if test "x$DRI" = xyes || test "x$DRI2" = xyes || test "x$DRI3" = xyes || test "x$CONFIG_UDEV_KMS" = xyes; then
 	if test "x$DRM" = xyes; then
 		AC_DEFINE(WITH_LIBDRM, 1, [Building with libdrm support])
 		PKG_CHECK_MODULES([LIBDRM], $LIBDRM)
@@ -1306,6 +1325,7 @@ if test "x$XDMAUTH" = xyes; then
 		XDMCP_MODULES="xdmcp"
 	fi
 fi
+REQUIRED_LIBS="$REQUIRED_LIBS xshmfence"
 
 AC_DEFINE_DIR(COMPILEDDEFAULTFONTPATH, FONTPATH, [Default font path])
 AC_DEFINE_DIR(SERVER_MISC_CONFIG_PATH, SERVERCONFIG, [Server miscellaneous config path])
@@ -1577,7 +1597,7 @@ AC_MSG_RESULT([$XVFB])
 AM_CONDITIONAL(XVFB, [test "x$XVFB" = xyes])
 
 if test "x$XVFB" = xyes; then
-	XVFB_LIBS="$FB_LIB $FIXES_LIB $XEXT_LIB $DBE_LIB $RECORD_LIB $GLX_LIBS $RANDR_LIB $RENDER_LIB $DAMAGE_LIB $MIEXT_SYNC_LIB $MIEXT_DAMAGE_LIB $MIEXT_SHADOW_LIB $XI_LIB $XKB_LIB $XKB_STUB_LIB $COMPOSITE_LIB"
+	XVFB_LIBS="$FB_LIB $FIXES_LIB $XEXT_LIB $DBE_LIB $RECORD_LIB $GLX_LIBS $RANDR_LIB $RENDER_LIB $DAMAGE_LIB $DRI3_LIB $MIEXT_SYNC_LIB $MIEXT_DAMAGE_LIB $MIEXT_SHADOW_LIB $XI_LIB $XKB_LIB $XKB_STUB_LIB $COMPOSITE_LIB"
 	XVFB_SYS_LIBS="$XVFBMODULES_LIBS $GLX_SYS_LIBS"
 	AC_SUBST([XVFB_LIBS])
 	AC_SUBST([XVFB_SYS_LIBS])
@@ -1598,7 +1618,7 @@ if test "x$XNEST" = xyes; then
 	if test "x$have_xnest" = xno; then
 		AC_MSG_ERROR([Xnest build explicitly requested, but required modules not found.])
 	fi
-	XNEST_LIBS="$FB_LIB $FIXES_LIB $MI_LIB $XEXT_LIB $DBE_LIB $RECORD_LIB $GLX_LIBS $RANDR_LIB $RENDER_LIB $DAMAGE_LIB $MIEXT_SYNC_LIB $MIEXT_DAMAGE_LIB $MIEXT_SHADOW_LIB $XI_LIB $XKB_LIB $XKB_STUB_LIB $COMPOSITE_LIB $MAIN_LIB $DIX_LIB $OS_LIB"
+	XNEST_LIBS="$FB_LIB $FIXES_LIB $MI_LIB $XEXT_LIB $DBE_LIB $RECORD_LIB $GLX_LIBS $RANDR_LIB $RENDER_LIB $DAMAGE_LIB  $DRI3_LIB $MIEXT_SYNC_LIB $MIEXT_DAMAGE_LIB $MIEXT_SHADOW_LIB $XI_LIB $XKB_LIB $XKB_STUB_LIB $COMPOSITE_LIB $MAIN_LIB $DIX_LIB $OS_LIB"
 	XNEST_SYS_LIBS="$XNESTMODULES_LIBS $GLX_SYS_LIBS"
 	AC_SUBST([XNEST_LIBS])
 	AC_SUBST([XNEST_SYS_LIBS])
@@ -1623,7 +1643,7 @@ if test "x$XORG" = xyes; then
 	XORG_OSINCS='-I$(top_srcdir)/hw/xfree86/os-support -I$(top_srcdir)/hw/xfree86/os-support/bus -I$(top_srcdir)/os'
 	XORG_INCS="$XORG_DDXINCS $XORG_OSINCS"
 	XORG_CFLAGS="$XORGSERVER_CFLAGS -DHAVE_XORG_CONFIG_H"
-	XORG_LIBS="$COMPOSITE_LIB $FIXES_LIB $XEXT_LIB $DBE_LIB $RECORD_LIB $RANDR_LIB $RENDER_LIB $DAMAGE_LIB $MIEXT_SYNC_LIB $MIEXT_DAMAGE_LIB $XI_LIB $XKB_LIB"
+	XORG_LIBS="$COMPOSITE_LIB $FIXES_LIB $XEXT_LIB $DBE_LIB $RECORD_LIB $RANDR_LIB $RENDER_LIB $DAMAGE_LIB $DRI3_LIB $MIEXT_SYNC_LIB $MIEXT_DAMAGE_LIB $XI_LIB $XKB_LIB"
 
 	dnl ==================================================================
 	dnl symbol visibility
@@ -2036,7 +2056,7 @@ if test "x$DMX" = xyes; then
 	fi
 	DMX_INCLUDES="$XEXT_INC $RENDER_INC $RECORD_INC"
 	XDMX_CFLAGS="$DMXMODULES_CFLAGS"
-	XDMX_LIBS="$FB_LIB $MI_LIB $XEXT_LIB $RENDER_LIB $RECORD_LIB $XI_LIB $XKB_LIB $XKB_STUB_LIB $MIEXT_SYNC_LIB $MIEXT_SHADOW_LIB $MIEXT_DAMAGE_LIB $COMPOSITE_LIB $DAMAGE_LIB $MAIN_LIB $DIX_LIB $CONFIG_LIB $OS_LIB $FIXES_LIB"
+	XDMX_LIBS="$FB_LIB $MI_LIB $XEXT_LIB $RENDER_LIB $RECORD_LIB $XI_LIB $XKB_LIB $XKB_STUB_LIB  $DRI3_LIB $MIEXT_SYNC_LIB $MIEXT_SHADOW_LIB $MIEXT_DAMAGE_LIB $COMPOSITE_LIB $DAMAGE_LIB $MAIN_LIB $DIX_LIB $CONFIG_LIB $OS_LIB $FIXES_LIB"
 	XDMX_SYS_LIBS="$DMXMODULES_LIBS"
 	AC_SUBST([XDMX_CFLAGS])
 	AC_SUBST([XDMX_LIBS])
@@ -2145,7 +2165,7 @@ if test "$KDRIVE" = yes; then
     
     KDRIVE_CFLAGS="$XSERVER_CFLAGS -DHAVE_KDRIVE_CONFIG_H $TSLIB_CFLAGS"
 
-    KDRIVE_PURE_LIBS="$FB_LIB $MI_LIB $FIXES_LIB $XEXT_LIB $DBE_LIB $RECORD_LIB $GLX_LIBS $RANDR_LIB $RENDER_LIB $DAMAGE_LIB $MIEXT_SYNC_LIB $MIEXT_DAMAGE_LIB $MIEXT_SHADOW_LIB $XI_LIB $XKB_LIB $XKB_STUB_LIB $COMPOSITE_LIB $OS_LIB"
+    KDRIVE_PURE_LIBS="$FB_LIB $MI_LIB $FIXES_LIB $XEXT_LIB $DBE_LIB $RECORD_LIB $GLX_LIBS $RANDR_LIB $RENDER_LIB $DAMAGE_LIB $DRI3_LIB $MIEXT_SYNC_LIB $MIEXT_DAMAGE_LIB $MIEXT_SHADOW_LIB $XI_LIB $XKB_LIB $XKB_STUB_LIB $COMPOSITE_LIB $OS_LIB"
     KDRIVE_LIB='$(top_builddir)/hw/kdrive/src/libkdrive.la'
     case $host_os in
 	*linux*)
@@ -2267,6 +2287,7 @@ Xext/Makefile
 Xi/Makefile
 xfixes/Makefile
 exa/Makefile
+dri3/Makefile
 hw/Makefile
 hw/xfree86/Makefile
 hw/xfree86/common/Makefile
diff --git a/dri3/Makefile.am b/dri3/Makefile.am
new file mode 100644
index 0000000..e47a734
--- /dev/null
+++ b/dri3/Makefile.am
@@ -0,0 +1,13 @@
+noinst_LTLIBRARIES = libdri3.la
+AM_CFLAGS = \
+	-DHAVE_XORG_CONFIG_H \
+	@DIX_CFLAGS@ @XORG_CFLAGS@
+
+libdri3_la_SOURCES = \
+	dri3.h \
+	dri3_priv.h \
+	dri3.c \
+	dri3_request.c \
+	dri3_screen.c
+
+sdk_HEADERS = dri3.h
diff --git a/dri3/dri3.c b/dri3/dri3.c
new file mode 100644
index 0000000..2bca7ae
--- /dev/null
+++ b/dri3/dri3.c
@@ -0,0 +1,87 @@
+/*
+ * Copyright © 2013 Keith Packard
+ *
+ * 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 the copyright holders not be used in advertising or
+ * publicity pertaining to distribution of the software without specific,
+ * written prior permission.  The 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.
+ */
+
+#ifdef HAVE_XORG_CONFIG_H
+#include <xorg-config.h>
+#endif
+
+#include "dri3_priv.h"
+
+int dri3_request;
+DevPrivateKeyRec dri3_screen_private_key;
+DevPrivateKeyRec dri3_window_private_key;
+
+static Bool
+dri3_close_screen(ScreenPtr screen)
+{
+    dri3_screen_priv_ptr screen_priv = dri3_screen_priv(screen);
+
+    unwrap(screen_priv, screen, CloseScreen);
+
+    free(screen_priv);
+    return (*screen->CloseScreen) (screen);
+}
+
+Bool
+dri3_screen_init(ScreenPtr screen, dri3_screen_info_ptr info)
+{
+    if (!dixRegisterPrivateKey(&dri3_screen_private_key, PRIVATE_SCREEN, 0))
+        return FALSE;
+
+    if (!dri3_screen_priv(screen)) {
+        dri3_screen_priv_ptr screen_priv = calloc(1, sizeof (dri3_screen_priv_rec));
+        if (!screen_priv)
+            return FALSE;
+
+        wrap(screen_priv, screen, CloseScreen, dri3_close_screen);
+
+        screen_priv->info = info;
+
+        dixSetPrivate(&screen->devPrivates, &dri3_screen_private_key, screen_priv);
+    }
+
+    return TRUE;
+}
+
+void
+dri3_extension_init(void)
+{
+    ExtensionEntry *extension;
+    int i;
+
+    extension = AddExtension(DRI3_NAME, DRI3NumberEvents, DRI3NumberErrors,
+                             proc_dri3_dispatch, sproc_dri3_dispatch,
+                             NULL, StandardMinorOpcode);
+    if (!extension)
+        goto bail;
+
+    dri3_request = extension->base;
+
+    for (i = 0; i < screenInfo.numScreens; i++) {
+        if (!dri3_screen_init(screenInfo.screens[i], NULL))
+            goto bail;
+    }
+    return;
+
+bail:
+    FatalError("Cannot initialize DRI3 extension");
+}
diff --git a/dri3/dri3.h b/dri3/dri3.h
new file mode 100644
index 0000000..7774c87
--- /dev/null
+++ b/dri3/dri3.h
@@ -0,0 +1,59 @@
+/*
+ * Copyright © 2013 Keith Packard
+ *
+ * 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 the copyright holders not be used in advertising or
+ * publicity pertaining to distribution of the software without specific,
+ * written prior permission.  The 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.
+ */
+
+#ifndef _DRI3_H_
+#define _DRI3_H_
+
+#include <X11/extensions/dri3proto.h>
+#include <randrstr.h>
+
+#define DRI3_SCREEN_INFO_VERSION        0
+
+typedef int (*dri3_open_proc)(ScreenPtr screen,
+                              RRProviderPtr provider,
+                              int *fd);
+
+typedef PixmapPtr (*dri3_pixmap_from_fd_proc) (ScreenPtr screen,
+                                               int fd,
+                                               CARD16 width,
+                                               CARD16 height,
+                                               CARD16 stride,
+                                               CARD8 depth,
+                                               CARD8 bpp);
+
+typedef int (*dri3_fd_from_pixmap_proc) (ScreenPtr screen,
+                                         PixmapPtr pixmap,
+                                         CARD16 *stride,
+                                         CARD32 *size);
+
+typedef struct dri3_screen_info {
+    uint32_t                    version;
+
+    dri3_open_proc              open;
+    dri3_pixmap_from_fd_proc    pixmap_from_fd;
+    dri3_fd_from_pixmap_proc    fd_from_pixmap;
+} dri3_screen_info_rec, *dri3_screen_info_ptr;
+
+extern _X_EXPORT Bool
+dri3_screen_init(ScreenPtr screen, dri3_screen_info_ptr info);
+
+#endif /* _DRI3_H_ */
diff --git a/dri3/dri3_event.c b/dri3/dri3_event.c
new file mode 100644
index 0000000..02f0f65
--- /dev/null
+++ b/dri3/dri3_event.c
@@ -0,0 +1,163 @@
+/*
+ * Copyright © 2013 Keith Packard
+ *
+ * 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 the copyright holders not be used in advertising or
+ * publicity pertaining to distribution of the software without specific,
+ * written prior permission.  The 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.
+ */
+
+#ifdef HAVE_XORG_CONFIG_H
+#include <xorg-config.h>
+#endif
+
+#include "dri3_priv.h"
+
+RESTYPE dri3_event_type;
+
+static int
+dri3_free_event(pointer data, XID id)
+{
+    dri3_event_ptr dri3_event = (dri3_event_ptr) data;
+    dri3_window_priv_ptr window_priv = dri3_window_priv(dri3_event->window);
+    dri3_event_ptr *previous, current;
+
+    for (previous = &window_priv->events; (current = *previous); previous = &current->next) {
+        if (current == dri3_event) {
+            *previous = dri3_event->next;
+            break;
+        }
+    }
+    free((pointer) dri3_event);
+    return 1;
+
+}
+
+void
+dri3_free_events(WindowPtr window)
+{
+    dri3_window_priv_ptr window_priv = dri3_window_priv(window);
+    dri3_event_ptr event;
+
+    if (!window_priv)
+        return;
+
+    while ((event = window_priv->events))
+        FreeResource(event->id, RT_NONE);
+}
+
+static void
+dri3_event_swap(xGenericEvent *from, xGenericEvent *to)
+{
+    *to = *from;
+    swaps(&to->sequenceNumber);
+    swapl(&to->length);
+    swaps(&to->evtype);
+    switch (from->evtype) {
+    case DRI3_ConfigureNotify: {
+        xDRI3ConfigureNotify *c = (xDRI3ConfigureNotify *) to;
+
+        swapl(&c->eid);
+        swapl(&c->window);
+        swaps(&c->x);
+        swaps(&c->y);
+        swaps(&c->width);
+        swaps(&c->height);
+        swaps(&c->off_x);
+        swaps(&c->off_y);
+        swaps(&c->pixmap_width);
+        swaps(&c->pixmap_height);
+        swapl(&c->pixmap_flags);
+        break;
+    }
+    }
+}
+
+void
+dri3_send_config_notify(WindowPtr window, int x, int y, int w, int h, int bw, WindowPtr sibling)
+{
+    dri3_window_priv_ptr window_priv = dri3_window_priv(window);
+
+    if (window_priv) {
+        xDRI3ConfigureNotify cn = {
+            .type = GenericEvent,
+            .extension = dri3_request,
+            .length = (sizeof(xDRI3ConfigureNotify) - 32) >> 2,
+            .evtype = DRI3_ConfigureNotify,
+            .eid = 0,
+            .window = window->drawable.id,
+            .x = x,
+            .y = y,
+            .width = w,
+            .height = h,
+            .off_x = 0,
+            .off_y = 0,
+            .pixmap_width = w,
+            .pixmap_height = h,
+            .pixmap_flags = 0
+        };
+        dri3_event_ptr event;
+        dri3_screen_priv_ptr screen_priv = dri3_screen_priv(window->drawable.pScreen);
+
+        if (screen_priv->info && screen_priv->info->driver_config)
+            screen_priv->info->driver_config(window, &cn);
+
+        for (event = window_priv->events; event; event = event->next) {
+            if (event->mask & (1 << DRI3ConfigureNotify)) {
+                cn.eid = event->id;
+                WriteEventsToClient(event->client, 1, (xEvent *) &cn);
+            }
+        }
+    }
+}
+
+int
+dri3_select_input(ClientPtr client, XID eid, WindowPtr window, CARD32 mask)
+{
+    dri3_window_priv_ptr window_priv = dri3_window_priv(window);
+    dri3_event_ptr event;
+
+    if (!window_priv)
+        return BadAlloc;
+
+    event = calloc (1, sizeof (dri3_event_rec));
+    if (!event)
+        return BadAlloc;
+
+    event->client = client;
+    event->window = window;
+    event->id = eid;
+    event->mask = mask;
+
+    event->next = window_priv->events;
+    window_priv->events = event;
+
+    if (!AddResource(event->id, dri3_event_type, (pointer) event))
+        return BadAlloc;
+
+    return Success;
+}
+
+Bool
+dri3_event_init(void)
+{
+    dri3_event_type = CreateNewResourceType(dri3_free_event, "DRI3Event");
+    if (!dri3_event_type)
+        return FALSE;
+
+    GERegisterExtension(dri3_request, dri3_event_swap);
+    return TRUE;
+}
diff --git a/dri3/dri3_priv.h b/dri3/dri3_priv.h
new file mode 100644
index 0000000..e2fed83
--- /dev/null
+++ b/dri3/dri3_priv.h
@@ -0,0 +1,80 @@
+/*
+ * Copyright © 2013 Keith Packard
+ *
+ * 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 the copyright holders not be used in advertising or
+ * publicity pertaining to distribution of the software without specific,
+ * written prior permission.  The 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.
+ */
+
+#ifndef _DRI3PRIV_H_
+#define _DRI3PRIV_H_
+
+#include <X11/X.h>
+#include "scrnintstr.h"
+#include "misc.h"
+#include "list.h"
+#include "windowstr.h"
+#include "dixstruct.h"
+#include <randrstr.h>
+#include "dri3.h"
+
+extern int dri3_request;
+
+extern DevPrivateKeyRec dri3_screen_private_key;
+
+typedef struct dri3_screen_priv {
+    CloseScreenProcPtr          CloseScreen;
+    ConfigNotifyProcPtr         ConfigNotify;
+    DestroyWindowProcPtr        DestroyWindow;
+
+    dri3_screen_info_ptr        info;
+} dri3_screen_priv_rec, *dri3_screen_priv_ptr;
+
+#define wrap(priv,real,mem,func) {\
+    priv->mem = real->mem; \
+    real->mem = func; \
+}
+
+#define unwrap(priv,real,mem) {\
+    real->mem = priv->mem; \
+}
+
+static inline dri3_screen_priv_ptr
+dri3_screen_priv(ScreenPtr screen)
+{
+    return (dri3_screen_priv_ptr)dixLookupPrivate(&(screen)->devPrivates, &dri3_screen_private_key);
+}
+
+int
+proc_dri3_dispatch(ClientPtr client);
+
+int
+sproc_dri3_dispatch(ClientPtr client);
+
+/* DDX interface */
+
+int
+dri3_open(ClientPtr client, ScreenPtr screen, RRProviderPtr provider, int *fd);
+
+int
+dri3_pixmap_from_fd(PixmapPtr *ppixmap, ScreenPtr screen, int fd,
+                    CARD16 width, CARD16 height, CARD16 stride, CARD8 depth, CARD8 bpp);
+
+int
+dri3_fd_from_pixmap(int *pfd, PixmapPtr pixmap, CARD16 *stride, CARD32 *size);
+
+#endif /* _DRI3PRIV_H_ */
diff --git a/dri3/dri3_request.c b/dri3/dri3_request.c
new file mode 100644
index 0000000..3ebb9d5
--- /dev/null
+++ b/dri3/dri3_request.c
@@ -0,0 +1,394 @@
+/*
+ * Copyright © 2013 Keith Packard
+ *
+ * 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 the copyright holders not be used in advertising or
+ * publicity pertaining to distribution of the software without specific,
+ * written prior permission.  The 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.
+ */
+
+#ifdef HAVE_XORG_CONFIG_H
+#include <xorg-config.h>
+#endif
+
+#include "dri3_priv.h"
+#include <syncsrv.h>
+#include <unistd.h>
+#include <xace.h>
+#include "../Xext/syncsdk.h"
+
+static int
+proc_dri3_query_version(ClientPtr client)
+{
+    REQUEST(xDRI3QueryVersionReq);
+    xDRI3QueryVersionReply rep = {
+        .type = X_Reply,
+        .sequenceNumber = client->sequence,
+        .length = 0,
+        .majorVersion = DRI3_MAJOR,
+        .minorVersion = DRI3_MINOR
+    };
+
+    REQUEST_SIZE_MATCH(xDRI3QueryVersionReq);
+    (void) stuff;
+    if (client->swapped) {
+        swaps(&rep.sequenceNumber);
+        swapl(&rep.length);
+        swapl(&rep.majorVersion);
+        swapl(&rep.minorVersion);
+    }
+    WriteToClient(client, sizeof(rep), &rep);
+    return Success;
+}
+
+static int
+proc_dri3_open(ClientPtr client)
+{
+    REQUEST(xDRI3OpenReq);
+    xDRI3OpenReply rep = {
+        .type = X_Reply,
+        .nfd = 1,
+        .sequenceNumber = client->sequence,
+        .length = 0,
+    };
+    RRProviderPtr provider;
+    DrawablePtr drawable;
+    ScreenPtr screen;
+    int fd;
+    int status;
+
+    REQUEST_SIZE_MATCH(xDRI3OpenReq);
+
+    status = dixLookupDrawable(&drawable, stuff->drawable, client, 0, DixReadAccess);
+    if (status != Success)
+        return status;
+
+    if (stuff->provider == None)
+        provider = NULL;
+    else if (!RRProviderType) {
+        return BadMatch;
+    } else {
+        VERIFY_RR_PROVIDER(stuff->provider, provider, DixReadAccess);
+        if (drawable->pScreen != provider->pScreen)
+            return BadMatch;
+    }
+    screen = drawable->pScreen;
+
+    status = dri3_open(client, screen, provider, &fd);
+    if (status != Success)
+        return status;
+
+    if (client->swapped) {
+        swaps(&rep.sequenceNumber);
+        swapl(&rep.length);
+    }
+
+    if (WriteFdToClient(client, fd, TRUE) < 0) {
+        close(fd);
+        return BadAlloc;
+    }
+
+    WriteToClient(client, sizeof (rep), &rep);
+
+    return Success;
+}
+
+static int
+proc_dri3_pixmap_from_buffer(ClientPtr client)
+{
+    REQUEST(xDRI3PixmapFromBufferReq);
+    int fd;
+    DrawablePtr drawable;
+    PixmapPtr pixmap;
+    int rc;
+
+    SetReqFds(client, 1);
+    REQUEST_SIZE_MATCH(xDRI3PixmapFromBufferReq);
+    LEGAL_NEW_RESOURCE(stuff->pixmap, client);
+    rc = dixLookupDrawable(&drawable, stuff->drawable, client, M_ANY, DixGetAttrAccess);
+    if (rc != Success) {
+        client->errorValue = stuff->drawable;
+        return rc;
+    }
+
+    if (!stuff->width || !stuff->height) {
+        client->errorValue = 0;
+        return BadValue;
+    }
+
+    if (stuff->width > 32767 || stuff->height > 32767)
+        return BadAlloc;
+
+    if (stuff->depth != 1) {
+        DepthPtr depth = drawable->pScreen->allowedDepths;
+        int i;
+        for (i = 0; i < drawable->pScreen->numDepths; i++, depth++)
+            if (depth->depth == stuff->depth)
+                break;
+        if (i == drawable->pScreen->numDepths) {
+            client->errorValue = stuff->depth;
+            return BadValue;
+        }
+    }
+
+    fd = ReadFdFromClient(client);
+    if (fd < 0)
+        return BadValue;
+
+    rc = dri3_pixmap_from_fd(&pixmap,
+                             drawable->pScreen, fd,
+                             stuff->width, stuff->height,
+                             stuff->stride, stuff->depth,
+                             stuff->bpp);
+    close (fd);
+    if (rc != Success)
+        return rc;
+
+    pixmap->drawable.id = stuff->pixmap;
+
+    /* security creation/labeling check */
+    rc = XaceHook(XACE_RESOURCE_ACCESS, client, stuff->pixmap, RT_PIXMAP,
+                  pixmap, RT_NONE, NULL, DixCreateAccess);
+
+    if (rc != Success) {
+        (*drawable->pScreen->DestroyPixmap) (pixmap);
+        return rc;
+    }
+    if (AddResource(stuff->pixmap, RT_PIXMAP, (pointer) pixmap))
+        return Success;
+
+    return Success;
+}
+
+static int
+proc_dri3_buffer_from_pixmap(ClientPtr client)
+{
+    REQUEST(xDRI3BufferFromPixmapReq);
+    xDRI3BufferFromPixmapReply rep = {
+        .type = X_Reply,
+        .nfd = 1,
+        .sequenceNumber = client->sequence,
+        .length = 0,
+    };
+    int rc;
+    int fd;
+    PixmapPtr pixmap;
+
+    REQUEST_SIZE_MATCH(xDRI3BufferFromPixmapReq);
+    rc = dixLookupResourceByType((pointer *) &pixmap, stuff->pixmap, RT_PIXMAP,
+                                 client, DixWriteAccess);
+    if (rc != Success) {
+        client->errorValue = stuff->pixmap;
+        return rc;
+    }
+
+    rep.width = pixmap->drawable.width;
+    rep.height = pixmap->drawable.height;
+    rep.depth = pixmap->drawable.depth;
+    rep.bpp = pixmap->drawable.bitsPerPixel;
+
+    rc = dri3_fd_from_pixmap(&fd, pixmap, &rep.stride, &rep.size);
+    if (rc != Success)
+        return rc;
+
+    if (client->swapped) {
+        swaps(&rep.sequenceNumber);
+        swapl(&rep.length);
+        swapl(&rep.size);
+        swaps(&rep.width);
+        swaps(&rep.height);
+        swaps(&rep.stride);
+    }
+    if (WriteFdToClient(client, fd, TRUE) < 0) {
+        close(fd);
+        return BadAlloc;
+    }
+
+    WriteToClient(client, sizeof(rep), &rep);
+
+    return client->noClientException;
+}
+
+static int
+proc_dri3_fence_from_fd(ClientPtr client)
+{
+    REQUEST(xDRI3FenceFromFDReq);
+    DrawablePtr drawable;
+    int fd;
+    int status;
+
+    SetReqFds(client, 1);
+    REQUEST_SIZE_MATCH(xDRI3FenceFromFDReq);
+    LEGAL_NEW_RESOURCE(stuff->fence, client);
+
+    status = dixLookupDrawable(&drawable, stuff->drawable, client, M_ANY, DixGetAttrAccess);
+    if (status != Success)
+        return status;
+
+    fd = ReadFdFromClient(client);
+    if (fd < 0)
+        return BadValue;
+
+    status = SyncCreateFenceFromFD(client, drawable, stuff->fence,
+                                   fd, stuff->initially_triggered);
+
+    return status;
+}
+
+static int
+proc_dri3_fd_from_fence(ClientPtr client)
+{
+    REQUEST(xDRI3FDFromFenceReq);
+    xDRI3FDFromFenceReply rep = {
+        .type = X_Reply,
+        .nfd = 1,
+        .sequenceNumber = client->sequence,
+        .length = 0,
+    };
+    DrawablePtr drawable;
+    int fd;
+    int status;
+    SyncFence *fence;
+
+    REQUEST_SIZE_MATCH(xDRI3FDFromFenceReq);
+
+    status = dixLookupDrawable(&drawable, stuff->drawable, client, M_ANY, DixGetAttrAccess);
+    if (status != Success)
+        return status;
+    status = SyncVerifyFence(&fence, stuff->fence, client, DixWriteAccess);
+    if (status != Success)
+        return status;
+
+    fd = SyncFDFromFence(client, drawable, fence);
+    if (fd < 0)
+        return BadMatch;
+
+    if (client->swapped) {
+        swaps(&rep.sequenceNumber);
+        swapl(&rep.length);
+    }
+    if (WriteFdToClient(client, fd, FALSE) < 0)
+        return BadAlloc;
+
+    WriteToClient(client, sizeof(rep), &rep);
+
+    return client->noClientException;
+}
+
+int (*proc_dri3_vector[DRI3NumberRequests]) (ClientPtr) = {
+    proc_dri3_query_version,            /* 0 */
+    proc_dri3_open,                     /* 1 */
+    proc_dri3_pixmap_from_buffer,       /* 2 */
+    proc_dri3_buffer_from_pixmap,       /* 3 */
+    proc_dri3_fence_from_fd,            /* 4 */
+    proc_dri3_fd_from_fence,            /* 5 */
+};
+
+int
+proc_dri3_dispatch(ClientPtr client)
+{
+    REQUEST(xReq);
+    if (stuff->data >= DRI3NumberRequests || !proc_dri3_vector[stuff->data])
+        return BadRequest;
+    return (*proc_dri3_vector[stuff->data]) (client);
+}
+
+static int
+sproc_dri3_query_version(ClientPtr client)
+{
+    REQUEST(xDRI3QueryVersionReq);
+
+    swaps(&stuff->length);
+    swapl(&stuff->majorVersion);
+    swapl(&stuff->minorVersion);
+    return (*proc_dri3_vector[stuff->dri3ReqType]) (client);
+}
+
+static int
+sproc_dri3_open(ClientPtr client)
+{
+    REQUEST(xDRI3OpenReq);
+
+    swaps(&stuff->length);
+    swapl(&stuff->drawable);
+    swapl(&stuff->provider);
+    return (*proc_dri3_vector[stuff->dri3ReqType]) (client);
+}
+
+static int
+sproc_dri3_pixmap_from_buffer(ClientPtr client)
+{
+    REQUEST(xDRI3PixmapFromBufferReq);
+
+    swaps(&stuff->length);
+    swapl(&stuff->pixmap);
+    swapl(&stuff->drawable);
+    swapl(&stuff->size);
+    swaps(&stuff->width);
+    swaps(&stuff->height);
+    swaps(&stuff->stride);
+    return (*proc_dri3_vector[stuff->dri3ReqType]) (client);
+}
+
+static int
+sproc_dri3_buffer_from_pixmap(ClientPtr client)
+{
+    REQUEST(xDRI3BufferFromPixmapReq);
+
+    swaps(&stuff->length);
+    swapl(&stuff->pixmap);
+    return (*proc_dri3_vector[stuff->dri3ReqType]) (client);
+}
+
+static int
+sproc_dri3_fence_from_fd(ClientPtr client)
+{
+    REQUEST(xDRI3FenceFromFDReq);
+
+    swaps(&stuff->length);
+    swapl(&stuff->drawable);
+    swapl(&stuff->fence);
+    return (*proc_dri3_vector[stuff->dri3ReqType]) (client);
+}
+
+static int
+sproc_dri3_fd_from_fence(ClientPtr client)
+{
+    REQUEST(xDRI3FDFromFenceReq);
+
+    swaps(&stuff->length);
+    swapl(&stuff->drawable);
+    swapl(&stuff->fence);
+    return (*proc_dri3_vector[stuff->dri3ReqType]) (client);
+}
+
+int (*sproc_dri3_vector[DRI3NumberRequests]) (ClientPtr) = {
+    sproc_dri3_query_version,           /* 0 */
+    sproc_dri3_open,                    /* 1 */
+    sproc_dri3_pixmap_from_buffer,      /* 2 */
+    sproc_dri3_buffer_from_pixmap,      /* 3 */
+    sproc_dri3_fence_from_fd,           /* 4 */
+    sproc_dri3_fd_from_fence,           /* 5 */
+};
+
+int
+sproc_dri3_dispatch(ClientPtr client)
+{
+    REQUEST(xReq);
+    if (stuff->data >= DRI3NumberRequests || !sproc_dri3_vector[stuff->data])
+        return BadRequest;
+    return (*sproc_dri3_vector[stuff->data]) (client);
+}
diff --git a/dri3/dri3_screen.c b/dri3/dri3_screen.c
new file mode 100644
index 0000000..cf2735b
--- /dev/null
+++ b/dri3/dri3_screen.c
@@ -0,0 +1,80 @@
+/*
+ * Copyright © 2013 Keith Packard
+ *
+ * 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 the copyright holders not be used in advertising or
+ * publicity pertaining to distribution of the software without specific,
+ * written prior permission.  The 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.
+ */
+
+#ifdef HAVE_XORG_CONFIG_H
+#include <xorg-config.h>
+#endif
+
+#include "dri3_priv.h"
+#include <syncsdk.h>
+#include <misync.h>
+#include <misyncshm.h>
+#include <randrstr.h>
+
+int
+dri3_open(ClientPtr client, ScreenPtr screen, RRProviderPtr provider, int *fd)
+{
+    dri3_screen_priv_ptr        ds = dri3_screen_priv(screen);
+    dri3_screen_info_ptr        info = ds->info;
+    int                         rc;
+
+    if (!info || !info->open)
+        return BadMatch;
+
+    rc = (*info->open) (screen, provider, fd);
+    if (rc != Success)
+        return rc;
+
+    return Success;
+}
+
+int
+dri3_pixmap_from_fd(PixmapPtr *ppixmap, ScreenPtr screen, int fd,
+                    CARD16 width, CARD16 height, CARD16 stride, CARD8 depth, CARD8 bpp)
+{
+    dri3_screen_priv_ptr        ds = dri3_screen_priv(screen);
+    dri3_screen_info_ptr        info = ds->info;
+    PixmapPtr                   pixmap;
+
+    pixmap = (*info->pixmap_from_fd) (screen, fd, width, height, stride, depth, bpp);
+    if (!pixmap)
+        return BadAlloc;
+
+    *ppixmap = pixmap;
+    return Success;
+}
+
+int
+dri3_fd_from_pixmap(int *pfd, PixmapPtr pixmap, CARD16 *stride, CARD32 *size)
+{
+    ScreenPtr                   screen = pixmap->drawable.pScreen;
+    dri3_screen_priv_ptr        ds = dri3_screen_priv(screen);
+    dri3_screen_info_ptr        info = ds->info;
+    int                         fd;
+
+    fd = (*info->fd_from_pixmap)(screen, pixmap, stride, size);
+    if (fd < 0)
+        return BadAlloc;
+    *pfd = fd;
+    return Success;
+}
+
diff --git a/dri3/dri3int.h b/dri3/dri3int.h
new file mode 100644
index 0000000..7f53eba
--- /dev/null
+++ b/dri3/dri3int.h
@@ -0,0 +1,26 @@
+/*
+ * Copyright © 2011 Daniel Stone
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ * Author: Daniel Stone <daniel at fooishbar.org>
+ */
+
+extern Bool DRI2ModuleSetup(void);
diff --git a/hw/dmx/dmxinit.c b/hw/dmx/dmxinit.c
index 65416ed..bd868a0 100644
--- a/hw/dmx/dmxinit.c
+++ b/hw/dmx/dmxinit.c
@@ -109,6 +109,8 @@ Bool dmxGLXSyncSwap = FALSE;
 Bool dmxGLXFinishSwap = FALSE;
 #endif
 
+RESTYPE RRProviderType = 0;
+
 Bool dmxIgnoreBadFontPaths = FALSE;
 
 Bool dmxAddRemoveScreens = FALSE;
diff --git a/hw/xfree86/Makefile.am b/hw/xfree86/Makefile.am
index 59cfb5f..eea16a8 100644
--- a/hw/xfree86/Makefile.am
+++ b/hw/xfree86/Makefile.am
@@ -41,7 +41,7 @@ nodist_Xorg_SOURCES = sdksyms.c
 AM_CFLAGS = $(DIX_CFLAGS) @XORG_CFLAGS@
 AM_CPPFLAGS = $(XORG_INCS) -I$(srcdir)/parser -I$(top_srcdir)/miext/cw \
 	-I$(srcdir)/ddc -I$(srcdir)/i2c -I$(srcdir)/modes -I$(srcdir)/ramdac \
-	-I$(srcdir)/dri -I$(srcdir)/dri2
+	-I$(srcdir)/dri -I$(srcdir)/dri2 -I$(top_srcdir)/dri3
 
 LOCAL_LIBS = \
             $(MAIN_LIB) \
@@ -59,6 +59,8 @@ LOCAL_LIBS = \
             dixmods/libxorgxkb.la \
             $(DRI_LIB) \
             $(DRI2_LIB) \
+	    $(top_builddir)/dri3/libdri3.la \
+	    $(top_builddir)/miext/sync/libsync.la \
             $(top_builddir)/mi/libmi.la \
             $(top_builddir)/os/libos.la
 Xorg_LDADD = \
diff --git a/hw/xfree86/sdksyms.sh b/hw/xfree86/sdksyms.sh
index 48b48b5..7c9734c 100755
--- a/hw/xfree86/sdksyms.sh
+++ b/hw/xfree86/sdksyms.sh
@@ -99,6 +99,7 @@ cat > sdksyms.c << EOF
 # include "dri2.h"
 #endif
 
+# include "dri3.h"
 
 /* hw/xfree86/vgahw/Makefile.am -- module */
 /*
diff --git a/include/dix-config.h.in b/include/dix-config.h.in
index a643dfc..d96da6a 100644
--- a/include/dix-config.h.in
+++ b/include/dix-config.h.in
@@ -39,6 +39,9 @@
 /* Build DPMS extension */
 #undef DPMSExtension
 
+/* Build DRI3 extension */
+#undef DRI3
+
 /* Build GLX extension */
 #undef GLXEXT
 
diff --git a/include/extinit.h b/include/extinit.h
index 6d67bf2..bdb149c 100644
--- a/include/extinit.h
+++ b/include/extinit.h
@@ -176,4 +176,9 @@ extern void XvExtensionInit(void);
 extern void XvMCExtensionInit(void);
 #endif
 
+#if defined(DRI3)
+#include <X11/extensions/dri3proto.h>
+extern void dri3_extension_init(void);
+#endif
+
 #endif
diff --git a/include/xorg-server.h.in b/include/xorg-server.h.in
index 81935be..5b3b664 100644
--- a/include/xorg-server.h.in
+++ b/include/xorg-server.h.in
@@ -28,6 +28,9 @@
 /* Build DPMS extension */
 #undef DPMSExtension
 
+/* Build DRI3 extension */
+#undef DRI3
+
 /* Build GLX extension */
 #undef GLXEXT
 
diff --git a/mi/miinitext.c b/mi/miinitext.c
index 145da38..e49948b 100644
--- a/mi/miinitext.c
+++ b/mi/miinitext.c
@@ -287,6 +287,7 @@ static ExtensionModule staticExtensions[] = {
 #ifdef DPMSExtension
     {DPMSExtensionInit, DPMSExtensionName, &noDPMSExtension},
 #endif
+    {dri3_extension_init, DRI3_NAME, NULL},
 #ifdef RES
     {ResExtensionInit, XRES_NAME, &noResExtension},
 #endif
diff --git a/miext/sync/Makefile.am b/miext/sync/Makefile.am
index 9aa1ba5..e25ceac 100644
--- a/miext/sync/Makefile.am
+++ b/miext/sync/Makefile.am
@@ -5,10 +5,11 @@ AM_CFLAGS = $(DIX_CFLAGS)
 AM_CPPFLAGS = 
 
 if XORG
-sdk_HEADERS = misync.h misyncstr.h
+sdk_HEADERS = misync.h misyncstr.h misyncshm.h
 endif
 
 libsync_la_SOURCES =	\
 	misync.c	\
 	misync.h	\
+	misyncshm.c	\
 	misyncstr.h
diff --git a/miext/sync/misync.c b/miext/sync/misync.c
index f380547..3d03d1b 100644
--- a/miext/sync/misync.c
+++ b/miext/sync/misync.c
@@ -29,20 +29,7 @@
 #include "misync.h"
 #include "misyncstr.h"
 
-static DevPrivateKeyRec syncScreenPrivateKeyRec;
-static DevPrivateKey syncScreenPrivateKey = &syncScreenPrivateKeyRec;
-
-#define SYNC_SCREEN_PRIV(pScreen) 				\
-    (SyncScreenPrivPtr) dixLookupPrivate(&pScreen->devPrivates,	\
-					 syncScreenPrivateKey)
-
-typedef struct _syncScreenPriv {
-    /* Wrappable sync-specific screen functions */
-    SyncScreenFuncsRec funcs;
-
-    /* Wrapped screen functions */
-    CloseScreenProcPtr CloseScreen;
-} SyncScreenPrivRec, *SyncScreenPrivPtr;
+DevPrivateKeyRec miSyncScreenPrivateKey;
 
 /* Default implementations of the sync screen functions */
 void
@@ -62,25 +49,25 @@ miSyncScreenDestroyFence(ScreenPtr pScreen, SyncFence * pFence)
 }
 
 /* Default implementations of the per-object functions */
-static void
+void
 miSyncFenceSetTriggered(SyncFence * pFence)
 {
     pFence->triggered = TRUE;
 }
 
-static void
+void
 miSyncFenceReset(SyncFence * pFence)
 {
     pFence->triggered = FALSE;
 }
 
-static Bool
+Bool
 miSyncFenceCheckTriggered(SyncFence * pFence)
 {
     return pFence->triggered;
 }
 
-static void
+void
 miSyncFenceAddTrigger(SyncTrigger * pTrigger)
 {
     (void) pTrigger;
@@ -88,7 +75,7 @@ miSyncFenceAddTrigger(SyncTrigger * pTrigger)
     return;
 }
 
-static void
+void
 miSyncFenceDeleteTrigger(SyncTrigger * pTrigger)
 {
     (void) pTrigger;
@@ -182,8 +169,8 @@ miSyncSetup(ScreenPtr pScreen)
         &miSyncScreenDestroyFence
     };
 
-    if (!dixPrivateKeyRegistered(syncScreenPrivateKey)) {
-        if (!dixRegisterPrivateKey(syncScreenPrivateKey, PRIVATE_SCREEN,
+    if (!dixPrivateKeyRegistered(&miSyncScreenPrivateKey)) {
+        if (!dixRegisterPrivateKey(&miSyncScreenPrivateKey, PRIVATE_SCREEN,
                                    sizeof(SyncScreenPrivRec)))
             return FALSE;
     }
diff --git a/miext/sync/misync.h b/miext/sync/misync.h
index deebb82..f63ec2b 100644
--- a/miext/sync/misync.h
+++ b/miext/sync/misync.h
@@ -76,4 +76,25 @@ extern _X_EXPORT SyncScreenFuncsPtr miSyncGetScreenFuncs(ScreenPtr pScreen);
 extern _X_EXPORT Bool
  miSyncSetup(ScreenPtr pScreen);
 
+Bool
+miSyncFenceCheckTriggered(SyncFence * pFence);
+
+void
+miSyncFenceSetTriggered(SyncFence * pFence);
+
+void
+miSyncFenceReset(SyncFence * pFence);
+
+void
+miSyncFenceAddTrigger(SyncTrigger * pTrigger);
+
+void
+miSyncFenceDeleteTrigger(SyncTrigger * pTrigger);
+
+int
+miSyncInitFenceFromFD(DrawablePtr pDraw, SyncFence *pFence, int fd, BOOL initially_triggered);
+
+int
+miSyncFDFromFence(DrawablePtr pDraw, SyncFence *pFence);
+
 #endif                          /* _MISYNC_H_ */
diff --git a/miext/sync/misyncshm.c b/miext/sync/misyncshm.c
new file mode 100644
index 0000000..ddd15ae
--- /dev/null
+++ b/miext/sync/misyncshm.c
@@ -0,0 +1,176 @@
+/*
+ * Copyright © 2013 Keith Packard
+ *
+ * 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 the copyright holders not be used in advertising or
+ * publicity pertaining to distribution of the software without specific,
+ * written prior permission.  The 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.
+ */
+
+#ifdef HAVE_DIX_CONFIG_H
+#include <dix-config.h>
+#endif
+
+#include "scrnintstr.h"
+#include "misync.h"
+#include "misyncstr.h"
+#include "misyncshm.h"
+#include "pixmapstr.h"
+#include <sys/mman.h>
+#include <unistd.h>
+#include <X11/xshmfence.h>
+
+static DevPrivateKeyRec syncShmFencePrivateKey;
+
+typedef struct _SyncShmFencePrivate {
+    int32_t             *fence;
+    int                 fd;
+} SyncShmFencePrivateRec, *SyncShmFencePrivatePtr;
+
+#define SYNC_FENCE_PRIV(pFence) \
+    (SyncShmFencePrivatePtr) dixLookupPrivate(&pFence->devPrivates, &syncShmFencePrivateKey)
+
+static void
+miSyncShmFenceSetTriggered(SyncFence * pFence)
+{
+    SyncShmFencePrivatePtr      pPriv = SYNC_FENCE_PRIV(pFence);
+
+    if (pPriv->fence)
+        xshmfence_trigger(pPriv->fence);
+    miSyncFenceSetTriggered(pFence);
+}
+
+static void
+miSyncShmFenceReset(SyncFence * pFence)
+{
+    SyncShmFencePrivatePtr      pPriv = SYNC_FENCE_PRIV(pFence);
+
+    if (pPriv->fence)
+        xshmfence_reset(pPriv->fence);
+    miSyncFenceReset(pFence);
+}
+
+static Bool
+miSyncShmFenceCheckTriggered(SyncFence * pFence)
+{
+    SyncShmFencePrivatePtr      pPriv = SYNC_FENCE_PRIV(pFence);
+
+    if (pPriv->fence)
+        return xshmfence_query(pPriv->fence);
+    else
+        return miSyncFenceCheckTriggered(pFence);
+}
+
+static void
+miSyncShmFenceAddTrigger(SyncTrigger * pTrigger)
+{
+    miSyncFenceAddTrigger(pTrigger);
+}
+
+static void
+miSyncShmFenceDeleteTrigger(SyncTrigger * pTrigger)
+{
+    miSyncFenceDeleteTrigger(pTrigger);
+}
+
+static const SyncFenceFuncsRec miSyncShmFenceFuncs = {
+    &miSyncShmFenceSetTriggered,
+    &miSyncShmFenceReset,
+    &miSyncShmFenceCheckTriggered,
+    &miSyncShmFenceAddTrigger,
+    &miSyncShmFenceDeleteTrigger
+};
+
+static void
+miSyncShmScreenCreateFence(ScreenPtr pScreen, SyncFence * pFence,
+                        Bool initially_triggered)
+{
+    SyncShmFencePrivatePtr      pPriv = SYNC_FENCE_PRIV(pFence);
+
+    pPriv->fence = NULL;
+    miSyncScreenCreateFence(pScreen, pFence, initially_triggered);
+    pFence->funcs = miSyncShmFenceFuncs;
+}
+
+static void
+miSyncShmScreenDestroyFence(ScreenPtr pScreen, SyncFence * pFence)
+{
+    SyncShmFencePrivatePtr      pPriv = SYNC_FENCE_PRIV(pFence);
+
+    if (pPriv->fence) {
+        xshmfence_trigger(pPriv->fence);
+        xshmfence_unmap_shm(pPriv->fence);
+        close(pPriv->fd);
+    }
+    miSyncScreenDestroyFence(pScreen, pFence);
+}
+
+int
+miSyncInitFenceFromFD(DrawablePtr pDraw, SyncFence *pFence, int fd, BOOL initially_triggered)
+
+{
+    SyncShmFencePrivatePtr      pPriv = SYNC_FENCE_PRIV(pFence);
+
+    miSyncInitFence(pDraw->pScreen, pFence, initially_triggered);
+
+    pPriv->fence = xshmfence_map_shm(fd);
+    if (pPriv->fence) {
+        pPriv->fd = fd;
+        return Success;
+    }
+    else
+        close(fd);
+    return BadValue;
+}
+
+int
+miSyncFDFromFence(DrawablePtr pDraw, SyncFence *pFence)
+{
+    SyncShmFencePrivatePtr      pPriv = SYNC_FENCE_PRIV(pFence);
+
+    if (!pPriv->fence) {
+        pPriv->fd = xshmfence_alloc_shm();
+        if (pPriv->fd < 0)
+            return -1;
+        pPriv->fence = xshmfence_map_shm(pPriv->fd);
+        if (!pPriv->fence) {
+            close (pPriv->fd);
+            return -1;
+        }
+    }
+    return pPriv->fd;
+}
+
+_X_EXPORT Bool miSyncShmScreenInit(ScreenPtr pScreen)
+{
+    SyncScreenFuncsPtr  funcs;
+
+    if (!miSyncSetup(pScreen))
+        return FALSE;
+
+    if (!dixPrivateKeyRegistered(&syncShmFencePrivateKey)) {
+        if (!dixRegisterPrivateKey(&syncShmFencePrivateKey, PRIVATE_SYNC_FENCE,
+                                   sizeof(SyncShmFencePrivateRec)))
+            return FALSE;
+    }
+
+    funcs = miSyncGetScreenFuncs(pScreen);
+
+    funcs->CreateFence = miSyncShmScreenCreateFence;
+    funcs->DestroyFence = miSyncShmScreenDestroyFence;
+    return TRUE;
+}
+
diff --git a/miext/sync/misyncshm.h b/miext/sync/misyncshm.h
new file mode 100644
index 0000000..4edbb50
--- /dev/null
+++ b/miext/sync/misyncshm.h
@@ -0,0 +1,28 @@
+/*
+ * Copyright © 2013 Keith Packard
+ *
+ * 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 the copyright holders not be used in advertising or
+ * publicity pertaining to distribution of the software without specific,
+ * written prior permission.  The 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.
+ */
+
+#ifndef _MISYNCSHM_H_
+#define _MISYNCSYM_H_
+
+extern _X_EXPORT Bool miSyncShmScreenInit(ScreenPtr pScreen);
+
+#endif /* _MISYNCSHM_H_ */
diff --git a/miext/sync/misyncstr.h b/miext/sync/misyncstr.h
index e19256f..b5bf6fd 100644
--- a/miext/sync/misyncstr.h
+++ b/miext/sync/misyncstr.h
@@ -29,6 +29,7 @@
 #define _MISYNCSTR_H_
 
 #include "dix.h"
+#include "scrnintstr.h"
 #include <X11/extensions/syncconst.h>
 
 #define CARD64 XSyncValue       /* XXX temporary! need real 64 bit values for Alpha */
@@ -79,4 +80,18 @@ typedef struct _SyncTriggerList {
     struct _SyncTriggerList *next;
 } SyncTriggerList;
 
+extern DevPrivateKeyRec miSyncScreenPrivateKey;
+
+#define SYNC_SCREEN_PRIV(pScreen) 				\
+    (SyncScreenPrivPtr) dixLookupPrivate(&pScreen->devPrivates,	\
+					 &miSyncScreenPrivateKey)
+
+typedef struct _syncScreenPriv {
+    /* Wrappable sync-specific screen functions */
+    SyncScreenFuncsRec funcs;
+
+    /* Wrapped screen functions */
+    CloseScreenProcPtr CloseScreen;
+} SyncScreenPrivRec, *SyncScreenPrivPtr;
+
 #endif                          /* _MISYNCSTR_H_ */
diff --git a/test/Makefile.am b/test/Makefile.am
index eff0c9d..e59c412 100644
--- a/test/Makefile.am
+++ b/test/Makefile.am
@@ -19,7 +19,7 @@ AM_CPPFLAGS += -I$(top_srcdir)/hw/xfree86/parser \
 	-I$(top_srcdir)/hw/xfree86/ddc \
 	-I$(top_srcdir)/hw/xfree86/i2c -I$(top_srcdir)/hw/xfree86/modes \
 	-I$(top_srcdir)/hw/xfree86/ramdac -I$(top_srcdir)/hw/xfree86/dri \
-	-I$(top_srcdir)/hw/xfree86/dri2
+	-I$(top_srcdir)/hw/xfree86/dri2 -I$(top_srcdir)/dri3
 endif
 TEST_LDADD=libxservertest.la $(XORG_SYS_LIBS) $(XSERVER_SYS_LIBS) $(GLX_SYS_LIBS)
 
@@ -64,6 +64,10 @@ if DRI2
 libxservertest_la_LIBADD += $(top_builddir)/hw/xfree86/dri2/libdri2.la
 endif
 
+if DRI3
+libxservertest_la_LIBADD += $(top_builddir)/dri3/libdri3.la
+endif
+
 else
 nodist_libxservertest_la_SOURCES = \
             ddxstubs.c \
@@ -105,6 +109,11 @@ libxservertest_la_LIBADD += \
             $(top_builddir)/record/librecord.la
 endif
 
+if DRI3
+libxservertest_la_LIBADD += \
+            $(top_builddir)/dri3/libdri3.la
+endif
+
 if XQUARTZ
 libxservertest_la_LIBADD += \
             $(top_builddir)/miext/rootless/librootless.la
commit fdec793cdc2ef9a6ea66b311cb1068a7bd4a3be3
Author: Keith Packard <keithp at keithp.com>
Date:   Thu Jan 17 13:46:55 2013 -0800

    Add support for MIT-SHM AttachFd request
    
    This passes a file descriptor from the client to the server, which is
    then mmap'd
    
    Signed-off-by: Keith Packard <keithp at keithp.com>
    Reviewed-by: Adam Jackson <ajax at redhat.com>

diff --git a/Xext/shm.c b/Xext/shm.c
index f6995cc..1a70260 100644
--- a/Xext/shm.c
+++ b/Xext/shm.c
@@ -53,6 +53,7 @@ in this Software without prior written authorization from The Open Group.
 #include "xace.h"
 #include <X11/extensions/shmproto.h>
 #include <X11/Xfuncproto.h>
+#include <sys/mman.h>
 #include "protocol-versions.h"
 
 /* Needed for Solaris cross-zone shared memory extension */
@@ -382,8 +383,10 @@ ProcShmAttach(ClientPtr client)
         client->errorValue = stuff->readOnly;
         return BadValue;
     }
-    for (shmdesc = Shmsegs;
-         shmdesc && (shmdesc->shmid != stuff->shmid); shmdesc = shmdesc->next);
+    for (shmdesc = Shmsegs; shmdesc; shmdesc = shmdesc->next) {
+        if (!shmdesc->is_fd && shmdesc->shmid == stuff->shmid)
+            break;
+    }
     if (shmdesc) {
         if (!stuff->readOnly && !shmdesc->writable)
             return BadAccess;
@@ -393,6 +396,7 @@ ProcShmAttach(ClientPtr client)
         shmdesc = malloc(sizeof(ShmDescRec));
         if (!shmdesc)
             return BadAlloc;
+        shmdesc->is_fd = FALSE;
         shmdesc->addr = shmat(stuff->shmid, 0,
                               stuff->readOnly ? SHM_RDONLY : 0);
         if ((shmdesc->addr == ((char *) -1)) || SHMSTAT(stuff->shmid, &buf)) {
@@ -431,7 +435,10 @@ ShmDetachSegment(pointer value, /* must conform to DeleteType */
 
     if (--shmdesc->refcnt)
         return TRUE;
-    shmdt(shmdesc->addr);
+    if (shmdesc->is_fd)
+        munmap(shmdesc->addr, shmdesc->size);
+    else
+        shmdt(shmdesc->addr);
     for (prev = &Shmsegs; *prev != shmdesc; prev = &(*prev)->next);
     *prev = shmdesc->next;
     free(shmdesc);
@@ -1088,6 +1095,122 @@ ProcShmCreatePixmap(ClientPtr client)
 }
 
 static int
+ProcShmAttachFd(ClientPtr client)
+{
+    int fd;
+    ShmDescPtr shmdesc;
+    REQUEST(xShmAttachFdReq);
+    struct stat statb;
+
+    SetReqFds(client, 1);
+    REQUEST_SIZE_MATCH(xShmAttachFdReq);
+    LEGAL_NEW_RESOURCE(stuff->shmseg, client);
+    if ((stuff->readOnly != xTrue) && (stuff->readOnly != xFalse)) {
+        client->errorValue = stuff->readOnly;
+        return BadValue;
+    }
+    fd = ReadFdFromClient(client);
+    if (fd < 0)
+        return BadMatch;
+
+    if (fstat(fd, &statb) < 0 || statb.st_size == 0) {
+        close(fd);
+        return BadMatch;
+    }
+
+    shmdesc = malloc(sizeof(ShmDescRec));
+    if (!shmdesc) {
+        close(fd);
+        return BadAlloc;
+    }
+    shmdesc->is_fd = TRUE;
+    shmdesc->addr = mmap(NULL, statb.st_size,
+                         stuff->readOnly ? PROT_READ : PROT_READ|PROT_WRITE,
+                         MAP_SHARED,
+                         fd, 0);
+
+    close(fd);
+    if ((shmdesc->addr == ((char *) -1))) {
+        free(shmdesc);
+        return BadAccess;
+    }
+
+    shmdesc->refcnt = 1;
+    shmdesc->writable = !stuff->readOnly;
+    shmdesc->size = statb.st_size;
+    shmdesc->next = Shmsegs;
+    Shmsegs = shmdesc;
+
+    if (!AddResource(stuff->shmseg, ShmSegType, (pointer) shmdesc))
+        return BadAlloc;
+    return Success;
+}
+
+static int
+ProcShmCreateSegment(ClientPtr client)
+{
+    int fd;
+    ShmDescPtr shmdesc;
+    REQUEST(xShmCreateSegmentReq);
+    xShmCreateSegmentReply rep = {
+        .type = X_Reply,
+        .nfd = 1,
+        .sequenceNumber = client->sequence,
+        .length = 0,
+    };
+    char template[] = "/tmp/shm-XXXXXX";
+
+    REQUEST_SIZE_MATCH(xShmCreateSegmentReq);
+    if ((stuff->readOnly != xTrue) && (stuff->readOnly != xFalse)) {
+        client->errorValue = stuff->readOnly;
+        return BadValue;
+    }
+    fd = mkstemp(template);
+    if (fd < 0)
+        return BadAlloc;
+    unlink(template);
+    if (ftruncate(fd, stuff->size) < 0) {
+        close(fd);
+        return BadAlloc;
+    }
+    shmdesc = malloc(sizeof(ShmDescRec));
+    if (!shmdesc) {
+        close(fd);
+        return BadAlloc;
+    }
+    shmdesc->is_fd = TRUE;
+    shmdesc->addr = mmap(NULL, stuff->size,
+                         stuff->readOnly ? PROT_READ : PROT_READ|PROT_WRITE,
+                         MAP_SHARED,
+                         fd, 0);
+
+    if ((shmdesc->addr == ((char *) -1))) {
+        close(fd);
+        free(shmdesc);
+        return BadAccess;
+    }
+
+    shmdesc->refcnt = 1;
+    shmdesc->writable = !stuff->readOnly;
+    shmdesc->size = stuff->size;
+    shmdesc->next = Shmsegs;
+    Shmsegs = shmdesc;
+
+    if (!AddResource(stuff->shmseg, ShmSegType, (pointer) shmdesc)) {
+        close(fd);
+        return BadAlloc;
+    }
+
+    if (WriteFdToClient(client, fd, TRUE) < 0) {
+        FreeResource(stuff->shmseg, RT_NONE);
+        close(fd);
+        return BadAlloc;
+    }
+    WriteToClient(client, sizeof (xShmCreateSegmentReply), &rep);
+    return Success;
+}
+
+static int
 ProcShmDispatch(ClientPtr client)
 {
     REQUEST(xReq);
@@ -1116,6 +1239,10 @@ ProcShmDispatch(ClientPtr client)
             return ProcPanoramiXShmCreatePixmap(client);
 #endif
         return ProcShmCreatePixmap(client);
+    case X_ShmAttachFd:
+        return ProcShmAttachFd(client);
+    case X_ShmCreateSegment:
+        return ProcShmCreateSegment(client);
     default:
         return BadRequest;
     }
@@ -1217,6 +1344,28 @@ SProcShmCreatePixmap(ClientPtr client)
 }
 
 static int
+SProcShmAttachFd(ClientPtr client)
+{
+    REQUEST(xShmAttachFdReq);
+    SetReqFds(client, 1);
+    swaps(&stuff->length);
+    REQUEST_SIZE_MATCH(xShmAttachFdReq);
+    swapl(&stuff->shmseg);
+    return ProcShmAttachFd(client);
+}
+
+static int
+SProcShmCreateSegment(ClientPtr client)
+{
+    REQUEST(xShmCreateSegmentReq);
+    swaps(&stuff->length);
+    REQUEST_SIZE_MATCH(xShmCreateSegmentReq);
+    swapl(&stuff->shmseg);
+    swapl(&stuff->size);
+    return ProcShmCreateSegment(client);
+}
+
+static int
 SProcShmDispatch(ClientPtr client)
 {
     REQUEST(xReq);
@@ -1233,6 +1382,10 @@ SProcShmDispatch(ClientPtr client)
         return SProcShmGetImage(client);
     case X_ShmCreatePixmap:
         return SProcShmCreatePixmap(client);
+    case X_ShmAttachFd:
+        return SProcShmAttachFd(client);
+    case X_ShmCreateSegment:
+        return SProcShmCreateSegment(client);
     default:
         return BadRequest;
     }
diff --git a/Xext/shmint.h b/Xext/shmint.h
index 9002ce5..db35fbb 100644
--- a/Xext/shmint.h
+++ b/Xext/shmint.h
@@ -61,6 +61,7 @@ typedef struct _ShmDesc {
     int shmid;
     int refcnt;
     char *addr;
+    Bool is_fd;
     Bool writable;
     unsigned long size;
 } ShmDescRec, *ShmDescPtr;
diff --git a/include/os.h b/include/os.h
index b654a0d..11b2198 100644
--- a/include/os.h
+++ b/include/os.h
@@ -100,6 +100,8 @@ extern _X_EXPORT int ReadRequestFromClient(ClientPtr /*client */ );
 
 extern _X_EXPORT int ReadFdFromClient(ClientPtr client);
 
+extern _X_EXPORT int WriteFdToClient(ClientPtr client, int fd, Bool do_close);
+
 extern _X_EXPORT Bool InsertFakeRequest(ClientPtr /*client */ ,
                                         char * /*data */ ,
                                         int /*count */ );
diff --git a/os/io.c b/os/io.c
index 83df6e9..a20faa5 100644
--- a/os/io.c
+++ b/os/io.c
@@ -506,6 +506,14 @@ ReadFdFromClient(ClientPtr client)
     return fd;
 }
 
+int
+WriteFdToClient(ClientPtr client, int fd, Bool do_close)
+{
+    OsCommPtr oc = (OsCommPtr) client->osPrivate;
+
+    return _XSERVTransSendFd(oc->trans_conn, fd, do_close);
+}
+
 /*****************************************************************
  * InsertFakeRequest
  *    Splice a consed up (possibly partial) request in as the next request.
commit 9fd35daa3160fd36f00ed354bfcbefefa1353cce
Author: Keith Packard <keithp at keithp.com>
Date:   Thu Jan 17 13:43:02 2013 -0800

    Add interfaces to get FDs from clients over the socket
    
    This adds two interfaces:
    
        void SetReqFds(ClientPtr client, int req_fds)
    
    	Marks the number of file descriptors expected for this
    	request. Call this before any request processing so that
    	any un-retrieved file descriptors will be closed
    	automatically.
    
        int ReadFdFromClient(ClientPtr client)
    
    	Reads the next queued file descriptor from the connection. If
    	this request is not expecting any more file descriptors, or
    	if there are no more file descriptors available from the
    	connection, then this will return -1.
    
    Signed-off-by: Keith Packard <keithp at keithp.com>
    Reviewed-by: Adam Jackson <ajax at redhat.com>

diff --git a/include/dixstruct.h b/include/dixstruct.h
index 7711cde..456e633 100644
--- a/include/dixstruct.h
+++ b/include/dixstruct.h
@@ -110,8 +110,16 @@ typedef struct _Client {
 
     DeviceIntPtr clientPtr;
     ClientIdPtr clientIds;
+    int req_fds;
 } ClientRec;
 
+static inline void
+SetReqFds(ClientPtr client, int req_fds) {
+    if (client->req_fds != 0 && req_fds != client->req_fds)
+        LogMessage(X_ERROR, "Mismatching number of request fds %d != %d\n", req_fds, client->req_fds);
+    client->req_fds = req_fds;
+}
+
 /*
  * Scheduling interface
  */
diff --git a/include/os.h b/include/os.h
index 3840ab9..b654a0d 100644
--- a/include/os.h
+++ b/include/os.h
@@ -98,6 +98,8 @@ extern _X_EXPORT int WaitForSomething(int *     /*pClientsReady */
 
 extern _X_EXPORT int ReadRequestFromClient(ClientPtr /*client */ );
 
+extern _X_EXPORT int ReadFdFromClient(ClientPtr client);
+
 extern _X_EXPORT Bool InsertFakeRequest(ClientPtr /*client */ ,
                                         char * /*data */ ,
                                         int /*count */ );
diff --git a/os/io.c b/os/io.c
index 3800366..83df6e9 100644
--- a/os/io.c
+++ b/os/io.c
@@ -259,6 +259,12 @@ ReadRequestFromClient(ClientPtr client)
         oc->input = oci;
     }
 
+    /* Discard any unused file descriptors */
+    while (client->req_fds > 0) {
+        int req_fd = ReadFdFromClient(client);
+        if (req_fd >= 0)
+            close(req_fd);
+    }
     /* advance to start of next request */
 
     oci->bufptr += oci->lenLastReq;
@@ -485,6 +491,21 @@ ReadRequestFromClient(ClientPtr client)
     return needed;
 }
 
+int
+ReadFdFromClient(ClientPtr client)
+{
+    int fd = -1;
+
+    if (client->req_fds > 0) {
+        OsCommPtr oc = (OsCommPtr) client->osPrivate;
+
+        --client->req_fds;
+        fd = _XSERVTransRecvFd(oc->trans_conn);
+    } else
+        LogMessage(X_ERROR, "Request asks for FD without setting req_fds\n");
+    return fd;
+}
+
 /*****************************************************************
  * InsertFakeRequest
  *    Splice a consed up (possibly partial) request in as the next request.
commit 264fc3abe5f18341d0cf9ddb6766e10e4154e447
Author: Keith Packard <keithp at keithp.com>
Date:   Thu Oct 31 13:01:46 2013 -0700

    misync: Don't smash custom screen sync functions
    
    There was a check to avoid smashing custom functions, but the sense
    was backwards causing it to always smash them, and also not set them otherwise.
    
    Signed-off-by: Keith Packard <keithp at keithp.com>
    Reviewed-by: Adam Jackson <ajax at redhat.com>

diff --git a/miext/sync/misync.c b/miext/sync/misync.c
index b6914d1..f380547 100644
--- a/miext/sync/misync.c
+++ b/miext/sync/misync.c
@@ -190,7 +190,7 @@ miSyncSetup(ScreenPtr pScreen)
 
     pScreenPriv = SYNC_SCREEN_PRIV(pScreen);
 
-    if (pScreenPriv->funcs.CreateFence) {
+    if (!pScreenPriv->funcs.CreateFence) {
         pScreenPriv->funcs = miSyncScreenFuncs;
 
         /* Wrap CloseScreen to clean up */
commit 2d96948ab5c952b68875ac63844cf7d778d4bf63
Author: Keith Packard <keithp at keithp.com>
Date:   Thu Jul 11 16:10:34 2013 -0700

    os: Add GetTimeInMicros
    
    64-bit higher resolution current time value.
    
    Signed-off-by: Keith Packard <keithp at keithp.com>
    Reviewed-by: Adam Jackson <ajax at redhat.com>

diff --git a/include/os.h b/include/os.h
index c7108a5..3840ab9 100644
--- a/include/os.h
+++ b/include/os.h
@@ -165,6 +165,7 @@ extern void ListenOnOpenFD(int /* fd */ , int /* noxauth */ );
 #endif
 
 extern _X_EXPORT CARD32 GetTimeInMillis(void);
+extern _X_EXPORT CARD64 GetTimeInMicros(void);
 
 extern _X_EXPORT void AdjustWaitForDelay(pointer /*waitTime */ ,
                                          unsigned long /*newdelay */ );
diff --git a/os/utils.c b/os/utils.c
index 97c3125..995f62a 100644
--- a/os/utils.c
+++ b/os/utils.c
@@ -430,6 +430,11 @@ GetTimeInMillis(void)
 {
     return GetTickCount();
 }
+CARD64
+GetTimeInMicros(void)
+{
+    return (CARD64) GetTickCount() * 1000;
+}
 #else
 CARD32
 GetTimeInMillis(void)
@@ -460,6 +465,28 @@ GetTimeInMillis(void)
     X_GETTIMEOFDAY(&tv);
     return (tv.tv_sec * 1000) + (tv.tv_usec / 1000);
 }
+
+CARD64
+GetTimeInMicros(void)
+{
+    struct timeval tv;
+#ifdef MONOTONIC_CLOCK
+    struct timespec tp;
+    static clockid_t clockid;
+
+    if (!clockid) {
+        if (clock_gettime(CLOCK_MONOTONIC, &tp) == 0)
+            clockid = CLOCK_MONOTONIC;
+        else
+            clockid = ~0L;
+    }
+    if (clock_gettime(CLOCK_MONOTONIC, &tp) == 0)
+        return (CARD64) tp.tv_sec * (CARD64)1000000 + tp.tv_nsec / 1000;
+#endif
+
+    X_GETTIMEOFDAY(&tv);
+    return (CARD64) tv.tv_sec * (CARD64)1000000000 + (CARD64) tv.tv_usec * 1000;
+}
 #endif
 
 void
commit 0c33f47281c36726848daf513fb0483cdea57bff
Author: Keith Packard <keithp at keithp.com>
Date:   Thu Jul 11 16:09:34 2013 -0700

    Add swapll to byte swap 64-bit datatypes
    
    Signed-off-by: Keith Packard <keithp at keithp.com>
    Reviewed-by: Adam Jackson <ajax at redhat.com>

diff --git a/include/misc.h b/include/misc.h
index 0c67f11..17de710 100644
--- a/include/misc.h
+++ b/include/misc.h
@@ -305,6 +305,35 @@ __builtin_constant_p(int x)
 }
 #endif
 
+/* byte swap a 64-bit value */
+static inline void
+swap_uint64(uint64_t *x)
+{
+    char n;
+
+    n = ((char *) x)[0];
+    ((char *) x)[0] = ((char *) x)[7];
+    ((char *) x)[7] = n;
+
+    n = ((char *) x)[1];
+    ((char *) x)[1] = ((char *) x)[6];
+    ((char *) x)[6] = n;
+
+    n = ((char *) x)[2];
+    ((char *) x)[2] = ((char *) x)[5];
+    ((char *) x)[5] = n;
+
+    n = ((char *) x)[3];
+    ((char *) x)[3] = ((char *) x)[4];
+    ((char *) x)[4] = n;
+}
+
+#define swapll(x) do { \
+		if (sizeof(*(x)) != 8) \
+			wrong_size(); \
+                swap_uint64((uint64_t *)(x));   \
+	} while (0)
+
 /* byte swap a 32-bit value */
 static inline void
 swap_uint32(uint32_t * x)
commit 26f013ba45b08a02bb028a461af68288a86fadb1
Author: Keith Packard <keithp at keithp.com>
Date:   Thu Jul 11 16:08:41 2013 -0700

    Add a RegionDuplicate function
    
    This allocates a new region structure and copies a source region into
    it in a single API rather than forcing the caller to do both steps themselves.
    
    Signed-off-by: Keith Packard <keithp at keithp.com>
    Reviewed-by: Adam Jackson <ajax at redhat.com>

diff --git a/dix/region.c b/dix/region.c
index 737d2a8..15f3d01 100644
--- a/dix/region.c
+++ b/dix/region.c
@@ -255,6 +255,21 @@ RegionDestroy(RegionPtr pReg)
         free(pReg);
 }
 
+RegionPtr
+RegionDuplicate(RegionPtr pOld)
+{
+    RegionPtr   pNew;
+
+    pNew = RegionCreate(&pOld->extents, 0);
+    if (!pNew)
+        return NULL;
+    if (!RegionCopy(pNew, pOld)) {
+        RegionDestroy(pNew);
+        return NULL;
+    }
+    return pNew;
+}
+
 void
 RegionPrint(RegionPtr rgn)
 {
diff --git a/include/regionstr.h b/include/regionstr.h
index 805257b..4a0725d 100644
--- a/include/regionstr.h
+++ b/include/regionstr.h
@@ -213,6 +213,8 @@ extern _X_EXPORT RegionPtr RegionCreate(BoxPtr /*rect */ ,
 
 extern _X_EXPORT void RegionDestroy(RegionPtr /*pReg */ );
 
+extern _X_EXPORT RegionPtr RegionDuplicate(RegionPtr /* pOld */);
+
 static inline Bool
 RegionCopy(RegionPtr dst, RegionPtr src)
 {
commit d25c217964eb1fe54c3a54bca4cac7f47b4b9fdf
Author: Keith Packard <keithp at keithp.com>
Date:   Mon Jan 14 14:24:36 2013 -0800

    Clean up a couple of warnings in os/
    
    Signed-off-by: Keith Packard <keithp at keithp.com>
    Reviewed-by: Adam Jackson <ajax at redhat.com>

diff --git a/os/connection.c b/os/connection.c
index 6cd8bcf..162e1d9 100644
--- a/os/connection.c
+++ b/os/connection.c
@@ -923,7 +923,7 @@ ErrorConnMax(XtransConnInfo trans_conn)
         iov[0].iov_len = sz_xConnSetupPrefix;
         iov[0].iov_base = (char *) &csp;
         iov[1].iov_len = csp.lengthReason;
-        iov[1].iov_base = NOROOM;
+        iov[1].iov_base = (void *) NOROOM;
         iov[2].iov_len = (4 - (csp.lengthReason & 3)) & 3;
         iov[2].iov_base = pad;
         (void) _XSERVTransWritev(trans_conn, iov, 3);
diff --git a/os/xstrans.c b/os/xstrans.c
index 6348a65..2bc79e7 100644
--- a/os/xstrans.c
+++ b/os/xstrans.c
@@ -5,9 +5,11 @@
 #include <X11/Xfuncproto.h>
 
 /* ErrorF is used by xtrans */
+#ifndef HAVE_DIX_CONFIG_H
 extern _X_EXPORT void
 ErrorF(const char *f, ...)
 _X_ATTRIBUTE_PRINTF(1, 2);
+#endif
 
 #define TRANS_REOPEN
 #define TRANS_SERVER
commit 7710f2b927ec8e3c631f72d66d494b523377b48e
Author: Keith Packard <keithp at keithp.com>
Date:   Fri Jan 18 21:43:40 2013 -0800

    Xext: Move MIT-SHM 'ShmDesc' to shmint.h
    
    This data structure is required to use shared memory objects in any
    extension. That includes the Xv extension, which (before this patch)
    duplicated the definition of this structure in its own code.
    
    Signed-off-by: Keith Packard <keithp at keithp.com>
    Reviewed-by: Adam Jackson <ajax at redhat.com>

diff --git a/Xext/shm.c b/Xext/shm.c
index 5596090..f6995cc 100644
--- a/Xext/shm.c
+++ b/Xext/shm.c
@@ -89,15 +89,6 @@ in this Software without prior written authorization from The Open Group.
 
 #include "extinit.h"
 
-typedef struct _ShmDesc {
-    struct _ShmDesc *next;
-    int shmid;
-    int refcnt;
-    char *addr;
-    Bool writable;
-    unsigned long size;
-} ShmDescRec, *ShmDescPtr;
-
 typedef struct _ShmScrPrivateRec {
     CloseScreenProcPtr CloseScreen;
     ShmFuncsPtr shmFuncs;
diff --git a/Xext/shmint.h b/Xext/shmint.h
index fa6941c..9002ce5 100644
--- a/Xext/shmint.h
+++ b/Xext/shmint.h
@@ -56,6 +56,15 @@ typedef struct _ShmFuncs {
     void (*PutImage) (XSHM_PUT_IMAGE_ARGS);
 } ShmFuncs, *ShmFuncsPtr;
 
+typedef struct _ShmDesc {
+    struct _ShmDesc *next;
+    int shmid;
+    int refcnt;
+    char *addr;
+    Bool writable;
+    unsigned long size;
+} ShmDescRec, *ShmDescPtr;
+
 extern _X_EXPORT void
  ShmRegisterFuncs(ScreenPtr pScreen, ShmFuncsPtr funcs);
 
diff --git a/Xext/xvdisp.c b/Xext/xvdisp.c
index 7877293..613867a 100644
--- a/Xext/xvdisp.c
+++ b/Xext/xvdisp.c
@@ -43,6 +43,7 @@ SOFTWARE.
 #include "xvdix.h"
 #ifdef MITSHM
 #include <X11/extensions/shmproto.h>
+#include "shmint.h"
 #endif
 
 #include "xvdisp.h"
@@ -949,18 +950,6 @@ ProcXvPutImage(ClientPtr client)
 }
 
 #ifdef MITSHM
-/* redefined here since it's not in any header file */
-typedef struct _ShmDesc {
-    struct _ShmDesc *next;
-    int shmid;
-    int refcnt;
-    char *addr;
-    Bool writable;
-    unsigned long size;
-} ShmDescRec, *ShmDescPtr;
-
-extern RESTYPE ShmSegType;
-extern int ShmCompletionCode;
 
 static int
 ProcXvShmPutImage(ClientPtr client)
commit e8961b718d82f1c081ec110d8d962f64e8406b82
Author: Peter Hutterer <peter.hutterer at who-t.net>
Date:   Tue Oct 22 14:24:52 2013 +1000

    os: use a constant for backtrace array size
    
    Signed-off-by: Peter Hutterer <peter.hutterer at who-t.net>
    Reviewed-by: Jasper St. Pierre <jstpierre at mecheye.net>

diff --git a/os/backtrace.c b/os/backtrace.c
index 426f9b1..3d1195b 100644
--- a/os/backtrace.c
+++ b/os/backtrace.c
@@ -114,14 +114,15 @@ xorg_backtrace(void)
 void
 xorg_backtrace(void)
 {
-    void *array[64];
+    const int BT_SIZE = 64;
+    void *array[BT_SIZE];
     const char *mod;
     int size, i;
     Dl_info info;
 
     ErrorFSigSafe("\n");
     ErrorFSigSafe("Backtrace:\n");
-    size = backtrace(array, 64);
+    size = backtrace(array, BT_SIZE);
     for (i = 0; i < size; i++) {
         int rc = dladdr(array[i], &info);
 
commit f12a9ed870017f35cf6d2a82b1405e843aae42ac
Author: Peter Hutterer <peter.hutterer at who-t.net>
Date:   Tue Oct 29 15:24:11 2013 +1000

    configure: remove a comment
    
    94ed0ba1b5043ad9fc33b42756af447d5ab15bbd moved backtracing into the DIX, so
    this comment is outdated. since no-one noticed and it's easier to just grep
    than update file references, remove the comment.
    
    Signed-off-by: Peter Hutterer <peter.hutterer at who-t.net>
    Reviewed-by: Jasper St. Pierre <jstpierre at mecheye.net>

diff --git a/configure.ac b/configure.ac
index e7385f8..75ec70b 100644
--- a/configure.ac
+++ b/configure.ac
@@ -300,7 +300,7 @@ AC_CHECK_HEADER([machine/apmvar.h],[
 AM_CONDITIONAL(BSD_APM, [test "x$ac_cv_BSD_APM" = xyes])
 AM_CONDITIONAL(BSD_KQUEUE_APM, [test "x$ac_cv_BSD_KQUEUE_APM" = xyes])
 	
-dnl glibc backtrace support check (hw/xfree86/common/xf86Events.c)
+dnl glibc backtrace support check
 AC_CHECK_HEADER([execinfo.h],[
     AC_CHECK_LIB(c, backtrace, [
         AC_DEFINE(HAVE_BACKTRACE, 1, [Has backtrace support])


More information about the Xquartz-changes mailing list