From 516ac2bd50ad1e71bd2a359d247532d9f18bcf99 Mon Sep 17 00:00:00 2001 From: Brian Paul Date: Wed, 22 Sep 2010 11:20:48 -0600 Subject: [PATCH] llvmpipe: fix sprite texcoord setup for non-projective texturing 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 | 85 +++++++++++++------ 1 file changed, 58 insertions(+), 27 deletions(-) diff --git a/src/gallium/drivers/llvmpipe/lp_setup_point.c b/src/gallium/drivers/llvmpipe/lp_setup_point.c index 774a3c80dad..2c354d1d0ed 100644 --- a/src/gallium/drivers/llvmpipe/lp_setup_point.c +++ b/src/gallium/drivers/llvmpipe/lp_setup_point.c @@ -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; } -- 2.30.2