Merge branch 'gallium-0.1' into gallium-tex-surfaces
[mesa.git] / src / gallium / drivers / i915simple / i915_fpc_translate.c
index 6c1524c768e0c4135f8284543ad0133278a01042..3ccf74c72c46c144bb5ac0cbb0573d23f45ea829 100644 (file)
@@ -33,7 +33,9 @@
 #include "i915_fpc.h"
 
 #include "pipe/p_shader_tokens.h"
+#include "util/u_string.h"
 #include "tgsi/util/tgsi_parse.h"
+#include "tgsi/util/tgsi_dump.h"
 
 #include "draw/draw_vertex.h"
 
@@ -97,19 +99,19 @@ negate(int reg, int x, int y, int z, int w)
 }
 
 
+/**
+ * In the event of a translation failure, we'll generate a simple color
+ * pass-through program.
+ */
 static void
-i915_use_passthrough_shader(struct i915_context *i915)
+i915_use_passthrough_shader(struct i915_fragment_shader *fs)
 {
-   debug_printf("**** Using i915 pass-through fragment shader\n");
-
-   i915->current.program = (uint *) MALLOC(sizeof(passthrough));
-   if (i915->current.program) {
-      memcpy(i915->current.program, passthrough, sizeof(passthrough));
-      i915->current.program_len = Elements(passthrough);
+   fs->program = (uint *) MALLOC(sizeof(passthrough));
+   if (fs->program) {
+      memcpy(fs->program, passthrough, sizeof(passthrough));
+      fs->program_len = Elements(passthrough);
    }
-
-   i915->current.num_constants[PIPE_SHADER_FRAGMENT] = 0;
-   i915->current.num_user_constants[PIPE_SHADER_FRAGMENT] = 0;
+   fs->num_constants = 0;
 }
 
 
@@ -121,7 +123,7 @@ i915_program_error(struct i915_fp_compile *p, const char *msg, ...)
 
    debug_printf("i915_program_error: ");
    va_start( args, msg );  
-   vsprintf( buffer, msg, args );
+   util_vsnprintf( buffer, sizeof(buffer), msg, args );
    va_end( args );
    debug_printf(buffer);
    debug_printf("\n");
@@ -161,11 +163,8 @@ src_vector(struct i915_fp_compile *p,
        * We also use a texture coordinate to pass wpos when possible.
        */
 
-      /* 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];
+      sem_name = p->shader->info.input_semantic_name[index];
+      sem_ind = p->shader->info.input_semantic_index[index];
 
       switch (sem_name) {
       case TGSI_SEMANTIC_POSITION:
@@ -201,7 +200,8 @@ src_vector(struct i915_fp_compile *p,
       break;
 
    case TGSI_FILE_IMMEDIATE:
-      /* XXX unfinished - need to append immediates onto const buffer */
+      assert(index < p->num_immediates);
+      index = p->immediates_map[index];
       /* fall-through */
    case TGSI_FILE_CONSTANT:
       src = UREG(REG_TYPE_CONST, index);
@@ -266,7 +266,7 @@ get_result_vector(struct i915_fp_compile *p,
    switch (dest->DstRegister.File) {
    case TGSI_FILE_OUTPUT:
       {
-         uint sem_name = p->output_semantic_name[dest->DstRegister.Index];
+         uint sem_name = p->shader->info.output_semantic_name[dest->DstRegister.Index];
          switch (sem_name) {
          case TGSI_SEMANTIC_POSITION:
             return UREG(REG_TYPE_OD, 0);
@@ -386,6 +386,26 @@ emit_simple_arith(struct i915_fp_compile *p,
                     arg3 );
 }
 
+
+/** As above, but swap the first two src regs */
+static void
+emit_simple_arith_swap2(struct i915_fp_compile *p,
+                        const struct tgsi_full_instruction *inst,
+                        uint opcode, uint numArgs)
+{
+   struct tgsi_full_instruction inst2;
+
+   assert(numArgs == 2);
+
+   /* transpose first two registers */
+   inst2 = *inst;
+   inst2.FullSrcRegisters[0] = inst->FullSrcRegisters[1];
+   inst2.FullSrcRegisters[1] = inst->FullSrcRegisters[0];
+
+   emit_simple_arith(p, &inst2, opcode, numArgs);
+}
+
+
 #ifndef M_PI
 #define M_PI 3.14159265358979323846
 #endif
@@ -556,8 +576,12 @@ i915_translate_instruction(struct i915_fp_compile *p,
       src0 = src_vector(p, &inst->FullSrcRegisters[0]);
       tmp = i915_get_utemp(p);
 
-      i915_emit_texld(p, tmp, A0_DEST_CHANNEL_ALL,   /* use a dummy dest reg */
-                      0, src0, T0_TEXKILL);
+      i915_emit_texld(p,
+                      tmp,                   /* dest reg: a dummy reg */
+                      A0_DEST_CHANNEL_ALL,   /* dest writemask */
+                      0,                     /* sampler */
+                      src0,                  /* coord*/
+                      T0_TEXKILL);           /* opcode */
       break;
 
    case TGSI_OPCODE_LG2:
@@ -773,6 +797,11 @@ i915_translate_instruction(struct i915_fp_compile *p,
       emit_simple_arith(p, inst, A0_SGE, 2);
       break;
 
+   case TGSI_OPCODE_SLE:
+      /* like SGE, but swap reg0, reg1 */
+      emit_simple_arith_swap2(p, inst, A0_SGE, 2);
+      break;
+
    case TGSI_OPCODE_SIN:
       src0 = src_vector(p, &inst->FullSrcRegisters[0]);
       tmp = i915_get_utemp(p);
@@ -827,6 +856,11 @@ i915_translate_instruction(struct i915_fp_compile *p,
       emit_simple_arith(p, inst, A0_SLT, 2);
       break;
 
+   case TGSI_OPCODE_SGT:
+      /* like SLT, but swap reg0, reg1 */
+      emit_simple_arith_swap2(p, inst, A0_SLT, 2);
+      break;
+
    case TGSI_OPCODE_SUB:
       src0 = src_vector(p, &inst->FullSrcRegisters[0]);
       src1 = src_vector(p, &inst->FullSrcRegisters[1]);
@@ -839,19 +873,17 @@ i915_translate_instruction(struct i915_fp_compile *p,
       break;
 
    case TGSI_OPCODE_TEX:
-      if (inst->FullSrcRegisters[0].SrcRegisterExtSwz.ExtDivide
-          == TGSI_EXTSWIZZLE_W) {
-         emit_tex(p, inst, T0_TEXLDP);
-      }
-      else {
-         emit_tex(p, inst, T0_TEXLD);
-      }
+      emit_tex(p, inst, T0_TEXLD);
       break;
 
    case TGSI_OPCODE_TXB:
       emit_tex(p, inst, T0_TEXLDB);
       break;
 
+   case TGSI_OPCODE_TXP:
+      emit_tex(p, inst, T0_TEXLDP);
+      break;
+
    case TGSI_OPCODE_XPD:
       /* Cross product:
        *      result.x = src0.y * src1.z - src0.z * src1.y;
@@ -880,6 +912,7 @@ i915_translate_instruction(struct i915_fp_compile *p,
 
    default:
       i915_program_error(p, "bad opcode %d", inst->Instruction.Opcode);
+      p->error = 1;
       return;
    }
 
@@ -896,6 +929,7 @@ static void
 i915_translate_instructions(struct i915_fp_compile *p,
                             const struct tgsi_token *tokens)
 {
+   struct i915_fragment_shader *ifs = p->shader;
    struct tgsi_parse_context parse;
 
    tgsi_parse_init( &parse, tokens );
@@ -907,34 +941,64 @@ i915_translate_instructions(struct i915_fp_compile *p,
       switch( parse.FullToken.Token.Type ) {
       case TGSI_TOKEN_TYPE_DECLARATION:
          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;
-            /*debug_printf("FS Input DECL [%u] sem %u\n", ind, sem);*/
-            p->input_semantic_name[ind] = sem;
-            p->input_semantic_index[ind] = semi;
+                  == TGSI_FILE_CONSTANT) {
+            uint i;
+            for (i = parse.FullToken.FullDeclaration.u.DeclarationRange.First;
+                 i <= parse.FullToken.FullDeclaration.u.DeclarationRange.Last;
+                 i++) {
+               assert(ifs->constant_flags[i] == 0x0);
+               ifs->constant_flags[i] = I915_CONSTFLAG_USER;
+               ifs->num_constants = MAX2(ifs->num_constants, i + 1);
+            }
          }
          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;
-            /*debug_printf("FS Output DECL [%u] sem %u\n", ind, sem);*/
-            p->output_semantic_name[ind] = sem;
-            p->output_semantic_index[ind] = semi;
+                  == TGSI_FILE_TEMPORARY) {
+            uint i;
+            for (i = parse.FullToken.FullDeclaration.u.DeclarationRange.First;
+                 i <= parse.FullToken.FullDeclaration.u.DeclarationRange.Last;
+                 i++) {
+               assert(i < I915_MAX_TEMPORARY);
+               /* XXX just use shader->info->file_mask[TGSI_FILE_TEMPORARY] */
+               p->temp_flag |= (1 << i); /* mark temp as used */
+            }
          }
          break;
 
       case TGSI_TOKEN_TYPE_IMMEDIATE:
-         /* XXX append the immediate to the const buffer... */
+         {
+            const struct tgsi_full_immediate *imm
+               = &parse.FullToken.FullImmediate;
+            const uint pos = p->num_immediates++;
+            uint j;
+            for (j = 0; j < imm->Immediate.Size; j++) {
+               p->immediates[pos][j] = imm->u.ImmediateFloat32[j].Float;
+            }
+         }
          break;
 
       case TGSI_TOKEN_TYPE_INSTRUCTION:
+         if (p->first_instruction) {
+            /* resolve location of immediates */
+            uint i, j;
+            for (i = 0; i < p->num_immediates; i++) {
+               /* find constant slot for this immediate */
+               for (j = 0; j < I915_MAX_CONSTANT; j++) {
+                  if (ifs->constant_flags[j] == 0x0) {
+                     memcpy(ifs->constants[j],
+                            p->immediates[i],
+                            4 * sizeof(float));
+                     /*printf("immediate %d maps to const %d\n", i, j);*/
+                     ifs->constant_flags[j] = 0xf;  /* all four comps used */
+                     p->immediates_map[i] = j;
+                     ifs->num_constants = MAX2(ifs->num_constants, j + 1);
+                     break;
+                  }
+               }
+            }
+
+            p->first_instruction = FALSE;
+         }
+
          i915_translate_instruction(p, &parse.FullToken.FullInstruction);
          break;
 
@@ -950,32 +1014,33 @@ i915_translate_instructions(struct i915_fp_compile *p,
 
 static struct i915_fp_compile *
 i915_init_compile(struct i915_context *i915,
-                  const struct pipe_shader_state *fs)
+                  struct i915_fragment_shader *ifs)
 {
    struct i915_fp_compile *p = CALLOC_STRUCT(i915_fp_compile);
 
-   p->shader = i915->fs;
+   p->shader = ifs;
 
-   p->vertex_info = &i915->current.vertex_info;
-
-   /* new constants found during translation get appended after the
-    * user-provided constants.
+   /* Put new constants at end of const buffer, growing downward.
+    * The problem is we don't know how many user-defined constants might
+    * be specified with pipe->set_constant_buffer().
+    * Should pre-scan the user's program to determine the highest-numbered
+    * constant referenced.
     */
-   p->constants = i915->current.constants[PIPE_SHADER_FRAGMENT];
-   p->num_constants = i915->current.num_user_constants[PIPE_SHADER_FRAGMENT];
+   ifs->num_constants = 0;
+   memset(ifs->constant_flags, 0, sizeof(ifs->constant_flags));
+
+   p->first_instruction = TRUE;
 
    p->nr_tex_indirect = 1;      /* correct? */
    p->nr_tex_insn = 0;
    p->nr_alu_insn = 0;
    p->nr_decl_insn = 0;
 
-   memset(p->constant_flags, 0, sizeof(p->constant_flags));
-
    p->csr = p->program;
    p->decl = p->declarations;
    p->decl_s = 0;
    p->decl_t = 0;
-   p->temp_flag = 0xffff000;
+   p->temp_flag = ~0x0 << I915_MAX_TEMPORARY;
    p->utemp_flag = ~0x7;
 
    p->wpos_tex = -1;
@@ -993,6 +1058,7 @@ i915_init_compile(struct i915_context *i915,
 static void
 i915_fini_compile(struct i915_context *i915, struct i915_fp_compile *p)
 {
+   struct i915_fragment_shader *ifs = p->shader;
    unsigned long program_size = (unsigned long) (p->csr - p->program);
    unsigned long decl_size = (unsigned long) (p->decl - p->declarations);
 
@@ -1008,19 +1074,13 @@ 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;
       p->NumNativeTexInstructions = 0;
       p->NumNativeTexIndirections = 0;
 
-      i915_use_passthrough_shader(i915);
+      i915_use_passthrough_shader(ifs);
    }
    else {
       p->NumNativeInstructions
@@ -1034,24 +1094,20 @@ i915_fini_compile(struct i915_context *i915, struct i915_fp_compile *p)
 
       /* Copy compilation results to fragment program struct: 
        */
-      i915->current.program
+      assert(!ifs->program);
+      ifs->program
          = (uint *) MALLOC((program_size + decl_size) * sizeof(uint));
-      if (i915->current.program) {
-         i915->current.program_len = program_size + decl_size;
+      if (ifs->program) {
+         ifs->program_len = program_size + decl_size;
 
-         memcpy(i915->current.program,
+         memcpy(ifs->program,
                 p->declarations, 
                 decl_size * sizeof(uint));
 
-         memcpy(i915->current.program + decl_size, 
+         memcpy(ifs->program + decl_size, 
                 p->program, 
                 program_size * sizeof(uint));
       }
-
-      /* 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: 
@@ -1085,7 +1141,7 @@ 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) {
+   if (p->shader->info.input_semantic_name[0] == TGSI_SEMANTIC_POSITION) {
       /* frag shader using the fragment position input */
 #if 0
       assert(0);
@@ -1106,7 +1162,7 @@ static void
 i915_fixup_depth_write(struct i915_fp_compile *p)
 {
    /* XXX assuming pos/depth is always in output[0] */
-   if (p->shader->output_semantic_name[0] == TGSI_SEMANTIC_POSITION) {
+   if (p->shader->info.output_semantic_name[0] == TGSI_SEMANTIC_POSITION) {
       const uint depth = UREG(REG_TYPE_OD, 0);
 
       i915_emit_arith(p,
@@ -1121,13 +1177,18 @@ i915_fixup_depth_write(struct i915_fp_compile *p)
 
 
 void
-i915_translate_fragment_program( struct i915_context *i915 )
+i915_translate_fragment_program( struct i915_context *i915,
+                                 struct i915_fragment_shader *fs)
 {
-   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, fs);
+   const struct tgsi_token *tokens = fs->state.tokens;
 
    i915_find_wpos_space(p);
 
+#if 0
+   tgsi_dump(tokens, 0);
+#endif
+
    i915_translate_instructions(p, tokens);
    i915_fixup_depth_write(p);