static void emit_sop(struct brw_wm_compile *c,
		struct prog_instruction *inst, GLuint cond)
{
    struct brw_compile *p = &c->func;
    GLuint mask = inst->DstReg.WriteMask;
    struct brw_reg dst, src0, src1;
    int i;

    for (i = 0; i < 4; i++) {
	if (mask & (1<<i)) {
	    dst = get_dst_reg(c, inst, i, 1);
	    src0 = get_src_reg(c, &inst->SrcReg[0], i, 1);
	    src1 = get_src_reg(c, &inst->SrcReg[1], i, 1);
	    brw_push_insn_state(p);
	    brw_CMP(p, brw_null_reg(), cond, src0, src1);
	    brw_set_predicate_control(p, BRW_PREDICATE_NONE);
	    brw_MOV(p, dst, brw_imm_f(0.0));
	    brw_set_predicate_control(p, BRW_PREDICATE_NORMAL);
	    brw_MOV(p, dst, brw_imm_f(1.0));
	    brw_pop_insn_state(p);
	}
    }
}
/**
 * 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);
}
Esempio n. 3
0
void brw_clip_tri_init_vertices( struct brw_clip_compile *c )
{
   struct brw_compile *p = &c->func;
   struct brw_reg tmp0 = c->reg.loopcount; /* handy temporary */

   /* Initial list of indices for incoming vertexes:
    */
   brw_AND(p, tmp0, get_element_ud(c->reg.R0, 2), brw_imm_ud(PRIM_MASK)); 
   brw_CMP(p, 
	   vec1(brw_null_reg()), 
	   BRW_CONDITIONAL_EQ, 
	   tmp0,
	   brw_imm_ud(_3DPRIM_TRISTRIP_REVERSE));

   /* XXX: Is there an easier way to do this?  Need to reverse every
    * second tristrip element:  Can ignore sometimes?
    */
   brw_IF(p, BRW_EXECUTE_1);
   {   
      brw_MOV(p, get_element(c->reg.inlist, 0),  brw_address(c->reg.vertex[1]) );
      brw_MOV(p, get_element(c->reg.inlist, 1),  brw_address(c->reg.vertex[0]) );
      if (c->need_direction)
	 brw_MOV(p, c->reg.dir, brw_imm_f(-1));
   }
   brw_ELSE(p);
   {
      brw_MOV(p, get_element(c->reg.inlist, 0),  brw_address(c->reg.vertex[0]) );
      brw_MOV(p, get_element(c->reg.inlist, 1),  brw_address(c->reg.vertex[1]) );
      if (c->need_direction)
	 brw_MOV(p, c->reg.dir, brw_imm_f(1));
   }
   brw_ENDIF(p);

   brw_MOV(p, get_element(c->reg.inlist, 2),  brw_address(c->reg.vertex[2]) );
   brw_MOV(p, brw_vec8_grf(c->reg.outlist.nr, 0), brw_imm_f(0));
   brw_MOV(p, c->reg.nr_verts, brw_imm_ud(3));
}
Esempio n. 4
0
static void emit_lit(struct brw_wm_compile *c,
		     const struct brw_reg *dst,
		     GLuint mask,
		     const struct brw_reg *arg0)
{
   struct brw_compile *p = &c->func;

   assert((mask & WRITEMASK_XW) == 0);

   if (mask & WRITEMASK_Y) {
      brw_set_saturate(p, (mask & SATURATE) ? 1 : 0);
      brw_MOV(p, dst[1], arg0[0]);
      brw_set_saturate(p, 0);
   }

   if (mask & WRITEMASK_Z) {
      emit_math2(c, BRW_MATH_FUNCTION_POW,
		 &dst[2],
		 WRITEMASK_X | (mask & SATURATE),
		 &arg0[1],
		 &arg0[3]);
   }

   /* Ordinarily you'd use an iff statement to skip or shortcircuit
    * some of the POW calculations above, but 16-wide iff statements
    * seem to lock c1 hardware, so this is a nasty workaround:
    */
   brw_CMP(p, brw_null_reg(), BRW_CONDITIONAL_LE, arg0[0], brw_imm_f(0));
   {
      if (mask & WRITEMASK_Y) 
	 brw_MOV(p, dst[1], brw_imm_f(0));

      if (mask & WRITEMASK_Z) 
	 brw_MOV(p, dst[2], brw_imm_f(0)); 
   }
   brw_set_predicate_control(p, BRW_PREDICATE_NONE);
}
Esempio n. 5
0
static void merge_edgeflags( struct brw_clip_compile *c )
{
   struct brw_compile *p = &c->func;
   const struct brw_context *brw = p->brw;
   struct brw_reg tmp0 = get_element_ud(c->reg.tmp0, 0);

   brw_AND(p, tmp0, get_element_ud(c->reg.R0, 2), brw_imm_ud(PRIM_MASK));
   brw_CMP(p,
	   vec1(brw_null_reg()),
	   BRW_CONDITIONAL_EQ,
	   tmp0,
	   brw_imm_ud(_3DPRIM_POLYGON));

   /* Get away with using reg.vertex because we know that this is not
    * a _3DPRIM_TRISTRIP_REVERSE:
    */
   brw_IF(p, BRW_EXECUTE_1);
   {
      brw_AND(p, vec1(brw_null_reg()), get_element_ud(c->reg.R0, 2), brw_imm_ud(1<<8));
      brw_inst_set_cond_modifier(brw, brw_last_inst, BRW_CONDITIONAL_EQ);
      brw_MOV(p, byte_offset(c->reg.vertex[0],
                             brw_varying_to_offset(&c->vue_map,
                                                   VARYING_SLOT_EDGE)),
              brw_imm_f(0));
      brw_inst_set_pred_control(brw, brw_last_inst, BRW_PREDICATE_NORMAL);

      brw_AND(p, vec1(brw_null_reg()), get_element_ud(c->reg.R0, 2), brw_imm_ud(1<<9));
      brw_inst_set_cond_modifier(brw, brw_last_inst, BRW_CONDITIONAL_EQ);
      brw_MOV(p, byte_offset(c->reg.vertex[2],
                             brw_varying_to_offset(&c->vue_map,
                                                   VARYING_SLOT_EDGE)),
              brw_imm_f(0));
      brw_inst_set_pred_control(brw, brw_last_inst, BRW_PREDICATE_NORMAL);
   }
   brw_ENDIF(p);
}
Esempio n. 6
0
static void copy_bfc( struct brw_clip_compile *c )
{
   struct brw_compile *p = &c->func;
   struct brw_instruction *ccw;
   GLuint conditional;

   /* Do we have any colors to copy? 
    */
   if (!(c->offset[VERT_RESULT_COL0] && c->offset[VERT_RESULT_BFC0]) &&
       !(c->offset[VERT_RESULT_COL1] && c->offset[VERT_RESULT_BFC1]))
      return;

   /* In some wierd degnerate cases we can end up testing the
    * direction twice, once for culling and once for bfc copying.  Oh
    * well, that's what you get for setting wierd GL state.
    */
   if (c->key.copy_bfc_ccw)
      conditional = BRW_CONDITIONAL_GE;
   else
      conditional = BRW_CONDITIONAL_L;

   brw_CMP(p,
	   vec1(brw_null_reg()),
	   conditional,
	   get_element(c->reg.dir, 2),
	   brw_imm_f(0));
   
   ccw = brw_IF(p, BRW_EXECUTE_1);
   {
      GLuint i;

      for (i = 0; i < 3; i++) {
	 if (c->offset[VERT_RESULT_COL0] && c->offset[VERT_RESULT_BFC0])
	    brw_MOV(p, 
		    byte_offset(c->reg.vertex[i], c->offset[VERT_RESULT_COL0]),
		    byte_offset(c->reg.vertex[i], c->offset[VERT_RESULT_BFC0]));

	 if (c->offset[VERT_RESULT_COL1] && c->offset[VERT_RESULT_BFC1])
	    brw_MOV(p, 
		    byte_offset(c->reg.vertex[i], c->offset[VERT_RESULT_COL1]),
		    byte_offset(c->reg.vertex[i], c->offset[VERT_RESULT_BFC1]));
      }
   }
   brw_ENDIF(p, ccw);
}
/* Kill pixel - set execution mask to zero for those pixels which
 * fail.
 */
static void emit_kil( struct brw_wm_compile *c,
		      struct brw_reg *arg0)
{
   struct brw_compile *p = &c->func;
   struct brw_reg r0uw = retype(brw_vec1_grf(0, 0), BRW_REGISTER_TYPE_UW);
   GLuint i;
   

   /* XXX - usually won't need 4 compares!
    */
   for (i = 0; i < 4; i++) {
      brw_push_insn_state(p);
      brw_CMP(p, brw_null_reg(), BRW_CONDITIONAL_GE, arg0[i], brw_imm_f(0));   
      brw_set_predicate_control_flag_value(p, 0xff);
      brw_set_compression_control(p, BRW_COMPRESSION_NONE);
      brw_AND(p, r0uw, brw_flag_reg(), r0uw);
      brw_pop_insn_state(p);
   }
}
Esempio n. 8
0
/**
 * Load a GPR from scratch memory. 
 */
