Mesa (9.0): vbo: fix glVertexAttribI* functions

Marek Olšák mareko at kemper.freedesktop.org
Fri Nov 23 01:01:35 UTC 2012


Module: Mesa
Branch: 9.0
Commit: 492b69f3be3e355064c67bc6f4a30d40e997ce9d
URL:    http://cgit.freedesktop.org/mesa/mesa/commit/?id=492b69f3be3e355064c67bc6f4a30d40e997ce9d

Author: Marek Olšák <maraeo at gmail.com>
Date:   Tue Oct 30 14:44:22 2012 +0100

vbo: fix glVertexAttribI* functions

The functions were broken, because they converted ints to floats.
Now we can finally advertise OpenGL 3.0. ;)

In this commit, the vbo module also tracks the type for each attrib
in addition to the size. It can be one of FLOAT, INT, UNSIGNED_INT.

The little ugliness is the vertex attribs are declared as floats even though
there may be integer values. The code just copies integer values into them
without any conversion.

This implementation passes the glVertexAttribI piglit test which I am going
to commit in piglit soon. The test covers vertex arrays, immediate mode and
display lists.

NOTE: This is a candidate for the stable branches.

Reviewed-by: Brian Paul <brianp at vmware.com>

v2: cosmetic changes as suggested by Brian
(cherry picked from commit acf438f5375e2426386694e541b843dc6f8fd11a)

---

 docs/GL3.txt                  |    3 +-
 src/mesa/main/imports.h       |    2 +-
 src/mesa/main/macros.h        |   39 ++++++++++++++++++
 src/mesa/vbo/vbo_attrib_tmp.h |   86 ++++++++++++++++++++++------------------
 src/mesa/vbo/vbo_context.h    |   43 ++++++++++++++++++++
 src/mesa/vbo/vbo_exec.h       |    1 +
 src/mesa/vbo/vbo_exec_api.c   |   29 +++++++++----
 src/mesa/vbo/vbo_exec_draw.c  |    7 +--
 src/mesa/vbo/vbo_save.h       |    2 +
 src/mesa/vbo/vbo_save_api.c   |   12 ++++--
 src/mesa/vbo/vbo_save_draw.c  |   21 +++++++---
 11 files changed, 180 insertions(+), 65 deletions(-)

diff --git a/docs/GL3.txt b/docs/GL3.txt
index 24b70a1..9035779 100644
--- a/docs/GL3.txt
+++ b/docs/GL3.txt
@@ -34,8 +34,7 @@ sRGB framebuffer format (GL_EXT_framebuffer_sRGB)     DONE (i965, r600)
 glClearBuffer commands                                DONE
 glGetStringi command                                  DONE
 glTexParameterI, glGetTexParameterI commands          DONE
-glVertexAttribI commands                              ~50% done (converts int
-                                                                 values to floats)
+glVertexAttribI commands                              DONE
 Depth format cube textures                            DONE
 GLX_ARB_create_context (GLX 1.4 is required)          DONE
 
