aboutsummaryrefslogtreecommitdiff
path: root/mesalib/src/mesa/vbo
diff options
context:
space:
mode:
Diffstat (limited to 'mesalib/src/mesa/vbo')
-rw-r--r--mesalib/src/mesa/vbo/vbo.h338
-rw-r--r--mesalib/src/mesa/vbo/vbo_attrib_tmp.h1226
-rw-r--r--mesalib/src/mesa/vbo/vbo_context.c494
-rw-r--r--mesalib/src/mesa/vbo/vbo_context.h224
-rw-r--r--mesalib/src/mesa/vbo/vbo_exec.c184
-rw-r--r--mesalib/src/mesa/vbo/vbo_exec.h396
-rw-r--r--mesalib/src/mesa/vbo/vbo_exec_api.c2111
-rw-r--r--mesalib/src/mesa/vbo/vbo_exec_array.c2490
-rw-r--r--mesalib/src/mesa/vbo/vbo_exec_draw.c841
-rw-r--r--mesalib/src/mesa/vbo/vbo_exec_eval.c526
-rw-r--r--mesalib/src/mesa/vbo/vbo_rebase.c490
-rw-r--r--mesalib/src/mesa/vbo/vbo_save.c244
-rw-r--r--mesalib/src/mesa/vbo/vbo_save.h400
-rw-r--r--mesalib/src/mesa/vbo/vbo_save_api.c2579
-rw-r--r--mesalib/src/mesa/vbo/vbo_save_draw.c606
-rw-r--r--mesalib/src/mesa/vbo/vbo_save_loopback.c390
-rw-r--r--mesalib/src/mesa/vbo/vbo_split.c338
-rw-r--r--mesalib/src/mesa/vbo/vbo_split.h144
-rw-r--r--mesalib/src/mesa/vbo/vbo_split_copy.c1250
-rw-r--r--mesalib/src/mesa/vbo/vbo_split_inplace.c566
20 files changed, 8127 insertions, 7710 deletions
diff --git a/mesalib/src/mesa/vbo/vbo.h b/mesalib/src/mesa/vbo/vbo.h
index 07d31f6ce..3575aa749 100644
--- a/mesalib/src/mesa/vbo/vbo.h
+++ b/mesalib/src/mesa/vbo/vbo.h
@@ -1,168 +1,170 @@
-/*
- * mesa 3-D graphics library
- * Version: 6.5
- *
- * Copyright (C) 1999-2006 Brian Paul All Rights Reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included
- * in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
- * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- */
-
-/**
- * \file vbo_context.h
- * \brief VBO builder module datatypes and definitions.
- * \author Keith Whitwell
- */
-
-
-#ifndef _VBO_H
-#define _VBO_H
-
-#include "main/mtypes.h"
-
-struct _mesa_prim {
- GLuint mode:8;
- GLuint indexed:1;
- GLuint begin:1;
- GLuint end:1;
- GLuint weak:1;
- GLuint pad:20;
-
- GLuint start;
- GLuint count;
- GLint basevertex;
- GLsizei num_instances;
-};
-
-/* Would like to call this a "vbo_index_buffer", but this would be
- * confusing as the indices are not neccessarily yet in a non-null
- * buffer object.
- */
-struct _mesa_index_buffer {
- GLuint count;
- GLenum type;
- struct gl_buffer_object *obj;
- const void *ptr;
-};
-
-
-
-GLboolean _vbo_CreateContext( GLcontext *ctx );
-void _vbo_DestroyContext( GLcontext *ctx );
-void _vbo_InvalidateState( GLcontext *ctx, GLuint new_state );
-
-
-typedef void (*vbo_draw_func)( GLcontext *ctx,
- const struct gl_client_array **arrays,
- const struct _mesa_prim *prims,
- GLuint nr_prims,
- const struct _mesa_index_buffer *ib,
- GLboolean index_bounds_valid,
- GLuint min_index,
- GLuint max_index );
-
-
-
-
-/* Utility function to cope with various constraints on tnl modules or
- * hardware. This can be used to split an incoming set of arrays and
- * primitives against the following constraints:
- * - Maximum number of indices in index buffer.
- * - Maximum number of vertices referenced by index buffer.
- * - Maximum hardware vertex buffer size.
- */
-struct split_limits {
- GLuint max_verts;
- GLuint max_indices;
- GLuint max_vb_size; /* bytes */
-};
-
-
-void vbo_split_prims( GLcontext *ctx,
- const struct gl_client_array *arrays[],
- const struct _mesa_prim *prim,
- GLuint nr_prims,
- const struct _mesa_index_buffer *ib,
- GLuint min_index,
- GLuint max_index,
- vbo_draw_func draw,
- const struct split_limits *limits );
-
-
-/* Helpers for dealing translating away non-zero min_index.
- */
-GLboolean vbo_all_varyings_in_vbos( const struct gl_client_array *arrays[] );
-
-void vbo_rebase_prims( GLcontext *ctx,
- const struct gl_client_array *arrays[],
- const struct _mesa_prim *prim,
- GLuint nr_prims,
- const struct _mesa_index_buffer *ib,
- GLuint min_index,
- GLuint max_index,
- vbo_draw_func draw );
-void
-vbo_get_minmax_index(GLcontext *ctx, const struct _mesa_prim *prim,
- const struct _mesa_index_buffer *ib,
- GLuint *min_index, GLuint *max_index);
-
-void vbo_use_buffer_objects(GLcontext *ctx);
-
-
-void vbo_set_draw_func(GLcontext *ctx, vbo_draw_func func);
-
-
-void GLAPIENTRY
-_vbo_Color4f(GLfloat r, GLfloat g, GLfloat b, GLfloat a);
-
-void GLAPIENTRY
-_vbo_Normal3f(GLfloat x, GLfloat y, GLfloat z);
-
-void GLAPIENTRY
-_vbo_MultiTexCoord4f(GLenum target, GLfloat s, GLfloat t, GLfloat r, GLfloat q);
-
-void GLAPIENTRY
-_vbo_Materialfv(GLenum face, GLenum pname, const GLfloat *params);
-
-void GLAPIENTRY
-_vbo_Materialf(GLenum face, GLenum pname, GLfloat param);
-
-void GLAPIENTRY
-_vbo_VertexAttrib4f(GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w);
-
-void GLAPIENTRY
-_vbo_VertexAttrib1f(GLuint indx, GLfloat x);
-
-void GLAPIENTRY
-_vbo_VertexAttrib1fv(GLuint indx, const GLfloat* values);
-
-void GLAPIENTRY
-_vbo_VertexAttrib2f(GLuint indx, GLfloat x, GLfloat y);
-
-void GLAPIENTRY
-_vbo_VertexAttrib2fv(GLuint indx, const GLfloat* values);
-
-void GLAPIENTRY
-_vbo_VertexAttrib3f(GLuint indx, GLfloat x, GLfloat y, GLfloat z);
-
-void GLAPIENTRY
-_vbo_VertexAttrib3fv(GLuint indx, const GLfloat* values);
-
-void GLAPIENTRY
-_vbo_VertexAttrib4fv(GLuint indx, const GLfloat* values);
-
-#endif
+/*
+ * mesa 3-D graphics library
+ * Version: 6.5
+ *
+ * Copyright (C) 1999-2006 Brian Paul All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+ * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/**
+ * \file vbo_context.h
+ * \brief VBO builder module datatypes and definitions.
+ * \author Keith Whitwell
+ */
+
+
+#ifndef _VBO_H
+#define _VBO_H
+
+#include "main/mtypes.h"
+
+struct _mesa_prim {
+ GLuint mode:8;
+ GLuint indexed:1;
+ GLuint begin:1;
+ GLuint end:1;
+ GLuint weak:1;
+ GLuint no_current_update:1;
+ GLuint pad:19;
+
+ GLuint start;
+ GLuint count;
+ GLint basevertex;
+ GLsizei num_instances;
+};
+
+/* Would like to call this a "vbo_index_buffer", but this would be
+ * confusing as the indices are not neccessarily yet in a non-null
+ * buffer object.
+ */
+struct _mesa_index_buffer {
+ GLuint count;
+ GLenum type;
+ struct gl_buffer_object *obj;
+ const void *ptr;
+};
+
+
+
+GLboolean _vbo_CreateContext( struct gl_context *ctx );
+void _vbo_DestroyContext( struct gl_context *ctx );
+void _vbo_InvalidateState( struct gl_context *ctx, GLuint new_state );
+
+
+typedef void (*vbo_draw_func)( struct gl_context *ctx,
+ const struct gl_client_array **arrays,
+ const struct _mesa_prim *prims,
+ GLuint nr_prims,
+ const struct _mesa_index_buffer *ib,
+ GLboolean index_bounds_valid,
+ GLuint min_index,
+ GLuint max_index );
+
+
+
+
+/* Utility function to cope with various constraints on tnl modules or
+ * hardware. This can be used to split an incoming set of arrays and
+ * primitives against the following constraints:
+ * - Maximum number of indices in index buffer.
+ * - Maximum number of vertices referenced by index buffer.
+ * - Maximum hardware vertex buffer size.
+ */
+struct split_limits {
+ GLuint max_verts;
+ GLuint max_indices;
+ GLuint max_vb_size; /* bytes */
+};
+
+
+void vbo_split_prims( struct gl_context *ctx,
+ const struct gl_client_array *arrays[],
+ const struct _mesa_prim *prim,
+ GLuint nr_prims,
+ const struct _mesa_index_buffer *ib,
+ GLuint min_index,
+ GLuint max_index,
+ vbo_draw_func draw,
+ const struct split_limits *limits );
+
+
+/* Helpers for dealing translating away non-zero min_index.
+ */
+GLboolean vbo_all_varyings_in_vbos( const struct gl_client_array *arrays[] );
+GLboolean vbo_any_varyings_in_vbos( const struct gl_client_array *arrays[] );
+
+void vbo_rebase_prims( struct gl_context *ctx,
+ const struct gl_client_array *arrays[],
+ const struct _mesa_prim *prim,
+ GLuint nr_prims,
+ const struct _mesa_index_buffer *ib,
+ GLuint min_index,
+ GLuint max_index,
+ vbo_draw_func draw );
+void
+vbo_get_minmax_index(struct gl_context *ctx, const struct _mesa_prim *prim,
+ const struct _mesa_index_buffer *ib,
+ GLuint *min_index, GLuint *max_index);
+
+void vbo_use_buffer_objects(struct gl_context *ctx);
+
+
+void vbo_set_draw_func(struct gl_context *ctx, vbo_draw_func func);
+
+
+void GLAPIENTRY
+_es_Color4f(GLfloat r, GLfloat g, GLfloat b, GLfloat a);
+
+void GLAPIENTRY
+_es_Normal3f(GLfloat x, GLfloat y, GLfloat z);
+
+void GLAPIENTRY
+_es_MultiTexCoord4f(GLenum target, GLfloat s, GLfloat t, GLfloat r, GLfloat q);
+
+void GLAPIENTRY
+_es_Materialfv(GLenum face, GLenum pname, const GLfloat *params);
+
+void GLAPIENTRY
+_es_Materialf(GLenum face, GLenum pname, GLfloat param);
+
+void GLAPIENTRY
+_es_VertexAttrib4f(GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w);
+
+void GLAPIENTRY
+_es_VertexAttrib1f(GLuint indx, GLfloat x);
+
+void GLAPIENTRY
+_es_VertexAttrib1fv(GLuint indx, const GLfloat* values);
+
+void GLAPIENTRY
+_es_VertexAttrib2f(GLuint indx, GLfloat x, GLfloat y);
+
+void GLAPIENTRY
+_es_VertexAttrib2fv(GLuint indx, const GLfloat* values);
+
+void GLAPIENTRY
+_es_VertexAttrib3f(GLuint indx, GLfloat x, GLfloat y, GLfloat z);
+
+void GLAPIENTRY
+_es_VertexAttrib3fv(GLuint indx, const GLfloat* values);
+
+void GLAPIENTRY
+_es_VertexAttrib4fv(GLuint indx, const GLfloat* values);
+
+#endif
diff --git a/mesalib/src/mesa/vbo/vbo_attrib_tmp.h b/mesalib/src/mesa/vbo/vbo_attrib_tmp.h
index 7a889b8e2..654f0eaae 100644
--- a/mesalib/src/mesa/vbo/vbo_attrib_tmp.h
+++ b/mesalib/src/mesa/vbo/vbo_attrib_tmp.h
@@ -1,486 +1,740 @@
-/**************************************************************************
-
-Copyright 2002 Tungsten Graphics Inc., Cedar Park, Texas.
-
-All Rights Reserved.
-
-Permission is hereby granted, free of charge, to any person obtaining a
-copy of this software and associated documentation files (the "Software"),
-to deal in the Software without restriction, including without limitation
-on the rights to use, copy, modify, merge, publish, distribute, sub
-license, and/or sell copies of the Software, and to permit persons to whom
-the Software is furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice (including the next
-paragraph) shall be included in all copies or substantial portions of the
-Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
-TUNGSTEN GRAPHICS AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
-DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
-OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
-USE OR OTHER DEALINGS IN THE SOFTWARE.
-
-**************************************************************************/
-
-#define ATTR1FV( A, V ) ATTR( A, 1, (V)[0], 0, 0, 1 )
-#define ATTR2FV( A, V ) ATTR( A, 2, (V)[0], (V)[1], 0, 1 )
-#define ATTR3FV( A, V ) ATTR( A, 3, (V)[0], (V)[1], (V)[2], 1 )
-#define ATTR4FV( A, V ) ATTR( A, 4, (V)[0], (V)[1], (V)[2], (V)[3] )
-
-#define ATTR1F( A, X ) ATTR( A, 1, X, 0, 0, 1 )
-#define ATTR2F( A, X, Y ) ATTR( A, 2, X, Y, 0, 1 )
-#define ATTR3F( A, X, Y, Z ) ATTR( A, 3, X, Y, Z, 1 )
-#define ATTR4F( A, X, Y, Z, W ) ATTR( A, 4, X, Y, Z, W )
-
-#define MAT_ATTR( A, N, V ) ATTR( A, N, (V)[0], (V)[1], (V)[2], (V)[3] )
-
-static void GLAPIENTRY TAG(Vertex2f)( GLfloat x, GLfloat y )
-{
- GET_CURRENT_CONTEXT( ctx );
- ATTR2F( VBO_ATTRIB_POS, x, y );
-}
-
-static void GLAPIENTRY TAG(Vertex2fv)( const GLfloat *v )
-{
- GET_CURRENT_CONTEXT( ctx );
- ATTR2FV( VBO_ATTRIB_POS, v );
-}
-
-static void GLAPIENTRY TAG(Vertex3f)( GLfloat x, GLfloat y, GLfloat z )
-{
- GET_CURRENT_CONTEXT( ctx );
- ATTR3F( VBO_ATTRIB_POS, x, y, z );
-}
-
-static void GLAPIENTRY TAG(Vertex3fv)( const GLfloat *v )
-{
- GET_CURRENT_CONTEXT( ctx );
- ATTR3FV( VBO_ATTRIB_POS, v );
-}
-
-static void GLAPIENTRY TAG(Vertex4f)( GLfloat x, GLfloat y, GLfloat z, GLfloat w )
-{
- GET_CURRENT_CONTEXT( ctx );
- ATTR4F( VBO_ATTRIB_POS, x, y, z, w );
-}
-
-static void GLAPIENTRY TAG(Vertex4fv)( const GLfloat *v )
-{
- GET_CURRENT_CONTEXT( ctx );
- ATTR4FV( VBO_ATTRIB_POS, v );
-}
-
-static void GLAPIENTRY TAG(TexCoord1f)( GLfloat x )
-{
- GET_CURRENT_CONTEXT( ctx );
- ATTR1F( VBO_ATTRIB_TEX0, x );
-}
-
-static void GLAPIENTRY TAG(TexCoord1fv)( const GLfloat *v )
-{
- GET_CURRENT_CONTEXT( ctx );
- ATTR1FV( VBO_ATTRIB_TEX0, v );
-}
-
-static void GLAPIENTRY TAG(TexCoord2f)( GLfloat x, GLfloat y )
-{
- GET_CURRENT_CONTEXT( ctx );
- ATTR2F( VBO_ATTRIB_TEX0, x, y );
-}
-
-static void GLAPIENTRY TAG(TexCoord2fv)( const GLfloat *v )
-{
- GET_CURRENT_CONTEXT( ctx );
- ATTR2FV( VBO_ATTRIB_TEX0, v );
-}
-
-static void GLAPIENTRY TAG(TexCoord3f)( GLfloat x, GLfloat y, GLfloat z )
-{
- GET_CURRENT_CONTEXT( ctx );
- ATTR3F( VBO_ATTRIB_TEX0, x, y, z );
-}
-
-static void GLAPIENTRY TAG(TexCoord3fv)( const GLfloat *v )
-{
- GET_CURRENT_CONTEXT( ctx );
- ATTR3FV( VBO_ATTRIB_TEX0, v );
-}
-
-static void GLAPIENTRY TAG(TexCoord4f)( GLfloat x, GLfloat y, GLfloat z, GLfloat w )
-{
- GET_CURRENT_CONTEXT( ctx );
- ATTR4F( VBO_ATTRIB_TEX0, x, y, z, w );
-}
-
-static void GLAPIENTRY TAG(TexCoord4fv)( const GLfloat *v )
-{
- GET_CURRENT_CONTEXT( ctx );
- ATTR4FV( VBO_ATTRIB_TEX0, v );
-}
-
-static void GLAPIENTRY TAG(Normal3f)( GLfloat x, GLfloat y, GLfloat z )
-{
- GET_CURRENT_CONTEXT( ctx );
- ATTR3F( VBO_ATTRIB_NORMAL, x, y, z );
-}
-
-static void GLAPIENTRY TAG(Normal3fv)( const GLfloat *v )
-{
- GET_CURRENT_CONTEXT( ctx );
- ATTR3FV( VBO_ATTRIB_NORMAL, v );
-}
-
-static void GLAPIENTRY TAG(FogCoordfEXT)( GLfloat x )
-{
- GET_CURRENT_CONTEXT( ctx );
- ATTR1F( VBO_ATTRIB_FOG, x );
-}
-
-static void GLAPIENTRY TAG(FogCoordfvEXT)( const GLfloat *v )
-{
- GET_CURRENT_CONTEXT( ctx );
- ATTR1FV( VBO_ATTRIB_FOG, v );
-}
-
-static void GLAPIENTRY TAG(Color3f)( GLfloat x, GLfloat y, GLfloat z )
-{
- GET_CURRENT_CONTEXT( ctx );
- ATTR3F( VBO_ATTRIB_COLOR0, x, y, z );
-}
-
-static void GLAPIENTRY TAG(Color3fv)( const GLfloat *v )
-{
- GET_CURRENT_CONTEXT( ctx );
- ATTR3FV( VBO_ATTRIB_COLOR0, v );
-}
-
-static void GLAPIENTRY TAG(Color4f)( GLfloat x, GLfloat y, GLfloat z, GLfloat w )
-{
- GET_CURRENT_CONTEXT( ctx );
- ATTR4F( VBO_ATTRIB_COLOR0, x, y, z, w );
-}
-
-static void GLAPIENTRY TAG(Color4fv)( const GLfloat *v )
-{
- GET_CURRENT_CONTEXT( ctx );
- ATTR4FV( VBO_ATTRIB_COLOR0, v );
-}
-
-static void GLAPIENTRY TAG(SecondaryColor3fEXT)( GLfloat x, GLfloat y, GLfloat z )
-{
- GET_CURRENT_CONTEXT( ctx );
- ATTR3F( VBO_ATTRIB_COLOR1, x, y, z );
-}
-
-static void GLAPIENTRY TAG(SecondaryColor3fvEXT)( const GLfloat *v )
-{
- GET_CURRENT_CONTEXT( ctx );
- ATTR3FV( VBO_ATTRIB_COLOR1, v );
-}
-
-
-static void GLAPIENTRY TAG(EdgeFlag)( GLboolean b )
-{
- GET_CURRENT_CONTEXT( ctx );
- ATTR1F( VBO_ATTRIB_EDGEFLAG, (GLfloat)b );
-}
-
-static void GLAPIENTRY TAG(Indexf)( GLfloat f )
-{
- GET_CURRENT_CONTEXT( ctx );
- ATTR1F( VBO_ATTRIB_INDEX, f );
-}
-
-static void GLAPIENTRY TAG(Indexfv)( const GLfloat *f )
-{
- GET_CURRENT_CONTEXT( ctx );
- ATTR1FV( VBO_ATTRIB_INDEX, f );
-}
-
-
-static void GLAPIENTRY TAG(MultiTexCoord1f)( GLenum target, GLfloat x )
-{
- GET_CURRENT_CONTEXT( ctx );
- GLuint attr = (target & 0x7) + VBO_ATTRIB_TEX0;
- ATTR1F( attr, x );
-}
-
-static void GLAPIENTRY TAG(MultiTexCoord1fv)( GLenum target, const GLfloat *v )
-{
- GET_CURRENT_CONTEXT( ctx );
- GLuint attr = (target & 0x7) + VBO_ATTRIB_TEX0;
- ATTR1FV( attr, v );
-}
-
-static void GLAPIENTRY TAG(MultiTexCoord2f)( GLenum target, GLfloat x, GLfloat y )
-{
- GET_CURRENT_CONTEXT( ctx );
- GLuint attr = (target & 0x7) + VBO_ATTRIB_TEX0;
- ATTR2F( attr, x, y );
-}
-
-static void GLAPIENTRY TAG(MultiTexCoord2fv)( GLenum target, const GLfloat *v )
-{
- GET_CURRENT_CONTEXT( ctx );
- GLuint attr = (target & 0x7) + VBO_ATTRIB_TEX0;
- ATTR2FV( attr, v );
-}
-
-static void GLAPIENTRY TAG(MultiTexCoord3f)( GLenum target, GLfloat x, GLfloat y,
- GLfloat z)
-{
- GET_CURRENT_CONTEXT( ctx );
- GLuint attr = (target & 0x7) + VBO_ATTRIB_TEX0;
- ATTR3F( attr, x, y, z );
-}
-
-static void GLAPIENTRY TAG(MultiTexCoord3fv)( GLenum target, const GLfloat *v )
-{
- GET_CURRENT_CONTEXT( ctx );
- GLuint attr = (target & 0x7) + VBO_ATTRIB_TEX0;
- ATTR3FV( attr, v );
-}
-
-static void GLAPIENTRY TAG(MultiTexCoord4f)( GLenum target, GLfloat x, GLfloat y,
- GLfloat z, GLfloat w )
-{
- GET_CURRENT_CONTEXT( ctx );
- GLuint attr = (target & 0x7) + VBO_ATTRIB_TEX0;
- ATTR4F( attr, x, y, z, w );
-}
-
-static void GLAPIENTRY TAG(MultiTexCoord4fv)( GLenum target, const GLfloat *v )
-{
- GET_CURRENT_CONTEXT( ctx );
- GLuint attr = (target & 0x7) + VBO_ATTRIB_TEX0;
- ATTR4FV( attr, v );
-}
-
-
-static void GLAPIENTRY TAG(VertexAttrib1fARB)( GLuint index, GLfloat x )
-{
- GET_CURRENT_CONTEXT( ctx );
- if (index == 0)
- ATTR1F(0, x);
- else if (index < MAX_VERTEX_GENERIC_ATTRIBS)
- ATTR1F(VBO_ATTRIB_GENERIC0 + index, x);
- else
- ERROR();
-}
-
-static void GLAPIENTRY TAG(VertexAttrib1fvARB)( GLuint index,
- const GLfloat *v )
-{
- GET_CURRENT_CONTEXT( ctx );
- if (index == 0)
- ATTR1FV(0, v);
- else if (index < MAX_VERTEX_GENERIC_ATTRIBS)
- ATTR1FV(VBO_ATTRIB_GENERIC0 + index, v);
- else
- ERROR();
-}
-
-static void GLAPIENTRY TAG(VertexAttrib2fARB)( GLuint index, GLfloat x,
- GLfloat y )
-{
- GET_CURRENT_CONTEXT( ctx );
- if (index == 0)
- ATTR2F(0, x, y);
- else if (index < MAX_VERTEX_GENERIC_ATTRIBS)
- ATTR2F(VBO_ATTRIB_GENERIC0 + index, x, y);
- else
- ERROR();
-}
-
-static void GLAPIENTRY TAG(VertexAttrib2fvARB)( GLuint index,
- const GLfloat *v )
-{
- GET_CURRENT_CONTEXT( ctx );
- if (index == 0)
- ATTR2FV(0, v);
- else if (index < MAX_VERTEX_GENERIC_ATTRIBS)
- ATTR2FV(VBO_ATTRIB_GENERIC0 + index, v);
- else
- ERROR();
-}
-
-static void GLAPIENTRY TAG(VertexAttrib3fARB)( GLuint index, GLfloat x,
- GLfloat y, GLfloat z )
-{
- GET_CURRENT_CONTEXT( ctx );
- if (index == 0)
- ATTR3F(0, x, y, z);
- else if (index < MAX_VERTEX_GENERIC_ATTRIBS)
- ATTR3F(VBO_ATTRIB_GENERIC0 + index, x, y, z);
- else
- ERROR();
-}
-
-static void GLAPIENTRY TAG(VertexAttrib3fvARB)( GLuint index,
- const GLfloat *v )
-{
- GET_CURRENT_CONTEXT( ctx );
- if (index == 0)
- ATTR3FV(0, v);
- else if (index < MAX_VERTEX_GENERIC_ATTRIBS)
- ATTR3FV(VBO_ATTRIB_GENERIC0 + index, v);
- else
- ERROR();
-}
-
-static void GLAPIENTRY TAG(VertexAttrib4fARB)( GLuint index, GLfloat x,
- GLfloat y, GLfloat z,
- GLfloat w )
-{
- GET_CURRENT_CONTEXT( ctx );
- if (index == 0)
- ATTR4F(0, x, y, z, w);
- else if (index < MAX_VERTEX_GENERIC_ATTRIBS)
- ATTR4F(VBO_ATTRIB_GENERIC0 + index, x, y, z, w);
- else
- ERROR();
-}
-
-static void GLAPIENTRY TAG(VertexAttrib4fvARB)( GLuint index,
- const GLfloat *v )
-{
- GET_CURRENT_CONTEXT( ctx );
- if (index == 0)
- ATTR4FV(0, v);
- else if (index < MAX_VERTEX_GENERIC_ATTRIBS)
- ATTR4FV(VBO_ATTRIB_GENERIC0 + index, v);
- else
- ERROR();
-}
-
-
-/* In addition to supporting NV_vertex_program, these entrypoints are
- * used by the display list and other code specifically because of
- * their property of aliasing with other attributes. (See
- * vbo_save_loopback.c)
- */
-static void GLAPIENTRY TAG(VertexAttrib1fNV)( GLuint index, GLfloat x )
-{
- GET_CURRENT_CONTEXT( ctx );
- if (index < VBO_ATTRIB_MAX)
- ATTR1F(index, x);
-}
-
-static void GLAPIENTRY TAG(VertexAttrib1fvNV)( GLuint index,
- const GLfloat *v )
-{
- GET_CURRENT_CONTEXT( ctx );
- if (index < VBO_ATTRIB_MAX)
- ATTR1FV(index, v);
-}
-
-static void GLAPIENTRY TAG(VertexAttrib2fNV)( GLuint index, GLfloat x,
- GLfloat y )
-{
- GET_CURRENT_CONTEXT( ctx );
- if (index < VBO_ATTRIB_MAX)
- ATTR2F(index, x, y);
-}
-
-static void GLAPIENTRY TAG(VertexAttrib2fvNV)( GLuint index,
- const GLfloat *v )
-{
- GET_CURRENT_CONTEXT( ctx );
- if (index < VBO_ATTRIB_MAX)
- ATTR2FV(index, v);
-}
-
-static void GLAPIENTRY TAG(VertexAttrib3fNV)( GLuint index, GLfloat x,
- GLfloat y, GLfloat z )
-{
- GET_CURRENT_CONTEXT( ctx );
- if (index < VBO_ATTRIB_MAX)
- ATTR3F(index, x, y, z);
-}
-
-static void GLAPIENTRY TAG(VertexAttrib3fvNV)( GLuint index,
- const GLfloat *v )
-{
- GET_CURRENT_CONTEXT( ctx );
- if (index < VBO_ATTRIB_MAX)
- ATTR3FV(index, v);
-}
-
-static void GLAPIENTRY TAG(VertexAttrib4fNV)( GLuint index, GLfloat x,
- GLfloat y, GLfloat z,
- GLfloat w )
-{
- GET_CURRENT_CONTEXT( ctx );
- if (index < VBO_ATTRIB_MAX)
- ATTR4F(index, x, y, z, w);
-}
-
-static void GLAPIENTRY TAG(VertexAttrib4fvNV)( GLuint index,
- const GLfloat *v )
-{
- GET_CURRENT_CONTEXT( ctx );
- if (index < VBO_ATTRIB_MAX)
- ATTR4FV(index, v);
-}
-
-
-#define MAT( ATTR, N, face, params ) \
-do { \
- if (face != GL_BACK) \
- MAT_ATTR( ATTR, N, params ); /* front */ \
- if (face != GL_FRONT) \
- MAT_ATTR( ATTR + 1, N, params ); /* back */ \
-} while (0)
-
-
-/* Colormaterial conflicts are dealt with later.
- */
-static void GLAPIENTRY TAG(Materialfv)( GLenum face, GLenum pname,
- const GLfloat *params )
-{
- GET_CURRENT_CONTEXT( ctx );
- switch (pname) {
- case GL_EMISSION:
- MAT( VBO_ATTRIB_MAT_FRONT_EMISSION, 4, face, params );
- break;
- case GL_AMBIENT:
- MAT( VBO_ATTRIB_MAT_FRONT_AMBIENT, 4, face, params );
- break;
- case GL_DIFFUSE:
- MAT( VBO_ATTRIB_MAT_FRONT_DIFFUSE, 4, face, params );
- break;
- case GL_SPECULAR:
- MAT( VBO_ATTRIB_MAT_FRONT_SPECULAR, 4, face, params );
- break;
- case GL_SHININESS:
- MAT( VBO_ATTRIB_MAT_FRONT_SHININESS, 1, face, params );
- break;
- case GL_COLOR_INDEXES:
- MAT( VBO_ATTRIB_MAT_FRONT_INDEXES, 3, face, params );
- break;
- case GL_AMBIENT_AND_DIFFUSE:
- MAT( VBO_ATTRIB_MAT_FRONT_AMBIENT, 4, face, params );
- MAT( VBO_ATTRIB_MAT_FRONT_DIFFUSE, 4, face, params );
- break;
- default:
- ERROR();
- return;
- }
-}
-
-
-#undef ATTR1FV
-#undef ATTR2FV
-#undef ATTR3FV
-#undef ATTR4FV
-
-#undef ATTR1F
-#undef ATTR2F
-#undef ATTR3F
-#undef ATTR4F
-
-#undef MAT
-#undef MAT_ATTR
+/**************************************************************************
+
+Copyright 2002 Tungsten Graphics Inc., Cedar Park, Texas.
+
+All Rights Reserved.
+
+Permission is hereby granted, free of charge, to any person obtaining a
+copy of this software and associated documentation files (the "Software"),
+to deal in the Software without restriction, including without limitation
+on the rights to use, copy, modify, merge, publish, distribute, sub
+license, and/or sell copies of the Software, and to permit persons to whom
+the Software is furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice (including the next
+paragraph) shall be included in all copies or substantial portions of the
+Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
+TUNGSTEN GRAPHICS AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
+DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+**************************************************************************/
+
+/* float */
+#define ATTR1FV( A, V ) ATTR( A, 1, (V)[0], 0, 0, 1 )
+#define ATTR2FV( A, V ) ATTR( A, 2, (V)[0], (V)[1], 0, 1 )
+#define ATTR3FV( A, V ) ATTR( A, 3, (V)[0], (V)[1], (V)[2], 1 )
+#define ATTR4FV( A, V ) ATTR( A, 4, (V)[0], (V)[1], (V)[2], (V)[3] )
+
+#define ATTR1F( A, X ) ATTR( A, 1, X, 0, 0, 1 )
+#define ATTR2F( A, X, Y ) ATTR( A, 2, X, Y, 0, 1 )
+#define ATTR3F( A, X, Y, Z ) ATTR( A, 3, X, Y, Z, 1 )
+#define ATTR4F( A, X, Y, Z, W ) ATTR( A, 4, X, Y, Z, W )
+
+/* int */
+#define ATTR2IV( A, V ) ATTR( A, 2, (V)[0], (V)[1], 0, 1 )
+#define ATTR3IV( A, V ) ATTR( A, 3, (V)[0], (V)[1], (V)[2], 1 )
+#define ATTR4IV( A, V ) ATTR( A, 4, (V)[0], (V)[1], (V)[2], (V)[3] )
+
+#define ATTR1I( A, X ) ATTR( A, 1, X, 0, 0, 1 )
+#define ATTR2I( A, X, Y ) ATTR( A, 2, X, Y, 0, 1 )
+#define ATTR3I( A, X, Y, Z ) ATTR( A, 3, X, Y, Z, 1 )
+#define ATTR4I( A, X, Y, Z, W ) ATTR( A, 4, X, Y, Z, W )
+
+
+/* uint */
+#define ATTR2UIV( A, V ) ATTR( A, 2, (V)[0], (V)[1], 0, 1 )
+#define ATTR3UIV( A, V ) ATTR( A, 3, (V)[0], (V)[1], (V)[2], 1 )
+#define ATTR4UIV( A, V ) ATTR( A, 4, (V)[0], (V)[1], (V)[2], (V)[3] )
+
+#define ATTR1UI( A, X ) ATTR( A, 1, X, 0, 0, 1 )
+#define ATTR2UI( A, X, Y ) ATTR( A, 2, X, Y, 0, 1 )
+#define ATTR3UI( A, X, Y, Z ) ATTR( A, 3, X, Y, Z, 1 )
+#define ATTR4UI( A, X, Y, Z, W ) ATTR( A, 4, X, Y, Z, W )
+
+#define MAT_ATTR( A, N, V ) ATTR( A, N, (V)[0], (V)[1], (V)[2], (V)[3] )
+
+
+
+static void GLAPIENTRY
+TAG(Vertex2f)(GLfloat x, GLfloat y)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ ATTR2F(VBO_ATTRIB_POS, x, y);
+}
+
+static void GLAPIENTRY
+TAG(Vertex2fv)(const GLfloat * v)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ ATTR2FV(VBO_ATTRIB_POS, v);
+}
+
+static void GLAPIENTRY
+TAG(Vertex3f)(GLfloat x, GLfloat y, GLfloat z)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ ATTR3F(VBO_ATTRIB_POS, x, y, z);
+}
+
+static void GLAPIENTRY
+TAG(Vertex3fv)(const GLfloat * v)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ ATTR3FV(VBO_ATTRIB_POS, v);
+}
+
+static void GLAPIENTRY
+TAG(Vertex4f)(GLfloat x, GLfloat y, GLfloat z, GLfloat w)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ ATTR4F(VBO_ATTRIB_POS, x, y, z, w);
+}
+
+static void GLAPIENTRY
+TAG(Vertex4fv)(const GLfloat * v)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ ATTR4FV(VBO_ATTRIB_POS, v);
+}
+
+
+
+static void GLAPIENTRY
+TAG(TexCoord1f)(GLfloat x)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ ATTR1F(VBO_ATTRIB_TEX0, x);
+}
+
+static void GLAPIENTRY
+TAG(TexCoord1fv)(const GLfloat * v)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ ATTR1FV(VBO_ATTRIB_TEX0, v);
+}
+
+static void GLAPIENTRY
+TAG(TexCoord2f)(GLfloat x, GLfloat y)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ ATTR2F(VBO_ATTRIB_TEX0, x, y);
+}
+
+static void GLAPIENTRY
+TAG(TexCoord2fv)(const GLfloat * v)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ ATTR2FV(VBO_ATTRIB_TEX0, v);
+}
+
+static void GLAPIENTRY
+TAG(TexCoord3f)(GLfloat x, GLfloat y, GLfloat z)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ ATTR3F(VBO_ATTRIB_TEX0, x, y, z);
+}
+
+static void GLAPIENTRY
+TAG(TexCoord3fv)(const GLfloat * v)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ ATTR3FV(VBO_ATTRIB_TEX0, v);
+}
+
+static void GLAPIENTRY
+TAG(TexCoord4f)(GLfloat x, GLfloat y, GLfloat z, GLfloat w)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ ATTR4F(VBO_ATTRIB_TEX0, x, y, z, w);
+}
+
+static void GLAPIENTRY
+TAG(TexCoord4fv)(const GLfloat * v)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ ATTR4FV(VBO_ATTRIB_TEX0, v);
+}
+
+
+
+static void GLAPIENTRY
+TAG(Normal3f)(GLfloat x, GLfloat y, GLfloat z)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ ATTR3F(VBO_ATTRIB_NORMAL, x, y, z);
+}
+
+static void GLAPIENTRY
+TAG(Normal3fv)(const GLfloat * v)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ ATTR3FV(VBO_ATTRIB_NORMAL, v);
+}
+
+
+
+static void GLAPIENTRY
+TAG(FogCoordfEXT)(GLfloat x)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ ATTR1F(VBO_ATTRIB_FOG, x);
+}
+
+
+
+static void GLAPIENTRY
+TAG(FogCoordfvEXT)(const GLfloat * v)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ ATTR1FV(VBO_ATTRIB_FOG, v);
+}
+
+static void GLAPIENTRY
+TAG(Color3f)(GLfloat x, GLfloat y, GLfloat z)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ ATTR3F(VBO_ATTRIB_COLOR0, x, y, z);
+}
+
+static void GLAPIENTRY
+TAG(Color3fv)(const GLfloat * v)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ ATTR3FV(VBO_ATTRIB_COLOR0, v);
+}
+
+static void GLAPIENTRY
+TAG(Color4f)(GLfloat x, GLfloat y, GLfloat z, GLfloat w)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ ATTR4F(VBO_ATTRIB_COLOR0, x, y, z, w);
+}
+
+static void GLAPIENTRY
+TAG(Color4fv)(const GLfloat * v)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ ATTR4FV(VBO_ATTRIB_COLOR0, v);
+}
+
+
+
+static void GLAPIENTRY
+TAG(SecondaryColor3fEXT)(GLfloat x, GLfloat y, GLfloat z)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ ATTR3F(VBO_ATTRIB_COLOR1, x, y, z);
+}
+
+static void GLAPIENTRY
+TAG(SecondaryColor3fvEXT)(const GLfloat * v)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ ATTR3FV(VBO_ATTRIB_COLOR1, v);
+}
+
+
+
+static void GLAPIENTRY
+TAG(EdgeFlag)(GLboolean b)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ ATTR1F(VBO_ATTRIB_EDGEFLAG, (GLfloat) b);
+}
+
+
+
+static void GLAPIENTRY
+TAG(Indexf)(GLfloat f)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ ATTR1F(VBO_ATTRIB_INDEX, f);
+}
+
+static void GLAPIENTRY
+TAG(Indexfv)(const GLfloat * f)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ ATTR1FV(VBO_ATTRIB_INDEX, f);
+}
+
+
+
+static void GLAPIENTRY
+TAG(MultiTexCoord1f)(GLenum target, GLfloat x)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ GLuint attr = (target & 0x7) + VBO_ATTRIB_TEX0;
+ ATTR1F(attr, x);
+}
+
+static void GLAPIENTRY
+TAG(MultiTexCoord1fv)(GLenum target, const GLfloat * v)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ GLuint attr = (target & 0x7) + VBO_ATTRIB_TEX0;
+ ATTR1FV(attr, v);
+}
+
+static void GLAPIENTRY
+TAG(MultiTexCoord2f)(GLenum target, GLfloat x, GLfloat y)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ GLuint attr = (target & 0x7) + VBO_ATTRIB_TEX0;
+ ATTR2F(attr, x, y);
+}
+
+static void GLAPIENTRY
+TAG(MultiTexCoord2fv)(GLenum target, const GLfloat * v)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ GLuint attr = (target & 0x7) + VBO_ATTRIB_TEX0;
+ ATTR2FV(attr, v);
+}
+
+static void GLAPIENTRY
+TAG(MultiTexCoord3f)(GLenum target, GLfloat x, GLfloat y, GLfloat z)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ GLuint attr = (target & 0x7) + VBO_ATTRIB_TEX0;
+ ATTR3F(attr, x, y, z);
+}
+
+static void GLAPIENTRY
+TAG(MultiTexCoord3fv)(GLenum target, const GLfloat * v)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ GLuint attr = (target & 0x7) + VBO_ATTRIB_TEX0;
+ ATTR3FV(attr, v);
+}
+
+static void GLAPIENTRY
+TAG(MultiTexCoord4f)(GLenum target, GLfloat x, GLfloat y, GLfloat z, GLfloat w)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ GLuint attr = (target & 0x7) + VBO_ATTRIB_TEX0;
+ ATTR4F(attr, x, y, z, w);
+}
+
+static void GLAPIENTRY
+TAG(MultiTexCoord4fv)(GLenum target, const GLfloat * v)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ GLuint attr = (target & 0x7) + VBO_ATTRIB_TEX0;
+ ATTR4FV(attr, v);
+}
+
+
+
+static void GLAPIENTRY
+TAG(VertexAttrib1fARB)(GLuint index, GLfloat x)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ if (index == 0)
+ ATTR1F(0, x);
+ else if (index < MAX_VERTEX_GENERIC_ATTRIBS)
+ ATTR1F(VBO_ATTRIB_GENERIC0 + index, x);
+ else
+ ERROR();
+}
+
+static void GLAPIENTRY
+TAG(VertexAttrib1fvARB)(GLuint index, const GLfloat * v)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ if (index == 0)
+ ATTR1FV(0, v);
+ else if (index < MAX_VERTEX_GENERIC_ATTRIBS)
+ ATTR1FV(VBO_ATTRIB_GENERIC0 + index, v);
+ else
+ ERROR();
+}
+
+static void GLAPIENTRY
+TAG(VertexAttrib2fARB)(GLuint index, GLfloat x, GLfloat y)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ if (index == 0)
+ ATTR2F(0, x, y);
+ else if (index < MAX_VERTEX_GENERIC_ATTRIBS)
+ ATTR2F(VBO_ATTRIB_GENERIC0 + index, x, y);
+ else
+ ERROR();
+}
+
+static void GLAPIENTRY
+TAG(VertexAttrib2fvARB)(GLuint index, const GLfloat * v)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ if (index == 0)
+ ATTR2FV(0, v);
+ else if (index < MAX_VERTEX_GENERIC_ATTRIBS)
+ ATTR2FV(VBO_ATTRIB_GENERIC0 + index, v);
+ else
+ ERROR();
+}
+
+static void GLAPIENTRY
+TAG(VertexAttrib3fARB)(GLuint index, GLfloat x, GLfloat y, GLfloat z)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ if (index == 0)
+ ATTR3F(0, x, y, z);
+ else if (index < MAX_VERTEX_GENERIC_ATTRIBS)
+ ATTR3F(VBO_ATTRIB_GENERIC0 + index, x, y, z);
+ else
+ ERROR();
+}
+
+static void GLAPIENTRY
+TAG(VertexAttrib3fvARB)(GLuint index, const GLfloat * v)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ if (index == 0)
+ ATTR3FV(0, v);
+ else if (index < MAX_VERTEX_GENERIC_ATTRIBS)
+ ATTR3FV(VBO_ATTRIB_GENERIC0 + index, v);
+ else
+ ERROR();
+}
+
+static void GLAPIENTRY
+TAG(VertexAttrib4fARB)(GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ if (index == 0)
+ ATTR4F(0, x, y, z, w);
+ else if (index < MAX_VERTEX_GENERIC_ATTRIBS)
+ ATTR4F(VBO_ATTRIB_GENERIC0 + index, x, y, z, w);
+ else
+ ERROR();
+}
+
+static void GLAPIENTRY
+TAG(VertexAttrib4fvARB)(GLuint index, const GLfloat * v)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ if (index == 0)
+ ATTR4FV(0, v);
+ else if (index < MAX_VERTEX_GENERIC_ATTRIBS)
+ ATTR4FV(VBO_ATTRIB_GENERIC0 + index, v);
+ else
+ ERROR();
+}
+
+
+
+/* Integer-valued generic attributes.
+ * XXX: the integers just get converted to floats at this time
+ */
+static void GLAPIENTRY
+TAG(VertexAttribI1i)(GLuint index, GLint x)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ if (index == 0)
+ ATTR1I(0, x);
+ else if (index < MAX_VERTEX_GENERIC_ATTRIBS)
+ ATTR1I(VBO_ATTRIB_GENERIC0 + index, x);
+ else
+ ERROR();
+}
+
+static void GLAPIENTRY
+TAG(VertexAttribI2i)(GLuint index, GLint x, GLint y)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ if (index == 0)
+ ATTR2I(0, x, y);
+ else if (index < MAX_VERTEX_GENERIC_ATTRIBS)
+ ATTR2I(VBO_ATTRIB_GENERIC0 + index, x, y);
+ else
+ ERROR();
+}
+
+static void GLAPIENTRY
+TAG(VertexAttribI3i)(GLuint index, GLint x, GLint y, GLint z)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ if (index == 0)
+ ATTR3I(0, x, y, z);
+ else if (index < MAX_VERTEX_GENERIC_ATTRIBS)
+ ATTR3I(VBO_ATTRIB_GENERIC0 + index, x, y, z);
+ else
+ ERROR();
+}
+
+static void GLAPIENTRY
+TAG(VertexAttribI4i)(GLuint index, GLint x, GLint y, GLint z, GLint w)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ if (index == 0)
+ ATTR4I(0, x, y, z, w);
+ else if (index < MAX_VERTEX_GENERIC_ATTRIBS)
+ ATTR4I(VBO_ATTRIB_GENERIC0 + index, x, y, z, w);
+ else
+ ERROR();
+}
+
+static void GLAPIENTRY
+TAG(VertexAttribI2iv)(GLuint index, const GLint *v)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ if (index == 0)
+ ATTR2IV(0, v);
+ else if (index < MAX_VERTEX_GENERIC_ATTRIBS)
+ ATTR2IV(VBO_ATTRIB_GENERIC0 + index, v);
+ else
+ ERROR();
+}
+
+static void GLAPIENTRY
+TAG(VertexAttribI3iv)(GLuint index, const GLint *v)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ if (index == 0)
+ ATTR3IV(0, v);
+ else if (index < MAX_VERTEX_GENERIC_ATTRIBS)
+ ATTR3IV(VBO_ATTRIB_GENERIC0 + index, v);
+ else
+ ERROR();
+}
+
+static void GLAPIENTRY
+TAG(VertexAttribI4iv)(GLuint index, const GLint *v)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ if (index == 0)
+ ATTR4IV(0, v);
+ else if (index < MAX_VERTEX_GENERIC_ATTRIBS)
+ ATTR4IV(VBO_ATTRIB_GENERIC0 + index, v);
+ else
+ ERROR();
+}
+
+
+
+/* Unsigned integer-valued generic attributes.
+ * XXX: the integers just get converted to floats at this time
+ */
+static void GLAPIENTRY
+TAG(VertexAttribI1ui)(GLuint index, GLuint x)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ if (index == 0)
+ ATTR1UI(0, x);
+ else if (index < MAX_VERTEX_GENERIC_ATTRIBS)
+ ATTR1UI(VBO_ATTRIB_GENERIC0 + index, x);
+ else
+ ERROR();
+}
+
+static void GLAPIENTRY
+TAG(VertexAttribI2ui)(GLuint index, GLuint x, GLuint y)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ if (index == 0)
+ ATTR2UI(0, x, y);
+ else if (index < MAX_VERTEX_GENERIC_ATTRIBS)
+ ATTR2UI(VBO_ATTRIB_GENERIC0 + index, x, y);
+ else
+ ERROR();
+}
+
+static void GLAPIENTRY
+TAG(VertexAttribI3ui)(GLuint index, GLuint x, GLuint y, GLuint z)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ if (index == 0)
+ ATTR3UI(0, x, y, z);
+ else if (index < MAX_VERTEX_GENERIC_ATTRIBS)
+ ATTR3UI(VBO_ATTRIB_GENERIC0 + index, x, y, z);
+ else
+ ERROR();
+}
+
+static void GLAPIENTRY
+TAG(VertexAttribI4ui)(GLuint index, GLuint x, GLuint y, GLuint z, GLuint w)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ if (index == 0)
+ ATTR4UI(0, x, y, z, w);
+ else if (index < MAX_VERTEX_GENERIC_ATTRIBS)
+ ATTR4UI(VBO_ATTRIB_GENERIC0 + index, x, y, z, w);
+ else
+ ERROR();
+}
+
+static void GLAPIENTRY
+TAG(VertexAttribI2uiv)(GLuint index, const GLuint *v)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ if (index == 0)
+ ATTR2UIV(0, v);
+ else if (index < MAX_VERTEX_GENERIC_ATTRIBS)
+ ATTR2UIV(VBO_ATTRIB_GENERIC0 + index, v);
+ else
+ ERROR();
+}
+
+static void GLAPIENTRY
+TAG(VertexAttribI3uiv)(GLuint index, const GLuint *v)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ if (index == 0)
+ ATTR3UIV(0, v);
+ else if (index < MAX_VERTEX_GENERIC_ATTRIBS)
+ ATTR3UIV(VBO_ATTRIB_GENERIC0 + index, v);
+ else
+ ERROR();
+}
+
+static void GLAPIENTRY
+TAG(VertexAttribI4uiv)(GLuint index, const GLuint *v)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ if (index == 0)
+ ATTR4UIV(0, v);
+ else if (index < MAX_VERTEX_GENERIC_ATTRIBS)
+ ATTR4UIV(VBO_ATTRIB_GENERIC0 + index, v);
+ else
+ ERROR();
+}
+
+
+
+/* In addition to supporting NV_vertex_program, these entrypoints are
+ * used by the display list and other code specifically because of
+ * their property of aliasing with other attributes. (See
+ * vbo_save_loopback.c)
+ */
+static void GLAPIENTRY
+TAG(VertexAttrib1fNV)(GLuint index, GLfloat x)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ if (index < VBO_ATTRIB_MAX)
+ ATTR1F(index, x);
+}
+
+static void GLAPIENTRY
+TAG(VertexAttrib1fvNV)(GLuint index, const GLfloat * v)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ if (index < VBO_ATTRIB_MAX)
+ ATTR1FV(index, v);
+}
+
+static void GLAPIENTRY
+TAG(VertexAttrib2fNV)(GLuint index, GLfloat x, GLfloat y)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ if (index < VBO_ATTRIB_MAX)
+ ATTR2F(index, x, y);
+}
+
+static void GLAPIENTRY
+TAG(VertexAttrib2fvNV)(GLuint index, const GLfloat * v)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ if (index < VBO_ATTRIB_MAX)
+ ATTR2FV(index, v);
+}
+
+static void GLAPIENTRY
+TAG(VertexAttrib3fNV)(GLuint index, GLfloat x, GLfloat y, GLfloat z)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ if (index < VBO_ATTRIB_MAX)
+ ATTR3F(index, x, y, z);
+}
+
+static void GLAPIENTRY
+TAG(VertexAttrib3fvNV)(GLuint index,
+ const GLfloat * v)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ if (index < VBO_ATTRIB_MAX)
+ ATTR3FV(index, v);
+}
+
+static void GLAPIENTRY
+TAG(VertexAttrib4fNV)(GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ if (index < VBO_ATTRIB_MAX)
+ ATTR4F(index, x, y, z, w);
+}
+
+static void GLAPIENTRY
+TAG(VertexAttrib4fvNV)(GLuint index, const GLfloat * v)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ if (index < VBO_ATTRIB_MAX)
+ ATTR4FV(index, v);
+}
+
+
+
+#define MAT( ATTR, N, face, params ) \
+do { \
+ if (face != GL_BACK) \
+ MAT_ATTR( ATTR, N, params ); /* front */ \
+ if (face != GL_FRONT) \
+ MAT_ATTR( ATTR + 1, N, params ); /* back */ \
+} while (0)
+
+
+/* Colormaterial conflicts are dealt with later.
+ */
+static void GLAPIENTRY
+TAG(Materialfv)(GLenum face, GLenum pname,
+ const GLfloat * params)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ switch (pname) {
+ case GL_EMISSION:
+ MAT(VBO_ATTRIB_MAT_FRONT_EMISSION, 4, face, params);
+ break;
+ case GL_AMBIENT:
+ MAT(VBO_ATTRIB_MAT_FRONT_AMBIENT, 4, face, params);
+ break;
+ case GL_DIFFUSE:
+ MAT(VBO_ATTRIB_MAT_FRONT_DIFFUSE, 4, face, params);
+ break;
+ case GL_SPECULAR:
+ MAT(VBO_ATTRIB_MAT_FRONT_SPECULAR, 4, face, params);
+ break;
+ case GL_SHININESS:
+ MAT(VBO_ATTRIB_MAT_FRONT_SHININESS, 1, face, params);
+ break;
+ case GL_COLOR_INDEXES:
+ MAT(VBO_ATTRIB_MAT_FRONT_INDEXES, 3, face, params);
+ break;
+ case GL_AMBIENT_AND_DIFFUSE:
+ MAT(VBO_ATTRIB_MAT_FRONT_AMBIENT, 4, face, params);
+ MAT(VBO_ATTRIB_MAT_FRONT_DIFFUSE, 4, face, params);
+ break;
+ default:
+ ERROR();
+ return;
+ }
+}
+
+
+#undef ATTR1FV
+#undef ATTR2FV
+#undef ATTR3FV
+#undef ATTR4FV
+
+#undef ATTR1F
+#undef ATTR2F
+#undef ATTR3F
+#undef ATTR4F
+
+#undef MAT
+#undef MAT_ATTR
diff --git a/mesalib/src/mesa/vbo/vbo_context.c b/mesalib/src/mesa/vbo/vbo_context.c
index 580850574..67a6091ba 100644
--- a/mesalib/src/mesa/vbo/vbo_context.c
+++ b/mesalib/src/mesa/vbo/vbo_context.c
@@ -1,247 +1,247 @@
-/*
- * Mesa 3-D graphics library
- * Version: 6.3
- *
- * Copyright (C) 1999-2005 Brian Paul All Rights Reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included
- * in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
- * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- *
- * Authors:
- * Keith Whitwell <keith@tungstengraphics.com>
- */
-
-#include "main/imports.h"
-#include "main/mtypes.h"
-#include "main/api_arrayelt.h"
-#include "main/bufferobj.h"
-#include "math/m_eval.h"
-#include "vbo.h"
-#include "vbo_context.h"
-
-
-
-#define NR_LEGACY_ATTRIBS 16
-#define NR_GENERIC_ATTRIBS 16
-#define NR_MAT_ATTRIBS 12
-
-
-static GLuint check_size( const GLfloat *attr )
-{
- if (attr[3] != 1.0) return 4;
- if (attr[2] != 0.0) return 3;
- if (attr[1] != 0.0) return 2;
- return 1;
-}
-
-
-static void init_legacy_currval(GLcontext *ctx)
-{
- struct vbo_context *vbo = vbo_context(ctx);
- struct gl_client_array *arrays = vbo->legacy_currval;
- GLuint i;
-
- memset(arrays, 0, sizeof(*arrays) * NR_LEGACY_ATTRIBS);
-
- /* Set up a constant (StrideB == 0) array for each current
- * attribute:
- */
- for (i = 0; i < NR_LEGACY_ATTRIBS; i++) {
- struct gl_client_array *cl = &arrays[i];
-
- /* Size will have to be determined at runtime:
- */
- cl->Size = check_size(ctx->Current.Attrib[i]);
- cl->Stride = 0;
- cl->StrideB = 0;
- cl->Enabled = 1;
- cl->Type = GL_FLOAT;
- cl->Format = GL_RGBA;
- cl->Ptr = (const void *)ctx->Current.Attrib[i];
- _mesa_reference_buffer_object(ctx, &cl->BufferObj,
- ctx->Shared->NullBufferObj);
- }
-}
-
-
-static void init_generic_currval(GLcontext *ctx)
-{
- struct vbo_context *vbo = vbo_context(ctx);
- struct gl_client_array *arrays = vbo->generic_currval;
- GLuint i;
-
- memset(arrays, 0, sizeof(*arrays) * NR_GENERIC_ATTRIBS);
-
- for (i = 0; i < NR_GENERIC_ATTRIBS; i++) {
- struct gl_client_array *cl = &arrays[i];
-
- /* This will have to be determined at runtime:
- */
- cl->Size = 1;
- cl->Type = GL_FLOAT;
- cl->Format = GL_RGBA;
- cl->Ptr = (const void *)ctx->Current.Attrib[VERT_ATTRIB_GENERIC0 + i];
- cl->Stride = 0;
- cl->StrideB = 0;
- cl->Enabled = 1;
- _mesa_reference_buffer_object(ctx, &cl->BufferObj,
- ctx->Shared->NullBufferObj);
- }
-}
-
-
-static void init_mat_currval(GLcontext *ctx)
-{
- struct vbo_context *vbo = vbo_context(ctx);
- struct gl_client_array *arrays = vbo->mat_currval;
- GLuint i;
-
- ASSERT(NR_MAT_ATTRIBS == MAT_ATTRIB_MAX);
-
- memset(arrays, 0, sizeof(*arrays) * NR_MAT_ATTRIBS);
-
- /* Set up a constant (StrideB == 0) array for each current
- * attribute:
- */
- 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
- * be determined at runtime:
- */
- switch (i - VERT_ATTRIB_GENERIC0) {
- case MAT_ATTRIB_FRONT_SHININESS:
- case MAT_ATTRIB_BACK_SHININESS:
- cl->Size = 1;
- break;
- case MAT_ATTRIB_FRONT_INDEXES:
- case MAT_ATTRIB_BACK_INDEXES:
- cl->Size = 3;
- break;
- default:
- cl->Size = 4;
- break;
- }
-
- cl->Ptr = (const void *)ctx->Light.Material.Attrib[i];
- cl->Type = GL_FLOAT;
- cl->Format = GL_RGBA;
- cl->Stride = 0;
- cl->StrideB = 0;
- cl->Enabled = 1;
- _mesa_reference_buffer_object(ctx, &cl->BufferObj,
- ctx->Shared->NullBufferObj);
- }
-}
-
-
-GLboolean _vbo_CreateContext( GLcontext *ctx )
-{
- struct vbo_context *vbo = CALLOC_STRUCT(vbo_context);
-
- ctx->swtnl_im = (void *)vbo;
-
- /* Initialize the arrayelt helper
- */
- if (!ctx->aelt_context &&
- !_ae_create_context( ctx )) {
- return GL_FALSE;
- }
-
- /* TODO: remove these pointers.
- */
- 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 );
- init_mat_currval( ctx );
-
- /* Build mappings from VERT_ATTRIB -> VBO_ATTRIB depending on type
- * of vertex program active.
- */
- {
- GLuint i;
-
- /* When no vertex program, pull in the material attributes in
- * the 16..32 generic range.
- */
- for (i = 0; i < 16; i++)
- vbo->map_vp_none[i] = i;
- for (i = 0; i < 12; i++)
- vbo->map_vp_none[16+i] = VBO_ATTRIB_MAT_FRONT_AMBIENT + i;
- for (i = 0; i < 4; i++)
- vbo->map_vp_none[28+i] = i;
-
- for (i = 0; i < Elements(vbo->map_vp_arb); i++)
- vbo->map_vp_arb[i] = i;
- }
-
-
- /* 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 );
- if (ctx->API == API_OPENGL)
- vbo_save_init( ctx );
-
- _math_init_eval();
-
- return GL_TRUE;
-}
-
-
-void _vbo_InvalidateState( GLcontext *ctx, GLuint new_state )
-{
- _ae_invalidate_state(ctx, new_state);
- vbo_exec_invalidate_state(ctx, new_state);
-}
-
-
-void _vbo_DestroyContext( GLcontext *ctx )
-{
- struct vbo_context *vbo = vbo_context(ctx);
-
- if (ctx->aelt_context) {
- _ae_destroy_context( ctx );
- ctx->aelt_context = NULL;
- }
-
- if (vbo) {
- GLuint i;
-
- for (i = 0; i < VBO_ATTRIB_MAX; i++) {
- _mesa_reference_buffer_object(ctx, &vbo->currval[i].BufferObj, NULL);
- }
-
- vbo_exec_destroy(ctx);
- if (ctx->API == API_OPENGL)
- vbo_save_destroy(ctx);
- FREE(vbo);
- ctx->swtnl_im = NULL;
- }
-}
-
-
-void vbo_set_draw_func(GLcontext *ctx, vbo_draw_func func)
-{
- struct vbo_context *vbo = vbo_context(ctx);
- vbo->draw_prims = func;
-}
-
+/*
+ * Mesa 3-D graphics library
+ * Version: 6.3
+ *
+ * Copyright (C) 1999-2005 Brian Paul All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+ * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors:
+ * Keith Whitwell <keith@tungstengraphics.com>
+ */
+
+#include "main/imports.h"
+#include "main/mtypes.h"
+#include "main/api_arrayelt.h"
+#include "main/bufferobj.h"
+#include "math/m_eval.h"
+#include "vbo.h"
+#include "vbo_context.h"
+
+
+
+#define NR_LEGACY_ATTRIBS 16
+#define NR_GENERIC_ATTRIBS 16
+#define NR_MAT_ATTRIBS 12
+
+
+static GLuint check_size( const GLfloat *attr )
+{
+ if (attr[3] != 1.0) return 4;
+ if (attr[2] != 0.0) return 3;
+ if (attr[1] != 0.0) return 2;
+ return 1;
+}
+
+
+static void init_legacy_currval(struct gl_context *ctx)
+{
+ struct vbo_context *vbo = vbo_context(ctx);
+ struct gl_client_array *arrays = vbo->legacy_currval;
+ GLuint i;
+
+ memset(arrays, 0, sizeof(*arrays) * NR_LEGACY_ATTRIBS);
+
+ /* Set up a constant (StrideB == 0) array for each current
+ * attribute:
+ */
+ for (i = 0; i < NR_LEGACY_ATTRIBS; i++) {
+ struct gl_client_array *cl = &arrays[i];
+
+ /* Size will have to be determined at runtime:
+ */
+ cl->Size = check_size(ctx->Current.Attrib[i]);
+ cl->Stride = 0;
+ cl->StrideB = 0;
+ cl->Enabled = 1;
+ cl->Type = GL_FLOAT;
+ cl->Format = GL_RGBA;
+ cl->Ptr = (const void *)ctx->Current.Attrib[i];
+ _mesa_reference_buffer_object(ctx, &cl->BufferObj,
+ ctx->Shared->NullBufferObj);
+ }
+}
+
+
+static void init_generic_currval(struct gl_context *ctx)
+{
+ struct vbo_context *vbo = vbo_context(ctx);
+ struct gl_client_array *arrays = vbo->generic_currval;
+ GLuint i;
+
+ memset(arrays, 0, sizeof(*arrays) * NR_GENERIC_ATTRIBS);
+
+ for (i = 0; i < NR_GENERIC_ATTRIBS; i++) {
+ struct gl_client_array *cl = &arrays[i];
+
+ /* This will have to be determined at runtime:
+ */
+ cl->Size = 1;
+ cl->Type = GL_FLOAT;
+ cl->Format = GL_RGBA;
+ cl->Ptr = (const void *)ctx->Current.Attrib[VERT_ATTRIB_GENERIC0 + i];
+ cl->Stride = 0;
+ cl->StrideB = 0;
+ cl->Enabled = 1;
+ _mesa_reference_buffer_object(ctx, &cl->BufferObj,
+ ctx->Shared->NullBufferObj);
+ }
+}
+
+
+static void init_mat_currval(struct gl_context *ctx)
+{
+ struct vbo_context *vbo = vbo_context(ctx);
+ struct gl_client_array *arrays = vbo->mat_currval;
+ GLuint i;
+
+ ASSERT(NR_MAT_ATTRIBS == MAT_ATTRIB_MAX);
+
+ memset(arrays, 0, sizeof(*arrays) * NR_MAT_ATTRIBS);
+
+ /* Set up a constant (StrideB == 0) array for each current
+ * attribute:
+ */
+ 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
+ * be determined at runtime:
+ */
+ switch (i - VERT_ATTRIB_GENERIC0) {
+ case MAT_ATTRIB_FRONT_SHININESS:
+ case MAT_ATTRIB_BACK_SHININESS:
+ cl->Size = 1;
+ break;
+ case MAT_ATTRIB_FRONT_INDEXES:
+ case MAT_ATTRIB_BACK_INDEXES:
+ cl->Size = 3;
+ break;
+ default:
+ cl->Size = 4;
+ break;
+ }
+
+ cl->Ptr = (const void *)ctx->Light.Material.Attrib[i];
+ cl->Type = GL_FLOAT;
+ cl->Format = GL_RGBA;
+ cl->Stride = 0;
+ cl->StrideB = 0;
+ cl->Enabled = 1;
+ _mesa_reference_buffer_object(ctx, &cl->BufferObj,
+ ctx->Shared->NullBufferObj);
+ }
+}
+
+
+GLboolean _vbo_CreateContext( struct gl_context *ctx )
+{
+ struct vbo_context *vbo = CALLOC_STRUCT(vbo_context);
+
+ ctx->swtnl_im = (void *)vbo;
+
+ /* Initialize the arrayelt helper
+ */
+ if (!ctx->aelt_context &&
+ !_ae_create_context( ctx )) {
+ return GL_FALSE;
+ }
+
+ /* TODO: remove these pointers.
+ */
+ 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 );
+ init_mat_currval( ctx );
+
+ /* Build mappings from VERT_ATTRIB -> VBO_ATTRIB depending on type
+ * of vertex program active.
+ */
+ {
+ GLuint i;
+
+ /* When no vertex program, pull in the material attributes in
+ * the 16..32 generic range.
+ */
+ for (i = 0; i < 16; i++)
+ vbo->map_vp_none[i] = i;
+ for (i = 0; i < 12; i++)
+ vbo->map_vp_none[16+i] = VBO_ATTRIB_MAT_FRONT_AMBIENT + i;
+ for (i = 0; i < 4; i++)
+ vbo->map_vp_none[28+i] = i;
+
+ for (i = 0; i < Elements(vbo->map_vp_arb); i++)
+ vbo->map_vp_arb[i] = i;
+ }
+
+
+ /* 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 );
+ if (ctx->API == API_OPENGL)
+ vbo_save_init( ctx );
+
+ _math_init_eval();
+
+ return GL_TRUE;
+}
+
+
+void _vbo_InvalidateState( struct gl_context *ctx, GLuint new_state )
+{
+ _ae_invalidate_state(ctx, new_state);
+ vbo_exec_invalidate_state(ctx, new_state);
+}
+
+
+void _vbo_DestroyContext( struct gl_context *ctx )
+{
+ struct vbo_context *vbo = vbo_context(ctx);
+
+ if (ctx->aelt_context) {
+ _ae_destroy_context( ctx );
+ ctx->aelt_context = NULL;
+ }
+
+ if (vbo) {
+ GLuint i;
+
+ for (i = 0; i < VBO_ATTRIB_MAX; i++) {
+ _mesa_reference_buffer_object(ctx, &vbo->currval[i].BufferObj, NULL);
+ }
+
+ vbo_exec_destroy(ctx);
+ if (ctx->API == API_OPENGL)
+ vbo_save_destroy(ctx);
+ FREE(vbo);
+ ctx->swtnl_im = NULL;
+ }
+}
+
+
+void vbo_set_draw_func(struct gl_context *ctx, vbo_draw_func func)
+{
+ struct vbo_context *vbo = vbo_context(ctx);
+ vbo->draw_prims = func;
+}
+
diff --git a/mesalib/src/mesa/vbo/vbo_context.h b/mesalib/src/mesa/vbo/vbo_context.h
index 00cfc522a..91953958b 100644
--- a/mesalib/src/mesa/vbo/vbo_context.h
+++ b/mesalib/src/mesa/vbo/vbo_context.h
@@ -1,112 +1,112 @@
-/*
- * mesa 3-D graphics library
- * Version: 6.5
- *
- * Copyright (C) 1999-2006 Brian Paul All Rights Reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included
- * in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
- * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- */
-
-/**
- * \file vbo_context.h
- * \brief VBO builder module datatypes and definitions.
- * \author Keith Whitwell
- */
-
-
-/**
- * \mainpage The VBO builder module
- *
- * This module hooks into the GL dispatch table and catches all vertex
- * building and drawing commands, such as glVertex3f, glBegin and
- * glDrawArrays. The module stores all incoming vertex data as arrays
- * in GL vertex buffer objects (VBOs), and translates all drawing
- * commands into calls to a driver supplied DrawPrimitives() callback.
- *
- * The module captures both immediate mode and display list drawing,
- * and manages the allocation, reference counting and deallocation of
- * vertex buffer objects itself.
- *
- * The DrawPrimitives() callback can be either implemented by the
- * driver itself or hooked to the tnl module's _tnl_draw_primitives()
- * function for hardware without tnl capablilties or during fallbacks.
- */
-
-
-#ifndef _VBO_CONTEXT_H
-#define _VBO_CONTEXT_H
-
-#include "vbo.h"
-#include "vbo_attrib.h"
-#include "vbo_exec.h"
-#include "vbo_save.h"
-
-
-struct vbo_context {
- 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[VERT_ATTRIB_MAX];
- GLuint map_vp_arb[VERT_ATTRIB_MAX];
-
- GLfloat *current[VBO_ATTRIB_MAX]; /* points into ctx->Current, ctx->Light.Material */
- GLfloat CurrentFloatEdgeFlag;
-
-
- struct vbo_exec_context exec;
-#if FEATURE_dlist
- struct vbo_save_context save;
-#endif
-
- /* Callback into the driver. This must always succeed, the driver
- * is responsible for initiating any fallback actions required:
- */
- vbo_draw_func draw_prims;
-};
-
-
-static INLINE struct vbo_context *vbo_context(GLcontext *ctx)
-{
- return (struct vbo_context *)(ctx->swtnl_im);
-}
-
-
-/**
- * Return VP_x token to indicate whether we're running fixed-function
- * vertex transformation, an NV vertex program or ARB vertex program/shader.
- */
-static INLINE enum vp_mode
-get_program_mode( GLcontext *ctx )
-{
- if (!ctx->VertexProgram._Current)
- return VP_NONE;
- else if (ctx->VertexProgram._Current == ctx->VertexProgram._TnlProgram)
- return VP_NONE;
- else if (ctx->VertexProgram._Current->IsNVProgram)
- return VP_NV;
- else
- return VP_ARB;
-}
-
-
-#endif
+/*
+ * mesa 3-D graphics library
+ * Version: 6.5
+ *
+ * Copyright (C) 1999-2006 Brian Paul All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+ * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/**
+ * \file vbo_context.h
+ * \brief VBO builder module datatypes and definitions.
+ * \author Keith Whitwell
+ */
+
+
+/**
+ * \mainpage The VBO builder module
+ *
+ * This module hooks into the GL dispatch table and catches all vertex
+ * building and drawing commands, such as glVertex3f, glBegin and
+ * glDrawArrays. The module stores all incoming vertex data as arrays
+ * in GL vertex buffer objects (VBOs), and translates all drawing
+ * commands into calls to a driver supplied DrawPrimitives() callback.
+ *
+ * The module captures both immediate mode and display list drawing,
+ * and manages the allocation, reference counting and deallocation of
+ * vertex buffer objects itself.
+ *
+ * The DrawPrimitives() callback can be either implemented by the
+ * driver itself or hooked to the tnl module's _tnl_draw_primitives()
+ * function for hardware without tnl capablilties or during fallbacks.
+ */
+
+
+#ifndef _VBO_CONTEXT_H
+#define _VBO_CONTEXT_H
+
+#include "vbo.h"
+#include "vbo_attrib.h"
+#include "vbo_exec.h"
+#include "vbo_save.h"
+
+
+struct vbo_context {
+ 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[VERT_ATTRIB_MAX];
+ GLuint map_vp_arb[VERT_ATTRIB_MAX];
+
+ GLfloat *current[VBO_ATTRIB_MAX]; /* points into ctx->Current, ctx->Light.Material */
+ GLfloat CurrentFloatEdgeFlag;
+
+
+ struct vbo_exec_context exec;
+#if FEATURE_dlist
+ struct vbo_save_context save;
+#endif
+
+ /* Callback into the driver. This must always succeed, the driver
+ * is responsible for initiating any fallback actions required:
+ */
+ vbo_draw_func draw_prims;
+};
+
+
+static INLINE struct vbo_context *vbo_context(struct gl_context *ctx)
+{
+ return (struct vbo_context *)(ctx->swtnl_im);
+}
+
+
+/**
+ * Return VP_x token to indicate whether we're running fixed-function
+ * vertex transformation, an NV vertex program or ARB vertex program/shader.
+ */
+static INLINE enum vp_mode
+get_program_mode( struct gl_context *ctx )
+{
+ if (!ctx->VertexProgram._Current)
+ return VP_NONE;
+ else if (ctx->VertexProgram._Current == ctx->VertexProgram._TnlProgram)
+ return VP_NONE;
+ else if (ctx->VertexProgram._Current->IsNVProgram)
+ return VP_NV;
+ else
+ return VP_ARB;
+}
+
+
+#endif
diff --git a/mesalib/src/mesa/vbo/vbo_exec.c b/mesalib/src/mesa/vbo/vbo_exec.c
index 046fa8105..7793aa238 100644
--- a/mesalib/src/mesa/vbo/vbo_exec.c
+++ b/mesalib/src/mesa/vbo/vbo_exec.c
@@ -1,92 +1,92 @@
-/*
- * Mesa 3-D graphics library
- * Version: 6.3
- *
- * Copyright (C) 1999-2005 Brian Paul All Rights Reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included
- * in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
- * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- *
- * Authors:
- * Keith Whitwell <keith@tungstengraphics.com>
- */
-
-
-#include "main/api_arrayelt.h"
-#include "main/glheader.h"
-#include "main/mtypes.h"
-#include "main/vtxfmt.h"
-#include "vbo_context.h"
-
-
-
-void vbo_exec_init( GLcontext *ctx )
-{
- struct vbo_exec_context *exec = &vbo_context(ctx)->exec;
-
- exec->ctx = ctx;
-
- /* Initialize the arrayelt helper
- */
- if (!ctx->aelt_context &&
- !_ae_create_context( ctx ))
- return;
-
- vbo_exec_vtx_init( exec );
- vbo_exec_array_init( exec );
-
- /* Hook our functions into exec and compile dispatch tables.
- */
- _mesa_install_exec_vtxfmt( ctx, &exec->vtxfmt );
-
- ctx->Driver.NeedFlush = 0;
- ctx->Driver.CurrentExecPrimitive = PRIM_OUTSIDE_BEGIN_END;
- ctx->Driver.BeginVertices = vbo_exec_BeginVertices;
- ctx->Driver.FlushVertices = vbo_exec_FlushVertices;
-
- vbo_exec_invalidate_state( ctx, ~0 );
-}
-
-
-void vbo_exec_destroy( GLcontext *ctx )
-{
- struct vbo_exec_context *exec = &vbo_context(ctx)->exec;
-
- if (ctx->aelt_context) {
- _ae_destroy_context( ctx );
- ctx->aelt_context = NULL;
- }
-
- vbo_exec_vtx_destroy( exec );
- vbo_exec_array_destroy( exec );
-}
-
-
-/**
- * Really want to install these callbacks to a central facility to be
- * invoked according to the state flags. That will have to wait for a
- * mesa rework:
- */
-void vbo_exec_invalidate_state( GLcontext *ctx, GLuint new_state )
-{
- struct vbo_exec_context *exec = &vbo_context(ctx)->exec;
-
- if (new_state & (_NEW_PROGRAM|_NEW_EVAL))
- exec->eval.recalculate_maps = 1;
-
- _ae_invalidate_state(ctx, new_state);
-}
+/*
+ * Mesa 3-D graphics library
+ * Version: 6.3
+ *
+ * Copyright (C) 1999-2005 Brian Paul All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+ * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors:
+ * Keith Whitwell <keith@tungstengraphics.com>
+ */
+
+
+#include "main/api_arrayelt.h"
+#include "main/glheader.h"
+#include "main/mtypes.h"
+#include "main/vtxfmt.h"
+#include "vbo_context.h"
+
+
+
+void vbo_exec_init( struct gl_context *ctx )
+{
+ struct vbo_exec_context *exec = &vbo_context(ctx)->exec;
+
+ exec->ctx = ctx;
+
+ /* Initialize the arrayelt helper
+ */
+ if (!ctx->aelt_context &&
+ !_ae_create_context( ctx ))
+ return;
+
+ vbo_exec_vtx_init( exec );
+ vbo_exec_array_init( exec );
+
+ /* Hook our functions into exec and compile dispatch tables.
+ */
+ _mesa_install_exec_vtxfmt( ctx, &exec->vtxfmt );
+
+ ctx->Driver.NeedFlush = 0;
+ ctx->Driver.CurrentExecPrimitive = PRIM_OUTSIDE_BEGIN_END;
+ ctx->Driver.BeginVertices = vbo_exec_BeginVertices;
+ ctx->Driver.FlushVertices = vbo_exec_FlushVertices;
+
+ vbo_exec_invalidate_state( ctx, ~0 );
+}
+
+
+void vbo_exec_destroy( struct gl_context *ctx )
+{
+ struct vbo_exec_context *exec = &vbo_context(ctx)->exec;
+
+ if (ctx->aelt_context) {
+ _ae_destroy_context( ctx );
+ ctx->aelt_context = NULL;
+ }
+
+ vbo_exec_vtx_destroy( exec );
+ vbo_exec_array_destroy( exec );
+}
+
+
+/**
+ * Really want to install these callbacks to a central facility to be
+ * invoked according to the state flags. That will have to wait for a
+ * mesa rework:
+ */
+void vbo_exec_invalidate_state( struct gl_context *ctx, GLuint new_state )
+{
+ struct vbo_exec_context *exec = &vbo_context(ctx)->exec;
+
+ if (new_state & (_NEW_PROGRAM|_NEW_EVAL))
+ exec->eval.recalculate_maps = 1;
+
+ _ae_invalidate_state(ctx, new_state);
+}
diff --git a/mesalib/src/mesa/vbo/vbo_exec.h b/mesalib/src/mesa/vbo/vbo_exec.h
index 33494f0ce..be3028941 100644
--- a/mesalib/src/mesa/vbo/vbo_exec.h
+++ b/mesalib/src/mesa/vbo/vbo_exec.h
@@ -1,198 +1,198 @@
-/**************************************************************************
-
-Copyright 2002 Tungsten Graphics Inc., Cedar Park, Texas.
-
-All Rights Reserved.
-
-Permission is hereby granted, free of charge, to any person obtaining a
-copy of this software and associated documentation files (the "Software"),
-to deal in the Software without restriction, including without limitation
-on the rights to use, copy, modify, merge, publish, distribute, sub
-license, and/or sell copies of the Software, and to permit persons to whom
-the Software is furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice (including the next
-paragraph) shall be included in all copies or substantial portions of the
-Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
-TUNGSTEN GRAPHICS AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
-DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
-OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
-USE OR OTHER DEALINGS IN THE SOFTWARE.
-
-**************************************************************************/
-
-/*
- * Authors:
- * Keith Whitwell <keith@tungstengraphics.com>
- *
- */
-
-#ifndef __VBO_EXEC_H__
-#define __VBO_EXEC_H__
-
-#include "main/mtypes.h"
-#include "vbo.h"
-#include "vbo_attrib.h"
-
-
-#define VBO_MAX_PRIM 64
-
-/* Wierd implementation stuff:
- */
-#define VBO_VERT_BUFFER_SIZE (1024*64) /* bytes */
-#define VBO_MAX_ATTR_CODEGEN 16
-#define ERROR_ATTRIB 16
-
-
-/** Current vertex program mode */
-enum vp_mode {
- VP_NONE, /**< fixed function */
- VP_NV, /**< NV vertex program */
- VP_ARB /**< ARB vertex program or GLSL vertex shader */
-};
-
-
-struct vbo_exec_eval1_map {
- struct gl_1d_map *map;
- GLuint sz;
-};
-
-struct vbo_exec_eval2_map {
- struct gl_2d_map *map;
- GLuint sz;
-};
-
-
-
-struct vbo_exec_copied_vtx {
- GLfloat buffer[VBO_ATTRIB_MAX * 4 * VBO_MAX_COPIED_VERTS];
- GLuint nr;
-};
-
-
-typedef void (*vbo_attrfv_func)( const GLfloat * );
-
-
-struct vbo_exec_context
-{
- GLcontext *ctx;
- GLvertexformat vtxfmt;
-
- struct {
- struct gl_buffer_object *bufferobj;
-
- GLuint vertex_size; /* in dwords */
-
- struct _mesa_prim prim[VBO_MAX_PRIM];
- GLuint prim_count;
-
- GLfloat *buffer_map;
- GLfloat *buffer_ptr; /* cursor, points into buffer */
- GLuint buffer_used; /* in bytes */
- GLfloat vertex[VBO_ATTRIB_MAX*4]; /* current vertex */
-
- GLuint vert_count;
- GLuint max_vert;
- struct vbo_exec_copied_vtx copied;
-
- GLubyte attrsz[VBO_ATTRIB_MAX];
- GLubyte active_sz[VBO_ATTRIB_MAX];
-
- GLfloat *attrptr[VBO_ATTRIB_MAX];
- struct gl_client_array arrays[VERT_ATTRIB_MAX];
-
- /* According to program mode, the values above plus current
- * values are squashed down to the 32 attributes passed to the
- * vertex program below:
- */
- enum vp_mode program_mode;
- GLuint enabled_flags;
- const struct gl_client_array *inputs[VERT_ATTRIB_MAX];
- } vtx;
-
-
- struct {
- GLboolean recalculate_maps;
- struct vbo_exec_eval1_map map1[VERT_ATTRIB_MAX];
- struct vbo_exec_eval2_map map2[VERT_ATTRIB_MAX];
- } eval;
-
- struct {
- enum vp_mode program_mode;
- GLuint enabled_flags;
- GLuint array_obj;
-
- /* These just mirror the current arrayobj (todo: make arrayobj
- * look like this and remove the mirror):
- */
- const struct gl_client_array *legacy_array[16];
- const struct gl_client_array *generic_array[16];
-
- /* Arrays and current values manipulated according to program
- * mode, etc. These are the attributes as seen by vertex
- * programs:
- */
- const struct gl_client_array *inputs[VERT_ATTRIB_MAX];
- } array;
-
-#ifdef DEBUG
- GLint flush_call_depth;
-#endif
-};
-
-
-
-/* External API:
- */
-void vbo_exec_init( GLcontext *ctx );
-void vbo_exec_destroy( GLcontext *ctx );
-void vbo_exec_invalidate_state( GLcontext *ctx, GLuint new_state );
-void vbo_exec_FlushVertices_internal( GLcontext *ctx, GLboolean unmap );
-
-void vbo_exec_BeginVertices( GLcontext *ctx );
-void vbo_exec_FlushVertices( GLcontext *ctx, GLuint flags );
-
-
-/* Internal functions:
- */
-void vbo_exec_array_init( struct vbo_exec_context *exec );
-void vbo_exec_array_destroy( struct vbo_exec_context *exec );
-
-
-void vbo_exec_vtx_init( struct vbo_exec_context *exec );
-void vbo_exec_vtx_destroy( struct vbo_exec_context *exec );
-
-#if FEATURE_beginend
-
-void vbo_exec_vtx_flush( struct vbo_exec_context *exec, GLboolean unmap );
-void vbo_exec_vtx_map( struct vbo_exec_context *exec );
-
-#else /* FEATURE_beginend */
-
-static INLINE void
-vbo_exec_vtx_flush( struct vbo_exec_context *exec, GLboolean unmap )
-{
-}
-
-static INLINE void
-vbo_exec_vtx_map( struct vbo_exec_context *exec )
-{
-}
-
-#endif /* FEATURE_beginend */
-
-void vbo_exec_vtx_wrap( struct vbo_exec_context *exec );
-
-void vbo_exec_eval_update( struct vbo_exec_context *exec );
-
-void vbo_exec_do_EvalCoord2f( struct vbo_exec_context *exec,
- GLfloat u, GLfloat v );
-
-void vbo_exec_do_EvalCoord1f( struct vbo_exec_context *exec,
- GLfloat u);
-
-#endif
+/**************************************************************************
+
+Copyright 2002 Tungsten Graphics Inc., Cedar Park, Texas.
+
+All Rights Reserved.
+
+Permission is hereby granted, free of charge, to any person obtaining a
+copy of this software and associated documentation files (the "Software"),
+to deal in the Software without restriction, including without limitation
+on the rights to use, copy, modify, merge, publish, distribute, sub
+license, and/or sell copies of the Software, and to permit persons to whom
+the Software is furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice (including the next
+paragraph) shall be included in all copies or substantial portions of the
+Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
+TUNGSTEN GRAPHICS AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
+DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+**************************************************************************/
+
+/*
+ * Authors:
+ * Keith Whitwell <keith@tungstengraphics.com>
+ *
+ */
+
+#ifndef __VBO_EXEC_H__
+#define __VBO_EXEC_H__
+
+#include "main/mtypes.h"
+#include "vbo.h"
+#include "vbo_attrib.h"
+
+
+#define VBO_MAX_PRIM 64
+
+/* Wierd implementation stuff:
+ */
+#define VBO_VERT_BUFFER_SIZE (1024*64) /* bytes */
+#define VBO_MAX_ATTR_CODEGEN 16
+#define ERROR_ATTRIB 16
+
+
+/** Current vertex program mode */
+enum vp_mode {
+ VP_NONE, /**< fixed function */
+ VP_NV, /**< NV vertex program */
+ VP_ARB /**< ARB vertex program or GLSL vertex shader */
+};
+
+
+struct vbo_exec_eval1_map {
+ struct gl_1d_map *map;
+ GLuint sz;
+};
+
+struct vbo_exec_eval2_map {
+ struct gl_2d_map *map;
+ GLuint sz;
+};
+
+
+
+struct vbo_exec_copied_vtx {
+ GLfloat buffer[VBO_ATTRIB_MAX * 4 * VBO_MAX_COPIED_VERTS];
+ GLuint nr;
+};
+
+
+typedef void (*vbo_attrfv_func)( const GLfloat * );
+
+
+struct vbo_exec_context
+{
+ struct gl_context *ctx;
+ GLvertexformat vtxfmt;
+
+ struct {
+ struct gl_buffer_object *bufferobj;
+
+ GLuint vertex_size; /* in dwords */
+
+ struct _mesa_prim prim[VBO_MAX_PRIM];
+ GLuint prim_count;
+
+ GLfloat *buffer_map;
+ GLfloat *buffer_ptr; /* cursor, points into buffer */
+ GLuint buffer_used; /* in bytes */
+ GLfloat vertex[VBO_ATTRIB_MAX*4]; /* current vertex */
+
+ GLuint vert_count;
+ GLuint max_vert;
+ struct vbo_exec_copied_vtx copied;
+
+ GLubyte attrsz[VBO_ATTRIB_MAX];
+ GLubyte active_sz[VBO_ATTRIB_MAX];
+
+ GLfloat *attrptr[VBO_ATTRIB_MAX];
+ struct gl_client_array arrays[VERT_ATTRIB_MAX];
+
+ /* According to program mode, the values above plus current
+ * values are squashed down to the 32 attributes passed to the
+ * vertex program below:
+ */
+ enum vp_mode program_mode;
+ GLuint enabled_flags;
+ const struct gl_client_array *inputs[VERT_ATTRIB_MAX];
+ } vtx;
+
+
+ struct {
+ GLboolean recalculate_maps;
+ struct vbo_exec_eval1_map map1[VERT_ATTRIB_MAX];
+ struct vbo_exec_eval2_map map2[VERT_ATTRIB_MAX];
+ } eval;
+
+ struct {
+ enum vp_mode program_mode;
+ GLuint enabled_flags;
+ GLuint array_obj;
+
+ /* These just mirror the current arrayobj (todo: make arrayobj
+ * look like this and remove the mirror):
+ */
+ const struct gl_client_array *legacy_array[16];
+ const struct gl_client_array *generic_array[16];
+
+ /* Arrays and current values manipulated according to program
+ * mode, etc. These are the attributes as seen by vertex
+ * programs:
+ */
+ const struct gl_client_array *inputs[VERT_ATTRIB_MAX];
+ } array;
+
+#ifdef DEBUG
+ GLint flush_call_depth;
+#endif
+};
+
+
+
+/* External API:
+ */
+void vbo_exec_init( struct gl_context *ctx );
+void vbo_exec_destroy( struct gl_context *ctx );
+void vbo_exec_invalidate_state( struct gl_context *ctx, GLuint new_state );
+void vbo_exec_FlushVertices_internal( struct gl_context *ctx, GLboolean unmap );
+
+void vbo_exec_BeginVertices( struct gl_context *ctx );
+void vbo_exec_FlushVertices( struct gl_context *ctx, GLuint flags );
+
+
+/* Internal functions:
+ */
+void vbo_exec_array_init( struct vbo_exec_context *exec );
+void vbo_exec_array_destroy( struct vbo_exec_context *exec );
+
+
+void vbo_exec_vtx_init( struct vbo_exec_context *exec );
+void vbo_exec_vtx_destroy( struct vbo_exec_context *exec );
+
+#if FEATURE_beginend
+
+void vbo_exec_vtx_flush( struct vbo_exec_context *exec, GLboolean unmap );
+void vbo_exec_vtx_map( struct vbo_exec_context *exec );
+
+#else /* FEATURE_beginend */
+
+static INLINE void
+vbo_exec_vtx_flush( struct vbo_exec_context *exec, GLboolean unmap )
+{
+}
+
+static INLINE void
+vbo_exec_vtx_map( struct vbo_exec_context *exec )
+{
+}
+
+#endif /* FEATURE_beginend */
+
+void vbo_exec_vtx_wrap( struct vbo_exec_context *exec );
+
+void vbo_exec_eval_update( struct vbo_exec_context *exec );
+
+void vbo_exec_do_EvalCoord2f( struct vbo_exec_context *exec,
+ GLfloat u, GLfloat v );
+
+void vbo_exec_do_EvalCoord1f( struct vbo_exec_context *exec,
+ GLfloat u);
+
+#endif
diff --git a/mesalib/src/mesa/vbo/vbo_exec_api.c b/mesalib/src/mesa/vbo/vbo_exec_api.c
index 9df75a840..b6ced258e 100644
--- a/mesalib/src/mesa/vbo/vbo_exec_api.c
+++ b/mesalib/src/mesa/vbo/vbo_exec_api.c
@@ -1,1032 +1,1079 @@
-/**************************************************************************
-
-Copyright 2002-2008 Tungsten Graphics Inc., Cedar Park, Texas.
-
-All Rights Reserved.
-
-Permission is hereby granted, free of charge, to any person obtaining a
-copy of this software and associated documentation files (the "Software"),
-to deal in the Software without restriction, including without limitation
-on the rights to use, copy, modify, merge, publish, distribute, sub
-license, and/or sell copies of the Software, and to permit persons to whom
-the Software is furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice (including the next
-paragraph) shall be included in all copies or substantial portions of the
-Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
-TUNGSTEN GRAPHICS AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
-DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
-OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
-USE OR OTHER DEALINGS IN THE SOFTWARE.
-
-**************************************************************************/
-
-/*
- * Authors:
- * Keith Whitwell <keith@tungstengraphics.com>
- */
-
-#include "main/glheader.h"
-#include "main/bufferobj.h"
-#include "main/context.h"
-#include "main/macros.h"
-#include "main/vtxfmt.h"
-#include "main/dlist.h"
-#include "main/eval.h"
-#include "main/state.h"
-#include "main/light.h"
-#include "main/api_arrayelt.h"
-#include "main/api_noop.h"
-#include "main/dispatch.h"
-
-#include "vbo_context.h"
-
-#ifdef ERROR
-#undef ERROR
-#endif
-
-
-/** ID/name for immediate-mode VBO */
-#define IMM_BUFFER_NAME 0xaabbccdd
-
-
-static void reset_attrfv( struct vbo_exec_context *exec );
-
-
-/**
- * Close off the last primitive, execute the buffer, restart the
- * primitive.
- */
-static void vbo_exec_wrap_buffers( struct vbo_exec_context *exec )
-{
- if (exec->vtx.prim_count == 0) {
- exec->vtx.copied.nr = 0;
- exec->vtx.vert_count = 0;
- exec->vtx.buffer_ptr = exec->vtx.buffer_map;
- }
- else {
- GLuint last_begin = exec->vtx.prim[exec->vtx.prim_count-1].begin;
- GLuint last_count;
-
- if (exec->ctx->Driver.CurrentExecPrimitive != PRIM_OUTSIDE_BEGIN_END) {
- GLint i = exec->vtx.prim_count - 1;
- assert(i >= 0);
- exec->vtx.prim[i].count = (exec->vtx.vert_count -
- exec->vtx.prim[i].start);
- }
-
- last_count = exec->vtx.prim[exec->vtx.prim_count-1].count;
-
- /* Execute the buffer and save copied vertices.
- */
- if (exec->vtx.vert_count)
- vbo_exec_vtx_flush( exec, GL_FALSE );
- else {
- exec->vtx.prim_count = 0;
- exec->vtx.copied.nr = 0;
- }
-
- /* Emit a glBegin to start the new list.
- */
- assert(exec->vtx.prim_count == 0);
-
- if (exec->ctx->Driver.CurrentExecPrimitive != PRIM_OUTSIDE_BEGIN_END) {
- exec->vtx.prim[0].mode = exec->ctx->Driver.CurrentExecPrimitive;
- exec->vtx.prim[0].start = 0;
- exec->vtx.prim[0].count = 0;
- exec->vtx.prim_count++;
-
- if (exec->vtx.copied.nr == last_count)
- exec->vtx.prim[0].begin = last_begin;
- }
- }
-}
-
-
-/**
- * Deal with buffer wrapping where provoked by the vertex buffer
- * filling up, as opposed to upgrade_vertex().
- */
-void vbo_exec_vtx_wrap( struct vbo_exec_context *exec )
-{
- GLfloat *data = exec->vtx.copied.buffer;
- GLuint i;
-
- /* Run pipeline on current vertices, copy wrapped vertices
- * to exec->vtx.copied.
- */
- vbo_exec_wrap_buffers( exec );
-
- /* Copy stored stored vertices to start of new list.
- */
- assert(exec->vtx.max_vert - exec->vtx.vert_count > exec->vtx.copied.nr);
-
- for (i = 0 ; i < exec->vtx.copied.nr ; i++) {
- memcpy( exec->vtx.buffer_ptr, data,
- exec->vtx.vertex_size * sizeof(GLfloat));
- exec->vtx.buffer_ptr += exec->vtx.vertex_size;
- data += exec->vtx.vertex_size;
- exec->vtx.vert_count++;
- }
-
- exec->vtx.copied.nr = 0;
-}
-
-
-/**
- * Copy the active vertex's values to the ctx->Current fields.
- */
-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]) {
- /* Note: the exec->vtx.current[i] pointers point into the
- * ctx->Current.Attrib and ctx->Light.Material.Attrib arrays.
- */
- GLfloat *current = (GLfloat *)vbo->currval[i].Ptr;
- GLfloat tmp[4];
-
- COPY_CLEAN_4V(tmp,
- exec->vtx.attrsz[i],
- exec->vtx.attrptr[i]);
-
- if (memcmp(current, tmp, sizeof(tmp)) != 0)
- {
- memcpy(current, tmp, sizeof(tmp));
-
- /* 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).
- */
- if (i >= VBO_ATTRIB_MAT_FRONT_AMBIENT &&
- i <= VBO_ATTRIB_MAT_BACK_INDEXES)
- ctx->NewState |= _NEW_LIGHT;
-
- ctx->NewState |= _NEW_CURRENT_ATTRIB;
- }
- }
- }
-
- /* Colormaterial -- this kindof sucks.
- */
- if (ctx->Light.ColorMaterialEnabled &&
- exec->vtx.attrsz[VBO_ATTRIB_COLOR0]) {
- _mesa_update_color_material(ctx,
- ctx->Current.Attrib[VBO_ATTRIB_COLOR0]);
- }
-}
-
-
-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;
-
- 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] = 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;
- }
- }
-}
-
-
-/**
- * Flush existing data, set new attrib size, replay copied vertices.
- */
-static void vbo_exec_wrap_upgrade_vertex( struct vbo_exec_context *exec,
- GLuint attr,
- GLuint newsz )
-{
- GLcontext *ctx = exec->ctx;
- struct vbo_context *vbo = vbo_context(ctx);
- GLint lastcount = exec->vtx.vert_count;
- GLfloat *tmp;
- GLuint oldsz;
- GLuint i;
-
- /* Run pipeline on current vertices, copy wrapped vertices
- * to exec->vtx.copied.
- */
- vbo_exec_wrap_buffers( exec );
-
-
- /* Do a COPY_TO_CURRENT to ensure back-copying works for the case
- * when the attribute already exists in the vertex and is having
- * its size increased.
- */
- vbo_exec_copy_to_current( exec );
-
-
- /* Heuristic: Attempt to isolate attributes received outside
- * begin/end so that they don't bloat the vertices.
- */
- if (ctx->Driver.CurrentExecPrimitive == PRIM_OUTSIDE_BEGIN_END &&
- exec->vtx.attrsz[attr] == 0 &&
- lastcount > 8 &&
- exec->vtx.vertex_size) {
- reset_attrfv( exec );
- }
-
- /* Fix up sizes:
- */
- oldsz = exec->vtx.attrsz[attr];
- exec->vtx.attrsz[attr] = newsz;
-
- exec->vtx.vertex_size += newsz - oldsz;
- exec->vtx.max_vert = ((VBO_VERT_BUFFER_SIZE - exec->vtx.buffer_used) /
- (exec->vtx.vertex_size * sizeof(GLfloat)));
- exec->vtx.vert_count = 0;
- exec->vtx.buffer_ptr = exec->vtx.buffer_map;
-
-
- /* Recalculate all the attrptr[] values
- */
- for (i = 0, tmp = exec->vtx.vertex ; i < VBO_ATTRIB_MAX ; i++) {
- if (exec->vtx.attrsz[i]) {
- exec->vtx.attrptr[i] = tmp;
- tmp += exec->vtx.attrsz[i];
- }
- else
- exec->vtx.attrptr[i] = NULL; /* will not be dereferenced */
- }
-
- /* Copy from current to repopulate the vertex with correct values.
- */
- vbo_exec_copy_from_current( exec );
-
- /* Replay stored vertices to translate them
- * to new format here.
- *
- * -- No need to replay - just copy piecewise
- */
- if (exec->vtx.copied.nr)
- {
- GLfloat *data = exec->vtx.copied.buffer;
- GLfloat *dest = exec->vtx.buffer_ptr;
- GLuint j;
-
- assert(exec->vtx.buffer_ptr == exec->vtx.buffer_map);
-
- for (i = 0 ; i < exec->vtx.copied.nr ; i++) {
- for (j = 0 ; j < VBO_ATTRIB_MAX ; j++) {
- if (exec->vtx.attrsz[j]) {
- if (j == attr) {
- if (oldsz) {
- COPY_CLEAN_4V( dest, oldsz, data );
- data += oldsz;
- dest += newsz;
- } else {
- const GLfloat *current = (const GLfloat *)vbo->currval[j].Ptr;
- COPY_SZ_4V( dest, newsz, current );
- dest += newsz;
- }
- }
- else {
- GLuint sz = exec->vtx.attrsz[j];
- COPY_SZ_4V( dest, sz, data );
- dest += sz;
- data += sz;
- }
- }
- }
- }
-
- exec->vtx.buffer_ptr = dest;
- exec->vtx.vert_count += exec->vtx.copied.nr;
- exec->vtx.copied.nr = 0;
- }
-}
-
-
-static void vbo_exec_fixup_vertex( GLcontext *ctx,
- GLuint attr, GLuint sz )
-{
- struct vbo_exec_context *exec = &vbo_context(ctx)->exec;
- int i;
-
- if (sz > exec->vtx.attrsz[attr]) {
- /* New size is larger. Need to flush existing vertices and get
- * an enlarged vertex format.
- */
- vbo_exec_wrap_upgrade_vertex( exec, attr, sz );
- }
- else if (sz < exec->vtx.active_sz[attr]) {
- static const GLfloat id[4] = { 0, 0, 0, 1 };
-
- /* New size is smaller - just need to fill in some
- * zeros. Don't need to flush or wrap.
- */
- for (i = sz ; i <= exec->vtx.attrsz[attr] ; i++)
- exec->vtx.attrptr[attr][i-1] = id[i-1];
- }
-
- exec->vtx.active_sz[attr] = sz;
-
- /* Does setting NeedFlush belong here? Necessitates resetting
- * vtxfmt on each flush (otherwise flags won't get reset
- * afterwards).
- */
- if (attr == 0)
- exec->ctx->Driver.NeedFlush |= FLUSH_STORED_VERTICES;
-}
-
-
-#if FEATURE_beginend
-
-/*
- */
-#define ATTR( A, N, V0, V1, V2, V3 ) \
-do { \
- struct vbo_exec_context *exec = &vbo_context(ctx)->exec; \
- \
- if (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; \
- } \
- \
- if ((A) == 0) { \
- 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; \
- exec->ctx->Driver.NeedFlush |= FLUSH_STORED_VERTICES; \
- \
- if (++exec->vtx.vert_count >= exec->vtx.max_vert) \
- vbo_exec_vtx_wrap( exec ); \
- } \
-} while (0)
-
-
-#define ERROR() _mesa_error( ctx, GL_INVALID_ENUM, __FUNCTION__ )
-#define TAG(x) vbo_##x
-
-#include "vbo_attrib_tmp.h"
-
-
-
-
-
-#if FEATURE_evaluators
-
-static void GLAPIENTRY vbo_exec_EvalCoord1f( GLfloat u )
-{
- GET_CURRENT_CONTEXT( ctx );
- struct vbo_exec_context *exec = &vbo_context(ctx)->exec;
-
- {
- GLint i;
- if (exec->eval.recalculate_maps)
- vbo_exec_eval_update( exec );
-
- for (i = 0; i <= VBO_ATTRIB_TEX7; i++) {
- if (exec->eval.map1[i].map)
- if (exec->vtx.active_sz[i] != exec->eval.map1[i].sz)
- vbo_exec_fixup_vertex( ctx, i, exec->eval.map1[i].sz );
- }
- }
-
-
- memcpy( exec->vtx.copied.buffer, exec->vtx.vertex,
- exec->vtx.vertex_size * sizeof(GLfloat));
-
- vbo_exec_do_EvalCoord1f( exec, u );
-
- memcpy( exec->vtx.vertex, exec->vtx.copied.buffer,
- exec->vtx.vertex_size * sizeof(GLfloat));
-}
-
-static void GLAPIENTRY vbo_exec_EvalCoord2f( GLfloat u, GLfloat v )
-{
- GET_CURRENT_CONTEXT( ctx );
- struct vbo_exec_context *exec = &vbo_context(ctx)->exec;
-
- {
- GLint i;
- if (exec->eval.recalculate_maps)
- vbo_exec_eval_update( exec );
-
- for (i = 0; i <= VBO_ATTRIB_TEX7; i++) {
- if (exec->eval.map2[i].map)
- if (exec->vtx.active_sz[i] != exec->eval.map2[i].sz)
- vbo_exec_fixup_vertex( ctx, i, exec->eval.map2[i].sz );
- }
-
- if (ctx->Eval.AutoNormal)
- if (exec->vtx.active_sz[VBO_ATTRIB_NORMAL] != 3)
- vbo_exec_fixup_vertex( ctx, VBO_ATTRIB_NORMAL, 3 );
- }
-
- memcpy( exec->vtx.copied.buffer, exec->vtx.vertex,
- exec->vtx.vertex_size * sizeof(GLfloat));
-
- vbo_exec_do_EvalCoord2f( exec, u, v );
-
- memcpy( exec->vtx.vertex, exec->vtx.copied.buffer,
- exec->vtx.vertex_size * sizeof(GLfloat));
-}
-
-static void GLAPIENTRY vbo_exec_EvalCoord1fv( const GLfloat *u )
-{
- vbo_exec_EvalCoord1f( u[0] );
-}
-
-static void GLAPIENTRY vbo_exec_EvalCoord2fv( const GLfloat *u )
-{
- vbo_exec_EvalCoord2f( u[0], u[1] );
-}
-
-static void GLAPIENTRY vbo_exec_EvalPoint1( GLint i )
-{
- GET_CURRENT_CONTEXT( ctx );
- GLfloat du = ((ctx->Eval.MapGrid1u2 - ctx->Eval.MapGrid1u1) /
- (GLfloat) ctx->Eval.MapGrid1un);
- GLfloat u = i * du + ctx->Eval.MapGrid1u1;
-
- vbo_exec_EvalCoord1f( u );
-}
-
-
-static void GLAPIENTRY vbo_exec_EvalPoint2( GLint i, GLint j )
-{
- GET_CURRENT_CONTEXT( ctx );
- GLfloat du = ((ctx->Eval.MapGrid2u2 - ctx->Eval.MapGrid2u1) /
- (GLfloat) ctx->Eval.MapGrid2un);
- GLfloat dv = ((ctx->Eval.MapGrid2v2 - ctx->Eval.MapGrid2v1) /
- (GLfloat) ctx->Eval.MapGrid2vn);
- GLfloat u = i * du + ctx->Eval.MapGrid2u1;
- GLfloat v = j * dv + ctx->Eval.MapGrid2v1;
-
- vbo_exec_EvalCoord2f( u, v );
-}
-
-/* use noop eval mesh */
-#define vbo_exec_EvalMesh1 _mesa_noop_EvalMesh1
-#define vbo_exec_EvalMesh2 _mesa_noop_EvalMesh2
-
-#endif /* FEATURE_evaluators */
-
-
-/**
- * Called via glBegin.
- */
-static void GLAPIENTRY vbo_exec_Begin( GLenum mode )
-{
- GET_CURRENT_CONTEXT( ctx );
-
- if (ctx->Driver.CurrentExecPrimitive == PRIM_OUTSIDE_BEGIN_END) {
- struct vbo_exec_context *exec = &vbo_context(ctx)->exec;
- int i;
-
- if (ctx->NewState) {
- _mesa_update_state( ctx );
-
- CALL_Begin(ctx->Exec, (mode));
- return;
- }
-
- if (!_mesa_valid_to_render(ctx, "glBegin")) {
- return;
- }
-
- /* Heuristic: attempt to isolate attributes occuring outside
- * begin/end pairs.
- */
- if (exec->vtx.vertex_size && !exec->vtx.attrsz[0])
- vbo_exec_FlushVertices_internal( ctx, GL_FALSE );
-
- i = exec->vtx.prim_count++;
- exec->vtx.prim[i].mode = mode;
- exec->vtx.prim[i].begin = 1;
- exec->vtx.prim[i].end = 0;
- exec->vtx.prim[i].indexed = 0;
- exec->vtx.prim[i].weak = 0;
- exec->vtx.prim[i].pad = 0;
- exec->vtx.prim[i].start = exec->vtx.vert_count;
- exec->vtx.prim[i].count = 0;
- exec->vtx.prim[i].num_instances = 1;
-
- ctx->Driver.CurrentExecPrimitive = mode;
- }
- else
- _mesa_error( ctx, GL_INVALID_OPERATION, "glBegin" );
-
-}
-
-
-/**
- * Called via glEnd.
- */
-static void GLAPIENTRY vbo_exec_End( void )
-{
- GET_CURRENT_CONTEXT( ctx );
-
- if (ctx->Driver.CurrentExecPrimitive != PRIM_OUTSIDE_BEGIN_END) {
- struct vbo_exec_context *exec = &vbo_context(ctx)->exec;
- int idx = exec->vtx.vert_count;
- int i = exec->vtx.prim_count - 1;
-
- exec->vtx.prim[i].end = 1;
- exec->vtx.prim[i].count = idx - exec->vtx.prim[i].start;
-
- ctx->Driver.CurrentExecPrimitive = PRIM_OUTSIDE_BEGIN_END;
-
- if (exec->vtx.prim_count == VBO_MAX_PRIM)
- vbo_exec_vtx_flush( exec, GL_FALSE );
- }
- else
- _mesa_error( ctx, GL_INVALID_OPERATION, "glEnd" );
-}
-
-
-static void vbo_exec_vtxfmt_init( struct vbo_exec_context *exec )
-{
- GLvertexformat *vfmt = &exec->vtxfmt;
-
- _MESA_INIT_ARRAYELT_VTXFMT(vfmt, _ae_);
-
- vfmt->Begin = vbo_exec_Begin;
- vfmt->End = vbo_exec_End;
-
- _MESA_INIT_DLIST_VTXFMT(vfmt, _mesa_);
- _MESA_INIT_EVAL_VTXFMT(vfmt, vbo_exec_);
-
- vfmt->Rectf = _mesa_noop_Rectf;
-
- /* from attrib_tmp.h:
- */
- vfmt->Color3f = vbo_Color3f;
- vfmt->Color3fv = vbo_Color3fv;
- vfmt->Color4f = vbo_Color4f;
- vfmt->Color4fv = vbo_Color4fv;
- vfmt->FogCoordfEXT = vbo_FogCoordfEXT;
- vfmt->FogCoordfvEXT = vbo_FogCoordfvEXT;
- vfmt->MultiTexCoord1fARB = vbo_MultiTexCoord1f;
- vfmt->MultiTexCoord1fvARB = vbo_MultiTexCoord1fv;
- vfmt->MultiTexCoord2fARB = vbo_MultiTexCoord2f;
- vfmt->MultiTexCoord2fvARB = vbo_MultiTexCoord2fv;
- vfmt->MultiTexCoord3fARB = vbo_MultiTexCoord3f;
- vfmt->MultiTexCoord3fvARB = vbo_MultiTexCoord3fv;
- vfmt->MultiTexCoord4fARB = vbo_MultiTexCoord4f;
- vfmt->MultiTexCoord4fvARB = vbo_MultiTexCoord4fv;
- vfmt->Normal3f = vbo_Normal3f;
- vfmt->Normal3fv = vbo_Normal3fv;
- vfmt->SecondaryColor3fEXT = vbo_SecondaryColor3fEXT;
- vfmt->SecondaryColor3fvEXT = vbo_SecondaryColor3fvEXT;
- vfmt->TexCoord1f = vbo_TexCoord1f;
- vfmt->TexCoord1fv = vbo_TexCoord1fv;
- vfmt->TexCoord2f = vbo_TexCoord2f;
- vfmt->TexCoord2fv = vbo_TexCoord2fv;
- vfmt->TexCoord3f = vbo_TexCoord3f;
- vfmt->TexCoord3fv = vbo_TexCoord3fv;
- vfmt->TexCoord4f = vbo_TexCoord4f;
- vfmt->TexCoord4fv = vbo_TexCoord4fv;
- vfmt->Vertex2f = vbo_Vertex2f;
- vfmt->Vertex2fv = vbo_Vertex2fv;
- vfmt->Vertex3f = vbo_Vertex3f;
- vfmt->Vertex3fv = vbo_Vertex3fv;
- vfmt->Vertex4f = vbo_Vertex4f;
- vfmt->Vertex4fv = vbo_Vertex4fv;
-
- vfmt->VertexAttrib1fARB = vbo_VertexAttrib1fARB;
- vfmt->VertexAttrib1fvARB = vbo_VertexAttrib1fvARB;
- vfmt->VertexAttrib2fARB = vbo_VertexAttrib2fARB;
- vfmt->VertexAttrib2fvARB = vbo_VertexAttrib2fvARB;
- vfmt->VertexAttrib3fARB = vbo_VertexAttrib3fARB;
- vfmt->VertexAttrib3fvARB = vbo_VertexAttrib3fvARB;
- vfmt->VertexAttrib4fARB = vbo_VertexAttrib4fARB;
- vfmt->VertexAttrib4fvARB = vbo_VertexAttrib4fvARB;
-
- vfmt->VertexAttrib1fNV = vbo_VertexAttrib1fNV;
- vfmt->VertexAttrib1fvNV = vbo_VertexAttrib1fvNV;
- vfmt->VertexAttrib2fNV = vbo_VertexAttrib2fNV;
- vfmt->VertexAttrib2fvNV = vbo_VertexAttrib2fvNV;
- vfmt->VertexAttrib3fNV = vbo_VertexAttrib3fNV;
- vfmt->VertexAttrib3fvNV = vbo_VertexAttrib3fvNV;
- vfmt->VertexAttrib4fNV = vbo_VertexAttrib4fNV;
- vfmt->VertexAttrib4fvNV = vbo_VertexAttrib4fvNV;
-
- vfmt->Materialfv = vbo_Materialfv;
-
- vfmt->EdgeFlag = vbo_EdgeFlag;
- vfmt->Indexf = vbo_Indexf;
- vfmt->Indexfv = vbo_Indexfv;
-
-}
-
-
-#else /* FEATURE_beginend */
-
-
-#define ATTR( A, N, V0, V1, V2, V3 ) \
-do { \
- struct vbo_exec_context *exec = &vbo_context(ctx)->exec; \
- \
- /* FLUSH_UPDATE_CURRENT needs to be set manually */ \
- exec->ctx->Driver.NeedFlush |= FLUSH_UPDATE_CURRENT; \
- \
- if (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; \
- } \
-} while (0)
-
-#define ERROR() _mesa_error( ctx, GL_INVALID_ENUM, __FUNCTION__ )
-#define TAG(x) vbo_##x
-
-#include "vbo_attrib_tmp.h"
-
-static void vbo_exec_vtxfmt_init( struct vbo_exec_context *exec )
-{
- /* silence warnings */
- (void) vbo_Color3f;
- (void) vbo_Color3fv;
- (void) vbo_Color4f;
- (void) vbo_Color4fv;
- (void) vbo_FogCoordfEXT;
- (void) vbo_FogCoordfvEXT;
- (void) vbo_MultiTexCoord1f;
- (void) vbo_MultiTexCoord1fv;
- (void) vbo_MultiTexCoord2f;
- (void) vbo_MultiTexCoord2fv;
- (void) vbo_MultiTexCoord3f;
- (void) vbo_MultiTexCoord3fv;
- (void) vbo_MultiTexCoord4f;
- (void) vbo_MultiTexCoord4fv;
- (void) vbo_Normal3f;
- (void) vbo_Normal3fv;
- (void) vbo_SecondaryColor3fEXT;
- (void) vbo_SecondaryColor3fvEXT;
- (void) vbo_TexCoord1f;
- (void) vbo_TexCoord1fv;
- (void) vbo_TexCoord2f;
- (void) vbo_TexCoord2fv;
- (void) vbo_TexCoord3f;
- (void) vbo_TexCoord3fv;
- (void) vbo_TexCoord4f;
- (void) vbo_TexCoord4fv;
- (void) vbo_Vertex2f;
- (void) vbo_Vertex2fv;
- (void) vbo_Vertex3f;
- (void) vbo_Vertex3fv;
- (void) vbo_Vertex4f;
- (void) vbo_Vertex4fv;
-
- (void) vbo_VertexAttrib1fARB;
- (void) vbo_VertexAttrib1fvARB;
- (void) vbo_VertexAttrib2fARB;
- (void) vbo_VertexAttrib2fvARB;
- (void) vbo_VertexAttrib3fARB;
- (void) vbo_VertexAttrib3fvARB;
- (void) vbo_VertexAttrib4fARB;
- (void) vbo_VertexAttrib4fvARB;
-
- (void) vbo_VertexAttrib1fNV;
- (void) vbo_VertexAttrib1fvNV;
- (void) vbo_VertexAttrib2fNV;
- (void) vbo_VertexAttrib2fvNV;
- (void) vbo_VertexAttrib3fNV;
- (void) vbo_VertexAttrib3fvNV;
- (void) vbo_VertexAttrib4fNV;
- (void) vbo_VertexAttrib4fvNV;
-
- (void) vbo_Materialfv;
-
- (void) vbo_EdgeFlag;
- (void) vbo_Indexf;
- (void) vbo_Indexfv;
-}
-
-
-#endif /* FEATURE_beginend */
-
-
-/**
- * Tell the VBO module to use a real OpenGL vertex buffer object to
- * store accumulated immediate-mode vertex data.
- * This replaces the malloced buffer which was created in
- * vb_exec_vtx_init() below.
- */
-void vbo_use_buffer_objects(GLcontext *ctx)
-{
- struct vbo_exec_context *exec = &vbo_context(ctx)->exec;
- /* Any buffer name but 0 can be used here since this bufferobj won't
- * go into the bufferobj hashtable.
- */
- GLuint bufName = IMM_BUFFER_NAME;
- GLenum target = GL_ARRAY_BUFFER_ARB;
- GLenum usage = GL_STREAM_DRAW_ARB;
- GLsizei size = VBO_VERT_BUFFER_SIZE;
-
- /* Make sure this func is only used once */
- assert(exec->vtx.bufferobj == ctx->Shared->NullBufferObj);
- if (exec->vtx.buffer_map) {
- _mesa_align_free(exec->vtx.buffer_map);
- exec->vtx.buffer_map = NULL;
- exec->vtx.buffer_ptr = NULL;
- }
-
- /* Allocate a real buffer object now */
- _mesa_reference_buffer_object(ctx, &exec->vtx.bufferobj, NULL);
- exec->vtx.bufferobj = ctx->Driver.NewBufferObject(ctx, bufName, target);
- ctx->Driver.BufferData(ctx, target, size, NULL, usage, exec->vtx.bufferobj);
-}
-
-
-
-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
- * continuously, unless vbo_use_buffer_objects() is called to enable
- * use of real VBOs.
- */
- _mesa_reference_buffer_object(ctx,
- &exec->vtx.bufferobj,
- ctx->Shared->NullBufferObj);
-
- ASSERT(!exec->vtx.buffer_map);
- exec->vtx.buffer_map = (GLfloat *)_mesa_align_malloc(VBO_VERT_BUFFER_SIZE, 64);
- exec->vtx.buffer_ptr = exec->vtx.buffer_map;
-
- vbo_exec_vtxfmt_init( exec );
-
- /* Hook our functions into the dispatch table.
- */
- _mesa_install_exec_vtxfmt( exec->ctx, &exec->vtxfmt );
-
- for (i = 0 ; i < VBO_ATTRIB_MAX ; i++) {
- ASSERT(i < Elements(exec->vtx.attrsz));
- exec->vtx.attrsz[i] = 0;
- ASSERT(i < Elements(exec->vtx.active_sz));
- exec->vtx.active_sz[i] = 0;
- }
- for (i = 0 ; i < VERT_ATTRIB_MAX; i++) {
- ASSERT(i < Elements(exec->vtx.inputs));
- ASSERT(i < Elements(exec->vtx.arrays));
- exec->vtx.inputs[i] = &exec->vtx.arrays[i];
- }
-
- {
- struct gl_client_array *arrays = exec->vtx.arrays;
- unsigned i;
-
- memcpy(arrays, vbo->legacy_currval, 16 * sizeof(arrays[0]));
- memcpy(arrays + 16, vbo->generic_currval, 16 * sizeof(arrays[0]));
-
- for (i = 0; i < 16; ++i) {
- arrays[i ].BufferObj = NULL;
- arrays[i + 16].BufferObj = NULL;
- _mesa_reference_buffer_object(ctx, &arrays[i ].BufferObj,
- vbo->legacy_currval[i].BufferObj);
- _mesa_reference_buffer_object(ctx, &arrays[i + 16].BufferObj,
- vbo->generic_currval[i].BufferObj);
- }
- }
-
- exec->vtx.vertex_size = 0;
-}
-
-
-void vbo_exec_vtx_destroy( struct vbo_exec_context *exec )
-{
- /* using a real VBO for vertex data */
- GLcontext *ctx = exec->ctx;
- unsigned i;
-
- /* True VBOs should already be unmapped
- */
- if (exec->vtx.buffer_map) {
- ASSERT(exec->vtx.bufferobj->Name == 0 ||
- exec->vtx.bufferobj->Name == IMM_BUFFER_NAME);
- if (exec->vtx.bufferobj->Name == 0) {
- _mesa_align_free(exec->vtx.buffer_map);
- exec->vtx.buffer_map = NULL;
- exec->vtx.buffer_ptr = NULL;
- }
- }
-
- /* Drop any outstanding reference to the vertex buffer
- */
- for (i = 0; i < Elements(exec->vtx.arrays); i++) {
- _mesa_reference_buffer_object(ctx,
- &exec->vtx.arrays[i].BufferObj,
- NULL);
- }
-
- /* Free the vertex buffer. Unmap first if needed.
- */
- if (_mesa_bufferobj_mapped(exec->vtx.bufferobj)) {
- ctx->Driver.UnmapBuffer(ctx, GL_ARRAY_BUFFER, exec->vtx.bufferobj);
- }
- _mesa_reference_buffer_object(ctx, &exec->vtx.bufferobj, NULL);
-}
-
-void vbo_exec_BeginVertices( GLcontext *ctx )
-{
- struct vbo_exec_context *exec = &vbo_context(ctx)->exec;
- if (0) printf("%s\n", __FUNCTION__);
- vbo_exec_vtx_map( exec );
-
- assert((exec->ctx->Driver.NeedFlush & FLUSH_UPDATE_CURRENT) == 0);
- exec->ctx->Driver.NeedFlush |= FLUSH_UPDATE_CURRENT;
-}
-
-void vbo_exec_FlushVertices_internal( GLcontext *ctx, GLboolean unmap )
-{
- struct vbo_exec_context *exec = &vbo_context(ctx)->exec;
-
- if (exec->vtx.vert_count || unmap) {
- vbo_exec_vtx_flush( exec, unmap );
- }
-
- if (exec->vtx.vertex_size) {
- vbo_exec_copy_to_current( exec );
- reset_attrfv( exec );
- }
-}
-
-
-/**
- * \param flags bitmask of FLUSH_STORED_VERTICES, FLUSH_UPDATE_CURRENT
- */
-void vbo_exec_FlushVertices( GLcontext *ctx, GLuint flags )
-{
- struct vbo_exec_context *exec = &vbo_context(ctx)->exec;
-
-#ifdef DEBUG
- /* debug check: make sure we don't get called recursively */
- exec->flush_call_depth++;
- assert(exec->flush_call_depth == 1);
-#endif
-
- if (0) printf("%s\n", __FUNCTION__);
-
- if (exec->ctx->Driver.CurrentExecPrimitive != PRIM_OUTSIDE_BEGIN_END) {
- if (0) printf("%s - inside begin/end\n", __FUNCTION__);
-#ifdef DEBUG
- exec->flush_call_depth--;
- assert(exec->flush_call_depth == 0);
-#endif
- return;
- }
-
- vbo_exec_FlushVertices_internal( ctx, GL_TRUE );
-
- /* Need to do this to ensure BeginVertices gets called again:
- */
- if (exec->ctx->Driver.NeedFlush & FLUSH_UPDATE_CURRENT) {
- _mesa_restore_exec_vtxfmt( ctx );
- exec->ctx->Driver.NeedFlush &= ~FLUSH_UPDATE_CURRENT;
- }
-
- exec->ctx->Driver.NeedFlush &= ~flags;
-
-#ifdef DEBUG
- exec->flush_call_depth--;
- assert(exec->flush_call_depth == 0);
-#endif
-}
-
-
-static void reset_attrfv( struct vbo_exec_context *exec )
-{
- GLuint i;
-
- for (i = 0 ; i < VBO_ATTRIB_MAX ; i++) {
- exec->vtx.attrsz[i] = 0;
- exec->vtx.active_sz[i] = 0;
- }
-
- exec->vtx.vertex_size = 0;
-}
-
-
-void GLAPIENTRY
-_vbo_Color4f(GLfloat r, GLfloat g, GLfloat b, GLfloat a)
-{
- vbo_Color4f(r, g, b, a);
-}
-
-
-void GLAPIENTRY
-_vbo_Normal3f(GLfloat x, GLfloat y, GLfloat z)
-{
- vbo_Normal3f(x, y, z);
-}
-
-
-void GLAPIENTRY
-_vbo_MultiTexCoord4f(GLenum target, GLfloat s, GLfloat t, GLfloat r, GLfloat q)
-{
- vbo_MultiTexCoord4f(target, s, t, r, q);
-}
-
-
-void GLAPIENTRY
-_vbo_Materialfv(GLenum face, GLenum pname, const GLfloat *params)
-{
- vbo_Materialfv(face, pname, params);
-}
-
-
-void GLAPIENTRY
-_vbo_Materialf(GLenum face, GLenum pname, GLfloat param)
-{
- GLfloat p[4];
- p[0] = param;
- p[1] = p[2] = p[3] = 0.0F;
- vbo_Materialfv(face, pname, p);
-}
-
-
-void GLAPIENTRY
-_vbo_VertexAttrib4f(GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w)
-{
- vbo_VertexAttrib4fARB(index, x, y, z, w);
-}
-
-
-void GLAPIENTRY
-_vbo_VertexAttrib1f(GLuint indx, GLfloat x)
-{
- vbo_VertexAttrib1fARB(indx, x);
-}
-
-
-void GLAPIENTRY
-_vbo_VertexAttrib1fv(GLuint indx, const GLfloat* values)
-{
- vbo_VertexAttrib1fvARB(indx, values);
-}
-
-
-void GLAPIENTRY
-_vbo_VertexAttrib2f(GLuint indx, GLfloat x, GLfloat y)
-{
- vbo_VertexAttrib2fARB(indx, x, y);
-}
-
-
-void GLAPIENTRY
-_vbo_VertexAttrib2fv(GLuint indx, const GLfloat* values)
-{
- vbo_VertexAttrib2fvARB(indx, values);
-}
-
-
-void GLAPIENTRY
-_vbo_VertexAttrib3f(GLuint indx, GLfloat x, GLfloat y, GLfloat z)
-{
- vbo_VertexAttrib3fARB(indx, x, y, z);
-}
-
-
-void GLAPIENTRY
-_vbo_VertexAttrib3fv(GLuint indx, const GLfloat* values)
-{
- vbo_VertexAttrib3fvARB(indx, values);
-}
-
-
-void GLAPIENTRY
-_vbo_VertexAttrib4fv(GLuint indx, const GLfloat* values)
-{
- vbo_VertexAttrib4fvARB(indx, values);
-}
+/**************************************************************************
+
+Copyright 2002-2008 Tungsten Graphics Inc., Cedar Park, Texas.
+
+All Rights Reserved.
+
+Permission is hereby granted, free of charge, to any person obtaining a
+copy of this software and associated documentation files (the "Software"),
+to deal in the Software without restriction, including without limitation
+on the rights to use, copy, modify, merge, publish, distribute, sub
+license, and/or sell copies of the Software, and to permit persons to whom
+the Software is furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice (including the next
+paragraph) shall be included in all copies or substantial portions of the
+Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
+TUNGSTEN GRAPHICS AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
+DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+**************************************************************************/
+
+/*
+ * Authors:
+ * Keith Whitwell <keith@tungstengraphics.com>
+ */
+
+#include "main/glheader.h"
+#include "main/bufferobj.h"
+#include "main/context.h"
+#include "main/macros.h"
+#include "main/vtxfmt.h"
+#include "main/dlist.h"
+#include "main/eval.h"
+#include "main/state.h"
+#include "main/light.h"
+#include "main/api_arrayelt.h"
+#include "main/api_noop.h"
+#include "main/dispatch.h"
+
+#include "vbo_context.h"
+
+#ifdef ERROR
+#undef ERROR
+#endif
+
+
+/** ID/name for immediate-mode VBO */
+#define IMM_BUFFER_NAME 0xaabbccdd
+
+
+static void reset_attrfv( struct vbo_exec_context *exec );
+
+
+/**
+ * Close off the last primitive, execute the buffer, restart the
+ * primitive.
+ */
+static void vbo_exec_wrap_buffers( struct vbo_exec_context *exec )
+{
+ if (exec->vtx.prim_count == 0) {
+ exec->vtx.copied.nr = 0;
+ exec->vtx.vert_count = 0;
+ exec->vtx.buffer_ptr = exec->vtx.buffer_map;
+ }
+ else {
+ GLuint last_begin = exec->vtx.prim[exec->vtx.prim_count-1].begin;
+ GLuint last_count;
+
+ if (exec->ctx->Driver.CurrentExecPrimitive != PRIM_OUTSIDE_BEGIN_END) {
+ GLint i = exec->vtx.prim_count - 1;
+ assert(i >= 0);
+ exec->vtx.prim[i].count = (exec->vtx.vert_count -
+ exec->vtx.prim[i].start);
+ }
+
+ last_count = exec->vtx.prim[exec->vtx.prim_count-1].count;
+
+ /* Execute the buffer and save copied vertices.
+ */
+ if (exec->vtx.vert_count)
+ vbo_exec_vtx_flush( exec, GL_FALSE );
+ else {
+ exec->vtx.prim_count = 0;
+ exec->vtx.copied.nr = 0;
+ }
+
+ /* Emit a glBegin to start the new list.
+ */
+ assert(exec->vtx.prim_count == 0);
+
+ if (exec->ctx->Driver.CurrentExecPrimitive != PRIM_OUTSIDE_BEGIN_END) {
+ exec->vtx.prim[0].mode = exec->ctx->Driver.CurrentExecPrimitive;
+ exec->vtx.prim[0].start = 0;
+ exec->vtx.prim[0].count = 0;
+ exec->vtx.prim_count++;
+
+ if (exec->vtx.copied.nr == last_count)
+ exec->vtx.prim[0].begin = last_begin;
+ }
+ }
+}
+
+
+/**
+ * Deal with buffer wrapping where provoked by the vertex buffer
+ * filling up, as opposed to upgrade_vertex().
+ */
+void vbo_exec_vtx_wrap( struct vbo_exec_context *exec )
+{
+ GLfloat *data = exec->vtx.copied.buffer;
+ GLuint i;
+
+ /* Run pipeline on current vertices, copy wrapped vertices
+ * to exec->vtx.copied.
+ */
+ vbo_exec_wrap_buffers( exec );
+
+ /* Copy stored stored vertices to start of new list.
+ */
+ assert(exec->vtx.max_vert - exec->vtx.vert_count > exec->vtx.copied.nr);
+
+ for (i = 0 ; i < exec->vtx.copied.nr ; i++) {
+ memcpy( exec->vtx.buffer_ptr, data,
+ exec->vtx.vertex_size * sizeof(GLfloat));
+ exec->vtx.buffer_ptr += exec->vtx.vertex_size;
+ data += exec->vtx.vertex_size;
+ exec->vtx.vert_count++;
+ }
+
+ exec->vtx.copied.nr = 0;
+}
+
+
+/**
+ * Copy the active vertex's values to the ctx->Current fields.
+ */
+static void vbo_exec_copy_to_current( struct vbo_exec_context *exec )
+{
+ struct gl_context *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]) {
+ /* Note: the exec->vtx.current[i] pointers point into the
+ * ctx->Current.Attrib and ctx->Light.Material.Attrib arrays.
+ */
+ GLfloat *current = (GLfloat *)vbo->currval[i].Ptr;
+ GLfloat tmp[4];
+
+ COPY_CLEAN_4V(tmp,
+ exec->vtx.attrsz[i],
+ exec->vtx.attrptr[i]);
+
+ if (memcmp(current, tmp, sizeof(tmp)) != 0)
+ {
+ memcpy(current, tmp, sizeof(tmp));
+
+ /* 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).
+ */
+ if (i >= VBO_ATTRIB_MAT_FRONT_AMBIENT &&
+ i <= VBO_ATTRIB_MAT_BACK_INDEXES)
+ ctx->NewState |= _NEW_LIGHT;
+
+ ctx->NewState |= _NEW_CURRENT_ATTRIB;
+ }
+ }
+ }
+
+ /* Colormaterial -- this kindof sucks.
+ */
+ if (ctx->Light.ColorMaterialEnabled &&
+ exec->vtx.attrsz[VBO_ATTRIB_COLOR0]) {
+ _mesa_update_color_material(ctx,
+ ctx->Current.Attrib[VBO_ATTRIB_COLOR0]);
+ }
+}
+
+
+static void vbo_exec_copy_from_current( struct vbo_exec_context *exec )
+{
+ struct gl_context *ctx = exec->ctx;
+ struct vbo_context *vbo = vbo_context(ctx);
+ GLint 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] = 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;
+ }
+ }
+}
+
+
+/**
+ * Flush existing data, set new attrib size, replay copied vertices.
+ */
+static void vbo_exec_wrap_upgrade_vertex( struct vbo_exec_context *exec,
+ GLuint attr,
+ GLuint newsz )
+{
+ struct gl_context *ctx = exec->ctx;
+ struct vbo_context *vbo = vbo_context(ctx);
+ GLint lastcount = exec->vtx.vert_count;
+ GLfloat *old_attrptr[VBO_ATTRIB_MAX];
+ GLuint old_vtx_size = exec->vtx.vertex_size;
+ GLuint oldsz = exec->vtx.attrsz[attr];
+ GLuint i;
+
+ /* Run pipeline on current vertices, copy wrapped vertices
+ * to exec->vtx.copied.
+ */
+ vbo_exec_wrap_buffers( exec );
+
+ if (unlikely(exec->vtx.copied.nr)) {
+ /* We're in the middle of a primitive, keep the old vertex
+ * format around to be able to translate the copied vertices to
+ * the new format.
+ */
+ memcpy(old_attrptr, exec->vtx.attrptr, sizeof(old_attrptr));
+ }
+
+ if (unlikely(oldsz)) {
+ /* Do a COPY_TO_CURRENT to ensure back-copying works for the
+ * case when the attribute already exists in the vertex and is
+ * having its size increased.
+ */
+ vbo_exec_copy_to_current( exec );
+ }
+
+ /* Heuristic: Attempt to isolate attributes received outside
+ * begin/end so that they don't bloat the vertices.
+ */
+ if (ctx->Driver.CurrentExecPrimitive == PRIM_OUTSIDE_BEGIN_END &&
+ !oldsz && lastcount > 8 && exec->vtx.vertex_size) {
+ vbo_exec_copy_to_current( exec );
+ reset_attrfv( exec );
+ }
+
+ /* Fix up sizes:
+ */
+ exec->vtx.attrsz[attr] = newsz;
+ exec->vtx.vertex_size += newsz - oldsz;
+ exec->vtx.max_vert = ((VBO_VERT_BUFFER_SIZE - exec->vtx.buffer_used) /
+ (exec->vtx.vertex_size * sizeof(GLfloat)));
+ exec->vtx.vert_count = 0;
+ exec->vtx.buffer_ptr = exec->vtx.buffer_map;
+
+ if (unlikely(oldsz)) {
+ /* Size changed, recalculate all the attrptr[] values
+ */
+ GLfloat *tmp = exec->vtx.vertex;
+
+ for (i = 0 ; i < VBO_ATTRIB_MAX ; i++) {
+ if (exec->vtx.attrsz[i]) {
+ exec->vtx.attrptr[i] = tmp;
+ tmp += exec->vtx.attrsz[i];
+ }
+ else
+ exec->vtx.attrptr[i] = NULL; /* will not be dereferenced */
+ }
+
+ /* Copy from current to repopulate the vertex with correct
+ * values.
+ */
+ vbo_exec_copy_from_current( exec );
+
+ } else {
+ /* Just have to append the new attribute at the end */
+ exec->vtx.attrptr[attr] = exec->vtx.vertex +
+ exec->vtx.vertex_size - newsz;
+ }
+
+ /* Replay stored vertices to translate them
+ * to new format here.
+ *
+ * -- No need to replay - just copy piecewise
+ */
+ if (unlikely(exec->vtx.copied.nr)) {
+ GLfloat *data = exec->vtx.copied.buffer;
+ GLfloat *dest = exec->vtx.buffer_ptr;
+ GLuint j;
+
+ assert(exec->vtx.buffer_ptr == exec->vtx.buffer_map);
+
+ for (i = 0 ; i < exec->vtx.copied.nr ; i++) {
+ for (j = 0 ; j < VBO_ATTRIB_MAX ; j++) {
+ GLuint sz = exec->vtx.attrsz[j];
+
+ if (sz) {
+ GLint old_offset = old_attrptr[j] - exec->vtx.vertex;
+ GLint new_offset = exec->vtx.attrptr[j] - exec->vtx.vertex;
+
+ if (j == attr) {
+ if (oldsz) {
+ GLfloat tmp[4];
+ COPY_CLEAN_4V(tmp, oldsz, data + old_offset);
+ COPY_SZ_4V(dest + new_offset, newsz, tmp);
+ } else {
+ GLfloat *current = (GLfloat *)vbo->currval[j].Ptr;
+ COPY_SZ_4V(dest + new_offset, sz, current);
+ }
+ }
+ else {
+ COPY_SZ_4V(dest + new_offset, sz, data + old_offset);
+ }
+ }
+ }
+
+ data += old_vtx_size;
+ dest += exec->vtx.vertex_size;
+ }
+
+ exec->vtx.buffer_ptr = dest;
+ exec->vtx.vert_count += exec->vtx.copied.nr;
+ exec->vtx.copied.nr = 0;
+ }
+}
+
+
+static void vbo_exec_fixup_vertex( struct gl_context *ctx,
+ GLuint attr, GLuint sz )
+{
+ struct vbo_exec_context *exec = &vbo_context(ctx)->exec;
+ int i;
+
+ if (sz > exec->vtx.attrsz[attr]) {
+ /* New size is larger. Need to flush existing vertices and get
+ * an enlarged vertex format.
+ */
+ vbo_exec_wrap_upgrade_vertex( exec, attr, sz );
+ }
+ else if (sz < exec->vtx.active_sz[attr]) {
+ static const GLfloat id[4] = { 0, 0, 0, 1 };
+
+ /* New size is smaller - just need to fill in some
+ * zeros. Don't need to flush or wrap.
+ */
+ for (i = sz ; i <= exec->vtx.attrsz[attr] ; i++)
+ exec->vtx.attrptr[attr][i-1] = id[i-1];
+ }
+
+ exec->vtx.active_sz[attr] = sz;
+
+ /* Does setting NeedFlush belong here? Necessitates resetting
+ * vtxfmt on each flush (otherwise flags won't get reset
+ * afterwards).
+ */
+ if (attr == 0)
+ exec->ctx->Driver.NeedFlush |= FLUSH_STORED_VERTICES;
+}
+
+
+/*
+ */
+#define ATTR( A, N, V0, V1, V2, V3 ) \
+do { \
+ struct vbo_exec_context *exec = &vbo_context(ctx)->exec; \
+ \
+ if (unlikely(!(exec->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; \
+ } \
+ \
+ if ((A) == 0) { \
+ 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; \
+ exec->ctx->Driver.NeedFlush |= FLUSH_STORED_VERTICES; \
+ \
+ if (++exec->vtx.vert_count >= exec->vtx.max_vert) \
+ vbo_exec_vtx_wrap( exec ); \
+ } \
+} while (0)
+
+
+#define ERROR() _mesa_error( ctx, GL_INVALID_ENUM, __FUNCTION__ )
+#define TAG(x) vbo_##x
+
+#include "vbo_attrib_tmp.h"
+
+
+#if FEATURE_beginend
+
+
+#if FEATURE_evaluators
+
+static void GLAPIENTRY vbo_exec_EvalCoord1f( GLfloat u )
+{
+ GET_CURRENT_CONTEXT( ctx );
+ struct vbo_exec_context *exec = &vbo_context(ctx)->exec;
+
+ {
+ GLint i;
+ if (exec->eval.recalculate_maps)
+ vbo_exec_eval_update( exec );
+
+ for (i = 0; i <= VBO_ATTRIB_TEX7; i++) {
+ if (exec->eval.map1[i].map)
+ if (exec->vtx.active_sz[i] != exec->eval.map1[i].sz)
+ vbo_exec_fixup_vertex( ctx, i, exec->eval.map1[i].sz );
+ }
+ }
+
+
+ memcpy( exec->vtx.copied.buffer, exec->vtx.vertex,
+ exec->vtx.vertex_size * sizeof(GLfloat));
+
+ vbo_exec_do_EvalCoord1f( exec, u );
+
+ memcpy( exec->vtx.vertex, exec->vtx.copied.buffer,
+ exec->vtx.vertex_size * sizeof(GLfloat));
+}
+
+static void GLAPIENTRY vbo_exec_EvalCoord2f( GLfloat u, GLfloat v )
+{
+ GET_CURRENT_CONTEXT( ctx );
+ struct vbo_exec_context *exec = &vbo_context(ctx)->exec;
+
+ {
+ GLint i;
+ if (exec->eval.recalculate_maps)
+ vbo_exec_eval_update( exec );
+
+ for (i = 0; i <= VBO_ATTRIB_TEX7; i++) {
+ if (exec->eval.map2[i].map)
+ if (exec->vtx.active_sz[i] != exec->eval.map2[i].sz)
+ vbo_exec_fixup_vertex( ctx, i, exec->eval.map2[i].sz );
+ }
+
+ if (ctx->Eval.AutoNormal)
+ if (exec->vtx.active_sz[VBO_ATTRIB_NORMAL] != 3)
+ vbo_exec_fixup_vertex( ctx, VBO_ATTRIB_NORMAL, 3 );
+ }
+
+ memcpy( exec->vtx.copied.buffer, exec->vtx.vertex,
+ exec->vtx.vertex_size * sizeof(GLfloat));
+
+ vbo_exec_do_EvalCoord2f( exec, u, v );
+
+ memcpy( exec->vtx.vertex, exec->vtx.copied.buffer,
+ exec->vtx.vertex_size * sizeof(GLfloat));
+}
+
+static void GLAPIENTRY vbo_exec_EvalCoord1fv( const GLfloat *u )
+{
+ vbo_exec_EvalCoord1f( u[0] );
+}
+
+static void GLAPIENTRY vbo_exec_EvalCoord2fv( const GLfloat *u )
+{
+ vbo_exec_EvalCoord2f( u[0], u[1] );
+}
+
+static void GLAPIENTRY vbo_exec_EvalPoint1( GLint i )
+{
+ GET_CURRENT_CONTEXT( ctx );
+ GLfloat du = ((ctx->Eval.MapGrid1u2 - ctx->Eval.MapGrid1u1) /
+ (GLfloat) ctx->Eval.MapGrid1un);
+ GLfloat u = i * du + ctx->Eval.MapGrid1u1;
+
+ vbo_exec_EvalCoord1f( u );
+}
+
+
+static void GLAPIENTRY vbo_exec_EvalPoint2( GLint i, GLint j )
+{
+ GET_CURRENT_CONTEXT( ctx );
+ GLfloat du = ((ctx->Eval.MapGrid2u2 - ctx->Eval.MapGrid2u1) /
+ (GLfloat) ctx->Eval.MapGrid2un);
+ GLfloat dv = ((ctx->Eval.MapGrid2v2 - ctx->Eval.MapGrid2v1) /
+ (GLfloat) ctx->Eval.MapGrid2vn);
+ GLfloat u = i * du + ctx->Eval.MapGrid2u1;
+ GLfloat v = j * dv + ctx->Eval.MapGrid2v1;
+
+ vbo_exec_EvalCoord2f( u, v );
+}
+
+/* use noop eval mesh */
+#define vbo_exec_EvalMesh1 _mesa_noop_EvalMesh1
+#define vbo_exec_EvalMesh2 _mesa_noop_EvalMesh2
+
+#endif /* FEATURE_evaluators */
+
+
+/**
+ * Called via glBegin.
+ */
+static void GLAPIENTRY vbo_exec_Begin( GLenum mode )
+{
+ GET_CURRENT_CONTEXT( ctx );
+
+ if (ctx->Driver.CurrentExecPrimitive == PRIM_OUTSIDE_BEGIN_END) {
+ struct vbo_exec_context *exec = &vbo_context(ctx)->exec;
+ int i;
+
+ if (ctx->NewState) {
+ _mesa_update_state( ctx );
+
+ CALL_Begin(ctx->Exec, (mode));
+ return;
+ }
+
+ if (!_mesa_valid_to_render(ctx, "glBegin")) {
+ return;
+ }
+
+ /* Heuristic: attempt to isolate attributes occuring outside
+ * begin/end pairs.
+ */
+ if (exec->vtx.vertex_size && !exec->vtx.attrsz[0])
+ vbo_exec_FlushVertices_internal( ctx, GL_FALSE );
+
+ i = exec->vtx.prim_count++;
+ exec->vtx.prim[i].mode = mode;
+ exec->vtx.prim[i].begin = 1;
+ exec->vtx.prim[i].end = 0;
+ exec->vtx.prim[i].indexed = 0;
+ exec->vtx.prim[i].weak = 0;
+ exec->vtx.prim[i].pad = 0;
+ exec->vtx.prim[i].start = exec->vtx.vert_count;
+ exec->vtx.prim[i].count = 0;
+ exec->vtx.prim[i].num_instances = 1;
+
+ ctx->Driver.CurrentExecPrimitive = mode;
+ }
+ else
+ _mesa_error( ctx, GL_INVALID_OPERATION, "glBegin" );
+
+}
+
+
+/**
+ * Called via glEnd.
+ */
+static void GLAPIENTRY vbo_exec_End( void )
+{
+ GET_CURRENT_CONTEXT( ctx );
+
+ if (ctx->Driver.CurrentExecPrimitive != PRIM_OUTSIDE_BEGIN_END) {
+ struct vbo_exec_context *exec = &vbo_context(ctx)->exec;
+ int idx = exec->vtx.vert_count;
+ int i = exec->vtx.prim_count - 1;
+
+ exec->vtx.prim[i].end = 1;
+ exec->vtx.prim[i].count = idx - exec->vtx.prim[i].start;
+
+ ctx->Driver.CurrentExecPrimitive = PRIM_OUTSIDE_BEGIN_END;
+
+ if (exec->vtx.prim_count == VBO_MAX_PRIM)
+ vbo_exec_vtx_flush( exec, GL_FALSE );
+ }
+ else
+ _mesa_error( ctx, GL_INVALID_OPERATION, "glEnd" );
+}
+
+
+/**
+ * Called via glPrimitiveRestartNV()
+ */
+static void GLAPIENTRY
+vbo_exec_PrimitiveRestartNV(void)
+{
+ GLenum curPrim;
+ GET_CURRENT_CONTEXT( ctx );
+
+ curPrim = ctx->Driver.CurrentExecPrimitive;
+
+ if (curPrim == PRIM_OUTSIDE_BEGIN_END) {
+ _mesa_error( ctx, GL_INVALID_OPERATION, "glPrimitiveRestartNV" );
+ }
+ else {
+ vbo_exec_End();
+ vbo_exec_Begin(curPrim);
+ }
+}
+
+
+
+static void vbo_exec_vtxfmt_init( struct vbo_exec_context *exec )
+{
+ GLvertexformat *vfmt = &exec->vtxfmt;
+
+ _MESA_INIT_ARRAYELT_VTXFMT(vfmt, _ae_);
+
+ vfmt->Begin = vbo_exec_Begin;
+ vfmt->End = vbo_exec_End;
+ vfmt->PrimitiveRestartNV = vbo_exec_PrimitiveRestartNV;
+
+ _MESA_INIT_DLIST_VTXFMT(vfmt, _mesa_);
+ _MESA_INIT_EVAL_VTXFMT(vfmt, vbo_exec_);
+
+ vfmt->Rectf = _mesa_noop_Rectf;
+
+ /* from attrib_tmp.h:
+ */
+ vfmt->Color3f = vbo_Color3f;
+ vfmt->Color3fv = vbo_Color3fv;
+ vfmt->Color4f = vbo_Color4f;
+ vfmt->Color4fv = vbo_Color4fv;
+ vfmt->FogCoordfEXT = vbo_FogCoordfEXT;
+ vfmt->FogCoordfvEXT = vbo_FogCoordfvEXT;
+ vfmt->MultiTexCoord1fARB = vbo_MultiTexCoord1f;
+ vfmt->MultiTexCoord1fvARB = vbo_MultiTexCoord1fv;
+ vfmt->MultiTexCoord2fARB = vbo_MultiTexCoord2f;
+ vfmt->MultiTexCoord2fvARB = vbo_MultiTexCoord2fv;
+ vfmt->MultiTexCoord3fARB = vbo_MultiTexCoord3f;
+ vfmt->MultiTexCoord3fvARB = vbo_MultiTexCoord3fv;
+ vfmt->MultiTexCoord4fARB = vbo_MultiTexCoord4f;
+ vfmt->MultiTexCoord4fvARB = vbo_MultiTexCoord4fv;
+ vfmt->Normal3f = vbo_Normal3f;
+ vfmt->Normal3fv = vbo_Normal3fv;
+ vfmt->SecondaryColor3fEXT = vbo_SecondaryColor3fEXT;
+ vfmt->SecondaryColor3fvEXT = vbo_SecondaryColor3fvEXT;
+ vfmt->TexCoord1f = vbo_TexCoord1f;
+ vfmt->TexCoord1fv = vbo_TexCoord1fv;
+ vfmt->TexCoord2f = vbo_TexCoord2f;
+ vfmt->TexCoord2fv = vbo_TexCoord2fv;
+ vfmt->TexCoord3f = vbo_TexCoord3f;
+ vfmt->TexCoord3fv = vbo_TexCoord3fv;
+ vfmt->TexCoord4f = vbo_TexCoord4f;
+ vfmt->TexCoord4fv = vbo_TexCoord4fv;
+ vfmt->Vertex2f = vbo_Vertex2f;
+ vfmt->Vertex2fv = vbo_Vertex2fv;
+ vfmt->Vertex3f = vbo_Vertex3f;
+ vfmt->Vertex3fv = vbo_Vertex3fv;
+ vfmt->Vertex4f = vbo_Vertex4f;
+ vfmt->Vertex4fv = vbo_Vertex4fv;
+
+ vfmt->VertexAttrib1fARB = vbo_VertexAttrib1fARB;
+ vfmt->VertexAttrib1fvARB = vbo_VertexAttrib1fvARB;
+ vfmt->VertexAttrib2fARB = vbo_VertexAttrib2fARB;
+ vfmt->VertexAttrib2fvARB = vbo_VertexAttrib2fvARB;
+ vfmt->VertexAttrib3fARB = vbo_VertexAttrib3fARB;
+ vfmt->VertexAttrib3fvARB = vbo_VertexAttrib3fvARB;
+ vfmt->VertexAttrib4fARB = vbo_VertexAttrib4fARB;
+ vfmt->VertexAttrib4fvARB = vbo_VertexAttrib4fvARB;
+
+ vfmt->VertexAttrib1fNV = vbo_VertexAttrib1fNV;
+ vfmt->VertexAttrib1fvNV = vbo_VertexAttrib1fvNV;
+ vfmt->VertexAttrib2fNV = vbo_VertexAttrib2fNV;
+ vfmt->VertexAttrib2fvNV = vbo_VertexAttrib2fvNV;
+ vfmt->VertexAttrib3fNV = vbo_VertexAttrib3fNV;
+ vfmt->VertexAttrib3fvNV = vbo_VertexAttrib3fvNV;
+ vfmt->VertexAttrib4fNV = vbo_VertexAttrib4fNV;
+ vfmt->VertexAttrib4fvNV = vbo_VertexAttrib4fvNV;
+
+ /* integer-valued */
+ vfmt->VertexAttribI1i = vbo_VertexAttribI1i;
+ vfmt->VertexAttribI2i = vbo_VertexAttribI2i;
+ vfmt->VertexAttribI3i = vbo_VertexAttribI3i;
+ vfmt->VertexAttribI4i = vbo_VertexAttribI4i;
+ vfmt->VertexAttribI2iv = vbo_VertexAttribI2iv;
+ vfmt->VertexAttribI3iv = vbo_VertexAttribI3iv;
+ vfmt->VertexAttribI4iv = vbo_VertexAttribI4iv;
+
+ /* unsigned integer-valued */
+ vfmt->VertexAttribI1ui = vbo_VertexAttribI1ui;
+ vfmt->VertexAttribI2ui = vbo_VertexAttribI2ui;
+ vfmt->VertexAttribI3ui = vbo_VertexAttribI3ui;
+ vfmt->VertexAttribI4ui = vbo_VertexAttribI4ui;
+ vfmt->VertexAttribI2uiv = vbo_VertexAttribI2uiv;
+ vfmt->VertexAttribI3uiv = vbo_VertexAttribI3uiv;
+ vfmt->VertexAttribI4uiv = vbo_VertexAttribI4uiv;
+
+ vfmt->Materialfv = vbo_Materialfv;
+
+ vfmt->EdgeFlag = vbo_EdgeFlag;
+ vfmt->Indexf = vbo_Indexf;
+ vfmt->Indexfv = vbo_Indexfv;
+
+}
+
+
+#else /* FEATURE_beginend */
+
+
+static void vbo_exec_vtxfmt_init( struct vbo_exec_context *exec )
+{
+ /* silence warnings */
+ (void) vbo_Color3f;
+ (void) vbo_Color3fv;
+ (void) vbo_Color4f;
+ (void) vbo_Color4fv;
+ (void) vbo_FogCoordfEXT;
+ (void) vbo_FogCoordfvEXT;
+ (void) vbo_MultiTexCoord1f;
+ (void) vbo_MultiTexCoord1fv;
+ (void) vbo_MultiTexCoord2f;
+ (void) vbo_MultiTexCoord2fv;
+ (void) vbo_MultiTexCoord3f;
+ (void) vbo_MultiTexCoord3fv;
+ (void) vbo_MultiTexCoord4f;
+ (void) vbo_MultiTexCoord4fv;
+ (void) vbo_Normal3f;
+ (void) vbo_Normal3fv;
+ (void) vbo_SecondaryColor3fEXT;
+ (void) vbo_SecondaryColor3fvEXT;
+ (void) vbo_TexCoord1f;
+ (void) vbo_TexCoord1fv;
+ (void) vbo_TexCoord2f;
+ (void) vbo_TexCoord2fv;
+ (void) vbo_TexCoord3f;
+ (void) vbo_TexCoord3fv;
+ (void) vbo_TexCoord4f;
+ (void) vbo_TexCoord4fv;
+ (void) vbo_Vertex2f;
+ (void) vbo_Vertex2fv;
+ (void) vbo_Vertex3f;
+ (void) vbo_Vertex3fv;
+ (void) vbo_Vertex4f;
+ (void) vbo_Vertex4fv;
+
+ (void) vbo_VertexAttrib1fARB;
+ (void) vbo_VertexAttrib1fvARB;
+ (void) vbo_VertexAttrib2fARB;
+ (void) vbo_VertexAttrib2fvARB;
+ (void) vbo_VertexAttrib3fARB;
+ (void) vbo_VertexAttrib3fvARB;
+ (void) vbo_VertexAttrib4fARB;
+ (void) vbo_VertexAttrib4fvARB;
+
+ (void) vbo_VertexAttrib1fNV;
+ (void) vbo_VertexAttrib1fvNV;
+ (void) vbo_VertexAttrib2fNV;
+ (void) vbo_VertexAttrib2fvNV;
+ (void) vbo_VertexAttrib3fNV;
+ (void) vbo_VertexAttrib3fvNV;
+ (void) vbo_VertexAttrib4fNV;
+ (void) vbo_VertexAttrib4fvNV;
+
+ (void) vbo_Materialfv;
+
+ (void) vbo_EdgeFlag;
+ (void) vbo_Indexf;
+ (void) vbo_Indexfv;
+}
+
+
+#endif /* FEATURE_beginend */
+
+
+/**
+ * Tell the VBO module to use a real OpenGL vertex buffer object to
+ * store accumulated immediate-mode vertex data.
+ * This replaces the malloced buffer which was created in
+ * vb_exec_vtx_init() below.
+ */
+void vbo_use_buffer_objects(struct gl_context *ctx)
+{
+ struct vbo_exec_context *exec = &vbo_context(ctx)->exec;
+ /* Any buffer name but 0 can be used here since this bufferobj won't
+ * go into the bufferobj hashtable.
+ */
+ GLuint bufName = IMM_BUFFER_NAME;
+ GLenum target = GL_ARRAY_BUFFER_ARB;
+ GLenum usage = GL_STREAM_DRAW_ARB;
+ GLsizei size = VBO_VERT_BUFFER_SIZE;
+
+ /* Make sure this func is only used once */
+ assert(exec->vtx.bufferobj == ctx->Shared->NullBufferObj);
+ if (exec->vtx.buffer_map) {
+ _mesa_align_free(exec->vtx.buffer_map);
+ exec->vtx.buffer_map = NULL;
+ exec->vtx.buffer_ptr = NULL;
+ }
+
+ /* Allocate a real buffer object now */
+ _mesa_reference_buffer_object(ctx, &exec->vtx.bufferobj, NULL);
+ exec->vtx.bufferobj = ctx->Driver.NewBufferObject(ctx, bufName, target);
+ ctx->Driver.BufferData(ctx, target, size, NULL, usage, exec->vtx.bufferobj);
+}
+
+
+
+void vbo_exec_vtx_init( struct vbo_exec_context *exec )
+{
+ struct gl_context *ctx = exec->ctx;
+ struct vbo_context *vbo = vbo_context(ctx);
+ GLuint i;
+
+ /* Allocate a buffer object. Will just reuse this object
+ * continuously, unless vbo_use_buffer_objects() is called to enable
+ * use of real VBOs.
+ */
+ _mesa_reference_buffer_object(ctx,
+ &exec->vtx.bufferobj,
+ ctx->Shared->NullBufferObj);
+
+ ASSERT(!exec->vtx.buffer_map);
+ exec->vtx.buffer_map = (GLfloat *)_mesa_align_malloc(VBO_VERT_BUFFER_SIZE, 64);
+ exec->vtx.buffer_ptr = exec->vtx.buffer_map;
+
+ vbo_exec_vtxfmt_init( exec );
+
+ /* Hook our functions into the dispatch table.
+ */
+ _mesa_install_exec_vtxfmt( exec->ctx, &exec->vtxfmt );
+
+ for (i = 0 ; i < VBO_ATTRIB_MAX ; i++) {
+ ASSERT(i < Elements(exec->vtx.attrsz));
+ exec->vtx.attrsz[i] = 0;
+ ASSERT(i < Elements(exec->vtx.active_sz));
+ exec->vtx.active_sz[i] = 0;
+ }
+ for (i = 0 ; i < VERT_ATTRIB_MAX; i++) {
+ ASSERT(i < Elements(exec->vtx.inputs));
+ ASSERT(i < Elements(exec->vtx.arrays));
+ exec->vtx.inputs[i] = &exec->vtx.arrays[i];
+ }
+
+ {
+ struct gl_client_array *arrays = exec->vtx.arrays;
+ unsigned i;
+
+ memcpy(arrays, vbo->legacy_currval, 16 * sizeof(arrays[0]));
+ memcpy(arrays + 16, vbo->generic_currval, 16 * sizeof(arrays[0]));
+
+ for (i = 0; i < 16; ++i) {
+ arrays[i ].BufferObj = NULL;
+ arrays[i + 16].BufferObj = NULL;
+ _mesa_reference_buffer_object(ctx, &arrays[i ].BufferObj,
+ vbo->legacy_currval[i].BufferObj);
+ _mesa_reference_buffer_object(ctx, &arrays[i + 16].BufferObj,
+ vbo->generic_currval[i].BufferObj);
+ }
+ }
+
+ exec->vtx.vertex_size = 0;
+}
+
+
+void vbo_exec_vtx_destroy( struct vbo_exec_context *exec )
+{
+ /* using a real VBO for vertex data */
+ struct gl_context *ctx = exec->ctx;
+ unsigned i;
+
+ /* True VBOs should already be unmapped
+ */
+ if (exec->vtx.buffer_map) {
+ ASSERT(exec->vtx.bufferobj->Name == 0 ||
+ exec->vtx.bufferobj->Name == IMM_BUFFER_NAME);
+ if (exec->vtx.bufferobj->Name == 0) {
+ _mesa_align_free(exec->vtx.buffer_map);
+ exec->vtx.buffer_map = NULL;
+ exec->vtx.buffer_ptr = NULL;
+ }
+ }
+
+ /* Drop any outstanding reference to the vertex buffer
+ */
+ for (i = 0; i < Elements(exec->vtx.arrays); i++) {
+ _mesa_reference_buffer_object(ctx,
+ &exec->vtx.arrays[i].BufferObj,
+ NULL);
+ }
+
+ /* Free the vertex buffer. Unmap first if needed.
+ */
+ if (_mesa_bufferobj_mapped(exec->vtx.bufferobj)) {
+ ctx->Driver.UnmapBuffer(ctx, GL_ARRAY_BUFFER, exec->vtx.bufferobj);
+ }
+ _mesa_reference_buffer_object(ctx, &exec->vtx.bufferobj, NULL);
+}
+
+void vbo_exec_BeginVertices( struct gl_context *ctx )
+{
+ struct vbo_exec_context *exec = &vbo_context(ctx)->exec;
+ if (0) printf("%s\n", __FUNCTION__);
+ vbo_exec_vtx_map( exec );
+
+ assert((exec->ctx->Driver.NeedFlush & FLUSH_UPDATE_CURRENT) == 0);
+ exec->ctx->Driver.NeedFlush |= FLUSH_UPDATE_CURRENT;
+}
+
+void vbo_exec_FlushVertices_internal( struct gl_context *ctx, GLboolean unmap )
+{
+ struct vbo_exec_context *exec = &vbo_context(ctx)->exec;
+
+ if (exec->vtx.vert_count || unmap) {
+ vbo_exec_vtx_flush( exec, unmap );
+ }
+
+ if (exec->vtx.vertex_size) {
+ vbo_exec_copy_to_current( exec );
+ reset_attrfv( exec );
+ }
+}
+
+
+/**
+ * \param flags bitmask of FLUSH_STORED_VERTICES, FLUSH_UPDATE_CURRENT
+ */
+void vbo_exec_FlushVertices( struct gl_context *ctx, GLuint flags )
+{
+ struct vbo_exec_context *exec = &vbo_context(ctx)->exec;
+
+#ifdef DEBUG
+ /* debug check: make sure we don't get called recursively */
+ exec->flush_call_depth++;
+ assert(exec->flush_call_depth == 1);
+#endif
+
+ if (0) printf("%s\n", __FUNCTION__);
+
+ if (exec->ctx->Driver.CurrentExecPrimitive != PRIM_OUTSIDE_BEGIN_END) {
+ if (0) printf("%s - inside begin/end\n", __FUNCTION__);
+#ifdef DEBUG
+ exec->flush_call_depth--;
+ assert(exec->flush_call_depth == 0);
+#endif
+ return;
+ }
+
+ vbo_exec_FlushVertices_internal( ctx, GL_TRUE );
+
+ /* Need to do this to ensure BeginVertices gets called again:
+ */
+ if (exec->ctx->Driver.NeedFlush & FLUSH_UPDATE_CURRENT)
+ exec->ctx->Driver.NeedFlush &= ~FLUSH_UPDATE_CURRENT;
+
+ exec->ctx->Driver.NeedFlush &= ~flags;
+
+#ifdef DEBUG
+ exec->flush_call_depth--;
+ assert(exec->flush_call_depth == 0);
+#endif
+}
+
+
+static void reset_attrfv( struct vbo_exec_context *exec )
+{
+ GLuint i;
+
+ for (i = 0 ; i < VBO_ATTRIB_MAX ; i++) {
+ exec->vtx.attrsz[i] = 0;
+ exec->vtx.active_sz[i] = 0;
+ }
+
+ exec->vtx.vertex_size = 0;
+}
+
+
+void GLAPIENTRY
+_es_Color4f(GLfloat r, GLfloat g, GLfloat b, GLfloat a)
+{
+ vbo_Color4f(r, g, b, a);
+}
+
+
+void GLAPIENTRY
+_es_Normal3f(GLfloat x, GLfloat y, GLfloat z)
+{
+ vbo_Normal3f(x, y, z);
+}
+
+
+void GLAPIENTRY
+_es_MultiTexCoord4f(GLenum target, GLfloat s, GLfloat t, GLfloat r, GLfloat q)
+{
+ vbo_MultiTexCoord4f(target, s, t, r, q);
+}
+
+
+void GLAPIENTRY
+_es_Materialfv(GLenum face, GLenum pname, const GLfloat *params)
+{
+ vbo_Materialfv(face, pname, params);
+}
+
+
+void GLAPIENTRY
+_es_Materialf(GLenum face, GLenum pname, GLfloat param)
+{
+ GLfloat p[4];
+ p[0] = param;
+ p[1] = p[2] = p[3] = 0.0F;
+ vbo_Materialfv(face, pname, p);
+}
+
+
+/**
+ * A special version of glVertexAttrib4f that does not treat index 0 as
+ * VBO_ATTRIB_POS.
+ */
+static void
+VertexAttrib4f_nopos(GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ if (index < MAX_VERTEX_GENERIC_ATTRIBS)
+ ATTR(VBO_ATTRIB_GENERIC0 + index, 4, x, y, z, w);
+ else
+ ERROR();
+}
+
+void GLAPIENTRY
+_es_VertexAttrib4f(GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w)
+{
+ VertexAttrib4f_nopos(index, x, y, z, w);
+}
+
+
+void GLAPIENTRY
+_es_VertexAttrib1f(GLuint indx, GLfloat x)
+{
+ VertexAttrib4f_nopos(indx, x, 0.0f, 0.0f, 1.0f);
+}
+
+
+void GLAPIENTRY
+_es_VertexAttrib1fv(GLuint indx, const GLfloat* values)
+{
+ VertexAttrib4f_nopos(indx, values[0], 0.0f, 0.0f, 1.0f);
+}
+
+
+void GLAPIENTRY
+_es_VertexAttrib2f(GLuint indx, GLfloat x, GLfloat y)
+{
+ VertexAttrib4f_nopos(indx, x, y, 0.0f, 1.0f);
+}
+
+
+void GLAPIENTRY
+_es_VertexAttrib2fv(GLuint indx, const GLfloat* values)
+{
+ VertexAttrib4f_nopos(indx, values[0], values[1], 0.0f, 1.0f);
+}
+
+
+void GLAPIENTRY
+_es_VertexAttrib3f(GLuint indx, GLfloat x, GLfloat y, GLfloat z)
+{
+ VertexAttrib4f_nopos(indx, x, y, z, 1.0f);
+}
+
+
+void GLAPIENTRY
+_es_VertexAttrib3fv(GLuint indx, const GLfloat* values)
+{
+ VertexAttrib4f_nopos(indx, values[0], values[1], values[2], 1.0f);
+}
+
+
+void GLAPIENTRY
+_es_VertexAttrib4fv(GLuint indx, const GLfloat* values)
+{
+ VertexAttrib4f_nopos(indx, values[0], values[1], values[2], values[3]);
+}
diff --git a/mesalib/src/mesa/vbo/vbo_exec_array.c b/mesalib/src/mesa/vbo/vbo_exec_array.c
index 1759e5788..5b3a06f3b 100644
--- a/mesalib/src/mesa/vbo/vbo_exec_array.c
+++ b/mesalib/src/mesa/vbo/vbo_exec_array.c
@@ -1,1213 +1,1277 @@
-/**************************************************************************
- *
- * Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas.
- * Copyright 2009 VMware, Inc.
- * All Rights Reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the
- * "Software"), to deal in the Software without restriction, including
- * without limitation the rights to use, copy, modify, merge, publish,
- * distribute, sub license, and/or sell copies of the Software, and to
- * permit persons to whom the Software is furnished to do so, subject to
- * the following conditions:
- *
- * The above copyright notice and this permission notice (including the
- * next paragraph) shall be included in all copies or substantial portions
- * of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
- * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
- * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
- * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
- * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- *
- **************************************************************************/
-
-#include "main/glheader.h"
-#include "main/context.h"
-#include "main/state.h"
-#include "main/api_validate.h"
-#include "main/varray.h"
-#include "main/bufferobj.h"
-#include "main/enums.h"
-#include "main/macros.h"
-
-#include "vbo_context.h"
-
-
-/**
- * Compute min and max elements by scanning the index buffer for
- * glDraw[Range]Elements() calls.
- */
-void
-vbo_get_minmax_index(GLcontext *ctx,
- const struct _mesa_prim *prim,
- const struct _mesa_index_buffer *ib,
- GLuint *min_index, GLuint *max_index)
-{
- GLuint i;
- GLuint count = prim->count;
- const void *indices;
-
- if (_mesa_is_bufferobj(ib->obj)) {
- const GLvoid *map =
- ctx->Driver.MapBuffer(ctx, GL_ELEMENT_ARRAY_BUFFER_ARB,
- GL_READ_ONLY, ib->obj);
- indices = ADD_POINTERS(map, ib->ptr);
- } else {
- indices = ib->ptr;
- }
-
- switch (ib->type) {
- case GL_UNSIGNED_INT: {
- const GLuint *ui_indices = (const GLuint *)indices;
- GLuint max_ui = ui_indices[count-1];
- GLuint min_ui = ui_indices[0];
- for (i = 0; i < count; i++) {
- if (ui_indices[i] > max_ui) max_ui = ui_indices[i];
- if (ui_indices[i] < min_ui) min_ui = ui_indices[i];
- }
- *min_index = min_ui;
- *max_index = max_ui;
- break;
- }
- case GL_UNSIGNED_SHORT: {
- const GLushort *us_indices = (const GLushort *)indices;
- GLuint max_us = us_indices[count-1];
- GLuint min_us = us_indices[0];
- for (i = 0; i < count; i++) {
- if (us_indices[i] > max_us) max_us = us_indices[i];
- if (us_indices[i] < min_us) min_us = us_indices[i];
- }
- *min_index = min_us;
- *max_index = max_us;
- break;
- }
- case GL_UNSIGNED_BYTE: {
- const GLubyte *ub_indices = (const GLubyte *)indices;
- GLuint max_ub = ub_indices[count-1];
- GLuint min_ub = ub_indices[0];
- for (i = 0; i < count; i++) {
- if (ub_indices[i] > max_ub) max_ub = ub_indices[i];
- if (ub_indices[i] < min_ub) min_ub = ub_indices[i];
- }
- *min_index = min_ub;
- *max_index = max_ub;
- break;
- }
- default:
- assert(0);
- break;
- }
-
- if (_mesa_is_bufferobj(ib->obj)) {
- ctx->Driver.UnmapBuffer(ctx, GL_ELEMENT_ARRAY_BUFFER_ARB, ib->obj);
- }
-}
-
-
-/**
- * Check that element 'j' of the array has reasonable data.
- * Map VBO if needed.
- * For debugging purposes; not normally used.
- */
-static void
-check_array_data(GLcontext *ctx, struct gl_client_array *array,
- GLuint attrib, GLuint j)
-{
- if (array->Enabled) {
- const void *data = array->Ptr;
- if (_mesa_is_bufferobj(array->BufferObj)) {
- if (!array->BufferObj->Pointer) {
- /* need to map now */
- array->BufferObj->Pointer =
- ctx->Driver.MapBuffer(ctx, GL_ARRAY_BUFFER_ARB,
- GL_READ_ONLY, array->BufferObj);
- }
- data = ADD_POINTERS(data, array->BufferObj->Pointer);
- }
- switch (array->Type) {
- case GL_FLOAT:
- {
- GLfloat *f = (GLfloat *) ((GLubyte *) data + array->StrideB * j);
- GLint k;
- for (k = 0; k < array->Size; k++) {
- if (IS_INF_OR_NAN(f[k]) ||
- f[k] >= 1.0e20 || f[k] <= -1.0e10) {
- printf("Bad array data:\n");
- printf(" Element[%u].%u = %f\n", j, k, f[k]);
- printf(" Array %u at %p\n", attrib, (void* ) array);
- printf(" Type 0x%x, Size %d, Stride %d\n",
- array->Type, array->Size, array->Stride);
- printf(" Address/offset %p in Buffer Object %u\n",
- array->Ptr, array->BufferObj->Name);
- f[k] = 1.0; /* XXX replace the bad value! */
- }
- /*assert(!IS_INF_OR_NAN(f[k]));*/
- }
- }
- break;
- default:
- ;
- }
- }
-}
-
-
-/**
- * Unmap the buffer object referenced by given array, if mapped.
- */
-static void
-unmap_array_buffer(GLcontext *ctx, struct gl_client_array *array)
-{
- if (array->Enabled &&
- _mesa_is_bufferobj(array->BufferObj) &&
- _mesa_bufferobj_mapped(array->BufferObj)) {
- ctx->Driver.UnmapBuffer(ctx, GL_ARRAY_BUFFER_ARB, array->BufferObj);
- }
-}
-
-
-/**
- * Examine the array's data for NaNs, etc.
- * For debug purposes; not normally used.
- */
-static void
-check_draw_elements_data(GLcontext *ctx, GLsizei count, GLenum elemType,
- const void *elements, GLint basevertex)
-{
- struct gl_array_object *arrayObj = ctx->Array.ArrayObj;
- const void *elemMap;
- GLint i, k;
-
- if (_mesa_is_bufferobj(ctx->Array.ElementArrayBufferObj)) {
- elemMap = ctx->Driver.MapBuffer(ctx,
- GL_ELEMENT_ARRAY_BUFFER_ARB,
- GL_READ_ONLY,
- ctx->Array.ElementArrayBufferObj);
- elements = ADD_POINTERS(elements, elemMap);
- }
-
- for (i = 0; i < count; i++) {
- GLuint j;
-
- /* j = element[i] */
- switch (elemType) {
- case GL_UNSIGNED_BYTE:
- j = ((const GLubyte *) elements)[i];
- break;
- case GL_UNSIGNED_SHORT:
- j = ((const GLushort *) elements)[i];
- break;
- case GL_UNSIGNED_INT:
- j = ((const GLuint *) elements)[i];
- break;
- default:
- assert(0);
- }
-
- /* check element j of each enabled array */
- check_array_data(ctx, &arrayObj->Vertex, VERT_ATTRIB_POS, j);
- check_array_data(ctx, &arrayObj->Normal, VERT_ATTRIB_NORMAL, j);
- check_array_data(ctx, &arrayObj->Color, VERT_ATTRIB_COLOR0, j);
- check_array_data(ctx, &arrayObj->SecondaryColor, VERT_ATTRIB_COLOR1, j);
- for (k = 0; k < Elements(arrayObj->TexCoord); k++) {
- check_array_data(ctx, &arrayObj->TexCoord[k], VERT_ATTRIB_TEX0 + k, j);
- }
- for (k = 0; k < Elements(arrayObj->VertexAttrib); k++) {
- check_array_data(ctx, &arrayObj->VertexAttrib[k],
- VERT_ATTRIB_GENERIC0 + k, j);
- }
- }
-
- if (_mesa_is_bufferobj(ctx->Array.ElementArrayBufferObj)) {
- ctx->Driver.UnmapBuffer(ctx, GL_ELEMENT_ARRAY_BUFFER_ARB,
- ctx->Array.ElementArrayBufferObj);
- }
-
- unmap_array_buffer(ctx, &arrayObj->Vertex);
- unmap_array_buffer(ctx, &arrayObj->Normal);
- unmap_array_buffer(ctx, &arrayObj->Color);
- for (k = 0; k < Elements(arrayObj->TexCoord); k++) {
- unmap_array_buffer(ctx, &arrayObj->TexCoord[k]);
- }
- for (k = 0; k < Elements(arrayObj->VertexAttrib); k++) {
- unmap_array_buffer(ctx, &arrayObj->VertexAttrib[k]);
- }
-}
-
-
-/**
- * Check array data, looking for NaNs, etc.
- */
-static void
-check_draw_arrays_data(GLcontext *ctx, GLint start, GLsizei count)
-{
- /* TO DO */
-}
-
-
-/**
- * Print info/data for glDrawArrays(), for debugging.
- */
-static void
-print_draw_arrays(GLcontext *ctx, struct vbo_exec_context *exec,
- GLenum mode, GLint start, GLsizei count)
-{
- int i;
-
- printf("vbo_exec_DrawArrays(mode 0x%x, start %d, count %d):\n",
- mode, start, count);
-
- for (i = 0; i < 32; i++) {
- GLuint bufName = exec->array.inputs[i]->BufferObj->Name;
- GLint stride = exec->array.inputs[i]->Stride;
- printf("attr %2d: size %d stride %d enabled %d "
- "ptr %p Bufobj %u\n",
- i,
- exec->array.inputs[i]->Size,
- stride,
- /*exec->array.inputs[i]->Enabled,*/
- exec->array.legacy_array[i]->Enabled,
- exec->array.inputs[i]->Ptr,
- bufName);
-
- if (bufName) {
- struct gl_buffer_object *buf = _mesa_lookup_bufferobj(ctx, bufName);
- GLubyte *p = ctx->Driver.MapBuffer(ctx, GL_ARRAY_BUFFER_ARB,
- GL_READ_ONLY_ARB, buf);
- int offset = (int) (GLintptr) exec->array.inputs[i]->Ptr;
- float *f = (float *) (p + offset);
- int *k = (int *) f;
- int i;
- int n = (count * stride) / 4;
- if (n > 32)
- n = 32;
- printf(" Data at offset %d:\n", offset);
- for (i = 0; i < n; i++) {
- printf(" float[%d] = 0x%08x %f\n", i, k[i], f[i]);
- }
- ctx->Driver.UnmapBuffer(ctx, GL_ARRAY_BUFFER_ARB, buf);
- }
- }
-}
-
-
-/**
- * Bind the VBO executor to the current vertex array object prior
- * to drawing.
- *
- * Just translate the arrayobj into a sane layout.
- */
-static void
-bind_array_obj(GLcontext *ctx)
-{
- struct vbo_context *vbo = vbo_context(ctx);
- struct vbo_exec_context *exec = &vbo->exec;
- struct gl_array_object *arrayObj = ctx->Array.ArrayObj;
- GLuint i;
-
- /* TODO: Fix the ArrayObj struct to keep legacy arrays in an array
- * rather than as individual named arrays. Then this function can
- * go away.
- */
- exec->array.legacy_array[VERT_ATTRIB_POS] = &arrayObj->Vertex;
- exec->array.legacy_array[VERT_ATTRIB_WEIGHT] = &arrayObj->Weight;
- exec->array.legacy_array[VERT_ATTRIB_NORMAL] = &arrayObj->Normal;
- exec->array.legacy_array[VERT_ATTRIB_COLOR0] = &arrayObj->Color;
- exec->array.legacy_array[VERT_ATTRIB_COLOR1] = &arrayObj->SecondaryColor;
- exec->array.legacy_array[VERT_ATTRIB_FOG] = &arrayObj->FogCoord;
- exec->array.legacy_array[VERT_ATTRIB_COLOR_INDEX] = &arrayObj->Index;
- if (arrayObj->PointSize.Enabled) {
- /* this aliases COLOR_INDEX */
- exec->array.legacy_array[VERT_ATTRIB_POINT_SIZE] = &arrayObj->PointSize;
- }
- exec->array.legacy_array[VERT_ATTRIB_EDGEFLAG] = &arrayObj->EdgeFlag;
-
- for (i = 0; i < Elements(arrayObj->TexCoord); i++)
- exec->array.legacy_array[VERT_ATTRIB_TEX0 + i] = &arrayObj->TexCoord[i];
-
- for (i = 0; i < Elements(arrayObj->VertexAttrib); i++) {
- assert(i < Elements(exec->array.generic_array));
- exec->array.generic_array[i] = &arrayObj->VertexAttrib[i];
- }
-
- exec->array.array_obj = arrayObj->Name;
-}
-
-
-/**
- * Set the vbo->exec->inputs[] pointers to point to the enabled
- * vertex arrays. This depends on the current vertex program/shader
- * being executed because of whether or not generic vertex arrays
- * alias the conventional vertex arrays.
- * For arrays that aren't enabled, we set the input[attrib] pointer
- * to point at a zero-stride current value "array".
- */
-static void
-recalculate_input_bindings(GLcontext *ctx)
-{
- struct vbo_context *vbo = vbo_context(ctx);
- struct vbo_exec_context *exec = &vbo->exec;
- const struct gl_client_array **inputs = &exec->array.inputs[0];
- GLbitfield const_inputs = 0x0;
- GLuint i;
-
- exec->array.program_mode = get_program_mode(ctx);
- exec->array.enabled_flags = ctx->Array.ArrayObj->_Enabled;
-
- switch (exec->array.program_mode) {
- case VP_NONE:
- /* When no vertex program is active (or the vertex program is generated
- * from fixed-function state). We put the material values into the
- * generic slots. This is the only situation where material values
- * are available as per-vertex attributes.
- */
- for (i = 0; i <= VERT_ATTRIB_TEX7; i++) {
- if (exec->array.legacy_array[i]->Enabled)
- inputs[i] = exec->array.legacy_array[i];
- else {
- inputs[i] = &vbo->legacy_currval[i];
- const_inputs |= 1 << i;
- }
- }
-
- for (i = 0; i < MAT_ATTRIB_MAX; i++) {
- inputs[VERT_ATTRIB_GENERIC0 + i] = &vbo->mat_currval[i];
- const_inputs |= 1 << (VERT_ATTRIB_GENERIC0 + i);
- }
-
- /* Could use just about anything, just to fill in the empty
- * slots:
- */
- for (i = MAT_ATTRIB_MAX; i < VERT_ATTRIB_MAX - VERT_ATTRIB_GENERIC0; i++) {
- inputs[VERT_ATTRIB_GENERIC0 + i] = &vbo->generic_currval[i];
- const_inputs |= 1 << (VERT_ATTRIB_GENERIC0 + i);
- }
- break;
-
- case VP_NV:
- /* NV_vertex_program - attribute arrays alias and override
- * conventional, legacy arrays. No materials, and the generic
- * slots are vacant.
- */
- for (i = 0; i <= VERT_ATTRIB_TEX7; i++) {
- if (exec->array.generic_array[i]->Enabled)
- inputs[i] = exec->array.generic_array[i];
- else if (exec->array.legacy_array[i]->Enabled)
- inputs[i] = exec->array.legacy_array[i];
- else {
- inputs[i] = &vbo->legacy_currval[i];
- const_inputs |= 1 << i;
- }
- }
-
- /* Could use just about anything, just to fill in the empty
- * slots:
- */
- for (i = VERT_ATTRIB_GENERIC0; i < VERT_ATTRIB_MAX; i++) {
- inputs[i] = &vbo->generic_currval[i - VERT_ATTRIB_GENERIC0];
- const_inputs |= 1 << i;
- }
- break;
-
- case VP_ARB:
- /* GL_ARB_vertex_program or GLSL vertex shader - Only the generic[0]
- * attribute array aliases and overrides the legacy position array.
- *
- * Otherwise, legacy attributes available in the legacy slots,
- * generic attributes in the generic slots and materials are not
- * available as per-vertex attributes.
- */
- if (exec->array.generic_array[0]->Enabled)
- inputs[0] = exec->array.generic_array[0];
- else if (exec->array.legacy_array[0]->Enabled)
- inputs[0] = exec->array.legacy_array[0];
- else {
- inputs[0] = &vbo->legacy_currval[0];
- const_inputs |= 1 << 0;
- }
-
- for (i = 1; i <= VERT_ATTRIB_TEX7; i++) {
- if (exec->array.legacy_array[i]->Enabled)
- inputs[i] = exec->array.legacy_array[i];
- else {
- inputs[i] = &vbo->legacy_currval[i];
- const_inputs |= 1 << i;
- }
- }
-
- for (i = 0; i < MAX_VERTEX_GENERIC_ATTRIBS; i++) {
- if (exec->array.generic_array[i]->Enabled)
- inputs[VERT_ATTRIB_GENERIC0 + i] = exec->array.generic_array[i];
- else {
- inputs[VERT_ATTRIB_GENERIC0 + i] = &vbo->generic_currval[i];
- const_inputs |= 1 << (VERT_ATTRIB_GENERIC0 + i);
- }
-
- }
- break;
- }
-
- _mesa_set_varying_vp_inputs( ctx, ~const_inputs );
-}
-
-
-/**
- * Examine the enabled vertex arrays to set the exec->array.inputs[] values.
- * These will point to the arrays to actually use for drawing. Some will
- * be user-provided arrays, other will be zero-stride const-valued arrays.
- * Note that this might set the _NEW_ARRAY dirty flag so state validation
- * must be done after this call.
- */
-static void
-bind_arrays(GLcontext *ctx)
-{
- bind_array_obj(ctx);
- recalculate_input_bindings(ctx);
-}
-
-
-
-/**
- * Called from glDrawArrays when in immediate mode (not display list mode).
- */
-static void GLAPIENTRY
-vbo_exec_DrawArrays(GLenum mode, GLint start, GLsizei count)
-{
- GET_CURRENT_CONTEXT(ctx);
- struct vbo_context *vbo = vbo_context(ctx);
- struct vbo_exec_context *exec = &vbo->exec;
- struct _mesa_prim prim[1];
-
- if (MESA_VERBOSE & VERBOSE_DRAW)
- _mesa_debug(ctx, "glDrawArrays(%s, %d, %d)\n",
- _mesa_lookup_enum_by_nr(mode), start, count);
-
- if (!_mesa_validate_DrawArrays( ctx, mode, start, count ))
- return;
-
- FLUSH_CURRENT( ctx, 0 );
-
- if (!_mesa_valid_to_render(ctx, "glDrawArrays")) {
- return;
- }
-
-#if 0
- check_draw_arrays_data(ctx, start, count);
-#else
- (void) check_draw_arrays_data;
-#endif
-
- bind_arrays( ctx );
-
- /* Again... because we may have changed the bitmask of per-vertex varying
- * attributes. If we regenerate the fixed-function vertex program now
- * we may be able to prune down the number of vertex attributes which we
- * need in the shader.
- */
- if (ctx->NewState)
- _mesa_update_state( ctx );
-
- prim[0].begin = 1;
- prim[0].end = 1;
- prim[0].weak = 0;
- prim[0].pad = 0;
- prim[0].mode = mode;
- prim[0].start = start;
- prim[0].count = count;
- prim[0].indexed = 0;
- prim[0].basevertex = 0;
- prim[0].num_instances = 1;
-
- vbo->draw_prims( ctx, exec->array.inputs, prim, 1, NULL,
- GL_TRUE, start, start + count - 1 );
-
-#if 0
- print_draw_arrays(ctx, exec, mode, start, count);
-#else
- (void) print_draw_arrays;
-#endif
-}
-
-
-/**
- * Called from glDrawArraysInstanced when in immediate mode (not
- * display list mode).
- */
-static void GLAPIENTRY
-vbo_exec_DrawArraysInstanced(GLenum mode, GLint start, GLsizei count,
- GLsizei primcount)
-{
- GET_CURRENT_CONTEXT(ctx);
- struct vbo_context *vbo = vbo_context(ctx);
- struct vbo_exec_context *exec = &vbo->exec;
- struct _mesa_prim prim[1];
-
- if (MESA_VERBOSE & VERBOSE_DRAW)
- _mesa_debug(ctx, "glDrawArraysInstanced(%s, %d, %d, %d)\n",
- _mesa_lookup_enum_by_nr(mode), start, count, primcount);
-
- if (!_mesa_validate_DrawArraysInstanced(ctx, mode, start, count, primcount))
- return;
-
- FLUSH_CURRENT( ctx, 0 );
-
- if (!_mesa_valid_to_render(ctx, "glDrawArraysInstanced")) {
- return;
- }
-
-#if 0 /* debug */
- check_draw_arrays_data(ctx, start, count);
-#endif
-
- bind_arrays( ctx );
-
- /* Again... because we may have changed the bitmask of per-vertex varying
- * attributes. If we regenerate the fixed-function vertex program now
- * we may be able to prune down the number of vertex attributes which we
- * need in the shader.
- */
- if (ctx->NewState)
- _mesa_update_state( ctx );
-
- prim[0].begin = 1;
- prim[0].end = 1;
- prim[0].weak = 0;
- prim[0].pad = 0;
- prim[0].mode = mode;
- prim[0].start = start;
- prim[0].count = count;
- prim[0].indexed = 0;
- prim[0].basevertex = 0;
- prim[0].num_instances = primcount;
-
- vbo->draw_prims( ctx, exec->array.inputs, prim, 1, NULL,
- GL_TRUE, start, start + count - 1 );
-
-#if 0 /* debug */
- print_draw_arrays(ctx, exec, mode, start, count);
-#endif
-}
-
-
-/**
- * Map GL_ELEMENT_ARRAY_BUFFER and print contents.
- * For debugging.
- */
-static void
-dump_element_buffer(GLcontext *ctx, GLenum type)
-{
- const GLvoid *map = ctx->Driver.MapBuffer(ctx,
- GL_ELEMENT_ARRAY_BUFFER_ARB,
- GL_READ_ONLY,
- ctx->Array.ElementArrayBufferObj);
- switch (type) {
- case GL_UNSIGNED_BYTE:
- {
- const GLubyte *us = (const GLubyte *) map;
- GLint i;
- for (i = 0; i < ctx->Array.ElementArrayBufferObj->Size; i++) {
- printf("%02x ", us[i]);
- if (i % 32 == 31)
- printf("\n");
- }
- printf("\n");
- }
- break;
- case GL_UNSIGNED_SHORT:
- {
- const GLushort *us = (const GLushort *) map;
- GLint i;
- for (i = 0; i < ctx->Array.ElementArrayBufferObj->Size / 2; i++) {
- printf("%04x ", us[i]);
- if (i % 16 == 15)
- printf("\n");
- }
- printf("\n");
- }
- break;
- case GL_UNSIGNED_INT:
- {
- const GLuint *us = (const GLuint *) map;
- GLint i;
- for (i = 0; i < ctx->Array.ElementArrayBufferObj->Size / 4; i++) {
- printf("%08x ", us[i]);
- if (i % 8 == 7)
- printf("\n");
- }
- printf("\n");
- }
- break;
- default:
- ;
- }
-
- ctx->Driver.UnmapBuffer(ctx, GL_ELEMENT_ARRAY_BUFFER_ARB,
- ctx->Array.ElementArrayBufferObj);
-}
-
-
-/**
- * Inner support for both _mesa_DrawElements and _mesa_DrawRangeElements.
- * Do the rendering for a glDrawElements or glDrawRangeElements call after
- * we've validated buffer bounds, etc.
- */
-static void
-vbo_validated_drawrangeelements(GLcontext *ctx, GLenum mode,
- GLboolean index_bounds_valid,
- GLuint start, GLuint end,
- GLsizei count, GLenum type,
- const GLvoid *indices,
- GLint basevertex, GLint primcount)
-{
- struct vbo_context *vbo = vbo_context(ctx);
- struct vbo_exec_context *exec = &vbo->exec;
- struct _mesa_index_buffer ib;
- struct _mesa_prim prim[1];
-
- FLUSH_CURRENT( ctx, 0 );
-
- if (!_mesa_valid_to_render(ctx, "glDraw[Range]Elements")) {
- return;
- }
-
- bind_arrays( ctx );
-
- /* check for dirty state again */
- if (ctx->NewState)
- _mesa_update_state( ctx );
-
- ib.count = count;
- ib.type = type;
- ib.obj = ctx->Array.ElementArrayBufferObj;
- ib.ptr = indices;
-
- prim[0].begin = 1;
- prim[0].end = 1;
- prim[0].weak = 0;
- prim[0].pad = 0;
- prim[0].mode = mode;
- prim[0].start = 0;
- prim[0].count = count;
- prim[0].indexed = 1;
- prim[0].basevertex = basevertex;
- prim[0].num_instances = primcount;
-
- /* Need to give special consideration to rendering a range of
- * indices starting somewhere above zero. Typically the
- * application is issuing multiple DrawRangeElements() to draw
- * successive primitives layed out linearly in the vertex arrays.
- * Unless the vertex arrays are all in a VBO (or locked as with
- * CVA), the OpenGL semantics imply that we need to re-read or
- * re-upload the vertex data on each draw call.
- *
- * In the case of hardware tnl, we want to avoid starting the
- * upload at zero, as it will mean every draw call uploads an
- * increasing amount of not-used vertex data. Worse - in the
- * software tnl module, all those vertices might be transformed and
- * lit but never rendered.
- *
- * If we just upload or transform the vertices in start..end,
- * however, the indices will be incorrect.
- *
- * At this level, we don't know exactly what the requirements of
- * the backend are going to be, though it will likely boil down to
- * either:
- *
- * 1) Do nothing, everything is in a VBO and is processed once
- * only.
- *
- * 2) Adjust the indices and vertex arrays so that start becomes
- * zero.
- *
- * Rather than doing anything here, I'll provide a helper function
- * for the latter case elsewhere.
- */
-
- vbo->draw_prims( ctx, exec->array.inputs, prim, 1, &ib,
- index_bounds_valid, start, end );
-}
-
-
-/**
- * Called by glDrawRangeElementsBaseVertex() in immediate mode.
- */
-static void GLAPIENTRY
-vbo_exec_DrawRangeElementsBaseVertex(GLenum mode,
- GLuint start, GLuint end,
- GLsizei count, GLenum type,
- const GLvoid *indices,
- GLint basevertex)
-{
- static GLuint warnCount = 0;
- GET_CURRENT_CONTEXT(ctx);
-
- if (MESA_VERBOSE & VERBOSE_DRAW)
- _mesa_debug(ctx,
- "glDrawRangeElementsBaseVertex(%s, %u, %u, %d, %s, %p, %d)\n",
- _mesa_lookup_enum_by_nr(mode), start, end, count,
- _mesa_lookup_enum_by_nr(type), indices, basevertex);
-
- if (!_mesa_validate_DrawRangeElements( ctx, mode, start, end, count,
- type, indices, basevertex ))
- return;
-
- /* NOTE: It's important that 'end' is a reasonable value.
- * in _tnl_draw_prims(), we use end to determine how many vertices
- * to transform. If it's too large, we can unnecessarily split prims
- * or we can read/write out of memory in several different places!
- */
-
- /* Catch/fix some potential user errors */
- if (type == GL_UNSIGNED_BYTE) {
- start = MIN2(start, 0xff);
- end = MIN2(end, 0xff);
- }
- else if (type == GL_UNSIGNED_SHORT) {
- start = MIN2(start, 0xffff);
- end = MIN2(end, 0xffff);
- }
-
- if (end >= ctx->Array.ArrayObj->_MaxElement) {
- /* the max element is out of bounds of one or more enabled arrays */
- warnCount++;
-
- if (warnCount < 10) {
- _mesa_warning(ctx, "glDraw[Range]Elements(start %u, end %u, count %d, "
- "type 0x%x, indices=%p)\n"
- "\tend is out of bounds (max=%u) "
- "Element Buffer %u (size %d)\n"
- "\tThis should probably be fixed in the application.",
- start, end, count, type, indices,
- ctx->Array.ArrayObj->_MaxElement - 1,
- ctx->Array.ElementArrayBufferObj->Name,
- (int) ctx->Array.ElementArrayBufferObj->Size);
- }
-
- if (0)
- dump_element_buffer(ctx, type);
-
- if (0)
- _mesa_print_arrays(ctx);
-
-#ifdef DEBUG
- /* 'end' was out of bounds, but now let's check the actual array
- * indexes to see if any of them are out of bounds.
- */
- {
- GLuint max = _mesa_max_buffer_index(ctx, count, type, indices,
- ctx->Array.ElementArrayBufferObj);
- if (max >= ctx->Array.ArrayObj->_MaxElement) {
- if (warnCount < 10) {
- _mesa_warning(ctx, "glDraw[Range]Elements(start %u, end %u, "
- "count %d, type 0x%x, indices=%p)\n"
- "\tindex=%u is out of bounds (max=%u) "
- "Element Buffer %u (size %d)\n"
- "\tSkipping the glDrawRangeElements() call",
- start, end, count, type, indices, max,
- ctx->Array.ArrayObj->_MaxElement - 1,
- ctx->Array.ElementArrayBufferObj->Name,
- (int) ctx->Array.ElementArrayBufferObj->Size);
- }
- }
- /* XXX we could also find the min index and compare to 'start'
- * to see if start is correct. But it's more likely to get the
- * upper bound wrong.
- */
- }
-#endif
-
- /* Set 'end' to the max possible legal value */
- assert(ctx->Array.ArrayObj->_MaxElement >= 1);
- end = ctx->Array.ArrayObj->_MaxElement - 1;
- }
- else if (0) {
- printf("glDraw[Range]Elements{,BaseVertex}"
- "(start %u, end %u, type 0x%x, count %d) ElemBuf %u, "
- "base %d\n",
- start, end, type, count,
- ctx->Array.ElementArrayBufferObj->Name,
- basevertex);
- }
-
-#if 0
- check_draw_elements_data(ctx, count, type, indices);
-#else
- (void) check_draw_elements_data;
-#endif
-
- vbo_validated_drawrangeelements(ctx, mode, GL_TRUE, start, end,
- count, type, indices, basevertex, 1);
-}
-
-
-/**
- * Called by glDrawRangeElements() in immediate mode.
- */
-static void GLAPIENTRY
-vbo_exec_DrawRangeElements(GLenum mode, GLuint start, GLuint end,
- GLsizei count, GLenum type, const GLvoid *indices)
-{
- GET_CURRENT_CONTEXT(ctx);
-
- if (MESA_VERBOSE & VERBOSE_DRAW)
- _mesa_debug(ctx,
- "glDrawRangeElements(%s, %u, %u, %d, %s, %p)\n",
- _mesa_lookup_enum_by_nr(mode), start, end, count,
- _mesa_lookup_enum_by_nr(type), indices);
-
- vbo_exec_DrawRangeElementsBaseVertex(mode, start, end, count, type,
- indices, 0);
-}
-
-
-/**
- * Called by glDrawElements() in immediate mode.
- */
-static void GLAPIENTRY
-vbo_exec_DrawElements(GLenum mode, GLsizei count, GLenum type,
- const GLvoid *indices)
-{
- GET_CURRENT_CONTEXT(ctx);
-
- if (MESA_VERBOSE & VERBOSE_DRAW)
- _mesa_debug(ctx, "glDrawElements(%s, %u, %s, %p)\n",
- _mesa_lookup_enum_by_nr(mode), count,
- _mesa_lookup_enum_by_nr(type), indices);
-
- if (!_mesa_validate_DrawElements( ctx, mode, count, type, indices, 0 ))
- return;
-
- vbo_validated_drawrangeelements(ctx, mode, GL_FALSE, ~0, ~0,
- count, type, indices, 0, 1);
-}
-
-
-/**
- * Called by glDrawElementsBaseVertex() in immediate mode.
- */
-static void GLAPIENTRY
-vbo_exec_DrawElementsBaseVertex(GLenum mode, GLsizei count, GLenum type,
- const GLvoid *indices, GLint basevertex)
-{
- GET_CURRENT_CONTEXT(ctx);
-
- if (MESA_VERBOSE & VERBOSE_DRAW)
- _mesa_debug(ctx, "glDrawElementsBaseVertex(%s, %d, %s, %p, %d)\n",
- _mesa_lookup_enum_by_nr(mode), count,
- _mesa_lookup_enum_by_nr(type), indices, basevertex);
-
- if (!_mesa_validate_DrawElements( ctx, mode, count, type, indices,
- basevertex ))
- return;
-
- vbo_validated_drawrangeelements(ctx, mode, GL_FALSE, ~0, ~0,
- count, type, indices, basevertex, 1);
-}
-
-
-/**
- * Called by glDrawElementsInstanced() in immediate mode.
- */
-static void GLAPIENTRY
-vbo_exec_DrawElementsInstanced(GLenum mode, GLsizei count, GLenum type,
- const GLvoid *indices, GLsizei primcount)
-{
- GET_CURRENT_CONTEXT(ctx);
-
- if (MESA_VERBOSE & VERBOSE_DRAW)
- _mesa_debug(ctx, "glDrawElementsInstanced(%s, %d, %s, %p, %d)\n",
- _mesa_lookup_enum_by_nr(mode), count,
- _mesa_lookup_enum_by_nr(type), indices, primcount);
-
- if (!_mesa_validate_DrawElementsInstanced(ctx, mode, count, type, indices,
- primcount))
- return;
-
- vbo_validated_drawrangeelements(ctx, mode, GL_FALSE, ~0, ~0,
- count, type, indices, 0, primcount);
-}
-
-
-/**
- * Inner support for both _mesa_MultiDrawElements() and
- * _mesa_MultiDrawRangeElements().
- * This does the actual rendering after we've checked array indexes, etc.
- */
-static void
-vbo_validated_multidrawelements(GLcontext *ctx, GLenum mode,
- const GLsizei *count, GLenum type,
- const GLvoid **indices, GLsizei primcount,
- const GLint *basevertex)
-{
- struct vbo_context *vbo = vbo_context(ctx);
- struct vbo_exec_context *exec = &vbo->exec;
- struct _mesa_index_buffer ib;
- struct _mesa_prim *prim;
- unsigned int index_type_size = 0;
- uintptr_t min_index_ptr, max_index_ptr;
- GLboolean fallback = GL_FALSE;
- int i;
-
- if (primcount == 0)
- return;
-
- FLUSH_CURRENT( ctx, 0 );
-
- if (!_mesa_valid_to_render(ctx, "glMultiDrawElements")) {
- return;
- }
-
- prim = calloc(1, primcount * sizeof(*prim));
- if (prim == NULL) {
- _mesa_error(ctx, GL_OUT_OF_MEMORY, "glMultiDrawElements");
- return;
- }
-
- /* Decide if we can do this all as one set of primitives sharing the
- * same index buffer, or if we have to reset the index pointer per
- * primitive.
- */
- bind_arrays( ctx );
-
- /* check for dirty state again */
- if (ctx->NewState)
- _mesa_update_state( ctx );
-
- switch (type) {
- case GL_UNSIGNED_INT:
- index_type_size = 4;
- break;
- case GL_UNSIGNED_SHORT:
- index_type_size = 2;
- break;
- case GL_UNSIGNED_BYTE:
- index_type_size = 1;
- break;
- default:
- assert(0);
- }
-
- min_index_ptr = (uintptr_t)indices[0];
- max_index_ptr = 0;
- for (i = 0; i < primcount; i++) {
- min_index_ptr = MIN2(min_index_ptr, (uintptr_t)indices[i]);
- max_index_ptr = MAX2(max_index_ptr, (uintptr_t)indices[i] +
- index_type_size * count[i]);
- }
-
- /* Check if we can handle this thing as a bunch of index offsets from the
- * same index pointer. If we can't, then we have to fall back to doing
- * a draw_prims per primitive.
- */
- if (index_type_size != 1) {
- for (i = 0; i < primcount; i++) {
- if ((((uintptr_t)indices[i] - min_index_ptr) % index_type_size) != 0) {
- fallback = GL_TRUE;
- break;
- }
- }
- }
-
- /* If the index buffer isn't in a VBO, then treating the application's
- * subranges of the index buffer as one large index buffer may lead to
- * us reading unmapped memory.
- */
- if (!_mesa_is_bufferobj(ctx->Array.ElementArrayBufferObj))
- fallback = GL_TRUE;
-
- if (!fallback) {
- ib.count = (max_index_ptr - min_index_ptr) / index_type_size;
- ib.type = type;
- ib.obj = ctx->Array.ElementArrayBufferObj;
- ib.ptr = (void *)min_index_ptr;
-
- for (i = 0; i < primcount; i++) {
- prim[i].begin = (i == 0);
- prim[i].end = (i == primcount - 1);
- prim[i].weak = 0;
- prim[i].pad = 0;
- prim[i].mode = mode;
- prim[i].start = ((uintptr_t)indices[i] - min_index_ptr) / index_type_size;
- prim[i].count = count[i];
- prim[i].indexed = 1;
- prim[i].num_instances = 1;
- if (basevertex != NULL)
- prim[i].basevertex = basevertex[i];
- else
- prim[i].basevertex = 0;
- }
-
- vbo->draw_prims(ctx, exec->array.inputs, prim, primcount, &ib,
- GL_FALSE, ~0, ~0);
- } else {
- /* render one prim at a time */
- for (i = 0; i < primcount; i++) {
- ib.count = count[i];
- ib.type = type;
- ib.obj = ctx->Array.ElementArrayBufferObj;
- ib.ptr = indices[i];
-
- prim[0].begin = 1;
- prim[0].end = 1;
- prim[0].weak = 0;
- prim[0].pad = 0;
- prim[0].mode = mode;
- prim[0].start = 0;
- prim[0].count = count[i];
- prim[0].indexed = 1;
- prim[0].num_instances = 1;
- if (basevertex != NULL)
- prim[0].basevertex = basevertex[i];
- else
- prim[0].basevertex = 0;
-
- vbo->draw_prims(ctx, exec->array.inputs, prim, 1, &ib,
- GL_FALSE, ~0, ~0);
- }
- }
-
- free(prim);
-}
-
-
-static void GLAPIENTRY
-vbo_exec_MultiDrawElements(GLenum mode,
- const GLsizei *count, GLenum type,
- const GLvoid **indices,
- GLsizei primcount)
-{
- GET_CURRENT_CONTEXT(ctx);
- GLint i;
-
- ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
-
- for (i = 0; i < primcount; i++) {
- if (!_mesa_validate_DrawElements(ctx, mode, count[i], type, indices[i],
- 0))
- return;
- }
-
- vbo_validated_multidrawelements(ctx, mode, count, type, indices, primcount,
- NULL);
-}
-
-
-static void GLAPIENTRY
-vbo_exec_MultiDrawElementsBaseVertex(GLenum mode,
- const GLsizei *count, GLenum type,
- const GLvoid **indices,
- GLsizei primcount,
- const GLsizei *basevertex)
-{
- GET_CURRENT_CONTEXT(ctx);
- GLint i;
-
- ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
-
- for (i = 0; i < primcount; i++) {
- if (!_mesa_validate_DrawElements(ctx, mode, count[i], type, indices[i],
- basevertex[i]))
- return;
- }
-
- vbo_validated_multidrawelements(ctx, mode, count, type, indices, primcount,
- basevertex);
-}
-
-
-/**
- * Plug in the immediate-mode vertex array drawing commands into the
- * givven vbo_exec_context object.
- */
-void
-vbo_exec_array_init( struct vbo_exec_context *exec )
-{
- exec->vtxfmt.DrawArrays = vbo_exec_DrawArrays;
- exec->vtxfmt.DrawElements = vbo_exec_DrawElements;
- exec->vtxfmt.DrawRangeElements = vbo_exec_DrawRangeElements;
- exec->vtxfmt.MultiDrawElementsEXT = vbo_exec_MultiDrawElements;
- exec->vtxfmt.DrawElementsBaseVertex = vbo_exec_DrawElementsBaseVertex;
- exec->vtxfmt.DrawRangeElementsBaseVertex = vbo_exec_DrawRangeElementsBaseVertex;
- exec->vtxfmt.MultiDrawElementsBaseVertex = vbo_exec_MultiDrawElementsBaseVertex;
- exec->vtxfmt.DrawArraysInstanced = vbo_exec_DrawArraysInstanced;
- exec->vtxfmt.DrawElementsInstanced = vbo_exec_DrawElementsInstanced;
-}
-
-
-void
-vbo_exec_array_destroy( struct vbo_exec_context *exec )
-{
- /* nothing to do */
-}
-
-
-
-/**
- * The following functions are only used for OpenGL ES 1/2 support.
- * And some aren't even supported (yet) in ES 1/2.
- */
-
-
-void GLAPIENTRY
-_mesa_DrawArrays(GLenum mode, GLint first, GLsizei count)
-{
- vbo_exec_DrawArrays(mode, first, count);
-}
-
-
-void GLAPIENTRY
-_mesa_DrawElements(GLenum mode, GLsizei count, GLenum type,
- const GLvoid *indices)
-{
- vbo_exec_DrawElements(mode, count, type, indices);
-}
-
-
-void GLAPIENTRY
-_mesa_DrawElementsBaseVertex(GLenum mode, GLsizei count, GLenum type,
- const GLvoid *indices, GLint basevertex)
-{
- vbo_exec_DrawElementsBaseVertex(mode, count, type, indices, basevertex);
-}
-
-
-void GLAPIENTRY
-_mesa_DrawRangeElements(GLenum mode, GLuint start, GLuint end, GLsizei count,
- GLenum type, const GLvoid *indices)
-{
- vbo_exec_DrawRangeElements(mode, start, end, count, type, indices);
-}
-
-
-void GLAPIENTRY
-_mesa_DrawRangeElementsBaseVertex(GLenum mode, GLuint start, GLuint end,
- GLsizei count, GLenum type,
- const GLvoid *indices, GLint basevertex)
-{
- vbo_exec_DrawRangeElementsBaseVertex(mode, start, end, count, type,
- indices, basevertex);
-}
-
-
-void GLAPIENTRY
-_mesa_MultiDrawElementsEXT(GLenum mode, const GLsizei *count, GLenum type,
- const GLvoid **indices, GLsizei primcount)
-{
- vbo_exec_MultiDrawElements(mode, count, type, indices, primcount);
-}
-
-
-void GLAPIENTRY
-_mesa_MultiDrawElementsBaseVertex(GLenum mode,
- const GLsizei *count, GLenum type,
- const GLvoid **indices, GLsizei primcount,
- const GLint *basevertex)
-{
- vbo_exec_MultiDrawElementsBaseVertex(mode, count, type, indices,
- primcount, basevertex);
-}
+/**************************************************************************
+ *
+ * Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * Copyright 2009 VMware, Inc.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+#include "main/glheader.h"
+#include "main/context.h"
+#include "main/state.h"
+#include "main/api_validate.h"
+#include "main/varray.h"
+#include "main/bufferobj.h"
+#include "main/enums.h"
+#include "main/macros.h"
+
+#include "vbo_context.h"
+
+
+/**
+ * Compute min and max elements by scanning the index buffer for
+ * glDraw[Range]Elements() calls.
+ * If primitive restart is enabled, we need to ignore restart
+ * indexes when computing min/max.
+ */
+void
+vbo_get_minmax_index(struct gl_context *ctx,
+ const struct _mesa_prim *prim,
+ const struct _mesa_index_buffer *ib,
+ GLuint *min_index, GLuint *max_index)
+{
+ const GLboolean restart = ctx->Array.PrimitiveRestart;
+ const GLuint restartIndex = ctx->Array.RestartIndex;
+ const GLuint count = prim->count;
+ const void *indices;
+ GLuint i;
+
+ if (_mesa_is_bufferobj(ib->obj)) {
+ const GLvoid *map =
+ ctx->Driver.MapBuffer(ctx, GL_ELEMENT_ARRAY_BUFFER_ARB,
+ GL_READ_ONLY, ib->obj);
+ indices = ADD_POINTERS(map, ib->ptr);
+ } else {
+ indices = ib->ptr;
+ }
+
+ switch (ib->type) {
+ case GL_UNSIGNED_INT: {
+ const GLuint *ui_indices = (const GLuint *)indices;
+ GLuint max_ui = 0;
+ GLuint min_ui = ~0U;
+ if (restart) {
+ for (i = 0; i < count; i++) {
+ if (ui_indices[i] != restartIndex) {
+ if (ui_indices[i] > max_ui) max_ui = ui_indices[i];
+ if (ui_indices[i] < min_ui) min_ui = ui_indices[i];
+ }
+ }
+ }
+ else {
+ for (i = 0; i < count; i++) {
+ if (ui_indices[i] > max_ui) max_ui = ui_indices[i];
+ if (ui_indices[i] < min_ui) min_ui = ui_indices[i];
+ }
+ }
+ *min_index = min_ui;
+ *max_index = max_ui;
+ break;
+ }
+ case GL_UNSIGNED_SHORT: {
+ const GLushort *us_indices = (const GLushort *)indices;
+ GLuint max_us = 0;
+ GLuint min_us = ~0U;
+ if (restart) {
+ for (i = 0; i < count; i++) {
+ if (us_indices[i] != restartIndex) {
+ if (us_indices[i] > max_us) max_us = us_indices[i];
+ if (us_indices[i] < min_us) min_us = us_indices[i];
+ }
+ }
+ }
+ else {
+ for (i = 0; i < count; i++) {
+ if (us_indices[i] > max_us) max_us = us_indices[i];
+ if (us_indices[i] < min_us) min_us = us_indices[i];
+ }
+ }
+ *min_index = min_us;
+ *max_index = max_us;
+ break;
+ }
+ case GL_UNSIGNED_BYTE: {
+ const GLubyte *ub_indices = (const GLubyte *)indices;
+ GLuint max_ub = 0;
+ GLuint min_ub = ~0U;
+ if (restart) {
+ for (i = 0; i < count; i++) {
+ if (ub_indices[i] != restartIndex) {
+ if (ub_indices[i] > max_ub) max_ub = ub_indices[i];
+ if (ub_indices[i] < min_ub) min_ub = ub_indices[i];
+ }
+ }
+ }
+ else {
+ for (i = 0; i < count; i++) {
+ if (ub_indices[i] > max_ub) max_ub = ub_indices[i];
+ if (ub_indices[i] < min_ub) min_ub = ub_indices[i];
+ }
+ }
+ *min_index = min_ub;
+ *max_index = max_ub;
+ break;
+ }
+ default:
+ assert(0);
+ break;
+ }
+
+ if (_mesa_is_bufferobj(ib->obj)) {
+ ctx->Driver.UnmapBuffer(ctx, GL_ELEMENT_ARRAY_BUFFER_ARB, ib->obj);
+ }
+}
+
+
+/**
+ * Check that element 'j' of the array has reasonable data.
+ * Map VBO if needed.
+ * For debugging purposes; not normally used.
+ */
+static void
+check_array_data(struct gl_context *ctx, struct gl_client_array *array,
+ GLuint attrib, GLuint j)
+{
+ if (array->Enabled) {
+ const void *data = array->Ptr;
+ if (_mesa_is_bufferobj(array->BufferObj)) {
+ if (!array->BufferObj->Pointer) {
+ /* need to map now */
+ array->BufferObj->Pointer =
+ ctx->Driver.MapBuffer(ctx, GL_ARRAY_BUFFER_ARB,
+ GL_READ_ONLY, array->BufferObj);
+ }
+ data = ADD_POINTERS(data, array->BufferObj->Pointer);
+ }
+ switch (array->Type) {
+ case GL_FLOAT:
+ {
+ GLfloat *f = (GLfloat *) ((GLubyte *) data + array->StrideB * j);
+ GLint k;
+ for (k = 0; k < array->Size; k++) {
+ if (IS_INF_OR_NAN(f[k]) ||
+ f[k] >= 1.0e20 || f[k] <= -1.0e10) {
+ printf("Bad array data:\n");
+ printf(" Element[%u].%u = %f\n", j, k, f[k]);
+ printf(" Array %u at %p\n", attrib, (void* ) array);
+ printf(" Type 0x%x, Size %d, Stride %d\n",
+ array->Type, array->Size, array->Stride);
+ printf(" Address/offset %p in Buffer Object %u\n",
+ array->Ptr, array->BufferObj->Name);
+ f[k] = 1.0; /* XXX replace the bad value! */
+ }
+ /*assert(!IS_INF_OR_NAN(f[k]));*/
+ }
+ }
+ break;
+ default:
+ ;
+ }
+ }
+}
+
+
+/**
+ * Unmap the buffer object referenced by given array, if mapped.
+ */
+static void
+unmap_array_buffer(struct gl_context *ctx, struct gl_client_array *array)
+{
+ if (array->Enabled &&
+ _mesa_is_bufferobj(array->BufferObj) &&
+ _mesa_bufferobj_mapped(array->BufferObj)) {
+ ctx->Driver.UnmapBuffer(ctx, GL_ARRAY_BUFFER_ARB, array->BufferObj);
+ }
+}
+
+
+/**
+ * Examine the array's data for NaNs, etc.
+ * For debug purposes; not normally used.
+ */
+static void
+check_draw_elements_data(struct gl_context *ctx, GLsizei count, GLenum elemType,
+ const void *elements, GLint basevertex)
+{
+ struct gl_array_object *arrayObj = ctx->Array.ArrayObj;
+ const void *elemMap;
+ GLint i, k;
+
+ if (_mesa_is_bufferobj(ctx->Array.ElementArrayBufferObj)) {
+ elemMap = ctx->Driver.MapBuffer(ctx,
+ GL_ELEMENT_ARRAY_BUFFER_ARB,
+ GL_READ_ONLY,
+ ctx->Array.ElementArrayBufferObj);
+ elements = ADD_POINTERS(elements, elemMap);
+ }
+
+ for (i = 0; i < count; i++) {
+ GLuint j;
+
+ /* j = element[i] */
+ switch (elemType) {
+ case GL_UNSIGNED_BYTE:
+ j = ((const GLubyte *) elements)[i];
+ break;
+ case GL_UNSIGNED_SHORT:
+ j = ((const GLushort *) elements)[i];
+ break;
+ case GL_UNSIGNED_INT:
+ j = ((const GLuint *) elements)[i];
+ break;
+ default:
+ assert(0);
+ }
+
+ /* check element j of each enabled array */
+ check_array_data(ctx, &arrayObj->Vertex, VERT_ATTRIB_POS, j);
+ check_array_data(ctx, &arrayObj->Normal, VERT_ATTRIB_NORMAL, j);
+ check_array_data(ctx, &arrayObj->Color, VERT_ATTRIB_COLOR0, j);
+ check_array_data(ctx, &arrayObj->SecondaryColor, VERT_ATTRIB_COLOR1, j);
+ for (k = 0; k < Elements(arrayObj->TexCoord); k++) {
+ check_array_data(ctx, &arrayObj->TexCoord[k], VERT_ATTRIB_TEX0 + k, j);
+ }
+ for (k = 0; k < Elements(arrayObj->VertexAttrib); k++) {
+ check_array_data(ctx, &arrayObj->VertexAttrib[k],
+ VERT_ATTRIB_GENERIC0 + k, j);
+ }
+ }
+
+ if (_mesa_is_bufferobj(ctx->Array.ElementArrayBufferObj)) {
+ ctx->Driver.UnmapBuffer(ctx, GL_ELEMENT_ARRAY_BUFFER_ARB,
+ ctx->Array.ElementArrayBufferObj);
+ }
+
+ unmap_array_buffer(ctx, &arrayObj->Vertex);
+ unmap_array_buffer(ctx, &arrayObj->Normal);
+ unmap_array_buffer(ctx, &arrayObj->Color);
+ for (k = 0; k < Elements(arrayObj->TexCoord); k++) {
+ unmap_array_buffer(ctx, &arrayObj->TexCoord[k]);
+ }
+ for (k = 0; k < Elements(arrayObj->VertexAttrib); k++) {
+ unmap_array_buffer(ctx, &arrayObj->VertexAttrib[k]);
+ }
+}
+
+
+/**
+ * Check array data, looking for NaNs, etc.
+ */
+static void
+check_draw_arrays_data(struct gl_context *ctx, GLint start, GLsizei count)
+{
+ /* TO DO */
+}
+
+
+/**
+ * Print info/data for glDrawArrays(), for debugging.
+ */
+static void
+print_draw_arrays(struct gl_context *ctx,
+ GLenum mode, GLint start, GLsizei count)
+{
+ struct vbo_context *vbo = vbo_context(ctx);
+ struct vbo_exec_context *exec = &vbo->exec;
+ int i;
+
+ printf("vbo_exec_DrawArrays(mode 0x%x, start %d, count %d):\n",
+ mode, start, count);
+
+ for (i = 0; i < 32; i++) {
+ GLuint bufName = exec->array.inputs[i]->BufferObj->Name;
+ GLint stride = exec->array.inputs[i]->Stride;
+ printf("attr %2d: size %d stride %d enabled %d "
+ "ptr %p Bufobj %u\n",
+ i,
+ exec->array.inputs[i]->Size,
+ stride,
+ /*exec->array.inputs[i]->Enabled,*/
+ exec->array.legacy_array[i]->Enabled,
+ exec->array.inputs[i]->Ptr,
+ bufName);
+
+ if (bufName) {
+ struct gl_buffer_object *buf = _mesa_lookup_bufferobj(ctx, bufName);
+ GLubyte *p = ctx->Driver.MapBuffer(ctx, GL_ARRAY_BUFFER_ARB,
+ GL_READ_ONLY_ARB, buf);
+ int offset = (int) (GLintptr) exec->array.inputs[i]->Ptr;
+ float *f = (float *) (p + offset);
+ int *k = (int *) f;
+ int i;
+ int n = (count * stride) / 4;
+ if (n > 32)
+ n = 32;
+ printf(" Data at offset %d:\n", offset);
+ for (i = 0; i < n; i++) {
+ printf(" float[%d] = 0x%08x %f\n", i, k[i], f[i]);
+ }
+ ctx->Driver.UnmapBuffer(ctx, GL_ARRAY_BUFFER_ARB, buf);
+ }
+ }
+}
+
+
+/**
+ * Bind the VBO executor to the current vertex array object prior
+ * to drawing.
+ *
+ * Just translate the arrayobj into a sane layout.
+ */
+static void
+bind_array_obj(struct gl_context *ctx)
+{
+ struct vbo_context *vbo = vbo_context(ctx);
+ struct vbo_exec_context *exec = &vbo->exec;
+ struct gl_array_object *arrayObj = ctx->Array.ArrayObj;
+ GLuint i;
+
+ /* TODO: Fix the ArrayObj struct to keep legacy arrays in an array
+ * rather than as individual named arrays. Then this function can
+ * go away.
+ */
+ exec->array.legacy_array[VERT_ATTRIB_POS] = &arrayObj->Vertex;
+ exec->array.legacy_array[VERT_ATTRIB_WEIGHT] = &arrayObj->Weight;
+ exec->array.legacy_array[VERT_ATTRIB_NORMAL] = &arrayObj->Normal;
+ exec->array.legacy_array[VERT_ATTRIB_COLOR0] = &arrayObj->Color;
+ exec->array.legacy_array[VERT_ATTRIB_COLOR1] = &arrayObj->SecondaryColor;
+ exec->array.legacy_array[VERT_ATTRIB_FOG] = &arrayObj->FogCoord;
+ exec->array.legacy_array[VERT_ATTRIB_COLOR_INDEX] = &arrayObj->Index;
+ if (arrayObj->PointSize.Enabled) {
+ /* this aliases COLOR_INDEX */
+ exec->array.legacy_array[VERT_ATTRIB_POINT_SIZE] = &arrayObj->PointSize;
+ }
+ exec->array.legacy_array[VERT_ATTRIB_EDGEFLAG] = &arrayObj->EdgeFlag;
+
+ for (i = 0; i < Elements(arrayObj->TexCoord); i++)
+ exec->array.legacy_array[VERT_ATTRIB_TEX0 + i] = &arrayObj->TexCoord[i];
+
+ for (i = 0; i < Elements(arrayObj->VertexAttrib); i++) {
+ assert(i < Elements(exec->array.generic_array));
+ exec->array.generic_array[i] = &arrayObj->VertexAttrib[i];
+ }
+
+ exec->array.array_obj = arrayObj->Name;
+}
+
+
+/**
+ * Set the vbo->exec->inputs[] pointers to point to the enabled
+ * vertex arrays. This depends on the current vertex program/shader
+ * being executed because of whether or not generic vertex arrays
+ * alias the conventional vertex arrays.
+ * For arrays that aren't enabled, we set the input[attrib] pointer
+ * to point at a zero-stride current value "array".
+ */
+static void
+recalculate_input_bindings(struct gl_context *ctx)
+{
+ struct vbo_context *vbo = vbo_context(ctx);
+ struct vbo_exec_context *exec = &vbo->exec;
+ const struct gl_client_array **inputs = &exec->array.inputs[0];
+ GLbitfield const_inputs = 0x0;
+ GLuint i;
+
+ exec->array.program_mode = get_program_mode(ctx);
+ exec->array.enabled_flags = ctx->Array.ArrayObj->_Enabled;
+
+ switch (exec->array.program_mode) {
+ case VP_NONE:
+ /* When no vertex program is active (or the vertex program is generated
+ * from fixed-function state). We put the material values into the
+ * generic slots. This is the only situation where material values
+ * are available as per-vertex attributes.
+ */
+ for (i = 0; i <= VERT_ATTRIB_TEX7; i++) {
+ if (exec->array.legacy_array[i]->Enabled)
+ inputs[i] = exec->array.legacy_array[i];
+ else {
+ inputs[i] = &vbo->legacy_currval[i];
+ const_inputs |= 1 << i;
+ }
+ }
+
+ for (i = 0; i < MAT_ATTRIB_MAX; i++) {
+ inputs[VERT_ATTRIB_GENERIC0 + i] = &vbo->mat_currval[i];
+ const_inputs |= 1 << (VERT_ATTRIB_GENERIC0 + i);
+ }
+
+ /* Could use just about anything, just to fill in the empty
+ * slots:
+ */
+ for (i = MAT_ATTRIB_MAX; i < VERT_ATTRIB_MAX - VERT_ATTRIB_GENERIC0; i++) {
+ inputs[VERT_ATTRIB_GENERIC0 + i] = &vbo->generic_currval[i];
+ const_inputs |= 1 << (VERT_ATTRIB_GENERIC0 + i);
+ }
+ break;
+
+ case VP_NV:
+ /* NV_vertex_program - attribute arrays alias and override
+ * conventional, legacy arrays. No materials, and the generic
+ * slots are vacant.
+ */
+ for (i = 0; i <= VERT_ATTRIB_TEX7; i++) {
+ if (exec->array.generic_array[i]->Enabled)
+ inputs[i] = exec->array.generic_array[i];
+ else if (exec->array.legacy_array[i]->Enabled)
+ inputs[i] = exec->array.legacy_array[i];
+ else {
+ inputs[i] = &vbo->legacy_currval[i];
+ const_inputs |= 1 << i;
+ }
+ }
+
+ /* Could use just about anything, just to fill in the empty
+ * slots:
+ */
+ for (i = VERT_ATTRIB_GENERIC0; i < VERT_ATTRIB_MAX; i++) {
+ inputs[i] = &vbo->generic_currval[i - VERT_ATTRIB_GENERIC0];
+ const_inputs |= 1 << i;
+ }
+ break;
+
+ case VP_ARB:
+ /* GL_ARB_vertex_program or GLSL vertex shader - Only the generic[0]
+ * attribute array aliases and overrides the legacy position array.
+ *
+ * Otherwise, legacy attributes available in the legacy slots,
+ * generic attributes in the generic slots and materials are not
+ * available as per-vertex attributes.
+ */
+ if (exec->array.generic_array[0]->Enabled)
+ inputs[0] = exec->array.generic_array[0];
+ else if (exec->array.legacy_array[0]->Enabled)
+ inputs[0] = exec->array.legacy_array[0];
+ else {
+ inputs[0] = &vbo->legacy_currval[0];
+ const_inputs |= 1 << 0;
+ }
+
+ for (i = 1; i <= VERT_ATTRIB_TEX7; i++) {
+ if (exec->array.legacy_array[i]->Enabled)
+ inputs[i] = exec->array.legacy_array[i];
+ else {
+ inputs[i] = &vbo->legacy_currval[i];
+ const_inputs |= 1 << i;
+ }
+ }
+
+ for (i = 0; i < MAX_VERTEX_GENERIC_ATTRIBS; i++) {
+ if (exec->array.generic_array[i]->Enabled)
+ inputs[VERT_ATTRIB_GENERIC0 + i] = exec->array.generic_array[i];
+ else {
+ inputs[VERT_ATTRIB_GENERIC0 + i] = &vbo->generic_currval[i];
+ const_inputs |= 1 << (VERT_ATTRIB_GENERIC0 + i);
+ }
+
+ }
+ break;
+ }
+
+ _mesa_set_varying_vp_inputs( ctx, ~const_inputs );
+}
+
+
+/**
+ * Examine the enabled vertex arrays to set the exec->array.inputs[] values.
+ * These will point to the arrays to actually use for drawing. Some will
+ * be user-provided arrays, other will be zero-stride const-valued arrays.
+ * Note that this might set the _NEW_ARRAY dirty flag so state validation
+ * must be done after this call.
+ */
+static void
+bind_arrays(struct gl_context *ctx)
+{
+ bind_array_obj(ctx);
+ recalculate_input_bindings(ctx);
+}
+
+
+/**
+ * Helper function called by the other DrawArrays() functions below.
+ * This is where we handle primitive restart for drawing non-indexed
+ * arrays. If primitive restart is enabled, it typically means
+ * splitting one DrawArrays() into two.
+ */
+static void
+vbo_draw_arrays(struct gl_context *ctx, GLenum mode, GLint start,
+ GLsizei count, GLuint numInstances)
+{
+ struct vbo_context *vbo = vbo_context(ctx);
+ struct vbo_exec_context *exec = &vbo->exec;
+ struct _mesa_prim prim[2];
+
+ bind_arrays(ctx);
+
+ /* Again... because we may have changed the bitmask of per-vertex varying
+ * attributes. If we regenerate the fixed-function vertex program now
+ * we may be able to prune down the number of vertex attributes which we
+ * need in the shader.
+ */
+ if (ctx->NewState)
+ _mesa_update_state(ctx);
+
+ prim[0].begin = 1;
+ prim[0].end = 1;
+ prim[0].weak = 0;
+ prim[0].pad = 0;
+ prim[0].mode = mode;
+ prim[0].start = 0; /* filled in below */
+ prim[0].count = 0; /* filled in below */
+ prim[0].indexed = 0;
+ prim[0].basevertex = 0;
+ prim[0].num_instances = numInstances;
+
+ /* Implement the primitive restart index */
+ if (ctx->Array.PrimitiveRestart && ctx->Array.RestartIndex < count) {
+ GLuint primCount = 0;
+
+ if (ctx->Array.RestartIndex == start) {
+ /* special case: RestartIndex at beginning */
+ if (count > 1) {
+ prim[0].start = start + 1;
+ prim[0].count = count - 1;
+ primCount = 1;
+ }
+ }
+ else if (ctx->Array.RestartIndex == start + count - 1) {
+ /* special case: RestartIndex at end */
+ if (count > 1) {
+ prim[0].start = start;
+ prim[0].count = count - 1;
+ primCount = 1;
+ }
+ }
+ else {
+ /* general case: RestartIndex in middle, split into two prims */
+ prim[0].start = start;
+ prim[0].count = ctx->Array.RestartIndex - start;
+
+ prim[1] = prim[0];
+ prim[1].start = ctx->Array.RestartIndex + 1;
+ prim[1].count = count - prim[1].start;
+
+ primCount = 2;
+ }
+
+ if (primCount > 0) {
+ /* draw one or two prims */
+ vbo->draw_prims(ctx, exec->array.inputs, prim, primCount, NULL,
+ GL_TRUE, start, start + count - 1);
+ }
+ }
+ else {
+ /* no prim restart */
+ prim[0].start = start;
+ prim[0].count = count;
+
+ vbo->draw_prims(ctx, exec->array.inputs, prim, 1, NULL,
+ GL_TRUE, start, start + count - 1);
+ }
+}
+
+
+
+/**
+ * Called from glDrawArrays when in immediate mode (not display list mode).
+ */
+static void GLAPIENTRY
+vbo_exec_DrawArrays(GLenum mode, GLint start, GLsizei count)
+{
+ GET_CURRENT_CONTEXT(ctx);
+
+ if (MESA_VERBOSE & VERBOSE_DRAW)
+ _mesa_debug(ctx, "glDrawArrays(%s, %d, %d)\n",
+ _mesa_lookup_enum_by_nr(mode), start, count);
+
+ if (!_mesa_validate_DrawArrays( ctx, mode, start, count ))
+ return;
+
+ FLUSH_CURRENT( ctx, 0 );
+
+ if (!_mesa_valid_to_render(ctx, "glDrawArrays")) {
+ return;
+ }
+
+ if (0)
+ check_draw_arrays_data(ctx, start, count);
+
+ vbo_draw_arrays(ctx, mode, start, count, 1);
+
+ if (0)
+ print_draw_arrays(ctx, mode, start, count);
+}
+
+
+/**
+ * Called from glDrawArraysInstanced when in immediate mode (not
+ * display list mode).
+ */
+static void GLAPIENTRY
+vbo_exec_DrawArraysInstanced(GLenum mode, GLint start, GLsizei count,
+ GLsizei primcount)
+{
+ GET_CURRENT_CONTEXT(ctx);
+
+ if (MESA_VERBOSE & VERBOSE_DRAW)
+ _mesa_debug(ctx, "glDrawArraysInstanced(%s, %d, %d, %d)\n",
+ _mesa_lookup_enum_by_nr(mode), start, count, primcount);
+
+ if (!_mesa_validate_DrawArraysInstanced(ctx, mode, start, count, primcount))
+ return;
+
+ FLUSH_CURRENT( ctx, 0 );
+
+ if (!_mesa_valid_to_render(ctx, "glDrawArraysInstanced")) {
+ return;
+ }
+
+ if (0)
+ check_draw_arrays_data(ctx, start, count);
+
+ vbo_draw_arrays(ctx, mode, start, count, primcount);
+
+ if (0)
+ print_draw_arrays(ctx, mode, start, count);
+}
+
+
+/**
+ * Map GL_ELEMENT_ARRAY_BUFFER and print contents.
+ * For debugging.
+ */
+static void
+dump_element_buffer(struct gl_context *ctx, GLenum type)
+{
+ const GLvoid *map = ctx->Driver.MapBuffer(ctx,
+ GL_ELEMENT_ARRAY_BUFFER_ARB,
+ GL_READ_ONLY,
+ ctx->Array.ElementArrayBufferObj);
+ switch (type) {
+ case GL_UNSIGNED_BYTE:
+ {
+ const GLubyte *us = (const GLubyte *) map;
+ GLint i;
+ for (i = 0; i < ctx->Array.ElementArrayBufferObj->Size; i++) {
+ printf("%02x ", us[i]);
+ if (i % 32 == 31)
+ printf("\n");
+ }
+ printf("\n");
+ }
+ break;
+ case GL_UNSIGNED_SHORT:
+ {
+ const GLushort *us = (const GLushort *) map;
+ GLint i;
+ for (i = 0; i < ctx->Array.ElementArrayBufferObj->Size / 2; i++) {
+ printf("%04x ", us[i]);
+ if (i % 16 == 15)
+ printf("\n");
+ }
+ printf("\n");
+ }
+ break;
+ case GL_UNSIGNED_INT:
+ {
+ const GLuint *us = (const GLuint *) map;
+ GLint i;
+ for (i = 0; i < ctx->Array.ElementArrayBufferObj->Size / 4; i++) {
+ printf("%08x ", us[i]);
+ if (i % 8 == 7)
+ printf("\n");
+ }
+ printf("\n");
+ }
+ break;
+ default:
+ ;
+ }
+
+ ctx->Driver.UnmapBuffer(ctx, GL_ELEMENT_ARRAY_BUFFER_ARB,
+ ctx->Array.ElementArrayBufferObj);
+}
+
+
+/**
+ * Inner support for both _mesa_DrawElements and _mesa_DrawRangeElements.
+ * Do the rendering for a glDrawElements or glDrawRangeElements call after
+ * we've validated buffer bounds, etc.
+ */
+static void
+vbo_validated_drawrangeelements(struct gl_context *ctx, GLenum mode,
+ GLboolean index_bounds_valid,
+ GLuint start, GLuint end,
+ GLsizei count, GLenum type,
+ const GLvoid *indices,
+ GLint basevertex, GLint primcount)
+{
+ struct vbo_context *vbo = vbo_context(ctx);
+ struct vbo_exec_context *exec = &vbo->exec;
+ struct _mesa_index_buffer ib;
+ struct _mesa_prim prim[1];
+
+ FLUSH_CURRENT( ctx, 0 );
+
+ if (!_mesa_valid_to_render(ctx, "glDraw[Range]Elements")) {
+ return;
+ }
+
+ bind_arrays( ctx );
+
+ /* check for dirty state again */
+ if (ctx->NewState)
+ _mesa_update_state( ctx );
+
+ ib.count = count;
+ ib.type = type;
+ ib.obj = ctx->Array.ElementArrayBufferObj;
+ ib.ptr = indices;
+
+ prim[0].begin = 1;
+ prim[0].end = 1;
+ prim[0].weak = 0;
+ prim[0].pad = 0;
+ prim[0].mode = mode;
+ prim[0].start = 0;
+ prim[0].count = count;
+ prim[0].indexed = 1;
+ prim[0].basevertex = basevertex;
+ prim[0].num_instances = primcount;
+
+ /* Need to give special consideration to rendering a range of
+ * indices starting somewhere above zero. Typically the
+ * application is issuing multiple DrawRangeElements() to draw
+ * successive primitives layed out linearly in the vertex arrays.
+ * Unless the vertex arrays are all in a VBO (or locked as with
+ * CVA), the OpenGL semantics imply that we need to re-read or
+ * re-upload the vertex data on each draw call.
+ *
+ * In the case of hardware tnl, we want to avoid starting the
+ * upload at zero, as it will mean every draw call uploads an
+ * increasing amount of not-used vertex data. Worse - in the
+ * software tnl module, all those vertices might be transformed and
+ * lit but never rendered.
+ *
+ * If we just upload or transform the vertices in start..end,
+ * however, the indices will be incorrect.
+ *
+ * At this level, we don't know exactly what the requirements of
+ * the backend are going to be, though it will likely boil down to
+ * either:
+ *
+ * 1) Do nothing, everything is in a VBO and is processed once
+ * only.
+ *
+ * 2) Adjust the indices and vertex arrays so that start becomes
+ * zero.
+ *
+ * Rather than doing anything here, I'll provide a helper function
+ * for the latter case elsewhere.
+ */
+
+ vbo->draw_prims( ctx, exec->array.inputs, prim, 1, &ib,
+ index_bounds_valid, start, end );
+}
+
+
+/**
+ * Called by glDrawRangeElementsBaseVertex() in immediate mode.
+ */
+static void GLAPIENTRY
+vbo_exec_DrawRangeElementsBaseVertex(GLenum mode,
+ GLuint start, GLuint end,
+ GLsizei count, GLenum type,
+ const GLvoid *indices,
+ GLint basevertex)
+{
+ static GLuint warnCount = 0;
+ GET_CURRENT_CONTEXT(ctx);
+
+ if (MESA_VERBOSE & VERBOSE_DRAW)
+ _mesa_debug(ctx,
+ "glDrawRangeElementsBaseVertex(%s, %u, %u, %d, %s, %p, %d)\n",
+ _mesa_lookup_enum_by_nr(mode), start, end, count,
+ _mesa_lookup_enum_by_nr(type), indices, basevertex);
+
+ if (!_mesa_validate_DrawRangeElements( ctx, mode, start, end, count,
+ type, indices, basevertex ))
+ return;
+
+ /* NOTE: It's important that 'end' is a reasonable value.
+ * in _tnl_draw_prims(), we use end to determine how many vertices
+ * to transform. If it's too large, we can unnecessarily split prims
+ * or we can read/write out of memory in several different places!
+ */
+
+ /* Catch/fix some potential user errors */
+ if (type == GL_UNSIGNED_BYTE) {
+ start = MIN2(start, 0xff);
+ end = MIN2(end, 0xff);
+ }
+ else if (type == GL_UNSIGNED_SHORT) {
+ start = MIN2(start, 0xffff);
+ end = MIN2(end, 0xffff);
+ }
+
+ if (end >= ctx->Array.ArrayObj->_MaxElement) {
+ /* the max element is out of bounds of one or more enabled arrays */
+ warnCount++;
+
+ if (warnCount < 10) {
+ _mesa_warning(ctx, "glDraw[Range]Elements(start %u, end %u, count %d, "
+ "type 0x%x, indices=%p)\n"
+ "\tend is out of bounds (max=%u) "
+ "Element Buffer %u (size %d)\n"
+ "\tThis should probably be fixed in the application.",
+ start, end, count, type, indices,
+ ctx->Array.ArrayObj->_MaxElement - 1,
+ ctx->Array.ElementArrayBufferObj->Name,
+ (int) ctx->Array.ElementArrayBufferObj->Size);
+ }
+
+ if (0)
+ dump_element_buffer(ctx, type);
+
+ if (0)
+ _mesa_print_arrays(ctx);
+
+#ifdef DEBUG
+ /* 'end' was out of bounds, but now let's check the actual array
+ * indexes to see if any of them are out of bounds.
+ */
+ {
+ GLuint max = _mesa_max_buffer_index(ctx, count, type, indices,
+ ctx->Array.ElementArrayBufferObj);
+ if (max >= ctx->Array.ArrayObj->_MaxElement) {
+ if (warnCount < 10) {
+ _mesa_warning(ctx, "glDraw[Range]Elements(start %u, end %u, "
+ "count %d, type 0x%x, indices=%p)\n"
+ "\tindex=%u is out of bounds (max=%u) "
+ "Element Buffer %u (size %d)\n"
+ "\tSkipping the glDrawRangeElements() call",
+ start, end, count, type, indices, max,
+ ctx->Array.ArrayObj->_MaxElement - 1,
+ ctx->Array.ElementArrayBufferObj->Name,
+ (int) ctx->Array.ElementArrayBufferObj->Size);
+ }
+ }
+ /* XXX we could also find the min index and compare to 'start'
+ * to see if start is correct. But it's more likely to get the
+ * upper bound wrong.
+ */
+ }
+#endif
+
+ /* Set 'end' to the max possible legal value */
+ assert(ctx->Array.ArrayObj->_MaxElement >= 1);
+ end = ctx->Array.ArrayObj->_MaxElement - 1;
+ }
+ else if (0) {
+ printf("glDraw[Range]Elements{,BaseVertex}"
+ "(start %u, end %u, type 0x%x, count %d) ElemBuf %u, "
+ "base %d\n",
+ start, end, type, count,
+ ctx->Array.ElementArrayBufferObj->Name,
+ basevertex);
+ }
+
+#if 0
+ check_draw_elements_data(ctx, count, type, indices);
+#else
+ (void) check_draw_elements_data;
+#endif
+
+ vbo_validated_drawrangeelements(ctx, mode, GL_TRUE, start, end,
+ count, type, indices, basevertex, 1);
+}
+
+
+/**
+ * Called by glDrawRangeElements() in immediate mode.
+ */
+static void GLAPIENTRY
+vbo_exec_DrawRangeElements(GLenum mode, GLuint start, GLuint end,
+ GLsizei count, GLenum type, const GLvoid *indices)
+{
+ GET_CURRENT_CONTEXT(ctx);
+
+ if (MESA_VERBOSE & VERBOSE_DRAW)
+ _mesa_debug(ctx,
+ "glDrawRangeElements(%s, %u, %u, %d, %s, %p)\n",
+ _mesa_lookup_enum_by_nr(mode), start, end, count,
+ _mesa_lookup_enum_by_nr(type), indices);
+
+ vbo_exec_DrawRangeElementsBaseVertex(mode, start, end, count, type,
+ indices, 0);
+}
+
+
+/**
+ * Called by glDrawElements() in immediate mode.
+ */
+static void GLAPIENTRY
+vbo_exec_DrawElements(GLenum mode, GLsizei count, GLenum type,
+ const GLvoid *indices)
+{
+ GET_CURRENT_CONTEXT(ctx);
+
+ if (MESA_VERBOSE & VERBOSE_DRAW)
+ _mesa_debug(ctx, "glDrawElements(%s, %u, %s, %p)\n",
+ _mesa_lookup_enum_by_nr(mode), count,
+ _mesa_lookup_enum_by_nr(type), indices);
+
+ if (!_mesa_validate_DrawElements( ctx, mode, count, type, indices, 0 ))
+ return;
+
+ vbo_validated_drawrangeelements(ctx, mode, GL_FALSE, ~0, ~0,
+ count, type, indices, 0, 1);
+}
+
+
+/**
+ * Called by glDrawElementsBaseVertex() in immediate mode.
+ */
+static void GLAPIENTRY
+vbo_exec_DrawElementsBaseVertex(GLenum mode, GLsizei count, GLenum type,
+ const GLvoid *indices, GLint basevertex)
+{
+ GET_CURRENT_CONTEXT(ctx);
+
+ if (MESA_VERBOSE & VERBOSE_DRAW)
+ _mesa_debug(ctx, "glDrawElementsBaseVertex(%s, %d, %s, %p, %d)\n",
+ _mesa_lookup_enum_by_nr(mode), count,
+ _mesa_lookup_enum_by_nr(type), indices, basevertex);
+
+ if (!_mesa_validate_DrawElements( ctx, mode, count, type, indices,
+ basevertex ))
+ return;
+
+ vbo_validated_drawrangeelements(ctx, mode, GL_FALSE, ~0, ~0,
+ count, type, indices, basevertex, 1);
+}
+
+
+/**
+ * Called by glDrawElementsInstanced() in immediate mode.
+ */
+static void GLAPIENTRY
+vbo_exec_DrawElementsInstanced(GLenum mode, GLsizei count, GLenum type,
+ const GLvoid *indices, GLsizei primcount)
+{
+ GET_CURRENT_CONTEXT(ctx);
+
+ if (MESA_VERBOSE & VERBOSE_DRAW)
+ _mesa_debug(ctx, "glDrawElementsInstanced(%s, %d, %s, %p, %d)\n",
+ _mesa_lookup_enum_by_nr(mode), count,
+ _mesa_lookup_enum_by_nr(type), indices, primcount);
+
+ if (!_mesa_validate_DrawElementsInstanced(ctx, mode, count, type, indices,
+ primcount))
+ return;
+
+ vbo_validated_drawrangeelements(ctx, mode, GL_FALSE, ~0, ~0,
+ count, type, indices, 0, primcount);
+}
+
+
+/**
+ * Inner support for both _mesa_MultiDrawElements() and
+ * _mesa_MultiDrawRangeElements().
+ * This does the actual rendering after we've checked array indexes, etc.
+ */
+static void
+vbo_validated_multidrawelements(struct gl_context *ctx, GLenum mode,
+ const GLsizei *count, GLenum type,
+ const GLvoid **indices, GLsizei primcount,
+ const GLint *basevertex)
+{
+ struct vbo_context *vbo = vbo_context(ctx);
+ struct vbo_exec_context *exec = &vbo->exec;
+ struct _mesa_index_buffer ib;
+ struct _mesa_prim *prim;
+ unsigned int index_type_size = 0;
+ uintptr_t min_index_ptr, max_index_ptr;
+ GLboolean fallback = GL_FALSE;
+ int i;
+
+ if (primcount == 0)
+ return;
+
+ FLUSH_CURRENT( ctx, 0 );
+
+ if (!_mesa_valid_to_render(ctx, "glMultiDrawElements")) {
+ return;
+ }
+
+ prim = calloc(1, primcount * sizeof(*prim));
+ if (prim == NULL) {
+ _mesa_error(ctx, GL_OUT_OF_MEMORY, "glMultiDrawElements");
+ return;
+ }
+
+ /* Decide if we can do this all as one set of primitives sharing the
+ * same index buffer, or if we have to reset the index pointer per
+ * primitive.
+ */
+ bind_arrays( ctx );
+
+ /* check for dirty state again */
+ if (ctx->NewState)
+ _mesa_update_state( ctx );
+
+ switch (type) {
+ case GL_UNSIGNED_INT:
+ index_type_size = 4;
+ break;
+ case GL_UNSIGNED_SHORT:
+ index_type_size = 2;
+ break;
+ case GL_UNSIGNED_BYTE:
+ index_type_size = 1;
+ break;
+ default:
+ assert(0);
+ }
+
+ min_index_ptr = (uintptr_t)indices[0];
+ max_index_ptr = 0;
+ for (i = 0; i < primcount; i++) {
+ min_index_ptr = MIN2(min_index_ptr, (uintptr_t)indices[i]);
+ max_index_ptr = MAX2(max_index_ptr, (uintptr_t)indices[i] +
+ index_type_size * count[i]);
+ }
+
+ /* Check if we can handle this thing as a bunch of index offsets from the
+ * same index pointer. If we can't, then we have to fall back to doing
+ * a draw_prims per primitive.
+ * Check that the difference between each prim's indexes is a multiple of
+ * the index/element size.
+ */
+ if (index_type_size != 1) {
+ for (i = 0; i < primcount; i++) {
+ if ((((uintptr_t)indices[i] - min_index_ptr) % index_type_size) != 0) {
+ fallback = GL_TRUE;
+ break;
+ }
+ }
+ }
+
+ /* If the index buffer isn't in a VBO, then treating the application's
+ * subranges of the index buffer as one large index buffer may lead to
+ * us reading unmapped memory.
+ */
+ if (!_mesa_is_bufferobj(ctx->Array.ElementArrayBufferObj))
+ fallback = GL_TRUE;
+
+ if (!fallback) {
+ ib.count = (max_index_ptr - min_index_ptr) / index_type_size;
+ ib.type = type;
+ ib.obj = ctx->Array.ElementArrayBufferObj;
+ ib.ptr = (void *)min_index_ptr;
+
+ for (i = 0; i < primcount; i++) {
+ prim[i].begin = (i == 0);
+ prim[i].end = (i == primcount - 1);
+ prim[i].weak = 0;
+ prim[i].pad = 0;
+ prim[i].mode = mode;
+ prim[i].start = ((uintptr_t)indices[i] - min_index_ptr) / index_type_size;
+ prim[i].count = count[i];
+ prim[i].indexed = 1;
+ prim[i].num_instances = 1;
+ if (basevertex != NULL)
+ prim[i].basevertex = basevertex[i];
+ else
+ prim[i].basevertex = 0;
+ }
+
+ vbo->draw_prims(ctx, exec->array.inputs, prim, primcount, &ib,
+ GL_FALSE, ~0, ~0);
+ } else {
+ /* render one prim at a time */
+ for (i = 0; i < primcount; i++) {
+ ib.count = count[i];
+ ib.type = type;
+ ib.obj = ctx->Array.ElementArrayBufferObj;
+ ib.ptr = indices[i];
+
+ prim[0].begin = 1;
+ prim[0].end = 1;
+ prim[0].weak = 0;
+ prim[0].pad = 0;
+ prim[0].mode = mode;
+ prim[0].start = 0;
+ prim[0].count = count[i];
+ prim[0].indexed = 1;
+ prim[0].num_instances = 1;
+ if (basevertex != NULL)
+ prim[0].basevertex = basevertex[i];
+ else
+ prim[0].basevertex = 0;
+
+ vbo->draw_prims(ctx, exec->array.inputs, prim, 1, &ib,
+ GL_FALSE, ~0, ~0);
+ }
+ }
+
+ free(prim);
+}
+
+
+static void GLAPIENTRY
+vbo_exec_MultiDrawElements(GLenum mode,
+ const GLsizei *count, GLenum type,
+ const GLvoid **indices,
+ GLsizei primcount)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ GLint i;
+
+ ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
+
+ for (i = 0; i < primcount; i++) {
+ if (!_mesa_validate_DrawElements(ctx, mode, count[i], type, indices[i],
+ 0))
+ return;
+ }
+
+ vbo_validated_multidrawelements(ctx, mode, count, type, indices, primcount,
+ NULL);
+}
+
+
+static void GLAPIENTRY
+vbo_exec_MultiDrawElementsBaseVertex(GLenum mode,
+ const GLsizei *count, GLenum type,
+ const GLvoid **indices,
+ GLsizei primcount,
+ const GLsizei *basevertex)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ GLint i;
+
+ ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
+
+ for (i = 0; i < primcount; i++) {
+ if (!_mesa_validate_DrawElements(ctx, mode, count[i], type, indices[i],
+ basevertex[i]))
+ return;
+ }
+
+ vbo_validated_multidrawelements(ctx, mode, count, type, indices, primcount,
+ basevertex);
+}
+
+
+/**
+ * Plug in the immediate-mode vertex array drawing commands into the
+ * givven vbo_exec_context object.
+ */
+void
+vbo_exec_array_init( struct vbo_exec_context *exec )
+{
+ exec->vtxfmt.DrawArrays = vbo_exec_DrawArrays;
+ exec->vtxfmt.DrawElements = vbo_exec_DrawElements;
+ exec->vtxfmt.DrawRangeElements = vbo_exec_DrawRangeElements;
+ exec->vtxfmt.MultiDrawElementsEXT = vbo_exec_MultiDrawElements;
+ exec->vtxfmt.DrawElementsBaseVertex = vbo_exec_DrawElementsBaseVertex;
+ exec->vtxfmt.DrawRangeElementsBaseVertex = vbo_exec_DrawRangeElementsBaseVertex;
+ exec->vtxfmt.MultiDrawElementsBaseVertex = vbo_exec_MultiDrawElementsBaseVertex;
+ exec->vtxfmt.DrawArraysInstanced = vbo_exec_DrawArraysInstanced;
+ exec->vtxfmt.DrawElementsInstanced = vbo_exec_DrawElementsInstanced;
+}
+
+
+void
+vbo_exec_array_destroy( struct vbo_exec_context *exec )
+{
+ /* nothing to do */
+}
+
+
+
+/**
+ * The following functions are only used for OpenGL ES 1/2 support.
+ * And some aren't even supported (yet) in ES 1/2.
+ */
+
+
+void GLAPIENTRY
+_mesa_DrawArrays(GLenum mode, GLint first, GLsizei count)
+{
+ vbo_exec_DrawArrays(mode, first, count);
+}
+
+
+void GLAPIENTRY
+_mesa_DrawElements(GLenum mode, GLsizei count, GLenum type,
+ const GLvoid *indices)
+{
+ vbo_exec_DrawElements(mode, count, type, indices);
+}
+
+
+void GLAPIENTRY
+_mesa_DrawElementsBaseVertex(GLenum mode, GLsizei count, GLenum type,
+ const GLvoid *indices, GLint basevertex)
+{
+ vbo_exec_DrawElementsBaseVertex(mode, count, type, indices, basevertex);
+}
+
+
+void GLAPIENTRY
+_mesa_DrawRangeElements(GLenum mode, GLuint start, GLuint end, GLsizei count,
+ GLenum type, const GLvoid *indices)
+{
+ vbo_exec_DrawRangeElements(mode, start, end, count, type, indices);
+}
+
+
+void GLAPIENTRY
+_mesa_DrawRangeElementsBaseVertex(GLenum mode, GLuint start, GLuint end,
+ GLsizei count, GLenum type,
+ const GLvoid *indices, GLint basevertex)
+{
+ vbo_exec_DrawRangeElementsBaseVertex(mode, start, end, count, type,
+ indices, basevertex);
+}
+
+
+void GLAPIENTRY
+_mesa_MultiDrawElementsEXT(GLenum mode, const GLsizei *count, GLenum type,
+ const GLvoid **indices, GLsizei primcount)
+{
+ vbo_exec_MultiDrawElements(mode, count, type, indices, primcount);
+}
+
+
+void GLAPIENTRY
+_mesa_MultiDrawElementsBaseVertex(GLenum mode,
+ const GLsizei *count, GLenum type,
+ const GLvoid **indices, GLsizei primcount,
+ const GLint *basevertex)
+{
+ vbo_exec_MultiDrawElementsBaseVertex(mode, count, type, indices,
+ primcount, basevertex);
+}
diff --git a/mesalib/src/mesa/vbo/vbo_exec_draw.c b/mesalib/src/mesa/vbo/vbo_exec_draw.c
index 84ae1b87f..ea2738421 100644
--- a/mesalib/src/mesa/vbo/vbo_exec_draw.c
+++ b/mesalib/src/mesa/vbo/vbo_exec_draw.c
@@ -1,422 +1,419 @@
-/*
- * Mesa 3-D graphics library
- * Version: 7.2
- *
- * Copyright (C) 1999-2008 Brian Paul All Rights Reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included
- * in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
- * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- *
- * Authors:
- * Keith Whitwell <keith@tungstengraphics.com>
- */
-
-#include "main/glheader.h"
-#include "main/bufferobj.h"
-#include "main/compiler.h"
-#include "main/enums.h"
-#include "main/state.h"
-
-#include "vbo_context.h"
-
-
-#if FEATURE_beginend
-
-
-static void
-vbo_exec_debug_verts( struct vbo_exec_context *exec )
-{
- GLuint count = exec->vtx.vert_count;
- GLuint i;
-
- printf("%s: %u vertices %d primitives, %d vertsize\n",
- __FUNCTION__,
- count,
- exec->vtx.prim_count,
- exec->vtx.vertex_size);
-
- for (i = 0 ; i < exec->vtx.prim_count ; i++) {
- struct _mesa_prim *prim = &exec->vtx.prim[i];
- printf(" prim %d: %s%s %d..%d %s %s\n",
- i,
- _mesa_lookup_prim_by_nr(prim->mode),
- prim->weak ? " (weak)" : "",
- prim->start,
- prim->start + prim->count,
- prim->begin ? "BEGIN" : "(wrap)",
- prim->end ? "END" : "(wrap)");
- }
-}
-
-
-/*
- * NOTE: Need to have calculated primitives by this point -- do it on the fly.
- * NOTE: Old 'parity' issue is gone.
- */
-static GLuint
-vbo_copy_vertices( struct vbo_exec_context *exec )
-{
- GLuint nr = exec->vtx.prim[exec->vtx.prim_count-1].count;
- GLuint ovf, i;
- GLuint sz = exec->vtx.vertex_size;
- GLfloat *dst = exec->vtx.copied.buffer;
- const GLfloat *src = (exec->vtx.buffer_map +
- exec->vtx.prim[exec->vtx.prim_count-1].start *
- exec->vtx.vertex_size);
-
-
- switch (exec->ctx->Driver.CurrentExecPrimitive) {
- case GL_POINTS:
- return 0;
- case GL_LINES:
- ovf = nr&1;
- for (i = 0 ; i < ovf ; i++)
- memcpy( dst+i*sz, src+(nr-ovf+i)*sz, sz * sizeof(GLfloat) );
- return i;
- case GL_TRIANGLES:
- ovf = nr%3;
- for (i = 0 ; i < ovf ; i++)
- memcpy( dst+i*sz, src+(nr-ovf+i)*sz, sz * sizeof(GLfloat) );
- return i;
- case GL_QUADS:
- ovf = nr&3;
- for (i = 0 ; i < ovf ; i++)
- memcpy( dst+i*sz, src+(nr-ovf+i)*sz, sz * sizeof(GLfloat) );
- return i;
- case GL_LINE_STRIP:
- if (nr == 0) {
- return 0;
- }
- else {
- memcpy( dst, src+(nr-1)*sz, sz * sizeof(GLfloat) );
- return 1;
- }
- case GL_LINE_LOOP:
- case GL_TRIANGLE_FAN:
- case GL_POLYGON:
- if (nr == 0) {
- return 0;
- }
- else if (nr == 1) {
- memcpy( dst, src+0, sz * sizeof(GLfloat) );
- return 1;
- }
- else {
- memcpy( dst, src+0, sz * sizeof(GLfloat) );
- memcpy( dst+sz, src+(nr-1)*sz, sz * sizeof(GLfloat) );
- return 2;
- }
- case GL_TRIANGLE_STRIP:
- /* no parity issue, but need to make sure the tri is not drawn twice */
- if (nr & 1) {
- exec->vtx.prim[exec->vtx.prim_count-1].count--;
- }
- /* fallthrough */
- case GL_QUAD_STRIP:
- switch (nr) {
- case 0:
- ovf = 0;
- break;
- case 1:
- ovf = 1;
- break;
- default:
- ovf = 2 + (nr & 1);
- break;
- }
- for (i = 0 ; i < ovf ; i++)
- memcpy( dst+i*sz, src+(nr-ovf+i)*sz, sz * sizeof(GLfloat) );
- return i;
- case PRIM_OUTSIDE_BEGIN_END:
- return 0;
- default:
- assert(0);
- return 0;
- }
-}
-
-
-
-/* TODO: populate these as the vertex is defined:
- */
-static void
-vbo_exec_bind_arrays( GLcontext *ctx )
-{
- struct vbo_context *vbo = vbo_context(ctx);
- struct vbo_exec_context *exec = &vbo->exec;
- struct gl_client_array *arrays = exec->vtx.arrays;
- const GLuint count = exec->vtx.vert_count;
- const GLubyte *data = (GLubyte *) exec->vtx.buffer_map;
- const GLuint *map;
- GLuint attr;
- GLbitfield varying_inputs = 0x0;
-
- /* Install the default (ie Current) attributes first, then overlay
- * all active ones.
- */
- switch (get_program_mode(exec->ctx)) {
- case VP_NONE:
- for (attr = 0; attr < 16; attr++) {
- exec->vtx.inputs[attr] = &vbo->legacy_currval[attr];
- }
- for (attr = 0; attr < MAT_ATTRIB_MAX; attr++) {
- ASSERT(attr + 16 < Elements(exec->vtx.inputs));
- exec->vtx.inputs[attr + 16] = &vbo->mat_currval[attr];
- }
- map = vbo->map_vp_none;
- break;
- case VP_NV:
- case VP_ARB:
- /* The aliasing of attributes for NV vertex programs has already
- * occurred. NV vertex programs cannot access material values,
- * nor attributes greater than VERT_ATTRIB_TEX7.
- */
- for (attr = 0; attr < 16; attr++) {
- exec->vtx.inputs[attr] = &vbo->legacy_currval[attr];
- ASSERT(attr + 16 < Elements(exec->vtx.inputs));
- exec->vtx.inputs[attr + 16] = &vbo->generic_currval[attr];
- }
- map = vbo->map_vp_arb;
-
- /* check if VERT_ATTRIB_POS is not read but VERT_BIT_GENERIC0 is read.
- * In that case we effectively need to route the data from
- * glVertexAttrib(0, val) calls to feed into the GENERIC0 input.
- */
- if ((ctx->VertexProgram._Current->Base.InputsRead & VERT_BIT_POS) == 0 &&
- (ctx->VertexProgram._Current->Base.InputsRead & VERT_BIT_GENERIC0)) {
- exec->vtx.inputs[16] = exec->vtx.inputs[0];
- exec->vtx.attrsz[16] = exec->vtx.attrsz[0];
- exec->vtx.attrptr[16] = exec->vtx.attrptr[0];
- exec->vtx.attrsz[0] = 0;
- }
- break;
- default:
- assert(0);
- }
-
- /* Make all active attributes (including edgeflag) available as
- * arrays of floats.
- */
- for (attr = 0; attr < VERT_ATTRIB_MAX ; attr++) {
- const GLuint src = map[attr];
-
- if (exec->vtx.attrsz[src]) {
- /* override the default array set above */
- ASSERT(attr < Elements(exec->vtx.inputs));
- ASSERT(attr < Elements(exec->vtx.arrays)); /* arrays[] */
- exec->vtx.inputs[attr] = &arrays[attr];
-
- if (_mesa_is_bufferobj(exec->vtx.bufferobj)) {
- /* a real buffer obj: Ptr is an offset, not a pointer*/
- GLsizeiptr offset;
- assert(exec->vtx.bufferobj->Pointer); /* buf should be mapped */
- offset = (GLbyte *) data -
- (GLbyte *) exec->vtx.bufferobj->Pointer +
- exec->vtx.bufferobj->Offset;
- assert(offset >= 0);
- arrays[attr].Ptr = (void *) offset;
- }
- else {
- /* Ptr into ordinary app memory */
- arrays[attr].Ptr = (void *) data;
- }
- arrays[attr].Size = exec->vtx.attrsz[src];
- arrays[attr].StrideB = exec->vtx.vertex_size * sizeof(GLfloat);
- arrays[attr].Stride = exec->vtx.vertex_size * sizeof(GLfloat);
- arrays[attr].Type = GL_FLOAT;
- arrays[attr].Format = GL_RGBA;
- arrays[attr].Enabled = 1;
- _mesa_reference_buffer_object(ctx,
- &arrays[attr].BufferObj,
- exec->vtx.bufferobj);
- arrays[attr]._MaxElement = count; /* ??? */
-
- data += exec->vtx.attrsz[src] * sizeof(GLfloat);
- varying_inputs |= 1 << attr;
- }
- }
-
- _mesa_set_varying_vp_inputs( ctx, varying_inputs );
-}
-
-
-static void
-vbo_exec_vtx_unmap( struct vbo_exec_context *exec )
-{
- GLenum target = GL_ARRAY_BUFFER_ARB;
-
- if (_mesa_is_bufferobj(exec->vtx.bufferobj)) {
- GLcontext *ctx = exec->ctx;
-
- if (ctx->Driver.FlushMappedBufferRange) {
- GLintptr offset = exec->vtx.buffer_used - exec->vtx.bufferobj->Offset;
- GLsizeiptr length = (exec->vtx.buffer_ptr - exec->vtx.buffer_map) * sizeof(float);
-
- if (length)
- ctx->Driver.FlushMappedBufferRange(ctx, target,
- offset, length,
- exec->vtx.bufferobj);
- }
-
- exec->vtx.buffer_used += (exec->vtx.buffer_ptr -
- exec->vtx.buffer_map) * sizeof(float);
-
- assert(exec->vtx.buffer_used <= VBO_VERT_BUFFER_SIZE);
- assert(exec->vtx.buffer_ptr != NULL);
-
- ctx->Driver.UnmapBuffer(ctx, target, exec->vtx.bufferobj);
- exec->vtx.buffer_map = NULL;
- exec->vtx.buffer_ptr = NULL;
- exec->vtx.max_vert = 0;
- }
-}
-
-
-void
-vbo_exec_vtx_map( struct vbo_exec_context *exec )
-{
- GLcontext *ctx = exec->ctx;
- const GLenum target = GL_ARRAY_BUFFER_ARB;
- const GLenum access = GL_READ_WRITE_ARB; /* for MapBuffer */
- const GLenum accessRange = GL_MAP_WRITE_BIT | /* for MapBufferRange */
- GL_MAP_INVALIDATE_RANGE_BIT |
- GL_MAP_UNSYNCHRONIZED_BIT |
- GL_MAP_FLUSH_EXPLICIT_BIT |
- MESA_MAP_NOWAIT_BIT;
- const GLenum usage = GL_STREAM_DRAW_ARB;
-
- if (!_mesa_is_bufferobj(exec->vtx.bufferobj))
- return;
-
- if (exec->vtx.buffer_map != NULL) {
- assert(0);
- exec->vtx.buffer_map = NULL;
- exec->vtx.buffer_ptr = NULL;
- }
-
- if (VBO_VERT_BUFFER_SIZE > exec->vtx.buffer_used + 1024 &&
- ctx->Driver.MapBufferRange) {
- exec->vtx.buffer_map =
- (GLfloat *)ctx->Driver.MapBufferRange(ctx,
- target,
- exec->vtx.buffer_used,
- (VBO_VERT_BUFFER_SIZE -
- exec->vtx.buffer_used),
- accessRange,
- exec->vtx.bufferobj);
- exec->vtx.buffer_ptr = exec->vtx.buffer_map;
- }
-
- if (!exec->vtx.buffer_map) {
- exec->vtx.buffer_used = 0;
-
- ctx->Driver.BufferData(ctx, target,
- VBO_VERT_BUFFER_SIZE,
- NULL, usage, exec->vtx.bufferobj);
-
-
- if (ctx->Driver.MapBufferRange)
- exec->vtx.buffer_map =
- (GLfloat *)ctx->Driver.MapBufferRange(ctx, target,
- 0, VBO_VERT_BUFFER_SIZE,
- accessRange,
- exec->vtx.bufferobj);
- if (!exec->vtx.buffer_map)
- exec->vtx.buffer_map =
- (GLfloat *)ctx->Driver.MapBuffer(ctx, target, access, exec->vtx.bufferobj);
- assert(exec->vtx.buffer_map);
- exec->vtx.buffer_ptr = exec->vtx.buffer_map;
- }
-
- if (0)
- printf("map %d..\n", exec->vtx.buffer_used);
-}
-
-
-
-/**
- * Execute the buffer and save copied verts.
- */
-void
-vbo_exec_vtx_flush( struct vbo_exec_context *exec, GLboolean unmap )
-{
- if (0)
- vbo_exec_debug_verts( exec );
-
- if (exec->vtx.prim_count &&
- exec->vtx.vert_count) {
-
- exec->vtx.copied.nr = vbo_copy_vertices( exec );
-
- if (exec->vtx.copied.nr != exec->vtx.vert_count) {
- GLcontext *ctx = exec->ctx;
-
- /* Before the update_state() as this may raise _NEW_ARRAY
- * from _mesa_set_varying_vp_inputs().
- */
- vbo_exec_bind_arrays( ctx );
-
- if (ctx->NewState)
- _mesa_update_state( ctx );
-
- if (_mesa_is_bufferobj(exec->vtx.bufferobj)) {
- vbo_exec_vtx_unmap( exec );
- }
-
- if (0)
- printf("%s %d %d\n", __FUNCTION__, exec->vtx.prim_count,
- exec->vtx.vert_count);
-
- vbo_context(ctx)->draw_prims( ctx,
- exec->vtx.inputs,
- exec->vtx.prim,
- exec->vtx.prim_count,
- NULL,
- GL_TRUE,
- 0,
- exec->vtx.vert_count - 1);
-
- /* If using a real VBO, get new storage -- unless asked not to.
- */
- if (_mesa_is_bufferobj(exec->vtx.bufferobj) && !unmap) {
- vbo_exec_vtx_map( exec );
- }
- }
- }
-
- /* May have to unmap explicitly if we didn't draw:
- */
- if (unmap &&
- _mesa_is_bufferobj(exec->vtx.bufferobj) &&
- exec->vtx.buffer_map) {
- vbo_exec_vtx_unmap( exec );
- }
-
-
- if (unmap || exec->vtx.vertex_size == 0)
- exec->vtx.max_vert = 0;
- else
- exec->vtx.max_vert = ((VBO_VERT_BUFFER_SIZE - exec->vtx.buffer_used) /
- (exec->vtx.vertex_size * sizeof(GLfloat)));
-
- exec->vtx.buffer_ptr = exec->vtx.buffer_map;
- exec->vtx.prim_count = 0;
- exec->vtx.vert_count = 0;
-}
-
-
-#endif /* FEATURE_beginend */
+/*
+ * Mesa 3-D graphics library
+ * Version: 7.2
+ *
+ * Copyright (C) 1999-2008 Brian Paul All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+ * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors:
+ * Keith Whitwell <keith@tungstengraphics.com>
+ */
+
+#include "main/glheader.h"
+#include "main/bufferobj.h"
+#include "main/compiler.h"
+#include "main/enums.h"
+#include "main/state.h"
+
+#include "vbo_context.h"
+
+
+#if FEATURE_beginend
+
+
+static void
+vbo_exec_debug_verts( struct vbo_exec_context *exec )
+{
+ GLuint count = exec->vtx.vert_count;
+ GLuint i;
+
+ printf("%s: %u vertices %d primitives, %d vertsize\n",
+ __FUNCTION__,
+ count,
+ exec->vtx.prim_count,
+ exec->vtx.vertex_size);
+
+ for (i = 0 ; i < exec->vtx.prim_count ; i++) {
+ struct _mesa_prim *prim = &exec->vtx.prim[i];
+ printf(" prim %d: %s%s %d..%d %s %s\n",
+ i,
+ _mesa_lookup_prim_by_nr(prim->mode),
+ prim->weak ? " (weak)" : "",
+ prim->start,
+ prim->start + prim->count,
+ prim->begin ? "BEGIN" : "(wrap)",
+ prim->end ? "END" : "(wrap)");
+ }
+}
+
+
+/*
+ * NOTE: Need to have calculated primitives by this point -- do it on the fly.
+ * NOTE: Old 'parity' issue is gone.
+ */
+static GLuint
+vbo_copy_vertices( struct vbo_exec_context *exec )
+{
+ GLuint nr = exec->vtx.prim[exec->vtx.prim_count-1].count;
+ GLuint ovf, i;
+ GLuint sz = exec->vtx.vertex_size;
+ GLfloat *dst = exec->vtx.copied.buffer;
+ const GLfloat *src = (exec->vtx.buffer_map +
+ exec->vtx.prim[exec->vtx.prim_count-1].start *
+ exec->vtx.vertex_size);
+
+
+ switch (exec->ctx->Driver.CurrentExecPrimitive) {
+ case GL_POINTS:
+ return 0;
+ case GL_LINES:
+ ovf = nr&1;
+ for (i = 0 ; i < ovf ; i++)
+ memcpy( dst+i*sz, src+(nr-ovf+i)*sz, sz * sizeof(GLfloat) );
+ return i;
+ case GL_TRIANGLES:
+ ovf = nr%3;
+ for (i = 0 ; i < ovf ; i++)
+ memcpy( dst+i*sz, src+(nr-ovf+i)*sz, sz * sizeof(GLfloat) );
+ return i;
+ case GL_QUADS:
+ ovf = nr&3;
+ for (i = 0 ; i < ovf ; i++)
+ memcpy( dst+i*sz, src+(nr-ovf+i)*sz, sz * sizeof(GLfloat) );
+ return i;
+ case GL_LINE_STRIP:
+ if (nr == 0) {
+ return 0;
+ }
+ else {
+ memcpy( dst, src+(nr-1)*sz, sz * sizeof(GLfloat) );
+ return 1;
+ }
+ case GL_LINE_LOOP:
+ case GL_TRIANGLE_FAN:
+ case GL_POLYGON:
+ if (nr == 0) {
+ return 0;
+ }
+ else if (nr == 1) {
+ memcpy( dst, src+0, sz * sizeof(GLfloat) );
+ return 1;
+ }
+ else {
+ memcpy( dst, src+0, sz * sizeof(GLfloat) );
+ memcpy( dst+sz, src+(nr-1)*sz, sz * sizeof(GLfloat) );
+ return 2;
+ }
+ case GL_TRIANGLE_STRIP:
+ /* no parity issue, but need to make sure the tri is not drawn twice */
+ if (nr & 1) {
+ exec->vtx.prim[exec->vtx.prim_count-1].count--;
+ }
+ /* fallthrough */
+ case GL_QUAD_STRIP:
+ switch (nr) {
+ case 0:
+ ovf = 0;
+ break;
+ case 1:
+ ovf = 1;
+ break;
+ default:
+ ovf = 2 + (nr & 1);
+ break;
+ }
+ for (i = 0 ; i < ovf ; i++)
+ memcpy( dst+i*sz, src+(nr-ovf+i)*sz, sz * sizeof(GLfloat) );
+ return i;
+ case PRIM_OUTSIDE_BEGIN_END:
+ return 0;
+ default:
+ assert(0);
+ return 0;
+ }
+}
+
+
+
+/* TODO: populate these as the vertex is defined:
+ */
+static void
+vbo_exec_bind_arrays( struct gl_context *ctx )
+{
+ struct vbo_context *vbo = vbo_context(ctx);
+ struct vbo_exec_context *exec = &vbo->exec;
+ struct gl_client_array *arrays = exec->vtx.arrays;
+ const GLuint count = exec->vtx.vert_count;
+ const GLuint *map;
+ GLuint attr;
+ GLbitfield varying_inputs = 0x0;
+
+ /* Install the default (ie Current) attributes first, then overlay
+ * all active ones.
+ */
+ switch (get_program_mode(exec->ctx)) {
+ case VP_NONE:
+ for (attr = 0; attr < 16; attr++) {
+ exec->vtx.inputs[attr] = &vbo->legacy_currval[attr];
+ }
+ for (attr = 0; attr < MAT_ATTRIB_MAX; attr++) {
+ ASSERT(attr + 16 < Elements(exec->vtx.inputs));
+ exec->vtx.inputs[attr + 16] = &vbo->mat_currval[attr];
+ }
+ map = vbo->map_vp_none;
+ break;
+ case VP_NV:
+ case VP_ARB:
+ /* The aliasing of attributes for NV vertex programs has already
+ * occurred. NV vertex programs cannot access material values,
+ * nor attributes greater than VERT_ATTRIB_TEX7.
+ */
+ for (attr = 0; attr < 16; attr++) {
+ exec->vtx.inputs[attr] = &vbo->legacy_currval[attr];
+ ASSERT(attr + 16 < Elements(exec->vtx.inputs));
+ exec->vtx.inputs[attr + 16] = &vbo->generic_currval[attr];
+ }
+ map = vbo->map_vp_arb;
+
+ /* check if VERT_ATTRIB_POS is not read but VERT_BIT_GENERIC0 is read.
+ * In that case we effectively need to route the data from
+ * glVertexAttrib(0, val) calls to feed into the GENERIC0 input.
+ */
+ if ((ctx->VertexProgram._Current->Base.InputsRead & VERT_BIT_POS) == 0 &&
+ (ctx->VertexProgram._Current->Base.InputsRead & VERT_BIT_GENERIC0)) {
+ exec->vtx.inputs[16] = exec->vtx.inputs[0];
+ exec->vtx.attrsz[16] = exec->vtx.attrsz[0];
+ exec->vtx.attrptr[16] = exec->vtx.attrptr[0];
+ exec->vtx.attrsz[0] = 0;
+ }
+ break;
+ default:
+ assert(0);
+ }
+
+ /* Make all active attributes (including edgeflag) available as
+ * arrays of floats.
+ */
+ for (attr = 0; attr < VERT_ATTRIB_MAX ; attr++) {
+ const GLuint src = map[attr];
+
+ if (exec->vtx.attrsz[src]) {
+ GLsizeiptr offset = (GLbyte *)exec->vtx.attrptr[src] -
+ (GLbyte *)exec->vtx.vertex;
+
+ /* override the default array set above */
+ ASSERT(attr < Elements(exec->vtx.inputs));
+ ASSERT(attr < Elements(exec->vtx.arrays)); /* arrays[] */
+ exec->vtx.inputs[attr] = &arrays[attr];
+
+ if (_mesa_is_bufferobj(exec->vtx.bufferobj)) {
+ /* a real buffer obj: Ptr is an offset, not a pointer*/
+ assert(exec->vtx.bufferobj->Pointer); /* buf should be mapped */
+ assert(offset >= 0);
+ arrays[attr].Ptr = (GLubyte *)exec->vtx.bufferobj->Offset + offset;
+ }
+ else {
+ /* Ptr into ordinary app memory */
+ arrays[attr].Ptr = (GLubyte *)exec->vtx.buffer_map + offset;
+ }
+ arrays[attr].Size = exec->vtx.attrsz[src];
+ arrays[attr].StrideB = exec->vtx.vertex_size * sizeof(GLfloat);
+ arrays[attr].Stride = exec->vtx.vertex_size * sizeof(GLfloat);
+ arrays[attr].Type = GL_FLOAT;
+ arrays[attr].Format = GL_RGBA;
+ arrays[attr].Enabled = 1;
+ _mesa_reference_buffer_object(ctx,
+ &arrays[attr].BufferObj,
+ exec->vtx.bufferobj);
+ arrays[attr]._MaxElement = count; /* ??? */
+
+ varying_inputs |= 1 << attr;
+ }
+ }
+
+ _mesa_set_varying_vp_inputs( ctx, varying_inputs );
+}
+
+
+static void
+vbo_exec_vtx_unmap( struct vbo_exec_context *exec )
+{
+ GLenum target = GL_ARRAY_BUFFER_ARB;
+
+ if (_mesa_is_bufferobj(exec->vtx.bufferobj)) {
+ struct gl_context *ctx = exec->ctx;
+
+ if (ctx->Driver.FlushMappedBufferRange) {
+ GLintptr offset = exec->vtx.buffer_used - exec->vtx.bufferobj->Offset;
+ GLsizeiptr length = (exec->vtx.buffer_ptr - exec->vtx.buffer_map) * sizeof(float);
+
+ if (length)
+ ctx->Driver.FlushMappedBufferRange(ctx, target,
+ offset, length,
+ exec->vtx.bufferobj);
+ }
+
+ exec->vtx.buffer_used += (exec->vtx.buffer_ptr -
+ exec->vtx.buffer_map) * sizeof(float);
+
+ assert(exec->vtx.buffer_used <= VBO_VERT_BUFFER_SIZE);
+ assert(exec->vtx.buffer_ptr != NULL);
+
+ ctx->Driver.UnmapBuffer(ctx, target, exec->vtx.bufferobj);
+ exec->vtx.buffer_map = NULL;
+ exec->vtx.buffer_ptr = NULL;
+ exec->vtx.max_vert = 0;
+ }
+}
+
+
+void
+vbo_exec_vtx_map( struct vbo_exec_context *exec )
+{
+ struct gl_context *ctx = exec->ctx;
+ const GLenum target = GL_ARRAY_BUFFER_ARB;
+ const GLenum access = GL_READ_WRITE_ARB; /* for MapBuffer */
+ const GLenum accessRange = GL_MAP_WRITE_BIT | /* for MapBufferRange */
+ GL_MAP_INVALIDATE_RANGE_BIT |
+ GL_MAP_UNSYNCHRONIZED_BIT |
+ GL_MAP_FLUSH_EXPLICIT_BIT |
+ MESA_MAP_NOWAIT_BIT;
+ const GLenum usage = GL_STREAM_DRAW_ARB;
+
+ if (!_mesa_is_bufferobj(exec->vtx.bufferobj))
+ return;
+
+ if (exec->vtx.buffer_map != NULL) {
+ assert(0);
+ exec->vtx.buffer_map = NULL;
+ exec->vtx.buffer_ptr = NULL;
+ }
+
+ if (VBO_VERT_BUFFER_SIZE > exec->vtx.buffer_used + 1024 &&
+ ctx->Driver.MapBufferRange) {
+ exec->vtx.buffer_map =
+ (GLfloat *)ctx->Driver.MapBufferRange(ctx,
+ target,
+ exec->vtx.buffer_used,
+ (VBO_VERT_BUFFER_SIZE -
+ exec->vtx.buffer_used),
+ accessRange,
+ exec->vtx.bufferobj);
+ exec->vtx.buffer_ptr = exec->vtx.buffer_map;
+ }
+
+ if (!exec->vtx.buffer_map) {
+ exec->vtx.buffer_used = 0;
+
+ ctx->Driver.BufferData(ctx, target,
+ VBO_VERT_BUFFER_SIZE,
+ NULL, usage, exec->vtx.bufferobj);
+
+
+ if (ctx->Driver.MapBufferRange)
+ exec->vtx.buffer_map =
+ (GLfloat *)ctx->Driver.MapBufferRange(ctx, target,
+ 0, VBO_VERT_BUFFER_SIZE,
+ accessRange,
+ exec->vtx.bufferobj);
+ if (!exec->vtx.buffer_map)
+ exec->vtx.buffer_map =
+ (GLfloat *)ctx->Driver.MapBuffer(ctx, target, access, exec->vtx.bufferobj);
+ assert(exec->vtx.buffer_map);
+ exec->vtx.buffer_ptr = exec->vtx.buffer_map;
+ }
+
+ if (0)
+ printf("map %d..\n", exec->vtx.buffer_used);
+}
+
+
+
+/**
+ * Execute the buffer and save copied verts.
+ */
+void
+vbo_exec_vtx_flush( struct vbo_exec_context *exec, GLboolean unmap )
+{
+ if (0)
+ vbo_exec_debug_verts( exec );
+
+ if (exec->vtx.prim_count &&
+ exec->vtx.vert_count) {
+
+ exec->vtx.copied.nr = vbo_copy_vertices( exec );
+
+ if (exec->vtx.copied.nr != exec->vtx.vert_count) {
+ struct gl_context *ctx = exec->ctx;
+
+ /* Before the update_state() as this may raise _NEW_ARRAY
+ * from _mesa_set_varying_vp_inputs().
+ */
+ vbo_exec_bind_arrays( ctx );
+
+ if (ctx->NewState)
+ _mesa_update_state( ctx );
+
+ if (_mesa_is_bufferobj(exec->vtx.bufferobj)) {
+ vbo_exec_vtx_unmap( exec );
+ }
+
+ if (0)
+ printf("%s %d %d\n", __FUNCTION__, exec->vtx.prim_count,
+ exec->vtx.vert_count);
+
+ vbo_context(ctx)->draw_prims( ctx,
+ exec->vtx.inputs,
+ exec->vtx.prim,
+ exec->vtx.prim_count,
+ NULL,
+ GL_TRUE,
+ 0,
+ exec->vtx.vert_count - 1);
+
+ /* If using a real VBO, get new storage -- unless asked not to.
+ */
+ if (_mesa_is_bufferobj(exec->vtx.bufferobj) && !unmap) {
+ vbo_exec_vtx_map( exec );
+ }
+ }
+ }
+
+ /* May have to unmap explicitly if we didn't draw:
+ */
+ if (unmap &&
+ _mesa_is_bufferobj(exec->vtx.bufferobj) &&
+ exec->vtx.buffer_map) {
+ vbo_exec_vtx_unmap( exec );
+ }
+
+
+ if (unmap || exec->vtx.vertex_size == 0)
+ exec->vtx.max_vert = 0;
+ else
+ exec->vtx.max_vert = ((VBO_VERT_BUFFER_SIZE - exec->vtx.buffer_used) /
+ (exec->vtx.vertex_size * sizeof(GLfloat)));
+
+ exec->vtx.buffer_ptr = exec->vtx.buffer_map;
+ exec->vtx.prim_count = 0;
+ exec->vtx.vert_count = 0;
+}
+
+
+#endif /* FEATURE_beginend */
diff --git a/mesalib/src/mesa/vbo/vbo_exec_eval.c b/mesalib/src/mesa/vbo/vbo_exec_eval.c
index 23ad12608..0aff01b25 100644
--- a/mesalib/src/mesa/vbo/vbo_exec_eval.c
+++ b/mesalib/src/mesa/vbo/vbo_exec_eval.c
@@ -1,263 +1,263 @@
-/*
- * Mesa 3-D graphics library
- * Version: 6.1
- *
- * Copyright (C) 1999-2004 Brian Paul All Rights Reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included
- * in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
- * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- *
- * Authors:
- * Keith Whitwell <keith@tungstengraphics.com>
- */
-
-#include "main/glheader.h"
-#include "main/context.h"
-#include "main/macros.h"
-#include "math/m_eval.h"
-#include "main/dispatch.h"
-#include "vbo_exec.h"
-
-
-static void clear_active_eval1( struct vbo_exec_context *exec, GLuint attr )
-{
- assert(attr < Elements(exec->eval.map1));
- exec->eval.map1[attr].map = NULL;
-}
-
-static void clear_active_eval2( struct vbo_exec_context *exec, GLuint attr )
-{
- assert(attr < Elements(exec->eval.map2));
- exec->eval.map2[attr].map = NULL;
-}
-
-static void set_active_eval1( struct vbo_exec_context *exec, GLuint attr, GLuint dim,
- struct gl_1d_map *map )
-{
- assert(attr < Elements(exec->eval.map1));
- if (!exec->eval.map1[attr].map) {
- exec->eval.map1[attr].map = map;
- exec->eval.map1[attr].sz = dim;
- }
-}
-
-static void set_active_eval2( struct vbo_exec_context *exec, GLuint attr, GLuint dim,
- struct gl_2d_map *map )
-{
- assert(attr < Elements(exec->eval.map2));
- if (!exec->eval.map2[attr].map) {
- exec->eval.map2[attr].map = map;
- exec->eval.map2[attr].sz = dim;
- }
-}
-
-void vbo_exec_eval_update( struct vbo_exec_context *exec )
-{
- GLcontext *ctx = exec->ctx;
- GLuint attr;
-
- /* Vertex program maps have priority over conventional attribs */
-
- for (attr = 0; attr < VBO_ATTRIB_FIRST_MATERIAL; attr++) {
- clear_active_eval1( exec, attr );
- clear_active_eval2( exec, attr );
- }
-
- if (ctx->Eval.Map1Color4)
- set_active_eval1( exec, VBO_ATTRIB_COLOR0, 4, &ctx->EvalMap.Map1Color4 );
-
- if (ctx->Eval.Map2Color4)
- set_active_eval2( exec, VBO_ATTRIB_COLOR0, 4, &ctx->EvalMap.Map2Color4 );
-
- if (ctx->Eval.Map1TextureCoord4)
- set_active_eval1( exec, VBO_ATTRIB_TEX0, 4, &ctx->EvalMap.Map1Texture4 );
- else if (ctx->Eval.Map1TextureCoord3)
- set_active_eval1( exec, VBO_ATTRIB_TEX0, 3, &ctx->EvalMap.Map1Texture3 );
- else if (ctx->Eval.Map1TextureCoord2)
- set_active_eval1( exec, VBO_ATTRIB_TEX0, 2, &ctx->EvalMap.Map1Texture2 );
- else if (ctx->Eval.Map1TextureCoord1)
- set_active_eval1( exec, VBO_ATTRIB_TEX0, 1, &ctx->EvalMap.Map1Texture1 );
-
- if (ctx->Eval.Map2TextureCoord4)
- set_active_eval2( exec, VBO_ATTRIB_TEX0, 4, &ctx->EvalMap.Map2Texture4 );
- else if (ctx->Eval.Map2TextureCoord3)
- set_active_eval2( exec, VBO_ATTRIB_TEX0, 3, &ctx->EvalMap.Map2Texture3 );
- else if (ctx->Eval.Map2TextureCoord2)
- set_active_eval2( exec, VBO_ATTRIB_TEX0, 2, &ctx->EvalMap.Map2Texture2 );
- else if (ctx->Eval.Map2TextureCoord1)
- set_active_eval2( exec, VBO_ATTRIB_TEX0, 1, &ctx->EvalMap.Map2Texture1 );
-
- if (ctx->Eval.Map1Normal)
- set_active_eval1( exec, VBO_ATTRIB_NORMAL, 3, &ctx->EvalMap.Map1Normal );
-
- if (ctx->Eval.Map2Normal)
- set_active_eval2( exec, VBO_ATTRIB_NORMAL, 3, &ctx->EvalMap.Map2Normal );
-
- if (ctx->Eval.Map1Vertex4)
- set_active_eval1( exec, VBO_ATTRIB_POS, 4, &ctx->EvalMap.Map1Vertex4 );
- else if (ctx->Eval.Map1Vertex3)
- set_active_eval1( exec, VBO_ATTRIB_POS, 3, &ctx->EvalMap.Map1Vertex3 );
-
- if (ctx->Eval.Map2Vertex4)
- set_active_eval2( exec, VBO_ATTRIB_POS, 4, &ctx->EvalMap.Map2Vertex4 );
- else if (ctx->Eval.Map2Vertex3)
- set_active_eval2( exec, VBO_ATTRIB_POS, 3, &ctx->EvalMap.Map2Vertex3 );
-
- /* _NEW_PROGRAM */
- if (ctx->VertexProgram._Enabled) {
- /* These are the 16 evaluators which GL_NV_vertex_program defines.
- * They alias and override the conventional vertex attributs.
- */
- for (attr = 0; attr < 16; attr++) {
- /* _NEW_EVAL */
- assert(attr < Elements(ctx->Eval.Map1Attrib));
- if (ctx->Eval.Map1Attrib[attr])
- set_active_eval1( exec, attr, 4, &ctx->EvalMap.Map1Attrib[attr] );
-
- assert(attr < Elements(ctx->Eval.Map2Attrib));
- if (ctx->Eval.Map2Attrib[attr])
- set_active_eval2( exec, attr, 4, &ctx->EvalMap.Map2Attrib[attr] );
- }
- }
-
- exec->eval.recalculate_maps = 0;
-}
-
-
-
-void vbo_exec_do_EvalCoord1f(struct vbo_exec_context *exec, GLfloat u)
-{
- GLuint attr;
-
- for (attr = 1; attr <= VBO_ATTRIB_TEX7; attr++) {
- struct gl_1d_map *map = exec->eval.map1[attr].map;
- if (map) {
- GLfloat uu = (u - map->u1) * map->du;
- GLfloat data[4];
-
- ASSIGN_4V(data, 0, 0, 0, 1);
-
- _math_horner_bezier_curve(map->Points, data, uu,
- exec->eval.map1[attr].sz,
- map->Order);
-
- COPY_SZ_4V( exec->vtx.attrptr[attr],
- exec->vtx.attrsz[attr],
- data );
- }
- }
-
- /** Vertex -- EvalCoord1f is a noop if this map not enabled:
- **/
- if (exec->eval.map1[0].map) {
- struct gl_1d_map *map = exec->eval.map1[0].map;
- GLfloat uu = (u - map->u1) * map->du;
- GLfloat vertex[4];
-
- ASSIGN_4V(vertex, 0, 0, 0, 1);
-
- _math_horner_bezier_curve(map->Points, vertex, uu,
- exec->eval.map1[0].sz,
- map->Order);
-
- if (exec->eval.map1[0].sz == 4)
- CALL_Vertex4fv(GET_DISPATCH(), ( vertex ));
- else
- CALL_Vertex3fv(GET_DISPATCH(), ( vertex ));
- }
-}
-
-
-
-void vbo_exec_do_EvalCoord2f( struct vbo_exec_context *exec,
- GLfloat u, GLfloat v )
-{
- GLuint attr;
-
- for (attr = 1; attr <= VBO_ATTRIB_TEX7; attr++) {
- struct gl_2d_map *map = exec->eval.map2[attr].map;
- if (map) {
- GLfloat uu = (u - map->u1) * map->du;
- GLfloat vv = (v - map->v1) * map->dv;
- GLfloat data[4];
-
- ASSIGN_4V(data, 0, 0, 0, 1);
-
- _math_horner_bezier_surf(map->Points,
- data,
- uu, vv,
- exec->eval.map2[attr].sz,
- map->Uorder, map->Vorder);
-
- COPY_SZ_4V( exec->vtx.attrptr[attr],
- exec->vtx.attrsz[attr],
- data );
- }
- }
-
- /** Vertex -- EvalCoord2f is a noop if this map not enabled:
- **/
- if (exec->eval.map2[0].map) {
- struct gl_2d_map *map = exec->eval.map2[0].map;
- GLfloat uu = (u - map->u1) * map->du;
- GLfloat vv = (v - map->v1) * map->dv;
- GLfloat vertex[4];
-
- ASSIGN_4V(vertex, 0, 0, 0, 1);
-
- if (exec->ctx->Eval.AutoNormal) {
- GLfloat normal[4];
- GLfloat du[4], dv[4];
-
- _math_de_casteljau_surf(map->Points, vertex, du, dv, uu, vv,
- exec->eval.map2[0].sz,
- map->Uorder, map->Vorder);
-
- if (exec->eval.map2[0].sz == 4) {
- du[0] = du[0]*vertex[3] - du[3]*vertex[0];
- du[1] = du[1]*vertex[3] - du[3]*vertex[1];
- du[2] = du[2]*vertex[3] - du[3]*vertex[2];
-
- dv[0] = dv[0]*vertex[3] - dv[3]*vertex[0];
- dv[1] = dv[1]*vertex[3] - dv[3]*vertex[1];
- dv[2] = dv[2]*vertex[3] - dv[3]*vertex[2];
- }
-
-
- CROSS3(normal, du, dv);
- NORMALIZE_3FV(normal);
- normal[3] = 1.0;
-
- COPY_SZ_4V( exec->vtx.attrptr[VBO_ATTRIB_NORMAL],
- exec->vtx.attrsz[VBO_ATTRIB_NORMAL],
- normal );
-
- }
- else {
- _math_horner_bezier_surf(map->Points, vertex, uu, vv,
- exec->eval.map2[0].sz,
- map->Uorder, map->Vorder);
- }
-
- if (exec->vtx.attrsz[0] == 4)
- CALL_Vertex4fv(GET_DISPATCH(), ( vertex ));
- else
- CALL_Vertex3fv(GET_DISPATCH(), ( vertex ));
- }
-}
-
-
+/*
+ * Mesa 3-D graphics library
+ * Version: 6.1
+ *
+ * Copyright (C) 1999-2004 Brian Paul All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+ * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors:
+ * Keith Whitwell <keith@tungstengraphics.com>
+ */
+
+#include "main/glheader.h"
+#include "main/context.h"
+#include "main/macros.h"
+#include "math/m_eval.h"
+#include "main/dispatch.h"
+#include "vbo_exec.h"
+
+
+static void clear_active_eval1( struct vbo_exec_context *exec, GLuint attr )
+{
+ assert(attr < Elements(exec->eval.map1));
+ exec->eval.map1[attr].map = NULL;
+}
+
+static void clear_active_eval2( struct vbo_exec_context *exec, GLuint attr )
+{
+ assert(attr < Elements(exec->eval.map2));
+ exec->eval.map2[attr].map = NULL;
+}
+
+static void set_active_eval1( struct vbo_exec_context *exec, GLuint attr, GLuint dim,
+ struct gl_1d_map *map )
+{
+ assert(attr < Elements(exec->eval.map1));
+ if (!exec->eval.map1[attr].map) {
+ exec->eval.map1[attr].map = map;
+ exec->eval.map1[attr].sz = dim;
+ }
+}
+
+static void set_active_eval2( struct vbo_exec_context *exec, GLuint attr, GLuint dim,
+ struct gl_2d_map *map )
+{
+ assert(attr < Elements(exec->eval.map2));
+ if (!exec->eval.map2[attr].map) {
+ exec->eval.map2[attr].map = map;
+ exec->eval.map2[attr].sz = dim;
+ }
+}
+
+void vbo_exec_eval_update( struct vbo_exec_context *exec )
+{
+ struct gl_context *ctx = exec->ctx;
+ GLuint attr;
+
+ /* Vertex program maps have priority over conventional attribs */
+
+ for (attr = 0; attr < VBO_ATTRIB_FIRST_MATERIAL; attr++) {
+ clear_active_eval1( exec, attr );
+ clear_active_eval2( exec, attr );
+ }
+
+ if (ctx->Eval.Map1Color4)
+ set_active_eval1( exec, VBO_ATTRIB_COLOR0, 4, &ctx->EvalMap.Map1Color4 );
+
+ if (ctx->Eval.Map2Color4)
+ set_active_eval2( exec, VBO_ATTRIB_COLOR0, 4, &ctx->EvalMap.Map2Color4 );
+
+ if (ctx->Eval.Map1TextureCoord4)
+ set_active_eval1( exec, VBO_ATTRIB_TEX0, 4, &ctx->EvalMap.Map1Texture4 );
+ else if (ctx->Eval.Map1TextureCoord3)
+ set_active_eval1( exec, VBO_ATTRIB_TEX0, 3, &ctx->EvalMap.Map1Texture3 );
+ else if (ctx->Eval.Map1TextureCoord2)
+ set_active_eval1( exec, VBO_ATTRIB_TEX0, 2, &ctx->EvalMap.Map1Texture2 );
+ else if (ctx->Eval.Map1TextureCoord1)
+ set_active_eval1( exec, VBO_ATTRIB_TEX0, 1, &ctx->EvalMap.Map1Texture1 );
+
+ if (ctx->Eval.Map2TextureCoord4)
+ set_active_eval2( exec, VBO_ATTRIB_TEX0, 4, &ctx->EvalMap.Map2Texture4 );
+ else if (ctx->Eval.Map2TextureCoord3)
+ set_active_eval2( exec, VBO_ATTRIB_TEX0, 3, &ctx->EvalMap.Map2Texture3 );
+ else if (ctx->Eval.Map2TextureCoord2)
+ set_active_eval2( exec, VBO_ATTRIB_TEX0, 2, &ctx->EvalMap.Map2Texture2 );
+ else if (ctx->Eval.Map2TextureCoord1)
+ set_active_eval2( exec, VBO_ATTRIB_TEX0, 1, &ctx->EvalMap.Map2Texture1 );
+
+ if (ctx->Eval.Map1Normal)
+ set_active_eval1( exec, VBO_ATTRIB_NORMAL, 3, &ctx->EvalMap.Map1Normal );
+
+ if (ctx->Eval.Map2Normal)
+ set_active_eval2( exec, VBO_ATTRIB_NORMAL, 3, &ctx->EvalMap.Map2Normal );
+
+ if (ctx->Eval.Map1Vertex4)
+ set_active_eval1( exec, VBO_ATTRIB_POS, 4, &ctx->EvalMap.Map1Vertex4 );
+ else if (ctx->Eval.Map1Vertex3)
+ set_active_eval1( exec, VBO_ATTRIB_POS, 3, &ctx->EvalMap.Map1Vertex3 );
+
+ if (ctx->Eval.Map2Vertex4)
+ set_active_eval2( exec, VBO_ATTRIB_POS, 4, &ctx->EvalMap.Map2Vertex4 );
+ else if (ctx->Eval.Map2Vertex3)
+ set_active_eval2( exec, VBO_ATTRIB_POS, 3, &ctx->EvalMap.Map2Vertex3 );
+
+ /* _NEW_PROGRAM */
+ if (ctx->VertexProgram._Enabled) {
+ /* These are the 16 evaluators which GL_NV_vertex_program defines.
+ * They alias and override the conventional vertex attributs.
+ */
+ for (attr = 0; attr < 16; attr++) {
+ /* _NEW_EVAL */
+ assert(attr < Elements(ctx->Eval.Map1Attrib));
+ if (ctx->Eval.Map1Attrib[attr])
+ set_active_eval1( exec, attr, 4, &ctx->EvalMap.Map1Attrib[attr] );
+
+ assert(attr < Elements(ctx->Eval.Map2Attrib));
+ if (ctx->Eval.Map2Attrib[attr])
+ set_active_eval2( exec, attr, 4, &ctx->EvalMap.Map2Attrib[attr] );
+ }
+ }
+
+ exec->eval.recalculate_maps = 0;
+}
+
+
+
+void vbo_exec_do_EvalCoord1f(struct vbo_exec_context *exec, GLfloat u)
+{
+ GLuint attr;
+
+ for (attr = 1; attr <= VBO_ATTRIB_TEX7; attr++) {
+ struct gl_1d_map *map = exec->eval.map1[attr].map;
+ if (map) {
+ GLfloat uu = (u - map->u1) * map->du;
+ GLfloat data[4];
+
+ ASSIGN_4V(data, 0, 0, 0, 1);
+
+ _math_horner_bezier_curve(map->Points, data, uu,
+ exec->eval.map1[attr].sz,
+ map->Order);
+
+ COPY_SZ_4V( exec->vtx.attrptr[attr],
+ exec->vtx.attrsz[attr],
+ data );
+ }
+ }
+
+ /** Vertex -- EvalCoord1f is a noop if this map not enabled:
+ **/
+ if (exec->eval.map1[0].map) {
+ struct gl_1d_map *map = exec->eval.map1[0].map;
+ GLfloat uu = (u - map->u1) * map->du;
+ GLfloat vertex[4];
+
+ ASSIGN_4V(vertex, 0, 0, 0, 1);
+
+ _math_horner_bezier_curve(map->Points, vertex, uu,
+ exec->eval.map1[0].sz,
+ map->Order);
+
+ if (exec->eval.map1[0].sz == 4)
+ CALL_Vertex4fv(GET_DISPATCH(), ( vertex ));
+ else
+ CALL_Vertex3fv(GET_DISPATCH(), ( vertex ));
+ }
+}
+
+
+
+void vbo_exec_do_EvalCoord2f( struct vbo_exec_context *exec,
+ GLfloat u, GLfloat v )
+{
+ GLuint attr;
+
+ for (attr = 1; attr <= VBO_ATTRIB_TEX7; attr++) {
+ struct gl_2d_map *map = exec->eval.map2[attr].map;
+ if (map) {
+ GLfloat uu = (u - map->u1) * map->du;
+ GLfloat vv = (v - map->v1) * map->dv;
+ GLfloat data[4];
+
+ ASSIGN_4V(data, 0, 0, 0, 1);
+
+ _math_horner_bezier_surf(map->Points,
+ data,
+ uu, vv,
+ exec->eval.map2[attr].sz,
+ map->Uorder, map->Vorder);
+
+ COPY_SZ_4V( exec->vtx.attrptr[attr],
+ exec->vtx.attrsz[attr],
+ data );
+ }
+ }
+
+ /** Vertex -- EvalCoord2f is a noop if this map not enabled:
+ **/
+ if (exec->eval.map2[0].map) {
+ struct gl_2d_map *map = exec->eval.map2[0].map;
+ GLfloat uu = (u - map->u1) * map->du;
+ GLfloat vv = (v - map->v1) * map->dv;
+ GLfloat vertex[4];
+
+ ASSIGN_4V(vertex, 0, 0, 0, 1);
+
+ if (exec->ctx->Eval.AutoNormal) {
+ GLfloat normal[4];
+ GLfloat du[4], dv[4];
+
+ _math_de_casteljau_surf(map->Points, vertex, du, dv, uu, vv,
+ exec->eval.map2[0].sz,
+ map->Uorder, map->Vorder);
+
+ if (exec->eval.map2[0].sz == 4) {
+ du[0] = du[0]*vertex[3] - du[3]*vertex[0];
+ du[1] = du[1]*vertex[3] - du[3]*vertex[1];
+ du[2] = du[2]*vertex[3] - du[3]*vertex[2];
+
+ dv[0] = dv[0]*vertex[3] - dv[3]*vertex[0];
+ dv[1] = dv[1]*vertex[3] - dv[3]*vertex[1];
+ dv[2] = dv[2]*vertex[3] - dv[3]*vertex[2];
+ }
+
+
+ CROSS3(normal, du, dv);
+ NORMALIZE_3FV(normal);
+ normal[3] = 1.0;
+
+ COPY_SZ_4V( exec->vtx.attrptr[VBO_ATTRIB_NORMAL],
+ exec->vtx.attrsz[VBO_ATTRIB_NORMAL],
+ normal );
+
+ }
+ else {
+ _math_horner_bezier_surf(map->Points, vertex, uu, vv,
+ exec->eval.map2[0].sz,
+ map->Uorder, map->Vorder);
+ }
+
+ if (exec->vtx.attrsz[0] == 4)
+ CALL_Vertex4fv(GET_DISPATCH(), ( vertex ));
+ else
+ CALL_Vertex3fv(GET_DISPATCH(), ( vertex ));
+ }
+}
+
+
diff --git a/mesalib/src/mesa/vbo/vbo_rebase.c b/mesalib/src/mesa/vbo/vbo_rebase.c
index ff7c7a6b0..a62777cbf 100644
--- a/mesalib/src/mesa/vbo/vbo_rebase.c
+++ b/mesalib/src/mesa/vbo/vbo_rebase.c
@@ -1,239 +1,251 @@
-
-/*
- * Mesa 3-D graphics library
- * Version: 6.5
- *
- * Copyright (C) 1999-2006 Brian Paul All Rights Reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included
- * in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
- * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- *
- * Authors:
- * Keith Whitwell <keith@tungstengraphics.com>
- */
-
-/* Helper for drivers which find themselves rendering a range of
- * indices starting somewhere above zero. Typically the application
- * is issuing multiple DrawArrays() or DrawElements() to draw
- * successive primitives layed out linearly in the vertex arrays.
- * Unless the vertex arrays are all in a VBO, the OpenGL semantics
- * imply that we need to re-upload the vertex data on each draw call.
- * In that case, we want to avoid starting the upload at zero, as it
- * will mean every draw call uploads an increasing amount of not-used
- * vertex data. Worse - in the software tnl module, all those
- * vertices will be transformed and lit.
- *
- * If we just upload the new data, however, the indices will be
- * incorrect as we tend to upload each set of vertex data to a new
- * region.
- *
- * This file provides a helper to adjust the arrays, primitives and
- * indices of a draw call so that it can be re-issued with a min_index
- * of zero.
- */
-
-#include "main/glheader.h"
-#include "main/imports.h"
-#include "main/mtypes.h"
-
-#include "vbo.h"
-
-
-#define REBASE(TYPE) \
-static void *rebase_##TYPE( const void *ptr, \
- GLuint count, \
- TYPE min_index ) \
-{ \
- const TYPE *in = (TYPE *)ptr; \
- TYPE *tmp_indices = malloc(count * sizeof(TYPE)); \
- GLuint i; \
- \
- for (i = 0; i < count; i++) \
- tmp_indices[i] = in[i] - min_index; \
- \
- return (void *)tmp_indices; \
-}
-
-
-REBASE(GLuint)
-REBASE(GLushort)
-REBASE(GLubyte)
-
-GLboolean vbo_all_varyings_in_vbos( const struct gl_client_array *arrays[] )
-{
- GLuint i;
-
- for (i = 0; i < VERT_ATTRIB_MAX; i++)
- if (arrays[i]->StrideB &&
- arrays[i]->BufferObj->Name == 0)
- return GL_FALSE;
-
- return GL_TRUE;
-}
-
-/* Adjust primitives, indices and vertex definitions so that min_index
- * becomes zero. There are lots of reasons for wanting to do this, eg:
- *
- * Software tnl:
- * - any time min_index != 0, otherwise unused vertices lower than
- * min_index will be transformed.
- *
- * Hardware tnl:
- * - if ib != NULL and min_index != 0, otherwise vertices lower than
- * min_index will be uploaded. Requires adjusting index values.
- *
- * - if ib == NULL and min_index != 0, just for convenience so this doesn't
- * have to be handled within the driver.
- *
- * Hardware tnl with VBO support:
- * - as above, but only when vertices are not (all?) in VBO's.
- * - can't save time by trying to upload half a vbo - typically it is
- * all or nothing.
- */
-void vbo_rebase_prims( GLcontext *ctx,
- const struct gl_client_array *arrays[],
- const struct _mesa_prim *prim,
- GLuint nr_prims,
- const struct _mesa_index_buffer *ib,
- GLuint min_index,
- GLuint max_index,
- vbo_draw_func draw )
-{
- struct gl_client_array tmp_arrays[VERT_ATTRIB_MAX];
- const struct gl_client_array *tmp_array_pointers[VERT_ATTRIB_MAX];
-
- struct _mesa_index_buffer tmp_ib;
- struct _mesa_prim *tmp_prims = NULL;
- void *tmp_indices = NULL;
- GLuint i;
-
- assert(min_index != 0);
-
- if (0)
- printf("%s %d..%d\n", __FUNCTION__, min_index, max_index);
-
-
- /* XXX this path is disabled for now.
- * There's rendering corruption in some apps when it's enabled.
- */
- if (0 && ib && ctx->Extensions.ARB_draw_elements_base_vertex) {
- /* If we can just tell the hardware or the TNL to interpret our
- * indices with a different base, do so.
- */
- tmp_prims = (struct _mesa_prim *)malloc(sizeof(*prim) * nr_prims);
-
- for (i = 0; i < nr_prims; i++) {
- tmp_prims[i] = prim[i];
- tmp_prims[i].basevertex -= min_index;
- }
-
- prim = tmp_prims;
- } else if (ib) {
- /* Unfortunately need to adjust each index individually.
- */
- GLboolean map_ib = ib->obj->Name && !ib->obj->Pointer;
- void *ptr;
-
- if (map_ib)
- ctx->Driver.MapBuffer(ctx,
- GL_ELEMENT_ARRAY_BUFFER,
- GL_READ_ONLY_ARB,
- ib->obj);
-
-
- ptr = ADD_POINTERS(ib->obj->Pointer, ib->ptr);
-
- /* Some users might prefer it if we translated elements to
- * GLuints here. Others wouldn't...
- */
- switch (ib->type) {
- case GL_UNSIGNED_INT:
- tmp_indices = rebase_GLuint( ptr, ib->count, min_index );
- break;
- case GL_UNSIGNED_SHORT:
- tmp_indices = rebase_GLushort( ptr, ib->count, min_index );
- break;
- case GL_UNSIGNED_BYTE:
- tmp_indices = rebase_GLubyte( ptr, ib->count, min_index );
- break;
- }
-
- if (map_ib)
- ctx->Driver.UnmapBuffer(ctx,
- GL_ELEMENT_ARRAY_BUFFER,
- ib->obj);
-
- tmp_ib.obj = ctx->Shared->NullBufferObj;
- tmp_ib.ptr = tmp_indices;
- tmp_ib.count = ib->count;
- tmp_ib.type = ib->type;
-
- ib = &tmp_ib;
- }
- else {
- /* Otherwise the primitives need adjustment.
- */
- tmp_prims = (struct _mesa_prim *)malloc(sizeof(*prim) * nr_prims);
-
- for (i = 0; i < nr_prims; i++) {
- /* If this fails, it could indicate an application error:
- */
- assert(prim[i].start >= min_index);
-
- tmp_prims[i] = prim[i];
- tmp_prims[i].start -= min_index;
- }
-
- prim = tmp_prims;
- }
-
- /* Just need to adjust the pointer values on each incoming array.
- * This works for VBO and non-vbo rendering and shouldn't pesimize
- * VBO-based upload schemes. However this may still not be a fast
- * path for hardware tnl for VBO based rendering as most machines
- * will be happier if you just specify a starting vertex value in
- * each primitive.
- *
- * For drivers with hardware tnl, you only want to do this if you
- * are forced to, eg non-VBO indexed rendering with start != 0.
- */
- for (i = 0; i < VERT_ATTRIB_MAX; i++) {
- tmp_arrays[i] = *arrays[i];
- tmp_arrays[i].Ptr += min_index * tmp_arrays[i].StrideB;
- tmp_array_pointers[i] = &tmp_arrays[i];
- }
-
- /* Re-issue the draw call.
- */
- draw( ctx,
- tmp_array_pointers,
- prim,
- nr_prims,
- ib,
- GL_TRUE,
- 0,
- max_index - min_index );
-
- if (tmp_indices)
- free(tmp_indices);
-
- if (tmp_prims)
- free(tmp_prims);
-}
-
-
-
+
+/*
+ * Mesa 3-D graphics library
+ * Version: 6.5
+ *
+ * Copyright (C) 1999-2006 Brian Paul All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+ * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors:
+ * Keith Whitwell <keith@tungstengraphics.com>
+ */
+
+/* Helper for drivers which find themselves rendering a range of
+ * indices starting somewhere above zero. Typically the application
+ * is issuing multiple DrawArrays() or DrawElements() to draw
+ * successive primitives layed out linearly in the vertex arrays.
+ * Unless the vertex arrays are all in a VBO, the OpenGL semantics
+ * imply that we need to re-upload the vertex data on each draw call.
+ * In that case, we want to avoid starting the upload at zero, as it
+ * will mean every draw call uploads an increasing amount of not-used
+ * vertex data. Worse - in the software tnl module, all those
+ * vertices will be transformed and lit.
+ *
+ * If we just upload the new data, however, the indices will be
+ * incorrect as we tend to upload each set of vertex data to a new
+ * region.
+ *
+ * This file provides a helper to adjust the arrays, primitives and
+ * indices of a draw call so that it can be re-issued with a min_index
+ * of zero.
+ */
+
+#include "main/glheader.h"
+#include "main/imports.h"
+#include "main/mtypes.h"
+
+#include "vbo.h"
+
+
+#define REBASE(TYPE) \
+static void *rebase_##TYPE( const void *ptr, \
+ GLuint count, \
+ TYPE min_index ) \
+{ \
+ const TYPE *in = (TYPE *)ptr; \
+ TYPE *tmp_indices = malloc(count * sizeof(TYPE)); \
+ GLuint i; \
+ \
+ for (i = 0; i < count; i++) \
+ tmp_indices[i] = in[i] - min_index; \
+ \
+ return (void *)tmp_indices; \
+}
+
+
+REBASE(GLuint)
+REBASE(GLushort)
+REBASE(GLubyte)
+
+GLboolean vbo_all_varyings_in_vbos( const struct gl_client_array *arrays[] )
+{
+ GLuint i;
+
+ for (i = 0; i < VERT_ATTRIB_MAX; i++)
+ if (arrays[i]->StrideB &&
+ arrays[i]->BufferObj->Name == 0)
+ return GL_FALSE;
+
+ return GL_TRUE;
+}
+
+GLboolean vbo_any_varyings_in_vbos( const struct gl_client_array *arrays[] )
+{
+ GLuint i;
+
+ for (i = 0; i < VERT_ATTRIB_MAX; i++)
+ if (arrays[i]->StrideB &&
+ arrays[i]->BufferObj->Name != 0)
+ return GL_TRUE;
+
+ return GL_FALSE;
+}
+
+/* Adjust primitives, indices and vertex definitions so that min_index
+ * becomes zero. There are lots of reasons for wanting to do this, eg:
+ *
+ * Software tnl:
+ * - any time min_index != 0, otherwise unused vertices lower than
+ * min_index will be transformed.
+ *
+ * Hardware tnl:
+ * - if ib != NULL and min_index != 0, otherwise vertices lower than
+ * min_index will be uploaded. Requires adjusting index values.
+ *
+ * - if ib == NULL and min_index != 0, just for convenience so this doesn't
+ * have to be handled within the driver.
+ *
+ * Hardware tnl with VBO support:
+ * - as above, but only when vertices are not (all?) in VBO's.
+ * - can't save time by trying to upload half a vbo - typically it is
+ * all or nothing.
+ */
+void vbo_rebase_prims( struct gl_context *ctx,
+ const struct gl_client_array *arrays[],
+ const struct _mesa_prim *prim,
+ GLuint nr_prims,
+ const struct _mesa_index_buffer *ib,
+ GLuint min_index,
+ GLuint max_index,
+ vbo_draw_func draw )
+{
+ struct gl_client_array tmp_arrays[VERT_ATTRIB_MAX];
+ const struct gl_client_array *tmp_array_pointers[VERT_ATTRIB_MAX];
+
+ struct _mesa_index_buffer tmp_ib;
+ struct _mesa_prim *tmp_prims = NULL;
+ void *tmp_indices = NULL;
+ GLuint i;
+
+ assert(min_index != 0);
+
+ if (0)
+ printf("%s %d..%d\n", __FUNCTION__, min_index, max_index);
+
+
+ /* XXX this path is disabled for now.
+ * There's rendering corruption in some apps when it's enabled.
+ */
+ if (0 && ib && ctx->Extensions.ARB_draw_elements_base_vertex) {
+ /* If we can just tell the hardware or the TNL to interpret our
+ * indices with a different base, do so.
+ */
+ tmp_prims = (struct _mesa_prim *)malloc(sizeof(*prim) * nr_prims);
+
+ for (i = 0; i < nr_prims; i++) {
+ tmp_prims[i] = prim[i];
+ tmp_prims[i].basevertex -= min_index;
+ }
+
+ prim = tmp_prims;
+ } else if (ib) {
+ /* Unfortunately need to adjust each index individually.
+ */
+ GLboolean map_ib = ib->obj->Name && !ib->obj->Pointer;
+ void *ptr;
+
+ if (map_ib)
+ ctx->Driver.MapBuffer(ctx,
+ GL_ELEMENT_ARRAY_BUFFER,
+ GL_READ_ONLY_ARB,
+ ib->obj);
+
+
+ ptr = ADD_POINTERS(ib->obj->Pointer, ib->ptr);
+
+ /* Some users might prefer it if we translated elements to
+ * GLuints here. Others wouldn't...
+ */
+ switch (ib->type) {
+ case GL_UNSIGNED_INT:
+ tmp_indices = rebase_GLuint( ptr, ib->count, min_index );
+ break;
+ case GL_UNSIGNED_SHORT:
+ tmp_indices = rebase_GLushort( ptr, ib->count, min_index );
+ break;
+ case GL_UNSIGNED_BYTE:
+ tmp_indices = rebase_GLubyte( ptr, ib->count, min_index );
+ break;
+ }
+
+ if (map_ib)
+ ctx->Driver.UnmapBuffer(ctx,
+ GL_ELEMENT_ARRAY_BUFFER,
+ ib->obj);
+
+ tmp_ib.obj = ctx->Shared->NullBufferObj;
+ tmp_ib.ptr = tmp_indices;
+ tmp_ib.count = ib->count;
+ tmp_ib.type = ib->type;
+
+ ib = &tmp_ib;
+ }
+ else {
+ /* Otherwise the primitives need adjustment.
+ */
+ tmp_prims = (struct _mesa_prim *)malloc(sizeof(*prim) * nr_prims);
+
+ for (i = 0; i < nr_prims; i++) {
+ /* If this fails, it could indicate an application error:
+ */
+ assert(prim[i].start >= min_index);
+
+ tmp_prims[i] = prim[i];
+ tmp_prims[i].start -= min_index;
+ }
+
+ prim = tmp_prims;
+ }
+
+ /* Just need to adjust the pointer values on each incoming array.
+ * This works for VBO and non-vbo rendering and shouldn't pesimize
+ * VBO-based upload schemes. However this may still not be a fast
+ * path for hardware tnl for VBO based rendering as most machines
+ * will be happier if you just specify a starting vertex value in
+ * each primitive.
+ *
+ * For drivers with hardware tnl, you only want to do this if you
+ * are forced to, eg non-VBO indexed rendering with start != 0.
+ */
+ for (i = 0; i < VERT_ATTRIB_MAX; i++) {
+ tmp_arrays[i] = *arrays[i];
+ tmp_arrays[i].Ptr += min_index * tmp_arrays[i].StrideB;
+ tmp_array_pointers[i] = &tmp_arrays[i];
+ }
+
+ /* Re-issue the draw call.
+ */
+ draw( ctx,
+ tmp_array_pointers,
+ prim,
+ nr_prims,
+ ib,
+ GL_TRUE,
+ 0,
+ max_index - min_index );
+
+ if (tmp_indices)
+ free(tmp_indices);
+
+ if (tmp_prims)
+ free(tmp_prims);
+}
+
+
+
diff --git a/mesalib/src/mesa/vbo/vbo_save.c b/mesalib/src/mesa/vbo/vbo_save.c
index dd5570689..87ced410c 100644
--- a/mesalib/src/mesa/vbo/vbo_save.c
+++ b/mesalib/src/mesa/vbo/vbo_save.c
@@ -1,122 +1,122 @@
-/*
- * Mesa 3-D graphics library
- * Version: 7.2
- *
- * Copyright (C) 1999-2008 Brian Paul All Rights Reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included
- * in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
- * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- *
- * Authors:
- * Keith Whitwell <keith@tungstengraphics.com>
- */
-
-
-#include "main/mtypes.h"
-#include "main/bufferobj.h"
-#include "main/imports.h"
-
-#include "vbo_context.h"
-
-
-#if FEATURE_dlist
-
-
-static void vbo_save_callback_init( GLcontext *ctx )
-{
- ctx->Driver.NewList = vbo_save_NewList;
- ctx->Driver.EndList = vbo_save_EndList;
- ctx->Driver.SaveFlushVertices = vbo_save_SaveFlushVertices;
- ctx->Driver.BeginCallList = vbo_save_BeginCallList;
- ctx->Driver.EndCallList = vbo_save_EndCallList;
- ctx->Driver.NotifySaveBegin = vbo_save_NotifyBegin;
-}
-
-
-
-void vbo_save_init( GLcontext *ctx )
-{
- 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;
- unsigned i;
-
- memcpy(arrays, vbo->legacy_currval, 16 * sizeof(arrays[0]));
- memcpy(arrays + 16, vbo->generic_currval, 16 * sizeof(arrays[0]));
-
- for (i = 0; i < 16; ++i) {
- arrays[i ].BufferObj = NULL;
- arrays[i + 16].BufferObj = NULL;
- _mesa_reference_buffer_object(ctx, &arrays[i ].BufferObj,
- vbo->legacy_currval[i].BufferObj);
- _mesa_reference_buffer_object(ctx, &arrays[i + 16].BufferObj,
- vbo->generic_currval[i].BufferObj);
- }
- }
-
- ctx->Driver.CurrentSavePrimitive = PRIM_UNKNOWN;
-}
-
-
-void vbo_save_destroy( GLcontext *ctx )
-{
- struct vbo_context *vbo = vbo_context(ctx);
- struct vbo_save_context *save = &vbo->save;
- GLuint i;
-
- if (save->prim_store) {
- if ( --save->prim_store->refcount == 0 ) {
- FREE( save->prim_store );
- save->prim_store = NULL;
- }
- if ( --save->vertex_store->refcount == 0 ) {
- _mesa_reference_buffer_object(ctx,
- &save->vertex_store->bufferobj, NULL);
- FREE( save->vertex_store );
- save->vertex_store = NULL;
- }
- }
-
- for (i = 0; i < VBO_ATTRIB_MAX; i++) {
- _mesa_reference_buffer_object(ctx, &save->arrays[i].BufferObj, NULL);
- }
-}
-
-
-
-
-/* Note that this can occur during the playback of a display list:
- */
-void vbo_save_fallback( GLcontext *ctx, GLboolean fallback )
-{
- struct vbo_save_context *save = &vbo_context(ctx)->save;
-
- if (fallback)
- save->replay_flags |= VBO_SAVE_FALLBACK;
- else
- save->replay_flags &= ~VBO_SAVE_FALLBACK;
-}
-
-
-#endif /* FEATURE_dlist */
+/*
+ * Mesa 3-D graphics library
+ * Version: 7.2
+ *
+ * Copyright (C) 1999-2008 Brian Paul All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+ * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors:
+ * Keith Whitwell <keith@tungstengraphics.com>
+ */
+
+
+#include "main/mtypes.h"
+#include "main/bufferobj.h"
+#include "main/imports.h"
+
+#include "vbo_context.h"
+
+
+#if FEATURE_dlist
+
+
+static void vbo_save_callback_init( struct gl_context *ctx )
+{
+ ctx->Driver.NewList = vbo_save_NewList;
+ ctx->Driver.EndList = vbo_save_EndList;
+ ctx->Driver.SaveFlushVertices = vbo_save_SaveFlushVertices;
+ ctx->Driver.BeginCallList = vbo_save_BeginCallList;
+ ctx->Driver.EndCallList = vbo_save_EndCallList;
+ ctx->Driver.NotifySaveBegin = vbo_save_NotifyBegin;
+}
+
+
+
+void vbo_save_init( struct gl_context *ctx )
+{
+ 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;
+ unsigned i;
+
+ memcpy(arrays, vbo->legacy_currval, 16 * sizeof(arrays[0]));
+ memcpy(arrays + 16, vbo->generic_currval, 16 * sizeof(arrays[0]));
+
+ for (i = 0; i < 16; ++i) {
+ arrays[i ].BufferObj = NULL;
+ arrays[i + 16].BufferObj = NULL;
+ _mesa_reference_buffer_object(ctx, &arrays[i ].BufferObj,
+ vbo->legacy_currval[i].BufferObj);
+ _mesa_reference_buffer_object(ctx, &arrays[i + 16].BufferObj,
+ vbo->generic_currval[i].BufferObj);
+ }
+ }
+
+ ctx->Driver.CurrentSavePrimitive = PRIM_UNKNOWN;
+}
+
+
+void vbo_save_destroy( struct gl_context *ctx )
+{
+ struct vbo_context *vbo = vbo_context(ctx);
+ struct vbo_save_context *save = &vbo->save;
+ GLuint i;
+
+ if (save->prim_store) {
+ if ( --save->prim_store->refcount == 0 ) {
+ FREE( save->prim_store );
+ save->prim_store = NULL;
+ }
+ if ( --save->vertex_store->refcount == 0 ) {
+ _mesa_reference_buffer_object(ctx,
+ &save->vertex_store->bufferobj, NULL);
+ FREE( save->vertex_store );
+ save->vertex_store = NULL;
+ }
+ }
+
+ for (i = 0; i < VBO_ATTRIB_MAX; i++) {
+ _mesa_reference_buffer_object(ctx, &save->arrays[i].BufferObj, NULL);
+ }
+}
+
+
+
+
+/* Note that this can occur during the playback of a display list:
+ */
+void vbo_save_fallback( struct gl_context *ctx, GLboolean fallback )
+{
+ struct vbo_save_context *save = &vbo_context(ctx)->save;
+
+ if (fallback)
+ save->replay_flags |= VBO_SAVE_FALLBACK;
+ else
+ save->replay_flags &= ~VBO_SAVE_FALLBACK;
+}
+
+
+#endif /* FEATURE_dlist */
diff --git a/mesalib/src/mesa/vbo/vbo_save.h b/mesalib/src/mesa/vbo/vbo_save.h
index 82ba6c8af..25704f827 100644
--- a/mesalib/src/mesa/vbo/vbo_save.h
+++ b/mesalib/src/mesa/vbo/vbo_save.h
@@ -1,199 +1,201 @@
-/**************************************************************************
-
-Copyright 2002 Tungsten Graphics Inc., Cedar Park, Texas.
-
-All Rights Reserved.
-
-Permission is hereby granted, free of charge, to any person obtaining a
-copy of this software and associated documentation files (the "Software"),
-to deal in the Software without restriction, including without limitation
-on the rights to use, copy, modify, merge, publish, distribute, sub
-license, and/or sell copies of the Software, and to permit persons to whom
-the Software is furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice (including the next
-paragraph) shall be included in all copies or substantial portions of the
-Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
-TUNGSTEN GRAPHICS AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
-DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
-OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
-USE OR OTHER DEALINGS IN THE SOFTWARE.
-
-**************************************************************************/
-
-/*
- * Authors:
- * Keith Whitwell <keith@tungstengraphics.com>
- *
- */
-
-#ifndef VBO_SAVE_H
-#define VBO_SAVE_H
-
-#include "main/mtypes.h"
-#include "vbo.h"
-#include "vbo_attrib.h"
-
-
-struct vbo_save_copied_vtx {
- GLfloat buffer[VBO_ATTRIB_MAX * 4 * VBO_MAX_COPIED_VERTS];
- GLuint nr;
-};
-
-
-/* For display lists, this structure holds a run of vertices of the
- * same format, and a strictly well-formed set of begin/end pairs,
- * starting on the first vertex and ending at the last. Vertex
- * copying on buffer breaks is precomputed according to these
- * primitives, though there are situations where the copying will need
- * correction at execute-time, perhaps by replaying the list as
- * immediate mode commands.
- *
- * On executing this list, the 'current' values may be updated with
- * the values of the final vertex, and often no fixup of the start of
- * the vertex list is required.
- *
- * Eval and other commands that don't fit into these vertex lists are
- * compiled using the fallback opcode mechanism provided by dlist.c.
- */
-struct vbo_save_vertex_list {
- GLubyte attrsz[VBO_ATTRIB_MAX];
- GLuint vertex_size;
-
- /* Copy of the final vertex from node->vertex_store->bufferobj.
- * Keep this in regular (non-VBO) memory to avoid repeated
- * map/unmap of the VBO when updating GL current data.
- */
- GLfloat *current_data;
- GLuint current_size;
-
- GLuint buffer_offset;
- GLuint count;
- GLuint wrap_count; /* number of copied vertices at start */
- GLboolean dangling_attr_ref; /* current attr implicitly referenced
- outside the list */
-
- struct _mesa_prim *prim;
- GLuint prim_count;
-
- struct vbo_save_vertex_store *vertex_store;
- struct vbo_save_primitive_store *prim_store;
-};
-
-/* These buffers should be a reasonable size to support upload to
- * hardware. Current vbo implementation will re-upload on any
- * changes, so don't make too big or apps which dynamically create
- * dlists and use only a few times will suffer.
- *
- * Consider stategy of uploading regions from the VBO on demand in the
- * case of dynamic vbos. Then make the dlist code signal that
- * likelyhood as it occurs. No reason we couldn't change usage
- * internally even though this probably isn't allowed for client VBOs?
- */
-#define VBO_SAVE_BUFFER_SIZE (8*1024) /* dwords */
-#define VBO_SAVE_PRIM_SIZE 128
-#define VBO_SAVE_PRIM_WEAK 0x40
-
-#define VBO_SAVE_FALLBACK 0x10000000
-
-/* Storage to be shared among several vertex_lists.
- */
-struct vbo_save_vertex_store {
- struct gl_buffer_object *bufferobj;
- GLfloat *buffer;
- GLuint used;
- GLuint refcount;
-};
-
-struct vbo_save_primitive_store {
- struct _mesa_prim buffer[VBO_SAVE_PRIM_SIZE];
- GLuint used;
- GLuint refcount;
-};
-
-
-struct vbo_save_context {
- GLcontext *ctx;
- GLvertexformat vtxfmt;
- struct gl_client_array arrays[VBO_ATTRIB_MAX];
- const struct gl_client_array *inputs[VBO_ATTRIB_MAX];
-
- GLubyte attrsz[VBO_ATTRIB_MAX];
- GLubyte active_sz[VBO_ATTRIB_MAX];
- GLuint vertex_size;
-
- GLfloat *buffer;
- GLuint count;
- GLuint wrap_count;
- GLuint replay_flags;
-
- struct _mesa_prim *prim;
- GLuint prim_count, prim_max;
-
- struct vbo_save_vertex_store *vertex_store;
- struct vbo_save_primitive_store *prim_store;
-
- GLfloat *buffer_ptr; /* cursor, points into buffer */
- GLfloat vertex[VBO_ATTRIB_MAX*4]; /* current values */
- GLfloat *attrptr[VBO_ATTRIB_MAX];
- GLuint vert_count;
- GLuint max_vert;
- GLboolean dangling_attr_ref;
- GLboolean have_materials;
-
- GLuint opcode_vertex_list;
-
- struct vbo_save_copied_vtx copied;
-
- GLfloat *current[VBO_ATTRIB_MAX]; /* points into ctx->ListState */
- GLubyte *currentsz[VBO_ATTRIB_MAX];
-};
-
-#if FEATURE_dlist
-
-void vbo_save_init( GLcontext *ctx );
-void vbo_save_destroy( GLcontext *ctx );
-void vbo_save_fallback( GLcontext *ctx, GLboolean fallback );
-
-/* save_loopback.c:
- */
-void vbo_loopback_vertex_list( GLcontext *ctx,
- const GLfloat *buffer,
- const GLubyte *attrsz,
- const struct _mesa_prim *prim,
- GLuint prim_count,
- GLuint wrap_count,
- GLuint vertex_size);
-
-/* Callbacks:
- */
-void vbo_save_EndList( GLcontext *ctx );
-void vbo_save_NewList( GLcontext *ctx, GLuint list, GLenum mode );
-void vbo_save_EndCallList( GLcontext *ctx );
-void vbo_save_BeginCallList( GLcontext *ctx, struct gl_display_list *list );
-void vbo_save_SaveFlushVertices( GLcontext *ctx );
-GLboolean vbo_save_NotifyBegin( GLcontext *ctx, GLenum mode );
-
-void vbo_save_playback_vertex_list( GLcontext *ctx, void *data );
-
-void vbo_save_api_init( struct vbo_save_context *save );
-
-#else /* FEATURE_dlist */
-
-static INLINE void
-vbo_save_init( GLcontext *ctx )
-{
-}
-
-static INLINE void
-vbo_save_destroy( GLcontext *ctx )
-{
-}
-
-#endif /* FEATURE_dlist */
-
-#endif /* VBO_SAVE_H */
+/**************************************************************************
+
+Copyright 2002 Tungsten Graphics Inc., Cedar Park, Texas.
+
+All Rights Reserved.
+
+Permission is hereby granted, free of charge, to any person obtaining a
+copy of this software and associated documentation files (the "Software"),
+to deal in the Software without restriction, including without limitation
+on the rights to use, copy, modify, merge, publish, distribute, sub
+license, and/or sell copies of the Software, and to permit persons to whom
+the Software is furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice (including the next
+paragraph) shall be included in all copies or substantial portions of the
+Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
+TUNGSTEN GRAPHICS AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
+DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+**************************************************************************/
+
+/*
+ * Authors:
+ * Keith Whitwell <keith@tungstengraphics.com>
+ *
+ */
+
+#ifndef VBO_SAVE_H
+#define VBO_SAVE_H
+
+#include "main/mtypes.h"
+#include "vbo.h"
+#include "vbo_attrib.h"
+
+
+struct vbo_save_copied_vtx {
+ GLfloat buffer[VBO_ATTRIB_MAX * 4 * VBO_MAX_COPIED_VERTS];
+ GLuint nr;
+};
+
+
+/* For display lists, this structure holds a run of vertices of the
+ * same format, and a strictly well-formed set of begin/end pairs,
+ * starting on the first vertex and ending at the last. Vertex
+ * copying on buffer breaks is precomputed according to these
+ * primitives, though there are situations where the copying will need
+ * correction at execute-time, perhaps by replaying the list as
+ * immediate mode commands.
+ *
+ * On executing this list, the 'current' values may be updated with
+ * the values of the final vertex, and often no fixup of the start of
+ * the vertex list is required.
+ *
+ * Eval and other commands that don't fit into these vertex lists are
+ * compiled using the fallback opcode mechanism provided by dlist.c.
+ */
+struct vbo_save_vertex_list {
+ GLubyte attrsz[VBO_ATTRIB_MAX];
+ GLuint vertex_size;
+
+ /* Copy of the final vertex from node->vertex_store->bufferobj.
+ * Keep this in regular (non-VBO) memory to avoid repeated
+ * map/unmap of the VBO when updating GL current data.
+ */
+ GLfloat *current_data;
+ GLuint current_size;
+
+ GLuint buffer_offset;
+ GLuint count;
+ GLuint wrap_count; /* number of copied vertices at start */
+ GLboolean dangling_attr_ref; /* current attr implicitly referenced
+ outside the list */
+
+ struct _mesa_prim *prim;
+ GLuint prim_count;
+
+ struct vbo_save_vertex_store *vertex_store;
+ struct vbo_save_primitive_store *prim_store;
+};
+
+/* These buffers should be a reasonable size to support upload to
+ * hardware. Current vbo implementation will re-upload on any
+ * changes, so don't make too big or apps which dynamically create
+ * dlists and use only a few times will suffer.
+ *
+ * Consider stategy of uploading regions from the VBO on demand in the
+ * case of dynamic vbos. Then make the dlist code signal that
+ * likelyhood as it occurs. No reason we couldn't change usage
+ * internally even though this probably isn't allowed for client VBOs?
+ */
+#define VBO_SAVE_BUFFER_SIZE (8*1024) /* dwords */
+#define VBO_SAVE_PRIM_SIZE 128
+#define VBO_SAVE_PRIM_MODE_MASK 0x3f
+#define VBO_SAVE_PRIM_WEAK 0x40
+#define VBO_SAVE_PRIM_NO_CURRENT_UPDATE 0x80
+
+#define VBO_SAVE_FALLBACK 0x10000000
+
+/* Storage to be shared among several vertex_lists.
+ */
+struct vbo_save_vertex_store {
+ struct gl_buffer_object *bufferobj;
+ GLfloat *buffer;
+ GLuint used;
+ GLuint refcount;
+};
+
+struct vbo_save_primitive_store {
+ struct _mesa_prim buffer[VBO_SAVE_PRIM_SIZE];
+ GLuint used;
+ GLuint refcount;
+};
+
+
+struct vbo_save_context {
+ struct gl_context *ctx;
+ GLvertexformat vtxfmt;
+ struct gl_client_array arrays[VBO_ATTRIB_MAX];
+ const struct gl_client_array *inputs[VBO_ATTRIB_MAX];
+
+ GLubyte attrsz[VBO_ATTRIB_MAX];
+ GLubyte active_sz[VBO_ATTRIB_MAX];
+ GLuint vertex_size;
+
+ GLfloat *buffer;
+ GLuint count;
+ GLuint wrap_count;
+ GLuint replay_flags;
+
+ struct _mesa_prim *prim;
+ GLuint prim_count, prim_max;
+
+ struct vbo_save_vertex_store *vertex_store;
+ struct vbo_save_primitive_store *prim_store;
+
+ GLfloat *buffer_ptr; /* cursor, points into buffer */
+ GLfloat vertex[VBO_ATTRIB_MAX*4]; /* current values */
+ GLfloat *attrptr[VBO_ATTRIB_MAX];
+ GLuint vert_count;
+ GLuint max_vert;
+ GLboolean dangling_attr_ref;
+ GLboolean have_materials;
+
+ GLuint opcode_vertex_list;
+
+ struct vbo_save_copied_vtx copied;
+
+ GLfloat *current[VBO_ATTRIB_MAX]; /* points into ctx->ListState */
+ GLubyte *currentsz[VBO_ATTRIB_MAX];
+};
+
+#if FEATURE_dlist
+
+void vbo_save_init( struct gl_context *ctx );
+void vbo_save_destroy( struct gl_context *ctx );
+void vbo_save_fallback( struct gl_context *ctx, GLboolean fallback );
+
+/* save_loopback.c:
+ */
+void vbo_loopback_vertex_list( struct gl_context *ctx,
+ const GLfloat *buffer,
+ const GLubyte *attrsz,
+ const struct _mesa_prim *prim,
+ GLuint prim_count,
+ GLuint wrap_count,
+ GLuint vertex_size);
+
+/* Callbacks:
+ */
+void vbo_save_EndList( struct gl_context *ctx );
+void vbo_save_NewList( struct gl_context *ctx, GLuint list, GLenum mode );
+void vbo_save_EndCallList( struct gl_context *ctx );
+void vbo_save_BeginCallList( struct gl_context *ctx, struct gl_display_list *list );
+void vbo_save_SaveFlushVertices( struct gl_context *ctx );
+GLboolean vbo_save_NotifyBegin( struct gl_context *ctx, GLenum mode );
+
+void vbo_save_playback_vertex_list( struct gl_context *ctx, void *data );
+
+void vbo_save_api_init( struct vbo_save_context *save );
+
+#else /* FEATURE_dlist */
+
+static INLINE void
+vbo_save_init( struct gl_context *ctx )
+{
+}
+
+static INLINE void
+vbo_save_destroy( struct gl_context *ctx )
+{
+}
+
+#endif /* FEATURE_dlist */
+
+#endif /* VBO_SAVE_H */
diff --git a/mesalib/src/mesa/vbo/vbo_save_api.c b/mesalib/src/mesa/vbo/vbo_save_api.c
index c3727cb52..7c928820a 100644
--- a/mesalib/src/mesa/vbo/vbo_save_api.c
+++ b/mesalib/src/mesa/vbo/vbo_save_api.c
@@ -1,1270 +1,1309 @@
-/**************************************************************************
-
-Copyright 2002-2008 Tungsten Graphics Inc., Cedar Park, Texas.
-
-All Rights Reserved.
-
-Permission is hereby granted, free of charge, to any person obtaining a
-copy of this software and associated documentation files (the "Software"),
-to deal in the Software without restriction, including without limitation
-on the rights to use, copy, modify, merge, publish, distribute, sub
-license, and/or sell copies of the Software, and to permit persons to whom
-the Software is furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice (including the next
-paragraph) shall be included in all copies or substantial portions of the
-Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
-TUNGSTEN GRAPHICS AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
-DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
-OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
-USE OR OTHER DEALINGS IN THE SOFTWARE.
-
-**************************************************************************/
-
-/*
- * Authors:
- * Keith Whitwell <keith@tungstengraphics.com>
- */
-
-
-
-/* Display list compiler attempts to store lists of vertices with the
- * same vertex layout. Additionally it attempts to minimize the need
- * for execute-time fixup of these vertex lists, allowing them to be
- * cached on hardware.
- *
- * There are still some circumstances where this can be thwarted, for
- * example by building a list that consists of one very long primitive
- * (eg Begin(Triangles), 1000 vertices, End), and calling that list
- * from inside a different begin/end object (Begin(Lines), CallList,
- * End).
- *
- * In that case the code will have to replay the list as individual
- * commands through the Exec dispatch table, or fix up the copied
- * vertices at execute-time.
- *
- * The other case where fixup is required is when a vertex attribute
- * is introduced in the middle of a primitive. Eg:
- * Begin(Lines)
- * TexCoord1f() Vertex2f()
- * TexCoord1f() Color3f() Vertex2f()
- * End()
- *
- * If the current value of Color isn't known at compile-time, this
- * primitive will require fixup.
- *
- *
- * The list compiler currently doesn't attempt to compile lists
- * containing EvalCoord or EvalPoint commands. On encountering one of
- * these, compilation falls back to opcodes.
- *
- * This could be improved to fallback only when a mix of EvalCoord and
- * Vertex commands are issued within a single primitive.
- */
-
-
-#include "main/glheader.h"
-#include "main/bufferobj.h"
-#include "main/context.h"
-#include "main/dlist.h"
-#include "main/enums.h"
-#include "main/eval.h"
-#include "main/macros.h"
-#include "main/api_noop.h"
-#include "main/api_validate.h"
-#include "main/api_arrayelt.h"
-#include "main/vtxfmt.h"
-#include "main/dispatch.h"
-
-#include "vbo_context.h"
-
-
-#if FEATURE_dlist
-
-
-#ifdef ERROR
-#undef ERROR
-#endif
-
-
-/* An interesting VBO number/name to help with debugging */
-#define VBO_BUF_ID 12345
-
-
-/*
- * NOTE: Old 'parity' issue is gone, but copying can still be
- * wrong-footed on replay.
- */
-static GLuint _save_copy_vertices( GLcontext *ctx,
- const struct vbo_save_vertex_list *node,
- const GLfloat *src_buffer)
-{
- struct vbo_save_context *save = &vbo_context( ctx )->save;
- const struct _mesa_prim *prim = &node->prim[node->prim_count-1];
- GLuint nr = prim->count;
- GLuint sz = save->vertex_size;
- const GLfloat *src = src_buffer + prim->start * sz;
- GLfloat *dst = save->copied.buffer;
- GLuint ovf, i;
-
- if (prim->end)
- return 0;
-
- switch( prim->mode )
- {
- case GL_POINTS:
- return 0;
- case GL_LINES:
- ovf = nr&1;
- for (i = 0 ; i < ovf ; i++)
- memcpy( dst+i*sz, src+(nr-ovf+i)*sz, sz*sizeof(GLfloat) );
- return i;
- case GL_TRIANGLES:
- ovf = nr%3;
- for (i = 0 ; i < ovf ; i++)
- memcpy( dst+i*sz, src+(nr-ovf+i)*sz, sz*sizeof(GLfloat) );
- return i;
- case GL_QUADS:
- ovf = nr&3;
- for (i = 0 ; i < ovf ; i++)
- memcpy( dst+i*sz, src+(nr-ovf+i)*sz, sz*sizeof(GLfloat) );
- return i;
- case GL_LINE_STRIP:
- if (nr == 0)
- return 0;
- else {
- memcpy( dst, src+(nr-1)*sz, sz*sizeof(GLfloat) );
- return 1;
- }
- case GL_LINE_LOOP:
- case GL_TRIANGLE_FAN:
- case GL_POLYGON:
- if (nr == 0)
- return 0;
- else if (nr == 1) {
- memcpy( dst, src+0, sz*sizeof(GLfloat) );
- return 1;
- } else {
- memcpy( dst, src+0, sz*sizeof(GLfloat) );
- memcpy( dst+sz, src+(nr-1)*sz, sz*sizeof(GLfloat) );
- return 2;
- }
- case GL_TRIANGLE_STRIP:
- case GL_QUAD_STRIP:
- switch (nr) {
- case 0: ovf = 0; break;
- case 1: ovf = 1; break;
- default: ovf = 2 + (nr&1); break;
- }
- for (i = 0 ; i < ovf ; i++)
- memcpy( dst+i*sz, src+(nr-ovf+i)*sz, sz*sizeof(GLfloat) );
- return i;
- default:
- assert(0);
- return 0;
- }
-}
-
-
-static struct vbo_save_vertex_store *alloc_vertex_store( GLcontext *ctx )
-{
- struct vbo_save_vertex_store *vertex_store = CALLOC_STRUCT(vbo_save_vertex_store);
-
- /* obj->Name needs to be non-zero, but won't ever be examined more
- * closely than that. In particular these buffers won't be entered
- * into the hash and can never be confused with ones visible to the
- * user. Perhaps there could be a special number for internal
- * buffers:
- */
- vertex_store->bufferobj = ctx->Driver.NewBufferObject(ctx,
- VBO_BUF_ID,
- GL_ARRAY_BUFFER_ARB);
-
- ctx->Driver.BufferData( ctx,
- GL_ARRAY_BUFFER_ARB,
- VBO_SAVE_BUFFER_SIZE * sizeof(GLfloat),
- NULL,
- GL_STATIC_DRAW_ARB,
- vertex_store->bufferobj);
-
- vertex_store->buffer = NULL;
- vertex_store->used = 0;
- vertex_store->refcount = 1;
-
- return vertex_store;
-}
-
-static void free_vertex_store( GLcontext *ctx, struct vbo_save_vertex_store *vertex_store )
-{
- assert(!vertex_store->buffer);
-
- if (vertex_store->bufferobj) {
- _mesa_reference_buffer_object(ctx, &vertex_store->bufferobj, NULL);
- }
-
- FREE( vertex_store );
-}
-
-static GLfloat *map_vertex_store( GLcontext *ctx, struct vbo_save_vertex_store *vertex_store )
-{
- assert(vertex_store->bufferobj);
- assert(!vertex_store->buffer);
- vertex_store->buffer = (GLfloat *)ctx->Driver.MapBuffer(ctx,
- GL_ARRAY_BUFFER_ARB, /* not used */
- GL_WRITE_ONLY, /* not used */
- vertex_store->bufferobj);
-
- assert(vertex_store->buffer);
- return vertex_store->buffer + vertex_store->used;
-}
-
-static void unmap_vertex_store( GLcontext *ctx, struct vbo_save_vertex_store *vertex_store )
-{
- ctx->Driver.UnmapBuffer( ctx, GL_ARRAY_BUFFER_ARB, vertex_store->bufferobj );
- vertex_store->buffer = NULL;
-}
-
-
-static struct vbo_save_primitive_store *alloc_prim_store( GLcontext *ctx )
-{
- struct vbo_save_primitive_store *store = CALLOC_STRUCT(vbo_save_primitive_store);
- (void) ctx;
- store->used = 0;
- store->refcount = 1;
- return store;
-}
-
-static void _save_reset_counters( GLcontext *ctx )
-{
- struct vbo_save_context *save = &vbo_context(ctx)->save;
-
- save->prim = save->prim_store->buffer + save->prim_store->used;
- save->buffer = (save->vertex_store->buffer +
- save->vertex_store->used);
-
- assert(save->buffer == save->buffer_ptr);
-
- if (save->vertex_size)
- save->max_vert = ((VBO_SAVE_BUFFER_SIZE - save->vertex_store->used) /
- save->vertex_size);
- else
- save->max_vert = 0;
-
- save->vert_count = 0;
- save->prim_count = 0;
- save->prim_max = VBO_SAVE_PRIM_SIZE - save->prim_store->used;
- save->dangling_attr_ref = 0;
-}
-
-
-/* Insert the active immediate struct onto the display list currently
- * being built.
- */
-static void _save_compile_vertex_list( GLcontext *ctx )
-{
- struct vbo_save_context *save = &vbo_context(ctx)->save;
- struct vbo_save_vertex_list *node;
-
- /* Allocate space for this structure in the display list currently
- * being compiled.
- */
- node = (struct vbo_save_vertex_list *)
- _mesa_dlist_alloc(ctx, save->opcode_vertex_list, sizeof(*node));
-
- if (!node)
- return;
-
- /* Duplicate our template, increment refcounts to the storage structs:
- */
- memcpy(node->attrsz, save->attrsz, sizeof(node->attrsz));
- node->vertex_size = save->vertex_size;
- node->buffer_offset = (save->buffer - save->vertex_store->buffer) * sizeof(GLfloat);
- node->count = save->vert_count;
- node->wrap_count = save->copied.nr;
- node->dangling_attr_ref = save->dangling_attr_ref;
- node->prim = save->prim;
- node->prim_count = save->prim_count;
- node->vertex_store = save->vertex_store;
- node->prim_store = save->prim_store;
-
- node->vertex_store->refcount++;
- node->prim_store->refcount++;
-
-
- node->current_size = node->vertex_size - node->attrsz[0];
- node->current_data = NULL;
-
- if (node->current_size) {
- /* If the malloc fails, we just pull the data out of the VBO
- * later instead.
- */
- node->current_data = MALLOC( node->current_size * sizeof(GLfloat) );
- if (node->current_data) {
- const char *buffer = (const char *)save->vertex_store->buffer;
- unsigned attr_offset = node->attrsz[0] * sizeof(GLfloat);
- unsigned vertex_offset = 0;
-
- if (node->count)
- vertex_offset = (node->count-1) * node->vertex_size * sizeof(GLfloat);
-
- memcpy( node->current_data,
- buffer + node->buffer_offset + vertex_offset + attr_offset,
- node->current_size * sizeof(GLfloat) );
- }
- }
-
-
-
- assert(node->attrsz[VBO_ATTRIB_POS] != 0 ||
- node->count == 0);
-
- if (save->dangling_attr_ref)
- ctx->ListState.CurrentList->Flags |= DLIST_DANGLING_REFS;
-
- save->vertex_store->used += save->vertex_size * node->count;
- save->prim_store->used += node->prim_count;
-
-
- /* Copy duplicated vertices
- */
- save->copied.nr = _save_copy_vertices( ctx, node, save->buffer );
-
-
- /* Deal with GL_COMPILE_AND_EXECUTE:
- */
- if (ctx->ExecuteFlag) {
- struct _glapi_table *dispatch = GET_DISPATCH();
-
- _glapi_set_dispatch(ctx->Exec);
-
- vbo_loopback_vertex_list( ctx,
- (const GLfloat *)((const char *)save->vertex_store->buffer +
- node->buffer_offset),
- node->attrsz,
- node->prim,
- node->prim_count,
- node->wrap_count,
- node->vertex_size);
-
- _glapi_set_dispatch(dispatch);
- }
-
-
- /* Decide whether the storage structs are full, or can be used for
- * the next vertex lists as well.
- */
- if (save->vertex_store->used >
- VBO_SAVE_BUFFER_SIZE - 16 * (save->vertex_size + 4)) {
-
- /* Unmap old store:
- */
- unmap_vertex_store( ctx, save->vertex_store );
-
- /* Release old reference:
- */
- save->vertex_store->refcount--;
- assert(save->vertex_store->refcount != 0);
- save->vertex_store = NULL;
-
- /* Allocate and map new store:
- */
- save->vertex_store = alloc_vertex_store( ctx );
- save->buffer_ptr = map_vertex_store( ctx, save->vertex_store );
- }
-
- if (save->prim_store->used > VBO_SAVE_PRIM_SIZE - 6) {
- save->prim_store->refcount--;
- assert(save->prim_store->refcount != 0);
- save->prim_store = alloc_prim_store( ctx );
- }
-
- /* Reset our structures for the next run of vertices:
- */
- _save_reset_counters( ctx );
-}
-
-
-/* TODO -- If no new vertices have been stored, don't bother saving
- * it.
- */
-static void _save_wrap_buffers( GLcontext *ctx )
-{
- struct vbo_save_context *save = &vbo_context(ctx)->save;
- GLint i = save->prim_count - 1;
- GLenum mode;
- GLboolean weak;
-
- assert(i < (GLint) save->prim_max);
- assert(i >= 0);
-
- /* Close off in-progress primitive.
- */
- save->prim[i].count = (save->vert_count -
- save->prim[i].start);
- mode = save->prim[i].mode;
- weak = save->prim[i].weak;
-
- /* store the copied vertices, and allocate a new list.
- */
- _save_compile_vertex_list( ctx );
-
- /* Restart interrupted primitive
- */
- save->prim[0].mode = mode;
- save->prim[0].weak = weak;
- save->prim[0].begin = 0;
- save->prim[0].end = 0;
- save->prim[0].pad = 0;
- save->prim[0].start = 0;
- save->prim[0].count = 0;
- save->prim[0].num_instances = 1;
- save->prim_count = 1;
-}
-
-
-
-/* Called only when buffers are wrapped as the result of filling the
- * vertex_store struct.
- */
-static void _save_wrap_filled_vertex( GLcontext *ctx )
-{
- struct vbo_save_context *save = &vbo_context(ctx)->save;
- GLfloat *data = save->copied.buffer;
- GLuint i;
-
- /* Emit a glEnd to close off the last vertex list.
- */
- _save_wrap_buffers( ctx );
-
- /* Copy stored stored vertices to start of new list.
- */
- assert(save->max_vert - save->vert_count > save->copied.nr);
-
- for (i = 0 ; i < save->copied.nr ; i++) {
- memcpy( save->buffer_ptr, data, save->vertex_size * sizeof(GLfloat));
- data += save->vertex_size;
- save->buffer_ptr += save->vertex_size;
- save->vert_count++;
- }
-}
-
-
-static void _save_copy_to_current( GLcontext *ctx )
-{
- struct vbo_save_context *save = &vbo_context(ctx)->save;
- GLuint i;
-
- for (i = VBO_ATTRIB_POS+1 ; i < VBO_ATTRIB_MAX ; i++) {
- if (save->attrsz[i]) {
- save->currentsz[i][0] = save->attrsz[i];
- COPY_CLEAN_4V(save->current[i],
- save->attrsz[i],
- save->attrptr[i]);
- }
- }
-}
-
-
-static void _save_copy_from_current( GLcontext *ctx )
-{
- struct vbo_save_context *save = &vbo_context(ctx)->save;
- GLint i;
-
- for (i = VBO_ATTRIB_POS+1 ; i < VBO_ATTRIB_MAX ; i++) {
- switch (save->attrsz[i]) {
- case 4: save->attrptr[i][3] = save->current[i][3];
- case 3: save->attrptr[i][2] = save->current[i][2];
- case 2: save->attrptr[i][1] = save->current[i][1];
- case 1: save->attrptr[i][0] = save->current[i][0];
- case 0: break;
- }
- }
-}
-
-
-
-
-/* Flush existing data, set new attrib size, replay copied vertices.
- */
-static void _save_upgrade_vertex( GLcontext *ctx,
- GLuint attr,
- GLuint newsz )
-{
- struct vbo_save_context *save = &vbo_context(ctx)->save;
- GLuint oldsz;
- GLuint i;
- GLfloat *tmp;
-
- /* Store the current run of vertices, and emit a GL_END. Emit a
- * BEGIN in the new buffer.
- */
- if (save->vert_count)
- _save_wrap_buffers( ctx );
- else
- assert( save->copied.nr == 0 );
-
- /* Do a COPY_TO_CURRENT to ensure back-copying works for the case
- * when the attribute already exists in the vertex and is having
- * its size increased.
- */
- _save_copy_to_current( ctx );
-
- /* Fix up sizes:
- */
- oldsz = save->attrsz[attr];
- save->attrsz[attr] = newsz;
-
- save->vertex_size += newsz - oldsz;
- save->max_vert = ((VBO_SAVE_BUFFER_SIZE - save->vertex_store->used) /
- save->vertex_size);
- save->vert_count = 0;
-
- /* Recalculate all the attrptr[] values:
- */
- for (i = 0, tmp = save->vertex ; i < VBO_ATTRIB_MAX ; i++) {
- if (save->attrsz[i]) {
- save->attrptr[i] = tmp;
- tmp += save->attrsz[i];
- }
- else
- save->attrptr[i] = NULL; /* will not be dereferenced. */
- }
-
- /* Copy from current to repopulate the vertex with correct values.
- */
- _save_copy_from_current( ctx );
-
- /* Replay stored vertices to translate them to new format here.
- *
- * If there are copied vertices and the new (upgraded) attribute
- * has not been defined before, this list is somewhat degenerate,
- * and will need fixup at runtime.
- */
- if (save->copied.nr)
- {
- GLfloat *data = save->copied.buffer;
- GLfloat *dest = save->buffer;
- GLuint j;
-
- /* Need to note this and fix up at runtime (or loopback):
- */
- if (attr != VBO_ATTRIB_POS && save->currentsz[attr][0] == 0) {
- assert(oldsz == 0);
- save->dangling_attr_ref = GL_TRUE;
- }
-
- for (i = 0 ; i < save->copied.nr ; i++) {
- for (j = 0 ; j < VBO_ATTRIB_MAX ; j++) {
- if (save->attrsz[j]) {
- if (j == attr) {
- if (oldsz) {
- COPY_CLEAN_4V( dest, oldsz, data );
- data += oldsz;
- dest += newsz;
- }
- else {
- COPY_SZ_4V( dest, newsz, save->current[attr] );
- dest += newsz;
- }
- }
- else {
- GLint sz = save->attrsz[j];
- COPY_SZ_4V( dest, sz, data );
- data += sz;
- dest += sz;
- }
- }
- }
- }
-
- save->buffer_ptr = dest;
- save->vert_count += save->copied.nr;
- }
-}
-
-static void save_fixup_vertex( GLcontext *ctx, GLuint attr, GLuint sz )
-{
- struct vbo_save_context *save = &vbo_context(ctx)->save;
-
- if (sz > save->attrsz[attr]) {
- /* New size is larger. Need to flush existing vertices and get
- * an enlarged vertex format.
- */
- _save_upgrade_vertex( ctx, attr, sz );
- }
- else if (sz < save->active_sz[attr]) {
- static GLfloat id[4] = { 0, 0, 0, 1 };
- GLuint i;
-
- /* New size is equal or smaller - just need to fill in some
- * zeros.
- */
- for (i = sz ; i <= save->attrsz[attr] ; i++)
- save->attrptr[attr][i-1] = id[i-1];
- }
-
- save->active_sz[attr] = sz;
-}
-
-static void _save_reset_vertex( GLcontext *ctx )
-{
- struct vbo_save_context *save = &vbo_context(ctx)->save;
- GLuint i;
-
- for (i = 0 ; i < VBO_ATTRIB_MAX ; i++) {
- save->attrsz[i] = 0;
- save->active_sz[i] = 0;
- }
-
- save->vertex_size = 0;
-}
-
-
-
-#define ERROR() _mesa_compile_error( ctx, GL_INVALID_ENUM, __FUNCTION__ );
-
-
-/* Only one size for each attribute may be active at once. Eg. if
- * Color3f is installed/active, then Color4f may not be, even if the
- * vertex actually contains 4 color coordinates. This is because the
- * 3f version won't otherwise set color[3] to 1.0 -- this is the job
- * of the chooser function when switching between Color4f and Color3f.
- */
-#define ATTR( A, N, V0, V1, V2, V3 ) \
-do { \
- struct vbo_save_context *save = &vbo_context(ctx)->save; \
- \
- if (save->active_sz[A] != N) \
- save_fixup_vertex(ctx, A, N); \
- \
- { \
- GLfloat *dest = save->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; \
- } \
- \
- if ((A) == 0) { \
- GLuint i; \
- \
- for (i = 0; i < save->vertex_size; i++) \
- save->buffer_ptr[i] = save->vertex[i]; \
- \
- save->buffer_ptr += save->vertex_size; \
- \
- if (++save->vert_count >= save->max_vert) \
- _save_wrap_filled_vertex( ctx ); \
- } \
-} while (0)
-
-#define TAG(x) _save_##x
-
-#include "vbo_attrib_tmp.h"
-
-
-
-
-/* Cope with EvalCoord/CallList called within a begin/end object:
- * -- Flush current buffer
- * -- Fallback to opcodes for the rest of the begin/end object.
- */
-static void DO_FALLBACK( GLcontext *ctx )
-{
- struct vbo_save_context *save = &vbo_context(ctx)->save;
-
- if (save->vert_count || save->prim_count) {
- GLint i = save->prim_count - 1;
-
- /* Close off in-progress primitive.
- */
- save->prim[i].count = (save->vert_count -
- save->prim[i].start);
-
- /* Need to replay this display list with loopback,
- * unfortunately, otherwise this primitive won't be handled
- * properly:
- */
- save->dangling_attr_ref = 1;
-
- _save_compile_vertex_list( ctx );
- }
-
- _save_copy_to_current( ctx );
- _save_reset_vertex( ctx );
- _save_reset_counters( ctx );
- _mesa_install_save_vtxfmt( ctx, &ctx->ListState.ListVtxfmt );
- ctx->Driver.SaveNeedFlush = 0;
-}
-
-static void GLAPIENTRY _save_EvalCoord1f( GLfloat u )
-{
- GET_CURRENT_CONTEXT(ctx);
- DO_FALLBACK(ctx);
- ctx->Save->EvalCoord1f( u );
-}
-
-static void GLAPIENTRY _save_EvalCoord1fv( const GLfloat *v )
-{
- GET_CURRENT_CONTEXT(ctx);
- DO_FALLBACK(ctx);
- ctx->Save->EvalCoord1fv( v );
-}
-
-static void GLAPIENTRY _save_EvalCoord2f( GLfloat u, GLfloat v )
-{
- GET_CURRENT_CONTEXT(ctx);
- DO_FALLBACK(ctx);
- ctx->Save->EvalCoord2f( u, v );
-}
-
-static void GLAPIENTRY _save_EvalCoord2fv( const GLfloat *v )
-{
- GET_CURRENT_CONTEXT(ctx);
- DO_FALLBACK(ctx);
- ctx->Save->EvalCoord2fv( v );
-}
-
-static void GLAPIENTRY _save_EvalPoint1( GLint i )
-{
- GET_CURRENT_CONTEXT(ctx);
- DO_FALLBACK(ctx);
- ctx->Save->EvalPoint1( i );
-}
-
-static void GLAPIENTRY _save_EvalPoint2( GLint i, GLint j )
-{
- GET_CURRENT_CONTEXT(ctx);
- DO_FALLBACK(ctx);
- ctx->Save->EvalPoint2( i, j );
-}
-
-static void GLAPIENTRY _save_CallList( GLuint l )
-{
- GET_CURRENT_CONTEXT(ctx);
- DO_FALLBACK(ctx);
- ctx->Save->CallList( l );
-}
-
-static void GLAPIENTRY _save_CallLists( GLsizei n, GLenum type, const GLvoid *v )
-{
- GET_CURRENT_CONTEXT(ctx);
- DO_FALLBACK(ctx);
- ctx->Save->CallLists( n, type, v );
-}
-
-
-
-
-/* This begin is hooked into ... Updating of
- * ctx->Driver.CurrentSavePrimitive is already taken care of.
- */
-GLboolean vbo_save_NotifyBegin( GLcontext *ctx, GLenum mode )
-{
- struct vbo_save_context *save = &vbo_context(ctx)->save;
-
- GLuint i = save->prim_count++;
-
- assert(i < save->prim_max);
- save->prim[i].mode = mode & ~VBO_SAVE_PRIM_WEAK;
- save->prim[i].begin = 1;
- save->prim[i].end = 0;
- save->prim[i].weak = (mode & VBO_SAVE_PRIM_WEAK) ? 1 : 0;
- save->prim[i].pad = 0;
- save->prim[i].start = save->vert_count;
- save->prim[i].count = 0;
- save->prim[i].num_instances = 1;
-
- _mesa_install_save_vtxfmt( ctx, &save->vtxfmt );
- ctx->Driver.SaveNeedFlush = 1;
- return GL_TRUE;
-}
-
-
-
-static void GLAPIENTRY _save_End( void )
-{
- GET_CURRENT_CONTEXT( ctx );
- struct vbo_save_context *save = &vbo_context(ctx)->save;
- GLint i = save->prim_count - 1;
-
- ctx->Driver.CurrentSavePrimitive = PRIM_OUTSIDE_BEGIN_END;
- save->prim[i].end = 1;
- save->prim[i].count = (save->vert_count -
- save->prim[i].start);
-
- if (i == (GLint) save->prim_max - 1) {
- _save_compile_vertex_list( ctx );
- assert(save->copied.nr == 0);
- }
-
- /* Swap out this vertex format while outside begin/end. Any color,
- * etc. received between here and the next begin will be compiled
- * as opcodes.
- */
- _mesa_install_save_vtxfmt( ctx, &ctx->ListState.ListVtxfmt );
-}
-
-
-/* These are all errors as this vtxfmt is only installed inside
- * begin/end pairs.
- */
-static void GLAPIENTRY _save_DrawElements(GLenum mode, GLsizei count, GLenum type,
- const GLvoid *indices)
-{
- GET_CURRENT_CONTEXT(ctx);
- (void) mode; (void) count; (void) type; (void) indices;
- _mesa_compile_error( ctx, GL_INVALID_OPERATION, "glDrawElements" );
-}
-
-
-static void GLAPIENTRY _save_DrawRangeElements(GLenum mode,
- GLuint start, GLuint end,
- GLsizei count, GLenum type,
- const GLvoid *indices)
-{
- GET_CURRENT_CONTEXT(ctx);
- (void) mode; (void) start; (void) end; (void) count; (void) type; (void) indices;
- _mesa_compile_error( ctx, GL_INVALID_OPERATION, "glDrawRangeElements" );
-}
-
-static void GLAPIENTRY _save_DrawElementsBaseVertex(GLenum mode,
- GLsizei count,
- GLenum type,
- const GLvoid *indices,
- GLint basevertex)
-{
- GET_CURRENT_CONTEXT(ctx);
- (void) mode; (void) count; (void) type; (void) indices; (void)basevertex;
-
- _mesa_compile_error( ctx, GL_INVALID_OPERATION, "glDrawElements" );
-}
-
-static void GLAPIENTRY _save_DrawRangeElementsBaseVertex(GLenum mode,
- GLuint start,
- GLuint end,
- GLsizei count,
- GLenum type,
- const GLvoid *indices,
- GLint basevertex)
-{
- GET_CURRENT_CONTEXT(ctx);
- (void) mode; (void) start; (void) end; (void) count; (void) type;
- (void) indices; (void)basevertex;
-
- _mesa_compile_error( ctx, GL_INVALID_OPERATION, "glDrawRangeElements" );
-}
-
-static void GLAPIENTRY _save_DrawArrays(GLenum mode, GLint start, GLsizei count)
-{
- GET_CURRENT_CONTEXT(ctx);
- (void) mode; (void) start; (void) count;
- _mesa_compile_error( ctx, GL_INVALID_OPERATION, "glDrawArrays" );
-}
-
-static void GLAPIENTRY _save_Rectf( GLfloat x1, GLfloat y1, GLfloat x2, GLfloat y2 )
-{
- GET_CURRENT_CONTEXT(ctx);
- (void) x1; (void) y1; (void) x2; (void) y2;
- _mesa_compile_error( ctx, GL_INVALID_OPERATION, "glRectf" );
-}
-
-static void GLAPIENTRY _save_EvalMesh1( GLenum mode, GLint i1, GLint i2 )
-{
- GET_CURRENT_CONTEXT(ctx);
- (void) mode; (void) i1; (void) i2;
- _mesa_compile_error( ctx, GL_INVALID_OPERATION, "glEvalMesh1" );
-}
-
-static void GLAPIENTRY _save_EvalMesh2( GLenum mode, GLint i1, GLint i2,
- GLint j1, GLint j2 )
-{
- GET_CURRENT_CONTEXT(ctx);
- (void) mode; (void) i1; (void) i2; (void) j1; (void) j2;
- _mesa_compile_error( ctx, GL_INVALID_OPERATION, "glEvalMesh2" );
-}
-
-static void GLAPIENTRY _save_Begin( GLenum mode )
-{
- GET_CURRENT_CONTEXT( ctx );
- (void) mode;
- _mesa_compile_error( ctx, GL_INVALID_OPERATION, "Recursive glBegin" );
-}
-
-
-/* Unlike the functions above, these are to be hooked into the vtxfmt
- * maintained in ctx->ListState, active when the list is known or
- * suspected to be outside any begin/end primitive.
- */
-static void GLAPIENTRY _save_OBE_Rectf( GLfloat x1, GLfloat y1, GLfloat x2, GLfloat y2 )
-{
- GET_CURRENT_CONTEXT(ctx);
- vbo_save_NotifyBegin( ctx, GL_QUADS | VBO_SAVE_PRIM_WEAK );
- CALL_Vertex2f(GET_DISPATCH(), ( x1, y1 ));
- CALL_Vertex2f(GET_DISPATCH(), ( x2, y1 ));
- CALL_Vertex2f(GET_DISPATCH(), ( x2, y2 ));
- CALL_Vertex2f(GET_DISPATCH(), ( x1, y2 ));
- CALL_End(GET_DISPATCH(), ());
-}
-
-
-static void GLAPIENTRY _save_OBE_DrawArrays(GLenum mode, GLint start, GLsizei count)
-{
- GET_CURRENT_CONTEXT(ctx);
- GLint i;
-
- if (!_mesa_validate_DrawArrays( ctx, mode, start, count ))
- return;
-
- _ae_map_vbos( ctx );
-
- vbo_save_NotifyBegin( ctx, mode | VBO_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
- * then emitting an indexed prim at runtime.
- */
-static void GLAPIENTRY _save_OBE_DrawElements(GLenum mode, GLsizei count, GLenum type,
- const GLvoid *indices)
-{
- GET_CURRENT_CONTEXT(ctx);
- GLint i;
-
- if (!_mesa_validate_DrawElements( ctx, mode, count, type, indices, 0 ))
- return;
-
- _ae_map_vbos( ctx );
-
- if (_mesa_is_bufferobj(ctx->Array.ElementArrayBufferObj))
- indices = ADD_POINTERS(ctx->Array.ElementArrayBufferObj->Pointer, indices);
-
- vbo_save_NotifyBegin( ctx, mode | VBO_SAVE_PRIM_WEAK );
-
- switch (type) {
- case GL_UNSIGNED_BYTE:
- for (i = 0 ; i < count ; i++)
- CALL_ArrayElement(GET_DISPATCH(), ( ((GLubyte *)indices)[i] ));
- break;
- case GL_UNSIGNED_SHORT:
- for (i = 0 ; i < count ; i++)
- CALL_ArrayElement(GET_DISPATCH(), ( ((GLushort *)indices)[i] ));
- break;
- case GL_UNSIGNED_INT:
- for (i = 0 ; i < count ; i++)
- CALL_ArrayElement(GET_DISPATCH(), ( ((GLuint *)indices)[i] ));
- break;
- default:
- _mesa_error( ctx, GL_INVALID_ENUM, "glDrawElements(type)" );
- break;
- }
-
- CALL_End(GET_DISPATCH(), ());
-
- _ae_unmap_vbos( ctx );
-}
-
-static void GLAPIENTRY _save_OBE_DrawRangeElements(GLenum mode,
- GLuint start, GLuint end,
- GLsizei count, GLenum type,
- const GLvoid *indices)
-{
- GET_CURRENT_CONTEXT(ctx);
- if (_mesa_validate_DrawRangeElements( ctx, mode,
- start, end,
- count, type, indices, 0 ))
- _save_OBE_DrawElements( mode, count, type, indices );
-}
-
-
-
-
-
-static void _save_vtxfmt_init( GLcontext *ctx )
-{
- struct vbo_save_context *save = &vbo_context(ctx)->save;
- GLvertexformat *vfmt = &save->vtxfmt;
-
- _MESA_INIT_ARRAYELT_VTXFMT(vfmt, _ae_);
-
- vfmt->Begin = _save_Begin;
- vfmt->Color3f = _save_Color3f;
- vfmt->Color3fv = _save_Color3fv;
- vfmt->Color4f = _save_Color4f;
- vfmt->Color4fv = _save_Color4fv;
- vfmt->EdgeFlag = _save_EdgeFlag;
- vfmt->End = _save_End;
- vfmt->FogCoordfEXT = _save_FogCoordfEXT;
- vfmt->FogCoordfvEXT = _save_FogCoordfvEXT;
- vfmt->Indexf = _save_Indexf;
- vfmt->Indexfv = _save_Indexfv;
- vfmt->Materialfv = _save_Materialfv;
- vfmt->MultiTexCoord1fARB = _save_MultiTexCoord1f;
- vfmt->MultiTexCoord1fvARB = _save_MultiTexCoord1fv;
- vfmt->MultiTexCoord2fARB = _save_MultiTexCoord2f;
- vfmt->MultiTexCoord2fvARB = _save_MultiTexCoord2fv;
- vfmt->MultiTexCoord3fARB = _save_MultiTexCoord3f;
- vfmt->MultiTexCoord3fvARB = _save_MultiTexCoord3fv;
- vfmt->MultiTexCoord4fARB = _save_MultiTexCoord4f;
- vfmt->MultiTexCoord4fvARB = _save_MultiTexCoord4fv;
- vfmt->Normal3f = _save_Normal3f;
- vfmt->Normal3fv = _save_Normal3fv;
- vfmt->SecondaryColor3fEXT = _save_SecondaryColor3fEXT;
- vfmt->SecondaryColor3fvEXT = _save_SecondaryColor3fvEXT;
- vfmt->TexCoord1f = _save_TexCoord1f;
- vfmt->TexCoord1fv = _save_TexCoord1fv;
- vfmt->TexCoord2f = _save_TexCoord2f;
- vfmt->TexCoord2fv = _save_TexCoord2fv;
- vfmt->TexCoord3f = _save_TexCoord3f;
- vfmt->TexCoord3fv = _save_TexCoord3fv;
- vfmt->TexCoord4f = _save_TexCoord4f;
- vfmt->TexCoord4fv = _save_TexCoord4fv;
- vfmt->Vertex2f = _save_Vertex2f;
- vfmt->Vertex2fv = _save_Vertex2fv;
- vfmt->Vertex3f = _save_Vertex3f;
- vfmt->Vertex3fv = _save_Vertex3fv;
- vfmt->Vertex4f = _save_Vertex4f;
- vfmt->Vertex4fv = _save_Vertex4fv;
- vfmt->VertexAttrib1fARB = _save_VertexAttrib1fARB;
- vfmt->VertexAttrib1fvARB = _save_VertexAttrib1fvARB;
- vfmt->VertexAttrib2fARB = _save_VertexAttrib2fARB;
- vfmt->VertexAttrib2fvARB = _save_VertexAttrib2fvARB;
- vfmt->VertexAttrib3fARB = _save_VertexAttrib3fARB;
- vfmt->VertexAttrib3fvARB = _save_VertexAttrib3fvARB;
- vfmt->VertexAttrib4fARB = _save_VertexAttrib4fARB;
- vfmt->VertexAttrib4fvARB = _save_VertexAttrib4fvARB;
-
- vfmt->VertexAttrib1fNV = _save_VertexAttrib1fNV;
- vfmt->VertexAttrib1fvNV = _save_VertexAttrib1fvNV;
- vfmt->VertexAttrib2fNV = _save_VertexAttrib2fNV;
- vfmt->VertexAttrib2fvNV = _save_VertexAttrib2fvNV;
- vfmt->VertexAttrib3fNV = _save_VertexAttrib3fNV;
- vfmt->VertexAttrib3fvNV = _save_VertexAttrib3fvNV;
- vfmt->VertexAttrib4fNV = _save_VertexAttrib4fNV;
- vfmt->VertexAttrib4fvNV = _save_VertexAttrib4fvNV;
-
- /* This will all require us to fallback to saving the list as opcodes:
- */
- _MESA_INIT_DLIST_VTXFMT(vfmt, _save_); /* inside begin/end */
-
- _MESA_INIT_EVAL_VTXFMT(vfmt, _save_);
-
- /* These are all errors as we at least know we are in some sort of
- * begin/end pair:
- */
- vfmt->Begin = _save_Begin;
- vfmt->Rectf = _save_Rectf;
- vfmt->DrawArrays = _save_DrawArrays;
- vfmt->DrawElements = _save_DrawElements;
- vfmt->DrawRangeElements = _save_DrawRangeElements;
- vfmt->DrawElementsBaseVertex = _save_DrawElementsBaseVertex;
- vfmt->DrawRangeElementsBaseVertex = _save_DrawRangeElementsBaseVertex;
- /* Loops back into vfmt->DrawElements */
- vfmt->MultiDrawElementsEXT = _mesa_noop_MultiDrawElements;
- vfmt->MultiDrawElementsBaseVertex = _mesa_noop_MultiDrawElementsBaseVertex;
-}
-
-
-void vbo_save_SaveFlushVertices( GLcontext *ctx )
-{
- struct vbo_save_context *save = &vbo_context(ctx)->save;
-
- /* Noop when we are actually active:
- */
- if (ctx->Driver.CurrentSavePrimitive == PRIM_INSIDE_UNKNOWN_PRIM ||
- ctx->Driver.CurrentSavePrimitive <= GL_POLYGON)
- return;
-
- if (save->vert_count ||
- save->prim_count)
- _save_compile_vertex_list( ctx );
-
- _save_copy_to_current( ctx );
- _save_reset_vertex( ctx );
- _save_reset_counters( ctx );
- ctx->Driver.SaveNeedFlush = 0;
-}
-
-void vbo_save_NewList( GLcontext *ctx, GLuint list, GLenum mode )
-{
- struct vbo_save_context *save = &vbo_context(ctx)->save;
-
- (void) list; (void) mode;
-
- if (!save->prim_store)
- save->prim_store = alloc_prim_store( ctx );
-
- if (!save->vertex_store)
- save->vertex_store = alloc_vertex_store( ctx );
-
- save->buffer_ptr = map_vertex_store( ctx, save->vertex_store );
-
- _save_reset_vertex( ctx );
- _save_reset_counters( ctx );
- ctx->Driver.SaveNeedFlush = 0;
-}
-
-void vbo_save_EndList( GLcontext *ctx )
-{
- struct vbo_save_context *save = &vbo_context(ctx)->save;
-
- /* EndList called inside a (saved) Begin/End pair?
- */
- if (ctx->Driver.CurrentSavePrimitive != PRIM_OUTSIDE_BEGIN_END) {
-
- if (save->prim_count > 0) {
- GLint i = save->prim_count - 1;
- ctx->Driver.CurrentSavePrimitive = PRIM_OUTSIDE_BEGIN_END;
- save->prim[i].end = 0;
- save->prim[i].count = (save->vert_count -
- save->prim[i].start);
- }
-
- /* Make sure this vertex list gets replayed by the "loopback"
- * mechanism:
- */
- save->dangling_attr_ref = 1;
- vbo_save_SaveFlushVertices( ctx );
-
- /* Swap out this vertex format while outside begin/end. Any color,
- * etc. received between here and the next begin will be compiled
- * as opcodes.
- */
- _mesa_install_save_vtxfmt( ctx, &ctx->ListState.ListVtxfmt );
- }
-
- unmap_vertex_store( ctx, save->vertex_store );
-
- assert(save->vertex_size == 0);
-}
-
-void vbo_save_BeginCallList( GLcontext *ctx, struct gl_display_list *dlist )
-{
- struct vbo_save_context *save = &vbo_context(ctx)->save;
- save->replay_flags |= dlist->Flags;
-}
-
-void vbo_save_EndCallList( GLcontext *ctx )
-{
- struct vbo_save_context *save = &vbo_context(ctx)->save;
-
- if (ctx->ListState.CallDepth == 1) {
- /* This is correct: want to keep only the VBO_SAVE_FALLBACK
- * flag, if it is set:
- */
- save->replay_flags &= VBO_SAVE_FALLBACK;
- }
-}
-
-
-static void vbo_destroy_vertex_list( GLcontext *ctx, void *data )
-{
- struct vbo_save_vertex_list *node = (struct vbo_save_vertex_list *)data;
- (void) ctx;
-
- if ( --node->vertex_store->refcount == 0 )
- free_vertex_store( ctx, node->vertex_store );
-
- if ( --node->prim_store->refcount == 0 )
- FREE( node->prim_store );
-
- if (node->current_data) {
- FREE(node->current_data);
- node->current_data = NULL;
- }
-}
-
-
-static void vbo_print_vertex_list( GLcontext *ctx, void *data )
-{
- struct vbo_save_vertex_list *node = (struct vbo_save_vertex_list *)data;
- GLuint i;
- (void) ctx;
-
- printf("VBO-VERTEX-LIST, %u vertices %d primitives, %d vertsize\n",
- node->count,
- node->prim_count,
- node->vertex_size);
-
- for (i = 0 ; i < node->prim_count ; i++) {
- struct _mesa_prim *prim = &node->prim[i];
- _mesa_debug(NULL, " prim %d: %s%s %d..%d %s %s\n",
- i,
- _mesa_lookup_prim_by_nr(prim->mode),
- prim->weak ? " (weak)" : "",
- prim->start,
- prim->start + prim->count,
- (prim->begin) ? "BEGIN" : "(wrap)",
- (prim->end) ? "END" : "(wrap)");
- }
-}
-
-
-static void _save_current_init( GLcontext *ctx )
-{
- struct vbo_save_context *save = &vbo_context(ctx)->save;
- GLint i;
-
- for (i = VBO_ATTRIB_POS; i <= VBO_ATTRIB_GENERIC15; i++) {
- const GLuint j = i - VBO_ATTRIB_POS;
- ASSERT(j < VERT_ATTRIB_MAX);
- save->currentsz[i] = &ctx->ListState.ActiveAttribSize[j];
- save->current[i] = ctx->ListState.CurrentAttrib[j];
- }
-
- for (i = VBO_ATTRIB_FIRST_MATERIAL; i <= VBO_ATTRIB_LAST_MATERIAL; i++) {
- const GLuint j = i - VBO_ATTRIB_FIRST_MATERIAL;
- ASSERT(j < MAT_ATTRIB_MAX);
- save->currentsz[i] = &ctx->ListState.ActiveMaterialSize[j];
- save->current[i] = ctx->ListState.CurrentMaterial[j];
- }
-}
-
-/**
- * Initialize the display list compiler
- */
-void vbo_save_api_init( struct vbo_save_context *save )
-{
- GLcontext *ctx = save->ctx;
- GLuint i;
-
- save->opcode_vertex_list =
- _mesa_dlist_alloc_opcode( ctx,
- sizeof(struct vbo_save_vertex_list),
- vbo_save_playback_vertex_list,
- vbo_destroy_vertex_list,
- vbo_print_vertex_list );
-
- ctx->Driver.NotifySaveBegin = vbo_save_NotifyBegin;
-
- _save_vtxfmt_init( ctx );
- _save_current_init( ctx );
-
- /* These will actually get set again when binding/drawing */
- for (i = 0; i < VBO_ATTRIB_MAX; i++)
- save->inputs[i] = &save->arrays[i];
-
- /* Hook our array functions into the outside-begin-end vtxfmt in
- * ctx->ListState.
- */
- ctx->ListState.ListVtxfmt.Rectf = _save_OBE_Rectf;
- ctx->ListState.ListVtxfmt.DrawArrays = _save_OBE_DrawArrays;
- ctx->ListState.ListVtxfmt.DrawElements = _save_OBE_DrawElements;
- ctx->ListState.ListVtxfmt.DrawRangeElements = _save_OBE_DrawRangeElements;
- /* loops back into _save_OBE_DrawElements */
- ctx->ListState.ListVtxfmt.MultiDrawElementsEXT = _mesa_noop_MultiDrawElements;
- ctx->ListState.ListVtxfmt.MultiDrawElementsBaseVertex = _mesa_noop_MultiDrawElementsBaseVertex;
- _mesa_install_save_vtxfmt( ctx, &ctx->ListState.ListVtxfmt );
-}
-
-
-#endif /* FEATURE_dlist */
+/**************************************************************************
+
+Copyright 2002-2008 Tungsten Graphics Inc., Cedar Park, Texas.
+
+All Rights Reserved.
+
+Permission is hereby granted, free of charge, to any person obtaining a
+copy of this software and associated documentation files (the "Software"),
+to deal in the Software without restriction, including without limitation
+on the rights to use, copy, modify, merge, publish, distribute, sub
+license, and/or sell copies of the Software, and to permit persons to whom
+the Software is furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice (including the next
+paragraph) shall be included in all copies or substantial portions of the
+Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
+TUNGSTEN GRAPHICS AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
+DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+**************************************************************************/
+
+/*
+ * Authors:
+ * Keith Whitwell <keith@tungstengraphics.com>
+ */
+
+
+
+/* Display list compiler attempts to store lists of vertices with the
+ * same vertex layout. Additionally it attempts to minimize the need
+ * for execute-time fixup of these vertex lists, allowing them to be
+ * cached on hardware.
+ *
+ * There are still some circumstances where this can be thwarted, for
+ * example by building a list that consists of one very long primitive
+ * (eg Begin(Triangles), 1000 vertices, End), and calling that list
+ * from inside a different begin/end object (Begin(Lines), CallList,
+ * End).
+ *
+ * In that case the code will have to replay the list as individual
+ * commands through the Exec dispatch table, or fix up the copied
+ * vertices at execute-time.
+ *
+ * The other case where fixup is required is when a vertex attribute
+ * is introduced in the middle of a primitive. Eg:
+ * Begin(Lines)
+ * TexCoord1f() Vertex2f()
+ * TexCoord1f() Color3f() Vertex2f()
+ * End()
+ *
+ * If the current value of Color isn't known at compile-time, this
+ * primitive will require fixup.
+ *
+ *
+ * The list compiler currently doesn't attempt to compile lists
+ * containing EvalCoord or EvalPoint commands. On encountering one of
+ * these, compilation falls back to opcodes.
+ *
+ * This could be improved to fallback only when a mix of EvalCoord and
+ * Vertex commands are issued within a single primitive.
+ */
+
+
+#include "main/glheader.h"
+#include "main/bufferobj.h"
+#include "main/context.h"
+#include "main/dlist.h"
+#include "main/enums.h"
+#include "main/eval.h"
+#include "main/macros.h"
+#include "main/api_noop.h"
+#include "main/api_validate.h"
+#include "main/api_arrayelt.h"
+#include "main/vtxfmt.h"
+#include "main/dispatch.h"
+
+#include "vbo_context.h"
+
+
+#if FEATURE_dlist
+
+
+#ifdef ERROR
+#undef ERROR
+#endif
+
+
+/* An interesting VBO number/name to help with debugging */
+#define VBO_BUF_ID 12345
+
+
+/*
+ * NOTE: Old 'parity' issue is gone, but copying can still be
+ * wrong-footed on replay.
+ */
+static GLuint _save_copy_vertices( struct gl_context *ctx,
+ const struct vbo_save_vertex_list *node,
+ const GLfloat *src_buffer)
+{
+ struct vbo_save_context *save = &vbo_context( ctx )->save;
+ const struct _mesa_prim *prim = &node->prim[node->prim_count-1];
+ GLuint nr = prim->count;
+ GLuint sz = save->vertex_size;
+ const GLfloat *src = src_buffer + prim->start * sz;
+ GLfloat *dst = save->copied.buffer;
+ GLuint ovf, i;
+
+ if (prim->end)
+ return 0;
+
+ switch( prim->mode )
+ {
+ case GL_POINTS:
+ return 0;
+ case GL_LINES:
+ ovf = nr&1;
+ for (i = 0 ; i < ovf ; i++)
+ memcpy( dst+i*sz, src+(nr-ovf+i)*sz, sz*sizeof(GLfloat) );
+ return i;
+ case GL_TRIANGLES:
+ ovf = nr%3;
+ for (i = 0 ; i < ovf ; i++)
+ memcpy( dst+i*sz, src+(nr-ovf+i)*sz, sz*sizeof(GLfloat) );
+ return i;
+ case GL_QUADS:
+ ovf = nr&3;
+ for (i = 0 ; i < ovf ; i++)
+ memcpy( dst+i*sz, src+(nr-ovf+i)*sz, sz*sizeof(GLfloat) );
+ return i;
+ case GL_LINE_STRIP:
+ if (nr == 0)
+ return 0;
+ else {
+ memcpy( dst, src+(nr-1)*sz, sz*sizeof(GLfloat) );
+ return 1;
+ }
+ case GL_LINE_LOOP:
+ case GL_TRIANGLE_FAN:
+ case GL_POLYGON:
+ if (nr == 0)
+ return 0;
+ else if (nr == 1) {
+ memcpy( dst, src+0, sz*sizeof(GLfloat) );
+ return 1;
+ } else {
+ memcpy( dst, src+0, sz*sizeof(GLfloat) );
+ memcpy( dst+sz, src+(nr-1)*sz, sz*sizeof(GLfloat) );
+ return 2;
+ }
+ case GL_TRIANGLE_STRIP:
+ case GL_QUAD_STRIP:
+ switch (nr) {
+ case 0: ovf = 0; break;
+ case 1: ovf = 1; break;
+ default: ovf = 2 + (nr&1); break;
+ }
+ for (i = 0 ; i < ovf ; i++)
+ memcpy( dst+i*sz, src+(nr-ovf+i)*sz, sz*sizeof(GLfloat) );
+ return i;
+ default:
+ assert(0);
+ return 0;
+ }
+}
+
+
+static struct vbo_save_vertex_store *alloc_vertex_store( struct gl_context *ctx )
+{
+ struct vbo_save_vertex_store *vertex_store = CALLOC_STRUCT(vbo_save_vertex_store);
+
+ /* obj->Name needs to be non-zero, but won't ever be examined more
+ * closely than that. In particular these buffers won't be entered
+ * into the hash and can never be confused with ones visible to the
+ * user. Perhaps there could be a special number for internal
+ * buffers:
+ */
+ vertex_store->bufferobj = ctx->Driver.NewBufferObject(ctx,
+ VBO_BUF_ID,
+ GL_ARRAY_BUFFER_ARB);
+
+ ctx->Driver.BufferData( ctx,
+ GL_ARRAY_BUFFER_ARB,
+ VBO_SAVE_BUFFER_SIZE * sizeof(GLfloat),
+ NULL,
+ GL_STATIC_DRAW_ARB,
+ vertex_store->bufferobj);
+
+ vertex_store->buffer = NULL;
+ vertex_store->used = 0;
+ vertex_store->refcount = 1;
+
+ return vertex_store;
+}
+
+static void free_vertex_store( struct gl_context *ctx, struct vbo_save_vertex_store *vertex_store )
+{
+ assert(!vertex_store->buffer);
+
+ if (vertex_store->bufferobj) {
+ _mesa_reference_buffer_object(ctx, &vertex_store->bufferobj, NULL);
+ }
+
+ FREE( vertex_store );
+}
+
+static GLfloat *map_vertex_store( struct gl_context *ctx, struct vbo_save_vertex_store *vertex_store )
+{
+ assert(vertex_store->bufferobj);
+ assert(!vertex_store->buffer);
+ vertex_store->buffer = (GLfloat *)ctx->Driver.MapBuffer(ctx,
+ GL_ARRAY_BUFFER_ARB, /* not used */
+ GL_WRITE_ONLY, /* not used */
+ vertex_store->bufferobj);
+
+ assert(vertex_store->buffer);
+ return vertex_store->buffer + vertex_store->used;
+}
+
+static void unmap_vertex_store( struct gl_context *ctx, struct vbo_save_vertex_store *vertex_store )
+{
+ ctx->Driver.UnmapBuffer( ctx, GL_ARRAY_BUFFER_ARB, vertex_store->bufferobj );
+ vertex_store->buffer = NULL;
+}
+
+
+static struct vbo_save_primitive_store *alloc_prim_store( struct gl_context *ctx )
+{
+ struct vbo_save_primitive_store *store = CALLOC_STRUCT(vbo_save_primitive_store);
+ (void) ctx;
+ store->used = 0;
+ store->refcount = 1;
+ return store;
+}
+
+static void _save_reset_counters( struct gl_context *ctx )
+{
+ struct vbo_save_context *save = &vbo_context(ctx)->save;
+
+ save->prim = save->prim_store->buffer + save->prim_store->used;
+ save->buffer = (save->vertex_store->buffer +
+ save->vertex_store->used);
+
+ assert(save->buffer == save->buffer_ptr);
+
+ if (save->vertex_size)
+ save->max_vert = ((VBO_SAVE_BUFFER_SIZE - save->vertex_store->used) /
+ save->vertex_size);
+ else
+ save->max_vert = 0;
+
+ save->vert_count = 0;
+ save->prim_count = 0;
+ save->prim_max = VBO_SAVE_PRIM_SIZE - save->prim_store->used;
+ save->dangling_attr_ref = 0;
+}
+
+
+/* Insert the active immediate struct onto the display list currently
+ * being built.
+ */
+static void _save_compile_vertex_list( struct gl_context *ctx )
+{
+ struct vbo_save_context *save = &vbo_context(ctx)->save;
+ struct vbo_save_vertex_list *node;
+
+ /* Allocate space for this structure in the display list currently
+ * being compiled.
+ */
+ node = (struct vbo_save_vertex_list *)
+ _mesa_dlist_alloc(ctx, save->opcode_vertex_list, sizeof(*node));
+
+ if (!node)
+ return;
+
+ /* Duplicate our template, increment refcounts to the storage structs:
+ */
+ memcpy(node->attrsz, save->attrsz, sizeof(node->attrsz));
+ node->vertex_size = save->vertex_size;
+ node->buffer_offset = (save->buffer - save->vertex_store->buffer) * sizeof(GLfloat);
+ node->count = save->vert_count;
+ node->wrap_count = save->copied.nr;
+ node->dangling_attr_ref = save->dangling_attr_ref;
+ node->prim = save->prim;
+ node->prim_count = save->prim_count;
+ node->vertex_store = save->vertex_store;
+ node->prim_store = save->prim_store;
+
+ node->vertex_store->refcount++;
+ node->prim_store->refcount++;
+
+ if (node->prim[0].no_current_update) {
+ node->current_size = 0;
+ node->current_data = NULL;
+ } else {
+ node->current_size = node->vertex_size - node->attrsz[0];
+ node->current_data = NULL;
+
+ if (node->current_size) {
+ /* If the malloc fails, we just pull the data out of the VBO
+ * later instead.
+ */
+ node->current_data = MALLOC( node->current_size * sizeof(GLfloat) );
+ if (node->current_data) {
+ const char *buffer = (const char *)save->vertex_store->buffer;
+ unsigned attr_offset = node->attrsz[0] * sizeof(GLfloat);
+ unsigned vertex_offset = 0;
+
+ if (node->count)
+ vertex_offset = (node->count-1) * node->vertex_size * sizeof(GLfloat);
+
+ memcpy( node->current_data,
+ buffer + node->buffer_offset + vertex_offset + attr_offset,
+ node->current_size * sizeof(GLfloat) );
+ }
+ }
+ }
+
+
+
+ assert(node->attrsz[VBO_ATTRIB_POS] != 0 ||
+ node->count == 0);
+
+ if (save->dangling_attr_ref)
+ ctx->ListState.CurrentList->Flags |= DLIST_DANGLING_REFS;
+
+ save->vertex_store->used += save->vertex_size * node->count;
+ save->prim_store->used += node->prim_count;
+
+
+ /* Copy duplicated vertices
+ */
+ save->copied.nr = _save_copy_vertices( ctx, node, save->buffer );
+
+
+ /* Deal with GL_COMPILE_AND_EXECUTE:
+ */
+ if (ctx->ExecuteFlag) {
+ struct _glapi_table *dispatch = GET_DISPATCH();
+
+ _glapi_set_dispatch(ctx->Exec);
+
+ vbo_loopback_vertex_list( ctx,
+ (const GLfloat *)((const char *)save->vertex_store->buffer +
+ node->buffer_offset),
+ node->attrsz,
+ node->prim,
+ node->prim_count,
+ node->wrap_count,
+ node->vertex_size);
+
+ _glapi_set_dispatch(dispatch);
+ }
+
+
+ /* Decide whether the storage structs are full, or can be used for
+ * the next vertex lists as well.
+ */
+ if (save->vertex_store->used >
+ VBO_SAVE_BUFFER_SIZE - 16 * (save->vertex_size + 4)) {
+
+ /* Unmap old store:
+ */
+ unmap_vertex_store( ctx, save->vertex_store );
+
+ /* Release old reference:
+ */
+ save->vertex_store->refcount--;
+ assert(save->vertex_store->refcount != 0);
+ save->vertex_store = NULL;
+
+ /* Allocate and map new store:
+ */
+ save->vertex_store = alloc_vertex_store( ctx );
+ save->buffer_ptr = map_vertex_store( ctx, save->vertex_store );
+ }
+
+ if (save->prim_store->used > VBO_SAVE_PRIM_SIZE - 6) {
+ save->prim_store->refcount--;
+ assert(save->prim_store->refcount != 0);
+ save->prim_store = alloc_prim_store( ctx );
+ }
+
+ /* Reset our structures for the next run of vertices:
+ */
+ _save_reset_counters( ctx );
+}
+
+
+/* TODO -- If no new vertices have been stored, don't bother saving
+ * it.
+ */
+static void _save_wrap_buffers( struct gl_context *ctx )
+{
+ struct vbo_save_context *save = &vbo_context(ctx)->save;
+ GLint i = save->prim_count - 1;
+ GLenum mode;
+ GLboolean weak;
+ GLboolean no_current_update;
+
+ assert(i < (GLint) save->prim_max);
+ assert(i >= 0);
+
+ /* Close off in-progress primitive.
+ */
+ save->prim[i].count = (save->vert_count -
+ save->prim[i].start);
+ mode = save->prim[i].mode;
+ weak = save->prim[i].weak;
+ no_current_update = save->prim[i].no_current_update;
+
+ /* store the copied vertices, and allocate a new list.
+ */
+ _save_compile_vertex_list( ctx );
+
+ /* Restart interrupted primitive
+ */
+ save->prim[0].mode = mode;
+ save->prim[0].weak = weak;
+ save->prim[0].no_current_update = no_current_update;
+ save->prim[0].begin = 0;
+ save->prim[0].end = 0;
+ save->prim[0].pad = 0;
+ save->prim[0].start = 0;
+ save->prim[0].count = 0;
+ save->prim[0].num_instances = 1;
+ save->prim_count = 1;
+}
+
+
+
+/* Called only when buffers are wrapped as the result of filling the
+ * vertex_store struct.
+ */
+static void _save_wrap_filled_vertex( struct gl_context *ctx )
+{
+ struct vbo_save_context *save = &vbo_context(ctx)->save;
+ GLfloat *data = save->copied.buffer;
+ GLuint i;
+
+ /* Emit a glEnd to close off the last vertex list.
+ */
+ _save_wrap_buffers( ctx );
+
+ /* Copy stored stored vertices to start of new list.
+ */
+ assert(save->max_vert - save->vert_count > save->copied.nr);
+
+ for (i = 0 ; i < save->copied.nr ; i++) {
+ memcpy( save->buffer_ptr, data, save->vertex_size * sizeof(GLfloat));
+ data += save->vertex_size;
+ save->buffer_ptr += save->vertex_size;
+ save->vert_count++;
+ }
+}
+
+
+static void _save_copy_to_current( struct gl_context *ctx )
+{
+ struct vbo_save_context *save = &vbo_context(ctx)->save;
+ GLuint i;
+
+ for (i = VBO_ATTRIB_POS+1 ; i < VBO_ATTRIB_MAX ; i++) {
+ if (save->attrsz[i]) {
+ save->currentsz[i][0] = save->attrsz[i];
+ COPY_CLEAN_4V(save->current[i],
+ save->attrsz[i],
+ save->attrptr[i]);
+ }
+ }
+}
+
+
+static void _save_copy_from_current( struct gl_context *ctx )
+{
+ struct vbo_save_context *save = &vbo_context(ctx)->save;
+ GLint i;
+
+ for (i = VBO_ATTRIB_POS+1 ; i < VBO_ATTRIB_MAX ; i++) {
+ switch (save->attrsz[i]) {
+ case 4: save->attrptr[i][3] = save->current[i][3];
+ case 3: save->attrptr[i][2] = save->current[i][2];
+ case 2: save->attrptr[i][1] = save->current[i][1];
+ case 1: save->attrptr[i][0] = save->current[i][0];
+ case 0: break;
+ }
+ }
+}
+
+
+
+
+/* Flush existing data, set new attrib size, replay copied vertices.
+ */
+static void _save_upgrade_vertex( struct gl_context *ctx,
+ GLuint attr,
+ GLuint newsz )
+{
+ struct vbo_save_context *save = &vbo_context(ctx)->save;
+ GLuint oldsz;
+ GLuint i;
+ GLfloat *tmp;
+
+ /* Store the current run of vertices, and emit a GL_END. Emit a
+ * BEGIN in the new buffer.
+ */
+ if (save->vert_count)
+ _save_wrap_buffers( ctx );
+ else
+ assert( save->copied.nr == 0 );
+
+ /* Do a COPY_TO_CURRENT to ensure back-copying works for the case
+ * when the attribute already exists in the vertex and is having
+ * its size increased.
+ */
+ _save_copy_to_current( ctx );
+
+ /* Fix up sizes:
+ */
+ oldsz = save->attrsz[attr];
+ save->attrsz[attr] = newsz;
+
+ save->vertex_size += newsz - oldsz;
+ save->max_vert = ((VBO_SAVE_BUFFER_SIZE - save->vertex_store->used) /
+ save->vertex_size);
+ save->vert_count = 0;
+
+ /* Recalculate all the attrptr[] values:
+ */
+ for (i = 0, tmp = save->vertex ; i < VBO_ATTRIB_MAX ; i++) {
+ if (save->attrsz[i]) {
+ save->attrptr[i] = tmp;
+ tmp += save->attrsz[i];
+ }
+ else
+ save->attrptr[i] = NULL; /* will not be dereferenced. */
+ }
+
+ /* Copy from current to repopulate the vertex with correct values.
+ */
+ _save_copy_from_current( ctx );
+
+ /* Replay stored vertices to translate them to new format here.
+ *
+ * If there are copied vertices and the new (upgraded) attribute
+ * has not been defined before, this list is somewhat degenerate,
+ * and will need fixup at runtime.
+ */
+ if (save->copied.nr)
+ {
+ GLfloat *data = save->copied.buffer;
+ GLfloat *dest = save->buffer;
+ GLuint j;
+
+ /* Need to note this and fix up at runtime (or loopback):
+ */
+ if (attr != VBO_ATTRIB_POS && save->currentsz[attr][0] == 0) {
+ assert(oldsz == 0);
+ save->dangling_attr_ref = GL_TRUE;
+ }
+
+ for (i = 0 ; i < save->copied.nr ; i++) {
+ for (j = 0 ; j < VBO_ATTRIB_MAX ; j++) {
+ if (save->attrsz[j]) {
+ if (j == attr) {
+ if (oldsz) {
+ COPY_CLEAN_4V( dest, oldsz, data );
+ data += oldsz;
+ dest += newsz;
+ }
+ else {
+ COPY_SZ_4V( dest, newsz, save->current[attr] );
+ dest += newsz;
+ }
+ }
+ else {
+ GLint sz = save->attrsz[j];
+ COPY_SZ_4V( dest, sz, data );
+ data += sz;
+ dest += sz;
+ }
+ }
+ }
+ }
+
+ save->buffer_ptr = dest;
+ save->vert_count += save->copied.nr;
+ }
+}
+
+static void save_fixup_vertex( struct gl_context *ctx, GLuint attr, GLuint sz )
+{
+ struct vbo_save_context *save = &vbo_context(ctx)->save;
+
+ if (sz > save->attrsz[attr]) {
+ /* New size is larger. Need to flush existing vertices and get
+ * an enlarged vertex format.
+ */
+ _save_upgrade_vertex( ctx, attr, sz );
+ }
+ else if (sz < save->active_sz[attr]) {
+ static GLfloat id[4] = { 0, 0, 0, 1 };
+ GLuint i;
+
+ /* New size is equal or smaller - just need to fill in some
+ * zeros.
+ */
+ for (i = sz ; i <= save->attrsz[attr] ; i++)
+ save->attrptr[attr][i-1] = id[i-1];
+ }
+
+ save->active_sz[attr] = sz;
+}
+
+static void _save_reset_vertex( struct gl_context *ctx )
+{
+ struct vbo_save_context *save = &vbo_context(ctx)->save;
+ GLuint i;
+
+ for (i = 0 ; i < VBO_ATTRIB_MAX ; i++) {
+ save->attrsz[i] = 0;
+ save->active_sz[i] = 0;
+ }
+
+ save->vertex_size = 0;
+}
+
+
+
+#define ERROR() _mesa_compile_error( ctx, GL_INVALID_ENUM, __FUNCTION__ );
+
+
+/* Only one size for each attribute may be active at once. Eg. if
+ * Color3f is installed/active, then Color4f may not be, even if the
+ * vertex actually contains 4 color coordinates. This is because the
+ * 3f version won't otherwise set color[3] to 1.0 -- this is the job
+ * of the chooser function when switching between Color4f and Color3f.
+ */
+#define ATTR( A, N, V0, V1, V2, V3 ) \
+do { \
+ struct vbo_save_context *save = &vbo_context(ctx)->save; \
+ \
+ if (save->active_sz[A] != N) \
+ save_fixup_vertex(ctx, A, N); \
+ \
+ { \
+ GLfloat *dest = save->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; \
+ } \
+ \
+ if ((A) == 0) { \
+ GLuint i; \
+ \
+ for (i = 0; i < save->vertex_size; i++) \
+ save->buffer_ptr[i] = save->vertex[i]; \
+ \
+ save->buffer_ptr += save->vertex_size; \
+ \
+ if (++save->vert_count >= save->max_vert) \
+ _save_wrap_filled_vertex( ctx ); \
+ } \
+} while (0)
+
+#define TAG(x) _save_##x
+
+#include "vbo_attrib_tmp.h"
+
+
+
+
+/* Cope with EvalCoord/CallList called within a begin/end object:
+ * -- Flush current buffer
+ * -- Fallback to opcodes for the rest of the begin/end object.
+ */
+static void DO_FALLBACK( struct gl_context *ctx )
+{
+ struct vbo_save_context *save = &vbo_context(ctx)->save;
+
+ if (save->vert_count || save->prim_count) {
+ GLint i = save->prim_count - 1;
+
+ /* Close off in-progress primitive.
+ */
+ save->prim[i].count = (save->vert_count -
+ save->prim[i].start);
+
+ /* Need to replay this display list with loopback,
+ * unfortunately, otherwise this primitive won't be handled
+ * properly:
+ */
+ save->dangling_attr_ref = 1;
+
+ _save_compile_vertex_list( ctx );
+ }
+
+ _save_copy_to_current( ctx );
+ _save_reset_vertex( ctx );
+ _save_reset_counters( ctx );
+ _mesa_install_save_vtxfmt( ctx, &ctx->ListState.ListVtxfmt );
+ ctx->Driver.SaveNeedFlush = 0;
+}
+
+static void GLAPIENTRY _save_EvalCoord1f( GLfloat u )
+{
+ GET_CURRENT_CONTEXT(ctx);
+ DO_FALLBACK(ctx);
+ CALL_EvalCoord1f(ctx->Save, (u));
+}
+
+static void GLAPIENTRY _save_EvalCoord1fv( const GLfloat *v )
+{
+ GET_CURRENT_CONTEXT(ctx);
+ DO_FALLBACK(ctx);
+ CALL_EvalCoord1fv(ctx->Save, (v));
+}
+
+static void GLAPIENTRY _save_EvalCoord2f( GLfloat u, GLfloat v )
+{
+ GET_CURRENT_CONTEXT(ctx);
+ DO_FALLBACK(ctx);
+ CALL_EvalCoord2f(ctx->Save, (u, v));
+}
+
+static void GLAPIENTRY _save_EvalCoord2fv( const GLfloat *v )
+{
+ GET_CURRENT_CONTEXT(ctx);
+ DO_FALLBACK(ctx);
+ CALL_EvalCoord2fv(ctx->Save, (v));
+}
+
+static void GLAPIENTRY _save_EvalPoint1( GLint i )
+{
+ GET_CURRENT_CONTEXT(ctx);
+ DO_FALLBACK(ctx);
+ CALL_EvalPoint1(ctx->Save, (i));
+}
+
+static void GLAPIENTRY _save_EvalPoint2( GLint i, GLint j )
+{
+ GET_CURRENT_CONTEXT(ctx);
+ DO_FALLBACK(ctx);
+ CALL_EvalPoint2(ctx->Save, (i, j));
+}
+
+static void GLAPIENTRY _save_CallList( GLuint l )
+{
+ GET_CURRENT_CONTEXT(ctx);
+ DO_FALLBACK(ctx);
+ CALL_CallList(ctx->Save, (l));
+}
+
+static void GLAPIENTRY _save_CallLists( GLsizei n, GLenum type, const GLvoid *v )
+{
+ GET_CURRENT_CONTEXT(ctx);
+ DO_FALLBACK(ctx);
+ CALL_CallLists(ctx->Save, (n, type, v));
+}
+
+
+
+
+/* This begin is hooked into ... Updating of
+ * ctx->Driver.CurrentSavePrimitive is already taken care of.
+ */
+GLboolean vbo_save_NotifyBegin( struct gl_context *ctx, GLenum mode )
+{
+ struct vbo_save_context *save = &vbo_context(ctx)->save;
+
+ GLuint i = save->prim_count++;
+
+ assert(i < save->prim_max);
+ save->prim[i].mode = mode & VBO_SAVE_PRIM_MODE_MASK;
+ save->prim[i].begin = 1;
+ save->prim[i].end = 0;
+ save->prim[i].weak = (mode & VBO_SAVE_PRIM_WEAK) ? 1 : 0;
+ save->prim[i].no_current_update = (mode & VBO_SAVE_PRIM_NO_CURRENT_UPDATE) ? 1 : 0;
+ save->prim[i].pad = 0;
+ save->prim[i].start = save->vert_count;
+ save->prim[i].count = 0;
+ save->prim[i].num_instances = 1;
+
+ _mesa_install_save_vtxfmt( ctx, &save->vtxfmt );
+ ctx->Driver.SaveNeedFlush = 1;
+ return GL_TRUE;
+}
+
+
+
+static void GLAPIENTRY _save_End( void )
+{
+ GET_CURRENT_CONTEXT( ctx );
+ struct vbo_save_context *save = &vbo_context(ctx)->save;
+ GLint i = save->prim_count - 1;
+
+ ctx->Driver.CurrentSavePrimitive = PRIM_OUTSIDE_BEGIN_END;
+ save->prim[i].end = 1;
+ save->prim[i].count = (save->vert_count -
+ save->prim[i].start);
+
+ if (i == (GLint) save->prim_max - 1) {
+ _save_compile_vertex_list( ctx );
+ assert(save->copied.nr == 0);
+ }
+
+ /* Swap out this vertex format while outside begin/end. Any color,
+ * etc. received between here and the next begin will be compiled
+ * as opcodes.
+ */
+ _mesa_install_save_vtxfmt( ctx, &ctx->ListState.ListVtxfmt );
+}
+
+
+/* These are all errors as this vtxfmt is only installed inside
+ * begin/end pairs.
+ */
+static void GLAPIENTRY _save_DrawElements(GLenum mode, GLsizei count, GLenum type,
+ const GLvoid *indices)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ (void) mode; (void) count; (void) type; (void) indices;
+ _mesa_compile_error( ctx, GL_INVALID_OPERATION, "glDrawElements" );
+}
+
+
+static void GLAPIENTRY _save_DrawRangeElements(GLenum mode,
+ GLuint start, GLuint end,
+ GLsizei count, GLenum type,
+ const GLvoid *indices)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ (void) mode; (void) start; (void) end; (void) count; (void) type; (void) indices;
+ _mesa_compile_error( ctx, GL_INVALID_OPERATION, "glDrawRangeElements" );
+}
+
+static void GLAPIENTRY _save_DrawElementsBaseVertex(GLenum mode,
+ GLsizei count,
+ GLenum type,
+ const GLvoid *indices,
+ GLint basevertex)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ (void) mode; (void) count; (void) type; (void) indices; (void)basevertex;
+
+ _mesa_compile_error( ctx, GL_INVALID_OPERATION, "glDrawElements" );
+}
+
+static void GLAPIENTRY _save_DrawRangeElementsBaseVertex(GLenum mode,
+ GLuint start,
+ GLuint end,
+ GLsizei count,
+ GLenum type,
+ const GLvoid *indices,
+ GLint basevertex)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ (void) mode; (void) start; (void) end; (void) count; (void) type;
+ (void) indices; (void)basevertex;
+
+ _mesa_compile_error( ctx, GL_INVALID_OPERATION, "glDrawRangeElements" );
+}
+
+static void GLAPIENTRY _save_DrawArrays(GLenum mode, GLint start, GLsizei count)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ (void) mode; (void) start; (void) count;
+ _mesa_compile_error( ctx, GL_INVALID_OPERATION, "glDrawArrays" );
+}
+
+static void GLAPIENTRY _save_Rectf( GLfloat x1, GLfloat y1, GLfloat x2, GLfloat y2 )
+{
+ GET_CURRENT_CONTEXT(ctx);
+ (void) x1; (void) y1; (void) x2; (void) y2;
+ _mesa_compile_error( ctx, GL_INVALID_OPERATION, "glRectf" );
+}
+
+static void GLAPIENTRY _save_EvalMesh1( GLenum mode, GLint i1, GLint i2 )
+{
+ GET_CURRENT_CONTEXT(ctx);
+ (void) mode; (void) i1; (void) i2;
+ _mesa_compile_error( ctx, GL_INVALID_OPERATION, "glEvalMesh1" );
+}
+
+static void GLAPIENTRY _save_EvalMesh2( GLenum mode, GLint i1, GLint i2,
+ GLint j1, GLint j2 )
+{
+ GET_CURRENT_CONTEXT(ctx);
+ (void) mode; (void) i1; (void) i2; (void) j1; (void) j2;
+ _mesa_compile_error( ctx, GL_INVALID_OPERATION, "glEvalMesh2" );
+}
+
+static void GLAPIENTRY _save_Begin( GLenum mode )
+{
+ GET_CURRENT_CONTEXT( ctx );
+ (void) mode;
+ _mesa_compile_error( ctx, GL_INVALID_OPERATION, "Recursive glBegin" );
+}
+
+
+static void GLAPIENTRY _save_PrimitiveRestartNV( void )
+{
+ GLenum curPrim;
+ GET_CURRENT_CONTEXT( ctx );
+
+ curPrim = ctx->Driver.CurrentSavePrimitive;
+
+ _save_End();
+ _save_Begin(curPrim);
+}
+
+
+/* Unlike the functions above, these are to be hooked into the vtxfmt
+ * maintained in ctx->ListState, active when the list is known or
+ * suspected to be outside any begin/end primitive.
+ */
+static void GLAPIENTRY _save_OBE_Rectf( GLfloat x1, GLfloat y1, GLfloat x2, GLfloat y2 )
+{
+ GET_CURRENT_CONTEXT(ctx);
+ vbo_save_NotifyBegin( ctx, GL_QUADS | VBO_SAVE_PRIM_WEAK );
+ CALL_Vertex2f(GET_DISPATCH(), ( x1, y1 ));
+ CALL_Vertex2f(GET_DISPATCH(), ( x2, y1 ));
+ CALL_Vertex2f(GET_DISPATCH(), ( x2, y2 ));
+ CALL_Vertex2f(GET_DISPATCH(), ( x1, y2 ));
+ CALL_End(GET_DISPATCH(), ());
+}
+
+
+static void GLAPIENTRY _save_OBE_DrawArrays(GLenum mode, GLint start, GLsizei count)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ GLint i;
+
+ if (!_mesa_validate_DrawArrays( ctx, mode, start, count ))
+ return;
+
+ _ae_map_vbos( ctx );
+
+ vbo_save_NotifyBegin( ctx, mode | VBO_SAVE_PRIM_WEAK | VBO_SAVE_PRIM_NO_CURRENT_UPDATE);
+
+ 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
+ * then emitting an indexed prim at runtime.
+ */
+static void GLAPIENTRY _save_OBE_DrawElements(GLenum mode, GLsizei count, GLenum type,
+ const GLvoid *indices)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ GLint i;
+
+ if (!_mesa_validate_DrawElements( ctx, mode, count, type, indices, 0 ))
+ return;
+
+ _ae_map_vbos( ctx );
+
+ if (_mesa_is_bufferobj(ctx->Array.ElementArrayBufferObj))
+ indices = ADD_POINTERS(ctx->Array.ElementArrayBufferObj->Pointer, indices);
+
+ vbo_save_NotifyBegin( ctx, mode | VBO_SAVE_PRIM_WEAK | VBO_SAVE_PRIM_NO_CURRENT_UPDATE );
+
+ switch (type) {
+ case GL_UNSIGNED_BYTE:
+ for (i = 0 ; i < count ; i++)
+ CALL_ArrayElement(GET_DISPATCH(), ( ((GLubyte *)indices)[i] ));
+ break;
+ case GL_UNSIGNED_SHORT:
+ for (i = 0 ; i < count ; i++)
+ CALL_ArrayElement(GET_DISPATCH(), ( ((GLushort *)indices)[i] ));
+ break;
+ case GL_UNSIGNED_INT:
+ for (i = 0 ; i < count ; i++)
+ CALL_ArrayElement(GET_DISPATCH(), ( ((GLuint *)indices)[i] ));
+ break;
+ default:
+ _mesa_error( ctx, GL_INVALID_ENUM, "glDrawElements(type)" );
+ break;
+ }
+
+ CALL_End(GET_DISPATCH(), ());
+
+ _ae_unmap_vbos( ctx );
+}
+
+static void GLAPIENTRY _save_OBE_DrawRangeElements(GLenum mode,
+ GLuint start, GLuint end,
+ GLsizei count, GLenum type,
+ const GLvoid *indices)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ if (_mesa_validate_DrawRangeElements( ctx, mode,
+ start, end,
+ count, type, indices, 0 ))
+ _save_OBE_DrawElements( mode, count, type, indices );
+}
+
+
+
+
+
+static void _save_vtxfmt_init( struct gl_context *ctx )
+{
+ struct vbo_save_context *save = &vbo_context(ctx)->save;
+ GLvertexformat *vfmt = &save->vtxfmt;
+
+ _MESA_INIT_ARRAYELT_VTXFMT(vfmt, _ae_);
+
+ vfmt->Begin = _save_Begin;
+ vfmt->Color3f = _save_Color3f;
+ vfmt->Color3fv = _save_Color3fv;
+ vfmt->Color4f = _save_Color4f;
+ vfmt->Color4fv = _save_Color4fv;
+ vfmt->EdgeFlag = _save_EdgeFlag;
+ vfmt->End = _save_End;
+ vfmt->PrimitiveRestartNV = _save_PrimitiveRestartNV;
+ vfmt->FogCoordfEXT = _save_FogCoordfEXT;
+ vfmt->FogCoordfvEXT = _save_FogCoordfvEXT;
+ vfmt->Indexf = _save_Indexf;
+ vfmt->Indexfv = _save_Indexfv;
+ vfmt->Materialfv = _save_Materialfv;
+ vfmt->MultiTexCoord1fARB = _save_MultiTexCoord1f;
+ vfmt->MultiTexCoord1fvARB = _save_MultiTexCoord1fv;
+ vfmt->MultiTexCoord2fARB = _save_MultiTexCoord2f;
+ vfmt->MultiTexCoord2fvARB = _save_MultiTexCoord2fv;
+ vfmt->MultiTexCoord3fARB = _save_MultiTexCoord3f;
+ vfmt->MultiTexCoord3fvARB = _save_MultiTexCoord3fv;
+ vfmt->MultiTexCoord4fARB = _save_MultiTexCoord4f;
+ vfmt->MultiTexCoord4fvARB = _save_MultiTexCoord4fv;
+ vfmt->Normal3f = _save_Normal3f;
+ vfmt->Normal3fv = _save_Normal3fv;
+ vfmt->SecondaryColor3fEXT = _save_SecondaryColor3fEXT;
+ vfmt->SecondaryColor3fvEXT = _save_SecondaryColor3fvEXT;
+ vfmt->TexCoord1f = _save_TexCoord1f;
+ vfmt->TexCoord1fv = _save_TexCoord1fv;
+ vfmt->TexCoord2f = _save_TexCoord2f;
+ vfmt->TexCoord2fv = _save_TexCoord2fv;
+ vfmt->TexCoord3f = _save_TexCoord3f;
+ vfmt->TexCoord3fv = _save_TexCoord3fv;
+ vfmt->TexCoord4f = _save_TexCoord4f;
+ vfmt->TexCoord4fv = _save_TexCoord4fv;
+ vfmt->Vertex2f = _save_Vertex2f;
+ vfmt->Vertex2fv = _save_Vertex2fv;
+ vfmt->Vertex3f = _save_Vertex3f;
+ vfmt->Vertex3fv = _save_Vertex3fv;
+ vfmt->Vertex4f = _save_Vertex4f;
+ vfmt->Vertex4fv = _save_Vertex4fv;
+ vfmt->VertexAttrib1fARB = _save_VertexAttrib1fARB;
+ vfmt->VertexAttrib1fvARB = _save_VertexAttrib1fvARB;
+ vfmt->VertexAttrib2fARB = _save_VertexAttrib2fARB;
+ vfmt->VertexAttrib2fvARB = _save_VertexAttrib2fvARB;
+ vfmt->VertexAttrib3fARB = _save_VertexAttrib3fARB;
+ vfmt->VertexAttrib3fvARB = _save_VertexAttrib3fvARB;
+ vfmt->VertexAttrib4fARB = _save_VertexAttrib4fARB;
+ vfmt->VertexAttrib4fvARB = _save_VertexAttrib4fvARB;
+
+ vfmt->VertexAttrib1fNV = _save_VertexAttrib1fNV;
+ vfmt->VertexAttrib1fvNV = _save_VertexAttrib1fvNV;
+ vfmt->VertexAttrib2fNV = _save_VertexAttrib2fNV;
+ vfmt->VertexAttrib2fvNV = _save_VertexAttrib2fvNV;
+ vfmt->VertexAttrib3fNV = _save_VertexAttrib3fNV;
+ vfmt->VertexAttrib3fvNV = _save_VertexAttrib3fvNV;
+ vfmt->VertexAttrib4fNV = _save_VertexAttrib4fNV;
+ vfmt->VertexAttrib4fvNV = _save_VertexAttrib4fvNV;
+
+ /* integer-valued */
+ vfmt->VertexAttribI1i = _save_VertexAttribI1i;
+ vfmt->VertexAttribI2i = _save_VertexAttribI2i;
+ vfmt->VertexAttribI3i = _save_VertexAttribI3i;
+ vfmt->VertexAttribI4i = _save_VertexAttribI4i;
+ vfmt->VertexAttribI2iv = _save_VertexAttribI2iv;
+ vfmt->VertexAttribI3iv = _save_VertexAttribI3iv;
+ vfmt->VertexAttribI4iv = _save_VertexAttribI4iv;
+
+ /* unsigned integer-valued */
+ vfmt->VertexAttribI1ui = _save_VertexAttribI1ui;
+ vfmt->VertexAttribI2ui = _save_VertexAttribI2ui;
+ vfmt->VertexAttribI3ui = _save_VertexAttribI3ui;
+ vfmt->VertexAttribI4ui = _save_VertexAttribI4ui;
+ vfmt->VertexAttribI2uiv = _save_VertexAttribI2uiv;
+ vfmt->VertexAttribI3uiv = _save_VertexAttribI3uiv;
+ vfmt->VertexAttribI4uiv = _save_VertexAttribI4uiv;
+
+ /* This will all require us to fallback to saving the list as opcodes:
+ */
+ _MESA_INIT_DLIST_VTXFMT(vfmt, _save_); /* inside begin/end */
+
+ _MESA_INIT_EVAL_VTXFMT(vfmt, _save_);
+
+ /* These are all errors as we at least know we are in some sort of
+ * begin/end pair:
+ */
+ vfmt->Begin = _save_Begin;
+ vfmt->Rectf = _save_Rectf;
+ vfmt->DrawArrays = _save_DrawArrays;
+ vfmt->DrawElements = _save_DrawElements;
+ vfmt->DrawRangeElements = _save_DrawRangeElements;
+ vfmt->DrawElementsBaseVertex = _save_DrawElementsBaseVertex;
+ vfmt->DrawRangeElementsBaseVertex = _save_DrawRangeElementsBaseVertex;
+ /* Loops back into vfmt->DrawElements */
+ vfmt->MultiDrawElementsEXT = _mesa_noop_MultiDrawElements;
+ vfmt->MultiDrawElementsBaseVertex = _mesa_noop_MultiDrawElementsBaseVertex;
+}
+
+
+void vbo_save_SaveFlushVertices( struct gl_context *ctx )
+{
+ struct vbo_save_context *save = &vbo_context(ctx)->save;
+
+ /* Noop when we are actually active:
+ */
+ if (ctx->Driver.CurrentSavePrimitive == PRIM_INSIDE_UNKNOWN_PRIM ||
+ ctx->Driver.CurrentSavePrimitive <= GL_POLYGON)
+ return;
+
+ if (save->vert_count ||
+ save->prim_count)
+ _save_compile_vertex_list( ctx );
+
+ _save_copy_to_current( ctx );
+ _save_reset_vertex( ctx );
+ _save_reset_counters( ctx );
+ ctx->Driver.SaveNeedFlush = 0;
+}
+
+void vbo_save_NewList( struct gl_context *ctx, GLuint list, GLenum mode )
+{
+ struct vbo_save_context *save = &vbo_context(ctx)->save;
+
+ (void) list; (void) mode;
+
+ if (!save->prim_store)
+ save->prim_store = alloc_prim_store( ctx );
+
+ if (!save->vertex_store)
+ save->vertex_store = alloc_vertex_store( ctx );
+
+ save->buffer_ptr = map_vertex_store( ctx, save->vertex_store );
+
+ _save_reset_vertex( ctx );
+ _save_reset_counters( ctx );
+ ctx->Driver.SaveNeedFlush = 0;
+}
+
+void vbo_save_EndList( struct gl_context *ctx )
+{
+ struct vbo_save_context *save = &vbo_context(ctx)->save;
+
+ /* EndList called inside a (saved) Begin/End pair?
+ */
+ if (ctx->Driver.CurrentSavePrimitive != PRIM_OUTSIDE_BEGIN_END) {
+
+ if (save->prim_count > 0) {
+ GLint i = save->prim_count - 1;
+ ctx->Driver.CurrentSavePrimitive = PRIM_OUTSIDE_BEGIN_END;
+ save->prim[i].end = 0;
+ save->prim[i].count = (save->vert_count -
+ save->prim[i].start);
+ }
+
+ /* Make sure this vertex list gets replayed by the "loopback"
+ * mechanism:
+ */
+ save->dangling_attr_ref = 1;
+ vbo_save_SaveFlushVertices( ctx );
+
+ /* Swap out this vertex format while outside begin/end. Any color,
+ * etc. received between here and the next begin will be compiled
+ * as opcodes.
+ */
+ _mesa_install_save_vtxfmt( ctx, &ctx->ListState.ListVtxfmt );
+ }
+
+ unmap_vertex_store( ctx, save->vertex_store );
+
+ assert(save->vertex_size == 0);
+}
+
+void vbo_save_BeginCallList( struct gl_context *ctx, struct gl_display_list *dlist )
+{
+ struct vbo_save_context *save = &vbo_context(ctx)->save;
+ save->replay_flags |= dlist->Flags;
+}
+
+void vbo_save_EndCallList( struct gl_context *ctx )
+{
+ struct vbo_save_context *save = &vbo_context(ctx)->save;
+
+ if (ctx->ListState.CallDepth == 1) {
+ /* This is correct: want to keep only the VBO_SAVE_FALLBACK
+ * flag, if it is set:
+ */
+ save->replay_flags &= VBO_SAVE_FALLBACK;
+ }
+}
+
+
+static void vbo_destroy_vertex_list( struct gl_context *ctx, void *data )
+{
+ struct vbo_save_vertex_list *node = (struct vbo_save_vertex_list *)data;
+ (void) ctx;
+
+ if ( --node->vertex_store->refcount == 0 )
+ free_vertex_store( ctx, node->vertex_store );
+
+ if ( --node->prim_store->refcount == 0 )
+ FREE( node->prim_store );
+
+ if (node->current_data) {
+ FREE(node->current_data);
+ node->current_data = NULL;
+ }
+}
+
+
+static void vbo_print_vertex_list( struct gl_context *ctx, void *data )
+{
+ struct vbo_save_vertex_list *node = (struct vbo_save_vertex_list *)data;
+ GLuint i;
+ (void) ctx;
+
+ printf("VBO-VERTEX-LIST, %u vertices %d primitives, %d vertsize\n",
+ node->count,
+ node->prim_count,
+ node->vertex_size);
+
+ for (i = 0 ; i < node->prim_count ; i++) {
+ struct _mesa_prim *prim = &node->prim[i];
+ _mesa_debug(NULL, " prim %d: %s%s %d..%d %s %s\n",
+ i,
+ _mesa_lookup_prim_by_nr(prim->mode),
+ prim->weak ? " (weak)" : "",
+ prim->start,
+ prim->start + prim->count,
+ (prim->begin) ? "BEGIN" : "(wrap)",
+ (prim->end) ? "END" : "(wrap)");
+ }
+}
+
+
+static void _save_current_init( struct gl_context *ctx )
+{
+ struct vbo_save_context *save = &vbo_context(ctx)->save;
+ GLint i;
+
+ for (i = VBO_ATTRIB_POS; i <= VBO_ATTRIB_GENERIC15; i++) {
+ const GLuint j = i - VBO_ATTRIB_POS;
+ ASSERT(j < VERT_ATTRIB_MAX);
+ save->currentsz[i] = &ctx->ListState.ActiveAttribSize[j];
+ save->current[i] = ctx->ListState.CurrentAttrib[j];
+ }
+
+ for (i = VBO_ATTRIB_FIRST_MATERIAL; i <= VBO_ATTRIB_LAST_MATERIAL; i++) {
+ const GLuint j = i - VBO_ATTRIB_FIRST_MATERIAL;
+ ASSERT(j < MAT_ATTRIB_MAX);
+ save->currentsz[i] = &ctx->ListState.ActiveMaterialSize[j];
+ save->current[i] = ctx->ListState.CurrentMaterial[j];
+ }
+}
+
+/**
+ * Initialize the display list compiler
+ */
+void vbo_save_api_init( struct vbo_save_context *save )
+{
+ struct gl_context *ctx = save->ctx;
+ GLuint i;
+
+ save->opcode_vertex_list =
+ _mesa_dlist_alloc_opcode( ctx,
+ sizeof(struct vbo_save_vertex_list),
+ vbo_save_playback_vertex_list,
+ vbo_destroy_vertex_list,
+ vbo_print_vertex_list );
+
+ ctx->Driver.NotifySaveBegin = vbo_save_NotifyBegin;
+
+ _save_vtxfmt_init( ctx );
+ _save_current_init( ctx );
+
+ /* These will actually get set again when binding/drawing */
+ for (i = 0; i < VBO_ATTRIB_MAX; i++)
+ save->inputs[i] = &save->arrays[i];
+
+ /* Hook our array functions into the outside-begin-end vtxfmt in
+ * ctx->ListState.
+ */
+ ctx->ListState.ListVtxfmt.Rectf = _save_OBE_Rectf;
+ ctx->ListState.ListVtxfmt.DrawArrays = _save_OBE_DrawArrays;
+ ctx->ListState.ListVtxfmt.DrawElements = _save_OBE_DrawElements;
+ ctx->ListState.ListVtxfmt.DrawRangeElements = _save_OBE_DrawRangeElements;
+ /* loops back into _save_OBE_DrawElements */
+ ctx->ListState.ListVtxfmt.MultiDrawElementsEXT = _mesa_noop_MultiDrawElements;
+ ctx->ListState.ListVtxfmt.MultiDrawElementsBaseVertex = _mesa_noop_MultiDrawElementsBaseVertex;
+ _mesa_install_save_vtxfmt( ctx, &ctx->ListState.ListVtxfmt );
+}
+
+
+#endif /* FEATURE_dlist */
diff --git a/mesalib/src/mesa/vbo/vbo_save_draw.c b/mesalib/src/mesa/vbo/vbo_save_draw.c
index 297fd8705..5d189ba4d 100644
--- a/mesalib/src/mesa/vbo/vbo_save_draw.c
+++ b/mesalib/src/mesa/vbo/vbo_save_draw.c
@@ -1,303 +1,303 @@
-/*
- * Mesa 3-D graphics library
- * Version: 7.2
- *
- * Copyright (C) 1999-2008 Brian Paul All Rights Reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included
- * in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
- * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- */
-
-/* Author:
- * Keith Whitwell <keith@tungstengraphics.com>
- */
-
-#include "main/glheader.h"
-#include "main/bufferobj.h"
-#include "main/context.h"
-#include "main/imports.h"
-#include "main/mtypes.h"
-#include "main/macros.h"
-#include "main/light.h"
-#include "main/state.h"
-
-#include "vbo_context.h"
-
-
-#if FEATURE_dlist
-
-
-/**
- * After playback, copy everything but the position from the
- * last vertex to the saved state
- */
-static void
-_playback_copy_to_current(GLcontext *ctx,
- const struct vbo_save_vertex_list *node)
-{
- struct vbo_context *vbo = vbo_context(ctx);
- GLfloat vertex[VBO_ATTRIB_MAX * 4];
- GLfloat *data;
- GLuint i, offset;
-
- if (node->current_size == 0)
- return;
-
- if (node->current_data) {
- data = node->current_data;
- }
- else {
- data = vertex;
-
- if (node->count)
- offset = (node->buffer_offset +
- (node->count-1) * node->vertex_size * sizeof(GLfloat));
- else
- offset = node->buffer_offset;
-
- ctx->Driver.GetBufferSubData( ctx, 0, offset,
- node->vertex_size * sizeof(GLfloat),
- data, node->vertex_store->bufferobj );
-
- data += node->attrsz[0]; /* skip vertex position */
- }
-
- for (i = VBO_ATTRIB_POS+1 ; i < VBO_ATTRIB_MAX ; i++) {
- if (node->attrsz[i]) {
- GLfloat *current = (GLfloat *)vbo->currval[i].Ptr;
- GLfloat tmp[4];
-
- COPY_CLEAN_4V(tmp,
- node->attrsz[i],
- data);
-
- if (memcmp(current, tmp, 4 * sizeof(GLfloat)) != 0) {
- memcpy(current, tmp, 4 * sizeof(GLfloat));
-
- vbo->currval[i].Size = node->attrsz[i];
-
- if (i >= VBO_ATTRIB_FIRST_MATERIAL &&
- i <= VBO_ATTRIB_LAST_MATERIAL)
- ctx->NewState |= _NEW_LIGHT;
-
- ctx->NewState |= _NEW_CURRENT_ATTRIB;
- }
-
- data += node->attrsz[i];
- }
- }
-
- /* Colormaterial -- this kindof sucks.
- */
- if (ctx->Light.ColorMaterialEnabled) {
- _mesa_update_color_material(ctx, ctx->Current.Attrib[VBO_ATTRIB_COLOR0]);
- }
-
- /* CurrentExecPrimitive
- */
- if (node->prim_count) {
- const struct _mesa_prim *prim = &node->prim[node->prim_count - 1];
- if (prim->end)
- ctx->Driver.CurrentExecPrimitive = PRIM_OUTSIDE_BEGIN_END;
- else
- ctx->Driver.CurrentExecPrimitive = prim->mode;
- }
-}
-
-
-
-/**
- * Treat the vertex storage as a VBO, define vertex arrays pointing
- * into it:
- */
-static void vbo_bind_vertex_list(GLcontext *ctx,
- const struct vbo_save_vertex_list *node)
-{
- struct vbo_context *vbo = vbo_context(ctx);
- struct vbo_save_context *save = &vbo->save;
- struct gl_client_array *arrays = save->arrays;
- GLuint buffer_offset = node->buffer_offset;
- const GLuint *map;
- GLuint attr;
- GLubyte node_attrsz[VBO_ATTRIB_MAX]; /* copy of node->attrsz[] */
- GLbitfield varying_inputs = 0x0;
-
- memcpy(node_attrsz, node->attrsz, sizeof(node->attrsz));
-
- /* Install the default (ie Current) attributes first, then overlay
- * all active ones.
- */
- switch (get_program_mode(ctx)) {
- case VP_NONE:
- for (attr = 0; attr < 16; attr++) {
- save->inputs[attr] = &vbo->legacy_currval[attr];
- }
- for (attr = 0; attr < MAT_ATTRIB_MAX; attr++) {
- save->inputs[attr + 16] = &vbo->mat_currval[attr];
- }
- map = vbo->map_vp_none;
- break;
- case VP_NV:
- case VP_ARB:
- /* The aliasing of attributes for NV vertex programs has already
- * occurred. NV vertex programs cannot access material values,
- * nor attributes greater than VERT_ATTRIB_TEX7.
- */
- for (attr = 0; attr < 16; attr++) {
- save->inputs[attr] = &vbo->legacy_currval[attr];
- save->inputs[attr + 16] = &vbo->generic_currval[attr];
- }
- map = vbo->map_vp_arb;
-
- /* check if VERT_ATTRIB_POS is not read but VERT_BIT_GENERIC0 is read.
- * In that case we effectively need to route the data from
- * glVertexAttrib(0, val) calls to feed into the GENERIC0 input.
- */
- if ((ctx->VertexProgram._Current->Base.InputsRead & VERT_BIT_POS) == 0 &&
- (ctx->VertexProgram._Current->Base.InputsRead & VERT_BIT_GENERIC0)) {
- save->inputs[16] = save->inputs[0];
- node_attrsz[16] = node_attrsz[0];
- node_attrsz[0] = 0;
- }
- break;
- default:
- assert(0);
- }
-
- for (attr = 0; attr < VERT_ATTRIB_MAX; attr++) {
- const GLuint src = map[attr];
-
- if (node_attrsz[src]) {
- /* override the default array set above */
- save->inputs[attr] = &arrays[attr];
-
- arrays[attr].Ptr = (const GLubyte *) NULL + buffer_offset;
- arrays[attr].Size = node->attrsz[src];
- arrays[attr].StrideB = node->vertex_size * sizeof(GLfloat);
- arrays[attr].Stride = node->vertex_size * sizeof(GLfloat);
- arrays[attr].Type = GL_FLOAT;
- arrays[attr].Format = GL_RGBA;
- arrays[attr].Enabled = 1;
- _mesa_reference_buffer_object(ctx,
- &arrays[attr].BufferObj,
- node->vertex_store->bufferobj);
- arrays[attr]._MaxElement = node->count; /* ??? */
-
- assert(arrays[attr].BufferObj->Name);
-
- buffer_offset += node->attrsz[src] * sizeof(GLfloat);
- varying_inputs |= 1<<attr;
- }
- }
-
- _mesa_set_varying_vp_inputs( ctx, varying_inputs );
-}
-
-
-static void
-vbo_save_loopback_vertex_list(GLcontext *ctx,
- const struct vbo_save_vertex_list *list)
-{
- const char *buffer = ctx->Driver.MapBuffer(ctx,
- GL_ARRAY_BUFFER_ARB,
- GL_READ_ONLY, /* ? */
- list->vertex_store->bufferobj);
-
- vbo_loopback_vertex_list(ctx,
- (const GLfloat *)(buffer + list->buffer_offset),
- list->attrsz,
- list->prim,
- list->prim_count,
- list->wrap_count,
- list->vertex_size);
-
- ctx->Driver.UnmapBuffer(ctx, GL_ARRAY_BUFFER_ARB,
- list->vertex_store->bufferobj);
-}
-
-
-/**
- * Execute the buffer and save copied verts.
- * This is called from the display list code when executing
- * a drawing command.
- */
-void
-vbo_save_playback_vertex_list(GLcontext *ctx, void *data)
-{
- const struct vbo_save_vertex_list *node =
- (const struct vbo_save_vertex_list *) data;
- struct vbo_save_context *save = &vbo_context(ctx)->save;
-
- FLUSH_CURRENT(ctx, 0);
-
- if (node->prim_count > 0 && node->count > 0) {
-
- if (ctx->Driver.CurrentExecPrimitive != PRIM_OUTSIDE_BEGIN_END &&
- node->prim[0].begin) {
-
- /* Degenerate case: list is called inside begin/end pair and
- * includes operations such as glBegin or glDrawArrays.
- */
- if (0)
- printf("displaylist recursive begin");
-
- vbo_save_loopback_vertex_list( ctx, node );
- return;
- }
- else if (save->replay_flags) {
- /* Various degnerate cases: translate into immediate mode
- * calls rather than trying to execute in place.
- */
- vbo_save_loopback_vertex_list( ctx, node );
- return;
- }
-
- if (ctx->NewState)
- _mesa_update_state( ctx );
-
- /* XXX also need to check if shader enabled, but invalid */
- if ((ctx->VertexProgram.Enabled && !ctx->VertexProgram._Enabled) ||
- (ctx->FragmentProgram.Enabled && !ctx->FragmentProgram._Enabled)) {
- _mesa_error(ctx, GL_INVALID_OPERATION,
- "glBegin (invalid vertex/fragment program)");
- return;
- }
-
- vbo_bind_vertex_list( ctx, node );
-
- /* Again...
- */
- if (ctx->NewState)
- _mesa_update_state( ctx );
-
- vbo_context(ctx)->draw_prims(ctx,
- save->inputs,
- node->prim,
- node->prim_count,
- NULL,
- GL_TRUE,
- 0, /* Node is a VBO, so this is ok */
- node->count - 1);
- }
-
- /* Copy to current?
- */
- _playback_copy_to_current( ctx, node );
-}
-
-
-#endif /* FEATURE_dlist */
+/*
+ * Mesa 3-D graphics library
+ * Version: 7.2
+ *
+ * Copyright (C) 1999-2008 Brian Paul All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+ * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/* Author:
+ * Keith Whitwell <keith@tungstengraphics.com>
+ */
+
+#include "main/glheader.h"
+#include "main/bufferobj.h"
+#include "main/context.h"
+#include "main/imports.h"
+#include "main/mtypes.h"
+#include "main/macros.h"
+#include "main/light.h"
+#include "main/state.h"
+
+#include "vbo_context.h"
+
+
+#if FEATURE_dlist
+
+
+/**
+ * After playback, copy everything but the position from the
+ * last vertex to the saved state
+ */
+static void
+_playback_copy_to_current(struct gl_context *ctx,
+ const struct vbo_save_vertex_list *node)
+{
+ struct vbo_context *vbo = vbo_context(ctx);
+ GLfloat vertex[VBO_ATTRIB_MAX * 4];
+ GLfloat *data;
+ GLuint i, offset;
+
+ if (node->current_size == 0)
+ return;
+
+ if (node->current_data) {
+ data = node->current_data;
+ }
+ else {
+ data = vertex;
+
+ if (node->count)
+ offset = (node->buffer_offset +
+ (node->count-1) * node->vertex_size * sizeof(GLfloat));
+ else
+ offset = node->buffer_offset;
+
+ ctx->Driver.GetBufferSubData( ctx, 0, offset,
+ node->vertex_size * sizeof(GLfloat),
+ data, node->vertex_store->bufferobj );
+
+ data += node->attrsz[0]; /* skip vertex position */
+ }
+
+ for (i = VBO_ATTRIB_POS+1 ; i < VBO_ATTRIB_MAX ; i++) {
+ if (node->attrsz[i]) {
+ GLfloat *current = (GLfloat *)vbo->currval[i].Ptr;
+ GLfloat tmp[4];
+
+ COPY_CLEAN_4V(tmp,
+ node->attrsz[i],
+ data);
+
+ if (memcmp(current, tmp, 4 * sizeof(GLfloat)) != 0) {
+ memcpy(current, tmp, 4 * sizeof(GLfloat));
+
+ vbo->currval[i].Size = node->attrsz[i];
+
+ if (i >= VBO_ATTRIB_FIRST_MATERIAL &&
+ i <= VBO_ATTRIB_LAST_MATERIAL)
+ ctx->NewState |= _NEW_LIGHT;
+
+ ctx->NewState |= _NEW_CURRENT_ATTRIB;
+ }
+
+ data += node->attrsz[i];
+ }
+ }
+
+ /* Colormaterial -- this kindof sucks.
+ */
+ if (ctx->Light.ColorMaterialEnabled) {
+ _mesa_update_color_material(ctx, ctx->Current.Attrib[VBO_ATTRIB_COLOR0]);
+ }
+
+ /* CurrentExecPrimitive
+ */
+ if (node->prim_count) {
+ const struct _mesa_prim *prim = &node->prim[node->prim_count - 1];
+ if (prim->end)
+ ctx->Driver.CurrentExecPrimitive = PRIM_OUTSIDE_BEGIN_END;
+ else
+ ctx->Driver.CurrentExecPrimitive = prim->mode;
+ }
+}
+
+
+
+/**
+ * Treat the vertex storage as a VBO, define vertex arrays pointing
+ * into it:
+ */
+static void vbo_bind_vertex_list(struct gl_context *ctx,
+ const struct vbo_save_vertex_list *node)
+{
+ struct vbo_context *vbo = vbo_context(ctx);
+ struct vbo_save_context *save = &vbo->save;
+ struct gl_client_array *arrays = save->arrays;
+ GLuint buffer_offset = node->buffer_offset;
+ const GLuint *map;
+ GLuint attr;
+ GLubyte node_attrsz[VBO_ATTRIB_MAX]; /* copy of node->attrsz[] */
+ GLbitfield varying_inputs = 0x0;
+
+ memcpy(node_attrsz, node->attrsz, sizeof(node->attrsz));
+
+ /* Install the default (ie Current) attributes first, then overlay
+ * all active ones.
+ */
+ switch (get_program_mode(ctx)) {
+ case VP_NONE:
+ for (attr = 0; attr < 16; attr++) {
+ save->inputs[attr] = &vbo->legacy_currval[attr];
+ }
+ for (attr = 0; attr < MAT_ATTRIB_MAX; attr++) {
+ save->inputs[attr + 16] = &vbo->mat_currval[attr];
+ }
+ map = vbo->map_vp_none;
+ break;
+ case VP_NV:
+ case VP_ARB:
+ /* The aliasing of attributes for NV vertex programs has already
+ * occurred. NV vertex programs cannot access material values,
+ * nor attributes greater than VERT_ATTRIB_TEX7.
+ */
+ for (attr = 0; attr < 16; attr++) {
+ save->inputs[attr] = &vbo->legacy_currval[attr];
+ save->inputs[attr + 16] = &vbo->generic_currval[attr];
+ }
+ map = vbo->map_vp_arb;
+
+ /* check if VERT_ATTRIB_POS is not read but VERT_BIT_GENERIC0 is read.
+ * In that case we effectively need to route the data from
+ * glVertexAttrib(0, val) calls to feed into the GENERIC0 input.
+ */
+ if ((ctx->VertexProgram._Current->Base.InputsRead & VERT_BIT_POS) == 0 &&
+ (ctx->VertexProgram._Current->Base.InputsRead & VERT_BIT_GENERIC0)) {
+ save->inputs[16] = save->inputs[0];
+ node_attrsz[16] = node_attrsz[0];
+ node_attrsz[0] = 0;
+ }
+ break;
+ default:
+ assert(0);
+ }
+
+ for (attr = 0; attr < VERT_ATTRIB_MAX; attr++) {
+ const GLuint src = map[attr];
+
+ if (node_attrsz[src]) {
+ /* override the default array set above */
+ save->inputs[attr] = &arrays[attr];
+
+ arrays[attr].Ptr = (const GLubyte *) NULL + buffer_offset;
+ arrays[attr].Size = node->attrsz[src];
+ arrays[attr].StrideB = node->vertex_size * sizeof(GLfloat);
+ arrays[attr].Stride = node->vertex_size * sizeof(GLfloat);
+ arrays[attr].Type = GL_FLOAT;
+ arrays[attr].Format = GL_RGBA;
+ arrays[attr].Enabled = 1;
+ _mesa_reference_buffer_object(ctx,
+ &arrays[attr].BufferObj,
+ node->vertex_store->bufferobj);
+ arrays[attr]._MaxElement = node->count; /* ??? */
+
+ assert(arrays[attr].BufferObj->Name);
+
+ buffer_offset += node->attrsz[src] * sizeof(GLfloat);
+ varying_inputs |= 1<<attr;
+ }
+ }
+
+ _mesa_set_varying_vp_inputs( ctx, varying_inputs );
+}
+
+
+static void
+vbo_save_loopback_vertex_list(struct gl_context *ctx,
+ const struct vbo_save_vertex_list *list)
+{
+ const char *buffer = ctx->Driver.MapBuffer(ctx,
+ GL_ARRAY_BUFFER_ARB,
+ GL_READ_ONLY, /* ? */
+ list->vertex_store->bufferobj);
+
+ vbo_loopback_vertex_list(ctx,
+ (const GLfloat *)(buffer + list->buffer_offset),
+ list->attrsz,
+ list->prim,
+ list->prim_count,
+ list->wrap_count,
+ list->vertex_size);
+
+ ctx->Driver.UnmapBuffer(ctx, GL_ARRAY_BUFFER_ARB,
+ list->vertex_store->bufferobj);
+}
+
+
+/**
+ * Execute the buffer and save copied verts.
+ * This is called from the display list code when executing
+ * a drawing command.
+ */
+void
+vbo_save_playback_vertex_list(struct gl_context *ctx, void *data)
+{
+ const struct vbo_save_vertex_list *node =
+ (const struct vbo_save_vertex_list *) data;
+ struct vbo_save_context *save = &vbo_context(ctx)->save;
+
+ FLUSH_CURRENT(ctx, 0);
+
+ if (node->prim_count > 0 && node->count > 0) {
+
+ if (ctx->Driver.CurrentExecPrimitive != PRIM_OUTSIDE_BEGIN_END &&
+ node->prim[0].begin) {
+
+ /* Degenerate case: list is called inside begin/end pair and
+ * includes operations such as glBegin or glDrawArrays.
+ */
+ if (0)
+ printf("displaylist recursive begin");
+
+ vbo_save_loopback_vertex_list( ctx, node );
+ return;
+ }
+ else if (save->replay_flags) {
+ /* Various degnerate cases: translate into immediate mode
+ * calls rather than trying to execute in place.
+ */
+ vbo_save_loopback_vertex_list( ctx, node );
+ return;
+ }
+
+ if (ctx->NewState)
+ _mesa_update_state( ctx );
+
+ /* XXX also need to check if shader enabled, but invalid */
+ if ((ctx->VertexProgram.Enabled && !ctx->VertexProgram._Enabled) ||
+ (ctx->FragmentProgram.Enabled && !ctx->FragmentProgram._Enabled)) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glBegin (invalid vertex/fragment program)");
+ return;
+ }
+
+ vbo_bind_vertex_list( ctx, node );
+
+ /* Again...
+ */
+ if (ctx->NewState)
+ _mesa_update_state( ctx );
+
+ vbo_context(ctx)->draw_prims(ctx,
+ save->inputs,
+ node->prim,
+ node->prim_count,
+ NULL,
+ GL_TRUE,
+ 0, /* Node is a VBO, so this is ok */
+ node->count - 1);
+ }
+
+ /* Copy to current?
+ */
+ _playback_copy_to_current( ctx, node );
+}
+
+
+#endif /* FEATURE_dlist */
diff --git a/mesalib/src/mesa/vbo/vbo_save_loopback.c b/mesalib/src/mesa/vbo/vbo_save_loopback.c
index 5d1c7e481..cc48e4a69 100644
--- a/mesalib/src/mesa/vbo/vbo_save_loopback.c
+++ b/mesalib/src/mesa/vbo/vbo_save_loopback.c
@@ -1,195 +1,195 @@
-/**************************************************************************
- *
- * Copyright 2005 Tungsten Graphics, Inc., Cedar Park, Texas.
- * All Rights Reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the
- * "Software"), to deal in the Software without restriction, including
- * without limitation the rights to use, copy, modify, merge, publish,
- * distribute, sub license, and/or sell copies of the Software, and to
- * permit persons to whom the Software is furnished to do so, subject to
- * the following conditions:
- *
- * The above copyright notice and this permission notice (including the
- * next paragraph) shall be included in all copies or substantial portions
- * of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
- * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
- * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
- * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
- * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- *
- **************************************************************************/
-
-#include "main/context.h"
-#include "main/glheader.h"
-#include "main/enums.h"
-#include "main/imports.h"
-#include "main/mtypes.h"
-#include "main/dispatch.h"
-#include "glapi/glapi.h"
-
-#include "vbo_context.h"
-
-
-#if FEATURE_dlist
-
-
-typedef void (*attr_func)( GLcontext *ctx, GLint target, const GLfloat * );
-
-
-/* This file makes heavy use of the aliasing of NV vertex attributes
- * with the legacy attributes, and also with ARB and Material
- * attributes as currently implemented.
- */
-static void VertexAttrib1fvNV(GLcontext *ctx, GLint target, const GLfloat *v)
-{
- CALL_VertexAttrib1fvNV(ctx->Exec, (target, v));
-}
-
-static void VertexAttrib2fvNV(GLcontext *ctx, GLint target, const GLfloat *v)
-{
- CALL_VertexAttrib2fvNV(ctx->Exec, (target, v));
-}
-
-static void VertexAttrib3fvNV(GLcontext *ctx, GLint target, const GLfloat *v)
-{
- CALL_VertexAttrib3fvNV(ctx->Exec, (target, v));
-}
-
-static void VertexAttrib4fvNV(GLcontext *ctx, GLint target, const GLfloat *v)
-{
- CALL_VertexAttrib4fvNV(ctx->Exec, (target, v));
-}
-
-static attr_func vert_attrfunc[4] = {
- VertexAttrib1fvNV,
- VertexAttrib2fvNV,
- VertexAttrib3fvNV,
- VertexAttrib4fvNV
-};
-
-struct loopback_attr {
- GLint target;
- GLint sz;
- attr_func func;
-};
-
-/* Don't emit ends and begins on wrapped primitives. Don't replay
- * wrapped vertices. If we get here, it's probably because the
- * precalculated wrapping is wrong.
- */
-static void loopback_prim( GLcontext *ctx,
- const GLfloat *buffer,
- const struct _mesa_prim *prim,
- GLuint wrap_count,
- GLuint vertex_size,
- const struct loopback_attr *la, GLuint nr )
-{
- GLint start = prim->start;
- GLint end = start + prim->count;
- const GLfloat *data;
- GLint j;
- GLuint k;
-
- if (0)
- printf("loopback prim %s(%s,%s) verts %d..%d\n",
- _mesa_lookup_prim_by_nr(prim->mode),
- prim->begin ? "begin" : "..",
- prim->end ? "end" : "..",
- start,
- end);
-
- if (prim->begin) {
- CALL_Begin(GET_DISPATCH(), ( prim->mode ));
- }
- else {
- assert(start == 0);
- start += wrap_count;
- }
-
- data = buffer + start * vertex_size;
-
- for (j = start ; j < end ; j++) {
- const GLfloat *tmp = data + la[0].sz;
-
- for (k = 1 ; k < nr ; k++) {
- la[k].func( ctx, la[k].target, tmp );
- tmp += la[k].sz;
- }
-
- /* Fire the vertex
- */
- la[0].func( ctx, VBO_ATTRIB_POS, data );
- data = tmp;
- }
-
- if (prim->end) {
- CALL_End(GET_DISPATCH(), ());
- }
-}
-
-/* Primitives generated by DrawArrays/DrawElements/Rectf may be
- * caught here. If there is no primitive in progress, execute them
- * normally, otherwise need to track and discard the generated
- * primitives.
- */
-static void loopback_weak_prim( GLcontext *ctx,
- const struct _mesa_prim *prim )
-{
- /* Use the prim_weak flag to ensure that if this primitive
- * wraps, we don't mistake future vertex_lists for part of the
- * surrounding primitive.
- *
- * While this flag is set, we are simply disposing of data
- * generated by an operation now known to be a noop.
- */
- if (prim->begin)
- ctx->Driver.CurrentExecPrimitive |= VBO_SAVE_PRIM_WEAK;
- if (prim->end)
- ctx->Driver.CurrentExecPrimitive &= ~VBO_SAVE_PRIM_WEAK;
-}
-
-
-void vbo_loopback_vertex_list( GLcontext *ctx,
- const GLfloat *buffer,
- const GLubyte *attrsz,
- const struct _mesa_prim *prim,
- GLuint prim_count,
- GLuint wrap_count,
- GLuint vertex_size)
-{
- struct loopback_attr la[VBO_ATTRIB_MAX];
- GLuint i, nr = 0;
-
- /* All Legacy, NV, ARB and Material attributes are routed through
- * the NV attributes entrypoints:
- */
- for (i = 0 ; i < VBO_ATTRIB_MAX ; i++) {
- if (attrsz[i]) {
- la[nr].target = i;
- la[nr].sz = attrsz[i];
- la[nr].func = vert_attrfunc[attrsz[i]-1];
- nr++;
- }
- }
-
- for (i = 0 ; i < prim_count ; i++) {
- if ((prim[i].mode & VBO_SAVE_PRIM_WEAK) &&
- (ctx->Driver.CurrentExecPrimitive != PRIM_OUTSIDE_BEGIN_END))
- {
- loopback_weak_prim( ctx, &prim[i] );
- }
- else
- {
- loopback_prim( ctx, buffer, &prim[i], wrap_count, vertex_size, la, nr );
- }
- }
-}
-
-
-#endif /* FEATURE_dlist */
+/**************************************************************************
+ *
+ * Copyright 2005 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+#include "main/context.h"
+#include "main/glheader.h"
+#include "main/enums.h"
+#include "main/imports.h"
+#include "main/mtypes.h"
+#include "main/dispatch.h"
+#include "glapi/glapi.h"
+
+#include "vbo_context.h"
+
+
+#if FEATURE_dlist
+
+
+typedef void (*attr_func)( struct gl_context *ctx, GLint target, const GLfloat * );
+
+
+/* This file makes heavy use of the aliasing of NV vertex attributes
+ * with the legacy attributes, and also with ARB and Material
+ * attributes as currently implemented.
+ */
+static void VertexAttrib1fvNV(struct gl_context *ctx, GLint target, const GLfloat *v)
+{
+ CALL_VertexAttrib1fvNV(ctx->Exec, (target, v));
+}
+
+static void VertexAttrib2fvNV(struct gl_context *ctx, GLint target, const GLfloat *v)
+{
+ CALL_VertexAttrib2fvNV(ctx->Exec, (target, v));
+}
+
+static void VertexAttrib3fvNV(struct gl_context *ctx, GLint target, const GLfloat *v)
+{
+ CALL_VertexAttrib3fvNV(ctx->Exec, (target, v));
+}
+
+static void VertexAttrib4fvNV(struct gl_context *ctx, GLint target, const GLfloat *v)
+{
+ CALL_VertexAttrib4fvNV(ctx->Exec, (target, v));
+}
+
+static attr_func vert_attrfunc[4] = {
+ VertexAttrib1fvNV,
+ VertexAttrib2fvNV,
+ VertexAttrib3fvNV,
+ VertexAttrib4fvNV
+};
+
+struct loopback_attr {
+ GLint target;
+ GLint sz;
+ attr_func func;
+};
+
+/* Don't emit ends and begins on wrapped primitives. Don't replay
+ * wrapped vertices. If we get here, it's probably because the
+ * precalculated wrapping is wrong.
+ */
+static void loopback_prim( struct gl_context *ctx,
+ const GLfloat *buffer,
+ const struct _mesa_prim *prim,
+ GLuint wrap_count,
+ GLuint vertex_size,
+ const struct loopback_attr *la, GLuint nr )
+{
+ GLint start = prim->start;
+ GLint end = start + prim->count;
+ const GLfloat *data;
+ GLint j;
+ GLuint k;
+
+ if (0)
+ printf("loopback prim %s(%s,%s) verts %d..%d\n",
+ _mesa_lookup_prim_by_nr(prim->mode),
+ prim->begin ? "begin" : "..",
+ prim->end ? "end" : "..",
+ start,
+ end);
+
+ if (prim->begin) {
+ CALL_Begin(GET_DISPATCH(), ( prim->mode ));
+ }
+ else {
+ assert(start == 0);
+ start += wrap_count;
+ }
+
+ data = buffer + start * vertex_size;
+
+ for (j = start ; j < end ; j++) {
+ const GLfloat *tmp = data + la[0].sz;
+
+ for (k = 1 ; k < nr ; k++) {
+ la[k].func( ctx, la[k].target, tmp );
+ tmp += la[k].sz;
+ }
+
+ /* Fire the vertex
+ */
+ la[0].func( ctx, VBO_ATTRIB_POS, data );
+ data = tmp;
+ }
+
+ if (prim->end) {
+ CALL_End(GET_DISPATCH(), ());
+ }
+}
+
+/* Primitives generated by DrawArrays/DrawElements/Rectf may be
+ * caught here. If there is no primitive in progress, execute them
+ * normally, otherwise need to track and discard the generated
+ * primitives.
+ */
+static void loopback_weak_prim( struct gl_context *ctx,
+ const struct _mesa_prim *prim )
+{
+ /* Use the prim_weak flag to ensure that if this primitive
+ * wraps, we don't mistake future vertex_lists for part of the
+ * surrounding primitive.
+ *
+ * While this flag is set, we are simply disposing of data
+ * generated by an operation now known to be a noop.
+ */
+ if (prim->begin)
+ ctx->Driver.CurrentExecPrimitive |= VBO_SAVE_PRIM_WEAK;
+ if (prim->end)
+ ctx->Driver.CurrentExecPrimitive &= ~VBO_SAVE_PRIM_WEAK;
+}
+
+
+void vbo_loopback_vertex_list( struct gl_context *ctx,
+ const GLfloat *buffer,
+ const GLubyte *attrsz,
+ const struct _mesa_prim *prim,
+ GLuint prim_count,
+ GLuint wrap_count,
+ GLuint vertex_size)
+{
+ struct loopback_attr la[VBO_ATTRIB_MAX];
+ GLuint i, nr = 0;
+
+ /* All Legacy, NV, ARB and Material attributes are routed through
+ * the NV attributes entrypoints:
+ */
+ for (i = 0 ; i < VBO_ATTRIB_MAX ; i++) {
+ if (attrsz[i]) {
+ la[nr].target = i;
+ la[nr].sz = attrsz[i];
+ la[nr].func = vert_attrfunc[attrsz[i]-1];
+ nr++;
+ }
+ }
+
+ for (i = 0 ; i < prim_count ; i++) {
+ if ((prim[i].mode & VBO_SAVE_PRIM_WEAK) &&
+ (ctx->Driver.CurrentExecPrimitive != PRIM_OUTSIDE_BEGIN_END))
+ {
+ loopback_weak_prim( ctx, &prim[i] );
+ }
+ else
+ {
+ loopback_prim( ctx, buffer, &prim[i], wrap_count, vertex_size, la, nr );
+ }
+ }
+}
+
+
+#endif /* FEATURE_dlist */
diff --git a/mesalib/src/mesa/vbo/vbo_split.c b/mesalib/src/mesa/vbo/vbo_split.c
index ce40cbbcc..e28f9afcf 100644
--- a/mesalib/src/mesa/vbo/vbo_split.c
+++ b/mesalib/src/mesa/vbo/vbo_split.c
@@ -1,169 +1,169 @@
-
-/*
- * Mesa 3-D graphics library
- * Version: 6.5
- *
- * Copyright (C) 1999-2006 Brian Paul All Rights Reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included
- * in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
- * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- *
- * Authors:
- * Keith Whitwell <keith@tungstengraphics.com>
- */
-
-/* Deal with hardware and/or swtnl maximums:
- * - maximum number of vertices in buffer
- * - maximum number of elements (maybe zero)
- *
- * The maximums may vary with opengl state (eg if a larger hardware
- * vertex is required in this state, the maximum number of vertices
- * may be smaller than in another state).
- *
- * We want buffer splitting to be a convenience function for the code
- * actually drawing the primitives rather than a system-wide maximum,
- * otherwise it is hard to avoid pessimism.
- *
- * For instance, if a driver has no hardware limits on vertex buffer
- * dimensions, it would not ordinarily want to split vbos. But if
- * there is an unexpected fallback, eg memory manager fails to upload
- * textures, it will want to pass the drawing commands onto swtnl,
- * which does have limitations. A convenience function allows swtnl
- * to split the drawing and vbos internally without imposing its
- * limitations on drivers which want to use it as a fallback path.
- */
-
-#include "main/glheader.h"
-#include "main/imports.h"
-#include "main/mtypes.h"
-#include "main/macros.h"
-
-#include "vbo_split.h"
-#include "vbo.h"
-
-/* True if a primitive can be split without copying of vertices, false
- * otherwise.
- */
-GLboolean split_prim_inplace(GLenum mode, GLuint *first, GLuint *incr)
-{
- switch (mode) {
- case GL_POINTS:
- *first = 1;
- *incr = 1;
- return GL_TRUE;
- case GL_LINES:
- *first = 2;
- *incr = 2;
- return GL_TRUE;
- case GL_LINE_STRIP:
- *first = 2;
- *incr = 1;
- return GL_TRUE;
- case GL_TRIANGLES:
- *first = 3;
- *incr = 3;
- return GL_TRUE;
- case GL_TRIANGLE_STRIP:
- *first = 3;
- *incr = 1;
- return GL_TRUE;
- case GL_QUADS:
- *first = 4;
- *incr = 4;
- return GL_TRUE;
- case GL_QUAD_STRIP:
- *first = 4;
- *incr = 2;
- return GL_TRUE;
- default:
- *first = 0;
- *incr = 1; /* so that count % incr works */
- return GL_FALSE;
- }
-}
-
-
-
-void vbo_split_prims( GLcontext *ctx,
- const struct gl_client_array *arrays[],
- const struct _mesa_prim *prim,
- GLuint nr_prims,
- const struct _mesa_index_buffer *ib,
- GLuint min_index,
- GLuint max_index,
- vbo_draw_func draw,
- const struct split_limits *limits )
-{
- GLint max_basevertex = prim->basevertex;
- GLuint i;
-
- for (i = 1; i < nr_prims; i++)
- max_basevertex = MAX2(max_basevertex, prim[i].basevertex);
-
- /* XXX max_basevertex is computed but not used, why? */
-
- if (ib) {
- if (limits->max_indices == 0) {
- /* Could traverse the indices, re-emitting vertices in turn.
- * But it's hard to see why this case would be needed - for
- * software tnl, it is better to convert to non-indexed
- * rendering after transformation is complete, as is done in
- * the t_dd_rendertmp.h templates. Are there any devices
- * with hardware tnl that cannot do indexed rendering?
- *
- * For now, this path is disabled.
- */
- assert(0);
- }
- else if (max_index - min_index >= limits->max_verts) {
- /* The vertex buffers are too large for hardware (or the
- * swtnl module). Traverse the indices, re-emitting vertices
- * in turn. Use a vertex cache to preserve some of the
- * sharing from the original index list.
- */
- vbo_split_copy(ctx, arrays, prim, nr_prims, ib,
- draw, limits );
- }
- else if (ib->count > limits->max_indices) {
- /* The index buffer is too large for hardware. Try to split
- * on whole-primitive boundaries, otherwise try to split the
- * individual primitives.
- */
- vbo_split_inplace(ctx, arrays, prim, nr_prims, ib,
- min_index, max_index, draw, limits );
- }
- else {
- /* Why were we called? */
- assert(0);
- }
- }
- else {
- if (max_index - min_index >= limits->max_verts) {
- /* The vertex buffer is too large for hardware (or the swtnl
- * module). Try to split on whole-primitive boundaries,
- * otherwise try to split the individual primitives.
- */
- vbo_split_inplace(ctx, arrays, prim, nr_prims, ib,
- min_index, max_index, draw, limits );
- }
- else {
- /* Why were we called? */
- assert(0);
- }
- }
-}
-
+
+/*
+ * Mesa 3-D graphics library
+ * Version: 6.5
+ *
+ * Copyright (C) 1999-2006 Brian Paul All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+ * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors:
+ * Keith Whitwell <keith@tungstengraphics.com>
+ */
+
+/* Deal with hardware and/or swtnl maximums:
+ * - maximum number of vertices in buffer
+ * - maximum number of elements (maybe zero)
+ *
+ * The maximums may vary with opengl state (eg if a larger hardware
+ * vertex is required in this state, the maximum number of vertices
+ * may be smaller than in another state).
+ *
+ * We want buffer splitting to be a convenience function for the code
+ * actually drawing the primitives rather than a system-wide maximum,
+ * otherwise it is hard to avoid pessimism.
+ *
+ * For instance, if a driver has no hardware limits on vertex buffer
+ * dimensions, it would not ordinarily want to split vbos. But if
+ * there is an unexpected fallback, eg memory manager fails to upload
+ * textures, it will want to pass the drawing commands onto swtnl,
+ * which does have limitations. A convenience function allows swtnl
+ * to split the drawing and vbos internally without imposing its
+ * limitations on drivers which want to use it as a fallback path.
+ */
+
+#include "main/glheader.h"
+#include "main/imports.h"
+#include "main/mtypes.h"
+#include "main/macros.h"
+
+#include "vbo_split.h"
+#include "vbo.h"
+
+/* True if a primitive can be split without copying of vertices, false
+ * otherwise.
+ */
+GLboolean split_prim_inplace(GLenum mode, GLuint *first, GLuint *incr)
+{
+ switch (mode) {
+ case GL_POINTS:
+ *first = 1;
+ *incr = 1;
+ return GL_TRUE;
+ case GL_LINES:
+ *first = 2;
+ *incr = 2;
+ return GL_TRUE;
+ case GL_LINE_STRIP:
+ *first = 2;
+ *incr = 1;
+ return GL_TRUE;
+ case GL_TRIANGLES:
+ *first = 3;
+ *incr = 3;
+ return GL_TRUE;
+ case GL_TRIANGLE_STRIP:
+ *first = 3;
+ *incr = 1;
+ return GL_TRUE;
+ case GL_QUADS:
+ *first = 4;
+ *incr = 4;
+ return GL_TRUE;
+ case GL_QUAD_STRIP:
+ *first = 4;
+ *incr = 2;
+ return GL_TRUE;
+ default:
+ *first = 0;
+ *incr = 1; /* so that count % incr works */
+ return GL_FALSE;
+ }
+}
+
+
+
+void vbo_split_prims( struct gl_context *ctx,
+ const struct gl_client_array *arrays[],
+ const struct _mesa_prim *prim,
+ GLuint nr_prims,
+ const struct _mesa_index_buffer *ib,
+ GLuint min_index,
+ GLuint max_index,
+ vbo_draw_func draw,
+ const struct split_limits *limits )
+{
+ GLint max_basevertex = prim->basevertex;
+ GLuint i;
+
+ for (i = 1; i < nr_prims; i++)
+ max_basevertex = MAX2(max_basevertex, prim[i].basevertex);
+
+ /* XXX max_basevertex is computed but not used, why? */
+
+ if (ib) {
+ if (limits->max_indices == 0) {
+ /* Could traverse the indices, re-emitting vertices in turn.
+ * But it's hard to see why this case would be needed - for
+ * software tnl, it is better to convert to non-indexed
+ * rendering after transformation is complete, as is done in
+ * the t_dd_rendertmp.h templates. Are there any devices
+ * with hardware tnl that cannot do indexed rendering?
+ *
+ * For now, this path is disabled.
+ */
+ assert(0);
+ }
+ else if (max_index - min_index >= limits->max_verts) {
+ /* The vertex buffers are too large for hardware (or the
+ * swtnl module). Traverse the indices, re-emitting vertices
+ * in turn. Use a vertex cache to preserve some of the
+ * sharing from the original index list.
+ */
+ vbo_split_copy(ctx, arrays, prim, nr_prims, ib,
+ draw, limits );
+ }
+ else if (ib->count > limits->max_indices) {
+ /* The index buffer is too large for hardware. Try to split
+ * on whole-primitive boundaries, otherwise try to split the
+ * individual primitives.
+ */
+ vbo_split_inplace(ctx, arrays, prim, nr_prims, ib,
+ min_index, max_index, draw, limits );
+ }
+ else {
+ /* Why were we called? */
+ assert(0);
+ }
+ }
+ else {
+ if (max_index - min_index >= limits->max_verts) {
+ /* The vertex buffer is too large for hardware (or the swtnl
+ * module). Try to split on whole-primitive boundaries,
+ * otherwise try to split the individual primitives.
+ */
+ vbo_split_inplace(ctx, arrays, prim, nr_prims, ib,
+ min_index, max_index, draw, limits );
+ }
+ else {
+ /* Why were we called? */
+ assert(0);
+ }
+ }
+}
+
diff --git a/mesalib/src/mesa/vbo/vbo_split.h b/mesalib/src/mesa/vbo/vbo_split.h
index 05888d048..14cf9e49c 100644
--- a/mesalib/src/mesa/vbo/vbo_split.h
+++ b/mesalib/src/mesa/vbo/vbo_split.h
@@ -1,72 +1,72 @@
-/*
- * mesa 3-D graphics library
- * Version: 6.5
- *
- * Copyright (C) 1999-2006 Brian Paul All Rights Reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included
- * in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
- * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- */
-
-/**
- * \file vbo_context.h
- * \brief VBO builder module datatypes and definitions.
- * \author Keith Whitwell
- */
-
-
-/**
- * \mainpage The VBO splitter
- *
- * This is the private data used internally to the vbo_split_prims()
- * helper function. Nobody outside the vbo_split* files needs to
- * include or know about this structure.
- */
-
-
-#ifndef _VBO_SPLIT_H
-#define _VBO_SPLIT_H
-
-#include "vbo.h"
-
-
-/* True if a primitive can be split without copying of vertices, false
- * otherwise.
- */
-GLboolean split_prim_inplace(GLenum mode, GLuint *first, GLuint *incr);
-
-void vbo_split_inplace( GLcontext *ctx,
- const struct gl_client_array *arrays[],
- const struct _mesa_prim *prim,
- GLuint nr_prims,
- const struct _mesa_index_buffer *ib,
- GLuint min_index,
- GLuint max_index,
- vbo_draw_func draw,
- const struct split_limits *limits );
-
-/* Requires ib != NULL:
- */
-void vbo_split_copy( GLcontext *ctx,
- const struct gl_client_array *arrays[],
- const struct _mesa_prim *prim,
- GLuint nr_prims,
- const struct _mesa_index_buffer *ib,
- vbo_draw_func draw,
- const struct split_limits *limits );
-
-#endif
+/*
+ * mesa 3-D graphics library
+ * Version: 6.5
+ *
+ * Copyright (C) 1999-2006 Brian Paul All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+ * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/**
+ * \file vbo_context.h
+ * \brief VBO builder module datatypes and definitions.
+ * \author Keith Whitwell
+ */
+
+
+/**
+ * \mainpage The VBO splitter
+ *
+ * This is the private data used internally to the vbo_split_prims()
+ * helper function. Nobody outside the vbo_split* files needs to
+ * include or know about this structure.
+ */
+
+
+#ifndef _VBO_SPLIT_H
+#define _VBO_SPLIT_H
+
+#include "vbo.h"
+
+
+/* True if a primitive can be split without copying of vertices, false
+ * otherwise.
+ */
+GLboolean split_prim_inplace(GLenum mode, GLuint *first, GLuint *incr);
+
+void vbo_split_inplace( struct gl_context *ctx,
+ const struct gl_client_array *arrays[],
+ const struct _mesa_prim *prim,
+ GLuint nr_prims,
+ const struct _mesa_index_buffer *ib,
+ GLuint min_index,
+ GLuint max_index,
+ vbo_draw_func draw,
+ const struct split_limits *limits );
+
+/* Requires ib != NULL:
+ */
+void vbo_split_copy( struct gl_context *ctx,
+ const struct gl_client_array *arrays[],
+ const struct _mesa_prim *prim,
+ GLuint nr_prims,
+ const struct _mesa_index_buffer *ib,
+ vbo_draw_func draw,
+ const struct split_limits *limits );
+
+#endif
diff --git a/mesalib/src/mesa/vbo/vbo_split_copy.c b/mesalib/src/mesa/vbo/vbo_split_copy.c
index 2ec7d9b0f..e172da08b 100644
--- a/mesalib/src/mesa/vbo/vbo_split_copy.c
+++ b/mesalib/src/mesa/vbo/vbo_split_copy.c
@@ -1,625 +1,625 @@
-
-/*
- * Mesa 3-D graphics library
- * Version: 6.5
- *
- * Copyright (C) 1999-2006 Brian Paul All Rights Reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included
- * in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
- * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- *
- * Authors:
- * Keith Whitwell <keith@tungstengraphics.com>
- */
-
-/* Split indexed primitives with per-vertex copying.
- */
-
-#include "main/glheader.h"
-#include "main/bufferobj.h"
-#include "main/imports.h"
-#include "main/image.h"
-#include "main/macros.h"
-#include "main/mtypes.h"
-
-#include "vbo_split.h"
-#include "vbo.h"
-
-
-#define ELT_TABLE_SIZE 16
-
-/**
- * Used for vertex-level splitting of indexed buffers. Note that
- * non-indexed primitives may be converted to indexed in some cases
- * (eg loops, fans) in order to use this splitting path.
- */
-struct copy_context {
-
- GLcontext *ctx;
- const struct gl_client_array **array;
- const struct _mesa_prim *prim;
- GLuint nr_prims;
- const struct _mesa_index_buffer *ib;
- vbo_draw_func draw;
-
- const struct split_limits *limits;
-
- struct {
- GLuint attr;
- GLuint size;
- const struct gl_client_array *array;
- const GLubyte *src_ptr;
-
- struct gl_client_array dstarray;
-
- } varying[VERT_ATTRIB_MAX];
- GLuint nr_varying;
-
- const struct gl_client_array *dstarray_ptr[VERT_ATTRIB_MAX];
- struct _mesa_index_buffer dstib;
-
- GLuint *translated_elt_buf;
- const GLuint *srcelt;
-
- /** A baby hash table to avoid re-emitting (some) duplicate
- * vertices when splitting indexed primitives.
- */
- struct {
- GLuint in;
- GLuint out;
- } vert_cache[ELT_TABLE_SIZE];
-
- GLuint vertex_size;
- GLubyte *dstbuf;
- GLubyte *dstptr; /**< dstptr == dstbuf + dstelt_max * vertsize */
- GLuint dstbuf_size; /**< in vertices */
- GLuint dstbuf_nr; /**< count of emitted vertices, also the largest value
- * in dstelt. Our MaxIndex.
- */
-
- GLuint *dstelt;
- GLuint dstelt_nr;
- GLuint dstelt_size;
-
-#define MAX_PRIM 32
- struct _mesa_prim dstprim[MAX_PRIM];
- GLuint dstprim_nr;
-
-};
-
-
-static GLuint attr_size( const struct gl_client_array *array )
-{
- return array->Size * _mesa_sizeof_type(array->Type);
-}
-
-
-/**
- * Starts returning true slightly before the buffer fills, to ensure
- * that there is sufficient room for any remaining vertices to finish
- * off the prim:
- */
-static GLboolean
-check_flush( struct copy_context *copy )
-{
- GLenum mode = copy->dstprim[copy->dstprim_nr].mode;
-
- if (GL_TRIANGLE_STRIP == mode &&
- copy->dstelt_nr & 1) { /* see bug9962 */
- return GL_FALSE;
- }
-
- if (copy->dstbuf_nr + 4 > copy->dstbuf_size)
- return GL_TRUE;
-
- if (copy->dstelt_nr + 4 > copy->dstelt_size)
- return GL_TRUE;
-
- return GL_FALSE;
-}
-
-
-/**
- * Dump the parameters/info for a vbo->draw() call.
- */
-static void
-dump_draw_info(GLcontext *ctx,
- const struct gl_client_array **arrays,
- const struct _mesa_prim *prims,
- GLuint nr_prims,
- const struct _mesa_index_buffer *ib,
- GLuint min_index,
- GLuint max_index)
-{
- GLuint i, j;
-
- printf("VBO Draw:\n");
- for (i = 0; i < nr_prims; i++) {
- printf("Prim %u of %u\n", i, nr_prims);
- printf(" Prim mode 0x%x\n", prims[i].mode);
- printf(" IB: %p\n", (void*) ib);
- for (j = 0; j < VERT_ATTRIB_MAX; j++) {
- printf(" array %d at %p:\n", j, (void*) arrays[j]);
- printf(" enabled %d, ptr %p, size %d, type 0x%x, stride %d\n",
- arrays[j]->Enabled, arrays[j]->Ptr,
- arrays[j]->Size, arrays[j]->Type, arrays[j]->StrideB);
- if (0) {
- GLint k = prims[i].start + prims[i].count - 1;
- GLfloat *last = (GLfloat *) (arrays[j]->Ptr + arrays[j]->Stride * k);
- printf(" last: %f %f %f\n",
- last[0], last[1], last[2]);
- }
- }
- }
-}
-
-
-static void
-flush( struct copy_context *copy )
-{
- GLuint i;
-
- /* Set some counters:
- */
- copy->dstib.count = copy->dstelt_nr;
-
-#if 0
- dump_draw_info(copy->ctx,
- copy->dstarray_ptr,
- copy->dstprim,
- copy->dstprim_nr,
- &copy->dstib,
- 0,
- copy->dstbuf_nr);
-#else
- (void) dump_draw_info;
-#endif
-
- copy->draw( copy->ctx,
- copy->dstarray_ptr,
- copy->dstprim,
- copy->dstprim_nr,
- &copy->dstib,
- GL_TRUE,
- 0,
- copy->dstbuf_nr - 1 );
-
- /* Reset all pointers:
- */
- copy->dstprim_nr = 0;
- copy->dstelt_nr = 0;
- copy->dstbuf_nr = 0;
- copy->dstptr = copy->dstbuf;
-
- /* Clear the vertex cache:
- */
- for (i = 0; i < ELT_TABLE_SIZE; i++)
- copy->vert_cache[i].in = ~0;
-}
-
-
-/**
- * Called at begin of each primitive during replay.
- */
-static void
-begin( struct copy_context *copy, GLenum mode, GLboolean begin_flag )
-{
- struct _mesa_prim *prim = &copy->dstprim[copy->dstprim_nr];
-
- prim->mode = mode;
- prim->begin = begin_flag;
-}
-
-
-/**
- * Use a hashtable to attempt to identify recently-emitted vertices
- * and avoid re-emitting them.
- */
-static GLuint
-elt(struct copy_context *copy, GLuint elt_idx)
-{
- GLuint elt = copy->srcelt[elt_idx];
- GLuint slot = elt & (ELT_TABLE_SIZE-1);
-
-/* printf("elt %d\n", elt); */
-
- /* Look up the incoming element in the vertex cache. Re-emit if
- * necessary.
- */
- if (copy->vert_cache[slot].in != elt) {
- GLubyte *csr = copy->dstptr;
- GLuint i;
-
-/* printf(" --> emit to dstelt %d\n", copy->dstbuf_nr); */
-
- for (i = 0; i < copy->nr_varying; i++) {
- const struct gl_client_array *srcarray = copy->varying[i].array;
- const GLubyte *srcptr = copy->varying[i].src_ptr + elt * srcarray->StrideB;
-
- memcpy(csr, srcptr, copy->varying[i].size);
- csr += copy->varying[i].size;
-
-#ifdef NAN_CHECK
- if (srcarray->Type == GL_FLOAT) {
- GLuint k;
- GLfloat *f = (GLfloat *) srcptr;
- for (k = 0; k < srcarray->Size; k++) {
- assert(!IS_INF_OR_NAN(f[k]));
- assert(f[k] <= 1.0e20 && f[k] >= -1.0e20);
- }
- }
-#endif
-
- if (0)
- {
- const GLuint *f = (const GLuint *)srcptr;
- GLuint j;
- printf(" varying %d: ", i);
- for(j = 0; j < copy->varying[i].size / 4; j++)
- printf("%x ", f[j]);
- printf("\n");
- }
- }
-
- copy->vert_cache[slot].in = elt;
- copy->vert_cache[slot].out = copy->dstbuf_nr++;
- copy->dstptr += copy->vertex_size;
-
- assert(csr == copy->dstptr);
- assert(copy->dstptr == (copy->dstbuf +
- copy->dstbuf_nr * copy->vertex_size));
- }
-/* else */
-/* printf(" --> reuse vertex\n"); */
-
-/* printf(" --> emit %d\n", copy->vert_cache[slot].out); */
- copy->dstelt[copy->dstelt_nr++] = copy->vert_cache[slot].out;
- return check_flush(copy);
-}
-
-
-/**
- * Called at end of each primitive during replay.
- */
-static void
-end( struct copy_context *copy, GLboolean end_flag )
-{
- struct _mesa_prim *prim = &copy->dstprim[copy->dstprim_nr];
-
-/* printf("end (%d)\n", end_flag); */
-
- prim->end = end_flag;
- prim->count = copy->dstelt_nr - prim->start;
-
- if (++copy->dstprim_nr == MAX_PRIM ||
- check_flush(copy))
- flush(copy);
-}
-
-
-static void
-replay_elts( struct copy_context *copy )
-{
- GLuint i, j, k;
- GLboolean split;
-
- for (i = 0; i < copy->nr_prims; i++) {
- const struct _mesa_prim *prim = &copy->prim[i];
- const GLuint start = prim->start;
- GLuint first, incr;
-
- switch (prim->mode) {
-
- case GL_LINE_LOOP:
- /* Convert to linestrip and emit the final vertex explicitly,
- * but only in the resultant strip that requires it.
- */
- j = 0;
- while (j != prim->count) {
- begin(copy, GL_LINE_STRIP, prim->begin && j == 0);
-
- for (split = GL_FALSE; j != prim->count && !split; j++)
- split = elt(copy, start + j);
-
- if (j == prim->count) {
- /* Done, emit final line. Split doesn't matter as
- * it is always raised a bit early so we can emit
- * the last verts if necessary!
- */
- if (prim->end)
- (void)elt(copy, start + 0);
-
- end(copy, prim->end);
- }
- else {
- /* Wrap
- */
- assert(split);
- end(copy, 0);
- j--;
- }
- }
- break;
-
- case GL_TRIANGLE_FAN:
- case GL_POLYGON:
- j = 2;
- while (j != prim->count) {
- begin(copy, prim->mode, prim->begin && j == 0);
-
- split = elt(copy, start+0);
- assert(!split);
-
- split = elt(copy, start+j-1);
- assert(!split);
-
- for (; j != prim->count && !split; j++)
- split = elt(copy, start+j);
-
- end(copy, prim->end && j == prim->count);
-
- if (j != prim->count) {
- /* Wrapped the primitive, need to repeat some vertices:
- */
- j -= 1;
- }
- }
- break;
-
- default:
- (void)split_prim_inplace(prim->mode, &first, &incr);
-
- j = 0;
- while (j != prim->count) {
-
- begin(copy, prim->mode, prim->begin && j == 0);
-
- split = 0;
- for (k = 0; k < first; k++, j++)
- split |= elt(copy, start+j);
-
- assert(!split);
-
- for (; j != prim->count && !split; )
- for (k = 0; k < incr; k++, j++)
- split |= elt(copy, start+j);
-
- end(copy, prim->end && j == prim->count);
-
- if (j != prim->count) {
- /* Wrapped the primitive, need to repeat some vertices:
- */
- assert(j > first - incr);
- j -= (first - incr);
- }
- }
- break;
- }
- }
-
- if (copy->dstprim_nr)
- flush(copy);
-}
-
-
-static void
-replay_init( struct copy_context *copy )
-{
- GLcontext *ctx = copy->ctx;
- GLuint i;
- GLuint offset;
- const GLvoid *srcptr;
-
- /* Make a list of varying attributes and their vbo's. Also
- * calculate vertex size.
- */
- copy->vertex_size = 0;
- for (i = 0; i < VERT_ATTRIB_MAX; i++) {
- struct gl_buffer_object *vbo = copy->array[i]->BufferObj;
-
- if (copy->array[i]->StrideB == 0) {
- copy->dstarray_ptr[i] = copy->array[i];
- }
- else {
- GLuint j = copy->nr_varying++;
-
- copy->varying[j].attr = i;
- copy->varying[j].array = copy->array[i];
- copy->varying[j].size = attr_size(copy->array[i]);
- copy->vertex_size += attr_size(copy->array[i]);
-
- if (_mesa_is_bufferobj(vbo) && !_mesa_bufferobj_mapped(vbo))
- ctx->Driver.MapBuffer(ctx, GL_ARRAY_BUFFER, GL_READ_ONLY, vbo);
-
- copy->varying[j].src_ptr = ADD_POINTERS(vbo->Pointer,
- copy->array[i]->Ptr);
-
- copy->dstarray_ptr[i] = &copy->varying[j].dstarray;
- }
- }
-
- /* There must always be an index buffer. Currently require the
- * caller convert non-indexed prims to indexed. Could alternately
- * do it internally.
- */
- if (_mesa_is_bufferobj(copy->ib->obj) &&
- !_mesa_bufferobj_mapped(copy->ib->obj))
- ctx->Driver.MapBuffer(ctx, GL_ELEMENT_ARRAY_BUFFER, GL_READ_ONLY,
- copy->ib->obj);
-
- srcptr = (const GLubyte *) ADD_POINTERS(copy->ib->obj->Pointer,
- copy->ib->ptr);
-
- switch (copy->ib->type) {
- case GL_UNSIGNED_BYTE:
- copy->translated_elt_buf = malloc(sizeof(GLuint) * copy->ib->count);
- copy->srcelt = copy->translated_elt_buf;
-
- for (i = 0; i < copy->ib->count; i++)
- copy->translated_elt_buf[i] = ((const GLubyte *)srcptr)[i];
- break;
-
- case GL_UNSIGNED_SHORT:
- copy->translated_elt_buf = malloc(sizeof(GLuint) * copy->ib->count);
- copy->srcelt = copy->translated_elt_buf;
-
- for (i = 0; i < copy->ib->count; i++)
- copy->translated_elt_buf[i] = ((const GLushort *)srcptr)[i];
- break;
-
- case GL_UNSIGNED_INT:
- copy->translated_elt_buf = NULL;
- copy->srcelt = (const GLuint *)srcptr;
- break;
- }
-
- /* Figure out the maximum allowed vertex buffer size:
- */
- if (copy->vertex_size * copy->limits->max_verts <= copy->limits->max_vb_size) {
- copy->dstbuf_size = copy->limits->max_verts;
- }
- else {
- copy->dstbuf_size = copy->limits->max_vb_size / copy->vertex_size;
- }
-
- /* Allocate an output vertex buffer:
- *
- * XXX: This should be a VBO!
- */
- copy->dstbuf = malloc(copy->dstbuf_size * copy->vertex_size);
- copy->dstptr = copy->dstbuf;
-
- /* Setup new vertex arrays to point into the output buffer:
- */
- for (offset = 0, i = 0; i < copy->nr_varying; i++) {
- const struct gl_client_array *src = copy->varying[i].array;
- struct gl_client_array *dst = &copy->varying[i].dstarray;
-
- dst->Size = src->Size;
- dst->Type = src->Type;
- dst->Format = GL_RGBA;
- dst->Stride = copy->vertex_size;
- dst->StrideB = copy->vertex_size;
- dst->Ptr = copy->dstbuf + offset;
- dst->Enabled = GL_TRUE;
- dst->Normalized = src->Normalized;
- dst->BufferObj = ctx->Shared->NullBufferObj;
- dst->_MaxElement = copy->dstbuf_size; /* may be less! */
-
- offset += copy->varying[i].size;
- }
-
- /* Allocate an output element list:
- */
- copy->dstelt_size = MIN2(65536,
- copy->ib->count * 2 + 3);
- copy->dstelt_size = MIN2(copy->dstelt_size,
- copy->limits->max_indices);
- copy->dstelt = malloc(sizeof(GLuint) * copy->dstelt_size);
- copy->dstelt_nr = 0;
-
- /* Setup the new index buffer to point to the allocated element
- * list:
- */
- copy->dstib.count = 0; /* duplicates dstelt_nr */
- copy->dstib.type = GL_UNSIGNED_INT;
- copy->dstib.obj = ctx->Shared->NullBufferObj;
- copy->dstib.ptr = copy->dstelt;
-}
-
-
-/**
- * Free up everything allocated during split/replay.
- */
-static void
-replay_finish( struct copy_context *copy )
-{
- GLcontext *ctx = copy->ctx;
- GLuint i;
-
- /* Free our vertex and index buffers:
- */
- free(copy->translated_elt_buf);
- free(copy->dstbuf);
- free(copy->dstelt);
-
- /* Unmap VBO's
- */
- for (i = 0; i < copy->nr_varying; i++) {
- struct gl_buffer_object *vbo = copy->varying[i].array->BufferObj;
- if (_mesa_is_bufferobj(vbo) && _mesa_bufferobj_mapped(vbo))
- ctx->Driver.UnmapBuffer(ctx, GL_ARRAY_BUFFER, vbo);
- }
-
- /* Unmap index buffer:
- */
- if (_mesa_is_bufferobj(copy->ib->obj) &&
- _mesa_bufferobj_mapped(copy->ib->obj)) {
- ctx->Driver.UnmapBuffer(ctx, GL_ELEMENT_ARRAY_BUFFER, copy->ib->obj);
- }
-}
-
-
-/**
- * Split VBO into smaller pieces, draw the pieces.
- */
-void vbo_split_copy( GLcontext *ctx,
- const struct gl_client_array *arrays[],
- const struct _mesa_prim *prim,
- GLuint nr_prims,
- const struct _mesa_index_buffer *ib,
- vbo_draw_func draw,
- const struct split_limits *limits )
-{
- struct copy_context copy;
- GLuint i, this_nr_prims;
-
- for (i = 0; i < nr_prims;) {
- /* Our SW TNL pipeline doesn't handle basevertex yet, so bind_indices
- * will rebase the elements to the basevertex, and we'll only
- * emit strings of prims with the same basevertex in one draw call.
- */
- for (this_nr_prims = 1; i + this_nr_prims < nr_prims;
- this_nr_prims++) {
- if (prim[i].basevertex != prim[i + this_nr_prims].basevertex)
- break;
- }
-
- memset(&copy, 0, sizeof(copy));
-
- /* Require indexed primitives:
- */
- assert(ib);
-
- copy.ctx = ctx;
- copy.array = arrays;
- copy.prim = &prim[i];
- copy.nr_prims = this_nr_prims;
- copy.ib = ib;
- copy.draw = draw;
- copy.limits = limits;
-
- /* Clear the vertex cache:
- */
- for (i = 0; i < ELT_TABLE_SIZE; i++)
- copy.vert_cache[i].in = ~0;
-
- replay_init(&copy);
- replay_elts(&copy);
- replay_finish(&copy);
- }
-}
+
+/*
+ * Mesa 3-D graphics library
+ * Version: 6.5
+ *
+ * Copyright (C) 1999-2006 Brian Paul All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+ * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors:
+ * Keith Whitwell <keith@tungstengraphics.com>
+ */
+
+/* Split indexed primitives with per-vertex copying.
+ */
+
+#include "main/glheader.h"
+#include "main/bufferobj.h"
+#include "main/imports.h"
+#include "main/image.h"
+#include "main/macros.h"
+#include "main/mtypes.h"
+
+#include "vbo_split.h"
+#include "vbo.h"
+
+
+#define ELT_TABLE_SIZE 16
+
+/**
+ * Used for vertex-level splitting of indexed buffers. Note that
+ * non-indexed primitives may be converted to indexed in some cases
+ * (eg loops, fans) in order to use this splitting path.
+ */
+struct copy_context {
+
+ struct gl_context *ctx;
+ const struct gl_client_array **array;
+ const struct _mesa_prim *prim;
+ GLuint nr_prims;
+ const struct _mesa_index_buffer *ib;
+ vbo_draw_func draw;
+
+ const struct split_limits *limits;
+
+ struct {
+ GLuint attr;
+ GLuint size;
+ const struct gl_client_array *array;
+ const GLubyte *src_ptr;
+
+ struct gl_client_array dstarray;
+
+ } varying[VERT_ATTRIB_MAX];
+ GLuint nr_varying;
+
+ const struct gl_client_array *dstarray_ptr[VERT_ATTRIB_MAX];
+ struct _mesa_index_buffer dstib;
+
+ GLuint *translated_elt_buf;
+ const GLuint *srcelt;
+
+ /** A baby hash table to avoid re-emitting (some) duplicate
+ * vertices when splitting indexed primitives.
+ */
+ struct {
+ GLuint in;
+ GLuint out;
+ } vert_cache[ELT_TABLE_SIZE];
+
+ GLuint vertex_size;
+ GLubyte *dstbuf;
+ GLubyte *dstptr; /**< dstptr == dstbuf + dstelt_max * vertsize */
+ GLuint dstbuf_size; /**< in vertices */
+ GLuint dstbuf_nr; /**< count of emitted vertices, also the largest value
+ * in dstelt. Our MaxIndex.
+ */
+
+ GLuint *dstelt;
+ GLuint dstelt_nr;
+ GLuint dstelt_size;
+
+#define MAX_PRIM 32
+ struct _mesa_prim dstprim[MAX_PRIM];
+ GLuint dstprim_nr;
+
+};
+
+
+static GLuint attr_size( const struct gl_client_array *array )
+{
+ return array->Size * _mesa_sizeof_type(array->Type);
+}
+
+
+/**
+ * Starts returning true slightly before the buffer fills, to ensure
+ * that there is sufficient room for any remaining vertices to finish
+ * off the prim:
+ */
+static GLboolean
+check_flush( struct copy_context *copy )
+{
+ GLenum mode = copy->dstprim[copy->dstprim_nr].mode;
+
+ if (GL_TRIANGLE_STRIP == mode &&
+ copy->dstelt_nr & 1) { /* see bug9962 */
+ return GL_FALSE;
+ }
+
+ if (copy->dstbuf_nr + 4 > copy->dstbuf_size)
+ return GL_TRUE;
+
+ if (copy->dstelt_nr + 4 > copy->dstelt_size)
+ return GL_TRUE;
+
+ return GL_FALSE;
+}
+
+
+/**
+ * Dump the parameters/info for a vbo->draw() call.
+ */
+static void
+dump_draw_info(struct gl_context *ctx,
+ const struct gl_client_array **arrays,
+ const struct _mesa_prim *prims,
+ GLuint nr_prims,
+ const struct _mesa_index_buffer *ib,
+ GLuint min_index,
+ GLuint max_index)
+{
+ GLuint i, j;
+
+ printf("VBO Draw:\n");
+ for (i = 0; i < nr_prims; i++) {
+ printf("Prim %u of %u\n", i, nr_prims);
+ printf(" Prim mode 0x%x\n", prims[i].mode);
+ printf(" IB: %p\n", (void*) ib);
+ for (j = 0; j < VERT_ATTRIB_MAX; j++) {
+ printf(" array %d at %p:\n", j, (void*) arrays[j]);
+ printf(" enabled %d, ptr %p, size %d, type 0x%x, stride %d\n",
+ arrays[j]->Enabled, arrays[j]->Ptr,
+ arrays[j]->Size, arrays[j]->Type, arrays[j]->StrideB);
+ if (0) {
+ GLint k = prims[i].start + prims[i].count - 1;
+ GLfloat *last = (GLfloat *) (arrays[j]->Ptr + arrays[j]->Stride * k);
+ printf(" last: %f %f %f\n",
+ last[0], last[1], last[2]);
+ }
+ }
+ }
+}
+
+
+static void
+flush( struct copy_context *copy )
+{
+ GLuint i;
+
+ /* Set some counters:
+ */
+ copy->dstib.count = copy->dstelt_nr;
+
+#if 0
+ dump_draw_info(copy->ctx,
+ copy->dstarray_ptr,
+ copy->dstprim,
+ copy->dstprim_nr,
+ &copy->dstib,
+ 0,
+ copy->dstbuf_nr);
+#else
+ (void) dump_draw_info;
+#endif
+
+ copy->draw( copy->ctx,
+ copy->dstarray_ptr,
+ copy->dstprim,
+ copy->dstprim_nr,
+ &copy->dstib,
+ GL_TRUE,
+ 0,
+ copy->dstbuf_nr - 1 );
+
+ /* Reset all pointers:
+ */
+ copy->dstprim_nr = 0;
+ copy->dstelt_nr = 0;
+ copy->dstbuf_nr = 0;
+ copy->dstptr = copy->dstbuf;
+
+ /* Clear the vertex cache:
+ */
+ for (i = 0; i < ELT_TABLE_SIZE; i++)
+ copy->vert_cache[i].in = ~0;
+}
+
+
+/**
+ * Called at begin of each primitive during replay.
+ */
+static void
+begin( struct copy_context *copy, GLenum mode, GLboolean begin_flag )
+{
+ struct _mesa_prim *prim = &copy->dstprim[copy->dstprim_nr];
+
+ prim->mode = mode;
+ prim->begin = begin_flag;
+}
+
+
+/**
+ * Use a hashtable to attempt to identify recently-emitted vertices
+ * and avoid re-emitting them.
+ */
+static GLuint
+elt(struct copy_context *copy, GLuint elt_idx)
+{
+ GLuint elt = copy->srcelt[elt_idx];
+ GLuint slot = elt & (ELT_TABLE_SIZE-1);
+
+/* printf("elt %d\n", elt); */
+
+ /* Look up the incoming element in the vertex cache. Re-emit if
+ * necessary.
+ */
+ if (copy->vert_cache[slot].in != elt) {
+ GLubyte *csr = copy->dstptr;
+ GLuint i;
+
+/* printf(" --> emit to dstelt %d\n", copy->dstbuf_nr); */
+
+ for (i = 0; i < copy->nr_varying; i++) {
+ const struct gl_client_array *srcarray = copy->varying[i].array;
+ const GLubyte *srcptr = copy->varying[i].src_ptr + elt * srcarray->StrideB;
+
+ memcpy(csr, srcptr, copy->varying[i].size);
+ csr += copy->varying[i].size;
+
+#ifdef NAN_CHECK
+ if (srcarray->Type == GL_FLOAT) {
+ GLuint k;
+ GLfloat *f = (GLfloat *) srcptr;
+ for (k = 0; k < srcarray->Size; k++) {
+ assert(!IS_INF_OR_NAN(f[k]));
+ assert(f[k] <= 1.0e20 && f[k] >= -1.0e20);
+ }
+ }
+#endif
+
+ if (0)
+ {
+ const GLuint *f = (const GLuint *)srcptr;
+ GLuint j;
+ printf(" varying %d: ", i);
+ for(j = 0; j < copy->varying[i].size / 4; j++)
+ printf("%x ", f[j]);
+ printf("\n");
+ }
+ }
+
+ copy->vert_cache[slot].in = elt;
+ copy->vert_cache[slot].out = copy->dstbuf_nr++;
+ copy->dstptr += copy->vertex_size;
+
+ assert(csr == copy->dstptr);
+ assert(copy->dstptr == (copy->dstbuf +
+ copy->dstbuf_nr * copy->vertex_size));
+ }
+/* else */
+/* printf(" --> reuse vertex\n"); */
+
+/* printf(" --> emit %d\n", copy->vert_cache[slot].out); */
+ copy->dstelt[copy->dstelt_nr++] = copy->vert_cache[slot].out;
+ return check_flush(copy);
+}
+
+
+/**
+ * Called at end of each primitive during replay.
+ */
+static void
+end( struct copy_context *copy, GLboolean end_flag )
+{
+ struct _mesa_prim *prim = &copy->dstprim[copy->dstprim_nr];
+
+/* printf("end (%d)\n", end_flag); */
+
+ prim->end = end_flag;
+ prim->count = copy->dstelt_nr - prim->start;
+
+ if (++copy->dstprim_nr == MAX_PRIM ||
+ check_flush(copy))
+ flush(copy);
+}
+
+
+static void
+replay_elts( struct copy_context *copy )
+{
+ GLuint i, j, k;
+ GLboolean split;
+
+ for (i = 0; i < copy->nr_prims; i++) {
+ const struct _mesa_prim *prim = &copy->prim[i];
+ const GLuint start = prim->start;
+ GLuint first, incr;
+
+ switch (prim->mode) {
+
+ case GL_LINE_LOOP:
+ /* Convert to linestrip and emit the final vertex explicitly,
+ * but only in the resultant strip that requires it.
+ */
+ j = 0;
+ while (j != prim->count) {
+ begin(copy, GL_LINE_STRIP, prim->begin && j == 0);
+
+ for (split = GL_FALSE; j != prim->count && !split; j++)
+ split = elt(copy, start + j);
+
+ if (j == prim->count) {
+ /* Done, emit final line. Split doesn't matter as
+ * it is always raised a bit early so we can emit
+ * the last verts if necessary!
+ */
+ if (prim->end)
+ (void)elt(copy, start + 0);
+
+ end(copy, prim->end);
+ }
+ else {
+ /* Wrap
+ */
+ assert(split);
+ end(copy, 0);
+ j--;
+ }
+ }
+ break;
+
+ case GL_TRIANGLE_FAN:
+ case GL_POLYGON:
+ j = 2;
+ while (j != prim->count) {
+ begin(copy, prim->mode, prim->begin && j == 0);
+
+ split = elt(copy, start+0);
+ assert(!split);
+
+ split = elt(copy, start+j-1);
+ assert(!split);
+
+ for (; j != prim->count && !split; j++)
+ split = elt(copy, start+j);
+
+ end(copy, prim->end && j == prim->count);
+
+ if (j != prim->count) {
+ /* Wrapped the primitive, need to repeat some vertices:
+ */
+ j -= 1;
+ }
+ }
+ break;
+
+ default:
+ (void)split_prim_inplace(prim->mode, &first, &incr);
+
+ j = 0;
+ while (j != prim->count) {
+
+ begin(copy, prim->mode, prim->begin && j == 0);
+
+ split = 0;
+ for (k = 0; k < first; k++, j++)
+ split |= elt(copy, start+j);
+
+ assert(!split);
+
+ for (; j != prim->count && !split; )
+ for (k = 0; k < incr; k++, j++)
+ split |= elt(copy, start+j);
+
+ end(copy, prim->end && j == prim->count);
+
+ if (j != prim->count) {
+ /* Wrapped the primitive, need to repeat some vertices:
+ */
+ assert(j > first - incr);
+ j -= (first - incr);
+ }
+ }
+ break;
+ }
+ }
+
+ if (copy->dstprim_nr)
+ flush(copy);
+}
+
+
+static void
+replay_init( struct copy_context *copy )
+{
+ struct gl_context *ctx = copy->ctx;
+ GLuint i;
+ GLuint offset;
+ const GLvoid *srcptr;
+
+ /* Make a list of varying attributes and their vbo's. Also
+ * calculate vertex size.
+ */
+ copy->vertex_size = 0;
+ for (i = 0; i < VERT_ATTRIB_MAX; i++) {
+ struct gl_buffer_object *vbo = copy->array[i]->BufferObj;
+
+ if (copy->array[i]->StrideB == 0) {
+ copy->dstarray_ptr[i] = copy->array[i];
+ }
+ else {
+ GLuint j = copy->nr_varying++;
+
+ copy->varying[j].attr = i;
+ copy->varying[j].array = copy->array[i];
+ copy->varying[j].size = attr_size(copy->array[i]);
+ copy->vertex_size += attr_size(copy->array[i]);
+
+ if (_mesa_is_bufferobj(vbo) && !_mesa_bufferobj_mapped(vbo))
+ ctx->Driver.MapBuffer(ctx, GL_ARRAY_BUFFER, GL_READ_ONLY, vbo);
+
+ copy->varying[j].src_ptr = ADD_POINTERS(vbo->Pointer,
+ copy->array[i]->Ptr);
+
+ copy->dstarray_ptr[i] = &copy->varying[j].dstarray;
+ }
+ }
+
+ /* There must always be an index buffer. Currently require the
+ * caller convert non-indexed prims to indexed. Could alternately
+ * do it internally.
+ */
+ if (_mesa_is_bufferobj(copy->ib->obj) &&
+ !_mesa_bufferobj_mapped(copy->ib->obj))
+ ctx->Driver.MapBuffer(ctx, GL_ELEMENT_ARRAY_BUFFER, GL_READ_ONLY,
+ copy->ib->obj);
+
+ srcptr = (const GLubyte *) ADD_POINTERS(copy->ib->obj->Pointer,
+ copy->ib->ptr);
+
+ switch (copy->ib->type) {
+ case GL_UNSIGNED_BYTE:
+ copy->translated_elt_buf = malloc(sizeof(GLuint) * copy->ib->count);
+ copy->srcelt = copy->translated_elt_buf;
+
+ for (i = 0; i < copy->ib->count; i++)
+ copy->translated_elt_buf[i] = ((const GLubyte *)srcptr)[i];
+ break;
+
+ case GL_UNSIGNED_SHORT:
+ copy->translated_elt_buf = malloc(sizeof(GLuint) * copy->ib->count);
+ copy->srcelt = copy->translated_elt_buf;
+
+ for (i = 0; i < copy->ib->count; i++)
+ copy->translated_elt_buf[i] = ((const GLushort *)srcptr)[i];
+ break;
+
+ case GL_UNSIGNED_INT:
+ copy->translated_elt_buf = NULL;
+ copy->srcelt = (const GLuint *)srcptr;
+ break;
+ }
+
+ /* Figure out the maximum allowed vertex buffer size:
+ */
+ if (copy->vertex_size * copy->limits->max_verts <= copy->limits->max_vb_size) {
+ copy->dstbuf_size = copy->limits->max_verts;
+ }
+ else {
+ copy->dstbuf_size = copy->limits->max_vb_size / copy->vertex_size;
+ }
+
+ /* Allocate an output vertex buffer:
+ *
+ * XXX: This should be a VBO!
+ */
+ copy->dstbuf = malloc(copy->dstbuf_size * copy->vertex_size);
+ copy->dstptr = copy->dstbuf;
+
+ /* Setup new vertex arrays to point into the output buffer:
+ */
+ for (offset = 0, i = 0; i < copy->nr_varying; i++) {
+ const struct gl_client_array *src = copy->varying[i].array;
+ struct gl_client_array *dst = &copy->varying[i].dstarray;
+
+ dst->Size = src->Size;
+ dst->Type = src->Type;
+ dst->Format = GL_RGBA;
+ dst->Stride = copy->vertex_size;
+ dst->StrideB = copy->vertex_size;
+ dst->Ptr = copy->dstbuf + offset;
+ dst->Enabled = GL_TRUE;
+ dst->Normalized = src->Normalized;
+ dst->BufferObj = ctx->Shared->NullBufferObj;
+ dst->_MaxElement = copy->dstbuf_size; /* may be less! */
+
+ offset += copy->varying[i].size;
+ }
+
+ /* Allocate an output element list:
+ */
+ copy->dstelt_size = MIN2(65536,
+ copy->ib->count * 2 + 3);
+ copy->dstelt_size = MIN2(copy->dstelt_size,
+ copy->limits->max_indices);
+ copy->dstelt = malloc(sizeof(GLuint) * copy->dstelt_size);
+ copy->dstelt_nr = 0;
+
+ /* Setup the new index buffer to point to the allocated element
+ * list:
+ */
+ copy->dstib.count = 0; /* duplicates dstelt_nr */
+ copy->dstib.type = GL_UNSIGNED_INT;
+ copy->dstib.obj = ctx->Shared->NullBufferObj;
+ copy->dstib.ptr = copy->dstelt;
+}
+
+
+/**
+ * Free up everything allocated during split/replay.
+ */
+static void
+replay_finish( struct copy_context *copy )
+{
+ struct gl_context *ctx = copy->ctx;
+ GLuint i;
+
+ /* Free our vertex and index buffers:
+ */
+ free(copy->translated_elt_buf);
+ free(copy->dstbuf);
+ free(copy->dstelt);
+
+ /* Unmap VBO's
+ */
+ for (i = 0; i < copy->nr_varying; i++) {
+ struct gl_buffer_object *vbo = copy->varying[i].array->BufferObj;
+ if (_mesa_is_bufferobj(vbo) && _mesa_bufferobj_mapped(vbo))
+ ctx->Driver.UnmapBuffer(ctx, GL_ARRAY_BUFFER, vbo);
+ }
+
+ /* Unmap index buffer:
+ */
+ if (_mesa_is_bufferobj(copy->ib->obj) &&
+ _mesa_bufferobj_mapped(copy->ib->obj)) {
+ ctx->Driver.UnmapBuffer(ctx, GL_ELEMENT_ARRAY_BUFFER, copy->ib->obj);
+ }
+}
+
+
+/**
+ * Split VBO into smaller pieces, draw the pieces.
+ */
+void vbo_split_copy( struct gl_context *ctx,
+ const struct gl_client_array *arrays[],
+ const struct _mesa_prim *prim,
+ GLuint nr_prims,
+ const struct _mesa_index_buffer *ib,
+ vbo_draw_func draw,
+ const struct split_limits *limits )
+{
+ struct copy_context copy;
+ GLuint i, this_nr_prims;
+
+ for (i = 0; i < nr_prims;) {
+ /* Our SW TNL pipeline doesn't handle basevertex yet, so bind_indices
+ * will rebase the elements to the basevertex, and we'll only
+ * emit strings of prims with the same basevertex in one draw call.
+ */
+ for (this_nr_prims = 1; i + this_nr_prims < nr_prims;
+ this_nr_prims++) {
+ if (prim[i].basevertex != prim[i + this_nr_prims].basevertex)
+ break;
+ }
+
+ memset(&copy, 0, sizeof(copy));
+
+ /* Require indexed primitives:
+ */
+ assert(ib);
+
+ copy.ctx = ctx;
+ copy.array = arrays;
+ copy.prim = &prim[i];
+ copy.nr_prims = this_nr_prims;
+ copy.ib = ib;
+ copy.draw = draw;
+ copy.limits = limits;
+
+ /* Clear the vertex cache:
+ */
+ for (i = 0; i < ELT_TABLE_SIZE; i++)
+ copy.vert_cache[i].in = ~0;
+
+ replay_init(&copy);
+ replay_elts(&copy);
+ replay_finish(&copy);
+ }
+}
diff --git a/mesalib/src/mesa/vbo/vbo_split_inplace.c b/mesalib/src/mesa/vbo/vbo_split_inplace.c
index 2fc866c57..98c32eda5 100644
--- a/mesalib/src/mesa/vbo/vbo_split_inplace.c
+++ b/mesalib/src/mesa/vbo/vbo_split_inplace.c
@@ -1,283 +1,283 @@
-
-/*
- * Mesa 3-D graphics library
- * Version: 6.5
- *
- * Copyright (C) 1999-2006 Brian Paul All Rights Reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included
- * in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
- * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- *
- * Authors:
- * Keith Whitwell <keith@tungstengraphics.com>
- */
-
-
-#include "main/mtypes.h"
-#include "main/macros.h"
-#include "main/enums.h"
-#include "main/image.h"
-#include "vbo_split.h"
-
-
-#define MAX_PRIM 32
-
-/* Used for splitting without copying. No attempt is made to handle
- * too large indexed vertex buffers: In general you need to copy to do
- * that.
- */
-struct split_context {
- GLcontext *ctx;
- const struct gl_client_array **array;
- const struct _mesa_prim *prim;
- GLuint nr_prims;
- const struct _mesa_index_buffer *ib;
- GLuint min_index;
- GLuint max_index;
- vbo_draw_func draw;
-
- const struct split_limits *limits;
- GLuint limit;
-
- struct _mesa_prim dstprim[MAX_PRIM];
- GLuint dstprim_nr;
-};
-
-
-
-
-static void flush_vertex( struct split_context *split )
-{
- struct _mesa_index_buffer ib;
- GLuint i;
-
- if (!split->dstprim_nr)
- return;
-
- if (split->ib) {
- ib = *split->ib;
-
- ib.count = split->max_index - split->min_index + 1;
- ib.ptr = (const void *)((const char *)ib.ptr +
- split->min_index * _mesa_sizeof_type(ib.type));
-
- /* Rebase the primitives to save index buffer entries. */
- for (i = 0; i < split->dstprim_nr; i++)
- split->dstprim[i].start -= split->min_index;
- }
-
- assert(split->max_index >= split->min_index);
-
- split->draw(split->ctx,
- split->array,
- split->dstprim,
- split->dstprim_nr,
- split->ib ? &ib : NULL,
- !split->ib,
- split->min_index,
- split->max_index);
-
- split->dstprim_nr = 0;
- split->min_index = ~0;
- split->max_index = 0;
-}
-
-
-static struct _mesa_prim *next_outprim( struct split_context *split )
-{
- if (split->dstprim_nr == MAX_PRIM-1) {
- flush_vertex(split);
- }
-
- {
- struct _mesa_prim *prim = &split->dstprim[split->dstprim_nr++];
- memset(prim, 0, sizeof(*prim));
- return prim;
- }
-}
-
-static void update_index_bounds(struct split_context *split,
- const struct _mesa_prim *prim)
-{
- split->min_index = MIN2(split->min_index, prim->start);
- split->max_index = MAX2(split->max_index, prim->start + prim->count - 1);
-}
-
-/* Return the maximum amount of vertices that can be emitted for a
- * primitive starting at 'prim->start', depending on the previous
- * index bounds.
- */
-static GLuint get_max_vertices(struct split_context *split,
- const struct _mesa_prim *prim)
-{
- if ((prim->start > split->min_index &&
- prim->start - split->min_index >= split->limit) ||
- (prim->start < split->max_index &&
- split->max_index - prim->start >= split->limit))
- /* "prim" starts too far away from the old range. */
- return 0;
-
- return MIN2(split->min_index, prim->start) + split->limit - prim->start;
-}
-
-/* Break large primitives into smaller ones. If not possible, convert
- * the primitive to indexed and pass to split_elts().
- */
-static void split_prims( struct split_context *split)
-{
- GLuint i;
-
- for (i = 0; i < split->nr_prims; i++) {
- const struct _mesa_prim *prim = &split->prim[i];
- GLuint first, incr;
- GLboolean split_inplace = split_prim_inplace(prim->mode, &first, &incr);
- GLuint available = get_max_vertices(split, prim);
- GLuint count = prim->count - (prim->count - first) % incr;
-
- if (prim->count < first)
- continue;
-
- if ((available < count && !split_inplace) ||
- (available < first && split_inplace)) {
- flush_vertex(split);
- available = get_max_vertices(split, prim);
- }
-
- if (available >= count) {
- struct _mesa_prim *outprim = next_outprim(split);
-
- *outprim = *prim;
- update_index_bounds(split, outprim);
- }
- else if (split_inplace) {
- GLuint j, nr;
-
- for (j = 0 ; j < count ; ) {
- GLuint remaining = count - j;
- struct _mesa_prim *outprim = next_outprim(split);
-
- nr = MIN2( available, remaining );
- nr -= (nr - first) % incr;
-
- outprim->mode = prim->mode;
- outprim->begin = (j == 0 && prim->begin);
- outprim->end = (nr == remaining && prim->end);
- outprim->start = prim->start + j;
- outprim->count = nr;
-
- update_index_bounds(split, outprim);
-
- if (nr == remaining) {
- /* Finished.
- */
- j += nr;
- }
- else {
- /* Wrapped the primitive:
- */
- j += nr - (first - incr);
- flush_vertex(split);
- available = get_max_vertices(split, prim);
- }
- }
- }
- else if (split->ib == NULL) {
- /* XXX: could at least send the first max_verts off from the
- * inplace buffers.
- */
-
- /* else convert to indexed primitive and pass to split_elts,
- * which will do the necessary copying and turn it back into a
- * vertex primitive for rendering...
- */
- struct _mesa_index_buffer ib;
- struct _mesa_prim tmpprim;
- GLuint *elts = malloc(count * sizeof(GLuint));
- GLuint j;
-
- for (j = 0; j < count; j++)
- elts[j] = prim->start + j;
-
- ib.count = count;
- ib.type = GL_UNSIGNED_INT;
- ib.obj = split->ctx->Shared->NullBufferObj;
- ib.ptr = elts;
-
- tmpprim = *prim;
- tmpprim.indexed = 1;
- tmpprim.start = 0;
- tmpprim.count = count;
-
- flush_vertex(split);
-
- vbo_split_copy(split->ctx,
- split->array,
- &tmpprim, 1,
- &ib,
- split->draw,
- split->limits);
-
- free(elts);
- }
- else {
- flush_vertex(split);
-
- vbo_split_copy(split->ctx,
- split->array,
- prim, 1,
- split->ib,
- split->draw,
- split->limits);
- }
- }
-
- flush_vertex(split);
-}
-
-
-void vbo_split_inplace( GLcontext *ctx,
- const struct gl_client_array *arrays[],
- const struct _mesa_prim *prim,
- GLuint nr_prims,
- const struct _mesa_index_buffer *ib,
- GLuint min_index,
- GLuint max_index,
- vbo_draw_func draw,
- const struct split_limits *limits )
-{
- struct split_context split;
-
- memset(&split, 0, sizeof(split));
-
- split.ctx = ctx;
- split.array = arrays;
- split.prim = prim;
- split.nr_prims = nr_prims;
- split.ib = ib;
-
- /* Empty interval, makes calculations simpler. */
- split.min_index = ~0;
- split.max_index = 0;
-
- split.draw = draw;
- split.limits = limits;
- split.limit = ib ? limits->max_indices : limits->max_verts;
-
- split_prims( &split );
-}
-
-
+
+/*
+ * Mesa 3-D graphics library
+ * Version: 6.5
+ *
+ * Copyright (C) 1999-2006 Brian Paul All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+ * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors:
+ * Keith Whitwell <keith@tungstengraphics.com>
+ */
+
+
+#include "main/mtypes.h"
+#include "main/macros.h"
+#include "main/enums.h"
+#include "main/image.h"
+#include "vbo_split.h"
+
+
+#define MAX_PRIM 32
+
+/* Used for splitting without copying. No attempt is made to handle
+ * too large indexed vertex buffers: In general you need to copy to do
+ * that.
+ */
+struct split_context {
+ struct gl_context *ctx;
+ const struct gl_client_array **array;
+ const struct _mesa_prim *prim;
+ GLuint nr_prims;
+ const struct _mesa_index_buffer *ib;
+ GLuint min_index;
+ GLuint max_index;
+ vbo_draw_func draw;
+
+ const struct split_limits *limits;
+ GLuint limit;
+
+ struct _mesa_prim dstprim[MAX_PRIM];
+ GLuint dstprim_nr;
+};
+
+
+
+
+static void flush_vertex( struct split_context *split )
+{
+ struct _mesa_index_buffer ib;
+ GLuint i;
+
+ if (!split->dstprim_nr)
+ return;
+
+ if (split->ib) {
+ ib = *split->ib;
+
+ ib.count = split->max_index - split->min_index + 1;
+ ib.ptr = (const void *)((const char *)ib.ptr +
+ split->min_index * _mesa_sizeof_type(ib.type));
+
+ /* Rebase the primitives to save index buffer entries. */
+ for (i = 0; i < split->dstprim_nr; i++)
+ split->dstprim[i].start -= split->min_index;
+ }
+
+ assert(split->max_index >= split->min_index);
+
+ split->draw(split->ctx,
+ split->array,
+ split->dstprim,
+ split->dstprim_nr,
+ split->ib ? &ib : NULL,
+ !split->ib,
+ split->min_index,
+ split->max_index);
+
+ split->dstprim_nr = 0;
+ split->min_index = ~0;
+ split->max_index = 0;
+}
+
+
+static struct _mesa_prim *next_outprim( struct split_context *split )
+{
+ if (split->dstprim_nr == MAX_PRIM-1) {
+ flush_vertex(split);
+ }
+
+ {
+ struct _mesa_prim *prim = &split->dstprim[split->dstprim_nr++];
+ memset(prim, 0, sizeof(*prim));
+ return prim;
+ }
+}
+
+static void update_index_bounds(struct split_context *split,
+ const struct _mesa_prim *prim)
+{
+ split->min_index = MIN2(split->min_index, prim->start);
+ split->max_index = MAX2(split->max_index, prim->start + prim->count - 1);
+}
+
+/* Return the maximum amount of vertices that can be emitted for a
+ * primitive starting at 'prim->start', depending on the previous
+ * index bounds.
+ */
+static GLuint get_max_vertices(struct split_context *split,
+ const struct _mesa_prim *prim)
+{
+ if ((prim->start > split->min_index &&
+ prim->start - split->min_index >= split->limit) ||
+ (prim->start < split->max_index &&
+ split->max_index - prim->start >= split->limit))
+ /* "prim" starts too far away from the old range. */
+ return 0;
+
+ return MIN2(split->min_index, prim->start) + split->limit - prim->start;
+}
+
+/* Break large primitives into smaller ones. If not possible, convert
+ * the primitive to indexed and pass to split_elts().
+ */
+static void split_prims( struct split_context *split)
+{
+ GLuint i;
+
+ for (i = 0; i < split->nr_prims; i++) {
+ const struct _mesa_prim *prim = &split->prim[i];
+ GLuint first, incr;
+ GLboolean split_inplace = split_prim_inplace(prim->mode, &first, &incr);
+ GLuint available = get_max_vertices(split, prim);
+ GLuint count = prim->count - (prim->count - first) % incr;
+
+ if (prim->count < first)
+ continue;
+
+ if ((available < count && !split_inplace) ||
+ (available < first && split_inplace)) {
+ flush_vertex(split);
+ available = get_max_vertices(split, prim);
+ }
+
+ if (available >= count) {
+ struct _mesa_prim *outprim = next_outprim(split);
+
+ *outprim = *prim;
+ update_index_bounds(split, outprim);
+ }
+ else if (split_inplace) {
+ GLuint j, nr;
+
+ for (j = 0 ; j < count ; ) {
+ GLuint remaining = count - j;
+ struct _mesa_prim *outprim = next_outprim(split);
+
+ nr = MIN2( available, remaining );
+ nr -= (nr - first) % incr;
+
+ outprim->mode = prim->mode;
+ outprim->begin = (j == 0 && prim->begin);
+ outprim->end = (nr == remaining && prim->end);
+ outprim->start = prim->start + j;
+ outprim->count = nr;
+
+ update_index_bounds(split, outprim);
+
+ if (nr == remaining) {
+ /* Finished.
+ */
+ j += nr;
+ }
+ else {
+ /* Wrapped the primitive:
+ */
+ j += nr - (first - incr);
+ flush_vertex(split);
+ available = get_max_vertices(split, prim);
+ }
+ }
+ }
+ else if (split->ib == NULL) {
+ /* XXX: could at least send the first max_verts off from the
+ * inplace buffers.
+ */
+
+ /* else convert to indexed primitive and pass to split_elts,
+ * which will do the necessary copying and turn it back into a
+ * vertex primitive for rendering...
+ */
+ struct _mesa_index_buffer ib;
+ struct _mesa_prim tmpprim;
+ GLuint *elts = malloc(count * sizeof(GLuint));
+ GLuint j;
+
+ for (j = 0; j < count; j++)
+ elts[j] = prim->start + j;
+
+ ib.count = count;
+ ib.type = GL_UNSIGNED_INT;
+ ib.obj = split->ctx->Shared->NullBufferObj;
+ ib.ptr = elts;
+
+ tmpprim = *prim;
+ tmpprim.indexed = 1;
+ tmpprim.start = 0;
+ tmpprim.count = count;
+
+ flush_vertex(split);
+
+ vbo_split_copy(split->ctx,
+ split->array,
+ &tmpprim, 1,
+ &ib,
+ split->draw,
+ split->limits);
+
+ free(elts);
+ }
+ else {
+ flush_vertex(split);
+
+ vbo_split_copy(split->ctx,
+ split->array,
+ prim, 1,
+ split->ib,
+ split->draw,
+ split->limits);
+ }
+ }
+
+ flush_vertex(split);
+}
+
+
+void vbo_split_inplace( struct gl_context *ctx,
+ const struct gl_client_array *arrays[],
+ const struct _mesa_prim *prim,
+ GLuint nr_prims,
+ const struct _mesa_index_buffer *ib,
+ GLuint min_index,
+ GLuint max_index,
+ vbo_draw_func draw,
+ const struct split_limits *limits )
+{
+ struct split_context split;
+
+ memset(&split, 0, sizeof(split));
+
+ split.ctx = ctx;
+ split.array = arrays;
+ split.prim = prim;
+ split.nr_prims = nr_prims;
+ split.ib = ib;
+
+ /* Empty interval, makes calculations simpler. */
+ split.min_index = ~0;
+ split.max_index = 0;
+
+ split.draw = draw;
+ split.limits = limits;
+ split.limit = ib ? limits->max_indices : limits->max_verts;
+
+ split_prims( &split );
+}
+
+