static void emit_unspill( struct brw_wm_compile *c,
			  struct brw_reg reg,
			  GLuint slot )
{
   struct brw_compile *p = &c->func;

   /* Slot 0 is the undef value.
    */
   if (slot == 0) {
      brw_MOV(p, reg, brw_imm_f(0));
      return;
   }

   /*
     mov (1) r0.2<1>:d    0x000000c0:d     { Align1 NoMask }
     send (16) r110.0<1>:uw m1               r0.0<8;8,1>:uw   0x041243ff:ud    { Align1 }
   */

   brw_oword_block_read(p, vec16(reg), brw_message_reg(1), 2, slot);
}
Esempio n. 9
0
void emit_cmp(struct brw_compile *p,
	      const struct brw_reg *dst,
	      GLuint mask,
	      const struct brw_reg *arg0,
	      const struct brw_reg *arg1,
	      const struct brw_reg *arg2)
{
   GLuint i;

   for (i = 0; i < 4; i++) {
      if (mask & (1<<i)) {	
	 brw_CMP(p, brw_null_reg(), BRW_CONDITIONAL_L, arg0[i], brw_imm_f(0));

	 brw_set_saturate(p, (mask & SATURATE) ? 1 : 0);
	 brw_SEL(p, dst[i], arg1[i], arg2[i]);
	 brw_set_saturate(p, 0);
	 brw_set_predicate_control_flag_value(p, 0xff);
      }
   }
}
Esempio n. 10
0
static void emit_points(struct brw_clip_compile *c,
			bool do_offset )
{
   struct brw_compile *p = &c->func;
   const struct brw_context *brw = p->brw;

   struct brw_indirect v0 = brw_indirect(0, 0);
   struct brw_indirect v0ptr = brw_indirect(2, 0);

   brw_MOV(p, c->reg.loopcount, c->reg.nr_verts);
   brw_MOV(p, get_addr_reg(v0ptr), brw_address(c->reg.inlist));

   brw_DO(p, BRW_EXECUTE_1);
   {
      brw_MOV(p, get_addr_reg(v0), deref_1uw(v0ptr, 0));
      brw_ADD(p, get_addr_reg(v0ptr), get_addr_reg(v0ptr), brw_imm_uw(2));

      /* draw if edgeflag != 0
       */
      brw_CMP(p,
	      vec1(brw_null_reg()), BRW_CONDITIONAL_NZ,
	      deref_1f(v0, brw_varying_to_offset(&c->vue_map,
                                                 VARYING_SLOT_EDGE)),
	      brw_imm_f(0));
      brw_IF(p, BRW_EXECUTE_1);
      {
	 if (do_offset)
	    apply_one_offset(c, v0);

	 brw_clip_emit_vue(c, v0, BRW_URB_WRITE_ALLOCATE_COMPLETE,
                           (_3DPRIM_POINTLIST << URB_WRITE_PRIM_TYPE_SHIFT)
                           | URB_WRITE_PRIM_START | URB_WRITE_PRIM_END);
      }
      brw_ENDIF(p);

      brw_ADD(p, c->reg.loopcount, c->reg.loopcount, brw_imm_d(-1));
      brw_inst_set_cond_modifier(brw, brw_last_inst, BRW_CONDITIONAL_NZ);
   }
   brw_WHILE(p);
   brw_inst_set_pred_control(brw, brw_last_inst, BRW_PREDICATE_NORMAL);
}
Esempio n. 11
0
static void do_twoside_color( struct brw_sf_compile *c )
{
    struct brw_compile *p = &c->func;
    GLuint backface_conditional = c->key.frontface_ccw ? BRW_CONDITIONAL_G : BRW_CONDITIONAL_L;

    /* Already done in clip program:
     */
    if (c->key.primitive == SF_UNFILLED_TRIS)
        return;

    /* XXX: What happens if BFC isn't present?  This could only happen
     * for user-supplied vertex programs, as t_vp_build.c always does
     * the right thing.
     */
    if (!(have_attr(c, VERT_RESULT_COL0) && have_attr(c, VERT_RESULT_BFC0)) &&
            !(have_attr(c, VERT_RESULT_COL1) && have_attr(c, VERT_RESULT_BFC1)))
        return;

    /* Need to use BRW_EXECUTE_4 and also do an 4-wide compare in order
     * to get all channels active inside the IF.  In the clipping code
     * we run with NoMask, so it's not an option and we can use
     * BRW_EXECUTE_1 for all comparisions.
     */
    brw_push_insn_state(p);
    brw_CMP(p, vec4(brw_null_reg()), backface_conditional, c->det, brw_imm_f(0));
    brw_IF(p, BRW_EXECUTE_4);
    {
        switch (c->nr_verts) {
        case 3:
            copy_bfc(c, c->vert[2]);
        case 2:
            copy_bfc(c, c->vert[1]);
        case 1:
            copy_bfc(c, c->vert[0]);
        }
    }
    brw_ENDIF(p);
    brw_pop_insn_state(p);
}
Esempio n. 12
0
static void emit_points(struct brw_clip_compile *c,
			bool do_offset )
{
   struct brw_compile *p = &c->func;

   struct brw_indirect v0 = brw_indirect(0, 0);
   struct brw_indirect v0ptr = brw_indirect(2, 0);

   brw_MOV(p, c->reg.loopcount, c->reg.nr_verts);
   brw_MOV(p, get_addr_reg(v0ptr), brw_address(c->reg.inlist));

   brw_DO(p, BRW_EXECUTE_1);
   {
      brw_MOV(p, get_addr_reg(v0), deref_1uw(v0ptr, 0));
      brw_ADD(p, get_addr_reg(v0ptr), get_addr_reg(v0ptr), brw_imm_uw(2));

      /* draw if edgeflag != 0 
       */
      brw_CMP(p, 
	      vec1(brw_null_reg()), BRW_CONDITIONAL_NZ, 
	      deref_1f(v0, brw_vert_result_to_offset(&c->vue_map,
                                                     VARYING_SLOT_EDGE)),
	      brw_imm_f(0));
      brw_IF(p, BRW_EXECUTE_1);
      {
	 if (do_offset)
	    apply_one_offset(c, v0);

	 brw_clip_emit_vue(c, v0, 1, 0,
                           (_3DPRIM_POINTLIST << URB_WRITE_PRIM_TYPE_SHIFT)
                           | URB_WRITE_PRIM_START | URB_WRITE_PRIM_END);
      }
      brw_ENDIF(p);

      brw_set_conditionalmod(p, BRW_CONDITIONAL_NZ);
      brw_ADD(p, c->reg.loopcount, c->reg.loopcount, brw_imm_d(-1));
   }
   brw_WHILE(p);
}
Esempio n. 13
0
static void emit_points(struct brw_clip_compile *c,
			GLboolean do_offset )
{
   struct brw_compile *p = &c->func;
   struct brw_instruction *loop;
   struct brw_instruction *draw_point;

   struct brw_indirect v0 = brw_indirect(0, 0);
   struct brw_indirect v0ptr = brw_indirect(2, 0);

   brw_MOV(p, c->reg.loopcount, c->reg.nr_verts);
   brw_MOV(p, get_addr_reg(v0ptr), brw_address(c->reg.inlist));

   loop = brw_DO(p, BRW_EXECUTE_1);
   {
      brw_MOV(p, get_addr_reg(v0), deref_1uw(v0ptr, 0));
      brw_ADD(p, get_addr_reg(v0ptr), get_addr_reg(v0ptr), brw_imm_uw(2));

      /* draw if edgeflag != 0 
       */
      brw_CMP(p, 
	      vec1(brw_null_reg()), BRW_CONDITIONAL_NZ, 
	      deref_1f(v0, c->offset[VERT_RESULT_EDGE]),
	      brw_imm_f(0));
      draw_point = brw_IF(p, BRW_EXECUTE_1);
      {
	 if (do_offset)
	    apply_one_offset(c, v0);

	 brw_clip_emit_vue(c, v0, 1, 0, (_3DPRIM_POINTLIST << 2) | R02_PRIM_START | R02_PRIM_END);
      }
      brw_ENDIF(p, draw_point);

      brw_set_conditionalmod(p, BRW_CONDITIONAL_NZ);
      brw_ADD(p, c->reg.loopcount, c->reg.loopcount, brw_imm_d(-1));
   }
   brw_WHILE(p, loop);
}
static void emit_unspill( struct brw_wm_compile *c,
			  struct brw_reg reg,
			  GLuint slot )
{
   struct brw_compile *p = &c->func;

   /* Slot 0 is the undef value.
    */
   if (slot == 0) {
      brw_MOV(p, reg, brw_imm_f(0));
      return;
   }

   /*
     mov (1) r0.2<1>:d    0x000000c0:d     { Align1 NoMask }
     send (16) r110.0<1>:uw m1               r0.0<8;8,1>:uw   0x041243ff:ud    { Align1 }
   */

   brw_dp_READ_16(p,
		  retype(vec16(reg), BRW_REGISTER_TYPE_UW),
		  1, 
		  slot);
}
Esempio n. 15
0
/**
 * Loads the clip distance for a vertex into `dst`, and ends with
 * a comparison of it to zero with the condition `cond`.
 *
 * - If using a fixed plane, the distance is dot(hpos, plane).
 * - If using a user clip plane, the distance is directly available in the vertex.
 */
static inline void
load_clip_distance(struct brw_clip_compile *c, struct brw_indirect vtx,
                struct brw_reg dst, GLuint hpos_offset, int cond)
{
   struct brw_codegen *p = &c->func;

   dst = vec4(dst);
   brw_AND(p, vec1(brw_null_reg()), c->reg.vertex_src_mask, brw_imm_ud(1));
   brw_inst_set_cond_modifier(p->devinfo, brw_last_inst, BRW_CONDITIONAL_NZ);
   brw_IF(p, BRW_EXECUTE_1);
   {
      struct brw_indirect temp_ptr = brw_indirect(7, 0);
      brw_ADD(p, get_addr_reg(temp_ptr), get_addr_reg(vtx), c->reg.clipdistance_offset);
      brw_MOV(p, vec1(dst), deref_1f(temp_ptr, 0));
   }
   brw_ELSE(p);
   {
      brw_MOV(p, dst, deref_4f(vtx, hpos_offset));
      brw_DP4(p, dst, dst, c->reg.plane_equation);
   }
   brw_ENDIF(p);

