[PATCH] r600-evergreen: use common surface allocator for tiling v2

Jerome Glisse jglisse at redhat.com
Tue Dec 13 08:08:19 PST 2011


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
2D tiling on GPU >= R600, set it to false as default

Signed-off-by: Jerome Glisse <jglisse at redhat.com>
---
 src/drmmode_display.c |   79 ++++++++++++++++++++++--
 src/evergreen_accel.c |  158 +++++++++++++++++++++++++++++++++++++++++++++----
 src/evergreen_exa.c   |   24 ++++++++
 src/evergreen_state.h |    6 ++
 src/r600_exa.c        |   62 ++++++++++++--------
 src/r600_state.h      |    6 ++
 src/r6xx_accel.c      |   59 ++++++++++++++++---
 src/radeon.h          |   12 ++++
 src/radeon_dri2.c     |   29 ++++++---
 src/radeon_drm.h      |   19 ++++--
 src/radeon_exa.c      |   73 +++++++++++++++++++++--
 src/radeon_kms.c      |   51 ++++++++++++++++
 12 files changed, 506 insertions(+), 72 deletions(-)

diff --git a/src/drmmode_display.c b/src/drmmode_display.c
index 02968d5..835619e 100644
--- a/src/drmmode_display.c
+++ b/src/drmmode_display.c
@@ -52,9 +52,11 @@
 static PixmapPtr drmmode_create_bo_pixmap(ScreenPtr pScreen,
 					  int width, int height,
 					  int depth, int bpp,
-					  int pitch, struct radeon_bo *bo)
+					  int pitch, int tiling,
+					  struct radeon_bo *bo)
 {
 	PixmapPtr pixmap;
+	struct radeon_surface *surface;
 
 	pixmap = (*pScreen->CreatePixmap)(pScreen, 0, 0, depth, 0);
 	if (!pixmap)
@@ -67,6 +69,21 @@ static PixmapPtr drmmode_create_bo_pixmap(ScreenPtr pScreen,
 
 	exaMoveInPixmap(pixmap);
 	radeon_set_pixmap_bo(pixmap, bo);
+	surface = radeon_get_pixmap_surface(pixmap);
+	if (surface) {
+		surface->level[0].width = width;
+		surface->level[0].height = height;
+		surface->level[0].height_aligned = RADEON_ALIGN(height, 8);
+		surface->level[0].pitch = pitch / (bpp / 8);
+		surface->level[0].pitch_bytes = pitch;
+		surface->level[0].mode = RADEON_SURF_MODE_LINEAR;
+		if (tiling & RADEON_TILING_MACRO) {
+			surface->level[0].mode = RADEON_SURF_MODE_2D;
+		}
+		if (tiling & RADEON_TILING_MICRO) {
+			surface->level[0].mode = RADEON_SURF_MODE_1D;
+		}
+	}
 
 	return pixmap;
 }
@@ -187,7 +204,7 @@ create_pixmap_for_fbcon(drmmode_ptr drmmode,
 
 	pixmap = drmmode_create_bo_pixmap(pScreen, fbcon->width, fbcon->height,
 					  fbcon->depth, fbcon->bpp,
-					  fbcon->pitch, bo);
+					  fbcon->pitch, 0, bo);
 	if (!pixmap) 
 		return NULL;
 
@@ -226,7 +243,7 @@ void drmmode_copy_fb(ScrnInfoPtr pScrn, drmmode_ptr drmmode)
 
 	if (info->allowColorTiling) {
 		if (info->ChipFamily >= CHIP_FAMILY_R600)
-			tiling_flags |= RADEON_TILING_MICRO;
+			tiling_flags |= RADEON_TILING_MACRO;
 		else
 			tiling_flags |= RADEON_TILING_MACRO;
 	}
@@ -238,7 +255,7 @@ void drmmode_copy_fb(ScrnInfoPtr pScrn, drmmode_ptr drmmode)
 	dst = drmmode_create_bo_pixmap(pScreen, 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 +309,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,
@@ -508,7 +528,7 @@ drmmode_crtc_shadow_create(xf86CrtcPtr crtc, void *data, int width, int 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 +1226,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;
 
@@ -1229,6 +1251,44 @@ drmmode_xf86crtc_resize (ScrnInfoPtr scrn, int width, int height)
 	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.width = width;
+		surface.height = height;
+		surface.depth = 1;
+		surface.last_level = 0;
+		surface.element_bytes = 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_1D, MODE);
+		surface.flags |= RADEON_SURF_SET(RADEON_SURF_MODE_LINEAR_ALIGNED, MODE);
+		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;
+		switch (surface.level[0].mode) {
+		case RADEON_SURF_MODE_2D:
+			tiling_flags |= RADEON_TILING_MACRO;
+			tiling_flags &= ~RADEON_TILING_MICRO;
+			tiling_flags |= surface.bank_width << RADEON_TILING_EG_BANKW_SHIFT;
+			tiling_flags |= surface.bank_height << RADEON_TILING_EG_BANKH_SHIFT;
+			tiling_flags |= surface.macro_tile_aspect << RADEON_TILING_EG_MACRO_TILE_ASPECT_SHIFT;
+			break;
+		case RADEON_SURF_MODE_1D:
+			tiling_flags |= RADEON_TILING_MICRO;
+			tiling_flags &= ~RADEON_TILING_MACRO;
+			break;
+		default:
+			tiling_flags &= ~RADEON_TILING_MACRO;
+			tiling_flags &= ~RADEON_TILING_MICRO;
+			break;
+		}
+		info->front_surface = surface;
+	}
 
 	xf86DrvMsg(scrn->scrnIndex, X_INFO,
 		   "Allocate new frame buffer %dx%d stride %d\n",
@@ -1244,7 +1304,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 +1330,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 +1733,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 83320c8..b1f1df5 100644
--- a/src/evergreen_accel.c
+++ b/src/evergreen_accel.c
@@ -75,6 +75,57 @@ evergreen_start_3d(ScrnInfoPtr pScrn)
 
 }
 
+static 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;
+	default:
+	case 1024:	tile_split = 4;	break;
+	case 2048:	tile_split = 5;	break;
+	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 = 1;
+		break;
+	}
+	w = cb_conf->surface->level[0].pitch;
+	h = cb_conf->surface->level[0].height_aligned;
+	pitch = (cb_conf->surface->level[0].pitch >> 3) - 1;
+	slice = ((cb_conf->surface->level[0].pitch * cb_conf->surface->level[0].height_aligned) / 64) - 1;
+	tile_split = cb_conf->surface->tile_split;
+	macro_aspect = cb_conf->surface->macro_tile_aspect;
+	bankw = cb_conf->surface->bank_width;
+	bankh = cb_conf->surface->bank_height;
+	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;
     }
