svga: Fix vPos usage
[mesa.git] / src / gallium / drivers / i915 / i915_state_emit.c
index 15350c0a5d710b322b19ae69198b0892a0957384..563c7d07be20994ae88c99cda2b0eb1d54b2b718 100644 (file)
@@ -34,7 +34,9 @@
 
 #include "pipe/p_context.h"
 #include "pipe/p_defines.h"
+#include "pipe/p_format.h"
 
+#include "util/u_format.h"
 #include "util/u_math.h"
 #include "util/u_memory.h"
 
@@ -119,7 +121,7 @@ validate_immediate(struct i915_context *i915, unsigned *batch_space)
                      1 << I915_IMMEDIATE_S5 | 1 << I915_IMMEDIATE_S6) &
                     i915->immediate_dirty;
 
-   if (i915->immediate_dirty & (1 << I915_IMMEDIATE_S0))
+   if (i915->immediate_dirty & (1 << I915_IMMEDIATE_S0) && i915->vbo)
       i915->validation_buffers[i915->num_validation_buffers++] = i915->vbo;
 
    *batch_space = 1 + util_bitcount(dirty);
@@ -128,7 +130,7 @@ validate_immediate(struct i915_context *i915, unsigned *batch_space)
 static void
 emit_immediate(struct i915_context *i915)
 {
-   /* remove unwatned bits and S7 */
+   /* remove unwanted bits and S7 */
    unsigned dirty = (1 << I915_IMMEDIATE_S0 | 1 << I915_IMMEDIATE_S1 |
                      1 << I915_IMMEDIATE_S2 | 1 << I915_IMMEDIATE_S3 |
                      1 << I915_IMMEDIATE_S3 | 1 << I915_IMMEDIATE_S4 |
@@ -173,25 +175,31 @@ emit_dynamic(struct i915_context *i915)
 static void
 validate_static(struct i915_context *i915, unsigned *batch_space)
 {
-   *batch_space = 2 + 5; /* including DRAW_RECT */
+   *batch_space = 0;
 
-   if (i915->current.cbuf_bo) {
+   if (i915->current.cbuf_bo && (i915->static_dirty & I915_DST_BUF_COLOR)) {
       i915->validation_buffers[i915->num_validation_buffers++]
          = i915->current.cbuf_bo;
       *batch_space += 3;
    }
 
-   if (i915->current.depth_bo) {
+   if (i915->current.depth_bo && (i915->static_dirty & I915_DST_BUF_DEPTH)) {
       i915->validation_buffers[i915->num_validation_buffers++]
          = i915->current.depth_bo;
       *batch_space += 3;
    }
+
+   if (i915->static_dirty & I915_DST_VARS)
+      *batch_space += 2;
+
+   if (i915->static_dirty & I915_DST_RECT)
+      *batch_space += 5;
 }
 
 static void
 emit_static(struct i915_context *i915)
 {
-   if (i915->current.cbuf_bo) {
+   if (i915->current.cbuf_bo && (i915->static_dirty & I915_DST_BUF_COLOR)) {
       OUT_BATCH(_3DSTATE_BUF_INFO_CMD);
       OUT_BATCH(i915->current.cbuf_flags);
       OUT_RELOC(i915->current.cbuf_bo,
@@ -201,7 +209,7 @@ emit_static(struct i915_context *i915)
 
    /* What happens if no zbuf??
     */
-   if (i915->current.depth_bo) {
+   if (i915->current.depth_bo && (i915->static_dirty & I915_DST_BUF_DEPTH)) {
       OUT_BATCH(_3DSTATE_BUF_INFO_CMD);
       OUT_BATCH(i915->current.depth_flags);
       OUT_RELOC(i915->current.depth_bo,
@@ -209,7 +217,7 @@ emit_static(struct i915_context *i915)
                 0);
    }
 
-   {
+   if (i915->static_dirty & I915_DST_VARS) {
       OUT_BATCH(_3DSTATE_DST_BUF_VARS_CMD);
       OUT_BATCH(i915->current.dst_buf_vars);
    }
@@ -273,7 +281,7 @@ emit_sampler(struct i915_context *i915)
    if (i915->current.sampler_enable_nr) {
       int i;
 
-      OUT_BATCH( _3DSTATE_SAMPLER_STATE | 
+      OUT_BATCH( _3DSTATE_SAMPLER_STATE |
                  (3 * i915->current.sampler_enable_nr) );
 
       OUT_BATCH( i915->current.sampler_enable_flags );
@@ -335,31 +343,96 @@ emit_constants(struct i915_context *i915)
    }
 }
 
+static const struct
+{
+   enum pipe_format format;
+   uint hw_swizzle;
+} fixup_formats[] = {
+   { PIPE_FORMAT_R8G8B8A8_UNORM, 0x21030000 /* BGRA */},
+   { PIPE_FORMAT_L8_UNORM,       0x00030000 /* RRRA */},
+   { PIPE_FORMAT_I8_UNORM,       0x00030000 /* RRRA */},
+   { PIPE_FORMAT_A8_UNORM,       0x33330000 /* AAAA */},
+   { PIPE_FORMAT_NONE,           0x00000000},
+};
+
+static uint need_target_fixup(struct pipe_surface* p)
+{
+   enum pipe_format f;
+   /* if we don't have a surface bound yet, we don't need to fixup the shader */
+   if (!p)
+      return 0;
+
+   f = p->format;
+   for(int i=0; fixup_formats[i].format != PIPE_FORMAT_NONE; i++)
+      if (fixup_formats[i].format == f)
+         return 1;
+
+   return 0;
+}
+
+static uint fixup_swizzle(enum pipe_format f)
+{
+   for(int i=0; fixup_formats[i].format != PIPE_FORMAT_NONE; i++)
+      if (fixup_formats[i].format == f)
+         return fixup_formats[i].hw_swizzle;
+
+   return 0;
+}
+
 static void
 validate_program(struct i915_context *i915, unsigned *batch_space)
 {
-   *batch_space = i915->fs->program_len;
+   struct pipe_surface *cbuf_surface = i915->framebuffer.cbufs[0];
+   uint additional_size = need_target_fixup(cbuf_surface);
+
+   /* we need more batch space if we want to emulate rgba framebuffers */
+   *batch_space = i915->fs->program_len + 3 * additional_size;
 }
 
 static void
 emit_program(struct i915_context *i915)
 {
-      uint i;
-      /* we should always have, at least, a pass-through program */
-      assert(i915->fs->program_len > 0);
-      for (i = 0; i < i915->fs->program_len; i++) {
-         OUT_BATCH(i915->fs->program[i]);
-      }
+   struct pipe_surface *cbuf_surface = i915->framebuffer.cbufs[0];
+   uint target_fixup = need_target_fixup(cbuf_surface);
+   uint i;
+
+   /* we should always have, at least, a pass-through program */
+   assert(i915->fs->program_len > 0);
+
+   {
+      /* first word has the size, we have to adjust that */
+      uint size = (i915->fs->program[0]);
+      size += target_fixup * 3;
+      OUT_BATCH(size);
+   }
+
+   /* output the declarations of the program */
+   for (i=1 ; i < i915->fs->program_len; i++)
+      OUT_BATCH(i915->fs->program[i]);
+
+   /* we emit an additional mov with swizzle to fake RGBA framebuffers */
+   if (target_fixup) {
+      /* mov out_color, out_color.zyxw */
+      OUT_BATCH(A0_MOV |
+                (REG_TYPE_OC << A0_DEST_TYPE_SHIFT) |
+                A0_DEST_CHANNEL_ALL |
+                (REG_TYPE_OC << A0_SRC0_TYPE_SHIFT) |
+                (T_DIFFUSE << A0_SRC0_NR_SHIFT));
+      OUT_BATCH(fixup_swizzle(cbuf_surface->format));
+      OUT_BATCH(0);
+   }
 }
 
 static void
 emit_draw_rect(struct i915_context *i915)
 {
-   OUT_BATCH(_3DSTATE_DRAW_RECT_CMD);
-   OUT_BATCH(DRAW_RECT_DIS_DEPTH_OFS);
-   OUT_BATCH(i915->current.draw_offset);
-   OUT_BATCH(i915->current.draw_size);
-   OUT_BATCH(i915->current.draw_offset);
+   if (i915->static_dirty & I915_DST_RECT) {
+      OUT_BATCH(_3DSTATE_DRAW_RECT_CMD);
+      OUT_BATCH(DRAW_RECT_DIS_DEPTH_OFS);
+      OUT_BATCH(i915->current.draw_offset);
+      OUT_BATCH(i915->current.draw_size);
+      OUT_BATCH(i915->current.draw_offset);
+   }
 }
 
 static boolean
@@ -405,6 +478,8 @@ i915_emit_hardware_state(struct i915_context *i915 )
    unsigned batch_space;
    uintptr_t save_ptr;
 
+   assert(i915->dirty == 0);
+
    if (I915_DBG_ON(DBG_ATOMS))
       i915_dump_hardware_dirty(i915, __FUNCTION__);
 
@@ -444,5 +519,6 @@ i915_emit_hardware_state(struct i915_context *i915 )
    i915->hardware_dirty = 0;
    i915->immediate_dirty = 0;
    i915->dynamic_dirty = 0;
+   i915->static_dirty = 0;
    i915->flush_dirty = 0;
 }