r600g: Store the chip class in r600_pipe_context.
[mesa.git] / src / gallium / drivers / r600 / r600_state_common.c
index 30c61817a08c82754e08c42492bf691203718e8d..408eaed491b2c79dcb1177a00f67c0c4d1909c8e 100644 (file)
@@ -28,6 +28,7 @@
 #include <util/u_format.h>
 #include <pipebuffer/pb_buffer.h>
 #include "pipe/p_shader_tokens.h"
+#include "tgsi/tgsi_parse.h"
 #include "r600_formats.h"
 #include "r600_pipe.h"
 #include "r600d.h"
@@ -99,6 +100,8 @@ void r600_bind_rs_state(struct pipe_context *ctx, void *state)
        if (state == NULL)
                return;
 
+       rctx->clamp_vertex_color = rs->clamp_vertex_color;
+       rctx->clamp_fragment_color = rs->clamp_fragment_color;
        rctx->flatshade = rs->flatshade;
        rctx->sprite_coord_enable = rs->sprite_coord_enable;
        rctx->rasterizer = rs;
@@ -106,13 +109,13 @@ void r600_bind_rs_state(struct pipe_context *ctx, void *state)
        rctx->states[rs->rstate.id] = &rs->rstate;
        r600_context_pipe_state_set(&rctx->ctx, &rs->rstate);
 
-       if (rctx->family >= CHIP_CEDAR) {
+       if (rctx->chip_class >= EVERGREEN) {
                evergreen_polygon_offset_update(rctx);
        } else {
                r600_polygon_offset_update(rctx);
        }
        if (rctx->ps_shader && rctx->vs_shader)
-               r600_spi_update(rctx);
+               rctx->spi_dirty = true;
 }
 
 void r600_delete_rs_state(struct pipe_context *ctx, void *state)
@@ -209,7 +212,7 @@ void r600_set_vertex_buffers(struct pipe_context *ctx, unsigned count,
        /* Zero states. */
        for (i = 0; i < count; i++) {
                if (!buffers[i].buffer) {
-                       if (rctx->family >= CHIP_CEDAR) {
+                       if (rctx->chip_class >= EVERGREEN) {
                                evergreen_context_pipe_state_set_fs_resource(&rctx->ctx, NULL, i);
                        } else {
                                r600_context_pipe_state_set_fs_resource(&rctx->ctx, NULL, i);
@@ -217,7 +220,7 @@ void r600_set_vertex_buffers(struct pipe_context *ctx, unsigned count,
                }
        }
        for (; i < rctx->vbuf_mgr->nr_real_vertex_buffers; i++) {
-               if (rctx->family >= CHIP_CEDAR) {
+               if (rctx->chip_class >= EVERGREEN) {
                        evergreen_context_pipe_state_set_fs_resource(&rctx->ctx, NULL, i);
                } else {
                        r600_context_pipe_state_set_fs_resource(&rctx->ctx, NULL, i);
@@ -257,7 +260,9 @@ void *r600_create_shader_state(struct pipe_context *ctx,
        struct r600_pipe_shader *shader =  CALLOC_STRUCT(r600_pipe_shader);
        int r;
 
-       r =  r600_pipe_shader_create(ctx, shader, state->tokens);
+       shader->tokens = tgsi_dup_tokens(state->tokens);
+
+       r =  r600_pipe_shader_create(ctx, shader);
        if (r) {
                return NULL;
        }
@@ -274,7 +279,7 @@ void r600_bind_ps_shader(struct pipe_context *ctx, void *state)
                r600_context_pipe_state_set(&rctx->ctx, &rctx->ps_shader->rstate);
        }
        if (rctx->ps_shader && rctx->vs_shader) {
-               r600_spi_update(rctx);
+               rctx->spi_dirty = true;
                r600_adjust_gprs(rctx);
        }
 }
@@ -289,7 +294,7 @@ void r600_bind_vs_shader(struct pipe_context *ctx, void *state)
                r600_context_pipe_state_set(&rctx->ctx, &rctx->vs_shader->rstate);
        }
        if (rctx->ps_shader && rctx->vs_shader) {
-               r600_spi_update(rctx);
+               rctx->spi_dirty = true;
                r600_adjust_gprs(rctx);
        }
 }
@@ -303,6 +308,7 @@ void r600_delete_ps_shader(struct pipe_context *ctx, void *state)
                rctx->ps_shader = NULL;
        }
 
+       free(shader->tokens);
        r600_pipe_shader_destroy(ctx, shader);
        free(shader);
 }
@@ -316,6 +322,7 @@ void r600_delete_vs_shader(struct pipe_context *ctx, void *state)
                rctx->vs_shader = NULL;
        }
 
+       free(shader->tokens);
        r600_pipe_shader_destroy(ctx, shader);
        free(shader);
 }
@@ -360,7 +367,7 @@ static void r600_spi_update(struct r600_pipe_context *rctx)
        for (i = 0; i < rshader->ninput; i++) {
                if (rshader->input[i].name == TGSI_SEMANTIC_POSITION ||
                    rshader->input[i].name == TGSI_SEMANTIC_FACE)
-                       if (rctx->family >= CHIP_CEDAR)
+                       if (rctx->chip_class >= EVERGREEN)
                                continue;
                        else
                                sid=0;
@@ -380,7 +387,7 @@ static void r600_spi_update(struct r600_pipe_context *rctx)
                        tmp |= S_028644_PT_SPRITE_TEX(1);
                }
 
