summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/mesa/pipe/draw/draw_clip.c1
-rw-r--r--src/mesa/pipe/draw/draw_prim.c9
-rw-r--r--src/mesa/pipe/draw/draw_private.h6
-rw-r--r--src/mesa/pipe/draw/draw_vertex_cache.c20
-rw-r--r--src/mesa/pipe/draw/draw_vertex_shader.c2
-rw-r--r--src/mesa/pipe/softpipe/Makefile1
-rw-r--r--src/mesa/pipe/softpipe/sp_context.c14
-rw-r--r--src/mesa/pipe/softpipe/sp_context.h2
-rw-r--r--src/mesa/pipe/softpipe/sp_prim_setup.c96
-rw-r--r--src/mesa/pipe/softpipe/sp_prim_setup.h34
-rw-r--r--src/mesa/pipe/softpipe/sp_prim_vbuf.c305
11 files changed, 476 insertions, 14 deletions
diff --git a/src/mesa/pipe/draw/draw_clip.c b/src/mesa/pipe/draw/draw_clip.c
index e2af69e048..3ccc408bc0 100644
--- a/src/mesa/pipe/draw/draw_clip.c
+++ b/src/mesa/pipe/draw/draw_clip.c
@@ -109,6 +109,7 @@ static void interp( const struct clipper *clip,
dst->clipmask = 0;
dst->edgeflag = 0;
dst->pad = 0;
+ dst->vertex_id = 0;
}
/* Clip coordinates: interpolate normally
diff --git a/src/mesa/pipe/draw/draw_prim.c b/src/mesa/pipe/draw/draw_prim.c
index e82e48b90b..be2f987b9a 100644
--- a/src/mesa/pipe/draw/draw_prim.c
+++ b/src/mesa/pipe/draw/draw_prim.c
@@ -106,9 +106,12 @@ void draw_flush( struct draw_context *draw )
static struct prim_header *get_queued_prim( struct draw_context *draw,
unsigned nr_verts )
{
- if (draw->pq.queue_nr + 1 >= PRIM_QUEUE_LENGTH ||
- !draw_vertex_cache_check_space( draw, nr_verts ))
- {
+ if (draw->pq.queue_nr + 1 >= PRIM_QUEUE_LENGTH) {
+// fprintf(stderr, "p");
+ draw_flush( draw );
+ }
+ else if (!draw_vertex_cache_check_space( draw, nr_verts )) {
+// fprintf(stderr, "v");
draw_flush( draw );
}
diff --git a/src/mesa/pipe/draw/draw_private.h b/src/mesa/pipe/draw/draw_private.h
index 1285f3200c..04d38c4e0c 100644
--- a/src/mesa/pipe/draw/draw_private.h
+++ b/src/mesa/pipe/draw/draw_private.h
@@ -54,7 +54,8 @@
struct vertex_header {
unsigned clipmask:12;
unsigned edgeflag:1;
- unsigned pad:19;
+ unsigned pad:3;
+ unsigned vertex_id:16;
float clip[4];
@@ -230,6 +231,8 @@ extern int draw_vertex_cache_check_space( struct draw_context *draw,
extern void draw_vertex_cache_validate( struct draw_context *draw );
extern void draw_vertex_cache_invalidate( struct draw_context *draw );
extern void draw_vertex_cache_unreference( struct draw_context *draw );
+extern void draw_vertex_cache_reset_vertex_ids( struct draw_context *draw );
+
extern void draw_vertex_shader_queue_flush( struct draw_context *draw );
@@ -255,6 +258,7 @@ dup_vert( struct draw_stage *stage,
{
struct vertex_header *tmp = stage->tmp[idx];
memcpy(tmp, vert, stage->draw->vertex_info.size * sizeof(float) );
+ tmp->vertex_id = ~0;
return tmp;
}
diff --git a/src/mesa/pipe/draw/draw_vertex_cache.c b/src/mesa/pipe/draw/draw_vertex_cache.c
index f1b0cb14bd..a226798123 100644
--- a/src/mesa/pipe/draw/draw_vertex_cache.c
+++ b/src/mesa/pipe/draw/draw_vertex_cache.c
@@ -46,6 +46,8 @@ void draw_vertex_cache_invalidate( struct draw_context *draw )
for (i = 0; i < Elements( draw->vcache.idx ); i++)
draw->vcache.idx[i] = ~0;
+
+// fprintf(stderr, "x\n");
}
@@ -63,10 +65,14 @@ static struct vertex_header *get_vertex( struct draw_context *draw,
/* If slot is in use, use the overflow area:
*/
- if (draw->vcache.referenced & (1 << slot))
+ if (draw->vcache.referenced & (1 << slot)) {
+// fprintf(stderr, "o");
slot = VCACHE_SIZE + draw->vcache.overflow++;
- else
+ }
+ else {
+// fprintf(stderr, ".");
draw->vcache.referenced |= (1 << slot); /* slot now in use */
+ }
draw->vcache.idx[slot] = i;
@@ -79,7 +85,10 @@ static struct vertex_header *get_vertex( struct draw_context *draw,
/* Need to set the vertex's edge flag here. If we're being called
* by do_ef_triangle(), that function needs edge flag info!
*/
+ draw->vcache.vertex[slot]->clipmask = 0;
draw->vcache.vertex[slot]->edgeflag = 1; /*XXX use user's edge flag! */
+ draw->vcache.vertex[slot]->pad = 0;
+ draw->vcache.vertex[slot]->vertex_id = ~0;
}
return draw->vcache.vertex[slot];
@@ -110,6 +119,13 @@ static struct vertex_header *get_ubyte_elt_vertex( struct draw_context *draw,
}
+void draw_vertex_cache_reset_vertex_ids( struct draw_context *draw )
+{
+ unsigned i;
+
+ for (i = 0; i < Elements(draw->vcache.vertex); i++)
+ draw->vcache.vertex[i]->vertex_id = ~0;
+}
void draw_vertex_cache_validate( struct draw_context *draw )
{
diff --git a/src/mesa/pipe/draw/draw_vertex_shader.c b/src/mesa/pipe/draw/draw_vertex_shader.c
index ef0399c46e..fe4f124dd2 100644
--- a/src/mesa/pipe/draw/draw_vertex_shader.c
+++ b/src/mesa/pipe/draw/draw_vertex_shader.c
@@ -189,6 +189,8 @@ void draw_vertex_shader_queue_flush( struct draw_context *draw )
{
unsigned i, j;
+// fprintf(stderr, " q(%d) ", draw->vs.queue_nr );
+
/* run vertex shader on vertex cache entries, four per invokation */
for (i = 0; i < draw->vs.queue_nr; i += 4) {
struct vertex_header *dests[4];
diff --git a/src/mesa/pipe/softpipe/Makefile b/src/mesa/pipe/softpipe/Makefile
index 0335f56b99..63eb6b5761 100644
--- a/src/mesa/pipe/softpipe/Makefile
+++ b/src/mesa/pipe/softpipe/Makefile
@@ -10,6 +10,7 @@ DRIVER_SOURCES = \
sp_context.c \
sp_draw_arrays.c \
sp_prim_setup.c \
+ sp_prim_vbuf.c \
sp_quad.c \
sp_quad_alpha_test.c \
sp_quad_blend.c \
diff --git a/src/mesa/pipe/softpipe/sp_context.c b/src/mesa/pipe/softpipe/sp_context.c
index a6ab45314c..e415966dae 100644
--- a/src/mesa/pipe/softpipe/sp_context.c
+++ b/src/mesa/pipe/softpipe/sp_context.c
@@ -334,7 +334,19 @@ struct pipe_context *softpipe_create( struct pipe_winsys *pipe_winsys,
*/
softpipe->draw = draw_create();
assert(softpipe->draw);
- draw_set_rasterize_stage(softpipe->draw, sp_draw_render_stage(softpipe));
+ softpipe->setup = sp_draw_render_stage(softpipe);
+
+ if (getenv("SP_VBUF")) {
+ softpipe->vbuf = sp_draw_vbuf_stage(softpipe->draw,
+ &softpipe->pipe,
+ sp_vbuf_setup_draw);
+
+ draw_set_rasterize_stage(softpipe->draw, softpipe->vbuf);
+ }
+ else {
+ draw_set_rasterize_stage(softpipe->draw, softpipe->setup);
+ }
+
sp_init_region_functions(softpipe);
sp_init_surface_functions(softpipe);
diff --git a/src/mesa/pipe/softpipe/sp_context.h b/src/mesa/pipe/softpipe/sp_context.h
index 7b1518cfac..c0a681f3d6 100644
--- a/src/mesa/pipe/softpipe/sp_context.h
+++ b/src/mesa/pipe/softpipe/sp_context.h
@@ -146,6 +146,8 @@ struct softpipe_context {
/** The primitive drawing context */
struct draw_context *draw;
+ struct draw_stage *setup;
+ struct draw_stage *vbuf;
struct pipe_surface *cbuf; /**< current color buffer (one of cbufs) */
};
diff --git a/src/mesa/pipe/softpipe/sp_prim_setup.c b/src/mesa/pipe/softpipe/sp_prim_setup.c
index 6d63cc9412..2e27d00acf 100644
--- a/src/mesa/pipe/softpipe/sp_prim_setup.c
+++ b/src/mesa/pipe/softpipe/sp_prim_setup.c
@@ -41,7 +41,7 @@
#include "pipe/draw/draw_vertex.h"
#include "pipe/p_util.h"
-
+#define DEBUG_VERTS 0
/**
* Triangle edge info
@@ -241,15 +241,15 @@ static void flush_spans( struct setup_stage *setup )
setup->span.right[1] = 0;
}
-#if 0
+#if DEBUG_VERTS
static void print_vertex(const struct setup_stage *setup,
const struct vertex_header *v)
{
int i;
- printf("Vertex:\n");
+ fprintf(stderr, "Vertex: (%p)\n", v);
for (i = 0; i < setup->quad.nr_attrs; i++) {
- printf(" %d: %f %f %f\n", i,
- v->data[i][0], v->data[i][1], v->data[i][2]);
+ fprintf(stderr, " %d: %f %f %f %f\n", i,
+ v->data[i][0], v->data[i][1], v->data[i][2], v->data[i][3]);
}
}
#endif
@@ -261,8 +261,8 @@ static boolean setup_sort_vertices( struct setup_stage *setup,
const struct vertex_header *v1 = prim->v[1];
const struct vertex_header *v2 = prim->v[2];
-#if 0
- printf("Triangle:\n");
+#if DEBUG_VERTS
+ fprintf(stderr, "Triangle:\n");
print_vertex(setup, v0);
print_vertex(setup, v1);
print_vertex(setup, v2);
@@ -1096,3 +1096,85 @@ struct draw_stage *sp_draw_render_stage( struct softpipe_context *softpipe )
return &setup->stage;
}
+
+
+/* Recalculate det. This is only used in the test harness below:
+ */
+static void calc_det( struct prim_header *header )
+{
+ /* Window coords: */
+ const float *v0 = header->v[0]->data[0];
+ const float *v1 = header->v[1]->data[0];
+ const float *v2 = header->v[2]->data[0];
+
+ /* edge vectors e = v0 - v2, f = v1 - v2 */
+ const float ex = v0[0] - v2[0];
+ const float ey = v0[1] - v2[1];
+ const float fx = v1[0] - v2[0];
+ const float fy = v1[1] - v2[1];
+
+ /* det = cross(e,f).z */
+ header->det = ex * fy - ey * fx;
+}
+
+
+
+/* Test harness - feed vertex buffer back into prim pipeline.
+ *
+ * The big issue at this point is that reset_stipple doesn't make it
+ * through the interface. Probably need to split primitives at reset
+ * stipple, perhaps using the ~0 index marker.
+ */
+void sp_vbuf_setup_draw( struct pipe_context *pipe,
+ unsigned primitive,
+ const ushort *elements,
+ unsigned nr_elements,
+ const void *vertex_buffer,
+ unsigned nr_vertices )
+{
+ struct softpipe_context *softpipe = softpipe_context( pipe );
+ struct setup_stage *setup = setup_stage( softpipe->setup );
+ struct prim_header prim;
+ unsigned vertex_size = setup->stage.draw->vertex_info.size * sizeof(float);
+ int i, j;
+
+ prim.det = 0;
+ prim.reset_line_stipple = 0;
+ prim.edgeflags = 0;
+ prim.pad = 0;
+
+ setup->stage.begin( &setup->stage );
+
+ switch (primitive) {
+ case PIPE_PRIM_TRIANGLES:
+ for (i = 0; i < nr_elements; i += 3) {
+ for (j = 0; j < 3; j++)
+ prim.v[j] = (struct vertex_header *)((char *)vertex_buffer +
+ elements[i+j] * vertex_size);
+
+ calc_det(&prim);
+ setup->stage.tri( &setup->stage, &prim );
+ }
+ break;
+
+ case PIPE_PRIM_LINES:
+ for (i = 0; i < nr_elements; i += 2) {
+ for (j = 0; j < 2; j++)
+ prim.v[j] = (struct vertex_header *)((char *)vertex_buffer +
+ elements[i+j] * vertex_size);
+
+ setup->stage.line( &setup->stage, &prim );
+ }
+ break;
+
+ case PIPE_PRIM_POINTS:
+ for (i = 0; i < nr_elements; i += 2) {
+ prim.v[i] = (struct vertex_header *)((char *)vertex_buffer +
+ elements[i] * vertex_size);
+ setup->stage.point( &setup->stage, &prim );
+ }
+ break;
+ }
+
+ setup->stage.end( &setup->stage );
+}
diff --git a/src/mesa/pipe/softpipe/sp_prim_setup.h b/src/mesa/pipe/softpipe/sp_prim_setup.h
index dece42fe45..598394f73e 100644
--- a/src/mesa/pipe/softpipe/sp_prim_setup.h
+++ b/src/mesa/pipe/softpipe/sp_prim_setup.h
@@ -44,5 +44,39 @@ struct softpipe_context;
extern struct draw_stage *sp_draw_render_stage( struct softpipe_context *softpipe );
+/* A special stage to gather the stream of triangles, lines, points
+ * together and reconstruct vertex buffers for hardware upload.
+ *
+ * First attempt, work in progress.
+ *
+ * TODO:
+ * - separate out vertex buffer building and primitive emit, ie >1 draw per vb.
+ * - tell vbuf stage how to build hw vertices directly
+ * - pass vbuf stage a buffer pointer for direct emit to agp/vram.
+ */
+typedef void (*vbuf_draw_func)( struct pipe_context *pipe,
+ unsigned prim,
+ const ushort *elements,
+ unsigned nr_elements,
+ const void *vertex_buffer,
+ unsigned nr_vertices );
+
+
+extern struct draw_stage *sp_draw_vbuf_stage( struct draw_context *draw_context,
+ struct pipe_context *pipe,
+ vbuf_draw_func draw );
+
+
+
+/* Test harness
+ */
+void sp_vbuf_setup_draw( struct pipe_context *pipe,
+ unsigned prim,
+ const ushort *elements,
+ unsigned nr_elements,
+ const void *vertex_buffer,
+ unsigned nr_vertices );
+
+
#endif /* SP_PRIM_SETUP_H */
diff --git a/src/mesa/pipe/softpipe/sp_prim_vbuf.c b/src/mesa/pipe/softpipe/sp_prim_vbuf.c
new file mode 100644
index 0000000000..235903ca6d
--- /dev/null
+++ b/src/mesa/pipe/softpipe/sp_prim_vbuf.c
@@ -0,0 +1,305 @@
+/**************************************************************************
+ *
+ * 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.
+ *
+ **************************************************************************/
+
+/**
+ * Build post-transformation, post-clipping vertex buffers and element
+ * lists by hooking into the end of the primitive pipeline and
+ * manipulating the vertex_id field in the vertex headers.
+ *
+ * Keith Whitwell <keith@tungstengraphics.com>
+ */
+
+
+#include "sp_context.h"
+#include "sp_headers.h"
+#include "sp_quad.h"
+#include "sp_prim_setup.h"
+#include "pipe/draw/draw_private.h"
+#include "pipe/draw/draw_vertex.h"
+#include "pipe/p_util.h"
+
+static void vbuf_flush_elements( struct draw_stage *stage );
+
+
+#define VBUF_SIZE (64*1024)
+#define IBUF_SIZE (16*1024)
+
+
+/**
+ * Vertex buffer emit stage.
+ */
+struct vbuf_stage {
+ struct draw_stage stage; /**< This must be first (base class) */
+
+ struct draw_context *draw_context;
+ struct pipe_context *pipe;
+ vbuf_draw_func draw;
+
+ /* Vertices are passed in as an array of floats making up each
+ * attribute in turn. Will eventually convert to hardware format
+ * in this stage.
+ */
+ char *vertex_map;
+ char *vertex_ptr;
+ unsigned vertex_size;
+ unsigned nr_vertices;
+
+ unsigned max_vertices;
+
+ ushort *element_map;
+ unsigned nr_elements;
+
+ unsigned prim;
+
+};
+
+/**
+ * Basically a cast wrapper.
+ */
+static INLINE struct vbuf_stage *vbuf_stage( struct draw_stage *stage )
+{
+ return (struct vbuf_stage *)stage;
+}
+
+
+
+
+static boolean overflow( void *map, void *ptr, unsigned bytes, unsigned bufsz )
+{
+ unsigned long used = (char *)ptr - (char *)map;
+ return (used + bytes) > bufsz;
+}
+
+
+static boolean check_space( struct vbuf_stage *vbuf )
+{
+ if (overflow( vbuf->vertex_map,
+ vbuf->vertex_ptr,
+ 4 * vbuf->vertex_size,
+ VBUF_SIZE ))
+ return FALSE;
+
+
+ if (vbuf->nr_elements + 4 > IBUF_SIZE / sizeof(ushort) )
+ return FALSE;
+
+ return TRUE;
+}
+
+
+static void emit_vertex( struct vbuf_stage *vbuf,
+ struct vertex_header *vertex )
+{
+ fprintf(stderr, "emit vertex %d to %p\n",
+ vbuf->nr_vertices, vbuf->vertex_ptr);
+
+ vertex->vertex_id = vbuf->nr_vertices++;
+
+ //vbuf->emit_vertex( vbuf->vertex_ptr, vertex );
+ memcpy(vbuf->vertex_ptr, vertex, vbuf->vertex_size);
+
+ vbuf->vertex_ptr += vbuf->vertex_size;
+}
+
+
+
+/**
+ *
+ */
+static void vbuf_tri( struct draw_stage *stage,
+ struct prim_header *prim )
+{
+ struct vbuf_stage *vbuf = vbuf_stage( stage );
+ unsigned i;
+
+ if (!check_space( vbuf ))
+ vbuf_flush_elements( stage );
+
+ for (i = 0; i < 3; i++) {
+ if (prim->v[i]->vertex_id == 0xffff)
+ emit_vertex( vbuf, prim->v[i] );
+
+ vbuf->element_map[vbuf->nr_elements++] = prim->v[i]->vertex_id;
+ }
+}
+
+
+static void vbuf_line(struct draw_stage *stage,
+ struct prim_header *prim)
+{
+ struct vbuf_stage *vbuf = vbuf_stage( stage );
+ unsigned i;
+
+ if (!check_space( vbuf ))
+ vbuf_flush_elements( stage );
+
+ for (i = 0; i < 2; i++) {
+ if (prim->v[i]->vertex_id == 0xffff)
+ emit_vertex( vbuf, prim->v[i] );
+
+ vbuf->element_map[vbuf->nr_elements++] = prim->v[i]->vertex_id;
+ }
+}
+
+
+static void vbuf_point(struct draw_stage *stage,
+ struct prim_header *prim)
+{
+ struct vbuf_stage *vbuf = vbuf_stage( stage );
+
+ if (!check_space( vbuf ))
+ vbuf_flush_elements( stage );
+
+ if (prim->v[0]->vertex_id == 0xffff)
+ emit_vertex( vbuf, prim->v[0] );
+
+ vbuf->element_map[vbuf->nr_elements++] = prim->v[0]->vertex_id;
+}
+
+
+static void vbuf_first_tri( struct draw_stage *stage,
+ struct prim_header *prim )
+{
+ struct vbuf_stage *vbuf = vbuf_stage( stage );
+
+ vbuf_flush_elements( stage );
+ stage->tri = vbuf_tri;
+ stage->tri( stage, prim );
+ vbuf->prim = PIPE_PRIM_TRIANGLES;
+}
+
+static void vbuf_first_line( struct draw_stage *stage,
+ struct prim_header *prim )
+{
+ struct vbuf_stage *vbuf = vbuf_stage( stage );
+
+ vbuf_flush_elements( stage );
+ stage->line = vbuf_line;
+ stage->line( stage, prim );
+ vbuf->prim = PIPE_PRIM_LINES;
+}
+
+static void vbuf_first_point( struct draw_stage *stage,
+ struct prim_header *prim )
+{
+ struct vbuf_stage *vbuf = vbuf_stage( stage );
+
+ vbuf_flush_elements( stage );
+ stage->point = vbuf_point;
+ stage->point( stage, prim );
+ vbuf->prim = PIPE_PRIM_POINTS;
+}
+
+
+
+static void vbuf_flush_elements( struct draw_stage *stage )
+{
+ struct vbuf_stage *vbuf = vbuf_stage( stage );
+
+ if (vbuf->nr_elements) {
+ fprintf(stderr, "%s (%d elts)\n", __FUNCTION__, vbuf->nr_elements);
+
+ /* Draw now or add to list of primitives???
+ */
+ vbuf->draw( vbuf->pipe,
+ vbuf->prim,
+ vbuf->element_map,
+ vbuf->nr_elements,
+ vbuf->vertex_map,
+ (vbuf->vertex_ptr - vbuf->vertex_map) / vbuf->vertex_size );
+
+ vbuf->nr_elements = 0;
+
+ vbuf->vertex_ptr = vbuf->vertex_map;
+ vbuf->nr_vertices = 0;
+
+ /* Reset vertex ids? Actually, want to not do that unless our
+ * vertex buffer is full. Would like separate
+ * flush-on-index-full and flush-on-vb-full, but may raise
+ * issues uploading vertices if the hardware wants to flush when
+ * we flush.
+ */
+ draw_vertex_cache_reset_vertex_ids( vbuf->draw_context );
+ }
+
+ stage->tri = vbuf_first_tri;
+ stage->line = vbuf_first_line;
+ stage->point = vbuf_first_point;
+}
+
+
+static void vbuf_begin( struct draw_stage *stage )
+{
+ struct vbuf_stage *vbuf = vbuf_stage(stage);
+
+ vbuf->vertex_size = vbuf->draw_context->vertex_info.size * sizeof(float);
+}
+
+
+static void vbuf_end( struct draw_stage *stage )
+{
+ /* Overkill.
+ */
+ vbuf_flush_elements( stage );
+}
+
+
+static void reset_stipple_counter( struct draw_stage *stage )
+{
+ /* XXX: This doesn't work.
+ */
+}
+
+
+/**
+ * Create a new primitive vbuf/render stage.
+ */
+struct draw_stage *sp_draw_vbuf_stage( struct draw_context *draw_context,
+ struct pipe_context *pipe,
+ vbuf_draw_func draw )
+{
+ struct vbuf_stage *vbuf = CALLOC_STRUCT(vbuf_stage);
+
+ vbuf->stage.begin = vbuf_begin;
+ vbuf->stage.point = vbuf_first_point;
+ vbuf->stage.line = vbuf_first_line;
+ vbuf->stage.tri = vbuf_first_tri;
+ vbuf->stage.end = vbuf_end;
+ vbuf->stage.reset_stipple_counter = reset_stipple_counter;
+
+ vbuf->pipe = pipe;
+ vbuf->draw = draw;
+ vbuf->draw_context = draw_context;
+
+ vbuf->element_map = malloc( IBUF_SIZE );
+ vbuf->vertex_map = malloc( VBUF_SIZE );
+
+ vbuf->vertex_ptr = vbuf->vertex_map;
+
+
+ return &vbuf->stage;
+}