summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/gallium/auxiliary/draw/Makefile4
-rw-r--r--src/gallium/auxiliary/draw/SConscript6
-rw-r--r--src/gallium/auxiliary/draw/draw_context.c65
-rw-r--r--src/gallium/auxiliary/draw/draw_passthrough.c4
-rw-r--r--src/gallium/auxiliary/draw/draw_prim.c2
-rw-r--r--src/gallium/auxiliary/draw/draw_private.h33
-rw-r--r--src/gallium/auxiliary/draw/draw_pt.c206
-rw-r--r--src/gallium/auxiliary/draw/draw_pt.h116
-rw-r--r--src/gallium/auxiliary/draw/draw_pt_elts.c88
-rw-r--r--src/gallium/auxiliary/draw/draw_pt_fetch_emit.c326
-rw-r--r--src/gallium/auxiliary/draw/draw_pt_vcache.c338
11 files changed, 1169 insertions, 19 deletions
diff --git a/src/gallium/auxiliary/draw/Makefile b/src/gallium/auxiliary/draw/Makefile
index 21e9f737b77..0c7ce5da5ba 100644
--- a/src/gallium/auxiliary/draw/Makefile
+++ b/src/gallium/auxiliary/draw/Makefile
@@ -16,6 +16,10 @@ C_SOURCES = \
draw_flatshade.c \
draw_offset.c \
draw_passthrough.c \
+ draw_pt.c \
+ draw_pt_vcache.c \
+ draw_pt_fetch_emit.c \
+ draw_pt_elts.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 d7fb86d992c..9b3e7247c54 100644
--- a/src/gallium/auxiliary/draw/SConscript
+++ b/src/gallium/auxiliary/draw/SConscript
@@ -14,7 +14,11 @@ draw = env.ConvenienceLibrary(
'draw_debug.c',
'draw_flatshade.c',
'draw_offset.c',
- 'draw_passthrough.c',
+ 'draw_passthrough.c', # going away soon
+ 'draw_pt.c',
+ 'draw_pt_vcache.c',
+ 'draw_pt_fetch_emit.c',
+ 'draw_pt_elts.c',
'draw_prim.c',
'draw_pstipple.c',
'draw_stipple.c',
diff --git a/src/gallium/auxiliary/draw/draw_context.c b/src/gallium/auxiliary/draw/draw_context.c
index 41da93cdf83..903cc267662 100644
--- a/src/gallium/auxiliary/draw/draw_context.c
+++ b/src/gallium/auxiliary/draw/draw_context.c
@@ -37,10 +37,11 @@
#include "draw_vbuf.h"
-
struct draw_context *draw_create( void )
{
struct draw_context *draw = CALLOC_STRUCT( draw_context );
+ if (draw == NULL)
+ goto fail;
#if defined(__i386__) || defined(__386__)
draw->use_sse = GETENV( "GALLIUM_NOSSE" ) == NULL;
@@ -61,6 +62,19 @@ struct draw_context *draw_create( void )
draw->pipeline.validate = draw_validate_stage( draw );
draw->pipeline.first = draw->pipeline.validate;
+ if (!draw->pipeline.wide_line ||
+ !draw->pipeline.wide_point ||
+ !draw->pipeline.stipple ||
+ !draw->pipeline.unfilled ||
+ !draw->pipeline.twoside ||
+ !draw->pipeline.offset ||
+ !draw->pipeline.clip ||
+ !draw->pipeline.flatshade ||
+ !draw->pipeline.cull ||
+ !draw->pipeline.validate)
+ goto fail;
+
+
ASSIGN_4V( draw->plane[0], -1, 0, 0, 1 );
ASSIGN_4V( draw->plane[1], 1, 0, 0, 1 );
ASSIGN_4V( draw->plane[2], 0, -1, 0, 1 );
@@ -75,6 +89,8 @@ struct draw_context *draw_create( void )
uint i;
const unsigned size = (MAX_VERTEX_SIZE + 0x0f) & ~0x0f;
char *tmp = align_malloc(Elements(draw->vs.queue) * size, 16);
+ if (!tmp)
+ goto fail;
for (i = 0; i < Elements(draw->vs.queue); i++)
draw->vs.queue[i].vertex = (struct vertex_header *)(tmp + i * size);
@@ -93,22 +109,42 @@ struct draw_context *draw_create( void )
draw_vertex_cache_invalidate( draw );
draw_set_mapped_element_buffer( draw, 0, NULL );
+ if (!draw_pt_init( draw ))
+ goto fail;
+
return draw;
+
+fail:
+ draw_destroy( draw );
+ return NULL;
}
void draw_destroy( struct draw_context *draw )
{
- draw->pipeline.wide_line->destroy( draw->pipeline.wide_line );
- draw->pipeline.wide_point->destroy( draw->pipeline.wide_point );
- draw->pipeline.stipple->destroy( draw->pipeline.stipple );
- draw->pipeline.unfilled->destroy( draw->pipeline.unfilled );
- draw->pipeline.twoside->destroy( draw->pipeline.twoside );
- draw->pipeline.offset->destroy( draw->pipeline.offset );
- draw->pipeline.clip->destroy( draw->pipeline.clip );
- draw->pipeline.flatshade->destroy( draw->pipeline.flatshade );
- draw->pipeline.cull->destroy( draw->pipeline.cull );
- draw->pipeline.validate->destroy( draw->pipeline.validate );
+ if (!draw)
+ return;
+
+ if (draw->pipeline.wide_line)
+ draw->pipeline.wide_line->destroy( draw->pipeline.wide_line );
+ if (draw->pipeline.wide_point)
+ draw->pipeline.wide_point->destroy( draw->pipeline.wide_point );
+ if (draw->pipeline.stipple)
+ draw->pipeline.stipple->destroy( draw->pipeline.stipple );
+ if (draw->pipeline.unfilled)
+ draw->pipeline.unfilled->destroy( draw->pipeline.unfilled );
+ if (draw->pipeline.twoside)
+ draw->pipeline.twoside->destroy( draw->pipeline.twoside );
+ if (draw->pipeline.offset)
+ draw->pipeline.offset->destroy( draw->pipeline.offset );
+ if (draw->pipeline.clip)
+ draw->pipeline.clip->destroy( draw->pipeline.clip );
+ if (draw->pipeline.flatshade)
+ draw->pipeline.flatshade->destroy( draw->pipeline.flatshade );
+ if (draw->pipeline.cull)
+ draw->pipeline.cull->destroy( draw->pipeline.cull );
+ if (draw->pipeline.validate)
+ draw->pipeline.validate->destroy( draw->pipeline.validate );
if (draw->pipeline.aaline)
draw->pipeline.aaline->destroy( draw->pipeline.aaline );
if (draw->pipeline.aapoint)
@@ -117,8 +153,11 @@ void draw_destroy( struct draw_context *draw )
draw->pipeline.pstipple->destroy( draw->pipeline.pstipple );
if (draw->pipeline.rasterize)
draw->pipeline.rasterize->destroy( draw->pipeline.rasterize );
+
tgsi_exec_machine_free_data(&draw->machine);
- align_free( draw->vs.queue[0].vertex ); /* Frees all the vertices. */
+
+ if (draw->vs.queue[0].vertex)
+ align_free( draw->vs.queue[0].vertex ); /* Frees all the vertices. */
/* Not so fast -- we're just borrowing this at the moment.
*
@@ -126,6 +165,8 @@ void draw_destroy( struct draw_context *draw )
draw->render->destroy( draw->render );
*/
+ draw_pt_destroy( draw );
+
FREE( draw );
}
diff --git a/src/gallium/auxiliary/draw/draw_passthrough.c b/src/gallium/auxiliary/draw/draw_passthrough.c
index fdec6a591b8..dd00894c5bd 100644
--- a/src/gallium/auxiliary/draw/draw_passthrough.c
+++ b/src/gallium/auxiliary/draw/draw_passthrough.c
@@ -125,9 +125,9 @@ fetch_store_general( struct draw_context *draw,
case PIPE_FORMAT_B8G8R8A8_UNORM:
{
ubyte *ub = (ubyte *) from;
- attrib[0] = UBYTE_TO_FLOAT(ub[0]);
+ attrib[2] = UBYTE_TO_FLOAT(ub[0]);
attrib[1] = UBYTE_TO_FLOAT(ub[1]);
- attrib[2] = UBYTE_TO_FLOAT(ub[2]);
+ attrib[0] = UBYTE_TO_FLOAT(ub[2]);
attrib[3] = UBYTE_TO_FLOAT(ub[3]);
}
break;
diff --git a/src/gallium/auxiliary/draw/draw_prim.c b/src/gallium/auxiliary/draw/draw_prim.c
index cb0277fb6c9..4fe0ddc02a7 100644
--- a/src/gallium/auxiliary/draw/draw_prim.c
+++ b/src/gallium/auxiliary/draw/draw_prim.c
@@ -526,7 +526,7 @@ draw_arrays(struct draw_context *draw, unsigned prim,
/* drawing done here: */
if (!draw->rasterizer->bypass_vs ||
- !draw_passthrough_arrays(draw, prim, start, count)) {
+ !draw_pt_arrays(draw, prim, start, count)) {
/* we have to run the whole pipeline */
draw_prim(draw, prim, start, count);
}
diff --git a/src/gallium/auxiliary/draw/draw_private.h b/src/gallium/auxiliary/draw/draw_private.h
index 1c65c3d1b2a..0c5afcacfae 100644
--- a/src/gallium/auxiliary/draw/draw_private.h
+++ b/src/gallium/auxiliary/draw/draw_private.h
@@ -53,6 +53,9 @@ struct pipe_context;
struct gallivm_prog;
struct gallivm_cpu_engine;
+struct draw_pt_middle_end;
+struct draw_pt_front_end;
+
/**
* Basic vertex info.
* Carry some useful information around with the vertices in the prim pipe.
@@ -203,8 +206,21 @@ struct draw_context
/* Support prototype passthrough path:
*/
struct {
- unsigned prim;
- unsigned hw_vertex_size;
+ unsigned prim; /* XXX: to be removed */
+ unsigned hw_vertex_size; /* XXX: to be removed */
+
+ struct {
+ struct draw_pt_middle_end *fetch_emit;
+ struct draw_pt_middle_end *fetch_shade_emit;
+ struct draw_pt_middle_end *fetch_shade_cliptest_pipeline_or_emit;
+ } middle;
+
+ struct {
+ struct draw_pt_front_end *noop;
+ struct draw_pt_front_end *split_arrays;
+ struct draw_pt_front_end *vcache;
+ } front;
+
} pt;
@@ -351,7 +367,18 @@ extern void draw_update_vertex_fetch( struct draw_context *draw );
extern boolean draw_need_pipeline(const struct draw_context *draw);
-/* Prototype/hack
+/* Passthrough mode (second attempt):
+ */
+boolean draw_pt_init( struct draw_context *draw );
+void draw_pt_destroy( struct draw_context *draw );
+boolean draw_pt_arrays( struct draw_context *draw,
+ unsigned prim,
+ unsigned start,
+ unsigned count );
+
+
+
+/* Prototype/hack (DEPRECATED)
*/
boolean
draw_passthrough_arrays(struct draw_context *draw,
diff --git a/src/gallium/auxiliary/draw/draw_pt.c b/src/gallium/auxiliary/draw/draw_pt.c
new file mode 100644
index 00000000000..219b5634227
--- /dev/null
+++ b/src/gallium/auxiliary/draw/draw_pt.c
@@ -0,0 +1,206 @@
+/**************************************************************************
+ *
+ * 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 <[email protected]>
+ */
+
+#include "pipe/p_util.h"
+#include "draw/draw_context.h"
+#include "draw/draw_private.h"
+#include "draw/draw_pt.h"
+
+
+static boolean too_many_verts( struct draw_context *draw,
+ unsigned verts )
+{
+ return verts < 1024;
+}
+
+static boolean too_many_elts( struct draw_context *draw,
+ unsigned elts )
+{
+ return elts < (16 * 1024);
+}
+
+
+boolean
+draw_pt_arrays(struct draw_context *draw,
+ unsigned prim,
+ unsigned start,
+ unsigned count)
+{
+ const boolean pipeline = draw_need_pipeline(draw);
+ const boolean cliptest = !draw->rasterizer->bypass_clipping;
+ const boolean shading = !draw->rasterizer->bypass_vs;
+ struct draw_pt_front_end *frontend = NULL;
+ struct draw_pt_middle_end *middle = NULL;
+
+
+ /* Overall we do:
+ * - frontend -- prepare fetch_elts, draw_elts - eg vcache
+ * - middle -- fetch, shade, cliptest, viewport
+ * - pipeline -- the prim pipeline: clipping, wide lines, etc
+ * - backend -- the vbuf_render provided by the driver.
+ */
+
+
+#if 0
+ if (!cliptest && !pipeline && !shading) {
+ /* This is the 'passthrough' path:
+ */
+ /* Fetch user verts, emit hw verts:
+ */
+ middle = draw->pt.middle.fetch_emit;
+ }
+ else if (!cliptest && !pipeline) {
+ /* Fetch user verts, run vertex shader, emit hw verts:
+ */
+ middle = draw->pt.middle.fetch_shade_emit;
+ }
+ else if (!pipeline) {
+ /* Even though !pipeline, we have to run it to get clipping. We
+ * do know that the pipeline is just the clipping operation, but
+ * that probably doesn't help much.
+ *
+ * This is going to be the most important path for a lot of
+ * swtnl cards.
+ */
+ /* Fetch user verts,
+ * run vertex shader,
+ * cliptest and viewport trasform
+ * if no clipped vertices,
+ * emit hw verts
+ * else
+ * run pipline
+ */
+ middle = draw->pt.middle.fetch_shade_cliptest_pipeline_or_emit;
+ }
+ else if (!cliptest) {
+ /* Fetch user verts, run vertex shader, run pipeline:
+ */
+ middle = draw->pt.middle.fetch_shade_pipeline;
+ }
+ else {
+ /* This is what we're currently always doing:
+ */
+ /* Fetch user verts, run vertex shader, cliptest, run pipeline:
+ */
+ middle = draw->pt.middle.fetch_shade_cliptest_pipeline;
+ }
+#else
+ if (cliptest /*|| pipeline*/ || shading)
+ return FALSE;
+
+ middle = draw->pt.middle.fetch_emit;
+#endif
+
+
+ /* If !pipeline, need to make sure we respect the driver's limited
+ * capabilites to receive blocks of vertex data and elements.
+ */
+#if 0
+ if (!pipeline) {
+ unsigned vertex_mode = passthrough;
+ unsigned nr_verts = count_vertices( draw, start, count );
+ unsigned hw_prim = prim;
+
+ if (is_elts(draw)) {
+ frontend = draw->pt.front.vcache;
+ hw_prim = reduced_prim(prim);
+ }
+
+ if (too_many_verts(nr_verts)) {
+ /* if (is_verts(draw) && can_split(prim)) {
+ draw = draw_arrays_split;
+ }
+ else */ {
+ frontend = draw->pt.front.vcache;
+ hw_prim = reduced_prim(prim);
+ }
+ }
+
+ if (too_many_elts(count)) {
+
+ /* if (is_elts(draw) && can_split(prim)) {
+ draw = draw_elts_split;
+ }
+ else */ {
+ frontend = draw->pt.front.vcache;
+ hw_prim = reduced_prim(prim);
+ }
+ }
+
+ if (!good_prim(hw_prim)) {
+ draw = draw->pt.front.vcache;
+ }
+ }
+#else
+ frontend = draw->pt.front.vcache;
+#endif
+
+ frontend->prepare( frontend, middle );
+
+ frontend->run( frontend,
+ prim,
+ draw_pt_elt_func( draw ),
+ draw_pt_elt_ptr( draw, start ),
+ count );
+
+ frontend->finish( frontend );
+
+ return TRUE;
+}
+
+
+boolean draw_pt_init( struct draw_context *draw )
+{
+ draw->pt.middle.fetch_emit = draw_pt_fetch_emit( draw );
+ if (!draw->pt.middle.fetch_emit)
+ return FALSE;
+
+ draw->pt.front.vcache = draw_pt_vcache();
+ if (!draw->pt.front.vcache)
+ return FALSE;
+
+ return TRUE;
+}
+
+
+void draw_pt_destroy( struct draw_context *draw )
+{
+ if (draw->pt.middle.fetch_emit) {
+ draw->pt.middle.fetch_emit->destroy( draw->pt.middle.fetch_emit );
+ draw->pt.middle.fetch_emit = 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
new file mode 100644
index 00000000000..1b81d196f62
--- /dev/null
+++ b/src/gallium/auxiliary/draw/draw_pt.h
@@ -0,0 +1,116 @@
+/**************************************************************************
+ *
+ * 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 <[email protected]>
+ */
+
+#ifndef DRAW_PT_H
+#define DRAW_PT_H
+
+#include "pipe/p_compiler.h"
+
+typedef ushort (*pt_elt_func)( const void *elts, ushort idx );
+
+
+/* The "front end" - prepare sets of fetch, draw elements for the
+ * middle end.
+ *
+ * Currenly one version of this:
+ * - vcache - catchall implementation, decomposes to TRI/LINE/POINT prims
+ * Later:
+ * - varray, varray_split
+ * - velement, velement_split
+ *
+ * Currenly only using the vcache version.
+ */
+struct draw_pt_front_end {
+ void (*prepare)( struct draw_pt_front_end *,
+ struct draw_pt_middle_end * );
+
+ void (*run)( struct draw_pt_front_end *,
+ unsigned prim,
+ pt_elt_func elt_func,
+ const void *elt_ptr,
+ unsigned count );
+
+ void (*finish)( struct draw_pt_front_end * );
+ void (*destroy)( struct draw_pt_front_end * );
+};
+
+
+/* The "middle end" - prepares actual hardware vertices for the
+ * hardware backend.
+ *
+ * Currently two versions of this:
+ * - fetch, vertex shade, cliptest, prim-pipeline
+ * - fetch, emit (ie passthrough)
+ * Later:
+ * - fetch, vertex shade, cliptest, maybe-pipeline, maybe-emit
+ * - fetch, vertex shade, emit
+ *
+ * Currenly only using the passthrough version.
+ */
+struct draw_pt_middle_end {
+ void (*prepare)( struct draw_pt_middle_end * );
+
+ void (*run)( struct draw_pt_middle_end *,
+ unsigned prim,
+ const unsigned *fetch_elts,
+ unsigned fetch_count,
+ const ushort *draw_elts,
+ unsigned draw_count );
+
+ void (*finish)( struct draw_pt_middle_end * );
+ void (*destroy)( struct draw_pt_middle_end * );
+};
+
+
+/* The "back end" - supplied by the driver, defined in draw_vbuf.h.
+ *
+ * Not sure whether to wrap the prim pipeline up as an alternate
+ * backend. Would be a win for everything except pure passthrough
+ * mode...
+ */
+struct vbuf_render;
+
+
+/* Helper functions.
+ */
+pt_elt_func draw_pt_elt_func( struct draw_context *draw );
+const void *draw_pt_elt_ptr( struct draw_context *draw,
+ unsigned start );
+
+/* Implementations:
+ */
+struct draw_pt_front_end *draw_pt_vcache( void );
+struct draw_pt_middle_end *draw_pt_fetch_emit( struct draw_context *draw );
+
+
+
+#endif
diff --git a/src/gallium/auxiliary/draw/draw_pt_elts.c b/src/gallium/auxiliary/draw/draw_pt_elts.c
new file mode 100644
index 00000000000..585b83fa903
--- /dev/null
+++ b/src/gallium/auxiliary/draw/draw_pt_elts.c
@@ -0,0 +1,88 @@
+/**************************************************************************
+ *
+ * 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 <[email protected]>
+ */
+
+#include "draw/draw_pt.h"
+#include "draw/draw_private.h"
+
+/* Neat get_elt func that also works for varrays drawing by encoding
+ * the start value into a pointer.
+ */
+
+static ushort elt_uint( const void *elts, ushort idx )
+{
+ return *(((const uint *)elts) + idx);
+}
+
+static ushort elt_ushort( const void *elts, ushort idx )
+{
+ return *(((const ushort *)elts) + idx);
+}
+
+static ushort elt_ubyte( const void *elts, ushort idx )
+{
+ return *(((const ubyte *)elts) + idx);
+}
+
+static ushort elt_vert( const void *elts, ushort idx )
+{
+ return (const ubyte *)elts - (const ubyte *)NULL + idx;
+}
+
+pt_elt_func draw_pt_elt_func( struct draw_context *draw )
+{
+ switch (draw->user.eltSize) {
+ case 0: return elt_vert;
+ case 1: return elt_ubyte;
+ case 2: return elt_ushort;
+ case 4: return elt_uint;
+ default: return NULL;
+ }
+}
+
+const void *draw_pt_elt_ptr( struct draw_context *draw,
+ unsigned start )
+{
+ const char *elts = draw->user.elts;
+
+ switch (draw->user.eltSize) {
+ case 0:
+ return (const void *)(((const ubyte *)NULL) + start);
+ case 1:
+ return (const void *)(((const ubyte *)elts) + start);
+ case 2:
+ return (const void *)(((const ushort *)elts) + start);
+ case 4:
+ return (const void *)(((const uint *)elts) + start);
+ default:
+ return NULL;
+ }
+}
diff --git a/src/gallium/auxiliary/draw/draw_pt_fetch_emit.c b/src/gallium/auxiliary/draw/draw_pt_fetch_emit.c
new file mode 100644
index 00000000000..74a946545ac
--- /dev/null
+++ b/src/gallium/auxiliary/draw/draw_pt_fetch_emit.c
@@ -0,0 +1,326 @@
+/**************************************************************************
+ *
+ * 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 <[email protected]>
+ */
+
+#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"
+
+/* 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_emit_middle_end {
+ struct draw_pt_middle_end base;
+ struct draw_context *draw;
+
+ struct {
+ const ubyte *ptr;
+ unsigned pitch;
+ enum pipe_format src_format;
+ unsigned dst_format;
+ } fetch[PIPE_ATTRIB_MAX];
+
+ unsigned nr_fetch;
+ unsigned hw_vertex_size;
+};
+
+
+/**
+ * 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_emit_middle_end *feme,
+ void *out_ptr,
+ const unsigned *fetch_elts,
+ unsigned count )
+{
+ float *out = (float *)out_ptr;
+ struct vbuf_render *render = feme->draw->render;
+ uint i, j;
+
+ for (i = 0; i < count; i++) {
+ unsigned elt = fetch_elts[i];
+
+ for (j = 0; j < feme->nr_fetch; j++) {
+ float attrib[4];
+ const ubyte *from = (feme->fetch[j].ptr +
+ feme->fetch[j].pitch * elt);
+
+ /* The normal fetch/emit code:
+ */
+ switch (feme->fetch[j].src_format) {
+ case PIPE_FORMAT_B8G8R8A8_UNORM:
+ {
+ 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]);
+ }
+ break;
+ 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:
+ assert(0);
+ }
+
+ if (0) debug_printf("attrib %d: %f %f %f %f\n", j,
+ attrib[0], attrib[1], attrib[2], attrib[3]);
+
+ switch (feme->fetch[j].dst_format) {
+ case EMIT_1F:
+ out[0] = attrib[0];
+ out += 1;
+ break;
+ case EMIT_2F:
+ out[0] = attrib[0];
+ out[1] = attrib[1];
+ out += 2;
+ break;
+ case EMIT_4F:
+ out[0] = attrib[0];
+ out[1] = attrib[1];
+ out[2] = attrib[2];
+ out[3] = attrib[3];
+ out += 4;
+ break;
+ default:
+ assert(0);
+ }
+ }
+ }
+}
+
+
+
+static void fetch_emit_prepare( struct draw_pt_middle_end *middle )
+{
+ struct fetch_emit_middle_end *feme = (struct fetch_emit_middle_end *)middle;
+ struct draw_context *draw = feme->draw;
+ const struct vertex_info *vinfo = draw->render->get_vertex_info(draw->render);
+ unsigned nr_attrs = vinfo->num_attribs;
+ unsigned i;
+
+ for (i = 0; i < nr_attrs; i++) {
+ enum pipe_format src_format;
+ unsigned dst_format;
+ const void *src_ptr;
+ unsigned pitch;
+
+ if (vinfo->emit[i] == EMIT_HEADER) {
+ static const unsigned zero = 0;
+ src_ptr = &zero;
+ src_format = PIPE_FORMAT_R32_FLOAT;
+ pitch = 0;
+ dst_format = EMIT_1F;
+ }
+ else if (vinfo->emit[i] == EMIT_1F_PSIZE) {
+ src_ptr = &feme->draw->rasterizer->point_size;
+ src_format = PIPE_FORMAT_R32_FLOAT;
+ pitch = 0;
+ dst_format = EMIT_1F;
+ }
+ else {
+ unsigned src_element = vinfo->src_index[i];
+ unsigned src_buffer = draw->vertex_element[src_element].vertex_buffer_index;
+
+ src_ptr = ((const ubyte *)draw->user.vbuffer[src_buffer] +
+ draw->vertex_buffer[src_buffer].buffer_offset +
+ draw->vertex_element[src_element].src_offset);
+
+ src_format = draw->vertex_element[src_element].src_format;
+ pitch = draw->vertex_buffer[src_buffer].pitch;
+ dst_format = vinfo->emit[i];
+ }
+
+ feme->fetch[i].src_format = src_format;
+ feme->fetch[i].ptr = src_ptr;
+ feme->fetch[i].pitch = pitch;
+ feme->fetch[i].dst_format = dst_format;
+ }
+
+
+ feme->nr_fetch = nr_attrs;
+ feme->hw_vertex_size = vinfo->size * 4;
+}
+
+
+
+
+
+static void fetch_emit_run( struct draw_pt_middle_end *middle,
+ unsigned prim,
+ const unsigned *fetch_elts,
+ unsigned fetch_count,
+ const ushort *draw_elts,
+ unsigned draw_count )
+{
+ struct fetch_emit_middle_end *feme = (struct fetch_emit_middle_end *)middle;
+ struct draw_context *draw = feme->draw;
+ void *hw_verts;
+ boolean ok;
+
+ ok = draw->render->set_primitive( draw->render,
+ prim );
+ if (!ok) {
+ assert(0);
+ return;
+ }
+
+
+ hw_verts = draw->render->allocate_vertices( draw->render,
+ (ushort)feme->hw_vertex_size,
+ (ushort)fetch_count );
+ if (!hw_verts) {
+ assert(0);
+ return;
+ }
+
+
+ /* Single routine to fetch vertices and emit HW verts.
+ */
+ fetch_store_general( feme,
+ hw_verts,
+ fetch_elts,
+ fetch_count );
+
+ /* XXX: Draw arrays path to avoid re-emitting index list again and
+ * again.
+ */
+ draw->render->draw( draw->render,
+ draw_elts,
+ draw_count );
+
+ /* Done -- that was easy, wasn't it:
+ */
+ draw->render->release_vertices( draw->render,
+ hw_verts,
+ feme->hw_vertex_size,
+ fetch_count );
+
+}
+
+
+
+static void fetch_emit_finish( struct draw_pt_middle_end *middle )
+{
+ /* nothing to do */
+}
+
+static void fetch_emit_destroy( struct draw_pt_middle_end *middle )
+{
+ FREE(middle);
+}
+
+
+struct draw_pt_middle_end *draw_pt_fetch_emit( struct draw_context *draw )
+{
+ struct fetch_emit_middle_end *fetch_emit = CALLOC_STRUCT( fetch_emit_middle_end );
+
+ 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->draw = draw;
+
+ return &fetch_emit->base;
+}
+
diff --git a/src/gallium/auxiliary/draw/draw_pt_vcache.c b/src/gallium/auxiliary/draw/draw_pt_vcache.c
new file mode 100644
index 00000000000..07e9f0ae5fa
--- /dev/null
+++ b/src/gallium/auxiliary/draw/draw_pt_vcache.c
@@ -0,0 +1,338 @@
+/**************************************************************************
+ *
+ * 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 <[email protected]>
+ */
+
+#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"
+
+
+#define CACHE_MAX 32
+#define FETCH_MAX 128
+#define DRAW_MAX (16*1024)
+
+struct vcache_frontend {
+ struct draw_pt_front_end base;
+
+ ushort in[CACHE_MAX];
+ ushort out[CACHE_MAX];
+
+ ushort draw_elts[DRAW_MAX];
+ unsigned fetch_elts[FETCH_MAX];
+
+ unsigned draw_count;
+ unsigned fetch_count;
+
+ pt_elt_func elt_func;
+ const void *elt_ptr;
+
+ struct draw_pt_middle_end *middle;
+ unsigned output_prim;
+};
+
+static void vcache_flush( struct vcache_frontend *vcache )
+{
+#if 0
+ /* Should always be true if output_prim == input_prim, otherwise
+ * not so much...
+ */
+ unsigned i;
+ for (i = 0; i < vcache->draw_count; i++) {
+ assert( vcache->fetch_elts[vcache->draw_elts[i]] ==
+ vcache->elt_func(vcache->elt_ptr, i) );
+ }
+#endif
+
+ if (vcache->draw_count)
+ vcache->middle->run( vcache->middle,
+ vcache->output_prim,
+ vcache->fetch_elts,
+ vcache->fetch_count,
+ vcache->draw_elts,
+ vcache->draw_count );
+
+ memset(vcache->in, ~0, sizeof(vcache->in));
+ vcache->fetch_count = 0;
+ vcache->draw_count = 0;
+}
+
+static void vcache_check_flush( struct vcache_frontend *vcache )
+{
+ if ( vcache->draw_count + 6 >= DRAW_MAX ||
+ vcache->fetch_count + 4 >= FETCH_MAX )
+ {
+ vcache_flush( vcache );
+ }
+}
+
+
+static void vcache_elt( struct vcache_frontend *vcache,
+ unsigned felt )
+{
+ // ushort felt = elt(draw, i);
+
+ ushort idx = felt % CACHE_MAX;
+
+ if (vcache->in[idx] != felt) {
+ assert(vcache->fetch_count < FETCH_MAX);
+
+ vcache->in[idx] = felt;
+ vcache->out[idx] = vcache->fetch_count;
+ vcache->fetch_elts[vcache->fetch_count++] = felt;
+ }
+
+ vcache->draw_elts[vcache->draw_count++] = vcache->out[idx];
+}
+
+static void vcache_triangle( struct vcache_frontend *vcache,
+ unsigned i0,
+ unsigned i1,
+ unsigned i2 )
+{
+ /* TODO: encode edgeflags in draw_elts */
+ vcache_elt(vcache, i0);
+ vcache_elt(vcache, i1);
+ vcache_elt(vcache, i2);
+ vcache_check_flush(vcache);
+}
+
+static void vcache_line( struct vcache_frontend *vcache,
+ boolean reset,
+ unsigned i0,
+ unsigned i1 )
+{
+ /* TODO: encode reset-line-stipple in draw_elts */
+ (void) reset;
+ vcache_elt(vcache, i0);
+ vcache_elt(vcache, i1);
+ vcache_check_flush(vcache);
+}
+
+
+static void vcache_point( struct vcache_frontend *vcache,
+ unsigned i0 )
+{
+ vcache_elt(vcache, i0);
+ vcache_check_flush(vcache);
+}
+
+static void vcache_quad( struct vcache_frontend *vcache,
+ unsigned i0,
+ unsigned i1,
+ unsigned i2,
+ unsigned i3 )
+{
+ vcache_triangle( vcache, i0, i1, i3 );
+ vcache_triangle( vcache, i1, i2, i3 );
+}
+
+
+static void vcache_prepare( struct draw_pt_front_end *frontend,
+ struct draw_pt_middle_end *middle )
+{
+ struct vcache_frontend *vcache = (struct vcache_frontend *)frontend;
+ vcache->middle = middle;
+ middle->prepare( middle );
+}
+
+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
+};
+
+
+static void vcache_run( struct draw_pt_front_end *frontend,
+ unsigned prim,
+ pt_elt_func get_elt,
+ const void *elts,
+ unsigned count )
+{
+ struct vcache_frontend *vcache = (struct vcache_frontend *)frontend;
+ unsigned i;
+
+ /* These are for validation only:
+ */
+ vcache->elt_func = get_elt;
+ vcache->elt_ptr = elts;
+ vcache->output_prim = reduced_prim[prim];
+
+ switch (prim) {
+ case PIPE_PRIM_POINTS:
+ for (i = 0; i < count; i ++) {
+ vcache_point( vcache,
+ get_elt(elts, i) );
+ }
+ break;
+
+ case PIPE_PRIM_LINES:
+ for (i = 0; i+1 < count; i += 2) {
+ vcache_line( vcache,
+ TRUE,
+ get_elt(elts, i + 0),
+ get_elt(elts, i + 1));
+ }
+ break;
+
+ case PIPE_PRIM_LINE_LOOP:
+ if (count >= 2) {
+ for (i = 1; i < count; i++) {
+ vcache_line( vcache,
+ i == 1, /* XXX: only if vb not split */
+ get_elt(elts, i - 1),
+ get_elt(elts, i) );
+ }
+
+ vcache_line( vcache,
+ 0,
+ get_elt(elts, count - 1),
+ get_elt(elts, 0) );
+ }
+ break;
+
+ case PIPE_PRIM_LINE_STRIP:
+ for (i = 1; i < count; i++) {
+ vcache_line( vcache,
+ i == 1,
+ get_elt(elts, i - 1),
+ get_elt(elts, i) );
+ }
+ break;
+
+ case PIPE_PRIM_TRIANGLES:
+ for (i = 0; i+2 < count; i += 3) {
+ vcache_triangle( vcache,
+ get_elt(elts, i + 0),
+ get_elt(elts, i + 1),
+ get_elt(elts, i + 2) );
+ }
+ break;
+
+ case PIPE_PRIM_TRIANGLE_STRIP:
+ for (i = 0; i+2 < count; i++) {
+ if (i & 1) {
+ vcache_triangle( vcache,
+ get_elt(elts, i + 1),
+ get_elt(elts, i + 0),
+ get_elt(elts, i + 2) );
+ }
+ else {
+ vcache_triangle( vcache,
+ get_elt(elts, i + 0),
+ get_elt(elts, i + 1),
+ get_elt(elts, i + 2) );
+ }
+ }
+ break;
+
+ case PIPE_PRIM_TRIANGLE_FAN:
+ for (i = 0; i+2 < count; i++) {
+ vcache_triangle( vcache,
+ get_elt(elts, 0),
+ get_elt(elts, i + 1),
+ get_elt(elts, i + 2) );
+ }
+ break;
+
+
+ case PIPE_PRIM_QUADS:
+ for (i = 0; i+3 < count; i += 4) {
+ vcache_quad( vcache,
+ get_elt(elts, i + 0),
+ get_elt(elts, i + 1),
+ get_elt(elts, i + 2),
+ get_elt(elts, i + 3));
+ }
+ break;
+
+ case PIPE_PRIM_QUAD_STRIP:
+ for (i = 0; i+3 < count; i += 2) {
+ vcache_quad( vcache,
+ get_elt(elts, i + 2),
+ get_elt(elts, i + 0),
+ get_elt(elts, i + 1),
+ get_elt(elts, i + 3));
+ }
+ break;
+
+ case PIPE_PRIM_POLYGON:
+ for (i = 0; i+2 < count; i++) {
+ vcache_triangle( vcache,
+ get_elt(elts, i + 1),
+ get_elt(elts, i + 2),
+ get_elt(elts, 0));
+ }
+ break;
+
+ default:
+ assert(0);
+ break;
+ }
+
+ vcache_flush( vcache );
+}
+
+static void vcache_finish( struct draw_pt_front_end *frontend )
+{
+ struct vcache_frontend *vcache = (struct vcache_frontend *)frontend;
+ vcache->middle->finish( vcache->middle );
+ vcache->middle = NULL;
+}
+
+static void vcache_destroy( struct draw_pt_front_end *frontend )
+{
+ FREE(frontend);
+}
+
+
+struct draw_pt_front_end *draw_pt_vcache( void )
+{
+ struct vcache_frontend *vcache = CALLOC_STRUCT( vcache_frontend );
+
+ vcache->base.prepare = vcache_prepare;
+ vcache->base.run = vcache_run;
+ vcache->base.finish = vcache_finish;
+ vcache->base.destroy = vcache_destroy;
+
+ memset(vcache->in, ~0, sizeof(vcache->in));
+
+ return &vcache->base;
+}