diff --git a/src/gallium/drivers/r300/r300_context.h b/src/gallium/drivers/r300/r300_context.h index 32b71eda4ee..d88ba3f7ed7 100644 --- a/src/gallium/drivers/r300/r300_context.h +++ b/src/gallium/drivers/r300/r300_context.h @@ -578,6 +578,7 @@ struct r300_context { int sprite_coord_enable; /* Whether two-sided color selection is enabled (AKA light_twoside). */ boolean two_sided_color; + boolean flatshade; /* Whether fast color clear is enabled. */ boolean cbzb_clear; /* Whether fragment shader needs to be validated. */ diff --git a/src/gallium/drivers/r300/r300_screen.c b/src/gallium/drivers/r300/r300_screen.c index 01f782c4a27..ebc8a2e958d 100644 --- a/src/gallium/drivers/r300/r300_screen.c +++ b/src/gallium/drivers/r300/r300_screen.c @@ -103,7 +103,6 @@ static int r300_get_param(struct pipe_screen* pscreen, enum pipe_cap param) case PIPE_CAP_TEXTURE_BARRIER: case PIPE_CAP_TGSI_CAN_COMPACT_VARYINGS: case PIPE_CAP_TGSI_CAN_COMPACT_CONSTANTS: - case PIPE_CAP_VERTEX_COLOR_CLAMPED: case PIPE_CAP_USER_INDEX_BUFFERS: case PIPE_CAP_USER_CONSTANT_BUFFERS: case PIPE_CAP_DEPTH_CLIP_DISABLE: /* XXX implemented, but breaks Regnum Online */ @@ -122,6 +121,11 @@ static int r300_get_param(struct pipe_screen* pscreen, enum pipe_cap param) case PIPE_CAP_TEXTURE_SWIZZLE: return util_format_s3tc_enabled ? r300screen->caps.dxtc_swizzle : 1; + /* We don't support color clamping on r500, so that we can use color + * intepolators for generic varyings. */ + case PIPE_CAP_VERTEX_COLOR_CLAMPED: + return !is_r500; + /* Supported on r500 only. */ case PIPE_CAP_VERTEX_COLOR_UNCLAMPED: case PIPE_CAP_MIXED_COLORBUFFER_FORMATS: diff --git a/src/gallium/drivers/r300/r300_shader_semantics.h b/src/gallium/drivers/r300/r300_shader_semantics.h index 4be23e64ce7..b756048c6c7 100644 --- a/src/gallium/drivers/r300/r300_shader_semantics.h +++ b/src/gallium/drivers/r300/r300_shader_semantics.h @@ -42,6 +42,8 @@ struct r300_shader_semantics { int generic[ATTR_GENERIC_COUNT]; int fog; int wpos; + + int num_generic; }; static INLINE void r300_shader_semantics_reset( @@ -63,6 +65,8 @@ static INLINE void r300_shader_semantics_reset( for (i = 0; i < ATTR_GENERIC_COUNT; i++) { info->generic[i] = ATTR_UNUSED; } + + info->num_generic = 0; } #endif diff --git a/src/gallium/drivers/r300/r300_state.c b/src/gallium/drivers/r300/r300_state.c index 15ce3e00c07..19c7d4eb322 100644 --- a/src/gallium/drivers/r300/r300_state.c +++ b/src/gallium/drivers/r300/r300_state.c @@ -1181,8 +1181,7 @@ static void* r300_create_rs_state(struct pipe_context* pipe, float point_texcoord_bottom = 0;/* R300_GA_POINT_T0: 0x4204 */ float point_texcoord_right = 1; /* R300_GA_POINT_S1: 0x4208 */ float point_texcoord_top = 0; /* R300_GA_POINT_T1: 0x420c */ - boolean vclamp = state->clamp_vertex_color || - !r300_context(pipe)->screen->caps.is_r500; + boolean vclamp = !r300_context(pipe)->screen->caps.is_r500; CB_LOCALS; /* Copy rasterizer state. */ @@ -1384,6 +1383,7 @@ static void r300_bind_rs_state(struct pipe_context* pipe, void* state) int last_sprite_coord_enable = r300->sprite_coord_enable; boolean last_two_sided_color = r300->two_sided_color; boolean last_msaa_enable = r300->msaa_enable; + boolean last_flatshade = r300->flatshade; if (r300->draw && rs) { draw_set_rasterizer_state(r300->draw, &rs->rs_draw, state); @@ -1394,18 +1394,21 @@ static void r300_bind_rs_state(struct pipe_context* pipe, void* state) r300->sprite_coord_enable = rs->rs.sprite_coord_enable; r300->two_sided_color = rs->rs.light_twoside; r300->msaa_enable = rs->rs.multisample; + r300->flatshade = rs->rs.flatshade; } else { r300->polygon_offset_enabled = FALSE; r300->sprite_coord_enable = 0; r300->two_sided_color = FALSE; r300->msaa_enable = FALSE; + r300->flatshade = FALSE; } UPDATE_STATE(state, r300->rs_state); 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) { + last_two_sided_color != r300->two_sided_color || + last_flatshade != r300->flatshade) { r300_mark_atom_dirty(r300, &r300->rs_block_state); } diff --git a/src/gallium/drivers/r300/r300_state_derived.c b/src/gallium/drivers/r300/r300_state_derived.c index 3ccf396b741..1013557bde9 100644 --- a/src/gallium/drivers/r300/r300_state_derived.c +++ b/src/gallium/drivers/r300/r300_state_derived.c @@ -316,6 +316,7 @@ static void r300_update_rs_block(struct r300_context *r300) struct r300_shader_semantics *fs_inputs = &r300_fs(r300)->shader->inputs; struct r300_rs_block rs = {0}; int i, col_count = 0, tex_count = 0, fp_offset = 0, count, loc = 0, tex_ptr = 0; + int gen_offset = 0; void (*rX00_rs_col)(struct r300_rs_block*, int, int, enum r300_rs_swizzle); void (*rX00_rs_col_write)(struct r300_rs_block*, int, int, enum r300_rs_col_write_type); void (*rX00_rs_tex)(struct r300_rs_block*, int, int, enum r300_rs_swizzle); @@ -436,8 +437,60 @@ static void r300_update_rs_block(struct r300_context *r300) fprintf(stderr, "r300: ERROR: FS input FACE unassigned.\n"); } + /* Re-use color varyings for texcoords if possible. + * + * The colors are interpolated as 20-bit floats (reduced precision), + * Use this hack only if there are too many generic varyings. + * (number of generic varyings + fog + wpos > 8) */ + if (r300->screen->caps.is_r500 && !any_bcolor_used && !r300->flatshade && + fs_inputs->face == ATTR_UNUSED && + vs_outputs->num_generic + (vs_outputs->fog != ATTR_UNUSED) + + (fs_inputs->wpos != ATTR_UNUSED) > 8) { + for (i = 0; i < ATTR_GENERIC_COUNT && col_count < 2; i++) { + /* Cannot use color varyings for sprite coords. */ + if (fs_inputs->generic[i] != ATTR_UNUSED && + (r300->sprite_coord_enable & (1 << i))) { + break; + } + + if (vs_outputs->generic[i] != ATTR_UNUSED) { + /* Set up the color in VAP. */ + rs.vap_vsm_vtx_assm |= R300_INPUT_CNTL_COLOR; + rs.vap_out_vtx_fmt[0] |= + R300_VAP_OUTPUT_VTX_FMT_0__COLOR_0_PRESENT << col_count; + stream_loc_notcl[loc++] = 2 + col_count; + + /* Rasterize it. */ + rX00_rs_col(&rs, col_count, col_count, SWIZ_XYZW); + + /* Write it to the FS input register if it's needed by the FS. */ + if (fs_inputs->generic[i] != ATTR_UNUSED) { + rX00_rs_col_write(&rs, col_count, fp_offset, WRITE_COLOR); + fp_offset++; + + DBG(r300, DBG_RS, + "r300: Rasterized generic %i redirected to color %i and written to FS.\n", + i, col_count); + } else { + DBG(r300, DBG_RS, "r300: Rasterized generic %i redirected to color %i unused.\n", + i, col_count); + } + col_count++; + } else { + /* Skip the FS input register, leave it uninitialized. */ + /* If we try to set it to (0,0,0,1), it will lock up. */ + if (fs_inputs->generic[i] != ATTR_UNUSED) { + fp_offset++; + + DBG(r300, DBG_RS, "r300: FS input generic %i unassigned%s.\n", i); + } + } + } + gen_offset = i; + } + /* Rasterize texture coordinates. */ - for (i = 0; i < ATTR_GENERIC_COUNT && tex_count < 8; i++) { + for (i = gen_offset; i < ATTR_GENERIC_COUNT && tex_count < 8; i++) { boolean sprite_coord = false; if (fs_inputs->generic[i] != ATTR_UNUSED) { diff --git a/src/gallium/drivers/r300/r300_vs.c b/src/gallium/drivers/r300/r300_vs.c index ea0621e2d3e..33612a322f7 100644 --- a/src/gallium/drivers/r300/r300_vs.c +++ b/src/gallium/drivers/r300/r300_vs.c @@ -72,6 +72,7 @@ static void r300_shader_read_vs_outputs( case TGSI_SEMANTIC_GENERIC: assert(index < ATTR_GENERIC_COUNT); vs_outputs->generic[index] = i; + vs_outputs->num_generic++; break; case TGSI_SEMANTIC_FOG: