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

Michel Dänzer daenzer at kemper.freedesktop.org
Tue Jul 10 15:24:17 UTC 2018


 configure.ac                        |   10 
 src/Makefile.am                     |    4 
 src/drmmode_display.c               |  252 ++++++----------------
 src/drmmode_display.h               |    2 
 src/evergreen_exa.c                 |   41 +--
 src/evergreen_state.h               |    2 
 src/evergreen_textured_videofuncs.c |    2 
 src/r600_exa.c                      |   41 +--
 src/r600_state.h                    |    2 
 src/r600_textured_videofuncs.c      |    2 
 src/radeon.h                        |   61 ++---
 src/radeon_bo_helper.c              |  404 +++++++++++++++++++++++-------------
 src/radeon_bo_helper.h              |   55 ++++
 src/radeon_dri2.c                   |   49 +---
 src/radeon_dri3.c                   |   15 -
 src/radeon_exa.c                    |   46 ----
 src/radeon_exa_funcs.c              |   44 ++-
 src/radeon_exa_shared.c             |    2 
 src/radeon_exa_shared.h             |    3 
 src/radeon_glamor.c                 |   57 +++--
 src/radeon_glamor.h                 |   28 ++
 src/radeon_glamor_wrappers.c        |   27 +-
 src/radeon_kms.c                    |  202 +++++++-----------
 src/radeon_present.c                |    4 
 src/radeon_textured_videofuncs.c    |   24 +-
 25 files changed, 705 insertions(+), 674 deletions(-)

New commits:
commit 3c4c0213c11d623cba7adbc28dde652694f2f758
Author: Michel Dänzer <michel.daenzer at amd.com>
Date:   Fri Jun 29 17:57:03 2018 +0200

    glamor: Use GBM for BO allocation when possible
    
    Inspired by amdgpu. This avoids various issues due to a GEM handle
    lifetime conflict between us and Mesa with current glamor.
    
    Bugzilla: https://bugs.freedesktop.org/105381
    Tested-by: Konstantin Kharlamov <hi-angel at yandex.ru>
    Reviewed-by: Alex Deucher <alexander.deucher at amd.com>

