From 5464cd0a60f474753abc6af047fd21b0e29b8ac4 Mon Sep 17 00:00:00 2001 From: Keith Whitwell Date: Mon, 15 Jan 2007 13:54:08 +0000 Subject: Split too-large draw commands. Use the vbo_split_ functionality to split incoming drawing command to fit within the fixed-size buffers used by software t&l module. --- src/mesa/tnl/t_draw.c | 128 ++++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 102 insertions(+), 26 deletions(-) (limited to 'src/mesa/tnl/t_draw.c') diff --git a/src/mesa/tnl/t_draw.c b/src/mesa/tnl/t_draw.c index 0f9615e7cc..25b8708948 100644 --- a/src/mesa/tnl/t_draw.c +++ b/src/mesa/tnl/t_draw.c @@ -32,6 +32,7 @@ #include "state.h" #include "mtypes.h" #include "macros.h" +#include "enums.h" #include "t_context.h" #include "t_pipeline.h" @@ -182,7 +183,7 @@ static GLboolean *_tnl_import_edgeflag( GLcontext *ctx, static void bind_inputs( GLcontext *ctx, const struct gl_client_array *inputs[], - GLint start, GLint end, + GLint min_index, GLint max_index, struct gl_buffer_object **bo, GLuint *nr_bo ) { @@ -214,15 +215,20 @@ static void bind_inputs( GLcontext *ctx, ptr = inputs[i]->Ptr; /* Just make sure the array is floating point, otherwise convert to - * temporary storage. Rebase arrays so that 'start' becomes + * temporary storage. Rebase arrays so that 'min_index' becomes * element zero. * * XXX: remove the GLvector4f type at some stage and just use * client arrays. */ - _tnl_import_array(ctx, i, start, end, inputs[i], ptr); + _tnl_import_array(ctx, i, min_index, max_index, inputs[i], ptr); } + /* We process only the vertices between min & max index: + */ + VB->Count = max_index - min_index; + + /* Legacy pointers -- remove one day. */ VB->ObjPtr = VB->AttribPtr[_TNL_ATTRIB_POS]; @@ -256,10 +262,11 @@ static void bind_inputs( GLcontext *ctx, /* Translate indices to GLuints and store in VB->Elts. */ -static void bind_indicies( GLcontext *ctx, - const struct _mesa_index_buffer *ib, - struct gl_buffer_object **bo, - GLuint *nr_bo) +static void bind_indices( GLcontext *ctx, + const struct _mesa_index_buffer *ib, + GLuint min_index, + struct gl_buffer_object **bo, + GLuint *nr_bo) { TNLcontext *tnl = TNL_CONTEXT(ctx); struct vertex_buffer *VB = &tnl->vb; @@ -282,7 +289,7 @@ static void bind_indicies( GLcontext *ctx, ptr = ADD_POINTERS(ib->obj->Pointer, ib->ptr); - if (ib->type == GL_UNSIGNED_INT) { + if (ib->type == GL_UNSIGNED_INT && min_index == 0) { VB->Elts = (GLuint *) ptr; VB->Elts += ib->rebase; } @@ -291,22 +298,54 @@ static void bind_indicies( GLcontext *ctx, VB->Elts = elts; switch (ib->type) { + case GL_UNSIGNED_INT: { + const GLuint *in = ((GLuint *)ptr) + ib->rebase; + for (i = 0; i < ib->count; i++) + *elts++ = *in++ - min_index; + break; + } case GL_UNSIGNED_SHORT: { const GLushort *in = ((GLushort *)ptr) + ib->rebase; for (i = 0; i < ib->count; i++) - *elts++ = *in++; + *elts++ = (GLuint)(*in++) - min_index; break; } case GL_UNSIGNED_BYTE: { const GLubyte *in = ((GLubyte *)ptr) + ib->rebase; for (i = 0; i < ib->count; i++) - *elts++ = *in++; + *elts++ = (GLuint)(*in++) - min_index; break; } } } } +static void bind_prims( GLcontext *ctx, + const struct _mesa_prim *prim, + GLuint nr_prims, + GLuint min_index ) +{ + TNLcontext *tnl = TNL_CONTEXT(ctx); + struct vertex_buffer *VB = &tnl->vb; + GLuint i; + + if (min_index != 0) { + struct _mesa_prim *tmp = (struct _mesa_prim *)get_space(ctx, nr_prims * sizeof(*prim)); + + for (i = 0; i < nr_prims; i++) { + tmp[i] = prim[i]; + tmp[i].start -= min_index; + } + + VB->Primitive = tmp; + } + else { + VB->Primitive = prim; + } + + VB->PrimitiveCount = nr_prims; +} + static void unmap_vbos( GLcontext *ctx, struct gl_buffer_object **bo, GLuint nr_bo ) @@ -335,26 +374,63 @@ void _tnl_draw_prims( GLcontext *ctx, { TNLcontext *tnl = TNL_CONTEXT(ctx); struct vertex_buffer *VB = &tnl->vb; + GLint max = VB->Size; + GLuint i; - /* May need to map a vertex buffer object for every attribute plus - * one for the index buffer. - */ - struct gl_buffer_object *bo[VERT_ATTRIB_MAX + 1]; - GLuint nr_bo = 0; - - /* Binding inputs may imply mapping some vertex buffer objects. - * They will need to be unmapped below. +#ifdef TEST_SPLIT + max = 8 + MAX_CLIPPED_VERTICES; +#endif + + assert(max_index > min_index); + assert(!(max_index & 0x80000000)); + + VB->Elts = NULL; + +#if 0 + _mesa_printf("%s %d..%d\n", __FUNCTION__, min_index, max_index); + for (i = 0; i < nr_prims; i++) + _mesa_printf("prim %d: %s start %d count %d\n", i, + _mesa_lookup_enum_by_nr(prim[i].mode), + prim[i].start, + prim[i].count); +#endif + + /* The software TNL pipeline has a fixed amount of storage for + * vertices and it is necessary to split incoming drawing commands + * if they exceed that limit. */ - bind_inputs(ctx, arrays, min_index, max_index, bo, &nr_bo); - bind_indicies(ctx, ib, bo, &nr_bo); + if (max_index - min_index >= max - MAX_CLIPPED_VERTICES) { + struct split_limits limits; + limits.max_verts = max - MAX_CLIPPED_VERTICES; + limits.max_vb_size = ~0; + limits.max_indices = ~0; + + /* This will split the buffers one way or another and + * recursively call back into this function. + */ + vbo_split_prims( ctx, arrays, prim, nr_prims, ib, + min_index, max_index, + _tnl_draw_prims, + &limits ); + } + else { + /* May need to map a vertex buffer object for every attribute plus + * one for the index buffer. + */ + struct gl_buffer_object *bo[VERT_ATTRIB_MAX + 1]; + GLuint nr_bo = 0; - VB->Primitive = prim; - VB->PrimitiveCount = nr_prims; - VB->Count = max_index - min_index; + /* Binding inputs may imply mapping some vertex buffer objects. + * They will need to be unmapped below. + */ + bind_inputs(ctx, arrays, min_index, max_index+1, bo, &nr_bo); + bind_indices(ctx, ib, min_index, bo, &nr_bo); + bind_prims(ctx, prim, nr_prims, VB->Elts ? 0 : min_index ); - TNL_CONTEXT(ctx)->Driver.RunPipeline(ctx); + TNL_CONTEXT(ctx)->Driver.RunPipeline(ctx); - unmap_vbos(ctx, bo, nr_bo); - free_space(ctx); + unmap_vbos(ctx, bo, nr_bo); + free_space(ctx); + } } -- cgit v1.2.3