From: Keith Whitwell Date: Sun, 6 Apr 2008 13:29:30 +0000 (+0100) Subject: draw: fix edgeflag handling on the pt paths X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=5c19e47362c2d193850e98bd43a2bc2b783b0b5c;p=mesa.git draw: fix edgeflag handling on the pt paths Encode edgeflags (and reset_stipple info) into the top two bits of the fetch elements. This info could be moved elsewhere, but for now we can live with a 1<<30 maximum element size... Also use the primitive decomposition code from draw_prim.c verbatim, as it includes all this stuff and is known to work. --- diff --git a/src/gallium/auxiliary/draw/draw_pt.h b/src/gallium/auxiliary/draw/draw_pt.h index 800072c5115..590823fd330 100644 --- a/src/gallium/auxiliary/draw/draw_pt.h +++ b/src/gallium/auxiliary/draw/draw_pt.h @@ -40,6 +40,16 @@ typedef unsigned (*pt_elt_func)( const void *elts, unsigned idx ); struct draw_pt_middle_end; struct draw_context; +/* We use the top couple of bits in the vertex fetch index to convey a + * little API information. This limits the number of vertices we can + * address to only 1 billion -- if that becomes a problem, these could + * be moved out & passed separately. + */ +#define DRAW_PT_EDGEFLAG (1<<30) +#define DRAW_PT_RESET_STIPPLE (1<<31) +#define DRAW_PT_FLAG_MASK (3<<30) + + /* The "front end" - prepare sets of fetch, draw elements for the * middle end. * diff --git a/src/gallium/auxiliary/draw/draw_pt_fetch_pipeline.c b/src/gallium/auxiliary/draw/draw_pt_fetch_pipeline.c index ba95420b72a..4c2a281b295 100644 --- a/src/gallium/auxiliary/draw/draw_pt_fetch_pipeline.c +++ b/src/gallium/auxiliary/draw/draw_pt_fetch_pipeline.c @@ -72,7 +72,7 @@ struct fetch_pipeline_middle_end { struct draw_pt_middle_end base; struct draw_context *draw; - void (*header)( const unsigned *edgeflag, unsigned count, float **out); + void (*header)( unsigned idx, float **out); struct { const ubyte *ptr; @@ -122,8 +122,7 @@ static void emit_R32G32B32A32_FLOAT( const float *attrib, (*out) += 4; } -static void header( const unsigned *edgeflag, - unsigned idx, +static void header( unsigned idx, float **out ) { struct vertex_header *header = (struct vertex_header *) (*out); @@ -141,14 +140,15 @@ static void header( const unsigned *edgeflag, } -static void header_ef( const unsigned *edgeflag, - unsigned idx, +static void header_ef( unsigned idx, float **out ) { struct vertex_header *header = (struct vertex_header *) (*out); + /* XXX: need a reset_stipple flag in the vertex header too? + */ header->clipmask = 0; - header->edgeflag = (edgeflag[idx/32] & (1 << (idx%32))) != 0; + header->edgeflag = (idx & DRAW_PT_EDGEFLAG) != 0; header->pad = 0; header->vertex_id = UNDEFINED_VERTEX_ID; @@ -172,14 +172,14 @@ fetch_store_general( struct fetch_pipeline_middle_end *fpme, const unsigned *fetch_elts, unsigned count ) { - const unsigned *edgeflag = fpme->draw->user.edgeflag; float *out = (float *)out_ptr; uint i, j; for (i = 0; i < count; i++) { unsigned elt = fetch_elts[i]; - fpme->header( edgeflag, i, &out ); + fpme->header( elt, &out ); + elt &= ~DRAW_PT_FLAG_MASK; for (j = 0; j < fpme->nr_fetch; j++) { float attrib[4]; diff --git a/src/gallium/auxiliary/draw/draw_pt_pipeline.c b/src/gallium/auxiliary/draw/draw_pt_pipeline.c index 942df518eb2..e70e63d08fb 100644 --- a/src/gallium/auxiliary/draw/draw_pt_pipeline.c +++ b/src/gallium/auxiliary/draw/draw_pt_pipeline.c @@ -85,7 +85,6 @@ static void do_triangle( struct draw_context *draw, { struct prim_header prim; -// _mesa_printf("tri %d %d %d\n", i0, i1, i2); prim.v[0] = (struct vertex_header *)v0; prim.v[1] = (struct vertex_header *)v1; prim.v[2] = (struct vertex_header *)v2; @@ -95,6 +94,11 @@ static void do_triangle( struct draw_context *draw, (prim.v[2]->edgeflag << 2)); prim.pad = 0; + if (0) debug_printf("tri ef: %d %d %d\n", + prim.v[0]->edgeflag, + prim.v[1]->edgeflag, + prim.v[2]->edgeflag); + draw->pipeline.first->tri( draw->pipeline.first, &prim ); } diff --git a/src/gallium/auxiliary/draw/draw_pt_vcache.c b/src/gallium/auxiliary/draw/draw_pt_vcache.c index 5a068761df9..107dcfc269c 100644 --- a/src/gallium/auxiliary/draw/draw_pt_vcache.c +++ b/src/gallium/auxiliary/draw/draw_pt_vcache.c @@ -55,9 +55,6 @@ struct vcache_frontend { unsigned draw_count; unsigned fetch_count; - pt_elt_func elt_func; - const void *elt_ptr; - struct draw_pt_middle_end *middle; unsigned input_prim; @@ -66,17 +63,6 @@ struct vcache_frontend { static void vcache_flush( struct vcache_frontend *vcache ) { -#if 0 - /* Should always be true if output_prim == input_prim, otherwise - * not so much... - */ - unsigned i; - for (i = 0; i < vcache->draw_count; i++) { - assert( vcache->fetch_elts[vcache->draw_elts[i]] == - vcache->elt_func(vcache->elt_ptr, i) ); - } -#endif - if (vcache->draw_count) { vcache->middle->run( vcache->middle, vcache->fetch_elts, @@ -115,26 +101,73 @@ static void vcache_elt( struct vcache_frontend *vcache, vcache->draw_elts[vcache->draw_count++] = vcache->out[idx]; } + +static unsigned add_edgeflag( struct vcache_frontend *vcache, + unsigned idx, + unsigned mask ) +{ + if (mask && draw_get_edgeflag(vcache->draw, idx)) + return idx | DRAW_PT_EDGEFLAG; + else + return idx; +} + + +static unsigned add_reset_stipple( unsigned idx, + unsigned reset ) +{ + if (reset) + return idx | DRAW_PT_RESET_STIPPLE; + else + return idx; +} + static void vcache_triangle( struct vcache_frontend *vcache, unsigned i0, unsigned i1, unsigned i2 ) { - /* TODO: encode edgeflags in draw_elts */ + vcache_elt(vcache, i0 | DRAW_PT_EDGEFLAG | DRAW_PT_RESET_STIPPLE); + vcache_elt(vcache, i1 | DRAW_PT_EDGEFLAG); + vcache_elt(vcache, i2 | DRAW_PT_EDGEFLAG); + vcache_check_flush(vcache); +} + + +static void vcache_ef_triangle( struct vcache_frontend *vcache, + boolean reset_stipple, + unsigned ef_mask, + unsigned i0, + unsigned i1, + unsigned i2 ) +{ + i0 = add_edgeflag( vcache, i0, (ef_mask >> 0) & 1 ); + i1 = add_edgeflag( vcache, i1, (ef_mask >> 1) & 1 ); + i2 = add_edgeflag( vcache, i2, (ef_mask >> 2) & 1 ); + + i0 = add_reset_stipple( i0, reset_stipple ); + vcache_elt(vcache, i0); vcache_elt(vcache, i1); vcache_elt(vcache, i2); vcache_check_flush(vcache); + + if (0) debug_printf("emit tri ef: %d %d %d\n", + !!(i0 & DRAW_PT_EDGEFLAG), + !!(i1 & DRAW_PT_EDGEFLAG), + !!(i2 & DRAW_PT_EDGEFLAG)); + } + static void vcache_line( struct vcache_frontend *vcache, - boolean reset, + boolean reset_stipple, unsigned i0, unsigned i1 ) { - /* TODO: encode reset-line-stipple in draw_elts */ - (void) reset; + i0 = add_reset_stipple( i0, reset_stipple ); + vcache_elt(vcache, i0); vcache_elt(vcache, i1); vcache_check_flush(vcache); @@ -158,39 +191,43 @@ static void vcache_quad( struct vcache_frontend *vcache, vcache_triangle( vcache, i1, i2, i3 ); } +static void vcache_ef_quad( struct vcache_frontend *vcache, + unsigned i0, + unsigned i1, + unsigned i2, + unsigned i3 ) +{ + const unsigned omitEdge2 = ~(1 << 1); + const unsigned omitEdge3 = ~(1 << 2); + vcache_ef_triangle( vcache, 1, omitEdge2, i0, i1, i3 ); + vcache_ef_triangle( vcache, 0, omitEdge3, i1, i2, i3 ); +} + -static unsigned reduced_prim[PIPE_PRIM_POLYGON + 1] = { - PIPE_PRIM_POINTS, - PIPE_PRIM_LINES, - PIPE_PRIM_LINES, - PIPE_PRIM_LINES, - PIPE_PRIM_TRIANGLES, - PIPE_PRIM_TRIANGLES, - PIPE_PRIM_TRIANGLES, - PIPE_PRIM_TRIANGLES, - PIPE_PRIM_TRIANGLES, - PIPE_PRIM_TRIANGLES -}; -static void vcache_run_pv2( struct draw_pt_front_end *frontend, - pt_elt_func get_elt, - const void *elts, - unsigned count ) +static void vcache_run( struct draw_pt_front_end *frontend, + pt_elt_func get_elt, + const void *elts, + unsigned count ) { struct vcache_frontend *vcache = (struct vcache_frontend *)frontend; + struct draw_context *draw = vcache->draw; + + boolean unfilled = (draw->rasterizer->fill_cw != PIPE_POLYGON_MODE_FILL || + draw->rasterizer->fill_ccw != PIPE_POLYGON_MODE_FILL); + + boolean flatfirst = (draw->rasterizer->flatshade && + draw->rasterizer->flatshade_first); unsigned i; - - /* These are for validation only: - */ - vcache->elt_func = get_elt; - vcache->elt_ptr = elts; + +// debug_printf("%s (%d) %d/%d\n", __FUNCTION__, draw->prim, start, count ); switch (vcache->input_prim) { case PIPE_PRIM_POINTS: for (i = 0; i < count; i ++) { - vcache_point( vcache, - get_elt(elts, i) ); + vcache_point( vcache, + get_elt(elts, i + 0) ); } break; @@ -205,17 +242,17 @@ static void vcache_run_pv2( struct draw_pt_front_end *frontend, case PIPE_PRIM_LINE_LOOP: if (count >= 2) { - for (i = 1; i < count; i++) { - vcache_line( vcache, + for (i = 1; i < count; i++) { + vcache_line( vcache, i == 1, /* XXX: only if vb not split */ get_elt(elts, i - 1), - get_elt(elts, i) ); - } + get_elt(elts, i )); + } - vcache_line( vcache, + vcache_line( vcache, 0, get_elt(elts, count - 1), - get_elt(elts, 0) ); + get_elt(elts, 0 )); } break; @@ -224,72 +261,163 @@ static void vcache_run_pv2( struct draw_pt_front_end *frontend, vcache_line( vcache, i == 1, get_elt(elts, i - 1), - get_elt(elts, i) ); + get_elt(elts, i )); } break; case PIPE_PRIM_TRIANGLES: - for (i = 0; i+2 < count; i += 3) { - vcache_triangle( vcache, - get_elt(elts, i + 0), - get_elt(elts, i + 1), - get_elt(elts, i + 2) ); + if (unfilled) { + for (i = 0; i+2 < count; i += 3) { + vcache_ef_triangle( vcache, + 1, + ~0, + get_elt(elts, i + 0), + get_elt(elts, i + 1), + get_elt(elts, i + 2 )); + } + } + else { + for (i = 0; i+2 < count; i += 3) { + vcache_triangle( vcache, + get_elt(elts, i + 0), + get_elt(elts, i + 1), + get_elt(elts, i + 2 )); + } } break; case PIPE_PRIM_TRIANGLE_STRIP: - for (i = 0; i+2 < count; i++) { - if (i & 1) { - vcache_triangle( vcache, - get_elt(elts, i + 1), - get_elt(elts, i + 0), - get_elt(elts, i + 2) ); + if (flatfirst) { + for (i = 0; i+2 < count; i++) { + if (i & 1) { + vcache_triangle( vcache, + get_elt(elts, i + 0), + get_elt(elts, i + 2), + get_elt(elts, i + 1 )); + } + else { + vcache_triangle( vcache, + get_elt(elts, i + 0), + get_elt(elts, i + 1), + get_elt(elts, i + 2 )); + } } - else { - vcache_triangle( vcache, - get_elt(elts, i + 0), - get_elt(elts, i + 1), - get_elt(elts, i + 2) ); + } + else { + for (i = 0; i+2 < count; i++) { + if (i & 1) { + vcache_triangle( vcache, + get_elt(elts, i + 1), + get_elt(elts, i + 0), + get_elt(elts, i + 2 )); + } + else { + vcache_triangle( vcache, + get_elt(elts, i + 0), + get_elt(elts, i + 1), + get_elt(elts, i + 2 )); + } } } break; case PIPE_PRIM_TRIANGLE_FAN: - for (i = 0; i+2 < count; i++) { - vcache_triangle( vcache, - get_elt(elts, 0), - get_elt(elts, i + 1), - get_elt(elts, i + 2) ); + if (count >= 3) { + if (flatfirst) { + for (i = 0; i+2 < count; i++) { + vcache_triangle( vcache, + get_elt(elts, i + 1), + get_elt(elts, i + 2), + get_elt(elts, 0 )); + } + } + else { + for (i = 0; i+2 < count; i++) { + vcache_triangle( vcache, + get_elt(elts, 0), + get_elt(elts, i + 1), + get_elt(elts, i + 2 )); + } + } } break; case PIPE_PRIM_QUADS: - for (i = 0; i+3 < count; i += 4) { - vcache_quad( vcache, - get_elt(elts, i + 0), - get_elt(elts, i + 1), - get_elt(elts, i + 2), - get_elt(elts, i + 3)); + if (unfilled) { + for (i = 0; i+3 < count; i += 4) { + vcache_ef_quad( vcache, + get_elt(elts, i + 0), + get_elt(elts, i + 1), + get_elt(elts, i + 2), + get_elt(elts, i + 3)); + } + } + else { + for (i = 0; i+3 < count; i += 4) { + vcache_quad( vcache, + get_elt(elts, i + 0), + get_elt(elts, i + 1), + get_elt(elts, i + 2), + get_elt(elts, i + 3)); + } } break; case PIPE_PRIM_QUAD_STRIP: - for (i = 0; i+3 < count; i += 2) { - vcache_quad( vcache, - get_elt(elts, i + 2), - get_elt(elts, i + 0), - get_elt(elts, i + 1), - get_elt(elts, i + 3)); + if (unfilled) { + for (i = 0; i+3 < count; i += 2) { + vcache_ef_quad( vcache, + get_elt(elts, i + 2), + get_elt(elts, i + 0), + get_elt(elts, i + 1), + get_elt(elts, i + 3)); + } + } + else { + for (i = 0; i+3 < count; i += 2) { + vcache_quad( vcache, + get_elt(elts, i + 2), + get_elt(elts, i + 0), + get_elt(elts, i + 1), + get_elt(elts, i + 3)); + } } break; case PIPE_PRIM_POLYGON: - for (i = 0; i+2 < count; i++) { - vcache_triangle( vcache, - get_elt(elts, i + 1), - get_elt(elts, i + 2), - get_elt(elts, 0)); + if (unfilled) { + /* These bitflags look a little odd because we submit the + * vertices as (1,2,0) to satisfy flatshade requirements. + */ + const unsigned edge_first = (1<<2); + const unsigned edge_middle = (1<<0); + const unsigned edge_last = (1<<1); + + for (i = 0; i+2 < count; i++) { + unsigned ef_mask = edge_middle; + + if (i == 0) + ef_mask |= edge_first; + + if (i + 3 == count) + ef_mask |= edge_last; + + vcache_ef_triangle( vcache, + i == 0, + ef_mask, + get_elt(elts, i + 1), + get_elt(elts, i + 2), + get_elt(elts, 0)); + } + } + else { + for (i = 0; i+2 < count; i++) { + vcache_triangle( vcache, + get_elt(elts, i + 1), + get_elt(elts, i + 2), + get_elt(elts, 0)); + } } break; @@ -302,88 +430,21 @@ static void vcache_run_pv2( struct draw_pt_front_end *frontend, } -static void vcache_run_pv0( struct draw_pt_front_end *frontend, - pt_elt_func get_elt, - const void *elts, - unsigned count ) -{ - struct vcache_frontend *vcache = (struct vcache_frontend *)frontend; - unsigned i; - - /* These are for validation only: - */ - vcache->elt_func = get_elt; - vcache->elt_ptr = elts; - - switch (vcache->input_prim) { - case PIPE_PRIM_POINTS: - for (i = 0; i < count; i ++) { - vcache_point( vcache, - get_elt(elts, i) ); - } - break; - - case PIPE_PRIM_LINES: - for (i = 0; i+1 < count; i += 2) { - vcache_line( vcache, - TRUE, - get_elt(elts, i + 0), - get_elt(elts, i + 1)); - } - break; - - case PIPE_PRIM_LINE_STRIP: - for (i = 1; i < count; i++) { - vcache_line( vcache, - i == 1, - get_elt(elts, i - 1), - get_elt(elts, i) ); - } - break; - - case PIPE_PRIM_TRIANGLES: - for (i = 0; i+2 < count; i += 3) { - vcache_triangle( vcache, - get_elt(elts, i + 0), - get_elt(elts, i + 1), - get_elt(elts, i + 2) ); - } - break; - - case PIPE_PRIM_TRIANGLE_STRIP: - for (i = 0; i+2 < count; i++) { - if (i & 1) { - vcache_triangle( vcache, - get_elt(elts, i + 0), - get_elt(elts, i + 2), - get_elt(elts, i + 1) ); - } - else { - vcache_triangle( vcache, - get_elt(elts, i + 0), - get_elt(elts, i + 1), - get_elt(elts, i + 2) ); - } - } - break; - case PIPE_PRIM_TRIANGLE_FAN: - for (i = 0; i+2 < count; i++) { - vcache_triangle( vcache, - get_elt(elts, i + 1), - get_elt(elts, i + 2), - get_elt(elts, 0) ); - } - break; +static unsigned reduced_prim[PIPE_PRIM_POLYGON + 1] = { + PIPE_PRIM_POINTS, + PIPE_PRIM_LINES, + PIPE_PRIM_LINES, + PIPE_PRIM_LINES, + PIPE_PRIM_TRIANGLES, + PIPE_PRIM_TRIANGLES, + PIPE_PRIM_TRIANGLES, + PIPE_PRIM_TRIANGLES, + PIPE_PRIM_TRIANGLES, + PIPE_PRIM_TRIANGLES +}; - default: - assert(0); - break; - } - - vcache_flush( vcache ); -} static void vcache_prepare( struct draw_pt_front_end *frontend, unsigned prim, @@ -391,11 +452,14 @@ static void vcache_prepare( struct draw_pt_front_end *frontend, { struct vcache_frontend *vcache = (struct vcache_frontend *)frontend; +/* if (vcache->draw->rasterizer->flatshade_first) vcache->base.run = vcache_run_pv0; else vcache->base.run = vcache_run_pv2; - +*/ + + vcache->base.run = vcache_run; vcache->input_prim = prim; vcache->output_prim = reduced_prim[prim];