   brw_CMP(p, brw_null_reg(), cond, vec1(dst), brw_imm_f(0.0f));
}
static void emit_lrp(struct brw_wm_compile *c,
		struct prog_instruction *inst)
{
    struct brw_compile *p = &c->func;
    GLuint mask = inst->DstReg.WriteMask;
    struct brw_reg dst, tmp1, tmp2, src0, src1, src2;
    int i;
    for (i = 0; i < 4; i++) {
	if (mask & (1<<i)) {
	    dst = get_dst_reg(c, inst, i, 1);
	    src0 = get_src_reg(c, &inst->SrcReg[0], i, 1);

	    src1 = get_src_reg(c, &inst->SrcReg[1], i, 1);

	    if (src1.nr == dst.nr) {
		tmp1 = alloc_tmp(c);
		brw_MOV(p, tmp1, src1);
	    } else
		tmp1 = src1;

	    src2 = get_src_reg(c, &inst->SrcReg[2], i, 1);
	    if (src2.nr == dst.nr) {
		tmp2 = alloc_tmp(c);
		brw_MOV(p, tmp2, src2);
	    } else
		tmp2 = src2;

	    brw_ADD(p, dst, negate(src0), brw_imm_f(1.0));
	    brw_MUL(p, brw_null_reg(), dst, tmp2);
	    brw_set_saturate(p, (inst->SaturateMode != SATURATE_OFF) ? 1 : 0);
	    brw_MAC(p, dst, src0, tmp1);
	    brw_set_saturate(p, 0);
	}
	release_tmps(c);
    }
}
Esempio n. 17
0
void emit_lrp(struct brw_compile *p,
	      const struct brw_reg *dst,
	      GLuint mask,
	      const struct brw_reg *arg0,
	      const struct brw_reg *arg1,
	      const struct brw_reg *arg2)
{
   GLuint i;

   /* Uses dst as a temporary:
    */
   for (i = 0; i < 4; i++) {
      if (mask & (1<<i)) {	
	 /* Can I use the LINE instruction for this? 
	  */
	 brw_ADD(p, dst[i], negate(arg0[i]), brw_imm_f(1.0));
	 brw_MUL(p, brw_null_reg(), dst[i], arg2[i]);

	 brw_set_saturate(p, (mask & SATURATE) ? 1 : 0);
	 brw_MAC(p, dst[i], arg0[i], arg1[i]);
	 brw_set_saturate(p, 0);
      }
   }
}
Esempio n. 18
0
/* Line clipping, more or less following the following algorithm:
 *
 *  for (p=0;p<MAX_PLANES;p++) {
 *     if (clipmask & (1 << p)) {
 *        GLfloat dp0 = DOTPROD( vtx0, plane[p] );
 *        GLfloat dp1 = DOTPROD( vtx1, plane[p] );
 *
 *        if (dp1 < 0.0f) {
 *           GLfloat t = dp1 / (dp1 - dp0);
 *           if (t > t1) t1 = t;
 *        } else {
 *           GLfloat t = dp0 / (dp0 - dp1);
 *           if (t > t0) t0 = t;
 *        }
 *
 *        if (t0 + t1 >= 1.0)
 *           return;
 *     }
 *  }
 *
 *  interp( ctx, newvtx0, vtx0, vtx1, t0 );
 *  interp( ctx, newvtx1, vtx1, vtx0, t1 );
 *
 */
static void clip_and_emit_line( struct brw_clip_compile *c )
{
   struct brw_codegen *p = &c->func;
   struct brw_indirect vtx0     = brw_indirect(0, 0);
   struct brw_indirect vtx1      = brw_indirect(1, 0);
   struct brw_indirect newvtx0   = brw_indirect(2, 0);
   struct brw_indirect newvtx1   = brw_indirect(3, 0);
   struct brw_indirect plane_ptr = brw_indirect(4, 0);
   struct brw_reg v1_null_ud = retype(vec1(brw_null_reg()), BRW_REGISTER_TYPE_UD);
   GLuint hpos_offset = brw_varying_to_offset(&c->vue_map, VARYING_SLOT_POS);
   GLint clipdist0_offset = c->key.nr_userclip
      ? brw_varying_to_offset(&c->vue_map, VARYING_SLOT_CLIP_DIST0)
      : 0;

   brw_MOV(p, get_addr_reg(vtx0),      brw_address(c->reg.vertex[0]));
   brw_MOV(p, get_addr_reg(vtx1),      brw_address(c->reg.vertex[1]));
   brw_MOV(p, get_addr_reg(newvtx0),   brw_address(c->reg.vertex[2]));
   brw_MOV(p, get_addr_reg(newvtx1),   brw_address(c->reg.vertex[3]));
   brw_MOV(p, get_addr_reg(plane_ptr), brw_clip_plane0_address(c));

   /* Note: init t0, t1 together:
    */
   brw_MOV(p, vec2(c->reg.t0), brw_imm_f(0));

   brw_clip_init_planes(c);
   brw_clip_init_clipmask(c);

   /* -ve rhw workaround */
   if (p->devinfo->has_negative_rhw_bug) {
      brw_AND(p, brw_null_reg(), get_element_ud(c->reg.R0, 2),
              brw_imm_ud(1<<20));
      brw_inst_set_cond_modifier(p->devinfo, brw_last_inst, BRW_CONDITIONAL_NZ);
      brw_OR(p, c->reg.planemask, c->reg.planemask, brw_imm_ud(0x3f));
      brw_inst_set_pred_control(p->devinfo, brw_last_inst, BRW_PREDICATE_NORMAL);
   }

   /* Set the initial vertex source mask: The first 6 planes are the bounds
    * of the view volume; the next 8 planes are the user clipping planes.
    */
   brw_MOV(p, c->reg.vertex_src_mask, brw_imm_ud(0x3fc0));

   /* Set the initial clipdistance offset to be 6 floats before gl_ClipDistance[0].
    * We'll increment 6 times before we start hitting actual user clipping. */
   brw_MOV(p, c->reg.clipdistance_offset, brw_imm_d(clipdist0_offset - 6*sizeof(float)));

   brw_DO(p, BRW_EXECUTE_1);
   {
      /* if (planemask & 1)
       */
      brw_AND(p, v1_null_ud, c->reg.planemask, brw_imm_ud(1));
      brw_inst_set_cond_modifier(p->devinfo, brw_last_inst, BRW_CONDITIONAL_NZ);

      brw_IF(p, BRW_EXECUTE_1);
      {
         brw_AND(p, v1_null_ud, c->reg.vertex_src_mask, brw_imm_ud(1));
         brw_inst_set_cond_modifier(p->devinfo, brw_last_inst, BRW_CONDITIONAL_NZ);
         brw_IF(p, BRW_EXECUTE_1);
         {
            /* user clip distance: just fetch the correct float from each vertex */
            struct brw_indirect temp_ptr = brw_indirect(7, 0);
            brw_ADD(p, get_addr_reg(temp_ptr), get_addr_reg(vtx0), c->reg.clipdistance_offset);
            brw_MOV(p, c->reg.dp0, deref_1f(temp_ptr, 0));
            brw_ADD(p, get_addr_reg(temp_ptr), get_addr_reg(vtx1), c->reg.clipdistance_offset);
            brw_MOV(p, c->reg.dp1, deref_1f(temp_ptr, 0));
         }
         brw_ELSE(p);
         {
            /* fixed plane: fetch the hpos, dp4 against the plane. */
            if (c->key.nr_userclip)
               brw_MOV(p, c->reg.plane_equation, deref_4f(plane_ptr, 0));
            else
               brw_MOV(p, c->reg.plane_equation, deref_4b(plane_ptr, 0));

            brw_DP4(p, vec4(c->reg.dp0), deref_4f(vtx0, hpos_offset), c->reg.plane_equation);
            brw_DP4(p, vec4(c->reg.dp1), deref_4f(vtx1, hpos_offset), c->reg.plane_equation);
         }
         brw_ENDIF(p);

         brw_CMP(p, brw_null_reg(), BRW_CONDITIONAL_L, vec1(c->reg.dp1), brw_imm_f(0.0f));

         brw_IF(p, BRW_EXECUTE_1);
         {
             /*
              * Both can be negative on GM965/G965 due to RHW workaround
              * if so, this object should be rejected.
              */
             if (p->devinfo->has_negative_rhw_bug) {
                 brw_CMP(p, vec1(brw_null_reg()), BRW_CONDITIONAL_LE, c->reg.dp0, brw_imm_f(0.0));
                 brw_IF(p, BRW_EXECUTE_1);
                 {
                     brw_clip_kill_thread(c);
                 }
                 brw_ENDIF(p);
             }

             brw_ADD(p, c->reg.t, c->reg.dp1, negate(c->reg.dp0));
             brw_math_invert(p, c->reg.t, c->reg.t);
             brw_MUL(p, c->reg.t, c->reg.t, c->reg.dp1);

             brw_CMP(p, vec1(brw_null_reg()), BRW_CONDITIONAL_G, c->reg.t, c->reg.t1 );
             brw_MOV(p, c->reg.t1, c->reg.t);
             brw_inst_set_pred_control(p->devinfo, brw_last_inst,
                                       BRW_PREDICATE_NORMAL);
	 }
	 brw_ELSE(p);
	 {
             /* Coming back in.  We know that both cannot be negative
              * because the line would have been culled in that case.
              */

             /* If both are positive, do nothing */
             /* Only on GM965/G965 */
             if (p->devinfo->has_negative_rhw_bug) {
                 brw_CMP(p, vec1(brw_null_reg()), BRW_CONDITIONAL_L, c->reg.dp0, brw_imm_f(0.0));
                 brw_IF(p, BRW_EXECUTE_1);
             }

             {
                 brw_ADD(p, c->reg.t, c->reg.dp0, negate(c->reg.dp1));
                 brw_math_invert(p, c->reg.t, c->reg.t);
                 brw_MUL(p, c->reg.t, c->reg.t, c->reg.dp0);

                 brw_CMP(p, vec1(brw_null_reg()), BRW_CONDITIONAL_G, c->reg.t, c->reg.t0 );
                 brw_MOV(p, c->reg.t0, c->reg.t);
                 brw_inst_set_pred_control(p->devinfo, brw_last_inst,
                                           BRW_PREDICATE_NORMAL);
             }

             if (p->devinfo->has_negative_rhw_bug) {
                 brw_ENDIF(p);
             }
         }
	 brw_ENDIF(p);
      }
      brw_ENDIF(p);

      /* plane_ptr++;
       */
      brw_ADD(p, get_addr_reg(plane_ptr), get_addr_reg(plane_ptr), brw_clip_plane_stride(c));

      /* while (planemask>>=1) != 0
       */
      brw_SHR(p, c->reg.planemask, c->reg.planemask, brw_imm_ud(1));
      brw_inst_set_cond_modifier(p->devinfo, brw_last_inst, BRW_CONDITIONAL_NZ);
      brw_SHR(p, c->reg.vertex_src_mask, c->reg.vertex_src_mask, brw_imm_ud(1));
      brw_inst_set_pred_control(p->devinfo, brw_last_inst, BRW_PREDICATE_NORMAL);
      brw_ADD(p, c->reg.clipdistance_offset, c->reg.clipdistance_offset, brw_imm_w(sizeof(float)));
      brw_inst_set_pred_control(p->devinfo, brw_last_inst, BRW_PREDICATE_NORMAL);
   }
   brw_WHILE(p);
   brw_inst_set_pred_control(p->devinfo, brw_last_inst, BRW_PREDICATE_NORMAL);

   brw_ADD(p, c->reg.t, c->reg.t0, c->reg.t1);
   brw_CMP(p, vec1(brw_null_reg()), BRW_CONDITIONAL_L, c->reg.t, brw_imm_f(1.0));
   brw_IF(p, BRW_EXECUTE_1);
   {
      brw_clip_interp_vertex(c, newvtx0, vtx0, vtx1, c->reg.t0, false);
      brw_clip_interp_vertex(c, newvtx1, vtx1, vtx0, c->reg.t1, false);

      brw_clip_emit_vue(c, newvtx0, BRW_URB_WRITE_ALLOCATE_COMPLETE,
                        (_3DPRIM_LINESTRIP << URB_WRITE_PRIM_TYPE_SHIFT)
                        | URB_WRITE_PRIM_START);
      brw_clip_emit_vue(c, newvtx1, BRW_URB_WRITE_EOT_COMPLETE,
                        (_3DPRIM_LINESTRIP << URB_WRITE_PRIM_TYPE_SHIFT)
                        | URB_WRITE_PRIM_END);
   }
   brw_ENDIF(p);
   brw_clip_kill_thread(c);
}
Esempio n. 19
0
/***********************************************************************
 * Output clipped polygon as an unfilled primitive:
 */
