Module: Mesa
Branch: 8.0
Commit: daefd7f20bc8e79b871a46c50710266fd2006d8c
URL:    
http://cgit.freedesktop.org/mesa/mesa/commit/?id=daefd7f20bc8e79b871a46c50710266fd2006d8c

Author: Vadim Girlin <vadimgir...@gmail.com>
Date:   Fri Jan  6 08:13:18 2012 +0400

r600g: implement two-sided lighting (v3)

v2: select the colors in the pixel shader

v3: fix rs state creation for pre-evergreen

Signed-off-by: Vadim Girlin <vadimgir...@gmail.com>
Signed-off-by: Dave Airlie <airl...@redhat.com>
(cherry picked from commit 725a820b926575265e6790601a0defd9c30947dc)

---

 src/gallium/drivers/r600/evergreen_state.c   |    1 +
 src/gallium/drivers/r600/r600_pipe.h         |    2 +
 src/gallium/drivers/r600/r600_shader.c       |  153 +++++++++++++++++++++----
 src/gallium/drivers/r600/r600_shader.h       |    1 +
 src/gallium/drivers/r600/r600_state.c        |    1 +
 src/gallium/drivers/r600/r600_state_common.c |    2 +
 6 files changed, 135 insertions(+), 25 deletions(-)

diff --git a/src/gallium/drivers/r600/evergreen_state.c 
b/src/gallium/drivers/r600/evergreen_state.c
index 185ea77..352ea23 100644
--- a/src/gallium/drivers/r600/evergreen_state.c
+++ b/src/gallium/drivers/r600/evergreen_state.c
@@ -906,6 +906,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;
 
diff --git a/src/gallium/drivers/r600/r600_pipe.h 
b/src/gallium/drivers/r600/r600_pipe.h
index 447b9dc..bd0b8fe 100644
--- a/src/gallium/drivers/r600/r600_pipe.h
+++ b/src/gallium/drivers/r600/r600_pipe.h
@@ -108,6 +108,7 @@ struct r600_pipe_rasterizer {
        boolean                         clamp_vertex_color;
        boolean                         clamp_fragment_color;
        boolean                         flatshade;
+       boolean                         two_side;
        unsigned                        sprite_coord_enable;
        float                           offset_units;
        float                           offset_scale;
@@ -218,6 +219,7 @@ struct r600_pipe_context {
        /* shader information */
        boolean                         clamp_vertex_color;
        boolean                         clamp_fragment_color;
+       boolean                         two_side;
        unsigned                        sprite_coord_enable;
        boolean                         export_16bpc;
        unsigned                        alpha_ref;
diff --git a/src/gallium/drivers/r600/r600_shader.c 
b/src/gallium/drivers/r600/r600_shader.c
index 568ab71..8a06e8f 100644
--- a/src/gallium/drivers/r600/r600_shader.c
+++ b/src/gallium/drivers/r600/r600_shader.c
@@ -191,6 +191,8 @@ struct r600_shader_ctx {
        boolean                                 input_linear;
        boolean                                 input_perspective;
        int                                     num_interp_gpr;
+       int                                     face_gpr;
+       int                                     colors_used;
 };
 
 struct r600_shader_tgsi_instruction {
@@ -374,12 +376,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);
                }
@@ -393,6 +389,51 @@ static int r600_spi_sid(struct r600_shader_io * io)
        return index;
 };
 