diff --git a/src/mesa/main/imports.h b/src/mesa/main/imports.h
index 551aea7..4b74f70 100644
--- a/src/mesa/main/imports.h
+++ b/src/mesa/main/imports.h
@@ -81,7 +81,7 @@ extern "C" {
  * these casts generate warnings.
  * The following union typedef is used to solve that.
  */
-typedef union { GLfloat f; GLint i; } fi_type;
+typedef union { GLfloat f; GLint i; GLuint u; } fi_type;
 
 
 
diff --git a/src/mesa/main/macros.h b/src/mesa/main/macros.h
index 5af9487..e7ef877 100644
--- a/src/mesa/main/macros.h
+++ b/src/mesa/main/macros.h
@@ -171,6 +171,20 @@ extern GLfloat _mesa_ubyte_to_float_color_tab[256];
 	ub = ((GLubyte) F_TO_I((f) * 255.0F))
 #endif
 
+static inline GLfloat INT_AS_FLT(GLint i)
+{
+   fi_type tmp;
+   tmp.i = i;
+   return tmp.f;
+}
+
+static inline GLfloat UINT_AS_FLT(GLuint u)
+{
+   fi_type tmp;
+   tmp.u = u;
+   return tmp.f;
+}
+
 /*@}*/
 
 
@@ -573,6 +587,31 @@ do {				\
 
 /*@}*/
 
+/** Copy \p sz elements into a homegeneous (4-element) vector, giving
+ * default values to the remaining components.
+ * The default values are chosen based on \p type.
+ */
+static inline void
+COPY_CLEAN_4V_TYPE_AS_FLOAT(GLfloat dst[4], int sz, const GLfloat src[4],
+                            GLenum type)
+{
+   switch (type) {
+   case GL_FLOAT:
+      ASSIGN_4V(dst, 0, 0, 0, 1);
+      break;
+   case GL_INT:
+      ASSIGN_4V(dst, INT_AS_FLT(0), INT_AS_FLT(0),
+                     INT_AS_FLT(0), INT_AS_FLT(1));
+      break;
+   case GL_UNSIGNED_INT:
+      ASSIGN_4V(dst, UINT_AS_FLT(0), UINT_AS_FLT(0),
+                     UINT_AS_FLT(0), UINT_AS_FLT(1));
+      break;
+   default:
+      ASSERT(0);
+   }
+   COPY_SZ_4V(dst, sz, src);
+}
 
 /** \name Linear interpolation functions */
 /*@{*/
diff --git a/src/mesa/vbo/vbo_attrib_tmp.h b/src/mesa/vbo/vbo_attrib_tmp.h
index d3fc77e..b4a6d73 100644
--- a/src/mesa/vbo/vbo_attrib_tmp.h
+++ b/src/mesa/vbo/vbo_attrib_tmp.h
@@ -26,38 +26,46 @@ 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 ATTR1FV( A, V ) ATTR( A, 1, GL_FLOAT, (V)[0], 0, 0, 1 )
+#define ATTR2FV( A, V ) ATTR( A, 2, GL_FLOAT, (V)[0], (V)[1], 0, 1 )
+#define ATTR3FV( A, V ) ATTR( A, 3, GL_FLOAT, (V)[0], (V)[1], (V)[2], 1 )
+#define ATTR4FV( A, V ) ATTR( A, 4, GL_FLOAT, (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 ATTR1F( A, X )          ATTR( A, 1, GL_FLOAT, X, 0, 0, 1 )
+#define ATTR2F( A, X, Y )       ATTR( A, 2, GL_FLOAT, X, Y, 0, 1 )
+#define ATTR3F( A, X, Y, Z )    ATTR( A, 3, GL_FLOAT, X, Y, Z, 1 )
+#define ATTR4F( A, X, Y, Z, W ) ATTR( A, 4, GL_FLOAT, 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 ATTRI( A, N, X, Y, Z, W) ATTR( A, N, GL_INT, \
+                                       INT_AS_FLT(X), INT_AS_FLT(Y), \
+                                       INT_AS_FLT(Z), INT_AS_FLT(W) )
 
-#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 )
+#define ATTR2IV( A, V ) ATTRI( A, 2, (V)[0], (V)[1], 0, 1 )
+#define ATTR3IV( A, V ) ATTRI( A, 3, (V)[0], (V)[1], (V)[2], 1 )
+#define ATTR4IV( A, V ) ATTRI( A, 4, (V)[0], (V)[1], (V)[2], (V)[3] )
+
+#define ATTR1I( A, X )          ATTRI( A, 1, X, 0, 0, 1 )
+#define ATTR2I( A, X, Y )       ATTRI( A, 2, X, Y, 0, 1 )
+#define ATTR3I( A, X, Y, Z )    ATTRI( A, 3, X, Y, Z, 1 )
+#define ATTR4I( A, X, Y, Z, W ) ATTRI( 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 ATTRUI( A, N, X, Y, Z, W) ATTR( A, N, GL_UNSIGNED_INT, \
+                                        UINT_AS_FLT(X), UINT_AS_FLT(Y), \
+                                        UINT_AS_FLT(Z), UINT_AS_FLT(W) )
+
+#define ATTR2UIV( A, V ) ATTRUI( A, 2, (V)[0], (V)[1], 0, 1 )
+#define ATTR3UIV( A, V ) ATTRUI( A, 3, (V)[0], (V)[1], (V)[2], 1 )
+#define ATTR4UIV( A, V ) ATTRUI( 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 ATTR1UI( A, X )          ATTRUI( A, 1, X, 0, 0, 1 )
+#define ATTR2UI( A, X, Y )       ATTRUI( A, 2, X, Y, 0, 1 )
+#define ATTR3UI( A, X, Y, Z )    ATTRUI( A, 3, X, Y, Z, 1 )
+#define ATTR4UI( A, X, Y, Z, W ) ATTRUI( A, 4, X, Y, Z, W )
 