static void emit_lines(struct brw_clip_compile *c,
		       bool do_offset)
{
   struct brw_compile *p = &c->func;
   const struct brw_context *brw = p->brw;
   struct brw_indirect v0 = brw_indirect(0, 0);
   struct brw_indirect v1 = brw_indirect(1, 0);
   struct brw_indirect v0ptr = brw_indirect(2, 0);
   struct brw_indirect v1ptr = brw_indirect(3, 0);

   /* Need a seperate loop for offset:
    */
   if (do_offset) {
      brw_MOV(p, c->reg.loopcount, c->reg.nr_verts);
      brw_MOV(p, get_addr_reg(v0ptr), brw_address(c->reg.inlist));

      brw_DO(p, BRW_EXECUTE_1);
      {
	 brw_MOV(p, get_addr_reg(v0), deref_1uw(v0ptr, 0));
	 brw_ADD(p, get_addr_reg(v0ptr), get_addr_reg(v0ptr), brw_imm_uw(2));
	
	 apply_one_offset(c, v0);
	
	 brw_ADD(p, c->reg.loopcount, c->reg.loopcount, brw_imm_d(-1));
         brw_inst_set_cond_modifier(brw, brw_last_inst, BRW_CONDITIONAL_G);
      }
      brw_WHILE(p);
      brw_inst_set_pred_control(brw, brw_last_inst, BRW_PREDICATE_NORMAL);
   }

   /* v1ptr = &inlist[nr_verts]
    * *v1ptr = v0
    */
   brw_MOV(p, c->reg.loopcount, c->reg.nr_verts);
   brw_MOV(p, get_addr_reg(v0ptr), brw_address(c->reg.inlist));
   brw_ADD(p, get_addr_reg(v1ptr), get_addr_reg(v0ptr), retype(c->reg.nr_verts, BRW_REGISTER_TYPE_UW));
   brw_ADD(p, get_addr_reg(v1ptr), get_addr_reg(v1ptr), retype(c->reg.nr_verts, BRW_REGISTER_TYPE_UW));
   brw_MOV(p, deref_1uw(v1ptr, 0), deref_1uw(v0ptr, 0));

   brw_DO(p, BRW_EXECUTE_1);
   {
      brw_MOV(p, get_addr_reg(v0), deref_1uw(v0ptr, 0));
      brw_MOV(p, get_addr_reg(v1), deref_1uw(v0ptr, 2));
      brw_ADD(p, get_addr_reg(v0ptr), get_addr_reg(v0ptr), brw_imm_uw(2));

      /* draw edge if edgeflag != 0 */
      brw_CMP(p,
	      vec1(brw_null_reg()), BRW_CONDITIONAL_NZ,
	      deref_1f(v0, brw_varying_to_offset(&c->vue_map,
                                                 VARYING_SLOT_EDGE)),
	      brw_imm_f(0));
      brw_IF(p, BRW_EXECUTE_1);
      {
	 brw_clip_emit_vue(c, v0, BRW_URB_WRITE_ALLOCATE_COMPLETE,
                           (_3DPRIM_LINESTRIP << URB_WRITE_PRIM_TYPE_SHIFT)
                           | URB_WRITE_PRIM_START);
	 brw_clip_emit_vue(c, v1, BRW_URB_WRITE_ALLOCATE_COMPLETE,
                           (_3DPRIM_LINESTRIP << URB_WRITE_PRIM_TYPE_SHIFT)
                           | URB_WRITE_PRIM_END);
      }
      brw_ENDIF(p);

      brw_ADD(p, c->reg.loopcount, c->reg.loopcount, brw_imm_d(-1));
      brw_inst_set_cond_modifier(brw, brw_last_inst, BRW_CONDITIONAL_NZ);
   }
   brw_WHILE(p);
   brw_inst_set_pred_control(brw, brw_last_inst, BRW_PREDICATE_NORMAL);
}
Esempio n. 20
0
/* Interpolate between two vertices and put the result into a0.0.  
 * Increment a0.0 accordingly.
 */
void brw_clip_interp_vertex( struct brw_clip_compile *c,
			     struct brw_indirect dest_ptr,
			     struct brw_indirect v0_ptr, /* from */
			     struct brw_indirect v1_ptr, /* to */
			     struct brw_reg t0,
			     GLboolean force_edgeflag)
{
   struct brw_compile *p = &c->func;
   struct brw_reg tmp = get_tmp(c);
   GLuint i;

   /* Just copy the vertex header:
    */
   /*
    * After CLIP stage, only first 256 bits of the VUE are read
    * back on IGDNG, so needn't change it
    */
   brw_copy_indirect_to_indirect(p, dest_ptr, v0_ptr, 1);
      
   /* Iterate over each attribute (could be done in pairs?)
    */
   for (i = 0; i < c->nr_attrs; i++) {
      GLuint delta = i*16 + 32;

      if (BRW_IS_IGDNG(p->brw))
          delta = i * 16 + 32 * 3;

      if (delta == c->offset[VERT_RESULT_EDGE]) {
	 if (force_edgeflag) 
	    brw_MOV(p, deref_4f(dest_ptr, delta), brw_imm_f(1));
	 else
	    brw_MOV(p, deref_4f(dest_ptr, delta), deref_4f(v0_ptr, delta));
      }
      else {
	 /* Interpolate: 
	  *
	  *        New = attr0 + t*attr1 - t*attr0
	  */
	 brw_MUL(p, 
		 vec4(brw_null_reg()),
		 deref_4f(v1_ptr, delta),
		 t0);

	 brw_MAC(p, 
		 tmp,	      
		 negate(deref_4f(v0_ptr, delta)),
		 t0); 
	      
	 brw_ADD(p,
		 deref_4f(dest_ptr, delta), 
		 deref_4f(v0_ptr, delta),
		 tmp);
      }
   }

   if (i & 1) {
      GLuint delta = i*16 + 32;

      if (BRW_IS_IGDNG(p->brw))
          delta = i * 16 + 32 * 3;

      brw_MOV(p, deref_4f(dest_ptr, delta), brw_imm_f(0));
   }

   release_tmp(c, tmp);

   /* Recreate the projected (NDC) coordinate in the new vertex
    * header:
    */
   brw_clip_project_vertex(c, dest_ptr );
}
Esempio n. 21
0
/***********************************************************************
 * Output clipped polygon as an unfilled primitive:
 */
