i965/fs: Add support for computing pixel_[xy] in 16-wide.
authorEric Anholt <eric@anholt.net>
Mon, 21 Mar 2011 22:54:18 +0000 (15:54 -0700)
committerEric Anholt <eric@anholt.net>
Tue, 26 Apr 2011 19:19:25 +0000 (12:19 -0700)
Reviewed-by: Kenneth Graunke <kenneth@whitecape.org>
src/mesa/drivers/dri/i965/brw_fs.cpp
src/mesa/drivers/dri/i965/brw_fs.h

index 44eb1be51083dac6b4b6b9ab81e2d4a22b6c6816..05b6e290deeab12cccaa052b35f0cccaec95e84e 100644 (file)
@@ -1916,21 +1916,14 @@ fs_visitor::interp_reg(int location, int channel)
 void
 fs_visitor::emit_interpolation_setup_gen4()
 {
-   struct brw_reg g1_uw = retype(brw_vec1_grf(1, 0), BRW_REGISTER_TYPE_UW);
-
    this->current_annotation = "compute pixel centers";
    this->pixel_x = fs_reg(this, glsl_type::uint_type);
    this->pixel_y = fs_reg(this, glsl_type::uint_type);
    this->pixel_x.type = BRW_REGISTER_TYPE_UW;
    this->pixel_y.type = BRW_REGISTER_TYPE_UW;
-   emit(BRW_OPCODE_ADD,
-       this->pixel_x,
-       fs_reg(stride(suboffset(g1_uw, 4), 2, 4, 0)),
-       fs_reg(brw_imm_v(0x10101010)));
-   emit(BRW_OPCODE_ADD,
-       this->pixel_y,
-       fs_reg(stride(suboffset(g1_uw, 5), 2, 4, 0)),
-       fs_reg(brw_imm_v(0x11001100)));
+
+   emit(FS_OPCODE_PIXEL_X, this->pixel_x);
+   emit(FS_OPCODE_PIXEL_Y, this->pixel_y);
 
    this->current_annotation = "compute pixel deltas from v0";
    if (brw->has_pln) {
@@ -2154,6 +2147,40 @@ fs_visitor::generate_fb_write(fs_inst *inst)
                inst->header_present);
 }
 
+/* Computes the integer pixel x,y values from the origin.
+ *
+ * This is the basis of gl_FragCoord computation, but is also used
+ * pre-gen6 for computing the deltas from v0 for computing
+ * interpolation.
+ */
+void
+fs_visitor::generate_pixel_xy(struct brw_reg dst, bool is_x)
+{
+   struct brw_reg g1_uw = retype(brw_vec1_grf(1, 0), BRW_REGISTER_TYPE_UW);
+   struct brw_reg src;
+   struct brw_reg deltas;
+
+   if (is_x) {
+      src = stride(suboffset(g1_uw, 4), 2, 4, 0);
+      deltas = brw_imm_v(0x10101010);
+   } else {
+      src = stride(suboffset(g1_uw, 5), 2, 4, 0);
+      deltas = brw_imm_v(0x11001100);
+   }
+
+   if (c->dispatch_width == 16) {
+      dst = vec16(dst);
+   }
+
+   /* We do this 8 or 16-wide, but since the destination is UW we
+    * don't do compression in the 16-wide case.
+    */
+   brw_push_insn_state(p);
+   brw_set_compression_control(p, BRW_COMPRESSION_NONE);
+   brw_ADD(p, dst, src, deltas);
+   brw_pop_insn_state(p);
+}
+
 void
 fs_visitor::generate_linterp(fs_inst *inst,
                             struct brw_reg dst, struct brw_reg *src)
@@ -3601,6 +3628,12 @@ fs_visitor::generate_code()
       case FS_OPCODE_COS:
         generate_math(inst, dst, src);
         break;
+      case FS_OPCODE_PIXEL_X:
+        generate_pixel_xy(dst, true);
+        break;
+      case FS_OPCODE_PIXEL_Y:
+        generate_pixel_xy(dst, false);
+        break;
       case FS_OPCODE_CINTERP:
         brw_MOV(p, dst, src[0]);
         break;
index f792906cfe79afeb41132c6818a859d82df0823d..fd83fcb3829bf67e3d02409ec21474c5f4db9cb8 100644 (file)
@@ -67,6 +67,8 @@ enum fs_opcodes {
    FS_OPCODE_COS,
    FS_OPCODE_DDX,
    FS_OPCODE_DDY,
+   FS_OPCODE_PIXEL_X,
+   FS_OPCODE_PIXEL_Y,
    FS_OPCODE_CINTERP,
    FS_OPCODE_LINTERP,
    FS_OPCODE_TEX,
@@ -481,6 +483,7 @@ public:
 
    void generate_code();
    void generate_fb_write(fs_inst *inst);
+   void generate_pixel_xy(struct brw_reg dst, bool is_x);
    void generate_linterp(fs_inst *inst, struct brw_reg dst,
                         struct brw_reg *src);
    void generate_tex(fs_inst *inst, struct brw_reg dst, struct brw_reg src);