Move edgeflag into the VERT_ATTRIB_SEVEN slot. This means that our
authorKeith Whitwell <keith@tungstengraphics.com>
Mon, 30 Oct 2006 20:16:35 +0000 (20:16 +0000)
committerKeith Whitwell <keith@tungstengraphics.com>
Mon, 30 Oct 2006 20:16:35 +0000 (20:16 +0000)
NV_vertex_program implementation has slightly incorrect aliasing
behaviour.  I think this is reasonable given the simplification and
the fact that the mainstream ARB_vp continues to have the correct
behaviour.

12 files changed:
src/mesa/main/api_noop.c
src/mesa/main/context.c
src/mesa/main/get.c
src/mesa/main/mtypes.h
src/mesa/main/state.c
src/mesa/vbo/vbo_context.c
src/mesa/vbo/vbo_context.h
src/mesa/vbo/vbo_exec.h
src/mesa/vbo/vbo_exec_api.c
src/mesa/vbo/vbo_exec_draw.c
src/mesa/vbo/vbo_save.c
src/mesa/vbo/vbo_save_draw.c

index 33d44e43296c200f641c645ce498b4c592f1de7b..0c1a35361f16ab9d36d5e546621122b377e6377f 100644 (file)
@@ -45,7 +45,7 @@
 static void GLAPIENTRY _mesa_noop_EdgeFlag( GLboolean b )
 {
    GET_CURRENT_CONTEXT(ctx);
-   ctx->Current.EdgeFlag = b;
+   ctx->Current.Attrib[VERT_ATTRIB_EDGEFLAG][0] = (GLfloat)b;
 }
 
 static void GLAPIENTRY _mesa_noop_Indexf( GLfloat f )
index e0630c33d0b0c95439f41688b333df75a6a15743..15b69db5951af0ecaa9b0dfb2bbf2f66c9e8948f 100644 (file)
@@ -967,8 +967,8 @@ _mesa_init_current( GLcontext *ctx )
    ASSIGN_4V( ctx->Current.Attrib[VERT_ATTRIB_COLOR0], 1.0, 1.0, 1.0, 1.0 );
    ASSIGN_4V( ctx->Current.Attrib[VERT_ATTRIB_COLOR1], 0.0, 0.0, 0.0, 1.0 );
    ASSIGN_4V( ctx->Current.Attrib[VERT_ATTRIB_FOG], 0.0, 0.0, 0.0, 0.0 );
-   ctx->Current.Attrib[VERT_ATTRIB_COLOR_INDEX][0] = 1.0;
-   ctx->Current.EdgeFlag = GL_TRUE;
+   ASSIGN_4V( ctx->Current.Attrib[VERT_ATTRIB_COLOR_INDEX], 1.0, 0.0, 0.0, 1.0 );
+   ASSIGN_4V( ctx->Current.Attrib[VERT_ATTRIB_EDGEFLAG], 1.0, 0.0, 0.0, 1.0 );
 }
 
 
index 61a76d000b96361c205c85707fb8c4aeaf2ae883..2a24b56974ceefb7ad7b53b331adf14e74fc6e1a 100644 (file)
@@ -323,7 +323,7 @@ _mesa_GetBooleanv( GLenum pname, GLboolean *params )
       case GL_EDGE_FLAG:
          {
          FLUSH_CURRENT(ctx, 0);
-         params[0] = ctx->Current.EdgeFlag;
+         params[0] = (ctx->Current.Attrib[VERT_ATTRIB_EDGEFLAG][0] == 1.0F);
          }
          break;
       case GL_FEEDBACK_BUFFER_SIZE:
@@ -2147,7 +2147,7 @@ _mesa_GetFloatv( GLenum pname, GLfloat *params )
       case GL_EDGE_FLAG:
          {
          FLUSH_CURRENT(ctx, 0);
-         params[0] = BOOLEAN_TO_FLOAT(ctx->Current.EdgeFlag);
+         params[0] = BOOLEAN_TO_FLOAT(ctx->Current.Attrib[VERT_ATTRIB_EDGEFLAG][0] == 1.0F);
          }
          break;
       case GL_FEEDBACK_BUFFER_SIZE:
