Merge branch 'mesa_7_5_branch'
[mesa.git] / src / mesa / drivers / dri / i965 / brw_wm_emit.c
index 6bafa44b82bc8d50d0a77bb3bfef4e7b725570f3..9f82916c025633eec53614c34c8be5026b094b4b 100644 (file)
@@ -30,7 +30,7 @@
   */
                
 
-#include "macros.h"
+#include "main/macros.h"
 #include "brw_context.h"
 #include "brw_wm.h"
 
@@ -39,7 +39,7 @@
 /* Not quite sure how correct this is - need to understand horiz
  * vs. vertical strides a little better.
  */
-static __inline struct brw_reg sechalf( struct brw_reg reg )
+static INLINE struct brw_reg sechalf( struct brw_reg reg )
 {
    if (reg.vstride)
       reg.nr++;
@@ -122,26 +122,30 @@ static void emit_delta_xy(struct brw_compile *p,
    }
 }
 
-static void emit_wpos_xy(struct brw_compile *p,
-                          const struct brw_reg *dst,
-                          GLuint mask,
-                          const struct brw_reg *arg0)
+static void emit_wpos_xy(struct brw_wm_compile *c,
+                        const struct brw_reg *dst,
+                        GLuint mask,
+                        const struct brw_reg *arg0)
 {
-   /* Calc delta X,Y by subtracting origin in r1 from the pixel
-    * centers.
+   struct brw_compile *p = &c->func;
+
+   /* Calculate the pixel offset from window bottom left into destination
+    * X and Y channels.
     */
    if (mask & WRITEMASK_X) {
-      brw_MOV(p,
+      /* X' = X - origin */
+      brw_ADD(p,
              dst[0],
-             retype(arg0[0], BRW_REGISTER_TYPE_UW));
+             retype(arg0[0], BRW_REGISTER_TYPE_W),
+             brw_imm_d(0 - c->key.origin_x));
    }
 
    if (mask & WRITEMASK_Y) {
-      /* TODO -- window_height - Y */
-      brw_MOV(p,
+      /* Y' = height - (Y - origin_y) = height + origin_y - Y */
+      brw_ADD(p,
              dst[1],
-             negate(retype(arg0[1], BRW_REGISTER_TYPE_UW)));
-
+             negate(retype(arg0[1], BRW_REGISTER_TYPE_W)),
+             brw_imm_d(c->key.origin_y + c->key.drawable_height - 1));
    }
 }
 
