-#define ATTR( A, N, T, V0, V1, V2, V3 ) \
-do { \
- struct vbo_exec_context *exec = &vbo_context(ctx)->exec; \
- \
- if (unlikely(!(ctx->Driver.NeedFlush & FLUSH_UPDATE_CURRENT))) \
- ctx->Driver.BeginVertices( ctx ); \
- \
- if (unlikely(exec->vtx.active_sz[A] != N)) \
- vbo_exec_fixup_vertex(ctx, A, N); \
- \
- { \
- GLfloat *dest = exec->vtx.attrptr[A]; \
- if (N>0) dest[0] = V0; \
- if (N>1) dest[1] = V1; \
- if (N>2) dest[2] = V2; \
- if (N>3) dest[3] = V3; \
- exec->vtx.attrtype[A] = T; \
- } \
- \
- if ((A) == 0) { \
- /* This is a glVertex call */ \
- GLuint i; \
- \
- for (i = 0; i < exec->vtx.vertex_size; i++) \
- exec->vtx.buffer_ptr[i] = exec->vtx.vertex[i]; \
- \
- exec->vtx.buffer_ptr += exec->vtx.vertex_size; \
- \
- /* Set FLUSH_STORED_VERTICES to indicate that there's now */ \
- /* something to draw (not just updating a color or texcoord).*/ \
- ctx->Driver.NeedFlush |= FLUSH_STORED_VERTICES; \
- \
- if (++exec->vtx.vert_count >= exec->vtx.max_vert) \
- vbo_exec_vtx_wrap( exec ); \
- } \
+#define ATTR_UNION(A, N, T, C, V0, V1, V2, V3) \
+do { \
+ struct vbo_exec_context *exec = &vbo_context(ctx)->exec; \
+ int sz = (sizeof(C) / sizeof(GLfloat)); \
+ \
+ assert(sz == 1 || sz == 2); \
+ \
+ /* check if attribute size or type is changing */ \
+ if (unlikely(exec->vtx.active_sz[A] != N * sz) || \
+ unlikely(exec->vtx.attrtype[A] != T)) { \
+ vbo_exec_fixup_vertex(ctx, A, N * sz, T); \
+ } \
+ \
+ /* store vertex attribute in vertex buffer */ \
+ { \
+ C *dest = (C *)exec->vtx.attrptr[A]; \
+ if (N>0) dest[0] = V0; \
+ if (N>1) dest[1] = V1; \
+ if (N>2) dest[2] = V2; \
+ if (N>3) dest[3] = V3; \
+ assert(exec->vtx.attrtype[A] == T); \
+ } \
+ \
+ if ((A) == 0) { \
+ /* This is a glVertex call */ \
+ GLuint i; \
+ \
+ if (unlikely((ctx->Driver.NeedFlush & FLUSH_UPDATE_CURRENT) == 0)) { \
+ vbo_exec_begin_vertices(ctx); \
+ } \
+ \
+ if (unlikely(!exec->vtx.buffer_ptr)) { \
+ vbo_exec_vtx_map(exec); \
+ } \
+ assert(exec->vtx.buffer_ptr); \
+ \
+ /* copy 32-bit words */ \
+ for (i = 0; i < exec->vtx.vertex_size; i++) \
+ exec->vtx.buffer_ptr[i] = exec->vtx.vertex[i]; \
+ \
+ exec->vtx.buffer_ptr += exec->vtx.vertex_size; \
+ \
+ /* Set FLUSH_STORED_VERTICES to indicate that there's now */ \
+ /* something to draw (not just updating a color or texcoord).*/ \
+ ctx->Driver.NeedFlush |= FLUSH_STORED_VERTICES; \
+ \
+ if (++exec->vtx.vert_count >= exec->vtx.max_vert) \
+ vbo_exec_vtx_wrap(exec); \
+ } else { \
+ /* we now have accumulated per-vertex attributes */ \
+ ctx->Driver.NeedFlush |= FLUSH_UPDATE_CURRENT; \
+ } \