@@ -3971,7 +3971,7 @@ _mesa_GetIntegerv( GLenum pname, GLint *params )
       case GL_EDGE_FLAG:
          {
          FLUSH_CURRENT(ctx, 0);
-         params[0] = BOOLEAN_TO_INT(ctx->Current.EdgeFlag);
+         params[0] = BOOLEAN_TO_INT(ctx->Current.Attrib[VERT_ATTRIB_EDGEFLAG][0] == 1.0F);
          }
          break;
       case GL_FEEDBACK_BUFFER_SIZE:
index 903779edae5800c88e9b5949c1e698d4b7ac27cc..bc7c6b8026fc1f6bd957e661dc3bf26fe68a85f7 100644 (file)
@@ -143,7 +143,7 @@ enum
    VERT_ATTRIB_COLOR1 = 4,
    VERT_ATTRIB_FOG = 5,
    VERT_ATTRIB_COLOR_INDEX = 6,
-   VERT_ATTRIB_SEVEN = 7,
+   VERT_ATTRIB_EDGEFLAG = 7,
    VERT_ATTRIB_TEX0 = 8,
    VERT_ATTRIB_TEX1 = 9,
    VERT_ATTRIB_TEX2 = 10,
@@ -183,7 +183,7 @@ enum
 #define VERT_BIT_COLOR1      (1 << VERT_ATTRIB_COLOR1)
 #define VERT_BIT_FOG         (1 << VERT_ATTRIB_FOG)
 #define VERT_BIT_COLOR_INDEX (1 << VERT_ATTRIB_COLOR_INDEX)
-#define VERT_BIT_SEVEN       (1 << VERT_ATTRIB_SEVEN)
+#define VERT_BIT_EDGEFLAG    (1 << VERT_ATTRIB_EDGEFLAG)
 #define VERT_BIT_TEX0        (1 << VERT_ATTRIB_TEX0)
 #define VERT_BIT_TEX1        (1 << VERT_ATTRIB_TEX1)
 #define VERT_BIT_TEX2        (1 << VERT_ATTRIB_TEX2)
@@ -616,11 +616,11 @@ struct gl_current_attrib
    /**
     * \name Current vertex attributes.
     * \note Values are valid only after FLUSH_VERTICES has been called.
+    * \note Index and Edgeflag current values are stored as floats in the 
+    * SIX and SEVEN attribute slots.
     */
    /*@{*/
    GLfloat Attrib[VERT_ATTRIB_MAX][4]; /**< Position, color, texcoords, etc */
-   GLfloat Index;                      /**< Current color index */
-   GLboolean EdgeFlag;                 /**< Current edge flag */
    /*@}*/
 
    /**
@@ -2604,7 +2604,7 @@ struct matrix_stack
 #define _NEW_ARRAY_COLOR1           VERT_BIT_COLOR1
 #define _NEW_ARRAY_FOGCOORD         VERT_BIT_FOG
 #define _NEW_ARRAY_INDEX            VERT_BIT_COLOR_INDEX
-#define _NEW_ARRAY_EDGEFLAG         VERT_BIT_SEVEN
+#define _NEW_ARRAY_EDGEFLAG         VERT_BIT_EDGEFLAG
 #define _NEW_ARRAY_TEXCOORD_0       VERT_BIT_TEX0
 #define _NEW_ARRAY_TEXCOORD_1       VERT_BIT_TEX1
 #define _NEW_ARRAY_TEXCOORD_2       VERT_BIT_TEX2
index 7dbcf8ad97d7376a753e274fd1de6e017ba700fc..d57217d9c4f69357455fbef66edfb47307057278 100644 (file)
@@ -887,8 +887,8 @@ update_arrays( GLcontext *ctx )
 
    /* 7 */
    if (ctx->VertexProgram._Enabled
-       && ctx->Array.ArrayObj->VertexAttrib[VERT_ATTRIB_SEVEN].Enabled) {
-      min = MIN2(min, ctx->Array.ArrayObj->VertexAttrib[VERT_ATTRIB_SEVEN]._MaxElement);
+       && ctx->Array.ArrayObj->VertexAttrib[VERT_ATTRIB_EDGEFLAG].Enabled) {
+      min = MIN2(min, ctx->Array.ArrayObj->VertexAttrib[VERT_ATTRIB_EDGEFLAG]._MaxElement);
    }
 
    /* 8..15 */
