summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKeith Whitwell <keith@tungstengraphics.com>2008-04-03 12:21:30 +0100
committerKeith Whitwell <keith@tungstengraphics.com>2008-04-03 12:21:30 +0100
commitd2cb4ba0bb2388c784f145c59f3798f914dc7f39 (patch)
tree61ab6f6d5e4311c2d98cebe3de1c821a4ef65bda
parentadd46fbc8cc04d3bce303815541a7bc5d0b33953 (diff)
draw: add passthrough path to the pipeline
This handles the case where bypass_vs is set, but vertices need to go through the pipeline for some reason - eg unfilled polygon mode. Demonstrates how to drive the pipeline from inside one of these things.
-rw-r--r--src/gallium/auxiliary/draw/Makefile1
-rw-r--r--src/gallium/auxiliary/draw/SConscript1
-rw-r--r--src/gallium/auxiliary/draw/draw_private.h6
-rw-r--r--src/gallium/auxiliary/draw/draw_pt.c23
-rw-r--r--src/gallium/auxiliary/draw/draw_pt.h1
-rw-r--r--src/gallium/auxiliary/draw/draw_pt_fetch_emit.c64
-rw-r--r--src/gallium/auxiliary/draw/draw_pt_fetch_pipeline.c391
-rw-r--r--src/gallium/auxiliary/draw/draw_vertex_fetch.c4
8 files changed, 424 insertions, 67 deletions
diff --git a/src/gallium/auxiliary/draw/Makefile b/src/gallium/auxiliary/draw/Makefile
index a0db2e4555..b28e516396 100644
--- a/src/gallium/auxiliary/draw/Makefile
+++ b/src/gallium/auxiliary/draw/Makefile
@@ -18,6 +18,7 @@ C_SOURCES = \
draw_pt.c \
draw_pt_vcache.c \
draw_pt_fetch_emit.c \
+ draw_pt_fetch_pipeline.c \
draw_pt_elts.c \
draw_prim.c \
draw_pstipple.c \
diff --git a/src/gallium/auxiliary/draw/SConscript b/src/gallium/auxiliary/draw/SConscript
index 981225a8c2..9ca4197441 100644
--- a/src/gallium/auxiliary/draw/SConscript
+++ b/src/gallium/auxiliary/draw/SConscript
@@ -17,6 +17,7 @@ draw = env.ConvenienceLibrary(
'draw_pt.c',
'draw_pt_vcache.c',
'draw_pt_fetch_emit.c',
+ 'draw_pt_fetch_pipeline.c',
'draw_pt_elts.c',
'draw_prim.c',
'draw_pstipple.c',
diff --git a/src/gallium/auxiliary/draw/draw_private.h b/src/gallium/auxiliary/draw/draw_private.h
index 9a9b25297f..0c9f9c2e03 100644
--- a/src/gallium/auxiliary/draw/draw_private.h
+++ b/src/gallium/auxiliary/draw/draw_private.h
@@ -160,6 +160,11 @@ struct draw_vertex_shader {
/* Internal function for vertex fetch.
*/
typedef void (*fetch_func)(const void *ptr, float *attrib);
+
+fetch_func draw_get_fetch_func( enum pipe_format format );
+
+
+
typedef void (*full_fetch_func)( struct draw_context *draw,
struct tgsi_exec_machine *machine,
const unsigned *elts,
@@ -211,6 +216,7 @@ struct draw_context
struct {
struct draw_pt_middle_end *fetch_emit;
+ struct draw_pt_middle_end *fetch_pipeline;
struct draw_pt_middle_end *fetch_shade_emit;
struct draw_pt_middle_end *fetch_shade_cliptest_pipeline_or_emit;
} middle;
diff --git a/src/gallium/auxiliary/draw/draw_pt.c b/src/gallium/auxiliary/draw/draw_pt.c
index c3baf5b7da..f59fb86f78 100644
--- a/src/gallium/auxiliary/draw/draw_pt.c
+++ b/src/gallium/auxiliary/draw/draw_pt.c
@@ -73,7 +73,6 @@ draw_pt_arrays(struct draw_context *draw,
*/
-#if 0
if (!cliptest && !pipeline && !shading) {
/* This is the 'passthrough' path:
*/
@@ -81,6 +80,14 @@ draw_pt_arrays(struct draw_context *draw,
*/
middle = draw->pt.middle.fetch_emit;
}
+ else if (!cliptest && !shading) {
+ /* This is the 'passthrough' path targetting the pipeline backend.
+ */
+ /* Fetch user verts, emit pipeline verts, run pipeline:
+ */
+ middle = draw->pt.middle.fetch_pipeline;
+ }
+#if 0
else if (!cliptest && !pipeline) {
/* Fetch user verts, run vertex shader, emit hw verts:
*/
@@ -117,10 +124,9 @@ draw_pt_arrays(struct draw_context *draw,
middle = draw->pt.middle.fetch_shade_cliptest_pipeline;
}
#else
- if (cliptest || pipeline || shading)
+ else {
return FALSE;
-
- middle = draw->pt.middle.fetch_emit;
+ }
#endif
@@ -190,6 +196,10 @@ boolean draw_pt_init( struct draw_context *draw )
if (!draw->pt.middle.fetch_emit)
return FALSE;
+ draw->pt.middle.fetch_pipeline = draw_pt_fetch_pipeline( draw );
+ if (!draw->pt.middle.fetch_pipeline)
+ return FALSE;
+
draw->pt.front.vcache = draw_pt_vcache( draw );
if (!draw->pt.front.vcache)
return FALSE;
@@ -205,6 +215,11 @@ void draw_pt_destroy( struct draw_context *draw )
draw->pt.middle.fetch_emit = NULL;
}
+ if (draw->pt.middle.fetch_pipeline) {
+ draw->pt.middle.fetch_pipeline->destroy( draw->pt.middle.fetch_pipeline );
+ draw->pt.middle.fetch_pipeline = NULL;
+ }
+
if (draw->pt.front.vcache) {
draw->pt.front.vcache->destroy( draw->pt.front.vcache );
draw->pt.front.vcache = NULL;
diff --git a/src/gallium/auxiliary/draw/draw_pt.h b/src/gallium/auxiliary/draw/draw_pt.h
index 428b1e0e6b..800072c511 100644
--- a/src/gallium/auxiliary/draw/draw_pt.h
+++ b/src/gallium/auxiliary/draw/draw_pt.h
@@ -112,6 +112,7 @@ 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_middle_end *draw_pt_fetch_emit( struct draw_context *draw );
+struct draw_pt_middle_end *draw_pt_fetch_pipeline( struct draw_context *draw );
diff --git a/src/gallium/auxiliary/draw/draw_pt_fetch_emit.c b/src/gallium/auxiliary/draw/draw_pt_fetch_emit.c
index f863a46d9c..39f0b40838 100644
--- a/src/gallium/auxiliary/draw/draw_pt_fetch_emit.c
+++ b/src/gallium/auxiliary/draw/draw_pt_fetch_emit.c
@@ -85,45 +85,6 @@ struct fetch_emit_middle_end {
};
-static void fetch_B8G8R8A8_UNORM( const void *from,
- float *attrib )
-{
- ubyte *ub = (ubyte *) from;
- attrib[2] = UBYTE_TO_FLOAT(ub[0]);
- attrib[1] = UBYTE_TO_FLOAT(ub[1]);
- attrib[0] = UBYTE_TO_FLOAT(ub[2]);
- attrib[3] = UBYTE_TO_FLOAT(ub[3]);
-}
-
-static void fetch_R32G32B32A32_FLOAT( const void *from,
- float *attrib )
-{
- float *f = (float *) from;
- attrib[0] = f[0];
- attrib[1] = f[1];
- attrib[2] = f[2];
- attrib[3] = f[3];
-}
-
-static void fetch_R32G32B32_FLOAT( const void *from,
- float *attrib )
-{
- float *f = (float *) from;
- attrib[0] = f[0];
- attrib[1] = f[1];
- attrib[2] = f[2];
- attrib[3] = 1.0;
-}
-
-static void fetch_R32G32_FLOAT( const void *from,
- float *attrib )
-{
- float *f = (float *) from;
- attrib[0] = f[0];
- attrib[1] = f[1];
- attrib[2] = 0.0;
- attrib[3] = 1.0;
-}
static void fetch_R32_FLOAT( const void *from,
float *attrib )
@@ -235,28 +196,9 @@ static void fetch_emit_prepare( struct draw_pt_middle_end *middle,
feme->fetch[i].pitch = draw->vertex_buffer[src_buffer].pitch;
- switch (draw->vertex_element[src_element].src_format) {
- case PIPE_FORMAT_B8G8R8A8_UNORM:
- feme->fetch[i].fetch = fetch_B8G8R8A8_UNORM;
- break;
- case PIPE_FORMAT_R32G32B32A32_FLOAT:
- feme->fetch[i].fetch = fetch_R32G32B32A32_FLOAT;
- break;
- case PIPE_FORMAT_R32G32B32_FLOAT:
- feme->fetch[i].fetch = fetch_R32G32B32_FLOAT;
- break;
- case PIPE_FORMAT_R32G32_FLOAT:
- feme->fetch[i].fetch = fetch_R32G32_FLOAT;
- break;
- case PIPE_FORMAT_R32_FLOAT:
- feme->fetch[i].fetch = fetch_R32_FLOAT;
- break;
- default:
- assert(0);
- feme->fetch[i].fetch = NULL;
- break;
- }
-
+ feme->fetch[i].fetch = draw_get_fetch_func(draw->vertex_element[src_element].src_format);
+
+
switch (vinfo->emit[i]) {
case EMIT_4F:
feme->fetch[i].emit = emit_R32G32B32A32_FLOAT;
diff --git a/src/gallium/auxiliary/draw/draw_pt_fetch_pipeline.c b/src/gallium/auxiliary/draw/draw_pt_fetch_pipeline.c
new file mode 100644
index 0000000000..94e7d01be4
--- /dev/null
+++ b/src/gallium/auxiliary/draw/draw_pt_fetch_pipeline.c
@@ -0,0 +1,391 @@
+/**************************************************************************
+ *
+ * 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_vertex.h"
+#include "draw/draw_pt.h"
+
+/* The simplest 'middle end' in the new vertex code.
+ *
+ * The responsibilities of a middle end are to:
+ * - perform vertex fetch using
+ * - draw vertex element/buffer state
+ * - a list of fetch indices we received as an input
+ * - run the vertex shader
+ * - cliptest,
+ * - clip coord calculation
+ * - viewport transformation
+ * - if necessary, run the primitive pipeline, passing it:
+ * - a linear array of vertex_header vertices constructed here
+ * - a set of draw indices we received as an input
+ * - otherwise, drive the hw backend,
+ * - allocate space for hardware format vertices
+ * - translate the vertex-shader output vertices to hw format
+ * - calling the backend draw functions.
+ *
+ * For convenience, we provide a helper function to drive the hardware
+ * backend given similar inputs to those required to run the pipeline.
+ *
+ * In the case of passthrough mode, many of these actions are disabled
+ * or noops, so we end up doing:
+ *
+ * - perform vertex fetch
+ * - drive the hw backend
+ *
+ * IE, basically just vertex fetch to post-vs-format vertices,
+ * followed by a call to the backend helper function.
+ */
+
+
+struct fetch_pipeline_middle_end {
+ struct draw_pt_middle_end base;
+ struct draw_context *draw;
+
+ struct {
+ const ubyte *ptr;
+ unsigned pitch;
+ void (*fetch)( const void *from, float *attrib);
+ void (*emit)( const float *attrib, float **out );
+ } fetch[PIPE_MAX_ATTRIBS];
+
+ unsigned nr_fetch;
+ unsigned pipeline_vertex_size;
+ unsigned prim;
+};
+
+
+static void fetch_NULL( const void *from,
+ float *attrib )
+{
+}
+
+
+
+static void emit_R32_FLOAT( const float *attrib,
+ float **out )
+{
+ (*out)[0] = attrib[0];
+ (*out) += 1;
+}
+
+static void emit_R32G32_FLOAT( const float *attrib,
+ float **out )
+{
+ (*out)[0] = attrib[0];
+ (*out)[1] = attrib[1];
+ (*out) += 2;
+}
+
+static void emit_R32G32B32_FLOAT( const float *attrib,
+ float **out )
+{
+ (*out)[0] = attrib[0];
+ (*out)[1] = attrib[1];
+ (*out)[2] = attrib[2];
+ (*out) += 3;
+}
+
+static void emit_R32G32B32A32_FLOAT( const float *attrib,
+ float **out )
+{
+ (*out)[0] = attrib[0];
+ (*out)[1] = attrib[1];
+ (*out)[2] = attrib[2];
+ (*out)[3] = attrib[3];
+ (*out) += 4;
+}
+
+static void emit_header( const float *attrib,
+ float **out )
+{
+ (*out)[0] = 0;
+ (*out)[1] = 0;
+ (*out)[2] = 0;
+ (*out)[3] = 0;
+ (*out)[3] = 1;
+ (*out) += 5;
+}
+
+/**
+ * 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 fetch_pipeline_middle_end *fpme,
+ void *out_ptr,
+ const unsigned *fetch_elts,
+ unsigned count )
+{
+ float *out = (float *)out_ptr;
+ uint i, j;
+
+ for (i = 0; i < count; i++) {
+ unsigned elt = fetch_elts[i];
+
+ for (j = 0; j < fpme->nr_fetch; j++) {
+ float attrib[4];
+ const ubyte *from = (fpme->fetch[j].ptr +
+ fpme->fetch[j].pitch * elt);
+
+ fpme->fetch[j].fetch( from, attrib );
+ fpme->fetch[j].emit( attrib, &out );
+ }
+ }
+}
+
+
+/* We aren't running a vertex shader, but are running the pipeline.
+ * That means the vertices we need to build look like:
+ *
+ * dw0: vertex header (zero?)
+ * dw1: clip coord 0
+ * dw2: clip coord 1
+ * dw3: clip coord 2
+ * dw4: clip coord 4
+ * dw5: screen coord 0
+ * dw6: screen coord 0
+ * dw7: screen coord 0
+ * dw8: screen coord 0
+ * dw9: other attribs...
+ *
+ */
+static void fetch_pipeline_prepare( struct draw_pt_middle_end *middle,
+ unsigned prim )
+{
+ static const float zero = 0;
+ struct fetch_pipeline_middle_end *fpme = (struct fetch_pipeline_middle_end *)middle;
+ struct draw_context *draw = fpme->draw;
+ unsigned i, nr = 0;
+
+ fpme->prim = prim;
+
+ /* Emit the vertex header and empty clipspace coord field:
+ */
+ {
+ fpme->fetch[nr].ptr = NULL;
+ fpme->fetch[nr].pitch = 0;
+ fpme->fetch[nr].fetch = fetch_NULL;
+ fpme->fetch[nr].emit = emit_header;
+ nr++;
+ }
+
+
+ /* Need to look at vertex shader inputs (we know it is a
+ * passthrough shader, so these define the outputs too). If we
+ * were running a shader, we'd still be looking at the inputs at
+ * this point.
+ */
+ for (i = 0; i < draw->vertex_shader->info.num_inputs; i++) {
+ unsigned buf = draw->vertex_element[i].vertex_buffer_index;
+ enum pipe_format format = draw->vertex_element[i].src_format;
+
+ fpme->fetch[nr].ptr = ((const ubyte *) draw->user.vbuffer[buf] +
+ draw->vertex_buffer[buf].buffer_offset +
+ draw->vertex_element[i].src_offset);
+
+ fpme->fetch[nr].pitch = draw->vertex_buffer[buf].pitch;
+ fpme->fetch[nr].fetch = draw_get_fetch_func( format );
+
+ /* Always do this -- somewhat redundant...
+ */
+ fpme->fetch[nr].emit = emit_R32G32B32A32_FLOAT;
+ nr++;
+ }
+
+ fpme->nr_fetch = nr;
+ fpme->pipeline_vertex_size = (5 + (nr-1) * 4) * sizeof(float);
+}
+
+
+
+/**
+ * Add a point to the primitive queue.
+ * \param i0 index into user's vertex arrays
+ */
+static void do_point( struct draw_context *draw,
+ const char *v0 )
+{
+ struct prim_header prim;
+
+ prim.reset_line_stipple = 0;
+ prim.edgeflags = 1;
+ prim.pad = 0;
+ prim.v[0] = (struct vertex_header *)v0;
+
+ draw->pipeline.first->point( draw->pipeline.first, &prim );
+}
+
+
+/**
+ * Add a line to the primitive queue.
+ * \param i0 index into user's vertex arrays
+ * \param i1 index into user's vertex arrays
+ */
+static void do_line( struct draw_context *draw,
+ const char *v0,
+ const char *v1 )
+{
+ struct prim_header prim;
+
+ prim.reset_line_stipple = 1; /* fixme */
+ prim.edgeflags = 1;
+ prim.pad = 0;
+ prim.v[0] = (struct vertex_header *)v0;
+ prim.v[1] = (struct vertex_header *)v1;
+
+ draw->pipeline.first->line( draw->pipeline.first, &prim );
+}
+
+/**
+ * Add a triangle to the primitive queue.
+ */
+static void do_triangle( struct draw_context *draw,
+ char *v0,
+ char *v1,
+ char *v2 )
+{
+ struct prim_header prim;
+
+// _mesa_printf("tri %d %d %d\n", i0, i1, i2);
+ prim.reset_line_stipple = 1;
+ prim.edgeflags = ~0;
+ prim.pad = 0;
+ prim.v[0] = (struct vertex_header *)v0;
+ prim.v[1] = (struct vertex_header *)v1;
+ prim.v[2] = (struct vertex_header *)v2;
+
+ draw->pipeline.first->tri( draw->pipeline.first, &prim );
+}
+
+
+static void run_pipeline( struct fetch_pipeline_middle_end *fpme,
+ char *verts,
+ const ushort *elts,
+ unsigned count )
+{
+ struct draw_context *draw = fpme->draw;
+ unsigned stride = fpme->pipeline_vertex_size;
+ unsigned i;
+
+ switch (fpme->prim) {
+ case PIPE_PRIM_POINTS:
+ for (i = 0; i < count; i++)
+ do_point( draw,
+ verts + stride * elts[i] );
+ break;
+ case PIPE_PRIM_LINES:
+ for (i = 0; i+1 < count; i += 2)
+ do_line( draw,
+ verts + stride * elts[i+0],
+ verts + stride * elts[i+1]);
+ break;
+ case PIPE_PRIM_TRIANGLES:
+ for (i = 0; i+2 < count; i += 3)
+ do_triangle( draw,
+ verts + stride * elts[i+0],
+ verts + stride * elts[i+1],
+ verts + stride * elts[i+2]);
+ break;
+ }
+}
+
+
+
+
+static void fetch_pipeline_run( struct draw_pt_middle_end *middle,
+ const unsigned *fetch_elts,
+ unsigned fetch_count,
+ const ushort *draw_elts,
+ unsigned draw_count )
+{
+ struct fetch_pipeline_middle_end *fpme = (struct fetch_pipeline_middle_end *)middle;
+ struct draw_context *draw = fpme->draw;
+ char *pipeline_verts;
+
+ pipeline_verts = MALLOC( fpme->pipeline_vertex_size *
+ fetch_count );
+ if (!pipeline_verts) {
+ assert(0);
+ return;
+ }
+
+
+ /* Single routine to fetch vertices and emit pipeline verts.
+ */
+ fetch_store_general( fpme,
+ pipeline_verts,
+ fetch_elts,
+ fetch_count );
+
+
+ run_pipeline( fpme,
+ pipeline_verts,
+ draw_elts,
+ draw_count );
+
+
+ /* Done -- that was easy, wasn't it:
+ */
+ FREE( pipeline_verts );
+}
+
+
+
+static void fetch_pipeline_finish( struct draw_pt_middle_end *middle )
+{
+ /* nothing to do */
+}
+
+static void fetch_pipeline_destroy( struct draw_pt_middle_end *middle )
+{
+ FREE(middle);
+}
+
+
+struct draw_pt_middle_end *draw_pt_fetch_pipeline( struct draw_context *draw )
+{
+ struct fetch_pipeline_middle_end *fetch_pipeline = CALLOC_STRUCT( fetch_pipeline_middle_end );
+
+ fetch_pipeline->base.prepare = fetch_pipeline_prepare;
+ fetch_pipeline->base.run = fetch_pipeline_run;
+ fetch_pipeline->base.finish = fetch_pipeline_finish;
+ fetch_pipeline->base.destroy = fetch_pipeline_destroy;
+
+ fetch_pipeline->draw = draw;
+
+ return &fetch_pipeline->base;
+}
+
diff --git a/src/gallium/auxiliary/draw/draw_vertex_fetch.c b/src/gallium/auxiliary/draw/draw_vertex_fetch.c
index 11f99babf6..9041041006 100644
--- a/src/gallium/auxiliary/draw/draw_vertex_fetch.c
+++ b/src/gallium/auxiliary/draw/draw_vertex_fetch.c
@@ -166,7 +166,7 @@ fetch_B8G8R8A8_UNORM(const void *ptr, float *attrib)
}
-static fetch_func get_fetch_func( enum pipe_format format )
+fetch_func draw_get_fetch_func( enum pipe_format format )
{
#if 0
{
@@ -502,7 +502,7 @@ void draw_update_vertex_fetch( struct draw_context *draw )
draw->vertex_element[i].src_offset;
draw->vertex_fetch.pitch[i] = draw->vertex_buffer[buf].pitch;
- draw->vertex_fetch.fetch[i] = get_fetch_func( format );
+ draw->vertex_fetch.fetch[i] = draw_get_fetch_func( format );
}
draw->vertex_fetch.nr_attrs = nr_attrs;