OSDN Git Service

Fragment shader translation seems to basically work now. More testing needed.
authorBrian <brian.paul@tungstengraphics.com>
Wed, 22 Aug 2007 02:13:31 +0000 (20:13 -0600)
committerBrian <brian.paul@tungstengraphics.com>
Wed, 22 Aug 2007 02:18:58 +0000 (20:18 -0600)
src/mesa/pipe/i915simple/Makefile
src/mesa/pipe/i915simple/i915_context.h
src/mesa/pipe/i915simple/i915_fpc.c
src/mesa/pipe/i915simple/i915_fpc.h
src/mesa/pipe/i915simple/i915_fpc_translate.c
src/mesa/pipe/i915simple/i915_state.c
src/mesa/pipe/i915simple/i915_state_derived.c
src/mesa/pipe/i915simple/i915_state_emit.c

index fc825c7..2353d0d 100644 (file)
@@ -22,7 +22,6 @@ DRIVER_SOURCES = \
        i915_strings.c \
        i915_prim_emit.c \
        i915_tex_layout.c \
-       i915_fpc.c \
        i915_fpc_debug.c \
        i915_fpc_emit.c \
        i915_fpc_translate.c \
index a3927bf..bc00d61 100644 (file)
@@ -84,6 +84,11 @@ struct i915_state
 {
    unsigned immediate[I915_MAX_IMMEDIATE];
    unsigned dynamic[I915_MAX_DYNAMIC];
+
+   uint *program;
+   uint program_len;
+   uint *constants;
+   uint num_constants;
    
    unsigned id;                        /* track lost context events */
 };
@@ -115,6 +120,8 @@ struct i915_context
    struct pipe_viewport_state viewport;
    struct pipe_vertex_buffer vertex_buffer[PIPE_ATTRIB_MAX];
 
+   struct pipe_constant_buffer temp_constants; /*XXX temporary*/
+
    unsigned dirty;
 
    unsigned *batch_start;
index fd0bbbc..3bf2231 100644 (file)
 
 #include "i915_fpc.h"
 
