[Mesa-dev] [PATCH] softpipe: Fix everything that is wrong with clipping and interpolation.
Olivier Galibert
galibert at pobox.com
Tue May 29 08:34:41 PDT 2012
This includes:
- picking up correctly which attributes are flatshaded and which are
noperspective
- copying the flatshaded attributes when needed, including the
non-built-in ones
- correctly interpolating the noperspective attributes in screen-space
instead than in a 3d-correct fashion.
Signed-off-by: Olivier Galibert <galibert at pobox.com>
---
src/gallium/auxiliary/draw/draw_pipe_clip.c | 105 +++++++++++++++++++--------
1 file changed, 74 insertions(+), 31 deletions(-)
diff --git a/src/gallium/auxiliary/draw/draw_pipe_clip.c b/src/gallium/auxiliary/draw/draw_pipe_clip.c
index 4da4d65..3824ced 100644
--- a/src/gallium/auxiliary/draw/draw_pipe_clip.c
+++ b/src/gallium/auxiliary/draw/draw_pipe_clip.c
@@ -39,6 +39,7 @@
#include "draw_vs.h"
#include "draw_pipe.h"
+#include "draw_fs.h"
#ifndef IS_NEGATIVE
@@ -56,11 +57,12 @@
struct clip_stage {
struct draw_stage stage; /**< base class */
- /* Basically duplicate some of the flatshading logic here:
- */
- boolean flat;
- uint num_color_attribs;
- uint color_attribs[4]; /* front/back primary/secondary colors */
+ /* List of the attributes to be flatshaded. */
+ uint num_flat_attribs;
+ uint flat_attribs[PIPE_MAX_SHADER_OUTPUTS];
+
+ /* Mask of attributes in noperspective mode */
+ boolean noperspective_attribs[PIPE_MAX_SHADER_OUTPUTS];
float (*plane)[4];
};
@@ -91,17 +93,16 @@ static void interp_attr( float dst[4],
/**
- * Copy front/back, primary/secondary colors from src vertex to dst vertex.
- * Used when flat shading.
+ * Copy flat shaded attributes src vertex to dst vertex.
*/
-static void copy_colors( struct draw_stage *stage,
- struct vertex_header *dst,
- const struct vertex_header *src )
+static void copy_flat( struct draw_stage *stage,
+ struct vertex_header *dst,
+ const struct vertex_header *src )
{
const struct clip_stage *clipper = clip_stage(stage);
uint i;
- for (i = 0; i < clipper->num_color_attribs; i++) {
- const uint attr = clipper->color_attribs[i];
+ for (i = 0; i < clipper->num_flat_attribs; i++) {
+ const uint attr = clipper->flat_attribs[i];
COPY_4FV(dst->data[attr], src->data[attr]);
}
}
@@ -120,6 +121,7 @@ static void interp( const struct clip_stage *clip,
const unsigned pos_attr = draw_current_shader_position_output(clip->stage.draw);
const unsigned clip_attr = draw_current_shader_clipvertex_output(clip->stage.draw);
unsigned j;
+ float t_nopersp = 0;
/* Vertex header.
*/
@@ -152,8 +154,27 @@ static void interp( const struct clip_stage *clip,
/* Other attributes
*/
for (j = 0; j < nr_attrs; j++) {
- if (j != pos_attr && j != clip_attr)
- interp_attr(dst->data[j], t, in->data[j], out->data[j]);
+ if (j != pos_attr && j != clip_attr) {
+ if (clip->noperspective_attribs[j]) {
+ if (!t_nopersp || !t) {
+ // Compute the t in screen-space instead of 3d space.
+ //
+ // When both points are at the same screen position,
+ // we can pick whatever value (the interpolated point
+ // won't be in front anyway), so just use t.
+ int k;
+ t_nopersp = t;
+ for (k=0; k < 2; k++)
+ if (in->data[pos_attr][k] != out->data[pos_attr][k]) {
+ t_nopersp = (dst->data[pos_attr][k] - out->data[pos_attr][k]) /
+ (in->data[pos_attr][k] - out->data[pos_attr][k]);
+ break;
+ }
+ }
+ interp_attr(dst->data[j], t_nopersp, in->data[j], out->data[j]);
+ } else
+ interp_attr(dst->data[j], t, in->data[j], out->data[j]);
+ }
}
}
@@ -406,14 +427,14 @@ do_clip_tri( struct draw_stage *stage,
/* If flat-shading, copy provoking vertex color to polygon vertex[0]
*/
if (n >= 3) {
- if (clipper->flat) {
+ if (clipper->num_flat_attribs) {
if (stage->draw->rasterizer->flatshade_first) {
if (inlist[0] != header->v[0]) {
assert(tmpnr < MAX_CLIPPED_VERTICES + 1);
if (tmpnr >= MAX_CLIPPED_VERTICES + 1)
return;
inlist[0] = dup_vert(stage, inlist[0], tmpnr++);
- copy_colors(stage, inlist[0], header->v[0]);
+ copy_flat(stage, inlist[0], header->v[0]);
}
}
else {
@@ -422,7 +443,7 @@ do_clip_tri( struct draw_stage *stage,
if (tmpnr >= MAX_CLIPPED_VERTICES + 1)
return;
inlist[0] = dup_vert(stage, inlist[0], tmpnr++);
- copy_colors(stage, inlist[0], header->v[2]);
+ copy_flat(stage, inlist[0], header->v[2]);
}
}
}
@@ -471,10 +492,7 @@ do_clip_line( struct draw_stage *stage,
if (v0->clipmask) {
interp( clipper, stage->tmp[0], t0, v0, v1 );
-
- if (clipper->flat)
- copy_colors(stage, stage->tmp[0], v0);
-
+ copy_flat(stage, stage->tmp[0], v0);
newprim.v[0] = stage->tmp[0];
}
else {
@@ -548,20 +566,45 @@ static void
clip_init_state( struct draw_stage *stage )
{
struct clip_stage *clipper = clip_stage( stage );
+ const struct draw_vertex_shader *vs = stage->draw->vs.vertex_shader;
+ const struct draw_fragment_shader *fs = stage->draw->fs.fragment_shader;
+ uint i;
- clipper->flat = stage->draw->rasterizer->flatshade ? TRUE : FALSE;
+ int indexed_interp[2];
+ indexed_interp[0] = indexed_interp[1] = stage->draw->rasterizer->flatshade ?
+ TGSI_INTERPOLATE_CONSTANT : TGSI_INTERPOLATE_PERSPECTIVE;
- if (clipper->flat) {
- const struct draw_vertex_shader *vs = stage->draw->vs.vertex_shader;
- uint i;
+ for (i = 0; i < fs->info.num_inputs; i++) {
+ if (fs->info.input_semantic_name[i] == TGSI_SEMANTIC_COLOR) {
+ if (fs->info.input_interpolate[i] != TGSI_INTERPOLATE_COLOR)
+ indexed_interp[fs->info.input_semantic_index[i]] = fs->info.input_interpolate[i];
+ }
+ }
- clipper->num_color_attribs = 0;
- for (i = 0; i < vs->info.num_outputs; i++) {
- if (vs->info.output_semantic_name[i] == TGSI_SEMANTIC_COLOR ||
- vs->info.output_semantic_name[i] == TGSI_SEMANTIC_BCOLOR) {
- clipper->color_attribs[clipper->num_color_attribs++] = i;
- }
+ clipper->num_flat_attribs = 0;
+ memset(clipper->noperspective_attribs, 0, sizeof(clipper->noperspective_attribs));
+ for (i = 0; i < vs->info.num_outputs; i++) {
+ int interp;
+ if (vs->info.output_semantic_name[i] == TGSI_SEMANTIC_COLOR ||
+ vs->info.output_semantic_name[i] == TGSI_SEMANTIC_BCOLOR) {
+ interp = indexed_interp[vs->info.output_semantic_index[i]];
+ } else {
+ uint j;
+ interp = TGSI_INTERPOLATE_PERSPECTIVE;
+ for (j = 0; j < fs->info.num_inputs; j++) {
+ if (vs->info.output_semantic_name[i] == fs->info.input_semantic_name[j] &&
+ vs->info.output_semantic_index[i] == fs->info.input_semantic_index[j]) {
+ interp = fs->info.input_interpolate[j];
+ break;
+ }
+ }
}
+
+ if (interp == TGSI_INTERPOLATE_CONSTANT) {
+ clipper->flat_attribs[clipper->num_flat_attribs] = i;
+ clipper->num_flat_attribs++;
+ } else
+ clipper->noperspective_attribs[i] = interp == TGSI_INTERPOLATE_LINEAR;
}
stage->tri = clip_tri;
--
1.7.10.280.gaa39
More information about the mesa-dev
mailing list