diff options
Diffstat (limited to 'src/gallium/drivers/r300/r300_state_derived.c')
-rw-r--r-- | src/gallium/drivers/r300/r300_state_derived.c | 241 |
1 files changed, 114 insertions, 127 deletions
diff --git a/src/gallium/drivers/r300/r300_state_derived.c b/src/gallium/drivers/r300/r300_state_derived.c index 9c8e907fdf..46c192eae1 100644 --- a/src/gallium/drivers/r300/r300_state_derived.c +++ b/src/gallium/drivers/r300/r300_state_derived.c @@ -30,6 +30,7 @@ #include "r300_fs.h" #include "r300_screen.h" #include "r300_shader_semantics.h" +#include "r300_state.h" #include "r300_state_derived.h" #include "r300_state_inlines.h" #include "r300_vs.h" @@ -37,6 +38,12 @@ /* r300_state_derived: Various bits of state which are dependent upon * currently bound CSO data. */ +enum r300_rs_swizzle { + SWIZ_XYZW = 0, + SWIZ_X001, + SWIZ_XY01, +}; + static void r300_draw_emit_attrib(struct r300_context* r300, enum attrib_emit emit, enum interp_mode interp, @@ -83,8 +90,10 @@ static void r300_draw_emit_all_attribs(struct r300_context* r300) /* XXX Back-face colors. */ /* Texture coordinates. */ + /* Only 8 generic vertex attributes can be used. If there are more, + * they won't be rasterized. */ gen_count = 0; - for (i = 0; i < ATTR_GENERIC_COUNT; i++) { + for (i = 0; i < ATTR_GENERIC_COUNT && gen_count < 8; i++) { if (vs_outputs->generic[i] != ATTR_UNUSED) { r300_draw_emit_attrib(r300, EMIT_4F, INTERP_PERSPECTIVE, vs_outputs->generic[i]); @@ -93,84 +102,26 @@ static void r300_draw_emit_all_attribs(struct r300_context* r300) } /* Fog coordinates. */ - if (vs_outputs->fog != ATTR_UNUSED) { + if (gen_count < 8 && vs_outputs->fog != ATTR_UNUSED) { r300_draw_emit_attrib(r300, EMIT_4F, INTERP_PERSPECTIVE, vs_outputs->fog); gen_count++; } - - /* XXX magic */ - assert(gen_count <= 8); -} - -/* Update the PSC tables. */ -/* XXX move this function into r300_state.c after TCL-bypass gets removed - * XXX because this one is dependent only on vertex elements. */ -static void r300_vertex_psc(struct r300_context* r300) -{ - struct r300_vertex_shader* vs = r300->vs_state.state; - struct r300_vertex_stream_state *vformat = - (struct r300_vertex_stream_state*)r300->vertex_stream_state.state; - uint16_t type, swizzle; - enum pipe_format format; - unsigned i; - int identity[16] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15}; - int* stream_tab; - - memset(vformat, 0, sizeof(struct r300_vertex_stream_state)); - - stream_tab = identity; - - /* Vertex shaders have no semantics on their inputs, - * so PSC should just route stuff based on the vertex elements, - * and not on attrib information. */ - DBG(r300, DBG_DRAW, "r300: vs expects %d attribs, routing %d elements" - " in psc\n", - vs->info.num_inputs, - r300->vertex_element_count); - - for (i = 0; i < r300->vertex_element_count; i++) { - format = r300->vertex_element[i].src_format; - - type = r300_translate_vertex_data_type(format) | - (stream_tab[i] << R300_DST_VEC_LOC_SHIFT); - swizzle = r300_translate_vertex_data_swizzle(format); - - if (i & 1) { - vformat->vap_prog_stream_cntl[i >> 1] |= type << 16; - vformat->vap_prog_stream_cntl_ext[i >> 1] |= swizzle << 16; - } else { - vformat->vap_prog_stream_cntl[i >> 1] |= type; - vformat->vap_prog_stream_cntl_ext[i >> 1] |= swizzle; - } - } - - assert(i <= 15); - - /* Set the last vector in the PSC. */ - if (i) { - i -= 1; - } - vformat->vap_prog_stream_cntl[i >> 1] |= - (R300_LAST_VEC << (i & 1 ? 16 : 0)); - - vformat->count = (i >> 1) + 1; - r300->vertex_stream_state.size = (1 + vformat->count) * 2; } /* Update the PSC tables for SW TCL, using Draw. */ -static void r300_swtcl_vertex_psc(struct r300_context* r300) +static void r300_swtcl_vertex_psc(struct r300_context *r300) { + struct r300_vertex_stream_state *vstream = r300->vertex_stream_state.state; struct r300_vertex_shader* vs = r300->vs_state.state; - struct r300_vertex_stream_state *vformat = - (struct r300_vertex_stream_state*)r300->vertex_stream_state.state; struct vertex_info* vinfo = &r300->vertex_info; uint16_t type, swizzle; enum pipe_format format; unsigned i, attrib_count; int* vs_output_tab = vs->stream_loc_notcl; - memset(vformat, 0, sizeof(struct r300_vertex_stream_state)); + /* XXX hax */ + memset(vstream, 0, sizeof(struct r300_vertex_stream_state)); /* For each Draw attribute, route it to the fragment shader according * to the vs_output_tab. */ @@ -181,9 +132,7 @@ static void r300_swtcl_vertex_psc(struct r300_context* r300) " vs_output_tab %d\n", vinfo->attrib[i].src_index, vinfo->attrib[i].interp_mode, vinfo->attrib[i].emit, vs_output_tab[i]); - } - for (i = 0; i < attrib_count; i++) { /* Make sure we have a proper destination for our attribute. */ assert(vs_output_tab[i] != -1); @@ -199,11 +148,11 @@ static void r300_swtcl_vertex_psc(struct r300_context* r300) /* Add the attribute to the PSC table. */ if (i & 1) { - vformat->vap_prog_stream_cntl[i >> 1] |= type << 16; - vformat->vap_prog_stream_cntl_ext[i >> 1] |= swizzle << 16; + vstream->vap_prog_stream_cntl[i >> 1] |= type << 16; + vstream->vap_prog_stream_cntl_ext[i >> 1] |= swizzle << 16; } else { - vformat->vap_prog_stream_cntl[i >> 1] |= type; - vformat->vap_prog_stream_cntl_ext[i >> 1] |= swizzle; + vstream->vap_prog_stream_cntl[i >> 1] |= type; + vstream->vap_prog_stream_cntl_ext[i >> 1] |= swizzle; } } @@ -211,11 +160,12 @@ static void r300_swtcl_vertex_psc(struct r300_context* r300) if (i) { i -= 1; } - vformat->vap_prog_stream_cntl[i >> 1] |= + vstream->vap_prog_stream_cntl[i >> 1] |= (R300_LAST_VEC << (i & 1 ? 16 : 0)); - vformat->count = (i >> 1) + 1; - r300->vertex_stream_state.size = (1 + vformat->count) * 2; + vstream->count = (i >> 1) + 1; + r300->vertex_stream_state.dirty = TRUE; + r300->vertex_stream_state.size = (1 + vstream->count) * 2; } static void r300_rs_col(struct r300_rs_block* rs, int id, int ptr, @@ -237,14 +187,20 @@ static void r300_rs_col_write(struct r300_rs_block* rs, int id, int fp_offset) } static void r300_rs_tex(struct r300_rs_block* rs, int id, int ptr, - boolean swizzle_X001) + enum r300_rs_swizzle swiz) { - if (swizzle_X001) { + if (swiz == SWIZ_X001) { rs->ip[id] |= R300_RS_TEX_PTR(ptr*4) | R300_RS_SEL_S(R300_RS_SEL_C0) | R300_RS_SEL_T(R300_RS_SEL_K0) | R300_RS_SEL_R(R300_RS_SEL_K0) | R300_RS_SEL_Q(R300_RS_SEL_K1); + } else if (swiz == SWIZ_XY01) { + rs->ip[id] |= R300_RS_TEX_PTR(ptr*4) | + R300_RS_SEL_S(R300_RS_SEL_C0) | + R300_RS_SEL_T(R300_RS_SEL_C1) | + R300_RS_SEL_R(R300_RS_SEL_K0) | + R300_RS_SEL_Q(R300_RS_SEL_K1); } else { rs->ip[id] |= R300_RS_TEX_PTR(ptr*4) | R300_RS_SEL_S(R300_RS_SEL_C0) | @@ -280,15 +236,20 @@ static void r500_rs_col_write(struct r300_rs_block* rs, int id, int fp_offset) } static void r500_rs_tex(struct r300_rs_block* rs, int id, int ptr, - boolean swizzle_X001) + enum r300_rs_swizzle swiz) { int rs_tex_comp = ptr*4; - if (swizzle_X001) { + if (swiz == SWIZ_X001) { rs->ip[id] |= R500_RS_SEL_S(rs_tex_comp) | R500_RS_SEL_T(R500_RS_IP_PTR_K0) | R500_RS_SEL_R(R500_RS_IP_PTR_K0) | R500_RS_SEL_Q(R500_RS_IP_PTR_K1); + } else if (swiz == SWIZ_XY01) { + rs->ip[id] |= R500_RS_SEL_S(rs_tex_comp) | + R500_RS_SEL_T(rs_tex_comp + 1) | + R500_RS_SEL_R(R500_RS_IP_PTR_K0) | + R500_RS_SEL_Q(R500_RS_IP_PTR_K1); } else { rs->ip[id] |= R500_RS_SEL_S(rs_tex_comp) | R500_RS_SEL_T(rs_tex_comp + 1) | @@ -317,12 +278,12 @@ static void r300_update_rs_block(struct r300_context* r300, int i, col_count = 0, tex_count = 0, fp_offset = 0, count; void (*rX00_rs_col)(struct r300_rs_block*, int, int, boolean); void (*rX00_rs_col_write)(struct r300_rs_block*, int, int); - void (*rX00_rs_tex)(struct r300_rs_block*, int, int, boolean); + void (*rX00_rs_tex)(struct r300_rs_block*, int, int, enum r300_rs_swizzle); void (*rX00_rs_tex_write)(struct r300_rs_block*, int, int); boolean any_bcolor_used = vs_outputs->bcolor[0] != ATTR_UNUSED || vs_outputs->bcolor[1] != ATTR_UNUSED; - if (r300_screen(r300->context.screen)->caps->is_r500) { + if (r300->screen->caps.is_r500) { rX00_rs_col = r500_rs_col; rX00_rs_col_write = r500_rs_col_write; rX00_rs_tex = r500_rs_tex; @@ -359,14 +320,19 @@ static void r300_update_rs_block(struct r300_context* r300, /* Rasterize texture coordinates. */ for (i = 0; i < ATTR_GENERIC_COUNT; i++) { - if (vs_outputs->generic[i] != ATTR_UNUSED) { + bool sprite_coord = !!(r300->sprite_coord_enable & (1 << i)); + + if (vs_outputs->generic[i] != ATTR_UNUSED || sprite_coord) { /* Always rasterize if it's written by the VS, * otherwise it locks up. */ - rX00_rs_tex(&rs, tex_count, tex_count, FALSE); + rX00_rs_tex(&rs, tex_count, tex_count, + sprite_coord ? SWIZ_XY01 : SWIZ_XYZW); /* Write it to the FS input register if it's used by the FS. */ if (fs_inputs->generic[i] != ATTR_UNUSED) { rX00_rs_tex_write(&rs, tex_count, fp_offset); + if (sprite_coord) + debug_printf("r300: SpriteCoord (generic index %i) is being written to reg %i\n", i, fp_offset); fp_offset++; } tex_count++; @@ -383,7 +349,7 @@ static void r300_update_rs_block(struct r300_context* r300, if (vs_outputs->fog != ATTR_UNUSED) { /* Always rasterize if it's written by the VS, * otherwise it locks up. */ - rX00_rs_tex(&rs, tex_count, tex_count, TRUE); + rX00_rs_tex(&rs, tex_count, tex_count, SWIZ_X001); /* Write it to the FS input register if it's used by the FS. */ if (fs_inputs->fog != ATTR_UNUSED) { @@ -401,8 +367,8 @@ static void r300_update_rs_block(struct r300_context* r300, /* Rasterize WPOS. */ /* If the FS doesn't need it, it's not written by the VS. */ - if (fs_inputs->wpos != ATTR_UNUSED) { - rX00_rs_tex(&rs, tex_count, tex_count, FALSE); + if (vs_outputs->wpos != ATTR_UNUSED && fs_inputs->wpos != ATTR_UNUSED) { + rX00_rs_tex(&rs, tex_count, tex_count, SWIZ_XYZW); rX00_rs_tex_write(&rs, tex_count, fp_offset); fp_offset++; @@ -432,23 +398,8 @@ static void r300_update_rs_block(struct r300_context* r300, static void r300_update_derived_shader_state(struct r300_context* r300) { struct r300_vertex_shader* vs = r300->vs_state.state; - struct r300_screen* r300screen = r300_screen(r300->context.screen); - struct r300_vap_output_state *vap_out = - (struct r300_vap_output_state*)r300->vap_output_state.state; - /* XXX Mmm, delicious hax */ - memset(&r300->vertex_info, 0, sizeof(struct vertex_info)); - memcpy(vap_out, vs->hwfmt, sizeof(uint)*4); - - r300_update_rs_block(r300, &vs->outputs, &r300->fs->inputs); - - if (r300screen->caps->has_tcl) { - r300_vertex_psc(r300); - } else { - r300_draw_emit_all_attribs(r300); - draw_compute_vertex_size(&r300->vertex_info); - r300_swtcl_vertex_psc(r300); - } + r300_update_rs_block(r300, &vs->outputs, &r300_fs(r300)->shader->inputs); } static boolean r300_dsa_writes_depth_stencil(struct r300_dsa_state* dsa) @@ -508,12 +459,12 @@ static void r300_update_ztop(struct r300_context* r300) /* ZS writes */ if (r300_dsa_writes_depth_stencil(r300->dsa_state.state) && - (r300_dsa_alpha_test_enabled(r300->dsa_state.state) ||/* (1) */ - r300->fs->info.uses_kill)) { /* (2) */ + (r300_dsa_alpha_test_enabled(r300->dsa_state.state) || /* (1) */ + r300_fs(r300)->shader->info.uses_kill)) { /* (2) */ ztop_state->z_buffer_top = R300_ZTOP_DISABLE; - } else if (r300_fragment_shader_writes_depth(r300->fs)) { /* (5) */ + } else if (r300_fragment_shader_writes_depth(r300_fs(r300))) { /* (5) */ ztop_state->z_buffer_top = R300_ZTOP_DISABLE; - } else if (r300->query_current) { /* (6) */ + } else if (r300->query_current) { /* (6) */ ztop_state->z_buffer_top = R300_ZTOP_DISABLE; } else { ztop_state->z_buffer_top = R300_ZTOP_ENABLE; @@ -528,48 +479,71 @@ static void r300_merge_textures_and_samplers(struct r300_context* r300) (struct r300_textures_state*)r300->textures_state.state; struct r300_texture_sampler_state *texstate; struct r300_sampler_state *sampler; + struct r300_sampler_view *view; struct r300_texture *tex; unsigned min_level, max_level, i, size; - unsigned count = MIN2(state->texture_count, state->sampler_count); + unsigned count = MIN2(state->sampler_view_count, + state->sampler_state_count); state->tx_enable = 0; + state->count = 0; size = 2; for (i = 0; i < count; i++) { - if (state->textures[i] && state->sampler_states[i]) { + if (state->sampler_views[i] && state->sampler_states[i]) { state->tx_enable |= 1 << i; - tex = state->textures[i]; + view = state->sampler_views[i]; + tex = r300_texture(view->base.texture); sampler = state->sampler_states[i]; texstate = &state->regs[i]; - memcpy(texstate->format, &tex->state, sizeof(uint32_t)*3); - texstate->filter[0] = sampler->filter0; - texstate->filter[1] = sampler->filter1; + texstate->format = view->format; + texstate->filter0 = sampler->filter0; + texstate->filter1 = sampler->filter1; texstate->border_color = sampler->border_color; - texstate->tile_config = R300_TXO_MACRO_TILE(tex->macrotile) | - R300_TXO_MICRO_TILE(tex->microtile); /* to emulate 1D textures through 2D ones correctly */ - if (tex->tex.target == PIPE_TEXTURE_1D) { - texstate->filter[0] &= ~R300_TX_WRAP_T_MASK; - texstate->filter[0] |= R300_TX_WRAP_T(R300_TX_CLAMP_TO_EDGE); + if (tex->b.b.target == PIPE_TEXTURE_1D) { + texstate->filter0 &= ~R300_TX_WRAP_T_MASK; + texstate->filter0 |= R300_TX_WRAP_T(R300_TX_CLAMP_TO_EDGE); } - if (tex->is_npot) { + if (tex->uses_pitch) { /* NPOT textures don't support mip filter, unfortunately. * This prevents incorrect rendering. */ - texstate->filter[0] &= ~R300_TX_MIN_FILTER_MIP_MASK; + texstate->filter0 &= ~R300_TX_MIN_FILTER_MIP_MASK; + + /* Mask out the mirrored flag. */ + if (texstate->filter0 & R300_TX_WRAP_S(R300_TX_MIRRORED)) { + texstate->filter0 &= ~R300_TX_WRAP_S(R300_TX_MIRRORED); + } + if (texstate->filter0 & R300_TX_WRAP_T(R300_TX_MIRRORED)) { + texstate->filter0 &= ~R300_TX_WRAP_T(R300_TX_MIRRORED); + } + + /* Change repeat to clamp-to-edge. + * (the repeat bit has a value of 0, no masking needed). */ + if ((texstate->filter0 & R300_TX_WRAP_S_MASK) == + R300_TX_WRAP_S(R300_TX_REPEAT)) { + texstate->filter0 |= R300_TX_WRAP_S(R300_TX_CLAMP_TO_EDGE); + } + if ((texstate->filter0 & R300_TX_WRAP_T_MASK) == + R300_TX_WRAP_T(R300_TX_REPEAT)) { + texstate->filter0 |= R300_TX_WRAP_T(R300_TX_CLAMP_TO_EDGE); + } } else { /* determine min/max levels */ /* the MAX_MIP level is the largest (finest) one */ - max_level = MIN2(sampler->max_lod, tex->tex.last_level); - min_level = MIN2(sampler->min_lod, max_level); - texstate->format[0] |= R300_TX_NUM_LEVELS(max_level); - texstate->filter[0] |= R300_TX_MAX_MIP_LEVEL(min_level); + max_level = MIN3(sampler->max_lod + view->base.first_level, + tex->b.b.last_level, view->base.last_level); + min_level = MIN2(sampler->min_lod + view->base.first_level, + max_level); + texstate->format.format0 |= R300_TX_NUM_LEVELS(max_level); + texstate->filter0 |= R300_TX_MAX_MIP_LEVEL(min_level); } - texstate->filter[0] |= i << 28; + texstate->filter0 |= i << 28; size += 16; state->count = i+1; @@ -577,18 +551,31 @@ static void r300_merge_textures_and_samplers(struct r300_context* r300) } r300->textures_state.size = size; + + /* Pick a fragment shader based on either the texture compare state + * or the uses_pitch flag. */ + if (r300->fs.state && count) { + if (r300_pick_fragment_shader(r300)) { + r300_mark_fs_code_dirty(r300); + } + } } void r300_update_derived_state(struct r300_context* r300) { - if (r300->rs_block_state.dirty || - r300->vertex_stream_state.dirty || /* XXX put updating this state out of this file */ - r300->rs_state.dirty) { /* XXX and remove this one (tcl_bypass dependency) */ + if (r300->textures_state.dirty) { + r300_merge_textures_and_samplers(r300); + } + + if (r300->rs_block_state.dirty) { r300_update_derived_shader_state(r300); } - if (r300->textures_state.dirty) { - r300_merge_textures_and_samplers(r300); + if (r300->draw) { + memset(&r300->vertex_info, 0, sizeof(struct vertex_info)); + r300_draw_emit_all_attribs(r300); + draw_compute_vertex_size(&r300->vertex_info); + r300_swtcl_vertex_psc(r300); } r300_update_ztop(r300); |