-
-
-void
-i915_program_error(struct i915_fp_compile *p, const char *msg)
-{
-   fprintf(stderr, "i915_program_error: %s", msg);
-   p->fp->error = 1;
-}
-
-
-static struct i915_fp_compile *
-i915_init_compile(struct i915_context *i915, struct i915_fragment_program *fp)
-{
-   struct i915_fp_compile *p = CALLOC_STRUCT(i915_fp_compile);
-
-   p->fp = fp;
-#if 0
-   p->env_param = NULL; /*i915->intel.ctx.FragmentProgram.Parameters;*/
-#endif
-   p->constants = i915->fs.constants;
-   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->utemp_flag = ~0x7;
-
-#if 0
-   p->fp->translated = 0;
-   p->fp->error = 0;
-   p->fp->nr_constants = 0;
-#endif
-   p->fp->wpos_tex = -1;
-   p->fp->nr_params = 0;
-
-   *(p->decl++) = _3DSTATE_PIXEL_SHADER_PROGRAM;
-
-   return p;
-}
-
-/* Copy compile results to the fragment program struct and destroy the
- * compilation context.
- */
-static void
-i915_fini_compile(struct i915_fp_compile *p)
-{
-   uint program_size = p->csr - p->program;
-   uint decl_size = p->decl - p->declarations;
-
-   if (p->nr_tex_indirect > I915_MAX_TEX_INDIRECT)
-      i915_program_error(p, "Exceeded max nr indirect texture lookups");
-
-   if (p->nr_tex_insn > I915_MAX_TEX_INSN)
-      i915_program_error(p, "Exceeded max TEX instructions");
-
-   if (p->nr_alu_insn > I915_MAX_ALU_INSN)
-      i915_program_error(p, "Exceeded max ALU instructions");
-
-   if (p->nr_decl_insn > I915_MAX_DECL_INSN)
-      i915_program_error(p, "Exceeded max DECL instructions");
-
-   if (p->fp->error) {
-      p->fp->NumNativeInstructions = 0;
-      p->fp->NumNativeAluInstructions = 0;
-      p->fp->NumNativeTexInstructions = 0;
-      p->fp->NumNativeTexIndirections = 0;
-      return;
-   }
-   else {
-      p->fp->NumNativeInstructions = (p->nr_alu_insn +
-                                      p->nr_tex_insn +
-                                      p->nr_decl_insn);
-      p->fp->NumNativeAluInstructions = p->nr_alu_insn;
-      p->fp->NumNativeTexInstructions = p->nr_tex_insn;
-      p->fp->NumNativeTexIndirections = p->nr_tex_indirect;
-   }
-
-   p->declarations[0] |= program_size + decl_size - 2;
-
-   /* Copy compilation results to fragment program struct: 
-    */
-   memcpy(p->fp->program, 
-         p->declarations, 
-         decl_size * sizeof(uint));
-
-   memcpy(p->fp->program + decl_size, 
-         p->program, 
-         program_size * sizeof(uint));
-      
-   p->fp->program_size = program_size + decl_size;
-
-   /* Release the compilation struct: 
-    */
-   free(p);
-}
-
-
-/**
- * Find an unused texture coordinate slot to use for fragment WPOS.
- * Update p->fp->wpos_tex with the result (-1 if no used texcoord slot is found).
- */
-static void
-find_wpos_space(struct i915_fp_compile *p)
-{
-   const uint inputs = p->shader->inputs_read;
-   uint i;
-
-   p->fp->wpos_tex = -1;
-
-   if (inputs & FRAG_BIT_WPOS) {
-      for (i = 0; i < I915_TEX_UNITS; i++) {
-        if ((inputs & (FRAG_BIT_TEX0 << i)) == 0) {
-           p->fp->wpos_tex = i;
-           return;
-        }
-      }
-
-      i915_program_error(p, "No free texcoord for wpos value");
-   }
-}
-
-
-
-void i915_compile_fragment_program( struct i915_context *i915,
-                                   struct i915_fragment_program *fp )
-{
-   struct i915_fp_compile *p = i915_init_compile(i915, fp);
-   struct tgsi_token *tokens = i915->fs.tokens;
-
-   find_wpos_space(p);
-
-   i915_translate_program(p, tokens);
-   i915_fixup_depth_write(p);
-
-   i915_fini_compile(p);
-#if 0
-   fp->translated = 1;
-#endif
-}
index 0a8bffc..1acb69e 100644 (file)
@@ -90,71 +90,10 @@ enum
 
 
 
-#if 1 /*XXX temp */
-/* Hardware version of a parsed fragment program.  "Derived" from the
- * mesa fragment_program struct.
- */
-struct i915_fragment_program
-{
-#if 0
-   struct gl_fragment_program Base;
-#else
-   uint NumNativeInstructions;
-   uint NumNativeAluInstructions;
-   uint NumNativeTexInstructions;
-   uint NumNativeTexIndirections;
-#endif
-
-   boolean error;      /**< Set if i915_program_error() is called */
-#if 0
-   uint id;            /**< String id */
-   boolean translated;
-#endif
-
-   /* Decls + instructions: 
-    */
-   uint program[I915_PROGRAM_SIZE];
-   uint program_size;
-   
-#if 0
-   /* Constant buffer:
-    */
-   float constant[I915_MAX_CONSTANT][4];
-   uint nr_constants;
-#endif
-
-   /* Some of which are parameters: 
-    */
-   struct
-   {
-      uint reg;               /* Hardware constant idx */
-      const float *values;    /* Pointer to tracked values */
-   } param[I915_MAX_CONSTANT];
-   uint nr_params;
-
-#if 0
-   uint param_state;
-#endif
-   uint wpos_tex;
-};
-#endif
-
-
-/***********************************************************************
- * Public interface for the compiler
- */
-
-void i915_compile_fragment_program( struct i915_context *i915,
-                                   struct i915_fragment_program *fp );
-
-
-/***********************************************************************
- * Private details of the compiler
+/**
+ * Program translation state
  */