-#define MAT_ATTR( A, N, V ) ATTR( A, N, (V)[0], (V)[1], (V)[2], (V)[3] )
+#define MAT_ATTR( A, N, V ) ATTR( A, N, GL_FLOAT, (V)[0], (V)[1], (V)[2], (V)[3] )
 
 static inline float conv_ui10_to_norm_float(unsigned ui10)
 {
@@ -69,20 +77,20 @@ static inline float conv_ui2_to_norm_float(unsigned ui2)
    return (float)(ui2) / 3.0;
 }
 
-#define ATTRUI10_1( A, UI ) ATTR( A, 1, (UI) & 0x3ff, 0, 0, 1 )
-#define ATTRUI10_2( A, UI ) ATTR( A, 2, (UI) & 0x3ff, ((UI) >> 10) & 0x3ff, 0, 1 )
-#define ATTRUI10_3( A, UI ) ATTR( A, 3, (UI) & 0x3ff, ((UI) >> 10) & 0x3ff, ((UI) >> 20) & 0x3ff, 1 )
-#define ATTRUI10_4( A, UI ) ATTR( A, 4, (UI) & 0x3ff, ((UI) >> 10) & 0x3ff, ((UI) >> 20) & 0x3ff, ((UI) >> 30) & 0x3 )
+#define ATTRUI10_1( A, UI ) ATTR( A, 1, GL_FLOAT, (UI) & 0x3ff, 0, 0, 1 )
+#define ATTRUI10_2( A, UI ) ATTR( A, 2, GL_FLOAT, (UI) & 0x3ff, ((UI) >> 10) & 0x3ff, 0, 1 )
+#define ATTRUI10_3( A, UI ) ATTR( A, 3, GL_FLOAT, (UI) & 0x3ff, ((UI) >> 10) & 0x3ff, ((UI) >> 20) & 0x3ff, 1 )
+#define ATTRUI10_4( A, UI ) ATTR( A, 4, GL_FLOAT, (UI) & 0x3ff, ((UI) >> 10) & 0x3ff, ((UI) >> 20) & 0x3ff, ((UI) >> 30) & 0x3 )
 
-#define ATTRUI10N_1( A, UI ) ATTR( A, 1, conv_ui10_to_norm_float((UI) & 0x3ff), 0, 0, 1 )
-#define ATTRUI10N_2( A, UI ) ATTR( A, 2, \
+#define ATTRUI10N_1( A, UI ) ATTR( A, 1, GL_FLOAT, conv_ui10_to_norm_float((UI) & 0x3ff), 0, 0, 1 )
+#define ATTRUI10N_2( A, UI ) ATTR( A, 2, GL_FLOAT, \
 				   conv_ui10_to_norm_float((UI) & 0x3ff), \
 				   conv_ui10_to_norm_float(((UI) >> 10) & 0x3ff), 0, 1 )
