diff options
-rw-r--r-- | src/mesa/drivers/x11/xm_softpipe.c | 9 | ||||
-rw-r--r-- | src/mesa/pipe/draw/draw_context.c | 10 | ||||
-rw-r--r-- | src/mesa/pipe/draw/draw_context.h | 4 | ||||
-rw-r--r-- | src/mesa/pipe/draw/draw_prim.c | 6 | ||||
-rw-r--r-- | src/mesa/pipe/draw/draw_private.h | 5 | ||||
-rw-r--r-- | src/mesa/pipe/softpipe/sp_context.c | 4 | ||||
-rw-r--r-- | src/mesa/pipe/softpipe/sp_context.h | 5 | ||||
-rw-r--r-- | src/mesa/pipe/softpipe/sp_draw_arrays.c | 224 | ||||
-rw-r--r-- | src/mesa/pipe/softpipe/sp_state_derived.c | 2 | ||||
-rw-r--r-- | src/mesa/state_tracker/st_atom.c | 1 | ||||
-rw-r--r-- | src/mesa/state_tracker/st_atom.h | 1 | ||||
-rw-r--r-- | src/mesa/state_tracker/st_atom_fs.c | 3 | ||||
-rw-r--r-- | src/mesa/state_tracker/st_atom_vs.c | 31 | ||||
-rw-r--r-- | src/mesa/state_tracker/st_context.c | 6 | ||||
-rw-r--r-- | src/mesa/state_tracker/st_context.h | 2 | ||||
-rw-r--r-- | src/mesa/state_tracker/st_draw.c | 113 | ||||
-rw-r--r-- | src/mesa/tnl/t_vp_build.c | 2 | ||||
-rw-r--r-- | src/mesa/vbo/vbo.h | 3 | ||||
-rw-r--r-- | src/mesa/vbo/vbo_exec_api.c | 35 | ||||
-rw-r--r-- | src/mesa/vbo/vbo_exec_draw.c | 17 |
20 files changed, 295 insertions, 188 deletions
diff --git a/src/mesa/drivers/x11/xm_softpipe.c b/src/mesa/drivers/x11/xm_softpipe.c index 09edea6265..432f306e94 100644 --- a/src/mesa/drivers/x11/xm_softpipe.c +++ b/src/mesa/drivers/x11/xm_softpipe.c @@ -51,6 +51,7 @@ struct xm_softpipe_winsys struct xm_buffer { int refcount; + int size; void *data; void *mapped; }; @@ -129,8 +130,12 @@ xm_buffer_data(struct pipe_winsys *pws, struct pipe_buffer_handle *buf, unsigned size, const void *data ) { struct xm_buffer *xm_buf = xm_bo(buf); - assert(!xm_buf->data); - xm_buf->data = malloc(size); + if (xm_buf->size != size) { + if (xm_buf->data) + free(xm_buf->data); + xm_buf->data = malloc(size); + xm_buf->size = size; + } if (data) memcpy(xm_buf->data, data, size); } diff --git a/src/mesa/pipe/draw/draw_context.c b/src/mesa/pipe/draw/draw_context.c index d5d7d408de..a808fb7777 100644 --- a/src/mesa/pipe/draw/draw_context.c +++ b/src/mesa/pipe/draw/draw_context.c @@ -201,13 +201,3 @@ void draw_set_viewport_state( struct draw_context *draw, * Full pipe will have vertex shader, vertex fetch of its own. */ } - - -void draw_set_vertex_array_info(struct draw_context *draw, - const struct pipe_vertex_buffer *buffers, - const struct pipe_vertex_element *elements) -{ - draw->vertex_buffer = buffers; - draw->vertex_element = elements; -} - diff --git a/src/mesa/pipe/draw/draw_context.h b/src/mesa/pipe/draw/draw_context.h index 19fddf7104..74fdd46262 100644 --- a/src/mesa/pipe/draw/draw_context.h +++ b/src/mesa/pipe/draw/draw_context.h @@ -98,10 +98,6 @@ void draw_set_vertex_attributes2( struct draw_context *draw, const unsigned *attrs, unsigned nr_attrs ); -void draw_set_vertex_array_info(struct draw_context *draw, - const struct pipe_vertex_buffer *buffers, - const struct pipe_vertex_element *elements); - /* XXX temporary */ void draw_vb(struct draw_context *draw, struct vertex_buffer *VB ); diff --git a/src/mesa/pipe/draw/draw_prim.c b/src/mesa/pipe/draw/draw_prim.c index 7757dacf34..95e71efd6d 100644 --- a/src/mesa/pipe/draw/draw_prim.c +++ b/src/mesa/pipe/draw/draw_prim.c @@ -258,8 +258,10 @@ static void do_quad( struct draw_context *draw, unsigned v2, unsigned v3 ) { - do_ef_triangle( draw, 1, ~(1<<0), v0, v1, v3 ); - do_ef_triangle( draw, 0, ~(1<<1), v1, v2, v3 ); + const unsigned omitEdge2 = ~(1 << 1); + const unsigned omitEdge3 = ~(1 << 2); + do_ef_triangle( draw, 1, omitEdge2, v0, v1, v3 ); + do_ef_triangle( draw, 0, omitEdge3, v1, v2, v3 ); } diff --git a/src/mesa/pipe/draw/draw_private.h b/src/mesa/pipe/draw/draw_private.h index 278950ec48..798fa5c3a6 100644 --- a/src/mesa/pipe/draw/draw_private.h +++ b/src/mesa/pipe/draw/draw_private.h @@ -158,8 +158,6 @@ struct draw_context /* pipe state that we need: */ struct pipe_setup_state setup; struct pipe_viewport_state viewport; - const struct pipe_vertex_buffer *vertex_buffer; /**< note: pointer */ - const struct pipe_vertex_element *vertex_element; /**< note: pointer */ /** need to know the pipe for vertex flushing/transformation: */ struct pipe_context *pipe; @@ -230,9 +228,6 @@ struct draw_context ubyte *verts; boolean in_vb; struct vertex_fetch *vf; - - /* Misc for sp_draw_arrays.c (temporary?) */ - void *mapped_vbuffer; }; diff --git a/src/mesa/pipe/softpipe/sp_context.c b/src/mesa/pipe/softpipe/sp_context.c index e63ce208d4..ea2f0ec04f 100644 --- a/src/mesa/pipe/softpipe/sp_context.c +++ b/src/mesa/pipe/softpipe/sp_context.c @@ -322,10 +322,6 @@ struct pipe_context *softpipe_create( struct pipe_winsys *pipe_winsys, assert(softpipe->draw); draw_set_setup_stage(softpipe->draw, sp_draw_render_stage(softpipe)); - draw_set_vertex_array_info(softpipe->draw, - softpipe->vertex_buffer, - softpipe->vertex_element); - 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 8f184c644a..14ae9f2105 100644 --- a/src/mesa/pipe/softpipe/sp_context.h +++ b/src/mesa/pipe/softpipe/sp_context.h @@ -101,6 +101,11 @@ struct softpipe_context { */ enum interp_mode interp[PIPE_ATTRIB_MAX]; + /* + * Mapped vertex buffers + */ + ubyte *mapped_vbuffer[PIPE_ATTRIB_MAX]; + /* FS + setup derived state: */ diff --git a/src/mesa/pipe/softpipe/sp_draw_arrays.c b/src/mesa/pipe/softpipe/sp_draw_arrays.c index 8f684ba00a..a7fb39ca09 100644 --- a/src/mesa/pipe/softpipe/sp_draw_arrays.c +++ b/src/mesa/pipe/softpipe/sp_draw_arrays.c @@ -87,6 +87,36 @@ compute_clipmask(float cx, float cy, float cz, float cw) } +/** + * Fetch a float[4] vertex attribute from memory, doing format/type + * conversion as needed. + * XXX this might be a temporary thing. + */ +static void +fetch_attrib4(const void *ptr, unsigned format, float attrib[4]) +{ + /* defaults */ + attrib[1] = 0.0; + attrib[2] = 0.0; + attrib[3] = 1.0; + switch (format) { + case PIPE_FORMAT_R32G32B32A32_FLOAT: + attrib[3] = ((float *) ptr)[3]; + /* fall-through */ + case PIPE_FORMAT_R32G32B32_FLOAT: + attrib[2] = ((float *) ptr)[2]; + /* fall-through */ + case PIPE_FORMAT_R32G32_FLOAT: + attrib[1] = ((float *) ptr)[1]; + /* fall-through */ + case PIPE_FORMAT_R32_FLOAT: + attrib[0] = ((float *) ptr)[0]; + break; + default: + assert(0); + } +} + /** * Transform vertices with the current vertex program/shader @@ -97,18 +127,17 @@ compute_clipmask(float cx, float cy, float cz, float cw) * \param vOut array of pointers to four output vertices */ static void -run_vertex_program(struct draw_context *draw, - const void *vbuffer, unsigned elts[4], unsigned count, +run_vertex_program(struct softpipe_context *sp, + unsigned elts[4], unsigned count, struct vertex_header *vOut[]) { - struct softpipe_context *sp = softpipe_context(draw->pipe); struct tgsi_exec_machine machine; unsigned int j; ALIGN16_DECL(struct tgsi_exec_vector, inputs, PIPE_ATTRIB_MAX); ALIGN16_DECL(struct tgsi_exec_vector, outputs, PIPE_ATTRIB_MAX); - const float *scale = draw->viewport.scale; - const float *trans = draw->viewport.translate; + const float *scale = sp->viewport.scale; + const float *trans = sp->viewport.translate; assert(count <= 4); @@ -129,21 +158,45 @@ run_vertex_program(struct draw_context *draw, machine.Inputs = ALIGN16_ASSIGN(inputs); machine.Outputs = ALIGN16_ASSIGN(outputs); + + if (0) + { + unsigned attr; + for (attr = 0; attr < 16; attr++) { + if (sp->vs.inputs_read & (1 << attr)) { + printf("attr %d: buf_off %d src_off %d pitch %d\n", + attr, + sp->vertex_buffer[attr].buffer_offset, + sp->vertex_element[attr].src_offset, + sp->vertex_buffer[attr].pitch); + } + } + } + /* load machine inputs */ for (j = 0; j < count; j++) { unsigned attr; for (attr = 0; attr < 16; attr++) { if (sp->vs.inputs_read & (1 << attr)) { - const float *p - = (const float *) ((const ubyte *) vbuffer - + draw->vertex_buffer[attr].buffer_offset - + draw->vertex_element[attr].src_offset - + elts[j] * draw->vertex_buffer[attr].pitch); + const void *src + = (const void *) ((const ubyte *) sp->mapped_vbuffer[attr] + + sp->vertex_buffer[attr].buffer_offset + + sp->vertex_element[attr].src_offset + + elts[j] * sp->vertex_buffer[attr].pitch); + float p[4]; + + fetch_attrib4(src, sp->vertex_element[attr].src_format, p); machine.Inputs[attr].xyzw[0].f[j] = p[0]; /*X*/ machine.Inputs[attr].xyzw[1].f[j] = p[1]; /*Y*/ machine.Inputs[attr].xyzw[2].f[j] = p[2]; /*Z*/ - machine.Inputs[attr].xyzw[3].f[j] = 1.0; /*W*/ + machine.Inputs[attr].xyzw[3].f[j] = p[3]; /*W*/ +#if 0 + if (attr == 0) { + printf("Input vertex %d: %f %f %f\n", + j, p[0], p[1], p[2]); + } +#endif } } } @@ -173,7 +226,7 @@ run_vertex_program(struct draw_context *draw, /* store machine results */ assert(sp->vs.outputs_written & (1 << VERT_RESULT_HPOS)); for (j = 0; j < count; j++) { - unsigned attr; + unsigned attr, slot; float x, y, z, w; /* Handle attr[0] (position) specially: */ @@ -183,7 +236,7 @@ run_vertex_program(struct draw_context *draw, w = vOut[j]->clip[3] = outputs[0].xyzw[3].f[j]; vOut[j]->clipmask = compute_clipmask(x, y, z, w); - vOut[j]->edgeflag = 0; + vOut[j]->edgeflag = 1; /* divide by w */ w = 1.0 / w; @@ -204,12 +257,16 @@ run_vertex_program(struct draw_context *draw, #endif /* remaining attributes: */ + /* pack into sequential post-transform attrib slots */ + slot = 1; for (attr = 1; attr < VERT_RESULT_MAX; attr++) { if (sp->vs.outputs_written & (1 << attr)) { - vOut[j]->data[attr][0] = outputs[attr].xyzw[0].f[j]; - vOut[j]->data[attr][1] = outputs[attr].xyzw[1].f[j]; - vOut[j]->data[attr][2] = outputs[attr].xyzw[2].f[j]; - vOut[j]->data[attr][3] = outputs[attr].xyzw[3].f[j]; + assert(slot < sp->nr_attrs); + vOut[j]->data[slot][0] = outputs[attr].xyzw[0].f[j]; + vOut[j]->data[slot][1] = outputs[attr].xyzw[1].f[j]; + vOut[j]->data[slot][2] = outputs[attr].xyzw[2].f[j]; + vOut[j]->data[slot][3] = outputs[attr].xyzw[3].f[j]; + slot++; } } } @@ -224,114 +281,16 @@ run_vertex_program(struct draw_context *draw, /** - * Stand-in for actual vertex program execution - * XXX this will probably live in a new file, like "sp_vs.c" - * \param draw the drawing context - * \param vbuffer the mapped vertex buffer pointer - * \param elem which element of the vertex buffer to use as input - * \param vOut the output vertex - */ -#if 0 -static void -run_vertex_program(struct draw_context *draw, - const void *vbuffer, unsigned elem, - struct vertex_header *vOut) -{ - const float *vIn, *cIn; - const float *scale = draw->viewport.scale; - const float *trans = draw->viewport.translate; - const void *mapped = vbuffer; - - /* XXX temporary hack: */ - GET_CURRENT_CONTEXT(ctx); - const float *m = ctx->_ModelProjectMatrix.m; - - vIn = (const float *) ((const ubyte *) mapped - + draw->vertex_buffer[0].buffer_offset - + draw->vertex_element[0].src_offset - + elem * draw->vertex_buffer[0].pitch); - - cIn = (const float *) ((const ubyte *) mapped - + draw->vertex_buffer[3].buffer_offset - + draw->vertex_element[3].src_offset - + elem * draw->vertex_buffer[3].pitch); - - { - float x = vIn[0]; - float y = vIn[1]; - float z = vIn[2]; - float w = 1.0; - - vOut->clipmask = 0x0; - vOut->edgeflag = 0; - /* MVP */ - vOut->clip[0] = m[0] * x + m[4] * y + m[ 8] * z + m[12] * w; - vOut->clip[1] = m[1] * x + m[5] * y + m[ 9] * z + m[13] * w; - vOut->clip[2] = m[2] * x + m[6] * y + m[10] * z + m[14] * w; - vOut->clip[3] = m[3] * x + m[7] * y + m[11] * z + m[15] * w; - - /* divide by w */ - x = vOut->clip[0] / vOut->clip[3]; - y = vOut->clip[1] / vOut->clip[3]; - z = vOut->clip[2] / vOut->clip[3]; - w = 1.0 / vOut->clip[3]; - - /* Viewport */ - vOut->data[0][0] = scale[0] * x + trans[0]; - vOut->data[0][1] = scale[1] * y + trans[1]; - vOut->data[0][2] = scale[2] * z + trans[2]; - vOut->data[0][3] = w; - - /* color */ - vOut->data[1][0] = cIn[0]; - vOut->data[1][1] = cIn[1]; - vOut->data[1][2] = cIn[2]; - vOut->data[1][3] = 1.0; - } -} -#endif - - -/** * Called by the draw module when the vertx cache needs to be flushed. * This involves running the vertex shader. */ static void vs_flush( struct draw_context *draw ) { + struct softpipe_context *sp = (struct softpipe_context *) draw->pipe; unsigned i, j; - /* We're not really running a vertex shader yet, so flushing the vs - * queue is just a matter of building the vertices and returning. - */ - /* Actually, I'm cheating even more and pre-building them still - * with the mesa/vf module. So it's very easy... - */ -#if 0 - for (i = 0; i < draw->vs.queue_nr; i++) { -#else - for (i = 0; i < draw->vs.queue_nr; i+=4) { -#endif - /* Would do the following steps here: - * - * 1) Loop over vertex element descriptors, fetch data from each - * to build the pre-tnl vertex. This might require a new struct - * to represent the pre-tnl vertex. - * - * 2) Bundle groups of upto 4 pre-tnl vertices together and pass - * to vertex shader. - * - * 3) Do any necessary unswizzling, make sure vertex headers are - * correctly populated, store resulting post-transformed - * vertices in vcache. - * - * In this version, just do the last step: - */ -#if 0 - const unsigned elt = draw->vs.queue[i].elt; - struct vertex_header *dest = draw->vs.queue[i].dest; - - run_vertex_program(draw, draw->mapped_vbuffer, elt, dest); -#else + /* 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]; unsigned elts[4]; int n; @@ -345,9 +304,9 @@ static void vs_flush( struct draw_context *draw ) assert(n > 0); assert(n <= 4); - run_vertex_program(draw, draw->mapped_vbuffer, elts, n, dests); -#endif + run_vertex_program(sp, elts, n, dests); } + draw->vs.queue_nr = 0; } @@ -359,17 +318,24 @@ softpipe_draw_arrays(struct pipe_context *pipe, unsigned mode, { struct softpipe_context *sp = softpipe_context(pipe); struct draw_context *draw = sp->draw; - struct pipe_buffer_handle *buf; + unsigned int i; + + if (sp->dirty) + softpipe_update_derived( sp ); softpipe_map_surfaces(sp); /* * Map vertex buffers */ - buf = sp->vertex_buffer[0].buffer; - draw->mapped_vbuffer - = pipe->winsys->buffer_map(pipe->winsys, buf, PIPE_BUFFER_FLAG_READ); - + for (i = 0; i < PIPE_ATTRIB_MAX; i++) { + if (sp->vertex_buffer[i].buffer) { + sp->mapped_vbuffer[i] + = pipe->winsys->buffer_map(pipe->winsys, + sp->vertex_buffer[i].buffer, + PIPE_BUFFER_FLAG_READ); + } + } /* tell drawing pipeline we're beginning drawing */ draw->pipeline.first->begin( draw->pipeline.first ); @@ -392,9 +358,13 @@ softpipe_draw_arrays(struct pipe_context *pipe, unsigned mode, draw->pipeline.first->end( draw->pipeline.first ); /* - * unmap vertex buffer + * unmap vertex buffers */ - pipe->winsys->buffer_unmap(pipe->winsys, buf); + for (i = 0; i < PIPE_ATTRIB_MAX; i++) { + if (sp->vertex_buffer[i].buffer) { + pipe->winsys->buffer_unmap(pipe->winsys, sp->vertex_buffer[i].buffer); + } + } softpipe_unmap_surfaces(sp); } diff --git a/src/mesa/pipe/softpipe/sp_state_derived.c b/src/mesa/pipe/softpipe/sp_state_derived.c index 35f1a971ca..95b0cfee03 100644 --- a/src/mesa/pipe/softpipe/sp_state_derived.c +++ b/src/mesa/pipe/softpipe/sp_state_derived.c @@ -216,7 +216,7 @@ static void calculate_vertex_layout( struct softpipe_context *softpipe ) if (attr_mask != softpipe->attr_mask) { softpipe->attr_mask = attr_mask; -#define USE_NEW_DRAW 0 +#define USE_NEW_DRAW 01 #if USE_NEW_DRAW draw_set_vertex_attributes2( softpipe->draw, slot_to_vf_attr, diff --git a/src/mesa/state_tracker/st_atom.c b/src/mesa/state_tracker/st_atom.c index 32b8b8f277..d67291e50b 100644 --- a/src/mesa/state_tracker/st_atom.c +++ b/src/mesa/state_tracker/st_atom.c @@ -46,6 +46,7 @@ static const struct st_tracked_state *atoms[] = &st_update_clear_color, &st_update_depth, &st_update_clip, + &st_update_tnl, &st_update_vs, &st_update_fs, &st_update_setup, diff --git a/src/mesa/state_tracker/st_atom.h b/src/mesa/state_tracker/st_atom.h index 2f628206ca..51da489f6d 100644 --- a/src/mesa/state_tracker/st_atom.h +++ b/src/mesa/state_tracker/st_atom.h @@ -48,6 +48,7 @@ const struct st_tracked_state st_update_framebuffer; const struct st_tracked_state st_update_clip; const struct st_tracked_state st_update_clear_color; const struct st_tracked_state st_update_depth; +const struct st_tracked_state st_update_tnl; const struct st_tracked_state st_update_fs; const struct st_tracked_state st_update_vs; const struct st_tracked_state st_update_setup; diff --git a/src/mesa/state_tracker/st_atom_fs.c b/src/mesa/state_tracker/st_atom_fs.c index 41ad49b317..9aba9aaa56 100644 --- a/src/mesa/state_tracker/st_atom_fs.c +++ b/src/mesa/state_tracker/st_atom_fs.c @@ -74,6 +74,9 @@ static void update_fs( struct st_context *st ) if (fp && params) { /* load program's constants array */ + + _mesa_load_state_parameters(st->ctx, params); + fp->constants.nr_constants = params->NumParameters; memcpy(fp->constants.constant, params->ParameterValues, diff --git a/src/mesa/state_tracker/st_atom_vs.c b/src/mesa/state_tracker/st_atom_vs.c index cef6e38d56..c8bd805e02 100644 --- a/src/mesa/state_tracker/st_atom_vs.c +++ b/src/mesa/state_tracker/st_atom_vs.c @@ -1,6 +1,6 @@ /************************************************************************** * - * Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas. + * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas. * All Rights Reserved. * * Permission is hereby granted, free of charge, to any person obtaining a @@ -27,9 +27,11 @@ /* * Authors: * Keith Whitwell <keith@tungstengraphics.com> + * Brian Paul */ #include "shader/prog_parameter.h" +#include "tnl/t_vp_build.h" #include "pipe/p_context.h" #include "pipe/tgsi/mesa/mesa_to_tgsi.h" @@ -39,6 +41,7 @@ #include "st_atom.h" #include "st_program.h" + #define TGSI_DEBUG 0 static void compile_vs( struct st_context *st, @@ -59,8 +62,10 @@ static void update_vs( struct st_context *st ) struct st_vertex_program *vp = NULL; struct gl_program_parameter_list *params = NULL; +#if 0 if (st->ctx->VertexProgram._MaintainTnlProgram) _tnl_UpdateFixedFunctionProgram( st->ctx ); +#endif if (st->ctx->Shader.CurrentProgram && st->ctx->Shader.CurrentProgram->LinkStatus && @@ -83,6 +88,7 @@ static void update_vs( struct st_context *st ) if (vp && params) { /* load program's constants array */ + /* XXX this should probably be done elsewhere/separately */ _mesa_load_state_parameters(st->ctx, params); vp->constants.nr_constants = params->NumParameters; @@ -117,3 +123,26 @@ const struct st_tracked_state st_update_vs = { }, .update = update_vs }; + + + + + +/** + * When TnL state has changed, need to generate new vertex program. + * This should be done before updating the vertes shader (vs) state. + */ +static void update_tnl( struct st_context *st ) +{ + if (st->ctx->VertexProgram._MaintainTnlProgram) + _tnl_UpdateFixedFunctionProgram( st->ctx ); +} + + +const struct st_tracked_state st_update_tnl = { + .dirty = { + .mesa = _NEW_PROGRAM | _NEW_LIGHT | _NEW_TEXTURE, /* XXX more? */ + .st = ST_NEW_MESA, /* XXX correct? */ + }, + .update = update_tnl +}; diff --git a/src/mesa/state_tracker/st_context.c b/src/mesa/state_tracker/st_context.c index 35a262ab5b..9e89ece52e 100644 --- a/src/mesa/state_tracker/st_context.c +++ b/src/mesa/state_tracker/st_context.c @@ -25,7 +25,8 @@ * **************************************************************************/ -#include "imports.h" +#include "main/imports.h" +#include "vbo/vbo.h" #include "st_public.h" #include "st_context.h" #include "st_cb_bufferobjects.h" @@ -68,6 +69,9 @@ struct st_context *st_create_context( GLcontext *ctx, st_init_atoms( st ); st_init_draw( st ); + /* we want all vertex data to be placed in buffer objects */ + vbo_use_buffer_objects(ctx); + /* Need these flags: */ st->ctx->FragmentProgram._MaintainTexEnvProgram = GL_TRUE; diff --git a/src/mesa/state_tracker/st_context.h b/src/mesa/state_tracker/st_context.h index 25ed20a5f8..35774a790e 100644 --- a/src/mesa/state_tracker/st_context.h +++ b/src/mesa/state_tracker/st_context.h @@ -104,6 +104,8 @@ struct st_context struct st_state_flags dirty; GLfloat polygon_offset_scale; /* ?? */ + + struct pipe_buffer_handle *default_attrib_buffer; }; diff --git a/src/mesa/state_tracker/st_draw.c b/src/mesa/state_tracker/st_draw.c index 425076d653..db24b24fa7 100644 --- a/src/mesa/state_tracker/st_draw.c +++ b/src/mesa/state_tracker/st_draw.c @@ -44,6 +44,7 @@ #include "st_cb_bufferobjects.h" #include "pipe/p_context.h" #include "pipe/p_defines.h" +#include "pipe/p_winsys.h" #include "vbo/vbo_context.h" @@ -52,7 +53,7 @@ * bypassing the T&L module. This only works with VBO-based demos, * such as progs/test/bufferobj.c */ -#define USE_NEW_DRAW 0 +#define USE_NEW_DRAW 01 /* @@ -135,6 +136,38 @@ pipe_vertex_format(GLenum format, GLuint size) /** + * The default attribute buffer is basically a copy of the + * ctx->Current.Attrib[] array. It's used when the vertex program + * references an attribute for which we don't have a VBO/array. + */ +static void +create_default_attribs_buffer(struct st_context *st) +{ + struct pipe_context *pipe = st->pipe; + st->default_attrib_buffer = pipe->winsys->buffer_create( pipe->winsys, 32 ); +} + + +static void +destroy_default_attribs_buffer(struct st_context *st) +{ + struct pipe_context *pipe = st->pipe; + pipe->winsys->buffer_unreference(pipe->winsys, &st->default_attrib_buffer); +} + + +static void +update_default_attribs_buffer(GLcontext *ctx) +{ + struct pipe_context *pipe = ctx->st->pipe; + struct pipe_buffer_handle *buf = ctx->st->default_attrib_buffer; + const unsigned size = sizeof(ctx->Current.Attrib); + const void *data = ctx->Current.Attrib; + pipe->winsys->buffer_data(pipe->winsys, buf, size, data); +} + + +/** * This function gets plugged into the VBO module and is called when * we have something to render. * Basically, translate the information into the format expected by pipe. @@ -150,41 +183,66 @@ draw_vbo(GLcontext *ctx, { struct pipe_context *pipe = ctx->st->pipe; GLuint attr, i; + GLbitfield attrsNeeded; + const unsigned attr0_offset = (unsigned) arrays[0]->Ptr; st_validate_state(ctx->st); + update_default_attribs_buffer(ctx); + /* this must be after state validation */ + attrsNeeded = ctx->st->state.vs.inputs_read; /* tell pipe about the vertex array element/attributes */ for (attr = 0; attr < 16; attr++) { - struct gl_buffer_object *bufobj = arrays[attr]->BufferObj; struct pipe_vertex_buffer vbuffer; struct pipe_vertex_element velement; - if (bufobj && bufobj->Name) { - struct st_buffer_object *stobj = st_buffer_object(bufobj); - - assert(stobj->buffer); - - vbuffer.pitch = arrays[attr]->StrideB; /* in bytes */ - vbuffer.max_index = 0; - vbuffer.buffer = stobj->buffer; - vbuffer.buffer_offset = 0; - - /* Recall that for VBOs, the gl_client_array->Ptr field is - * really an offset from the start of the VBO, not a pointer. - */ - velement.src_offset = (unsigned) arrays[attr]->Ptr; - velement.vertex_buffer_index = attr; - velement.dst_offset = 0; - velement.src_format = pipe_vertex_format(arrays[attr]->Type, - arrays[attr]->Size); + vbuffer.buffer = NULL; + vbuffer.pitch = 0; + velement.src_offset = 0; + velement.vertex_buffer_index = 0; + velement.src_format = 0; + + if (attrsNeeded & (1 << attr)) { + struct gl_buffer_object *bufobj = arrays[attr]->BufferObj; + + if (bufobj && bufobj->Name) { + struct st_buffer_object *stobj = st_buffer_object(bufobj); + /* Recall that for VBOs, the gl_client_array->Ptr field is + * really an offset from the start of the VBO, not a pointer. + */ + unsigned offset = (unsigned) arrays[attr]->Ptr; + + assert(stobj->buffer); + + vbuffer.buffer = stobj->buffer; + vbuffer.buffer_offset = attr0_offset; /* in bytes */ + vbuffer.pitch = arrays[attr]->StrideB; /* in bytes */ + vbuffer.max_index = 0; /* need this? */ + + velement.src_offset = offset - attr0_offset; /* bytes */ + velement.vertex_buffer_index = attr; + velement.dst_offset = 0; /* need this? */ + velement.src_format = pipe_vertex_format(arrays[attr]->Type, + arrays[attr]->Size); + assert(velement.src_format); + } + else { + /* use the default attribute buffer */ + vbuffer.buffer = ctx->st->default_attrib_buffer; + vbuffer.buffer_offset = 0; + vbuffer.pitch = 0; /* must be zero! */ + vbuffer.max_index = 1; + + velement.src_offset = attr * 4 * sizeof(GLfloat); + velement.vertex_buffer_index = attr; + velement.dst_offset = 0; + velement.src_format = PIPE_FORMAT_R32G32B32A32_FLOAT; + } } - else { - /* vertex attribute data is not an a real buffer! */ - /* XXX we'll want to handle that someday... */ - vbuffer.buffer = NULL; - } + if (attr == 0) + assert(vbuffer.buffer); pipe->set_vertex_buffer(pipe, attr, &vbuffer); pipe->set_vertex_element(pipe, attr, &velement); @@ -209,6 +267,8 @@ void st_init_draw( struct st_context *st ) #if USE_NEW_DRAW struct vbo_context *vbo = (struct vbo_context *) ctx->swtnl_im; + create_default_attribs_buffer(st); + assert(vbo); assert(vbo->draw_prims); vbo->draw_prims = draw_vbo; @@ -224,8 +284,7 @@ void st_init_draw( struct st_context *st ) void st_destroy_draw( struct st_context *st ) { - /* Nothing to do. - */ + destroy_default_attribs_buffer(st); } diff --git a/src/mesa/tnl/t_vp_build.c b/src/mesa/tnl/t_vp_build.c index ee1a2498b3..eb5e176895 100644 --- a/src/mesa/tnl/t_vp_build.c +++ b/src/mesa/tnl/t_vp_build.c @@ -146,7 +146,7 @@ static struct state_key *make_state_key( GLcontext *ctx ) } for (i = _TNL_FIRST_MAT; i <= _TNL_LAST_MAT; i++) - if (VB->AttribPtr[i]->stride) + if (VB->AttribPtr[i] && VB->AttribPtr[i]->stride) key->light_material_mask |= 1<<(i-_TNL_ATTRIB_MAT_FRONT_AMBIENT); for (i = 0; i < MAX_LIGHTS; i++) { diff --git a/src/mesa/vbo/vbo.h b/src/mesa/vbo/vbo.h index 04c59c05b2..4c51b44cda 100644 --- a/src/mesa/vbo/vbo.h +++ b/src/mesa/vbo/vbo.h @@ -114,4 +114,7 @@ void vbo_rebase_prims( GLcontext *ctx, vbo_draw_func draw ); +void vbo_use_buffer_objects(GLcontext *ctx); + + #endif diff --git a/src/mesa/vbo/vbo_exec_api.c b/src/mesa/vbo/vbo_exec_api.c index 7f56b3b629..24e2eba472 100644 --- a/src/mesa/vbo/vbo_exec_api.c +++ b/src/mesa/vbo/vbo_exec_api.c @@ -631,6 +631,41 @@ static void vbo_exec_vtxfmt_init( struct vbo_exec_context *exec ) } +/** + * Tell the VBO module to use a real OpenGL vertex buffer object to + * store accumulated immediate-mode vertex data. + * This replaces the malloced buffer which was created in + * vb_exec_vtx_init() below. + */ +void vbo_use_buffer_objects(GLcontext *ctx) +{ + struct vbo_exec_context *exec = &vbo_context(ctx)->exec; + /* Any buffer name but 0 can be used here since this bufferobj won't + * go into the bufferobj hashtable. + */ + GLuint bufName = 0xaabbccdd; + GLenum target = GL_ARRAY_BUFFER_ARB; + GLenum access = GL_READ_WRITE_ARB; + GLenum usage = GL_STREAM_DRAW_ARB; + GLsizei size = VBO_VERT_BUFFER_SIZE * sizeof(GLfloat); + + /* Make sure this func is only used once */ + assert(exec->vtx.bufferobj == ctx->Array.NullBufferObj); + if (exec->vtx.buffer_map) { + _mesa_align_free(exec->vtx.buffer_map); + } + + /* Allocate a real buffer object now */ + exec->vtx.bufferobj = ctx->Driver.NewBufferObject(ctx, bufName, target); + ctx->Driver.BufferData(ctx, target, size, NULL, usage, exec->vtx.bufferobj); + + /* and map it */ + exec->vtx.buffer_map + = ctx->Driver.MapBuffer(ctx, target, access, exec->vtx.bufferobj); +} + + + void vbo_exec_vtx_init( struct vbo_exec_context *exec ) { GLcontext *ctx = exec->ctx; diff --git a/src/mesa/vbo/vbo_exec_draw.c b/src/mesa/vbo/vbo_exec_draw.c index 0ef26cdfe3..68aba1df66 100644 --- a/src/mesa/vbo/vbo_exec_draw.c +++ b/src/mesa/vbo/vbo_exec_draw.c @@ -175,16 +175,27 @@ static void vbo_exec_bind_arrays( GLcontext *ctx ) * arrays of floats. */ for (attr = 0; attr < VERT_ATTRIB_MAX ; attr++) { - GLuint src = map[attr]; + const GLuint src = map[attr]; if (exec->vtx.attrsz[src]) { - arrays[attr].Ptr = (void *)data; + if (exec->vtx.bufferobj->Name) { + /* a real buffer obj: Ptr is an offset, not a pointer*/ + int offset; + assert(exec->vtx.bufferobj->Pointer); /* buf should be mapped */ + offset = (GLbyte *) data - (GLbyte *) exec->vtx.bufferobj->Pointer; + assert(offset >= 0); + arrays[attr].Ptr = (void *) offset; + } + else { + /* Ptr into ordinary app memory */ + arrays[attr].Ptr = (void *) data; + } arrays[attr].Size = exec->vtx.attrsz[src]; arrays[attr].StrideB = exec->vtx.vertex_size * sizeof(GLfloat); arrays[attr].Stride = exec->vtx.vertex_size * sizeof(GLfloat); arrays[attr].Type = GL_FLOAT; arrays[attr].Enabled = 1; - arrays[attr].BufferObj = exec->vtx.bufferobj; /* NullBufferObj */ + arrays[attr].BufferObj = exec->vtx.bufferobj; arrays[attr]._MaxElement = count; /* ??? */ data += exec->vtx.attrsz[attr] * sizeof(GLfloat); |