@@ -608,17 +702,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].pitch >> 3;
+	tile_split = tex_res->surface->tile_split;
+	macro_aspect = tex_res->surface->macro_tile_aspect;
+	bankw = tex_res->surface->bank_width;
+	bankh = tex_res->surface->bank_height;
+	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);
@@ -647,12 +777,18 @@ 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) |
+			     (3 << SQ_TEX_RESOURCE_WORD7_0__NUM_BANKS_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 603d854..cb42032 100644
--- a/src/evergreen_exa.c
+++ b/src/evergreen_exa.c
@@ -77,6 +77,7 @@ 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);
 
     dst.pitch = exaGetPixmapPitch(pPix) / (pPix->drawable.bitsPerPixel / 8);
     dst.width = pPix->drawable.width;
@@ -129,6 +130,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 +315,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 +359,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,6 +471,8 @@ 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 (radeon_get_pixmap_bo(pSrc) == radeon_get_pixmap_bo(pDst))
@@ -495,6 +501,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;
@@ -575,12 +584,15 @@ EVERGREENCopy(PixmapPtr pDst,
 	uint32_t orig_src_tiling_flags = accel_state->src_obj[0].tiling_flags;
 	uint32_t orig_dst_tiling_flags = accel_state->dst_obj.tiling_flags;
 	struct radeon_bo *orig_bo = accel_state->dst_obj.bo;
+	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;
 	accel_state->dst_obj.bo = accel_state->copy_area_bo;
 	accel_state->dst_obj.offset = 0;
 	accel_state->dst_obj.tiling_flags = 0;
+	accel_state->dst_obj.surface = NULL;
 	EVERGREENDoPrepareCopy(pScrn);
 	EVERGREENAppendCopyVertex(pScrn, srcX, srcY, dstX, dstY, w, h);
 	EVERGREENDoCopy(pScrn);
@@ -590,10 +602,12 @@ 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->dst_obj.surface = orig_dst_surface;
 	EVERGREENDoPrepareCopy(pScrn);
 	EVERGREENAppendCopyVertex(pScrn, dstX, dstY, dstX, dstY, w, h);
 	EVERGREENDoCopyVline(pDst);
@@ -603,6 +617,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);
 