@@ -190,7 +194,7 @@ static void emit_linterp( struct brw_compile *p,
    interp[2] = brw_vec1_grf(nr+1, 0);
    interp[3] = brw_vec1_grf(nr+1, 4);
 
-   for(i = 0; i < 4; i++ ) {
+   for (i = 0; i < 4; i++) {
       if (mask & (1<<i)) {
         brw_LINE(p, brw_null_reg(), interp[i], deltas[0]);
         brw_MAC(p, dst[i], suboffset(interp[i],1), deltas[1]);
@@ -215,39 +219,69 @@ static void emit_pinterp( struct brw_compile *p,
    interp[2] = brw_vec1_grf(nr+1, 0);
    interp[3] = brw_vec1_grf(nr+1, 4);
 
-   for(i = 0; i < 4; i++ ) {
+   for (i = 0; i < 4; i++) {
       if (mask & (1<<i)) {
         brw_LINE(p, brw_null_reg(), interp[i], deltas[0]);
         brw_MAC(p, dst[i], suboffset(interp[i],1), deltas[1]);
+      }
+   }
+   for (i = 0; i < 4; i++) {
+      if (mask & (1<<i)) {
         brw_MUL(p, dst[i], dst[i], w[3]);
       }
    }
 }
 
+
 static void emit_cinterp( struct brw_compile *p, 
                         const struct brw_reg *dst,
                         GLuint mask,
                         const struct brw_reg *arg0 )
 {
-       struct brw_reg interp[4];
-       GLuint nr = arg0[0].nr;
-       GLuint i;
-
-       interp[0] = brw_vec1_grf(nr, 0);
-       interp[1] = brw_vec1_grf(nr, 4);
-       interp[2] = brw_vec1_grf(nr+1, 0);
-       interp[3] = brw_vec1_grf(nr+1, 4);
-
-       for(i = 0; i < 4; i++ ) {
-               if (mask & (1<<i)) {
-                       brw_MOV(p, dst[i], suboffset(interp[i],3));     /* TODO: optimize away like other moves */
-               }
-       }
+   struct brw_reg interp[4];
+   GLuint nr = arg0[0].nr;
+   GLuint i;
+
+   interp[0] = brw_vec1_grf(nr, 0);
+   interp[1] = brw_vec1_grf(nr, 4);
+   interp[2] = brw_vec1_grf(nr+1, 0);
+   interp[3] = brw_vec1_grf(nr+1, 4);
+
+   for (i = 0; i < 4; i++) {
+      if (mask & (1<<i)) {
+         brw_MOV(p, dst[i], suboffset(interp[i],3));   /* TODO: optimize away like other moves */
+      }
+   }
 }
 
+/* Sets the destination channels to 1.0 or 0.0 according to glFrontFacing. */
+static void emit_frontfacing( struct brw_compile *p,
+                             const struct brw_reg *dst,
+                             GLuint mask )
+{
+   struct brw_reg r1_6ud = retype(brw_vec1_grf(1, 6), BRW_REGISTER_TYPE_UD);
+   GLuint i;
 
+   if (!(mask & WRITEMASK_XYZW))
+      return;
 
+   for (i = 0; i < 4; i++) {
+      if (mask & (1<<i)) {
+        brw_MOV(p, dst[i], brw_imm_f(0.0));
+      }
+   }
 
+   /* bit 31 is "primitive is back face", so checking < (1 << 31) gives
+    * us front face
+    */
+   brw_CMP(p, brw_null_reg(), BRW_CONDITIONAL_L, r1_6ud, brw_imm_ud(1 << 31));
+   for (i = 0; i < 4; i++) {
+      if (mask & (1<<i)) {
+        brw_MOV(p, dst[i], brw_imm_f(1.0));
+      }
+   }
+   brw_set_predicate_control_flag_value(p, 0xff);
+}
 
 static void emit_alu1( struct brw_compile *p, 
                       struct brw_instruction *(*func)(struct brw_compile *, 
@@ -272,6 +306,7 @@ static void emit_alu1( struct brw_compile *p,
       brw_set_saturate(p, 0);
 }
 
+
 static void emit_alu2( struct brw_compile *p, 
                       struct brw_instruction *(*func)(struct brw_compile *, 
                                                       struct brw_reg, 
@@ -318,6 +353,19 @@ static void emit_mad( struct brw_compile *p,
    }
 }
 
+static void emit_trunc( struct brw_compile *p,
+                     const struct brw_reg *dst,
+                     GLuint mask,
+                     const struct brw_reg *arg0)
+{
+   GLuint i;
+
+   for (i = 0; i < 4; i++) {
+      if (mask & (1<<i)) {
+        brw_RNDZ(p, dst[i], arg0[i]);
+      }
+   }
+}
 
 static void emit_lrp( struct brw_compile *p, 
                      const struct brw_reg *dst,
@@ -343,6 +391,7 @@ static void emit_lrp( struct brw_compile *p,
       }
    }
 }
+
 static void emit_sop( struct brw_compile *p, 
                      const struct brw_reg *dst,
                      GLuint mask,
@@ -368,7 +417,7 @@ static void emit_slt( struct brw_compile *p,
                      const struct brw_reg *arg0,
                      const struct brw_reg *arg1 )
 {
-        emit_sop(p, dst, mask, BRW_CONDITIONAL_L, arg0, arg1);
+   emit_sop(p, dst, mask, BRW_CONDITIONAL_L, arg0, arg1);
 }
 
 static void emit_sle( struct brw_compile *p, 
@@ -377,7 +426,7 @@ static void emit_sle( struct brw_compile *p,
                      const struct brw_reg *arg0,
                      const struct brw_reg *arg1 )
 {
-        emit_sop(p, dst, mask, BRW_CONDITIONAL_LE, arg0, arg1);
+   emit_sop(p, dst, mask, BRW_CONDITIONAL_LE, arg0, arg1);
 }
 
 static void emit_sgt( struct brw_compile *p, 
@@ -386,7 +435,7 @@ static void emit_sgt( struct brw_compile *p,
                      const struct brw_reg *arg0,
                      const struct brw_reg *arg1 )
 {
-        emit_sop(p, dst, mask, BRW_CONDITIONAL_G, arg0, arg1);
+   emit_sop(p, dst, mask, BRW_CONDITIONAL_G, arg0, arg1);
 }
 
 static void emit_sge( struct brw_compile *p, 
@@ -395,7 +444,7 @@ static void emit_sge( struct brw_compile *p,
                      const struct brw_reg *arg0,
                      const struct brw_reg *arg1 )
 {
-        emit_sop(p, dst, mask, BRW_CONDITIONAL_GE, arg0, arg1);
+   emit_sop(p, dst, mask, BRW_CONDITIONAL_GE, arg0, arg1);
 }
 
 static void emit_seq( struct brw_compile *p, 
@@ -404,7 +453,7 @@ static void emit_seq( struct brw_compile *p,
                      const struct brw_reg *arg0,
                      const struct brw_reg *arg1 )
 {
-        emit_sop(p, dst, mask, BRW_CONDITIONAL_EQ, arg0, arg1);
+   emit_sop(p, dst, mask, BRW_CONDITIONAL_EQ, arg0, arg1);
 }
 
 static void emit_sne( struct brw_compile *p, 
@@ -413,7 +462,7 @@ static void emit_sne( struct brw_compile *p,
                      const struct brw_reg *arg0,
                      const struct brw_reg *arg1 )
 {
-        emit_sop(p, dst, mask, BRW_CONDITIONAL_NEQ, arg0, arg1);
+   emit_sop(p, dst, mask, BRW_CONDITIONAL_NEQ, arg0, arg1);
 }
 
 static void emit_cmp( struct brw_compile *p, 
@@ -496,6 +545,9 @@ static void emit_dp3( struct brw_compile *p,
                      const struct brw_reg *arg0,
                      const struct brw_reg *arg1 )
 {
+   if (!(mask & WRITEMASK_XYZW))
+      return; /* Do not emit dead code */
+
    assert((mask & WRITEMASK_XYZW) == WRITEMASK_X);
 
    brw_MUL(p, brw_null_reg(), arg0[0], arg1[0]);
@@ -513,6 +565,9 @@ static void emit_dp4( struct brw_compile *p,
                      const struct brw_reg *arg0,
                      const struct brw_reg *arg1 )
 {
+   if (!(mask & WRITEMASK_XYZW))
+      return; /* Do not emit dead code */
+
    assert((mask & WRITEMASK_XYZW) == WRITEMASK_X);
 
    brw_MUL(p, brw_null_reg(), arg0[0], arg1[0]);
@@ -531,6 +586,9 @@ static void emit_dph( struct brw_compile *p,
                      const struct brw_reg *arg0,
                      const struct brw_reg *arg1 )
 {
+   if (!(mask & WRITEMASK_XYZW))
+      return; /* Do not emit dead code */
+
    assert((mask & WRITEMASK_XYZW) == WRITEMASK_X);
 
    brw_MUL(p, brw_null_reg(), arg0[0], arg1[0]);
@@ -574,6 +632,9 @@ static void emit_math1( struct brw_compile *p,
                        GLuint mask,
                        const struct brw_reg *arg0 )
 {
+   if (!(mask & WRITEMASK_XYZW))
+      return; /* Do not emit dead code */
+
    //assert((mask & WRITEMASK_XYZW) == WRITEMASK_X ||
    //    function == BRW_MATH_FUNCTION_SINCOS);
    
@@ -598,6 +659,9 @@ static void emit_math2( struct brw_compile *p,
                        const struct brw_reg *arg0,
                        const struct brw_reg *arg1)
 {
+   if (!(mask & WRITEMASK_XYZW))
+      return; /* Do not emit dead code */
+
    assert((mask & WRITEMASK_XYZW) == WRITEMASK_X);
 
    brw_push_insn_state(p);
@@ -648,9 +712,9 @@ static void emit_tex( struct brw_wm_compile *c,
 {
    struct brw_compile *p = &c->func;
    GLuint msgLength, responseLength;
-   GLboolean shadow = (c->key.shadowtex_mask & (1<<inst->tex_unit)) ? 1 : 0;
    GLuint i, nr;
    GLuint emit;
+   GLuint msg_type;
 
    /* How many input regs are there?
     */
@@ -670,7 +734,7 @@ static void emit_tex( struct brw_wm_compile *c,
       break;
    }
 
-   if (shadow) {
+   if (inst->tex_shadow) {
       nr = 4;
       emit |= WRITEMASK_W;
    }
@@ -688,22 +752,31 @@ static void emit_tex( struct brw_wm_compile *c,
 
    responseLength = 8;         /* always */
 
+   if (BRW_IS_IGDNG(p->brw)) {
+       if (inst->tex_shadow)
+           msg_type = BRW_SAMPLER_MESSAGE_SIMD16_SAMPLE_COMPARE_IGDNG;
+       else
+           msg_type = BRW_SAMPLER_MESSAGE_SIMD16_SAMPLE_IGDNG;
+   } else {
+       if (inst->tex_shadow)
+           msg_type = BRW_SAMPLER_MESSAGE_SIMD16_SAMPLE_COMPARE;
+       else
+           msg_type = BRW_SAMPLER_MESSAGE_SIMD16_SAMPLE;
+   }
+
    brw_SAMPLE(p, 
              retype(vec16(dst[0]), BRW_REGISTER_TYPE_UW),
              1,
              retype(c->payload.depth[0].hw_reg, BRW_REGISTER_TYPE_UW),
-             inst->tex_unit + 1, /* surface */
+              SURF_INDEX_TEXTURE(inst->tex_unit),
              inst->tex_unit,     /* sampler */
              inst->writemask,
-             (shadow ? 
-              BRW_SAMPLER_MESSAGE_SIMD16_SAMPLE_COMPARE : 
-              BRW_SAMPLER_MESSAGE_SIMD16_SAMPLE),
+             msg_type, 
              responseLength,
              msgLength,
-             0);       
-
-   if (shadow)
-       brw_MOV(p, dst[3], brw_imm_f(1.0));
+             0,        
+             1,
+             BRW_SAMPLER_SIMD_MODE_SIMD16);    
 }
 
 
@@ -715,7 +788,7 @@ static void emit_txb( struct brw_wm_compile *c,
 {
    struct brw_compile *p = &c->func;
    GLuint msgLength;
-
+   GLuint msg_type;
    /* Shadow ignored for txb.
     */
    switch (inst->tex_idx) {
@@ -740,19 +813,24 @@ static void emit_txb( struct brw_wm_compile *c,
    brw_MOV(p, brw_message_reg(8), arg[3]);
    msgLength = 9;
 
+   if (BRW_IS_IGDNG(p->brw))
+       msg_type = BRW_SAMPLER_MESSAGE_SIMD16_SAMPLE_BIAS_IGDNG;
+   else
+       msg_type = BRW_SAMPLER_MESSAGE_SIMD16_SAMPLE_BIAS;
 
    brw_SAMPLE(p, 
              retype(vec16(dst[0]), BRW_REGISTER_TYPE_UW),
              1,
              retype(c->payload.depth[0].hw_reg, BRW_REGISTER_TYPE_UW),
-             inst->tex_unit + 1, /* surface */
+              SURF_INDEX_TEXTURE(inst->tex_unit),
              inst->tex_unit,     /* sampler */
              inst->writemask,
-             BRW_SAMPLER_MESSAGE_SIMD16_SAMPLE_BIAS,
+             msg_type,
              8,                /* responseLength */
              msgLength,
-             0);       
-
+             0,        
+             1,
+             BRW_SAMPLER_SIMD_MODE_SIMD16);    
 }
 
 
@@ -803,7 +881,6 @@ static void emit_kil( struct brw_wm_compile *c,
    struct brw_reg r0uw = retype(brw_vec1_grf(0, 0), BRW_REGISTER_TYPE_UW);
    GLuint i;
    
-
    /* XXX - usually won't need 4 compares!
     */
    for (i = 0; i < 4; i++) {
@@ -816,9 +893,12 @@ static void emit_kil( struct brw_wm_compile *c,
    }
 }
 
+
 static void fire_fb_write( struct brw_wm_compile *c,
                           GLuint base_reg,
-                          GLuint nr )
+                          GLuint nr,
+                          GLuint target,
+                          GLuint eot )
 {
    struct brw_compile *p = &c->func;
    
@@ -841,12 +921,13 @@ static void fire_fb_write( struct brw_wm_compile *c,
                retype(vec16(brw_null_reg()), BRW_REGISTER_TYPE_UW),
                base_reg,
                retype(brw_vec8_grf(0, 0), BRW_REGISTER_TYPE_UW),
-               0,              /* render surface always 0 */
+               target,         
                nr,
                0, 
-               1);
+               eot);
 }
 
+
 static void emit_aa( struct brw_wm_compile *c,
                     struct brw_reg *arg1,
                     GLuint reg )
@@ -865,11 +946,16 @@ static void emit_aa( struct brw_wm_compile *c,
 
 /* Post-fragment-program processing.  Send the results to the
  * framebuffer.
+ * \param arg0  the fragment color
+ * \param arg1  the pass-through depth value
+ * \param arg2  the shader-computed depth value
  */
 static void emit_fb_write( struct brw_wm_compile *c,
                           struct brw_reg *arg0,
                           struct brw_reg *arg1,
-                          struct brw_reg *arg2)
+                          struct brw_reg *arg2,
+                          GLuint target,
+                          GLuint eot)
 {
    struct brw_compile *p = &c->func;
    GLuint nr = 2;
@@ -924,25 +1010,25 @@ static void emit_fb_write( struct brw_wm_compile *c,
       GLuint off = c->key.dest_depth_reg % 2;
 
       if (off != 0) {
-        brw_push_insn_state(p);
-        brw_set_compression_control(p, BRW_COMPRESSION_NONE);
-        brw_MOV(p, brw_message_reg(nr), arg1[comp]);
-        /* 2nd half? */
-        brw_MOV(p, brw_message_reg(nr+1), offset(arg1[comp],1));
-        brw_pop_insn_state(p);
+         brw_push_insn_state(p);
+         brw_set_compression_control(p, BRW_COMPRESSION_NONE);
+
+         brw_MOV(p, brw_message_reg(nr), offset(arg1[comp],1));
+         /* 2nd half? */
+         brw_MOV(p, brw_message_reg(nr+1), arg1[comp+1]);
+         brw_pop_insn_state(p);
       }
       else {
-        brw_MOV(p, brw_message_reg(nr), arg1[comp]);
+         brw_MOV(p, brw_message_reg(nr), arg1[comp]);
       }
       nr += 2;
    }
 
-
    if (!c->key.runtime_check_aads_emit) {
       if (c->key.aa_dest_stencil_reg)
         emit_aa(c, arg1, 2);
 
-      fire_fb_write(c, 0, nr);
+      fire_fb_write(c, 0, nr, target, eot);
    }
    else {
       struct brw_reg v1_null_ud = vec1(retype(brw_null_reg(), BRW_REGISTER_TYPE_UD));
@@ -956,25 +1042,23 @@ static void emit_fb_write( struct brw_wm_compile *c,
              get_element_ud(brw_vec8_grf(1,0), 6), 
              brw_imm_ud(1<<26)); 
 
-      jmp = brw_JMPI(p, ip, ip, brw_imm_w(0));
+      jmp = brw_JMPI(p, ip, ip, brw_imm_d(0));
       {
         emit_aa(c, arg1, 2);
-        fire_fb_write(c, 0, nr);
+        fire_fb_write(c, 0, nr, target, eot);
         /* note - thread killed in subroutine */
       }
       brw_land_fwd_jump(p, jmp);
 
       /* ELSE: Shuffle up one register to fill in the hole left for AA:
        */
-      fire_fb_write(c, 1, nr-1);
+      fire_fb_write(c, 1, nr-1, target, eot);
    }
 }
 
 
-
-
-/* Post-fragment-program processing.  Send the results to the
- * framebuffer.
+/**
+ * Move a GPR to scratch memory. 
  */
 static void emit_spill( struct brw_wm_compile *c,
                        struct brw_reg reg,
@@ -993,10 +1077,13 @@ static void emit_spill( struct brw_wm_compile *c,
    */
    brw_dp_WRITE_16(p, 
                   retype(vec16(brw_vec8_grf(0, 0)), BRW_REGISTER_TYPE_UW),
-                  1, 
                   slot);
 }
 
+
+/**
+ * Load a GPR from scratch memory. 
+ */
 static void emit_unspill( struct brw_wm_compile *c,
                          struct brw_reg reg,
                          GLuint slot )
@@ -1017,14 +1104,13 @@ static void emit_unspill( struct brw_wm_compile *c,
 
    brw_dp_READ_16(p,
                  retype(vec16(reg), BRW_REGISTER_TYPE_UW),
-                 1, 
                  slot);
 }
 
 
-
 /**
- * Retrieve upto 4 GEN4 register pairs for the given wm reg:
+ * Retrieve up to 4 GEN4 register pairs for the given wm reg:
+ * Args with unspill_reg != 0 will be loaded from scratch memory.
  */
 static void get_argument_regs( struct brw_wm_compile *c,
                               struct brw_wm_ref *arg[],
@@ -1034,13 +1120,12 @@ static void get_argument_regs( struct brw_wm_compile *c,
 
    for (i = 0; i < 4; i++) {
       if (arg[i]) {
-
-        if (arg[i]->unspill_reg) 
-           emit_unspill(c, 
+        if (arg[i]->unspill_reg)
+           emit_unspill(c,
                         brw_vec8_grf(arg[i]->unspill_reg, 0),
                         arg[i]->value->spill_slot);
 
-        regs[i] = arg[i]->hw_reg;       
+        regs[i] = arg[i]->hw_reg;
       }
       else {
         regs[i] = brw_null_reg();
@@ -1048,6 +1133,10 @@ static void get_argument_regs( struct brw_wm_compile *c,
    }
 }
 
+
+/**
+ * For values that have a spill_slot!=0, write those regs to scratch memory.
+ */
 static void spill_values( struct brw_wm_compile *c,
                          struct brw_wm_value *values,
                          GLuint nr )
@@ -1060,7 +1149,6 @@ static void spill_values( struct brw_wm_compile *c,
 }
 
 
-
 /* Emit the fragment program instructions here.
  */
 void brw_wm_emit( struct brw_wm_compile *c )
@@ -1114,7 +1202,7 @@ void brw_wm_emit( struct brw_wm_compile *c )
         break;
 
       case WM_WPOSXY:
-        emit_wpos_xy(p, dst, dst_flags, args[0]);
+        emit_wpos_xy(c, dst, dst_flags, args[0]);
         break;
 
       case WM_PIXELW:
@@ -1134,7 +1222,11 @@ void brw_wm_emit( struct brw_wm_compile *c )
         break;
 
       case WM_FB_WRITE:
-        emit_fb_write(c, args[0], args[1], args[2]);
+        emit_fb_write(c, args[0], args[1], args[2], inst->target, inst->eot);
+        break;
+
+      case WM_FRONTFACING:
+        emit_frontfacing(p, dst, dst_flags);
         break;
 
         /* Straightforward arithmetic:
@@ -1151,7 +1243,7 @@ void brw_wm_emit( struct brw_wm_compile *c )
         emit_alu1(p, brw_RNDD, dst, dst_flags, args[0]);
         break;
 
-      case OPCODE_DP3: /*  */
+      case OPCODE_DP3:
         emit_dp3(p, dst, dst_flags, args[0], args[1]);
         break;
 
@@ -1163,7 +1255,11 @@ void brw_wm_emit( struct brw_wm_compile *c )
         emit_dph(p, dst, dst_flags, args[0], args[1]);
         break;
 
-      case OPCODE_LRP: /*  */
+      case OPCODE_TRUNC:
+        emit_trunc(p, dst, dst_flags, args[0]);
+        break;
+
+      case OPCODE_LRP:
         emit_lrp(p, dst, dst_flags, args[0], args[1], args[2]);
         break;
 
@@ -1277,8 +1373,10 @@ void brw_wm_emit( struct brw_wm_compile *c )
         break;
 
       default:
-       _mesa_printf("unsupport opcode %d in fragment program\n", 
-               inst->opcode);
+        _mesa_printf("Unsupported opcode %i (%s) in fragment shader\n",
+                     inst->opcode, inst->opcode < MAX_OPCODE ?
+                                   _mesa_opcode_string(inst->opcode) :
+                                   "unknown");
       }
       
       for (i = 0; i < 4; i++)
@@ -1288,8 +1386,3 @@ void brw_wm_emit( struct brw_wm_compile *c )
                      inst->dst[i]->spill_slot);
    }
 }
-
-
-
-
-