i965: Fix glFrontFacing in twoside GLSL demo.
[mesa.git] / src / mesa / drivers / dri / i965 / brw_wm_fp.c
index 37766b7c3a05be1847cb351d81762645b634dfcd..a7f5f1b9a28c21d232a92adc3ca32b130ae25d70 100644 (file)
@@ -58,7 +58,8 @@ static const char *wm_opcode_strings[] = {
    "PINTERP",
    "CINTERP",
    "WPOSXY",
-   "FB_WRITE"
+   "FB_WRITE",
+   "FRONTFACING",
 };
 
 #if 0
@@ -129,7 +130,7 @@ static struct prog_dst_register dst_reg(GLuint file, GLuint idx)
    reg.Index = idx;
    reg.WriteMask = WRITEMASK_XYZW;
    reg.RelAddr = 0;
-   reg.CondMask = 0;
+   reg.CondMask = COND_TR;
    reg.CondSwizzle = 0;
    reg.CondSrc = 0;
    reg.pad = 0;
@@ -289,8 +290,7 @@ static struct prog_src_register get_pixel_w( struct brw_wm_compile *c )
       struct prog_dst_register pixel_w = get_temp(c);
       struct prog_src_register deltas = get_delta_xy(c);
       struct prog_src_register interp_wpos = src_reg(PROGRAM_PAYLOAD, FRAG_ATTRIB_WPOS);
