diff options
Diffstat (limited to 'src/mesa/tnl/t_draw.c')
-rw-r--r-- | src/mesa/tnl/t_draw.c | 173 |
1 files changed, 133 insertions, 40 deletions
diff --git a/src/mesa/tnl/t_draw.c b/src/mesa/tnl/t_draw.c index c84a10856e..0e7c2b6a68 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" @@ -41,13 +42,13 @@ -static GLfloat *get_space(GLcontext *ctx, GLuint bytes) +static GLubyte *get_space(GLcontext *ctx, GLuint bytes) { TNLcontext *tnl = TNL_CONTEXT(ctx); GLubyte *space = _mesa_malloc(bytes); tnl->block[tnl->nr_blocks++] = space; - return (GLfloat *)space; + return space; } @@ -97,7 +98,7 @@ static void _tnl_import_array( GLcontext *ctx, GLuint start, GLuint end, const struct gl_client_array *input, - const char *ptr ) + const GLubyte *ptr ) { TNLcontext *tnl = TNL_CONTEXT(ctx); struct vertex_buffer *VB = &tnl->vb; @@ -108,7 +109,8 @@ static void _tnl_import_array( GLcontext *ctx, if (input->Type != GL_FLOAT) { const GLuint sz = input->Size; - GLfloat *fptr = get_space(ctx, count * sz * sizeof(GLfloat)); + GLubyte *buf = get_space(ctx, count * sz * sizeof(GLfloat)); + GLfloat *fptr = (GLfloat *)buf; switch (input->Type) { case GL_BYTE: @@ -137,7 +139,7 @@ static void _tnl_import_array( GLcontext *ctx, break; } - ptr = (const char *)fptr; + ptr = buf; stride = sz * sizeof(GLfloat); } @@ -181,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 ) { @@ -197,7 +199,7 @@ static void bind_inputs( GLcontext *ctx, if (inputs[i]->BufferObj->Name) { if (!inputs[i]->BufferObj->Pointer) { bo[*nr_bo] = inputs[i]->BufferObj; - *nr_bo++; + (*nr_bo)++; ctx->Driver.MapBuffer(ctx, GL_ARRAY_BUFFER, GL_READ_ONLY_ARB, @@ -213,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]; @@ -255,20 +262,23 @@ 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; + GLuint i; + void *ptr; if (!ib) return; if (ib->obj->Name && !ib->obj->Pointer) { bo[*nr_bo] = ib->obj; - *nr_bo++; + (*nr_bo)++; ctx->Driver.MapBuffer(ctx, GL_ELEMENT_ARRAY_BUFFER, GL_READ_ONLY_ARB, @@ -277,19 +287,63 @@ static void bind_indicies( GLcontext *ctx, assert(ib->obj->Pointer); } - VB->Elts = (GLuint *)ADD_POINTERS(ib->obj->Pointer, - ib->ptr); - - VB->Elts += ib->rebase; + ptr = ADD_POINTERS(ib->obj->Pointer, ib->ptr); - switch (ib->type) { - case GL_UNSIGNED_INT: - return; - case GL_UNSIGNED_SHORT: - break; - case GL_UNSIGNED_BYTE: - break; + if (ib->type == GL_UNSIGNED_INT && min_index == 0) { + VB->Elts = (GLuint *) ptr; + VB->Elts += ib->rebase; + } + else { + GLuint *elts = (GLuint *)get_space(ctx, ib->count * sizeof(GLuint)); + 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++ = (GLuint)(*in++) - min_index; + break; + } + case GL_UNSIGNED_BYTE: { + const GLubyte *in = ((GLubyte *)ptr) + ib->rebase; + for (i = 0; i < ib->count; i++) + *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, @@ -320,26 +374,65 @@ void _tnl_draw_prims( GLcontext *ctx, { TNLcontext *tnl = TNL_CONTEXT(ctx); struct vertex_buffer *VB = &tnl->vb; + GLint max = VB->Size; - /* 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; +#ifdef TEST_SPLIT + max = 8 + MAX_CLIPPED_VERTICES; +#endif + + assert(max_index > min_index); + assert(!(max_index & 0x80000000)); + + VB->Elts = NULL; - /* Binding inputs may imply mapping some vertex buffer objects. - * They will need to be unmapped below. +#if 0 + { + GLuint i; + _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); + } } |