@@ -848,6 +863,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) {
@@ -1130,6 +1146,8 @@ 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);
 
@@ -1151,6 +1169,7 @@ 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);
 
 	mask_obj.width = pMask->drawable.width;
 	mask_obj.height = pMask->drawable.height;
@@ -1259,6 +1278,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:
@@ -1497,6 +1517,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;
@@ -1506,6 +1527,7 @@ 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 (!R600SetAccelState(pScrn,
 			   &src_obj,
@@ -1636,6 +1658,7 @@ 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);
 
     dst_obj.pitch = scratch_pitch;
     dst_obj.width = w;
@@ -1645,6 +1668,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/r600_exa.c b/src/r600_exa.c
index 71e1393..3b77923 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,13 @@ 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;
+	}
 	if (accel_state->dst_obj.pitch & pitch_align)
 	    RADEON_FALLBACK(("Bad dst pitch 0x%08x\n", accel_state->dst_obj.pitch));
 
@@ -197,6 +193,7 @@ 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);
     } else
 #endif
     {
@@ -254,6 +251,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 +431,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 +476,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 +591,8 @@ 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 (radeon_get_pixmap_bo(pSrc) == radeon_get_pixmap_bo(pDst))
 	    accel_state->same_surface = TRUE;
     } else
@@ -626,10 +628,11 @@ 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;
 #else
 	unsigned height = pDst->drawable.height;
-#endif
 	unsigned long size = height * accel_state->dst_obj.pitch * pDst->drawable.bitsPerPixel/8;
+#endif
 
 #if defined(XF86DRM_MODE)
 	if (info->cs) {
@@ -976,6 +979,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
@@ -1291,6 +1295,8 @@ 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);
     } else
 #endif
     {
@@ -1318,6 +1324,7 @@ 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);
 	} else
 #endif
 	{
@@ -1429,6 +1436,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:
@@ -1865,6 +1873,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;
@@ -1874,6 +1883,7 @@ 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 (!R600SetAccelState(pScrn,
 			   &src_obj,
@@ -2000,6 +2010,7 @@ 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);
 
     dst_obj.pitch = scratch_pitch;
     dst_obj.width = w;
@@ -2009,6 +2020,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/r6xx_accel.c b/src/r6xx_accel.c
index 752165b..ec4b575 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 = 1;
+		break;
+	}
+	pitch = (cb_conf->surface->level[0].pitch >> 3) - 1;
+	slice = ((cb_conf->surface->level[0].pitch * cb_conf->surface->level[0].height_aligned) / 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);
@@ -609,12 +630,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 = 1;
+		break;
+	}
+	pitch = tex_res->surface->level[0].pitch >> 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 91c7b62..4d47d12 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;
@@ -1320,6 +1331,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);
diff --git a/src/radeon_dri2.c b/src/radeon_dri2.c
index 52f2b82..f2defd5 100644
--- a/src/radeon_dri2.c
+++ b/src/radeon_dri2.c
@@ -271,9 +271,13 @@ 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;
+		}
+	    } 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,7 +287,11 @@ 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;
 	    } else