-#define ATTRUI10N_3( A, UI ) ATTR( A, 3, \
+#define ATTRUI10N_3( A, UI ) ATTR( A, 3, GL_FLOAT, \
 				   conv_ui10_to_norm_float((UI) & 0x3ff), \
 				   conv_ui10_to_norm_float(((UI) >> 10) & 0x3ff), \
 				   conv_ui10_to_norm_float(((UI) >> 20) & 0x3ff), 1 )
-#define ATTRUI10N_4( A, UI ) ATTR( A, 4, \
+#define ATTRUI10N_4( A, UI ) ATTR( A, 4, GL_FLOAT, \
 				   conv_ui10_to_norm_float((UI) & 0x3ff), \
 				   conv_ui10_to_norm_float(((UI) >> 10) & 0x3ff), \
 				   conv_ui10_to_norm_float(((UI) >> 20) & 0x3ff), \
@@ -119,30 +127,30 @@ static inline float conv_i2_to_norm_float(int i2)
    return (float)val.x;
 }
 
-#define ATTRI10_1( A, I10 ) ATTR( A, 1, conv_i10_to_i((I10) & 0x3ff), 0, 0, 1 )
-#define ATTRI10_2( A, I10 ) ATTR( A, 2, \
+#define ATTRI10_1( A, I10 ) ATTR( A, 1, GL_FLOAT, conv_i10_to_i((I10) & 0x3ff), 0, 0, 1 )
+#define ATTRI10_2( A, I10 ) ATTR( A, 2, GL_FLOAT, \
 				conv_i10_to_i((I10) & 0x3ff),		\
 				conv_i10_to_i(((I10) >> 10) & 0x3ff), 0, 1 )
-#define ATTRI10_3( A, I10 ) ATTR( A, 3, \
+#define ATTRI10_3( A, I10 ) ATTR( A, 3, GL_FLOAT, \
 				conv_i10_to_i((I10) & 0x3ff),	    \
 				conv_i10_to_i(((I10) >> 10) & 0x3ff), \
 				conv_i10_to_i(((I10) >> 20) & 0x3ff), 1 )
-#define ATTRI10_4( A, I10 ) ATTR( A, 4, \
+#define ATTRI10_4( A, I10 ) ATTR( A, 4, GL_FLOAT, \
 				conv_i10_to_i((I10) & 0x3ff),		\
 				conv_i10_to_i(((I10) >> 10) & 0x3ff), \
 				conv_i10_to_i(((I10) >> 20) & 0x3ff), \
 				conv_i2_to_i(((I10) >> 30) & 0x3))
 
 
-#define ATTRI10N_1( A, I10 ) ATTR( A, 1, conv_i10_to_norm_float((I10) & 0x3ff), 0, 0, 1 )
-#define ATTRI10N_2( A, I10 ) ATTR( A, 2, \
+#define ATTRI10N_1( A, I10 ) ATTR( A, 1, GL_FLOAT, conv_i10_to_norm_float((I10) & 0x3ff), 0, 0, 1 )
+#define ATTRI10N_2( A, I10 ) ATTR( A, 2, GL_FLOAT, \
 				conv_i10_to_norm_float((I10) & 0x3ff),		\
 				conv_i10_to_norm_float(((I10) >> 10) & 0x3ff), 0, 1 )
-#define ATTRI10N_3( A, I10 ) ATTR( A, 3, \
+#define ATTRI10N_3( A, I10 ) ATTR( A, 3, GL_FLOAT, \
 				conv_i10_to_norm_float((I10) & 0x3ff),	    \
 				conv_i10_to_norm_float(((I10) >> 10) & 0x3ff), \
 				conv_i10_to_norm_float(((I10) >> 20) & 0x3ff), 1 )
-#define ATTRI10N_4( A, I10 ) ATTR( A, 4, \
+#define ATTRI10N_4( A, I10 ) ATTR( A, 4, GL_FLOAT, \
 				conv_i10_to_norm_float((I10) & 0x3ff),		\
 				conv_i10_to_norm_float(((I10) >> 10) & 0x3ff), \
 				conv_i10_to_norm_float(((I10) >> 20) & 0x3ff), \
