fix get_result_vector() since fp output slots are not fixed anymore
[mesa.git] / src / mesa / pipe / i915simple / i915_fpc_translate.c
index 6583cbfa2800c70a41249b2d060bfbd0c03cf708..f34225bfedcaae46c97442f8ccd8d5ce489eb293 100644 (file)
 #include "i915_context.h"
 #include "i915_fpc.h"
 
-#include "pipe/tgsi/core/tgsi_token.h"
-#include "pipe/tgsi/core/tgsi_parse.h"
+#include "pipe/tgsi/exec/tgsi_token.h"
+#include "pipe/tgsi/exec/tgsi_parse.h"
+
+#include "pipe/draw/draw_vertex.h"
+
 
 /**
  * Simple pass-through fragment shader to use when we don't have
@@ -77,17 +80,33 @@ static const float cos_constants[4] = { 1.0,
 
 
 
+/**
+ * component-wise negation of ureg
+ */
+static INLINE int
+negate(int reg, int x, int y, int z, int w)
+{
+   /* Another neat thing about the UREG representation */
+   return reg ^ (((x & 1) << UREG_CHANNEL_X_NEGATE_SHIFT) |
+                 ((y & 1) << UREG_CHANNEL_Y_NEGATE_SHIFT) |
+                 ((z & 1) << UREG_CHANNEL_Z_NEGATE_SHIFT) |
+                 ((w & 1) << UREG_CHANNEL_W_NEGATE_SHIFT));
+}
+
+
 static void
 i915_use_passthrough_shader(struct i915_context *i915)
 {
    fprintf(stderr, "**** Using i915 pass-through fragment shader\n");
 
    i915->current.program = (uint *) malloc(sizeof(passthrough));
-   memcpy(i915->current.program, passthrough, sizeof(passthrough));
-   i915->current.program_len = Elements(passthrough);
+   if (i915->current.program) {
+      memcpy(i915->current.program, passthrough, sizeof(passthrough));
+      i915->current.program_len = Elements(passthrough);
+   }
 
-   i915->current.constants = NULL;
-   i915->current.num_constants = 0;
+   i915->current.num_constants[PIPE_SHADER_FRAGMENT] = 0;
+   i915->current.num_user_constants[PIPE_SHADER_FRAGMENT] = 0;
 }
 
 
