X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;f=src%2Fgallium%2Fauxiliary%2Fdraw%2Fdraw_pipe_unfilled.c;h=7a88ce0f6d70f0b4a71120f26cd2248f663601e1;hb=76feef0823df75a36f264f48ec843dd863fd5b89;hp=68835fd1a592ac6eb2eb25e208b588467b36d2fd;hpb=3059ceb7f8128f00846f261f1927f5ec72d5dd15;p=mesa.git diff --git a/src/gallium/auxiliary/draw/draw_pipe_unfilled.c b/src/gallium/auxiliary/draw/draw_pipe_unfilled.c index 68835fd1a59..7a88ce0f6d7 100644 --- a/src/gallium/auxiliary/draw/draw_pipe_unfilled.c +++ b/src/gallium/auxiliary/draw/draw_pipe_unfilled.c @@ -37,6 +37,7 @@ #include "pipe/p_defines.h" #include "draw_private.h" #include "draw_pipe.h" +#include "draw_fs.h" struct unfilled_stage { @@ -47,6 +48,8 @@ struct unfilled_stage { * and PIPE_POLYGON_MODE_POINT, */ unsigned mode[2]; + + int face_slot; }; @@ -55,8 +58,33 @@ static INLINE struct unfilled_stage *unfilled_stage( struct draw_stage *stage ) return (struct unfilled_stage *)stage; } +static void +inject_front_face_info(struct draw_stage *stage, + struct prim_header *header) +{ + struct unfilled_stage *unfilled = unfilled_stage(stage); + unsigned ccw = header->det < 0.0; + boolean is_front_face = ( + (stage->draw->rasterizer->front_ccw && ccw) || + (!stage->draw->rasterizer->front_ccw && !ccw)); + int slot = unfilled->face_slot; + unsigned i; + + /* In case the backend doesn't care about it */ + if (slot < 0) { + return; + } + + for (i = 0; i < 3; ++i) { + struct vertex_header *v = header->v[i]; + v->data[slot][0] = is_front_face; + v->data[slot][1] = is_front_face; + v->data[slot][2] = is_front_face; + v->data[slot][3] = is_front_face; + } +} - + static void point( struct draw_stage *stage, struct vertex_header *v0 ) { @@ -83,6 +111,8 @@ static void points( struct draw_stage *stage, struct vertex_header *v1 = header->v[1]; struct vertex_header *v2 = header->v[2]; + inject_front_face_info(stage, header); + if ((header->flags & DRAW_PIPE_EDGE_FLAG_0) && v0->edgeflag) point( stage, v0 ); if ((header->flags & DRAW_PIPE_EDGE_FLAG_1) && v1->edgeflag) point( stage, v1 ); if ((header->flags & DRAW_PIPE_EDGE_FLAG_2) && v2->edgeflag) point( stage, v2 ); @@ -99,12 +129,31 @@ static void lines( struct draw_stage *stage, if (header->flags & DRAW_PIPE_RESET_STIPPLE) stage->next->reset_stipple_counter( stage->next ); + inject_front_face_info(stage, header); + if ((header->flags & DRAW_PIPE_EDGE_FLAG_2) && v2->edgeflag) line( stage, v2, v0 ); if ((header->flags & DRAW_PIPE_EDGE_FLAG_0) && v0->edgeflag) line( stage, v0, v1 ); if ((header->flags & DRAW_PIPE_EDGE_FLAG_1) && v1->edgeflag) line( stage, v1, v2 ); } +/** For debugging */ +static void +print_header_flags(unsigned flags) +{ + debug_printf("header->flags = "); + if (flags & DRAW_PIPE_RESET_STIPPLE) + debug_printf("RESET_STIPPLE "); + if (flags & DRAW_PIPE_EDGE_FLAG_0) + debug_printf("EDGE_FLAG_0 "); + if (flags & DRAW_PIPE_EDGE_FLAG_1) + debug_printf("EDGE_FLAG_1 "); + if (flags & DRAW_PIPE_EDGE_FLAG_2) + debug_printf("EDGE_FLAG_2 "); + debug_printf("\n"); +} + + /* Unfilled tri: * * Note edgeflags in the vertex struct is not sufficient as we will @@ -117,8 +166,12 @@ static void unfilled_tri( struct draw_stage *stage, struct prim_header *header ) { struct unfilled_stage *unfilled = unfilled_stage(stage); - unsigned mode = unfilled->mode[header->det >= 0.0]; + unsigned cw = header->det >= 0.0; + unsigned mode = unfilled->mode[cw]; + if (0) + print_header_flags(header->flags); + switch (mode) { case PIPE_POLYGON_MODE_FILL: stage->next->tri( stage->next, header ); @@ -139,9 +192,10 @@ static void unfilled_first_tri( struct draw_stage *stage, struct prim_header *header ) { struct unfilled_stage *unfilled = unfilled_stage(stage); + const struct pipe_rasterizer_state *rast = stage->draw->rasterizer; - unfilled->mode[0] = stage->draw->rasterizer->fill_ccw; /* front */ - unfilled->mode[1] = stage->draw->rasterizer->fill_cw; /* back */ + unfilled->mode[0] = rast->front_ccw ? rast->fill_front : rast->fill_back; + unfilled->mode[1] = rast->front_ccw ? rast->fill_back : rast->fill_front; stage->tri = unfilled_tri; stage->tri( stage, header ); @@ -170,6 +224,29 @@ static void unfilled_destroy( struct draw_stage *stage ) FREE( stage ); } +/* + * Try to allocate an output slot which we can use + * to preserve the front face information. + */ +void +draw_unfilled_prepare_outputs( struct draw_context *draw, + struct draw_stage *stage ) +{ + struct unfilled_stage *unfilled = unfilled_stage(stage); + const struct pipe_rasterizer_state *rast = draw ? draw->rasterizer : 0; + boolean is_unfilled = (rast && + (rast->fill_front != PIPE_POLYGON_MODE_FILL || + rast->fill_back != PIPE_POLYGON_MODE_FILL)); + const struct draw_fragment_shader *fs = draw->fs.fragment_shader; + + if (is_unfilled && fs && fs->info.uses_frontface) { + unfilled->face_slot = draw_alloc_extra_vertex_attrib( + stage->draw, TGSI_SEMANTIC_FACE, 0); + } else { + unfilled->face_slot = -1; + } +} + /** * Create unfilled triangle stage. @@ -180,10 +257,8 @@ struct draw_stage *draw_unfilled_stage( struct draw_context *draw ) if (unfilled == NULL) goto fail; - if (!draw_alloc_temp_verts( &unfilled->stage, 0 )) - goto fail; - unfilled->stage.draw = draw; + unfilled->stage.name = "unfilled"; unfilled->stage.next = NULL; unfilled->stage.tmp = NULL; unfilled->stage.point = draw_pipe_passthrough_point; @@ -193,6 +268,11 @@ struct draw_stage *draw_unfilled_stage( struct draw_context *draw ) unfilled->stage.reset_stipple_counter = unfilled_reset_stipple_counter; unfilled->stage.destroy = unfilled_destroy; + unfilled->face_slot = -1; + + if (!draw_alloc_temp_verts( &unfilled->stage, 0 )) + goto fail; + return &unfilled->stage; fail: