draw: Properly limit vertex buffer fetches on draw arrays.
[mesa.git] / src / gallium / drivers / i915 / i915_state_emit.c
index 8ab8fb8cd7474529b35527bdbff72b7c541df224..590a1baa42093213dd83cb2cd62918c5c4e04a72 100644 (file)
@@ -30,6 +30,7 @@
 #include "i915_context.h"
 #include "i915_batch.h"
 #include "i915_debug.h"
+#include "i915_fpc.h"
 #include "i915_resource.h"
 
 #include "pipe/p_context.h"
@@ -316,8 +317,10 @@ emit_sampler(struct i915_context *i915)
 static void
 validate_constants(struct i915_context *i915, unsigned *batch_space)
 {
-   *batch_space = i915->fs->num_constants ?
+   int nr = i915->fs->num_constants ?
       2 + 4*i915->fs->num_constants : 0;
+
+   *batch_space = nr;
 }
 
 static void
@@ -327,6 +330,8 @@ emit_constants(struct i915_context *i915)
     * immediates according to the constant_flags[] array.
     */
    const uint nr = i915->fs->num_constants;
+
+   assert(nr < I915_MAX_CONSTANT);
    if (nr) {
       uint i;
 
@@ -363,18 +368,24 @@ emit_constants(struct i915_context *i915)
 static void
 validate_program(struct i915_context *i915, unsigned *batch_space)
 {
-   uint additional_size = i915->current.target_fixup_format ? 1 : 0;
+   uint additional_size = 0;
+
+   additional_size += i915->current.target_fixup_format ? 3 : 0;
 
    /* we need more batch space if we want to emulate rgba framebuffers */
-   *batch_space = i915->fs->decl_len + i915->fs->program_len + 3 * additional_size;
+   *batch_space = i915->fs->decl_len + i915->fs->program_len + additional_size;
 }
 
 static void
 emit_program(struct i915_context *i915)
 {
-   uint need_target_fixup = i915->current.target_fixup_format ? 1 : 0;
+   uint additional_size = 0;
    uint i;
 
+   /* count how much additional space we'll need */
+   validate_program(i915, &additional_size);
+   additional_size -= i915->fs->decl_len + i915->fs->program_len;
+
    /* we should always have, at least, a pass-through program */
    assert(i915->fs->program_len > 0);
 
@@ -382,7 +393,7 @@ emit_program(struct i915_context *i915)
    {
       /* first word has the size, we have to adjust that */
       uint size = (i915->fs->decl[0]);
-      size += need_target_fixup * 3;
+      size += additional_size;
       OUT_BATCH(size);
    }
 
@@ -390,11 +401,15 @@ emit_program(struct i915_context *i915)
       OUT_BATCH(i915->fs->decl[i]);
 
    /* output the program */
-   for (i = 0 ; i < i915->fs->program_len; i++)
+   assert(i915->fs->program_len % 3 == 0);
+   for (i = 0 ; i < i915->fs->program_len; i+=3) {
       OUT_BATCH(i915->fs->program[i]);
+      OUT_BATCH(i915->fs->program[i+1]);
+      OUT_BATCH(i915->fs->program[i+2]);
+   }
 
    /* we emit an additional mov with swizzle to fake RGBA framebuffers */
-   if (need_target_fixup) {
+   if (i915->current.target_fixup_format) {
       /* mov out_color, out_color.zyxw */
       OUT_BATCH(A0_MOV |
                 (REG_TYPE_OC << A0_DEST_TYPE_SHIFT) |