Rendering in two-sided mode is performed in separate passes for front and
back faces, corresponding colors are selected by semantic ids.

Signed-off-by: Vadim Girlin <[email protected]>
---

Tested on evergreen: no regressions, fixes two-side tests.

 src/gallium/drivers/r600/evergreen_state.c   |    9 ++-
 src/gallium/drivers/r600/r600_pipe.h         |    3 +
 src/gallium/drivers/r600/r600_shader.c       |    6 --
 src/gallium/drivers/r600/r600_state.c        |    9 ++-
 src/gallium/drivers/r600/r600_state_common.c |   82 +++++++++++++++++++++++++-
 5 files changed, 96 insertions(+), 13 deletions(-)

diff --git a/src/gallium/drivers/r600/evergreen_state.c 
b/src/gallium/drivers/r600/evergreen_state.c
index ed75ae3..b0999c4 100644
--- a/src/gallium/drivers/r600/evergreen_state.c
+++ b/src/gallium/drivers/r600/evergreen_state.c
@@ -902,6 +902,7 @@ static void *evergreen_create_rs_state(struct pipe_context 
*ctx,
        rs->clamp_fragment_color = state->clamp_fragment_color;
        rs->flatshade = state->flatshade;
        rs->sprite_coord_enable = state->sprite_coord_enable;
+       rs->two_side = state->light_twoside;
 
        clip_rule = state->scissor ? 0xAAAA : 0xFFFF;
 
@@ -927,10 +928,14 @@ static void *evergreen_create_rs_state(struct 
pipe_context *ctx,
 
        polygon_dual_mode = (state->fill_front != PIPE_POLYGON_MODE_FILL ||
                                state->fill_back != PIPE_POLYGON_MODE_FILL);
+
+       rs->cull_front = state->rasterizer_discard || (state->cull_face & 
PIPE_FACE_FRONT) ? 1 : 0;
+       rs->cull_back = state->rasterizer_discard || (state->cull_face & 
PIPE_FACE_BACK) ? 1 : 0;
+
        r600_pipe_state_add_reg(rstate, R_028814_PA_SU_SC_MODE_CNTL,
                S_028814_PROVOKING_VTX_LAST(prov_vtx) |
-               S_028814_CULL_FRONT(state->rasterizer_discard || 
(state->cull_face & PIPE_FACE_FRONT) ? 1 : 0) |
-               S_028814_CULL_BACK(state->rasterizer_discard || 
(state->cull_face & PIPE_FACE_BACK) ? 1 : 0) |
+               S_028814_CULL_FRONT(rs->cull_front) |
+               S_028814_CULL_BACK(rs->cull_back) |
                S_028814_FACE(!state->front_ccw) |
                S_028814_POLY_OFFSET_FRONT_ENABLE(state->offset_tri) |
                S_028814_POLY_OFFSET_BACK_ENABLE(state->offset_tri) |
diff --git a/src/gallium/drivers/r600/r600_pipe.h 
b/src/gallium/drivers/r600/r600_pipe.h
index 447b9dc..30cc6d9 100644
--- a/src/gallium/drivers/r600/r600_pipe.h
+++ b/src/gallium/drivers/r600/r600_pipe.h
@@ -108,6 +108,9 @@ struct r600_pipe_rasterizer {
        boolean                         clamp_vertex_color;
        boolean                         clamp_fragment_color;
        boolean                         flatshade;
+       boolean                         two_side;
+       boolean                         cull_front;
+       boolean                         cull_back;
        unsigned                        sprite_coord_enable;
        float                           offset_units;
        float                           offset_scale;
diff --git a/src/gallium/drivers/r600/r600_shader.c 
b/src/gallium/drivers/r600/r600_shader.c
index ad4aded..bade11e 100644
--- a/src/gallium/drivers/r600/r600_shader.c
+++ b/src/gallium/drivers/r600/r600_shader.c
@@ -374,12 +374,6 @@ static int r600_spi_sid(struct r600_shader_io * io)
                        /* For generic params simply use sid from tgsi */
                        index = io->sid;
                } else {
-
-                       /* FIXME: two-side rendering is broken in r600g, this 
will
-                        * keep old functionality */
-                       if (name == TGSI_SEMANTIC_BCOLOR)
-                               name = TGSI_SEMANTIC_COLOR;
-
                        /* For non-generic params - pack name and sid into 8 
bits */
                        index = 0x80 | (name<<3) | (io->sid);
                }
diff --git a/src/gallium/drivers/r600/r600_state.c 
b/src/gallium/drivers/r600/r600_state.c
index 12157ff..df1d3c0 100644
--- a/src/gallium/drivers/r600/r600_state.c
+++ b/src/gallium/drivers/r600/r600_state.c
@@ -954,6 +954,7 @@ static void *r600_create_rs_state(struct pipe_context *ctx,
        rs->clamp_fragment_color = state->clamp_fragment_color;
        rs->flatshade = state->flatshade;
        rs->sprite_coord_enable = state->sprite_coord_enable;
+       rs->two_side = state->light_twoside;
 
        clip_rule = state->scissor ? 0xAAAA : 0xFFFF;
        /* offset */
@@ -978,10 +979,14 @@ static void *r600_create_rs_state(struct pipe_context 
*ctx,
 
        polygon_dual_mode = (state->fill_front != PIPE_POLYGON_MODE_FILL ||
                                state->fill_back != PIPE_POLYGON_MODE_FILL);
+
+       rs->cull_front = state->rasterizer_discard || (state->cull_face & 
PIPE_FACE_FRONT) ? 1 : 0;
+       rs->cull_back = state->rasterizer_discard || (state->cull_face & 
PIPE_FACE_BACK) ? 1 : 0;
+
        r600_pipe_state_add_reg(rstate, R_028814_PA_SU_SC_MODE_CNTL,
                S_028814_PROVOKING_VTX_LAST(prov_vtx) |
-               S_028814_CULL_FRONT(state->rasterizer_discard || 
(state->cull_face & PIPE_FACE_FRONT) ? 1 : 0) |
-               S_028814_CULL_BACK(state->rasterizer_discard || 
(state->cull_face & PIPE_FACE_BACK) ? 1 : 0) |
+               S_028814_CULL_FRONT(rs->cull_front) |
+               S_028814_CULL_BACK(rs->cull_back) |
                S_028814_FACE(!state->front_ccw) |
                S_028814_POLY_OFFSET_FRONT_ENABLE(state->offset_tri) |
                S_028814_POLY_OFFSET_BACK_ENABLE(state->offset_tri) |
diff --git a/src/gallium/drivers/r600/r600_state_common.c 
b/src/gallium/drivers/r600/r600_state_common.c
index 9f6f514..f1abf41 100644
--- a/src/gallium/drivers/r600/r600_state_common.c
+++ b/src/gallium/drivers/r600/r600_state_common.c
@@ -586,6 +586,55 @@ static void r600_update_derived_state(struct 
r600_pipe_context *rctx)
 
 }
 
+
+/* Prepare/restore the state for two-sided rendering.
+ * Front/back faces are rendered in separate passes,
+ * required color from vertex shader is selected by semantic id
+ *
+ * stage defines the current mode:
+ *    0 - rendering front faces only with front colors
+ *    1 - rendering back faces only with back colors
+ *    2 - restore normal state
+ */
+static void r600_prepare_two_side_mode(struct r600_pipe_context * rctx, 
unsigned stage)
+{
+       struct r600_shader * rshader = &rctx->ps_shader->shader;
+       struct r600_pipe_state rstate;
+       unsigned i, idx = 0, sid, tmp;
+       boolean eg_mode = (rctx->chip_class >= EVERGREEN);
+
+       rstate.nregs = 0;
+
+       if (stage>0) {
+
+               for (i = 0; i < rshader->ninput; i++) {
+
+                       sid = rshader->input[i].spi_sid;
+
+                       if (rshader->input[i].name == TGSI_SEMANTIC_COLOR) {
+
+                               /* switch between front/back colors semantic 
ids from vertex shader */
+                               sid += (stage == 1 ? 1<<3 : 0 );
+
+                               tmp = S_028644_SEMANTIC(sid);
+                               r600_pipe_state_add_reg(&rstate, 
R_028644_SPI_PS_INPUT_CNTL_0 + idx * 4,
+                                               tmp, S_028644_SEMANTIC(0xFF), 
NULL, 0);
+                       }
+
+                       if (sid || !eg_mode)
+                               idx++;
+               }
+
+       }
+
+       r600_pipe_state_add_reg(&rstate, R_028814_PA_SU_SC_MODE_CNTL,
+                       S_028814_CULL_FRONT(stage==1 ? 1 : 
rctx->rasterizer->cull_front) |
+                       S_028814_CULL_BACK (stage==0 ? 1 : 
rctx->rasterizer->cull_back),
+                       S_028814_CULL_FRONT(1) | S_028814_CULL_BACK(1), NULL, 
0);
+
+       r600_context_pipe_state_set(&rctx->ctx, &rstate);
+}
+
 void r600_draw_vbo(struct pipe_context *ctx, const struct pipe_draw_info 
*dinfo)
 {
        struct r600_pipe_context *rctx = (struct r600_pipe_context *)ctx;
@@ -692,10 +741,37 @@ void r600_draw_vbo(struct pipe_context *ctx, const struct 
pipe_draw_info *dinfo)
 
        r600_context_pipe_state_set(&rctx->ctx, &rctx->vgt);
 
-       if (rctx->chip_class >= EVERGREEN) {
-               evergreen_context_draw(&rctx->ctx, &rdraw);
+       if (unlikely(rctx->rasterizer->two_side)) {
+
+               /* front faces */
+               r600_prepare_two_side_mode(rctx, 0);
+
+               if (rctx->chip_class >= EVERGREEN) {
+                       evergreen_context_draw(&rctx->ctx, &rdraw);
+               } else {
+                       r600_context_draw(&rctx->ctx, &rdraw);
+               }
+
+               /* back faces */
+               r600_prepare_two_side_mode(rctx, 1);
+
+               if (rctx->chip_class >= EVERGREEN) {
+                       evergreen_context_draw(&rctx->ctx, &rdraw);
+               } else {
+                       r600_context_draw(&rctx->ctx, &rdraw);
+               }
+
+               /* restore normal state */
+               r600_prepare_two_side_mode(rctx, 2);
+
        } else {
-               r600_context_draw(&rctx->ctx, &rdraw);
+
+               if (rctx->chip_class >= EVERGREEN) {
+                       evergreen_context_draw(&rctx->ctx, &rdraw);
+               } else {
+                       r600_context_draw(&rctx->ctx, &rdraw);
+               }
+
        }
 
        if (rctx->framebuffer.zsbuf)
-- 
1.7.7.5

_______________________________________________
mesa-dev mailing list
[email protected]
http://lists.freedesktop.org/mailman/listinfo/mesa-dev

Reply via email to