Merge branch 'mesa_7_5_branch'
[mesa.git] / src / mesa / drivers / dri / i965 / brw_wm_emit.c
index 0000edda8434b0be0c91d1b27deb9d2f74d4387f..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++;
@@ -194,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]);
@@ -219,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 *, 
@@ -276,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, 
@@ -322,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,
@@ -347,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,
@@ -372,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, 
@@ -381,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, 
@@ -390,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, 
@@ -399,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, 
@@ -408,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, 
@@ -417,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, 
@@ -500,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]);
@@ -517,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]);
@@ -535,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]);
@@ -578,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);
    
@@ -602,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);
@@ -652,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?
     */
@@ -674,7 +734,7 @@ static void emit_tex( struct brw_wm_compile *c,
       break;
    }
 
-   if (shadow) {
+   if (inst->tex_shadow) {
       nr = 4;
       emit |= WRITEMASK_W;
    }
@@ -692,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 + MAX_DRAW_BUFFERS, /* 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);    
 }
 
 
@@ -719,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) {
@@ -744,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 + MAX_DRAW_BUFFERS, /* 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);    
 }
 
 
@@ -807,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++) {
@@ -820,6 +893,7 @@ static void emit_kil( struct brw_wm_compile *c,
    }
 }
 
+
 static void fire_fb_write( struct brw_wm_compile *c,
                           GLuint base_reg,
                           GLuint nr,
@@ -853,6 +927,7 @@ static void fire_fb_write( struct brw_wm_compile *c,
                eot);
 }
 
+
 static void emit_aa( struct brw_wm_compile *c,
                     struct brw_reg *arg1,
                     GLuint reg )
@@ -871,6 +946,9 @@ 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,
@@ -932,20 +1010,20 @@ 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);
@@ -964,7 +1042,7 @@ 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, target, eot);
@@ -979,10 +1057,8 @@ static void emit_fb_write( struct brw_wm_compile *c,
 }
 
 
-
-
-/* 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,
@@ -1001,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 )
@@ -1025,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[],
@@ -1042,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();
@@ -1056,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 )
@@ -1068,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 )
@@ -1145,6 +1225,10 @@ void brw_wm_emit( struct brw_wm_compile *c )
         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:
          */
       case OPCODE_ADD:
@@ -1159,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;
 
@@ -1171,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;
 
@@ -1285,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++)
@@ -1296,8 +1386,3 @@ void brw_wm_emit( struct brw_wm_compile *c )
                      inst->dst[i]->spill_slot);
    }
 }
-
-
-
-
-