static void emit_lines(struct brw_clip_compile *c,
		       GLboolean do_offset)
{
   struct brw_compile *p = &c->func;
   struct brw_instruction *loop;
   struct brw_instruction *draw_edge;
   struct brw_indirect v0 = brw_indirect(0, 0);
   struct brw_indirect v1 = brw_indirect(1, 0);
   struct brw_indirect v0ptr = brw_indirect(2, 0);
   struct brw_indirect v1ptr = brw_indirect(3, 0);

   /* Need a seperate loop for offset:
    */
   if (do_offset) {
      brw_MOV(p, c->reg.loopcount, c->reg.nr_verts);
      brw_MOV(p, get_addr_reg(v0ptr), brw_address(c->reg.inlist));

      loop = brw_DO(p, BRW_EXECUTE_1);
      {
	 brw_MOV(p, get_addr_reg(v0), deref_1uw(v0ptr, 0));
	 brw_ADD(p, get_addr_reg(v0ptr), get_addr_reg(v0ptr), brw_imm_uw(2));
	    
	 apply_one_offset(c, v0);
	    
	 brw_set_conditionalmod(p, BRW_CONDITIONAL_G);
	 brw_ADD(p, c->reg.loopcount, c->reg.loopcount, brw_imm_d(-1));
      }
      brw_WHILE(p, loop);
   }

   /* v1ptr = &inlist[nr_verts]
    * *v1ptr = v0
    */
   brw_MOV(p, c->reg.loopcount, c->reg.nr_verts);
   brw_MOV(p, get_addr_reg(v0ptr), brw_address(c->reg.inlist));
   brw_ADD(p, get_addr_reg(v1ptr), get_addr_reg(v0ptr), retype(c->reg.nr_verts, BRW_REGISTER_TYPE_UW));
   brw_ADD(p, get_addr_reg(v1ptr), get_addr_reg(v1ptr), retype(c->reg.nr_verts, BRW_REGISTER_TYPE_UW));
   brw_MOV(p, deref_1uw(v1ptr, 0), deref_1uw(v0ptr, 0));

   loop = brw_DO(p, BRW_EXECUTE_1);
   {
      brw_MOV(p, get_addr_reg(v0), deref_1uw(v0ptr, 0));
      brw_MOV(p, get_addr_reg(v1), deref_1uw(v0ptr, 2));
      brw_ADD(p, get_addr_reg(v0ptr), get_addr_reg(v0ptr), brw_imm_uw(2));

      /* draw edge if edgeflag != 0 */
      brw_CMP(p, 
	      vec1(brw_null_reg()), BRW_CONDITIONAL_NZ, 
	      deref_1f(v0, c->offset[VERT_RESULT_EDGE]),
	      brw_imm_f(0));
      draw_edge = brw_IF(p, BRW_EXECUTE_1);
      {
	 brw_clip_emit_vue(c, v0, 1, 0, (_3DPRIM_LINESTRIP << 2) | R02_PRIM_START);
	 brw_clip_emit_vue(c, v1, 1, 0, (_3DPRIM_LINESTRIP << 2) | R02_PRIM_END);
      }
      brw_ENDIF(p, draw_edge);

      brw_set_conditionalmod(p, BRW_CONDITIONAL_NZ);
      brw_ADD(p, c->reg.loopcount, c->reg.loopcount, brw_imm_d(-1));
   }
   brw_WHILE(p, loop);
}
void brw_emit_point_sprite_setup( struct brw_sf_compile *c, GLboolean allocate)
{
   struct brw_compile *p = &c->func;
   GLuint i;

   c->nr_verts = 1;

   if (allocate)
      alloc_regs(c);

   copy_z_inv_w(c);
   for (i = 0; i < c->nr_setup_regs; i++)
   {
      struct brw_sf_point_tex *tex = &c->point_attrs[c->idx_to_attr[2*i]];
      struct brw_reg a0 = offset(c->vert[0], i);
      GLushort pc, pc_persp, pc_linear;
      GLboolean last = calculate_masks(c, i, &pc, &pc_persp, &pc_linear);
            
      if (pc_persp)
      {				
	  if (!tex->CoordReplace) {
	      brw_set_predicate_control_flag_value(p, pc_persp);
	      brw_MUL(p, a0, a0, c->inv_w[0]);
	  }
      }

      if (tex->CoordReplace) {
	  /* Caculate 1.0/PointWidth */
	  brw_math(&c->func,
		  c->tmp,
		  BRW_MATH_FUNCTION_INV,
		  BRW_MATH_SATURATE_NONE,
		  0,
		  c->dx0,
		  BRW_MATH_DATA_SCALAR,
		  BRW_MATH_PRECISION_FULL);

	  if (c->key.SpriteOrigin == GL_LOWER_LEFT) {
	   	brw_MUL(p, c->m1Cx, c->tmp, c->inv_w[0]);
		brw_MOV(p, vec1(suboffset(c->m1Cx, 1)), brw_imm_f(0.0));
	  	brw_MUL(p, c->m2Cy, c->tmp, negate(c->inv_w[0]));
		brw_MOV(p, vec1(suboffset(c->m2Cy, 0)), brw_imm_f(0.0));
	  } else {
	   	brw_MUL(p, c->m1Cx, c->tmp, c->inv_w[0]);
		brw_MOV(p, vec1(suboffset(c->m1Cx, 1)), brw_imm_f(0.0));
	  	brw_MUL(p, c->m2Cy, c->tmp, c->inv_w[0]);
		brw_MOV(p, vec1(suboffset(c->m2Cy, 0)), brw_imm_f(0.0));
	  }
      } else {
	  brw_MOV(p, c->m1Cx, brw_imm_ud(0));
	  brw_MOV(p, c->m2Cy, brw_imm_ud(0));
      }

      {
	 brw_set_predicate_control_flag_value(p, pc); 
	 if (tex->CoordReplace) {
	     if (c->key.SpriteOrigin == GL_LOWER_LEFT) {
		 brw_MUL(p, c->m3C0, c->inv_w[0], brw_imm_f(1.0));
		 brw_MOV(p, vec1(suboffset(c->m3C0, 0)), brw_imm_f(0.0));
	     }
	     else
		 brw_MOV(p, c->m3C0, brw_imm_f(0.0));
	 } else {
	 	brw_MOV(p, c->m3C0, a0); /* constant value */
	 }

	 /* Copy m0..m3 to URB. 
	  */
	 brw_urb_WRITE(p, 
		       brw_null_reg(),
		       0,
		       brw_vec8_grf(0, 0),
		       0, 	/* allocate */
		       1,	/* used */
		       4, 	/* msg len */
		       0,	/* response len */
		       last, 	/* eot */
		       last, 	/* writes complete */
		       i*4,	/* urb destination offset */
		       BRW_URB_SWIZZLE_TRANSPOSE);
      }
   }
}
Esempio n. 23
0
/* Interpolate between two vertices and put the result into a0.0.  
 * Increment a0.0 accordingly.
 */
