Mesa (master): r600g: add big endian support for r6xx/r7xx

Alex Deucher agd5f at kemper.freedesktop.org
Tue Apr 19 10:43:43 PDT 2011


Module: Mesa
Branch: master
Commit: 843dfe3206c4f397c7911b748373dde5540392a4
URL:    http://cgit.freedesktop.org/mesa/mesa/commit/?id=843dfe3206c4f397c7911b748373dde5540392a4

Author: Cédric Cano <ccano at interfaceconcept.com>
Date:   Tue Apr 19 13:02:14 2011 -0400

r600g: add big endian support for r6xx/r7xx

Signed-off-by: Cedric Cano <ccano at interfaceconcept.com>
Signed-off-by: Alex Deucher <alexdeucher at gmail.com>

---

 src/gallium/drivers/r600/r600_asm.c           |   33 ++++++++++++++--
 src/gallium/drivers/r600/r600_asm.h           |    1 +
 src/gallium/drivers/r600/r600_buffer.c        |   22 +++++++++++
 src/gallium/drivers/r600/r600_shader.c        |   21 +++++++++-
 src/gallium/drivers/r600/r600_state.c         |   20 +++++++--
 src/gallium/drivers/r600/r600_state_common.c  |   11 ++++-
 src/gallium/drivers/r600/r600_state_inlines.h |   51 +++++++++++++++++++++++++
 src/gallium/drivers/r600/r600d.h              |    6 +++
 8 files changed, 151 insertions(+), 14 deletions(-)

diff --git a/src/gallium/drivers/r600/r600_asm.c b/src/gallium/drivers/r600/r600_asm.c
index c22bd8e..7e854b1 100644
--- a/src/gallium/drivers/r600/r600_asm.c
+++ b/src/gallium/drivers/r600/r600_asm.c
@@ -22,6 +22,7 @@
  */
 #include <stdio.h>
 #include <errno.h>
+#include <byteswap.h>
 #include "util/u_format.h"
 #include "util/u_memory.h"
 #include "pipe/p_shader_tokens.h"
@@ -32,6 +33,12 @@
 #include "r600_formats.h"
 #include "r600d.h"
 
+#ifdef PIPE_ARCH_BIG_ENDIAN
+#define CPU_TO_LE32(x)	bswap_32(x)
+#else
+#define CPU_TO_LE32(x)	(x)
+#endif
+
 #define NUM_OF_CYCLES 3
 #define NUM_OF_COMPONENTS 4
 
