[PATCH xf86-video-ati 09/10] Add struct radeon_buffer

Michel Dänzer michel at daenzer.net
Thu Jul 5 12:13:06 UTC 2018


From: Michel Dänzer <michel.daenzer at amd.com>

Inspired by amdgpu, preparation for the following change. For now, this
is mostly a wrapper around struct radeon_bo, no functional change
intended.

Signed-off-by: Michel Dänzer <michel.daenzer at amd.com>
---
 src/drmmode_display.c               | 123 ++++++++++------------------
 src/drmmode_display.h               |   2 +-
 src/evergreen_exa.c                 |  40 ++++-----
 src/evergreen_state.h               |   1 -
 src/evergreen_textured_videofuncs.c |   2 +-
 src/r600_exa.c                      |  40 ++++-----
 src/r600_state.h                    |   1 -
 src/r600_textured_videofuncs.c      |   2 +-
 src/radeon.h                        |  31 ++++---
 src/radeon_bo_helper.c              |  34 +++++---
 src/radeon_bo_helper.h              |  38 ++++++++-
 src/radeon_dri2.c                   |  22 ++---
 src/radeon_dri3.c                   |   4 +-
 src/radeon_exa.c                    |  17 ++--
 src/radeon_exa_funcs.c              |  43 +++++-----
 src/radeon_exa_shared.c             |   2 +-
 src/radeon_exa_shared.h             |   3 +-
 src/radeon_glamor.c                 |  10 +--
 src/radeon_glamor_wrappers.c        |   6 +-
 src/radeon_kms.c                    | 104 ++++++++---------------
 src/radeon_present.c                |   2 +-
 src/radeon_textured_videofuncs.c    |  24 ++++--
 22 files changed, 267 insertions(+), 284 deletions(-)

diff --git a/src/drmmode_display.c b/src/drmmode_display.c
index 3c4d94fd9..c91f5bb20 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 e0b97e721..23460fdc0 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 41edd3453..dae8b6a15 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 ef3310025..7e54e1c7f 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 20805ff40..536756001 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 a111dd456..bd824c877 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 4898e8de8..343459967 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 d20df7e2e..c8a9b1978 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 499e89f92..648fd98a5 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 7cfe91265..2b836bbf6 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 fa99201b2..53af87c37 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 6f4691276..584a1d9d1 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 3e689ffd7..b199c7937 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 ef60bc0c1..90d92d7b8 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 add89458f..819b42580 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 cca1c67ea..94238a5a9 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 3df7fa207..fe28c2302 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 6cff72e1f..c1d961604 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 94700a7b9..79d98cc77 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 d4b59e81b..d3eeebea8 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 66805d7df..2982d7286 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 653de44de..0959b119a 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) {
-- 
2.18.0



More information about the amd-gfx mailing list