void brw_clip_interp_vertex( struct brw_clip_compile *c,
			     struct brw_indirect dest_ptr,
			     struct brw_indirect v0_ptr, /* from */
			     struct brw_indirect v1_ptr, /* to */
			     struct brw_reg t0,
			     bool force_edgeflag)
{
   struct brw_compile *p = &c->func;
   struct brw_reg tmp = get_tmp(c);
   GLuint slot;

   /* Just copy the vertex header:
    */
   /*
    * After CLIP stage, only first 256 bits of the VUE are read
    * back on Ironlake, so needn't change it
    */
   brw_copy_indirect_to_indirect(p, dest_ptr, v0_ptr, 1);
      
   /* Iterate over each attribute (could be done in pairs?)
    */
   for (slot = 0; slot < c->vue_map.num_slots; slot++) {
      int varying = c->vue_map.slot_to_varying[slot];
      GLuint delta = brw_vue_slot_to_offset(slot);

      if (varying == VARYING_SLOT_EDGE) {
	 if (force_edgeflag) 
	    brw_MOV(p, deref_4f(dest_ptr, delta), brw_imm_f(1));
	 else
	    brw_MOV(p, deref_4f(dest_ptr, delta), deref_4f(v0_ptr, delta));
      } else if (varying == VARYING_SLOT_PSIZ ||
                 varying == VARYING_SLOT_CLIP_DIST0 ||
                 varying == VARYING_SLOT_CLIP_DIST1) {
	 /* PSIZ doesn't need interpolation because it isn't used by the
          * fragment shader.  CLIP_DIST0 and CLIP_DIST1 don't need
          * intepolation because on pre-GEN6, these are just placeholder VUE
          * slots that don't perform any action.
          */
      } else if (varying < VARYING_SLOT_MAX) {
	 /* This is a true vertex result (and not a special value for the VUE
	  * header), so interpolate:
	  *
	  *        New = attr0 + t*attr1 - t*attr0
	  */
	 brw_MUL(p, 
		 vec4(brw_null_reg()),
		 deref_4f(v1_ptr, delta),
		 t0);

	 brw_MAC(p, 
		 tmp,	      
		 negate(deref_4f(v0_ptr, delta)),
		 t0); 
	      
	 brw_ADD(p,
		 deref_4f(dest_ptr, delta), 
		 deref_4f(v0_ptr, delta),
		 tmp);
      }
   }

   if (c->vue_map.num_slots % 2) {
      GLuint delta = brw_vue_slot_to_offset(c->vue_map.num_slots);

      brw_MOV(p, deref_4f(dest_ptr, delta), brw_imm_f(0));
   }

   release_tmp(c, tmp);

   /* Recreate the projected (NDC) coordinate in the new vertex
    * header:
    */
   brw_clip_project_vertex(c, dest_ptr );
}
Esempio n. 24
0
void emit_txb(struct brw_wm_compile *c,
	      struct brw_reg *dst,
	      GLuint dst_flags,
	      struct brw_reg *arg,
	      struct brw_reg depth_payload,
	      GLuint tex_idx,
	      GLuint sampler)
{
   struct brw_compile *p = &c->func;
   struct intel_context *intel = &p->brw->intel;
   GLuint msgLength;
   GLuint msg_type;
   GLuint mrf_per_channel;
   GLuint response_length;
   struct brw_reg dst_retyped;

   /* The G45 and older chipsets don't support 8-wide dispatch for LOD biased
    * samples, so we'll use the 16-wide instruction, leave the second halves
    * undefined, and trust the execution mask to keep the undefined pixels
    * from mattering.
    */
   if (c->dispatch_width == 16 || intel->gen < 5) {
      if (intel->gen >= 5)
	 msg_type = GEN5_SAMPLER_MESSAGE_SAMPLE_BIAS;
      else
	 msg_type = BRW_SAMPLER_MESSAGE_SIMD16_SAMPLE_BIAS;
      mrf_per_channel = 2;
      dst_retyped = retype(vec16(dst[0]), BRW_REGISTER_TYPE_UW);
      response_length = 8;
   } else {
      msg_type = GEN5_SAMPLER_MESSAGE_SAMPLE_BIAS;
      mrf_per_channel = 1;
      dst_retyped = retype(vec8(dst[0]), BRW_REGISTER_TYPE_UW);
      response_length = 4;
   }

   /* Shadow ignored for txb. */
   switch (tex_idx) {
   case TEXTURE_1D_INDEX:
      brw_MOV(p, brw_message_reg(2 + 0 * mrf_per_channel), arg[0]);
      brw_MOV(p, brw_message_reg(2 + 1 * mrf_per_channel), brw_imm_f(0));
      brw_MOV(p, brw_message_reg(2 + 2 * mrf_per_channel), brw_imm_f(0));
      break;
   case TEXTURE_2D_INDEX:
   case TEXTURE_RECT_INDEX:
      brw_MOV(p, brw_message_reg(2 + 0 * mrf_per_channel), arg[0]);
      brw_MOV(p, brw_message_reg(2 + 1 * mrf_per_channel), arg[1]);
      brw_MOV(p, brw_message_reg(2 + 2 * mrf_per_channel), brw_imm_f(0));
      break;
   case TEXTURE_3D_INDEX:
   case TEXTURE_CUBE_INDEX:
      brw_MOV(p, brw_message_reg(2 + 0 * mrf_per_channel), arg[0]);
      brw_MOV(p, brw_message_reg(2 + 1 * mrf_per_channel), arg[1]);
      brw_MOV(p, brw_message_reg(2 + 2 * mrf_per_channel), arg[2]);
      break;
   default:
      /* unexpected target */
      abort();
   }

   brw_MOV(p, brw_message_reg(2 + 3 * mrf_per_channel), arg[3]);
   msgLength = 2 + 4 * mrf_per_channel - 1;

   brw_SAMPLE(p, 
	      dst_retyped,
	      1,
	      retype(depth_payload, BRW_REGISTER_TYPE_UW),
              SURF_INDEX_TEXTURE(sampler),
	      sampler,
	      dst_flags & WRITEMASK_XYZW,
	      msg_type,
	      response_length,
	      msgLength,
	      1,
	      BRW_SAMPLER_SIMD_MODE_SIMD16,
	      BRW_SAMPLER_RETURN_FORMAT_FLOAT32);
}
Esempio n. 25
0
void emit_tex(struct brw_wm_compile *c,
	      struct brw_reg *dst,
	      GLuint dst_flags,
	      struct brw_reg *arg,
	      struct brw_reg depth_payload,
	      GLuint tex_idx,
	      GLuint sampler,
	      bool shadow)
{
   struct brw_compile *p = &c->func;
   struct intel_context *intel = &p->brw->intel;
   struct brw_reg dst_retyped;
   GLuint cur_mrf = 2, response_length;
   GLuint i, nr_texcoords;
   GLuint emit;
   GLuint msg_type;
   GLuint mrf_per_channel;
   GLuint simd_mode;

   if (c->dispatch_width == 16) {
      mrf_per_channel = 2;
      response_length = 8;
      dst_retyped = retype(vec16(dst[0]), BRW_REGISTER_TYPE_UW);
      simd_mode = BRW_SAMPLER_SIMD_MODE_SIMD16;
   } else {
      mrf_per_channel = 1;
      response_length = 4;
      dst_retyped = retype(vec8(dst[0]), BRW_REGISTER_TYPE_UW);
      simd_mode = BRW_SAMPLER_SIMD_MODE_SIMD8;
   }

   /* How many input regs are there?
    */
   switch (tex_idx) {
   case TEXTURE_1D_INDEX:
      emit = WRITEMASK_X;
      nr_texcoords = 1;
      break;
   case TEXTURE_2D_INDEX:
   case TEXTURE_1D_ARRAY_INDEX:
   case TEXTURE_RECT_INDEX:
      emit = WRITEMASK_XY;
      nr_texcoords = 2;
      break;
   case TEXTURE_3D_INDEX:
   case TEXTURE_2D_ARRAY_INDEX:
   case TEXTURE_CUBE_INDEX:
      emit = WRITEMASK_XYZ;
      nr_texcoords = 3;
      break;
   default:
      /* unexpected target */
      abort();
   }

   /* Pre-Ironlake, the 8-wide sampler always took u,v,r. */
   if (intel->gen < 5 && c->dispatch_width == 8)
      nr_texcoords = 3;

   if (shadow) {
      if (intel->gen < 7) {
	 /* For shadow comparisons, we have to supply u,v,r. */
	 nr_texcoords = 3;
      } else {
	 /* On Ivybridge, the shadow comparitor comes first. Just load it. */
	 brw_MOV(p, brw_message_reg(cur_mrf), arg[2]);
	 cur_mrf += mrf_per_channel;
      }
   }

   /* Emit the texcoords. */
   for (i = 0; i < nr_texcoords; i++) {
      if (c->key.tex.gl_clamp_mask[i] & (1 << sampler))
	 brw_set_saturate(p, true);

      if (emit & (1<<i))
	 brw_MOV(p, brw_message_reg(cur_mrf), arg[i]);
      else
	 brw_MOV(p, brw_message_reg(cur_mrf), brw_imm_f(0));
      cur_mrf += mrf_per_channel;

      brw_set_saturate(p, false);
   }

   /* Fill in the shadow comparison reference value. */
   if (shadow && intel->gen < 7) {
      if (intel->gen >= 5) {
	 /* Fill in the cube map array index value. */
	 brw_MOV(p, brw_message_reg(cur_mrf), brw_imm_f(0));
	 cur_mrf += mrf_per_channel;
      } else if (c->dispatch_width == 8) {
	 /* Fill in the LOD bias value. */
	 brw_MOV(p, brw_message_reg(cur_mrf), brw_imm_f(0));
	 cur_mrf += mrf_per_channel;
      }
      brw_MOV(p, brw_message_reg(cur_mrf), arg[2]);
      cur_mrf += mrf_per_channel;
   }

   if (intel->gen >= 5) {
      if (shadow)
	 msg_type = GEN5_SAMPLER_MESSAGE_SAMPLE_COMPARE;
      else
	 msg_type = GEN5_SAMPLER_MESSAGE_SAMPLE;
   } else {
      /* Note that G45 and older determines shadow compare and dispatch width
       * from message length for most messages.
       */
      if (c->dispatch_width == 16 && shadow)
	 msg_type = BRW_SAMPLER_MESSAGE_SIMD16_SAMPLE_COMPARE;
      else
	 msg_type = BRW_SAMPLER_MESSAGE_SIMD16_SAMPLE;
   }

   brw_SAMPLE(p,
	      dst_retyped,
	      1,
	      retype(depth_payload, BRW_REGISTER_TYPE_UW),
              SURF_INDEX_TEXTURE(sampler),
	      sampler,
	      dst_flags & WRITEMASK_XYZW,
	      msg_type,
	      response_length,
	      cur_mrf - 1,
	      1,
	      simd_mode,
	      BRW_SAMPLER_RETURN_FORMAT_FLOAT32);
}
/* Interpolate between two vertices and put the result into a0.0.
 * Increment a0.0 accordingly.
 *
 * Beware that dest_ptr can be equal to v0_ptr!
 */