@@ -1383,6 +1390,7 @@ static int r600_bc_vtx_build(struct r600_bc *bc, struct r600_bc_vtx *vtx, unsign
 				S_SQ_VTX_WORD1_SRF_MODE_ALL(vtx->srf_mode_all) |
 				S_SQ_VTX_WORD1_GPR_DST_GPR(vtx->dst_gpr);
 	bc->bytecode[id++] = S_SQ_VTX_WORD2_OFFSET(vtx->offset) |
+	   			S_SQ_VTX_WORD2_ENDIAN_SWAP(vtx->endian) |
 				S_SQ_VTX_WORD2_MEGA_FETCH(1);
 	bc->bytecode[id++] = 0;
 	return 0;
@@ -1917,6 +1925,7 @@ void r600_bc_dump(struct r600_bc *bc)
 			fprintf(stderr, "MODE:%d)\n", vtx->srf_mode_all);
 			id++;
 			fprintf(stderr, "%04d %08X   ", id, bc->bytecode[id]);
+			fprintf(stderr, "ENDIAN:%d ", vtx->endian);
 			fprintf(stderr, "OFFSET:%d\n", vtx->offset);
 			//TODO
 			id++;
@@ -1929,7 +1938,7 @@ void r600_bc_dump(struct r600_bc *bc)
 }
 
 static void r600_vertex_data_type(enum pipe_format pformat, unsigned *format,
-				unsigned *num_format, unsigned *format_comp)
+				unsigned *num_format, unsigned *format_comp, unsigned *endian)
 {
 	const struct util_format_description *desc;
 	unsigned i;
@@ -1937,6 +1946,7 @@ static void r600_vertex_data_type(enum pipe_format pformat, unsigned *format,
 	*format = 0;
 	*num_format = 0;
 	*format_comp = 0;
+	*endian = ENDIAN_NONE;
 
 	desc = util_format_description(pformat);
 	if (desc->layout != UTIL_FORMAT_LAYOUT_PLAIN) {
@@ -1967,6 +1977,9 @@ static void r600_vertex_data_type(enum pipe_format pformat, unsigned *format,
 				*format = FMT_16_16_16_16_FLOAT;
 				break;
 			}
+#ifdef PIPE_ARCH_BIG_ENDIAN
+			*endian = ENDIAN_8IN16;
+#endif
 			break;
 		case 32:
 			switch (desc->nr_channels) {
@@ -1983,6 +1996,9 @@ static void r600_vertex_data_type(enum pipe_format pformat, unsigned *format,
 				*format = FMT_32_32_32_32_FLOAT;
 				break;
 			}
+#ifdef PIPE_ARCH_BIG_ENDIAN
+			*endian = ENDIAN_8IN32;
+#endif
 			break;
 		default:
 			goto out_unknown;
@@ -2020,6 +2036,9 @@ static void r600_vertex_data_type(enum pipe_format pformat, unsigned *format,
 				*format = FMT_16_16_16_16;
 				break;
 			}
+#ifdef PIPE_ARCH_BIG_ENDIAN
+			*endian = ENDIAN_8IN16;
+#endif
 			break;
 		case 32:
 			switch (desc->nr_channels) {
@@ -2036,6 +2055,9 @@ static void r600_vertex_data_type(enum pipe_format pformat, unsigned *format,
 				*format = FMT_32_32_32_32;
 				break;
 			}
+#ifdef PIPE_ARCH_BIG_ENDIAN
+			*endian = ENDIAN_8IN32;
+#endif
 			break;
 		default:
 			goto out_unknown;
@@ -2067,7 +2089,7 @@ int r600_vertex_elements_build_fetch_shader(struct r600_pipe_context *rctx, stru
 	struct pipe_vertex_element *elements = ve->elements;
 	const struct util_format_description *desc;
 	unsigned fetch_resource_start = rctx->family >= CHIP_CEDAR ? 0 : 160;
-	unsigned format, num_format, format_comp;
+	unsigned format, num_format, format_comp, endian;
 	u32 *bytecode;
 	int i, r;
 
@@ -2114,7 +2136,7 @@ int r600_vertex_elements_build_fetch_shader(struct r600_pipe_context *rctx, stru
 
 	for (i = 0; i < ve->count; i++) {
 		unsigned vbuffer_index;
-		r600_vertex_data_type(ve->elements[i].src_format, &format, &num_format, &format_comp);
+		r600_vertex_data_type(ve->elements[i].src_format, &format, &num_format, &format_comp, &endian);
 		desc = util_format_description(ve->elements[i].src_format);
 		if (desc == NULL) {
 			r600_bc_clear(&bc);
@@ -2140,6 +2162,7 @@ int r600_vertex_elements_build_fetch_shader(struct r600_pipe_context *rctx, stru
 		vtx.format_comp_all = format_comp;
 		vtx.srf_mode_all = 1;
 		vtx.offset = elements[i].src_offset;
+		vtx.endian = endian;
 
 		if ((r = r600_bc_add_vtx(&bc, &vtx))) {
 			r600_bc_clear(&bc);
@@ -2179,7 +2202,9 @@ int r600_vertex_elements_build_fetch_shader(struct r600_pipe_context *rctx, stru
 		return -ENOMEM;
 	}
 
-	memcpy(bytecode, bc.bytecode, ve->fs_size);
+	for(i = 0; i < ve->fs_size / 4; i++) {
+		*(bytecode + i) = CPU_TO_LE32(*(bc.bytecode + i));
+	}
 
 	r600_bo_unmap(rctx->radeon, ve->fetch_shader);
 	r600_bc_clear(&bc);
diff --git a/src/gallium/drivers/r600/r600_asm.h b/src/gallium/drivers/r600/r600_asm.h
index 27ea293..26d337f 100644
--- a/src/gallium/drivers/r600/r600_asm.h
+++ b/src/gallium/drivers/r600/r600_asm.h
@@ -104,6 +104,7 @@ struct r600_bc_vtx {
 	unsigned			format_comp_all;
 	unsigned			srf_mode_all;
 	unsigned			offset;
+	unsigned			endian;
 };
 
 struct r600_bc_output {
diff --git a/src/gallium/drivers/r600/r600_buffer.c b/src/gallium/drivers/r600/r600_buffer.c
index 6ced719..c1f063f 100644
--- a/src/gallium/drivers/r600/r600_buffer.c
+++ b/src/gallium/drivers/r600/r600_buffer.c
@@ -24,6 +24,8 @@
  *      Jerome Glisse
  *      Corbin Simpson <MostAwesomeDude at gmail.com>
  */
+#include <byteswap.h>
+
 #include <pipe/p_screen.h>
 #include <util/u_format.h>
 #include <util/u_math.h>
@@ -266,11 +268,31 @@ void r600_upload_const_buffer(struct r600_pipe_context *rctx, struct r600_resour
 		uint8_t *ptr = (*rbuffer)->r.b.user_ptr;
 		unsigned size = (*rbuffer)->r.b.b.b.width0;
 		boolean flushed;
+#ifdef PIPE_ARCH_BIG_ENDIAN
+		int i;
+		uint32_t *tmpPtr;
+
+		*rbuffer = NULL;
+
+		tmpPtr = (uint32_t *)malloc(size);
+		/* big endian swap */
+		if(tmpPtr == NULL) {
+			return;
+		}
+		for(i = 0; i < size / 4; i++) {
+			tmpPtr[i] = bswap_32(*((uint32_t *)ptr + i));
+		}
+	
+		u_upload_data(rctx->vbuf_mgr->uploader, 0, size, tmpPtr, const_offset,
+			      (struct pipe_resource**)rbuffer, &flushed);
 
+		free(tmpPtr);
+#else
 		*rbuffer = NULL;
 
 		u_upload_data(rctx->vbuf_mgr->uploader, 0, size, ptr, const_offset,
 			      (struct pipe_resource**)rbuffer, &flushed);
+#endif
 	} else {
 		*const_offset = 0;
 	}
diff --git a/src/gallium/drivers/r600/r600_shader.c b/src/gallium/drivers/r600/r600_shader.c
index 6eac1f7..188cea0 100644
--- a/src/gallium/drivers/r600/r600_shader.c
+++ b/src/gallium/drivers/r600/r600_shader.c
@@ -33,6 +33,13 @@
 #include "r600d.h"
 #include <stdio.h>
 #include <errno.h>
+#include <byteswap.h>
+
+#ifdef PIPE_ARCH_BIG_ENDIAN
+#define CPU_TO_LE32(x)	bswap_32(x)
+#else
+#define CPU_TO_LE32(x)	(x)
+#endif
 
 int r600_find_vs_semantic_index(struct r600_shader *vs,
 				struct r600_shader *ps, int id)
@@ -52,7 +59,8 @@ static int r600_pipe_shader(struct pipe_context *ctx, struct r600_pipe_shader *s
 {
 	struct r600_pipe_context *rctx = (struct r600_pipe_context *)ctx;
 	struct r600_shader *rshader = &shader->shader;
-	void *ptr;
+	uint32_t *ptr;
+	int	i;
 
 	/* copy new shader */
 	if (shader->bo == NULL) {
@@ -60,8 +68,10 @@ static int r600_pipe_shader(struct pipe_context *ctx, struct r600_pipe_shader *s
 		if (shader->bo == NULL) {
 			return -ENOMEM;
 		}
-		ptr = r600_bo_map(rctx->radeon, shader->bo, 0, NULL);
-		memcpy(ptr, rshader->bc.bytecode, rshader->bc.ndw * 4);
+		ptr = (uint32_t*)r600_bo_map(rctx->radeon, shader->bo, 0, NULL);
+		for(i = 0; i < rshader->bc.ndw; i++) {
+			*(ptr + i) = CPU_TO_LE32(*(rshader->bc.bytecode + i));
+		}
 		r600_bo_unmap(rctx->radeon, shader->bo);
 	}
 	/* build state */
@@ -467,6 +477,11 @@ static int tgsi_fetch_rel_const(struct r600_shader_ctx *ctx, unsigned int offset
 	vtx.num_format_all = 2;		/* NUM_FORMAT_SCALED */
 	vtx.format_comp_all = 1;	/* FORMAT_COMP_SIGNED */
 	vtx.srf_mode_all = 1;		/* SRF_MODE_NO_ZERO */
+#ifdef PIPE_ARCH_BIG_ENDIAN
+	vtx.endian = ENDIAN_8IN32;
+#else
+	vtx.endian = ENDIAN_NONE;
+#endif
 
 	if ((r = r600_bc_add_vtx(ctx->bc, &vtx)))
 		return r;
diff --git a/src/gallium/drivers/r600/r600_state.c b/src/gallium/drivers/r600/r600_state.c
index eba48f8..e9814da 100644
--- a/src/gallium/drivers/r600/r600_state.c
+++ b/src/gallium/drivers/r600/r600_state.c
@@ -413,7 +413,7 @@ static struct pipe_sampler_view *r600_create_sampler_view(struct pipe_context *c
 	const struct util_format_description *desc;
 	struct r600_resource_texture *tmp;
 	struct r600_resource *rbuffer;
-	unsigned format;
+	unsigned format, endian;
 	uint32_t word4 = 0, yuv_format = 0, pitch = 0;
 	unsigned char swizzle[4], array_mode = 0, tile_type = 0;
 	struct r600_bo *bo[2];
@@ -450,6 +450,7 @@ static struct pipe_sampler_view *r600_create_sampler_view(struct pipe_context *c
 	        r600_texture_depth_flush(ctx, texture, TRUE);
 		tmp = tmp->flushed_depth_texture;
 	}
+	endian = r600_colorformat_endian_swap(format);
 
 	if (tmp->force_int_type) {
 		word4 &= C_038010_NUM_FORMAT_ALL;
@@ -490,6 +491,7 @@ static struct pipe_sampler_view *r600_create_sampler_view(struct pipe_context *c
 				word4 |
 				S_038010_SRF_MODE_ALL(V_038010_SRF_MODE_NO_ZERO) |
 				S_038010_REQUEST_SIZE(1) |
+				S_038010_ENDIAN_SWAP(endian) |
 				S_038010_BASE_LEVEL(state->u.tex.first_level), 0xFFFFFFFF, NULL);
 	r600_pipe_state_add_reg(rstate, R_038014_RESOURCE0_WORD5,
 				S_038014_LAST_LEVEL(state->u.tex.last_level) |
@@ -718,7 +720,7 @@ static void r600_cb(struct r600_pipe_context *rctx, struct r600_pipe_state *rsta
 	unsigned level = state->cbufs[cb]->u.tex.level;
 	unsigned pitch, slice;
 	unsigned color_info;
-	unsigned format, swap, ntype;
+	unsigned format, swap, ntype, endian;
 	unsigned offset;
 	const struct util_format_description *desc;
 	struct r600_bo *bo[3];
@@ -757,6 +759,11 @@ static void r600_cb(struct r600_pipe_context *rctx, struct r600_pipe_state *rsta
 
 	format = r600_translate_colorformat(surf->base.format);
 	swap = r600_translate_colorswap(surf->base.format);
+	if(rbuffer->b.b.b.usage == PIPE_USAGE_STAGING) {
+		endian = ENDIAN_NONE;
+	} else {
+		endian = r600_colorformat_endian_swap(format);
+	}
 
 	/* disable when gallium grows int textures */
 	if ((format == FMT_32_32_32_32 || format == FMT_16_16_16_16) && rtex->force_int_type)
@@ -766,7 +773,8 @@ static void r600_cb(struct r600_pipe_context *rctx, struct r600_pipe_state *rsta
 		S_0280A0_COMP_SWAP(swap) |
 		S_0280A0_ARRAY_MODE(rtex->array_mode[level]) |
 		S_0280A0_BLEND_CLAMP(1) |
-		S_0280A0_NUMBER_TYPE(ntype);
+		S_0280A0_NUMBER_TYPE(ntype) |
+		S_0280A0_ENDIAN(endian);
 
 	/* on R600 this can't be set if BLEND_CLAMP isn't set,
 	   if BLEND_FLOAT32 is set of > 11 bits in a UNORM or SNORM */
@@ -1445,8 +1453,10 @@ void r600_pipe_set_buffer_resource(struct r600_pipe_context *rctx,
 	r600_pipe_state_add_reg(rstate, R_038004_RESOURCE0_WORD1,
 				rbuffer->bo_size - offset - 1, 0xFFFFFFFF, NULL);
 	r600_pipe_state_add_reg(rstate, R_038008_RESOURCE0_WORD2,
-				S_038008_STRIDE(stride),
-				0xFFFFFFFF, NULL);
+#ifdef PIPE_ARCH_BIG_ENDIAN
+				S_038008_ENDIAN_SWAP(ENDIAN_8IN32) |
+#endif
+				S_038008_STRIDE(stride), 0xFFFFFFFF, NULL);
 	r600_pipe_state_add_reg(rstate, R_03800C_RESOURCE0_WORD3,
 				0x00000000, 0xFFFFFFFF, NULL);
 	r600_pipe_state_add_reg(rstate, R_038010_RESOURCE0_WORD4,
diff --git a/src/gallium/drivers/r600/r600_state_common.c b/src/gallium/drivers/r600/r600_state_common.c
index 43dad0c..997c9a5 100644
--- a/src/gallium/drivers/r600/r600_state_common.c
+++ b/src/gallium/drivers/r600/r600_state_common.c
@@ -435,7 +435,7 @@ void r600_draw_vbo(struct pipe_context *ctx, const struct pipe_draw_info *info)
 {
 	struct r600_pipe_context *rctx = (struct r600_pipe_context *)ctx;
 	struct r600_resource *rbuffer;
-	u32 vgt_dma_index_type, vgt_draw_initiator, mask;
+	u32 vgt_dma_index_type, vgt_dma_swap_mode, vgt_draw_initiator, mask;
 	struct r600_draw rdraw;
 	struct r600_pipe_state vgt;
 	struct r600_drawl draw = {};
@@ -467,14 +467,21 @@ void r600_draw_vbo(struct pipe_context *ctx, const struct pipe_draw_info *info)
 		draw.info.index_bias = info->start;
 	}
 
+	vgt_dma_swap_mode = 0;
 	switch (draw.index_size) {
 	case 2:
 		vgt_draw_initiator = 0;
 		vgt_dma_index_type = 0;
+#ifdef PIPE_ARCH_BIG_ENDIAN
+		vgt_dma_swap_mode = ENDIAN_8IN16;
+#endif
 		break;
 	case 4:
 		vgt_draw_initiator = 0;
 		vgt_dma_index_type = 1;
+#ifdef PIPE_ARCH_BIG_ENDIAN
+		vgt_dma_swap_mode = ENDIAN_8IN32;
+#endif
 		break;
 	case 0:
 		vgt_draw_initiator = 2;
@@ -521,7 +528,7 @@ void r600_draw_vbo(struct pipe_context *ctx, const struct pipe_draw_info *info)
 
 	rdraw.vgt_num_indices = draw.info.count;
 	rdraw.vgt_num_instances = draw.info.instance_count;
-	rdraw.vgt_index_type = vgt_dma_index_type;
+	rdraw.vgt_index_type = vgt_dma_index_type | (vgt_dma_swap_mode << 2);
 	rdraw.vgt_draw_initiator = vgt_draw_initiator;
 	rdraw.indices = NULL;
 	if (draw.index_buffer) {
diff --git a/src/gallium/drivers/r600/r600_state_inlines.h b/src/gallium/drivers/r600/r600_state_inlines.h
index ebb372b..5d61456 100644
--- a/src/gallium/drivers/r600/r600_state_inlines.h
+++ b/src/gallium/drivers/r600/r600_state_inlines.h
@@ -501,6 +501,57 @@ static INLINE uint32_t r600_translate_colorformat(enum pipe_format format)
 	}
 }
 
+static INLINE uint32_t r600_colorformat_endian_swap(uint32_t colorformat)
+{
+#ifdef PIPE_ARCH_BIG_ENDIAN
+	switch(colorformat) {
+	case V_0280A0_COLOR_4_4:
+		return(ENDIAN_NONE);
+
+		/* 8-bit buffers. */
+	case V_0280A0_COLOR_8:
+		return(ENDIAN_NONE);
+
+		/* 16-bit buffers. */
+	case V_0280A0_COLOR_5_6_5:
+	case V_0280A0_COLOR_1_5_5_5:
+	case V_0280A0_COLOR_4_4_4_4:
+	case V_0280A0_COLOR_16:
+	case V_0280A0_COLOR_8_8:
+		return(ENDIAN_8IN16);
+
+		/* 32-bit buffers. */
+	case V_0280A0_COLOR_8_8_8_8:
+	case V_0280A0_COLOR_2_10_10_10:
+	case V_0280A0_COLOR_8_24:
+	case V_0280A0_COLOR_24_8:
+	case V_0280A0_COLOR_32_FLOAT:
+	case V_0280A0_COLOR_16_16_FLOAT:
+	case V_0280A0_COLOR_16_16:
+		return(ENDIAN_8IN32);
+
+		/* 64-bit buffers. */
+	case V_0280A0_COLOR_16_16_16_16:
+	case V_0280A0_COLOR_16_16_16_16_FLOAT:
+		return(ENDIAN_8IN16);
+
+	case V_0280A0_COLOR_32_32_FLOAT:
+	case V_0280A0_COLOR_32_32:
+		return(ENDIAN_8IN32);
+
+		/* 128-bit buffers. */
+	case V_0280A0_COLOR_32_32_32_FLOAT:
+	case V_0280A0_COLOR_32_32_32_32_FLOAT:
+	case V_0280A0_COLOR_32_32_32_32:
+		return(ENDIAN_8IN32);
+	default:
+		return ENDIAN_NONE; /* Unsupported. */
+	}
+#else
+	return ENDIAN_NONE;
+#endif
+}
+
 static INLINE boolean r600_is_sampler_format_supported(struct pipe_screen *screen, enum pipe_format format)
 {
 	return r600_translate_texformat(screen, format, NULL, NULL, NULL) != ~0;
diff --git a/src/gallium/drivers/r600/r600d.h b/src/gallium/drivers/r600/r600d.h
index df70e28..2bff52b 100644
--- a/src/gallium/drivers/r600/r600d.h
+++ b/src/gallium/drivers/r600/r600d.h
@@ -3460,4 +3460,10 @@
 #define SQ_TEX_INST_SAMPLE 0x10
 #define SQ_TEX_INST_SAMPLE_L 0x11
 #define SQ_TEX_INST_SAMPLE_C 0x18
+
+#define ENDIAN_NONE		0
+#define ENDIAN_8IN16	1
+#define ENDIAN_8IN32	2
+#define ENDIAN_8IN64	3
+
 #endif



More information about the mesa-commit mailing list