diff options
author | Cédric Cano <[email protected]> | 2011-04-19 13:02:14 -0400 |
---|---|---|
committer | Alex Deucher <[email protected]> | 2011-04-19 13:02:14 -0400 |
commit | 843dfe3206c4f397c7911b748373dde5540392a4 (patch) | |
tree | 7267cdef130f1aacc34c9ca9852d8710b474192b /src/gallium/drivers | |
parent | b545b2987aaca856f3a54ecb31fb4646bf619cc6 (diff) |
r600g: add big endian support for r6xx/r7xx
Signed-off-by: Cedric Cano <[email protected]>
Signed-off-by: Alex Deucher <[email protected]>
Diffstat (limited to 'src/gallium/drivers')
-rw-r--r-- | src/gallium/drivers/r600/r600_asm.c | 33 | ||||
-rw-r--r-- | src/gallium/drivers/r600/r600_asm.h | 1 | ||||
-rw-r--r-- | src/gallium/drivers/r600/r600_buffer.c | 22 | ||||
-rw-r--r-- | src/gallium/drivers/r600/r600_shader.c | 21 | ||||
-rw-r--r-- | src/gallium/drivers/r600/r600_state.c | 20 | ||||
-rw-r--r-- | src/gallium/drivers/r600/r600_state_common.c | 11 | ||||
-rw-r--r-- | src/gallium/drivers/r600/r600_state_inlines.h | 51 | ||||
-rw-r--r-- | 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 c22bd8e228c..7e854b1b81d 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 27ea293ebe5..26d337fe125 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 6ced719c8f0..c1f063fc21a 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 <[email protected]> */ +#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 6eac1f724af..188cea0ff88 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 eba48f8ad74..e9814da84fe 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 43dad0c8023..997c9a597ee 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 ebb372b244f..5d6145661a0 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 df70e2889e2..2bff52bec8c 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 |