void brw_clip_interp_vertex( struct brw_clip_compile *c,
			     struct brw_indirect dest_ptr,
			     struct brw_indirect v0_ptr, /* from */
			     struct brw_indirect v1_ptr, /* to */
			     struct brw_reg t0,
			     bool force_edgeflag)
{
   struct brw_codegen *p = &c->func;
   struct brw_reg t_nopersp, v0_ndc_copy;
   GLuint slot;

   /* Just copy the vertex header:
    */
   /*
    * After CLIP stage, only first 256 bits of the VUE are read
    * back on Ironlake, so needn't change it
    */
   brw_copy_indirect_to_indirect(p, dest_ptr, v0_ptr, 1);


   /* First handle the 3D and NDC interpolation, in case we
    * need noperspective interpolation. Doing it early has no
    * performance impact in any case.
    */

   /* Take a copy of the v0 NDC coordinates, in case dest == v0. */
   if (c->has_noperspective_shading) {
      GLuint offset = brw_varying_to_offset(&c->vue_map,
                                                 BRW_VARYING_SLOT_NDC);
      v0_ndc_copy = get_tmp(c);
      brw_MOV(p, v0_ndc_copy, deref_4f(v0_ptr, offset));
   }

   /* Compute the new 3D position
    *
    * dest_hpos = v0_hpos * (1 - t0) + v1_hpos * t0
    */
   {
      GLuint delta = brw_varying_to_offset(&c->vue_map, VARYING_SLOT_POS);
      struct brw_reg tmp = get_tmp(c);
      brw_MUL(p, vec4(brw_null_reg()), deref_4f(v1_ptr, delta), t0);
      brw_MAC(p, tmp, negate(deref_4f(v0_ptr, delta)), t0);
      brw_ADD(p, deref_4f(dest_ptr, delta), deref_4f(v0_ptr, delta), tmp);
      release_tmp(c, tmp);
   }

   /* Recreate the projected (NDC) coordinate in the new vertex header */
   brw_clip_project_vertex(c, dest_ptr);

   /* If we have noperspective attributes,
    * we need to compute the screen-space t
    */
   if (c->has_noperspective_shading) {
      GLuint delta = brw_varying_to_offset(&c->vue_map,
                                                BRW_VARYING_SLOT_NDC);
      struct brw_reg tmp = get_tmp(c);
      t_nopersp = get_tmp(c);

      /* t_nopersp = vec4(v1.xy, dest.xy) */
      brw_MOV(p, t_nopersp, deref_4f(v1_ptr, delta));
      brw_MOV(p, tmp, deref_4f(dest_ptr, delta));
      brw_set_default_access_mode(p, BRW_ALIGN_16);
      brw_MOV(p,
              brw_writemask(t_nopersp, WRITEMASK_ZW),
              brw_swizzle(tmp, 0, 1, 0, 1));

      /* t_nopersp = vec4(v1.xy, dest.xy) - v0.xyxy */
      brw_ADD(p, t_nopersp, t_nopersp,
              negate(brw_swizzle(v0_ndc_copy, 0, 1, 0, 1)));

      /* Add the absolute values of the X and Y deltas so that if
       * the points aren't in the same place on the screen we get
       * nonzero values to divide.
       *
       * After that, we have vert1 - vert0 in t_nopersp.x and
       * vertnew - vert0 in t_nopersp.y
       *
       * t_nopersp = vec2(|v1.x  -v0.x| + |v1.y  -v0.y|,
       *                  |dest.x-v0.x| + |dest.y-v0.y|)
       */
      brw_ADD(p,
              brw_writemask(t_nopersp, WRITEMASK_XY),
              brw_abs(brw_swizzle(t_nopersp, 0, 2, 0, 0)),
              brw_abs(brw_swizzle(t_nopersp, 1, 3, 0, 0)));
      brw_set_default_access_mode(p, BRW_ALIGN_1);

      /* If the points are in the same place, just substitute a
       * value to avoid divide-by-zero
       */
      brw_CMP(p, vec1(brw_null_reg()), BRW_CONDITIONAL_EQ,
              vec1(t_nopersp),
              brw_imm_f(0));
      brw_IF(p, BRW_EXECUTE_1);
      brw_MOV(p, t_nopersp, brw_imm_vf4(brw_float_to_vf(1.0),
                                        brw_float_to_vf(0.0),
                                        brw_float_to_vf(0.0),
                                        brw_float_to_vf(0.0)));
      brw_ENDIF(p);

      /* Now compute t_nopersp = t_nopersp.y/t_nopersp.x and broadcast it. */
      brw_math_invert(p, get_element(t_nopersp, 0), get_element(t_nopersp, 0));
      brw_MUL(p, vec1(t_nopersp), vec1(t_nopersp),
            vec1(suboffset(t_nopersp, 1)));
      brw_set_default_access_mode(p, BRW_ALIGN_16);
      brw_MOV(p, t_nopersp, brw_swizzle(t_nopersp, 0, 0, 0, 0));
      brw_set_default_access_mode(p, BRW_ALIGN_1);

      release_tmp(c, tmp);
      release_tmp(c, v0_ndc_copy);
   }

   /* Now we can iterate over each attribute
    * (could be done in pairs?)
    */
   for (slot = 0; slot < c->vue_map.num_slots; slot++) {
      int varying = c->vue_map.slot_to_varying[slot];
      GLuint delta = brw_vue_slot_to_offset(slot);

      /* HPOS, NDC already handled above */
      if (varying == VARYING_SLOT_POS || varying == BRW_VARYING_SLOT_NDC)
         continue;


      if (varying == VARYING_SLOT_EDGE) {
	 if (force_edgeflag)
	    brw_MOV(p, deref_4f(dest_ptr, delta), brw_imm_f(1));
	 else
	    brw_MOV(p, deref_4f(dest_ptr, delta), deref_4f(v0_ptr, delta));
      } else if (varying == VARYING_SLOT_PSIZ) {
         /* PSIZ doesn't need interpolation because it isn't used by the
          * fragment shader.
          */
      } else if (varying < VARYING_SLOT_MAX) {
	 /* This is a true vertex result (and not a special value for the VUE
	  * header), so interpolate:
	  *
	  *        New = attr0 + t*attr1 - t*attr0
          *
          * Unless the attribute is flat shaded -- in which case just copy
          * from one of the sources (doesn't matter which; already copied from pv)
	  */
         GLuint interp = c->key.interpolation_mode.mode[slot];

         if (interp != INTERP_QUALIFIER_FLAT) {
            struct brw_reg tmp = get_tmp(c);
            struct brw_reg t =
               interp == INTERP_QUALIFIER_NOPERSPECTIVE ? t_nopersp : t0;

            brw_MUL(p,
                  vec4(brw_null_reg()),
                  deref_4f(v1_ptr, delta),
                  t);

            brw_MAC(p,
                  tmp,
                  negate(deref_4f(v0_ptr, delta)),
                  t);

            brw_ADD(p,
                  deref_4f(dest_ptr, delta),
                  deref_4f(v0_ptr, delta),
                  tmp);

            release_tmp(c, tmp);
         }
         else {
            brw_MOV(p,
                  deref_4f(dest_ptr, delta),
                  deref_4f(v0_ptr, delta));
         }
      }
   }

   if (c->vue_map.num_slots % 2) {
      GLuint delta = brw_vue_slot_to_offset(c->vue_map.num_slots);

      brw_MOV(p, deref_4f(dest_ptr, delta), brw_imm_f(0));
   }

   if (c->has_noperspective_shading)
      release_tmp(c, t_nopersp);
}
Esempio n. 27
0
void brw_clip_tri_alloc_regs( struct brw_clip_compile *c, 
			      GLuint nr_verts )
{
   struct intel_context *intel = &c->func.brw->intel;
   GLuint i = 0,j;

   /* Register usage is static, precompute here:
    */
   c->reg.R0 = retype(brw_vec8_grf(i, 0), BRW_REGISTER_TYPE_UD); i++;

   if (c->key.nr_userclip) {
      c->reg.fixed_planes = brw_vec4_grf(i, 0);
      i += (6 + c->key.nr_userclip + 1) / 2;

      c->prog_data.curb_read_length = (6 + c->key.nr_userclip + 1) / 2;
   }
   else
      c->prog_data.curb_read_length = 0;


   /* Payload vertices plus space for more generated vertices:
    */
   for (j = 0; j < nr_verts; j++) {
      c->reg.vertex[j] = brw_vec4_grf(i, 0);
      i += c->nr_regs;
   }

   if (c->vue_map.num_slots % 2) {
      /* The VUE has an odd number of slots so the last register is only half
       * used.  Fill the second half with zero.
       */
      for (j = 0; j < 3; j++) {
	 GLuint delta = brw_vue_slot_to_offset(c->vue_map.num_slots);

	 brw_MOV(&c->func, byte_offset(c->reg.vertex[j], delta), brw_imm_f(0));
      }
   }

   c->reg.t          = brw_vec1_grf(i, 0);
   c->reg.loopcount  = retype(brw_vec1_grf(i, 1), BRW_REGISTER_TYPE_D);
   c->reg.nr_verts   = retype(brw_vec1_grf(i, 2), BRW_REGISTER_TYPE_UD);
   c->reg.planemask  = retype(brw_vec1_grf(i, 3), BRW_REGISTER_TYPE_UD);
   c->reg.plane_equation = brw_vec4_grf(i, 4);
   i++;

   c->reg.dpPrev     = brw_vec1_grf(i, 0); /* fixme - dp4 will clobber r.1,2,3 */
   c->reg.dp         = brw_vec1_grf(i, 4);
   i++;

   c->reg.inlist     = brw_uw16_reg(BRW_GENERAL_REGISTER_FILE, i, 0);
   i++;

   c->reg.outlist    = brw_uw16_reg(BRW_GENERAL_REGISTER_FILE, i, 0);
   i++;

   c->reg.freelist   = brw_uw16_reg(BRW_GENERAL_REGISTER_FILE, i, 0);
   i++;

   if (!c->key.nr_userclip) {
      c->reg.fixed_planes = brw_vec8_grf(i, 0); 
      i++;
   }

   if (c->key.do_unfilled) {
      c->reg.dir     = brw_vec4_grf(i, 0);
      c->reg.offset  = brw_vec4_grf(i, 4);
      i++;
      c->reg.tmp0    = brw_vec4_grf(i, 0);
      c->reg.tmp1    = brw_vec4_grf(i, 4);
      i++;
   }

   if (intel->needs_ff_sync) {
      c->reg.ff_sync = retype(brw_vec1_grf(i, 0), BRW_REGISTER_TYPE_UD);
      i++;
   }

   c->first_tmp = i;
   c->last_tmp = i;

   c->prog_data.urb_read_length = c->nr_regs; /* ? */
   c->prog_data.total_grf = i;
}
Esempio n. 28
0
void brw_clip_tri_alloc_regs( struct brw_clip_compile *c, 
			      GLuint nr_verts )
{
   GLuint i = 0,j;

   /* Register usage is static, precompute here:
    */
   c->reg.R0 = retype(brw_vec8_grf(i, 0), BRW_REGISTER_TYPE_UD); i++;

   if (c->key.nr_userclip) {
      c->reg.fixed_planes = brw_vec4_grf(i, 0);
      i += (6 + c->key.nr_userclip + 1) / 2;

      c->prog_data.curb_read_length = (6 + c->key.nr_userclip + 1) / 2;
   }
   else
      c->prog_data.curb_read_length = 0;


   /* Payload vertices plus space for more generated vertices:
    */
   for (j = 0; j < nr_verts; j++) {
      c->reg.vertex[j] = brw_vec4_grf(i, 0);
      i += c->nr_regs;
   }

   if (c->key.nr_attrs & 1) {
      for (j = 0; j < 3; j++) {
	 GLuint delta = c->key.nr_attrs*16 + 32;

         if (c->chipset.is_igdng)
             delta = c->key.nr_attrs * 16 + 32 * 3;

	 brw_MOV(&c->func, byte_offset(c->reg.vertex[j], delta), brw_imm_f(0));
      }
   }

   c->reg.t          = brw_vec1_grf(i, 0);
   c->reg.loopcount  = retype(brw_vec1_grf(i, 1), BRW_REGISTER_TYPE_D);
   c->reg.nr_verts   = retype(brw_vec1_grf(i, 2), BRW_REGISTER_TYPE_UD);
   c->reg.planemask  = retype(brw_vec1_grf(i, 3), BRW_REGISTER_TYPE_UD);
   c->reg.plane_equation = brw_vec4_grf(i, 4);
   i++;

   c->reg.dpPrev     = brw_vec1_grf(i, 0); /* fixme - dp4 will clobber r.1,2,3 */
   c->reg.dp         = brw_vec1_grf(i, 4);
   i++;

   c->reg.inlist     = brw_uw16_reg(BRW_GENERAL_REGISTER_FILE, i, 0);
   i++;

   c->reg.outlist    = brw_uw16_reg(BRW_GENERAL_REGISTER_FILE, i, 0);
   i++;

   c->reg.freelist   = brw_uw16_reg(BRW_GENERAL_REGISTER_FILE, i, 0);
   i++;

   if (!c->key.nr_userclip) {
      c->reg.fixed_planes = brw_vec8_grf(i, 0); 
      i++;
   }

   if (c->key.do_unfilled) {
      c->reg.dir     = brw_vec4_grf(i, 0);
      c->reg.offset  = brw_vec4_grf(i, 4);
      i++;
      c->reg.tmp0    = brw_vec4_grf(i, 0);
      c->reg.tmp1    = brw_vec4_grf(i, 4);
      i++;
   }

   if (c->need_ff_sync) {
      c->reg.ff_sync = retype(brw_vec1_grf(i, 0), BRW_REGISTER_TYPE_UD);
      i++;
   }

   c->first_tmp = i;
   c->last_tmp = i;

   c->prog_data.urb_read_length = c->nr_regs; /* ? */
   c->prog_data.total_grf = i;
}
Esempio n. 29
0
void brw_emit_point_sprite_setup(struct brw_sf_compile *c, bool allocate)
{
   struct brw_compile *p = &c->func;
   GLuint i;

   c->flag_value = 0xff;
   c->nr_verts = 1;

   if (allocate)
      alloc_regs(c);

   copy_z_inv_w(c);
   for (i = 0; i < c->nr_setup_regs; i++)
   {
      struct brw_reg a0 = offset(c->vert[0], i);
      GLushort pc, pc_persp, pc_linear, pc_coord_replace;
      bool last = calculate_masks(c, i, &pc, &pc_persp, &pc_linear);

      pc_coord_replace = calculate_point_sprite_mask(c, i);
      pc_persp &= ~pc_coord_replace;

      if (pc_persp) {
	 set_predicate_control_flag_value(p, c, pc_persp);
	 brw_MUL(p, a0, a0, c->inv_w[0]);
      }

      /* Point sprite coordinate replacement: A texcoord with this
       * enabled gets replaced with the value (x, y, 0, 1) where x and
       * y vary from 0 to 1 across the horizontal and vertical of the
       * point.
       */
      if (pc_coord_replace) {
	 set_predicate_control_flag_value(p, c, pc_coord_replace);
	 /* Caculate 1.0/PointWidth */
	 gen4_math(&c->func,
		   c->tmp,
		   BRW_MATH_FUNCTION_INV,
		   0,
		   c->dx0,
		   BRW_MATH_DATA_SCALAR,
		   BRW_MATH_PRECISION_FULL);

	 brw_set_default_access_mode(p, BRW_ALIGN_16);

	 /* dA/dx, dA/dy */
	 brw_MOV(p, c->m1Cx, brw_imm_f(0.0));
	 brw_MOV(p, c->m2Cy, brw_imm_f(0.0));
	 brw_MOV(p, brw_writemask(c->m1Cx, WRITEMASK_X), c->tmp);
	 if (c->key.sprite_origin_lower_left) {
	    brw_MOV(p, brw_writemask(c->m2Cy, WRITEMASK_Y), negate(c->tmp));
	 } else {
	    brw_MOV(p, brw_writemask(c->m2Cy, WRITEMASK_Y), c->tmp);
	 }

	 /* attribute constant offset */
	 brw_MOV(p, c->m3C0, brw_imm_f(0.0));
	 if (c->key.sprite_origin_lower_left) {
	    brw_MOV(p, brw_writemask(c->m3C0, WRITEMASK_YW), brw_imm_f(1.0));
	 } else {
	    brw_MOV(p, brw_writemask(c->m3C0, WRITEMASK_W), brw_imm_f(1.0));
	 }

	 brw_set_default_access_mode(p, BRW_ALIGN_1);
      }

      if (pc & ~pc_coord_replace) {
	 set_predicate_control_flag_value(p, c, pc & ~pc_coord_replace);
	 brw_MOV(p, c->m1Cx, brw_imm_ud(0));
	 brw_MOV(p, c->m2Cy, brw_imm_ud(0));
	 brw_MOV(p, c->m3C0, a0); /* constant value */
      }


      set_predicate_control_flag_value(p, c, pc);
      /* Copy m0..m3 to URB. */
      brw_urb_WRITE(p,
		    brw_null_reg(),
		    0,
		    brw_vec8_grf(0, 0),
                    last ? BRW_URB_WRITE_EOT_COMPLETE
                    : BRW_URB_WRITE_NO_FLAGS,
		    4, 	/* msg len */
		    0,	/* response len */
		    i*4,	/* urb destination offset */
		    BRW_URB_SWIZZLE_TRANSPOSE);
   }

   brw_set_default_predicate_control(p, BRW_PREDICATE_NONE);
}
Esempio n. 30
0
/* Interpolate between two vertices and put the result into a0.0.
 * Increment a0.0 accordingly.
 */