index 291eb0bed3b0dba5e210f0646c053917694833ef..165e32da8a86f14ef40dfb9fc46105d402725fcc 100644 (file)
@@ -61,27 +61,14 @@ static void init_legacy_currval(GLcontext *ctx)
    for (i = 0; i < NR_LEGACY_ATTRIBS; i++) {
       struct gl_client_array *cl = &arrays[i];
 
-      switch (i) {
-      case VBO_ATTRIB_EDGEFLAG:
-        cl->Type = GL_UNSIGNED_BYTE;
-        cl->Ptr = (const void *)&ctx->Current.EdgeFlag;
-        break;
-      case VBO_ATTRIB_INDEX:
-        cl->Type = GL_FLOAT;
-        cl->Ptr = (const void *)&ctx->Current.Index;
-        break;
-      default:
-        cl->Type = GL_FLOAT;
-        cl->Ptr = (const void *)ctx->Current.Attrib[i];
-        break;
-      }
-
-      /* This will have to be determined at runtime:
+      /* Size will have to be determined at runtime:
        */
       cl->Size = 1;
       cl->Stride = 0;
       cl->StrideB = 0;
       cl->Enabled = 1;
+      cl->Type = GL_FLOAT;
+      cl->Ptr = (const void *)ctx->Current.Attrib[i];
       cl->BufferObj = ctx->Array.NullBufferObj;
    }
 }
@@ -118,12 +105,12 @@ static void init_mat_currval(GLcontext *ctx)
    struct gl_client_array *arrays = vbo->mat_currval;
    GLuint i;
 
-   memset(arrays, 0, sizeof(*arrays) * NR_GENERIC_ATTRIBS);
+   memset(arrays, 0, sizeof(*arrays) * NR_MAT_ATTRIBS);
 
    /* Set up a constant (StrideB == 0) array for each current
     * attribute:
     */
-   for (i = 0; i < NR_GENERIC_ATTRIBS; i++) {
+   for (i = 0; i < NR_MAT_ATTRIBS; i++) {
       struct gl_client_array *cl = &arrays[i];
 
       /* Size is fixed for the material attributes, for others will
@@ -156,7 +143,23 @@ static void init_mat_currval(GLcontext *ctx)
    }
 }
 
+#if 0
 
+static void vbo_exec_current_init( struct vbo_exec_context *exec ) 
+{
+   GLcontext *ctx = exec->ctx;
+   GLint i;
+
+   /* setup the pointers for the typical 16 vertex attributes */
+   for (i = 0; i < VBO_ATTRIB_FIRST_MATERIAL; i++) 
+      exec->vtx.current[i] = ctx->Current.Attrib[i];
+
+   /* setup pointers for the 12 material attributes */
+   for (i = 0; i < MAT_ATTRIB_MAX; i++)
+      exec->vtx.current[VBO_ATTRIB_FIRST_MATERIAL + i] = 
+        ctx->Light.Material.Attrib[i];
+}
+#endif
 
 GLboolean _vbo_CreateContext( GLcontext *ctx )
 {
@@ -171,13 +174,11 @@ GLboolean _vbo_CreateContext( GLcontext *ctx )
       return GL_FALSE;
    }
 
-   /* Hook our functions into exec and compile dispatch tables.  These
-    * will pretty much be permanently installed, which means that the
-    * vtxfmt mechanism can be removed now.
+   /* TODO: remove these pointers.
     */
-   vbo_exec_init( ctx );
-   vbo_save_init( ctx );
-
+   vbo->legacy_currval = &vbo->currval[VBO_ATTRIB_POS];
+   vbo->generic_currval = &vbo->currval[VBO_ATTRIB_GENERIC0];
+   vbo->mat_currval = &vbo->currval[VBO_ATTRIB_MAT_FRONT_AMBIENT];
 
    init_legacy_currval( ctx );
    init_generic_currval( ctx );
@@ -207,6 +208,14 @@ GLboolean _vbo_CreateContext( GLcontext *ctx )
    /* By default: 
     */
    vbo->draw_prims = _tnl_draw_prims;
+
+   /* Hook our functions into exec and compile dispatch tables.  These
+    * will pretty much be permanently installed, which means that the
+    * vtxfmt mechanism can be removed now.
+    */
+   vbo_exec_init( ctx );
+   vbo_save_init( ctx );
+
    
    return GL_TRUE;
 }
