xf86-video-ati: Branch 'master' - 14 commits

Michel Dänzer daenzer at kemper.freedesktop.org
Mon Mar 16 19:12:37 PDT 2015


 configure.ac           |   35 ++-
 man/radeon.man         |    4 
 src/Makefile.am        |    7 
 src/drmmode_display.c  |  114 ++++++++----
 src/drmmode_display.h  |   13 +
 src/radeon.h           |   52 +++++
 src/radeon_accel.c     |    1 
 src/radeon_bo_helper.c |   43 ++++
 src/radeon_dri2.c      |  463 ++++++++++++++++++-------------------------------
 src/radeon_dri2.h      |   37 ---
 src/radeon_dri3.c      |  201 +++++++++++++++++++++
 src/radeon_drm_queue.c |  181 +++++++++++++++++++
 src/radeon_drm_queue.h |   56 +++++
 src/radeon_exa.c       |    1 
 src/radeon_glamor.c    |   13 -
 src/radeon_glamor.h    |   35 ---
 src/radeon_kms.c       |   47 ++++
 src/radeon_list.h      |   38 ++++
 src/radeon_present.c   |  418 ++++++++++++++++++++++++++++++++++++++++++++
 src/radeon_sync.c      |  144 +++++++++++++++
 src/radeon_video.c     |    1 
 21 files changed, 1475 insertions(+), 429 deletions(-)

New commits:
commit 64e1e4dbdd3caee6f5d8f6b6c094b4533fa94953
Author: Michel Dänzer <michel.daenzer at amd.com>
Date:   Tue Mar 10 16:53:11 2015 +0900

    Add DRI3 support v2
    
    Must be enabled with
    
    	Option	"DRI3"
    
    in xorg.conf.
    
    v2: Adapt to v2 of patches 11/12.
    
    Reviewed-by: Alex Deucher <alexander.deucher at amd.com>