void brw_clip_interp_vertex( struct brw_clip_compile *c,
			     struct brw_indirect dest_ptr,
			     struct brw_indirect v0_ptr, /* from */
			     struct brw_indirect v1_ptr, /* to */
			     struct brw_reg t0,
			     boolean force_edgeflag)
{
#if 0
   struct brw_compile *p = &c->func;
   struct brw_reg tmp = get_tmp(c);
   unsigned i;

   /* Just copy the vertex header:
    */
   brw_copy_indirect_to_indirect(p, dest_ptr, v0_ptr, 1);

   /* Iterate over each attribute (could be done in pairs?)
    */
   for (i = 0; i < c->nr_attrs; i++) {
      unsigned delta = i*16 + 32;

      if (delta == c->offset[VERT_RESULT_EDGE]) {
	 if (force_edgeflag)
	    brw_MOV(p, deref_4f(dest_ptr, delta), brw_imm_f(1));
	 else
	    brw_MOV(p, deref_4f(dest_ptr, delta), deref_4f(v0_ptr, delta));
      }
      else {
	 /* Interpolate:
	  *
	  *        New = attr0 + t*attr1 - t*attr0
	  */
	 brw_MUL(p,
		 vec4(brw_null_reg()),
		 deref_4f(v1_ptr, delta),
		 t0);

	 brw_MAC(p,
		 tmp,
		 negate(deref_4f(v0_ptr, delta)),
		 t0);

	 brw_ADD(p,
		 deref_4f(dest_ptr, delta),
		 deref_4f(v0_ptr, delta),
		 tmp);
      }
   }

   if (i & 1) {
      unsigned delta = i*16 + 32;
      brw_MOV(p, deref_4f(dest_ptr, delta), brw_imm_f(0));
   }

   release_tmp(c, tmp);

   /* Recreate the projected (NDC) coordinate in the new vertex
    * header:
    */
   brw_clip_project_vertex(c, dest_ptr );
#else
         #warning "disabled"
#endif
}