-
 struct i915_fp_compile {
-   struct i915_fragment_program *fp;
-
    struct pipe_shader_state *shader;
 
    uint declarations[I915_PROGRAM_SIZE];
@@ -186,9 +125,12 @@ struct i915_fp_compile {
    uint nr_alu_insn;
    uint nr_decl_insn;
 
-#if 0
-   float (*env_param)[4];
-#endif
+   boolean error;      /**< Set if i915_program_error() is called */
+   uint wpos_tex;
+   uint NumNativeInstructions;
+   uint NumNativeAluInstructions;
+   uint NumNativeTexInstructions;
+   uint NumNativeTexIndirections;
 };
 
 
@@ -268,6 +210,14 @@ negate(int reg, int x, int y, int z, int w)
 }
 
 
+
+/***********************************************************************
+ * Public interface for the compiler
+ */
+extern void i915_translate_fragment_program( struct i915_context *i915 );
+
+
+
 extern uint i915_get_temp(struct i915_fp_compile *p);
 extern uint i915_get_utemp(struct i915_fp_compile *p);
 extern void i915_release_utemps(struct i915_fp_compile *p);
@@ -302,38 +252,21 @@ extern uint i915_emit_const4f(struct i915_fp_compile *p,
                                 float c2, float c3);
 
 
-#if 0
-extern uint i915_emit_param4fv(struct i915_fp_compile *p,
-                                 const float * values);
-#endif
-
-
-
-/*======================================================================
- * i915_fpc_debug.c
- */
-extern void i915_program_error(struct i915_fp_compile *p,
-                               const char *msg);
-
-
 /*======================================================================
  * i915_fpc_debug.c
  */
 extern void i915_disassemble_program(const uint * program, uint sz);
 
-#if 0
-extern void i915_print_mesa_instructions( const struct prog_instruction *insn,
-                                         uint nr );
-#endif
 
 /*======================================================================
  * i915_fpc_translate.c
  */
-void i915_fixup_depth_write(struct i915_fp_compile *p);
 
 extern void
-i915_translate_program(struct i915_fp_compile *p, const struct tgsi_token *token);
+i915_program_error(struct i915_fp_compile *p, const char *msg);
 
+extern void
+i915_translate_fragment_program(struct i915_context *i915);
 
 
 #endif
index db6b92a..cf6a142 100644 (file)
 #include "pipe/tgsi/core/tgsi_token.h"
 #include "pipe/tgsi/core/tgsi_parse.h"
 
+/**
+ * Simple pass-through fragment shader to use when we don't have
+ * a real shader (or it fails to compile for some reason).
+ */
+static unsigned passthrough[] = 
+{
+   _3DSTATE_PIXEL_SHADER_PROGRAM | ((2*3)-1),
+
+   /* declare input color:
+    */
+   (D0_DCL | 
+    (REG_TYPE_T << D0_TYPE_SHIFT) | 
+    (T_DIFFUSE << D0_NR_SHIFT) | 
+    D0_CHANNEL_ALL),
+   0,
+   0,
+
+   /* move to output color:
+    */
+   (A0_MOV | 
+    (REG_TYPE_OC << A0_DEST_TYPE_SHIFT) | 
+    A0_DEST_CHANNEL_ALL | 
+    (REG_TYPE_T << A0_SRC0_TYPE_SHIFT) |
+    (T_DIFFUSE << A0_SRC0_NR_SHIFT)),
+   0x01230000,                 /* .xyzw */
+   0
+};
+
 
 /* 1, -1/3!, 1/5!, -1/7! */
 static const float sin_constants[4] = { 1.0,
@@ -48,6 +76,30 @@ static const float cos_constants[4] = { 1.0,
 };
 
 
+
+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);
+
+   i915->current.constants = NULL;
+   i915->current.num_constants = 0;
+}
+
+
+void
+i915_program_error(struct i915_fp_compile *p, const char *msg)
+{
+   fprintf(stderr, "i915_program_error: %s\n", msg);
+   p->error = 1;
+}
+
+
+
 /**
  * Construct a ureg for the given source register.  Will emit
  * constants, apply swizzling and negation as needed.
@@ -59,7 +111,7 @@ src_vector(struct i915_fp_compile *p,
    const uint index = source->SrcRegister.Index;
    uint src;
 
-   switch (source->SrcRegisterInd.File) {
+   switch (source->SrcRegister.File) {
    case TGSI_FILE_TEMPORARY:
       if (source->SrcRegister.Index >= I915_MAX_TEMPORARY) {
          i915_program_error(p, "Exceeded max temporary reg");
@@ -79,7 +131,7 @@ src_vector(struct i915_fp_compile *p,
        */
       switch (index) {
       case FRAG_ATTRIB_WPOS:
-         src = i915_emit_decl(p, REG_TYPE_T, p->fp->wpos_tex, D0_CHANNEL_ALL);
+         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);
@@ -111,27 +163,9 @@ src_vector(struct i915_fp_compile *p,
       }
       break;
 
