i965: Fix glFrontFacing in twoside GLSL demo.
authorEric Anholt <eric@anholt.net>
Mon, 23 Mar 2009 23:29:31 +0000 (16:29 -0700)
committerEric Anholt <eric@anholt.net>
Tue, 24 Mar 2009 05:52:51 +0000 (22:52 -0700)
This also cuts instructions by just using the existing bit in the payload
rather than computing it from the determinant in the SF unit and passing it
as a varying down to the WM.  Something still goes wrong with getting the
backface color right, but a simpler shader appears to get the right result.

src/mesa/drivers/dri/i965/brw_sf_emit.c
src/mesa/drivers/dri/i965/brw_wm.c
src/mesa/drivers/dri/i965/brw_wm.h
src/mesa/drivers/dri/i965/brw_wm_debug.c
src/mesa/drivers/dri/i965/brw_wm_emit.c
src/mesa/drivers/dri/i965/brw_wm_fp.c
src/mesa/drivers/dri/i965/brw_wm_glsl.c
src/mesa/drivers/dri/i965/brw_wm_pass1.c

index ffdb0ae6df861b7afa3f33a7832a1b758056e047..862835f157a4f856dabc96d73aa40b081892699f 100644 (file)
@@ -59,37 +59,6 @@ static GLboolean have_attr(struct brw_sf_compile *c,
    return (c->key.attrs & (1<<attr)) ? 1 : 0;
 }
 
-/**
- * Sets VERT_RESULT_FOGC.Y  for gl_FrontFacing
- *
- * This is currently executed if the fragment program uses VERT_RESULT_FOGC
- * at all, but this could be eliminated with a scan of the FP contents.
- */
-static void
-do_front_facing( struct brw_sf_compile *c )
-{
-   struct brw_compile *p = &c->func; 
-   int i;
-
-   if (!have_attr(c, VERT_RESULT_FOGC))
-      return;
-
-   brw_push_insn_state(p);
-   brw_CMP(p, brw_null_reg(), 
-        c->key.frontface_ccw ? BRW_CONDITIONAL_G : BRW_CONDITIONAL_L,
-        c->det, brw_imm_f(0));
-   brw_set_predicate_control(p, BRW_PREDICATE_NONE);
-   for (i = 0; i < 3; i++) {
-       struct brw_reg fogc = get_vert_attr(c, c->vert[i],FRAG_ATTRIB_FOGC);
-       brw_MOV(p, get_element(fogc, 1), brw_imm_f(0));
-       brw_set_predicate_control(p, BRW_PREDICATE_NORMAL);
-       brw_MOV(p, get_element(fogc, 1), brw_imm_f(1));
-       brw_set_predicate_control(p, BRW_PREDICATE_NONE);
-   }
-   brw_pop_insn_state(p);
-}
-
-                        
 /*********************************************************************** 
  * Twoside lighting
  */
@@ -384,7 +353,6 @@ void brw_emit_tri_setup( struct brw_sf_compile *c, GLboolean allocate)
 
    invert_det(c);
    copy_z_inv_w(c);
-   do_front_facing(c);
 
    if (c->key.do_twoside_color) 
       do_twoside_color(c);
