gallivm,draw,llvmpipe: use base ptr + mip offsets instead of mip pointers
[mesa.git] / src / gallium / drivers / i915 / i915_state_emit.c
index 426c683502ac5322d7b495ca2bdd24bf3cb0736e..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"
@@ -151,8 +152,25 @@ emit_immediate(struct i915_context *i915)
    }
 
    for (i = 1; i < I915_MAX_IMMEDIATE; i++) {
-      if (dirty & (1 << i))
-         OUT_BATCH(i915->current.immediate[i]);
+      if (dirty & (1 << i)) {
+         /* Fixup blend function for A8 dst buffers.
+          * When we blend to an A8 buffer, the GPU thinks it's a G8 buffer,
+          * and therefore we need to use the color factor for alphas. */
+         if ((i == I915_IMMEDIATE_S6) &&
+             (i915->current.target_fixup_format == PIPE_FORMAT_A8_UNORM)) {
+            uint32_t imm = i915->current.immediate[i];
+            uint32_t srcRGB = (imm >> S6_CBUF_SRC_BLEND_FACT_SHIFT) & BLENDFACT_MASK;
+            if (srcRGB == BLENDFACT_DST_ALPHA)
+               srcRGB = BLENDFACT_DST_COLR;
+            else if (srcRGB == BLENDFACT_INV_DST_ALPHA)
+               srcRGB = BLENDFACT_INV_DST_COLR;
+            imm &= ~SRC_BLND_FACT(BLENDFACT_MASK);
+            imm |= SRC_BLND_FACT(srcRGB);
+            OUT_BATCH(imm);
+         } else {
+            OUT_BATCH(i915->current.immediate[i]);
+         }
+      }
    }
 }
 
@@ -299,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
@@ -310,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;
 
@@ -346,34 +368,48 @@ emit_constants(struct i915_context *i915)
 static void
 validate_program(struct i915_context *i915, unsigned *batch_space)
 {
-   uint additional_size = i915->current.need_target_fixup;
+   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->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 target_fixup = i915->current.need_target_fixup;
+   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);
 
+   /* output the declarations */
    {
       /* first word has the size, we have to adjust that */
-      uint size = (i915->fs->program[0]);
-      size += target_fixup * 3;
+      uint size = (i915->fs->decl[0]);
+      size += additional_size;
       OUT_BATCH(size);
    }
 
-   /* output the declarations of the program */
-   for (i=1 ; i < i915->fs->program_len; i++)
+   for (i = 1 ; i < i915->fs->decl_len; i++)
+      OUT_BATCH(i915->fs->decl[i]);
+
+   /* output the program */
+   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 (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) |
@@ -408,10 +444,22 @@ i915_validate_state(struct i915_context *i915, unsigned *batch_space)
    else
       *batch_space = 0;
 
+#if 0
+static int counter_total = 0;
+#define VALIDATE_ATOM(atom, hw_dirty) \
+   if (i915->hardware_dirty & hw_dirty) { \
+      static int counter_##atom = 0;\
+      validate_##atom(i915, &tmp); \
+      *batch_space += tmp;\
+      counter_##atom += tmp;\
+      counter_total += tmp;\
+      printf("%s: \t%d/%d \t%2.2f\n",#atom, counter_##atom, counter_total, counter_##atom*100.f/counter_total);}
+#else
 #define VALIDATE_ATOM(atom, hw_dirty) \
    if (i915->hardware_dirty & hw_dirty) { \
       validate_##atom(i915, &tmp); \
       *batch_space += tmp; }
+#endif
    VALIDATE_ATOM(flush, I915_HW_FLUSH);
    VALIDATE_ATOM(immediate, I915_HW_IMMEDIATE);
    VALIDATE_ATOM(dynamic, I915_HW_DYNAMIC);