-      /* Various parameters and env values.  All emitted to
-       * hardware as program constants.
-       */
-#if 0
-   case PROGRAM_LOCAL_PARAM:
-      src = i915_emit_param4fv(p, program->Base.LocalParams[index]);
-      break;
-   case PROGRAM_ENV_PARAM:
-      src = i915_emit_param4fv(p, p->env_param[index]);
-      break;
-   case PROGRAM_CONSTANT:
-   case PROGRAM_STATE_VAR:
-   case PROGRAM_NAMED_PARAM:
-      src = i915_emit_param4fv(
-        p, program->Base.Parameters->ParameterValues[index]);
-      break;
-#else
    case TGSI_FILE_CONSTANT:
       src = UREG(REG_TYPE_CONST, index);
       break;
-#endif
 
    default:
       i915_program_error(p, "Bad source->File");
@@ -151,26 +185,14 @@ src_vector(struct i915_fp_compile *p,
    assert(!source->SrcRegisterExtSwz.NegateW);
    assert(!source->SrcRegisterExtMod.Absolute);
    assert(!source->SrcRegisterExtMod.Negate);
-#if 0
-   if (source->SrcRegister.Negate)
-      negate all 
-
-   if (extended source swiz per component)
-      src = negate(src,
-                   source->SrcRegisterExtSwz.NegateX,
-                   source->SrcRegisterExtSwz.NegateY,
-                   source->SrcRegisterExtSwz.NegateZ,
-                   source->SrcRegisterExtSwz.NegateW);
-   if (mod.abs)
-      absolute value
-
-   if (mod.negate)
-      another negate;
-#endif
+
    return src;
 }
 
 
+/**
+ * Construct a ureg for a destination register.
+ */
 static uint
 get_result_vector(struct i915_fp_compile *p,
                   const struct tgsi_full_dst_register *dest)
