xf86-video-ati: Branch 'master'

Jerome Glisse glisse at kemper.freedesktop.org
Mon Feb 6 16:01:08 PST 2012


 configure.ac                        |    2 
 src/drmmode_display.c               |  136 +++++++++++++++++++++++++++----
 src/evergreen_accel.c               |  157 +++++++++++++++++++++++++++++++++---
 src/evergreen_exa.c                 |   53 ++++++++++++
 src/evergreen_state.h               |    6 +
 src/evergreen_textured_videofuncs.c |    7 +
 src/r600_exa.c                      |   96 ++++++++++++++++------
 src/r600_state.h                    |    6 +
 src/r600_textured_videofuncs.c      |    7 +
 src/r6xx_accel.c                    |   59 +++++++++++--
 src/radeon.h                        |   14 +++
 src/radeon_dri2.c                   |   70 +++++-----------
 src/radeon_drm.h                    |   23 +++--
 src/radeon_exa.c                    |   84 ++++++++++++++++++-
 src/radeon_kms.c                    |   74 ++++++++++++++++
 15 files changed, 671 insertions(+), 123 deletions(-)

New commits:
commit 615033f2b5e3817e335e9d022fc9fdcf8ac8b11a
Author: Jerome Glisse <jglisse at redhat.com>
Date:   Tue Dec 13 11:08:19 2011 -0500

    r600-evergreen: use common surface allocator for tiling v11
    
    Use libdrm common surface code so mesa,ddx have same idea
    about tiling surface and what their pitch should be and
    the alignment constraint.
    
    v2 fix remaining issue add new option to conditionaly enable
    v3 fix fbcon copy and r600 exa copy path
    v4 fix non tiled path 2D tiling on GPU >= R600, set it to false
       as default
    v5 adapt to pixel/element size split of libdrm/radeon
    v6 update to properly handle falling back to 1d tiled
    v6 final fix to tile split value on evergreen and newer
    v7 fix default array mode on r6xx, fix height alignment issue
       on evergreen
    v8 fix tile split value
    v9 add stencil tile split support, simplify dri2 for stencil
       with evergreen
    v10 Try to fix xv path regarding tiling. Adapt to libdrm API
        change. Try to fix case where there is no surface which
        means non tiled bo.
    v11 check for proper libdrm
    
    Signed-off-by: Jerome Glisse <jglisse at redhat.com>