diff --git a/configure.ac b/configure.ac
index 71d8ff0..acd9fe0 100644
--- a/configure.ac
+++ b/configure.ac
@@ -143,6 +143,10 @@ AC_CHECK_HEADERS([present.h], [], [],
 		 #include <X11/X.h>
 		 #include "xorg-server.h"])
 
+AC_CHECK_HEADERS([dri3.h], [], [],
+		 [#include <X11/Xmd.h>
+		 #include <xorg-server.h>])
+
 CPPFLAGS="$SAVE_CPPFLAGS"
 
 PKG_CHECK_MODULES([PCIACCESS], [pciaccess >= 0.8.0])
diff --git a/man/radeon.man b/man/radeon.man
index 7dde040..6e46f89 100644
--- a/man/radeon.man
+++ b/man/radeon.man
@@ -267,6 +267,10 @@ The default value is
 for R/RV6XX, R/RV7XX, RS780, RS880, EVERGREEN, CAYMAN, ARUBA, Southern Islands, and
 Sea Islands.
 .TP
+.BI "Option \*qDRI3\*q \*q" boolean \*q
+Enable the DRI3 extension. The default is
+.B off.
+.TP
 .BI "Option \*qEnablePageFlip\*q \*q" boolean \*q
 Enable DRI2 page flipping.  The default is
 .B on.
diff --git a/src/Makefile.am b/src/Makefile.am
index a3d732a..697c08c 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -29,8 +29,9 @@
 ati_drv_la_LIBADD = $(PCIACCESS_LIBS)
 radeon_drv_la_LIBADD = $(LIBDRM_RADEON_LIBS) $(PCIACCESS_LIBS)
 
-RADEON_KMS_SRCS=radeon_dri2.c radeon_drm_queue.c radeon_kms.c radeon_present.c \
-	radeon_sync.c radeon_vbo.c radeon_bo_helper.c drmmode_display.c
+RADEON_KMS_SRCS=radeon_dri2.c radeon_dri3.c radeon_drm_queue.c radeon_kms.c \
+	radeon_present.c radeon_sync.c radeon_vbo.c radeon_bo_helper.c \
+	drmmode_display.c
 
 RADEON_EXA_SOURCES = radeon_exa.c r600_exa.c r6xx_accel.c r600_textured_videofuncs.c r600_shader.c radeon_exa_shared.c \
 	evergreen_exa.c evergreen_accel.c evergreen_shader.c evergreen_textured_videofuncs.c cayman_accel.c cayman_shader.c
diff --git a/src/radeon.h b/src/radeon.h
index 9346fbd..6084cfe 100644
--- a/src/radeon.h
+++ b/src/radeon.h
@@ -150,6 +150,7 @@ typedef enum {
     OPTION_ZAPHOD_HEADS,
     OPTION_SWAPBUFFERS_WAIT,
     OPTION_DELETE_DP12,
+    OPTION_DRI3,
 } RADEONOpts;
 
 
@@ -549,6 +550,9 @@ extern Bool RADEONGetDatatypeBpp(int bpp, uint32_t *type);
 extern Bool RADEONGetPixmapOffsetPitch(PixmapPtr pPix,
 				       uint32_t *pitch_offset);
 
+/* radeon_dri3.c */
+Bool radeon_dri3_screen_init(ScreenPtr screen);
+
 /* radeon_present.c */
 Bool radeon_present_screen_init(ScreenPtr screen);
 
diff --git a/src/radeon_dri3.c b/src/radeon_dri3.c
new file mode 100644
index 0000000..83bffae
--- /dev/null
+++ b/src/radeon_dri3.c
@@ -0,0 +1,201 @@
+/*
+ * Copyright © 2013-2014 Intel Corporation
+ * Copyright © 2015 Advanced Micro Devices, Inc.
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, provided that
+ * the above copyright notice appear in all copies and that both that copyright
+ * notice and this permission notice appear in supporting documentation, and
+ * that the name of 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 "xorg-server.h"
+#include "xf86.h"
+#include "fb.h"
+
+#ifdef HAVE_DRI3_H
+
+#include "radeon.h"
+#include "radeon_bo_gem.h"
+#include "radeon_glamor.h"
+#include "dri3.h"
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <errno.h>
+
+
+static int
+radeon_dri3_open_client(ClientPtr client,
+			ScreenPtr screen,
+			RRProviderPtr provider,
+			int *out)
+{
+	ScrnInfoPtr scrn = xf86ScreenToScrn(screen);
+	RADEONInfoPtr info = RADEONPTR(scrn);
+	drm_magic_t magic;
+	int fd;
+
+	fd = open(info->dri2.device_name, O_RDWR | O_CLOEXEC);
+	if (fd < 0)
+		return BadAlloc;
+
+	/* Before FD passing in the X protocol with DRI3 (and increased
+	 * security of rendering with per-process address spaces on the
+	 * GPU), the kernel had to come up with a way to have the server
+	 * decide which clients got to access the GPU, which was done by
+	 * each client getting a unique (magic) number from the kernel,
+	 * passing it to the server, and the server then telling the
+	 * kernel which clients were authenticated for using the device.
+	 *
+	 * Now that we have FD passing, the server can just set up the
+	 * authentication on its own and hand the prepared FD off to the
+	 * client.
+	 */
+	if (drmGetMagic(fd, &magic) < 0) {
+		if (errno == EACCES) {
+			/* Assume that we're on a render node, and the fd is
+			 * already as authenticated as it should be.
+			 */
+			*out = fd;
+			return Success;
+		} else {
+			close(fd);
+			return BadMatch;
+		}
+	}
+
+	if (drmAuthMagic(info->dri2.drm_fd, magic) < 0) {
+		close(fd);
+		return BadMatch;
+	}
+
+	*out = fd;
+	return Success;
+}
+
+static PixmapPtr radeon_dri3_pixmap_from_fd(ScreenPtr screen,
+					    int fd,
+					    CARD16 width,
+					    CARD16 height,
+					    CARD16 stride,
+					    CARD8 depth,
+					    CARD8 bpp)
+{
+	PixmapPtr pixmap;
+
+	if (depth < 8)
+		return NULL;
+
+	switch (bpp) {
+	case 8:
+	case 16:
+	case 32:
+		break;
+	default:
+		return NULL;
+	}
+
+	pixmap = fbCreatePixmap(screen, 0, 0, depth, 0);
+	if (!pixmap)
+		return NULL;
+
+	if (!screen->ModifyPixmapHeader(pixmap, width, height, 0, 0, stride, NULL))
+		goto free_pixmap;
+
+	if (screen->SetSharedPixmapBacking(pixmap, (void*)(intptr_t)fd))
+		return pixmap;
+
+free_pixmap:
+	fbDestroyPixmap(pixmap);
+	return NULL;
+}
+
+static int radeon_dri3_fd_from_pixmap(ScreenPtr screen,
+				      PixmapPtr pixmap,
+				      CARD16 *stride,
+				      CARD32 *size)
+{
+	struct radeon_bo *bo;
+	int fd;
+
+	bo = radeon_get_pixmap_bo(pixmap);
+	if (!bo) {
+#ifdef USE_GLAMOR
+		ScrnInfoPtr scrn = xf86ScreenToScrn(screen);
+		RADEONInfoPtr info = RADEONPTR(scrn);
+
+		if (info->use_glamor)
+			return glamor_fd_from_pixmap(screen, pixmap, stride, size);
+#endif
+
+		exaMoveInPixmap(pixmap);
+		bo = radeon_get_pixmap_bo(pixmap);
+		if (!bo)
+			return -1;
+	}
+
+	if (pixmap->devKind > UINT16_MAX)
+		return -1;
+
+	if (radeon_gem_prime_share_bo(bo, &fd) < 0)
+		return -1;
+
+	*stride = pixmap->devKind;
+	*size = bo->size;
+	return fd;
+}
+
+static dri3_screen_info_rec radeon_dri3_screen_info = {
+	.version = 1,
+
+	.open_client = radeon_dri3_open_client,
+	.pixmap_from_fd = radeon_dri3_pixmap_from_fd,
+	.fd_from_pixmap = radeon_dri3_fd_from_pixmap
+};
+
+Bool
+radeon_dri3_screen_init(ScreenPtr screen)
+{
+	ScrnInfoPtr scrn = xf86ScreenToScrn(screen);
+
+	if (!dri3_screen_init(screen, &radeon_dri3_screen_info)) {
+		xf86DrvMsg(scrn->scrnIndex, X_WARNING,
+			   "dri3_screen_init failed\n");
+		return FALSE;
+	}
+
+	return TRUE;
+}
+
+#else /* !HAVE_DRI3_H */
+
+Bool
+radeon_dri3_screen_init(ScreenPtr screen)
+{
+	xf86DrvMsg(xf86ScreenToScrn(screen)->scrnIndex, X_INFO,
+		   "Can't initialize DRI3 because dri3.h not available at "
+		   "build time\n");
+
+	return FALSE;
+}
+
+#endif
diff --git a/src/radeon_kms.c b/src/radeon_kms.c
index f4452bc..b32086e 100644
--- a/src/radeon_kms.c
+++ b/src/radeon_kms.c
@@ -76,6 +76,7 @@ const OptionInfoRec RADEONOptions_KMS[] = {
     { OPTION_ZAPHOD_HEADS,   "ZaphodHeads",      OPTV_STRING,  {0}, FALSE },
     { OPTION_SWAPBUFFERS_WAIT,"SwapbuffersWait", OPTV_BOOLEAN, {0}, FALSE },
     { OPTION_DELETE_DP12,    "DeleteUnusedDP12Displays", OPTV_BOOLEAN, {0}, FALSE},
+    { OPTION_DRI3,           "DRI3",             OPTV_BOOLEAN, {0}, FALSE },
     { -1,                    NULL,               OPTV_NONE,    {0}, FALSE }
 };
 
@@ -1230,6 +1231,8 @@ Bool RADEONScreenInit_KMS(SCREEN_INIT_ARGS_DECL)
     ScrnInfoPtr    pScrn = xf86ScreenToScrn(pScreen);
     RADEONInfoPtr  info  = RADEONPTR(pScrn);
     int            subPixelOrder = SubPixelUnknown;
+    MessageType from;
+    Bool have_present = FALSE, value;
     const char *s;
     void *front_ptr;
 
@@ -1341,7 +1344,23 @@ Bool RADEONScreenInit_KMS(SCREEN_INIT_ARGS_DECL)
 #endif
 
     if (radeon_sync_init(pScreen))
-	radeon_present_screen_init(pScreen);
+	have_present = radeon_present_screen_init(pScreen);
+
+    if (xf86GetOptValBool(info->Options, OPTION_DRI3, &value))
+	from = X_CONFIG;
+    else
+	from = X_DEFAULT;
+
+    if (value) {
+	if (have_present)
+	    value = radeon_dri3_screen_init(pScreen);
+	else
+	    value = FALSE;
+
+	if (!value)
+	    from = X_WARNING;
+    }
+    xf86DrvMsg(pScrn->scrnIndex, from, "DRI3 %sabled\n", value ? "en" : "dis");
 
     pScrn->vtSema = TRUE;
     xf86SetBackingStore(pScreen);
commit 69ae0194778fe4276895839db92383f63f0b5de4
Author: David Heidelberger <david.heidelberger at ixit.cz>
Date:   Fri Mar 6 17:57:22 2015 +0900

    Handle tiling in radeon_set_shared_pixmap_backing
    
    [ Michel Dänzer: Fixups for glamor ]
    Signed-off-by: David Heidelberger <david.heidelberger at ixit.cz>
    Signed-off-by: Axel Davy <axel.davy at ens.fr>
    
    Reviewed-by: Alex Deucher <alexander.deucher at amd.com>

diff --git a/src/radeon_bo_helper.c b/src/radeon_bo_helper.c
index ed964d7..c3a2d63 100644
--- a/src/radeon_bo_helper.c
+++ b/src/radeon_bo_helper.c
@@ -200,6 +200,21 @@ Bool radeon_share_pixmap_backing(struct radeon_bo *bo, void **handle_p)
     return TRUE;
 }
 
+static unsigned eg_tile_split_opp(unsigned tile_split)
+{
+    switch (tile_split) {
+        case 0:     tile_split = 64;    break;
+        case 1:     tile_split = 128;   break;
+        case 2:     tile_split = 256;   break;
+        case 3:     tile_split = 512;   break;
+        default:
+        case 4:     tile_split = 1024;  break;
+        case 5:     tile_split = 2048;  break;
+        case 6:     tile_split = 4096;  break;
+    }
+    return tile_split;
+}
+
 Bool radeon_set_shared_pixmap_backing(PixmapPtr ppix, void *fd_handle,
 				      struct radeon_surface *surface)
 {
@@ -215,7 +230,22 @@ Bool radeon_set_shared_pixmap_backing(PixmapPtr ppix, void *fd_handle,
 
     memset(surface, 0, sizeof(struct radeon_surface));
 
+    radeon_set_pixmap_bo(ppix, bo);
+
     if (info->ChipFamily >= CHIP_FAMILY_R600 && info->surf_man) {
+	uint32_t tiling_flags;
+
+#ifdef USE_GLAMOR
+	if (info->use_glamor) {
+	    tiling_flags = radeon_get_pixmap_private(ppix)->tiling_flags;
+	} else
+#endif
+	{
+	    struct radeon_exa_pixmap_priv *driver_priv;
+
+	    driver_priv = exaGetPixmapDriverPrivate(ppix);
+	    tiling_flags = driver_priv->tiling_flags;
+	}
 
 	surface->npix_x = ppix->drawable.width;
 	surface->npix_y = ppix->drawable.height;
@@ -229,7 +259,17 @@ Bool radeon_set_shared_pixmap_backing(PixmapPtr ppix, void *fd_handle,
 	/* we are requiring a recent enough libdrm version */
 	surface->flags |= RADEON_SURF_HAS_TILE_MODE_INDEX;
 	surface->flags |= RADEON_SURF_SET(RADEON_SURF_TYPE_2D, TYPE);
-	surface->flags |= RADEON_SURF_SET(RADEON_SURF_MODE_LINEAR, MODE);
+	if (tiling_flags & RADEON_TILING_MACRO)
+	    surface->flags |= RADEON_SURF_SET(RADEON_SURF_MODE_2D, MODE);
+	else if (tiling_flags & RADEON_TILING_MICRO)
+	    surface->flags |= RADEON_SURF_SET(RADEON_SURF_MODE_1D, MODE);
+	else
+	    surface->flags |= RADEON_SURF_SET(RADEON_SURF_MODE_LINEAR_ALIGNED, MODE);
+	surface->bankw = (tiling_flags >> RADEON_TILING_EG_BANKW_SHIFT) & RADEON_TILING_EG_BANKW_MASK;
+	surface->bankh = (tiling_flags >> RADEON_TILING_EG_BANKH_SHIFT) & RADEON_TILING_EG_BANKH_MASK;
+	surface->tile_split = eg_tile_split_opp((tiling_flags >> RADEON_TILING_EG_TILE_SPLIT_SHIFT) & RADEON_TILING_EG_TILE_SPLIT_MASK);
+	surface->stencil_tile_split = (tiling_flags >> RADEON_TILING_EG_STENCIL_TILE_SPLIT_SHIFT) & RADEON_TILING_EG_STENCIL_TILE_SPLIT_MASK;
+	surface->mtilea = (tiling_flags >> RADEON_TILING_EG_MACRO_TILE_ASPECT_SHIFT) & RADEON_TILING_EG_MACRO_TILE_ASPECT_MASK;
 	if (radeon_surface_best(info->surf_man, surface)) {
 	    return FALSE;
 	}
@@ -241,7 +281,6 @@ Bool radeon_set_shared_pixmap_backing(PixmapPtr ppix, void *fd_handle,
 	surface->level[0].pitch_bytes = ppix->devKind;
 	surface->level[0].nblk_x = ppix->devKind / surface->bpe;
     }
-    radeon_set_pixmap_bo(ppix, bo);
 
     close(ihandle);
     /* we have a reference from the alloc and one from set pixmap bo,
diff --git a/src/radeon_exa.c b/src/radeon_exa.c
index 0d6cd24..1e457a8 100644
--- a/src/radeon_exa.c
+++ b/src/radeon_exa.c
@@ -330,7 +330,6 @@ Bool RADEONEXASetSharedPixmapBacking(PixmapPtr ppix, void *fd_handle)
 	return FALSE;
 
     driver_priv->shared = TRUE;
-    driver_priv->tiling_flags = 0;
     return TRUE;
 }
 #endif
diff --git a/src/radeon_glamor.c b/src/radeon_glamor.c
index f0996fe..c49c7f6 100644
--- a/src/radeon_glamor.c
+++ b/src/radeon_glamor.c
@@ -303,7 +303,6 @@ radeon_glamor_set_shared_pixmap_backing(PixmapPtr pixmap, void *handle)
 	priv = radeon_get_pixmap_private(pixmap);
 	priv->stride = pixmap->devKind;
 	priv->surface = surface;
-	priv->tiling_flags = 0;
 
 	if (!radeon_glamor_create_textured_pixmap(pixmap)) {
 		xf86DrvMsg(scrn->scrnIndex, X_ERROR,
commit 3c65fb849e1ba9fb6454bcaa55b696548902f3fc
Author: Michel Dänzer <michel.daenzer at amd.com>
Date:   Tue Mar 10 16:52:54 2015 +0900

    Add support for the Present extension v2
    
    v2: Fix up for struct radeon_drm_queue -> radeon_drm_queue_entry.
        Swapped order of patches 11 & 12 because the Present extension uses
        SYNC fences.
    
    Reviewed-by: Alex Deucher <alexander.deucher at amd.com>

diff --git a/configure.ac b/configure.ac
index c2e5a20..71d8ff0 100644
--- a/configure.ac
+++ b/configure.ac
@@ -137,6 +137,12 @@ AC_CHECK_HEADERS([misyncshm.h], [], [],
 	          #include "screenint.h"
 	          #include "xorg-server.h"])
 
+AC_CHECK_HEADERS([present.h], [], [],
+		 [#include <X11/Xmd.h>
+		 #include <X11/Xproto.h>
+		 #include <X11/X.h>
+		 #include "xorg-server.h"])
+
 CPPFLAGS="$SAVE_CPPFLAGS"
 
 PKG_CHECK_MODULES([PCIACCESS], [pciaccess >= 0.8.0])
diff --git a/src/Makefile.am b/src/Makefile.am
index acb83f1..a3d732a 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -29,8 +29,8 @@
 ati_drv_la_LIBADD = $(PCIACCESS_LIBS)
 radeon_drv_la_LIBADD = $(LIBDRM_RADEON_LIBS) $(PCIACCESS_LIBS)
 
-RADEON_KMS_SRCS=radeon_dri2.c radeon_drm_queue.c radeon_kms.c radeon_sync.c \
-	radeon_vbo.c radeon_bo_helper.c drmmode_display.c
+RADEON_KMS_SRCS=radeon_dri2.c radeon_drm_queue.c radeon_kms.c radeon_present.c \
+	radeon_sync.c radeon_vbo.c radeon_bo_helper.c drmmode_display.c
 
 RADEON_EXA_SOURCES = radeon_exa.c r600_exa.c r6xx_accel.c r600_textured_videofuncs.c r600_shader.c radeon_exa_shared.c \
 	evergreen_exa.c evergreen_accel.c evergreen_shader.c evergreen_textured_videofuncs.c cayman_accel.c cayman_shader.c
diff --git a/src/radeon.h b/src/radeon.h
index cc52bd9..9346fbd 100644
--- a/src/radeon.h
+++ b/src/radeon.h
@@ -549,6 +549,9 @@ extern Bool RADEONGetDatatypeBpp(int bpp, uint32_t *type);
 extern Bool RADEONGetPixmapOffsetPitch(PixmapPtr pPix,
 				       uint32_t *pitch_offset);
 
+/* radeon_present.c */
+Bool radeon_present_screen_init(ScreenPtr screen);
+
 /* radeon_sync.c */
 extern Bool radeon_sync_init(ScreenPtr screen);
 extern void radeon_sync_close(ScreenPtr screen);
diff --git a/src/radeon_kms.c b/src/radeon_kms.c
index 521f3b9..f4452bc 100644
--- a/src/radeon_kms.c
+++ b/src/radeon_kms.c
@@ -1340,7 +1340,8 @@ Bool RADEONScreenInit_KMS(SCREEN_INIT_ARGS_DECL)
     }
 #endif
 
-    radeon_sync_init(pScreen);
+    if (radeon_sync_init(pScreen))
+	radeon_present_screen_init(pScreen);
 
     pScrn->vtSema = TRUE;
     xf86SetBackingStore(pScreen);
diff --git a/src/radeon_present.c b/src/radeon_present.c
new file mode 100644
index 0000000..d884548
--- /dev/null
+++ b/src/radeon_present.c
@@ -0,0 +1,418 @@
+/*
+ * Copyright © 2014 Intel Corporation
+ * Copyright © 2015 Advanced Micro Devices, Inc.
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, provided that
+ * the above copyright notice appear in all copies and that both that copyright
+ * notice and this permission notice appear in supporting documentation, and
+ * that the name of 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 <xorg-server.h>
+#include <xf86.h>
+
+#ifdef HAVE_PRESENT_H
+
+#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 <poll.h>
+#include <sys/time.h>
+#include <time.h>
+#include <errno.h>
+
+#include "xf86_OSproc.h"
+
+#include "xf86Pci.h"
+#include "xf86drm.h"
+
+#include "windowstr.h"
+#include "shadow.h"
+#include "fb.h"
+
+#include "radeon.h"
+#include "radeon_video.h"
+
+#include "present.h"
+
+struct radeon_present_vblank_event {
+    uint64_t event_id;
+};
+
+static uint32_t crtc_select(int crtc_id)
+{
+    if (crtc_id > 1)
+	return crtc_id << DRM_VBLANK_HIGH_CRTC_SHIFT;
+    else if (crtc_id > 0)
+	return DRM_VBLANK_SECONDARY;
+    else
+	return 0;
+}
+
+static RRCrtcPtr
+radeon_present_get_crtc(WindowPtr window)
+{
+    ScreenPtr screen = window->drawable.pScreen;
+    ScrnInfoPtr pScrn = xf86ScreenToScrn(screen);
+    xf86CrtcPtr crtc;
+    RRCrtcPtr randr_crtc = NULL;
+
+    crtc = radeon_pick_best_crtc(pScrn, FALSE,
+				 window->drawable.x,
+				 window->drawable.x + window->drawable.width,
+				 window->drawable.y,
+				 window->drawable.y + window->drawable.height);
+
+    /* Make sure the CRTC is valid and this is the real front buffer */
+    if (crtc != NULL && !crtc->rotatedData)
+	randr_crtc = crtc->randr_crtc;
+
+    return randr_crtc;
+}
+
+static int
+radeon_present_get_ust_msc(RRCrtcPtr crtc, CARD64 *ust, CARD64 *msc)
+{
+    return drmmode_crtc_get_ust_msc(crtc->devPrivate, ust, msc);
+}
+
+/*
+ * Flush the DRM event queue when full; this
+ * makes space for new requests
+ */
+static Bool
+radeon_present_flush_drm_events(ScreenPtr screen)
+{
+    ScrnInfoPtr scrn = xf86ScreenToScrn(screen);
+    xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(scrn);
+    drmmode_crtc_private_ptr drmmode_crtc = xf86_config->crtc[0]->driver_private;
+    drmmode_ptr drmmode = drmmode_crtc->drmmode;
+    struct pollfd p = { .fd = drmmode->fd, .events = POLLIN };
+    int r;
+
+    do {
+	r = poll(&p, 1, 0);
+    } while (r == -1 && (errno == EINTR || errno == EAGAIN));
+
+    if (r <= 0)
+	return 0;
+
+    return drmHandleEvent(drmmode->fd, &drmmode->event_context) >= 0;
+}
+
+/*
+ * Called when the queued vblank event has occurred
+ */
+static void
+radeon_present_vblank_handler(ScrnInfoPtr scrn, unsigned int msc,
+			      uint64_t usec, void *data)
+{
+    struct radeon_present_vblank_event *event = data;
+
+    present_event_notify(event->event_id, usec, msc);
+    free(event);
+}
+
+/*
+ * Called when the queued vblank is aborted
+ */
+static void
+radeon_present_vblank_abort(ScrnInfoPtr scrn, void *data)
+{
+    struct radeon_present_vblank_event *event = data;
+
+    free(event);
+}
+
+/*
+ * Queue an event to report back to the Present extension when the specified
+ * MSC has past
+ */
+static int
+radeon_present_queue_vblank(RRCrtcPtr crtc, uint64_t event_id, uint64_t msc)
+{
+    xf86CrtcPtr xf86_crtc = crtc->devPrivate;
+    ScreenPtr screen = crtc->pScreen;
+    ScrnInfoPtr scrn = xf86ScreenToScrn(screen);
+    RADEONInfoPtr info = RADEONPTR(scrn);
+    int crtc_id = drmmode_get_crtc_id(xf86_crtc);
+    struct radeon_present_vblank_event *event;
+    struct radeon_drm_queue_entry *queue;
+    drmVBlank vbl;
+    int ret;
+
+    event = calloc(sizeof(struct radeon_present_vblank_event), 1);
+    if (!event)
+	return BadAlloc;
+    event->event_id = event_id;
+    queue = radeon_drm_queue_alloc(scrn, RADEON_DRM_QUEUE_CLIENT_DEFAULT,
+				   event_id, event,
+				   radeon_present_vblank_handler,
+				   radeon_present_vblank_abort);
+    if (!queue) {
+	free(event);
+	return BadAlloc;
+    }
+
+    vbl.request.type = DRM_VBLANK_ABSOLUTE | DRM_VBLANK_EVENT | crtc_select(crtc_id);
+    vbl.request.sequence = msc;
+    vbl.request.signal = (unsigned long)queue;
+    for (;;) {
+	ret = drmWaitVBlank(info->dri2.drm_fd, &vbl);
+	if (!ret)
+	    break;
+	if (errno != EBUSY || !radeon_present_flush_drm_events(screen)) {
+	    radeon_drm_abort_entry(queue);
+	    return BadAlloc;
+	}
+    }
+
+    return Success;
+}
+
+/*
+ * Remove a pending vblank event from the DRM queue so that it is not reported
+ * to the extension
+ */
+static void
+radeon_present_abort_vblank(RRCrtcPtr crtc, uint64_t event_id, uint64_t msc)
+{
+    radeon_drm_abort_id(event_id);
+}
+
+/*
+ * Flush our batch buffer when requested by the Present extension.
+ */
+static void
+radeon_present_flush(WindowPtr window)
+{
+    radeon_cs_flush_indirect(xf86ScreenToScrn(window->drawable.pScreen));
+}
+
+static drmmode_crtc_private_ptr
+get_drmmode_crtc(ScrnInfoPtr scrn, RRCrtcPtr crtc)
+{
+    xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(scrn);
+    int i;
+
+    for (i = 0; i < config->num_crtc; i++) {
+	xf86CrtcPtr xf86crtc = config->crtc[i];
+
+	if (xf86crtc->randr_crtc == crtc)
+	    return xf86crtc->driver_private;
+    }
+
+    return NULL;
+}
+
+/*
+ * Test to see if page flipping is possible on the target crtc
+ */
+static Bool
+radeon_present_check_flip(RRCrtcPtr crtc, WindowPtr window, PixmapPtr pixmap,
+			  Bool sync_flip)
+{
+    ScreenPtr screen = window->drawable.pScreen;
+    ScrnInfoPtr scrn = xf86ScreenToScrn(screen);
+    RADEONInfoPtr info = RADEONPTR(scrn);
+
+    if (!scrn->vtSema)
+	return FALSE;
+
+    if (!info->allowPageFlip)
+	return FALSE;
+
+    if (crtc) {
+	drmmode_crtc_private_ptr drmmode_crtc = get_drmmode_crtc(scrn, crtc);
+
+	if (!drmmode_crtc ||
+	    drmmode_crtc->rotate_bo != NULL ||
+	    drmmode_crtc->dpms_mode != DPMSModeOn)
+	    return FALSE;
+    }
+
+    return TRUE;
+}
+
+/*
+ * Once the flip has been completed on all CRTCs, notify the
+ * extension code telling it when that happened
+ */
+static void
+radeon_present_flip_event(ScrnInfoPtr scrn, uint32_t msc, uint64_t ust, void *pageflip_data)
+{
+    struct radeon_present_vblank_event *event = pageflip_data;
+
+    present_event_notify(event->event_id, ust, msc);
+    free(event);
+}
+
+/*
+ * The flip has been aborted, free the structure
+ */
+static void
+radeon_present_flip_abort(ScrnInfoPtr scrn, void *pageflip_data)
+{
+    struct radeon_present_vblank_event *event = pageflip_data;
+
+    free(event);
+}
+
+/*
+ * Queue a flip on 'crtc' to 'pixmap' at 'target_msc'. If 'sync_flip' is true,
+ * then wait for vblank. Otherwise, flip immediately
+ */
+static Bool
+radeon_present_flip(RRCrtcPtr crtc, uint64_t event_id, uint64_t target_msc,
+                   PixmapPtr pixmap, Bool sync_flip)
+{
+    ScreenPtr screen = crtc->pScreen;
+    ScrnInfoPtr scrn = xf86ScreenToScrn(screen);
+    struct radeon_present_vblank_event *event;
+    drmmode_crtc_private_ptr drmmode_crtc = get_drmmode_crtc(scrn, crtc);
+    int crtc_id = drmmode_crtc->mode_crtc->crtc_id;
+    struct radeon_bo *bo;
+    Bool ret;
+
+    if (!sync_flip)
+	return FALSE;
+
+    if (!radeon_present_check_flip(crtc, screen->root, pixmap, sync_flip))
+	return FALSE;
+
+    bo = radeon_get_pixmap_bo(pixmap);
+    if (!bo)
+	return FALSE;
+
+    event = calloc(1, sizeof(struct radeon_present_vblank_event));
+    if (!event)
+	return FALSE;
+
+    event->event_id = event_id;
+
+    ret = radeon_do_pageflip(scrn, RADEON_DRM_QUEUE_CLIENT_DEFAULT, bo,
+			     event_id, event, crtc_id,
+			     radeon_present_flip_event,
+			     radeon_present_flip_abort);
+    if (!ret)
+	xf86DrvMsg(scrn->scrnIndex, X_ERROR, "present flip failed\n");
+
+    return ret;
+}
+
+/*
+ * Queue a flip back to the normal frame buffer
+ */
+static void
+radeon_present_unflip(ScreenPtr screen, uint64_t event_id)
+{
+    ScrnInfoPtr scrn = xf86ScreenToScrn(screen);
+    struct radeon_present_vblank_event *event;
+    PixmapPtr pixmap = screen->GetScreenPixmap(screen);
+    struct radeon_bo *bo;
+    Bool ret;
+
+    if (!radeon_present_check_flip(NULL, screen->root, pixmap, TRUE))
+	return;
+
+    bo = radeon_get_pixmap_bo(pixmap);
+    if (!bo)
+	return;
+
+    event = calloc(1, sizeof(struct radeon_present_vblank_event));
+    if (!event)
+	return;
+
+    event->event_id = event_id;
+
+    ret = radeon_do_pageflip(scrn, RADEON_DRM_QUEUE_CLIENT_DEFAULT, bo,
+			     event_id, event, -1, radeon_present_flip_event,
+			     radeon_present_flip_abort);
+    if (!ret)
+	xf86DrvMsg(scrn->scrnIndex, X_ERROR, "present unflip failed\n");
+}
+
+static present_screen_info_rec radeon_present_screen_info = {
+    .version = 0,
+
+    .get_crtc = radeon_present_get_crtc,
+    .get_ust_msc = radeon_present_get_ust_msc,
+    .queue_vblank = radeon_present_queue_vblank,
+    .abort_vblank = radeon_present_abort_vblank,
+    .flush = radeon_present_flush,
+
+    .capabilities = PresentCapabilityNone,
+    .check_flip = radeon_present_check_flip,
+    .flip = radeon_present_flip,
+    .unflip = radeon_present_unflip,
+};
+
+static Bool
+radeon_present_has_async_flip(ScreenPtr screen)
+{
+#ifdef DRM_CAP_ASYNC_PAGE_FLIP
+    ScrnInfoPtr scrn = xf86ScreenToScrn(screen);
+    RADEONInfoPtr info = RADEONPTR(scrn);
+    int ret;
+    uint64_t value;
+
+    ret = drmGetCap(info->dri2.drm_fd, DRM_CAP_ASYNC_PAGE_FLIP, &value);
+    if (ret == 0)
+	return value == 1;
+#endif
+    return FALSE;
+}
+
+Bool
+radeon_present_screen_init(ScreenPtr screen)
+{
+    if (radeon_present_has_async_flip(screen))
+	radeon_present_screen_info.capabilities |= PresentCapabilityAsync;
+
+    if (!present_screen_init(screen, &radeon_present_screen_info)) {
+	xf86DrvMsg(xf86ScreenToScrn(screen)->scrnIndex, X_WARNING,
+		   "Present extension disabled because present_screen_init failed\n");
+	return FALSE;
+    }
+
+    xf86DrvMsg(xf86ScreenToScrn(screen)->scrnIndex, X_INFO,
+	       "Present extension enabled\n");
+
+    return TRUE;
+}
+
+#else /* !HAVE_PRESENT_H */
+
+Bool
+radeon_present_screen_init(ScreenPtr screen)
+{
+    xf86DrvMsg(xf86ScreenToScrn(screen)->scrnIndex, X_INFO,
+	       "Present extension disabled because present.h not available at "
+	       "build time\n");
+
+    return FALSE;
+}
+
+#endif
commit 8fc9a241ab59ffbcdc178d6415332c88a54e85fe
Author: Michel Dänzer <michel.daenzer at amd.com>
Date:   Thu Mar 5 18:18:56 2015 +0900

    Add support for SYNC extension fences v2
    
    v2: Swapped order of patches 11 & 12 because the Present extension uses
        SYNC fences.
    
    Reviewed-by: Alex Deucher <alexander.deucher at amd.com>

diff --git a/configure.ac b/configure.ac
index 891da03..c2e5a20 100644
--- a/configure.ac
+++ b/configure.ac
@@ -131,6 +131,12 @@ AC_CHECK_DECL(xorg_list_init,
 	      #include "xorg-server.h"
 	      #include "list.h"])
 
+AC_CHECK_HEADERS([misyncshm.h], [], [],
+                 [#include <X11/Xdefs.h>
+	          #include <X11/Xfuncproto.h>
+	          #include "screenint.h"
+	          #include "xorg-server.h"])
+
 CPPFLAGS="$SAVE_CPPFLAGS"
 
 PKG_CHECK_MODULES([PCIACCESS], [pciaccess >= 0.8.0])
diff --git a/src/Makefile.am b/src/Makefile.am
index 9cc8a2d..acb83f1 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -29,8 +29,8 @@
 ati_drv_la_LIBADD = $(PCIACCESS_LIBS)
 radeon_drv_la_LIBADD = $(LIBDRM_RADEON_LIBS) $(PCIACCESS_LIBS)
 
-RADEON_KMS_SRCS=radeon_dri2.c radeon_drm_queue.c radeon_kms.c drmmode_display.c \
-	radeon_vbo.c radeon_bo_helper.c
+RADEON_KMS_SRCS=radeon_dri2.c radeon_drm_queue.c radeon_kms.c radeon_sync.c \
+	radeon_vbo.c radeon_bo_helper.c drmmode_display.c
 
 RADEON_EXA_SOURCES = radeon_exa.c r600_exa.c r6xx_accel.c r600_textured_videofuncs.c r600_shader.c radeon_exa_shared.c \
 	evergreen_exa.c evergreen_accel.c evergreen_shader.c evergreen_textured_videofuncs.c cayman_accel.c cayman_shader.c
diff --git a/src/radeon.h b/src/radeon.h
index e503cbb..cc52bd9 100644
--- a/src/radeon.h
+++ b/src/radeon.h
@@ -90,6 +90,8 @@
 #include "simple_list.h"
 #include "atipcirename.h"
 
+typedef struct _SyncFence SyncFence;
+
 #ifndef MAX
 #define MAX(a,b) ((a)>(b)?(a):(b))
 #endif
@@ -445,6 +447,9 @@ typedef struct {
 
     void              (*BlockHandler)(BLOCKHANDLER_ARGS_DECL);
 
+    void              (*CreateFence) (ScreenPtr pScreen, SyncFence *pFence,
+				      Bool initially_triggered);
+
     int               pix24bpp;         /* Depth of pixmap for 24bpp fb      */
     Bool              dac6bits;         /* Use 6 bit DAC?                    */
 
@@ -544,6 +549,10 @@ extern Bool RADEONGetDatatypeBpp(int bpp, uint32_t *type);
 extern Bool RADEONGetPixmapOffsetPitch(PixmapPtr pPix,
 				       uint32_t *pitch_offset);
 
+/* radeon_sync.c */
+extern Bool radeon_sync_init(ScreenPtr screen);
+extern void radeon_sync_close(ScreenPtr screen);
+
 /* radeon_video.c */
 extern void RADEONInitVideo(ScreenPtr pScreen);
 extern void RADEONResetVideo(ScrnInfoPtr pScrn);
diff --git a/src/radeon_kms.c b/src/radeon_kms.c
index d25d7f5..521f3b9 100644
--- a/src/radeon_kms.c
+++ b/src/radeon_kms.c
@@ -1192,6 +1192,8 @@ static Bool RADEONCloseScreen_KMS(CLOSE_SCREEN_ARGS_DECL)
 	info->accel_state->exa = NULL;
     }
 
+    radeon_sync_close(pScreen);
+
     if (info->accel_state->use_vbos)
         radeon_vbo_free_lists(pScrn);
 
@@ -1338,6 +1340,8 @@ Bool RADEONScreenInit_KMS(SCREEN_INIT_ARGS_DECL)
     }
 #endif
 
+    radeon_sync_init(pScreen);
+
     pScrn->vtSema = TRUE;
     xf86SetBackingStore(pScreen);
 
diff --git a/src/radeon_sync.c b/src/radeon_sync.c
new file mode 100644
index 0000000..d8ab5bc
--- /dev/null
+++ b/src/radeon_sync.c
@@ -0,0 +1,144 @@
+/*
+ * Copyright © 2013-2014 Intel Corporation
+ * Copyright © 2015 Advanced Micro Devices, Inc.
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, provided that
+ * the above copyright notice appear in all copies and that both that copyright
+ * notice and this permission notice appear in supporting documentation, and
+ * that the name of 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 "radeon.h"
+
+#ifdef HAVE_MISYNCSHM_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 radeon_sync_fence_private_key;
+
+typedef struct _radeon_sync_fence_private {
+        SyncFenceSetTriggeredFunc set_triggered;
+} radeon_sync_fence_private;
+
+#define SYNC_FENCE_PRIV(pFence)                                         \
+        (radeon_sync_fence_private *) dixLookupPrivate(&pFence->devPrivates, &radeon_sync_fence_private_key)
+
+static void
+radeon_sync_fence_set_triggered (SyncFence *fence)
+{
+	ScreenPtr screen = fence->pScreen;
+	radeon_sync_fence_private *private = SYNC_FENCE_PRIV(fence);
+
+	/* Flush pending rendering operations */
+	radeon_cs_flush_indirect(xf86ScreenToScrn(screen));
+
+	fence->funcs.SetTriggered = private->set_triggered;
+	fence->funcs.SetTriggered(fence);
+	private->set_triggered = fence->funcs.SetTriggered;
+	fence->funcs.SetTriggered = radeon_sync_fence_set_triggered;
+}
+
+static void
+radeon_sync_create_fence(ScreenPtr screen,
+                        SyncFence *fence,
+                        Bool initially_triggered)
+{
+	ScrnInfoPtr scrn = xf86ScreenToScrn(screen);
+	RADEONInfoPtr info = RADEONPTR(scrn);
+	SyncScreenFuncsPtr screen_funcs = miSyncGetScreenFuncs(screen);
+	radeon_sync_fence_private *private = SYNC_FENCE_PRIV(fence);
+
+	screen_funcs->CreateFence = info->CreateFence;
+	screen_funcs->CreateFence(screen, fence, initially_triggered);
+	info->CreateFence = screen_funcs->CreateFence;
+	screen_funcs->CreateFence = radeon_sync_create_fence;
+
+	private->set_triggered = fence->funcs.SetTriggered;
+	fence->funcs.SetTriggered = radeon_sync_fence_set_triggered;
+}
+
+Bool
+radeon_sync_init(ScreenPtr screen)
+{
+	ScrnInfoPtr scrn = xf86ScreenToScrn(screen);
+	RADEONInfoPtr info = RADEONPTR(scrn);
+	SyncScreenFuncsPtr screen_funcs;
+
+	if (!miSyncShmScreenInit(screen)) {
+		xf86DrvMsg(scrn->scrnIndex, X_WARNING,
+			   "SYNC extension fences disabled because "
+			   "miSyncShmScreenInit failed\n");
+		return FALSE;
+	}
+
+	if (!dixPrivateKeyRegistered(&radeon_sync_fence_private_key)) {
+		if (!dixRegisterPrivateKey(&radeon_sync_fence_private_key,
+					   PRIVATE_SYNC_FENCE,
+					   sizeof (radeon_sync_fence_private))) {
+			xf86DrvMsg(scrn->scrnIndex, X_WARNING,
+				   "SYNC extension fences disabled because "
+				   "dixRegisterPrivateKey failed\n");
+			return FALSE;
+		}
+	}
+
+	xf86DrvMsg(xf86ScreenToScrn(screen)->scrnIndex, X_INFO,
+		   "SYNC extension fences enabled\n");
+
+	screen_funcs = miSyncGetScreenFuncs(screen);
+	info->CreateFence = screen_funcs->CreateFence;
+	screen_funcs->CreateFence = radeon_sync_create_fence;
+	return TRUE;
+}
+
+void
+radeon_sync_close(ScreenPtr screen)
+{
+	ScrnInfoPtr scrn = xf86ScreenToScrn(screen);
+	RADEONInfoPtr info = RADEONPTR(scrn);
+	SyncScreenFuncsPtr screen_funcs = miSyncGetScreenFuncs(screen);
+
+	if (screen_funcs && info->CreateFence)
+		screen_funcs->CreateFence = info->CreateFence;
+
+	info->CreateFence = NULL;
+}
+
+#else /* !HAVE_MISYNCSHM_H */
+
+Bool
+radeon_sync_init(ScreenPtr screen)
+{
+	xf86DrvMsg(xf86ScreenToScrn(screen)->scrnIndex, X_INFO,
+		   "SYNC extension fences disabled because misyncshm.h not "
+		   "available at build time\n");
+
+	return FALSE;
+}
+
+void
+radeon_sync_close(ScreenPtr screen)
+{
+}
+
+#endif
commit 4a35e2f33d9cdfb608423046391311109f96fb6b
Author: Michel Dänzer <michel.daenzer at amd.com>
Date:   Thu Mar 5 18:34:07 2015 +0900

    Fold radeon_glamor_flush into radeon_cs_flush_indirect
    
    Reviewed-by: Alex Deucher <alexander.deucher at amd.com>

diff --git a/src/radeon_glamor.c b/src/radeon_glamor.c
index 950f891..f0996fe 100644
--- a/src/radeon_glamor.c
+++ b/src/radeon_glamor.c
@@ -363,15 +363,6 @@ radeon_glamor_init(ScreenPtr screen)
 	return TRUE;
 }
 
-void
-radeon_glamor_flush(ScrnInfoPtr pScrn)
-{
-	RADEONInfoPtr info = RADEONPTR(pScrn);
-
-	if (info->use_glamor)
-		glamor_block_handler(pScrn->pScreen);
-}
-
 XF86VideoAdaptorPtr radeon_glamor_xv_init(ScreenPtr pScreen, int num_adapt)
 {
 	return glamor_xv_init(pScreen, num_adapt);
diff --git a/src/radeon_glamor.h b/src/radeon_glamor.h
index 548ea98..c402a10 100644
--- a/src/radeon_glamor.h
+++ b/src/radeon_glamor.h
@@ -40,8 +40,6 @@ Bool radeon_glamor_init(ScreenPtr screen);
 Bool radeon_glamor_create_screen_resources(ScreenPtr screen);
 void radeon_glamor_free_screen(int scrnIndex, int flags);
 
-void radeon_glamor_flush(ScrnInfoPtr pScrn);
-
 Bool radeon_glamor_create_textured_pixmap(PixmapPtr pixmap);
 void radeon_glamor_exchange_buffers(PixmapPtr src, PixmapPtr dst);
 
@@ -56,8 +54,6 @@ static inline Bool radeon_glamor_init(ScreenPtr screen) { return FALSE; }
 static inline Bool radeon_glamor_create_screen_resources(ScreenPtr screen) { return FALSE; }
 static inline void radeon_glamor_free_screen(int scrnIndex, int flags) { }
 
-static inline void radeon_glamor_flush(ScrnInfoPtr pScrn) { }
-
 static inline Bool radeon_glamor_create_textured_pixmap(PixmapPtr pixmap) { return TRUE; }
 
 static inline void radeon_glamor_exchange_buffers(PixmapPtr src, PixmapPtr dst) {}
diff --git a/src/radeon_kms.c b/src/radeon_kms.c
index 23c0694..d25d7f5 100644
--- a/src/radeon_kms.c
+++ b/src/radeon_kms.c
@@ -84,12 +84,21 @@ const OptionInfoRec *RADEONOptionsWeak(void) { return RADEONOptions_KMS; }
 void radeon_cs_flush_indirect(ScrnInfoPtr pScrn)
 {
     RADEONInfoPtr  info = RADEONPTR(pScrn);
-    struct radeon_accel_state *accel_state = info->accel_state;
+    struct radeon_accel_state *accel_state;
     int ret;
 
+#ifdef USE_GLAMOR
+    if (info->use_glamor) {
+	glamor_block_handler(pScrn->pScreen);
+	return;
+    }
+#endif
+
     if (!info->cs->cdw)
 	return;
 
+    accel_state = info->accel_state;
+
     /* release the current VBO so we don't block on mapping it later */
     if (info->accel_state->vbo.vb_offset && info->accel_state->vbo.vb_bo) {
         radeon_vbo_put(pScrn, &info->accel_state->vbo);
@@ -307,9 +316,6 @@ static void RADEONBlockHandler_KMS(BLOCKHANDLER_ARGS_DECL)
     (*pScreen->BlockHandler) (BLOCKHANDLER_ARGS);
     pScreen->BlockHandler = RADEONBlockHandler_KMS;
 
-    if (info->use_glamor)
-	radeon_glamor_flush(pScrn);
-
     radeon_cs_flush_indirect(pScrn);
 #ifdef RADEON_PIXMAP_SHARING
     radeon_dirty_update(pScreen);
@@ -322,10 +328,8 @@ radeon_flush_callback(CallbackListPtr *list,
 {
     ScrnInfoPtr pScrn = user_data;
 
-    if (pScrn->vtSema) {
+    if (pScrn->vtSema)
         radeon_cs_flush_indirect(pScrn);
-	radeon_glamor_flush(pScrn);
-    }
 }
 
 static Bool RADEONIsFastFBWorking(ScrnInfoPtr pScrn)
commit 4b8adebb80158bcf81ada83bb88517febe931b12
Author: Michel Dänzer <michel.daenzer at amd.com>
Date:   Thu Mar 5 18:40:23 2015 +0900

    Move #include "radeon_glamor.h" from radeon.h to where it's needed
    
    Reviewed-by: Alex Deucher <alexander.deucher at amd.com>

diff --git a/src/drmmode_display.c b/src/drmmode_display.c
index bb3d989..86bc446 100644
--- a/src/drmmode_display.c
+++ b/src/drmmode_display.c
@@ -36,6 +36,7 @@
 #include "micmap.h"
 #include "xf86cmap.h"
 #include "radeon.h"
+#include "radeon_glamor.h"
 #include "radeon_reg.h"
 
 #include "drmmode_display.h"
diff --git a/src/radeon.h b/src/radeon.h
index 88a0bd5..e503cbb 100644
--- a/src/radeon.h
+++ b/src/radeon.h
@@ -51,8 +51,6 @@
 
 #include "exa.h"
 
-#include "radeon_glamor.h"
-
 				/* Exa and Cursor Support */
 #include "xf86Cursor.h"
 
@@ -242,6 +240,40 @@ typedef enum {
 #define CURSOR_WIDTH_CIK	128
 #define CURSOR_HEIGHT_CIK	128
 
+
+#ifdef USE_GLAMOR
+
+struct radeon_pixmap {
+	struct radeon_surface surface;
+	struct radeon_bo *bo;
+
+	uint32_t tiling_flags;
+	int stride;
+};
+
+#if HAS_DEVPRIVATEKEYREC
+extern DevPrivateKeyRec glamor_pixmap_index;
+#else
+extern int glamor_pixmap_index;
+#endif
+
+static inline struct radeon_pixmap *radeon_get_pixmap_private(PixmapPtr pixmap)
+{
+#if HAS_DEVPRIVATEKEYREC
+	return dixGetPrivate(&pixmap->devPrivates, &glamor_pixmap_index);
+#else
+	return dixLookupPrivate(&pixmap->devPrivates, &glamor_pixmap_index);
+#endif
+}
+
+static inline void radeon_set_pixmap_private(PixmapPtr pixmap, struct radeon_pixmap *priv)
+{
+	dixSetPrivate(&pixmap->devPrivates, &glamor_pixmap_index, priv);
+}
+
+#endif /* USE_GLAMOR */
+
+
 struct radeon_exa_pixmap_priv {
     struct radeon_bo *bo;
     uint32_t tiling_flags;
diff --git a/src/radeon_accel.c b/src/radeon_accel.c
index 8eff5c5..1def2a3 100644
--- a/src/radeon_accel.c
+++ b/src/radeon_accel.c
@@ -78,6 +78,7 @@
 #include <assert.h>
 				/* Driver data structures */
 #include "radeon.h"
+#include "radeon_glamor.h"
 #include "radeon_reg.h"
 #include "r600_reg.h"
 #include "radeon_probe.h"
diff --git a/src/radeon_dri2.c b/src/radeon_dri2.c
index 0577d8f..02e8e8f 100644
--- a/src/radeon_dri2.c
+++ b/src/radeon_dri2.c
@@ -53,9 +53,7 @@
 
 #define FALLBACK_SWAP_DELAY 16
 
-#ifdef USE_GLAMOR
-#include <glamor.h>
-#endif
+#include "radeon_glamor.h"
 
 typedef DRI2BufferPtr BufferPtr;
 
diff --git a/src/radeon_glamor.c b/src/radeon_glamor.c
index 210ddcf..950f891 100644
--- a/src/radeon_glamor.c
+++ b/src/radeon_glamor.c
@@ -29,11 +29,10 @@
 #endif
 
 #include <xf86.h>
-#define GLAMOR_FOR_XORG  1
-#include <glamor.h>
 
 #include "radeon.h"
 #include "radeon_bo_helper.h"
+#include "radeon_glamor.h"
 
 #if HAS_DEVPRIVATEKEYREC
 DevPrivateKeyRec glamor_pixmap_index;
diff --git a/src/radeon_glamor.h b/src/radeon_glamor.h
index 36addd7..548ea98 100644
--- a/src/radeon_glamor.h
+++ b/src/radeon_glamor.h
@@ -30,6 +30,9 @@
 #include "xf86xv.h"
 #ifdef USE_GLAMOR
 
+#define GLAMOR_FOR_XORG  1
+#include <glamor.h>
+
 #include "radeon_surface.h"
 
 Bool radeon_glamor_pre_init(ScrnInfoPtr scrn);
@@ -46,34 +49,6 @@ Bool radeon_glamor_pixmap_is_offscreen(PixmapPtr pixmap);
 
 XF86VideoAdaptorPtr radeon_glamor_xv_init(ScreenPtr pScreen, int num_adapt);
 
-struct radeon_pixmap {
-	struct radeon_surface surface;
-	struct radeon_bo *bo;
-
-	uint32_t tiling_flags;
-	int stride;
-};
-
-#if HAS_DEVPRIVATEKEYREC
-extern DevPrivateKeyRec glamor_pixmap_index;
-#else
-extern int glamor_pixmap_index;
-#endif
-
-static inline struct radeon_pixmap *radeon_get_pixmap_private(PixmapPtr pixmap)
-{
-#if HAS_DEVPRIVATEKEYREC
-	return dixGetPrivate(&pixmap->devPrivates, &glamor_pixmap_index);
-#else
-	return dixLookupPrivate(&pixmap->devPrivates, &glamor_pixmap_index);
-#endif
-}
-
-static inline void radeon_set_pixmap_private(PixmapPtr pixmap, struct radeon_pixmap *priv)
-{
-	dixSetPrivate(&pixmap->devPrivates, &glamor_pixmap_index, priv);
-}
-
 #else
 
 static inline Bool radeon_glamor_pre_init(ScrnInfoPtr scrn) { return FALSE; }
diff --git a/src/radeon_kms.c b/src/radeon_kms.c
index ced3594..23c0694 100644
--- a/src/radeon_kms.c
+++ b/src/radeon_kms.c
@@ -33,6 +33,7 @@
 /* Driver data structures */
 #include "radeon.h"
 #include "radeon_drm_queue.h"
+#include "radeon_glamor.h"
 #include "radeon_reg.h"
 #include "radeon_probe.h"
 #include "micmap.h"
diff --git a/src/radeon_video.c b/src/radeon_video.c
index cbfd554..f66ba55 100644
--- a/src/radeon_video.c
+++ b/src/radeon_video.c
@@ -9,6 +9,7 @@
 #include <math.h>
 
 #include "radeon.h"
+#include "radeon_glamor.h"
 #include "radeon_reg.h"
 #include "radeon_probe.h"
 #include "radeon_video.h"
commit 76c2923ac5c7230a8b2f9f8329c308d28b44d9c0
Author: Michel Dänzer <michel.daenzer at amd.com>
Date:   Wed Mar 4 10:30:19 2015 +0900

    DRI2: Split out helper for getting UST and MSC of a specific CRTC
    
    Reviewed-by: Alex Deucher <alexander.deucher at amd.com>

diff --git a/src/drmmode_display.c b/src/drmmode_display.c
index 5ea2344..bb3d989 100644
--- a/src/drmmode_display.c
+++ b/src/drmmode_display.c
@@ -245,6 +245,33 @@ int drmmode_get_current_ust(int drm_fd, CARD64 *ust)
 	return 0;
 }
 
+/*
+ * Get current frame count and frame count timestamp of the crtc.
+ */
+int drmmode_crtc_get_ust_msc(xf86CrtcPtr crtc, CARD64 *ust, CARD64 *msc)
+{
+    ScrnInfoPtr scrn = crtc->scrn;
+    RADEONInfoPtr info = RADEONPTR(scrn);
+    drmVBlank vbl;
+    int ret;
+
+    vbl.request.type = DRM_VBLANK_RELATIVE;
+    vbl.request.type |= radeon_populate_vbl_request_type(crtc);
+    vbl.request.sequence = 0;
+
+    ret = drmWaitVBlank(info->dri2.drm_fd, &vbl);
+    if (ret) {
+	xf86DrvMsg(scrn->scrnIndex, X_WARNING,
+		   "get vblank counter failed: %s\n", strerror(errno));
+	return ret;
+    }
+
+    *ust = ((CARD64)vbl.reply.tval_sec * 1000000) + vbl.reply.tval_usec;
+    *msc = vbl.reply.sequence;
+
+    return Success;
+}
+
 static void
 drmmode_do_crtc_dpms(xf86CrtcPtr crtc, int mode)
 {
diff --git a/src/drmmode_display.h b/src/drmmode_display.h
index b313460..6f883c0 100644
--- a/src/drmmode_display.h
+++ b/src/drmmode_display.h
@@ -132,6 +132,7 @@ Bool radeon_do_pageflip(ScrnInfoPtr scrn, ClientPtr client,
 			struct radeon_bo *new_front, uint64_t id, void *data,
 			int ref_crtc_hw_id, radeon_drm_handler_proc handler,
 			radeon_drm_abort_proc abort);
+int drmmode_crtc_get_ust_msc(xf86CrtcPtr crtc, CARD64 *ust, CARD64 *msc);
 int drmmode_get_current_ust(int drm_fd, CARD64 *ust);
 
 #endif
diff --git a/src/radeon_dri2.c b/src/radeon_dri2.c
index 5134154..0577d8f 100644
--- a/src/radeon_dri2.c
+++ b/src/radeon_dri2.c
@@ -952,17 +952,13 @@ CARD32 radeon_dri2_extrapolate_msc_delay(xf86CrtcPtr crtc, CARD64 *target_msc,
 }
 
 /*
- * Get current frame count and frame count timestamp, based on drawable's
- * crtc.
+ * Get current interpolated frame count and frame count timestamp, based on
+ * drawable's crtc.
  */
 static int radeon_dri2_get_msc(DrawablePtr draw, CARD64 *ust, CARD64 *msc)
 {
-    ScreenPtr screen = draw->pScreen;
-    ScrnInfoPtr scrn = xf86ScreenToScrn(screen);
-    RADEONInfoPtr info = RADEONPTR(scrn);
-    drmVBlank vbl;
-    int ret;
     xf86CrtcPtr crtc = radeon_dri2_drawable_crtc(draw, TRUE);
+    int ret;
 
     /* Drawable not displayed, make up a value */
     if (crtc == NULL) {
@@ -970,25 +966,20 @@ static int radeon_dri2_get_msc(DrawablePtr draw, CARD64 *ust, CARD64 *msc)
         *msc = 0;
         return TRUE;
     }
+
     if (radeon_crtc_is_enabled(crtc)) {
 	/* CRTC is running, read vblank counter and timestamp */
-	vbl.request.type = DRM_VBLANK_RELATIVE;
-	vbl.request.type |= radeon_populate_vbl_request_type(crtc);
-	vbl.request.sequence = 0;
+	ret = drmmode_crtc_get_ust_msc(crtc, ust, msc);
 
-	ret = drmWaitVBlank(info->dri2.drm_fd, &vbl);
-	if (ret) {
-	    xf86DrvMsg(scrn->scrnIndex, X_WARNING,
-		       "get vblank counter failed: %s\n", strerror(errno));
-	    return FALSE;
+	if (ret != Success) {
+	    *msc += radeon_get_interpolated_vblanks(crtc);
+	    *msc &= 0xffffffff;
 	}
-
-	*ust = ((CARD64)vbl.reply.tval_sec * 1000000) + vbl.reply.tval_usec;
-	*msc = vbl.reply.sequence + radeon_get_interpolated_vblanks(crtc);
-	*msc &= 0xffffffff;
     } else {
 	/* CRTC is not running, extrapolate MSC and timestamp */
 	drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
+	ScrnInfoPtr scrn = crtc->scrn;
+	RADEONInfoPtr info = RADEONPTR(scrn);
 	CARD64 now, delta_t, delta_seq;
 
 	if (!drmmode_crtc->dpms_last_ust)
@@ -1011,7 +1002,8 @@ static int radeon_dri2_get_msc(DrawablePtr draw, CARD64 *ust, CARD64 *msc)
 	*msc += delta_seq;
 	*msc &= 0xffffffff;
     }
-    return TRUE;
+
+    return ret == Success;
 }
 
 static
commit 6c3a721cde9317233072b573f9502348dcd21b16
Author: Michel Dänzer <michel.daenzer at amd.com>
Date:   Tue Mar 10 16:52:18 2015 +0900

    DRI2: Use helper functions for DRM event queue management v3
    
    This is mostly in preparation for Present support, but it also simplifies
    the DRI2 specific code a little.
    
    v2: Fix up for struct radeon_drm_queue -> radeon_drm_queue_entry.
    v3: Removed excess 0s from conversion from microseconds to seconds,
        thanks to Richard Wilbur <richard.wilbur at gmail.com> for the catch!
    
    Reviewed-by: Alex Deucher <alexander.deucher at amd.com>

diff --git a/src/drmmode_display.c b/src/drmmode_display.c
index cebd206..5ea2344 100644
--- a/src/drmmode_display.c
+++ b/src/drmmode_display.c
@@ -1799,45 +1799,52 @@ static const xf86CrtcConfigFuncsRec drmmode_xf86crtc_config_funcs = {
 };
 
 static void
-drmmode_vblank_handler(int fd, unsigned int frame, unsigned int tv_sec,
-			unsigned int tv_usec, void *event_data)
+drmmode_flip_free(drmmode_flipevtcarrier_ptr flipcarrier)
 {
-	radeon_dri2_frame_event_handler(frame, tv_sec, tv_usec, event_data);
+	drmmode_flipdata_ptr flipdata = flipcarrier->flipdata;
+
+	free(flipcarrier);
+
+	if (--flipdata->flip_count > 0)
+		return;
+
+	/* Release framebuffer */
+	drmModeRmFB(flipdata->drmmode->fd, flipdata->old_fb_id);
+
+	free(flipdata);
 }
 
 static void
-drmmode_flip_handler(int fd, unsigned int frame, unsigned int tv_sec,
-		     unsigned int tv_usec, void *event_data)
+drmmode_flip_abort(ScrnInfoPtr scrn, void *event_data)
+{
+	drmmode_flipevtcarrier_ptr flipcarrier = event_data;
+	drmmode_flipdata_ptr flipdata = flipcarrier->flipdata;
+
+	if (flipdata->flip_count == 1)
+		flipcarrier->abort(scrn, flipdata->event_data);
+
+	drmmode_flip_free(flipcarrier);
+}
+
+static void
+drmmode_flip_handler(ScrnInfoPtr scrn, uint32_t frame, uint64_t usec, void *event_data)
 {
 	drmmode_flipevtcarrier_ptr flipcarrier = event_data;
 	drmmode_flipdata_ptr flipdata = flipcarrier->flipdata;
-	drmmode_ptr drmmode = flipdata->drmmode;
 
 	/* Is this the event whose info shall be delivered to higher level? */
 	if (flipcarrier->dispatch_me) {
 		/* Yes: Cache msc, ust for later delivery. */
 		flipdata->fe_frame = frame;
-		flipdata->fe_tv_sec = tv_sec;
-		flipdata->fe_tv_usec = tv_usec;
+		flipdata->fe_usec = usec;
 	}
-	free(flipcarrier);
-
-	/* Last crtc completed flip? */
-	flipdata->flip_count--;
-	if (flipdata->flip_count > 0)
-		return;
-
-	/* Release framebuffer */
-	drmModeRmFB(drmmode->fd, flipdata->old_fb_id);
-
-	if (flipdata->event_data == NULL)
-		return;
 
 	/* Deliver cached msc, ust from reference crtc to flip event handler */
-	radeon_dri2_flip_event_handler(flipdata->fe_frame, flipdata->fe_tv_sec,
-				       flipdata->fe_tv_usec, flipdata->event_data);
+	if (flipdata->event_data && flipdata->flip_count == 1)
+		flipcarrier->handler(scrn, flipdata->fe_frame, flipdata->fe_usec,
+				     flipdata->event_data);
 
-	free(flipdata);
+	drmmode_flip_free(flipcarrier);
 }
 
 
@@ -1884,8 +1891,8 @@ Bool drmmode_pre_init(ScrnInfoPtr pScrn, drmmode_ptr drmmode, int cpp)
 	xf86InitialConfiguration(pScrn, TRUE);
 
 	drmmode->event_context.version = DRM_EVENT_CONTEXT_VERSION;
-	drmmode->event_context.vblank_handler = drmmode_vblank_handler;
-	drmmode->event_context.page_flip_handler = drmmode_flip_handler;
+	drmmode->event_context.vblank_handler = radeon_drm_queue_handler;
+	drmmode->event_context.page_flip_handler = radeon_drm_queue_handler;
 
 	drmModeFreeResources(mode_res);
 	return TRUE;
@@ -2229,7 +2236,10 @@ void drmmode_uevent_fini(ScrnInfoPtr scrn, drmmode_ptr drmmode)
 #endif
 }
 
-Bool radeon_do_pageflip(ScrnInfoPtr scrn, struct radeon_bo *new_front, void *data, int ref_crtc_hw_id)
+Bool radeon_do_pageflip(ScrnInfoPtr scrn, ClientPtr client,
+			struct radeon_bo *new_front, uint64_t id, void *data,
+			int ref_crtc_hw_id, radeon_drm_handler_proc handler,
+			radeon_drm_abort_proc abort)
 {
 	RADEONInfoPtr info = RADEONPTR(scrn);
 	xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(scrn);
@@ -2240,7 +2250,8 @@ Bool radeon_do_pageflip(ScrnInfoPtr scrn, struct radeon_bo *new_front, void *dat
 	uint32_t tiling_flags = 0;
 	int height, emitted = 0;
 	drmmode_flipdata_ptr flipdata;
-	drmmode_flipevtcarrier_ptr flipcarrier;
+	drmmode_flipevtcarrier_ptr flipcarrier = NULL;
+	struct radeon_drm_queue_entry *drm_queue = 0;
 
 	if (info->allowColorTiling) {
 		if (info->ChipFamily >= CHIP_FAMILY_R600)
@@ -2305,9 +2316,22 @@ Bool radeon_do_pageflip(ScrnInfoPtr scrn, struct radeon_bo *new_front, void *dat
 		 */
 		flipcarrier->dispatch_me = (drmmode_crtc->hw_id == ref_crtc_hw_id);
 		flipcarrier->flipdata = flipdata;
+		flipcarrier->handler = handler;
+		flipcarrier->abort = abort;
+
+		drm_queue = radeon_drm_queue_alloc(scrn, client, id,
+						   flipcarrier,
+						   drmmode_flip_handler,
+						   drmmode_flip_abort);
+		if (!drm_queue) {
+			xf86DrvMsg(scrn->scrnIndex, X_WARNING,
+				   "Allocating DRM queue event entry failed.\n");
+			goto error_undo;
+		}
 
 		if (drmModePageFlip(drmmode->fd, drmmode_crtc->mode_crtc->crtc_id,
-				    drmmode->fb_id, DRM_MODE_PAGE_FLIP_EVENT, flipcarrier)) {
+				    drmmode->fb_id, DRM_MODE_PAGE_FLIP_EVENT,
+				    drm_queue)) {
 			xf86DrvMsg(scrn->scrnIndex, X_WARNING,
 				   "flip queue failed: %s\n", strerror(errno));
 			free(flipcarrier);
@@ -2322,6 +2346,11 @@ Bool radeon_do_pageflip(ScrnInfoPtr scrn, struct radeon_bo *new_front, void *dat
 	return TRUE;
 
 error_undo:
+	if (drm_queue)
+		radeon_drm_abort_entry(drm_queue);
+	else
+		drmmode_flip_abort(scrn, flipcarrier);
+
 	drmModeRmFB(drmmode->fd, drmmode->fb_id);
 	drmmode->fb_id = old_fb_id;
 
@@ -2330,4 +2359,3 @@ error_out:
 		   strerror(errno));
 	return FALSE;
 }
-
diff --git a/src/drmmode_display.h b/src/drmmode_display.h
index c9920e0..b313460 100644
--- a/src/drmmode_display.h
+++ b/src/drmmode_display.h
@@ -32,6 +32,7 @@
 #include "libudev.h"
 #endif
 
+#include "radeon_drm_queue.h"
 #include "radeon_probe.h"
 
 #ifndef DRM_CAP_TIMESTAMP_MONOTONIC
@@ -61,13 +62,14 @@ typedef struct {
   int flip_count;
   void *event_data;
   unsigned int fe_frame;
-  unsigned int fe_tv_sec;
-  unsigned int fe_tv_usec;
+  uint64_t fe_usec;
 } drmmode_flipdata_rec, *drmmode_flipdata_ptr;
 
 typedef struct {
   drmmode_flipdata_ptr flipdata;
   Bool dispatch_me;
+  radeon_drm_handler_proc handler;
+  radeon_drm_abort_proc abort;
 } drmmode_flipevtcarrier_rec, *drmmode_flipevtcarrier_ptr;
 
 typedef struct {
@@ -121,11 +123,15 @@ extern Bool drmmode_setup_colormap(ScreenPtr pScreen, ScrnInfoPtr pScrn);
 extern void drmmode_uevent_init(ScrnInfoPtr scrn, drmmode_ptr drmmode);
 extern void drmmode_uevent_fini(ScrnInfoPtr scrn, drmmode_ptr drmmode);
 
+extern int drmmode_get_crtc_id(xf86CrtcPtr crtc);
 extern int drmmode_get_height_align(ScrnInfoPtr scrn, uint32_t tiling);
 extern int drmmode_get_pitch_align(ScrnInfoPtr scrn, int bpe, uint32_t tiling);
 extern int drmmode_get_base_align(ScrnInfoPtr scrn, int bpe, uint32_t tiling);
 
-Bool radeon_do_pageflip(ScrnInfoPtr scrn, struct radeon_bo *new_front, void *data, int ref_crtc_hw_id);
+Bool radeon_do_pageflip(ScrnInfoPtr scrn, ClientPtr client,
+			struct radeon_bo *new_front, uint64_t id, void *data,
+			int ref_crtc_hw_id, radeon_drm_handler_proc handler,
+			radeon_drm_abort_proc abort);
 int drmmode_get_current_ust(int drm_fd, CARD64 *ust);
 
 #endif
diff --git a/src/radeon_dri2.c b/src/radeon_dri2.c
index a3f0776..5134154 100644
--- a/src/radeon_dri2.c
+++ b/src/radeon_dri2.c
@@ -45,6 +45,8 @@
 
 #include "radeon_bo_gem.h"
 
+#include <xf86Priv.h>
+
 #if DRI2INFOREC_VERSION >= 9
 #define USE_DRI2_PRIME
 #endif
@@ -485,67 +487,20 @@ typedef struct _DRI2FrameEvent {
     XID drawable_id;
     ClientPtr client;
     enum DRI2FrameEventType type;
-    int frame;
+    unsigned frame;
     xf86CrtcPtr crtc;
+    OsTimerPtr timer;
+    struct radeon_drm_queue_entry *drm_queue;
 
     /* for swaps & flips only */
     DRI2SwapEventPtr event_complete;
     void *event_data;
     DRI2BufferPtr front;
     DRI2BufferPtr back;
-
-    Bool valid;
-
-    struct xorg_list link;
 } DRI2FrameEventRec, *DRI2FrameEventPtr;
 
-typedef struct _DRI2ClientEvents {
-    struct xorg_list   reference_list;
-} DRI2ClientEventsRec, *DRI2ClientEventsPtr;
-
-#if HAS_DEVPRIVATEKEYREC
-
 static int DRI2InfoCnt;
 
-static DevPrivateKeyRec DRI2ClientEventsPrivateKeyRec;
-#define DRI2ClientEventsPrivateKey (&DRI2ClientEventsPrivateKeyRec)
-
-#else
-
-static int DRI2ClientEventsPrivateKeyIndex;
-DevPrivateKey DRI2ClientEventsPrivateKey = &DRI2ClientEventsPrivateKeyIndex;
-
-#endif /* HAS_DEVPRIVATEKEYREC */
-
-#define GetDRI2ClientEvents(pClient)	((DRI2ClientEventsPtr) \
-    dixLookupPrivate(&(pClient)->devPrivates, DRI2ClientEventsPrivateKey))
-
-static int
-ListAddDRI2ClientEvents(ClientPtr client, struct xorg_list *entry)
-{
-    DRI2ClientEventsPtr pClientPriv;
-    pClientPriv = GetDRI2ClientEvents(client);
-
-    if (!pClientPriv) {
-        return BadAlloc;
-    }
-
-    xorg_list_add(entry, &pClientPriv->reference_list);
-    return 0;
-}
-
-static void
-ListDelDRI2ClientEvents(ClientPtr client, struct xorg_list *entry)
-{
-    DRI2ClientEventsPtr pClientPriv;
-    pClientPriv = GetDRI2ClientEvents(client);
-
-    if (!pClientPriv) {
-        return;
-    }
-    xorg_list_del(entry);
-}
-
 static void
 radeon_dri2_ref_buffer(BufferPtr buffer)
 {
@@ -565,28 +520,13 @@ radeon_dri2_unref_buffer(BufferPtr buffer)
 static void
 radeon_dri2_client_state_changed(CallbackListPtr *ClientStateCallback, pointer data, pointer calldata)
 {
-    DRI2ClientEventsPtr pClientEventsPriv;
-    DRI2FrameEventPtr ref;
     NewClientInfoRec *clientinfo = calldata;
     ClientPtr pClient = clientinfo->client;
-    pClientEventsPriv = GetDRI2ClientEvents(pClient);
 
     switch (pClient->clientState) {
-    case ClientStateInitial:
-        xorg_list_init(&pClientEventsPriv->reference_list);
-        break;
-    case ClientStateRunning:
-        break;
-
     case ClientStateRetained:
     case ClientStateGone:
-        if (pClientEventsPriv) {
-            xorg_list_for_each_entry(ref, &pClientEventsPriv->reference_list, link) {
-                ref->valid = FALSE;
-                radeon_dri2_unref_buffer(ref->front);
-                radeon_dri2_unref_buffer(ref->back);
-            }
-        }
+        radeon_drm_abort_client(pClient);
         break;
     default:
         break;
@@ -613,36 +553,41 @@ xf86CrtcPtr radeon_dri2_drawable_crtc(DrawablePtr pDraw, Bool consider_disabled)
 	return NULL;
 }
 
-void radeon_dri2_flip_event_handler(unsigned int frame, unsigned int tv_sec,
-				    unsigned int tv_usec, void *event_data)
+static void
+radeon_dri2_flip_event_abort(ScrnInfoPtr scrn, void *event_data)
+{
+    free(event_data);
+}
+
+static void
+radeon_dri2_flip_event_handler(ScrnInfoPtr scrn, uint32_t frame, uint64_t usec,
+			       void *event_data)
 {
     DRI2FrameEventPtr flip = event_data;
+    unsigned tv_sec, tv_usec;
     DrawablePtr drawable;
     ScreenPtr screen;
-    ScrnInfoPtr scrn;
     int status;
     PixmapPtr pixmap;
 
     status = dixLookupDrawable(&drawable, flip->drawable_id, serverClient,
 			       M_ANY, DixWriteAccess);
-    if (status != Success) {
-	free(flip);
-	return;
-    }
-    if (!flip->crtc) {
-	free(flip);
-	return;
-    }
-    frame += radeon_get_interpolated_vblanks(flip->crtc);
+    if (status != Success)
+	goto abort;
 
-    screen = drawable->pScreen;
-    scrn = xf86ScreenToScrn(screen);
+    if (!flip->crtc)
+	goto abort;
+    frame += radeon_get_interpolated_vblanks(flip->crtc);
 
+    screen = scrn->pScreen;
     pixmap = screen->GetScreenPixmap(screen);
     xf86DrvMsgVerb(scrn->scrnIndex, X_INFO, RADEON_LOGLEVEL_DEBUG,
 		   "%s:%d fevent[%p] width %d pitch %d (/4 %d)\n",
 		   __func__, __LINE__, flip, pixmap->drawable.width, pixmap->devKind, pixmap->devKind/4);
 
+    tv_sec = usec / 1000000;
+    tv_usec = usec % 1000000;
+
     /* We assume our flips arrive in order, so we don't check the frame */
     switch (flip->type) {
     case DRI2_SWAP:
@@ -652,8 +597,8 @@ void radeon_dri2_flip_event_handler(unsigned int frame, unsigned int tv_sec,
 	 */
 	if ((frame < flip->frame) && (flip->frame - frame < 5)) {
 	    xf86DrvMsg(scrn->scrnIndex, X_WARNING,
-		       "%s: Pageflip completion event has impossible msc %d < target_msc %d\n",
-		        __func__, frame, flip->frame);
+		       "%s: Pageflip completion event has impossible msc %u < target_msc %u\n",
+		       __func__, frame, flip->frame);
 	    /* All-Zero values signal failure of (msc, ust) timestamping to client. */
 	    frame = tv_sec = tv_usec = 0;
 	}
@@ -668,7 +613,8 @@ void radeon_dri2_flip_event_handler(unsigned int frame, unsigned int tv_sec,
 	break;
     }
 
-    free(flip);
+abort:
+    radeon_dri2_flip_event_abort(scrn, event_data);
 }
 
 static Bool
@@ -703,7 +649,10 @@ radeon_dri2_schedule_flip(ScrnInfoPtr scrn, ClientPtr client,
     back_priv = back->driverPrivate;
     bo = radeon_get_pixmap_bo(back_priv->pixmap);
 
-    return radeon_do_pageflip(scrn, bo, flip_info, ref_crtc_hw_id);
+    return radeon_do_pageflip(scrn, client, bo, RADEON_DRM_QUEUE_ID_DEFAULT,
+			      flip_info, ref_crtc_hw_id,
+			      radeon_dri2_flip_event_handler,
+			      radeon_dri2_flip_event_abort);
 }
 
 static Bool
@@ -825,31 +774,36 @@ radeon_dri2_exchange_buffers(DrawablePtr draw, DRI2BufferPtr front, DRI2BufferPt
     DamageRegionProcessPending(&front_priv->pixmap->drawable);
 }
 
-void radeon_dri2_frame_event_handler(unsigned int frame, unsigned int tv_sec,
-                                     unsigned int tv_usec, void *event_data)
+static void radeon_dri2_frame_event_abort(ScrnInfoPtr scrn, void *event_data)
+{
+    DRI2FrameEventPtr event = event_data;
+
+    TimerCancel(event->timer);
+    TimerFree(event->timer);
+    radeon_dri2_unref_buffer(event->front);
+    radeon_dri2_unref_buffer(event->back);
+    free(event);
+}
+
+static void radeon_dri2_frame_event_handler(ScrnInfoPtr scrn, uint32_t seq,
+					    uint64_t usec, void *event_data)
 {
     DRI2FrameEventPtr event = event_data;
     DrawablePtr drawable;
-    ScreenPtr screen;
-    ScrnInfoPtr scrn;
     int status;
     int swap_type;
     BoxRec box;
     RegionRec region;
 
-    if (!event->valid)
+    if (!event->crtc)
 	goto cleanup;
 
     status = dixLookupDrawable(&drawable, event->drawable_id, serverClient,
                                M_ANY, DixWriteAccess);
     if (status != Success)
         goto cleanup;
-    if (!event->crtc)
-	goto cleanup;
-    frame += radeon_get_interpolated_vblanks(event->crtc);
 
-    screen = drawable->pScreen;
-    scrn = xf86ScreenToScrn(screen);
+    seq += radeon_get_interpolated_vblanks(event->crtc);
 
     switch (event->type) {
     case DRI2_FLIP:
@@ -881,12 +835,14 @@ void radeon_dri2_frame_event_handler(unsigned int frame, unsigned int tv_sec,
 	    swap_type = DRI2_BLIT_COMPLETE;
 	}
 
-        DRI2SwapComplete(event->client, drawable, frame, tv_sec, tv_usec,
-                swap_type, event->event_complete, event->event_data);
+        DRI2SwapComplete(event->client, drawable, seq, usec / 1000000,
+			 usec % 1000000, swap_type, event->event_complete,
+			 event->event_data);
 
         break;
     case DRI2_WAITMSC:
-        DRI2WaitMSCComplete(event->client, drawable, frame, tv_sec, tv_usec);
+        DRI2WaitMSCComplete(event->client, drawable, seq, usec / 1000000,
+			    usec % 1000000);
         break;
     default:
         /* Unknown type */
@@ -896,12 +852,7 @@ void radeon_dri2_frame_event_handler(unsigned int frame, unsigned int tv_sec,
     }
 
 cleanup:
-    if (event->valid) {
-        radeon_dri2_unref_buffer(event->front);
-        radeon_dri2_unref_buffer(event->back);
-        ListDelDRI2ClientEvents(event->client, &event->link);
-    }
-    free(event);
+    radeon_dri2_frame_event_abort(scrn, event_data);
 }
 
 drmVBlankSeqType radeon_populate_vbl_request_type(xf86CrtcPtr crtc)
@@ -1067,17 +1018,13 @@ static
 CARD32 radeon_dri2_deferred_event(OsTimerPtr timer, CARD32 now, pointer data)
 {
     DRI2FrameEventPtr event_info = (DRI2FrameEventPtr)data;
-    DrawablePtr drawable;
-    ScreenPtr screen;
+    xf86CrtcPtr crtc = event_info->crtc;
     ScrnInfoPtr scrn;
     RADEONInfoPtr info;
-    int status;
     CARD64 drm_now;
     int ret;
-    unsigned int tv_sec, tv_usec;
     CARD64 delta_t, delta_seq, frame;
     drmmode_crtc_private_ptr drmmode_crtc;
-    TimerFree(timer);
 
     /*
      * This is emulated event, so its time is current time, which we
@@ -1088,28 +1035,26 @@ CARD32 radeon_dri2_deferred_event(OsTimerPtr timer, CARD32 now, pointer data)
      */
     if (!event_info->crtc) {
 	ErrorF("%s no crtc\n", __func__);
-	radeon_dri2_frame_event_handler(0, 0, 0, data);
-	return 0;
-    }
-    status = dixLookupDrawable(&drawable, event_info->drawable_id, serverClient,
-			       M_ANY, DixWriteAccess);
-    if (status != Success) {
-	ErrorF("%s cannot lookup drawable\n", __func__);
-	radeon_dri2_frame_event_handler(0, 0, 0, data);
+	if (event_info->drm_queue)
+	    radeon_drm_abort_entry(event_info->drm_queue);
+	else
+	    radeon_dri2_frame_event_abort(NULL, data);
 	return 0;
     }
-    screen = drawable->pScreen;
-    scrn = xf86ScreenToScrn(screen);
+
+    scrn = crtc->scrn;
     info = RADEONPTR(scrn);
     ret = drmmode_get_current_ust(info->dri2.drm_fd, &drm_now);
     if (ret) {
 	xf86DrvMsg(scrn->scrnIndex, X_ERROR,
 		   "%s cannot get current time\n", __func__);
-	radeon_dri2_frame_event_handler(0, 0, 0, data);
+	if (event_info->drm_queue)
+	    radeon_drm_queue_handler(info->dri2.drm_fd, 0, 0, 0,
+				     event_info->drm_queue);
+	else
+	    radeon_dri2_frame_event_handler(scrn, 0, 0, data);
 	return 0;
     }
-    tv_sec = (unsigned int)(drm_now / 1000000);
-    tv_usec = (unsigned int)(drm_now - (CARD64)tv_sec * 1000000);
     /*
      * calculate the frame number from current time
      * that would come from CRTC if it were running
@@ -1119,20 +1064,22 @@ CARD32 radeon_dri2_deferred_event(OsTimerPtr timer, CARD32 now, pointer data)
     delta_seq = delta_t * drmmode_crtc->dpms_last_fps;
     delta_seq /= 1000000;
     frame = (CARD64)drmmode_crtc->dpms_last_seq + delta_seq;
-    frame &= 0xffffffff;
-    radeon_dri2_frame_event_handler((unsigned int)frame, tv_sec, tv_usec, data);
+    if (event_info->drm_queue)
+	radeon_drm_queue_handler(info->dri2.drm_fd, frame, drm_now / 1000000,
+				 drm_now % 1000000, event_info->drm_queue);
+    else
+	radeon_dri2_frame_event_handler(scrn, frame, drm_now, data);
     return 0;
 }
 
 static
-void radeon_dri2_schedule_event(CARD32 delay, pointer arg)
+void radeon_dri2_schedule_event(CARD32 delay, DRI2FrameEventPtr event_info)
 {
-    OsTimerPtr timer;
-
-    timer = TimerSet(NULL, 0, delay, radeon_dri2_deferred_event, arg);
+    event_info->timer = TimerSet(NULL, 0, delay, radeon_dri2_deferred_event,
+				 event_info);
     if (delay == 0) {
 	CARD32 now = GetTimeInMillis();
-	radeon_dri2_deferred_event(timer, now, arg);
+	radeon_dri2_deferred_event(event_info->timer, now, event_info);
     }
 }
 
@@ -1150,6 +1097,7 @@ static int radeon_dri2_schedule_wait_msc(ClientPtr client, DrawablePtr draw,
     ScrnInfoPtr scrn = xf86ScreenToScrn(screen);
     RADEONInfoPtr info = RADEONPTR(scrn);
     DRI2FrameEventPtr wait_info = NULL;
+    struct radeon_drm_queue_entry *wait = NULL;
     xf86CrtcPtr crtc = radeon_dri2_drawable_crtc(draw, TRUE);
     drmVBlank vbl;
     int ret;
@@ -1172,17 +1120,8 @@ static int radeon_dri2_schedule_wait_msc(ClientPtr client, DrawablePtr draw,
     wait_info->drawable_id = draw->id;
     wait_info->client = client;
     wait_info->type = DRI2_WAITMSC;
-    wait_info->valid = TRUE;
     wait_info->crtc = crtc;
 
-    if (ListAddDRI2ClientEvents(client, &wait_info->link)) {
-        xf86DrvMsg(scrn->scrnIndex, X_WARNING,
-                "add events to client private failed.\n");
-        free(wait_info);
-        wait_info = NULL;
-        goto out_complete;
-    }
-
     /*
      * CRTC is in DPMS off state, calculate wait time from current time,
      * target_msc and last vblank time/sequence when CRTC was turned off
@@ -1210,6 +1149,16 @@ static int radeon_dri2_schedule_wait_msc(ClientPtr client, DrawablePtr draw,
     current_msc = vbl.reply.sequence + radeon_get_interpolated_vblanks(crtc);
     current_msc &= 0xffffffff;
 
+    wait = radeon_drm_queue_alloc(scrn, client, RADEON_DRM_QUEUE_ID_DEFAULT,
+				  wait_info, radeon_dri2_frame_event_handler,
+				  radeon_dri2_frame_event_abort);
+    if (!wait) {
+        xf86DrvMsg(scrn->scrnIndex, X_WARNING,
+		   "Allocating DRM queue event entry failed.\n");
+        goto out_complete;
+    }
+    wait_info->drm_queue = wait;
+
     /*
      * If divisor is zero, or current_msc is smaller than target_msc,
      * we just need to make sure target_msc passes  before waking up the
@@ -1228,7 +1177,7 @@ static int radeon_dri2_schedule_wait_msc(ClientPtr client, DrawablePtr draw,
 	vbl.request.type |= radeon_populate_vbl_request_type(crtc);
         vbl.request.sequence = target_msc;
 	vbl.request.sequence -= radeon_get_interpolated_vblanks(crtc);
-        vbl.request.signal = (unsigned long)wait_info;
+        vbl.request.signal = (unsigned long)wait;
         ret = drmWaitVBlank(info->dri2.drm_fd, &vbl);
         if (ret) {
             xf86DrvMsg(scrn->scrnIndex, X_WARNING,
@@ -1260,7 +1209,7 @@ static int radeon_dri2_schedule_wait_msc(ClientPtr client, DrawablePtr draw,
         vbl.request.sequence += divisor;
     vbl.request.sequence -= radeon_get_interpolated_vblanks(crtc);
 
-    vbl.request.signal = (unsigned long)wait_info;
+    vbl.request.signal = (unsigned long)wait;
     ret = drmWaitVBlank(info->dri2.drm_fd, &vbl);
     if (ret) {
         xf86DrvMsg(scrn->scrnIndex, X_WARNING,
@@ -1273,11 +1222,8 @@ static int radeon_dri2_schedule_wait_msc(ClientPtr client, DrawablePtr draw,
     return TRUE;
 
 out_complete:
-    if (wait_info) {
-        ListDelDRI2ClientEvents(wait_info->client, &wait_info->link);
-        free(wait_info);
-    }
-    DRI2WaitMSCComplete(client, draw, target_msc, 0, 0);
+    if (wait_info)
+	radeon_dri2_deferred_event(NULL, 0, wait_info);
     return TRUE;
 }
 
@@ -1314,6 +1260,7 @@ static int radeon_dri2_schedule_swap(ClientPtr client, DrawablePtr draw,
     drmVBlank vbl;
     int ret, flip = 0;
     DRI2FrameEventPtr swap_info = NULL;
+    struct radeon_drm_queue_entry *swap;
     CARD64 current_msc;
     BoxRec box;
     RegionRec region;
@@ -1346,15 +1293,17 @@ static int radeon_dri2_schedule_swap(ClientPtr client, DrawablePtr draw,
     swap_info->event_data = data;
     swap_info->front = front;
     swap_info->back = back;
-    swap_info->valid = TRUE;
     swap_info->crtc = crtc;
-    if (ListAddDRI2ClientEvents(client, &swap_info->link)) {
+
+    swap = radeon_drm_queue_alloc(scrn, client, RADEON_DRM_QUEUE_ID_DEFAULT,
+				  swap_info, radeon_dri2_frame_event_handler,
+				  radeon_dri2_frame_event_abort);
+    if (!swap) {
         xf86DrvMsg(scrn->scrnIndex, X_WARNING,
-                "add events to client private failed.\n");
-        free(swap_info);
-        swap_info = NULL;
+		   "Allocating DRM queue entry failed.\n");
         goto blit_fallback;
     }
+    swap_info->drm_queue = swap;
 
     /*
      * CRTC is in DPMS off state, fallback to blit, but calculate
@@ -1421,7 +1370,7 @@ static int radeon_dri2_schedule_swap(ClientPtr client, DrawablePtr draw,
 
         vbl.request.sequence = *target_msc;
 	vbl.request.sequence -= radeon_get_interpolated_vblanks(crtc);
-        vbl.request.signal = (unsigned long)swap_info;
+        vbl.request.signal = (unsigned long)swap;
         ret = drmWaitVBlank(info->dri2.drm_fd, &vbl);
         if (ret) {
             xf86DrvMsg(scrn->scrnIndex, X_WARNING,
@@ -1468,7 +1417,7 @@ static int radeon_dri2_schedule_swap(ClientPtr client, DrawablePtr draw,
     /* Account for 1 frame extra pageflip delay if flip > 0 */
     vbl.request.sequence -= flip;
 
-    vbl.request.signal = (unsigned long)swap_info;
+    vbl.request.signal = (unsigned long)swap;
     ret = drmWaitVBlank(info->dri2.drm_fd, &vbl);
     if (ret) {
         xf86DrvMsg(scrn->scrnIndex, X_WARNING,
@@ -1581,22 +1530,6 @@ radeon_dri2_screen_init(ScreenPtr pScreen)
             driverNames[1] = NULL; /* no VDPAU support */
 
 	if (DRI2InfoCnt == 0) {
-#if HAS_DIXREGISTERPRIVATEKEY
-	    if (!dixRegisterPrivateKey(DRI2ClientEventsPrivateKey,
-				       PRIVATE_CLIENT, sizeof(DRI2ClientEventsRec))) {
-		xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "DRI2 registering "
-			   "private key to client failed\n");
-		return FALSE;
-	    }
-#else
-	    if (!dixRequestPrivate(DRI2ClientEventsPrivateKey,
-				   sizeof(DRI2ClientEventsRec))) {
-		xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "DRI2 requesting "
-			   "private key to client failed\n");
-		return FALSE;
-	    }
-#endif
-
 	    AddCallback(&ClientStateCallback, radeon_dri2_client_state_changed, 0);
 	}
 
diff --git a/src/radeon_dri2.h b/src/radeon_dri2.h
index 37d46f3..9ba47c7 100644
--- a/src/radeon_dri2.h
+++ b/src/radeon_dri2.h
@@ -43,48 +43,11 @@ struct radeon_dri2 {
 Bool radeon_dri2_screen_init(ScreenPtr pScreen);
 void radeon_dri2_close_screen(ScreenPtr pScreen);
 
-int drmmode_get_crtc_id(xf86CrtcPtr crtc);
-void radeon_dri2_frame_event_handler(unsigned int frame, unsigned int tv_sec,
-                                     unsigned int tv_usec, void *event_data);
-void radeon_dri2_flip_event_handler(unsigned int frame, unsigned int tv_sec,
-				    unsigned int tv_usec, void *event_data);
-
 #else
 
 static inline Bool radeon_dri2_screen_init(ScreenPtr pScreen) { return FALSE; }
 static inline void radeon_dri2_close_screen(ScreenPtr pScreen) {}
 
-static inline void
-radeon_dri2_dummy_event_handler(unsigned int frame, unsigned int tv_sec,
-				unsigned int tv_usec, void *event_data,
-				const char *name)
-{
-	static Bool warned;
-
-	if (!warned) {
-		ErrorF("%s called but DRI2 disabled at build time\n", name);
-		warned = TRUE;
-	}
-
-	free(event_data);
-}
-
-static inline void
-radeon_dri2_frame_event_handler(unsigned int frame, unsigned int tv_sec,
-				unsigned int tv_usec, void *event_data)
-{
-	radeon_dri2_dummy_event_handler(frame, tv_sec, tv_usec, event_data,
-					__func__);
-}
-
-static inline void
-radeon_dri2_flip_event_handler(unsigned int frame, unsigned int tv_sec,
-			       unsigned int tv_usec, void *event_data)
-{
-	radeon_dri2_dummy_event_handler(frame, tv_sec, tv_usec, event_data,
-					__func__);
-}
-
 #endif
 
 #endif /* RADEON_DRI2_H */
commit c3fa22a479e61d1899fa9d327d9c4e2a7f64b0c1
Author: Michel Dänzer <michel.daenzer at amd.com>
Date:   Wed Mar 11 17:47:59 2015 +0900

    DRI2: Move radeon_dri2_flip_event_handler
    
    In preparation for the next change, which will modify it to a static
    function which needs to be in the new place. No functional change.
    
    Reviewed-by: Alex Deucher <alexander.deucher at amd.com>

diff --git a/src/radeon_dri2.c b/src/radeon_dri2.c
index a0eecac..a3f0776 100644
--- a/src/radeon_dri2.c
+++ b/src/radeon_dri2.c
@@ -613,6 +613,64 @@ xf86CrtcPtr radeon_dri2_drawable_crtc(DrawablePtr pDraw, Bool consider_disabled)
 	return NULL;
 }
 
+void radeon_dri2_flip_event_handler(unsigned int frame, unsigned int tv_sec,
+				    unsigned int tv_usec, void *event_data)
+{
+    DRI2FrameEventPtr flip = event_data;
+    DrawablePtr drawable;
+    ScreenPtr screen;
+    ScrnInfoPtr scrn;
+    int status;
+    PixmapPtr pixmap;
+
+    status = dixLookupDrawable(&drawable, flip->drawable_id, serverClient,
+			       M_ANY, DixWriteAccess);
+    if (status != Success) {
+	free(flip);
+	return;
+    }
+    if (!flip->crtc) {
+	free(flip);
+	return;
+    }
+    frame += radeon_get_interpolated_vblanks(flip->crtc);
+
+    screen = drawable->pScreen;
+    scrn = xf86ScreenToScrn(screen);
+
+    pixmap = screen->GetScreenPixmap(screen);
+    xf86DrvMsgVerb(scrn->scrnIndex, X_INFO, RADEON_LOGLEVEL_DEBUG,
+		   "%s:%d fevent[%p] width %d pitch %d (/4 %d)\n",
+		   __func__, __LINE__, flip, pixmap->drawable.width, pixmap->devKind, pixmap->devKind/4);
+
+    /* We assume our flips arrive in order, so we don't check the frame */
+    switch (flip->type) {
+    case DRI2_SWAP:
+	/* Check for too small vblank count of pageflip completion, taking wraparound
+	 * into account. This usually means some defective kms pageflip completion,
+	 * causing wrong (msc, ust) return values and possible visual corruption.
+	 */
+	if ((frame < flip->frame) && (flip->frame - frame < 5)) {
+	    xf86DrvMsg(scrn->scrnIndex, X_WARNING,
+		       "%s: Pageflip completion event has impossible msc %d < target_msc %d\n",
+		        __func__, frame, flip->frame);
+	    /* All-Zero values signal failure of (msc, ust) timestamping to client. */
+	    frame = tv_sec = tv_usec = 0;
+	}
+
+	DRI2SwapComplete(flip->client, drawable, frame, tv_sec, tv_usec,
+			 DRI2_FLIP_COMPLETE, flip->event_complete,
+			 flip->event_data);
+	break;
+    default:
+	xf86DrvMsg(scrn->scrnIndex, X_WARNING, "%s: unknown vblank event received\n", __func__);
+	/* Unknown type */
+	break;
+    }
+
+    free(flip);
+}
+
 static Bool
 radeon_dri2_schedule_flip(ScrnInfoPtr scrn, ClientPtr client,
 			  DrawablePtr draw, DRI2BufferPtr front,
@@ -1223,64 +1281,6 @@ out_complete:
     return TRUE;
 }
 
-void radeon_dri2_flip_event_handler(unsigned int frame, unsigned int tv_sec,
-				    unsigned int tv_usec, void *event_data)
-{
-    DRI2FrameEventPtr flip = event_data;
-    DrawablePtr drawable;
-    ScreenPtr screen;
-    ScrnInfoPtr scrn;
-    int status;
-    PixmapPtr pixmap;
-
-    status = dixLookupDrawable(&drawable, flip->drawable_id, serverClient,
-			       M_ANY, DixWriteAccess);
-    if (status != Success) {
-	free(flip);
-	return;
-    }
-    if (!flip->crtc) {
-	free(flip);
-	return;
-    }
-    frame += radeon_get_interpolated_vblanks(flip->crtc);
-
-    screen = drawable->pScreen;
-    scrn = xf86ScreenToScrn(screen);
-
-    pixmap = screen->GetScreenPixmap(screen);
-    xf86DrvMsgVerb(scrn->scrnIndex, X_INFO, RADEON_LOGLEVEL_DEBUG,
-		   "%s:%d fevent[%p] width %d pitch %d (/4 %d)\n",
-		   __func__, __LINE__, flip, pixmap->drawable.width, pixmap->devKind, pixmap->devKind/4);
-
-    /* We assume our flips arrive in order, so we don't check the frame */
-    switch (flip->type) {
-    case DRI2_SWAP:
-	/* Check for too small vblank count of pageflip completion, taking wraparound
-	 * into account. This usually means some defective kms pageflip completion,
-	 * causing wrong (msc, ust) return values and possible visual corruption.
-	 */
-	if ((frame < flip->frame) && (flip->frame - frame < 5)) {
-	    xf86DrvMsg(scrn->scrnIndex, X_WARNING,
-		       "%s: Pageflip completion event has impossible msc %d < target_msc %d\n",
-		        __func__, frame, flip->frame);
-	    /* All-Zero values signal failure of (msc, ust) timestamping to client. */
-	    frame = tv_sec = tv_usec = 0;
-	}
-
-	DRI2SwapComplete(flip->client, drawable, frame, tv_sec, tv_usec,
-			 DRI2_FLIP_COMPLETE, flip->event_complete,
-			 flip->event_data);
-	break;
-    default:
-	xf86DrvMsg(scrn->scrnIndex, X_WARNING, "%s: unknown vblank event received\n", __func__);
-	/* Unknown type */
-	break;
-    }
-
-    free(flip);
-}
-
 /*
  * ScheduleSwap is responsible for requesting a DRM vblank event for the
  * appropriate frame.
commit 65045112fdc8a9fa36e0e00f46739a6152b775ff
Author: Michel Dänzer <michel.daenzer at amd.com>
Date:   Wed Mar 11 17:33:54 2015 +0900

    DRI2: Remove superfluous assignments to *_info->frame
    
    That field is only used for page flipping.
    
    Reviewed-by: Alex Deucher <alexander.deucher at amd.com>

diff --git a/src/radeon_dri2.c b/src/radeon_dri2.c
index 31bd73c..a0eecac 100644
--- a/src/radeon_dri2.c
+++ b/src/radeon_dri2.c
@@ -1133,7 +1133,6 @@ static int radeon_dri2_schedule_wait_msc(ClientPtr client, DrawablePtr draw,
 	CARD32 delay;
 	delay = radeon_dri2_extrapolate_msc_delay(crtc, &target_msc,
 						  divisor, remainder);
-	wait_info->frame = target_msc;
 	radeon_dri2_schedule_event(delay, wait_info);
 	DRI2BlockClient(client, draw);
 	return TRUE;
@@ -1179,8 +1178,6 @@ static int radeon_dri2_schedule_wait_msc(ClientPtr client, DrawablePtr draw,
             goto out_complete;
         }
 
-        wait_info->frame = vbl.reply.sequence;
-	wait_info->frame += radeon_get_interpolated_vblanks(crtc);
         DRI2BlockClient(client, draw);
         return TRUE;
     }
@@ -1213,8 +1210,6 @@ static int radeon_dri2_schedule_wait_msc(ClientPtr client, DrawablePtr draw,
         goto out_complete;
     }
 
-    wait_info->frame = vbl.reply.sequence;
-    wait_info->frame += radeon_get_interpolated_vblanks(crtc);
     DRI2BlockClient(client, draw);
 
     return TRUE;
@@ -1370,7 +1365,6 @@ static int radeon_dri2_schedule_swap(ClientPtr client, DrawablePtr draw,
 	CARD32 delay;
 	delay = radeon_dri2_extrapolate_msc_delay(crtc, target_msc,
 						  divisor, remainder);
-	swap_info->frame = *target_msc;
 	radeon_dri2_schedule_event(delay, swap_info);
 	return TRUE;
     }
commit ad27f16f308079d06a2b1c788b3cb0947531253a
Author: Michel Dänzer <michel.daenzer at amd.com>
Date:   Wed Mar 11 17:30:11 2015 +0900

    DRI2: Simplify blit fallback handling for scheduled swaps
    
    Also use radeon_dri2_schedule_event when possible.
    
    Reviewed-by: Alex Deucher <alexander.deucher at amd.com>

diff --git a/src/radeon_dri2.c b/src/radeon_dri2.c
index 36ab4d0..31bd73c 100644
--- a/src/radeon_dri2.c
+++ b/src/radeon_dri2.c
@@ -1319,7 +1319,6 @@ static int radeon_dri2_schedule_swap(ClientPtr client, DrawablePtr draw,
     drmVBlank vbl;
     int ret, flip = 0;
     DRI2FrameEventPtr swap_info = NULL;
-    enum DRI2FrameEventType swap_type = DRI2_SWAP;
     CARD64 current_msc;
     BoxRec box;
     RegionRec region;
@@ -1345,6 +1344,7 @@ static int radeon_dri2_schedule_swap(ClientPtr client, DrawablePtr draw,
     if (!swap_info)
         goto blit_fallback;
 
+    swap_info->type = DRI2_SWAP;
     swap_info->drawable_id = draw->id;
     swap_info->client = client;
     swap_info->event_complete = func;
@@ -1384,9 +1384,7 @@ static int radeon_dri2_schedule_swap(ClientPtr client, DrawablePtr draw,
         xf86DrvMsg(scrn->scrnIndex, X_WARNING,
                 "first get vblank counter failed: %s\n",
                 strerror(errno));
-	*target_msc = 0;
-	radeon_dri2_schedule_event(FALLBACK_SWAP_DELAY, swap_info);
-	return TRUE;
+	goto blit_fallback;
     }
 
     current_msc = vbl.reply.sequence + radeon_get_interpolated_vblanks(crtc);
@@ -1394,13 +1392,11 @@ static int radeon_dri2_schedule_swap(ClientPtr client, DrawablePtr draw,
 
     /* Flips need to be submitted one frame before */
     if (can_flip(scrn, draw, front, back)) {
-	swap_type = DRI2_FLIP;
+	swap_info->type = DRI2_FLIP;
 	flip = 1;
     }
 
-    swap_info->type = swap_type;
-
-    /* Correct target_msc by 'flip' if swap_type == DRI2_FLIP.
+    /* Correct target_msc by 'flip' if swap_info->type == DRI2_FLIP.
      * Do it early, so handling of different timing constraints
      * for divisor, remainder and msc vs. target_msc works.
      */
@@ -1437,9 +1433,7 @@ static int radeon_dri2_schedule_swap(ClientPtr client, DrawablePtr draw,
             xf86DrvMsg(scrn->scrnIndex, X_WARNING,
                     "divisor 0 get vblank counter failed: %s\n",
                     strerror(errno));
-	    *target_msc = 0;
-	    radeon_dri2_schedule_event(FALLBACK_SWAP_DELAY, swap_info);
-            return TRUE;
+	    goto blit_fallback;
         }
 
         *target_msc = vbl.reply.sequence + flip;
@@ -1486,9 +1480,7 @@ static int radeon_dri2_schedule_swap(ClientPtr client, DrawablePtr draw,
         xf86DrvMsg(scrn->scrnIndex, X_WARNING,
                 "final get vblank counter failed: %s\n",
                 strerror(errno));
-	*target_msc = 0;
-	radeon_dri2_schedule_event(FALLBACK_SWAP_DELAY, swap_info);
-	return TRUE;
+	goto blit_fallback;
     }
 
     /* Adjust returned value for 1 fame pageflip offset of flip > 0 */
@@ -1499,22 +1491,23 @@ static int radeon_dri2_schedule_swap(ClientPtr client, DrawablePtr draw,
     return TRUE;
 
 blit_fallback:
-    box.x1 = 0;
-    box.y1 = 0;
-    box.x2 = draw->width;
-    box.y2 = draw->height;
-    REGION_INIT(pScreen, &region, &box, 0);
+    if (swap_info) {
+	swap_info->type = DRI2_SWAP;
+	radeon_dri2_schedule_event(FALLBACK_SWAP_DELAY, swap_info);
+    } else {
+	box.x1 = 0;
+	box.y1 = 0;
+	box.x2 = draw->width;
+	box.y2 = draw->height;
+	REGION_INIT(pScreen, &region, &box, 0);
 
-    radeon_dri2_copy_region(draw, &region, front, back);
+	radeon_dri2_copy_region(draw, &region, front, back);
 
-    DRI2SwapComplete(client, draw, 0, 0, 0, DRI2_BLIT_COMPLETE, func, data);
-    if (swap_info) {
-        ListDelDRI2ClientEvents(swap_info->client, &swap_info->link);
-        free(swap_info);
-    }
+	DRI2SwapComplete(client, draw, 0, 0, 0, DRI2_BLIT_COMPLETE, func, data);
 
-    radeon_dri2_unref_buffer(front);
-    radeon_dri2_unref_buffer(back);
+	radeon_dri2_unref_buffer(front);
+	radeon_dri2_unref_buffer(back);
+    }
 
     *target_msc = 0; /* offscreen, so zero out target vblank count */
     return TRUE;
commit b4af8a327ed8420f0ff4ea0f113f4a59406ed4d3
Author: Michel Dänzer <michel.daenzer at amd.com>
Date:   Mon Mar 2 18:59:54 2015 +0900

    Add DRM event queue helpers v2
    
    v2: Rename struct radeon_drm_queue to struct radeon_drm_queue_event,
    thanks to Richard Wilbur <richard.wilbur at gmail.com> for the suggestion.
    Also changed the corresponding parameter and local variable names from
    'q' to 'e'.
    
    Reviewed-by: Alex Deucher <alexander.deucher at amd.com>

diff --git a/src/Makefile.am b/src/Makefile.am
index 708f2ad..9cc8a2d 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -29,8 +29,8 @@
 ati_drv_la_LIBADD = $(PCIACCESS_LIBS)
 radeon_drv_la_LIBADD = $(LIBDRM_RADEON_LIBS) $(PCIACCESS_LIBS)
 
-RADEON_KMS_SRCS=radeon_dri2.c radeon_kms.c drmmode_display.c radeon_vbo.c \
-	radeon_bo_helper.c
+RADEON_KMS_SRCS=radeon_dri2.c radeon_drm_queue.c radeon_kms.c drmmode_display.c \
+	radeon_vbo.c radeon_bo_helper.c
 
 RADEON_EXA_SOURCES = radeon_exa.c r600_exa.c r6xx_accel.c r600_textured_videofuncs.c r600_shader.c radeon_exa_shared.c \
 	evergreen_exa.c evergreen_accel.c evergreen_shader.c evergreen_textured_videofuncs.c cayman_accel.c cayman_shader.c
@@ -88,6 +88,7 @@ EXTRA_DIST = \
 	bicubic_table.h \
 	bicubic_table.py \
 	radeon_bo_helper.h \
+	radeon_drm_queue.h \
 	radeon_exa_render.c \
 	radeon_exa_funcs.c \
 	radeon_exa_shared.h \
diff --git a/src/radeon_drm_queue.c b/src/radeon_drm_queue.c
new file mode 100644
index 0000000..5e54ef8
--- /dev/null
+++ b/src/radeon_drm_queue.c
@@ -0,0 +1,181 @@
+/*
+ * Copyright © 2007 Red Hat, Inc.
+ * Copyright © 2015 Advanced Micro Devices, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * Authors:
+ *    Dave Airlie <airlied at redhat.com>
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <xorg-server.h>
+
+#include "radeon.h"
+#include "radeon_drm_queue.h"
+#include "radeon_list.h"
+
+
+struct radeon_drm_queue_entry {
+    struct xorg_list list;
+    uint64_t id;
+    void *data;
+    ClientPtr client;
+    ScrnInfoPtr scrn;
+    radeon_drm_handler_proc handler;
+    radeon_drm_abort_proc abort;
+};
+
+static int radeon_drm_queue_refcnt;
+static struct xorg_list radeon_drm_queue;
+
+
+/*
+ * Handle a DRM event
+ */
+void
+radeon_drm_queue_handler(int fd, unsigned int frame, unsigned int sec,
+			 unsigned int usec, void *user_ptr)
+{
+	struct radeon_drm_queue_entry *user_data = user_ptr;
+	struct radeon_drm_queue_entry *e, *tmp;
+
+	xorg_list_for_each_entry_safe(e, tmp, &radeon_drm_queue, list) {
+		if (e == user_data) {
+			xorg_list_del(&e->list);
+			e->handler(e->scrn, frame,
+				   (uint64_t)sec * 1000000 + usec, e->data);
+			free(e);
+			break;
+		}
+	}
+}
+
+/*
+ * Enqueue a potential drm response; when the associated response
+ * appears, we've got data to pass to the handler from here
+ */
+struct radeon_drm_queue_entry *
+radeon_drm_queue_alloc(ScrnInfoPtr scrn, ClientPtr client,
+		       uint64_t id, void *data,
+		       radeon_drm_handler_proc handler,
+		       radeon_drm_abort_proc abort)
+{
+    struct radeon_drm_queue_entry *e;
+
+    e = calloc(1, sizeof(struct radeon_drm_queue_entry));
+    if (!e)
+	return NULL;
+
+    e->client = client;
+    e->scrn = scrn;
+    e->id = id;
+    e->data = data;
+    e->handler = handler;
+    e->abort = abort;
+
+    xorg_list_add(&e->list, &radeon_drm_queue);
+
+    return e;
+}
+
+/*
+ * Abort one queued DRM entry, removing it
+ * from the list, calling the abort function and
+ * freeing the memory
+ */
+static void
+radeon_drm_abort_one(struct radeon_drm_queue_entry *e)
+{
+    xorg_list_del(&e->list);
+    e->abort(e->scrn, e->data);
+    free(e);
+}
+
+/*
+ * Abort drm queue entries for a client
+ */
+void
+radeon_drm_abort_client(ClientPtr client)
+{
+    struct radeon_drm_queue_entry *e, *tmp;
+
+    xorg_list_for_each_entry_safe(e, tmp, &radeon_drm_queue, list) {
+	if (e->client == client)
+	    radeon_drm_abort_one(e);
+    }
+}
+
+/*
+ * Abort specific drm queue entry
+ */
+void
+radeon_drm_abort_entry(struct radeon_drm_queue_entry *entry)
+{
+    radeon_drm_abort_one(entry);
+}
+
+/*
+ * Abort specific drm queue entry by ID
+ */
+void
+radeon_drm_abort_id(uint64_t id)
+{
+    struct radeon_drm_queue_entry *e, *tmp;
+
+    xorg_list_for_each_entry_safe(e, tmp, &radeon_drm_queue, list) {
+	if (e->id == id) {
+	    radeon_drm_abort_one(e);
+	    break;
+	}
+    }
+}
+
+/*
+ * Initialize the DRM event queue
+ */
+void
+radeon_drm_queue_init()
+{
+    if (radeon_drm_queue_refcnt++)
+	return;
+
+    xorg_list_init(&radeon_drm_queue);
+}
+
+/*
+ * Deinitialize the DRM event queue
+ */
+void
+radeon_drm_queue_close(ScrnInfoPtr scrn)
+{
+    struct radeon_drm_queue_entry *e, *tmp;
+
+    xorg_list_for_each_entry_safe(e, tmp, &radeon_drm_queue, list) {
+	if (e->scrn == scrn)
+	    radeon_drm_abort_one(e);
+    }
+
+    radeon_drm_queue_refcnt--;
+}
diff --git a/src/radeon_drm_queue.h b/src/radeon_drm_queue.h
new file mode 100644
index 0000000..8fc1c42
--- /dev/null
+++ b/src/radeon_drm_queue.h
@@ -0,0 +1,56 @@
+/*
+ * Copyright © 2007 Red Hat, Inc.
+ * Copyright © 2015 Advanced Micro Devices, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * Authors:
+ *    Dave Airlie <airlied at redhat.com>
+ *
+ */
+
+#ifndef _RADEON_DRM_QUEUE_H_
+#define _RADEON_DRM_QUEUE_H_
+
+#define RADEON_DRM_QUEUE_CLIENT_DEFAULT serverClient
+#define RADEON_DRM_QUEUE_ID_DEFAULT ~0ULL
+
+struct radeon_drm_queue_entry;
+
+typedef void (*radeon_drm_handler_proc)(ScrnInfoPtr scrn, uint32_t seq,
+					uint64_t usec, void *data);
+typedef void (*radeon_drm_abort_proc)(ScrnInfoPtr scrn, void *data);
+
+void radeon_drm_queue_handler(int fd, unsigned int frame,
+			      unsigned int tv_sec, unsigned int tv_usec,
+			      void *user_ptr);
+struct radeon_drm_queue_entry *radeon_drm_queue_alloc(ScrnInfoPtr scrn,
+						      ClientPtr client,
+						      uint64_t id,
+						      void *data,
+						      radeon_drm_handler_proc handler,
+						      radeon_drm_abort_proc abort);
+void radeon_drm_abort_client(ClientPtr client);
+void radeon_drm_abort_entry(struct radeon_drm_queue_entry *entry);
+void radeon_drm_abort_id(uint64_t id);
+void radeon_drm_queue_init();
+void radeon_drm_queue_close(ScrnInfoPtr scrn);
+
+#endif /* _RADEON_DRM_QUEUE_H_ */
diff --git a/src/radeon_kms.c b/src/radeon_kms.c
index 62364d9..ced3594 100644
--- a/src/radeon_kms.c
+++ b/src/radeon_kms.c
@@ -32,6 +32,7 @@
 #include <sys/ioctl.h>
 /* Driver data structures */
 #include "radeon.h"
+#include "radeon_drm_queue.h"
 #include "radeon_reg.h"
 #include "radeon_probe.h"
 #include "micmap.h"
@@ -876,6 +877,8 @@ Bool RADEONPreInit_KMS(ScrnInfoPtr pScrn, int flags)
 
     if (!RADEONPreInitAccel_KMS(pScrn))              goto fail;
 
+    radeon_drm_queue_init();
+
     info->allowColorTiling2D = FALSE;
 
     RADEONSetupCapabilities(pScrn);
@@ -1173,6 +1176,7 @@ static Bool RADEONCloseScreen_KMS(CLOSE_SCREEN_ARGS_DECL)
 		   "RADEONCloseScreen\n");
 
     drmmode_uevent_fini(pScrn, &info->drmmode);
+    radeon_drm_queue_close(pScrn);
     radeon_cs_flush_indirect(pScrn);
 
     DeleteCallback(&FlushCallback, radeon_flush_callback, pScrn);
commit 7c3470f4b659206ed23f761948936ede3a2dba3d
Author: Michel Dänzer <michel.daenzer at amd.com>
Date:   Fri Mar 6 18:51:29 2015 +0900

    Move xorg_list backwards compatibility to new radeon_list.h header
    
    Reviewed-by: Alex Deucher <alexander.deucher at amd.com>

diff --git a/src/Makefile.am b/src/Makefile.am
index 9ff1ffb..708f2ad 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -93,6 +93,7 @@ EXTRA_DIST = \
 	radeon_exa_shared.h \
 	radeon_glamor.h \
 	radeon.h \
+	radeon_list.h \
 	radeon_probe.h \
 	radeon_reg.h \
 	radeon_version.h \
diff --git a/src/radeon_dri2.c b/src/radeon_dri2.c
index 8cc7e56..36ab4d0 100644
--- a/src/radeon_dri2.c
+++ b/src/radeon_dri2.c
@@ -41,15 +41,7 @@
 #include <errno.h>
 
 #include "radeon_version.h"
-
-#include "list.h"
-#if !HAVE_XORG_LIST
-#define xorg_list			list
-#define xorg_list_init			list_init
-#define xorg_list_add			list_add
-#define xorg_list_del			list_del
-#define xorg_list_for_each_entry	list_for_each_entry
-#endif
+#include "radeon_list.h"
 
 #include "radeon_bo_gem.h"
 
diff --git a/src/radeon_list.h b/src/radeon_list.h
new file mode 100644
index 0000000..4002013
--- /dev/null
+++ b/src/radeon_list.h
@@ -0,0 +1,38 @@
+/*
+ * Copyright © 2015 Advanced Micro Devices, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#ifndef _RADEON_LIST_H_
+#define _RADEON_LIST_H_
+
+#include <xorg-server.h>
+#include <list.h>
+
+#if !HAVE_XORG_LIST
+#define xorg_list			list
+#define xorg_list_init			list_init
+#define xorg_list_add			list_add
+#define xorg_list_del			list_del
+#define xorg_list_for_each_entry	list_for_each_entry
+#endif
+
+#endif /* _RADEON_LIST_H_ */
commit 7388d0b6c54b9d536fdb161e3aa61b326627b939
Author: Michel Dänzer <michel.daenzer at amd.com>
Date:   Thu Mar 5 17:35:06 2015 +0900

    Require at least xserver 1.8
    
    So we can rely on the list.h header.
    
    xserver 1.8 was released in April 2010.
    
    Reviewed-by: Alex Deucher <alexander.deucher at amd.com>

diff --git a/configure.ac b/configure.ac
index c471ff5..891da03 100644
--- a/configure.ac
+++ b/configure.ac
@@ -75,7 +75,7 @@ PKG_CHECK_MODULES(LIBDRM, [libdrm >= 2.4.58])
 PKG_CHECK_MODULES(LIBDRM_RADEON, [libdrm_radeon])
 
 # Obtain compiler/linker options for the driver dependencies
-PKG_CHECK_MODULES(XORG, [xorg-server >= 1.7 xproto fontsproto xf86driproto $REQUIRED_MODULES])
+PKG_CHECK_MODULES(XORG, [xorg-server >= 1.8 xproto fontsproto xf86driproto $REQUIRED_MODULES])
 PKG_CHECK_MODULES(XEXT, [xextproto >= 7.0.99.1],
                   HAVE_XEXTPROTO_71="yes"; AC_DEFINE(HAVE_XEXTPROTO_71, 1, [xextproto 7.1 available]),
                   HAVE_XEXTPROTO_71="no")
@@ -125,18 +125,11 @@ else
 fi
 AM_CONDITIONAL(GLAMOR, test x$GLAMOR != xno)
 
-AC_CHECK_HEADERS([list.h],
-		 [have_list_h="yes"], [have_list_h="no"],
-		 [#include <X11/Xdefs.h>
-		  #include "xorg-server.h"])
-
-if test "x$have_list_h" = xyes; then
-    AC_CHECK_DECL(xorg_list_init,
-		  [AC_DEFINE(HAVE_XORG_LIST, 1, [Have xorg_list API])], [],
-		  [#include <X11/Xdefs.h>
-		   #include "xorg-server.h"
-		   #include "list.h"])
-fi
+AC_CHECK_DECL(xorg_list_init,
+	      [AC_DEFINE(HAVE_XORG_LIST, 1, [Have xorg_list API])], [],
+	      [#include <X11/Xdefs.h>
+	      #include "xorg-server.h"
+	      #include "list.h"])
 
 CPPFLAGS="$SAVE_CPPFLAGS"
 
diff --git a/src/radeon_dri2.c b/src/radeon_dri2.c
index 56beeec..8cc7e56 100644
--- a/src/radeon_dri2.c
+++ b/src/radeon_dri2.c
@@ -42,7 +42,6 @@
 
 #include "radeon_version.h"
 
-#if HAVE_LIST_H
 #include "list.h"
 #if !HAVE_XORG_LIST
 #define xorg_list			list
@@ -51,15 +50,9 @@
 #define xorg_list_del			list_del
 #define xorg_list_for_each_entry	list_for_each_entry
 #endif
-#endif
-
 
 #include "radeon_bo_gem.h"
 
-#if DRI2INFOREC_VERSION >= 4 && HAVE_LIST_H
-#define USE_DRI2_SCHEDULING
-#endif
-
 #if DRI2INFOREC_VERSION >= 9
 #define USE_DRI2_PRIME
 #endif
@@ -490,8 +483,6 @@ radeon_dri2_copy_region(DrawablePtr pDraw, RegionPtr pRegion,
 				     pDstBuffer, pSrcBuffer);
 }
 
-#ifdef USE_DRI2_SCHEDULING
-
 enum DRI2FrameEventType {
     DRI2_SWAP,
     DRI2_FLIP,
@@ -1537,8 +1528,6 @@ blit_fallback:
     return TRUE;
 }
 
-#endif /* USE_DRI2_SCHEDULING */
-
 
 Bool
 radeon_dri2_screen_init(ScreenPtr pScreen)
@@ -1546,10 +1535,8 @@ radeon_dri2_screen_init(ScreenPtr pScreen)
     ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
     RADEONInfoPtr info = RADEONPTR(pScrn);
     DRI2InfoRec dri2_info = { 0 };
-#ifdef USE_DRI2_SCHEDULING
     const char *driverNames[2];
     Bool scheduling_works = TRUE;
-#endif
 
     if (!info->dri2.available)
         return FALSE;
@@ -1574,7 +1561,6 @@ radeon_dri2_screen_init(ScreenPtr pScreen)
     dri2_info.DestroyBuffer = radeon_dri2_destroy_buffer;
     dri2_info.CopyRegion = radeon_dri2_copy_region;
 
-#ifdef USE_DRI2_SCHEDULING
     if (info->dri2.pKernelDRMVersion->version_minor < 4) {
 	xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "You need a newer kernel for "
 		   "sync extension\n");
@@ -1637,7 +1623,6 @@ radeon_dri2_screen_init(ScreenPtr pScreen)
 
 	DRI2InfoCnt++;
     }
-#endif
 
 #if DRI2INFOREC_VERSION >= 9
     dri2_info.version = 9;
@@ -1655,10 +1640,8 @@ void radeon_dri2_close_screen(ScreenPtr pScreen)
     ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
     RADEONInfoPtr info = RADEONPTR(pScrn);
 
-#ifdef USE_DRI2_SCHEDULING
     if (--DRI2InfoCnt == 0)
     	DeleteCallback(&ClientStateCallback, radeon_dri2_client_state_changed, 0);
-#endif
 
     DRI2CloseScreen(pScreen);
     drmFree(info->dri2.device_name);


More information about the xorg-commit mailing list