xf86-video-amdgpu: Branch 'master' - 13 commits

Michel Dänzer daenzer at kemper.freedesktop.org
Mon Jun 8 02:01:40 PDT 2015


 configure.ac           |   35 ++-
 man/amdgpu.man         |    4 
 src/Makefile.am        |    5 
 src/amdgpu_bo_helper.c |  102 ++++++++--
 src/amdgpu_dri2.c      |  470 ++++++++++++++++++-------------------------------
 src/amdgpu_dri2.h      |   37 ---
 src/amdgpu_dri3.c      |  196 ++++++++++++++++++++
 src/amdgpu_drm_queue.c |  181 ++++++++++++++++++
 src/amdgpu_drm_queue.h |   56 +++++
 src/amdgpu_drv.h       |   18 +
 src/amdgpu_glamor.c    |   20 --
 src/amdgpu_glamor.h    |    5 
 src/amdgpu_kms.c       |   25 ++
 src/amdgpu_list.h      |   39 ++++
 src/amdgpu_present.c   |  394 +++++++++++++++++++++++++++++++++++++++++
 src/amdgpu_sync.c      |  147 +++++++++++++++
 src/drmmode_display.c  |  120 +++++++++---
 src/drmmode_display.h  |   14 +
 18 files changed, 1445 insertions(+), 423 deletions(-)

New commits:
commit edfff6b1a3a19953644b8052b30076f76f7dc337
Author: Michel Dänzer <michel.daenzer at amd.com>
Date:   Tue Jun 2 17:04:21 2015 +0900

    Add DRI3 support
    
    Must be enabled with
    
    	Option	"DRI3"
    
    in xorg.conf.
    
    (Cherry picked from radeon commits 64e1e4dbdd3caee6f5d8f6b6c094b4533fa94953,
    694e04720b886060fe3eefdce59741f218c8269f,
    f940fd741b15f03393037c5bb904cd74f012de9d,
    fcd37f65f485291084c174666bd605e215bf1398,
    4b0997e56dec0053cb2cb793e0f4ae35055ff7e6,
    f68d9b5ba0c91a725b5eec9386c61bea8824c299 and
    98fb4199e63fedd4607cddee64bf602d6398df81)
    
    Reviewed-by: Alex Deucher <alexander.deucher at amd.com>

diff --git a/configure.ac b/configure.ac
index b91ce17..d9d97ef 100644
--- a/configure.ac
+++ b/configure.ac
@@ -168,6 +168,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/amdgpu.man b/man/amdgpu.man
index 64633b3..bc7bf30 100644
--- a/man/amdgpu.man
+++ b/man/amdgpu.man
@@ -70,6 +70,10 @@ For example:
 Option \*qZaphodHeads\*q \*qLVDS,VGA-0\*q
 will assign xrandr outputs LVDS and VGA-0 to this instance of the driver.
 .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 fc8b77a..b953d4c 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -28,8 +28,8 @@
 
 amdgpu_drv_la_LIBADD = $(PCIACCESS_LIBS) $(LIBDRM_AMDGPU_LIBS) $(GBM_LIBS)
 
-AMDGPU_KMS_SRCS=amdgpu_bo_helper.c amdgpu_dri2.c amdgpu_drm_queue.c amdgpu_kms.c \
-	amdgpu_present.c amdgpu_sync.c drmmode_display.c
+AMDGPU_KMS_SRCS=amdgpu_bo_helper.c amdgpu_dri2.c amdgpu_dri3.c amdgpu_drm_queue.c \
+	amdgpu_kms.c amdgpu_present.c amdgpu_sync.c drmmode_display.c
 
 AM_CFLAGS = \
             @GBM_CFLAGS@ \
diff --git a/src/amdgpu_dri3.c b/src/amdgpu_dri3.c
new file mode 100644
index 0000000..ce0f8e7
--- /dev/null
+++ b/src/amdgpu_dri3.c
@@ -0,0 +1,196 @@
+/*
+ * 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 "amdgpu_drv.h"
+
+#ifdef HAVE_DRI3_H
+
+#include "amdgpu_glamor.h"
+#include "amdgpu_pixmap.h"
+#include "dri3.h"
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <errno.h>
+
+
+static int
+amdgpu_dri3_open(ScreenPtr screen, RRProviderPtr provider, int *out)
+{
+	ScrnInfoPtr scrn = xf86ScreenToScrn(screen);
+	AMDGPUInfoPtr info = AMDGPUPTR(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 amdgpu_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 = screen->CreatePixmap(screen, 0, 0, depth, 0);
+	if (!pixmap)
+		return NULL;
+
+	if (!screen->ModifyPixmapHeader(pixmap, width, height, 0, bpp, stride,
+					NULL))
+		goto free_pixmap;
+
+	if (screen->SetSharedPixmapBacking(pixmap, (void*)(intptr_t)fd))
+		return pixmap;
+
+free_pixmap:
+	fbDestroyPixmap(pixmap);
+	return NULL;
+}
+
+static int amdgpu_dri3_fd_from_pixmap(ScreenPtr screen,
+				      PixmapPtr pixmap,
+				      CARD16 *stride,
+				      CARD32 *size)
+{
+	ScrnInfoPtr scrn = xf86ScreenToScrn(screen);
+	AMDGPUInfoPtr info = AMDGPUPTR(scrn);
+	struct amdgpu_buffer *bo;
+	struct amdgpu_bo_info bo_info;
+	uint32_t fd;
+
+#ifdef USE_GLAMOR
+	if (info->use_glamor)
+		return glamor_fd_from_pixmap(screen, pixmap, stride, size);
+#endif
+
+	bo = amdgpu_get_pixmap_bo(pixmap);
+	if (!bo)
+		return -1;
+
+	if (pixmap->devKind > UINT16_MAX)
+		return -1;
+
+	if (amdgpu_bo_query_info(bo->bo.amdgpu, &bo_info) != 0)
+		return -1;
+
+	if (amdgpu_bo_export(bo->bo.amdgpu, amdgpu_bo_handle_type_dma_buf_fd,
+			     &fd) != 0)
+		return -1;
+
+	*stride = pixmap->devKind;
+	*size = bo_info.alloc_size;
+	return fd;
+}
+
+static dri3_screen_info_rec amdgpu_dri3_screen_info = {
+	.version = 0,
+
+	.open = amdgpu_dri3_open,
+	.pixmap_from_fd = amdgpu_dri3_pixmap_from_fd,
+	.fd_from_pixmap = amdgpu_dri3_fd_from_pixmap
+};
+
+Bool
+amdgpu_dri3_screen_init(ScreenPtr screen)
+{
+	ScrnInfoPtr scrn = xf86ScreenToScrn(screen);
+
+	if (!dri3_screen_init(screen, &amdgpu_dri3_screen_info)) {
+		xf86DrvMsg(scrn->scrnIndex, X_WARNING,
+			   "dri3_screen_init failed\n");
+		return FALSE;
+	}
+
+	return TRUE;
+}
+
+#else /* !HAVE_DRI3_H */
+
+Bool
+amdgpu_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/amdgpu_drv.h b/src/amdgpu_drv.h
index c6c968f..5ffbc6a 100644
--- a/src/amdgpu_drv.h
+++ b/src/amdgpu_drv.h
@@ -140,7 +140,8 @@ typedef enum {
 	OPTION_SUBPIXEL_ORDER,
 #endif
 	OPTION_ZAPHOD_HEADS,
-	OPTION_ACCEL_METHOD
+	OPTION_ACCEL_METHOD,
+	OPTION_DRI3,
 } AMDGPUOpts;
 
 #define AMDGPU_VSYNC_TIMEOUT	20000	/* Maximum wait for VSYNC (in usecs) */
@@ -233,6 +234,9 @@ typedef struct {
 } AMDGPUInfoRec, *AMDGPUInfoPtr;
 
 
+/* amdgpu_dri3.c */
+Bool amdgpu_dri3_screen_init(ScreenPtr screen);
+
 /* amdgpu_present.c */
 Bool amdgpu_present_screen_init(ScreenPtr screen);
 
diff --git a/src/amdgpu_kms.c b/src/amdgpu_kms.c
index 05e9adf..1e256af 100644
--- a/src/amdgpu_kms.c
+++ b/src/amdgpu_kms.c
@@ -66,6 +66,7 @@ const OptionInfoRec AMDGPUOptions_KMS[] = {
 	{OPTION_SUBPIXEL_ORDER, "SubPixelOrder", OPTV_ANYSTR, {0}, FALSE},
 	{OPTION_ZAPHOD_HEADS, "ZaphodHeads", OPTV_STRING, {0}, FALSE},
 	{OPTION_ACCEL_METHOD, "AccelMethod", OPTV_STRING, {0}, FALSE},
+	{ OPTION_DRI3, "DRI3", OPTV_BOOLEAN, {0}, FALSE },
 	{-1, NULL, OPTV_NONE, {0}, FALSE}
 };
 
@@ -738,6 +739,8 @@ Bool AMDGPUScreenInit_KMS(SCREEN_INIT_ARGS_DECL)
 	ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
 	AMDGPUInfoPtr info = AMDGPUPTR(pScrn);
 	int subPixelOrder = SubPixelUnknown;
+	MessageType from;
+	Bool value;
 	char *s;
 	void *front_ptr;
 	int ret;
@@ -827,8 +830,21 @@ Bool AMDGPUScreenInit_KMS(SCREEN_INIT_ARGS_DECL)
 	}
 #endif
 
-	if (amdgpu_sync_init(pScreen))
-		amdgpu_present_screen_init(pScreen);
+	value = FALSE;
+	if (xf86GetOptValBool(info->Options, OPTION_DRI3, &value))
+		from = X_CONFIG;
+	else
+		from = X_DEFAULT;
+
+	if (value) {
+		value = amdgpu_sync_init(pScreen) &&
+			amdgpu_present_screen_init(pScreen) &&
+			amdgpu_dri3_screen_init(pScreen);
+
+		if (!value)
+			from = X_WARNING;
+	}
+	xf86DrvMsg(pScrn->scrnIndex, from, "DRI3 %sabled\n", value ? "en" : "dis");
 
 	pScrn->vtSema = TRUE;
 	xf86SetBackingStore(pScreen);
