diff --git a/configure.ac b/configure.ac
index 0783d61..13b9970 100644
--- a/configure.ac
+++ b/configure.ac
@@ -276,6 +276,7 @@ XORG_DRIVER_CHECK_EXT(RANDR, randrproto)
 XORG_DRIVER_CHECK_EXT(RENDER, renderproto)
 XORG_DRIVER_CHECK_EXT(XF86DRI, xextproto x11)
 XORG_DRIVER_CHECK_EXT(DPMSExtension, xextproto)
+XORG_DRIVER_CHECK_EXT(DRI3, dri3proto)
 
 # Obtain compiler/linker options for the driver dependencies
 PKG_CHECK_MODULES(DRM, [libdrm >= 2.4.20]) # libdrm_intel is checked separately
@@ -463,6 +464,19 @@ else
 	UXA=no
 fi
 
+if test "x$DRI3" != "xno"; then
+	save_CFLAGS=$CFLAGS
+	CFLAGS="$XORG_CFLAGS $DRM_CFLAGS $DRI_CFLAGS $DRI3_CFLAGS"
+	AC_CHECK_DECL(DRI3,
+		      [DRI3=yes], [DRI3=no],
+		      [#include <xorg-server.h>])
+	CFLAGS=$save_CFLAGS
+	dri_msg="$dri_msg DRI3"
+fi
+AC_MSG_CHECKING([whether to include DRI3 support])
+AM_CONDITIONAL(DRI3, test "x$DRI3" = xyes)
+AC_MSG_RESULT([$DRI3])
+
 AC_CHECK_HEADERS([X11/extensions/dpmsconst.h])
 
 AC_MSG_CHECKING([whether to include UXA support])
diff --git a/src/uxa/Makefile.am b/src/uxa/Makefile.am
index 971ac21..3c9e693 100644
--- a/src/uxa/Makefile.am
+++ b/src/uxa/Makefile.am
@@ -80,6 +80,13 @@ libuxa_la_LIBADD += \
 	$(NULL)
 endif
 
+if DRI3
+libuxa_la_SOURCES += \
+	intel_dri3.c \
+	intel_sync.c \
+	$(NULL)
+endif
+
 if XVMC
 AM_CFLAGS += -I$(top_srcdir)/xvmc
 libuxa_la_SOURCES += \
diff --git a/src/uxa/intel.h b/src/uxa/intel.h
index 922b208..c3d00f4 100644
--- a/src/uxa/intel.h
+++ b/src/uxa/intel.h
@@ -59,6 +59,7 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 #include "xf86xv.h"
 #include "xf86Crtc.h"
 #include "xf86RandR12.h"
+#include "misync.h"
 
 #include "xorg-server.h"
 #include <pciaccess.h>
@@ -352,6 +353,11 @@ typedef struct intel_screen_private {
 	InputHandlerProc uevent_handler;
 #endif
 	Bool has_prime_vmap_flush;
+
+        SyncScreenFuncsRec save_sync_screen_funcs;
+
+        void (*flush_rendering)(struct intel_screen_private *intel);
+
 } intel_screen_private;
 
 #define INTEL_INFO(intel) ((intel)->info)
@@ -519,6 +525,9 @@ void I830DRI2FrameEventHandler(unsigned int frame, unsigned int tv_sec,
 void I830DRI2FlipEventHandler(unsigned int frame, unsigned int tv_sec,
 			      unsigned int tv_usec, DRI2FrameEventPtr flip_info);
 
+/* intel_dri3.c */
+Bool intel_dri3_screen_init(ScreenPtr screen);
+
 extern Bool intel_crtc_on(xf86CrtcPtr crtc);
 int intel_crtc_to_pipe(xf86CrtcPtr crtc);
 
@@ -725,4 +734,12 @@ static inline Bool intel_pixmap_is_offscreen(PixmapPtr pixmap)
 	return priv && priv->offscreen;
 }
 
+#if DRI3
+Bool
+intel_sync_init(ScreenPtr screen);
+#endif
+
+void
+intel_sync_close(ScreenPtr screen);
+
 #endif /* _I830_H_ */
diff --git a/src/uxa/intel_dri3.c b/src/uxa/intel_dri3.c
new file mode 100644
index 0000000..99ac9d5
--- /dev/null
+++ b/src/uxa/intel_dri3.c
@@ -0,0 +1,184 @@
+/*
+ * 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_CONFIG_H
+#include "config.h"
+#endif
+
+#include <stdio.h>
+#include <string.h>
+#include <assert.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/ioctl.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <sys/time.h>
+#include <time.h>
+#include <errno.h>
+
+#include "xf86.h"
+#include "xf86_OSproc.h"
+
+#include "xf86Pci.h"
+#include "xf86drm.h"
+
+#include "windowstr.h"
+#include "shadow.h"
+#include "fb.h"
+
+#include "intel.h"
+#include "i830_reg.h"
+
+#include "i915_drm.h"
+
+#include "dri3.h"
+
+#include "intel_glamor.h"
+#include "uxa.h"
+
+static int
+intel_dri3_open(ScreenPtr screen,
+                RRProviderPtr provider,
+                int *fdp)
+{
+	ScrnInfoPtr scrn = xf86ScreenToScrn(screen);
+	intel_screen_private *intel = intel_get_screen_private(scrn);
+        drm_magic_t magic;
+        int fd;
+
+        /* Open the device for the client */
+        fd = open(intel->deviceName, O_RDWR | O_CLOEXEC);
+        if (fd == -1 && errno == EINVAL) {
+                fd = open(intel->deviceName, O_RDWR);
+                if (fd != -1)
+                    fcntl(fd, F_SETFD, fcntl(fd, F_GETFD) | FD_CLOEXEC);
+        }
+
+        if (fd < 0)
+                return BadAlloc;
+
+        /* Go through the auth dance locally */
+        if (drmGetMagic(fd, &magic) < 0) {
+                close(fd);
+                return BadMatch;
+        }
+
+        if (drmAuthMagic(intel->drmSubFD, magic) < 0) {
+                close (fd);
+                return BadMatch;
+        }
+
+        /* And we're done */
+        *fdp = fd;
+        return Success;
+}
+
+static PixmapPtr intel_dri3_pixmap_from_fd (ScreenPtr screen,
+                                            int fd,
+                                            CARD16 width,
+                                            CARD16 height,
+                                            CARD16 stride,
+                                            CARD8 depth,
+                                            CARD8 bpp)
+{
+	ScrnInfoPtr scrn = xf86ScreenToScrn(screen);
+	intel_screen_private *intel = intel_get_screen_private(scrn);
+	struct intel_pixmap *priv;
+	PixmapPtr pixmap;
+        uint32_t bit_6_swizzle, tiling;
+        int ret;
+
+        if (depth == 1)
+                return NULL;
+
+        pixmap = fbCreatePixmap(screen, 0, 0, depth, 0);
+        if (!pixmap)
+                goto no_pixmap;
+        priv = calloc(1, sizeof (struct intel_pixmap));
+        if (priv == NULL)
+                goto no_priv;
+
+        priv->bo = drm_intel_bo_gem_create_from_prime(intel->bufmgr,
+                                                      fd, (uint32_t) height * stride);
+        if (priv->bo == NULL)
+                goto no_bo;
+
+        ret = drm_intel_bo_get_tiling(priv->bo, &tiling, &bit_6_swizzle);
+        if (ret != 0)
+                goto no_tiling;
+
+        priv->stride = stride;
+        priv->tiling = tiling;
+        priv->offscreen = 1;
+        list_init(&priv->batch);
+        intel_set_pixmap_private(pixmap, priv);
+
+        screen->ModifyPixmapHeader(pixmap, width, height, 0, 0, stride, NULL);
+
+        return pixmap;
+no_tiling:
+        drm_intel_bo_unreference(priv->bo);
+no_bo:
+        free (priv);
+no_priv:
+        fbDestroyPixmap(pixmap);
+no_pixmap:
+        return NULL;
+}
+
+static int intel_dri3_fd_from_pixmap (ScreenPtr screen,
+                                      PixmapPtr pixmap,
+                                      CARD16 *stride,
+                                      CARD32 *size)
+{
+	struct intel_pixmap     *priv;
+	ScrnInfoPtr             scrn = xf86ScreenToScrn(screen);
+	intel_screen_private    *intel = intel_get_screen_private(scrn);
+        int                     fd;
+        int                     ret;
+
+        priv = intel_get_pixmap_private(pixmap);
+        if (!priv)
+                return -1;
+        (*intel->flush_rendering)(intel);
+        ret = drm_intel_bo_gem_export_to_prime(priv->bo, &fd);
+        if (ret < 0)
+                return -1;
+        *stride = priv->stride;
+        *size = priv->bo->size;
+        return fd;
+}
+
+static dri3_screen_info_rec intel_dri3_screen_info = {
+        .version = DRI3_SCREEN_INFO_VERSION,
+
+        .open = intel_dri3_open,
+        .pixmap_from_fd = intel_dri3_pixmap_from_fd,
+        .fd_from_pixmap = intel_dri3_fd_from_pixmap
+};
+
+Bool
+intel_dri3_screen_init(ScreenPtr screen)
+{
+        return dri3_screen_init(screen, &intel_dri3_screen_info);
+}
diff --git a/src/uxa/intel_driver.c b/src/uxa/intel_driver.c
index 431c34b..12c7b34 100644
--- a/src/uxa/intel_driver.c
+++ b/src/uxa/intel_driver.c
@@ -1050,6 +1050,10 @@ I830ScreenInit(SCREEN_INIT_ARGS_DECL)
 	if (intel->XvEnabled)
 		I830InitVideo(screen);
 
+#if DRI3
+        intel_dri3_screen_init(screen);
+#endif
+
 #if defined(DRI2)
 	switch (intel->directRenderingType) {
 	case DRI_DRI2:
@@ -1076,6 +1080,11 @@ I830ScreenInit(SCREEN_INIT_ARGS_DECL)
 
 	intel_mode_init(intel);
 
+
+#if DRI3
+        (void) intel_sync_init(screen);
+#endif
+
 	intel->suspended = FALSE;
 
 #if HAVE_UDEV
@@ -1163,6 +1172,10 @@ static Bool I830CloseScreen(CLOSE_SCREEN_ARGS_DECL)
 	I830UeventFini(scrn);
 #endif
 
+#if DRI3
+        intel_sync_close(screen);
+#endif
+
 	intel_mode_close(intel);
 
 	DeleteCallback(&FlushCallback, intel_flush_callback, scrn);
diff --git a/src/uxa/intel_sync.c b/src/uxa/intel_sync.c
new file mode 100644
index 0000000..94426d3
--- /dev/null
+++ b/src/uxa/intel_sync.c
@@ -0,0 +1,109 @@
+/*
+ * 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.
+ */
+
+#include "intel.h"
+#include "misyncshm.h"
+#include "misyncstr.h"
+
+/*
+ * This whole file exists to wrap a sync fence trigger operation
+ * so that we can flush the batch buffer to provide serialization
+ * between the server and the shm fence client
+ */
+
+static DevPrivateKeyRec intel_sync_fence_private_key;
+
+typedef struct _intel_sync_fence_private {
+        SyncFenceSetTriggeredFunc set_triggered;
+} intel_sync_fence_private;
+
+#define SYNC_FENCE_PRIV(pFence)                                         \
+        (intel_sync_fence_private *) dixLookupPrivate(&pFence->devPrivates, &intel_sync_fence_private_key)
+
+static void
+intel_sync_fence_set_triggered (SyncFence *fence)
+{
+        ScreenPtr screen = fence->pScreen;
+        ScrnInfoPtr scrn = xf86ScreenToScrn(screen);
+        intel_screen_private *intel = intel_get_screen_private(scrn);
+        intel_sync_fence_private *private = SYNC_FENCE_PRIV(fence);
+
+
+        /* Flush pending rendering operations */
+        if (intel->flush_rendering)
+                intel->flush_rendering(intel);
+
+        fence->funcs.SetTriggered = private->set_triggered;
+        (*fence->funcs.SetTriggered)(fence);
+        private->set_triggered = fence->funcs.SetTriggered;
+        fence->funcs.SetTriggered = intel_sync_fence_set_triggered;
+}
+
+static void
+intel_sync_create_fence(ScreenPtr screen,
+                        SyncFence *fence,
+                        Bool initially_triggered)
+{
+        ScrnInfoPtr scrn = xf86ScreenToScrn(screen);
+        intel_screen_private *intel = intel_get_screen_private(scrn);
+        SyncScreenFuncsPtr screen_funcs = miSyncGetScreenFuncs(screen);
+        intel_sync_fence_private *private = SYNC_FENCE_PRIV(fence);
+
+        screen_funcs->CreateFence = intel->save_sync_screen_funcs.CreateFence;
+        (*screen_funcs->CreateFence)(screen, fence, initially_triggered);
+
+        private->set_triggered = fence->funcs.SetTriggered;
+        fence->funcs.SetTriggered = intel_sync_fence_set_triggered;
+}
+
+Bool
+intel_sync_init(ScreenPtr screen)
+{
+        ScrnInfoPtr scrn = xf86ScreenToScrn(screen);
+        intel_screen_private *intel = intel_get_screen_private(scrn);
+        SyncScreenFuncsPtr screen_funcs;
+        if (!miSyncShmScreenInit(screen))
+                return FALSE;
+
+        if (!dixPrivateKeyRegistered(&intel_sync_fence_private_key)) {
+                if (!dixRegisterPrivateKey(&intel_sync_fence_private_key,
+                                           PRIVATE_SYNC_FENCE,
+                                           sizeof (intel_sync_fence_private)))
+                        return FALSE;
+        }
+
+        screen_funcs = miSyncGetScreenFuncs(screen);
+        intel->save_sync_screen_funcs.CreateFence = screen_funcs->CreateFence;
+        screen_funcs->CreateFence = intel_sync_create_fence;
+        return TRUE;
+}
+
+void
+intel_sync_close(ScreenPtr screen)
+{
+        ScrnInfoPtr scrn = xf86ScreenToScrn(screen);
+        intel_screen_private *intel = intel_get_screen_private(scrn);
+        SyncScreenFuncsPtr screen_funcs = miSyncGetScreenFuncs(screen);
+
+        if (screen_funcs)
+                screen_funcs->CreateFence = intel->save_sync_screen_funcs.CreateFence;
+}
diff --git a/src/uxa/intel_uxa.c b/src/uxa/intel_uxa.c
index 6fb1333..a31d196 100644
--- a/src/uxa/intel_uxa.c
+++ b/src/uxa/intel_uxa.c
@@ -1420,5 +1420,6 @@ Bool intel_uxa_init(ScreenPtr screen)
 	uxa_set_fallback_debug(screen, intel->fallback_debug);
 	uxa_set_force_fallback(screen, intel->force_fallback);
 
+        intel->flush_rendering = intel_flush_rendering;
 	return TRUE;
 }
