summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBrian Paul <brianp@vmware.com>2010-05-05 18:19:06 -0600
committerBrian Paul <brianp@vmware.com>2010-05-05 18:19:06 -0600
commitcb136a93aba4dc64db7e446b0fbc36c9172e4017 (patch)
treef899c682980b4af56e4dd0c7cd2d08cefb4efce3
parenta8bb49562938e94459f398a1733a76eb9c690f6c (diff)
gallium: rework provoking vertex code
Builds on commit ddb0e18f6c5582d4d2cc59ffd16ad9c4639ed059 and fixes regressions in glean clipFlat test. We assume that Gallium drivers observe flatshade_first for all triangles and that all the assorted per-triangle calls in the 'draw' module also follow flatshade_first. Everything else builds on those rules. Gallium does not use follow flatshade_first for GL quads, quad strips and polygons; the "last" vertex is always the provoking vertex for those prims. So now there are separate QUAD_FIRST_PV and QUAD_LAST_PV macros in the draw primitive decomposition code instead of one QUAD macro.
-rw-r--r--src/gallium/auxiliary/draw/draw_pipe.c42
-rw-r--r--src/gallium/auxiliary/draw/draw_pipe_clip.c36
-rw-r--r--src/gallium/auxiliary/draw/draw_pipe_vbuf.c15
-rw-r--r--src/gallium/auxiliary/draw/draw_pt_decompose.h71
-rw-r--r--src/gallium/auxiliary/draw/draw_pt_vcache.c8
-rw-r--r--src/gallium/drivers/softpipe/sp_prim_vbuf.c308
-rw-r--r--src/gallium/drivers/softpipe/sp_setup.c5
7 files changed, 321 insertions, 164 deletions
diff --git a/src/gallium/auxiliary/draw/draw_pipe.c b/src/gallium/auxiliary/draw/draw_pipe.c
index 64c3502508..7ea04e3819 100644
--- a/src/gallium/auxiliary/draw/draw_pipe.c
+++ b/src/gallium/auxiliary/draw/draw_pipe.c
@@ -170,7 +170,25 @@ static void do_triangle( struct draw_context *draw,
* Set up macros for draw_pt_decompose.h template code.
* This code uses vertex indexes / elements.
*/
-#define QUAD(i0,i1,i2,i3) \
+
+/* emit first quad vertex as first vertex in triangles */
+#define QUAD_FIRST_PV(i0,i1,i2,i3) \
+ do_triangle( draw, \
+ ( DRAW_PIPE_RESET_STIPPLE | \
+ DRAW_PIPE_EDGE_FLAG_0 | \
+ DRAW_PIPE_EDGE_FLAG_1 ), \
+ verts + stride * elts[i0], \
+ verts + stride * elts[i1], \
+ verts + stride * elts[i2]); \
+ do_triangle( draw, \
+ ( DRAW_PIPE_EDGE_FLAG_1 | \
+ DRAW_PIPE_EDGE_FLAG_2 ), \
+ verts + stride * elts[i0], \
+ verts + stride * elts[i2], \
+ verts + stride * elts[i3])
+
+/* emit last quad vertex as last vertex in triangles */
+#define QUAD_LAST_PV(i0,i1,i2,i3) \
do_triangle( draw, \
( DRAW_PIPE_RESET_STIPPLE | \
DRAW_PIPE_EDGE_FLAG_0 | \
@@ -261,9 +279,27 @@ void draw_pipeline_run( struct draw_context *draw,
/*
* Set up macros for draw_pt_decompose.h template code.
- * This code is for non-indexed rendering (no elts).
+ * This code is for non-indexed (aka linear) rendering (no elts).
*/
-#define QUAD(i0,i1,i2,i3) \
+
+/* emit first quad vertex as first vertex in triangles */
+#define QUAD_FIRST_PV(i0,i1,i2,i3) \
+ do_triangle( draw, \
+ ( DRAW_PIPE_RESET_STIPPLE | \
+ DRAW_PIPE_EDGE_FLAG_0 | \
+ DRAW_PIPE_EDGE_FLAG_1 ), \
+ verts + stride * ((i0) & ~DRAW_PIPE_FLAG_MASK), \
+ verts + stride * (i1), \
+ verts + stride * (i2)); \
+ do_triangle( draw, \
+ ( DRAW_PIPE_EDGE_FLAG_1 | \
+ DRAW_PIPE_EDGE_FLAG_2 ), \
+ verts + stride * ((i0) & ~DRAW_PIPE_FLAG_MASK), \
+ verts + stride * (i2), \
+ verts + stride * (i3))
+
+/* emit last quad vertex as last vertex in triangles */
+#define QUAD_LAST_PV(i0,i1,i2,i3) \
do_triangle( draw, \
( DRAW_PIPE_RESET_STIPPLE | \
DRAW_PIPE_EDGE_FLAG_0 | \
diff --git a/src/gallium/auxiliary/draw/draw_pipe_clip.c b/src/gallium/auxiliary/draw/draw_pipe_clip.c
index 428ef4ef67..d0532cb341 100644
--- a/src/gallium/auxiliary/draw/draw_pipe_clip.c
+++ b/src/gallium/auxiliary/draw/draw_pipe_clip.c
@@ -164,10 +164,18 @@ static void emit_poly( struct draw_stage *stage,
{
struct prim_header header;
unsigned i;
+ ushort edge_first, edge_middle, edge_last;
- const ushort edge_first = DRAW_PIPE_EDGE_FLAG_2;
- const ushort edge_middle = DRAW_PIPE_EDGE_FLAG_0;
- const ushort edge_last = DRAW_PIPE_EDGE_FLAG_1;
+ if (stage->draw->rasterizer->flatshade_first) {
+ edge_first = DRAW_PIPE_EDGE_FLAG_0;
+ edge_middle = DRAW_PIPE_EDGE_FLAG_1;
+ edge_last = DRAW_PIPE_EDGE_FLAG_2;
+ }
+ else {
+ edge_first = DRAW_PIPE_EDGE_FLAG_2;
+ edge_middle = DRAW_PIPE_EDGE_FLAG_0;
+ edge_last = DRAW_PIPE_EDGE_FLAG_1;
+ }
/* later stages may need the determinant, but only the sign matters */
header.det = origPrim->det;
@@ -301,21 +309,21 @@ do_clip_tri( struct draw_stage *stage,
/* If flat-shading, copy color to new provoking vertex.
*/
- if (stage->draw->rasterizer->flatshade_first) {
- if (clipper->flat && inlist[0] != header->v[0]) {
- inlist[0] = dup_vert(stage, inlist[0], tmpnr++);
-
- copy_colors(stage, inlist[0], header->v[0]);
+ if (clipper->flat) {
+ if (stage->draw->rasterizer->flatshade_first) {
+ if (inlist[0] != header->v[0]) {
+ inlist[0] = dup_vert(stage, inlist[0], tmpnr++);
+ copy_colors(stage, inlist[0], header->v[0]);
+ }
}
- } else {
- if (clipper->flat && inlist[0] != header->v[2]) {
- inlist[0] = dup_vert(stage, inlist[0], tmpnr++);
-
- copy_colors(stage, inlist[0], header->v[2]);
+ else {
+ if (inlist[0] != header->v[2]) {
+ 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)
diff --git a/src/gallium/auxiliary/draw/draw_pipe_vbuf.c b/src/gallium/auxiliary/draw/draw_pipe_vbuf.c
index abbf6247ab..1fd083e54d 100644
--- a/src/gallium/auxiliary/draw/draw_pipe_vbuf.c
+++ b/src/gallium/auxiliary/draw/draw_pipe_vbuf.c
@@ -159,19 +159,8 @@ vbuf_tri( struct draw_stage *stage,
check_space( vbuf, 3 );
- if (vbuf->stage.draw->rasterizer->flatshade_first) {
- /* Put provoking vertex in position expected by the driver.
- * Emit last provoking vertex in first pos.
- * Swap verts 0 & 1 to preserve polygon winding.
- */
- vbuf->indices[vbuf->nr_indices++] = emit_vertex( vbuf, prim->v[2] );
- vbuf->indices[vbuf->nr_indices++] = emit_vertex( vbuf, prim->v[0] );
- vbuf->indices[vbuf->nr_indices++] = emit_vertex( vbuf, prim->v[1] );
- }
- else {
- for (i = 0; i < 3; i++) {
- vbuf->indices[vbuf->nr_indices++] = emit_vertex( vbuf, prim->v[i] );
- }
+ for (i = 0; i < 3; i++) {
+ vbuf->indices[vbuf->nr_indices++] = emit_vertex( vbuf, prim->v[i] );
}
}
diff --git a/src/gallium/auxiliary/draw/draw_pt_decompose.h b/src/gallium/auxiliary/draw/draw_pt_decompose.h
index 02567d97f2..52f9593d46 100644
--- a/src/gallium/auxiliary/draw/draw_pt_decompose.h
+++ b/src/gallium/auxiliary/draw/draw_pt_decompose.h
@@ -57,6 +57,7 @@ static void FUNC( ARGS,
case PIPE_PRIM_TRIANGLE_STRIP:
if (flatfirst) {
for (i = 0; i+2 < count; i++) {
+ /* Emit first triangle vertex as first triangle vertex */
TRIANGLE( DRAW_PIPE_RESET_STIPPLE | DRAW_PIPE_EDGE_FLAG_ALL,
(i + 0),
(i + 1 + (i&1)),
@@ -65,6 +66,7 @@ static void FUNC( ARGS,
}
else {
for (i = 0; i+2 < count; i++) {
+ /* Emit last triangle vertex as last triangle vertex */
TRIANGLE( DRAW_PIPE_RESET_STIPPLE | DRAW_PIPE_EDGE_FLAG_ALL,
(i + 0 + (i&1)),
(i + 1 - (i&1)),
@@ -96,24 +98,52 @@ static void FUNC( ARGS,
case PIPE_PRIM_QUADS:
- for (i = 0; i+3 < count; i += 4) {
- QUAD( (i + 0),
- (i + 1),
- (i + 2),
- (i + 3));
+ /* GL quads don't follow provoking vertex convention */
+ if (flatfirst) {
+ for (i = 0; i+3 < count; i += 4) {
+ /* emit last quad vertex as first triangle vertex */
+ QUAD_FIRST_PV( (i + 3),
+ (i + 0),
+ (i + 1),
+ (i + 2) );
+ }
+ }
+ else {
+ for (i = 0; i+3 < count; i += 4) {
+ /* emit last quad vertex as last triangle vertex */
+ QUAD_LAST_PV( (i + 0),
+ (i + 1),
+ (i + 2),
+ (i + 3) );
+ }
}
break;
case PIPE_PRIM_QUAD_STRIP:
- for (i = 0; i+3 < count; i += 2) {
- QUAD( (i + 2),
- (i + 0),
- (i + 1),
- (i + 3));
+ /* GL quad strips don't follow provoking vertex convention */
+ if (flatfirst) {
+ for (i = 0; i+3 < count; i += 2) {
+ /* emit last quad vertex as first triangle vertex */
+ QUAD_FIRST_PV( (i + 3),
+ (i + 2),
+ (i + 0),
+ (i + 1) );
+
+ }
+ }
+ else {
+ for (i = 0; i+3 < count; i += 2) {
+ /* emit last quad vertex as last triangle vertex */
+ QUAD_LAST_PV( (i + 2),
+ (i + 0),
+ (i + 1),
+ (i + 3) );
+ }
}
break;
case PIPE_PRIM_POLYGON:
+ /* GL polygons don't follow provoking vertex convention */
{
/* These bitflags look a little odd because we submit the
* vertices as (1,2,0) to satisfy flatshade requirements.
@@ -129,10 +159,20 @@ static void FUNC( ARGS,
if (i + 3 == count)
flags |= edge_last;
- TRIANGLE( flags,
- (i + 1),
- (i + 2),
- (0));
+ if (flatfirst) {
+ /* emit first polygon vertex as first triangle vertex */
+ TRIANGLE( flags,
+ (0),
+ (i + 1),
+ (i + 2) );
+ }
+ else {
+ /* emit first polygon vertex as last triangle vertex */
+ TRIANGLE( flags,
+ (i + 1),
+ (i + 2),
+ (0));
+ }
}
}
break;
@@ -147,7 +187,8 @@ static void FUNC( ARGS,
#undef TRIANGLE
-#undef QUAD
+#undef QUAD_FIRST_PV
+#undef QUAD_LAST_PV
#undef POINT
#undef LINE
#undef FUNC
diff --git a/src/gallium/auxiliary/draw/draw_pt_vcache.c b/src/gallium/auxiliary/draw/draw_pt_vcache.c
index 37ffbac4f9..bfcd709f25 100644
--- a/src/gallium/auxiliary/draw/draw_pt_vcache.c
+++ b/src/gallium/auxiliary/draw/draw_pt_vcache.c
@@ -199,12 +199,12 @@ vcache_ef_quad( struct vcache_frontend *vcache,
( DRAW_PIPE_RESET_STIPPLE |
DRAW_PIPE_EDGE_FLAG_0 |
DRAW_PIPE_EDGE_FLAG_1 ),
- i0, i1, i2 );
+ i3, i0, i1 );
vcache_triangle_flags( vcache,
- ( DRAW_PIPE_EDGE_FLAG_2 |
- DRAW_PIPE_EDGE_FLAG_1 ),
- i0, i2, i3 );
+ ( DRAW_PIPE_EDGE_FLAG_1 |
+ DRAW_PIPE_EDGE_FLAG_2 ),
+ i3, i1, i2 );
}
else {
vcache_triangle_flags( vcache,
diff --git a/src/gallium/drivers/softpipe/sp_prim_vbuf.c b/src/gallium/drivers/softpipe/sp_prim_vbuf.c
index a58bc107c0..0168b32037 100644
--- a/src/gallium/drivers/softpipe/sp_prim_vbuf.c
+++ b/src/gallium/drivers/softpipe/sp_prim_vbuf.c
@@ -164,20 +164,21 @@ sp_vbuf_draw(struct vbuf_render *vbr, const ushort *indices, uint nr)
struct softpipe_context *softpipe = cvbr->softpipe;
const unsigned stride = softpipe->vertex_info_vbuf.size * sizeof(float);
const void *vertex_buffer = cvbr->vertex_buffer;
- struct setup_context *setup_ctx = cvbr->setup;
+ struct setup_context *setup = cvbr->setup;
+ const boolean flatshade_first = softpipe->rasterizer->flatshade_first;
unsigned i;
switch (cvbr->prim) {
case PIPE_PRIM_POINTS:
for (i = 0; i < nr; i++) {
- sp_setup_point( setup_ctx,
+ sp_setup_point( setup,
get_vert(vertex_buffer, indices[i-0], stride) );
}
break;
case PIPE_PRIM_LINES:
for (i = 1; i < nr; i += 2) {
- sp_setup_line( setup_ctx,
+ sp_setup_line( setup,
get_vert(vertex_buffer, indices[i-1], stride),
get_vert(vertex_buffer, indices[i-0], stride) );
}
@@ -185,7 +186,7 @@ sp_vbuf_draw(struct vbuf_render *vbr, const ushort *indices, uint nr)
case PIPE_PRIM_LINE_STRIP:
for (i = 1; i < nr; i ++) {
- sp_setup_line( setup_ctx,
+ sp_setup_line( setup,
get_vert(vertex_buffer, indices[i-1], stride),
get_vert(vertex_buffer, indices[i-0], stride) );
}
@@ -193,48 +194,41 @@ sp_vbuf_draw(struct vbuf_render *vbr, const ushort *indices, uint nr)
case PIPE_PRIM_LINE_LOOP:
for (i = 1; i < nr; i ++) {
- sp_setup_line( setup_ctx,
+ sp_setup_line( setup,
get_vert(vertex_buffer, indices[i-1], stride),
get_vert(vertex_buffer, indices[i-0], stride) );
}
if (nr) {
- sp_setup_line( setup_ctx,
+ sp_setup_line( setup,
get_vert(vertex_buffer, indices[nr-1], stride),
get_vert(vertex_buffer, indices[0], stride) );
}
break;
case PIPE_PRIM_TRIANGLES:
- if (softpipe->rasterizer->flatshade_first) {
- for (i = 2; i < nr; i += 3) {
- sp_setup_tri( setup_ctx,
- get_vert(vertex_buffer, indices[i-1], stride),
- get_vert(vertex_buffer, indices[i-0], stride),
- get_vert(vertex_buffer, indices[i-2], stride) );
- }
- }
- else {
- for (i = 2; i < nr; i += 3) {
- sp_setup_tri( setup_ctx,
- get_vert(vertex_buffer, indices[i-2], stride),
- get_vert(vertex_buffer, indices[i-1], stride),
- get_vert(vertex_buffer, indices[i-0], stride) );
- }
+ for (i = 2; i < nr; i += 3) {
+ sp_setup_tri( setup,
+ get_vert(vertex_buffer, indices[i-2], stride),
+ get_vert(vertex_buffer, indices[i-1], stride),
+ get_vert(vertex_buffer, indices[i-0], stride) );
}
break;
case PIPE_PRIM_TRIANGLE_STRIP:
- if (softpipe->rasterizer->flatshade_first) {
+ if (flatshade_first) {
for (i = 2; i < nr; i += 1) {
- sp_setup_tri( setup_ctx,
+ /* emit first triangle vertex as first triangle vertex */
+ sp_setup_tri( setup,
+ get_vert(vertex_buffer, indices[i-2], stride),
get_vert(vertex_buffer, indices[i+(i&1)-1], stride),
- get_vert(vertex_buffer, indices[i-(i&1)], stride),
- get_vert(vertex_buffer, indices[i-2], stride) );
+ get_vert(vertex_buffer, indices[i-(i&1)], stride) );
+
}
}
else {
for (i = 2; i < nr; i += 1) {
- sp_setup_tri( setup_ctx,
+ /* emit last triangle vertex as last triangle vertex */
+ sp_setup_tri( setup,
get_vert(vertex_buffer, indices[i+(i&1)-2], stride),
get_vert(vertex_buffer, indices[i-(i&1)-1], stride),
get_vert(vertex_buffer, indices[i-0], stride) );
@@ -243,17 +237,19 @@ sp_vbuf_draw(struct vbuf_render *vbr, const ushort *indices, uint nr)
break;
case PIPE_PRIM_TRIANGLE_FAN:
- if (softpipe->rasterizer->flatshade_first) {
+ if (flatshade_first) {
for (i = 2; i < nr; i += 1) {
- sp_setup_tri( setup_ctx,
+ /* emit first non-spoke vertex as first vertex */
+ sp_setup_tri( setup,
+ get_vert(vertex_buffer, indices[i-1], stride),
get_vert(vertex_buffer, indices[i-0], stride),
- get_vert(vertex_buffer, indices[0], stride),
- get_vert(vertex_buffer, indices[i-1], stride) );
+ get_vert(vertex_buffer, indices[0], stride) );
}
}
else {
for (i = 2; i < nr; i += 1) {
- sp_setup_tri( setup_ctx,
+ /* emit last non-spoke vertex as last vertex */
+ sp_setup_tri( setup,
get_vert(vertex_buffer, indices[0], stride),
get_vert(vertex_buffer, indices[i-1], stride),
get_vert(vertex_buffer, indices[i-0], stride) );
@@ -262,43 +258,88 @@ sp_vbuf_draw(struct vbuf_render *vbr, const ushort *indices, uint nr)
break;
case PIPE_PRIM_QUADS:
- for (i = 3; i < nr; i += 4) {
- sp_setup_tri( setup_ctx,
- get_vert(vertex_buffer, indices[i-3], stride),
- get_vert(vertex_buffer, indices[i-2], stride),
- get_vert(vertex_buffer, indices[i-0], stride) );
+ /* GL quads don't follow provoking vertex convention */
+ if (flatshade_first) {
+ /* emit last quad vertex as first triangle vertex */
+ for (i = 3; i < nr; i += 4) {
+ sp_setup_tri( setup,
+ get_vert(vertex_buffer, indices[i-0], stride),
+ get_vert(vertex_buffer, indices[i-3], stride),
+ get_vert(vertex_buffer, indices[i-2], stride) );
- sp_setup_tri( setup_ctx,
- get_vert(vertex_buffer, indices[i-2], stride),
- get_vert(vertex_buffer, indices[i-1], stride),
- get_vert(vertex_buffer, indices[i-0], stride) );
+ sp_setup_tri( setup,
+ get_vert(vertex_buffer, indices[i-0], stride),
+ get_vert(vertex_buffer, indices[i-2], stride),
+ get_vert(vertex_buffer, indices[i-1], stride) );
+ }
+ }
+ else {
+ /* emit last quad vertex as last triangle vertex */
+ for (i = 3; i < nr; i += 4) {
+ sp_setup_tri( setup,
+ get_vert(vertex_buffer, indices[i-3], stride),
+ get_vert(vertex_buffer, indices[i-2], stride),
+ get_vert(vertex_buffer, indices[i-0], stride) );
+
+ sp_setup_tri( setup,
+ get_vert(vertex_buffer, indices[i-2], stride),
+ get_vert(vertex_buffer, indices[i-1], stride),
+ get_vert(vertex_buffer, indices[i-0], stride) );
+ }
}
break;
case PIPE_PRIM_QUAD_STRIP:
- for (i = 3; i < nr; i += 2) {
- sp_setup_tri( setup_ctx,
- get_vert(vertex_buffer, indices[i-3], stride),
- get_vert(vertex_buffer, indices[i-2], stride),
- get_vert(vertex_buffer, indices[i-0], stride) );
- sp_setup_tri( setup_ctx,
- get_vert(vertex_buffer, indices[i-1], stride),
- get_vert(vertex_buffer, indices[i-3], stride),
- get_vert(vertex_buffer, indices[i-0], stride) );
+ /* GL quad strips don't follow provoking vertex convention */
+ if (flatshade_first) {
+ /* emit last quad vertex as first triangle vertex */
+ for (i = 3; i < nr; i += 2) {
+ sp_setup_tri( setup,
+ get_vert(vertex_buffer, indices[i-0], stride),
+ get_vert(vertex_buffer, indices[i-3], stride),
+ get_vert(vertex_buffer, indices[i-2], stride) );
+ sp_setup_tri( setup,
+ get_vert(vertex_buffer, indices[i-0], stride),
+ get_vert(vertex_buffer, indices[i-1], stride),
+ get_vert(vertex_buffer, indices[i-3], stride) );
+ }
+ }
+ else {
+ /* emit last quad vertex as last triangle vertex */
+ for (i = 3; i < nr; i += 2) {
+ sp_setup_tri( setup,
+ get_vert(vertex_buffer, indices[i-3], stride),
+ get_vert(vertex_buffer, indices[i-2], stride),
+ get_vert(vertex_buffer, indices[i-0], stride) );
+ sp_setup_tri( setup,
+ get_vert(vertex_buffer, indices[i-1], stride),
+ get_vert(vertex_buffer, indices[i-3], stride),
+ get_vert(vertex_buffer, indices[i-0], stride) );
+ }
}
break;
case PIPE_PRIM_POLYGON:
/* Almost same as tri fan but the _first_ vertex specifies the flat
- * shading color. Note that the first polygon vertex is passed as
- * the last triangle vertex here.
- * flatshade_first state makes no difference.
+ * shading color.
*/
- for (i = 2; i < nr; i += 1) {
- sp_setup_tri( setup_ctx,
- get_vert(vertex_buffer, indices[i-0], stride),
- get_vert(vertex_buffer, indices[i-1], stride),
- get_vert(vertex_buffer, indices[0], stride) );
+ if (flatshade_first) {
+ /* emit first polygon vertex as first triangle vertex */
+ for (i = 2; i < nr; i += 1) {
+ sp_setup_tri( setup,
+ get_vert(vertex_buffer, indices[0], stride),
+ get_vert(vertex_buffer, indices[i-1], stride),
+ get_vert(vertex_buffer, indices[i-0], stride) );
+ }
+ }
+ else {
+ /* emit first polygon vertex as last triangle vertex */
+ for (i = 2; i < nr; i += 1) {
+ sp_setup_tri( setup,
+ get_vert(vertex_buffer, indices[i-1], stride),
+ get_vert(vertex_buffer, indices[i-0], stride),
+ get_vert(vertex_buffer, indices[0], stride) );
+ }
}
break;
@@ -317,23 +358,24 @@ sp_vbuf_draw_arrays(struct vbuf_render *vbr, uint start, uint nr)
{
struct softpipe_vbuf_render *cvbr = softpipe_vbuf_render(vbr);
struct softpipe_context *softpipe = cvbr->softpipe;
- struct setup_context *setup_ctx = cvbr->setup;
+ struct setup_context *setup = cvbr->setup;
const unsigned stride = softpipe->vertex_info_vbuf.size * sizeof(float);
const void *vertex_buffer =
(void *) get_vert(cvbr->vertex_buffer, start, stride);
+ const boolean flatshade_first = softpipe->rasterizer->flatshade_first;
unsigned i;
switch (cvbr->prim) {
case PIPE_PRIM_POINTS:
for (i = 0; i < nr; i++) {
- sp_setup_point( setup_ctx,
+ sp_setup_point( setup,
get_vert(vertex_buffer, i-0, stride) );
}
break;
case PIPE_PRIM_LINES:
for (i = 1; i < nr; i += 2) {
- sp_setup_line( setup_ctx,
+ sp_setup_line( setup,
get_vert(vertex_buffer, i-1, stride),
get_vert(vertex_buffer, i-0, stride) );
}
@@ -341,7 +383,7 @@ sp_vbuf_draw_arrays(struct vbuf_render *vbr, uint start, uint nr)
case PIPE_PRIM_LINE_STRIP:
for (i = 1; i < nr; i ++) {
- sp_setup_line( setup_ctx,
+ sp_setup_line( setup,
get_vert(vertex_buffer, i-1, stride),
get_vert(vertex_buffer, i-0, stride) );
}
@@ -349,48 +391,40 @@ sp_vbuf_draw_arrays(struct vbuf_render *vbr, uint start, uint nr)
case PIPE_PRIM_LINE_LOOP:
for (i = 1; i < nr; i ++) {
- sp_setup_line( setup_ctx,
+ sp_setup_line( setup,
get_vert(vertex_buffer, i-1, stride),
get_vert(vertex_buffer, i-0, stride) );
}
if (nr) {
- sp_setup_line( setup_ctx,
+ sp_setup_line( setup,
get_vert(vertex_buffer, nr-1, stride),
get_vert(vertex_buffer, 0, stride) );
}
break;
case PIPE_PRIM_TRIANGLES:
- if (softpipe->rasterizer->flatshade_first) {
- for (i = 2; i < nr; i += 3) {
- sp_setup_tri( setup_ctx,
- get_vert(vertex_buffer, i-1, stride),
- get_vert(vertex_buffer, i-0, stride),
- get_vert(vertex_buffer, i-2, stride) );
- }
- }
- else {
- for (i = 2; i < nr; i += 3) {
- sp_setup_tri( setup_ctx,
- get_vert(vertex_buffer, i-2, stride),
- get_vert(vertex_buffer, i-1, stride),
- get_vert(vertex_buffer, i-0, stride) );
- }
+ for (i = 2; i < nr; i += 3) {
+ sp_setup_tri( setup,
+ get_vert(vertex_buffer, i-2, stride),
+ get_vert(vertex_buffer, i-1, stride),
+ get_vert(vertex_buffer, i-0, stride) );
}
break;
case PIPE_PRIM_TRIANGLE_STRIP:
- if (softpipe->rasterizer->flatshade_first) {
+ if (flatshade_first) {
for (i = 2; i < nr; i++) {
- sp_setup_tri( setup_ctx,
+ /* emit first triangle vertex as first triangle vertex */
+ sp_setup_tri( setup,
+ get_vert(vertex_buffer, i-2, stride),
get_vert(vertex_buffer, i+(i&1)-1, stride),
- get_vert(vertex_buffer, i-(i&1), stride),
- get_vert(vertex_buffer, i-2, stride) );
+ get_vert(vertex_buffer, i-(i&1), stride) );
}
}
else {
for (i = 2; i < nr; i++) {
- sp_setup_tri( setup_ctx,
+ /* emit last triangle vertex as last triangle vertex */
+ sp_setup_tri( setup,
get_vert(vertex_buffer, i+(i&1)-2, stride),
get_vert(vertex_buffer, i-(i&1)-1, stride),
get_vert(vertex_buffer, i-0, stride) );
@@ -399,17 +433,19 @@ sp_vbuf_draw_arrays(struct vbuf_render *vbr, uint start, uint nr)
break;
case PIPE_PRIM_TRIANGLE_FAN:
- if (softpipe->rasterizer->flatshade_first) {
+ if (flatshade_first) {
for (i = 2; i < nr; i += 1) {
- sp_setup_tri( setup_ctx,
+ /* emit first non-spoke vertex as first vertex */
+ sp_setup_tri( setup,
+ get_vert(vertex_buffer, i-1, stride),
get_vert(vertex_buffer, i-0, stride),
- get_vert(vertex_buffer, 0, stride),
- get_vert(vertex_buffer, i-1, stride) );
+ get_vert(vertex_buffer, 0, stride) );
}
}
else {
for (i = 2; i < nr; i += 1) {
- sp_setup_tri( setup_ctx,
+ /* emit last non-spoke vertex as last vertex */
+ sp_setup_tri( setup,
get_vert(vertex_buffer, 0, stride),
get_vert(vertex_buffer, i-1, stride),
get_vert(vertex_buffer, i-0, stride) );
@@ -418,42 +454,86 @@ sp_vbuf_draw_arrays(struct vbuf_render *vbr, uint start, uint nr)
break;
case PIPE_PRIM_QUADS:
- for (i = 3; i < nr; i += 4) {
- sp_setup_tri( setup_ctx,
- get_vert(vertex_buffer, i-3, stride),
- get_vert(vertex_buffer, i-2, stride),
- get_vert(vertex_buffer, i-0, stride) );
- sp_setup_tri( setup_ctx,
- get_vert(vertex_buffer, i-2, stride),
- get_vert(vertex_buffer, i-1, stride),
- get_vert(vertex_buffer, i-0, stride) );
+ /* GL quads don't follow provoking vertex convention */
+ if (flatshade_first) {
+ /* emit last quad vertex as first triangle vertex */
+ for (i = 3; i < nr; i += 4) {
+ sp_setup_tri( setup,
+ get_vert(vertex_buffer, i-0, stride),
+ get_vert(vertex_buffer, i-3, stride),
+ get_vert(vertex_buffer, i-2, stride) );
+ sp_setup_tri( setup,
+ get_vert(vertex_buffer, i-0, stride),
+ get_vert(vertex_buffer, i-2, stride),
+ get_vert(vertex_buffer, i-1, stride) );
+ }
+ }
+ else {
+ /* emit last quad vertex as last triangle vertex */
+ for (i = 3; i < nr; i += 4) {
+ sp_setup_tri( setup,
+ get_vert(vertex_buffer, i-3, stride),
+ get_vert(vertex_buffer, i-2, stride),
+ get_vert(vertex_buffer, i-0, stride) );
+ sp_setup_tri( setup,
+ get_vert(vertex_buffer, i-2, stride),
+ get_vert(vertex_buffer, i-1, stride),
+ get_vert(vertex_buffer, i-0, stride) );
+ }
}
break;
case PIPE_PRIM_QUAD_STRIP:
- for (i = 3; i < nr; i += 2) {
- sp_setup_tri( setup_ctx,
- get_vert(vertex_buffer, i-3, stride),
- get_vert(vertex_buffer, i-2, stride),
- get_vert(vertex_buffer, i-0, stride) );
- sp_setup_tri( setup_ctx,
- get_vert(vertex_buffer, i-1, stride),
- get_vert(vertex_buffer, i-3, stride),
- get_vert(vertex_buffer, i-0, stride) );
+ /* GL quad strips don't follow provoking vertex convention */
+ if (flatshade_first) {
+ /* emit last quad vertex as first triangle vertex */
+ for (i = 3; i < nr; i += 2) {
+ sp_setup_tri( setup,
+ get_vert(vertex_buffer, i-0, stride),
+ get_vert(vertex_buffer, i-3, stride),
+ get_vert(vertex_buffer, i-2, stride) );
+ sp_setup_tri( setup,
+ get_vert(vertex_buffer, i-0, stride),
+ get_vert(vertex_buffer, i-1, stride),
+ get_vert(vertex_buffer, i-3, stride) );
+ }
+ }
+ else {
+ /* emit last quad vertex as last triangle vertex */
+ for (i = 3; i < nr; i += 2) {
+ sp_setup_tri( setup,
+ get_vert(vertex_buffer, i-3, stride),
+ get_vert(vertex_buffer, i-2, stride),
+ get_vert(vertex_buffer, i-0, stride) );
+ sp_setup_tri( setup,
+ get_vert(vertex_buffer, i-1, stride),
+ get_vert(vertex_buffer, i-3, stride),
+ get_vert(vertex_buffer, i-0, stride) );
+ }
}
break;
case PIPE_PRIM_POLYGON:
/* Almost same as tri fan but the _first_ vertex specifies the flat
- * shading color. Note that the first polygon vertex is passed as
- * the last triangle vertex here.
- * flatshade_first state makes no difference.
+ * shading color.
*/
- for (i = 2; i < nr; i += 1) {
- sp_setup_tri( setup_ctx,
- get_vert(vertex_buffer, i-1, stride),
- get_vert(vertex_buffer, i-0, stride),
- get_vert(vertex_buffer, 0, stride) );
+ if (flatshade_first) {
+ /* emit first polygon vertex as first triangle vertex */
+ for (i = 2; i < nr; i += 1) {
+ sp_setup_tri( setup,
+ get_vert(vertex_buffer, 0, stride),
+ get_vert(vertex_buffer, i-1, stride),
+ get_vert(vertex_buffer, i-0, stride) );
+ }
+ }
+ else {
+ /* emit first polygon vertex as last triangle vertex */
+ for (i = 2; i < nr; i += 1) {
+ sp_setup_tri( setup,
+ get_vert(vertex_buffer, i-1, stride),
+ get_vert(vertex_buffer, i-0, stride),
+ get_vert(vertex_buffer, 0, stride) );
+ }
}
break;
diff --git a/src/gallium/drivers/softpipe/sp_setup.c b/src/gallium/drivers/softpipe/sp_setup.c
index 86354664e4..35ef9e698d 100644
--- a/src/gallium/drivers/softpipe/sp_setup.c
+++ b/src/gallium/drivers/softpipe/sp_setup.c
@@ -304,7 +304,10 @@ setup_sort_vertices(struct setup_context *setup,
const float (*v1)[4],
const float (*v2)[4])
{
- setup->vprovoke = v2;
+ if (setup->softpipe->rasterizer->flatshade_first)
+ setup->vprovoke = v0;
+ else
+ setup->vprovoke = v2;
/* determine bottom to top order of vertices */
{