@@ -178,9 +200,9 @@ get_result_vector(struct i915_fp_compile *p,
    switch (dest->DstRegister.File) {
    case TGSI_FILE_OUTPUT:
       switch (dest->DstRegister.Index) {
-      case FRAG_RESULT_COLR:
+      case 1: /*COLOR*/  /*FRAG_RESULT_COLR:*/
          return UREG(REG_TYPE_OC, 0);
-      case FRAG_RESULT_DEPR:
+      case 0: /*DEPTH*/  /*FRAG_RESULT_DEPR:*/
          return UREG(REG_TYPE_OD, 0);
       default:
          i915_program_error(p, "Bad inst->DstReg.Index");
@@ -296,12 +318,15 @@ emit_simple_arith(struct i915_fp_compile *p,
 }
 
 
-#define EMIT_1ARG_ARITH( OP ) emit_simple_arith(p, inst, OP, 1)
-#define EMIT_2ARG_ARITH( OP ) emit_simple_arith(p, inst, OP, 2)
-#define EMIT_3ARG_ARITH( OP ) emit_simple_arith(p, inst, OP, 3)
-
-
-
+/*
+ * Translate TGSI instruction to i915 instruction.
+ *
+ * Possible concerns:
+ *
+ * SIN, COS -- could use another taylor step?
+ * LIT      -- results seem a little different to sw mesa
+ * LOG      -- different to mesa on negative numbers, but this is conformant.
+ */ 
 static void
 i915_translate_instruction(struct i915_fp_compile *p,
                            const struct tgsi_full_instruction *inst)
@@ -321,7 +346,7 @@ i915_translate_instruction(struct i915_fp_compile *p,
       break;
 
    case TGSI_OPCODE_ADD:
-      EMIT_2ARG_ARITH(A0_ADD);
+      emit_simple_arith(p, inst, A0_ADD, 2);
       break;
 
    case TGSI_OPCODE_CMP:
@@ -385,11 +410,11 @@ i915_translate_instruction(struct i915_fp_compile *p,
       break;
 
    case TGSI_OPCODE_DP3:
-      EMIT_2ARG_ARITH(A0_DP3);
+      emit_simple_arith(p, inst, A0_DP3, 2);
       break;
 
    case TGSI_OPCODE_DP4:
-      EMIT_2ARG_ARITH(A0_DP4);
+      emit_simple_arith(p, inst, A0_DP4, 2);
       break;
 
    case TGSI_OPCODE_DPH:
@@ -431,11 +456,11 @@ i915_translate_instruction(struct i915_fp_compile *p,
       break;
 
    case TGSI_OPCODE_FLR:
-      EMIT_1ARG_ARITH(A0_FLR);
+      emit_simple_arith(p, inst, A0_FLR, 1);
       break;
 
    case TGSI_OPCODE_FRC:
-      EMIT_1ARG_ARITH(A0_FRC);
+      emit_simple_arith(p, inst, A0_FRC, 1);
       break;
 
    case TGSI_OPCODE_KIL:
@@ -512,11 +537,11 @@ i915_translate_instruction(struct i915_fp_compile *p,
       break;
 
    case TGSI_OPCODE_MAD:
-      EMIT_3ARG_ARITH(A0_MAD);
+      emit_simple_arith(p, inst, A0_MAD, 3);
       break;
 
    case TGSI_OPCODE_MAX:
-      EMIT_2ARG_ARITH(A0_MAX);
+      emit_simple_arith(p, inst, A0_MAX, 2);
       break;
 
    case TGSI_OPCODE_MIN:
@@ -539,11 +564,11 @@ i915_translate_instruction(struct i915_fp_compile *p,
 
    case TGSI_OPCODE_MOV:
       /* aka TGSI_OPCODE_SWZ */
-      EMIT_1ARG_ARITH(A0_MOV);
+      emit_simple_arith(p, inst, A0_MOV, 1);
       break;
 
    case TGSI_OPCODE_MUL:
-      EMIT_2ARG_ARITH(A0_MUL);
+      emit_simple_arith(p, inst, A0_MUL, 2);
       break;
 
    case TGSI_OPCODE_POW:
@@ -652,7 +677,7 @@ i915_translate_instruction(struct i915_fp_compile *p,
       break;
 
    case TGSI_OPCODE_SGE:
-      EMIT_2ARG_ARITH(A0_SGE);
+      emit_simple_arith(p, inst, A0_SGE, 2);
       break;
 
    case TGSI_OPCODE_SIN:
@@ -706,7 +731,7 @@ i915_translate_instruction(struct i915_fp_compile *p,
       break;
 
    case TGSI_OPCODE_SLT:
-      EMIT_2ARG_ARITH(A0_SLT);
+      emit_simple_arith(p, inst, A0_SLT, 2);
       break;
 
    case TGSI_OPCODE_SUB:
@@ -769,20 +794,12 @@ i915_translate_instruction(struct i915_fp_compile *p,
 
 /**
  * Translate TGSI fragment shader into i915 hardware instructions.
- *
- * Possible concerns:
- *
- * SIN, COS -- could use another taylor step?
- * LIT      -- results seem a little different to sw mesa
- * LOG      -- different to mesa on negative numbers, but this is conformant.
- * 
- * Parse failures -- Mesa doesn't currently give a good indication
- * internally whether a particular program string parsed or not.  This
- * can lead to confusion -- hopefully we cope with it ok now.
+ * \param p  the translation state
+ * \param tokens  the TGSI token array
  */
-void
-i915_translate_program(struct i915_fp_compile *p,
-                       const struct tgsi_token *tokens)
+static void
+i915_translate_instructions(struct i915_fp_compile *p,
+                            const struct tgsi_token *tokens)
 {
    struct tgsi_parse_context parse;
 
@@ -794,10 +811,11 @@ i915_translate_program(struct i915_fp_compile *p,
 
       switch( parse.FullToken.Token.Type ) {
       case TGSI_TOKEN_TYPE_DECLARATION:
-         assert(0);
+         /* XXX no-op? */
          break;
 
       case TGSI_TOKEN_TYPE_IMMEDIATE:
+         /* XXX no-op? */
          assert(0);
          break;
 
@@ -815,13 +833,139 @@ i915_translate_program(struct i915_fp_compile *p,
 }
 
 
+static struct i915_fp_compile *
+i915_init_compile(struct i915_context *i915,
+                  struct pipe_shader_state *fs)
+{
+   struct i915_fp_compile *p = CALLOC_STRUCT(i915_fp_compile);
+
+   p->shader = &i915->fs;
+
+   /* 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;
+
+   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->utemp_flag = ~0x7;
+
+   p->wpos_tex = -1;
+
+   /* initialize the first program word */
+   *(p->decl++) = _3DSTATE_PIXEL_SHADER_PROGRAM;
+
+   return p;
+}
+
+/* Copy compile results to the fragment program struct and destroy the
+ * compilation context.
+ */
+static void
+i915_fini_compile(struct i915_context *i915, struct i915_fp_compile *p)
+{
+   uint program_size = p->csr - p->program;
+   uint decl_size = p->decl - p->declarations;
+
+   if (p->nr_tex_indirect > I915_MAX_TEX_INDIRECT)
+      i915_program_error(p, "Exceeded max nr indirect texture lookups");
+
+   if (p->nr_tex_insn > I915_MAX_TEX_INSN)
+      i915_program_error(p, "Exceeded max TEX instructions");
+
+   if (p->nr_alu_insn > I915_MAX_ALU_INSN)
+      i915_program_error(p, "Exceeded max ALU instructions");
+
+   if (p->nr_decl_insn > I915_MAX_DECL_INSN)
+      i915_program_error(p, "Exceeded max DECL instructions");
+
+   if (p->error) {
+      p->NumNativeInstructions = 0;
+      p->NumNativeAluInstructions = 0;
+      p->NumNativeTexInstructions = 0;
+      p->NumNativeTexIndirections = 0;
+
+      i915_use_passthrough_shader(i915);
+   }
+   else {
+      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;
+
+      /* patch in the program length */
+      p->declarations[0] |= program_size + decl_size - 2;
+
+      /* Copy compilation results to fragment program struct: 
+       */
+      i915->current.program
+         = (uint *) malloc((program_size + decl_size) * sizeof(uint));
+      i915->current.program_len = program_size + decl_size;
+
+      memcpy(i915->current.program,
+             p->declarations, 
+             decl_size * sizeof(uint));
 
+      memcpy(i915->current.program + decl_size, 
+             p->program, 
+             program_size * sizeof(uint));
 
-/* Rather than trying to intercept and jiggle depth writes during
+      i915->current.constants = (uint *) p->constants->constant;
+      i915->current.num_constants = p->constants->nr_constants;
+   }
+
+   /* Release the compilation struct: 
+    */
+   free(p);
+}
+
+
+/**
+ * Find an unused texture coordinate slot to use for fragment WPOS.
+ * Update p->fp->wpos_tex with the result (-1 if no used texcoord slot is found).
+ */
+static void
+i915_find_wpos_space(struct i915_fp_compile *p)
+{
+   const uint inputs = p->shader->inputs_read;
+   uint i;
+
+   p->wpos_tex = -1;
+
+   if (inputs & FRAG_BIT_WPOS) {
+      for (i = 0; i < I915_TEX_UNITS; i++) {
+        if ((inputs & (FRAG_BIT_TEX0 << i)) == 0) {
+           p->wpos_tex = i;
+           return;
+        }
+      }
+
+      i915_program_error(p, "No free texcoord for wpos value");
+   }
+}
+
+
+
+
+/**
+ * Rather than trying to intercept and jiggle depth writes during
  * emit, just move the value into its correct position at the end of
  * the program:
  */
-void
+static void
 i915_fixup_depth_write(struct i915_fp_compile *p)
 {
    if (p->shader->outputs_written & (1<<FRAG_RESULT_DEPR)) {
@@ -835,5 +979,16 @@ 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;
 
+   i915_find_wpos_space(p);
 
+   i915_translate_instructions(p, tokens);
+   i915_fixup_depth_write(p);
+
+   i915_fini_compile(i915, p);
+}
index 1de6fea..e8ffd1f 100644 (file)
@@ -27,7 +27,7 @@
 
 /* Authors:  Keith Whitwell <keith@tungstengraphics.com>
  */
-//#include "imports.h"
+
 
 #include "pipe/draw/draw_context.h"
 
index a01b193..b4ec480 100644 (file)
@@ -149,6 +149,11 @@ void i915_update_derived( struct i915_context *i915 )
    if (i915->dirty)
       i915_update_dynamic( i915 );
 
+   if (i915->dirty & I915_NEW_FS) {
+      i915_translate_fragment_program(i915);
+      i915->hardware_dirty |= I915_HW_PROGRAM; /* XXX right? */
+   }
+
    /* HW emit currently references framebuffer state directly:
     */
    if (i915->dirty & I915_NEW_FRAMEBUFFER)
index a7ae92d..da9d541 100644 (file)
  **************************************************************************/
 
 
-
-//#include "glheader.h"
-//#include "mtypes.h"
-
 #include "i915_reg.h"
 #include "i915_context.h"
 #include "i915_winsys.h"
@@ -116,9 +112,6 @@ i915_emit_hardware_state(struct i915_context *i915 )
    }
    
 
-
-
-
    if (i915->hardware_dirty & I915_HW_IMMEDIATE)
    {
       OUT_BATCH(_3DSTATE_LOAD_STATE_IMMEDIATE_1 | 
@@ -143,8 +136,6 @@ i915_emit_hardware_state(struct i915_context *i915 )
       }
    }
 
-
-
    if (i915->hardware_dirty & I915_HW_STATIC)
    {
       if (i915->framebuffer.cbufs[0]) {
@@ -180,7 +171,6 @@ i915_emit_hardware_state(struct i915_context *i915 )
                   I915_BUFFER_ACCESS_WRITE,
                   0);
       }
-
    
       {
         unsigned cformat = translate_format( i915->framebuffer.cbufs[0]->format );
@@ -198,19 +188,38 @@ i915_emit_hardware_state(struct i915_context *i915 )
                   cformat |
                   zformat );
       }
-
    }
 
+   /* constants */
+   if (i915->hardware_dirty & I915_HW_PROGRAM)
+   {
+      const uint nr = i915->current.num_constants;
+      if (nr > 0) {
+         const uint *c = (const uint *) i915->current.constants;
+         uint i;
+         OUT_BATCH( _3DSTATE_PIXEL_SHADER_CONSTANTS | (nr * 4) );
+         OUT_BATCH( (1 << (nr - 1)) | ((1 << (nr - 1)) - 1) );
+         for (i = 0; i < nr; i++) {
+            OUT_BATCH(*c++);
+            OUT_BATCH(*c++);
+            OUT_BATCH(*c++);
+            OUT_BATCH(*c++);
+         }
+      }
+   }
 
-
+   /* Fragment program */
+   if (i915->hardware_dirty & I915_HW_PROGRAM)
    {
-      unsigned i, dwords;
-      unsigned *prog = i915_passthrough_program( &dwords );
-      
-      for (i = 0; i < dwords; i++)
-        OUT_BATCH( prog[i] );
+      uint i;
+      /* we should always have, at least, a pass-through program */
+      assert(i915->current.program_len > 0);
+      for (i = 0; i < i915->current.program_len; i++) {
+         OUT_BATCH(i915->current.program[i]);
+      }
    }
 
+   /* drawing surface size */
    {
       int w = i915->framebuffer.cbufs[0]->width;
       int h = i915->framebuffer.cbufs[0]->height;