index 1645ca0b70e7ce3cfe8bb57074c10b54e0c52e87..7909fd65a9337b0026274ffcdb410d578e24352e 100644 (file)
@@ -40,6 +40,8 @@
 GLuint brw_wm_nr_args( GLuint opcode )
 {
    switch (opcode) {
+   case WM_FRONTFACING:
+      return 0;
    case WM_PIXELXY:
    case WM_CINTERP:
    case WM_WPOSXY:
index 7f0e5702f2ebb928e48d3f6f27bf30c602cea3bb..03dc08fcca9c03a576d0a99d059e732ed0bb1995 100644 (file)
@@ -172,7 +172,8 @@ struct brw_wm_instruction {
 #define WM_CINTERP        (MAX_OPCODE + 5)
 #define WM_WPOSXY         (MAX_OPCODE + 6)
 #define WM_FB_WRITE       (MAX_OPCODE + 7)
-#define MAX_WM_OPCODE     (MAX_OPCODE + 8)
+#define WM_FRONTFACING    (MAX_OPCODE + 8)
+#define MAX_WM_OPCODE     (MAX_OPCODE + 9)
 
 #define PROGRAM_PAYLOAD   (PROGRAM_FILE_MAX)
 #define PAYLOAD_DEPTH     (FRAG_ATTRIB_MAX)
index 8f07f89ebc5979cff6a91d25a4eaf4760cedbf51..220821087c101ad2e8c348427c79be0130d6c724 100644 (file)
@@ -130,6 +130,9 @@ void brw_wm_print_insn( struct brw_wm_compile *c,
    case WM_FB_WRITE:
       _mesa_printf(" = FB_WRITE");
       break;
+   case WM_FRONTFACING:
+      _mesa_printf(" = FRONTFACING");
+      break;
    default:
       _mesa_printf(" = %s", _mesa_opcode_string(inst->opcode));
       break;
index f2dca9caa6c725cff343f14214a922a86de2e138..4372ed3d9a102f42cbcb7d2a7ba0cf858f52935a 100644 (file)
@@ -254,6 +254,34 @@ static void emit_cinterp( struct brw_compile *p,
    }
 }
 
+/* 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 *, 
@@ -1160,6 +1188,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:
index 63a7593449ac4cfb015390ddd4d4905692f29aa9..a7f5f1b9a28c21d232a92adc3ca32b130ae25d70 100644 (file)
@@ -58,7 +58,8 @@ static const char *wm_opcode_strings[] = {
    "PINTERP",
    "CINTERP",
    "WPOSXY",
-   "FB_WRITE"
+   "FB_WRITE",
+   "FRONTFACING",
 };
 
 #if 0
@@ -384,12 +385,12 @@ static void emit_interp( struct brw_wm_compile *c,
       /* Move the front facing value into FOGC.y if it's needed. */
       if (c->fp->program.UsesFrontFacing) {
         emit_op(c,
-                WM_PINTERP,
+                WM_FRONTFACING,
                 dst_mask(dst, WRITEMASK_Y),
                 0,
-                interp,
-                deltas,
-                get_pixel_w(c));
+                src_undef(),
+                src_undef(),
+                src_undef());
       } else {
         emit_op(c,
                 OPCODE_MOV,
index 4cf092226cf2bda902bcfc845508ec3015662e62..b3c15fe87f8cdfceca89bcc8d4ec80b28b1375fa 100644 (file)
@@ -653,6 +653,36 @@ static void emit_pinterp(struct brw_wm_compile *c,
     }
 }
 
+/* Sets the destination channels to 1.0 or 0.0 according to glFrontFacing. */
+static void emit_frontfacing(struct brw_wm_compile *c,
+                            struct prog_instruction *inst)
+{
+    struct brw_compile *p = &c->func;
+    struct brw_reg r1_6ud = retype(brw_vec1_grf(1, 6), BRW_REGISTER_TYPE_UD);
+    struct brw_reg dst;
+    GLuint mask = inst->DstReg.WriteMask;
+    int i;
+
+    for (i = 0; i < 4; i++) {
+       if (mask & (1<<i)) {
+           dst = get_dst_reg(c, inst, i, 1);
+           brw_MOV(p, dst, 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)) {
+           dst = get_dst_reg(c, inst, i, 1);
+           brw_MOV(p, dst, brw_imm_f(1.0));
+       }
+    }
+    brw_set_predicate_control_flag_value(p, 0xff);
+}
+
 static void emit_xpd(struct brw_wm_compile *c,
                struct prog_instruction *inst)
 {
@@ -2435,6 +2465,9 @@ static void brw_wm_emit_glsl(struct brw_context *brw, struct brw_wm_compile *c)
            case WM_FB_WRITE:
                emit_fb_write(c, inst);
                break;
+           case WM_FRONTFACING:
+               emit_frontfacing(c, inst);
+               break;
            case OPCODE_ABS:
                emit_abs(c, inst);
                break;
index cf031899dd23c6d6aaa6b6e7d9d225e9501e25fd..ab9aa2f10d0b6df36ed71cc97b87f8fd2efbe8e6 100644 (file)
@@ -268,6 +268,7 @@ void brw_wm_pass1( struct brw_wm_compile *c )
         break;
 
       case OPCODE_DST:
+      case WM_FRONTFACING:
       default:
         break;
       }