Use new rebase helper. Remove other rebase code.

This commit is contained in:
Keith Whitwell
2007-01-30 20:22:55 +00:00
parent 240641de0c
commit 893526b8a8
8 changed files with 187 additions and 235 deletions

View File

@@ -198,7 +198,9 @@ static void brw_merge_inputs( struct brw_context *brw,
brw->state.dirty.brw |= BRW_NEW_INPUT_VARYING; brw->state.dirty.brw |= BRW_NEW_INPUT_VARYING;
} }
/* XXX: could split the primitive list to fallback only on the
* non-conformant primitives.
*/
static GLboolean check_fallbacks( struct brw_context *brw, static GLboolean check_fallbacks( struct brw_context *brw,
const struct _mesa_prim *prim, const struct _mesa_prim *prim,
GLuint nr_prims ) GLuint nr_prims )
@@ -251,7 +253,9 @@ static GLboolean check_fallbacks( struct brw_context *brw,
return GL_FALSE; return GL_FALSE;
} }
/* May fail if out of video memory for texture or vbo upload, or on
* fallback conditions.
*/
static GLboolean brw_try_draw_prims( GLcontext *ctx, static GLboolean brw_try_draw_prims( GLcontext *ctx,
const struct gl_client_array *arrays[], const struct gl_client_array *arrays[],
const struct _mesa_prim *prim, const struct _mesa_prim *prim,
@@ -376,6 +380,33 @@ static GLboolean brw_try_draw_prims( GLcontext *ctx,
return retval; return retval;
} }
static GLboolean brw_need_rebase( GLcontext *ctx,
const struct gl_client_array *arrays[],
const struct _mesa_index_buffer *ib,
GLuint min_index )
{
if (min_index == 0)
return GL_FALSE;
if (ib) {
if (!vbo_all_varyings_in_vbos(arrays))
return GL_TRUE;
else
return GL_FALSE;
}
else {
/* Hmm. This isn't quite what I wanted. BRW can actually
* handle the mixed case well enough that we shouldn't need to
* rebase. However, it's probably not very common, nor hugely
* expensive to do it this way:
*/
if (!vbo_all_varyings_in_vbos(arrays))
return GL_TRUE;
else
return GL_FALSE;
}
}
void brw_draw_prims( GLcontext *ctx, void brw_draw_prims( GLcontext *ctx,
const struct gl_client_array *arrays[], const struct gl_client_array *arrays[],
@@ -388,6 +419,21 @@ void brw_draw_prims( GLcontext *ctx,
struct intel_context *intel = intel_context(ctx); struct intel_context *intel = intel_context(ctx);
GLboolean retval; GLboolean retval;
/* Decide if we want to rebase. If so we end up recursing once
* only into this function.
*/
if (brw_need_rebase( ctx, arrays, ib, min_index )) {
vbo_rebase_prims( ctx, arrays,
prim, nr_prims,
ib, min_index, max_index,
brw_draw_prims );
return;
}
/* Make a first attempt at drawing:
*/
retval = brw_try_draw_prims(ctx, arrays, prim, nr_prims, ib, min_index, max_index); retval = brw_try_draw_prims(ctx, arrays, prim, nr_prims, ib, min_index, max_index);
@@ -440,14 +486,13 @@ void brw_draw_init( struct brw_context *brw )
for (i = 0; i < BRW_NR_UPLOAD_BUFS; i++) { for (i = 0; i < BRW_NR_UPLOAD_BUFS; i++) {
brw->vb.upload.vbo[i] = ctx->Driver.NewBufferObject(ctx, 1, GL_ARRAY_BUFFER_ARB); brw->vb.upload.vbo[i] = ctx->Driver.NewBufferObject(ctx, 1, GL_ARRAY_BUFFER_ARB);
/* XXX: Set these to no-backing-store /* NOTE: These are set to no-backing-store.
*/ */
bmBufferSetInvalidateCB(&brw->intel, bmBufferSetInvalidateCB(&brw->intel,
intel_bufferobj_buffer(intel_buffer_object(brw->vb.upload.vbo[i])), intel_bufferobj_buffer(intel_buffer_object(brw->vb.upload.vbo[i])),
brw_invalidate_vbo_cb, brw_invalidate_vbo_cb,
&brw->intel, &brw->intel,
GL_TRUE); GL_TRUE);
} }
ctx->Driver.BufferData( ctx, ctx->Driver.BufferData( ctx,

View File

@@ -309,7 +309,6 @@ copy_array_to_vbo_array( struct brw_context *brw,
GLuint i, GLuint i,
const struct gl_client_array *array, const struct gl_client_array *array,
GLuint element_size, GLuint element_size,
GLuint min_index,
GLuint count) GLuint count)
{ {
GLcontext *ctx = &brw->intel.ctx; GLcontext *ctx = &brw->intel.ctx;
@@ -347,7 +346,7 @@ copy_array_to_vbo_array( struct brw_context *brw,
map += offset; map += offset;
copy_strided_array( map, copy_strided_array( map,
array->Ptr + min_index * array->StrideB, array->Ptr,
element_size, element_size,
array->StrideB, array->StrideB,
count); count);
@@ -438,10 +437,8 @@ GLboolean brw_upload_vertices( struct brw_context *brw,
} }
upload[nr_uploads++] = input; upload[nr_uploads++] = input;
input->vbo_rebase_offset = 0; assert(min_index == 0);
} }
else
input->vbo_rebase_offset = min_index * input->glarray->StrideB;
} }
/* Upload interleaved arrays if all uploads are interleaved /* Upload interleaved arrays if all uploads are interleaved
@@ -454,7 +451,6 @@ GLboolean brw_upload_vertices( struct brw_context *brw,
input0->glarray = copy_array_to_vbo_array(brw, 0, input0->glarray = copy_array_to_vbo_array(brw, 0,
input0->glarray, input0->glarray,
interleave, interleave,
min_index,
input0->count); input0->count);
for (i = 1; i < nr_uploads; i++) { for (i = 1; i < nr_uploads; i++) {
@@ -472,7 +468,6 @@ GLboolean brw_upload_vertices( struct brw_context *brw,
input->glarray = copy_array_to_vbo_array(brw, i, input->glarray = copy_array_to_vbo_array(brw, i,
input->glarray, input->glarray,
input->element_size, input->element_size,
min_index,
input->count); input->count);
} }
@@ -520,9 +515,9 @@ GLboolean brw_upload_vertices( struct brw_context *brw,
vbp.vb[i].vb0.bits.pad = 0; vbp.vb[i].vb0.bits.pad = 0;
vbp.vb[i].vb0.bits.access_type = BRW_VERTEXBUFFER_ACCESS_VERTEXDATA; vbp.vb[i].vb0.bits.access_type = BRW_VERTEXBUFFER_ACCESS_VERTEXDATA;
vbp.vb[i].vb0.bits.vb_index = i; vbp.vb[i].vb0.bits.vb_index = i;
vbp.vb[i].offset = (GLuint)input->glarray->Ptr + input->vbo_rebase_offset; vbp.vb[i].offset = (GLuint)input->glarray->Ptr;
vbp.vb[i].buffer = array_buffer(input->glarray); vbp.vb[i].buffer = array_buffer(input->glarray);
vbp.vb[i].max_index = max_index - min_index; vbp.vb[i].max_index = max_index;
} }
@@ -563,93 +558,31 @@ static GLuint element_size( GLenum type )
void brw_upload_indices( struct brw_context *brw,
static void rebase_indices_to_vbo_indices( struct brw_context *brw, const struct _mesa_index_buffer *index_buffer )
const struct _mesa_index_buffer *index_buffer,
struct gl_buffer_object **vbo_return,
GLuint *offset_return )
{ {
GLcontext *ctx = &brw->intel.ctx; GLcontext *ctx = &brw->intel.ctx;
GLuint min_index = index_buffer->rebase;
const void *indices = index_buffer->ptr;
GLsizei count = index_buffer->count;
GLenum type = index_buffer->type;
GLuint size = element_size(type) * count;
struct gl_buffer_object *bufferobj;
GLuint offset;
GLuint i;
get_space(brw, size, &bufferobj, &offset);
*vbo_return = bufferobj;
*offset_return = offset;
if (min_index == 0) {
/* Straight upload
*/
ctx->Driver.BufferSubData( ctx,
GL_ELEMENT_ARRAY_BUFFER_ARB,
offset,
size,
indices,
bufferobj);
}
else {
void *map = ctx->Driver.MapBuffer(ctx,
GL_ELEMENT_ARRAY_BUFFER_ARB,
GL_DYNAMIC_DRAW_ARB,
bufferobj);
map += offset;
switch (type) {
case GL_UNSIGNED_INT: {
GLuint *ui_map = (GLuint *)map;
const GLuint *ui_indices = (const GLuint *)indices;
for (i = 0; i < count; i++)
ui_map[i] = ui_indices[i] - min_index;
break;
}
case GL_UNSIGNED_SHORT: {
GLushort *us_map = (GLushort *)map;
const GLushort *us_indices = (const GLushort *)indices;
for (i = 0; i < count; i++)
us_map[i] = us_indices[i] - min_index;
break;
}
case GL_UNSIGNED_BYTE: {
GLubyte *ub_map = (GLubyte *)map;
const GLubyte *ub_indices = (const GLubyte *)indices;
for (i = 0; i < count; i++)
ub_map[i] = ub_indices[i] - min_index;
break;
}
}
ctx->Driver.UnmapBuffer(ctx,
GL_ELEMENT_ARRAY_BUFFER_ARB,
bufferobj);
}
}
void brw_upload_indices( struct brw_context *brw,
const struct _mesa_index_buffer *index_buffer)
{
struct intel_context *intel = &brw->intel; struct intel_context *intel = &brw->intel;
GLuint ib_size = get_size(index_buffer->type) * index_buffer->count; GLuint ib_size = get_size(index_buffer->type) * index_buffer->count;
struct gl_buffer_object *bufferobj = index_buffer->obj; struct gl_buffer_object *bufferobj = index_buffer->obj;
GLuint offset = (GLuint)index_buffer->ptr; GLuint offset = (GLuint)index_buffer->ptr;
/* Already turned into a proper VBO: /* Turn into a proper VBO:
*/ */
if (!index_buffer->obj->Name) { if (!bufferobj->Name) {
rebase_indices_to_vbo_indices(brw, index_buffer, &bufferobj, &offset );
/* Get new bufferobj, offset:
*/
get_space(brw, ib_size, &bufferobj, &offset);
/* Straight upload
*/
ctx->Driver.BufferSubData( ctx,
GL_ELEMENT_ARRAY_BUFFER_ARB,
offset,
ib_size,
index_buffer->ptr,
bufferobj);
} }
/* Emit the indexbuffer packet: /* Emit the indexbuffer packet:

View File

@@ -95,18 +95,14 @@ static void free_space(GLcontext *ctx)
*/ */
static void _tnl_import_array( GLcontext *ctx, static void _tnl_import_array( GLcontext *ctx,
GLuint attrib, GLuint attrib,
GLuint start, GLuint count,
GLuint end,
const struct gl_client_array *input, const struct gl_client_array *input,
const GLubyte *ptr ) const GLubyte *ptr )
{ {
TNLcontext *tnl = TNL_CONTEXT(ctx); TNLcontext *tnl = TNL_CONTEXT(ctx);
struct vertex_buffer *VB = &tnl->vb; struct vertex_buffer *VB = &tnl->vb;
const GLuint count = end - start;
GLuint stride = input->StrideB; GLuint stride = input->StrideB;
ptr += start * stride;
if (input->Type != GL_FLOAT) { if (input->Type != GL_FLOAT) {
const GLuint sz = input->Size; const GLuint sz = input->Size;
GLubyte *buf = get_space(ctx, count * sz * sizeof(GLfloat)); GLubyte *buf = get_space(ctx, count * sz * sizeof(GLfloat));
@@ -183,7 +179,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 min_index, GLint max_index, GLint count,
struct gl_buffer_object **bo, struct gl_buffer_object **bo,
GLuint *nr_bo ) GLuint *nr_bo )
{ {
@@ -215,18 +211,17 @@ 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 'min_index' becomes * temporary storage.
* 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, min_index, max_index, inputs[i], ptr); _tnl_import_array(ctx, i, count, inputs[i], ptr);
} }
/* We process only the vertices between min & max index: /* We process only the vertices between min & max index:
*/ */
VB->Count = max_index - min_index; VB->Count = count;
/* Legacy pointers -- remove one day. /* Legacy pointers -- remove one day.
@@ -264,7 +259,6 @@ static void bind_inputs( GLcontext *ctx,
*/ */
static void bind_indices( GLcontext *ctx, static void bind_indices( GLcontext *ctx,
const struct _mesa_index_buffer *ib, const struct _mesa_index_buffer *ib,
GLuint min_index,
struct gl_buffer_object **bo, struct gl_buffer_object **bo,
GLuint *nr_bo) GLuint *nr_bo)
{ {
@@ -273,8 +267,10 @@ static void bind_indices( GLcontext *ctx,
GLuint i; GLuint i;
void *ptr; void *ptr;
if (!ib) if (!ib) {
VB->Elts = NULL;
return; return;
}
if (ib->obj->Name && !ib->obj->Pointer) { if (ib->obj->Name && !ib->obj->Pointer) {
bo[*nr_bo] = ib->obj; bo[*nr_bo] = ib->obj;
@@ -289,60 +285,34 @@ static void bind_indices( GLcontext *ctx,
ptr = ADD_POINTERS(ib->obj->Pointer, ib->ptr); ptr = ADD_POINTERS(ib->obj->Pointer, ib->ptr);
if (ib->type == GL_UNSIGNED_INT && min_index == 0) { if (ib->type == GL_UNSIGNED_INT) {
VB->Elts = (GLuint *) ptr; VB->Elts = (GLuint *) ptr;
VB->Elts += ib->rebase;
} }
else { else {
GLuint *elts = (GLuint *)get_space(ctx, ib->count * sizeof(GLuint)); GLuint *elts = (GLuint *)get_space(ctx, ib->count * sizeof(GLuint));
VB->Elts = elts; VB->Elts = elts;
switch (ib->type) { if (ib->type == GL_UNSIGNED_SHORT) {
case GL_UNSIGNED_INT: { const GLushort *in = (GLushort *)ptr;
const GLuint *in = ((GLuint *)ptr) + ib->rebase;
for (i = 0; i < ib->count; i++) for (i = 0; i < ib->count; i++)
*elts++ = *in++ - min_index; *elts++ = (GLuint)(*in++);
break;
} }
case GL_UNSIGNED_SHORT: { else {
const GLushort *in = ((GLushort *)ptr) + ib->rebase; const GLubyte *in = (GLubyte *)ptr;
for (i = 0; i < ib->count; i++) for (i = 0; i < ib->count; i++)
*elts++ = (GLuint)(*in++) - min_index; *elts++ = (GLuint)(*in++);
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, static void bind_prims( GLcontext *ctx,
const struct _mesa_prim *prim, const struct _mesa_prim *prim,
GLuint nr_prims, GLuint nr_prims )
GLuint min_index )
{ {
TNLcontext *tnl = TNL_CONTEXT(ctx); TNLcontext *tnl = TNL_CONTEXT(ctx);
struct vertex_buffer *VB = &tnl->vb; 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->Primitive = prim;
VB->PrimitiveCount = nr_prims; VB->PrimitiveCount = nr_prims;
} }
@@ -373,19 +343,10 @@ void _tnl_draw_prims( GLcontext *ctx,
GLuint max_index) GLuint max_index)
{ {
TNLcontext *tnl = TNL_CONTEXT(ctx); TNLcontext *tnl = TNL_CONTEXT(ctx);
struct vertex_buffer *VB = &tnl->vb; const GLuint TEST_SPLIT = 0;
GLint max = VB->Size; const GLint max = TEST_SPLIT ? 8 : tnl->vb.Size - MAX_CLIPPED_VERTICES;
#ifdef TEST_SPLIT if (0)
max = 8 + MAX_CLIPPED_VERTICES;
#endif
assert(max_index > min_index);
assert(!(max_index & 0x80000000));
VB->Elts = NULL;
#if 0
{ {
GLuint i; GLuint i;
_mesa_printf("%s %d..%d\n", __FUNCTION__, min_index, max_index); _mesa_printf("%s %d..%d\n", __FUNCTION__, min_index, max_index);
@@ -395,15 +356,22 @@ void _tnl_draw_prims( GLcontext *ctx,
prim[i].start, prim[i].start,
prim[i].count); prim[i].count);
} }
#endif
/* The software TNL pipeline has a fixed amount of storage for if (min_index) {
* vertices and it is necessary to split incoming drawing commands /* We always translate away calls with min_index != 0.
* if they exceed that limit. */
*/ vbo_rebase_prims( ctx, arrays, prim, nr_prims, ib,
if (max_index - min_index >= max - MAX_CLIPPED_VERTICES) { min_index, max_index,
_tnl_draw_prims );
return;
}
else if (max_index >= max) {
/* 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 split_limits limits; struct split_limits limits;
limits.max_verts = max - MAX_CLIPPED_VERTICES; limits.max_verts = max;
limits.max_vb_size = ~0; limits.max_vb_size = ~0;
limits.max_indices = ~0; limits.max_indices = ~0;
@@ -411,7 +379,7 @@ void _tnl_draw_prims( GLcontext *ctx,
* recursively call back into this function. * recursively call back into this function.
*/ */
vbo_split_prims( ctx, arrays, prim, nr_prims, ib, vbo_split_prims( ctx, arrays, prim, nr_prims, ib,
min_index, max_index, 0, max_index,
_tnl_draw_prims, _tnl_draw_prims,
&limits ); &limits );
} }
@@ -425,9 +393,9 @@ void _tnl_draw_prims( GLcontext *ctx,
/* Binding inputs may imply mapping some vertex buffer objects. /* Binding inputs may imply mapping some vertex buffer objects.
* They will need to be unmapped below. * They will need to be unmapped below.
*/ */
bind_inputs(ctx, arrays, min_index, max_index+1, bo, &nr_bo); bind_inputs(ctx, arrays, max_index+1, bo, &nr_bo);
bind_indices(ctx, ib, min_index, bo, &nr_bo); bind_indices(ctx, ib, bo, &nr_bo);
bind_prims(ctx, prim, nr_prims, VB->Elts ? 0 : min_index ); bind_prims(ctx, prim, nr_prims );
TNL_CONTEXT(ctx)->Driver.RunPipeline(ctx); TNL_CONTEXT(ctx)->Driver.RunPipeline(ctx);

View File

@@ -55,7 +55,6 @@ struct _mesa_index_buffer {
GLenum type; GLenum type;
struct gl_buffer_object *obj; struct gl_buffer_object *obj;
const void *ptr; const void *ptr;
GLuint rebase;
}; };

View File

@@ -34,45 +34,55 @@
#include "vbo_context.h" #include "vbo_context.h"
static GLuint get_max_index( GLuint count, GLuint type, /* Compute min and max elements for drawelements calls.
const GLvoid *indices ) */
static void get_minmax_index( GLuint count, GLuint type,
const GLvoid *indices,
GLuint *min_index,
GLuint *max_index)
{ {
GLint i; GLint i;
/* Compute max element. This is only needed for upload of non-VBO,
* non-constant data elements.
*
* XXX: Postpone this calculation until it is known that it is
* needed. Otherwise could scan this pointlessly in the all-vbo
* case.
*/
switch(type) { switch(type) {
case GL_UNSIGNED_INT: { case GL_UNSIGNED_INT: {
const GLuint *ui_indices = (const GLuint *)indices; const GLuint *ui_indices = (const GLuint *)indices;
GLuint max_ui = 0; GLuint max_ui = ui_indices[0];
for (i = 0; i < count; i++) GLuint min_ui = ui_indices[0];
if (ui_indices[i] > max_ui) for (i = 1; i < count; i++) {
max_ui = ui_indices[i]; if (ui_indices[i] > max_ui) max_ui = ui_indices[i];
return max_ui; if (ui_indices[i] < min_ui) min_ui = ui_indices[i];
}
*min_index = min_ui;
*max_index = max_ui;
break;
} }
case GL_UNSIGNED_SHORT: { case GL_UNSIGNED_SHORT: {
const GLushort *us_indices = (const GLushort *)indices; const GLushort *us_indices = (const GLushort *)indices;
GLuint max_us = 0; GLuint max_us = us_indices[0];
for (i = 0; i < count; i++) GLuint min_us = us_indices[0];
if (us_indices[i] > max_us) for (i = 1; i < count; i++) {
max_us = us_indices[i]; if (us_indices[i] > max_us) max_us = us_indices[i];
return max_us; if (us_indices[i] < min_us) min_us = us_indices[i];
}
*min_index = min_us;
*max_index = max_us;
break;
} }
case GL_UNSIGNED_BYTE: { case GL_UNSIGNED_BYTE: {
const GLubyte *ub_indices = (const GLubyte *)indices; const GLubyte *ub_indices = (const GLubyte *)indices;
GLuint max_ub = 0; GLuint max_ub = ub_indices[0];
for (i = 0; i < count; i++) GLuint min_ub = ub_indices[0];
if (ub_indices[i] > max_ub) for (i = 1; i < count; i++) {
max_ub = ub_indices[i]; if (ub_indices[i] > max_ub) max_ub = ub_indices[i];
return max_ub; if (ub_indices[i] < min_ub) min_ub = ub_indices[i];
}
*min_index = min_ub;
*max_index = max_ub;
break;
} }
default: default:
return 0; assert(0);
break;
} }
} }
@@ -241,31 +251,12 @@ vbo_exec_DrawArrays(GLenum mode, GLint start, GLsizei count)
prim[0].end = 1; prim[0].end = 1;
prim[0].weak = 0; prim[0].weak = 0;
prim[0].pad = 0; prim[0].pad = 0;
prim[0].mode = mode;
prim[0].start = start;
prim[0].count = count;
prim[0].indexed = 0;
if (exec->array.inputs[0]->BufferObj->Name) { vbo->draw_prims( ctx, exec->array.inputs, prim, 1, NULL, start, start + count - 1 );
/* Use vertex attribute as a hint to tell us if we expect all
* arrays to be in VBO's and if so, don't worry about avoiding
* the upload of elements < start.
*/
prim[0].mode = mode;
prim[0].start = start;
prim[0].count = count;
prim[0].indexed = 0;
vbo->draw_prims( ctx, exec->array.inputs, prim, 1, NULL, 0, start + count );
}
else {
/* If not using VBO's, we don't want to upload any more elements
* than necessary from the arrays as they will not be valid next
* time the application tries to draw with them.
*/
prim[0].mode = mode;
prim[0].start = 0;
prim[0].count = count;
prim[0].indexed = 0;
vbo->draw_prims( ctx, exec->array.inputs, prim, 1, NULL, start, start + count );
}
} }
@@ -296,20 +287,6 @@ vbo_exec_DrawRangeElements(GLenum mode,
ib.obj = ctx->Array.ElementArrayBufferObj; ib.obj = ctx->Array.ElementArrayBufferObj;
ib.ptr = indices; ib.ptr = indices;
if (ctx->Array.ElementArrayBufferObj->Name) {
/* Use the fact that indices are in a VBO as a hint that the
* program has put all the arrays in VBO's and we don't have to
* worry about performance implications of start > 0.
*
* XXX: consider passing start as min_index to draw_prims instead.
* XXX: don't rebase because it didn't work.
*/
ib.rebase = 0;
}
else {
ib.rebase = /*start*/ 0;
}
prim[0].begin = 1; prim[0].begin = 1;
prim[0].end = 1; prim[0].end = 1;
prim[0].weak = 0; prim[0].weak = 0;
@@ -319,15 +296,46 @@ vbo_exec_DrawRangeElements(GLenum mode,
prim[0].count = count; prim[0].count = count;
prim[0].indexed = 1; prim[0].indexed = 1;
vbo->draw_prims( ctx, exec->array.inputs, prim, 1, &ib, /*ib.rebase*/ start, end+1 ); /* Need to give special consideration to rendering a range of
} * indices starting somewhere above zero. Typically the
* application is issuing multiple DrawRangeElements() to draw
* successive primitives layed out linearly in the vertex arrays.
* Unless the vertex arrays are all in a VBO (or locked as with
* CVA), the OpenGL semantics imply that we need to re-read or
* re-upload the vertex data on each draw call.
*
* In the case of hardware tnl, we want to avoid starting the
* upload at zero, as it will mean every draw call uploads an
* increasing amount of not-used vertex data. Worse - in the
* software tnl module, all those vertices might be transformed and
* lit but never rendered.
*
* If we just upload or transform the vertices in start..end,
* however, the indices will be incorrect.
*
* At this level, we don't know exactly what the requirements of
* the backend are going to be, though it will likely boil down to
* either:
*
* 1) Do nothing, everything is in a VBO and is processed once
* only.
*
* 2) Adjust the indices and vertex arrays so that start becomes
* zero.
*
* Rather than doing anything here, I'll provide a helper function
* for the latter case elsewhere.
*/
vbo->draw_prims( ctx, exec->array.inputs, prim, 1, &ib, start, end );
}
static void GLAPIENTRY static void GLAPIENTRY
vbo_exec_DrawElements(GLenum mode, GLsizei count, GLenum type, const GLvoid *indices) vbo_exec_DrawElements(GLenum mode, GLsizei count, GLenum type, const GLvoid *indices)
{ {
GET_CURRENT_CONTEXT(ctx); GET_CURRENT_CONTEXT(ctx);
GLuint max_index; GLuint min_index = 0;
GLuint max_index = 0;
if (!_mesa_validate_DrawElements( ctx, mode, count, type, indices )) if (!_mesa_validate_DrawElements( ctx, mode, count, type, indices ))
return; return;
@@ -338,17 +346,17 @@ vbo_exec_DrawElements(GLenum mode, GLsizei count, GLenum type, const GLvoid *ind
GL_READ_ONLY, GL_READ_ONLY,
ctx->Array.ElementArrayBufferObj); ctx->Array.ElementArrayBufferObj);
max_index = get_max_index(count, type, ADD_POINTERS(map, indices)); get_minmax_index(count, type, ADD_POINTERS(map, indices), &min_index, &max_index);
ctx->Driver.UnmapBuffer(ctx, ctx->Driver.UnmapBuffer(ctx,
GL_ELEMENT_ARRAY_BUFFER_ARB, GL_ELEMENT_ARRAY_BUFFER_ARB,
ctx->Array.ElementArrayBufferObj); ctx->Array.ElementArrayBufferObj);
} }
else { else {
max_index = get_max_index(count, type, indices); get_minmax_index(count, type, indices, &min_index, &max_index);
} }
vbo_exec_DrawRangeElements(mode, 0, max_index, count, type, indices); vbo_exec_DrawRangeElements(mode, min_index, max_index, count, type, indices);
} }

View File

@@ -123,7 +123,8 @@ void vbo_rebase_prims( GLcontext *ctx,
assert(min_index != 0); assert(min_index != 0);
_mesa_printf("%s %d..%d\n", __FUNCTION__, min_index, max_index); if (0)
_mesa_printf("%s %d..%d\n", __FUNCTION__, min_index, max_index);
if (ib) { if (ib) {
/* Unfortunately need to adjust each index individually. /* Unfortunately need to adjust each index individually.

View File

@@ -479,7 +479,6 @@ static void replay_init( struct copy_context *copy )
copy->dstib.type = GL_UNSIGNED_INT; copy->dstib.type = GL_UNSIGNED_INT;
copy->dstib.obj = ctx->Array.NullBufferObj; copy->dstib.obj = ctx->Array.NullBufferObj;
copy->dstib.ptr = copy->dstelt; copy->dstib.ptr = copy->dstelt;
copy->dstib.rebase = 0;
} }

View File

@@ -223,7 +223,6 @@ static void split_prims( struct split_context *split)
ib.type = GL_UNSIGNED_INT; ib.type = GL_UNSIGNED_INT;
ib.obj = split->ctx->Array.NullBufferObj; ib.obj = split->ctx->Array.NullBufferObj;
ib.ptr = elts; ib.ptr = elts;
ib.rebase = 0; /* ? */
tmpprim = *prim; tmpprim = *prim;
tmpprim.indexed = 1; tmpprim.indexed = 1;