diff --git a/configure.ac b/configure.ac
index ec54478..29f129a 100644
--- a/configure.ac
+++ b/configure.ac
@@ -141,7 +141,7 @@ if test "$DRI" = yes; then
 	   	AC_CHECK_HEADER(xf86drmMode.h,[DRM_MODE=yes],[DRM_MODE=no],[#include <stdint.h>
 #include <stdlib.h>])
 		if test "x$DRM_MODE" = xyes; then
-			PKG_CHECK_MODULES(LIBDRM_RADEON, [xorg-server >= 1.6.2 libdrm_radeon],
+			PKG_CHECK_MODULES(LIBDRM_RADEON, [xorg-server >= 1.6.2 libdrm >= 2.4.31 libdrm_radeon],
 			[LIBDRM_RADEON=yes], [LIBDRM_RADEON=no])
 
 			if test "x$LIBDRM_RADEON" = xyes; then
diff --git a/src/drmmode_display.c b/src/drmmode_display.c
index 02968d5..89ac6d7 100644
--- a/src/drmmode_display.c
+++ b/src/drmmode_display.c
@@ -49,12 +49,16 @@
 #include <X11/extensions/dpms.h>
 #endif
 
-static PixmapPtr drmmode_create_bo_pixmap(ScreenPtr pScreen,
+static PixmapPtr drmmode_create_bo_pixmap(ScrnInfoPtr pScrn,
 					  int width, int height,
 					  int depth, int bpp,
-					  int pitch, struct radeon_bo *bo)
+					  int pitch, int tiling,
+					  struct radeon_bo *bo)
 {
+	RADEONInfoPtr info = RADEONPTR(pScrn);
+	ScreenPtr pScreen = pScrn->pScreen;
 	PixmapPtr pixmap;
+	struct radeon_surface *surface;
 
 	pixmap = (*pScreen->CreatePixmap)(pScreen, 0, 0, depth, 0);
 	if (!pixmap)
@@ -67,6 +71,37 @@ static PixmapPtr drmmode_create_bo_pixmap(ScreenPtr pScreen,
 
 	exaMoveInPixmap(pixmap);
 	radeon_set_pixmap_bo(pixmap, bo);
+	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;
+		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 (radeon_surface_best(info->surf_man, surface)) {
+			return FALSE;
+		}
+		if (radeon_surface_init(info->surf_man, surface)) {
+			return FALSE;
+		}
+	}
 
 	return pixmap;
 }
@@ -159,7 +194,6 @@ create_pixmap_for_fbcon(drmmode_ptr drmmode,
 {
 	xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
 	drmmode_crtc_private_ptr drmmode_crtc;
-	ScreenPtr pScreen = pScrn->pScreen;
 	PixmapPtr pixmap;
 	struct radeon_bo *bo;
 	drmModeFBPtr fbcon;
@@ -185,9 +219,9 @@ create_pixmap_for_fbcon(drmmode_ptr drmmode,
 		return NULL;
 	}
 
-	pixmap = drmmode_create_bo_pixmap(pScreen, fbcon->width, fbcon->height,
+	pixmap = drmmode_create_bo_pixmap(pScrn, fbcon->width, fbcon->height,
 					  fbcon->depth, fbcon->bpp,
-					  fbcon->pitch, bo);
+					  fbcon->pitch, 0, bo);
 	if (!pixmap) 
 		return NULL;
 
@@ -225,9 +259,13 @@ void drmmode_copy_fb(ScrnInfoPtr pScrn, drmmode_ptr drmmode)
 		return;
 
 	if (info->allowColorTiling) {
-		if (info->ChipFamily >= CHIP_FAMILY_R600)
-			tiling_flags |= RADEON_TILING_MICRO;
-		else
+		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;
 	}
 
@@ -235,10 +273,10 @@ void drmmode_copy_fb(ScrnInfoPtr pScrn, drmmode_ptr drmmode)
 			     drmmode_get_pitch_align(pScrn, info->CurrentLayout.pixel_bytes, tiling_flags)) *
 		info->CurrentLayout.pixel_bytes;
 
-	dst = drmmode_create_bo_pixmap(pScreen, pScrn->virtualX,
+	dst = drmmode_create_bo_pixmap(pScrn, pScrn->virtualX,
 				       pScrn->virtualY, pScrn->depth,
 				       pScrn->bitsPerPixel, pitch,
-				       info->front_bo);
+				       tiling_flags, info->front_bo);
 	if (!dst)
 		goto out_free_src;
 
@@ -292,6 +330,9 @@ drmmode_set_mode_major(xf86CrtcPtr crtc, DisplayModePtr mode,
 	pitch = RADEON_ALIGN(pScrn->displayWidth, drmmode_get_pitch_align(pScrn, info->CurrentLayout.pixel_bytes, tiling_flags)) *
 		info->CurrentLayout.pixel_bytes;
 	height = RADEON_ALIGN(pScrn->virtualY, drmmode_get_height_align(pScrn, tiling_flags));
+	if (info->ChipFamily >= CHIP_FAMILY_R600) {
+		pitch = info->front_surface.level[0].pitch_bytes;
+	}
 
 	if (drmmode->fb_id == 0) {
 		ret = drmModeAddFB(drmmode->fd,
@@ -503,12 +544,12 @@ drmmode_crtc_shadow_create(xf86CrtcPtr crtc, void *data, int width, int height)
 
 	rotate_pitch = RADEON_ALIGN(width, drmmode_get_pitch_align(pScrn, drmmode->cpp, 0)) * drmmode->cpp;
 
-	rotate_pixmap = drmmode_create_bo_pixmap(pScrn->pScreen,
+	rotate_pixmap = drmmode_create_bo_pixmap(pScrn,
 						 width, height,
 						 pScrn->depth,
 						 pScrn->bitsPerPixel,
 						 rotate_pitch,
-						 drmmode_crtc->rotate_bo);
+						 0, drmmode_crtc->rotate_bo);
 	if (rotate_pixmap == NULL) {
 		xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
 			   "Couldn't allocate shadow pixmap for rotated CRTC\n");
@@ -1206,7 +1247,9 @@ drmmode_xf86crtc_resize (ScrnInfoPtr scrn, int width, int height)
 	int screen_size;
 	int cpp = info->CurrentLayout.pixel_bytes;
 	struct radeon_bo *front_bo;
-	uint32_t tiling_flags = 0;
+	struct radeon_surface surface;
+	struct radeon_surface *psurface;
+	uint32_t tiling_flags = 0, base_align;
 	PixmapPtr ppix = screen->GetScreenPixmap(screen);
 	void *fb_shadow;
 
@@ -1220,15 +1263,69 @@ drmmode_xf86crtc_resize (ScrnInfoPtr scrn, int width, int height)
 		radeon_bo_wait(front_bo);
 
 	if (info->allowColorTiling) {
-		if (info->ChipFamily >= CHIP_FAMILY_R600)
-			tiling_flags |= RADEON_TILING_MICRO;
-		else
+		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;
 	height = RADEON_ALIGN(height, drmmode_get_height_align(scrn, tiling_flags));
 	screen_size = RADEON_ALIGN(pitch * height, RADEON_GPU_PAGE_SIZE);
+	base_align = 4096;
+	if (info->ChipFamily >= CHIP_FAMILY_R600) {
+		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;
+		surface.flags |= RADEON_SURF_SET(RADEON_SURF_TYPE_2D, TYPE);
+		surface.flags |= RADEON_SURF_SET(RADEON_SURF_MODE_LINEAR, MODE);
+		if (tiling_flags & RADEON_TILING_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)) {
+			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;
+			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;
+		}
+		info->front_surface = surface;
+	}
 
 	xf86DrvMsg(scrn->scrnIndex, X_INFO,
 		   "Allocate new frame buffer %dx%d stride %d\n",
@@ -1244,7 +1341,7 @@ drmmode_xf86crtc_resize (ScrnInfoPtr scrn, int width, int height)
 	scrn->virtualY = height;
 	scrn->displayWidth = pitch / cpp;
 
-	info->front_bo = radeon_bo_open(info->bufmgr, 0, screen_size, 0, RADEON_GEM_DOMAIN_VRAM, 0);
+	info->front_bo = radeon_bo_open(info->bufmgr, 0, screen_size, base_align, RADEON_GEM_DOMAIN_VRAM, 0);
 	if (!info->front_bo)
 		goto fail;
 
@@ -1270,6 +1367,8 @@ drmmode_xf86crtc_resize (ScrnInfoPtr scrn, int width, int height)
 
 	if (!info->r600_shadow_fb) {
 		radeon_set_pixmap_bo(ppix, info->front_bo);
+		psurface = radeon_get_pixmap_surface(ppix);
+		*psurface = info->front_surface;
 		screen->ModifyPixmapHeader(ppix,
 					   width, height, -1, -1, pitch, NULL);
 	} else {
@@ -1671,6 +1770,9 @@ Bool radeon_do_pageflip(ScrnInfoPtr scrn, struct radeon_bo *new_front, void *dat
 	pitch = RADEON_ALIGN(scrn->displayWidth, drmmode_get_pitch_align(scrn, info->CurrentLayout.pixel_bytes, tiling_flags)) *
 		info->CurrentLayout.pixel_bytes;
 	height = RADEON_ALIGN(scrn->virtualY, drmmode_get_height_align(scrn, tiling_flags));
+	if (info->ChipFamily >= CHIP_FAMILY_R600 && info->surf_man) {
+		pitch = info->front_surface.level[0].pitch_bytes;
+	}
 
 	/*
 	 * Create a new handle for the back buffer
diff --git a/src/evergreen_accel.c b/src/evergreen_accel.c
index 6610c28..3c76d38 100644
--- a/src/evergreen_accel.c
+++ b/src/evergreen_accel.c
@@ -75,6 +75,57 @@ evergreen_start_3d(ScrnInfoPtr pScrn)
 
 }
 
+unsigned eg_tile_split(unsigned tile_split)
+{
+	switch (tile_split) {
+	case 64:	tile_split = 0;	break;
+	case 128:	tile_split = 1;	break;
+	case 256:	tile_split = 2;	break;
+	case 512:	tile_split = 3;	break;
+	case 1024:	tile_split = 4;	break;
+	case 2048:	tile_split = 5;	break;
+	default:
+	case 4096:	tile_split = 6;	break;
+	}
+	return tile_split;
+}
+
+static unsigned eg_macro_tile_aspect(unsigned macro_tile_aspect)
+{
+	switch (macro_tile_aspect) {
+	default:
+	case 1:	macro_tile_aspect = 0;	break;
+	case 2:	macro_tile_aspect = 1;	break;
+	case 4:	macro_tile_aspect = 2;	break;
+	case 8:	macro_tile_aspect = 3;	break;
+	}
+	return macro_tile_aspect;
+}
+
+static unsigned eg_bank_wh(unsigned bankwh)
+{
+	switch (bankwh) {
+	default:
+	case 1:	bankwh = 0;	break;
+	case 2:	bankwh = 1;	break;
+	case 4:	bankwh = 2;	break;
+	case 8:	bankwh = 3;	break;
+	}
+	return bankwh;
+}
+
+static unsigned eg_nbanks(unsigned nbanks)
+{
+	switch (nbanks) {
+	default:
+	case 2: nbanks = 0; break;
+	case 4: nbanks = 1; break;
+	case 8: nbanks = 2; break;
+	case 16: nbanks = 3; break;
+	}
+	return nbanks;
+}
+
 /*
  * Setup of functional groups
  */
@@ -154,12 +205,59 @@ void
 evergreen_set_render_target(ScrnInfoPtr pScrn, cb_config_t *cb_conf, uint32_t domain)
 {
     uint32_t cb_color_info, cb_color_attrib = 0, cb_color_dim;
-    int pitch, slice, h;
+    unsigned pitch, slice, w, h, array_mode, nbanks;
+    uint32_t tile_split, macro_aspect, bankw, bankh;
     RADEONInfoPtr info = RADEONPTR(pScrn);
 
+#if defined(XF86DRM_MODE)
+    if (cb_conf->surface) {
+	switch (cb_conf->surface->level[0].mode) {
+	case RADEON_SURF_MODE_1D:
+		array_mode = 2;
+		break;
+	case RADEON_SURF_MODE_2D:
+		array_mode = 4;
+		break;
+	default:
+		array_mode = 0;
+		break;
+	}
+	w = cb_conf->surface->level[0].npix_x;
+	h = cb_conf->surface->level[0].npix_y;
+	pitch = (cb_conf->surface->level[0].nblk_x >> 3) - 1;
+	slice = ((cb_conf->surface->level[0].nblk_x * cb_conf->surface->level[0].nblk_y) / 64) - 1;
+	tile_split = cb_conf->surface->tile_split;
+	macro_aspect = cb_conf->surface->mtilea;
+	bankw = cb_conf->surface->bankw;
+	bankh = cb_conf->surface->bankh;
+	tile_split = eg_tile_split(tile_split);
+	macro_aspect = eg_macro_tile_aspect(macro_aspect);
+	bankw = eg_bank_wh(bankw);
+	bankh = eg_bank_wh(bankh);
+    } else
+#endif
+    {
+	pitch = (cb_conf->w / 8) - 1;
+	h = RADEON_ALIGN(cb_conf->h, 8);
+	slice = ((cb_conf->w * h) / 64) - 1;
+	array_mode = cb_conf->array_mode;
+	w = cb_conf->w;
+	tile_split = 4;
+	macro_aspect = 0;
+	bankw = 0;
+	bankh = 0;
+    }
+    nbanks = info->num_banks;
+    nbanks = eg_nbanks(nbanks);
+
+    cb_color_attrib |= (tile_split << CB_COLOR0_ATTRIB__TILE_SPLIT_shift)|
+		       (nbanks << CB_COLOR0_ATTRIB__NUM_BANKS_shift) |
+		       (bankw << CB_COLOR0_ATTRIB__BANK_WIDTH_shift) |
+		       (bankh << CB_COLOR0_ATTRIB__BANK_HEIGHT_shift) |
+		       (macro_aspect << CB_COLOR0_ATTRIB__MACRO_TILE_ASPECT_shift);
     cb_color_info = ((cb_conf->endian      << ENDIAN_shift)				|
 		     (cb_conf->format      << CB_COLOR0_INFO__FORMAT_shift)		|
-		     (cb_conf->array_mode  << CB_COLOR0_INFO__ARRAY_MODE_shift)		|
+		     (array_mode  << CB_COLOR0_INFO__ARRAY_MODE_shift)		|
 		     (cb_conf->number_type << NUMBER_TYPE_shift)			|
 		     (cb_conf->comp_swap   << COMP_SWAP_shift)				|
 		     (cb_conf->source_format << SOURCE_FORMAT_shift)                    |
@@ -185,10 +283,6 @@ evergreen_set_render_target(ScrnInfoPtr pScrn, cb_config_t *cb_conf, uint32_t do
     if (cb_conf->non_disp_tiling)
 	cb_color_attrib |= CB_COLOR0_ATTRIB__NON_DISP_TILING_ORDER_bit;
 
-    pitch = (cb_conf->w / 8) - 1;
-    h = RADEON_ALIGN(cb_conf->h, 8);
-    slice = ((cb_conf->w * h) / 64) - 1;
-
     switch (cb_conf->resource_type) {
     case BUFFER:
 	/* number of elements in the surface */
@@ -196,7 +290,7 @@ evergreen_set_render_target(ScrnInfoPtr pScrn, cb_config_t *cb_conf, uint32_t do
 	break;
     default:
 	/* w/h of the surface */
-	cb_color_dim = (((cb_conf->w - 1) << WIDTH_MAX_shift) |
+	cb_color_dim = (((w - 1) << WIDTH_MAX_shift) |
 			((cb_conf->h - 1) << HEIGHT_MAX_shift));
 	break;
     }
@@ -601,17 +695,53 @@ evergreen_set_tex_resource(ScrnInfoPtr pScrn, tex_resource_t *tex_res, uint32_t
     RADEONInfoPtr info = RADEONPTR(pScrn);
     uint32_t sq_tex_resource_word0, sq_tex_resource_word1, sq_tex_resource_word4;
     uint32_t sq_tex_resource_word5, sq_tex_resource_word6, sq_tex_resource_word7;
+    uint32_t array_mode, pitch, tile_split, macro_aspect, bankw, bankh, nbanks;
+
+#if defined(XF86DRM_MODE)
+    if (tex_res->surface) {
+	switch (tex_res->surface->level[0].mode) {
+	case RADEON_SURF_MODE_1D:
+		array_mode = 2;
+		break;
+	case RADEON_SURF_MODE_2D:
+		array_mode = 4;
+		break;
+	default:
+		array_mode = 0;
+		break;
+	}
+	pitch = tex_res->surface->level[0].nblk_x >> 3;
+	tile_split = tex_res->surface->tile_split;
+	macro_aspect = tex_res->surface->mtilea;
+	bankw = tex_res->surface->bankw;
+	bankh = tex_res->surface->bankh;
+	tile_split = eg_tile_split(tile_split);
+	macro_aspect = eg_macro_tile_aspect(macro_aspect);
+	bankw = eg_bank_wh(bankw);
+	bankh = eg_bank_wh(bankh);
+    } else
+#endif
+    {
+	array_mode = tex_res->array_mode;
+	pitch = (tex_res->pitch + 7) >> 3;
+	tile_split = 4;
+	macro_aspect = 0;
+	bankw = 0;
+	bankh = 0;
+    }
+    nbanks = info->num_banks;
+    nbanks = eg_nbanks(nbanks);
 
     sq_tex_resource_word0 = (tex_res->dim << DIM_shift);
 
     if (tex_res->w)
-	sq_tex_resource_word0 |= (((((tex_res->pitch + 7) >> 3) - 1) << PITCH_shift) |
-				  ((tex_res->w - 1) << TEX_WIDTH_shift));
+	sq_tex_resource_word0 |= ( ((pitch - 1) << PITCH_shift) |
+				   ((tex_res->w - 1) << TEX_WIDTH_shift) );
 
     if (tex_res->tile_type)
 	sq_tex_resource_word0 |= SQ_TEX_RESOURCE_WORD0_0__NON_DISP_TILING_ORDER_bit;
 
-    sq_tex_resource_word1 = (tex_res->array_mode << SQ_TEX_RESOURCE_WORD1_0__ARRAY_MODE_shift);
+    sq_tex_resource_word1 = (array_mode << SQ_TEX_RESOURCE_WORD1_0__ARRAY_MODE_shift);
 
     if (tex_res->h)
 	sq_tex_resource_word1 |= ((tex_res->h - 1) << TEX_HEIGHT_shift);
@@ -640,12 +770,17 @@ evergreen_set_tex_resource(ScrnInfoPtr pScrn, tex_resource_t *tex_res, uint32_t
 			     (tex_res->last_array << LAST_ARRAY_shift));
 
     sq_tex_resource_word6 = ((tex_res->min_lod << SQ_TEX_RESOURCE_WORD6_0__MIN_LOD_shift) |
-			     (tex_res->perf_modulation << PERF_MODULATION_shift));
+			     (tex_res->perf_modulation << PERF_MODULATION_shift) |
+			     (tile_split << SQ_TEX_RESOURCE_WORD6_0__TILE_SPLIT_shift));
 
     if (tex_res->interlaced)
 	sq_tex_resource_word6 |= INTERLACED_bit;
 
     sq_tex_resource_word7 = ((tex_res->format << SQ_TEX_RESOURCE_WORD7_0__DATA_FORMAT_shift) |
+			     (macro_aspect << SQ_TEX_RESOURCE_WORD7_0__MACRO_TILE_ASPECT_shift) |
+			     (nbanks << SQ_TEX_RESOURCE_WORD7_0__NUM_BANKS_shift) |
+			     (bankw << SQ_TEX_RESOURCE_WORD7_0__BANK_WIDTH_shift) |
+			     (bankh << SQ_TEX_RESOURCE_WORD7_0__BANK_HEIGHT_shift) |
 			     (SQ_TEX_VTX_VALID_TEXTURE << SQ_TEX_RESOURCE_WORD7_0__TYPE_shift));
 
     /* flush texture cache */
diff --git a/src/evergreen_exa.c b/src/evergreen_exa.c
index f17e5a6..8c32245 100644
--- a/src/evergreen_exa.c
+++ b/src/evergreen_exa.c
@@ -77,6 +77,10 @@ EVERGREENPrepareSolid(PixmapPtr pPix, int alu, Pixel pm, Pixel fg)
     dst.offset = 0;
     dst.bo = radeon_get_pixmap_bo(pPix);
     dst.tiling_flags = radeon_get_pixmap_tiling(pPix);
+    dst.surface = radeon_get_pixmap_surface(pPix);
+    if (dst.surface->npix_x != pPix->drawable.width) {
+	dst.surface = NULL;
+    }
 
     dst.pitch = exaGetPixmapPitch(pPix) / (pPix->drawable.bitsPerPixel / 8);
     dst.width = pPix->drawable.width;
@@ -129,6 +133,7 @@ EVERGREENPrepareSolid(PixmapPtr pPix, int alu, Pixel pm, Pixel fg)
     cb_conf.h = accel_state->dst_obj.height;
     cb_conf.base = accel_state->dst_obj.offset;
     cb_conf.bo = accel_state->dst_obj.bo;
+    cb_conf.surface = accel_state->dst_obj.surface;
 
     if (accel_state->dst_obj.bpp == 8) {
 	cb_conf.format = COLOR_8;
@@ -313,6 +318,7 @@ EVERGREENDoPrepareCopy(ScrnInfoPtr pScrn)
     tex_res.size                = accel_state->src_size[0];
     tex_res.bo                  = accel_state->src_obj[0].bo;
     tex_res.mip_bo              = accel_state->src_obj[0].bo;
+    tex_res.surface             = accel_state->src_obj[0].surface;
     if (accel_state->src_obj[0].bpp == 8) {
 	tex_res.format              = FMT_8;
 	tex_res.dst_sel_x           = SQ_SEL_1; /* R */
@@ -356,6 +362,7 @@ EVERGREENDoPrepareCopy(ScrnInfoPtr pScrn)
     cb_conf.h = accel_state->dst_obj.height;
     cb_conf.base = accel_state->dst_obj.offset;
     cb_conf.bo = accel_state->dst_obj.bo;
+    cb_conf.surface = accel_state->dst_obj.surface;
     if (accel_state->dst_obj.bpp == 8) {
 	cb_conf.format = COLOR_8;
 	cb_conf.comp_swap = 3; /* A */
@@ -467,8 +474,18 @@ EVERGREENPrepareCopy(PixmapPtr pSrc,   PixmapPtr pDst,
     dst_obj.offset = 0;
     src_obj.bo = radeon_get_pixmap_bo(pSrc);
     dst_obj.bo = radeon_get_pixmap_bo(pDst);
+    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 (dst_obj.surface->npix_x != pDst->drawable.width) {
+        dst_obj.surface = NULL;
+	dst_obj.tiling_flags = 0;
+    }
+    if (src_obj.surface->npix_x != pSrc->drawable.width) {
+        src_obj.surface = NULL;
+	src_obj.tiling_flags = 0;
+    }
     if (radeon_get_pixmap_bo(pSrc) == radeon_get_pixmap_bo(pDst))
 	accel_state->same_surface = TRUE;
 
@@ -495,6 +512,9 @@ EVERGREENPrepareCopy(PixmapPtr pSrc,   PixmapPtr pDst,
 				       drmmode_get_height_align(pScrn, accel_state->dst_obj.tiling_flags));
 	unsigned long size = height * accel_state->dst_obj.pitch * pDst->drawable.bitsPerPixel/8;
 
+	if (accel_state->dst_obj.surface)
+		size = accel_state->dst_obj.surface->bo_size;
+
 	if (accel_state->copy_area_bo) {
 	    radeon_bo_unref(accel_state->copy_area_bo);
 	    accel_state->copy_area_bo = NULL;
@@ -576,6 +596,8 @@ EVERGREENCopy(PixmapPtr pDst,
 	uint32_t orig_dst_tiling_flags = accel_state->dst_obj.tiling_flags;
 	struct radeon_bo *orig_bo = accel_state->dst_obj.bo;
 	int orig_rop = accel_state->rop;
+	struct radeon_surface *orig_dst_surface = accel_state->dst_obj.surface;
+	struct radeon_surface *orig_src_surface = accel_state->src_obj[0].surface;
 
 	/* src to tmp */
 	accel_state->dst_obj.domain = RADEON_GEM_DOMAIN_VRAM;
@@ -583,6 +605,7 @@ EVERGREENCopy(PixmapPtr pDst,
 	accel_state->dst_obj.offset = 0;
 	accel_state->dst_obj.tiling_flags = 0;
 	accel_state->rop = 3;
+	accel_state->dst_obj.surface = NULL;
 	EVERGREENDoPrepareCopy(pScrn);
 	EVERGREENAppendCopyVertex(pScrn, srcX, srcY, dstX, dstY, w, h);
 	EVERGREENDoCopy(pScrn);
@@ -592,11 +615,13 @@ EVERGREENCopy(PixmapPtr pDst,
 	accel_state->src_obj[0].bo = accel_state->copy_area_bo;
 	accel_state->src_obj[0].offset = 0;
 	accel_state->src_obj[0].tiling_flags = 0;
+	accel_state->src_obj[0].surface = NULL;
 	accel_state->dst_obj.domain = orig_dst_domain;
 	accel_state->dst_obj.bo = orig_bo;
 	accel_state->dst_obj.offset = 0;
 	accel_state->dst_obj.tiling_flags = orig_dst_tiling_flags;
 	accel_state->rop = orig_rop;
+	accel_state->dst_obj.surface = orig_dst_surface;
 	EVERGREENDoPrepareCopy(pScrn);
 	EVERGREENAppendCopyVertex(pScrn, dstX, dstY, dstX, dstY, w, h);
 	EVERGREENDoCopyVline(pDst);
@@ -606,6 +631,7 @@ EVERGREENCopy(PixmapPtr pDst,
 	accel_state->src_obj[0].bo = orig_bo;
 	accel_state->src_obj[0].offset = 0;
 	accel_state->src_obj[0].tiling_flags = orig_src_tiling_flags;
+	accel_state->src_obj[0].surface = orig_src_surface;
     } else
 	EVERGREENAppendCopyVertex(pScrn, srcX, srcY, dstX, dstY, w, h);
 
@@ -851,6 +877,7 @@ static Bool EVERGREENTextureSetup(PicturePtr pPict, PixmapPtr pPix,
     tex_res.format              = EVERGREENTexFormats[i].card_fmt;
     tex_res.bo                  = accel_state->src_obj[unit].bo;
     tex_res.mip_bo              = accel_state->src_obj[unit].bo;
+    tex_res.surface             = accel_state->src_obj[unit].surface;
 
 #if X_BYTE_ORDER == X_BIG_ENDIAN
     switch (accel_state->src_obj[unit].bpp) {
@@ -1133,8 +1160,18 @@ static Bool EVERGREENPrepareComposite(int op, PicturePtr pSrcPicture,
     dst_obj.offset = 0;
     src_obj.bo = radeon_get_pixmap_bo(pSrc);
     dst_obj.bo = radeon_get_pixmap_bo(pDst);
+    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 (dst_obj.surface->npix_x != pDst->drawable.width) {
+        dst_obj.surface = NULL;
+	dst_obj.tiling_flags = 0;
+    }
+    if (src_obj.surface->npix_x != pSrc->drawable.width) {
+        src_obj.surface = NULL;
+	src_obj.tiling_flags = 0;
+    }
 
     src_obj.pitch = exaGetPixmapPitch(pSrc) / (pSrc->drawable.bitsPerPixel / 8);
     dst_obj.pitch = exaGetPixmapPitch(pDst) / (pDst->drawable.bitsPerPixel / 8);
@@ -1154,6 +1191,10 @@ static Bool EVERGREENPrepareComposite(int op, PicturePtr pSrcPicture,
 	mask_obj.bo = radeon_get_pixmap_bo(pMask);
 	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);
+	if (mask_obj.surface->npix_x != pMask->drawable.width) {
+		mask_obj.surface = NULL;
+	}
 
 	mask_obj.width = pMask->drawable.width;
 	mask_obj.height = pMask->drawable.height;
@@ -1262,6 +1303,7 @@ static Bool EVERGREENPrepareComposite(int op, PicturePtr pSrcPicture,
     cb_conf.base = accel_state->dst_obj.offset;
     cb_conf.format = dst_format;
     cb_conf.bo = accel_state->dst_obj.bo;
+    cb_conf.surface = accel_state->dst_obj.surface;
 
     switch (pDstPicture->format) {
     case PICT_a8r8g8b8:
@@ -1500,6 +1542,7 @@ EVERGREENUploadToScreen(PixmapPtr pDst, int x, int y, int w, int h,
     src_obj.domain = RADEON_GEM_DOMAIN_GTT;
     src_obj.bo = scratch;
     src_obj.tiling_flags = 0;
+    src_obj.surface = NULL;
 
     dst_obj.pitch = dst_pitch_hw;
     dst_obj.width = pDst->drawable.width;
@@ -1509,6 +1552,11 @@ EVERGREENUploadToScreen(PixmapPtr pDst, int x, int y, int w, int h,
     dst_obj.domain = RADEON_GEM_DOMAIN_VRAM;
     dst_obj.bo = radeon_get_pixmap_bo(pDst);
     dst_obj.tiling_flags = radeon_get_pixmap_tiling(pDst);
+    dst_obj.surface = radeon_get_pixmap_surface(pDst);
+    if (dst_obj.surface->npix_x != pDst->drawable.width) {
+	dst_obj.surface = NULL;
+	dst_obj.tiling_flags = 0;
+    }
 
     if (!R600SetAccelState(pScrn,
 			   &src_obj,
@@ -1639,6 +1687,10 @@ EVERGREENDownloadFromScreen(PixmapPtr pSrc, int x, int y, int w,
     src_obj.domain = RADEON_GEM_DOMAIN_VRAM | RADEON_GEM_DOMAIN_GTT;
     src_obj.bo = radeon_get_pixmap_bo(pSrc);
     src_obj.tiling_flags = radeon_get_pixmap_tiling(pSrc);
+    src_obj.surface = radeon_get_pixmap_surface(pSrc);
+    if (src_obj.surface->npix_x != pSrc->drawable.width) {
+	    src_obj.surface = NULL;
+    }
 
     dst_obj.pitch = scratch_pitch;
     dst_obj.width = w;
@@ -1648,6 +1700,7 @@ EVERGREENDownloadFromScreen(PixmapPtr pSrc, int x, int y, int w,
     dst_obj.bpp = bpp;
     dst_obj.domain = RADEON_GEM_DOMAIN_GTT;
     dst_obj.tiling_flags = 0;
+    dst_obj.surface = NULL;
 
     if (!R600SetAccelState(pScrn,
 			   &src_obj,
diff --git a/src/evergreen_state.h b/src/evergreen_state.h
index 5fd85f8..5a29f8f 100644
--- a/src/evergreen_state.h
+++ b/src/evergreen_state.h
@@ -93,6 +93,9 @@ typedef struct {
     int blend_enable;
     uint32_t blendcntl;
     struct radeon_bo *bo;
+#ifdef XF86DRM_MODE
+    struct radeon_surface *surface;
+#endif
 } cb_config_t;
 
 /* Shader */
@@ -179,6 +182,9 @@ typedef struct {
     int min_lod;
     struct radeon_bo *bo;
     struct radeon_bo *mip_bo;
+#ifdef XF86DRM_MODE
+    struct radeon_surface *surface;
+#endif
 } tex_resource_t;
 
 /* Texture sampler */
diff --git a/src/evergreen_textured_videofuncs.c b/src/evergreen_textured_videofuncs.c
index d27a02a..4cf8640 100644
--- a/src/evergreen_textured_videofuncs.c
+++ b/src/evergreen_textured_videofuncs.c
@@ -158,6 +158,10 @@ EVERGREENDisplayTexturedVideo(ScrnInfoPtr pScrn, RADEONPortPrivPtr pPriv)
     src_obj.offset = 0;
     dst_obj.bo = radeon_get_pixmap_bo(pPixmap);
     dst_obj.tiling_flags = radeon_get_pixmap_tiling(pPixmap);
+    dst_obj.surface = radeon_get_pixmap_surface(pPixmap);
+    if (dst_obj.surface->npix_x != pPixmap->drawable.width) {
+	    dst_obj.surface = NULL;
+    }
 
     dst_obj.pitch = exaGetPixmapPitch(pPixmap) / (pPixmap->drawable.bitsPerPixel / 8);
 
@@ -248,6 +252,7 @@ EVERGREENDisplayTexturedVideo(ScrnInfoPtr pScrn, RADEONPortPrivPtr pPriv)
 	tex_res.size                = accel_state->src_size[0];
 	tex_res.bo                  = accel_state->src_obj[0].bo;
 	tex_res.mip_bo              = accel_state->src_obj[0].bo;
+	tex_res.surface             = NULL;
 
 	tex_res.format              = FMT_8;
 	tex_res.dst_sel_x           = SQ_SEL_X; /* Y */
@@ -340,6 +345,7 @@ EVERGREENDisplayTexturedVideo(ScrnInfoPtr pScrn, RADEONPortPrivPtr pPriv)
 	tex_res.size                = accel_state->src_size[0];
 	tex_res.bo                  = accel_state->src_obj[0].bo;
 	tex_res.mip_bo              = accel_state->src_obj[0].bo;
+	tex_res.surface             = NULL;
 
 	tex_res.format              = FMT_8_8;
 	if (pPriv->id == FOURCC_UYVY)
@@ -406,6 +412,7 @@ EVERGREENDisplayTexturedVideo(ScrnInfoPtr pScrn, RADEONPortPrivPtr pPriv)
     cb_conf.h = accel_state->dst_obj.height;
     cb_conf.base = accel_state->dst_obj.offset;
     cb_conf.bo = accel_state->dst_obj.bo;
+    cb_conf.surface = accel_state->dst_obj.surface;
 
     switch (accel_state->dst_obj.bpp) {
     case 16:
diff --git a/src/r600_exa.c b/src/r600_exa.c
index b0c66ee..47218d8 100644
--- a/src/r600_exa.c
+++ b/src/r600_exa.c
@@ -62,15 +62,14 @@ R600SetAccelState(ScrnInfoPtr pScrn,
 	memcpy(&accel_state->src_obj[0], src0, sizeof(struct r600_accel_object));
 	accel_state->src_size[0] = src0->pitch * src0->height * (src0->bpp/8);
 #if defined(XF86DRM_MODE)
-	if (info->cs) {
-	    pitch_align = drmmode_get_pitch_align(pScrn,
-						  accel_state->src_obj[0].bpp / 8,
-						  accel_state->src_obj[0].tiling_flags) - 1;
-	    base_align = drmmode_get_base_align(pScrn,
-						accel_state->src_obj[0].bpp / 8,
-						accel_state->src_obj[0].tiling_flags) - 1;
-	}
+	if (info->cs && src0->surface) {
+		accel_state->src_size[0] = src0->surface->bo_size;
+	} else
 #endif
+	{
+		accel_state->src_obj[0].surface = NULL;
+	}
+
 	/* bad pitch */
 	if (accel_state->src_obj[0].pitch & pitch_align)
 	    RADEON_FALLBACK(("Bad src pitch 0x%08x\n", accel_state->src_obj[0].pitch));
@@ -88,15 +87,14 @@ R600SetAccelState(ScrnInfoPtr pScrn,
 	memcpy(&accel_state->src_obj[1], src1, sizeof(struct r600_accel_object));
 	accel_state->src_size[1] = src1->pitch * src1->height * (src1->bpp/8);
 #if defined(XF86DRM_MODE)
-	if (info->cs) {
-	    pitch_align = drmmode_get_pitch_align(pScrn,
-						  accel_state->src_obj[1].bpp / 8,
-						  accel_state->src_obj[1].tiling_flags) - 1;
-	    base_align = drmmode_get_base_align(pScrn,
-						accel_state->src_obj[1].bpp / 8,
-						accel_state->src_obj[1].tiling_flags) - 1;
-	}
+	if (info->cs && src1->surface) {
+		accel_state->src_size[1] = src1->surface->bo_size;
+	} else
 #endif
+	{
+		accel_state->src_obj[1].surface = NULL;
+	}
+
 	/* bad pitch */
 	if (accel_state->src_obj[1].pitch & pitch_align)
 	    RADEON_FALLBACK(("Bad src pitch 0x%08x\n", accel_state->src_obj[1].pitch));
@@ -113,15 +111,14 @@ R600SetAccelState(ScrnInfoPtr pScrn,
 	memcpy(&accel_state->dst_obj, dst, sizeof(struct r600_accel_object));
 	accel_state->dst_size = dst->pitch * dst->height * (dst->bpp/8);
 #if defined(XF86DRM_MODE)
-	if (info->cs) {
-	    pitch_align = drmmode_get_pitch_align(pScrn,
-						  accel_state->dst_obj.bpp / 8,
-						  accel_state->dst_obj.tiling_flags) - 1;
-	    base_align = drmmode_get_base_align(pScrn,
-						accel_state->dst_obj.bpp / 8,
-						accel_state->dst_obj.tiling_flags) - 1;
-	}
+	if (info->cs && dst->surface) {
+		accel_state->dst_size = dst->surface->bo_size;
+	} else
 #endif
+	{
+		accel_state->dst_obj.surface = NULL;
+		accel_state->dst_obj.tiling_flags = 0;
+	}
 	if (accel_state->dst_obj.pitch & pitch_align)
 	    RADEON_FALLBACK(("Bad dst pitch 0x%08x\n", accel_state->dst_obj.pitch));
 
@@ -197,6 +194,10 @@ R600PrepareSolid(PixmapPtr pPix, int alu, Pixel pm, Pixel fg)
 	dst.offset = 0;
 	dst.bo = radeon_get_pixmap_bo(pPix);
 	dst.tiling_flags = radeon_get_pixmap_tiling(pPix);
+	dst.surface = radeon_get_pixmap_surface(pPix);
+	if (dst.surface->npix_x != pPix->drawable.width) {
+		dst.surface = NULL;
+	}
     } else
 #endif
     {
@@ -254,6 +255,7 @@ R600PrepareSolid(PixmapPtr pPix, int alu, Pixel pm, Pixel fg)
     cb_conf.h = accel_state->dst_obj.height;
     cb_conf.base = accel_state->dst_obj.offset;
     cb_conf.bo = accel_state->dst_obj.bo;
+    cb_conf.surface = accel_state->dst_obj.surface;
 
     if (accel_state->dst_obj.bpp == 8) {
 	cb_conf.format = COLOR_8;
@@ -433,6 +435,7 @@ R600DoPrepareCopy(ScrnInfoPtr pScrn)
     tex_res.size                = accel_state->src_size[0];
     tex_res.bo                  = accel_state->src_obj[0].bo;
     tex_res.mip_bo              = accel_state->src_obj[0].bo;
+    tex_res.surface             = accel_state->src_obj[0].surface;
     if (accel_state->src_obj[0].bpp == 8) {
 	tex_res.format              = FMT_8;
 	tex_res.dst_sel_x           = SQ_SEL_1; /* R */
@@ -477,6 +480,7 @@ R600DoPrepareCopy(ScrnInfoPtr pScrn)
     cb_conf.h = accel_state->dst_obj.height;
     cb_conf.base = accel_state->dst_obj.offset;
     cb_conf.bo = accel_state->dst_obj.bo;
+    cb_conf.surface = accel_state->dst_obj.surface;
     if (accel_state->dst_obj.bpp == 8) {
 	cb_conf.format = COLOR_8;
 	cb_conf.comp_swap = 3; /* A */
@@ -591,6 +595,16 @@ R600PrepareCopy(PixmapPtr pSrc,   PixmapPtr pDst,
 	dst_obj.bo = radeon_get_pixmap_bo(pDst);
 	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 (dst_obj.surface->npix_x != pDst->drawable.width) {
+		dst_obj.surface = NULL;
+		dst_obj.tiling_flags = 0;
+	}
+	if (src_obj.surface->npix_x != pSrc->drawable.width) {
+		src_obj.surface = NULL;
+		src_obj.tiling_flags = 0;
+	}
 	if (radeon_get_pixmap_bo(pSrc) == radeon_get_pixmap_bo(pDst))
 	    accel_state->same_surface = TRUE;
     } else
@@ -626,10 +640,13 @@ R600PrepareCopy(PixmapPtr pSrc,   PixmapPtr pDst,
 #if defined(XF86DRM_MODE)
 	unsigned height = RADEON_ALIGN(pDst->drawable.height,
 				       drmmode_get_height_align(pScrn, accel_state->dst_obj.tiling_flags));
+	unsigned long size = accel_state->dst_obj.surface->bo_size;
+	unsigned long align = accel_state->dst_obj.surface->bo_alignment;
 #else
 	unsigned height = pDst->drawable.height;
-#endif
 	unsigned long size = height * accel_state->dst_obj.pitch * pDst->drawable.bitsPerPixel/8;
+	unsigned long align = 0;
+#endif
 
 #if defined(XF86DRM_MODE)
 	if (info->cs) {
@@ -637,7 +654,7 @@ R600PrepareCopy(PixmapPtr pSrc,   PixmapPtr pDst,
 		radeon_bo_unref(accel_state->copy_area_bo);
 		accel_state->copy_area_bo = NULL;
 	    }
-	    accel_state->copy_area_bo = radeon_bo_open(info->bufmgr, 0, size, 0,
+	    accel_state->copy_area_bo = radeon_bo_open(info->bufmgr, 0, size, align,
 						       RADEON_GEM_DOMAIN_VRAM,
 						       0);
 	    if (accel_state->copy_area_bo == NULL)
@@ -979,6 +996,7 @@ static Bool R600TextureSetup(PicturePtr pPict, PixmapPtr pPix,
     tex_res.format              = R600TexFormats[i].card_fmt;
     tex_res.bo                  = accel_state->src_obj[unit].bo;
     tex_res.mip_bo              = accel_state->src_obj[unit].bo;
+    tex_res.surface             = accel_state->src_obj[unit].surface;
     tex_res.request_size        = 1;
 
 #if X_BYTE_ORDER == X_BIG_ENDIAN
@@ -1294,6 +1312,16 @@ static Bool R600PrepareComposite(int op, PicturePtr pSrcPicture,
 	dst_obj.bo = radeon_get_pixmap_bo(pDst);
 	dst_obj.tiling_flags = radeon_get_pixmap_tiling(pDst);
 	src_obj.tiling_flags = radeon_get_pixmap_tiling(pSrc);
+	dst_obj.surface = radeon_get_pixmap_surface(pDst);
+	src_obj.surface = radeon_get_pixmap_surface(pSrc);
+	if (dst_obj.surface->npix_x != pDst->drawable.width) {
+		dst_obj.surface = NULL;
+		dst_obj.tiling_flags = 0;
+	}
+	if (src_obj.surface->npix_x != pSrc->drawable.width) {
+		src_obj.surface = NULL;
+		src_obj.tiling_flags = 0;
+	}
     } else
 #endif
     {
@@ -1321,6 +1349,10 @@ static Bool R600PrepareComposite(int op, PicturePtr pSrcPicture,
 	    mask_obj.offset = 0;
 	    mask_obj.bo = radeon_get_pixmap_bo(pMask);
 	    mask_obj.tiling_flags = radeon_get_pixmap_tiling(pMask);
+	    mask_obj.surface = radeon_get_pixmap_surface(pMask);
+	    if (mask_obj.surface->npix_x != pMask->drawable.width) {
+		mask_obj.surface = NULL;
+	    }
 	} else
 #endif
 	{
@@ -1432,6 +1464,7 @@ static Bool R600PrepareComposite(int op, PicturePtr pSrcPicture,
     cb_conf.base = accel_state->dst_obj.offset;
     cb_conf.format = dst_format;
     cb_conf.bo = accel_state->dst_obj.bo;
+    cb_conf.surface = accel_state->dst_obj.surface;
 
     switch (pDstPicture->format) {
     case PICT_a8r8g8b8:
@@ -1868,6 +1901,7 @@ R600UploadToScreenCS(PixmapPtr pDst, int x, int y, int w, int h,
     src_obj.domain = RADEON_GEM_DOMAIN_GTT;
     src_obj.bo = scratch;
     src_obj.tiling_flags = 0;
+    src_obj.surface = NULL;
 
     dst_obj.pitch = dst_pitch_hw;
     dst_obj.width = pDst->drawable.width;
@@ -1877,6 +1911,11 @@ R600UploadToScreenCS(PixmapPtr pDst, int x, int y, int w, int h,
     dst_obj.domain = RADEON_GEM_DOMAIN_VRAM;
     dst_obj.bo = radeon_get_pixmap_bo(pDst);
     dst_obj.tiling_flags = radeon_get_pixmap_tiling(pDst);
+    dst_obj.surface = radeon_get_pixmap_surface(pDst);
+    if (dst_obj.surface->npix_x != pDst->drawable.width) {
+	dst_obj.surface = NULL;
+	dst_obj.tiling_flags = 0;
+    }
 
     if (!R600SetAccelState(pScrn,
 			   &src_obj,
@@ -2003,6 +2042,10 @@ R600DownloadFromScreenCS(PixmapPtr pSrc, int x, int y, int w,
     src_obj.domain = RADEON_GEM_DOMAIN_VRAM | RADEON_GEM_DOMAIN_GTT;
     src_obj.bo = radeon_get_pixmap_bo(pSrc);
     src_obj.tiling_flags = radeon_get_pixmap_tiling(pSrc);
+    src_obj.surface = radeon_get_pixmap_surface(pSrc);
+    if (src_obj.surface->npix_x != pSrc->drawable.width) {
+	src_obj.surface = NULL;
+    }
 
     dst_obj.pitch = scratch_pitch;
     dst_obj.width = w;
@@ -2012,6 +2055,7 @@ R600DownloadFromScreenCS(PixmapPtr pSrc, int x, int y, int w,
     dst_obj.bpp = bpp;
     dst_obj.domain = RADEON_GEM_DOMAIN_GTT;
     dst_obj.tiling_flags = 0;
+    dst_obj.surface = NULL;
 
     if (!R600SetAccelState(pScrn,
 			   &src_obj,
diff --git a/src/r600_state.h b/src/r600_state.h
index d5785cd..f6d5a88 100644
--- a/src/r600_state.h
+++ b/src/r600_state.h
@@ -56,6 +56,9 @@ typedef struct {
     int blend_enable;
     uint32_t blendcntl;
     struct radeon_bo *bo;
+#ifdef XF86DRM_MODE
+    struct radeon_surface *surface;
+#endif
 } cb_config_t;
 
 /* Depth buffer */
@@ -142,6 +145,9 @@ typedef struct {
     int interlaced;
     struct radeon_bo *bo;
     struct radeon_bo *mip_bo;
+#ifdef XF86DRM_MODE
+    struct radeon_surface *surface;
+#endif
 } tex_resource_t;
 
 /* Texture sampler */
diff --git a/src/r600_textured_videofuncs.c b/src/r600_textured_videofuncs.c
index aab43f3..fbaa9b1 100644
--- a/src/r600_textured_videofuncs.c
+++ b/src/r600_textured_videofuncs.c
@@ -170,6 +170,10 @@ R600DisplayTexturedVideo(ScrnInfoPtr pScrn, RADEONPortPrivPtr pPriv)
 	src_obj.offset = 0;
 	dst_obj.bo = radeon_get_pixmap_bo(pPixmap);
 	dst_obj.tiling_flags = radeon_get_pixmap_tiling(pPixmap);
+	dst_obj.surface = radeon_get_pixmap_surface(pPixmap);
+	if (dst_obj.surface->npix_x != pPixmap->drawable.width) {
+		dst_obj.surface = NULL;
+	}
     } else
 #endif
     {
@@ -186,6 +190,7 @@ R600DisplayTexturedVideo(ScrnInfoPtr pScrn, RADEONPortPrivPtr pPriv)
     src_obj.domain = RADEON_GEM_DOMAIN_VRAM | RADEON_GEM_DOMAIN_GTT;
     src_obj.bo = pPriv->src_bo[pPriv->currentBuffer];
     src_obj.tiling_flags = 0;
+    src_obj.surface = NULL;
 
     dst_obj.width = pPixmap->drawable.width;
     dst_obj.height = pPixmap->drawable.height;
@@ -270,6 +275,7 @@ R600DisplayTexturedVideo(ScrnInfoPtr pScrn, RADEONPortPrivPtr pPriv)
 	tex_res.size                = accel_state->src_size[0];
 	tex_res.bo                  = accel_state->src_obj[0].bo;
 	tex_res.mip_bo              = accel_state->src_obj[0].bo;
+	tex_res.surface             = NULL;
 
 	tex_res.format              = FMT_8;
 	tex_res.dst_sel_x           = SQ_SEL_X; /* Y */
@@ -431,6 +437,7 @@ R600DisplayTexturedVideo(ScrnInfoPtr pScrn, RADEONPortPrivPtr pPriv)
     cb_conf.h = accel_state->dst_obj.height;
     cb_conf.base = accel_state->dst_obj.offset;
     cb_conf.bo = accel_state->dst_obj.bo;
+    cb_conf.surface = accel_state->dst_obj.surface;
 
     switch (accel_state->dst_obj.bpp) {
     case 16:
diff --git a/src/r6xx_accel.c b/src/r6xx_accel.c
index d1a5085..8e6bffa 100644
--- a/src/r6xx_accel.c
+++ b/src/r6xx_accel.c
@@ -223,12 +223,37 @@ void
 r600_set_render_target(ScrnInfoPtr pScrn, drmBufPtr ib, cb_config_t *cb_conf, uint32_t domain)
 {
     uint32_t cb_color_info, cb_color_control;
-    int pitch, slice, h;
+    unsigned pitch, slice, h, array_mode;
     RADEONInfoPtr info = RADEONPTR(pScrn);
 
+
+#if defined(XF86DRM_MODE)
+    if (cb_conf->surface) {
+	switch (cb_conf->surface->level[0].mode) {
+	case RADEON_SURF_MODE_1D:
+		array_mode = 2;
+		break;
+	case RADEON_SURF_MODE_2D:
+		array_mode = 4;
+		break;
+	default:
+		array_mode = 0;
+		break;
+	}
+	pitch = (cb_conf->surface->level[0].nblk_x >> 3) - 1;
+	slice = ((cb_conf->surface->level[0].nblk_x * cb_conf->surface->level[0].nblk_y) / 64) - 1;
+    } else
+#endif
+    {
+	array_mode = cb_conf->array_mode;
+	pitch = (cb_conf->w / 8) - 1;
+	h = RADEON_ALIGN(cb_conf->h, 8);
+	slice = ((cb_conf->w * h) / 64) - 1;
+    }
+
     cb_color_info = ((cb_conf->endian      << ENDIAN_shift)				|
 		     (cb_conf->format      << CB_COLOR0_INFO__FORMAT_shift)		|
-		     (cb_conf->array_mode  << CB_COLOR0_INFO__ARRAY_MODE_shift)		|
+		     (array_mode  << CB_COLOR0_INFO__ARRAY_MODE_shift)		|
 		     (cb_conf->number_type << NUMBER_TYPE_shift)			|
 		     (cb_conf->comp_swap   << COMP_SWAP_shift)				|
 		     (cb_conf->tile_mode   << CB_COLOR0_INFO__TILE_MODE_shift));
@@ -251,10 +276,6 @@ r600_set_render_target(ScrnInfoPtr pScrn, drmBufPtr ib, cb_config_t *cb_conf, ui
     if (cb_conf->source_format)
 	cb_color_info |= SOURCE_FORMAT_bit;
 
-    pitch = (cb_conf->w / 8) - 1;
-    h = RADEON_ALIGN(cb_conf->h, 8);
-    slice = ((cb_conf->w * h) / 64) - 1;
-
     BEGIN_BATCH(3 + 2);
     EREG(ib, (CB_COLOR0_BASE + (4 * cb_conf->id)), (cb_conf->base >> 8));
     RELOC_BATCH(cb_conf->bo, 0, domain);
@@ -602,12 +623,34 @@ r600_set_tex_resource(ScrnInfoPtr pScrn, drmBufPtr ib, tex_resource_t *tex_res,
     RADEONInfoPtr info = RADEONPTR(pScrn);
     uint32_t sq_tex_resource_word0, sq_tex_resource_word1, sq_tex_resource_word4;
     uint32_t sq_tex_resource_word5, sq_tex_resource_word6;
+    uint32_t array_mode, pitch;
+
+#if defined(XF86DRM_MODE)
+    if (tex_res->surface) {
+	switch (tex_res->surface->level[0].mode) {
+	case RADEON_SURF_MODE_1D:
+		array_mode = 2;
+		break;
+	case RADEON_SURF_MODE_2D:
+		array_mode = 4;
+		break;
+	default:
+		array_mode = 0;
+		break;
+	}
+	pitch = tex_res->surface->level[0].nblk_x >> 3;
+    } else
+#endif
+    {
+	array_mode = tex_res->tile_mode;
+	pitch = (tex_res->pitch + 7) >> 3;
+    }
 
     sq_tex_resource_word0 = ((tex_res->dim << DIM_shift) |
-			     (tex_res->tile_mode << SQ_TEX_RESOURCE_WORD0_0__TILE_MODE_shift));
+		     (array_mode << SQ_TEX_RESOURCE_WORD0_0__TILE_MODE_shift));
 
     if (tex_res->w)
-	sq_tex_resource_word0 |= (((((tex_res->pitch + 7) >> 3) - 1) << PITCH_shift) |
+	sq_tex_resource_word0 |= (((pitch - 1) << PITCH_shift) |
 				  ((tex_res->w - 1) << TEX_WIDTH_shift));
 
     if (tex_res->tile_type)
diff --git a/src/radeon.h b/src/radeon.h
index d99fe3a..ce9508c 100644
--- a/src/radeon.h
+++ b/src/radeon.h
@@ -91,6 +91,7 @@
 #include "radeon_cs.h"
 #include "radeon_dri2.h"
 #include "drmmode_display.h"
+#include "radeon_surface.h"
 #else
 #include "radeon_dummy_bufmgr.h"
 #endif
@@ -183,6 +184,7 @@ typedef enum {
     OPTION_PANEL_SIZE,
     OPTION_MIN_DOTCLOCK,
     OPTION_COLOR_TILING,
+    OPTION_COLOR_TILING_2D,
 #ifdef XvExtension
     OPTION_VIDEO_KEY,
     OPTION_RAGE_THEATRE_CRYSTAL,
@@ -442,6 +444,9 @@ typedef struct _atomBiosHandle *atomBiosHandlePtr;
 struct radeon_exa_pixmap_priv {
     struct radeon_bo *bo;
     uint32_t tiling_flags;
+#ifdef XF86DRM_MODE
+    struct radeon_surface surface;
+#endif
     Bool bo_mapped;
 };
 
@@ -621,6 +626,9 @@ struct r600_accel_object {
     uint32_t domain;
     struct radeon_bo *bo;
     uint32_t tiling_flags;
+#if defined(XF86DRM_MODE)
+    struct radeon_surface *surface;
+#endif
 };
 
 struct radeon_vbo_object {
@@ -889,6 +897,7 @@ typedef struct {
     /* accel */
     Bool              RenderAccel; /* Render */
     Bool              allowColorTiling;
+    Bool              allowColorTiling2D;
     Bool              tilingEnabled; /* mirror of sarea->tiling_enabled */
     struct radeon_accel_state *accel_state;
     Bool              accelOn;
@@ -1014,6 +1023,8 @@ typedef struct {
     int num_channels;
     int num_banks;
     int r7xx_bank_op;
+    struct radeon_surface_manager *surf_man;
+    struct radeon_surface front_surface;
 #else
     /* fake bool */
     Bool cs;
@@ -1231,6 +1242,7 @@ extern void RADEONPMFini(ScrnInfoPtr pScrn);
 
 #ifdef USE_EXA
 /* radeon_exa.c */
+extern unsigned eg_tile_split(unsigned tile_split);
 extern Bool RADEONSetupMemEXA(ScreenPtr pScreen);
 extern Bool radeon_transform_is_affine_or_scaled(PictTransformPtr t);
 
@@ -1322,6 +1334,7 @@ extern void radeon_ddx_cs_start(ScrnInfoPtr pScrn,
 				int num, const char *file,
 				const char *func, int line);
 void radeon_kms_update_vram_limit(ScrnInfoPtr pScrn, int new_fb_size);
+struct radeon_surface *radeon_get_pixmap_surface(PixmapPtr pPix);
 #endif
 struct radeon_bo *radeon_get_pixmap_bo(PixmapPtr pPix);
 void radeon_set_pixmap_bo(PixmapPtr pPix, struct radeon_bo *bo);
@@ -1670,6 +1683,7 @@ enum {
     RADEON_CREATE_PIXMAP_TILING_MACRO = 0x10000000,
     RADEON_CREATE_PIXMAP_TILING_MICRO = 0x20000000,
     RADEON_CREATE_PIXMAP_DEPTH = 0x40000000, /* for r200 */
+    RADEON_CREATE_PIXMAP_SZBUFFER = 0x80000000, /* for eg */
 };
 
 #endif /* _RADEON_H_ */
diff --git a/src/radeon_dri2.c b/src/radeon_dri2.c
index 5a7ebd4..835575f 100644
--- a/src/radeon_dri2.c
+++ b/src/radeon_dri2.c
@@ -244,10 +244,10 @@ radeon_dri2_create_buffer(DrawablePtr drawable,
     struct dri2_buffer_priv *privates;
     PixmapPtr pixmap, depth_pixmap;
     struct radeon_exa_pixmap_priv *driver_priv;
-    int need_enlarge = 0;
     int flags;
     unsigned front_width;
     uint32_t tiling = 0;
+    unsigned aligned_width = drawable->width;
 
     pixmap = pScreen->GetScreenPixmap(pScreen);
     front_width = pixmap->drawable.width;
@@ -271,9 +271,15 @@ radeon_dri2_create_buffer(DrawablePtr drawable,
 	    /* macro is the preferred setting, but the 2D detiling for software
 	     * fallbacks in mesa still has issues on some configurations
 	     */
-	    if (info->ChipFamily >= CHIP_FAMILY_R600)
-		flags = RADEON_CREATE_PIXMAP_TILING_MICRO;
-	    else
+	    if (info->ChipFamily >= CHIP_FAMILY_R600) {
+		if (info->allowColorTiling2D) {
+			flags = RADEON_CREATE_PIXMAP_TILING_MACRO;
+		} else {
+			flags = RADEON_CREATE_PIXMAP_TILING_MICRO;
+		}
+		if (info->ChipFamily >= CHIP_FAMILY_CEDAR)
+		    flags |= RADEON_CREATE_PIXMAP_SZBUFFER;
+	    } else
 		flags = RADEON_CREATE_PIXMAP_TILING_MACRO | RADEON_CREATE_PIXMAP_TILING_MICRO;
 	    if (IS_R200_3D || info->ChipFamily == CHIP_FAMILY_RV200 || info->ChipFamily == CHIP_FAMILY_RADEON)
 		flags |= RADEON_CREATE_PIXMAP_DEPTH;
@@ -283,24 +289,30 @@ radeon_dri2_create_buffer(DrawablePtr drawable,
 	     * fallbacks in mesa still has issues on some configurations
 	     */
 	    if (info->ChipFamily >= CHIP_FAMILY_R600) {
-		flags = RADEON_CREATE_PIXMAP_TILING_MICRO;
+		if (info->allowColorTiling2D) {
+			flags = RADEON_CREATE_PIXMAP_TILING_MACRO;
+		} else {
+			flags = RADEON_CREATE_PIXMAP_TILING_MICRO;
+		}
 		if (info->ChipFamily >= CHIP_FAMILY_CEDAR)
-		    need_enlarge = 1;
+		    flags |= RADEON_CREATE_PIXMAP_SZBUFFER;
 	    } else
 		flags = RADEON_CREATE_PIXMAP_TILING_MACRO | RADEON_CREATE_PIXMAP_TILING_MICRO;
 	    if (IS_R200_3D || info->ChipFamily == CHIP_FAMILY_RV200 || info->ChipFamily == CHIP_FAMILY_RADEON)
 		flags |= RADEON_CREATE_PIXMAP_DEPTH;
+		
 	    break;
 	case DRI2BufferBackLeft:
 	case DRI2BufferBackRight:
 	case DRI2BufferFakeFrontLeft:
 	case DRI2BufferFakeFrontRight:
-	    if (info->ChipFamily >= CHIP_FAMILY_R600)
-		/* macro is the preferred setting, but the 2D detiling for software
-		 * fallbacks in mesa still has issues on some configurations
-		 */
-		flags = RADEON_CREATE_PIXMAP_TILING_MICRO;
-	    else
+	    if (info->ChipFamily >= CHIP_FAMILY_R600) {
+		if (info->allowColorTiling2D) {
+			flags = RADEON_CREATE_PIXMAP_TILING_MACRO;
+		} else {
+			flags = RADEON_CREATE_PIXMAP_TILING_MICRO;
+		}
+	    } else
 		flags = RADEON_CREATE_PIXMAP_TILING_MACRO;
 	    break;
 	default:
@@ -312,39 +324,6 @@ radeon_dri2_create_buffer(DrawablePtr drawable,
 	if (flags & RADEON_CREATE_PIXMAP_TILING_MACRO)
 	    tiling |= RADEON_TILING_MACRO;
 
-	if (need_enlarge) {
-	    /* evergreen uses separate allocations for depth and stencil
-	     * so we make an extra large depth buffer to cover stencil
-	     * as well.
-	     */
-	    int depth = (format != 0) ? format : drawable->depth;
-	    unsigned aligned_width = drawable->width;
-	    unsigned width_align = drmmode_get_pitch_align(pScrn, drawable->depth / 8, tiling);
-	    unsigned aligned_height;
-	    unsigned height_align = drmmode_get_height_align(pScrn, tiling);
-	    unsigned base_align = drmmode_get_base_align(pScrn, drawable->depth / 8, tiling);
-	    unsigned pitch_bytes;
-	    unsigned size;
-
-	    if (aligned_width == front_width)
-		aligned_width = pScrn->virtualX;
-	    aligned_width = RADEON_ALIGN(aligned_width, width_align);
-	    pitch_bytes = aligned_width * (depth / 8);
-	    aligned_height = RADEON_ALIGN(drawable->height, height_align);
-	    size = pitch_bytes * aligned_height;
-	    size = RADEON_ALIGN(size, base_align);
-	    /* add additional size for stencil */
-	    size += aligned_width * aligned_height;
-	    aligned_height = RADEON_ALIGN(size / pitch_bytes, height_align);
-
-	    pixmap = (*pScreen->CreatePixmap)(pScreen,
-					      aligned_width,
-					      aligned_height,
-					      (format != 0)?format:drawable->depth,
-					      flags);
-
-	} else {
-	    unsigned aligned_width = drawable->width;
 
 	    if (aligned_width == front_width)
 		aligned_width = pScrn->virtualX;
@@ -354,7 +333,6 @@ radeon_dri2_create_buffer(DrawablePtr drawable,
 					      drawable->height,
 					      (format != 0)?format:drawable->depth,
 					      flags);
-	}
     }
 
     if (!pixmap)
diff --git a/src/radeon_drm.h b/src/radeon_drm.h
index 49a5f81..042e822 100644
--- a/src/radeon_drm.h
+++ b/src/radeon_drm.h
@@ -800,12 +800,23 @@ struct drm_radeon_gem_create {
 	uint32_t	flags;
 };
 
-#define RADEON_TILING_MACRO 0x1
-#define RADEON_TILING_MICRO 0x2
-#define RADEON_TILING_SWAP_16BIT  0x4
-#define RADEON_TILING_SWAP_32BIT  0x8
-#define RADEON_TILING_SURFACE     0x10 /* this object requires a surface
-					* when mapped - i.e. front buffer */
+#define RADEON_TILING_MACRO				0x1
+#define RADEON_TILING_MICRO				0x2
+#define RADEON_TILING_SWAP_16BIT			0x4
+#define RADEON_TILING_SWAP_32BIT			0x8
+/* this object requires a surface when mapped - i.e. front buffer */
+#define RADEON_TILING_SURFACE				0x10
+#define RADEON_TILING_MICRO_SQUARE			0x20
+#define RADEON_TILING_EG_BANKW_SHIFT			8
+#define RADEON_TILING_EG_BANKW_MASK			0xf
+#define RADEON_TILING_EG_BANKH_SHIFT			12
+#define RADEON_TILING_EG_BANKH_MASK			0xf
+#define RADEON_TILING_EG_MACRO_TILE_ASPECT_SHIFT	16
+#define RADEON_TILING_EG_MACRO_TILE_ASPECT_MASK		0xf
+#define RADEON_TILING_EG_TILE_SPLIT_SHIFT		24
+#define RADEON_TILING_EG_TILE_SPLIT_MASK		0xf
+#define RADEON_TILING_EG_STENCIL_TILE_SPLIT_SHIFT	28
+#define RADEON_TILING_EG_STENCIL_TILE_SPLIT_MASK	0xf
 
 struct drm_radeon_gem_set_tiling {
 	uint32_t	handle;
diff --git a/src/radeon_exa.c b/src/radeon_exa.c
index 554af36..99a5806 100644
--- a/src/radeon_exa.c
+++ b/src/radeon_exa.c
@@ -454,9 +454,12 @@ void *RADEONEXACreatePixmap2(ScreenPtr pScreen, int width, int height,
     RADEONInfoPtr info = RADEONPTR(pScrn);
     struct radeon_exa_pixmap_priv *new_priv;
     int pitch, base_align;
-    uint32_t size;
+    uint32_t size, heighta;
     uint32_t tiling = 0;
     int cpp = bitsPerPixel / 8;
+#ifdef XF86DRM_MODE
+    struct radeon_surface surface;
+#endif
 
 #ifdef EXA_MIXED_PIXMAPS
     if (info->accel_state->exa->flags & EXA_MIXED_PIXMAPS) {
@@ -488,17 +491,78 @@ void *RADEONEXACreatePixmap2(ScreenPtr pScreen, int width, int height,
         tiling &= ~RADEON_TILING_MACRO;
     }
 
-    height = RADEON_ALIGN(height, drmmode_get_height_align(pScrn, tiling));
+    heighta = RADEON_ALIGN(height, drmmode_get_height_align(pScrn, tiling));
     pitch = RADEON_ALIGN(width, drmmode_get_pitch_align(pScrn, cpp, tiling)) * cpp;
     base_align = drmmode_get_base_align(pScrn, cpp, tiling);
-    size = RADEON_ALIGN(height * pitch, RADEON_GPU_PAGE_SIZE);
+    size = RADEON_ALIGN(heighta * pitch, RADEON_GPU_PAGE_SIZE);
+    memset(&surface, 0, sizeof(struct radeon_surface));
+
+#ifdef XF86DRM_MODE
+    if (info->ChipFamily >= CHIP_FAMILY_R600 && info->surf_man) {
+		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;
+			surface.flags = RADEON_SURF_SCANOUT;
+			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;
+				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;
+			}
+		}
+	}
+#endif
 
     new_priv = calloc(1, sizeof(struct radeon_exa_pixmap_priv));
-    if (!new_priv)
+    if (!new_priv) {
 	return NULL;
+    }
 
-    if (size == 0)
+    if (size == 0) {
 	return new_priv;
+    }
 
     *new_pitch = pitch;
 
@@ -513,6 +577,7 @@ void *RADEONEXACreatePixmap2(ScreenPtr pScreen, int width, int height,
     if (tiling && !radeon_bo_set_tiling(new_priv->bo, tiling, *new_pitch))
 	new_priv->tiling_flags = tiling;
 
+    new_priv->surface = surface;
     return new_priv;
 }
 
@@ -535,6 +600,15 @@ struct radeon_bo *radeon_get_pixmap_bo(PixmapPtr pPix)
     return driver_priv->bo;
 }
 
+#if defined(XF86DRM_MODE)
+struct radeon_surface *radeon_get_pixmap_surface(PixmapPtr pPix)
+{
+    struct radeon_exa_pixmap_priv *driver_priv;
+    driver_priv = exaGetPixmapDriverPrivate(pPix);
+    return &driver_priv->surface;
+}
+#endif
+
 uint32_t radeon_get_pixmap_tiling(PixmapPtr pPix)
 {
     struct radeon_exa_pixmap_priv *driver_priv;
diff --git a/src/radeon_kms.c b/src/radeon_kms.c
index 1604f25..7ac4f05 100644
--- a/src/radeon_kms.c
+++ b/src/radeon_kms.c
@@ -62,6 +62,7 @@ const OptionInfoRec RADEONOptions_KMS[] = {
     { OPTION_ACCEL_DFS,      "AccelDFS",         OPTV_BOOLEAN, {0}, FALSE },
     { OPTION_IGNORE_EDID,    "IgnoreEDID",       OPTV_BOOLEAN, {0}, FALSE },
     { OPTION_COLOR_TILING,   "ColorTiling",      OPTV_BOOLEAN, {0}, FALSE },
+    { OPTION_COLOR_TILING_2D,"ColorTiling2D",    OPTV_BOOLEAN, {0}, FALSE },
     { OPTION_RENDER_ACCEL,   "RenderAccel",      OPTV_BOOLEAN, {0}, FALSE },
     { OPTION_SUBPIXEL_ORDER, "SubPixelOrder",    OPTV_ANYSTR,  {0}, FALSE },
     { OPTION_ACCELMETHOD,    "AccelMethod",      OPTV_STRING,  {0}, FALSE },
@@ -158,6 +159,7 @@ static Bool RADEONCreateScreenResources_KMS(ScreenPtr pScreen)
     ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
     RADEONInfoPtr  info   = RADEONPTR(pScrn);
     PixmapPtr pixmap;
+    struct radeon_surface *surface;
 
     pScreen->CreateScreenResources = info->CreateScreenResources;
     if (!(*pScreen->CreateScreenResources)(pScreen))
@@ -181,6 +183,10 @@ static Bool RADEONCreateScreenResources_KMS(ScreenPtr pScreen)
 	if (info->front_bo) {
 	    PixmapPtr pPix = pScreen->GetScreenPixmap(pScreen);
 	    radeon_set_pixmap_bo(pPix, info->front_bo);
+	    surface = radeon_get_pixmap_surface(pPix);
+	    if (surface) {
+		*surface = info->front_surface;
+	    }
 	}
     }
     return TRUE;
@@ -674,6 +680,8 @@ Bool RADEONPreInit_KMS(ScrnInfoPtr pScrn, int flags)
 
     if (!RADEONPreInitAccel_KMS(pScrn))              goto fail;
 
+    info->allowColorTiling2D = FALSE;
+
 #ifdef EXA_MIXED_PIXMAPS
     /* don't enable tiling if accel is not enabled */
     if (!info->r600_shadow_fb) {
@@ -682,6 +690,11 @@ Bool RADEONPreInit_KMS(ScrnInfoPtr pScrn, int flags)
 	    info->ChipFamily >= CHIP_FAMILY_R300 &&
 	    info->ChipFamily <= CHIP_FAMILY_CAYMAN;
 
+	/* 2D color tiling */
+	if (info->ChipFamily >= CHIP_FAMILY_R600) {
+		info->allowColorTiling2D = xf86ReturnOptValBool(info->Options, OPTION_COLOR_TILING_2D, FALSE);
+	}
+
 	if (info->ChipFamily >= CHIP_FAMILY_R600) {
 	    /* set default group bytes, overridden by kernel info below */
 	    info->group_bytes = 256;
@@ -933,6 +946,7 @@ Bool RADEONScreenInit_KMS(int scrnIndex, ScreenPtr pScreen,
 
     front_ptr = info->FB;
 
+    info->surf_man = radeon_surface_manager_new(info->dri->drmFD);
     if (!info->bufmgr)
         info->bufmgr = radeon_bo_manager_gem_ctor(info->dri->drmFD);
     if (!info->bufmgr) {
@@ -1209,6 +1223,7 @@ static Bool radeon_setup_kernel_mem(ScreenPtr pScreen)
     int pitch, base_align;
     int total_size_bytes = 0;
     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");
@@ -1221,14 +1236,67 @@ static Bool radeon_setup_kernel_mem(ScreenPtr pScreen)
     }
 
     if (info->allowColorTiling) {
-	if (info->ChipFamily >= CHIP_FAMILY_R600)
-	    tiling_flags |= RADEON_TILING_MICRO;
-	else
+	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->displayWidth, 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) {
+		memset(&surface, 0, sizeof(struct radeon_surface));
+		surface.npix_x = pScrn->displayWidth;
+		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;
+		surface.flags |= RADEON_SURF_SET(RADEON_SURF_TYPE_2D, TYPE);
+		surface.flags |= RADEON_SURF_SET(RADEON_SURF_MODE_LINEAR, MODE);
+		if (tiling_flags & RADEON_TILING_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)) {
+			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;
+			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;
+		}
+		info->front_surface = surface;
+	}
     {
 	int cursor_size = 64 * 4 * 64;
 	int c;


More information about the xorg-commit mailing list