-               if (rctx->family < CHIP_CEDAR) {
+               if (rctx->chip_class < EVERGREEN) {
                        if (rshader->input[i].centroid)
                                tmp |= S_028644_SEL_CENTROID(1);
 
@@ -391,6 +398,7 @@ static void r600_spi_update(struct r600_pipe_context *rctx)
                r600_pipe_state_mod_reg(rstate, tmp);
        }
 
+       rctx->spi_dirty = false;
        r600_context_pipe_state_set(&rctx->ctx, rstate);
 }
 
@@ -426,14 +434,14 @@ void r600_set_constant_buffer(struct pipe_context *ctx, uint shader, uint index,
 
                rstate = &rctx->vs_const_buffer_resource[index];
                if (!rstate->id) {
-                       if (rctx->family >= CHIP_CEDAR) {
+                       if (rctx->chip_class >= EVERGREEN) {
                                evergreen_pipe_init_buffer_resource(rctx, rstate);
                        } else {
                                r600_pipe_init_buffer_resource(rctx, rstate);
                        }
                }
 
-               if (rctx->family >= CHIP_CEDAR) {
+               if (rctx->chip_class >= EVERGREEN) {
                        evergreen_pipe_mod_buffer_resource(rstate, &rbuffer->r, offset, 16);
                        evergreen_context_pipe_state_set_vs_resource(&rctx->ctx, rstate, index);
                } else {
@@ -454,13 +462,13 @@ void r600_set_constant_buffer(struct pipe_context *ctx, uint shader, uint index,
 
                rstate = &rctx->ps_const_buffer_resource[index];
                if (!rstate->id) {
-                       if (rctx->family >= CHIP_CEDAR) {
+                       if (rctx->chip_class >= EVERGREEN) {
                                evergreen_pipe_init_buffer_resource(rctx, rstate);
                        } else {
                                r600_pipe_init_buffer_resource(rctx, rstate);
                        }
                }
-               if (rctx->family >= CHIP_CEDAR) {
+               if (rctx->chip_class >= EVERGREEN) {
                        evergreen_pipe_mod_buffer_resource(rstate, &rbuffer->r, offset, 16);
                        evergreen_context_pipe_state_set_ps_resource(&rctx->ctx, rstate, index);
                } else {
@@ -513,14 +521,14 @@ static void r600_vertex_buffer_update(struct r600_pipe_context *rctx)
                offset += vertex_buffer->buffer_offset + r600_bo_offset(rbuffer->bo);
 
                if (!rstate->id) {
-                       if (rctx->family >= CHIP_CEDAR) {
+                       if (rctx->chip_class >= EVERGREEN) {
                                evergreen_pipe_init_buffer_resource(rctx, rstate);
                        } else {
                                r600_pipe_init_buffer_resource(rctx, rstate);
                        }
                }
 
-               if (rctx->family >= CHIP_CEDAR) {
+               if (rctx->chip_class >= EVERGREEN) {
                        evergreen_pipe_mod_buffer_resource(rstate, rbuffer, offset, vertex_buffer->stride);
                        evergreen_context_pipe_state_set_fs_resource(&rctx->ctx, rstate, i);
                } else {
@@ -530,6 +538,21 @@ static void r600_vertex_buffer_update(struct r600_pipe_context *rctx)
        }
 }
 
+static int r600_shader_rebuild(struct pipe_context * ctx, struct r600_pipe_shader * shader)
+{
+       struct r600_pipe_context *rctx = (struct r600_pipe_context *)ctx;
+       int r;
+
+       r600_pipe_shader_destroy(ctx, shader);
+       r = r600_pipe_shader_create(ctx, shader);
+       if (r) {
+               return r;
+       }
+       r600_context_pipe_state_set(&rctx->ctx, &shader->rstate);
+
+       return 0;
+}
+
 void r600_draw_vbo(struct pipe_context *ctx, const struct pipe_draw_info *info)
 {
        struct r600_pipe_context *rctx = (struct r600_pipe_context *)ctx;
@@ -573,6 +596,17 @@ void r600_draw_vbo(struct pipe_context *ctx, const struct pipe_draw_info *info)
        if (r600_conv_pipe_prim(draw.info.mode, &prim))
                return;
 
+       if (rctx->vs_shader->shader.clamp_color != rctx->clamp_vertex_color)
+               r600_shader_rebuild(ctx, rctx->vs_shader);
+
+       if ((rctx->ps_shader->shader.clamp_color != rctx->clamp_fragment_color) ||
+           ((rctx->chip_class >= EVERGREEN) && rctx->ps_shader->shader.fs_write_all &&
+            (rctx->ps_shader->shader.nr_cbufs != rctx->nr_cbufs)))
+               r600_shader_rebuild(ctx, rctx->ps_shader);
+
+       if (rctx->spi_dirty)
+               r600_spi_update(rctx);
+
        if (rctx->alpha_ref_dirty)
                r600_update_alpha_ref(rctx);
 
@@ -621,7 +655,7 @@ void r600_draw_vbo(struct pipe_context *ctx, const struct pipe_draw_info *info)
                rdraw.indices_bo_offset = draw.index_buffer_offset;
        }
 
-       if (rctx->family >= CHIP_CEDAR) {
+       if (rctx->chip_class >= EVERGREEN) {
                evergreen_context_draw(&rctx->ctx, &rdraw);
        } else {
                r600_context_draw(&rctx->ctx, &rdraw);