@@ -295,12 +303,13 @@ radeon_dri2_create_buffer(DrawablePtr drawable,
 	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:
diff --git a/src/radeon_drm.h b/src/radeon_drm.h
index 49a5f81..46e3fe5 100644
--- a/src/radeon_drm.h
+++ b/src/radeon_drm.h
@@ -800,12 +800,19 @@ 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
 
 struct drm_radeon_gem_set_tiling {
 	uint32_t	handle;
diff --git a/src/radeon_exa.c b/src/radeon_exa.c
index 554af36..ce5aeb4 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,67 @@ 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);
+
+#ifdef XF86DRM_MODE
+    if (info->ChipFamily >= CHIP_FAMILY_R600 && info->surf_man) {
+		memset(&surface, 0, sizeof(struct radeon_surface));
+		if (width) {
+			surface.width = width;
+			surface.height = height;
+			surface.depth = 1;
+			surface.last_level = 0;
+			surface.element_bytes = 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 (radeon_surface_init(info->surf_man, &surface)) {
+				return NULL;
+			}
+			size = surface.bo_size;
+			base_align = surface.bo_alignment;
+			pitch = surface.level[0].pitch_bytes;
+			switch (surface.level[0].mode) {
+			case RADEON_SURF_MODE_2D:
+				tiling |= RADEON_TILING_MACRO;
+				tiling &= ~RADEON_TILING_MICRO;
+				tiling |= surface.bank_width << RADEON_TILING_EG_BANKW_SHIFT;
+				tiling |= surface.bank_height << RADEON_TILING_EG_BANKH_SHIFT;
+				tiling |= surface.macro_tile_aspect << RADEON_TILING_EG_MACRO_TILE_ASPECT_SHIFT;
+				break;
+			case RADEON_SURF_MODE_1D:
+				tiling |= RADEON_TILING_MICRO;
+				tiling &= ~RADEON_TILING_MACRO;
+				break;
+			default:
+				tiling &= ~RADEON_TILING_MACRO;
+				tiling &= ~RADEON_TILING_MICRO;
+				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 +566,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 +589,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..6c0f06a 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");
@@ -1229,6 +1244,42 @@ static Bool radeon_setup_kernel_mem(ScreenPtr pScreen)
     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.width = pScrn->displayWidth;
+		surface.height = pScrn->virtualY;
+		surface.depth = 1;
+		surface.last_level = 0;
+		surface.element_bytes = 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_2D, MODE);
+		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;
+		switch (surface.level[0].mode) {
+		case RADEON_SURF_MODE_2D:
+			tiling_flags |= RADEON_TILING_MACRO;
+			tiling_flags &= ~RADEON_TILING_MICRO;
+			tiling_flags |= surface.bank_width << RADEON_TILING_EG_BANKW_SHIFT;
+			tiling_flags |= surface.bank_height << RADEON_TILING_EG_BANKH_SHIFT;
+			tiling_flags |= surface.macro_tile_aspect << RADEON_TILING_EG_MACRO_TILE_ASPECT_SHIFT;
+			break;
+		case RADEON_SURF_MODE_1D:
+			tiling_flags |= RADEON_TILING_MICRO;
+			tiling_flags &= ~RADEON_TILING_MACRO;
+			break;
+		default:
+			tiling_flags &= ~RADEON_TILING_MACRO;
+			tiling_flags &= ~RADEON_TILING_MICRO;
+			break;
+		}
+		info->front_surface = surface;
+	}
     {
 	int cursor_size = 64 * 4 * 64;
 	int c;
-- 
1.7.7.1


--IJpNTDwzlM2Ie8A6
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment; filename="0001-r600g-add-support-for-common-surface-allocator-for-t.patch"



More information about the mesa-dev mailing list