Make sure vbo's are mapped before accessing their contents in

api_arrayelt.c.  Reported by Haihao Xiang.
This commit is contained in:
Keith Whitwell 2006-11-16 02:33:38 +00:00
parent 82eeb62a31
commit b979479721
4 changed files with 110 additions and 6 deletions

View File

@ -855,10 +855,14 @@ static void GLAPIENTRY _save_OBE_DrawArrays(GLenum mode, GLint start, GLsizei co
if (!_mesa_validate_DrawArrays( ctx, mode, start, count ))
return;
_ae_map_vbos( ctx );
brw_save_NotifyBegin( ctx, mode | BRW_SAVE_PRIM_WEAK );
for (i = 0; i < count; i++)
CALL_ArrayElement(GET_DISPATCH(), (start + i));
CALL_End(GET_DISPATCH(), ());
_ae_unmap_vbos( ctx );
}
/* Could do better by copying the arrays and element list intact and
@ -873,6 +877,8 @@ static void GLAPIENTRY _save_OBE_DrawElements(GLenum mode, GLsizei count, GLenum
if (!_mesa_validate_DrawElements( ctx, mode, count, type, indices ))
return;
_ae_map_vbos( ctx );
brw_save_NotifyBegin( ctx, mode | BRW_SAVE_PRIM_WEAK );
switch (type) {
@ -894,6 +900,8 @@ static void GLAPIENTRY _save_OBE_DrawElements(GLenum mode, GLsizei count, GLenum
}
CALL_End(GET_DISPATCH(), ());
_ae_unmap_vbos( ctx );
}
static void GLAPIENTRY _save_OBE_DrawRangeElements(GLenum mode,

View File

@ -53,6 +53,11 @@ typedef struct {
AEarray arrays[32];
AEattrib attribs[VERT_ATTRIB_MAX + 1];
GLuint NewState;
struct gl_buffer_object *vbo[VERT_ATTRIB_MAX];
GLuint nr_vbos;
GLboolean mapped_vbos;
} AEcontext;
#define AE_CONTEXT(ctx) ((AEcontext *)(ctx)->aelt_context)
@ -1063,6 +1068,18 @@ void _ae_destroy_context( GLcontext *ctx )
}
}
static void check_vbo( AEcontext *actx,
struct gl_buffer_object *vbo )
{
if (vbo->Name && !vbo->Pointer) {
GLuint i;
for (i = 0; i < actx->nr_vbos; i++)
if (actx->vbo[i] == vbo)
return;
actx->vbo[actx->nr_vbos++] = vbo;
}
}
/**
* Make a list of per-vertex functions to call for each glArrayElement call.
@ -1081,31 +1098,37 @@ static void _ae_update_state( GLcontext *ctx )
if (ctx->Array.ArrayObj->Index.Enabled) {
aa->array = &ctx->Array.ArrayObj->Index;
aa->offset = IndexFuncs[TYPE_IDX(aa->array->Type)];
check_vbo(actx, aa->array->BufferObj);
aa++;
}
if (ctx->Array.ArrayObj->EdgeFlag.Enabled) {
aa->array = &ctx->Array.ArrayObj->EdgeFlag;
aa->offset = _gloffset_EdgeFlagv;
check_vbo(actx, aa->array->BufferObj);
aa++;
}
if (ctx->Array.ArrayObj->Normal.Enabled) {
aa->array = &ctx->Array.ArrayObj->Normal;
aa->offset = NormalFuncs[TYPE_IDX(aa->array->Type)];
check_vbo(actx, aa->array->BufferObj);
aa++;
}
if (ctx->Array.ArrayObj->Color.Enabled) {
aa->array = &ctx->Array.ArrayObj->Color;
aa->offset = ColorFuncs[aa->array->Size-3][TYPE_IDX(aa->array->Type)];
check_vbo(actx, aa->array->BufferObj);
aa++;
}
if (ctx->Array.ArrayObj->SecondaryColor.Enabled) {
aa->array = &ctx->Array.ArrayObj->SecondaryColor;
aa->offset = SecondaryColorFuncs[TYPE_IDX(aa->array->Type)];
check_vbo(actx, aa->array->BufferObj);
aa++;
}
if (ctx->Array.ArrayObj->FogCoord.Enabled) {
aa->array = &ctx->Array.ArrayObj->FogCoord;
aa->offset = FogCoordFuncs[TYPE_IDX(aa->array->Type)];
check_vbo(actx, aa->array->BufferObj);
aa++;
}
for (i = 0; i < ctx->Const.MaxTextureCoordUnits; i++) {
@ -1120,11 +1143,12 @@ static void _ae_update_state( GLcontext *ctx )
[at->array->Size-1]
[TYPE_IDX(at->array->Type)];
at->index = VERT_ATTRIB_TEX0 + i;
check_vbo(actx, aa->array->BufferObj);
at++;
}
}
/* generic vertex attribute arrays */
/* generic vertex attribute arrays */
for (i = 1; i < VERT_ATTRIB_MAX; i++) { /* skip zero! */
struct gl_client_array *attribArray = &ctx->Array.ArrayObj->VertexAttrib[i];
if (attribArray->Enabled) {
@ -1146,6 +1170,7 @@ static void _ae_update_state( GLcontext *ctx )
[TYPE_IDX(at->array->Type)];
}
at->index = i;
check_vbo(actx, aa->array->BufferObj);
at++;
}
}
@ -1158,14 +1183,18 @@ static void _ae_update_state( GLcontext *ctx )
aa->array = &ctx->Array.ArrayObj->VertexAttrib[0];
assert(aa->array->Size >= 2); /* XXX fix someday? */
aa->offset = VertexFuncs[aa->array->Size-2][TYPE_IDX(aa->array->Type)];
check_vbo(actx, aa->array->BufferObj);
aa++;
}
else if (ctx->Array.ArrayObj->Vertex.Enabled) {
aa->array = &ctx->Array.ArrayObj->Vertex;
aa->offset = VertexFuncs[aa->array->Size-2][TYPE_IDX(aa->array->Type)];
check_vbo(actx, aa->array->BufferObj);
aa++;
}
check_vbo(actx, ctx->Array.ElementArrayBufferObj);
ASSERT(at - actx->attribs <= VERT_ATTRIB_MAX);
ASSERT(aa - actx->arrays < 32);
at->func = NULL; /* terminate the list */
@ -1174,6 +1203,45 @@ static void _ae_update_state( GLcontext *ctx )
actx->NewState = 0;
}
void _ae_map_vbos( GLcontext *ctx )
{
AEcontext *actx = AE_CONTEXT(ctx);
GLuint i;
if (actx->mapped_vbos)
return;
if (actx->NewState)
_ae_update_state(ctx);
for (i = 0; i < actx->nr_vbos; i++)
ctx->Driver.MapBuffer(ctx,
GL_ARRAY_BUFFER_ARB,
GL_DYNAMIC_DRAW_ARB,
actx->vbo[i]);
actx->mapped_vbos = GL_TRUE;
}
void _ae_unmap_vbos( GLcontext *ctx )
{
AEcontext *actx = AE_CONTEXT(ctx);
GLuint i;
if (actx->mapped_vbos)
return;
if (actx->NewState)
_ae_update_state(ctx);
for (i = 0; i < actx->nr_vbos; i++)
ctx->Driver.UnmapBuffer(ctx,
GL_ARRAY_BUFFER_ARB,
actx->vbo[i]);
actx->mapped_vbos = GL_TRUE;
}
/**
* Called via glArrayElement() and glDrawArrays().
@ -1188,15 +1256,24 @@ void GLAPIENTRY _ae_loopback_array_elt( GLint elt )
const AEarray *aa;
const AEattrib *at;
const struct _glapi_table * const disp = GET_DISPATCH();
GLboolean do_map;
if (actx->NewState)
if (actx->NewState) {
assert(!actx->mapped_vbos);
_ae_update_state( ctx );
}
do_map = actx->nr_vbos && !actx->mapped_vbos;
/*
*/
if (do_map)
_ae_map_vbos(ctx);
/* generic attributes */
for (at = actx->attribs; at->func; at++) {
const GLubyte *src
= ADD_POINTERS(at->array->BufferObj->Data, at->array->Ptr)
= ADD_POINTERS(at->array->BufferObj->Pointer, at->array->Ptr)
+ elt * at->array->StrideB;
at->func( at->index, src );
}
@ -1204,15 +1281,21 @@ void GLAPIENTRY _ae_loopback_array_elt( GLint elt )
/* conventional arrays */
for (aa = actx->arrays; aa->offset != -1 ; aa++) {
const GLubyte *src
= ADD_POINTERS(aa->array->BufferObj->Data, aa->array->Ptr)
= ADD_POINTERS(aa->array->BufferObj->Pointer, aa->array->Ptr)
+ elt * aa->array->StrideB;
CALL_by_offset( disp, (array_func), aa->offset,
((const void *) src) );
}
if (do_map)
_ae_unmap_vbos(ctx);
}
void _ae_invalidate_state( GLcontext *ctx, GLuint new_state )
{
AE_CONTEXT(ctx)->NewState |= new_state;
AEcontext *actx = AE_CONTEXT(ctx);
assert(!actx->mapped_vbos);
actx->NewState |= new_state;
}

