summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBrian <[email protected]>2008-03-13 17:10:28 -0600
committerBrian <[email protected]>2008-03-13 17:10:28 -0600
commitd088d640fca415261a208d3cbede94a6522ebb6b (patch)
tree58c6ff82993089556ed15938c87c4f7201867368
parent5bae5871f03c96eb173cb55d7e8a846a2c4bd4a0 (diff)
gallium: plug in vertex passthrough code
Based on a patch from Zack. Basically, implement a new draw_arrays function that copies the incoming user-vertices to the hardware vertex buffer, doing format/type conversion as needed. The vertex fetch/store code is totally temporary for now.
-rw-r--r--src/gallium/auxiliary/draw/Makefile1
-rw-r--r--src/gallium/auxiliary/draw/SConscript1
-rw-r--r--src/gallium/auxiliary/draw/draw_passthrough.c106
-rw-r--r--src/gallium/auxiliary/draw/draw_prim.c47
4 files changed, 147 insertions, 8 deletions
diff --git a/src/gallium/auxiliary/draw/Makefile b/src/gallium/auxiliary/draw/Makefile
index 2daa1636f36..21e9f737b77 100644
--- a/src/gallium/auxiliary/draw/Makefile
+++ b/src/gallium/auxiliary/draw/Makefile
@@ -15,6 +15,7 @@ C_SOURCES = \
draw_debug.c \
draw_flatshade.c \
draw_offset.c \
+ draw_passthrough.c \
draw_prim.c \
draw_pstipple.c \
draw_stipple.c \
diff --git a/src/gallium/auxiliary/draw/SConscript b/src/gallium/auxiliary/draw/SConscript
index 5cb7664c85d..64b444dbd56 100644
--- a/src/gallium/auxiliary/draw/SConscript
+++ b/src/gallium/auxiliary/draw/SConscript
@@ -15,6 +15,7 @@ draw = env.ConvenienceLibrary(
'draw_flatshade.c',
'draw_offset.c',
'draw_prim.c',
+ 'draw_passthrough.c',
'draw_pstipple.c',
'draw_passthrough.c',
'draw_stipple.c',
diff --git a/src/gallium/auxiliary/draw/draw_passthrough.c b/src/gallium/auxiliary/draw/draw_passthrough.c
index a51fa0ab23c..d16f056191c 100644
--- a/src/gallium/auxiliary/draw/draw_passthrough.c
+++ b/src/gallium/auxiliary/draw/draw_passthrough.c
@@ -66,6 +66,95 @@
#include "draw/draw_vertex.h"
+/**
+ * General-purpose fetch from user's vertex arrays, emit to driver's
+ * vertex buffer.
+ *
+ * XXX this is totally temporary.
+ */
+static void
+fetch_store_general( struct draw_context *draw,
+ float *out,
+ unsigned start,
+ unsigned count )
+{
+ const struct vertex_info *vinfo = draw->render->get_vertex_info(draw->render);
+ const unsigned nr_attrs = vinfo->num_attribs;
+ uint i, j;
+
+ const unsigned *pitch = draw->vertex_fetch.pitch;
+ const ubyte **src = draw->vertex_fetch.src_ptr;
+
+ for (i = start; i < count; i++) {
+ for (j = 0; j < nr_attrs; j++) {
+ const uint jj = vinfo->src_index[j];
+ const enum pipe_format srcFormat = draw->vertex_element[jj].src_format;
+ const ubyte *from = src[jj] + i * pitch[jj];
+ float attrib[4];
+
+ switch (srcFormat) {
+ case PIPE_FORMAT_R32G32B32A32_FLOAT:
+ {
+ float *f = (float *) from;
+ attrib[0] = f[0];
+ attrib[1] = f[1];
+ attrib[2] = f[2];
+ attrib[3] = f[3];
+ }
+ break;
+ case PIPE_FORMAT_R32G32B32_FLOAT:
+ {
+ float *f = (float *) from;
+ attrib[0] = f[0];
+ attrib[1] = f[1];
+ attrib[2] = f[2];
+ attrib[3] = 1.0;
+ }
+ break;
+ case PIPE_FORMAT_R32G32_FLOAT:
+ {
+ float *f = (float *) from;
+ attrib[0] = f[0];
+ attrib[1] = f[1];
+ attrib[2] = 0.0;
+ attrib[3] = 1.0;
+ }
+ break;
+ case PIPE_FORMAT_R32_FLOAT:
+ {
+ float *f = (float *) from;
+ attrib[0] = f[0];
+ attrib[1] = 0.0;
+ attrib[2] = 0.0;
+ attrib[3] = 1.0;
+ }
+ break;
+ default:
+ abort();
+ }
+
+ /* XXX this will probably only work for softpipe */
+ switch (vinfo->emit[j]) {
+ case EMIT_HEADER:
+ memset(out, 0, sizeof(struct vertex_header));
+ out += sizeof(struct vertex_header) / 4;
+ break;
+ case EMIT_4F:
+ out[0] = attrib[0];
+ out[1] = attrib[1];
+ out[2] = attrib[2];
+ out[3] = attrib[3];
+ out += 4;
+ break;
+ default:
+ abort();
+ }
+
+ }
+ }
+}
+
+
/* Example of a fetch/emit passthrough shader which could be
* generated when bypass_clipping is enabled on a passthrough vertex
@@ -116,7 +205,6 @@ static void fetch_xyz_rgb_st( struct draw_context *draw,
}
}
-
static boolean update_shader( struct draw_context *draw )
{
const struct vertex_info *vinfo = draw->render->get_vertex_info(draw->render);
@@ -143,11 +231,15 @@ static boolean update_shader( struct draw_context *draw )
/* Just trying to figure out how this would work:
*/
- if (nr_attrs == 3 &&
- 0 /* some other tests */)
+ if (draw->rasterizer->bypass_vs ||
+ (nr_attrs == 3 && 0 /* some other tests */))
{
+#if 0
draw->vertex_fetch.pt_fetch = fetch_xyz_rgb_st;
- assert(vinfo->size == 10);
+#else
+ draw->vertex_fetch.pt_fetch = fetch_store_general;
+#endif
+ /*assert(vinfo->size == 10);*/
return TRUE;
}
@@ -175,7 +267,6 @@ static boolean set_prim( struct draw_context *draw,
}
-
boolean
draw_passthrough_arrays(struct draw_context *draw,
unsigned prim,
@@ -184,10 +275,13 @@ draw_passthrough_arrays(struct draw_context *draw,
{
float *hw_verts;
+ if (draw_need_pipeline(draw))
+ return FALSE;
+
if (!set_prim(draw, prim))
return FALSE;
- if (!update_shader( draw ))
+ if (!update_shader(draw))
return FALSE;
hw_verts = draw->render->allocate_vertices( draw->render,
diff --git a/src/gallium/auxiliary/draw/draw_prim.c b/src/gallium/auxiliary/draw/draw_prim.c
index 7d6cd43410c..ff71ba9b73c 100644
--- a/src/gallium/auxiliary/draw/draw_prim.c
+++ b/src/gallium/auxiliary/draw/draw_prim.c
@@ -31,6 +31,7 @@
*/
#include "pipe/p_debug.h"
+#include "pipe/p_util.h"
#include "draw_private.h"
#include "draw_context.h"
@@ -118,7 +119,42 @@ static void draw_prim_queue_flush( struct draw_context *draw )
draw_vertex_cache_unreference( draw );
}
+static INLINE void fetch_and_store(struct draw_context *draw)
+{
+ unsigned i;
+
+ /* run vertex shader on vertex cache entries, four per invokation */
+#if 0
+ {
+ const struct vertex_info *vinfo = draw->render->get_vertex_info(draw->render);
+ memcpy(draw->vs.queue[0].vertex, draw->vs.queue[i + j].elt,
+ count * vinfo->size);
+ }
+#elif 0
+ draw_update_vertex_fetch(draw);
+ for (i = 0; i < draw->vs.queue_nr; i += 4) {
+ struct vertex_header *dests[4];
+ unsigned elts[4];
+ struct tgsi_exec_machine *machine = &draw->machine;
+ int j, n = MIN2(4, draw->vs.queue_nr - i);
+
+ for (j = 0; j < n; j++) {
+ elts[j] = draw->vs.queue[i + j].elt;
+ dests[j] = draw->vs.queue[i + j].vertex;
+ }
+ for ( ; j < 4; j++) {
+ elts[j] = elts[0];
+ dests[j] = draw->vs.queue[i + j].vertex;
+ }
+ //fetch directly into dests
+ draw->vertex_fetch.fetch_func(draw, machine, dests, count);
+ }
+#endif
+
+ draw->vs.post_nr = draw->vs.queue_nr;
+ draw->vs.queue_nr = 0;
+}
void draw_do_flush( struct draw_context *draw, unsigned flags )
{
@@ -134,7 +170,10 @@ void draw_do_flush( struct draw_context *draw, unsigned flags )
if (flags >= DRAW_FLUSH_SHADER_QUEUE) {
if (draw->vs.queue_nr)
- (*draw->shader_queue_flush)(draw);
+ if (draw->rasterizer->bypass_vs)
+ fetch_and_store(draw);
+ else
+ (*draw->shader_queue_flush)(draw);
if (flags >= DRAW_FLUSH_PRIM_QUEUE) {
if (draw->pq.queue_nr)
@@ -485,7 +524,11 @@ draw_arrays(struct draw_context *draw, unsigned prim,
}
/* drawing done here: */
- draw_prim(draw, prim, start, count);
+ if (!draw->rasterizer->bypass_vs ||
+ !draw_passthrough_arrays(draw, prim, start, count)) {
+ /* we have to run the whole pipeline */
+ draw_prim(draw, prim, start, count);
+ }
}