llvmpipe: fix sprite texcoord setup for non-projective texturing
authorBrian Paul <brianp@vmware.com>
Wed, 22 Sep 2010 17:20:48 +0000 (11:20 -0600)
committerBrian Paul <brianp@vmware.com>
Wed, 22 Sep 2010 17:25:18 +0000 (11:25 -0600)
Normally the Mesa state tracker uses TXP instructions for texturing.
But if a fragment shader uses texture2D() that's a TEX instruction.
In that case we were incorrectly computing the texcoord coefficients
in the point sprite setup code.  Some new comments in the code explain
things.

src/gallium/drivers/llvmpipe/lp_setup_point.c

index 774a3c80dad7ae949c5b23f656d893f3e598505c..2c354d1d0ed9c079116619ce013f2e175525908a 100644 (file)
@@ -65,47 +65,77 @@ constant_coef(struct lp_setup_context *setup,
 }
 
 
+/**
+ * Setup automatic texcoord coefficients (for sprite rendering).
+ * \param slot  the vertex attribute slot to setup
+ * \param i  the attribute channel in [0,3]
+ * \param sprite_coord_origin  one of PIPE_SPRITE_COORD_x
+ * \param perspective_proj  will the TEX instruction do a divide by Q?
+ */
 static void
-perspective_coef(struct lp_setup_context *setup,
-                 struct lp_rast_triangle *point,
-                 const struct point_info *info,
-                 unsigned slot,
-                 unsigned vert_attr,
-                 unsigned i,
-                 unsigned sprite_coord_origin)
+texcoord_coef(struct lp_setup_context *setup,
+              struct lp_rast_triangle *point,
+              const struct point_info *info,
+              unsigned slot,
+              unsigned i,
+              unsigned sprite_coord_origin,
+              boolean perspective_proj)
 {
+   assert(i < 4);
+
    if (i == 0) {
       float dadx = FIXED_ONE / (float)info->dx12;
       float dady =  0.0f;
-      point->inputs.dadx[slot][i] = dadx;
-      point->inputs.dady[slot][i] = dady;
-      point->inputs.a0[slot][i] = (0.5 -
-                                  (dadx * ((float)info->v0[0][0] - setup->pixel_offset) +
-                                   dady * ((float)info->v0[0][1] - setup->pixel_offset)));
+      float x0 = info->v0[0][0] - setup->pixel_offset;
+      float y0 = info->v0[0][1] - setup->pixel_offset;
+
+      point->inputs.dadx[slot][0] = dadx;
+      point->inputs.dady[slot][0] = dady;
+      point->inputs.a0[slot][0] = 0.5 - (dadx * x0 + dady * y0);
+
+      if (!perspective_proj) {
+         /* Divide coefficients by vertex.w here.
+          *
+          * It would be clearer to always multiply by w0 above and
+          * then divide it out for perspective projection here, but
+          * doing it this way involves less algebra.
+          */
+         float w0 = info->v0[0][3];
+         point->inputs.dadx[slot][0] *= w0;
+         point->inputs.dady[slot][0] *= w0;
+         point->inputs.a0[slot][0] *= w0;
+      }
    }
    else if (i == 1) {
       float dadx = 0.0f;
       float dady = FIXED_ONE / (float)info->dx12;
+      float x0 = info->v0[0][0] - setup->pixel_offset;
+      float y0 = info->v0[0][1] - setup->pixel_offset;
 
       if (sprite_coord_origin == PIPE_SPRITE_COORD_LOWER_LEFT) {
          dady = -dady;
       }
 
-      point->inputs.dadx[slot][i] = dadx;
-      point->inputs.dady[slot][i] = dady;
-      point->inputs.a0[slot][i] = (0.5 -
-                                   (dadx * ((float)info->v0[0][0] - setup->pixel_offset) +
-                                    dady * ((float)info->v0[0][1] - setup->pixel_offset)));
+      point->inputs.dadx[slot][1] = dadx;
+      point->inputs.dady[slot][1] = dady;
+      point->inputs.a0[slot][1] = 0.5 - (dadx * x0 + dady * y0);
+
+      if (!perspective_proj) {
+         float w0 = info->v0[0][3];
+         point->inputs.dadx[slot][1] *= w0;
+         point->inputs.dady[slot][1] *= w0;
+         point->inputs.a0[slot][1] *= w0;
+      }
    }
    else if (i == 2) {
-      point->inputs.a0[slot][i] = 0.0f;
-      point->inputs.dadx[slot][i] = 0.0f;
-      point->inputs.dady[slot][i] = 0.0f;
+      point->inputs.a0[slot][2] = 0.0f;
+      point->inputs.dadx[slot][2] = 0.0f;
+      point->inputs.dady[slot][2] = 0.0f;
    }
-   else if (i == 3) {
-      point->inputs.a0[slot][i] = 1.0f;
-      point->inputs.dadx[slot][i] = 0.0f;
-      point->inputs.dady[slot][i] = 0.0f;
+   else {
+      point->inputs.a0[slot][3] = 1.0f;
+      point->inputs.dadx[slot][3] = 0.0f;
+      point->inputs.dady[slot][3] = 0.0f;
    }
 }
 
@@ -184,7 +214,7 @@ setup_point_coefficients( struct lp_setup_context *setup,
 
       case LP_INTERP_PERSPECTIVE:
          /* check if the sprite coord flag is set for this attribute.
-          * If so, set it up so it up so x any y vary from 0 to 1.
+          * If so, set it up so it up so x and y vary from 0 to 1.
           */
          if (shader->info.input_semantic_name[slot] == TGSI_SEMANTIC_GENERIC) {
             const int index = shader->info.input_semantic_index[slot];
@@ -195,8 +225,9 @@ setup_point_coefficients( struct lp_setup_context *setup,
                 (setup->sprite_coord_enable & (1 << index))) {
                for (i = 0; i < NUM_CHANNELS; i++)
                   if (usage_mask & (1 << i))
-                     perspective_coef(setup, point, info, slot+1, vert_attr, i,
-                                      setup->sprite_coord_origin);
+                     texcoord_coef(setup, point, info, slot + 1, i,
+                                   setup->sprite_coord_origin,
+                                   (usage_mask & TGSI_WRITEMASK_W));
                fragcoord_usage_mask |= TGSI_WRITEMASK_W;
                break;                     
             }