View File

@ -34,4 +34,9 @@ extern void _ae_destroy_context( GLcontext *ctx );
extern void _ae_invalidate_state( GLcontext *ctx, GLuint new_state );
extern void GLAPIENTRY _ae_loopback_array_elt( GLint elt );
/* May optionally be called before a batch of element calls:
*/
extern void _ae_map_vbos( GLcontext *ctx );
extern void _ae_unmap_vbos( GLcontext *ctx );
#endif

View File

@ -1413,10 +1413,14 @@ static void GLAPIENTRY _save_OBE_DrawArrays(GLenum mode, GLint start, GLsizei co
if (!_mesa_validate_DrawArrays( ctx, mode, start, count ))
return;
_ae_map_vbos( ctx );
_save_NotifyBegin( ctx, mode | PRIM_WEAK );
for (i = 0; i < count; i++)
CALL_ArrayElement(GET_DISPATCH(), (start + i));
CALL_End(GET_DISPATCH(), ());
_ae_unmap_vbos( ctx );
}
@ -1429,6 +1433,8 @@ static void GLAPIENTRY _save_OBE_DrawElements(GLenum mode, GLsizei count, GLenum
if (!_mesa_validate_DrawElements( ctx, mode, count, type, indices ))
return;
_ae_map_vbos( ctx );
_save_NotifyBegin( ctx, mode | PRIM_WEAK );
switch (type) {
@ -1450,6 +1456,8 @@ static void GLAPIENTRY _save_OBE_DrawElements(GLenum mode, GLsizei count, GLenum
}
CALL_End(GET_DISPATCH(), ());
_ae_unmap_vbos( ctx );
}
static void GLAPIENTRY _save_OBE_DrawRangeElements(GLenum mode,