summaryrefslogtreecommitdiff
path: root/src/gallium/auxiliary
diff options
context:
space:
mode:
Diffstat (limited to 'src/gallium/auxiliary')
-rw-r--r--src/gallium/auxiliary/draw/Makefile3
-rw-r--r--src/gallium/auxiliary/draw/draw_pipe.c65
-rw-r--r--src/gallium/auxiliary/draw/draw_pipe_vbuf.c3
-rw-r--r--src/gallium/auxiliary/draw/draw_private.h9
-rw-r--r--src/gallium/auxiliary/draw/draw_pt.c60
-rw-r--r--src/gallium/auxiliary/draw/draw_pt.h26
-rw-r--r--src/gallium/auxiliary/draw/draw_pt_decompose.h153
-rw-r--r--src/gallium/auxiliary/draw/draw_pt_emit.c47
-rw-r--r--src/gallium/auxiliary/draw/draw_pt_fetch.c39
-rw-r--r--src/gallium/auxiliary/draw/draw_pt_fetch_emit.c65
-rw-r--r--src/gallium/auxiliary/draw/draw_pt_fetch_shade_emit.c677
-rw-r--r--src/gallium/auxiliary/draw/draw_pt_fetch_shade_pipeline.c84
-rw-r--r--src/gallium/auxiliary/draw/draw_pt_middle_fse.c705
-rw-r--r--src/gallium/auxiliary/draw/draw_pt_util.c103
-rw-r--r--src/gallium/auxiliary/draw/draw_pt_varray.c159
-rw-r--r--src/gallium/auxiliary/draw/draw_pt_varray_tmp.h193
-rw-r--r--src/gallium/auxiliary/draw/draw_pt_varray_tmp_linear.h94
-rw-r--r--src/gallium/auxiliary/draw/draw_pt_vcache.c130
18 files changed, 2357 insertions, 258 deletions
diff --git a/src/gallium/auxiliary/draw/Makefile b/src/gallium/auxiliary/draw/Makefile
index da7eded21f..67d78bdbbd 100644
--- a/src/gallium/auxiliary/draw/Makefile
+++ b/src/gallium/auxiliary/draw/Makefile
@@ -26,8 +26,11 @@ C_SOURCES = \
draw_pt_emit.c \
draw_pt_fetch.c \
draw_pt_fetch_emit.c \
+ draw_pt_fetch_shade_emit.c \
+ draw_pt_middle_fse.c \
draw_pt_fetch_shade_pipeline.c \
draw_pt_post_vs.c \
+ draw_pt_util.c \
draw_pt_varray.c \
draw_pt_vcache.c \
draw_vertex.c \
diff --git a/src/gallium/auxiliary/draw/draw_pipe.c b/src/gallium/auxiliary/draw/draw_pipe.c
index 46afb0f41f..1d26706dee 100644
--- a/src/gallium/auxiliary/draw/draw_pipe.c
+++ b/src/gallium/auxiliary/draw/draw_pipe.c
@@ -212,6 +212,71 @@ void draw_pipeline_run( struct draw_context *draw,
draw->pipeline.vertex_count = 0;
}
+#define QUAD(i0,i1,i2,i3) \
+ do_triangle( draw, \
+ ( DRAW_PIPE_RESET_STIPPLE | \
+ DRAW_PIPE_EDGE_FLAG_0 | \
+ DRAW_PIPE_EDGE_FLAG_2 ), \
+ verts + stride * ((i0) & ~DRAW_PIPE_FLAG_MASK), \
+ verts + stride * (i1), \
+ verts + stride * (i3)); \
+ do_triangle( draw, \
+ ( DRAW_PIPE_EDGE_FLAG_0 | \
+ DRAW_PIPE_EDGE_FLAG_1 ), \
+ verts + stride * ((i1) & ~DRAW_PIPE_FLAG_MASK), \
+ verts + stride * (i2), \
+ verts + stride * (i3))
+
+#define TRIANGLE(flags,i0,i1,i2) \
+ do_triangle( draw, \
+ flags, /* flags */ \
+ verts + stride * ((i0) & ~DRAW_PIPE_FLAG_MASK), \
+ verts + stride * (i1), \
+ verts + stride * (i2))
+
+#define LINE(flags,i0,i1) \
+ do_line( draw, \
+ flags, \
+ verts + stride * ((i0) & ~DRAW_PIPE_FLAG_MASK), \
+ verts + stride * (i+1))
+
+#define POINT(i0) \
+ do_point( draw, \
+ verts + stride * i0 )
+
+#define FUNC pipe_run_linear
+#define ARGS \
+ struct draw_context *draw, \
+ unsigned prim, \
+ struct vertex_header *vertices, \
+ unsigned stride
+
+#define LOCAL_VARS \
+ char *verts = (char *)vertices; \
+ boolean flatfirst = (draw->rasterizer->flatshade && \
+ draw->rasterizer->flatshade_first); \
+ unsigned i, flags
+
+#define FLUSH
+
+#include "draw_pt_decompose.h"
+
+void draw_pipeline_run_linear( struct draw_context *draw,
+ unsigned prim,
+ struct vertex_header *vertices,
+ unsigned count,
+ unsigned stride )
+{
+ char *verts = (char *)vertices;
+ draw->pipeline.verts = verts;
+ draw->pipeline.vertex_stride = stride;
+ draw->pipeline.vertex_count = count;
+
+ pipe_run_linear(draw, prim, vertices, stride, count);
+
+ draw->pipeline.verts = NULL;
+ draw->pipeline.vertex_count = 0;
+}
void draw_pipeline_flush( struct draw_context *draw,
diff --git a/src/gallium/auxiliary/draw/draw_pipe_vbuf.c b/src/gallium/auxiliary/draw/draw_pipe_vbuf.c
index 86a7d1c730..67b9a9503d 100644
--- a/src/gallium/auxiliary/draw/draw_pipe_vbuf.c
+++ b/src/gallium/auxiliary/draw/draw_pipe_vbuf.c
@@ -427,9 +427,6 @@ static void vbuf_destroy( struct draw_stage *stage )
if(vbuf->indices)
align_free( vbuf->indices );
- if(vbuf->translate)
- vbuf->translate->release( vbuf->translate );
-
if (vbuf->render)
vbuf->render->destroy( vbuf->render );
diff --git a/src/gallium/auxiliary/draw/draw_private.h b/src/gallium/auxiliary/draw/draw_private.h
index cee58bbf73..86b901a3c8 100644
--- a/src/gallium/auxiliary/draw/draw_private.h
+++ b/src/gallium/auxiliary/draw/draw_private.h
@@ -124,12 +124,14 @@ struct draw_context
struct {
struct {
struct draw_pt_middle_end *fetch_emit;
+ struct draw_pt_middle_end *fetch_shade_emit;
struct draw_pt_middle_end *general;
} middle;
struct {
struct draw_pt_front_end *vcache;
struct draw_pt_front_end *varray;
+ struct draw_pt_front_end *fetch_shade_emit; /* temp hack */
} front;
struct pipe_vertex_buffer vertex_buffer[PIPE_MAX_ATTRIBS];
@@ -154,6 +156,7 @@ struct draw_context
const void *constants;
} user;
+ boolean test_fse;
} pt;
struct {
@@ -247,6 +250,12 @@ void draw_pipeline_run( struct draw_context *draw,
const ushort *elts,
unsigned count );
+void draw_pipeline_run_linear( struct draw_context *draw,
+ unsigned prim,
+ struct vertex_header *vertices,
+ unsigned count,
+ unsigned stride );
+
void draw_pipeline_flush( struct draw_context *draw,
diff --git a/src/gallium/auxiliary/draw/draw_pt.c b/src/gallium/auxiliary/draw/draw_pt.c
index c9c5d18313..91e35db819 100644
--- a/src/gallium/auxiliary/draw/draw_pt.c
+++ b/src/gallium/auxiliary/draw/draw_pt.c
@@ -64,7 +64,7 @@ draw_pt_arrays(struct draw_context *draw,
opt |= PT_PIPELINE;
}
- if (!draw->bypass_clipping) {
+ if (!draw->bypass_clipping && !draw->pt.test_fse) {
opt |= PT_CLIPTEST;
}
@@ -72,17 +72,24 @@ draw_pt_arrays(struct draw_context *draw,
opt |= PT_SHADE;
}
- if (opt)
- middle = draw->pt.middle.general;
- else
+
+ if (opt == 0)
middle = draw->pt.middle.fetch_emit;
+ else if (opt == PT_SHADE && draw->pt.test_fse)
+ middle = draw->pt.middle.fetch_shade_emit;
+ else
+ middle = draw->pt.middle.general;
/* Pick the right frontend
*/
- if (draw->pt.user.elts ||
- count >= 256) {
+ if (draw->pt.user.elts || (opt & PT_PIPELINE)) {
frontend = draw->pt.front.vcache;
+#if 0
+ } else if (opt == PT_SHADE && draw->pt.test_fse) {
+ /* should be a middle end.. */
+ frontend = draw->pt.front.fetch_shade_emit;
+#endif
} else {
frontend = draw->pt.front.varray;
}
@@ -102,6 +109,8 @@ draw_pt_arrays(struct draw_context *draw,
boolean draw_pt_init( struct draw_context *draw )
{
+ draw->pt.test_fse = GETENV("DRAW_FSE") != NULL;
+
draw->pt.front.vcache = draw_pt_vcache( draw );
if (!draw->pt.front.vcache)
return FALSE;
@@ -114,6 +123,17 @@ boolean draw_pt_init( struct draw_context *draw )
if (!draw->pt.middle.fetch_emit)
return FALSE;
+ if (draw->pt.test_fse) {
+ draw->pt.middle.fetch_shade_emit = draw_pt_middle_fse( draw );
+ if (!draw->pt.middle.fetch_shade_emit)
+ return FALSE;
+
+ draw->pt.front.fetch_shade_emit = draw_pt_fetch_shade_emit( draw );
+ if (!draw->pt.front.fetch_shade_emit)
+ return FALSE;
+ }
+
+
draw->pt.middle.general = draw_pt_fetch_pipeline_or_emit( draw );
if (!draw->pt.middle.general)
return FALSE;
@@ -134,6 +154,16 @@ void draw_pt_destroy( struct draw_context *draw )
draw->pt.middle.fetch_emit = NULL;
}
+ if (draw->pt.middle.fetch_shade_emit) {
+ draw->pt.middle.fetch_shade_emit->destroy( draw->pt.middle.fetch_shade_emit );
+ draw->pt.middle.fetch_shade_emit = NULL;
+ }
+
+ if (draw->pt.front.fetch_shade_emit) {
+ draw->pt.front.fetch_shade_emit->destroy( draw->pt.front.fetch_shade_emit );
+ draw->pt.front.fetch_shade_emit = NULL;
+ }
+
if (draw->pt.front.vcache) {
draw->pt.front.vcache->destroy( draw->pt.front.vcache );
draw->pt.front.vcache = NULL;
@@ -147,19 +177,6 @@ void draw_pt_destroy( struct draw_context *draw )
-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
@@ -172,9 +189,10 @@ void
draw_arrays(struct draw_context *draw, unsigned prim,
unsigned start, unsigned count)
{
- if (reduced_prim[prim] != draw->reduced_prim) {
+ unsigned reduced_prim = draw_pt_reduced_prim(prim);
+ if (reduced_prim != draw->reduced_prim) {
draw_do_flush( draw, DRAW_FLUSH_STATE_CHANGE );
- draw->reduced_prim = reduced_prim[prim];
+ draw->reduced_prim = reduced_prim;
}
/* drawing done here: */
diff --git a/src/gallium/auxiliary/draw/draw_pt.h b/src/gallium/auxiliary/draw/draw_pt.h
index 2dec376cee..cdae46b8d2 100644
--- a/src/gallium/auxiliary/draw/draw_pt.h
+++ b/src/gallium/auxiliary/draw/draw_pt.h
@@ -92,6 +92,10 @@ struct draw_pt_middle_end {
const ushort *draw_elts,
unsigned draw_count );
+ void (*run_linear)(struct draw_pt_middle_end *,
+ unsigned start,
+ unsigned count);
+
void (*finish)( struct draw_pt_middle_end * );
void (*destroy)( struct draw_pt_middle_end * );
};
@@ -117,6 +121,8 @@ const void *draw_pt_elt_ptr( struct draw_context *draw,
struct draw_pt_front_end *draw_pt_vcache( struct draw_context *draw );
struct draw_pt_front_end *draw_pt_varray(struct draw_context *draw);
+struct draw_pt_front_end *draw_pt_fetch_shade_emit( struct draw_context *draw );
+
/* Middle-ends:
*
* Currently one general-purpose case which can do all possibilities,
@@ -128,6 +134,7 @@ struct draw_pt_front_end *draw_pt_varray(struct draw_context *draw);
* vertex_elements.
*/
struct draw_pt_middle_end *draw_pt_fetch_emit( struct draw_context *draw );
+struct draw_pt_middle_end *draw_pt_middle_fse( struct draw_context *draw );
struct draw_pt_middle_end *draw_pt_fetch_pipeline_or_emit(struct draw_context *draw);
@@ -152,6 +159,13 @@ void draw_pt_emit( struct pt_emit *emit,
const ushort *elts,
unsigned count );
+void draw_pt_emit_linear( struct pt_emit *emit,
+ const float (*vertex_data)[4],
+ unsigned vertex_count,
+ unsigned stride,
+ unsigned start,
+ unsigned count );
+
void draw_pt_emit_destroy( struct pt_emit *emit );
struct pt_emit *draw_pt_emit_create( struct draw_context *draw );
@@ -170,6 +184,11 @@ void draw_pt_fetch_run( struct pt_fetch *fetch,
unsigned count,
char *verts );
+void draw_pt_fetch_run_linear( struct pt_fetch *fetch,
+ unsigned start,
+ unsigned count,
+ char *verts );
+
void draw_pt_fetch_destroy( struct pt_fetch *fetch );
struct pt_fetch *draw_pt_fetch_create( struct draw_context *draw );
@@ -194,4 +213,11 @@ struct pt_post_vs *draw_pt_post_vs_create( struct draw_context *draw );
void draw_pt_post_vs_destroy( struct pt_post_vs *pvs );
+/*******************************************************************************
+ * Utils:
+ */
+void draw_pt_split_prim(unsigned prim, unsigned *first, unsigned *incr);
+unsigned draw_pt_reduced_prim(unsigned prim);
+
+
#endif
diff --git a/src/gallium/auxiliary/draw/draw_pt_decompose.h b/src/gallium/auxiliary/draw/draw_pt_decompose.h
new file mode 100644
index 0000000000..dccfde99dd
--- /dev/null
+++ b/src/gallium/auxiliary/draw/draw_pt_decompose.h
@@ -0,0 +1,153 @@
+
+
+static void FUNC( ARGS,
+ unsigned count )
+{
+ LOCAL_VARS;
+
+ switch (prim) {
+ case PIPE_PRIM_POINTS:
+ for (i = 0; i < count; i ++) {
+ POINT( (i + 0) );
+ }
+ break;
+
+ case PIPE_PRIM_LINES:
+ for (i = 0; i+1 < count; i += 2) {
+ LINE( DRAW_PIPE_RESET_STIPPLE,
+ (i + 0),
+ (i + 1));
+ }
+ break;
+
+ case PIPE_PRIM_LINE_LOOP:
+ if (count >= 2) {
+ flags = DRAW_PIPE_RESET_STIPPLE;
+
+ for (i = 1; i < count; i++, flags = 0) {
+ LINE( flags,
+ (i - 1),
+ (i ));
+ }
+
+ LINE( flags,
+ (i - 1),
+ (0 ));
+ }
+ break;
+
+ case PIPE_PRIM_LINE_STRIP:
+ flags = DRAW_PIPE_RESET_STIPPLE;
+ for (i = 1; i < count; i++, flags = 0) {
+ LINE( flags,
+ (i - 1),
+ (i ));
+ }
+ break;
+
+ case PIPE_PRIM_TRIANGLES:
+ for (i = 0; i+2 < count; i += 3) {
+ TRIANGLE( DRAW_PIPE_RESET_STIPPLE | DRAW_PIPE_EDGE_FLAG_ALL,
+ (i + 0),
+ (i + 1),
+ (i + 2 ));
+ }
+ break;
+
+ case PIPE_PRIM_TRIANGLE_STRIP:
+ if (flatfirst) {
+ for (i = 0; i+2 < count; i++) {
+ TRIANGLE( DRAW_PIPE_RESET_STIPPLE | DRAW_PIPE_EDGE_FLAG_ALL,
+ (i + 0),
+ (i + 1 + (i&1)),
+ (i + 2 - (i&1)));
+ }
+ }
+ else {
+ for (i = 0; i+2 < count; i++) {
+ TRIANGLE( DRAW_PIPE_RESET_STIPPLE | DRAW_PIPE_EDGE_FLAG_ALL,
+ (i + 0 + (i&1)),
+ (i + 1 - (i&1)),
+ (i + 2 ));
+ }
+ }
+ break;
+
+ case PIPE_PRIM_TRIANGLE_FAN:
+ if (count >= 3) {
+ if (flatfirst) {
+ for (i = 0; i+2 < count; i++) {
+ TRIANGLE( DRAW_PIPE_RESET_STIPPLE | DRAW_PIPE_EDGE_FLAG_ALL,
+ (i + 1),
+ (i + 2),
+ (0 ));
+ }
+ }
+ else {
+ for (i = 0; i+2 < count; i++) {
+ TRIANGLE( DRAW_PIPE_RESET_STIPPLE | DRAW_PIPE_EDGE_FLAG_ALL,
+ (0),
+ (i + 1),
+ (i + 2 ));
+ }
+ }
+ }
+ break;
+
+
+ case PIPE_PRIM_QUADS:
+ for (i = 0; i+3 < count; i += 4) {
+ QUAD( (i + 0),
+ (i + 1),
+ (i + 2),
+ (i + 3));
+ }
+ break;
+
+ case PIPE_PRIM_QUAD_STRIP:
+ for (i = 0; i+3 < count; i += 2) {
+ QUAD( (i + 2),
+ (i + 0),
+ (i + 1),
+ (i + 3));
+ }
+ break;
+
+ case PIPE_PRIM_POLYGON:
+ {
+ /* These bitflags look a little odd because we submit the
+ * vertices as (1,2,0) to satisfy flatshade requirements.
+ */
+ const unsigned edge_first = DRAW_PIPE_EDGE_FLAG_2;
+ const unsigned edge_middle = DRAW_PIPE_EDGE_FLAG_0;
+ const unsigned edge_last = DRAW_PIPE_EDGE_FLAG_1;
+
+ flags = DRAW_PIPE_RESET_STIPPLE | edge_first | edge_middle;
+
+ for (i = 0; i+2 < count; i++, flags = edge_middle) {
+
+ if (i + 3 == count)
+ flags |= edge_last;
+
+ TRIANGLE( flags,
+ (i + 1),
+ (i + 2),
+ (0));
+ }
+ }
+ break;
+
+ default:
+ assert(0);
+ break;
+ }
+
+ FLUSH;
+}
+
+
+#undef TRIANGLE
+#undef QUAD
+#undef POINT
+#undef LINE
+#undef FUNC
diff --git a/src/gallium/auxiliary/draw/draw_pt_emit.c b/src/gallium/auxiliary/draw/draw_pt_emit.c
index ce3a153f64..22a83ec78f 100644
--- a/src/gallium/auxiliary/draw/draw_pt_emit.c
+++ b/src/gallium/auxiliary/draw/draw_pt_emit.c
@@ -178,6 +178,53 @@ void draw_pt_emit( struct pt_emit *emit,
}
+void draw_pt_emit_linear(struct pt_emit *emit,
+ const float (*vertex_data)[4],
+ unsigned vertex_count,
+ unsigned stride,
+ unsigned start,
+ unsigned count)
+{
+ struct draw_context *draw = emit->draw;
+ struct translate *translate = emit->translate;
+ struct vbuf_render *render = draw->render;
+ void *hw_verts;
+
+#if 0
+ debug_printf("Linear emit\n");
+#endif
+ /* XXX: need to flush to get prim_vbuf.c to release its allocation??
+ */
+ draw_do_flush( draw, DRAW_FLUSH_BACKEND );
+
+ hw_verts = render->allocate_vertices(render,
+ (ushort)translate->key.output_stride,
+ (ushort)count);
+ if (!hw_verts) {
+ assert(0);
+ return;
+ }
+
+ translate->set_buffer(translate, 0,
+ vertex_data, stride);
+
+ translate->set_buffer(translate, 1,
+ &draw->rasterizer->point_size,
+ 0);
+
+ translate->run(translate,
+ 0,
+ vertex_count,
+ hw_verts);
+
+ render->draw_arrays(render, start, count);
+
+ render->release_vertices(render,
+ hw_verts,
+ translate->key.output_stride,
+ vertex_count);
+}
+
struct pt_emit *draw_pt_emit_create( struct draw_context *draw )
{
struct pt_emit *emit = CALLOC_STRUCT(pt_emit);
diff --git a/src/gallium/auxiliary/draw/draw_pt_fetch.c b/src/gallium/auxiliary/draw/draw_pt_fetch.c
index 100117a9ae..07f4c99164 100644
--- a/src/gallium/auxiliary/draw/draw_pt_fetch.c
+++ b/src/gallium/auxiliary/draw/draw_pt_fetch.c
@@ -166,6 +166,42 @@ void draw_pt_fetch_run( struct pt_fetch *fetch,
}
+void draw_pt_fetch_run_linear( struct pt_fetch *fetch,
+ unsigned start,
+ unsigned count,
+ char *verts )
+{
+ struct draw_context *draw = fetch->draw;
+ struct translate *translate = fetch->translate;
+ unsigned i;
+
+ for (i = 0; i < draw->pt.nr_vertex_buffers; i++) {
+ translate->set_buffer(translate,
+ i,
+ ((char *)draw->pt.user.vbuffer[i] +
+ draw->pt.vertex_buffer[i].buffer_offset),
+ draw->pt.vertex_buffer[i].pitch );
+ }
+
+ translate->run( translate,
+ start,
+ count,
+ verts );
+
+ /* Edgeflags are hard to fit into a translate program, populate
+ * them separately if required. In the setup above they are
+ * defaulted to one, so only need this if there is reason to change
+ * that default:
+ */
+ if (fetch->need_edgeflags) {
+ for (i = 0; i < count; i++) {
+ struct vertex_header *vh = (struct vertex_header *)(verts + i * fetch->vertex_size);
+ vh->edgeflag = draw_pt_get_edgeflag( draw, start + i );
+ }
+ }
+}
+
+
struct pt_fetch *draw_pt_fetch_create( struct draw_context *draw )
{
struct pt_fetch *fetch = CALLOC_STRUCT(pt_fetch);
@@ -184,7 +220,8 @@ struct pt_fetch *draw_pt_fetch_create( struct draw_context *draw )
void draw_pt_fetch_destroy( struct pt_fetch *fetch )
{
- translate_cache_destroy(fetch->cache);
+ if (fetch->cache)
+ translate_cache_destroy(fetch->cache);
FREE(fetch);
}
diff --git a/src/gallium/auxiliary/draw/draw_pt_fetch_emit.c b/src/gallium/auxiliary/draw/draw_pt_fetch_emit.c
index b7b970a297..a1d041a74f 100644
--- a/src/gallium/auxiliary/draw/draw_pt_fetch_emit.c
+++ b/src/gallium/auxiliary/draw/draw_pt_fetch_emit.c
@@ -258,6 +258,59 @@ static void fetch_emit_run( struct draw_pt_middle_end *middle,
}
+static void fetch_emit_run_linear( struct draw_pt_middle_end *middle,
+ unsigned start,
+ unsigned count )
+{
+ struct fetch_emit_middle_end *feme = (struct fetch_emit_middle_end *)middle;
+ struct draw_context *draw = feme->draw;
+ void *hw_verts;
+
+ /* XXX: need to flush to get prim_vbuf.c to release its allocation??
+ */
+ draw_do_flush( draw, DRAW_FLUSH_BACKEND );
+
+ hw_verts = draw->render->allocate_vertices( draw->render,
+ (ushort)feme->translate->key.output_stride,
+ (ushort)count );
+ if (!hw_verts) {
+ assert(0);
+ return;
+ }
+
+ /* Single routine to fetch vertices and emit HW verts.
+ */
+ feme->translate->run( feme->translate,
+ start,
+ count,
+ hw_verts );
+
+ if (0) {
+ unsigned i;
+ for (i = 0; i < count; i++) {
+ debug_printf("\n\nvertex %d:\n", i);
+ draw_dump_emitted_vertex( feme->vinfo,
+ (const uint8_t *)hw_verts + feme->vinfo->size * 4 * i );
+ }
+ }
+
+ /* XXX: Draw arrays path to avoid re-emitting index list again and
+ * again.
+ */
+ draw->render->draw_arrays( draw->render,
+ 0, /*start*/
+ count );
+
+ /* Done -- that was easy, wasn't it:
+ */
+ draw->render->release_vertices( draw->render,
+ hw_verts,
+ feme->translate->key.output_stride,
+ count );
+
+}
+
+
static void fetch_emit_finish( struct draw_pt_middle_end *middle )
{
@@ -268,7 +321,8 @@ static void fetch_emit_destroy( struct draw_pt_middle_end *middle )
{
struct fetch_emit_middle_end *feme = (struct fetch_emit_middle_end *)middle;
- translate_cache_destroy(feme->cache);
+ if (feme->cache)
+ translate_cache_destroy(feme->cache);
FREE(middle);
}
@@ -286,10 +340,11 @@ struct draw_pt_middle_end *draw_pt_fetch_emit( struct draw_context *draw )
return NULL;
}
- fetch_emit->base.prepare = fetch_emit_prepare;
- fetch_emit->base.run = fetch_emit_run;
- fetch_emit->base.finish = fetch_emit_finish;
- fetch_emit->base.destroy = fetch_emit_destroy;
+ fetch_emit->base.prepare = fetch_emit_prepare;
+ fetch_emit->base.run = fetch_emit_run;
+ fetch_emit->base.run_linear = fetch_emit_run_linear;
+ fetch_emit->base.finish = fetch_emit_finish;
+ fetch_emit->base.destroy = fetch_emit_destroy;
fetch_emit->draw = draw;
diff --git a/src/gallium/auxiliary/draw/draw_pt_fetch_shade_emit.c b/src/gallium/auxiliary/draw/draw_pt_fetch_shade_emit.c
new file mode 100644
index 0000000000..f756d3e0bb
--- /dev/null
+++ b/src/gallium/auxiliary/draw/draw_pt_fetch_shade_emit.c
@@ -0,0 +1,677 @@
+/**************************************************************************
+ *
+ * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+ /*
+ * Authors:
+ * Keith Whitwell <keith@tungstengraphics.com>
+ */
+
+
+#include "pipe/p_util.h"
+#include "draw/draw_context.h"
+#include "draw/draw_private.h"
+#include "draw/draw_vbuf.h"
+#include "draw/draw_vertex.h"
+#include "draw/draw_pt.h"
+#include "draw/draw_vs.h"
+
+#include "translate/translate.h"
+
+struct fetch_shade_emit;
+
+struct fse_shader {
+ struct translate_key key;
+
+ void (*run_linear)( const struct fetch_shade_emit *fse,
+ unsigned start,
+ unsigned count,
+ char *buffer );
+};
+
+/* Prototype fetch, shade, emit-hw-verts all in one go.
+ */
+struct fetch_shade_emit {
+ struct draw_pt_front_end base;
+
+ struct draw_context *draw;
+
+ struct translate_key key;
+
+ /* Temporaries:
+ */
+ const float *constants;
+ unsigned pitch[PIPE_MAX_ATTRIBS];
+ const ubyte *src[PIPE_MAX_ATTRIBS];
+ unsigned prim;
+
+ /* Points to one of the three hardwired example shaders, below:
+ */
+ struct fse_shader *active;
+
+ /* Temporary: A list of hard-wired shaders. Of course the plan
+ * would be to generate these for a given (vertex-shader,
+ * translate-key) pair...
+ */
+ struct fse_shader shader[10];
+ int nr_shaders;
+};
+
+
+
+/* Not quite passthrough yet -- we're still running the 'shader' here,
+ * inlined into the vertex fetch function.
+ */
+static void fetch_xyz_rgb_st( const struct fetch_shade_emit *fse,
+ unsigned start,
+ unsigned count,
+ char *buffer )
+{
+ unsigned i;
+
+ const float *m = fse->constants;
+ const float m0 = m[0], m4 = m[4], m8 = m[8], m12 = m[12];
+ const float m1 = m[1], m5 = m[5], m9 = m[9], m13 = m[13];
+ const float m2 = m[2], m6 = m[6], m10 = m[10], m14 = m[14];
+ const float m3 = m[3], m7 = m[7], m11 = m[11], m15 = m[15];
+
+ const ubyte *xyz = fse->src[0] + start * fse->pitch[0];
+ const ubyte *st = fse->src[2] + start * fse->pitch[2];
+
+ float *out = (float *)buffer;
+
+
+ assert(fse->pitch[1] == 0);
+
+ /* loop over vertex attributes (vertex shader inputs)
+ */
+ for (i = 0; i < count; i++) {
+ {
+ const float *in = (const float *)xyz;
+ const float ix = in[0], iy = in[1], iz = in[2];
+
+ out[0] = m0 * ix + m4 * iy + m8 * iz + m12;
+ out[1] = m1 * ix + m5 * iy + m9 * iz + m13;
+ out[2] = m2 * ix + m6 * iy + m10 * iz + m14;
+ out[3] = m3 * ix + m7 * iy + m11 * iz + m15;
+ xyz += fse->pitch[0];
+ }
+
+ {
+ out[4] = 1.0f;
+ out[5] = 1.0f;
+ out[6] = 1.0f;
+ out[7] = 1.0f;
+ }
+
+ {
+ const float *in = (const float *)st; st += fse->pitch[2];
+ out[8] = in[0];
+ out[9] = in[1];
+ out[10] = 0.0f;
+ out[11] = 1.0f;
+ }
+
+ out += 12;
+ }
+}
+
+
+
+static void fetch_xyz_rgb( const struct fetch_shade_emit *fse,
+ unsigned start,
+ unsigned count,
+ char *buffer )
+{
+ unsigned i;
+
+ const float *m = (const float *)fse->constants;
+ const float m0 = m[0], m4 = m[4], m8 = m[8], m12 = m[12];
+ const float m1 = m[1], m5 = m[5], m9 = m[9], m13 = m[13];
+ const float m2 = m[2], m6 = m[6], m10 = m[10], m14 = m[14];
+ const float m3 = m[3], m7 = m[7], m11 = m[11], m15 = m[15];
+
+ const ubyte *xyz = fse->src[0] + start * fse->pitch[0];
+ const ubyte *rgb = fse->src[1] + start * fse->pitch[1];
+
+ float *out = (float *)buffer;
+
+// debug_printf("rgb %f %f %f\n", rgb[0], rgb[1], rgb[2]);
+
+
+ for (i = 0; i < count; i++) {
+ {
+ const float *in = (const float *)xyz;
+ const float ix = in[0], iy = in[1], iz = in[2];
+
+ out[0] = m0 * ix + m4 * iy + m8 * iz + m12;
+ out[1] = m1 * ix + m5 * iy + m9 * iz + m13;
+ out[2] = m2 * ix + m6 * iy + m10 * iz + m14;
+ out[3] = m3 * ix + m7 * iy + m11 * iz + m15;
+ xyz += fse->pitch[0];
+ }
+
+ {
+ const float *in = (const float *)rgb;
+ out[4] = in[0];
+ out[5] = in[1];
+ out[6] = in[2];
+ out[7] = 1.0f;
+ rgb += fse->pitch[1];
+ }
+
+ out += 8;
+ }
+}
+
+
+
+
+static void fetch_xyz_rgb_psiz( const struct fetch_shade_emit *fse,
+ unsigned start,
+ unsigned count,
+ char *buffer )
+{
+ unsigned i;
+
+ const float *m = (const float *)fse->constants;
+ const float m0 = m[0], m4 = m[4], m8 = m[8], m12 = m[12];
+ const float m1 = m[1], m5 = m[5], m9 = m[9], m13 = m[13];
+ const float m2 = m[2], m6 = m[6], m10 = m[10], m14 = m[14];
+ const float m3 = m[3], m7 = m[7], m11 = m[11], m15 = m[15];
+
+ const ubyte *xyz = fse->src[0] + start * fse->pitch[0];
+ const float *rgb = (const float *)(fse->src[1] + start * fse->pitch[1]);
+ const float psiz = 1.0;
+
+ float *out = (float *)buffer;
+
+
+ assert(fse->pitch[1] == 0);
+
+ for (i = 0; i < count; i++) {
+ {
+ const float *in = (const float *)xyz;
+ const float ix = in[0], iy = in[1], iz = in[2];
+
+ out[0] = m0 * ix + m4 * iy + m8 * iz + m12;
+ out[1] = m1 * ix + m5 * iy + m9 * iz + m13;
+ out[2] = m2 * ix + m6 * iy + m10 * iz + m14;
+ out[3] = m3 * ix + m7 * iy + m11 * iz + m15;
+ xyz += fse->pitch[0];
+ }
+
+ {
+ out[4] = rgb[0];
+ out[5] = rgb[1];
+ out[6] = rgb[2];
+ out[7] = 1.0f;
+ }
+
+ {
+ out[8] = psiz;
+ }
+
+ out += 9;
+ }
+}
+
+
+
+
+static boolean set_prim( struct fetch_shade_emit *fse,
+ unsigned prim,
+ unsigned count )
+{
+ struct draw_context *draw = fse->draw;
+
+ fse->prim = prim;
+
+ switch (prim) {
+ case PIPE_PRIM_LINE_LOOP:
+ if (count > 1024)
+ return FALSE;
+ draw->render->set_primitive( draw->render, PIPE_PRIM_LINE_STRIP );
+ break;
+
+ case PIPE_PRIM_TRIANGLE_FAN:
+ case PIPE_PRIM_POLYGON:
+ if (count > 1024)
+ return FALSE;
+ draw->render->set_primitive( draw->render, prim );
+ break;
+
+ case PIPE_PRIM_QUADS:
+ case PIPE_PRIM_QUAD_STRIP:
+ draw->render->set_primitive( draw->render, PIPE_PRIM_TRIANGLES );
+ break;
+
+ default:
+ draw->render->set_primitive( draw->render, prim );
+ break;
+ }
+
+ return TRUE;
+}
+
+
+
+
+
+
+static void fse_prepare( struct draw_pt_front_end *fe,
+ unsigned prim,
+ struct draw_pt_middle_end *unused,
+ unsigned opt )
+{
+ struct fetch_shade_emit *fse = (struct fetch_shade_emit *)fe;
+ struct draw_context *draw = fse->draw;
+ unsigned num_vs_inputs = draw->vertex_shader->info.num_inputs;
+ unsigned num_vs_outputs = draw->vertex_shader->info.num_outputs;
+ const struct vertex_info *vinfo;
+ unsigned i;
+ boolean need_psize = 0;
+
+
+ if (draw->pt.user.elts) {
+ assert(0);
+ return ;
+ }
+
+ if (!set_prim(fse, prim, /*count*/1022 )) {
+ assert(0);
+ return ;
+ }
+
+ /* Must do this after set_primitive() above:
+ */
+ vinfo = draw->render->get_vertex_info(draw->render);
+
+
+
+ fse->key.nr_elements = MAX2(num_vs_outputs, /* outputs - translate to hw format */
+ num_vs_inputs); /* inputs - fetch from api format */
+
+ fse->key.output_stride = vinfo->size * 4;
+ memset(fse->key.element, 0,
+ fse->key.nr_elements * sizeof(fse->key.element[0]));
+
+ for (i = 0; i < num_vs_inputs; i++) {
+ const struct pipe_vertex_element *src = &draw->pt.vertex_element[i];
+ fse->key.element[i].input_format = src->src_format;
+
+ /* Consider ignoring these at this point, ie make generated
+ * programs independent of this state:
+ */
+ fse->key.element[i].input_buffer = 0; //src->vertex_buffer_index;
+ fse->key.element[i].input_offset = 0; //src->src_offset;
+ }
+
+
+ {
+ unsigned dst_offset = 0;
+
+ for (i = 0; i < vinfo->num_attribs; i++) {
+ unsigned emit_sz = 0;
+ unsigned output_format = PIPE_FORMAT_NONE;
+ unsigned vs_output = vinfo->src_index[i];
+
+ switch (vinfo->emit[i]) {
+ case EMIT_4F:
+ output_format = PIPE_FORMAT_R32G32B32A32_FLOAT;
+ emit_sz = 4 * sizeof(float);
+ break;
+ case EMIT_3F:
+ output_format = PIPE_FORMAT_R32G32B32_FLOAT;
+ emit_sz = 3 * sizeof(float);
+ break;
+ case EMIT_2F:
+ output_format = PIPE_FORMAT_R32G32_FLOAT;
+ emit_sz = 2 * sizeof(float);
+ break;
+ case EMIT_1F:
+ output_format = PIPE_FORMAT_R32_FLOAT;
+ emit_sz = 1 * sizeof(float);
+ break;
+ case EMIT_1F_PSIZE:
+ need_psize = 1;
+ output_format = PIPE_FORMAT_R32_FLOAT;
+ emit_sz = 1 * sizeof(float);
+ vs_output = num_vs_outputs + 1;
+
+ break;
+ default:
+ assert(0);
+ break;
+ }
+
+ /* The elements in the key correspond to vertex shader output
+ * numbers, not to positions in the hw vertex description --
+ * that's handled by the output_offset field.
+ */
+ fse->key.element[vs_output].output_format = output_format;
+ fse->key.element[vs_output].output_offset = dst_offset;
+
+ dst_offset += emit_sz;
+ assert(fse->key.output_stride >= dst_offset);
+ }
+ }
+
+ /* To make psize work, really need to tell the vertex shader to
+ * copy that value from input->output. For 'translate' this was
+ * implicit for all elements.
+ */
+#if 0
+ if (need_psize) {
+ unsigned input = num_vs_inputs + 1;
+ const struct pipe_vertex_element *src = &draw->pt.vertex_element[i];
+ fse->key.element[i].input_format = PIPE_FORMAT_R32_FLOAT;
+ fse->key.element[i].input_buffer = 0; //nr_buffers + 1;
+ fse->key.element[i].input_offset = 0;
+
+ fse->key.nr_elements += 1;
+
+ }
+#endif
+
+ fse->constants = draw->pt.user.constants;
+
+ /* Would normally look up a vertex shader and peruse its list of
+ * varients somehow. We omitted that step and put all the
+ * hardcoded "shaders" into an array. We're just making the
+ * assumption that this happens to be a matching shader... ie
+ * you're running isosurf, aren't you?
+ */
+ fse->active = NULL;
+ for (i = 0; i < fse->nr_shaders; i++) {
+ if (translate_key_compare( &fse->key, &fse->shader[i].key) == 0)
+ fse->active = &fse->shader[i];
+ }
+
+ if (!fse->active) {
+ assert(0);
+ return ;
+ }
+
+ /* Now set buffer pointers:
+ */
+ for (i = 0; i < num_vs_inputs; i++) {
+ unsigned buf = draw->pt.vertex_element[i].vertex_buffer_index;
+
+ fse->src[i] = ((const ubyte *) draw->pt.user.vbuffer[buf] +
+ draw->pt.vertex_buffer[buf].buffer_offset +
+ draw->pt.vertex_element[i].src_offset);
+
+ fse->pitch[i] = draw->pt.vertex_buffer[buf].pitch;
+
+ }
+
+
+ //return TRUE;
+}
+
+
+
+
+
+
+#define INDEX(i) (start + (i))
+static void fse_render_linear( struct vbuf_render *render,
+ unsigned prim,
+ unsigned start,
+ unsigned length )
+{
+ ushort *tmp = NULL;
+ unsigned i, j;
+
+ switch (prim) {
+ case PIPE_PRIM_LINE_LOOP:
+ tmp = MALLOC( sizeof(ushort) * (length + 1) );
+
+ for (i = 0; i < length; i++)
+ tmp[i] = INDEX(i);
+ tmp[length] = 0;
+
+ render->draw( render,
+ tmp,
+ length+1 );
+ break;
+
+
+ case PIPE_PRIM_QUAD_STRIP:
+ tmp = MALLOC( sizeof(ushort) * (length / 2 * 6) );
+
+ for (j = i = 0; i + 3 < length; i += 2, j += 6) {
+ tmp[j+0] = INDEX(i+0);
+ tmp[j+1] = INDEX(i+1);
+ tmp[j+2] = INDEX(i+3);
+
+ tmp[j+3] = INDEX(i+2);
+ tmp[j+4] = INDEX(i+0);
+ tmp[j+5] = INDEX(i+3);
+ }
+
+ if (j)
+ render->draw( render, tmp, j );
+ break;
+
+ case PIPE_PRIM_QUADS:
+ tmp = MALLOC( sizeof(int) * (length / 4 * 6) );
+
+ for (j = i = 0; i + 3 < length; i += 4, j += 6) {
+ tmp[j+0] = INDEX(i+0);
+ tmp[j+1] = INDEX(i+1);
+ tmp[j+2] = INDEX(i+3);
+
+ tmp[j+3] = INDEX(i+1);
+ tmp[j+4] = INDEX(i+2);
+ tmp[j+5] = INDEX(i+3);
+ }
+
+ if (j)
+ render->draw( render, tmp, j );
+ break;
+
+ default:
+ render->draw_arrays( render,
+ start,
+ length );
+ break;
+ }
+
+ if (tmp)
+ FREE(tmp);
+}
+
+
+
+static boolean do_draw( struct fetch_shade_emit *fse,
+ unsigned start, unsigned count )
+{
+ struct draw_context *draw = fse->draw;
+
+ char *hw_verts =
+ draw->render->allocate_vertices( draw->render,
+ (ushort)fse->key.output_stride,
+ (ushort)count );
+
+ if (!hw_verts)
+ return FALSE;
+
+ /* Single routine to fetch vertices, run shader and emit HW verts.
+ * Clipping and viewport transformation are done on hardware.
+ */
+ fse->active->run_linear( fse,
+ start, count,
+ hw_verts );
+
+ /* Draw arrays path to avoid re-emitting index list again and
+ * again.
+ */
+ fse_render_linear( draw->render,
+ fse->prim,
+ 0,
+ count );
+
+
+ draw->render->release_vertices( draw->render,
+ hw_verts,
+ fse->key.output_stride,
+ count );
+
+ return TRUE;
+}
+
+
+static void
+fse_run(struct draw_pt_front_end *fe,
+ pt_elt_func elt_func,
+ const void *elt_ptr,
+ unsigned count)
+{
+ struct fetch_shade_emit *fse = (struct fetch_shade_emit *)fe;
+ unsigned i = 0;
+ unsigned first, incr;
+ unsigned start = elt_func(elt_ptr, 0);
+
+ //debug_printf("%s prim %d start %d count %d\n", __FUNCTION__, prim, start, count);
+
+ draw_pt_split_prim(fse->prim, &first, &incr);
+
+ count -= (count - first) % incr;
+
+ while (i + first <= count) {
+ int nr = MIN2( count - i, 1024 );
+
+ /* snap to prim boundary
+ */
+ nr -= (nr - first) % incr;
+
+ if (!do_draw( fse, start + i, nr )) {
+ assert(0);
+ return ;
+ }
+
+ /* increment allowing for repeated vertices
+ */
+ i += nr - (first - incr);
+ }
+
+ //return TRUE;
+}
+
+
+static void fse_finish( struct draw_pt_front_end *frontend )
+{
+}
+
+
+static void
+fse_destroy( struct draw_pt_front_end *frontend )
+{
+ FREE(frontend);
+}
+
+struct draw_pt_front_end *draw_pt_fetch_shade_emit( struct draw_context *draw )
+{
+ struct fetch_shade_emit *fse = CALLOC_STRUCT(fetch_shade_emit);
+ if (!fse)
+ return NULL;
+
+ fse->base.prepare = fse_prepare;
+ fse->base.run = fse_run;
+ fse->base.finish = fse_finish;
+ fse->base.destroy = fse_destroy;
+ fse->draw = draw;
+
+ fse->shader[0].run_linear = fetch_xyz_rgb_st;
+ fse->shader[0].key.nr_elements = 3;
+ fse->shader[0].key.output_stride = 12 * sizeof(float);
+
+ fse->shader[0].key.element[0].input_format = PIPE_FORMAT_R32G32B32_FLOAT;
+ fse->shader[0].key.element[0].input_buffer = 0;
+ fse->shader[0].key.element[0].input_offset = 0;
+ fse->shader[0].key.element[0].output_format = PIPE_FORMAT_R32G32B32A32_FLOAT;
+ fse->shader[0].key.element[0].output_offset = 0;
+
+ fse->shader[0].key.element[1].input_format = PIPE_FORMAT_R32G32B32_FLOAT;
+ fse->shader[0].key.element[1].input_buffer = 0;
+ fse->shader[0].key.element[1].input_offset = 0;
+ fse->shader[0].key.element[1].output_format = PIPE_FORMAT_R32G32B32A32_FLOAT;
+ fse->shader[0].key.element[1].output_offset = 16;
+
+ fse->shader[0].key.element[1].input_format = PIPE_FORMAT_R32G32_FLOAT;
+ fse->shader[0].key.element[1].input_buffer = 0;
+ fse->shader[0].key.element[1].input_offset = 0;
+ fse->shader[0].key.element[1].output_format = PIPE_FORMAT_R32G32B32A32_FLOAT;
+ fse->shader[0].key.element[1].output_offset = 32;
+
+ fse->shader[1].run_linear = fetch_xyz_rgb;
+ fse->shader[1].key.nr_elements = 2;
+ fse->shader[1].key.output_stride = 8 * sizeof(float);
+
+ fse->shader[1].key.element[0].input_format = PIPE_FORMAT_R32G32B32_FLOAT;
+ fse->shader[1].key.element[0].input_buffer = 0;
+ fse->shader[1].key.element[0].input_offset = 0;
+ fse->shader[1].key.element[0].output_format = PIPE_FORMAT_R32G32B32A32_FLOAT;
+ fse->shader[1].key.element[0].output_offset = 0;
+
+ fse->shader[1].key.element[1].input_format = PIPE_FORMAT_R32G32B32_FLOAT;
+ fse->shader[1].key.element[1].input_buffer = 0;
+ fse->shader[1].key.element[1].input_offset = 0;
+ fse->shader[1].key.element[1].output_format = PIPE_FORMAT_R32G32B32A32_FLOAT;
+ fse->shader[1].key.element[1].output_offset = 16;
+
+ fse->shader[2].run_linear = fetch_xyz_rgb_psiz;
+ fse->shader[2].key.nr_elements = 3;
+ fse->shader[2].key.output_stride = 9 * sizeof(float);
+
+ fse->shader[2].key.element[0].input_format = PIPE_FORMAT_R32G32B32_FLOAT;
+ fse->shader[2].key.element[0].input_buffer = 0;
+ fse->shader[2].key.element[0].input_offset = 0;
+ fse->shader[2].key.element[0].output_format = PIPE_FORMAT_R32G32B32A32_FLOAT;
+ fse->shader[2].key.element[0].output_offset = 0;
+
+ fse->shader[2].key.element[1].input_format = PIPE_FORMAT_R32G32B32_FLOAT;
+ fse->shader[2].key.element[1].input_buffer = 0;
+ fse->shader[2].key.element[1].input_offset = 0;
+ fse->shader[2].key.element[1].output_format = PIPE_FORMAT_R32G32B32A32_FLOAT;
+ fse->shader[2].key.element[1].output_offset = 16;
+
+ /* psize is special
+ * -- effectively add it here as another input!?!
+ * -- who knows how to add it as a buffer?
+ */
+ fse->shader[2].key.element[2].input_format = PIPE_FORMAT_R32_FLOAT;
+ fse->shader[2].key.element[2].input_buffer = 0;
+ fse->shader[2].key.element[2].input_offset = 0;
+ fse->shader[2].key.element[2].output_format = PIPE_FORMAT_R32_FLOAT;
+ fse->shader[2].key.element[2].output_offset = 32;
+
+ fse->nr_shaders = 3;
+
+ return &fse->base;
+}
diff --git a/src/gallium/auxiliary/draw/draw_pt_fetch_shade_pipeline.c b/src/gallium/auxiliary/draw/draw_pt_fetch_shade_pipeline.c
index 4ec20493c4..dad54690a5 100644
--- a/src/gallium/auxiliary/draw/draw_pt_fetch_shade_pipeline.c
+++ b/src/gallium/auxiliary/draw/draw_pt_fetch_shade_pipeline.c
@@ -162,7 +162,7 @@ static void fetch_pipeline_run( struct draw_pt_middle_end *middle,
fpme->vertex_size,
draw_elts,
draw_count );
- }
+ }
else {
draw_pt_emit( fpme->emit,
(const float (*)[4])pipeline_verts->data,
@@ -177,6 +177,79 @@ static void fetch_pipeline_run( struct draw_pt_middle_end *middle,
}
+static void fetch_pipeline_linear_run( struct draw_pt_middle_end *middle,
+ unsigned start,
+ unsigned count)
+{
+ struct fetch_pipeline_middle_end *fpme = (struct fetch_pipeline_middle_end *)middle;
+ struct draw_context *draw = fpme->draw;
+ struct draw_vertex_shader *shader = draw->vertex_shader;
+ unsigned opt = fpme->opt;
+ unsigned alloc_count = align_int( count, 4 );
+
+ struct vertex_header *pipeline_verts =
+ (struct vertex_header *)MALLOC(fpme->vertex_size * alloc_count);
+
+ if (!pipeline_verts) {
+ /* Not much we can do here - just skip the rendering.
+ */
+ assert(0);
+ return;
+ }
+
+ /* Fetch into our vertex buffer
+ */
+ draw_pt_fetch_run_linear( fpme->fetch,
+ start,
+ count,
+ (char *)pipeline_verts );
+
+ /* Run the shader, note that this overwrites the data[] parts of
+ * the pipeline verts. If there is no shader, ie a bypass shader,
+ * then the inputs == outputs, and are already in the correct
+ * place.
+ */
+ if (opt & PT_SHADE)
+ {
+ shader->run_linear(shader,
+ (const float (*)[4])pipeline_verts->data,
+ ( float (*)[4])pipeline_verts->data,
+ (const float (*)[4])draw->pt.user.constants,
+ count,
+ fpme->vertex_size,
+ fpme->vertex_size);
+ }
+
+ if (draw_pt_post_vs_run( fpme->post_vs,
+ pipeline_verts,
+ count,
+ fpme->vertex_size ))
+ {
+ opt |= PT_PIPELINE;
+ }
+
+ /* Do we need to run the pipeline?
+ */
+ if (opt & PT_PIPELINE) {
+ draw_pipeline_run_linear( fpme->draw,
+ fpme->prim,
+ pipeline_verts,
+ count,
+ fpme->vertex_size);
+ }
+ else {
+ draw_pt_emit_linear( fpme->emit,
+ (const float (*)[4])pipeline_verts->data,
+ count,
+ fpme->vertex_size,
+ 0, /*start*/
+ count );
+ }
+
+ FREE(pipeline_verts);
+}
+
+
static void fetch_pipeline_finish( struct draw_pt_middle_end *middle )
{
@@ -206,10 +279,11 @@ struct draw_pt_middle_end *draw_pt_fetch_pipeline_or_emit( struct draw_context *
if (!fpme)
goto fail;
- fpme->base.prepare = fetch_pipeline_prepare;
- fpme->base.run = fetch_pipeline_run;
- fpme->base.finish = fetch_pipeline_finish;
- fpme->base.destroy = fetch_pipeline_destroy;
+ fpme->base.prepare = fetch_pipeline_prepare;
+ fpme->base.run = fetch_pipeline_run;
+ fpme->base.run_linear = fetch_pipeline_linear_run;
+ fpme->base.finish = fetch_pipeline_finish;
+ fpme->base.destroy = fetch_pipeline_destroy;
fpme->draw = draw;
diff --git a/src/gallium/auxiliary/draw/draw_pt_middle_fse.c b/src/gallium/auxiliary/draw/draw_pt_middle_fse.c
new file mode 100644
index 0000000000..cdb7d260da
--- /dev/null
+++ b/src/gallium/auxiliary/draw/draw_pt_middle_fse.c
@@ -0,0 +1,705 @@
+/**************************************************************************
+ *
+ * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+ /*
+ * Authors:
+ * Keith Whitwell <keith@tungstengraphics.com>
+ */
+
+
+#include "pipe/p_util.h"
+#include "draw/draw_context.h"
+#include "draw/draw_private.h"
+#include "draw/draw_vbuf.h"
+#include "draw/draw_vertex.h"
+#include "draw/draw_pt.h"
+#include "draw/draw_vs.h"
+
+#include "translate/translate.h"
+
+struct fetch_shade_emit;
+
+struct fse_shader {
+ struct translate_key key;
+
+ void (*run_linear)( const struct fetch_shade_emit *fse,
+ unsigned start,
+ unsigned count,
+ char *buffer );
+
+ void (*run_elts)( const struct fetch_shade_emit *fse,
+ const unsigned *fetch_elts,
+ unsigned fetch_count,
+ char *buffer );
+
+};
+
+/* Prototype fetch, shade, emit-hw-verts all in one go.
+ */
+struct fetch_shade_emit {
+ struct draw_pt_middle_end base;
+ struct draw_context *draw;
+
+ struct translate_key key;
+
+ /* Temporaries:
+ */
+ const float *constants;
+ unsigned pitch[PIPE_MAX_ATTRIBS];
+ const ubyte *src[PIPE_MAX_ATTRIBS];
+ unsigned prim;
+
+ /* Points to one of the three hardwired example shaders, below:
+ */
+ struct fse_shader *active;
+
+ /* Temporary: A list of hard-wired shaders. Of course the plan
+ * would be to generate these for a given (vertex-shader,
+ * translate-key) pair...
+ */
+ struct fse_shader shader[10];
+ int nr_shaders;
+};
+
+
+
+/* Not quite passthrough yet -- we're still running the 'shader' here,
+ * inlined into the vertex fetch function.
+ */
+static void shader0_run_linear( const struct fetch_shade_emit *fse,
+ unsigned start,
+ unsigned count,
+ char *buffer )
+{
+ unsigned i;
+
+ const float *m = fse->constants;
+ const ubyte *xyz = fse->src[0] + start * fse->pitch[0];
+ const ubyte *rgb = fse->src[1] + start * fse->pitch[1];
+ const ubyte *st = fse->src[2] + start * fse->pitch[2];
+
+ float *out = (float *)buffer;
+
+ /* loop over vertex attributes (vertex shader inputs)
+ */
+ for (i = 0; i < count; i++) {
+ {
+ const float *in = (const float *)xyz;
+ const float ix = in[0], iy = in[1], iz = in[2];
+
+ out[0] = m[0] * ix + m[4] * iy + m[8] * iz + m[12];
+ out[1] = m[1] * ix + m[5] * iy + m[9] * iz + m[13];
+ out[2] = m[2] * ix + m[6] * iy + m[10] * iz + m[14];
+ out[3] = m[3] * ix + m[7] * iy + m[11] * iz + m[15];
+ xyz += fse->pitch[0];
+ }
+
+ {
+ const float *in = (const float *)rgb;
+ out[4] = in[0];
+ out[5] = in[1];
+ out[6] = in[2];
+ out[7] = 1.0f;
+ rgb += fse->pitch[1];
+ }
+
+ {
+ const float *in = (const float *)st;
+ out[8] = in[0];
+ out[9] = in[1];
+ out[10] = 0.0f;
+ out[11] = 1.0f;
+ st += fse->pitch[2];
+ }
+
+ out += 12;
+ }
+}
+
+
+
+static void shader1_run_linear( const struct fetch_shade_emit *fse,
+ unsigned start,
+ unsigned count,
+ char *buffer )
+{
+ unsigned i;
+ const float *m = (const float *)fse->constants;
+ const ubyte *xyz = fse->src[0] + start * fse->pitch[0];
+ const ubyte *rgb = fse->src[1] + start * fse->pitch[1];
+ float *out = (float *)buffer;
+
+// debug_printf("rgb %f %f %f\n", rgb[0], rgb[1], rgb[2]);
+
+
+ for (i = 0; i < count; i++) {
+ {
+ const float *in = (const float *)xyz;
+ const float ix = in[0], iy = in[1], iz = in[2];
+
+ out[0] = m[0] * ix + m[4] * iy + m[8] * iz + m[12];
+ out[1] = m[1] * ix + m[5] * iy + m[9] * iz + m[13];
+ out[2] = m[2] * ix + m[6] * iy + m[10] * iz + m[14];
+ out[3] = m[3] * ix + m[7] * iy + m[11] * iz + m[15];
+ xyz += fse->pitch[0];
+ }
+
+ {
+ const float *in = (const float *)rgb;
+ out[4] = in[0];
+ out[5] = in[1];
+ out[6] = in[2];
+ out[7] = 1.0f;
+ rgb += fse->pitch[1];
+ }
+
+ out += 8;
+ }
+}
+
+
+
+
+static void shader2_run_linear( const struct fetch_shade_emit *fse,
+ unsigned start,
+ unsigned count,
+ char *buffer )
+{
+ unsigned i;
+ const float *m = (const float *)fse->constants;
+ const ubyte *xyz = fse->src[0] + start * fse->pitch[0];
+ const ubyte *rgb = fse->src[1] + start * fse->pitch[1];
+ const float psiz = 1.0;
+ float *out = (float *)buffer;
+
+
+ assert(fse->pitch[1] == 0);
+
+ for (i = 0; i < count; i++) {
+ {
+ const float *in = (const float *)xyz;
+ const float ix = in[0], iy = in[1], iz = in[2];
+
+ out[0] = m[0] * ix + m[4] * iy + m[8] * iz + m[12];
+ out[1] = m[1] * ix + m[5] * iy + m[9] * iz + m[13];
+ out[2] = m[2] * ix + m[6] * iy + m[10] * iz + m[14];
+ out[3] = m[3] * ix + m[7] * iy + m[11] * iz + m[15];
+ xyz += fse->pitch[0];
+ }
+
+ {
+ const float *in = (const float *)rgb;
+ out[4] = in[0];
+ out[5] = in[1];
+ out[6] = in[2];
+ out[7] = 1.0f;
+ rgb += fse->pitch[1];
+ }
+
+ {
+ out[8] = psiz;
+ }
+
+ out += 9;
+ }
+}
+
+
+
+
+static void shader0_run_elts( const struct fetch_shade_emit *fse,
+ const unsigned *elts,
+ unsigned count,
+ char *buffer )
+{
+ unsigned i;
+ const float *m = fse->constants;
+ float *out = (float *)buffer;
+
+
+ /* loop over vertex attributes (vertex shader inputs)
+ */
+ for (i = 0; i < count; i++) {
+ unsigned elt = elts[i];
+ {
+ const ubyte *xyz = fse->src[0] + elt * fse->pitch[0];
+ const float *in = (const float *)xyz;
+ const float ix = in[0], iy = in[1], iz = in[2];
+
+ out[0] = m[0] * ix + m[4] * iy + m[8] * iz + m[12];
+ out[1] = m[1] * ix + m[5] * iy + m[9] * iz + m[13];
+ out[2] = m[2] * ix + m[6] * iy + m[10] * iz + m[14];
+ out[3] = m[3] * ix + m[7] * iy + m[11] * iz + m[15];
+ }
+
+ {
+ const ubyte *rgb = fse->src[1] + elt * fse->pitch[1];
+ const float *in = (const float *)rgb;
+ out[4] = in[0];
+ out[5] = in[1];
+ out[6] = in[2];
+ out[7] = 1.0f;
+ }
+
+ {
+ const ubyte *st = fse->src[2] + elt * fse->pitch[2];
+ const float *in = (const float *)st;
+ out[8] = in[0];
+ out[9] = in[1];
+ out[10] = 0.0f;
+ out[11] = 1.0f;
+ }
+
+ out += 12;
+ }
+}
+
+
+
+static void shader1_run_elts( const struct fetch_shade_emit *fse,
+ const unsigned *elts,
+ unsigned count,
+ char *buffer )
+{
+ unsigned i;
+ const float *m = (const float *)fse->constants;
+ float *out = (float *)buffer;
+
+ for (i = 0; i < count; i++) {
+ unsigned elt = elts[i];
+
+ {
+ const ubyte *xyz = fse->src[0] + elt * fse->pitch[0];
+ const float *in = (const float *)xyz;
+ const float ix = in[0], iy = in[1], iz = in[2];
+
+ out[0] = m[0] * ix + m[4] * iy + m[8] * iz + m[12];
+ out[1] = m[1] * ix + m[5] * iy + m[9] * iz + m[13];
+ out[2] = m[2] * ix + m[6] * iy + m[10] * iz + m[14];
+ out[3] = m[3] * ix + m[7] * iy + m[11] * iz + m[15];
+ xyz += fse->pitch[0];
+ }
+
+ {
+ const ubyte *rgb = fse->src[1] + elt * fse->pitch[1];
+ const float *in = (const float *)rgb;
+ out[4] = in[0];
+ out[5] = in[1];
+ out[6] = in[2];
+ out[7] = 1.0f;
+ rgb += fse->pitch[1];
+ }
+
+ out += 8;
+ }
+}
+
+
+
+
+static void shader2_run_elts( const struct fetch_shade_emit *fse,
+ const unsigned *elts,
+ unsigned count,
+ char *buffer )
+{
+ unsigned i;
+ const float *m = (const float *)fse->constants;
+ const float psiz = 1.0;
+ float *out = (float *)buffer;
+
+ for (i = 0; i < count; i++) {
+ unsigned elt = elts[i];
+ {
+ const ubyte *xyz = fse->src[0] + elt * fse->pitch[0];
+ const float *in = (const float *)xyz;
+ const float ix = in[0], iy = in[1], iz = in[2];
+
+ out[0] = m[0] * ix + m[4] * iy + m[8] * iz + m[12];
+ out[1] = m[1] * ix + m[5] * iy + m[9] * iz + m[13];
+ out[2] = m[2] * ix + m[6] * iy + m[10] * iz + m[14];
+ out[3] = m[3] * ix + m[7] * iy + m[11] * iz + m[15];
+ }
+
+ {
+ const ubyte *rgb = fse->src[1] + elt * fse->pitch[1];
+ out[4] = rgb[0];
+ out[5] = rgb[1];
+ out[6] = rgb[2];
+ out[7] = 1.0f;
+ }
+
+ {
+ out[8] = psiz;
+ }
+
+ out += 9;
+ }
+}
+
+
+
+static void fse_prepare( struct draw_pt_middle_end *middle,
+ unsigned prim,
+ unsigned opt )
+{
+ struct fetch_shade_emit *fse = (struct fetch_shade_emit *)middle;
+ struct draw_context *draw = fse->draw;
+ unsigned num_vs_inputs = draw->vertex_shader->info.num_inputs;
+ unsigned num_vs_outputs = draw->vertex_shader->info.num_outputs;
+ const struct vertex_info *vinfo;
+ unsigned i;
+ boolean need_psize = 0;
+
+
+ if (draw->pt.user.elts) {
+ assert(0);
+ return ;
+ }
+
+ if (!draw->render->set_primitive( draw->render,
+ prim )) {
+ assert(0);
+ return;
+ }
+
+ /* Must do this after set_primitive() above:
+ */
+ vinfo = draw->render->get_vertex_info(draw->render);
+
+
+
+ fse->key.nr_elements = MAX2(num_vs_outputs, /* outputs - translate to hw format */
+ num_vs_inputs); /* inputs - fetch from api format */
+
+ fse->key.output_stride = vinfo->size * 4;
+ memset(fse->key.element, 0,
+ fse->key.nr_elements * sizeof(fse->key.element[0]));
+
+ for (i = 0; i < num_vs_inputs; i++) {
+ const struct pipe_vertex_element *src = &draw->pt.vertex_element[i];
+ fse->key.element[i].input_format = src->src_format;
+
+ /* Consider ignoring these at this point, ie make generated
+ * programs independent of this state:
+ */
+ fse->key.element[i].input_buffer = 0; //src->vertex_buffer_index;
+ fse->key.element[i].input_offset = 0; //src->src_offset;
+ }
+
+
+ {
+ unsigned dst_offset = 0;
+
+ for (i = 0; i < vinfo->num_attribs; i++) {
+ unsigned emit_sz = 0;
+ unsigned output_format = PIPE_FORMAT_NONE;
+ unsigned vs_output = vinfo->src_index[i];
+
+ switch (vinfo->emit[i]) {
+ case EMIT_4F:
+ output_format = PIPE_FORMAT_R32G32B32A32_FLOAT;
+ emit_sz = 4 * sizeof(float);
+ break;
+ case EMIT_3F:
+ output_format = PIPE_FORMAT_R32G32B32_FLOAT;
+ emit_sz = 3 * sizeof(float);
+ break;
+ case EMIT_2F:
+ output_format = PIPE_FORMAT_R32G32_FLOAT;
+ emit_sz = 2 * sizeof(float);
+ break;
+ case EMIT_1F:
+ output_format = PIPE_FORMAT_R32_FLOAT;
+ emit_sz = 1 * sizeof(float);
+ break;
+ case EMIT_1F_PSIZE:
+ need_psize = 1;
+ output_format = PIPE_FORMAT_R32_FLOAT;
+ emit_sz = 1 * sizeof(float);
+ vs_output = num_vs_outputs + 1;
+
+ break;
+ default:
+ assert(0);
+ break;
+ }
+
+ /* The elements in the key correspond to vertex shader output
+ * numbers, not to positions in the hw vertex description --
+ * that's handled by the output_offset field.
+ */
+ fse->key.element[vs_output].output_format = output_format;
+ fse->key.element[vs_output].output_offset = dst_offset;
+
+ dst_offset += emit_sz;
+ assert(fse->key.output_stride >= dst_offset);
+ }
+ }
+
+ /* To make psize work, really need to tell the vertex shader to
+ * copy that value from input->output. For 'translate' this was
+ * implicit for all elements.
+ */
+#if 0
+ if (need_psize) {
+ unsigned input = num_vs_inputs + 1;
+ const struct pipe_vertex_element *src = &draw->pt.vertex_element[i];
+ fse->key.element[i].input_format = PIPE_FORMAT_R32_FLOAT;
+ fse->key.element[i].input_buffer = 0; //nr_buffers + 1;
+ fse->key.element[i].input_offset = 0;
+
+ fse->key.nr_elements += 1;
+
+ }
+#endif
+
+ fse->constants = draw->pt.user.constants;
+
+ /* Would normally look up a vertex shader and peruse its list of
+ * varients somehow. We omitted that step and put all the
+ * hardcoded "shaders" into an array. We're just making the
+ * assumption that this happens to be a matching shader... ie
+ * you're running isosurf, aren't you?
+ */
+ fse->active = NULL;
+ for (i = 0; i < fse->nr_shaders; i++) {
+ if (translate_key_compare( &fse->key, &fse->shader[i].key) == 0)
+ fse->active = &fse->shader[i];
+ }
+
+ if (!fse->active) {
+ assert(0);
+ return ;
+ }
+
+ /* Now set buffer pointers:
+ */
+ for (i = 0; i < num_vs_inputs; i++) {
+ unsigned buf = draw->pt.vertex_element[i].vertex_buffer_index;
+
+ fse->src[i] = ((const ubyte *) draw->pt.user.vbuffer[buf] +
+ draw->pt.vertex_buffer[buf].buffer_offset +
+ draw->pt.vertex_element[i].src_offset);
+
+ fse->pitch[i] = draw->pt.vertex_buffer[buf].pitch;
+
+ }
+
+
+ //return TRUE;
+}
+
+
+
+
+
+
+
+static void fse_run_linear( struct draw_pt_middle_end *middle,
+ unsigned start,
+ unsigned count )
+{
+ struct fetch_shade_emit *fse = (struct fetch_shade_emit *)middle;
+ struct draw_context *draw = fse->draw;
+
+ char *hw_verts;
+
+ /* XXX: need to flush to get prim_vbuf.c to release its allocation??
+ */
+ draw_do_flush( draw, DRAW_FLUSH_BACKEND );
+
+ hw_verts = draw->render->allocate_vertices( draw->render,
+ (ushort)fse->key.output_stride,
+ (ushort)count );
+
+ if (!hw_verts) {
+ assert(0);
+ return;
+ }
+
+ /* Single routine to fetch vertices, run shader and emit HW verts.
+ * Clipping and viewport transformation are done elsewhere --
+ * either by the API or on hardware, or for some other reason not
+ * required...
+ */
+ fse->active->run_linear( fse,
+ start, count,
+ hw_verts );
+
+ /* Draw arrays path to avoid re-emitting index list again and
+ * again.
+ */
+ draw->render->draw_arrays( draw->render,
+ 0,
+ count );
+
+
+ draw->render->release_vertices( draw->render,
+ hw_verts,
+ fse->key.output_stride,
+ count );
+}
+
+
+static void
+fse_run(struct draw_pt_middle_end *middle,
+ const unsigned *fetch_elts,
+ unsigned fetch_count,
+ const ushort *draw_elts,
+ unsigned draw_count )
+{
+ struct fetch_shade_emit *fse = (struct fetch_shade_emit *)middle;
+ struct draw_context *draw = fse->draw;
+ void *hw_verts;
+
+ /* XXX: need to flush to get prim_vbuf.c to release its allocation??
+ */
+ draw_do_flush( draw, DRAW_FLUSH_BACKEND );
+
+ hw_verts = draw->render->allocate_vertices( draw->render,
+ (ushort)fse->key.output_stride,
+ (ushort)fetch_count );
+ if (!hw_verts) {
+ assert(0);
+ return;
+ }
+
+
+ /* Single routine to fetch vertices, run shader and emit HW verts.
+ */
+ fse->active->run_elts( fse,
+ fetch_elts,
+ fetch_count,
+ hw_verts );
+
+ draw->render->draw( draw->render,
+ draw_elts,
+ draw_count );
+
+ draw->render->release_vertices( draw->render,
+ hw_verts,
+ fse->key.output_stride,
+ fetch_count );
+
+}
+
+
+static void fse_finish( struct draw_pt_middle_end *middle )
+{
+}
+
+
+static void
+fse_destroy( struct draw_pt_middle_end *middle )
+{
+ FREE(middle);
+}
+
+struct draw_pt_middle_end *draw_pt_middle_fse( struct draw_context *draw )
+{
+ struct fetch_shade_emit *fse = CALLOC_STRUCT(fetch_shade_emit);
+ if (!fse)
+ return NULL;
+
+ fse->base.prepare = fse_prepare;
+ fse->base.run = fse_run;
+ fse->base.run_linear = fse_run_linear;
+ fse->base.finish = fse_finish;
+ fse->base.destroy = fse_destroy;
+ fse->draw = draw;
+
+ fse->shader[0].run_linear = shader0_run_linear;
+ fse->shader[0].run_elts = shader0_run_elts;
+ fse->shader[0].key.nr_elements = 3;
+ fse->shader[0].key.output_stride = 12 * sizeof(float);
+
+ fse->shader[0].key.element[0].input_format = PIPE_FORMAT_R32G32B32_FLOAT;
+ fse->shader[0].key.element[0].input_buffer = 0;
+ fse->shader[0].key.element[0].input_offset = 0;
+ fse->shader[0].key.element[0].output_format = PIPE_FORMAT_R32G32B32A32_FLOAT;
+ fse->shader[0].key.element[0].output_offset = 0;
+
+ fse->shader[0].key.element[1].input_format = PIPE_FORMAT_R32G32B32_FLOAT;
+ fse->shader[0].key.element[1].input_buffer = 0;
+ fse->shader[0].key.element[1].input_offset = 0;
+ fse->shader[0].key.element[1].output_format = PIPE_FORMAT_R32G32B32A32_FLOAT;
+ fse->shader[0].key.element[1].output_offset = 16;
+
+ fse->shader[0].key.element[1].input_format = PIPE_FORMAT_R32G32_FLOAT;
+ fse->shader[0].key.element[1].input_buffer = 0;
+ fse->shader[0].key.element[1].input_offset = 0;
+ fse->shader[0].key.element[1].output_format = PIPE_FORMAT_R32G32B32A32_FLOAT;
+ fse->shader[0].key.element[1].output_offset = 32;
+
+ fse->shader[1].run_linear = shader1_run_linear;
+ fse->shader[1].run_elts = shader1_run_elts;
+ fse->shader[1].key.nr_elements = 2;
+ fse->shader[1].key.output_stride = 8 * sizeof(float);
+
+ fse->shader[1].key.element[0].input_format = PIPE_FORMAT_R32G32B32_FLOAT;
+ fse->shader[1].key.element[0].input_buffer = 0;
+ fse->shader[1].key.element[0].input_offset = 0;
+ fse->shader[1].key.element[0].output_format = PIPE_FORMAT_R32G32B32A32_FLOAT;
+ fse->shader[1].key.element[0].output_offset = 0;
+
+ fse->shader[1].key.element[1].input_format = PIPE_FORMAT_R32G32B32_FLOAT;
+ fse->shader[1].key.element[1].input_buffer = 0;
+ fse->shader[1].key.element[1].input_offset = 0;
+ fse->shader[1].key.element[1].output_format = PIPE_FORMAT_R32G32B32A32_FLOAT;
+ fse->shader[1].key.element[1].output_offset = 16;
+
+ fse->shader[2].run_linear = shader2_run_linear;
+ fse->shader[2].run_elts = shader2_run_elts;
+ fse->shader[2].key.nr_elements = 3;
+ fse->shader[2].key.output_stride = 9 * sizeof(float);
+
+ fse->shader[2].key.element[0].input_format = PIPE_FORMAT_R32G32B32_FLOAT;
+ fse->shader[2].key.element[0].input_buffer = 0;
+ fse->shader[2].key.element[0].input_offset = 0;
+ fse->shader[2].key.element[0].output_format = PIPE_FORMAT_R32G32B32A32_FLOAT;
+ fse->shader[2].key.element[0].output_offset = 0;
+
+ fse->shader[2].key.element[1].input_format = PIPE_FORMAT_R32G32B32_FLOAT;
+ fse->shader[2].key.element[1].input_buffer = 0;
+ fse->shader[2].key.element[1].input_offset = 0;
+ fse->shader[2].key.element[1].output_format = PIPE_FORMAT_R32G32B32A32_FLOAT;
+ fse->shader[2].key.element[1].output_offset = 16;
+
+ /* psize is special
+ * -- effectively add it here as another input!?!
+ * -- who knows how to add it as a buffer?
+ */
+ fse->shader[2].key.element[2].input_format = PIPE_FORMAT_R32_FLOAT;
+ fse->shader[2].key.element[2].input_buffer = 0;
+ fse->shader[2].key.element[2].input_offset = 0;
+ fse->shader[2].key.element[2].output_format = PIPE_FORMAT_R32_FLOAT;
+ fse->shader[2].key.element[2].output_offset = 32;
+
+ fse->nr_shaders = 3;
+
+ return &fse->base;
+}
diff --git a/src/gallium/auxiliary/draw/draw_pt_util.c b/src/gallium/auxiliary/draw/draw_pt_util.c
new file mode 100644
index 0000000000..32c8a9632c
--- /dev/null
+++ b/src/gallium/auxiliary/draw/draw_pt_util.c
@@ -0,0 +1,103 @@
+/**************************************************************************
+ *
+ * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+ /*
+ * Authors:
+ * Keith Whitwell <keith@tungstengraphics.com>
+ */
+
+#include "pipe/p_util.h"
+#include "draw/draw_context.h"
+#include "draw/draw_private.h"
+#include "draw/draw_pt.h"
+
+void draw_pt_split_prim(unsigned prim, unsigned *first, unsigned *incr)
+{
+ switch (prim) {
+ case PIPE_PRIM_POINTS:
+ *first = 1;
+ *incr = 1;
+ break;
+ case PIPE_PRIM_LINES:
+ *first = 2;
+ *incr = 2;
+ break;
+ case PIPE_PRIM_LINE_STRIP:
+ case PIPE_PRIM_LINE_LOOP:
+ *first = 2;
+ *incr = 1;
+ break;
+ case PIPE_PRIM_TRIANGLES:
+ *first = 3;
+ *incr = 3;
+ break;
+ case PIPE_PRIM_TRIANGLE_STRIP:
+ case PIPE_PRIM_TRIANGLE_FAN:
+ case PIPE_PRIM_POLYGON:
+ *first = 3;
+ *incr = 1;
+ break;
+ case PIPE_PRIM_QUADS:
+ *first = 4;
+ *incr = 4;
+ break;
+ case PIPE_PRIM_QUAD_STRIP:
+ *first = 4;
+ *incr = 2;
+ break;
+ default:
+ assert(0);
+ *first = 0;
+ *incr = 1; /* set to one so that count % incr works */
+ break;
+ }
+}
+
+
+unsigned draw_pt_reduced_prim(unsigned prim)
+{
+ switch (prim) {
+ case PIPE_PRIM_POINTS:
+ return PIPE_PRIM_POINTS;
+ case PIPE_PRIM_LINES:
+ case PIPE_PRIM_LINE_STRIP:
+ case PIPE_PRIM_LINE_LOOP:
+ return PIPE_PRIM_LINES;
+ case PIPE_PRIM_TRIANGLES:
+ case PIPE_PRIM_TRIANGLE_STRIP:
+ case PIPE_PRIM_TRIANGLE_FAN:
+ case PIPE_PRIM_POLYGON:
+ case PIPE_PRIM_QUADS:
+ case PIPE_PRIM_QUAD_STRIP:
+ return PIPE_PRIM_TRIANGLES;
+ default:
+ assert(0);
+ return PIPE_PRIM_POINTS;
+ }
+}
+
+
diff --git a/src/gallium/auxiliary/draw/draw_pt_varray.c b/src/gallium/auxiliary/draw/draw_pt_varray.c
index 355093f945..06fd866ccd 100644
--- a/src/gallium/auxiliary/draw/draw_pt_varray.c
+++ b/src/gallium/auxiliary/draw/draw_pt_varray.c
@@ -43,6 +43,8 @@ struct varray_frontend {
unsigned draw_count;
unsigned fetch_count;
+ unsigned fetch_start;
+
struct draw_pt_middle_end *middle;
unsigned input_prim;
@@ -56,6 +58,11 @@ static void varray_flush(struct varray_frontend *varray)
debug_printf("FLUSH fc = %d, dc = %d\n",
varray->fetch_count,
varray->draw_count);
+ debug_printf("\telt0 = %d, eltx = %d, draw0 = %d, drawx = %d\n",
+ varray->fetch_elts[0],
+ varray->fetch_elts[varray->fetch_count-1],
+ varray->draw_elts[0],
+ varray->draw_elts[varray->draw_count-1]);
#endif
varray->middle->run(varray->middle,
varray->fetch_elts,
@@ -68,20 +75,43 @@ static void varray_flush(struct varray_frontend *varray)
varray->draw_count = 0;
}
-#if 0
-static void varray_check_flush(struct varray_frontend *varray)
+static void varray_flush_linear(struct varray_frontend *varray,
+ unsigned start, unsigned count)
{
- if (varray->draw_count + 6 >= DRAW_MAX/* ||
- varray->fetch_count + 4 >= FETCH_MAX*/) {
- varray_flush(varray);
+ if (count) {
+#if 0
+ debug_printf("FLUSH LINEAR start = %d, count = %d\n",
+ start,
+ count);
+#endif
+ assert(varray->middle->run_linear);
+ varray->middle->run_linear(varray->middle, start, count);
}
}
+
+static INLINE void fetch_init(struct varray_frontend *varray,
+ unsigned count)
+{
+ unsigned idx;
+#if 0
+ debug_printf("FETCH INIT c = %d, fs = %d\n",
+ count,
+ varray->fetch_start);
#endif
+ for (idx = 0; idx < count; ++idx) {
+ varray->fetch_elts[idx] = varray->fetch_start + idx;
+ }
+ varray->fetch_start += idx;
+ varray->fetch_count = idx;
+}
+
+
+
static INLINE void add_draw_el(struct varray_frontend *varray,
- int idx, ushort flags)
+ int idx)
{
- varray->draw_elts[varray->draw_count++] = idx | flags;
+ varray->draw_elts[varray->draw_count++] = idx;
}
@@ -90,106 +120,52 @@ static INLINE void varray_triangle( struct varray_frontend *varray,
unsigned i1,
unsigned i2 )
{
- add_draw_el(varray, i0, 0);
- add_draw_el(varray, i1, 0);
- add_draw_el(varray, i2, 0);
-}
-
-static INLINE void varray_triangle_flags( struct varray_frontend *varray,
- ushort flags,
- unsigned i0,
- unsigned i1,
- unsigned i2 )
-{
- add_draw_el(varray, i0, flags);
- add_draw_el(varray, i1, 0);
- add_draw_el(varray, i2, 0);
+ add_draw_el(varray, i0);
+ add_draw_el(varray, i1);
+ add_draw_el(varray, i2);
}
static INLINE void varray_line( struct varray_frontend *varray,
unsigned i0,
unsigned i1 )
{
- add_draw_el(varray, i0, 0);
- add_draw_el(varray, i1, 0);
-}
-
-
-static INLINE void varray_line_flags( struct varray_frontend *varray,
- ushort flags,
- unsigned i0,
- unsigned i1 )
-{
- add_draw_el(varray, i0, flags);
- add_draw_el(varray, i1, 0);
+ add_draw_el(varray, i0);
+ add_draw_el(varray, i1);
}
static INLINE void varray_point( struct varray_frontend *varray,
unsigned i0 )
{
- add_draw_el(varray, i0, 0);
-}
-
-static INLINE void varray_quad( struct varray_frontend *varray,
- unsigned i0,
- unsigned i1,
- unsigned i2,
- unsigned i3 )
-{
- varray_triangle( varray, i0, i1, i3 );
- varray_triangle( varray, i1, i2, i3 );
-}
-
-static INLINE void varray_ef_quad( struct varray_frontend *varray,
- unsigned i0,
- unsigned i1,
- unsigned i2,
- unsigned i3 )
-{
- const unsigned omitEdge1 = DRAW_PIPE_EDGE_FLAG_0 | DRAW_PIPE_EDGE_FLAG_2;
- const unsigned omitEdge2 = DRAW_PIPE_EDGE_FLAG_0 | DRAW_PIPE_EDGE_FLAG_1;
-
- varray_triangle_flags( varray,
- DRAW_PIPE_RESET_STIPPLE | omitEdge1,
- i0, i1, i3 );
-
- varray_triangle_flags( varray,
- omitEdge2,
- i1, i2, i3 );
+ add_draw_el(varray, i0);
}
-/* At least for now, we're back to using a template include file for
- * this. The two paths aren't too different though - it may be
- * possible to reunify them.
- */
-#define TRIANGLE(vc,flags,i0,i1,i2) varray_triangle_flags(vc,flags,i0,i1,i2)
-#define QUAD(vc,i0,i1,i2,i3) varray_ef_quad(vc,i0,i1,i2,i3)
-#define LINE(vc,flags,i0,i1) varray_line_flags(vc,flags,i0,i1)
-#define POINT(vc,i0) varray_point(vc,i0)
-#define FUNC varray_run_extras
-#include "draw_pt_varray_tmp.h"
-#define TRIANGLE(vc,flags,i0,i1,i2) varray_triangle(vc,i0,i1,i2)
-#define QUAD(vc,i0,i1,i2,i3) varray_quad(vc,i0,i1,i2,i3)
-#define LINE(vc,flags,i0,i1) varray_line(vc,i0,i1)
+#if 0
+#define TRIANGLE(flags,i0,i1,i2) varray_triangle(varray,i0,i1,i2)
+#define LINE(flags,i0,i1) varray_line(varray,i0,i1)
+#define POINT(i0) varray_point(varray,i0)
+#define FUNC varray_decompose
+#include "draw_pt_decompose.h"
+#else
+#define TRIANGLE(vc,i0,i1,i2) varray_triangle(vc,i0,i1,i2)
+#define LINE(vc,i0,i1) varray_line(vc,i0,i1)
#define POINT(vc,i0) varray_point(vc,i0)
#define FUNC varray_run
-#include "draw_pt_varray_tmp.h"
-
-
+#include "draw_pt_varray_tmp_linear.h"
+#endif
-static unsigned reduced_prim[PIPE_PRIM_POLYGON + 1] = {
+static unsigned decompose_prim[PIPE_PRIM_POLYGON + 1] = {
PIPE_PRIM_POINTS,
PIPE_PRIM_LINES,
- PIPE_PRIM_LINES,
- PIPE_PRIM_LINES,
+ PIPE_PRIM_LINE_STRIP,
+ PIPE_PRIM_LINES, /* decomposed */
PIPE_PRIM_TRIANGLES,
- PIPE_PRIM_TRIANGLES,
- PIPE_PRIM_TRIANGLES,
- PIPE_PRIM_TRIANGLES,
- PIPE_PRIM_TRIANGLES,
- PIPE_PRIM_TRIANGLES
+ PIPE_PRIM_TRIANGLE_STRIP,
+ PIPE_PRIM_TRIANGLES, /* decomposed */
+ PIPE_PRIM_QUADS,
+ PIPE_PRIM_QUAD_STRIP,
+ PIPE_PRIM_TRIANGLES /* decomposed */
};
@@ -201,17 +177,10 @@ static void varray_prepare(struct draw_pt_front_end *frontend,
{
struct varray_frontend *varray = (struct varray_frontend *)frontend;
- if (opt & PT_PIPELINE)
- {
- varray->base.run = varray_run_extras;
- }
- else
- {
- varray->base.run = varray_run;
- }
+ varray->base.run = varray_run;
varray->input_prim = prim;
- varray->output_prim = reduced_prim[prim];
+ varray->output_prim = decompose_prim[prim];
varray->middle = middle;
middle->prepare(middle, varray->output_prim, opt);
diff --git a/src/gallium/auxiliary/draw/draw_pt_varray_tmp.h b/src/gallium/auxiliary/draw/draw_pt_varray_tmp.h
index b9a319b253..6979f6b544 100644
--- a/src/gallium/auxiliary/draw/draw_pt_varray_tmp.h
+++ b/src/gallium/auxiliary/draw/draw_pt_varray_tmp.h
@@ -10,32 +10,44 @@ static void FUNC(struct draw_pt_front_end *frontend,
boolean flatfirst = (draw->rasterizer->flatshade &&
draw->rasterizer->flatshade_first);
- unsigned i, flags;
+ unsigned i, j, flags;
+ unsigned first, incr;
+
+ varray->fetch_start = start;
+
+ draw_pt_split_prim(varray->input_prim, &first, &incr);
#if 0
- debug_printf("%s (%d) %d/%d\n", __FUNCTION__, draw->prim, start, count);
-#endif
-#if 0
- debug_printf("INPUT PRIM = %d (start = %d, count = %d)\n", varray->input_prim,
+ debug_printf("%s (%d) %d/%d\n", __FUNCTION__,
+ varray->input_prim,
start, count);
#endif
- for (i = 0; i < count; ++i) {
- varray->fetch_elts[i] = start + i;
- }
- varray->fetch_count = count;
-
switch (varray->input_prim) {
case PIPE_PRIM_POINTS:
- for (i = 0; i < count; i ++) {
- POINT(varray, i + 0);
+ for (j = 0; j + first <= count; j += i) {
+ unsigned end = MIN2(FETCH_MAX, count - j);
+ end -= (end % incr);
+ for (i = 0; i < end; i++) {
+ POINT(varray, i + 0);
+ }
+ i = end;
+ fetch_init(varray, end);
+ varray_flush(varray);
}
break;
case PIPE_PRIM_LINES:
- for (i = 0; i+1 < count; i += 2) {
- LINE(varray, DRAW_PIPE_RESET_STIPPLE,
- i + 0, i + 1);
+ for (j = 0; j + first <= count; j += i) {
+ unsigned end = MIN2(FETCH_MAX, count - j);
+ end -= (end % incr);
+ for (i = 0; i+1 < end; i += 2) {
+ LINE(varray, DRAW_PIPE_RESET_STIPPLE,
+ i + 0, i + 1);
+ }
+ i = end;
+ fetch_init(varray, end);
+ varray_flush(varray);
}
break;
@@ -43,38 +55,81 @@ static void FUNC(struct draw_pt_front_end *frontend,
if (count >= 2) {
flags = DRAW_PIPE_RESET_STIPPLE;
- for (i = 1; i < count; i++, flags = 0) {
- LINE(varray, flags, i - 1, i);
+ for (j = 0; j + first <= count; j += i) {
+ unsigned end = MIN2(FETCH_MAX, count - j);
+ end -= (end % incr);
+ for (i = 1; i < end; i++, flags = 0) {
+ LINE(varray, flags, i - 1, i);
+ }
+ LINE(varray, flags, i - 1, 0);
+ i = end;
+ fetch_init(varray, end);
+ varray_flush(varray);
}
- LINE(varray, flags, i - 1, 0);
}
break;
case PIPE_PRIM_LINE_STRIP:
flags = DRAW_PIPE_RESET_STIPPLE;
- for (i = 1; i < count; i++, flags = 0) {
- LINE(varray, flags, i - 1, i);
+ for (j = 0; j + first <= count; j += i) {
+ unsigned end = MIN2(FETCH_MAX, count - j);
+ end -= (end % incr);
+ for (i = 1; i < end; i++, flags = 0) {
+ LINE(varray, flags, i - 1, i);
+ }
+ i = end;
+ fetch_init(varray, end);
+ varray_flush(varray);
}
break;
case PIPE_PRIM_TRIANGLES:
- for (i = 0; i+2 < count; i += 3) {
- TRIANGLE(varray, DRAW_PIPE_RESET_STIPPLE | DRAW_PIPE_EDGE_FLAG_ALL,
- i + 0, i + 1, i + 2);
+ for (j = 0; j + first <= count; j += i) {
+ unsigned end = MIN2(FETCH_MAX, count - j);
+ end -= (end % incr);
+ for (i = 0; i+2 < end; i += 3) {
+ TRIANGLE(varray, DRAW_PIPE_RESET_STIPPLE | DRAW_PIPE_EDGE_FLAG_ALL,
+ i + 0, i + 1, i + 2);
+ }
+ i = end;
+ fetch_init(varray, end);
+ varray_flush(varray);
}
break;
case PIPE_PRIM_TRIANGLE_STRIP:
if (flatfirst) {
- for (i = 0; i+2 < count; i++) {
- TRIANGLE(varray, DRAW_PIPE_RESET_STIPPLE | DRAW_PIPE_EDGE_FLAG_ALL,
- i + 0, i + 1 + (i&1), i + 2 - (i&1));
+ for (j = 0; j + first <= count; j += i) {
+ unsigned end = MIN2(FETCH_MAX, count - j);
+ end -= (end % incr);
+ for (i = 0; i+2 < end; i++) {
+ TRIANGLE(varray, DRAW_PIPE_RESET_STIPPLE | DRAW_PIPE_EDGE_FLAG_ALL,
+ i + 0, i + 1 + (i&1), i + 2 - (i&1));
+ }
+ i = end;
+ fetch_init(varray, end);
+ varray_flush(varray);
+ if (j + first + i <= count) {
+ varray->fetch_start -= 2;
+ i -= 2;
+ }
}
}
else {
- for (i = 0; i+2 < count; i++) {
- TRIANGLE(varray, DRAW_PIPE_RESET_STIPPLE | DRAW_PIPE_EDGE_FLAG_ALL,
- i + 0 + (i&1), i + 1 - (i&1), i + 2);
+ for (j = 0; j + first <= count; j += i) {
+ unsigned end = MIN2(FETCH_MAX, count - j);
+ end -= (end % incr);
+ for (i = 0; i + 2 < end; i++) {
+ TRIANGLE(varray, DRAW_PIPE_RESET_STIPPLE | DRAW_PIPE_EDGE_FLAG_ALL,
+ i + 0 + (i&1), i + 1 - (i&1), i + 2);
+ }
+ i = end;
+ fetch_init(varray, end);
+ varray_flush(varray);
+ if (j + first + i <= count) {
+ varray->fetch_start -= 2;
+ i -= 2;
+ }
}
}
break;
@@ -83,51 +138,89 @@ static void FUNC(struct draw_pt_front_end *frontend,
if (count >= 3) {
if (flatfirst) {
flags = DRAW_PIPE_RESET_STIPPLE | DRAW_PIPE_EDGE_FLAG_ALL;
- for (i = 0; i+2 < count; i++) {
- TRIANGLE(varray, flags, i + 1, i + 2, 0);
+ for (j = 0; j + first <= count; j += i) {
+ unsigned end = MIN2(FETCH_MAX, count - j);
+ end -= (end % incr);
+ for (i = 0; i+2 < end; i++) {
+ TRIANGLE(varray, flags, i + 1, i + 2, 0);
+ }
+ i = end;
+ fetch_init(varray, end);
+ varray_flush(varray);
}
}
else {
flags = DRAW_PIPE_RESET_STIPPLE | DRAW_PIPE_EDGE_FLAG_ALL;
- for (i = 0; i+2 < count; i++) {
- TRIANGLE(varray, flags, 0, i + 1, i + 2);
+ for (j = 0; j + first <= count; j += i) {
+ unsigned end = MIN2(FETCH_MAX, count - j);
+ end -= (end % incr);
+ for (i = 0; i+2 < end; i++) {
+ TRIANGLE(varray, flags, 0, i + 1, i + 2);
+ }
+ i = end;
+ fetch_init(varray, end);
+ varray_flush(varray);
}
}
}
break;
case PIPE_PRIM_QUADS:
- for (i = 0; i+3 < count; i += 4) {
- QUAD(varray, i + 0, i + 1, i + 2, i + 3);
+ for (j = 0; j + first <= count; j += i) {
+ unsigned end = MIN2(FETCH_MAX, count - j);
+ end -= (end % incr);
+ for (i = 0; i+3 < end; i += 4) {
+ QUAD(varray, i + 0, i + 1, i + 2, i + 3);
+ }
+ i = end;
+ fetch_init(varray, end);
+ varray_flush(varray);
}
break;
case PIPE_PRIM_QUAD_STRIP:
- for (i = 0; i+3 < count; i += 2) {
- QUAD(varray, i + 2, i + 0, i + 1, i + 3);
+ for (j = 0; j + first <= count; j += i) {
+ unsigned end = MIN2(FETCH_MAX, count - j);
+ end -= (end % incr);
+ for (i = 0; i+3 < end; i += 2) {
+ QUAD(varray, i + 2, i + 0, i + 1, i + 3);
+ }
+ i = end;
+ fetch_init(varray, end);
+ varray_flush(varray);
+ if (j + first + i <= count) {
+ varray->fetch_start -= 2;
+ i -= 2;
+ }
}
break;
case PIPE_PRIM_POLYGON:
{
- /* These bitflags look a little odd because we submit the
- * vertices as (1,2,0) to satisfy flatshade requirements.
- */
- const unsigned edge_first = DRAW_PIPE_EDGE_FLAG_2;
- const unsigned edge_middle = DRAW_PIPE_EDGE_FLAG_0;
- const unsigned edge_last = DRAW_PIPE_EDGE_FLAG_1;
-
- flags = DRAW_PIPE_RESET_STIPPLE | edge_first | edge_middle;
-
- for (i = 0; i+2 < count; i++, flags = edge_middle) {
+ /* These bitflags look a little odd because we submit the
+ * vertices as (1,2,0) to satisfy flatshade requirements.
+ */
+ const unsigned edge_first = DRAW_PIPE_EDGE_FLAG_2;
+ const unsigned edge_middle = DRAW_PIPE_EDGE_FLAG_0;
+ const unsigned edge_last = DRAW_PIPE_EDGE_FLAG_1;
+
+ flags = DRAW_PIPE_RESET_STIPPLE | edge_first | edge_middle;
+ for (j = 0; j + first <= count; j += i) {
+ unsigned end = MIN2(FETCH_MAX, count - j);
+ end -= (end % incr);
+ for (i = 0; i+2 < end; i++, flags = edge_middle) {
if (i + 3 == count)
flags |= edge_last;
- TRIANGLE(varray, flags, i + 1, i + 2, 0);
- }
+ TRIANGLE(varray, flags, i + 1, i + 2, 0);
+ }
+ i = end;
+ fetch_init(varray, end);
+ varray_flush(varray);
}
- break;
+ }
+ break;
default:
assert(0);
diff --git a/src/gallium/auxiliary/draw/draw_pt_varray_tmp_linear.h b/src/gallium/auxiliary/draw/draw_pt_varray_tmp_linear.h
new file mode 100644
index 0000000000..114ed371a0
--- /dev/null
+++ b/src/gallium/auxiliary/draw/draw_pt_varray_tmp_linear.h
@@ -0,0 +1,94 @@
+static unsigned trim( unsigned count, unsigned first, unsigned incr )
+{
+ return count - (count - first) % incr;
+}
+
+static void FUNC(struct draw_pt_front_end *frontend,
+ pt_elt_func get_elt,
+ const void *elts,
+ unsigned count)
+{
+ struct varray_frontend *varray = (struct varray_frontend *)frontend;
+ unsigned start = (unsigned)elts;
+
+ unsigned i, j;
+ unsigned first, incr;
+
+ varray->fetch_start = start;
+
+ draw_pt_split_prim(varray->input_prim, &first, &incr);
+
+ /* Sanitize primitive length:
+ */
+ count = trim(count, first, incr);
+ if (count < first)
+ return;
+
+#if 0
+ debug_printf("%s (%d) %d/%d\n", __FUNCTION__,
+ varray->input_prim,
+ start, count);
+#endif
+
+ switch (varray->input_prim) {
+ case PIPE_PRIM_POINTS:
+ case PIPE_PRIM_LINES:
+ case PIPE_PRIM_TRIANGLES:
+ case PIPE_PRIM_LINE_STRIP:
+ case PIPE_PRIM_TRIANGLE_STRIP:
+ case PIPE_PRIM_QUADS:
+ case PIPE_PRIM_QUAD_STRIP:
+ for (j = 0; j < count;) {
+ unsigned remaining = count - j;
+ unsigned nr = trim( MIN2(FETCH_MAX, remaining), first, incr );
+ varray_flush_linear(varray, start + j, nr);
+ j += nr;
+ if (nr != remaining)
+ j -= (first - incr);
+ }
+ break;
+
+ case PIPE_PRIM_LINE_LOOP:
+ if (count >= 2) {
+ for (j = 0; j + first <= count; j += i) {
+ unsigned end = MIN2(FETCH_MAX, count - j);
+ end -= (end % incr);
+ for (i = 1; i < end; i++) {
+ LINE(varray, i - 1, i);
+ }
+ LINE(varray, i - 1, 0);
+ i = end;
+ fetch_init(varray, end);
+ varray_flush(varray);
+ }
+ }
+ break;
+
+
+ case PIPE_PRIM_POLYGON:
+ case PIPE_PRIM_TRIANGLE_FAN:
+ for (j = 0; j + first <= count; j += i) {
+ unsigned end = MIN2(FETCH_MAX, count - j);
+ end -= (end % incr);
+ for (i = 2; i < end; i++) {
+ TRIANGLE(varray, 0, i - 1, i);
+ }
+ i = end;
+ fetch_init(varray, end);
+ varray_flush(varray);
+ }
+ break;
+
+ default:
+ assert(0);
+ break;
+ }
+
+ varray_flush(varray);
+}
+
+#undef TRIANGLE
+#undef QUAD
+#undef POINT
+#undef LINE
+#undef FUNC
diff --git a/src/gallium/auxiliary/draw/draw_pt_vcache.c b/src/gallium/auxiliary/draw/draw_pt_vcache.c
index 6b3fb1406b..6c17edba34 100644
--- a/src/gallium/auxiliary/draw/draw_pt_vcache.c
+++ b/src/gallium/auxiliary/draw/draw_pt_vcache.c
@@ -104,23 +104,11 @@ static INLINE void vcache_elt( struct vcache_frontend *vcache,
static void vcache_triangle( struct vcache_frontend *vcache,
+ ushort flags,
unsigned i0,
unsigned i1,
unsigned i2 )
{
- vcache_elt(vcache, i0, 0);
- vcache_elt(vcache, i1, 0);
- vcache_elt(vcache, i2, 0);
- vcache_check_flush(vcache);
-}
-
-
-static void vcache_triangle_flags( struct vcache_frontend *vcache,
- ushort flags,
- unsigned i0,
- unsigned i1,
- unsigned i2 )
-{
vcache_elt(vcache, i0, flags);
vcache_elt(vcache, i1, 0);
vcache_elt(vcache, i2, 0);
@@ -128,20 +116,10 @@ static void vcache_triangle_flags( struct vcache_frontend *vcache,
}
static void vcache_line( struct vcache_frontend *vcache,
+ ushort flags,
unsigned i0,
unsigned i1 )
{
- vcache_elt(vcache, i0, 0);
- vcache_elt(vcache, i1, 0);
- vcache_check_flush(vcache);
-}
-
-
-static void vcache_line_flags( struct vcache_frontend *vcache,
- ushort flags,
- unsigned i0,
- unsigned i1 )
-{
vcache_elt(vcache, i0, flags);
vcache_elt(vcache, i1, 0);
vcache_check_flush(vcache);
@@ -161,61 +139,65 @@ static void vcache_quad( struct vcache_frontend *vcache,
unsigned i2,
unsigned i3 )
{
- vcache_triangle( vcache, i0, i1, i3 );
- vcache_triangle( vcache, i1, i2, i3 );
-}
-
-static void vcache_ef_quad( struct vcache_frontend *vcache,
- unsigned i0,
- unsigned i1,
- unsigned i2,
- unsigned i3 )
-{
- const unsigned omitEdge1 = DRAW_PIPE_EDGE_FLAG_0 | DRAW_PIPE_EDGE_FLAG_2;
- const unsigned omitEdge2 = DRAW_PIPE_EDGE_FLAG_0 | DRAW_PIPE_EDGE_FLAG_1;
-
- vcache_triangle_flags( vcache,
- DRAW_PIPE_RESET_STIPPLE | omitEdge1,
- i0, i1, i3 );
-
- vcache_triangle_flags( vcache,
- omitEdge2,
- i1, i2, i3 );
+ vcache_triangle( vcache,
+ ( DRAW_PIPE_RESET_STIPPLE |
+ DRAW_PIPE_EDGE_FLAG_0 |
+ DRAW_PIPE_EDGE_FLAG_2 ),
+ i0, i1, i3 );
+
+ vcache_triangle( vcache,
+ ( DRAW_PIPE_EDGE_FLAG_0 |
+ DRAW_PIPE_EDGE_FLAG_1 ),
+ i1, i2, i3 );
}
/* At least for now, we're back to using a template include file for
* this. The two paths aren't too different though - it may be
* possible to reunify them.
*/
-#define TRIANGLE(vc,flags,i0,i1,i2) vcache_triangle_flags(vc,flags,i0,i1,i2)
-#define QUAD(vc,i0,i1,i2,i3) vcache_ef_quad(vc,i0,i1,i2,i3)
-#define LINE(vc,flags,i0,i1) vcache_line_flags(vc,flags,i0,i1)
-#define POINT(vc,i0) vcache_point(vc,i0)
-#define FUNC vcache_run_extras
-#include "draw_pt_vcache_tmp.h"
-
-#define TRIANGLE(vc,flags,i0,i1,i2) vcache_triangle(vc,i0,i1,i2)
-#define QUAD(vc,i0,i1,i2,i3) vcache_quad(vc,i0,i1,i2,i3)
-#define LINE(vc,flags,i0,i1) vcache_line(vc,i0,i1)
-#define POINT(vc,i0) vcache_point(vc,i0)
+#define TRIANGLE(flags,i0,i1,i2) \
+ vcache_triangle(vcache, \
+ flags, \
+ get_elt(elts,i0), \
+ get_elt(elts,i1), \
+ get_elt(elts,i2))
+
+#define QUAD(i0,i1,i2,i3) \
+ vcache_quad(vcache, \
+ get_elt(elts,i0), \
+ get_elt(elts,i1), \
+ get_elt(elts,i2), \
+ get_elt(elts,i3))
+
+#define LINE(flags,i0,i1) \
+ vcache_line(vcache, \
+ flags, \
+ get_elt(elts,i0), \
+ get_elt(elts,i1))
+
+#define POINT(i0) \
+ vcache_point(vcache, \
+ get_elt(elts,i0))
+
#define FUNC vcache_run
-#include "draw_pt_vcache_tmp.h"
+#define ARGS \
+ struct draw_pt_front_end *frontend, \
+ pt_elt_func get_elt, \
+ const void *elts
+#define LOCAL_VARS \
+ struct vcache_frontend *vcache = (struct vcache_frontend *)frontend; \
+ struct draw_context *draw = vcache->draw; \
+ boolean flatfirst = (draw->rasterizer->flatshade && \
+ draw->rasterizer->flatshade_first); \
+ unsigned prim = vcache->input_prim; \
+ unsigned i, flags;
+#define FLUSH vcache_flush( vcache )
+
+#include "draw_pt_decompose.h"
-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
-};
@@ -226,17 +208,9 @@ static void vcache_prepare( struct draw_pt_front_end *frontend,
{
struct vcache_frontend *vcache = (struct vcache_frontend *)frontend;
- if (opt & PT_PIPELINE)
- {
- vcache->base.run = vcache_run_extras;
- }
- else
- {
- vcache->base.run = vcache_run;
- }
-
+ vcache->base.run = vcache_run;
vcache->input_prim = prim;
- vcache->output_prim = reduced_prim[prim];
+ vcache->output_prim = draw_pt_reduced_prim(prim);
vcache->middle = middle;
middle->prepare( middle, vcache->output_prim, opt );