commit 64c9b3283b6eb1beae9361c97fa632a3061734e9
Author: Eric Anholt <eric@anholt.net>
Date:   Mon Mar 8 12:12:31 2010 -0800

    i965: Fix up the handling of point sprite coordinate replacement.
    
    The code was walking over the regs of pairs of attributes and checking
    whether the attribute with a given reg index had point sprite enabled.
    So the point sprite setup code was rarely even getting executed.
    Instead, we need to determine which channels of a reg need point
    sprite coordinate replacement.

diff --git a/src/mesa/drivers/dri/i965/brw_sf.c b/src/mesa/drivers/dri/i965/brw_sf.c
index 8e6839b..6ce0c90 100644
--- a/src/mesa/drivers/dri/i965/brw_sf.c
+++ b/src/mesa/drivers/dri/i965/brw_sf.c
@@ -46,7 +46,6 @@
 static void compile_sf_prog( struct brw_context *brw,
 			     struct brw_sf_prog_key *key )
 {
-   GLcontext *ctx = &brw->intel.ctx;
    struct brw_sf_compile c;
    const GLuint *program;
    GLuint program_size;
@@ -63,26 +62,19 @@ static void compile_sf_prog( struct brw_context *brw,
    c.nr_attr_regs = (c.nr_attrs+1)/2;
    c.nr_setup_attrs = brw_count_bits(c.key.attrs);
    c.nr_setup_regs = (c.nr_setup_attrs+1)/2;
-
    c.prog_data.urb_read_length = c.nr_attr_regs;
    c.prog_data.urb_entry_size = c.nr_setup_regs * 2;
 
    /* Construct map from attribute number to position in the vertex.
     */
-   for (i = idx = 0; i < VERT_RESULT_MAX; i++) 
+   for (i = idx = 0; i < VERT_RESULT_MAX; i++) {
       if (c.key.attrs & BITFIELD64_BIT(i)) {
 	 c.attr_to_idx[i] = idx;
 	 c.idx_to_attr[idx] = i;
-	 if (i >= VERT_RESULT_TEX0 && i <= VERT_RESULT_TEX7) {
-            c.point_attrs[i].CoordReplace = 
-               ctx->Point.CoordReplace[i - VERT_RESULT_TEX0];
-	 }
-         else {
-            c.point_attrs[i].CoordReplace = GL_FALSE;
-         }
 	 idx++;
       }
-   
+   }
+
    /* Which primitive?  Or all three? 
     */
    switch (key->primitive) {
@@ -162,6 +154,14 @@ static void upload_sf_prog(struct brw_context *brw)
    }
 
    key.do_point_sprite = ctx->Point.PointSprite;
+   if (key.do_point_sprite) {
+      int i;
+
+      for (i = 0; i < 8; i++) {
+	 if (ctx->Point.CoordReplace[i])
+	    key.point_sprite_coord_replace |= (1 << i);
+      }
+   }
    key.sprite_origin_lower_left = (ctx->Point.SpriteOrigin == GL_LOWER_LEFT);
    /* _NEW_LIGHT */
    key.do_flat_shading = (ctx->Light.ShadeModel == GL_FLAT);
diff --git a/src/mesa/drivers/dri/i965/brw_sf.h b/src/mesa/drivers/dri/i965/brw_sf.h
index 0ba731f..a0680a5 100644
--- a/src/mesa/drivers/dri/i965/brw_sf.h
+++ b/src/mesa/drivers/dri/i965/brw_sf.h
@@ -46,6 +46,7 @@
 
 struct brw_sf_prog_key {
    GLbitfield64 attrs;
+   uint8_t point_sprite_coord_replace;
    GLuint primitive:2;
    GLuint do_twoside_color:1;
    GLuint do_flat_shading:1;
@@ -56,10 +57,6 @@ struct brw_sf_prog_key {
    GLuint pad:24;
 };
 
-struct brw_sf_point_tex {
-   GLboolean CoordReplace;	
-};
-
 struct brw_sf_compile {
    struct brw_compile func;
    struct brw_sf_prog_key key;
@@ -100,7 +97,6 @@ struct brw_sf_compile {
 
    GLubyte attr_to_idx[VERT_RESULT_MAX];   
    GLubyte idx_to_attr[VERT_RESULT_MAX];   
-   struct brw_sf_point_tex point_attrs[VERT_RESULT_MAX];
 };
 
  
diff --git a/src/mesa/drivers/dri/i965/brw_sf_emit.c b/src/mesa/drivers/dri/i965/brw_sf_emit.c
index bb08055..f31e995 100644
--- a/src/mesa/drivers/dri/i965/brw_sf_emit.c
+++ b/src/mesa/drivers/dri/i965/brw_sf_emit.c
@@ -354,6 +354,34 @@ static GLboolean calculate_masks( struct brw_sf_compile *c,
    return is_last_attr;
 }
 
+/* Calculates the predicate control for which channels of a reg
+ * (containing 2 attrs) to do point sprite coordinate replacement on.
+ */
+static uint8_t
+calculate_point_sprite_mask(struct brw_sf_compile *c, GLuint reg)
+{
+   int attr1, attr2;
+   uint8_t pc = 0;
+
+   attr1 = c->idx_to_attr[reg * 2];
+
+   if (attr1 >= VERT_RESULT_TEX0 && attr1 <= VERT_RESULT_TEX7) {
+      if (c->key.point_sprite_coord_replace & (1 << (attr1 - VERT_RESULT_TEX0)))
+	 pc |= 0x0f;
+   }
+
+   if (reg * 2 + 1 < c->nr_setup_attrs) {
+       attr2 = c->idx_to_attr[reg * 2 + 1];
+       if (attr2 >= VERT_RESULT_TEX0 && attr2 <= VERT_RESULT_TEX7) {
+	  if (c->key.point_sprite_coord_replace & (1 << (attr2 -
+							 VERT_RESULT_TEX0)))
+	     pc |= 0xf0;
+       }
+   }
+
+   return pc;
+}
+
 
 
 void brw_emit_tri_setup( struct brw_sf_compile *c, GLboolean allocate)
@@ -529,20 +557,21 @@ void brw_emit_point_sprite_setup( struct brw_sf_compile *c, GLboolean allocate)
    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;
+      GLushort pc, pc_persp, pc_linear, pc_coord_replace;
       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]);
-	  }
+
+      pc_coord_replace = calculate_point_sprite_mask(c, i);
+      pc_persp &= ~pc_coord_replace;
+
+      fprintf(stderr, "0x%08x 0x%08x 0x%08x\n", pc, pc_persp, pc_coord_replace);
+      if (pc_persp) {
+	 brw_set_predicate_control_flag_value(p, pc_persp);
+	 brw_MUL(p, a0, a0, c->inv_w[0]);
       }
 
-      if (tex->CoordReplace) {
+      if (pc_coord_replace) {
+	 brw_set_predicate_control_flag_value(p, pc_coord_replace);
 	  /* Caculate 1.0/PointWidth */
 	  brw_math(&c->func,
 		  c->tmp,
@@ -564,39 +593,42 @@ void brw_emit_point_sprite_setup( struct brw_sf_compile *c, GLboolean allocate)
 	  	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 {
+      }
+
+      if (pc & ~pc_coord_replace) {
+	  brw_set_predicate_control_flag_value(p, pc & ~pc_coord_replace);
 	  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.sprite_origin_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 */
+      if (pc_coord_replace) {
+	 brw_set_predicate_control_flag_value(p, pc_coord_replace);
+	 if (c->key.sprite_origin_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));
 	 }
-
-	 /* 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);
+	 else
+	    brw_MOV(p, c->m3C0, brw_imm_f(0.0));
       }
+      if (pc & ~pc_coord_replace) {
+	 brw_set_predicate_control_flag_value(p, pc & ~pc_coord_replace);
+	 brw_MOV(p, c->m3C0, a0); /* constant value */
+      }
+
+      brw_set_predicate_control_flag_value(p, pc);
+      /* 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);
    }
 }
 
