#include "draw/draw_pt.h"
-/* XXX: Shouldn't those two functions below use the '>' operator???
- */
-
-static boolean too_many_verts( struct draw_context *draw,
- unsigned verts )
-{
- return verts < 1024;
-}
-static boolean too_many_elts( struct draw_context *draw,
- unsigned elts )
-{
- return elts < (16 * 1024);
-}
-
-boolean
+/* Overall we split things into:
+ * - frontend -- prepare fetch_elts, draw_elts - eg vcache
+ * - middle -- fetch, shade, cliptest, viewport
+ * - pipeline -- the prim pipeline: clipping, wide lines, etc
+ * - backend -- the vbuf_render provided by the driver.
+ */
+static boolean
draw_pt_arrays(struct draw_context *draw,
unsigned prim,
unsigned start,
unsigned count)
{
- const boolean pipeline = draw_need_pipeline(draw, prim);
- const boolean cliptest = !draw->rasterizer->bypass_clipping;
- const boolean shading = !draw->rasterizer->bypass_vs;
struct draw_pt_front_end *frontend = NULL;
struct draw_pt_middle_end *middle = NULL;
+ unsigned opt = 0;
-
- /* Overall we do:
- * - frontend -- prepare fetch_elts, draw_elts - eg vcache
- * - middle -- fetch, shade, cliptest, viewport
- * - pipeline -- the prim pipeline: clipping, wide lines, etc
- * - backend -- the vbuf_render provided by the driver.
- */
-
-
-#if 0
- if (!cliptest && !pipeline && !shading) {
- /* This is the 'passthrough' path:
- */
- /* Fetch user verts, emit hw verts:
- */
- middle = draw->pt.middle.fetch_emit;
- }
- else if (!cliptest && !pipeline) {
- /* Fetch user verts, run vertex shader, emit hw verts:
- */
- middle = draw->pt.middle.fetch_shade_emit;
+ if (!draw->render) {
+ opt |= PT_PIPELINE;
}
- else if (!pipeline) {
- /* Even though !pipeline, we have to run it to get clipping. We
- * do know that the pipeline is just the clipping operation, but
- * that probably doesn't help much.
- *
- * This is going to be the most important path for a lot of
- * swtnl cards.
- */
- /* Fetch user verts,
- * run vertex shader,
- * cliptest and viewport trasform
- * if no clipped vertices,
- * emit hw verts
- * else
- * run pipline
- */
- middle = draw->pt.middle.fetch_shade_cliptest_pipeline_or_emit;
+
+ if (draw_need_pipeline(draw, prim)) {
+ opt |= PT_PIPELINE;
}
- else if (!cliptest) {
- /* Fetch user verts, run vertex shader, run pipeline:
- */
- middle = draw->pt.middle.fetch_shade_pipeline;
+
+ if (!draw->rasterizer->bypass_clipping) {
+ opt |= PT_CLIPTEST;
}
- else {
- /* This is what we're currently always doing:
- */
- /* Fetch user verts, run vertex shader, cliptest, run pipeline:
- */
- middle = draw->pt.middle.fetch_shade_cliptest_pipeline;
+
+ if (!draw->rasterizer->bypass_vs) {
+ opt |= PT_SHADE;
}
-#else
- if (cliptest || pipeline || shading)
- return FALSE;
- middle = draw->pt.middle.fetch_emit;
-#endif
+ if (opt)
+ middle = draw->pt.middle.general;
+ else
+ middle = draw->pt.middle.fetch_emit;
- /* If !pipeline, need to make sure we respect the driver's limited
- * capabilites to receive blocks of vertex data and elements.
+ /* May create a short-circuited version of this for small primitives:
*/
-#if 0
- if (!pipeline) {
- unsigned vertex_mode = passthrough;
- unsigned nr_verts = count_vertices( draw, start, count );
- unsigned hw_prim = prim;
-
- if (is_elts(draw)) {
- frontend = draw->pt.front.vcache;
- hw_prim = reduced_prim(prim);
- }
-
- if (too_many_verts(nr_verts)) {
- /* if (is_verts(draw) && can_split(prim)) {
- draw = draw_arrays_split;
- }
- else */ {
- frontend = draw->pt.front.vcache;
- hw_prim = reduced_prim(prim);
- }
- }
-
- if (too_many_elts(count)) {
-
- /* if (is_elts(draw) && can_split(prim)) {
- draw = draw_elts_split;
- }
- else */ {
- frontend = draw->pt.front.vcache;
- hw_prim = reduced_prim(prim);
- }
- }
-
- if (!good_prim(hw_prim)) {
- draw = draw->pt.front.vcache;
- }
- }
-#else
frontend = draw->pt.front.vcache;
-#endif
-
- /* XXX: need to flush to get prim_vbuf.c to release its allocation??
- */
- draw_do_flush( draw, DRAW_FLUSH_BACKEND );
- frontend->prepare( frontend, middle );
+ frontend->prepare( frontend, prim, middle, opt );
frontend->run( frontend,
- prim,
draw_pt_elt_func( draw ),
draw_pt_elt_ptr( draw, start ),
count );
boolean draw_pt_init( struct draw_context *draw )
{
+ draw->pt.front.vcache = draw_pt_vcache( draw );
+ if (!draw->pt.front.vcache)
+ return FALSE;
+
draw->pt.middle.fetch_emit = draw_pt_fetch_emit( draw );
if (!draw->pt.middle.fetch_emit)
return FALSE;
- draw->pt.front.vcache = draw_pt_vcache( draw );
- if (!draw->pt.front.vcache)
+ draw->pt.middle.general = draw_pt_fetch_pipeline_or_emit( draw );
+ if (!draw->pt.middle.general)
return FALSE;
return TRUE;
void draw_pt_destroy( struct draw_context *draw )
{
+ if (draw->pt.middle.general) {
+ draw->pt.middle.general->destroy( draw->pt.middle.general );
+ draw->pt.middle.general = NULL;
+ }
+
if (draw->pt.middle.fetch_emit) {
draw->pt.middle.fetch_emit->destroy( draw->pt.middle.fetch_emit );
draw->pt.middle.fetch_emit = NULL;
draw->pt.front.vcache = NULL;
}
}
+
+
+
+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
+};
+
+
+/**
+ * Draw vertex arrays
+ * This is the main entrypoint into the drawing module.
+ * \param prim one of PIPE_PRIM_x
+ * \param start index of first vertex to draw
+ * \param count number of vertices to draw
+ */
+void
+draw_arrays(struct draw_context *draw, unsigned prim,
+ unsigned start, unsigned count)
+{
+ if (reduced_prim[prim] != draw->reduced_prim) {
+ draw_do_flush( draw, DRAW_FLUSH_STATE_CHANGE );
+ draw->reduced_prim = reduced_prim[prim];
+ }
+
+ /* drawing done here: */
+ draw_pt_arrays(draw, prim, start, count);
+}
+
+boolean draw_pt_get_edgeflag( struct draw_context *draw,
+ unsigned idx )
+{
+ if (draw->pt.user.edgeflag)
+ return (draw->pt.user.edgeflag[idx/32] & (1 << (idx%32))) != 0;
+ else
+ return 1;
+}