Make sure vbo's are mapped before accessing their contents in
authorKeith Whitwell <keith@tungstengraphics.com>
Thu, 16 Nov 2006 02:33:38 +0000 (02:33 +0000)
committerKeith Whitwell <keith@tungstengraphics.com>
Thu, 16 Nov 2006 02:33:38 +0000 (02:33 +0000)
api_arrayelt.c.  Reported by Haihao Xiang.

src/mesa/drivers/dri/i965/brw_save_api.c
src/mesa/main/api_arrayelt.c
src/mesa/main/api_arrayelt.h
src/mesa/tnl/t_save_api.c

index 9c0e4af..b2f255d 100644 (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,
index dda659b..3c26c2c 100644 (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;
 }
index 1c0af9f..e621724 100644 (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
index 11d2130..dbbd095 100644 (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,