diff options
Diffstat (limited to 'src/gallium/drivers/r300')
-rw-r--r-- | src/gallium/drivers/r300/Makefile | 1 | ||||
-rw-r--r-- | src/gallium/drivers/r300/r300_context.h | 13 | ||||
-rw-r--r-- | src/gallium/drivers/r300/r300_emit.c | 20 | ||||
-rw-r--r-- | src/gallium/drivers/r300/r300_fs.c | 58 | ||||
-rw-r--r-- | src/gallium/drivers/r300/r300_query.c | 6 | ||||
-rw-r--r-- | src/gallium/drivers/r300/r300_render_translate.c | 112 | ||||
-rw-r--r-- | src/gallium/drivers/r300/r300_screen.c | 1 | ||||
-rw-r--r-- | src/gallium/drivers/r300/r300_state.c | 28 | ||||
-rw-r--r-- | src/gallium/drivers/r300/r300_state_derived.c | 82 | ||||
-rw-r--r-- | src/gallium/drivers/r300/r300_state_inlines.h | 18 | ||||
-rw-r--r-- | src/gallium/drivers/r300/r300_texture.c | 64 | ||||
-rw-r--r-- | src/gallium/drivers/r300/r300_texture_desc.c | 51 |
12 files changed, 234 insertions, 220 deletions
diff --git a/src/gallium/drivers/r300/Makefile b/src/gallium/drivers/r300/Makefile index 728bc40a5bb..66d900ebb5f 100644 --- a/src/gallium/drivers/r300/Makefile +++ b/src/gallium/drivers/r300/Makefile @@ -39,5 +39,6 @@ EXTRA_OBJECTS = \ include ../../Makefile.template +.PHONY: $(COMPILER_ARCHIVE) $(COMPILER_ARCHIVE): $(MAKE) -C $(TOP)/src/mesa/drivers/dri/r300/compiler diff --git a/src/gallium/drivers/r300/r300_context.h b/src/gallium/drivers/r300/r300_context.h index 7f655dbfd21..b59bc002610 100644 --- a/src/gallium/drivers/r300/r300_context.h +++ b/src/gallium/drivers/r300/r300_context.h @@ -125,6 +125,8 @@ struct r300_gpu_flush { uint32_t cb_flush_clean[6]; }; +#define RS_STATE_MAIN_SIZE 23 + struct r300_rs_state { /* Original rasterizer state. */ struct pipe_rasterizer_state rs; @@ -132,7 +134,7 @@ struct r300_rs_state { struct pipe_rasterizer_state rs_draw; /* Command buffers. */ - uint32_t cb_main[25]; + uint32_t cb_main[RS_STATE_MAIN_SIZE]; uint32_t cb_poly_offset_zb16[5]; uint32_t cb_poly_offset_zb24[5]; @@ -150,6 +152,7 @@ struct r300_rs_block { uint32_t vap_vtx_state_cntl; /* R300_VAP_VTX_STATE_CNTL: 0x2180 */ uint32_t vap_vsm_vtx_assm; /* R300_VAP_VSM_VTX_ASSM: 0x2184 */ uint32_t vap_out_vtx_fmt[2]; /* R300_VAP_OUTPUT_VTX_FMT_[0-1]: 0x2090 */ + uint32_t gb_enable; uint32_t ip[8]; /* R300_RS_IP_[0-7], R500_RS_IP_[0-7] */ uint32_t count; /* R300_RS_COUNT */ @@ -162,7 +165,6 @@ struct r300_sampler_state { uint32_t filter0; /* R300_TX_FILTER0: 0x4400 */ uint32_t filter1; /* R300_TX_FILTER1: 0x4440 */ - uint32_t border_color; /* R300_TX_BORDER_COLOR: 0x45c0 */ /* Min/max LOD must be clamped to [0, last_level], thus * it's dependent on a currently bound texture */ @@ -334,6 +336,13 @@ struct r300_texture_desc { /* Parent class. */ struct u_resource b; + /* Width, height, and depth. + * Most of the time, these are equal to pipe_texture::width0, height0, + * and depth0. However, NPOT 3D textures must have dimensions aligned + * to POT, and this is the only case when these variables differ from + * pipe_texture. */ + unsigned width0, height0, depth0; + /* Buffer tiling. * Macrotiling is specified per-level because small mipmaps cannot * be macrotiled. */ diff --git a/src/gallium/drivers/r300/r300_emit.c b/src/gallium/drivers/r300/r300_emit.c index b2b34c3efcb..3a1085d2dc5 100644 --- a/src/gallium/drivers/r300/r300_emit.c +++ b/src/gallium/drivers/r300/r300_emit.c @@ -89,7 +89,7 @@ static const float * get_rc_constant_state( { struct r300_textures_state* texstate = r300->textures_state.state; static float vec[4] = { 0.0, 0.0, 0.0, 1.0 }; - struct pipe_resource *tex; + struct r300_texture *tex; assert(constant->Type == RC_CONSTANT_STATE); @@ -97,9 +97,17 @@ static const float * get_rc_constant_state( /* Factor for converting rectangle coords to * normalized coords. Should only show up on non-r500. */ case RC_STATE_R300_TEXRECT_FACTOR: - tex = texstate->sampler_views[constant->u.State[1]]->base.texture; - vec[0] = 1.0 / tex->width0; - vec[1] = 1.0 / tex->height0; + tex = r300_texture(texstate->sampler_views[constant->u.State[1]]->base.texture); + vec[0] = 1.0 / tex->desc.width0; + vec[1] = 1.0 / tex->desc.height0; + break; + + case RC_STATE_R300_TEXSCALE_FACTOR: + tex = r300_texture(texstate->sampler_views[constant->u.State[1]]->base.texture); + /* Add a small number to the texture size to work around rounding errors in hw. */ + vec[0] = tex->desc.b.b.width0 / (tex->desc.width0 + 0.001f); + vec[1] = tex->desc.b.b.height0 / (tex->desc.height0 + 0.001f); + vec[2] = tex->desc.b.b.depth0 / (tex->desc.depth0 + 0.001f); break; case RC_STATE_R300_VIEWPORT_SCALE: @@ -667,7 +675,7 @@ void r300_emit_rs_state(struct r300_context* r300, unsigned size, void* state) CS_LOCALS(r300); BEGIN_CS(size); - OUT_CS_TABLE(rs->cb_main, 25); + OUT_CS_TABLE(rs->cb_main, RS_STATE_MAIN_SIZE); if (rs->polygon_offset_enable) { if (r300->zbuffer_bpp == 16) { OUT_CS_TABLE(rs->cb_poly_offset_zb16, 5); @@ -709,6 +717,8 @@ void r300_emit_rs_block_state(struct r300_context* r300, OUT_CS_REG_SEQ(R300_VAP_OUTPUT_VTX_FMT_0, 2); OUT_CS(rs->vap_out_vtx_fmt[0]); OUT_CS(rs->vap_out_vtx_fmt[1]); + OUT_CS_REG_SEQ(R300_GB_ENABLE, 1); + OUT_CS(rs->gb_enable); if (r300->screen->caps.is_r500) { OUT_CS_REG_SEQ(R500_RS_IP_0, count); diff --git a/src/gallium/drivers/r300/r300_fs.c b/src/gallium/drivers/r300/r300_fs.c index b8dab88ef09..d9d4a9304df 100644 --- a/src/gallium/drivers/r300/r300_fs.c +++ b/src/gallium/drivers/r300/r300_fs.c @@ -150,12 +150,16 @@ static void get_external_state( unsigned char *swizzle; for (i = 0; i < texstate->sampler_state_count; i++) { - struct r300_sampler_state* s = texstate->sampler_states[i]; + struct r300_sampler_state *s = texstate->sampler_states[i]; + struct r300_sampler_view *v = texstate->sampler_views[i]; + struct r300_texture *t; - if (!s) { + if (!s || !v) { continue; } + t = r300_texture(texstate->sampler_views[i]->base.texture); + if (s->state.compare_mode == PIPE_TEX_COMPARE_R_TO_TEXTURE) { state->unit[i].compare_mode_enabled = 1; @@ -176,35 +180,29 @@ static void get_external_state( state->unit[i].non_normalized_coords = !s->state.normalized_coords; - if (texstate->sampler_views[i]) { - struct r300_texture *t; - t = (struct r300_texture*)texstate->sampler_views[i]->base.texture; - - /* XXX this should probably take into account STR, not just S. */ - if (t->desc.is_npot) { - switch (s->state.wrap_s) { - case PIPE_TEX_WRAP_REPEAT: - state->unit[i].wrap_mode = RC_WRAP_REPEAT; - state->unit[i].fake_npot = TRUE; - break; - - case PIPE_TEX_WRAP_MIRROR_REPEAT: - state->unit[i].wrap_mode = RC_WRAP_MIRRORED_REPEAT; - state->unit[i].fake_npot = TRUE; - break; - - case PIPE_TEX_WRAP_MIRROR_CLAMP: - case PIPE_TEX_WRAP_MIRROR_CLAMP_TO_EDGE: - case PIPE_TEX_WRAP_MIRROR_CLAMP_TO_BORDER: - state->unit[i].wrap_mode = RC_WRAP_MIRRORED_CLAMP; - state->unit[i].fake_npot = TRUE; - break; - - default: - state->unit[i].wrap_mode = RC_WRAP_NONE; - break; - } + /* XXX this should probably take into account STR, not just S. */ + if (t->desc.is_npot) { + switch (s->state.wrap_s) { + case PIPE_TEX_WRAP_REPEAT: + state->unit[i].wrap_mode = RC_WRAP_REPEAT; + break; + + case PIPE_TEX_WRAP_MIRROR_REPEAT: + state->unit[i].wrap_mode = RC_WRAP_MIRRORED_REPEAT; + break; + + case PIPE_TEX_WRAP_MIRROR_CLAMP: + case PIPE_TEX_WRAP_MIRROR_CLAMP_TO_EDGE: + case PIPE_TEX_WRAP_MIRROR_CLAMP_TO_BORDER: + state->unit[i].wrap_mode = RC_WRAP_MIRRORED_CLAMP; + break; + + default: + state->unit[i].wrap_mode = RC_WRAP_NONE; } + + if (t->desc.b.b.target == PIPE_TEXTURE_3D) + state->unit[i].clamp_and_scale_before_fetch = TRUE; } } } diff --git a/src/gallium/drivers/r300/r300_query.c b/src/gallium/drivers/r300/r300_query.c index 5b0121ce9e1..5f34fcb2744 100644 --- a/src/gallium/drivers/r300/r300_query.c +++ b/src/gallium/drivers/r300/r300_query.c @@ -158,7 +158,7 @@ static void r300_render_condition(struct pipe_context *pipe, uint mode) { struct r300_context *r300 = r300_context(pipe); - uint64_t result; + uint64_t result = 0; boolean wait; if (query) { @@ -167,9 +167,9 @@ static void r300_render_condition(struct pipe_context *pipe, if (!r300_get_query_result(pipe, query, wait, &result)) { r300->skip_rendering = FALSE; + } else { + r300->skip_rendering = result == 0; } - - r300->skip_rendering = result == 0; } else { r300->skip_rendering = FALSE; } diff --git a/src/gallium/drivers/r300/r300_render_translate.c b/src/gallium/drivers/r300/r300_render_translate.c index 0ea11e5bfc2..9247064508f 100644 --- a/src/gallium/drivers/r300/r300_render_translate.c +++ b/src/gallium/drivers/r300/r300_render_translate.c @@ -29,6 +29,7 @@ #include "r300_context.h" #include "translate/translate.h" +#include "util/u_index_modify.h" void r300_begin_vertex_translate(struct r300_context *r300) { @@ -188,111 +189,6 @@ void r300_end_vertex_translate(struct r300_context *r300) NULL); } -static void r300_shorten_ubyte_elts(struct r300_context* r300, - struct pipe_resource** elts, - int index_bias, - unsigned start, - unsigned count) -{ - struct pipe_context* context = &r300->context; - struct pipe_screen* screen = r300->context.screen; - struct pipe_resource* new_elts; - unsigned char *in_map; - unsigned short *out_map; - struct pipe_transfer *src_transfer, *dst_transfer; - unsigned i; - - new_elts = pipe_buffer_create(screen, - PIPE_BIND_INDEX_BUFFER, - 2 * count); - - in_map = pipe_buffer_map(context, *elts, PIPE_TRANSFER_READ, &src_transfer); - out_map = pipe_buffer_map(context, new_elts, PIPE_TRANSFER_WRITE, &dst_transfer); - - in_map += start; - - for (i = 0; i < count; i++) { - *out_map = (unsigned short)(*in_map + index_bias); - in_map++; - out_map++; - } - - pipe_buffer_unmap(context, *elts, src_transfer); - pipe_buffer_unmap(context, new_elts, dst_transfer); - - *elts = new_elts; -} - -static void r300_rebuild_ushort_elts(struct r300_context *r300, - struct pipe_resource **elts, - int index_bias, - unsigned start, unsigned count) -{ - struct pipe_context *context = &r300->context; - struct pipe_transfer *in_transfer = NULL; - struct pipe_transfer *out_transfer = NULL; - struct pipe_resource *new_elts; - unsigned short *in_map; - unsigned short *out_map; - unsigned i; - - new_elts = pipe_buffer_create(context->screen, - PIPE_BIND_INDEX_BUFFER, - 2 * count); - - in_map = pipe_buffer_map(context, *elts, - PIPE_TRANSFER_READ, &in_transfer); - out_map = pipe_buffer_map(context, new_elts, - PIPE_TRANSFER_WRITE, &out_transfer); - - in_map += start; - for (i = 0; i < count; i++) { - *out_map = (unsigned short)(*in_map + index_bias); - in_map++; - out_map++; - } - - pipe_buffer_unmap(context, *elts, in_transfer); - pipe_buffer_unmap(context, new_elts, out_transfer); - - *elts = new_elts; -} - -static void r300_rebuild_uint_elts(struct r300_context *r300, - struct pipe_resource **elts, - int index_bias, - unsigned start, unsigned count) -{ - struct pipe_context *context = &r300->context; - struct pipe_transfer *in_transfer = NULL; - struct pipe_transfer *out_transfer = NULL; - struct pipe_resource *new_elts; - unsigned int *in_map; - unsigned int *out_map; - unsigned i; - - new_elts = pipe_buffer_create(context->screen, - PIPE_BIND_INDEX_BUFFER, - 2 * count); - - in_map = pipe_buffer_map(context, *elts, - PIPE_TRANSFER_READ, &in_transfer); - out_map = pipe_buffer_map(context, new_elts, - PIPE_TRANSFER_WRITE, &out_transfer); - - in_map += start; - for (i = 0; i < count; i++) { - *out_map = (unsigned int)(*in_map + index_bias); - in_map++; - out_map++; - } - - pipe_buffer_unmap(context, *elts, in_transfer); - pipe_buffer_unmap(context, new_elts, out_transfer); - - *elts = new_elts; -} - void r300_translate_index_buffer(struct r300_context *r300, struct pipe_resource **index_buffer, unsigned *index_size, unsigned index_offset, @@ -300,21 +196,21 @@ void r300_translate_index_buffer(struct r300_context *r300, { switch (*index_size) { case 1: - r300_shorten_ubyte_elts(r300, index_buffer, index_offset, *start, count); + util_shorten_ubyte_elts(&r300->context, index_buffer, index_offset, *start, count); *index_size = 2; *start = 0; break; case 2: if (*start % 2 != 0 || index_offset) { - r300_rebuild_ushort_elts(r300, index_buffer, index_offset, *start, count); + util_rebuild_ushort_elts(&r300->context, index_buffer, index_offset, *start, count); *start = 0; } break; case 4: if (index_offset) { - r300_rebuild_uint_elts(r300, index_buffer, index_offset, *start, count); + util_rebuild_uint_elts(&r300->context, index_buffer, index_offset, *start, count); *start = 0; } break; diff --git a/src/gallium/drivers/r300/r300_screen.c b/src/gallium/drivers/r300/r300_screen.c index 7f41ff0e2ec..b448924f85e 100644 --- a/src/gallium/drivers/r300/r300_screen.c +++ b/src/gallium/drivers/r300/r300_screen.c @@ -124,6 +124,7 @@ static int r300_get_param(struct pipe_screen* pscreen, enum pipe_cap param) case PIPE_CAP_INDEP_BLEND_FUNC: case PIPE_CAP_DEPTH_CLAMP: /* XXX implemented, but breaks Regnum Online */ case PIPE_CAP_DEPTHSTENCIL_CLEAR_SEPARATE: + case PIPE_CAP_SHADER_STENCIL_EXPORT: return 0; /* Texturing. */ diff --git a/src/gallium/drivers/r300/r300_state.c b/src/gallium/drivers/r300/r300_state.c index 8ccb63964e7..f2479a994c8 100644 --- a/src/gallium/drivers/r300/r300_state.c +++ b/src/gallium/drivers/r300/r300_state.c @@ -922,7 +922,6 @@ static void* r300_create_rs_state(struct pipe_context* pipe, const struct pipe_rasterizer_state* state) { struct r300_rs_state* rs = CALLOC_STRUCT(r300_rs_state); - int i; float psiz; uint32_t vap_control_status; /* R300_VAP_CNTL_STATUS: 0x2140 */ uint32_t point_size; /* R300_GA_POINT_SIZE: 0x421c */ @@ -935,10 +934,6 @@ static void* r300_create_rs_state(struct pipe_context* pipe, uint32_t polygon_mode; /* R300_GA_POLY_MODE: 0x4288 */ uint32_t clip_rule; /* R300_SC_CLIP_RULE: 0x43D0 */ - /* Specifies top of Raster pipe specific enable controls, - * i.e. texture coordinates stuffing for points, lines, triangles */ - uint32_t stuffing_enable; /* R300_GB_ENABLE: 0x4008 */ - /* Point sprites texture coordinates, 0: lower left, 1: upper right */ float point_texcoord_left = 0; /* R300_GA_POINT_S0: 0x4200 */ float point_texcoord_bottom = 0;/* R300_GA_POINT_T0: 0x4204 */ @@ -950,10 +945,8 @@ static void* r300_create_rs_state(struct pipe_context* pipe, rs->rs = *state; rs->rs_draw = *state; - /* Generate point sprite texture coordinates in GENERIC0 - * if point_quad_rasterization is TRUE. */ rs->rs.sprite_coord_enable = state->point_quad_rasterization * - (state->sprite_coord_enable | 1); + state->sprite_coord_enable; /* Override some states for Draw. */ rs->rs_draw.sprite_coord_enable = 0; /* We can do this in HW. */ @@ -1054,16 +1047,8 @@ static void* r300_create_rs_state(struct pipe_context* pipe, clip_rule = state->scissor ? 0xAAAA : 0xFFFF; - /* Point sprites */ - stuffing_enable = 0; + /* Point sprites coord mode */ if (rs->rs.sprite_coord_enable) { - stuffing_enable = R300_GB_POINT_STUFF_ENABLE; - for (i = 0; i < 8; i++) { - if (rs->rs.sprite_coord_enable & (1 << i)) - stuffing_enable |= - R300_GB_TEX_ST << (R300_GB_TEX0_SOURCE_SHIFT + (i*2)); - } - switch (state->sprite_coord_mode) { case PIPE_SPRITE_COORD_UPPER_LEFT: point_texcoord_top = 0.0f; @@ -1077,7 +1062,7 @@ static void* r300_create_rs_state(struct pipe_context* pipe, } /* Build the main command buffer. */ - BEGIN_CB(rs->cb_main, 25); + BEGIN_CB(rs->cb_main, RS_STATE_MAIN_SIZE); OUT_CB_REG(R300_VAP_CNTL_STATUS, vap_control_status); OUT_CB_REG(R300_GA_POINT_SIZE, point_size); OUT_CB_REG_SEQ(R300_GA_POINT_MINMAX, 2); @@ -1091,7 +1076,6 @@ static void* r300_create_rs_state(struct pipe_context* pipe, OUT_CB_REG(R300_GA_LINE_STIPPLE_VALUE, line_stipple_value); OUT_CB_REG(R300_GA_POLY_MODE, polygon_mode); OUT_CB_REG(R300_SC_CLIP_RULE, clip_rule); - OUT_CB_REG(R300_GB_ENABLE, stuffing_enable); OUT_CB_REG_SEQ(R300_GA_POINT_S0, 4); OUT_CB_32F(point_texcoord_left); OUT_CB_32F(point_texcoord_bottom); @@ -1149,7 +1133,7 @@ static void r300_bind_rs_state(struct pipe_context* pipe, void* state) } UPDATE_STATE(state, r300->rs_state); - r300->rs_state.size = 25 + (r300->polygon_offset_enabled ? 5 : 0); + r300->rs_state.size = RS_STATE_MAIN_SIZE + (r300->polygon_offset_enabled ? 5 : 0); if (last_sprite_coord_enable != r300->sprite_coord_enable || last_two_sided_color != r300->two_sided_color) { @@ -1171,7 +1155,6 @@ static void* struct r300_sampler_state* sampler = CALLOC_STRUCT(r300_sampler_state); boolean is_r500 = r300->screen->caps.is_r500; int lod_bias; - union util_color uc; sampler->state = *state; @@ -1228,9 +1211,6 @@ static void* sampler->filter1 |= r500_anisotropy(state->max_anisotropy); } - util_pack_color(state->border_color, PIPE_FORMAT_B8G8R8A8_UNORM, &uc); - sampler->border_color = uc.ui; - /* R500-specific fixups and optimizations */ if (r300->screen->caps.is_r500) { sampler->filter1 |= R500_BORDER_FIX; diff --git a/src/gallium/drivers/r300/r300_state_derived.c b/src/gallium/drivers/r300/r300_state_derived.c index f9a516825df..904736ef06d 100644 --- a/src/gallium/drivers/r300/r300_state_derived.c +++ b/src/gallium/drivers/r300/r300_state_derived.c @@ -324,6 +324,7 @@ static void r300_update_rs_block(struct r300_context *r300) boolean any_bcolor_used = vs_outputs->bcolor[0] != ATTR_UNUSED || vs_outputs->bcolor[1] != ATTR_UNUSED; int *stream_loc_notcl = r300->stream_loc_notcl; + uint32_t stuffing_enable = 0; if (r300->screen->caps.is_r500) { rX00_rs_col = r500_rs_col; @@ -436,7 +437,11 @@ static void r300_update_rs_block(struct r300_context *r300) /* Rasterize texture coordinates. */ for (i = 0; i < ATTR_GENERIC_COUNT && tex_count < 8; i++) { - bool sprite_coord = !!(r300->sprite_coord_enable & (1 << i)); + bool sprite_coord = false; + + if (fs_inputs->generic[i] != ATTR_UNUSED) { + sprite_coord = !!(r300->sprite_coord_enable & (1 << i)); + } if (vs_outputs->generic[i] != ATTR_UNUSED || sprite_coord) { if (!sprite_coord) { @@ -444,7 +449,9 @@ static void r300_update_rs_block(struct r300_context *r300) rs.vap_vsm_vtx_assm |= (R300_INPUT_CNTL_TC0 << tex_count); rs.vap_out_vtx_fmt[1] |= (4 << (3 * tex_count)); stream_loc_notcl[loc++] = 6 + tex_count; - } + } else + stuffing_enable |= + R300_GB_TEX_ST << (R300_GB_TEX0_SOURCE_SHIFT + (tex_count*2)); /* Rasterize it. */ rX00_rs_tex(&rs, tex_count, tex_ptr, @@ -456,8 +463,8 @@ static void r300_update_rs_block(struct r300_context *r300) fp_offset++; DBG(r300, DBG_RS, - "r300: Rasterized generic %i written to FS%s.\n", - i, sprite_coord ? " (sprite coord)" : ""); + "r300: Rasterized generic %i written to FS%s in texcoord %d.\n", + i, sprite_coord ? " (sprite coord)" : "", tex_count); } else { DBG(r300, DBG_RS, "r300: Rasterized generic %i unused%s.\n", @@ -560,13 +567,72 @@ static void r300_update_rs_block(struct r300_context *r300) count = MAX3(col_count, tex_count, 1); rs.inst_count = count - 1; + /* set the GB enable flags */ + if (r300->sprite_coord_enable) + stuffing_enable |= R300_GB_POINT_STUFF_ENABLE; + + rs.gb_enable = stuffing_enable; + /* Now, after all that, see if we actually need to update the state. */ if (memcmp(r300->rs_block_state.state, &rs, sizeof(struct r300_rs_block))) { memcpy(r300->rs_block_state.state, &rs, sizeof(struct r300_rs_block)); - r300->rs_block_state.size = 11 + count*2; + r300->rs_block_state.size = 13 + count*2; } } +static uint32_t r300_get_border_color(enum pipe_format format, + const float border[4]) +{ + const struct util_format_description *desc; + float border_swizzled[4] = { + border[2], + border[1], + border[0], + border[3] + }; + uint32_t r; + + desc = util_format_description(format); + + /* We don't use util_pack_format because it does not handle the formats + * we want, e.g. R4G4B4A4 is non-existent in Gallium. */ + switch (desc->channel[0].size) { + case 4: + r = ((float_to_ubyte(border_swizzled[0]) & 0xf0) >> 4) | + ((float_to_ubyte(border_swizzled[1]) & 0xf0) << 0) | + ((float_to_ubyte(border_swizzled[2]) & 0xf0) << 4) | + ((float_to_ubyte(border_swizzled[3]) & 0xf0) << 8); + break; + + case 5: + if (desc->channel[1].size == 5) { + r = ((float_to_ubyte(border_swizzled[0]) & 0xf8) >> 3) | + ((float_to_ubyte(border_swizzled[1]) & 0xf8) << 2) | + ((float_to_ubyte(border_swizzled[2]) & 0xf8) << 7) | + ((float_to_ubyte(border_swizzled[3]) & 0x80) << 8); + } else if (desc->channel[1].size == 6) { + r = ((float_to_ubyte(border_swizzled[0]) & 0xf8) >> 3) | + ((float_to_ubyte(border_swizzled[1]) & 0xfc) << 3) | + ((float_to_ubyte(border_swizzled[2]) & 0xf8) << 8); + } else { + assert(0); + r = 0; + } + break; + + default: + /* I think the fat formats (16, 32) are specified + * as the 8-bit ones. I am not sure how compressed formats + * work here. */ + r = ((float_to_ubyte(border_swizzled[0]) & 0xff) << 0) | + ((float_to_ubyte(border_swizzled[1]) & 0xff) << 8) | + ((float_to_ubyte(border_swizzled[2]) & 0xff) << 16) | + ((float_to_ubyte(border_swizzled[3]) & 0xff) << 24); + } + + return r; +} + static void r300_merge_textures_and_samplers(struct r300_context* r300) { struct r300_textures_state *state = @@ -599,7 +665,11 @@ static void r300_merge_textures_and_samplers(struct r300_context* r300) texstate->format = view->format; texstate->filter0 = sampler->filter0; texstate->filter1 = sampler->filter1; - texstate->border_color = sampler->border_color; + + /* Set the border color. */ + texstate->border_color = + r300_get_border_color(view->base.format, + sampler->state.border_color); /* determine min/max levels */ max_level = MIN3(sampler->max_lod + view->base.first_level, diff --git a/src/gallium/drivers/r300/r300_state_inlines.h b/src/gallium/drivers/r300/r300_state_inlines.h index 03ec127ff79..7e501221b1f 100644 --- a/src/gallium/drivers/r300/r300_state_inlines.h +++ b/src/gallium/drivers/r300/r300_state_inlines.h @@ -364,6 +364,7 @@ static INLINE uint16_t r300_translate_vertex_data_type(enum pipe_format format) { uint32_t result = 0; const struct util_format_description *desc; + unsigned i; desc = util_format_description(format); @@ -371,10 +372,17 @@ r300_translate_vertex_data_type(enum pipe_format format) { return R300_INVALID_FORMAT; } - switch (desc->channel[0].type) { + /* Find the first non-VOID channel. */ + for (i = 0; i < 4; i++) { + if (desc->channel[i].type != UTIL_FORMAT_TYPE_VOID) { + break; + } + } + + switch (desc->channel[i].type) { /* Half-floats, floats, doubles */ case UTIL_FORMAT_TYPE_FLOAT: - switch (desc->channel[0].size) { + switch (desc->channel[i].size) { case 16: /* Supported only on RV350 and later. */ if (desc->nr_channels > 2) { @@ -394,7 +402,7 @@ r300_translate_vertex_data_type(enum pipe_format format) { case UTIL_FORMAT_TYPE_UNSIGNED: /* Signed ints */ case UTIL_FORMAT_TYPE_SIGNED: - switch (desc->channel[0].size) { + switch (desc->channel[i].size) { case 8: result = R300_DATA_TYPE_BYTE; break; @@ -413,10 +421,10 @@ r300_translate_vertex_data_type(enum pipe_format format) { return R300_INVALID_FORMAT; } - if (desc->channel[0].type == UTIL_FORMAT_TYPE_SIGNED) { + if (desc->channel[i].type == UTIL_FORMAT_TYPE_SIGNED) { result |= R300_SIGNED; } - if (desc->channel[0].normalized) { + if (desc->channel[i].normalized) { result |= R300_NORMALIZE; } diff --git a/src/gallium/drivers/r300/r300_texture.c b/src/gallium/drivers/r300/r300_texture.c index 34105aa4bcd..cee56bccdcd 100644 --- a/src/gallium/drivers/r300/r300_texture.c +++ b/src/gallium/drivers/r300/r300_texture.c @@ -260,16 +260,26 @@ uint32_t r300_translate_texformat(enum pipe_format format, return ~0; /* Unsupported/unknown. */ } + /* Find the first non-VOID channel. */ + for (i = 0; i < 4; i++) { + if (desc->channel[i].type != UTIL_FORMAT_TYPE_VOID) { + break; + } + } + + if (i == 4) + return ~0; /* Unsupported/unknown. */ + /* And finally, uniform formats. */ - switch (desc->channel[0].type) { + switch (desc->channel[i].type) { case UTIL_FORMAT_TYPE_UNSIGNED: case UTIL_FORMAT_TYPE_SIGNED: - if (!desc->channel[0].normalized && + if (!desc->channel[i].normalized && desc->colorspace != UTIL_FORMAT_COLORSPACE_SRGB) { return ~0; } - switch (desc->channel[0].size) { + switch (desc->channel[i].size) { case 4: switch (desc->nr_channels) { case 2: @@ -303,7 +313,7 @@ uint32_t r300_translate_texformat(enum pipe_format format, return ~0; case UTIL_FORMAT_TYPE_FLOAT: - switch (desc->channel[0].size) { + switch (desc->channel[i].size) { case 16: switch (desc->nr_channels) { case 1: @@ -359,6 +369,11 @@ static uint32_t r300_translate_colorformat(enum pipe_format format) return R300_COLOR_FORMAT_I8; /* 16-bit buffers. */ + case PIPE_FORMAT_L8A8_UNORM: + case PIPE_FORMAT_R8G8_UNORM: + case PIPE_FORMAT_R8G8_SNORM: + return R300_COLOR_FORMAT_UV88; + case PIPE_FORMAT_B5G6R5_UNORM: return R300_COLOR_FORMAT_RGB565; @@ -443,15 +458,25 @@ static uint32_t r300_translate_out_fmt(enum pipe_format format) desc = util_format_description(format); + /* Find the first non-VOID channel. */ + for (i = 0; i < 4; i++) { + if (desc->channel[i].type != UTIL_FORMAT_TYPE_VOID) { + break; + } + } + + if (i == 4) + return ~0; /* Unsupported/unknown. */ + /* Specifies how the shader output is written to the fog unit. */ - if (desc->channel[0].type == UTIL_FORMAT_TYPE_FLOAT) { - if (desc->channel[0].size == 32) { + if (desc->channel[i].type == UTIL_FORMAT_TYPE_FLOAT) { + if (desc->channel[i].size == 32) { modifier |= R300_US_OUT_FMT_C4_32_FP; } else { modifier |= R300_US_OUT_FMT_C4_16_FP; } } else { - if (desc->channel[0].size == 16) { + if (desc->channel[i].size == 16) { modifier |= R300_US_OUT_FMT_C4_16; } else { /* C4_8 seems to be used for the formats whose pixel size @@ -468,7 +493,7 @@ static uint32_t r300_translate_out_fmt(enum pipe_format format) /* Add swizzles and return. */ switch (format) { - /* 8-bit outputs. + /* 8-bit outputs, one channel. * COLORFORMAT_I8 stores the C2 component. */ case PIPE_FORMAT_A8_UNORM: return modifier | R300_C2_SEL_A; @@ -478,6 +503,14 @@ static uint32_t r300_translate_out_fmt(enum pipe_format format) case PIPE_FORMAT_R8_SNORM: return modifier | R300_C2_SEL_R; + /* 16-bit outputs, two channels. + * COLORFORMAT_UV88 stores C2 and C0. */ + case PIPE_FORMAT_L8A8_UNORM: + return modifier | R300_C0_SEL_A | R300_C2_SEL_R; + case PIPE_FORMAT_R8G8_UNORM: + case PIPE_FORMAT_R8G8_SNORM: + return modifier | R300_C0_SEL_G | R300_C2_SEL_R; + /* BGRA outputs. */ case PIPE_FORMAT_B5G6R5_UNORM: case PIPE_FORMAT_B5G5R5A1_UNORM: @@ -556,18 +589,15 @@ void r300_texture_setup_format_state(struct r300_screen *screen, out->tile_config = 0; /* Set sampler state. */ - out->format0 = R300_TX_WIDTH((u_minify(pt->width0, level) - 1) & 0x7ff) | - R300_TX_HEIGHT((u_minify(pt->height0, level) - 1) & 0x7ff); + out->format0 = + R300_TX_WIDTH((u_minify(desc->width0, level) - 1) & 0x7ff) | + R300_TX_HEIGHT((u_minify(desc->height0, level) - 1) & 0x7ff) | + R300_TX_DEPTH(util_logbase2(u_minify(desc->depth0, level)) & 0xf); if (desc->uses_stride_addressing) { /* rectangles love this */ out->format0 |= R300_TX_PITCH_EN; out->format2 = (desc->stride_in_pixels[level] - 1) & 0x1fff; - } else { - /* Power of two textures (3D, mipmaps, and no pitch), - * also NPOT textures with a width being POT. */ - out->format0 |= - R300_TX_DEPTH(util_logbase2(u_minify(pt->depth0, level)) & 0xf); } if (pt->target == PIPE_TEXTURE_CUBE) { @@ -580,10 +610,10 @@ void r300_texture_setup_format_state(struct r300_screen *screen, /* large textures on r500 */ if (is_r500) { - if (pt->width0 > 2048) { + if (desc->width0 > 2048) { out->format2 |= R500_TXWIDTH_BIT11; } - if (pt->height0 > 2048) { + if (desc->height0 > 2048) { out->format2 |= R500_TXHEIGHT_BIT11; } } diff --git a/src/gallium/drivers/r300/r300_texture_desc.c b/src/gallium/drivers/r300/r300_texture_desc.c index 112282a0a6a..543d0fdc15b 100644 --- a/src/gallium/drivers/r300/r300_texture_desc.c +++ b/src/gallium/drivers/r300/r300_texture_desc.c @@ -44,7 +44,7 @@ unsigned r300_get_pixel_alignment(enum pipe_format format, {{ 32, 1}, { 8, 4}, { 0, 0}}, /* 8 bits per pixel */ {{ 16, 1}, { 8, 2}, { 4, 4}}, /* 16 bits per pixel */ {{ 8, 1}, { 4, 2}, { 0, 0}}, /* 32 bits per pixel */ - {{ 4, 1}, { 0, 0}, { 2, 2}}, /* 64 bits per pixel */ + {{ 4, 1}, { 2, 2}, { 0, 0}}, /* 64 bits per pixel */ {{ 2, 1}, { 0, 0}, { 0, 0}} /* 128 bits per pixel */ }, { @@ -53,7 +53,7 @@ unsigned r300_get_pixel_alignment(enum pipe_format format, {{256, 8}, {64, 32}, { 0, 0}}, /* 8 bits per pixel */ {{128, 8}, {64, 16}, {32, 32}}, /* 16 bits per pixel */ {{ 64, 8}, {32, 16}, { 0, 0}}, /* 32 bits per pixel */ - {{ 32, 8}, { 0, 0}, {16, 16}}, /* 64 bits per pixel */ + {{ 32, 8}, {16, 16}, { 0, 0}}, /* 64 bits per pixel */ {{ 16, 8}, { 0, 0}, { 0, 0}} /* 128 bits per pixel */ } }; @@ -91,9 +91,9 @@ static boolean r300_texture_macro_switch(struct r300_texture_desc *desc, tile = r300_get_pixel_alignment(desc->b.b.format, desc->b.b.nr_samples, desc->microtile, R300_BUFFER_TILED, dim); if (dim == DIM_WIDTH) { - texdim = u_minify(desc->b.b.width0, level); + texdim = u_minify(desc->width0, level); } else { - texdim = u_minify(desc->b.b.height0, level); + texdim = u_minify(desc->height0, level); } /* See TX_FILTER1_n.MACRO_SWITCH. */ @@ -124,7 +124,7 @@ static unsigned r300_texture_get_stride(struct r300_screen *screen, return 0; } - width = u_minify(desc->b.b.width0, level); + width = u_minify(desc->width0, level); if (util_format_is_plain(desc->b.b.format)) { tile_width = r300_get_pixel_alignment(desc->b.b.format, @@ -172,7 +172,7 @@ static unsigned r300_texture_get_nblocksy(struct r300_texture_desc *desc, { unsigned height, tile_height; - height = u_minify(desc->b.b.height0, level); + height = u_minify(desc->height0, level); if (util_format_is_plain(desc->b.b.format)) { tile_height = r300_get_pixel_alignment(desc->b.b.format, @@ -237,7 +237,7 @@ static void r300_texture_3d_fix_mipmapping(struct r300_screen *screen, r300_texture_get_nblocksy(desc, i, FALSE); } - size *= desc->b.b.depth0; + size *= desc->depth0; desc->size_in_bytes = size; } } @@ -256,7 +256,7 @@ static void r300_setup_miptree(struct r300_screen *screen, { struct pipe_resource *base = &desc->b.b; unsigned stride, size, layer_size, nblocksy, i; - boolean rv350_mode = screen->caps.is_rv350; + boolean rv350_mode = screen->caps.family >= CHIP_FAMILY_R350; boolean aligned_for_cbzb; desc->size_in_bytes = 0; @@ -292,7 +292,7 @@ static void r300_setup_miptree(struct r300_screen *screen, if (base->target == PIPE_TEXTURE_CUBE) size = layer_size * 6; else - size = layer_size * u_minify(base->depth0, i); + size = layer_size * u_minify(desc->depth0, i); desc->offset_in_bytes[i] = desc->size_in_bytes; desc->size_in_bytes = desc->offset_in_bytes[i] + size; @@ -303,8 +303,8 @@ static void r300_setup_miptree(struct r300_screen *screen, SCREEN_DBG(screen, DBG_TEXALLOC, "r300: Texture miptree: Level %d " "(%dx%dx%d px, pitch %d bytes) %d bytes total, macrotiled %s\n", - i, u_minify(base->width0, i), u_minify(base->height0, i), - u_minify(base->depth0, i), stride, desc->size_in_bytes, + i, u_minify(desc->width0, i), u_minify(desc->height0, i), + u_minify(desc->depth0, i), stride, desc->size_in_bytes, desc->macrotile[i] ? "TRUE" : "FALSE"); } } @@ -313,14 +313,14 @@ static void r300_setup_flags(struct r300_texture_desc *desc) { desc->uses_stride_addressing = !util_is_power_of_two(desc->b.b.width0) || - !util_is_power_of_two(desc->b.b.height0) || (desc->stride_in_bytes_override && stride_to_width(desc->b.b.format, desc->stride_in_bytes_override) != desc->b.b.width0); desc->is_npot = desc->uses_stride_addressing || - !util_is_power_of_two(desc->b.b.height0); + !util_is_power_of_two(desc->b.b.height0) || + !util_is_power_of_two(desc->b.b.depth0); } static void r300_setup_cbzb_flags(struct r300_screen *rscreen, @@ -351,7 +351,7 @@ static void r300_setup_tiling(struct r300_screen *screen, { struct r300_winsys_screen *rws = screen->rws; enum pipe_format format = desc->b.b.format; - boolean rv350_mode = screen->caps.is_rv350; + boolean rv350_mode = screen->caps.family >= CHIP_FAMILY_R350; boolean is_zb = util_format_is_depth_or_stencil(format); boolean dbg_no_tiling = SCREEN_DBG_ON(screen, DBG_NO_TILING); @@ -368,11 +368,11 @@ static void r300_setup_tiling(struct r300_screen *screen, switch (util_format_get_blocksize(format)) { case 1: case 4: + case 8: desc->microtile = R300_BUFFER_TILED; break; case 2: - case 8: if (rws->get_value(rws, R300_VID_SQUARE_TILING_SUPPORT)) { desc->microtile = R300_BUFFER_SQUARETILED; } @@ -416,9 +416,21 @@ boolean r300_texture_desc_init(struct r300_screen *rscreen, { desc->b.b = *base; desc->b.b.screen = &rscreen->screen; - desc->stride_in_bytes_override = stride_in_bytes_override; + desc->width0 = base->width0; + desc->height0 = base->height0; + desc->depth0 = base->depth0; + r300_setup_flags(desc); + + /* Align a 3D NPOT texture to POT. */ + if (base->target == PIPE_TEXTURE_3D && desc->is_npot) { + desc->width0 = util_next_power_of_two(desc->width0); + desc->height0 = util_next_power_of_two(desc->height0); + desc->depth0 = util_next_power_of_two(desc->depth0); + } + + /* Setup tiling. */ if (microtile == R300_BUFFER_SELECT_LAYOUT || macrotile == R300_BUFFER_SELECT_LAYOUT) { r300_setup_tiling(rscreen, desc); @@ -428,7 +440,6 @@ boolean r300_texture_desc_init(struct r300_screen *rscreen, assert(desc->b.b.last_level == 0); } - r300_setup_flags(desc); r300_setup_cbzb_flags(rscreen, desc); /* Setup the miptree description. */ @@ -444,10 +455,10 @@ boolean r300_texture_desc_init(struct r300_screen *rscreen, if (max_buffer_size) { /* Make sure the buffer we got is large enough. */ if (desc->size_in_bytes > max_buffer_size) { - fprintf(stderr, "r300: texture_from_handle: The buffer is not " + fprintf(stderr, "r300: texture_desc_init: The buffer is not " "large enough. Got: %i, Need: %i, Info:\n", max_buffer_size, desc->size_in_bytes); - r300_tex_print_info(rscreen, desc, "texture_from_handle"); + r300_tex_print_info(rscreen, desc, "texture_desc_init"); return FALSE; } @@ -457,7 +468,7 @@ boolean r300_texture_desc_init(struct r300_screen *rscreen, } if (SCREEN_DBG_ON(rscreen, DBG_TEX)) - r300_tex_print_info(rscreen, desc, "texture_from_handle"); + r300_tex_print_info(rscreen, desc, "texture_desc_init"); return TRUE; } |