diff --git a/src/mesa/vbo/vbo_context.h b/src/mesa/vbo/vbo_context.h
index 1c49de0..6fcd47f 100644
--- a/src/mesa/vbo/vbo_context.h
+++ b/src/mesa/vbo/vbo_context.h
@@ -151,4 +151,47 @@ vbo_draw_method(struct vbo_context *vbo, enum draw_method method)
    }
 }
 
+/**
+ * Return if format is integer. The immediate mode commands only emit floats
+ * for non-integer types, thus everything else is integer.
+ */
+static inline GLboolean
+vbo_attrtype_to_integer_flag(GLenum format)
+{
+   switch (format) {
+   case GL_FLOAT:
+      return GL_FALSE;
+   case GL_INT:
+   case GL_UNSIGNED_INT:
+      return GL_TRUE;
+   default:
+      ASSERT(0);
+      return GL_FALSE;
+   }
+}
+
+
+/**
+ * Return default component values for the given format.
+ * The return type is an array of floats, because that's how we declare
+ * the vertex storage despite the fact we sometimes store integers in there.
+ */
+static inline const GLfloat *
+vbo_get_default_vals_as_float(GLenum format)
+{
+   static const GLfloat default_float[4] = { 0, 0, 0, 1 };
+   static const GLint default_int[4] = { 0, 0, 0, 1 };
+
+   switch (format) {
+   case GL_FLOAT:
+      return default_float;
+   case GL_INT:
+   case GL_UNSIGNED_INT:
+      return (const GLfloat*)default_int;
+   default:
+      ASSERT(0);
+      return NULL;
+   }
+}
+
 #endif
diff --git a/src/mesa/vbo/vbo_exec.h b/src/mesa/vbo/vbo_exec.h
index 4ac7d16..34a6fe7 100644
--- a/src/mesa/vbo/vbo_exec.h
+++ b/src/mesa/vbo/vbo_exec.h
@@ -102,6 +102,7 @@ struct vbo_exec_context
       struct vbo_exec_copied_vtx copied;
 
       GLubyte attrsz[VBO_ATTRIB_MAX];
+      GLenum attrtype[VBO_ATTRIB_MAX];
       GLubyte active_sz[VBO_ATTRIB_MAX];
 
       GLfloat *attrptr[VBO_ATTRIB_MAX]; 
diff --git a/src/mesa/vbo/vbo_exec_api.c b/src/mesa/vbo/vbo_exec_api.c
index 781e360..64762c7 100644
--- a/src/mesa/vbo/vbo_exec_api.c
+++ b/src/mesa/vbo/vbo_exec_api.c
@@ -157,11 +157,13 @@ static void vbo_exec_copy_to_current( struct vbo_exec_context *exec )
 	 GLfloat *current = (GLfloat *)vbo->currval[i].Ptr;
          GLfloat tmp[4];
 
-         COPY_CLEAN_4V(tmp, 
-                       exec->vtx.attrsz[i], 
-                       exec->vtx.attrptr[i]);
+         COPY_CLEAN_4V_TYPE_AS_FLOAT(tmp,
+                                     exec->vtx.attrsz[i],
+                                     exec->vtx.attrptr[i],
+                                     exec->vtx.attrtype[i]);
          
