summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKeith Whitwell <keith@tungstengraphics.com>2008-01-28 15:50:02 +0000
committerKeith Whitwell <keith@tungstengraphics.com>2008-01-28 15:50:02 +0000
commit82d9063708539d53c7670b2ab732bed24230b94d (patch)
tree668ee28b9fa45e5d87753ac26390c97d9c5900a4
parent88858e046888d0bcb763537adc74a64e564678df (diff)
gallium: handle flatshading explicitly in clipper stage
We can do a better job in the clip stage than just relying on the brute-force approach of copying colors to all incoming vertices applied in the flatshade stage. At very least, it is only necessary to do this in the clipper when a primitive is actually being clipped.
-rw-r--r--src/mesa/pipe/draw/draw_clip.c136
-rw-r--r--src/mesa/pipe/draw/draw_validate.c10
2 files changed, 99 insertions, 47 deletions
diff --git a/src/mesa/pipe/draw/draw_clip.c b/src/mesa/pipe/draw/draw_clip.c
index 2d410e3244..da20028904 100644
--- a/src/mesa/pipe/draw/draw_clip.c
+++ b/src/mesa/pipe/draw/draw_clip.c
@@ -33,6 +33,8 @@
#include "pipe/p_util.h"
+#include "pipe/p_shader_tokens.h"
+
#include "draw_context.h"
#include "draw_private.h"
@@ -54,6 +56,12 @@
struct clipper {
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 */
+
float (*plane)[4];
};
@@ -82,6 +90,17 @@ static void interp_attr( float *fdst,
fdst[3] = LINTERP( t, fout[3], fin[3] );
}
+static void copy_colors( struct draw_stage *stage,
+ struct vertex_header *dst,
+ const struct vertex_header *src )
+{
+ const struct clipper *clipper = clipper_stage(stage);
+ uint i;
+ for (i = 0; i < clipper->num_color_attribs; i++) {
+ const uint attr = clipper->color_attribs[i];
+ COPY_4FV(dst->data[attr], src->data[attr]);
+ }
+}
@@ -134,27 +153,11 @@ static void interp( const struct clipper *clip,
}
}
-#if 0
-static INLINE void do_tri( struct draw_stage *next,
- struct prim_header *header )
-{
- unsigned i;
- for (i = 0; i < 3; i++) {
- float *ndc = header->v[i]->data[0];
- _mesa_printf("ndc %f %f %f\n", ndc[0], ndc[1], ndc[2]);
- assert(ndc[0] >= -1 && ndc[0] <= 641);
- assert(ndc[1] >= 30 && ndc[1] <= 481);
- }
- _mesa_printf("\n");
- next->tri(next, header);
-}
-#endif
-
static void emit_poly( struct draw_stage *stage,
struct vertex_header **inlist,
unsigned n,
- const struct prim_header *origPrim)
+ const struct prim_header *origPrim)
{
struct prim_header header;
unsigned i;
@@ -163,16 +166,16 @@ static void emit_poly( struct draw_stage *stage,
header.det = origPrim->det;
for (i = 2; i < n; i++) {
- header.v[0] = inlist[0];
- header.v[1] = inlist[i-1];
- header.v[2] = inlist[i];
+ header.v[0] = inlist[i-1];
+ header.v[1] = inlist[i];
+ header.v[2] = inlist[0]; /* keep in v[2] for flatshading */
{
- unsigned tmp0 = header.v[0]->edgeflag;
+ unsigned tmp1 = header.v[1]->edgeflag;
unsigned tmp2 = header.v[2]->edgeflag;
- if (i != 2) header.v[0]->edgeflag = 0;
- if (i != n-1) header.v[2]->edgeflag = 0;
+ if (i != n-1) header.v[1]->edgeflag = 0;
+ if (i != 2) header.v[2]->edgeflag = 0;
header.edgeflags = ((header.v[0]->edgeflag << 0) |
(header.v[1]->edgeflag << 1) |
@@ -180,27 +183,13 @@ static void emit_poly( struct draw_stage *stage,
stage->next->tri( stage->next, &header );
- header.v[0]->edgeflag = tmp0;
+ header.v[1]->edgeflag = tmp1;
header.v[2]->edgeflag = tmp2;
}
}
}
-#if 0
-static void emit_poly( struct draw_stage *stage )
-{
- unsigned i;
-
- for (i = 2; i < n; i++) {
- header->v[0] = inlist[0];
- header->v[1] = inlist[i-1];
- header->v[2] = inlist[i];
-
- stage->next->tri( stage->next, header );
- }
-}
-#endif
/* Clip a triangle against the viewport and user clip planes.
@@ -281,6 +270,18 @@ do_clip_tri( struct draw_stage *stage,
}
}
+ /* If flat-shading, copy color to new provoking vertex.
+ */
+ if (clipper->flat && inlist[0] != header->v[2]) {
+ if (1) {
+ inlist[0] = dup_vert(stage, inlist[0], tmpnr++);
+ }
+
+ copy_colors(stage, inlist[0], header->v[2]);
+ }
+
+
+
/* Emit the polygon as triangles to the setup stage:
*/
if (n >= 3)
@@ -328,6 +329,10 @@ 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);
+
newprim.v[0] = stage->tmp[0];
}
else {
@@ -393,8 +398,55 @@ clip_tri( struct draw_stage *stage,
}
}
-static void clip_flush( struct draw_stage *stage, unsigned flags )
+/* Update state. Could further delay this until we hit the first
+ * primitive that really requires clipping.
+ */
+static void
+clip_init_state( struct draw_stage *stage )
+{
+ struct clipper *clipper = clipper_stage( stage );
+
+ clipper->flat = stage->draw->rasterizer->flatshade;
+
+ if (clipper->flat) {
+ const struct pipe_shader_state *vs = stage->draw->vertex_shader->state;
+ uint i;
+
+ clipper->num_color_attribs = 0;
+ for (i = 0; i < vs->num_outputs; i++) {
+ if (vs->output_semantic_name[i] == TGSI_SEMANTIC_COLOR ||
+ vs->output_semantic_name[i] == TGSI_SEMANTIC_BCOLOR) {
+ clipper->color_attribs[clipper->num_color_attribs++] = i;
+ }
+ }
+ }
+
+ stage->tri = clip_tri;
+ stage->line = clip_line;
+}
+
+
+
+static void clip_first_tri( struct draw_stage *stage,
+ struct prim_header *header )
+{
+ clip_init_state( stage );
+ stage->tri( stage, header );
+}
+
+static void clip_first_line( struct draw_stage *stage,
+ struct prim_header *header )
+{
+ clip_init_state( stage );
+ stage->line( stage, header );
+}
+
+
+static void clip_flush( struct draw_stage *stage,
+ unsigned flags )
{
+ stage->tri = clip_first_tri;
+ stage->line = clip_first_line;
stage->next->flush( stage->next, flags );
}
@@ -420,12 +472,12 @@ struct draw_stage *draw_clip_stage( struct draw_context *draw )
{
struct clipper *clipper = CALLOC_STRUCT(clipper);
- draw_alloc_tmps( &clipper->stage, MAX_CLIPPED_VERTICES );
+ draw_alloc_tmps( &clipper->stage, MAX_CLIPPED_VERTICES+1 );
clipper->stage.draw = draw;
clipper->stage.point = clip_point;
- clipper->stage.line = clip_line;
- clipper->stage.tri = clip_tri;
+ clipper->stage.line = clip_first_line;
+ clipper->stage.tri = clip_first_tri;
clipper->stage.flush = clip_flush;
clipper->stage.reset_stipple_counter = clip_reset_stipple_counter;
clipper->stage.destroy = clip_destroy;
diff --git a/src/mesa/pipe/draw/draw_validate.c b/src/mesa/pipe/draw/draw_validate.c
index 86d5a5f814..4375ebabbc 100644
--- a/src/mesa/pipe/draw/draw_validate.c
+++ b/src/mesa/pipe/draw/draw_validate.c
@@ -78,6 +78,11 @@ static struct draw_stage *validate_pipeline( struct draw_stage *stage )
precalc_flat = 1; /* only needed for triangles really */
need_det = 1;
}
+
+ if (draw->rasterizer->flatshade && precalc_flat) {
+ draw->pipeline.flatshade->next = next;
+ next = draw->pipeline.flatshade;
+ }
if (draw->rasterizer->offset_cw ||
draw->rasterizer->offset_ccw) {
@@ -110,13 +115,8 @@ static struct draw_stage *validate_pipeline( struct draw_stage *stage )
{
draw->pipeline.clip->next = next;
next = draw->pipeline.clip;
- precalc_flat = 1; /* XXX: FIX ME! Only needed for clipped prims */
}
- if (draw->rasterizer->flatshade && precalc_flat) {
- draw->pipeline.flatshade->next = next;
- next = draw->pipeline.flatshade;
- }
draw->pipeline.first = next;
return next;