diff options
-rw-r--r-- | src/gallium/drivers/r300/r300_context.h | 2 | ||||
-rw-r--r-- | src/gallium/drivers/r300/r300_state.c | 6 | ||||
-rw-r--r-- | src/gallium/drivers/r300/r300_state_derived.c | 24 |
3 files changed, 27 insertions, 5 deletions
diff --git a/src/gallium/drivers/r300/r300_context.h b/src/gallium/drivers/r300/r300_context.h index dd16565c562..4b401a7040c 100644 --- a/src/gallium/drivers/r300/r300_context.h +++ b/src/gallium/drivers/r300/r300_context.h @@ -442,6 +442,8 @@ struct r300_context { boolean stencil_ref_bf_fallback; /* Point sprites texcoord index, 1 bit per texcoord */ int sprite_coord_enable; + /* Whether two-sided color selection is enabled (AKA light_twoside). */ + boolean two_sided_color; /* upload managers */ struct u_upload_mgr *upload_vb; diff --git a/src/gallium/drivers/r300/r300_state.c b/src/gallium/drivers/r300/r300_state.c index 1344415861c..399099785c6 100644 --- a/src/gallium/drivers/r300/r300_state.c +++ b/src/gallium/drivers/r300/r300_state.c @@ -870,6 +870,7 @@ static void r300_bind_rs_state(struct pipe_context* pipe, void* state) struct r300_context* r300 = r300_context(pipe); struct r300_rs_state* rs = (struct r300_rs_state*)state; int last_sprite_coord_enable = r300->sprite_coord_enable; + boolean last_two_sided_color = r300->two_sided_color; if (r300->draw) { draw_flush(r300->draw); @@ -879,15 +880,18 @@ static void r300_bind_rs_state(struct pipe_context* pipe, void* state) if (rs) { r300->polygon_offset_enabled = rs->rs.offset_cw || rs->rs.offset_ccw; r300->sprite_coord_enable = rs->rs.sprite_coord_enable; + r300->two_sided_color = rs->rs.light_twoside; } else { r300->polygon_offset_enabled = FALSE; r300->sprite_coord_enable = 0; + r300->two_sided_color = FALSE; } UPDATE_STATE(state, r300->rs_state); r300->rs_state.size = 27 + (r300->polygon_offset_enabled ? 5 : 0); - if (last_sprite_coord_enable != r300->sprite_coord_enable) { + if (last_sprite_coord_enable != r300->sprite_coord_enable || + last_two_sided_color != r300->two_sided_color) { r300->rs_block_state.dirty = TRUE; } } diff --git a/src/gallium/drivers/r300/r300_state_derived.c b/src/gallium/drivers/r300/r300_state_derived.c index 193a60c034f..c7388998270 100644 --- a/src/gallium/drivers/r300/r300_state_derived.c +++ b/src/gallium/drivers/r300/r300_state_derived.c @@ -355,10 +355,26 @@ static void r300_update_rs_block(struct r300_context *r300) /* Set up back-face colors. The rasterizer will do the color selection * automatically. */ if (any_bcolor_used) { - for (i = 0; i < ATTR_COLOR_COUNT; i++) { - rs.vap_vsm_vtx_assm |= R300_INPUT_CNTL_COLOR; - rs.vap_out_vtx_fmt[0] |= R300_VAP_OUTPUT_VTX_FMT_0__COLOR_0_PRESENT << (2+i); - stream_loc_notcl[loc++] = 4 + i; + if (r300->two_sided_color) { + /* Rasterize as back-face colors. */ + for (i = 0; i < ATTR_COLOR_COUNT; i++) { + rs.vap_vsm_vtx_assm |= R300_INPUT_CNTL_COLOR; + rs.vap_out_vtx_fmt[0] |= R300_VAP_OUTPUT_VTX_FMT_0__COLOR_0_PRESENT << (2+i); + stream_loc_notcl[loc++] = 4 + i; + } + } else { + /* Rasterize two fake texcoords to prevent from the two-sided color + * selection. */ + /* XXX Consider recompiling the vertex shader to save 2 RS units. */ + for (i = 0; i < 2; i++) { + 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; + + /* Rasterize it. */ + rX00_rs_tex(&rs, tex_count, tex_count, SWIZ_XYZW); + tex_count++; + } } } |