-         if (memcmp(current, tmp, sizeof(tmp)) != 0) { 
+         if (exec->vtx.attrtype[i] != vbo->currval[i].Type ||
+             memcmp(current, tmp, sizeof(tmp)) != 0) {
             memcpy(current, tmp, sizeof(tmp));
 	 
             /* Given that we explicitly state size here, there is no need
@@ -170,8 +172,10 @@ static void vbo_exec_copy_to_current( struct vbo_exec_context *exec )
              * directly.
              */
             vbo->currval[i].Size = exec->vtx.attrsz[i];
-            assert(vbo->currval[i].Type == GL_FLOAT);
             vbo->currval[i]._ElementSize = vbo->currval[i].Size * sizeof(GLfloat);
+            vbo->currval[i].Type = exec->vtx.attrtype[i];
+            vbo->currval[i].Integer =
+                  vbo_attrtype_to_integer_flag(exec->vtx.attrtype[i]);
 
             /* This triggers rather too much recalculation of Mesa state
              * that doesn't get used (eg light positions).
@@ -324,7 +328,9 @@ vbo_exec_wrap_upgrade_vertex(struct vbo_exec_context *exec,
 	       if (j == attr) {
 		  if (oldSize) {
 		     GLfloat tmp[4];
-		     COPY_CLEAN_4V(tmp, oldSize, data + old_offset);
+                     COPY_CLEAN_4V_TYPE_AS_FLOAT(tmp, oldSize,
+                                                 data + old_offset,
+                                                 exec->vtx.attrtype[j]);
 		     COPY_SZ_4V(dest + new_offset, newSize, tmp);
 		  } else {
 		     GLfloat *current = (GLfloat *)vbo->currval[j].Ptr;
@@ -365,8 +371,9 @@ vbo_exec_fixup_vertex(struct gl_context *ctx, GLuint attr, GLuint newSize)
       vbo_exec_wrap_upgrade_vertex( exec, attr, newSize );
    }
    else if (newSize < exec->vtx.active_sz[attr]) {
-      static const GLfloat id[4] = { 0, 0, 0, 1 };
       GLuint i;
+      const GLfloat *id =
+            vbo_get_default_vals_as_float(exec->vtx.attrtype[attr]);
 
       /* New size is smaller - just need to fill in some
        * zeros.  Don't need to flush or wrap.
@@ -390,7 +397,7 @@ vbo_exec_fixup_vertex(struct gl_context *ctx, GLuint attr, GLuint newSize)
  * This macro is used to implement all the glVertex, glColor, glTexCoord,
  * glVertexAttrib, etc functions.
  */
-#define ATTR( A, N, V0, V1, V2, V3 )					\
+#define ATTR( A, N, T, V0, V1, V2, V3 )					\
 do {									\
    struct vbo_exec_context *exec = &vbo_context(ctx)->exec;		\
 									\
@@ -406,6 +413,7 @@ do {									\
       if (N>1) dest[1] = V1;						\
       if (N>2) dest[2] = V2;						\
       if (N>3) dest[3] = V3;						\
+      exec->vtx.attrtype[A] = T;                                        \
    }									\
 									\
    if ((A) == 0) {							\
@@ -1192,6 +1200,8 @@ void vbo_exec_vtx_init( struct vbo_exec_context *exec )
    for (i = 0 ; i < VBO_ATTRIB_MAX ; i++) {
       ASSERT(i < Elements(exec->vtx.attrsz));
       exec->vtx.attrsz[i] = 0;
+      ASSERT(i < Elements(exec->vtx.attrtype));
+      exec->vtx.attrtype[i] = GL_FLOAT;
       ASSERT(i < Elements(exec->vtx.active_sz));
       exec->vtx.active_sz[i] = 0;
    }
@@ -1328,6 +1338,7 @@ static void reset_attrfv( struct vbo_exec_context *exec )
 
    for (i = 0 ; i < VBO_ATTRIB_MAX ; i++) {
       exec->vtx.attrsz[i] = 0;
+      exec->vtx.attrtype[i] = GL_FLOAT;
       exec->vtx.active_sz[i] = 0;
    }
 
@@ -1382,7 +1393,7 @@ 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);
+      ATTR(VBO_ATTRIB_GENERIC0 + index, 4, GL_FLOAT, x, y, z, w);
    else
       ERROR(GL_INVALID_VALUE);
 }
diff --git a/src/mesa/vbo/vbo_exec_draw.c b/src/mesa/vbo/vbo_exec_draw.c
index 77db8ec..14d22ee 100644
--- a/src/mesa/vbo/vbo_exec_draw.c
+++ b/src/mesa/vbo/vbo_exec_draw.c
@@ -215,9 +215,6 @@ vbo_exec_bind_arrays( struct gl_context *ctx )
       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];
 
@@ -243,7 +240,9 @@ vbo_exec_bind_arrays( struct gl_context *ctx )
 	 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].Type = exec->vtx.attrtype[src];
