summaryrefslogtreecommitdiff
path: root/src/gallium/drivers/llvmpipe/lp_setup_point.c
diff options
context:
space:
mode:
authorJosé Fonseca <jfonseca@vmware.com>2010-09-26 11:22:20 +0100
committerJosé Fonseca <jfonseca@vmware.com>2010-10-06 11:44:59 +0100
commite74955eba3fc22fcf6e9111a4e5bbc095d34d357 (patch)
tree0cb6dc63712366064753e68d60468e6839de9d27 /src/gallium/drivers/llvmpipe/lp_setup_point.c
parent446dbb921762710d678486f3f5a6dfdf318fe34c (diff)
llvmpipe: Fix perspective interpolation for point sprites.
Once a fragment is generated with LP_INTERP_PERSPECTIVE set for an input, it will do a divide by w for that input. Therefore it's not OK to treat LP_INTERP_PERSPECTIVE as LP_INTERP_LINEAR or vice-versa, even if the attribute is known to not vary. A better strategy would be to take the primitive in consideration when generating the fragment shader key, and therefore avoid the per-fragment perspective divide.
Diffstat (limited to 'src/gallium/drivers/llvmpipe/lp_setup_point.c')
-rw-r--r--src/gallium/drivers/llvmpipe/lp_setup_point.c71
1 files changed, 54 insertions, 17 deletions
diff --git a/src/gallium/drivers/llvmpipe/lp_setup_point.c b/src/gallium/drivers/llvmpipe/lp_setup_point.c
index 3b217f9544..c91e85f915 100644
--- a/src/gallium/drivers/llvmpipe/lp_setup_point.c
+++ b/src/gallium/drivers/llvmpipe/lp_setup_point.c
@@ -64,12 +64,37 @@ constant_coef(struct lp_setup_context *setup,
}
+static void
+point_persp_coeff(struct lp_setup_context *setup,
+ struct lp_rast_triangle *point,
+ const struct point_info *info,
+ unsigned slot,
+ unsigned i)
+{
+ /*
+ * Fragment shader expects pre-multiplied w for LP_INTERP_PERSPECTIVE. A
+ * better stratergy would be to take the primitive in consideration when
+ * generating the fragment shader key, and therefore avoid the per-fragment
+ * perspective divide.
+ */
+
+ float w0 = info->v0[0][3];
+
+ assert(i < 4);
+
+ point->inputs.a0[slot][i] = info->v0[slot][i]*w0;
+ point->inputs.dadx[slot][i] = 0.0f;
+ point->inputs.dady[slot][i] = 0.0f;
+}
+
+
/**
* 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?
+ * \param perspective does the shader expects pre-multiplied w, i.e.,
+ * LP_INTERP_PERSPECTIVE is specified in the shader key
*/
static void
texcoord_coef(struct lp_setup_context *setup,
@@ -78,7 +103,7 @@ texcoord_coef(struct lp_setup_context *setup,
unsigned slot,
unsigned i,
unsigned sprite_coord_origin,
- boolean perspective_proj)
+ boolean perspective)
{
assert(i < 4);
@@ -92,7 +117,7 @@ texcoord_coef(struct lp_setup_context *setup,
point->inputs.dady[slot][0] = dady;
point->inputs.a0[slot][0] = 0.5 - (dadx * x0 + dady * y0);
- if (!perspective_proj) {
+ if (perspective) {
/* Divide coefficients by vertex.w here.
*
* It would be clearer to always multiply by w0 above and
@@ -119,7 +144,7 @@ texcoord_coef(struct lp_setup_context *setup,
point->inputs.dady[slot][1] = dady;
point->inputs.a0[slot][1] = 0.5 - (dadx * x0 + dady * y0);
- if (!perspective_proj) {
+ if (perspective) {
float w0 = info->v0[0][3];
point->inputs.dadx[slot][1] *= w0;
point->inputs.dady[slot][1] *= w0;
@@ -193,11 +218,17 @@ setup_point_coefficients( struct lp_setup_context *setup,
/* setup interpolation for all the remaining attributes:
*/
for (slot = 0; slot < setup->fs.nr_inputs; slot++) {
+ enum lp_interp interp = setup->fs.input[slot].interp;
+ boolean perspective = !!(interp == LP_INTERP_PERSPECTIVE);
unsigned vert_attr = setup->fs.input[slot].src_index;
unsigned usage_mask = setup->fs.input[slot].usage_mask;
unsigned i;
+
+ if (perspective & usage_mask) {
+ fragcoord_usage_mask |= TGSI_WRITEMASK_W;
+ }
- switch (setup->fs.input[slot].interp) {
+ switch (interp) {
case LP_INTERP_POSITION:
/*
* The generated pixel interpolators will pick up the coeffs from
@@ -210,32 +241,38 @@ setup_point_coefficients( struct lp_setup_context *setup,
case LP_INTERP_LINEAR:
/* Sprite tex coords may use linear interpolation someday */
/* fall-through */
-
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 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];
+ unsigned semantic_index = shader->info.input_semantic_index[slot];
/* Note that sprite_coord enable is a bitfield of
* PIPE_MAX_SHADER_OUTPUTS bits.
*/
- if (index < PIPE_MAX_SHADER_OUTPUTS &&
- (setup->sprite_coord_enable & (1 << index))) {
- for (i = 0; i < NUM_CHANNELS; i++)
- if (usage_mask & (1 << i))
+ if (semantic_index < PIPE_MAX_SHADER_OUTPUTS &&
+ (setup->sprite_coord_enable & (1 << semantic_index))) {
+ for (i = 0; i < NUM_CHANNELS; i++) {
+ if (usage_mask & (1 << i)) {
texcoord_coef(setup, point, info, slot + 1, i,
setup->sprite_coord_origin,
- (usage_mask & TGSI_WRITEMASK_W));
- fragcoord_usage_mask |= TGSI_WRITEMASK_W;
- break;
+ perspective);
+ }
+ }
+ break;
}
}
- /* FALLTHROUGH */
+ /* fall-through */
case LP_INTERP_CONSTANT:
for (i = 0; i < NUM_CHANNELS; i++) {
- if (usage_mask & (1 << i))
- constant_coef(setup, point, slot+1, info->v0[vert_attr][i], i);
+ if (usage_mask & (1 << i)) {
+ if (perspective) {
+ point_persp_coeff(setup, point, info, slot+1, i);
+ }
+ else {
+ constant_coef(setup, point, slot+1, info->v0[vert_attr][i], i);
+ }
+ }
}
break;