commit d295b5b3310bc5c23d232c4be4170165a057c090
Author: Michel Dänzer <michel.daenzer at amd.com>
Date:   Tue Jun 2 17:01:06 2015 +0900

    amdgpu_set_shared_pixmap_backing: Add support for GBM / glamor v2
    
    v2: Initialize reference count of imported GBM BOs to 1, fixes leaking
        them.
    
    Reviewed-by: Alex Deucher <alexander.deucher at amd.com> [v1]

diff --git a/src/amdgpu_bo_helper.c b/src/amdgpu_bo_helper.c
index 0487b46..c778796 100644
--- a/src/amdgpu_bo_helper.c
+++ b/src/amdgpu_bo_helper.c
@@ -27,8 +27,32 @@
 #include <gbm.h>
 #include "amdgpu_drv.h"
 #include "amdgpu_bo_helper.h"
+#include "amdgpu_glamor.h"
 #include "amdgpu_pixmap.h"
 
+static uint32_t
+amdgpu_get_gbm_format(int depth, int bitsPerPixel)
+{
+	switch (depth) {
+#ifdef GBM_FORMAT_R8
+	case 8:
+		return GBM_FORMAT_R8;
+#endif
+	case 16:
+		return GBM_FORMAT_RGB565;
+	case 32:
+		return GBM_FORMAT_ARGB8888;
+	case 24:
+		if (bitsPerPixel == 32)
+			return GBM_FORMAT_XRGB8888;
+		/* fall through */
+	default:
+		ErrorF("%s: Unsupported depth/bpp %d/%d\n", __func__,
+		       depth, bitsPerPixel);
+		return ~0U;
+	}
+}
+
 /* Calculate appropriate pitch for a pixmap and allocate a BO that can hold it.
  */
 struct amdgpu_buffer *amdgpu_alloc_pixmap_bo(ScrnInfoPtr pScrn, int width,
@@ -40,31 +64,10 @@ struct amdgpu_buffer *amdgpu_alloc_pixmap_bo(ScrnInfoPtr pScrn, int width,
 
 	if (info->gbm) {
 		uint32_t bo_use = GBM_BO_USE_RENDERING;
-		uint32_t gbm_format;
+		uint32_t gbm_format = amdgpu_get_gbm_format(depth, bitsPerPixel);
 
-		switch (depth) {
-#ifdef GBM_FORMAT_R8
-		case 8:
-			gbm_format = GBM_FORMAT_R8;
-			break;
-#endif
-		case 16:
-			gbm_format = GBM_FORMAT_RGB565;
-			break;
-		case 32:
-			gbm_format = GBM_FORMAT_ARGB8888;
-			break;
-		case 24:
-			if (bitsPerPixel == 32) {
-				gbm_format = GBM_FORMAT_XRGB8888;
-				break;
-			}
-			/* fall through */
-		default:
-			ErrorF("%s: Unsupported depth/bpp %d/%d\n", __func__,
-			       depth, bitsPerPixel);
+		if (gbm_format == ~0U)
 			return NULL;
-		}
 
 		pixmap_buffer = (struct amdgpu_buffer *)calloc(1, sizeof(struct amdgpu_buffer));
 		if (!pixmap_buffer) {
@@ -310,11 +313,64 @@ Bool amdgpu_share_pixmap_backing(struct amdgpu_buffer *bo, void **handle_p)
 Bool amdgpu_set_shared_pixmap_backing(PixmapPtr ppix, void *fd_handle)
 {
 	ScrnInfoPtr pScrn = xf86ScreenToScrn(ppix->drawable.pScreen);
+	AMDGPUInfoPtr info = AMDGPUPTR(pScrn);
 	AMDGPUEntPtr pAMDGPUEnt = AMDGPUEntPriv(pScrn);
 	struct amdgpu_buffer *pixmap_buffer = NULL;
 	int ihandle = (int)(long)fd_handle;
 	uint32_t size = ppix->devKind * ppix->drawable.height;
 
+	if (info->gbm) {
+		struct amdgpu_pixmap *priv;
+		struct gbm_import_fd_data data;
+		uint32_t bo_use = GBM_BO_USE_RENDERING;
+
+		data.format = amdgpu_get_gbm_format(ppix->drawable.depth,
+						    ppix->drawable.bitsPerPixel);
+		if (data.format == ~0U)
+			return FALSE;
+
+		priv = calloc(1, sizeof(struct amdgpu_pixmap));
+		if (!priv)
+			return FALSE;
+
+		priv->bo = calloc(1, sizeof(struct amdgpu_buffer));
+		if (!priv->bo) {
+			free(priv);
+			return FALSE;
+		}
+		priv->bo->ref_count = 1;
+
+		data.fd = ihandle;
+		data.width = ppix->drawable.width;
+		data.height = ppix->drawable.height;
+		data.stride = ppix->devKind;
+
+		if (ppix->drawable.bitsPerPixel == pScrn->bitsPerPixel)
+			bo_use |= GBM_BO_USE_SCANOUT;
+
+		priv->bo->bo.gbm = gbm_bo_import(info->gbm, GBM_BO_IMPORT_FD,
+						 &data, bo_use);
+		if (!priv->bo->bo.gbm) {
+			free(priv->bo);
+			free(priv);
+			return FALSE;
+		}
+
+		priv->bo->flags |= AMDGPU_BO_FLAGS_GBM;
+
+#ifdef USE_GLAMOR
+		if (info->use_glamor &&
+		    !amdgpu_glamor_create_textured_pixmap(ppix, priv)) {
+			free(priv->bo);
+			free(priv);
+			return FALSE;
+		}
+#endif
+
+		amdgpu_set_pixmap_private(ppix, priv);
+		return TRUE;
+	}
+
 	pixmap_buffer = amdgpu_gem_bo_open_prime(pAMDGPUEnt->pDev, ihandle, size);
 	if (!pixmap_buffer) {
 		return FALSE;
commit 03ad0fa0185d215f7d4234006e04406af1ab63ca
Author: Michel Dänzer <michel.daenzer at amd.com>
Date:   Fri May 29 18:53:45 2015 +0900

    glamor: Add radeon_pixmap parameter to radeon_glamor_create_textured_pixmap
    
    (cherry picked from radeon commit 051d46382656ffc3e6cac1aab3aee7efdf5b623a)
    
    Reviewed-by: Michel Dänzer <michel.daenzer at amd.com>
    Signed-off-by: Darren Powell <darren.powell at amd.com>
    Reviewed-by: Alex Deucher <alexander.deucher at amd.com>

diff --git a/src/amdgpu_glamor.c b/src/amdgpu_glamor.c
index 36241ce..79b3d01 100644
--- a/src/amdgpu_glamor.c
+++ b/src/amdgpu_glamor.c
@@ -126,28 +126,22 @@ Bool amdgpu_glamor_pre_init(ScrnInfoPtr scrn)
 	return TRUE;
 }
 
-Bool amdgpu_glamor_create_textured_pixmap(PixmapPtr pixmap)
+Bool
+amdgpu_glamor_create_textured_pixmap(PixmapPtr pixmap, struct amdgpu_pixmap *priv)
 {
 	ScrnInfoPtr scrn = xf86ScreenToScrn(pixmap->drawable.pScreen);
 	AMDGPUInfoPtr info = AMDGPUPTR(scrn);
-	struct amdgpu_pixmap *priv;
 	union gbm_bo_handle bo_handle;
 
 	if ((info->use_glamor) == 0)
 		return TRUE;
 
-	priv = amdgpu_get_pixmap_private(pixmap);
-	if (!priv->stride) {
+	if (!priv->stride)
 		priv->stride = pixmap->devKind;
-	}
 
 	bo_handle = gbm_bo_get_handle(priv->bo->bo.gbm);
-	if (glamor_egl_create_textured_pixmap(pixmap, bo_handle.u32,
-					      priv->stride)) {
-		return TRUE;
-	} else {
-		return FALSE;
-	}
+	return glamor_egl_create_textured_pixmap(pixmap, bo_handle.u32,
+						 priv->stride);
 }
 
 Bool amdgpu_glamor_pixmap_is_offscreen(PixmapPtr pixmap)
@@ -206,7 +200,7 @@ amdgpu_glamor_create_pixmap(ScreenPtr screen, int w, int h, int depth,
 		screen->ModifyPixmapHeader(pixmap, w, h, 0, 0, priv->stride,
 					   NULL);
 
-		if (!amdgpu_glamor_create_textured_pixmap(pixmap))
+		if (!amdgpu_glamor_create_textured_pixmap(pixmap, priv))
 			goto fallback_glamor;
 	}
 
@@ -280,7 +274,7 @@ amdgpu_glamor_set_shared_pixmap_backing(PixmapPtr pixmap, void *handle)
 	priv = amdgpu_get_pixmap_private(pixmap);
 	priv->stride = pixmap->devKind;
 
-	if (!amdgpu_glamor_create_textured_pixmap(pixmap)) {
+	if (!amdgpu_glamor_create_textured_pixmap(pixmap, priv)) {
 		xf86DrvMsg(scrn->scrnIndex, X_ERROR,
 			   "Failed to get PRIME drawable for glamor pixmap.\n");
 		return FALSE;
diff --git a/src/amdgpu_glamor.h b/src/amdgpu_glamor.h
index 01b5ce1..f2414da 100644
--- a/src/amdgpu_glamor.h
+++ b/src/amdgpu_glamor.h
@@ -48,6 +48,8 @@
 #define GLAMOR_USE_PICTURE_SCREEN 0
 #endif
 
+struct amdgpu_pixmap;
+
 Bool amdgpu_glamor_pre_init(ScrnInfoPtr scrn);
 Bool amdgpu_glamor_init(ScreenPtr screen);
 Bool amdgpu_glamor_create_screen_resources(ScreenPtr screen);
@@ -55,7 +57,8 @@ void amdgpu_glamor_free_screen(int scrnIndex, int flags);
 
 void amdgpu_glamor_flush(ScrnInfoPtr pScrn);
 
-Bool amdgpu_glamor_create_textured_pixmap(PixmapPtr pixmap);
+Bool
+amdgpu_glamor_create_textured_pixmap(PixmapPtr pixmap, struct amdgpu_pixmap *priv);
 void amdgpu_glamor_exchange_buffers(PixmapPtr src, PixmapPtr dst);
 
 Bool amdgpu_glamor_pixmap_is_offscreen(PixmapPtr pixmap);
diff --git a/src/drmmode_display.c b/src/drmmode_display.c
index 01fe860..870ced6 100644
--- a/src/drmmode_display.c
+++ b/src/drmmode_display.c
@@ -108,7 +108,8 @@ static PixmapPtr drmmode_create_bo_pixmap(ScrnInfoPtr pScrn,
 
 	amdgpu_set_pixmap_bo(pixmap, bo);
 
-	if (!amdgpu_glamor_create_textured_pixmap(pixmap)) {
+	if (!amdgpu_glamor_create_textured_pixmap(pixmap,
+						  amdgpu_get_pixmap_private(pixmap))) {
 		pScreen->DestroyPixmap(pixmap);
 		return NULL;
 	}
commit fafb8c6ac925ad16073e5a60dbf60d5add11bb25
Author: Michel Dänzer <michel.daenzer at amd.com>
Date:   Tue Jun 2 17:00:46 2015 +0900

    Add support for the Present extension
    
    (Cherry picked from radeon commits 3c65fb849e1ba9fb6454bcaa55b696548902f3fc,
    694e04720b886060fe3eefdce59741f218c8269f,
    e3be8b0a8cf484ff16597413a6172788178e80c8,
    80eede245d1eda27eaba108b0761a24bfd69aff6 and
    5f82a720374c9c1caebb42bfbeea1f0cf8847d28)
    
    Reviewed-by: Alex Deucher <alexander.deucher at amd.com>

diff --git a/configure.ac b/configure.ac
index 2d6d4c7..b91ce17 100644
--- a/configure.ac
+++ b/configure.ac
@@ -162,6 +162,12 @@ AC_CHECK_HEADERS([misyncshm.h], [], [],
 	          #include <xorg-server.h>
 		  #include <screenint.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 fa3be5c..fc8b77a 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -29,7 +29,7 @@
 amdgpu_drv_la_LIBADD = $(PCIACCESS_LIBS) $(LIBDRM_AMDGPU_LIBS) $(GBM_LIBS)
 
 AMDGPU_KMS_SRCS=amdgpu_bo_helper.c amdgpu_dri2.c amdgpu_drm_queue.c amdgpu_kms.c \
-	amdgpu_sync.c drmmode_display.c
+	amdgpu_present.c amdgpu_sync.c drmmode_display.c
 
 AM_CFLAGS = \
             @GBM_CFLAGS@ \
diff --git a/src/amdgpu_drv.h b/src/amdgpu_drv.h
index ad51c86..c6c968f 100644
--- a/src/amdgpu_drv.h
+++ b/src/amdgpu_drv.h
@@ -233,6 +233,9 @@ typedef struct {
 } AMDGPUInfoRec, *AMDGPUInfoPtr;
 
 
+/* amdgpu_present.c */
+Bool amdgpu_present_screen_init(ScreenPtr screen);
+
 /* amdgpu_sync.c */
 extern Bool amdgpu_sync_init(ScreenPtr screen);
 extern void amdgpu_sync_close(ScreenPtr screen);
diff --git a/src/amdgpu_kms.c b/src/amdgpu_kms.c
index 28d9305..05e9adf 100644
--- a/src/amdgpu_kms.c
+++ b/src/amdgpu_kms.c
@@ -827,7 +827,8 @@ Bool AMDGPUScreenInit_KMS(SCREEN_INIT_ARGS_DECL)
 	}
 #endif
 
-	amdgpu_sync_init(pScreen);
+	if (amdgpu_sync_init(pScreen))
+		amdgpu_present_screen_init(pScreen);
 
 	pScrn->vtSema = TRUE;
 	xf86SetBackingStore(pScreen);
diff --git a/src/amdgpu_present.c b/src/amdgpu_present.c
new file mode 100644
index 0000000..c0a5a32
--- /dev/null
+++ b/src/amdgpu_present.c
@@ -0,0 +1,394 @@
+/*
+ * 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 "amdgpu_drv.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 "amdgpu_glamor.h"
+#include "amdgpu_pixmap.h"
+#include "amdgpu_video.h"
+
+#include "present.h"
+
+struct amdgpu_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
+amdgpu_present_get_crtc(WindowPtr window)
+{
+	ScreenPtr screen = window->drawable.pScreen;
+	ScrnInfoPtr pScrn = xf86ScreenToScrn(screen);
+	xf86CrtcPtr crtc;
+	RRCrtcPtr randr_crtc = NULL;
+
+	crtc = amdgpu_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
+amdgpu_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
+amdgpu_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
+amdgpu_present_vblank_handler(ScrnInfoPtr scrn, unsigned int msc,
+			      uint64_t usec, void *data)
+{
+	struct amdgpu_present_vblank_event *event = data;
+
+	present_event_notify(event->event_id, usec, msc);
+	free(event);
+}
+
+/*
+ * Called when the queued vblank is aborted
+ */
+static void
+amdgpu_present_vblank_abort(ScrnInfoPtr scrn, void *data)
+{
+	struct amdgpu_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
+amdgpu_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);
+	AMDGPUInfoPtr info = AMDGPUPTR(scrn);
+	int crtc_id = drmmode_get_crtc_id(xf86_crtc);
+	struct amdgpu_present_vblank_event *event;
+	struct amdgpu_drm_queue_entry *queue;
+	drmVBlank vbl;
+	int ret;
+
+	event = calloc(sizeof(struct amdgpu_present_vblank_event), 1);
+	if (!event)
+		return BadAlloc;
+	event->event_id = event_id;
+	queue = amdgpu_drm_queue_alloc(scrn, AMDGPU_DRM_QUEUE_CLIENT_DEFAULT,
+				       event_id, event,
+				       amdgpu_present_vblank_handler,
+				       amdgpu_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 || !amdgpu_present_flush_drm_events(screen)) {
+			amdgpu_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
+amdgpu_present_abort_vblank(RRCrtcPtr crtc, uint64_t event_id, uint64_t msc)
+{
+	amdgpu_drm_abort_id(event_id);
+}
+
+/*
+ * Flush our batch buffer when requested by the Present extension.
+ */
+static void
+amdgpu_present_flush(WindowPtr window)
+{
+	amdgpu_glamor_flush(xf86ScreenToScrn(window->drawable.pScreen));
+}
+
+/*
+ * Test to see if page flipping is possible on the target crtc
+ */
+static Bool
+amdgpu_present_check_flip(RRCrtcPtr crtc, WindowPtr window, PixmapPtr pixmap,
+			  Bool sync_flip)
+{
+	ScreenPtr screen = window->drawable.pScreen;
+	ScrnInfoPtr scrn = xf86ScreenToScrn(screen);
+	AMDGPUInfoPtr info = AMDGPUPTR(scrn);
+
+	if (!scrn->vtSema)
+		return FALSE;
+
+	if (!info->allowPageFlip)
+		return FALSE;
+
+	if (!sync_flip)
+		return FALSE;
+
+	if (crtc) {
+		xf86CrtcPtr xf86_crtc = crtc->devPrivate;
+		drmmode_crtc_private_ptr drmmode_crtc = xf86_crtc->driver_private;
+
+		if (!drmmode_crtc ||
+		    drmmode_crtc->rotate_buffer != 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
+amdgpu_present_flip_event(ScrnInfoPtr scrn, uint32_t msc, uint64_t ust, void *pageflip_data)
+{
+	struct amdgpu_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
+amdgpu_present_flip_abort(ScrnInfoPtr scrn, void *pageflip_data)
+{
+	struct amdgpu_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
+amdgpu_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 amdgpu_present_vblank_event *event;
+	xf86CrtcPtr xf86_crtc = crtc->devPrivate;
+	int crtc_id = xf86_crtc ? drmmode_get_crtc_id(xf86_crtc) : -1;
+	struct amdgpu_buffer *bo;
+	Bool ret;
+
+	if (!amdgpu_present_check_flip(crtc, screen->root, pixmap, sync_flip))
+		return FALSE;
+
+	bo = amdgpu_get_pixmap_bo(pixmap);
+	if (!bo)
+		return FALSE;
+
+	event = calloc(1, sizeof(struct amdgpu_present_vblank_event));
+	if (!event)
+		return FALSE;
+
+	event->event_id = event_id;
+
+	ret = amdgpu_do_pageflip(scrn, AMDGPU_DRM_QUEUE_CLIENT_DEFAULT, bo,
+				 event_id, event, crtc_id,
+				 amdgpu_present_flip_event,
+				 amdgpu_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
+amdgpu_present_unflip(ScreenPtr screen, uint64_t event_id)
+{
+	ScrnInfoPtr scrn = xf86ScreenToScrn(screen);
+	struct amdgpu_present_vblank_event *event;
+	PixmapPtr pixmap = screen->GetScreenPixmap(screen);
+	struct amdgpu_buffer *bo;
+	Bool ret;
+
+	if (!amdgpu_present_check_flip(NULL, screen->root, pixmap, TRUE))
+		return;
+
+	bo = amdgpu_get_pixmap_bo(pixmap);
+	if (!bo)
+		return;
+
+	event = calloc(1, sizeof(struct amdgpu_present_vblank_event));
+	if (!event)
+		return;
+
+	event->event_id = event_id;
+
+	ret = amdgpu_do_pageflip(scrn, AMDGPU_DRM_QUEUE_CLIENT_DEFAULT, bo,
+				 event_id, event, -1, amdgpu_present_flip_event,
+				 amdgpu_present_flip_abort);
+	if (!ret)
+		xf86DrvMsg(scrn->scrnIndex, X_ERROR, "present unflip failed\n");
+}
+
+static present_screen_info_rec amdgpu_present_screen_info = {
+	.version = 0,
+
+	.get_crtc = amdgpu_present_get_crtc,
+	.get_ust_msc = amdgpu_present_get_ust_msc,
+	.queue_vblank = amdgpu_present_queue_vblank,
+	.abort_vblank = amdgpu_present_abort_vblank,
+	.flush = amdgpu_present_flush,
+
+	.capabilities = PresentCapabilityNone,
+	.check_flip = amdgpu_present_check_flip,
+	.flip = amdgpu_present_flip,
+	.unflip = amdgpu_present_unflip,
+};
+
+static Bool
+amdgpu_present_has_async_flip(ScreenPtr screen)
+{
+#ifdef DRM_CAP_ASYNC_PAGE_FLIP
+	ScrnInfoPtr scrn = xf86ScreenToScrn(screen);
+	AMDGPUInfoPtr info = AMDGPUPTR(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
+amdgpu_present_screen_init(ScreenPtr screen)
+{
+	if (amdgpu_present_has_async_flip(screen))
+		amdgpu_present_screen_info.capabilities |= PresentCapabilityAsync;
+
+	if (!present_screen_init(screen, &amdgpu_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
+amdgpu_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 5b51f0e7e396ea946ef85429a8e9be5c1d5c39c3
Author: Michel Dänzer <michel.daenzer at amd.com>
Date:   Tue Jun 2 16:58:27 2015 +0900

    Add support for SYNC extension fences
    
    (Cherry picked from radeon commits 8fc9a241ab59ffbcdc178d6415332c88a54e85fe,
    af1862a37570fa512a525ab47d72b30400d2e2d6,
    aa7825eb29cdf6ac9d7b28ad18186807ff384687,
    af6076241c0d322b295a4e898407ae2472bd8eb4 and
    d64a13ebe0ecd241ee3260dbffd8f4a01e254183)
    
    Reviewed-by: Alex Deucher <alexander.deucher at amd.com>

diff --git a/configure.ac b/configure.ac
index ff0979e..2d6d4c7 100644
--- a/configure.ac
+++ b/configure.ac
@@ -156,6 +156,12 @@ AC_CHECK_DECL(GBM_BO_USE_LINEAR,
 	      [#include <stdlib.h>
 	       #include <gbm.h>])
 
+AC_CHECK_HEADERS([misyncshm.h], [], [],
+                 [#include <X11/Xdefs.h>
+	          #include <X11/Xfuncproto.h>
+	          #include <xorg-server.h>
+		  #include <screenint.h>])
+
 CPPFLAGS="$SAVE_CPPFLAGS"
 
 PKG_CHECK_MODULES([PCIACCESS], [pciaccess >= 0.8.0])
diff --git a/src/Makefile.am b/src/Makefile.am
index 8e91472..fa3be5c 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -29,7 +29,7 @@
 amdgpu_drv_la_LIBADD = $(PCIACCESS_LIBS) $(LIBDRM_AMDGPU_LIBS) $(GBM_LIBS)
 
 AMDGPU_KMS_SRCS=amdgpu_bo_helper.c amdgpu_dri2.c amdgpu_drm_queue.c amdgpu_kms.c \
-	drmmode_display.c
+	amdgpu_sync.c drmmode_display.c
 
 AM_CFLAGS = \
             @GBM_CFLAGS@ \
diff --git a/src/amdgpu_drv.h b/src/amdgpu_drv.h
index 4b87e6e..ad51c86 100644
--- a/src/amdgpu_drv.h
+++ b/src/amdgpu_drv.h
@@ -88,6 +88,8 @@
 #include "simple_list.h"
 #include "amdpciids.h"
 
+struct _SyncFence;
+
 #ifndef MAX
 #define MAX(a,b) ((a)>(b)?(a):(b))
 #endif
@@ -185,6 +187,9 @@ typedef struct {
 
 	void (*BlockHandler) (BLOCKHANDLER_ARGS_DECL);
 
+	void (*CreateFence) (ScreenPtr pScreen, struct _SyncFence *pFence,
+			     Bool initially_triggered);
+
 	int pix24bpp;		/* Depth of pixmap for 24bpp fb      */
 	Bool dac6bits;		/* Use 6 bit DAC?                    */
 
@@ -228,6 +233,10 @@ typedef struct {
 } AMDGPUInfoRec, *AMDGPUInfoPtr;
 
 
+/* amdgpu_sync.c */
+extern Bool amdgpu_sync_init(ScreenPtr screen);
+extern void amdgpu_sync_close(ScreenPtr screen);
+
 /* amdgpu_video.c */
 extern void AMDGPUInitVideo(ScreenPtr pScreen);
 extern void AMDGPUResetVideo(ScrnInfoPtr pScrn);
diff --git a/src/amdgpu_kms.c b/src/amdgpu_kms.c
index 71a4aa7..28d9305 100644
--- a/src/amdgpu_kms.c
+++ b/src/amdgpu_kms.c
@@ -703,6 +703,8 @@ static Bool AMDGPUCloseScreen_KMS(CLOSE_SCREEN_ARGS_DECL)
 
 	DeleteCallback(&FlushCallback, amdgpu_flush_callback, pScrn);
 
+	amdgpu_sync_close(pScreen);
+
 	drmDropMaster(info->dri2.drm_fd);
 
 	drmmode_fini(pScrn, &info->drmmode);
@@ -825,6 +827,8 @@ Bool AMDGPUScreenInit_KMS(SCREEN_INIT_ARGS_DECL)
 	}
 #endif
 
+	amdgpu_sync_init(pScreen);
+
 	pScrn->vtSema = TRUE;
 	xf86SetBackingStore(pScreen);
 
diff --git a/src/amdgpu_sync.c b/src/amdgpu_sync.c
new file mode 100644
index 0000000..baade0e
--- /dev/null
+++ b/src/amdgpu_sync.c
@@ -0,0 +1,147 @@
+/*
+ * 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 "amdgpu_drv.h"
+
+#ifdef HAVE_MISYNCSHM_H
+
+#include "misync.h"
+#include "misyncshm.h"
+#include "misyncstr.h"
+
+#include "amdgpu_glamor.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 amdgpu_sync_fence_private_key;
+
+typedef struct _amdgpu_sync_fence_private {
+        SyncFenceSetTriggeredFunc set_triggered;
+} amdgpu_sync_fence_private;
+
+#define SYNC_FENCE_PRIV(pFence)                                         \
+        (amdgpu_sync_fence_private *) dixLookupPrivate(&pFence->devPrivates, &amdgpu_sync_fence_private_key)
+
+static void
+amdgpu_sync_fence_set_triggered (SyncFence *fence)
+{
+	ScreenPtr screen = fence->pScreen;
+	amdgpu_sync_fence_private *private = SYNC_FENCE_PRIV(fence);
+
+	/* Flush pending rendering operations */
+	amdgpu_glamor_flush(xf86ScreenToScrn(screen));
+
+	fence->funcs.SetTriggered = private->set_triggered;
+	fence->funcs.SetTriggered(fence);
+	private->set_triggered = fence->funcs.SetTriggered;
+	fence->funcs.SetTriggered = amdgpu_sync_fence_set_triggered;
+}
+
+static void
+amdgpu_sync_create_fence(ScreenPtr screen,
+                        SyncFence *fence,
+                        Bool initially_triggered)
+{
+	ScrnInfoPtr scrn = xf86ScreenToScrn(screen);
+	AMDGPUInfoPtr info = AMDGPUPTR(scrn);
+	SyncScreenFuncsPtr screen_funcs = miSyncGetScreenFuncs(screen);
+	amdgpu_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 = amdgpu_sync_create_fence;
+
+	private->set_triggered = fence->funcs.SetTriggered;
+	fence->funcs.SetTriggered = amdgpu_sync_fence_set_triggered;
+}
+
+Bool
+amdgpu_sync_init(ScreenPtr screen)
+{
+	ScrnInfoPtr scrn = xf86ScreenToScrn(screen);
+	AMDGPUInfoPtr info = AMDGPUPTR(scrn);
+	SyncScreenFuncsPtr screen_funcs;
+
+	if (!miSyncShmScreenInit(screen)) {
+		xf86DrvMsg(scrn->scrnIndex, X_WARNING,
+			   "SYNC extension fences disabled because "
+			   "miSyncShmScreenInit failed\n");
+		return FALSE;
+	}
+
+	if (!dixPrivateKeyRegistered(&amdgpu_sync_fence_private_key)) {
+		if (!dixRegisterPrivateKey(&amdgpu_sync_fence_private_key,
+					   PRIVATE_SYNC_FENCE,
+					   sizeof (amdgpu_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 = amdgpu_sync_create_fence;
+	return TRUE;
+}
+
+void
+amdgpu_sync_close(ScreenPtr screen)
+{
+	ScrnInfoPtr scrn = xf86ScreenToScrn(screen);
+	AMDGPUInfoPtr info = AMDGPUPTR(scrn);
+	SyncScreenFuncsPtr screen_funcs = miSyncGetScreenFuncs(screen);
+
+	if (screen_funcs && info->CreateFence)
+		screen_funcs->CreateFence = info->CreateFence;
+
+	info->CreateFence = NULL;
+}
+
+#else /* !HAVE_MISYNCSHM_H */
+
+Bool
+amdgpu_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
+amdgpu_sync_close(ScreenPtr screen)
+{
+}
+
+#endif
commit a30060d22a42688371166a861e5050fdd5ce8f7b
Author: Michel Dänzer <michel.daenzer at amd.com>
Date:   Mon Jun 1 18:33:33 2015 +0900

    DRI2: Split out helper for getting UST and MSC of a specific CRTC
    
    (Cherry picked from radeon commits 76c2923ac5c7230a8b2f9f8329c308d28b44d9c0
    and d7c82731a8bf3d381bc571b94d80d9bb2dd6e40d)
    
    Reviewed-by: Alex Deucher <alexander.deucher at amd.com>

diff --git a/src/amdgpu_dri2.c b/src/amdgpu_dri2.c
index 95db216..28c56e7 100644
--- a/src/amdgpu_dri2.c
+++ b/src/amdgpu_dri2.c
@@ -851,17 +851,13 @@ CARD32 amdgpu_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 amdgpu_dri2_get_msc(DrawablePtr draw, CARD64 * ust, CARD64 * msc)
 {
-	ScreenPtr screen = draw->pScreen;
-	ScrnInfoPtr scrn = xf86ScreenToScrn(screen);
-	AMDGPUInfoPtr info = AMDGPUPTR(scrn);
-	drmVBlank vbl;
-	int ret;
 	xf86CrtcPtr crtc = amdgpu_dri2_drawable_crtc(draw, TRUE);
+	int ret;
 
 	/* Drawable not displayed, make up a value */
 	if (crtc == NULL) {
@@ -869,29 +865,20 @@ static int amdgpu_dri2_get_msc(DrawablePtr draw, CARD64 * ust, CARD64 * msc)
 		*msc = 0;
 		return TRUE;
 	}
+
 	if (amdgpu_crtc_is_enabled(crtc)) {
 		/* CRTC is running, read vblank counter and timestamp */
-		vbl.request.type = DRM_VBLANK_RELATIVE;
-		vbl.request.type |= amdgpu_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));
+		ret = drmmode_crtc_get_ust_msc(crtc, ust, msc);
+		if (ret != Success)
 			return FALSE;
-		}
 
-		*ust =
-		    ((CARD64) vbl.reply.tval_sec * 1000000) +
-		    vbl.reply.tval_usec;
-		*msc =
-		    vbl.reply.sequence + amdgpu_get_interpolated_vblanks(crtc);
+		*msc += amdgpu_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;
+		AMDGPUInfoPtr info = AMDGPUPTR(scrn);
 		CARD64 now, delta_t, delta_seq;
 
 		if (!drmmode_crtc->dpms_last_ust)
@@ -914,7 +901,8 @@ static int amdgpu_dri2_get_msc(DrawablePtr draw, CARD64 * ust, CARD64 * msc)
 		*msc += delta_seq;
 		*msc &= 0xffffffff;
 	}
-	return TRUE;
+
+	return ret == Success;
 }
 
 static
diff --git a/src/drmmode_display.c b/src/drmmode_display.c
index aa7c8c4..01fe860 100644
--- a/src/drmmode_display.c
+++ b/src/drmmode_display.c
@@ -204,6 +204,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;
+	AMDGPUInfoPtr info = AMDGPUPTR(scrn);
+	drmVBlank vbl;
+	int ret;
+
+	vbl.request.type = DRM_VBLANK_RELATIVE;
+	vbl.request.type |= amdgpu_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_crtc_dpms(xf86CrtcPtr crtc, int mode)
 {
 	drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
diff --git a/src/drmmode_display.h b/src/drmmode_display.h
index 9cf6932..90ab537 100644
--- a/src/drmmode_display.h
+++ b/src/drmmode_display.h
@@ -125,6 +125,7 @@ Bool amdgpu_do_pageflip(ScrnInfoPtr scrn, ClientPtr client,
 			struct amdgpu_buffer *new_front, uint64_t id, void *data,
 			int ref_crtc_hw_id, amdgpu_drm_handler_proc handler,
 			amdgpu_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
commit 9a554a683b970660b467566cf05b921393705a20
Author: Michel Dänzer <michel.daenzer at amd.com>
Date:   Mon Jun 1 17:32:56 2015 +0900

    DRI2: Use helper functions for DRM event queue management
    
    This is mostly in preparation for Present support, but it also simplifies
    the DRI2 specific code a little.
    
    (Cherry picked from radeon commit 6c3a721cde9317233072b573f9502348dcd21b16)
    
    Reviewed-by: Alex Deucher <alexander.deucher at amd.com>

diff --git a/src/amdgpu_dri2.c b/src/amdgpu_dri2.c
index c139dec..95db216 100644
--- a/src/amdgpu_dri2.c
+++ b/src/amdgpu_dri2.c
@@ -49,6 +49,8 @@
 
 #include "amdgpu_list.h"
 
+#include <xf86Priv.h>
+
 #if DRI2INFOREC_VERSION >= 9
 #define USE_DRI2_PRIME
 #endif
@@ -370,65 +372,20 @@ typedef struct _DRI2FrameEvent {
 	XID drawable_id;
 	ClientPtr client;
 	enum DRI2FrameEventType type;
-	int frame;
+	unsigned frame;
 	xf86CrtcPtr crtc;
+	OsTimerPtr timer;
+	struct amdgpu_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 amdgpu_dri2_ref_buffer(BufferPtr buffer)
 {
 	struct dri2_buffer_priv *private = buffer->driverPrivate;
@@ -448,30 +405,13 @@ static void
 amdgpu_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;
-				amdgpu_dri2_unref_buffer(ref->front);
-				amdgpu_dri2_unref_buffer(ref->back);
-			}
-		}
+		amdgpu_drm_abort_client(pClient);
 		break;
 	default:
 		break;
@@ -497,37 +437,42 @@ xf86CrtcPtr amdgpu_dri2_drawable_crtc(DrawablePtr pDraw, Bool consider_disabled)
 		return NULL;
 }
 
-void amdgpu_dri2_flip_event_handler(unsigned int frame, unsigned int tv_sec,
-				    unsigned int tv_usec, void *event_data)
+static void
+amdgpu_dri2_flip_event_abort(ScrnInfoPtr scrn, void *event_data)
+{
+	free(event_data);
+}
+
+static void
+amdgpu_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 += amdgpu_get_interpolated_vblanks(flip->crtc);
+	if (status != Success)
+		goto abort;
 
-	screen = drawable->pScreen;
-	scrn = xf86ScreenToScrn(screen);
+	if (!flip->crtc)
+		goto abort;
+	frame += amdgpu_get_interpolated_vblanks(flip->crtc);
 
+	screen = scrn->pScreen;
 	pixmap = screen->GetScreenPixmap(screen);
 	xf86DrvMsgVerb(scrn->scrnIndex, X_INFO, AMDGPU_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:
@@ -537,7 +482,7 @@ void amdgpu_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",
+				   "%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;
@@ -554,7 +499,8 @@ void amdgpu_dri2_flip_event_handler(unsigned int frame, unsigned int tv_sec,
 		break;
 	}
 
-	free(flip);
+abort:
+	amdgpu_dri2_flip_event_abort(scrn, event_data);
 }
 
 static Bool
@@ -589,7 +535,10 @@ amdgpu_dri2_schedule_flip(ScrnInfoPtr scrn, ClientPtr client,
 	back_priv = back->driverPrivate;
 	bo = amdgpu_get_pixmap_bo(back_priv->pixmap);
 
-	return amdgpu_do_pageflip(scrn, bo, flip_info, ref_crtc_hw_id);
+	return amdgpu_do_pageflip(scrn, client, bo, AMDGPU_DRM_QUEUE_ID_DEFAULT,
+				  flip_info, ref_crtc_hw_id,
+				  amdgpu_dri2_flip_event_handler,
+				  amdgpu_dri2_flip_event_abort);
 }
 
 static Bool update_front(DrawablePtr draw, DRI2BufferPtr front)
@@ -719,31 +668,36 @@ amdgpu_dri2_exchange_buffers(DrawablePtr draw, DRI2BufferPtr front,
 	DamageRegionProcessPending(&front_priv->pixmap->drawable);
 }
 
-void amdgpu_dri2_frame_event_handler(unsigned int frame, unsigned int tv_sec,
-				     unsigned int tv_usec, void *event_data)
+static void amdgpu_dri2_frame_event_abort(ScrnInfoPtr scrn, void *event_data)
+{
+	DRI2FrameEventPtr event = event_data;
+
+	TimerCancel(event->timer);
+	TimerFree(event->timer);
+	amdgpu_dri2_unref_buffer(event->front);
+	amdgpu_dri2_unref_buffer(event->back);
+	free(event);
+}
+
+static void amdgpu_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 += amdgpu_get_interpolated_vblanks(event->crtc);
 
-	screen = drawable->pScreen;
-	scrn = xf86ScreenToScrn(screen);
+	seq += amdgpu_get_interpolated_vblanks(event->crtc);
 
 	switch (event->type) {
 	case DRI2_FLIP:
@@ -778,14 +732,14 @@ void amdgpu_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,
+		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 */
@@ -795,12 +749,7 @@ void amdgpu_dri2_frame_event_handler(unsigned int frame, unsigned int tv_sec,
 	}
 
 cleanup:
-	if (event->valid) {
-		amdgpu_dri2_unref_buffer(event->front);
-		amdgpu_dri2_unref_buffer(event->back);
-		ListDelDRI2ClientEvents(event->client, &event->link);
-	}
-	free(event);
+	amdgpu_dri2_frame_event_abort(scrn, event_data);
 }
 
 drmVBlankSeqType amdgpu_populate_vbl_request_type(xf86CrtcPtr crtc)
@@ -972,17 +921,13 @@ static
 CARD32 amdgpu_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;
 	AMDGPUInfoPtr 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
@@ -993,29 +938,26 @@ CARD32 amdgpu_dri2_deferred_event(OsTimerPtr timer, CARD32 now, pointer data)
 	 */
 	if (!event_info->crtc) {
 		ErrorF("%s no crtc\n", __func__);
-		amdgpu_dri2_frame_event_handler(0, 0, 0, data);
+		if (event_info->drm_queue)
+			amdgpu_drm_abort_entry(event_info->drm_queue);
+		else
+			amdgpu_dri2_frame_event_abort(NULL, data);
 		return 0;
 	}
-	status =
-	    dixLookupDrawable(&drawable, event_info->drawable_id, serverClient,
-			      M_ANY, DixWriteAccess);
-	if (status != Success) {
-		ErrorF("%s cannot lookup drawable\n", __func__);
-		amdgpu_dri2_frame_event_handler(0, 0, 0, data);
-		return 0;
-	}
-	screen = drawable->pScreen;
-	scrn = xf86ScreenToScrn(screen);
+
+	scrn = crtc->scrn;
 	info = AMDGPUPTR(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__);
-		amdgpu_dri2_frame_event_handler(0, 0, 0, data);
+		if (event_info->drm_queue)
+			amdgpu_drm_queue_handler(info->dri2.drm_fd, 0, 0, 0,
+						 event_info->drm_queue);
+		else
+			amdgpu_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
@@ -1025,21 +967,22 @@ CARD32 amdgpu_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;
-	amdgpu_dri2_frame_event_handler((unsigned int)frame, tv_sec, tv_usec,
-					data);
+	if (event_info->drm_queue)
+		amdgpu_drm_queue_handler(info->dri2.drm_fd, frame, drm_now / 1000000,
+					 drm_now % 1000000, event_info->drm_queue);
+	else
+		amdgpu_dri2_frame_event_handler(scrn, frame, drm_now, data);
 	return 0;
 }
 
 static
-void amdgpu_dri2_schedule_event(CARD32 delay, pointer arg)
+void amdgpu_dri2_schedule_event(CARD32 delay, DRI2FrameEventPtr event_info)
 {
-	OsTimerPtr timer;
-
-	timer = TimerSet(NULL, 0, delay, amdgpu_dri2_deferred_event, arg);
+	event_info->timer = TimerSet(NULL, 0, delay, amdgpu_dri2_deferred_event,
+				     event_info);
 	if (delay == 0) {
 		CARD32 now = GetTimeInMillis();
-		amdgpu_dri2_deferred_event(timer, now, arg);
+		amdgpu_dri2_deferred_event(event_info->timer, now, event_info);
 	}
 }
 
@@ -1057,6 +1000,7 @@ static int amdgpu_dri2_schedule_wait_msc(ClientPtr client, DrawablePtr draw,
 	ScrnInfoPtr scrn = xf86ScreenToScrn(screen);
 	AMDGPUInfoPtr info = AMDGPUPTR(scrn);
 	DRI2FrameEventPtr wait_info = NULL;
+	struct amdgpu_drm_queue_entry *wait = NULL;
 	xf86CrtcPtr crtc = amdgpu_dri2_drawable_crtc(draw, TRUE);
 	drmVBlank vbl;
 	int ret;
@@ -1079,17 +1023,8 @@ static int amdgpu_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
@@ -1118,6 +1053,16 @@ static int amdgpu_dri2_schedule_wait_msc(ClientPtr client, DrawablePtr draw,
 	    vbl.reply.sequence + amdgpu_get_interpolated_vblanks(crtc);
 	current_msc &= 0xffffffff;
 
+	wait = amdgpu_drm_queue_alloc(scrn, client, AMDGPU_DRM_QUEUE_ID_DEFAULT,
+				      wait_info, amdgpu_dri2_frame_event_handler,
+				      amdgpu_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
@@ -1136,7 +1081,7 @@ static int amdgpu_dri2_schedule_wait_msc(ClientPtr client, DrawablePtr draw,
 		vbl.request.type |= amdgpu_populate_vbl_request_type(crtc);
 		vbl.request.sequence = target_msc;
 		vbl.request.sequence -= amdgpu_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,
@@ -1169,7 +1114,7 @@ static int amdgpu_dri2_schedule_wait_msc(ClientPtr client, DrawablePtr draw,
 		vbl.request.sequence += divisor;
 	vbl.request.sequence -= amdgpu_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,
@@ -1182,11 +1127,8 @@ static int amdgpu_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)
+		amdgpu_dri2_deferred_event(NULL, 0, wait_info);
 	return TRUE;
 }
 
@@ -1223,6 +1165,7 @@ static int amdgpu_dri2_schedule_swap(ClientPtr client, DrawablePtr draw,
 	drmVBlank vbl;
 	int ret, flip = 0;
 	DRI2FrameEventPtr swap_info = NULL;
+	struct amdgpu_drm_queue_entry *swap;
 	CARD64 current_msc;
 	BoxRec box;
 	RegionRec region;
@@ -1255,15 +1198,17 @@ static int amdgpu_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 = amdgpu_drm_queue_alloc(scrn, client, AMDGPU_DRM_QUEUE_ID_DEFAULT,
+				      swap_info, amdgpu_dri2_frame_event_handler,
+				      amdgpu_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
@@ -1331,7 +1276,7 @@ static int amdgpu_dri2_schedule_swap(ClientPtr client, DrawablePtr draw,
 
 		vbl.request.sequence = *target_msc;
 		vbl.request.sequence -= amdgpu_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,
@@ -1378,7 +1323,7 @@ static int amdgpu_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,
@@ -1472,26 +1417,6 @@ Bool amdgpu_dri2_screen_init(ScreenPtr pScreen)
 		driverNames[0] = driverNames[1] = dri2_info.driverName;
 
 		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,
 				    amdgpu_dri2_client_state_changed, 0);
 		}
diff --git a/src/amdgpu_dri2.h b/src/amdgpu_dri2.h
index 3ca9dd2..d9bec91 100644
--- a/src/amdgpu_dri2.h
+++ b/src/amdgpu_dri2.h
@@ -43,12 +43,6 @@ struct amdgpu_dri2 {
 Bool amdgpu_dri2_screen_init(ScreenPtr pScreen);
 void amdgpu_dri2_close_screen(ScreenPtr pScreen);
 
-int drmmode_get_crtc_id(xf86CrtcPtr crtc);
-void amdgpu_dri2_frame_event_handler(unsigned int frame, unsigned int tv_sec,
-				     unsigned int tv_usec, void *event_data);
-void amdgpu_dri2_flip_event_handler(unsigned int frame, unsigned int tv_sec,
-				    unsigned int tv_usec, void *event_data);
-
 #else
 
 static inline Bool amdgpu_dri2_screen_init(ScreenPtr pScreen)
@@ -60,37 +54,6 @@ static inline void amdgpu_dri2_close_screen(ScreenPtr pScreen)
 {
 }
 
-static inline void
-amdgpu_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
-amdgpu_dri2_frame_event_handler(unsigned int frame, unsigned int tv_sec,
-				unsigned int tv_usec, void *event_data)
-{
-	amdgpu_dri2_dummy_event_handler(frame, tv_sec, tv_usec, event_data,
-					__func__);
-}
-
-static inline void
-amdgpu_dri2_flip_event_handler(unsigned int frame, unsigned int tv_sec,
-			       unsigned int tv_usec, void *event_data)
-{
-	amdgpu_dri2_dummy_event_handler(frame, tv_sec, tv_usec, event_data,
-					__func__);
-}
-
 #endif
 
 #endif /* AMDGPU_DRI2_H */
diff --git a/src/drmmode_display.c b/src/drmmode_display.c
index bb93833..aa7c8c4 100644
--- a/src/drmmode_display.c
+++ b/src/drmmode_display.c
@@ -1391,46 +1391,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)
 {
-	amdgpu_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_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(int fd, unsigned int frame, unsigned int tv_sec,
-		     unsigned int tv_usec, void *event_data)
+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 */
-	amdgpu_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);
 }
 
 static void drm_wakeup_handler(pointer data, int err, pointer p)
@@ -1475,8 +1481,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 = amdgpu_drm_queue_handler;
+	drmmode->event_context.page_flip_handler = amdgpu_drm_queue_handler;
 
 	return TRUE;
 }
@@ -1743,8 +1749,10 @@ void drmmode_uevent_fini(ScrnInfoPtr scrn, drmmode_ptr drmmode)
 #endif
 }
 
-Bool amdgpu_do_pageflip(ScrnInfoPtr scrn, struct amdgpu_buffer *new_front,
-			void *data, int ref_crtc_hw_id)
+Bool amdgpu_do_pageflip(ScrnInfoPtr scrn, ClientPtr client,
+			struct amdgpu_buffer *new_front, uint64_t id, void *data,
+			int ref_crtc_hw_id, amdgpu_drm_handler_proc handler,
+			amdgpu_drm_abort_proc abort)
 {
 	AMDGPUInfoPtr info = AMDGPUPTR(scrn);
 	xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(scrn);
@@ -1754,7 +1762,8 @@ Bool amdgpu_do_pageflip(ScrnInfoPtr scrn, struct amdgpu_buffer *new_front,
 	int i, old_fb_id;
 	int height, emitted = 0;
 	drmmode_flipdata_ptr flipdata;
-	drmmode_flipevtcarrier_ptr flipcarrier;
+	drmmode_flipevtcarrier_ptr flipcarrier = NULL;
+	struct amdgpu_drm_queue_entry *drm_queue = 0;
 	union gbm_bo_handle bo_handle;
 	uint32_t handle;
 
@@ -1823,10 +1832,22 @@ Bool amdgpu_do_pageflip(ScrnInfoPtr scrn, struct amdgpu_buffer *new_front,
 		flipcarrier->dispatch_me =
 		    (drmmode_crtc->hw_id == ref_crtc_hw_id);
 		flipcarrier->flipdata = flipdata;
+		flipcarrier->handler = handler;
+		flipcarrier->abort = abort;
+
+		drm_queue = amdgpu_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)) {
+		if (drmModePageFlip(drmmode->fd, drmmode_crtc->mode_crtc->crtc_id,
+				    drmmode->fb_id, DRM_MODE_PAGE_FLIP_EVENT,
+				    drm_queue)) {
 			xf86DrvMsg(scrn->scrnIndex, X_WARNING,
 				   "flip queue failed: %s\n", strerror(errno));
 			free(flipcarrier);
@@ -1841,6 +1862,11 @@ Bool amdgpu_do_pageflip(ScrnInfoPtr scrn, struct amdgpu_buffer *new_front,
 	return TRUE;
 
 error_undo:
+	if (drm_queue)
+		amdgpu_drm_abort_entry(drm_queue);
+	else
+		drmmode_flip_abort(scrn, flipcarrier);
+
 	drmModeRmFB(drmmode->fd, drmmode->fb_id);
 	drmmode->fb_id = old_fb_id;
 
diff --git a/src/drmmode_display.h b/src/drmmode_display.h
index c2ec683..9cf6932 100644
--- a/src/drmmode_display.h
+++ b/src/drmmode_display.h
@@ -32,6 +32,7 @@
 #include "libudev.h"
 #endif
 
+#include "amdgpu_drm_queue.h"
 #include "amdgpu_probe.h"
 #include "amdgpu.h"
 
@@ -59,13 +60,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;
+	amdgpu_drm_handler_proc handler;
+	amdgpu_drm_abort_proc abort;
 } drmmode_flipevtcarrier_rec, *drmmode_flipevtcarrier_ptr;
 
 typedef struct {
@@ -117,9 +119,12 @@ 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_pitch_align(ScrnInfoPtr scrn, int bpe);
-Bool amdgpu_do_pageflip(ScrnInfoPtr scrn, struct amdgpu_buffer *new_front,
-			void *data, int ref_crtc_hw_id);
+Bool amdgpu_do_pageflip(ScrnInfoPtr scrn, ClientPtr client,
+			struct amdgpu_buffer *new_front, uint64_t id, void *data,
+			int ref_crtc_hw_id, amdgpu_drm_handler_proc handler,
+			amdgpu_drm_abort_proc abort);
 int drmmode_get_current_ust(int drm_fd, CARD64 * ust);
 
 #endif
commit e6164ad340f65ff8ee6f6a6934302591af875a43
Author: Michel Dänzer <michel.daenzer at amd.com>
Date:   Mon Jun 1 17:29:30 2015 +0900

    DRI2: Move amdgpu_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.
    
    (Cherry picked from radeon commit c3fa22a479e61d1899fa9d327d9c4e2a7f64b0c1)
    
    Reviewed-by: Alex Deucher <alexander.deucher at amd.com>

diff --git a/src/amdgpu_dri2.c b/src/amdgpu_dri2.c
index fd98fa7..c139dec 100644
--- a/src/amdgpu_dri2.c
+++ b/src/amdgpu_dri2.c
@@ -497,6 +497,66 @@ xf86CrtcPtr amdgpu_dri2_drawable_crtc(DrawablePtr pDraw, Bool consider_disabled)
 		return NULL;
 }
 
+void amdgpu_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 += amdgpu_get_interpolated_vblanks(flip->crtc);
+
+	screen = drawable->pScreen;
+	scrn = xf86ScreenToScrn(screen);
+
+	pixmap = screen->GetScreenPixmap(screen);
+	xf86DrvMsgVerb(scrn->scrnIndex, X_INFO, AMDGPU_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
 amdgpu_dri2_schedule_flip(ScrnInfoPtr scrn, ClientPtr client,
 			  DrawablePtr draw, DRI2BufferPtr front,
@@ -1130,66 +1190,6 @@ out_complete:
 	return TRUE;
 }
 
-void amdgpu_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 += amdgpu_get_interpolated_vblanks(flip->crtc);
-
-	screen = drawable->pScreen;
-	scrn = xf86ScreenToScrn(screen);
-
-	pixmap = screen->GetScreenPixmap(screen);
-	xf86DrvMsgVerb(scrn->scrnIndex, X_INFO, AMDGPU_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 5419e13da7ec3cffd43510ac88106076ea81124c
Author: Michel Dänzer <michel.daenzer at amd.com>
Date:   Mon Jun 1 17:25:23 2015 +0900

    DRI2: Remove superfluous assignments to *_info->frame
    
    That field is only used for page flipping.
    
    (Cherry picked from radeon commit 65045112fdc8a9fa36e0e00f46739a6152b775ff)
    
    Reviewed-by: Alex Deucher <alexander.deucher at amd.com>

diff --git a/src/amdgpu_dri2.c b/src/amdgpu_dri2.c
index 895abcd..fd98fa7 100644
--- a/src/amdgpu_dri2.c
+++ b/src/amdgpu_dri2.c
@@ -1038,7 +1038,6 @@ static int amdgpu_dri2_schedule_wait_msc(ClientPtr client, DrawablePtr draw,
 		CARD32 delay;
 		delay = amdgpu_dri2_extrapolate_msc_delay(crtc, &target_msc,
 							  divisor, remainder);
-		wait_info->frame = target_msc;
 		amdgpu_dri2_schedule_event(delay, wait_info);
 		DRI2BlockClient(client, draw);
 		return TRUE;
@@ -1086,8 +1085,6 @@ static int amdgpu_dri2_schedule_wait_msc(ClientPtr client, DrawablePtr draw,
 			goto out_complete;
 		}
 
-		wait_info->frame = vbl.reply.sequence;
-		wait_info->frame += amdgpu_get_interpolated_vblanks(crtc);
 		DRI2BlockClient(client, draw);
 		return TRUE;
 	}
@@ -1120,8 +1117,6 @@ static int amdgpu_dri2_schedule_wait_msc(ClientPtr client, DrawablePtr draw,
 		goto out_complete;
 	}
 
-	wait_info->frame = vbl.reply.sequence;
-	wait_info->frame += amdgpu_get_interpolated_vblanks(crtc);
 	DRI2BlockClient(client, draw);
 
 	return TRUE;
@@ -1279,7 +1274,6 @@ static int amdgpu_dri2_schedule_swap(ClientPtr client, DrawablePtr draw,
 		CARD32 delay;
 		delay = amdgpu_dri2_extrapolate_msc_delay(crtc, target_msc,
 							  divisor, remainder);
-		swap_info->frame = *target_msc;
 		amdgpu_dri2_schedule_event(delay, swap_info);
 		return TRUE;
 	}
commit f4c2b640be17ab1f8694b35d4cb74ccfce3d1385
Author: Michel Dänzer <michel.daenzer at amd.com>
Date:   Mon Jun 1 17:11:30 2015 +0900

    DRI2: Simplify blit fallback handling for scheduled swaps
    
    Also use amdgpu_dri2_schedule_event when possible.
    
    (Cherry picked from radeon commit ad27f16f308079d06a2b1c788b3cb0947531253a)
    
    Reviewed-by: Alex Deucher <alexander.deucher at amd.com>

diff --git a/src/amdgpu_dri2.c b/src/amdgpu_dri2.c
index f05b742..895abcd 100644
--- a/src/amdgpu_dri2.c
+++ b/src/amdgpu_dri2.c
@@ -1228,7 +1228,6 @@ static int amdgpu_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;
@@ -1254,6 +1253,7 @@ static int amdgpu_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;
@@ -1293,9 +1293,7 @@ static int amdgpu_dri2_schedule_swap(ClientPtr client, DrawablePtr draw,
 		xf86DrvMsg(scrn->scrnIndex, X_WARNING,
 			   "first get vblank counter failed: %s\n",
 			   strerror(errno));
-		*target_msc = 0;
-		amdgpu_dri2_schedule_event(FALLBACK_SWAP_DELAY, swap_info);
-		return TRUE;
+		goto blit_fallback;
 	}
 
 	current_msc =
@@ -1304,13 +1302,11 @@ static int amdgpu_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.
 	 */
@@ -1347,10 +1343,7 @@ static int amdgpu_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;
-			amdgpu_dri2_schedule_event(FALLBACK_SWAP_DELAY,
-						   swap_info);
-			return TRUE;
+			goto blit_fallback;
 		}
 
 		*target_msc = vbl.reply.sequence + flip;
@@ -1397,9 +1390,7 @@ static int amdgpu_dri2_schedule_swap(ClientPtr client, DrawablePtr draw,
 		xf86DrvMsg(scrn->scrnIndex, X_WARNING,
 			   "final get vblank counter failed: %s\n",
 			   strerror(errno));
-		*target_msc = 0;
-		amdgpu_dri2_schedule_event(FALLBACK_SWAP_DELAY, swap_info);
-		return TRUE;
+		goto blit_fallback;
 	}
 
 	/* Adjust returned value for 1 fame pageflip offset of flip > 0 */
@@ -1410,22 +1401,23 @@ static int amdgpu_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;
+		amdgpu_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);
 
-	amdgpu_dri2_copy_region(draw, &region, front, back);
+		amdgpu_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);
 
-	amdgpu_dri2_unref_buffer(front);
-	amdgpu_dri2_unref_buffer(back);
+		amdgpu_dri2_unref_buffer(front);
+		amdgpu_dri2_unref_buffer(back);
+	}
 
 	*target_msc = 0;	/* offscreen, so zero out target vblank count */
 	return TRUE;
commit 13a7284e061081a12180b375d66f9b8394cf8753
Author: Michel Dänzer <michel.daenzer at amd.com>
Date:   Mon Jun 1 16:58:00 2015 +0900

    Add DRM event queue helpers
    
    (Cherry picked from radeon commit b4af8a327ed8420f0ff4ea0f113f4a59406ed4d3)
    
    Reviewed-by: Alex Deucher <alexander.deucher at amd.com>

diff --git a/src/Makefile.am b/src/Makefile.am
index 3fe1cd0..8e91472 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -28,7 +28,8 @@
 
 amdgpu_drv_la_LIBADD = $(PCIACCESS_LIBS) $(LIBDRM_AMDGPU_LIBS) $(GBM_LIBS)
 
-AMDGPU_KMS_SRCS=amdgpu_dri2.c amdgpu_kms.c drmmode_display.c amdgpu_bo_helper.c
+AMDGPU_KMS_SRCS=amdgpu_bo_helper.c amdgpu_dri2.c amdgpu_drm_queue.c amdgpu_kms.c \
+	drmmode_display.c
 
 AM_CFLAGS = \
             @GBM_CFLAGS@ \
@@ -57,6 +58,7 @@ amdgpu_drv_la_SOURCES += \
 EXTRA_DIST = \
 	compat-api.h \
 	amdgpu_bo_helper.h \
+	amdgpu_drm_queue.h \
 	amdgpu_glamor.h \
 	amdgpu_drv.h \
 	amdgpu_list.h \
diff --git a/src/amdgpu_drm_queue.c b/src/amdgpu_drm_queue.c
new file mode 100644
index 0000000..9bec658
--- /dev/null
+++ b/src/amdgpu_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 "amdgpu_drv.h"
+#include "amdgpu_drm_queue.h"
+#include "amdgpu_list.h"
+
+
+struct amdgpu_drm_queue_entry {
+	struct xorg_list list;
+	uint64_t id;
+	void *data;
+	ClientPtr client;
+	ScrnInfoPtr scrn;
+	amdgpu_drm_handler_proc handler;
+	amdgpu_drm_abort_proc abort;
+};
+
+static int amdgpu_drm_queue_refcnt;
+static struct xorg_list amdgpu_drm_queue;
+
+
+/*
+ * Handle a DRM event
+ */
+void
+amdgpu_drm_queue_handler(int fd, unsigned int frame, unsigned int sec,
+			 unsigned int usec, void *user_ptr)
+{
+	struct amdgpu_drm_queue_entry *user_data = user_ptr;
+	struct amdgpu_drm_queue_entry *e, *tmp;
+
+	xorg_list_for_each_entry_safe(e, tmp, &amdgpu_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 amdgpu_drm_queue_entry *
+amdgpu_drm_queue_alloc(ScrnInfoPtr scrn, ClientPtr client,
+		       uint64_t id, void *data,
+		       amdgpu_drm_handler_proc handler,
+		       amdgpu_drm_abort_proc abort)
+{
+	struct amdgpu_drm_queue_entry *e;
+
+	e = calloc(1, sizeof(struct amdgpu_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, &amdgpu_drm_queue);
+
+	return e;
+}
+
+/*
+ * Abort one queued DRM entry, removing it
+ * from the list, calling the abort function and
+ * freeing the memory
+ */
+static void
+amdgpu_drm_abort_one(struct amdgpu_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
+amdgpu_drm_abort_client(ClientPtr client)
+{
+	struct amdgpu_drm_queue_entry *e, *tmp;
+
+	xorg_list_for_each_entry_safe(e, tmp, &amdgpu_drm_queue, list) {
+		if (e->client == client)
+			amdgpu_drm_abort_one(e);
+	}
+}
+
+/*
+ * Abort specific drm queue entry
+ */
+void
+amdgpu_drm_abort_entry(struct amdgpu_drm_queue_entry *entry)
+{
+	amdgpu_drm_abort_one(entry);
+}
+
+/*
+ * Abort specific drm queue entry by ID
+ */
+void
+amdgpu_drm_abort_id(uint64_t id)
+{
+	struct amdgpu_drm_queue_entry *e, *tmp;
+
+	xorg_list_for_each_entry_safe(e, tmp, &amdgpu_drm_queue, list) {
+		if (e->id == id) {
+			amdgpu_drm_abort_one(e);
+			break;
+		}
+	}
+}
+
+/*
+ * Initialize the DRM event queue
+ */
+void
+amdgpu_drm_queue_init()
+{
+	if (amdgpu_drm_queue_refcnt++)
+		return;
+
+	xorg_list_init(&amdgpu_drm_queue);
+}
+
+/*
+ * Deinitialize the DRM event queue
+ */
+void
+amdgpu_drm_queue_close(ScrnInfoPtr scrn)
+{
+	struct amdgpu_drm_queue_entry *e, *tmp;
+
+	xorg_list_for_each_entry_safe(e, tmp, &amdgpu_drm_queue, list) {
+		if (e->scrn == scrn)
+			amdgpu_drm_abort_one(e);
+	}
+
+	amdgpu_drm_queue_refcnt--;
+}
diff --git a/src/amdgpu_drm_queue.h b/src/amdgpu_drm_queue.h
new file mode 100644
index 0000000..96841f6
--- /dev/null
+++ b/src/amdgpu_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 _AMDGPU_DRM_QUEUE_H_
+#define _AMDGPU_DRM_QUEUE_H_
+
+#define AMDGPU_DRM_QUEUE_CLIENT_DEFAULT serverClient
+#define AMDGPU_DRM_QUEUE_ID_DEFAULT ~0ULL
+
+struct amdgpu_drm_queue_entry;
+
+typedef void (*amdgpu_drm_handler_proc)(ScrnInfoPtr scrn, uint32_t seq,
+					uint64_t usec, void *data);
+typedef void (*amdgpu_drm_abort_proc)(ScrnInfoPtr scrn, void *data);
+
+void amdgpu_drm_queue_handler(int fd, unsigned int frame,
+			      unsigned int tv_sec, unsigned int tv_usec,
+			      void *user_ptr);
+struct amdgpu_drm_queue_entry *amdgpu_drm_queue_alloc(ScrnInfoPtr scrn,
+						      ClientPtr client,
+						      uint64_t id,
+						      void *data,
+						      amdgpu_drm_handler_proc handler,
+						      amdgpu_drm_abort_proc abort);
+void amdgpu_drm_abort_client(ClientPtr client);
+void amdgpu_drm_abort_entry(struct amdgpu_drm_queue_entry *entry);
+void amdgpu_drm_abort_id(uint64_t id);
+void amdgpu_drm_queue_init();
+void amdgpu_drm_queue_close(ScrnInfoPtr scrn);
+
+#endif /* _AMDGPU_DRM_QUEUE_H_ */
diff --git a/src/amdgpu_kms.c b/src/amdgpu_kms.c
index 16a7449..71a4aa7 100644
--- a/src/amdgpu_kms.c
+++ b/src/amdgpu_kms.c
@@ -32,6 +32,7 @@
 #include <sys/ioctl.h>
 /* Driver data structures */
 #include "amdgpu_drv.h"
+#include "amdgpu_drm_queue.h"
 #include "amdgpu_glamor.h"
 #include "amdgpu_probe.h"
 #include "micmap.h"
@@ -529,6 +530,8 @@ Bool AMDGPUPreInit_KMS(ScrnInfoPtr pScrn, int flags)
 	if (!AMDGPUPreInitAccel_KMS(pScrn))
 		goto fail;
 
+	amdgpu_drm_queue_init();
+
 	AMDGPUSetupCapabilities(pScrn);
 
 	/* don't enable tiling if accel is not enabled */
@@ -696,6 +699,7 @@ static Bool AMDGPUCloseScreen_KMS(CLOSE_SCREEN_ARGS_DECL)
 		       "AMDGPUCloseScreen\n");
 
 	drmmode_uevent_fini(pScrn, &info->drmmode);
+	amdgpu_drm_queue_close(pScrn);
 
 	DeleteCallback(&FlushCallback, amdgpu_flush_callback, pScrn);
 
commit eb7c6958dff5cb8b0aad02d1d5673483dae4e3d4
Author: Michel Dänzer <michel.daenzer at amd.com>
Date:   Mon Jun 1 16:52:40 2015 +0900

    Move xorg_list backwards compatibility to new amdgpu_list.h header
    
    (Cherry picked from radeon commits 7c3470f4b659206ed23f761948936ede3a2dba3d
    and 4a98f60117c387a228d5cbaadb6e298fb4e865df)
    
    Reviewed-by: Alex Deucher <alexander.deucher at amd.com>

diff --git a/src/Makefile.am b/src/Makefile.am
index 8715eb3..3fe1cd0 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -59,6 +59,7 @@ EXTRA_DIST = \
 	amdgpu_bo_helper.h \
 	amdgpu_glamor.h \
 	amdgpu_drv.h \
+	amdgpu_list.h \
 	amdgpu_probe.h \
 	amdgpu_version.h \
 	amdgpu_video.h \
diff --git a/src/amdgpu_dri2.c b/src/amdgpu_dri2.c
index 32f6171..f05b742 100644
--- a/src/amdgpu_dri2.c
+++ b/src/amdgpu_dri2.c
@@ -47,14 +47,7 @@
 
 #include "amdgpu_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 "amdgpu_list.h"
 
 #if DRI2INFOREC_VERSION >= 9
 #define USE_DRI2_PRIME
diff --git a/src/amdgpu_list.h b/src/amdgpu_list.h
new file mode 100644
index 0000000..c1e3516
--- /dev/null
+++ b/src/amdgpu_list.h
@@ -0,0 +1,39 @@
+/*
+ * 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 _AMDGPU_LIST_H_
+#define _AMDGPU_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
+#define xorg_list_for_each_entry_safe	list_for_each_entry_safe
+#endif
+
+#endif /* _AMDGPU_LIST_H_ */
commit 69d161a54b4ea0d8033a0873210f2857c91ceae8
Author: Michel Dänzer <michel.daenzer at amd.com>
Date:   Mon Jun 1 16:46:30 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.
    
    (Cherry picked from radeon commit 7388d0b6c54b9d536fdb161e3aa61b326627b939)
    
    Reviewed-by: Alex Deucher <alexander.deucher at amd.com>

diff --git a/configure.ac b/configure.ac
index b26eebb..ff0979e 100644
--- a/configure.ac
+++ b/configure.ac
@@ -76,7 +76,7 @@ PKG_CHECK_MODULES(LIBDRM_AMDGPU, [libdrm_amdgpu])
 PKG_CHECK_MODULES(GBM, [gbm])
 
 # 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")
@@ -145,18 +145,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"])
 
 AC_CHECK_DECL(GBM_BO_USE_LINEAR,
 	      [AC_DEFINE(HAVE_GBM_BO_USE_LINEAR, 1, [Have GBM_BO_USE_LINEAR])], [],
diff --git a/src/amdgpu_dri2.c b/src/amdgpu_dri2.c
index 15bb497..32f6171 100644
--- a/src/amdgpu_dri2.c
+++ b/src/amdgpu_dri2.c
@@ -47,7 +47,6 @@
 
 #include "amdgpu_version.h"
 
-#if HAVE_LIST_H
 #include "list.h"
 #if !HAVE_XORG_LIST
 #define xorg_list			list
@@ -56,11 +55,6 @@
 #define xorg_list_del			list_del
 #define xorg_list_for_each_entry	list_for_each_entry
 #endif
-#endif
-
-#if DRI2INFOREC_VERSION >= 4 && HAVE_LIST_H
-#define USE_DRI2_SCHEDULING
-#endif
 
 #if DRI2INFOREC_VERSION >= 9
 #define USE_DRI2_PRIME
@@ -373,8 +367,6 @@ amdgpu_dri2_copy_region(DrawablePtr pDraw, RegionPtr pRegion,
 					pDstBuffer, pSrcBuffer);
 }
 
-#ifdef USE_DRI2_SCHEDULING
-
 enum DRI2FrameEventType {
 	DRI2_SWAP,
 	DRI2_FLIP,
@@ -1446,17 +1438,13 @@ blit_fallback:
 	return TRUE;
 }
 
-#endif /* USE_DRI2_SCHEDULING */
-
 Bool amdgpu_dri2_screen_init(ScreenPtr pScreen)
 {
 	ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
 	AMDGPUInfoPtr info = AMDGPUPTR(pScrn);
 	DRI2InfoRec dri2_info = { 0 };
-#ifdef USE_DRI2_SCHEDULING
 	const char *driverNames[2];
 	Bool scheduling_works = TRUE;
-#endif
 
 	if (!info->dri2.available)
 		return FALSE;
@@ -1471,7 +1459,6 @@ Bool amdgpu_dri2_screen_init(ScreenPtr pScreen)
 	dri2_info.DestroyBuffer = amdgpu_dri2_destroy_buffer;
 	dri2_info.CopyRegion = amdgpu_dri2_copy_region;
 
-#ifdef USE_DRI2_SCHEDULING
 	if (info->drmmode.mode_res->count_crtcs > 2) {
 #ifdef DRM_CAP_VBLANK_HIGH_CRTC
 		uint64_t cap_value;
@@ -1532,7 +1519,6 @@ Bool amdgpu_dri2_screen_init(ScreenPtr pScreen)
 
 		DRI2InfoCnt++;
 	}
-#endif
 
 #if DRI2INFOREC_VERSION >= 9
 	dri2_info.version = 9;
@@ -1550,11 +1536,9 @@ void amdgpu_dri2_close_screen(ScreenPtr pScreen)
 	ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
 	AMDGPUInfoPtr info = AMDGPUPTR(pScrn);
 
-#ifdef USE_DRI2_SCHEDULING
 	if (--DRI2InfoCnt == 0)
 		DeleteCallback(&ClientStateCallback,
 			       amdgpu_dri2_client_state_changed, 0);
-#endif
 
 	DRI2CloseScreen(pScreen);
 	drmFree(info->dri2.device_name);


More information about the xorg-commit mailing list