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.
This commit is contained in:
@@ -32,6 +32,7 @@
|
|||||||
#include "state.h"
|
#include "state.h"
|
||||||
#include "mtypes.h"
|
#include "mtypes.h"
|
||||||
#include "macros.h"
|
#include "macros.h"
|
||||||
|
#include "enums.h"
|
||||||
|
|
||||||
#include "t_context.h"
|
#include "t_context.h"
|
||||||
#include "t_pipeline.h"
|
#include "t_pipeline.h"
|
||||||
@@ -182,7 +183,7 @@ static GLboolean *_tnl_import_edgeflag( GLcontext *ctx,
|
|||||||
|
|
||||||
static void bind_inputs( GLcontext *ctx,
|
static void bind_inputs( GLcontext *ctx,
|
||||||
const struct gl_client_array *inputs[],
|
const struct gl_client_array *inputs[],
|
||||||
GLint start, GLint end,
|
GLint min_index, GLint max_index,
|
||||||
struct gl_buffer_object **bo,
|
struct gl_buffer_object **bo,
|
||||||
GLuint *nr_bo )
|
GLuint *nr_bo )
|
||||||
{
|
{
|
||||||
@@ -214,15 +215,20 @@ static void bind_inputs( GLcontext *ctx,
|
|||||||
ptr = inputs[i]->Ptr;
|
ptr = inputs[i]->Ptr;
|
||||||
|
|
||||||
/* Just make sure the array is floating point, otherwise convert to
|
/* 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.
|
* element zero.
|
||||||
*
|
*
|
||||||
* XXX: remove the GLvector4f type at some stage and just use
|
* XXX: remove the GLvector4f type at some stage and just use
|
||||||
* client arrays.
|
* 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.
|
/* Legacy pointers -- remove one day.
|
||||||
*/
|
*/
|
||||||
VB->ObjPtr = VB->AttribPtr[_TNL_ATTRIB_POS];
|
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.
|
/* Translate indices to GLuints and store in VB->Elts.
|
||||||
*/
|
*/
|
||||||
static void bind_indicies( GLcontext *ctx,
|
static void bind_indices( GLcontext *ctx,
|
||||||
const struct _mesa_index_buffer *ib,
|
const struct _mesa_index_buffer *ib,
|
||||||
struct gl_buffer_object **bo,
|
GLuint min_index,
|
||||||
GLuint *nr_bo)
|
struct gl_buffer_object **bo,
|
||||||
|
GLuint *nr_bo)
|
||||||
{
|
{
|
||||||
TNLcontext *tnl = TNL_CONTEXT(ctx);
|
TNLcontext *tnl = TNL_CONTEXT(ctx);
|
||||||
struct vertex_buffer *VB = &tnl->vb;
|
struct vertex_buffer *VB = &tnl->vb;
|
||||||
@@ -282,7 +289,7 @@ static void bind_indicies( GLcontext *ctx,
|
|||||||
|
|
||||||
ptr = ADD_POINTERS(ib->obj->Pointer, ib->ptr);
|
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 = (GLuint *) ptr;
|
||||||
VB->Elts += ib->rebase;
|
VB->Elts += ib->rebase;
|
||||||
}
|
}
|
||||||
@@ -291,22 +298,54 @@ static void bind_indicies( GLcontext *ctx,
|
|||||||
VB->Elts = elts;
|
VB->Elts = elts;
|
||||||
|
|
||||||
switch (ib->type) {
|
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: {
|
case GL_UNSIGNED_SHORT: {
|
||||||
const GLushort *in = ((GLushort *)ptr) + ib->rebase;
|
const GLushort *in = ((GLushort *)ptr) + ib->rebase;
|
||||||
for (i = 0; i < ib->count; i++)
|
for (i = 0; i < ib->count; i++)
|
||||||
*elts++ = *in++;
|
*elts++ = (GLuint)(*in++) - min_index;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case GL_UNSIGNED_BYTE: {
|
case GL_UNSIGNED_BYTE: {
|
||||||
const GLubyte *in = ((GLubyte *)ptr) + ib->rebase;
|
const GLubyte *in = ((GLubyte *)ptr) + ib->rebase;
|
||||||
for (i = 0; i < ib->count; i++)
|
for (i = 0; i < ib->count; i++)
|
||||||
*elts++ = *in++;
|
*elts++ = (GLuint)(*in++) - min_index;
|
||||||
break;
|
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,
|
static void unmap_vbos( GLcontext *ctx,
|
||||||
struct gl_buffer_object **bo,
|
struct gl_buffer_object **bo,
|
||||||
GLuint nr_bo )
|
GLuint nr_bo )
|
||||||
@@ -335,26 +374,63 @@ void _tnl_draw_prims( GLcontext *ctx,
|
|||||||
{
|
{
|
||||||
TNLcontext *tnl = TNL_CONTEXT(ctx);
|
TNLcontext *tnl = TNL_CONTEXT(ctx);
|
||||||
struct vertex_buffer *VB = &tnl->vb;
|
struct vertex_buffer *VB = &tnl->vb;
|
||||||
|
GLint max = VB->Size;
|
||||||
|
GLuint i;
|
||||||
|
|
||||||
/* May need to map a vertex buffer object for every attribute plus
|
#ifdef TEST_SPLIT
|
||||||
* one for the index buffer.
|
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.
|
||||||
*/
|
*/
|
||||||
struct gl_buffer_object *bo[VERT_ATTRIB_MAX + 1];
|
if (max_index - min_index >= max - MAX_CLIPPED_VERTICES) {
|
||||||
GLuint nr_bo = 0;
|
struct split_limits limits;
|
||||||
|
limits.max_verts = max - MAX_CLIPPED_VERTICES;
|
||||||
|
limits.max_vb_size = ~0;
|
||||||
|
limits.max_indices = ~0;
|
||||||
|
|
||||||
/* Binding inputs may imply mapping some vertex buffer objects.
|
/* This will split the buffers one way or another and
|
||||||
* They will need to be unmapped below.
|
* recursively call back into this function.
|
||||||
*/
|
*/
|
||||||
bind_inputs(ctx, arrays, min_index, max_index, bo, &nr_bo);
|
vbo_split_prims( ctx, arrays, prim, nr_prims, ib,
|
||||||
bind_indicies(ctx, ib, bo, &nr_bo);
|
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;
|
/* Binding inputs may imply mapping some vertex buffer objects.
|
||||||
VB->PrimitiveCount = nr_prims;
|
* They will need to be unmapped below.
|
||||||
VB->Count = max_index - min_index;
|
*/
|
||||||
|
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);
|
unmap_vbos(ctx, bo, nr_bo);
|
||||||
free_space(ctx);
|
free_space(ctx);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user