diff options
author | Keith Whitwell <keith@tungstengraphics.com> | 2006-10-30 20:16:35 +0000 |
---|---|---|
committer | Keith Whitwell <keith@tungstengraphics.com> | 2006-10-30 20:16:35 +0000 |
commit | fd2756006a0baf63f60548d8f509de5b9a143608 (patch) | |
tree | dab83baaadc0ffd77c5dfa31a0e30084288683e6 | |
parent | e8abd098b36c30d76b4c396970fd793ae58e0702 (diff) |
Move edgeflag into the VERT_ATTRIB_SEVEN slot. This means that our
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.
-rw-r--r-- | src/mesa/main/api_noop.c | 2 | ||||
-rw-r--r-- | src/mesa/main/context.c | 4 | ||||
-rw-r--r-- | src/mesa/main/get.c | 6 | ||||
-rw-r--r-- | src/mesa/main/mtypes.h | 10 | ||||
-rw-r--r-- | src/mesa/main/state.c | 4 | ||||
-rw-r--r-- | src/mesa/vbo/vbo_context.c | 57 | ||||
-rw-r--r-- | src/mesa/vbo/vbo_context.h | 14 | ||||
-rw-r--r-- | src/mesa/vbo/vbo_exec.h | 3 | ||||
-rw-r--r-- | src/mesa/vbo/vbo_exec_api.c | 76 | ||||
-rw-r--r-- | src/mesa/vbo/vbo_exec_draw.c | 2 | ||||
-rw-r--r-- | src/mesa/vbo/vbo_save.c | 9 | ||||
-rw-r--r-- | src/mesa/vbo/vbo_save_draw.c | 22 |
12 files changed, 107 insertions, 102 deletions
diff --git a/src/mesa/main/api_noop.c b/src/mesa/main/api_noop.c index 33d44e4329..0c1a35361f 100644 --- a/src/mesa/main/api_noop.c +++ b/src/mesa/main/api_noop.c @@ -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 ) diff --git a/src/mesa/main/context.c b/src/mesa/main/context.c index e0630c33d0..15b69db595 100644 --- a/src/mesa/main/context.c +++ b/src/mesa/main/context.c @@ -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 ); } diff --git a/src/mesa/main/get.c b/src/mesa/main/get.c index 61a76d000b..2a24b56974 100644 --- a/src/mesa/main/get.c +++ b/src/mesa/main/get.c @@ -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: diff --git a/src/mesa/main/mtypes.h b/src/mesa/main/mtypes.h index 903779edae..bc7c6b8026 100644 --- a/src/mesa/main/mtypes.h +++ b/src/mesa/main/mtypes.h @@ -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 diff --git a/src/mesa/main/state.c b/src/mesa/main/state.c index 7dbcf8ad97..d57217d9c4 100644 --- a/src/mesa/main/state.c +++ b/src/mesa/main/state.c @@ -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 */ diff --git a/src/mesa/vbo/vbo_context.c b/src/mesa/vbo/vbo_context.c index 291eb0bed3..165e32da8a 100644 --- a/src/mesa/vbo/vbo_context.c +++ b/src/mesa/vbo/vbo_context.c @@ -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; } diff --git a/src/mesa/vbo/vbo_context.h b/src/mesa/vbo/vbo_context.h index 982da00437..cd02472023 100644 --- a/src/mesa/vbo/vbo_context.h +++ b/src/mesa/vbo/vbo_context.h @@ -57,13 +57,21 @@ 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; diff --git a/src/mesa/vbo/vbo_exec.h b/src/mesa/vbo/vbo_exec.h index ef158de825..e1fc7b2794 100644 --- a/src/mesa/vbo/vbo_exec.h +++ b/src/mesa/vbo/vbo_exec.h @@ -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; diff --git a/src/mesa/vbo/vbo_exec_api.c b/src/mesa/vbo/vbo_exec_api.c index c764c4d8b6..71fee8ca16 100644 --- a/src/mesa/vbo/vbo_exec_api.c +++ b/src/mesa/vbo/vbo_exec_api.c @@ -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; } diff --git a/src/mesa/vbo/vbo_exec_draw.c b/src/mesa/vbo/vbo_exec_draw.c index c1898aea49..846d5dc196 100644 --- a/src/mesa/vbo/vbo_exec_draw.c +++ b/src/mesa/vbo/vbo_exec_draw.c @@ -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: diff --git a/src/mesa/vbo/vbo_save.c b/src/mesa/vbo/vbo_save.c index 3a97ea66a4..e7f4687963 100644 --- a/src/mesa/vbo/vbo_save.c +++ b/src/mesa/vbo/vbo_save.c @@ -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; } diff --git a/src/mesa/vbo/vbo_save_draw.c b/src/mesa/vbo/vbo_save_draw.c index 18c770a41c..527e57d6bd 100644 --- a/src/mesa/vbo/vbo_save_draw.c +++ b/src/mesa/vbo/vbo_save_draw.c @@ -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: |