summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/gallium/auxiliary/draw/draw_context.c6
-rw-r--r--src/gallium/auxiliary/draw/draw_private.h8
-rw-r--r--src/gallium/auxiliary/draw/draw_pt.c49
-rw-r--r--src/gallium/auxiliary/draw/draw_pt.h2
-rw-r--r--src/gallium/auxiliary/draw/draw_pt_vsplit.c11
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;