index 982da004378682c77786d8cfe1064113fc78c51a..cd024720232e3d7fba8dae670ddcf55c9b0b06ea 100644 (file)
 
 
 struct vbo_context {
-   struct gl_client_array legacy_currval[16];
-   struct gl_client_array generic_currval[16];
-   struct gl_client_array mat_currval[16];
+   struct gl_client_array currval[VBO_ATTRIB_MAX];
+   
+   /* These point into the above.  TODO: remove. 
+    */
+   struct gl_client_array *legacy_currval;
+   struct gl_client_array *generic_currval;
+   struct gl_client_array *mat_currval;
 
    GLuint map_vp_none[32];
    GLuint map_vp_arb[32];
 
+   GLfloat *current[VBO_ATTRIB_MAX]; /* points into ctx->Current, ctx->Light.Material */
+   GLfloat CurrentFloatEdgeFlag;
+
+
    struct vbo_exec_context exec;
    struct vbo_save_context save;
 
index ef158de825a343d887bdea3cd978086093992ad1..e1fc7b2794408688277135583df1c9caa678a417 100644 (file)
@@ -87,9 +87,6 @@ struct vbo_exec_context
       GLfloat *vbptr;               /* cursor, points into buffer */
       GLfloat vertex[VBO_ATTRIB_MAX*4]; /* current vertex */
 
-      GLfloat *current[VBO_ATTRIB_MAX]; /* points into ctx->Current, ctx->Light.Material */
-      GLfloat CurrentFloatEdgeFlag;
-
       GLuint vert_count;
       GLuint max_vert;
       struct vbo_exec_copied_vtx copied;
index c764c4d8b63e109ec7379c34a515ff82bca6e773..71fee8ca16eb15703988f978064f7f4f42586e13 100644 (file)
@@ -130,17 +130,28 @@ void vbo_exec_vtx_wrap( struct vbo_exec_context *exec )
 static void vbo_exec_copy_to_current( struct vbo_exec_context *exec )
 {
    GLcontext *ctx = exec->ctx;
+   struct vbo_context *vbo = vbo_context(ctx);
    GLuint i;
 
    for (i = VBO_ATTRIB_POS+1 ; i < VBO_ATTRIB_MAX ; i++) {
       if (exec->vtx.attrsz[i]) {
+        GLfloat *current = (GLfloat *)vbo->currval[i].Ptr;
+
          /* Note: the exec->vtx.current[i] pointers point into the
           * ctx->Current.Attrib and ctx->Light.Material.Attrib arrays.
           */
-        COPY_CLEAN_4V(exec->vtx.current[i]
+        COPY_CLEAN_4V(current
                       exec->vtx.attrsz[i], 
                       exec->vtx.attrptr[i]);
 
+        
+        /* Given that we explicitly state size here, there is no need
+         * for the COPY_CLEAN above, could just copy 16 bytes and be
+         * done.  The only problem is when Mesa accesses ctx->Current
+         * directly.
+         */
+        vbo->currval[i].Size = exec->vtx.attrsz[i];
+
         /* This triggers rather too much recalculation of Mesa state
          * that doesn't get used (eg light positions).
          */
@@ -150,19 +161,6 @@ static void vbo_exec_copy_to_current( struct vbo_exec_context *exec )
       }
    }
 
-   /* color index is special (it's not a float[4] so COPY_CLEAN_4V above
-    * will trash adjacent memory!)
-    */
-   if (exec->vtx.attrsz[VBO_ATTRIB_INDEX]) {
-      ctx->Current.Index = exec->vtx.attrptr[VBO_ATTRIB_INDEX][0];
-   }
-
-   /* Edgeflag requires additional treatment:
-    */
-   if (exec->vtx.attrsz[VBO_ATTRIB_EDGEFLAG]) {
-      ctx->Current.EdgeFlag = (exec->vtx.CurrentFloatEdgeFlag == 1.0);
-   }
-
    /* Colormaterial -- this kindof sucks.
     */
    if (ctx->Light.ColorMaterialEnabled &&
@@ -178,21 +176,19 @@ static void vbo_exec_copy_to_current( struct vbo_exec_context *exec )
 static void vbo_exec_copy_from_current( struct vbo_exec_context *exec )
 {
    GLcontext *ctx = exec->ctx;
+   struct vbo_context *vbo = vbo_context(ctx);
    GLint i;
 
-   /* Edgeflag requires additional treatment:
-    */
-   exec->vtx.CurrentFloatEdgeFlag = 
-      (GLfloat)ctx->Current.EdgeFlag;
-   
-   for (i = VBO_ATTRIB_POS+1 ; i < VBO_ATTRIB_MAX ; i++) 
+   for (i = VBO_ATTRIB_POS+1 ; i < VBO_ATTRIB_MAX ; i++) {
+      const GLfloat *current = (GLfloat *)vbo->currval[i].Ptr;
       switch (exec->vtx.attrsz[i]) {
-      case 4: exec->vtx.attrptr[i][3] = exec->vtx.current[i][3];
-      case 3: exec->vtx.attrptr[i][2] = exec->vtx.current[i][2];
-      case 2: exec->vtx.attrptr[i][1] = exec->vtx.current[i][1];
-      case 1: exec->vtx.attrptr[i][0] = exec->vtx.current[i][0];
+      case 4: exec->vtx.attrptr[i][3] = current[3];
+      case 3: exec->vtx.attrptr[i][2] = current[2];
+      case 2: exec->vtx.attrptr[i][1] = current[1];
+      case 1: exec->vtx.attrptr[i][0] = current[0];
         break;
       }
+   }
 
    ctx->Driver.NeedFlush |= FLUSH_UPDATE_CURRENT;
 }
@@ -205,6 +201,7 @@ static void vbo_exec_wrap_upgrade_vertex( struct vbo_exec_context *exec,
                                          GLuint newsz )
 {
    GLcontext *ctx = exec->ctx;
+   struct vbo_context *vbo = vbo_context(ctx);
    GLint lastcount = exec->vtx.vert_count;
    GLfloat *tmp;
    GLuint oldsz;
@@ -281,7 +278,8 @@ static void vbo_exec_wrap_upgrade_vertex( struct vbo_exec_context *exec,
                     data += oldsz;
                     dest += newsz;
                  } else {
-                    COPY_SZ_4V( dest, newsz, exec->vtx.current[j] );
+                    const GLfloat *current = (const GLfloat *)vbo->currval[j].Ptr;
+                    COPY_SZ_4V( dest, newsz, current );
                     dest += newsz;
                  }
               }
@@ -627,27 +625,10 @@ static void vbo_exec_vtxfmt_init( struct vbo_exec_context *exec )
 }
 
 
-static void vbo_exec_current_init( struct vbo_exec_context *exec ) 
-{
-   GLcontext *ctx = exec->ctx;
-   GLint i;
-
-   /* setup the pointers for the typical 16 vertex attributes */
-   for (i = 0; i < VBO_ATTRIB_FIRST_MATERIAL; i++) 
-      exec->vtx.current[i] = ctx->Current.Attrib[i];
-
-   /* setup pointers for the 12 material attributes */
-   for (i = 0; i < MAT_ATTRIB_MAX; i++)
-      exec->vtx.current[VBO_ATTRIB_FIRST_MATERIAL + i] = 
-        ctx->Light.Material.Attrib[i];
-
-   exec->vtx.current[VBO_ATTRIB_INDEX] = &ctx->Current.Index;
-   exec->vtx.current[VBO_ATTRIB_EDGEFLAG] = &exec->vtx.CurrentFloatEdgeFlag;
-}
-
 void vbo_exec_vtx_init( struct vbo_exec_context *exec )
 {
    GLcontext *ctx = exec->ctx;
+   struct vbo_context *vbo = vbo_context(ctx);
    GLuint i;
 
    /* Allocate a buffer object.  Will just reuse this object
@@ -656,7 +637,6 @@ void vbo_exec_vtx_init( struct vbo_exec_context *exec )
    exec->vtx.bufferobj = ctx->Array.NullBufferObj;
    exec->vtx.buffer_map = ALIGN_MALLOC(VBO_VERT_BUFFER_SIZE * sizeof(GLfloat), 64);
 
-   vbo_exec_current_init( exec );
    vbo_exec_vtxfmt_init( exec );
 
    /* Hook our functions into the dispatch table.
@@ -668,7 +648,13 @@ void vbo_exec_vtx_init( struct vbo_exec_context *exec )
       exec->vtx.active_sz[i] = 0;
       exec->vtx.inputs[i] = &exec->vtx.arrays[i];
    }
+   
+   {
+      struct gl_client_array *arrays = exec->vtx.arrays;
+      memcpy(arrays,      vbo->legacy_currval,  16 * sizeof(arrays[0]));
+      memcpy(arrays + 16, vbo->generic_currval, 16 * sizeof(arrays[0]));
+   }
+
    exec->vtx.vertex_size = 0;
 }
 
index c1898aea4972a3ce73f4acccdc04f2d1586c4450..846d5dc196cee4f59d2261c438907fda282405e8 100644 (file)
@@ -151,7 +151,7 @@ static void vbo_exec_bind_arrays( GLcontext *ctx )
    switch (get_program_mode(exec->ctx)) {
    case VP_NONE:
       memcpy(arrays,      vbo->legacy_currval, 16 * sizeof(arrays[0]));
-      memcpy(arrays + 16, vbo->mat_currval,    16 * sizeof(arrays[0]));
+      memcpy(arrays + 16, vbo->mat_currval,    MAT_ATTRIB_MAX * sizeof(arrays[0]));
       map = vbo->map_vp_none;
       break;
    case VP_NV:
index 3a97ea66a4ffe026fe8604708e382c7b456524e2..e7f46879639c4eea88c92ca07dfb4d14212836b4 100644 (file)
@@ -49,13 +49,20 @@ static void vbo_save_callback_init( GLcontext *ctx )
 
 void vbo_save_init( GLcontext *ctx )
 {
-   struct vbo_save_context *save = &vbo_context(ctx)->save;
+   struct vbo_context *vbo = vbo_context(ctx);
+   struct vbo_save_context *save = &vbo->save;
 
    save->ctx = ctx;
 
    vbo_save_api_init( save );
    vbo_save_callback_init(ctx);
 
+   {
+      struct gl_client_array *arrays = save->arrays;
+      memcpy(arrays,      vbo->legacy_currval,  16 * sizeof(arrays[0]));
+      memcpy(arrays + 16, vbo->generic_currval, 16 * sizeof(arrays[0]));
+   }
+
    ctx->Driver.CurrentSavePrimitive = PRIM_UNKNOWN;
 }
 
index 18c770a41cb3b21f56b2ab94ba12bdfb3e03f4c5..527e57d6bdb828d71c703513159f8d9c20cf6f9b 100644 (file)
@@ -41,7 +41,7 @@
 static void _playback_copy_to_current( GLcontext *ctx,
                                       const struct vbo_save_vertex_list *node )
 {
-   struct vbo_save_context *save = &vbo_context(ctx)->save; 
+   struct vbo_context *vbo = vbo_context(ctx);
    GLfloat vertex[VBO_ATTRIB_MAX * 4], *data = vertex;
    GLuint i, offset;
 
@@ -55,7 +55,14 @@ static void _playback_copy_to_current( GLcontext *ctx,
 
    for (i = VBO_ATTRIB_POS+1 ; i <= VBO_ATTRIB_INDEX ; i++) {
       if (node->attrsz[i]) {
-        COPY_CLEAN_4V(save->current[i], node->attrsz[i], data);
+        GLfloat *current = (GLfloat *)vbo->currval[i].Ptr;
+
+        COPY_CLEAN_4V(current, 
+                      node->attrsz[i], 
+                      data);
+
+        vbo->currval[i].Size = node->attrsz[i];
+
         data += node->attrsz[i];
 
         if (i >= VBO_ATTRIB_MAT_FRONT_AMBIENT &&
@@ -64,20 +71,11 @@ static void _playback_copy_to_current( GLcontext *ctx,
       }
    }
 
-   /* Edgeflag requires special treatment:
-    */
-   if (node->attrsz[VBO_ATTRIB_EDGEFLAG]) {
-      ctx->Current.EdgeFlag = (data[0] == 1.0);
-   }
-
-
-#if 1
    /* Colormaterial -- this kindof sucks.
     */
    if (ctx->Light.ColorMaterialEnabled) {
       _mesa_update_color_material(ctx, ctx->Current.Attrib[VBO_ATTRIB_COLOR0]);
    }
-#endif
 
    /* CurrentExecPrimitive
     */
@@ -111,7 +109,7 @@ static void vbo_bind_vertex_list( GLcontext *ctx,
    switch (get_program_mode(ctx)) {
    case VP_NONE:
       memcpy(arrays,      vbo->legacy_currval, 16 * sizeof(arrays[0]));
-      memcpy(arrays + 16, vbo->mat_currval,    16 * sizeof(arrays[0]));
+      memcpy(arrays + 16, vbo->mat_currval,    MAT_ATTRIB_MAX * sizeof(arrays[0]));
       map = vbo->map_vp_none;
       break;
    case VP_NV: