Merge commit 'origin/perrtblend'
[mesa.git] / src / gallium / drivers / r300 / r300_state.c
index c5e313ce437a11b56eaa809e870f59008684210c..3cdcf94274c041c89110fcf7be67a41137e3039f 100644 (file)
@@ -30,7 +30,6 @@
 #include "tgsi/tgsi_parse.h"
 
 #include "pipe/p_config.h"
-#include "pipe/internal/p_winsys_screen.h"
 
 #include "r300_context.h"
 #include "r300_reg.h"
@@ -488,20 +487,30 @@ static void
     struct r300_context* r300 = r300_context(pipe);
     uint32_t zbuffer_bpp = 0;
 
+    r300->fb_state.size = (10 * state->nr_cbufs) +
+        (2 * (4 - state->nr_cbufs)) +
+        (state->zsbuf ? 10 : 0) + 6;
+
+    if (state->nr_cbufs > 4) {
+        debug_printf("r300: Implementation error: Too many MRTs in %s, "
+            "refusing to bind framebuffer state!\n", __FUNCTION__);
+        return;
+    }
+
     if (r300->draw) {
         draw_flush(r300->draw);
     }
 
-    r300->framebuffer_state = *state;
+    r300->fb_state.state = state;
 
     /* Don't rely on the order of states being set for the first time. */
-    r300->dirty_state |= R300_NEW_FRAMEBUFFERS;
-
+    /* XXX wait what */
     r300->blend_state.dirty = TRUE;
     r300->dsa_state.dirty = TRUE;
+    r300->fb_state.dirty = TRUE;
     r300->scissor_state.dirty = TRUE;
 
-    /* Polyfon offset depends on the zbuffer bit depth. */
+    /* Polygon offset depends on the zbuffer bit depth. */
     if (state->zsbuf && r300->polygon_offset_enabled) {
         switch (util_format_get_blocksize(state->zsbuf->texture->format)) {
             case 2:
@@ -552,7 +561,7 @@ static void r300_bind_fs_state(struct pipe_context* pipe, void* shader)
     r300_pick_fragment_shader(r300);
 
     if (r300->vs && r300_vertex_shader_setup_wpos(r300)) {
-        r300->dirty_state |= R300_NEW_VERTEX_FORMAT;
+        r300->vertex_format_state.dirty = TRUE;
     }
 
     r300->dirty_state |= R300_NEW_FRAGMENT_SHADER | R300_NEW_FRAGMENT_SHADER_CONSTANTS;
@@ -720,7 +729,6 @@ static void r300_bind_rs_state(struct pipe_context* pipe, void* state)
     r300->viewport_state.dirty = TRUE;
 
     /* XXX Clean these up when we move to atom emits */
-    r300->dirty_state |= R300_NEW_RS_BLOCK;
     if (r300->fs && r300->fs->inputs.wpos != ATTR_UNUSED) {
         r300->dirty_state |= R300_NEW_FRAGMENT_SHADER_CONSTANTS;
     }
@@ -921,7 +929,23 @@ static void r300_set_vertex_buffers(struct pipe_context* pipe,
         draw_set_vertex_buffers(r300->draw, count, buffers);
     }
 
-    r300->dirty_state |= R300_NEW_VERTEX_FORMAT;
+    r300->vertex_format_state.dirty = TRUE;
+}
+
+static boolean r300_validate_aos(struct r300_context *r300)
+{
+    struct pipe_vertex_buffer *vbuf = r300->vertex_buffer;
+    struct pipe_vertex_element *velem = r300->vertex_element;
+    int i;
+
+    /* Check if formats and strides are aligned to the size of DWORD. */
+    for (i = 0; i < r300->vertex_element_count; i++) {
+        if (vbuf[velem[i].vertex_buffer_index].stride % 4 != 0 ||
+            util_format_get_blocksize(velem[i].src_format) % 4 != 0) {
+            return FALSE;
+        }
+    }
+    return TRUE;
 }
 
 static void r300_set_vertex_elements(struct pipe_context* pipe,
@@ -939,6 +963,12 @@ static void r300_set_vertex_elements(struct pipe_context* pipe,
         draw_flush(r300->draw);
         draw_set_vertex_elements(r300->draw, count, elements);
     }
+
+    if (!r300_validate_aos(r300)) {
+        /* XXX We should fallback using draw. */
+        assert(0);
+        abort();
+    }
 }
 
 static void* r300_create_vs_state(struct pipe_context* pipe,
@@ -979,9 +1009,10 @@ static void r300_bind_vs_state(struct pipe_context* pipe, void* shader)
             r300_vertex_shader_setup_wpos(r300);
         }
 
+        r300->vertex_format_state.dirty = TRUE;
+
         r300->dirty_state |=
-            R300_NEW_VERTEX_SHADER | R300_NEW_VERTEX_SHADER_CONSTANTS |
-            R300_NEW_VERTEX_FORMAT;
+            R300_NEW_VERTEX_SHADER | R300_NEW_VERTEX_SHADER_CONSTANTS;
     } else {
         draw_flush(r300->draw);
         draw_bind_vertex_shader(r300->draw,