+	 arrays[attr].Integer =
+               vbo_attrtype_to_integer_flag(exec->vtx.attrtype[src]);
          arrays[attr].Format = GL_RGBA;
 	 arrays[attr].Enabled = 1;
          arrays[attr]._ElementSize = arrays[attr].Size * sizeof(GLfloat);
diff --git a/src/mesa/vbo/vbo_save.h b/src/mesa/vbo/vbo_save.h
index 0b4d563..9aadde4 100644
--- a/src/mesa/vbo/vbo_save.h
+++ b/src/mesa/vbo/vbo_save.h
@@ -63,6 +63,7 @@ struct vbo_save_copied_vtx {
  */
 struct vbo_save_vertex_list {
    GLubyte attrsz[VBO_ATTRIB_MAX];
+   GLenum attrtype[VBO_ATTRIB_MAX];
    GLuint vertex_size;
 
    /* Copy of the final vertex from node->vertex_store->bufferobj.
@@ -127,6 +128,7 @@ struct vbo_save_context {
    const struct gl_client_array *inputs[VBO_ATTRIB_MAX];
 
    GLubyte attrsz[VBO_ATTRIB_MAX];
+   GLenum attrtype[VBO_ATTRIB_MAX];
    GLubyte active_sz[VBO_ATTRIB_MAX];
    GLuint vertex_size;
 
diff --git a/src/mesa/vbo/vbo_save_api.c b/src/mesa/vbo/vbo_save_api.c
index a02a13d..1386d71 100644
--- a/src/mesa/vbo/vbo_save_api.c
+++ b/src/mesa/vbo/vbo_save_api.c
@@ -327,6 +327,7 @@ _save_compile_vertex_list(struct gl_context *ctx)
    /* Duplicate our template, increment refcounts to the storage structs:
     */
    memcpy(node->attrsz, save->attrsz, sizeof(node->attrsz));
+   memcpy(node->attrtype, save->attrtype, sizeof(node->attrtype));
    node->vertex_size = save->vertex_size;
    node->buffer_offset =
       (save->buffer - save->vertex_store->buffer) * sizeof(GLfloat);
@@ -513,7 +514,8 @@ _save_copy_to_current(struct gl_context *ctx)
    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]);
+         COPY_CLEAN_4V_TYPE_AS_FLOAT(save->current[i], save->attrsz[i],
+                                     save->attrptr[i], save->attrtype[i]);
       }
    }
 }