-      
-      
+
       /* deltas.xyw = DELTAS2 deltas.xy, payload.interp_wpos.x
        */
       emit_op(c,
@@ -314,18 +314,13 @@ static void emit_interp( struct brw_wm_compile *c,
    struct prog_dst_register dst = dst_reg(PROGRAM_INPUT, idx);
    struct prog_src_register interp = src_reg(PROGRAM_PAYLOAD, idx);
    struct prog_src_register deltas = get_delta_xy(c);
-   struct prog_src_register arg2;
-   GLuint opcode;
-   
+
    /* Need to use PINTERP on attributes which have been
     * multiplied by 1/W in the SF program, and LINTERP on those
     * which have not:
     */
    switch (idx) {
    case FRAG_ATTRIB_WPOS:
-      opcode = WM_LINTERP;
-      arg2 = src_undef();
-
       /* Have to treat wpos.xy specially:
        */
       emit_op(c,
@@ -346,7 +341,7 @@ static void emit_interp( struct brw_wm_compile *c,
              0,
              interp,
              deltas,
-             arg2);
+             src_undef());
       break;
    case FRAG_ATTRIB_COL0:
    case FRAG_ATTRIB_COL1:
@@ -369,6 +364,56 @@ static void emit_interp( struct brw_wm_compile *c,
                 src_undef());
       }
       break;
+   case FRAG_ATTRIB_FOGC:
+      /* The FOGC input is really special.  When a program uses glFogFragCoord,
+       * the results returned are supposed to be (f,0,0,1).  But for Mesa GLSL,
+       * the glFrontFacing and glPointCoord values are also stashed in FOGC.
+       * So, write the interpolated fog value to X, then either 0, 1, or the
+       * stashed values to Y, Z, W.  Note that this means that
+       * glFogFragCoord.yzw can be wrong in those cases!
+       */
+
+      /* Interpolate the fog coordinate */
+      emit_op(c,
+             WM_PINTERP,
+             dst_mask(dst, WRITEMASK_X),
+             0,
+             interp,
+             deltas,
+             get_pixel_w(c));
+
+      /* Move the front facing value into FOGC.y if it's needed. */
+      if (c->fp->program.UsesFrontFacing) {
+        emit_op(c,
+                WM_FRONTFACING,
+                dst_mask(dst, WRITEMASK_Y),
+                0,
+                src_undef(),
+                src_undef(),
+                src_undef());
+      } else {
+        emit_op(c,
+                OPCODE_MOV,
+                dst_mask(dst, WRITEMASK_Y),
+                0,
+                src_swizzle1(interp, SWIZZLE_ZERO),
+                src_undef(),
+                src_undef());
+      }
+
+      /* Should do the PointCoord thing here. */
+      emit_op(c,
+             OPCODE_MOV,
+             dst_mask(dst, WRITEMASK_ZW),
+             0,
+             src_swizzle(interp,
+                         SWIZZLE_ZERO,
+                         SWIZZLE_ZERO,
+                         SWIZZLE_ZERO,
+                         SWIZZLE_ONE),
+             src_undef(),
+             src_undef());
+      break;
    default:
       emit_op(c,
              WM_PINTERP,
@@ -510,7 +555,6 @@ static void precalc_dst( struct brw_wm_compile *c,
              src_undef());
    }
 
-
    if (dst.WriteMask & WRITEMASK_XZ) {
       struct prog_instruction *swz;
       GLuint z = GET_SWZ(src0.Swizzle, Z);
@@ -563,7 +607,6 @@ static void precalc_lit( struct brw_wm_compile *c,
       swz->SrcReg[0].NegateBase = 0;
    }
 
-
    if (dst.WriteMask & WRITEMASK_YZ) {
       emit_op(c,
              OPCODE_LIT,
@@ -865,42 +908,41 @@ static void precalc_txp( struct brw_wm_compile *c,
 static void emit_fb_write( struct brw_wm_compile *c )
 {
    struct prog_src_register payload_r0_depth = src_reg(PROGRAM_PAYLOAD, PAYLOAD_DEPTH);
-   struct prog_src_register outdepth = src_reg(PROGRAM_OUTPUT, FRAG_RESULT_DEPR);
+   struct prog_src_register outdepth = src_reg(PROGRAM_OUTPUT, FRAG_RESULT_DEPTH);
    struct prog_src_register outcolor;
    GLuint i;
 
    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 */
-
-   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);
-          last_inst = inst = emit_op(c,
-                  WM_FB_WRITE, dst_mask(dst_undef(),0), 0,
-                  outcolor, payload_r0_depth, outdepth);
-          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, outcolor, payload_r0_depth, outdepth);
-              inst->Sampler = (i<<1);
-          }
-       }
-       last_inst->Sampler |= 1; //eot
+   /* The inst->Aux field is used for FB write target and the EOT marker */
+
+   if (brw->state.nr_color_regions > 1) {
+      for (i = 0 ; i < brw->state.nr_color_regions; i++) {
+         outcolor = src_reg(PROGRAM_OUTPUT, FRAG_RESULT_DATA0 + i);
+         last_inst = inst = emit_op(c,
+                                    WM_FB_WRITE, dst_mask(dst_undef(),0), 0,
+                                    outcolor, payload_r0_depth, outdepth);
+         inst->Aux = (i<<1);
+         if (c->fp_fragcolor_emitted) {
+            outcolor = src_reg(PROGRAM_OUTPUT, FRAG_RESULT_COLOR);
+            last_inst = inst = emit_op(c, WM_FB_WRITE, dst_mask(dst_undef(),0),
+                                       0, outcolor, payload_r0_depth, outdepth);
+            inst->Aux = (i<<1);
+         }
+      }
+      last_inst->Aux |= 1; //eot
    }
    else {
       /* if gl_FragData[0] is written, use it, else use gl_FragColor */
       if (c->fp->program.Base.OutputsWritten & (1 << FRAG_RESULT_DATA0))
          outcolor = src_reg(PROGRAM_OUTPUT, FRAG_RESULT_DATA0);
       else 
-         outcolor = src_reg(PROGRAM_OUTPUT, FRAG_RESULT_COLR);
+         outcolor = src_reg(PROGRAM_OUTPUT, FRAG_RESULT_COLOR);
 
-       inst = emit_op(c, WM_FB_WRITE, dst_mask(dst_undef(),0),
-              0, outcolor, payload_r0_depth, outdepth);
-       inst->Sampler = 1|(0<<1);
+      inst = emit_op(c, WM_FB_WRITE, dst_mask(dst_undef(),0),
+                     0, outcolor, payload_r0_depth, outdepth);
+      inst->Aux = 1|(0<<1);
    }
 }
 
@@ -931,9 +973,9 @@ 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;
+      GLuint idx = inst->DstReg.Index;
+      if (idx == FRAG_RESULT_COLOR)
+         c->fp_fragcolor_emitted = 1;
    }
 }
 
@@ -953,8 +995,7 @@ static void print_insns( const struct prog_instruction *insn,
                                     3);
       }
       else 
-        _mesa_printf("UNKNOWN\n");
-          
+        _mesa_printf("965 Opcode %d\n", insn->Opcode);
    }
 }
 
@@ -1079,9 +1120,9 @@ void brw_wm_pass_fp( struct brw_wm_compile *c )
    }
 
    if (INTEL_DEBUG & DEBUG_WM) {
-          _mesa_printf("pass_fp:\n");
-          print_insns( c->prog_instructions, c->nr_fp_insns );
-          _mesa_printf("\n");
+      _mesa_printf("pass_fp:\n");
+      print_insns( c->prog_instructions, c->nr_fp_insns );
+      _mesa_printf("\n");
    }
 }