Make sure vbo's are mapped before accessing their contents in
api_arrayelt.c.  Reported by Haihao Xiang.
diff --git a/src/mesa/main/api_arrayelt.c b/src/mesa/main/api_arrayelt.c
index dda659b..3c26c2c 100644
--- a/src/mesa/main/api_arrayelt.c
+++ b/src/mesa/main/api_arrayelt.c
@@ -53,6 +53,11 @@
    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 @@
    }
 }
 
+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 @@
   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 @@
                                  [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 @@
                                      [TYPE_IDX(at->array->Type)];
          }
          at->index = i;
+	 check_vbo(actx, aa->array->BufferObj);
          at++;
       }
    }
@@ -1158,14 +1183,18 @@
       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 @@
    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 @@
    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 @@
    /* 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;
 }