+/* turn input into interpolate on EG */
+static int evergreen_interp_input(struct r600_shader_ctx *ctx, int index)
+{
+       int r = 0;
+
+       if (ctx->shader->input[index].spi_sid) {
+               ctx->shader->input[index].lds_pos = ctx->shader->nlds++;
+               if (ctx->shader->input[index].interpolate > 0) {
+                       r = evergreen_interp_alu(ctx, index);
+               } else {
+                       r = evergreen_interp_flat(ctx, index);
+               }
+       }
+       return r;
+}
+
+static int select_twoside_color(struct r600_shader_ctx *ctx, int front, int 
back)
+{
+       struct r600_bytecode_alu alu;
+       int i, r;
+       int gpr_front = ctx->shader->input[front].gpr;
+       int gpr_back = ctx->shader->input[back].gpr;
+
+       for (i = 0; i < 4; i++) {
+               memset(&alu, 0, sizeof(alu));
+               alu.inst = CTX_INST(V_SQ_ALU_WORD1_OP3_SQ_OP3_INST_CNDGT);
+               alu.is_op3 = 1;
+               alu.dst.write = 1;
+               alu.dst.sel = gpr_front;
+               alu.src[0].sel = ctx->face_gpr;
+               alu.src[1].sel = gpr_front;
+               alu.src[2].sel = gpr_back;
+
+               alu.dst.chan = i;
+               alu.src[1].chan = i;
+               alu.src[2].chan = i;
+               alu.last = (i==3);
+
+               if ((r = r600_bytecode_add_alu(ctx->bc, &alu)))
+                       return r;
+       }
+
+       return 0;
+}
+
 static int tgsi_declaration(struct r600_shader_ctx *ctx)
 {
        struct tgsi_full_declaration *d = &ctx->parse.FullToken.FullDeclaration;
@@ -408,15 +449,15 @@ static int tgsi_declaration(struct r600_shader_ctx *ctx)
                ctx->shader->input[i].interpolate = d->Declaration.Interpolate;
                ctx->shader->input[i].centroid = d->Declaration.Centroid;
                ctx->shader->input[i].gpr = ctx->file_offset[TGSI_FILE_INPUT] + 
d->Range.First;
-               if (ctx->type == TGSI_PROCESSOR_FRAGMENT && ctx->bc->chip_class 
>= EVERGREEN) {
-                       /* turn input into interpolate on EG */
-                       if (ctx->shader->input[i].spi_sid) {
-                               ctx->shader->input[i].lds_pos = 
ctx->shader->nlds++;
-                               if (ctx->shader->input[i].interpolate > 0) {
-                                       evergreen_interp_alu(ctx, i);
-                               } else {
-                                       evergreen_interp_flat(ctx, i);
-                               }
+               if (ctx->type == TGSI_PROCESSOR_FRAGMENT) {
+                       if (ctx->shader->input[i].name == TGSI_SEMANTIC_FACE)
+                               ctx->face_gpr = ctx->shader->input[i].gpr;
+                       else if (ctx->shader->input[i].name == 
TGSI_SEMANTIC_COLOR)
+                               ctx->colors_used++;
+                       if (ctx->bc->chip_class >= EVERGREEN) {
+                               r = evergreen_interp_input(ctx, i);
+                               if (r)
+                                       return r;
                        }
                }
                break;
@@ -690,6 +731,47 @@ static int tgsi_split_literal_constant(struct 
r600_shader_ctx *ctx)
        return 0;
 }
 
+static int process_twoside_color_inputs(struct r600_shader_ctx *ctx)
+{
+       int i, r, count = ctx->shader->ninput;
+
+       /* additional inputs will be allocated right after the existing inputs,
+        * we won't need them after the color selection, so we don't need to
+        * reserve these gprs for the rest of the shader code and to adjust
+        * output offsets etc. */
+       int gpr = ctx->file_offset[TGSI_FILE_INPUT] +
+                       ctx->info.file_max[TGSI_FILE_INPUT] + 1;
+
+       if (ctx->face_gpr == -1) {
+               i = ctx->shader->ninput++;
+               ctx->shader->input[i].name = TGSI_SEMANTIC_FACE;
+               ctx->shader->input[i].spi_sid = 0;
+               ctx->shader->input[i].gpr = gpr++;
+               ctx->face_gpr = ctx->shader->input[i].gpr;
+       }
+
+       for (i = 0; i < count; i++) {
+               if (ctx->shader->input[i].name == TGSI_SEMANTIC_COLOR) {
+                       int ni = ctx->shader->ninput++;
+                       memcpy(&ctx->shader->input[ni],&ctx->shader->input[i], 
sizeof(struct r600_shader_io));
+                       ctx->shader->input[ni].name = TGSI_SEMANTIC_BCOLOR;
+                       ctx->shader->input[ni].spi_sid = 
r600_spi_sid(&ctx->shader->input[ni]);
+                       ctx->shader->input[ni].gpr = gpr++;
+
+                       if (ctx->bc->chip_class >= EVERGREEN) {
+                               r = evergreen_interp_input(ctx, ni);
+                               if (r)
+                                       return r;
+                       }
+
+                       r = select_twoside_color(ctx, i, ni);
+                       if (r)
+                               return r;
+               }
+       }
+       return 0;
+}
+
 static int r600_shader_from_tgsi(struct r600_pipe_context * rctx, struct 
r600_pipe_shader *pipeshader)
 {
        struct r600_shader *shader = &pipeshader->shader;
@@ -713,6 +795,11 @@ static int r600_shader_from_tgsi(struct r600_pipe_context 
* rctx, struct r600_pi
        shader->processor_type = ctx.type;
        ctx.bc->type = shader->processor_type;
 
+       ctx.face_gpr = -1;
+       ctx.colors_used = 0;
+
+       shader->two_side = (ctx.type == TGSI_PROCESSOR_FRAGMENT) && 
rctx->two_side;
+
        shader->clamp_color = (((ctx.type == TGSI_PROCESSOR_FRAGMENT) && 
rctx->clamp_fragment_color) ||
                ((ctx.type == TGSI_PROCESSOR_VERTEX) && 
rctx->clamp_vertex_color));
 
@@ -792,6 +879,31 @@ static int r600_shader_from_tgsi(struct r600_pipe_context 
* rctx, struct r600_pi
                                goto out_err;
                        break;
                case TGSI_TOKEN_TYPE_INSTRUCTION:
+                       break;
+               case TGSI_TOKEN_TYPE_PROPERTY:
+                       property = &ctx.parse.FullToken.FullProperty;
+                       if (property->Property.PropertyName == 
TGSI_PROPERTY_FS_COLOR0_WRITES_ALL_CBUFS) {
+                               if (property->u[0].Data == 1)
+                                       shader->fs_write_all = TRUE;
+                       }
+                       break;
+               default:
+                       R600_ERR("unsupported token type %d\n", 
ctx.parse.FullToken.Token.Type);
+                       r = -EINVAL;
+                       goto out_err;
+               }
+       }
+
+       if (shader->two_side && ctx.colors_used) {
+               if ((r = process_twoside_color_inputs(&ctx)))
+                       return r;
+       }
+
+       tgsi_parse_init(&ctx.parse, tokens);
+       while (!tgsi_parse_end_of_tokens(&ctx.parse)) {
+               tgsi_parse_token(&ctx.parse);
+               switch (ctx.parse.FullToken.Token.Type) {
+               case TGSI_TOKEN_TYPE_INSTRUCTION:
                        r = tgsi_is_supported(&ctx);
                        if (r)
                                goto out_err;
@@ -814,17 +926,8 @@ static int r600_shader_from_tgsi(struct r600_pipe_context 
* rctx, struct r600_pi
                        if (r)
                                goto out_err;
                        break;
-               case TGSI_TOKEN_TYPE_PROPERTY:
-                       property = &ctx.parse.FullToken.FullProperty;
-                       if (property->Property.PropertyName == 
TGSI_PROPERTY_FS_COLOR0_WRITES_ALL_CBUFS) {
-                               if (property->u[0].Data == 1)
-                                       shader->fs_write_all = TRUE;
-                       }
-                       break;
                default:
-                       R600_ERR("unsupported token type %d\n", 
ctx.parse.FullToken.Token.Type);
-                       r = -EINVAL;
-                       goto out_err;
+                       break;
                }
        }
 
diff --git a/src/gallium/drivers/r600/r600_shader.h 
b/src/gallium/drivers/r600/r600_shader.h
index 9990ba6..530a776 100644
--- a/src/gallium/drivers/r600/r600_shader.h
+++ b/src/gallium/drivers/r600/r600_shader.h
@@ -47,6 +47,7 @@ struct r600_shader {
        boolean                 uses_kill;
        boolean                 fs_write_all;
        boolean                 clamp_color;
+       boolean                 two_side;
        unsigned                nr_cbufs;
 };
 
diff --git a/src/gallium/drivers/r600/r600_state.c 
b/src/gallium/drivers/r600/r600_state.c
index 8fc5618..fb95caa 100644
--- a/src/gallium/drivers/r600/r600_state.c
+++ b/src/gallium/drivers/r600/r600_state.c
@@ -958,6 +958,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 */
diff --git a/src/gallium/drivers/r600/r600_state_common.c 
b/src/gallium/drivers/r600/r600_state_common.c
index 054ab90..7f8aad6 100644
--- a/src/gallium/drivers/r600/r600_state_common.c
+++ b/src/gallium/drivers/r600/r600_state_common.c
@@ -103,6 +103,7 @@ void r600_bind_rs_state(struct pipe_context *ctx, void 
*state)
        rctx->clamp_fragment_color = rs->clamp_fragment_color;
 
        rctx->sprite_coord_enable = rs->sprite_coord_enable;
+       rctx->two_side = rs->two_side;
 
        rctx->rasterizer = rs;
 
@@ -564,6 +565,7 @@ static void r600_update_derived_state(struct 
r600_pipe_context *rctx)
        }
 
        if ((rctx->ps_shader->shader.clamp_color != rctx->clamp_fragment_color) 
||
+           (rctx->ps_shader->shader.two_side != rctx->two_side) ||
            ((rctx->chip_class >= EVERGREEN) && 
rctx->ps_shader->shader.fs_write_all &&
             (rctx->ps_shader->shader.nr_cbufs != rctx->nr_cbufs))) {
                r600_shader_rebuild(&rctx->context, rctx->ps_shader);

_______________________________________________
mesa-commit mailing list
mesa-commit@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/mesa-commit

Reply via email to