[PATCH 1/3] r600: add span support for 2D tiling

Alex Deucher alexdeucher at gmail.com
Tue May 25 16:12:52 PDT 2010


Requires tiling config ioctl support from the drm to use.
kms only.

Signed-off-by: Alex Deucher <alexdeucher at gmail.com>
---
 .../drivers/dri/radeon/radeon_common_context.c     |    9 +-
 .../drivers/dri/radeon/radeon_common_context.h     |    7 +
 src/mesa/drivers/dri/radeon/radeon_screen.h        |    7 +
 src/mesa/drivers/dri/radeon/radeon_span.c          |  192 +++++++++++++++++++-
 4 files changed, 210 insertions(+), 5 deletions(-)

diff --git a/src/mesa/drivers/dri/radeon/radeon_common_context.c b/src/mesa/drivers/dri/radeon/radeon_common_context.c
index 94f4766..1cce032 100644
--- a/src/mesa/drivers/dri/radeon/radeon_common_context.c
+++ b/src/mesa/drivers/dri/radeon/radeon_common_context.c
@@ -650,6 +650,13 @@ radeon_update_renderbuffers(__DRIcontext *context, __DRIdrawable *drawable,
 		rb->base.Height = drawable->h;
 		rb->has_surface = 0;
 
+		/* r6xx+ tiling */
+		rb->tile_config = radeon->radeonScreen->tile_config;
+		rb->group_bytes = radeon->radeonScreen->group_bytes;
+		rb->num_channels = radeon->radeonScreen->num_channels;
+		rb->num_banks = radeon->radeonScreen->num_banks;
+		rb->r7xx_bank_op = radeon->radeonScreen->r7xx_bank_op;
+
 		if (buffers[i].attachment == __DRI_BUFFER_STENCIL && depth_bo) {
 			if (RADEON_DEBUG & RADEON_DRI)
 				fprintf(stderr, "(reusing depth buffer as stencil)\n");
@@ -678,7 +685,7 @@ radeon_update_renderbuffers(__DRIcontext *context, __DRIdrawable *drawable,
 				bo->flags |= RADEON_BO_FLAGS_MACRO_TILE;
 			if (tiling_flags & RADEON_TILING_MICRO)
 				bo->flags |= RADEON_BO_FLAGS_MICRO_TILE;
-			
+
 		}
 
 		if (buffers[i].attachment == __DRI_BUFFER_DEPTH) {
diff --git a/src/mesa/drivers/dri/radeon/radeon_common_context.h b/src/mesa/drivers/dri/radeon/radeon_common_context.h
index 5156c5d..3fd00eb 100644
--- a/src/mesa/drivers/dri/radeon/radeon_common_context.h
+++ b/src/mesa/drivers/dri/radeon/radeon_common_context.h
@@ -93,6 +93,13 @@ struct radeon_renderbuffer
 	GLuint pf_pending;  /**< sequence number of pending flip */
 	GLuint vbl_pending;   /**< vblank sequence number of pending flip */
 	__DRIdrawable *dPriv;
+
+	/* r6xx+ tiling */
+	GLuint tile_config;
+	GLint group_bytes;
+	GLint num_channels;
+	GLint num_banks;
+	GLint r7xx_bank_op;
 };
 
 struct radeon_framebuffer
diff --git a/src/mesa/drivers/dri/radeon/radeon_screen.h b/src/mesa/drivers/dri/radeon/radeon_screen.h
index 0d7e335..2b33201 100644
--- a/src/mesa/drivers/dri/radeon/radeon_screen.h
+++ b/src/mesa/drivers/dri/radeon/radeon_screen.h
@@ -112,6 +112,13 @@ typedef struct radeon_screen {
    int kernel_mm;
    drm_radeon_sarea_t *sarea;	/* Private SAREA data */
    struct radeon_bo_manager *bom;
+
+   /* r6xx+ tiling */
+   GLuint tile_config;
+   GLint group_bytes;
+   GLint num_channels;
+   GLint num_banks;
+   GLint r7xx_bank_op;
 } radeonScreenRec, *radeonScreenPtr;
 
 #define IS_R100_CLASS(screen) \
diff --git a/src/mesa/drivers/dri/radeon/radeon_span.c b/src/mesa/drivers/dri/radeon/radeon_span.c
index 1adb609..9dfe2dd 100644
--- a/src/mesa/drivers/dri/radeon/radeon_span.c
+++ b/src/mesa/drivers/dri/radeon/radeon_span.c
@@ -111,7 +111,6 @@ static GLubyte *r200_depth_4byte(const struct radeon_renderbuffer * rrb,
  * two main types:
  * - 1D (akin to macro-linear/micro-tiled on older asics)
  * - 2D (akin to macro-tiled/micro-tiled on older asics)
- * only 1D tiling is implemented below
  */
 #if defined(RADEON_R600)
 static inline GLint r600_1d_tile_helper(const struct radeon_renderbuffer * rrb,
@@ -208,12 +207,190 @@ static inline GLint r600_1d_tile_helper(const struct radeon_renderbuffer * rrb,
     return offset;
 }
 
+static inline GLint r600_log2(GLint n)
+{
+	GLint log2 = 0;
+
+	while (n >>= 1)
+		++log2;
+	return log2;
+}
+
+static inline GLint r600_2d_tile_helper(const struct radeon_renderbuffer * rrb,
+					GLint x, GLint y, GLint is_depth, GLint is_stencil)
+{
+	GLint group_bytes = rrb->group_bytes;
+	GLint num_channels = rrb->num_channels;
+	GLint num_banks = rrb->num_banks;
+	GLint r7xx_bank_op = rrb->r7xx_bank_op;
+	/* */
+	GLint group_bits = r600_log2(group_bytes);
+	GLint channel_bits = r600_log2(num_channels);
+	GLint bank_bits = r600_log2(num_banks);
+	GLint element_bytes = rrb->cpp;
+	GLint num_samples = 1;
+	GLint tile_width = 8;
+	GLint tile_height = 8;
+	GLint tile_thickness = 1;
+	GLint macro_tile_width = num_banks;
+	GLint macro_tile_height = num_channels;
+	GLint pitch_elements = (rrb->pitch / element_bytes) / tile_width;
+	GLint height = rrb->base.Height / tile_height;
+	GLint z = 0;
+	GLint sample_number = 0;
+	/* */
+	GLint tile_bytes;
+	GLint macro_tile_bytes;
+	GLint macro_tiles_per_row;
+	GLint macro_tiles_per_slice;
+	GLint slice_offset;
+	GLint macro_tile_row_index;
+	GLint macro_tile_column_index;
+	GLint macro_tile_offset;
+	GLint pixel_number = 0;
+	GLint element_offset;
+	GLint bank = 0;
+	GLint channel = 0;
+	GLint total_offset;
+	GLint group_mask = (1 << group_bits) - 1;
+	GLint offset_low;
+	GLint offset_high;
+	GLint offset = 0;
+
+	switch (num_channels) {
+	case 2:
+	default:
+		// channel[0] = x[3] ^ y[3]
+		channel |= (((x >> 3) ^ (y >> 3)) & 1) << 0;
+		break;
+	case 4:
+		// channel[0] = x[4] ^ y[3]
+		channel |= (((x >> 4) ^ (y >> 3)) & 1) << 0;
+		// channel[1] = x[3] ^ y[4]
+		channel |= (((x >> 3) ^ (y >> 4)) & 1) << 1;
+		break;
+	case 8:
+		// channel[0] = x[5] ^ y[3]
+		channel |= (((x >> 5) ^ (y >> 3)) & 1) << 0;
+		// channel[0] = x[4] ^ x[5] ^ y[4]
+		channel |= (((x >> 4) ^ (x >> 5) ^ (y >> 4)) & 1) << 1;
+		// channel[0] = x[3] ^ y[5]
+		channel |= (((x >> 3) ^ (y >> 5)) & 1) << 2;
+		break;
+	}
+
+	switch (num_banks) {
+	case 4:
+		// bank[0] = x[3] ^ y[4 + log2(num_channels)]
+		bank |= (((x >> 3) ^ (y >> (4 + channel_bits))) & 1) << 0;
+		if (r7xx_bank_op)
+			// bank[1] = x[3] ^ y[4 + log2(num_channels)] ^ x[5]
+			bank |= (((x >> 4) ^ (y >> (3 + channel_bits)) ^ (x >> 5)) & 1) << 1;
+		else
+			// bank[1] = x[4] ^ y[3 + log2(num_channels)]
+			bank |= (((x >> 4) ^ (y >> (3 + channel_bits))) & 1) << 1;
+		break;
+	case 8:
+		// bank[0] = x[3] ^ y[5 + log2(num_channels)]
+		bank |= (((x >> 3) ^ (y >> (5 + channel_bits))) & 1) << 0;
+		// bank[1] = x[4] ^ y[4 + log2(num_channels)] ^ y[5 + log2(num_channels)]
+		bank |= (((x >> 4) ^ (y >> (4 + channel_bits)) ^ (y >> (5 + channel_bits))) & 1) << 1;
+		if (r7xx_bank_op)
+			// bank[2] = x[5] ^ y[3 + log2(num_channels)] ^ x[6]
+			bank |= (((x >> 5) ^ (y >> (3 + channel_bits)) ^ (x >> 6)) & 1) << 2;
+		else
+			// bank[2] = x[5] ^ y[3 + log2(num_channels)]
+			bank |= (((x >> 5) ^ (y >> (3 + channel_bits))) & 1) << 2;
+		break;
+	}
+
+	tile_bytes = tile_width * tile_height * tile_thickness * element_bytes * num_samples;
+	macro_tile_bytes = macro_tile_width * macro_tile_height * tile_bytes;
+	macro_tiles_per_row = pitch_elements / macro_tile_width;
+	macro_tiles_per_slice = macro_tiles_per_row * (height / macro_tile_height);
+	slice_offset = (z / tile_thickness) * macro_tiles_per_slice * macro_tile_bytes;
+	macro_tile_row_index = (y / tile_height) / macro_tile_height;
+	macro_tile_column_index = (x / tile_width) / macro_tile_width;
+	macro_tile_offset = ((macro_tile_row_index * macro_tiles_per_row) + macro_tile_column_index) * macro_tile_bytes;
+
+	if (is_depth) {
+		GLint pixel_offset = 0;
+
+		pixel_number |= ((x >> 0) & 1) << 0; // pn[0] = x[0]
+		pixel_number |= ((y >> 0) & 1) << 1; // pn[1] = y[0]
+		pixel_number |= ((x >> 1) & 1) << 2; // pn[2] = x[1]
+		pixel_number |= ((y >> 1) & 1) << 3; // pn[3] = y[1]
+		pixel_number |= ((x >> 2) & 1) << 4; // pn[4] = x[2]
+		pixel_number |= ((y >> 2) & 1) << 5; // pn[5] = y[2]
+		switch (element_bytes) {
+		case 2:
+			pixel_offset = pixel_number * element_bytes * num_samples;
+			break;
+		case 4:
+			/* stencil and depth data are stored separately within a tile.
+			 * stencil is stored in a contiguous tile before the depth tile.
+			 * stencil element is 1 byte, depth element is 3 bytes.
+			 * stencil tile is 64 bytes.
+			 */
+			if (is_stencil)
+				pixel_offset = pixel_number * 1 * num_samples;
+			else
+				pixel_offset = (pixel_number * 3 * num_samples) + 64;
+			break;
+		}
+		element_offset = pixel_offset + (sample_number * element_bytes);
+	} else {
+		GLint sample_offset;
+
+		switch (element_bytes) {
+		case 1:
+			pixel_number |= ((x >> 0) & 1) << 0; // pn[0] = x[0]
+			pixel_number |= ((x >> 1) & 1) << 1; // pn[1] = x[1]
+			pixel_number |= ((x >> 2) & 1) << 2; // pn[2] = x[2]
+			pixel_number |= ((y >> 1) & 1) << 3; // pn[3] = y[1]
+			pixel_number |= ((y >> 0) & 1) << 4; // pn[4] = y[0]
+			pixel_number |= ((y >> 2) & 1) << 5; // pn[5] = y[2]
+			break;
+		case 2:
+			pixel_number |= ((x >> 0) & 1) << 0; // pn[0] = x[0]
+			pixel_number |= ((x >> 1) & 1) << 1; // pn[1] = x[1]
+			pixel_number |= ((x >> 2) & 1) << 2; // pn[2] = x[2]
+			pixel_number |= ((y >> 0) & 1) << 3; // pn[3] = y[0]
+			pixel_number |= ((y >> 1) & 1) << 4; // pn[4] = y[1]
+			pixel_number |= ((y >> 2) & 1) << 5; // pn[5] = y[2]
+			break;
+		case 4:
+			pixel_number |= ((x >> 0) & 1) << 0; // pn[0] = x[0]
+			pixel_number |= ((x >> 1) & 1) << 1; // pn[1] = x[1]
+			pixel_number |= ((y >> 0) & 1) << 2; // pn[2] = y[0]
+			pixel_number |= ((x >> 2) & 1) << 3; // pn[3] = x[2]
+			pixel_number |= ((y >> 1) & 1) << 4; // pn[4] = y[1]
+			pixel_number |= ((y >> 2) & 1) << 5; // pn[5] = y[2]
+			break;
+		}
+		sample_offset = sample_number * (tile_bytes / num_samples);
+		element_offset = sample_offset + (pixel_number * element_bytes);
+	}
+	total_offset = (slice_offset + macro_tile_offset) >> (channel_bits + bank_bits);
+	total_offset += element_offset;
+
+	offset_low = total_offset & group_mask;
+	offset_high = (total_offset & ~group_mask) << (channel_bits + bank_bits);
+	offset = (bank << (group_bits + channel_bits)) + (channel << group_bits) + offset_low + offset_high;
+
+	return offset;
+}
+
 /* depth buffers */
 static GLubyte *r600_ptr_depth(const struct radeon_renderbuffer * rrb,
 			       GLint x, GLint y)
 {
     GLubyte *ptr = rrb->bo->ptr;
-    GLint offset = r600_1d_tile_helper(rrb, x, y, 1, 0);
+    GLint offset;
+    if (rrb->bo->flags & RADEON_BO_FLAGS_MACRO_TILE)
+	    offset = r600_2d_tile_helper(rrb, x, y, 1, 0);
+    else
+	    offset = r600_1d_tile_helper(rrb, x, y, 1, 0);
     return &ptr[offset];
 }
 
@@ -221,7 +398,11 @@ static GLubyte *r600_ptr_stencil(const struct radeon_renderbuffer * rrb,
 				 GLint x, GLint y)
 {
     GLubyte *ptr = rrb->bo->ptr;
-    GLint offset = r600_1d_tile_helper(rrb, x, y, 1, 1);
+    GLint offset;
+    if (rrb->bo->flags & RADEON_BO_FLAGS_MACRO_TILE)
+	    offset = r600_2d_tile_helper(rrb, x, y, 1, 1);
+    else
+	    offset = r600_1d_tile_helper(rrb, x, y, 1, 1);
     return &ptr[offset];
 }
 
@@ -235,7 +416,10 @@ static GLubyte *r600_ptr_color(const struct radeon_renderbuffer * rrb,
     if (rrb->has_surface || !(rrb->bo->flags & mask)) {
         offset = x * rrb->cpp + y * rrb->pitch;
     } else {
-	    offset = r600_1d_tile_helper(rrb, x, y, 0, 0);
+	    if (rrb->bo->flags & RADEON_BO_FLAGS_MACRO_TILE)
+		    offset = r600_2d_tile_helper(rrb, x, y, 0, 0);
+	    else
+		    offset = r600_1d_tile_helper(rrb, x, y, 0, 0);
     }
     return &ptr[offset];
 }
-- 
1.5.6.3



More information about the dri-devel mailing list