From cb136a93aba4dc64db7e446b0fbc36c9172e4017 Mon Sep 17 00:00:00 2001 From: Brian Paul Date: Wed, 5 May 2010 18:19:06 -0600 Subject: 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. --- src/gallium/auxiliary/draw/draw_pipe.c | 42 +++- src/gallium/auxiliary/draw/draw_pipe_clip.c | 36 +-- src/gallium/auxiliary/draw/draw_pipe_vbuf.c | 15 +- src/gallium/auxiliary/draw/draw_pt_decompose.h | 71 ++++-- src/gallium/auxiliary/draw/draw_pt_vcache.c | 8 +- src/gallium/drivers/softpipe/sp_prim_vbuf.c | 308 ++++++++++++++++--------- src/gallium/drivers/softpipe/sp_setup.c | 5 +- 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 64c35025081..7ea04e38193 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 428ef4ef67a..d0532cb341e 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 abbf6247ab8..1fd083e54d0 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 02567d97f26..52f9593d46e 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 37ffbac4f92..bfcd709f25d 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 a58bc107c0a..0168b320371 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 86354664e4b..35ef9e698d5 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 */ { -- cgit v1.2.3