diff options
-rw-r--r-- | src/gallium/auxiliary/draw/Makefile | 4 | ||||
-rw-r--r-- | src/gallium/auxiliary/draw/SConscript | 6 | ||||
-rw-r--r-- | src/gallium/auxiliary/draw/draw_context.c | 65 | ||||
-rw-r--r-- | src/gallium/auxiliary/draw/draw_passthrough.c | 4 | ||||
-rw-r--r-- | src/gallium/auxiliary/draw/draw_prim.c | 2 | ||||
-rw-r--r-- | src/gallium/auxiliary/draw/draw_private.h | 33 | ||||
-rw-r--r-- | src/gallium/auxiliary/draw/draw_pt.c | 206 | ||||
-rw-r--r-- | src/gallium/auxiliary/draw/draw_pt.h | 116 | ||||
-rw-r--r-- | src/gallium/auxiliary/draw/draw_pt_elts.c | 88 | ||||
-rw-r--r-- | src/gallium/auxiliary/draw/draw_pt_fetch_emit.c | 326 | ||||
-rw-r--r-- | src/gallium/auxiliary/draw/draw_pt_vcache.c | 338 |
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; +} |