diff options
-rw-r--r-- | src/gallium/auxiliary/draw/draw_context.c | 6 | ||||
-rw-r--r-- | src/gallium/auxiliary/draw/draw_private.h | 8 | ||||
-rw-r--r-- | src/gallium/auxiliary/draw/draw_pt.c | 49 | ||||
-rw-r--r-- | src/gallium/auxiliary/draw/draw_pt.h | 2 | ||||
-rw-r--r-- | src/gallium/auxiliary/draw/draw_pt_vsplit.c | 11 |
5 files changed, 66 insertions, 10 deletions
diff --git a/src/gallium/auxiliary/draw/draw_context.c b/src/gallium/auxiliary/draw/draw_context.c index 4ce44455084..3c0b1aa39c9 100644 --- a/src/gallium/auxiliary/draw/draw_context.c +++ b/src/gallium/auxiliary/draw/draw_context.c @@ -355,6 +355,10 @@ draw_set_vertex_elements(struct draw_context *draw, { assert(count <= PIPE_MAX_ATTRIBS); + /* We could improve this by only flushing the frontend and the fetch part + * of the middle. This would avoid recalculating the emit keys.*/ + draw_do_flush( draw, DRAW_FLUSH_STATE_CHANGE ); + memcpy(draw->pt.vertex_element, elements, count * sizeof(elements[0])); draw->pt.nr_vertex_elements = count; } @@ -654,6 +658,8 @@ void draw_do_flush( struct draw_context *draw, unsigned flags ) draw_pipeline_flush( draw, flags ); + draw_pt_flush( draw, flags ); + draw->flushing = FALSE; } } diff --git a/src/gallium/auxiliary/draw/draw_private.h b/src/gallium/auxiliary/draw/draw_private.h index 1a0286de891..c3eca973e92 100644 --- a/src/gallium/auxiliary/draw/draw_private.h +++ b/src/gallium/auxiliary/draw/draw_private.h @@ -63,6 +63,7 @@ struct draw_stage; struct vbuf_render; struct tgsi_exec_machine; struct tgsi_sampler; +struct draw_pt_front_end; /** @@ -137,6 +138,12 @@ struct draw_context /* Support prototype passthrough path: */ struct { + /* Current active frontend */ + struct draw_pt_front_end *frontend; + unsigned prim; + unsigned opt; + unsigned eltSize; /* saved eltSize for flushing */ + struct { struct draw_pt_middle_end *fetch_emit; struct draw_pt_middle_end *fetch_shade_emit; @@ -391,6 +398,7 @@ void draw_remove_extra_vertex_attribs(struct draw_context *draw); boolean draw_pt_init( struct draw_context *draw ); void draw_pt_destroy( struct draw_context *draw ); void draw_pt_reset_vertex_ids( struct draw_context *draw ); +void draw_pt_flush( struct draw_context *draw, unsigned flags ); /******************************************************************************* diff --git a/src/gallium/auxiliary/draw/draw_pt.c b/src/gallium/auxiliary/draw/draw_pt.c index 9a017fd0567..025d53989e4 100644 --- a/src/gallium/auxiliary/draw/draw_pt.c +++ b/src/gallium/auxiliary/draw/draw_pt.c @@ -52,7 +52,7 @@ DEBUG_GET_ONCE_BOOL_OPTION(draw_no_fse, "DRAW_NO_FSE", FALSE) * - backend -- the vbuf_render provided by the driver. */ static boolean -draw_pt_arrays(struct draw_context *draw, +draw_pt_arrays(struct draw_context *draw, unsigned prim, unsigned start, unsigned count) @@ -106,17 +106,56 @@ draw_pt_arrays(struct draw_context *draw, middle = draw->pt.middle.general; } - frontend = draw->pt.front.vsplit; + frontend = draw->pt.frontend; + + if (frontend ) { + if (draw->pt.prim != prim || draw->pt.opt != opt) { + /* In certain conditions switching primitives requires us to flush + * and validate the different stages. One example is when smooth + * lines are active but first drawn with triangles and then with + * lines. + */ + draw_do_flush( draw, DRAW_FLUSH_STATE_CHANGE ); + frontend = NULL; + } else if (draw->pt.eltSize != draw->pt.user.eltSize) { + /* Flush draw state if eltSize changed. + * This could be improved so only the frontend is flushed since it + * converts all indices to ushorts and the fetch part of the middle + * always perpares both linear and indexed. + */ + frontend->flush( frontend, DRAW_FLUSH_STATE_CHANGE ); + frontend = NULL; + } + } - frontend->prepare( frontend, prim, middle, opt ); + if (!frontend) { + frontend = draw->pt.front.vsplit; - frontend->run(frontend, start, count); + frontend->prepare( frontend, prim, middle, opt ); - frontend->finish( frontend ); + draw->pt.frontend = frontend; + draw->pt.eltSize = draw->pt.user.eltSize; + draw->pt.prim = prim; + draw->pt.opt = opt; + } + + frontend->run( frontend, start, count ); return TRUE; } +void draw_pt_flush( struct draw_context *draw, unsigned flags ) +{ + if (draw->pt.frontend) { + draw->pt.frontend->flush( draw->pt.frontend, flags ); + + /* don't prepare if we only are flushing the backend */ + if (!(flags & DRAW_FLUSH_BACKEND)) + draw->pt.frontend = NULL; + } +} + + boolean draw_pt_init( struct draw_context *draw ) { diff --git a/src/gallium/auxiliary/draw/draw_pt.h b/src/gallium/auxiliary/draw/draw_pt.h index 9a45845521a..2c2efdc1c59 100644 --- a/src/gallium/auxiliary/draw/draw_pt.h +++ b/src/gallium/auxiliary/draw/draw_pt.h @@ -73,7 +73,7 @@ struct draw_pt_front_end { unsigned start, unsigned count ); - void (*finish)( struct draw_pt_front_end * ); + void (*flush)( struct draw_pt_front_end *, unsigned flags ); void (*destroy)( struct draw_pt_front_end * ); }; diff --git a/src/gallium/auxiliary/draw/draw_pt_vsplit.c b/src/gallium/auxiliary/draw/draw_pt_vsplit.c index c19dcd9e1f7..0fed057efbe 100644 --- a/src/gallium/auxiliary/draw/draw_pt_vsplit.c +++ b/src/gallium/auxiliary/draw/draw_pt_vsplit.c @@ -178,11 +178,14 @@ static void vsplit_prepare(struct draw_pt_front_end *frontend, } -static void vsplit_finish(struct draw_pt_front_end *frontend) +static void vsplit_flush(struct draw_pt_front_end *frontend, unsigned flags) { struct vsplit_frontend *vsplit = (struct vsplit_frontend *) frontend; - vsplit->middle->finish(vsplit->middle); - vsplit->middle = NULL; + + if (!(flags & DRAW_FLUSH_BACKEND)) { + vsplit->middle->finish(vsplit->middle); + vsplit->middle = NULL; + } } @@ -202,7 +205,7 @@ struct draw_pt_front_end *draw_pt_vsplit(struct draw_context *draw) vsplit->base.prepare = vsplit_prepare; vsplit->base.run = NULL; - vsplit->base.finish = vsplit_finish; + vsplit->base.flush = vsplit_flush; vsplit->base.destroy = vsplit_destroy; vsplit->draw = draw; |