{
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;
}
draw_pipeline_flush( draw, flags );
+ draw_pt_flush( draw, flags );
+
draw->flushing = FALSE;
}
}
struct vbuf_render;
struct tgsi_exec_machine;
struct tgsi_sampler;
+struct draw_pt_front_end;
/**
/* 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;
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 );
/*******************************************************************************
* - 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)
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 )
{
}
-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;
+ }
}
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;