i965: Fix failure to upload new constant data when changing programs.
[mesa.git] / src / mesa / drivers / dri / i965 / brw_wm_fp.c
index 621106f14dc830acfdf1cdf74a37bf48f1de037a..7f7b957cbe892bfde9c390c55f4ecc44e4780d38 100644 (file)
@@ -30,9 +30,9 @@
   */
                
 
-#include "glheader.h"
-#include "macros.h"
-#include "enums.h"
+#include "main/glheader.h"
+#include "main/macros.h"
+#include "main/enums.h"
 #include "brw_context.h"
 #include "brw_wm.h"
 #include "brw_util.h"
@@ -426,10 +426,6 @@ static struct prog_src_register search_or_add_param5(struct brw_wm_compile *c,
 
    idx = _mesa_add_state_reference( paramList, tokens );
 
-   /* Recalculate state dependency: 
-    */
-   c->fp->param_state = paramList->StateFlags;
-
    return src_reg(PROGRAM_STATE_VAR, idx);
 }
 
@@ -494,17 +490,20 @@ static void precalc_dst( struct brw_wm_compile *c,
 
 
    if (dst.WriteMask & WRITEMASK_XZ) {
+      struct prog_instruction *swz;
       GLuint z = GET_SWZ(src0.Swizzle, Z);
 
       /* dst.xz = swz src0.1zzz
        */
-      emit_op(c,
-             OPCODE_SWZ,
-             dst_mask(dst, WRITEMASK_XZ),
-             inst->SaturateMode, 0, 0,
-             src_swizzle(src0, SWIZZLE_ONE, z, z, z),
-             src_undef(),
-             src_undef());
+      swz = emit_op(c,
+                   OPCODE_SWZ,
+                   dst_mask(dst, WRITEMASK_XZ),
+                   inst->SaturateMode, 0, 0,
+                   src_swizzle(src0, SWIZZLE_ONE, z, z, z),
+                   src_undef(),
+                   src_undef());
+      /* Avoid letting negation flag of src0 affect our 1 constant. */
+      swz->SrcReg[0].NegateBase &= ~NEGATE_X;
    }
    if (dst.WriteMask & WRITEMASK_W) {
       /* dst.w = mov src1.w
@@ -527,15 +526,19 @@ static void precalc_lit( struct brw_wm_compile *c,
    struct prog_dst_register dst = inst->DstReg;
    
    if (dst.WriteMask & WRITEMASK_XW) {
+      struct prog_instruction *swz;
+
       /* dst.xw = swz src0.1111
        */
-      emit_op(c,
-             OPCODE_SWZ,
-             dst_mask(dst, WRITEMASK_XW),
-             0, 0, 0,
-             src_swizzle1(src0, SWIZZLE_ONE),
-             src_undef(),
-             src_undef());
+      swz = emit_op(c,
+                   OPCODE_SWZ,
+                   dst_mask(dst, WRITEMASK_XW),
+                   0, 0, 0,
+                   src_swizzle1(src0, SWIZZLE_ONE),
+                   src_undef(),
+                   src_undef());
+      /* Avoid letting the negation flag of src0 affect our 1 constant. */
+      swz->SrcReg[0].NegateBase = 0;
    }
 
 
@@ -555,6 +558,7 @@ static void precalc_tex( struct brw_wm_compile *c,
 {
    struct prog_src_register coord;
    struct prog_dst_register tmpcoord;
+   GLuint unit = c->fp->program.Base.SamplerUnits[inst->TexSrcUnit];
 
    if (inst->TexSrcTarget == TEXTURE_CUBE_INDEX) {
        struct prog_instruction *out;
@@ -611,7 +615,7 @@ static void precalc_tex( struct brw_wm_compile *c,
         search_or_add_param5( c, 
                               STATE_INTERNAL, 
                               STATE_TEXRECT_SCALE,
-                              inst->TexSrcUnit,
+                              unit,
                               0,0 );
 
       tmpcoord = get_temp(c);
@@ -637,19 +641,19 @@ static void precalc_tex( struct brw_wm_compile *c,
     * conversion requires allocating a temporary variable which we
     * don't have the facility to do that late in the compilation.
     */
-   if (!(c->key.yuvtex_mask & (1<<inst->TexSrcUnit))) {
+   if (!(c->key.yuvtex_mask & (1<<unit))) {
       emit_op(c, 
              OPCODE_TEX,
              inst->DstReg,
              inst->SaturateMode,
-             inst->TexSrcUnit,
+             unit,
              inst->TexSrcTarget,
              coord,
              src_undef(),
              src_undef());
    }
    else {
-       GLboolean  swap_uv = c->key.yuvtex_swap_mask & (1<<inst->TexSrcUnit);
+       GLboolean  swap_uv = c->key.yuvtex_swap_mask & (1<<unit);
 
       /* 
         CONST C0 = { -.5, -.0625,  -.5, 1.164 }
@@ -675,7 +679,7 @@ static void precalc_tex( struct brw_wm_compile *c,
              OPCODE_TEX,
              tmp,
              inst->SaturateMode,
-             inst->TexSrcUnit,
+             unit,
              inst->TexSrcTarget,
              coord,
              src_undef(),
@@ -730,7 +734,8 @@ static void precalc_tex( struct brw_wm_compile *c,
       release_temp(c, tmp);
    }
 
-   if (inst->TexSrcTarget == GL_TEXTURE_RECTANGLE_NV) 
+   if ((inst->TexSrcTarget == TEXTURE_RECT_INDEX) ||
+       (inst->TexSrcTarget == TEXTURE_CUBE_INDEX))
       release_temp(c, tmpcoord);
 }
 
@@ -863,25 +868,31 @@ static void emit_fb_write( struct brw_wm_compile *c )
    struct prog_src_register outdepth = src_reg(PROGRAM_OUTPUT, FRAG_RESULT_DEPR);
    GLuint i;
 
-   struct prog_instruction *inst;
+   struct prog_instruction *inst, *last_inst;
    struct brw_context *brw = c->func.brw;
 
    /* inst->Sampler is not used by backend, 
       use it for fb write target and eot */
 
-   inst = emit_op(c, WM_FB_WRITE, dst_mask(dst_undef(),0),
-           0, 0, 0, outcolor, payload_r0_depth, outdepth);
-   inst->Sampler = (brw->state.nr_draw_regions > 1 ? 0: 1)|(0<<1);
-
    if (brw->state.nr_draw_regions > 1) {
        for (i = 0 ; i < brw->state.nr_draw_regions; i++) {
           outcolor = src_reg(PROGRAM_OUTPUT, FRAG_RESULT_DATA0 + i);
-          inst = emit_op(c,
+          last_inst = inst = emit_op(c,
                   WM_FB_WRITE, dst_mask(dst_undef(),0), 0, 0, 0,
                   outcolor, payload_r0_depth, outdepth);
-          inst->Sampler = ((i == brw->state.nr_draw_regions - 1) ? 1: 0);
-          inst->Sampler |= (i<<1);
+          inst->Sampler = (i<<1);
+          if (c->fp_fragcolor_emitted) {
+              outcolor = src_reg(PROGRAM_OUTPUT, FRAG_RESULT_COLR);
+              last_inst = inst = emit_op(c, WM_FB_WRITE, dst_mask(dst_undef(),0),
+                      0, 0, 0, outcolor, payload_r0_depth, outdepth);
+              inst->Sampler = (i<<1);
+          }
        }
+       last_inst->Sampler |= 1; //eot
+   }else {
+       inst = emit_op(c, WM_FB_WRITE, dst_mask(dst_undef(),0),
+              0, 0, 0, outcolor, payload_r0_depth, outdepth);
+       inst->Sampler = 1|(0<<1);
    }
 }
 
@@ -908,7 +919,15 @@ static void validate_src_regs( struct brw_wm_compile *c,
    }
 }
         
-
+static void validate_dst_regs( struct brw_wm_compile *c,
+                              const struct prog_instruction *inst )
+{
+   if (inst->DstReg.File == PROGRAM_OUTPUT) {
+       GLuint idx = inst->DstReg.Index;
+       if (idx == FRAG_RESULT_COLR)
+          c->fp_fragcolor_emitted = 1;
+   }
+}
 
 static void print_insns( const struct prog_instruction *insn,
                         GLuint nr )
@@ -951,6 +970,11 @@ void brw_wm_pass_fp( struct brw_wm_compile *c )
     */
 
 
+   for (insn = 0; insn < fp->program.Base.NumInstructions; insn++) {
+      const struct prog_instruction *inst = &fp->program.Base.Instructions[insn];
+      validate_src_regs(c, inst);
+      validate_dst_regs(c, inst);
+   }
    for (insn = 0; insn < fp->program.Base.NumInstructions; insn++) {
       const struct prog_instruction *inst = &fp->program.Base.Instructions[insn];
       struct prog_instruction *out;
@@ -958,7 +982,6 @@ void brw_wm_pass_fp( struct brw_wm_compile *c )
       /* Check for INPUT values, emit INTERP instructions where
        * necessary:
        */
-      validate_src_regs(c, inst);
 
 
       switch (inst->Opcode) {
@@ -994,11 +1017,20 @@ void brw_wm_pass_fp( struct brw_wm_compile *c )
       case OPCODE_LIT:
         precalc_lit(c, inst);
         break;
-     
+
+      case OPCODE_TEX:
+        precalc_tex(c, inst);
+        break;
+
       case OPCODE_TXP:
         precalc_txp(c, inst);
         break;
 
+      case OPCODE_TXB:
+        out = emit_insn(c, inst);
+        out->TexSrcUnit = fp->program.Base.SamplerUnits[inst->TexSrcUnit];
+        break;
+
       case OPCODE_XPD: 
         out = emit_insn(c, inst);
         /* This should probably be done in the parser.