i965: Fix fog coordinate g,b,a values when glFrontFacing isn't used.
authorEric Anholt <eric@anholt.net>
Tue, 24 Mar 2009 05:35:03 +0000 (22:35 -0700)
committerEric Anholt <eric@anholt.net>
Tue, 24 Mar 2009 05:52:17 +0000 (22:52 -0700)
Previously, we would sample (f,glFrontFacing,undef,undef) instead of the
(f,0,0,1) that fragment.fogcoord is supposed to return.  Due to
glFrontFacing's presence in FOGC.y, we'll still give bad results there when
glFrontFacing is used.

Bug #19122, piglit testcase fp-fog.

src/mesa/drivers/dri/i965/brw_wm_fp.c

index cff50b85e2645ce75ed18132da73563d9fe0b423..63a7593449ac4cfb015390ddd4d4905692f29aa9 100644 (file)
@@ -363,6 +363,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_PINTERP,
+                dst_mask(dst, WRITEMASK_Y),
+                0,
+                interp,
+                deltas,
+                get_pixel_w(c));
+      } 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,