diff --git a/configure.ac b/configure.ac
index 11efdf0a..f5614749 100644
--- a/configure.ac
+++ b/configure.ac
@@ -138,12 +138,22 @@ if test "x$GLAMOR" != "xno"; then
 					 [Have glamor_egl_destroy_textured_pixmap API])], [],
 			      [#include "xorg-server.h"
 			       #include "glamor.h"])
+
+		AC_CHECK_DECL(glamor_finish,
+			      [AC_DEFINE(HAVE_GLAMOR_FINISH, 1,
+					 [Have glamor_finish API])],
+					 [PKG_CHECK_MODULES(LIBGL, [gl])],
+			      [#include "xorg-server.h"
+			       #include "glamor.h"])
 	fi
 
 	if test "x$GLAMOR_XSERVER" != xyes; then
 		PKG_CHECK_MODULES(LIBGLAMOR, [glamor >= 0.6.0])
 		PKG_CHECK_MODULES(LIBGLAMOR_EGL, [glamor-egl])
 	fi
+
+	PKG_CHECK_MODULES(GBM, [gbm >= 10.6])
+
 	AC_DEFINE(USE_GLAMOR, 1, [Enable glamor acceleration])
 else
 	AC_MSG_RESULT([$GLAMOR])
diff --git a/src/Makefile.am b/src/Makefile.am
index ed1bfa9e..df4a95e4 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -62,8 +62,8 @@ radeon_drv_la_SOURCES = \
 	$(RADEON_KMS_SRCS)
 
 if GLAMOR
-AM_CFLAGS += @LIBGLAMOR_CFLAGS@
-radeon_drv_la_LIBADD += @LIBGLAMOR_LIBS@
+AM_CFLAGS += @LIBGLAMOR_CFLAGS@ @GBM_CFLAGS@
+radeon_drv_la_LIBADD += @LIBGLAMOR_LIBS@ @GBM_LIBS@
 radeon_drv_la_SOURCES += \
 	 radeon_glamor_wrappers.c \
 	 radeon_glamor.c
diff --git a/src/drmmode_display.c b/src/drmmode_display.c
index c91f5bb2..2773ce67 100644
--- a/src/drmmode_display.c
+++ b/src/drmmode_display.c
@@ -142,8 +142,7 @@ static PixmapPtr drmmode_create_bo_pixmap(ScrnInfoPtr pScrn,
 	}
 
 	if (!info->use_glamor ||
-	    radeon_glamor_create_textured_pixmap(pixmap,
-						 radeon_get_pixmap_private(pixmap)))
+	    radeon_glamor_create_textured_pixmap(pixmap, bo))
 		return pixmap;
 
 fail:
@@ -435,8 +434,14 @@ destroy_pixmap_for_fbcon(ScrnInfoPtr pScrn)
 	/* XXX: The current GPUVM support in the kernel doesn't allow removing
 	 * the virtual address range for this BO, so we need to keep around
 	 * the pixmap to avoid breaking glamor with GPUVM
+	 *
+	 * Similarly, need to keep around the pixmap with current glamor, to
+	 * avoid issues due to a GEM handle lifetime conflict between us and
+	 * Mesa
 	 */
-	if (info->use_glamor && info->ChipFamily >= CHIP_FAMILY_CAYMAN)
+	if (info->use_glamor &&
+	    (info->ChipFamily >= CHIP_FAMILY_CAYMAN ||
+	     xorgGetVersion() >= XORG_VERSION_NUMERIC(1,19,99,1,0)))
 		return;
 
 	if (info->fbcon_pixmap)
@@ -2277,21 +2282,23 @@ drmmode_xf86crtc_resize (ScrnInfoPtr scrn, int width, int height)
 
 	scrn->displayWidth = pitch / cpp;
 
+	if (!info->use_glamor) {
 #if X_BYTE_ORDER == X_BIG_ENDIAN
-	switch (cpp) {
-	case 4:
-	    tiling_flags |= RADEON_TILING_SWAP_32BIT;
-	    break;
-	case 2:
-	    tiling_flags |= RADEON_TILING_SWAP_16BIT;
-	    break;
-	}
-	if (info->ChipFamily < CHIP_FAMILY_R600 &&
-	    info->r600_shadow_fb && tiling_flags)
-	    tiling_flags |= RADEON_TILING_SURFACE;
+		switch (cpp) {
+		case 4:
+			tiling_flags |= RADEON_TILING_SWAP_32BIT;
+			break;
+		case 2:
+			tiling_flags |= RADEON_TILING_SWAP_16BIT;
+			break;
+		}
+		if (info->ChipFamily < CHIP_FAMILY_R600 &&
+		    info->r600_shadow_fb && tiling_flags)
+			tiling_flags |= RADEON_TILING_SURFACE;
 #endif
-	if (tiling_flags)
-	    radeon_bo_set_tiling(info->front_buffer->bo.radeon, tiling_flags, pitch);
+		if (tiling_flags)
+			radeon_bo_set_tiling(info->front_buffer->bo.radeon, tiling_flags, pitch);
+	}
 
 	if (!info->r600_shadow_fb) {
 		if (info->surf_man && !info->use_glamor)
diff --git a/src/radeon.h b/src/radeon.h
index 648fd98a..2bcfa41b 100644
--- a/src/radeon.h
+++ b/src/radeon.h
@@ -606,6 +606,8 @@ typedef struct {
     unsigned hwcursor_disabled;
 
 #ifdef USE_GLAMOR
+    struct gbm_device *gbm;
+
     struct {
 	CreateGCProcPtr SavedCreateGC;
 	RegionPtr (*SavedCopyArea)(DrawablePtr, DrawablePtr, GCPtr, int, int,
@@ -744,8 +746,6 @@ static inline Bool radeon_set_pixmap_bo(PixmapPtr pPix, struct radeon_buffer *bo
 	}
 
 	if (bo) {
-	    uint32_t pitch;
-
 	    if (!priv) {
 		priv = calloc(1, sizeof (struct radeon_pixmap));
 		if (!priv)
@@ -754,11 +754,10 @@ static inline Bool radeon_set_pixmap_bo(PixmapPtr pPix, struct radeon_buffer *bo
 
 	    radeon_buffer_ref(bo);
 	    priv->bo = bo;
-
-	    radeon_bo_get_tiling(bo->bo.radeon, &priv->tiling_flags, &pitch);
 	}
 
 	radeon_set_pixmap_private(pPix, priv);
+	radeon_get_pixmap_tiling_flags(pPix);
 	return TRUE;
     } else
 #endif /* USE_GLAMOR */
diff --git a/src/radeon_bo_helper.c b/src/radeon_bo_helper.c
index 2b836bbf..79e8ff1b 100644
--- a/src/radeon_bo_helper.c
+++ b/src/radeon_bo_helper.c
@@ -28,6 +28,37 @@
 #include "radeon_glamor.h"
 #include "radeon_bo_gem.h"
 
+
+#ifdef USE_GLAMOR
+
+static uint32_t
+radeon_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 30:
+	return GBM_FORMAT_XRGB2101010;
+    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;
+    }
+}
+
+#endif /* USE_GLAMOR */
+
+
 static const unsigned MicroBlockTable[5][3][2] = {
     /*linear  tiled   square-tiled */
     {{32, 1}, {8, 4}, {0, 0}}, /*   8 bits per pixel */
@@ -158,6 +189,46 @@ radeon_alloc_pixmap_bo(ScrnInfoPtr pScrn, int width, int height, int depth,
     struct radeon_surface surface;
     struct radeon_buffer *bo;
     int domain = RADEON_GEM_DOMAIN_VRAM;
+
+#ifdef USE_GLAMOR
+    if (info->use_glamor &&
+	!(usage_hint == CREATE_PIXMAP_USAGE_BACKING_PIXMAP &&
+	  info->shadow_primary)) {
+	uint32_t bo_use = GBM_BO_USE_RENDERING;
+	uint32_t gbm_format = radeon_get_gbm_format(depth, bitsPerPixel);
+
+	if (gbm_format == ~0U)
+	    return NULL;
+
+	bo = calloc(1, sizeof(struct radeon_buffer));
+	if (!bo)
+	    return NULL;
+
+	bo->ref_count = 1;
+
+	if (bitsPerPixel == pScrn->bitsPerPixel)
+	    bo_use |= GBM_BO_USE_SCANOUT;
+
+	if ((usage_hint == CREATE_PIXMAP_USAGE_BACKING_PIXMAP &&
+	     info->shadow_primary) ||
+	    (usage_hint & 0xffff) == CREATE_PIXMAP_USAGE_SHARED)
+	    bo_use |= GBM_BO_USE_LINEAR;
+
+	bo->bo.gbm = gbm_bo_create(info->gbm, width, height, gbm_format, bo_use);
+	if (!bo->bo.gbm) {
+	    free(bo);
+	    return NULL;
+	}
+
+	bo->flags |= RADEON_BO_FLAGS_GBM;
+
+	if (new_pitch)
+	    *new_pitch = gbm_bo_get_stride(bo->bo.gbm);
+
+	return bo;
+    }
+#endif
+
     if (usage_hint) {
 	if (info->allowColorTiling) {
 	    if (usage_hint & RADEON_CREATE_PIXMAP_TILING_MACRO)
@@ -245,6 +316,13 @@ radeon_alloc_pixmap_bo(ScrnInfoPtr pScrn, int width, int height, int depth,
 void
 radeon_finish(ScrnInfoPtr scrn, struct radeon_buffer *bo)
 {
+    RADEONInfoPtr info = RADEONPTR(scrn);
+
+    if (info->use_glamor) {
+	radeon_glamor_finish(scrn);
+	return;
+    }
+
     radeon_cs_flush_indirect(scrn);
     radeon_bo_wait(bo->bo.radeon);
 }
@@ -282,7 +360,7 @@ Bool radeon_get_pixmap_handle(PixmapPtr pixmap, uint32_t *handle)
     RADEONInfoPtr info = RADEONPTR(scrn);
 #endif
 
-    if (bo) {
+    if (bo && !(bo->flags & RADEON_BO_FLAGS_GBM)) {
 	*handle = bo->bo.radeon->handle;
 	return TRUE;
     }
@@ -380,6 +458,44 @@ Bool radeon_set_shared_pixmap_backing(PixmapPtr ppix, void *fd_handle,
     if (!bo)
 	goto error;
 
+#ifdef USE_GLAMOR
+    if (info->use_glamor) {
+	struct gbm_import_fd_data data;
+	uint32_t bo_use = GBM_BO_USE_RENDERING;
+
+	data.format = radeon_get_gbm_format(ppix->drawable.depth,
+					    ppix->drawable.bitsPerPixel);
+	if (data.format == ~0U)
+	    goto error;
+
+	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;
+
+	bo->bo.gbm = gbm_bo_import(info->gbm, GBM_BO_IMPORT_FD, &data, bo_use);
+	if (!bo->bo.gbm)
+	    goto error;
+
+	bo->flags |= RADEON_BO_FLAGS_GBM;
+
+	if (!radeon_glamor_create_textured_pixmap(ppix, bo)) {
+	    radeon_buffer_unref(&bo);
+	    return FALSE;
+	}
+
+	ret = radeon_set_pixmap_bo(ppix, bo);
+	/* radeon_set_pixmap_bo increments ref_count if it succeeds */
+	radeon_buffer_unref(&bo);
+	return ret;
+    }
+#endif
+
     bo->bo.radeon = radeon_gem_bo_open_prime(info->bufmgr, ihandle, size);
     if (!bo)
         goto error;
diff --git a/src/radeon_bo_helper.h b/src/radeon_bo_helper.h
index 53af87c3..cc3d1d3b 100644
--- a/src/radeon_bo_helper.h
+++ b/src/radeon_bo_helper.h
@@ -23,13 +23,21 @@
 #ifndef RADEON_BO_HELPER_H
 #define RADEON_BO_HELPER_H 1
 
+#ifdef USE_GLAMOR
+#include <gbm.h>
+#endif
+
 #define RADEON_BO_FLAGS_GBM	0x1
 
 struct radeon_buffer {
 	union {
+#ifdef USE_GLAMOR
+		struct gbm_bo *gbm;
+#endif
 		struct radeon_bo *radeon;
 	} bo;
 	uint32_t ref_count;
+    uint32_t flags;
 };
 
 extern struct radeon_buffer *
@@ -88,8 +96,16 @@ radeon_buffer_unref(struct radeon_buffer **buffer)
 	return;
     }
 
-    radeon_bo_unmap(buf->bo.radeon);
-    radeon_bo_unref(buf->bo.radeon);
+#ifdef USE_GLAMOR
+    if (buf->flags & RADEON_BO_FLAGS_GBM) {
+	gbm_bo_destroy(buf->bo.gbm);
+    } else
+#endif
+    {
+	radeon_bo_unmap(buf->bo.radeon);
+	radeon_bo_unref(buf->bo.radeon);
+    }
+
     free(buf);
     *buffer = NULL;
 }
diff --git a/src/radeon_dri2.c b/src/radeon_dri2.c
index 584a1d9d..ab3db6c5 100644
--- a/src/radeon_dri2.c
+++ b/src/radeon_dri2.c
@@ -79,11 +79,12 @@ static DevPrivateKeyRec dri2_window_private_key_rec;
 static Bool
 radeon_get_flink_name(RADEONEntPtr pRADEONEnt, PixmapPtr pixmap, uint32_t *name)
 {
-    struct radeon_bo *bo = radeon_get_pixmap_bo(pixmap)->bo.radeon;
+    struct radeon_buffer *bo = radeon_get_pixmap_bo(pixmap);
     struct drm_gem_flink flink;
 
-    if (bo)
-	return radeon_gem_get_kernel_name(bo, name) == 0;
+    if (bo && !(bo->flags & RADEON_BO_FLAGS_GBM) &&
+	radeon_gem_get_kernel_name(bo->bo.radeon, name) == 0)
+	return TRUE;
 
     if (radeon_get_pixmap_handle(pixmap, &flink.handle)) {
 	if (drmIoctl(pRADEONEnt->fd, DRM_IOCTL_GEM_FLINK, &flink) != 0)
diff --git a/src/radeon_dri3.c b/src/radeon_dri3.c
index b199c793..688e594e 100644
--- a/src/radeon_dri3.c
+++ b/src/radeon_dri3.c
@@ -213,17 +213,16 @@ static int radeon_dri3_fd_from_pixmap(ScreenPtr screen,
 {
 	struct radeon_bo *bo;
 	int fd;
-
-	bo = radeon_get_pixmap_bo(pixmap)->bo.radeon;
-	if (!bo) {
 #ifdef USE_GLAMOR
-		ScrnInfoPtr scrn = xf86ScreenToScrn(screen);
-		RADEONInfoPtr info = RADEONPTR(scrn);
+	ScrnInfoPtr scrn = xf86ScreenToScrn(screen);
+	RADEONInfoPtr info = RADEONPTR(scrn);
 
-		if (info->use_glamor)
-			return glamor_fd_from_pixmap(screen, pixmap, stride, size);
+	if (info->use_glamor)
+		return glamor_fd_from_pixmap(screen, pixmap, stride, size);
 #endif
 
+	bo = radeon_get_pixmap_bo(pixmap)->bo.radeon;
+	if (!bo) {
 		exaMoveInPixmap(pixmap);
 		bo = radeon_get_pixmap_bo(pixmap)->bo.radeon;
 		if (!bo)
diff --git a/src/radeon_glamor.c b/src/radeon_glamor.c
index c1d96160..fa634947 100644
--- a/src/radeon_glamor.c
+++ b/src/radeon_glamor.c
@@ -52,6 +52,7 @@ radeon_glamor_create_screen_resources(ScreenPtr screen)
 {
 	ScrnInfoPtr scrn = xf86ScreenToScrn(screen);
 	RADEONInfoPtr info = RADEONPTR(scrn);
+	uint32_t handle;
 
 	if (!info->use_glamor)
 		return TRUE;
@@ -61,8 +62,12 @@ radeon_glamor_create_screen_resources(ScreenPtr screen)
 		return FALSE;
 #endif
 
-	if (!glamor_egl_create_textured_screen(screen,
-					       info->front_buffer->bo.radeon->handle,
+	if (info->front_buffer->flags & RADEON_BO_FLAGS_GBM)
+		handle = gbm_bo_get_handle(info->front_buffer->bo.gbm).u32;
+	else
+		handle = info->front_buffer->bo.radeon->handle;
+
+	if (!glamor_egl_create_textured_screen(screen, handle,
 					       scrn->displayWidth *
 					       info->pixel_bytes))
 		return FALSE;
@@ -136,6 +141,13 @@ radeon_glamor_pre_init(ScrnInfoPtr scrn)
 	}
 #endif
 
+	info->gbm = gbm_create_device(pRADEONEnt->fd);
+	if (!info->gbm) {
+		xf86DrvMsg(scrn->scrnIndex, X_ERROR,
+			   "gbm_create_device returned NULL\n");
+		return FALSE;
+	}
+
 	/* Load glamor module */
 	if ((glamor_module = xf86LoadSubModule(scrn, GLAMOR_EGL_MODULE_NAME))) {
 		version = xf86GetModuleVersion(glamor_module);
@@ -164,10 +176,21 @@ radeon_glamor_pre_init(ScrnInfoPtr scrn)
 }
 
 Bool
-radeon_glamor_create_textured_pixmap(PixmapPtr pixmap, struct radeon_pixmap *priv)
+radeon_glamor_create_textured_pixmap(PixmapPtr pixmap, struct radeon_buffer *bo)
 {
-	return glamor_egl_create_textured_pixmap(pixmap, priv->bo->bo.radeon->handle,
-						 pixmap->devKind);
+	ScrnInfoPtr scrn = xf86ScreenToScrn(pixmap->drawable.pScreen);
+	RADEONInfoPtr info = RADEONPTR(scrn);
+	uint32_t handle;
+
+	if (!info->use_glamor)
+		return TRUE;
+
+	if (bo->flags & RADEON_BO_FLAGS_GBM)
+		handle = gbm_bo_get_handle(bo->bo.gbm).u32;
+	else
+		handle = bo->bo.radeon->handle;
+
+	return glamor_egl_create_textured_pixmap(pixmap, handle, pixmap->devKind);
 }
 
 static Bool radeon_glamor_destroy_pixmap(PixmapPtr pixmap)
@@ -179,13 +202,6 @@ static Bool radeon_glamor_destroy_pixmap(PixmapPtr pixmap)
 #endif
 
 	if (pixmap->refcnt == 1) {
-		if (pixmap->devPrivate.ptr) {
-			struct radeon_buffer *bo = radeon_get_pixmap_bo(pixmap);
-
-			if (bo)
-				radeon_bo_unmap(bo->bo.radeon);
-		}
-
 #ifdef HAVE_GLAMOR_EGL_DESTROY_TEXTURED_PIXMAP
 		glamor_egl_destroy_textured_pixmap(pixmap);
 #endif
@@ -259,7 +275,7 @@ radeon_glamor_create_pixmap(ScreenPtr screen, int w, int h, int depth,
 
 		screen->ModifyPixmapHeader(pixmap, w, h, 0, 0, stride, NULL);
 
-		if (!radeon_glamor_create_textured_pixmap(pixmap, priv))
+		if (!radeon_glamor_create_textured_pixmap(pixmap, priv->bo))
 			goto fallback_glamor;
 
 		pixmap->devPrivate.ptr = NULL;
@@ -390,13 +406,12 @@ radeon_glamor_set_shared_pixmap_backing(PixmapPtr pixmap, void *handle)
 {
 	ScreenPtr screen = pixmap->drawable.pScreen;
 	ScrnInfoPtr scrn = xf86ScreenToScrn(screen);
-	struct radeon_pixmap *priv;
 
 	if (!radeon_set_shared_pixmap_backing(pixmap, handle, NULL))
 		return FALSE;
 
-	priv = radeon_get_pixmap_private(pixmap);
-	if (!radeon_glamor_create_textured_pixmap(pixmap, priv)) {
+	if (!radeon_glamor_create_textured_pixmap(pixmap,
+						  radeon_get_pixmap_bo(pixmap))) {
 		xf86DrvMsg(scrn->scrnIndex, X_ERROR,
 			   "Failed to get PRIME drawable for glamor pixmap.\n");
 		return FALSE;
diff --git a/src/radeon_glamor.h b/src/radeon_glamor.h
index ec42df1f..2740ab33 100644
--- a/src/radeon_glamor.h
+++ b/src/radeon_glamor.h
@@ -33,6 +33,12 @@ struct radeon_pixmap;
 
 #ifdef USE_GLAMOR
 
+#ifndef HAVE_GLAMOR_FINISH
+#include <GL/gl.h>
+#endif
+
+#include <gbm.h>
+
 #define GLAMOR_FOR_XORG  1
 #include <glamor.h>
 
@@ -65,12 +71,27 @@ void radeon_glamor_screen_init(ScreenPtr screen);
 Bool radeon_glamor_create_screen_resources(ScreenPtr screen);
 void radeon_glamor_free_screen(int scrnIndex, int flags);
 
-Bool radeon_glamor_create_textured_pixmap(PixmapPtr pixmap, struct radeon_pixmap *priv);
+Bool radeon_glamor_create_textured_pixmap(PixmapPtr pixmap, struct radeon_buffer *bo);
 void radeon_glamor_exchange_buffers(PixmapPtr src, PixmapPtr dst);
 PixmapPtr radeon_glamor_set_pixmap_bo(DrawablePtr drawable, PixmapPtr pixmap);
 
 XF86VideoAdaptorPtr radeon_glamor_xv_init(ScreenPtr pScreen, int num_adapt);
 
+static inline void
+radeon_glamor_finish(ScrnInfoPtr scrn)
+{
+	RADEONInfoPtr info = RADEONPTR(scrn);
+
+#if HAVE_GLAMOR_FINISH
+	glamor_finish(scrn->pScreen);
+#else
+	glamor_block_handler(scrn);
+	glFinish();
+#endif
+
+	info->gpu_flushed++;
+}
+
 #else
 
 static inline Bool radeon_glamor_pre_init(ScrnInfoPtr scrn) { return FALSE; }
@@ -79,7 +100,7 @@ static inline void radeon_glamor_fini(ScreenPtr screen) { }
 static inline Bool radeon_glamor_create_screen_resources(ScreenPtr screen) { return FALSE; }
 static inline void radeon_glamor_free_screen(int scrnIndex, int flags) { }
 
-static inline Bool radeon_glamor_create_textured_pixmap(PixmapPtr pixmap, struct radeon_pixmap *priv) { return TRUE; }
+static inline Bool radeon_glamor_create_textured_pixmap(PixmapPtr pixmap, struct radeon_buffer *bo) { return TRUE; }
 
 static inline void radeon_glamor_exchange_buffers(PixmapPtr src, PixmapPtr dst) {}
 static inline PixmapPtr radeon_glamor_set_pixmap_bo(DrawablePtr drawable, PixmapPtr pixmap) { return pixmap; }
@@ -87,6 +108,9 @@ static inline PixmapPtr radeon_glamor_set_pixmap_bo(DrawablePtr drawable, Pixmap
 static inline struct radeon_pixmap *radeon_get_pixmap_private(PixmapPtr pixmap) { return NULL; }
 
 static inline XF86VideoAdaptorPtr radeon_glamor_xv_init(ScreenPtr pScreen, int num_adapt) { return NULL; }
+
+static inline void radeon_glamor_finish(ScrnInfoPtr pScrn) { }
+
 #endif
 
 #endif /* RADEON_GLAMOR_H */
diff --git a/src/radeon_kms.c b/src/radeon_kms.c
index d3eeebea..72e60831 100644
--- a/src/radeon_kms.c
+++ b/src/radeon_kms.c
@@ -212,6 +212,11 @@ static void RADEONFreeRec(ScrnInfoPtr pScrn)
 	    info->accel_state = NULL;
 	}
 
+#ifdef USE_GLAMOR
+	if (info->gbm)
+	    gbm_device_destroy(info->gbm);
+#endif
+
 	pEnt = info->pEnt;
 	free(pScrn->driverPrivate);
 	pScrn->driverPrivate = NULL;
@@ -2269,7 +2274,11 @@ Bool RADEONScreenInit_KMS(ScreenPtr pScreen, int argc, char **argv)
 	xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "radeon_setup_kernel_mem failed\n");
 	return FALSE;
     }
-    front_ptr = info->front_buffer->bo.radeon->ptr;
+
+    if (!(info->front_buffer->flags & RADEON_BO_FLAGS_GBM))
+	front_ptr = info->front_buffer->bo.radeon->ptr;
+    else
+	front_ptr = NULL;
 
     if (info->r600_shadow_fb) {
 	info->fb_shadow = calloc(1,
@@ -2739,21 +2748,24 @@ static Bool radeon_setup_kernel_mem(ScreenPtr pScreen)
                 ErrorF("Failed to map cursor buffer memory\n");
             }
         }
+
+	if (!info->use_glamor) {
 #if X_BYTE_ORDER == X_BIG_ENDIAN
-	switch (cpp) {
-	case 4:
-	    tiling_flags |= RADEON_TILING_SWAP_32BIT;
-	    break;
-	case 2:
-	    tiling_flags |= RADEON_TILING_SWAP_16BIT;
-	    break;
-	}
-	if (info->ChipFamily < CHIP_FAMILY_R600 &&
-	    info->r600_shadow_fb && tiling_flags)
-	    tiling_flags |= RADEON_TILING_SURFACE;
+	    switch (cpp) {
+	    case 4:
+		tiling_flags |= RADEON_TILING_SWAP_32BIT;
+		break;
+	    case 2:
+		tiling_flags |= RADEON_TILING_SWAP_16BIT;
+		break;
+	    }
+	    if (info->ChipFamily < CHIP_FAMILY_R600 &&
+		info->r600_shadow_fb && tiling_flags)
+		tiling_flags |= RADEON_TILING_SURFACE;
 #endif
-	if (tiling_flags)
-            radeon_bo_set_tiling(info->front_buffer->bo.radeon, tiling_flags, pitch);
+	    if (tiling_flags)
+		radeon_bo_set_tiling(info->front_buffer->bo.radeon, tiling_flags, pitch);
+	}
     }
 
     pScrn->displayWidth = pitch / cpp;
commit b85b7b11f5b5e792f21951b881bd8433d3d70858
Author: Michel Dänzer <michel.daenzer at amd.com>
Date:   Fri May 18 18:49:35 2018 +0200

    Add struct radeon_buffer
    
    Inspired by amdgpu, preparation for the following change. For now, this
    is mostly a wrapper around struct radeon_bo, no functional change
    intended.
    
    Reviewed-by: Alex Deucher <alexander.deucher at amd.com>

diff --git a/src/drmmode_display.c b/src/drmmode_display.c
index 3c4d94fd..c91f5bb2 100644
--- a/src/drmmode_display.c
+++ b/src/drmmode_display.c
@@ -111,7 +111,7 @@ static PixmapPtr drmmode_create_bo_pixmap(ScrnInfoPtr pScrn,
 					  int width, int height,
 					  int depth, int bpp,
 					  int pitch,
-					  struct radeon_bo *bo)
+					  struct radeon_buffer *bo)
 {
 	RADEONInfoPtr info = RADEONPTR(pScrn);
 	ScreenPtr pScreen = pScrn->pScreen;
@@ -379,7 +379,7 @@ create_pixmap_for_fbcon(drmmode_ptr drmmode,
 	RADEONEntPtr pRADEONEnt = RADEONEntPriv(pScrn);
 	RADEONInfoPtr info = RADEONPTR(pScrn);
 	PixmapPtr pixmap = info->fbcon_pixmap;
-	struct radeon_bo *bo;
+	struct radeon_buffer *bo;
 	drmModeFBPtr fbcon;
 	struct drm_gem_flink flink;
 
@@ -402,10 +402,18 @@ create_pixmap_for_fbcon(drmmode_ptr drmmode,
 		goto out_free_fb;
 	}
 
-	bo = radeon_bo_open(drmmode->bufmgr, flink.name, 0, 0, 0, 0);
+	bo = calloc(1, sizeof(struct radeon_buffer));
+	if (!bo) {
+		xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+			   "Couldn't allocate BO for fbcon handle\n");
+		goto out_free_fb;
+	}
+	bo->ref_count = 1;
+
+	bo->bo.radeon = radeon_bo_open(drmmode->bufmgr, flink.name, 0, 0, 0, 0);
 	if (bo == NULL) {
 		xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
-			   "Couldn't allocate bo for fbcon handle\n");
+			   "Couldn't open BO for fbcon handle\n");
 		goto out_free_fb;
 	}
 
@@ -413,7 +421,7 @@ create_pixmap_for_fbcon(drmmode_ptr drmmode,
 					  fbcon->depth, fbcon->bpp, fbcon->pitch,
 					  bo);
 	info->fbcon_pixmap = pixmap;
-	radeon_bo_unref(bo);
+	radeon_buffer_unref(&bo);
 out_free_fb:
 	drmModeFreeFB(fbcon);
 	return pixmap;
@@ -496,11 +504,7 @@ drmmode_crtc_scanout_destroy(drmmode_ptr drmmode,
 		scanout->pixmap = NULL;
 	}
 
-	if (scanout->bo) {
-		radeon_bo_unmap(scanout->bo);
-		radeon_bo_unref(scanout->bo);
-		scanout->bo = NULL;
-	}
+	radeon_buffer_unref(&scanout->bo);
 }
 
 void
@@ -913,7 +917,7 @@ drmmode_set_mode_major(xf86CrtcPtr crtc, DisplayModePtr mode,
 			fb = radeon_fb_create(pScrn, pRADEONEnt->fd,
 					      pScrn->virtualX, pScrn->virtualY,
 					      pScrn->displayWidth * info->pixel_bytes,
-					      info->front_bo->handle);
+					      info->front_buffer->bo.radeon->handle);
 			/* Prevent refcnt of ad-hoc FBs from reaching 2 */
 			drmmode_fb_reference(pRADEONEnt->fd, &drmmode_crtc->fb, NULL);
 			drmmode_crtc->fb = fb;
@@ -2232,14 +2236,12 @@ drmmode_xf86crtc_resize (ScrnInfoPtr scrn, int width, int height)
 {
 	xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(scrn);
 	RADEONInfoPtr info = RADEONPTR(scrn);
-	struct radeon_bo *old_front = NULL;
+	struct radeon_buffer *old_front = NULL;
 	ScreenPtr   screen = xf86ScrnToScreen(scrn);
 	int	    i, pitch, old_width, old_height, old_pitch;
-	int aligned_height;
-	uint32_t screen_size;
+	int usage = CREATE_PIXMAP_USAGE_BACKING_PIXMAP;
 	int cpp = info->pixel_bytes;
-	struct radeon_surface surface;
-	uint32_t tiling_flags = 0, base_align;
+	uint32_t tiling_flags;
 	PixmapPtr ppix = screen->GetScreenPixmap(screen);
 	void *fb_shadow;
 
@@ -2247,71 +2249,34 @@ drmmode_xf86crtc_resize (ScrnInfoPtr scrn, int width, int height)
 		return TRUE;
 
 	if (info->allowColorTiling && !info->shadow_primary) {
-		if (info->ChipFamily >= CHIP_FAMILY_R600) {
-			if (info->allowColorTiling2D) {
-				tiling_flags |= RADEON_TILING_MACRO;
-			} else {
-				tiling_flags |= RADEON_TILING_MICRO;
-			}
-		} else
-			tiling_flags |= RADEON_TILING_MACRO;
-	}
-
-	pitch = RADEON_ALIGN(width, drmmode_get_pitch_align(scrn, cpp, tiling_flags)) * cpp;
-	aligned_height = RADEON_ALIGN(height, drmmode_get_height_align(scrn, tiling_flags));
-	screen_size = RADEON_ALIGN(pitch * aligned_height, RADEON_GPU_PAGE_SIZE);
-	base_align = 4096;
-
-	if (info->surf_man) {
-		if (!radeon_surface_initialize(info, &surface, width, height,
-					       cpp, tiling_flags, 0))
-			return FALSE;
-
-		screen_size = surface.bo_size;
-		base_align = surface.bo_alignment;
-		pitch = surface.level[0].pitch_bytes;
-		tiling_flags = 0;
-		switch (surface.level[0].mode) {
-		case RADEON_SURF_MODE_2D:
-			tiling_flags |= RADEON_TILING_MACRO;
-			tiling_flags |= surface.bankw << RADEON_TILING_EG_BANKW_SHIFT;
-			tiling_flags |= surface.bankh << RADEON_TILING_EG_BANKH_SHIFT;
-			tiling_flags |= surface.mtilea << RADEON_TILING_EG_MACRO_TILE_ASPECT_SHIFT;
-			if (surface.tile_split)
-				tiling_flags |= eg_tile_split(surface.tile_split)
-						<< RADEON_TILING_EG_TILE_SPLIT_SHIFT;
-			break;
-		case RADEON_SURF_MODE_1D:
-			tiling_flags |= RADEON_TILING_MICRO;
-			break;
-		default:
-			break;
-		}
-		if (!info->use_glamor)
-			info->front_surface = surface;
+		if (info->ChipFamily < CHIP_FAMILY_R600 || info->allowColorTiling2D)
+			usage |= RADEON_CREATE_PIXMAP_TILING_MACRO;
+		else
+			usage |= RADEON_CREATE_PIXMAP_TILING_MICRO;
 	}
 
-	xf86DrvMsg(scrn->scrnIndex, X_INFO,
-		   "Allocate new frame buffer %dx%d stride %d\n",
-		   width, height, pitch / cpp);
+	xf86DrvMsg(scrn->scrnIndex, X_INFO, "Allocate new frame buffer %dx%d\n",
+		   width, height);
 
 	old_width = scrn->virtualX;
 	old_height = scrn->virtualY;
 	old_pitch = scrn->displayWidth;
-	old_front = info->front_bo;
+	old_front = info->front_buffer;
 
 	scrn->virtualX = width;
 	scrn->virtualY = height;
-	scrn->displayWidth = pitch / cpp;
 
-	info->front_bo = radeon_bo_open(info->bufmgr, 0, screen_size, base_align,
-					info->shadow_primary ?
-					RADEON_GEM_DOMAIN_GTT :
-					RADEON_GEM_DOMAIN_VRAM,
-					tiling_flags ? RADEON_GEM_NO_CPU_ACCESS : 0);
-	if (!info->front_bo)
+	info->front_buffer = radeon_alloc_pixmap_bo(scrn, scrn->virtualX,
+						    scrn->virtualY, scrn->depth,
+						    usage, scrn->bitsPerPixel,
+						    &pitch,
+						    &info->front_surface,
+						    &tiling_flags);
+	if (!info->front_buffer)
 		goto fail;
 
+	scrn->displayWidth = pitch / cpp;
+
 #if X_BYTE_ORDER == X_BIG_ENDIAN
 	switch (cpp) {
 	case 4:
@@ -2326,7 +2291,7 @@ drmmode_xf86crtc_resize (ScrnInfoPtr scrn, int width, int height)
 	    tiling_flags |= RADEON_TILING_SURFACE;
 #endif
 	if (tiling_flags)
-	    radeon_bo_set_tiling(info->front_bo, tiling_flags, pitch);
+	    radeon_bo_set_tiling(info->front_buffer->bo.radeon, tiling_flags, pitch);
 
 	if (!info->r600_shadow_fb) {
 		if (info->surf_man && !info->use_glamor)
@@ -2334,9 +2299,9 @@ drmmode_xf86crtc_resize (ScrnInfoPtr scrn, int width, int height)
 		screen->ModifyPixmapHeader(ppix,
 					   width, height, -1, -1, pitch, NULL);
 	} else {
-		if (radeon_bo_map(info->front_bo, 1))
+		if (radeon_bo_map(info->front_buffer->bo.radeon, 1))
 			goto fail;
-		fb_shadow = calloc(1, screen_size);
+		fb_shadow = calloc(1, pitch * scrn->virtualY);
 		if (fb_shadow == NULL)
 			goto fail;
 		free(info->fb_shadow);
@@ -2350,12 +2315,12 @@ drmmode_xf86crtc_resize (ScrnInfoPtr scrn, int width, int height)
 		radeon_glamor_create_screen_resources(scrn->pScreen);
 
 	if (!info->r600_shadow_fb) {
-		if (!radeon_set_pixmap_bo(ppix, info->front_bo))
+		if (!radeon_set_pixmap_bo(ppix, info->front_buffer))
 			goto fail;
 	}
 
 	radeon_pixmap_clear(ppix);
-	radeon_finish(scrn, info->front_bo);
+	radeon_finish(scrn, info->front_buffer);
 
 	for (i = 0; i < xf86_config->num_crtc; i++) {
 		xf86CrtcPtr crtc = xf86_config->crtc[i];
@@ -2367,16 +2332,14 @@ drmmode_xf86crtc_resize (ScrnInfoPtr scrn, int width, int height)
 				       crtc->rotation, crtc->x, crtc->y);
 	}
 
-	if (old_front)
-		radeon_bo_unref(old_front);
+	radeon_buffer_unref(&old_front);
 
-	radeon_kms_update_vram_limit(scrn, screen_size);
+	radeon_kms_update_vram_limit(scrn, pitch * scrn->virtualY);
 	return TRUE;
 
  fail:
-	if (info->front_bo)
-		radeon_bo_unref(info->front_bo);
-	info->front_bo = old_front;
+	radeon_buffer_unref(&info->front_buffer);
+	info->front_buffer = old_front;
 	scrn->virtualX = old_width;
 	scrn->virtualY = old_height;
 	scrn->displayWidth = old_pitch;
diff --git a/src/drmmode_display.h b/src/drmmode_display.h
index e0b97e72..23460fdc 100644
--- a/src/drmmode_display.h
+++ b/src/drmmode_display.h
@@ -72,7 +72,7 @@ struct drmmode_fb {
 };
 
 struct drmmode_scanout {
-    struct radeon_bo *bo;
+    struct radeon_buffer *bo;
     PixmapPtr pixmap;
     int width, height;
 };
diff --git a/src/evergreen_exa.c b/src/evergreen_exa.c
index 41edd345..dae8b6a1 100644
--- a/src/evergreen_exa.c
+++ b/src/evergreen_exa.c
@@ -71,7 +71,7 @@ EVERGREENPrepareSolid(PixmapPtr pPix, int alu, Pixel pm, Pixel fg)
     if (!RADEONValidPM(pm, pPix->drawable.bitsPerPixel))
 	RADEON_FALLBACK(("invalid planemask\n"));
 
-    dst.bo = radeon_get_pixmap_bo(pPix);
+    dst.bo = radeon_get_pixmap_bo(pPix)->bo.radeon;
     dst.tiling_flags = radeon_get_pixmap_tiling(pPix);
     dst.surface = radeon_get_pixmap_surface(pPix);
 
@@ -466,13 +466,13 @@ EVERGREENPrepareCopy(PixmapPtr pSrc,   PixmapPtr pDst,
 
     accel_state->same_surface = FALSE;
 
-    src_obj.bo = radeon_get_pixmap_bo(pSrc);
-    dst_obj.bo = radeon_get_pixmap_bo(pDst);
+    src_obj.bo = radeon_get_pixmap_bo(pSrc)->bo.radeon;
+    dst_obj.bo = radeon_get_pixmap_bo(pDst)->bo.radeon;
     dst_obj.surface = radeon_get_pixmap_surface(pDst);
     src_obj.surface = radeon_get_pixmap_surface(pSrc);
     dst_obj.tiling_flags = radeon_get_pixmap_tiling(pDst);
     src_obj.tiling_flags = radeon_get_pixmap_tiling(pSrc);
-    if (radeon_get_pixmap_bo(pSrc) == radeon_get_pixmap_bo(pDst))
+    if (src_obj.bo == dst_obj.bo)
 	accel_state->same_surface = TRUE;
 
     src_obj.width = pSrc->drawable.width;
@@ -1301,7 +1301,7 @@ static Bool EVERGREENPrepareComposite(int op, PicturePtr pSrcPicture,
 	return FALSE;
 
     if (pSrc) {
-	src_obj.bo = radeon_get_pixmap_bo(pSrc);
+	src_obj.bo = radeon_get_pixmap_bo(pSrc)->bo.radeon;
 	src_obj.surface = radeon_get_pixmap_surface(pSrc);
 	src_obj.tiling_flags = radeon_get_pixmap_tiling(pSrc);
 	src_obj.pitch = exaGetPixmapPitch(pSrc) / (pSrc->drawable.bitsPerPixel / 8);
@@ -1311,7 +1311,7 @@ static Bool EVERGREENPrepareComposite(int op, PicturePtr pSrcPicture,
 	src_obj.domain = RADEON_GEM_DOMAIN_VRAM | RADEON_GEM_DOMAIN_GTT;
     }
 
-    dst_obj.bo = radeon_get_pixmap_bo(pDst);
+    dst_obj.bo = radeon_get_pixmap_bo(pDst)->bo.radeon;
     dst_obj.surface = radeon_get_pixmap_surface(pDst);
     dst_obj.tiling_flags = radeon_get_pixmap_tiling(pDst);
     dst_obj.pitch = exaGetPixmapPitch(pDst) / (pDst->drawable.bitsPerPixel / 8);
@@ -1325,7 +1325,7 @@ static Bool EVERGREENPrepareComposite(int op, PicturePtr pSrcPicture,
 
     if (pMaskPicture) {
 	if (pMask) {
-	    mask_obj.bo = radeon_get_pixmap_bo(pMask);
+	    mask_obj.bo = radeon_get_pixmap_bo(pMask)->bo.radeon;
 	    mask_obj.tiling_flags = radeon_get_pixmap_tiling(pMask);
 	    mask_obj.pitch = exaGetPixmapPitch(pMask) / (pMask->drawable.bitsPerPixel / 8);
 	    mask_obj.surface = radeon_get_pixmap_surface(pMask);
@@ -1673,16 +1673,16 @@ EVERGREENUploadToScreen(PixmapPtr pDst, int x, int y, int w, int h,
 	return FALSE;
 
     driver_priv = exaGetPixmapDriverPrivate(pDst);
-    if (!driver_priv || !driver_priv->bo)
+    if (!driver_priv || !driver_priv->bo->bo.radeon)
 	return FALSE;
 
     /* If we know the BO won't be busy / in VRAM, don't bother with a scratch */
-    copy_dst = driver_priv->bo;
+    copy_dst = driver_priv->bo->bo.radeon;
     copy_pitch = pDst->devKind;
     if (!(driver_priv->tiling_flags & (RADEON_TILING_MACRO | RADEON_TILING_MICRO))) {
-	if (!radeon_bo_is_referenced_by_cs(driver_priv->bo, info->cs)) {
+	if (!radeon_bo_is_referenced_by_cs(driver_priv->bo->bo.radeon, info->cs)) {
 	    flush = FALSE;
-	    if (!radeon_bo_is_busy(driver_priv->bo, &dst_domain) &&
+	    if (!radeon_bo_is_busy(driver_priv->bo->bo.radeon, &dst_domain) &&
 		!(dst_domain & RADEON_GEM_DOMAIN_VRAM))
 		goto copy;
 	}
@@ -1711,7 +1711,7 @@ EVERGREENUploadToScreen(PixmapPtr pDst, int x, int y, int w, int h,
     dst_obj.height = pDst->drawable.height;
     dst_obj.bpp = bpp;
     dst_obj.domain = RADEON_GEM_DOMAIN_VRAM;
-    dst_obj.bo = radeon_get_pixmap_bo(pDst);
+    dst_obj.bo = radeon_get_pixmap_bo(pDst)->bo.radeon;
     dst_obj.tiling_flags = radeon_get_pixmap_tiling(pDst);
     dst_obj.surface = radeon_get_pixmap_surface(pDst);
 
@@ -1739,7 +1739,7 @@ copy:
     r = TRUE;
     size = w * bpp / 8;
     dst = copy_dst->ptr;
-    if (copy_dst == driver_priv->bo)
+    if (copy_dst == driver_priv->bo->bo.radeon)
 	dst += y * copy_pitch + x * bpp / 8;
     for (i = 0; i < h; i++) {
 	memcpy(dst + i * copy_pitch, src, size);
@@ -1789,15 +1789,15 @@ EVERGREENDownloadFromScreen(PixmapPtr pSrc, int x, int y, int w,
 	return FALSE;
 
     driver_priv = exaGetPixmapDriverPrivate(pSrc);
-    if (!driver_priv || !driver_priv->bo)
+    if (!driver_priv || !driver_priv->bo->bo.radeon)
 	return FALSE;
 
     /* If we know the BO won't end up in VRAM anyway, don't bother with a scratch */
-    copy_src = driver_priv->bo;
+    copy_src = driver_priv->bo->bo.radeon;
     copy_pitch = pSrc->devKind;
     if (!(driver_priv->tiling_flags & (RADEON_TILING_MACRO | RADEON_TILING_MICRO))) {
-	if (radeon_bo_is_referenced_by_cs(driver_priv->bo, info->cs)) {
-	    src_domain = radeon_bo_get_src_domain(driver_priv->bo);
+	if (radeon_bo_is_referenced_by_cs(driver_priv->bo->bo.radeon, info->cs)) {
+	    src_domain = radeon_bo_get_src_domain(driver_priv->bo->bo.radeon);
 	    if ((src_domain & (RADEON_GEM_DOMAIN_GTT | RADEON_GEM_DOMAIN_VRAM)) ==
 		(RADEON_GEM_DOMAIN_GTT | RADEON_GEM_DOMAIN_VRAM))
 		src_domain = 0;
@@ -1806,7 +1806,7 @@ EVERGREENDownloadFromScreen(PixmapPtr pSrc, int x, int y, int w,
 	}
 
 	if (!src_domain)
-	    radeon_bo_is_busy(driver_priv->bo, &src_domain);
+	    radeon_bo_is_busy(driver_priv->bo->bo.radeon, &src_domain);
 
 	if (src_domain & ~(uint32_t)RADEON_GEM_DOMAIN_VRAM)
 	    goto copy;
@@ -1841,7 +1841,7 @@ EVERGREENDownloadFromScreen(PixmapPtr pSrc, int x, int y, int w,
     src_obj.height = pSrc->drawable.height;
     src_obj.bpp = bpp;
     src_obj.domain = RADEON_GEM_DOMAIN_VRAM | RADEON_GEM_DOMAIN_GTT;
-    src_obj.bo = radeon_get_pixmap_bo(pSrc);
+    src_obj.bo = radeon_get_pixmap_bo(pSrc)->bo.radeon;
     src_obj.tiling_flags = radeon_get_pixmap_tiling(pSrc);
     src_obj.surface = radeon_get_pixmap_surface(pSrc);
 
@@ -1883,7 +1883,7 @@ copy:
     }
     r = TRUE;
     w *= bpp / 8;
-    if (copy_src == driver_priv->bo)
+    if (copy_src == driver_priv->bo->bo.radeon)
 	size = y * copy_pitch + x * bpp / 8;
     else
 	size = 0;
diff --git a/src/evergreen_state.h b/src/evergreen_state.h
index ef331002..7e54e1c7 100644
--- a/src/evergreen_state.h
+++ b/src/evergreen_state.h
@@ -349,7 +349,6 @@ extern void *RADEONEXACreatePixmap2(ScreenPtr pScreen, int width, int height,
 				    int depth, int usage_hint, int bitsPerPixel,
 				    int *new_pitch);
 extern void RADEONEXADestroyPixmap(ScreenPtr pScreen, void *driverPriv);
-extern struct radeon_bo *radeon_get_pixmap_bo(PixmapPtr pPix);
 extern Bool RADEONEXAPixmapIsOffscreen(PixmapPtr pPix);
 extern Bool RADEONEXASharePixmapBacking(PixmapPtr ppix, ScreenPtr slave, void **handle_p);
 extern Bool RADEONEXASetSharedPixmapBacking(PixmapPtr ppix, void *handle);
diff --git a/src/evergreen_textured_videofuncs.c b/src/evergreen_textured_videofuncs.c
index 20805ff4..53675600 100644
--- a/src/evergreen_textured_videofuncs.c
+++ b/src/evergreen_textured_videofuncs.c
@@ -140,7 +140,7 @@ EVERGREENDisplayTexturedVideo(ScrnInfoPtr pScrn, RADEONPortPrivPtr pPriv)
     CLEAR (vs_const_conf);
     CLEAR (ps_const_conf);
 
-    dst_obj.bo = radeon_get_pixmap_bo(pPixmap);
+    dst_obj.bo = radeon_get_pixmap_bo(pPixmap)->bo.radeon;
     dst_obj.tiling_flags = radeon_get_pixmap_tiling(pPixmap);
     dst_obj.surface = radeon_get_pixmap_surface(pPixmap);
 
diff --git a/src/r600_exa.c b/src/r600_exa.c
index a111dd45..bd824c87 100644
--- a/src/r600_exa.c
+++ b/src/r600_exa.c
@@ -150,7 +150,7 @@ R600PrepareSolid(PixmapPtr pPix, int alu, Pixel pm, Pixel fg)
     if (!RADEONValidPM(pm, pPix->drawable.bitsPerPixel))
 	RADEON_FALLBACK(("invalid planemask\n"));
 
-    dst.bo = radeon_get_pixmap_bo(pPix);
+    dst.bo = radeon_get_pixmap_bo(pPix)->bo.radeon;
     dst.tiling_flags = radeon_get_pixmap_tiling(pPix);
     dst.surface = radeon_get_pixmap_surface(pPix);
 
@@ -534,13 +534,13 @@ R600PrepareCopy(PixmapPtr pSrc,   PixmapPtr pDst,
 
     accel_state->same_surface = FALSE;
 
-    src_obj.bo = radeon_get_pixmap_bo(pSrc);
-    dst_obj.bo = radeon_get_pixmap_bo(pDst);
+    src_obj.bo = radeon_get_pixmap_bo(pSrc)->bo.radeon;
+    dst_obj.bo = radeon_get_pixmap_bo(pDst)->bo.radeon;
     dst_obj.tiling_flags = radeon_get_pixmap_tiling(pDst);
     src_obj.tiling_flags = radeon_get_pixmap_tiling(pSrc);
     src_obj.surface = radeon_get_pixmap_surface(pSrc);
     dst_obj.surface = radeon_get_pixmap_surface(pDst);
-    if (radeon_get_pixmap_bo(pSrc) == radeon_get_pixmap_bo(pDst))
+    if (src_obj.bo == dst_obj.bo)
 	accel_state->same_surface = TRUE;
 
     src_obj.width = pSrc->drawable.width;
@@ -1344,7 +1344,7 @@ static Bool R600PrepareComposite(int op, PicturePtr pSrcPicture,
 	return FALSE;
 
     if (pSrc) {
-	src_obj.bo = radeon_get_pixmap_bo(pSrc);
+	src_obj.bo = radeon_get_pixmap_bo(pSrc)->bo.radeon;
 	src_obj.tiling_flags = radeon_get_pixmap_tiling(pSrc);
 	src_obj.surface = radeon_get_pixmap_surface(pSrc);
 	src_obj.pitch = exaGetPixmapPitch(pSrc) / (pSrc->drawable.bitsPerPixel / 8);
@@ -1354,7 +1354,7 @@ static Bool R600PrepareComposite(int op, PicturePtr pSrcPicture,
 	src_obj.domain = RADEON_GEM_DOMAIN_VRAM | RADEON_GEM_DOMAIN_GTT;
     }
 
-    dst_obj.bo = radeon_get_pixmap_bo(pDst);
+    dst_obj.bo = radeon_get_pixmap_bo(pDst)->bo.radeon;
     dst_obj.tiling_flags = radeon_get_pixmap_tiling(pDst);
     dst_obj.surface = radeon_get_pixmap_surface(pDst);
     dst_obj.pitch = exaGetPixmapPitch(pDst) / (pDst->drawable.bitsPerPixel / 8);
@@ -1368,7 +1368,7 @@ static Bool R600PrepareComposite(int op, PicturePtr pSrcPicture,
 
     if (pMaskPicture) {
 	if (pMask) {
-	    mask_obj.bo = radeon_get_pixmap_bo(pMask);
+	    mask_obj.bo = radeon_get_pixmap_bo(pMask)->bo.radeon;
 	    mask_obj.tiling_flags = radeon_get_pixmap_tiling(pMask);
 	    mask_obj.surface = radeon_get_pixmap_surface(pMask);
 	    mask_obj.pitch = exaGetPixmapPitch(pMask) / (pMask->drawable.bitsPerPixel / 8);
@@ -1700,16 +1700,16 @@ R600UploadToScreenCS(PixmapPtr pDst, int x, int y, int w, int h,
 	return FALSE;
 
     driver_priv = exaGetPixmapDriverPrivate(pDst);
-    if (!driver_priv || !driver_priv->bo)
+    if (!driver_priv || !driver_priv->bo->bo.radeon)
 	return FALSE;
 
     /* If we know the BO won't be busy / in VRAM, don't bother with a scratch */
-    copy_dst = driver_priv->bo;
+    copy_dst = driver_priv->bo->bo.radeon;
     copy_pitch = pDst->devKind;
     if (!(driver_priv->tiling_flags & (RADEON_TILING_MACRO | RADEON_TILING_MICRO))) {
-	if (!radeon_bo_is_referenced_by_cs(driver_priv->bo, info->cs)) {
+	if (!radeon_bo_is_referenced_by_cs(driver_priv->bo->bo.radeon, info->cs)) {
 	    flush = FALSE;
-	    if (!radeon_bo_is_busy(driver_priv->bo, &dst_domain) &&
+	    if (!radeon_bo_is_busy(driver_priv->bo->bo.radeon, &dst_domain) &&
 		!(dst_domain & RADEON_GEM_DOMAIN_VRAM))
 		goto copy;
 	}
@@ -1741,7 +1741,7 @@ R600UploadToScreenCS(PixmapPtr pDst, int x, int y, int w, int h,
     dst_obj.height = pDst->drawable.height;
     dst_obj.bpp = bpp;
     dst_obj.domain = RADEON_GEM_DOMAIN_VRAM;
-    dst_obj.bo = radeon_get_pixmap_bo(pDst);
+    dst_obj.bo = radeon_get_pixmap_bo(pDst)->bo.radeon;
     dst_obj.tiling_flags = radeon_get_pixmap_tiling(pDst);
     dst_obj.surface = radeon_get_pixmap_surface(pDst);
 
@@ -1769,7 +1769,7 @@ copy:
     r = TRUE;
     size = w * bpp / 8;
     dst = copy_dst->ptr;
-    if (copy_dst == driver_priv->bo)
+    if (copy_dst == driver_priv->bo->bo.radeon)
 	dst += y * copy_pitch + x * bpp / 8;
     for (i = 0; i < h; i++) {
         memcpy(dst + i * copy_pitch, src, size);
@@ -1819,15 +1819,15 @@ R600DownloadFromScreenCS(PixmapPtr pSrc, int x, int y, int w,
 	return FALSE;
 
     driver_priv = exaGetPixmapDriverPrivate(pSrc);
-    if (!driver_priv || !driver_priv->bo)
+    if (!driver_priv || !driver_priv->bo->bo.radeon)
 	return FALSE;
 
     /* If we know the BO won't end up in VRAM anyway, don't bother with a scratch */
-    copy_src = driver_priv->bo;
+    copy_src = driver_priv->bo->bo.radeon;
     copy_pitch = pSrc->devKind;
     if (!(driver_priv->tiling_flags & (RADEON_TILING_MACRO | RADEON_TILING_MICRO))) {
-	if (radeon_bo_is_referenced_by_cs(driver_priv->bo, info->cs)) {
-	    src_domain = radeon_bo_get_src_domain(driver_priv->bo);
+	if (radeon_bo_is_referenced_by_cs(driver_priv->bo->bo.radeon, info->cs)) {
+	    src_domain = radeon_bo_get_src_domain(driver_priv->bo->bo.radeon);
 	    if ((src_domain & (RADEON_GEM_DOMAIN_GTT | RADEON_GEM_DOMAIN_VRAM)) ==
 		(RADEON_GEM_DOMAIN_GTT | RADEON_GEM_DOMAIN_VRAM))
 		src_domain = 0;
@@ -1836,7 +1836,7 @@ R600DownloadFromScreenCS(PixmapPtr pSrc, int x, int y, int w,
 	}
 
 	if (!src_domain)
-	    radeon_bo_is_busy(driver_priv->bo, &src_domain);
+	    radeon_bo_is_busy(driver_priv->bo->bo.radeon, &src_domain);
 
 	if (src_domain & ~(uint32_t)RADEON_GEM_DOMAIN_VRAM)
 	    goto copy;
@@ -1867,7 +1867,7 @@ R600DownloadFromScreenCS(PixmapPtr pSrc, int x, int y, int w,
     src_obj.height = pSrc->drawable.height;
     src_obj.bpp = bpp;
     src_obj.domain = RADEON_GEM_DOMAIN_VRAM | RADEON_GEM_DOMAIN_GTT;
-    src_obj.bo = radeon_get_pixmap_bo(pSrc);
+    src_obj.bo = radeon_get_pixmap_bo(pSrc)->bo.radeon;
     src_obj.tiling_flags = radeon_get_pixmap_tiling(pSrc);
     src_obj.surface = radeon_get_pixmap_surface(pSrc);
 
@@ -1909,7 +1909,7 @@ copy:
     }
     r = TRUE;
     w *= bpp / 8;
-    if (copy_src == driver_priv->bo)
+    if (copy_src == driver_priv->bo->bo.radeon)
 	size = y * copy_pitch + x * bpp / 8;
     else
 	size = 0;
diff --git a/src/r600_state.h b/src/r600_state.h
index 4898e8de..34345996 100644
--- a/src/r600_state.h
+++ b/src/r600_state.h
@@ -320,7 +320,6 @@ extern void *RADEONEXACreatePixmap2(ScreenPtr pScreen, int width, int height,
 				    int depth, int usage_hint, int bitsPerPixel,
 				    int *new_pitch);
 extern void RADEONEXADestroyPixmap(ScreenPtr pScreen, void *driverPriv);
-extern struct radeon_bo *radeon_get_pixmap_bo(PixmapPtr pPix);
 extern Bool RADEONEXAPixmapIsOffscreen(PixmapPtr pPix);
 extern Bool RADEONEXASharePixmapBacking(PixmapPtr ppix, ScreenPtr slave, void **handle_p);
 extern Bool RADEONEXASetSharedPixmapBacking(PixmapPtr ppix, void *handle);
diff --git a/src/r600_textured_videofuncs.c b/src/r600_textured_videofuncs.c
index d20df7e2..c8a9b197 100644
--- a/src/r600_textured_videofuncs.c
+++ b/src/r600_textured_videofuncs.c
@@ -152,7 +152,7 @@ R600DisplayTexturedVideo(ScrnInfoPtr pScrn, RADEONPortPrivPtr pPriv)
     CLEAR (vs_conf);
     CLEAR (ps_conf);
 
-    dst_obj.bo = radeon_get_pixmap_bo(pPixmap);
+    dst_obj.bo = radeon_get_pixmap_bo(pPixmap)->bo.radeon;
     dst_obj.tiling_flags = radeon_get_pixmap_tiling(pPixmap);
     dst_obj.surface = radeon_get_pixmap_surface(pPixmap);
 
diff --git a/src/radeon.h b/src/radeon.h
index 499e89f9..648fd98a 100644
--- a/src/radeon.h
+++ b/src/radeon.h
@@ -83,6 +83,7 @@
 #include "radeon_dri2.h"
 #include "drmmode_display.h"
 #include "radeon_surface.h"
+#include "radeon_bo_helper.h"
 
 				/* Render support */
 #ifdef RENDER
@@ -300,14 +301,13 @@ radeon_dirty_src_equals(PixmapDirtyUpdatePtr dirty, PixmapPtr pixmap)
 #define CURSOR_WIDTH_CIK	128
 #define CURSOR_HEIGHT_CIK	128
 
-
 #ifdef USE_GLAMOR
 
 struct radeon_pixmap {
 	uint_fast32_t gpu_read;
 	uint_fast32_t gpu_write;
 
-	struct radeon_bo *bo;
+	struct radeon_buffer *bo;
 	struct drmmode_fb *fb;
 
 	uint32_t tiling_flags;
@@ -333,7 +333,7 @@ static inline void radeon_set_pixmap_private(PixmapPtr pixmap, struct radeon_pix
 
 
 struct radeon_exa_pixmap_priv {
-    struct radeon_bo *bo;
+    struct radeon_buffer *bo;
     struct drmmode_fb *fb;
     uint32_t tiling_flags;
     struct radeon_surface surface;
@@ -567,7 +567,7 @@ typedef struct {
 
     void (*reemit_current2d)(ScrnInfoPtr pScrn, int op); // emit the current 2D state into the IB 
     struct radeon_2d_state state_2d;
-    struct radeon_bo *front_bo;
+    struct radeon_buffer *front_buffer;
     struct radeon_bo_manager *bufmgr;
     struct radeon_cs_manager *csm;
     struct radeon_cs *cs;
@@ -713,7 +713,7 @@ static inline struct radeon_surface *radeon_get_pixmap_surface(PixmapPtr pPix)
 
 uint32_t radeon_get_pixmap_tiling(PixmapPtr pPix);
 
-static inline Bool radeon_set_pixmap_bo(PixmapPtr pPix, struct radeon_bo *bo)
+static inline Bool radeon_set_pixmap_bo(PixmapPtr pPix, struct radeon_buffer *bo)
 {
     ScrnInfoPtr scrn = xf86ScreenToScrn(pPix->drawable.pScreen);
     RADEONEntPtr pRADEONEnt = RADEONEntPriv(scrn);
@@ -732,7 +732,7 @@ static inline Bool radeon_set_pixmap_bo(PixmapPtr pPix, struct radeon_bo *bo)
 		if (priv->bo == bo)
 		    return TRUE;
 
-		radeon_bo_unref(priv->bo);
+		radeon_buffer_unref(&priv->bo);
 	    }
 
 	    drmmode_fb_reference(pRADEONEnt->fd, &priv->fb, NULL);
@@ -752,10 +752,10 @@ static inline Bool radeon_set_pixmap_bo(PixmapPtr pPix, struct radeon_bo *bo)
 		    return FALSE;
 	    }
 
-	    radeon_bo_ref(bo);
+	    radeon_buffer_ref(bo);
 	    priv->bo = bo;
 
-	    radeon_bo_get_tiling(bo, &priv->tiling_flags, &pitch);
+	    radeon_bo_get_tiling(bo->bo.radeon, &priv->tiling_flags, &pitch);
 	}
 
 	radeon_set_pixmap_private(pPix, priv);
@@ -769,15 +769,14 @@ static inline Bool radeon_set_pixmap_bo(PixmapPtr pPix, struct radeon_bo *bo)
 	if (driver_priv) {
 	    uint32_t pitch;
 
-	    if (driver_priv->bo)
-		radeon_bo_unref(driver_priv->bo);
-
+	    radeon_buffer_unref(&driver_priv->bo);
 	    drmmode_fb_reference(pRADEONEnt->fd, &driver_priv->fb, NULL);
 
-	    radeon_bo_ref(bo);
+	    radeon_buffer_ref(bo);
 	    driver_priv->bo = bo;
 
-	    radeon_bo_get_tiling(bo, &driver_priv->tiling_flags, &pitch);
+	    radeon_bo_get_tiling(bo->bo.radeon, &driver_priv->tiling_flags,
+				 &pitch);
 	    return TRUE;
 	}
 
@@ -785,7 +784,7 @@ static inline Bool radeon_set_pixmap_bo(PixmapPtr pPix, struct radeon_bo *bo)
     }
 }
 
-static inline struct radeon_bo *radeon_get_pixmap_bo(PixmapPtr pPix)
+static inline struct radeon_buffer *radeon_get_pixmap_bo(PixmapPtr pPix)
 {
 #ifdef USE_GLAMOR
     RADEONInfoPtr info = RADEONPTR(xf86ScreenToScrn(pPix->drawable.pScreen));
@@ -1004,7 +1003,7 @@ do {									\
 #define EMIT_OFFSET(reg, value, pPix, rd, wd) do {		\
     driver_priv = exaGetPixmapDriverPrivate(pPix);		\
     OUT_RING_REG((reg), (value));				\
-    OUT_RING_RELOC(driver_priv->bo, (rd), (wd));			\
+    OUT_RING_RELOC(driver_priv->bo->bo.radeon, (rd), (wd));	\
     } while(0)
 
 #define EMIT_READ_OFFSET(reg, value, pPix) EMIT_OFFSET(reg, value, pPix, (RADEON_GEM_DOMAIN_VRAM | RADEON_GEM_DOMAIN_GTT), 0)
@@ -1018,7 +1017,7 @@ do {									\
 #define EMIT_COLORPITCH(reg, value, pPix) do {			\
     driver_priv = exaGetPixmapDriverPrivate(pPix);			\
     OUT_RING_REG((reg), value);					\
-    OUT_RING_RELOC(driver_priv->bo, 0, RADEON_GEM_DOMAIN_VRAM);		\
+    OUT_RING_RELOC(driver_priv->bo->bo.radeon, 0, RADEON_GEM_DOMAIN_VRAM);	\
 } while(0)
 
 static __inline__ void RADEON_SYNC(RADEONInfoPtr info, ScrnInfoPtr pScrn)
diff --git a/src/radeon_bo_helper.c b/src/radeon_bo_helper.c
index 7cfe9126..2b836bbf 100644
--- a/src/radeon_bo_helper.c
+++ b/src/radeon_bo_helper.c
@@ -145,7 +145,7 @@ radeon_surface_initialize(RADEONInfoPtr info, struct radeon_surface *surface,
 /* Calculate appropriate tiling and pitch for a pixmap and allocate a BO that
  * can hold it.
  */
-struct radeon_bo*
+struct radeon_buffer *
 radeon_alloc_pixmap_bo(ScrnInfoPtr pScrn, int width, int height, int depth,
 		       int usage_hint, int bitsPerPixel, int *new_pitch,
 		       struct radeon_surface *new_surface, uint32_t *new_tiling)
@@ -156,7 +156,7 @@ radeon_alloc_pixmap_bo(ScrnInfoPtr pScrn, int width, int height, int depth,
     int cpp = bitsPerPixel / 8;
     uint32_t tiling = 0, flags = 0;
     struct radeon_surface surface;
-    struct radeon_bo *bo;
+    struct radeon_buffer *bo;
     int domain = RADEON_GEM_DOMAIN_VRAM;
     if (usage_hint) {
 	if (info->allowColorTiling) {
@@ -225,10 +225,15 @@ radeon_alloc_pixmap_bo(ScrnInfoPtr pScrn, int width, int height, int depth,
     if (tiling)
 	flags |= RADEON_GEM_NO_CPU_ACCESS;
 
-    bo = radeon_bo_open(info->bufmgr, 0, size, base_align,
-			domain, flags);
+    bo = calloc(1, sizeof(struct radeon_buffer));
+    if (!bo)
+	return NULL;
+
+    bo->ref_count = 1;
+    bo->bo.radeon = radeon_bo_open(info->bufmgr, 0, size, base_align,
+				   domain, flags);
 
-    if (bo && tiling && radeon_bo_set_tiling(bo, tiling, pitch) == 0)
+    if (bo && tiling && radeon_bo_set_tiling(bo->bo.radeon, tiling, pitch) == 0)
 	*new_tiling = tiling;
 
     *new_pitch = pitch;
@@ -238,10 +243,10 @@ radeon_alloc_pixmap_bo(ScrnInfoPtr pScrn, int width, int height, int depth,
 
 /* Flush and wait for the BO to become idle */
 void
-radeon_finish(ScrnInfoPtr scrn, struct radeon_bo *bo)
+radeon_finish(ScrnInfoPtr scrn, struct radeon_buffer *bo)
 {
     radeon_cs_flush_indirect(scrn);
-    radeon_bo_wait(bo);
+    radeon_bo_wait(bo->bo.radeon);
 }
 
 
@@ -269,7 +274,7 @@ radeon_pixmap_clear(PixmapPtr pixmap)
 /* Get GEM handle for the pixmap */
 Bool radeon_get_pixmap_handle(PixmapPtr pixmap, uint32_t *handle)
 {
-    struct radeon_bo *bo = radeon_get_pixmap_bo(pixmap);
+    struct radeon_buffer *bo = radeon_get_pixmap_bo(pixmap);
 #ifdef USE_GLAMOR
     ScreenPtr screen = pixmap->drawable.pScreen;
     ScrnInfoPtr scrn = xf86ScreenToScrn(screen);
@@ -278,7 +283,7 @@ Bool radeon_get_pixmap_handle(PixmapPtr pixmap, uint32_t *handle)
 #endif
 
     if (bo) {
-	*handle = bo->handle;
+	*handle = bo->bo.radeon->handle;
 	return TRUE;
     }
 
@@ -366,15 +371,20 @@ Bool radeon_set_shared_pixmap_backing(PixmapPtr ppix, void *fd_handle,
 {
     ScrnInfoPtr pScrn = xf86ScreenToScrn(ppix->drawable.pScreen);
     RADEONInfoPtr info = RADEONPTR(pScrn);
-    struct radeon_bo *bo;
+    struct radeon_buffer *bo;
     int ihandle = (int)(long)fd_handle;
     uint32_t size = ppix->devKind * ppix->drawable.height;
     Bool ret = FALSE;
 
-    bo = radeon_gem_bo_open_prime(info->bufmgr, ihandle, size);
+    bo = (struct radeon_buffer *)calloc(1, sizeof(struct radeon_buffer));
+    if (!bo)
+	goto error;
+
+    bo->bo.radeon = radeon_gem_bo_open_prime(info->bufmgr, ihandle, size);
     if (!bo)
         goto error;
 
+    bo->ref_count = 1;
     ret = radeon_set_pixmap_bo(ppix, bo);
     if (!ret)
 	goto error;
@@ -404,6 +414,6 @@ Bool radeon_set_shared_pixmap_backing(PixmapPtr ppix, void *fd_handle,
     close(ihandle);
     /* we have a reference from the alloc and one from set pixmap bo,
        drop one */
-    radeon_bo_unref(bo);
+    radeon_buffer_unref(&bo);
     return ret;
 }
diff --git a/src/radeon_bo_helper.h b/src/radeon_bo_helper.h
index fa99201b..53af87c3 100644
--- a/src/radeon_bo_helper.h
+++ b/src/radeon_bo_helper.h
@@ -23,13 +23,22 @@
 #ifndef RADEON_BO_HELPER_H
 #define RADEON_BO_HELPER_H 1
 
-extern struct radeon_bo*
+#define RADEON_BO_FLAGS_GBM	0x1
+
+struct radeon_buffer {
+	union {
+		struct radeon_bo *radeon;
+	} bo;
+	uint32_t ref_count;
+};
+
+extern struct radeon_buffer *
 radeon_alloc_pixmap_bo(ScrnInfoPtr pScrn, int width, int height, int depth,
 		       int usage_hint, int bitsPerPixel, int *new_pitch,
 		       struct radeon_surface *new_surface, uint32_t *new_tiling);
 
 extern void
-radeon_finish(ScrnInfoPtr scrn, struct radeon_bo *bo);
+radeon_finish(ScrnInfoPtr scrn, struct radeon_buffer *bo);
 
 extern void
 radeon_pixmap_clear(PixmapPtr pixmap);
@@ -60,4 +69,29 @@ static inline PixmapPtr get_drawable_pixmap(DrawablePtr drawable)
 	return drawable->pScreen->GetWindowPixmap((WindowPtr)drawable);
 }
 
+static inline void
+radeon_buffer_ref(struct radeon_buffer *buffer)
+{
+    buffer->ref_count++;
+}
+
+static inline void
+radeon_buffer_unref(struct radeon_buffer **buffer)
+{
+    struct radeon_buffer *buf = *buffer;
+
+    if (!buf)
+	return;
+
+    if (buf->ref_count > 1) {
+	buf->ref_count--;
+	return;
+    }
+
+    radeon_bo_unmap(buf->bo.radeon);
+    radeon_bo_unref(buf->bo.radeon);
+    free(buf);
+    *buffer = NULL;
+}
+
 #endif /* RADEON_BO_HELPER_H */
diff --git a/src/radeon_dri2.c b/src/radeon_dri2.c
index 6f469127..584a1d9d 100644
--- a/src/radeon_dri2.c
+++ b/src/radeon_dri2.c
@@ -79,7 +79,7 @@ static DevPrivateKeyRec dri2_window_private_key_rec;
 static Bool
 radeon_get_flink_name(RADEONEntPtr pRADEONEnt, PixmapPtr pixmap, uint32_t *name)
 {
-    struct radeon_bo *bo = radeon_get_pixmap_bo(pixmap);
+    struct radeon_bo *bo = radeon_get_pixmap_bo(pixmap)->bo.radeon;
     struct drm_gem_flink flink;
 
     if (bo)
@@ -719,7 +719,7 @@ radeon_dri2_exchange_buffers(DrawablePtr draw, DRI2BufferPtr front, DRI2BufferPt
 {
     struct dri2_buffer_priv *front_priv = front->driverPrivate;
     struct dri2_buffer_priv *back_priv = back->driverPrivate;
-    struct radeon_bo *front_bo, *back_bo;
+    struct radeon_buffer *front_buffer, *back_buffer;
     ScreenPtr screen;
     RADEONInfoPtr info;
     RegionRec region;
@@ -737,19 +737,19 @@ radeon_dri2_exchange_buffers(DrawablePtr draw, DRI2BufferPtr front, DRI2BufferPt
     back->name = tmp;
 
     /* Swap pixmap bos */
-    front_bo = radeon_get_pixmap_bo(front_priv->pixmap);
-    back_bo = radeon_get_pixmap_bo(back_priv->pixmap);
-    radeon_set_pixmap_bo(front_priv->pixmap, back_bo);
-    radeon_set_pixmap_bo(back_priv->pixmap, front_bo);
+    front_buffer = radeon_get_pixmap_bo(front_priv->pixmap);
+    back_buffer = radeon_get_pixmap_bo(back_priv->pixmap);
+    radeon_set_pixmap_bo(front_priv->pixmap, back_buffer);
+    radeon_set_pixmap_bo(back_priv->pixmap, front_buffer);
 
     /* Do we need to update the Screen? */
     screen = draw->pScreen;
     info = RADEONPTR(xf86ScreenToScrn(screen));
-    if (front_bo == info->front_bo) {
-	radeon_bo_ref(back_bo);
-	radeon_bo_unref(info->front_bo);
-	info->front_bo = back_bo;
-	radeon_set_pixmap_bo(screen->GetScreenPixmap(screen), back_bo);
+    if (front_buffer == info->front_buffer) {
+	radeon_buffer_ref(back_buffer);
+	radeon_buffer_unref(&info->front_buffer);
+	info->front_buffer = back_buffer;
+	radeon_set_pixmap_bo(screen->GetScreenPixmap(screen), back_buffer);
     }
 
     radeon_glamor_exchange_buffers(front_priv->pixmap, back_priv->pixmap);
diff --git a/src/radeon_dri3.c b/src/radeon_dri3.c
index 3e689ffd..b199c793 100644
--- a/src/radeon_dri3.c
+++ b/src/radeon_dri3.c
@@ -214,7 +214,7 @@ static int radeon_dri3_fd_from_pixmap(ScreenPtr screen,
 	struct radeon_bo *bo;
 	int fd;
 
-	bo = radeon_get_pixmap_bo(pixmap);
+	bo = radeon_get_pixmap_bo(pixmap)->bo.radeon;
 	if (!bo) {
 #ifdef USE_GLAMOR
 		ScrnInfoPtr scrn = xf86ScreenToScrn(screen);
@@ -225,7 +225,7 @@ static int radeon_dri3_fd_from_pixmap(ScreenPtr screen,
 #endif
 
 		exaMoveInPixmap(pixmap);
-		bo = radeon_get_pixmap_bo(pixmap);
+		bo = radeon_get_pixmap_bo(pixmap)->bo.radeon;
 		if (!bo)
 			return -1;
 	}
diff --git a/src/radeon_exa.c b/src/radeon_exa.c
index ef60bc0c..90d92d7b 100644
--- a/src/radeon_exa.c
+++ b/src/radeon_exa.c
@@ -184,11 +184,11 @@ Bool RADEONPrepareAccess_CS(PixmapPtr pPix, int index)
 	return FALSE;
 
     /* if we have more refs than just the BO then flush */
-    if (radeon_bo_is_referenced_by_cs(driver_priv->bo, info->cs)) {
+    if (radeon_bo_is_referenced_by_cs(driver_priv->bo->bo.radeon, info->cs)) {
 	flush = TRUE;
 
 	if (can_fail) {
-	    possible_domains = radeon_bo_get_src_domain(driver_priv->bo);
+	    possible_domains = radeon_bo_get_src_domain(driver_priv->bo->bo.radeon);
 	    if (possible_domains == RADEON_GEM_DOMAIN_VRAM)
 		return FALSE; /* use DownloadFromScreen */
 	}
@@ -196,7 +196,7 @@ Bool RADEONPrepareAccess_CS(PixmapPtr pPix, int index)
 
     /* if the BO might end up in VRAM, prefer DownloadFromScreen */
     if (can_fail && (possible_domains & RADEON_GEM_DOMAIN_VRAM)) {
-	radeon_bo_is_busy(driver_priv->bo, &current_domain);
+	radeon_bo_is_busy(driver_priv->bo->bo.radeon, &current_domain);
 
 	if (current_domain & possible_domains) {
 	    if (current_domain == RADEON_GEM_DOMAIN_VRAM)
@@ -209,14 +209,14 @@ Bool RADEONPrepareAccess_CS(PixmapPtr pPix, int index)
         radeon_cs_flush_indirect(pScrn);
     
     /* flush IB */
-    ret = radeon_bo_map(driver_priv->bo, 1);
+    ret = radeon_bo_map(driver_priv->bo->bo.radeon, 1);
     if (ret) {
       FatalError("failed to map pixmap %d\n", ret);
       return FALSE;
     }
     driver_priv->bo_mapped = TRUE;
 
-    pPix->devPrivate.ptr = driver_priv->bo->ptr;
+    pPix->devPrivate.ptr = driver_priv->bo->bo.radeon->ptr;
 
     return TRUE;
 }
@@ -229,7 +229,7 @@ void RADEONFinishAccess_CS(PixmapPtr pPix, int index)
     if (!driver_priv || !driver_priv->bo_mapped)
         return;
 
-    radeon_bo_unmap(driver_priv->bo);
+    radeon_bo_unmap(driver_priv->bo->bo.radeon);
     driver_priv->bo_mapped = FALSE;
     pPix->devPrivate.ptr = NULL;
 }
@@ -277,8 +277,7 @@ void RADEONEXADestroyPixmap(ScreenPtr pScreen, void *driverPriv)
     if (!driverPriv)
       return;
 
-    if (driver_priv->bo)
-	radeon_bo_unref(driver_priv->bo);
+    radeon_buffer_unref(&driver_priv->bo);
     drmmode_fb_reference(pRADEONEnt->fd, &driver_priv->fb, NULL);
     free(driverPriv);
 }
@@ -287,7 +286,7 @@ Bool RADEONEXASharePixmapBacking(PixmapPtr ppix, ScreenPtr slave, void **fd_hand
 {
     struct radeon_exa_pixmap_priv *driver_priv = exaGetPixmapDriverPrivate(ppix);
 
-    if (!radeon_share_pixmap_backing(driver_priv->bo, fd_handle))
+    if (!radeon_share_pixmap_backing(driver_priv->bo->bo.radeon, fd_handle))
 	return FALSE;
 
     driver_priv->shared = TRUE;
diff --git a/src/radeon_exa_funcs.c b/src/radeon_exa_funcs.c
index add89458..819b4258 100644
--- a/src/radeon_exa_funcs.c
+++ b/src/radeon_exa_funcs.c
@@ -138,7 +138,8 @@ RADEONPrepareSolid(PixmapPtr pPix, int alu, Pixel pm, Pixel fg)
     radeon_cs_space_reset_bos(info->cs);
 
     driver_priv = exaGetPixmapDriverPrivate(pPix);
-    radeon_cs_space_add_persistent_bo(info->cs, driver_priv->bo, 0, RADEON_GEM_DOMAIN_VRAM);
+    radeon_cs_space_add_persistent_bo(info->cs, driver_priv->bo->bo.radeon, 0,
+				      RADEON_GEM_DOMAIN_VRAM);
 
     ret = radeon_cs_space_check(info->cs);
     if (ret)
@@ -146,7 +147,7 @@ RADEONPrepareSolid(PixmapPtr pPix, int alu, Pixel pm, Pixel fg)
 
     driver_priv = exaGetPixmapDriverPrivate(pPix);
     if (driver_priv) {
-	info->state_2d.dst_bo = driver_priv->bo;
+	info->state_2d.dst_bo = driver_priv->bo->bo.radeon;
  	info->state_2d.dst_domain = driver_priv->shared ? RADEON_GEM_DOMAIN_GTT : RADEON_GEM_DOMAIN_VRAM;
     }
 
@@ -256,13 +257,15 @@ RADEONPrepareCopy(PixmapPtr pSrc,   PixmapPtr pDst,
     radeon_cs_space_reset_bos(info->cs);
 
     driver_priv = exaGetPixmapDriverPrivate(pSrc);
-    radeon_cs_space_add_persistent_bo(info->cs, driver_priv->bo, RADEON_GEM_DOMAIN_GTT | RADEON_GEM_DOMAIN_VRAM, 0);
-    info->state_2d.src_bo = driver_priv->bo;
+    radeon_cs_space_add_persistent_bo(info->cs, driver_priv->bo->bo.radeon,
+				      RADEON_GEM_DOMAIN_GTT | RADEON_GEM_DOMAIN_VRAM, 0);
+    info->state_2d.src_bo = driver_priv->bo->bo.radeon;
 
     driver_priv = exaGetPixmapDriverPrivate(pDst);
-    info->state_2d.dst_bo = driver_priv->bo;
+    info->state_2d.dst_bo = driver_priv->bo->bo.radeon;
     info->state_2d.dst_domain = driver_priv->shared ? RADEON_GEM_DOMAIN_GTT : RADEON_GEM_DOMAIN_VRAM;
-    radeon_cs_space_add_persistent_bo(info->cs, driver_priv->bo, 0, info->state_2d.dst_domain);
+    radeon_cs_space_add_persistent_bo(info->cs, driver_priv->bo->bo.radeon, 0,
+				      info->state_2d.dst_domain);
 
     ret = radeon_cs_space_check(info->cs);
     if (ret)
@@ -389,7 +392,7 @@ RADEONUploadToScreenCS(PixmapPtr pDst, int x, int y, int w, int h,
 	return FALSE;
 
     driver_priv = exaGetPixmapDriverPrivate(pDst);
-    if (!driver_priv || !driver_priv->bo)
+    if (!driver_priv || !driver_priv->bo->bo.radeon)
 	return FALSE;
 
 #if X_BYTE_ORDER == X_BIG_ENDIAN
@@ -404,12 +407,12 @@ RADEONUploadToScreenCS(PixmapPtr pDst, int x, int y, int w, int h,
 #endif
 
     /* If we know the BO won't be busy / in VRAM, don't bother with a scratch */
-    copy_dst = driver_priv->bo;
+    copy_dst = driver_priv->bo->bo.radeon;
     copy_pitch = pDst->devKind;
     if (!(driver_priv->tiling_flags & (RADEON_TILING_MACRO | RADEON_TILING_MICRO))) {
-	if (!radeon_bo_is_referenced_by_cs(driver_priv->bo, info->cs)) {
+	if (!radeon_bo_is_referenced_by_cs(driver_priv->bo->bo.radeon, info->cs)) {
 	    flush = FALSE;
-	    if (!radeon_bo_is_busy(driver_priv->bo, &dst_domain) &&
+	    if (!radeon_bo_is_busy(driver_priv->bo->bo.radeon, &dst_domain) &&
 		!(dst_domain & RADEON_GEM_DOMAIN_VRAM))
 		goto copy;
 	}
@@ -446,7 +449,7 @@ copy:
     r = TRUE;
     size = w * bpp / 8;
     dst = copy_dst->ptr;
-    if (copy_dst == driver_priv->bo)
+    if (copy_dst == driver_priv->bo->bo.radeon)
 	dst += y * copy_pitch + x * bpp / 8;
     for (i = 0; i < h; i++) {
         RADEONCopySwap(dst + i * copy_pitch, (uint8_t*)src, size, swap);
@@ -458,7 +461,7 @@ copy:
 	RADEONGetDatatypeBpp(pDst->drawable.bitsPerPixel, &datatype);
 	RADEONGetPixmapOffsetPitch(pDst, &dst_pitch_offset);
 	RADEON_SWITCH_TO_2D();
-	RADEONBlitChunk(pScrn, scratch, driver_priv->bo, datatype, scratch_pitch << 16,
+	RADEONBlitChunk(pScrn, scratch, driver_priv->bo->bo.radeon, datatype, scratch_pitch << 16,
 			dst_pitch_offset, 0, 0, x, y, w, h,
 			RADEON_GEM_DOMAIN_GTT, RADEON_GEM_DOMAIN_VRAM);
     }
@@ -493,7 +496,7 @@ RADEONDownloadFromScreenCS(PixmapPtr pSrc, int x, int y, int w,
 	return FALSE;
 
     driver_priv = exaGetPixmapDriverPrivate(pSrc);
-    if (!driver_priv || !driver_priv->bo)
+    if (!driver_priv || !driver_priv->bo->bo.radeon)
 	return FALSE;
 
 #if X_BYTE_ORDER == X_BIG_ENDIAN
@@ -508,11 +511,11 @@ RADEONDownloadFromScreenCS(PixmapPtr pSrc, int x, int y, int w,
 #endif
 
     /* If we know the BO won't end up in VRAM anyway, don't bother with a scratch */
-    copy_src = driver_priv->bo;
+    copy_src = driver_priv->bo->bo.radeon;
     copy_pitch = pSrc->devKind;
     if (!(driver_priv->tiling_flags & (RADEON_TILING_MACRO | RADEON_TILING_MICRO))) {
-	if (radeon_bo_is_referenced_by_cs(driver_priv->bo, info->cs)) {
-	    src_domain = radeon_bo_get_src_domain(driver_priv->bo);
+	if (radeon_bo_is_referenced_by_cs(driver_priv->bo->bo.radeon, info->cs)) {
+	    src_domain = radeon_bo_get_src_domain(driver_priv->bo->bo.radeon);
 	    if ((src_domain & (RADEON_GEM_DOMAIN_GTT | RADEON_GEM_DOMAIN_VRAM)) ==
 		(RADEON_GEM_DOMAIN_GTT | RADEON_GEM_DOMAIN_VRAM))
 		src_domain = 0;
@@ -521,7 +524,7 @@ RADEONDownloadFromScreenCS(PixmapPtr pSrc, int x, int y, int w,
 	}
 
 	if (!src_domain)
-	    radeon_bo_is_busy(driver_priv->bo, &src_domain);
+	    radeon_bo_is_busy(driver_priv->bo->bo.radeon, &src_domain);
 
 	if (src_domain & ~(uint32_t)RADEON_GEM_DOMAIN_VRAM)
 	    goto copy;
@@ -541,8 +544,8 @@ RADEONDownloadFromScreenCS(PixmapPtr pSrc, int x, int y, int w,
     RADEONGetDatatypeBpp(pSrc->drawable.bitsPerPixel, &datatype);
     RADEONGetPixmapOffsetPitch(pSrc, &src_pitch_offset);
     RADEON_SWITCH_TO_2D();
-    RADEONBlitChunk(pScrn, driver_priv->bo, scratch, datatype, src_pitch_offset,
-                    scratch_pitch << 16, x, y, 0, 0, w, h,
+    RADEONBlitChunk(pScrn, driver_priv->bo->bo.radeon, scratch, datatype,
+		    src_pitch_offset, scratch_pitch << 16, x, y, 0, 0, w, h,
                     RADEON_GEM_DOMAIN_VRAM | RADEON_GEM_DOMAIN_GTT,
                     RADEON_GEM_DOMAIN_GTT);
     copy_src = scratch;
@@ -561,7 +564,7 @@ copy:
     }
     r = TRUE;
     w *= bpp / 8;
-    if (copy_src == driver_priv->bo)
+    if (copy_src == driver_priv->bo->bo.radeon)
 	size = y * copy_pitch + x * bpp / 8;
     else
 	size = 0;
diff --git a/src/radeon_exa_shared.c b/src/radeon_exa_shared.c
index cca1c67e..94238a5a 100644
--- a/src/radeon_exa_shared.c
+++ b/src/radeon_exa_shared.c
@@ -129,7 +129,7 @@ PixmapPtr RADEONSolidPixmap(ScreenPtr pScreen, uint32_t solid)
     struct radeon_bo *bo;
     exaMoveInPixmap(pPix);
 
-    bo = radeon_get_pixmap_bo(pPix);
+    bo = radeon_get_pixmap_bo(pPix)->bo.radeon;
 
     if (radeon_bo_map(bo, 1)) {
 	pScreen->DestroyPixmap(pPix);
diff --git a/src/radeon_exa_shared.h b/src/radeon_exa_shared.h
index 3df7fa20..fe28c230 100644
--- a/src/radeon_exa_shared.h
+++ b/src/radeon_exa_shared.h
@@ -66,7 +66,8 @@ static inline void radeon_add_pixmap(struct radeon_cs *cs, PixmapPtr pPix, int r
 {
     struct radeon_exa_pixmap_priv *driver_priv = exaGetPixmapDriverPrivate(pPix);
 
-    radeon_cs_space_add_persistent_bo(cs, driver_priv->bo, read_domains, write_domain);
+    radeon_cs_space_add_persistent_bo(cs, driver_priv->bo->bo.radeon,
+				      read_domains, write_domain);
 }
 
 extern void radeon_ib_discard(ScrnInfoPtr pScrn);
diff --git a/src/radeon_glamor.c b/src/radeon_glamor.c
index 6cff72e1..c1d96160 100644
--- a/src/radeon_glamor.c
+++ b/src/radeon_glamor.c
@@ -62,7 +62,7 @@ radeon_glamor_create_screen_resources(ScreenPtr screen)
 #endif
 
 	if (!glamor_egl_create_textured_screen(screen,
-					       info->front_bo->handle,
+					       info->front_buffer->bo.radeon->handle,
 					       scrn->displayWidth *
 					       info->pixel_bytes))
 		return FALSE;
@@ -166,7 +166,7 @@ radeon_glamor_pre_init(ScrnInfoPtr scrn)
 Bool
 radeon_glamor_create_textured_pixmap(PixmapPtr pixmap, struct radeon_pixmap *priv)
 {
-	return glamor_egl_create_textured_pixmap(pixmap, priv->bo->handle,
+	return glamor_egl_create_textured_pixmap(pixmap, priv->bo->bo.radeon->handle,
 						 pixmap->devKind);
 }
 
@@ -180,10 +180,10 @@ static Bool radeon_glamor_destroy_pixmap(PixmapPtr pixmap)
 
 	if (pixmap->refcnt == 1) {
 		if (pixmap->devPrivate.ptr) {
-			struct radeon_bo *bo = radeon_get_pixmap_bo(pixmap);
+			struct radeon_buffer *bo = radeon_get_pixmap_bo(pixmap);
 
 			if (bo)
-				radeon_bo_unmap(bo);
+				radeon_bo_unmap(bo->bo.radeon);
 		}
 
 #ifdef HAVE_GLAMOR_EGL_DESTROY_TEXTURED_PIXMAP
@@ -289,7 +289,7 @@ fallback_glamor:
 	 * afterwards.
 	 */
 	new_pixmap = glamor_create_pixmap(screen, w, h,	depth, usage);
-	radeon_bo_unref(priv->bo);
+	radeon_buffer_unref(&priv->bo);
 fallback_priv:
 	free(priv);
 fallback_pixmap:
diff --git a/src/radeon_glamor_wrappers.c b/src/radeon_glamor_wrappers.c
index 94700a7b..79d98cc7 100644
--- a/src/radeon_glamor_wrappers.c
+++ b/src/radeon_glamor_wrappers.c
@@ -55,7 +55,7 @@ radeon_glamor_prepare_access_cpu(ScrnInfoPtr scrn, RADEONInfoPtr info,
 				 PixmapPtr pixmap, struct radeon_pixmap *priv,
 				 Bool need_sync)
 {
-	struct radeon_bo *bo = priv->bo;
+	struct radeon_buffer *bo = priv->bo;
 	int ret;
 
 	if (!pixmap->devPrivate.ptr) {
@@ -65,7 +65,7 @@ radeon_glamor_prepare_access_cpu(ScrnInfoPtr scrn, RADEONInfoPtr info,
 			info->gpu_flushed++;
 		}
 
-		ret = radeon_bo_map(bo, 1);
+		ret = radeon_bo_map(bo->bo.radeon, 1);
 		if (ret) {
 			xf86DrvMsg(scrn->scrnIndex, X_WARNING,
 				   "%s: bo map (tiling_flags %d) failed: %s\n",
@@ -75,7 +75,7 @@ radeon_glamor_prepare_access_cpu(ScrnInfoPtr scrn, RADEONInfoPtr info,
 			return FALSE;
 		}
 
-		pixmap->devPrivate.ptr = bo->ptr;
+		pixmap->devPrivate.ptr = bo->bo.radeon->ptr;
 	} else if (need_sync)
 		radeon_finish(scrn, bo);
 
diff --git a/src/radeon_kms.c b/src/radeon_kms.c
index d4b59e81..d3eeebea 100644
--- a/src/radeon_kms.c
+++ b/src/radeon_kms.c
@@ -254,7 +254,7 @@ radeonShadowWindow(ScreenPtr screen, CARD32 row, CARD32 offset, int mode,
     stride = (pScrn->displayWidth * pScrn->bitsPerPixel) / 8;
     *size = stride;
 
-    return ((uint8_t *)info->front_bo->ptr + row * stride + offset);
+    return ((uint8_t *)info->front_buffer->bo.radeon->ptr + row * stride + offset);
 }
 
 static void
@@ -359,9 +359,9 @@ static Bool RADEONCreateScreenResources_KMS(ScreenPtr pScreen)
     }
 
     if (info->dri2.enabled || info->use_glamor) {
-	if (info->front_bo) {
+	if (info->front_buffer) {
 	    PixmapPtr pPix = pScreen->GetScreenPixmap(pScreen);
-	    if (!radeon_set_pixmap_bo(pPix, info->front_bo))
+	    if (!radeon_set_pixmap_bo(pPix, info->front_buffer))
 		return FALSE;
 
 	    if (info->surf_man && !info->use_glamor)
@@ -1681,7 +1681,7 @@ void RADEONWindowExposures_oneshot(WindowPtr pWin, RegionPtr pRegion
     pScreen->WindowExposures(pWin, pRegion);
 #endif
 
-    radeon_finish(pScrn, info->front_bo);
+    radeon_finish(pScrn, info->front_buffer);
     drmmode_set_desired_modes(pScrn, &info->drmmode, TRUE);
 }
 
@@ -2269,7 +2269,7 @@ Bool RADEONScreenInit_KMS(ScreenPtr pScreen, int argc, char **argv)
 	xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "radeon_setup_kernel_mem failed\n");
 	return FALSE;
     }
-    front_ptr = info->front_bo->ptr;
+    front_ptr = info->front_buffer->bo.radeon->ptr;
 
     if (info->r600_shadow_fb) {
 	info->fb_shadow = calloc(1,
@@ -2478,15 +2478,17 @@ Bool RADEONEnterVT_KMS(ScrnInfoPtr pScrn)
     if (info->r600_shadow_fb) {
 	int base_align = drmmode_get_base_align(pScrn, info->pixel_bytes, 0);
 	struct radeon_bo *front_bo = radeon_bo_open(info->bufmgr, 0,
-						    info->front_bo->size,
+						    pScrn->displayWidth *
+						    info->pixel_bytes *
+						    pScrn->virtualY,
 						    base_align,
 						    RADEON_GEM_DOMAIN_VRAM, 0);
 
 	if (front_bo) {
 	    if (radeon_bo_map(front_bo, 1) == 0) {
 		memset(front_bo->ptr, 0, front_bo->size);
-		radeon_bo_unref(info->front_bo);
-		info->front_bo = front_bo;
+		radeon_bo_unref(info->front_buffer->bo.radeon);
+		info->front_buffer->bo.radeon = front_bo;
 	    } else {
 		radeon_bo_unref(front_bo);
 		front_bo = NULL;
@@ -2633,7 +2635,8 @@ void RADEONLeaveVT_KMS(ScrnInfoPtr pScrn)
 
 	pixmap_unref_fb(pScreen->GetScreenPixmap(pScreen), None, pRADEONEnt);
     } else {
-	memset(info->front_bo->ptr, 0, info->front_bo->size);
+	memset(info->front_buffer->bo.radeon->ptr, 0,
+	       pScrn->displayWidth * info->pixel_bytes * pScrn->virtualY);
     }
 
     TimerSet(NULL, 0, 1000, cleanup_black_fb, pScreen);
@@ -2671,10 +2674,8 @@ static Bool radeon_setup_kernel_mem(ScreenPtr pScreen)
     RADEONInfoPtr info = RADEONPTR(pScrn);
     xf86CrtcConfigPtr   xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
     int cpp = info->pixel_bytes;
-    uint32_t screen_size;
-    int pitch, base_align;
+    int pitch;
     uint32_t tiling_flags = 0;
-    struct radeon_surface surface;
 
     if (info->accel_state->exa != NULL) {
 	xf86DrvMsg(pScreen->myNum, X_ERROR, "Memory map already initialized\n");
@@ -2688,50 +2689,6 @@ static Bool radeon_setup_kernel_mem(ScreenPtr pScreen)
 	}
     }
 
-    if (info->allowColorTiling && !info->shadow_primary) {
-	if (info->ChipFamily >= CHIP_FAMILY_R600) {
-		if (info->allowColorTiling2D) {
-			tiling_flags |= RADEON_TILING_MACRO;
-		} else {
-			tiling_flags |= RADEON_TILING_MICRO;
-		}
-	} else
-	    tiling_flags |= RADEON_TILING_MACRO;
-    }
-    pitch = RADEON_ALIGN(pScrn->virtualX, drmmode_get_pitch_align(pScrn, cpp, tiling_flags)) * cpp;
-    screen_size = RADEON_ALIGN(pScrn->virtualY, drmmode_get_height_align(pScrn, tiling_flags)) * pitch;
-    base_align = drmmode_get_base_align(pScrn, cpp, tiling_flags);
-	if (info->surf_man) {
-		if (!radeon_surface_initialize(info, &surface, pScrn->virtualX,
-					       pScrn->virtualY, cpp,
-					       tiling_flags, 0)) {
-			xf86DrvMsg(pScreen->myNum, X_ERROR,
-				   "radeon_surface_initialize failed\n");
-			return FALSE;
-		}
-		pitch = surface.level[0].pitch_bytes;
-		screen_size = surface.bo_size;
-		base_align = surface.bo_alignment;
-		tiling_flags = 0;
-		switch (surface.level[0].mode) {
-		case RADEON_SURF_MODE_2D:
-			tiling_flags |= RADEON_TILING_MACRO;
-			tiling_flags |= surface.bankw << RADEON_TILING_EG_BANKW_SHIFT;
-			tiling_flags |= surface.bankh << RADEON_TILING_EG_BANKH_SHIFT;
-			tiling_flags |= surface.mtilea << RADEON_TILING_EG_MACRO_TILE_ASPECT_SHIFT;
-			if (surface.tile_split)
-				tiling_flags |= eg_tile_split(surface.tile_split)
-						<< RADEON_TILING_EG_TILE_SPLIT_SHIFT;
-			break;
-		case RADEON_SURF_MODE_1D:
-			tiling_flags |= RADEON_TILING_MICRO;
-			break;
-		default:
-			break;
-		}
-		if (!info->use_glamor)
-		    info->front_surface = surface;
-	}
     {
 	int cursor_size;
 	int c;
@@ -2758,17 +2715,27 @@ static Bool radeon_setup_kernel_mem(ScreenPtr pScreen)
         }
     }
 
-    screen_size = RADEON_ALIGN(screen_size, RADEON_GPU_PAGE_SIZE);
+    if (info->front_buffer == NULL) {
+	int usage = CREATE_PIXMAP_USAGE_BACKING_PIXMAP;
+
+	if (info->allowColorTiling && !info->shadow_primary) {
+	    if (info->ChipFamily < CHIP_FAMILY_R600 || info->allowColorTiling2D)
+		usage |= RADEON_CREATE_PIXMAP_TILING_MACRO;
+	    else
+		usage |= RADEON_CREATE_PIXMAP_TILING_MICRO;
+	}
+
+        info->front_buffer = radeon_alloc_pixmap_bo(pScrn, pScrn->virtualX,
+						    pScrn->virtualY,
+						    pScrn->depth,
+						    usage,
+						    pScrn->bitsPerPixel,
+						    &pitch,
+						    &info->front_surface,
+						    &tiling_flags);
 
-    if (info->front_bo == NULL) {
-        info->front_bo = radeon_bo_open(info->bufmgr, 0, screen_size,
-                                        base_align,
-                                        info->shadow_primary ?
-                                        RADEON_GEM_DOMAIN_GTT :
-                                        RADEON_GEM_DOMAIN_VRAM,
-                                        tiling_flags ? RADEON_GEM_NO_CPU_ACCESS : 0);
         if (info->r600_shadow_fb == TRUE) {
-            if (radeon_bo_map(info->front_bo, 1)) {
+            if (radeon_bo_map(info->front_buffer->bo.radeon, 1)) {
                 ErrorF("Failed to map cursor buffer memory\n");
             }
         }
@@ -2786,13 +2753,14 @@ static Bool radeon_setup_kernel_mem(ScreenPtr pScreen)
 	    tiling_flags |= RADEON_TILING_SURFACE;
 #endif
 	if (tiling_flags)
-            radeon_bo_set_tiling(info->front_bo, tiling_flags, pitch);
+            radeon_bo_set_tiling(info->front_buffer->bo.radeon, tiling_flags, pitch);
     }
 
     pScrn->displayWidth = pitch / cpp;
 
-    xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Front buffer size: %dK\n", info->front_bo->size/1024);
-    radeon_kms_update_vram_limit(pScrn, screen_size);
+    xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Front buffer size: %dK\n",
+	       pitch * pScrn->virtualY / 1024);
+    radeon_kms_update_vram_limit(pScrn, pitch * pScrn->virtualY);
     return TRUE;
 }
 
diff --git a/src/radeon_present.c b/src/radeon_present.c
index 66805d7d..2982d728 100644
--- a/src/radeon_present.c
+++ b/src/radeon_present.c
@@ -422,7 +422,7 @@ radeon_present_unflip(ScreenPtr screen, uint64_t event_id)
 	return;
 
 modeset:
-    radeon_finish(scrn, info->front_bo);
+    radeon_finish(scrn, info->front_buffer);
     for (i = 0; i < config->num_crtc; i++) {
 	xf86CrtcPtr crtc = config->crtc[i];
 	drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
diff --git a/src/radeon_textured_videofuncs.c b/src/radeon_textured_videofuncs.c
index 653de44d..0959b119 100644
--- a/src/radeon_textured_videofuncs.c
+++ b/src/radeon_textured_videofuncs.c
@@ -63,10 +63,12 @@ RADEONPrepareTexturedVideo(ScrnInfoPtr pScrn, RADEONPortPrivPtr pPriv)
     radeon_cs_space_add_persistent_bo(info->cs, src_bo, RADEON_GEM_DOMAIN_GTT | RADEON_GEM_DOMAIN_VRAM, 0);
 
     if (pPriv->bicubic_enabled)
-	radeon_cs_space_add_persistent_bo(info->cs, info->bicubic_bo, RADEON_GEM_DOMAIN_GTT | RADEON_GEM_DOMAIN_VRAM, 0);
+	radeon_cs_space_add_persistent_bo(info->cs, info->bicubic_bo,
+					  RADEON_GEM_DOMAIN_GTT | RADEON_GEM_DOMAIN_VRAM, 0);
 
     driver_priv = exaGetPixmapDriverPrivate(pPixmap);
-    radeon_cs_space_add_persistent_bo(info->cs, driver_priv->bo, 0, RADEON_GEM_DOMAIN_VRAM);
+    radeon_cs_space_add_persistent_bo(info->cs, driver_priv->bo->bo.radeon, 0,
+				      RADEON_GEM_DOMAIN_VRAM);
 
     ret = radeon_cs_space_check(info->cs);
     if (ret) {
@@ -433,10 +435,12 @@ R200PrepareTexturedVideo(ScrnInfoPtr pScrn, RADEONPortPrivPtr pPriv)
     radeon_cs_space_add_persistent_bo(info->cs, src_bo, RADEON_GEM_DOMAIN_GTT | RADEON_GEM_DOMAIN_VRAM, 0);
 
     if (pPriv->bicubic_enabled)
-	radeon_cs_space_add_persistent_bo(info->cs, info->bicubic_bo, RADEON_GEM_DOMAIN_GTT | RADEON_GEM_DOMAIN_VRAM, 0);
+	radeon_cs_space_add_persistent_bo(info->cs, info->bicubic_bo,
+					  RADEON_GEM_DOMAIN_GTT | RADEON_GEM_DOMAIN_VRAM, 0);
 
     driver_priv = exaGetPixmapDriverPrivate(pPixmap);
-    radeon_cs_space_add_persistent_bo(info->cs, driver_priv->bo, 0, RADEON_GEM_DOMAIN_VRAM);
+    radeon_cs_space_add_persistent_bo(info->cs, driver_priv->bo->bo.radeon, 0,
+				      RADEON_GEM_DOMAIN_VRAM);
 
     ret = radeon_cs_space_check(info->cs);
     if (ret) {
@@ -958,10 +962,12 @@ R300PrepareTexturedVideo(ScrnInfoPtr pScrn, RADEONPortPrivPtr pPriv)
     radeon_cs_space_add_persistent_bo(info->cs, src_bo, RADEON_GEM_DOMAIN_GTT | RADEON_GEM_DOMAIN_VRAM, 0);
 
     if (pPriv->bicubic_enabled)
-	radeon_cs_space_add_persistent_bo(info->cs, info->bicubic_bo, RADEON_GEM_DOMAIN_GTT | RADEON_GEM_DOMAIN_VRAM, 0);
+	radeon_cs_space_add_persistent_bo(info->cs, info->bicubic_bo,
+					  RADEON_GEM_DOMAIN_GTT | RADEON_GEM_DOMAIN_VRAM, 0);
 
     driver_priv = exaGetPixmapDriverPrivate(pPixmap);
-    radeon_cs_space_add_persistent_bo(info->cs, driver_priv->bo, 0, RADEON_GEM_DOMAIN_VRAM);
+    radeon_cs_space_add_persistent_bo(info->cs, driver_priv->bo->bo.radeon, 0,
+				      RADEON_GEM_DOMAIN_VRAM);
 
     ret = radeon_cs_space_check(info->cs);
     if (ret) {
@@ -2376,10 +2382,12 @@ R500PrepareTexturedVideo(ScrnInfoPtr pScrn, RADEONPortPrivPtr pPriv)
     radeon_cs_space_add_persistent_bo(info->cs, src_bo, RADEON_GEM_DOMAIN_GTT | RADEON_GEM_DOMAIN_VRAM, 0);
 
     if (pPriv->bicubic_enabled)
-	radeon_cs_space_add_persistent_bo(info->cs, info->bicubic_bo, RADEON_GEM_DOMAIN_GTT | RADEON_GEM_DOMAIN_VRAM, 0);
+	radeon_cs_space_add_persistent_bo(info->cs, info->bicubic_bo,
+					  RADEON_GEM_DOMAIN_GTT | RADEON_GEM_DOMAIN_VRAM, 0);
     
     driver_priv = exaGetPixmapDriverPrivate(pPixmap);
-    radeon_cs_space_add_persistent_bo(info->cs, driver_priv->bo, 0, RADEON_GEM_DOMAIN_VRAM);
+    radeon_cs_space_add_persistent_bo(info->cs, driver_priv->bo->bo.radeon, 0,
+				      RADEON_GEM_DOMAIN_VRAM);
 
     ret = radeon_cs_space_check(info->cs);
     if (ret) {
commit 37ba075b34130c41bb7a2261bd666af5b29ffaf3
Author: Michel Dänzer <michel.daenzer at amd.com>
Date:   Fri Jun 15 18:23:53 2018 +0200

    Refactor radeon_finish helper
    
    Reviewed-by: Alex Deucher <alexander.deucher at amd.com>

diff --git a/src/drmmode_display.c b/src/drmmode_display.c
index 54b09730..3c4d94fd 100644
--- a/src/drmmode_display.c
+++ b/src/drmmode_display.c
@@ -726,8 +726,7 @@ drmmode_crtc_prime_scanout_update(xf86CrtcPtr crtc, DisplayModePtr mode,
 					  gc, 0, 0, mode->HDisplay, mode->VDisplay,
 					  0, 0);
 			FreeScratchGC(gc);
-			radeon_cs_flush_indirect(scrn);
-			radeon_bo_wait(drmmode_crtc->scanout[0].bo);
+			radeon_finish(scrn, drmmode_crtc->scanout[0].bo);
 		}
 	}
 
@@ -785,8 +784,7 @@ drmmode_crtc_scanout_update(xf86CrtcPtr crtc, DisplayModePtr mode,
 		radeon_scanout_do_update(crtc, scanout_id,
 					 screen->GetWindowPixmap(screen->root),
 					 *box);
-		radeon_cs_flush_indirect(scrn);
-		radeon_bo_wait(drmmode_crtc->scanout[scanout_id].bo);
+		radeon_finish(scrn, drmmode_crtc->scanout[scanout_id].bo);
 	}
 }
 
@@ -2240,7 +2238,6 @@ drmmode_xf86crtc_resize (ScrnInfoPtr scrn, int width, int height)
 	int aligned_height;
 	uint32_t screen_size;
 	int cpp = info->pixel_bytes;
-	struct radeon_bo *front_bo;
 	struct radeon_surface surface;
 	uint32_t tiling_flags = 0, base_align;
 	PixmapPtr ppix = screen->GetScreenPixmap(screen);
@@ -2249,12 +2246,6 @@ drmmode_xf86crtc_resize (ScrnInfoPtr scrn, int width, int height)
 	if (scrn->virtualX == width && scrn->virtualY == height)
 		return TRUE;
 
-	front_bo = info->front_bo;
-	radeon_cs_flush_indirect(scrn);
-
-	if (front_bo)
-		radeon_bo_wait(front_bo);
-
 	if (info->allowColorTiling && !info->shadow_primary) {
 		if (info->ChipFamily >= CHIP_FAMILY_R600) {
 			if (info->allowColorTiling2D) {
@@ -2364,8 +2355,7 @@ drmmode_xf86crtc_resize (ScrnInfoPtr scrn, int width, int height)
 	}
 
 	radeon_pixmap_clear(ppix);
-	radeon_cs_flush_indirect(scrn);
-	radeon_bo_wait(info->front_bo);
+	radeon_finish(scrn, info->front_bo);
 
 	for (i = 0; i < xf86_config->num_crtc; i++) {
 		xf86CrtcPtr crtc = xf86_config->crtc[i];
diff --git a/src/radeon.h b/src/radeon.h
index c2ae6606..499e89f9 100644
--- a/src/radeon.h
+++ b/src/radeon.h
@@ -895,6 +895,7 @@ radeon_pixmap_get_fb(PixmapPtr pix)
     return *fb_ptr;
 }
 
+
 #define CP_PACKET0(reg, n)						\
 	(RADEON_CP_PACKET0 | ((n) << 16) | ((reg) >> 2))
 #define CP_PACKET1(reg0, reg1)						\
diff --git a/src/radeon_bo_helper.c b/src/radeon_bo_helper.c
index 37658942..7cfe9126 100644
--- a/src/radeon_bo_helper.c
+++ b/src/radeon_bo_helper.c
@@ -235,6 +235,16 @@ radeon_alloc_pixmap_bo(ScrnInfoPtr pScrn, int width, int height, int depth,
     return bo;
 }
 
+
+/* Flush and wait for the BO to become idle */
+void
+radeon_finish(ScrnInfoPtr scrn, struct radeon_bo *bo)
+{
+    radeon_cs_flush_indirect(scrn);
+    radeon_bo_wait(bo);
+}
+
+
 /* Clear the pixmap contents to black */
 void
 radeon_pixmap_clear(PixmapPtr pixmap)
diff --git a/src/radeon_bo_helper.h b/src/radeon_bo_helper.h
index e1856adb..fa99201b 100644
--- a/src/radeon_bo_helper.h
+++ b/src/radeon_bo_helper.h
@@ -29,6 +29,9 @@ radeon_alloc_pixmap_bo(ScrnInfoPtr pScrn, int width, int height, int depth,
 		       struct radeon_surface *new_surface, uint32_t *new_tiling);
 
 extern void
+radeon_finish(ScrnInfoPtr scrn, struct radeon_bo *bo);
+
+extern void
 radeon_pixmap_clear(PixmapPtr pixmap);
 
 extern uint32_t
diff --git a/src/radeon_glamor_wrappers.c b/src/radeon_glamor_wrappers.c
index d7374252..94700a7b 100644
--- a/src/radeon_glamor_wrappers.c
+++ b/src/radeon_glamor_wrappers.c
@@ -58,13 +58,13 @@ radeon_glamor_prepare_access_cpu(ScrnInfoPtr scrn, RADEONInfoPtr info,
 	struct radeon_bo *bo = priv->bo;
 	int ret;
 
-	/* When falling back to swrast, flush all pending operations */
-	if (need_sync) {
-		glamor_block_handler(scrn->pScreen);
-		info->gpu_flushed++;
-	}
-
 	if (!pixmap->devPrivate.ptr) {
+		/* When falling back to swrast, flush all pending operations */
+		if (need_sync) {
+			glamor_block_handler(scrn->pScreen);
+			info->gpu_flushed++;
+		}
+
 		ret = radeon_bo_map(bo, 1);
 		if (ret) {
 			xf86DrvMsg(scrn->scrnIndex, X_WARNING,
@@ -76,11 +76,10 @@ radeon_glamor_prepare_access_cpu(ScrnInfoPtr scrn, RADEONInfoPtr info,
 		}
 
 		pixmap->devPrivate.ptr = bo->ptr;
-		info->gpu_synced = info->gpu_flushed;
-	} else if (need_sync) {
-		radeon_bo_wait(bo);
-		info->gpu_synced = info->gpu_flushed;
-	}
+	} else if (need_sync)
+		radeon_finish(scrn, bo);
+
+	info->gpu_synced = info->gpu_flushed;
 
 	return TRUE;
 }
diff --git a/src/radeon_kms.c b/src/radeon_kms.c
index 8579aaf8..d4b59e81 100644
--- a/src/radeon_kms.c
+++ b/src/radeon_kms.c
@@ -1681,8 +1681,7 @@ void RADEONWindowExposures_oneshot(WindowPtr pWin, RegionPtr pRegion
     pScreen->WindowExposures(pWin, pRegion);
 #endif
 
-    radeon_cs_flush_indirect(pScrn);
-    radeon_bo_wait(info->front_bo);
+    radeon_finish(pScrn, info->front_bo);
     drmmode_set_desired_modes(pScrn, &info->drmmode, TRUE);
 }
 
@@ -2585,8 +2584,7 @@ void RADEONLeaveVT_KMS(ScrnInfoPtr pScrn)
 		    radeon_pixmap_get_fb(black_scanout.pixmap);
 
 		radeon_pixmap_clear(black_scanout.pixmap);
-		radeon_cs_flush_indirect(pScrn);
-		radeon_bo_wait(black_scanout.bo);
+		radeon_finish(pScrn, black_scanout.bo);
 
 		for (i = 0; i < xf86_config->num_crtc; i++) {
 		    crtc = xf86_config->crtc[i];
diff --git a/src/radeon_present.c b/src/radeon_present.c
index d734b9d4..66805d7d 100644
--- a/src/radeon_present.c
+++ b/src/radeon_present.c
@@ -404,8 +404,6 @@ radeon_present_unflip(ScreenPtr screen, uint64_t event_id)
 	FLIP_ASYNC : FLIP_VSYNC;
     int i;
 
-    radeon_cs_flush_indirect(scrn);
-
     if (!radeon_present_check_unflip(scrn))
 	goto modeset;
 
@@ -424,7 +422,7 @@ radeon_present_unflip(ScreenPtr screen, uint64_t event_id)
 	return;
 
 modeset:
-    radeon_bo_wait(info->front_bo);
+    radeon_finish(scrn, info->front_bo);
     for (i = 0; i < config->num_crtc; i++) {
 	xf86CrtcPtr crtc = config->crtc[i];
 	drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
commit 6c986e997159ad0086f940294b244fc4c30b61fc
Author: Jammy Zhou <Jammy.Zhou at amd.com>
Date:   Fri Jun 15 18:41:34 2018 +0200

    Remove throttling from radeon_dri2_copy_region2
    
    Throttling should be handled by the client-side drivers.
    
    Signed-off-by: Jammy Zhou <Jammy.Zhou at amd.com>
    (Ported from amdgpu commit 8a34a8149860ac15e83ccdbd8d9a527d8d3e5997)
    Reviewed-by: Alex Deucher <alexander.deucher at amd.com>

diff --git a/src/radeon_dri2.c b/src/radeon_dri2.c
index 3b75f66f..6f469127 100644
--- a/src/radeon_dri2.c
+++ b/src/radeon_dri2.c
@@ -336,9 +336,7 @@ radeon_dri2_copy_region2(ScreenPtr pScreen,
     Bool vsync;
     Bool translate = FALSE;
     int off_x = 0, off_y = 0;
-    PixmapPtr dst_ppix;
 
-    dst_ppix = dst_private->pixmap;
     src_drawable = &src_private->pixmap->drawable;
     dst_drawable = &dst_private->pixmap->drawable;
 
@@ -355,7 +353,6 @@ radeon_dri2_copy_region2(ScreenPtr pScreen,
 	    dst_drawable = DRI2UpdatePrime(drawable, dest_buffer);
 	    if (!dst_drawable)
 		return;
-	    dst_ppix = (PixmapPtr)dst_drawable;
 	    if (dst_drawable != drawable)
 		translate = TRUE;
 	} else
@@ -379,26 +376,7 @@ radeon_dri2_copy_region2(ScreenPtr pScreen,
     (*gc->funcs->ChangeClip) (gc, CT_REGION, copy_clip, 0);
     ValidateGC(dst_drawable, gc);
 
-    /* If this is a full buffer swap or frontbuffer flush, throttle on the
-     * previous one
-     */
-    if (dst_private->attachment == DRI2BufferFrontLeft) {
-	if (REGION_NUM_RECTS(region) == 1) {
-	    BoxPtr extents = REGION_EXTENTS(pScreen, region);
-
-	    if (extents->x1 == 0 && extents->y1 == 0 &&
-		extents->x2 == drawable->width &&
-		extents->y2 == drawable->height) {
-		struct radeon_bo *bo = radeon_get_pixmap_bo(dst_ppix);
-
-		if (bo)
-		    radeon_bo_wait(bo);
-	    }
-	}
-    }
-
     vsync = info->accel_state->vsync;
-
     /* Driver option "SwapbuffersWait" defines if we vsync DRI2 copy-swaps. */ 
     info->accel_state->vsync = info->swapBuffersWait;
     info->accel_state->force = TRUE;
commit 90b94d40449f665f2d12874598062a5e5e5b64cd
Author: Michel Dänzer <michel.daenzer at amd.com>
Date:   Fri Jun 15 18:27:46 2018 +0200

    Move flush from radeon_scanout_do_update to its callers
    
    No functional change intended.
    
    Reviewed-by: Alex Deucher <alexander.deucher at amd.com>

diff --git a/src/drmmode_display.c b/src/drmmode_display.c
index c7bec59c..54b09730 100644
--- a/src/drmmode_display.c
+++ b/src/drmmode_display.c
@@ -785,6 +785,7 @@ drmmode_crtc_scanout_update(xf86CrtcPtr crtc, DisplayModePtr mode,
 		radeon_scanout_do_update(crtc, scanout_id,
 					 screen->GetWindowPixmap(screen->root),
 					 *box);
+		radeon_cs_flush_indirect(scrn);
 		radeon_bo_wait(drmmode_crtc->scanout[scanout_id].bo);
 	}
 }
@@ -3225,6 +3226,7 @@ Bool radeon_do_pageflip(ScrnInfoPtr scrn, ClientPtr client,
 
 			radeon_scanout_do_update(crtc, scanout_id, new_front,
 						 extents);
+			radeon_cs_flush_indirect(crtc->scrn);
 
 			drmmode_crtc_wait_pending_event(drmmode_crtc, pRADEONEnt->fd,
 							drmmode_crtc->scanout_update_pending);
diff --git a/src/radeon_kms.c b/src/radeon_kms.c
index 7ff66bf3..8579aaf8 100644
--- a/src/radeon_kms.c
+++ b/src/radeon_kms.c
@@ -985,8 +985,6 @@ radeon_scanout_do_update(xf86CrtcPtr xf86_crtc, int scanout_id,
 	FreeScratchGC(gc);
     }
 
-    radeon_cs_flush_indirect(scrn);
-
     info->accel_state->force = force;
 
     return TRUE;
@@ -1013,8 +1011,10 @@ radeon_scanout_update_handler(xf86CrtcPtr crtc, uint32_t frame, uint64_t usec,
 	drmmode_crtc->dpms_mode == DPMSModeOn) {
 	if (radeon_scanout_do_update(crtc, drmmode_crtc->scanout_id,
 				     screen->GetWindowPixmap(screen->root),
-				     region->extents))
+				     region->extents)) {
+	    radeon_cs_flush_indirect(crtc->scrn);
 	    RegionEmpty(region);
+	}
     }
 
     radeon_scanout_update_abort(crtc, event_data);
@@ -1096,6 +1096,8 @@ radeon_scanout_flip(ScreenPtr pScreen, RADEONInfoPtr info,
 				  pScreen->GetWindowPixmap(pScreen->root),
 				  region->extents))
 	return;
+
+    radeon_cs_flush_indirect(scrn);
     RegionEmpty(region);
 
     drm_queue_seq = radeon_drm_queue_alloc(xf86_crtc,
commit 5da2bf43e64f2d702fe05016263f617c10f8f134
Author: Michel Dänzer <michel.daenzer at amd.com>
Date:   Mon May 28 18:35:32 2018 +0200

    Factor out radeon_surface_initialize helper
    
    Reviewed-by: Alex Deucher <alexander.deucher at amd.com>

diff --git a/src/drmmode_display.c b/src/drmmode_display.c
index 8dc776fa..c7bec59c 100644
--- a/src/drmmode_display.c
+++ b/src/drmmode_display.c
@@ -116,7 +116,6 @@ static PixmapPtr drmmode_create_bo_pixmap(ScrnInfoPtr pScrn,
 	RADEONInfoPtr info = RADEONPTR(pScrn);
 	ScreenPtr pScreen = pScrn->pScreen;
 	PixmapPtr pixmap;
-	uint32_t tiling;
 
 	pixmap = (*pScreen->CreatePixmap)(pScreen, 0, 0, depth,
 					  RADEON_CREATE_PIXMAP_SCANOUT);
@@ -137,37 +136,8 @@ static PixmapPtr drmmode_create_bo_pixmap(ScrnInfoPtr pScrn,
 	if (info->surf_man && !info->use_glamor) {
 		struct radeon_surface *surface = radeon_get_pixmap_surface(pixmap);
 
-		memset(surface, 0, sizeof(struct radeon_surface));
-		surface->npix_x = width;
-		surface->npix_y = height;
-		surface->npix_z = 1;
-		surface->blk_w = 1;
-		surface->blk_h = 1;
-		surface->blk_d = 1;
-		surface->array_size = 1;
-		surface->last_level = 0;
-		surface->bpe = bpp / 8;
-		surface->nsamples = 1;
-		surface->flags = RADEON_SURF_SCANOUT;
-		/* we are requiring a recent enough libdrm version */
-		surface->flags |= RADEON_SURF_HAS_TILE_MODE_INDEX;
-		surface->flags |= RADEON_SURF_SET(RADEON_SURF_TYPE_2D, TYPE);
-		surface->flags |= RADEON_SURF_SET(RADEON_SURF_MODE_LINEAR_ALIGNED, MODE);
-		tiling = radeon_get_pixmap_tiling_flags(pixmap);
-
-		if (tiling & RADEON_TILING_MICRO) {
-			surface->flags = RADEON_SURF_CLR(surface->flags, MODE);
-			surface->flags |= RADEON_SURF_SET(RADEON_SURF_MODE_1D, MODE);
-		}
-		if (tiling & RADEON_TILING_MACRO) {
-			surface->flags = RADEON_SURF_CLR(surface->flags, MODE);
-			surface->flags |= RADEON_SURF_SET(RADEON_SURF_MODE_2D, MODE);
-		}
-
-		if (radeon_surface_best(info->surf_man, surface))
-			goto fail;
-
-		if (radeon_surface_init(info->surf_man, surface))
+		if (!radeon_surface_initialize(info, surface, width, height, bpp / 8,
+					       radeon_get_pixmap_tiling_flags(pixmap), 0))
 			goto fail;
 	}
 
@@ -2301,36 +2271,10 @@ drmmode_xf86crtc_resize (ScrnInfoPtr scrn, int width, int height)
 	base_align = 4096;
 
 	if (info->surf_man) {
-		memset(&surface, 0, sizeof(struct radeon_surface));
-		surface.npix_x = width;
-		surface.npix_y = height;
-		surface.npix_z = 1;
-		surface.blk_w = 1;
-		surface.blk_h = 1;
-		surface.blk_d = 1;
-		surface.array_size = 1;
-		surface.last_level = 0;
-		surface.bpe = cpp;
-		surface.nsamples = 1;
-		surface.flags = RADEON_SURF_SCANOUT;
-		/* we are requiring a recent enough libdrm version */
-		surface.flags |= RADEON_SURF_HAS_TILE_MODE_INDEX;
-		surface.flags |= RADEON_SURF_SET(RADEON_SURF_TYPE_2D, TYPE);
-		surface.flags |= RADEON_SURF_SET(RADEON_SURF_MODE_LINEAR_ALIGNED, MODE);
-		if (tiling_flags & RADEON_TILING_MICRO) {
-			surface.flags = RADEON_SURF_CLR(surface.flags, MODE);
-			surface.flags |= RADEON_SURF_SET(RADEON_SURF_MODE_1D, MODE);
-		}
-		if (tiling_flags & RADEON_TILING_MACRO) {
-			surface.flags = RADEON_SURF_CLR(surface.flags, MODE);
-			surface.flags |= RADEON_SURF_SET(RADEON_SURF_MODE_2D, MODE);
-		}
-		if (radeon_surface_best(info->surf_man, &surface)) {
-			return FALSE;
-		}
-		if (radeon_surface_init(info->surf_man, &surface)) {
+		if (!radeon_surface_initialize(info, &surface, width, height,
+					       cpp, tiling_flags, 0))
 			return FALSE;
-		}
+
 		screen_size = surface.bo_size;
 		base_align = surface.bo_alignment;
 		pitch = surface.level[0].pitch_bytes;
diff --git a/src/radeon.h b/src/radeon.h
index 63b6cf1f..c2ae6606 100644
--- a/src/radeon.h
+++ b/src/radeon.h
@@ -643,6 +643,11 @@ extern void RADEONInit3DEngine(ScrnInfoPtr pScrn);
 extern int radeon_cs_space_remaining(ScrnInfoPtr pScrn);
 
 /* radeon_bo_helper.c */
+extern Bool
+radeon_surface_initialize(RADEONInfoPtr info, struct radeon_surface *surface,
+			  int width, int height, int cpp, uint32_t tiling_flags,
+			  int usage_hint);
+
 extern Bool radeon_get_pixmap_handle(PixmapPtr pixmap, uint32_t *handle);
 
 /* radeon_commonfuncs.c */
diff --git a/src/radeon_bo_helper.c b/src/radeon_bo_helper.c
index be879aad..37658942 100644
--- a/src/radeon_bo_helper.c
+++ b/src/radeon_bo_helper.c
@@ -59,6 +59,89 @@ static Bool RADEONMacroSwitch(int width, int height, int bpp,
     }
 }
 
+static unsigned eg_tile_split_opp(unsigned tile_split)
+{
+    switch (tile_split) {
+        case 0:     tile_split = 64;    break;
+        case 1:     tile_split = 128;   break;
+        case 2:     tile_split = 256;   break;
+        case 3:     tile_split = 512;   break;
+        default:
+        case 4:     tile_split = 1024;  break;
+        case 5:     tile_split = 2048;  break;
+        case 6:     tile_split = 4096;  break;
+    }
+    return tile_split;
+}
+
+Bool
+radeon_surface_initialize(RADEONInfoPtr info, struct radeon_surface *surface,
+			  int width, int height, int cpp, uint32_t tiling_flags,
+			  int usage_hint)
+{
+	memset(surface, 0, sizeof(struct radeon_surface));
+
+	surface->npix_x = width;
+	/* need to align height to 8 for old kernel */
+	surface->npix_y = RADEON_ALIGN(height, 8);
+	surface->npix_z = 1;
+	surface->blk_w = 1;
+	surface->blk_h = 1;
+	surface->blk_d = 1;
+	surface->array_size = 1;
+	surface->last_level = 0;
+	surface->bpe = cpp;
+	surface->nsamples = 1;
+	if (height < 128) {
+	    /* disable 2d tiling for small surface to work around
+	     * the fact that ddx align height to 8 pixel for old
+	     * obscure reason i can't remember
+	     */
+	    tiling_flags &= ~RADEON_TILING_MACRO;
+	}
+
+	surface->flags = RADEON_SURF_SCANOUT | RADEON_SURF_HAS_TILE_MODE_INDEX |
+	    RADEON_SURF_SET(RADEON_SURF_TYPE_2D, TYPE);
+
+	if (usage_hint & RADEON_CREATE_PIXMAP_SZBUFFER) {
+	    surface->flags |= RADEON_SURF_ZBUFFER;
+	    surface->flags |= RADEON_SURF_SBUFFER;
+	}
+
+	if ((tiling_flags & RADEON_TILING_MACRO)) {
+	    surface->flags = RADEON_SURF_CLR(surface->flags, MODE);
+	    surface->flags |= RADEON_SURF_SET(RADEON_SURF_MODE_2D, MODE);
+	} else if ((tiling_flags & RADEON_TILING_MICRO)) {
+	    surface->flags = RADEON_SURF_CLR(surface->flags, MODE);
+	    surface->flags |= RADEON_SURF_SET(RADEON_SURF_MODE_1D, MODE);
+	} else
+	    surface->flags |= RADEON_SURF_SET(RADEON_SURF_MODE_LINEAR, MODE);
+
+	if (info->ChipFamily >= CHIP_FAMILY_CEDAR) {
+	    surface->bankw = (tiling_flags >> RADEON_TILING_EG_BANKW_SHIFT) &
+		RADEON_TILING_EG_BANKW_MASK;
+	    surface->bankh = (tiling_flags >> RADEON_TILING_EG_BANKH_SHIFT) &
+		RADEON_TILING_EG_BANKH_MASK;
+	    surface->tile_split = eg_tile_split_opp((tiling_flags >> RADEON_TILING_EG_TILE_SPLIT_SHIFT) &
+						    RADEON_TILING_EG_TILE_SPLIT_MASK);
+	    if (surface->flags & RADEON_SURF_SBUFFER) {
+		surface->stencil_tile_split =
+		    (tiling_flags >> RADEON_TILING_EG_STENCIL_TILE_SPLIT_SHIFT) &
+		    RADEON_TILING_EG_STENCIL_TILE_SPLIT_MASK;
+	    }
+	    surface->mtilea = (tiling_flags >> RADEON_TILING_EG_MACRO_TILE_ASPECT_SHIFT) &
+		RADEON_TILING_EG_MACRO_TILE_ASPECT_MASK;
+	}
+
+	if (radeon_surface_best(info->surf_man, surface))
+	    return FALSE;
+
+	if (radeon_surface_init(info->surf_man, surface))
+	    return FALSE;
+
+	return TRUE;
+}
+
 /* Calculate appropriate tiling and pitch for a pixmap and allocate a BO that
  * can hold it.
  */
@@ -108,77 +191,37 @@ radeon_alloc_pixmap_bo(ScrnInfoPtr pScrn, int width, int height, int depth,
     base_align = drmmode_get_base_align(pScrn, cpp, tiling);
     size = RADEON_ALIGN(heighta * pitch, RADEON_GPU_PAGE_SIZE);
 
-    if (info->surf_man) {
-	memset(&surface, 0, sizeof(struct radeon_surface));
-
-		if (width) {
-			surface.npix_x = width;
-			/* need to align height to 8 for old kernel */
-			surface.npix_y = RADEON_ALIGN(height, 8);
-			surface.npix_z = 1;
-			surface.blk_w = 1;
-			surface.blk_h = 1;
-			surface.blk_d = 1;
-			surface.array_size = 1;
-			surface.last_level = 0;
-			surface.bpe = cpp;
-			surface.nsamples = 1;
-			if (height < 128) {
-				/* disable 2d tiling for small surface to work around
-				 * the fact that ddx align height to 8 pixel for old
-				 * obscure reason i can't remember
-				 */
-				tiling &= ~RADEON_TILING_MACRO;
-			}
-			surface.flags = RADEON_SURF_SCANOUT;
-			/* we are requiring a recent enough libdrm version */
-			surface.flags |= RADEON_SURF_HAS_TILE_MODE_INDEX;
-			surface.flags |= RADEON_SURF_SET(RADEON_SURF_TYPE_2D, TYPE);
-			surface.flags |= RADEON_SURF_SET(RADEON_SURF_MODE_LINEAR, MODE);
-			if ((tiling & RADEON_TILING_MICRO)) {
-				surface.flags = RADEON_SURF_CLR(surface.flags, MODE);
-				surface.flags |= RADEON_SURF_SET(RADEON_SURF_MODE_1D, MODE);
-			}
-			if ((tiling & RADEON_TILING_MACRO)) {
-				surface.flags = RADEON_SURF_CLR(surface.flags, MODE);
-				surface.flags |= RADEON_SURF_SET(RADEON_SURF_MODE_2D, MODE);
-			}
-			if (usage_hint & RADEON_CREATE_PIXMAP_SZBUFFER) {
-				surface.flags |= RADEON_SURF_ZBUFFER;
-				surface.flags |= RADEON_SURF_SBUFFER;
-			}
-			if (radeon_surface_best(info->surf_man, &surface)) {
-				return NULL;
-			}
-			if (radeon_surface_init(info->surf_man, &surface)) {
-				return NULL;
-			}
-			size = surface.bo_size;
-			base_align = surface.bo_alignment;
-			pitch = surface.level[0].pitch_bytes;
-			tiling = 0;
-			switch (surface.level[0].mode) {
-			case RADEON_SURF_MODE_2D:
-				tiling |= RADEON_TILING_MACRO;
-				tiling |= surface.bankw << RADEON_TILING_EG_BANKW_SHIFT;
-				tiling |= surface.bankh << RADEON_TILING_EG_BANKH_SHIFT;
-				tiling |= surface.mtilea << RADEON_TILING_EG_MACRO_TILE_ASPECT_SHIFT;
-				if (surface.tile_split)
-					tiling |= eg_tile_split(surface.tile_split) << RADEON_TILING_EG_TILE_SPLIT_SHIFT;
-				tiling |= eg_tile_split(surface.stencil_tile_split) << RADEON_TILING_EG_STENCIL_TILE_SPLIT_SHIFT;
-				break;
-			case RADEON_SURF_MODE_1D:
-				tiling |= RADEON_TILING_MICRO;
-				break;
-			default:
-				break;
-			}
-		}
-
-		if (new_surface)
-		    *new_surface = surface;
+    if (width && info->surf_man) {
+	if (!radeon_surface_initialize(info, &surface, width, height, cpp,
+				       tiling, usage_hint))
+	    return NULL;
+
+	size = surface.bo_size;
+	base_align = surface.bo_alignment;
+	pitch = surface.level[0].pitch_bytes;
+	tiling = 0;
+	switch (surface.level[0].mode) {
+	case RADEON_SURF_MODE_2D:
+	    tiling |= RADEON_TILING_MACRO;
+	    tiling |= surface.bankw << RADEON_TILING_EG_BANKW_SHIFT;
+	    tiling |= surface.bankh << RADEON_TILING_EG_BANKH_SHIFT;
+	    tiling |= surface.mtilea << RADEON_TILING_EG_MACRO_TILE_ASPECT_SHIFT;
+	    if (surface.tile_split)
+		tiling |= eg_tile_split(surface.tile_split) << RADEON_TILING_EG_TILE_SPLIT_SHIFT;
+	    if (surface.flags & RADEON_SURF_SBUFFER)
+		tiling |= eg_tile_split(surface.stencil_tile_split) << RADEON_TILING_EG_STENCIL_TILE_SPLIT_SHIFT;
+	    break;
+	case RADEON_SURF_MODE_1D:
+	    tiling |= RADEON_TILING_MICRO;
+	    break;
+	default:
+	    break;
 	}
 
+	if (new_surface)
+	    *new_surface = surface;
+    }
+
     if (tiling)
 	flags |= RADEON_GEM_NO_CPU_ACCESS;
 
@@ -308,21 +351,6 @@ Bool radeon_share_pixmap_backing(struct radeon_bo *bo, void **handle_p)
     return TRUE;
 }
 
-static unsigned eg_tile_split_opp(unsigned tile_split)
-{
-    switch (tile_split) {
-        case 0:     tile_split = 64;    break;
-        case 1:     tile_split = 128;   break;
-        case 2:     tile_split = 256;   break;
-        case 3:     tile_split = 512;   break;
-        default:
-        case 4:     tile_split = 1024;  break;
-        case 5:     tile_split = 2048;  break;
-        case 6:     tile_split = 4096;  break;
-    }
-    return tile_split;
-}
-
 Bool radeon_set_shared_pixmap_backing(PixmapPtr ppix, void *fd_handle,
 				      struct radeon_surface *surface)
 {
@@ -348,39 +376,14 @@ Bool radeon_set_shared_pixmap_backing(PixmapPtr ppix, void *fd_handle,
 	driver_priv = exaGetPixmapDriverPrivate(ppix);
 	tiling_flags = driver_priv->tiling_flags;
 
-	memset(surface, 0, sizeof(struct radeon_surface));
-
-	surface->npix_x = ppix->drawable.width;
-	surface->npix_y = ppix->drawable.height;
-	surface->npix_z = 1;
-	surface->blk_w = 1;
-	surface->blk_h = 1;
-	surface->blk_d = 1;
-	surface->array_size = 1;
-	surface->bpe = ppix->drawable.bitsPerPixel / 8;
-	surface->nsamples = 1;
-	/* we are requiring a recent enough libdrm version */
-	surface->flags |= RADEON_SURF_HAS_TILE_MODE_INDEX;
-	surface->flags |= RADEON_SURF_SET(RADEON_SURF_TYPE_2D, TYPE);
-	if (tiling_flags & RADEON_TILING_MACRO)
-	    surface->flags |= RADEON_SURF_SET(RADEON_SURF_MODE_2D, MODE);
-	else if (tiling_flags & RADEON_TILING_MICRO)
-	    surface->flags |= RADEON_SURF_SET(RADEON_SURF_MODE_1D, MODE);
-	else
-	    surface->flags |= RADEON_SURF_SET(RADEON_SURF_MODE_LINEAR_ALIGNED, MODE);
-	surface->bankw = (tiling_flags >> RADEON_TILING_EG_BANKW_SHIFT) & RADEON_TILING_EG_BANKW_MASK;
-	surface->bankh = (tiling_flags >> RADEON_TILING_EG_BANKH_SHIFT) & RADEON_TILING_EG_BANKH_MASK;
-	surface->tile_split = eg_tile_split_opp((tiling_flags >> RADEON_TILING_EG_TILE_SPLIT_SHIFT) & RADEON_TILING_EG_TILE_SPLIT_MASK);
-	surface->stencil_tile_split = (tiling_flags >> RADEON_TILING_EG_STENCIL_TILE_SPLIT_SHIFT) & RADEON_TILING_EG_STENCIL_TILE_SPLIT_MASK;
-	surface->mtilea = (tiling_flags >> RADEON_TILING_EG_MACRO_TILE_ASPECT_SHIFT) & RADEON_TILING_EG_MACRO_TILE_ASPECT_MASK;
-	if (radeon_surface_best(info->surf_man, surface)) {
-	    ret = FALSE;
-	    goto error;
-	}
-	if (radeon_surface_init(info->surf_man, surface)) {
+	if (!radeon_surface_initialize(info, surface, ppix->drawable.width,
+				       ppix->drawable.height,
+				       ppix->drawable.bitsPerPixel / 8,
+				       tiling_flags, 0)) {
 	    ret = FALSE;
 	    goto error;
 	}
+
 	/* we have to post hack the surface to reflect the actual size
 	   of the shared pixmap */
 	surface->level[0].pitch_bytes = ppix->devKind;
diff --git a/src/radeon_kms.c b/src/radeon_kms.c
index 0066c4e9..7ff66bf3 100644
--- a/src/radeon_kms.c
+++ b/src/radeon_kms.c
@@ -2702,38 +2702,11 @@ static Bool radeon_setup_kernel_mem(ScreenPtr pScreen)
     screen_size = RADEON_ALIGN(pScrn->virtualY, drmmode_get_height_align(pScrn, tiling_flags)) * pitch;
     base_align = drmmode_get_base_align(pScrn, cpp, tiling_flags);
 	if (info->surf_man) {
-		memset(&surface, 0, sizeof(struct radeon_surface));
-		surface.npix_x = pScrn->virtualX;
-		surface.npix_y = pScrn->virtualY;
-		surface.npix_z = 1;
-		surface.blk_w = 1;
-		surface.blk_h = 1;
-		surface.blk_d = 1;
-		surface.array_size = 1;
-		surface.last_level = 0;
-		surface.bpe = cpp;
-		surface.nsamples = 1;
-		surface.flags = RADEON_SURF_SCANOUT;
-		/* we are requiring a recent enough libdrm version */
-		surface.flags |= RADEON_SURF_HAS_TILE_MODE_INDEX;
-		surface.flags |= RADEON_SURF_SET(RADEON_SURF_TYPE_2D, TYPE);
-		surface.flags |= RADEON_SURF_SET(RADEON_SURF_MODE_LINEAR_ALIGNED, MODE);
-		if (tiling_flags & RADEON_TILING_MICRO) {
-			surface.flags = RADEON_SURF_CLR(surface.flags, MODE);
-			surface.flags |= RADEON_SURF_SET(RADEON_SURF_MODE_1D, MODE);
-		}
-		if (tiling_flags & RADEON_TILING_MACRO) {
-			surface.flags = RADEON_SURF_CLR(surface.flags, MODE);
-			surface.flags |= RADEON_SURF_SET(RADEON_SURF_MODE_2D, MODE);
-		}
-		if (radeon_surface_best(info->surf_man, &surface)) {
-			xf86DrvMsg(pScreen->myNum, X_ERROR,
-				   "radeon_surface_best failed\n");
-			return FALSE;
-		}
-		if (radeon_surface_init(info->surf_man, &surface)) {
+		if (!radeon_surface_initialize(info, &surface, pScrn->virtualX,
+					       pScrn->virtualY, cpp,
+					       tiling_flags, 0)) {
 			xf86DrvMsg(pScreen->myNum, X_ERROR,
-				   "radeon_surface_init failed\n");
+				   "radeon_surface_initialize failed\n");
 			return FALSE;
 		}
 		pitch = surface.level[0].pitch_bytes;
commit ba5d5402b3e2e807d7e47205ac83f930b6c8caf5
Author: Michel Dänzer <michel.daenzer at amd.com>
Date:   Thu May 17 12:36:29 2018 +0200

    glamor: Don't store radeon_surfaces in pixmaps
    
    Only EXA needs them.
    
    Reviewed-by: Alex Deucher <alexander.deucher at amd.com>

diff --git a/src/drmmode_display.c b/src/drmmode_display.c
index f99667fb..8dc776fa 100644
--- a/src/drmmode_display.c
+++ b/src/drmmode_display.c
@@ -116,7 +116,6 @@ static PixmapPtr drmmode_create_bo_pixmap(ScrnInfoPtr pScrn,
 	RADEONInfoPtr info = RADEONPTR(pScrn);
 	ScreenPtr pScreen = pScrn->pScreen;
 	PixmapPtr pixmap;
-	struct radeon_surface *surface;
 	uint32_t tiling;
 
 	pixmap = (*pScreen->CreatePixmap)(pScreen, 0, 0, depth,
@@ -135,41 +134,41 @@ static PixmapPtr drmmode_create_bo_pixmap(ScrnInfoPtr pScrn,
 	if (!radeon_set_pixmap_bo(pixmap, bo))
 		goto fail;
 
-	if (info->surf_man) {
-		surface = radeon_get_pixmap_surface(pixmap);
-		if (surface) {
-			memset(surface, 0, sizeof(struct radeon_surface));
-			surface->npix_x = width;
-			surface->npix_y = height;
-			surface->npix_z = 1;
-			surface->blk_w = 1;
-			surface->blk_h = 1;
-			surface->blk_d = 1;
-			surface->array_size = 1;
-			surface->last_level = 0;
-			surface->bpe = bpp / 8;
-			surface->nsamples = 1;
-			surface->flags = RADEON_SURF_SCANOUT;
-			/* we are requiring a recent enough libdrm version */
-			surface->flags |= RADEON_SURF_HAS_TILE_MODE_INDEX;
-			surface->flags |= RADEON_SURF_SET(RADEON_SURF_TYPE_2D, TYPE);
-			surface->flags |= RADEON_SURF_SET(RADEON_SURF_MODE_LINEAR_ALIGNED, MODE);
-			tiling = radeon_get_pixmap_tiling_flags(pixmap);
-			if (tiling & RADEON_TILING_MICRO) {
-				surface->flags = RADEON_SURF_CLR(surface->flags, MODE);
-				surface->flags |= RADEON_SURF_SET(RADEON_SURF_MODE_1D, MODE);
-			}
-			if (tiling & RADEON_TILING_MACRO) {
-				surface->flags = RADEON_SURF_CLR(surface->flags, MODE);
-				surface->flags |= RADEON_SURF_SET(RADEON_SURF_MODE_2D, MODE);
-			}
-			if (radeon_surface_best(info->surf_man, surface)) {
-				goto fail;
-			}
-			if (radeon_surface_init(info->surf_man, surface)) {
-				goto fail;
-			}
+	if (info->surf_man && !info->use_glamor) {
+		struct radeon_surface *surface = radeon_get_pixmap_surface(pixmap);
+
+		memset(surface, 0, sizeof(struct radeon_surface));
+		surface->npix_x = width;
+		surface->npix_y = height;
+		surface->npix_z = 1;
+		surface->blk_w = 1;
+		surface->blk_h = 1;
+		surface->blk_d = 1;
+		surface->array_size = 1;
+		surface->last_level = 0;
+		surface->bpe = bpp / 8;
+		surface->nsamples = 1;
+		surface->flags = RADEON_SURF_SCANOUT;
+		/* we are requiring a recent enough libdrm version */
+		surface->flags |= RADEON_SURF_HAS_TILE_MODE_INDEX;
+		surface->flags |= RADEON_SURF_SET(RADEON_SURF_TYPE_2D, TYPE);
+		surface->flags |= RADEON_SURF_SET(RADEON_SURF_MODE_LINEAR_ALIGNED, MODE);
+		tiling = radeon_get_pixmap_tiling_flags(pixmap);
+
+		if (tiling & RADEON_TILING_MICRO) {
+			surface->flags = RADEON_SURF_CLR(surface->flags, MODE);
+			surface->flags |= RADEON_SURF_SET(RADEON_SURF_MODE_1D, MODE);
 		}
+		if (tiling & RADEON_TILING_MACRO) {
+			surface->flags = RADEON_SURF_CLR(surface->flags, MODE);
+			surface->flags |= RADEON_SURF_SET(RADEON_SURF_MODE_2D, MODE);
+		}
+
+		if (radeon_surface_best(info->surf_man, surface))
+			goto fail;
+
+		if (radeon_surface_init(info->surf_man, surface))
+			goto fail;
 	}
 
 	if (!info->use_glamor ||
@@ -2272,7 +2271,6 @@ drmmode_xf86crtc_resize (ScrnInfoPtr scrn, int width, int height)
 	int cpp = info->pixel_bytes;
 	struct radeon_bo *front_bo;
 	struct radeon_surface surface;
-	struct radeon_surface *psurface;
 	uint32_t tiling_flags = 0, base_align;
 	PixmapPtr ppix = screen->GetScreenPixmap(screen);
 	void *fb_shadow;
@@ -2353,7 +2351,8 @@ drmmode_xf86crtc_resize (ScrnInfoPtr scrn, int width, int height)
 		default:
 			break;
 		}
-		info->front_surface = surface;
+		if (!info->use_glamor)
+			info->front_surface = surface;
 	}
 
 	xf86DrvMsg(scrn->scrnIndex, X_INFO,
@@ -2394,8 +2393,8 @@ drmmode_xf86crtc_resize (ScrnInfoPtr scrn, int width, int height)
 	    radeon_bo_set_tiling(info->front_bo, tiling_flags, pitch);
 
 	if (!info->r600_shadow_fb) {
-		psurface = radeon_get_pixmap_surface(ppix);
-		*psurface = info->front_surface;
+		if (info->surf_man && !info->use_glamor)
+			*radeon_get_pixmap_surface(ppix) = info->front_surface;
 		screen->ModifyPixmapHeader(ppix,
 					   width, height, -1, -1, pitch, NULL);
 	} else {
diff --git a/src/radeon.h b/src/radeon.h
index 598a83c1..63b6cf1f 100644
--- a/src/radeon.h
+++ b/src/radeon.h
@@ -304,8 +304,6 @@ radeon_dirty_src_equals(PixmapDirtyUpdatePtr dirty, PixmapPtr pixmap)
 #ifdef USE_GLAMOR
 
 struct radeon_pixmap {
-	struct radeon_surface surface;
-
 	uint_fast32_t gpu_read;
 	uint_fast32_t gpu_write;
 
@@ -703,22 +701,9 @@ extern RADEONEntPtr RADEONEntPriv(ScrnInfoPtr pScrn);
 
 static inline struct radeon_surface *radeon_get_pixmap_surface(PixmapPtr pPix)
 {
-#ifdef USE_GLAMOR
-    RADEONInfoPtr info = RADEONPTR(xf86ScreenToScrn(pPix->drawable.pScreen));
-
-    if (info->use_glamor) {
-	struct radeon_pixmap *priv;
-	priv = radeon_get_pixmap_private(pPix);
-	return priv ? &priv->surface : NULL;
-    } else
-#endif
-    {
-	struct radeon_exa_pixmap_priv *driver_priv;
-	driver_priv = exaGetPixmapDriverPrivate(pPix);
-	return &driver_priv->surface;
-    }
+    struct radeon_exa_pixmap_priv *driver_priv = exaGetPixmapDriverPrivate(pPix);
 
-    return NULL;
+    return &driver_priv->surface;
 }
 
 uint32_t radeon_get_pixmap_tiling(PixmapPtr pPix);
diff --git a/src/radeon_bo_helper.c b/src/radeon_bo_helper.c
index 8245d624..be879aad 100644
--- a/src/radeon_bo_helper.c
+++ b/src/radeon_bo_helper.c
@@ -174,6 +174,9 @@ radeon_alloc_pixmap_bo(ScrnInfoPtr pScrn, int width, int height, int depth,
 				break;
 			}
 		}
+
+		if (new_surface)
+		    *new_surface = surface;
 	}
 
     if (tiling)
@@ -185,7 +188,6 @@ radeon_alloc_pixmap_bo(ScrnInfoPtr pScrn, int width, int height, int depth,
     if (bo && tiling && radeon_bo_set_tiling(bo, tiling, pitch) == 0)
 	*new_tiling = tiling;
 
-    *new_surface = surface;
     *new_pitch = pitch;
     return bo;
 }
@@ -335,26 +337,18 @@ Bool radeon_set_shared_pixmap_backing(PixmapPtr ppix, void *fd_handle,
     if (!bo)
         goto error;
 
-    memset(surface, 0, sizeof(struct radeon_surface));
-
     ret = radeon_set_pixmap_bo(ppix, bo);
     if (!ret)
 	goto error;
 
-    if (info->surf_man) {
+    if (surface) {
+	struct radeon_exa_pixmap_priv *driver_priv;
 	uint32_t tiling_flags;
 
-#ifdef USE_GLAMOR
-	if (info->use_glamor) {
-	    tiling_flags = radeon_get_pixmap_private(ppix)->tiling_flags;
-	} else
-#endif
-	{
-	    struct radeon_exa_pixmap_priv *driver_priv;
+	driver_priv = exaGetPixmapDriverPrivate(ppix);
+	tiling_flags = driver_priv->tiling_flags;
 
-	    driver_priv = exaGetPixmapDriverPrivate(ppix);
-	    tiling_flags = driver_priv->tiling_flags;
-	}
+	memset(surface, 0, sizeof(struct radeon_surface));
 
 	surface->npix_x = ppix->drawable.width;
 	surface->npix_y = ppix->drawable.height;
diff --git a/src/radeon_glamor.c b/src/radeon_glamor.c
index 10d513ea..6cff72e1 100644
--- a/src/radeon_glamor.c
+++ b/src/radeon_glamor.c
@@ -250,8 +250,7 @@ radeon_glamor_create_pixmap(ScreenPtr screen, int w, int h, int depth,
 
 		priv->bo = radeon_alloc_pixmap_bo(scrn, w, h, depth, usage,
 						  pixmap->drawable.bitsPerPixel,
-						  &stride,
-						  &priv->surface,
+						  &stride, NULL,
 						  &priv->tiling_flags);
 		if (!priv->bo)
 			goto fallback_priv;
@@ -391,15 +390,12 @@ radeon_glamor_set_shared_pixmap_backing(PixmapPtr pixmap, void *handle)
 {
 	ScreenPtr screen = pixmap->drawable.pScreen;
 	ScrnInfoPtr scrn = xf86ScreenToScrn(screen);
-	struct radeon_surface surface;
 	struct radeon_pixmap *priv;
 
-	if (!radeon_set_shared_pixmap_backing(pixmap, handle, &surface))
+	if (!radeon_set_shared_pixmap_backing(pixmap, handle, NULL))
 		return FALSE;
 
 	priv = radeon_get_pixmap_private(pixmap);
-	priv->surface = surface;
-
 	if (!radeon_glamor_create_textured_pixmap(pixmap, priv)) {
 		xf86DrvMsg(scrn->scrnIndex, X_ERROR,
 			   "Failed to get PRIME drawable for glamor pixmap.\n");
diff --git a/src/radeon_kms.c b/src/radeon_kms.c
index 861fbf97..0066c4e9 100644
--- a/src/radeon_kms.c
+++ b/src/radeon_kms.c
@@ -326,7 +326,6 @@ static Bool RADEONCreateScreenResources_KMS(ScreenPtr pScreen)
     ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
     RADEONInfoPtr  info   = RADEONPTR(pScrn);
     PixmapPtr pixmap;
-    struct radeon_surface *surface;
 
     pScreen->CreateScreenResources = info->CreateScreenResources;
     if (!(*pScreen->CreateScreenResources)(pScreen))
@@ -364,10 +363,9 @@ static Bool RADEONCreateScreenResources_KMS(ScreenPtr pScreen)
 	    PixmapPtr pPix = pScreen->GetScreenPixmap(pScreen);
 	    if (!radeon_set_pixmap_bo(pPix, info->front_bo))
 		return FALSE;
-	    surface = radeon_get_pixmap_surface(pPix);
-	    if (surface) {
-		*surface = info->front_surface;
-	    }
+
+	    if (info->surf_man && !info->use_glamor)
+		*radeon_get_pixmap_surface(pPix) = info->front_surface;
 	}
     }
 
@@ -2758,7 +2756,8 @@ static Bool radeon_setup_kernel_mem(ScreenPtr pScreen)
 		default:
 			break;
 		}
-		info->front_surface = surface;
+		if (!info->use_glamor)
+		    info->front_surface = surface;
 	}
     {
 	int cursor_size;
commit eec4a41925127ae490f0a5156a881a08d521e28e
Author: Michel Dänzer <michel.daenzer at amd.com>
Date:   Thu May 17 18:25:37 2018 +0200

    Only initialize libdrm_radeon surface manager for >= R600
    
    Not used with older GPUs.
    
    Reviewed-by: Alex Deucher <alexander.deucher at amd.com>

diff --git a/src/drmmode_display.c b/src/drmmode_display.c
index 958532fb..f99667fb 100644
--- a/src/drmmode_display.c
+++ b/src/drmmode_display.c
@@ -135,7 +135,7 @@ static PixmapPtr drmmode_create_bo_pixmap(ScrnInfoPtr pScrn,
 	if (!radeon_set_pixmap_bo(pixmap, bo))
 		goto fail;
 
-	if (info->ChipFamily >= CHIP_FAMILY_R600) {
+	if (info->surf_man) {
 		surface = radeon_get_pixmap_surface(pixmap);
 		if (surface) {
 			memset(surface, 0, sizeof(struct radeon_surface));
@@ -2301,7 +2301,8 @@ drmmode_xf86crtc_resize (ScrnInfoPtr scrn, int width, int height)
 	aligned_height = RADEON_ALIGN(height, drmmode_get_height_align(scrn, tiling_flags));
 	screen_size = RADEON_ALIGN(pitch * aligned_height, RADEON_GPU_PAGE_SIZE);
 	base_align = 4096;
-	if (info->ChipFamily >= CHIP_FAMILY_R600) {
+
+	if (info->surf_man) {
 		memset(&surface, 0, sizeof(struct radeon_surface));
 		surface.npix_x = width;
 		surface.npix_y = height;
diff --git a/src/radeon_bo_helper.c b/src/radeon_bo_helper.c
index 0366f613..8245d624 100644
--- a/src/radeon_bo_helper.c
+++ b/src/radeon_bo_helper.c
@@ -107,9 +107,10 @@ radeon_alloc_pixmap_bo(ScrnInfoPtr pScrn, int width, int height, int depth,
     pitch = RADEON_ALIGN(width, drmmode_get_pitch_align(pScrn, cpp, tiling)) * cpp;
     base_align = drmmode_get_base_align(pScrn, cpp, tiling);
     size = RADEON_ALIGN(heighta * pitch, RADEON_GPU_PAGE_SIZE);
-    memset(&surface, 0, sizeof(struct radeon_surface));
 
-    if (info->ChipFamily >= CHIP_FAMILY_R600 && info->surf_man) {
+    if (info->surf_man) {
+	memset(&surface, 0, sizeof(struct radeon_surface));
+
 		if (width) {
 			surface.npix_x = width;
 			/* need to align height to 8 for old kernel */
@@ -340,7 +341,7 @@ Bool radeon_set_shared_pixmap_backing(PixmapPtr ppix, void *fd_handle,
     if (!ret)
 	goto error;
 
-    if (info->ChipFamily >= CHIP_FAMILY_R600 && info->surf_man) {
+    if (info->surf_man) {
 	uint32_t tiling_flags;
 
 #ifdef USE_GLAMOR
diff --git a/src/radeon_kms.c b/src/radeon_kms.c
index 26810e08..861fbf97 100644
--- a/src/radeon_kms.c
+++ b/src/radeon_kms.c
@@ -2228,7 +2228,16 @@ Bool RADEONScreenInit_KMS(ScreenPtr pScreen, int argc, char **argv)
     if (info->r600_shadow_fb == FALSE)
         info->directRenderingEnabled = radeon_dri2_screen_init(pScreen);
 
-    info->surf_man = radeon_surface_manager_new(pRADEONEnt->fd);
+    if (info->ChipFamily >= CHIP_FAMILY_R600) {
+	info->surf_man = radeon_surface_manager_new(pRADEONEnt->fd);
+
+	if (!info->surf_man) {
+	    xf86DrvMsg(pScreen->myNum, X_ERROR,
+		       "Failed to initialize surface manager\n");
+	    return FALSE;
+	}
+    }
+
     if (!info->bufmgr)
         info->bufmgr = radeon_bo_manager_gem_ctor(pRADEONEnt->fd);
     if (!info->bufmgr) {
@@ -2694,12 +2703,7 @@ static Bool radeon_setup_kernel_mem(ScreenPtr pScreen)
     pitch = RADEON_ALIGN(pScrn->virtualX, drmmode_get_pitch_align(pScrn, cpp, tiling_flags)) * cpp;
     screen_size = RADEON_ALIGN(pScrn->virtualY, drmmode_get_height_align(pScrn, tiling_flags)) * pitch;
     base_align = drmmode_get_base_align(pScrn, cpp, tiling_flags);
-	if (info->ChipFamily >= CHIP_FAMILY_R600) {
-		if(!info->surf_man) {
-			xf86DrvMsg(pScreen->myNum, X_ERROR,
-				   "failed to initialise surface manager\n");
-			return FALSE;
-		}
+	if (info->surf_man) {
 		memset(&surface, 0, sizeof(struct radeon_surface));
 		surface.npix_x = pScrn->virtualX;
 		surface.npix_y = pScrn->virtualY;
commit ac18a993a3a68629805b8f272a339e25444c0897
Author: Michel Dänzer <michel.daenzer at amd.com>
Date:   Wed May 23 12:18:36 2018 +0200

    EXA: Remove old RADEONEXACreatePixmap hook
    
    Not used by any supported version of xserver.
    
    Reviewed-by: Alex Deucher <alexander.deucher at amd.com>

diff --git a/src/evergreen_exa.c b/src/evergreen_exa.c
index 85848133..41edd345 100644
--- a/src/evergreen_exa.c
+++ b/src/evergreen_exa.c
@@ -2065,7 +2065,6 @@ EVERGREENDrawInit(ScreenPtr pScreen)
     info->accel_state->exa->MarkSync = EVERGREENMarkSync;
     info->accel_state->exa->WaitMarker = EVERGREENSync;
 
-    info->accel_state->exa->CreatePixmap = RADEONEXACreatePixmap;
     info->accel_state->exa->DestroyPixmap = RADEONEXADestroyPixmap;
     info->accel_state->exa->PixmapIsOffscreen = RADEONEXAPixmapIsOffscreen;
     info->accel_state->exa->PrepareAccess = RADEONPrepareAccess_CS;
diff --git a/src/evergreen_state.h b/src/evergreen_state.h
index 795d4472..ef331002 100644
--- a/src/evergreen_state.h
+++ b/src/evergreen_state.h
@@ -345,7 +345,6 @@ R600SetAccelState(ScrnInfoPtr pScrn,
 
 extern Bool RADEONPrepareAccess_CS(PixmapPtr pPix, int index);
 extern void RADEONFinishAccess_CS(PixmapPtr pPix, int index);
-extern void *RADEONEXACreatePixmap(ScreenPtr pScreen, int size, int align);
 extern void *RADEONEXACreatePixmap2(ScreenPtr pScreen, int width, int height,
 				    int depth, int usage_hint, int bitsPerPixel,
 				    int *new_pitch);
diff --git a/src/r600_exa.c b/src/r600_exa.c
index c69b8fce..a111dd45 100644
--- a/src/r600_exa.c
+++ b/src/r600_exa.c
@@ -2044,7 +2044,6 @@ R600DrawInit(ScreenPtr pScreen)
     info->accel_state->exa->MarkSync = R600MarkSync;
     info->accel_state->exa->WaitMarker = R600Sync;
 
-    info->accel_state->exa->CreatePixmap = RADEONEXACreatePixmap;
     info->accel_state->exa->DestroyPixmap = RADEONEXADestroyPixmap;
     info->accel_state->exa->PixmapIsOffscreen = RADEONEXAPixmapIsOffscreen;
     info->accel_state->exa->PrepareAccess = RADEONPrepareAccess_CS;
diff --git a/src/r600_state.h b/src/r600_state.h
index fda297d3..4898e8de 100644
--- a/src/r600_state.h
+++ b/src/r600_state.h
@@ -316,7 +316,6 @@ R600SetAccelState(ScrnInfoPtr pScrn,
 
 extern Bool RADEONPrepareAccess_CS(PixmapPtr pPix, int index);
 extern void RADEONFinishAccess_CS(PixmapPtr pPix, int index);
-extern void *RADEONEXACreatePixmap(ScreenPtr pScreen, int size, int align);
 extern void *RADEONEXACreatePixmap2(ScreenPtr pScreen, int width, int height,
 				    int depth, int usage_hint, int bitsPerPixel,
 				    int *new_pitch);
diff --git a/src/radeon_exa.c b/src/radeon_exa.c
index 9106d5c6..ef60bc0c 100644
--- a/src/radeon_exa.c
+++ b/src/radeon_exa.c
@@ -235,35 +235,6 @@ void RADEONFinishAccess_CS(PixmapPtr pPix, int index)
 }
 
 
-void *RADEONEXACreatePixmap(ScreenPtr pScreen, int size, int align)
-{
-    ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
-    RADEONInfoPtr info = RADEONPTR(pScrn);
-    struct radeon_exa_pixmap_priv *new_priv;
-
-    if (size != 0 && !info->exa_force_create &&
-	info->exa_pixmaps == FALSE)
-        return NULL;
-	    
-    new_priv = calloc(1, sizeof(struct radeon_exa_pixmap_priv));
-    if (!new_priv)
-	return NULL;
-
-    if (size == 0)
-	return new_priv;
-
-    new_priv->bo = radeon_bo_open(info->bufmgr, 0, size, align,
-				  RADEON_GEM_DOMAIN_VRAM, 0);
-    if (!new_priv->bo) {
-	free(new_priv);
-	ErrorF("Failed to alloc memory\n");
-	return NULL;
-    }
-    
-    return new_priv;
-
-}
-
 void *RADEONEXACreatePixmap2(ScreenPtr pScreen, int width, int height,
 			     int depth, int usage_hint, int bitsPerPixel,
 			     int *new_pitch)
diff --git a/src/radeon_exa_funcs.c b/src/radeon_exa_funcs.c
index da0524ed..add89458 100644
--- a/src/radeon_exa_funcs.c
+++ b/src/radeon_exa_funcs.c
@@ -638,7 +638,6 @@ Bool RADEONDrawInit(ScreenPtr pScreen)
     }
 #endif
 
-    info->accel_state->exa->CreatePixmap = RADEONEXACreatePixmap;
     info->accel_state->exa->DestroyPixmap = RADEONEXADestroyPixmap;
     info->accel_state->exa->PixmapIsOffscreen = RADEONEXAPixmapIsOffscreen;
     info->accel_state->exa->PrepareAccess = RADEONPrepareAccess_CS;
commit 25836375e0aab17a2e6bd91acb1c19b837ae2109
Author: Michel Dänzer <michel.daenzer at amd.com>
Date:   Thu May 17 18:18:42 2018 +0200

    Drop unused drmmode_create_bo_pixmap surface parameter
    
    Reviewed-by: Alex Deucher <alexander.deucher at amd.com>

diff --git a/src/drmmode_display.c b/src/drmmode_display.c
index f056bf3b..958532fb 100644
--- a/src/drmmode_display.c
+++ b/src/drmmode_display.c
@@ -111,7 +111,7 @@ static PixmapPtr drmmode_create_bo_pixmap(ScrnInfoPtr pScrn,
 					  int width, int height,
 					  int depth, int bpp,
 					  int pitch,
-					  struct radeon_bo *bo, struct radeon_surface *psurf)
+					  struct radeon_bo *bo)
 {
 	RADEONInfoPtr info = RADEONPTR(pScrn);
 	ScreenPtr pScreen = pScrn->pScreen;
@@ -137,9 +137,7 @@ static PixmapPtr drmmode_create_bo_pixmap(ScrnInfoPtr pScrn,
 
 	if (info->ChipFamily >= CHIP_FAMILY_R600) {
 		surface = radeon_get_pixmap_surface(pixmap);
-		if (surface && psurf) 
-			*surface = *psurf;
-		else if (surface) {
+		if (surface) {
 			memset(surface, 0, sizeof(struct radeon_surface));
 			surface->npix_x = width;
 			surface->npix_y = height;
@@ -444,7 +442,7 @@ create_pixmap_for_fbcon(drmmode_ptr drmmode,
 
 	pixmap = drmmode_create_bo_pixmap(pScrn, fbcon->width, fbcon->height,
 					  fbcon->depth, fbcon->bpp, fbcon->pitch,
-					  bo, NULL);
+					  bo);
 	info->fbcon_pixmap = pixmap;
 	radeon_bo_unref(bo);
 out_free_fb:
@@ -581,7 +579,7 @@ drmmode_crtc_scanout_create(xf86CrtcPtr crtc, struct drmmode_scanout *scanout,
 						 width, height,
 						 pScrn->depth,
 						 pScrn->bitsPerPixel,
-						 pitch, scanout->bo, NULL);
+						 pitch, scanout->bo);
 	if (!scanout->pixmap) {
 		ErrorF("failed to create CRTC scanout pixmap\n");
 		goto error;


More information about the xorg-commit mailing list