@@ -615,7 +617,8 @@ _save_upgrade_vertex(struct gl_context *ctx, GLuint attr, GLuint newsz)
             if (save->attrsz[j]) {
                if (j == attr) {
                   if (oldsz) {
-                     COPY_CLEAN_4V(dest, oldsz, data);
+                     COPY_CLEAN_4V_TYPE_AS_FLOAT(dest, oldsz, data,
+                                                 save->attrtype[j]);
                      data += oldsz;
                      dest += newsz;
                   }
@@ -652,8 +655,8 @@ save_fixup_vertex(struct gl_context *ctx, GLuint attr, GLuint sz)
       _save_upgrade_vertex(ctx, attr, sz);
    }
    else if (sz < save->active_sz[attr]) {
-      static GLfloat id[4] = { 0, 0, 0, 1 };
       GLuint i;
+      const GLfloat *id = vbo_get_default_vals_as_float(save->attrtype[attr]);
 
       /* New size is equal or smaller - just need to fill in some
        * zeros.
@@ -691,7 +694,7 @@ _save_reset_vertex(struct gl_context *ctx)
  * 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)				\
+#define ATTR(A, N, T, V0, V1, V2, V3)				\
 do {								\
    struct vbo_save_context *save = &vbo_context(ctx)->save;	\
 								\
@@ -704,6 +707,7 @@ do {								\
       if (N>1) dest[1] = V1;					\
       if (N>2) dest[2] = V2;					\
       if (N>3) dest[3] = V3;					\
+      save->attrtype[A] = T;                                    \
    }								\
 								\
    if ((A) == 0) {						\
diff --git a/src/mesa/vbo/vbo_save_draw.c b/src/mesa/vbo/vbo_save_draw.c
index c6425ab..8e70dbd 100644
--- a/src/mesa/vbo/vbo_save_draw.c
+++ b/src/mesa/vbo/vbo_save_draw.c
@@ -82,16 +82,20 @@ _playback_copy_to_current(struct gl_context *ctx,
 	 GLfloat *current = (GLfloat *)vbo->currval[i].Ptr;
          GLfloat tmp[4];
 
-         COPY_CLEAN_4V(tmp, 
-                       node->attrsz[i], 
-                       data);
+         COPY_CLEAN_4V_TYPE_AS_FLOAT(tmp,
+                                     node->attrsz[i],
+                                     data,
+                                     node->attrtype[i]);
          
-         if (memcmp(current, tmp, 4 * sizeof(GLfloat)) != 0) {
+         if (node->attrtype[i] != vbo->currval[i].Type ||
+             memcmp(current, tmp, 4 * sizeof(GLfloat)) != 0) {
             memcpy(current, tmp, 4 * sizeof(GLfloat));
 
             vbo->currval[i].Size = node->attrsz[i];
-            assert(vbo->currval[i].Type == GL_FLOAT);
             vbo->currval[i]._ElementSize = vbo->currval[i].Size * sizeof(GLfloat);
+            vbo->currval[i].Type = node->attrtype[i];
+            vbo->currval[i].Integer =
+                  vbo_attrtype_to_integer_flag(node->attrtype[i]);
 
             if (i >= VBO_ATTRIB_FIRST_MATERIAL &&
                 i <= VBO_ATTRIB_LAST_MATERIAL)
@@ -137,9 +141,11 @@ static void vbo_bind_vertex_list(struct gl_context *ctx,
    const GLuint *map;
    GLuint attr;
    GLubyte node_attrsz[VBO_ATTRIB_MAX];  /* copy of node->attrsz[] */
+   GLenum node_attrtype[VBO_ATTRIB_MAX];  /* copy of node->attrtype[] */
    GLbitfield64 varying_inputs = 0x0;
 
    memcpy(node_attrsz, node->attrsz, sizeof(node->attrsz));
+   memcpy(node_attrtype, node->attrtype, sizeof(node->attrtype));
 
    /* Install the default (ie Current) attributes first, then overlay
     * all active ones.
@@ -178,6 +184,7 @@ static void vbo_bind_vertex_list(struct gl_context *ctx,
           (ctx->VertexProgram._Current->Base.InputsRead & VERT_BIT_GENERIC0)) {
          save->inputs[VERT_ATTRIB_GENERIC0] = save->inputs[0];
          node_attrsz[VERT_ATTRIB_GENERIC0] = node_attrsz[0];
+         node_attrtype[VERT_ATTRIB_GENERIC0] = node_attrtype[0];
          node_attrsz[0] = 0;
       }
       break;
@@ -196,7 +203,9 @@ static void vbo_bind_vertex_list(struct gl_context *ctx,
 	 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].Type = node_attrtype[src];
+         arrays[attr].Integer =
+               vbo_attrtype_to_integer_flag(node_attrtype[src]);
          arrays[attr].Format = GL_RGBA;
 	 arrays[attr].Enabled = 1;
          arrays[attr]._ElementSize = arrays[attr].Size * sizeof(GLfloat);




More information about the mesa-commit mailing list