Merge remote branch 'origin/7.8'
[mesa.git] / src / gallium / drivers / r300 / r300_state.c
index f1a062333a61dc69981aa42a6412938abb3a8539..9eb8539a655220c7bff4f09d8557e000e588f8c4 100644 (file)
@@ -36,6 +36,7 @@
 #include "r300_reg.h"
 #include "r300_screen.h"
 #include "r300_screen_buffer.h"
+#include "r300_state.h"
 #include "r300_state_inlines.h"
 #include "r300_fs.h"
 #include "r300_texture.h"
@@ -683,7 +684,7 @@ static void* r300_create_fs_state(struct pipe_context* pipe,
     return (void*)fs;
 }
 
-static void r300_mark_fs_code_dirty(struct r300_context *r300)
+void r300_mark_fs_code_dirty(struct r300_context *r300)
 {
     struct r300_fragment_shader* fs = r300_fs(r300);
 
@@ -757,6 +758,7 @@ static void* r300_create_rs_state(struct pipe_context* pipe,
                                   const struct pipe_rasterizer_state* state)
 {
     struct r300_rs_state* rs = CALLOC_STRUCT(r300_rs_state);
+    int i;
 
     /* Copy rasterizer state for Draw. */
     rs->rs = *state;
@@ -851,6 +853,30 @@ static void* r300_create_rs_state(struct pipe_context* pipe,
 
     rs->clip_rule = state->scissor ? 0xAAAA : 0xFFFF;
 
+    /* Point sprites */
+    if (state->sprite_coord_enable) {
+        rs->stuffing_enable = R300_GB_POINT_STUFF_ENABLE;
+       for (i = 0; i < 8; i++) {
+           if (state->sprite_coord_enable & (1 << i))
+               rs->stuffing_enable |=
+                   R300_GB_TEX_STR << (R300_GB_TEX0_SOURCE_SHIFT + (i*2));
+       }
+
+        rs->point_texcoord_left = 0.0f;
+        rs->point_texcoord_right = 1.0f;
+
+        switch (state->sprite_coord_mode) {
+            case PIPE_SPRITE_COORD_UPPER_LEFT:
+                rs->point_texcoord_top = 0.0f;
+                rs->point_texcoord_bottom = 1.0f;
+                break;
+            case PIPE_SPRITE_COORD_LOWER_LEFT:
+                rs->point_texcoord_top = 1.0f;
+                rs->point_texcoord_bottom = 0.0f;
+                break;
+        }
+    }
+
     return (void*)rs;
 }
 
@@ -859,20 +885,27 @@ 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;
 
     if (r300->draw) {
         draw_flush(r300->draw);
-        draw_set_rasterizer_state(r300->draw, &rs->rs);
+        draw_set_rasterizer_state(r300->draw, &rs->rs, state);
     }
 
     if (rs) {
         r300->polygon_offset_enabled = rs->rs.offset_cw || rs->rs.offset_ccw;
+        r300->sprite_coord_enable = rs->rs.sprite_coord_enable;
     } else {
         r300->polygon_offset_enabled = FALSE;
+        r300->sprite_coord_enable = 0;
     }
 
     UPDATE_STATE(state, r300->rs_state);
-    r300->rs_state.size = 19 + (r300->polygon_offset_enabled ? 5 : 0);
+    r300->rs_state.size = 26 + (r300->polygon_offset_enabled ? 5 : 0);
+
+    if (last_sprite_coord_enable != r300->sprite_coord_enable) {
+        r300->rs_block_state.dirty = TRUE;
+    }
 }
 
 /* Free rasterizer state. */
@@ -950,13 +983,6 @@ static void r300_bind_sampler_states(struct pipe_context* pipe,
     state->sampler_state_count = count;
 
     r300->textures_state.dirty = TRUE;
-
-    /* Pick a fragment shader based on the texture compare state. */
-    if (r300->fs.state && count) {
-        if (r300_pick_fragment_shader(r300)) {
-            r300_mark_fs_code_dirty(r300);
-        }
-    }
 }
 
 static void r300_lacks_vertex_textures(struct pipe_context* pipe,
@@ -980,7 +1006,6 @@ static void r300_set_fragment_sampler_views(struct pipe_context* pipe,
     struct r300_texture *texture;
     unsigned i;
     unsigned tex_units = r300->screen->caps.num_tex_units;
-    boolean is_r500 = r300->screen->caps.is_r500;
     boolean dirty_tex = FALSE;
 
     if (count > tex_units) {
@@ -1000,9 +1025,10 @@ static void r300_set_fragment_sampler_views(struct pipe_context* pipe,
             /* A new sampler view (= texture)... */
             dirty_tex = TRUE;
 
-            /* R300-specific - set the texrect factor in the fragment shader */
+            /* Set the texrect factor in the fragment shader.
+             * Needed for RECT and NPOT fallback. */
             texture = r300_texture(views[i]->texture);
-            if (!is_r500 && texture->uses_pitch) {
+            if (texture->uses_pitch) {
                 r300->fs_rc_constant_state.dirty = TRUE;
             }
         }
@@ -1166,14 +1192,13 @@ static void r300_set_vertex_buffers(struct pipe_context* pipe,
         }
 
         if (vbo->max_index == ~0) {
-            /* Bogus value from broken state tracker; hax it. */
-           /* TODO - more hax - fixes doom3 from almos on irc */
-           if (!vbo->stride) {
-               fprintf(stderr, "r300: got a VBO with stride 0 fixing up to stide 4\n");
-               vbo->stride = 4;
-           }
-            vbo->max_index =
-                (vbo->buffer->width0 - vbo->buffer_offset) / vbo->stride;
+           /* if no VBO stride then only one vertex value so max index is 1 */
+           /* should think about converting to VS constants like svga does */
+           if (!vbo->stride)
+               vbo->max_index = 1;
+           else
+               vbo->max_index =
+                                (vbo->buffer->width0 - vbo->buffer_offset) / vbo->stride;
         }
 
         max_index = MIN2(vbo->max_index, max_index);
@@ -1347,11 +1372,18 @@ static void r300_bind_vs_state(struct pipe_context* pipe, void* shader)
 
     if (r300->screen->caps.has_tcl) {
         r300->vs_state.dirty = TRUE;
-        r300->vs_state.size = vs->code.length + 9;
+        r300->vs_state.size =
+                vs->code.length + 9 +
+                (vs->immediates_count ? vs->immediates_count * 4 + 3 : 0);
 
-        r300->pvs_flush.dirty = TRUE;
+        if (vs->externals_count) {
+            r300->vs_constants.dirty = TRUE;
+            r300->vs_constants.size = vs->externals_count * 4 + 3;
+        } else {
+            r300->vs_constants.size = 0;
+        }
 
-        r300->dirty_state |= R300_NEW_VERTEX_SHADER_CONSTANTS;
+        r300->pvs_flush.dirty = TRUE;
     } else {
         draw_flush(r300->draw);
         draw_bind_vertex_shader(r300->draw,
@@ -1387,7 +1419,7 @@ static void r300_set_constant_buffer(struct pipe_context *pipe,
 
     switch (shader) {
         case PIPE_SHADER_VERTEX:
-            cbuf = &r300->shader_constants[PIPE_SHADER_VERTEX];
+            cbuf = (struct r300_constant_buffer*)r300->vs_constants.state;
             max_size = 256;
             break;
         case PIPE_SHADER_FRAGMENT:
@@ -1400,6 +1432,7 @@ static void r300_set_constant_buffer(struct pipe_context *pipe,
             break;
         default:
             assert(0);
+            return;
     }
 
     if (buf == NULL || buf->width0 == 0 ||
@@ -1425,7 +1458,9 @@ static void r300_set_constant_buffer(struct pipe_context *pipe,
 
     if (shader == PIPE_SHADER_VERTEX) {
         if (r300->screen->caps.has_tcl) {
-            r300->dirty_state |= R300_NEW_VERTEX_SHADER_CONSTANTS;
+            if (r300->vs_constants.size) {
+                r300->vs_constants.dirty = TRUE;
+            }
             r300->pvs_flush.dirty = TRUE;
         } else if (r300->draw) {
             draw_set_mapped_constant_buffer(r300->draw, PIPE_SHADER_VERTEX,