From b97947972193b6b004a0ee49da31146230d43dd8 Mon Sep 17 00:00:00 2001 From: Keith Whitwell Date: Thu, 16 Nov 2006 02:33:38 +0000 Subject: Make sure vbo's are mapped before accessing their contents in api_arrayelt.c. Reported by Haihao Xiang. --- src/mesa/drivers/dri/i965/brw_save_api.c | 8 +++ src/mesa/main/api_arrayelt.c | 95 ++++++++++++++++++++++++++++++-- src/mesa/main/api_arrayelt.h | 5 ++ src/mesa/tnl/t_save_api.c | 8 +++ 4 files changed, 110 insertions(+), 6 deletions(-) diff --git a/src/mesa/drivers/dri/i965/brw_save_api.c b/src/mesa/drivers/dri/i965/brw_save_api.c index 9c0e4af48a..b2f255d095 100644 --- a/src/mesa/drivers/dri/i965/brw_save_api.c +++ b/src/mesa/drivers/dri/i965/brw_save_api.c @@ -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, diff --git a/src/mesa/main/api_arrayelt.c b/src/mesa/main/api_arrayelt.c index dda659bbc3..3c26c2c590 100644 --- a/src/mesa/main/api_arrayelt.c +++ b/src/mesa/main/api_arrayelt.c @@ -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; } diff --git a/src/mesa/main/api_arrayelt.h b/src/mesa/main/api_arrayelt.h index 1c0af9f3ea..e621724fb2 100644 --- a/src/mesa/main/api_arrayelt.h +++ b/src/mesa/main/api_arrayelt.h @@ -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 diff --git a/src/mesa/tnl/t_save_api.c b/src/mesa/tnl/t_save_api.c index 11d21301d9..dbbd095fe4 100644 --- a/src/mesa/tnl/t_save_api.c +++ b/src/mesa/tnl/t_save_api.c @@ -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, -- cgit v1.2.3