@@ -108,8 +127,8 @@ static uint
 src_vector(struct i915_fp_compile *p,
            const struct tgsi_full_src_register *source)
 {
-   const uint index = source->SrcRegister.Index;
-   uint src;
+   uint index = source->SrcRegister.Index;
+   uint src, sem_name, sem_ind;
 
    switch (source->SrcRegister.File) {
    case TGSI_FILE_TEMPORARY:
@@ -129,34 +148,40 @@ src_vector(struct i915_fp_compile *p,
        * 
        * We also use a texture coordinate to pass wpos when possible.
        */
-      switch (index) {
-      case FRAG_ATTRIB_WPOS:
+
+      /* use vertex format info to map a slot number to a VF attrib */
+      assert(index < p->vertex_info->num_attribs);
+
+      sem_name = p->input_semantic_name[index];
+      sem_ind = p->input_semantic_index[index];
+
+      switch (sem_name) {
+      case TGSI_SEMANTIC_POSITION:
+         printf("SKIP SEM POS\n");
+         /*
+         assert(p->wpos_tex != -1);
          src = i915_emit_decl(p, REG_TYPE_T, p->wpos_tex, D0_CHANNEL_ALL);
+         */
          break;
-      case FRAG_ATTRIB_COL0:
-         src = i915_emit_decl(p, REG_TYPE_T, T_DIFFUSE, D0_CHANNEL_ALL);
-         break;
-      case FRAG_ATTRIB_COL1:
-         src = i915_emit_decl(p, REG_TYPE_T, T_SPECULAR, D0_CHANNEL_XYZ);
-         src = swizzle(src, X, Y, Z, ONE);
+      case TGSI_SEMANTIC_COLOR:
+         if (sem_ind == 0) {
+            src = i915_emit_decl(p, REG_TYPE_T, T_DIFFUSE, D0_CHANNEL_ALL);
+         }
+         else {
+            /* secondary color */
+            assert(sem_ind == 1);
+            src = i915_emit_decl(p, REG_TYPE_T, T_SPECULAR, D0_CHANNEL_XYZ);
+            src = swizzle(src, X, Y, Z, ONE);
+         }
          break;
-      case FRAG_ATTRIB_FOGC:
+      case TGSI_SEMANTIC_FOG:
          src = i915_emit_decl(p, REG_TYPE_T, T_FOG_W, D0_CHANNEL_W);
          src = swizzle(src, W, W, W, W);
          break;
-      case FRAG_ATTRIB_TEX0:
-      case FRAG_ATTRIB_TEX1:
-      case FRAG_ATTRIB_TEX2:
-      case FRAG_ATTRIB_TEX3:
-      case FRAG_ATTRIB_TEX4:
-      case FRAG_ATTRIB_TEX5:
-      case FRAG_ATTRIB_TEX6:
-      case FRAG_ATTRIB_TEX7:
-         src = i915_emit_decl(p, REG_TYPE_T,
-                              T_TEX0 + (index - FRAG_ATTRIB_TEX0),
-                              D0_CHANNEL_ALL);
+      case TGSI_SEMANTIC_GENERIC:
+         /* usually a texcoord */
+         src = i915_emit_decl(p, REG_TYPE_T, T_TEX0 + sem_ind, D0_CHANNEL_ALL);
          break;
-
       default:
          i915_program_error(p, "Bad source->Index");
          return 0;
@@ -196,9 +221,12 @@ src_vector(struct i915_fp_compile *p,
    }
 
    /* no abs() or post-abs negation */
+#if 0
+   /* XXX assertions disabled to allow arbfplight.c to run */
+   /* XXX enable these assertions, or fix things */
    assert(!source->SrcRegisterExtMod.Absolute);
    assert(!source->SrcRegisterExtMod.Negate);
-
+#endif
    return src;
 }
 
@@ -212,14 +240,17 @@ get_result_vector(struct i915_fp_compile *p,
 {
    switch (dest->DstRegister.File) {
    case TGSI_FILE_OUTPUT:
-      switch (dest->DstRegister.Index) {
-      case 1: /*COLOR*/  /*FRAG_RESULT_COLR:*/
-         return UREG(REG_TYPE_OC, 0);
-      case 0: /*DEPTH*/  /*FRAG_RESULT_DEPR:*/
-         return UREG(REG_TYPE_OD, 0);
-      default:
-         i915_program_error(p, "Bad inst->DstReg.Index");
-         return 0;
+      {
+         uint sem_name = p->output_semantic_name[dest->DstRegister.Index];
+         switch (sem_name) {
+         case TGSI_SEMANTIC_POSITION:
+            return UREG(REG_TYPE_OD, 0);
+         case TGSI_SEMANTIC_COLOR:
+            return UREG(REG_TYPE_OC, 0);
+         default:
+            i915_program_error(p, "Bad inst->DstReg.Index/semantics");
+            return 0;
+         }
       }
    case TGSI_FILE_TEMPORARY:
       return UREG(REG_TYPE_R, dest->DstRegister.Index);
@@ -458,6 +489,10 @@ i915_translate_instruction(struct i915_fp_compile *p,
                       swizzle(src1, ONE, Y, ONE, W), 0);
       break;
 
+   case TGSI_OPCODE_END:
+      /* no-op */
+      break;
+
    case TGSI_OPCODE_EX2:
       src0 = src_vector(p, &inst->FullSrcRegisters[0]);
 
@@ -824,7 +859,28 @@ i915_translate_instructions(struct i915_fp_compile *p,
 
       switch( parse.FullToken.Token.Type ) {
       case TGSI_TOKEN_TYPE_DECLARATION:
-         /* XXX no-op? */
+         if (parse.FullToken.FullDeclaration.Declaration.File
+             == TGSI_FILE_INPUT) {
+            /* save input register info for use in src_vector() */
+            uint ind, sem, semi;
+            ind = parse.FullToken.FullDeclaration.u.DeclarationRange.First;
+            sem = parse.FullToken.FullDeclaration.Semantic.SemanticName;
+            semi = parse.FullToken.FullDeclaration.Semantic.SemanticIndex;
+            /*printf("FS Input DECL [%u] sem %u\n", ind, sem);*/
+            p->input_semantic_name[ind] = sem;
+            p->input_semantic_index[ind] = semi;
+         }
+         else if (parse.FullToken.FullDeclaration.Declaration.File
+             == TGSI_FILE_OUTPUT) {
+            /* save output register info for use in get_result_vector() */
+            uint ind, sem, semi;
+            ind = parse.FullToken.FullDeclaration.u.DeclarationRange.First;
+            sem = parse.FullToken.FullDeclaration.Semantic.SemanticName;
+            semi = parse.FullToken.FullDeclaration.Semantic.SemanticIndex;
+            /*printf("FS Output DECL [%u] sem %u\n", ind, sem);*/
+            p->output_semantic_name[ind] = sem;
+            p->output_semantic_index[ind] = semi;
+         }
          break;
 
       case TGSI_TOKEN_TYPE_IMMEDIATE:
@@ -848,17 +904,19 @@ i915_translate_instructions(struct i915_fp_compile *p,
 
 static struct i915_fp_compile *
 i915_init_compile(struct i915_context *i915,
-                  struct pipe_shader_state *fs)
+                  const struct pipe_shader_state *fs)
 {
    struct i915_fp_compile *p = CALLOC_STRUCT(i915_fp_compile);
 
-   p->shader = &i915->fs;
+   p->shader = i915->fs;
+
+   p->vertex_info = &i915->current.vertex_info;
 
-   /* a bit of a hack, need to improve constant buffer infrastructure */
-   if (i915->fs.constants)
-      p->constants = i915->fs.constants;
-   else
-      p->constants = &i915->temp_constants;
+   /* new constants found during translation get appended after the
+    * user-provided constants.
+    */
+   p->constants = i915->current.constants[PIPE_SHADER_FRAGMENT];
+   p->num_constants = i915->current.num_user_constants[PIPE_SHADER_FRAGMENT];
 
    p->nr_tex_indirect = 1;      /* correct? */
    p->nr_tex_insn = 0;
@@ -882,6 +940,7 @@ i915_init_compile(struct i915_context *i915,
    return p;
 }
 
+
 /* Copy compile results to the fragment program struct and destroy the
  * compilation context.
  */
@@ -903,6 +962,12 @@ i915_fini_compile(struct i915_context *i915, struct i915_fp_compile *p)
    if (p->nr_decl_insn > I915_MAX_DECL_INSN)
       i915_program_error(p, "Exceeded max DECL instructions");
 
+   /* free old program, if present */
+   if (i915->current.program) {
+      free(i915->current.program);
+      i915->current.program_len = 0;
+   }
+
    if (p->error) {
       p->NumNativeInstructions = 0;
       p->NumNativeAluInstructions = 0;
@@ -912,9 +977,8 @@ i915_fini_compile(struct i915_context *i915, struct i915_fp_compile *p)
       i915_use_passthrough_shader(i915);
    }
    else {
-      p->NumNativeInstructions = (p->nr_alu_insn +
-                                      p->nr_tex_insn +
-                                      p->nr_decl_insn);
+      p->NumNativeInstructions
+         = p->nr_alu_insn + p->nr_tex_insn + p->nr_decl_insn;
       p->NumNativeAluInstructions = p->nr_alu_insn;
       p->NumNativeTexInstructions = p->nr_tex_insn;
       p->NumNativeTexIndirections = p->nr_tex_indirect;
@@ -926,18 +990,22 @@ i915_fini_compile(struct i915_context *i915, struct i915_fp_compile *p)
        */
       i915->current.program
          = (uint *) malloc((program_size + decl_size) * sizeof(uint));
-      i915->current.program_len = program_size + decl_size;
+      if (i915->current.program) {
+         i915->current.program_len = program_size + decl_size;
 
-      memcpy(i915->current.program,
-             p->declarations, 
-             decl_size * sizeof(uint));
+         memcpy(i915->current.program,
+                p->declarations, 
+                decl_size * sizeof(uint));
 
-      memcpy(i915->current.program + decl_size, 
-             p->program, 
-             program_size * sizeof(uint));
+         memcpy(i915->current.program + decl_size, 
+                p->program, 
+                program_size * sizeof(uint));
+      }
 
-      i915->current.constants = (uint *) p->constants->constant;
-      i915->current.num_constants = p->constants->nr_constants;
+      /* update number of constants */
+      i915->current.num_constants[PIPE_SHADER_FRAGMENT] = p->num_constants;
+      assert(i915->current.num_constants[PIPE_SHADER_FRAGMENT]
+             >= i915->current.num_user_constants[PIPE_SHADER_FRAGMENT]);
    }
 
    /* Release the compilation struct: 
@@ -953,14 +1021,16 @@ i915_fini_compile(struct i915_context *i915, struct i915_fp_compile *p)
 static void
 i915_find_wpos_space(struct i915_fp_compile *p)
 {
-   const uint inputs = p->shader->inputs_read;
+#if 0
+   const uint inputs
+      = p->shader->inputs_read | (1 << TGSI_ATTRIB_POS); /*XXX hack*/
    uint i;
 
    p->wpos_tex = -1;
 
-   if (inputs & FRAG_BIT_WPOS) {
+   if (inputs & (1 << TGSI_ATTRIB_POS)) {
       for (i = 0; i < I915_TEX_UNITS; i++) {
-        if ((inputs & (FRAG_BIT_TEX0 << i)) == 0) {
+        if ((inputs & (1 << (TGSI_ATTRIB_TEX0 + i))) == 0) {
            p->wpos_tex = i;
            return;
         }
@@ -968,6 +1038,14 @@ i915_find_wpos_space(struct i915_fp_compile *p)
 
       i915_program_error(p, "No free texcoord for wpos value");
    }
+#else
+   if (p->shader->input_semantic_name[0] == TGSI_SEMANTIC_POSITION) {
+      /* frag shader using the fragment position input */
+#if 0
+      assert(0);
+#endif
+   }
+#endif
 }
 
 
@@ -981,13 +1059,17 @@ i915_find_wpos_space(struct i915_fp_compile *p)
 static void
 i915_fixup_depth_write(struct i915_fp_compile *p)
 {
-   if (p->shader->outputs_written & (1<<FRAG_RESULT_DEPR)) {
-      uint depth = UREG(REG_TYPE_OD, 0);
+   /* XXX assuming pos/depth is always in output[0] */
+   if (p->shader->output_semantic_name[0] == TGSI_SEMANTIC_POSITION) {
+      const uint depth = UREG(REG_TYPE_OD, 0);
 
       i915_emit_arith(p,
-                      A0_MOV,
-                      depth, A0_DEST_CHANNEL_W, 0,
-                      swizzle(depth, X, Y, Z, Z), 0, 0);
+                      A0_MOV,                     /* opcode */
+                      depth,                      /* dest reg */
+                      A0_DEST_CHANNEL_W,          /* write mask */
+                      0,                          /* saturate? */
+                      swizzle(depth, X, Y, Z, Z), /* src0 */
+                      0, 0 /* src1, src2 */);
    }
 }
 
@@ -995,8 +1077,8 @@ i915_fixup_depth_write(struct i915_fp_compile *p)
 void
 i915_translate_fragment_program( struct i915_context *i915 )
 {
-   struct i915_fp_compile *p = i915_init_compile(i915, &i915->fs);
-   const struct tgsi_token *tokens = i915->fs.tokens;
+   struct i915_fp_compile *p = i915_init_compile(i915, i915->fs);
+   const struct tgsi_token *tokens = i915->fs->tokens;
 
    i915_find_wpos_space(p);