From acf438f5375e2426386694e541b843dc6f8fd11a Mon Sep 17 00:00:00 2001 From: =?utf8?q?Marek=20Ol=C5=A1=C3=A1k?= Date: Tue, 30 Oct 2012 14:44:22 +0100 Subject: [PATCH] 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 v2: cosmetic changes as suggested by Brian --- 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 4f44764c2c5..28f6ae603ae 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 a78d67966f8..40ba75785fc 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 7b7fd1b6d76..14a5d5fe16e 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 88484453570..6bc53bab3d2 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 ui2 / 3.0f; } -#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 c896f1196f7..1ff6ec0004e 100644 --- a/src/mesa/vbo/vbo_context.h +++ b/src/mesa/vbo/vbo_context.h @@ -147,4 +147,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 ef57a81992f..96cf4c82bf9 100644 --- a/src/mesa/vbo/vbo_exec.h +++ b/src/mesa/vbo/vbo_exec.h @@ -101,6 +101,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 2ddb715889e..75e549fc419 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) { \ @@ -1119,6 +1127,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; } @@ -1255,6 +1265,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; } @@ -1309,7 +1320,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 817af4dd52b..9529ce0698e 100644 --- a/src/mesa/vbo/vbo_exec_draw.c +++ b/src/mesa/vbo/vbo_exec_draw.c @@ -207,9 +207,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]; @@ -235,7 +232,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 f33669670c4..750117b1239 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 89f09a8d83c..75b8ca3385f 100644 --- a/src/mesa/vbo/vbo_save_api.c +++ b/src/mesa/vbo/vbo_save_api.c @@ -324,6 +324,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); @@ -510,7 +511,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]); } } } @@ -612,7 +614,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; } @@ -649,8 +652,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. @@ -688,7 +691,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; \ \ @@ -701,6 +704,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 09b8b8ab2b8..efb386e5c93 100644 --- a/src/mesa/vbo/vbo_save_draw.c +++ b/src/mesa/vbo/vbo_save_draw.c @@ -79,16 +79,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) @@ -134,9 +138,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. @@ -170,6 +176,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; @@ -188,7 +195,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); -- 2.30.2