i965/fs: Do flat shading when appropriate.
authorEric Anholt <eric@anholt.net>
Wed, 12 Jan 2011 20:52:16 +0000 (12:52 -0800)
committerEric Anholt <eric@anholt.net>
Wed, 12 Jan 2011 21:51:01 +0000 (13:51 -0800)
We were trying to interpolate, which would end up doing unnecessary
math, and doing so on undefined values.   Fixes glsl-fs-flat-color.

src/mesa/drivers/dri/i965/brw_fs.cpp
src/mesa/drivers/dri/i965/brw_fs.h

index b618ee5b157c4e1c207e91d59e5889ea6ccad05e..d2947eee1f8208dd67880310772caf736c9b657e 100644 (file)
@@ -534,25 +534,40 @@ fs_visitor::emit_general_interpolation(ir_variable *ir)
            continue;
         }
 
-        for (unsigned int c = 0; c < type->vector_elements; c++) {
-           struct brw_reg interp = interp_reg(location, c);
-           emit(fs_inst(FS_OPCODE_LINTERP,
-                        attr,
-                        this->delta_x,
-                        this->delta_y,
-                        fs_reg(interp)));
-           attr.reg_offset++;
-        }
-
-        if (intel->gen < 6) {
-           attr.reg_offset -= type->vector_elements;
+        if (c->key.flat_shade && (location == FRAG_ATTRIB_COL0 ||
+                                  location == FRAG_ATTRIB_COL1)) {
+           /* Constant interpolation (flat shading) case. The SF has
+            * handed us defined values in only the constant offset
+            * field of the setup reg.
+            */
            for (unsigned int c = 0; c < type->vector_elements; c++) {
-              emit(fs_inst(BRW_OPCODE_MUL,
-                           attr,
+              struct brw_reg interp = interp_reg(location, c);
+              interp = suboffset(interp, 3);
+              emit(fs_inst(FS_OPCODE_CINTERP, attr, fs_reg(interp)));
+              attr.reg_offset++;
+           }
+        } else {
+           /* Perspective interpolation case. */
+           for (unsigned int c = 0; c < type->vector_elements; c++) {
+              struct brw_reg interp = interp_reg(location, c);
+              emit(fs_inst(FS_OPCODE_LINTERP,
                            attr,
-                           this->pixel_w));
+                           this->delta_x,
+                           this->delta_y,
+                           fs_reg(interp)));
               attr.reg_offset++;
            }
+
+           if (intel->gen < 6) {
+              attr.reg_offset -= type->vector_elements;
+              for (unsigned int c = 0; c < type->vector_elements; c++) {
+                 emit(fs_inst(BRW_OPCODE_MUL,
+                              attr,
+                              attr,
+                              this->pixel_w));
+                 attr.reg_offset++;
+              }
+           }
         }
         location++;
       }
@@ -2557,12 +2572,15 @@ fs_visitor::assign_urb_setup()
    foreach_iter(exec_list_iterator, iter, this->instructions) {
       fs_inst *inst = (fs_inst *)iter.get();
 
-      if (inst->opcode != FS_OPCODE_LINTERP)
-        continue;
-
-      assert(inst->src[2].file == FIXED_HW_REG);
+      if (inst->opcode == FS_OPCODE_LINTERP) {
+        assert(inst->src[2].file == FIXED_HW_REG);
+        inst->src[2].fixed_hw_reg.nr += urb_start;
+      }
 
-      inst->src[2].fixed_hw_reg.nr += urb_start;
+      if (inst->opcode == FS_OPCODE_CINTERP) {
+        assert(inst->src[0].file == FIXED_HW_REG);
+        inst->src[0].fixed_hw_reg.nr += urb_start;
+      }
    }
 
    this->first_non_payload_grf = urb_start + c->prog_data.urb_read_length;
@@ -3501,6 +3519,9 @@ fs_visitor::generate_code()
       case FS_OPCODE_COS:
         generate_math(inst, dst, src);
         break;
+      case FS_OPCODE_CINTERP:
+        brw_MOV(p, dst, src[0]);
+        break;
       case FS_OPCODE_LINTERP:
         generate_linterp(inst, dst, src);
         break;
index d213c62dcb7e4e3b27ff7c5c3cc24a21293e059f..82d96f6ac0297a1acece61ad015e7dac6ab1180a 100644 (file)
@@ -68,6 +68,7 @@ enum fs_opcodes {
    FS_OPCODE_COS,
    FS_OPCODE_DDX,
    FS_OPCODE_DDY,
+   FS_OPCODE_CINTERP,
    FS_OPCODE_LINTERP,
    FS_OPCODE_TEX,
    FS_OPCODE_TXB,